vsvg-parser
Advanced tools
Comparing version 0.2.0 to 0.3.1
var parser = require( '../' ), | ||
inspect = require( 'util' ).inspect; | ||
console.log( inspect( parser.parse( '<svg><svg:g></svg:g><line /></svg>'), { depth: Infinity, color: true } ) ); | ||
console.log( inspect( parser.parse( '<svg><line /></svg>'), { depth: Infinity, color: true } ) ); |
141
index.js
@@ -5,2 +5,4 @@ 'use strict'; | ||
endTag = /<\/([-A-Za-z0-9_:]+)[^>]*>/, // this just matches the first one | ||
docTag = /^<(\?)(.*?)(\/?)>/g, // this is like a doc tag of a proper svg, | ||
commentTag = /^<(\!--)(.*?)(\/?)>/g, | ||
attr = /([-A-Za-z0-9_:]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // match tag attributes | ||
@@ -10,4 +12,4 @@ | ||
function makeArray( arr ) { | ||
return Array.prototype.slice.call( arr, 0 ); | ||
function makeArray(arr) { | ||
return Array.prototype.slice.call(arr, 0); | ||
} | ||
@@ -18,3 +20,3 @@ | ||
params | ||
attributes { Array } - array of strings eg. [ 'x="5"' ] | ||
attributes { Array } - array of strings eg. ['x="5"'] | ||
returns | ||
@@ -25,14 +27,14 @@ attributes { Object } - object of key values eg. { x: '5' } | ||
var getAttributes = | ||
exports.getAttributes = function getAttributes( attributes ) { | ||
exports.getAttributes = function getAttributes(attributes) { | ||
var _attributes = {}; | ||
function addToAttributes( keyvalue ) { | ||
var arr = keyvalue.split( /=/ ), | ||
key = arr[ 0 ], | ||
value = arr[ 1 ] ? arr[ 1 ].slice( 1 ).slice( 0, -1 ) : ''; | ||
function addToAttributes(keyvalue) { | ||
var arr = keyvalue.split(/=/), | ||
key = arr[0], | ||
value = arr[1] ? arr[1].slice(1).slice(0, -1) : ''; | ||
_attributes[ key ] = value; | ||
_attributes[key] = value; | ||
} | ||
attributes.forEach( addToAttributes ); | ||
attributes.forEach(addToAttributes); | ||
@@ -52,5 +54,5 @@ return _attributes; | ||
var getTagIndex = | ||
exports.getTagIndex = function getTagIndex( tagName, tags ) { | ||
for ( var i = tags.length - 1; i >= 0; i -= 1 ) { | ||
if ( tags[i].tagName === tagName ) { | ||
exports.getTagIndex = function getTagIndex(tagName, tags) { | ||
for (var i = tags.length - 1; i >= 0; i -= 1) { | ||
if (tags[i].tagName === tagName) { | ||
return i; | ||
@@ -72,8 +74,8 @@ } | ||
var getLastOpenTag = | ||
exports.getLastOpenTag = function getLastOpenTag( tags ) { | ||
for ( var i = tags.length - 1; i >= 0; i -= 1 ) { | ||
if ( !tags[ i ].closed ) { | ||
exports.getLastOpenTag = function getLastOpenTag(tags) { | ||
for (var i = tags.length - 1; i >= 0; i -= 1) { | ||
if (!tags[i].closed) { | ||
return i; | ||
} | ||
} | ||
} | ||
return -1; | ||
@@ -91,22 +93,22 @@ }; | ||
var createTree = | ||
exports.createTree = function createTree( tags ) { | ||
exports.createTree = function createTree(tags) { | ||
var _tags = []; | ||
function getArray( position, arr ) { | ||
var _position = makeArray( position ); | ||
if ( _position.length === 1 ) { | ||
function getArray(position, arr) { | ||
var _position = makeArray(position); | ||
if (_position.length === 1) { | ||
return arr; | ||
} | ||
var next = arr[ _position[ 0 ] ].children; | ||
var next = arr[_position[0]].children; | ||
_position.shift(); | ||
return getArray( _position, next ); | ||
return getArray(_position, next); | ||
} | ||
function addTagToTree( tag ) { | ||
var arr = getArray( tag.position, _tags ); | ||
arr.push( tag ); | ||
function addTagToTree(tag) { | ||
var arr = getArray(tag.position, _tags); | ||
arr.push(tag); | ||
} | ||
tags.forEach( addTagToTree ); | ||
tags.forEach(addTagToTree); | ||
return _tags; | ||
@@ -124,3 +126,3 @@ | ||
index { Array } - array of tags in a tree form same as the structure as the xml string | ||
eg. | ||
@@ -130,3 +132,3 @@ [{ | ||
attributes: {}, | ||
position: [ 0 ] | ||
position: [0] | ||
children: [{ | ||
@@ -136,3 +138,3 @@ tagName: 'line', | ||
children: [], | ||
postion: [ 0, 0 ] | ||
postion: [0, 0] | ||
}] | ||
@@ -143,9 +145,9 @@ }] | ||
function parse( xml ) { | ||
function parse(xml) { | ||
xml = xml.replace( /(\r\n|\n|\r)/gm, '' ); // remove all line breaks | ||
xml = xml.replace(/(\r\n|\n|\r)/gm, ''); // remove all line breaks | ||
var tags = [], | ||
position = [ 0 ], // initial position | ||
openTag, | ||
position = [-1], // initial position | ||
openTag, | ||
attributes, | ||
@@ -159,10 +161,11 @@ end, | ||
tagName, | ||
tag; | ||
tag, | ||
specialTag; | ||
while ( xml ) { // we carve away at the xml variable | ||
while (xml) { // we carve away at the xml variable | ||
// this checks to see if the previous string length is same as | ||
// this checks to see if the previous string length is same as | ||
// the current string length | ||
if ( xml.length === prevLength ) { | ||
throw new Error( 'Failed to parse SVG at chars: ' + xml.substring( 0, 5 ) ); | ||
if (xml.length === prevLength) { | ||
throw new Error('Failed to parse SVG at chars: ' + xml.substring(0, 5)); | ||
} | ||
@@ -174,8 +177,9 @@ // set prevLength | ||
openTag = xml.match( startTag ); | ||
openTag = xml.match(startTag); | ||
specialTag = xml.match(docTag) || xml.match(commentTag); | ||
if ( openTag ) { // if there is an open tag grab the attribute, and remove tag from xml string | ||
openTag = openTag[ 0 ]; | ||
attributes = openTag.match( attr ); | ||
xml = xml.substring( openTag.length ); | ||
if (openTag) { // if there is an open tag grab the attribute, and remove tag from xml string | ||
openTag = openTag[0]; | ||
attributes = openTag.match(attr); | ||
xml = xml.substring(openTag.length); | ||
// reseting some vars | ||
@@ -185,14 +189,16 @@ text = null; | ||
closed = null; | ||
if ( /\/>$/.test( openTag ) ) { // testing for self closing tags | ||
if (/\/>$/.test(openTag)) { // testing for self closing tags | ||
closed = true; | ||
} | ||
} | ||
else { | ||
end = xml.match( endTag ); // see if there is an end tag | ||
} else if (specialTag) { | ||
xml = xml.substring(specialTag[0].length); | ||
attributes = []; | ||
if ( end ) { // if there is a end tag find the last tag with same name, set text, and remove data from xml string | ||
index = getTagIndex( end[ 1 ], tags ); | ||
prevTag = tags[ index ]; | ||
text = xml.slice( 0, end.index ); | ||
xml = xml.substring( end.index + end[ 0 ].length ); | ||
} else { | ||
end = xml.match(endTag); // see if there is an end tag | ||
attributes = []; | ||
if (end) { // if there is a end tag find the last tag with same name, set text, and remove data from xml string | ||
index = getTagIndex(end[1], tags); | ||
prevTag = tags[index]; | ||
text = xml.slice(0, end.index); | ||
xml = xml.substring(end.index + end[0].length); | ||
} | ||
@@ -203,26 +209,29 @@ } | ||
if ( tagName || text ) { // tagName or text will be set if it is somewhat of a good output | ||
if (tagName || text) { // tagName or text will be set if it is somewhat of a good output | ||
tag = { | ||
tagName: tagName, | ||
attributes: getAttributes( attributes ), // convert to object | ||
attributes: getAttributes(attributes), // convert to object | ||
children: [], | ||
text: text, | ||
inside: getLastOpenTag( tags ), // this is needed to get an accurate position | ||
inside: getLastOpenTag(tags), // this is needed to get an accurate position | ||
closed: closed || !!text | ||
}; | ||
if ( tag.inside > -1 ) { | ||
position.push( -1 ); // push this value it is sometime just cut off | ||
position[ tags[ tag.inside ].position.length ] += 1; | ||
position = position.slice( 0, tags[ tag.inside ].position.length + 1 ); | ||
// eg. [ 0, 0, 1 ] this is a map of where this tag should be at | ||
if (tag.inside > -1) { | ||
position.push(-1); // push this value it is sometime just cut off | ||
position[tags[tag.inside].position.length] += 1; | ||
position = position.slice(0, tags[tag.inside].position.length + 1); | ||
// eg. [0, 0, 1] this is a map of where this tag should be at | ||
} else { | ||
position[0] += 1; | ||
} | ||
tag.position = makeArray( position ); | ||
tags.push( tag ); // push the tag | ||
tag.position = makeArray(position); | ||
tags.push(tag); // push the tag | ||
} | ||
if ( prevTag ) { | ||
if (prevTag) { | ||
prevTag.closed = true; // close the prevTag | ||
@@ -233,3 +242,3 @@ } | ||
return createTree( tags ); // convert flat array to tree | ||
} | ||
return createTree(tags); // convert flat array to tree | ||
} |
{ | ||
"name": "vsvg-parser", | ||
"version": "0.2.0", | ||
"version": "0.3.1", | ||
"description": "A minimal implementation of a svg parser used in vsvg", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -1,12 +0,14 @@ | ||
var test = require( 'tape' ), | ||
parser = require( '../' ); | ||
'use strict'; | ||
test( 'testing parser::getAttributes', function( t ) { | ||
var test = require('tape'), | ||
parser = require('../'); | ||
test('testing parser::getAttributes', function(t) { | ||
var attributes = parser.getAttributes(['foo="bar"']); | ||
// test out some of the properties of new element | ||
t.equals( attributes.foo, 'bar', 'object contains correct key and value' ); | ||
t.equals(attributes.foo, 'bar', 'object contains correct key and value'); | ||
t.end(); | ||
} ); | ||
}); | ||
test( 'testing parser::getTagIndex', function( t ) { | ||
test('testing parser::getTagIndex', function(t) { | ||
var tags = [{ | ||
@@ -17,6 +19,6 @@ tagName: 'line' | ||
}], | ||
index = parser.getTagIndex( 'line', tags ); | ||
index = parser.getTagIndex('line', tags); | ||
// test out some of the properties of new element | ||
t.equals( index, 0, 'the correct index is returned' ); | ||
t.equals(index, 0, 'the correct index is returned'); | ||
@@ -27,13 +29,13 @@ tags.push({ | ||
index = parser.getTagIndex( 'line', tags ); | ||
t.equals( index, 2, 'the correct index is returned of the last tag' ); | ||
index = parser.getTagIndex('line', tags); | ||
t.equals(index, 2, 'the correct index is returned of the last tag'); | ||
index = parser.getTagIndex( 'svg', tags ); | ||
t.equals( index, -1, 'negative -1 is given when tag is not in array' ); | ||
index = parser.getTagIndex('svg', tags); | ||
t.equals(index, -1, 'negative -1 is given when tag is not in array'); | ||
t.end(); | ||
} ); | ||
}); | ||
test( 'testing parser::getLastOpenTag', function( t ) { | ||
test('testing parser::getLastOpenTag', function(t) { | ||
var tags = [{ | ||
@@ -43,14 +45,14 @@ },{ | ||
}], | ||
index = parser.getLastOpenTag( tags ); | ||
index = parser.getLastOpenTag(tags); | ||
// test out some of the properties of new element | ||
t.equals( index, 0, 'the correct index is returned' ); | ||
tags[ 0 ].closed = true; | ||
index = parser.getLastOpenTag( tags ); | ||
t.equals( index, -1, 'negative -1 is given when closed tag is not in array' ); | ||
t.equals(index, 0, 'the correct index is returned'); | ||
tags[0].closed = true; | ||
index = parser.getLastOpenTag(tags); | ||
t.equals(index, -1, 'negative -1 is given when closed tag is not in array'); | ||
t.end(); | ||
} ); | ||
}); | ||
test( 'testing parser::createTree', function( t ) { | ||
test('testing parser::createTree', function(t) { | ||
var tags = [{ | ||
@@ -68,31 +70,51 @@ position: [0], | ||
}], | ||
tree = parser.createTree( tags ); | ||
tree = parser.createTree(tags); | ||
// test out some of the properties of new element | ||
t.equals( tree[ 0 ].foo, 'bar', 'the root tag is correct' ); | ||
t.equals( tree[ 0 ].children[ 0 ].baz, 'qux', 'the nested tag is correct' ); | ||
t.equals( tree[ 1 ].bar, 'baz', 'the sibling tag is correct' ); | ||
t.equals(tree[0].foo, 'bar', 'the root tag is correct'); | ||
t.equals(tree[0].children[0].baz, 'qux', 'the nested tag is correct'); | ||
t.equals(tree[1].bar, 'baz', 'the sibling tag is correct'); | ||
t.end(); | ||
} ); | ||
}); | ||
test( 'testing parser::parse', function( t ) { | ||
test('testing parser::parse', function(t) { | ||
var svg = '<svg foo:bar="baz" ><line foo="bar"></line><polygon /><g><line /></g><svg:line></svg:line><g></g></svg>', | ||
tree = parser.parse( svg ); | ||
groups = '<g></g><text>foo</text>', | ||
tree = parser.parse(svg), | ||
groupTree = parser.parse(groups); | ||
// test out some of the properties of new element | ||
t.equals( Array.isArray( tree ), true, 'an array is returned' ) | ||
t.equals( tree[ 0 ].tagName, 'svg', 'the root tag is correct' ); | ||
t.equals( tree[ 0 ].attributes['foo:bar'], 'baz', 'the root tag\'s attributes foo:baz is parsed correctly' ); | ||
t.equals( tree[ 0 ].children[ 0 ].tagName, 'line', 'the nested tag is correct' ); | ||
t.equals( tree[ 0 ].children[ 0 ].attributes.foo, 'bar', 'the nested tag attributes are correct' ); | ||
t.equals( tree[ 0 ].children[ 1 ].tagName, 'polygon', 'the nested self closing tag is correct' ); | ||
t.equals( tree[ 0 ].children[ 2 ].children[ 0 ].tagName, 'line', 'the nested, nest self closing tag is correct' ); | ||
t.equals( tree[ 0 ].children[ 3 ].tagName, 'svg:line', 'the addition of a colon to the tagname parses correctly' ); | ||
t.equals( tree[ 0 ].children[ 3 ].children.length, 0, 'the addition of a colon to the tagname does not mistakenly next sibling elements into it' ); | ||
t.equals(Array.isArray(tree), true, 'an array is returned'); | ||
t.equals(tree[0].tagName, 'svg', 'the root tag is correct'); | ||
t.equals(tree[0].attributes['foo:bar'], 'baz', 'the root tag\'s attributes foo:baz is parsed correctly'); | ||
t.equals(tree[0].children[0].tagName, 'line', 'the nested tag is correct'); | ||
t.equals(tree[0].children[0].attributes.foo, 'bar', 'the nested tag attributes are correct'); | ||
t.equals(tree[0].children[1].tagName, 'polygon', 'the nested self closing tag is correct'); | ||
t.equals(tree[0].children[2].children[0].tagName, 'line', 'the nested, nest self closing tag is correct'); | ||
t.equals(tree[0].children[3].tagName, 'svg:line', 'the addition of a colon to the tagname parses correctly'); | ||
t.equals(tree[0].children[3].children.length, 0, 'the addition of a colon to the tagname does not mistakenly next sibling elements into it'); | ||
// testing some same level elements | ||
t.equals(groupTree.length, 2, 'There is the correct amount of elements in the groupTree array'); | ||
t.equals(groupTree[0].tagName, 'g', 'The first element in the groupTree is a g tag'); | ||
t.equals(groupTree[1].tagName, 'text', 'The second element in the groupTree is a text tag'); | ||
t.equals(groupTree[1].children.length, 1, 'The text element has one child'); | ||
t.equals(groupTree[1].children[0].text, 'foo', 'The first element in the text node is "foo"'); | ||
// errors | ||
t.throws( parser.parse.bind( parser, '<<foo>>' ), /Failed to parse SVG/, 'If parse fails to parse svg an error is thrown' ); | ||
t.throws(parser.parse.bind(parser, '<<foo>>'), /Failed to parse SVG/, 'If parse fails to parse svg an error is thrown'); | ||
t.end(); | ||
} ); | ||
}); | ||
test('testing parser svg doc, comments tags', function(t) { | ||
var svg = '<?xml version="1.0" encoding="utf-8"?><!-- foobar --><svg><circle></circle></svg>', | ||
tree = parser.parse(svg); | ||
t.equals(Array.isArray(tree), true, 'return from parser is an array'); | ||
t.equals(tree.length, 1, 'there is only one root element in the svg'); | ||
t.equals(tree[0].tagName, 'svg', 'first tag is a svg'); | ||
t.equals(tree[0].children.length, 1, 'first tag has the correct amount of children'); | ||
t.end(); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
0
16094
10
281
1