xmlui 0.12.7 → 0.12.10

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 (37) hide show
  1. package/dist/bin/index.cjs +159 -20
  2. package/dist/bin/index.js +160 -20
  3. package/dist/for-node/server.cjs +13 -0
  4. package/dist/for-node/server.js +13 -0
  5. package/dist/for-node/vite-xmlui-plugin.cjs +18 -9
  6. package/dist/for-node/vite-xmlui-plugin.js +18 -9
  7. package/dist/lib/{index-BcKxSpA3.js → index-BWw39YM0.js} +4777 -3697
  8. package/dist/lib/index.css +2 -2
  9. package/dist/lib/{initMock-cRIup3Sb.js → initMock-lQC6q8bk.js} +2 -2
  10. package/dist/lib/{parser-SxInW5FF.js → parser-CYOUj4Ep.js} +30 -15
  11. package/dist/lib/scss/components-core/theming/_themes.scss +14 -0
  12. package/dist/lib/scss/index.scss +2 -1
  13. package/dist/lib/testing.d.ts +0 -8
  14. package/dist/lib/testing.js +2 -21
  15. package/dist/lib/{xmlui-parser-B4dCFLUY.js → xmlui-parser-CbfXITG_.js} +1 -1
  16. package/dist/lib/xmlui-parser.d.ts +8 -1
  17. package/dist/lib/xmlui-parser.js +2 -2
  18. package/dist/lib/{xmlui-serializer-DqzZyjXw.js → xmlui-serializer-DdE6E99O.js} +102 -73
  19. package/dist/lib/xmlui.d.ts +22 -10
  20. package/dist/lib/xmlui.js +24 -25
  21. package/dist/metadata/{TextBox-DZuZK3AL.js → TextBox-CTl_l46B.js} +5448 -4425
  22. package/dist/metadata/TextBox-DPwSmadf.cjs +1 -0
  23. package/dist/metadata/behaviors.cjs +1 -1
  24. package/dist/metadata/behaviors.js +1 -1
  25. package/dist/metadata/{initMock-DoJrNR2N.cjs → initMock-BwhjWmHJ.cjs} +1 -1
  26. package/dist/metadata/{initMock-BbVqGQI7.js → initMock-CsnHImOv.js} +1 -1
  27. package/dist/metadata/metadata-utils.cjs +1 -1
  28. package/dist/metadata/metadata-utils.js +1 -1
  29. package/dist/metadata/{transform-RxMduR7r.cjs → transform-BNkTh88a.cjs} +1 -1
  30. package/dist/metadata/{transform-C2uIjxX9.js → transform-DcrD_B3c.js} +43 -15
  31. package/dist/metadata/xmlui-metadata.cjs +1 -1
  32. package/dist/metadata/xmlui-metadata.js +12 -5
  33. package/dist/metadata/xmlui.css +2 -2
  34. package/dist/standalone/xmlui-standalone.es.d.ts +23 -14
  35. package/dist/standalone/xmlui-standalone.umd.js +38 -37
  36. package/package.json +3 -3
  37. package/dist/metadata/TextBox-_u8ZSzmG.cjs +0 -1
@@ -8467,11 +8467,19 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8467
8467
  reportError(DIAGS_TRANSFORM.globalNotAllowedInNested);
8468
8468
  return;
8469
8469
  }
8470
- collectElementHelper(usesStack$1, comp, child, (name$49) => isComponent(comp) ? comp.globalVars?.[name$49] : void 0, (name$49, value$2) => {
8471
- if (!isComponent(comp)) return;
8472
- comp.globalVars ??= {};
8473
- comp.globalVars[name$49] = value$2;
8474
- });
8470
+ {
8471
+ const attrs = getAttributes(child).map(segmentAttr);
8472
+ const storageKey = attrs.find((a$4) => a$4.name === "storageKey")?.value;
8473
+ const persistAttr = attrs.find((a$4) => a$4.name === "persist")?.value;
8474
+ const shouldPersist = persistAttr === "true" || persistAttr === "{true}" || persistAttr === "1";
8475
+ collectElementHelper(usesStack$1, comp, child, (name$49) => isComponent(comp) ? comp.globalVars?.[name$49] : void 0, (name$49, value$2) => {
8476
+ if (!isComponent(comp)) return;
8477
+ comp.globalVars ??= {};
8478
+ comp.globalVars[name$49] = value$2;
8479
+ const effectiveStorageKey = storageKey ?? (shouldPersist ? name$49 : void 0);
8480
+ if (effectiveStorageKey) comp.globalVars[`__storageKey_${name$49}`] = effectiveStorageKey;
8481
+ }, void 0, ["storageKey", "persist"]);
8482
+ }
8475
8483
  return;
8476
8484
  case "loaders":
8477
8485
  collectLoadersElements(usesStack$1, comp, child);
@@ -8594,14 +8602,15 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8594
8602
  });
8595
8603
  return result;
8596
8604
  }
