diff --git a/README.md b/README.md index af705ce1..3f8e7746 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Documentation: [EN](https://vpdpersonal.github.io/Aspid.FastTools/docs), [RU](ht - +
Package Manager installs Aspid.FastTools from its git URLPackage Manager installs Aspid.FastTools from its git URL
  1. Open Window → Package Manager
  2. diff --git a/Website/docs/Images/readme-previews/install.webp b/Website/docs/Images/readme-previews/install.webp deleted file mode 100644 index 7d60813c..00000000 Binary files a/Website/docs/Images/readme-previews/install.webp and /dev/null differ diff --git a/Website/media/readme-previews/README.md b/Website/media/readme-previews/README.md index 1d8c33eb..0d7e7783 100644 --- a/Website/media/readme-previews/README.md +++ b/Website/media/readme-previews/README.md @@ -1,19 +1,22 @@ # README feature previews -The root README cannot run the introduction's animated feature previews (`Website/src/components/FeaturePreview`) or -the install panel's Package Manager walk-through (`Website/src/components/InstallPanel`), so +The root README cannot run the introduction's animated feature previews (`Website/src/components/FeaturePreview`), so `Website/scripts/github-readme.mjs` shows a recording of each one in its card: -`Website/docs/Images/readme-previews/.webp`, `install` for the walk-through. Only the dark theme: a `` per +`Website/docs/Images/readme-previews/.webp`. Only the dark theme: a `` per theme follows the system theme, not GitHub's, so the README shows no light variants. `record.mjs` opens the built introduction in headless Chrome on virtual time and records one loop of each preview at 2x in the green accent and the dark theme: 20 fps, the Profiler's scrolling timeline 12.5 fps. `img2webp` encodes it losslessly: lossy WebP leaves ghosts of earlier frames on these flat interfaces. The Profiler's timeline takes mixed frames (q 90) instead, which keeps it near 2 MB. Each loop length comes from the preview's `useLoop` steps (the -Profiler's ticker for ProfilerMarkers, `DURATIONS` in `InstallPanel` for the walk-through); update `PREVIEWS` when they -change. The recording drops the frame of the card or panel, since on GitHub the table cell is the frame. The -walk-through hides the package version, but its typed URL names the channel (`#upm-preview`), so re-record `install` -when a release switches channels; `scripts/set-version.sh` says so. +Profiler's ticker for ProfilerMarkers); update `PREVIEWS` when they change. The recording drops the frame of the card, +since on GitHub the table cell is the frame. + +The installation walkthrough is generated centrally in +[VPDPersonal](https://github.com/VPDPersonal/VPDPersonal/tree/main/scripts/installation), with cached PNG/WebP output +on GitHub Pages. The README generator selects the stable or preview URL from its copyable install command; +changing a release channel does not require a local recording. The documentation site's interactive +`Website/src/components/InstallPanel` remains its own component. 1. Build and serve the site: `Website/scripts/serve-all.sh`. 2. Record every preview, or only the named ones: `node Website/media/readme-previews/record.mjs http://localhost:/Aspid.FastTools/ [name …]`. diff --git a/Website/media/readme-previews/record.mjs b/Website/media/readme-previews/record.mjs index 04683bb9..c84c2789 100644 --- a/Website/media/readme-previews/record.mjs +++ b/Website/media/readme-previews/record.mjs @@ -1,5 +1,5 @@ -// Records the introduction's animated feature previews (Website/src/components/FeaturePreview) and the install panel's -// Package Manager walk-through (Website/src/components/InstallPanel) from a built site into looping WebPs for the GitHub +// Records the introduction's animated feature previews (Website/src/components/FeaturePreview) +// from a built site into looping WebPs for the GitHub // README: Website/docs/Images/readme-previews/.webp, in the dark theme only. Headless Chrome runs on // virtual time, so every frame lands on its exact timestamp however slow the capture is. // Website/scripts/serve-all.sh @@ -22,11 +22,6 @@ const OUT = fileURLToPath(new URL('../../docs/Images/readme-previews/', import.m const FPS = 20; const ENCODE = ['-lossless', '-m', '6']; const PREVIEWS = { - // InstallPanel: the sum of DURATIONS. It plays PLAYS (2) times, so a short warm-up records the first play, which runs - // into the second one's first frame. The installed package's version is hidden, so a release needs no new recording; - // the typed URL still names the channel. - 'install': {loop: 1300 + 1400 + 1800 + 1100 + 2600, warmup: 100, - box: `document.querySelector('section[class*="install_"] [class*="preview_"]')`}, 'profiler-markers': {loop: 22000, fps: 12.5, encode: ['-mixed', '-q', '90', '-m', '6']}, 'visual-element-extensions': {loop: 6 * 1100}, 'serialized-property-extensions': {loop: 5 * 1200}, @@ -115,7 +110,7 @@ async function open() { const page = (method, params) => send(method, params, sessionId); await page('Page.enable'); await page('Emulation.setDeviceMetricsOverride', {...VIEWPORT, mobile: false}); - // The entrance has played, so the banner rests. The frame of a card or the install panel, its rounded corner and the + // The entrance has played, so the banner rests. The frame of a card, its rounded corner and the // line between preview and text go: on GitHub the table cell is the frame. await page('Page.addScriptToEvaluateOnNewDocument', {source: ` localStorage.setItem('theme', 'dark'); @@ -124,9 +119,6 @@ async function open() { + '.feature-card { border: 0 !important; border-radius: 0 !important; }' + '.feature-card__preview { border-right: 0 !important; }' + '.feature-card__live [class*="inspector_"], .feature-card__live [class*="uiStage_"] { border-radius: 0 !important; }' - + 'section[class*="install_"] { border: 0 !important; border-radius: 0 !important; }' - + 'section[class*="install_"] [class*="preview_"] { border-right: 0 !important; }' - + 'section[class*="install_"] [class*="pmNew_"] span:last-child { visibility: hidden; }' + ''));`}); const loaded = once('Page.loadEventFired', sessionId); await page('Page.navigate', {url: new URL('docs', base).href}); diff --git a/Website/scripts/github-readme.mjs b/Website/scripts/github-readme.mjs index cd340b01..9a564659 100644 --- a/Website/scripts/github-readme.mjs +++ b/Website/scripts/github-readme.mjs @@ -3,8 +3,8 @@ * site-only blocks get the closest GitHub equivalent in plain HTML (src/remark/introBanner.js builds the site's): * - links to doc pages and to the samples overview open the site, which renders them in full; * - the link row's link to the site lists the site's languages: `Documentation: EN, RU`; - * - the install instruction becomes a card like the site's install panel (src/components/InstallPanel): the recording - * of its Package Manager walk-through beside its numbered steps, the URL to copy below; + * - the install instruction becomes a card like the site's install panel (src/components/InstallPanel): the shared + * Package Manager walk-through beside its numbered steps, the URL to copy below; * - the note under the install URL links the site's install panel for versions and channels; * - every feature becomes a card: a one-row table with the preview on the left, the title and summary on the right; * a code preview gives way to the recording of the site's animated preview (`Website/docs/Images/readme-previews`); @@ -88,13 +88,16 @@ function linkRow(tree, site, locales) { } /** The install section: an instruction, the URL block and a note. The instruction gives way to the install card. */ -function installCard(tree, {previews, exists}) { +function installCard(tree, {installation}) { const index = tree.children.findIndex((node, at) => isHeading(node, 2) && tree.children[at + 1]?.type === 'paragraph' && tree.children[at + 2]?.type === 'code' && /\.git#upm/.test(tree.children[at + 2].value)); - const file = `${previews}/install.webp`; - if (index === -1 || !exists(file)) return; + if (index === -1 || !installation) return; + const branch = /#(upm(?:-preview)?)(?:\/[^\s]+)?$/.exec(tree.children[index + 2].value.trim())?.[1]; + if (!branch) return; + const file = `${installation}/${branch === 'upm-preview' ? 'preview/' : ''}install`; const steps = TEXT.steps.map((step) => `
  3. ${step}
  4. `).join('\n'); - tree.children[index + 1] = html(`\n\n\n` + const picture = `${image(`${escape(file)}.png`, TEXT.walkthrough, ' width="100%"')}`; + tree.children[index + 1] = html(`
    ${image(file, TEXT.walkthrough, ' width="100%"')}
    \n\n\n` + `\n\n
    ${picture}\n
      \n${steps}\n
    \n
    `); } @@ -218,6 +221,7 @@ function donateCard(tree, {images, exists}) { * @param options.repository the repository's GitHub URL, without a trailing `/` * @param options.previews the folder of the preview recordings, relative to the README * @param options.images the folder of the README images, relative to the README + * @param options.installation the shared installation media base URL for this package * @param options.exists whether a URL relative to the README names a file */ export function githubLayout(tree, options) { diff --git a/Website/scripts/github-readme.test.mjs b/Website/scripts/github-readme.test.mjs index 92cafe64..146d6fd0 100644 --- a/Website/scripts/github-readme.test.mjs +++ b/Website/scripts/github-readme.test.mjs @@ -13,6 +13,7 @@ const repository = 'https://github.com/owner/repo'; function layout(markdown, files = []) { const tree = processor.parse(markdown); githubLayout(tree, {site, locales: ['en', 'ru'], repository, previews: 'Website/docs/Images/readme-previews', + installation: 'https://vpdpersonal.github.io/VPDPersonal/installation/aspid-fasttools', images: 'Website/docs/Images', exists: (url) => files.includes(url)}); return processor.stringify(tree); } @@ -74,11 +75,16 @@ test('the note under the install URL links the install panel on the site', () => test('the install instruction becomes a card with the walk-through and the steps', () => { const install = '## Installation\n\nIn **Window → Package Manager**, paste this URL:\n\n```text\nhttps://github.com/owner/repo.git#upm\n```\n\nThe URL installs the latest release.\n'; - const result = layout(install, ['Website/docs/Images/readme-previews/install.webp']); - assert.match(result, /^## Installation\n\n\n\n\n
    \n
    /); + assert.ok(result.includes('srcset="https://vpdpersonal.github.io/VPDPersonal/installation/aspid-fasttools/install.webp"')); + assert.ok(result.includes('src="https://vpdpersonal.github.io/VPDPersonal/installation/aspid-fasttools/install.png"')); assert.match(result, /
      \n
    1. Open Window → Package Manager<\/b><\/li>\n.*\n
    2. Paste the URL and press Install<\/b><\/li>\n<\/ol>/); assert.match(result, /<\/table>\n\n```text\nhttps:\/\/github.com\/owner\/repo.git#upm\n```/); - assert.match(layout(install), /^## Installation\n\nIn \*\*Window → Package Manager\*\*, paste this URL:/); + const preview = layout(install.replaceAll('#upm', '#upm-preview')); + assert.ok(preview.includes('/installation/aspid-fasttools/preview/install.webp')); + assert.ok(preview.includes('/installation/aspid-fasttools/preview/install.png')); + assert.match(preview, /```text\nhttps:\/\/github.com\/owner\/repo.git#upm-preview\n```/); }); test('a feature becomes a card with its dark preview only, its summary as HTML', () => { diff --git a/Website/scripts/sync-readme.mjs b/Website/scripts/sync-readme.mjs index 6bc941a6..f349e504 100644 --- a/Website/scripts/sync-readme.mjs +++ b/Website/scripts/sync-readme.mjs @@ -49,6 +49,7 @@ function generate() { site, locales, repository, + installation: 'https://vpdpersonal.github.io/VPDPersonal/installation/aspid-fasttools', previews: path.posix.relative(destinationDir, 'Website/docs/Images/readme-previews'), images: path.posix.relative(destinationDir, 'Website/docs/Images'), exists: (url) => fs.existsSync(path.join(repoDir, destinationDir, url)), diff --git a/scripts/set-version.sh b/scripts/set-version.sh index a1ee4be5..f1425f1b 100755 --- a/scripts/set-version.sh +++ b/scripts/set-version.sh @@ -91,7 +91,4 @@ npm --prefix Website run --silent sync-readme # Whatever a pattern above missed (a reworded badge, say) fails here instead of at the release. node scripts/check-version.mjs echo "$OLD -> $NEW ($BRANCH)" -# The GitHub README's install walk-through types the channel's URL; a recording is not a text file to rewrite. -case "$OLD" in *-*) OLD_BRANCH=upm-preview ;; *) OLD_BRANCH=upm ;; esac -[ "$OLD_BRANCH" = "$BRANCH" ] || echo "The channel changed: re-record the README install walk-through (Website/media/readme-previews/README.md)." git status --short diff --git a/scripts/set-version.test.mjs b/scripts/set-version.test.mjs index a80c6be7..61ef128d 100644 --- a/scripts/set-version.test.mjs +++ b/scripts/set-version.test.mjs @@ -135,7 +135,8 @@ test('a stable version moves the files to the release channel and ships the anal assert.equal(result.status, 0, output(result)); assert.equal(version(dir), STABLE); assertVersionChecked(dir); - assert.equal(/The channel changed/.test(result.stdout), current.includes('-'), result.stdout); + assert.doesNotMatch(result.stdout, /re-record/); + assert.match(read(dir, 'README.md'), /installation\/aspid-fasttools\/install\.webp/); for (const file of [DOCS, RU_DOCS]) { assert.match(read(dir, file), /\[!\[Release 99\.0\.0\]/, file);