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.
		
		
		
		
		
			
		
			
				
					
					
						
							168 lines
						
					
					
						
							6.3 KiB
						
					
					
				
			
		
		
	
	
							168 lines
						
					
					
						
							6.3 KiB
						
					
					
				/** | 
						|
 * @license | 
						|
 * The MIT License | 
						|
 * | 
						|
 * Copyright © 2012–2016 Kir Belevich | 
						|
 * | 
						|
 * Permission is hereby granted, free of charge, to any person | 
						|
 * obtaining a copy of this software and associated documentation | 
						|
 * files (the "Software"), to deal in the Software without | 
						|
 * restriction, including without limitation the rights to use, | 
						|
 * copy, modify, merge, publish, distribute, sublicense, and/or sell | 
						|
 * copies of the Software, and to permit persons to whom the | 
						|
 * Software is furnished to do so, subject to the following | 
						|
 * conditions: | 
						|
 * | 
						|
 * The above copyright notice and this permission notice shall be | 
						|
 * included in all copies or substantial portions of the Software. | 
						|
 * | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
						|
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | 
						|
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
						|
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | 
						|
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | 
						|
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 
						|
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 
						|
 * OTHER DEALINGS IN THE SOFTWARE. | 
						|
 * | 
						|
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | 
						|
 * | 
						|
 * Лицензия MIT | 
						|
 * | 
						|
 * Copyright © 2012–2016 Кир Белевич | 
						|
 * | 
						|
 * Данная лицензия разрешает лицам, получившим копию | 
						|
 * данного | 
						|
 * программного обеспечения и сопутствующей | 
						|
 * документации | 
						|
 * (в дальнейшем именуемыми «Программное Обеспечение»), | 
						|
 * безвозмездно | 
						|
 * использовать Программное Обеспечение без | 
						|
 * ограничений, включая | 
						|
 * неограниченное право на использование, копирование, | 
						|
 * изменение, | 
						|
 * добавление, публикацию, распространение, | 
						|
 * сублицензирование | 
						|
 * и/или продажу копий Программного Обеспечения, также | 
						|
 * как и лицам, | 
						|
 * которым предоставляется данное Программное | 
						|
 * Обеспечение, | 
						|
 * при соблюдении следующих условий: | 
						|
 * | 
						|
 * Указанное выше уведомление об авторском праве и | 
						|
 * данные условия | 
						|
 * должны быть включены во все копии или значимые части | 
						|
 * данного | 
						|
 * Программного Обеспечения. | 
						|
 * | 
						|
 * ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК | 
						|
 * ЕСТЬ», | 
						|
 * БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ | 
						|
 * ПОДРАЗУМЕВАЕМЫХ, | 
						|
 * ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЯМИ ТОВАРНОЙ | 
						|
 * ПРИГОДНОСТИ, | 
						|
 * СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И | 
						|
 * ОТСУТСТВИЯ НАРУШЕНИЙ | 
						|
 * ПРАВ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ | 
						|
 * НЕСУТ | 
						|
 * ОТВЕТСТВЕННОСТИ ПО ИСКАМ О ВОЗМЕЩЕНИИ УЩЕРБА, УБЫТКОВ | 
						|
 * ИЛИ ДРУГИХ | 
						|
 * ТРЕБОВАНИЙ ПО ДЕЙСТВУЮЩИМ КОНТРАКТАМ, ДЕЛИКТАМ ИЛИ | 
						|
 * ИНОМУ, | 
						|
 * ВОЗНИКШИМ ИЗ, ИМЕЮЩИМ ПРИЧИНОЙ ИЛИ СВЯЗАННЫМ С | 
						|
 * ПРОГРАММНЫМ | 
						|
 * ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ПРОГРАММНОГО | 
						|
 * ОБЕСПЕЧЕНИЯ | 
						|
 * ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ. | 
						|
 */ | 
						|
 | 
						|
'use strict'; | 
						|
 | 
						|
