diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml index 2fde9d2..77e1bdd 100644 --- a/.github/workflows/site.yml +++ b/.github/workflows/site.yml @@ -25,9 +25,10 @@ jobs: cache: npm - run: npm ci - run: npm run check - - uses: actions/upload-pages-artifact@v5 + - if: github.event_name == 'push' + uses: actions/upload-pages-artifact@v5 with: - path: _site + path: site # Runs only if every check passed, so a failure leaves the last good site live. deploy: diff --git a/.gitignore b/.gitignore index fb97e10..4bcf4ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .DS_Store .claude/ node_modules/ -_site/ test-results/ diff --git a/.nojekyll b/.nojekyll deleted file mode 100644 index e69de29..0000000 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 79cfef5..5fba268 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,4 +12,4 @@ This website is under the BSD 3-Clause license, so any code added to it has to b | Non-commercial or no-derivatives terms | Don't adapt it. | | Unknown, or no license | Don't adapt it. | -Fonts and other assets are the exception. They keep their own licenses, as long as those allow redistribution, including commercial use. Put the license file next to the asset and mention it in the README, as `fonts/OFL.txt` does for JetBrains Mono. An asset pasted into a page has no folder of its own, so its license goes in `licenses/`, as `licenses/octicons.txt` does for the GitHub mark. +Fonts and other assets are the exception. They keep their own licenses, as long as those allow redistribution, including commercial use. Put the license file next to the asset and mention it in the README, as `site/fonts/OFL.txt` does for JetBrains Mono. An asset pasted into a page has no folder of its own, so its license goes in `site/licenses/`, as `site/licenses/octicons.txt` does for the GitHub mark. diff --git a/README.md b/README.md index aaff03e..4f33953 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,14 @@ Ventris Tools is an open-source project for understanding EEG. Its first tool is This is plain HTML and CSS, with no build step and no dependencies. ```bash -python3 -m http.server 4174 +python3 -m http.server 4174 --directory site ``` Then open . The Ventris card's link gives a 404 here, because `/ventris/` is a separate site. ## Checks -The site has no dependencies, but its checks do. They need Node 22 and Google Chrome. +The site has no dependencies, but its checks do. They need Node 22.22 or 24.8 and up, and Google Chrome. ```bash npm ci @@ -29,15 +29,15 @@ This validates the HTML, then opens the pages in Chrome. It looks for console er ## Deployment -Every push to `main` runs the checks on GitHub Actions. If they pass, GitHub Pages publishes the `_site` folder they tested. If they fail, the last good version stays live. +Every push to `main` runs the checks on GitHub Actions. If they pass, GitHub Pages publishes the `site` folder they tested. If they fail, the last good version stays live. -`_site` holds only the files listed in `scripts/collect-site.sh`, so add any new file the site needs there. The checks fail if a page refers to a file that isn't listed. +Everything in `site/` is published, so keep anything that shouldn't be public out of it. The app at `/ventris/` is the Pages site of the [ventris](https://github.com/ventris-tools/ventris) repository, so the card's link depends on that repository's name. ## Images -`og.png` and `apple-touch-icon.png` are rendered from the site's own copy, colors and fonts. Run this after you change the headline, the `og:description` or the palette. It needs Google Chrome. +`site/og.png` and `site/apple-touch-icon.png` are rendered from the site's own copy, colors and fonts. Run this after you change the headline, the `og:description` or the palette. It needs Google Chrome. ```bash python3 scripts/make-images.py @@ -47,10 +47,10 @@ python3 scripts/make-images.py ## Fonts -The files in `fonts/` are JetBrains Mono v2.304, cut down to Latin text without the code ligatures. A character outside this set falls back to a system font, so add it and run this on the release's `fonts/webfonts` files. It needs the `fonttools` and `brotli` Python packages. +The files in `site/fonts/` are JetBrains Mono v2.304, cut down to the characters English text needs, without hinting or OpenType features. A character outside this set falls back to a system font, so add it here and to `outsideFonts` in `test/site.spec.js`, then run this on the release's `fonts/webfonts` files. It needs the `fonttools` and `brotli` Python packages. ```bash -pyftsubset JetBrainsMono-Regular.woff2 --unicodes='U+0020-007E,U+00A0-00FF,U+2013,U+2014,U+2018,U+2019,U+201C,U+201D,U+2026,U+2190-2193' --layout-features='kern,mark,mkmk,ccmp,locl' --name-IDs='*' --flavor=woff2 --output-file=fonts/JetBrainsMono-Regular.woff2 +pyftsubset JetBrainsMono-Regular.woff2 --unicodes='U+0020-007E,U+00A0,U+00B7,U+2013,U+2014,U+2018,U+2019,U+201C,U+201D,U+2026,U+2192' --layout-features='' --no-hinting --name-IDs='*' --flavor=woff2 --output-file=site/fonts/JetBrainsMono-Regular.woff2 ``` Do the same for `JetBrainsMono-Medium.woff2`. @@ -63,6 +63,6 @@ Read [CONTRIBUTING.md](CONTRIBUTING.md) before you reuse code from another proje BSD 3-Clause. See [LICENSE](LICENSE). -The site uses [JetBrains Mono](https://github.com/JetBrains/JetBrainsMono), hosted here so that visitors make no third-party requests. The font is under the SIL Open Font License. See [fonts/OFL.txt](fonts/OFL.txt). +The site uses [JetBrains Mono](https://github.com/JetBrains/JetBrainsMono), hosted here so that visitors make no third-party requests. The font is under the SIL Open Font License. See [site/fonts/OFL.txt](site/fonts/OFL.txt). -The GitHub mark in the header is from [Octicons](https://github.com/primer/octicons), under the MIT license. See [licenses/octicons.txt](licenses/octicons.txt). +The GitHub mark in the header is from [Octicons](https://github.com/primer/octicons), under the MIT license. See [site/licenses/octicons.txt](site/licenses/octicons.txt). diff --git a/favicon.svg b/favicon.svg deleted file mode 100644 index 0421cac..0000000 --- a/favicon.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/fonts/JetBrainsMono-Medium.woff2 b/fonts/JetBrainsMono-Medium.woff2 deleted file mode 100644 index f62e3d9..0000000 Binary files a/fonts/JetBrainsMono-Medium.woff2 and /dev/null differ diff --git a/fonts/JetBrainsMono-Regular.woff2 b/fonts/JetBrainsMono-Regular.woff2 deleted file mode 100644 index 7780f17..0000000 Binary files a/fonts/JetBrainsMono-Regular.woff2 and /dev/null differ diff --git a/package-lock.json b/package-lock.json index 1fec5f1..fe015cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,10 @@ "devDependencies": { "@axe-core/playwright": "^4.14.0", "@playwright/test": "^1.64.1", - "fontkit": "^2.0.4", "html-validate": "^11.18.0" }, "engines": { - "node": ">=22.13" + "node": "^22.22.0 || >=24.8.0" } }, "node_modules/@axe-core/playwright": { @@ -71,13 +70,6 @@ "ajv": "^8.0.0" } }, - "node_modules/@swc/helpers": { - "version": "0.5.24", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.24.tgz", - "integrity": "sha512-6tcXo4kA8HgGO7AVmawB57RYi/piBPYVHVcO6dXjX+SZw8GoHmi262sp4v2Ha2kNP9Cx84qei27yT+fjS1lxgg==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/ajv": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", @@ -105,54 +97,6 @@ "node": ">=4" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/brotli": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", - "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.1.2" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/dfa": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", - "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", - "dev": true, - "license": "MIT" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -177,24 +121,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/fontkit": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", - "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@swc/helpers": "^0.5.12", - "brotli": "^1.3.2", - "clone": "^2.1.2", - "dfa": "^1.2.0", - "fast-deep-equal": "^3.1.3", - "restructure": "^3.0.0", - "tiny-inflate": "^1.0.3", - "unicode-properties": "^1.4.0", - "unicode-trie": "^2.0.0" - } - }, "node_modules/html-validate": { "version": "11.18.0", "resolved": "https://registry.npmjs.org/html-validate/-/html-validate-11.18.0.tgz", @@ -263,13 +189,6 @@ "node": ">=6" } }, - "node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", - "dev": true, - "license": "MIT" - }, "node_modules/playwright": { "version": "1.64.1", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.1.tgz", @@ -333,13 +252,6 @@ "node": ">=0.10.0" } }, - "node_modules/restructure": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", - "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==", - "dev": true, - "license": "MIT" - }, "node_modules/semver": { "version": "7.8.6", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", @@ -359,35 +271,6 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true, "license": "MIT" - }, - "node_modules/tiny-inflate": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", - "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/unicode-properties": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", - "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.0", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/unicode-trie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", - "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "pako": "^0.2.5", - "tiny-inflate": "^1.0.0" - } } } } diff --git a/package.json b/package.json index a4efc14..8cd2a5c 100644 --- a/package.json +++ b/package.json @@ -4,20 +4,18 @@ "private": true, "type": "module", "scripts": { - "collect": "bash scripts/collect-site.sh", - "lint": "html-validate index.html 404.html", + "lint": "html-validate site/*.html", "test": "playwright test", - "check": "npm run collect && npm run lint && npm run check:images && npm test", + "check": "npm run lint && npm run check:images && npm test", "check:images": "python3 scripts/make-images.py --check", "check:links": "node scripts/check-links.js" }, "engines": { - "node": ">=22.13" + "node": "^22.22.0 || >=24.8.0" }, "devDependencies": { "@axe-core/playwright": "^4.14.0", "@playwright/test": "^1.64.1", - "fontkit": "^2.0.4", "html-validate": "^11.18.0" } } diff --git a/playwright.config.js b/playwright.config.js index 6f1a4ac..205e447 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -14,7 +14,7 @@ export default defineConfig({ channel: "chrome", }, webServer: { - command: `python3 -m http.server ${port} --bind 127.0.0.1 --directory _site`, + command: `python3 -m http.server ${port} --bind 127.0.0.1 --directory site`, url: `http://127.0.0.1:${port}`, stderr: "ignore", }, diff --git a/scripts/collect-site.sh b/scripts/collect-site.sh deleted file mode 100644 index 189b309..0000000 --- a/scripts/collect-site.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# Copy the files GitHub Pages publishes into _site. The checks run against _site and the -# same folder is what gets deployed, so a new file the site needs has to be added here -# or the checks fail. -set -euo pipefail - -cd "$(dirname "$0")/.." -rm -rf _site -mkdir _site -cp -R index.html 404.html styles.css favicon.svg apple-touch-icon.png og.png LICENSE fonts licenses _site/ diff --git a/scripts/images.sha256 b/scripts/images.sha256 index a1b7853..84f039a 100644 --- a/scripts/images.sha256 +++ b/scripts/images.sha256 @@ -1 +1 @@ -45f170b515ec00b826632b4a200db2c4106c8ff3533e610f0784246049ea02e3 +23906fa57472a37b9096da51068d2937b3fe0a64a3f80b14271a0cf20a24fd62 diff --git a/scripts/make-images.py b/scripts/make-images.py index d571b0a..483ab7a 100644 --- a/scripts/make-images.py +++ b/scripts/make-images.py @@ -20,12 +20,14 @@ import tempfile from pathlib import Path -ROOT = Path(__file__).resolve().parent.parent +SCRIPTS = Path(__file__).resolve().parent +SITE = SCRIPTS.parent / "site" CHROME = os.environ.get("CHROME", "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome") -page = (ROOT / "index.html").read_text(encoding="utf-8") -css = (ROOT / "styles.css").read_text(encoding="utf-8") -logo = (ROOT / "favicon.svg").read_text(encoding="utf-8") +page = (SITE / "index.html").read_text(encoding="utf-8") +css = (SITE / "styles.css").read_text(encoding="utf-8") +# The images have one theme, so the logo's dark colors stay out of them. +logo = re.sub(r"", "", (SITE / "favicon.svg").read_text(encoding="utf-8")) def find(pattern, text): @@ -41,7 +43,7 @@ def color(name): def font(weight): - data = (ROOT / "fonts" / f"JetBrainsMono-{weight}.woff2").read_bytes() + data = (SITE / "fonts" / f"JetBrainsMono-{weight}.woff2").read_bytes() return "data:font/woff2;base64," + base64.b64encode(data).decode() @@ -105,13 +107,13 @@ def render(markup, width, height, output): # These two pages hold everything the images are made from, so this changes when an image would. fingerprint = hashlib.sha256((OG_PAGE + ICON_PAGE).encode()).hexdigest() -stamp = ROOT / "scripts" / "images.sha256" +stamp = SCRIPTS / "images.sha256" if "--check" in sys.argv: if stamp.read_text(encoding="utf-8").strip() != fingerprint: raise SystemExit("og.png or apple-touch-icon.png is out of date. Run: python3 scripts/make-images.py") sys.exit() -render(OG_PAGE, 1200, 630, ROOT / "og.png") -render(ICON_PAGE, 180, 180, ROOT / "apple-touch-icon.png") +render(OG_PAGE, 1200, 630, SITE / "og.png") +render(ICON_PAGE, 180, 180, SITE / "apple-touch-icon.png") stamp.write_text(fingerprint + "\n", encoding="utf-8") diff --git a/404.html b/site/404.html similarity index 80% rename from 404.html rename to site/404.html index c961d3a..eb0f865 100644 --- a/404.html +++ b/site/404.html @@ -13,10 +13,7 @@
- + Ventris Tools
diff --git a/apple-touch-icon.png b/site/apple-touch-icon.png similarity index 100% rename from apple-touch-icon.png rename to site/apple-touch-icon.png diff --git a/site/favicon.svg b/site/favicon.svg new file mode 100644 index 0000000..a60ce8b --- /dev/null +++ b/site/favicon.svg @@ -0,0 +1 @@ + diff --git a/site/fonts/JetBrainsMono-Medium.woff2 b/site/fonts/JetBrainsMono-Medium.woff2 new file mode 100644 index 0000000..a1d1537 Binary files /dev/null and b/site/fonts/JetBrainsMono-Medium.woff2 differ diff --git a/site/fonts/JetBrainsMono-Regular.woff2 b/site/fonts/JetBrainsMono-Regular.woff2 new file mode 100644 index 0000000..7676069 Binary files /dev/null and b/site/fonts/JetBrainsMono-Regular.woff2 differ diff --git a/fonts/OFL.txt b/site/fonts/OFL.txt similarity index 100% rename from fonts/OFL.txt rename to site/fonts/OFL.txt diff --git a/index.html b/site/index.html similarity index 52% rename from index.html rename to site/index.html index abff6c6..398b10a 100644 --- a/index.html +++ b/site/index.html @@ -25,10 +25,7 @@
- + Ventris Tools @@ -46,7 +43,7 @@

