123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- /* eslint-disable no-cond-assign, default-case */
- const escapeForRegexp = require('escape-string-regexp');
- const URL_PATTERN = /url\(#([^ ]+?)\s*\)/g;
- const defaultPattern = '[id]';
- /**
- * @param {string} id
- * @param {string|Function} pattern
- */
- function renameId(id, pattern) {
- const result = (typeof pattern === 'function' ? pattern(id) : pattern).toString();
- const re = new RegExp(escapeForRegexp('[id]'), 'g');
- return result.replace(re, id);
- }
- /**
- * @param {string|Function} [pattern]
- * @returns {Function}
- */
- function plugin(pattern) {
- const p = pattern || defaultPattern;
- return (tree) => {
- const mappedIds = {};
- tree.match({ attrs: { id: /.*/ } }, (node) => {
- const { attrs } = node;
- const currentId = attrs.id;
- const newId = renameId(currentId, p);
- attrs.id = newId;
- mappedIds[currentId] = {
- id: newId,
- referenced: false,
- node
- };
- return node;
- });
- tree.match({ tag: /.*/ }, (node) => {
- const { attrs } = node;
- if (node.tag === 'style') {
- while (true) {
- const content = Array.isArray(node.content) ? node.content.join('') : node.content.toString();
- const match = URL_PATTERN.exec(content);
- if (match === null) {
- break;
- }
- const id = match[1];
- if (mappedIds[id]) {
- mappedIds[id].referenced = true;
- const re = new RegExp(escapeForRegexp(match[0]), 'g');
- node.content = content.replace(re, `url(#${mappedIds[id].id})`);
- }
- }
- }
- if ('attrs' in node === false) {
- return node;
- }
- Object.keys(attrs).forEach((attrName) => {
- const value = attrs[attrName];
- let id;
- let match;
- while ((match = URL_PATTERN.exec(value)) !== null) {
- id = match[1];
- if (mappedIds[id]) {
- mappedIds[id].referenced = true;
- const re = new RegExp(escapeForRegexp(match[0]), 'g');
- attrs[attrName] = value.replace(re, `url(#${mappedIds[id].id})`);
- }
- }
- let idObj;
- switch (attrName) {
- case 'href':
- case 'xlink:href':
- if (value.substring(0, 1) !== '#') {
- break;
- }
- id = value.substring(1);
- idObj = mappedIds[id];
- if (idObj) {
- idObj.referenced = false;
- attrs[attrName] = `#${idObj.id}`;
- }
- break;
- case 'for':
- if (node.tag !== 'label') {
- break;
- }
- id = value;
- idObj = mappedIds[id];
- if (idObj) {
- idObj.referenced = false;
- attrs[attrName] = idObj.id;
- }
- break;
- }
- });
- return node;
- });
- return tree;
- };
- }
- module.exports = plugin;
|