Skip to content

Commit

Permalink
feat(*): add plugin remove elements by selector & scale
Browse files Browse the repository at this point in the history
  • Loading branch information
Gypsophyllite committed May 11, 2023
1 parent 631ced6 commit 7e1dcea
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .prettierrc
@@ -0,0 +1,3 @@
{
"tabWith": 2
}
2 changes: 2 additions & 0 deletions lib/builtin.js
Expand Up @@ -31,6 +31,7 @@ exports.builtin = [
require('../plugins/removeDoctype.js'),
require('../plugins/removeEditorsNSData.js'),
require('../plugins/removeElementsByAttr.js'),
require('../plugins/removeElementsBySelector.js'),
require('../plugins/removeEmptyAttrs.js'),
require('../plugins/removeEmptyContainers.js'),
require('../plugins/removeEmptyText.js'),
Expand All @@ -50,6 +51,7 @@ exports.builtin = [
require('../plugins/removeXMLNS.js'),
require('../plugins/removeXMLProcInst.js'),
require('../plugins/reusePaths.js'),
require('../plugins/scale.js'),
require('../plugins/sortAttrs.js'),
require('../plugins/sortDefsChildren.js'),
];
69 changes: 69 additions & 0 deletions plugins/convertStrokePathToFillPath.js
@@ -0,0 +1,69 @@
let svg = document.querySelector('svg');
let stroke = svg.querySelector('#stroke');
let strokeWidth = stroke.getStrokeWidth();
let dashArray = stroke.getStrokeDasharray();

let path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
svg.appendChild(path);

let startPoint;
for (let i = 0; i < stroke.pathSegList.numberOfItems; i++) {
let pathSeg = stroke.pathSegList.getItem(i);
if (pathSeg.pathSegType === 1) {
//svgPathSegMoveToAbs
startPoint = pathSeg;
path.setAttribute('d', 'M' + pathSeg.x + ',' + pathSeg.y);
} else if (pathSeg.pathSegType === 2) {
//svgPathSegLinetoAbs
let endPoint = {
x:
pathSeg.x +
dashArray[i % dashArray.length] *
strokeWidth *
Math.cos(stroke.getTotalLength()),
y:
pathSeg.y +
dashArray[i % dashArray.length] *
strokeWidth *
Math.sin(stroke.getTotalLength()),
};
path.setAttribute(
'd',
path.getAttribute('d') + 'L' + endPoint.x + ',' + endPoint.y
);
}
}
path.setAttribute('d', path.getAttribute('d') + 'Z');
('use strict');

const { querySelectorAll, detachNodeFromParent } = require('../lib/xast.js');

exports.name = 'convertStrokePathToFillPath';
exports.description = 'removes elemnts that match a css selector';

/**
* @author Gypsophyllite
*
* @type {import('./plugins-types.js').Plugin<'convertStrokePathToFillPath'>}
*/
exports.fn = (root, params) => {
const nodes = querySelectorAll(root, 'path[stroke]');

console.log(nodes);

return {
element: {
enter: (node, parentNode) => {
// for (const { selector } of selectors) {
// const nodes = querySelectorAll(root, selector);
// for (const n of nodes) {
// if (n.type === 'element' && n === node) {
// detachNodeFromParent(node, parentNode);
// }
// }
// }
},
},
};
};
4 changes: 4 additions & 0 deletions plugins/plugins-types.ts
Expand Up @@ -172,6 +172,9 @@ type DefaultPlugins = {
};
removeViewBox: void;
removeXMLProcInst: void;
scale: {
size: number;
};
sortAttrs: {
order?: Array<string>;
xmlnsOrder?: 'front' | 'alphabetical';
Expand Down Expand Up @@ -242,6 +245,7 @@ export type BuiltinsWithRequiredParams = {
id?: string | Array<string>;
class?: string | Array<string>;
};
removeElementsBySelector: any;
};

type PluginsParams = BuiltinsWithOptionalParams & BuiltinsWithRequiredParams;
Expand Down
33 changes: 33 additions & 0 deletions plugins/removeElementsBySelector.js
@@ -0,0 +1,33 @@
'use strict';

const { querySelectorAll, detachNodeFromParent } = require('../lib/xast.js');

exports.name = 'removeElementsBySelector';
exports.description = 'removes elements that match a css selector';

/**
* @author Gypsophyllite
*
* @type {import('./plugins-types.js').Plugin<'removeElementsBySelector'>}
*/
exports.fn = (root, params) => {
const selectors = Array.isArray(params.selectors)
? params.selectors
: [params];

return {
element: {
enter: (node, parentNode) => {
for (const { selector } of selectors) {
const nodes = querySelectorAll(root, selector);
for (const n of nodes) {
if (n.type === 'element' && n === node) {
detachNodeFromParent(node, parentNode);
}
}
}
},
},
};
};
93 changes: 93 additions & 0 deletions plugins/scale.js
@@ -0,0 +1,93 @@
'use strict';

// const { fstat, writeFileSync } = require('fs');
const { stringifyPathData } = require('../lib/path.js');
const { querySelectorAll } = require('../lib/xast.js');
const { path2js } = require('./_path.js');

exports.name = 'scale';
exports.description = 'scale svg';

/**
* @author Gypsophyllite
*
* @type {import('./plugins-types.js').Plugin<'scale'>}
*/
exports.fn = (root, params) => {
const size = params.size || 1024;

let scaleFactor = 1;

let pathCount = 0;

let scaledCount = 0;

return {
element: {
enter: (node, parentNode) => {
if (
node.name === 'svg' &&
parentNode.type === 'root' &&
node.attributes.viewBox !== `0 0 ${size} ${size}` &&
node.attributes.width !== '1em'
) {
// console.log(node.attributes, size);

pathCount = querySelectorAll(root, 'path').length;

scaleFactor =
size /
Math.max(
Number(node.attributes.width) || 0,
Number(node.attributes.height) || 0
);

node.attributes.viewBox = `0 0 ${size} ${size}`;
node.attributes.width = '1em';
node.attributes.height = '1em';
}

if (node.name === 'path' && scaledCount < pathCount) {
const pathJS = path2js(node);
// writeFileSync('before.json', JSON.stringify(n))
pathJS.forEach((item) => {
if (Array.isArray(item.args)) {
if (item.command === 'A' || item.command === 'a') {
item.args = item.args.map((a, index) =>
a === 1 && [2, 3, 4].includes(index) ? 1 : a * scaleFactor
);
} else {
item.args = item.args.map((a) => a * scaleFactor);
}
}

// if (Array.isArray(item.base)) {
// item.base = item.base.map(b => b * scaleFactor)
// }

// if (Array.isArray(item.coords)) {
// item.coords = item.coords.map(c => c * scaleFactor)
// }

// if (Array.isArray(item.sdata)) {
// item.sdata = item.sdata.map(s => s * scaleFactor)
// }
});

if (node.attributes.stroke) {
node.attributes['stroke-width'] = (
Number(node.attributes['stroke-width'] || 1) * scaleFactor
).toString();
}

node.attributes.d = stringifyPathData({
pathData: pathJS,
precision: 3,
});
scaledCount++;
// writeFileSync('after.json', JSON.stringify(n))
}
},
},
};
};

0 comments on commit 7e1dcea

Please sign in to comment.