114 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						||
 | 
						||
const { removeLeadingZero } = require('../lib/svgo/tools');
 | 
						||
 | 
						||
exports.name = 'cleanupNumericValues';
 | 
						||
exports.type = 'visitor';
 | 
						||
exports.active = true;
 | 
						||
exports.description =
 | 
						||
  'rounds numeric values to the fixed precision, removes default ‘px’ units';
 | 
						||
 | 
						||
const regNumericValues =
 | 
						||
  /^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/;
 | 
						||
 | 
						||
const absoluteLengths = {
 | 
						||
  // relative to px
 | 
						||
  cm: 96 / 2.54,
 | 
						||
  mm: 96 / 25.4,
 | 
						||
  in: 96,
 | 
						||
  pt: 4 / 3,
 | 
						||
  pc: 16,
 | 
						||
  px: 1,
 | 
						||
};
 | 
						||
 | 
						||
/**
 | 
						||
 * Round numeric values to the fixed precision,
 | 
						||
 * remove default 'px' units.
 | 
						||
 *
 | 
						||
 * @author Kir Belevich
 | 
						||
 *
 | 
						||
 * @type {import('../lib/types').Plugin<{
 | 
						||
 *   floatPrecision?: number,
 | 
						||
 *   leadingZero?: boolean,
 | 
						||
 *   defaultPx?: boolean,
 | 
						||
 *   convertToPx?: boolean
 | 
						||
 * }>}
 | 
						||
 */
 | 
						||
exports.fn = (_root, params) => {
 | 
						||
  const {
 | 
						||
    floatPrecision = 3,
 | 
						||
    leadingZero = true,
 | 
						||
    defaultPx = true,
 | 
						||
    convertToPx = true,
 | 
						||
  } = params;
 | 
						||
 | 
						||
  return {
 | 
						||
    element: {
 | 
						||
      enter: (node) => {
 | 
						||
        if (node.attributes.viewBox != null) {
 | 
						||
          const nums = node.attributes.viewBox.split(/\s,?\s*|,\s*/g);
 | 
						||
          node.attributes.viewBox = nums
 | 
						||
            .map((value) => {
 | 
						||
              const num = Number(value);
 | 
						||
              return Number.isNaN(num)
 | 
						||
                ? value
 | 
						||
                : Number(num.toFixed(floatPrecision));
 | 
						||
            })
 | 
						||
            .join(' ');
 | 
						||
        }
 | 
						||
 | 
						||
        for (const [name, value] of Object.entries(node.attributes)) {
 | 
						||
          // The `version` attribute is a text string and cannot be rounded
 | 
						||
          if (name === 'version') {
 | 
						||
            continue;
 | 
						||
          }
 | 
						||
 | 
						||
          const match = value.match(regNumericValues);
 | 
						||
 | 
						||
          // if attribute value matches regNumericValues
 | 
						||
          if (match) {
 | 
						||
            // round it to the fixed precision
 | 
						||
            let num = Number(Number(match[1]).toFixed(floatPrecision));
 | 
						||
            /**
 | 
						||
             * @type {any}
 | 
						||
             */
 | 
						||
            let matchedUnit = match[3] || '';
 | 
						||
            /**
 | 
						||
             * @type{'' | keyof typeof absoluteLengths}
 | 
						||
             */
 | 
						||
            let units = matchedUnit;
 | 
						||
 | 
						||
            // convert absolute values to pixels
 | 
						||
            if (convertToPx && units !== '' && units in absoluteLengths) {
 | 
						||
              const pxNum = Number(
 | 
						||
                (absoluteLengths[units] * Number(match[1])).toFixed(
 | 
						||
                  floatPrecision
 | 
						||
                )
 | 
						||
              );
 | 
						||
              if (pxNum.toString().length < match[0].length) {
 | 
						||
                num = pxNum;
 | 
						||
                units = 'px';
 | 
						||
              }
 | 
						||
            }
 | 
						||
 | 
						||
            // and remove leading zero
 | 
						||
            let str;
 | 
						||
            if (leadingZero) {
 | 
						||
              str = removeLeadingZero(num);
 | 
						||
            } else {
 | 
						||
              str = num.toString();
 | 
						||
            }
 | 
						||
 | 
						||
            // remove default 'px' units
 | 
						||
            if (defaultPx && units === 'px') {
 | 
						||
              units = '';
 | 
						||
            }
 | 
						||
 | 
						||
            node.attributes[name] = str + units;
 | 
						||
          }
 | 
						||
        }
 | 
						||
      },
 | 
						||
    },
 | 
						||
  };
 | 
						||
};
 |