Skip to content
Permalink
Browse files Browse the repository at this point in the history
Refactored SVGRenderer text to not use backtracking regexes to replac…
…e attributes.

Adds support for single quoted class, href and style attributes in strings.
  • Loading branch information
TorsteinHonsi committed Mar 1, 2018
1 parent 9bcb40d commit 7c547e1
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 20 deletions.
58 changes: 38 additions & 20 deletions js/parts/SvgRenderer.js
Expand Up @@ -2348,9 +2348,6 @@ extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ {
hasMarkup = textStr.indexOf('<') !== -1,
lines,
childNodes = textNode.childNodes,
clsRegex,
styleRegex,
hrefRegex,
wasTooLong,
parentX = attr(textNode, 'x'),
textStyles = wrapper.styles,
Expand Down Expand Up @@ -2390,6 +2387,23 @@ extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ {
}
});
return inputStr;
},
parseAttribute = function (s, attr) {
var start,
delimiter;

start = s.indexOf('<');
s = s.substring(start, s.indexOf('>') - start);

start = s.indexOf(attr + '=');
if (start !== -1) {
start = start + attr.length + 1;
delimiter = s.charAt(start);
if (delimiter === '"' || delimiter === "'") { // eslint-disable-line quotes
s = s.substring(start + 1);
return s.substring(0, s.indexOf(delimiter));
}
}
};

// The buildText code is quite heavy, so if we're not changing something
Expand Down Expand Up @@ -2427,10 +2441,6 @@ extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ {
// Complex strings, add more logic
} else {

clsRegex = /<.*class="([^"]+)".*>/;
styleRegex = /<.*style="([^"]+)".*>/;
hrefRegex = /<.*href="([^"]+)".*>/;

if (tempParent) {
// attach it to the DOM to read offset width
tempParent.appendChild(textNode);
Expand Down Expand Up @@ -2485,27 +2495,31 @@ extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ {
renderer.SVG_NS,
'tspan'
),
spanCls,
spanStyle; // #390
if (clsRegex.test(span)) {
spanCls = span.match(clsRegex)[1];
attr(tspan, 'class', spanCls);
classAttribute,
styleAttribute, // #390
hrefAttribute;

classAttribute = parseAttribute(span, 'class');
if (classAttribute) {
attr(tspan, 'class', classAttribute);
}
if (styleRegex.test(span)) {
spanStyle = span.match(styleRegex)[1].replace(

styleAttribute = parseAttribute(span, 'style');
if (styleAttribute) {
styleAttribute = styleAttribute.replace(
/(;| |^)color([ :])/,
'$1fill$2'
);
attr(tspan, 'style', spanStyle);
attr(tspan, 'style', styleAttribute);
}

// Not for export - #1529
if (hrefRegex.test(span) && !forExport) {
hrefAttribute = parseAttribute(span, 'href');
if (hrefAttribute && !forExport) {
attr(
tspan,
'onclick',
'location.href=\"' +
span.match(hrefRegex)[1] + '\"'
'location.href=\"' + hrefAttribute + '\"'
);
attr(tspan, 'class', 'highcharts-anchor');
/*= if (build.classic) { =*/
Expand Down Expand Up @@ -2649,8 +2663,12 @@ extend(SVGRenderer.prototype, /** @lends Highcharts.SVGRenderer.prototype */ {
dy: dy,
x: parentX
});
if (spanStyle) { // #390
attr(tspan, 'style', spanStyle);
if (styleAttribute) { // #390
attr(
tspan,
'style',
styleAttribute
);
}
textNode.appendChild(tspan);
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -82,6 +82,7 @@
"aws-sdk": "^2.94.0",
"babel-runtime": "^6.20.0",
"glob": "^7.1.2",
"safe-regex": "^1.1.0",
"taffydb": "^2.7.3"
}
}
36 changes: 36 additions & 0 deletions samples/unit-tests/svgrenderer/text/demo.js
Expand Up @@ -204,3 +204,39 @@ QUnit.test('Dir rtl (#3482)', function (assert) {

document.getElementById('container').removeAttribute('dir');
});

QUnit.test('Attributes', function (assert) {
var ren = new Highcharts.Renderer(
document.getElementById('container'),
600,
400
);

var text = ren
.text(
'The quick brown fox jumps <span class="red">over</span> the lazy dog',
20,
20
)
.add();

assert.strictEqual(
text.element.childNodes[1].getAttribute('class'),
'red',
'Double quotes, red span should be picked up'
);

text = ren
.text(
"The quick brown fox jumps <span class='red'>over</span> the lazy dog",
20,
20
)
.add();

assert.strictEqual(
text.element.childNodes[1].getAttribute('class'),
'red',
'Single quotes, red span should be picked up'
);
});

0 comments on commit 7c547e1

Please sign in to comment.