nodality 1.0.167 → 1.0.170

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 (106) hide show
  1. package/bin/nodality.js +63 -1
  2. package/dist/bundle.umd.js +2 -1
  3. package/dist/bundle.umd.js.LICENSE.txt +33 -0
  4. package/dist/finalresult.esm.js +2 -1
  5. package/dist/finalresult.esm.js.LICENSE.txt +60 -0
  6. package/dist/index.cjs.js +2 -1
  7. package/dist/index.cjs.js.LICENSE.txt +60 -0
  8. package/dist/index.esm.js +2 -1
  9. package/dist/index.esm.js.LICENSE.txt +60 -0
  10. package/layout/animator.js +1 -1
  11. package/layout/audio.js +1 -1
  12. package/layout/audionew.js +1 -1
  13. package/layout/base-2.js +1 -1
  14. package/layout/base.js +1 -1
  15. package/layout/beta-desktop-bar.js +1 -1
  16. package/layout/beta-mobile-bar.js +1 -1
  17. package/layout/box.js +1 -1
  18. package/layout/button.js +1 -1
  19. package/layout/cards.js +1 -1
  20. package/layout/center.js +1 -1
  21. package/layout/checkbox.js +1 -1
  22. package/layout/circle.js +1 -1
  23. package/layout/clean-row.js +1 -1
  24. package/layout/code.js +1 -1
  25. package/layout/container.js +1 -1
  26. package/layout/custom.js +1 -1
  27. package/layout/div-image.js +1 -1
  28. package/layout/dropdown-2025.js +1 -1
  29. package/layout/dropdown.js +1 -1
  30. package/layout/empty-element.js +1 -1
  31. package/layout/external-stylesheet.js +1 -1
  32. package/layout/flex-card.js +1 -1
  33. package/layout/flex-grid.js +1 -1
  34. package/layout/flex-row.js +1 -1
  35. package/layout/footer.js +1 -1
  36. package/layout/form-components/custom.js +1 -1
  37. package/layout/form-components/data-list.js +1 -1
  38. package/layout/form-components/floating-input.js +1 -1
  39. package/layout/form-components/form-all.js +1 -1
  40. package/layout/form-components/form.js +1 -1
  41. package/layout/form-components/image-picker.js +1 -1
  42. package/layout/form-components/picker.js +1 -1
  43. package/layout/form-components/radio.js +1 -1
  44. package/layout/form-components/radiogroup.js +1 -1
  45. package/layout/form-components/range.js +1 -1
  46. package/layout/free.js +1 -1
  47. package/layout/grid-new.js +1 -1
  48. package/layout/grid-switcher.js +1 -1
  49. package/layout/grid.js +1 -1
  50. package/layout/group.js +1 -1
  51. package/layout/header.js +1 -1
  52. package/layout/horizontal-scroller.js +1 -1
  53. package/layout/image-old.js +1 -1
  54. package/layout/image.js +1 -1
  55. package/layout/index.js +24 -2
  56. package/layout/label.js +1 -1
  57. package/layout/link.js +1 -1
  58. package/layout/list-OLD.js +1 -1
  59. package/layout/list.js +1 -1
  60. package/layout/meta-adder.js +1 -1
  61. package/layout/modal-2025.js +1 -1
  62. package/layout/modernwrap.js +1 -1
  63. package/layout/multiswitcher.js +1 -1
  64. package/layout/multiswitcherBeta.js +1 -1
  65. package/layout/nav-bar.js +1 -1
  66. package/layout/nav-factor/custom-div.js +1 -1
  67. package/layout/navBar-OLD.js +1 -1
  68. package/layout/new-flat-adder.js +1 -1
  69. package/layout/new-nav-bar.js +1 -1
  70. package/layout/offset-container.js +1 -1
  71. package/layout/polygon.js +1 -1
  72. package/layout/prerender-site.js +16 -2
  73. package/layout/prerender.js +15 -5
  74. package/layout/progress.js +1 -1
  75. package/layout/row.js +1 -1
  76. package/layout/saved-new-nav-bar.js +1 -1
  77. package/layout/scroll-video.js +1 -1
  78. package/layout/side-bar.js +1 -1
  79. package/layout/side-nav-bar.js +1 -1
  80. package/layout/simple-bar.js +1 -1
  81. package/layout/slider-2025.js +1 -1
  82. package/layout/spacer.js +1 -1
  83. package/layout/stack.js +1 -1
  84. package/layout/styler.js +1 -1
  85. package/layout/svg.js +1 -1
  86. package/layout/switcher.js +1 -1
  87. package/layout/table.js +1 -1
  88. package/layout/text-field.js +1 -1
  89. package/layout/text.js +1 -1
  90. package/layout/ulist.js +1 -1
  91. package/layout/video.js +1 -1
  92. package/layout/without-new.js +1 -1
  93. package/layout/wrap.js +1 -1
  94. package/layout/zoom-card.js +1 -1
  95. package/lib/card-getter.js +1 -1
  96. package/lib/data.js +43 -0
  97. package/lib/designer.js +1 -1
  98. package/lib/element-mapper.js +1 -1
  99. package/lib/keyframe-animation.js +1 -1
  100. package/lib/link-getter.js +1 -1
  101. package/lib/scroll-video.js +1 -1
  102. package/lib/seo.js +198 -0
  103. package/lib/stacker.js +1 -1
  104. package/lib/theme.js +1 -1
  105. package/lib/transform-anim.js +1 -1
  106. package/package.json +4 -2
