@stacksjs/stx 0.2.119 → 0.2.121

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 (62) hide show
  1. package/dist/builtins/attrs.d.ts +16 -0
  2. package/dist/builtins/attrs.js +16 -0
  3. package/dist/builtins/safe-image.js +2 -9
  4. package/dist/builtins/stx-image.js +2 -9
  5. package/dist/builtins/stx-link.js +2 -9
  6. package/dist/cli.js +1869 -863
  7. package/dist/client-script-bundler.d.ts +9 -7
  8. package/dist/client-script-bundler.js +43 -4
  9. package/dist/client-script.d.ts +24 -0
  10. package/dist/client-script.js +59 -5
  11. package/dist/component-library.js +30 -12
  12. package/dist/component-registry.d.ts +1 -0
  13. package/dist/component-renderer.js +13 -5
  14. package/dist/composables/index.d.ts +1 -0
  15. package/dist/composables/index.js +1 -0
  16. package/dist/composables/use-scroll-lock.d.ts +13 -0
  17. package/dist/composables/use-scroll-lock.js +55 -0
  18. package/dist/composition-api.d.ts +1 -1
  19. package/dist/composition-api.js +13 -4
  20. package/dist/craft-bridge.d.ts +80 -1
  21. package/dist/craft-bridge.js +80 -1
  22. package/dist/craft-components.d.ts +77 -3
  23. package/dist/craft-components.js +138 -9
  24. package/dist/craft.js +12708 -118
  25. package/dist/dev-server/crosswind.d.ts +15 -1
  26. package/dist/dev-server/crosswind.js +12 -3
  27. package/dist/dev-server/serve-app.js +3 -3
  28. package/dist/document-shell.d.ts +17 -0
  29. package/dist/document-shell.js +72 -2
  30. package/dist/expressions.js +14 -7
  31. package/dist/head.d.ts +8 -0
  32. package/dist/head.js +11 -8
  33. package/dist/html-masking.d.ts +12 -0
  34. package/dist/html-masking.js +50 -15
  35. package/dist/index.d.ts +9 -1
  36. package/dist/index.js +9 -1
  37. package/dist/native-build.d.ts +6 -0
  38. package/dist/native-build.js +77 -60
  39. package/dist/process.js +11 -3
  40. package/dist/pwa.js +1232 -508
  41. package/dist/render.js +6 -1
  42. package/dist/runtime-globals.d.ts +7 -4
  43. package/dist/runtime-globals.js +10 -2
  44. package/dist/runtime-injection.js +15 -1
  45. package/dist/signal-processing.js +19 -28
  46. package/dist/signals-api.d.ts +2 -0
  47. package/dist/signals-api.js +9 -0
  48. package/dist/signals.js +785 -62
  49. package/dist/ssg.js +1176 -452
  50. package/dist/state-management.d.ts +1 -1
  51. package/dist/state-management.js +1 -1
  52. package/dist/strict-lint.d.ts +1 -1
  53. package/dist/strict-lint.js +1 -1
  54. package/dist/stx.d.ts +6 -0
  55. package/dist/style-scoping.js +10 -0
  56. package/dist/utils.js +5 -3
  57. package/dist/variable-extractor.js +14 -22
  58. package/dist/vue-template.js +3 -2
  59. package/dist/x-element.d.ts +2 -2
  60. package/dist/x-element.js +9 -8
  61. package/package.json +5 -5
  62. package/stx.d.ts +6 -0
@@ -4,6 +4,7 @@ import { spawn, execSync } from "node:child_process";
4
4
  import { tmpdir, homedir, platform as osPlatform } from "node:os";
5
5
  import { injectCraftBridge } from "./craft-bridge.js";
6
6
  import { processCraftComponents, CRAFT_COMPONENT_STYLES } from "./craft-components.js";
