RazrFalcon / svgcleaner

svgcleaner could help you to clean up your SVG files from the unnecessary data.
GNU General Public License v2.0
1.63k stars 94 forks source link

Optionally postprocess inline CSS to SVG attributes #134

Open sanmai-NL opened 6 years ago

sanmai-NL commented 6 years ago

This is an exploratory issue, I hope to get everyone’s views on this.

In some contexts, inline CSS limits compatibility of SVG data (e.g., given Web Content Security Policy restrictions, see plotly/plotly.js#2355). As noted in the previously mentioned issue, there exist equivalents of CSS style rules in the form of SVG attributes. Would you find it interesting to add (some amount of; optional) inline CSS -> SVG attributes postprocessing to svgcleaner?

sanmai-NL commented 6 years ago

For svgcleaner specifically, extracting all CSS and linking it in as external resource is a useful functionality too. This could even improve compression, which the functionality proposed in my opening post probably won’t, as there are specialized tools for CSS file compression.

RazrFalcon commented 6 years ago

Can you give some examples of what you need? Like input -> output.

sanmai-NL commented 6 years ago

Feature 1: translate inline CSS styles in SVG data into SVG attributes

Parameters:

Input

<svg viewBox='0 0 100 100' xmlns="http://www.w3.org/2000/svg">
  <style>
  circle {
    opacity: 0.5;
  }
  </style>
  <circle id='c1' r="32" cx="35" cy="65" style="fill: #F00;"/>
  <circle id='c2' r="32" cx="65" cy="65" style="fill: #0F0;"/>
  <circle id='c3' r="32" cx="50" cy="35" style="fill: #00F;"/>
</svg>

Output

<svg viewBox='0 0 100 100' xmlns="http://www.w3.org/2000/svg">
  <circle r="32" cx="35" cy="65" fill="#F00" opacity="0.5"/>
  <circle r="32" cx="65" cy="65" fill="#0F0" opacity="0.5"/>
  <circle r="32" cx="50" cy="35" fill="#00F" opacity="0.5"/>
</svg>

The output SVG data still works outside browsers (perhaps even better than the CSS-styled equivalent?). It also helps to control styling with Content-Security-Policy’s style-src.

Feature 2: unbundle SVG file into SVG data and CSS stylesheet

Parameters:

Input

<svg viewBox='0 0 100 100' xmlns="http://www.w3.org/2000/svg">
  <circle r="32" cx="35" cy="65" fill="#F00" opacity="0.5"/>
  <circle r="32" cx="65" cy="65" fill="#0F0" opacity="0.5"/>
  <circle r="32" cx="50" cy="35" fill="#00F" opacity="0.5"/>
</svg>

Output

SVG 1.1

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet href="svg1.css" type="text/css"?>
<svg id='svg1' viewBox='0 0 100 100' xmlns="http://www.w3.org/2000/svg">
  <circle id='c1' r="32" cx="35" cy="65"/>
  <circle id='c2' r="32" cx="65" cy="65"/>
  <circle id='c3' r="32" cx="50" cy="35"/>
</svg>

SVG 2

<svg id='svg1' viewBox='0 0 100 100' xmlns="http://www.w3.org/2000/svg">
  <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="svg1.css" type="text/css"/>
  <circle id='c1' r="32" cx="35" cy="65"/>
  <circle id='c2' r="32" cx="65" cy="65"/>
  <circle id='c3' r="32" cx="50" cy="35"/>
</svg>

svg1.css:

#svg1 #c1 {
    fill: #f00;
    opacity: 0.5;
}

#svg1 #c2 {
    fill: #0F0;
    opacity: 0.5;
}

#svg1 #c3 {
    fill: #00F;
    opacity: 0.5;
}

The separate CSS file, still uncompressed in the sample output, can then be processed by specialized tools. Moreover, this helps to control styling with Content-Security-Policy’s style-src.

RazrFalcon commented 6 years ago
  1. Already implemented. Default behavior. CSS support is minimal, at least for now.
  2. Can be implemented, but I can't call it optimization because we just extracting styles from the file. And yes, it can be done.
sanmai-NL commented 6 years ago

Alright! 2 would fit ‘cleaning’, but yeah, maybe not optimization per se.

sanmai-NL commented 6 years ago

I see there’s a mistake in the samples for the second feature. For my use case (CSP), I only need to extract all style tags and style attributes, not SVG attributes that have an SVG attribute equivalent. So for my use case the feature request is even simpler.

RazrFalcon commented 6 years ago

Some clarification needed: does it okay to store presentation properties as attributes and not as style attribute? If so - you can use --join-style-attributes no already.

sanmai-NL commented 6 years ago

Yes, based on my last comment that would suffice for me. (But not for extracting all presentation as external CSS to do postprocessing on that CSS).

So I understand, with --join-style-attributes no, all existent CSS in style tags and attributes (i.e., all non-external CSS) will be translated to SVG attributes?

RazrFalcon commented 6 years ago

So again to clarify: you need an option which will extract all presentation attributes to a separated CSS file?

sanmai-NL commented 6 years ago

A separate CSS file would be useful, but not critical (for the CSP use case). What is critical is removal of any style tags and attributes. Alternative to a separate CSS file, translating style tags and attributes to SVG attributes (i.e., other than style) would also work for me.

RazrFalcon commented 6 years ago

What is critical is removal of any style tags and attributes.

But this is already implemented.