nodality 1.0.161 → 1.0.163

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 (102) hide show
  1. package/bin/nodality.js +180 -0
  2. package/dist/bundle.umd.js +1 -1
  3. package/dist/designer.cjs.js +1 -1
  4. package/dist/designer.esm.js +1 -1
  5. package/dist/finalresult.esm.js +1 -1
  6. package/dist/index.cjs.js +1 -1
  7. package/dist/index.esm.js +1 -1
  8. package/layout/animator.js +1 -1
  9. package/layout/audio.js +1 -1
  10. package/layout/audionew.js +1 -1
  11. package/layout/base-2.js +1 -1
  12. package/layout/base.js +1 -1
  13. package/layout/beta-desktop-bar.js +1 -1
  14. package/layout/beta-mobile-bar.js +1 -1
  15. package/layout/box.js +1 -1
  16. package/layout/button.js +1 -1
  17. package/layout/cards.js +1 -1
  18. package/layout/center.js +1 -1
  19. package/layout/checkbox.js +1 -1
  20. package/layout/circle.js +1 -1
  21. package/layout/clean-row.js +1 -1
  22. package/layout/code.js +1 -1
  23. package/layout/container.js +1 -1
  24. package/layout/custom.js +1 -1
  25. package/layout/div-image.js +1 -1
  26. package/layout/dropdown-2025.js +1 -1
  27. package/layout/dropdown.js +1 -1
  28. package/layout/empty-element.js +1 -1
  29. package/layout/external-stylesheet.js +1 -1
  30. package/layout/flex-card.js +1 -1
  31. package/layout/flex-grid.js +1 -1
  32. package/layout/flex-row.js +1 -1
  33. package/layout/footer.js +1 -1
  34. package/layout/form-components/custom.js +1 -1
  35. package/layout/form-components/data-list.js +1 -1
  36. package/layout/form-components/floating-input.js +1 -1
  37. package/layout/form-components/form-all.js +1 -1
  38. package/layout/form-components/form.js +1 -1
  39. package/layout/form-components/image-picker.js +1 -1
  40. package/layout/form-components/picker.js +1 -1
  41. package/layout/form-components/radio.js +1 -1
  42. package/layout/form-components/radiogroup.js +1 -1
  43. package/layout/form-components/range.js +1 -1
  44. package/layout/free.js +1 -1
  45. package/layout/grid-new.js +1 -1
  46. package/layout/grid-switcher.js +1 -1
  47. package/layout/grid.js +1 -1
  48. package/layout/group.js +1 -1
  49. package/layout/header.js +1 -1
  50. package/layout/horizontal-scroller.js +1 -1
  51. package/layout/image-old.js +1 -1
  52. package/layout/image.js +1 -1
  53. package/layout/index.js +1 -1
  54. package/layout/label.js +1 -1
  55. package/layout/link.js +1 -1
  56. package/layout/list-OLD.js +1 -1
  57. package/layout/list.js +1 -1
  58. package/layout/meta-adder.js +1 -1
  59. package/layout/modal-2025.js +1 -1
  60. package/layout/modernwrap.js +1 -1
  61. package/layout/multiswitcher.js +1 -1
  62. package/layout/multiswitcherBeta.js +1 -1
  63. package/layout/nav-bar.js +1 -1
  64. package/layout/nav-factor/custom-div.js +1 -1
  65. package/layout/navBar-OLD.js +1 -1
  66. package/layout/new-flat-adder.js +1 -1
  67. package/layout/new-nav-bar.js +1 -1
  68. package/layout/offset-container.js +1 -1
  69. package/layout/polygon.js +1 -1
  70. package/layout/prerender-site.js +1 -1
  71. package/layout/prerender.js +1 -1
  72. package/layout/progress.js +1 -1
  73. package/layout/row.js +1 -1
  74. package/layout/saved-new-nav-bar.js +1 -1
  75. package/layout/scroll-video.js +1 -1
  76. package/layout/side-bar.js +1 -1
  77. package/layout/side-nav-bar.js +1 -1
  78. package/layout/simple-bar.js +1 -1
  79. package/layout/slider-2025.js +1 -1
  80. package/layout/spacer.js +1 -1
  81. package/layout/stack.js +1 -1
  82. package/layout/styler.js +1 -1
  83. package/layout/svg.js +1 -1
  84. package/layout/switcher.js +1 -1
  85. package/layout/table.js +1 -1
  86. package/layout/text-field.js +1 -1
  87. package/layout/text.js +1 -1
  88. package/layout/ulist.js +1 -1
  89. package/layout/video.js +1 -1
  90. package/layout/without-new.js +1 -1
  91. package/layout/wrap.js +1 -1
  92. package/layout/zoom-card.js +1 -1
  93. package/lib/card-getter.js +1 -1
  94. package/lib/designer.js +10 -1
  95. package/lib/element-mapper.js +1 -1
  96. package/lib/keyframe-animation.js +1 -1
  97. package/lib/link-getter.js +1 -1
  98. package/lib/scroll-video.js +1 -1
  99. package/lib/stacker.js +1 -1
  100. package/lib/theme.js +1 -1
  101. package/lib/transform-anim.js +1 -1
  102. package/package.json +1 -1