var JSAPI = require('../lib/svgo/jsAPI'); | 
						|
 | 
						|
exports.type = 'full'; | 
						|
 | 
						|
exports.active = false; | 
						|
 | 
						|
exports.description = 'Finds <path> elements with the same d, fill, and ' + | 
						|
                      'stroke, and converts them to <use> elements ' + | 
						|
                      'referencing a single <path> def.'; | 
						|
 | 
						|
/** | 
						|
 * Finds <path> elements with the same d, fill, and stroke, and converts them to | 
						|
 * <use> elements referencing a single <path> def. | 
						|
 * | 
						|
 * @author Jacob Howcroft | 
						|
 */ | 
						|
exports.fn = function(data) { | 
						|
  const seen = new Map(); | 
						|
  let count = 0; | 
						|
  const defs = []; | 
						|
  traverse(data, item => { | 
						|
    if (!item.isElem('path') || !item.hasAttr('d')) { | 
						|
      return; | 
						|
    } | 
						|
    const d = item.attr('d').value; | 
						|
    const fill = (item.hasAttr('fill') && item.attr('fill').value) || ''; | 
						|
    const stroke = (item.hasAttr('stroke') && item.attr('stroke').value) || ''; | 
						|
    const key = d + ';s:' + stroke + ';f:' + fill; | 
						|
    const hasSeen = seen.get(key); | 
						|
    if (!hasSeen) { | 
						|
      seen.set(key, {elem: item, reused: false}); | 
						|
      return; | 
						|
    } | 
						|
    if (!hasSeen.reused) { | 
						|
      hasSeen.reused = true; | 
						|
      if (!hasSeen.elem.hasAttr('id')) { | 
						|
        hasSeen.elem.addAttr({name: 'id', local: 'id', | 
						|
                              prefix: '', value: 'reuse-' + (count++)}); | 
						|
      } | 
						|
      defs.push(hasSeen.elem); | 
						|
    } | 
						|
    item = convertToUse(item, hasSeen.elem.attr('id').value); | 
						|
  }); | 
						|
  const defsTag = new JSAPI({ | 
						|
    elem: 'defs', prefix: '', local: 'defs', content: [], attrs: []}, data); | 
						|
  data.content[0].spliceContent(0, 0, defsTag); | 
						|
  for (let def of defs) { | 
						|
    // Remove class and style before copying to avoid circular refs in | 
						|
    // JSON.stringify. This is fine because we don't actually want class or | 
						|
    // style information to be copied. | 
						|
    const style = def.style; | 
						|
    const defClass = def.class; | 
						|
    delete def.style; | 
						|
    delete def.class; | 
						|
    const defClone = def.clone(); | 
						|
    def.style = style; | 
						|
    def.class = defClass; | 
						|
    defClone.removeAttr('transform'); | 
						|
    defsTag.spliceContent(0, 0, defClone); | 
						|
    // Convert the original def to a use so the first usage isn't duplicated. | 
						|
    def = convertToUse(def, defClone.attr('id').value); | 
						|
    def.removeAttr('id'); | 
						|
  } | 
						|
  return data; | 
						|
}; | 
						|
 | 
						|
/** */ | 
						|
function convertToUse(item, href) { | 
						|
  item.renameElem('use'); | 
						|
  item.removeAttr('d'); | 
						|
  item.removeAttr('stroke'); | 
						|
  item.removeAttr('fill'); | 
						|
  item.addAttr({name: 'xlink:href', local: 'xlink:href', | 
						|
                prefix: 'none', value: '#' + href}); | 
						|
  delete item.pathJS; | 
						|
  return item; | 
						|
} | 
						|
 | 
						|
/** */ | 
						|
function traverse(parent, callback) { | 
						|
  if (parent.isEmpty()) { | 
						|
    return; | 
						|
  } | 
						|
  for (let child of parent.content) { | 
						|
    callback(child); | 
						|
    traverse(child, callback); | 
						|
  } | 
						|
}
 | 
						|
 |