@refrakt-md/highlight 0.12.0 → 0.14.1
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/README.md +30 -0
- package/dist/extended-theme.d.ts +55 -0
- package/dist/extended-theme.d.ts.map +1 -0
- package/dist/extended-theme.js +157 -0
- package/dist/extended-theme.js.map +1 -0
- package/dist/highlight.d.ts +9 -1
- package/dist/highlight.d.ts.map +1 -1
- package/dist/highlight.js +79 -12
- package/dist/highlight.js.map +1 -1
- package/package.json +3 -3
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# @refrakt-md/highlight
|
|
2
|
+
|
|
3
|
+
Syntax-highlighting transform for refrakt. Walks a serialized renderable tree, finds elements carrying `data-language`, highlights their text via Shiki, and emits HTML the Renderer can inject.
|
|
4
|
+
|
|
5
|
+
The default highlighter wraps Shiki's `createCssVariablesTheme` so all highlighting flows through `--rf-syntax-token-*` custom properties. Themes don't import Shiki; they just supply values to the `--rf-syntax-*` contract surface established by SPEC-048, and the highlighter is interchangeable as an implementation detail.
|
|
6
|
+
|
|
7
|
+
## Default theme — extended CSS variables (SPEC-056)
|
|
8
|
+
|
|
9
|
+
The default theme used by `createHighlightTransform` is an **extended** css-variables theme that builds on Shiki's stock `createCssVariablesTheme` and adds scope→variable mappings for the optional syntax roles SPEC-056 introduced.
|
|
10
|
+
|
|
11
|
+
See `src/extended-theme.ts` for the full audit table of what Shiki's stock theme emits vs. what the extended theme adds. Summary:
|
|
12
|
+
|
|
13
|
+
| Role | Stock Shiki? | Extended theme adds? |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `keyword`, `function`, `string`, `constant`, `comment`, `punctuation`, `string-expression`, `link`, `parameter` | ✓ emitted | — |
|
|
16
|
+
| `type` | ✗ (routes to `function`) | ✓ via `entity.name.type`, `entity.name.class`, `support.type`, `support.class`, etc. |
|
|
17
|
+
| `tag` | ✗ (routes to `string-expression`) | ✓ via `entity.name.tag` |
|
|
18
|
+
| `attribute` | ✗ (routes to `function`) | ✓ via `entity.other.attribute-name` |
|
|
19
|
+
| `property` | ✗ | ✓ via `variable.other.property`, `meta.object-literal.key`, etc. |
|
|
20
|
+
| `operator` | ✗ (routes to `keyword`) | ✓ via `keyword.operator.*` (assignment, arithmetic, comparison, logical, …) |
|
|
21
|
+
| `number` | ✗ (routes to `constant`) | ✓ via `constant.numeric.*` |
|
|
22
|
+
| `regex` | ✗ (routes to `string-expression`) | ✓ via `string.regexp`, `string.regex` |
|
|
23
|
+
|
|
24
|
+
A preset that doesn't set the extended roles inherits the broad-mapping default emitted by the token-stylesheet generator (e.g. `--rf-syntax-token-type` falls back to `function`'s value when the preset doesn't supply `syntax.type`). A preset that *does* set the extended role gets dedicated colouring on the matching scopes.
|
|
25
|
+
|
|
26
|
+
## Alternative themes
|
|
27
|
+
|
|
28
|
+
`createHighlightTransform({ theme: 'github-dark' })` — pass a Shiki theme name to use it directly. Bypasses the `--rf-syntax-*` contract; the highlighter writes inline colours into spans and emits CSS that overrides `--rf-color-code-bg` / `--rf-color-code-text` for the page.
|
|
29
|
+
|
|
30
|
+
`createHighlightTransform({ theme: { light: 'github-light', dark: 'github-dark' } })` — dual themes that switch with the page's light/dark mode.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extended CSS-variables theme for refrakt.
|
|
3
|
+
*
|
|
4
|
+
* Builds on Shiki's `createCssVariablesTheme` (which emits ~9 `token-*`
|
|
5
|
+
* variables — link, string, comment, constant, keyword, parameter,
|
|
6
|
+
* function, string-expression, punctuation) and appends scope→variable
|
|
7
|
+
* mappings for the SPEC-056 extended roles that the stock theme doesn't
|
|
8
|
+
* route to dedicated variables today.
|
|
9
|
+
*
|
|
10
|
+
* Audit (against `@shikijs/core` createCssVariablesTheme as of v3.x):
|
|
11
|
+
*
|
|
12
|
+
* | Role | In stock theme? | Notes |
|
|
13
|
+
* |---|---|---|
|
|
14
|
+
* | `link`, `string`, `comment`, `constant`, `keyword`, `parameter`, `function`, `string-expression`, `punctuation` | ✓ | Emitted by stock theme — refrakt gets them for free. |
|
|
15
|
+
* | `type` | ✗ | `entity.name.type` etc. currently route to `token-function`. We override. |
|
|
16
|
+
* | `property` | ✗ | `variable.other.property` etc. not mapped. We add. |
|
|
17
|
+
* | `tag` | ✗ | `entity.name.tag` currently routes to `token-string-expression` (yes, really). We override to a dedicated `token-tag`. |
|
|
18
|
+
* | `attribute` | ✗ | `entity.other.attribute-name` currently routes to `token-function`. We override. |
|
|
19
|
+
* | `operator` | ✗ | `keyword.operator` falls through to `token-keyword`. We override. |
|
|
20
|
+
* | `number` | ✗ | `constant.numeric` falls into the broader `token-constant` scope list. We split it out. |
|
|
21
|
+
* | `regex` | ✗ | `string.regexp` currently routes to `token-string-expression`. We override. |
|
|
22
|
+
*
|
|
23
|
+
* The override mechanism is TextMate scope matching: an entry later in
|
|
24
|
+
* `tokenColors` with an equally-or-more-specific scope wins over earlier
|
|
25
|
+
* entries. Our overrides target the same scope strings the stock theme
|
|
26
|
+
* uses (or more specific children) so the routing changes deterministically.
|
|
27
|
+
*
|
|
28
|
+
* Variable values for the new roles default to the matching core role
|
|
29
|
+
* via the CSS generator's broad-mapping pattern (see
|
|
30
|
+
* `packages/transform/src/token-stylesheet.ts` `SYNTAX_TO_SHIKI_ALIASES`).
|
|
31
|
+
* A preset that doesn't set the extended role renders identically to
|
|
32
|
+
* stock Shiki; a preset that *does* set it picks up the dedicated colour.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createExtendedCssVariablesTheme(options?: {
|
|
35
|
+
variablePrefix?: string;
|
|
36
|
+
}): {
|
|
37
|
+
tokenColors: ({
|
|
38
|
+
scope: string[];
|
|
39
|
+
settings: {
|
|
40
|
+
foreground: string;
|
|
41
|
+
};
|
|
42
|
+
} | import("shiki").RawThemeSetting)[];
|
|
43
|
+
name?: string | undefined;
|
|
44
|
+
displayName?: string | undefined;
|
|
45
|
+
type?: "light" | "dark" | undefined;
|
|
46
|
+
settings?: import("shiki").RawThemeSetting[] | undefined;
|
|
47
|
+
fg?: string | undefined;
|
|
48
|
+
bg?: string | undefined;
|
|
49
|
+
colorReplacements?: Record<string, string> | undefined;
|
|
50
|
+
colors?: Record<string, string> | undefined;
|
|
51
|
+
$schema?: string | undefined;
|
|
52
|
+
semanticHighlighting?: boolean | undefined;
|
|
53
|
+
semanticTokenColors?: Record<string, string> | undefined;
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=extended-theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extended-theme.d.ts","sourceRoot":"","sources":["../src/extended-theme.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO;;;;;;;;;;;;;;;;;;EAmIxF"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { createCssVariablesTheme } from 'shiki';
|
|
2
|
+
/**
|
|
3
|
+
* Extended CSS-variables theme for refrakt.
|
|
4
|
+
*
|
|
5
|
+
* Builds on Shiki's `createCssVariablesTheme` (which emits ~9 `token-*`
|
|
6
|
+
* variables — link, string, comment, constant, keyword, parameter,
|
|
7
|
+
* function, string-expression, punctuation) and appends scope→variable
|
|
8
|
+
* mappings for the SPEC-056 extended roles that the stock theme doesn't
|
|
9
|
+
* route to dedicated variables today.
|
|
10
|
+
*
|
|
11
|
+
* Audit (against `@shikijs/core` createCssVariablesTheme as of v3.x):
|
|
12
|
+
*
|
|
13
|
+
* | Role | In stock theme? | Notes |
|
|
14
|
+
* |---|---|---|
|
|
15
|
+
* | `link`, `string`, `comment`, `constant`, `keyword`, `parameter`, `function`, `string-expression`, `punctuation` | ✓ | Emitted by stock theme — refrakt gets them for free. |
|
|
16
|
+
* | `type` | ✗ | `entity.name.type` etc. currently route to `token-function`. We override. |
|
|
17
|
+
* | `property` | ✗ | `variable.other.property` etc. not mapped. We add. |
|
|
18
|
+
* | `tag` | ✗ | `entity.name.tag` currently routes to `token-string-expression` (yes, really). We override to a dedicated `token-tag`. |
|
|
19
|
+
* | `attribute` | ✗ | `entity.other.attribute-name` currently routes to `token-function`. We override. |
|
|
20
|
+
* | `operator` | ✗ | `keyword.operator` falls through to `token-keyword`. We override. |
|
|
21
|
+
* | `number` | ✗ | `constant.numeric` falls into the broader `token-constant` scope list. We split it out. |
|
|
22
|
+
* | `regex` | ✗ | `string.regexp` currently routes to `token-string-expression`. We override. |
|
|
23
|
+
*
|
|
24
|
+
* The override mechanism is TextMate scope matching: an entry later in
|
|
25
|
+
* `tokenColors` with an equally-or-more-specific scope wins over earlier
|
|
26
|
+
* entries. Our overrides target the same scope strings the stock theme
|
|
27
|
+
* uses (or more specific children) so the routing changes deterministically.
|
|
28
|
+
*
|
|
29
|
+
* Variable values for the new roles default to the matching core role
|
|
30
|
+
* via the CSS generator's broad-mapping pattern (see
|
|
31
|
+
* `packages/transform/src/token-stylesheet.ts` `SYNTAX_TO_SHIKI_ALIASES`).
|
|
32
|
+
* A preset that doesn't set the extended role renders identically to
|
|
33
|
+
* stock Shiki; a preset that *does* set it picks up the dedicated colour.
|
|
34
|
+
*/
|
|
35
|
+
export function createExtendedCssVariablesTheme(options = {}) {
|
|
36
|
+
const { variablePrefix = '--rf-syntax-' } = options;
|
|
37
|
+
const base = createCssVariablesTheme({ variablePrefix });
|
|
38
|
+
const v = (name) => `var(${variablePrefix}${name})`;
|
|
39
|
+
const extendedTokenColors = [
|
|
40
|
+
// ── type ──────────────────────────────────────────────────────────
|
|
41
|
+
// Type names, class names, interface names. Stock theme currently
|
|
42
|
+
// routes these to token-function; we split them off.
|
|
43
|
+
{
|
|
44
|
+
scope: [
|
|
45
|
+
'entity.name.type',
|
|
46
|
+
'entity.name.class',
|
|
47
|
+
'entity.other.inherited-class',
|
|
48
|
+
'support.type',
|
|
49
|
+
'support.class',
|
|
50
|
+
'meta.type.declaration entity.name',
|
|
51
|
+
'meta.interface.declaration entity.name',
|
|
52
|
+
'storage.type.class',
|
|
53
|
+
'storage.type.interface',
|
|
54
|
+
],
|
|
55
|
+
settings: { foreground: v('token-type') },
|
|
56
|
+
},
|
|
57
|
+
// ── tag ───────────────────────────────────────────────────────────
|
|
58
|
+
// JSX/HTML/XML element tag names. Stock theme routes these to
|
|
59
|
+
// token-string-expression (surprisingly); we split them off.
|
|
60
|
+
{
|
|
61
|
+
scope: [
|
|
62
|
+
'entity.name.tag',
|
|
63
|
+
'meta.tag entity.name',
|
|
64
|
+
'support.class.component',
|
|
65
|
+
],
|
|
66
|
+
settings: { foreground: v('token-tag') },
|
|
67
|
+
},
|
|
68
|
+
// ── attribute ─────────────────────────────────────────────────────
|
|
69
|
+
// JSX/HTML/XML attribute names. Stock theme routes these to
|
|
70
|
+
// token-function; we split them off.
|
|
71
|
+
{
|
|
72
|
+
scope: [
|
|
73
|
+
'entity.other.attribute-name',
|
|
74
|
+
'meta.attribute entity.other.attribute-name',
|
|
75
|
+
],
|
|
76
|
+
settings: { foreground: v('token-attribute') },
|
|
77
|
+
},
|
|
78
|
+
// ── property ──────────────────────────────────────────────────────
|
|
79
|
+
// Object property access, property keys. Stock theme doesn't emit a
|
|
80
|
+
// dedicated variable for these.
|
|
81
|
+
{
|
|
82
|
+
scope: [
|
|
83
|
+
'variable.other.property',
|
|
84
|
+
'variable.other.object.property',
|
|
85
|
+
'support.variable.property',
|
|
86
|
+
'meta.property.object',
|
|
87
|
+
'meta.object-literal.key',
|
|
88
|
+
'support.type.property-name',
|
|
89
|
+
],
|
|
90
|
+
settings: { foreground: v('token-property') },
|
|
91
|
+
},
|
|
92
|
+
// ── parameter (broader) ───────────────────────────────────────────
|
|
93
|
+
// Stock theme only matches `variable.parameter.function` (narrow).
|
|
94
|
+
// Broaden to all parameter-like positions.
|
|
95
|
+
{
|
|
96
|
+
scope: [
|
|
97
|
+
'variable.parameter',
|
|
98
|
+
'variable.parameter.function-call',
|
|
99
|
+
'meta.function.parameters variable',
|
|
100
|
+
],
|
|
101
|
+
settings: { foreground: v('token-parameter') },
|
|
102
|
+
},
|
|
103
|
+
// ── operator ──────────────────────────────────────────────────────
|
|
104
|
+
// Arithmetic, comparison, logical operators. Stock theme falls
|
|
105
|
+
// through to token-keyword via `keyword.operator → keyword`.
|
|
106
|
+
// Note: `keyword.operator.accessor` is already reset to `foreground`
|
|
107
|
+
// in stock theme (intentionally), so we don't override that one.
|
|
108
|
+
{
|
|
109
|
+
scope: [
|
|
110
|
+
'keyword.operator.assignment',
|
|
111
|
+
'keyword.operator.arithmetic',
|
|
112
|
+
'keyword.operator.comparison',
|
|
113
|
+
'keyword.operator.logical',
|
|
114
|
+
'keyword.operator.bitwise',
|
|
115
|
+
'keyword.operator.relational',
|
|
116
|
+
'keyword.operator.ternary',
|
|
117
|
+
'keyword.operator.new',
|
|
118
|
+
'keyword.operator.delete',
|
|
119
|
+
'keyword.operator.spread',
|
|
120
|
+
'keyword.operator.rest',
|
|
121
|
+
'keyword.operator.optional',
|
|
122
|
+
'keyword.operator.expression',
|
|
123
|
+
],
|
|
124
|
+
settings: { foreground: v('token-operator') },
|
|
125
|
+
},
|
|
126
|
+
// ── number ────────────────────────────────────────────────────────
|
|
127
|
+
// Numeric literals — split out from the broader token-constant
|
|
128
|
+
// group when a palette wants distinct number colouring.
|
|
129
|
+
{
|
|
130
|
+
scope: [
|
|
131
|
+
'constant.numeric',
|
|
132
|
+
'constant.numeric.integer',
|
|
133
|
+
'constant.numeric.float',
|
|
134
|
+
'constant.numeric.hex',
|
|
135
|
+
'constant.numeric.binary',
|
|
136
|
+
'constant.numeric.octal',
|
|
137
|
+
],
|
|
138
|
+
settings: { foreground: v('token-number') },
|
|
139
|
+
},
|
|
140
|
+
// ── regex ─────────────────────────────────────────────────────────
|
|
141
|
+
// Regular expression literals. Stock theme routes string.regexp to
|
|
142
|
+
// token-string-expression; we split them off.
|
|
143
|
+
{
|
|
144
|
+
scope: [
|
|
145
|
+
'string.regexp',
|
|
146
|
+
'string.regex',
|
|
147
|
+
'string.quoted.regex',
|
|
148
|
+
],
|
|
149
|
+
settings: { foreground: v('token-regex') },
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
return {
|
|
153
|
+
...base,
|
|
154
|
+
tokenColors: [...(base.tokenColors ?? []), ...extendedTokenColors],
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=extended-theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extended-theme.js","sourceRoot":"","sources":["../src/extended-theme.ts"],"names":[],"mappings":"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"}
|
package/dist/highlight.d.ts
CHANGED
|
@@ -8,11 +8,19 @@ export interface HighlightOptions {
|
|
|
8
8
|
* Default: Shiki with css-variables theme. */
|
|
9
9
|
highlight?: (code: string, lang: string) => string;
|
|
10
10
|
/** Shiki theme — a built-in theme name, or { light, dark } pair for dual themes.
|
|
11
|
-
* Default: CSS variables theme
|
|
11
|
+
* Default: CSS variables theme emitting `--rf-syntax-*` custom properties
|
|
12
|
+
* (see SPEC-048 — the contract surface that hides the highlighter from themes). */
|
|
12
13
|
theme?: string | {
|
|
13
14
|
light: string;
|
|
14
15
|
dark: string;
|
|
15
16
|
};
|
|
17
|
+
/** Force fenced code blocks to a fixed colour scheme regardless of the page's
|
|
18
|
+
* light/dark mode. When set to `'light'` or `'dark'`, every `<pre>` carrying
|
|
19
|
+
* a `data-language` attribute is stamped with `data-color-scheme=<value>`
|
|
20
|
+
* so the existing token cascade (`[data-color-scheme="dark"]` rules in
|
|
21
|
+
* Lumina and in the generated site-tokens.css) flips that subtree's
|
|
22
|
+
* syntax + code-surface variables. Default `'auto'` (no attribute added). */
|
|
23
|
+
codeColorScheme?: 'auto' | 'light' | 'dark';
|
|
16
24
|
}
|
|
17
25
|
/** A highlight transform function with an attached `.css` property containing
|
|
18
26
|
* any CSS needed for the selected theme (background overrides, dual-theme toggle). */
|
package/dist/highlight.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"highlight.d.ts","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAqD,MAAM,OAAO,CAAC;AAErG,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"highlight.d.ts","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAqD,MAAM,OAAO,CAAC;AAErG,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,mBAAmB,CAAC;AAiBrE,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;IACnD;;wFAEoF;IACpF,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD;;;;;kFAK8E;IAC9E,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;CAC5C;AAED;uFACuF;AACvF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAU1F;;;;;;;;;;;GAWG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAAC,kBAAkB,CAAC,CAoD7B"}
|
package/dist/highlight.js
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
import { createHighlighter
|
|
1
|
+
import { createHighlighter } from 'shiki';
|
|
2
2
|
import { isTag } from '@refrakt-md/transform';
|
|
3
3
|
import { markdocLanguage } from './langs/markdoc.js';
|
|
4
|
-
|
|
4
|
+
import { createExtendedCssVariablesTheme } from './extended-theme.js';
|
|
5
|
+
/** The CSS-variables theme uses `--rf-syntax-*` instead of Shiki's default
|
|
6
|
+
* `--shiki-*` prefix, so the highlighter is invisible to themes that only
|
|
7
|
+
* see the `--rf-syntax-*` contract surface (SPEC-048). Swapping Shiki for
|
|
8
|
+
* Prism, Starry Night, or a server-side alternative becomes an internal
|
|
9
|
+
* change rather than a breaking change for every downstream theme.
|
|
10
|
+
*
|
|
11
|
+
* Extended per SPEC-056 with additional scope→variable mappings for the
|
|
12
|
+
* optional syntax roles (`type`, `tag`, `attribute`, `property`,
|
|
13
|
+
* `parameter` widened, `operator`, `number`, `regex`) that the stock
|
|
14
|
+
* Shiki theme doesn't route to dedicated variables. See
|
|
15
|
+
* `extended-theme.ts` for the audit and override list. */
|
|
16
|
+
const cssVarsTheme = createExtendedCssVariablesTheme({ variablePrefix: '--rf-syntax-' });
|
|
5
17
|
const DEFAULT_LANGS = [
|
|
6
18
|
'javascript', 'typescript', 'html', 'css', 'json', 'shell',
|
|
7
19
|
'python', 'ruby', 'go', 'rust', 'java', 'c', 'cpp',
|
|
@@ -22,7 +34,10 @@ const DEFAULT_LANGS = [
|
|
|
22
34
|
* for the selected theme (background color overrides, dual-theme toggle rules).
|
|
23
35
|
*/
|
|
24
36
|
export async function createHighlightTransform(options = {}) {
|
|
25
|
-
const { langs = DEFAULT_LANGS, highlight: customHighlight, theme } = options;
|
|
37
|
+
const { langs = DEFAULT_LANGS, highlight: customHighlight, theme, codeColorScheme } = options;
|
|
38
|
+
const forcedScheme = codeColorScheme === 'light' || codeColorScheme === 'dark'
|
|
39
|
+
? codeColorScheme
|
|
40
|
+
: undefined;
|
|
26
41
|
let highlightFn;
|
|
27
42
|
let css = '';
|
|
28
43
|
if (customHighlight) {
|
|
@@ -67,7 +82,7 @@ export async function createHighlightTransform(options = {}) {
|
|
|
67
82
|
return extractInnerHtml(html);
|
|
68
83
|
};
|
|
69
84
|
}
|
|
70
|
-
const transform = ((tree) => walk(tree, highlightFn));
|
|
85
|
+
const transform = ((tree) => walk(tree, highlightFn, forcedScheme, false).node);
|
|
71
86
|
transform.css = css;
|
|
72
87
|
return transform;
|
|
73
88
|
}
|
|
@@ -117,21 +132,73 @@ pre[data-language] {
|
|
|
117
132
|
}
|
|
118
133
|
`;
|
|
119
134
|
}
|
|
120
|
-
/** Walk the serialized tree, highlighting elements with `data-language`.
|
|
121
|
-
|
|
135
|
+
/** Walk the serialized tree, highlighting elements with `data-language`.
|
|
136
|
+
* Returns the transformed node plus whether any highlighted (or
|
|
137
|
+
* `<pre data-language>`) descendant was produced, so callers can stamp
|
|
138
|
+
* `data-color-scheme` on the rune wrapper that hosts the code.
|
|
139
|
+
*
|
|
140
|
+
* Stamping rules:
|
|
141
|
+
* - A `<pre data-language>` (the codeblock wrapper) is stamped UNLESS it
|
|
142
|
+
* sits inside a `data-code-host` ancestor — in which case the host owns
|
|
143
|
+
* the stamp and the inner `<pre>` inherits via CSS cascade.
|
|
144
|
+
* - An element with `data-code-host` (set by diff, compare, code-group)
|
|
145
|
+
* is stamped when it hosts code below it. Generic content wrappers
|
|
146
|
+
* that merely happen to contain a code rune (preview, hint, callout,
|
|
147
|
+
* etc.) deliberately do NOT carry `data-code-host`, so their chrome
|
|
148
|
+
* stays in the page's normal colour scheme.
|
|
149
|
+
* - Stamping consumes the flag so outer non-host wrappers don't see a
|
|
150
|
+
* spurious "hasHighlighted" signal and start flipping their own chrome.
|
|
151
|
+
*/
|
|
152
|
+
function walk(node, highlightFn, forcedScheme, hasCodeHostAncestor) {
|
|
122
153
|
if (node === null || node === undefined)
|
|
123
|
-
return node;
|
|
154
|
+
return { node, hasHighlighted: false };
|
|
124
155
|
if (typeof node === 'string' || typeof node === 'number')
|
|
125
|
-
return node;
|
|
156
|
+
return { node, hasHighlighted: false };
|
|
126
157
|
if (!isTag(node))
|
|
127
|
-
return node;
|
|
158
|
+
return { node, hasHighlighted: false };
|
|
128
159
|
const lang = node.attributes?.['data-language'];
|
|
160
|
+
const isCodeHost = !!node.attributes?.['data-code-host'];
|
|
161
|
+
const isPreCodeblock = !!lang && node.name === 'pre';
|
|
129
162
|
if (lang && hasTextChildren(node)) {
|
|
130
|
-
return highlightNode(node, lang, highlightFn);
|
|
163
|
+
return { node: highlightNode(node, lang, highlightFn), hasHighlighted: true };
|
|
164
|
+
}
|
|
165
|
+
const childHasCodeHost = hasCodeHostAncestor || isCodeHost;
|
|
166
|
+
let anyHighlighted = false;
|
|
167
|
+
const children = node.children.map(c => {
|
|
168
|
+
const result = walk(c, highlightFn, forcedScheme, childHasCodeHost);
|
|
169
|
+
if (result.hasHighlighted)
|
|
170
|
+
anyHighlighted = true;
|
|
171
|
+
return result.node;
|
|
172
|
+
});
|
|
173
|
+
// `<pre data-language>` always counts as a code container, even if the
|
|
174
|
+
// inner highlight failed (unknown language). The override still flips
|
|
175
|
+
// the code surface for fallback rendering.
|
|
176
|
+
const isCodeContainer = isPreCodeblock || anyHighlighted;
|
|
177
|
+
if (forcedScheme) {
|
|
178
|
+
if (isCodeHost && isCodeContainer) {
|
|
179
|
+
return {
|
|
180
|
+
node: {
|
|
181
|
+
...node,
|
|
182
|
+
attributes: { ...node.attributes, 'data-color-scheme': forcedScheme },
|
|
183
|
+
children,
|
|
184
|
+
},
|
|
185
|
+
hasHighlighted: false,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
if (isPreCodeblock && !hasCodeHostAncestor) {
|
|
189
|
+
return {
|
|
190
|
+
node: {
|
|
191
|
+
...node,
|
|
192
|
+
attributes: { ...node.attributes, 'data-color-scheme': forcedScheme },
|
|
193
|
+
children,
|
|
194
|
+
},
|
|
195
|
+
hasHighlighted: false,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
131
198
|
}
|
|
132
199
|
return {
|
|
133
|
-
...node,
|
|
134
|
-
|
|
200
|
+
node: { ...node, children },
|
|
201
|
+
hasHighlighted: isCodeContainer,
|
|
135
202
|
};
|
|
136
203
|
}
|
|
137
204
|
function hasTextChildren(node) {
|
package/dist/highlight.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"highlight.js","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"highlight.js","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@refrakt-md/highlight",
|
|
3
3
|
"description": "Syntax highlighting transform for refrakt.md — Shiki-based tree walker with pluggable highlighter",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"build": "tsc"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@refrakt-md/types": "0.
|
|
33
|
-
"@refrakt-md/transform": "0.
|
|
32
|
+
"@refrakt-md/types": "0.14.1",
|
|
33
|
+
"@refrakt-md/transform": "0.14.1",
|
|
34
34
|
"shiki": "^3.0.0"
|
|
35
35
|
}
|
|
36
36
|
}
|