Skip to content

Commit ed94a10

Browse files
authored
Merge pull request #1086 from mathjax/refactor/1/unit_utils
Refactor Units computation into separate Utils
2 parents 81e2437 + fcff964 commit ed94a10

File tree

16 files changed

+242
-207
lines changed

16 files changed

+242
-207
lines changed

pnpm-lock.yaml

Lines changed: 12 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/length.test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
import {jest} from '@jest/globals';
2-
import {ParseUtil} from '../mjs/input/tex/ParseUtil.js';
2+
import {UnitUtil} from '../mjs/input/tex/UnitUtil.js';
33
import * as Length from '../mjs/util/lengths.js';
44

55
// These methods will be rewritten into non-ParseUtil ones.
66
function convertLength(unit, num) {
7-
return ParseUtil.UNIT_CASES.get(unit) * (num);
7+
return UnitUtil.UNIT_CASES.get(unit) * (num);
88
}
99

1010
function matchDimension(str) {
11-
return ParseUtil.matchDimen(str);
11+
return UnitUtil.matchDimen(str);
1212
}
1313

1414
function convertDimension(str) {
15-
return ParseUtil.dimen2em(str);
15+
return UnitUtil.dimen2em(str);
1616
}
1717

1818
function convertLengthDim(str) {
1919
return Length.length2em(str);
2020
}
2121

2222
function convertEm(num) {
23-
return ParseUtil.em(num);
23+
return UnitUtil.em(num);
2424
}
2525