EEG decoding in your browser

diff --git a/licenses/octicons.txt b/site/licenses/octicons.txt similarity index 100% rename from licenses/octicons.txt rename to site/licenses/octicons.txt diff --git a/og.png b/site/og.png similarity index 66% rename from og.png rename to site/og.png index c1d808a..668bb91 100644 Binary files a/og.png and b/site/og.png differ diff --git a/styles.css b/site/styles.css similarity index 86% rename from styles.css rename to site/styles.css index 75d3e09..5913d56 100644 --- a/styles.css +++ b/site/styles.css @@ -2,7 +2,6 @@ font-family: "JetBrains Mono"; src: url("fonts/JetBrainsMono-Regular.woff2") format("woff2"); font-weight: 400; - font-style: normal; font-display: swap; } @@ -10,33 +9,29 @@ font-family: "JetBrains Mono"; src: url("fonts/JetBrainsMono-Medium.woff2") format("woff2"); font-weight: 500; - font-style: normal; font-display: swap; } :root { - color-scheme: light; + color-scheme: light dark; --paper: #f7f3ea; --surface: #fffdf8; --ink: #211c17; --ink-2: #5b5248; --line: #cfc4af; --accent: #008a7a; - --on-accent: #ffffff; --v: 1px; /* vertical spacing unit, shrunk on short desktop windows below */ --heading-gap: calc(6px + 8 * var(--v)); /* shrinks less than section gaps, so headings stay with their section */ } @media (prefers-color-scheme: dark) { :root { - color-scheme: dark; --paper: #171411; --surface: #1f1b17; --ink: #f2ece1; --ink-2: #c4b9a8; --line: #4d4439; --accent: #1aa394; - --on-accent: #0e1a18; } } @@ -58,12 +53,14 @@ h1, h2, h3 { font-weight: 500; } a { color: inherit; text-underline-offset: 3px; } +a:hover { color: var(--ink); } + :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; } .masthead, main, .colophon { max-width: 880px; margin-inline: auto; - padding-inline: 24px; + padding-inline: 16px; } .masthead { @@ -83,16 +80,6 @@ a { color: inherit; text-underline-offset: 3px; } text-decoration: none; } -.brand-tablet { fill: var(--accent); } - -.brand-trace { - fill: none; - stroke: var(--on-accent); - stroke-width: 2.2; - stroke-linecap: round; - stroke-linejoin: round; -} - .github-link { display: inline-flex; align-items: center; @@ -103,11 +90,9 @@ a { color: inherit; text-underline-offset: 3px; } color: var(--ink-2); } -.github-link:hover { color: var(--ink); } - .github-link svg { fill: currentColor; } -.intro { padding-block: calc(72 * var(--v)) calc(36 * var(--v)); } +.intro { padding-block: 40px 28px; } h1 { font-size: clamp(1.85rem, 6vw, 3.25rem); @@ -158,7 +143,7 @@ h2 { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 8px 16px; - padding: 20px 24px; + padding: 18px; border: 1px solid var(--line); border-radius: 14px; background: var(--surface); @@ -236,10 +221,11 @@ h3 { font-size: 1.35rem; line-height: 1.2; letter-spacing: -0.02em; } .colophon p { text-wrap: balance; } -.principles a:hover, .colophon a:hover { color: var(--ink); } - -/* Wide enough for columns, well before the desktop rule below. */ +/* Wide enough for columns and more room, well before the desktop rule below. */ @media (min-width: 700px) { + .masthead, main, .colophon { padding-inline: 24px; } + .intro { padding-block: calc(72 * var(--v)) calc(36 * var(--v)); } + .tool { padding: 20px 24px; } .principles { grid-template-columns: repeat(3, minmax(0, 1fr)); } .colophon { grid-template-columns: 2fr 1fr; } } @@ -257,9 +243,3 @@ h3 { font-size: 1.35rem; line-height: 1.2; letter-spacing: -0.02em; } } .lede { max-width: none; text-wrap: balance; } } - -@media (max-width: 640px) { - .masthead, main, .colophon { padding-inline: 16px; } - .intro { padding-block: 40px 28px; } - .tool { padding: 18px; } -} diff --git a/test/site.spec.js b/test/site.spec.js index d6c7b1c..1d23f69 100644 --- a/test/site.spec.js +++ b/test/site.spec.js @@ -1,16 +1,16 @@ import AxeBuilder from "@axe-core/playwright"; import { expect, test } from "@playwright/test"; -import { openSync } from "fontkit"; const pages = ["/", "/404.html"]; const liveOrigin = "https://ventris-tools.github.io"; -// Ventris is a separate site, published from its own repository, so it is not in _site. +// Ventris is a separate site, published from its own repository, so it is not in site/. const otherSite = "/ventris/"; const pageWeightBudget = 50_000; -const fonts = ["Regular", "Medium"].map((weight) => openSync(`_site/fonts/JetBrainsMono-${weight}.woff2`)); +// Anything other than the characters in site/fonts. The README has the command that cuts them. +const outsideFonts = /[^\u0020-\u007E\u00A0\u00B7\u2013\u2014\u2018\u2019\u201C\u201D\u2026\u2192\n\r\t]/g; // The fonts change the layout, so nothing is measured until they have loaded. async function open(page, path) { @@ -60,12 +60,8 @@ for (const path of pages) { await open(page, path); const text = await page.evaluate(() => document.body.textContent); - const characters = [...new Set(text.replace(/[\n\r\t]/g, ""))]; - const missing = characters.filter( - (character) => !fonts.every((font) => font.hasGlyphForCodePoint(character.codePointAt(0))), - ); - expect(missing).toEqual([]); + expect(text.match(outsideFonts) ?? []).toEqual([]); }); for (const width of [320, 375, 768]) {