UNPKG

jsdom

Version:

A JavaScript implementation of many web standards

172 lines (153 loc) 4.83 kB
"use strict"; // TODO: Support math keyword. const cssValues = require("./css-values"); const FONT_SIZE_REGEXP = /^((?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)(%|[a-z]+)$/; const LENGTH_REGEXP = /^([+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)(%|[a-z]*)$/; // Absolute font size mapping table. const absoluteFontSize = new Map([ ["xx-small", { px: 9, ratio: 9 / 16 }], ["x-small", { px: 10, ratio: 5 / 8 }], ["small", { px: 13, ratio: 13 / 16 }], ["medium", { px: 16, ratio: 1 }], ["large", { px: 18, ratio: 9 / 8 }], ["x-large", { px: 24, ratio: 1.5 }], ["xx-large", { px: 32, ratio: 2 }], ["xxx-large", { px: 48, ratio: 3 }] ]); // Ratio of relative font size to pixels. const relativeFontSize = new Map([ ["smaller", 1 / 1.2], ["larger", 1.2] ]); // Ratio of absolute length to pixels. const absoluteLength = new Map([ ["cm", 96 / 2.54], ["mm", 96 / 25.4], ["q", 96 / 101.6], ["in", 96], ["pc", 16], ["pt", 96 / 72], ["px", 1] ]); // Ratio of root relative length to pixels. const rootRelativeLength = new Map([ ["rcap", 1], ["rch", 0.5], ["rem", 1], ["rex", 0.5], ["ric", 1], ["rlh", 1.2] ]); // Ratio of relative length or percentage to pixels. const relativeLength = new Map([ ["%", 0.01], ["cap", 1], ["ch", 0.5], ["em", 1], ["ex", 0.5], ["ic", 1], ["lh", 1.2] ]); function resolveFontSizeInPixels(elementImpl, size, root, parent) { const isRelative = typeof parent === "number"; if (absoluteFontSize.has(size)) { const pxSize = absoluteFontSize.get(size).px; if (isRelative) { return pxSize * parent; } return pxSize; } else if (isRelative && relativeFontSize.has(size)) { return relativeFontSize.get(size) * parent; } const match = FONT_SIZE_REGEXP.exec(size); if (match) { const [, value, unit] = match; if (absoluteLength.has(unit)) { return value * absoluteLength.get(unit); } else if (rootRelativeLength.has(unit)) { const pxSize = root ?? absoluteFontSize.get("medium").px; return value * rootRelativeLength.get(unit) * pxSize; } else if (relativeLength.has(unit)) { if (isRelative) { return value * relativeLength.get(unit) * parent; } const pxSize = root ?? absoluteFontSize.get("medium").px; return value * relativeLength.get(unit) * pxSize; } } return Number.NaN; } function resolveLengthInPixels(elementImpl, size, dimension, isFontSize) { const { em, rem, vh, vw } = dimension; if (absoluteFontSize.has(size)) { return absoluteFontSize.get(size).px; } else if (relativeFontSize.has(size)) { return relativeFontSize.get(size) * em; } else if (cssValues.hasCalcFunc(size)) { let resolvedSize; if (elementImpl === elementImpl._ownerDocument.documentElement) { resolvedSize = cssValues.resolveCalc(size, { dimension: { em: absoluteFontSize.get("medium").px, rem: absoluteFontSize.get("medium").px, vh: elementImpl._globalObject.innerHeight / 100, vw: elementImpl._globalObject.innerWidth / 100 }, format: "computedValue" }); } else { resolvedSize = cssValues.resolveCalc(size, { dimension, format: "computedValue" }); } const matchLength = LENGTH_REGEXP.exec(resolvedSize); if (matchLength) { const [, value] = matchLength; return Number(value); } // Return as-is as a fallback. return size; } const match = LENGTH_REGEXP.exec(size); if (match) { const [, value, unit] = match; // Percentage value resolution varies depending on the property. // Therefore, except for font-size, the values are returned as-is without attempting to resolve them. if (unit === "%" && !isFontSize) { return size; } else if (absoluteLength.has(unit)) { return value * absoluteLength.get(unit); } else if (rootRelativeLength.has(unit)) { const pxSize = rem ?? absoluteFontSize.get("medium").px; return value * rootRelativeLength.get(unit) * pxSize; } else if (relativeLength.has(unit)) { const pxSize = em ?? absoluteFontSize.get("medium").px; return value * relativeLength.get(unit) * pxSize; } switch (unit) { case "vb": { return value * vh; } case "vi": { return value * vw; } case "vmax": { return value * Math.max(vh, vw); } case "vmin": { return value * Math.min(vh, vw); } default: { if (Object.hasOwn(dimension, unit)) { return value * dimension[unit]; } } } } // Return as-is as a fallback. return size; } exports.absoluteFontSize = absoluteFontSize; exports.resolveFontSizeInPixels = resolveFontSizeInPixels; exports.resolveLengthInPixels = resolveLengthInPixels;