如何检测标准HTML或SVG属性的值无效



给定一个类似这样的SVG片段:

<path d="..." fill-rule="invalid-value" />

JS中检测fill-rule属性值无效的最佳方法是什么?在MDN规范中,它必须是nonzeroevenodd

我想验证所有的标准属性,并试图避免为每个标准属性编写自定义解析器。

在某种程度上,通过比较属性值和计算的样式值,您可能会发现无效值

示例1:检查单个属性

let els = document.querySelectorAll("path, polygon");
els.forEach(function(path) {
let fiilRuleAtt = path.getAttribute("fill-rule");
let pathStyle = window.getComputedStyle(path);
let fiilRuleStyle = pathStyle.fillRule;
if (fiilRuleAtt != fiilRuleStyle) {
console.log(`${path.id}  has invalid attribute value: "${fiilRuleAtt}". Reset to css value: ${fiilRuleStyle}`);
}
});
svg {
width: 50%;
display: inline-block;
}
<svg viewBox="-10 -10 320 120" xmlns="http://www.w3.org/2000/svg">
<polygon id="star" fill-rule="nonzero" stroke="red" points="50,0 21,90 98,35 2,35 79,90" />
<path id="rect1" fill-rule="nonsenseFillRule" stroke="red" d="M110,0  h90 v90 h-90 z
M130,20 h50 v50 h-50 z" />
<path id="rect2" fill-rule="nonzero" stroke="red" d="M210,0  h90 v90 h-90 z
M230,20 v50 h50 v-50 z" />
</svg>

示例2:检查所有属性,排除的属性除外

我们可以定义一组与样式无关的属性,如:idclass等。
此外,数据属性也被忽略。

let els = document.querySelectorAll("path, polygon");
let excludedAtts = ["id", "class", "points", "d", "fill", "stroke"];
els.forEach(function (el) {
let attributes = [...el.attributes];
attributes.forEach(function (att, i) {
let attName = att.nodeName;
let attNameJs = camalize(attName);
//exclude properties defined in array and also data attributes
if (excludedAtts.indexOf(attName) == -1 && attName.indexOf("data-") == -1) {
let attValue = el.getAttribute(attName);
let elStyle = window.getComputedStyle(el);
let styleValue = elStyle[attNameJs];
//not supported properties
if (styleValue === undefined) {
console.log(
`${el.id}  has unsupported property "${attName}": "${attValue}".`
);
} else {
//strip units
attValue = attValue.split(/[, ]/).filter(Boolean).map( (val)=>{return val.replaceAll('px','')} ).join(' ');
let styleValueUnitless = styleValue.split(/[, ]/).filter(Boolean).map( (val)=>{return val.replaceAll('px','')} ).join(' ');
styleValue = attValue === styleValueUnitless ? styleValueUnitless : styleValue;
if (attValue != styleValue) {
console.log(
`${el.id}  has invalid ${attName} value: "${attValue}". Reset to css value: ${styleValue}`
);
}
}
}
});
});

/**
* @smilyface: https://stackoverflow.com/questions/2970525/converting-any-string-into-camel-case#52551910
**/
function camalize(str) {
return str
.toLowerCase()
.replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());
}
svg {
width: 50%;
display: inline-block;
}
<svg viewBox="-10 -10 320 120" xmlns="http://www.w3.org/2000/svg">
<polygon id="star" fill-rule="nonzero" stroke="red" points="50,0 21,90 98,35 2,35 79,90" />
<path id="rect1" fill-rule="notValid" stroke="red" d="M110,0  h90 v90 h-90 z M130,20 h50 v50 h-50 z" />
<path id="rect2" data-id="test" rotate="33" fill-rule="nonzero" stroke="red" stroke-dasharray="auto" d="M210,0  h90 v90 h-90 z M230,20 v50 h50 v-50 z" />
</svg>

但最有可能的是,对于当前浏览器尚未支持的更新/实验功能,您也会收到误报。

最新更新