@deot/docs-playground 1.1.3 → 1.1.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.
Files changed (27) hide show
  1. package/README.md +1 -0
  2. package/dist/{cdn-Czve5_9b.cjs → cdn-BoYKnGD3.cjs} +7 -0
  3. package/dist/{cdn-DEvdGJu2.js → cdn-DQoETju_.js} +2 -1
  4. package/dist/{compile-Bw7v7QE-.js → compile-BHD98Ttf.js} +24 -32
  5. package/dist/{compile-DSMuM8zl.cjs → compile-Da095AyM.cjs} +24 -32
  6. package/dist/{files-C5UMzYxA.js → files-BqucFldk.js} +33 -4
  7. package/dist/{files-D5LNOtjp.cjs → files-BsAOZiPN.cjs} +93 -18
  8. package/dist/index.cjs +35 -30
  9. package/dist/index.js +35 -30
  10. package/dist/index.style.css +1 -1
  11. package/dist/{linker-B--sjERT.cjs → linker-DIpEiean.cjs} +2 -2
  12. package/dist/{linker-JHdz37DK.js → linker-xqjVl0X0.js} +2 -2
  13. package/dist/{local-sandbox-DnkKrBhf.cjs → local-sandbox-0ojvBQPO.cjs} +12 -8
  14. package/dist/{local-sandbox-B8IJ5jWb.js → local-sandbox-DvcgaBOa.js} +14 -21
  15. package/dist/{modules-DlLJF_vd.js → modules-BGzPcoRR.js} +7 -1
  16. package/dist/{modules-CInmL-8h.cjs → modules-E6kK6ZJH.cjs} +7 -1
  17. package/dist/{remote-CKMzn1J3.cjs → remote-BG0E1Ugo.cjs} +67 -21
  18. package/dist/{remote-DfXAsO9n.js → remote-mq4zvrI1.js} +67 -21
  19. package/dist/script-BiCcpu3G.cjs +111 -0
  20. package/dist/script-DjUf9uWK.js +98 -0
  21. package/dist/{scss-DaIqB_qT.cjs → scss-B8OFbz1k.cjs} +23 -5
  22. package/dist/{scss-Co2it4vB.js → scss-DIh6971q.js} +18 -6
  23. package/dist/{store-D8vwi-HV.js → store-BOyC8F2y.js} +149 -6
  24. package/dist/{store-BF7z-oaO.cjs → store-DKawhFZu.cjs} +151 -6
  25. package/package.json +8 -7
  26. package/dist/script-5Xzzx7u5.cjs +0 -57
  27. package/dist/script-xKUjE8pf.js +0 -46
@@ -1,18 +1,24 @@
1
- const require_files = require("./files-D5LNOtjp.cjs");
2
- const require_script = require("./script-5Xzzx7u5.cjs");
3
- const require_modules = require("./modules-CInmL-8h.cjs");
1
+ const require_cdn = require("./cdn-BoYKnGD3.cjs");
2
+ const require_files = require("./files-BsAOZiPN.cjs");
3
+ const require_script = require("./script-BiCcpu3G.cjs");
4
+ const require_modules = require("./modules-E6kK6ZJH.cjs");
5
+ let es_module_lexer = require("es-module-lexer");
4
6
  let sucrase = require("sucrase");
5
7
  //#region packages/playground/src/core/runtime/local/remote.ts
6
8
  var HOST_VUE = /* @__PURE__ */ new Set(["vue", "vue/server-renderer"]);
7
9
  /**
8
10
  * 把 CDN 上的 ESM 先拉完整张依赖图,再在当前页面里执行。
9
- * 裸导入走同一份 import map。与默认 CDN 不同的 `vue` 地址会远程加载。
11
+ * 裸导入优先走 import map,缺失的 npm 依赖回退到 CDN ESM;import() 按需加载。
10
12
  * @param imports 合并后的 import map。
11
13
  * @param builtins 宿主 Vue 与 vue-router。
12
14
  * @param cdnURL 当前 CDN 根,用来识别默认地址。
15
+ * @param importModule 浏览器原生 ESM 加载器。
13
16
  * @returns 按 URL 加载并执行远程模块的加载器。
14
17
  */
