shift73k/assets_old/node_modules/posthtml-rename-id/index.js

120 lines
2.8 KiB
JavaScript

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