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:
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
12
lib/svgo.js
12
lib/svgo.js
@ -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
2
lib/svgo/jsAPI.d.ts
vendored
@ -1,2 +0,0 @@
|
|||||||
declare let obj: any;
|
|
||||||
export = obj;
|
|
@ -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;
|
|
@ -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,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -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 (
|
||||||
|
@ -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) {
|
||||||
|
@ -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({});
|
|
||||||
});
|
|
||||||
});
|
|
Reference in New Issue
Block a user