@mui/internal-docs-infra 0.10.1-canary.2 → 0.10.1-canary.4
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/enhanceCodeEmphasis/enhanceCodeEmphasis.mjs +26 -7
- package/pipeline/hastUtils/getHastTextContent.d.mts +9 -0
- package/pipeline/hastUtils/getHastTextContent.mjs +25 -0
- package/pipeline/hastUtils/index.d.mts +1 -0
- package/pipeline/hastUtils/index.mjs +1 -0
- package/pipeline/loadServerTypes/hastTypeUtils.d.mts +3 -9
- package/pipeline/loadServerTypes/hastTypeUtils.mjs +2 -27
- package/pipeline/parseSource/addLineGutters.mjs +13 -3
- package/pipeline/transformHtmlCodeInline/transformHtmlCodeInline.mjs +2 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-docs-infra",
|
|
3
|
-
"version": "0.10.1-canary.
|
|
3
|
+
"version": "0.10.1-canary.4",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "MUI Infra - internal documentation creation tools.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -643,5 +643,5 @@
|
|
|
643
643
|
"bin": {
|
|
644
644
|
"docs-infra": "./cli/index.mjs"
|
|
645
645
|
},
|
|
646
|
-
"gitSha": "
|
|
646
|
+
"gitSha": "a6c1a30f23657628b384ef27f0c3c4cb7f37869b"
|
|
647
647
|
}
|
|
@@ -587,7 +587,11 @@ function calculateEmphasizedLines(directives, lineElements) {
|
|
|
587
587
|
lineHighlight: directive.lineHighlight,
|
|
588
588
|
focus: directive.focus,
|
|
589
589
|
paddingFrameMaxSize: directive.paddingFrameMaxSize,
|
|
590
|
-
focusFramesMaxSize: directive.focusFramesMaxSize
|
|
590
|
+
focusFramesMaxSize: directive.focusFramesMaxSize,
|
|
591
|
+
// Treat a single `@highlight` as a containing highlight range of depth 1
|
|
592
|
+
// so that an outer multiline range wrapping this line is detected as
|
|
593
|
+
// nesting and promoted to `strong`.
|
|
594
|
+
containingRangeDepth: directive.lineHighlight ? 1 : undefined
|
|
591
595
|
});
|
|
592
596
|
} else if (directive.type === 'text') {
|
|
593
597
|
// Text highlight - emphasize specific text(s) within the line.
|
|
@@ -640,7 +644,12 @@ function calculateEmphasizedLines(directives, lineElements) {
|
|
|
640
644
|
|
|
641
645
|
// Determine position for this line in the current range
|
|
642
646
|
let position;
|
|
643
|
-
if (line === startLine && line
|
|
647
|
+
if (line === startLine && line === endLine) {
|
|
648
|
+
// A multiline range that resolves to a single content line (e.g.
|
|
649
|
+
// when comment-only lines are stripped) should be treated as a
|
|
650
|
+
// standalone single-line highlight.
|
|
651
|
+
position = 'single';
|
|
652
|
+
} else if (line === startLine && line !== endLine) {
|
|
644
653
|
position = 'start';
|
|
645
654
|
} else if (line === endLine && line !== startLine) {
|
|
646
655
|
position = 'end';
|
|
@@ -651,13 +660,20 @@ function calculateEmphasizedLines(directives, lineElements) {
|
|
|
651
660
|
// A focus range overlapping with a highlight is not nesting — it just
|
|
652
661
|
// merges focus into the existing entry.
|
|
653
662
|
const meta = existing ? {
|
|
654
|
-
// Nested highlight ranges are strong; focus+highlight overlap is not
|
|
655
|
-
|
|
663
|
+
// Nested highlight ranges are strong; focus+highlight overlap is not.
|
|
664
|
+
// Detect true nesting via `containingRangeDepth` rather than
|
|
665
|
+
// `existing.lineHighlight`. This works when the existing entry
|
|
666
|
+
// came from a `@highlight-text` directive on a line that's also
|
|
667
|
+
// wrapped in a highlight range — `existing.lineHighlight` is true
|
|
668
|
+
// after the first range merge, so a second wrapping range needs to
|
|
669
|
+
// see the depth to know nesting occurred.
|
|
670
|
+
strong: (existing.containingRangeDepth ?? 0) >= 1 && startDirective.lineHighlight || existing.strong || strong,
|
|
656
671
|
description: existing.description ?? (line === startLine ? description : undefined),
|
|
657
672
|
// Inner range position takes precedence, but 'single' from a standalone
|
|
658
673
|
// @highlight-text should be replaced by the multiline range's position.
|
|
659
|
-
// Keep 'single' from
|
|
660
|
-
|
|
674
|
+
// Keep 'single' from a real @highlight (lineHighlight is set), even when
|
|
675
|
+
// the line also carries @highlight-text.
|
|
676
|
+
position: existing.position && !(existing.position === 'single' && existing.highlightTexts && !existing.lineHighlight) ? existing.position : position,
|
|
661
677
|
highlightTexts: existing.highlightTexts,
|
|
662
678
|
// Preserve text highlights from @highlight-text
|
|
663
679
|
lineHighlight: existing.lineHighlight || startDirective.lineHighlight,
|
|
@@ -682,7 +698,10 @@ function calculateEmphasizedLines(directives, lineElements) {
|
|
|
682
698
|
focus: startDirective.focus,
|
|
683
699
|
paddingFrameMaxSize: startDirective.paddingFrameMaxSize,
|
|
684
700
|
focusFramesMaxSize: startDirective.focusFramesMaxSize,
|
|
685
|
-
propagatedOverride: true
|
|
701
|
+
propagatedOverride: true,
|
|
702
|
+
// Track depth so a wrapping outer range can detect nesting
|
|
703
|
+
// (used by the `strong` calculation above).
|
|
704
|
+
containingRangeDepth: startDirective.lineHighlight ? 1 : undefined
|
|
686
705
|
};
|
|
687
706
|
emphasizedLines.set(line, meta);
|
|
688
707
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Root as HastRoot, Element, Text, RootContent } from 'hast';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts all text content from a HAST node recursively.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getHastTextContent(node: HastRoot | Element | Text | RootContent): string;
|
|
6
|
+
/**
|
|
7
|
+
* Gets the direct text content of a HAST element (non-recursive, first level only).
|
|
8
|
+
*/
|
|
9
|
+
export declare function getShallowTextContent(element: Element): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts all text content from a HAST node recursively.
|
|
3
|
+
*/
|
|
4
|
+
export function getHastTextContent(node) {
|
|
5
|
+
if (node.type === 'text') {
|
|
6
|
+
return node.value || '';
|
|
7
|
+
}
|
|
8
|
+
if ('children' in node && Array.isArray(node.children)) {
|
|
9
|
+
return node.children.map(child => getHastTextContent(child)).join('');
|
|
10
|
+
}
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Gets the direct text content of a HAST element (non-recursive, first level only).
|
|
16
|
+
*/
|
|
17
|
+
export function getShallowTextContent(element) {
|
|
18
|
+
let text = '';
|
|
19
|
+
for (const child of element.children) {
|
|
20
|
+
if (child.type === 'text') {
|
|
21
|
+
text += child.value;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return text;
|
|
25
|
+
}
|
|
@@ -4,20 +4,14 @@
|
|
|
4
4
|
* These utilities work on already-highlighted HAST nodes to detect type patterns
|
|
5
5
|
* (unions, functions, objects) and derive shortType/detailedType variants.
|
|
6
6
|
*/
|
|
7
|
-
import type { Root as HastRoot, Element
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*/
|
|
11
|
-
export declare function getHastTextContent(node: HastRoot | Element | Text | RootContent): string;
|
|
7
|
+
import type { Root as HastRoot, Element } from 'hast';
|
|
8
|
+
import { getHastTextContent, getShallowTextContent } from "../hastUtils/index.mjs";
|
|
9
|
+
export { getHastTextContent, getShallowTextContent };
|
|
12
10
|
/**
|
|
13
11
|
* Checks if a HAST element has a specific CSS class.
|
|
14
12
|
* Handles both string and array class representations.
|
|
15
13
|
*/
|
|
16
14
|
export declare function hasClass(element: Element, className: string): boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Gets the direct text content of a HAST element (non-recursive, first level only).
|
|
19
|
-
*/
|
|
20
|
-
export declare function getShallowTextContent(element: Element): string;
|
|
21
15
|
/**
|
|
22
16
|
* Checks if a HAST element is a span with class `line`.
|
|
23
17
|
*/
|
|
@@ -5,20 +5,8 @@
|
|
|
5
5
|
* (unions, functions, objects) and derive shortType/detailedType variants.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { compressHast } from "../hastUtils/index.mjs";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Extracts all text content from a HAST node recursively.
|
|
12
|
-
*/
|
|
13
|
-
export function getHastTextContent(node) {
|
|
14
|
-
if (node.type === 'text') {
|
|
15
|
-
return node.value || '';
|
|
16
|
-
}
|
|
17
|
-
if ('children' in node && Array.isArray(node.children)) {
|
|
18
|
-
return node.children.map(child => getHastTextContent(child)).join('');
|
|
19
|
-
}
|
|
20
|
-
return '';
|
|
21
|
-
}
|
|
8
|
+
import { compressHast, getHastTextContent, getShallowTextContent } from "../hastUtils/index.mjs";
|
|
9
|
+
export { getHastTextContent, getShallowTextContent };
|
|
22
10
|
|
|
23
11
|
/**
|
|
24
12
|
* Checks if a HAST element has a specific CSS class.
|
|
@@ -35,19 +23,6 @@ export function hasClass(element, className) {
|
|
|
35
23
|
return false;
|
|
36
24
|
}
|
|
37
25
|
|
|
38
|
-
/**
|
|
39
|
-
* Gets the direct text content of a HAST element (non-recursive, first level only).
|
|
40
|
-
*/
|
|
41
|
-
export function getShallowTextContent(element) {
|
|
42
|
-
let text = '';
|
|
43
|
-
for (const child of element.children) {
|
|
44
|
-
if (child.type === 'text') {
|
|
45
|
-
text += child.value;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return text;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
26
|
/**
|
|
52
27
|
* Checks if a HAST element is a span with class `line`.
|
|
53
28
|
*/
|
|
@@ -127,16 +127,26 @@ export function starryNightGutter(tree, sourceLines, frameSize = 120) {
|
|
|
127
127
|
replacement.push(createFrame(frameLines));
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
// If there are multiple frames and sourceLines provided, add dataAsString to each frame
|
|
130
|
+
// If there are multiple frames and sourceLines provided, add dataAsString to each frame.
|
|
131
|
+
// Every frame except the last covers `frameSize` source lines, each of which
|
|
132
|
+
// was followed by a newline separator in the original source, so its text
|
|
133
|
+
// ends with a trailing '\n'. The final frame only carries a trailing newline
|
|
134
|
+
// if the source itself ends with one. Without this trailing '\n', the
|
|
135
|
+
// plain-text fallback and the highlighted render disagree by exactly one
|
|
136
|
+
// newline per non-final frame, which causes a layout shift during lazy
|
|
137
|
+
// hydration when a frame toggles between the two.
|
|
131
138
|
if (replacement.length > 1 && sourceLines) {
|
|
132
|
-
|
|
139
|
+
const lastIndex = replacement.length - 1;
|
|
140
|
+
for (let frameIndex = 0; frameIndex < replacement.length; frameIndex += 1) {
|
|
141
|
+
const frame = replacement[frameIndex];
|
|
133
142
|
if (frame.type === 'element' && frame.tagName === 'span' && frame.properties?.className === 'frame') {
|
|
134
143
|
// Extract line range from child .line elements
|
|
135
144
|
const lineChildren = frame.children.filter(c => c.type === 'element' && c.properties?.className === 'line' && typeof c.properties.dataLn === 'number');
|
|
136
145
|
if (lineChildren.length > 0) {
|
|
137
146
|
const startLine = Number(lineChildren[0].properties.dataLn) - 1;
|
|
138
147
|
const endLine = Number(lineChildren[lineChildren.length - 1].properties.dataLn);
|
|
139
|
-
|
|
148
|
+
const joined = sourceLines.slice(startLine, endLine).join('\n');
|
|
149
|
+
frame.properties.dataAsString = frameIndex < lastIndex ? `${joined}\n` : joined;
|
|
140
150
|
}
|
|
141
151
|
}
|
|
142
152
|
}
|
|
@@ -2,6 +2,7 @@ import { createStarryNight } from '@wooorm/starry-night';
|
|
|
2
2
|
import { visit } from 'unist-util-visit';
|
|
3
3
|
import { grammars, extensionMap } from "../parseSource/grammars.mjs";
|
|
4
4
|
import { extendSyntaxTokens } from "../parseSource/extendSyntaxTokens.mjs";
|
|
5
|
+
import { getHastTextContent } from "../hastUtils/index.mjs";
|
|
5
6
|
import { removePrefixFromHighlightedNodes } from "./removePrefixFromHighlightedNodes.mjs";
|
|
6
7
|
const STARRY_NIGHT_KEY = '__docs_infra_starry_night_instance__';
|
|
7
8
|
|
|
@@ -56,18 +57,7 @@ export default function transformHtmlCodeInline(options = {}) {
|
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
// Extract all text content from children (handles multiple text nodes and newlines)
|
|
59
|
-
const
|
|
60
|
-
return children.map(child => {
|
|
61
|
-
if (child.type === 'text') {
|
|
62
|
-
return child.value;
|
|
63
|
-
}
|
|
64
|
-
if (child.type === 'element' && 'children' in child) {
|
|
65
|
-
return getTextContent(child.children);
|
|
66
|
-
}
|
|
67
|
-
return '';
|
|
68
|
-
}).join('');
|
|
69
|
-
};
|
|
70
|
-
const source = getTextContent(node.children);
|
|
60
|
+
const source = node.children.map(child => getHastTextContent(child)).join('');
|
|
71
61
|
if (!source) {
|
|
72
62
|
return;
|
|
73
63
|
}
|