Giter VIP home page Giter VIP logo

svg-slim's People

Contributors

benboba avatar dependabot[bot] avatar tombyrer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

svg-slim's Issues

[archive] CLI-tool svgSLIM

summary

I've written a small CLI slimmer. As you can see, I'm not an advanced JS-coder, but perhaps it helps others.

usage

node svgSlim.js pictogramm.svg > new.svg
<othertool> | node svgSlim.js > new.svg
<othertool> | node svgSlim.js /dev/stdin > new.svg
<othertool> | node svgSlim.js - > new.svg
cat pictogramm.svg | node svgSlim.js > new.svg
< pictogramm.svg node svgSlim.js > new.svg

code

'use strict';

function MergeRecursive(obj1, obj2) {
    // based on https://stackoverflow.com/a/383245 - (c) users Markus etc. under CC BY-SA 3.0
    for (let p in obj2) {
        try {
            // property in destination object set; update its value
            if (obj2[p].constructor == Object) {
                obj1[p] = MergeRecursive(obj1[p], obj2[p]);
            } else {
                obj1[p] = obj2[p];
            }
        } catch(e) {
            // property in destination object not set; create it and set its value
            obj1[p] = obj2[p];
        }
    }
    return obj1;
}

const defaultConfig = {
    "rules": {
        "collapse-g": true,
        "collapse-textwrap": true,
        "combine-path": [ false, {
                "disregardFill": false,
                "disregardOpacity": false
            }
        ],
        "combine-transform": true,
        "compute-path": true,
        "rm-attribute": [ true, {
                "keepAria": false,
                "keepEvent": false
            }
        ],
        "rm-comments": true,
        "rm-doctype": true,
        "rm-hidden": true,
        "rm-irregular-nesting": [ true, {
                "ignore": []
            }
        ],
        "rm-irregular-tag": [ true, {
                "ignore": []
            }
        ],
        "rm-px": true,
        "rm-unnecessary": [ true, {
                "tags": [
                    "desc",
                    "discard",
                    "foreignObject",
                    "video",
                    "audio",
                    "iframe",
                    "canvas",
                    "metadata",
                    "script",
                    "title",
                    "unknown",
                    "image"
                ]
            }
        ],
        "rm-version": true,
        "rm-viewbox": true,
        "rm-xml-decl": true,
        "rm-xmlns": true,
        "shorten-animate": [ true, {
                "remove": false
            }
        ],
        "shorten-class": true,
        "shorten-color": [ true, {
                "rrggbbaa": false
            }
        ],
        "shorten-decimal-digits": true,
        "shorten-defs": true,
        "shorten-filter": true,
        "shorten-id": true,
        "shorten-shape": true,
        "shorten-style-attr": true,
        "shorten-style-tag": [ true, {
                "deepShorten": true
            }
        ],
    },
    "params": {
        "sizeDigit": 2,
        "angelDigit": 2,
        "trifuncDigit": 3,
        "opacityDigit": 3,
        "thinning": 0,
        "straighten": 0,
        "mergePoint": 0,
        "exchangeStyle": false,
        "rmAttrEqDefault": true
    },
    "browsers": ["defaults"]
};

const userConfig = {
    "params": {
        "sizeDigit": 5,
        "angelDigit": 5,
        "trifuncDigit": 5
    }
};

const fs = require('fs');
const svgSlimming = require('svg-slim');
const fileOrStdin = require('file-or-stdin');
const args = process.argv.slice(2);

async function main() {
    const svgFN = (args[0] === '-') ? '/dev/stdin' : args[0];
    
    try {
        const svgcode = await fileOrStdin(svgFN, 'utf8');
        try {
            const config = MergeRecursive(defaultConfig, userConfig);
            const result = await svgSlimming(svgcode, config)
            console.log(result);
        } catch(e) {
            console.error('Error while slimming. ' + e);
        }
    } catch(e) {
        console.error('File not found. ' + e);
    }
    return;
}

