Search code examples
cssnode.jssvgstylusdata-uri

Stylus inline SVG data uri without base64 encoding


How can I embed a SVG data uri in CSS using Stylus preprocessor without the SVG being Base64 encoded?

Like this:

background: url('data:image/svg+xml;utf8,<svg>[...]</svg>');

instead of this:

background: url('data:image/svg+xml;base64,PD94bWwg[...]');

Normaly I've used stylus.url() to embed images, but it will also Base64 encode SVGs.

I want to use data uris instead of external files to save file requests. And I've realised that Base64 encoding SVGs actually adds bytes instead of reducing size.

I can't find a method to embed the SVG as-is.


Solution

  • As I couldn't find a established way to do this I had to solve it myself. I wrote a simple node module that wraps stylus.url() but replaces how SVGs are inlined.

    Link to the module: https://www.npmjs.com/package/stylus-inline-svg

    Except for some checks it basically does this:

    found = stylus.utils.lookup(url.string, options.paths);
    
    if(!found) return literal;
    
    buf = fs.readFileSync(found);
    
    buf = String(buf)
        .replace(/<\?xml(.+?)\?>/, '')
        .replace(/^\s+|\s+$/g, '')
        .replace(/(\r\n|\n|\r)/gm, '');
    
    return new stylus.nodes.Literal("url('data:image/svg+xml;utf8," + buf + "')");