@mui/internal-markdown 2.0.11 → 2.0.13
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/extractImports.mjs +6 -0
- package/loader.mjs +134 -59
- package/package.json +4 -4
- package/parseMarkdown.test.mjs +1 -0
- package/prepareMarkdown.mjs +18 -2
- package/textToHash.test.mjs +1 -0
- package/vitest.config.mts +4 -0
package/extractImports.mjs
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
const importModuleRegexp =
|
|
2
4
|
/^\s*import (?:["'\s]*(?:[\w*{}\n, ]+)from\s*)?["'\s]*([^"'{}$\s]+)["'\s].*/gm;
|
|
3
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} code
|
|
8
|
+
* @returns {string[]}
|
|
9
|
+
*/
|
|
4
10
|
export default function extractImports(code) {
|
|
5
11
|
return (code.match(importModuleRegexp) || []).map((x) => x.replace(importModuleRegexp, '$1'));
|
|
6
12
|
}
|
package/loader.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
import { promises as fs, readdirSync, statSync } from 'fs';
|
|
2
4
|
import path from 'path';
|
|
3
5
|
import prepareMarkdown from './prepareMarkdown.mjs';
|
|
@@ -28,9 +30,24 @@ function moduleIDToJSIdentifier(moduleID) {
|
|
|
28
30
|
.join('');
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {Record<string, Record<string, string>> } ComponentPackageMapping
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** @type {ComponentPackageMapping | null} */
|
|
31
38
|
let componentPackageMapping = null;
|
|
32
39
|
|
|
40
|
+
/**
|
|
41
|
+
* @typedef {Object} Package
|
|
42
|
+
* @property {string[]} paths
|
|
43
|
+
* @property {string} productId
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {Package[]} packages
|
|
48
|
+
*/
|
|
33
49
|
function findComponents(packages) {
|
|
50
|
+
/** @type {ComponentPackageMapping} */
|
|
34
51
|
const mapping = {};
|
|
35
52
|
|
|
36
53
|
packages.forEach((pkg) => {
|
|
@@ -57,7 +74,48 @@ function findComponents(packages) {
|
|
|
57
74
|
}
|
|
58
75
|
|
|
59
76
|
/**
|
|
60
|
-
* @
|
|
77
|
+
* @typedef {Object} LoaderOptions
|
|
78
|
+
* @property {Package[]} packages
|
|
79
|
+
* @property {string[]} languagesInProgress
|
|
80
|
+
* @property {string} workspaceRoot
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @typedef {Object} ModuleData
|
|
85
|
+
* @property {string} module
|
|
86
|
+
* @property {string} raw
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @typedef {Object} Translation
|
|
91
|
+
* @property {string} filename
|
|
92
|
+
* @property {string} userLanguage
|
|
93
|
+
* @property {string} [markdown]
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @typedef {Object} Demo
|
|
98
|
+
* @property {string} module
|
|
99
|
+
* @property {string} [moduleTS]
|
|
100
|
+
* @property {string} [moduleTailwind]
|
|
101
|
+
* @property {string} [moduleTSTailwind]
|
|
102
|
+
* @property {string} [moduleCSS]
|
|
103
|
+
* @property {string} [moduleTSCSS]
|
|
104
|
+
* @property {string} raw
|
|
105
|
+
* @property {string} [rawTS]
|
|
106
|
+
* @property {string} [rawTailwind]
|
|
107
|
+
* @property {string} [rawTailwindTS]
|
|
108
|
+
* @property {string} [rawCSS]
|
|
109
|
+
* @property {string} [rawCSSTS]
|
|
110
|
+
* @property {string} [jsxPreview]
|
|
111
|
+
* @property {string} [tailwindJsxPreview]
|
|
112
|
+
* @property {string} [cssJsxPreview]
|
|
113
|
+
* @property {Object.<string, ModuleData[]>} [relativeModules]
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @type {import('webpack').LoaderDefinitionFunction<LoaderOptions>}
|
|
118
|
+
* @this {import('webpack').LoaderContext<LoaderOptions>}
|
|
61
119
|
*/
|
|
62
120
|
export default async function demoLoader() {
|
|
63
121
|
const englishFilepath = this.resourcePath;
|
|
@@ -71,41 +129,42 @@ export default async function demoLoader() {
|
|
|
71
129
|
|
|
72
130
|
const files = await fs.readdir(path.dirname(englishFilepath));
|
|
73
131
|
const translations = await Promise.all(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
132
|
+
/** @type {Translation[]} */ (
|
|
133
|
+
files
|
|
134
|
+
.map((filename) => {
|
|
135
|
+
if (filename === `${englishFilename}.md`) {
|
|
136
|
+
return {
|
|
137
|
+
filename,
|
|
138
|
+
userLanguage: 'en',
|
|
139
|
+
};
|
|
140
|
+
}
|
|
82
141
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
142
|
+
const matchNotEnglishMarkdown = filename.match(notEnglishMarkdownRegExp);
|
|
143
|
+
|
|
144
|
+
if (
|
|
145
|
+
filename.startsWith(englishFilename) &&
|
|
146
|
+
matchNotEnglishMarkdown !== null &&
|
|
147
|
+
options.languagesInProgress.includes(matchNotEnglishMarkdown[1])
|
|
148
|
+
) {
|
|
149
|
+
return {
|
|
150
|
+
filename,
|
|
151
|
+
userLanguage: matchNotEnglishMarkdown[1],
|
|
152
|
+
};
|
|
153
|
+
}
|
|
95
154
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
155
|
+
return null;
|
|
156
|
+
})
|
|
157
|
+
.filter((translation) => translation)
|
|
158
|
+
).map(async (translation) => {
|
|
159
|
+
const filepath = path.join(path.dirname(englishFilepath), translation.filename);
|
|
160
|
+
this.addDependency(filepath);
|
|
161
|
+
const markdown = await fs.readFile(filepath, { encoding: 'utf8' });
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
...translation,
|
|
165
|
+
markdown,
|
|
166
|
+
};
|
|
167
|
+
}),
|
|
109
168
|
);
|
|
110
169
|
|
|
111
170
|
// Use .. as the docs runs from the /docs folder
|
|
@@ -121,25 +180,33 @@ export default async function demoLoader() {
|
|
|
121
180
|
options,
|
|
122
181
|
});
|
|
123
182
|
|
|
183
|
+
/** @type {Record<string, Demo>} */
|
|
124
184
|
const demos = {};
|
|
185
|
+
/** @type {Set<string>} */
|
|
125
186
|
const importedModuleIDs = new Set();
|
|
187
|
+
/** @type {Record<string, string>} */
|
|
126
188
|
const components = {};
|
|
189
|
+
/** @type {Set<string>} */
|
|
127
190
|
const demoModuleIDs = new Set();
|
|
191
|
+
/** @type {Set<string>} */
|
|
128
192
|
const componentModuleIDs = new Set();
|
|
193
|
+
/** @type {Set<string>} */
|
|
129
194
|
const nonEditableDemos = new Set();
|
|
195
|
+
/** @type {Map<string, Map<string, string[]>>} */
|
|
130
196
|
const relativeModules = new Map();
|
|
197
|
+
/** @type {string[]} */
|
|
131
198
|
const demoNames = Array.from(
|
|
132
199
|
new Set(
|
|
133
|
-
|
|
134
|
-
.filter((markdownOrComponentConfig) => {
|
|
200
|
+
/** @type {import('./prepareMarkdown.mjs').DemoEntry[]} */ (
|
|
201
|
+
docs.en.rendered.filter((markdownOrComponentConfig) => {
|
|
135
202
|
return typeof markdownOrComponentConfig !== 'string' && markdownOrComponentConfig.demo;
|
|
136
203
|
})
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
204
|
+
).map((demoConfig) => {
|
|
205
|
+
if (demoConfig.hideToolbar) {
|
|
206
|
+
nonEditableDemos.add(demoConfig.demo);
|
|
207
|
+
}
|
|
208
|
+
return demoConfig.demo;
|
|
209
|
+
}),
|
|
143
210
|
),
|
|
144
211
|
);
|
|
145
212
|
|
|
@@ -204,21 +271,21 @@ export default async function demoLoader() {
|
|
|
204
271
|
|
|
205
272
|
/**
|
|
206
273
|
* Inserts the moduleData into the relativeModules object
|
|
207
|
-
* @param string demoName
|
|
208
|
-
* @param {
|
|
209
|
-
* @param string variant
|
|
210
|
-
* @example updateRelativeModules(demoName, {module: 'constants.js', raw: ... }, 'JS') => demos[demoName].relativeModules[variant].push(moduleData)
|
|
274
|
+
* @param {string} demoName
|
|
275
|
+
* @param {ModuleData} moduleData
|
|
276
|
+
* @param {string} variant
|
|
211
277
|
*/
|
|
212
278
|
function updateRelativeModules(demoName, moduleData, variant) {
|
|
213
|
-
|
|
279
|
+
const variantModule = /** @type {Object.<string, ModuleData[]>} */ (
|
|
280
|
+
demos[demoName].relativeModules
|
|
281
|
+
);
|
|
282
|
+
if (variantModule[variant]) {
|
|
214
283
|
// Avoid duplicates
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
) {
|
|
218
|
-
demos[demoName].relativeModules[variant].push(moduleData);
|
|
284
|
+
if (!variantModule[variant].some((elem) => elem.module === moduleData.module)) {
|
|
285
|
+
variantModule[variant].push(moduleData);
|
|
219
286
|
}
|
|
220
287
|
} else {
|
|
221
|
-
|
|
288
|
+
variantModule[variant] = [moduleData];
|
|
222
289
|
}
|
|
223
290
|
}
|
|
224
291
|
|
|
@@ -460,10 +527,15 @@ export default async function demoLoader() {
|
|
|
460
527
|
demos[demoName].relativeModules = {};
|
|
461
528
|
}
|
|
462
529
|
|
|
530
|
+
/** @type {Record<string, Set<string>>} */
|
|
463
531
|
const addedModulesRelativeToModulePathPerVariant = {};
|
|
464
532
|
|
|
533
|
+
const demoRelativeModules = /** @type {Map<string, string[]>} */ (
|
|
534
|
+
relativeModules.get(demoName)
|
|
535
|
+
);
|
|
536
|
+
|
|
465
537
|
await Promise.all(
|
|
466
|
-
Array.from(
|
|
538
|
+
Array.from(demoRelativeModules).map(async ([relativeModuleID, variants]) => {
|
|
467
539
|
for (const variant of variants) {
|
|
468
540
|
addedModulesRelativeToModulePathPerVariant[variant] ??= new Set();
|
|
469
541
|
const addedModulesRelativeToModulePath =
|
|
@@ -523,7 +595,9 @@ export default async function demoLoader() {
|
|
|
523
595
|
// We are only iterating through an array that looks
|
|
524
596
|
// like this: ['JS', 'TS'], so it is safe to await
|
|
525
597
|
// eslint-disable-next-line no-await-in-loop
|
|
526
|
-
const rawEntry = await fs.readFile(entryModuleFilePath, {
|
|
598
|
+
const rawEntry = await fs.readFile(entryModuleFilePath, {
|
|
599
|
+
encoding: 'utf8',
|
|
600
|
+
});
|
|
527
601
|
|
|
528
602
|
extractImports(rawEntry).forEach((importModuleID) => {
|
|
529
603
|
// detect relative import
|
|
@@ -570,17 +644,18 @@ export default async function demoLoader() {
|
|
|
570
644
|
}),
|
|
571
645
|
);
|
|
572
646
|
|
|
647
|
+
/** @type {string[]} */
|
|
573
648
|
const componentNames = Array.from(
|
|
574
649
|
new Set(
|
|
575
|
-
|
|
576
|
-
.filter((markdownOrComponentConfig) => {
|
|
650
|
+
/** @type {import('./prepareMarkdown.mjs').ComponentEntry[]} */ (
|
|
651
|
+
docs.en.rendered.filter((markdownOrComponentConfig) => {
|
|
577
652
|
return (
|
|
578
653
|
typeof markdownOrComponentConfig !== 'string' && markdownOrComponentConfig.component
|
|
579
654
|
);
|
|
580
655
|
})
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
656
|
+
).map((componentConfig) => {
|
|
657
|
+
return componentConfig.component;
|
|
658
|
+
}),
|
|
584
659
|
),
|
|
585
660
|
);
|
|
586
661
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-markdown",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.13",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "MUI markdown parser. This is an internal package not meant for general use.",
|
|
6
6
|
"main": "./index.mjs",
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@babel/runtime": "^7.28.4",
|
|
25
|
-
"
|
|
26
|
-
"marked": "^
|
|
25
|
+
"es-toolkit": "^1.41.0",
|
|
26
|
+
"marked": "^17.0.1",
|
|
27
27
|
"prismjs": "^1.30.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@types/chai": "^
|
|
30
|
+
"@types/chai": "^5.2.3",
|
|
31
31
|
"chai": "^6.0.1"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
package/parseMarkdown.test.mjs
CHANGED
|
@@ -283,6 +283,7 @@ title: "Our docs just got a major upgrade—here's what that means for you"
|
|
|
283
283
|
describe('createRender', () => {
|
|
284
284
|
it('should collect headers correctly', () => {
|
|
285
285
|
const context = { toc: [], headingHashes: {} };
|
|
286
|
+
// eslint-disable-next-line testing-library/render-result-naming-convention
|
|
286
287
|
const render = createRender(context);
|
|
287
288
|
|
|
288
289
|
expect(
|
package/prepareMarkdown.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import kebabCase from '
|
|
3
|
+
import { kebabCase } from 'es-toolkit/string';
|
|
4
4
|
import {
|
|
5
5
|
createRender,
|
|
6
6
|
getContents,
|
|
@@ -11,6 +11,9 @@ import {
|
|
|
11
11
|
getTitle,
|
|
12
12
|
} from './parseMarkdown.mjs';
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @type {string | string[]}
|
|
16
|
+
*/
|
|
14
17
|
const BaseUIReexportedComponents = [];
|
|
15
18
|
|
|
16
19
|
/**
|
|
@@ -47,17 +50,30 @@ function resolveComponentApiUrl(productId, componentPkg, component) {
|
|
|
47
50
|
return `/${productId}/api/${kebabCase(component)}/`;
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {{ component: string, demo?: undefined }} ComponentEntry
|
|
55
|
+
* @typedef {{ component?: undefined, demo: string, hideToolbar?: boolean }} DemoEntry
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @typedef {{ rendered: Array<string | ComponentEntry | DemoEntry> }} TranslatedDoc
|
|
60
|
+
*/
|
|
61
|
+
|
|
50
62
|
/**
|
|
51
63
|
* @param {object} config
|
|
52
64
|
* @param {Array<{ markdown: string, filename: string, userLanguage: string }>} config.translations - Mapping of locale to its markdown
|
|
53
65
|
* @param {string} config.fileRelativeContext - posix filename relative to repository root directory
|
|
54
66
|
* @param {object} config.options - provided to the webpack loader
|
|
67
|
+
* @param {string} config.options.workspaceRoot - The absolute path of the repository root directory
|
|
68
|
+
* @param {object} [config.componentPackageMapping] - Mapping of productId to mapping of component name to package name
|
|
69
|
+
* @example { 'material': { 'Button': 'mui-material' } }
|
|
70
|
+
* @returns {{ docs: Record<string, TranslatedDoc> }} - Mapping of locale to its prepared markdown
|
|
55
71
|
*/
|
|
56
72
|
function prepareMarkdown(config) {
|
|
57
73
|
const { fileRelativeContext, translations, componentPackageMapping = {}, options } = config;
|
|
58
74
|
|
|
59
75
|
/**
|
|
60
|
-
* @type {Record<string,
|
|
76
|
+
* @type {Record<string, TranslatedDoc>}
|
|
61
77
|
*/
|
|
62
78
|
const docs = {};
|
|
63
79
|
const headingHashes = {};
|
package/textToHash.test.mjs
CHANGED
|
@@ -17,6 +17,7 @@ describe('textToHash', () => {
|
|
|
17
17
|
];
|
|
18
18
|
table.forEach((entry, index) => {
|
|
19
19
|
const [markdown, expected] = entry;
|
|
20
|
+
// eslint-disable-next-line testing-library/render-result-naming-convention
|
|
20
21
|
const text = renderInlineMarkdown(markdown, { mangle: false, headerIds: false });
|
|
21
22
|
const actual = textToHash(text);
|
|
22
23
|
|