main();

[archive] config based on current defaults

I've just created a config based on the current defaults (3e81e7a). This might help others with playing with the settings - at least it helped my.

{
    "collapse-g": [ true ],
    "collapse-textwrap": [ true ],
    "combine-path": [ true, {
            "disregardFill": false,
            "disregardOpacity": false
        }
    ],
    "combine-transform": [ true, {
            "angelDigit": 2,
            "sizeDigit": 2,
            "trifuncDigit": 3
        }
    ],
    "compute-path": [ true, {
            "angelDigit": 2,
            "sizeDigit": 2,
            "straighten": 0,
            "thinning": 0
        }
    ],
    "rm-attribute": [ true, {
            "keepAria": false,
            "keepEvent": false,
            "rmDefault": true
        }
    ],
    "rm-comments": [ true ],
    "rm-doctype": [ true ],
    "rm-hidden": [ true ],
    "rm-irregular-nesting": [ true, {
            "ignore": []
        }
    ],
    "rm-irregular-tag": [ true, {
            "ignore": []
        }
    ],
    "rm-px": [ true ],
    "rm-unnecessary": [ true, {
            "tags": [
                "desc",
                "discard",
                "foreignObject",
                "video",
                "audio",
                "iframe",
                "canvas",
                "metadata",
                "script",
                "title",
                "unknown",
                "image"
            ]
        }
    ],
    "rm-version": [ true ],
    "rm-viewbox": [ true ],
    "rm-xml-decl": [ true ],
    "rm-xmlns": [ true ],
    "shorten-animate": [ true, {
            "remove": false
        }
    ],
    "shorten-class": [ true ],
    "shorten-color": [ true, {
            "opacityDigit": 3,
            "rrggbbaa": false
        }
    ],
    "shorten-decimal-digits": [ true, {
            "angelDigit": 2,
            "sizeDigit": 2
        }
    ],
    "shorten-defs": [ true ],
    "shorten-filter": [ true ],
    "shorten-id": [ true ],
    "shorten-shape": [ true, {
            "thinning": 0
        }
    ],
    "shorten-style-attr": [ true, {
            "exchange": false,
            "rmDefault": true
        }
    ],
    "shorten-style-tag": [ true, {
            "deepShorten": true,
            "rmDefault": true
        }
    ]
}

rm-hidden 需要进一步完善

例如:use、patten 的自我嵌套或循环嵌套
某些元素当 width 和 height 为负或为 0 时不可渲染等
需要根据 svg 规范进行改进

feature request: create classes from styles

acknowledgement

First of all, thanks for this nice tool. It's by far the best solution on the web. Good work.

feature request

I've got SVGs with lots of text nodes, which have the same styling. So, it's repeated over and over, which increases the size. Would it be possible to create classes to slim the file down even more? This would save many bytes.

what it looks like

<text style="font-family:Arial;font-size:13.31;font-stretch:Normal;font-weight:400;letter-spacing:0;word-spacing:0" dx="206.4" dy="285.43">70</text>
<text style="font-family:Arial;font-size:13.31;font-stretch:Normal;font-weight:400;letter-spacing:0;word-spacing:0" dx="206.4" dy="253.69">80</text>
<text style="font-family:Arial;font-size:13.31;font-stretch:Normal;font-weight:400;letter-spacing:0;word-spacing:0" dx="206.4" dy="221.95">90</text>
<text style="font-family:Arial;font-size:13.31;font-stretch:Normal;font-weight:400;letter-spacing:0;word-spacing:0" dx="198.7" dy="190.21">100</text>

what it could look like

<style type="text/css">
    .textA { font-family: Arial; font-size: 13.31; font-stretch: Normal; font-weight: 400; letter-spacing: 0; word-spacing: 0 }
