polen 0.9.0-next.5 → 0.9.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/api/singletons/markdown/markdown.d.ts.map +1 -1
- package/build/api/singletons/markdown/markdown.js +33 -11
- package/build/api/singletons/markdown/markdown.js.map +1 -1
- package/build/api/vite/plugins/pages.d.ts.map +1 -1
- package/build/api/vite/plugins/pages.js +17 -0
- package/build/api/vite/plugins/pages.js.map +1 -1
- package/build/lib/shiki/index.d.ts +2 -0
- package/build/lib/shiki/index.d.ts.map +1 -0
- package/build/lib/shiki/index.js +2 -0
- package/build/lib/shiki/index.js.map +1 -0
- package/build/lib/shiki/shiki.d.ts +26 -0
- package/build/lib/shiki/shiki.d.ts.map +1 -0
- package/build/lib/shiki/shiki.js +105 -0
- package/build/lib/shiki/shiki.js.map +1 -0
- package/build/template/components/CodeBlock.d.ts +17 -0
- package/build/template/components/CodeBlock.d.ts.map +1 -0
- package/build/template/components/CodeBlock.jsx +42 -0
- package/build/template/components/CodeBlock.jsx.map +1 -0
- package/build/template/entry.client.jsx +1 -0
- package/build/template/entry.client.jsx.map +1 -1
- package/build/template/routes/root.d.ts.map +1 -1
- package/build/template/routes/root.jsx +32 -0
- package/build/template/routes/root.jsx.map +1 -1
- package/package.json +9 -1
- package/src/api/singletons/markdown/markdown.test.ts +89 -0
- package/src/api/singletons/markdown/markdown.ts +35 -13
- package/src/api/vite/plugins/pages.ts +17 -0
- package/src/lib/shiki/index.ts +1 -0
- package/src/lib/shiki/shiki.test.ts +107 -0
- package/src/lib/shiki/shiki.ts +161 -0
- package/src/template/components/CodeBlock.tsx +73 -0
- package/src/template/entry.client.tsx +1 -0
- package/src/template/routes/root.tsx +32 -0
- package/src/template/styles/code-block.css +186 -0
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../../src/api/singletons/markdown/markdown.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../../src/api/singletons/markdown/markdown.ts"],"names":[],"mappings":"AAiCA,eAAO,MAAM,KAAK,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,MAAM,CAG3D,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,SAAS,MAAM,KAAG,MAI3C,CAAA"}
|
@@ -1,18 +1,40 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
import
|
1
|
+
import { unified } from 'unified';
|
2
|
+
import remarkParse from 'remark-parse';
|
3
|
+
import remarkGfm from 'remark-gfm';
|
4
|
+
import remarkRehype from 'remark-rehype';
|
5
|
+
import rehypeShiki from '@shikijs/rehype';
|
6
|
+
import rehypeStringify from 'rehype-stringify';
|
7
|
+
// Create a processor with Shiki for syntax highlighting (async only)
|
8
|
+
const createProcessorWithShiki = () => {
|
9
|
+
return unified()
|
10
|
+
.use(remarkParse)
|
11
|
+
.use(remarkGfm)
|
12
|
+
.use(remarkRehype)
|
13
|
+
.use(rehypeShiki, {
|
14
|
+
themes: {
|
15
|
+
light: `github-light`,
|
16
|
+
dark: `tokyo-night`,
|
17
|
+
},
|
18
|
+
defaultColor: false,
|
19
|
+
cssVariablePrefix: `--shiki-`,
|
20
|
+
})
|
21
|
+
.use(rehypeStringify);
|
22
|
+
};
|
23
|
+
// Create a processor without syntax highlighting for sync processing
|
24
|
+
const createProcessorSync = () => {
|
25
|
+
return unified()
|
26
|
+
.use(remarkParse)
|
27
|
+
.use(remarkGfm)
|
28
|
+
.use(remarkRehype)
|
29
|
+
.use(rehypeStringify);
|
30
|
+
};
|
4
31
|
export const parse = async (content) => {
|
5
|
-
const result = await
|
6
|
-
.use(RemarkGfm)
|
7
|
-
.use(RemarkHtml)
|
8
|
-
.process(content);
|
32
|
+
const result = await createProcessorWithShiki().process(content);
|
9
33
|
return String(result);
|
10
34
|
};
|
11
35
|
export const parseSync = (content) => {
|
12
|
-
|
13
|
-
|
14
|
-
.use(RemarkHtml)
|
15
|
-
.processSync(content);
|
36
|
+
// Note: Syntax highlighting is not available in sync mode due to @shikijs/rehype being async-only
|
37
|
+
const result = createProcessorSync().processSync(content);
|
16
38
|
return String(result);
|
17
39
|
};
|
18
40
|
//# sourceMappingURL=markdown.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../../../src/api/singletons/markdown/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../../../src/api/singletons/markdown/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,WAAW,MAAM,cAAc,CAAA;AACtC,OAAO,SAAS,MAAM,YAAY,CAAA;AAClC,OAAO,YAAY,MAAM,eAAe,CAAA;AACxC,OAAO,WAAW,MAAM,iBAAiB,CAAA;AACzC,OAAO,eAAe,MAAM,kBAAkB,CAAA;AAE9C,qEAAqE;AACrE,MAAM,wBAAwB,GAAG,GAAG,EAAE;IACpC,OAAO,OAAO,EAAE;SACb,GAAG,CAAC,WAAW,CAAC;SAChB,GAAG,CAAC,SAAS,CAAC;SACd,GAAG,CAAC,YAAY,CAAC;SACjB,GAAG,CAAC,WAAW,EAAE;QAChB,MAAM,EAAE;YACN,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE,aAAa;SACpB;QACD,YAAY,EAAE,KAAK;QACnB,iBAAiB,EAAE,UAAU;KAC9B,CAAC;SACD,GAAG,CAAC,eAAe,CAAC,CAAA;AACzB,CAAC,CAAA;AAED,qEAAqE;AACrE,MAAM,mBAAmB,GAAG,GAAG,EAAE;IAC/B,OAAO,OAAO,EAAE;SACb,GAAG,CAAC,WAAW,CAAC;SAChB,GAAG,CAAC,SAAS,CAAC;SACd,GAAG,CAAC,YAAY,CAAC;SACjB,GAAG,CAAC,eAAe,CAAC,CAAA;AACzB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,OAAe,EAAmB,EAAE;IAC9D,MAAM,MAAM,GAAG,MAAM,wBAAwB,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAChE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAe,EAAU,EAAE;IACnD,kGAAkG;IAClG,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IACzD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;AACvB,CAAC,CAAA"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../../../src/api/vite/plugins/pages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAE/D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../../../src/api/vite/plugins/pages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAE/D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAWnD,eAAO,MAAM,cAAc,8DAA0E,CAAA;AACrG,eAAO,MAAM,kBAAkB,8DAAwF,CAAA;AAEvH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,kBAAkB,CAAA;IAC/B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,UAAU,KAAK,IAAI,CAAA;IACtD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,aAAa,KAAK,IAAI,CAAA;CACxD;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,YAAY,CAAA;IAC1B,eAAe,EAAE,UAAU,CAAC,UAAU,CAAA;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,cAAc,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAA;CACrD;AAED;;GAEG;AACH,eAAO,MAAM,KAAK,GAAI,sDAKnB,sBAAsB,KAAG,IAAI,CAAC,MAAM,EAwStC,CAAA;AAGD,eAAO,MAAM,YAAY,GAAU,QAAQ,MAAM,CAAC,MAAM,KAAG,OAAO,CAAC,UAAU,CAAC,aAAa,CAM1F,CAAA"}
|
@@ -7,6 +7,7 @@ import { superjson } from '#singletons/superjson';
|
|
7
7
|
import mdx from '@mdx-js/rollup';
|
8
8
|
import { Path, Str } from '@wollybeard/kit';
|
9
9
|
import remarkGfm from 'remark-gfm';
|
10
|
+
import rehypeShiki from '@shikijs/rehype';
|
10
11
|
const _debug = debug.sub(`vite-plugin-pages`);
|
11
12
|
export const viProjectPages = polenVirtual([`project`, `pages.jsx`], { allowPluginProcessing: true });
|
12
13
|
export const viProjectPagesData = polenVirtual([`project`, `data`, 'pages.jsonsuper'], { allowPluginProcessing: true });
|
@@ -87,6 +88,22 @@ export const Pages = ({ config, navbarData, onPagesChange, onTreeChange, }) => {
|
|
87
88
|
...mdx({
|
88
89
|
jsxImportSource: `polen/react`,
|
89
90
|
remarkPlugins: [remarkGfm],
|
91
|
+
rehypePlugins: [
|
92
|
+
[
|
93
|
+
rehypeShiki,
|
94
|
+
{
|
95
|
+
themes: {
|
96
|
+
light: `github-light`,
|
97
|
+
dark: `tokyo-night`,
|
98
|
+
},
|
99
|
+
defaultColor: false,
|
100
|
+
cssVariablePrefix: `--shiki-`,
|
101
|
+
transformers: [
|
102
|
+
// Line numbers will be handled via CSS
|
103
|
+
],
|
104
|
+
},
|
105
|
+
],
|
106
|
+
],
|
90
107
|
}),
|
91
108
|
},
|
92
109
|
// Plugin 2: Pages Management
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../../../src/api/vite/plugins/pages.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,GAAG,MAAM,gBAAgB,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,SAAS,MAAM,YAAY,CAAA;
|
1
|
+
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../../../src/api/vite/plugins/pages.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/shiki/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/shiki/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { type Highlighter, type BundledTheme, type BundledLanguage } from 'shiki';
|
2
|
+
export interface ShikiOptions {
|
3
|
+
themes?: {
|
4
|
+
light: BundledTheme;
|
5
|
+
dark: BundledTheme;
|
6
|
+
};
|
7
|
+
langs?: BundledLanguage[];
|
8
|
+
defaultTheme?: 'light' | 'dark';
|
9
|
+
}
|
10
|
+
export declare function getHighlighter(options?: ShikiOptions): Promise<Highlighter>;
|
11
|
+
export interface CodeHighlightOptions {
|
12
|
+
code: string;
|
13
|
+
lang?: string;
|
14
|
+
theme?: 'light' | 'dark';
|
15
|
+
showLineNumbers?: boolean;
|
16
|
+
highlightLines?: number[];
|
17
|
+
diffLines?: {
|
18
|
+
add: number[];
|
19
|
+
remove: number[];
|
20
|
+
};
|
21
|
+
focusLines?: number[];
|
22
|
+
showInvisibles?: boolean;
|
23
|
+
}
|
24
|
+
export declare function highlightCode({ code, lang, theme, showLineNumbers, highlightLines, diffLines, focusLines, showInvisibles, }: CodeHighlightOptions): Promise<string>;
|
25
|
+
export type { Highlighter, BundledTheme, BundledLanguage } from 'shiki';
|
26
|
+
//# sourceMappingURL=shiki.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"shiki.d.ts","sourceRoot":"","sources":["../../../src/lib/shiki/shiki.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,OAAO,CAAA;AAQpG,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,YAAY,CAAA;QACnB,IAAI,EAAE,YAAY,CAAA;KACnB,CAAA;IACD,KAAK,CAAC,EAAE,eAAe,EAAE,CAAA;IACzB,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CAChC;AAgDD,wBAAsB,cAAc,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAmBrF;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC/C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,wBAAsB,aAAa,CAAC,EAClC,IAAI,EACJ,IAAa,EACb,KAAe,EACf,eAAuB,EACvB,cAAmB,EACnB,SAAS,EACT,UAAe,EACf,cAAsB,GACvB,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqDxC;AAGD,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,OAAO,CAAA"}
|
@@ -0,0 +1,105 @@
|
|
1
|
+
import { createHighlighter } from 'shiki';
|
2
|
+
import { transformerNotationHighlight, transformerNotationDiff, transformerNotationFocus, transformerRenderWhitespace, } from '@shikijs/transformers';
|
3
|
+
const DEFAULT_THEMES = {
|
4
|
+
light: `github-light`,
|
5
|
+
dark: `tokyo-night`,
|
6
|
+
};
|
7
|
+
const DEFAULT_LANGS = [
|
8
|
+
`typescript`,
|
9
|
+
`javascript`,
|
10
|
+
`jsx`,
|
11
|
+
`tsx`,
|
12
|
+
`graphql`,
|
13
|
+
`json`,
|
14
|
+
`yaml`,
|
15
|
+
`markdown`,
|
16
|
+
`bash`,
|
17
|
+
`shell`,
|
18
|
+
`css`,
|
19
|
+
`html`,
|
20
|
+
`sql`,
|
21
|
+
`python`,
|
22
|
+
`rust`,
|
23
|
+
`go`,
|
24
|
+
`java`,
|
25
|
+
`csharp`,
|
26
|
+
`php`,
|
27
|
+
`ruby`,
|
28
|
+
`swift`,
|
29
|
+
`kotlin`,
|
30
|
+
`scala`,
|
31
|
+
`r`,
|
32
|
+
`matlab`,
|
33
|
+
`latex`,
|
34
|
+
`dockerfile`,
|
35
|
+
`makefile`,
|
36
|
+
`nginx`,
|
37
|
+
`apache`,
|
38
|
+
`xml`,
|
39
|
+
`toml`,
|
40
|
+
`ini`,
|
41
|
+
`diff`,
|
42
|
+
];
|
43
|
+
// Singleton highlighter instance
|
44
|
+
let highlighterInstance = null;
|
45
|
+
let highlighterPromise = null;
|
46
|
+
export async function getHighlighter(options = {}) {
|
47
|
+
if (highlighterInstance) {
|
48
|
+
return highlighterInstance;
|
49
|
+
}
|
50
|
+
if (!highlighterPromise) {
|
51
|
+
const themes = options.themes || DEFAULT_THEMES;
|
52
|
+
const langs = options.langs || DEFAULT_LANGS;
|
53
|
+
highlighterPromise = createHighlighter({
|
54
|
+
themes: [themes.light, themes.dark],
|
55
|
+
langs,
|
56
|
+
}).then(highlighter => {
|
57
|
+
highlighterInstance = highlighter;
|
58
|
+
return highlighter;
|
59
|
+
});
|
60
|
+
}
|
61
|
+
return highlighterPromise;
|
62
|
+
}
|
63
|
+
export async function highlightCode({ code, lang = `text`, theme = `light`, showLineNumbers = false, highlightLines = [], diffLines, focusLines = [], showInvisibles = false, }) {
|
64
|
+
const highlighter = await getHighlighter();
|
65
|
+
const themes = {
|
66
|
+
light: DEFAULT_THEMES.light,
|
67
|
+
dark: DEFAULT_THEMES.dark,
|
68
|
+
};
|
69
|
+
const transformers = [];
|
70
|
+
// Add line numbers transformer if needed
|
71
|
+
if (showLineNumbers) {
|
72
|
+
// Custom line numbers will be handled in CSS
|
73
|
+
transformers.push({
|
74
|
+
name: `line-numbers`,
|
75
|
+
pre(node) {
|
76
|
+
node.properties[`data-line-numbers`] = `true`;
|
77
|
+
}
|
78
|
+
});
|
79
|
+
}
|
80
|
+
// Add highlight transformer
|
81
|
+
if (highlightLines.length > 0) {
|
82
|
+
transformers.push({
|
83
|
+
name: `highlight-lines`,
|
84
|
+
line(node, line) {
|
85
|
+
if (highlightLines.includes(line)) {
|
86
|
+
node.properties[`data-highlighted`] = `true`;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
});
|
90
|
+
}
|
91
|
+
// Add standard transformers
|
92
|
+
transformers.push(transformerNotationHighlight(), transformerNotationDiff(), transformerNotationFocus());
|
93
|
+
if (showInvisibles) {
|
94
|
+
transformers.push(transformerRenderWhitespace());
|
95
|
+
}
|
96
|
+
// Generate HTML with CSS variables for theme switching
|
97
|
+
const html = highlighter.codeToHtml(code, {
|
98
|
+
lang,
|
99
|
+
themes,
|
100
|
+
defaultColor: false,
|
101
|
+
transformers,
|
102
|
+
});
|
103
|
+
return html;
|
104
|
+
}
|
105
|
+
//# sourceMappingURL=shiki.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"shiki.js","sourceRoot":"","sources":["../../../src/lib/shiki/shiki.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
interface CodeBlockProps {
|
3
|
+
children: string;
|
4
|
+
language?: string;
|
5
|
+
className?: string;
|
6
|
+
showLineNumbers?: boolean;
|
7
|
+
highlightLines?: number[];
|
8
|
+
diffLines?: {
|
9
|
+
add: number[];
|
10
|
+
remove: number[];
|
11
|
+
};
|
12
|
+
focusLines?: number[];
|
13
|
+
showInvisibles?: boolean;
|
14
|
+
}
|
15
|
+
export declare const CodeBlock: React.FC<CodeBlockProps>;
|
16
|
+
export {};
|
17
|
+
//# sourceMappingURL=CodeBlock.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CodeBlock.d.ts","sourceRoot":"","sources":["../../../src/template/components/CodeBlock.tsx"],"names":[],"mappings":"AACA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAElD,UAAU,cAAc;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC/C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA0D9C,CAAA"}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import { highlightCode } from '#lib/shiki/index';
|
2
|
+
import React, { useEffect, useState } from 'react';
|
3
|
+
export const CodeBlock = ({ children, language = `text`, className = ``, showLineNumbers = false, highlightLines = [], diffLines, focusLines = [], showInvisibles = false, }) => {
|
4
|
+
const [html, setHtml] = useState(``);
|
5
|
+
const [isLoading, setIsLoading] = useState(true);
|
6
|
+
// TODO: Implement proper theme detection
|
7
|
+
// For now, we'll rely on CSS to handle theme switching
|
8
|
+
const theme = `light`; // Default to light theme
|
9
|
+
useEffect(() => {
|
10
|
+
const renderCode = async () => {
|
11
|
+
try {
|
12
|
+
const output = await highlightCode({
|
13
|
+
code: children,
|
14
|
+
lang: language,
|
15
|
+
theme,
|
16
|
+
showLineNumbers,
|
17
|
+
highlightLines,
|
18
|
+
diffLines,
|
19
|
+
focusLines,
|
20
|
+
showInvisibles,
|
21
|
+
});
|
22
|
+
setHtml(output);
|
23
|
+
}
|
24
|
+
catch (error) {
|
25
|
+
console.error(`Failed to highlight code:`, error);
|
26
|
+
// Fallback to plain text
|
27
|
+
setHtml(`<pre><code>${children}</code></pre>`);
|
28
|
+
}
|
29
|
+
finally {
|
30
|
+
setIsLoading(false);
|
31
|
+
}
|
32
|
+
};
|
33
|
+
renderCode();
|
34
|
+
}, [children, language, showLineNumbers, highlightLines, diffLines, focusLines, showInvisibles]);
|
35
|
+
if (isLoading) {
|
36
|
+
return (<pre className={className}>
|
37
|
+
<code>{children}</code>
|
38
|
+
</pre>);
|
39
|
+
}
|
40
|
+
return (<div className={`code-block ${className}`} dangerouslySetInnerHTML={{ __html: html }}/>);
|
41
|
+
};
|
42
|
+
//# sourceMappingURL=CodeBlock.jsx.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CodeBlock.jsx","sourceRoot":"","sources":["../../../src/template/components/CodeBlock.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAalD,MAAM,CAAC,MAAM,SAAS,GAA6B,CAAC,EAClD,QAAQ,EACR,QAAQ,GAAG,MAAM,EACjB,SAAS,GAAG,EAAE,EACd,eAAe,GAAG,KAAK,EACvB,cAAc,GAAG,EAAE,EACnB,SAAS,EACT,UAAU,GAAG,EAAE,EACf,cAAc,GAAG,KAAK,GACvB,EAAE,EAAE;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAA;IAC5C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAEhD,yCAAyC;IACzC,uDAAuD;IACvD,MAAM,KAAK,GAAG,OAAO,CAAA,CAAC,yBAAyB;IAE/C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;YAC5B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;oBACjC,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,QAAQ;oBACd,KAAK;oBACL,eAAe;oBACf,cAAc;oBACd,SAAS;oBACT,UAAU;oBACV,cAAc;iBACf,CAAC,CAAA;gBAEF,OAAO,CAAC,MAAM,CAAC,CAAA;YACjB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAA;gBACjD,yBAAyB;gBACzB,OAAO,CAAC,cAAc,QAAQ,eAAe,CAAC,CAAA;YAChD,CAAC;oBAAS,CAAC;gBACT,YAAY,CAAC,KAAK,CAAC,CAAA;YACrB,CAAC;QACH,CAAC,CAAA;QAED,UAAU,EAAE,CAAA;IACd,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC,CAAA;IAEhG,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CACL,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CACxB;QAAA,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CACxB;MAAA,EAAE,GAAG,CAAC,CACP,CAAA;IACH,CAAC;IAED,OAAO,CACL,CAAC,GAAG,CACF,SAAS,CAAC,CAAC,cAAc,SAAS,EAAE,CAAC,CACrC,uBAAuB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAC1C,CACH,CAAA;AACH,CAAC,CAAA"}
|
@@ -2,6 +2,7 @@
|
|
2
2
|
// But then, we won't get it from the client manifest. But we could get it from the server manifest. Should we do that?
|
3
3
|
// But then, that wouldn't work for SPA. Does that matter? Just put a conditional here e.g. if (import.meta.env.PROD) ...?
|
4
4
|
import '@radix-ui/themes/styles.css';
|
5
|
+
// import './styles/code-block.css' // TODO: Handle CSS in build process
|
5
6
|
import { ReactDomClient } from '#dep/react-dom-client/index';
|
6
7
|
import { StrictMode } from 'react';
|
7
8
|
import { createBrowserRouter, RouterProvider } from 'react-router';
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"entry.client.jsx","sourceRoot":"","sources":["../../src/template/entry.client.tsx"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,uHAAuH;AACvH,0HAA0H;AAC1H,OAAO,6BAA6B,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC,MAAM;AAEN,6CAA6C;AAE7C,+BAA+B;AAC/B,wCAAwC;AACxC,IAAI;AAEJ,MAAM;AAEN,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,EAAE;IACzC,aAAa,EAAE,MAAM,CAAC,2BAA2B;CAClD,CAAC,CAAA;AAEF,cAAc,CAAC,WAAW,CACxB,QAAQ,EACR,CACE,CAAC,UAAU,CACT;MAAA,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EACjC;IAAA,EAAE,UAAU,CAAC,CACd,CACF,CAAA"}
|
1
|
+
{"version":3,"file":"entry.client.jsx","sourceRoot":"","sources":["../../src/template/entry.client.tsx"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,uHAAuH;AACvH,0HAA0H;AAC1H,OAAO,6BAA6B,CAAA;AACpC,wEAAwE;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC,MAAM;AAEN,6CAA6C;AAE7C,+BAA+B;AAC/B,wCAAwC;AACxC,IAAI;AAEJ,MAAM;AAEN,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,EAAE;IACzC,aAAa,EAAE,MAAM,CAAC,2BAA2B;CAClD,CAAC,CAAA;AAEF,cAAc,CAAC,WAAW,CACxB,QAAQ,EACR,CACE,CAAC,UAAU,CACT;MAAA,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EACjC;IAAA,EAAE,UAAU,CAAC,CACd,CACF,CAAA"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AA8B1D,eAAO,MAAM,SAAS,mCA6BrB,CAAA;
|
1
|
+
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AA8B1D,eAAO,MAAM,SAAS,mCA6BrB,CAAA;AAwLD,eAAO,MAAM,IAAI;;;;CAIf,CAAA"}
|
@@ -78,6 +78,38 @@ const Layout = () => {
|
|
78
78
|
</Flex>);
|
79
79
|
return (<Theme asChild>
|
80
80
|
<Grid width={{ initial: 'var(--container-4)' }} areas="'header header header header header header header header' 'sidebar sidebar . content content content content content'" rows='min-content auto' columns='repeat(8, 1fr)' gapX='2' my='8' mx='auto'>
|
81
|
+
<style>{`
|
82
|
+
/* Shiki code blocks */
|
83
|
+
pre.shiki {
|
84
|
+
margin: 1rem 0;
|
85
|
+
padding: 1rem;
|
86
|
+
border-radius: 8px;
|
87
|
+
overflow-x: auto;
|
88
|
+
font-size: 14px;
|
89
|
+
line-height: 1.6;
|
90
|
+
background-color: #f6f8fa;
|
91
|
+
}
|
92
|
+
|
93
|
+
/* Light mode: use --shiki-light CSS variables from inline styles */
|
94
|
+
pre.shiki span {
|
95
|
+
color: var(--shiki-light);
|
96
|
+
}
|
97
|
+
|
98
|
+
/* Dark mode - Radix Themes uses [data-is-root-theme="dark"] */
|
99
|
+
[data-is-root-theme="dark"] pre.shiki {
|
100
|
+
background-color: #1a1b26;
|
101
|
+
}
|
102
|
+
|
103
|
+
[data-is-root-theme="dark"] pre.shiki span {
|
104
|
+
color: var(--shiki-dark);
|
105
|
+
}
|
106
|
+
|
107
|
+
pre.shiki code {
|
108
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
|
109
|
+
background: transparent;
|
110
|
+
display: block;
|
111
|
+
}
|
112
|
+
`}</style>
|
81
113
|
{header}
|
82
114
|
{isShowSidebar && (<Sidebar gridColumn='1 / 3' gridRow='2 / auto' data={sidebar.items}/>)}
|
83
115
|
<Box gridArea='content / content / auto / 8'>
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"root.jsx","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"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"}
|
1
|
+
{"version":3,"file":"root.jsx","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "polen",
|
3
|
-
"version": "0.9.0-next.
|
3
|
+
"version": "0.9.0-next.6",
|
4
4
|
"type": "module",
|
5
5
|
"description": "A framework for delightful GraphQL developer portals",
|
6
6
|
"author": {
|
@@ -84,6 +84,9 @@
|
|
84
84
|
"@radix-ui/themes": "^3.2.1",
|
85
85
|
"@rolldown/pluginutils": "1.0.0-beta.12",
|
86
86
|
"@rollup/pluginutils": "^5.1.4",
|
87
|
+
"@shikijs/rehype": "^3.6.0",
|
88
|
+
"@shikijs/transformers": "^3.6.0",
|
89
|
+
"@shikijs/twoslash": "^3.6.0",
|
87
90
|
"@swc/core": "^1.11.31",
|
88
91
|
"@types/jsesc": "^3.0.3",
|
89
92
|
"@vitejs/plugin-react": "^4.5.1",
|
@@ -105,16 +108,21 @@
|
|
105
108
|
"react": "^19.1.0",
|
106
109
|
"react-dom": "^19.1.0",
|
107
110
|
"react-router": "^7.6.2",
|
111
|
+
"rehype-stringify": "^10.0.1",
|
108
112
|
"remark": "^15.0.1",
|
109
113
|
"remark-gfm": "^4.0.1",
|
110
114
|
"remark-html": "^16.0.1",
|
115
|
+
"remark-parse": "^11.0.0",
|
116
|
+
"remark-rehype": "^11.1.2",
|
111
117
|
"resolve.imports": "^2.0.3",
|
112
118
|
"rolldown": "1.0.0-beta.12",
|
119
|
+
"shiki": "^3.6.0",
|
113
120
|
"source-map": "^0.7.4",
|
114
121
|
"superjson": "^2.2.2",
|
115
122
|
"tinyglobby": "^0.2.14",
|
116
123
|
"tsx": "^4.19.4",
|
117
124
|
"typescript": "^5.8.3",
|
125
|
+
"unified": "^11.0.5",
|
118
126
|
"vfile": "^6.0.3",
|
119
127
|
"vite": "npm:rolldown-vite@~6.3.18",
|
120
128
|
"vite-plugin-inspect": "^11.1.0",
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
2
|
+
import { parse } from './markdown.js'
|
3
|
+
|
4
|
+
describe(`markdown parser with syntax highlighting`, () => {
|
5
|
+
test(`parse highlights code blocks`, async () => {
|
6
|
+
const markdown = `
|
7
|
+
# Hello
|
8
|
+
|
9
|
+
\`\`\`javascript
|
10
|
+
const x = 42
|
11
|
+
console.log(x)
|
12
|
+
\`\`\`
|
13
|
+
`
|
14
|
+
const result = await parse(markdown)
|
15
|
+
|
16
|
+
expect(result).toContain(`<h1>Hello</h1>`)
|
17
|
+
expect(result).toContain(`<pre`)
|
18
|
+
expect(result).toContain(`shiki`)
|
19
|
+
expect(result).toContain(`console`)
|
20
|
+
expect(result).toContain(`42`)
|
21
|
+
})
|
22
|
+
|
23
|
+
// Note: parseSync cannot be used with async rehype plugins like Shiki
|
24
|
+
// This is a known limitation - syntax highlighting requires async processing
|
25
|
+
|
26
|
+
test(`parse supports GraphQL syntax`, async () => {
|
27
|
+
const markdown = `
|
28
|
+
\`\`\`graphql
|
29
|
+
type Query {
|
30
|
+
user(id: ID!): User
|
31
|
+
}
|
32
|
+
\`\`\`
|
33
|
+
`
|
34
|
+
const result = await parse(markdown)
|
35
|
+
|
36
|
+
expect(result).toContain(`type`)
|
37
|
+
expect(result).toContain(`Query`)
|
38
|
+
// Check that both ID and ! are present (they may be in separate spans)
|
39
|
+
expect(result).toContain(`> ID<`)
|
40
|
+
expect(result).toContain(`>!</`)
|
41
|
+
})
|
42
|
+
|
43
|
+
test(`parse handles inline code`, async () => {
|
44
|
+
const markdown = `This is \`inline code\` in a sentence.`
|
45
|
+
const result = await parse(markdown)
|
46
|
+
|
47
|
+
expect(result).toContain(`<code>inline code</code>`)
|
48
|
+
})
|
49
|
+
|
50
|
+
test(`parse supports GitHub Flavored Markdown`, async () => {
|
51
|
+
const markdown = `
|
52
|
+
| Column 1 | Column 2 |
|
53
|
+
|----------|----------|
|
54
|
+
| Cell 1 | Cell 2 |
|
55
|
+
|
56
|
+
- [x] Task 1
|
57
|
+
- [ ] Task 2
|
58
|
+
`
|
59
|
+
const result = await parse(markdown)
|
60
|
+
|
61
|
+
expect(result).toContain(`<table>`)
|
62
|
+
expect(result).toContain(`<input`)
|
63
|
+
expect(result).toContain(`checked`)
|
64
|
+
})
|
65
|
+
|
66
|
+
test(`parse handles code blocks without language`, async () => {
|
67
|
+
const markdown = `
|
68
|
+
\`\`\`
|
69
|
+
plain text without language
|
70
|
+
\`\`\`
|
71
|
+
`
|
72
|
+
const result = await parse(markdown)
|
73
|
+
|
74
|
+
expect(result).toContain(`<pre`)
|
75
|
+
expect(result).toContain(`plain text without language`)
|
76
|
+
})
|
77
|
+
|
78
|
+
test(`parse preserves theme CSS variables`, async () => {
|
79
|
+
const markdown = `
|
80
|
+
\`\`\`javascript
|
81
|
+
const theme = "light"
|
82
|
+
\`\`\`
|
83
|
+
`
|
84
|
+
const result = await parse(markdown)
|
85
|
+
|
86
|
+
expect(result).toContain(`--shiki-light`)
|
87
|
+
expect(result).toContain(`--shiki-dark`)
|
88
|
+
})
|
89
|
+
})
|
@@ -1,21 +1,43 @@
|
|
1
|
-
import
|
2
|
-
import
|
3
|
-
import
|
1
|
+
import { unified } from 'unified'
|
2
|
+
import remarkParse from 'remark-parse'
|
3
|
+
import remarkGfm from 'remark-gfm'
|
4
|
+
import remarkRehype from 'remark-rehype'
|
5
|
+
import rehypeShiki from '@shikijs/rehype'
|
6
|
+
import rehypeStringify from 'rehype-stringify'
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
.use(
|
9
|
-
.
|
8
|
+
// Create a processor with Shiki for syntax highlighting (async only)
|
9
|
+
const createProcessorWithShiki = () => {
|
10
|
+
return unified()
|
11
|
+
.use(remarkParse)
|
12
|
+
.use(remarkGfm)
|
13
|
+
.use(remarkRehype)
|
14
|
+
.use(rehypeShiki, {
|
15
|
+
themes: {
|
16
|
+
light: `github-light`,
|
17
|
+
dark: `tokyo-night`,
|
18
|
+
},
|
19
|
+
defaultColor: false,
|
20
|
+
cssVariablePrefix: `--shiki-`,
|
21
|
+
})
|
22
|
+
.use(rehypeStringify)
|
23
|
+
}
|
24
|
+
|
25
|
+
// Create a processor without syntax highlighting for sync processing
|
26
|
+
const createProcessorSync = () => {
|
27
|
+
return unified()
|
28
|
+
.use(remarkParse)
|
29
|
+
.use(remarkGfm)
|
30
|
+
.use(remarkRehype)
|
31
|
+
.use(rehypeStringify)
|
32
|
+
}
|
10
33
|
|
34
|
+
export const parse = async (content: string): Promise<string> => {
|
35
|
+
const result = await createProcessorWithShiki().process(content)
|
11
36
|
return String(result)
|
12
37
|
}
|
13
38
|
|
14
39
|
export const parseSync = (content: string): string => {
|
15
|
-
|
16
|
-
|
17
|
-
.use(RemarkHtml)
|
18
|
-
.processSync(content)
|
19
|
-
|
40
|
+
// Note: Syntax highlighting is not available in sync mode due to @shikijs/rehype being async-only
|
41
|
+
const result = createProcessorSync().processSync(content)
|
20
42
|
return String(result)
|
21
43
|
}
|
@@ -10,6 +10,7 @@ import { superjson } from '#singletons/superjson'
|
|
10
10
|
import mdx from '@mdx-js/rollup'
|
11
11
|
import { Path, Str } from '@wollybeard/kit'
|
12
12
|
import remarkGfm from 'remark-gfm'
|
13
|
+
import rehypeShiki from '@shikijs/rehype'
|
13
14
|
|
14
15
|
const _debug = debug.sub(`vite-plugin-pages`)
|
15
16
|
|
@@ -123,6 +124,22 @@ export const Pages = ({
|
|
123
124
|
...mdx({
|
124
125
|
jsxImportSource: `polen/react`,
|
125
126
|
remarkPlugins: [remarkGfm],
|
127
|
+
rehypePlugins: [
|
128
|
+
[
|
129
|
+
rehypeShiki,
|
130
|
+
{
|
131
|
+
themes: {
|
132
|
+
light: `github-light`,
|
133
|
+
dark: `tokyo-night`,
|
134
|
+
},
|
135
|
+
defaultColor: false,
|
136
|
+
cssVariablePrefix: `--shiki-`,
|
137
|
+
transformers: [
|
138
|
+
// Line numbers will be handled via CSS
|
139
|
+
],
|
140
|
+
},
|
141
|
+
],
|
142
|
+
],
|
126
143
|
}),
|
127
144
|
},
|
128
145
|
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './shiki.ts'
|
@@ -0,0 +1,107 @@
|
|
1
|
+
import { expect, test } from 'vitest'
|
2
|
+
import { getHighlighter, highlightCode } from './shiki.js'
|
3
|
+
|
4
|
+
test(`getHighlighter returns singleton instance`, async () => {
|
5
|
+
const highlighter1 = await getHighlighter()
|
6
|
+
const highlighter2 = await getHighlighter()
|
7
|
+
|
8
|
+
expect(highlighter1).toBe(highlighter2)
|
9
|
+
})
|
10
|
+
|
11
|
+
test(`highlightCode generates HTML with syntax highlighting`, async () => {
|
12
|
+
const code = `const hello = "world"`
|
13
|
+
const result = await highlightCode({
|
14
|
+
code,
|
15
|
+
lang: `javascript`,
|
16
|
+
theme: `light`,
|
17
|
+
})
|
18
|
+
|
19
|
+
expect(result).toContain(`<pre`)
|
20
|
+
expect(result).toContain(`shiki`)
|
21
|
+
expect(result).toContain(`hello`)
|
22
|
+
expect(result).toContain(`world`)
|
23
|
+
})
|
24
|
+
|
25
|
+
test(`highlightCode supports TypeScript`, async () => {
|
26
|
+
const code = `interface User { name: string }`
|
27
|
+
const result = await highlightCode({
|
28
|
+
code,
|
29
|
+
lang: `typescript`,
|
30
|
+
theme: `light`,
|
31
|
+
})
|
32
|
+
|
33
|
+
expect(result).toContain(`interface`)
|
34
|
+
expect(result).toContain(`User`)
|
35
|
+
expect(result).toContain(`string`)
|
36
|
+
})
|
37
|
+
|
38
|
+
test(`highlightCode supports GraphQL`, async () => {
|
39
|
+
const code = `type Query { user: User }`
|
40
|
+
const result = await highlightCode({
|
41
|
+
code,
|
42
|
+
lang: `graphql`,
|
43
|
+
theme: `light`,
|
44
|
+
})
|
45
|
+
|
46
|
+
expect(result).toContain(`type`)
|
47
|
+
expect(result).toContain(`Query`)
|
48
|
+
expect(result).toContain(`User`)
|
49
|
+
})
|
50
|
+
|
51
|
+
test(`highlightCode handles unknown language gracefully`, async () => {
|
52
|
+
const code = `some random text`
|
53
|
+
// Use 'text' as fallback for unknown languages
|
54
|
+
const result = await highlightCode({
|
55
|
+
code,
|
56
|
+
lang: `text`,
|
57
|
+
theme: `light`,
|
58
|
+
})
|
59
|
+
|
60
|
+
// Should still return highlighted HTML
|
61
|
+
expect(result).toContain(`<pre`)
|
62
|
+
expect(result).toContain(`some random text`)
|
63
|
+
})
|
64
|
+
|
65
|
+
test(`highlightCode applies line numbers when requested`, async () => {
|
66
|
+
const code = `line 1\nline 2\nline 3`
|
67
|
+
const result = await highlightCode({
|
68
|
+
code,
|
69
|
+
lang: `text`,
|
70
|
+
theme: `light`,
|
71
|
+
showLineNumbers: true,
|
72
|
+
})
|
73
|
+
|
74
|
+
expect(result).toContain(`data-line-numbers="true"`)
|
75
|
+
})
|
76
|
+
|
77
|
+
test(`highlightCode applies line highlighting`, async () => {
|
78
|
+
const code = `line 1\nline 2\nline 3`
|
79
|
+
const result = await highlightCode({
|
80
|
+
code,
|
81
|
+
lang: `text`,
|
82
|
+
theme: `light`,
|
83
|
+
highlightLines: [2],
|
84
|
+
})
|
85
|
+
|
86
|
+
expect(result).toContain(`data-highlighted="true"`)
|
87
|
+
})
|
88
|
+
|
89
|
+
test(`highlightCode supports both light and dark themes`, async () => {
|
90
|
+
const code = `const x = 1`
|
91
|
+
|
92
|
+
const lightResult = await highlightCode({
|
93
|
+
code,
|
94
|
+
lang: `javascript`,
|
95
|
+
theme: `light`,
|
96
|
+
})
|
97
|
+
|
98
|
+
const darkResult = await highlightCode({
|
99
|
+
code,
|
100
|
+
lang: `javascript`,
|
101
|
+
theme: `dark`,
|
102
|
+
})
|
103
|
+
|
104
|
+
// Both should contain theme CSS variables
|
105
|
+
expect(lightResult).toContain(`--shiki-light`)
|
106
|
+
expect(darkResult).toContain(`--shiki-dark`)
|
107
|
+
})
|
@@ -0,0 +1,161 @@
|
|
1
|
+
import { createHighlighter, type Highlighter, type BundledTheme, type BundledLanguage } from 'shiki'
|
2
|
+
import {
|
3
|
+
transformerNotationHighlight,
|
4
|
+
transformerNotationDiff,
|
5
|
+
transformerNotationFocus,
|
6
|
+
transformerRenderWhitespace,
|
7
|
+
} from '@shikijs/transformers'
|
8
|
+
|
9
|
+
export interface ShikiOptions {
|
10
|
+
themes?: {
|
11
|
+
light: BundledTheme
|
12
|
+
dark: BundledTheme
|
13
|
+
}
|
14
|
+
langs?: BundledLanguage[]
|
15
|
+
defaultTheme?: 'light' | 'dark'
|
16
|
+
}
|
17
|
+
|
18
|
+
const DEFAULT_THEMES = {
|
19
|
+
light: `github-light` as BundledTheme,
|
20
|
+
dark: `tokyo-night` as BundledTheme,
|
21
|
+
}
|
22
|
+
|
23
|
+
const DEFAULT_LANGS: BundledLanguage[] = [
|
24
|
+
`typescript`,
|
25
|
+
`javascript`,
|
26
|
+
`jsx`,
|
27
|
+
`tsx`,
|
28
|
+
`graphql`,
|
29
|
+
`json`,
|
30
|
+
`yaml`,
|
31
|
+
`markdown`,
|
32
|
+
`bash`,
|
33
|
+
`shell`,
|
34
|
+
`css`,
|
35
|
+
`html`,
|
36
|
+
`sql`,
|
37
|
+
`python`,
|
38
|
+
`rust`,
|
39
|
+
`go`,
|
40
|
+
`java`,
|
41
|
+
`csharp`,
|
42
|
+
`php`,
|
43
|
+
`ruby`,
|
44
|
+
`swift`,
|
45
|
+
`kotlin`,
|
46
|
+
`scala`,
|
47
|
+
`r`,
|
48
|
+
`matlab`,
|
49
|
+
`latex`,
|
50
|
+
`dockerfile`,
|
51
|
+
`makefile`,
|
52
|
+
`nginx`,
|
53
|
+
`apache`,
|
54
|
+
`xml`,
|
55
|
+
`toml`,
|
56
|
+
`ini`,
|
57
|
+
`diff`,
|
58
|
+
]
|
59
|
+
|
60
|
+
// Singleton highlighter instance
|
61
|
+
let highlighterInstance: Highlighter | null = null
|
62
|
+
let highlighterPromise: Promise<Highlighter> | null = null
|
63
|
+
|
64
|
+
export async function getHighlighter(options: ShikiOptions = {}): Promise<Highlighter> {
|
65
|
+
if (highlighterInstance) {
|
66
|
+
return highlighterInstance
|
67
|
+
}
|
68
|
+
|
69
|
+
if (!highlighterPromise) {
|
70
|
+
const themes = options.themes || DEFAULT_THEMES
|
71
|
+
const langs = options.langs || DEFAULT_LANGS
|
72
|
+
|
73
|
+
highlighterPromise = createHighlighter({
|
74
|
+
themes: [themes.light, themes.dark],
|
75
|
+
langs,
|
76
|
+
}).then(highlighter => {
|
77
|
+
highlighterInstance = highlighter
|
78
|
+
return highlighter
|
79
|
+
})
|
80
|
+
}
|
81
|
+
|
82
|
+
return highlighterPromise
|
83
|
+
}
|
84
|
+
|
85
|
+
export interface CodeHighlightOptions {
|
86
|
+
code: string
|
87
|
+
lang?: string
|
88
|
+
theme?: 'light' | 'dark'
|
89
|
+
showLineNumbers?: boolean
|
90
|
+
highlightLines?: number[]
|
91
|
+
diffLines?: { add: number[], remove: number[] }
|
92
|
+
focusLines?: number[]
|
93
|
+
showInvisibles?: boolean
|
94
|
+
}
|
95
|
+
|
96
|
+
export async function highlightCode({
|
97
|
+
code,
|
98
|
+
lang = `text`,
|
99
|
+
theme = `light`,
|
100
|
+
showLineNumbers = false,
|
101
|
+
highlightLines = [],
|
102
|
+
diffLines,
|
103
|
+
focusLines = [],
|
104
|
+
showInvisibles = false,
|
105
|
+
}: CodeHighlightOptions): Promise<string> {
|
106
|
+
const highlighter = await getHighlighter()
|
107
|
+
|
108
|
+
const themes = {
|
109
|
+
light: DEFAULT_THEMES.light,
|
110
|
+
dark: DEFAULT_THEMES.dark,
|
111
|
+
}
|
112
|
+
|
113
|
+
const transformers = []
|
114
|
+
|
115
|
+
// Add line numbers transformer if needed
|
116
|
+
if (showLineNumbers) {
|
117
|
+
// Custom line numbers will be handled in CSS
|
118
|
+
transformers.push({
|
119
|
+
name: `line-numbers`,
|
120
|
+
pre(node: any) {
|
121
|
+
node.properties[`data-line-numbers`] = `true`
|
122
|
+
}
|
123
|
+
})
|
124
|
+
}
|
125
|
+
|
126
|
+
// Add highlight transformer
|
127
|
+
if (highlightLines.length > 0) {
|
128
|
+
transformers.push({
|
129
|
+
name: `highlight-lines`,
|
130
|
+
line(node: any, line: number) {
|
131
|
+
if (highlightLines.includes(line)) {
|
132
|
+
node.properties[`data-highlighted`] = `true`
|
133
|
+
}
|
134
|
+
}
|
135
|
+
})
|
136
|
+
}
|
137
|
+
|
138
|
+
// Add standard transformers
|
139
|
+
transformers.push(
|
140
|
+
transformerNotationHighlight(),
|
141
|
+
transformerNotationDiff(),
|
142
|
+
transformerNotationFocus(),
|
143
|
+
)
|
144
|
+
|
145
|
+
if (showInvisibles) {
|
146
|
+
transformers.push(transformerRenderWhitespace())
|
147
|
+
}
|
148
|
+
|
149
|
+
// Generate HTML with CSS variables for theme switching
|
150
|
+
const html = highlighter.codeToHtml(code, {
|
151
|
+
lang,
|
152
|
+
themes,
|
153
|
+
defaultColor: false,
|
154
|
+
transformers,
|
155
|
+
})
|
156
|
+
|
157
|
+
return html
|
158
|
+
}
|
159
|
+
|
160
|
+
// Re-export types
|
161
|
+
export type { Highlighter, BundledTheme, BundledLanguage } from 'shiki'
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import { highlightCode } from '#lib/shiki/index'
|
2
|
+
import React, { useEffect, useState } from 'react'
|
3
|
+
|
4
|
+
interface CodeBlockProps {
|
5
|
+
children: string
|
6
|
+
language?: string
|
7
|
+
className?: string
|
8
|
+
showLineNumbers?: boolean
|
9
|
+
highlightLines?: number[]
|
10
|
+
diffLines?: { add: number[]; remove: number[] }
|
11
|
+
focusLines?: number[]
|
12
|
+
showInvisibles?: boolean
|
13
|
+
}
|
14
|
+
|
15
|
+
export const CodeBlock: React.FC<CodeBlockProps> = ({
|
16
|
+
children,
|
17
|
+
language = `text`,
|
18
|
+
className = ``,
|
19
|
+
showLineNumbers = false,
|
20
|
+
highlightLines = [],
|
21
|
+
diffLines,
|
22
|
+
focusLines = [],
|
23
|
+
showInvisibles = false,
|
24
|
+
}) => {
|
25
|
+
const [html, setHtml] = useState<string>(``)
|
26
|
+
const [isLoading, setIsLoading] = useState(true)
|
27
|
+
|
28
|
+
// TODO: Implement proper theme detection
|
29
|
+
// For now, we'll rely on CSS to handle theme switching
|
30
|
+
const theme = `light` // Default to light theme
|
31
|
+
|
32
|
+
useEffect(() => {
|
33
|
+
const renderCode = async () => {
|
34
|
+
try {
|
35
|
+
const output = await highlightCode({
|
36
|
+
code: children,
|
37
|
+
lang: language,
|
38
|
+
theme,
|
39
|
+
showLineNumbers,
|
40
|
+
highlightLines,
|
41
|
+
diffLines,
|
42
|
+
focusLines,
|
43
|
+
showInvisibles,
|
44
|
+
})
|
45
|
+
|
46
|
+
setHtml(output)
|
47
|
+
} catch (error) {
|
48
|
+
console.error(`Failed to highlight code:`, error)
|
49
|
+
// Fallback to plain text
|
50
|
+
setHtml(`<pre><code>${children}</code></pre>`)
|
51
|
+
} finally {
|
52
|
+
setIsLoading(false)
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
renderCode()
|
57
|
+
}, [children, language, showLineNumbers, highlightLines, diffLines, focusLines, showInvisibles])
|
58
|
+
|
59
|
+
if (isLoading) {
|
60
|
+
return (
|
61
|
+
<pre className={className}>
|
62
|
+
<code>{children}</code>
|
63
|
+
</pre>
|
64
|
+
)
|
65
|
+
}
|
66
|
+
|
67
|
+
return (
|
68
|
+
<div
|
69
|
+
className={`code-block ${className}`}
|
70
|
+
dangerouslySetInnerHTML={{ __html: html }}
|
71
|
+
/>
|
72
|
+
)
|
73
|
+
}
|
@@ -2,6 +2,7 @@
|
|
2
2
|
// But then, we won't get it from the client manifest. But we could get it from the server manifest. Should we do that?
|
3
3
|
// But then, that wouldn't work for SPA. Does that matter? Just put a conditional here e.g. if (import.meta.env.PROD) ...?
|
4
4
|
import '@radix-ui/themes/styles.css'
|
5
|
+
// import './styles/code-block.css' // TODO: Handle CSS in build process
|
5
6
|
import { ReactDomClient } from '#dep/react-dom-client/index'
|
6
7
|
import { StrictMode } from 'react'
|
7
8
|
import { createBrowserRouter, RouterProvider } from 'react-router'
|
@@ -120,6 +120,38 @@ const Layout = () => {
|
|
120
120
|
my='8'
|
121
121
|
mx='auto'
|
122
122
|
>
|
123
|
+
<style>{`
|
124
|
+
/* Shiki code blocks */
|
125
|
+
pre.shiki {
|
126
|
+
margin: 1rem 0;
|
127
|
+
padding: 1rem;
|
128
|
+
border-radius: 8px;
|
129
|
+
overflow-x: auto;
|
130
|
+
font-size: 14px;
|
131
|
+
line-height: 1.6;
|
132
|
+
background-color: #f6f8fa;
|
133
|
+
}
|
134
|
+
|
135
|
+
/* Light mode: use --shiki-light CSS variables from inline styles */
|
136
|
+
pre.shiki span {
|
137
|
+
color: var(--shiki-light);
|
138
|
+
}
|
139
|
+
|
140
|
+
/* Dark mode - Radix Themes uses [data-is-root-theme="dark"] */
|
141
|
+
[data-is-root-theme="dark"] pre.shiki {
|
142
|
+
background-color: #1a1b26;
|
143
|
+
}
|
144
|
+
|
145
|
+
[data-is-root-theme="dark"] pre.shiki span {
|
146
|
+
color: var(--shiki-dark);
|
147
|
+
}
|
148
|
+
|
149
|
+
pre.shiki code {
|
150
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
|
151
|
+
background: transparent;
|
152
|
+
display: block;
|
153
|
+
}
|
154
|
+
`}</style>
|
123
155
|
{header}
|
124
156
|
{isShowSidebar && (
|
125
157
|
<Sidebar
|
@@ -0,0 +1,186 @@
|
|
1
|
+
/* Code Block Styles */
|
2
|
+
|
3
|
+
/* Base code block container */
|
4
|
+
.code-block {
|
5
|
+
position: relative;
|
6
|
+
margin: 1rem 0;
|
7
|
+
border-radius: 8px;
|
8
|
+
overflow: hidden;
|
9
|
+
font-size: 14px;
|
10
|
+
line-height: 1.6;
|
11
|
+
}
|
12
|
+
|
13
|
+
.code-block pre {
|
14
|
+
margin: 0;
|
15
|
+
padding: 1rem;
|
16
|
+
overflow-x: auto;
|
17
|
+
background: inherit;
|
18
|
+
}
|
19
|
+
|
20
|
+
.code-block code {
|
21
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
|
22
|
+
font-variant-ligatures: contextual;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* Shiki theme switching with CSS variables */
|
26
|
+
/* Default to light theme */
|
27
|
+
:root {
|
28
|
+
color-scheme: light;
|
29
|
+
}
|
30
|
+
|
31
|
+
/* When dark mode is active */
|
32
|
+
.dark {
|
33
|
+
color-scheme: dark;
|
34
|
+
}
|
35
|
+
|
36
|
+
/* Shiki code blocks */
|
37
|
+
pre.shiki {
|
38
|
+
margin: 1rem 0;
|
39
|
+
padding: 1rem;
|
40
|
+
border-radius: 8px;
|
41
|
+
overflow-x: auto;
|
42
|
+
font-size: 14px;
|
43
|
+
line-height: 1.6;
|
44
|
+
}
|
45
|
+
|
46
|
+
pre.shiki code {
|
47
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
|
48
|
+
font-variant-ligatures: contextual;
|
49
|
+
}
|
50
|
+
|
51
|
+
/* Line numbers */
|
52
|
+
.code-block[data-line-numbers="true"] pre {
|
53
|
+
padding-left: 3.5rem;
|
54
|
+
position: relative;
|
55
|
+
}
|
56
|
+
|
57
|
+
.code-block[data-line-numbers="true"] .line {
|
58
|
+
position: relative;
|
59
|
+
}
|
60
|
+
|
61
|
+
.code-block[data-line-numbers="true"] .line::before {
|
62
|
+
content: attr(data-line);
|
63
|
+
position: absolute;
|
64
|
+
left: -3rem;
|
65
|
+
width: 2.5rem;
|
66
|
+
text-align: right;
|
67
|
+
color: var(--gray-a6);
|
68
|
+
user-select: none;
|
69
|
+
}
|
70
|
+
|
71
|
+
/* Line highlighting */
|
72
|
+
.code-block .line[data-highlighted="true"] {
|
73
|
+
background-color: var(--amber-a3);
|
74
|
+
display: block;
|
75
|
+
margin: 0 -1rem;
|
76
|
+
padding: 0 1rem;
|
77
|
+
}
|
78
|
+
|
79
|
+
/* Diff lines */
|
80
|
+
.code-block .line[data-diff="+"] {
|
81
|
+
background-color: var(--green-a3);
|
82
|
+
display: block;
|
83
|
+
margin: 0 -1rem;
|
84
|
+
padding: 0 1rem;
|
85
|
+
}
|
86
|
+
|
87
|
+
.code-block .line[data-diff="-"] {
|
88
|
+
background-color: var(--red-a3);
|
89
|
+
display: block;
|
90
|
+
margin: 0 -1rem;
|
91
|
+
padding: 0 1rem;
|
92
|
+
}
|
93
|
+
|
94
|
+
.code-block .line[data-diff="+"]::before {
|
95
|
+
content: "+ ";
|
96
|
+
color: var(--green-11);
|
97
|
+
font-weight: bold;
|
98
|
+
}
|
99
|
+
|
100
|
+
.code-block .line[data-diff="-"]::before {
|
101
|
+
content: "- ";
|
102
|
+
color: var(--red-11);
|
103
|
+
font-weight: bold;
|
104
|
+
}
|
105
|
+
|
106
|
+
/* Focus lines */
|
107
|
+
.code-block .line:not([data-focus="true"]) {
|
108
|
+
opacity: 0.5;
|
109
|
+
filter: grayscale(100%);
|
110
|
+
transition: opacity 0.2s, filter 0.2s;
|
111
|
+
}
|
112
|
+
|
113
|
+
.code-block:hover .line:not([data-focus="true"]) {
|
114
|
+
opacity: 0.8;
|
115
|
+
filter: grayscale(0%);
|
116
|
+
}
|
117
|
+
|
118
|
+
/* Copy button */
|
119
|
+
.code-block-copy {
|
120
|
+
position: absolute;
|
121
|
+
top: 0.5rem;
|
122
|
+
right: 0.5rem;
|
123
|
+
padding: 0.25rem 0.5rem;
|
124
|
+
border-radius: 4px;
|
125
|
+
background: var(--gray-a3);
|
126
|
+
color: var(--gray-12);
|
127
|
+
border: 1px solid var(--gray-a5);
|
128
|
+
cursor: pointer;
|
129
|
+
font-size: 12px;
|
130
|
+
transition: all 0.2s;
|
131
|
+
}
|
132
|
+
|
133
|
+
.code-block-copy:hover {
|
134
|
+
background: var(--gray-a4);
|
135
|
+
border-color: var(--gray-a6);
|
136
|
+
}
|
137
|
+
|
138
|
+
.code-block-copy.copied {
|
139
|
+
background: var(--green-a3);
|
140
|
+
border-color: var(--green-a5);
|
141
|
+
color: var(--green-11);
|
142
|
+
}
|
143
|
+
|
144
|
+
/* Language badge */
|
145
|
+
.code-block-lang {
|
146
|
+
position: absolute;
|
147
|
+
top: 0;
|
148
|
+
right: 0;
|
149
|
+
padding: 0.25rem 0.75rem;
|
150
|
+
background: var(--gray-a3);
|
151
|
+
color: var(--gray-11);
|
152
|
+
font-size: 12px;
|
153
|
+
font-weight: 500;
|
154
|
+
border-bottom-left-radius: 4px;
|
155
|
+
user-select: none;
|
156
|
+
}
|
157
|
+
|
158
|
+
/* Scrollbar styling */
|
159
|
+
.code-block pre::-webkit-scrollbar {
|
160
|
+
height: 8px;
|
161
|
+
width: 8px;
|
162
|
+
}
|
163
|
+
|
164
|
+
.code-block pre::-webkit-scrollbar-track {
|
165
|
+
background: var(--gray-a3);
|
166
|
+
border-radius: 4px;
|
167
|
+
}
|
168
|
+
|
169
|
+
.code-block pre::-webkit-scrollbar-thumb {
|
170
|
+
background: var(--gray-a6);
|
171
|
+
border-radius: 4px;
|
172
|
+
}
|
173
|
+
|
174
|
+
.code-block pre::-webkit-scrollbar-thumb:hover {
|
175
|
+
background: var(--gray-a7);
|
176
|
+
}
|
177
|
+
|
178
|
+
/* Inline code */
|
179
|
+
code:not(.code-block code) {
|
180
|
+
padding: 0.2em 0.4em;
|
181
|
+
margin: 0;
|
182
|
+
font-size: 0.85em;
|
183
|
+
background-color: var(--gray-a3);
|
184
|
+
border-radius: 4px;
|
185
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
|
186
|
+
}
|