diff --git a/.svgo.yml b/.svgo.yml
index 31862671..d467e3a7 100644
--- a/.svgo.yml
+++ b/.svgo.yml
@@ -45,3 +45,4 @@ plugins:
- transformsWithOnePath
- sortAttrs
- removeDimensions
+ - removeAttrs
diff --git a/README.md b/README.md
index 9ddf74c5..d681a187 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,7 @@ Today we have:
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertShapeToPath.js) ] convert some basic shapes to path
* [ [>](https://github.com/svg/svgo/blob/master/plugins/transformsWithOnePath.js) ] apply transforms, crop by real width, center vertical alignment and resize SVG with one Path inside
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeDimensions.js) ] remove width/height attributes if viewBox is present
+* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeAttrs.js) ] remove attributes by pattern
Want to know how it works and how to write your own plugin? [Of course you want to](https://github.com/svg/svgo/blob/master/docs/how-it-works/en.md).
diff --git a/README.ru.md b/README.ru.md
index 75afee26..28d4a229 100644
--- a/README.ru.md
+++ b/README.ru.md
@@ -48,6 +48,7 @@ SVGO имеет расширяемую архитектуру, в которой
* [ [>](https://github.com/svg/svgo/blob/master/plugins/convertShapeToPath.js) ] конвертирование простых форм в Path
* [ [>](https://github.com/svg/svgo/blob/master/plugins/transformsWithOnePath.js) ] применение трансформаций, обрезка по реальной ширине, вертикальное выравнивание по центру и изменение размеров SVG с одним Path внутри
* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeDimensions.js) ] !!translation needed - remove width/height attributes if viewBox is present
+* [ [>](https://github.com/svg/svgo/blob/master/plugins/removeAttrs.js) ] !!translation needed - remove attributes by pattern
Хотите узнать, как это работает и как написать свой плагин? [Конечно же, да!](https://github.com/svg/svgo/blob/master/docs/how-it-works/ru.md).
diff --git a/plugins/removeAttrs.js b/plugins/removeAttrs.js
new file mode 100644
index 00000000..eef4606d
--- /dev/null
+++ b/plugins/removeAttrs.js
@@ -0,0 +1,112 @@
+'use strict';
+
+var ELEM_SEP = ':';
+
+exports.type = 'perItem';
+
+exports.active = false;
+
+exports.params = {
+ attrs: []
+};
+
+/**
+ * Remove attributes
+ *
+ * @param attrs:
+ *
+ * format: [ element* : attribute* ]
+ *
+ * element : regexp (wrapped into ^...$), single * or omitted > all elements
+ * attribute : regexp (wrapped into ^...$)
+ *
+ * examples:
+ *
+ * > remove fill attribute on path element
+ * ---
+ * attrs: 'path:fill'
+ *
+ *
+ * > remove all fill and stroke attribute
+ * ---
+ * attrs:
+ * - 'fill'
+ * - 'stroke'
+ *
+ * [is same as]
+ *
+ * attrs: '(fill|stroke)'
+ *
+ * [is same as]
+ *
+ * attrs: '*:(fill|stroke)'
+ *
+ * [is same as]
+ *
+ * attrs: '.*:(fill|stroke)'
+ *
+ *
+ * > remove all stroke related attributes
+ * ----
+ * attrs: 'stroke.*'
+ *
+ *
+ * @param {Object} item current iteration item
+ * @param {Object} params plugin params
+ * @return {Boolean} if false, item will be filtered out
+ *
+ * @author Benny Schudel
+ */
+exports.fn = function(item, params) {
+
+ // wrap into an array if params is not
+ if (!Array.isArray(params.attrs)) {
+ params.attrs = [params.attrs];
+ }
+
+ if (item.isElem()) {
+
+ // prepare patterns
+ var patterns = params.attrs.map(function(pattern) {
+
+ // apply to all elements if specifc element is omitted
+ if (pattern.indexOf(ELEM_SEP) === -1) {
+ pattern = ['.*', ELEM_SEP, pattern].join('');
+ }
+
+ // create regexps for element and attribute name
+ return pattern.split(ELEM_SEP)
+ .map(function(value) {
+
+ // adjust single * to match anything
+ if (value === '*') { value = '.*'; }
+
+ return new RegExp(['^', value, '$'].join(''), 'i');
+ });
+
+ });
+
+ // loop patterns
+ patterns.forEach(function(pattern) {
+
+ // matches element
+ if (pattern[0].test(item.elem)) {
+
+ // loop attributes
+ item.eachAttr(function(attr) {
+ var name = attr.name;
+
+ // matches attribute name
+ if (pattern[1].test(name)) {
+ item.removeAttr(name);
+ }
+
+ });
+
+ }
+
+ });
+
+ }
+
+};
diff --git a/test/plugins/_index.js b/test/plugins/_index.js
index cf39ed78..6b3030f7 100644
--- a/test/plugins/_index.js
+++ b/test/plugins/_index.js
@@ -13,38 +13,39 @@ describe('plugins tests', function() {
var match = file.match(regFilename),
index,
- name,
- svgo,
- plugins;
+ name;
if (match) {
- name = match[1];
+ name = match[1];
index = match[2];
file = PATH.resolve(__dirname, file);
- plugins = {};
- plugins[name] = true;
-
- svgo = new SVGO({
- full: true,
- plugins: [ plugins ],
- js2svg: { pretty: true }
- });
-
it(name + '.' + index, function(done) {
FS.readFile(file, 'utf8', function(err, data) {
- var splitted = data.split('@@@'),
- orig = splitted[0],
- should = splitted[1];
+ var splitted = data.trim().split(/\s*@@@\s*/),
+ orig = splitted[0],
+ should = splitted[1],
+ params = splitted[2],
+
+ plugins = {},
+ svgo;
+
+ plugins[name] = (params) ? JSON.parse(params) : true;
+
+ svgo = new SVGO({
+ full : true,
+ plugins : [ plugins ],
+ js2svg : { pretty: true }
+ });
svgo.optimize(orig, function(result) {
- result = '\n\n' + result.data;
- result.should.be.equal(should);
+//FIXME: results.data has a '\n' at the end while it should not
+ ( result.data.trim() ).should.be.equal(should);
done();
});
diff --git a/test/plugins/removeAttrs.01.svg b/test/plugins/removeAttrs.01.svg
new file mode 100644
index 00000000..241c29d8
--- /dev/null
+++ b/test/plugins/removeAttrs.01.svg
@@ -0,0 +1,19 @@
+
+
+@@@
+
+
+
+@@@
+
+{"attrs":["circle:stroke.*","path:fill"]}
diff --git a/test/plugins/removeAttrs.02.svg b/test/plugins/removeAttrs.02.svg
new file mode 100644
index 00000000..98b857c1
--- /dev/null
+++ b/test/plugins/removeAttrs.02.svg
@@ -0,0 +1,19 @@
+
+
+@@@
+
+
+
+@@@
+
+{"attrs":"(fill|stroke)"}