@stacksjs/stx 0.2.120 → 0.2.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/appearance-bootstrap.d.ts +20 -0
- package/dist/appearance-bootstrap.js +92 -0
- package/dist/cli.js +546 -567
- package/dist/client-script-bundler.d.ts +13 -0
- package/dist/client-script-bundler.js +19 -2
- package/dist/component-library.js +30 -12
- package/dist/craft.js +12302 -120
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/native-build.d.ts +6 -0
- package/dist/native-build.js +77 -60
- package/dist/process.js +5 -1
- package/dist/pwa.js +376 -375
- package/dist/render.js +6 -1
- package/dist/signals.js +2 -1
- package/dist/ssg.js +373 -372
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./a11y.js";
|
|
|
13
13
|
export * from "./analytics.js";
|
|
14
14
|
export * from "./analyzer.js";
|
|
15
15
|
export * from "./animation.js";
|
|
16
|
+
export * from "./appearance-bootstrap.js";
|
|
16
17
|
export * from "./assets.js";
|
|
17
18
|
export * from "./app-shell.js";
|
|
18
19
|
export * from "./async-components.js";
|
package/dist/native-build.d.ts
CHANGED
|
@@ -62,10 +62,16 @@ export declare interface NativeBuildConfig {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
systemTray?: boolean
|
|
65
|
+
menubarOnly?: boolean
|
|
66
|
+
infoPlist?: Record<string, string | number | boolean>
|
|
67
|
+
minimumSystemVersion?: string
|
|
68
|
+
category?: string
|
|
69
|
+
copyright?: string
|
|
65
70
|
hotReload?: boolean
|
|
66
71
|
devTools?: boolean
|
|
67
72
|
craftPath?: string
|
|
68
73
|
env?: Record<string, string>
|
|
74
|
+
context?: Record<string, unknown>
|
|
69
75
|
verbose?: boolean
|
|
70
76
|
}
|
|
71
77
|
export declare interface NativeBuildResult {
|
package/dist/native-build.js
CHANGED
|
@@ -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
|
|
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")"` : "",
|
|
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
|
-
"$
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
106
|
-
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
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
|
-
"
|
|
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 ? "
|
|
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
|
-
"$
|
|
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 ? "
|
|
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
|
|
236
|
-
join(process.cwd(), "../craft/packages/zig/zig-out/bin/craft
|
|
237
|
-
join(homedir(), "Code/craft/packages/zig/zig-out/bin/craft
|
|
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
|
@@ -12,9 +12,10 @@ import { extractBridgeData, processClientScript } from "./client-script.js";
|
|
|
12
12
|
import { processReactiveDirectives } from "./reactive.js";
|
|
13
13
|
import { processMarkdownFileDirectives } from "./assets.js";
|
|
14
14
|
import { processAuthDirectives, processConditionals, processEnvDirective, processIssetEmptyDirectives } from "./conditionals.js";
|
|
15
|
-
import { injectCspMetaTag, processCspDirectives } from "./csp.js";
|
|
15
|
+
import { addNonceToInlineContent, injectCspMetaTag, processCspDirectives } from "./csp.js";
|
|
16
16
|
import { processCsrfDirectives } from "./csrf.js";
|
|
17
17
|
import { processCustomDirectives } from "./custom-directives.js";
|
|
18
|
+
import { processAppearanceBootstrapDirective } from "./appearance-bootstrap.js";
|
|
18
19
|
import { devHelpers, errorLogger, errorRecovery, safeExecuteAsync, StxRuntimeError, StxValidationError } from "./error-handling.js";
|
|
19
20
|
import { getHead as getHeadStatic } from "./head.js";
|
|
20
21
|
import { processExpressions, usesSignalsInScript } from "./expressions.js";
|
|
@@ -669,6 +670,7 @@ async function processOtherDirectives(template, context, filePath, options, depe
|
|
|
669
670
|
output = processXElementDirectives(output);
|
|
670
671
|
const pageFilePath = context.__originalFilePath || filePath, serverData = extractBridgeData(context);
|
|
671
672
|
output = await processSignals(output, opts, pageFilePath, serverData);
|
|
673
|
+
output = processAppearanceBootstrapDirective(output, context);
|
|
672
674
|
output = await runPostProcessingMiddleware(output, context, filePath, opts);
|
|
673
675
|
if (opts.media?.image?.autoSiblings) {
|
|
674
676
|
const publicDir = opts.publicDir || "public", { rewriteImagesWithSiblings } = await import("./image-optimization/auto-sibling.js");
|
|
@@ -775,5 +777,7 @@ ${runtimeScript}`);
|
|
|
775
777
|
}
|
|
776
778
|
if (clientScriptsTransformed)
|
|
777
779
|
context.__stx_event_bindings = [];
|
|
780
|
+
if (opts.csp?.enabled && opts.csp.useNonce && typeof context.cspNonce === "string")
|
|
781
|
+
output = addNonceToInlineContent(output, context.cspNonce);
|
|
778
782
|
return output;
|
|
779
783
|
}
|