mirror of
https://github.com/svg/svgo.git
synced 2025-07-03 05:42:32 +03:00
This should help to avoid node.parentNode and closestByName in some cases by skiping visiting children of current node. Works only in `enter` listener.
123 lines
2.6 KiB
JavaScript
123 lines
2.6 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* @typedef {import('./types').XastRoot} XastRoot
|
|
* @typedef {import('./types').XastElement} XastElement
|
|
*/
|
|
|
|
const { visit, visitSkip, detachNodeFromParent } = require('./xast.js');
|
|
|
|
/**
|
|
* @type {(children: Array<XastElement>) => XastRoot}
|
|
*/
|
|
const root = (children) => {
|
|
return { type: 'root', children };
|
|
};
|
|
|
|
/**
|
|
* @type {(
|
|
* name: string,
|
|
* attrs?: null | Record<string, string>,
|
|
* children?: Array<XastElement>
|
|
* ) => XastElement}
|
|
*/
|
|
const x = (name, attrs = null, children = []) => {
|
|
return { type: 'element', name, attributes: attrs || {}, children };
|
|
};
|
|
|
|
test('visit enters into nodes', () => {
|
|
const ast = root([x('g', null, [x('rect'), x('circle')]), x('ellipse')]);
|
|
/**
|
|
* @type {Array<string>}
|
|
*/
|
|
const entered = [];
|
|
visit(ast, {
|
|
root: {
|
|
enter: (node) => {
|
|
entered.push(node.type);
|
|
},
|
|
},
|
|
element: {
|
|
enter: (node) => {
|
|
entered.push(`${node.type}:${node.name}`);
|
|
},
|
|
},
|
|
});
|
|
expect(entered).toEqual([
|
|
'root',
|
|
'element:g',
|
|
'element:rect',
|
|
'element:circle',
|
|
'element:ellipse',
|
|
]);
|
|
});
|
|
|
|
test('visit exits from nodes', () => {
|
|
const ast = root([x('g', null, [x('rect'), x('circle')]), x('ellipse')]);
|
|
/**
|
|
* @type {Array<string>}
|
|
*/
|
|
const exited = [];
|
|
visit(ast, {
|
|
root: {
|
|
exit: (node) => {
|
|
exited.push(node.type);
|
|
},
|
|
},
|
|
element: {
|
|
exit: (node) => {
|
|
exited.push(`${node.type}:${node.name}`);
|
|
},
|
|
},
|
|
});
|
|
expect(exited).toEqual([
|
|
'element:rect',
|
|
'element:circle',
|
|
'element:g',
|
|
'element:ellipse',
|
|
'root',
|
|
]);
|
|
});
|
|
|
|
test('visit skips entering children if node is detached', () => {
|
|
const ast = root([x('g', null, [x('rect'), x('circle')]), x('ellipse')]);
|
|
/**
|
|
* @type {Array<string>}
|
|
*/
|
|
const entered = [];
|
|
visit(ast, {
|
|
element: {
|
|
enter: (node, parentNode) => {
|
|
entered.push(node.name);
|
|
if (node.name === 'g') {
|
|
detachNodeFromParent(node, parentNode);
|
|
}
|
|
},
|
|
},
|
|
});
|
|
expect(entered).toEqual(['g', 'ellipse']);
|
|
expect(ast).toEqual(root([x('ellipse')]));
|
|
});
|
|
|
|
test('visit skips entering children when symbol is passed', () => {
|
|
const ast = root([x('g', null, [x('rect'), x('circle')]), x('ellipse')]);
|
|
/**
|
|
* @type {Array<string>}
|
|
*/
|
|
const entered = [];
|
|
visit(ast, {
|
|
element: {
|
|
enter: (node) => {
|
|
entered.push(node.name);
|
|
if (node.name === 'g') {
|
|
return visitSkip;
|
|
}
|
|
},
|
|
},
|
|
});
|
|
expect(entered).toEqual(['g', 'ellipse']);
|
|
expect(ast).toEqual(
|
|
root([x('g', null, [x('rect'), x('circle')]), x('ellipse')])
|
|
);
|
|
});
|