package/bin/nodality.js CHANGED
@@ -206,7 +206,22 @@ function runFanout(cwd, uploadDir, fanoutConfig) {
206
206
 
207
207
  let totalWrote = 0;
208
208
  for (const spec of fanoutConfig) {
209
- const { template, data, items, id = "id", title, entry, bodyAttr = "data-product-id" } = spec;
209
+ const {
210
+ template, data, items, id = "id", title, entry,
211
+ bodyAttr = "data-product-id",
212
+ // ─── Auto-injected JSON-LD per item (1.0.168+) ─────────
213
+ // When `jsonLdType` is set, fanout emits a
214
+ // `<script type="application/ld+json" data-seo="1">` block per
215
+ // generated HTML with the right schema.org type and fields
216
+ // mapped from each item. Saves projects from importing
217
+ // nodality/seo and calling productJsonLd() by hand inside the
218
+ // page entry — useful because the page entry runs LATE (after
219
+ // the static HTML is already served) so crawlers that don't
220
+ // execute JS miss any client-injected structured data.
221
+ jsonLdType, // e.g. "Product" | "Article"
222
+ jsonLdFields, // map of schema-key → dot-path on item (e.g. { name: "name", image: "images.0", sku: "id" })
223
+ jsonLdExtra, // static fields to add verbatim (e.g. { brand: { "@type": "Brand", name: "SLS3" }, priceCurrency: "CZK" })
224
+ } = spec;
210
225
  if (!template || !data) {
211
226
  console.warn(`[nodality] fanout: skipping spec without template/data`);
212
227
  continue;
@@ -292,6 +307,18 @@ function runFanout(cwd, uploadDir, fanoutConfig) {
292
307
  );
293
308
  html = html.replace(srcRx, `$1$2${entryBase}-${itemId}.js$3`);
294
309
 
310
+ // Auto-injected JSON-LD per item, if the spec asked for it.
311
+ // Inserted inside <head> (before </head>) so crawlers see it
312
+ // without executing the page entry — critical for Bing /
313
+ // social-card scrapers / non-Google crawlers that don't run JS.
314
+ if (jsonLdType && jsonLdFields) {
315
+ const ld = buildItemJsonLd(jsonLdType, jsonLdFields, jsonLdExtra, item);
316
+ const tag = `<script type="application/ld+json" data-seo="1">${
317
+ JSON.stringify(ld)
318
+ }</script>`;
319
+ html = html.replace(/<\/head>/i, `${tag}\n</head>`);
320
+ }
321
+
295
322
  fs.writeFileSync(path.join(uploadDir, `${base}-${itemId}.html`), html);
296
323
 
297
324
  // JS wrapper. The user's entry must export an async function
@@ -335,6 +362,41 @@ await fn(${JSON.stringify(String(itemId))});
335
362
  return totalWrote;
336
363
  }
337
364
 
365
+ /**
366
+ * Look up a dot/bracket path on a single item, e.g. "images.0" or
367
+ * "sizing.sizes.0.range". Returns undefined for missing branches.
368
+ * Used by fanout's per-item JSON-LD field mapper.
369
+ */
370
+ function getByPath(obj, path) {
371
+ if (obj == null || !path) return undefined;
372
+ const parts = String(path).split(".");
373
+ let acc = obj;
374
+ for (const p of parts) {
375
+ if (acc == null) return undefined;
376
+ acc = acc[p];
377
+ }
378
+ return acc;
379
+ }
380
+
381
+ /**
382
+ * Build a schema.org JSON-LD object for one fanout item. `fields`
383
+ * maps schema-key → dot-path on the item; `extra` is merged in
384
+ * verbatim (static fields like brand, priceCurrency, "@context").
385
+ */
386
+ function buildItemJsonLd(type, fields, extra, item) {
387
+ const out = { "@context": "https://schema.org", "@type": type };
388
+ for (const [key, fieldPath] of Object.entries(fields || {})) {
389
+ const v = getByPath(item, fieldPath);
390
+ if (v !== undefined && v !== null && v !== "") out[key] = v;
391
+ }
392
+ if (extra && typeof extra === "object") {
393
+ for (const [k, v] of Object.entries(extra)) {
394
+ if (v !== undefined) out[k] = v;
395
+ }
396
+ }
397
+ return out;
398
+ }
399
+
338
400
  /** Resolve a dot-path with `[]` segments to an array of items. */
339
401
  function resolveItemsPath(data, path) {
340
402
  if (!path) return Array.isArray(data) ? data : [];