1
0
mirror of https://github.com/svg/svgo.git synced 2025-07-29 20:21:14 +03:00

Drop createContentItem from public api and JSAPI node wrappers

This commit is contained in:
Bogdan Chadkin
2022-10-02 12:00:44 +03:00
parent 50e836d5a4
commit 516c6e1fc1
10 changed files with 51 additions and 90 deletions

View File

@ -10,11 +10,11 @@
* @typedef {import('./types').XastCdata} XastCdata * @typedef {import('./types').XastCdata} XastCdata
* @typedef {import('./types').XastText} XastText * @typedef {import('./types').XastText} XastText
* @typedef {import('./types').XastParent} XastParent * @typedef {import('./types').XastParent} XastParent
* @typedef {import('./types').XastChild} XastChild
*/ */
// @ts-ignore sax will be replaced with something else later // @ts-ignore sax will be replaced with something else later
const SAX = require('@trysound/sax'); const SAX = require('@trysound/sax');
const JSAPI = require('./svgo/jsAPI.js');
const { textElems } = require('../plugins/_collections.js'); const { textElems } = require('../plugins/_collections.js');
class SvgoParserError extends Error { class SvgoParserError extends Error {
@ -94,7 +94,7 @@ const parseSvg = (data, from) => {
/** /**
* @type {XastRoot} * @type {XastRoot}
*/ */
const root = new JSAPI({ type: 'root', children: [] }); const root = { type: 'root', children: [] };
/** /**
* @type {XastParent} * @type {XastParent}
*/ */
@ -105,12 +105,15 @@ const parseSvg = (data, from) => {
const stack = [root]; const stack = [root];
/** /**
* @type {<T extends XastNode>(node: T) => T} * @type {(node: XastChild) => void}
*/ */
const pushToContent = (node) => { const pushToContent = (node) => {
const wrapped = new JSAPI(node, current); // TODO remove legacy parentNode in v4
current.children.push(wrapped); Object.defineProperty(node, 'parentNode', {
return wrapped; writable: true,
value: current,
});
current.children.push(node);
}; };
/** /**
@ -199,7 +202,7 @@ const parseSvg = (data, from) => {
for (const [name, attr] of Object.entries(data.attributes)) { for (const [name, attr] of Object.entries(data.attributes)) {
element.attributes[name] = attr.value; element.attributes[name] = attr.value;
} }
element = pushToContent(element); pushToContent(element);
current = element; current = element;
stack.push(element); stack.push(element);
}; };

View File

@ -4,9 +4,7 @@ const os = require('os');
const fs = require('fs'); const fs = require('fs');
const { pathToFileURL } = require('url'); const { pathToFileURL } = require('url');
const path = require('path'); const path = require('path');
const { optimize: optimizeAgnostic, createContentItem } = require('./svgo.js'); const { optimize: optimizeAgnostic } = require('./svgo.js');
exports.createContentItem = createContentItem;
const importConfig = async (configFile) => { const importConfig = async (configFile) => {
let config; let config;

View File

@ -4,7 +4,6 @@ const { defaultPlugins, resolvePluginConfig } = require('./svgo/config.js');
const { parseSvg } = require('./parser.js'); const { parseSvg } = require('./parser.js');
const { stringifySvg } = require('./stringifier.js'); const { stringifySvg } = require('./stringifier.js');
const { invokePlugins } = require('./svgo/plugins.js'); const { invokePlugins } = require('./svgo/plugins.js');
const JSAPI = require('./svgo/jsAPI.js');
const { encodeSVGDatauri } = require('./svgo/tools.js'); const { encodeSVGDatauri } = require('./svgo/tools.js');
const optimize = (input, config) => { const optimize = (input, config) => {
@ -64,14 +63,3 @@ const optimize = (input, config) => {
return svgjs; return svgjs;
}; };
exports.optimize = optimize; exports.optimize = optimize;
/**
* The factory that creates a content item with the helper methods.
*
* @param {Object} data which is passed to jsAPI constructor
* @returns {JSAPI} content item
*/
const createContentItem = (data) => {
return new JSAPI(data);
};
exports.createContentItem = createContentItem;

2
lib/svgo/jsAPI.d.ts vendored
View File

@ -1,2 +0,0 @@
declare let obj: any;
export = obj;

View File

@ -1,12 +0,0 @@
'use strict';
var JSAPI = function (data, parentNode) {
Object.assign(this, data);
if (this.type === 'element') {
Object.defineProperty(this, 'parentNode', {
writable: true,
value: parentNode,
});
}
};
module.exports = JSAPI;

View File

@ -122,11 +122,12 @@ exports.fn = () => {
// replace current node with all its children // replace current node with all its children
const index = parentNode.children.indexOf(node); const index = parentNode.children.indexOf(node);
parentNode.children.splice(index, 1, ...node.children); parentNode.children.splice(index, 1, ...node.children);
// TODO remove in v3 // TODO remove legacy parentNode in v4
for (const child of node.children) { for (const child of node.children) {
// @ts-ignore parentNode is forbidden for public usage Object.defineProperty(child, 'parentNode', {
// and will be moved in v3 writable: true,
child.parentNode = parentNode; value: parentNode,
});
} }
} }
}, },

