Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add style argument which can convert SVG attributes to CSS Style attribute (the opposite of style_to_xml.) #267

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
32 changes: 28 additions & 4 deletions scour/scour.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
from decimal import Context, Decimal, InvalidOperation, getcontext

import six
from six.moves import range, urllib
import urllib

from scour.stats import ScourStats
from scour.svg_regex import svg_parser
Expand Down Expand Up @@ -1792,9 +1792,22 @@ def repairStyle(node, options):
del styleMap['overflow']
num += 1

# now if any of the properties match known SVG attributes we prefer attributes
# over style so emit them and remove them from the style map
if options.style_to_xml:
if node.nodeType == Node.ELEMENT_NODE:
if options.style_type == "inline-css":
# Prefer inline style
# Remove known SVG attributes and store their values in style attribute
attributes = [node.attributes.item(i) for i in range(node.attributes.length)]
for attribute in attributes:
attributeName = attribute.nodeName
if attributeName in svgAttributes:
styleMap[attributeName] = attribute.nodeValue
node.removeAttribute(attributeName)
elif options.style_type == "preserve":
# Keep whatever style of attribute versus style the file currently has
pass
elif options.style_type == "attributes":
# now if any of the properties match known SVG attributes we prefer attributes
# over style so emit them and remove them from the style map
for propName in list(styleMap):
if propName in svgAttributes:
node.setAttribute(propName, styleMap[propName])
Expand Down Expand Up @@ -3948,6 +3961,10 @@ def format_usage(self, usage):
_option_group_optimization.add_option("--disable-style-to-xml",
action="store_false", dest="style_to_xml", default=True,
help="won't convert styles into XML attributes")
_option_group_optimization.add_option("--style",
action="store", type="string", dest="style_type", default="none", metavar="TYPE",
help="style type (overrides style-to-xml): none, preserve, inline-css, "
"attributes (default: none)")
_option_group_optimization.add_option("--disable-group-collapsing",
action="store_false", dest="group_collapse", default=True,
help="won't collapse <g> elements")
Expand Down Expand Up @@ -4064,6 +4081,8 @@ def parse_args(args=None, ignore_additional_args=False):
_options_parser.error("Value for --nindent should be positive (or zero), see --help")
if options.infilename and options.outfilename and options.infilename == options.outfilename:
_options_parser.error("Input filename is the same as output filename")
if options.style_type not in ['none', 'preserve', 'attributes', 'inline-css']:
_options_parser.error("Invalid value for --style, see --help")

return options

Expand All @@ -4081,6 +4100,10 @@ def sanitizeOptions(options=None):
sanitizedOptions = _options_parser.get_default_values()
sanitizedOptions._update_careful(optionsDict)

#For backwards compatibility, we support style_to_xml but style_type can override it.
if sanitizedOptions.style_type == 'none' and sanitizedOptions.style_to_xml:
sanitizedOptions.style_type = 'attributes'

return sanitizedOptions


Expand Down Expand Up @@ -4185,4 +4208,5 @@ def run():


if __name__ == '__main__':
print('running')
run()
41 changes: 41 additions & 0 deletions test_scour.py
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,47 @@ def runTest(self):
self.assertEqual(line.getAttribute('marker-end'), 'url(#m)')


class AttrToStyle(unittest.TestCase):

def runTest(self):
doc = scourXmlFile('unittests/attr-to-style.svg',
parse_args(['--style=inline-css']))
line = doc.getElementsByTagName('line')[0]
self.assertEqual(line.getAttribute('stroke'), '')
self.assertEqual(line.getAttribute('marker-start'), '')
self.assertEqual(line.getAttribute('marker-mid'), '')
self.assertEqual(line.getAttribute('marker-end'), '')

style_attribute = line.getAttribute('style')
rawStyles = style_attribute.split(';')
self.assertTrue("color:#FF0000" in rawStyles)
self.assertTrue("stroke:#000" in rawStyles)
self.assertTrue("marker-start:url(#m)" in rawStyles)
self.assertTrue("marker-end:url(#m)" in rawStyles)
self.assertTrue("marker-mid:url(#m)" in rawStyles)


class StylePreserve(unittest.TestCase):

def runTest(self):
doc = scourXmlFile('unittests/attr-to-style.svg',
parse_args(['--style=preserve']))

# First line uses attributes.
line = doc.getElementsByTagName('line')[0]
self.assertNotEqual(line.getAttribute('stroke'), '')
self.assertNotEqual(line.getAttribute('marker-start'), '')
self.assertNotEqual(line.getAttribute('marker-mid'), '')
self.assertNotEqual(line.getAttribute('marker-end'), '')

# Second line uses style attribute.
line = doc.getElementsByTagName('line')[1]
self.assertEqual(line.getAttribute('stroke'), '')
self.assertEqual(line.getAttribute('marker-start'), '')
self.assertEqual(line.getAttribute('marker-mid'), '')
self.assertEqual(line.getAttribute('marker-end'), '')


class PathCommandRewrites(unittest.TestCase):

def runTest(self):
Expand Down
10 changes: 10 additions & 0 deletions unittests/attr-to-style.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.