From f7a20466cbe098731b367f6e975bd033001adf4e Mon Sep 17 00:00:00 2001 From: plmn95 Date: Wed, 23 Sep 2026 15:10:43 +0300 Subject: [PATCH] Expose editing on documentation mirrors and copy section links without scrolling --- README.md | 6 +++--- src/components/EditPageLink.astro | 6 +++--- src/components/ManualFooter.astro | 2 ++ src/components/SectionLinks.astro | 22 ++++++++++++++++++++++ src/components/SuggestChange.astro | 6 +++--- src/lib/suggestions/config.mjs | 6 ++++++ src/styles/vizard.css | 11 +++++++++++ tests/docs-controls.spec.ts | 24 ++++++++++++++++++++++++ 8 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 src/components/SectionLinks.astro create mode 100644 tests/docs-controls.spec.ts diff --git a/README.md b/README.md index 6716e8d..cb12563 100644 --- a/README.md +++ b/README.md @@ -25,14 +25,14 @@ npm run check ## Contributing -When enabled, **Edit this page** opens a full-page Milkdown editor. Readers can +**Edit this page** opens a full-page Milkdown editor. Readers can send changes for review without a GitHub account. **Describe a problem** accepts reports. GitHub editing remains available for experienced contributors. See [CONTRIBUTING.md](CONTRIBUTING.md). The account-free service requires separate Cloudflare and GitHub App setup; -see [setup and operations](services/suggestions/README.md). It stays disabled -until configured. Run `npm run test:suggestions` for delivery and source-mapping +see [setup and operations](services/suggestions/README.md). Local editor routes stay disabled until configured; unconfigured mirrors link to +the canonical GitHub Pages editor. Versioned manuals retain their online correction link. Run `npm run test:suggestions` for delivery and source-mapping tests, `npm run test:editor` for corpus and browser checks, and `npm run suggestions:check` to verify the Worker bundle. ## Manuals shipped with Vizard diff --git a/src/components/EditPageLink.astro b/src/components/EditPageLink.astro index 9983d6b..e79cb17 100644 --- a/src/components/EditPageLink.astro +++ b/src/components/EditPageLink.astro @@ -1,10 +1,10 @@ --- -import { enabled } from '../lib/suggestions/config.mjs'; +import { contributionEnabled, editorUrl } from '../lib/suggestions/config.mjs'; const path = String(Astro.locals.starlightRoute.editUrl ?? '').split('/edit/main/src/content/docs/')[1]; const base = import.meta.env.BASE_URL.replace(/\/$/, ''); -const href = path ? `${base}/edit/${path.replace(/\.md$/, '')}/` : ''; +const href = path ? editorUrl(path, base) : ''; --- -{enabled && href && Edit this page } +{contributionEnabled && href && Edit this page } + diff --git a/src/components/SuggestChange.astro b/src/components/SuggestChange.astro index 19b655f..4066c10 100644 --- a/src/components/SuggestChange.astro +++ b/src/components/SuggestChange.astro @@ -1,12 +1,12 @@ --- import EditPageLink from './EditPageLink.astro'; -import { enabled } from '../lib/suggestions/config.mjs'; +import { contributionEnabled, editorUrl } from '../lib/suggestions/config.mjs'; const path = String(Astro.locals.starlightRoute.editUrl ?? '').split('/edit/main/src/content/docs/')[1]; const base = import.meta.env.BASE_URL.replace(/\/$/, ''); --- -{enabled && path &&
+{contributionEnabled && path &&
- Describe a problem + Describe a problem

No account needed. Changes are reviewed before publication.

} diff --git a/src/lib/suggestions/config.mjs b/src/lib/suggestions/config.mjs index dbc5ba7..0fd33f6 100644 --- a/src/lib/suggestions/config.mjs +++ b/src/lib/suggestions/config.mjs @@ -6,3 +6,9 @@ export const siteKey = process.env.VIZARD_TURNSTILE_SITE_KEY || ''; export const enabled = Boolean(api && siteKey && !process.env.VIZARD_DOCS_VERSION); if (api && !/^https:\/\/[^\s]+$/.test(api) && !/^http:\/\/(localhost|127\.0\.0\.1):\d+$/.test(api)) throw new Error('VIZARD_SUGGESTIONS_API must be an HTTPS URL (or localhost for development).'); + +// Unconfigured mirrors still offer the canonical, account-free editor. +export const contributionEnabled = !process.env.VIZARD_DOCS_VERSION; +export function editorUrl(path, base = '') { + return `${enabled ? base.replace(/\/$/, '') : 'https://plmn95.github.io/vizard-docs'}/edit/${path.replace(/\.md$/, '')}/`; +} diff --git a/src/styles/vizard.css b/src/styles/vizard.css index 257de5e..6ef445d 100644 --- a/src/styles/vizard.css +++ b/src/styles/vizard.css @@ -537,3 +537,14 @@ mobile-starlight-toc:has(li:only-child > a[href='#_top']) { transition-duration: 0.01ms !important; } } + +/* Match wrapper metrics to our heading sizes; Starlight uses them for icon placement. */ +.sl-markdown-content .sl-heading-wrapper.level-h2 { font-size: clamp(1.35rem, 2.4vw, 1.65rem); } +.sl-markdown-content .sl-heading-wrapper.level-h3 { font-size: 1.15rem; } +.sl-markdown-content .sl-anchor-link { vertical-align: 0.15em; } +.sl-markdown-content .sl-anchor-icon > svg { + display: inline-block; + height: var(--sl-anchor-icon-size); + vertical-align: baseline; + transform: none; +} diff --git a/tests/docs-controls.spec.ts b/tests/docs-controls.spec.ts new file mode 100644 index 0000000..16abf90 --- /dev/null +++ b/tests/docs-controls.spec.ts @@ -0,0 +1,24 @@ +import { test, expect } from '@playwright/test'; + +test('page editing is discoverable and section links copy without scrolling', async ({ page }) => { + const errors: string[] = []; + page.on('pageerror', error => errors.push(error.message)); + await page.addInitScript(() => Object.defineProperty(navigator, 'clipboard', {value: {writeText: async (text: string) => { (window as any).copiedLink = text; }}})); + await page.goto('./'); + await expect(page).toHaveTitle(/Vizard/); + await expect(page.locator('.title-row').getByRole('link', {name: 'Edit this page'})).toBeVisible(); + const link = page.getByRole('link', {name: 'Copy link to Start here', exact: true}); + await link.scrollIntoViewIfNeeded(); + const before = await page.evaluate(() => ({y: scrollY, url: location.href})); + await link.click(); + await expect(page.getByRole('status')).toHaveText('Link to Start here copied.'); + expect(await page.evaluate(() => ({y: scrollY, url: location.href}))).toEqual(before); + expect(await page.evaluate(() => (window as any).copiedLink)).toContain('#start-here'); + await page.screenshot({path: '/tmp/vizard-doc-controls-desktop.png'}); + await page.setViewportSize({width: 390, height: 844}); + await page.goto('./'); + await expect(page.locator('.title-row').getByRole('link', {name: 'Edit this page'})).toBeVisible(); + expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true); + await page.screenshot({path: '/tmp/vizard-doc-controls-mobile.png'}); + expect(errors).toEqual([]); +});