mirror of
https://github.com/svg/svgo.git
synced 2025-07-28 09:22:00 +03:00
global refactoring dump
This commit is contained in:
250
.svgo.yml
250
.svgo.yml
@ -1,216 +1,40 @@
|
||||
plugins:
|
||||
|
||||
- name: removeDoctype
|
||||
active: true
|
||||
type: perItem
|
||||
# - name
|
||||
#
|
||||
# or:
|
||||
# - name: false
|
||||
# - name: true
|
||||
#
|
||||
# or:
|
||||
# - name:
|
||||
# param1: 1
|
||||
# param2: 2
|
||||
|
||||
- name: removeXMLProcInst
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: removeComments
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: removeMetadata
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: removeEditorsNSData
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: cleanupAttrs
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
newlines: true
|
||||
trim: true
|
||||
spaces: true
|
||||
|
||||
- name: convertStyleToAttrs
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: removeRasterImages
|
||||
active: false
|
||||
type: perItem
|
||||
|
||||
- name: cleanupNumericValues
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
floatPrecision: 3
|
||||
leadingZero: true
|
||||
defaultPx: true
|
||||
|
||||
- name: convertColors
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
names2hex: true
|
||||
rgb2hex: true
|
||||
shorthex: true
|
||||
|
||||
- name: removeUnknownsAndDefaults
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
SVGid: true
|
||||
unknownContent: true
|
||||
unknownAttrs: true
|
||||
defaultAttrs: true
|
||||
|
||||
- name: removeNonInheritableGroupAttrs
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: removeUselessStrokeAndFill
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
stroke: true
|
||||
fill: true
|
||||
|
||||
- name: removeViewBox
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: cleanupEnableBackground
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: removeHiddenElems
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
displayNone: true
|
||||
opacity0: true
|
||||
circleR0: true
|
||||
ellipseRX0: true
|
||||
ellipseRY0: true
|
||||
rectWidth0: true
|
||||
rectHeight0: true
|
||||
patternWidth0: true
|
||||
patternHeight0: true
|
||||
imageWidth0: true
|
||||
imageHeight0: true
|
||||
pathEmptyD: true
|
||||
polylineEmptyPoints: true
|
||||
polygonEmptyPoints: true
|
||||
|
||||
- name: removeEmptyText
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
text: true
|
||||
tspan: true
|
||||
tref: true
|
||||
|
||||
- name: moveElemsAttrsToGroup
|
||||
active: true
|
||||
type: perItemReverse
|
||||
|
||||
- name: collapseGroups
|
||||
active: true
|
||||
type: perItemReverse
|
||||
|
||||
- name: moveGroupAttrsToElems
|
||||
active: true
|
||||
type: perItemReverse
|
||||
|
||||
- name: convertPathData
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
applyTransforms: true
|
||||
straightCurves: true
|
||||
lineShorthands: true
|
||||
curveSmoothShorthands: true
|
||||
floatPrecision: 3
|
||||
removeUseless: true
|
||||
collapseRepeated: true
|
||||
leadingZero: true
|
||||
negativeExtraSpace: true
|
||||
|
||||
- name: convertTransform
|
||||
active: true
|
||||
type: perItem
|
||||
params:
|
||||
convertToShorts: true
|
||||
floatPrecision: 3
|
||||
matrixToTransform: true
|
||||
shortTranslate: true
|
||||
shortScale: true
|
||||
shortRotate: true
|
||||
removeUseless: true
|
||||
collapseIntoOne: true
|
||||
leadingZero: true
|
||||
negativeExtraSpace: false
|
||||
|
||||
- name: removeEmptyAttrs
|
||||
active: true
|
||||
type: perItem
|
||||
|
||||
- name: removeEmptyContainers
|
||||
active: true
|
||||
type: perItemReverse
|
||||
|
||||
- name: cleanupIDs
|
||||
active: true
|
||||
type: full
|
||||
params:
|
||||
remove: true
|
||||
minify: true
|
||||
|
||||
- name: removeUnusedNS
|
||||
active: true
|
||||
type: full
|
||||
|
||||
- name: cropAndCenterAlongPath
|
||||
active: false
|
||||
type: full
|
||||
params:
|
||||
hcrop: true
|
||||
vcenter: true
|
||||
floatPrecision: 3
|
||||
leadingZero: true
|
||||
negativeExtraSpace: true
|
||||
|
||||
svg2js:
|
||||
|
||||
strict: true
|
||||
trim: true
|
||||
normalize: true
|
||||
lowercase: true
|
||||
xmlns: true
|
||||
position: false
|
||||
|
||||
js2svg:
|
||||
|
||||
doctypeStart: "<!DOCTYPE"
|
||||
doctypeEnd: ">"
|
||||
procInstStart: "<?"
|
||||
procInstEnd: "?>"
|
||||
tagOpenStart: "<"
|
||||
tagOpenEnd: ">"
|
||||
tagCloseStart: "</"
|
||||
tagCloseEnd: ">"
|
||||
tagShortStart: "<"
|
||||
tagShortEnd: "/>"
|
||||
attrStart: "=\""
|
||||
attrEnd: "\""
|
||||
commentStart: "<!--"
|
||||
commentEnd: "-->"
|
||||
cdataStart: "<![CDATA["
|
||||
cdataEnd: "]]>"
|
||||
textStart: ""
|
||||
textEnd: ""
|
||||
indent: " "
|
||||
entities:
|
||||
"&": "&"
|
||||
"'": "'"
|
||||
"\"": """
|
||||
">": ">"
|
||||
"<": "<"
|
||||
pretty: false
|
||||
- removeDoctype
|
||||
- removeXMLProcInst
|
||||
- removeComments
|
||||
- removeMetadata
|
||||
- removeEditorsNSData
|
||||
- cleanupAttrs
|
||||
- convertStyleToAttrs
|
||||
- removeRasterImages
|
||||
- cleanupNumericValues
|
||||
- convertColors
|
||||
- removeUnknownsAndDefaults
|
||||
- removeNonInheritableGroupAttrs
|
||||
- removeUselessStrokeAndFill
|
||||
- removeViewBox
|
||||
- cleanupEnableBackground
|
||||
- removeHiddenElems
|
||||
- removeEmptyText
|
||||
- moveElemsAttrsToGroup
|
||||
- collapseGroups
|
||||
- moveGroupAttrsToElems
|
||||
- convertPathData
|
||||
- convertTransform
|
||||
- removeEmptyAttrs
|
||||
- removeEmptyContainers
|
||||
- cleanupIDs
|
||||
- removeUnusedNS
|
||||
- cropAndCenterAlongPath
|
||||
|
106
lib/svgo.js
106
lib/svgo.js
@ -5,118 +5,32 @@
|
||||
*
|
||||
* @see http://deepsweet.github.com/svgo/
|
||||
*
|
||||
* @module svgo
|
||||
*
|
||||
* @author Kir Belevich <kir@soulshine.in> (https://github.com/deepsweet)
|
||||
* @copyright © 2012 Kir Belevich
|
||||
* @license MIT https://raw.github.com/deepsweet/svgo/master/LICENSE
|
||||
*/
|
||||
|
||||
var INHERIT = require('inherit'),
|
||||
Q = require('q'),
|
||||
FS = require('fs'),
|
||||
CONFIG = require('./svgo/config'),
|
||||
var CONFIG = require('./svgo/config'),
|
||||
SVG2JS = require('./svgo/svg2js'),
|
||||
PLUGINS = require('./svgo/plugins'),
|
||||
JS2SVG = require('./svgo/js2svg'),
|
||||
decodeSVGDatauri = require('./svgo/tools').decodeSVGDatauri;
|
||||
JS2SVG = require('./svgo/js2svg');
|
||||
|
||||
/**
|
||||
* @class SVGO.
|
||||
*/
|
||||
module.exports = INHERIT(/** @lends SVGO.prototype */{
|
||||
|
||||
/**
|
||||
* @param {Object} [config] custom config to extend default
|
||||
*
|
||||
* @constructs
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
__constructor: function(config) {
|
||||
var SVGO = module.exports = function(config) {
|
||||
|
||||
this.config = CONFIG(config);
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Optimize SVG data from string.
|
||||
*
|
||||
* @param {String} str input string
|
||||
*
|
||||
* @return {Object} output string deferred promise
|
||||
*/
|
||||
fromString: function(str) {
|
||||
SVGO.prototype.optimize = function(svgstr, callback) {
|
||||
|
||||
var startTime = Date.now();
|
||||
var config = this.config;
|
||||
|
||||
str = decodeSVGDatauri(str);
|
||||
SVG2JS(svgstr, function(svgjs) {
|
||||
|
||||
return this.config
|
||||
.then(function(config) {
|
||||
svgjs = PLUGINS(svgjs, config.plugins);
|
||||
|
||||
return SVG2JS(str, config.svg2js)
|
||||
.then(function(jsdata) {
|
||||
|
||||
var result = JS2SVG(PLUGINS(jsdata, config.plugins), config.js2svg);
|
||||
|
||||
result.info.inBytes = Buffer.byteLength(str, 'utf-8');
|
||||
result.info.outBytes = Buffer.byteLength(result.data, 'utf-8');
|
||||
|
||||
result.info.time = Date.now() - startTime;
|
||||
|
||||
return result;
|
||||
callback(JS2SVG(svgjs, config.js2svg));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Optimize SVG data from Stream.
|
||||
*
|
||||
* @param {Object} stream input stream
|
||||
*
|
||||
* @return {Object} output string deferred promise
|
||||
*/
|
||||
fromStream: function(stream) {
|
||||
|
||||
var deferred = Q.defer(),
|
||||
inputData = '',
|
||||
self = this;
|
||||
|
||||
stream.pause();
|
||||
|
||||
stream
|
||||
.on('data', function(chunk) {
|
||||
inputData += chunk;
|
||||
})
|
||||
.once('end', function() {
|
||||
deferred.resolve(inputData);
|
||||
})
|
||||
.resume();
|
||||
|
||||
return deferred.promise
|
||||
.then(function(str) {
|
||||
|
||||
return self.fromString(str);
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Optimize SVG data from file.
|
||||
*
|
||||
* @param {String} path file path
|
||||
*
|
||||
* @return {Object} output string deferred promise
|
||||
*/
|
||||
fromFile: function(path) {
|
||||
|
||||
return this.fromStream(FS.createReadStream(path, { encoding: 'utf8' }));
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
222
lib/svgo/coa.js
222
lib/svgo/coa.js
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
require('colors');
|
||||
require('js-yaml');
|
||||
|
||||
var FS = require('fs'),
|
||||
QFS = require('q-fs'),
|
||||
PATH = require('path'),
|
||||
UTIL = require('util'),
|
||||
SVGO = require('../svgo'),
|
||||
info = JSON.parse(require('fs').readFileSync(__dirname + '/../../package.json')),
|
||||
PKG = require('../../package.json'),
|
||||
encodeSVGDatauri = require('./tools').encodeSVGDatauri,
|
||||
regSVGFile = /\.svg$/;
|
||||
|
||||
@ -15,20 +15,18 @@ var FS = require('fs'),
|
||||
* Command-Option-Argument.
|
||||
*
|
||||
* @see https://github.com/veged/coa
|
||||
*
|
||||
* @module coa
|
||||
*/
|
||||
module.exports = require('coa').Cmd()
|
||||
.helpful()
|
||||
.name(info.name)
|
||||
.title(info.description)
|
||||
.name(PKG.name)
|
||||
.title(PKG.description)
|
||||
.opt()
|
||||
.name('version').title('Version')
|
||||
.short('v').long('version')
|
||||
.only()
|
||||
.flag()
|
||||
.act(function() {
|
||||
return info.version;
|
||||
return PKG.version;
|
||||
})
|
||||
.end()
|
||||
.opt()
|
||||
@ -99,109 +97,144 @@ module.exports = require('coa').Cmd()
|
||||
|
||||
var input = args && args.input ? args.input : opts.input,
|
||||
output = args && args.output ? args.output : opts.output,
|
||||
string = opts.string,
|
||||
folder = opts.folder,
|
||||
svgo;
|
||||
config;
|
||||
|
||||
// w/o anything
|
||||
if (
|
||||
(!input || input === '-') &&
|
||||
!string &&
|
||||
!opts.string &&
|
||||
!opts.stdin &&
|
||||
!opts.folder &&
|
||||
process.stdin.isTTY
|
||||
) return this.usage();
|
||||
|
||||
// --config
|
||||
if (opts.config) {
|
||||
|
||||
// string
|
||||
if (opts.config.charAt(0) === '{') {
|
||||
config = JSON.parse(opts.config);
|
||||
|
||||
// external file
|
||||
} else {
|
||||
config = require(opts.config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// --pretty
|
||||
if (opts.pretty) {
|
||||
|
||||
config = config || {};
|
||||
config.js2svg = config.js2svg || {};
|
||||
config.js2svg.pretty = true;
|
||||
|
||||
}
|
||||
|
||||
// --folder
|
||||
if (folder) {
|
||||
optimizeFolder(folder, opts);
|
||||
if (opts.folder) {
|
||||
optimizeFolder(opts.folder, config);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// --string
|
||||
if (string) {
|
||||
svgo = new SVGO({ coa: opts }).fromString(string);
|
||||
}
|
||||
// --inpput
|
||||
if (input) {
|
||||
|
||||
// STDIN
|
||||
else if (input === '-') {
|
||||
svgo = new SVGO({ coa: opts }).fromStream(process.stdin);
|
||||
}
|
||||
if (input === '-') {
|
||||
|
||||
var data = '';
|
||||
|
||||
process.stdin.pause();
|
||||
|
||||
process.stdin
|
||||
.on('data', function(chunk) {
|
||||
data += chunk;
|
||||
})
|
||||
.once('end', function() {
|
||||
optimizeFromString(data, config, input, output);
|
||||
})
|
||||
.resume();
|
||||
|
||||
// file
|
||||
else if (input) {
|
||||
svgo = new SVGO({ coa: opts }).fromFile(input);
|
||||
} else {
|
||||
|
||||
FS.readFile(input, 'utf8', function(err, data) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return svgo.then(function(result) {
|
||||
optimizeFromString(data, config, input, output);
|
||||
});
|
||||
|
||||
// --datauri
|
||||
if (opts.datauri) {
|
||||
// convert to Data URI base64 string
|
||||
result.data = encodeSVGDatauri(result.data);
|
||||
}
|
||||
|
||||
// --string
|
||||
} else if (opts.string) {
|
||||
|
||||
optimizeFromString(opts.string, config, input, output);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function optimizeFromString(svgstr, config, input, output) {
|
||||
|
||||
var startTime = Date.now(config),
|
||||
time,
|
||||
inBytes = Buffer.byteLength(svgstr, 'utf8'),
|
||||
outBytes,
|
||||
svgo = new SVGO(config);
|
||||
|
||||
svgo.optimize(svgstr, function(result) {
|
||||
|
||||
outBytes = Buffer.byteLength(result.data, 'utf8');
|
||||
time = Date.now() - startTime;
|
||||
|
||||
// stdout
|
||||
if (output === '-' || (input === '-' && !output)) {
|
||||
|
||||
process.stdout.write(result.data + '\n');
|
||||
}
|
||||
|
||||
// file
|
||||
else {
|
||||
} else {
|
||||
|
||||
// if input is from file - overwrite it
|
||||
// overwrite input file if there is no output
|
||||
if (!output && input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
UTIL.puts('\r');
|
||||
saveFileAndPrintInfo(result, output, opts.pretty);
|
||||
|
||||
saveFileAndPrintInfo(result.data, output, inBytes, outBytes, time);
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
.done();
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Save file and print info.
|
||||
*
|
||||
* @param {Object} result SVGO result
|
||||
* @param {String} output output filename
|
||||
* @param {Boolean} pretty is pretty printed?
|
||||
*/
|
||||
function saveFileAndPrintInfo(result, output, pretty) {
|
||||
}
|
||||
|
||||
// output file
|
||||
output = FS.createWriteStream(output, { encoding: 'utf8' });
|
||||
output.write(result.data);
|
||||
output.end();
|
||||
function saveFileAndPrintInfo(data, path, inBytes, outBytes, time) {
|
||||
|
||||
FS.writeFile(path, data, 'utf8', function() {
|
||||
|
||||
// print time info
|
||||
printTimeInfo(result.info.time);
|
||||
printTimeInfo(time);
|
||||
|
||||
// print optimization profit info
|
||||
printProfitInfo(result.info.inBytes, result.info.outBytes);
|
||||
printProfitInfo(inBytes, outBytes);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print time info.
|
||||
*
|
||||
* @param {Number} time working time in ms
|
||||
*/
|
||||
function printTimeInfo(time) {
|
||||
|
||||
UTIL.puts('Done in ' + time + ' ms!');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print optimization profit info.
|
||||
*
|
||||
* @param {Number} inBytes input file byteLength
|
||||
* @param {Number} outBytes output file byteLength
|
||||
*/
|
||||
function printProfitInfo(inBytes, outBytes) {
|
||||
|
||||
var profitPercents = 100 - outBytes * 100 / inBytes;
|
||||
@ -215,55 +248,66 @@ function printProfitInfo(inBytes, outBytes) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize all *.svg files in a specific folder.
|
||||
*
|
||||
* @param {String} folder folder path
|
||||
* @param {Object} opts COA options
|
||||
*/
|
||||
function optimizeFolder(folder, opts) {
|
||||
function optimizeFolder(path, config) {
|
||||
|
||||
var svgo = new SVGO({ coa: opts });
|
||||
var svgo = new SVGO(config);
|
||||
|
||||
folder = PATH.resolve(process.cwd(), folder);
|
||||
// absoluted folder path
|
||||
path = PATH.resolve(process.cwd(), path);
|
||||
|
||||
UTIL.puts('\n' + folder + ':\n');
|
||||
UTIL.puts('\n' + path + ':\n');
|
||||
|
||||
// list directory
|
||||
QFS.list(folder).then(function(list) {
|
||||
// list folder content
|
||||
FS.readdir(path, function(err, files) {
|
||||
|
||||
list.forEach(function(item) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
var filename = item;
|
||||
files.forEach(function(filename) {
|
||||
|
||||
item = folder + '/' + item;
|
||||
// absoluted file path
|
||||
var filepath = PATH.resolve(path, filename);
|
||||
|
||||
// checkif item is a file
|
||||
QFS.isFile(item)
|
||||
.then(function(isFile) {
|
||||
// check if file name matches *.svg
|
||||
if (regSVGFile.test(filepath)) {
|
||||
|
||||
// and file name matches *.svg
|
||||
if (isFile && regSVGFile.test(item)) {
|
||||
FS.readFile(filepath, 'utf8', function(err, data) {
|
||||
|
||||
// then optimize it and output profit information
|
||||
return svgo.fromFile(item)
|
||||
.then(function(result) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
var startTime = Date.now(),
|
||||
time,
|
||||
inBytes = Buffer.byteLength(data, 'utf8'),
|
||||
outBytes;
|
||||
|
||||
svgo.optimize(data, function(result) {
|
||||
|
||||
outBytes = Buffer.byteLength(result.data, 'utf8');
|
||||
time = Date.now() - startTime;
|
||||
|
||||
FS.writeFile(filepath, result.data, 'utf8', function() {
|
||||
|
||||
UTIL.puts(filename + ':');
|
||||
saveFileAndPrintInfo(result, item, opts.pretty);
|
||||
|
||||
// print time info
|
||||
printTimeInfo(time);
|
||||
|
||||
// print optimization profit info
|
||||
printProfitInfo(inBytes, outBytes);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
.fail(function(e) {
|
||||
UTIL.puts(filename + ':\n' + String('Error! "' + e.message + '"').red + '\n');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
.done();
|
||||
|
||||
}
|
||||
|
@ -1,177 +1,166 @@
|
||||
'use strict';
|
||||
|
||||
var QFS = require('q-fs'),
|
||||
PATH = require('path'),
|
||||
YAML = require('js-yaml'),
|
||||
extend = require('./tools').extend,
|
||||
defaultConfigPath = PATH.resolve(__dirname, '../../.svgo.yml');
|
||||
require('js-yaml');
|
||||
|
||||
var EXTEND = require('node.extend');
|
||||
|
||||
/**
|
||||
* Read and/or extend default config file,
|
||||
* prepare and optimize plugins array.
|
||||
*
|
||||
* @module config
|
||||
*
|
||||
* @param {Object} [params] config object to extend or coa params
|
||||
*
|
||||
* @return {Object} config deferred promise
|
||||
* @param {Object} [config] input config
|
||||
* @return {Object} output config
|
||||
*/
|
||||
module.exports = function(params) {
|
||||
module.exports = function(config) {
|
||||
|
||||
return _getConfig(params).then(function(config) {
|
||||
var defaults = require('../../.svgo.yml');
|
||||
|
||||
config.plugins = preparePluginsArray(config.plugins);
|
||||
config.plugins = optimizePluginsArray(config.plugins);
|
||||
defaults.plugins = preparePluginsArray(defaults.plugins);
|
||||
|
||||
return config;
|
||||
if (config) {
|
||||
defaults = extendConfig(defaults, config);
|
||||
}
|
||||
|
||||
});
|
||||
defaults.plugins = optimizePluginsArray(defaults.plugins);
|
||||
|
||||
return defaults;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Get default or extended config.
|
||||
*
|
||||
* @param {Object} [params] config object to extend or coa params
|
||||
*
|
||||
* @return {Object} default or extended config
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function _getConfig(params) {
|
||||
|
||||
// if there are no any params then return default config
|
||||
if (!params) return readConfig(defaultConfigPath);
|
||||
|
||||
// COA params
|
||||
if (params.coa) {
|
||||
|
||||
params = params.coa;
|
||||
|
||||
return readConfig(defaultConfigPath)
|
||||
.then(function(defaultConfig) {
|
||||
|
||||
// --pretty
|
||||
if (params.pretty) defaultConfig.js2svg.pretty = true;
|
||||
|
||||
// --disable
|
||||
if (params.disable) return changePluginsState(params.disable, false, defaultConfig);
|
||||
|
||||
// --enable
|
||||
if (params.enable) return changePluginsState(params.enable, true, defaultConfig);
|
||||
|
||||
// --config
|
||||
if (params.config) {
|
||||
|
||||
var localConfigPath = PATH.resolve(process.cwd, params.config);
|
||||
|
||||
// check for the local config file
|
||||
return QFS.exists(localConfigPath)
|
||||
.then(function(exist) {
|
||||
|
||||
// if it doesn't exists then return default
|
||||
if (!exist) return defaultConfig;
|
||||
|
||||
// if it exists then return extended default
|
||||
return readConfig(localConfigPath);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return defaultConfig;
|
||||
|
||||
});
|
||||
|
||||
// inline {} params
|
||||
} else {
|
||||
|
||||
// return extended default
|
||||
return readConfig(defaultConfigPath)
|
||||
.then(function(defaultConfig) {
|
||||
|
||||
return extend(true, defaultConfig, params);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and YAML.parse config file by path.
|
||||
*
|
||||
* @param {String} path config path
|
||||
*
|
||||
* @return {Object} read config deferred promise
|
||||
*/
|
||||
function readConfig(path) {
|
||||
|
||||
return QFS.read(path)
|
||||
.then(function(data) {
|
||||
return YAML.load(data.toString());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Require() all plugins in array and convert it to array of arrays.
|
||||
* Require() all plugins in array.
|
||||
*
|
||||
* @param {Array} plugins input plugins array
|
||||
*
|
||||
* @return {Array} input plugins array of arrays
|
||||
*/
|
||||
function preparePluginsArray(plugins) {
|
||||
|
||||
return plugins.map(function(plugin) {
|
||||
plugin.fn = require('../../plugins/' + plugin.name)[plugin.name];
|
||||
var plugin,
|
||||
key;
|
||||
|
||||
return plugins.map(function(item) {
|
||||
|
||||
// {}
|
||||
if (typeof item === 'object') {
|
||||
|
||||
key = Object.keys(item)[0];
|
||||
plugin = require('../../plugins/' + key);
|
||||
|
||||
// name: {}
|
||||
if (typeof item[key] === 'object') {
|
||||
plugin.params = EXTEND(plugin.params || {}, item[key]);
|
||||
|
||||
// name: false
|
||||
} else if (item[key] === false) {
|
||||
plugin.active = false;
|
||||
|
||||
// name: true
|
||||
} else if (item[key] === true) {
|
||||
plugin.active = true;
|
||||
}
|
||||
|
||||
plugin.name = key;
|
||||
|
||||
// name
|
||||
} else {
|
||||
|
||||
plugin = require('../../plugins/' + item);
|
||||
plugin.name = item;
|
||||
|
||||
}
|
||||
|
||||
return plugin;
|
||||
|
||||
return [plugin];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend plugins with the custom config object.
|
||||
*
|
||||
* @param {Array} plugins input plugins
|
||||
* @param {Object} config config
|
||||
* @return {Array} output plugins
|
||||
*/
|
||||
function extendConfig(defaults, config) {
|
||||
|
||||
var key;
|
||||
|
||||
// plugins
|
||||
if (config.plugins) {
|
||||
|
||||
config.plugins.forEach(function(item) {
|
||||
|
||||
// {}
|
||||
if (typeof item === 'object') {
|
||||
|
||||
key = Object.keys(item)[0];
|
||||
|
||||
defaults.plugins.forEach(function(plugin) {
|
||||
|
||||
if (plugin.name === key) {
|
||||
// name: {}
|
||||
if (typeof item[key] === 'object') {
|
||||
plugin.params = EXTEND(plugin.params || {}, item[key]);
|
||||
plugin.active = true;
|
||||
|
||||
// name: false
|
||||
} else if (item[key] === false) {
|
||||
plugin.active = false;
|
||||
|
||||
// name: true
|
||||
} else if (item[key] === true) {
|
||||
plugin.active = true;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// svg2js
|
||||
if (config.svg2js) {
|
||||
defaults.svg2js = config.svg2js;
|
||||
}
|
||||
|
||||
// js2svg
|
||||
if (config.js2svg) {
|
||||
defaults.js2svg = config.js2svg;
|
||||
}
|
||||
|
||||
return defaults;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to group sequential elements of plugins array.
|
||||
*
|
||||
* @param {Object} plugins input plugins array
|
||||
*
|
||||
* @return {Array} output plugins array
|
||||
* @param {Object} plugins input plugins
|
||||
* @return {Array} output plugins
|
||||
*/
|
||||
function optimizePluginsArray(plugins) {
|
||||
|
||||
var prev;
|
||||
|
||||
plugins = plugins.filter(function(item) {
|
||||
plugins = plugins.map(function(item) {
|
||||
return [item];
|
||||
});
|
||||
|
||||
return plugins.filter(function(item) {
|
||||
|
||||
if (prev && item[0].type === prev[0].type) {
|
||||
prev.push(item[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
prev = item;
|
||||
|
||||
return true;
|
||||
|
||||
});
|
||||
|
||||
return plugins;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Change plugins state by names array.
|
||||
*
|
||||
* @param {Array} names plugins names
|
||||
* @param {Boolean} state active state
|
||||
* @param {Object} config original config
|
||||
*
|
||||
* @return {Object} changed config
|
||||
*/
|
||||
function changePluginsState(names, state, config) {
|
||||
|
||||
config.plugins.forEach(function(plugin) {
|
||||
if (names.indexOf(plugin.name) > -1) {
|
||||
plugin.active = state;
|
||||
}
|
||||
});
|
||||
|
||||
return config;
|
||||
|
||||
}
|
||||
|
@ -1,51 +1,59 @@
|
||||
'use strict';
|
||||
|
||||
var INHERIT = require('inherit'),
|
||||
extend = require('./tools').extend;
|
||||
var EXTEND = require('./tools').extend;
|
||||
|
||||
var defaults = {
|
||||
doctypeStart: '<!DOCTYPE',
|
||||
doctypeEnd: '>',
|
||||
procInstStart: '<?',
|
||||
procInstEnd: '?>',
|
||||
tagOpenStart: '<',
|
||||
tagOpenEnd: '>',
|
||||
tagCloseStart: '</',
|
||||
tagCloseEnd: '>',
|
||||
tagShortStart: '<',
|
||||
tagShortEnd: '/>',
|
||||
attrStart: '="',
|
||||
attrEnd: '"',
|
||||
commentStart: '<!--',
|
||||
commentEnd: '-->',
|
||||
cdataStart: '<![CDATA[',
|
||||
cdataEnd: ']]>',
|
||||
textStart: '',
|
||||
textEnd: '',
|
||||
indent: ' ',
|
||||
entities: {
|
||||
'&': '&',
|
||||
'\'': ''',
|
||||
'"': '"',
|
||||
'>': '>',
|
||||
'<': '<',
|
||||
},
|
||||
pretty: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert SVG-as-JS object to SVG (XML) string.
|
||||
*
|
||||
* @module js2svg
|
||||
*
|
||||
* @param {Object} jsdata input data
|
||||
* @param {Object} data input data
|
||||
* @param {Object} config config
|
||||
*
|
||||
* @return {Object} output data
|
||||
*/
|
||||
module.exports = function(jsdata, config) {
|
||||
module.exports = function(data, config) {
|
||||
|
||||
return new Converter(config).run(jsdata);
|
||||
return new JS2SVG(config).convert(data);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Converter
|
||||
*/
|
||||
var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
function JS2SVG(config) {
|
||||
|
||||
/**
|
||||
* @constructs
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
__constructor: function(config) {
|
||||
if (config) {
|
||||
this.config = EXTEND(true, {}, defaults, config);
|
||||
} else {
|
||||
this.config = defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shallow copy of converter config.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
this.config = extend({}, config);
|
||||
|
||||
/**
|
||||
* Current indent level hack.
|
||||
*
|
||||
* @type {Number}
|
||||
*/
|
||||
this.indentLevel = 0;
|
||||
|
||||
// pretty
|
||||
if (this.config.pretty) {
|
||||
this.config.doctypeEnd += '\n';
|
||||
this.config.procInstEnd += '\n';
|
||||
@ -57,16 +65,18 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
this.config.textEnd += '\n';
|
||||
}
|
||||
|
||||
},
|
||||
this.indentLevel = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Start conversion.
|
||||
*
|
||||
* @param {Object} svg-as-js data object
|
||||
* @param {Object} data input data
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
run: function(data) {
|
||||
JS2SVG.prototype.convert = function(data) {
|
||||
|
||||
var svg = '';
|
||||
|
||||
@ -104,14 +114,14 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
}
|
||||
};
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create indent string in accordance with the current node level.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
createIndent: function() {
|
||||
JS2SVG.prototype.createIndent = function() {
|
||||
|
||||
var indent = '';
|
||||
|
||||
@ -123,7 +133,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
|
||||
return indent;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create doctype tag.
|
||||
@ -132,13 +142,13 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
createDoctype: function(doctype) {
|
||||
JS2SVG.prototype.createDoctype = function(doctype) {
|
||||
|
||||
return this.config.doctypeStart +
|
||||
doctype +
|
||||
this.config.doctypeEnd;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create XML Processing Instruction tag.
|
||||
@ -147,7 +157,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
createProcInst: function(instruction) {
|
||||
JS2SVG.prototype.createProcInst = function(instruction) {
|
||||
|
||||
return this.config.procInstStart +
|
||||
instruction.name +
|
||||
@ -155,7 +165,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
instruction.body +
|
||||
this.config.procInstEnd;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create comment tag.
|
||||
@ -164,13 +174,13 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
createComment: function(comment) {
|
||||
JS2SVG.prototype.createComment = function(comment) {
|
||||
|
||||
return this.config.commentStart +
|
||||
comment +
|
||||
this.config.commentEnd;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create CDATA section.
|
||||
@ -179,13 +189,13 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
createCDATA: function(cdata) {
|
||||
JS2SVG.prototype.createCDATA = function(cdata) {
|
||||
|
||||
return this.config.cdataStart +
|
||||
cdata +
|
||||
this.config.cdataEnd;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create element tag.
|
||||
@ -194,7 +204,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
createElem: function(data) {
|
||||
JS2SVG.prototype.createElem = function(data) {
|
||||
|
||||
// beautiful injection for obtaining SVG information :)
|
||||
if (
|
||||
@ -223,7 +233,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
data.elem +
|
||||
this.createAttrs(data) +
|
||||
this.config.tagOpenEnd +
|
||||
this.run(data).data +
|
||||
this.convert(data).data +
|
||||
this.createIndent() +
|
||||
this.config.tagCloseStart +
|
||||
data.elem +
|
||||
@ -231,7 +241,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create element attributes.
|
||||
@ -240,7 +250,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
createAttrs: function(elem) {
|
||||
JS2SVG.prototype.createAttrs = function(elem) {
|
||||
|
||||
var attrs = '';
|
||||
|
||||
@ -256,7 +266,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
|
||||
return attrs;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create text node.
|
||||
@ -265,7 +275,7 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
createText: function(text) {
|
||||
JS2SVG.prototype.createText = function(text) {
|
||||
|
||||
// convert entities back
|
||||
for (var entity in this.config.entities) {
|
||||
@ -277,6 +287,4 @@ var Converter = INHERIT(/** @lends Nodes.prototype */{
|
||||
text +
|
||||
this.config.textEnd;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
@ -1,35 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var INHERIT = require('inherit'),
|
||||
extend = require('./tools').extend;
|
||||
var EXTEND = require('node.extend');
|
||||
|
||||
/**
|
||||
* @module jsAPI
|
||||
*
|
||||
* @class SVG-as-JS Nodes API.
|
||||
*/
|
||||
module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
var JSAPI = module.exports = function(data) {
|
||||
|
||||
/**
|
||||
* @constructs
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
__constructor: function(data) {
|
||||
EXTEND(this, data);
|
||||
|
||||
extend(this, data);
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if item is an element
|
||||
* (any, with a specific name or in a names array).
|
||||
*
|
||||
* @param {String|Array} [param] element name or names arrays
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isElem: function(param) {
|
||||
JSAPI.prototype.isElem = function(param) {
|
||||
|
||||
if (!param) return !!this.elem;
|
||||
|
||||
@ -37,18 +23,18 @@ module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
|
||||
return !!this.elem && this.elem === param;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if element is empty.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isEmpty: function() {
|
||||
JSAPI.prototype.isEmpty = function() {
|
||||
|
||||
return !this.content || !this.content.length;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if element has an attribute
|
||||
@ -56,10 +42,9 @@ module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @param {String} [name] attribute name
|
||||
* @param {String} [val] attribute value (will be toString()'ed)
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
hasAttr: function(name, val) {
|
||||
JSAPI.prototype.hasAttr = function(name, val) {
|
||||
|
||||
if (!this.attrs || !Object.keys(this.attrs).length) return false;
|
||||
|
||||
@ -69,7 +54,7 @@ module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
|
||||
return !!this.attrs[name];
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a specific attribute from an element
|
||||
@ -77,10 +62,9 @@ module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
*
|
||||
* @param {String} name attribute name
|
||||
* @param {String} [val] attribute value (will be toString()'ed)
|
||||
*
|
||||
* @return {Object|Undefined}
|
||||
*/
|
||||
attr: function(name, val) {
|
||||
JSAPI.prototype.attr = function(name, val) {
|
||||
|
||||
if (!this.hasAttr() || !arguments.length) return undefined;
|
||||
|
||||
@ -88,17 +72,16 @@ module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
|
||||
return this.attrs[name];
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a specific attribute.
|
||||
*
|
||||
* @param {String} name attribute name
|
||||
* @param {String} [val] attribute value
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
removeAttr: function(name, val) {
|
||||
JSAPI.prototype.removeAttr = function(name, val) {
|
||||
|
||||
if (!arguments.length) return false;
|
||||
|
||||
@ -112,16 +95,15 @@ module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
|
||||
return true;
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Add attribute.
|
||||
*
|
||||
* @param {Object} attr attribute object
|
||||
*
|
||||
* @return {Object} created attribute
|
||||
*/
|
||||
addAttr: function(attr) {
|
||||
JSAPI.prototype.addAttr = function(attr) {
|
||||
|
||||
if (!attr ||
|
||||
(attr && attr.name === undefined) ||
|
||||
@ -131,20 +113,20 @@ module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
) return false;
|
||||
|
||||
this.attrs = this.attrs || {};
|
||||
this.attrs[attr.name] = attr;
|
||||
|
||||
return (this.attrs[attr.name] = attr);
|
||||
return this.attrs[attr.name];
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterates over all attributes.
|
||||
*
|
||||
* @param {Function} callback callback
|
||||
* @param {Object} [context] callback context
|
||||
*
|
||||
* @return {Boolean} false if there are no any attributes
|
||||
*/
|
||||
eachAttr: function(callback, context) {
|
||||
JSAPI.prototype.eachAttr = function(callback, context) {
|
||||
|
||||
if (!this.hasAttr()) return false;
|
||||
|
||||
@ -154,6 +136,4 @@ module.exports = INHERIT(/** @lends Nodes.prototype */{
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
@ -7,7 +7,6 @@
|
||||
*
|
||||
* @param {Object} data input data
|
||||
* @param {Object} plugins plugins object from config
|
||||
*
|
||||
* @return {Object} output data
|
||||
*/
|
||||
module.exports = function(data, plugins) {
|
||||
@ -38,7 +37,6 @@ module.exports = function(data, plugins) {
|
||||
* @param {Object} data input data
|
||||
* @param {Array} plugins plugins list to process
|
||||
* @param {Boolean} [reverse] reverse pass?
|
||||
*
|
||||
* @return {Object} output data
|
||||
*/
|
||||
function perItem(data, plugins, reverse) {
|
||||
@ -89,7 +87,6 @@ function perItem(data, plugins, reverse) {
|
||||
*
|
||||
* @param {Object} data input data
|
||||
* @param {Array} plugins plugins list to process
|
||||
*
|
||||
* @return {Object} output data
|
||||
*/
|
||||
function full(data, plugins) {
|
||||
|
@ -1,23 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
var Q = require('q'),
|
||||
SAX = require('sax'),
|
||||
var SAX = require('sax'),
|
||||
JSAPI = require('./jsAPI');
|
||||
|
||||
var config = {
|
||||
strict: true,
|
||||
trim: true,
|
||||
normalize: true,
|
||||
lowercase: true,
|
||||
xmlns: true,
|
||||
position: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert SVG (XML) string to SVG-as-JS object.
|
||||
*
|
||||
* @module svg2js
|
||||
*
|
||||
* @param {String} svg input data
|
||||
* @param {Object} config sax xml parser config
|
||||
*
|
||||
* @return {Object} output data deferred promise
|
||||
* @param {String} data input data
|
||||
* @param {Function} callback
|
||||
*/
|
||||
module.exports = function(svg, config) {
|
||||
module.exports = function(data, callback) {
|
||||
|
||||
var deferred = Q.defer(),
|
||||
sax = SAX.parser(config.strict, config),
|
||||
var sax = SAX.parser(config.strict, config),
|
||||
root = {},
|
||||
current = root,
|
||||
stack = [];
|
||||
@ -109,23 +112,21 @@ module.exports = function(svg, config) {
|
||||
|
||||
sax.onerror = function(e) {
|
||||
|
||||
deferred.reject(new Error('svg2js: ' + e.message));
|
||||
|
||||
// https://github.com/isaacs/sax-js#events
|
||||
// "The error will be hanging out on parser.error,
|
||||
// and must be deleted before parsing can continue"
|
||||
this.error = null;
|
||||
|
||||
throw new Error('svg2js: ' + e.message);
|
||||
|
||||
};
|
||||
|
||||
sax.onend = function() {
|
||||
|
||||
deferred.resolve(root);
|
||||
callback(root);
|
||||
|
||||
};
|
||||
|
||||
sax.write(svg).close();
|
||||
|
||||
return deferred.promise;
|
||||
sax.write(data).close();
|
||||
|
||||
};
|
||||
|
11
package.json
11
package.json
@ -32,25 +32,20 @@
|
||||
"example": "./examples"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "./node_modules/.bin/mocha --reporter spec --recursive",
|
||||
"test": "./node_modules/.bin/mocha --reporter spec test/plugins test/svg2js",
|
||||
"cover": "./node_modules/.bin/istanbul instrument --output lib-cov --no-compact --variable global.__coverage__ lib && ./node_modules/.bin/mocha --reporter mocha-istanbul --recursive",
|
||||
"jshint": "jshint --show-non-errors ."
|
||||
},
|
||||
"dependencies": {
|
||||
"sax": "~0.5.0",
|
||||
"q": "~0.8.10",
|
||||
"q-fs": "~0.1.0",
|
||||
"coa": "~0.3.7",
|
||||
"inherit": "",
|
||||
"node.extend": "",
|
||||
"js-yaml": "",
|
||||
"colors": "~0.6.0"
|
||||
"colors": "~0.6.0",
|
||||
"node.extend": ""
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~1.8.0",
|
||||
"mocha-as-promised": "~1.2.0",
|
||||
"chai": "~1.5.0",
|
||||
"chai-as-promised": "~3.2.3",
|
||||
"istanbul": "~0.1.0",
|
||||
"mocha-istanbul": ""
|
||||
},
|
||||
|
@ -1,5 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
newlines: true,
|
||||
trim: true,
|
||||
spaces: true
|
||||
};
|
||||
|
||||
var regNewlines = /\n/g,
|
||||
regSpaces = /\s{2,}/g;
|
||||
|
||||
@ -12,7 +22,7 @@ var regNewlines = /\n/g,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.cleanupAttrs = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
if (item.isElem()) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var regEnableBackground = /^new\s0\s0\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)$/,
|
||||
elems = ['svg', 'mask', 'pattern'];
|
||||
|
||||
@ -18,7 +22,7 @@ var regEnableBackground = /^new\s0\s0\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)\s([\-+]
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.cleanupEnableBackground = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (
|
||||
item.isElem(elems) &&
|
||||
|
@ -1,5 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'full';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
remove: true,
|
||||
minify: true
|
||||
};
|
||||
|
||||
var referencesProps = require('./_collections').referencesProps,
|
||||
regReferencesUrl = /^url\(#(.+?)\)$/,
|
||||
regReferencesHref = /^#(.+?)$/,
|
||||
@ -19,7 +28,7 @@ var referencesProps = require('./_collections').referencesProps,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.cleanupIDs = function(data, params) {
|
||||
exports.fn = function(data, params) {
|
||||
|
||||
var currentID,
|
||||
currentIDstring,
|
||||
|
@ -1,5 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
floatPrecision: 3,
|
||||
leadingZero: true,
|
||||
defaultPx: true
|
||||
};
|
||||
|
||||
var regNumericValues = /^([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/,
|
||||
removeLeadingZero = require('../lib/svgo/tools').removeLeadingZero;
|
||||
|
||||
@ -13,7 +23,7 @@ var regNumericValues = /^([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)(px|pt|pc|mm|cm|m|in|f
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.cleanupNumericValues = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
if (item.isElem()) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItemReverse';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var flattenOneLevel = require('../lib/svgo/tools').flattenOneLevel;
|
||||
|
||||
/*
|
||||
@ -25,7 +29,7 @@ var flattenOneLevel = require('../lib/svgo/tools').flattenOneLevel;
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.collapseGroups = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
// non-empty elements
|
||||
if (item.elem && !item.isEmpty()) {
|
||||
|
@ -1,26 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
names2hex: true,
|
||||
rgb2hex: true,
|
||||
shorthex: true
|
||||
};
|
||||
|
||||
var collections = require('./_collections'),
|
||||
regRGB = /^rgb\((\d+%?),\s*(\d+%?),\s*(\d+%?)\)$/,
|
||||
regHEX = /^\#(([a-fA-F0-9])\2){3}$/;
|
||||
|
||||
/**
|
||||
* Convert [r, g, b] to #rrggbb.
|
||||
*
|
||||
* @see https://gist.github.com/983535
|
||||
*
|
||||
* @example
|
||||
* rgb2hex([255, 255, 255]) // '#ffffff'
|
||||
*
|
||||
* @param {Array} rgb [r, g, b]
|
||||
* @return {String} #rrggbb
|
||||
*
|
||||
* @author Jed Schmidt
|
||||
*/
|
||||
function rgb2hex(rgb) {
|
||||
return '#' + ((256 + rgb[0] << 8 | rgb[1]) << 8 | rgb[2]).toString(16).slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert different colors formats in element attributes to hex.
|
||||
*
|
||||
@ -44,7 +37,7 @@ function rgb2hex(rgb) {
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.convertColors = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
if (item.elem) {
|
||||
|
||||
@ -88,3 +81,20 @@ exports.convertColors = function(item, params) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert [r, g, b] to #rrggbb.
|
||||
*
|
||||
* @see https://gist.github.com/983535
|
||||
*
|
||||
* @example
|
||||
* rgb2hex([255, 255, 255]) // '#ffffff'
|
||||
*
|
||||
* @param {Array} rgb [r, g, b]
|
||||
* @return {String} #rrggbb
|
||||
*
|
||||
* @author Jed Schmidt
|
||||
*/
|
||||
function rgb2hex(rgb) {
|
||||
return '#' + ((256 + rgb[0] << 8 | rgb[1]) << 8 | rgb[2]).toString(16).slice(1);
|
||||
}
|
||||
|
@ -1,5 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
applyTransforms: true,
|
||||
straightCurves: true,
|
||||
lineShorthands: true,
|
||||
curveSmoothShorthands: true,
|
||||
floatPrecision: 3,
|
||||
removeUseless: true,
|
||||
collapseRepeated: true,
|
||||
leadingZero: true,
|
||||
negativeExtraSpace: true
|
||||
};
|
||||
|
||||
var pathElems = require('./_collections.js').pathElems,
|
||||
path2js = require('./_path.js').path2js,
|
||||
js2path = require('./_path.js').js2path,
|
||||
@ -22,7 +38,7 @@ var pathElems = require('./_collections.js').pathElems,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.convertPathData = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
if (item.isElem(pathElems) && item.hasAttr('d')) {
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
var extend = require('../lib/svgo/tools').extend,
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var EXTEND = require('node.extend'),
|
||||
stylingProps = require('./_collections').stylingProps,
|
||||
regCleanupStyle = /(:|;)\s+/g;
|
||||
|
||||
@ -22,7 +26,7 @@ var extend = require('../lib/svgo/tools').extend,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.convertStyleToAttrs = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (item.elem && item.hasAttr('style')) {
|
||||
// ['opacity: 1', 'color: #000']
|
||||
@ -57,7 +61,7 @@ exports.convertStyleToAttrs = function(item) {
|
||||
return true;
|
||||
});
|
||||
|
||||
extend(item.attrs, attrs);
|
||||
EXTEND(item.attrs, attrs);
|
||||
|
||||
if (styles.length) {
|
||||
item.attr('style').value = styles.join(';')
|
||||
|
@ -1,5 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
convertToShorts: true,
|
||||
floatPrecision: 3,
|
||||
matrixToTransform: true,
|
||||
shortTranslate: true,
|
||||
shortScale: true,
|
||||
shortRotate: true,
|
||||
removeUseless: true,
|
||||
collapseIntoOne: true,
|
||||
leadingZero: true,
|
||||
negativeExtraSpace: false
|
||||
};
|
||||
|
||||
var cleanupOutData = require('../lib/svgo/tools').cleanupOutData,
|
||||
transform2js = require('./_transforms.js').transform2js,
|
||||
transformsMultiply = require('./_transforms.js').transformsMultiply,
|
||||
@ -19,7 +36,7 @@ var cleanupOutData = require('../lib/svgo/tools').cleanupOutData,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.convertTransform = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
if (item.elem) {
|
||||
|
||||
|
@ -1,5 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'full';
|
||||
|
||||
exports.active = false;
|
||||
|
||||
exports.params = {
|
||||
hcrop: true,
|
||||
vcenter: true,
|
||||
floatPrecision: 3,
|
||||
leadingZero: true,
|
||||
negativeExtraSpace: true
|
||||
};
|
||||
|
||||
var relative2absolute = require('./_path.js').relative2absolute,
|
||||
computeCubicBoundingBox = require('./_path.js').computeCubicBoundingBox,
|
||||
computeQuadraticBoundingBox = require('./_path.js').computeQuadraticBoundingBox,
|
||||
@ -7,7 +19,7 @@ var relative2absolute = require('./_path.js').relative2absolute,
|
||||
js2path = require('./_path.js').js2path,
|
||||
extend = require('../lib/svgo/tools').extend;
|
||||
|
||||
exports.cropAndCenterAlongPath = function(data, params) {
|
||||
exports.fn = function(data, params) {
|
||||
|
||||
data.content.forEach(function(item) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItemReverse';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var inheritableAttrs = require('./_collections').inheritableAttrs,
|
||||
pathElems = require('./_collections.js').pathElems;
|
||||
|
||||
@ -27,7 +31,7 @@ var inheritableAttrs = require('./_collections').inheritableAttrs,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.moveElemsAttrsToGroup = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (item.isElem('g') && !item.isEmpty() && item.content.length > 1) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItemReverse';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var pathElems = require('./_collections.js').pathElems;
|
||||
|
||||
/**
|
||||
@ -21,7 +25,7 @@ var pathElems = require('./_collections.js').pathElems;
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.moveGroupAttrsToElems = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
// move group transform attr to content's pathElems
|
||||
if (
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
/**
|
||||
* Remove comments.
|
||||
*
|
||||
@ -12,7 +16,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeComments = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (item.comment && item.comment.charAt(0) !== '!') {
|
||||
return false;
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
/**
|
||||
* Remove DOCTYPE declaration.
|
||||
*
|
||||
@ -25,7 +29,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeDoctype = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
// remove doctype only if custom XML entities declaration block does not presents
|
||||
// http://en.wikipedia.org/wiki/Document_Type_Definition#Entity_declarations
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var editorNamespaces = require('./_collections').editorNamespaces,
|
||||
prefixes = [];
|
||||
|
||||
@ -16,7 +20,7 @@ var editorNamespaces = require('./_collections').editorNamespaces,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeEditorsNSData = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (item.elem) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
/**
|
||||
* Remove attributes with empty values.
|
||||
*
|
||||
@ -8,7 +12,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeEmptyAttrs = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (item.elem) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItemReverse';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var container = require('./_collections').elemsGroups.container;
|
||||
|
||||
/**
|
||||
@ -18,7 +22,7 @@ var container = require('./_collections').elemsGroups.container;
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeEmptyContainers = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
return !(item.isElem(container) && !item.isElem('svg') && item.isEmpty());
|
||||
|
||||
|
@ -1,5 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
text: true,
|
||||
tspan: true,
|
||||
tref: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove empty Text elements.
|
||||
*
|
||||
@ -21,7 +31,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeEmptyText = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
// Remove empty text element
|
||||
if (
|
||||
|
@ -1,5 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
displayNone: true,
|
||||
opacity0: true,
|
||||
circleR0: true,
|
||||
ellipseRX0: true,
|
||||
ellipseRY0: true,
|
||||
rectWidth0: true,
|
||||
rectHeight0: true,
|
||||
patternWidth0: true,
|
||||
patternHeight0: true,
|
||||
imageWidth0: true,
|
||||
imageHeight0: true,
|
||||
pathEmptyD: true,
|
||||
polylineEmptyPoints: true,
|
||||
polygonEmptyPoints: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove hidden elements with disabled rendering:
|
||||
* - display="none"
|
||||
@ -19,7 +40,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeHiddenElems = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
if (item.elem) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
/**
|
||||
* Remove <metadata>.
|
||||
*
|
||||
@ -10,7 +14,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeMetadata = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
return !item.isElem('metadata');
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var inheritableAttrs = require('./_collections').inheritableAttrs,
|
||||
presentationAttrs = require('./_collections').attrsGroups.presentation,
|
||||
excludedAttrs = ['display', 'opacity'];
|
||||
@ -12,7 +16,7 @@ var inheritableAttrs = require('./_collections').inheritableAttrs,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeNonInheritableGroupAttrs = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (item.isElem('g')) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = false;
|
||||
|
||||
/**
|
||||
* Remove raster images references in <image>.
|
||||
*
|
||||
@ -10,7 +14,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeRasterImages = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (
|
||||
item.isElem('image') &&
|
||||
|
@ -1,5 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
SVGid: true,
|
||||
unknownContent: true,
|
||||
unknownAttrs: true,
|
||||
defaultAttrs: true
|
||||
};
|
||||
|
||||
var collections = require('./_collections'),
|
||||
elems = collections.elems,
|
||||
attrsGroups = collections.attrsGroups,
|
||||
@ -48,7 +59,7 @@ for (var elem in elems) {
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeUnknownsAndDefaults = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
// elems w/o namespace prefix
|
||||
if (item.isElem() && !item.prefix) {
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'full';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
/**
|
||||
* Remove unused namespaces declaration.
|
||||
*
|
||||
@ -8,7 +12,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeUnusedNS = function(data) {
|
||||
exports.fn = function(data) {
|
||||
|
||||
var svgElem,
|
||||
xmlnsCollection = [];
|
||||
|
@ -1,5 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'peItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
exports.params = {
|
||||
stroke: true,
|
||||
fill: true
|
||||
};
|
||||
|
||||
var regStrokeProps = /^stroke/,
|
||||
regFillProps = /^fill/;
|
||||
|
||||
@ -12,7 +21,7 @@ var regStrokeProps = /^stroke/,
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeUselessStrokeAndFill = function(item, params) {
|
||||
exports.fn = function(item, params) {
|
||||
|
||||
if (item.isElem()) {
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
var regViewBox = /^0\s0\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)$/,
|
||||
viewBoxElems = ['svg', 'pattern'];
|
||||
|
||||
@ -18,7 +22,7 @@ var regViewBox = /^0\s0\s([\-+]?\d*\.?\d+([eE][\-+]?\d+)?)\s([\-+]?\d*\.?\d+([eE
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeViewBox = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
if (
|
||||
item.isElem(viewBoxElems) &&
|
||||
|
@ -1,5 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
exports.type = 'perItem';
|
||||
|
||||
exports.active = true;
|
||||
|
||||
/**
|
||||
* Remove XML Processing Instruction.
|
||||
*
|
||||
@ -11,7 +15,7 @@
|
||||
*
|
||||
* @author Kir Belevich
|
||||
*/
|
||||
exports.removeXMLProcInst = function(item) {
|
||||
exports.fn = function(item) {
|
||||
|
||||
return !(item.processinginstruction && item.processinginstruction.name === 'xml');
|
||||
|
||||
|
Reference in New Issue
Block a user