| 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;
 |