You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					120 lines
				
				2.8 KiB
			
		
		
			
		
	
	
					120 lines
				
				2.8 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								/* 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;
							 |