nodality 1.0.167 → 1.0.168
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/bin/nodality.js +63 -1
- package/layout/animator.js +1 -1
- package/layout/audio.js +1 -1
- package/layout/audionew.js +1 -1
- package/layout/base-2.js +1 -1
- package/layout/base.js +1 -1
- package/layout/beta-desktop-bar.js +1 -1
- package/layout/beta-mobile-bar.js +1 -1
- package/layout/box.js +1 -1
- package/layout/button.js +1 -1
- package/layout/cards.js +1 -1
- package/layout/center.js +1 -1
- package/layout/checkbox.js +1 -1
- package/layout/circle.js +1 -1
- package/layout/clean-row.js +1 -1
- package/layout/code.js +1 -1
- package/layout/container.js +1 -1
- package/layout/custom.js +1 -1
- package/layout/div-image.js +1 -1
- package/layout/dropdown-2025.js +1 -1
- package/layout/dropdown.js +1 -1
- package/layout/empty-element.js +1 -1
- package/layout/external-stylesheet.js +1 -1
- package/layout/flex-card.js +1 -1
- package/layout/flex-grid.js +1 -1
- package/layout/flex-row.js +1 -1
- package/layout/footer.js +1 -1
- package/layout/form-components/custom.js +1 -1
- package/layout/form-components/data-list.js +1 -1
- package/layout/form-components/floating-input.js +1 -1
- package/layout/form-components/form-all.js +1 -1
- package/layout/form-components/form.js +1 -1
- package/layout/form-components/image-picker.js +1 -1
- package/layout/form-components/picker.js +1 -1
- package/layout/form-components/radio.js +1 -1
- package/layout/form-components/radiogroup.js +1 -1
- package/layout/form-components/range.js +1 -1
- package/layout/free.js +1 -1
- package/layout/grid-new.js +1 -1
- package/layout/grid-switcher.js +1 -1
- package/layout/grid.js +1 -1
- package/layout/group.js +1 -1
- package/layout/header.js +1 -1
- package/layout/horizontal-scroller.js +1 -1
- package/layout/image-old.js +1 -1
- package/layout/image.js +1 -1
- package/layout/index.js +1 -1
- package/layout/label.js +1 -1
- package/layout/link.js +1 -1
- package/layout/list-OLD.js +1 -1
- package/layout/list.js +1 -1
- package/layout/meta-adder.js +1 -1
- package/layout/modal-2025.js +1 -1
- package/layout/modernwrap.js +1 -1
- package/layout/multiswitcher.js +1 -1
- package/layout/multiswitcherBeta.js +1 -1
- package/layout/nav-bar.js +1 -1
- package/layout/nav-factor/custom-div.js +1 -1
- package/layout/navBar-OLD.js +1 -1
- package/layout/new-flat-adder.js +1 -1
- package/layout/new-nav-bar.js +1 -1
- package/layout/offset-container.js +1 -1
- package/layout/polygon.js +1 -1
- package/layout/prerender-site.js +16 -2
- package/layout/prerender.js +15 -5
- package/layout/progress.js +1 -1
- package/layout/row.js +1 -1
- package/layout/saved-new-nav-bar.js +1 -1
- package/layout/scroll-video.js +1 -1
- package/layout/side-bar.js +1 -1
- package/layout/side-nav-bar.js +1 -1
- package/layout/simple-bar.js +1 -1
- package/layout/slider-2025.js +1 -1
- package/layout/spacer.js +1 -1
- package/layout/stack.js +1 -1
- package/layout/styler.js +1 -1
- package/layout/svg.js +1 -1
- package/layout/switcher.js +1 -1
- package/layout/table.js +1 -1
- package/layout/text-field.js +1 -1
- package/layout/text.js +1 -1
- package/layout/ulist.js +1 -1
- package/layout/video.js +1 -1
- package/layout/without-new.js +1 -1
- package/layout/wrap.js +1 -1
- package/layout/zoom-card.js +1 -1
- package/lib/card-getter.js +1 -1
- package/lib/data.js +48 -0
- package/lib/designer.js +1 -1
- package/lib/element-mapper.js +1 -1
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/scroll-video.js +1 -1
- package/lib/seo.js +198 -0
- package/lib/stacker.js +1 -1
- package/lib/theme.js +1 -1
- package/lib/transform-anim.js +1 -1
- 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 {
|
|
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 : [];
|
package/layout/animator.js
CHANGED
package/layout/audio.js
CHANGED
package/layout/audionew.js
CHANGED
package/layout/base-2.js
CHANGED
package/layout/base.js
CHANGED
package/layout/box.js
CHANGED
package/layout/button.js
CHANGED
package/layout/cards.js
CHANGED
package/layout/center.js
CHANGED
package/layout/checkbox.js
CHANGED
package/layout/circle.js
CHANGED
package/layout/clean-row.js
CHANGED
package/layout/code.js
CHANGED
package/layout/container.js
CHANGED
package/layout/custom.js
CHANGED
package/layout/div-image.js
CHANGED
package/layout/dropdown-2025.js
CHANGED
package/layout/dropdown.js
CHANGED
package/layout/empty-element.js
CHANGED
package/layout/flex-card.js
CHANGED
package/layout/flex-grid.js
CHANGED
package/layout/flex-row.js
CHANGED
package/layout/footer.js
CHANGED
package/layout/free.js
CHANGED
package/layout/grid-new.js
CHANGED
package/layout/grid-switcher.js
CHANGED
package/layout/grid.js
CHANGED
package/layout/group.js
CHANGED
package/layout/header.js
CHANGED
package/layout/image-old.js
CHANGED
package/layout/image.js
CHANGED
package/layout/index.js
CHANGED
package/layout/label.js
CHANGED
package/layout/link.js
CHANGED
package/layout/list-OLD.js
CHANGED
package/layout/list.js
CHANGED
package/layout/meta-adder.js
CHANGED
package/layout/modal-2025.js
CHANGED
package/layout/modernwrap.js
CHANGED
package/layout/multiswitcher.js
CHANGED
package/layout/nav-bar.js
CHANGED
package/layout/navBar-OLD.js
CHANGED
package/layout/new-flat-adder.js
CHANGED
package/layout/new-nav-bar.js
CHANGED
package/layout/polygon.js
CHANGED
package/layout/prerender-site.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.0.
|
|
2
|
+
* nodality v1.0.168
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -146,6 +146,16 @@ export async function prerenderSite(config) {
|
|
|
146
146
|
await runChild(config, locale);
|
|
147
147
|
const elapsed = ((Date.now() - startedAt) / 1000).toFixed(1);
|
|
148
148
|
console.log(`✅ Prerender done in ${elapsed}s — ${config.pages.length} page(s)`);
|
|
149
|
+
// Single-locale sitemap (1.0.168+). Earlier versions only wrote
|
|
150
|
+
// a sitemap on multi-locale builds, so single-locale projects had
|
|
151
|
+
// to bolt on their own `scripts/generate-sitemap.mjs`. We now
|
|
152
|
+
// emit on every build unless the caller explicitly opts out
|
|
153
|
+
// with `sitemap: false`. URLs are origin + page.html, lastmod is
|
|
154
|
+
// build time, no hreflang (single locale has nothing to alternate).
|
|
155
|
+
if (config.sitemap !== false) {
|
|
156
|
+
await writeSitemap(config);
|
|
157
|
+
console.log(`✅ Sitemap regenerated — ${config.pages.length} URL(s)`);
|
|
158
|
+
}
|
|
149
159
|
return;
|
|
150
160
|
}
|
|
151
161
|
|
|
@@ -399,6 +409,10 @@ function urlFor(config, locale, page) {
|
|
|
399
409
|
|
|
400
410
|
/** hreflang alternates for one page (all locales + x-default). */
|
|
401
411
|
function alternatesFor(config, page) {
|
|
412
|
+
// Single-locale builds (incl. the implicit untagged-locale case)
|
|
413
|
+
// have nothing to alternate to — emitting `xhtml:link rel="alternate"`
|
|
414
|
+
// with the same URL as the `<loc>` would just clutter the sitemap.
|
|
415
|
+
if (config.locales.length <= 1) return [];
|
|
402
416
|
const xDefault = config.xDefaultLocale || config.defaultLocale;
|
|
403
417
|
const alts = config.locales.map((l) => ({ hreflang: l, href: urlFor(config, l, page) }));
|
|
404
418
|
alts.push({ hreflang: "x-default", href: urlFor(config, xDefault, page) });
|
|
@@ -427,7 +441,7 @@ async function writeSitemap(config) {
|
|
|
427
441
|
` <lastmod>${now}</lastmod>\n` +
|
|
428
442
|
` <changefreq>${changefreq}</changefreq>\n` +
|
|
429
443
|
` <priority>${priority}</priority>\n` +
|
|
430
|
-
altLines + "\n" +
|
|
444
|
+
(altLines ? altLines + "\n" : "") +
|
|
431
445
|
` </url>`
|
|
432
446
|
);
|
|
433
447
|
}
|