@mui/internal-docs-infra 0.3.1-canary.3 → 0.3.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/esm/CodeControllerContext/CodeControllerContext.js +2 -2
- package/esm/CodeExternalsContext/CodeExternalsContext.js +1 -1
- package/esm/CodeHighlighter/CodeHighlighter.js +247 -329
- package/esm/CodeHighlighter/CodeHighlighterClient.js +447 -653
- package/esm/CodeHighlighter/CodeHighlighterContext.js +2 -2
- package/esm/CodeHighlighter/CodeHighlighterFallbackContext.js +2 -2
- package/esm/CodeHighlighter/codeToFallbackProps.js +21 -37
- package/esm/CodeHighlighter/errors.js +248 -400
- package/esm/CodeHighlighter/parseControlledCode.js +12 -20
- package/esm/CodeProvider/CodeContext.js +3 -3
- package/esm/CodeProvider/CodeProvider.js +31 -40
- package/esm/abstractCreateDemo/abstractCreateDemo.js +13 -17
- package/esm/abstractCreateDemoClient/abstractCreateDemoClient.js +12 -12
- package/esm/cli/index.js +1 -1
- package/esm/cli/runValidate.js +160 -264
- package/esm/createDemoData/createDemoData.js +11 -12
- package/esm/createSitemap/createSitemap.js +2 -2
- package/esm/pipeline/getFileConventions/fileConventions.js +1 -1
- package/esm/pipeline/getFileConventions/getFileConventions.js +2 -15
- package/esm/pipeline/hastUtils/hastUtils.js +16 -17
- package/esm/pipeline/loadCodeVariant/addCodeVariantPaths.js +24 -24
- package/esm/pipeline/loadCodeVariant/applyCodeTransform.js +12 -22
- package/esm/pipeline/loadCodeVariant/calculateMainFilePath.js +30 -37
- package/esm/pipeline/loadCodeVariant/computeHastDeltas.js +107 -185
- package/esm/pipeline/loadCodeVariant/diffHast.js +18 -53
- package/esm/pipeline/loadCodeVariant/examineCodeVariant.js +24 -27
- package/esm/pipeline/loadCodeVariant/flattenCodeVariant.js +9 -10
- package/esm/pipeline/loadCodeVariant/hasAllCodeVariants.js +5 -5
- package/esm/pipeline/loadCodeVariant/loadCodeFallback.js +516 -731
- package/esm/pipeline/loadCodeVariant/loadCodeVariant.js +679 -1079
- package/esm/pipeline/loadCodeVariant/maybeCodeInitialData.js +14 -20
- package/esm/pipeline/loadCodeVariant/mergeCodeMetadata.js +53 -63
- package/esm/pipeline/loadCodeVariant/parseCode.js +40 -48
- package/esm/pipeline/loadCodeVariant/pathUtils.js +43 -64
- package/esm/pipeline/loadCodeVariant/transformSource.js +55 -125
- package/esm/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.js +160 -221
- package/esm/pipeline/loadPrecomputedCodeHighlighter/parseCreateFactoryCall.js +377 -479
- package/esm/pipeline/loadPrecomputedCodeHighlighter/parseFunctionArguments.js +171 -173
- package/esm/pipeline/loadPrecomputedCodeHighlighter/performanceLogger.js +14 -30
- package/esm/pipeline/loadPrecomputedCodeHighlighter/replacePrecomputeValue.js +19 -21
- package/esm/pipeline/loadPrecomputedCodeHighlighter/serializeFunctionArguments.js +37 -71
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/filterRuntimeExternals.js +3 -9
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/generateImportStatements.js +54 -80
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/generateResolvedExternals.js +71 -98
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/injectImportsIntoSource.js +5 -5
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/loadPrecomputedCodeHighlighterClient.js +161 -211
- package/esm/pipeline/loadPrecomputedSitemap/loadPrecomputedSitemap.js +159 -207
- package/esm/pipeline/loadServerCodeMeta/loadServerCodeMeta.js +42 -64
- package/esm/pipeline/loadServerCodeMeta/resolveModulePathWithFs.js +20 -96
- package/esm/pipeline/loadServerPageIndex/loadServerPageIndex.js +66 -85
- package/esm/pipeline/loadServerSitemap/loadServerSitemap.js +71 -118
- package/esm/pipeline/loadServerSource/loadServerSource.js +121 -148
- package/esm/pipeline/loaderUtils/externalsToPackages.js +7 -7
- package/esm/pipeline/loaderUtils/extractNameAndSlugFromUrl.js +8 -12
- package/esm/pipeline/loaderUtils/fileUrlToPortablePath.js +5 -5
- package/esm/pipeline/loaderUtils/getFileNameFromUrl.js +19 -29
- package/esm/pipeline/loaderUtils/getLanguageFromExtension.js +3 -4
- package/esm/pipeline/loaderUtils/mergeExternals.js +15 -35
- package/esm/pipeline/loaderUtils/parseImportsAndComments.js +413 -433
- package/esm/pipeline/loaderUtils/processRelativeImports.js +153 -239
- package/esm/pipeline/loaderUtils/resolveModulePath.js +544 -1303
- package/esm/pipeline/loaderUtils/rewriteImports.js +73 -111
- package/esm/pipeline/parseSource/addLineGutters.js +33 -45
- package/esm/pipeline/parseSource/grammars.js +3 -3
- package/esm/pipeline/parseSource/parseSource.js +13 -31
- package/esm/pipeline/syncPageIndex/createMarkdownNodes.js +32 -55
- package/esm/pipeline/syncPageIndex/mergeMetadataMarkdown.js +107 -160
- package/esm/pipeline/syncPageIndex/metadataToMarkdown.js +846 -1033
- package/esm/pipeline/syncPageIndex/syncPageIndex.js +291 -438
- package/esm/pipeline/transformHtmlCodePrecomputed/transformHtmlCodePrecomputed.js +213 -311
- package/esm/pipeline/transformMarkdownBlockquoteCallouts/transformMarkdownBlockquoteCallouts.js +10 -10
- package/esm/pipeline/transformMarkdownCode/transformMarkdownCode.js +133 -193
- package/esm/pipeline/transformMarkdownDemoLinks/transformMarkdownDemoLinks.js +25 -27
- package/esm/pipeline/transformMarkdownMetadata/transformMarkdownMetadata.js +572 -717
- package/esm/pipeline/transformMarkdownRelativePaths/transformMarkdownRelativePaths.js +8 -8
- package/esm/pipeline/transformTypescriptToJavascript/removeTypes.js +84 -113
- package/esm/pipeline/transformTypescriptToJavascript/transformTypescriptToJavascript.js +10 -26
- package/esm/useCode/Pre.js +58 -62
- package/esm/useCode/useCode.js +59 -61
- package/esm/useCode/useCodeUtils.js +54 -63
- package/esm/useCode/useCopyFunctionality.js +10 -9
- package/esm/useCode/useFileNavigation.js +150 -212
- package/esm/useCode/useSourceEditing.js +17 -14
- package/esm/useCode/useTransformManagement.js +23 -26
- package/esm/useCode/useUIState.js +12 -20
- package/esm/useCode/useVariantSelection.js +62 -79
- package/esm/useCopier/index.js +29 -56
- package/esm/useDemo/createCodeSandbox.js +12 -15
- package/esm/useDemo/createStackBlitz.js +14 -20
- package/esm/useDemo/exportVariant.js +200 -180
- package/esm/useDemo/exportVariantAsCra.js +22 -25
- package/esm/useDemo/useDemo.js +80 -84
- package/esm/useErrors/ErrorsContext.js +1 -1
- package/esm/useErrors/useErrors.js +3 -3
- package/esm/useLocalStorageState/useLocalStorageState.js +23 -39
- package/esm/usePreference/PreferencesProvider.js +1 -1
- package/esm/usePreference/usePreference.js +9 -11
- package/esm/useSearch/useSearch.js +290 -387
- package/esm/useUrlHashState/useUrlHashState.js +11 -14
- package/esm/withDocsInfra/withDeploymentConfig.js +26 -21
- package/esm/withDocsInfra/withDocsInfra.js +99 -101
- package/package.json +7 -4
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import _regenerator from "@babel/runtime/helpers/esm/regenerator";
|
|
2
|
-
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
3
|
-
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
4
|
-
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
5
|
-
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
6
|
-
import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
|
|
7
|
-
var _excluded = ["position"];
|
|
8
1
|
import { unified } from 'unified';
|
|
9
2
|
import remarkParse from 'remark-parse';
|
|
10
3
|
import { visit } from 'unist-util-visit';
|
|
@@ -16,30 +9,21 @@ import { heading, paragraph, text, link, comment } from "./createMarkdownNodes.j
|
|
|
16
9
|
* Converts AST nodes (from heading.children) back to markdown string
|
|
17
10
|
*/
|
|
18
11
|
function astNodesToMarkdown(nodes) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
} else if (node.type === 'link') {
|
|
34
|
-
result += "[".concat(astNodesToMarkdown(node.children), "](").concat(node.url, ")");
|
|
35
|
-
} else if ('children' in node) {
|
|
36
|
-
result += astNodesToMarkdown(node.children);
|
|
37
|
-
}
|
|
12
|
+
let result = '';
|
|
13
|
+
for (const node of nodes) {
|
|
14
|
+
if (node.type === 'text') {
|
|
15
|
+
result += node.value;
|
|
16
|
+
} else if (node.type === 'inlineCode') {
|
|
17
|
+
result += `\`${node.value}\``;
|
|
18
|
+
} else if (node.type === 'emphasis') {
|
|
19
|
+
result += `*${astNodesToMarkdown(node.children)}*`;
|
|
20
|
+
} else if (node.type === 'strong') {
|
|
21
|
+
result += `**${astNodesToMarkdown(node.children)}**`;
|
|
22
|
+
} else if (node.type === 'link') {
|
|
23
|
+
result += `[${astNodesToMarkdown(node.children)}](${node.url})`;
|
|
24
|
+
} else if ('children' in node) {
|
|
25
|
+
result += astNodesToMarkdown(node.children);
|
|
38
26
|
}
|
|
39
|
-
} catch (err) {
|
|
40
|
-
_iterator.e(err);
|
|
41
|
-
} finally {
|
|
42
|
-
_iterator.f();
|
|
43
27
|
}
|
|
44
28
|
return result;
|
|
45
29
|
}
|
|
@@ -51,21 +35,21 @@ function astNodesToMarkdown(nodes) {
|
|
|
51
35
|
/**
|
|
52
36
|
* Converts a HeadingHierarchy into markdown list format
|
|
53
37
|
*/
|
|
54
|
-
function headingHierarchyToMarkdown(hierarchy, basePath) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
38
|
+
function headingHierarchyToMarkdown(hierarchy, basePath, depth = 0) {
|
|
39
|
+
let result = '';
|
|
40
|
+
const indent = ' '.repeat(depth);
|
|
41
|
+
for (const node of Object.values(hierarchy)) {
|
|
42
|
+
const {
|
|
43
|
+
titleMarkdown,
|
|
44
|
+
children
|
|
45
|
+
} = node;
|
|
62
46
|
// Convert AST nodes back to markdown string with preserved formatting
|
|
63
|
-
|
|
47
|
+
let titleString = astNodesToMarkdown(titleMarkdown);
|
|
64
48
|
|
|
65
49
|
// Escape numbered list syntax (e.g., "1. Text" -> "1\. Text")
|
|
66
50
|
// This prevents markdown from treating "- 1. Text" as a nested ordered list
|
|
67
51
|
titleString = titleString.replace(/^(\d+)\.\s/, '$1\\. ');
|
|
68
|
-
result +=
|
|
52
|
+
result += `${indent}- ${titleString}\n`;
|
|
69
53
|
if (Object.keys(children).length > 0) {
|
|
70
54
|
result += headingHierarchyToMarkdown(children, basePath, depth + 1);
|
|
71
55
|
}
|
|
@@ -77,12 +61,13 @@ function headingHierarchyToMarkdown(hierarchy, basePath) {
|
|
|
77
61
|
* Converts a HeadingHierarchy into markdown AST list nodes
|
|
78
62
|
*/
|
|
79
63
|
function headingHierarchyToListNodes(hierarchy, basePath) {
|
|
80
|
-
|
|
81
|
-
for (
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
children
|
|
85
|
-
|
|
64
|
+
const listItems = [];
|
|
65
|
+
for (const node of Object.values(hierarchy)) {
|
|
66
|
+
const {
|
|
67
|
+
titleMarkdown,
|
|
68
|
+
children
|
|
69
|
+
} = node;
|
|
70
|
+
const listItem = {
|
|
86
71
|
type: 'listItem',
|
|
87
72
|
children: [{
|
|
88
73
|
type: 'paragraph',
|
|
@@ -92,7 +77,7 @@ function headingHierarchyToListNodes(hierarchy, basePath) {
|
|
|
92
77
|
|
|
93
78
|
// Add nested children if they exist
|
|
94
79
|
if (Object.keys(children).length > 0) {
|
|
95
|
-
|
|
80
|
+
const nestedList = {
|
|
96
81
|
type: 'list',
|
|
97
82
|
ordered: false,
|
|
98
83
|
children: headingHierarchyToListNodes(children, basePath)
|
|
@@ -108,9 +93,11 @@ function headingHierarchyToListNodes(hierarchy, basePath) {
|
|
|
108
93
|
* Strips position metadata from AST nodes recursively
|
|
109
94
|
*/
|
|
110
95
|
function stripPositions(nodes) {
|
|
111
|
-
return nodes.map(
|
|
112
|
-
|
|
113
|
-
|
|
96
|
+
return nodes.map(node => {
|
|
97
|
+
const {
|
|
98
|
+
position,
|
|
99
|
+
...rest
|
|
100
|
+
} = node;
|
|
114
101
|
if (rest.children) {
|
|
115
102
|
rest.children = stripPositions(rest.children);
|
|
116
103
|
}
|
|
@@ -128,121 +115,84 @@ function stripPositions(nodes) {
|
|
|
128
115
|
* - CSS Variables: --var1, --var2
|
|
129
116
|
*/
|
|
130
117
|
function parseExportsFromListItem(listItem) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
var parts = {};
|
|
118
|
+
const exports = {};
|
|
119
|
+
const parts = {};
|
|
134
120
|
|
|
135
121
|
// Find the nested list within this list item
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
});
|
|
139
|
-
if (!(nestedList != null && nestedList.children)) {
|
|
122
|
+
const nestedList = listItem.children?.find(child => child.type === 'list');
|
|
123
|
+
if (!nestedList?.children) {
|
|
140
124
|
return {
|
|
141
|
-
exports
|
|
125
|
+
exports
|
|
142
126
|
};
|
|
143
127
|
}
|
|
144
128
|
|
|
145
129
|
// Parse each export/part item from the nested list
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
var _exportListItem$child, _exportParagraph$chil, _exportListItem$child2;
|
|
151
|
-
var exportListItem = _step2.value;
|
|
152
|
-
if (exportListItem.type !== 'listItem') {
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
130
|
+
for (const exportListItem of nestedList.children) {
|
|
131
|
+
if (exportListItem.type !== 'listItem') {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
155
134
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
135
|
+
// Find the paragraph with the export/part name
|
|
136
|
+
const exportParagraph = exportListItem.children?.find(child => child.type === 'paragraph');
|
|
137
|
+
if (!exportParagraph) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
163
140
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
var fullName = textNode.value || '';
|
|
141
|
+
// Extract the name from the text node
|
|
142
|
+
const textNode = exportParagraph.children?.find(child => child.type === 'text');
|
|
143
|
+
if (!textNode) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const fullName = textNode.value || '';
|
|
172
147
|
|
|
173
|
-
|
|
174
|
-
|
|
148
|
+
// Check if this is a part (has dash) or export (no dash)
|
|
149
|
+
const hasDash = fullName.includes(' - ');
|
|
175
150
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return child.type === 'list';
|
|
179
|
-
});
|
|
151
|
+
// Find the nested list with props/dataAttributes/cssVariables
|
|
152
|
+
const metadataList = exportListItem.children?.find(child => child.type === 'list');
|
|
180
153
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
} else if (metadataText.startsWith('Data Attributes:')) {
|
|
209
|
-
var dataAttributesText = metadataText.replace('Data Attributes:', '').trim();
|
|
210
|
-
if (dataAttributesText) {
|
|
211
|
-
metadata.dataAttributes = dataAttributesText.split(',').map(function (attr) {
|
|
212
|
-
return attr.trim();
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
} else if (metadataText.startsWith('CSS Variables:')) {
|
|
216
|
-
var cssVariablesText = metadataText.replace('CSS Variables:', '').trim();
|
|
217
|
-
if (cssVariablesText) {
|
|
218
|
-
metadata.cssVariables = cssVariablesText.split(',').map(function (cssVar) {
|
|
219
|
-
return cssVar.trim();
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
}
|
|
154
|
+
// Initialize the metadata (only add properties that have content)
|
|
155
|
+
const metadata = {};
|
|
156
|
+
if (metadataList) {
|
|
157
|
+
// Parse each metadata item
|
|
158
|
+
for (const metadataItem of metadataList.children) {
|
|
159
|
+
if (metadataItem.type !== 'listItem') {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const metadataParagraph = metadataItem.children?.find(child => child.type === 'paragraph');
|
|
163
|
+
if (!metadataParagraph) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const metadataText = extractPlainTextFromNode(metadataParagraph);
|
|
167
|
+
if (metadataText.startsWith('Props:')) {
|
|
168
|
+
const propsText = metadataText.replace('Props:', '').trim();
|
|
169
|
+
if (propsText) {
|
|
170
|
+
metadata.props = propsText.split(',').map(p => p.trim());
|
|
171
|
+
}
|
|
172
|
+
} else if (metadataText.startsWith('Data Attributes:')) {
|
|
173
|
+
const dataAttributesText = metadataText.replace('Data Attributes:', '').trim();
|
|
174
|
+
if (dataAttributesText) {
|
|
175
|
+
metadata.dataAttributes = dataAttributesText.split(',').map(attr => attr.trim());
|
|
176
|
+
}
|
|
177
|
+
} else if (metadataText.startsWith('CSS Variables:')) {
|
|
178
|
+
const cssVariablesText = metadataText.replace('CSS Variables:', '').trim();
|
|
179
|
+
if (cssVariablesText) {
|
|
180
|
+
metadata.cssVariables = cssVariablesText.split(',').map(cssVar => cssVar.trim());
|
|
223
181
|
}
|
|
224
|
-
} catch (err) {
|
|
225
|
-
_iterator3.e(err);
|
|
226
|
-
} finally {
|
|
227
|
-
_iterator3.f();
|
|
228
182
|
}
|
|
229
183
|
}
|
|
230
|
-
if (hasDash) {
|
|
231
|
-
// This is a part name (e.g., "ComponentName - PartName")
|
|
232
|
-
var partName = fullName.split(' - ').pop() || fullName;
|
|
233
|
-
// Always add the part, even if it has no properties
|
|
234
|
-
parts[partName] = metadata;
|
|
235
|
-
} else {
|
|
236
|
-
// This is an export name (no dash)
|
|
237
|
-
var exportName = fullName;
|
|
238
|
-
// Always add the export, even if it has no properties
|
|
239
|
-
exports[exportName] = metadata;
|
|
240
|
-
}
|
|
241
184
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
185
|
+
if (hasDash) {
|
|
186
|
+
// This is a part name (e.g., "ComponentName - PartName")
|
|
187
|
+
const partName = fullName.split(' - ').pop() || fullName;
|
|
188
|
+
// Always add the part, even if it has no properties
|
|
189
|
+
parts[partName] = metadata;
|
|
190
|
+
} else {
|
|
191
|
+
// This is an export name (no dash)
|
|
192
|
+
const exportName = fullName;
|
|
193
|
+
// Always add the export, even if it has no properties
|
|
194
|
+
exports[exportName] = metadata;
|
|
195
|
+
}
|
|
246
196
|
}
|
|
247
197
|
return {
|
|
248
198
|
exports: Object.keys(exports).length > 0 ? exports : undefined,
|
|
@@ -256,45 +206,37 @@ function parseExportsFromListItem(listItem) {
|
|
|
256
206
|
* OR plain text in the format: Title
|
|
257
207
|
*/
|
|
258
208
|
function parseHeadingSections(listNode) {
|
|
259
|
-
|
|
260
|
-
|
|
209
|
+
const hierarchy = {};
|
|
210
|
+
const stack = [{
|
|
261
211
|
depth: -1,
|
|
262
212
|
node: hierarchy
|
|
263
213
|
}];
|
|
264
214
|
|
|
265
215
|
// Helper to calculate depth from list nesting
|
|
266
|
-
function processListItems(items, baseDepth) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
for (var i = 0; i < items.length; i += 1) {
|
|
270
|
-
var _item$children, _itemParagraph$childr;
|
|
271
|
-
var item = items[i];
|
|
216
|
+
function processListItems(items, baseDepth, parentIsOrdered = false, startIndex = 1) {
|
|
217
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
218
|
+
const item = items[i];
|
|
272
219
|
if (item.type !== 'listItem') {
|
|
273
220
|
continue;
|
|
274
221
|
}
|
|
275
222
|
|
|
276
223
|
// Find the paragraph content
|
|
277
|
-
|
|
278
|
-
return child.type === 'paragraph';
|
|
279
|
-
});
|
|
224
|
+
const itemParagraph = item.children?.find(child => child.type === 'paragraph');
|
|
280
225
|
if (!itemParagraph) {
|
|
281
226
|
continue;
|
|
282
227
|
}
|
|
283
228
|
|
|
284
229
|
// Try to find a link first (linked format)
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
var titleMarkdown = [];
|
|
290
|
-
var slug = '';
|
|
230
|
+
const itemLink = itemParagraph?.children?.find(child => child.type === 'link');
|
|
231
|
+
let title = '';
|
|
232
|
+
let titleMarkdown = [];
|
|
233
|
+
let slug = '';
|
|
291
234
|
if (itemLink) {
|
|
292
|
-
var _itemLink$children;
|
|
293
235
|
// Linked format: [Title](path#slug)
|
|
294
|
-
title =
|
|
236
|
+
title = itemLink.children?.[0]?.value || '';
|
|
295
237
|
// Strip position metadata from titleMarkdown
|
|
296
238
|
titleMarkdown = stripPositions(itemLink.children || []);
|
|
297
|
-
|
|
239
|
+
const url = itemLink.url || '';
|
|
298
240
|
slug = url.split('#')[1] || '';
|
|
299
241
|
} else {
|
|
300
242
|
// Plain text format: extract all children (preserves formatting)
|
|
@@ -302,7 +244,7 @@ function parseHeadingSections(listNode) {
|
|
|
302
244
|
titleMarkdown = stripPositions(itemParagraph.children || []);
|
|
303
245
|
|
|
304
246
|
// Extract plain text for slug generation
|
|
305
|
-
|
|
247
|
+
let rawTitle = itemParagraph.children.map(child => {
|
|
306
248
|
if (child.type === 'text') {
|
|
307
249
|
return child.value;
|
|
308
250
|
}
|
|
@@ -322,8 +264,8 @@ function parseHeadingSections(listNode) {
|
|
|
322
264
|
|
|
323
265
|
// If this is from an ordered list, prepend the number
|
|
324
266
|
if (parentIsOrdered) {
|
|
325
|
-
|
|
326
|
-
title =
|
|
267
|
+
const itemNumber = startIndex + i;
|
|
268
|
+
title = `${itemNumber}. ${rawTitle}`;
|
|
327
269
|
// Update titleMarkdown to include the number
|
|
328
270
|
titleMarkdown = [{
|
|
329
271
|
type: 'text',
|
|
@@ -337,15 +279,14 @@ function parseHeadingSections(listNode) {
|
|
|
337
279
|
slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
338
280
|
}
|
|
339
281
|
if (title && slug && titleMarkdown.length > 0) {
|
|
340
|
-
var _item$children2;
|
|
341
282
|
// Pop stack until we find the parent at the right depth
|
|
342
283
|
while (stack.length > 0 && stack[stack.length - 1].depth >= baseDepth) {
|
|
343
284
|
stack.pop();
|
|
344
285
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
title
|
|
348
|
-
titleMarkdown
|
|
286
|
+
const parent = stack[stack.length - 1].node;
|
|
287
|
+
const newNode = {
|
|
288
|
+
title,
|
|
289
|
+
titleMarkdown,
|
|
349
290
|
children: {}
|
|
350
291
|
};
|
|
351
292
|
parent[slug] = newNode;
|
|
@@ -355,46 +296,38 @@ function parseHeadingSections(listNode) {
|
|
|
355
296
|
});
|
|
356
297
|
|
|
357
298
|
// Check for nested lists (can be ordered or unordered)
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
var nestedList = _step4.value;
|
|
366
|
-
if (nestedList.children) {
|
|
367
|
-
var nestedIsOrdered = nestedList.ordered === true;
|
|
368
|
-
var nestedStart = nestedList.start || 1;
|
|
369
|
-
// Always increment depth for true nesting
|
|
370
|
-
processListItems(nestedList.children, baseDepth + 1, nestedIsOrdered, nestedStart);
|
|
371
|
-
}
|
|
299
|
+
const nestedLists = item.children?.filter(child => child.type === 'list');
|
|
300
|
+
for (const nestedList of nestedLists || []) {
|
|
301
|
+
if (nestedList.children) {
|
|
302
|
+
const nestedIsOrdered = nestedList.ordered === true;
|
|
303
|
+
const nestedStart = nestedList.start || 1;
|
|
304
|
+
// Always increment depth for true nesting
|
|
305
|
+
processListItems(nestedList.children, baseDepth + 1, nestedIsOrdered, nestedStart);
|
|
372
306
|
}
|
|
373
|
-
} catch (err) {
|
|
374
|
-
_iterator4.e(err);
|
|
375
|
-
} finally {
|
|
376
|
-
_iterator4.f();
|
|
377
307
|
}
|
|
378
308
|
}
|
|
379
309
|
}
|
|
380
310
|
}
|
|
381
|
-
if (
|
|
311
|
+
if (listNode?.type === 'list' && listNode.children) {
|
|
382
312
|
processListItems(listNode.children, 0);
|
|
383
313
|
}
|
|
384
314
|
return hierarchy;
|
|
385
315
|
} /**
|
|
386
316
|
* Converts an array of page metadata into a markdown AST
|
|
387
317
|
*/
|
|
388
|
-
export function metadataToMarkdownAst(data) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
indexWrapperComponent
|
|
392
|
-
path
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
318
|
+
export function metadataToMarkdownAst(data, options = {}) {
|
|
319
|
+
const {
|
|
320
|
+
editableMarker,
|
|
321
|
+
indexWrapperComponent,
|
|
322
|
+
path
|
|
323
|
+
} = options;
|
|
324
|
+
const {
|
|
325
|
+
title: mainTitle,
|
|
326
|
+
description: mainDescription,
|
|
327
|
+
pages,
|
|
328
|
+
pageMetadata
|
|
329
|
+
} = data;
|
|
330
|
+
const children = [];
|
|
398
331
|
|
|
399
332
|
// Add main title
|
|
400
333
|
children.push(heading(1, mainTitle));
|
|
@@ -406,11 +339,11 @@ export function metadataToMarkdownAst(data) {
|
|
|
406
339
|
|
|
407
340
|
// Add editable section marker
|
|
408
341
|
// Extract just the comment text from the marker (strip [//]: # 'text' wrapper)
|
|
409
|
-
|
|
410
|
-
|
|
342
|
+
const defaultMarkerText = 'This file is autogenerated, but the following list can be modified.';
|
|
343
|
+
let markerText = defaultMarkerText;
|
|
411
344
|
if (editableMarker) {
|
|
412
345
|
// Extract text between single quotes: [//]: # 'text'
|
|
413
|
-
|
|
346
|
+
const match = editableMarker.match(/\[\/\/\]: # '(.+)'/);
|
|
414
347
|
markerText = match ? match[1] : defaultMarkerText;
|
|
415
348
|
}
|
|
416
349
|
children.push(comment(markerText));
|
|
@@ -419,78 +352,51 @@ export function metadataToMarkdownAst(data) {
|
|
|
419
352
|
if (indexWrapperComponent) {
|
|
420
353
|
children.push({
|
|
421
354
|
type: 'html',
|
|
422
|
-
value:
|
|
355
|
+
value: `<${indexWrapperComponent}>`
|
|
423
356
|
});
|
|
424
357
|
}
|
|
425
358
|
|
|
426
359
|
// Add page list (editable section) as proper list items
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
//
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
if (
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
// Add tags if present (directly after link)
|
|
443
|
-
if (page.tags && page.tags.length > 0) {
|
|
444
|
-
var _iterator7 = _createForOfIteratorHelper(page.tags),
|
|
445
|
-
_step7;
|
|
446
|
-
try {
|
|
447
|
-
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
448
|
-
var tag = _step7.value;
|
|
449
|
-
paragraphChildren.push(text(" [".concat(tag, "]")));
|
|
450
|
-
}
|
|
451
|
-
} catch (err) {
|
|
452
|
-
_iterator7.e(err);
|
|
453
|
-
} finally {
|
|
454
|
-
_iterator7.f();
|
|
455
|
-
}
|
|
360
|
+
const listItems = [];
|
|
361
|
+
for (const page of pages) {
|
|
362
|
+
const pageTitle = page.title || page.slug;
|
|
363
|
+
|
|
364
|
+
// Check if this is a single-link entry (external link or no detail section)
|
|
365
|
+
const isSingleLink = page.skipDetailSection || false;
|
|
366
|
+
let paragraphChildren;
|
|
367
|
+
if (isSingleLink) {
|
|
368
|
+
// Format: - [Title](./path) [Tag1] [Tag2]
|
|
369
|
+
paragraphChildren = [link(page.path, pageTitle)];
|
|
370
|
+
|
|
371
|
+
// Add tags if present (directly after link)
|
|
372
|
+
if (page.tags && page.tags.length > 0) {
|
|
373
|
+
for (const tag of page.tags) {
|
|
374
|
+
paragraphChildren.push(text(` [${tag}]`));
|
|
456
375
|
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
|
|
467
|
-
var _tag = _step8.value;
|
|
468
|
-
paragraphChildren.push(text(" [".concat(_tag, "]")));
|
|
469
|
-
}
|
|
470
|
-
} catch (err) {
|
|
471
|
-
_iterator8.e(err);
|
|
472
|
-
} finally {
|
|
473
|
-
_iterator8.f();
|
|
474
|
-
}
|
|
376
|
+
}
|
|
377
|
+
} else {
|
|
378
|
+
// Format: - [Title](#slug) [Tag1] [Tag2] - [Full Docs](./path/page.mdx)
|
|
379
|
+
paragraphChildren = [link(`#${page.slug}`, pageTitle)];
|
|
380
|
+
|
|
381
|
+
// Add tags if present (directly after component name)
|
|
382
|
+
if (page.tags && page.tags.length > 0) {
|
|
383
|
+
for (const tag of page.tags) {
|
|
384
|
+
paragraphChildren.push(text(` [${tag}]`));
|
|
475
385
|
}
|
|
476
|
-
|
|
477
|
-
// Add separator and Full Docs link
|
|
478
|
-
paragraphChildren.push(text(' - '));
|
|
479
|
-
paragraphChildren.push(link(page.path, 'Full Docs'));
|
|
480
386
|
}
|
|
481
|
-
listItems.push({
|
|
482
|
-
type: 'listItem',
|
|
483
|
-
spread: false,
|
|
484
|
-
children: [paragraph(paragraphChildren)]
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
387
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
388
|
+
// Add separator and Full Docs link
|
|
389
|
+
paragraphChildren.push(text(' - '));
|
|
390
|
+
paragraphChildren.push(link(page.path, 'Full Docs'));
|
|
391
|
+
}
|
|
392
|
+
listItems.push({
|
|
393
|
+
type: 'listItem',
|
|
394
|
+
spread: false,
|
|
395
|
+
children: [paragraph(paragraphChildren)]
|
|
396
|
+
});
|
|
493
397
|
}
|
|
398
|
+
|
|
399
|
+
// Add the list to children
|
|
494
400
|
children.push({
|
|
495
401
|
type: 'list',
|
|
496
402
|
ordered: false,
|
|
@@ -500,248 +406,237 @@ export function metadataToMarkdownAst(data) {
|
|
|
500
406
|
|
|
501
407
|
// Add non-editable section marker
|
|
502
408
|
// Trim common prefixes and suffixes from path, quote if contains parentheses for shell safety
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
409
|
+
const trimmedPath = path?.replace(/^(src\/app\/|app\/)/, '').replace(/\/page\.mdx$/, '');
|
|
410
|
+
const quotedPath = trimmedPath && /[()]/.test(trimmedPath) ? `"${trimmedPath}"` : trimmedPath;
|
|
411
|
+
const doNotEditComment = quotedPath ? `This file is autogenerated, DO NOT EDIT AFTER THIS LINE, run: pnpm docs:validate ${quotedPath}` : 'This file is autogenerated, DO NOT EDIT AFTER THIS LINE';
|
|
506
412
|
children.push(comment(doNotEditComment));
|
|
507
413
|
|
|
508
414
|
// Add detailed page sections (non-editable)
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
children.push(
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
415
|
+
for (const page of pages) {
|
|
416
|
+
const pageTitle = page.title || page.slug;
|
|
417
|
+
// Note: We don't replace newlines here to allow natural line breaks in detailed sections
|
|
418
|
+
const description = page.description || 'No description available';
|
|
419
|
+
const keywords = page.keywords || [];
|
|
420
|
+
const image = page.image;
|
|
421
|
+
|
|
422
|
+
// Add page heading
|
|
423
|
+
children.push(heading(2, pageTitle));
|
|
424
|
+
|
|
425
|
+
// Add description
|
|
426
|
+
children.push(paragraph(description));
|
|
427
|
+
|
|
428
|
+
// Add image if available
|
|
429
|
+
if (image) {
|
|
430
|
+
children.push({
|
|
431
|
+
type: 'paragraph',
|
|
432
|
+
children: [{
|
|
433
|
+
type: 'image',
|
|
434
|
+
url: image.url,
|
|
435
|
+
alt: image.alt || pageTitle
|
|
436
|
+
}]
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Add metadata list (keywords, sections, parts, and exports combined)
|
|
441
|
+
const hasKeywords = keywords.length > 0;
|
|
442
|
+
const hasSections = page.sections && Object.keys(page.sections).length > 0;
|
|
443
|
+
const hasParts = page.parts && Object.keys(page.parts).length > 0;
|
|
444
|
+
const hasExports = page.exports && Object.keys(page.exports).length > 0;
|
|
445
|
+
if (hasKeywords || hasSections || hasParts || hasExports) {
|
|
446
|
+
const metadataListItems = [];
|
|
447
|
+
if (hasKeywords) {
|
|
448
|
+
metadataListItems.push({
|
|
449
|
+
type: 'listItem',
|
|
450
|
+
children: [paragraph(`Keywords: ${keywords.join(', ')}`)]
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
if (hasSections && page.sections) {
|
|
454
|
+
const sectionListItems = headingHierarchyToListNodes(page.sections, page.path);
|
|
455
|
+
metadataListItems.push({
|
|
456
|
+
type: 'listItem',
|
|
457
|
+
children: [paragraph('Sections:'), {
|
|
458
|
+
type: 'list',
|
|
459
|
+
ordered: false,
|
|
460
|
+
children: sectionListItems
|
|
534
461
|
}]
|
|
535
462
|
});
|
|
536
463
|
}
|
|
464
|
+
if (hasParts || hasExports) {
|
|
465
|
+
const exportsListItems = [];
|
|
466
|
+
|
|
467
|
+
// First, add all parts with their metadata (use dash format)
|
|
468
|
+
if (hasParts && page.parts) {
|
|
469
|
+
for (const [partName, partMetadata] of Object.entries(page.parts)) {
|
|
470
|
+
const partListItems = [];
|
|
471
|
+
if (partMetadata.props && partMetadata.props.length > 0) {
|
|
472
|
+
partListItems.push({
|
|
473
|
+
type: 'listItem',
|
|
474
|
+
children: [paragraph(`Props: ${partMetadata.props.join(', ')}`)]
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
if (partMetadata.dataAttributes && partMetadata.dataAttributes.length > 0) {
|
|
478
|
+
partListItems.push({
|
|
479
|
+
type: 'listItem',
|
|
480
|
+
children: [paragraph(`Data Attributes: ${partMetadata.dataAttributes.join(', ')}`)]
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
if (partMetadata.cssVariables && partMetadata.cssVariables.length > 0) {
|
|
484
|
+
partListItems.push({
|
|
485
|
+
type: 'listItem',
|
|
486
|
+
children: [paragraph(`CSS Variables: ${partMetadata.cssVariables.join(', ')}`)]
|
|
487
|
+
});
|
|
488
|
+
}
|
|
537
489
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
var metadataListItems = [];
|
|
545
|
-
if (hasKeywords) {
|
|
546
|
-
metadataListItems.push({
|
|
547
|
-
type: 'listItem',
|
|
548
|
-
children: [paragraph("Keywords: ".concat(keywords.join(', ')))]
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
if (hasSections && _page.sections) {
|
|
552
|
-
var sectionListItems = headingHierarchyToListNodes(_page.sections, _page.path);
|
|
553
|
-
metadataListItems.push({
|
|
554
|
-
type: 'listItem',
|
|
555
|
-
children: [paragraph('Sections:'), {
|
|
556
|
-
type: 'list',
|
|
557
|
-
ordered: false,
|
|
558
|
-
children: sectionListItems
|
|
559
|
-
}]
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
if (hasParts || hasExports) {
|
|
563
|
-
var exportsListItems = [];
|
|
564
|
-
|
|
565
|
-
// First, add all parts with their metadata (use dash format)
|
|
566
|
-
if (hasParts && _page.parts) {
|
|
567
|
-
for (var _i3 = 0, _Object$entries = Object.entries(_page.parts); _i3 < _Object$entries.length; _i3++) {
|
|
568
|
-
var _Object$entries$_i = _slicedToArray(_Object$entries[_i3], 2),
|
|
569
|
-
partName = _Object$entries$_i[0],
|
|
570
|
-
partMetadata = _Object$entries$_i[1];
|
|
571
|
-
var partListItems = [];
|
|
572
|
-
if (partMetadata.props && partMetadata.props.length > 0) {
|
|
573
|
-
partListItems.push({
|
|
574
|
-
type: 'listItem',
|
|
575
|
-
children: [paragraph("Props: ".concat(partMetadata.props.join(', ')))]
|
|
576
|
-
});
|
|
577
|
-
}
|
|
578
|
-
if (partMetadata.dataAttributes && partMetadata.dataAttributes.length > 0) {
|
|
579
|
-
partListItems.push({
|
|
580
|
-
type: 'listItem',
|
|
581
|
-
children: [paragraph("Data Attributes: ".concat(partMetadata.dataAttributes.join(', ')))]
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
if (partMetadata.cssVariables && partMetadata.cssVariables.length > 0) {
|
|
585
|
-
partListItems.push({
|
|
586
|
-
type: 'listItem',
|
|
587
|
-
children: [paragraph("CSS Variables: ".concat(partMetadata.cssVariables.join(', ')))]
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// Add the part with dash separator
|
|
592
|
-
if (partListItems.length > 0) {
|
|
593
|
-
exportsListItems.push({
|
|
594
|
-
type: 'listItem',
|
|
490
|
+
// Add the part with dash separator
|
|
491
|
+
if (partListItems.length > 0) {
|
|
492
|
+
exportsListItems.push({
|
|
493
|
+
type: 'listItem',
|
|
494
|
+
children: [{
|
|
495
|
+
type: 'paragraph',
|
|
595
496
|
children: [{
|
|
596
|
-
type: '
|
|
597
|
-
|
|
598
|
-
type: 'text',
|
|
599
|
-
value: "".concat(_page.title, " - ").concat(partName)
|
|
600
|
-
}]
|
|
601
|
-
}, {
|
|
602
|
-
type: 'list',
|
|
603
|
-
ordered: false,
|
|
604
|
-
children: partListItems
|
|
497
|
+
type: 'text',
|
|
498
|
+
value: `${page.title} - ${partName}`
|
|
605
499
|
}]
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
500
|
+
}, {
|
|
501
|
+
type: 'list',
|
|
502
|
+
ordered: false,
|
|
503
|
+
children: partListItems
|
|
504
|
+
}]
|
|
505
|
+
});
|
|
506
|
+
} else {
|
|
507
|
+
// Part with no properties - just add the part name with dash
|
|
508
|
+
exportsListItems.push({
|
|
509
|
+
type: 'listItem',
|
|
510
|
+
children: [{
|
|
511
|
+
type: 'paragraph',
|
|
611
512
|
children: [{
|
|
612
|
-
type: '
|
|
613
|
-
|
|
614
|
-
type: 'text',
|
|
615
|
-
value: "".concat(_page.title, " - ").concat(partName)
|
|
616
|
-
}]
|
|
513
|
+
type: 'text',
|
|
514
|
+
value: `${page.title} - ${partName}`
|
|
617
515
|
}]
|
|
618
|
-
}
|
|
619
|
-
}
|
|
516
|
+
}]
|
|
517
|
+
});
|
|
620
518
|
}
|
|
621
519
|
}
|
|
520
|
+
}
|
|
622
521
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
children: [paragraph("CSS Variables: ".concat(exportMetadata.cssVariables.join(', ')))]
|
|
646
|
-
});
|
|
647
|
-
}
|
|
522
|
+
// Then add all exports with their metadata (no dash format)
|
|
523
|
+
if (hasExports && page.exports) {
|
|
524
|
+
for (const [exportName, exportMetadata] of Object.entries(page.exports)) {
|
|
525
|
+
const exportListItems = [];
|
|
526
|
+
if (exportMetadata.props && exportMetadata.props.length > 0) {
|
|
527
|
+
exportListItems.push({
|
|
528
|
+
type: 'listItem',
|
|
529
|
+
children: [paragraph(`Props: ${exportMetadata.props.join(', ')}`)]
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
if (exportMetadata.dataAttributes && exportMetadata.dataAttributes.length > 0) {
|
|
533
|
+
exportListItems.push({
|
|
534
|
+
type: 'listItem',
|
|
535
|
+
children: [paragraph(`Data Attributes: ${exportMetadata.dataAttributes.join(', ')}`)]
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
if (exportMetadata.cssVariables && exportMetadata.cssVariables.length > 0) {
|
|
539
|
+
exportListItems.push({
|
|
540
|
+
type: 'listItem',
|
|
541
|
+
children: [paragraph(`CSS Variables: ${exportMetadata.cssVariables.join(', ')}`)]
|
|
542
|
+
});
|
|
543
|
+
}
|
|
648
544
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
545
|
+
// Always add the export, even if it has no properties
|
|
546
|
+
if (exportListItems.length > 0) {
|
|
547
|
+
exportsListItems.push({
|
|
548
|
+
type: 'listItem',
|
|
549
|
+
children: [{
|
|
550
|
+
type: 'paragraph',
|
|
653
551
|
children: [{
|
|
654
|
-
type: '
|
|
655
|
-
|
|
656
|
-
type: 'text',
|
|
657
|
-
value: exportName
|
|
658
|
-
}]
|
|
659
|
-
}, {
|
|
660
|
-
type: 'list',
|
|
661
|
-
ordered: false,
|
|
662
|
-
children: exportListItems
|
|
552
|
+
type: 'text',
|
|
553
|
+
value: exportName
|
|
663
554
|
}]
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
555
|
+
}, {
|
|
556
|
+
type: 'list',
|
|
557
|
+
ordered: false,
|
|
558
|
+
children: exportListItems
|
|
559
|
+
}]
|
|
560
|
+
});
|
|
561
|
+
} else {
|
|
562
|
+
// Export with no properties - just add the export name
|
|
563
|
+
exportsListItems.push({
|
|
564
|
+
type: 'listItem',
|
|
565
|
+
children: [{
|
|
566
|
+
type: 'paragraph',
|
|
669
567
|
children: [{
|
|
670
|
-
type: '
|
|
671
|
-
|
|
672
|
-
type: 'text',
|
|
673
|
-
value: exportName
|
|
674
|
-
}]
|
|
568
|
+
type: 'text',
|
|
569
|
+
value: exportName
|
|
675
570
|
}]
|
|
676
|
-
}
|
|
677
|
-
}
|
|
571
|
+
}]
|
|
572
|
+
});
|
|
678
573
|
}
|
|
679
574
|
}
|
|
680
|
-
if (exportsListItems.length > 0) {
|
|
681
|
-
metadataListItems.push({
|
|
682
|
-
type: 'listItem',
|
|
683
|
-
children: [paragraph('Exports:'), {
|
|
684
|
-
type: 'list',
|
|
685
|
-
ordered: false,
|
|
686
|
-
children: exportsListItems
|
|
687
|
-
}]
|
|
688
|
-
});
|
|
689
|
-
}
|
|
690
575
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
});
|
|
702
|
-
children.push(paragraph(''));
|
|
703
|
-
children.push({
|
|
704
|
-
type: 'list',
|
|
705
|
-
ordered: false,
|
|
706
|
-
children: metadataListItems
|
|
707
|
-
});
|
|
708
|
-
children.push(paragraph(''));
|
|
709
|
-
children.push({
|
|
710
|
-
type: 'html',
|
|
711
|
-
value: '</details>'
|
|
712
|
-
});
|
|
576
|
+
if (exportsListItems.length > 0) {
|
|
577
|
+
metadataListItems.push({
|
|
578
|
+
type: 'listItem',
|
|
579
|
+
children: [paragraph('Exports:'), {
|
|
580
|
+
type: 'list',
|
|
581
|
+
ordered: false,
|
|
582
|
+
children: exportsListItems
|
|
583
|
+
}]
|
|
584
|
+
});
|
|
585
|
+
}
|
|
713
586
|
}
|
|
714
587
|
|
|
715
|
-
//
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
588
|
+
// Wrap metadata in details/summary tags
|
|
589
|
+
children.push({
|
|
590
|
+
type: 'html',
|
|
591
|
+
value: '<details>'
|
|
592
|
+
});
|
|
593
|
+
children.push(paragraph(''));
|
|
594
|
+
children.push({
|
|
595
|
+
type: 'html',
|
|
596
|
+
value: '<summary>Outline</summary>'
|
|
597
|
+
});
|
|
598
|
+
children.push(paragraph(''));
|
|
599
|
+
children.push({
|
|
600
|
+
type: 'list',
|
|
601
|
+
ordered: false,
|
|
602
|
+
children: metadataListItems
|
|
603
|
+
});
|
|
604
|
+
children.push(paragraph(''));
|
|
605
|
+
children.push({
|
|
606
|
+
type: 'html',
|
|
607
|
+
value: '</details>'
|
|
608
|
+
});
|
|
609
|
+
}
|
|
719
610
|
|
|
720
|
-
|
|
721
|
-
|
|
611
|
+
// Add embeddings as a comment if available
|
|
612
|
+
if (page.embeddings && page.embeddings.length > 0) {
|
|
613
|
+
children.push(comment(`Embeddings: ${JSON.stringify(page.embeddings)}`));
|
|
722
614
|
}
|
|
723
615
|
|
|
724
|
-
//
|
|
725
|
-
|
|
726
|
-
_iterator6.e(err);
|
|
727
|
-
} finally {
|
|
728
|
-
_iterator6.f();
|
|
616
|
+
// Add read more link
|
|
617
|
+
children.push(paragraph([link(page.path, 'Read more')]));
|
|
729
618
|
}
|
|
619
|
+
|
|
620
|
+
// Close wrapper component if provided
|
|
730
621
|
if (indexWrapperComponent) {
|
|
731
622
|
children.push({
|
|
732
623
|
type: 'html',
|
|
733
|
-
value:
|
|
624
|
+
value: `</${indexWrapperComponent}>`
|
|
734
625
|
});
|
|
735
626
|
}
|
|
736
627
|
|
|
737
628
|
// Add metadata export at the end
|
|
738
629
|
children.push(comment('This file is autogenerated, but the following metadata can be modified.'));
|
|
739
|
-
|
|
630
|
+
let metadataCode;
|
|
740
631
|
if (pageMetadata && Object.keys(pageMetadata).length > 0) {
|
|
741
|
-
metadataCode =
|
|
632
|
+
metadataCode = `export const metadata = ${JSON.stringify(pageMetadata, null, 2)};`;
|
|
742
633
|
} else {
|
|
743
634
|
// Default metadata with robots noindex
|
|
744
|
-
metadataCode =
|
|
635
|
+
metadataCode = `export const metadata = {
|
|
636
|
+
robots: {
|
|
637
|
+
index: false,
|
|
638
|
+
},
|
|
639
|
+
};`;
|
|
745
640
|
}
|
|
746
641
|
// Output as raw MDX/JSX code (mdxjsEsm node type)
|
|
747
642
|
children.push({
|
|
@@ -750,30 +645,33 @@ export function metadataToMarkdownAst(data) {
|
|
|
750
645
|
});
|
|
751
646
|
return {
|
|
752
647
|
type: 'root',
|
|
753
|
-
children
|
|
648
|
+
children
|
|
754
649
|
};
|
|
755
650
|
}
|
|
756
651
|
|
|
757
652
|
/**
|
|
758
653
|
* Converts an array of page metadata into the markdown format (string)
|
|
759
654
|
*/
|
|
760
|
-
export function metadataToMarkdown(data) {
|
|
761
|
-
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
655
|
+
export function metadataToMarkdown(data, options = {}) {
|
|
762
656
|
// Support legacy signature where second param was editableMarker string
|
|
763
|
-
|
|
657
|
+
const normalizedOptions = typeof options === 'string' ? {
|
|
764
658
|
editableMarker: options
|
|
765
659
|
} : options;
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
660
|
+
const {
|
|
661
|
+
editableMarker,
|
|
662
|
+
indexWrapperComponent,
|
|
663
|
+
path
|
|
664
|
+
} = normalizedOptions;
|
|
665
|
+
const {
|
|
666
|
+
title,
|
|
667
|
+
description,
|
|
668
|
+
pages,
|
|
669
|
+
pageMetadata
|
|
670
|
+
} = data;
|
|
671
|
+
const lines = [];
|
|
774
672
|
|
|
775
673
|
// Add main title
|
|
776
|
-
lines.push(
|
|
674
|
+
lines.push(`# ${title}`);
|
|
777
675
|
lines.push('');
|
|
778
676
|
|
|
779
677
|
// Add description if provided (editable section)
|
|
@@ -783,224 +681,182 @@ export function metadataToMarkdown(data) {
|
|
|
783
681
|
}
|
|
784
682
|
|
|
785
683
|
// Add editable section marker
|
|
786
|
-
|
|
684
|
+
const marker = editableMarker ?? "[//]: # 'This file is autogenerated, but the following list can be modified.'";
|
|
787
685
|
lines.push(marker);
|
|
788
686
|
lines.push('');
|
|
789
687
|
|
|
790
688
|
// Open wrapper component if provided
|
|
791
689
|
if (indexWrapperComponent) {
|
|
792
|
-
lines.push(
|
|
690
|
+
lines.push(`<${indexWrapperComponent}>`);
|
|
793
691
|
lines.push('');
|
|
794
692
|
}
|
|
795
693
|
|
|
796
694
|
// Add page list (editable section)
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
//
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
if (
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
// Add tags if present (directly after link)
|
|
812
|
-
if (page.tags && page.tags.length > 0) {
|
|
813
|
-
var _iterator1 = _createForOfIteratorHelper(page.tags),
|
|
814
|
-
_step1;
|
|
815
|
-
try {
|
|
816
|
-
for (_iterator1.s(); !(_step1 = _iterator1.n()).done;) {
|
|
817
|
-
var tag = _step1.value;
|
|
818
|
-
line += " [".concat(tag, "]");
|
|
819
|
-
}
|
|
820
|
-
} catch (err) {
|
|
821
|
-
_iterator1.e(err);
|
|
822
|
-
} finally {
|
|
823
|
-
_iterator1.f();
|
|
824
|
-
}
|
|
695
|
+
for (const page of pages) {
|
|
696
|
+
const pageTitle = page.title || page.slug;
|
|
697
|
+
|
|
698
|
+
// Check if this is a single-link entry (external link or no detail section)
|
|
699
|
+
const isSingleLink = page.skipDetailSection || false;
|
|
700
|
+
let line;
|
|
701
|
+
if (isSingleLink) {
|
|
702
|
+
// Format: - [Title](./path) [Tag1] [Tag2]
|
|
703
|
+
line = `- [${pageTitle}](${page.path})`;
|
|
704
|
+
|
|
705
|
+
// Add tags if present (directly after link)
|
|
706
|
+
if (page.tags && page.tags.length > 0) {
|
|
707
|
+
for (const tag of page.tags) {
|
|
708
|
+
line += ` [${tag}]`;
|
|
825
709
|
}
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
|
|
836
|
-
var _tag2 = _step10.value;
|
|
837
|
-
line += " [".concat(_tag2, "]");
|
|
838
|
-
}
|
|
839
|
-
} catch (err) {
|
|
840
|
-
_iterator10.e(err);
|
|
841
|
-
} finally {
|
|
842
|
-
_iterator10.f();
|
|
843
|
-
}
|
|
710
|
+
}
|
|
711
|
+
} else {
|
|
712
|
+
// Format: - [Title](#slug) [Tag1] [Tag2] - [Full Docs](./path/page.mdx)
|
|
713
|
+
line = `- [${pageTitle}](#${page.slug})`;
|
|
714
|
+
|
|
715
|
+
// Add tags if present (directly after component name)
|
|
716
|
+
if (page.tags && page.tags.length > 0) {
|
|
717
|
+
for (const tag of page.tags) {
|
|
718
|
+
line += ` [${tag}]`;
|
|
844
719
|
}
|
|
845
|
-
|
|
846
|
-
// Add separator and Full Docs link
|
|
847
|
-
line += " - [Full Docs](".concat(page.path, ")");
|
|
848
720
|
}
|
|
849
|
-
|
|
721
|
+
|
|
722
|
+
// Add separator and Full Docs link
|
|
723
|
+
line += ` - [Full Docs](${page.path})`;
|
|
850
724
|
}
|
|
851
|
-
|
|
852
|
-
_iterator9.e(err);
|
|
853
|
-
} finally {
|
|
854
|
-
_iterator9.f();
|
|
725
|
+
lines.push(line);
|
|
855
726
|
}
|
|
856
727
|
lines.push('');
|
|
857
728
|
|
|
858
729
|
// Add non-editable section marker
|
|
859
730
|
// Trim common prefixes and suffixes from path, quote if contains parentheses for shell safety
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
731
|
+
const trimmedPath = path?.replace(/^(src\/app\/|app\/)/, '').replace(/\/page\.mdx$/, '');
|
|
732
|
+
const quotedPath = trimmedPath && /[()]/.test(trimmedPath) ? `"${trimmedPath}"` : trimmedPath;
|
|
733
|
+
const doNotEditMarker = quotedPath ? `[//]: # 'This file is autogenerated, DO NOT EDIT AFTER THIS LINE, run: pnpm docs:validate ${quotedPath}'` : "[//]: # 'This file is autogenerated, DO NOT EDIT AFTER THIS LINE'";
|
|
863
734
|
lines.push(doNotEditMarker);
|
|
864
735
|
lines.push('');
|
|
865
736
|
|
|
866
737
|
// Add detailed page sections (non-editable)
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
pageDescription = _page2.description || 'No description available';
|
|
884
|
-
}
|
|
885
|
-
var keywords = _page2.keywords || [];
|
|
886
|
-
var image = _page2.image;
|
|
738
|
+
for (const page of pages) {
|
|
739
|
+
// Skip detail section for single-link entries (external links)
|
|
740
|
+
if (page.skipDetailSection) {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
const pageTitle = page.title || page.slug;
|
|
744
|
+
// Use descriptionMarkdown to preserve formatting if available
|
|
745
|
+
// Note: We don't replace newlines here to allow natural line breaks in detailed sections
|
|
746
|
+
let pageDescription;
|
|
747
|
+
if (page.descriptionMarkdown && page.descriptionMarkdown.length > 0) {
|
|
748
|
+
pageDescription = astNodesToMarkdown(page.descriptionMarkdown);
|
|
749
|
+
} else {
|
|
750
|
+
pageDescription = page.description || 'No description available';
|
|
751
|
+
}
|
|
752
|
+
const keywords = page.keywords || [];
|
|
753
|
+
const image = page.image;
|
|
887
754
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
755
|
+
// Add page heading
|
|
756
|
+
lines.push(`## ${pageTitle}`);
|
|
757
|
+
lines.push('');
|
|
891
758
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
759
|
+
// Add description
|
|
760
|
+
lines.push(pageDescription);
|
|
761
|
+
lines.push('');
|
|
895
762
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
763
|
+
// Add image if available
|
|
764
|
+
if (image) {
|
|
765
|
+
lines.push(``);
|
|
766
|
+
lines.push('');
|
|
767
|
+
}
|
|
901
768
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
769
|
+
// Add metadata list (keywords, sections, parts, and exports)
|
|
770
|
+
const hasKeywords = keywords.length > 0;
|
|
771
|
+
const hasSections = page.sections && Object.keys(page.sections).length > 0;
|
|
772
|
+
const hasParts = page.parts && Object.keys(page.parts).length > 0;
|
|
773
|
+
const hasExports = page.exports && Object.keys(page.exports).length > 0;
|
|
907
774
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
}
|
|
948
|
-
if (hasCssVariables) {
|
|
949
|
-
lines.push(" - CSS Variables: ".concat(partMetadata.cssVariables.join(', ')));
|
|
950
|
-
}
|
|
775
|
+
// Track if we actually add any metadata content
|
|
776
|
+
let hasMetadataContent = false;
|
|
777
|
+
if (hasKeywords || hasSections || hasParts || hasExports) {
|
|
778
|
+
lines.push('<details>');
|
|
779
|
+
lines.push('');
|
|
780
|
+
lines.push('<summary>Outline</summary>');
|
|
781
|
+
lines.push('');
|
|
782
|
+
if (hasKeywords) {
|
|
783
|
+
lines.push(`- Keywords: ${keywords.join(', ')}`);
|
|
784
|
+
hasMetadataContent = true;
|
|
785
|
+
}
|
|
786
|
+
if (hasSections && page.sections) {
|
|
787
|
+
const sectionLines = headingHierarchyToMarkdown(page.sections, page.path, 1); // Start at depth 1 for indentation
|
|
788
|
+
lines.push('- Sections:');
|
|
789
|
+
lines.push(sectionLines.trimEnd());
|
|
790
|
+
hasMetadataContent = true;
|
|
791
|
+
}
|
|
792
|
+
// Handle both parts and exports
|
|
793
|
+
// Parts and exports are combined into a single "Exports:" section
|
|
794
|
+
// Parts use format "ComponentName - PartName" (written with dash)
|
|
795
|
+
// Exports use just "ExportName" (written without dash)
|
|
796
|
+
if (hasParts || hasExports) {
|
|
797
|
+
lines.push('- Exports:');
|
|
798
|
+
|
|
799
|
+
// First, list all parts with their metadata (use dash format)
|
|
800
|
+
if (hasParts && page.parts) {
|
|
801
|
+
for (const [partName, partMetadata] of Object.entries(page.parts)) {
|
|
802
|
+
const hasProps = partMetadata.props && partMetadata.props.length > 0;
|
|
803
|
+
const hasDataAttributes = partMetadata.dataAttributes && partMetadata.dataAttributes.length > 0;
|
|
804
|
+
const hasCssVariables = partMetadata.cssVariables && partMetadata.cssVariables.length > 0;
|
|
805
|
+
lines.push(` - ${page.title} - ${partName}`);
|
|
806
|
+
if (hasProps) {
|
|
807
|
+
lines.push(` - Props: ${partMetadata.props.join(', ')}`);
|
|
808
|
+
}
|
|
809
|
+
if (hasDataAttributes) {
|
|
810
|
+
lines.push(` - Data Attributes: ${partMetadata.dataAttributes.join(', ')}`);
|
|
811
|
+
}
|
|
812
|
+
if (hasCssVariables) {
|
|
813
|
+
lines.push(` - CSS Variables: ${partMetadata.cssVariables.join(', ')}`);
|
|
951
814
|
}
|
|
952
815
|
}
|
|
816
|
+
}
|
|
953
817
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
}
|
|
970
|
-
if (_hasCssVariables) {
|
|
971
|
-
lines.push(" - CSS Variables: ".concat(exportMetadata.cssVariables.join(', ')));
|
|
972
|
-
}
|
|
818
|
+
// Then list all exports with their metadata (no dash format)
|
|
819
|
+
if (hasExports && page.exports) {
|
|
820
|
+
for (const [exportName, exportMetadata] of Object.entries(page.exports)) {
|
|
821
|
+
const hasProps = exportMetadata.props && exportMetadata.props.length > 0;
|
|
822
|
+
const hasDataAttributes = exportMetadata.dataAttributes && exportMetadata.dataAttributes.length > 0;
|
|
823
|
+
const hasCssVariables = exportMetadata.cssVariables && exportMetadata.cssVariables.length > 0;
|
|
824
|
+
lines.push(` - ${exportName}`);
|
|
825
|
+
if (hasProps) {
|
|
826
|
+
lines.push(` - Props: ${exportMetadata.props.join(', ')}`);
|
|
827
|
+
}
|
|
828
|
+
if (hasDataAttributes) {
|
|
829
|
+
lines.push(` - Data Attributes: ${exportMetadata.dataAttributes.join(', ')}`);
|
|
830
|
+
}
|
|
831
|
+
if (hasCssVariables) {
|
|
832
|
+
lines.push(` - CSS Variables: ${exportMetadata.cssVariables.join(', ')}`);
|
|
973
833
|
}
|
|
974
834
|
}
|
|
975
|
-
hasMetadataContent = true;
|
|
976
|
-
}
|
|
977
|
-
lines.push('');
|
|
978
|
-
lines.push('</details>');
|
|
979
|
-
// Only add blank line if we actually added metadata content
|
|
980
|
-
if (hasMetadataContent) {
|
|
981
|
-
lines.push('');
|
|
982
835
|
}
|
|
836
|
+
hasMetadataContent = true;
|
|
983
837
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
if
|
|
987
|
-
|
|
838
|
+
lines.push('');
|
|
839
|
+
lines.push('</details>');
|
|
840
|
+
// Only add blank line if we actually added metadata content
|
|
841
|
+
if (hasMetadataContent) {
|
|
988
842
|
lines.push('');
|
|
989
843
|
}
|
|
844
|
+
}
|
|
990
845
|
|
|
991
|
-
|
|
992
|
-
|
|
846
|
+
// Add embeddings as a comment if available
|
|
847
|
+
if (page.embeddings && page.embeddings.length > 0) {
|
|
848
|
+
lines.push(`[//]: # 'Embeddings: ${JSON.stringify(page.embeddings)}'`);
|
|
993
849
|
lines.push('');
|
|
994
850
|
}
|
|
995
851
|
|
|
996
|
-
//
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
} finally {
|
|
1000
|
-
_iterator0.f();
|
|
852
|
+
// Add read more link
|
|
853
|
+
lines.push(`[Read more](${page.path})`);
|
|
854
|
+
lines.push('');
|
|
1001
855
|
}
|
|
856
|
+
|
|
857
|
+
// Close wrapper component if provided
|
|
1002
858
|
if (indexWrapperComponent) {
|
|
1003
|
-
lines.push(
|
|
859
|
+
lines.push(`</${indexWrapperComponent}>`);
|
|
1004
860
|
lines.push('');
|
|
1005
861
|
}
|
|
1006
862
|
|
|
@@ -1008,389 +864,356 @@ export function metadataToMarkdown(data) {
|
|
|
1008
864
|
lines.push("[//]: # 'This file is autogenerated, but the following metadata can be modified.'");
|
|
1009
865
|
lines.push('');
|
|
1010
866
|
if (pageMetadata && Object.keys(pageMetadata).length > 0) {
|
|
1011
|
-
lines.push(
|
|
867
|
+
lines.push(`export const metadata = ${JSON.stringify(pageMetadata, null, 2)};`);
|
|
1012
868
|
} else {
|
|
1013
869
|
// Default metadata with robots noindex
|
|
1014
|
-
lines.push(
|
|
870
|
+
lines.push(`export const metadata = {
|
|
871
|
+
robots: {
|
|
872
|
+
index: false,
|
|
873
|
+
},
|
|
874
|
+
};`);
|
|
1015
875
|
}
|
|
1016
876
|
lines.push('');
|
|
1017
877
|
|
|
1018
878
|
// Remove trailing empty line
|
|
1019
|
-
return
|
|
879
|
+
return `${lines.join('\n').trimEnd()}\n`;
|
|
1020
880
|
}
|
|
1021
881
|
|
|
1022
882
|
/**
|
|
1023
883
|
* Parses markdown content and extracts page metadata using unified
|
|
1024
884
|
*/
|
|
1025
|
-
export function markdownToMetadata(
|
|
1026
|
-
|
|
1027
|
-
|
|
885
|
+
export async function markdownToMetadata(markdown) {
|
|
886
|
+
const tree = unified().use(remarkParse).parse(markdown);
|
|
887
|
+
let title = null;
|
|
888
|
+
let description;
|
|
889
|
+
let pageMetadata;
|
|
890
|
+
let indexWrapperComponent;
|
|
891
|
+
const pages = [];
|
|
892
|
+
let currentSection = 'header';
|
|
893
|
+
let currentPage = null;
|
|
894
|
+
|
|
895
|
+
// Visit all nodes in the AST
|
|
896
|
+
visit(tree, (node, index, parent) => {
|
|
897
|
+
// Track sections based on definition nodes (HTML-style comments)
|
|
898
|
+
if (node.type === 'definition') {
|
|
899
|
+
const defNode = node;
|
|
900
|
+
if (defNode.title?.includes('following list can be modified')) {
|
|
901
|
+
currentSection = 'editable';
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
if (defNode.title?.includes('DO NOT EDIT AFTER THIS LINE')) {
|
|
905
|
+
currentSection = 'details';
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
if (defNode.title?.includes('following metadata can be modified')) {
|
|
909
|
+
currentSection = 'metadata';
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
// Parse embeddings from comment
|
|
913
|
+
if (currentPage && defNode.title?.includes('Embeddings:')) {
|
|
914
|
+
const embeddingsText = defNode.title.replace('Embeddings:', '').trim();
|
|
915
|
+
try {
|
|
916
|
+
currentPage.embeddings = JSON.parse(embeddingsText);
|
|
917
|
+
} catch (error) {
|
|
918
|
+
console.error('Failed to parse embeddings:', error);
|
|
919
|
+
}
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
1028
923
|
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
case 0:
|
|
1039
|
-
tree = unified().use(remarkParse).parse(markdown);
|
|
1040
|
-
title = null;
|
|
1041
|
-
pages = [];
|
|
1042
|
-
currentSection = 'header';
|
|
1043
|
-
currentPage = null; // Visit all nodes in the AST
|
|
1044
|
-
visit(tree, function (node, index, parent) {
|
|
1045
|
-
// Track sections based on definition nodes (HTML-style comments)
|
|
1046
|
-
if (node.type === 'definition') {
|
|
1047
|
-
var _defNode$title, _defNode$title2, _defNode$title3, _defNode$title4;
|
|
1048
|
-
var defNode = node;
|
|
1049
|
-
if ((_defNode$title = defNode.title) != null && _defNode$title.includes('following list can be modified')) {
|
|
1050
|
-
currentSection = 'editable';
|
|
1051
|
-
return;
|
|
1052
|
-
}
|
|
1053
|
-
if ((_defNode$title2 = defNode.title) != null && _defNode$title2.includes('DO NOT EDIT AFTER THIS LINE')) {
|
|
1054
|
-
currentSection = 'details';
|
|
1055
|
-
return;
|
|
1056
|
-
}
|
|
1057
|
-
if ((_defNode$title3 = defNode.title) != null && _defNode$title3.includes('following metadata can be modified')) {
|
|
1058
|
-
currentSection = 'metadata';
|
|
1059
|
-
return;
|
|
1060
|
-
}
|
|
1061
|
-
// Parse embeddings from comment
|
|
1062
|
-
if (currentPage && (_defNode$title4 = defNode.title) != null && _defNode$title4.includes('Embeddings:')) {
|
|
1063
|
-
var embeddingsText = defNode.title.replace('Embeddings:', '').trim();
|
|
1064
|
-
try {
|
|
1065
|
-
currentPage.embeddings = JSON.parse(embeddingsText);
|
|
1066
|
-
} catch (error) {
|
|
1067
|
-
console.error('Failed to parse embeddings:', error);
|
|
1068
|
-
}
|
|
1069
|
-
return;
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
924
|
+
// Extract wrapper component from HTML nodes (e.g., <PagesIndex>)
|
|
925
|
+
if (node.type === 'html' && !indexWrapperComponent) {
|
|
926
|
+
const htmlNode = node;
|
|
927
|
+
// Match opening tag like <PagesIndex> or <ComponentsIndex>
|
|
928
|
+
const openingTagMatch = htmlNode.value.match(/^<([A-Z][a-zA-Z0-9]*)>$/);
|
|
929
|
+
if (openingTagMatch) {
|
|
930
|
+
indexWrapperComponent = openingTagMatch[1];
|
|
931
|
+
}
|
|
932
|
+
}
|
|
1072
933
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
934
|
+
// Extract main title (H1)
|
|
935
|
+
if (node.type === 'heading') {
|
|
936
|
+
const headingNode = node;
|
|
937
|
+
if (headingNode.depth === 1) {
|
|
938
|
+
title = extractPlainTextFromNode(headingNode);
|
|
939
|
+
currentSection = 'header';
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
1082
943
|
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
944
|
+
// Parse description in header section (paragraph after H1, before editable marker)
|
|
945
|
+
if (currentSection === 'header' && node.type === 'paragraph' && parent?.type === 'root') {
|
|
946
|
+
const paragraphNode = node;
|
|
947
|
+
const paragraphText = extractPlainTextFromNode(paragraphNode);
|
|
948
|
+
if (paragraphText && !description) {
|
|
949
|
+
description = paragraphText;
|
|
950
|
+
}
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
1092
953
|
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
954
|
+
// Parse editable list items - check if we're in a paragraph that's a child of a listItem
|
|
955
|
+
if (currentSection === 'editable' && node.type === 'paragraph' && parent?.type === 'listItem') {
|
|
956
|
+
const paragraphNode = node;
|
|
957
|
+
if (paragraphNode.children) {
|
|
958
|
+
// Look for links in the paragraph
|
|
959
|
+
const links = paragraphNode.children.filter(child => child.type === 'link');
|
|
960
|
+
if (links.length === 0) {
|
|
961
|
+
// No links found, skip this item
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
if (links.length === 1) {
|
|
965
|
+
// Single link format: - [Title](./path) [Tag1] [Tag2]
|
|
966
|
+
// This is for external links or pages that don't have detail sections
|
|
967
|
+
const singleLink = links[0];
|
|
968
|
+
const pageTitle = extractPlainTextFromNode(singleLink);
|
|
969
|
+
const path = singleLink.url;
|
|
970
|
+
|
|
971
|
+
// Generate slug from title for consistency
|
|
972
|
+
const slug = titleToSlug(pageTitle);
|
|
973
|
+
|
|
974
|
+
// Extract tags from text nodes after the link
|
|
975
|
+
// Tags are in the format [Tag] where Tag can be New, Hot, Beta, External, etc.
|
|
976
|
+
const tags = [];
|
|
977
|
+
let foundLink = false;
|
|
978
|
+
for (const child of paragraphNode.children) {
|
|
979
|
+
if (child === singleLink) {
|
|
980
|
+
foundLink = true;
|
|
981
|
+
continue;
|
|
1101
982
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
return child.type === 'link';
|
|
1110
|
-
});
|
|
1111
|
-
if (links.length === 0) {
|
|
1112
|
-
// No links found, skip this item
|
|
1113
|
-
return;
|
|
1114
|
-
}
|
|
1115
|
-
if (links.length === 1) {
|
|
1116
|
-
// Single link format: - [Title](./path) [Tag1] [Tag2]
|
|
1117
|
-
// This is for external links or pages that don't have detail sections
|
|
1118
|
-
var singleLink = links[0];
|
|
1119
|
-
var pageTitle = extractPlainTextFromNode(singleLink);
|
|
1120
|
-
var path = singleLink.url;
|
|
1121
|
-
|
|
1122
|
-
// Generate slug from title for consistency
|
|
1123
|
-
var slug = titleToSlug(pageTitle);
|
|
1124
|
-
|
|
1125
|
-
// Extract tags from text nodes after the link
|
|
1126
|
-
// Tags are in the format [Tag] where Tag can be New, Hot, Beta, External, etc.
|
|
1127
|
-
var tags = [];
|
|
1128
|
-
var foundLink = false;
|
|
1129
|
-
var _iterator11 = _createForOfIteratorHelper(_paragraphNode.children),
|
|
1130
|
-
_step11;
|
|
1131
|
-
try {
|
|
1132
|
-
for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
|
|
1133
|
-
var child = _step11.value;
|
|
1134
|
-
if (child === singleLink) {
|
|
1135
|
-
foundLink = true;
|
|
1136
|
-
continue;
|
|
1137
|
-
}
|
|
1138
|
-
if (foundLink && child.type === 'text') {
|
|
1139
|
-
// Match [Tag] patterns in the text
|
|
1140
|
-
var tagRegex = /\[(\w+)\]/g;
|
|
1141
|
-
var match = tagRegex.exec(child.value);
|
|
1142
|
-
while (match !== null) {
|
|
1143
|
-
tags.push(match[1]);
|
|
1144
|
-
match = tagRegex.exec(child.value);
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
// These entries are preserved as-is in the editable section
|
|
1150
|
-
// They won't have detail sections generated
|
|
1151
|
-
} catch (err) {
|
|
1152
|
-
_iterator11.e(err);
|
|
1153
|
-
} finally {
|
|
1154
|
-
_iterator11.f();
|
|
1155
|
-
}
|
|
1156
|
-
pages.push({
|
|
1157
|
-
slug: slug,
|
|
1158
|
-
path: path,
|
|
1159
|
-
title: pageTitle,
|
|
1160
|
-
description: 'No description available',
|
|
1161
|
-
tags: tags.length > 0 ? tags : undefined,
|
|
1162
|
-
skipDetailSection: true // Mark as external/single-link entry
|
|
1163
|
-
});
|
|
1164
|
-
} else if (links.length >= 2) {
|
|
1165
|
-
// Two-link format: - [Title](#slug) [Tag1] [Tag2] - [Full Docs](./path/page.mdx)
|
|
1166
|
-
var sectionLink = links[0];
|
|
1167
|
-
var docsLink = links[1];
|
|
1168
|
-
var _pageTitle3 = extractPlainTextFromNode(sectionLink);
|
|
1169
|
-
var _slug = sectionLink.url.replace('#', ''); // Extract slug from #slug
|
|
1170
|
-
var _path = docsLink.url; // Get path from full docs link
|
|
1171
|
-
|
|
1172
|
-
// Extract tags from text nodes between the section link and full docs link
|
|
1173
|
-
// Tags are in the format [Tag] where Tag can be New, Hot, Beta, etc.
|
|
1174
|
-
var _tags = [];
|
|
1175
|
-
var foundSectionLink = false;
|
|
1176
|
-
var foundDocsLink = false;
|
|
1177
|
-
var _iterator12 = _createForOfIteratorHelper(_paragraphNode.children),
|
|
1178
|
-
_step12;
|
|
1179
|
-
try {
|
|
1180
|
-
for (_iterator12.s(); !(_step12 = _iterator12.n()).done;) {
|
|
1181
|
-
var _child = _step12.value;
|
|
1182
|
-
if (_child === sectionLink) {
|
|
1183
|
-
foundSectionLink = true;
|
|
1184
|
-
continue;
|
|
1185
|
-
}
|
|
1186
|
-
if (_child === docsLink) {
|
|
1187
|
-
foundDocsLink = true;
|
|
1188
|
-
break;
|
|
1189
|
-
}
|
|
1190
|
-
if (foundSectionLink && !foundDocsLink && _child.type === 'text') {
|
|
1191
|
-
// Match [Tag] patterns in the text
|
|
1192
|
-
var _tagRegex = /\[(\w+)\]/g;
|
|
1193
|
-
var _match = _tagRegex.exec(_child.value);
|
|
1194
|
-
while (_match !== null) {
|
|
1195
|
-
_tags.push(_match[1]);
|
|
1196
|
-
_match = _tagRegex.exec(_child.value);
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
// Only extract slug, path, title, and tags from the editable list
|
|
1202
|
-
// The description will be filled in from the details section
|
|
1203
|
-
} catch (err) {
|
|
1204
|
-
_iterator12.e(err);
|
|
1205
|
-
} finally {
|
|
1206
|
-
_iterator12.f();
|
|
1207
|
-
}
|
|
1208
|
-
pages.push({
|
|
1209
|
-
slug: _slug,
|
|
1210
|
-
path: _path,
|
|
1211
|
-
title: _pageTitle3,
|
|
1212
|
-
description: 'No description available',
|
|
1213
|
-
// Will be updated from details section
|
|
1214
|
-
tags: _tags.length > 0 ? _tags : undefined
|
|
1215
|
-
});
|
|
1216
|
-
}
|
|
983
|
+
if (foundLink && child.type === 'text') {
|
|
984
|
+
// Match [Tag] patterns in the text
|
|
985
|
+
const tagRegex = /\[(\w+)\]/g;
|
|
986
|
+
let match = tagRegex.exec(child.value);
|
|
987
|
+
while (match !== null) {
|
|
988
|
+
tags.push(match[1]);
|
|
989
|
+
match = tagRegex.exec(child.value);
|
|
1217
990
|
}
|
|
1218
|
-
return;
|
|
1219
991
|
}
|
|
992
|
+
}
|
|
1220
993
|
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
994
|
+
// These entries are preserved as-is in the editable section
|
|
995
|
+
// They won't have detail sections generated
|
|
996
|
+
pages.push({
|
|
997
|
+
slug,
|
|
998
|
+
path,
|
|
999
|
+
title: pageTitle,
|
|
1000
|
+
description: 'No description available',
|
|
1001
|
+
tags: tags.length > 0 ? tags : undefined,
|
|
1002
|
+
skipDetailSection: true // Mark as external/single-link entry
|
|
1003
|
+
});
|
|
1004
|
+
} else if (links.length >= 2) {
|
|
1005
|
+
// Two-link format: - [Title](#slug) [Tag1] [Tag2] - [Full Docs](./path/page.mdx)
|
|
1006
|
+
const sectionLink = links[0];
|
|
1007
|
+
const docsLink = links[1];
|
|
1008
|
+
const pageTitle = extractPlainTextFromNode(sectionLink);
|
|
1009
|
+
const slug = sectionLink.url.replace('#', ''); // Extract slug from #slug
|
|
1010
|
+
const path = docsLink.url; // Get path from full docs link
|
|
1011
|
+
|
|
1012
|
+
// Extract tags from text nodes between the section link and full docs link
|
|
1013
|
+
// Tags are in the format [Tag] where Tag can be New, Hot, Beta, etc.
|
|
1014
|
+
const tags = [];
|
|
1015
|
+
let foundSectionLink = false;
|
|
1016
|
+
let foundDocsLink = false;
|
|
1017
|
+
for (const child of paragraphNode.children) {
|
|
1018
|
+
if (child === sectionLink) {
|
|
1019
|
+
foundSectionLink = true;
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
if (child === docsLink) {
|
|
1023
|
+
foundDocsLink = true;
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
if (foundSectionLink && !foundDocsLink && child.type === 'text') {
|
|
1027
|
+
// Match [Tag] patterns in the text
|
|
1028
|
+
const tagRegex = /\[(\w+)\]/g;
|
|
1029
|
+
let match = tagRegex.exec(child.value);
|
|
1030
|
+
while (match !== null) {
|
|
1031
|
+
tags.push(match[1]);
|
|
1032
|
+
match = tagRegex.exec(child.value);
|
|
1259
1033
|
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1260
1036
|
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
// Parse exports - they're in a nested list within the same parent list item
|
|
1278
|
-
if (_paragraphText.startsWith('Exports:')) {
|
|
1279
|
-
var result = parseExportsFromListItem(parent);
|
|
1280
|
-
if (result.exports) {
|
|
1281
|
-
currentPage.exports = result.exports;
|
|
1282
|
-
}
|
|
1283
|
-
if (result.parts) {
|
|
1284
|
-
currentPage.parts = result.parts;
|
|
1285
|
-
}
|
|
1286
|
-
return;
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
// Parse sections - now they're in a nested list within the same parent list item
|
|
1290
|
-
if (_paragraphText.startsWith('Sections:')) {
|
|
1291
|
-
var _listItem$children2;
|
|
1292
|
-
// Find the nested list within this list item
|
|
1293
|
-
var listItem = parent;
|
|
1294
|
-
var nestedList = (_listItem$children2 = listItem.children) == null ? void 0 : _listItem$children2.find(function (child) {
|
|
1295
|
-
return child.type === 'list';
|
|
1296
|
-
});
|
|
1297
|
-
if (nestedList && nestedList.children) {
|
|
1298
|
-
currentPage.sections = parseHeadingSections(nestedList);
|
|
1299
|
-
} else {
|
|
1300
|
-
currentPage.sections = {};
|
|
1301
|
-
}
|
|
1302
|
-
return;
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
// Skip read more links
|
|
1307
|
-
if (_paragraphText.startsWith('[Read more]')) {
|
|
1308
|
-
return;
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
// Parse description (first paragraph after title, not in a list)
|
|
1312
|
-
if (!currentPage.description && (parent == null ? void 0 : parent.type) !== 'listItem') {
|
|
1313
|
-
currentPage.description = _paragraphText;
|
|
1314
|
-
// Store the AST nodes with position info stripped for clean serialization
|
|
1315
|
-
if (_paragraphNode2.children) {
|
|
1316
|
-
currentPage.descriptionMarkdown = stripPositions(_paragraphNode2.children);
|
|
1317
|
-
}
|
|
1318
|
-
return;
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1037
|
+
// Only extract slug, path, title, and tags from the editable list
|
|
1038
|
+
// The description will be filled in from the details section
|
|
1039
|
+
pages.push({
|
|
1040
|
+
slug,
|
|
1041
|
+
path,
|
|
1042
|
+
title: pageTitle,
|
|
1043
|
+
description: 'No description available',
|
|
1044
|
+
// Will be updated from details section
|
|
1045
|
+
tags: tags.length > 0 ? tags : undefined
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1321
1051
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1052
|
+
// Parse detail sections
|
|
1053
|
+
if (currentSection === 'details') {
|
|
1054
|
+
// Start of a new page section (H2)
|
|
1055
|
+
if (node.type === 'heading') {
|
|
1056
|
+
const headingNode = node;
|
|
1057
|
+
if (headingNode.depth === 2) {
|
|
1058
|
+
// Save previous page if exists
|
|
1059
|
+
if (currentPage?.slug) {
|
|
1060
|
+
const savedSlug = currentPage.slug;
|
|
1061
|
+
const foundIndex = pages.findIndex(c => c.slug === savedSlug);
|
|
1062
|
+
if (foundIndex !== -1) {
|
|
1063
|
+
pages[foundIndex] = {
|
|
1064
|
+
...pages[foundIndex],
|
|
1065
|
+
...currentPage
|
|
1066
|
+
};
|
|
1331
1067
|
}
|
|
1068
|
+
}
|
|
1069
|
+
const pageTitle = extractPlainTextFromNode(headingNode);
|
|
1070
|
+
// Find the page in the existing pages array by matching the title
|
|
1071
|
+
const existingPage = pages.find(p => p.title === pageTitle);
|
|
1072
|
+
if (existingPage) {
|
|
1073
|
+
// Start updating this existing page
|
|
1074
|
+
currentPage = {
|
|
1075
|
+
slug: existingPage.slug,
|
|
1076
|
+
title: pageTitle
|
|
1077
|
+
};
|
|
1078
|
+
} else {
|
|
1079
|
+
// If no matching page found, create a new one with slug from title
|
|
1080
|
+
const slug = titleToSlug(pageTitle);
|
|
1081
|
+
currentPage = {
|
|
1082
|
+
slug,
|
|
1083
|
+
title: pageTitle
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1332
1089
|
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
return;
|
|
1349
|
-
}
|
|
1350
|
-
});
|
|
1090
|
+
// Parse description (first paragraph after title) and keywords/sections
|
|
1091
|
+
if (currentPage && node.type === 'paragraph') {
|
|
1092
|
+
const paragraphNode = node;
|
|
1093
|
+
const paragraphText = extractTextFromNode(paragraphNode);
|
|
1094
|
+
|
|
1095
|
+
// Check if we're in a list item
|
|
1096
|
+
if (parent?.type === 'listItem') {
|
|
1097
|
+
// Parse keywords
|
|
1098
|
+
if (paragraphText.startsWith('Keywords:')) {
|
|
1099
|
+
const keywordsText = paragraphText.replace('Keywords:', '').trim();
|
|
1100
|
+
currentPage.keywords = keywordsText.split(',').map(k => k.trim());
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1351
1103
|
|
|
1352
|
-
//
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
console.error('Failed to parse page metadata from raw export:', error);
|
|
1104
|
+
// Parse exports - they're in a nested list within the same parent list item
|
|
1105
|
+
if (paragraphText.startsWith('Exports:')) {
|
|
1106
|
+
const result = parseExportsFromListItem(parent);
|
|
1107
|
+
if (result.exports) {
|
|
1108
|
+
currentPage.exports = result.exports;
|
|
1109
|
+
}
|
|
1110
|
+
if (result.parts) {
|
|
1111
|
+
currentPage.parts = result.parts;
|
|
1361
1112
|
}
|
|
1113
|
+
return;
|
|
1362
1114
|
}
|
|
1363
1115
|
|
|
1364
|
-
//
|
|
1365
|
-
if (
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
}
|
|
1116
|
+
// Parse sections - now they're in a nested list within the same parent list item
|
|
1117
|
+
if (paragraphText.startsWith('Sections:')) {
|
|
1118
|
+
// Find the nested list within this list item
|
|
1119
|
+
const listItem = parent;
|
|
1120
|
+
const nestedList = listItem.children?.find(child => child.type === 'list');
|
|
1121
|
+
if (nestedList && nestedList.children) {
|
|
1122
|
+
currentPage.sections = parseHeadingSections(nestedList);
|
|
1123
|
+
} else {
|
|
1124
|
+
currentPage.sections = {};
|
|
1374
1125
|
}
|
|
1126
|
+
return;
|
|
1375
1127
|
}
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// Skip read more links
|
|
1131
|
+
if (paragraphText.startsWith('[Read more]')) {
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// Parse description (first paragraph after title, not in a list)
|
|
1136
|
+
if (!currentPage.description && parent?.type !== 'listItem') {
|
|
1137
|
+
currentPage.description = paragraphText;
|
|
1138
|
+
// Store the AST nodes with position info stripped for clean serialization
|
|
1139
|
+
if (paragraphNode.children) {
|
|
1140
|
+
currentPage.descriptionMarkdown = stripPositions(paragraphNode.children);
|
|
1379
1141
|
}
|
|
1380
|
-
return
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// Parse image
|
|
1147
|
+
if (currentPage && node.type === 'image') {
|
|
1148
|
+
const imageNode = node;
|
|
1149
|
+
currentPage.image = {
|
|
1150
|
+
url: imageNode.url,
|
|
1151
|
+
alt: imageNode.alt || currentPage.title || currentPage.slug || ''
|
|
1152
|
+
};
|
|
1153
|
+
return;
|
|
1389
1154
|
}
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// Parse metadata export section (code block or raw export statement after metadata comment)
|
|
1158
|
+
if (currentSection === 'metadata' && node.type === 'code') {
|
|
1159
|
+
const codeNode = node;
|
|
1160
|
+
const codeValue = codeNode.value;
|
|
1161
|
+
// Parse the export const metadata = { ... } statement
|
|
1162
|
+
const metadataMatch = codeValue.match(/export\s+const\s+metadata\s*=\s*(\{[\s\S]*\})/);
|
|
1163
|
+
if (metadataMatch) {
|
|
1164
|
+
try {
|
|
1165
|
+
// Use Function constructor to safely parse the object literal
|
|
1166
|
+
// eslint-disable-next-line no-new-func
|
|
1167
|
+
pageMetadata = new Function(`return ${metadataMatch[1]}`)();
|
|
1168
|
+
} catch (error) {
|
|
1169
|
+
console.error('Failed to parse page metadata:', error);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
|
|
1176
|
+
// Also try to parse metadata from raw export statement in the markdown
|
|
1177
|
+
// This handles MDX files where the export is not in a code block
|
|
1178
|
+
const metadataExportMatch = markdown.match(/\[\/\/\]: # 'This file is autogenerated, but the following metadata can be modified\.'\s*\n\s*\n\s*export\s+const\s+metadata\s*=\s*(\{[\s\S]*?\n\})/);
|
|
1179
|
+
if (metadataExportMatch && !pageMetadata) {
|
|
1180
|
+
try {
|
|
1181
|
+
// eslint-disable-next-line no-new-func
|
|
1182
|
+
pageMetadata = new Function(`return ${metadataExportMatch[1]}`)();
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
console.error('Failed to parse page metadata from raw export:', error);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
// Save last page if exists
|
|
1189
|
+
if (currentPage) {
|
|
1190
|
+
const partialPage = currentPage;
|
|
1191
|
+
if (partialPage.slug) {
|
|
1192
|
+
const foundIndex = pages.findIndex(c => c.slug === partialPage.slug);
|
|
1193
|
+
if (foundIndex !== -1) {
|
|
1194
|
+
pages[foundIndex] = {
|
|
1195
|
+
...pages[foundIndex],
|
|
1196
|
+
...partialPage
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
if (!title) {
|
|
1202
|
+
return null;
|
|
1203
|
+
}
|
|
1204
|
+
return {
|
|
1205
|
+
title,
|
|
1206
|
+
description,
|
|
1207
|
+
pages,
|
|
1208
|
+
pageMetadata,
|
|
1209
|
+
indexWrapperComponent
|
|
1210
|
+
};
|
|
1393
1211
|
}
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* Extracts plain text content from any mdast node without markdown formatting
|
|
1215
|
+
* Used for titles and other places where we don't want markdown syntax
|
|
1216
|
+
*/
|
|
1394
1217
|
function extractPlainTextFromNode(node) {
|
|
1395
1218
|
if (node.type === 'text') {
|
|
1396
1219
|
return node.value;
|
|
@@ -1399,9 +1222,7 @@ function extractPlainTextFromNode(node) {
|
|
|
1399
1222
|
return node.value;
|
|
1400
1223
|
}
|
|
1401
1224
|
if (node.children) {
|
|
1402
|
-
|
|
1403
|
-
return extractPlainTextFromNode(child);
|
|
1404
|
-
}).join('');
|
|
1225
|
+
const extractedText = node.children.map(child => extractPlainTextFromNode(child)).join('');
|
|
1405
1226
|
// For paragraph nodes, replace sequences of regular whitespace (spaces, tabs, newlines)
|
|
1406
1227
|
// with a single space, but preserve non-breaking spaces and other special whitespace
|
|
1407
1228
|
if (node.type === 'paragraph') {
|
|
@@ -1421,30 +1242,22 @@ function extractTextFromNode(node) {
|
|
|
1421
1242
|
return node.value;
|
|
1422
1243
|
}
|
|
1423
1244
|
if (node.type === 'inlineCode') {
|
|
1424
|
-
return
|
|
1245
|
+
return `\`${node.value}\``;
|
|
1425
1246
|
}
|
|
1426
1247
|
if (node.type === 'link') {
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
}).join('');
|
|
1430
|
-
return "[".concat(linkText, "](").concat(node.url, ")");
|
|
1248
|
+
const linkText = node.children.map(child => extractTextFromNode(child)).join('');
|
|
1249
|
+
return `[${linkText}](${node.url})`;
|
|
1431
1250
|
}
|
|
1432
1251
|
if (node.type === 'emphasis') {
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
}).join('');
|
|
1436
|
-
return "*".concat(emphasisText, "*");
|
|
1252
|
+
const emphasisText = node.children.map(child => extractTextFromNode(child)).join('');
|
|
1253
|
+
return `*${emphasisText}*`;
|
|
1437
1254
|
}
|
|
1438
1255
|
if (node.type === 'strong') {
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
}).join('');
|
|
1442
|
-
return "**".concat(strongText, "**");
|
|
1256
|
+
const strongText = node.children.map(child => extractTextFromNode(child)).join('');
|
|
1257
|
+
return `**${strongText}**`;
|
|
1443
1258
|
}
|
|
1444
1259
|
if (node.children) {
|
|
1445
|
-
|
|
1446
|
-
return extractTextFromNode(child);
|
|
1447
|
-
}).join('');
|
|
1260
|
+
const extractedText = node.children.map(child => extractTextFromNode(child)).join('');
|
|
1448
1261
|
// For paragraph nodes, replace sequences of regular whitespace (spaces, tabs, newlines)
|
|
1449
1262
|
// with a single space, but preserve non-breaking spaces and other special whitespace
|
|
1450
1263
|
if (node.type === 'paragraph') {
|