-30
.github/workflows/build.yml
-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
+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
+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
+3
-1
.gitignore
+3
astro.config.mjs
+3
astro.config.mjs
+35
-1
bun.lock
+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
+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
+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
+2
src/middleware.ts
+37
tests/screenshots.spec.ts
+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
+
}