diff --git a/package.json b/package.json index e103df0..f0bc4ec 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "preview": "astro preview", "astro": "astro", "build:icon-data": "node scripts/build-icon-data.mjs", - "check": "node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-catalog.mjs && node --disable-warning=ExperimentalWarning scripts/check-business-hours.mjs && node scripts/check-news-ticker.mjs && node --disable-warning=ExperimentalWarning scripts/check-flip-box.mjs && node scripts/check-social-grid.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-four.mjs && node --disable-warning=ExperimentalWarning scripts/check-video-player.mjs && node scripts/check-cookie-consent.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-icon.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-animated-background.mjs && node --disable-warning=ExperimentalWarning scripts/check-modal-and-bar.mjs && node --disable-warning=ExperimentalWarning scripts/check-reveal-cards.mjs && node --disable-warning=ExperimentalWarning scripts/check-time-and-toggles.mjs && node --disable-warning=ExperimentalWarning scripts/check-media-and-links.mjs && node --disable-warning=ExperimentalWarning scripts/check-structure.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-feedback.mjs && node --disable-warning=ExperimentalWarning scripts/check-controls.mjs && node scripts/check-small-pieces.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-categories.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-mega-menu.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-styles.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-type.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-palettes.mjs && node --disable-warning=ExperimentalWarning scripts/check-shop.mjs" + "check": "node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-catalog.mjs && node --disable-warning=ExperimentalWarning scripts/check-business-hours.mjs && node scripts/check-news-ticker.mjs && node --disable-warning=ExperimentalWarning scripts/check-flip-box.mjs && node scripts/check-social-grid.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-four.mjs && node --disable-warning=ExperimentalWarning scripts/check-video-player.mjs && node scripts/check-cookie-consent.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-icon.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-animated-background.mjs && node --disable-warning=ExperimentalWarning scripts/check-modal-and-bar.mjs && node --disable-warning=ExperimentalWarning scripts/check-reveal-cards.mjs && node --disable-warning=ExperimentalWarning scripts/check-time-and-toggles.mjs && node --disable-warning=ExperimentalWarning scripts/check-media-and-links.mjs && node --disable-warning=ExperimentalWarning scripts/check-structure.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-feedback.mjs && node --disable-warning=ExperimentalWarning scripts/check-controls.mjs && node scripts/check-small-pieces.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-categories.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-mega-menu.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-styles.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-type.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-palettes.mjs && node --disable-warning=ExperimentalWarning scripts/check-shop.mjs && node --experimental-strip-types --disable-warning=ExperimentalWarning scripts/check-image-effects.mjs" }, "dependencies": { "astro": "^7.2.1" diff --git a/public/demo/scene-city.svg b/public/demo/scene-city.svg new file mode 100644 index 0000000..2681fcd --- /dev/null +++ b/public/demo/scene-city.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/demo/scene-dunes.svg b/public/demo/scene-dunes.svg new file mode 100644 index 0000000..f043f44 --- /dev/null +++ b/public/demo/scene-dunes.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/demo/scene-forest.svg b/public/demo/scene-forest.svg new file mode 100644 index 0000000..da44ac8 --- /dev/null +++ b/public/demo/scene-forest.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/demo/scene-harbor.svg b/public/demo/scene-harbor.svg new file mode 100644 index 0000000..885b9cf --- /dev/null +++ b/public/demo/scene-harbor.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/demo/scene-lavender.svg b/public/demo/scene-lavender.svg new file mode 100644 index 0000000..9b6c185 --- /dev/null +++ b/public/demo/scene-lavender.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/demo/scene-peaks.svg b/public/demo/scene-peaks.svg new file mode 100644 index 0000000..4b584de --- /dev/null +++ b/public/demo/scene-peaks.svg @@ -0,0 +1,4 @@ + + + + diff --git a/scripts/check-categories.mjs b/scripts/check-categories.mjs index 04858ff..ceda33d 100644 --- a/scripts/check-categories.mjs +++ b/scripts/check-categories.mjs @@ -69,6 +69,7 @@ const GOLDEN = { 'card-slider': 'media', 'testimonial-carousel': 'media', icon: 'media', + 'image-effects': 'media', countdown: 'conversion', 'announcement-bar': 'conversion', diff --git a/scripts/check-image-effects.mjs b/scripts/check-image-effects.mjs new file mode 100644 index 0000000..d16ad2f --- /dev/null +++ b/scripts/check-image-effects.mjs @@ -0,0 +1,205 @@ +#!/usr/bin/env node +/** + * npm run check (after check-catalog.mjs, which builds dist/) — pins image-effects. + * + * Source (src/library/image-effects/ImageEffects.astro) + * 1. The `` block names exactly the effects the catalogue's `effect` prop + * lists, in the same order, so the docs never offer an effect the file refuses or hide one + * it has. + * 2. The stylesheet: every transition, animation and will-change sits inside + * `@media (prefers-reduced-motion: no-preference)`; so do zoom's `scale` and shine's sweep. + * No `:hover` in it stands without a keyboard twin (`:focus-visible` or `:focus-within`) in + * the same selector, except tilt (the script does it) and caption's figure hover, which + * carries `:focus-within`. + * 3. The runtime: each moving block (``, ``, ``, + * ``) reads `still.matches` (reduced motion, tracked live), and the tile + * animation uses Slider Revolution's numbers: 1000 ms, 45 ms apart, power3.out. + * + * Built pages (the demo page and the gallery index) + * 4. The stylesheet and the runtime are on the page once; every scripted root (pixelate, + * tilt, tiles, gallery-open) is followed straight away by its mount line; a CSS-only root + * is not. + * 5. Every in an element has an alt attribute. + * 6. tiles, as a visitor without JavaScript gets it: a named carousel, slides as groups named + * "n of total", the first one current, the controls `hidden` with three named buttons. + * On the index (`quiet`) it neither autoplays nor flies in on load. + * + * Mutation tests: the built-page checks run again on broken copies of the demo page; each must + * be caught, or the check itself is broken. + * + * Exits 1 with one line per failure. + */ +import { existsSync, readFileSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const root = join(dirname(fileURLToPath(import.meta.url)), '..'); +const SRC = 'src/library/image-effects/ImageEffects.astro'; +const failures = []; +const fail = (m) => failures.push(m); +const src = readFileSync(join(root, SRC), 'utf8'); +const { catalog } = await import(pathToFileURL(join(root, 'src/data/catalog.ts')).href); +const entry = catalog.find((e) => e.id === 'image-effects'); + +// ------------------------------------------------------------------ 1. effect list +const listBlock = src.match(/\/\/ ([\s\S]*?)\/\/ <\/image-effects-list>/)?.[1] ?? ''; +const quoted = (s) => [...s.matchAll(/'([a-z-]+)'/g)].map((m) => m[1]); +const fileEffects = quoted(listBlock); +const docEffects = quoted(entry?.props.find((p) => p.name === 'effect')?.type ?? ''); +if (!fileEffects.length) fail(`${SRC}: no block.`); +if (fileEffects.join() !== docEffects.join()) { + fail(`${SRC} offers [${fileEffects.join(', ')}] but the catalogue's \`effect\` prop lists [${docEffects.join(', ')}]; keep them the same, in order.`); +} + +// ------------------------------------------------------------------ 2. stylesheet +const css = (src.match(/'), 'm'), /stylesheet is on the page 2 times/], + ['a missing mount line', () => pageFailures(demoHtml.replace(MOUNT, ''), 'm'), /mount line/], + ['controls shown without JavaScript', () => pageFailures(demoHtml.replace(/(data-ie-controls)/, '$1-x').replace(/