@vizejs/vite-plugin-musea 0.32.0 → 0.34.0

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 (63) hide show
  1. package/README.md +7 -7
  2. package/dist/a11y/index.d.mts +2 -0
  3. package/dist/a11y/index.mjs +2 -0
  4. package/dist/{a11y-7maCHrYD.js → a11y-DNCg2qCB.mjs} +16 -24
  5. package/dist/a11y-DNCg2qCB.mjs.map +1 -0
  6. package/dist/autogen/index.d.mts +66 -0
  7. package/dist/autogen/index.d.mts.map +1 -0
  8. package/dist/autogen/index.mjs +2 -0
  9. package/dist/{autogen-dfLosbY_.js → autogen-3-y1d0ou.mjs} +29 -21
  10. package/dist/autogen-3-y1d0ou.mjs.map +1 -0
  11. package/dist/cli/{index.d.ts → index.d.mts} +3 -24
  12. package/dist/cli/index.d.mts.map +1 -0
  13. package/dist/cli/{index.js → index.mjs} +62 -62
  14. package/dist/cli/index.mjs.map +1 -0
  15. package/dist/gallery/assets/{cssMode-B7TGecRV.js → cssMode-cT8muvO_.js} +1 -1
  16. package/dist/gallery/assets/{editor.api-BC1PBCLb.js → editor.api-aFfQJDkw.js} +1 -1
  17. package/dist/gallery/assets/{editor.main-DLQsz_NY.js → editor.main-DMqE48tW.js} +2 -2
  18. package/dist/gallery/assets/{freemarker2-D2ZPJ6qb.js → freemarker2-B6IBKB9r.js} +1 -1
  19. package/dist/gallery/assets/{handlebars-CcyadhwH.js → handlebars-zNX2LtzG.js} +1 -1
  20. package/dist/gallery/assets/{html-q3gp27Kd.js → html-BKYZbazO.js} +1 -1
  21. package/dist/gallery/assets/{htmlMode-T3iVYbeW.js → htmlMode-Bl1BwXnQ.js} +1 -1
  22. package/dist/gallery/assets/index-9OXG8DGI.css +1 -0
  23. package/dist/gallery/assets/{index-Cr99oWYP.js → index-Dltd3znx.js} +5 -5
  24. package/dist/gallery/assets/{javascript-S0QyTjKY.js → javascript-DwBI_Z0J.js} +1 -1
  25. package/dist/gallery/assets/{jsonMode-BIxPM6pZ.js → jsonMode-CBK55pb7.js} +1 -1
  26. package/dist/gallery/assets/{liquid-CNck0h86.js → liquid-D87ggETD.js} +1 -1
  27. package/dist/gallery/assets/{mdx-D6_ZVroO.js → mdx-CBs_aoHd.js} +1 -1
  28. package/dist/gallery/assets/{monaco.contribution-rExTCYiy.js → monaco.contribution-BHYQJQ-0.js} +2 -2
  29. package/dist/gallery/assets/{python-DSEg-0AY.js → python-CWI5d6bd.js} +1 -1
  30. package/dist/gallery/assets/{razor-kebzKtsv.js → razor-CPcSAg2x.js} +1 -1
  31. package/dist/gallery/assets/{tsMode-BZSsu7di.js → tsMode-1ZmI8w72.js} +1 -1
  32. package/dist/gallery/assets/{typescript-MSiFowAO.js → typescript-CVZCJg8D.js} +1 -1
  33. package/dist/gallery/assets/{xml-D6T21GmG.js → xml-B_rQCZJa.js} +1 -1
  34. package/dist/gallery/assets/{yaml-CVRjrT5r.js → yaml-gB0iHXGe.js} +1 -1
  35. package/dist/gallery/index.html +17 -14
  36. package/dist/index-BWuuTDDw.d.mts +151 -0
  37. package/dist/index-BWuuTDDw.d.mts.map +1 -0
  38. package/dist/{index.d.ts → index.d.mts} +6 -224
  39. package/dist/index.d.mts.map +1 -0
  40. package/dist/{index.js → index.mjs} +168 -178
  41. package/dist/index.mjs.map +1 -0
  42. package/dist/{vrt-D6OumJUH.d.ts → vrt-B4uxOrnN.d.mts} +6 -18
  43. package/dist/vrt-B4uxOrnN.d.mts.map +1 -0
  44. package/dist/{vrt-5_c9P1YY.js → vrt-CjFf5GR0.mjs} +39 -47
  45. package/dist/vrt-CjFf5GR0.mjs.map +1 -0
  46. package/dist/vrt.d.mts +2 -0
  47. package/dist/vrt.mjs +2 -0
  48. package/package.json +49 -49
  49. package/dist/a11y-7maCHrYD.js.map +0 -1
  50. package/dist/a11y-CjpWs0s0.js +0 -3
  51. package/dist/autogen-Dx-SIBf_.js +0 -3
  52. package/dist/autogen-dfLosbY_.js.map +0 -1
  53. package/dist/cli/index.d.ts.map +0 -1
  54. package/dist/cli/index.js.map +0 -1
  55. package/dist/gallery/assets/index-Cp7AWs0x.css +0 -1
  56. package/dist/index.css +0 -496
  57. package/dist/index.css.map +0 -1
  58. package/dist/index.d.ts.map +0 -1
  59. package/dist/index.js.map +0 -1
  60. package/dist/vrt-5_c9P1YY.js.map +0 -1
  61. package/dist/vrt-D6OumJUH.d.ts.map +0 -1
  62. package/dist/vrt.d.ts +0 -2
  63. package/dist/vrt.js +0 -3
package/README.md CHANGED
@@ -12,19 +12,19 @@ npm install @vizejs/vite-plugin-musea
12
12
 
13
13
  ```ts
14
14
  // vite.config.ts
15
- import { defineConfig } from 'vite'
16
- import { musea } from '@vizejs/vite-plugin-musea'
15
+ import { defineConfig } from "vite";
16
+ import { musea } from "@vizejs/vite-plugin-musea";
17
17
 
18
18
  export default defineConfig({
19
19
  plugins: [
20
20
  musea({
21
21
  // Art files pattern
22
- include: '**/*.art.vue',
22
+ include: "**/*.art.vue",
23
23
  // Output directory
24
- outDir: '.musea'
25
- })
26
- ]
27
- })
24
+ outDir: ".musea",
25
+ }),
26
+ ],
27
+ });
28
28
  ```
