fix(import): keep the content a compound button wraps - #476
Merged
DavidBabinec merged 3 commits intoSep 2, 2026
Conversation
A `<button>` or a `.btn` anchor that wrapped an icon, an inline `<svg>` or
an `<img>` alongside its label imported as a label-only node. base.button
is `canHaveChildren: false`, so the nested markup had nowhere to go and was
dropped without a warning, while any image it referenced stayed behind in
the Media Library — leaving the missing content hard to trace back to the
import.
Handle it the way the heading and label rules already handle the same
problem: keep the leaf mapping while the element holds nothing but text,
and recurse into a child-capable module when it wraps elements. A compound
`.btn` anchor maps to base.link, which is what the plain anchor rule below
it already does for a compound `<a>` and which keeps href and target. A
compound non-submit `<button>` maps to a container tagged `button`. Class
names ride along as classIds, so `.btn` styling is unaffected by the swap.
Submit buttons stay on base.submit even when compound: core/forms
identifies a form's submit control by that module id, so re-tagging one as
a container would leave the form without a submit. A compound submit button
therefore still keeps only its label; lifting that needs base.submit to
accept children, which is a module change rather than an importer one.
The svgMapping case that asserted the old behaviour ("icon not preserved —
buttons are leaves") now asserts preservation, with a new case covering the
text-only anchor that still maps to base.button.
Closes CoreBunch#413
Release notes are written in the release-preparation PR from the merged PRs, so feature and fix PRs leave CHANGELOG.md untouched.
PR 480 landed doc rows for the img rule next to the anchor and button rows this branch rewrites; both sides are kept.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #413.
A
<button>or a.btnanchor that wrapped an icon, an inline<svg>or an<img>alongside its label imported as a label-only node.base.buttoniscanHaveChildren: false, so the nested markup had nowhere to go and was dropped without a warning — while any image it referenced stayed behind in the Media Library, which makes the missing content hard to trace back to the import.This handles it the way the heading and
labelrules in the same file already handle the same problem: keep the leaf mapping while the element holds nothing but text, and recurse into a child-capable module when it wraps elements..btnanchor maps tobase.link— what the plain anchor rule directly below it already does for a compound<a>— which keepshrefandtarget. Class names ride along as classIds, so.btnstyling is unaffected by the module swap.<button>maps to abase.containertaggedbutton, mirroring how a wrapper<label>becomes a container taggedlabel.base.button.Submit buttons are deliberately excluded.
core/formsidentifies a form's submit control by thebase.submitmodule id (src/core/forms/snapshot.ts), so re-tagging one as a container would leave the form without a submit. A compound submit button therefore still keeps only its label — lifting that needsbase.submitto accept children, which is a module change rather than an importer one, so it felt like the wrong thing to fold into this PR. Happy to follow up if you'd like it covered.The issue also offered a warning as a fallback if preservation wasn't practical. Since the content is now preserved, no
import-descendants-droppedwarning was added.Note on an existing test
svgMapping.test.tshad a case asserting the old behaviour — "a btn-classed anchor stays base.button (icon not preserved — buttons are leaves)" — which is the limitation #413 reports. It now asserts preservation, and a new case covers the text-only.btnanchor that still maps tobase.button.The docs table's
a(nobtnclass) row also said "No" for recurse while that rule already recursed on element children; corrected in passing since the neighbouring rows changed.Verification
bun run buildbun testbun run lintbun teston this branch: 6721 pass, 19 fail. All 19 failures are pre-existing onmain— I ran the full suite on a cleanorigin/maincheckout to confirm, and the failure sets are identical apart from one flaky SQLite concurrency test that failed on the baseline run and passed here. None are insrc/__tests__/htmlImport, which is 195 pass, 0 fail.Both new preservation tests were confirmed to fail without the
rules.tschange and pass with it.Checklist
docs/features/html-import.mdmapping table + a key-details entry, and a CHANGELOG entry under 0.0.18.