15
- var createRemoteLoader = (imports, builtins, cdnURL) => {
18
+ var createRemoteLoader = (imports, builtins, cdnURL, importModule = (url) => import(
19
+ /* @vite-ignore */
20
+ url
21
+ )) => {
16
22
  const hostModules = {
17
23
  "vue": builtins.vue,
18
24
  "vue-router": builtins.vueRouter
@@ -21,6 +27,19 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
21
27
  const texts = /* @__PURE__ */ new Map();
22
28
  const evaluated = /* @__PURE__ */ new Map();
23
29
  const crawled = /* @__PURE__ */ new Set();
30
+ const nativeModules = /* @__PURE__ */ new Map();
31
+ const loadNative = (url) => {
32
+ let pending = nativeModules.get(url);
33
+ if (!pending) {
34
+ pending = importModule(url).then((module) => {
35
+ const exports = require_modules.toHostModule(module);
36
+ evaluated.set(url, exports);
37
+ return exports;
38
+ });
39
+ nativeModules.set(url, pending);
40
+ }
41
+ return pending;
42
+ };
24
43
  const localBuiltinId = (id) => {
25
44
  if (imports[id] && !require_modules.prefersLocalBuiltin(id, imports, cdnURL)) return null;
26
45
  if (require_modules.prefersLocalBuiltin(id, imports, cdnURL)) return id;
@@ -34,7 +53,7 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
34
53
  }
35
54
  };
36
55
  const dependencyUrl = (from, specifier) => {
37
- if (require_files.isRelativeSpecifier(specifier)) return new URL(specifier, from).href;
56
+ if (require_files.isRelativeSpecifier(specifier) || /^https?:\/\//.test(specifier)) return new URL(specifier, from).href;
38
57
  if (imports[specifier] && !require_modules.prefersLocalBuiltin(specifier, imports, cdnURL)) return imports[specifier];
39
58
  if (HOST_VUE.has(specifier) && require_modules.prefersLocalBuiltin(specifier, imports, cdnURL)) return null;
40
59
  let cursor = specifier;
@@ -48,19 +67,29 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
48
67
  cursor = cursor.slice(0, slash);
49
68
  }
50
69
  const target = imports[specifier] ? specifier : require_modules.resolveImportTarget(specifier, imports);
51
- if (!target || !imports[target]) return null;
70
+ if (!target) {
71
+ imports[specifier] = require_cdn.resolveNpmImport(specifier);
72
+ return imports[specifier];
73
+ }
52
74
  return imports[target];
53
75
  };
54
76
  const crawl = async (url) => {
77
+ if (/\/\+esm(?:[?#]|$)/.test(url)) {
78
+ await loadNative(url);
79
+ return;
80
+ }
55
81
  if (crawled.has(url)) return;
56
82
  crawled.add(url);
57
83
  const response = await fetch(url);
58
84
  if (!response.ok) throw new Error(`${response.status} ${url}`);
59
85
  const text = await response.text();
60
- texts.set(url, text);
61
- const source = text.replace(/\/\*[\s\S]*?\*\//g, "");
62
- await Promise.all(require_files.listImportSpecifiers(source).map(async (specifier) => {
63
- const next = dependencyUrl(url, specifier);
86
+ await es_module_lexer.init;
87
+ const [specifiers] = (0, es_module_lexer.parse)(text);
88
+ let source = text;
89
+ for (const item of [...specifiers].reverse()) if (item.d >= 0) source = source.slice(0, item.ss) + "__import" + source.slice(item.ss + 6);
90
+ texts.set(url, source);
91
+ await Promise.all(specifiers.filter((item) => item.d === -1).map(async (item) => {
92
+ const next = dependencyUrl(url, item.n);
64
93
  if (next) await crawl(next);
65
94
  }));
66
95
  };
@@ -68,7 +97,7 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
68
97
  if (HOST_VUE.has(id) && require_modules.prefersLocalBuiltin(id, imports, cdnURL)) return require_modules.toHostModule(builtins.vue);
69
98
  const builtinId = localBuiltinId(id);
70
99
  if (builtinId) return require_modules.toHostModule(hostModules[builtinId]);
71
- if (require_files.isRelativeSpecifier(id)) return evaluate(new URL(id, from).href);
100
+ if (require_files.isRelativeSpecifier(id) || /^https?:\/\//.test(id)) return evaluate(new URL(id, from).href);
72
101
  const target = imports[id] ? id : require_modules.resolveImportTarget(id, imports);
73
102
  if (!target || !imports[target]) throw new Error(`[Playground] 未注册的模块 "${id}"`);
74
103
  const loaded = evaluate(imports[target]);
@@ -84,23 +113,40 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
84
113
  if (text == null) throw new Error(`[Playground] 远程模块尚未下载: ${url}`);
85
114
  const cjs = (0, sucrase.transform)(require_script.rewriteImportMeta(text, url), {
86
115
  transforms: ["imports"],
116
+ disableESTransforms: true,
87
117
  production: true,
88
118
  filePath: url
89
119
  }).code;
90
120
  const module = { exports: {} };
91
121
  evaluated.set(url, module.exports);
92
- new Function("require", "module", "exports", cjs)(requireFrom(url), module, module.exports);
122
+ new Function("require", "module", "exports", "__import", cjs)(requireFrom(url), module, module.exports, async (id) => {
123
+ const next = dependencyUrl(url, id);
124
+ if (next) await load(next);
125
+ else {
126
+ const builtinId = localBuiltinId(id);
127
+ if (builtinId && !(builtinId in hostModules)) hostModules[builtinId] = await require_modules.ensureLocalBuiltin(builtinId);
128
+ }
129
+ return requireFrom(url)(id);
130
+ });
93
131
  evaluated.set(url, module.exports);
94
132
  return module.exports;
95
133
  };
96
- return { load: async (url) => {
97
- await crawl(url);
98
- await Promise.all([...pendingBuiltins].map(async (id) => {
99
- if (id === "vue" || id === "vue-router") return;
100
- hostModules[id] = await require_modules.ensureLocalBuiltin(id);
101
- }));
102
- return evaluate(url);
103
- } };
134
+ const loading = /* @__PURE__ */ new Map();
135
+ const load = (url) => {
136
+ const pending = loading.get(url);
137
+ if (pending) return pending;
138
+ const task = (async () => {
139
+ await crawl(url);
140
+ await Promise.all([...pendingBuiltins].map(async (id) => {
141
+ if (id === "vue" || id === "vue-router") return;
142
+ hostModules[id] = await require_modules.ensureLocalBuiltin(id);
143
+ }));
144
+ return evaluate(url);
145
+ })();
146
+ loading.set(url, task);
147
+ return task;
148
+ };
149
+ return { load };
104
150
  };
105
151
  //#endregion
106
152
  exports.createRemoteLoader = createRemoteLoader;
@@ -1,18 +1,24 @@
1
- import { isRelativeSpecifier, listImportSpecifiers } from "./files-C5UMzYxA.js";
2
- import { t as rewriteImportMeta } from "./script-xKUjE8pf.js";
3
- import { n as localBuiltinIds, prefersLocalBuiltin, resolveHostModule, resolveImportTarget, t as ensureLocalBuiltin, toHostModule } from "./modules-DlLJF_vd.js";
1
+ import { l as isRelativeSpecifier } from "./files-BqucFldk.js";
2
+ import { a as resolveNpmImport } from "./cdn-DQoETju_.js";
3
+ import { t as rewriteImportMeta } from "./script-DjUf9uWK.js";
4
+ import { n as localBuiltinIds, prefersLocalBuiltin, resolveHostModule, resolveImportTarget, t as ensureLocalBuiltin, toHostModule } from "./modules-BGzPcoRR.js";
5
+ import { init, parse } from "es-module-lexer";
4
6
  import { transform } from "sucrase";
5
7
  //#region packages/playground/src/core/runtime/local/remote.ts
6
8
  var HOST_VUE = /* @__PURE__ */ new Set(["vue", "vue/server-renderer"]);
7
9
  /**
8
10
  * 把 CDN 上的 ESM 先拉完整张依赖图,再在当前页面里执行。
9
- * 裸导入走同一份 import map。与默认 CDN 不同的 `vue` 地址会远程加载。
11
+ * 裸导入优先走 import map,缺失的 npm 依赖回退到 CDN ESM;import() 按需加载。
10
12
  * @param imports 合并后的 import map。
11
13
  * @param builtins 宿主 Vue 与 vue-router。
12
14
  * @param cdnURL 当前 CDN 根,用来识别默认地址。
15
+ * @param importModule 浏览器原生 ESM 加载器。
13
16
  * @returns 按 URL 加载并执行远程模块的加载器。
14
17
  */
15
- var createRemoteLoader = (imports, builtins, cdnURL) => {
18
+ var createRemoteLoader = (imports, builtins, cdnURL, importModule = (url) => import(
19
+ /* @vite-ignore */
20
+ url
21
+ )) => {
16
22
  const hostModules = {
17
23
  "vue": builtins.vue,
18
24
  "vue-router": builtins.vueRouter
@@ -21,6 +27,19 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
21
27
  const texts = /* @__PURE__ */ new Map();
22
28
  const evaluated = /* @__PURE__ */ new Map();
23
29
  const crawled = /* @__PURE__ */ new Set();
30
+ const nativeModules = /* @__PURE__ */ new Map();
31
+ const loadNative = (url) => {
32
+ let pending = nativeModules.get(url);
33
+ if (!pending) {
34
+ pending = importModule(url).then((module) => {
35
+ const exports = toHostModule(module);
36
+ evaluated.set(url, exports);
37
+ return exports;
38
+ });
39
+ nativeModules.set(url, pending);
40
+ }
41
+ return pending;
42
+ };
24
43
  const localBuiltinId = (id) => {
25
44
  if (imports[id] && !prefersLocalBuiltin(id, imports, cdnURL)) return null;
26
45
  if (prefersLocalBuiltin(id, imports, cdnURL)) return id;
@@ -34,7 +53,7 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
34
53
  }
35
54
  };
36
55
  const dependencyUrl = (from, specifier) => {
37
- if (isRelativeSpecifier(specifier)) return new URL(specifier, from).href;
56
+ if (isRelativeSpecifier(specifier) || /^https?:\/\//.test(specifier)) return new URL(specifier, from).href;
38
57
  if (imports[specifier] && !prefersLocalBuiltin(specifier, imports, cdnURL)) return imports[specifier];
39
58
  if (HOST_VUE.has(specifier) && prefersLocalBuiltin(specifier, imports, cdnURL)) return null;
40
59
  let cursor = specifier;
@@ -48,19 +67,29 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
48
67
  cursor = cursor.slice(0, slash);
49
68
  }
50
69
  const target = imports[specifier] ? specifier : resolveImportTarget(specifier, imports);
51
- if (!target || !imports[target]) return null;
70
+ if (!target) {
71
+ imports[specifier] = resolveNpmImport(specifier);
72
+ return imports[specifier];
73
+ }
52
74
  return imports[target];
53
75
  };
54
76
  const crawl = async (url) => {
77
+ if (/\/\+esm(?:[?#]|$)/.test(url)) {
78
+ await loadNative(url);
79
+ return;
80
+ }
55
81
  if (crawled.has(url)) return;
56
82
  crawled.add(url);
57
83
  const response = await fetch(url);
58
84
  if (!response.ok) throw new Error(`${response.status} ${url}`);
59
85
  const text = await response.text();
60
- texts.set(url, text);
61
- const source = text.replace(/\/\*[\s\S]*?\*\//g, "");
62
- await Promise.all(listImportSpecifiers(source).map(async (specifier) => {
63
- const next = dependencyUrl(url, specifier);
86
+ await init;
87
+ const [specifiers] = parse(text);
88
+ let source = text;
89
+ for (const item of [...specifiers].reverse()) if (item.d >= 0) source = source.slice(0, item.ss) + "__import" + source.slice(item.ss + 6);
90
+ texts.set(url, source);
91
+ await Promise.all(specifiers.filter((item) => item.d === -1).map(async (item) => {
92
+ const next = dependencyUrl(url, item.n);
64
93
  if (next) await crawl(next);
65
94
  }));
66
95
  };
@@ -68,7 +97,7 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
68
97
  if (HOST_VUE.has(id) && prefersLocalBuiltin(id, imports, cdnURL)) return toHostModule(builtins.vue);
69
98
  const builtinId = localBuiltinId(id);
70
99
  if (builtinId) return toHostModule(hostModules[builtinId]);
71
- if (isRelativeSpecifier(id)) return evaluate(new URL(id, from).href);
100
+ if (isRelativeSpecifier(id) || /^https?:\/\//.test(id)) return evaluate(new URL(id, from).href);
72
101
  const target = imports[id] ? id : resolveImportTarget(id, imports);
73
102
  if (!target || !imports[target]) throw new Error(`[Playground] 未注册的模块 "${id}"`);
74
103
  const loaded = evaluate(imports[target]);
@@ -84,23 +113,40 @@ var createRemoteLoader = (imports, builtins, cdnURL) => {
84
113
  if (text == null) throw new Error(`[Playground] 远程模块尚未下载: ${url}`);
85
114
  const cjs = transform(rewriteImportMeta(text, url), {
86
115
  transforms: ["imports"],
116
+ disableESTransforms: true,
87
117
  production: true,
88
118
  filePath: url
89
119
  }).code;
90
120
  const module = { exports: {} };
91
121
  evaluated.set(url, module.exports);
92
- new Function("require", "module", "exports", cjs)(requireFrom(url), module, module.exports);
122
+ new Function("require", "module", "exports", "__import", cjs)(requireFrom(url), module, module.exports, async (id) => {
123
+ const next = dependencyUrl(url, id);
124
+ if (next) await load(next);
125
+ else {
126
+ const builtinId = localBuiltinId(id);
127
+ if (builtinId && !(builtinId in hostModules)) hostModules[builtinId] = await ensureLocalBuiltin(builtinId);
128
+ }
129
+ return requireFrom(url)(id);
130
+ });
93
131
  evaluated.set(url, module.exports);
94
132
  return module.exports;
95
133
  };
96
- return { load: async (url) => {
97
- await crawl(url);
98
- await Promise.all([...pendingBuiltins].map(async (id) => {
99
- if (id === "vue" || id === "vue-router") return;
100
- hostModules[id] = await ensureLocalBuiltin(id);
101
- }));
102
- return evaluate(url);
103
- } };
134
+ const loading = /* @__PURE__ */ new Map();
135
+ const load = (url) => {
136
+ const pending = loading.get(url);
137
+ if (pending) return pending;
138
+ const task = (async () => {
139
+ await crawl(url);
140
+ await Promise.all([...pendingBuiltins].map(async (id) => {
141
+ if (id === "vue" || id === "vue-router") return;
142
+ hostModules[id] = await ensureLocalBuiltin(id);
143
+ }));
144
+ return evaluate(url);
145
+ })();
146
+ loading.set(url, task);
147
+ return task;
148
+ };
149
+ return { load };
104
150
  };
105
151
  //#endregion
106
152
  export { createRemoteLoader };
@@ -0,0 +1,111 @@
1
+ const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
+ let sucrase = require("sucrase");
3
+ let _vue_compiler_sfc_dist_compiler_sfc_esm_browser_js = require("@vue/compiler-sfc/dist/compiler-sfc.esm-browser.js");
4
+ _vue_compiler_sfc_dist_compiler_sfc_esm_browser_js = require_rolldown_runtime.__toESM(_vue_compiler_sfc_dist_compiler_sfc_esm_browser_js);
5
+ //#region packages/playground/src/core/runtime/local/compile/script.ts
6
+ var { babelParse, walkIdentifiers, MagicString } = _vue_compiler_sfc_dist_compiler_sfc_esm_browser_js;
7
+ var rewriteJsxAttributes = (code) => {
8
+ const replacements = [];
9
+ for (const match of code.matchAll(/\b([\w-]+:[\w-]+)\s*=\s*\{/g)) {
10
+ let depth = 1;
11
+ let quote = "";
12
+ const start = match.index + match[0].length;
13
+ let end = start;
14
+ for (; end < code.length; end += 1) {
15
+ const character = code[end];
16
+ if (quote) {
17
+ if (character === "\\") end += 1;
18
+ else if (character === quote) quote = "";
19
+ } else if ("\"'`".includes(character)) quote = character;
20
+ else if (character === "{") depth += 1;
21
+ else if (character === "}" && --depth === 0) break;
22
+ }
23
+ replacements.push({
24
+ start: match.index,
25
+ end: end + 1,
26
+ text: `{...{${JSON.stringify(match[1])}: ${code.slice(start, end)}}}`
27
+ });
28
+ }
29
+ for (const item of replacements.reverse()) code = code.slice(0, item.start) + item.text + code.slice(item.end);
30
+ return code;
31
+ };
32
+ var removeImportedTypeExports = (code) => {
33
+ const types = /* @__PURE__ */ new Set();
34
+ for (const match of code.matchAll(/\bimport\s+type\s*\{([^}]+)\}\s*from\s*['"][^'"]+['"]/g)) for (const item of match[1].split(",")) types.add(item.trim().split(/\s+as\s+/).pop());
35
+ return code.replace(/\bexport\s*\{([^}]+)\}(?!\s*from)/g, (_statement, names) => `export {${names.split(",").filter((item) => !types.has(item.trim().split(/\s+as\s+/)[0])).join(",")}}`);
36
+ };
37
+ /**
38
+ * files 里的 `import.meta.env` 没有 Vite 注入,接到开发态占位对象上。
39
+ * @param code 源码文本。
40
+ * @param filename 当前虚拟文件名。
41
+ * @returns 替换 `import.meta` 之后的源码。
42
+ */
43
+ var rewriteImportMeta = (code, filename) => {
44
+ if (!code.includes("process") && !code.includes("import.meta")) return code;
45
+ const source = new MagicString(code);
46
+ let hasMeta = false;
47
+ walkIdentifiers(babelParse(code, { sourceType: "module" }), (id, parent, parents) => {
48
+ if (id.name === "import" && parent?.type === "MetaProperty") {
49
+ source.overwrite(parent.start, parent.end, "import_meta");
50
+ hasMeta = true;
51
+ }
52
+ const outer = parents[parents.length - 2];
53
+ if (id.name === "process" && parent?.type === "MemberExpression" && parent.object === id && !parent.computed && parent.property.type === "Identifier" && parent.property.name === "env" && outer?.type === "MemberExpression" && outer.object === parent && !outer.computed && outer.property.type === "Identifier" && outer.property.name === "NODE_ENV") source.overwrite(outer.start, outer.end, JSON.stringify("development"));
54
+ }, true);
55
+ if (!hasMeta) return source.toString();
56
+ const meta = {
57
+ url: `playground://${filename}`,
58
+ env: {
59
+ MODE: "development",
60
+ DEV: true,
61
+ PROD: false,
62
+ SSR: false
63
+ }
64
+ };
65
+ return `var import_meta = ${JSON.stringify(meta)};\n${source}`;
66
+ };
67
+ /**
68
+ * 将 TS / ESM 转成可被 `new Function('require','module','exports', code)` 执行的 CJS。
69
+ * @param code 源码文本。
70
+ * @param filename 当前虚拟文件名,用来判断是否按 TypeScript 转换。
71
+ * @param options 转换选项。
72
+ * @param options.typescript 是否启用 TypeScript 转换。
73
+ * @param options.jsx 是否转换 Vue JSX。
74
+ * @param options.esm 是否保留 ESM 导入导出供 iframe 使用。
75
+ * @returns 可执行的 CJS 文本。
76
+ */
77
+ var transformScript = (code, filename, options = {}) => {
78
+ const transforms = options.esm ? [] : ["imports"];
79
+ const wantTs = options.typescript === true || options.typescript !== false && (filename.endsWith(".ts") || filename.endsWith(".tsx"));
80
+ if (wantTs) transforms.unshift("typescript");
81
+ if (options.jsx) transforms.unshift("jsx");
82
+ try {
83
+ const script = wantTs ? removeImportedTypeExports(code) : code;
84
+ const source = options.jsx ? `import { h as __docs_h, Fragment as __docs_Fragment } from 'vue';\n${rewriteJsxAttributes(script)}` : script;
85
+ return `${rewriteImportMeta((0, sucrase.transform)(source, {
86
+ transforms,
87
+ disableESTransforms: true,
88
+ production: true,
89
+ jsxRuntime: "classic",
90
+ jsxPragma: "__docs_h",
91
+ jsxFragmentPragma: "__docs_Fragment",
92
+ filePath: filename
93
+ }).code, filename)}\n//# sourceURL=playground://${filename}`;
94
+ } catch (error) {
95
+ const message = error instanceof Error ? error.message : String(error);
96
+ throw new Error(`[Playground] 脚本转换失败 ${filename}: ${message}`, { cause: error });
97
+ }
98
+ };
99
+ //#endregion
100
+ Object.defineProperty(exports, "rewriteImportMeta", {
101
+ enumerable: true,
102
+ get: function() {
103
+ return rewriteImportMeta;
104
+ }
105
+ });
106
+ Object.defineProperty(exports, "transformScript", {
107
+ enumerable: true,
108
+ get: function() {
109
+ return transformScript;
110
+ }
111
+ });
@@ -0,0 +1,98 @@
1
+ import { transform } from "sucrase";
2
+ import * as VueCompiler from "@vue/compiler-sfc/dist/compiler-sfc.esm-browser.js";
3
+ //#region packages/playground/src/core/runtime/local/compile/script.ts
4
+ var { babelParse, walkIdentifiers, MagicString } = VueCompiler;
5
+ var rewriteJsxAttributes = (code) => {
6
+ const replacements = [];
7
+ for (const match of code.matchAll(/\b([\w-]+:[\w-]+)\s*=\s*\{/g)) {
8
+ let depth = 1;
9
+ let quote = "";
10
+ const start = match.index + match[0].length;
11
+ let end = start;
12
+ for (; end < code.length; end += 1) {
13
+ const character = code[end];
14
+ if (quote) {
15
+ if (character === "\\") end += 1;
16
+ else if (character === quote) quote = "";
17
+ } else if ("\"'`".includes(character)) quote = character;
18
+ else if (character === "{") depth += 1;
19
+ else if (character === "}" && --depth === 0) break;
20
+ }
21
+ replacements.push({
22
+ start: match.index,
23
+ end: end + 1,
24
+ text: `{...{${JSON.stringify(match[1])}: ${code.slice(start, end)}}}`
25
+ });
26
+ }
27
+ for (const item of replacements.reverse()) code = code.slice(0, item.start) + item.text + code.slice(item.end);
28
+ return code;
29
+ };
30
+ var removeImportedTypeExports = (code) => {
31
+ const types = /* @__PURE__ */ new Set();
32
+ for (const match of code.matchAll(/\bimport\s+type\s*\{([^}]+)\}\s*from\s*['"][^'"]+['"]/g)) for (const item of match[1].split(",")) types.add(item.trim().split(/\s+as\s+/).pop());
33
+ return code.replace(/\bexport\s*\{([^}]+)\}(?!\s*from)/g, (_statement, names) => `export {${names.split(",").filter((item) => !types.has(item.trim().split(/\s+as\s+/)[0])).join(",")}}`);
34
+ };
35
+ /**
36
+ * files 里的 `import.meta.env` 没有 Vite 注入,接到开发态占位对象上。
37
+ * @param code 源码文本。
38
+ * @param filename 当前虚拟文件名。
39
+ * @returns 替换 `import.meta` 之后的源码。
40
+ */
41
+ var rewriteImportMeta = (code, filename) => {
42
+ if (!code.includes("process") && !code.includes("import.meta")) return code;
43
+ const source = new MagicString(code);
44
+ let hasMeta = false;
45
+ walkIdentifiers(babelParse(code, { sourceType: "module" }), (id, parent, parents) => {
46
+ if (id.name === "import" && parent?.type === "MetaProperty") {
47
+ source.overwrite(parent.start, parent.end, "import_meta");
48
+ hasMeta = true;
49
+ }
50
+ const outer = parents[parents.length - 2];
51
+ if (id.name === "process" && parent?.type === "MemberExpression" && parent.object === id && !parent.computed && parent.property.type === "Identifier" && parent.property.name === "env" && outer?.type === "MemberExpression" && outer.object === parent && !outer.computed && outer.property.type === "Identifier" && outer.property.name === "NODE_ENV") source.overwrite(outer.start, outer.end, JSON.stringify("development"));
52
+ }, true);
53
+ if (!hasMeta) return source.toString();
54
+ const meta = {
55
+ url: `playground://${filename}`,
56
+ env: {
57
+ MODE: "development",
58
+ DEV: true,
59
+ PROD: false,
60
+ SSR: false
61
+ }
62
+ };
63
+ return `var import_meta = ${JSON.stringify(meta)};\n${source}`;
64
+ };
65
+ /**
66
+ * 将 TS / ESM 转成可被 `new Function('require','module','exports', code)` 执行的 CJS。
67
+ * @param code 源码文本。
68
+ * @param filename 当前虚拟文件名,用来判断是否按 TypeScript 转换。
69
+ * @param options 转换选项。
70
+ * @param options.typescript 是否启用 TypeScript 转换。
71
+ * @param options.jsx 是否转换 Vue JSX。
72
+ * @param options.esm 是否保留 ESM 导入导出供 iframe 使用。
73
+ * @returns 可执行的 CJS 文本。
74
+ */
75
+ var transformScript = (code, filename, options = {}) => {
76
+ const transforms = options.esm ? [] : ["imports"];
77
+ const wantTs = options.typescript === true || options.typescript !== false && (filename.endsWith(".ts") || filename.endsWith(".tsx"));
78
+ if (wantTs) transforms.unshift("typescript");
79
+ if (options.jsx) transforms.unshift("jsx");
80
+ try {
81
+ const script = wantTs ? removeImportedTypeExports(code) : code;
82
+ const source = options.jsx ? `import { h as __docs_h, Fragment as __docs_Fragment } from 'vue';\n${rewriteJsxAttributes(script)}` : script;
83
+ return `${rewriteImportMeta(transform(source, {
84
+ transforms,
85
+ disableESTransforms: true,
86
+ production: true,
87
+ jsxRuntime: "classic",
88
+ jsxPragma: "__docs_h",
89
+ jsxFragmentPragma: "__docs_Fragment",
90
+ filePath: filename
91
+ }).code, filename)}\n//# sourceURL=playground://${filename}`;
92
+ } catch (error) {
93
+ const message = error instanceof Error ? error.message : String(error);
94
+ throw new Error(`[Playground] 脚本转换失败 ${filename}: ${message}`, { cause: error });
95
+ }
96
+ };
97
+ //#endregion
98
+ export { transformScript as n, rewriteImportMeta as t };
@@ -1,4 +1,4 @@
1
- const require_cdn = require("./cdn-Czve5_9b.cjs");
1
+ const require_cdn = require("./cdn-BoYKnGD3.cjs");
2
2
  let vue = require("vue");
3
3
  //#region packages/playground/src/core/scss.ts
4
4
  var SCHEME = "docs-playground";
@@ -8,7 +8,6 @@ var LANG_ATTR_RE = /\s*lang\s*=\s*(['"]?)s[ac]ss\1/i;
8
8
  var SCSS_ERROR_MARK = "[playground-sass]";
9
9
  var INJECT_START = "/* docs-playground-scss-start */";
10
10
  var INJECT_END = "/* docs-playground-scss-end */";
11
- var EMPTY_JS = "export default {}\n";
12
11
  var boundStores = /* @__PURE__ */ new WeakSet();
13
12
  var wrappedCompilers = /* @__PURE__ */ new WeakSet();
14
13
  var testLoader;
@@ -164,6 +163,20 @@ var syncScssErrors = (store, scssErrors) => {
164
163
  if (next.map(String).join("\0") === store.errors.map(String).join("\0")) return;
165
164
  store.errors = next;
166
165
  };
166
+ var extractScssExports = (css, filename) => {
167
+ const exports = {};
168
+ if (/\.module\.(?:scss|sass)$/.test(filename)) css = css.replace(/:export\s*\{([^}]*)\}/g, (_block, declarations) => {
169
+ for (const declaration of declarations.split(";")) {
170
+ const colon = declaration.indexOf(":");
171
+ if (colon >= 0) exports[declaration.slice(0, colon).trim()] = declaration.slice(colon + 1).trim();
172
+ }
173
+ return "";
174
+ });
175
+ return {
176
+ css,
177
+ exports
178
+ };
179
+ };
167
180
  var applyStandaloneScss = (store, sass = loadedSass) => {
168
181
  if (!sass) return [];
169
182
  const fileMap = toPlaygroundFileMap(store.files);
@@ -172,10 +185,9 @@ var applyStandaloneScss = (store, sass = loadedSass) => {
172
185
  for (const [filename, file] of Object.entries(store.files)) {
173
186
  if (!isScssFile(filename) || !file.compiled) continue;
174
187
  try {
175
- const css = compileScssSource(file.code, filename, sass, fileMap);
188
+ const { css, exports } = extractScssExports(compileScssSource(file.code, filename, sass, fileMap), filename);
176
189
  file.compiled.css = css;
177
- file.compiled.js = EMPTY_JS;
178
- file.compiled.ssr = EMPTY_JS;
190
+ file.compiled.js = file.compiled.ssr = `export default ${JSON.stringify(exports)};\n`;
179
191
  if (!isScssPartial(filename) && css.trim()) injected.push(css);
180
192
  } catch (error) {
181
193
  errors.push(scssFail(filename, error));
@@ -225,6 +237,12 @@ Object.defineProperty(exports, "compileScssSource", {
225
237
  return compileScssSource;
226
238
  }
227
239
  });
240
+ Object.defineProperty(exports, "extractScssExports", {
241
+ enumerable: true,
242
+ get: function() {
243
+ return extractScssExports;
244
+ }
245
+ });
228
246
  Object.defineProperty(exports, "whenSassReady", {
229
247
  enumerable: true,
230
248
  get: function() {
@@ -1,4 +1,4 @@
1
- import { t as SASS_CDN_URL } from "./cdn-DEvdGJu2.js";
1
+ import { t as SASS_CDN_URL } from "./cdn-DQoETju_.js";
2
2
  import { watch } from "vue";
3
3
  //#region packages/playground/src/core/scss.ts
4
4
  var SCHEME = "docs-playground";
@@ -8,7 +8,6 @@ var LANG_ATTR_RE = /\s*lang\s*=\s*(['"]?)s[ac]ss\1/i;
8
8
  var SCSS_ERROR_MARK = "[playground-sass]";
9
9
  var INJECT_START = "/* docs-playground-scss-start */";
10
10
  var INJECT_END = "/* docs-playground-scss-end */";
11
- var EMPTY_JS = "export default {}\n";
12
11
  var boundStores = /* @__PURE__ */ new WeakSet();
13
12
  var wrappedCompilers = /* @__PURE__ */ new WeakSet();
14
13
  var loadedSass;
@@ -163,6 +162,20 @@ var syncScssErrors = (store, scssErrors) => {
163
162
  if (next.map(String).join("\0") === store.errors.map(String).join("\0")) return;
164
163
  store.errors = next;
165
164
  };
165
+ var extractScssExports = (css, filename) => {
166
+ const exports = {};
167
+ if (/\.module\.(?:scss|sass)$/.test(filename)) css = css.replace(/:export\s*\{([^}]*)\}/g, (_block, declarations) => {
168
+ for (const declaration of declarations.split(";")) {
169
+ const colon = declaration.indexOf(":");
170
+ if (colon >= 0) exports[declaration.slice(0, colon).trim()] = declaration.slice(colon + 1).trim();
171
+ }
172
+ return "";
173
+ });
174
+ return {
175
+ css,
176
+ exports
177
+ };
178
+ };
166
179
  var applyStandaloneScss = (store, sass = loadedSass) => {
167
180
  if (!sass) return [];
168
181
  const fileMap = toPlaygroundFileMap(store.files);
@@ -171,10 +184,9 @@ var applyStandaloneScss = (store, sass = loadedSass) => {
171
184
  for (const [filename, file] of Object.entries(store.files)) {
172
185
  if (!isScssFile(filename) || !file.compiled) continue;
173
186
  try {
174
- const css = compileScssSource(file.code, filename, sass, fileMap);
187
+ const { css, exports } = extractScssExports(compileScssSource(file.code, filename, sass, fileMap), filename);
175
188
  file.compiled.css = css;
176
- file.compiled.js = EMPTY_JS;
177
- file.compiled.ssr = EMPTY_JS;
189
+ file.compiled.js = file.compiled.ssr = `export default ${JSON.stringify(exports)};\n`;
178
190
  if (!isScssPartial(filename) && css.trim()) injected.push(css);
179
191
  } catch (error) {
180
192
  errors.push(scssFail(filename, error));
@@ -212,4 +224,4 @@ var bindPlaygroundScss = (store) => {
212
224
  };
213
225
  };
214
226
  //#endregion
215
- export { compileScssSource as n, whenSassReady as r, bindPlaygroundScss as t };
227
+ export { whenSassReady as i, compileScssSource as n, extractScssExports as r, bindPlaygroundScss as t };