this repo has no description

👷 Setup visual diffing

-30
.github/workflows/build.yml
··· 1 - name: Verify that it builds 2 - 3 - on: 4 - push: 5 - branches: 6 - - main 7 - pull_request: 8 - branches: 9 - - main 10 - 11 - jobs: 12 - build: 13 - runs-on: ubuntu-latest 14 - strategy: 15 - fail-fast: false 16 - matrix: 17 - lang: [en, fr] 18 - steps: 19 - - uses: actions/checkout@v5 20 - - uses: oven-sh/setup-bun@v2 21 - with: 22 - bun-version-file: ".bun-version" 23 - 24 - - name: Install dependencies 25 - run: bun install 26 - 27 - - name: Build the project 28 - run: bun run build 29 - env: 30 - LANG: ${{ matrix.lang }}
+46
.github/workflows/clean-gh-pages.yml
··· 1 + name: Clean gh-pages branch 2 + 3 + on: 4 + schedule: 5 + - cron: "0 0 * * *" # Every day at midnight 6 + workflow_dispatch: 7 + 8 + jobs: 9 + clean-gh-pages: 10 + runs-on: ubuntu-latest 11 + permissions: 12 + contents: write 13 + steps: 14 + - name: Checkout gh-pages branch 15 + uses: actions/checkout@v5 16 + with: 17 + ref: gh-pages 18 + - name: Install gh CLI 19 + run: | 20 + sudo apt-get install gh -y 21 + - name: Remove dirs for PRs that are no longer open 22 + env: 23 + REPO_PR_URL: ${{ github.event.repository.html_url }}/pull 24 + GH_TOKEN: ${{ github.token }} 25 + run: | 26 + open_prs=$(gh pr list --state open --json number --jq '.[].number') 27 + echo Open PRs: $open_prs 28 + for pr in pr-*; do 29 + number=$(basename "$pr" | sed 's/^pr-//') 30 + if ! echo "$open_prs" | grep -q "$number"; then 31 + echo "Removing $pr, $number does not match any open PR: $REPO_PR_URL/$number" 32 + rm -rf "$pr" 33 + else 34 + echo "Keeping $pr as $number is still open: $REPO_PR_URL/$number" 35 + fi 36 + done 37 + 38 + - name: Collapse branch history and push 39 + run: | 40 + git config --local user.name "GitHub Actions" 41 + git config --local user.email "github-actions@github.com" 42 + git checkout --orphan flattened 43 + git add -A 44 + git commit -m "Clean up gh-pages branch" 45 + git branch -M gh-pages 46 + git push -f origin gh-pages
+104
.github/workflows/test.yml
··· 1 + name: Visual diffing 2 + 3 + on: 4 + push: 5 + branches: [main] 6 + pull_request: 7 + branches: [main] 8 + 9 + concurrency: 10 + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 11 + cancel-in-progress: true 12 + 13 + permissions: 14 + contents: write 15 + 16 + jobs: 17 + update: 18 + if: github.event_name == 'push' 19 + name: Update screenshots 20 + runs-on: ubuntu-latest 21 + container: 22 + image: ghcr.io/gwennlbh/playwright-bun:v1.55.1 23 + steps: 24 + - uses: actions/checkout@v5 25 + 26 + # Probably due to using a container 27 + - name: Fix dubious ownership of .git dir 28 + run: git config --global --add safe.directory $(pwd) 29 + 30 + - name: Remove git pre-push hook 31 + run: echo "" > .husky/pre-push 32 + 33 + - name: Setup Bun 34 + uses: oven-sh/setup-bun@v2 35 + with: 36 + bun-version-file: .bun-version 37 + 38 + - name: Install dependencies 39 + run: bun install --frozen-lockfile 40 + 41 + - name: Build site 42 + run: bun run build 43 + env: 44 + LANG: fr 45 + LOCALE: fr-FR 46 + BUILD_COMMIT: testing 47 + 48 + - name: Update screenshots 49 + run: bunx playwright test --update-snapshots --update-source-method overwrite 50 + 51 + - name: Commit updated screenshots 52 + uses: stefanzweifel/git-auto-commit-action@v4 53 + with: 54 + commit_message: ✅ Update screenshots 55 + file_pattern: screenshots/ 56 + 57 + test: 58 + if: github.event_name == 'pull_request' 59 + name: Test 60 + runs-on: ubuntu-latest 61 + container: 62 + image: ghcr.io/gwennlbh/playwright-bun:v1.55.1 63 + environment: 64 + name: Visual diffing for PR #${{ github.event.pull_request.number }} 65 + url: ${{ steps.deploy-to-gh-pages.outputs.page_url }} 66 + steps: 67 + - uses: actions/checkout@v5 68 + 69 + # Probably due to using a container 70 + - name: Fix dubious ownership of .git dir 71 + run: git config --global --add safe.directory $(pwd) 72 + 73 + - name: Setup Bun 74 + uses: oven-sh/setup-bun@v2 75 + with: 76 + bun-version-file: .bun-version 77 + 78 + - name: Install dependencies 79 + run: bun install --frozen-lockfile 80 + 81 + - name: Remove git pre-push hook 82 + run: echo "" > .husky/pre-push 83 + 84 + - name: Build site 85 + run: bun run build 86 + env: 87 + LANG: fr 88 + LOCALE: fr-FR 89 + BUILD_COMMIT: testing 90 + 91 + - name: Verify screenshots 92 + run: bunx playwright test 93 + 94 + - if: ${{ !cancelled() }} 95 + name: Upload report to github pages 96 + uses: JamesIves/github-pages-deploy-action@v4 97 + with: 98 + folder: playwright-report 99 + target-folder: pr-${{ github.event.pull_request.number }} 100 + force: true 101 + single-commit: true 102 + clean-exclude: | 103 + .nojekyll 104 + pr-*
+3 -1
.gitignore
··· 31 31 .secrets 32 32 33 33 # wakatime response cache 34 - .wakatime-cache.json 34 + .wakatime-cache.json 35 + 36 + test-results/
+3
astro.config.mjs
··· 7 7 8 8 // https://astro.build/config 9 9 export default defineConfig({ 10 + devToolbar: { 11 + enabled: !process.env.PLAYWRIGHT, 12 + }, 10 13 integrations: [ 11 14 mdx(), 12 15 sitemap({
+35 -1
bun.lock
··· 17 17 "yaml": "^2.7.0", 18 18 }, 19 19 "devDependencies": { 20 + "@playwright/test": "^1.55.1", 20 21 "@types/bun": "^1.2.23", 21 22 "@types/jsdom": "^27.0.0", 22 23 "@types/picomatch": "^4.0.0", ··· 28 29 "prettier-plugin-sort-json": "^4.1.1", 29 30 "rehype-katex": "^7.0.1", 30 31 "remark-math": "^6.0.0", 32 + "sirv-cli": "^3.0.1", 31 33 }, 32 34 }, 33 35 }, ··· 180 182 181 183 "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="], 182 184 185 + "@playwright/test": ["@playwright/test@1.55.1", "", { "dependencies": { "playwright": "1.55.1" }, "bin": { "playwright": "cli.js" } }, "sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig=="], 186 + 187 + "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], 188 + 183 189 "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], 184 190 185 191 "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.2", "", { "os": "android", "cpu": "arm" }, "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A=="], ··· 374 380 375 381 "common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="], 376 382 383 + "console-clear": ["console-clear@1.1.1", "", {}, "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ=="], 384 + 377 385 "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], 378 386 379 387 "cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="], ··· 484 492 485 493 "fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], 486 494 487 - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], 495 + "fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], 488 496 489 497 "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], 490 498 491 499 "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="], 492 500 493 501 "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], 502 + 503 + "get-port": ["get-port@5.1.1", "", {}, "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ=="], 494 504 495 505 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], 496 506 ··· 603 613 "klaw-sync": ["klaw-sync@6.0.0", "", { "dependencies": { "graceful-fs": "^4.1.11" } }, "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ=="], 604 614 605 615 "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], 616 + 617 + "local-access": ["local-access@1.1.0", "", {}, "sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw=="], 606 618 607 619 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], 608 620 ··· 732 744 733 745 "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], 734 746 747 + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], 748 + 735 749 "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], 736 750 737 751 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], ··· 786 800 787 801 "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], 788 802 803 + "playwright": ["playwright@1.55.1", "", { "dependencies": { "playwright-core": "1.55.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A=="], 804 + 805 + "playwright-core": ["playwright-core@1.55.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w=="], 806 + 789 807 "pofile": ["pofile@1.1.4", "", {}, "sha512-r6Q21sKsY1AjTVVjOuU02VYKVNQGJNQHjTIvs4dEbeuuYfxgYk/DGD2mqqq4RDaVkwdSq0VEtmQUOPe/wH8X3g=="], 790 808 791 809 "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], ··· 866 884 867 885 "s.color": ["s.color@0.0.15", "", {}, "sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA=="], 868 886 887 + "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], 888 + 869 889 "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], 870 890 871 891 "sass-formatter": ["sass-formatter@0.7.9", "", { "dependencies": { "suf-log": "^2.5.3" } }, "sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw=="], ··· 873 893 "sax": ["sax@1.4.1", "", {}, "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="], 874 894 875 895 "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="], 896 + 897 + "semiver": ["semiver@1.1.0", "", {}, "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg=="], 876 898 877 899 "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], 878 900 ··· 888 910 889 911 "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], 890 912 913 + "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="], 914 + 915 + "sirv-cli": ["sirv-cli@3.0.1", "", { "dependencies": { "console-clear": "^1.1.0", "get-port": "^5.1.1", "kleur": "^4.1.4", "local-access": "^1.0.1", "sade": "^1.6.0", "semiver": "^1.0.0", "sirv": "^3.0.0", "tinydate": "^1.0.0" }, "bin": { "sirv": "bin.js" } }, "sha512-ICXaF2u6IQhLZ0EXF6nqUF4YODfSQSt+mGykt4qqO5rY+oIiwdg7B8w2PVDBJlQulaS2a3J8666CUoDoAuCGvg=="], 916 + 891 917 "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], 892 918 893 919 "sitemap": ["sitemap@8.0.0", "", { "dependencies": { "@types/node": "^17.0.5", "@types/sax": "^1.2.1", "arg": "^5.0.0", "sax": "^1.2.4" }, "bin": { "sitemap": "dist/cli.js" } }, "sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A=="], ··· 928 954 929 955 "tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="], 930 956 957 + "tinydate": ["tinydate@1.3.0", "", {}, "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w=="], 958 + 931 959 "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], 932 960 933 961 "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], ··· 939 967 "tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="], 940 968 941 969 "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], 970 + 971 + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], 942 972 943 973 "tough-cookie": ["tough-cookie@6.0.0", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w=="], 944 974 ··· 1084 1114 1085 1115 "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], 1086 1116 1117 + "rollup/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], 1118 + 1087 1119 "sitemap/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="], 1120 + 1121 + "vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], 1088 1122 1089 1123 "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], 1090 1124
+4 -2
package.json
··· 5 5 "scripts": { 6 6 "dev": "astro dev --port 5173", 7 7 "build": "astro build", 8 - "preview": "astro preview", 8 + "preview": "sirv dist/ --port 4173", 9 9 "astro": "astro", 10 10 "format": "prettier --write .", 11 11 "database": "ortfodb --config ./ortfodb.yaml --scattered build works.json", ··· 32 32 "yaml": "^2.7.0" 33 33 }, 34 34 "devDependencies": { 35 + "@playwright/test": "^1.55.1", 35 36 "@types/bun": "^1.2.23", 36 37 "@types/jsdom": "^27.0.0", 37 38 "@types/picomatch": "^4.0.0", ··· 42 43 "prettier-plugin-astro": "^0.14.1", 43 44 "prettier-plugin-sort-json": "^4.1.1", 44 45 "rehype-katex": "^7.0.1", 45 - "remark-math": "^6.0.0" 46 + "remark-math": "^6.0.0", 47 + "sirv-cli": "^3.0.1" 46 48 } 47 49 }
+96
playwright.config.ts
··· 1 + import { defineConfig, devices } from "@playwright/test"; 2 + import { minutesToMilliseconds } from "date-fns"; 3 + 4 + /** 5 + * @see https://playwright.dev/docs/test-configuration 6 + */ 7 + export default defineConfig({ 8 + /* Leave some time before github actions makes the job time out (1 hour), so the report can be deployed */ 9 + globalTimeout: minutesToMilliseconds(9), 10 + timeout: minutesToMilliseconds(1.2), 11 + testDir: "./tests", 12 + /* Run tests in files in parallel */ 13 + fullyParallel: true, 14 + /* Fail the build on CI if you accidentally left test.only in the source code. */ 15 + forbidOnly: !!process.env.CI, 16 + /* Retry on CI only */ 17 + retries: 0, 18 + /* Opt out of parallel tests on CI. */ 19 + workers: process.env.CI ? 1 : undefined, 20 + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ 21 + reporter: process.env.CI 22 + ? [ 23 + ["json", { outputFile: "test-results.json" }], 24 + [process.env.SHARDING ? "blob" : "html"], 25 + ["github"], 26 + ["list"], 27 + ] 28 + : [], 29 + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ 30 + use: { 31 + /* Base URL to use in actions like `await page.goto('/')`. */ 32 + baseURL: dependsOnTarget({ 33 + live: process.env.BASE_URL, 34 + dev: "http://localhost:5173", 35 + built: "http://localhost:4173", 36 + }), 37 + 38 + // See https://github.com/microsoft/playwright/issues/16357 39 + bypassCSP: dependsOnTarget({ 40 + live: true, 41 + dev: false, 42 + built: false, 43 + }), 44 + 45 + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ 46 + trace: "on-first-retry", 47 + 48 + locale: "fr-FR", 49 + 50 + // Ensure no TZ issues for assertions that depend on time 51 + timezoneId: "Etc/UTC", 52 + }, 53 + 54 + snapshotPathTemplate: "screenshots/{testName}/{projectName}{ext}", 55 + 56 + /* Configure projects for major browsers */ 57 + projects: [ 58 + { name: "desktop", use: devices["Desktop Chrome"] }, 59 + { name: "mobile", use: devices["iPhone SE (3rd gen)"] }, 60 + ], 61 + 62 + /* Run your local dev server before starting the tests */ 63 + webServer: dependsOnTarget({ 64 + live: undefined, 65 + dev: { 66 + command: "bun run dev", 67 + port: 5173, 68 + reuseExistingServer: true, 69 + }, 70 + built: { 71 + command: "bun run preview", 72 + port: 4173, 73 + reuseExistingServer: false, 74 + }, 75 + }), 76 + }); 77 + 78 + /** 79 + * 80 + * @param param0.live - Value to return if we're checking against a live URL (meaning $BASE_URL is set) 81 + * @param param0.dev - Value to return if we're checking against a dev server (meaning $CI is not set) 82 + * @param param0.built - Value to return if we're checking against a built version (meaning $CI is set) 83 + */ 84 + function dependsOnTarget<L, B, D>({ 85 + live, 86 + dev, 87 + built, 88 + }: { 89 + live: L; 90 + dev: D; 91 + built: B; 92 + }): L | B | D { 93 + if (process.env.BASE_URL) return live; 94 + if (process.env.CI) return built; 95 + return dev; 96 + }
+2
src/middleware.ts
··· 7 7 locals.locale = (process.env.LOCALE || 8 8 "en-US") as `${typeof locals.lang}-${string}`; 9 9 locals.buildCommit = 10 + // Explicit commit 11 + process.env.BUILD_COMMIT || 10 12 // Netlify 11 13 process.env.COMMIT_REF || 12 14 // Cloudflare Pages
+37
tests/screenshots.spec.ts
··· 1 + import { test, expect } from "@playwright/test"; 2 + import path from "node:path"; 3 + 4 + type ConfigEntry = `/${string}` | { [name: string]: ConfigEntry }; 5 + type Config = Record<string, ConfigEntry>; 6 + 7 + /** 8 + * Map screenshot filename (without extension) to URL. 9 + * Object values allow making directories for screenshots 10 + */ 11 + const pages: Config = { 12 + index: "/", 13 + projects: { 14 + "gwen.works": "/gwen.works", 15 + }, 16 + blog: { 17 + lsp: "/blog/making-an-lsp-server-in-go", 18 + }, 19 + }; 20 + 21 + function runScreenshotTest(screenshotName: string, urlOrFolder: ConfigEntry) { 22 + if (typeof urlOrFolder === "string") { 23 + test(screenshotName, async ({ page }) => { 24 + process.env.PLAYWRIGHT = "1"; 25 + await page.goto(urlOrFolder); 26 + await expect(page).toHaveScreenshot(); 27 + }); 28 + } else { 29 + for (const [name, entry] of Object.entries(urlOrFolder)) { 30 + runScreenshotTest(path.join(screenshotName, name), entry); 31 + } 32 + } 33 + } 34 + 35 + for (const [name, entry] of Object.entries(pages)) { 36 + runScreenshotTest(name, entry); 37 + }