From f5ea4edc13eca59b7a1e1c69615539f21186b302 Mon Sep 17 00:00:00 2001 From: Neal Lin <21194575+Neallin-917@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:18:46 +0800 Subject: [PATCH] fix: preserve inheritable defaults in referenced subtrees --- plugins/removeUnknownsAndDefaults.js | 29 ++++++++++++++++++- .../removeUnknownsAndDefaults.18.svg.txt | 23 +++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 test/plugins/removeUnknownsAndDefaults.18.svg.txt diff --git a/plugins/removeUnknownsAndDefaults.js b/plugins/removeUnknownsAndDefaults.js index fb4177b5b..ca1d233c0 100644 --- a/plugins/removeUnknownsAndDefaults.js +++ b/plugins/removeUnknownsAndDefaults.js @@ -3,6 +3,7 @@ import { attrsGroupsDefaults, elems, elemsGroups, + inheritableAttrs, presentationNonInheritableGroupAttrs, } from './_collections.js'; import { detachNodeFromParent } from '../lib/xast.js'; @@ -114,6 +115,28 @@ export const fn = (root, params) => { } = params; const stylesheet = collectStylesheet(root); + /** + * A referenced subtree may be instantiated by a `use` element, whose + * inherited styles must not replace defaults declared inside the subtree. + * + * @param {import('../lib/types.js').XastNode} node + * @returns {boolean} + */ + const hasReferenceableAncestor = (node) => { + let ancestor = node; + while (ancestor.type === 'element') { + if (ancestor.attributes.id != null) { + return true; + } + const parent = stylesheet.parents.get(ancestor); + if (parent == null) { + return false; + } + ancestor = parent; + } + return false; + }; + return { instruction: { enter: (node) => { @@ -194,7 +217,11 @@ export const fn = (root, params) => { defaultAttrs && node.attributes.id == null && attributesDefaults && - attributesDefaults.get(name) === value + attributesDefaults.get(name) === value && + // An inheritable default inside a referenceable subtree may keep + // that subtree from inheriting a different value via `use`. + (inheritableAttrs.has(name) === false || + hasReferenceableAncestor(parentNode) === false) ) { // keep defaults if parent has own or inherited style if ( diff --git a/test/plugins/removeUnknownsAndDefaults.18.svg.txt b/test/plugins/removeUnknownsAndDefaults.18.svg.txt new file mode 100644 index 000000000..d46bf0f61 --- /dev/null +++ b/test/plugins/removeUnknownsAndDefaults.18.svg.txt @@ -0,0 +1,23 @@ +Keep inheritable default attributes inside a referenceable subtree. + +=== + + + + + + + + + + +@@@ + + + + + + + + +