@vizejs/vite-plugin-musea 0.0.1-alpha.101 → 0.0.1-alpha.103
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 +250 -54
- 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 +7 -7
- 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
|
};
|
|
@@ -1379,7 +1490,8 @@ function shouldProcess(file, include, exclude, root) {
|
|
|
1379
1490
|
return false;
|
|
1380
1491
|
}
|
|
1381
1492
|
function matchGlob(filepath, pattern) {
|
|
1382
|
-
const
|
|
1493
|
+
const PLACEHOLDER = "<<GLOBSTAR>>";
|
|
1494
|
+
const regex = pattern.replaceAll("**", PLACEHOLDER).replace(/\./g, "\\.").replace(/\*/g, "[^/]*").replaceAll(PLACEHOLDER, ".*");
|
|
1383
1495
|
return new RegExp(`^${regex}$`).test(filepath);
|
|
1384
1496
|
}
|
|
1385
1497
|
async function scanArtFiles(root, include, exclude, scanInlineArt = false) {
|
|
@@ -2439,10 +2551,15 @@ function __museaInitAddons(container, variantName) {
|
|
|
2439
2551
|
window.parent.postMessage({ type: 'musea:ready', payload: {} }, '*');
|
|
2440
2552
|
}
|
|
2441
2553
|
`;
|
|
2442
|
-
function generatePreviewModule(art, variantComponentName, variantName) {
|
|
2554
|
+
function generatePreviewModule(art, variantComponentName, variantName, cssImports = [], previewSetup = null) {
|
|
2443
2555
|
const artModuleId = `virtual:musea-art:${art.path}`;
|
|
2444
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);" : "";
|
|
2445
2560
|
return `
|
|
2561
|
+
${cssImportStatements}
|
|
2562
|
+
${setupImport}
|
|
2446
2563
|
import { createApp, reactive, h } from 'vue';
|
|
2447
2564
|
import * as artModule from '${artModuleId}';
|
|
2448
2565
|
|
|
@@ -2478,6 +2595,7 @@ async function mount() {
|
|
|
2478
2595
|
|
|
2479
2596
|
// Create and mount the app
|
|
2480
2597
|
const app = createApp(VariantComponent);
|
|
2598
|
+
${setupCall}
|
|
2481
2599
|
container.innerHTML = '';
|
|
2482
2600
|
container.className = 'musea-variant';
|
|
2483
2601
|
app.mount(container);
|
|
@@ -2512,7 +2630,7 @@ async function mount() {
|
|
|
2512
2630
|
}
|
|
2513
2631
|
}
|
|
2514
2632
|
|
|
2515
|
-
function remountWithProps(Component) {
|
|
2633
|
+
async function remountWithProps(Component) {
|
|
2516
2634
|
if (currentApp) {
|
|
2517
2635
|
currentApp.unmount();
|
|
2518
2636
|
}
|
|
@@ -2523,12 +2641,11 @@ function remountWithProps(Component) {
|
|
|
2523
2641
|
if (slotsOverride.default) {
|
|
2524
2642
|
slotFns.default = () => h('span', { innerHTML: slotsOverride.default });
|
|
2525
2643
|
}
|
|
2526
|
-
return h(
|
|
2527
|
-
h(Component, { ...propsOverride }, slotFns)
|
|
2528
|
-
]);
|
|
2644
|
+
return h(Component, { ...propsOverride }, slotFns);
|
|
2529
2645
|
};
|
|
2530
2646
|
}
|
|
2531
2647
|
});
|
|
2648
|
+
${setupCall}
|
|
2532
2649
|
container.innerHTML = '';
|
|
2533
2650
|
app.mount(container);
|
|
2534
2651
|
currentApp = app;
|
|
@@ -2541,6 +2658,57 @@ function generateManifestModule(artFiles) {
|
|
|
2541
2658
|
const arts = Array.from(artFiles.values());
|
|
2542
2659
|
return `export const arts = ${JSON.stringify(arts, null, 2)};`;
|
|
2543
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
|
+
}
|
|
2544
2712
|
function generateArtModule(art, filePath) {
|
|
2545
2713
|
let componentImportPath;
|
|
2546
2714
|
let componentName;
|
|
@@ -2552,12 +2720,27 @@ function generateArtModule(art, filePath) {
|
|
|
2552
2720
|
componentImportPath = path.isAbsolute(comp) ? comp : path.resolve(path.dirname(filePath), comp);
|
|
2553
2721
|
componentName = path.basename(comp, ".vue");
|
|
2554
2722
|
}
|
|
2723
|
+
const scriptSetup = art.scriptSetupContent ? parseScriptSetupForArt(art.scriptSetupContent) : null;
|
|
2555
2724
|
let code = `
|
|
2556
2725
|
// Auto-generated module for: ${path.basename(filePath)}
|
|
2557
2726
|
import { defineComponent, h } from 'vue';
|
|
2558
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
|
+
}
|
|
2559
2738
|
if (componentImportPath && componentName) {
|
|
2560
|
-
|
|
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`;
|
|
2561
2744
|
code += `export const __component__ = ${componentName};\n`;
|
|
2562
2745
|
}
|
|
2563
2746
|
code += `
|
|
@@ -2569,12 +2752,27 @@ export const variants = ${JSON.stringify(art.variants)};
|
|
|
2569
2752
|
let template = variant.template;
|
|
2570
2753
|
if (componentName) template = template.replace(/<Self/g, `<${componentName}`).replace(/<\/Self>/g, `</${componentName}>`);
|
|
2571
2754
|
const escapedTemplate = template.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
|
|
2572
|
-
const fullTemplate = `<div
|
|
2573
|
-
|
|
2574
|
-
|
|
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({
|
|
2575
2764
|
name: '${variantComponentName}',
|
|
2576
|
-
|
|
2765
|
+
${components} setup() {
|
|
2766
|
+
${scriptSetup.setupBody.map((l) => ` ${l}`).join("\n")}
|
|
2767
|
+
return { ${scriptSetup.returnNames.join(", ")} };
|
|
2768
|
+
},
|
|
2577
2769
|
template: \`${fullTemplate}\`,
|
|
2770
|
+
});
|
|
2771
|
+
`;
|
|
2772
|
+
else if (componentName) code += `
|
|
2773
|
+
export const ${variantComponentName} = {
|
|
2774
|
+
name: '${variantComponentName}',
|
|
2775
|
+
${components} template: \`${fullTemplate}\`,
|
|
2578
2776
|
};
|
|
2579
2777
|
`;
|
|
2580
2778
|
else code += `
|
|
@@ -2610,11 +2808,16 @@ function toPascalCase(str) {
|
|
|
2610
2808
|
function escapeTemplate(str) {
|
|
2611
2809
|
return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n");
|
|
2612
2810
|
}
|
|
2613
|
-
function generatePreviewModuleWithProps(art, variantComponentName, variantName, propsOverride) {
|
|
2811
|
+
function generatePreviewModuleWithProps(art, variantComponentName, variantName, propsOverride, cssImports = [], previewSetup = null) {
|
|
2614
2812
|
const artModuleId = `virtual:musea-art:${art.path}`;
|
|
2615
2813
|
const escapedVariantName = escapeTemplate(variantName);
|
|
2616
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);" : "";
|
|
2617
2818
|
return `
|
|
2819
|
+
${cssImportStatements}
|
|
2820
|
+
${setupImport}
|
|
2618
2821
|
import { createApp, h } from 'vue';
|
|
2619
2822
|
import * as artModule from '${artModuleId}';
|
|
2620
2823
|
|
|
@@ -2637,6 +2840,7 @@ async function mount() {
|
|
|
2637
2840
|
};
|
|
2638
2841
|
|
|
2639
2842
|
const app = createApp(WrappedComponent);
|
|
2843
|
+
${setupCall}
|
|
2640
2844
|
container.innerHTML = '';
|
|
2641
2845
|
container.className = 'musea-variant';
|
|
2642
2846
|
app.mount(container);
|
|
@@ -2651,14 +2855,16 @@ async function mount() {
|
|
|
2651
2855
|
mount();
|
|
2652
2856
|
`;
|
|
2653
2857
|
}
|
|
2654
|
-
function generatePreviewHtml(art, variant, _basePath) {
|
|
2655
|
-
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(/\/$/, "");
|
|
2656
2861
|
return `<!DOCTYPE html>
|
|
2657
2862
|
<html lang="en">
|
|
2658
2863
|
<head>
|
|
2659
2864
|
<meta charset="UTF-8">
|
|
2660
2865
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
2661
2866
|
<title>${escapeHtml(art.metadata.title)} - ${escapeHtml(variant.name)}</title>
|
|
2867
|
+
<script type="module" src="${base}/@vite/client"></script>
|
|
2662
2868
|
<style>
|
|
2663
2869
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
2664
2870
|
html, body {
|
|
@@ -2670,10 +2876,6 @@ function generatePreviewHtml(art, variant, _basePath) {
|
|
|
2670
2876
|
background: #ffffff;
|
|
2671
2877
|
}
|
|
2672
2878
|
.musea-variant {
|
|
2673
|
-
padding: 1.5rem;
|
|
2674
|
-
display: flex;
|
|
2675
|
-
align-items: center;
|
|
2676
|
-
justify-content: center;
|
|
2677
2879
|
min-height: 100vh;
|
|
2678
2880
|
}
|
|
2679
2881
|
.musea-error {
|
|
@@ -2747,13 +2949,7 @@ function generatePreviewHtml(art, variant, _basePath) {
|
|
|
2747
2949
|
Loading component...
|
|
2748
2950
|
</div>
|
|
2749
2951
|
</div>
|
|
2750
|
-
<script type="module">
|
|
2751
|
-
import(${importSpecifier}).catch(function(e) {
|
|
2752
|
-
console.error('[musea-preview] Failed to load module:', e);
|
|
2753
|
-
var c = document.getElementById('app');
|
|
2754
|
-
if (c) c.innerHTML = '<div class="musea-error"><div class="musea-error-title">Failed to load preview module</div><div>' + e.message + '</div></div>';
|
|
2755
|
-
});
|
|
2756
|
-
</script>
|
|
2952
|
+
<script type="module" src="${previewModuleUrl}"></script>
|
|
2757
2953
|
</body>
|
|
2758
2954
|
</html>`;
|
|
2759
2955
|
}
|