View File

@ -2,10 +2,10 @@
/** /**
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastChild} XastChild
*/ */
const { visitSkip, detachNodeFromParent } = require('../lib/xast.js'); const { visitSkip, detachNodeFromParent } = require('../lib/xast.js');
const JSAPI = require('../lib/svgo/jsAPI.js');
exports.name = 'mergeStyles'; exports.name = 'mergeStyles';
exports.type = 'visitor'; exports.type = 'visitor';
@ -25,6 +25,9 @@ exports.fn = () => {
*/ */
let firstStyleElement = null; let firstStyleElement = null;
let collectedStyles = ''; let collectedStyles = '';
/**
* @type {'text' | 'cdata'}
*/
let styleContentType = 'text'; let styleContentType = 'text';
return { return {
@ -80,12 +83,16 @@ exports.fn = () => {
firstStyleElement = node; firstStyleElement = node;
} else { } else {
detachNodeFromParent(node, parentNode); detachNodeFromParent(node, parentNode);
firstStyleElement.children = [ /**
new JSAPI( * @type {XastChild}
{ type: styleContentType, value: collectedStyles }, */
firstStyleElement const child = { type: styleContentType, value: collectedStyles };
), // TODO remove legacy parentNode in v4
]; Object.defineProperty(child, 'parentNode', {
writable: true,
value: firstStyleElement,
});
firstStyleElement.children = [child];
} }
}, },
}, },

View File

@ -32,10 +32,12 @@ exports.fn = () => {
if (usefulNodes.length === 0) { if (usefulNodes.length === 0) {
detachNodeFromParent(node, parentNode); detachNodeFromParent(node, parentNode);
} }
// TODO remove in SVGO 3 // TODO remove legacy parentNode in v4
for (const usefulNode of usefulNodes) { for (const usefulNode of usefulNodes) {
// @ts-ignore parentNode is legacy Object.defineProperty(usefulNode, 'parentNode', {
usefulNode.parentNode = node; writable: true,
value: node,
});
} }
node.children = usefulNodes; node.children = usefulNodes;
} else if ( } else if (

View File

@ -6,8 +6,6 @@
* @typedef {import('../lib/types').XastNode} XastNode * @typedef {import('../lib/types').XastNode} XastNode
*/ */
const JSAPI = require('../lib/svgo/jsAPI.js');
exports.type = 'visitor'; exports.type = 'visitor';
exports.name = 'reusePaths'; exports.name = 'reusePaths';
exports.active = false; exports.active = false;
@ -52,16 +50,17 @@ exports.fn = () => {
/** /**
* @type {XastElement} * @type {XastElement}
*/ */
const rawDefs = { const defsTag = {
type: 'element', type: 'element',
name: 'defs', name: 'defs',
attributes: {}, attributes: {},
children: [], children: [],
}; };
/** // TODO remove legacy parentNode in v4
* @type {XastElement} Object.defineProperty(defsTag, 'parentNode', {
*/ writable: true,
const defsTag = new JSAPI(rawDefs, node); value: node,
});
let index = 0; let index = 0;
for (const list of paths.values()) { for (const list of paths.values()) {
if (list.length > 1) { if (list.length > 1) {
@ -69,26 +68,27 @@ exports.fn = () => {
/** /**
* @type {XastElement} * @type {XastElement}
*/ */
const rawPath = { const reusablePath = {
type: 'element', type: 'element',
name: 'path', name: 'path',
attributes: { ...list[0].attributes }, attributes: { ...list[0].attributes },
children: [], children: [],
}; };
delete rawPath.attributes.transform; delete reusablePath.attributes.transform;
let id; let id;
if (rawPath.attributes.id == null) { if (reusablePath.attributes.id == null) {
id = 'reuse-' + index; id = 'reuse-' + index;
index += 1; index += 1;
rawPath.attributes.id = id; reusablePath.attributes.id = id;
} else { } else {
id = rawPath.attributes.id; id = reusablePath.attributes.id;
delete list[0].attributes.id; delete list[0].attributes.id;
} }
/** // TODO remove legacy parentNode in v4
* @type {XastElement} Object.defineProperty(reusablePath, 'parentNode', {
*/ writable: true,
const reusablePath = new JSAPI(rawPath, defsTag); value: defsTag,
});
defsTag.children.push(reusablePath); defsTag.children.push(reusablePath);
// convert paths to <use> // convert paths to <use>
for (const pathNode of list) { for (const pathNode of list) {

View File

@ -1,24 +0,0 @@
'use strict';
const { createContentItem } = require('../../lib/svgo.js');
const JSAPI = require('../../lib/svgo/jsAPI.js');
describe('svgo api', function () {
it('should has createContentItem method', function () {
expect(createContentItem).toBeInstanceOf(Function);
});
it('should be able to create content item', function () {
var item = createContentItem({
elem: 'elementName',
});
expect(item).toBeInstanceOf(JSAPI);
expect(item.elem).toEqual('elementName');
});
it('should be able create content item without argument', function () {
var item = createContentItem();
expect(item).toBeInstanceOf(JSAPI);
expect(item).toEqual({});
});
});