Parser RegEx update (#4003)

* better regex and attribute validation as well as public accesss to the regex

* lint
This commit is contained in:
Stefan Hayden 2017-08-14 07:52:52 -04:00 committed by Andrea Bogazzi
parent b7d9047c9c
commit b114d8d0ee
3 changed files with 51 additions and 10 deletions

View file

@ -48,7 +48,8 @@ fabric.SHARED_ATTRIBUTES = [
"stroke", "stroke-dasharray", "stroke-linecap",
"stroke-linejoin", "stroke-miterlimit",
"stroke-opacity", "stroke-width",
"id"
"id",
"instantiated_by_use"
];
/* _FROM_SVG_END_ */

View file

@ -14,10 +14,11 @@
parseUnit = fabric.util.parseUnit,
multiplyTransformMatrices = fabric.util.multiplyTransformMatrices,
reAllowedSVGTagNames = /^(path|circle|polygon|polyline|ellipse|rect|line|image|text)$/i,
reViewBoxTagNames = /^(symbol|image|marker|pattern|view|svg)$/i,
reNotAllowedAncestors = /^(?:pattern|defs|symbol|metadata|clipPath|mask)$/i,
reAllowedParents = /^(symbol|g|a|svg)$/i,
svgValidTagNames = ['path', 'circle', 'polygon', 'polyline', 'ellipse', 'rect', 'line',
'image', 'text', 'linearGradient', 'radialGradient', 'stop'],
svgViewBoxElements = ['symbol', 'image', 'marker', 'pattern', 'view', 'svg'],
svgInvalidAncestors = ['pattern', 'defs', 'symbol', 'metadata', 'clipPath', 'mask', 'desc'],
svgValidParents = ['symbol', 'g', 'a', 'svg'],
attributesMap = {
cx: 'left',
@ -50,6 +51,11 @@
fill: 'fillOpacity'
};
fabric.svgValidTagNamesRegEx = getSvgRegex(svgValidTagNames);
fabric.svgViewBoxElementsRegEx = getSvgRegex(svgViewBoxElements);
fabric.svgInvalidAncestorsRegEx = getSvgRegex(svgInvalidAncestors);
fabric.svgValidParentsRegEx = getSvgRegex(svgValidParents);
fabric.cssRules = { };
fabric.gradientDefs = { };
@ -110,6 +116,13 @@
return (!isArray && isNaN(parsed) ? value : parsed);
}
/**
* @private
*/
function getSvgRegex(arr) {
return new RegExp('^(' + arr.join('|') + ')\\b', 'i');
}
/**
* @private
* @param {Object} attributes Array of attributes to parse
@ -508,7 +521,7 @@
x = element.getAttribute('x') || 0,
y = element.getAttribute('y') || 0,
preserveAspectRatio = element.getAttribute('preserveAspectRatio') || '',
missingViewBox = (!viewBoxAttr || !reViewBoxTagNames.test(element.nodeName)
missingViewBox = (!viewBoxAttr || !fabric.svgViewBoxElementsRegEx.test(element.nodeName)
|| !(viewBoxAttr = viewBoxAttr.match(reViewBoxAttrValue))),
missingDimAttr = (!widthAttr || !heightAttr || widthAttr === '100%' || heightAttr === '100%'),
toBeParsed = missingViewBox && missingDimAttr,
@ -631,8 +644,8 @@
var elements = descendants.filter(function(el) {
applyViewboxTransform(el);
return reAllowedSVGTagNames.test(el.nodeName.replace('svg:', '')) &&
!hasAncestorWithNodeName(el, reNotAllowedAncestors); // http://www.w3.org/TR/SVG/struct.html#DefsElement
return fabric.svgValidTagNamesRegEx.test(el.nodeName.replace('svg:', '')) &&
!hasAncestorWithNodeName(el, fabric.svgInvalidAncestorsRegEx); // http://www.w3.org/TR/SVG/struct.html#DefsElement
});
if (!elements || (elements && !elements.length)) {
@ -759,7 +772,7 @@
svgUid = element.getAttribute('svgUid');
}
// if there's a parent container (`g` or `a` or `symbol` node), parse its attributes recursively upwards
if (element.parentNode && reAllowedParents.test(element.parentNode.nodeName)) {
if (element.parentNode && fabric.svgValidParentsRegEx.test(element.parentNode.nodeName)) {
parentAttributes = fabric.parseAttributes(element.parentNode, attributes, svgUid);
}
fontSize = (parentAttributes && parentAttributes.fontSize ) ||
@ -787,7 +800,7 @@
fabric.parseFontDeclaration(normalizedStyle.font, normalizedStyle);
}
var mergedAttrs = extend(parentAttributes, normalizedStyle);
return reAllowedParents.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs);
return fabric.svgValidParentsRegEx.test(element.nodeName) ? mergedAttrs : _setStrokeFillOpacity(mergedAttrs);
},
/**

View file

@ -229,6 +229,33 @@
return fabric.util.resolveNamespace(namespace)[type];
},
/**
* Returns array of attributes for given svg that fabric parses
* @memberOf fabric.util
* @param {String} type Type of svg element (eg. 'circle')
* @return {Array} string names of supported attributes
*/
getSvgAttributes: function(type) {
var attributes = [
'instantiated_by_use',
'style',
'id',
'class'
];
switch (type) {
case 'linearGradient':
attributes = attributes.concat(['x1', 'y1', 'x2', 'y2', 'gradientUnits', 'gradientTransform']);
break;
case 'radialGradient':
attributes = attributes.concat(['gradientUnits', 'gradientTransform', 'cx', 'cy', 'r', 'fx', 'fy', 'fr']);
break;
case 'stop':
attributes = attributes.concat(['offset', 'stop-color', 'stop-opacity']);
break;
}
return attributes;
},
/**
* Returns object of given namespace
* @memberOf fabric.util