@vizejs/vite-plugin-musea 0.0.1-alpha.102 → 0.0.1-alpha.104
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/{a11y-CHcxz6UR.d.ts → a11y-Bvx5TJb8.d.ts} +2 -2
- package/dist/{a11y-CHcxz6UR.d.ts.map → a11y-Bvx5TJb8.d.ts.map} +1 -1
- package/dist/a11y.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +248 -53
- package/dist/index.js.map +1 -1
- package/dist/{vrt-m01uFerp.d.ts → vrt-Vb4aqPZE.d.ts} +23 -1
- package/dist/vrt-Vb4aqPZE.d.ts.map +1 -0
- package/dist/vrt.d.ts +1 -1
- package/package.json +4 -4
- package/dist/vrt-m01uFerp.d.ts.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A11yOptions, A11yResult, ArtFileInfo, MuseaVrtRunner$1 as MuseaVrtRunner } from "./vrt-
|
|
1
|
+
import { A11yOptions, A11yResult, ArtFileInfo, MuseaVrtRunner$1 as MuseaVrtRunner } from "./vrt-Vb4aqPZE.js";
|
|
2
2
|
import { Page } from "playwright";
|
|
3
3
|
|
|
4
4
|
//#region src/a11y.d.ts
|
|
@@ -58,4 +58,4 @@ declare class MuseaA11yRunner {
|
|
|
58
58
|
|
|
59
59
|
//# sourceMappingURL=a11y.d.ts.map
|
|
60
60
|
export { A11ySummary, MuseaA11yRunner as MuseaA11yRunner$1 };
|
|
61
|
-
//# sourceMappingURL=a11y-
|
|
61
|
+
//# sourceMappingURL=a11y-Bvx5TJb8.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a11y-
|
|
1
|
+
{"version":3,"file":"a11y-Bvx5TJb8.d.ts","names":[],"sources":["../src/a11y.ts"],"sourcesContent":null,"mappings":";;;;;;;;AAmBA;;;UAAiB,WAAA;EA4BJ,eAAA,EAAA,MAAe;EAAA,aAAA,EAAA,MAAA;EAAA,eAGL,EAAA,MAAA;EAAgB,aAczB,EAAA,MAAA;EAAW,YAET,EAAA,MAAA;EAAc,aACjB,EAAA,MAAA;EAAU,UAAlB,EAAA,MAAA;;;;;AAkGgC,cAtHxB,eAAA,CAsHwB;EAAW,QAkBlB,OAAA;EAAU,WA6IV,CAAA,OAAA,CAAA,EAlRP,WAkRO;EAAU;;;;sBApQ1B,4CAEE,iBACX,QAAQ;;;;kBA+DW,6CAA6C,QAAQ;;;;sBAmCvD,eAAe;;;;8BAkBP;;;;8BA6IA"}
|
package/dist/a11y.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "./vrt-
|
|
2
|
-
import { A11ySummary, MuseaA11yRunner$1 as MuseaA11yRunner } from "./a11y-
|
|
1
|
+
import "./vrt-Vb4aqPZE.js";
|
|
2
|
+
import { A11ySummary, MuseaA11yRunner$1 as MuseaA11yRunner } from "./a11y-Bvx5TJb8.js";
|
|
3
3
|
export { A11ySummary, MuseaA11yRunner };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A11yOptions, A11yResult, AnalysisApiResponse, ArtFileInfo, ArtMetadata, ArtVariant, CaptureConfig, CiConfig, ComparisonConfig, CsfOutput, MuseaOptions, MuseaTheme, MuseaThemeColors, MuseaVrtRunner$1 as MuseaVrtRunner, PaletteApiResponse, ViewportConfig, VrtOptions, VrtResult, VrtSummary, generateVrtJsonReport$1 as generateVrtJsonReport, generateVrtReport$1 as generateVrtReport } from "./vrt-
|
|
2
|
-
import { A11ySummary, MuseaA11yRunner$1 as MuseaA11yRunner } from "./a11y-
|
|
1
|
+
import { A11yOptions, A11yResult, AnalysisApiResponse, ArtFileInfo, ArtMetadata, ArtVariant, CaptureConfig, CiConfig, ComparisonConfig, CsfOutput, MuseaOptions, MuseaTheme, MuseaThemeColors, MuseaVrtRunner$1 as MuseaVrtRunner, PaletteApiResponse, ViewportConfig, VrtOptions, VrtResult, VrtSummary, generateVrtJsonReport$1 as generateVrtJsonReport, generateVrtReport$1 as generateVrtReport } from "./vrt-Vb4aqPZE.js";
|
|
2
|
+
import { A11ySummary, MuseaA11yRunner$1 as MuseaA11yRunner } from "./a11y-Bvx5TJb8.js";
|
|
3
3
|
import { AutogenOptions, AutogenOutput, GeneratedVariant, PropDefinition, generateArtFile$1 as generateArtFile, writeArtFile$1 as writeArtFile } from "./autogen-D3Zjc3zI.js";
|
|
4
4
|
import { Plugin } from "vite";
|
|
5
5
|
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/style-dictionary.ts","../src/index.ts"],"sourcesContent":null,"mappings":";;;;;;;;;;;;;;;;;;;;UAWiB,WAAA;;;;eAIF;;EAJE,UAAA,CAAA,EAAA,MAAW;;;;AAa5B;;AAEyB,UAFR,aAAA,CAEQ;EAAW,IAA1B,EAAA,MAAA;EAAM,MACE,EADR,MACQ,CAAA,MAAA,EADO,WACP,CAAA;EAAa,aAAA,CAAA,EAAb,aAAa,EAAA;;;;AAM/B;UAAiB,qBAAA;cACH;;IAWG,IAAA,EAAA,MAAA;;;;AA2BjB;;;;AAAgF,UA3B/D,qBAAA,CA2B+D;;;;EAK1D,UAAA,EAAA,MAAW;EAAA;;;AAA6B;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/style-dictionary.ts","../src/index.ts"],"sourcesContent":null,"mappings":";;;;;;;;;;;;;;;;;;;;UAWiB,WAAA;;;;eAIF;;EAJE,UAAA,CAAA,EAAA,MAAW;;;;AAa5B;;AAEyB,UAFR,aAAA,CAEQ;EAAW,IAA1B,EAAA,MAAA;EAAM,MACE,EADR,MACQ,CAAA,MAAA,EADO,WACP,CAAA;EAAa,aAAA,CAAA,EAAb,aAAa,EAAA;;;;AAM/B;UAAiB,qBAAA;cACH;;IAWG,IAAA,EAAA,MAAA;;;;AA2BjB;;;;AAAgF,UA3B/D,qBAAA,CA2B+D;;;;EAK1D,UAAA,EAAA,MAAW;EAAA;;;AAA6B;;;;AA2J9D;;EAA6B,SACf,CAAA,EAAA,MAAA;EAAa;;AAElB;eAzKM;;;AAoMf;;AACc,KA/LF,cAAA,GA+LE,CAAA,KAAA,EA/LuB,WA+LvB,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,GA/LuD,WA+LvD;;;AACI;iBA3LI,WAAA,sBAAiC,QAAQ;;;AAgY/D;iBArOgB,aAAA,aACF,qCAEX,eAAe;;;AAoWlB;iBAzUgB,iBAAA,aACF,2BACF,eAAe;;;AA6W3B;;;;;iBAxKgB,kBAAA,aAA+B;ACtH/C;;;AAAmD,iBDwPnC,sBAAA,CCxPmC,UAAA,EDwPA,aCxPA,EAAA,CAAA,EAAA,MAAA;AAAM;;;iBD8RnC,sBAAA,SACZ,wBACP,QAAQ;UA6CM,eAAA;;;;;UAMA,eAAA;;;;WAIN;;KAGC,aAAA,GAAgB,eAAe;;;;;;;;;;;iBA8B3B,cAAA,WACJ;;;;;;cACA,eAAe,eACxB;;;;AAvrB4B;;;iBC4Tf,KAAA,WAAe,eAAoB"}
|
package/dist/index.js
CHANGED
|
@@ -86,15 +86,15 @@ function extractSubcategories(obj) {
|
|
|
86
86
|
function isTokenValue(value) {
|
|
87
87
|
if (typeof value !== "object" || value === null) return false;
|
|
88
88
|
const obj = value;
|
|
89
|
-
return "value" in obj && (typeof obj.value === "string" || typeof obj.value === "number");
|
|
89
|
+
return "value" in obj && (typeof obj.value === "string" || typeof obj.value === "number") || "$value" in obj && (typeof obj.$value === "string" || typeof obj.$value === "number");
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
92
|
* Normalize token to DesignToken interface.
|
|
93
93
|
*/
|
|
94
94
|
function normalizeToken(raw) {
|
|
95
95
|
const token = {
|
|
96
|
-
value: raw.value,
|
|
97
|
-
type: raw.type,
|
|
96
|
+
value: raw.value ?? raw.$value,
|
|
97
|
+
type: raw.type ?? raw.$type,
|
|
98
98
|
description: raw.description,
|
|
99
99
|
attributes: raw.attributes
|
|
100
100
|
};
|
|
@@ -549,6 +549,71 @@ function loadNative() {
|
|
|
549
549
|
}
|
|
550
550
|
}
|
|
551
551
|
/**
|
|
552
|
+
* JS-based fallback for SFC analysis when native `analyzeSfc` is not available.
|
|
553
|
+
* Uses regex parsing to extract props and emits from Vue SFC source.
|
|
554
|
+
*/
|
|
555
|
+
function analyzeSfcFallback(source, _options) {
|
|
556
|
+
try {
|
|
557
|
+
const props = [];
|
|
558
|
+
const emits = [];
|
|
559
|
+
const scriptSetupMatch = source.match(/<script\s+[^>]*setup[^>]*>([\s\S]*?)<\/script>/);
|
|
560
|
+
if (!scriptSetupMatch) {
|
|
561
|
+
const scriptMatch = source.match(/<script[^>]*>([\s\S]*?)<\/script>/);
|
|
562
|
+
if (!scriptMatch) return {
|
|
563
|
+
props: [],
|
|
564
|
+
emits: []
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
const scriptContent = scriptSetupMatch?.[1] || "";
|
|
568
|
+
const propsMatch = scriptContent.match(/defineProps\s*<\s*\{([\s\S]*?)\}>\s*\(/);
|
|
569
|
+
const propsMatch2 = scriptContent.match(/defineProps\s*<\s*\{([\s\S]*?)\}>/);
|
|
570
|
+
const propsBody = propsMatch?.[1] || propsMatch2?.[1];
|
|
571
|
+
if (propsBody) {
|
|
572
|
+
const lines = propsBody.split("\n");
|
|
573
|
+
let i = 0;
|
|
574
|
+
while (i < lines.length) {
|
|
575
|
+
const line = lines[i].trim();
|
|
576
|
+
if (line.startsWith("/**") || line.startsWith("*") || line.startsWith("*/")) {
|
|
577
|
+
i++;
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
const propMatch = line.match(/^(\w+)(\?)?:\s*(.+?)(?:;?\s*)$/);
|
|
581
|
+
if (propMatch) {
|
|
582
|
+
const name = propMatch[1];
|
|
583
|
+
const optional = !!propMatch[2];
|
|
584
|
+
let type = propMatch[3].replace(/;$/, "").trim();
|
|
585
|
+
const defaultPattern = new RegExp(`\\b${name}\\s*=\\s*([^,}\\n]+)`);
|
|
586
|
+
const defaultMatch = scriptContent.match(defaultPattern);
|
|
587
|
+
const defaultValue = defaultMatch ? defaultMatch[1].trim() : void 0;
|
|
588
|
+
props.push({
|
|
589
|
+
name,
|
|
590
|
+
type,
|
|
591
|
+
required: !optional && defaultValue === void 0,
|
|
592
|
+
...defaultValue !== void 0 ? { default_value: defaultValue } : {}
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
i++;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const emitsMatch = scriptContent.match(/defineEmits\s*<\s*\{([\s\S]*?)\}>/);
|
|
599
|
+
if (emitsMatch) {
|
|
600
|
+
const emitsBody = emitsMatch[1];
|
|
601
|
+
const emitRegex = /(\w+)\s*:/g;
|
|
602
|
+
let match;
|
|
603
|
+
while ((match = emitRegex.exec(emitsBody)) !== null) emits.push(match[1]);
|
|
604
|
+
}
|
|
605
|
+
return {
|
|
606
|
+
props,
|
|
607
|
+
emits
|
|
608
|
+
};
|
|
609
|
+
} catch {
|
|
610
|
+
return {
|
|
611
|
+
props: [],
|
|
612
|
+
emits: []
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
552
617
|
* Build the theme config object from plugin options for runtime injection.
|
|
553
618
|
*/
|
|
554
619
|
function buildThemeConfig(theme) {
|
|
@@ -577,9 +642,13 @@ function musea(options = {}) {
|
|
|
577
642
|
let inlineArt = options.inlineArt ?? false;
|
|
578
643
|
const tokensPath = options.tokensPath;
|
|
579
644
|
const themeConfig = buildThemeConfig(options.theme);
|
|
645
|
+
const previewCss = options.previewCss ?? [];
|
|
646
|
+
const previewSetup = options.previewSetup;
|
|
580
647
|
let config;
|
|
581
648
|
let server = null;
|
|
582
649
|
const artFiles = new Map();
|
|
650
|
+
let resolvedPreviewCss = [];
|
|
651
|
+
let resolvedPreviewSetup = null;
|
|
583
652
|
const mainPlugin = {
|
|
584
653
|
name: "vite-plugin-musea",
|
|
585
654
|
enforce: "pre",
|
|
@@ -597,6 +666,8 @@ function musea(options = {}) {
|
|
|
597
666
|
if (options.storybookCompat === void 0 && mc.storybookCompat !== void 0) storybookCompat = mc.storybookCompat;
|
|
598
667
|
if (options.inlineArt === void 0 && mc.inlineArt !== void 0) inlineArt = mc.inlineArt;
|
|
599
668
|
}
|
|
669
|
+
resolvedPreviewCss = previewCss.map((cssPath) => path.isAbsolute(cssPath) ? cssPath : path.resolve(resolvedConfig.root, cssPath));
|
|
670
|
+
if (previewSetup) resolvedPreviewSetup = path.isAbsolute(previewSetup) ? previewSetup : path.resolve(resolvedConfig.root, previewSetup);
|
|
600
671
|
},
|
|
601
672
|
configureServer(devServer) {
|
|
602
673
|
server = devServer;
|
|
@@ -610,7 +681,6 @@ function musea(options = {}) {
|
|
|
610
681
|
let html = await fs.promises.readFile(indexHtmlPath, "utf-8");
|
|
611
682
|
const themeScript = themeConfig ? `window.__MUSEA_THEME_CONFIG__=${JSON.stringify(themeConfig)};` : "";
|
|
612
683
|
html = html.replace("</head>", `<script>window.__MUSEA_BASE_PATH__='${basePath}';${themeScript}</script></head>`);
|
|
613
|
-
html = await devServer.transformIndexHtml(basePath + url, html);
|
|
614
684
|
res.setHeader("Content-Type", "text/html");
|
|
615
685
|
res.end(html);
|
|
616
686
|
return;
|
|
@@ -669,7 +739,7 @@ function musea(options = {}) {
|
|
|
669
739
|
return;
|
|
670
740
|
}
|
|
671
741
|
const variantComponentName = toPascalCase(variant.name);
|
|
672
|
-
const moduleCode = generatePreviewModule(art, variantComponentName, variant.name);
|
|
742
|
+
const moduleCode = generatePreviewModule(art, variantComponentName, variant.name, resolvedPreviewCss, resolvedPreviewSetup);
|
|
673
743
|
try {
|
|
674
744
|
const result = await devServer.transformRequest(`virtual:musea-preview:${artPath}:${variantName}`);
|
|
675
745
|
if (result) {
|
|
@@ -704,8 +774,7 @@ function musea(options = {}) {
|
|
|
704
774
|
res.end("Variant not found");
|
|
705
775
|
return;
|
|
706
776
|
}
|
|
707
|
-
const
|
|
708
|
-
const html = await devServer.transformIndexHtml(`${basePath}/preview?art=${encodeURIComponent(artPath)}&variant=${encodeURIComponent(variantName)}`, rawHtml);
|
|
777
|
+
const html = generatePreviewHtml(art, variant, basePath, config.base);
|
|
709
778
|
res.setHeader("Content-Type", "text/html");
|
|
710
779
|
res.end(html);
|
|
711
780
|
});
|
|
@@ -1021,16 +1090,57 @@ function musea(options = {}) {
|
|
|
1021
1090
|
try {
|
|
1022
1091
|
const source = await fs.promises.readFile(artPath$1, "utf-8");
|
|
1023
1092
|
const binding = loadNative();
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
} else sendJson({
|
|
1093
|
+
let palette;
|
|
1094
|
+
if (binding.generateArtPalette) palette = binding.generateArtPalette(source, { filename: artPath$1 });
|
|
1095
|
+
else palette = {
|
|
1028
1096
|
title: art$1.metadata.title,
|
|
1029
1097
|
controls: [],
|
|
1030
1098
|
groups: [],
|
|
1031
1099
|
json: "{}",
|
|
1032
1100
|
typescript: ""
|
|
1033
|
-
}
|
|
1101
|
+
};
|
|
1102
|
+
if (palette.controls.length === 0 && art$1.metadata.component) {
|
|
1103
|
+
const resolvedComponentPath = path.isAbsolute(art$1.metadata.component) ? art$1.metadata.component : path.resolve(path.dirname(artPath$1), art$1.metadata.component);
|
|
1104
|
+
try {
|
|
1105
|
+
const componentSource = await fs.promises.readFile(resolvedComponentPath, "utf-8");
|
|
1106
|
+
const analysis = binding.analyzeSfc ? binding.analyzeSfc(componentSource, { filename: resolvedComponentPath }) : analyzeSfcFallback(componentSource, { filename: resolvedComponentPath });
|
|
1107
|
+
if (analysis.props.length > 0) {
|
|
1108
|
+
palette.controls = analysis.props.map((prop) => {
|
|
1109
|
+
let control = "text";
|
|
1110
|
+
if (prop.type === "boolean") control = "boolean";
|
|
1111
|
+
else if (prop.type === "number") control = "number";
|
|
1112
|
+
else if (prop.type.includes("|") && !prop.type.includes("=>")) control = "select";
|
|
1113
|
+
const options$1 = [];
|
|
1114
|
+
if (control === "select") {
|
|
1115
|
+
const optionMatches = prop.type.match(/"([^"]+)"/g);
|
|
1116
|
+
if (optionMatches) for (const opt of optionMatches) {
|
|
1117
|
+
const val = opt.replace(/"/g, "");
|
|
1118
|
+
options$1.push({
|
|
1119
|
+
label: val,
|
|
1120
|
+
value: val
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
return {
|
|
1125
|
+
name: prop.name,
|
|
1126
|
+
control,
|
|
1127
|
+
default_value: prop.default_value !== void 0 ? prop.default_value === "true" ? true : prop.default_value === "false" ? false : typeof prop.default_value === "string" && prop.default_value.startsWith("\"") ? prop.default_value.replace(/^"|"$/g, "") : prop.default_value : void 0,
|
|
1128
|
+
description: void 0,
|
|
1129
|
+
required: prop.required,
|
|
1130
|
+
options: options$1,
|
|
1131
|
+
range: void 0,
|
|
1132
|
+
group: void 0
|
|
1133
|
+
};
|
|
1134
|
+
});
|
|
1135
|
+
palette.json = JSON.stringify({
|
|
1136
|
+
title: palette.title,
|
|
1137
|
+
controls: palette.controls
|
|
1138
|
+
}, null, 2);
|
|
1139
|
+
palette.typescript = `export interface ${palette.title}Props {\n${palette.controls.map((c) => ` ${c.name}${c.required ? "" : "?"}: ${c.control === "boolean" ? "boolean" : c.control === "number" ? "number" : c.control === "select" ? c.options.map((o) => `"${String(o.value)}"`).join(" | ") : "string"};`).join("\n")}\n}\n`;
|
|
1140
|
+
}
|
|
1141
|
+
} catch {}
|
|
1142
|
+
}
|
|
1143
|
+
sendJson(palette);
|
|
1034
1144
|
} catch (e) {
|
|
1035
1145
|
sendError(e instanceof Error ? e.message : String(e));
|
|
1036
1146
|
}
|
|
@@ -1051,10 +1161,10 @@ function musea(options = {}) {
|
|
|
1051
1161
|
if (binding.analyzeSfc) {
|
|
1052
1162
|
const analysis = binding.analyzeSfc(source, { filename: resolvedComponentPath });
|
|
1053
1163
|
sendJson(analysis);
|
|
1054
|
-
} else
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
}
|
|
1164
|
+
} else {
|
|
1165
|
+
const analysis = analyzeSfcFallback(source, { filename: resolvedComponentPath });
|
|
1166
|
+
sendJson(analysis);
|
|
1167
|
+
}
|
|
1058
1168
|
} else sendJson({
|
|
1059
1169
|
props: [],
|
|
1060
1170
|
emits: []
|
|
@@ -1144,7 +1254,7 @@ function musea(options = {}) {
|
|
|
1144
1254
|
return;
|
|
1145
1255
|
}
|
|
1146
1256
|
const variantComponentName = toPascalCase(variant.name);
|
|
1147
|
-
const moduleCode = generatePreviewModuleWithProps(art, variantComponentName, variant.name, propsOverride);
|
|
1257
|
+
const moduleCode = generatePreviewModuleWithProps(art, variantComponentName, variant.name, propsOverride, resolvedPreviewCss, resolvedPreviewSetup);
|
|
1148
1258
|
res.setHeader("Content-Type", "application/javascript");
|
|
1149
1259
|
res.end(moduleCode);
|
|
1150
1260
|
} catch (e) {
|
|
@@ -1278,15 +1388,15 @@ function musea(options = {}) {
|
|
|
1278
1388
|
if (id.startsWith("virtual:musea-preview:")) return "\0musea-preview:" + id.slice(22);
|
|
1279
1389
|
if (id.startsWith("virtual:musea-art:")) {
|
|
1280
1390
|
const artPath = id.slice(18);
|
|
1281
|
-
if (artFiles.has(artPath)) return "\0musea-art:" + artPath;
|
|
1391
|
+
if (artFiles.has(artPath)) return "\0musea-art:" + artPath + "?musea-virtual";
|
|
1282
1392
|
}
|
|
1283
1393
|
if (id.endsWith(".art.vue")) {
|
|
1284
1394
|
const resolved = path.resolve(config.root, id);
|
|
1285
|
-
if (artFiles.has(resolved)) return VIRTUAL_MUSEA_PREFIX + resolved;
|
|
1395
|
+
if (artFiles.has(resolved)) return VIRTUAL_MUSEA_PREFIX + resolved + "?musea-virtual";
|
|
1286
1396
|
}
|
|
1287
1397
|
if (inlineArt && id.endsWith(".vue") && !id.endsWith(".art.vue")) {
|
|
1288
1398
|
const resolved = path.resolve(config.root, id);
|
|
1289
|
-
if (artFiles.has(resolved)) return VIRTUAL_MUSEA_PREFIX + resolved;
|
|
1399
|
+
if (artFiles.has(resolved)) return VIRTUAL_MUSEA_PREFIX + resolved + "?musea-virtual";
|
|
1290
1400
|
}
|
|
1291
1401
|
return null;
|
|
1292
1402
|
},
|
|
@@ -1302,17 +1412,17 @@ function musea(options = {}) {
|
|
|
1302
1412
|
const art = artFiles.get(artPath);
|
|
1303
1413
|
if (art) {
|
|
1304
1414
|
const variantComponentName = toPascalCase(variantName);
|
|
1305
|
-
return generatePreviewModule(art, variantComponentName, variantName);
|
|
1415
|
+
return generatePreviewModule(art, variantComponentName, variantName, resolvedPreviewCss, resolvedPreviewSetup);
|
|
1306
1416
|
}
|
|
1307
1417
|
}
|
|
1308
1418
|
}
|
|
1309
1419
|
if (id.startsWith("\0musea-art:")) {
|
|
1310
|
-
const artPath = id.slice(11);
|
|
1420
|
+
const artPath = id.slice(11).replace(/\?musea-virtual$/, "");
|
|
1311
1421
|
const art = artFiles.get(artPath);
|
|
1312
1422
|
if (art) return generateArtModule(art, artPath);
|
|
1313
1423
|
}
|
|
1314
1424
|
if (id.startsWith(VIRTUAL_MUSEA_PREFIX)) {
|
|
1315
|
-
const realPath = id.slice(VIRTUAL_MUSEA_PREFIX.length);
|
|
1425
|
+
const realPath = id.slice(VIRTUAL_MUSEA_PREFIX.length).replace(/\?musea-virtual$/, "");
|
|
1316
1426
|
const art = artFiles.get(realPath);
|
|
1317
1427
|
if (art) return generateArtModule(art, realPath);
|
|
1318
1428
|
}
|
|
@@ -1322,7 +1432,7 @@ function musea(options = {}) {
|
|
|
1322
1432
|
const { file } = ctx;
|
|
1323
1433
|
if (file.endsWith(".art.vue") && artFiles.has(file)) {
|
|
1324
1434
|
await processArtFile(file);
|
|
1325
|
-
const virtualId = VIRTUAL_MUSEA_PREFIX + file;
|
|
1435
|
+
const virtualId = VIRTUAL_MUSEA_PREFIX + file + "?musea-virtual";
|
|
1326
1436
|
const modules = server?.moduleGraph.getModulesByFile(virtualId);
|
|
1327
1437
|
if (modules) return [...modules];
|
|
1328
1438
|
}
|
|
@@ -1356,12 +1466,13 @@ function musea(options = {}) {
|
|
|
1356
1466
|
variants: parsed.variants.map((v) => ({
|
|
1357
1467
|
name: v.name,
|
|
1358
1468
|
template: v.template,
|
|
1359
|
-
isDefault: v.
|
|
1360
|
-
skipVrt: v.
|
|
1469
|
+
isDefault: v.isDefault,
|
|
1470
|
+
skipVrt: v.skipVrt
|
|
1361
1471
|
})),
|
|
1362
|
-
hasScriptSetup: parsed.
|
|
1363
|
-
|
|
1364
|
-
|
|
1472
|
+
hasScriptSetup: parsed.hasScriptSetup,
|
|
1473
|
+
scriptSetupContent: parsed.hasScriptSetup ? extractScriptSetupContent(source) : void 0,
|
|
1474
|
+
hasScript: parsed.hasScript,
|
|
1475
|
+
styleCount: parsed.styleCount,
|
|
1365
1476
|
isInline,
|
|
1366
1477
|
componentPath: isInline ? filePath : void 0
|
|
1367
1478
|
};
|
|
@@ -2440,10 +2551,15 @@ function __museaInitAddons(container, variantName) {
|
|
|
2440
2551
|
window.parent.postMessage({ type: 'musea:ready', payload: {} }, '*');
|
|
2441
2552
|
}
|
|
2442
2553
|
`;
|
|
2443
|
-
function generatePreviewModule(art, variantComponentName, variantName) {
|
|
2554
|
+
function generatePreviewModule(art, variantComponentName, variantName, cssImports = [], previewSetup = null) {
|
|
2444
2555
|
const artModuleId = `virtual:musea-art:${art.path}`;
|
|
2445
2556
|
const escapedVariantName = escapeTemplate(variantName);
|
|
2557
|
+
const cssImportStatements = cssImports.map((cssPath) => `import '${cssPath}';`).join("\n");
|
|
2558
|
+
const setupImport = previewSetup ? `import __museaPreviewSetup from '${previewSetup}';` : "";
|
|
2559
|
+
const setupCall = previewSetup ? "await __museaPreviewSetup(app);" : "";
|
|
2446
2560
|
return `
|
|
2561
|
+
${cssImportStatements}
|
|
2562
|
+
${setupImport}
|
|
2447
2563
|
import { createApp, reactive, h } from 'vue';
|
|
2448
2564
|
import * as artModule from '${artModuleId}';
|
|
2449
2565
|
|
|
@@ -2479,6 +2595,7 @@ async function mount() {
|
|
|
2479
2595
|
|
|
2480
2596
|
// Create and mount the app
|
|
2481
2597
|
const app = createApp(VariantComponent);
|
|
2598
|
+
${setupCall}
|
|
2482
2599
|
container.innerHTML = '';
|
|
2483
2600
|
container.className = 'musea-variant';
|
|
2484
2601
|
app.mount(container);
|
|
@@ -2513,7 +2630,7 @@ async function mount() {
|
|
|
2513
2630
|
}
|
|
2514
2631
|
}
|
|
2515
2632
|
|
|
2516
|
-
function remountWithProps(Component) {
|
|
2633
|
+
async function remountWithProps(Component) {
|
|
2517
2634
|
if (currentApp) {
|
|
2518
2635
|
currentApp.unmount();
|
|
2519
2636
|
}
|
|
@@ -2524,12 +2641,11 @@ function remountWithProps(Component) {
|
|
|
2524
2641
|
if (slotsOverride.default) {
|
|
2525
2642
|
slotFns.default = () => h('span', { innerHTML: slotsOverride.default });
|
|
2526
2643
|
}
|
|
2527
|
-
return h(
|
|
2528
|
-
h(Component, { ...propsOverride }, slotFns)
|
|
2529
|
-
]);
|
|
2644
|
+
return h(Component, { ...propsOverride }, slotFns);
|
|
2530
2645
|
};
|
|
2531
2646
|
}
|
|
2532
2647
|
});
|
|
2648
|
+
${setupCall}
|
|
2533
2649
|
container.innerHTML = '';
|
|
2534
2650
|
app.mount(container);
|
|
2535
2651
|
currentApp = app;
|
|
@@ -2542,6 +2658,57 @@ function generateManifestModule(artFiles) {
|
|
|
2542
2658
|
const arts = Array.from(artFiles.values());
|
|
2543
2659
|
return `export const arts = ${JSON.stringify(arts, null, 2)};`;
|
|
2544
2660
|
}
|
|
2661
|
+
/**
|
|
2662
|
+
* Extract the content of the first <script setup> block from a Vue SFC source.
|
|
2663
|
+
*/
|
|
2664
|
+
function extractScriptSetupContent(source) {
|
|
2665
|
+
const match = source.match(/<script\s+[^>]*setup[^>]*>([\s\S]*?)<\/script>/);
|
|
2666
|
+
return match?.[1]?.trim();
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Parse script setup content into imports and setup body.
|
|
2670
|
+
* Returns the import lines, setup body lines, and all identifiers to expose.
|
|
2671
|
+
*/
|
|
2672
|
+
function parseScriptSetupForArt(content) {
|
|
2673
|
+
const lines = content.split("\n");
|
|
2674
|
+
const imports = [];
|
|
2675
|
+
const setupBody = [];
|
|
2676
|
+
const returnNames = new Set();
|
|
2677
|
+
for (const line of lines) {
|
|
2678
|
+
const trimmed = line.trim();
|
|
2679
|
+
if (!trimmed || trimmed.startsWith("//")) continue;
|
|
2680
|
+
if (trimmed.startsWith("import ")) {
|
|
2681
|
+
imports.push(line);
|
|
2682
|
+
const defaultMatch = trimmed.match(/^import\s+(\w+)/);
|
|
2683
|
+
if (defaultMatch && defaultMatch[1] !== "type") returnNames.add(defaultMatch[1]);
|
|
2684
|
+
const namedMatch = trimmed.match(/\{([^}]+)\}/);
|
|
2685
|
+
if (namedMatch) for (const part of namedMatch[1].split(",")) {
|
|
2686
|
+
const name = part.trim().split(/\s+as\s+/).pop()?.trim();
|
|
2687
|
+
if (name && !name.startsWith("type ")) returnNames.add(name);
|
|
2688
|
+
}
|
|
2689
|
+
} else {
|
|
2690
|
+
setupBody.push(line);
|
|
2691
|
+
const constMatch = trimmed.match(/^(?:const|let|var)\s+(\w+)/);
|
|
2692
|
+
if (constMatch) returnNames.add(constMatch[1]);
|
|
2693
|
+
const destructMatch = trimmed.match(/^(?:const|let|var)\s+\{([^}]+)\}/);
|
|
2694
|
+
if (destructMatch) for (const part of destructMatch[1].split(",")) {
|
|
2695
|
+
const name = part.trim().split(/\s*:\s*/).shift()?.trim();
|
|
2696
|
+
if (name) returnNames.add(name);
|
|
2697
|
+
}
|
|
2698
|
+
const arrayMatch = trimmed.match(/^(?:const|let|var)\s+\[([^\]]+)\]/);
|
|
2699
|
+
if (arrayMatch) for (const part of arrayMatch[1].split(",")) {
|
|
2700
|
+
const name = part.trim();
|
|
2701
|
+
if (name && name !== "...") returnNames.add(name);
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
returnNames.delete("type");
|
|
2706
|
+
return {
|
|
2707
|
+
imports,
|
|
2708
|
+
setupBody,
|
|
2709
|
+
returnNames: [...returnNames]
|
|
2710
|
+
};
|
|
2711
|
+
}
|
|
2545
2712
|
function generateArtModule(art, filePath) {
|
|
2546
2713
|
let componentImportPath;
|
|
2547
2714
|
let componentName;
|
|
@@ -2553,12 +2720,27 @@ function generateArtModule(art, filePath) {
|
|
|
2553
2720
|
componentImportPath = path.isAbsolute(comp) ? comp : path.resolve(path.dirname(filePath), comp);
|
|
2554
2721
|
componentName = path.basename(comp, ".vue");
|
|
2555
2722
|
}
|
|
2723
|
+
const scriptSetup = art.scriptSetupContent ? parseScriptSetupForArt(art.scriptSetupContent) : null;
|
|
2556
2724
|
let code = `
|
|
2557
2725
|
// Auto-generated module for: ${path.basename(filePath)}
|
|
2558
2726
|
import { defineComponent, h } from 'vue';
|
|
2559
2727
|
`;
|
|
2728
|
+
if (scriptSetup) {
|
|
2729
|
+
const artDir = path.dirname(filePath);
|
|
2730
|
+
for (const imp of scriptSetup.imports) {
|
|
2731
|
+
const resolved = imp.replace(/from\s+(['"])(\.[^'"]+)\1/, (_match, quote, relPath) => {
|
|
2732
|
+
const absPath = path.resolve(artDir, relPath);
|
|
2733
|
+
return `from ${quote}${absPath}${quote}`;
|
|
2734
|
+
});
|
|
2735
|
+
code += `${resolved}\n`;
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2560
2738
|
if (componentImportPath && componentName) {
|
|
2561
|
-
|
|
2739
|
+
const alreadyImported = scriptSetup?.imports.some((imp) => {
|
|
2740
|
+
if (imp.includes(`from '${componentImportPath}'`) || imp.includes(`from "${componentImportPath}"`)) return true;
|
|
2741
|
+
return new RegExp(`^import\\s+${componentName}[\\s,]`).test(imp.trim());
|
|
2742
|
+
});
|
|
2743
|
+
if (!alreadyImported) code += `import ${componentName} from '${componentImportPath}';\n`;
|
|
2562
2744
|
code += `export const __component__ = ${componentName};\n`;
|
|
2563
2745
|
}
|
|
2564
2746
|
code += `
|
|
@@ -2570,12 +2752,27 @@ export const variants = ${JSON.stringify(art.variants)};
|
|
|
2570
2752
|
let template = variant.template;
|
|
2571
2753
|
if (componentName) template = template.replace(/<Self/g, `<${componentName}`).replace(/<\/Self>/g, `</${componentName}>`);
|
|
2572
2754
|
const escapedTemplate = template.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
|
|
2573
|
-
const fullTemplate = `<div
|
|
2574
|
-
|
|
2575
|
-
|
|
2755
|
+
const fullTemplate = `<div data-variant="${variant.name}">${escapedTemplate}</div>`;
|
|
2756
|
+
const componentNames = new Set();
|
|
2757
|
+
if (componentName) componentNames.add(componentName);
|
|
2758
|
+
if (scriptSetup) {
|
|
2759
|
+
for (const name of scriptSetup.returnNames) if (/^[A-Z]/.test(name)) componentNames.add(name);
|
|
2760
|
+
}
|
|
2761
|
+
const components = componentNames.size > 0 ? ` components: { ${[...componentNames].join(", ")} },\n` : "";
|
|
2762
|
+
if (scriptSetup && scriptSetup.setupBody.length > 0) code += `
|
|
2763
|
+
export const ${variantComponentName} = defineComponent({
|
|
2576
2764
|
name: '${variantComponentName}',
|
|
2577
|
-
|
|
2765
|
+
${components} setup() {
|
|
2766
|
+
${scriptSetup.setupBody.map((l) => ` ${l}`).join("\n")}
|
|
2767
|
+
return { ${scriptSetup.returnNames.join(", ")} };
|
|
2768
|
+
},
|
|
2578
2769
|
template: \`${fullTemplate}\`,
|
|
2770
|
+
});
|
|
2771
|
+
`;
|
|
2772
|
+
else if (componentName) code += `
|
|
2773
|
+
export const ${variantComponentName} = {
|
|
2774
|
+
name: '${variantComponentName}',
|
|
2775
|
+
${components} template: \`${fullTemplate}\`,
|
|
2579
2776
|
};
|
|
2580
2777
|
`;
|
|
2581
2778
|
else code += `
|
|
@@ -2611,11 +2808,16 @@ function toPascalCase(str) {
|
|
|
2611
2808
|
function escapeTemplate(str) {
|
|
2612
2809
|
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n");
|
|
2613
2810
|
}
|
|
2614
|
-
function generatePreviewModuleWithProps(art, variantComponentName, variantName, propsOverride) {
|
|
2811
|
+
function generatePreviewModuleWithProps(art, variantComponentName, variantName, propsOverride, cssImports = [], previewSetup = null) {
|
|
2615
2812
|
const artModuleId = `virtual:musea-art:${art.path}`;
|
|
2616
2813
|
const escapedVariantName = escapeTemplate(variantName);
|
|
2617
2814
|
const propsJson = JSON.stringify(propsOverride);
|
|
2815
|
+
const cssImportStatements = cssImports.map((cssPath) => `import '${cssPath}';`).join("\n");
|
|
2816
|
+
const setupImport = previewSetup ? `import __museaPreviewSetup from '${previewSetup}';` : "";
|
|
2817
|
+
const setupCall = previewSetup ? "await __museaPreviewSetup(app);" : "";
|
|
2618
2818
|
return `
|
|
2819
|
+
${cssImportStatements}
|
|
2820
|
+
${setupImport}
|
|
2619
2821
|
import { createApp, h } from 'vue';
|
|
2620
2822
|
import * as artModule from '${artModuleId}';
|
|
2621
2823
|
|
|
@@ -2638,6 +2840,7 @@ async function mount() {
|
|
|
2638
2840
|
};
|
|
2639
2841
|
|
|
2640
2842
|
const app = createApp(WrappedComponent);
|
|
2843
|
+
${setupCall}
|
|
2641
2844
|
container.innerHTML = '';
|
|
2642
2845
|
container.className = 'musea-variant';
|
|
2643
2846
|
app.mount(container);
|
|
@@ -2652,14 +2855,16 @@ async function mount() {
|
|
|
2652
2855
|
mount();
|
|
2653
2856
|
`;
|
|
2654
2857
|
}
|
|
2655
|
-
function generatePreviewHtml(art, variant, _basePath) {
|
|
2656
|
-
const
|
|
2858
|
+
function generatePreviewHtml(art, variant, _basePath, viteBase) {
|
|
2859
|
+
const previewModuleUrl = `${_basePath}/preview-module?art=${encodeURIComponent(art.path)}&variant=${encodeURIComponent(variant.name)}`;
|
|
2860
|
+
const base = (viteBase || "/").replace(/\/$/, "");
|
|
2657
2861
|
return `<!DOCTYPE html>
|
|
2658
2862
|
<html lang="en">
|
|
2659
2863
|
<head>
|
|
2660
2864
|
<meta charset="UTF-8">
|
|
2661
2865
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
2662
2866
|
<title>${escapeHtml(art.metadata.title)} - ${escapeHtml(variant.name)}</title>
|
|
2867
|
+
<script type="module" src="${base}/@vite/client"></script>
|
|
2663
2868
|
<style>
|
|
2664
2869
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
2665
2870
|
html, body {
|
|
@@ -2671,10 +2876,6 @@ function generatePreviewHtml(art, variant, _basePath) {
|
|
|
2671
2876
|
background: #ffffff;
|
|
2672
2877
|
}
|
|
2673
2878
|
.musea-variant {
|
|
2674
|
-
padding: 1.5rem;
|
|
2675
|
-
display: flex;
|
|
2676
|
-
align-items: center;
|
|
2677
|
-
justify-content: center;
|
|
2678
2879
|
min-height: 100vh;
|
|
2679
2880
|
}
|
|
2680
2881
|
.musea-error {
|
|
@@ -2748,13 +2949,7 @@ function generatePreviewHtml(art, variant, _basePath) {
|
|
|
2748
2949
|
Loading component...
|
|
2749
2950
|
</div>
|
|
2750
2951
|
</div>
|
|
2751
|
-
<script type="module">
|
|
2752
|
-
import(${importSpecifier}).catch(function(e) {
|
|
2753
|
-
console.error('[musea-preview] Failed to load module:', e);
|
|
2754
|
-
var c = document.getElementById('app');
|
|
2755
|
-
if (c) c.innerHTML = '<div class="musea-error"><div class="musea-error-title">Failed to load preview module</div><div>' + e.message + '</div></div>';
|
|
2756
|
-
});
|
|
2757
|
-
</script>
|
|
2952
|
+
<script type="module" src="${previewModuleUrl}"></script>
|
|
2758
2953
|
</body>
|
|
2759
2954
|
</html>`;
|
|
2760
2955
|
}
|