8597
- function collectValue(usesStack$1, element, allowName = true) {
8605
+ function collectValue(usesStack$1, element, allowName = true, extraAllowedAttrs = []) {
8598
8606
  const elementName = getComponentName(element, getText);
8599
8607
  const childNodes = getChildNodes(element);
8600
8608
  const nestedComponents = childNodes.filter((c$4) => c$4.kind === SyntaxKind.ElementNode && UCRegex.test(getComponentName(c$4, getText)));
8601
8609
  const nestedHelpers = childNodes.filter((c$4) => c$4.kind === SyntaxKind.ElementNode && !UCRegex.test(getComponentName(c$4, getText)));
8602
8610
  const attrNodes = getAttributes(element);
8603
8611
  const attrsSegmented = attrNodes.map(segmentAttr);
8604
- const attrProps = attrsSegmented.filter((attr) => propAttrs.indexOf(attr.name) >= 0);
8612
+ const allAllowedAttrs = extraAllowedAttrs.length > 0 ? [...propAttrs, ...extraAllowedAttrs] : propAttrs;
8613
+ const attrProps = attrsSegmented.filter((attr) => allAllowedAttrs.indexOf(attr.name) >= 0);
8605
8614
  if (attrsSegmented.length > attrProps.length) {
8606
8615
  reportError(DIAGS_TRANSFORM.onlyNameValueAttrs(elementName));
8607
8616
  return null;
@@ -8685,8 +8694,8 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8685
8694
  comp.loaders.push(loaderDef);
8686
8695
  });
8687
8696
  }
