Skip to content

Instantly share code, notes, and snippets.

@dmitriid
Created September 11, 2015 10:30
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmitriid/e3aa38043f054d6e0ae3 to your computer and use it in GitHub Desktop.
Save dmitriid/e3aa38043f054d6e0ae3 to your computer and use it in GitHub Desktop.
Convert svg files to virtual-dom's VTree
/*
Convert svg files to virtual-dom's VTree
To use the resulting tree
import svg from 'virtual-dom/virtual-hyperscript/svg'
if you use Cycle.js:
import {svg} from '@cycle/dom';
*/
import fs from 'fs';
import libxmljs from 'libxmljs';
import {js_beautify} from 'js-beautify';
function attr2h(attrs){
let attributes = {};
let dataSet = {};
for(const v of attrs){
const key = v.name();
const value = v.value();
const maybeData = key.split('-');
if(maybeData[0] === 'data'){
dataSet[maybeData[1]] = value;
} else {
attributes[key] = value;
}
}
attributes['dataset'] = dataSet;
return JSON.stringify(attributes);
}
function node2h(node) {
if (node.name() === 'text') {
const str = node.toString().trim();
return str === '' ? str : `'${str}'`;
}
const children = node.childNodes().reduce((acc, child) => {
const ch = node2h(child);
if(ch !== ''){
acc.push(ch);
}
return acc;
}, []).join(',\n');
const attrs = attr2h(node.attrs());
return js_beautify(`svg('${node.name()}', ${attrs}, [${children}])`);
}
export default function(what, saveTo){
var str = fs.readFileSync(what);
var doc = libxmljs.parseXml(str);
fs.writeFileSync(saveTo, node2h(doc.root()));
}
@dmitriid
Copy link
Author

Example, using an icon from http://useiconic.com

Original file

<svg xmlns="http://www.w3.org/2000/svg" class="iconic iconic-circle-check" width="128" height="128" viewBox="0 0 128 128">
  <g class="iconic-metadata">
    <title>Circle Check</title>
  </g>
  <defs>
    <clipPath id="iconic-size-lg-circle-check-clip-0">
      <path d="M0 0v128h128v-128h-128zm54.196 92.201l-23.853-23.853 5.657-5.657 17.891 17.891 39.813-44.23 5.946 5.352-45.453 50.498z" />
    </clipPath>
    <clipPath id="iconic-size-md-circle-check-clip-0">
      <path d="M0 0v32h32v-32h-32zm13.052 24.173l-6.173-6.173 2.121-2.121 3.948 3.948 9.951-10.946 2.22 2.018-12.067 13.274z" />
    </clipPath>
    <clipPath id="iconic-size-sm-circle-check-clip-0">
      <path d="M0 0v16h16v-16h-16zm7 11.414l-3.414-3.414 1.414-1.414 2 2 4-4 1.414 1.414-5.414 5.414z" />
    </clipPath>
  </defs>
  <g class="iconic-circle-check-lg iconic-container iconic-lg" data-width="128" data-height="128" display="inline">
    <circle cx="64" cy="64" r="64" clip-path="url(#iconic-size-lg-circle-check-clip-0)" class="iconic-circle-check-body iconic-property-fill" />
  </g>
  <g class="iconic-circle-check-md iconic-container iconic-md" data-width="32" data-height="32" display="none" transform="scale(4)">
    <circle cx="16" cy="16" r="16" clip-path="url(#iconic-size-md-circle-check-clip-0)" class="iconic-circle-check-body iconic-property-fill" />
  </g>
  <g class="iconic-circle-check-sm iconic-container iconic-sm" data-width="16" data-height="16" display="none" transform="scale(8)">
    <circle cx="8" cy="8" r="8" clip-path="url(#iconic-size-sm-circle-check-clip-0)" class="iconic-circle-check-body iconic-property-fill" />
  </g>
</svg>

Convert

import svg2virtual from './svg-to-virtual-dom.js';

svg2virtual('./circle-check.svg', '/temp/circle-check.js');

Result:

svg('svg', {
    "class": "iconic iconic-circle-check",
    "width": "128",
    "height": "128",
    "viewBox": "0 0 128 128",
    "dataset": {}
}, [svg('g', {
    "class": "iconic-metadata",
    "dataset": {}
}, [svg('title', {
    "dataset": {}
}, ['Circle Check'])]),
    svg('defs', {
        "dataset": {}
    }, [svg('clipPath', {
        "id": "iconic-size-lg-circle-check-clip-0",
        "dataset": {}
    }, [svg('path', {
        "d": "M0 0v128h128v-128h-128zm54.196 92.201l-23.853-23.853 5.657-5.657 17.891 17.891 39.813-44.23 5.946 5.352-45.453 50.498z",
        "dataset": {}
    }, [])]),
        svg('clipPath', {
            "id": "iconic-size-md-circle-check-clip-0",
            "dataset": {}
        }, [svg('path', {
            "d": "M0 0v32h32v-32h-32zm13.052 24.173l-6.173-6.173 2.121-2.121 3.948 3.948 9.951-10.946 2.22 2.018-12.067 13.274z",
            "dataset": {}
        }, [])]),
        svg('clipPath', {
            "id": "iconic-size-sm-circle-check-clip-0",
            "dataset": {}
        }, [svg('path', {
            "d": "M0 0v16h16v-16h-16zm7 11.414l-3.414-3.414 1.414-1.414 2 2 4-4 1.414 1.414-5.414 5.414z",
            "dataset": {}
        }, [])])]),
    svg('g', {
        "class": "iconic-circle-check-lg iconic-container iconic-lg",
        "display": "inline",
        "dataset": {
            "width": "128",
            "height": "128"
        }
    }, [svg('circle', {
        "cx": "64",
        "cy": "64",
        "r": "64",
        "clip-path": "url(#iconic-size-lg-circle-check-clip-0)",
        "class": "iconic-circle-check-body iconic-property-fill",
        "dataset": {}
    }, [])]),
    svg('g', {
        "class": "iconic-circle-check-md iconic-container iconic-md",
        "display": "none",
        "transform": "scale(4)",
        "dataset": {
            "width": "32",
            "height": "32"
        }
    }, [svg('circle', {
        "cx": "16",
        "cy": "16",
        "r": "16",
        "clip-path": "url(#iconic-size-md-circle-check-clip-0)",
        "class": "iconic-circle-check-body iconic-property-fill",
        "dataset": {}
    }, [])]),
    svg('g', {
        "class": "iconic-circle-check-sm iconic-container iconic-sm",
        "display": "none",
        "transform": "scale(8)",
        "dataset": {
            "width": "16",
            "height": "16"
        }
    }, [svg('circle', {
        "cx": "8",
        "cy": "8",
        "r": "8",
        "clip-path": "url(#iconic-size-sm-circle-check-clip-0)",
        "class": "iconic-circle-check-body iconic-property-fill",
        "dataset": {}
    }, [])])])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment