mikser-io-layouts 2.12.0 → 2.13.0

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 (2) hide show
  1. package/index.js +33 -3
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -245,12 +245,13 @@ export function layouts(userOptions = {}) {
245
245
  //
246
246
  // Two components:
247
247
  // own — the layout's own sidecar, `<name>.js`
248
- // shared — every OTHER .js under the folder, as one digest
248
+ // shared — ALL sidecar scripts under the folder, as one digest
249
+ // (its own included; `own` just names it separately)
249
250
  //
250
251
  // `shared` is coarse on purpose: a sidecar's own imports
251
252
  // (layouts/lib/context.js and friends) would otherwise need a module
252
- // graph walk. Treating any shared .js change as invalidating every
253
- // layout is what the folder can afford — tens of files, not
253
+ // graph walk. One global digest means any sidecar change invalidates
254
+ // EVERY layout, which is what the folder can afford — tens of files, not
254
255
  // thousands — and it is predictable, which a partial graph walk
255
256
  // would not be.
256
257
  // NOT every .js under the folder is a sidecar. `post.hbs.js` is a
@@ -380,6 +381,35 @@ export function layouts(userOptions = {}) {
380
381
  },
381
382
  }
382
383
  Object.assign(layout, await getFormatInfo(relativePath))
384
+
385
+ // Two files can resolve to ONE layout name, and this map is
386
+ // keyed by name — so the second one silently replaced the
387
+ // first and which one won depended on scan order.
388
+ //
389
+ // getFormatInfo strips the whole compound extension:
390
+ // sitemap.xml.liquid, sitemap.liquid and sitemap.xml.js are
391
+ // all named `sitemap`. A document asking for `layout: sitemap`
392
+ // then got whichever landed last, and if that was a `js`
393
+ // template it rendered nothing — no error, no warning, the
394
+ // build green and the page absent. Reported from a real
395
+ // migration, where the same shape worked for one layout and
396
+ // not another and no rule could be found, because the rule was
397
+ // directory order.
398
+ //
399
+ // Not resolved here, because picking a winner would be
400
+ // guessing at intent. Said out loud instead, naming both
401
+ // files, which is the thing that was missing.
402
+ const clash = layouts[layout.name]
403
+ if (clash && clash.id !== layout.id) {
404
+ logger.warn(
405
+ { code: 'layout-name-collision', name: layout.name, files: [clash.uri, layout.uri] },
406
+ 'Layouts %j is claimed by two files — %s and %s. Both reduce to the same layout name, '
407
+ + 'so one replaces the other and which one wins is directory order. A document asking '
408
+ + 'for this layout may render with the wrong template, or with a `js` template that '
409
+ + 'emits nothing at all. Rename one of them.',
410
+ layout.name, clash.uri, layout.uri)
411
+ }
412
+
383
413
  layouts[layout.name] = layout
384
414
  await createEntity(layout)
385
415
  stats.emitted++
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mikser-io-layouts",
3
- "version": "2.12.0",
3
+ "version": "2.13.0",
4
4
  "description": "SSG-flavor task-production policy for mikser-io. Multi-match layout assignment, per-layout destinations, postprocess chain attachment, layout inspection.",
5
5
  "main": "index.js",
6
6
  "type": "module",