nodality 1.0.149 → 1.0.151
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/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.js +122 -3
- 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/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/stacker.js +1 -1
- package/lib/theme.js +1 -1
- package/lib/transform-anim.js +1 -1
- package/package.json +1 -1
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.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.0.
|
|
2
|
+
* nodality v1.0.151
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -120,6 +120,9 @@ export async function prerender({
|
|
|
120
120
|
localStorageKey = "h7lang",
|
|
121
121
|
url = "http://localhost/",
|
|
122
122
|
viewport = { width: 390, height: 844 },
|
|
123
|
+
htmlLang,
|
|
124
|
+
canonical,
|
|
125
|
+
alternates,
|
|
123
126
|
build,
|
|
124
127
|
output,
|
|
125
128
|
}) {
|
|
@@ -334,6 +337,112 @@ export async function prerender({
|
|
|
334
337
|
// promise-based for full coverage.
|
|
335
338
|
await new Promise((resolve) => setImmediate(resolve));
|
|
336
339
|
|
|
340
|
+
// ─── Cleanup pass: dedupe styles + strip body noise ─────────────
|
|
341
|
+
//
|
|
342
|
+
// Nodality's components have render-time side effects that
|
|
343
|
+
// accumulate during the prerender build:
|
|
344
|
+
//
|
|
345
|
+
// • Each section calling .render("#mount") injects its own
|
|
346
|
+
// <style> tag into <head>. The same `.hiw-card` block ends
|
|
347
|
+
// up duplicated once per section that uses those classes.
|
|
348
|
+
//
|
|
349
|
+
// • Dropdown.render() appends its floating panel
|
|
350
|
+
// (`this.contentWrap`) directly to `document.body`, OUTSIDE
|
|
351
|
+
// `#mount`. Each render call appends another copy. With
|
|
352
|
+
// Switcher rendering both mobile + desktop variants, plus
|
|
353
|
+
// repeated render() invocations across the build, you can
|
|
354
|
+
// end up with 10+ identical hidden dropdowns.
|
|
355
|
+
//
|
|
356
|
+
// • Modal components do the same thing — fixed-position
|
|
357
|
+
// overlays appended to body.
|
|
358
|
+
//
|
|
359
|
+
// None of this duplication is needed in the static output. The
|
|
360
|
+
// crawler-relevant content all lives INSIDE #mount. The floating
|
|
361
|
+
// panels are JS-driven UI that the browser recreates fresh when
|
|
362
|
+
// the runtime clear-mount script fires + app.js re-renders.
|
|
363
|
+
//
|
|
364
|
+
// So: dedupe <style> tags by text content and remove every
|
|
365
|
+
// body child that isn't #mount. Cuts the prerender output
|
|
366
|
+
// roughly in half without changing what's visible to crawlers
|
|
367
|
+
// or to real users.
|
|
368
|
+
|
|
369
|
+
// Dedupe identical <style> tags. Keep the first occurrence,
|
|
370
|
+
// remove subsequent ones with the same textContent.
|
|
371
|
+
{
|
|
372
|
+
const seen = new Set();
|
|
373
|
+
for (const style of window.document.head.querySelectorAll("style")) {
|
|
374
|
+
const key = style.textContent || "";
|
|
375
|
+
if (seen.has(key)) {
|
|
376
|
+
style.remove();
|
|
377
|
+
} else {
|
|
378
|
+
seen.add(key);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Strip every body child except #mount (or whichever element
|
|
384
|
+
// matches the `mount` selector) and the runtime <script> tags.
|
|
385
|
+
// Floating dropdowns, modals, tooltips, etc. — all appended to
|
|
386
|
+
// body by their respective render()s — get evicted here.
|
|
387
|
+
if (mount) {
|
|
388
|
+
const mountEl = window.document.querySelector(mount);
|
|
389
|
+
const body = window.document.body;
|
|
390
|
+
const keepers = new Set();
|
|
391
|
+
if (mountEl) keepers.add(mountEl);
|
|
392
|
+
// Keep all <script> tags so the runtime entries (app.js,
|
|
393
|
+
// cookie-consent.js, the clear-mount inline) survive.
|
|
394
|
+
for (const s of body.querySelectorAll(":scope > script")) keepers.add(s);
|
|
395
|
+
// Keep GTM noscript iframe + any other <noscript> fallbacks.
|
|
396
|
+
for (const n of body.querySelectorAll(":scope > noscript")) keepers.add(n);
|
|
397
|
+
// Remove every direct child that wasn't whitelisted.
|
|
398
|
+
for (const child of Array.from(body.children)) {
|
|
399
|
+
if (!keepers.has(child)) child.remove();
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// ─── SEO head injection ─────────────────────────────────────────
|
|
404
|
+
//
|
|
405
|
+
// Inject per-locale `<html lang>`, `<link rel="canonical">`, and
|
|
406
|
+
// `<link rel="alternate" hreflang>` tags so search engines and
|
|
407
|
+
// social-share crawlers can attribute each prerendered file to
|
|
408
|
+
// its correct language and prevent duplicate-content rank
|
|
409
|
+
// collapse across locales.
|
|
410
|
+
//
|
|
411
|
+
// Doing this at the library level (rather than the consumer
|
|
412
|
+
// template) keeps every SSG site that uses `nodality/ssg`
|
|
413
|
+
// SEO-complete without each consumer reinventing the boilerplate.
|
|
414
|
+
|
|
415
|
+
if (htmlLang) {
|
|
416
|
+
window.document.documentElement.setAttribute("lang", htmlLang);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (canonical) {
|
|
420
|
+
// Remove any prior <link rel="canonical"> from the template so
|
|
421
|
+
// we don't end up with two competing canonicals after re-runs.
|
|
422
|
+
const prior = window.document.head.querySelector('link[rel="canonical"]');
|
|
423
|
+
if (prior) prior.remove();
|
|
424
|
+
const link = window.document.createElement("link");
|
|
425
|
+
link.setAttribute("rel", "canonical");
|
|
426
|
+
link.setAttribute("href", canonical);
|
|
427
|
+
window.document.head.appendChild(link);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (Array.isArray(alternates) && alternates.length > 0) {
|
|
431
|
+
// Strip prior hreflang alternates so successive prerender runs
|
|
432
|
+
// produce byte-identical output (idempotent build).
|
|
433
|
+
for (const el of window.document.head.querySelectorAll('link[rel="alternate"][hreflang]')) {
|
|
434
|
+
el.remove();
|
|
435
|
+
}
|
|
436
|
+
for (const alt of alternates) {
|
|
437
|
+
if (!alt || !alt.hreflang || !alt.href) continue;
|
|
438
|
+
const link = window.document.createElement("link");
|
|
439
|
+
link.setAttribute("rel", "alternate");
|
|
440
|
+
link.setAttribute("hreflang", alt.hreflang);
|
|
441
|
+
link.setAttribute("href", alt.href);
|
|
442
|
+
window.document.head.appendChild(link);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
337
446
|
// ─── Hydration handoff ──────────────────────────────────────────
|
|
338
447
|
//
|
|
339
448
|
// The runtime <script> tags from the template still load in the
|
|
@@ -359,6 +468,17 @@ export async function prerender({
|
|
|
359
468
|
// every consumer would each need the same boilerplate. Doing it
|
|
360
469
|
// here, once, keeps consumers untouched.
|
|
361
470
|
if (mount) {
|
|
471
|
+
const expectedClearBody =
|
|
472
|
+
`(function(){var m=document.querySelector(${JSON.stringify(mount)});if(m)m.innerHTML='';})();`;
|
|
473
|
+
|
|
474
|
+
// Remove any pre-existing clear-mount scripts (left over from
|
|
475
|
+
// a prior prerender run that read this same file as its
|
|
476
|
+
// template). Without this, each successive build adds another
|
|
477
|
+
// copy and the inline script section bloats.
|
|
478
|
+
for (const s of window.document.querySelectorAll("body > script:not([src]):not([type])")) {
|
|
479
|
+
if (s.textContent === expectedClearBody) s.remove();
|
|
480
|
+
}
|
|
481
|
+
|
|
362
482
|
const firstRuntimeScript = window.document.querySelector(
|
|
363
483
|
'body script[type="module"][src], body script[src][type="module"]'
|
|
364
484
|
);
|
|
@@ -368,8 +488,7 @@ export async function prerender({
|
|
|
368
488
|
// before any module scripts begin loading. Module scripts
|
|
369
489
|
// are always deferred, so the clear runs in the right order
|
|
370
490
|
// regardless of where it sits in the DOM relative to them.
|
|
371
|
-
clearScript.textContent =
|
|
372
|
-
`(function(){var m=document.querySelector(${JSON.stringify(mount)});if(m)m.innerHTML='';})();`;
|
|
491
|
+
clearScript.textContent = expectedClearBody;
|
|
373
492
|
firstRuntimeScript.parentNode.insertBefore(clearScript, firstRuntimeScript);
|
|
374
493
|
}
|
|
375
494
|
}
|
package/layout/progress.js
CHANGED
package/layout/row.js
CHANGED
package/layout/scroll-video.js
CHANGED
package/layout/side-bar.js
CHANGED
package/layout/side-nav-bar.js
CHANGED
package/layout/simple-bar.js
CHANGED
package/layout/slider-2025.js
CHANGED
package/layout/spacer.js
CHANGED
package/layout/stack.js
CHANGED
package/layout/styler.js
CHANGED
package/layout/svg.js
CHANGED
package/layout/switcher.js
CHANGED
package/layout/table.js
CHANGED
package/layout/text-field.js
CHANGED
package/layout/text.js
CHANGED
package/layout/ulist.js
CHANGED
package/layout/video.js
CHANGED
package/layout/without-new.js
CHANGED
package/layout/wrap.js
CHANGED
package/layout/zoom-card.js
CHANGED
package/lib/card-getter.js
CHANGED
package/lib/designer.js
CHANGED
package/lib/element-mapper.js
CHANGED
package/lib/link-getter.js
CHANGED
package/lib/scroll-video.js
CHANGED
package/lib/stacker.js
CHANGED
package/lib/theme.js
CHANGED
package/lib/transform-anim.js
CHANGED