From 8622a5f31b8fa60680b9f530c842b8ec834c4dbb Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Wed, 10 Mar 2021 14:06:06 +0300 Subject: [PATCH] Convert to xast doctype, instruction and comment nodes Here we add [xast](https://github.com/syntax-tree/xast) support to three basic nodes: doctype, instruction and comment Some tests are rewritten instead of checking each field to `.include` assertion which is able to match shape of object. --- lib/svgo/js2svg.js | 29 +++++++++--------- lib/svgo/svg2js.js | 14 +++++++-- plugins/removeComments.js | 2 +- plugins/removeDoctype.js | 2 +- plugins/removeXMLProcInst.js | 6 ++-- test/svg2js/_index.js | 59 +++++++++++------------------------- 6 files changed, 48 insertions(+), 64 deletions(-) diff --git a/lib/svgo/js2svg.js b/lib/svgo/js2svg.js index 8cb7f484..5ba604ae 100644 --- a/lib/svgo/js2svg.js +++ b/lib/svgo/js2svg.js @@ -101,12 +101,12 @@ JS2SVG.prototype.convert = function (data) { svg += this.createElem(item); } else if (item.text) { svg += this.createText(item.text); - } else if (item.doctype) { - svg += this.createDoctype(item.doctype); - } else if (item.processinginstruction) { - svg += this.createProcInst(item.processinginstruction); - } else if (item.comment) { - svg += this.createComment(item.comment); + } else if (item.type === 'doctype') { + svg += this.createDoctype(item); + } else if (item.type === 'instruction') { + svg += this.createProcInst(item); + } else if (item.type === 'comment') { + svg += this.createComment(item); } else if (item.cdata) { svg += this.createCDATA(item.cdata); } @@ -146,7 +146,8 @@ JS2SVG.prototype.createIndent = function () { * * @return {String} */ -JS2SVG.prototype.createDoctype = function (doctype) { +JS2SVG.prototype.createDoctype = function (node) { + const { doctype } = node.data; return this.config.doctypeStart + doctype + this.config.doctypeEnd; }; @@ -157,13 +158,10 @@ JS2SVG.prototype.createDoctype = function (doctype) { * * @return {String} */ -JS2SVG.prototype.createProcInst = function (instruction) { +JS2SVG.prototype.createProcInst = function (node) { + const { name, value } = node; return ( - this.config.procInstStart + - instruction.name + - ' ' + - instruction.body + - this.config.procInstEnd + this.config.procInstStart + name + ' ' + value + this.config.procInstEnd ); }; @@ -174,8 +172,9 @@ JS2SVG.prototype.createProcInst = function (instruction) { * * @return {String} */ -JS2SVG.prototype.createComment = function (comment) { - return this.config.commentStart + comment + this.config.commentEnd; +JS2SVG.prototype.createComment = function (node) { + const { value } = node; + return this.config.commentStart + value + this.config.commentEnd; }; /** diff --git a/lib/svgo/svg2js.js b/lib/svgo/svg2js.js index bc5a4143..b77f3049 100644 --- a/lib/svgo/svg2js.js +++ b/lib/svgo/svg2js.js @@ -37,7 +37,12 @@ module.exports = function (data) { sax.ondoctype = function (doctype) { pushToContent({ - doctype: doctype, + type: 'doctype', + // TODO parse doctype for name, public and system to match xast + name: 'svg', + data: { + doctype, + }, }); var subsetStart = doctype.indexOf('['), @@ -54,13 +59,16 @@ module.exports = function (data) { sax.onprocessinginstruction = function (data) { pushToContent({ - processinginstruction: data, + type: 'instruction', + name: data.name, + value: data.body, }); }; sax.oncomment = function (comment) { pushToContent({ - comment: comment.trim(), + type: 'comment', + value: comment.trim(), }); }; diff --git a/plugins/removeComments.js b/plugins/removeComments.js index e2899f2a..191618f7 100644 --- a/plugins/removeComments.js +++ b/plugins/removeComments.js @@ -19,7 +19,7 @@ exports.description = 'removes comments'; * @author Kir Belevich */ exports.fn = function (item) { - if (item.comment && item.comment.charAt(0) !== '!') { + if (item.type === 'comment' && item.value.charAt(0) !== '!') { return false; } }; diff --git a/plugins/removeDoctype.js b/plugins/removeDoctype.js index a0b11d5e..6e17bd87 100644 --- a/plugins/removeDoctype.js +++ b/plugins/removeDoctype.js @@ -32,7 +32,7 @@ exports.description = 'removes doctype declaration'; * @author Kir Belevich */ exports.fn = function (item) { - if (item.doctype) { + if (item.type === 'doctype') { return false; } }; diff --git a/plugins/removeXMLProcInst.js b/plugins/removeXMLProcInst.js index e3f2a1e4..7a3e4d12 100644 --- a/plugins/removeXMLProcInst.js +++ b/plugins/removeXMLProcInst.js @@ -18,7 +18,7 @@ exports.description = 'removes XML processing instructions'; * @author Kir Belevich */ exports.fn = function (item) { - return !( - item.processinginstruction && item.processinginstruction.name === 'xml' - ); + if (item.type === 'instruction' && item.name === 'xml') { + return false; + } }; diff --git a/test/svg2js/_index.js b/test/svg2js/_index.js index 86cc7211..ce65d710 100644 --- a/test/svg2js/_index.js +++ b/test/svg2js/_index.js @@ -49,53 +49,30 @@ describe('svg2js', function () { }); }); - describe('root.content[0].processinginstruction', function () { - it('should exist', function () { - expect(root.content[0].processinginstruction).to.exist; - }); - - it('should be an instance of Object', function () { - expect(root.content[0].processinginstruction).to.be.an.instanceOf( - Object - ); - }); - - it('should have property "name" with value "xml"', function () { - expect(root.content[0].processinginstruction).to.have.property( - 'name', - 'xml' - ); - }); - - it('should have property "body" with value `version="1.0" encoding="utf-8"`', function () { - expect(root.content[0].processinginstruction).to.have.property( - 'body', - 'version="1.0" encoding="utf-8"' - ); + it('the first node should be instruction', () => { + expect(root.content[0]).to.include({ + type: 'instruction', + name: 'xml', + value: 'version="1.0" encoding="utf-8"', }); }); - describe('root.content[1].comment', function () { - it('should exist', function () { - expect(root.content[1].comment).to.exist; - }); - - it('should equal "Generator: Adobe Illustrator…"', function () { - expect(root.content[1].comment).to.equal( - 'Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)' - ); + it('the second node should be comment', () => { + expect(root.content[1]).to.include({ + type: 'comment', + value: + 'Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)', }); }); - describe('root.content[2].doctype', function () { - it('should exist', function () { - expect(root.content[2].doctype).to.exist; - }); - - it('should eventually equal " svg PUBLIC…"', function () { - expect(root.content[2].doctype).to.equal( - ' svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"' - ); + it('the third node should be doctype', () => { + expect(root.content[2]).to.deep.include({ + type: 'doctype', + name: 'svg', + data: { + doctype: + ' svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"', + }, }); });