</style>
<text class="textA" dx="206.4" dy="285.43">70</text>
<text class="textA" dx="206.4" dy="253.69">80</text>
<text class="textA" dx="206.4" dy="221.95">90</text>
<text class="textA" dx="198.7" dy="190.21">100</text>

[bug] whitespace gets introduced within <text>

summary

In 454349f, some whitespace gets introduced within text-tag.

incoming SVG

<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="1000" height="150">
  <text font-size="20px" x="500" y="100">
      <tspan>fixme</tspan>
  </text>
</svg>

after processing with svg-slim

<svg xmlns="http://www.w3.org/2000/svg" width="1e3" height="150"><text font-size="20" x="5e2" y="1e2"> fixme </text></svg>

[feature request] merge styles of nested TSPANs

summary

As discussed in #27, sometimes an SVG can contain nested TSPAN-elements. That's bad of course. But perhaps we can fix this. As you can see, the styled of the inner TSPAN gets lost. It contains fill: red aka fill: #FF0000;, which gets lost right now. Also, the x and y coordinates of the surrounding TSPAN gets lost (this is fine in this case since they're zero).

It should be discussed, what to do in such cases. I think the lower solution might be fine?

incoming SVG

<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="900" height="150">
  <text x="500.298343" y="115.726494" style="fill:#00FF00;">
     <tspan x="0.000" y="0.000">
       <tspan style="fill:#FF0000;">fixme</tspan>
     </tspan>
  </text>
</svg>

incoming processed SVG

<svg xmlns="http://www.w3.org/2000/svg" width="9e2" height="150">
  <text x="500.29834" y="115.72649" fill="#0f0">
    <tspan>fixme</tspan>
  </text>
</svg>

one solution

<svg xmlns="http://www.w3.org/2000/svg" width="9e2" height="150">
  <text x="500.29834" y="115.72649" fill="#0f0">
    <tspan fill="red" x="0" y="0">fixme</tspan>
  </text>
</svg>

Verify the style of each element

The style of each element should be analyzed in detail, rather than judging whether there is a style tag, so that it will no longer rely on the exchangeStyle configuration item

Unable to parse style to attribute

While optimizing some SVGs with nodeJS I have encountered my several svg files giving style issues.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
    <defs>
        <style>.a{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}</style>
    </defs>
    <title>3d-box-corner</title>
    <line class="a" x1="12.03" y1="1.5" x2="12.03" y2="6"/>
    <polygon class="a" points="12.03 6 4.03 9.5 12.03 13 20.03 9.5 12.03 6"/>
    <polyline class="a" points="4.03 9.5 4.03 19 12.03 22.5 20.03 19 20.03 9.5"/>
    <line class="a" x1="12.03" y1="13" x2="12.03" y2="22.5"/>
    <line class="a" x1="1.03" y1="20.496" x2="4.03" y2="19"/>
    <line class="a" x1="20.03" y1="19" x2="23" y2="20.482"/>
</svg>

If I tried to convert this SVG it converts this into :

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0,0,24,24"><path d="m12.03,1.5V6m0,0-8,3.5,8,3.5,8-3.5-8-3.5zm-8,3.5V19l8,3.5,8-3.5V9.5m-8,3.5v9.5m-11-2,3-1.5m16,0L23,20.48" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/></svg>

which is okay, it does the job, converting my <style> into attribute of a single path.
But when I tried to convert this one into a single path svg

