Nov25 fixes (#1072)

* update deps
* fixes #963 and #1061
* fix the issue #974
* update test
This commit is contained in:
JFH
2025-11-27 14:10:49 -03:00
committed by GitHub
parent 16a0e0d945
commit babd3490c9
6 changed files with 60 additions and 9 deletions

View File

@@ -105,6 +105,11 @@ export const recalculateDimensions = selected => {
return null
}
// Avoid remapping transforms on <use> to preserve referenced positioning/rotation
if (selected.tagName === 'use') {
return null
}
// Set up undo command
const batchCmd = new BatchCommand('Transform')

View File

@@ -7,7 +7,7 @@
*/
import { getReverseNS, NS } from './namespaces.js'
import { getHref, setHref, getUrlFromAttr } from './utilities.js'
import { getHref, getRefElem, setHref, getUrlFromAttr } from './utilities.js'
const REVERSE_NS = getReverseNS()
@@ -39,7 +39,11 @@ const svgWhiteList_ = {
filter: ['color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'href', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'],
foreignObject: ['font-size', 'height', 'opacity', 'requiredFeatures', 'width', 'x', 'y'],
g: ['clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'systemLanguage', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'],
image: ['clip-path', 'clip-rule', 'filter', 'height', 'mask', 'opacity', 'requiredFeatures', 'systemLanguage', 'width', 'x', 'href', 'xlink:href', 'xlink:title', 'y'],
image: [
'clip-path', 'clip-rule', 'filter', 'height', 'mask', 'opacity',
'preserveAspectRatio', 'requiredFeatures', 'systemLanguage', 'viewBox',
'width', 'x', 'href', 'xlink:href', 'xlink:title', 'y'
],
line: ['clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'systemLanguage', 'x1', 'x2', 'y1', 'y2'],
linearGradient: ['gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'href', 'xlink:href', 'y1', 'y2'],
marker: ['markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'se_type', 'systemLanguage', 'viewBox'],
@@ -224,6 +228,13 @@ export const sanitizeSvg = (node) => {
}
}
// If legacy xlink:href is present but href is missing, mirror it to href for modern browsers
const xlinkHref = node.getAttributeNS(NS.XLINK, 'href')
if (xlinkHref) {
node.setAttribute('href', xlinkHref)
node.removeAttributeNS(NS.XLINK, 'href')
}
Object.values(seAttrs).forEach(([att, val, ns]) => {
node.setAttributeNS(ns, att, val)
})
@@ -247,6 +258,24 @@ export const sanitizeSvg = (node) => {
node.remove()
return
}
// For <use> elements with missing width/height, derive defaults from referenced viewBox/size for proper sizing/selection
if (node.nodeName === 'use') {
const ref = getRefElem(getHref(node))
if (ref) {
const refViewBox = ref.getAttribute('viewBox')
const viewBoxParts = refViewBox ? refViewBox.split(/[\s,]+/).map(Number) : null
const refWidth = Number(ref.getAttribute('width'))
const refHeight = Number(ref.getAttribute('height'))
if (!node.hasAttribute('width')) {
const width = viewBoxParts?.[2] || refWidth
if (width) node.setAttribute('width', width)
}
if (!node.hasAttribute('height')) {
const height = viewBoxParts?.[3] || refHeight
if (height) node.setAttribute('height', height)
}
}
}
// if the element has attributes pointing to a non-local reference,
// need to remove the attribute
['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'].forEach((attr) => {

View File

@@ -1131,7 +1131,11 @@ export let getRotationAngle = (elem, toRad) => {
* @returns {Element} Reference element
*/
export const getRefElem = attrVal => {
return getElement(getUrlFromAttr(attrVal).substr(1))
if (!attrVal) return null
const url = getUrlFromAttr(attrVal)
if (!url) return null
const id = url[0] === '#' ? url.substr(1) : url
return getElement(id)
}
/**
* Get the reference element associated with the given attribute value.