@rspress/plugin-playground 0.0.0-next-20230925114748

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.
@@ -0,0 +1,321 @@
1
+ // src/web/index.ts
2
+ import { default as default2, loader as loader2, EditorProps } from "@monaco-editor/react";
3
+
4
+ // src/web/editor.tsx
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import MonacoEditor, { loader } from "@monaco-editor/react";
7
+
8
+ // src/web/constant.ts
9
+ var DEFAULT_BABEL_URL = "https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.20/babel.min.js";
10
+ var DEFAULT_MONACO_URL = "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.43.0/min/vs";
11
+
12
+ // src/web/editor.tsx
13
+ function initLoader() {
14
+ let loaderConfig = {
15
+ paths: {
16
+ vs: DEFAULT_MONACO_URL
17
+ }
18
+ };
19
+ try {
20
+ const keys = Object.keys(__PLAYGROUND_MONACO_LOADER__);
21
+ if (keys.length > 0) {
22
+ loaderConfig = __PLAYGROUND_MONACO_LOADER__;
23
+ }
24
+ } catch (e) {
25
+ }
26
+ loader.config(loaderConfig);
27
+ }
28
+ initLoader();
29
+ function getMonacoOptions() {
30
+ try {
31
+ return __PLAYGROUND_MONACO_OPTIONS__;
32
+ } catch (e) {
33
+ }
34
+ return {};
35
+ }
36
+ function Editor(props) {
37
+ const { options, className = "", ...rest } = props || {};
38
+ return /* @__PURE__ */ _jsx("div", {
39
+ className: `rspress-playground-editor ${className}`,
40
+ children: /* @__PURE__ */ _jsx(MonacoEditor, {
41
+ ...rest,
42
+ theme: "light",
43
+ options: {
44
+ minimap: {
45
+ enabled: true,
46
+ autohide: true
47
+ },
48
+ fontSize: 14,
49
+ lineNumbersMinChars: 7,
50
+ scrollBeyondLastLine: false,
51
+ automaticLayout: true,
52
+ wordBasedSuggestions: true,
53
+ quickSuggestions: true,
54
+ scrollbar: {
55
+ verticalScrollbarSize: 8,
56
+ horizontalScrollbarSize: 8
57
+ },
58
+ scrollPredominantAxis: false,
59
+ ...getMonacoOptions(),
60
+ ...options
61
+ }
62
+ })
63
+ });
64
+ }
65
+
66
+ // src/web/runner.tsx
67
+ import { jsx as _jsx2 } from "react/jsx-runtime";
68
+ import React, { Component } from "react";
69
+
70
+ // src/web/ast.ts
71
+ function createVariableDeclaration(id, init) {
72
+ return {
73
+ type: "VariableDeclaration",
74
+ declarations: [
75
+ {
76
+ type: "VariableDeclarator",
77
+ id: typeof id === "string" ? {
78
+ type: "Identifier",
79
+ name: id
80
+ } : id,
81
+ init
82
+ }
83
+ ],
84
+ kind: "const"
85
+ };
86
+ }
87
+ function createObjectPattern(names) {
88
+ return {
89
+ type: "ObjectPattern",
90
+ properties: names.map((name) => ({
91
+ type: "ObjectProperty",
92
+ key: {
93
+ type: "Identifier",
94
+ name
95
+ },
96
+ computed: false,
97
+ method: false,
98
+ shorthand: true,
99
+ value: {
100
+ type: "Identifier",
101
+ name
102
+ }
103
+ }))
104
+ };
105
+ }
106
+ function createGetImport(name, getDefault) {
107
+ return {
108
+ type: "CallExpression",
109
+ callee: {
110
+ type: "Identifier",
111
+ name: "__get_import"
112
+ },
113
+ arguments: [
114
+ {
115
+ type: "StringLiteral",
116
+ value: name
117
+ },
118
+ {
119
+ type: "BooleanLiteral",
120
+ value: Boolean(getDefault)
121
+ }
122
+ ]
123
+ };
124
+ }
125
+
126
+ // src/web/utils.ts
127
+ var loadingMap = /* @__PURE__ */ new Map();
128
+ function loadScript(url) {
129
+ const exists = loadingMap.get(url);
130
+ if (exists) {
131
+ return exists;
132
+ }
133
+ const n = new Promise((resolve) => {
134
+ const e = document.createElement("script");
135
+ e.src = url;
136
+ e.onload = () => resolve();
137
+ document.body.appendChild(e);
138
+ });
139
+ loadingMap.set(url, n);
140
+ return n;
141
+ }
142
+
143
+ // src/web/babel.ts
144
+ async function getBabel() {
145
+ if (!window.Babel) {
146
+ let babelUrl = DEFAULT_BABEL_URL;
147
+ try {
148
+ const u = __PLAYGROUND_BABEL_URL__;
149
+ if (u) {
150
+ babelUrl = u;
151
+ }
152
+ } catch (e) {
153
+ }
154
+ await loadScript(babelUrl);
155
+ }
156
+ return window.Babel;
157
+ }
158
+
159
+ // src/web/runner.tsx
160
+ function _define_property(obj, key, value) {
161
+ if (key in obj) {
162
+ Object.defineProperty(obj, key, {
163
+ value,
164
+ enumerable: true,
165
+ configurable: true,
166
+ writable: true
167
+ });
168
+ } else {
169
+ obj[key] = value;
170
+ }
171
+ return obj;
172
+ }
173
+ var Runner = class extends Component {
174
+ static getDerivedStateFromError(error) {
175
+ return {
176
+ error,
177
+ comp: null
178
+ };
179
+ }
180
+ waitCompile(targetCode) {
181
+ if (this.timer) {
182
+ clearTimeout(this.timer);
183
+ }
184
+ this.timer = setTimeout(() => {
185
+ this.timer = null;
186
+ this.doCompile(targetCode);
187
+ }, 600);
188
+ }
189
+ async doCompile(targetCode) {
190
+ const { language, getImport } = this.props;
191
+ const babel = await getBabel();
192
+ try {
193
+ const presets = [
194
+ [
195
+ babel.availablePresets.react
196
+ ],
197
+ [
198
+ babel.availablePresets.env,
199
+ {
200
+ modules: "commonjs"
201
+ }
202
+ ]
203
+ ];
204
+ if (language === "tsx" || language === "ts") {
205
+ presets.unshift([
206
+ babel.availablePresets.typescript,
207
+ {
208
+ allExtensions: true,
209
+ isTSX: language === "tsx"
210
+ }
211
+ ]);
212
+ }
213
+ const result = babel.transform(targetCode, {
214
+ sourceType: "module",
215
+ presets,
216
+ plugins: [
217
+ {
218
+ visitor: {
219
+ ImportDeclaration(path) {
220
+ const pkg = path.node.source.value;
221
+ const code = [];
222
+ for (const specifier of path.node.specifiers) {
223
+ if (specifier.type === "ImportDefaultSpecifier") {
224
+ code.push(createVariableDeclaration(specifier.local.name, createGetImport(pkg, true)));
225
+ }
226
+ if (specifier.type === "ImportNamespaceSpecifier") {
227
+ code.push(createVariableDeclaration(specifier.local.name, createGetImport(pkg)));
228
+ }
229
+ if (specifier.type === "ImportSpecifier") {
230
+ code.push(createVariableDeclaration(createObjectPattern([
231
+ specifier.local.name
232
+ ]), createGetImport(pkg)));
233
+ }
234
+ }
235
+ path.replaceWithMultiple(code);
236
+ }
237
+ }
238
+ }
239
+ ]
240
+ });
241
+ if (targetCode !== this.props.code || !result || !result.code) {
242
+ return;
243
+ }
244
+ const runExports = {};
245
+ const func = new Function("__get_import", "exports", result.code);
246
+ func(getImport, runExports);
247
+ if (runExports.default) {
248
+ this.setState({
249
+ error: void 0,
250
+ comp: /* @__PURE__ */ React.createElement(runExports.default)
251
+ });
252
+ return;
253
+ }
254
+ this.setState({
255
+ error: new Error("No default export"),
256
+ comp: null
257
+ });
258
+ } catch (e) {
259
+ if (targetCode !== this.props.code) {
260
+ return;
261
+ }
262
+ console.error(e);
263
+ this.setState({
264
+ error: e,
265
+ comp: null
266
+ });
267
+ }
268
+ }
269
+ componentDidCatch(error, errorInfo) {
270
+ console.error(error);
271
+ console.error(errorInfo);
272
+ }
273
+ componentDidMount() {
274
+ this.doCompile(this.props.code);
275
+ }
276
+ componentDidUpdate(prevProps) {
277
+ if (prevProps.code !== this.props.code) {
278
+ this.waitCompile(this.props.code);
279
+ }
280
+ }
281
+ render() {
282
+ const { className = "", code, language, getImport, ...rest } = this.props;
283
+ const { error, comp } = this.state;
284
+ if (error) {
285
+ return /* @__PURE__ */ _jsx2("div", {
286
+ className: `rspress-playground-runner ${className}`,
287
+ ...rest,
288
+ children: /* @__PURE__ */ _jsx2("span", {
289
+ style: {
290
+ color: "red"
291
+ },
292
+ children: error.message
293
+ })
294
+ });
295
+ }
296
+ return /* @__PURE__ */ _jsx2("div", {
297
+ className: `rspress-playground-runner ${className}`,
298
+ ...rest,
299
+ children: comp
300
+ });
301
+ }
302
+ constructor(props) {
303
+ super(props);
304
+ _define_property(this, "timer", void 0);
305
+ this.state = {
306
+ error: void 0,
307
+ comp: null
308
+ };
309
+ this.doCompile = this.doCompile.bind(this);
310
+ this.waitCompile = this.waitCompile.bind(this);
311
+ }
312
+ };
313
+ export {
314
+ Editor,
315
+ default2 as MonacoEditor,
316
+ loader2 as MonacoEditorLoader,
317
+ EditorProps as MonacoEditorProps,
318
+ Runner
319
+ };
320
+
321
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":"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","names":["MonacoEditor","default","MonacoEditorLoader","loader","MonacoEditorProps","DEFAULT_BABEL_URL","DEFAULT_MONACO_URL","initLoader","loaderConfig","paths","vs","keys","Object","__PLAYGROUND_MONACO_LOADER__","length","e","config","getMonacoOptions","__PLAYGROUND_MONACO_OPTIONS__","Editor","props","options","className","rest","div","theme","minimap","enabled","autohide","fontSize","lineNumbersMinChars","scrollBeyondLastLine","automaticLayout","wordBasedSuggestions","quickSuggestions","scrollbar","verticalScrollbarSize","horizontalScrollbarSize","scrollPredominantAxis","React","Component","createVariableDeclaration","id","init","type","declarations","name","kind","createObjectPattern","names","properties","map","key","computed","method","shorthand","value","createGetImport","getDefault","callee","arguments","Boolean","loadingMap","Map","loadScript","url","exists","get","n","Promise","resolve","document","createElement","src","onload","body","appendChild","set","getBabel","window","Babel","babelUrl","u","__PLAYGROUND_BABEL_URL__","Runner","getDerivedStateFromError","error","comp","waitCompile","targetCode","timer","clearTimeout","setTimeout","doCompile","language","getImport","babel","presets","availablePresets","react","env","modules","unshift","typescript","allExtensions","isTSX","result","transform","sourceType","plugins","visitor","ImportDeclaration","path","pkg","node","source","code","specifier","specifiers","push","local","replaceWithMultiple","runExports","func","Function","setState","undefined","Error","console","componentDidCatch","errorInfo","componentDidMount","componentDidUpdate","prevProps","render","state","span","style","color","message","constructor","bind"],"sources":["../../../src/web/home/runner/work/rspress/rspress/packages/plugin-playground/src/web/index.ts","../../../src/web/home/runner/work/rspress/rspress/packages/plugin-playground/src/web/editor.tsx","../../../src/web/home/runner/work/rspress/rspress/packages/plugin-playground/src/web/constant.ts","../../../src/web/home/runner/work/rspress/rspress/packages/plugin-playground/src/web/runner.tsx","../../../src/web/home/runner/work/rspress/rspress/packages/plugin-playground/src/web/ast.ts","../../../src/web/home/runner/work/rspress/rspress/packages/plugin-playground/src/web/utils.ts","../../../src/web/home/runner/work/rspress/rspress/packages/plugin-playground/src/web/babel.ts"],"sourcesContent":["export {\n default as MonacoEditor,\n loader as MonacoEditorLoader,\n EditorProps as MonacoEditorProps,\n} from '@monaco-editor/react';\nexport { Editor } from './editor';\nexport { Runner } from './runner';\n","import React from 'react';\nimport MonacoEditor, {\n loader,\n EditorProps as MonacoEditorProps,\n} from '@monaco-editor/react';\nimport { DEFAULT_MONACO_URL } from './constant';\n\n// inject by builder in cli/index.ts\n// see: https://modernjs.dev/builder/api/config-source.html#sourcedefine\ndeclare global {\n const __PLAYGROUND_MONACO_LOADER__: any;\n const __PLAYGROUND_MONACO_OPTIONS__: any;\n}\n\nfunction initLoader() {\n let loaderConfig = {\n paths: {\n vs: DEFAULT_MONACO_URL,\n },\n };\n\n try {\n const keys = Object.keys(__PLAYGROUND_MONACO_LOADER__);\n\n if (keys.length > 0) {\n loaderConfig = __PLAYGROUND_MONACO_LOADER__;\n }\n } catch (e) {\n // ignore\n }\n\n loader.config(loaderConfig);\n}\ninitLoader();\n\nfunction getMonacoOptions() {\n try {\n return __PLAYGROUND_MONACO_OPTIONS__;\n } catch (e) {\n // ignore\n }\n return {};\n}\n\nexport type EditorProps = Partial<MonacoEditorProps>;\n\nexport function Editor(props: EditorProps) {\n const { options, className = '', ...rest } = props || {};\n\n return (\n <div className={`rspress-playground-editor ${className}`}>\n <MonacoEditor\n {...rest}\n theme=\"light\"\n options={{\n minimap: {\n enabled: true,\n autohide: true,\n },\n fontSize: 14,\n lineNumbersMinChars: 7,\n scrollBeyondLastLine: false,\n automaticLayout: true,\n wordBasedSuggestions: true,\n quickSuggestions: true,\n scrollbar: {\n verticalScrollbarSize: 8,\n horizontalScrollbarSize: 8,\n },\n scrollPredominantAxis: false,\n ...getMonacoOptions(),\n ...options,\n }}\n />\n </div>\n );\n}\n","export const DEFAULT_BABEL_URL =\n 'https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.20/babel.min.js';\n\nexport const DEFAULT_MONACO_URL =\n 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.43.0/min/vs';\n","import type { Node } from '@babel/types';\nimport React, { Component, HTMLAttributes } from 'react';\nimport {\n createGetImport,\n createObjectPattern,\n createVariableDeclaration,\n} from './ast';\nimport { getBabel } from './babel';\n\ninterface RunnerProps extends HTMLAttributes<HTMLDivElement> {\n code: string;\n language: string;\n getImport: (name: string, getDefault?: boolean) => void;\n}\n\ninterface RunnerState {\n error?: Error;\n comp: any;\n}\n\nclass Runner extends Component<RunnerProps, RunnerState> {\n static getDerivedStateFromError(error: Error) {\n return {\n error,\n comp: null,\n };\n }\n\n timer: any;\n\n constructor(props: RunnerProps) {\n super(props);\n\n this.state = {\n error: undefined,\n comp: null,\n };\n\n this.doCompile = this.doCompile.bind(this);\n this.waitCompile = this.waitCompile.bind(this);\n }\n\n waitCompile(targetCode: string) {\n if (this.timer) {\n clearTimeout(this.timer);\n }\n this.timer = setTimeout(() => {\n this.timer = null;\n this.doCompile(targetCode);\n }, 600);\n }\n\n async doCompile(targetCode: string) {\n const { language, getImport } = this.props;\n const babel = await getBabel();\n try {\n const presets = [\n [babel.availablePresets.react],\n [babel.availablePresets.env, { modules: 'commonjs' }],\n ];\n if (language === 'tsx' || language === 'ts') {\n presets.unshift([\n babel.availablePresets.typescript,\n {\n allExtensions: true,\n isTSX: language === 'tsx',\n },\n ]);\n }\n const result = babel.transform(targetCode, {\n sourceType: 'module',\n presets,\n plugins: [\n {\n visitor: {\n ImportDeclaration(path) {\n const pkg = path.node.source.value;\n const code: Node[] = [];\n for (const specifier of path.node.specifiers) {\n // import X from 'xxx'\n if (specifier.type === 'ImportDefaultSpecifier') {\n // const ${specifier.local.name} = __get_import()\n code.push(\n createVariableDeclaration(\n specifier.local.name,\n createGetImport(pkg, true),\n ),\n );\n }\n // import * as X from 'xxx'\n if (specifier.type === 'ImportNamespaceSpecifier') {\n // const ${specifier.local.name} = __get_import()\n code.push(\n createVariableDeclaration(\n specifier.local.name,\n createGetImport(pkg),\n ),\n );\n }\n // import { a, b, c } from 'xxx'\n if (specifier.type === 'ImportSpecifier') {\n // const {${specifier.local.name}} = __get_import()\n code.push(\n createVariableDeclaration(\n createObjectPattern([specifier.local.name]),\n createGetImport(pkg),\n ),\n );\n }\n }\n path.replaceWithMultiple(code);\n },\n },\n },\n ],\n });\n\n // Code has been updated\n if (targetCode !== this.props.code || !result || !result.code) {\n return;\n }\n\n const runExports: any = {};\n // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func\n const func = new Function('__get_import', 'exports', result.code);\n func(getImport, runExports);\n\n if (runExports.default) {\n this.setState({\n error: undefined,\n comp: React.createElement(runExports.default),\n });\n return;\n }\n\n this.setState({\n error: new Error('No default export'),\n comp: null,\n });\n } catch (e) {\n // Code has been updated\n if (targetCode !== this.props.code) {\n return;\n }\n console.error(e);\n this.setState({\n error: e as Error,\n comp: null,\n });\n }\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error(error);\n console.error(errorInfo);\n }\n\n componentDidMount() {\n this.doCompile(this.props.code);\n }\n\n componentDidUpdate(prevProps: RunnerProps) {\n if (prevProps.code !== this.props.code) {\n this.waitCompile(this.props.code);\n }\n }\n\n render() {\n const { className = '', code, language, getImport, ...rest } = this.props;\n const { error, comp } = this.state;\n\n if (error) {\n return (\n <div className={`rspress-playground-runner ${className}`} {...rest}>\n <span style={{ color: 'red' }}>{error.message}</span>\n </div>\n );\n }\n\n return (\n <div className={`rspress-playground-runner ${className}`} {...rest}>\n {comp}\n </div>\n );\n }\n}\n\nexport { Runner };\n","import type {\n CallExpression,\n Expression,\n ObjectPattern,\n VariableDeclaration,\n} from '@babel/types';\n\nexport function createVariableDeclaration(\n id: string | ObjectPattern,\n init: Expression,\n): VariableDeclaration {\n return {\n type: 'VariableDeclaration',\n declarations: [\n {\n type: 'VariableDeclarator',\n id:\n typeof id === 'string'\n ? {\n type: 'Identifier',\n name: id,\n }\n : id,\n init,\n },\n ],\n kind: 'const',\n };\n}\n\nexport function createObjectPattern(names: string[]): ObjectPattern {\n return {\n type: 'ObjectPattern',\n properties: names.map(name => ({\n type: 'ObjectProperty',\n key: {\n type: 'Identifier',\n name,\n },\n computed: false,\n method: false,\n shorthand: true,\n value: {\n type: 'Identifier',\n name,\n },\n })),\n };\n}\n\nexport function createGetImport(\n name: string,\n getDefault?: boolean,\n): CallExpression {\n return {\n type: 'CallExpression',\n callee: {\n type: 'Identifier',\n name: '__get_import',\n },\n arguments: [\n {\n type: 'StringLiteral',\n value: name,\n },\n {\n type: 'BooleanLiteral',\n value: Boolean(getDefault),\n },\n ],\n };\n}\n","const loadingMap = new Map<string, Promise<void>>();\n\nexport function loadScript(url: string): Promise<void> {\n const exists = loadingMap.get(url);\n if (exists) {\n return exists;\n }\n const n: Promise<void> = new Promise(resolve => {\n const e = document.createElement('script');\n e.src = url;\n e.onload = () => resolve();\n document.body.appendChild(e);\n });\n loadingMap.set(url, n);\n return n;\n}\n\nexport function normalizeUrl(u: string) {\n return u.replace(/\\/\\//g, '/');\n}\n","import type babel from '@babel/standalone';\nimport { DEFAULT_BABEL_URL } from './constant';\nimport { loadScript } from './utils';\n\ndeclare global {\n // inject by builder in cli/index.ts\n // see: https://modernjs.dev/builder/api/config-source.html#sourcedefine\n const __PLAYGROUND_BABEL_URL__: any;\n interface Window {\n Babel: typeof babel;\n }\n}\n\nasync function getBabel() {\n if (!window.Babel) {\n let babelUrl = DEFAULT_BABEL_URL;\n try {\n const u = __PLAYGROUND_BABEL_URL__;\n if (u) {\n babelUrl = u;\n }\n } catch (e) {\n // ignore\n }\n await loadScript(babelUrl);\n }\n return window.Babel;\n}\n\nexport { getBabel };\n"]}
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "@rspress/plugin-playground",
3
+ "version": "0.0.0-next-20230925114748",
4
+ "description": "A plugin for rspress to preview the code block in markdown/mdx file.",
5
+ "bugs": "https://github.com/web-infra-dev/rspress/issues",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/web-infra-dev/rspress",
9
+ "directory": "packages/plugin-preview"
10
+ },
11
+ "license": "MIT",
12
+ "types": "./dist/cli/esm/index.d.ts",
13
+ "main": "./dist/cli/cjs/index.js",
14
+ "module": "./dist/cli/esm/index.js",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/cli/esm/index.d.ts",
18
+ "import": "./dist/cli/esm/index.js",
19
+ "default": "./dist/cli/cjs/index.js"
20
+ },
21
+ "./web": {
22
+ "types": "./dist/web/esm/index.d.ts",
23
+ "import": "./dist/web/esm/index.js",
24
+ "default": "./dist/web/cjs/index.js"
25
+ }
26
+ },
27
+ "engines": {
28
+ "node": ">=14.17.6"
29
+ },
30
+ "eslintIgnore": [
31
+ "node_modules/",
32
+ "dist/"
33
+ ],
34
+ "dependencies": {
35
+ "@mdx-js/mdx": "2.2.1",
36
+ "@modern-js/utils": "2.35.1",
37
+ "@monaco-editor/react": "~4.4.6",
38
+ "@oxidation-compiler/napi": "^0.1.0",
39
+ "remark-gfm": "3.0.1",
40
+ "@rspress/shared": "0.0.0-next-20230925114748"
41
+ },
42
+ "devDependencies": {
43
+ "@babel/types": "^7.22.17",
44
+ "@types/babel__core": "^7.20.1",
45
+ "@types/babel__standalone": "^7.1.4",
46
+ "@types/babel__traverse": "^7.20.1",
47
+ "@types/mdast": "^3.0.10",
48
+ "@types/node": "^18.11.17",
49
+ "@types/react": "^18",
50
+ "@types/react-dom": "^18",
51
+ "mdast-util-mdxjs-esm": "^1.3.0",
52
+ "prettier": "^2.6.2",
53
+ "react": "^18",
54
+ "react-dom": "^18",
55
+ "react-router-dom": "^6.8.1",
56
+ "rspack-plugin-virtual-module": "0.1.11",
57
+ "typescript": "^5",
58
+ "unified": "^10.1.2",
59
+ "unist-util-visit": "^4.1.1"
60
+ },
61
+ "peerDependencies": {
62
+ "@rspress/core": "0.0.0-next-20230925114748",
63
+ "react": ">=17",
64
+ "react-router-dom": "^6.8.1"
65
+ },
66
+ "files": [
67
+ "dist",
68
+ "static"
69
+ ],
70
+ "publishConfig": {
71
+ "access": "public",
72
+ "provenance": true,
73
+ "registry": "https://registry.npmjs.org/"
74
+ },
75
+ "scripts": {
76
+ "dev": "modern build -w",
77
+ "build": "modern build",
78
+ "reset": "rimraf ./**/node_modules",
79
+ "lint": "modern lint",
80
+ "change": "modern change",
81
+ "bump": "modern bump",
82
+ "pre": "modern pre",
83
+ "change-status": "modern change-status",
84
+ "gen-release-note": "modern gen-release-note",
85
+ "release": "modern release",
86
+ "new": "modern new",
87
+ "test": "vitest run --passWithNoTests",
88
+ "upgrade": "modern upgrade"
89
+ }
90
+ }
@@ -0,0 +1,51 @@
1
+ import React, { HTMLAttributes, useCallback, useState } from 'react';
2
+ import getImport from '_rspress_playground_imports';
3
+ import { Editor, Runner } from '../../dist/web/esm';
4
+
5
+ interface PlaygroundProps extends HTMLAttributes<HTMLDivElement> {
6
+ code: string;
7
+ language: string;
8
+ direction?: 'horizontal' | 'vertical';
9
+ editorPosition?: 'left' | 'right';
10
+ }
11
+
12
+ export default function Playground(props: PlaygroundProps) {
13
+ const {
14
+ code: codeProp,
15
+ language,
16
+ className = '',
17
+ direction = 'horizontal',
18
+ editorPosition,
19
+ ...rest
20
+ } = props;
21
+
22
+ const [code, setCode] = useState(codeProp);
23
+
24
+ const handleCodeChange = useCallback((e?: string) => {
25
+ setCode(e || '');
26
+ }, []);
27
+
28
+ const useReverseLayout =
29
+ direction === 'horizontal' && editorPosition === 'left';
30
+
31
+ const monacoLanguage =
32
+ language === 'tsx' || language === 'ts' ? 'typescript' : 'javascript';
33
+
34
+ const classNames = [
35
+ 'rspress-playground',
36
+ `rspress-playground-${direction}`,
37
+ `rspress-playground-reverse-${useReverseLayout ? 'y' : 'n'}`,
38
+ className,
39
+ ].join(' ');
40
+
41
+ return (
42
+ <div className={classNames} {...rest}>
43
+ <Runner language={language} code={code} getImport={getImport} />
44
+ <Editor
45
+ value={code}
46
+ onChange={handleCodeChange}
47
+ language={monacoLanguage}
48
+ />
49
+ </div>
50
+ );
51
+ }
@@ -0,0 +1,51 @@
1
+ .rspress-playground {
2
+ display: flex;
3
+ border: 1px solid rgba(28, 31, 35, 0.08);
4
+ border-radius: 3px;
5
+ margin-top: 20px;
6
+ margin-bottom: 20px;
7
+ }
8
+
9
+ .rspress-playground-horizontal {
10
+ flex-direction: row;
11
+ height: 400px;
12
+ }
13
+
14
+ .rspress-playground-horizontal.rspress-playground-reverse-y {
15
+ flex-direction: row-reverse;
16
+ }
17
+
18
+ .rspress-playground-vertical {
19
+ flex-direction: column;
20
+ }
21
+
22
+ .rspress-playground > .rspress-playground-runner {
23
+ padding: 20px;
24
+ overflow: auto;
25
+ }
26
+
27
+ .rspress-playground-horizontal > .rspress-playground-runner {
28
+ width: 40%;
29
+ }
30
+
31
+ .rspress-playground-horizontal > .rspress-playground-editor {
32
+ width: 60%;
33
+ }
34
+
35
+ .rspress-playground-horizontal.rspress-playground-reverse-y
36
+ > .rspress-playground-editor {
37
+ border-right: 1px solid rgba(28, 31, 35, 0.08);
38
+ }
39
+
40
+ .rspress-playground-horizontal.rspress-playground-reverse-n
41
+ > .rspress-playground-editor {
42
+ border-left: 1px solid rgba(28, 31, 35, 0.08);
43
+ }
44
+
45
+ .rspress-playground-vertical > .rspress-playground-editor {
46
+ height: 300px;
47
+ }
48
+
49
+ .rspress-playground-vertical > .rspress-playground-editor {
50
+ border-top: 1px solid rgba(28, 31, 35, 0.08);
51
+ }
@@ -0,0 +1,6 @@
1
+ /// <reference types='@modern-js/module-tools/types' />
2
+
3
+ declare module '_rspress_playground_imports' {
4
+ const getImport: (name: string, getDefault?: boolean) => void;
5
+ export default getImport;
6
+ }