Skip to content

Commit

Permalink
React-compatible SVG generation
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmielnik committed Aug 14, 2018
1 parent 65d7744 commit dcd2877
Show file tree
Hide file tree
Showing 9 changed files with 428 additions and 6 deletions.
17 changes: 15 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"lodash.difference": "4.5.0",
"recast": "git+https://github.com/yuriyyakym/recast.git#newest",
"stable": "0.1.8",
"xml2js": "^0.4.19",
"yargs": "12.0.1"
},
"devDependencies": {
Expand Down
27 changes: 27 additions & 0 deletions src/__tests__/convert-svg-to-component.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { readDirectoryFilenames, readFile } = require('./test-utils');
const ConvertSvgToComponent = require('../refactorings/convert-svg-to-component');

const tests = readDirectoryFilenames('convert-svg-to-component/input')
.map((filename) => ({
name: filename,
input: readFile(`convert-svg-to-component/input/${filename}`),
output: readFile(`convert-svg-to-component/output/${filename}`)
}));

describe('convert-svg-to-component:canApply', () => {
const refactoring = new ConvertSvgToComponent();
tests.forEach((test) => {
it(`canApply: ${test.name}`, () => {
expect(refactoring.canApply(test.input)).toBeTruthy();
});
});
});

describe('convert-svg-to-component:refactor', () => {
const refactoring = new ConvertSvgToComponent();
tests.forEach((test) => {
it(`refactor: ${test.name}`, () => {
expect(refactoring.refactor(test.input)).toBe(test.output);
});
});
});
17 changes: 17 additions & 0 deletions src/__tests__/data/convert-svg-to-component/input/file1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="14px" viewBox="0 0 16 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
<title>Icons/16x16/toolbar/green/img-contained</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Brand" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-9.000000, -48.000000)">
<g id="Icons/16x16/toolbar/green/img-contained" transform="translate(9.000000, 47.000000)">
<g>
<rect id="shape-hold" x="0" y="0" width="16" height="16"></rect>
<path d="M0.5,4 L15.5,4 C15.7761424,4 16,4.22385763 16,4.5 L16,11.5 C16,11.7761424 15.7761424,12 15.5,12 L0.5,12 C0.223857625,12 3.38176876e-17,11.7761424 0,11.5 L0,4.5 C-3.38176876e-17,4.22385763 0.223857625,4 0.5,4 Z M0.5,13.5 L15.5,13.5 C15.7761424,13.5 16,13.7238576 16,14 L16,14.5 C16,14.7761424 15.7761424,15 15.5,15 L0.5,15 C0.223857625,15 3.38176876e-17,14.7761424 0,14.5 L0,14 C-3.38176876e-17,13.7238576 0.223857625,13.5 0.5,13.5 Z M0.5,1 L15.5,1 C15.7761424,1 16,1.22385763 16,1.5 L16,2 C16,2.27614237 15.7761424,2.5 15.5,2.5 L0.5,2.5 C0.223857625,2.5 3.38176876e-17,2.27614237 0,2 L0,1.5 C-3.38176876e-17,1.22385763 0.223857625,1 0.5,1 Z" id="icon.image-align-left" fill="#02ab5c"></path>
</g>
</g>
</g>
</g>
</svg>
15 changes: 15 additions & 0 deletions src/__tests__/data/convert-svg-to-component/output/file1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<svg width="16px" height="14px" viewBox="0 0 16 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
<title>Icons/16x16/toolbar/green/img-contained</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Brand" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<g id="Artboard" transform="translate(-9.000000, -48.000000)">
<g id="Icons/16x16/toolbar/green/img-contained" transform="translate(9.000000, 47.000000)">
<g>
<rect id="shape-hold" x="0" y="0" width="16" height="16" />
<path d="M0.5,4 L15.5,4 C15.7761424,4 16,4.22385763 16,4.5 L16,11.5 C16,11.7761424 15.7761424,12 15.5,12 L0.5,12 C0.223857625,12 3.38176876e-17,11.7761424 0,11.5 L0,4.5 C-3.38176876e-17,4.22385763 0.223857625,4 0.5,4 Z M0.5,13.5 L15.5,13.5 C15.7761424,13.5 16,13.7238576 16,14 L16,14.5 C16,14.7761424 15.7761424,15 15.5,15 L0.5,15 C0.223857625,15 3.38176876e-17,14.7761424 0,14.5 L0,14 C-3.38176876e-17,13.7238576 0.223857625,13.5 0.5,13.5 Z M0.5,1 L15.5,1 C15.7761424,1 16,1.22385763 16,1.5 L16,2 C16,2.27614237 15.7761424,2.5 15.5,2.5 L0.5,2.5 C0.223857625,2.5 3.38176876e-17,2.27614237 0,2 L0,1.5 C-3.38176876e-17,1.22385763 0.223857625,1 0.5,1 Z" id="icon.image-align-left" fill="#02ab5c" />
</g>
</g>
</g>
</g>
</svg>
9 changes: 5 additions & 4 deletions src/model/refactoring.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const parser = require('../utils/parser');
const defaultParser = require('../utils/parser');

const CODE_SEPARATOR = '\n================================\n';

class Refactoring {
constructor(transformations = []) {
constructor(parser = defaultParser, transformations = []) {
this.parser = parser;
this.transformations = transformations;
}

Expand All @@ -17,7 +18,7 @@ class Refactoring {

refactor(code) {
try {
parser.parse(code);
this.parser.parse(code);
} catch (error) {
return [
'Parsing failure - syntax error'
Expand All @@ -29,7 +30,7 @@ class Refactoring {

for (const transformation of transformations) {
try {
const ast = parser.parse(nextCode);
const ast = this.parser.parse(nextCode);
nextCode = transformation(nextCode, ast);
} catch (error) {
return [
Expand Down
70 changes: 70 additions & 0 deletions src/refactorings/convert-svg-to-component/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* TODO */
// specjalne handlowanie atrybutu "style" - string na obiekt

const { Refactoring } = require('../../model');
const settings = require('../../settings');
const { generateIndent } = require('../../utils');
const xmlParser = require('../../utils/xml-parser');
const SVG_ATTRIBUTES = require('./svg-attributes');

class ConvertSvgToComponent extends Refactoring {
constructor() {
super(xmlParser);
this.transformations = [
(code, jsXml) => this.refactorSvg(code, jsXml)
];
}

canApply() {
return true;
}

refactorSvg(code, jsXml) {
return this.buildNode('svg', jsXml.svg);
}

buildNode(name, node, level = 0) {
const attributes = this.buildAttributes(node);
const children = this.buildChildren(node, level + 1);

let builder = `<${name}`;
if (attributes) {
builder += ` ${attributes}`;
}
if (children) {
const indent = generateIndent(level * settings.indent);
builder += `>${settings.endOfLine}${children}${settings.endOfLine}${indent}</${name}>`;
} else {
builder += ' />';
}

return builder;
}

buildAttributes(node) {
const attributesObject = node.$ || {};
return Object.keys(attributesObject).map((key) => {
const value = attributesObject[key];
return `${SVG_ATTRIBUTES[key] || key}="${value}"`;
}).join(' ');
}

buildChildren(node, level) {
const childrenTags = Object.keys(node).filter((key) => key !== '$');
return childrenTags.map((tag) => {
const tagValue = node[tag];
if (Array.isArray(tagValue)) {
const firstElement = tagValue[0];
if (typeof firstElement === 'string') {
return `${generateIndent(level * settings.indent)}<${tag}>${firstElement}</${tag}>`;
}
return `${generateIndent(level * settings.indent)}${this.buildNode(tag, firstElement, level)}`;
} else if (typeof tagValue === 'object') {
return this.buildNode(tag, node, level + 1);
}
return '';
}).join(settings.endOfLine);
}
}

module.exports = ConvertSvgToComponent;
Loading

0 comments on commit dcd2877

Please sign in to comment.