@rspress/plugin-preview 2.0.0-beta.9 → 2.0.0-rc.1
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/dist/index.d.ts +1 -1
- package/dist/index.js +57 -62
- package/index.d.ts +1 -2
- package/package.json +15 -20
- package/static/global-components/Container.tsx +2 -2
- package/static/global-components/Device.tsx +2 -17
- package/static/global-styles/entry.css +8 -7
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const
|
|
1
|
+
import node_net from "node:net";
|
|
2
|
+
import node_path, { dirname, join, resolve as external_node_path_resolve } from "node:path";
|
|
3
|
+
import { createRsbuild, mergeRsbuildConfig } from "@rsbuild/core";
|
|
4
|
+
import { pluginBabel } from "@rsbuild/plugin-babel";
|
|
5
|
+
import { pluginReact } from "@rsbuild/plugin-react";
|
|
6
|
+
import { pluginSolid } from "@rsbuild/plugin-solid";
|
|
7
|
+
import { RSPRESS_TEMP_DIR, normalizePosixPath, removeTrailingSlash } from "@rspress/core";
|
|
8
|
+
import { cloneDeep, isEqual } from "lodash";
|
|
9
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
10
|
+
import node_fs from "node:fs";
|
|
11
|
+
const staticPath = node_path.join(__dirname, '..', 'static');
|
|
12
|
+
const demoBlockComponentPath = node_path.join(staticPath, 'global-components', 'DemoBlock.tsx');
|
|
13
|
+
const virtualDir = node_path.join(process.cwd(), 'node_modules', RSPRESS_TEMP_DIR, 'virtual-demo');
|
|
13
14
|
const toValidVarName = (str)=>{
|
|
14
15
|
if (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(str)) return str;
|
|
15
16
|
return str.replace(/[^0-9a-zA-Z_$]/g, '_').replace(/^([0-9])/, '_$1');
|
|
@@ -30,13 +31,15 @@ const getLangFileExt = (lang)=>{
|
|
|
30
31
|
return lang;
|
|
31
32
|
}
|
|
32
33
|
};
|
|
33
|
-
function generateEntry(demos, framework, position, customEntry) {
|
|
34
|
+
async function generateEntry(demos, framework, position, customEntry) {
|
|
34
35
|
const sourceEntry = {};
|
|
35
|
-
const entryCssPath =
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const entryCssPath = join(staticPath, 'global-styles', 'entry.css');
|
|
37
|
+
await mkdir(virtualDir, {
|
|
38
|
+
recursive: true
|
|
39
|
+
});
|
|
40
|
+
if ('follow' === position) await Promise.all(Object.values(demos).map((routes)=>routes.map(async (route)=>{
|
|
38
41
|
const { id, path: demoPath } = route;
|
|
39
|
-
const entry =
|
|
42
|
+
const entry = join(virtualDir, `${id}.entry.tsx`);
|
|
40
43
|
const solidEntry = `
|
|
41
44
|
import { render } from 'solid-js/web';
|
|
42
45
|
import ${JSON.stringify(entryCssPath)};
|
|
@@ -54,11 +57,10 @@ function generateEntry(demos, framework, position, customEntry) {
|
|
|
54
57
|
entryCssPath,
|
|
55
58
|
demoPath
|
|
56
59
|
}) : 'react' === framework ? reactEntry : solidEntry;
|
|
57
|
-
|
|
60
|
+
await writeFile(entry, entryContent);
|
|
58
61
|
sourceEntry[id] = entry;
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
else Object.entries(demos).forEach(([key, routes])=>{
|
|
62
|
+
})).flat());
|
|
63
|
+
else await Promise.all(Object.entries(demos).map(async ([key, routes])=>{
|
|
62
64
|
if (0 === routes.length) return;
|
|
63
65
|
const reactContent = `
|
|
64
66
|
import { createRoot } from 'react-dom/client';
|
|
@@ -91,10 +93,10 @@ function generateEntry(demos, framework, position, customEntry) {
|
|
|
91
93
|
`;
|
|
92
94
|
const renderContent = 'solid' === framework ? solidContent : reactContent;
|
|
93
95
|
const id = `_${toValidVarName(key)}`;
|
|
94
|
-
const entry =
|
|
95
|
-
|
|
96
|
+
const entry = join(virtualDir, `${id}.entry.tsx`);
|
|
97
|
+
await writeFile(entry, renderContent);
|
|
96
98
|
sourceEntry[id] = entry;
|
|
97
|
-
});
|
|
99
|
+
}));
|
|
98
100
|
return sourceEntry;
|
|
99
101
|
}
|
|
100
102
|
const convert = function(test) {
|
|
@@ -303,13 +305,13 @@ const getExternalDemoContent = (tempVar)=>({
|
|
|
303
305
|
const remarkPlugin_demos = {};
|
|
304
306
|
const remarkCodeToDemo = function({ getRouteMeta, previewMode, defaultRenderMode, position, previewLanguages, previewCodeTransform }) {
|
|
305
307
|
const routeMeta = getRouteMeta();
|
|
306
|
-
|
|
308
|
+
node_fs.mkdirSync(virtualDir, {
|
|
307
309
|
recursive: true
|
|
308
310
|
});
|
|
309
311
|
const data = this.data();
|
|
310
312
|
return (tree, vfile)=>{
|
|
311
313
|
const demoMdx = [];
|
|
312
|
-
const route = routeMeta.find((meta)=>
|
|
314
|
+
const route = routeMeta.find((meta)=>normalizePosixPath(meta.absolutePath) === normalizePosixPath(vfile.path || vfile.history[0]));
|
|
313
315
|
if (!route) return;
|
|
314
316
|
const { pageName } = route;
|
|
315
317
|
remarkPlugin_demos[pageName] = [];
|
|
@@ -321,7 +323,7 @@ const remarkCodeToDemo = function({ getRouteMeta, previewMode, defaultRenderMode
|
|
|
321
323
|
remarkPlugin_demos[pageName].push({
|
|
322
324
|
title,
|
|
323
325
|
id: demoId,
|
|
324
|
-
path: relativePathReg.test(demoPath) ? (
|
|
326
|
+
path: relativePathReg.test(demoPath) ? external_node_path_resolve(vfile.dirname || dirname(vfile.path), demoPath) : demoPath
|
|
325
327
|
});
|
|
326
328
|
} else demoMdx.push(getASTNodeImport(`Demo${demoId}`, demoPath));
|
|
327
329
|
const tempVar = `externalDemoContent${externalDemoIndex}`;
|
|
@@ -377,13 +379,13 @@ const remarkCodeToDemo = function({ getRouteMeta, previewMode, defaultRenderMode
|
|
|
377
379
|
});
|
|
378
380
|
const isMobileMode = node.meta?.includes('mobile') || node.meta?.includes('iframe') || !node.meta?.includes('web') && !node.meta?.includes('internal') && 'iframe' === previewMode;
|
|
379
381
|
const id = generateId(pageName, index++);
|
|
380
|
-
const virtualModulePath =
|
|
382
|
+
const virtualModulePath = join(virtualDir, `${id}.${getLangFileExt(node.lang)}`);
|
|
381
383
|
constructDemoNode(id, virtualModulePath, node, isMobileMode);
|
|
382
|
-
if (
|
|
383
|
-
const content =
|
|
384
|
+
if (node_fs.existsSync(virtualModulePath)) {
|
|
385
|
+
const content = node_fs.readFileSync(virtualModulePath, 'utf-8');
|
|
384
386
|
if (content === value) return;
|
|
385
387
|
}
|
|
386
|
-
|
|
388
|
+
node_fs.writeFileSync(virtualModulePath, value);
|
|
387
389
|
}
|
|
388
390
|
});
|
|
389
391
|
tree.children.unshift(...demoMdx);
|
|
@@ -400,7 +402,7 @@ function pluginPreview(options) {
|
|
|
400
402
|
const previewMode = options?.previewMode ?? (isMobile ? 'iframe' : 'internal');
|
|
401
403
|
const { devPort = 7890, framework = 'react', position = iframePosition, builderConfig = {}, customEntry } = iframeOptions;
|
|
402
404
|
const globalUIComponents = 'fixed' === position ? [
|
|
403
|
-
|
|
405
|
+
join(staticPath, 'global-components', 'Device.tsx')
|
|
404
406
|
] : [];
|
|
405
407
|
const getRouteMeta = ()=>src_routeMeta;
|
|
406
408
|
let lastDemos;
|
|
@@ -419,7 +421,7 @@ function pluginPreview(options) {
|
|
|
419
421
|
async beforeBuild (_, isProd) {
|
|
420
422
|
if (!isProd) try {
|
|
421
423
|
await new Promise((resolve, reject)=>{
|
|
422
|
-
const server =
|
|
424
|
+
const server = node_net.createServer();
|
|
423
425
|
server.unref();
|
|
424
426
|
server.on('error', reject);
|
|
425
427
|
server.listen({
|
|
@@ -435,60 +437,54 @@ function pluginPreview(options) {
|
|
|
435
437
|
}
|
|
436
438
|
},
|
|
437
439
|
async afterBuild (config, isProd) {
|
|
438
|
-
if (
|
|
439
|
-
lastDemos =
|
|
440
|
+
if (isEqual(remarkPlugin_demos, lastDemos)) return;
|
|
441
|
+
lastDemos = cloneDeep(remarkPlugin_demos);
|
|
440
442
|
await devServer?.server?.close();
|
|
441
443
|
devServer = void 0;
|
|
442
|
-
const sourceEntry = generateEntry(remarkPlugin_demos, framework, position, customEntry);
|
|
443
|
-
const outDir =
|
|
444
|
+
const sourceEntry = await generateEntry(remarkPlugin_demos, framework, position, customEntry);
|
|
445
|
+
const outDir = join(config.outDir ?? 'doc_build', '~demo');
|
|
444
446
|
if (0 === Object.keys(sourceEntry).length) return;
|
|
445
|
-
const {
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
progressBar: false
|
|
449
|
-
},
|
|
447
|
+
const { source, output, performance } = clientConfig ?? {};
|
|
448
|
+
const { preEntry: _, ...otherSourceOptions } = source ?? {};
|
|
449
|
+
const rsbuildConfig = mergeRsbuildConfig({
|
|
450
450
|
server: {
|
|
451
451
|
port: devPort,
|
|
452
452
|
printUrls: ()=>void 0,
|
|
453
453
|
strictPort: true
|
|
454
454
|
},
|
|
455
|
+
dev: {
|
|
456
|
+
lazyCompilation: false
|
|
457
|
+
},
|
|
455
458
|
performance: {
|
|
456
459
|
...performance,
|
|
457
|
-
printFileSize: false
|
|
460
|
+
printFileSize: false,
|
|
461
|
+
buildCache: false
|
|
458
462
|
},
|
|
459
|
-
html,
|
|
460
463
|
source: {
|
|
461
|
-
...
|
|
464
|
+
...otherSourceOptions,
|
|
462
465
|
entry: sourceEntry
|
|
463
466
|
},
|
|
464
467
|
output: {
|
|
465
468
|
...output,
|
|
466
|
-
assetPrefix: output?.assetPrefix ? `${
|
|
469
|
+
assetPrefix: output?.assetPrefix ? `${removeTrailingSlash(output.assetPrefix)}/~demo` : '/~demo',
|
|
467
470
|
distPath: {
|
|
468
471
|
root: outDir
|
|
469
472
|
},
|
|
470
473
|
copy: void 0
|
|
471
|
-
}
|
|
472
|
-
plugins: config?.builderPlugins
|
|
474
|
+
}
|
|
473
475
|
}, builderConfig);
|
|
474
|
-
const rsbuildInstance = await
|
|
476
|
+
const rsbuildInstance = await createRsbuild({
|
|
475
477
|
callerName: 'rspress',
|
|
476
478
|
rsbuildConfig
|
|
477
479
|
});
|
|
478
|
-
const { pluginSass } = await import("@rsbuild/plugin-sass");
|
|
479
|
-
const { pluginLess } = await import("@rsbuild/plugin-less");
|
|
480
|
-
rsbuildInstance.addPlugins([
|
|
481
|
-
pluginSass(),
|
|
482
|
-
pluginLess()
|
|
483
|
-
]);
|
|
484
480
|
if ('solid' === framework) rsbuildInstance.addPlugins([
|
|
485
|
-
|
|
481
|
+
pluginBabel({
|
|
486
482
|
include: /\.(?:jsx|tsx)$/
|
|
487
483
|
}),
|
|
488
|
-
|
|
484
|
+
pluginSolid()
|
|
489
485
|
]);
|
|
490
486
|
if ('react' === framework) rsbuildInstance.addPlugins([
|
|
491
|
-
|
|
487
|
+
pluginReact()
|
|
492
488
|
]);
|
|
493
489
|
if (isProd) rsbuildInstance.build();
|
|
494
490
|
else devServer = await rsbuildInstance.startDevServer();
|
|
@@ -496,7 +492,7 @@ function pluginPreview(options) {
|
|
|
496
492
|
builderConfig: {
|
|
497
493
|
source: {
|
|
498
494
|
include: [
|
|
499
|
-
|
|
495
|
+
join(__dirname, '..')
|
|
500
496
|
]
|
|
501
497
|
},
|
|
502
498
|
tools: {
|
|
@@ -527,7 +523,6 @@ function pluginPreview(options) {
|
|
|
527
523
|
},
|
|
528
524
|
extendPageData (pageData, isProd) {
|
|
529
525
|
if (!isProd) pageData.devPort = port;
|
|
530
|
-
pageData.extraHighlightLanguages = previewLanguages;
|
|
531
526
|
},
|
|
532
527
|
markdown: {
|
|
533
528
|
remarkPlugins: [
|
|
@@ -544,11 +539,11 @@ function pluginPreview(options) {
|
|
|
544
539
|
]
|
|
545
540
|
],
|
|
546
541
|
globalComponents: [
|
|
547
|
-
|
|
542
|
+
join(staticPath, 'global-components', 'Container.tsx')
|
|
548
543
|
]
|
|
549
544
|
},
|
|
550
545
|
globalUIComponents,
|
|
551
|
-
globalStyles:
|
|
546
|
+
globalStyles: join(staticPath, 'global-styles', `${previewMode}.css`)
|
|
552
547
|
};
|
|
553
548
|
}
|
|
554
549
|
export { pluginPreview };
|
package/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rspress/plugin-preview",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-rc.1",
|
|
4
4
|
"description": "A plugin for rspress to preview the code block in markdown/mdx file.",
|
|
5
5
|
"bugs": "https://github.com/web-infra-dev/rspress/issues",
|
|
6
6
|
"repository": {
|
|
@@ -23,36 +23,32 @@
|
|
|
23
23
|
"static"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@rsbuild/core": "~1.
|
|
27
|
-
"@rsbuild/plugin-babel": "~1.0.
|
|
28
|
-
"@rsbuild/plugin-
|
|
29
|
-
"@rsbuild/plugin-
|
|
30
|
-
"@rsbuild/plugin-sass": "~1.3.1",
|
|
31
|
-
"@rsbuild/plugin-solid": "~1.0.5",
|
|
26
|
+
"@rsbuild/core": "~1.6.6",
|
|
27
|
+
"@rsbuild/plugin-babel": "~1.0.6",
|
|
28
|
+
"@rsbuild/plugin-react": "~1.4.2",
|
|
29
|
+
"@rsbuild/plugin-solid": "~1.0.6",
|
|
32
30
|
"lodash": "4.17.21",
|
|
33
|
-
"qrcode.react": "^4.2.0"
|
|
34
|
-
"@rspress/shared": "2.0.0-beta.9",
|
|
35
|
-
"@rspress/theme-default": "2.0.0-beta.9"
|
|
31
|
+
"qrcode.react": "^4.2.0"
|
|
36
32
|
},
|
|
37
33
|
"devDependencies": {
|
|
38
|
-
"@rslib/core": "0.
|
|
39
|
-
"@types/lodash": "^4.17.
|
|
34
|
+
"@rslib/core": "0.17.2",
|
|
35
|
+
"@types/lodash": "^4.17.20",
|
|
40
36
|
"@types/mdast": "^4.0.4",
|
|
41
37
|
"@types/node": "^22.8.1",
|
|
42
|
-
"@types/react": "^
|
|
43
|
-
"@types/react-dom": "^
|
|
38
|
+
"@types/react": "^19.2.5",
|
|
39
|
+
"@types/react-dom": "^19.2.3",
|
|
44
40
|
"mdast-util-mdx-jsx": "^3.2.0",
|
|
45
41
|
"mdast-util-mdxjs-esm": "^2.0.1",
|
|
46
|
-
"react": "^19.
|
|
47
|
-
"react-dom": "^19.
|
|
48
|
-
"react-router-dom": "^6.
|
|
49
|
-
"rsbuild-plugin-publint": "^0.3.
|
|
42
|
+
"react": "^19.2.0",
|
|
43
|
+
"react-dom": "^19.2.0",
|
|
44
|
+
"react-router-dom": "^6.30.2",
|
|
45
|
+
"rsbuild-plugin-publint": "^0.3.3",
|
|
50
46
|
"typescript": "^5.8.2",
|
|
51
47
|
"unified": "^11.0.5",
|
|
52
48
|
"unist-util-visit": "^5.0.0"
|
|
53
49
|
},
|
|
54
50
|
"peerDependencies": {
|
|
55
|
-
"@rspress/core": "^2.0.0-
|
|
51
|
+
"@rspress/core": "^2.0.0-rc.1",
|
|
56
52
|
"react": ">=18.0.0",
|
|
57
53
|
"react-router-dom": "^6.8.1"
|
|
58
54
|
},
|
|
@@ -61,7 +57,6 @@
|
|
|
61
57
|
},
|
|
62
58
|
"publishConfig": {
|
|
63
59
|
"access": "public",
|
|
64
|
-
"provenance": true,
|
|
65
60
|
"registry": "https://registry.npmjs.org/"
|
|
66
61
|
},
|
|
67
62
|
"scripts": {
|
|
@@ -43,9 +43,9 @@ const Container: React.FC<ContainerProps> = props => {
|
|
|
43
43
|
|
|
44
44
|
return (
|
|
45
45
|
<NoSSR>
|
|
46
|
-
<div className="rspress-preview">
|
|
46
|
+
<div className="rspress-preview rp-not-doc">
|
|
47
47
|
{isMobile === 'true' ? (
|
|
48
|
-
<div className="rspress-preview-wrapper
|
|
48
|
+
<div className="rspress-preview-wrapper" style={{ display: 'flex' }}>
|
|
49
49
|
<div className="rspress-preview-code">{children?.[0]}</div>
|
|
50
50
|
<div className="rspress-preview-device">
|
|
51
51
|
<iframe src={getPageUrl()} key={iframeKey}></iframe>
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
withBase,
|
|
6
6
|
} from '@rspress/core/runtime';
|
|
7
7
|
import { useCallback, useEffect, useState } from 'react';
|
|
8
|
-
// @ts-
|
|
8
|
+
// @ts-expect-error
|
|
9
9
|
import { normalizeId } from '../../dist/utils';
|
|
10
10
|
import MobileOperation from './common/mobile-operation';
|
|
11
11
|
import './Device.css';
|
|
@@ -27,27 +27,14 @@ export default () => {
|
|
|
27
27
|
// Do nothing in ssr
|
|
28
28
|
return '';
|
|
29
29
|
};
|
|
30
|
-
const [asideWidth, setAsideWidth] = useState('0px');
|
|
31
30
|
const { width: innerWidth } = useWindowSize();
|
|
32
31
|
const [iframeKey, setIframeKey] = useState(0);
|
|
33
32
|
const refresh = useCallback(() => {
|
|
34
33
|
setIframeKey(Math.random());
|
|
35
34
|
}, []);
|
|
36
35
|
|
|
37
|
-
// get default value from root
|
|
38
|
-
// listen resize and re-render
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
const root = document.querySelector(':root');
|
|
41
|
-
if (root) {
|
|
42
|
-
const defaultAsideWidth =
|
|
43
|
-
getComputedStyle(root).getPropertyValue('--rp-aside-width');
|
|
44
|
-
setAsideWidth(defaultAsideWidth);
|
|
45
|
-
}
|
|
46
|
-
}, []);
|
|
47
|
-
|
|
48
36
|
useEffect(() => {
|
|
49
37
|
const node = document.querySelector('.rspress-doc-container');
|
|
50
|
-
const { style } = document.documentElement;
|
|
51
38
|
if (haveDemos) {
|
|
52
39
|
if (innerWidth > 1280) {
|
|
53
40
|
node?.setAttribute(
|
|
@@ -64,12 +51,10 @@ export default () => {
|
|
|
64
51
|
} else {
|
|
65
52
|
node?.removeAttribute('style');
|
|
66
53
|
}
|
|
67
|
-
style.setProperty('--rp-aside-width', '0px');
|
|
68
54
|
} else {
|
|
69
55
|
node?.removeAttribute('style');
|
|
70
|
-
style.setProperty('--rp-aside-width', asideWidth);
|
|
71
56
|
}
|
|
72
|
-
}, [haveDemos,
|
|
57
|
+
}, [haveDemos, innerWidth]);
|
|
73
58
|
|
|
74
59
|
return haveDemos ? (
|
|
75
60
|
<div className="fixed-device">
|
|
@@ -15,13 +15,14 @@ body {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/* #region copied from preflight.css */
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
::
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
@layer rp-base {
|
|
19
|
+
*,
|
|
20
|
+
::before,
|
|
21
|
+
::after {
|
|
22
|
+
box-sizing: border-box; /* 1 */
|
|
23
|
+
border-width: 0; /* 2 */
|
|
24
|
+
border-style: solid; /* 2 */
|
|
25
|
+
}
|
|
25
26
|
}
|
|
26
27
|
/* #endregion copied from preflight.css */
|
|
27
28
|
|