Browse Source

Properly handle newline escape sequences in strings for DOT (#3112)

* Properly handle newline escape sequences in strings for DOT

* Adjust comments in code
gemini
wimrijnders 7 years ago
committed by yotamberk
parent
commit
b882b3873c
2 changed files with 104 additions and 2 deletions
  1. +30
    -2
      lib/network/dotparser.js
  2. +74
    -0
      test/dotparser.test.js

+ 30
- 2
lib/network/dotparser.js View File

@ -10,6 +10,29 @@
* @return {Object} graph An object containing two parameters: * @return {Object} graph An object containing two parameters:
* {Object[]} nodes * {Object[]} nodes
* {Object[]} edges * {Object[]} edges
*
* -------------------------------------------
* TODO
* ====
*
* For label handling, this is an incomplete implementation. From docs (quote #3015):
*
* > the escape sequences "\n", "\l" and "\r" divide the label into lines, centered,
* > left-justified, and right-justified, respectively.
*
* Source: http://www.graphviz.org/content/attrs#kescString
*
* > As another aid for readability, dot allows double-quoted strings to span multiple physical
* > lines using the standard C convention of a backslash immediately preceding a newline
* > character
* > In addition, double-quoted strings can be concatenated using a '+' operator.
* > As HTML strings can contain newline characters, which are used solely for formatting,
* > the language does not allow escaped newlines or concatenation operators to be used
* > within them.
*
* - Currently, only '\\n' is handled
* - Note that text explicitly says 'labels'; the dot parser currently handles escape
* sequences in **all** strings.
*/ */
function parseDOT (data) { function parseDOT (data) {
dot = data; dot = data;
@ -358,9 +381,14 @@ function getToken() {
if (c === '"') { if (c === '"') {
next(); next();
while (c != '' && (c != '"' || (c === '"' && nextPreview() === '"'))) { while (c != '' && (c != '"' || (c === '"' && nextPreview() === '"'))) {
token += c;
if (c === '"') { // skip the escape character
if (c === '"') { // skip the escape character
token += c;
next();
} else if (c === '\\' && nextPreview() === 'n') { // Honor a newline escape sequence
token += '\n';
next(); next();
} else {
token += c;
} }
next(); next();
} }

+ 74
- 0
test/dotparser.test.js View File

@ -183,4 +183,78 @@ describe('dotparser', function () {
}); });
}); });
/**
* DOT-format examples taken from #3015
*/
it('properly handles newline escape sequences in strings', function (done) {
var data = 'dinetwork {1 [label="new\\nline"];}';
data = String(data);
var graph = dot.parseDOT(data);
assert.deepEqual(graph, {
"id": "dinetwork",
"nodes": [
{
"id": 1,
"attr": {
"label": "new\nline", // And not "new\\nline"
}
}
]
});
// Note the double backslashes
var data2 = 'digraph {' + "\n" +
' 3 [color="#0d2b7c", label="query:1230:add_q\\n0.005283\\n6.83%\\n(0.0001)\\n(0.13%)\\n17×"];' + "\n" +
' 3 -> 7 [color="#0d2a7b", fontcolor="#0d2a7b", label="0.005128\\n6.63%\\n17×"];' + "\n" +
' 5 [color="#0d1976", label="urlresolvers:537:reverse\\n0.00219\\n2.83%\\n(0.000193)\\n(0.25%)\\n29×"];' + "\n" +
"}"
data2 = String(data2);
var graph2 = dot.parseDOT(data2);
//console.log(JSON.stringify(graph, null, 2));
assert.deepEqual(graph2, {
"type": "digraph",
"nodes": [
{
"id": 3,
"attr": {
"color": "#0d2b7c",
"label": "query:1230:add_q\n0.005283\n6.83%\n(0.0001)\n(0.13%)\n17×"
}
},
{
"id": 7
},
{
"id": 5,
"attr": {
"color": "#0d1976",
"label": "urlresolvers:537:reverse\n0.00219\n2.83%\n(0.000193)\n(0.25%)\n29×"
}
}
],
"edges": [
{
"from": 3,
"to": 7,
"type": "->",
"attr": {
"color": "#0d2a7b",
"fontcolor": "#0d2a7b",
"label": "0.005128\n6.63%\n17×"
}
}
]
});
done();
});
}); });

Loading…
Cancel
Save