@mui/internal-docs-infra 0.12.1-canary.31 → 0.12.1-canary.33
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/package.json +2 -2
- package/pipeline/cacheUtils/constants.d.mts +11 -1
- package/pipeline/cacheUtils/constants.mjs +12 -1
- package/pipeline/cacheUtils/index.d.mts +1 -1
- package/pipeline/cacheUtils/index.mjs +1 -1
- package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasis.mjs +9 -7
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransformWithComments.mjs +3 -3
- package/pipeline/loadIsomorphicCodeVariant/diffHast.mjs +10 -12
- package/pipeline/loadIsomorphicCodeVariant/embedTransforms.d.mts +4 -3
- package/pipeline/loadIsomorphicCodeVariant/embedTransforms.mjs +9 -11
- package/pipeline/loadIsomorphicCodeVariant/getInitialVisibleSourceLines.mjs +3 -3
- package/pipeline/loadServerTypes/hastTypeUtils.d.mts +2 -2
- package/pipeline/loadServerTypes/hastTypeUtils.mjs +2 -11
- package/pipeline/loadServerTypes/loadServerTypes.mjs +4 -1
- package/pipeline/loadServerTypesText/parseTypesMarkdown.mjs +53 -91
- package/pipeline/loadServerTypesText/resolveTypesCacheKey.d.mts +4 -2
- package/pipeline/loadServerTypesText/resolveTypesCacheKey.mjs +6 -3
- package/pipeline/parseSource/addLineGutters.mjs +3 -3
- package/pipeline/parseSource/createFrame.mjs +1 -1
- package/pipeline/parseSource/isFrameSpan.d.mts +5 -10
- package/pipeline/parseSource/isFrameSpan.mjs +6 -12
- package/pipeline/parseSource/restructureFrames.mjs +4 -4
- package/pipeline/transformMarkdownCode/transformMarkdownCode.mjs +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-docs-infra",
|
|
3
|
-
"version": "0.12.1-canary.
|
|
3
|
+
"version": "0.12.1-canary.33",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "MUI Infra - internal documentation creation tools.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -804,5 +804,5 @@
|
|
|
804
804
|
"bin": {
|
|
805
805
|
"docs-infra": "./cli/index.mjs"
|
|
806
806
|
},
|
|
807
|
-
"gitSha": "
|
|
807
|
+
"gitSha": "adffaff76b0a500634bfdd5960365616eb6d2137"
|
|
808
808
|
}
|
|
@@ -2,4 +2,14 @@
|
|
|
2
2
|
* Default root directory for docs-infra build caches. Sits alongside the marker
|
|
3
3
|
* directories already written under `.next/cache/docs-infra`.
|
|
4
4
|
*/
|
|
5
|
-
export declare const DEFAULT_CACHE_DIR = ".next/cache/docs-infra";
|
|
5
|
+
export declare const DEFAULT_CACHE_DIR = ".next/cache/docs-infra";
|
|
6
|
+
/**
|
|
7
|
+
* Version of the shape of cached *output*. Entries are validated by hashing their inputs, so a
|
|
8
|
+
* pipeline change that alters the output for unchanged input is invisible to that hash — and
|
|
9
|
+
* `.next/cache` survives between builds (`@mui/internal-netlify-cache` restores it), so a warm
|
|
10
|
+
* cache would keep serving output produced by the previous code.
|
|
11
|
+
*
|
|
12
|
+
* Bump this whenever such a change lands. Caches whose stored shape can change fold it into their
|
|
13
|
+
* `getCacheContent`, which makes existing entries hash as stale and be recomputed in place.
|
|
14
|
+
*/
|
|
15
|
+
export declare const CACHE_SCHEMA_VERSION = 1;
|
|
@@ -2,4 +2,15 @@
|
|
|
2
2
|
* Default root directory for docs-infra build caches. Sits alongside the marker
|
|
3
3
|
* directories already written under `.next/cache/docs-infra`.
|
|
4
4
|
*/
|
|
5
|
-
export const DEFAULT_CACHE_DIR = '.next/cache/docs-infra';
|
|
5
|
+
export const DEFAULT_CACHE_DIR = '.next/cache/docs-infra';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Version of the shape of cached *output*. Entries are validated by hashing their inputs, so a
|
|
9
|
+
* pipeline change that alters the output for unchanged input is invisible to that hash — and
|
|
10
|
+
* `.next/cache` survives between builds (`@mui/internal-netlify-cache` restores it), so a warm
|
|
11
|
+
* cache would keep serving output produced by the previous code.
|
|
12
|
+
*
|
|
13
|
+
* Bump this whenever such a change lands. Caches whose stored shape can change fold it into their
|
|
14
|
+
* `getCacheContent`, which makes existing entries hash as stale and be recomputed in place.
|
|
15
|
+
*/
|
|
16
|
+
export const CACHE_SCHEMA_VERSION = 1;
|
|
@@ -5,5 +5,5 @@ export { saveFileCache } from "./saveFileCache.mjs";
|
|
|
5
5
|
export { resolveCachePath } from "./resolveCachePath.mjs";
|
|
6
6
|
export { withFileCache } from "./withFileCache.mjs";
|
|
7
7
|
export type { FileCacheTask } from "./withFileCache.mjs";
|
|
8
|
-
export { DEFAULT_CACHE_DIR } from "./constants.mjs";
|
|
8
|
+
export { DEFAULT_CACHE_DIR, CACHE_SCHEMA_VERSION } from "./constants.mjs";
|
|
9
9
|
export type { FileCacheRef, FileCacheEntry } from "./types.mjs";
|
|
@@ -4,4 +4,4 @@ export { loadFileCacheEntry } from "./loadFileCacheEntry.mjs";
|
|
|
4
4
|
export { saveFileCache } from "./saveFileCache.mjs";
|
|
5
5
|
export { resolveCachePath } from "./resolveCachePath.mjs";
|
|
6
6
|
export { withFileCache } from "./withFileCache.mjs";
|
|
7
|
-
export { DEFAULT_CACHE_DIR } from "./constants.mjs";
|
|
7
|
+
export { DEFAULT_CACHE_DIR, CACHE_SCHEMA_VERSION } from "./constants.mjs";
|
|
@@ -2,6 +2,7 @@ import { getHastTextContent } from "../loadServerTypes/hastTypeUtils.mjs";
|
|
|
2
2
|
import { calculateFrameRanges } from "../parseSource/calculateFrameRanges.mjs";
|
|
3
3
|
import { calculateFrameIndent } from "./calculateFrameIndent.mjs";
|
|
4
4
|
import { restructureFrames } from "../parseSource/restructureFrames.mjs";
|
|
5
|
+
import { hasClassName } from "../parseSource/isFrameSpan.mjs";
|
|
5
6
|
/**
|
|
6
7
|
* The prefix used to identify emphasis comments in source code.
|
|
7
8
|
* Comments starting with this prefix will be processed for emphasis.
|
|
@@ -494,7 +495,7 @@ function buildLineElementMap(node) {
|
|
|
494
495
|
}
|
|
495
496
|
|
|
496
497
|
// Check if this is a line element
|
|
497
|
-
if (child.tagName === 'span' && child
|
|
498
|
+
if (child.tagName === 'span' && hasClassName(child, 'line') && typeof child.properties.dataLn === 'number') {
|
|
498
499
|
map.set(child.properties.dataLn, child);
|
|
499
500
|
}
|
|
500
501
|
|
|
@@ -530,9 +531,10 @@ function isCommentOnlyLine(lineElement, commentText) {
|
|
|
530
531
|
hasNonWhitespaceContent = true;
|
|
531
532
|
}
|
|
532
533
|
} else if (child.type === 'element') {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
534
|
+
// Read once: this runs per token span, and both branches below test the
|
|
535
|
+
// same list.
|
|
536
|
+
const classNames = child.properties?.className;
|
|
537
|
+
if (classNames?.includes('pl-c')) {
|
|
536
538
|
// This is a comment element - check if it contains the expected text
|
|
537
539
|
const text = getHastTextContent(child);
|
|
538
540
|
if (text.includes(commentText)) {
|
|
@@ -541,7 +543,7 @@ function isCommentOnlyLine(lineElement, commentText) {
|
|
|
541
543
|
// Some other comment
|
|
542
544
|
hasNonWhitespaceContent = true;
|
|
543
545
|
}
|
|
544
|
-
} else if (classNames
|
|
546
|
+
} else if (classNames?.includes('pl-pse')) {
|
|
545
547
|
// This is punctuation for special expressions (JSX braces for comments)
|
|
546
548
|
// Check if it's just `{` or `}` which are used for JSX comment syntax
|
|
547
549
|
const text = getHastTextContent(child);
|
|
@@ -1108,7 +1110,7 @@ function applyEmphasisAndCollectHighlightedElements(node, emphasizedLines, optio
|
|
|
1108
1110
|
}
|
|
1109
1111
|
|
|
1110
1112
|
// Check if this is a line element
|
|
1111
|
-
if (child.tagName === 'span' && child
|
|
1113
|
+
if (child.tagName === 'span' && hasClassName(child, 'line') && typeof child.properties.dataLn === 'number') {
|
|
1112
1114
|
const lineNumber = child.properties.dataLn;
|
|
1113
1115
|
const meta = emphasizedLines.get(lineNumber);
|
|
1114
1116
|
if (meta !== undefined) {
|
|
@@ -1242,7 +1244,7 @@ function reconcileLineAndFrameEmphasis(root, emphasizedLines) {
|
|
|
1242
1244
|
const frameType = frame.properties?.dataFrameType;
|
|
1243
1245
|
const isHighlightedFrame = frameType === 'highlighted' || frameType === 'highlighted-unfocused';
|
|
1244
1246
|
for (const child of frame.children) {
|
|
1245
|
-
if (child.type !== 'element' || child.tagName !== 'span' || child
|
|
1247
|
+
if (child.type !== 'element' || child.tagName !== 'span' || !hasClassName(child, 'line') || typeof child.properties.dataLn !== 'number') {
|
|
1246
1248
|
continue;
|
|
1247
1249
|
}
|
|
1248
1250
|
const meta = emphasizedLines.get(child.properties.dataLn);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { patch, clone } from 'jsondiffpatch';
|
|
12
12
|
import { findExpandingRanges } from "./findExpandingRanges.mjs";
|
|
13
|
-
import { isFrameSpan } from "../parseSource/isFrameSpan.mjs";
|
|
13
|
+
import { hasClassName, isFrameSpan } from "../parseSource/isFrameSpan.mjs";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Decodes a `VariantSource` to a live `HastRoot` (or `null` for string /
|
|
@@ -60,7 +60,7 @@ function renumberLines(root) {
|
|
|
60
60
|
const children = frame.children;
|
|
61
61
|
for (let i = 0; i < children.length; i += 1) {
|
|
62
62
|
const child = children[i];
|
|
63
|
-
if (child.type === 'element' && child.properties != null && child
|
|
63
|
+
if (child.type === 'element' && child.properties != null && hasClassName(child, 'line')) {
|
|
64
64
|
lineNumber += 1;
|
|
65
65
|
const previous = child.properties.dataLn;
|
|
66
66
|
if (typeof previous === 'number') {
|
|
@@ -120,7 +120,7 @@ function markAddedLinesInPlace(root, ranges) {
|
|
|
120
120
|
const children = frame.children;
|
|
121
121
|
for (let i = 0; i < children.length; i += 1) {
|
|
122
122
|
const child = children[i];
|
|
123
|
-
if (child.type !== 'element' || child.properties == null || child
|
|
123
|
+
if (child.type !== 'element' || child.properties == null || !hasClassName(child, 'line')) {
|
|
124
124
|
continue;
|
|
125
125
|
}
|
|
126
126
|
const lineNumber = child.properties.dataLn;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { create, patch } from 'jsondiffpatch';
|
|
2
2
|
import { findExpandingRanges, hasExpandingRanges } from "./findExpandingRanges.mjs";
|
|
3
3
|
import { getInitialVisibleSourceLines } from "./getInitialVisibleSourceLines.mjs";
|
|
4
|
+
import { hasClassName } from "../parseSource/isFrameSpan.mjs";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Async-friendly variant of {@link ParseSource}. The build-time diff path
|
|
@@ -27,15 +28,12 @@ const differ = create({
|
|
|
27
28
|
if (value === null || typeof value !== 'object') {
|
|
28
29
|
return `idx:${index}`;
|
|
29
30
|
}
|
|
31
|
+
// jsondiffpatch hands us `unknown`; the checks below validate the cast.
|
|
30
32
|
const node = value;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// can't morph a wiped line span into a placeholder in place.
|
|
36
|
-
if (className === 'collapse') {
|
|
37
|
-
return `collapse:${index}`;
|
|
38
|
-
}
|
|
33
|
+
// Collapse placeholders get a unique identity so jsondiffpatch
|
|
34
|
+
// can't morph a wiped line span into a placeholder in place.
|
|
35
|
+
if (node.type === 'element' && node.tagName === 'span' && hasClassName(node, 'collapse')) {
|
|
36
|
+
return `collapse:${index}`;
|
|
39
37
|
}
|
|
40
38
|
// Everything else (frames, lines, text) falls back to positional
|
|
41
39
|
// identity — same as jsondiffpatch's default behavior — so we don't
|
|
@@ -63,7 +61,7 @@ function isEmptyLine(line) {
|
|
|
63
61
|
return false;
|
|
64
62
|
}
|
|
65
63
|
function isLineElement(node) {
|
|
66
|
-
return !!node && node.type === 'element' && node.tagName === 'span' && node.properties != null && node
|
|
64
|
+
return !!node && node.type === 'element' && node.tagName === 'span' && node.properties != null && hasClassName(node, 'line');
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
/**
|
|
@@ -84,7 +82,7 @@ function stripLineNumbersInPlace(root) {
|
|
|
84
82
|
const lines = frame.children;
|
|
85
83
|
for (let i = 0; i < lines.length; i += 1) {
|
|
86
84
|
const line = lines[i];
|
|
87
|
-
if (line.type === 'element' && line.properties != null && line
|
|
85
|
+
if (line.type === 'element' && line.properties != null && hasClassName(line, 'line') && line.properties.dataLn !== undefined) {
|
|
88
86
|
delete line.properties.dataLn;
|
|
89
87
|
}
|
|
90
88
|
}
|
|
@@ -187,7 +185,7 @@ function renumberLinesInPlace(root) {
|
|
|
187
185
|
const children = frame.children;
|
|
188
186
|
for (let i = 0; i < children.length; i += 1) {
|
|
189
187
|
const child = children[i];
|
|
190
|
-
if (child.type === 'element' && child.properties != null && child
|
|
188
|
+
if (child.type === 'element' && child.properties != null && hasClassName(child, 'line')) {
|
|
191
189
|
lineNumber += 1;
|
|
192
190
|
child.properties.dataLn = lineNumber;
|
|
193
191
|
}
|
|
@@ -303,7 +301,7 @@ function makePlaceholder(count) {
|
|
|
303
301
|
type: 'element',
|
|
304
302
|
tagName: 'span',
|
|
305
303
|
properties: {
|
|
306
|
-
className: 'collapse',
|
|
304
|
+
className: ['collapse'],
|
|
307
305
|
dataLines: count
|
|
308
306
|
},
|
|
309
307
|
children
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { HastRoot, Transforms } from "../../CodeHighlighter/types.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Recursively walks a jsondiffpatch delta looking for any inserted hast
|
|
4
|
-
* element
|
|
4
|
+
* element whose `className` includes `'collapse'`. Used to mark a manifest entry
|
|
5
5
|
* as layout-affecting (phase 1, coordinated barrier so peers stay in
|
|
6
6
|
* lockstep) so the runtime doesn't have to decompress the embedded hast
|
|
7
7
|
* payload on every selection change to classify the swap.
|
|
@@ -10,8 +10,9 @@ import type { HastRoot, Transforms } from "../../CodeHighlighter/types.mjs";
|
|
|
10
10
|
* opcodes (`[value]` for insert, `[oldValue, 0, 0]` for delete, `_t: 'a'`
|
|
11
11
|
* + `_N` keys for array ops). The collapse placeholder is only ever
|
|
12
12
|
* produced by `compactCollapseInTreeInPlace` on the *transform* side of
|
|
13
|
-
* the diff, so any hast element
|
|
14
|
-
* the delta tree is necessarily part of an insertion or
|
|
13
|
+
* the diff, so any hast element whose `className` includes `'collapse'`
|
|
14
|
+
* anywhere in the delta tree is necessarily part of an insertion or an
|
|
15
|
+
* in-place rewrite.
|
|
15
16
|
*/
|
|
16
17
|
export declare function deltaContainsCollapse(delta: unknown): boolean;
|
|
17
18
|
/**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { hasClassName } from "../parseSource/isFrameSpan.mjs";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Recursively walks a jsondiffpatch delta looking for any inserted hast
|
|
3
|
-
* element
|
|
5
|
+
* element whose `className` includes `'collapse'`. Used to mark a manifest entry
|
|
4
6
|
* as layout-affecting (phase 1, coordinated barrier so peers stay in
|
|
5
7
|
* lockstep) so the runtime doesn't have to decompress the embedded hast
|
|
6
8
|
* payload on every selection change to classify the swap.
|
|
@@ -9,22 +11,18 @@
|
|
|
9
11
|
* opcodes (`[value]` for insert, `[oldValue, 0, 0]` for delete, `_t: 'a'`
|
|
10
12
|
* + `_N` keys for array ops). The collapse placeholder is only ever
|
|
11
13
|
* produced by `compactCollapseInTreeInPlace` on the *transform* side of
|
|
12
|
-
* the diff, so any hast element
|
|
13
|
-
* the delta tree is necessarily part of an insertion or
|
|
14
|
+
* the diff, so any hast element whose `className` includes `'collapse'`
|
|
15
|
+
* anywhere in the delta tree is necessarily part of an insertion or an
|
|
16
|
+
* in-place rewrite.
|
|
14
17
|
*/
|
|
15
18
|
export function deltaContainsCollapse(delta) {
|
|
16
19
|
if (delta === null || typeof delta !== 'object') {
|
|
17
20
|
return false;
|
|
18
21
|
}
|
|
22
|
+
// The delta holds arbitrary values; the `type` check below validates the cast.
|
|
19
23
|
const candidate = delta;
|
|
20
|
-
if (candidate.type === 'element') {
|
|
21
|
-
|
|
22
|
-
if (cls === 'collapse') {
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
if (Array.isArray(cls) && cls.includes('collapse')) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
24
|
+
if (candidate.type === 'element' && hasClassName(candidate, 'collapse')) {
|
|
25
|
+
return true;
|
|
28
26
|
}
|
|
29
27
|
if (Array.isArray(delta)) {
|
|
30
28
|
for (const item of delta) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { COLLAPSED_VISIBLE_FRAME_TYPES } from "../parseSource/frameVisibility.mjs";
|
|
2
|
-
import { isFrameSpan } from "../parseSource/isFrameSpan.mjs";
|
|
2
|
+
import { hasClassName, isFrameSpan } from "../parseSource/isFrameSpan.mjs";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Returns the set of 1-indexed source line numbers that are visible when
|
|
@@ -35,7 +35,7 @@ export function getInitialVisibleSourceLines(tree) {
|
|
|
35
35
|
hasVisibleEmphasisFrame = true;
|
|
36
36
|
}
|
|
37
37
|
for (const grandChild of frame.children) {
|
|
38
|
-
if (grandChild.type === 'element' && grandChild
|
|
38
|
+
if (grandChild.type === 'element' && hasClassName(grandChild, 'line')) {
|
|
39
39
|
lineNumber += 1;
|
|
40
40
|
if (frameVisible) {
|
|
41
41
|
visible.add(lineNumber);
|
|
@@ -61,7 +61,7 @@ export function getInitialVisibleSourceLines(tree) {
|
|
|
61
61
|
}
|
|
62
62
|
const frame = child;
|
|
63
63
|
for (const grandChild of frame.children) {
|
|
64
|
-
if (grandChild.type === 'element' && grandChild
|
|
64
|
+
if (grandChild.type === 'element' && hasClassName(grandChild, 'line')) {
|
|
65
65
|
fallbackLine += 1;
|
|
66
66
|
visible.add(fallbackLine);
|
|
67
67
|
}
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Root as HastRoot, Element } from 'hast';
|
|
8
8
|
import { getHastTextContent, getShallowTextContent } from "../hastUtils/index.mjs";
|
|
9
|
+
import { hasClassName } from "../parseSource/isFrameSpan.mjs";
|
|
9
10
|
export { getHastTextContent, getShallowTextContent };
|
|
10
11
|
/**
|
|
11
12
|
* Checks if a HAST element has a specific CSS class.
|
|
12
|
-
* Handles both string and array class representations.
|
|
13
13
|
*/
|
|
14
|
-
export declare
|
|
14
|
+
export declare const hasClass: typeof hasClassName;
|
|
15
15
|
/**
|
|
16
16
|
* Checks if a HAST element is a span with class `line`.
|
|
17
17
|
*/
|
|
@@ -6,22 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { compressHast, getHastTextContent, getShallowTextContent } from "../hastUtils/index.mjs";
|
|
9
|
+
import { hasClassName } from "../parseSource/isFrameSpan.mjs";
|
|
9
10
|
export { getHastTextContent, getShallowTextContent };
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Checks if a HAST element has a specific CSS class.
|
|
13
|
-
* Handles both string and array class representations.
|
|
14
14
|
*/
|
|
15
|
-
export
|
|
16
|
-
const classes = element.properties?.className;
|
|
17
|
-
if (Array.isArray(classes)) {
|
|
18
|
-
return classes.includes(className);
|
|
19
|
-
}
|
|
20
|
-
if (typeof classes === 'string') {
|
|
21
|
-
return classes.split(' ').includes(className);
|
|
22
|
-
}
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
15
|
+
export const hasClass = hasClassName;
|
|
25
16
|
|
|
26
17
|
/**
|
|
27
18
|
* Checks if a HAST element is a span with class `line`.
|
|
@@ -7,7 +7,7 @@ import { highlightTypesMeta } from "./highlightTypesMeta.mjs";
|
|
|
7
7
|
import { syncTypes } from "../syncTypes/index.mjs";
|
|
8
8
|
import { loadServerTypesText } from "../loadServerTypesText/index.mjs";
|
|
9
9
|
import { resolveTypesCacheKey } from "../loadServerTypesText/resolveTypesCacheKey.mjs";
|
|
10
|
-
import { withFileCache } from "../cacheUtils/index.mjs";
|
|
10
|
+
import { CACHE_SCHEMA_VERSION, withFileCache } from "../cacheUtils/index.mjs";
|
|
11
11
|
const functionName = 'Load Server Types';
|
|
12
12
|
|
|
13
13
|
/** Cache namespace for the enhanced (highlighted) loadServerTypes result. */
|
|
@@ -66,6 +66,9 @@ export async function loadServerTypes(options) {
|
|
|
66
66
|
ref: cacheRef,
|
|
67
67
|
readOrigin: () => syncResult,
|
|
68
68
|
getCacheContent: source => JSON.stringify({
|
|
69
|
+
// The cached value is hast, whose shape can change between releases — see
|
|
70
|
+
// CACHE_SCHEMA_VERSION. Dropping this lets a warm cache serve the old shape.
|
|
71
|
+
cacheSchemaVersion: CACHE_SCHEMA_VERSION,
|
|
69
72
|
// Exclude allDependencies (re-attached fresh below) so a dep-list change does not needlessly
|
|
70
73
|
// invalidate the cached highlighting, and the transient `updated` flag for hash stability.
|
|
71
74
|
source: {
|
|
@@ -76,6 +76,16 @@ function extractInlineCodeOrText(node) {
|
|
|
76
76
|
return '';
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
/** Extract inline-code values from mdast phrasing content. */
|
|
80
|
+
function extractInlineCodeValues(nodes) {
|
|
81
|
+
return nodes.flatMap(node => {
|
|
82
|
+
if (node.type === 'inlineCode') {
|
|
83
|
+
return node.value;
|
|
84
|
+
}
|
|
85
|
+
return 'children' in node ? extractInlineCodeValues(node.children) : [];
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
79
89
|
/**
|
|
80
90
|
* A target for batch HAST conversion: a setter to assign the result and the mdast nodes to convert.
|
|
81
91
|
*/
|
|
@@ -533,6 +543,9 @@ export async function parseTypesMarkdown(content, ordering) {
|
|
|
533
543
|
const allTypes = [];
|
|
534
544
|
const descriptionTargets = [];
|
|
535
545
|
const externalTypes = {};
|
|
546
|
+
const parsedVariantTypes = {};
|
|
547
|
+
const typeNameMap = {};
|
|
548
|
+
const parsedVariantTypeNameMapKeys = {};
|
|
536
549
|
|
|
537
550
|
// Track current context
|
|
538
551
|
let currentH3Name = null;
|
|
@@ -553,6 +566,7 @@ export async function parseTypesMarkdown(content, ordering) {
|
|
|
553
566
|
let lastParamExampleName = null;
|
|
554
567
|
let lastPropReferencesName = null;
|
|
555
568
|
let lastParamReferencesName = null;
|
|
569
|
+
let metadataSection = null;
|
|
556
570
|
|
|
557
571
|
// Helper to flush the current section
|
|
558
572
|
const flushSection = () => {
|
|
@@ -697,6 +711,12 @@ export async function parseTypesMarkdown(content, ordering) {
|
|
|
697
711
|
if (node.type === 'heading' && node.depth === 2) {
|
|
698
712
|
flushSection();
|
|
699
713
|
const text = extractText(node.children);
|
|
714
|
+
metadataSection = null;
|
|
715
|
+
if (text === 'Export Groups') {
|
|
716
|
+
metadataSection = 'export-groups';
|
|
717
|
+
} else if (text === 'Canonical Types') {
|
|
718
|
+
metadataSection = 'canonical-types';
|
|
719
|
+
}
|
|
700
720
|
if (text === 'External Types') {
|
|
701
721
|
inExternalTypes = true;
|
|
702
722
|
} else if (text === 'Additional Types') {
|
|
@@ -712,6 +732,7 @@ export async function parseTypesMarkdown(content, ordering) {
|
|
|
712
732
|
if (node.type === 'heading' && node.depth === 3) {
|
|
713
733
|
flushSection();
|
|
714
734
|
inExternalTypes = false;
|
|
735
|
+
metadataSection = null;
|
|
715
736
|
currentH3Name = extractText(node.children);
|
|
716
737
|
continue;
|
|
717
738
|
}
|
|
@@ -722,6 +743,36 @@ export async function parseTypesMarkdown(content, ordering) {
|
|
|
722
743
|
continue;
|
|
723
744
|
}
|
|
724
745
|
|
|
746
|
+
// Handle generated metadata lists
|
|
747
|
+
if (node.type === 'list' && metadataSection) {
|
|
748
|
+
for (const item of node.children) {
|
|
749
|
+
const children = item.children.flatMap(child => child.type === 'paragraph' ? child.children : []);
|
|
750
|
+
const separatorIndex = children.findIndex(child => child.type === 'text' && child.value.includes(':'));
|
|
751
|
+
const namesBeforeSeparator = extractInlineCodeValues(children.slice(0, separatorIndex === -1 ? children.length : separatorIndex));
|
|
752
|
+
const namesAfterSeparator = separatorIndex === -1 ? [] : extractInlineCodeValues(children.slice(separatorIndex + 1));
|
|
753
|
+
if (metadataSection === 'export-groups') {
|
|
754
|
+
const variantName = namesBeforeSeparator[0];
|
|
755
|
+
if (variantName) {
|
|
756
|
+
parsedVariantTypes[variantName] = separatorIndex === -1 ? [variantName] : namesAfterSeparator;
|
|
757
|
+
}
|
|
758
|
+
} else {
|
|
759
|
+
const [canonicalName, ...variants] = namesBeforeSeparator;
|
|
760
|
+
if (!canonicalName || separatorIndex === -1) {
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
for (const flatName of namesAfterSeparator) {
|
|
764
|
+
typeNameMap[flatName] = canonicalName;
|
|
765
|
+
}
|
|
766
|
+
for (const variant of variants) {
|
|
767
|
+
const keys = parsedVariantTypeNameMapKeys[variant] ?? [];
|
|
768
|
+
keys.push(...namesAfterSeparator);
|
|
769
|
+
parsedVariantTypeNameMapKeys[variant] = keys;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
continue;
|
|
774
|
+
}
|
|
775
|
+
|
|
725
776
|
// Handle code blocks
|
|
726
777
|
if (node.type === 'code') {
|
|
727
778
|
if (inExternalTypes && currentExternalTypeName) {
|
|
@@ -833,97 +884,8 @@ export async function parseTypesMarkdown(content, ordering) {
|
|
|
833
884
|
|
|
834
885
|
// Flush the last section
|
|
835
886
|
flushSection();
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
// The new format uses "## Export Groups" and "## Canonical Types" sections
|
|
839
|
-
|
|
840
|
-
// Parse Export Groups section
|
|
841
|
-
// Format: - `VariantName`: `Type1`, `Type2` (or just `- VariantName` if key equals single value)
|
|
842
|
-
let variantTypes = null;
|
|
843
|
-
const exportGroupsMatch = content.match(/## Export Groups\n([\s\S]*?)(?=\n## |$)/);
|
|
844
|
-
if (exportGroupsMatch) {
|
|
845
|
-
variantTypes = {};
|
|
846
|
-
const lines = exportGroupsMatch[1].trim().split('\n');
|
|
847
|
-
for (const line of lines) {
|
|
848
|
-
// Match: - `VariantName`: `Type1`, `Type2` OR - `VariantName`
|
|
849
|
-
const withValuesMatch = line.match(/^- `([^`]+)`:\s*(.+)$/);
|
|
850
|
-
const singleMatch = line.match(/^- `([^`]+)`$/);
|
|
851
|
-
if (withValuesMatch) {
|
|
852
|
-
const variantName = withValuesMatch[1];
|
|
853
|
-
// Extract all backtick-wrapped values
|
|
854
|
-
const values = withValuesMatch[2].match(/`([^`]+)`/g);
|
|
855
|
-
variantTypes[variantName] = values ? values.map(v => v.slice(1, -1)) : [];
|
|
856
|
-
} else if (singleMatch) {
|
|
857
|
-
// Key equals value - the variant name IS the single type
|
|
858
|
-
const variantName = singleMatch[1];
|
|
859
|
-
variantTypes[variantName] = [variantName];
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
// Only keep variantTypes if we found entries
|
|
863
|
-
if (Object.keys(variantTypes).length === 0) {
|
|
864
|
-
variantTypes = null;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
// Parse Canonical Types section
|
|
869
|
-
// Format: - `CanonicalName` (`Variant1`, `Variant2`): `FlatName1`, `FlatName2`
|
|
870
|
-
// OR: - `CanonicalName`: `FlatName1`, `FlatName2` (no variant annotation)
|
|
871
|
-
const typeNameMap = {};
|
|
872
|
-
let variantTypeNameMapKeys = null;
|
|
873
|
-
const canonicalTypesMatch = content.match(/## Canonical Types\n([\s\S]*?)(?=\n## |$)/);
|
|
874
|
-
if (canonicalTypesMatch) {
|
|
875
|
-
variantTypeNameMapKeys = {};
|
|
876
|
-
const lines = canonicalTypesMatch[1].trim().split('\n');
|
|
877
|
-
for (const line of lines) {
|
|
878
|
-
// Match: - `CanonicalName` (`Variant1`, `Variant2`): `FlatName1`, `FlatName2`
|
|
879
|
-
// OR: - `CanonicalName`: `FlatName1`, `FlatName2`
|
|
880
|
-
const withVariantMatch = line.match(/^- `([^`]+)`\s+\(([^)]+)\):\s*(.+)$/);
|
|
881
|
-
const withoutVariantMatch = line.match(/^- `([^`]+)`:\s*(.+)$/);
|
|
882
|
-
let canonicalName;
|
|
883
|
-
let flatNamesStr;
|
|
884
|
-
let variants = [];
|
|
885
|
-
if (withVariantMatch) {
|
|
886
|
-
canonicalName = withVariantMatch[1];
|
|
887
|
-
// Extract variants from parentheses
|
|
888
|
-
const variantStr = withVariantMatch[2];
|
|
889
|
-
const variantMatches = variantStr.match(/`([^`]+)`/g);
|
|
890
|
-
variants = variantMatches ? variantMatches.map(v => v.slice(1, -1)) : [];
|
|
891
|
-
flatNamesStr = withVariantMatch[3];
|
|
892
|
-
} else if (withoutVariantMatch) {
|
|
893
|
-
canonicalName = withoutVariantMatch[1];
|
|
894
|
-
flatNamesStr = withoutVariantMatch[2];
|
|
895
|
-
// No variant annotation - applies to all variants
|
|
896
|
-
} else {
|
|
897
|
-
continue;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
// Extract all flat names
|
|
901
|
-
const flatNameMatches = flatNamesStr.match(/`([^`]+)`/g);
|
|
902
|
-
const flatNames = flatNameMatches ? flatNameMatches.map(v => v.slice(1, -1)) : [];
|
|
903
|
-
|
|
904
|
-
// Build typeNameMap (flat name -> canonical name)
|
|
905
|
-
for (const flatName of flatNames) {
|
|
906
|
-
typeNameMap[flatName] = canonicalName;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
// Build variantTypeNameMapKeys (variant -> list of keys)
|
|
910
|
-
// If no variants specified, we don't track variant-specific keys
|
|
911
|
-
if (variants.length > 0) {
|
|
912
|
-
for (const variant of variants) {
|
|
913
|
-
if (!variantTypeNameMapKeys[variant]) {
|
|
914
|
-
variantTypeNameMapKeys[variant] = [];
|
|
915
|
-
}
|
|
916
|
-
for (const flatName of flatNames) {
|
|
917
|
-
variantTypeNameMapKeys[variant].push(flatName);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
// Only keep variantTypeNameMapKeys if we found entries
|
|
923
|
-
if (Object.keys(variantTypeNameMapKeys).length === 0) {
|
|
924
|
-
variantTypeNameMapKeys = null;
|
|
925
|
-
}
|
|
926
|
-
}
|
|
887
|
+
const variantTypes = Object.keys(parsedVariantTypes).length > 0 ? parsedVariantTypes : null;
|
|
888
|
+
const variantTypeNameMapKeys = Object.keys(parsedVariantTypeNameMapKeys).length > 0 ? parsedVariantTypeNameMapKeys : null;
|
|
927
889
|
|
|
928
890
|
// Convert all description mdast nodes to HAST in parallel
|
|
929
891
|
await convertDescriptions(descriptionTargets);
|
|
@@ -13,7 +13,9 @@ export declare function resolveTypesCacheKey(typesMarkdownPath: string, rootCont
|
|
|
13
13
|
/**
|
|
14
14
|
* Builds the hash-validation content for the types.md parse cache. Includes the
|
|
15
15
|
* ordering config because it changes `parseTypesMarkdown`'s output, so the cache is
|
|
16
|
-
* invalidated when either the markdown or the ordering changes
|
|
17
|
-
*
|
|
16
|
+
* invalidated when either the markdown or the ordering changes, and CACHE_SCHEMA_VERSION
|
|
17
|
+
* because the parsed value embeds hast (descriptions), whose shape can change between
|
|
18
|
+
* releases. The writer (syncTypes) and reader (loadServerTypesText) must build this
|
|
19
|
+
* identically for their hashes to match.
|
|
18
20
|
*/
|
|
19
21
|
export declare function buildTypesTextCacheContent(markdown: string, ordering?: OrderingConfig): string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CACHE_SCHEMA_VERSION } from "../cacheUtils/index.mjs";
|
|
1
2
|
import { extractPrefixAndTitle } from "../loadServerPageIndex/extractPrefixAndTitle.mjs";
|
|
2
3
|
/** Cache namespace for the types.md parse cache (TypesSourceData), mirroring the page-index cache. */
|
|
3
4
|
export const TYPES_TEXT_CACHE_NAMESPACE = 'types-text';
|
|
@@ -21,9 +22,11 @@ export function resolveTypesCacheKey(typesMarkdownPath, rootContext) {
|
|
|
21
22
|
/**
|
|
22
23
|
* Builds the hash-validation content for the types.md parse cache. Includes the
|
|
23
24
|
* ordering config because it changes `parseTypesMarkdown`'s output, so the cache is
|
|
24
|
-
* invalidated when either the markdown or the ordering changes
|
|
25
|
-
*
|
|
25
|
+
* invalidated when either the markdown or the ordering changes, and CACHE_SCHEMA_VERSION
|
|
26
|
+
* because the parsed value embeds hast (descriptions), whose shape can change between
|
|
27
|
+
* releases. The writer (syncTypes) and reader (loadServerTypesText) must build this
|
|
28
|
+
* identically for their hashes to match.
|
|
26
29
|
*/
|
|
27
30
|
export function buildTypesTextCacheContent(markdown, ordering) {
|
|
28
|
-
return `${JSON.stringify(ordering ?? null)}\n${markdown}`;
|
|
31
|
+
return `${CACHE_SCHEMA_VERSION}\n${JSON.stringify(ordering ?? null)}\n${markdown}`;
|
|
29
32
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Example copied from https://github.com/wooorm/starry-night#example-adding-line-numbers
|
|
2
2
|
|
|
3
3
|
import { createFrame } from "./createFrame.mjs";
|
|
4
|
-
import { isFrameSpan } from "./isFrameSpan.mjs";
|
|
4
|
+
import { hasClassName, isFrameSpan } from "./isFrameSpan.mjs";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Counts the number of lines in a HAST tree without mutating it.
|
|
@@ -154,7 +154,7 @@ export function starryNightGutter(tree, sourceLines, frameSize = 120) {
|
|
|
154
154
|
const frame = replacement[frameIndex];
|
|
155
155
|
if (frame.type === 'element' && frame.tagName === 'span' && isFrameSpan(frame)) {
|
|
156
156
|
// Extract line range from child .line elements
|
|
157
|
-
const lineChildren = frame.children.filter(c => c.type === 'element' && c
|
|
157
|
+
const lineChildren = frame.children.filter(c => c.type === 'element' && hasClassName(c, 'line') && typeof c.properties.dataLn === 'number');
|
|
158
158
|
if (lineChildren.length > 0) {
|
|
159
159
|
const startLine = Number(lineChildren[0].properties.dataLn) - 1;
|
|
160
160
|
const endLine = Number(lineChildren[lineChildren.length - 1].properties.dataLn);
|
|
@@ -204,7 +204,7 @@ function createLine(children, line) {
|
|
|
204
204
|
type: 'element',
|
|
205
205
|
tagName: 'span',
|
|
206
206
|
properties: {
|
|
207
|
-
className: 'line',
|
|
207
|
+
className: ['line'],
|
|
208
208
|
dataLn: line
|
|
209
209
|
},
|
|
210
210
|
children
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import type { Element as HastElement } from 'hast';
|
|
2
2
|
/**
|
|
3
|
-
* Returns `true` when a HAST element carries the given class name
|
|
4
|
-
* both shapes `className` can take:
|
|
3
|
+
* Returns `true` when a HAST element carries the given class name.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* any HAST that round-trips through serialization.
|
|
10
|
-
*
|
|
11
|
-
* Matching only the string silently skips real fallback frames, so class checks
|
|
12
|
-
* on HAST that may come from either path must go through this helper.
|
|
5
|
+
* `className` is always the array shape (`['frame']`): it is what the
|
|
6
|
+
* highlighter, `fallbackToHast` and any HAST that round-trips through
|
|
7
|
+
* serialization produce, and what the compression dictionary encodes.
|
|
13
8
|
*/
|
|
14
9
|
export declare function hasClassName(element: HastElement, name: string): boolean;
|
|
15
10
|
/**
|
|
16
11
|
* Returns `true` when a HAST element is a code frame span — its `className`
|
|
17
|
-
* includes `'frame'`
|
|
12
|
+
* includes `'frame'` (see {@link hasClassName}).
|
|
18
13
|
*/
|
|
19
14
|
export declare function isFrameSpan(element: HastElement): boolean;
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Returns `true` when a HAST element carries the given class name
|
|
3
|
-
* both shapes `className` can take:
|
|
2
|
+
* Returns `true` when a HAST element carries the given class name.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* any HAST that round-trips through serialization.
|
|
9
|
-
*
|
|
10
|
-
* Matching only the string silently skips real fallback frames, so class checks
|
|
11
|
-
* on HAST that may come from either path must go through this helper.
|
|
4
|
+
* `className` is always the array shape (`['frame']`): it is what the
|
|
5
|
+
* highlighter, `fallbackToHast` and any HAST that round-trips through
|
|
6
|
+
* serialization produce, and what the compression dictionary encodes.
|
|
12
7
|
*/
|
|
13
8
|
export function hasClassName(element, name) {
|
|
14
|
-
|
|
15
|
-
return className === name || Array.isArray(className) && className.includes(name);
|
|
9
|
+
return element.properties?.className?.includes(name) ?? false;
|
|
16
10
|
}
|
|
17
11
|
|
|
18
12
|
/**
|
|
19
13
|
* Returns `true` when a HAST element is a code frame span — its `className`
|
|
20
|
-
* includes `'frame'`
|
|
14
|
+
* includes `'frame'` (see {@link hasClassName}).
|
|
21
15
|
*/
|
|
22
16
|
export function isFrameSpan(element) {
|
|
23
17
|
return hasClassName(element, 'frame');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createFrame } from "./createFrame.mjs";
|
|
2
|
-
import { isFrameSpan } from "./isFrameSpan.mjs";
|
|
2
|
+
import { hasClassName, isFrameSpan } from "./isFrameSpan.mjs";
|
|
3
3
|
import { redistributeFrameFallbacks } from "./redistributeFrameFallbacks.mjs";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -15,7 +15,7 @@ import { redistributeFrameFallbacks } from "./redistributeFrameFallbacks.mjs";
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
function isCollapsedLinesPlaceholder(node) {
|
|
18
|
-
return node.type === 'element' && node.tagName === 'span' && node.properties != null && node
|
|
18
|
+
return node.type === 'element' && node.tagName === 'span' && node.properties != null && hasClassName(node, 'collapse');
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -38,7 +38,7 @@ function flattenLineEntries(root) {
|
|
|
38
38
|
const children = frame.children ?? [];
|
|
39
39
|
for (let i = 0; i < children.length; i += 1) {
|
|
40
40
|
const child = children[i];
|
|
41
|
-
if (child.type === 'element' && child.tagName === 'span' && child
|
|
41
|
+
if (child.type === 'element' && child.tagName === 'span' && hasClassName(child, 'line') && typeof child.properties.dataLn === 'number') {
|
|
42
42
|
const lineNumber = child.properties.dataLn;
|
|
43
43
|
// Resolve any placeholders waiting on a following line.
|
|
44
44
|
for (const pending of pendingNextAnchor) {
|
|
@@ -92,7 +92,7 @@ function collectFrameFallbacks(root) {
|
|
|
92
92
|
let startLine = Infinity;
|
|
93
93
|
let endLine = -Infinity;
|
|
94
94
|
for (const child of frame.children) {
|
|
95
|
-
if (child.type === 'element' && child
|
|
95
|
+
if (child.type === 'element' && hasClassName(child, 'line') && typeof child.properties.dataLn === 'number') {
|
|
96
96
|
const lineNumber = child.properties.dataLn;
|
|
97
97
|
if (lineNumber < startLine) {
|
|
98
98
|
startLine = lineNumber;
|
|
@@ -255,7 +255,7 @@ export const transformMarkdownCode = (options = {}) => {
|
|
|
255
255
|
|
|
256
256
|
// Add normalized language as class
|
|
257
257
|
if (langFromMeta) {
|
|
258
|
-
codeHProperties.className = `language-${normalizeLanguage(langFromMeta)}
|
|
258
|
+
codeHProperties.className = [`language-${normalizeLanguage(langFromMeta)}`];
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
// Add all props as data attributes (in camelCase)
|
|
@@ -534,7 +534,7 @@ export const transformMarkdownCode = (options = {}) => {
|
|
|
534
534
|
|
|
535
535
|
// Add normalized language as class
|
|
536
536
|
if (block.actualLang) {
|
|
537
|
-
codeHProperties.className = `language-${normalizeLanguage(block.actualLang)}
|
|
537
|
+
codeHProperties.className = [`language-${normalizeLanguage(block.actualLang)}`];
|
|
538
538
|
}
|
|
539
539
|
|
|
540
540
|
// Add additional props as data attributes (in camelCase)
|
|
@@ -693,7 +693,7 @@ export const transformMarkdownCode = (options = {}) => {
|
|
|
693
693
|
|
|
694
694
|
// Add normalized language as class
|
|
695
695
|
if (block.actualLang) {
|
|
696
|
-
codeHProperties.className = `language-${normalizeLanguage(block.actualLang)}
|
|
696
|
+
codeHProperties.className = [`language-${normalizeLanguage(block.actualLang)}`];
|
|
697
697
|
}
|
|
698
698
|
|
|
699
699
|
// Add additional props as data attributes (in camelCase)
|