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.
		
		
		
		
		
			
		
			
				
					
					
						
							119 lines
						
					
					
						
							2.8 KiB
						
					
					
				
			
		
		
	
	
							119 lines
						
					
					
						
							2.8 KiB
						
					
					
				/* 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;
 | 
						|
 |