7
+ import { renderTemplate } from "./render.js";
7
8
  export async function buildNative(config) {
8
9
  const startTime = Date.now();
9
10
  try {
@@ -17,7 +18,10 @@ export async function buildNative(config) {
17
18
  const target = config.target || detectPlatform(), format = config.format || getDefaultFormat(target), outputDir = config.output || join(process.cwd(), "dist", "native");
18
19
  if (!existsSync(outputDir))
19
20
  mkdirSync(outputDir, { recursive: !0 });
20
- let html = await Bun.file(config.input).text();
21
+ let html = await renderTemplate(config.input, {
22
+ context: config.context,
23
+ options: { isDev: !1 }
24
+ });
21
25
  html = injectCraftBridge(html, { debug: config.verbose });
22
26
  html = processCraftComponents(html);
23
27
  if (!html.includes("craft-component-styles")) {
@@ -87,64 +91,51 @@ async function buildMacOS(html, appName, appVersion, outputDir, format, config,
87
91
  sidebarConfigPath = join(resourcesDir, "sidebar-config.json");
88
92
  await Bun.write(sidebarConfigPath, JSON.stringify(config.sidebar.config));
89
93
  }
90
- const sidebarFlags = config.sidebar?.enabled ? `--native-sidebar --sidebar-width ${config.sidebar?.width || 240} --sidebar-config "$(cat "$RESOURCES/sidebar-config.json")"` : "", launcherScript = `#!/bin/bash
94
+ const sidebarFlags = config.sidebar?.enabled ? `--native-sidebar --sidebar-width ${config.sidebar?.width || 240} --sidebar-config "$(cat "$RESOURCES/sidebar-config.json")"` : "", craftBinaryDest = join(macOSDir, "craft");
95
+ copyFileSync(craftPath, craftBinaryDest);
96
+ chmodSync(craftBinaryDest, 493);
97
+ const menubarOnly = config.menubarOnly ?? config.systemTray, launcherScript = `#!/bin/bash
98
+ set -euo pipefail
91
99
  DIR="$( cd "$( dirname "\${BASH_SOURCE[0]}" )" && pwd )"
92
100
  RESOURCES="$DIR/../Resources"
93
- "${craftPath}" --html "$(cat "$RESOURCES/index.html")" \\
94
- --title "${config.window?.title || appName}" \\
95
- --width ${config.window?.width || 1200} \\
96
- --height ${config.window?.height || 800} \\
97
- ${config.systemTray ? "--system-tray" : ""} \\
98
- ${config.devTools ? "--dev-tools" : ""} \\
99
- ${config.window?.frameless ? "--frameless" : ""} \\
100
- ${config.window?.alwaysOnTop ? "--always-on-top" : ""} \\
101
- ${sidebarFlags}
101
+ exec "$DIR/craft" --html-file "$RESOURCES/index.html" \\
102
+ ${[
103
+ `--title "${config.window?.title || appName}"`,
104
+ `--width ${config.window?.width || 1200}`,
105
+ `--height ${config.window?.height || 800}`,
106
+ menubarOnly ? "--menubar-only" : config.systemTray ? "--system-tray" : "",
107
+ config.devTools ? "" : "--no-devtools",
108
+ config.window?.frameless ? "--frameless" : "",
109
+ config.window?.transparent ? "--transparent" : "",
110
+ config.window?.alwaysOnTop ? "--always-on-top" : "",
111
+ config.window?.resizable === !1 ? "--no-resize" : "",
112
+ sidebarFlags
113
+ ].filter(Boolean).join(" \\\n ")}
102
114
  `, launcherPath = join(macOSDir, appName);
103
115
  await Bun.write(launcherPath, launcherScript);
104
116
  chmodSync(launcherPath, 493);
105
- const craftBinaryDest = join(macOSDir, "craft");
106
- try {
107
- copyFileSync(craftPath, craftBinaryDest);
108
- chmodSync(craftBinaryDest, 493);
109
- } catch {
110
- const craftWrapperScript = `#!/bin/bash
111
- exec "${craftPath}" "$@"`;
112
- await Bun.write(craftBinaryDest, craftWrapperScript);
113
- chmodSync(craftBinaryDest, 493);
114
- }
115
- const infoPlist = `<?xml version="1.0" encoding="UTF-8"?>
116
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
117
- <plist version="1.0">
118
- <dict>
119
- <key>CFBundleExecutable</key>
120
- <string>${appName}</string>
121
- <key>CFBundleIdentifier</key>
122
- <string>${bundleId}</string>
123
- <key>CFBundleName</key>
124
- <string>${appName}</string>
125
- <key>CFBundleDisplayName</key>
126
- <string>${appName}</string>
127
- <key>CFBundleShortVersionString</key>
128
- <string>${appVersion}</string>
129
- <key>CFBundleVersion</key>
130
- <string>${appVersion}</string>
131
- <key>CFBundlePackageType</key>
132
- <string>APPL</string>
133
- <key>CFBundleSignature</key>
134
- <string>????</string>
135
- <key>LSMinimumSystemVersion</key>
136
- <string>10.15</string>
137
- <key>NSHighResolutionCapable</key>
138
- <true/>
139
- <key>NSSupportsAutomaticGraphicsSwitching</key>
140
- <true/>
141
- <key>LSUIElement</key>
142
- <${config.systemTray ? "true" : "false"}/>
143
- </dict>
144
- </plist>`;
145
- await Bun.write(join(contentsDir, "Info.plist"), infoPlist);
146
- if (config.icon && await Bun.file(config.icon).exists())
117
+ const hasIcon = Boolean(config.icon && await Bun.file(config.icon).exists());
118
+ if (hasIcon)
147
119
  copyFileSync(config.icon, join(resourcesDir, "AppIcon.icns"));
120
+ const plistEntries = {
121
+ CFBundleExecutable: appName,
122
+ CFBundleIdentifier: bundleId,
123
+ CFBundleName: appName,
124
+ CFBundleDisplayName: appName,
125
+ CFBundleShortVersionString: appVersion,
126
+ CFBundleVersion: appVersion,
127
+ CFBundlePackageType: "APPL",
128
+ CFBundleSignature: "????",
129
+ LSMinimumSystemVersion: config.minimumSystemVersion || "13.0",
130
+ NSHighResolutionCapable: !0,
131
+ NSSupportsAutomaticGraphicsSwitching: !0,
132
+ LSUIElement: config.menubarOnly ?? Boolean(config.systemTray),
133
+ ...hasIcon ? { CFBundleIconFile: "AppIcon" } : {},
134
+ ...config.category ? { LSApplicationCategoryType: config.category } : {},
135
+ ...config.copyright ? { NSHumanReadableCopyright: config.copyright } : {},
136
+ ...config.infoPlist || {}
137
+ };
138
+ await Bun.write(join(contentsDir, "Info.plist"), renderInfoPlist(plistEntries));
148
139
  if (format === "dmg") {
149
140
  const dmgPath = join(outputDir, `${appName}-${appVersion}.dmg`), dmgResult = await createDMG(appBundlePath, dmgPath, appName);
150
141
  if (!dmgResult.success)
@@ -153,19 +144,38 @@ exec "${craftPath}" "$@"`;
153
144
  }
154
145
  return { success: !0, target: "macos", format: "app", outputPath: appBundlePath };
155
146
  }
147
+ function escapeXml(value) {
148
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
149
+ }
150
+ function renderInfoPlist(entries) {
151
+ return `<?xml version="1.0" encoding="UTF-8"?>
152
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
153
+ <plist version="1.0">
154
+ <dict>
155
+ ${Object.entries(entries).map(([key, value]) => {
156
+ const rendered = typeof value === "boolean" ? `<${value}/>` : typeof value === "number" ? `<integer>${value}</integer>` : `<string>${escapeXml(String(value))}</string>`;
157
+ return ` <key>${escapeXml(key)}</key>
158
+ ${rendered}`;
159
+ }).join(`
160
+ `)}
161
+ </dict>
162
+ </plist>
163
+ `;
164
+ }
156
165
  async function buildWindows(html, appName, appVersion, outputDir, format, config, craftPath) {
157
166
  const appDir = join(outputDir, appName);
158
167
  mkdirSync(appDir, { recursive: !0 });
159
168
  const htmlPath = join(appDir, "index.html");
160
169
  await Bun.write(htmlPath, html);
170
+ copyFileSync(craftPath, join(appDir, "craft.exe"));
161
171
  const launcherBat = `@echo off
162
172
  set DIR=%~dp0
163
- "${craftPath}" --html-file "%DIR%index.html" ^
173
+ "%DIR%craft.exe" --html-file "%DIR%index.html" ^
164
174
  --title "${config.window?.title || appName}" ^
165
175
  --width ${config.window?.width || 1200} ^
166
176
  --height ${config.window?.height || 800} ^
167
177
  ${config.systemTray ? "--system-tray" : ""} ^
168
- ${config.devTools ? "--dev-tools" : ""}
178
+ ${config.devTools ? "" : "--no-devtools"}
169
179
  `;
170
180
  await Bun.write(join(appDir, `${appName}.bat`), launcherBat);
171
181
  if (format === "zip") {
@@ -181,14 +191,18 @@ async function buildLinux(html, appName, appVersion, outputDir, format, config,
181
191
  mkdirSync(appDir, { recursive: !0 });
182
192
  const htmlPath = join(appDir, "index.html");
183
193
  await Bun.write(htmlPath, html);
194
+ const craftDest = join(appDir, "craft");
195
+ copyFileSync(craftPath, craftDest);
196
+ chmodSync(craftDest, 493);
184
197
  const launcherScript = `#!/bin/bash
198
+ set -euo pipefail
185
199
  DIR="$( cd "$( dirname "\${BASH_SOURCE[0]}" )" && pwd )"
186
- "${craftPath}" --html-file "$DIR/index.html" \\
200
+ exec "$DIR/craft" --html-file "$DIR/index.html" \\
187
201
  --title "${config.window?.title || appName}" \\
188
202
  --width ${config.window?.width || 1200} \\
189
203
  --height ${config.window?.height || 800} \\
190
204
  ${config.systemTray ? "--system-tray" : ""} \\
191
- ${config.devTools ? "--dev-tools" : ""}
205
+ ${config.devTools ? "" : "--no-devtools"}
192
206
  `, launcherPath = join(appDir, appName.toLowerCase());
193
207
  await Bun.write(launcherPath, launcherScript);
194
208
  chmodSync(launcherPath, 493);
@@ -231,10 +245,13 @@ async function buildAndroid(_html, appName, _appVersion, _outputDir, _config, _c
231
245
  };
232
246
  }
233
247
  async function findCraftBinary() {
248
+ if (process.env.CRAFT_BIN && await Bun.file(process.env.CRAFT_BIN).exists())
249
+ return process.env.CRAFT_BIN;
234
250
  const possiblePaths = [
235
- join(process.cwd(), "../../craft/packages/zig/zig-out/bin/craft-minimal"),
236
- join(process.cwd(), "../craft/packages/zig/zig-out/bin/craft-minimal"),
237
- join(homedir(), "Code/craft/packages/zig/zig-out/bin/craft-minimal"),
251
+ join(process.cwd(), "../../craft/packages/zig/zig-out/bin/craft"),
252
+ join(process.cwd(), "../craft/packages/zig/zig-out/bin/craft"),
253
+ join(homedir(), "Code/Tools/craft/packages/zig/zig-out/bin/craft"),
254
+ join(homedir(), "Code/craft/packages/zig/zig-out/bin/craft"),
238
255
  "/usr/local/bin/craft",
239
256
  "/usr/bin/craft",
240
257
  join(homedir(), ".local/bin/craft"),
package/dist/process.js CHANGED
@@ -676,9 +676,17 @@ async function processOtherDirectives(template, context, filePath, options, depe
676
676
  }
677
677
  if (opts.seo?.enabled)
678
678
  output = injectSeoTags(output, context, opts);
679
- const injectIntoHead = (html, snippet) => {
679
+ const injectIntoHead = (html, snippet, replaceExistingTitle = !0) => {
680
680
  if (!snippet)
681
681
  return html;
682
+ const incomingTitle = snippet.match(/<title\b[^>]*>[\s\S]*?<\/title>/i), existingTitle = html.match(/<title\b[^>]*>[\s\S]*?<\/title>/i);
683
+ if (incomingTitle && existingTitle) {
684
+ if (replaceExistingTitle)
685
+ html = html.replace(existingTitle[0], incomingTitle[0]);
686
+ snippet = snippet.replace(incomingTitle[0], "").trim();
687
+ if (!snippet)
688
+ return html;
689
+ }
682
690
  if (/<\/head>/i.test(html))
683
691
  return html.replace(/<\/head>/i, `${snippet}
684
692
  </head>`);
@@ -691,14 +699,14 @@ ${snippet}`);
691
699
  ${snippet}
692
700
  </head>`);
693
701
  return html;
694
- }, { renderHead, getHead } = await import("./head.js"), contextHead = context.__stx_runtime_head, headConfig = contextHead && (contextHead.title || contextHead.meta?.length || contextHead.link?.length) ? contextHead : getHead();
702
+ }, { renderHead, getHead } = await import("./head.js"), headConfig = context.__stx_runtime_head ?? getHead();
695
703
  if (headConfig.title || headConfig.meta?.length || headConfig.link?.length) {
696
704
  const renderedHead = renderHead(headConfig);
697
705
  if (renderedHead)
698
706
  output = injectIntoHead(output, renderedHead);
699
707
  }
700
708
  if (headResult.headContent)
701
- output = injectIntoHead(output, headResult.headContent);
709
+ output = injectIntoHead(output, headResult.headContent, !headConfig.title);
702
710
  if (opts.csp?.enabled && opts.csp.addMetaTag)
703
711
  output = injectCspMetaTag(output, opts.csp, context);
704
712
  if (opts.analytics?.enabled)