mikser-io 9.14.0 → 9.15.1
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/index.js +15 -6
- package/package.json +1 -1
- package/src/manifest.js +16 -0
- package/src/plugins/render/asset.js +2 -2
- package/src/plugins/render/file.js +1 -1
- package/src/plugins/render/href.js +2 -2
- package/src/plugins/render/preset.js +4 -5
- package/src/plugins/render/resource.js +2 -2
- package/src/render.js +20 -2
- package/src/track.js +29 -1
package/index.js
CHANGED
|
@@ -45,9 +45,18 @@ export { yaml } from './src/plugins/yaml.js'
|
|
|
45
45
|
// loader stores in `runtime.renderers`; the same module also still
|
|
46
46
|
// exports `load`/`render` at the top level so Piscina worker dispatch
|
|
47
47
|
// can resolve via dynamic import. ADR-0010.
|
|
48
|
-
|
|
49
|
-
export {
|
|
50
|
-
export {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
// Renderers — these have a render() and turn an entity into a file.
|
|
49
|
+
export { renderHbs } from './src/plugins/render/hbs.js'
|
|
50
|
+
export { renderPreset } from './src/plugins/render/preset.js'
|
|
51
|
+
|
|
52
|
+
// Template helpers — these only install functions on `runtime` for templates
|
|
53
|
+
// to call. They render nothing, which is what the old render* names hid: two
|
|
54
|
+
// of the six factories in this folder are renderers and four are not, and
|
|
55
|
+
// naming all six after the object they concern rather than the job they do
|
|
56
|
+
// led someone to add renderPreset() expecting a helper and watch every page
|
|
57
|
+
// render throw. Renamed in 10.0.0; there are no aliases.
|
|
58
|
+
export { assetUrlHelper } from './src/plugins/render/asset.js'
|
|
59
|
+
export { hrefUrlHelpers } from './src/plugins/render/href.js'
|
|
60
|
+
export { resourceUrlHelper } from './src/plugins/render/resource.js'
|
|
61
|
+
export { fileHelpers } from './src/plugins/render/file.js'
|
|
62
|
+
|
package/package.json
CHANGED
package/src/manifest.js
CHANGED
|
@@ -440,6 +440,22 @@ export function createManifest(db) {
|
|
|
440
440
|
})
|
|
441
441
|
}
|
|
442
442
|
}
|
|
443
|
+
if (track?.lookups) {
|
|
444
|
+
for (const target of track.lookups) {
|
|
445
|
+
// findById is extension-tolerant and also resolves a
|
|
446
|
+
// meta.href, so the hash is the resolved entity's when
|
|
447
|
+
// there is one. No hash means "nothing resolved" —
|
|
448
|
+
// shouldSkip treats a hashless edge whose target mutated
|
|
449
|
+
// as a re-render, which is what should happen when a page
|
|
450
|
+
// that was linked-to-but-missing finally appears.
|
|
451
|
+
const resolved = findById(target)
|
|
452
|
+
edges.push({
|
|
453
|
+
kind: 'lookup',
|
|
454
|
+
target,
|
|
455
|
+
hash: resolved ? inputHashOf(resolved) : undefined,
|
|
456
|
+
})
|
|
457
|
+
}
|
|
458
|
+
}
|
|
443
459
|
if (track?.queries) {
|
|
444
460
|
for (const filter of track.queries) {
|
|
445
461
|
edges.push({ kind: 'query', filter })
|
|
@@ -41,6 +41,6 @@ export function load({ entity, runtime, options }) {
|
|
|
41
41
|
runtime.next = entity.page + 1 < entity.pages ? entity.page + 1 : false
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export function
|
|
44
|
+
export function hrefUrlHelpers(options = {}) {
|
|
45
45
|
return { name: options.name ?? 'href', options, load }
|
|
46
|
-
}
|
|
46
|
+
}
|
|
@@ -2,7 +2,7 @@ import { mkdir } from 'node:fs/promises'
|
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
|
|
4
4
|
// A renderer's `load` runs for EVERY entity in the cycle, not only the ones
|
|
5
|
-
// this renderer will render — that is deliberate and is how
|
|
5
|
+
// this renderer will render — that is deliberate and is how assetUrlHelper
|
|
6
6
|
// installs runtime.asset() for all templates. So this has to tolerate an
|
|
7
7
|
// entity that has no preset, rather than assume it is looking at one.
|
|
8
8
|
//
|
|
@@ -11,13 +11,12 @@ import path from 'node:path'
|
|
|
11
11
|
// "you have found something real", which is a much more expensive wrong
|
|
12
12
|
// signal than a no-op. The names invite exactly that mistake:
|
|
13
13
|
//
|
|
14
|
-
//
|
|
14
|
+
// assetUrlHelper() provides runtime.asset() to templates (a URL helper)
|
|
15
15
|
// assets() runs presets and produces derivatives (the work)
|
|
16
16
|
// renderPreset() renders a preset-authored layout (this file)
|
|
17
17
|
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// but not unreasonable.
|
|
18
|
+
// The helpers were renamed for their role in 10.0.0 for exactly this reason;
|
|
19
|
+
// renderPreset keeps its name because it really is a renderer.
|
|
21
20
|
export async function load({ entity, runtime }) {
|
|
22
21
|
if (!entity?.preset?.uri) return
|
|
23
22
|
const preset = await import(`${entity.preset.uri}?stamp=${Date.now()}`)
|
package/src/render.js
CHANGED
|
@@ -187,10 +187,28 @@ export default async ({ entity, options, config, context, state, logger, port, t
|
|
|
187
187
|
// state.layouts.sitemap map that was serialized per render
|
|
188
188
|
// task. Goes through the same WAL-backed read-only handle
|
|
189
189
|
// every worker shares with the engine writer.
|
|
190
|
-
|
|
190
|
+
// Both lookups RECORD what they were asked for, via track.lookup.
|
|
191
|
+
//
|
|
192
|
+
// They read the catalog directly, and until this they told nobody —
|
|
193
|
+
// so nothing knew a page depended on the page it links to. Renaming
|
|
194
|
+
// a target left every page linking to it pointing at a file that no
|
|
195
|
+
// longer existed, on a green build, because manifest.shouldSkip had
|
|
196
|
+
// no edge to check. A sidecar's findEntities() was tracked all along;
|
|
197
|
+
// these two were the asymmetry.
|
|
198
|
+
//
|
|
199
|
+
// The recorded target is the string the template asked for, not the
|
|
200
|
+
// resolved id — see track.lookup for why that also covers a target that
|
|
201
|
+
// does not exist yet.
|
|
202
|
+
lookupHref: (href) => {
|
|
203
|
+
track?.lookup?.(href)
|
|
204
|
+
return lookupHrefViaDb(href)
|
|
205
|
+
},
|
|
191
206
|
// Resolve a served-entity reference to its deployed URL, absolute
|
|
192
207
|
// when runtime.options.url is set (ADR-0011).
|
|
193
|
-
lookupUrl: (ref, preset) =>
|
|
208
|
+
lookupUrl: (ref, preset) => {
|
|
209
|
+
if (typeof ref === 'string') track?.lookup?.(ref)
|
|
210
|
+
return lookupUrlViaDb(ref, preset, options.url)
|
|
211
|
+
},
|
|
194
212
|
content() {
|
|
195
213
|
return readFileSync(entity.source, { encoding: 'utf8' })
|
|
196
214
|
},
|
package/src/track.js
CHANGED
|
@@ -40,8 +40,36 @@ export function filterKey(filter) {
|
|
|
40
40
|
// The returned object exposes `partials: Set<string>` and
|
|
41
41
|
// `queries: Array<filter | null>` directly. Consumers iterate either
|
|
42
42
|
// shape; both are owned by the track for the lifetime of the run.
|
|
43
|
-
export function createTrack({ partial = true, query = true } = {}) {
|
|
43
|
+
export function createTrack({ partial = true, query = true, lookup = true } = {}) {
|
|
44
44
|
const track = {}
|
|
45
|
+
if (lookup) {
|
|
46
|
+
// Lookups a TEMPLATE made by name: runtime.href('/contacts'),
|
|
47
|
+
// runtime.lookupUrl('/media/clip.mp4'). Both read the catalog
|
|
48
|
+
// directly, and until this existed neither told anyone — so nothing
|
|
49
|
+
// recorded that a page depends on the page it links to.
|
|
50
|
+
//
|
|
51
|
+
// Measured consequence: rename contacts.md to contact-us.md and only
|
|
52
|
+
// the renamed page re-renders. Every page linking to it keeps a href
|
|
53
|
+
// pointing at a file that no longer exists, on a green build.
|
|
54
|
+
//
|
|
55
|
+
// The edge kind is 'lookup', NOT 'ref': mikser_refs divides ownership
|
|
56
|
+
// by kind — indexEntity owns kind='ref' (static frontmatter $-refs)
|
|
57
|
+
// and clears it per source, while replaceDynamic owns everything
|
|
58
|
+
// else. Writing these as 'ref' got them inserted by replaceDynamic
|
|
59
|
+
// and then wiped by the next indexEntity, so the edge existed in
|
|
60
|
+
// the manifest and never in the refs index — recorded, and still
|
|
61
|
+
// never scheduling a re-render.
|
|
62
|
+
//
|
|
63
|
+
// The target is the STRING the template asked for, not the resolved
|
|
64
|
+
// entity's id, and that is deliberate: lookupKeys() expands a mutated
|
|
65
|
+
// entity into its id, its meta.href AND its id-minus-extension, so an
|
|
66
|
+
// edge on '/contacts' fires whether the target was edited, renamed,
|
|
67
|
+
// deleted, or created for the first time. Recording the resolved id
|
|
68
|
+
// instead would miss the case where nothing resolved yet.
|
|
69
|
+
const lookups = new Set()
|
|
70
|
+
track.lookups = lookups
|
|
71
|
+
track.lookup = (target) => { if (target && typeof target === 'string') lookups.add(target) }
|
|
72
|
+
}
|
|
45
73
|
if (partial) {
|
|
46
74
|
const partials = new Set()
|
|
47
75
|
track.partials = partials
|