<svg id="Light" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
    <defs>
        <style>.cls-1{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}</style>
    </defs>
    <title>multiple-actions-lock</title>
    <g id="_10_23" data-name="10*23">
        <path class="cls-1" d="M7.5,23.5l.5-6h2.5V14a5,5,0,0,0-10,0v3.5H3l.5,6Z"/>
        <circle class="cls-1" cx="5.5" cy="4" r="3.5"/>
    </g>
    <g id="_10_23_-_cut" data-name="10*23 - cut">
        <g id="_Group_" data-name="&lt;Group&gt;">
            <path class="cls-1" d="M17.439,10.37a5.006,5.006,0,0,0-5.561-.9"/>
            <circle class="cls-1" cx="14" cy="4.5" r="3"/>
        </g>
    </g>
    <rect class="cls-1" x="14.5" y="16.5" width="9" height="7" rx="1" ry="1"/>
    <path class="cls-1" d="M19,19a1,1,0,1,0,1,1,1,1,0,0,0-1-1Z"/>
    <path class="cls-1" d="M16.5,16.5V15a2.5,2.5,0,0,1,5,0v1.5"/>
</svg>

it gives this error instead of converting it.

\dist\index.js:10102
                    dom.styletag.childNodes[0].textContent = cssText;
                                                           ^

TypeError: Cannot set properties of undefined (setting 'textContent')
    at createXML (C:\Users\tidus\Projects\depauli-icons\node_modules\svg-slim\dist\index.js:10102:53)
    at C:\Users\tidus\Projects\depauli-icons\node_modules\svg-slim\dist\index.js:10125:18

What I don't understand is they both have the same <style> tags but one of them is giving issue. I tried to change class name to like the first working example but still giving error.

shorten-id 的一个 bug

当一个 id 被多处引用,但最后发现不存在时,实际上只有第一处引用被正确移除了

[bug] text in nested tspans gets removed

summary

Text in nested tspans gets removed when using defaults. I'm using v1.5.3

incoming SVG file (Inkscape v1.0.1 - plain-svg-output)

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0" width="800" height="600" id="svg2020">
    <text xml:space="preserve" style="font-size:24.000000px;font-style:normal;font-variant:normal;font-weight:700;font-stretch:Normal;line-height:125.000000%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif;text-align:start;text-anchor:start;" transform="matrix(1.000000,-0.000000,0.000000,1.000000,200,200)" x="0.000000" y="0.000000" id="text2018">
        <tspan x="0.000000" y="0.000000" id="tspan2016">
            <tspan dx="0.000000" dy="0.000000" style="fill:#000000;font-size:24.000000px;font-style:normal;font-variant:normal;font-weight:700;font-stretch:Normal;font-family: sans-serif;" id="tspan2014">fixme</tspan>
        </tspan>
    </text>
</svg>

what slimming looks like

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="8e2" height="6e2">
  <text style="font-size:24;font-weight:700;font-stretch:Normal;letter-spacing:0;word-spacing:0;font-family:sans-serif" dx="2e2" dy="2e2">
    <tspan x="0" y="0"> </tspan>
  </text>
</svg>

what it should look like

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="8e2" height="6e2">
  <text style="font-size:24;font-weight:700;font-stretch:Normal;letter-spacing:0;word-spacing:0;font-family:sans-serif" dx="2e2" dy="2e2">fixme</text>
</svg>

[feature request] keep unit for font-size

summary

Some browsers, like Internet Explorer 11, need a unit at font-size. Seems like config browsers: [] is perfect for this in the future.

incoming SVG

<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="1000" height="150">
  <text font-size="20px" x="500" y="100">
      <tspan>fixme</tspan>
  </text>
</svg>

after processing with svg-slim

<svg xmlns="http://www.w3.org/2000/svg" width="1e3" height="150"><text font-size="20" x="5e2" y="1e2"> fixme </text></svg>

should be for IE11

<svg xmlns="http://www.w3.org/2000/svg" width="1e3" height="150"><text font-size="20px" x="5e2" y="1e2">fixme</text></svg>

A bad case

Before compression:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="7px" height="14px" viewBox="0 0 7 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <title>向左icon</title>
    <g id="向左icon" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
        <polyline id="路径备份" stroke="currentColor" points="6 13 1 6.74135516 6 1"></polyline>
    </g>
</svg>

After compression

<svg width="7" height="14" xmlns="http://www.w3.org/2000/svg"/>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.