Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions src/js/css-calc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from './cache';
import { isString, isStringOrNumber } from './common';
import { resolveVar } from './css-var';
import { roundToPrecision } from './util';
import { resolveLengthInPixels, roundToPrecision } from './util';
import { MatchedRegExp, Options } from './typedef';

/* constants */
Expand Down Expand Up @@ -786,22 +786,12 @@ export const resolveDimension = (
unit: string;
value: number;
};
const { dimension = {} } = opt;
if (unit === 'px') {
return `${value}${unit}`;
}
const relativeValue = Number(value);
if (unit && Number.isFinite(relativeValue)) {
let pixelValue;
if (Object.hasOwn(dimension, unit)) {
pixelValue = dimension[unit];
} else if (typeof dimension.callback === 'function') {
pixelValue = dimension.callback(unit);
}
pixelValue = Number(pixelValue);
if (Number.isFinite(pixelValue)) {
return `${relativeValue * pixelValue}px`;
}
const pixelValue = resolveLengthInPixels(Number(value), unit, opt);
if (Number.isFinite(pixelValue)) {
return `${roundToPrecision(pixelValue, HEX)}px`;
}
return new NullObject();
};
Expand Down
117 changes: 117 additions & 0 deletions src/js/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,120 @@ export const interpolateHue = (
}
return [hueA, hueB];
};

/* absolute font size to pixel ratio */
const absoluteFontSize = new Map([
['xx-small', 3 / 5],
['x-small', 3 / 4],
['small', 8 / 9],
['medium', 1],
['large', 6 / 5],
['x-large', 3 / 2],
['xx-large', 2],
['xxx-large', 3]
]);

/* relative font size to pixel ratio */
const relativeFontSize = new Map([
['smaller', 1 / 1.2],
['larger', 1.2]
]);

/* absolute length to pixel ratio */
const absoluteLength = new Map([
['cm', 96 / 2.54],
['mm', 96 / 2.54 / 10],
['q', 96 / 2.54 / 40],
['in', 96],
['pc', 96 / 6],
['pt', 96 / 72],
['px', 1]
]);

/* root relative length to pixel ratio */
const rootLength = new Map([
['rcap', 1],
['rch', 0.5],
['rem', 1],
['rex', 0.5],
['ric', 1],
['rlh', 1.2]
]);

/* relative length to pixel ratio */
const relativeLength = new Map([
['cap', 1],
['ch', 0.5],
['em', 1],
['ex', 0.5],
['ic', 1],
['lh', 1.2]
]);

/**
* resolve length in pixels
* @param value - value
* @param unit - unit
* @param [opt] - options
* @returns pixelated value
*/
export const resolveLengthInPixels = (
value: number | string,
unit: string | undefined,
opt: Options = {}
): number => {
const { dimension = {} } = opt;
const { callback, em, rem, vh, vw } = dimension as {
callback: (K: string) => number;
em: number;
rem: number;
vh: number;
vw: number;
};
if (isString(value)) {
value = value.toLowerCase().trim();
if (absoluteFontSize.has(value)) {
return Number(absoluteFontSize.get(value)) * rem;
} else if (relativeFontSize.has(value)) {
return Number(relativeFontSize.get(value)) * em;
}
return Number.NaN;
} else if (Number.isFinite(value) && unit) {
if (Object.hasOwn(dimension, unit)) {
return value * Number(dimension[unit]);
} else if (typeof callback === 'function') {
return value * callback(unit);
} else if (absoluteLength.has(unit)) {
return value * Number(absoluteLength.get(unit));
} else if (rootLength.has(unit)) {
return value * Number(rootLength.get(unit)) * rem;
} else if (relativeLength.has(unit)) {
return value * Number(relativeLength.get(unit)) * em;
} else {
switch (unit) {
case 'vb':
case 'vi': {
return value * vw;
}
case 'vmax': {
if (vh > vw) {
return value * vh;
}
return value * vw;
}
case 'vmin': {
if (vh < vw) {
return value * vh;
}
return value * vw;
}
default: {
// unsupported or invalid unit
return Number.NaN;
}
}
}
}
// unsupported or invalid value
return Number.NaN;
};
24 changes: 12 additions & 12 deletions test/css-calc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,7 @@ describe('resolve dimension', () => {
assert.strictEqual(res, '1200px', 'result');
});

it('should get null object', () => {
it('should get value', () => {
const token = [
'dimension-token',
'100ch',
Expand All @@ -1024,10 +1024,10 @@ describe('resolve dimension', () => {
vw: 10.26
}
});
assert.strictEqual(res.isNull, true, 'result');
assert.strictEqual(res, '600px', 'result');
});

it('should get null object', () => {
it('should get value', () => {
const token = [
'dimension-token',
'100ex',
Expand All @@ -1047,10 +1047,10 @@ describe('resolve dimension', () => {
vw: 10.26
}
});
assert.strictEqual(res.isNull, true, 'result');
assert.strictEqual(res, '600px', 'result');
});

it('should get null object', () => {
it('should get value', () => {
const token = [
'dimension-token',
'100lh',
Expand All @@ -1070,10 +1070,10 @@ describe('resolve dimension', () => {
vw: 10.26
}
});
assert.strictEqual(res.isNull, true, 'result');
assert.strictEqual(res, '1440px', 'result');
});

it('should get null object', () => {
it('should get value', () => {
const token = [
'dimension-token',
'10rch',
Expand All @@ -1093,10 +1093,10 @@ describe('resolve dimension', () => {
vw: 10.26
}
});
assert.strictEqual(res.isNull, true, 'result');
assert.strictEqual(res, '80px', 'result');
});

it('should get null object', () => {
it('should get value', () => {
const token = [
'dimension-token',
'10rex',
Expand All @@ -1116,10 +1116,10 @@ describe('resolve dimension', () => {
vw: 10.26
}
});
assert.strictEqual(res.isNull, true, 'result');
assert.strictEqual(res, '80px', 'result');
});

it('should get null object', () => {
it('should get value', () => {
const token = [
'dimension-token',
'100rlh',
Expand All @@ -1139,7 +1139,7 @@ describe('resolve dimension', () => {
vw: 10.26
}
});
assert.strictEqual(res.isNull, true, 'result');
assert.strictEqual(res, '1920px', 'result');
});

it('should get null object', () => {
Expand Down
Loading
Loading