Skip to content

fix(linker): stop appended/prepended blocks rendering twice when nested - #3475

Open
afonsojanu wants to merge 1 commit into
pugjs:masterfrom
afonsojanu:fix/nested-append-block-double-render
Open

fix(linker): stop appended/prepended blocks rendering twice when nested#3475
afonsojanu wants to merge 1 commit into
pugjs:masterfrom
afonsojanu:fix/nested-append-block-double-render

Conversation

@afonsojanu

Copy link
Copy Markdown

This fixes #3158, which has been open since 2019.

The repro from that issue still happens on current master: including a template that appends to a layout block causes the appended content to show up twice, once in the layout block where it belongs and once again right where the include was.

It's not actually specific to includes. The same thing happens with any block append/prepend/replace that ends up nested somewhere other than the top level of a template, for example:

extends layout

block content
  p Hi
  block append stylesheets
    link(rel="stylesheet" href="inline.css")

pug-linker's extend() walks the whole tree looking for named blocks, and when it finds one matching a block declared further up the extends chain, it correctly merges that block's content into the target. What it didn't do was clear the block out from its own original spot in the tree, so anything code-gen visits afterward (which just treats a leftover NamedBlock the same as a plain Block) renders it a second time.

The fix clears a block's own nodes once its content has been merged elsewhere, but only after the walk has finished descending into it, otherwise a block nested even deeper inside it (again, this can happen through an include) never gets visited at all.

I added an end-to-end case reproducing the exact scenario from the issue (packages/pug/test/cases/append-inside-include.*), plus updated a handful of pug-linker snapshot tests. Those snapshot diffs are limited to declaredBlocks, an internal bookkeeping structure the linker builds for chained extends — I checked that nothing outside pug-linker itself reads that property, and traced through a 3-level extends chain by hand to confirm the actual chaining behavior (matching a block declared two levels up) is unaffected.

Ran the full suite (npx jest) before and after; the only failures either way are two pre-existing error.reporting tests that expect an older Node.js error message format, unrelated to this change.

When a block declared with append, prepend or replace shows up somewhere
other than the top level of a template (for example one pulled in
through an include), its content was left sitting in its original spot
in the tree in addition to being merged into the matching parent block.
That meant it rendered twice.

Fixes pugjs#3158.
@rollingversions

Copy link
Copy Markdown

There is no change log for this pull request yet.

Create a changelog

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Append in included file causes append to be printed twice

1 participant