Skip to content

Keep Markup: preserve nested empty markup - #4122

Open
dyk1454683243-sudo wants to merge 1 commit into
PrismJS:v2from
dyk1454683243-sudo:cursor/fix-keep-markup-nested-empty-1640-278b
Open

dyk1454683243-sudo wants to merge 1 commit into
PrismJS:v2from
dyk1454683243-sudo:cursor/fix-keep-markup-nested-empty-1640-278b

Conversation

@dyk1454683243-sudo

Copy link
Copy Markdown

Fixes #1640

Keep Markup flattened nested zero-length markup (tags with empty textContent) out of their parents:

  • <x><y></y></x><x></x><y></y>
  • <x>a<y></y></x><x>a</x> (child dropped; with following text it became <x>a</x><y></y>)
  • deeper nests / multiple empty children likewise

Mid-stream empties with text on both sides (<x>a<y></y>b</x>) and sibling empties (x<a></a><b></b>y) already survived.

Cause

before-highlight records text offsets. Parents are reinserted first. Wrapping a parent does innerHTML = '', which detaches stored empty children. The child's empty range sits at the same text offset as the parent's posClose (or at the start of the following text), so Range#insertNode places it after the parent.

Fix

Record each node's keep-markup ancestor while walking the original tree. After highlighting:

  • If an empty node's walk would insert at a text position outside that already-reinserted ancestor, appendChild it to the ancestor instead.
  • If the walk never starts (empty at the ancestor's posClose, no later text inside it), append to the ancestor the same way.

Sibling empties, contentful last markup, order, double-highlight, and no-clone behavior are unchanged.

Tests

  • Issue fixtures: <x><y></y></x>, <x>a<y></y></x>, multiple empty children, deeper nest
  • Mid-stream nested empty with sibling text (<x>a<y></y>b</x>)
  • Flatten repros with following text (<x><y></y></x>foo, <x>a<y></y></x>b)
  • Same-element parent pointer after highlight

Related

Shares empty-range care with #1618 / #4121 (empty markup as the last child of <code> is still dropped on this branch; that last-child survival is #4121). This PR does not close #1618.

Fixes PrismJS#1640

Wrapping a parent keep-markup element cleared its original empty
children, then the after-highlight walk reinserted those zero-width
ranges at the same text offset — as siblings after the parent.

Record the keep-markup ancestor and append empty descendants to it
when the walk would place them outside that ancestor.

Co-authored-by: David <dyk1454683243-sudo@users.noreply.github.com>
@netlify

netlify Bot commented Sep 20, 2026

Copy link
Copy Markdown

Deploy Preview for dev-prismjs-com ready!

Name Link
🔨 Latest commit 18b3a5e
🔍 Latest deploy log https://app.netlify.com/projects/dev-prismjs-com/deploys/6aaf5b3bedef4d0008b5f37c
😎 Deploy Preview https://deploy-preview-4122--dev-prismjs-com.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

This branch has not been deployed

No deployments
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.

Keep Markup and zero-length tags Keep Markup: the markup is removed if it's the last element

2 participants