@refrakt-md/highlight 0.3.0
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/dist/highlight.d.ts +20 -0
- package/dist/highlight.d.ts.map +1 -0
- package/dist/highlight.js +84 -0
- package/dist/highlight.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/langs/markdoc.d.ts +11 -0
- package/dist/langs/markdoc.d.ts.map +1 -0
- package/dist/langs/markdoc.js +61 -0
- package/dist/langs/markdoc.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { LanguageRegistration } from 'shiki';
|
|
2
|
+
import type { RendererNode } from '@refrakt-md/types';
|
|
3
|
+
export interface HighlightOptions {
|
|
4
|
+
/** Languages to pre-load when using the default Shiki highlighter.
|
|
5
|
+
* Accepts bundled language names or custom LanguageRegistration objects. */
|
|
6
|
+
langs?: (string | LanguageRegistration)[];
|
|
7
|
+
/** Custom highlight function. Receives raw code + language, returns HTML string.
|
|
8
|
+
* Default: Shiki with css-variables theme. */
|
|
9
|
+
highlight?: (code: string, lang: string) => string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create a syntax highlight transform that walks the serialized tree,
|
|
13
|
+
* finds elements with `data-language` + text children, highlights them,
|
|
14
|
+
* and sets `data-codeblock: true` for raw HTML injection by the Renderer.
|
|
15
|
+
*
|
|
16
|
+
* Uses Shiki with a CSS variables theme by default. Pass a custom
|
|
17
|
+
* `highlight` function to use a different highlighter.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createHighlightTransform(options?: HighlightOptions): Promise<(tree: RendererNode) => RendererNode>;
|
|
20
|
+
//# sourceMappingURL=highlight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.d.ts","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,mBAAmB,CAAC;AAKrE,MAAM,WAAW,gBAAgB;IAChC;iFAC6E;IAC7E,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,oBAAoB,CAAC,EAAE,CAAC;IAC1C;mDAC+C;IAC/C,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACnD;AAUD;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAAC,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC,CAmB/C"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createHighlighter, createCssVariablesTheme } from 'shiki';
|
|
2
|
+
import { isTag } from '@refrakt-md/transform';
|
|
3
|
+
import { markdocLanguage } from './langs/markdoc.js';
|
|
4
|
+
const cssVarsTheme = createCssVariablesTheme();
|
|
5
|
+
const DEFAULT_LANGS = [
|
|
6
|
+
'javascript', 'typescript', 'html', 'css', 'json', 'shell',
|
|
7
|
+
'python', 'ruby', 'go', 'rust', 'java', 'c', 'cpp',
|
|
8
|
+
'markdown', 'yaml', 'toml', 'sql', 'graphql', 'svelte',
|
|
9
|
+
'jsx', 'tsx', 'diff', 'xml',
|
|
10
|
+
markdocLanguage,
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* Create a syntax highlight transform that walks the serialized tree,
|
|
14
|
+
* finds elements with `data-language` + text children, highlights them,
|
|
15
|
+
* and sets `data-codeblock: true` for raw HTML injection by the Renderer.
|
|
16
|
+
*
|
|
17
|
+
* Uses Shiki with a CSS variables theme by default. Pass a custom
|
|
18
|
+
* `highlight` function to use a different highlighter.
|
|
19
|
+
*/
|
|
20
|
+
export async function createHighlightTransform(options = {}) {
|
|
21
|
+
const { langs = DEFAULT_LANGS, highlight: customHighlight } = options;
|
|
22
|
+
let highlightFn;
|
|
23
|
+
if (customHighlight) {
|
|
24
|
+
highlightFn = customHighlight;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const highlighter = await createHighlighter({
|
|
28
|
+
themes: [cssVarsTheme],
|
|
29
|
+
langs,
|
|
30
|
+
});
|
|
31
|
+
highlightFn = (code, lang) => {
|
|
32
|
+
const html = highlighter.codeToHtml(code, { lang, theme: 'css-variables' });
|
|
33
|
+
return extractInnerHtml(html);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return (tree) => walk(tree, highlightFn);
|
|
37
|
+
}
|
|
38
|
+
/** Walk the serialized tree, highlighting elements with `data-language`. */
|
|
39
|
+
function walk(node, highlightFn) {
|
|
40
|
+
if (node === null || node === undefined)
|
|
41
|
+
return node;
|
|
42
|
+
if (typeof node === 'string' || typeof node === 'number')
|
|
43
|
+
return node;
|
|
44
|
+
if (!isTag(node))
|
|
45
|
+
return node;
|
|
46
|
+
const lang = node.attributes?.['data-language'];
|
|
47
|
+
if (lang && hasTextChildren(node)) {
|
|
48
|
+
return highlightNode(node, lang, highlightFn);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
...node,
|
|
52
|
+
children: node.children.map(c => walk(c, highlightFn)),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function hasTextChildren(node) {
|
|
56
|
+
return node.children.some(c => typeof c === 'string');
|
|
57
|
+
}
|
|
58
|
+
function highlightNode(node, lang, highlightFn) {
|
|
59
|
+
const text = node.children
|
|
60
|
+
.filter((c) => typeof c === 'string')
|
|
61
|
+
.join('');
|
|
62
|
+
try {
|
|
63
|
+
const html = highlightFn(text, lang);
|
|
64
|
+
return {
|
|
65
|
+
...node,
|
|
66
|
+
attributes: { ...node.attributes, 'data-codeblock': true },
|
|
67
|
+
children: [html],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Unknown language or highlight failure — leave text unchanged
|
|
72
|
+
return node;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Strip Shiki's <pre><code> wrapper to get just the highlighted spans. */
|
|
76
|
+
function extractInnerHtml(html) {
|
|
77
|
+
const codeStart = html.indexOf('<code>');
|
|
78
|
+
const codeEnd = html.lastIndexOf('</code>');
|
|
79
|
+
if (codeStart !== -1 && codeEnd !== -1) {
|
|
80
|
+
return html.slice(codeStart + '<code>'.length, codeEnd);
|
|
81
|
+
}
|
|
82
|
+
return html;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=highlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.js","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LanguageRegistration } from 'shiki';
|
|
2
|
+
/**
|
|
3
|
+
* TextMate grammar for Markdoc syntax.
|
|
4
|
+
*
|
|
5
|
+
* Highlights `{% tag %}` blocks with rune names, attributes, string values,
|
|
6
|
+
* numbers, and booleans. Markdown is the base language.
|
|
7
|
+
*
|
|
8
|
+
* Reusable by the VS Code extension (Phase 9a).
|
|
9
|
+
*/
|
|
10
|
+
export declare const markdocLanguage: LanguageRegistration;
|
|
11
|
+
//# sourceMappingURL=markdoc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdoc.d.ts","sourceRoot":"","sources":["../../src/langs/markdoc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,oBAmD7B,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TextMate grammar for Markdoc syntax.
|
|
3
|
+
*
|
|
4
|
+
* Highlights `{% tag %}` blocks with rune names, attributes, string values,
|
|
5
|
+
* numbers, and booleans. Markdown is the base language.
|
|
6
|
+
*
|
|
7
|
+
* Reusable by the VS Code extension (Phase 9a).
|
|
8
|
+
*/
|
|
9
|
+
export const markdocLanguage = {
|
|
10
|
+
name: 'markdoc',
|
|
11
|
+
scopeName: 'text.html.markdoc',
|
|
12
|
+
displayName: 'Markdoc',
|
|
13
|
+
embeddedLangs: ['markdown'],
|
|
14
|
+
patterns: [
|
|
15
|
+
{ include: '#markdoc-tag' },
|
|
16
|
+
{ include: 'text.html.markdown' },
|
|
17
|
+
],
|
|
18
|
+
repository: {
|
|
19
|
+
'markdoc-tag': {
|
|
20
|
+
name: 'meta.tag.markdoc',
|
|
21
|
+
begin: '(\\{%)(\\s*\\/?\\s*[a-z][a-z0-9-]*)',
|
|
22
|
+
end: '(%\\})',
|
|
23
|
+
beginCaptures: {
|
|
24
|
+
1: { name: 'punctuation.definition.tag.begin.markdoc' },
|
|
25
|
+
2: { name: 'entity.name.tag.markdoc' },
|
|
26
|
+
},
|
|
27
|
+
endCaptures: {
|
|
28
|
+
1: { name: 'punctuation.definition.tag.end.markdoc' },
|
|
29
|
+
},
|
|
30
|
+
patterns: [
|
|
31
|
+
{ include: '#tag-attributes' },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
'tag-attributes': {
|
|
35
|
+
patterns: [
|
|
36
|
+
{ include: '#attribute-name' },
|
|
37
|
+
{ include: '#attribute-value-string' },
|
|
38
|
+
{ include: '#attribute-value-number' },
|
|
39
|
+
{ include: '#attribute-value-boolean' },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
'attribute-name': {
|
|
43
|
+
name: 'entity.other.attribute-name.markdoc',
|
|
44
|
+
match: '[a-zA-Z_][a-zA-Z0-9_-]*(?=\\s*=)',
|
|
45
|
+
},
|
|
46
|
+
'attribute-value-string': {
|
|
47
|
+
name: 'string.quoted.double.markdoc',
|
|
48
|
+
begin: '"',
|
|
49
|
+
end: '"',
|
|
50
|
+
},
|
|
51
|
+
'attribute-value-number': {
|
|
52
|
+
name: 'constant.numeric.markdoc',
|
|
53
|
+
match: '\\b\\d+\\b',
|
|
54
|
+
},
|
|
55
|
+
'attribute-value-boolean': {
|
|
56
|
+
name: 'constant.language.markdoc',
|
|
57
|
+
match: '\\b(true|false)\\b',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=markdoc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdoc.js","sourceRoot":"","sources":["../../src/langs/markdoc.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAyB;IACpD,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,mBAAmB;IAC9B,WAAW,EAAE,SAAS;IACtB,aAAa,EAAE,CAAC,UAAU,CAAC;IAC3B,QAAQ,EAAE;QACT,EAAE,OAAO,EAAE,cAAc,EAAE;QAC3B,EAAE,OAAO,EAAE,oBAAoB,EAAE;KACjC;IACD,UAAU,EAAE;QACX,aAAa,EAAE;YACd,IAAI,EAAE,kBAAkB;YACxB,KAAK,EAAE,qCAAqC;YAC5C,GAAG,EAAE,QAAQ;YACb,aAAa,EAAE;gBACd,CAAC,EAAE,EAAE,IAAI,EAAE,0CAA0C,EAAE;gBACvD,CAAC,EAAE,EAAE,IAAI,EAAE,yBAAyB,EAAE;aACtC;YACD,WAAW,EAAE;gBACZ,CAAC,EAAE,EAAE,IAAI,EAAE,wCAAwC,EAAE;aACrD;YACD,QAAQ,EAAE;gBACT,EAAE,OAAO,EAAE,iBAAiB,EAAE;aAC9B;SACD;QACD,gBAAgB,EAAE;YACjB,QAAQ,EAAE;gBACT,EAAE,OAAO,EAAE,iBAAiB,EAAE;gBAC9B,EAAE,OAAO,EAAE,yBAAyB,EAAE;gBACtC,EAAE,OAAO,EAAE,yBAAyB,EAAE;gBACtC,EAAE,OAAO,EAAE,0BAA0B,EAAE;aACvC;SACD;QACD,gBAAgB,EAAE;YACjB,IAAI,EAAE,qCAAqC;YAC3C,KAAK,EAAE,kCAAkC;SACzC;QACD,wBAAwB,EAAE;YACzB,IAAI,EAAE,8BAA8B;YACpC,KAAK,EAAE,GAAG;YACV,GAAG,EAAE,GAAG;SACR;QACD,wBAAwB,EAAE;YACzB,IAAI,EAAE,0BAA0B;YAChC,KAAK,EAAE,YAAY;SACnB;QACD,yBAAyB,EAAE;YAC1B,IAAI,EAAE,2BAA2B;YACjC,KAAK,EAAE,oBAAoB;SAC3B;KACD;CACD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@refrakt-md/highlight",
|
|
3
|
+
"description": "Syntax highlighting transform for refrakt.md — Shiki-based tree walker with pluggable highlighter",
|
|
4
|
+
"version": "0.3.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/refrakt-md/refrakt.git",
|
|
10
|
+
"directory": "packages/highlight"
|
|
11
|
+
},
|
|
12
|
+
"bugs": "https://github.com/refrakt-md/refrakt/issues",
|
|
13
|
+
"homepage": "https://github.com/refrakt-md/refrakt",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"main": "dist/index.js",
|
|
18
|
+
"types": "dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"default": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@refrakt-md/types": "0.3.0",
|
|
33
|
+
"@refrakt-md/transform": "0.3.0",
|
|
34
|
+
"shiki": "^3.0.0"
|
|
35
|
+
}
|
|
36
|
+
}
|