29
29
 
30
30
  ## Art File Format
@@ -0,0 +1,2 @@
1
+ import { a as generateA11yJsonReport, i as generateA11yHtmlReport, n as MuseaA11yRunner, r as computeA11ySummary, t as A11ySummary } from "../index-BWuuTDDw.mjs";
2
+ export { A11ySummary, MuseaA11yRunner, computeA11ySummary, generateA11yHtmlReport, generateA11yJsonReport };
@@ -0,0 +1,2 @@
1
+ import { i as generateA11yJsonReport, n as computeA11ySummary, r as generateA11yHtmlReport, t as MuseaA11yRunner } from "../a11y-DNCg2qCB.mjs";
2
+ export { MuseaA11yRunner, computeA11ySummary, generateA11yHtmlReport, generateA11yJsonReport };
@@ -1,5 +1,4 @@
1
1
  import path from "node:path";
2
-
3
2
  //#region src/a11y/report.ts
4
3
  /**
5
4
  * Compute a11y summary statistics from results.
@@ -21,7 +20,7 @@ function computeA11ySummary(results) {
21
20
  * Generate HTML report from a11y results.
22
21
  */
23
22
  function generateA11yHtmlReport(results, summary) {
24
- const timestamp = new Date().toLocaleString("ja-JP", {
23
+ const timestamp = (/* @__PURE__ */ new Date()).toLocaleString("ja-JP", {
25
24
  year: "numeric",
26
25
  month: "2-digit",
27
26
  day: "2-digit",
@@ -142,7 +141,7 @@ function generateA11yHtmlReport(results, summary) {
142
141
  function generateA11yJsonReport(results) {
143
142
  const summary = computeA11ySummary(results);
144
143
  return JSON.stringify({
145
- timestamp: new Date().toISOString(),
144
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
146
145
  summary,
147
146
  results: results.map((r) => ({
148
147
  art: path.basename(r.artPath, ".art.vue"),
@@ -156,7 +155,6 @@ function generateA11yJsonReport(results) {
156
155
  function escapeHtml(str) {
157
156
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
158
157
  }
159
-
160
158
  //#endregion
161
159
  //#region src/a11y/index.ts
162
160
  /**
@@ -193,8 +191,7 @@ var MuseaA11yRunner = class {
193
191
  page = context.page;
194
192
  } else {
195
193
  const { chromium } = await import("playwright");
196
- const browser = await chromium.launch({ headless: true });
197
- const ctx = await browser.newContext({ viewport: {
194
+ const ctx = await (await chromium.launch({ headless: true })).newContext({ viewport: {
198
195
  width: defaultViewport.width,
199
196
  height: defaultViewport.height
200
197
  } });
@@ -240,17 +237,16 @@ var MuseaA11yRunner = class {
240
237
  const axeResult = await page.evaluate((opts) => {
241
238
  return window.axe.run(document, opts);
242
239
  }, runOptions);
243
- const violations = axeResult.violations.map((v) => ({
244
- id: v.id,
245
- impact: v.impact,
246
- description: v.description,
247
- helpUrl: v.helpUrl,
248
- nodes: v.nodes.length
249
- }));
250
240
  return {
251
241
  artPath,
252
242
  variantName,
253
- violations,
243
+ violations: axeResult.violations.map((v) => ({
244
+ id: v.id,
245
+ impact: v.impact,
246
+ description: v.description,
247
+ helpUrl: v.helpUrl,
248
+ nodes: v.nodes.length
249
+ })),
254
250
  passes: axeResult.passes.length,
255
251
  incomplete: axeResult.incomplete.length
256
252
  };
@@ -265,8 +261,7 @@ var MuseaA11yRunner = class {
265
261
  * Generate HTML report.
266
262
  */
267
263
  generateHtmlReport(results) {
268
- const summary = this.getSummary(results);
269
- return generateA11yHtmlReport(results, summary);
264
+ return generateA11yHtmlReport(results, this.getSummary(results));
270
265
  }
271
266
  /**
272
267
  * Generate JSON report for CI integration.
@@ -279,8 +274,7 @@ var MuseaA11yRunner = class {
279
274
  */
280
275
  async getAxeSource() {
281
276
  try {
282
- const axeCore = await import("axe-core");
283
- return axeCore.source;
277
+ return (await import("axe-core")).source;
284
278
  } catch {
285
279
  throw new Error("axe-core is not installed. Install it as a peer dependency: npm install axe-core");
286
280
  }
@@ -315,12 +309,10 @@ var MuseaA11yRunner = class {
315
309
  };
316
310
  }
317
311
  buildVariantUrl(baseUrl, artPath, variantName) {
318
- const encodedPath = encodeURIComponent(artPath);
319
- const encodedVariant = encodeURIComponent(variantName);
320
- return `${baseUrl}/__musea__/preview?art=${encodedPath}&variant=${encodedVariant}`;
312
+ return `${baseUrl}/__musea__/preview?art=${encodeURIComponent(artPath)}&variant=${encodeURIComponent(variantName)}`;
321
313
  }
322
314
  };
323
-
324
315
  //#endregion
325
- export { MuseaA11yRunner, computeA11ySummary, generateA11yHtmlReport, generateA11yJsonReport };
326
- //# sourceMappingURL=a11y-7maCHrYD.js.map
316
+ export { generateA11yJsonReport as i, computeA11ySummary as n, generateA11yHtmlReport as r, MuseaA11yRunner as t };
317
+
318
+ //# sourceMappingURL=a11y-DNCg2qCB.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y-DNCg2qCB.mjs","names":[],"sources":["../src/a11y/report.ts","../src/a11y/index.ts"],"sourcesContent":["/**\n * A11y report generation for Musea.\n *\n * Generates HTML and JSON reports from accessibility audit results,\n * plus summary statistics computation.\n */\n\nimport type { A11yResult } from \"../types/index.js\";\nimport type { A11ySummary } from \"./index.js\";\nimport path from \"node:path\";\n\n/**\n * Compute a11y summary statistics from results.\n */\nexport function computeA11ySummary(results: A11yResult[]): A11ySummary {\n const components = new Set(results.map((r) => r.artPath));\n const allViolations = results.flatMap((r) => r.violations);\n\n return {\n totalComponents: components.size,\n totalVariants: results.length,\n totalViolations: allViolations.length,\n criticalCount: allViolations.filter((v) => v.impact === \"critical\").length,\n seriousCount: allViolations.filter((v) => v.impact === \"serious\").length,\n moderateCount: allViolations.filter((v) => v.impact === \"moderate\").length,\n minorCount: allViolations.filter((v) => v.impact === \"minor\").length,\n };\n}\n\n/**\n * Generate HTML report from a11y results.\n */\nexport function generateA11yHtmlReport(results: A11yResult[], summary: A11ySummary): string {\n const timestamp = new Date().toLocaleString(\"ja-JP\", {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n\n const impactColor = (impact: string): string => {\n switch (impact) {\n case \"critical\":\n return \"#f87171\";\n case \"serious\":\n return \"#fb923c\";\n case \"moderate\":\n return \"#fbbf24\";\n case \"minor\":\n return \"#60a5fa\";\n default:\n return \"#7b8494\";\n }\n };\n\n const resultItems = results\n .filter((r) => r.violations.length > 0)\n .map((r) => {\n const artName = path.basename(r.artPath, \".art.vue\");\n const violationRows = r.violations\n .map(\n (v) => `\n <tr>\n <td><span style=\"color:${impactColor(v.impact)};font-weight:600;text-transform:uppercase;font-size:0.6875rem\">${escapeHtml(v.impact)}</span></td>\n <td><code>${escapeHtml(v.id)}</code></td>\n <td>${escapeHtml(v.description)}</td>\n <td>${v.nodes}</td>\n <td>${v.helpUrl ? `<a href=\"${escapeHtml(v.helpUrl)}\" target=\"_blank\" style=\"color:#60a5fa\">docs</a>` : \"\"}</td>\n </tr>`,\n )\n .join(\"\");\n\n return `\n <div class=\"result\">\n <div class=\"result-header\">\n <div class=\"result-info\">\n <span class=\"result-name\">${escapeHtml(artName)} / ${escapeHtml(r.variantName)}</span>\n <span class=\"result-count\">${r.violations.length} violation(s)</span>\n </div>\n </div>\n <table class=\"violations-table\">\n <thead><tr><th>Impact</th><th>Rule</th><th>Description</th><th>Nodes</th><th>Help</th></tr></thead>\n <tbody>${violationRows}</tbody>\n </table>\n </div>`;\n })\n .join(\"\");\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>A11y Report - Musea</title>\n <style>\n :root {\n --musea-bg-primary: #0d0d0d;\n --musea-bg-secondary: #1a1815;\n --musea-bg-tertiary: #252220;\n --musea-accent: #a34828;\n --musea-text: #e6e9f0;\n --musea-text-muted: #7b8494;\n --musea-border: #3a3530;\n }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n background: var(--musea-bg-primary);\n color: var(--musea-text);\n min-height: 100vh;\n line-height: 1.5;\n }\n .header {\n background: var(--musea-bg-secondary);\n border-bottom: 1px solid var(--musea-border);\n padding: 1rem 2rem;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n .logo { font-size: 1.25rem; font-weight: 700; color: var(--musea-accent); }\n .header-meta { color: var(--musea-text-muted); font-size: 0.8125rem; }\n .main { max-width: 1200px; margin: 0 auto; padding: 2rem; }\n .summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 1rem; margin-bottom: 2rem; }\n .stat { background: var(--musea-bg-secondary); border: 1px solid var(--musea-border); border-radius: 8px; padding: 1rem; text-align: center; }\n .stat-value { font-size: 1.75rem; font-weight: 700; font-variant-numeric: tabular-nums; }\n .stat-label { color: var(--musea-text-muted); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; }\n .stat.critical .stat-value { color: #f87171; }\n .stat.serious .stat-value { color: #fb923c; }\n .stat.moderate .stat-value { color: #fbbf24; }\n .stat.minor .stat-value { color: #60a5fa; }\n .stat.total .stat-value { color: var(--musea-text); }\n .results { display: flex; flex-direction: column; gap: 1rem; }\n .result { background: var(--musea-bg-secondary); border: 1px solid var(--musea-border); border-radius: 8px; overflow: hidden; }\n .result-header { padding: 1rem; background: var(--musea-bg-tertiary); display: flex; justify-content: space-between; align-items: center; }\n .result-name { font-weight: 600; }\n .result-count { color: var(--musea-text-muted); font-size: 0.8125rem; }\n .violations-table { width: 100%; border-collapse: collapse; font-size: 0.8125rem; }\n .violations-table th { padding: 0.75rem 1rem; text-align: left; color: var(--musea-text-muted); font-weight: 500; font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.08em; border-bottom: 1px solid var(--musea-border); }\n .violations-table td { padding: 0.75rem 1rem; border-bottom: 1px solid var(--musea-border); }\n .violations-table code { background: var(--musea-bg-tertiary); padding: 0.125rem 0.375rem; border-radius: 3px; font-size: 0.75rem; }\n .all-clear { background: rgba(74, 222, 128, 0.1); border: 1px solid rgba(74, 222, 128, 0.2); border-radius: 8px; padding: 2rem; text-align: center; }\n .all-clear-text { color: #4ade80; font-weight: 600; }\n </style>\n</head>\n<body>\n <header class=\"header\">\n <div><span class=\"logo\">Musea</span> <span style=\"color:var(--musea-text-muted);font-size:0.875rem;margin-left:1rem\">Accessibility Report</span></div>\n <div class=\"header-meta\">${timestamp}</div>\n </header>\n <main class=\"main\">\n <div class=\"summary\">\n <div class=\"stat total\"><div class=\"stat-value\">${summary.totalViolations}</div><div class=\"stat-label\">Violations</div></div>\n <div class=\"stat critical\"><div class=\"stat-value\">${summary.criticalCount}</div><div class=\"stat-label\">Critical</div></div>\n <div class=\"stat serious\"><div class=\"stat-value\">${summary.seriousCount}</div><div class=\"stat-label\">Serious</div></div>\n <div class=\"stat moderate\"><div class=\"stat-value\">${summary.moderateCount}</div><div class=\"stat-label\">Moderate</div></div>\n <div class=\"stat minor\"><div class=\"stat-value\">${summary.minorCount}</div><div class=\"stat-label\">Minor</div></div>\n </div>\n ${\n summary.totalViolations === 0\n ? `<div class=\"all-clear\"><div class=\"all-clear-text\">No accessibility violations found across ${summary.totalVariants} variant(s)</div></div>`\n : `<div class=\"results\">${resultItems}</div>`\n }\n </main>\n</body>\n</html>`;\n}\n\n/**\n * Generate JSON report for CI integration.\n */\nexport function generateA11yJsonReport(results: A11yResult[]): string {\n const summary = computeA11ySummary(results);\n return JSON.stringify(\n {\n timestamp: new Date().toISOString(),\n summary,\n results: results.map((r) => ({\n art: path.basename(r.artPath, \".art.vue\"),\n variant: r.variantName,\n violations: r.violations,\n passes: r.passes,\n incomplete: r.incomplete,\n })),\n },\n null,\n 2,\n );\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#x27;\");\n}\n","/**\n * Accessibility (a11y) testing module for Musea.\n * Uses axe-core for automated accessibility auditing via Playwright.\n */\n\nimport type { Page } from \"playwright\";\nimport type {\n ArtFileInfo,\n A11yResult,\n A11yViolation,\n A11yOptions,\n ViewportConfig,\n} from \"../types/index.js\";\nimport type { MuseaVrtRunner } from \"../vrt.js\";\n\nimport { computeA11ySummary, generateA11yHtmlReport, generateA11yJsonReport } from \"./report.js\";\n\n// Re-export report functions so consumers importing from a11y.js still work\nexport { computeA11ySummary, generateA11yHtmlReport, generateA11yJsonReport } from \"./report.js\";\n\n/**\n * A11y audit summary.\n */\nexport interface A11ySummary {\n totalComponents: number;\n totalVariants: number;\n totalViolations: number;\n criticalCount: number;\n seriousCount: number;\n moderateCount: number;\n minorCount: number;\n}\n\n/**\n * axe-core result shape (subset).\n */\ninterface AxeResult {\n violations: Array<{\n id: string;\n impact: string;\n description: string;\n helpUrl: string;\n nodes: Array<unknown>;\n }>;\n passes: Array<unknown>;\n incomplete: Array<unknown>;\n}\n\n/**\n * A11y runner using axe-core via Playwright.\n */\nexport class MuseaA11yRunner {\n private options: Required<A11yOptions>;\n\n constructor(options: A11yOptions = {}) {\n this.options = {\n enabled: options.enabled ?? true,\n includeRules: options.includeRules ?? [],\n excludeRules: options.excludeRules ?? [],\n level: options.level ?? \"AA\",\n };\n }\n\n /**\n * Run a11y audits on all art file variants.\n * Reuses VRT runner's browser if available.\n */\n async runAudits(\n artFiles: ArtFileInfo[],\n baseUrl: string,\n vrtRunner?: MuseaVrtRunner,\n ): Promise<A11yResult[]> {\n const results: A11yResult[] = [];\n const defaultViewport: ViewportConfig = { width: 1280, height: 720, name: \"desktop\" };\n\n for (const art of artFiles) {\n for (const variant of art.variants) {\n if (variant.skipVrt) continue;\n\n let page: Page | null = null;\n let context: { page: Page; context: { close(): Promise<void> } } | null = null;\n\n try {\n if (vrtRunner) {\n context = await vrtRunner.createPage(defaultViewport);\n page = context.page;\n } else {\n // Standalone mode: launch own browser\n const { chromium } = await import(\"playwright\");\n const browser = await chromium.launch({ headless: true });\n const ctx = await browser.newContext({\n viewport: { width: defaultViewport.width, height: defaultViewport.height },\n });\n page = await ctx.newPage();\n context = { page, context: ctx };\n }\n\n const variantUrl = this.buildVariantUrl(baseUrl, art.path, variant.name);\n await page.goto(variantUrl, { waitUntil: \"networkidle\" });\n await page.waitForSelector(\".musea-variant\", { timeout: 10000 });\n await page.waitForTimeout(200);\n\n const result = await this.auditPage(page, art.path, variant.name);\n results.push(result);\n } catch (error) {\n results.push({\n artPath: art.path,\n variantName: variant.name,\n violations: [\n {\n id: \"audit-error\",\n impact: \"critical\",\n description: `Audit failed: ${error instanceof Error ? error.message : String(error)}`,\n helpUrl: \"\",\n nodes: 0,\n },\n ],\n passes: 0,\n incomplete: 0,\n });\n } finally {\n if (context) {\n await context.context.close();\n }\n }\n }\n }\n\n return results;\n }\n\n /**\n * Audit a single page using axe-core.\n */\n async auditPage(page: Page, artPath: string, variantName: string): Promise<A11yResult> {\n // Inject axe-core into the page\n const axeSource = await this.getAxeSource();\n await page.evaluate(axeSource);\n\n // Build axe-core run options\n const runOptions = this.buildAxeOptions();\n\n // Run axe-core\n const axeResult = (await page.evaluate((opts) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (window as any).axe.run(document, opts);\n }, runOptions)) as AxeResult;\n\n // Map to our result format\n const violations: A11yViolation[] = axeResult.violations.map((v) => ({\n id: v.id,\n impact: v.impact as A11yViolation[\"impact\"],\n description: v.description,\n helpUrl: v.helpUrl,\n nodes: v.nodes.length,\n }));\n\n return {\n artPath,\n variantName,\n violations,\n passes: axeResult.passes.length,\n incomplete: axeResult.incomplete.length,\n };\n }\n\n /**\n * Get summary statistics from results.\n */\n getSummary(results: A11yResult[]): A11ySummary {\n return computeA11ySummary(results);\n }\n\n /**\n * Generate HTML report.\n */\n generateHtmlReport(results: A11yResult[]): string {\n const summary = this.getSummary(results);\n return generateA11yHtmlReport(results, summary);\n }\n\n /**\n * Generate JSON report for CI integration.\n */\n generateJsonReport(results: A11yResult[]): string {\n return generateA11yJsonReport(results);\n }\n\n /**\n * Get axe-core source code for injection.\n */\n private async getAxeSource(): Promise<string> {\n try {\n const axeCore = await import(\"axe-core\");\n return axeCore.source;\n } catch {\n throw new Error(\n \"axe-core is not installed. Install it as a peer dependency: npm install axe-core\",\n );\n }\n }\n\n /**\n * Build axe-core run options from configuration.\n */\n private buildAxeOptions(): Record<string, unknown> {\n const runOnly: Record<string, unknown> = {};\n\n // Set WCAG level\n const tags: string[] = [];\n switch (this.options.level) {\n case \"A\":\n tags.push(\"wcag2a\", \"wcag21a\");\n break;\n case \"AA\":\n tags.push(\"wcag2a\", \"wcag2aa\", \"wcag21a\", \"wcag21aa\", \"wcag22aa\");\n break;\n case \"AAA\":\n tags.push(\"wcag2a\", \"wcag2aa\", \"wcag2aaa\", \"wcag21a\", \"wcag21aa\", \"wcag22aa\");\n break;\n }\n\n if (tags.length > 0) {\n runOnly.type = \"tag\";\n runOnly.values = tags;\n }\n\n const rules: Record<string, { enabled: boolean }> = {};\n\n for (const ruleId of this.options.includeRules) {\n rules[ruleId] = { enabled: true };\n }\n for (const ruleId of this.options.excludeRules) {\n rules[ruleId] = { enabled: false };\n }\n\n return {\n ...(Object.keys(runOnly).length > 0 ? { runOnly } : {}),\n ...(Object.keys(rules).length > 0 ? { rules } : {}),\n };\n }\n\n private buildVariantUrl(baseUrl: string, artPath: string, variantName: string): string {\n const encodedPath = encodeURIComponent(artPath);\n const encodedVariant = encodeURIComponent(variantName);\n return `${baseUrl}/__musea__/preview?art=${encodedPath}&variant=${encodedVariant}`;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ //#region src/autogen/index.d.ts
2
+ /**
3
+ * Variant auto-generation module.
4
+ * Generates .art.vue files from component prop analysis.
5
+ *
6
+ * JS-based fallback logic (extractPropsSimple, generateMinimalArt,
7
+ * generateArtFileJs, and helpers) is extracted into `fallback.ts`.
8
+ */
9
+ /**
10
+ * Autogen configuration options.
11
+ */
12
+ interface AutogenOptions {
13
+ /** Maximum number of variants to generate (default: 20) */
14
+ maxVariants?: number;
15
+ /** Include a "Default" variant with all default values (default: true) */
16
+ includeDefault?: boolean;
17
+ /** Include boolean toggle variants (default: true) */
18
+ includeBooleanToggles?: boolean;
19
+ /** Include enum/union variants (default: true) */
20
+ includeEnumVariants?: boolean;
21
+ /** Include boundary value variants for numbers (default: false) */
22
+ includeBoundaryValues?: boolean;
23
+ /** Include empty string variants for optional strings (default: false) */
24
+ includeEmptyStrings?: boolean;
25
+ }
26
+ /**
27
+ * Prop definition for variant generation.
28
+ */
29
+ interface PropDefinition {
30
+ name: string;
31
+ propType: string;
32
+ required: boolean;
33
+ defaultValue?: unknown;
34
+ }
35
+ /**
36
+ * Generated variant.
37
+ */
38
+ interface GeneratedVariant {
39
+ name: string;
40
+ isDefault: boolean;
41
+ props: Record<string, unknown>;
42
+ description?: string;
43
+ }
44
+ /**
45
+ * Autogen output.
46
+ */
47
+ interface AutogenOutput {
48
+ variants: GeneratedVariant[];
49
+ artFileContent: string;
50
+ componentName: string;
51
+ }
52
+ /**
53
+ * Generate .art.vue file for a component.
54
+ *
55
+ * @param componentPath - Path to the Vue component file
56
+ * @param options - Auto-generation options
57
+ * @returns Generated .art.vue content and metadata
58
+ */
59
+ declare function generateArtFile(componentPath: string, options?: AutogenOptions): Promise<AutogenOutput>;
60
+ /**
61
+ * Write generated .art.vue file to disk.
62
+ */
63
+ declare function writeArtFile(componentPath: string, options?: AutogenOptions, outputPath?: string): Promise<string>;
64
+ //#endregion
65
+ export { AutogenOptions, AutogenOutput, GeneratedVariant, PropDefinition, generateArtFile, writeArtFile };
66
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/autogen/index.ts"],"mappings":";;AAiBA;;;;;;;;;UAAiB,cAAA;EAYI;EAVnB,WAAA;EAgBe;EAdf,cAAA;;EAEA,qBAAA;EAaA;EAXA,mBAAA;EAaA;EAXA,qBAAA;EAYY;EAVZ,mBAAA;AAAA;;;;UAMe,cAAA;EACf,IAAA;EACA,QAAA;EACA,QAAA;EACA,YAAA;AAAA;;AAgBF;;UAViB,gBAAA;EACf,IAAA;EACA,SAAA;EACA,KAAA,EAAO,MAAA;EACP,WAAA;AAAA;;;AAuEF;UAjEiB,aAAA;EACf,QAAA,EAAU,gBAAA;EACV,cAAA;EACA,aAAA;AAAA;;;;;;;;iBA8DoB,eAAA,CACpB,aAAA,UACA,OAAA,GAAS,cAAA,GACR,OAAA,CAAQ,aAAA;;AAsEX;;iBAAsB,YAAA,CACpB,aAAA,UACA,OAAA,GAAS,cAAA,EACT,UAAA,YACC,OAAA"}
@@ -0,0 +1,2 @@
1
+ import { n as writeArtFile, t as generateArtFile } from "../autogen-3-y1d0ou.mjs";
2
+ export { generateArtFile, writeArtFile };
@@ -1,17 +1,22 @@
1
+ import { createRequire } from "node:module";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
- import { createRequire } from "node:module";
4
-
5
4
  //#region src/autogen/fallback.ts
6
5
  /**
6
+ * JS-based fallback for variant auto-generation.
7
+ *
8
+ * Used when the native Rust binding is not available. Provides simple
9
+ * regex-based prop extraction, minimal art file generation, and a pure
10
+ * JS variant generator.
11
+ */
12
+ /**
7
13
  * Simple prop extraction fallback (when native binding not available).
8
14
  */
9
15
  function extractPropsSimple(source) {
10
16
  const props = [];
11
17
  const propsMatch = source.match(/defineProps\s*<\s*\{([^}]*)\}\s*>/s);
12
18
  if (propsMatch) {
13
- const propsBlock = propsMatch[1];
14
- const propLines = propsBlock.split("\n");
19
+ const propLines = propsMatch[1].split("\n");
15
20
  for (const line of propLines) {
16
21
  const propMatch = line.trim().match(/^(\w+)(\?)?:\s*(.+?)\s*;?\s*$/);
17
22
  if (propMatch) props.push({
@@ -35,7 +40,7 @@ function generateMinimalArt(componentName, componentPath) {
35
40
 
36
41
  <script setup lang="ts">
37
42
  import ${componentName} from '${componentPath}'
38
- </script>
43
+ <\/script>
39
44
  `;
40
45
  }
41
46
  /**
@@ -94,7 +99,7 @@ function generateArtFileJs(componentPath, props, options) {
94
99
  content += ` <${componentName}${propsStr ? " " + propsStr : ""} />\n`;
95
100
  content += ` </variant>\n\n`;
96
101
  }
97
- content += `</art>\n\n<script setup lang="ts">\nimport ${componentName} from '${relPath}'\n</script>\n`;
102
+ content += `</art>\n\n<script setup lang="ts">\nimport ${componentName} from '${relPath}'\n<\/script>\n`;
98
103
  return {
99
104
  variants,
100
105
  artFileContent: content,
@@ -112,9 +117,15 @@ function parseUnionType(typeStr) {
112
117
  function toPascalCase(str) {
113
118
  return str.split(/[\s\-_]+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
114
119
  }
115
-
116
120
  //#endregion
117
121
  //#region src/autogen/index.ts
122
+ /**
123
+ * Variant auto-generation module.
124
+ * Generates .art.vue files from component prop analysis.
125
+ *
126
+ * JS-based fallback logic (extractPropsSimple, generateMinimalArt,
127
+ * generateArtFileJs, and helpers) is extracted into `fallback.ts`.
128
+ */
118
129
  let native = null;
119
130
  function loadNative() {
120
131
  if (native) return native;
@@ -138,25 +149,22 @@ async function generateArtFile(componentPath, options = {}) {
138
149
  const source = await fs.promises.readFile(absolutePath, "utf-8");
139
150
  const binding = loadNative();
140
151
  let props;
141
- if (binding.analyzeSfc) {
142
- const analysis = binding.analyzeSfc(source, { filename: absolutePath });
143
- props = analysis.props.map((p) => ({
144
- name: p.name,
145
- propType: p.type,
146
- required: p.required,
147
- defaultValue: p.default_value
148
- }));
149
- } else props = extractPropsSimple(source);
152
+ if (binding.analyzeSfc) props = binding.analyzeSfc(source, { filename: absolutePath }).props.map((p) => ({
153
+ name: p.name,
154
+ propType: p.type,
155
+ required: p.required,
156
+ defaultValue: p.default_value
157
+ }));
158
+ else props = extractPropsSimple(source);
150
159
  if (props.length === 0) {
151
160
  const componentName = path.basename(componentPath, ".vue");
152
- const relPath = `./${path.basename(componentPath)}`;
153
161
  return {
154
162
  variants: [{
155
163
  name: "Default",
156
164
  isDefault: true,
157
165
  props: {}
158
166
  }],
159
- artFileContent: generateMinimalArt(componentName, relPath),
167
+ artFileContent: generateMinimalArt(componentName, `./${path.basename(componentPath)}`),
160
168
  componentName
161
169
  };
162
170
  }
@@ -199,7 +207,7 @@ async function writeArtFile(componentPath, options = {}, outputPath) {
199
207
  await fs.promises.writeFile(targetPath, output.artFileContent, "utf-8");
200
208
  return targetPath;
201
209
  }
202
-
203
210
  //#endregion
204
- export { generateArtFile, writeArtFile };
205
- //# sourceMappingURL=autogen-dfLosbY_.js.map
211
+ export { writeArtFile as n, generateArtFile as t };
212
+
213
+ //# sourceMappingURL=autogen-3-y1d0ou.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autogen-3-y1d0ou.mjs","names":[],"sources":["../src/autogen/fallback.ts","../src/autogen/index.ts"],"sourcesContent":["/**\n * JS-based fallback for variant auto-generation.\n *\n * Used when the native Rust binding is not available. Provides simple\n * regex-based prop extraction, minimal art file generation, and a pure\n * JS variant generator.\n */\n\nimport path from \"node:path\";\n\nimport type { AutogenOptions, AutogenOutput, GeneratedVariant, PropDefinition } from \"./index.js\";\n\n/**\n * Simple prop extraction fallback (when native binding not available).\n */\nexport function extractPropsSimple(source: string): PropDefinition[] {\n const props: PropDefinition[] = [];\n\n // Match defineProps<{ ... }>() or defineProps({ ... })\n const propsMatch = source.match(/defineProps\\s*<\\s*\\{([^}]*)\\}\\s*>/s);\n\n if (propsMatch) {\n const propsBlock = propsMatch[1];\n const propLines = propsBlock.split(\"\\n\");\n\n for (const line of propLines) {\n const propMatch = line.trim().match(/^(\\w+)(\\?)?:\\s*(.+?)\\s*;?\\s*$/);\n if (propMatch) {\n props.push({\n name: propMatch[1],\n propType: propMatch[3].replace(/,\\s*$/, \"\"),\n required: !propMatch[2],\n });\n }\n }\n }\n\n return props;\n}\n\n/**\n * Minimal art file for components with no props.\n */\nexport function generateMinimalArt(componentName: string, componentPath: string): string {\n return `<art title=\"${componentName}\" component=\"${componentPath}\">\n <variant name=\"Default\" default>\n <${componentName} />\n </variant>\n</art>\n\n<script setup lang=\"ts\">\nimport ${componentName} from '${componentPath}'\n</script>\n`;\n}\n\n/**\n * JS-based variant generation fallback.\n */\nexport function generateArtFileJs(\n componentPath: string,\n props: PropDefinition[],\n options: AutogenOptions,\n): AutogenOutput {\n const componentName = path.basename(componentPath, \".vue\");\n const relPath = `./${path.basename(componentPath)}`;\n const maxVariants = options.maxVariants ?? 20;\n const variants: GeneratedVariant[] = [];\n\n // Default variant\n if (options.includeDefault !== false) {\n const defaultProps: Record<string, unknown> = {};\n for (const prop of props) {\n if (prop.defaultValue !== undefined) {\n defaultProps[prop.name] = prop.defaultValue;\n }\n }\n variants.push({\n name: \"Default\",\n isDefault: true,\n props: defaultProps,\n description: `${componentName} with default props`,\n });\n }\n\n // Enum variants\n if (options.includeEnumVariants !== false) {\n for (const prop of props) {\n const unionValues = parseUnionType(prop.propType);\n for (const val of unionValues) {\n if (variants.length >= maxVariants) break;\n const name =\n typeof val === \"string\" ? toPascalCase(val) : `${toPascalCase(prop.name)}_${String(val)}`;\n variants.push({\n name,\n isDefault: false,\n props: { [prop.name]: val },\n description: `${prop.name} = ${JSON.stringify(val)}`,\n });\n }\n }\n }\n\n // Boolean toggle variants\n if (options.includeBooleanToggles !== false) {\n for (const prop of props) {\n if (variants.length >= maxVariants) break;\n if (prop.propType.toLowerCase() === \"boolean\") {\n const nonDefault = prop.defaultValue === true ? false : true;\n variants.push({\n name: nonDefault ? toPascalCase(prop.name) : `No${toPascalCase(prop.name)}`,\n isDefault: false,\n props: { [prop.name]: nonDefault },\n description: `${prop.name} = ${nonDefault}`,\n });\n }\n }\n }\n\n // Generate art file content\n let content = `<art title=\"${componentName}\" component=\"${relPath}\">\\n`;\n for (const variant of variants) {\n const attrs = variant.isDefault ? `name=\"${variant.name}\" default` : `name=\"${variant.name}\"`;\n content += ` <variant ${attrs}>\\n`;\n\n const propsStr = Object.entries(variant.props)\n .map(([k, v]) => {\n if (typeof v === \"string\") return `${k}=\"${v}\"`;\n if (typeof v === \"boolean\" && v) return k;\n if (typeof v === \"boolean\" && !v) return `:${k}=\"false\"`;\n return `:${k}=\"${JSON.stringify(v)}\"`;\n })\n .join(\" \");\n\n content += ` <${componentName}${propsStr ? \" \" + propsStr : \"\"} />\\n`;\n content += ` </variant>\\n\\n`;\n }\n content += `</art>\\n\\n<script setup lang=\"ts\">\\nimport ${componentName} from '${relPath}'\\n</script>\\n`;\n\n return {\n variants,\n artFileContent: content,\n componentName,\n };\n}\n\nexport function parseUnionType(typeStr: string): unknown[] {\n const trimmed = typeStr.trim();\n if (!trimmed.includes(\"|\")) return [];\n\n if (trimmed.includes(\"'\") || trimmed.includes('\"')) {\n return trimmed\n .split(\"|\")\n .map((s) => s.trim().replace(/^['\"]|['\"]$/g, \"\"))\n .filter((s) => s.length > 0);\n }\n\n const parts = trimmed.split(\"|\").map((s) => s.trim());\n if (parts.every((p) => !isNaN(Number(p)))) {\n return parts.map(Number);\n }\n\n return [];\n}\n\nexport function toPascalCase(str: string): string {\n return str\n .split(/[\\s\\-_]+/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\"\");\n}\n","/**\n * Variant auto-generation module.\n * Generates .art.vue files from component prop analysis.\n *\n * JS-based fallback logic (extractPropsSimple, generateMinimalArt,\n * generateArtFileJs, and helpers) is extracted into `fallback.ts`.\n */\n\nimport { createRequire } from \"node:module\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { extractPropsSimple, generateMinimalArt, generateArtFileJs } from \"./fallback.js\";\n\n/**\n * Autogen configuration options.\n */\nexport interface AutogenOptions {\n /** Maximum number of variants to generate (default: 20) */\n maxVariants?: number;\n /** Include a \"Default\" variant with all default values (default: true) */\n includeDefault?: boolean;\n /** Include boolean toggle variants (default: true) */\n includeBooleanToggles?: boolean;\n /** Include enum/union variants (default: true) */\n includeEnumVariants?: boolean;\n /** Include boundary value variants for numbers (default: false) */\n includeBoundaryValues?: boolean;\n /** Include empty string variants for optional strings (default: false) */\n includeEmptyStrings?: boolean;\n}\n\n/**\n * Prop definition for variant generation.\n */\nexport interface PropDefinition {\n name: string;\n propType: string;\n required: boolean;\n defaultValue?: unknown;\n}\n\n/**\n * Generated variant.\n */\nexport interface GeneratedVariant {\n name: string;\n isDefault: boolean;\n props: Record<string, unknown>;\n description?: string;\n}\n\n/**\n * Autogen output.\n */\nexport interface AutogenOutput {\n variants: GeneratedVariant[];\n artFileContent: string;\n componentName: string;\n}\n\n// Native binding types\ninterface NativeAutogen {\n generateVariants?: (\n componentPath: string,\n props: Array<{\n name: string;\n prop_type: string;\n required: boolean;\n default_value?: unknown;\n }>,\n config?: {\n max_variants?: number;\n include_default?: boolean;\n include_boolean_toggles?: boolean;\n include_enum_variants?: boolean;\n include_boundary_values?: boolean;\n include_empty_strings?: boolean;\n },\n ) => {\n variants: Array<{\n name: string;\n is_default: boolean;\n props: Record<string, unknown>;\n description?: string;\n }>;\n art_file_content: string;\n component_name: string;\n };\n analyzeSfc?: (\n source: string,\n options?: { filename?: string },\n ) => {\n props: Array<{ name: string; type: string; required: boolean; default_value?: unknown }>;\n emits: string[];\n };\n}\n\nlet native: NativeAutogen | null = null;\n\nfunction loadNative(): NativeAutogen {\n if (native) return native;\n const require = createRequire(import.meta.url);\n try {\n native = require(\"@vizejs/native\") as NativeAutogen;\n return native;\n } catch (e) {\n throw new Error(\n `Failed to load @vizejs/native. Make sure it's installed and built:\\n${String(e)}`,\n );\n }\n}\n\n/**\n * Generate .art.vue file for a component.\n *\n * @param componentPath - Path to the Vue component file\n * @param options - Auto-generation options\n * @returns Generated .art.vue content and metadata\n */\nexport async function generateArtFile(\n componentPath: string,\n options: AutogenOptions = {},\n): Promise<AutogenOutput> {\n const absolutePath = path.resolve(componentPath);\n const source = await fs.promises.readFile(absolutePath, \"utf-8\");\n\n const binding = loadNative();\n\n // Analyze component to extract props\n let props: PropDefinition[];\n if (binding.analyzeSfc) {\n const analysis = binding.analyzeSfc(source, { filename: absolutePath });\n props = analysis.props.map((p) => ({\n name: p.name,\n propType: p.type,\n required: p.required,\n defaultValue: p.default_value,\n }));\n } else {\n // Fallback: simple regex-based prop extraction\n props = extractPropsSimple(source);\n }\n\n if (props.length === 0) {\n // No props found: generate minimal art file\n const componentName = path.basename(componentPath, \".vue\");\n const relPath = `./${path.basename(componentPath)}`;\n return {\n variants: [{ name: \"Default\", isDefault: true, props: {} }],\n artFileContent: generateMinimalArt(componentName, relPath),\n componentName,\n };\n }\n\n // Use native variant generation if available\n if (binding.generateVariants) {\n const nativeProps = props.map((p) => ({\n name: p.name,\n prop_type: p.propType,\n required: p.required,\n default_value: p.defaultValue,\n }));\n\n const relPath = `./${path.basename(componentPath)}`;\n const result = binding.generateVariants(relPath, nativeProps, {\n max_variants: options.maxVariants,\n include_default: options.includeDefault,\n include_boolean_toggles: options.includeBooleanToggles,\n include_enum_variants: options.includeEnumVariants,\n include_boundary_values: options.includeBoundaryValues,\n include_empty_strings: options.includeEmptyStrings,\n });\n\n return {\n variants: result.variants.map((v) => ({\n name: v.name,\n isDefault: v.is_default,\n props: v.props,\n description: v.description,\n })),\n artFileContent: result.art_file_content,\n componentName: result.component_name,\n };\n }\n\n // Fallback: JS-based generation\n return generateArtFileJs(componentPath, props, options);\n}\n\n/**\n * Write generated .art.vue file to disk.\n */\nexport async function writeArtFile(\n componentPath: string,\n options: AutogenOptions = {},\n outputPath?: string,\n): Promise<string> {\n const output = await generateArtFile(componentPath, options);\n\n const targetPath = outputPath ?? componentPath.replace(/\\.vue$/, \".art.vue\");\n\n await fs.promises.mkdir(path.dirname(targetPath), { recursive: true });\n await fs.promises.writeFile(targetPath, output.artFileContent, \"utf-8\");\n\n return targetPath;\n}\n"],"mappings":"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"}
@@ -1,26 +1,4 @@
1
- #!/usr/bin/env node
2
1
  //#region src/cli/index.d.ts
3
- /**
4
- * Musea CLI
5
- *
6
- * Usage:
7
- * musea-vrt [command] [options]
8
- *
9
- * Commands:
10
- * (default) Run VRT tests
11
- * approve [pat] Approve failed snapshots (optionally filtered by pattern)
12
- * clean Remove orphaned snapshots
13
- *
14
- * Options:
15
- * -u, --update Update baseline snapshots
16
- * -c, --config Path to vite config (default: vite.config.ts)
17
- * -o, --output Output directory for reports (default: .vize)
18
- * -t, --threshold Diff threshold percentage (default: 0.1)
19
- * --json Output JSON report instead of HTML
20
- * --ci CI mode - exit with non-zero code on failures
21
- * --a11y Run accessibility audits alongside VRT
22
- * -h, --help Show help
23
- */
24
2
  /**
25
3
  * Musea CLI
26
4
  *
@@ -56,6 +34,7 @@ interface CliOptions {
56
34
  baseUrl: string;
57
35
  pattern?: string;
58
36
  componentPath?: string;
59
- } //#endregion
37
+ }
38
+ //#endregion
60
39
  export { CliOptions };
61
- //# sourceMappingURL=index.d.ts.map
40
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cli/index.ts"],"mappings":";;;;;;AA6BA;;;;;;;;;;;;;;;;KAFK,OAAA;AAAA,UAEY,UAAA;EACf,OAAA,EAAS,OAAA;EACT,MAAA;EACA,MAAA;EACA,MAAA;EACA,SAAA;EACA,IAAA;EACA,EAAA;EACA,IAAA;EACA,IAAA;EACA,OAAA;EACA,OAAA;EACA,aAAA;AAAA"}