A designer gave us a set of SVG assets for a project I’m working on. Unfortunately, they each had a <style>
tag, and each one used the same conflicting class names (.st0
, .st1
, .st2
, etc). I wrote a quick python script to convert the css rules to attributes so they wouldn’t conflict.
from bs4 import BeautifulSoup
import tinycss
import click
css_parser = tinycss.make_parser('page3')
# Known good list of attributes that can be applied inline.
# Feel free to expand this list if need be. These were just
# the only ones we needed.
STYLE_ATTRS = (
'fill', 'stroke', 'stroke-width', 'stroke-miterlimit',
)
def apply_styles(elem, declarations):
for decl in declarations:
if decl.name not in STYLE_ATTRS:
raise ValueError(
'unknown svg attribute: {}'.format(decl.name))
elem.attrs[decl.name] = decl.value.as_css()
@click.command()
@click.option('--infile', default='-', type=click.File('r'))
@click.option('--outfile', default='-', type=click.File('w'))
def inline_styles(infile, outfile):
soup = BeautifulSoup(infile.read(), 'html.parser')
stylesheet = css_parser.parse_stylesheet(
soup.find('style').text)
for rule in stylesheet.rules:
elems = soup.select(rule.selector.as_css())
for elem in elems:
apply_styles(elem, rule.declarations)
elem.attrs.pop('class')
soup.find('style').extract()
outfile.write(soup.prettify())
if __name__ == '__main__':
inline_styles()