package/bin/nodality.js CHANGED
@@ -47,14 +47,88 @@ Prerender flags (all optional; fall through to nodality.config.json, then defaul
47
47
  --tolerate-async Install uncaught/unhandledRejection handlers so a single page's
48
48
  late throw (from a deferred animation/fetch timer) doesn't abort
49
49
  the whole batch — useful for sites with span-animation entries.
50
+ --verbose Print every console.log() emitted by the library during render.
51
+ Default is quiet — only progress lines, page sizes, and the
52
+ final summary are shown. Use this when debugging.
50
53
 
51
54
  Examples:
52
55
  nodality prerender
53
56
  nodality prerender --origin=https://example.com --tolerate-async
57
+ nodality prerender --verbose
54
58
  `);
55
59
  process.exit(1);
56
60
  }
57
61
 
62
+ /**
63
+ * Install a stdout filter that hides the library's internal debug
64
+ * chatter (OGA, MBO, BRIS, APPENDED-, 0P, TAGS SET, date stamps, raw
65
+ * object dumps, "Appending brand:" lines, etc.) during prerender.
66
+ * Progress banners from `prerenderSite` (page-name lines, `→ … KB`,
67
+ * `✅ Prerender done`) and our own `[nodality] …` banner pass through
68
+ * unmodified.
69
+ *
70
+ * Bypassed with --verbose (or NODALITY_VERBOSE=1) when you need the
71
+ * full chatter to debug a render that silently goes wrong.
72
+ *
73
+ * We hook process.stdout.write (not console.log) because the library
74
+ * has 100+ scattered console.log calls across 30 files, AND because
75
+ * jsdom's virtual console forwards differently than expected, AND
76
+ * because some output uses process.stdout.write directly. Filtering
77
+ * at the byte stream catches every path uniformly.
78
+ */
79
+ function installLogFilter() {
80
+ const origWrite = process.stdout.write.bind(process.stdout);
81
+
82
+ // Strict whitelist: only lines matching one of these patterns
83
+ // survive. Everything else (dev markers, object dumps, stack traces
84
+ // from page scripts, HTML fragments leaking out of jsdom, media-
85
+ // query strings, date stamps, …) is dropped.
86
+ const ALLOW = [
87
+ /^\[nodality\]/, // our CLI banner
88
+ /^🌍/, // prerenderSite progress banner
89
+ /^✅/, /^❌/, /^⚠/, // status emojis
90
+ /^── /, // locale separators
91
+ /^ [a-z0-9\-]+\.html\s/, // page progress: " index.html ..."
92
+ /^→ /, // result lines
93
+ /^$/, // blank lines (preserve spacing)
94
+ ];
95
+
96
+ function shouldDropLine(line) {
97
+ for (const rx of ALLOW) if (rx.test(line)) return false;
98
+ return true;
99
+ }
100
+
101
+ // Buffer partial lines so we can decide on line boundaries.
102
+ let buf = "";
103
+
104
+ process.stdout.write = function (chunk, encoding, cb) {
105
+ const s = typeof chunk === "string" ? chunk : chunk?.toString?.(encoding || "utf8") ?? "";
106
+ buf += s;
107
+
108
+ let out = "";
109
+ let nl;
110
+ while ((nl = buf.indexOf("\n")) !== -1) {
111
+ const line = buf.slice(0, nl);
112
+ buf = buf.slice(nl + 1);
113
+ if (!shouldDropLine(line)) out += line + "\n";
114
+ }
115
+
116
+ // A trailing buffer with no newline is a progress write like
117
+ // ` index.html ` from prerender-site.js. Pass it
118
+ // through so the user sees progress before the line completes.
119
+ // We only do this when the buffered fragment passes the page-
120
+ // progress check; otherwise hold until newline.
121
+ if (buf && /^ [a-z0-9\-]+\.html\s/.test(buf)) {
122
+ out += buf;
123
+ buf = "";
124
+ }
125
+
126
+ if (out) origWrite(out, encoding, cb);
127
+ else if (cb) cb();
128
+ return true;
129
+ };
130
+ }
131
+
58
132
  // ─── Flag parsing — minimal, no deps ────────────────────────────
59
133
 
60
134
  function parseFlags(argv) {
@@ -81,6 +155,90 @@ function loadConfigFile(cwd) {
81
155
  }
82
156
  }
83
157
 
158
+ // ─── SSG bootstrap ──────────────────────────────────────────────
159
+
160
+ /**
161
+ * On first run, derive the upload/ structure from the project's root
162
+ * files so a freshly scaffolded project can prerender without manual
163
+ * setup. For each `src/<name>.js` we generate `upload/pages/<name>.js`
164
+ * (verbatim copy) and an `upload/<name>.html` whose importmap points
165
+ * at `./lib.bundle.js` and whose `<script src>` points at the page
166
+ * entry. The first src file (alphabetically) is also written as
167
+ * `upload/index.html` when no explicit index entry exists, so the
168
+ * dev server has a default landing page.
169
+ *
170
+ * If the user has already populated upload/ themselves, we touch
171
+ * nothing. Bootstrap only runs when upload/ is missing OR contains
172
+ * no .html files.
173
+ */
174
+ function bootstrapUpload(cwd, uploadDir) {
175
+ const srcDir = path.join(cwd, "src");
176
+ if (!fs.existsSync(srcDir)) return false;
177
+
178
+ const srcFiles = fs.readdirSync(srcDir).filter((f) => f.endsWith(".js"));
179
+ if (srcFiles.length === 0) return false;
180
+
181
+ fs.mkdirSync(uploadDir, { recursive: true });
182
+ const pagesDir = path.join(uploadDir, "pages");
183
+ fs.mkdirSync(pagesDir, { recursive: true });
184
+
185
+ const projectName = path.basename(cwd);
186
+ let wrote = 0;
187
+ for (const srcFile of srcFiles) {
188
+ const base = path.basename(srcFile, ".js");
189
+ // Convention: src/app.js → upload/index.html + upload/pages/index.js.
190
+ // All others: src/<name>.js → upload/<name>.html + upload/pages/<name>.js.
191
+ const pageName = base === "app" ? "index" : base;
192
+
193
+ const entryPath = path.join(pagesDir, `${pageName}.js`);
194
+ if (!fs.existsSync(entryPath)) {
195
+ fs.copyFileSync(path.join(srcDir, srcFile), entryPath);
196
+ wrote++;
197
+ }
198
+
199
+ const htmlPath = path.join(uploadDir, `${pageName}.html`);
200
+ if (!fs.existsSync(htmlPath)) {
201
+ fs.writeFileSync(htmlPath, renderUploadHtml(projectName, pageName));
202
+ wrote++;
203
+ }
204
+ }
205
+
206
+ if (wrote > 0) {
207
+ console.log(`[nodality] Bootstrapped upload/ from src/ (${wrote} file(s) written)`);
208
+ }
209
+
210
+ if (!fs.existsSync(path.join(uploadDir, "lib.bundle.js"))) {
211
+ console.warn(
212
+ `[nodality] ⚠ upload/lib.bundle.js missing — run \`npm run build\` first ` +
213
+ `so the prerendered HTML can load the library bundle at runtime.`,
214
+ );
215
+ }
216
+ return true;
217
+ }
218
+
219
+ function renderUploadHtml(projectName, pageName) {
220
+ return `<!DOCTYPE html>
221
+ <html lang="en">
222
+ <head>
223
+ <meta charset="UTF-8">
224
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
225
+ <title>${projectName}</title>
226
+ <script type="importmap">
227
+ {
228
+ "imports": {
229
+ "nodality": "./lib.bundle.js"
230
+ }
231
+ }
232
+ </script>
233
+ </head>
234
+ <body>
235
+ <div id="mount"></div>
236
+ <script type="module" src="./pages/${pageName}.js"></script>
237
+ </body>
238
+ </html>
239
+ `;
240
+ }
241
+
84
242
  // ─── Page auto-discovery ────────────────────────────────────────
