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`.
This commit is contained in:
Valentin Maerten
2026-08-30 14:22:50 +02:00
parent e209766d52
commit c8e814333c
6 changed files with 128 additions and 53 deletions

View File

@@ -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) {
<span class="status-dot" aria-hidden="true"></span>
Taskfile.yml
</div>
<pre
v-pre
><code><span class="syntax-key">version</span>: <span class="syntax-string">'3'</span>
<span class="syntax-key">vars</span>:
<span class="syntax-key">GREETING</span>: <span class="syntax-string">Hello</span>
<span class="syntax-key">tasks</span>:
<span class="syntax-key">test</span>:
<span class="syntax-key">desc</span>: <span class="syntax-string">Run the test suite</span>
<span class="syntax-key">sources</span>: [<span class="syntax-string">'**/*.go'</span>]
<span class="syntax-key">cmds</span>:
- go test ./...
<span class="syntax-key">build</span>:
<span class="syntax-key">desc</span>: <span class="syntax-string">Build the application</span>
<span class="syntax-key">deps</span>: [test]
<span class="syntax-key">sources</span>: [<span class="syntax-string">'**/*.go'</span>]
<span class="syntax-key">generates</span>: [bin/app]
<span class="syntax-key">cmds</span>:
- mkdir -p bin
- echo <span class="syntax-string">"{{.GREETING}} from Task"</span>
- go build -o bin/app ./cmd/app</code></pre>
<div class="code-body" v-html="example.taskfile"></div>
</div>
<div class="code-panel terminal-panel">
@@ -127,22 +106,9 @@ function track(event: string) {
<span class="status-dot" aria-hidden="true"></span>
Terminal
</div>
<pre><code><span class="terminal-prompt">$</span> task --list
task: Available tasks for this project:
* build: Build the application
* test: Run the test suite
<span class="terminal-prompt">$</span> 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
<span class="terminal-prompt">$</span> task build
task: Task "test" is up to date
task: Task "build" is up to date</code></pre>
<div class="code-body">
<pre><code v-html="example.terminal"></code></pre>
</div>
</div>
</div>
@@ -286,7 +252,7 @@ task: Task "build" is up to date</code></pre>
}
.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></pre>
}
.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</code></pre>
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</code></pre>
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</code></pre>
border-left: 0;
}
.code-panel pre {
.code-panel :deep(pre) {
min-height: auto;
}
@@ -530,7 +497,7 @@ task: Task "build" is up to date</code></pre>
grid-column: 1 / -1;
}
.code-panel pre {
.code-panel :deep(pre) {
padding: 1rem;
font-size: 0.74rem;
}

View File

@@ -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<HomeExample> {
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('$ ')
? `<span class="terminal-prompt">$</span>${escapeHtml(line.slice(1))}`
: escapeHtml(line)
)
.join('\n');
}
function escapeHtml(value: string): string {
return value
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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)