123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- import namespaces from 'svg-baker/namespaces';
- import selectAttributes from './select-attributes';
- import arrayFrom from './array-from';
- const xLinkNS = namespaces.xlink.uri;
- const xLinkAttrName = 'xlink:href';
- // eslint-disable-next-line no-useless-escape
- const specialUrlCharsPattern = /[{}|\\\^\[\]`"<>]/g;
- function encoder(url) {
- return url.replace(specialUrlCharsPattern, (match) => {
- return `%${match[0].charCodeAt(0).toString(16).toUpperCase()}`;
- });
- }
- function escapeRegExp(str) {
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
- }
- /**
- * @param {NodeList} nodes
- * @param {string} startsWith
- * @param {string} replaceWith
- * @return {NodeList}
- */
- function updateReferences(nodes, startsWith, replaceWith) {
- arrayFrom(nodes).forEach((node) => {
- const href = node.getAttribute(xLinkAttrName);
- if (href && href.indexOf(startsWith) === 0) {
- const newUrl = href.replace(startsWith, replaceWith);
- node.setAttributeNS(xLinkNS, xLinkAttrName, newUrl);
- }
- });
- return nodes;
- }
- /**
- * List of SVG attributes to update url() target in them
- */
- const attList = [
- 'clipPath',
- 'colorProfile',
- 'src',
- 'cursor',
- 'fill',
- 'filter',
- 'marker',
- 'markerStart',
- 'markerMid',
- 'markerEnd',
- 'mask',
- 'stroke',
- 'style'
- ];
- const attSelector = attList.map(attr => `[${attr}]`).join(',');
- /**
- * Update URLs in svg image (like `fill="url(...)"`) and update referencing elements
- * @param {Element} svg
- * @param {NodeList} references
- * @param {string|RegExp} startsWith
- * @param {string} replaceWith
- * @return {void}
- *
- * @example
- * const sprite = document.querySelector('svg.sprite');
- * const usages = document.querySelectorAll('use');
- * updateUrls(sprite, usages, '#', 'prefix#');
- */
- export default function (svg, references, startsWith, replaceWith) {
- const startsWithEncoded = encoder(startsWith);
- const replaceWithEncoded = encoder(replaceWith);
- const nodes = svg.querySelectorAll(attSelector);
- const attrs = selectAttributes(nodes, ({ localName, value }) => {
- return attList.indexOf(localName) !== -1 && value.indexOf(`url(${startsWithEncoded}`) !== -1;
- });
- attrs.forEach(attr => attr.value = attr.value.replace(new RegExp(escapeRegExp(startsWithEncoded), 'g'), replaceWithEncoded));
- updateReferences(references, startsWithEncoded, replaceWithEncoded);
- }
|