@mui/internal-markdown 1.0.1 → 1.0.3
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/loader.js +131 -4
- package/package.json +3 -3
- package/parseMarkdown.js +1 -5
- package/parseMarkdown.test.js +3 -3
- package/prepareMarkdown.js +1 -1
package/loader.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { promises: fs, readdirSync } = require('fs');
|
|
1
|
+
const { promises: fs, readdirSync, statSync } = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const prepareMarkdown = require('./prepareMarkdown');
|
|
4
4
|
const extractImports = require('./extractImports');
|
|
@@ -126,6 +126,8 @@ module.exports = async function demoLoader() {
|
|
|
126
126
|
const components = {};
|
|
127
127
|
const demoModuleIDs = new Set();
|
|
128
128
|
const componentModuleIDs = new Set();
|
|
129
|
+
const nonEditableDemos = new Set();
|
|
130
|
+
const relativeModules = new Map();
|
|
129
131
|
const demoNames = Array.from(
|
|
130
132
|
new Set(
|
|
131
133
|
docs.en.rendered
|
|
@@ -133,11 +135,71 @@ module.exports = async function demoLoader() {
|
|
|
133
135
|
return typeof markdownOrComponentConfig !== 'string' && markdownOrComponentConfig.demo;
|
|
134
136
|
})
|
|
135
137
|
.map((demoConfig) => {
|
|
138
|
+
if (demoConfig.hideToolbar) {
|
|
139
|
+
nonEditableDemos.add(demoConfig.demo);
|
|
140
|
+
}
|
|
136
141
|
return demoConfig.demo;
|
|
137
142
|
}),
|
|
138
143
|
),
|
|
139
144
|
);
|
|
140
145
|
|
|
146
|
+
/**
|
|
147
|
+
* @param {*} demoName
|
|
148
|
+
* @param {*} moduleFilepath
|
|
149
|
+
* @param {*} variant
|
|
150
|
+
* @param {*} importModuleID
|
|
151
|
+
* @example detectRelativeImports('ComboBox.js', '', JS', './top100Films') => relativeModules.set('ComboBox.js', new Map([['./top100Films.js', ['JS']]]))
|
|
152
|
+
*/
|
|
153
|
+
function detectRelativeImports(demoName, moduleFilepath, variant, importModuleID) {
|
|
154
|
+
if (importModuleID.startsWith('.')) {
|
|
155
|
+
let relativeModuleFilename = importModuleID;
|
|
156
|
+
const demoMap = relativeModules.get(demoName);
|
|
157
|
+
// If the moduleID does not end with an extension, or ends with an unsupported extension (e.g. ".styling") we need to resolve it
|
|
158
|
+
// Fastest way to get a file extension, see: https://stackoverflow.com/a/12900504/
|
|
159
|
+
const importType = importModuleID.slice(
|
|
160
|
+
(Math.max(0, importModuleID.lastIndexOf('.')) || Infinity) + 1,
|
|
161
|
+
);
|
|
162
|
+
const supportedTypes = ['js', 'jsx', 'ts', 'tsx', 'css', 'json'];
|
|
163
|
+
if (!importType || !supportedTypes.includes(importType)) {
|
|
164
|
+
// If the demo is a JS demo, we can assume that the relative import is either
|
|
165
|
+
// a `.js` or a `.jsx` file, with `.js` taking precedence over `.jsx`
|
|
166
|
+
// likewise for TS demos, with `.ts` taking precedence over `.tsx`
|
|
167
|
+
const extensions =
|
|
168
|
+
variant === 'JS' ? ['.js', '.jsx', '.ts', '.tsx'] : ['.ts', '.tsx', '.js', '.jsx'];
|
|
169
|
+
const extension = extensions.find((ext) => {
|
|
170
|
+
try {
|
|
171
|
+
return statSync(path.join(moduleFilepath, '..', `${importModuleID}${ext}`));
|
|
172
|
+
} catch (error) {
|
|
173
|
+
// If the file does not exist, we return false and continue to the next extension
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
if (!extension) {
|
|
178
|
+
throw new Error(
|
|
179
|
+
[
|
|
180
|
+
`You are trying to import a module "${importModuleID}" in the demo "${demoName}" that could not be resolved.`,
|
|
181
|
+
`Please make sure that one of the following file exists:`,
|
|
182
|
+
...extensions.map((ext) => `- ${importModuleID}${ext}`),
|
|
183
|
+
].join('\n'),
|
|
184
|
+
);
|
|
185
|
+
} else {
|
|
186
|
+
relativeModuleFilename = `${importModuleID}${extension}`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (!demoMap) {
|
|
191
|
+
relativeModules.set(demoName, new Map([[relativeModuleFilename, [variant]]]));
|
|
192
|
+
} else {
|
|
193
|
+
const variantArray = demoMap.get(relativeModuleFilename);
|
|
194
|
+
if (variantArray) {
|
|
195
|
+
variantArray.push(variant);
|
|
196
|
+
} else {
|
|
197
|
+
demoMap.set(relativeModuleFilename, [variant]);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
141
203
|
await Promise.all(
|
|
142
204
|
demoNames.map(async (demoName) => {
|
|
143
205
|
const multipleDemoVersionsUsed = !demoName.endsWith('.js');
|
|
@@ -164,9 +226,15 @@ module.exports = async function demoLoader() {
|
|
|
164
226
|
raw: await fs.readFile(moduleFilepath, { encoding: 'utf8' }),
|
|
165
227
|
};
|
|
166
228
|
demoModuleIDs.add(moduleID);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
)
|
|
229
|
+
|
|
230
|
+
// Skip non-editable demos
|
|
231
|
+
if (!nonEditableDemos.has(demoName)) {
|
|
232
|
+
extractImports(demos[demoName].raw).forEach((importModuleID) => {
|
|
233
|
+
// detect relative import
|
|
234
|
+
detectRelativeImports(demoName, moduleFilepath, 'JS', importModuleID);
|
|
235
|
+
importedModuleIDs.add(importModuleID);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
170
238
|
|
|
171
239
|
if (multipleDemoVersionsUsed) {
|
|
172
240
|
// Add Tailwind demo data
|
|
@@ -336,10 +404,69 @@ module.exports = async function demoLoader() {
|
|
|
336
404
|
// But this leads to building both demo version i.e. more build time.
|
|
337
405
|
demos[demoName].moduleTS = this.mode === 'production' ? moduleID : moduleTS;
|
|
338
406
|
demos[demoName].rawTS = rawTS;
|
|
407
|
+
|
|
408
|
+
// Extract relative imports from the TypeScript version
|
|
409
|
+
// of demos which have relative imports in the JS version
|
|
410
|
+
if (relativeModules.has(demoName)) {
|
|
411
|
+
extractImports(demos[demoName].rawTS).forEach((importModuleID) => {
|
|
412
|
+
detectRelativeImports(demoName, moduleTSFilepath, 'TS', importModuleID);
|
|
413
|
+
importedModuleIDs.add(importModuleID);
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
339
417
|
demoModuleIDs.add(demos[demoName].moduleTS);
|
|
340
418
|
} catch (error) {
|
|
341
419
|
// TS version of the demo doesn't exist. This is fine.
|
|
342
420
|
}
|
|
421
|
+
|
|
422
|
+
/* Map over relative import module IDs and resolve them
|
|
423
|
+
* while grouping by demo variant
|
|
424
|
+
* From:
|
|
425
|
+
* relativeModules: { 'ComboBox.js' =>
|
|
426
|
+
* { './top100Films.js' => ['JS', 'TS'] }
|
|
427
|
+
* }
|
|
428
|
+
* To:
|
|
429
|
+
* demos["ComboBox.js"].relativeModules = {
|
|
430
|
+
* JS: [{ module: './top100Films.js', raw: '...' }],
|
|
431
|
+
* TS: [{ module: './top100Films.js', raw: '...' }]
|
|
432
|
+
* }
|
|
433
|
+
* }
|
|
434
|
+
*/
|
|
435
|
+
|
|
436
|
+
if (relativeModules.has(demoName)) {
|
|
437
|
+
if (!demos[demoName].relativeModules) {
|
|
438
|
+
demos[demoName].relativeModules = {};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
await Promise.all(
|
|
442
|
+
Array.from(relativeModules.get(demoName)).map(async ([relativeModuleID, variants]) => {
|
|
443
|
+
let raw = '';
|
|
444
|
+
try {
|
|
445
|
+
raw = await fs.readFile(path.join(path.dirname(moduleFilepath), relativeModuleID), {
|
|
446
|
+
encoding: 'utf8',
|
|
447
|
+
});
|
|
448
|
+
} catch {
|
|
449
|
+
throw new Error(
|
|
450
|
+
`Could not find a module for the relative import "${relativeModuleID}" in the demo "${demoName}"`,
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const moduleData = { module: relativeModuleID, raw };
|
|
455
|
+
const modules = demos[demoName].relativeModules;
|
|
456
|
+
|
|
457
|
+
variants.forEach((variant) => {
|
|
458
|
+
if (modules[variant]) {
|
|
459
|
+
// Avoid duplicates
|
|
460
|
+
if (!modules[variant].some((elem) => elem.module === relativeModuleID)) {
|
|
461
|
+
modules[variant].push(moduleData);
|
|
462
|
+
}
|
|
463
|
+
} else {
|
|
464
|
+
modules[variant] = [moduleData];
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
}),
|
|
468
|
+
);
|
|
469
|
+
}
|
|
343
470
|
}),
|
|
344
471
|
);
|
|
345
472
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-markdown",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
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.js",
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
"directory": "packages/markdown"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@babel/runtime": "^7.
|
|
19
|
+
"@babel/runtime": "^7.24.4",
|
|
20
20
|
"lodash": "^4.17.21",
|
|
21
21
|
"marked": "^5.1.2",
|
|
22
22
|
"prismjs": "^1.29.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@types/chai": "^4.3.
|
|
25
|
+
"@types/chai": "^4.3.14",
|
|
26
26
|
"chai": "^4.4.1"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
package/parseMarkdown.js
CHANGED
|
@@ -364,11 +364,7 @@ function createRender(context) {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
return [
|
|
367
|
-
`<h${level} id="${hash}">`,
|
|
368
|
-
headingHtml,
|
|
369
|
-
`<a aria-labelledby="${hash}" class="anchor-link" href="#${hash}" tabindex="-1">`,
|
|
370
|
-
'<svg><use xlink:href="#anchor-link-icon" /></svg>',
|
|
371
|
-
'</a>',
|
|
367
|
+
`<h${level} id="${hash}"><a href="#${hash}" class="title-link-to-anchor">${headingHtml}<div class="anchor-icon"><svg><use xlink:href="#anchor-link-icon" /></svg></div></a>`,
|
|
372
368
|
`<button title="Post a comment" class="comment-link" data-feedback-hash="${hash}">`,
|
|
373
369
|
'<svg><use xlink:href="#comment-link-icon" /></svg>',
|
|
374
370
|
`</button>`,
|
package/parseMarkdown.test.js
CHANGED
|
@@ -295,9 +295,9 @@ authors:
|
|
|
295
295
|
).to.equal(
|
|
296
296
|
[
|
|
297
297
|
`<h1>Accordion</h1>`,
|
|
298
|
-
`<h2 id="basic-features"
|
|
299
|
-
`<h2 id="using-slots-and-slotprops"
|
|
300
|
-
`<h3 id="specific-example"
|
|
298
|
+
`<h2 id="basic-features"><a href="#basic-features" class="title-link-to-anchor">Basic features 🧪<div class="anchor-icon"><svg><use xlink:href="#anchor-link-icon" /></svg></div></a><button title="Post a comment" class="comment-link" data-feedback-hash="basic-features"><svg><use xlink:href="#comment-link-icon" /></svg></button></h2>`,
|
|
299
|
+
`<h2 id="using-slots-and-slotprops"><a href="#using-slots-and-slotprops" class="title-link-to-anchor">Using <code>slots</code> and <code>slotProps</code><div class="anchor-icon"><svg><use xlink:href="#anchor-link-icon" /></svg></div></a><button title="Post a comment" class="comment-link" data-feedback-hash="using-slots-and-slotprops"><svg><use xlink:href="#comment-link-icon" /></svg></button></h2>`,
|
|
300
|
+
`<h3 id="specific-example"><a href="#specific-example" class="title-link-to-anchor">Specific example<div class="anchor-icon"><svg><use xlink:href="#anchor-link-icon" /></svg></div></a><button title="Post a comment" class="comment-link" data-feedback-hash="specific-example"><svg><use xlink:href="#comment-link-icon" /></svg></button></h3>`,
|
|
301
301
|
].join(''),
|
|
302
302
|
);
|
|
303
303
|
|
package/prepareMarkdown.js
CHANGED