nodality 1.0.157 → 1.0.161

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 (108) hide show
  1. package/bin/nodality.js +223 -0
  2. package/dist/bundle.umd.js +1 -1
  3. package/dist/button.cjs.js +1 -1
  4. package/dist/button.esm.js +1 -1
  5. package/dist/designer.cjs.js +1 -1
  6. package/dist/designer.esm.js +1 -1
  7. package/dist/element-mapper.cjs.js +1 -1
  8. package/dist/element-mapper.esm.js +1 -1
  9. package/dist/finalresult.esm.js +1 -1
  10. package/dist/index.cjs.js +1 -1
  11. package/dist/index.esm.js +1 -1
  12. package/dist/slider-2025.cjs.js +1 -1
  13. package/dist/slider-2025.esm.js +1 -1
  14. package/layout/animator.js +1 -1
  15. package/layout/audio.js +1 -1
  16. package/layout/audionew.js +1 -1
  17. package/layout/base-2.js +1 -1
  18. package/layout/base.js +1 -1
  19. package/layout/beta-desktop-bar.js +1 -1
  20. package/layout/beta-mobile-bar.js +1 -1
  21. package/layout/box.js +1 -1
  22. package/layout/button.js +9 -4
  23. package/layout/cards.js +1 -1
  24. package/layout/center.js +1 -1
  25. package/layout/checkbox.js +1 -1
  26. package/layout/circle.js +1 -1
  27. package/layout/clean-row.js +1 -1
  28. package/layout/code.js +1 -1
  29. package/layout/container.js +1 -1
  30. package/layout/custom.js +1 -1
  31. package/layout/div-image.js +1 -1
  32. package/layout/dropdown-2025.js +1 -1
  33. package/layout/dropdown.js +1 -1
  34. package/layout/empty-element.js +1 -1
  35. package/layout/external-stylesheet.js +1 -1
  36. package/layout/flex-card.js +1 -1
  37. package/layout/flex-grid.js +1 -1
  38. package/layout/flex-row.js +1 -1
  39. package/layout/footer.js +1 -1
  40. package/layout/form-components/custom.js +1 -1
  41. package/layout/form-components/data-list.js +1 -1
  42. package/layout/form-components/floating-input.js +1 -1
  43. package/layout/form-components/form-all.js +1 -1
  44. package/layout/form-components/form.js +1 -1
  45. package/layout/form-components/image-picker.js +1 -1
  46. package/layout/form-components/picker.js +1 -1
  47. package/layout/form-components/radio.js +1 -1
  48. package/layout/form-components/radiogroup.js +1 -1
  49. package/layout/form-components/range.js +1 -1
  50. package/layout/free.js +1 -1
  51. package/layout/grid-new.js +1 -1
  52. package/layout/grid-switcher.js +1 -1
  53. package/layout/grid.js +1 -1
  54. package/layout/group.js +1 -1
  55. package/layout/header.js +1 -1
  56. package/layout/horizontal-scroller.js +1 -1
  57. package/layout/image-old.js +1 -1
  58. package/layout/image.js +1 -1
  59. package/layout/index.js +1 -1
  60. package/layout/label.js +1 -1
  61. package/layout/link.js +1 -1
  62. package/layout/list-OLD.js +1 -1
  63. package/layout/list.js +1 -1
  64. package/layout/meta-adder.js +1 -1
  65. package/layout/modal-2025.js +1 -1
  66. package/layout/modernwrap.js +1 -1
  67. package/layout/multiswitcher.js +1 -1
  68. package/layout/multiswitcherBeta.js +1 -1
  69. package/layout/nav-bar.js +1 -1
  70. package/layout/nav-factor/custom-div.js +1 -1
  71. package/layout/navBar-OLD.js +1 -1
  72. package/layout/new-flat-adder.js +1 -1
  73. package/layout/new-nav-bar.js +1 -1
  74. package/layout/offset-container.js +1 -1
  75. package/layout/polygon.js +1 -1
  76. package/layout/prerender-site.js +1 -1
  77. package/layout/prerender.js +1 -1
  78. package/layout/progress.js +1 -1
  79. package/layout/row.js +1 -1
  80. package/layout/saved-new-nav-bar.js +1 -1
  81. package/layout/scroll-video.js +1 -1
  82. package/layout/side-bar.js +1 -1
  83. package/layout/side-nav-bar.js +1 -1
  84. package/layout/simple-bar.js +1 -1
  85. package/layout/slider-2025.js +1 -1
  86. package/layout/spacer.js +1 -1
  87. package/layout/stack.js +1 -1
  88. package/layout/styler.js +1 -1
  89. package/layout/svg.js +1 -1
  90. package/layout/switcher.js +1 -1
  91. package/layout/table.js +1 -1
  92. package/layout/text-field.js +1 -1
  93. package/layout/text.js +1 -1
  94. package/layout/ulist.js +1 -1
  95. package/layout/video.js +1 -1
  96. package/layout/without-new.js +1 -1
  97. package/layout/wrap.js +1 -1
  98. package/layout/zoom-card.js +1 -1
  99. package/lib/card-getter.js +1 -1
  100. package/lib/designer.js +1 -1
  101. package/lib/element-mapper.js +1 -1
  102. package/lib/keyframe-animation.js +1 -1
  103. package/lib/link-getter.js +1 -1
  104. package/lib/scroll-video.js +1 -1
  105. package/lib/stacker.js +1 -1
  106. package/lib/theme.js +1 -1
  107. package/lib/transform-anim.js +1 -1
  108. package/package.json +11 -3
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+ // bin/nodality.js — `npx nodality <command>` CLI entry shipped with
3
+ // the nodality package. Today the only subcommand is `prerender`,
4
+ // which walks the consumer's `upload/` directory, pairs each
5
+ // `<name>.html` with `pages/<name>.js` (or `<name>.js` for flat
6
+ // layouts), and renders the resulting tree to static HTML in place.
7
+ //
8
+ // Why this lives in the nodality package rather than in a separate
9
+ // `nodality-cli`:
10
+ // • Single install (`npm i nodality`) gives you the engine AND the
11
+ // runner — same pattern as next, vite, astro, prisma.
12
+ // • The CLI and the engine ship together so version drift between
13
+ // them is impossible.
14
+ // • Consumer scripts wrap this in `npm run prerender`, but
15
+ // `npx nodality prerender` also works without any wiring.
16
+ //
17
+ // Configuration lives in the consumer's `nodality.config.json`:
18
+ //
19
+ // {
20
+ // "origin": "https://example.com",
21
+ // "uploadDir": "upload",
22
+ // "defaultLocale": "cs",
23
+ // "locales": ["cs", "en", ...],
24
+ // "pages": [{ "html": "index.html", "entry": "app.js" }, ...]
25
+ // "tolerateAsyncErrors": true
26
+ // }
27
+ //
28
+ // Anything omitted falls back to sensible defaults (single-locale,
29
+ // upload/, auto-discovered page list). CLI flags override the file.
30
+
31
+ import fs from "node:fs";
32
+ import path from "node:path";
33
+ import { prerenderSite } from "../layout/prerender-site.js";
34
+
35
+ // ─── Usage ──────────────────────────────────────────────────────
36
+
37
+ function showUsage() {
38
+ console.log(`Usage:
39
+ nodality prerender [flags] # SSG: render upload/*.html in place
40
+ nodality help
41
+
42
+ Prerender flags (all optional; fall through to nodality.config.json, then defaults):
43
+ --origin=<url> Public origin, e.g. https://example.com (required if no config)
44
+ --upload=<path> Upload directory (default: ./upload)
45
+ --default-locale=<code> Default locale code for multi-locale builds
46
+ --locales=<a,b,c> Comma-separated locale list
47
+ --tolerate-async Install uncaught/unhandledRejection handlers so a single page's
48
+ late throw (from a deferred animation/fetch timer) doesn't abort
49
+ the whole batch — useful for sites with span-animation entries.
50
+
51
+ Examples:
52
+ nodality prerender
53
+ nodality prerender --origin=https://example.com --tolerate-async
54
+ `);
55
+ process.exit(1);
56
+ }
57
+
58
+ // ─── Flag parsing — minimal, no deps ────────────────────────────
59
+
60
+ function parseFlags(argv) {
61
+ const flags = {};
62
+ for (const arg of argv) {
63
+ if (!arg.startsWith("--")) continue;
64
+ const eq = arg.indexOf("=");
65
+ if (eq === -1) flags[arg.slice(2)] = true;
66
+ else flags[arg.slice(2, eq)] = arg.slice(eq + 1);
67
+ }
68
+ return flags;
69
+ }
70
+
71
+ // ─── Config file loader ─────────────────────────────────────────
72
+
73
+ function loadConfigFile(cwd) {
74
+ const p = path.join(cwd, "nodality.config.json");
75
+ if (!fs.existsSync(p)) return {};
76
+ try {
77
+ return JSON.parse(fs.readFileSync(p, "utf8"));
78
+ } catch (e) {
79
+ console.error(`[nodality] Failed to parse ${p}: ${e.message}`);
80
+ process.exit(1);
81
+ }
82
+ }
83
+
84
+ // ─── Page auto-discovery ────────────────────────────────────────
85
+
86
+ /**
87
+ * Pair each upload/<name>.html with its entry script. Supports both
88
+ * common layouts:
89
+ * • Flat: `upload/app.js`, `upload/o-konceptu.js` at uploadDir root
90
+ * • Nested: `upload/pages/index.js`, `upload/pages/products.js`
91
+ *
92
+ * HTMLs with no matching entry are skipped with a warning. Irregular
93
+ * pairs (e.g. `index.html → app.js`) can be declared explicitly via
94
+ * the `pages` key in nodality.config.json, which bypasses discovery.
95
+ */
96
+ function discoverPages(uploadDir) {
97
+ if (!fs.existsSync(uploadDir)) {
98
+ console.error(`[nodality] uploadDir not found: ${uploadDir}`);
99
+ process.exit(1);
100
+ }
101
+ const htmls = fs
102
+ .readdirSync(uploadDir)
103
+ .filter((f) => f.endsWith(".html"))
104
+ .sort();
105
+
106
+ const pages = [];
107
+ for (const html of htmls) {
108
+ const base = path.basename(html, ".html");
109
+ const candidates = [path.join("pages", `${base}.js`), `${base}.js`];
110
+ let entry = null;
111
+ for (const c of candidates) {
112
+ if (fs.existsSync(path.join(uploadDir, c))) {
113
+ entry = c;
114
+ break;
115
+ }
116
+ }
117
+ if (entry) pages.push({ html, entry });
118
+ else console.warn(`[nodality] ⚠ ${html} skipped — no pages/${base}.js or ${base}.js`);
119
+ }
120
+
121
+ if (pages.length === 0) {
122
+ console.error(`[nodality] No HTML/entry pairs found under ${uploadDir}.`);
123
+ process.exit(1);
124
+ }
125
+ return pages;
126
+ }
127
+
128
+ // ─── prerender subcommand ──────────────────────────────────────
129
+
130
+ async function runPrerender(rawArgs) {
131
+ const cwd = process.cwd();
132
+ const flags = parseFlags(rawArgs);
133
+ const fileConfig = loadConfigFile(cwd);
134
+
135
+ // Flag > config file > default.
136
+ const origin = flags.origin || fileConfig.origin || null;
137
+ const uploadDir = path.resolve(cwd, flags.upload || fileConfig.uploadDir || "upload");
138
+ const defaultLocale = flags["default-locale"] || fileConfig.defaultLocale || null;
139
+ const locales =
140
+ (flags.locales && flags.locales.split(",").map((s) => s.trim())) ||
141
+ fileConfig.locales ||
142
+ null;
143
+ const tolerateAsync =
144
+ flags["tolerate-async"] === true ||
145
+ flags["tolerate-async"] === "true" ||
146
+ fileConfig.tolerateAsyncErrors === true;
147
+
148
+ if (!origin) {
149
+ console.error(`[nodality] --origin not given and no "origin" in nodality.config.json.`);
150
+ process.exit(1);
151
+ }
152
+
153
+ if (tolerateAsync) {
154
+ // Some Nodality animation ops schedule setTimeout callbacks that
155
+ // fire AFTER prerender has serialized the page. When those throw
156
+ // (jsdom realm closed, etc.) a Node default-handler would kill
157
+ // the whole process mid-batch. Demote to warnings so the loop
158
+ // keeps going — same pattern the hand-written prerender.mjs
159
+ // files used in sls3-2025/2026.
160
+ process.on("uncaughtException", (e) =>
161
+ console.warn(`⚠ uncaughtException: ${e.message}`),
162
+ );
163
+ process.on("unhandledRejection", (e) =>
164
+ console.warn(`⚠ unhandledRejection: ${e?.message ?? e}`),
165
+ );
166
+ }
167
+
168
+ // Explicit `pages` from config wins over auto-discovery. The
169
+ // discovery rules (pages/<base>.js, <base>.js) can't infer
170
+ // irregular pairs like h7-nodality's `index.html → app.js`; for
171
+ // those projects the user lists pairs in nodality.config.json.
172
+ const pages =
173
+ Array.isArray(fileConfig.pages) && fileConfig.pages.length
174
+ ? fileConfig.pages
175
+ : discoverPages(uploadDir);
176
+
177
+ // Only the PARENT process prints the banner. In multi-locale fanout
178
+ // each locale runs in a child subprocess that re-enters this same
179
+ // script with NODALITY_SSG_LOCALE set; suppressing the banner there
180
+ // keeps output clean (the parent already prints `── cs ──` separators).
181
+ if (!process.env.NODALITY_SSG_LOCALE) {
182
+ console.log(
183
+ `[nodality] Prerender ${pages.length} page(s) @ ${origin}` +
184
+ (defaultLocale ? ` (default: ${defaultLocale})` : " (single-locale, untagged)"),
185
+ );
186
+ }
187
+
188
+ const config = { origin, uploadDir, pages };
189
+ if (defaultLocale) config.defaultLocale = defaultLocale;
190
+ if (locales) config.locales = locales;
191
+
192
+ await prerenderSite(config);
193
+ }
194
+
195
+ // ─── Dispatch ──────────────────────────────────────────────────
196
+
197
+ async function main() {
198
+ // Subprocess-mode shortcut. `prerenderSite` parallelises locales
199
+ // by spawning `process.argv[1]` (this script) as a child with the
200
+ // NODALITY_SSG_LOCALE env var set but NO CLI args. Without this
201
+ // branch the child would hit showUsage() and exit, killing every
202
+ // locale's render. Re-enter the prerender directly when the env
203
+ // var is present.
204
+ if (process.env.NODALITY_SSG_LOCALE !== undefined) {
205
+ await runPrerender([]);
206
+ return;
207
+ }
208
+
209
+ const [command, ...rest] = process.argv.slice(2);
210
+ if (!command || command === "help" || command === "--help" || command === "-h") {
211
+ showUsage();
212
+ } else if (command === "prerender") {
213
+ await runPrerender(rest);
214
+ } else {
215
+ console.error(`[nodality] Unknown command: ${command}`);
216
+ showUsage();
217
+ }
218
+ }
219
+
220
+ main().catch((err) => {
221
+ console.error(`[nodality] ${err?.message ?? err}`);
222
+ process.exit(1);
223
+ });