85
243
 
86
244
  /**
@@ -145,6 +303,18 @@ async function runPrerender(rawArgs) {
145
303
  flags["tolerate-async"] === "true" ||
146
304
  fileConfig.tolerateAsyncErrors === true;
147
305
 
306
+ // Quiet by default; --verbose or NODALITY_VERBOSE=1 turns the
307
+ // library's internal chatter back on. Only install the filter once
308
+ // (the multi-locale fanout re-enters this function in the parent
309
+ // process for the no-locales path, but on the child path
310
+ // NODALITY_SSG_LOCALE is set and we still want the filter on).
311
+ const verbose =
312
+ flags.verbose === true ||
313
+ flags.verbose === "true" ||
314
+ process.env.NODALITY_VERBOSE === "1" ||
315
+ fileConfig.verbose === true;
316
+ if (!verbose) installLogFilter();
317
+
148
318
  if (!origin) {
149
319
  console.error(`[nodality] --origin not given and no "origin" in nodality.config.json.`);
150
320
  process.exit(1);
@@ -165,6 +335,16 @@ async function runPrerender(rawArgs) {
165
335
  );
166
336
  }
167
337
 
338
+ // First-run bootstrap: if upload/ is missing or has no HTML pages
339
+ // yet, derive it from the project's src/ + root index.html. This is
340
+ // what create-nodality projects rely on so the scaffolder doesn't
341
+ // have to ship duplicate copies of source files. No-op if upload/
342
+ // is already populated.
343
+ const needsBootstrap =
344
+ !fs.existsSync(uploadDir) ||
345
+ fs.readdirSync(uploadDir).filter((f) => f.endsWith(".html")).length === 0;
346
+ if (needsBootstrap) bootstrapUpload(cwd, uploadDir);
347
+
168
348
  // Explicit `pages` from config wins over auto-discovery. The
169
349
  // discovery rules (pages/<base>.js, <base>.js) can't infer
170
350
  // irregular pairs like h7-nodality's `index.html → app.js`; for