2626
describe('Length conversion', () => {
@@ -125,7 +125,7 @@ describe.skip('Dimension conversion comparison', () => {
125125

126126
// Useful for the IEEE case.
127127
describe('Adds pi unit', () => {
128-
beforeAll(() => ParseUtil.UNIT_CASES.set('pi', 1 / 10));
128+
beforeAll(() => UnitUtil.UNIT_CASES.set('pi', 1 / 10));
129129
it('pi', () => expect(convertLength('pi', 9)).toBe(0.9));
130130
it('9pi', () => expect(matchDimension('9pi')).toEqual(['9', 'pi', 3]));
131131
it('10pi', () => expect(matchDimension('10pi')).toEqual(['10', 'pi', 4]));

ts/input/tex/ColumnParser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import TexParser from './TexParser.js';
2626
import TexError from './TexError.js';
2727
import {lookup} from '../../util/Options.js';
2828
import {ParseUtil} from './ParseUtil.js';
29+
import { UnitUtil } from './UnitUtil.js';
2930

3031
/***********************************************************************/
3132

@@ -233,7 +234,7 @@ export class ColumnParser {
233234
*/
234235
public getDimen(state: ColumnState) {
235236
const dim = this.getBraces(state) || '';
236-
if (!ParseUtil.matchDimen(dim)[0]) {
237+
if (!UnitUtil.matchDimen(dim)[0]) {
237238
throw new TexError('MissingColumnDimOrUnits',
238239
'Missing dimension or its units for %1 column declaration', state.c);
239240
}

ts/input/tex/ParseUtil.ts

Lines changed: 4 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -31,79 +31,7 @@ import TexParser from './TexParser.js';
3131
import TexError from './TexError.js';
3232
import {entities} from '../../util/Entities.js';
3333
import {MmlMunderover} from '../../core/MmlTree/MmlNodes/munderover.js';
34-
35-
36-
class UnitMap extends Map<string, number> {
37-
38-
public num = '([-+]?([.,]\\d+|\\d+([.,]\\d*)?))';
39-
public unit = '';
40-
public dimenEnd = /./;
41-
public dimenRest = /./;
42-
43-
/**
44-
* @override
45-
*/
46-
constructor(map: [string, number][]) {
47-
super(map);
48-
this.updateDimen();
49-
}
50-
51-
/**
52-
* Updates the regular expressions for the unit.
53-
*/
54-
private updateDimen() {
55-
this.unit = `(${Array.from(this.keys()).join('|')})`;
56-
this.dimenEnd = RegExp('^\\s*' + this.num + '\\s*' + this.unit + '\\s*$');
57-
this.dimenRest = RegExp('^\\s*' + this.num + '\\s*' + this.unit + ' ?');
58-
}
59-
60-
/**
61-
* @override
62-
*/
63-
public set(name: string, ems: number) {
64-
super.set(name, ems);
65-
this.updateDimen();
66-
return this;
67-
}
68-
69-
/**
70-
* Retrieves conversion value for an existing dimension. If the dimension does
71-
* not exist, `pt` is used, similar to TeX behaviour. However, no error is thrown.
72-
*
73-
* @override
74-
*/
75-
public get(name: string) {
76-
return super.get(name) || super.get('pt');
77-
}
78-
79-
/**
80-
* @override
81-
*/
82-
public delete(name: string) {
83-
if (super.delete(name)) {
84-
this.updateDimen();
85-
return true;
86-
}
87-
return false;
88-
}
89-
90-
}
91-
92-
const emPerInch = 7.2;
93-
const pxPerInch = 72;
94-
95-
/**
96-
* Transforms mu dimension to em if necessary.
97-
* @param {[string, string, number]} [value, unit, length] The dimension triple.
98-
* @return {[string, string, number]} [value, unit, length] The transformed triple.
99-
*/
100-
function muReplace([value, unit, length]: [string, string, number]): [string, string, number] {
101-
if (unit !== 'mu') {
102-
return [value, unit, length];
103-
}
104-
let em = ParseUtil.em(ParseUtil.UNIT_CASES.get(unit) * (parseFloat(value || '1')));
105-
return [em.slice(0, -2), 'em', length];
106-
}
34+
import { UnitUtil } from './UnitUtil.js';
10735

10836

10937
/**
@@ -157,7 +85,7 @@ export const KeyValueTypes: {[name: string]: KeyValueType<any> | ((data: any) =>
15785
),
15886
dimen: new KeyValueType<string>(
15987
'dimen',
160-
(value) => ParseUtil.matchDimen(value)[0] !== null,
88+
(value) => UnitUtil.matchDimen(value)[0] !== null,
16189
(value) => value
16290
)
16391
};
@@ -271,62 +199,6 @@ function readValue(text: string, end: string[],
271199

272200
export const ParseUtil = {
273201

274-
// Note, the following are TeX CM font values.
275-
UNIT_CASES: new UnitMap([
276-
['em', 1],
277-
['ex', .43],
278-
['pt', 1 / 10], // 10 pt to an em
279-
['pc', 1.2], // 12 pt to a pc
280-
['px', emPerInch / pxPerInch],
281-
['in', emPerInch],
282-
['cm', emPerInch / 2.54], // 2.54 cm to an inch
283-
['mm', emPerInch / 25.4], // 10 mm to a cm
284-
['mu', 1 / 18],
285-
]),
286-
287-
288-
/**
289-
* Matches for a dimension argument.
290-
* @param {string} dim The argument.
291-
* @param {boolean} rest Allow for trailing garbage in the dimension string.
292-
* @return {[string, string, number]} The match result as (Anglosaxon) value,
293-
* unit name, length of matched string. The latter is interesting in the
294-
* case of trailing garbage.
295-
*/
296-
matchDimen(
297-
dim: string, rest: boolean = false): [string, string, number] {
298-
let match = dim.match(rest ? ParseUtil.UNIT_CASES.dimenRest : ParseUtil.UNIT_CASES.dimenEnd);
299-
return match ?
300-
muReplace([match[1].replace(/,/, '.'), match[4], match[0].length]) :
301-
[null, null, 0];
302-
},
303-
304-
305-
/**
306-
* Convert a dimension string into standard em dimension.
307-
* @param {string} dim The attribute string.
308-
* @return {number} The numerical value.
309-
*/
310-
dimen2em(dim: string): number {
311-
let [value, unit] = ParseUtil.matchDimen(dim);
312-
let m = parseFloat(value || '1');
313-
let factor = ParseUtil.UNIT_CASES.get(unit);
314-
return factor ? factor * (m) : 0;
315-
},
316-
317-
318-
/**
319-
* Turns a number into an em value.
320-
* @param {number} m The number.
321-
* @return {string} The em dimension string.
322-
*/
323-
em(m: number): string {
324-
if (Math.abs(m) < .0006) {
325-
return '0em';
326-
}
327-
return m.toFixed(3).replace(/\.?0+$/, '') + 'em';
328-
},
329-
330202
// Above will move into lenghts
331203
//
332204
// Remainder: Parse Utililities
@@ -337,7 +209,7 @@ export const ParseUtil = {
337209
* @return {string} The numbers with em units, separated by spaces.
338210
*/
339211
cols(...W: number[]): string {
340-
return W.map(n => ParseUtil.em(n)).join(' ');
212+
return W.map(n => UnitUtil.em(n)).join(' ');
341213
},
342214

343215

@@ -638,23 +510,6 @@ export const ParseUtil = {
638510
}
639511
},
640512

641-
/**
642-
* Trim spaces from a string.
643-
* @param {string} text The string to clean.
644-
* @return {string} The string with leading and trailing whitespace removed.
645-
*/
646-
trimSpaces(text: string): string {
647-
if (typeof(text) !== 'string') {
648-
return text;
649-
}
650-
let TEXT = text.trim();
651-
if (TEXT.match(/\\$/) && text.match(/ $/)) {
652-
TEXT += ' ';
653-
}
654-
return TEXT;
655-
},
656-
657-
658513
/**
659514
* Sets alignment in array definitions.
660515
* @param {ArrayItem} array The array item.
@@ -665,7 +520,7 @@ export const ParseUtil = {
665520
setArrayAlign(array: ArrayItem, align: string, parser?: TexParser): ArrayItem {
666521
// @test Array1, Array2, Array Test
667522
if (!parser) {
668-
align = ParseUtil.trimSpaces(align || '');
523+
align = UnitUtil.trimSpaces(align || '');
669524
}
670525
if (align === 't') {
671526
array.arraydef.align = 'baseline 1';

ts/input/tex/TexParser.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* @author [email protected] (Volker Sorge)
2424
*/
2525

26-
import {ParseUtil} from './ParseUtil.js';
26+
import {UnitUtil} from './UnitUtil.js';
2727
import {HandlerType} from './MapHandler.js';
2828
import Stack from './Stack.js';
2929
import StackItemFactory from './StackItemFactory.js';
@@ -415,15 +415,15 @@ export default class TexParser {
415415
public GetDimen(name: string): string {
416416
if (this.GetNext() === '{') {
417417
let dimen = this.GetArgument(name);
418-
let [value, unit] = ParseUtil.matchDimen(dimen);
418+
let [value, unit] = UnitUtil.matchDimen(dimen);
419419
if (value) {
420420
// @test Raise In Line, Lower 2, (Raise|Lower) Negative
421421
return value + unit;
422422
}
423423
} else {
424424
// @test Above, Raise, Lower, Modulo, Above With Delims
425425
let dimen = this.string.slice(this.i);
426-
let [value, unit, length] = ParseUtil.matchDimen(dimen, true);
426+
let [value, unit, length] = UnitUtil.matchDimen(dimen, true);
427427
if (value) {
428428
this.i += length;
429429
return value + unit;
@@ -498,7 +498,7 @@ export default class TexParser {
498498
* @return {string} The delimiter.
499499
*/
500500
public GetDelimiterArg(name: string): string {
501-
let c = ParseUtil.trimSpaces(this.GetArgument(name));
501+
let c = UnitUtil.trimSpaces(this.GetArgument(name));
502502
if (c === '') {
503503
return null;
504504
}

0 commit comments

Comments
 (0)