Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

vsvg-parser

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vsvg-parser - npm Package Compare versions

Comparing version 0.2.0 to 0.3.1

CONTRIBUTING.md

2

examples/basics.js
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 } ) );

@@ -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();
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc