Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Documentation: [EN](https://vpdpersonal.github.io/Aspid.FastTools/docs), [RU](ht

<table>
<tr>
<td width="56%"><img src="Website/docs/Images/readme-previews/install.webp" alt="Package Manager installs Aspid.FastTools from its git URL" width="100%"></td>
<td width="56%"><picture><source srcset="https://vpdpersonal.github.io/VPDPersonal/installation/aspid-fasttools/install.webp" type="image/webp"><img src="https://vpdpersonal.github.io/VPDPersonal/installation/aspid-fasttools/install.png" alt="Package Manager installs Aspid.FastTools from its git URL" width="100%"></picture></td>
<td width="44%">
<ol>
<li>Open <b>Window → Package Manager</b></li>
Expand Down
Binary file removed Website/docs/Images/readme-previews/install.webp
Binary file not shown.
17 changes: 10 additions & 7 deletions Website/media/readme-previews/README.md
Original file line number Diff line number Diff line change
@@ -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/<name>.webp`, `install` for the walk-through. Only the dark theme: a `<picture>` per
`Website/docs/Images/readme-previews/<name>.webp`. Only the dark theme: a `<picture>` 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:<port>/Aspid.FastTools/ [name …]`.
Expand Down
14 changes: 3 additions & 11 deletions Website/media/readme-previews/record.mjs
Original file line number Diff line number Diff line change
@@ -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/<name>.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
Expand All @@ -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},
Expand Down Expand Up @@ -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');
Expand All @@ -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; }'
+ '</style>'));`});
const loaded = once('Page.loadEventFired', sessionId);
await page('Page.navigate', {url: new URL('docs', base).href});
Expand Down
16 changes: 10 additions & 6 deletions Website/scripts/github-readme.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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`);
Expand Down Expand Up @@ -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) => `<li>${step}</li>`).join('\n');
tree.children[index + 1] = html(`<table>\n<tr>\n<td width="56%">${image(file, TEXT.walkthrough, ' width="100%"')}</td>\n`
const picture = `<picture><source srcset="${escape(file)}.webp" type="image/webp">${image(`${escape(file)}.png`, TEXT.walkthrough, ' width="100%"')}</picture>`;
tree.children[index + 1] = html(`<table>\n<tr>\n<td width="56%">${picture}</td>\n`
+ `<td width="44%">\n<ol>\n${steps}\n</ol>\n</td>\n</tr>\n</table>`);
}

Expand Down Expand Up @@ -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) {
Expand Down
12 changes: 9 additions & 3 deletions Website/scripts/github-readme.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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<table>\n<tr>\n<td width="56%"><img src="Website\/docs\/Images\/readme-previews\/install.webp"/);
const result = layout(install);
assert.match(result, /^## Installation\n\n<table>\n<tr>\n<td width="56%"><picture>/);
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, /<ol>\n<li>Open <b>Window → Package Manager<\/b><\/li>\n.*\n<li>Paste the URL and press <b>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', () => {
Expand Down
1 change: 1 addition & 0 deletions Website/scripts/sync-readme.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down
3 changes: 0 additions & 3 deletions scripts/set-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 2 additions & 1 deletion scripts/set-version.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading