diff --git a/astro.config.mjs b/astro.config.mjs index a2e204b..f0db395 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -8,6 +8,27 @@ import rehypeAutolinkHeadings from 'rehype-autolink-headings'; import { lastModified, pageReleases, pageSources } from './src/lib/lastmod.ts'; import { getReleases } from './src/lib/github.ts'; +/** + * Wraps every markdown table in a container that scrolls sideways. The page + * clips horizontal overflow (global.css), so a table wider than a phone screen + * would otherwise be cut off rather than scroll. + */ +function rehypeScrollingTables() { + /** @param {any} node */ + const visit = (node) => { + if (!Array.isArray(node.children)) return; + node.children = node.children.map((/** @type {any} */ child) => { + if (child.type === 'element' && child.tagName === 'table') { + // Focusable, like the code blocks, so that it can be scrolled from the keyboard. + return { type: 'element', tagName: 'div', properties: { className: ['table-scroll'], tabIndex: 0 }, children: [child] }; + } + visit(child); + return child; + }); + }; + return (/** @type {any} */ tree) => visit(tree); +} + // https://astro.build/config export default defineConfig({ site: 'https://thinkwat.ch', @@ -87,6 +108,7 @@ export default defineConfig({ wrap: false, }, rehypePlugins: [ + rehypeScrollingTables, rehypeSlug, [ rehypeAutolinkHeadings, diff --git a/package.json b/package.json index 4ac8384..bfb5581 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "pagefind": "pagefind --site dist --output-path dist/pagefind", "preview": "astro preview", "releases": "node scripts/update-releases.mjs", + "core-docs": "node scripts/update-core-docs.mjs", "favicons": "node scripts/generate-favicons.mjs", "astro": "astro" }, diff --git a/scripts/update-core-docs.mjs b/scripts/update-core-docs.mjs new file mode 100644 index 0000000..680a59c --- /dev/null +++ b/scripts/update-core-docs.mjs @@ -0,0 +1,18 @@ +// Refresh src/data/core-docs, the committed copy of the ThinkWatch Core +// documents this site publishes (the configuration reference and the server +// deployment guide), from the latest Core release. The build always fetches +// the documents itself and uses this copy only when GitHub cannot be reached; +// it warns when the copy no longer matches. See src/lib/core-docs.mjs. +// +// Run with: pnpm core-docs (GITHUB_TOKEN is used when set; CORE_DOCS_REF +// takes another tag). +import { fileURLToPath } from "node:url"; + +// Paths in core-docs.mjs are relative to the project root. +process.chdir(fileURLToPath(new URL("..", import.meta.url))); +const { coreDocsRef, fetchCoreDocs, SNAPSHOT_DIR, writeSnapshot } = await import("../src/lib/core-docs.mjs"); + +const ref = await coreDocsRef(); +const docs = await fetchCoreDocs(ref); +await writeSnapshot(docs); +console.log(`✓ Wrote ${SNAPSHOT_DIR} from ThinkWatch Core ${ref} (${Object.keys(docs.files).join(", ")})`); diff --git a/src/components/CopyCommand.astro b/src/components/CopyCommand.astro new file mode 100644 index 0000000..21f7b33 --- /dev/null +++ b/src/components/CopyCommand.astro @@ -0,0 +1,58 @@ +--- +// A shell command with a copy button: the command scrolls, the button stays. +// Used for the twcore install command on the Core page and on the home page. +import { getLang, t } from "~/i18n"; + +interface Props { + command: string; + /** Colour and size of the command text */ + class?: string; +} + +const { command, class: className = "text-[#e6ebf2] text-[15px] sm:text-base" } = Astro.props; +const ui = t(getLang(Astro)).common; +--- + +
+ $ {command}
+
+
++
+
{c.hero.sub}
-{c.install.eyebrow}
+{text}
+ ))} + +{c.install.scriptLabel}
+{c.install.pinNote}
+{c.install.nextLabel}
+{row.cmd}
+ {row.note}
+ {c.install.serviceUser}
+{asServiceUser}
+ {c.install.binariesBody}
+ ++ {version && `${c.install.version} ${version} · `} + {c.install.releases} +
+{c.install.sourceBody}
+{row.crates}
- {i === 0 ? (
-
+ {row.mark === "shared" ? (
+
{c.layers.sharedTag}
- ) : i >= 2 ? (
+ ) : row.mark === "local" ? (
{c.layers.localNote}
) : (
@@ -130,6 +253,7 @@ const textLink =
))}
{c.layers.footnote}
+ {c.layers.docs}+ {zh ? "本页取自 ThinkWatch Core 仓库 " : "This page is published from "} + {synced.source} + {zh ? `(${synced.ref})。` : ` in the ThinkWatch Core repository, at ${synced.ref}.`} +
+ )} {homeCards.length > 0 && (