font-utils.js (3323B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 module.exports = { 8 /** 9 * Given a CSS unit type, get the amount by which to increment a numeric value. 10 * Used as the step attribute in inputs of type "range" or "number". 11 * 12 * @param {string} unit 13 * CSS unit type (px, %, em, rem, vh, vw, ...) 14 * @return {number} 15 * Amount by which to increment. 16 */ 17 getStepForUnit(unit) { 18 let step; 19 switch (unit) { 20 case "": 21 case "em": 22 case "rem": 23 case "vw": 24 case "vh": 25 case "vmin": 26 case "vmax": 27 step = 0.1; 28 break; 29 default: 30 step = 1; 31 } 32 33 return step; 34 }, 35 36 /** 37 * Get the unit type from the end of a CSS value string. 38 * Returns null for non-string input or unitless values. 39 * 40 * @param {string} value 41 * CSS value string. 42 * @return {string | null} 43 * CSS unit type, like "px", "em", "rem", etc or null. 44 */ 45 getUnitFromValue(value) { 46 if (typeof value !== "string" || isNaN(parseFloat(value))) { 47 return null; 48 } 49 50 const match = value.match(/\D+?$/); 51 return match?.length ? match[0] : null; 52 }, 53 54 /** 55 * Parse the string value of CSS font-variation-settings into an object with 56 * axis tag names and corresponding values. If the string is a keyword or does not 57 * contain axes, return an empty object. 58 * 59 * @param {string} string 60 * Value of font-variation-settings property coming from node's computed style. 61 * Its contents are expected to be stable having been already parsed by the 62 * browser. 63 * @return {object} 64 */ 65 parseFontVariationAxes(string) { 66 let axes = {}; 67 const keywords = ["initial", "normal", "inherit", "unset"]; 68 69 if (!string || keywords.includes(string.trim())) { 70 return axes; 71 } 72 73 // Parse font-variation-settings CSS declaration into an object 74 // with axis tags as keys and axis values as values. 75 axes = string.split(",").reduce((acc, pair) => { 76 // Tags are always in quotes. Split by quote and filter excessive whitespace. 77 pair = pair.split(/["']/).filter(part => part.trim() !== ""); 78 // Guard against malformed input that may have slipped through. 79 if (pair.length === 0) { 80 return acc; 81 } 82 83 const tag = pair[0]; 84 const value = pair[1].trim(); 85 // Axis tags shorter or longer than 4 characters are invalid. Whitespace is valid. 86 if (tag.length === 4) { 87 acc[tag] = parseFloat(value); 88 } 89 return acc; 90 }, {}); 91 92 return axes; 93 }, 94 95 /** 96 * Limit the decimal count of a number. Unlike Number.toFixed(), 97 * this function does not pad with extra zeros. If the input is not a number, 98 * the function throws an error. 99 * 100 * @param {number} number 101 * @param {number} decimals 102 * Decimal count in the output number. Default to one decimal. 103 * @return {number} 104 */ 105 toFixed(number, decimals = 1) { 106 if (typeof number !== "number") { 107 throw new Error(`Input: "${number}" is not a number.`); 108 } 109 110 return Math.floor(number * Math.pow(10, decimals)) / Math.pow(10, decimals); 111 }, 112 };