mirror of
https://github.com/zoriya/v10.git
synced 2026-08-05 05:37:21 +00:00
feat(site): add shiki notation transformers (#937)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
62a8c389e1
commit
2c2610f168
Generated
+44
-1
@@ -440,6 +440,9 @@ importers:
|
||||
'@sentry/astro':
|
||||
specifier: ^10.32.1
|
||||
version: 10.42.0(astro@5.18.0(@netlify/blobs@10.7.0)(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.59.0)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))(rollup@4.59.0)
|
||||
'@shikijs/transformers':
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2))
|
||||
@@ -2945,6 +2948,10 @@ packages:
|
||||
'@shikijs/core@3.23.0':
|
||||
resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==}
|
||||
|
||||
'@shikijs/core@4.0.2':
|
||||
resolution: {integrity: sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
'@shikijs/engine-javascript@3.23.0':
|
||||
resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==}
|
||||
|
||||
@@ -2954,12 +2961,24 @@ packages:
|
||||
'@shikijs/langs@3.23.0':
|
||||
resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==}
|
||||
|
||||
'@shikijs/primitive@4.0.2':
|
||||
resolution: {integrity: sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
'@shikijs/themes@3.23.0':
|
||||
resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==}
|
||||
|
||||
'@shikijs/transformers@4.0.2':
|
||||
resolution: {integrity: sha512-1+L0gf9v+SdDXs08vjaLb3mBFa8U7u37cwcBQIv/HCocLwX69Tt6LpUCjtB+UUTvQxI7BnjZKhN/wMjhHBcJGg==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
'@shikijs/types@3.23.0':
|
||||
resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==}
|
||||
|
||||
'@shikijs/types@4.0.2':
|
||||
resolution: {integrity: sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
'@shikijs/vscode-textmate@10.0.2':
|
||||
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
|
||||
|
||||
@@ -10302,6 +10321,14 @@ snapshots:
|
||||
'@types/hast': 3.0.4
|
||||
hast-util-to-html: 9.0.5
|
||||
|
||||
'@shikijs/core@4.0.2':
|
||||
dependencies:
|
||||
'@shikijs/primitive': 4.0.2
|
||||
'@shikijs/types': 4.0.2
|
||||
'@shikijs/vscode-textmate': 10.0.2
|
||||
'@types/hast': 3.0.4
|
||||
hast-util-to-html: 9.0.5
|
||||
|
||||
'@shikijs/engine-javascript@3.23.0':
|
||||
dependencies:
|
||||
'@shikijs/types': 3.23.0
|
||||
@@ -10317,15 +10344,31 @@ snapshots:
|
||||
dependencies:
|
||||
'@shikijs/types': 3.23.0
|
||||
|
||||
'@shikijs/primitive@4.0.2':
|
||||
dependencies:
|
||||
'@shikijs/types': 4.0.2
|
||||
'@shikijs/vscode-textmate': 10.0.2
|
||||
'@types/hast': 3.0.4
|
||||
|
||||
'@shikijs/themes@3.23.0':
|
||||
dependencies:
|
||||
'@shikijs/types': 3.23.0
|
||||
|
||||
'@shikijs/transformers@4.0.2':
|
||||
dependencies:
|
||||
'@shikijs/core': 4.0.2
|
||||
'@shikijs/types': 4.0.2
|
||||
|
||||
'@shikijs/types@3.23.0':
|
||||
dependencies:
|
||||
'@shikijs/vscode-textmate': 10.0.2
|
||||
'@types/hast': 3.0.4
|
||||
|
||||
'@shikijs/types@4.0.2':
|
||||
dependencies:
|
||||
'@shikijs/vscode-textmate': 10.0.2
|
||||
'@types/hast': 3.0.4
|
||||
|
||||
'@shikijs/vscode-textmate@10.0.2': {}
|
||||
|
||||
'@simple-libs/stream-utils@1.2.0': {}
|
||||
@@ -10804,7 +10847,7 @@ snapshots:
|
||||
std-env: 3.10.0
|
||||
test-exclude: 7.0.2
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@27.4.0)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||
optionalDependencies:
|
||||
'@vitest/browser': 3.2.4(playwright@1.58.2)(vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.2))(vitest@3.2.4)
|
||||
transitivePeerDependencies:
|
||||
|
||||
@@ -15,6 +15,7 @@ import pagefind from './integrations/pagefind';
|
||||
import rehypePrepareCodeBlocks from './src/utils/rehypePrepareCodeBlocks';
|
||||
import remarkConditionalHeadings from './src/utils/remarkConditionalHeadings';
|
||||
import { remarkReadingTime } from './src/utils/remarkReadingTime.mjs';
|
||||
import { shikiNotationTransformers } from './src/utils/shikiNotationTransformers';
|
||||
import shikiTransformMetadata from './src/utils/shikiTransformMetadata';
|
||||
|
||||
// On production deploys, use the custom domain — DEPLOY_PRIME_URL always returns
|
||||
@@ -98,8 +99,7 @@ export default defineConfig({
|
||||
light: 'gruvbox-dark-hard',
|
||||
dark: 'gruvbox-dark-soft',
|
||||
},
|
||||
// TODO more shiki transformers
|
||||
transformers: [shikiTransformMetadata],
|
||||
transformers: [shikiTransformMetadata, ...shikiNotationTransformers],
|
||||
},
|
||||
remarkPlugins: [remarkConditionalHeadings, remarkReadingTime],
|
||||
rehypePlugins: [rehypePrepareCodeBlocks],
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"@nanostores/react": "^1.0.0",
|
||||
"@pagefind/default-ui": "^1.4.0",
|
||||
"@sentry/astro": "^10.32.1",
|
||||
"@shikijs/transformers": "^4.0.2",
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
"@videojs/html": "workspace:*",
|
||||
"@videojs/react": "workspace:*",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import clsx from 'clsx';
|
||||
import type { BundledLanguage, Highlighter } from 'shiki';
|
||||
import { hastToHtml } from 'shiki';
|
||||
import { shikiNotationTransformers } from '@/utils/shikiNotationTransformers';
|
||||
|
||||
export interface SharedProps {
|
||||
code: string;
|
||||
@@ -15,6 +16,7 @@ export default function Shared({ code, lang, highlighter }: SharedProps) {
|
||||
light: 'gruvbox-dark-hard',
|
||||
dark: 'gruvbox-dark-soft',
|
||||
},
|
||||
transformers: shikiNotationTransformers,
|
||||
});
|
||||
|
||||
// shiki gives us a root > pre > code > text structure
|
||||
@@ -39,7 +41,7 @@ export default function Shared({ code, lang, highlighter }: SharedProps) {
|
||||
const { class: codeClassName } = codeProps;
|
||||
|
||||
return (
|
||||
<pre className={clsx('shiki text-manila-light', preClassName)}>
|
||||
<pre className={clsx('shiki astro-code text-manila-light', preClassName)}>
|
||||
<code className={clsx('font-mono text-code', codeClassName)} dangerouslySetInnerHTML={{ __html: html }} />
|
||||
</pre>
|
||||
);
|
||||
|
||||
@@ -216,6 +216,44 @@ we can use 3 backticks ``` in new line and write snippet and close with 3 backti
|
||||
</html>
|
||||
```
|
||||
|
||||
### Code annotations
|
||||
|
||||
You can annotate code blocks with special comments to highlight, diff, focus, or word-highlight specific lines. The annotation comments are stripped from the rendered output (and from copy/paste).
|
||||
|
||||
#### Diff
|
||||
|
||||
Show added and removed lines with `// [!code ++]` and `// [!code --]`:
|
||||
|
||||
```ts
|
||||
function greet(name: string) {
|
||||
console.log('Hello') // [!code --]
|
||||
console.log(`Hello, ${name}!`) // [!code ++]
|
||||
console.log(`It's great to meet you.`) // [!code ++]
|
||||
}
|
||||
```
|
||||
|
||||
#### Focus
|
||||
|
||||
Dim everything except the focused lines with `// [!code focus]`. Hovering the code block reveals all lines:
|
||||
|
||||
```ts
|
||||
function greet(name: string) {
|
||||
const message = `hello, ${name}!`
|
||||
console.log(message) // [!code focus]
|
||||
}
|
||||
```
|
||||
|
||||
#### Word highlight
|
||||
|
||||
Highlight a specific word or phrase with `// [!code word:term]`. For example, `// [!code word:name]` looks like this:
|
||||
|
||||
```ts
|
||||
// [!code word:name]
|
||||
function greet(name: string) {
|
||||
console.log(`hello, ${name}!`)
|
||||
}
|
||||
```
|
||||
|
||||
### List types
|
||||
|
||||
#### Ordered list
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "tailwindcss";
|
||||
@import "./shiki-transformers.css";
|
||||
|
||||
/**
|
||||
* @license
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
@layer base {
|
||||
.astro-code code {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.astro-code .line {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
line-height: 1.75;
|
||||
}
|
||||
.astro-code .line.diff,
|
||||
.astro-code .line.focused {
|
||||
width: calc(100% + var(--spacing) * 12);
|
||||
margin-inline: calc(var(--spacing) * -6);
|
||||
padding-inline: calc(var(--spacing) * 6);
|
||||
}
|
||||
|
||||
/* Diff: added lines */
|
||||
.astro-code .line.diff.add {
|
||||
background-color: rgba(184, 187, 38, 0.12);
|
||||
}
|
||||
|
||||
.astro-code .line.diff.add::before,
|
||||
.astro-code .line.diff.remove::before {
|
||||
position: absolute;
|
||||
font-weight: bold;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: calc(var(--spacing) * 6);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.astro-code .line.diff.add::before {
|
||||
content: "+";
|
||||
color: rgba(184, 187, 31, 1);
|
||||
}
|
||||
|
||||
/* Diff: removed lines */
|
||||
.astro-code .line.diff.remove {
|
||||
background-color: rgba(251, 73, 52, 0.12);
|
||||
}
|
||||
|
||||
.astro-code .line.diff.remove::before {
|
||||
content: "-";
|
||||
color: rgba(251, 73, 52, 1);
|
||||
}
|
||||
|
||||
/* Word highlight */
|
||||
.astro-code .highlighted-word {
|
||||
background-color: var(--color-soot);
|
||||
border-bottom: 1px solid var(--color-manila-dark);
|
||||
padding-inline: 0.2em;
|
||||
}
|
||||
|
||||
:where(.dark, .dark *) .astro-code .highlighted-word {
|
||||
background-color: var(--color-faded-black);
|
||||
}
|
||||
|
||||
/* Focus: mute unfocused lines, reveal on hover */
|
||||
.astro-code:has(.line.focused) .line:not(.focused) span {
|
||||
opacity: 0.4;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.astro-code:has(.line.focused):hover .line:not(.focused) span,
|
||||
.astro-code:has(.line.focused):focus-within .line:not(.focused) span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import {
|
||||
transformerNotationDiff,
|
||||
transformerNotationFocus,
|
||||
transformerNotationWordHighlight,
|
||||
} from '@shikijs/transformers';
|
||||
import type { ShikiTransformer } from 'shiki';
|
||||
|
||||
export const shikiNotationTransformers: ShikiTransformer[] = [
|
||||
transformerNotationDiff({ matchAlgorithm: 'v3' }),
|
||||
transformerNotationFocus({ matchAlgorithm: 'v3' }),
|
||||
transformerNotationWordHighlight({ matchAlgorithm: 'v3' }),
|
||||
];
|
||||
Reference in New Issue
Block a user