Skip to content
This repository has been archived by the owner on Feb 12, 2019. It is now read-only.

Commit

Permalink
New stringify options
Browse files Browse the repository at this point in the history
- Remove deps
- New exports named/default

closes #8
  • Loading branch information
elrumordelaluz committed Oct 26, 2018
1 parent 051e8c6 commit 1afa35e
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 12 deletions.
1 change: 0 additions & 1 deletion package.json
Expand Up @@ -37,7 +37,6 @@
"clean-deep": "3.0.2",
"deep-rename-keys": "^0.2.1",
"omit-deep": "0.3.0",
"xml-printer": "1.1.3",
"xml-reader": "2.4.3"
},
"devDependencies": {
Expand Down
5 changes: 3 additions & 2 deletions src/index-es.js
@@ -1,3 +1,4 @@
import { svgson, stringify } from './svgson'
import svgson from './svgson'
import stringify from './stringify'
export default svgson
export { stringify }
export { stringify, svgson as parse }
3 changes: 2 additions & 1 deletion src/index-umd.js
@@ -1,2 +1,3 @@
import { svgson, stringify } from './svgson'
import svgson from './svgson'
import stringify from './stringify'
export default Object.assign({}, { parse: svgson, stringify })
37 changes: 37 additions & 0 deletions src/stringify.js
@@ -0,0 +1,37 @@
import { escapeText, escapeAttr } from './tools'

const stringify = (
ast,
{
transformAttr = (key, value, escape) => `${key}="${escape(value)}"`,
selfClose = true,
} = {}
) => {
if (Array.isArray(ast)) {
return ast.map(ast => stringify(ast, { transformAttr, selfClose })).join('')
}

if (ast.type === 'text') {
return escapeText(ast.value)
}

let attributes = ''
for (const attr in ast.attributes) {
const attrStr = transformAttr(
attr,
ast.attributes[attr],
escapeAttr,
ast.name
)
attributes += attrStr ? ` ${attrStr}` : ''
}

return ast.children.length || !selfClose
? `<${ast.name}${attributes}>${stringify(ast.children, {
transformAttr,
selfClose,
})}</${ast.name}>`
: `<${ast.name}${attributes}/>`
}

export default stringify
5 changes: 1 addition & 4 deletions src/svgson.js
Expand Up @@ -6,7 +6,6 @@ import {
camelize,
applyCompat,
} from './tools'
import xmlPrint from 'xml-printer'

const svgson = function svgson(
input,
Expand Down Expand Up @@ -52,6 +51,4 @@ const svgson = function svgson(
.then(res => (res.name === 'root' ? res.children : res))
}

const stringify = input => xmlPrint(input)

export { svgson, stringify }
export default svgson
19 changes: 19 additions & 0 deletions src/tools.js
Expand Up @@ -59,3 +59,22 @@ export const toCamelCase = prop =>
prop.replace(/[-|:]([a-z])/gi, (all, letter) => letter.toUpperCase())

const notCamelcase = prop => /^(data|aria)(-\w+)/.test(prop)

export const escapeText = text => {
if (text) {
const str = String(text)
return /[&<>]/.test(str)
? `<![CDATA[${str.replace(/]]>/, ']]]]><![CDATA[>')}]]>`
: str
}
return ''
}

export const escapeAttr = attr => {
return String(attr)
.replace(/&/g, '&amp;')
.replace(/'/g, '&apos;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
}
34 changes: 34 additions & 0 deletions test.js
Expand Up @@ -24,6 +24,12 @@ const optimizeSVG = (input, config) => {
const SVG =
'<svg viewBox="0 0 100 100" width="100" height="100"><circle r="15" data-name="stroke" stroke-linecap="round"/></svg>'

const SVG2 =
'<svg viewBox="0 0 100 100" width="100" height="100"><circle r="15" data-name="stroke" stroke-linecap="round" data-custom-data="{&amp;quot;foo&amp;quot;:{&amp;quot;bar&amp;quot;:&amp;quot;baz&amp;quot;}}"/></svg>'

const SVG_WITHOUT_WH =
'<svg viewBox="0 0 100 100"><circle r="15" data-name="stroke" stroke-linecap="round"/></svg>'

const MULTIPLE_SVG = `
<svg viewBox="0 0 100 100" width="100" height="100">
<circle r="15" data-name="first" stroke-linecap="round"/>
Expand Down Expand Up @@ -244,6 +250,34 @@ test('Stringify', async t => {
t.is(SVG, stringify(res))
})

test('Stringify using transformAttr', async t => {
const res = await svgson(SVG2)
t.is(
SVG2,
stringify(res, {
transformAttr: (key, value, escape) => {
return /^data-/.test(key)
? `${key}="${value}"`
: `${key}="${escape(value)}"`
},
})
)
})

test('Stringify using transformAttr to remove Attributes conditionally', async t => {
const res = await svgson(SVG)
t.is(
SVG_WITHOUT_WH,
stringify(res, {
transformAttr: (key, value, escape, name) => {
return name === 'svg' && /(width|height)/.test(key)
? null
: `${key}="${escape(value)}"`
},
})
)
})

test('Works with doctype', async t => {
const svg = `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
Expand Down
4 changes: 0 additions & 4 deletions yarn.lock
Expand Up @@ -4997,10 +4997,6 @@ xml-lexer@^0.2.2:
dependencies:
eventemitter3 "^2.0.0"

xml-printer@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/xml-printer/-/xml-printer-1.1.3.tgz#f87e5a08b6b89b8e1ab89f9649bb90d4f9684b78"

xml-reader@2.4.3:
version "2.4.3"
resolved "https://registry.yarnpkg.com/xml-reader/-/xml-reader-2.4.3.tgz#9f810caf7c425a5aafb848b1c45103c9e71d7530"
Expand Down

0 comments on commit 1afa35e

Please sign in to comment.