From c8e814333ce494b620c9486f98556c5e34a72cd4 Mon Sep 17 00:00:00 2001 From: Valentin Maerten Date: Sun, 30 Aug 2026 14:22:50 +0200 Subject: [PATCH] refactor(site): render the homepage example with shiki The Taskfile and terminal panels were hand-marked HTML with their own .syntax-* classes, so the sample missed the site's code theme and could drift from what Task actually prints. Move both to files under .vitepress/snippets and highlight the YAML at build time through a VitePress data loader, using the same Shiki themes as fenced code blocks. The terminal transcript is now the verbatim output of running the sample Taskfile: the previous one had the wrong column padding for `task --list`. --- website/.vitepress/components/HomePage.vue | 71 +++++-------------- .../.vitepress/components/homeExample.data.ts | 67 +++++++++++++++++ .../.vitepress/snippets/homepage-taskfile.yml | 21 ++++++ .../.vitepress/snippets/homepage-terminal.txt | 16 +++++ website/package.json | 3 +- website/pnpm-lock.yaml | 3 + 6 files changed, 128 insertions(+), 53 deletions(-) create mode 100644 website/.vitepress/components/homeExample.data.ts create mode 100644 website/.vitepress/snippets/homepage-taskfile.yml create mode 100644 website/.vitepress/snippets/homepage-terminal.txt diff --git a/website/.vitepress/components/HomePage.vue b/website/.vitepress/components/HomePage.vue index 0339bcda..9c2d993a 100644 --- a/website/.vitepress/components/HomePage.vue +++ b/website/.vitepress/components/HomePage.vue @@ -3,6 +3,7 @@ import { computed, ref } from 'vue'; import { VPHomeSponsors } from 'vitepress/theme'; import { sponsors } from '../sponsors'; import AdoptersCarousel from './AdoptersCarousel.vue'; +import { data as example } from './homeExample.data'; const installCommand = 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin'; @@ -97,29 +98,7 @@ function track(event: string) { Taskfile.yml -
version: '3'
-
-vars:
-  GREETING: Hello
-
-tasks:
-  test:
-    desc: Run the test suite
-    sources: ['**/*.go']
-    cmds:
-      - go test ./...
-
-  build:
-    desc: Build the application
-    deps: [test]
-    sources: ['**/*.go']
-    generates: [bin/app]
-    cmds:
-      - mkdir -p bin
-      - echo "{{.GREETING}} from Task"
-      - go build -o bin/app ./cmd/app
+
@@ -127,22 +106,9 @@ function track(event: string) { Terminal
-
$ task --list
-task: Available tasks for this project:
-* build:  Build the application
-* test:   Run the test suite
-
-$ task build
-task: [test] go test ./...
-ok      example/app
-task: [build] mkdir -p bin
-task: [build] echo "Hello from Task"
-Hello from Task
-task: [build] go build -o bin/app ./cmd/app
-
-$ task build
-task: Task "test" is up to date
-task: Task "build" is up to date
+
+
+
@@ -286,7 +252,7 @@ task: Task "build" is up to date } .install-command .prompt, -.terminal-prompt { +.example :deep(.terminal-prompt) { color: var(--vp-c-brand-1); font-weight: 700; } @@ -354,6 +320,14 @@ task: Task "build" is up to date } .code-panel { + display: flex; + flex-direction: column; + min-width: 0; +} + +.code-body { + display: flex; + flex: 1; min-width: 0; } @@ -378,8 +352,9 @@ task: Task "build" is up to date box-shadow: 0 0 0 4px var(--vp-c-brand-soft); } -.code-panel pre { +.code-panel :deep(pre) { min-height: 420px; + min-width: 0; margin: 0; overflow: auto; padding: 1.5rem; @@ -390,15 +365,7 @@ task: Task "build" is up to date line-height: 1.65; } -.syntax-key { - color: var(--vp-c-brand-1); -} - -.syntax-string { - color: var(--vp-c-yellow-1); -} - -.terminal-panel pre { +.terminal-panel :deep(pre) { color: var(--vp-c-text-2); } @@ -502,7 +469,7 @@ task: Task "build" is up to date border-left: 0; } - .code-panel pre { + .code-panel :deep(pre) { min-height: auto; } @@ -530,7 +497,7 @@ task: Task "build" is up to date grid-column: 1 / -1; } - .code-panel pre { + .code-panel :deep(pre) { padding: 1rem; font-size: 0.74rem; } diff --git a/website/.vitepress/components/homeExample.data.ts b/website/.vitepress/components/homeExample.data.ts new file mode 100644 index 00000000..03b14713 --- /dev/null +++ b/website/.vitepress/components/homeExample.data.ts @@ -0,0 +1,67 @@ +import fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { defineLoader } from 'vitepress'; +import { codeToHtml } from 'shiki'; + +// Same themes VitePress uses for fenced code blocks, so the homepage sample +// picks up the site's own light/dark code colours through `.vp-code`. +const THEMES = { light: 'github-light', dark: 'github-dark' } as const; + +const taskfilePath = fileURLToPath( + new URL('../snippets/homepage-taskfile.yml', import.meta.url) +); +const terminalPath = fileURLToPath( + new URL('../snippets/homepage-terminal.txt', import.meta.url) +); + +export interface HomeExample { + taskfile: string; + terminal: string; +} + +declare const data: HomeExample; +export { data }; + +export default defineLoader({ + watch: [ + '../snippets/homepage-taskfile.yml', + '../snippets/homepage-terminal.txt' + ], + async load(): Promise { + const taskfile = fs.readFileSync(taskfilePath, 'utf-8').trimEnd(); + return { + taskfile: await codeToHtml(taskfile, { + lang: 'yaml', + themes: THEMES, + defaultColor: false, + transformers: [ + { + pre(node) { + this.addClassToHast(node, 'vp-code'); + } + } + ] + }), + terminal: renderTerminal(fs.readFileSync(terminalPath, 'utf-8')) + }; + } +}); + +function renderTerminal(source: string): string { + return source + .trimEnd() + .split('\n') + .map((line) => + line.startsWith('$ ') + ? `$${escapeHtml(line.slice(1))}` + : escapeHtml(line) + ) + .join('\n'); +} + +function escapeHtml(value: string): string { + return value + .replace(/&/g, '&') + .replace(//g, '>'); +} diff --git a/website/.vitepress/snippets/homepage-taskfile.yml b/website/.vitepress/snippets/homepage-taskfile.yml new file mode 100644 index 00000000..2e3c9a7e --- /dev/null +++ b/website/.vitepress/snippets/homepage-taskfile.yml @@ -0,0 +1,21 @@ +version: '3' + +vars: + GREETING: Hello + +tasks: + test: + desc: Run the test suite + sources: ['**/*.go'] + cmds: + - go test ./... + + build: + desc: Build the application + deps: [test] + sources: ['**/*.go'] + generates: [bin/app] + cmds: + - mkdir -p bin + - echo "{{.GREETING}} from Task" + - go build -o bin/app ./cmd/app diff --git a/website/.vitepress/snippets/homepage-terminal.txt b/website/.vitepress/snippets/homepage-terminal.txt new file mode 100644 index 00000000..7aec0c00 --- /dev/null +++ b/website/.vitepress/snippets/homepage-terminal.txt @@ -0,0 +1,16 @@ +$ task --list +task: Available tasks for this project: +* build: Build the application +* test: Run the test suite + +$ task build +task: [test] go test ./... +ok example/app 0.2s +task: [build] mkdir -p bin +task: [build] echo "Hello from Task" +Hello from Task +task: [build] go build -o bin/app ./cmd/app + +$ task build +task: Task "test" is up to date +task: Task "build" is up to date diff --git a/website/package.json b/website/package.json index a8be0fbe..51ff6f18 100644 --- a/website/package.json +++ b/website/package.json @@ -18,10 +18,11 @@ "gray-matter": "^4.0.3", "netlify-cli": "^27.0.0", "prettier": "^3.6.2", + "shiki": "^2.5.0", "vitepress": "^1.6.3", "vitepress-plugin-group-icons": "^1.6.1", - "vitepress-plugin-tabs": "^0.9.0", "vitepress-plugin-llms": "^1.9.1", + "vitepress-plugin-tabs": "^0.9.0", "vue": "^3.5.18" }, "packageManager": "pnpm@11.22.0+sha512.1ff870c4c6133dfd88fb2afc46dd13d47f09c9794b438c6fdb47ca98caf3bc16381ee0be93a091b8e3824cf01f889f46d7d9e20910fb0be1ab0fb5baa80dd621" diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index 94599d49..5a86df40 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: prettier: specifier: ^3.6.2 version: 3.9.6 + shiki: + specifier: ^2.5.0 + version: 2.5.0 vitepress: specifier: ^1.6.3 version: 1.6.4(@algolia/client-search@5.35.0)(@types/node@24.13.3)(jwt-decode@4.0.0)(postcss@8.5.26)(search-insights@2.17.3)(typescript@5.9.3)