Steps to Reproduce
Resolve this body against a greedy field matching list|tag:track, with an itemModel and emitTag: 'track':
- Song A
- Song B
{% track name="Song C" /%}
- Song D
Expected
Four track tags, in document order: the three list-derived ones and the authored Song C. Both syntaxes are the same thing after conversion, which is the point of emitTag.
Actual
names: [ 'Song A', 'Song B', 'Song D' ]
Song C is gone. No error, no warning, no build diagnostic.
Notes
- Severity is
major because the failure is silent content loss, the same class as BUG-028. A rune that refused the mixed declaration would be a smaller problem than one that quietly eats half of it. - No rune hits this today:
cast, audio and plot use emitTag on list-only fields, and playlist uses a mixed field without emitTag. The bug is latent, and it is latent because the obvious combination does not work — so it has shaped the code around it rather than showing up as a defect. - The fix looks small: pass a non-list node through into
tagNodes instead of continue-ing past it. It is already a tag, so it needs no conversion — only to keep its place. That yields a homogeneous, document-ordered array, which is strictly better than cast's concatenation (which appends all explicit tags after all list-derived ones and so loses interleaving). - Worth confirming as part of any fix: that an emitted tag and an authored one of the same name really are interchangeable downstream —
adoptNestedTrack exists because playlist found they were not, and that difference should be removed rather than re-encoded. - Surfaced while considering whether SPEC-141's per-rune preprocess could subsume
emitTag. It cannot and should not, but the question exposed this.
References
- SPEC-003 — the declarative content model this belongs to
- BUG-028 —
figure dropping non-media children; the same silent-content-loss class - BUG-031 — the reference drops
emitTag, template and the whole itemModel grammar, so neither half of the dual-syntax contract is visible - SPEC-141 — where the question that exposed this came from