8688
- function collectElementHelper(usesStack$1, comp, child, getter, setter, nameValidator) {
8689
- const valueInfo = collectValue(usesStack$1, child);
8697
+ function collectElementHelper(usesStack$1, comp, child, getter, setter, nameValidator, extraAllowedAttrs = []) {
8698
+ const valueInfo = collectValue(usesStack$1, child, true, extraAllowedAttrs);
8690
8699
  if (!valueInfo) return;
8691
8700
  nameValidator?.(valueInfo?.name ?? "");
8692
8701
  const name$49 = valueInfo.name;
@@ -236874,6 +236883,7 @@ const SEARCH_CATEGORIES = [
236874
236883
  ];
236875
236884
  const SEARCH_DEFAULT_CATEGORY = "other";
236876
236885
  const SEARCH_INDEX_FILE_NAME = "__xmlui-search-index.json";
236886
+ const SEARCH_INDEX_STUB_JSON = "[]";
236877
236887
  const SSG_WRITE_CONCURRENCY = 16;
236878
236888
  const EXTENSION_FILE_CANDIDATES = [
236879
236889
  "extensions.ts",
@@ -236890,6 +236900,13 @@ function getOutputHtmlPath(outDir, routePath) {
236890
236900
  if (routePath === "/") return node_path.default.join(outDir, "index.html");
236891
236901
  return node_path.default.join(outDir, routePath.slice(1), "index.html");
236892
236902
  }
236903
+ function isHtmlNavigationRequest(url$2, acceptHeader) {
236904
+ if (!acceptHeader?.includes("text/html")) return false;
236905
+ const pathname = new URL(url$2, "http://localhost").pathname;
236906
+ if (pathname === `/${SEARCH_INDEX_FILE_NAME}`) return false;
236907
+ if (pathname.startsWith("/@") || pathname.startsWith("/__vite") || pathname.startsWith("/__id")) return false;
236908
+ return !node_path.default.basename(pathname).includes(".");
236909
+ }
236893
236910
  function executeInlineScripts(html) {
236894
236911
  new import_api.JSDOM(html, { runScripts: "outside-only" }).window.document.querySelectorAll("script:not([src])").forEach((script) => {
236895
236912
  const content = (script.textContent || "").trim();
@@ -237097,7 +237114,134 @@ async function getWorkspaceExtensionAliases(cwd) {
237097
237114
  }
237098
237115
  return aliases;
237099
237116
  }
237117
+ function mergeAliases(existingAlias, extensionAliases) {
237118
+ if (Array.isArray(existingAlias)) return [...existingAlias, ...Object.entries(extensionAliases).map(([find$1, replacement]) => ({
237119
+ find: find$1,
237120
+ replacement
237121
+ }))];
237122
+ if (existingAlias && typeof existingAlias === "object") return {
237123
+ ...existingAlias,
237124
+ ...extensionAliases
237125
+ };
237126
+ return { ...extensionAliases };
237127
+ }
237128
+ function prioritizeTypeScriptExtensions(extensions) {
237129
+ if (!extensions) return;
237130
+ const priority = new Map([
237131
+ [".ts", 0],
237132
+ [".tsx", 1],
237133
+ [".jsx", 2],
237134
+ [".js", 3]
237135
+ ]);
237136
+ return [...extensions].sort((left, right) => {
237137
+ return (priority.get(left) ?? 100) - (priority.get(right) ?? 100);
237138
+ });
237139
+ }
237140
+ async function runDebugSsgServer() {
237141
+ const cwd = process.cwd();
237142
+ const sourceIndexPath = node_path.default.resolve(cwd, "index.html");
237143
+ const tempEntryPath = node_path.default.resolve(cwd, TEMP_ENTRY_FILE_NAME);
237144
+ log(`starting debug server in ${cwd}`);
237145
+ executeInlineScripts(await (0, node_fs_promises.readFile)(sourceIndexPath, "utf-8"));
237146
+ const extensionImportSpecifiers = await getExtensionImportSpecifiers(cwd);
237147
+ if (extensionImportSpecifiers.length > 0) log(`detected extensions: ${extensionImportSpecifiers.join(", ")}`);
237148
+ log("creating SSR module");
237149
+ await (0, node_fs_promises.writeFile)(tempEntryPath, getSsgEntrySource(extensionImportSpecifiers), "utf-8");
237150
+ process.once("exit", () => {
237151
+ try {
237152
+ (0, node_fs.rmSync)(tempEntryPath, { force: true });
237153
+ } catch {}
237154
+ });
237155
+ const viteConfig = await getViteConfig({});
237156
+ const extensionAliases = await getWorkspaceExtensionAliases(cwd);
237157
+ if (Object.keys(extensionAliases).length > 0) log(`using workspace extension aliases: ${Object.keys(extensionAliases).join(", ")}`);
237158
+ const mergedAlias = mergeAliases(viteConfig.resolve?.alias, extensionAliases);
237159
+ const basePlugins = Array.isArray(viteConfig.plugins) ? viteConfig.plugins : viteConfig.plugins ? [viteConfig.plugins] : [];
237160
+ const ssgDebugPlugin = {
237161
+ name: "xmlui-ssg-debug",
237162
+ configureServer(server$1) {
237163
+ server$1.middlewares.use(async (req$1, res, next) => {
237164
+ const requestUrl = req$1.originalUrl || req$1.url || "/";
237165
+ if (new URL(requestUrl, "http://localhost").pathname === `/${SEARCH_INDEX_FILE_NAME}`) {
237166
+ res.statusCode = 200;
237167
+ res.setHeader("Content-Type", "application/json");
237168
+ res.end(SEARCH_INDEX_STUB_JSON);
237169
+ return;
237170
+ }
237171
+ if (!isHtmlNavigationRequest(requestUrl, req$1.headers.accept)) {
237172
+ next();
237173
+ return;
237174
+ }
237175
+ try {
237176
+ const shellHtml = await (0, node_fs_promises.readFile)(sourceIndexPath, "utf-8");
237177
+ const transformedShell = await server$1.transformIndexHtml(requestUrl, shellHtml, req$1.originalUrl);
237178
+ const renderModule = await server$1.ssrLoadModule(`${(0, node_url.pathToFileURL)(tempEntryPath).href}?t=${Date.now()}`);
237179
+ if (!renderModule?.renderPath) throw new Error("failed to load renderPath from temporary SSG entry module");
237180
+ const finalHtml = applyRenderToShell(transformedShell, renderModule.renderPath(requestUrl));
237181
+ res.statusCode = 200;
237182
+ res.setHeader("Content-Type", "text/html");
237183
+ res.end(finalHtml);
237184
+ } catch (error$2) {
237185
+ const err$1 = error$2;
237186
+ server$1.ssrFixStacktrace(err$1);
237187
+ res.statusCode = 500;
237188
+ res.setHeader("Content-Type", "text/plain");
237189
+ res.end(err$1.stack || err$1.message || String(err$1));
237190
+ }
237191
+ });
237192
+ }
237193
+ };
237194
+ const server = await (0, vite.createServer)({
237195
+ ...viteConfig,
237196
+ resolve: {
237197
+ ...viteConfig.resolve,
237198
+ alias: mergedAlias,
237199
+ extensions: prioritizeTypeScriptExtensions(viteConfig.resolve?.extensions)
237200
+ },
237201
+ define: {
237202
+ ...viteConfig.define,
237203
+ "process.env.VITE_BUILD_MODE": "\"ALL\"",
237204
+ "process.env.VITE_DEV_MODE": true,
237205
+ "process.env.VITE_STANDALONE": process.env.VITE_STANDALONE,
237206
+ "process.env.VITE_MOCK_ENABLED": true,
237207
+ "process.env.VITE_INCLUDE_ALL_COMPONENTS": "\"true\"",
237208
+ "process.env.VITE_USER_COMPONENTS_Inspect": "\"true\""
237209
+ },
237210
+ plugins: [...basePlugins, ssgDebugPlugin]
237211
+ });
237212
+ if (!server.httpServer) throw new Error("HTTP server not available");
237213
+ let cleanedUp = false;
237214
+ const cleanup = async () => {
237215
+ if (cleanedUp) return;
237216
+ cleanedUp = true;
237217
+ await (0, node_fs_promises.rm)(tempEntryPath, { force: true });
237218
+ };
237219
+ const shutdown = async (signal) => {
237220
+ log(`received ${signal}, shutting down debug server`);
237221
+ await server.close();
237222
+ await cleanup();
237223
+ process.exit(0);
237224
+ };
237225
+ process.once("SIGINT", () => {
237226
+ shutdown("SIGINT");
237227
+ });
237228
+ process.once("SIGTERM", () => {
237229
+ shutdown("SIGTERM");
237230
+ });
237231
+ try {
237232
+ await server.listen();
237233
+ server.printUrls();
237234
+ log(`serving search index stub at /${SEARCH_INDEX_FILE_NAME}`);
237235
+ } catch (error$2) {
237236
+ await cleanup();
237237
+ throw error$2;
237238
+ }
237239
+ }
237100
237240
  const ssg = async ({ outDir = "dist-ssg", fallbackFile = "200", debug: debug$3 = false, contentDir = "content" } = {}) => {
237241
+ if (debug$3) {
237242
+ await runDebugSsgServer();
237243
+ return;
237244
+ }
237101
237245
  const cwd = process.cwd();
237102
237246
  const outPath = node_path.default.resolve(cwd, outDir);
237103
237247
  const distPath = node_path.default.resolve(cwd, "dist");
@@ -237216,16 +237360,11 @@ const ssg = async ({ outDir = "dist-ssg", fallbackFile = "200", debug: debug$3 =
237216
237360
  await (0, node_fs_promises.writeFile)(fallbackOutputFile, fallbackHtml, "utf-8");
237217
237361
  log(`wrote ${fallbackOutputFile}`);
237218
237362
  } finally {
237219
- if (debug$3) {
237220
- log(`debug mode: preserved SSR entry at ${tempEntryPath}`);
237221
- log(`debug mode: preserved SSR build at ${ssrBuildPath}`);
237222
- } else {
237223
- await (0, node_fs_promises.rm)(tempEntryPath, { force: true });
237224
- await (0, node_fs_promises.rm)(ssrBuildPath, {
237225
- recursive: true,
237226
- force: true
237227
- });
237228
- }
237363
+ await (0, node_fs_promises.rm)(tempEntryPath, { force: true });
237364
+ await (0, node_fs_promises.rm)(ssrBuildPath, {
237365
+ recursive: true,
237366
+ force: true
237367
+ });
237229
237368
  }
237230
237369
  log(`completed. static files are in ${outPath}`);
237231
237370
  };
@@ -237420,7 +237559,7 @@ function getStringArg(arg, defaultValue) {
237420
237559
  description: "Base name for the fallback HTML file served for unknown routes"
237421
237560
  }).option("debug", {
237422
237561
  type: "boolean",
237423
- description: "Preserve intermediate SSR files for debugging",
237562
+ description: "Run SSG in Vite SSR debug mode",
237424
237563
  hidden: true
237425
237564
  }).option("contentDir", {
237426
237565
  type: "string",
package/dist/bin/index.js CHANGED
@@ -14,6 +14,7 @@ import * as path$4 from "path";
14
14
  import path from "path";
15
15
  import { parseRegExpLiteral } from "@eslint-community/regexpp";
16
16
  import * as fs$4 from "node:fs";
17
+ import { rmSync } from "node:fs";
17
18
  import { fileURLToPath, pathToFileURL } from "node:url";
18
19
  import path$1 from "node:path";
19
20
  import { cp as cp$1, mkdir as mkdir$1, readFile, readdir, rm as rm$1, stat, writeFile as writeFile$1 } from "node:fs/promises";
@@ -8451,11 +8452,19 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8451
8452
  reportError(DIAGS_TRANSFORM.globalNotAllowedInNested);
8452
8453
  return;
8453
8454
  }
8454
- collectElementHelper(usesStack$1, comp, child, (name$49) => isComponent(comp) ? comp.globalVars?.[name$49] : void 0, (name$49, value$2) => {
8455
- if (!isComponent(comp)) return;
8456
- comp.globalVars ??= {};
8457
- comp.globalVars[name$49] = value$2;
8458
- });
8455
+ {
8456
+ const attrs = getAttributes(child).map(segmentAttr);
8457
+ const storageKey = attrs.find((a$4) => a$4.name === "storageKey")?.value;
8458
+ const persistAttr = attrs.find((a$4) => a$4.name === "persist")?.value;
8459
+ const shouldPersist = persistAttr === "true" || persistAttr === "{true}" || persistAttr === "1";
8460
+ collectElementHelper(usesStack$1, comp, child, (name$49) => isComponent(comp) ? comp.globalVars?.[name$49] : void 0, (name$49, value$2) => {
8461
+ if (!isComponent(comp)) return;
8462
+ comp.globalVars ??= {};
8463
+ comp.globalVars[name$49] = value$2;
8464
+ const effectiveStorageKey = storageKey ?? (shouldPersist ? name$49 : void 0);
8465
+ if (effectiveStorageKey) comp.globalVars[`__storageKey_${name$49}`] = effectiveStorageKey;
8466
+ }, void 0, ["storageKey", "persist"]);
8467
+ }
8459
8468
  return;
8460
8469
  case "loaders":
8461
8470
  collectLoadersElements(usesStack$1, comp, child);
@@ -8578,14 +8587,15 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8578
8587
  });
8579
8588
  return result;
8580
8589
  }
8581
- function collectValue(usesStack$1, element, allowName = true) {
8590
+ function collectValue(usesStack$1, element, allowName = true, extraAllowedAttrs = []) {
8582
8591
  const elementName = getComponentName(element, getText);
8583
8592
  const childNodes = getChildNodes(element);
8584
8593
  const nestedComponents = childNodes.filter((c$4) => c$4.kind === SyntaxKind.ElementNode && UCRegex.test(getComponentName(c$4, getText)));
8585
8594
  const nestedHelpers = childNodes.filter((c$4) => c$4.kind === SyntaxKind.ElementNode && !UCRegex.test(getComponentName(c$4, getText)));
8586
8595
  const attrNodes = getAttributes(element);
8587
8596
  const attrsSegmented = attrNodes.map(segmentAttr);
8588
- const attrProps = attrsSegmented.filter((attr) => propAttrs.indexOf(attr.name) >= 0);
8597
+ const allAllowedAttrs = extraAllowedAttrs.length > 0 ? [...propAttrs, ...extraAllowedAttrs] : propAttrs;
8598
+ const attrProps = attrsSegmented.filter((attr) => allAllowedAttrs.indexOf(attr.name) >= 0);
8589
8599
  if (attrsSegmented.length > attrProps.length) {
8590
8600
  reportError(DIAGS_TRANSFORM.onlyNameValueAttrs(elementName));
8591
8601
  return null;
@@ -8669,8 +8679,8 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8669
8679
  comp.loaders.push(loaderDef);
8670
8680
  });
8671
8681
  }
8672
- function collectElementHelper(usesStack$1, comp, child, getter, setter, nameValidator) {
8673
- const valueInfo = collectValue(usesStack$1, child);
8682
+ function collectElementHelper(usesStack$1, comp, child, getter, setter, nameValidator, extraAllowedAttrs = []) {
8683
+ const valueInfo = collectValue(usesStack$1, child, true, extraAllowedAttrs);
8674
8684
  if (!valueInfo) return;
8675
8685
  nameValidator?.(valueInfo?.name ?? "");
8676
8686
  const name$49 = valueInfo.name;
@@ -236868,6 +236878,7 @@ const SEARCH_CATEGORIES = [
236868
236878
  ];
236869
236879
  const SEARCH_DEFAULT_CATEGORY = "other";
236870
236880
  const SEARCH_INDEX_FILE_NAME = "__xmlui-search-index.json";
236881
+ const SEARCH_INDEX_STUB_JSON = "[]";
236871
236882
  const SSG_WRITE_CONCURRENCY = 16;
236872
236883
  const EXTENSION_FILE_CANDIDATES = [
236873
236884
  "extensions.ts",
@@ -236884,6 +236895,13 @@ function getOutputHtmlPath(outDir, routePath) {
236884
236895
  if (routePath === "/") return path$1.join(outDir, "index.html");
236885
236896
  return path$1.join(outDir, routePath.slice(1), "index.html");
236886
236897
  }
236898
+ function isHtmlNavigationRequest(url$2, acceptHeader) {
236899
+ if (!acceptHeader?.includes("text/html")) return false;
236900
+ const pathname = new URL(url$2, "http://localhost").pathname;
236901
+ if (pathname === `/${SEARCH_INDEX_FILE_NAME}`) return false;
236902
+ if (pathname.startsWith("/@") || pathname.startsWith("/__vite") || pathname.startsWith("/__id")) return false;
236903
+ return !path$1.basename(pathname).includes(".");
236904
+ }
236887
236905
  function executeInlineScripts(html) {
236888
236906
  new import_api.JSDOM(html, { runScripts: "outside-only" }).window.document.querySelectorAll("script:not([src])").forEach((script) => {
236889
236907
  const content = (script.textContent || "").trim();
@@ -237091,7 +237109,134 @@ async function getWorkspaceExtensionAliases(cwd) {
237091
237109
  }
237092
237110
  return aliases;
237093
237111
  }
237112
+ function mergeAliases(existingAlias, extensionAliases) {
237113
+ if (Array.isArray(existingAlias)) return [...existingAlias, ...Object.entries(extensionAliases).map(([find$1, replacement]) => ({
237114
+ find: find$1,
237115
+ replacement
237116
+ }))];
237117
+ if (existingAlias && typeof existingAlias === "object") return {
237118
+ ...existingAlias,
237119
+ ...extensionAliases
237120
+ };
237121
+ return { ...extensionAliases };
237122
+ }
237123
+ function prioritizeTypeScriptExtensions(extensions) {
237124
+ if (!extensions) return;
237125
+ const priority = new Map([
237126
+ [".ts", 0],
237127
+ [".tsx", 1],
237128
+ [".jsx", 2],
237129
+ [".js", 3]
237130
+ ]);
237131
+ return [...extensions].sort((left, right) => {
237132
+ return (priority.get(left) ?? 100) - (priority.get(right) ?? 100);
237133
+ });
237134
+ }
237135
+ async function runDebugSsgServer() {
237136
+ const cwd = process.cwd();
237137
+ const sourceIndexPath = path$1.resolve(cwd, "index.html");
237138
+ const tempEntryPath = path$1.resolve(cwd, TEMP_ENTRY_FILE_NAME);
237139
+ log(`starting debug server in ${cwd}`);
237140
+ executeInlineScripts(await readFile(sourceIndexPath, "utf-8"));
237141
+ const extensionImportSpecifiers = await getExtensionImportSpecifiers(cwd);
237142
+ if (extensionImportSpecifiers.length > 0) log(`detected extensions: ${extensionImportSpecifiers.join(", ")}`);
237143
+ log("creating SSR module");
237144
+ await writeFile$1(tempEntryPath, getSsgEntrySource(extensionImportSpecifiers), "utf-8");
237145
+ process.once("exit", () => {
237146
+ try {
237147
+ rmSync(tempEntryPath, { force: true });
237148
+ } catch {}
237149
+ });
237150
+ const viteConfig = await getViteConfig({});
237151
+ const extensionAliases = await getWorkspaceExtensionAliases(cwd);
237152
+ if (Object.keys(extensionAliases).length > 0) log(`using workspace extension aliases: ${Object.keys(extensionAliases).join(", ")}`);
237153
+ const mergedAlias = mergeAliases(viteConfig.resolve?.alias, extensionAliases);
237154
+ const basePlugins = Array.isArray(viteConfig.plugins) ? viteConfig.plugins : viteConfig.plugins ? [viteConfig.plugins] : [];
237155
+ const ssgDebugPlugin = {
237156
+ name: "xmlui-ssg-debug",
237157
+ configureServer(server$1) {
237158
+ server$1.middlewares.use(async (req$1, res, next) => {
237159
+ const requestUrl = req$1.originalUrl || req$1.url || "/";
237160
+ if (new URL(requestUrl, "http://localhost").pathname === `/${SEARCH_INDEX_FILE_NAME}`) {
237161
+ res.statusCode = 200;
237162
+ res.setHeader("Content-Type", "application/json");
237163
+ res.end(SEARCH_INDEX_STUB_JSON);
237164
+ return;
237165
+ }
237166
+ if (!isHtmlNavigationRequest(requestUrl, req$1.headers.accept)) {
237167
+ next();
237168
+ return;
237169
+ }
237170
+ try {
237171
+ const shellHtml = await readFile(sourceIndexPath, "utf-8");
237172
+ const transformedShell = await server$1.transformIndexHtml(requestUrl, shellHtml, req$1.originalUrl);
237173
+ const renderModule = await server$1.ssrLoadModule(`${pathToFileURL(tempEntryPath).href}?t=${Date.now()}`);
237174
+ if (!renderModule?.renderPath) throw new Error("failed to load renderPath from temporary SSG entry module");
237175
+ const finalHtml = applyRenderToShell(transformedShell, renderModule.renderPath(requestUrl));
237176
+ res.statusCode = 200;
237177
+ res.setHeader("Content-Type", "text/html");
237178
+ res.end(finalHtml);
237179
+ } catch (error$2) {
237180
+ const err$1 = error$2;
237181
+ server$1.ssrFixStacktrace(err$1);
237182
+ res.statusCode = 500;
237183
+ res.setHeader("Content-Type", "text/plain");
237184
+ res.end(err$1.stack || err$1.message || String(err$1));
237185
+ }
237186
+ });
237187
+ }
237188
+ };
237189
+ const server = await createServer({
237190
+ ...viteConfig,
237191
+ resolve: {
237192
+ ...viteConfig.resolve,
237193
+ alias: mergedAlias,
237194
+ extensions: prioritizeTypeScriptExtensions(viteConfig.resolve?.extensions)
237195
+ },
237196
+ define: {
237197
+ ...viteConfig.define,
237198
+ "process.env.VITE_BUILD_MODE": "\"ALL\"",
237199
+ "process.env.VITE_DEV_MODE": true,
237200
+ "process.env.VITE_STANDALONE": process.env.VITE_STANDALONE,
237201
+ "process.env.VITE_MOCK_ENABLED": true,
237202
+ "process.env.VITE_INCLUDE_ALL_COMPONENTS": "\"true\"",
237203
+ "process.env.VITE_USER_COMPONENTS_Inspect": "\"true\""
237204
+ },
237205
+ plugins: [...basePlugins, ssgDebugPlugin]
237206
+ });
237207
+ if (!server.httpServer) throw new Error("HTTP server not available");
237208
+ let cleanedUp = false;
237209
+ const cleanup = async () => {
237210
+ if (cleanedUp) return;
237211
+ cleanedUp = true;
237212
+ await rm$1(tempEntryPath, { force: true });
237213
+ };
237214
+ const shutdown = async (signal) => {
237215
+ log(`received ${signal}, shutting down debug server`);
237216
+ await server.close();
237217
+ await cleanup();
237218
+ process.exit(0);
237219
+ };
237220
+ process.once("SIGINT", () => {
237221
+ shutdown("SIGINT");
237222
+ });
237223
+ process.once("SIGTERM", () => {
237224
+ shutdown("SIGTERM");
237225
+ });
237226
+ try {
237227
+ await server.listen();
237228
+ server.printUrls();
237229
+ log(`serving search index stub at /${SEARCH_INDEX_FILE_NAME}`);
237230
+ } catch (error$2) {
237231
+ await cleanup();
237232
+ throw error$2;
237233
+ }
237234
+ }
237094
237235
  const ssg = async ({ outDir = "dist-ssg", fallbackFile = "200", debug: debug$3 = false, contentDir = "content" } = {}) => {
237236
+ if (debug$3) {
237237
+ await runDebugSsgServer();
237238
+ return;
237239
+ }
237095
237240
  const cwd = process.cwd();
237096
237241
  const outPath = path$1.resolve(cwd, outDir);
237097
237242
  const distPath = path$1.resolve(cwd, "dist");
@@ -237210,16 +237355,11 @@ const ssg = async ({ outDir = "dist-ssg", fallbackFile = "200", debug: debug$3 =
237210
237355
  await writeFile$1(fallbackOutputFile, fallbackHtml, "utf-8");
237211
237356
  log(`wrote ${fallbackOutputFile}`);
237212
237357
  } finally {
237213
- if (debug$3) {
237214
- log(`debug mode: preserved SSR entry at ${tempEntryPath}`);
237215
- log(`debug mode: preserved SSR build at ${ssrBuildPath}`);
237216
- } else {
237217
- await rm$1(tempEntryPath, { force: true });
237218
- await rm$1(ssrBuildPath, {
237219
- recursive: true,
237220
- force: true
237221
- });
237222
- }
237358
+ await rm$1(tempEntryPath, { force: true });
237359
+ await rm$1(ssrBuildPath, {
237360
+ recursive: true,
237361
+ force: true
237362
+ });
237223
237363
  }
237224
237364
  log(`completed. static files are in ${outPath}`);
237225
237365
  };
@@ -237414,7 +237554,7 @@ yargs(hideBin(process.argv)).command("build", "Build the project", (yargs$1) =>
237414
237554
  description: "Base name for the fallback HTML file served for unknown routes"
237415
237555
  }).option("debug", {
237416
237556
  type: "boolean",
237417
- description: "Preserve intermediate SSR files for debugging",
237557
+ description: "Run SSG in Vite SSR debug mode",
237418
237558
  hidden: true
237419
237559
  }).option("contentDir", {
237420
237560
  type: "string",
@@ -623,6 +623,19 @@ const layoutOptionKeys = [
623
623
  "overflowX",
624
624
  "overflowY",
625
625
  "zIndex",
626
+ "scrollSnapType",
627
+ "scrollSnapAlign",
628
+ "scrollSnapStop",
629
+ "scrollPadding",
630
+ "scrollPaddingTop",
631
+ "scrollPaddingRight",
632
+ "scrollPaddingBottom",
633
+ "scrollPaddingLeft",
634
+ "scrollMargin",
635
+ "scrollMarginTop",
636
+ "scrollMarginRight",
637
+ "scrollMarginBottom",
638
+ "scrollMarginLeft",
626
639
  "color",
627
640
  "fontFamily",
628
641
  "fontSize",
@@ -594,6 +594,19 @@ const layoutOptionKeys = [
594
594
  "overflowX",
595
595
  "overflowY",
596
596
  "zIndex",
597
+ "scrollSnapType",
598
+ "scrollSnapAlign",
599
+ "scrollSnapStop",
600
+ "scrollPadding",
601
+ "scrollPaddingTop",
602
+ "scrollPaddingRight",
603
+ "scrollPaddingBottom",
604
+ "scrollPaddingLeft",
605
+ "scrollMargin",
606
+ "scrollMarginTop",
607
+ "scrollMarginRight",
608
+ "scrollMarginBottom",
609
+ "scrollMarginLeft",
597
610
  "color",
598
611
  "fontFamily",
599
612
  "fontSize",
@@ -8425,11 +8425,19 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8425
8425
  reportError(DIAGS_TRANSFORM.globalNotAllowedInNested);
8426
8426
  return;
8427
8427
  }
8428
- collectElementHelper(usesStack$1, comp, child, (name) => isComponent(comp) ? comp.globalVars?.[name] : void 0, (name, value) => {
8429
- if (!isComponent(comp)) return;
8430
- comp.globalVars ??= {};
8431
- comp.globalVars[name] = value;
8432
- });
8428
+ {
8429
+ const attrs = getAttributes(child).map(segmentAttr);
8430
+ const storageKey = attrs.find((a) => a.name === "storageKey")?.value;
8431
+ const persistAttr = attrs.find((a) => a.name === "persist")?.value;
8432
+ const shouldPersist = persistAttr === "true" || persistAttr === "{true}" || persistAttr === "1";
8433
+ collectElementHelper(usesStack$1, comp, child, (name) => isComponent(comp) ? comp.globalVars?.[name] : void 0, (name, value) => {
8434
+ if (!isComponent(comp)) return;
8435
+ comp.globalVars ??= {};
8436
+ comp.globalVars[name] = value;
8437
+ const effectiveStorageKey = storageKey ?? (shouldPersist ? name : void 0);
8438
+ if (effectiveStorageKey) comp.globalVars[`__storageKey_${name}`] = effectiveStorageKey;
8439
+ }, void 0, ["storageKey", "persist"]);
8440
+ }
8433
8441
  return;
8434
8442
  case "loaders":
8435
8443
  collectLoadersElements(usesStack$1, comp, child);
@@ -8552,14 +8560,15 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8552
8560
  });
8553
8561
  return result;
8554
8562
  }
8555
- function collectValue(usesStack$1, element, allowName = true) {
8563
+ function collectValue(usesStack$1, element, allowName = true, extraAllowedAttrs = []) {
8556
8564
  const elementName = getComponentName(element, getText);
8557
8565
  const childNodes = getChildNodes(element);
8558
8566
  const nestedComponents = childNodes.filter((c) => c.kind === SyntaxKind.ElementNode && UCRegex.test(getComponentName(c, getText)));
8559
8567
  const nestedHelpers = childNodes.filter((c) => c.kind === SyntaxKind.ElementNode && !UCRegex.test(getComponentName(c, getText)));
8560
8568
  const attrNodes = getAttributes(element);
8561
8569
  const attrsSegmented = attrNodes.map(segmentAttr);
8562
- const attrProps = attrsSegmented.filter((attr) => propAttrs.indexOf(attr.name) >= 0);
8570
+ const allAllowedAttrs = extraAllowedAttrs.length > 0 ? [...propAttrs, ...extraAllowedAttrs] : propAttrs;
8571
+ const attrProps = attrsSegmented.filter((attr) => allAllowedAttrs.indexOf(attr.name) >= 0);
8563
8572
  if (attrsSegmented.length > attrProps.length) {
8564
8573
  reportError(DIAGS_TRANSFORM.onlyNameValueAttrs(elementName));
8565
8574
  return null;
@@ -8643,8 +8652,8 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8643
8652
  comp.loaders.push(loaderDef);
8644
8653
  });
8645
8654
  }
8646
- function collectElementHelper(usesStack$1, comp, child, getter, setter, nameValidator) {
8647
- const valueInfo = collectValue(usesStack$1, child);
8655
+ function collectElementHelper(usesStack$1, comp, child, getter, setter, nameValidator, extraAllowedAttrs = []) {
8656
+ const valueInfo = collectValue(usesStack$1, child, true, extraAllowedAttrs);
8648
8657
  if (!valueInfo) return;
8649
8658
  nameValidator?.(valueInfo?.name ?? "");
8650
8659
  const name = valueInfo.name;
@@ -8425,11 +8425,19 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8425
8425
  reportError(DIAGS_TRANSFORM.globalNotAllowedInNested);
8426
8426
  return;
8427
8427
  }
8428
- collectElementHelper(usesStack$1, comp, child, (name) => isComponent(comp) ? comp.globalVars?.[name] : void 0, (name, value) => {
8429
- if (!isComponent(comp)) return;
8430
- comp.globalVars ??= {};
8431
- comp.globalVars[name] = value;
8432
- });
8428
+ {
8429
+ const attrs = getAttributes(child).map(segmentAttr);
8430
+ const storageKey = attrs.find((a) => a.name === "storageKey")?.value;
8431
+ const persistAttr = attrs.find((a) => a.name === "persist")?.value;
8432
+ const shouldPersist = persistAttr === "true" || persistAttr === "{true}" || persistAttr === "1";
8433
+ collectElementHelper(usesStack$1, comp, child, (name) => isComponent(comp) ? comp.globalVars?.[name] : void 0, (name, value) => {
8434
+ if (!isComponent(comp)) return;
8435
+ comp.globalVars ??= {};
8436
+ comp.globalVars[name] = value;
8437
+ const effectiveStorageKey = storageKey ?? (shouldPersist ? name : void 0);
8438
+ if (effectiveStorageKey) comp.globalVars[`__storageKey_${name}`] = effectiveStorageKey;
8439
+ }, void 0, ["storageKey", "persist"]);
8440
+ }
8433
8441
  return;
8434
8442
  case "loaders":
8435
8443
  collectLoadersElements(usesStack$1, comp, child);
@@ -8552,14 +8560,15 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8552
8560
  });
8553
8561
  return result;
8554
8562
  }
8555
- function collectValue(usesStack$1, element, allowName = true) {
8563
+ function collectValue(usesStack$1, element, allowName = true, extraAllowedAttrs = []) {
8556
8564
  const elementName = getComponentName(element, getText);
8557
8565
  const childNodes = getChildNodes(element);
8558
8566
  const nestedComponents = childNodes.filter((c) => c.kind === SyntaxKind.ElementNode && UCRegex.test(getComponentName(c, getText)));
8559
8567
  const nestedHelpers = childNodes.filter((c) => c.kind === SyntaxKind.ElementNode && !UCRegex.test(getComponentName(c, getText)));
8560
8568
  const attrNodes = getAttributes(element);
8561
8569
  const attrsSegmented = attrNodes.map(segmentAttr);
8562
- const attrProps = attrsSegmented.filter((attr) => propAttrs.indexOf(attr.name) >= 0);
8570
+ const allAllowedAttrs = extraAllowedAttrs.length > 0 ? [...propAttrs, ...extraAllowedAttrs] : propAttrs;
8571
+ const attrProps = attrsSegmented.filter((attr) => allAllowedAttrs.indexOf(attr.name) >= 0);
8563
8572
  if (attrsSegmented.length > attrProps.length) {
8564
8573
  reportError(DIAGS_TRANSFORM.onlyNameValueAttrs(elementName));
8565
8574
  return null;
@@ -8643,8 +8652,8 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
8643
8652
  comp.loaders.push(loaderDef);
8644
8653
  });
8645
8654
  }
8646
- function collectElementHelper(usesStack$1, comp, child, getter, setter, nameValidator) {
8647
- const valueInfo = collectValue(usesStack$1, child);
8655
+ function collectElementHelper(usesStack$1, comp, child, getter, setter, nameValidator, extraAllowedAttrs = []) {
8656
+ const valueInfo = collectValue(usesStack$1, child, true, extraAllowedAttrs);
8648
8657
  if (!valueInfo) return;
8649
8658
  nameValidator?.(valueInfo?.name ?? "");
8650
8659
  const name = valueInfo.name;