@mui/internal-docs-infra 0.7.1-canary.4 → 0.8.1-canary.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/CodeHighlighter/CodeHighlighter.mjs +2 -2
- package/CodeHighlighter/types.d.mts +2 -2
- package/abstractCreateTypes/TypeCode.d.mts +43 -0
- package/abstractCreateTypes/TypeCode.mjs +166 -0
- package/abstractCreateTypes/abstractCreateTypes.d.mts +12 -0
- package/abstractCreateTypes/abstractCreateTypes.mjs +6 -2
- package/abstractCreateTypes/typesToJsx.d.mts +10 -0
- package/abstractCreateTypes/typesToJsx.mjs +216 -37
- package/cli/index.mjs +1 -1
- package/package.json +2 -2
- package/pipeline/hastUtils/fallbackFormat.d.mts +37 -0
- package/pipeline/hastUtils/fallbackFormat.mjs +144 -0
- package/pipeline/hastUtils/hastCompress.d.mts +20 -0
- package/pipeline/hastUtils/hastCompress.mjs +62 -0
- package/pipeline/hastUtils/hastCompression.d.mts +3 -0
- package/pipeline/hastUtils/hastCompression.mjs +3 -0
- package/pipeline/hastUtils/hastDecompress.d.mts +20 -0
- package/pipeline/hastUtils/hastDecompress.mjs +82 -0
- package/pipeline/hastUtils/hastDictionary.d.mts +54 -0
- package/pipeline/hastUtils/hastDictionary.mjs +124 -0
- package/pipeline/hastUtils/hastUtils.d.mts +3 -3
- package/pipeline/hastUtils/hastUtils.mjs +10 -11
- package/pipeline/hastUtils/index.d.mts +3 -1
- package/pipeline/hastUtils/index.mjs +3 -1
- package/pipeline/hastUtils/stripHighlightingSpans.d.mts +15 -0
- package/pipeline/hastUtils/stripHighlightingSpans.mjs +70 -0
- package/pipeline/loadCodeVariant/loadCodeVariant.mjs +5 -20
- package/pipeline/loadCodeVariant/transformSource.mjs +3 -18
- package/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.d.mts +1 -1
- package/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.mjs +1 -1
- package/pipeline/loadPrecomputedTypes/loadPrecomputedTypes.mjs +1 -1
- package/pipeline/loadServerTypes/hastTypeUtils.d.mts +13 -0
- package/pipeline/loadServerTypes/hastTypeUtils.mjs +27 -0
- package/pipeline/loadServerTypes/highlightTypes.d.mts +2 -1
- package/pipeline/loadServerTypes/highlightTypes.mjs +9 -9
- package/pipeline/loadServerTypes/highlightTypesMeta.d.mts +6 -10
- package/pipeline/loadServerTypes/highlightTypesMeta.mjs +49 -48
- package/pipeline/loadServerTypes/loadServerTypes.d.mts +11 -8
- package/pipeline/loadServerTypes/loadServerTypes.mjs +7 -7
- package/pipeline/parseSource/addLineGutters.mjs +10 -9
- package/pipeline/parseSource/createFrame.d.mts +1 -1
- package/pipeline/parseSource/createFrame.mjs +1 -5
- package/pipeline/parseSource/restructureFrames.mjs +1 -1
- package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.mjs +1 -1
- package/useCode/CodeComponentsContext.d.mts +6 -0
- package/useCode/CodeComponentsContext.mjs +8 -0
- package/useCode/Pre.mjs +36 -13
- package/useCode/index.d.mts +1 -0
- package/useCode/index.mjs +1 -0
- package/useCode/useFileNavigation.mjs +3 -4
- package/useCode/useSourceEnhancing.mjs +5 -6
- package/withDocsInfra/withDocsInfra.mjs +1 -1
|
@@ -109,7 +109,7 @@ async function CodeSourceLoader(props) {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
-
let output = '
|
|
112
|
+
let output = 'hastCompressed';
|
|
113
113
|
if (props.deferParsing === 'json') {
|
|
114
114
|
output = 'hastJson';
|
|
115
115
|
} else if (props.deferParsing === 'none') {
|
|
@@ -248,7 +248,7 @@ async function CodeInitialSourceLoader(props) {
|
|
|
248
248
|
if (!url) {
|
|
249
249
|
throw new Errors.ErrorCodeHighlighterServerMissingUrl();
|
|
250
250
|
}
|
|
251
|
-
let output = '
|
|
251
|
+
let output = 'hastCompressed';
|
|
252
252
|
if (props.deferParsing === 'json') {
|
|
253
253
|
output = 'hastJson';
|
|
254
254
|
} else if (props.deferParsing === 'none') {
|
|
@@ -29,7 +29,7 @@ export interface HastRoot extends Root {
|
|
|
29
29
|
export type VariantSource = string | HastRoot | {
|
|
30
30
|
hastJson: string;
|
|
31
31
|
} | {
|
|
32
|
-
|
|
32
|
+
hastCompressed: string;
|
|
33
33
|
};
|
|
34
34
|
/**
|
|
35
35
|
* Additional files associated with a code variant.
|
|
@@ -182,7 +182,7 @@ export interface LoadFileOptions {
|
|
|
182
182
|
/** Output format for the loaded file
|
|
183
183
|
* @default 'hast'
|
|
184
184
|
*/
|
|
185
|
-
output?: 'hast' | 'hastJson' | '
|
|
185
|
+
output?: 'hast' | 'hastJson' | 'hastCompressed';
|
|
186
186
|
}
|
|
187
187
|
/**
|
|
188
188
|
* Options for the loadCodeVariant function, extending LoadFileOptions with required function dependencies
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { FallbackNode } from "../pipeline/hastUtils/fallbackFormat.mjs";
|
|
3
|
+
type HighlightAt = 'hydration' | 'idle' | 'visible';
|
|
4
|
+
interface TypeCodeProps {
|
|
5
|
+
/** JSON-serialized HAST tree (root > pre > code > children). */
|
|
6
|
+
hastJson?: string;
|
|
7
|
+
/** DEFLATE-compressed, base64-encoded HAST tree. */
|
|
8
|
+
hastCompressed?: string;
|
|
9
|
+
/** When to replace the fallback with the fully-highlighted version. */
|
|
10
|
+
highlightAt: HighlightAt;
|
|
11
|
+
/**
|
|
12
|
+
* Links-only fallback (code children with highlighting spans stripped),
|
|
13
|
+
* in compact `FallbackNode[]` format.
|
|
14
|
+
* Serves two purposes:
|
|
15
|
+
* 1. Rendered as the initial display until the full highlight is ready.
|
|
16
|
+
* 2. Its text content is used as a DEFLATE dictionary for decompression
|
|
17
|
+
* when `hastCompressed` was compressed with that same text dictionary.
|
|
18
|
+
*/
|
|
19
|
+
fallback?: FallbackNode[];
|
|
20
|
+
/** Props for the `<code>` element wrapper (className, etc.). */
|
|
21
|
+
codeProps?: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Renders a links-only fallback on the server and replaces it with the
|
|
25
|
+
* fully syntax-highlighted version on the client at the configured time.
|
|
26
|
+
*
|
|
27
|
+
* When `fallback` is provided, it is converted to HAST and rendered for the
|
|
28
|
+
* initial display. Its text content is derived (via `fallbackToText`) to serve
|
|
29
|
+
* as the DEFLATE dictionary for decompressing `hastCompressed`.
|
|
30
|
+
*
|
|
31
|
+
* - `'hydration'`: parse immediately on mount.
|
|
32
|
+
* - `'idle'`: defer to `requestIdleCallback` regardless of visibility.
|
|
33
|
+
* - `'visible'`: wait until the element enters the viewport (IntersectionObserver),
|
|
34
|
+
* then defer to `requestIdleCallback` to avoid blocking scroll or paint.
|
|
35
|
+
*/
|
|
36
|
+
export declare function TypeCode({
|
|
37
|
+
hastJson,
|
|
38
|
+
hastCompressed,
|
|
39
|
+
highlightAt,
|
|
40
|
+
fallback,
|
|
41
|
+
codeProps
|
|
42
|
+
}: TypeCodeProps): React.DetailedReactHTMLElement<React.HTMLAttributes<HTMLElement>, HTMLElement> | React.DetailedReactHTMLElement<Record<string, unknown>, HTMLElement>;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { decompressHast, hastToJsx } from "../pipeline/hastUtils/index.mjs";
|
|
5
|
+
import { useCodeComponents } from "../useCode/CodeComponentsContext.mjs";
|
|
6
|
+
import { fallbackToHast, fallbackToText } from "../pipeline/hastUtils/fallbackFormat.mjs";
|
|
7
|
+
/**
|
|
8
|
+
* Find the children of the first `<code>` element in a parsed HAST tree.
|
|
9
|
+
*/
|
|
10
|
+
function findCodeChildren(node) {
|
|
11
|
+
if (node.type === 'element' && node.tagName === 'code') {
|
|
12
|
+
return node.children;
|
|
13
|
+
}
|
|
14
|
+
for (const child of node.children) {
|
|
15
|
+
if (child.type === 'element') {
|
|
16
|
+
const found = findCodeChildren(child);
|
|
17
|
+
if (found) {
|
|
18
|
+
return found;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Renders a links-only fallback on the server and replaces it with the
|
|
27
|
+
* fully syntax-highlighted version on the client at the configured time.
|
|
28
|
+
*
|
|
29
|
+
* When `fallback` is provided, it is converted to HAST and rendered for the
|
|
30
|
+
* initial display. Its text content is derived (via `fallbackToText`) to serve
|
|
31
|
+
* as the DEFLATE dictionary for decompressing `hastCompressed`.
|
|
32
|
+
*
|
|
33
|
+
* - `'hydration'`: parse immediately on mount.
|
|
34
|
+
* - `'idle'`: defer to `requestIdleCallback` regardless of visibility.
|
|
35
|
+
* - `'visible'`: wait until the element enters the viewport (IntersectionObserver),
|
|
36
|
+
* then defer to `requestIdleCallback` to avoid blocking scroll or paint.
|
|
37
|
+
*/
|
|
38
|
+
export function TypeCode({
|
|
39
|
+
hastJson,
|
|
40
|
+
hastCompressed,
|
|
41
|
+
highlightAt,
|
|
42
|
+
fallback,
|
|
43
|
+
codeProps
|
|
44
|
+
}) {
|
|
45
|
+
const components = useCodeComponents();
|
|
46
|
+
// Determine the effective mode: fall back to 'idle' when IntersectionObserver
|
|
47
|
+
// is unavailable (progressive enhancement for older browsers/runtimes).
|
|
48
|
+
const effectiveMode = highlightAt === 'visible' && (typeof IntersectionObserver === 'undefined' || typeof ResizeObserver === 'undefined') ? 'idle' : highlightAt;
|
|
49
|
+
const [hast, setHast] = React.useState(null);
|
|
50
|
+
const [isVisible, setIsVisible] = React.useState(effectiveMode !== 'visible');
|
|
51
|
+
const [codeElement, setCodeElement] = React.useState(null);
|
|
52
|
+
|
|
53
|
+
// Synchronize visibility state when the effective mode changes.
|
|
54
|
+
React.useEffect(() => {
|
|
55
|
+
setIsVisible(effectiveMode !== 'visible');
|
|
56
|
+
}, [effectiveMode]);
|
|
57
|
+
|
|
58
|
+
// Convert compact fallback to HAST for rendering.
|
|
59
|
+
const fallbackHastRoot = React.useMemo(() => fallback ? fallbackToHast(fallback) : undefined, [fallback]);
|
|
60
|
+
|
|
61
|
+
// Derive text dictionary from fallback for decompression.
|
|
62
|
+
const textDictionary = React.useMemo(() => fallback ? fallbackToText(fallback) : undefined, [fallback]);
|
|
63
|
+
|
|
64
|
+
// Render fallback HAST as JSX for initial display.
|
|
65
|
+
const fallbackJsx = React.useMemo(() => fallbackHastRoot ? hastToJsx(fallbackHastRoot, components) : null, [fallbackHastRoot, components]);
|
|
66
|
+
|
|
67
|
+
// Observe visibility for 'visible' mode: decompress when scrolled into view,
|
|
68
|
+
// release expanded HAST when scrolled away to reduce memory pressure.
|
|
69
|
+
//
|
|
70
|
+
// Three complementary observers cover different visibility triggers:
|
|
71
|
+
// - IntersectionObserver: scroll-based viewport entry/exit.
|
|
72
|
+
// - ResizeObserver: ancestor layout changes (CSS-based tabs, accordions)
|
|
73
|
+
// that resize the element without necessarily triggering IO.
|
|
74
|
+
// - Document 'toggle' listener (capture phase): native <details> elements
|
|
75
|
+
// whose toggle event does not bubble and may not trigger IO or RO.
|
|
76
|
+
React.useEffect(() => {
|
|
77
|
+
if (effectiveMode !== 'visible' || !codeElement) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
const updateVisibility = inViewport => {
|
|
81
|
+
if (inViewport) {
|
|
82
|
+
setIsVisible(true);
|
|
83
|
+
} else {
|
|
84
|
+
setIsVisible(false);
|
|
85
|
+
setHast(null);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const io = new IntersectionObserver(([entry]) => {
|
|
89
|
+
updateVisibility(entry.isIntersecting);
|
|
90
|
+
});
|
|
91
|
+
io.observe(codeElement);
|
|
92
|
+
|
|
93
|
+
// Force IO to re-evaluate without a synchronous getBoundingClientRect call.
|
|
94
|
+
const nudgeObserver = () => {
|
|
95
|
+
io.unobserve(codeElement);
|
|
96
|
+
io.observe(codeElement);
|
|
97
|
+
};
|
|
98
|
+
const ro = new ResizeObserver(nudgeObserver);
|
|
99
|
+
ro.observe(codeElement);
|
|
100
|
+
|
|
101
|
+
// Native <details> toggle events don't bubble, but capture-phase
|
|
102
|
+
// listeners on the document still intercept them. Re-check visibility
|
|
103
|
+
// whenever any <details> on the page opens or closes.
|
|
104
|
+
document.addEventListener('toggle', nudgeObserver, true);
|
|
105
|
+
return () => {
|
|
106
|
+
io.disconnect();
|
|
107
|
+
ro.disconnect();
|
|
108
|
+
document.removeEventListener('toggle', nudgeObserver, true);
|
|
109
|
+
};
|
|
110
|
+
}, [effectiveMode, codeElement]);
|
|
111
|
+
|
|
112
|
+
// Parse and decompress once visible.
|
|
113
|
+
React.useEffect(() => {
|
|
114
|
+
if (!isVisible) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
const parse = () => {
|
|
118
|
+
if (hastCompressed == null && hastJson == null) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const raw = hastCompressed ? decompressHast(hastCompressed, textDictionary) : hastJson;
|
|
123
|
+
const parsed = JSON.parse(raw);
|
|
124
|
+
|
|
125
|
+
// Extract code element's children from the full tree.
|
|
126
|
+
const root = parsed.type === 'root' ? parsed : {
|
|
127
|
+
type: 'root',
|
|
128
|
+
children: Array.isArray(parsed) ? parsed : [parsed]
|
|
129
|
+
};
|
|
130
|
+
const codeChildren = findCodeChildren(root);
|
|
131
|
+
const hastRoot = {
|
|
132
|
+
type: 'root',
|
|
133
|
+
children: codeChildren ?? root.children
|
|
134
|
+
};
|
|
135
|
+
setHast(hastRoot);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.warn('Failed to parse highlighted code HAST; rendering fallback instead.', error);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
if (effectiveMode === 'hydration') {
|
|
141
|
+
parse();
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 'idle' and 'visible' both defer to idle time to avoid blocking the main thread.
|
|
146
|
+
if (typeof requestIdleCallback !== 'undefined') {
|
|
147
|
+
const id = requestIdleCallback(parse, {
|
|
148
|
+
timeout: 2000
|
|
149
|
+
});
|
|
150
|
+
return () => cancelIdleCallback(id);
|
|
151
|
+
}
|
|
152
|
+
const id = setTimeout(parse, 0);
|
|
153
|
+
return () => clearTimeout(id);
|
|
154
|
+
}, [isVisible, hastJson, hastCompressed, effectiveMode, textDictionary]);
|
|
155
|
+
const highlighted = React.useMemo(() => hast !== null ? hastToJsx(hast, components) : null, [hast, components]);
|
|
156
|
+
const content = highlighted ?? fallbackJsx;
|
|
157
|
+
|
|
158
|
+
// 'hydration' and 'idle' parse without visibility gating — no observer needed.
|
|
159
|
+
if (effectiveMode !== 'visible') {
|
|
160
|
+
return /*#__PURE__*/React.createElement('code', codeProps, content);
|
|
161
|
+
}
|
|
162
|
+
return /*#__PURE__*/React.createElement('code', {
|
|
163
|
+
...codeProps,
|
|
164
|
+
ref: setCodeElement
|
|
165
|
+
}, content);
|
|
166
|
+
}
|
|
@@ -97,6 +97,12 @@ export type TypesTableMeta = {
|
|
|
97
97
|
* Pass an empty array to disable all inline enhancers.
|
|
98
98
|
*/
|
|
99
99
|
enhancersInline?: PluggableList;
|
|
100
|
+
/**
|
|
101
|
+
* Controls when expensive detailedType and formattedCode HAST fields are
|
|
102
|
+
* converted to fully-highlighted JSX.
|
|
103
|
+
* When set, overrides the factory-level highlightAt.
|
|
104
|
+
*/
|
|
105
|
+
highlightAt?: TypesJsxOptions['highlightAt'];
|
|
100
106
|
/**
|
|
101
107
|
* Custom component tag name to use instead of `<a>` for type reference links.
|
|
102
108
|
* When set, enhanceCodeTypes emits elements with this tag name,
|
|
@@ -243,6 +249,12 @@ export type AbstractCreateTypesOptions<T extends {} = {}> = {
|
|
|
243
249
|
* Can be overridden by TypesTableMeta.defaultImportSlug.
|
|
244
250
|
*/
|
|
245
251
|
defaultImportSlug?: string;
|
|
252
|
+
/**
|
|
253
|
+
* Controls when expensive detailedType and formattedCode HAST fields are
|
|
254
|
+
* converted to fully-highlighted JSX.
|
|
255
|
+
* Can be overridden by TypesTableMeta.highlightAt.
|
|
256
|
+
*/
|
|
257
|
+
highlightAt?: TypesJsxOptions['highlightAt'];
|
|
246
258
|
};
|
|
247
259
|
export declare function abstractCreateTypes<T extends {}>(options: AbstractCreateTypesOptions<T>, url: string, meta: TypesTableMeta | undefined, exportName?: string): React.ComponentType<T>;
|
|
248
260
|
export declare function createTypesFactory<T extends {}>(options: AbstractCreateTypesOptions<T>): (url: string, typeDef: object, meta?: TypesTableMeta | undefined) => React.ComponentType<T>;
|
|
@@ -42,6 +42,7 @@ export function abstractCreateTypes(options, url, meta, exportName) {
|
|
|
42
42
|
const ShortTypeCode = meta.ShortTypeCode ?? options.ShortTypeCode;
|
|
43
43
|
const DefaultCode = meta.DefaultCode ?? options.DefaultCode;
|
|
44
44
|
const RawTypePre = meta.RawTypePre ?? options.RawTypePre;
|
|
45
|
+
const highlightAt = meta.highlightAt ?? options.highlightAt;
|
|
45
46
|
|
|
46
47
|
// Enhancers from meta completely override options.enhancers if set
|
|
47
48
|
// Use DEFAULT_ENHANCERS if neither meta nor options specify enhancers
|
|
@@ -126,7 +127,8 @@ export function abstractCreateTypes(options, url, meta, exportName) {
|
|
|
126
127
|
DefaultCode,
|
|
127
128
|
RawTypePre,
|
|
128
129
|
enhancers,
|
|
129
|
-
enhancersInline
|
|
130
|
+
enhancersInline,
|
|
131
|
+
highlightAt
|
|
130
132
|
},
|
|
131
133
|
// Include additionalTypes for:
|
|
132
134
|
// 1. Single component mode (createTypes)
|
|
@@ -213,6 +215,7 @@ function createAdditionalTypesComponent(options, url, meta) {
|
|
|
213
215
|
const ShortTypeCode = meta.ShortTypeCode ?? options.ShortTypeCode;
|
|
214
216
|
const DefaultCode = meta.DefaultCode ?? options.DefaultCode;
|
|
215
217
|
const RawTypePre = meta.RawTypePre ?? options.RawTypePre;
|
|
218
|
+
const highlightAt = meta.highlightAt ?? options.highlightAt;
|
|
216
219
|
|
|
217
220
|
// Enhancers from meta completely override options.enhancers if set
|
|
218
221
|
// Use DEFAULT_ENHANCERS if neither meta nor options specify enhancers
|
|
@@ -273,7 +276,8 @@ function createAdditionalTypesComponent(options, url, meta) {
|
|
|
273
276
|
DefaultCode,
|
|
274
277
|
RawTypePre,
|
|
275
278
|
enhancers,
|
|
276
|
-
enhancersInline
|
|
279
|
+
enhancersInline,
|
|
280
|
+
highlightAt
|
|
277
281
|
}), []);
|
|
278
282
|
return /*#__PURE__*/_jsx(options.TypesTable, {
|
|
279
283
|
...props,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
1
2
|
import type { PluggableList } from 'unified';
|
|
2
3
|
import type { HighlightedComponentTypeMeta, HighlightedHookTypeMeta, HighlightedFunctionTypeMeta, HighlightedClassTypeMeta, HighlightedRawTypeMeta, HighlightedEnumMemberMeta, HighlightedTypesMeta, HighlightedProperty, HighlightedParameter, HighlightedMethod, HighlightedClassProperty } from "../pipeline/loadServerTypes/index.mjs";
|
|
3
4
|
import type { FormattedEnumMember } from "../pipeline/loadServerTypesMeta/index.mjs";
|
|
@@ -56,6 +57,15 @@ export type TypesJsxOptions = {
|
|
|
56
57
|
* Applied instead of the full enhancers for these compact fields.
|
|
57
58
|
*/
|
|
58
59
|
enhancersInline?: PluggableList;
|
|
60
|
+
/**
|
|
61
|
+
* Controls when expensive detailedType and formattedCode HAST fields are
|
|
62
|
+
* converted to fully-highlighted JSX.
|
|
63
|
+
* - `'init'`: convert immediately during SSG
|
|
64
|
+
* - `'hydration'`: server-render a links-only fallback, highlight on client mount
|
|
65
|
+
* - `'idle'`: server-render a links-only fallback, highlight when browser is idle
|
|
66
|
+
* - `'visible'`: server-render a links-only fallback, highlight when scrolled into view (default)
|
|
67
|
+
*/
|
|
68
|
+
highlightAt?: 'init' | 'hydration' | 'idle' | 'visible';
|
|
59
69
|
};
|
|
60
70
|
/**
|
|
61
71
|
* An enhanced property with HAST fields converted to React nodes.
|