From 6eca37184d61ff788577d20ee4e76be5e174fa7a Mon Sep 17 00:00:00 2001 From: Fernando Niwes Date: Mon, 10 Sep 2018 21:55:12 -0300 Subject: [PATCH] Support for TSpan --- src/__tests__/fixtures.test.js | 4 ++++ src/__tests__/parser.test.js | 10 ++++++++- src/converter.js | 38 ++++++++++++++++++++++++---------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/__tests__/fixtures.test.js b/src/__tests__/fixtures.test.js index 3b9d407..59726ec 100644 --- a/src/__tests__/fixtures.test.js +++ b/src/__tests__/fixtures.test.js @@ -44,6 +44,10 @@ const SIMPLE_SVG = ` baby + + + + T ` diff --git a/src/__tests__/parser.test.js b/src/__tests__/parser.test.js index 2017125..33a6b72 100644 --- a/src/__tests__/parser.test.js +++ b/src/__tests__/parser.test.js @@ -22,7 +22,7 @@ describe('svg-parser main lib', () => { expect(dom.childNodes[2].tagName).toBe('svg') expect(dom.documentElement.tagName).toBe('svg') expect(dom.documentElement.namespaceURI).toBe('http://www.w3.org/2000/svg') - expect(dom.documentElement.childNodes.length).toBe(5) + expect(dom.documentElement.childNodes.length).toBe(9) }) it('should return an svg in react native SVG format', () => { @@ -73,6 +73,14 @@ describe('svg-parser main lib', () => { expect(textElement.props.children).toEqual('baby') }) + it('handles tspan elements', () => { + const svg = parser(SIMPLE_SVG, SIMPLE_CSS) + const textElement = svg.props.children[3] + const tspanElement = textElement.props.children[0] + + expect(tspanElement.props.children).toEqual('T') + }) + it('readme example works', () => { const svgString = ` diff --git a/src/converter.js b/src/converter.js index e5534b9..92eb1c3 100644 --- a/src/converter.js +++ b/src/converter.js @@ -16,7 +16,8 @@ import Svg, { Text, Use, Defs, - Stop + Stop, + TSpan } from 'react-native-svg' const mapping = { @@ -35,7 +36,8 @@ const mapping = { 'radialGradient': RadialGradient, 'use': Use, 'defs': Defs, - 'stop': Stop + 'stop': Stop, + 'tspan': TSpan } function extractViewbox (markup) { @@ -170,20 +172,17 @@ function traverse (markup, config, i = 0) { } // map the tag to an element. - const Elem = mapping[ tagName.toLowerCase() ] + const Elem = mapping[tagName.toLowerCase()] // Note, if the element is not found it was not in the mapping. if (!Elem) { return null } - const children = (Elem === Text && markup.childNodes.length === 1) - ? markup.childNodes[0].data - : markup.childNodes.length ? Object.values(markup.childNodes).map((child) => { - return traverse(child, config, ++i) - }).filter((node) => { - return !!node - }) : [] + let children = [] + if (markup.childNodes) { + children = traverseChildNodes(getChildNodes(markup), config, ++i) + } const elemAttributes = {} attrs.forEach((attr) => { @@ -191,7 +190,24 @@ function traverse (markup, config, i = 0) { }) const k = i + Math.random() - return { children } + return {children} +} + +function getChildNodes (markup) { + return Object.keys(markup.childNodes) + .filter(n => n !== 'length') + .map(i => markup.childNodes[i]) +} + +function traverseChildNodes (nodes, config, i) { + // if there is just one node and that node have data return the data value + if (nodes.length === 1 && nodes[0].data) { + return nodes[0].data + } + + return nodes + .map(child => traverse(child, config, ++i)) + .filter(node => !!node) } export { extractViewbox, getCssRulesForAttr, findApplicableCssProps, addNonCssAttributes }