diff --git a/components/mjs/input/tex/extensions/braket/config.json b/components/mjs/input/tex/extensions/braket/config.json index 6c565b4d3..b548fd447 100644 --- a/components/mjs/input/tex/extensions/braket/config.json +++ b/components/mjs/input/tex/extensions/braket/config.json @@ -6,13 +6,6 @@ "input/tex/braket" ] }, - "copy": { - "to": "[bundle]/input/tex/extensions/braket", - "from": "[ts]/input/tex/braket", - "copy": [ - "__locales__" - ] - }, "webpack": { "name": "input/tex/extensions/braket", "libs": [ diff --git a/components/mjs/input/tex/extensions/texhtml/config.json b/components/mjs/input/tex/extensions/texhtml/config.json index f83300f1d..ec464a094 100644 --- a/components/mjs/input/tex/extensions/texhtml/config.json +++ b/components/mjs/input/tex/extensions/texhtml/config.json @@ -6,13 +6,6 @@ "input/tex/texhtml" ] }, - "copy": { - "to": "[bundle]/input/tex/extensions/texhtml", - "from": "[ts]/input/tex/texhtml", - "copy": [ - "__locales__" - ] - }, "webpack": { "name": "input/tex/extensions/texhtml", "libs": [ diff --git a/testsuite/tests/input/tex/Base.test.ts b/testsuite/tests/input/tex/Base.test.ts index 6e06df5d7..ac6aa539c 100644 --- a/testsuite/tests/input/tex/Base.test.ts +++ b/testsuite/tests/input/tex/Base.test.ts @@ -255,7 +255,7 @@ describe('Error', () => { }); it('Ampersand-error', () => { - expectTexError('&').toBe('Misplaced &'); + expectTexError('&').toBe("Misplaced '&'"); }); it('Argument-error', () => { @@ -389,7 +389,7 @@ describe('Error', () => { }); it('Misplaced Cr', () => { - expectTexError('a\\cr b').toBe('Misplaced \\cr'); + expectTexError('a\\cr b').toBe("Misplaced '\\cr'"); }); it('Dimension Error', () => { @@ -461,7 +461,7 @@ describe('Error', () => { }); it('Misplaced hline', () => { - expectTexError('\\hline').toBe('Misplaced \\hline'); + expectTexError('\\hline').toBe("Misplaced '\\hline'"); }); it('UnsupportedHFill', () => { diff --git a/testsuite/tests/input/tex/Physics.test.ts b/testsuite/tests/input/tex/Physics.test.ts index f95ea9cc5..7f0987202 100644 --- a/testsuite/tests/input/tex/Physics.test.ts +++ b/testsuite/tests/input/tex/Physics.test.ts @@ -2472,6 +2472,18 @@ describe('Physics Errors', () => { it('InvalidNumber XMatrix m+', () => { expectTexError('\\smqty(\\xmatrix{a}{2}{2.0})').toBe('Invalid number'); }); + + it('Missing Closing Delimiter', () => { + expect( + tex2mml('\\sin(1\\over2') + ).toMatchSnapshot(); + }); + + it('Extra Open Delimiter', () => { + expect( + tex2mml('\\sin((1\\over2)') + ).toMatchSnapshot(); + }); }); /**********************************************************************************/ diff --git a/testsuite/tests/input/tex/Tex.test.ts b/testsuite/tests/input/tex/Tex.test.ts index a13a21551..a085b0bdf 100644 --- a/testsuite/tests/input/tex/Tex.test.ts +++ b/testsuite/tests/input/tex/Tex.test.ts @@ -24,6 +24,7 @@ import { HandlerType, ConfigurationType } from '#js/input/tex/HandlerTypes.js'; import { CommandMap } from '#js/input/tex/TokenMap.js'; import { Token } from '#js/input/tex/Token.js'; import { TagsFactory } from '#js/input/tex/Tags.js'; +import { texError } from '#js/input/tex/TexError.js'; import TexError from '#js/input/tex/TexError.js'; import { ParseUtil, @@ -138,26 +139,43 @@ describe('Tags', () => { describe('TexError', () => { test('Number argument', () => { - const err = new TexError(null, 'test', 'Number: %1', 1 as any); + const err = new TexError('test', 'Number: %1', 1 as any); expect(err.message).toBe('Number: 1'); }); test('Braced insertion', () => { - const err = new TexError(null, 'test', 'Msg: %{1}, Number: %{2}', 'OK', 2 as any); + const err = new TexError('test', 'Msg: %{1}, Number: %{2}', 'OK', 2 as any); expect(err.message).toBe('Msg: OK, Number: 2'); }); test.skip('Plural', () => { - const err = new TexError(null, 'test', '%{plural:%1|abc}', 'apple'); + const err = new TexError('test', '%{plural:%1|abc}', 'apple'); expect(err.message).toBe('%{plural:%1|abc}'); }); test('Percent', () => { - const err = new TexError(null, 'test', '10%%'); + const err = new TexError('test', '10%%'); expect(err.message).toBe('10%'); }); }); +describe('texError', () => { + test('Number argument', () => { + expect(() => texError(null, 'test', 'Number: %1', '1')) + .toThrow('Number: 1'); + }); + + test('Braced insertion', () => { + expect(() => texError(null, 'test', 'Msg: %{1}, Number: %{2}', 'OK', '2')) + .toThrow('Msg: OK, Number: 2'); + }); + + test('Percent', () => { + expect(() => texError(null, 'test', '10%%')) + .toThrow('10%'); + }); +}); + /**********************************************************************************/ setupComponents({ diff --git a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap index bc59e9aa3..66b32fe9e 100644 --- a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap @@ -3495,8 +3495,8 @@ exports[`Environments math 1`] = ` exports[`Error merror node 1`] = ` " - - Misplaced & + + Misplaced '&' " `; diff --git a/testsuite/tests/input/tex/__snapshots__/Noerrors.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Noerrors.test.ts.snap index 78b214274..2cf6cc091 100644 --- a/testsuite/tests/input/tex/__snapshots__/Noerrors.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Noerrors.test.ts.snap @@ -2,7 +2,7 @@ exports[`NoError Ampersand-error 1`] = ` " - + & " @@ -210,7 +210,7 @@ exports[`NoError Middle with Right 1`] = ` exports[`NoError Misplaced Cr 1`] = ` " - + a\\cr b " @@ -226,7 +226,7 @@ exports[`NoError Misplaced Move Root 1`] = ` exports[`NoError Misplaced hline 1`] = ` " - + \\hline " diff --git a/testsuite/tests/input/tex/__snapshots__/Physics.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Physics.test.ts.snap index 218039580..e644e868f 100644 --- a/testsuite/tests/input/tex/__snapshots__/Physics.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Physics.test.ts.snap @@ -1154,6 +1154,22 @@ exports[`Options Italicdif true 1`] = ` " `; +exports[`Physics Errors Extra Open Delimiter 1`] = ` +" + + Extra open or missing close delimiter + +" +`; + +exports[`Physics Errors Missing Closing Delimiter 1`] = ` +" + + Extra open or missing close delimiter + +" +`; + exports[`Physics1_0 Quantities_Quantities_0 1`] = ` " diff --git a/ts/input/tex/ColumnParser.ts b/ts/input/tex/ColumnParser.ts index c86a440a7..ffa6ed05c 100644 --- a/ts/input/tex/ColumnParser.ts +++ b/ts/input/tex/ColumnParser.ts @@ -23,7 +23,7 @@ import { ArrayItem } from './base/BaseItems.js'; import TexParser from './TexParser.js'; -import TexError from './TexError.js'; +import { texError } from './TexError.js'; import { lookup } from '../../util/Options.js'; import { ParseUtil } from './ParseUtil.js'; import { UnitUtil } from './UnitUtil.js'; @@ -135,13 +135,13 @@ export class ColumnParser { let n = 0; while (state.i < state.template.length) { if (n++ > this.MAXCOLUMNS) { - throw new TexError(COMPONENT, 'MaxColumns'); + texError(COMPONENT, 'MaxColumns'); } const code = state.template.codePointAt(state.i); const c = (state.c = String.fromCodePoint(code)); state.i += c.length; if (!Object.hasOwn(this.columnHandler, c)) { - throw new TexError(COMPONENT, 'BadPreamToken', c); + texError(COMPONENT, 'BadPreamToken', c); } this.columnHandler[c](state); } @@ -263,7 +263,7 @@ export class ColumnParser { public getDimen(state: ColumnState): string { const dim = this.getBraces(state); if (!UnitUtil.matchDimen(dim)[0]) { - throw new TexError(COMPONENT, 'MissingColumnDimOrUnits', state.c); + texError(COMPONENT, 'MissingColumnDimOrUnits', state.c); } return dim; } @@ -294,7 +294,7 @@ export class ColumnParser { public getBraces(state: ColumnState): string { while (state.template[state.i] === ' ') state.i++; if (state.i >= state.template.length) { - throw new TexError(COMPONENT, 'MissingArgForColumn', state.c); + texError(COMPONENT, 'MissingArgForColumn', state.c); } if (state.template[state.i] !== '{') { return state.template[state.i++]; @@ -316,7 +316,7 @@ export class ColumnParser { break; } } - throw new TexError(COMPONENT, 'MissingCloseBrace'); + texError(COMPONENT, 'MissingCloseBrace'); } /** @@ -401,7 +401,7 @@ export class ColumnParser { const cols = this.getBraces(state); const n = parseInt(num); if (String(n) !== num) { - throw new TexError(COMPONENT, 'ColArgNotNum', '*'); + texError(COMPONENT, 'ColArgNotNum', '*'); } state.template = new Array(n).fill(cols).join('') + state.template.substring(state.i); diff --git a/ts/input/tex/ParseUtil.ts b/ts/input/tex/ParseUtil.ts index 4fab7078d..807c22b7b 100644 --- a/ts/input/tex/ParseUtil.ts +++ b/ts/input/tex/ParseUtil.ts @@ -27,7 +27,7 @@ import { ArrayItem } from './base/BaseItems.js'; import ParseOptions from './ParseOptions.js'; import NodeUtil from './NodeUtil.js'; import TexParser from './TexParser.js'; -import TexError from './TexError.js'; +import { texError } from './TexError.js'; import { entities } from '../../util/Entities.js'; import { MmlMunderover } from '../../core/MmlTree/MmlNodes/munderover.js'; import { UnitUtil } from './UnitUtil.js'; @@ -188,7 +188,7 @@ function readValue( case '}': if (!braces) { // Closing braces. - throw new TexError(COMPONENT, 'ExtraCloseMissingOpen'); + texError(COMPONENT, 'ExtraCloseMissingOpen'); } braces--; countBraces = false; // Stop counting start left braces. @@ -211,7 +211,7 @@ function readValue( value += c; } if (braces) { - throw new TexError(COMPONENT, 'ExtraOpenMissingClose'); + texError(COMPONENT, 'ExtraOpenMissingClose'); } return dropBrace && start ? ['', '', removeBraces(value, 1)] @@ -543,7 +543,7 @@ export const ParseUtil = { .substring(i) .match(/^\s*(?:([0-9A-F])|\{\s*([0-9A-F]+)\s*\})/); if (!arg) { - throw new TexError(COMPONENT, 'BadRawUnicode', '\\U'); + texError(COMPONENT, 'BadRawUnicode', '\\U'); } // Replace \U{...} with specified character const c = String.fromCodePoint(parseInt(arg[1] || arg[2], 16)); @@ -558,7 +558,7 @@ export const ParseUtil = { } if (match !== '') { // @test Internal Math Error - throw new TexError(COMPONENT, 'MathNotTerminated'); + texError(COMPONENT, 'MathNotTerminated'); } } if (k < text.length) { @@ -723,7 +723,7 @@ export const ParseUtil = { text += c; } else { if (!c.match(/[1-9]/) || parseInt(c, 10) > args.length) { - throw new TexError(COMPONENT, 'IllegalMacroParam'); + texError(COMPONENT, 'IllegalMacroParam'); } newstring = ParseUtil.addArgs( parser, @@ -754,7 +754,7 @@ export const ParseUtil = { s1 += ' '; } if (s1.length + s2.length > parser.configuration.options['maxBuffer']) { - throw new TexError(COMPONENT, 'MaxBufferSize'); + texError(COMPONENT, 'MaxBufferSize'); } return s1 + s2; }, @@ -770,9 +770,9 @@ export const ParseUtil = { return; } if (isMacro) { - throw new TexError(COMPONENT, 'MaxMacroSub1'); + texError(COMPONENT, 'MaxMacroSub1'); } else { - throw new TexError(COMPONENT, 'MaxMacroSub2'); + texError(COMPONENT, 'MaxMacroSub2'); } }, @@ -795,7 +795,7 @@ export const ParseUtil = { return; } if (!top.isKind('start') || first) { - throw new TexError(COMPONENT, 'ErroneousNestingEq'); + texError(COMPONENT, 'ErroneousNestingEq'); } }, @@ -874,13 +874,13 @@ export const ParseUtil = { const type = allowed[key] as KeyValueDef; const value = String(def[key]); if (!type.verify(value)) { - throw new TexError(COMPONENT, 'InvalidValue', key); + texError(COMPONENT, 'InvalidValue', key); } def[key] = type.convert(value); } } else { if (error) { - throw new TexError(COMPONENT, 'InvalidOption', key); + texError(COMPONENT, 'InvalidOption', key); } delete def[key]; } diff --git a/ts/input/tex/StackItem.ts b/ts/input/tex/StackItem.ts index a5407dda0..e86b23839 100644 --- a/ts/input/tex/StackItem.ts +++ b/ts/input/tex/StackItem.ts @@ -23,10 +23,9 @@ import { MmlNode } from '../../core/MmlTree/MmlNode.js'; import { FactoryNodeClass } from '../../core/Tree/Factory.js'; -import TexError from './TexError.js'; +import { texError } from './TexError.js'; import StackItemFactory from './StackItemFactory.js'; import { TexConstant } from './TexConstants.js'; - import { COMPONENT } from './__locales__/Component.js'; // Union types for abbreviation. @@ -390,16 +389,16 @@ export abstract class BaseItem extends MmlStack implements StackItem { /** * A list of basic errors. * - * @type {{[key: string]: string}} + * @type {{[key: string]: [string, string]}} */ - protected static errors: { [key: string]: string } = { + protected static errors: { [key: string]: [string, string] } = { // @test ExtraOpenMissingClose - end: 'MissingBeginExtraEnd', + end: [COMPONENT, 'MissingBeginExtraEnd'], // @test ExtraCloseMissingOpen - close: 'ExtraCloseMissingOpen', + close: [COMPONENT, 'ExtraCloseMissingOpen'], // @test MissingLeftExtraRight - right: 'MissingLeftExtraRight', - middle: 'ExtraMiddle', + right: [COMPONENT, 'MissingLeftExtraRight'], + middle: [COMPONENT, 'ExtraMiddle'], }; /** @@ -516,12 +515,12 @@ export abstract class BaseItem extends MmlStack implements StackItem { return BaseItem.fail; } // @test Ampersand-error - throw new TexError(COMPONENT, 'Misplaced', item.getName()); + texError(COMPONENT, 'Misplaced', item.getName()); } if (item.isClose && this.getError(item.kind)) { // @test ExtraOpenMissingClose, ExtraCloseMissingOpen, // MissingLeftExtraRight, MissingBeginExtraEnd - throw new TexError(COMPONENT, this.getError(item.kind), item.getName()); + texError(...this.getError(item.kind), item.getName()); } if (!item.isFinal) { return BaseItem.success; @@ -567,9 +566,9 @@ export abstract class BaseItem extends MmlStack implements StackItem { * subclasses. * * @param {string} kind The stack item type. - * @returns {string} The id of the error message. + * @returns {[string, string]} The component and id of the error message. */ - public getError(kind: string): string { + public getError(kind: string): [string, string] { const CLASS = this.constructor as typeof BaseItem; return CLASS.errors?.[kind] ?? BaseItem.errors[kind]; } diff --git a/ts/input/tex/Tags.ts b/ts/input/tex/Tags.ts index 0f62b716a..74ded1d7b 100644 --- a/ts/input/tex/Tags.ts +++ b/ts/input/tex/Tags.ts @@ -22,10 +22,12 @@ */ import TexParser from './TexParser.js'; +import { texError } from './TexError.js'; import { MmlNode } from '../../core/MmlTree/MmlNode.js'; import { MathItem } from '../../core/MathItem.js'; import { EnvList } from './StackItem.js'; import ParseOptions from './ParseOptions.js'; +import { COMPONENT } from './__locales__/Component.js'; /** * Simple class for label objects. @@ -696,7 +698,7 @@ export const TagsFactory = { create(name: string): Tags { const constr = tagsMapping.get(name) || tagsMapping.get(defaultTags); if (!constr) { - throw Error('Unknown tags class'); + texError(COMPONENT, 'UnknownTag'); } return new constr(); }, diff --git a/ts/input/tex/TexError.ts b/ts/input/tex/TexError.ts index 330c2a005..e5b75e973 100644 --- a/ts/input/tex/TexError.ts +++ b/ts/input/tex/TexError.ts @@ -27,15 +27,29 @@ export default class TexError { public message: string; /** - * @param {string} component locale component (e.g. '[tex]/base') * @param {string} id message id + * @param {string} message text of English message * @param {string[]} args substitution arguments */ constructor( - public component: string, public id: string, + message: string, ...args: string[] ) { - this.message = Locale.message(component, id, ...args); + this.message = Locale.processMessage(message, args[0], ...args.slice(1)); } } + +/** + * @param {string} component locale component (e.g. '[tex]/base') + * @param {string} id message id + * @param {string[]} args substitution arguments + */ +export function texError( + component: string, + id: string, + ...args: string[] +): never { + const message = Locale.message(component, id, ...args); + throw new TexError(id, message, ...args); +} diff --git a/ts/input/tex/TexParser.ts b/ts/input/tex/TexParser.ts index 6b5e08611..ba11b419a 100644 --- a/ts/input/tex/TexParser.ts +++ b/ts/input/tex/TexParser.ts @@ -27,7 +27,7 @@ import { UnitUtil } from './UnitUtil.js'; import Stack from './Stack.js'; import StackItemFactory from './StackItemFactory.js'; import { Tags } from './Tags.js'; -import TexError from './TexError.js'; +import { texError } from './TexError.js'; import { MmlNode, AbstractMmlNode } from '../../core/MmlTree/MmlNode.js'; import { ParseInput, ParseResult } from './Types.js'; import ParseOptions from './ParseOptions.js'; @@ -35,7 +35,6 @@ import { BaseItem, StackItem, EnvList } from './StackItem.js'; import { Token } from './Token.js'; import { OptionList } from '../../util/Options.js'; import { TexConstant } from './TexConstants.js'; - import { COMPONENT } from './__locales__/Component.js'; /** @@ -332,13 +331,13 @@ export default class TexParser { case '': if (!noneOK) { // @test MissingArgFor - throw new TexError(COMPONENT, 'MissingArgFor', this.currentCS); + texError(COMPONENT, 'MissingArgFor', this.currentCS); } return null; case '}': if (!noneOK) { // @test ExtraCloseMissingOpen - throw new TexError(COMPONENT, 'ExtraCloseMissingOpen'); + texError(COMPONENT, 'ExtraCloseMissingOpen'); } return null; case '\\': @@ -363,7 +362,7 @@ export default class TexParser { } } // @test MissingCloseBrace - throw new TexError(COMPONENT, 'MissingCloseBrace'); + texError(COMPONENT, 'MissingCloseBrace'); } } const c = this.getCodePoint(); @@ -401,7 +400,7 @@ export default class TexParser { case '}': if (braces-- <= 0) { // @test ExtraCloseLooking1 - throw new TexError(COMPONENT, 'ExtraCloseLooking', "']'"); + texError(COMPONENT, 'ExtraCloseLooking', "']'"); } break; case '[': @@ -418,7 +417,7 @@ export default class TexParser { } } // @test MissingCloseBracket - throw new TexError(COMPONENT, 'MissingCloseBracket', this.currentCS); + texError(COMPONENT, 'MissingCloseBracket', this.currentCS); } /** @@ -443,7 +442,7 @@ export default class TexParser { } } // @test MissingOrUnrecognizedDelim1, MissingOrUnrecognizedDelim2 - throw new TexError(COMPONENT, 'MissingOrUnrecognizedDelim', this.currentCS); + texError(COMPONENT, 'MissingOrUnrecognizedDelim', this.currentCS); } /** @@ -470,7 +469,7 @@ export default class TexParser { } } // @test MissingDimOrUnits - throw new TexError(COMPONENT, 'MissingDimOrUnits', this.currentCS); + texError(COMPONENT, 'MissingDimOrUnits', this.currentCS); } /** @@ -500,7 +499,7 @@ export default class TexParser { case '}': if (braces === 0) { // @test ExtraCloseLooking2 - throw new TexError(COMPONENT, 'ExtraCloseLooking', token); + texError(COMPONENT, 'ExtraCloseLooking', token); } braces--; break; @@ -510,12 +509,7 @@ export default class TexParser { } } // @test TokenNotFoundForCommand - throw new TexError( - COMPONENT, - 'TokenNotFoundForCommand', - token, - this.currentCS - ); + texError(COMPONENT, 'TokenNotFoundForCommand', token, this.currentCS); } /** @@ -562,7 +556,7 @@ export default class TexParser { return c; } // @test MissingOrUnrecognizedDelim - throw new TexError(COMPONENT, 'MissingOrUnrecognizedDelim', this.currentCS); + texError(COMPONENT, 'MissingOrUnrecognizedDelim', this.currentCS); } /** diff --git a/ts/input/tex/__locales__/de.json b/ts/input/tex/__locales__/de.json index bfc88580e..ff5024281 100644 --- a/ts/input/tex/__locales__/de.json +++ b/ts/input/tex/__locales__/de.json @@ -5,7 +5,6 @@ "ErroneousNestingEq": "Fehlerhafte Verschachtelung von Gleichungsstrukturen", "ExtraCloseLooking": "Überflüssige schließende Klammer bei der Suche nach %1", "ExtraCloseMissingOpen": "Überflüssige schließende Klammer oder fehlende öffnende Klammer", - "ExtraLeftMissingRight": "Überflüssiges \\left oder fehlendes \\right", "ExtraMiddle": "Zusätzliches \\middle", "ExtraOpenMissingClose": "Zusätzliche öffnende Klammer oder fehlende schließende Klammer", "IllegalMacroParam": "Ungültiger Makroparameterverweis", @@ -16,7 +15,7 @@ "MaxColumns": "Zu viele Spaltenangaben (möglicherweise sich wiederholende Spaltendefinitionen?)", "MaxMacroSub1": "Maximale Anzahl an Makrosubstitutionen in MathJax überschritten; liegt ein rekursiver Makroaufruf vor?", "MaxMacroSub2": "Maximale Anzahl an Ersetzungen in MathJax überschritten; liegt eine rekursive LaTeX-Umgebung vor?", - "Misplaced": "%1 falsch platziert", + "Misplaced": "'%1' falsch platziert", "MissingArgFor": "Fehlendes Argument für %1", "MissingArgForColumn": "Fehlendes Argument für die Spaltendeklaration %1", "MissingBeginExtraEnd": "Fehlendes \\begin{%1} oder zusätzliches \\end{%1}", @@ -27,5 +26,6 @@ "MissingLeftExtraRight": "Missing \\left or extra \\right", "MissingOrUnrecognizedDelim": "Missing or unrecognized delimiter for %1", "MissingScript": "Fehlendes Argument für Hoch- oder Tiefstellung", - "TokenNotFoundForCommand": "Could not find %1 for %2" + "TokenNotFoundForCommand": "Could not find %1 for %2", + "UnknownTag": "Unbekannte Bezeichner Klasse" } diff --git a/ts/input/tex/__locales__/en.json b/ts/input/tex/__locales__/en.json index 829f1d746..c822ef075 100644 --- a/ts/input/tex/__locales__/en.json +++ b/ts/input/tex/__locales__/en.json @@ -5,7 +5,6 @@ "ErroneousNestingEq": "Erroneous nesting of equation structures", "ExtraCloseLooking": "Extra close brace while looking for %1", "ExtraCloseMissingOpen": "Extra close brace or missing open brace", - "ExtraLeftMissingRight": "Extra \\left or missing \\right", "ExtraMiddle": "Extra \\middle", "ExtraOpenMissingClose": "Extra open brace or missing close brace", "IllegalMacroParam": "Illegal macro parameter reference", @@ -16,7 +15,7 @@ "MaxColumns": "Too many column specifiers (perhaps looping column definitions?)", "MaxMacroSub1": "MathJax maximum macro substitution count exceeded; is there a recursive macro call?", "MaxMacroSub2": "MathJax maximum substitution count exceeded; is there a recursive latex environment?", - "Misplaced": "Misplaced %1", + "Misplaced": "Misplaced '%1'", "MissingArgFor": "Missing argument for %1", "MissingArgForColumn": "Missing argument for %1 column declaration", "MissingBeginExtraEnd": "Missing \\begin{%1} or extra \\end{%1}", @@ -27,5 +26,6 @@ "MissingLeftExtraRight": "Missing \\left or extra \\right", "MissingOrUnrecognizedDelim": "Missing or unrecognized delimiter for %1", "MissingScript": "Missing superscript or subscript argument", - "TokenNotFoundForCommand": "Could not find %1 for %2" + "TokenNotFoundForCommand": "Could not find %1 for %2", + "UnknownTag": "Unknown tags class" } diff --git a/ts/input/tex/ams/AmsItems.ts b/ts/input/tex/ams/AmsItems.ts index fde4ba8c1..c4f122a93 100644 --- a/ts/input/tex/ams/AmsItems.ts +++ b/ts/input/tex/ams/AmsItems.ts @@ -24,7 +24,7 @@ import { ArrayItem, EqnArrayItem } from '../base/BaseItems.js'; import { ParseUtil } from '../ParseUtil.js'; import NodeUtil from '../NodeUtil.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { TexConstant } from '../TexConstants.js'; import StackItemFactory from '../StackItemFactory.js'; import { MmlNode } from '../../../core/MmlTree/MmlNode.js'; @@ -79,7 +79,7 @@ export class MultlineItem extends ArrayItem { public EndRow() { if (this.row.length !== 1) { // @test MultlineRowsOneCol - throw new TexError(COMPONENT, 'MultlineRowsOneCol', 'multline'); + texError(COMPONENT, 'MultlineRowsOneCol', 'multline'); } const row = this.create('node', 'mtr', this.row); this.table.push(row); @@ -171,7 +171,7 @@ export class FlalignItem extends EqnArrayItem { const n = this.getProperty('xalignat') as number; if (!n) return; if (this.row.length > n) { - throw new TexError(COMPONENT, 'XalignOverflow', '&', this.name); + texError(COMPONENT, 'XalignOverflow', '&', this.name); } } diff --git a/ts/input/tex/ams/AmsMethods.ts b/ts/input/tex/ams/AmsMethods.ts index 5f0c66743..9b0254645 100644 --- a/ts/input/tex/ams/AmsMethods.ts +++ b/ts/input/tex/ams/AmsMethods.ts @@ -29,7 +29,7 @@ import ParseMethods from '../ParseMethods.js'; import NodeUtil from '../NodeUtil.js'; import { TexConstant } from '../TexConstants.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { ArrayItem } from '../base/BaseItems.js'; import { FlalignItem } from './AmsItems.js'; import BaseMethods from '../base/BaseMethods.js'; @@ -149,11 +149,7 @@ export const AmsMethods: { [key: string]: ParseMethod } = { const n = parser.GetArgument('\\begin{' + name + '}'); if (n.match(/[^0-9]/)) { // @test PositiveIntegerArg - throw new TexError( - COMPONENT, - 'PositiveIntegerArg', - '\\begin{' + name + '}' - ); + texError(COMPONENT, 'PositiveIntegerArg', '\\begin{' + name + '}'); } let count = parseInt(n, 10); while (count > 0) { @@ -242,7 +238,7 @@ export const AmsMethods: { [key: string]: ParseMethod } = { ): ParseResult { const n = parser.GetArgument('\\begin{' + begin.getName() + '}'); if (n.match(/[^0-9]/)) { - throw new TexError( + texError( COMPONENT, 'PositiveIntegerArg', '\\begin{' + begin.getName() + '}' @@ -621,7 +617,7 @@ export const AmsMethods: { [key: string]: ParseMethod } = { // @test Shove (Left|Right) (Top|Middle|Bottom) if (top.kind !== 'multline') { // @test Shove Error Environment - throw new TexError( + texError( COMPONENT, 'CommandOnlyAllowedInEnv', parser.currentCS, @@ -630,11 +626,7 @@ export const AmsMethods: { [key: string]: ParseMethod } = { } if (top.Size()) { // @test Shove Error (Top|Middle|Bottom) - throw new TexError( - COMPONENT, - 'CommandAtTheBeginingOfLine', - parser.currentCS - ); + texError(COMPONENT, 'CommandAtTheBeginingOfLine', parser.currentCS); } top.setProperty('shove', shove); }, @@ -668,7 +660,7 @@ export const AmsMethods: { [key: string]: ParseMethod } = { lr = lrMap[lr]; if (lr == null) { // @test Center Fraction Error - throw new TexError(COMPONENT, 'IllegalAlign', parser.currentCS); + texError(COMPONENT, 'IllegalAlign', parser.currentCS); } if (lr) { // @test Right Fraction, Left Fraction @@ -729,7 +721,7 @@ export const AmsMethods: { [key: string]: ParseMethod } = { const styleAlpha = ['D', 'T', 'S', 'SS'][styleDigit]; if (styleAlpha == null) { // @test Genfrac Error - throw new TexError(COMPONENT, 'BadMathStyleFor', parser.currentCS); + texError(COMPONENT, 'BadMathStyleFor', parser.currentCS); } frac = parser.create('node', 'mstyle', [frac]); if (styleAlpha === 'D') { @@ -758,7 +750,7 @@ export const AmsMethods: { [key: string]: ParseMethod } = { HandleTag(parser: TexParser, name: string) { if (!parser.tags.currentTag.taggable && parser.tags.env) { // @test Illegal Tag Error - throw new TexError( + texError( COMPONENT, 'CommandNotAllowedInEnv', parser.currentCS, @@ -767,7 +759,7 @@ export const AmsMethods: { [key: string]: ParseMethod } = { } if (parser.tags.currentTag.tag) { // @test Double Tag Error - throw new TexError(COMPONENT, 'MultipleCommand', parser.currentCS); + texError(COMPONENT, 'MultipleCommand', parser.currentCS); } const star = parser.GetStar(); const tagId = UnitUtil.trimSpaces(parser.GetArgument(name)); diff --git a/ts/input/tex/base/BaseConfiguration.ts b/ts/input/tex/base/BaseConfiguration.ts index b39883433..fb3ef2b68 100644 --- a/ts/input/tex/base/BaseConfiguration.ts +++ b/ts/input/tex/base/BaseConfiguration.ts @@ -24,7 +24,7 @@ import { HandlerType, ConfigurationType } from '../HandlerTypes.js'; import { Configuration } from '../Configuration.js'; import { MapHandler } from '../MapHandler.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import NodeUtil from '../NodeUtil.js'; import TexParser from '../TexParser.js'; import { CharacterMap, RegExpMap } from '../TokenMap.js'; @@ -91,7 +91,7 @@ export function Other(parser: TexParser, char: string) { */ function csUndefined(_parser: TexParser, name: string) { // @test Undefined-CS - throw new TexError(COMPONENT, 'UndefinedControlSequence', '\\' + name); + texError(COMPONENT, 'UndefinedControlSequence', '\\' + name); } /** @@ -102,7 +102,7 @@ function csUndefined(_parser: TexParser, name: string) { */ function envUndefined(_parser: TexParser, env: string) { // @test Undefined-Env - throw new TexError(COMPONENT, 'UnknownEnv', env); + texError(COMPONENT, 'UnknownEnv', env); } /** diff --git a/ts/input/tex/base/BaseItems.ts b/ts/input/tex/base/BaseItems.ts index 11a626673..133450956 100644 --- a/ts/input/tex/base/BaseItems.ts +++ b/ts/input/tex/base/BaseItems.ts @@ -29,7 +29,7 @@ import { MmlMo } from '../../../core/MmlTree/MmlNodes/mo.js'; import { MmlMsubsup } from '../../../core/MmlTree/MmlNodes/msubsup.js'; import { MmlMunderover } from '../../../core/MmlTree/MmlNodes/munderover.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { ParseUtil } from '../ParseUtil.js'; import { UnitUtil } from '../UnitUtil.js'; import NodeUtil from '../NodeUtil.js'; @@ -39,6 +39,7 @@ import { CheckType, BaseItem, StackItem, EnvList } from '../StackItem.js'; import { TRBL } from '../../../util/Styles.js'; import { TexConstant } from '../TexConstants.js'; +import { COMPONENT as TEX_COMPONENT } from '../__locales__/Component.js'; import { COMPONENT } from './__locales__/Component.js'; /** @@ -113,7 +114,7 @@ export class OpenItem extends BaseItem { */ protected static errors = Object.assign(Object.create(BaseItem.errors), { // @test ExtraOpenMissingClose - stop: 'ExtraOpenMissingClose', + stop: [TEX_COMPONENT, 'ExtraOpenMissingClose'], }); /** @@ -224,11 +225,11 @@ export class SubsupItem extends BaseItem { */ protected static errors = Object.assign(Object.create(BaseItem.errors), { // @test MissingScript Sub, MissingScript Sup - stop: 'MissingScript', + stop: [COMPONENT, 'MissingScript'], // @test MissingOpenForSup - sup: 'MissingOpenForSup', + sup: [COMPONENT, 'MissingOpenForSup'], // @test MissingOpenForSub - sub: 'MissingOpenForSub', + sub: [COMPONENT, 'MissingOpenForSub'], }); /** @@ -281,7 +282,7 @@ export class SubsupItem extends BaseItem { if (super.checkItem(item)[1]) { // @test Brace Superscript Error, MissingOpenForSup, MissingOpenForSub const error = this.getError(['', 'sub', 'sup'][position]); - throw new TexError(COMPONENT, error); + texError(...error); } return null; } @@ -319,7 +320,7 @@ export class OverItem extends BaseItem { public checkItem(item: StackItem): CheckType { if (item.isKind('over')) { // @test Double Over - throw new TexError(COMPONENT, 'AmbiguousUseOf', item.getName()); + texError(COMPONENT, 'AmbiguousUseOf', item.getName()); } if (item.isClose) { // @test Over @@ -373,7 +374,7 @@ export class LeftItem extends BaseItem { */ protected static errors = Object.assign(Object.create(BaseItem.errors), { // @test ExtraLeftMissingRight - stop: 'ExtraLeftMissingRight', + stop: [COMPONENT, 'ExtraLeftMissingRight'], }); /** @@ -586,12 +587,7 @@ export class BeginItem extends BaseItem { if (item.isKind('end')) { if (item.getName() !== this.getName()) { // @test EnvBadEnd - throw new TexError( - COMPONENT, - 'EnvBadEnd', - this.getName(), - item.getName() - ); + texError(COMPONENT, 'EnvBadEnd', this.getName(), item.getName()); } // @test Hfill const node = this.toMml(); @@ -600,7 +596,7 @@ export class BeginItem extends BaseItem { } if (item.isKind('stop')) { // @test EnvMissingEnd Array - throw new TexError(COMPONENT, 'EnvMissingEnd', this.getName()); + texError(COMPONENT, 'EnvMissingEnd', this.getName()); } return super.checkItem(item); } @@ -673,7 +669,7 @@ export class PositionItem extends BaseItem { public checkItem(item: StackItem): CheckType { if (item.isClose) { // @test MissingBoxFor - throw new TexError(COMPONENT, 'MissingBoxFor', this.getName()); + texError(COMPONENT, 'MissingBoxFor', this.getName()); } if (item.isFinal) { let mml = item.toMml(); @@ -1083,7 +1079,7 @@ export class ArrayItem extends BaseItem { return [[newItem], true]; } // @test MissingCloseBrace2 - throw new TexError(COMPONENT, 'MissingCloseBrace'); + texError(TEX_COMPONENT, 'MissingCloseBrace'); } return [[newItem, item], true]; } @@ -1225,7 +1221,7 @@ export class ArrayItem extends BaseItem { ++this.templateSubs > parser.configuration.options.maxTemplateSubtitutions ) { - throw new TexError(COMPONENT, 'MaxTemplateSubs'); + texError(COMPONENT, 'MaxTemplateSubs'); } } } @@ -1644,7 +1640,7 @@ export class EquationItem extends BaseItem { } if (item.isKind('stop')) { // @test EnvMissingEnd Equation - throw new TexError(COMPONENT, 'EnvMissingEnd', this.getName()); + texError(COMPONENT, 'EnvMissingEnd', this.getName()); } return super.checkItem(item); } diff --git a/ts/input/tex/base/BaseMethods.ts b/ts/input/tex/base/BaseMethods.ts index e8d77aa2c..3621f8f04 100644 --- a/ts/input/tex/base/BaseMethods.ts +++ b/ts/input/tex/base/BaseMethods.ts @@ -27,7 +27,7 @@ import { StackItem, EnvList } from '../StackItem.js'; import { Macro } from '../Token.js'; import { ParseResult, ParseMethod } from '../Types.js'; import NodeUtil from '../NodeUtil.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import TexParser from '../TexParser.js'; import { TexConstant } from '../TexConstants.js'; import { ParseUtil } from '../ParseUtil.js'; @@ -44,6 +44,7 @@ import { lookup } from '../../../util/Options.js'; import { ColumnState } from '../ColumnParser.js'; import { replaceUnicode } from '../../../util/string.js'; +import { COMPONENT as TEX_COMPONENT } from '../__locales__/Component.js'; import { COMPONENT } from './__locales__/Component.js'; const P_HEIGHT = 1.2 / 0.85; // cmex10 height plus depth over .85 @@ -72,12 +73,12 @@ export function splitAlignArray(align: string, n: number = Infinity): string { .map((s: string) => { const name = { t: 'top', b: 'bottom', m: 'middle', c: 'center' }[s]; if (!name) { - throw new TexError(COMPONENT, 'BadBreakAlign', s); + texError(COMPONENT, 'BadBreakAlign', s); } return name; }); if (list.length > n) { - throw new TexError(COMPONENT, 'TooManyAligns', align); + texError(COMPONENT, 'TooManyAligns', align); } return n === 1 ? list[0] : list.join(' '); } @@ -218,7 +219,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { !NodeUtil.getProperty(base, 'subsupOK')) ) { // @test Double-super-error, Double-over-error - throw new TexError(COMPONENT, 'DoubleExponent'); + texError(COMPONENT, 'DoubleExponent'); } if (!NodeUtil.isType(base, 'msubsup') || NodeUtil.isType(base, 'msup')) { if (movesupsub) { @@ -290,7 +291,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { !NodeUtil.getProperty(base, 'subsupOK')) ) { // @test Double-sub-error, Double-under-error - throw new TexError(COMPONENT, 'DoubleSubscripts'); + texError(COMPONENT, 'DoubleSubscripts'); } if (!NodeUtil.isType(base, 'msubsup') || NodeUtil.isType(base, 'msup')) { if (movesupsub) { @@ -344,7 +345,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { !NodeUtil.getProperty(base, 'subsupOK')) ) { // @test Double Prime Error - throw new TexError(COMPONENT, 'DoubleExponentPrime'); + texError(COMPONENT, 'DoubleExponentPrime'); } let sup = ''; parser.i--; @@ -382,7 +383,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { */ Hash(_parser: TexParser, _c: string) { // @test Hash Error - throw new TexError(COMPONENT, 'CantUseHash1'); + texError(COMPONENT, 'CantUseHash1'); }, /** @@ -615,7 +616,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { NodeUtil.getProperty(op, 'movesupsub') == null) ) { // @test Limits Error - throw new TexError(COMPONENT, 'MisplacedLimits', parser.currentCS); + texError(COMPONENT, 'MisplacedLimits', parser.currentCS); } const top = parser.stack.Top(); let node; @@ -738,16 +739,16 @@ const BaseMethods: { [key: string]: ParseMethod } = { // @test Tweaked Root if (!parser.stack.env['inRoot']) { // @test Misplaced Move Root - throw new TexError(COMPONENT, 'MisplacedMoveRoot', parser.currentCS); + texError(COMPONENT, 'MisplacedMoveRoot', parser.currentCS); } if (parser.stack.global[id]) { // @test Multiple Move Root - throw new TexError(COMPONENT, 'MultipleMoveRoot', parser.currentCS); + texError(COMPONENT, 'MultipleMoveRoot', parser.currentCS); } let n = parser.GetArgument(name); if (!n.match(/-?[0-9]+/)) { // @test Incorrect Move Root - throw new TexError(COMPONENT, 'IntegerArg', parser.currentCS); + texError(COMPONENT, 'IntegerArg', parser.currentCS); } n = parseInt(n, 10) / 15 + 'em'; if (n.substring(0, 1) !== '-') { @@ -983,42 +984,30 @@ const BaseMethods: { [key: string]: ParseMethod } = { BreakAlign(parser: TexParser, name: string) { const top = parser.stack.Top() as sitem.ArrayItem; if (!(top instanceof sitem.ArrayItem)) { - throw new TexError(COMPONENT, 'BreakNotInArray', parser.currentCS); + texError(COMPONENT, 'BreakNotInArray', parser.currentCS); } const type = parser.GetArgument(name).trim(); switch (type) { case 'c': if (top.First) { - throw new TexError( - COMPONENT, - 'BreakFirstInEntry', - parser.currentCS + '{c}' - ); + texError(COMPONENT, 'BreakFirstInEntry', parser.currentCS + '{c}'); } top.breakAlign.cell = splitAlignArray(parser.GetArgument(name), 1); break; case 'r': if (top.row.length || top.First) { - throw new TexError( - COMPONENT, - 'BreakFirstInRow', - parser.currentCS + '{r}' - ); + texError(COMPONENT, 'BreakFirstInRow', parser.currentCS + '{r}'); } top.breakAlign.row = splitAlignArray(parser.GetArgument(name)); break; case 't': if (top.table.length || top.row.length || top.First) { - throw new TexError( - COMPONENT, - 'BreakFirstInTable', - parser.currentCS + '{t}' - ); + texError(COMPONENT, 'BreakFirstInTable', parser.currentCS + '{t}'); } top.breakAlign.table = splitAlignArray(parser.GetArgument(name)); break; default: - throw new TexError(COMPONENT, 'BreakType', parser.currentCS); + texError(COMPONENT, 'BreakType', parser.currentCS); } }, @@ -1043,7 +1032,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { } if (!node || !node.isToken) { // @test Token Illegal Type, Token Wrong Type - throw new TexError(COMPONENT, 'NotMathMLToken', kind); + texError(COMPONENT, 'NotMathMLToken', kind); } while (attr !== '') { const match = attr.match( @@ -1051,15 +1040,11 @@ const BaseMethods: { [key: string]: ParseMethod } = { ); if (!match) { // @test Token Invalid Attribute - throw new TexError( - COMPONENT, - 'InvalidMathMLAttr', - attr.split(/[\s\n=]/)[0] - ); + texError(COMPONENT, 'InvalidMathMLAttr', attr.split(/[\s\n=]/)[0]); } if (!node.attributes.hasDefault(match[1]) && !MmlTokenAllow[match[1]]) { // @test Token Unknown Attribute, Token Wrong Attribute - throw new TexError(COMPONENT, 'UnknownAttrForElement', match[1], kind); + texError(COMPONENT, 'UnknownAttrForElement', match[1], kind); } let value: string | boolean = ParseUtil.mmlFilterAttribute( parser, @@ -1512,7 +1497,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { const c = parser.GetNext(); if (c === '') { // @test Matrix Error - throw new TexError(COMPONENT, 'MissingArgFor', parser.currentCS); + texError(TEX_COMPONENT, 'MissingArgFor', parser.currentCS); } if (c === '{') { // @test Matrix Braces, Matrix Columns, Matrix Rows. @@ -1622,7 +1607,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { // Extra alignment tabs are not allowed in cases // // @test ExtraAlignTab - throw new TexError(COMPONENT, 'ExtraAlignTab'); + texError(COMPONENT, 'ExtraAlignTab'); } else if (c === '\\') { // // If the macro is \cr or \\, end the search, otherwise skip the macro @@ -1702,7 +1687,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { // @test Custom Linebreak if (dim && !value) { // @test Dimension Error - throw new TexError(COMPONENT, 'BracketMustBeDimension', name); + texError(COMPONENT, 'BracketMustBeDimension', name); } n = value + unit; } @@ -1746,7 +1731,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { const top = parser.stack.Top(); if (!(top instanceof sitem.ArrayItem) || top.Size()) { // @test Misplaced hline - throw new TexError(COMPONENT, 'Misplaced', parser.currentCS); + texError(TEX_COMPONENT, 'Misplaced', parser.currentCS); } if (!top.table.length) { // @test Enclosed top, Enclosed top bottom @@ -1777,7 +1762,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { top.hfill.push(top.Size()); } else { // @test UnsupportedHFill - throw new TexError(COMPONENT, 'UnsupportedHFill', parser.currentCS); + texError(COMPONENT, 'UnsupportedHFill', parser.currentCS); } }, @@ -1792,10 +1777,10 @@ const BaseMethods: { [key: string]: ParseMethod } = { const n = parser.GetBrackets(name, '0'); const macro = parser.GetArgument(name); if (c.length !== 1) { - throw new TexError(COMPONENT, 'BadColumnName', c); + texError(COMPONENT, 'BadColumnName', c); } if (!n.match(/^\d+$/)) { - throw new TexError(COMPONENT, 'PositiveIntegerArg', n); + texError(COMPONENT, 'PositiveIntegerArg', n); } const cparser = parser.configuration.columnParser; cparser.columnHandler[c] = (state: ColumnState) => @@ -1818,7 +1803,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { const env = parser.GetArgument(name); if (env.match(/\\/)) { // @test InvalidEnv - throw new TexError(COMPONENT, 'InvalidEnv', env); + texError(COMPONENT, 'InvalidEnv', env); } const macro = parser.configuration.handlers .get(HandlerType.ENVIRONMENT) @@ -1955,14 +1940,14 @@ const BaseMethods: { [key: string]: ParseMethod } = { (shift && !UnitUtil.matchDimen(shift)[0]) || (last && !UnitUtil.matchDimen(last)[0]) ) { - throw new TexError(COMPONENT, 'BracketMustBeDimension', name); + texError(COMPONENT, 'BracketMustBeDimension', name); } // // Get the indentalign values, if any // const lcr = parser.GetArgument(name); if (lcr && !lcr.match(/^([lcr]{1,3})?$/)) { - throw new TexError(COMPONENT, 'BadAlignment'); + texError(COMPONENT, 'BadAlignment'); } const align = [...lcr].map( (c) => ({ l: 'left', c: 'center', r: 'right' })[c] @@ -2104,7 +2089,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { // @test Label, Ref, Ref Unknown if (parser.tags.label) { // @test Double Label Error - throw new TexError(COMPONENT, 'MultipleCommand', parser.currentCS); + texError(COMPONENT, 'MultipleCommand', parser.currentCS); } parser.tags.label = label; if ( @@ -2112,7 +2097,7 @@ const BaseMethods: { [key: string]: ParseMethod } = { !parser.options['ignoreDuplicateLabels'] ) { // @ Duplicate Label Error - throw new TexError(COMPONENT, 'MultipleLabel', label); + texError(COMPONENT, 'MultipleLabel', label); } // TODO: This should be set in the tags structure! parser.tags.labels[label] = new Label(); // will be replaced by tag value later diff --git a/ts/input/tex/base/__locales__/de.json b/ts/input/tex/base/__locales__/de.json index ae939b480..c5d53b47a 100644 --- a/ts/input/tex/base/__locales__/de.json +++ b/ts/input/tex/base/__locales__/de.json @@ -16,6 +16,8 @@ "EnvBadEnd": "\\begin{%1} endete mit \\end{%2}", "EnvMissingEnd": "Fehlendes \\end{%1}", "ExtraAlignTab": "Zusätzlicher Ausrichtungs-Tabulator im \\cases-Text", + "ExtraLeftMissingRight": "Überflüssiges \\left oder fehlendes \\right", + "ExtraOpenMissingClose": "Zusätzliche öffnende Klammer oder fehlende schließende Klammer", "IntegerArg": "Das Argument für %1 muss eine ganze Zahl sein", "InvalidEnv": "Ungültiger Umgebungsname '%1'", "InvalidMathMLAttr": "Ungültiges MathML-Attribut: %1", @@ -25,6 +27,7 @@ "MissingBoxFor": "Fehlende Box für %1", "MissingOpenForSub": "Fehlende öffnende Klammer für Tiefstellung", "MissingOpenForSup": "Fehlende öffnende Klammer für Hochstellung", + "MissingScript": "Fehlendes Argument für Hoch- oder Tiefstellung", "MultipleCommand": "Mehrere %1", "MultipleLabel": "Bezeichnung '%1' mehrfach definiert", "MultipleMoveRoot": "Mehrfache Verwendung von %1", diff --git a/ts/input/tex/base/__locales__/en.json b/ts/input/tex/base/__locales__/en.json index 79028ff29..6b5f3b71e 100644 --- a/ts/input/tex/base/__locales__/en.json +++ b/ts/input/tex/base/__locales__/en.json @@ -16,6 +16,8 @@ "EnvBadEnd": "\\begin{%1} ended with \\end{%2}", "EnvMissingEnd": "Missing \\end{%1}", "ExtraAlignTab": "Extra alignment tab in \\cases text", + "ExtraLeftMissingRight": "Extra \\left or missing \\right", + "ExtraOpenMissingClose": "Extra open brace or missing close brace", "IntegerArg": "The argument to %1 must be an integer", "InvalidEnv": "Invalid environment name '%1'", "InvalidMathMLAttr": "Invalid MathML attribute: %1", @@ -25,6 +27,7 @@ "MissingBoxFor": "Missing box for %1", "MissingOpenForSub": "Missing open brace for subscript", "MissingOpenForSup": "Missing open brace for superscript", + "MissingScript": "Missing superscript or subscript argument", "MultipleCommand": "Multiple %1", "MultipleLabel": "Label '%1' multiply defined", "MultipleMoveRoot": "Multiple use of %1", diff --git a/ts/input/tex/bbox/BboxConfiguration.ts b/ts/input/tex/bbox/BboxConfiguration.ts index a4966f242..7700752e6 100644 --- a/ts/input/tex/bbox/BboxConfiguration.ts +++ b/ts/input/tex/bbox/BboxConfiguration.ts @@ -26,7 +26,7 @@ import { Configuration } from '../Configuration.js'; import TexParser from '../TexParser.js'; import { CommandMap } from '../TokenMap.js'; import { ParseMethod } from '../Types.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { COMPONENT } from './__locales__/Component.js'; export { COMPONENT }; @@ -52,12 +52,7 @@ const BboxMethods: { [key: string]: ParseMethod } = { // @test Bbox-Padding if (def) { // @test Bbox-Padding-Error - throw new TexError( - COMPONENT, - 'MultipleBBoxProperty', - 'Padding', - name - ); + texError(COMPONENT, 'MultipleBBoxProperty', 'Padding', name); } const pad = BBoxPadding(match[1] + match[3]); if (pad) { @@ -73,24 +68,19 @@ const BboxMethods: { [key: string]: ParseMethod } = { // @test Bbox-Background if (background) { // @test Bbox-Background-Error - throw new TexError( - COMPONENT, - 'MultipleBBoxProperty', - 'Background', - name - ); + texError(COMPONENT, 'MultipleBBoxProperty', 'Background', name); } background = part; } else if (part.match(/^[-a-z]+:/i)) { // @test Bbox-Frame if (style) { // @test Bbox-Frame-Error - throw new TexError(COMPONENT, 'MultipleBBoxProperty', 'Style', name); + texError(COMPONENT, 'MultipleBBoxProperty', 'Style', name); } style = BBoxStyle(part); } else if (part !== '') { // @test Bbox-General-Error - throw new TexError(COMPONENT, 'InvalidBBoxProperty', part); + texError(COMPONENT, 'InvalidBBoxProperty', part); } } if (def) { diff --git a/ts/input/tex/begingroup/BegingroupMethods.ts b/ts/input/tex/begingroup/BegingroupMethods.ts index 83e7366e5..e0b050a4e 100644 --- a/ts/input/tex/begingroup/BegingroupMethods.ts +++ b/ts/input/tex/begingroup/BegingroupMethods.ts @@ -23,7 +23,7 @@ import { CommandMap } from '../TokenMap.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { COMPONENT } from './__locales__/Component.js'; import BaseMethods from '../base/BaseMethods.js'; @@ -85,7 +85,7 @@ export const BegingroupMethods = { // Check that \global can be used with the following CS // if (!parser.options.begingroup.allowGlobal.includes(cs)) { - throw new TexError(COMPONENT, 'IllegalGlobal', parser.currentCS); + texError(COMPONENT, 'IllegalGlobal', parser.currentCS); } parser.stack.env.isGlobal = true; }, diff --git a/ts/input/tex/begingroup/BegingroupStack.ts b/ts/input/tex/begingroup/BegingroupStack.ts index d338b1ac4..1443da966 100644 --- a/ts/input/tex/begingroup/BegingroupStack.ts +++ b/ts/input/tex/begingroup/BegingroupStack.ts @@ -31,7 +31,7 @@ import { } from '../TokenMap.js'; import { Token } from '../Token.js'; import { MapHandler, SubHandlers } from '../MapHandler.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { COMPONENT } from './__locales__/Component.js'; import { @@ -172,7 +172,7 @@ export class BegingroupStack { */ public pop() { if (this.i === this.base) { - throw new TexError(COMPONENT, 'MissingBegingroup'); + texError(COMPONENT, 'MissingBegingroup'); } this.handlers.remove(BegingroupStack.handlerConfig, {}); // diff --git a/ts/input/tex/braket/BraketConfiguration.ts b/ts/input/tex/braket/BraketConfiguration.ts index 3e2d755e2..344e88e52 100644 --- a/ts/input/tex/braket/BraketConfiguration.ts +++ b/ts/input/tex/braket/BraketConfiguration.ts @@ -25,7 +25,6 @@ import { HandlerType, ConfigurationType } from '../HandlerTypes.js'; import { Configuration } from '../Configuration.js'; import { BraketItem } from './BraketItems.js'; import './BraketMappings.js'; -export { COMPONENT } from './__locales__/Component.js'; export const BraketConfiguration = Configuration.create('braket', { [ConfigurationType.HANDLER]: { diff --git a/ts/input/tex/bussproofs/BussproofsItems.ts b/ts/input/tex/bussproofs/BussproofsItems.ts index ca52d5b3b..29b465475 100644 --- a/ts/input/tex/bussproofs/BussproofsItems.ts +++ b/ts/input/tex/bussproofs/BussproofsItems.ts @@ -21,7 +21,7 @@ * @author v.sorge@mathjax.org (Volker Sorge) */ -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { BaseItem, CheckType, StackItem } from '../StackItem.js'; import { MmlNode } from '../../../core/MmlTree/MmlNode.js'; import Stack from '../Stack.js'; @@ -63,7 +63,7 @@ export class ProofTreeItem extends BaseItem { return [[this.factory.create('mml', node), item], true]; } if (item.isKind('stop')) { - throw new TexError(COMPONENT, 'EnvMissingEnd', this.getName()); + texError(COMPONENT, 'EnvMissingEnd', this.getName()); } this.innerStack.Push(item); return BaseItem.fail; diff --git a/ts/input/tex/bussproofs/BussproofsMethods.ts b/ts/input/tex/bussproofs/BussproofsMethods.ts index ccd6d3577..f67176707 100644 --- a/ts/input/tex/bussproofs/BussproofsMethods.ts +++ b/ts/input/tex/bussproofs/BussproofsMethods.ts @@ -22,7 +22,7 @@ */ import { ParseMethod } from '../Types.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import TexParser from '../TexParser.js'; import { ParseUtil } from '../ParseUtil.js'; import { UnitUtil } from '../UnitUtil.js'; @@ -138,12 +138,12 @@ function createRule( function parseFCenterLine(parser: TexParser, name: string): MmlNode { const dollar = parser.GetNext(); if (dollar !== '$') { - throw new TexError(COMPONENT, 'IllegalUseOfCommand', name); + texError(COMPONENT, 'IllegalUseOfCommand', name); } parser.i++; const axiom = parser.GetUpTo(name, '$'); if (!axiom.includes('\\fCenter')) { - throw new TexError(COMPONENT, 'MissingProofCommand', '\\fCenter', name); + texError(COMPONENT, 'MissingProofCommand', '\\fCenter', name); } // Check for fCenter and throw error? const [prem, conc] = axiom.split('\\fCenter'); @@ -209,7 +209,7 @@ const BussproofsMethods: { [key: string]: ParseMethod } = { const top = parser.stack.Top(); // TODO: Label error if (top.kind !== 'proofTree') { - throw new TexError(COMPONENT, 'IllegalProofCommand'); + texError(COMPONENT, 'IllegalProofCommand'); } const content = paddedContent(parser, parser.GetArgument(name)); BussproofsUtil.setProperty(content, 'axiom', true); @@ -226,10 +226,10 @@ const BussproofsMethods: { [key: string]: ParseMethod } = { Inference(parser: TexParser, name: string, n: number) { const top = parser.stack.Top(); if (top.kind !== 'proofTree') { - throw new TexError(COMPONENT, 'IllegalProofCommand'); + texError(COMPONENT, 'IllegalProofCommand'); } if (top.Size() < n) { - throw new TexError(COMPONENT, 'BadProofTree'); + texError(COMPONENT, 'BadProofTree'); } const rootAtTop = top.getProperty('rootAtTop') as boolean; const childCount = n === 1 && !top.Peek()[0].childNodes.length ? 0 : n; @@ -281,7 +281,7 @@ const BussproofsMethods: { [key: string]: ParseMethod } = { const top = parser.stack.Top(); // Label error if (top.kind !== 'proofTree') { - throw new TexError(COMPONENT, 'IllegalProofCommand'); + texError(COMPONENT, 'IllegalProofCommand'); } const content = ParseUtil.internalMath(parser, parser.GetArgument(name), 0); const label = @@ -303,7 +303,7 @@ const BussproofsMethods: { [key: string]: ParseMethod } = { const top = parser.stack.Top(); // Label error if (top.kind !== 'proofTree') { - throw new TexError(COMPONENT, 'IllegalProofCommand'); + texError(COMPONENT, 'IllegalProofCommand'); } top.setProperty('currentLine', style); if (always) { @@ -321,7 +321,7 @@ const BussproofsMethods: { [key: string]: ParseMethod } = { RootAtTop(parser: TexParser, _name: string, where: boolean) { const top = parser.stack.Top(); if (top.kind !== 'proofTree') { - throw new TexError(COMPONENT, 'IllegalProofCommand'); + texError(COMPONENT, 'IllegalProofCommand'); } top.setProperty('rootAtTop', where); }, @@ -335,7 +335,7 @@ const BussproofsMethods: { [key: string]: ParseMethod } = { AxiomF(parser: TexParser, name: string) { const top = parser.stack.Top(); if (top.kind !== 'proofTree') { - throw new TexError(COMPONENT, 'IllegalProofCommand'); + texError(COMPONENT, 'IllegalProofCommand'); } const line = parseFCenterLine(parser, name); BussproofsUtil.setProperty(line, 'axiom', true); @@ -360,10 +360,10 @@ const BussproofsMethods: { [key: string]: ParseMethod } = { InferenceF(parser: TexParser, name: string, n: number) { const top = parser.stack.Top(); if (top.kind !== 'proofTree') { - throw new TexError(COMPONENT, 'IllegalProofCommand'); + texError(COMPONENT, 'IllegalProofCommand'); } if (top.Size() < n) { - throw new TexError(COMPONENT, 'BadProofTree'); + texError(COMPONENT, 'BadProofTree'); } const rootAtTop = top.getProperty('rootAtTop') as boolean; const childCount = n === 1 && !top.Peek()[0].childNodes.length ? 0 : n; diff --git a/ts/input/tex/cases/CasesConfiguration.ts b/ts/input/tex/cases/CasesConfiguration.ts index e93ae1ce4..802e636d8 100644 --- a/ts/input/tex/cases/CasesConfiguration.ts +++ b/ts/input/tex/cases/CasesConfiguration.ts @@ -5,7 +5,7 @@ import { ParseResult, ParseMethod } from '../Types.js'; import { ParseUtil } from '../ParseUtil.js'; import BaseMethods from '../base/BaseMethods.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { BeginItem, EqnArrayItem } from '../base/BaseItems.js'; import { AmsTags } from '../ams/AmsConfiguration.js'; import { StackItem, CheckType } from '../StackItem.js'; @@ -183,7 +183,7 @@ export const CasesMethods = { // // Extra alignment tabs are not allowed in cases // - throw new TexError(COMPONENT, 'ExtraCasesAlignTab'); + texError(COMPONENT, 'ExtraCasesAlignTab'); } else if (c === '\\' && braces === 0) { // // If the macro is \cr or \\, end the search, otherwise skip the macro diff --git a/ts/input/tex/color/ColorUtil.ts b/ts/input/tex/color/ColorUtil.ts index 3f0d9261e..97f5e0615 100644 --- a/ts/input/tex/color/ColorUtil.ts +++ b/ts/input/tex/color/ColorUtil.ts @@ -21,7 +21,7 @@ * @author i@omardo.com (Omar Al-Ithawi) */ -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { COLORS } from './ColorConstants.js'; import { COMPONENT } from './__locales__/Component.js'; @@ -51,7 +51,7 @@ export class ColorModel { private normalizeColor(model: string, def: string): string { if (!model || model === 'named') { if (def.match(/;/)) { - throw new TexError(COMPONENT, 'BadColorValue'); + texError(COMPONENT, 'BadColorValue'); } // Allow to define colors directly by using the CSS format e.g. `#888` return def; @@ -61,7 +61,7 @@ export class ColorModel { return modelProcessor(def); } - throw new TexError(COMPONENT, 'UndefinedColorModel', model); + texError(COMPONENT, 'UndefinedColorModel', model); } /** @@ -99,7 +99,7 @@ export class ColorModel { return COLORS.get(name); } if (name.match(/;/)) { - throw new TexError(COMPONENT, 'BadColorValue', 'Invalid color value'); + texError(COMPONENT, 'BadColorValue', 'Invalid color value'); } // Pass the color name as-is to CSS return name; @@ -131,17 +131,17 @@ ColorModelProcessors.set('rgb', function (rgb: string): string { let RGB: string = '#'; if (rgbParts.length !== 3) { - throw new TexError(COMPONENT, 'ModelArg1', 'rgb'); + texError(COMPONENT, 'ModelArg1', 'rgb'); } for (const rgbPart of rgbParts) { if (!rgbPart.match(/^(\d+(\.\d*)?|\.\d+)$/)) { - throw new TexError(COMPONENT, 'InvalidDecimalNumber'); + texError(COMPONENT, 'InvalidDecimalNumber'); } const n = parseFloat(rgbPart); if (n < 0 || n > 1) { - throw new TexError(COMPONENT, 'ModelArg2', 'rgb', '0', '1'); + texError(COMPONENT, 'ModelArg2', 'rgb', '0', '1'); } let pn = Math.floor(n * 255).toString(16); @@ -166,17 +166,17 @@ ColorModelProcessors.set('RGB', function (rgb: string): string { let RGB = '#'; if (rgbParts.length !== 3) { - throw new TexError(COMPONENT, 'ModelArg1', 'RGB'); + texError(COMPONENT, 'ModelArg1', 'RGB'); } for (const rgbPart of rgbParts) { if (!rgbPart.match(/^\d+$/)) { - throw new TexError(COMPONENT, 'InvalidNumber'); + texError(COMPONENT, 'InvalidNumber'); } const n = parseInt(rgbPart); if (n > 255) { - throw new TexError(COMPONENT, 'ModelArg2', 'RGB', '0', '255'); + texError(COMPONENT, 'ModelArg2', 'RGB', '0', '255'); } let pn = n.toString(16); @@ -196,12 +196,12 @@ ColorModelProcessors.set('RGB', function (rgb: string): string { */ ColorModelProcessors.set('gray', function (gray: string): string { if (!gray.match(/^\s*(\d+(\.\d*)?|\.\d+)\s*$/)) { - throw new TexError(COMPONENT, 'InvalidDecimalNumber'); + texError(COMPONENT, 'InvalidDecimalNumber'); } const n: number = parseFloat(gray); if (n < 0 || n > 1) { - throw new TexError(COMPONENT, 'ModelArg2', 'gray', '0', '1'); + texError(COMPONENT, 'ModelArg2', 'gray', '0', '1'); } let pn = Math.floor(n * 255).toString(16); if (pn.length < 2) { diff --git a/ts/input/tex/colortbl/ColortblConfiguration.ts b/ts/input/tex/colortbl/ColortblConfiguration.ts index c753d7432..02143cc4c 100644 --- a/ts/input/tex/colortbl/ColortblConfiguration.ts +++ b/ts/input/tex/colortbl/ColortblConfiguration.ts @@ -30,7 +30,7 @@ import { } from '../Configuration.js'; import { CommandMap } from '../TokenMap.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { TeX } from '../../tex.js'; import { COMPONENT } from './__locales__/Component.js'; @@ -132,14 +132,14 @@ function TableColor(parser: TexParser, name: string, type: keyof ColorData) { // const top = parser.stack.Top() as ColorArrayItem; if (!(top instanceof ColorArrayItem)) { - throw new TexError(COMPONENT, 'UnsupportedTableColor', parser.currentCS); + texError(COMPONENT, 'UnsupportedTableColor', parser.currentCS); } // // Check the position of the macro and save the color. // if (type === 'col') { if (top.table.length && top.color.col[top.row.length] !== color) { - throw new TexError(COMPONENT, 'ColumnColorNotTop', name); + texError(COMPONENT, 'ColumnColorNotTop', name); } top.color.col[top.row.length] = color; // @@ -151,7 +151,7 @@ function TableColor(parser: TexParser, name: string, type: keyof ColorData) { } else { top.color[type] = color; if (type === 'row' && (top.Size() || top.row.length)) { - throw new TexError(COMPONENT, 'RowColorNotFirst', name); + texError(COMPONENT, 'RowColorNotFirst', name); } } } diff --git a/ts/input/tex/empheq/EmpheqConfiguration.ts b/ts/input/tex/empheq/EmpheqConfiguration.ts index 7c872bb07..613fe36c5 100644 --- a/ts/input/tex/empheq/EmpheqConfiguration.ts +++ b/ts/input/tex/empheq/EmpheqConfiguration.ts @@ -26,7 +26,7 @@ import { Configuration } from '../Configuration.js'; import { CommandMap, EnvironmentMap } from '../TokenMap.js'; import { ParseUtil } from '../ParseUtil.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { BeginItem } from '../base/BaseItems.js'; import { EmpheqUtil } from './EmpheqUtil.js'; import ParseMethods from '../ParseMethods.js'; @@ -64,7 +64,7 @@ export const EmpheqMethods = { .GetArgument('\\begin{' + begin.getName() + '}') .split(/=/); if (!EmpheqUtil.checkEnv(env)) { - throw new TexError(COMPONENT, 'EmpheqInvalidEnv', env, begin.getName()); + texError(COMPONENT, 'EmpheqInvalidEnv', env, begin.getName()); } begin.setProperty('nestStart', true); if (opts) { diff --git a/ts/input/tex/extpfeil/ExtpfeilConfiguration.ts b/ts/input/tex/extpfeil/ExtpfeilConfiguration.ts index dbf0f6426..b1d5b0f40 100644 --- a/ts/input/tex/extpfeil/ExtpfeilConfiguration.ts +++ b/ts/input/tex/extpfeil/ExtpfeilConfiguration.ts @@ -30,7 +30,7 @@ import { ParseMethod } from '../Types.js'; import { AmsMethods } from '../ams/AmsMethods.js'; import { NewcommandUtil } from '../newcommand/NewcommandUtil.js'; import { NewcommandConfig } from '../newcommand/NewcommandConfiguration.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { COMPONENT } from './__locales__/Component.js'; export { COMPONENT }; @@ -47,13 +47,13 @@ const ExtpfeilMethods: { [key: string]: ParseMethod } = { const space = parser.GetArgument(name); const chr = parser.GetArgument(name); if (!cs.match(/^\\([a-z]+|.)$/i)) { - throw new TexError(COMPONENT, 'NewextarrowArg1', name); + texError(COMPONENT, 'NewextarrowArg1', name); } if (!space.match(/^(\d+),(\d+)$/)) { - throw new TexError(COMPONENT, 'NewextarrowArg2', name); + texError(COMPONENT, 'NewextarrowArg2', name); } if (!chr.match(/^(\d+|0x[0-9A-F]+)$/i)) { - throw new TexError(COMPONENT, 'NewextarrowArg3', name); + texError(COMPONENT, 'NewextarrowArg3', name); } cs = cs.substring(1); const spaces = space.split(','); diff --git a/ts/input/tex/html/HtmlMethods.ts b/ts/input/tex/html/HtmlMethods.ts index c27a56106..10c9b38e6 100644 --- a/ts/input/tex/html/HtmlMethods.ts +++ b/ts/input/tex/html/HtmlMethods.ts @@ -26,7 +26,7 @@ import { ParseMethod } from '../Types.js'; import NodeUtil from '../NodeUtil.js'; import { ParseUtil } from '../ParseUtil.js'; import { MmlNode } from '../../../core/MmlTree/MmlNode.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { COMPONENT } from './__locales__/Component.js'; @@ -65,7 +65,7 @@ const HtmlMethods: { [key: string]: ParseMethod } = { for (const key in data) { // remove illegal attribute names if (!isLegalAttributeName(key)) { - throw new TexError(COMPONENT, 'InvalidHTMLAttr', `data-${key}`); + texError(COMPONENT, 'InvalidHTMLAttr', `data-${key}`); } NodeUtil.setAttribute(arg, `data-${key}`, data[key]); } diff --git a/ts/input/tex/mathtools/MathtoolsMethods.ts b/ts/input/tex/mathtools/MathtoolsMethods.ts index c725073ad..7045bcee8 100644 --- a/ts/input/tex/mathtools/MathtoolsMethods.ts +++ b/ts/input/tex/mathtools/MathtoolsMethods.ts @@ -29,7 +29,7 @@ import { ParseMethod, ParseResult } from '../Types.js'; import { AmsMethods } from '../ams/AmsMethods.js'; import BaseMethods from '../base/BaseMethods.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import NodeUtil from '../NodeUtil.js'; import { TEXCLASS } from '../../../core/MmlTree/MmlNode.js'; import { length2em, em } from '../../../util/lengths.js'; @@ -137,7 +137,7 @@ export const MathtoolsMethods: { [key: string]: ParseMethod } = { width = arg; } if (width && !UnitUtil.matchDimen(width)[0]) { - throw new TexError(COMPONENT, 'BadWidth', name); + texError(COMPONENT, 'BadWidth', name); } } parser.Push(begin); @@ -165,10 +165,10 @@ export const MathtoolsMethods: { [key: string]: ParseMethod } = { HandleShove(parser: TexParser, name: string, shove: string) { const top = parser.stack.Top(); if (top.kind !== 'multline' && top.kind !== 'multlined') { - throw new TexError(COMPONENT, 'CommandInMultlined', name); + texError(COMPONENT, 'CommandInMultlined', name); } if (top.Size()) { - throw new TexError(COMPONENT, 'CommandAtTheBeginingOfLine', name); + texError(COMPONENT, 'CommandAtTheBeginingOfLine', name); } top.setProperty('shove', shove); const shift = parser.GetBrackets(name); @@ -458,7 +458,7 @@ export const MathtoolsMethods: { [key: string]: ParseMethod } = { const box = NewcommandUtil.GetCSname(parser, name + '\\' + cs); const handlers = parser.configuration.handlers; if (handlers.get(HandlerType.MACRO).lookup(cs)) { - throw new TexError(COMPONENT, 'AlreadyDefined', '\\' + cs); + texError(COMPONENT, 'AlreadyDefined', '\\' + cs); } const handler = handlers.retrieve( NewcommandTables.NEW_COMMAND @@ -476,7 +476,7 @@ export const MathtoolsMethods: { [key: string]: ParseMethod } = { ArrowBetweenLines(parser: TexParser, name: string) { const top = MathtoolsUtil.checkAlignment(parser, name); if (top.Size() || top.row.length) { - throw new TexError(COMPONENT, 'BetweenLines', name); + texError(COMPONENT, 'BetweenLines', name); } const star = parser.GetStar(); const symbol = parser.GetBrackets(name, '\\Updownarrow'); @@ -926,17 +926,17 @@ export const MathtoolsMethods: { [key: string]: ParseMethod } = { NewTagForm(parser: TexParser, name: string, renew: boolean = false) { const tags = parser.tags as MathtoolsTags; if (!('mtFormats' in tags)) { - throw new TexError(COMPONENT, 'TagsNotMT', name); + texError(COMPONENT, 'TagsNotMT', name); } const id = parser.GetArgument(name).trim(); if (!id) { - throw new TexError(COMPONENT, 'InvalidTagFormID'); + texError(COMPONENT, 'InvalidTagFormID'); } const format = parser.GetBrackets(name, ''); const left = parser.GetArgument(name); const right = parser.GetArgument(name); if (!renew && tags.mtFormats.has(id)) { - throw new TexError(COMPONENT, 'DuplicateTagForm', id); + texError(COMPONENT, 'DuplicateTagForm', id); } tags.mtFormats.set(id, [left, right, format]); parser.Push(parser.itemFactory.create('null')); @@ -951,7 +951,7 @@ export const MathtoolsMethods: { [key: string]: ParseMethod } = { UseTagForm(parser: TexParser, name: string) { const tags = parser.tags as MathtoolsTags; if (!('mtFormats' in tags)) { - throw new TexError(COMPONENT, 'TagsNotMT', name); + texError(COMPONENT, 'TagsNotMT', name); } const id = parser.GetArgument(name).trim(); if (!id) { @@ -960,7 +960,7 @@ export const MathtoolsMethods: { [key: string]: ParseMethod } = { return; } if (!tags.mtFormats.has(id)) { - throw new TexError(COMPONENT, 'UndefinedTagForm', id); + texError(COMPONENT, 'UndefinedTagForm', id); } tags.mtCurrent = tags.mtFormats.get(id); parser.Push(parser.itemFactory.create('null')); @@ -975,7 +975,7 @@ export const MathtoolsMethods: { [key: string]: ParseMethod } = { SetOptions(parser: TexParser, name: string) { const options = parser.options.mathtools; if (!options['allow-mathtoolsset']) { - throw new TexError(COMPONENT, 'ForbiddenMathtoolsSet', name); + texError(COMPONENT, 'ForbiddenMathtoolsSet', name); } const allowed = {} as { [id: string]: number }; Object.keys(options).forEach((id) => { diff --git a/ts/input/tex/mathtools/MathtoolsTags.ts b/ts/input/tex/mathtools/MathtoolsTags.ts index 22c8ec693..13c18a317 100644 --- a/ts/input/tex/mathtools/MathtoolsTags.ts +++ b/ts/input/tex/mathtools/MathtoolsTags.ts @@ -20,7 +20,7 @@ * @author dpvc@mathjax.org (Davide P. Cervone) */ -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { ParserConfiguration } from '../Configuration.js'; import { TeX } from '../../tex.js'; import { AbstractTags, TagsFactory } from '../Tags.js'; @@ -90,7 +90,7 @@ export function MathtoolsTagFormat( const forms = jax.parseOptions.options.mathtools.tagforms; for (const form of Object.keys(forms)) { if (!Array.isArray(forms[form]) || forms[form].length !== 3) { - throw new TexError(COMPONENT, 'InvalidTagFormDef', form); + texError(COMPONENT, 'InvalidTagFormDef', form); } this.mtFormats.set(form, forms[form] as [string, string, string]); } diff --git a/ts/input/tex/mathtools/MathtoolsUtil.ts b/ts/input/tex/mathtools/MathtoolsUtil.ts index 1d724e9e3..99ac61db7 100644 --- a/ts/input/tex/mathtools/MathtoolsUtil.ts +++ b/ts/input/tex/mathtools/MathtoolsUtil.ts @@ -23,7 +23,7 @@ import { EqnArrayItem } from '../base/BaseItems.js'; import { UnitUtil } from '../UnitUtil.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { lookup } from '../../../util/Options.js'; import { MmlNode } from '../../../core/MmlTree/MmlNode.js'; import { HandlerType } from '../HandlerTypes.js'; @@ -71,7 +71,7 @@ export const MathtoolsUtil = { checkAlignment(parser: TexParser, name: string): EqnArrayItem { const top = parser.stack.Top() as EqnArrayItem; if (top.kind !== EqnArrayItem.prototype.kind) { - throw new TexError(COMPONENT, 'NotInAlignment', name); + texError(COMPONENT, 'NotInAlignment', name); } return top; }, @@ -88,7 +88,7 @@ export const MathtoolsUtil = { */ addPairedDelims(parser: TexParser, cs: string, args: string[]) { if (parser.configuration.handlers.get(HandlerType.MACRO).contains(cs)) { - throw new TexError(COMPONENT, 'CommadExists', `\\${cs}`); + texError(COMPONENT, 'CommadExists', `\\${cs}`); } NewcommandUtil.addMacro( parser, @@ -125,7 +125,7 @@ export const MathtoolsUtil = { plusOrMinus(name: string, n: string): string { n = n.trim(); if (!n.match(/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)$/)) { - throw new TexError(COMPONENT, 'NotANumber', name); + texError(COMPONENT, 'NotANumber', name); } return n.match(/^[-+]/) ? n : '+' + n; }, diff --git a/ts/input/tex/mhchem/MhchemConfiguration.ts b/ts/input/tex/mhchem/MhchemConfiguration.ts index 4923008a1..3b610ad74 100644 --- a/ts/input/tex/mhchem/MhchemConfiguration.ts +++ b/ts/input/tex/mhchem/MhchemConfiguration.ts @@ -26,7 +26,7 @@ import { Configuration } from '../Configuration.js'; import { CommandMap, CharacterMap } from '../TokenMap.js'; import { Token } from '../Token.js'; import { ParseMethod } from '../Types.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import TexParser from '../TexParser.js'; import BaseMethods from '../base/BaseMethods.js'; import { AmsMethods } from '../ams/AmsMethods.js'; @@ -105,7 +105,7 @@ export const MhchemMethods: { [key: string]: ParseMethod } = { tex = tex.replace(pattern, name as string); } } catch (err) { - throw new TexError(null, err[0], err[1]); + texError(null, err[0], err[1]); } parser.string = tex + parser.string.substring(parser.i); parser.i = 0; diff --git a/ts/input/tex/newcommand/NewcommandItems.ts b/ts/input/tex/newcommand/NewcommandItems.ts index 10482c83b..11d6870a3 100644 --- a/ts/input/tex/newcommand/NewcommandItems.ts +++ b/ts/input/tex/newcommand/NewcommandItems.ts @@ -21,7 +21,7 @@ * @author v.sorge@mathjax.org (Volker Sorge) */ -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { CheckType, BaseItem, StackItem } from '../StackItem.js'; import { COMPONENT } from './__locales__/Component.js'; @@ -54,18 +54,13 @@ export class BeginEnvItem extends BaseItem { // @test Newenvironment Empty, Newenvironment Align if (item.getName() !== this.getName()) { // @test (missing) \newenvironment{env}{aa}{bb}\begin{env}cc\end{equation} - throw new TexError( - COMPONENT, - 'EnvBadEnd', - this.getName(), - item.getName() - ); + texError(COMPONENT, 'EnvBadEnd', this.getName(), item.getName()); } return [[this.factory.create('mml', this.toMml())], true]; } if (item.isKind('stop')) { // @test (missing) \newenvironment{env}{aa}{bb}\begin{env}cc - throw new TexError(COMPONENT, 'EnvMissingEnd', this.getName()); + texError(COMPONENT, 'EnvMissingEnd', this.getName()); } // @test Newenvironment Empty, Newenvironment Align return super.checkItem(item); diff --git a/ts/input/tex/newcommand/NewcommandMethods.ts b/ts/input/tex/newcommand/NewcommandMethods.ts index 4ad4dff38..d43ce9c8f 100644 --- a/ts/input/tex/newcommand/NewcommandMethods.ts +++ b/ts/input/tex/newcommand/NewcommandMethods.ts @@ -23,7 +23,7 @@ import { HandlerType } from '../HandlerTypes.js'; import { ParseResult, ParseMethod } from '../Types.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import TexParser from '../TexParser.js'; import * as sm from '../TokenMap.js'; import { Token } from '../Token.js'; @@ -217,7 +217,7 @@ const NewcommandMethods: { [key: string]: ParseMethod } = { parser.GetNext(); if (params[0] && !NewcommandUtil.MatchParam(parser, params[0])) { // @test Missing Arguments - throw new TexError(COMPONENT, 'MismatchUseDef', name); + texError(COMPONENT, 'MismatchUseDef', name); } if (argCount) { for (let i = 0; i < argCount; i++) { diff --git a/ts/input/tex/newcommand/NewcommandUtil.ts b/ts/input/tex/newcommand/NewcommandUtil.ts index fef773426..bb7ff956d 100644 --- a/ts/input/tex/newcommand/NewcommandUtil.ts +++ b/ts/input/tex/newcommand/NewcommandUtil.ts @@ -24,7 +24,7 @@ import { HandlerType } from '../HandlerTypes.js'; import { SubHandler } from '../MapHandler.js'; import { UnitUtil } from '../UnitUtil.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import TexParser from '../TexParser.js'; import { Macro, Token } from '../Token.js'; import { Args, Attributes, ParseMethod } from '../Types.js'; @@ -59,7 +59,7 @@ export const NewcommandUtil = { const c = parser.GetNext(); if (c !== '\\') { // @test No CS - throw new TexError(COMPONENT, 'MissingCS', cmd); + texError(COMPONENT, 'MissingCS', cmd); } const cs = UnitUtil.trimSpaces(parser.GetArgument(cmd)).substring(1); this.checkProtectedMacros(parser, cs); @@ -81,7 +81,7 @@ export const NewcommandUtil = { } if (!cs.match(/^(.|[a-z]+)$/i)) { // @test Illegal CS - throw new TexError(COMPONENT, 'IllegalControlSequenceName', name); + texError(COMPONENT, 'IllegalControlSequenceName', name); } this.checkProtectedMacros(parser, cs); return cs; @@ -102,7 +102,7 @@ export const NewcommandUtil = { n = UnitUtil.trimSpaces(n); if (!n.match(/^[0-9]+$/)) { // @test Illegal Argument Number - throw new TexError(COMPONENT, 'IllegalParamNumber', name); + texError(COMPONENT, 'IllegalParamNumber', name); } } return n; @@ -135,11 +135,11 @@ export const NewcommandUtil = { c = parser.string.charAt(++parser.i); if (!c.match(/^[1-9]$/)) { // @test Illegal Hash - throw new TexError(COMPONENT, 'CantUseHash2', cs); + texError(COMPONENT, 'CantUseHash2', cs); } if (parseInt(c) !== ++n) { // @test No Sequence - throw new TexError(COMPONENT, 'SequentialParam', cs); + texError(COMPONENT, 'SequentialParam', cs); } i = parser.i + 1; } else if (c === '{') { @@ -166,7 +166,7 @@ export const NewcommandUtil = { parser.i++; } // @test No Replacement - throw new TexError(COMPONENT, 'MissingReplacementString', cmd); + texError(COMPONENT, 'MissingReplacementString', cmd); }, /** @@ -220,7 +220,7 @@ export const NewcommandUtil = { } } // @test Runaway Argument - throw new TexError(COMPONENT, 'RunawayArgument', name); + texError(COMPONENT, 'RunawayArgument', name); }, /** @@ -284,7 +284,7 @@ export const NewcommandUtil = { */ checkProtectedMacros(parser: TexParser, cs: string) { if (parser.options.protectedMacros?.includes(cs)) { - throw new TexError(COMPONENT, 'ProtectedMacro', `\\${cs}`); + texError(COMPONENT, 'ProtectedMacro', `\\${cs}`); } }, diff --git a/ts/input/tex/physics/PhysicsItems.ts b/ts/input/tex/physics/PhysicsItems.ts index 3fab3799c..ede292204 100644 --- a/ts/input/tex/physics/PhysicsItems.ts +++ b/ts/input/tex/physics/PhysicsItems.ts @@ -26,13 +26,14 @@ import { ParseUtil } from '../ParseUtil.js'; import NodeUtil from '../NodeUtil.js'; import TexParser from '../TexParser.js'; import { AbstractMmlTokenNode } from '../../../core/MmlTree/MmlNode.js'; +import { COMPONENT } from './__locales__/Component.js'; export class AutoOpen extends BaseItem { /** * @override */ protected static errors = Object.assign(Object.create(BaseItem.errors), { - stop: ['ExtraOrMissingDelims', 'Extra open or missing close delimiter'], + stop: [COMPONENT, 'ExtraOrMissingDelims'], }); /** diff --git a/ts/input/tex/physics/PhysicsMethods.ts b/ts/input/tex/physics/PhysicsMethods.ts index a227c6b4e..2c5216a0b 100644 --- a/ts/input/tex/physics/PhysicsMethods.ts +++ b/ts/input/tex/physics/PhysicsMethods.ts @@ -25,7 +25,7 @@ import { HandlerType } from '../HandlerTypes.js'; import { ParseMethod, ParseResult } from '../Types.js'; import BaseMethods from '../base/BaseMethods.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { TEXCLASS, MmlNode } from '../../../core/MmlTree/MmlNode.js'; import { ParseUtil } from '../ParseUtil.js'; import NodeUtil from '../NodeUtil.js'; @@ -33,6 +33,7 @@ import { NodeFactory } from '../NodeFactory.js'; import { Macro } from '../Token.js'; import { AutoOpen } from './PhysicsItems.js'; +import { COMPONENT as TEX_COMPONENT } from '../__locales__/Component.js'; import { COMPONENT } from './__locales__/Component.js'; /** @@ -245,7 +246,7 @@ const PhysicsMethods: { [key: string]: ParseMethod } = { } let right = pairs[next]; if (arg && next !== '{') { - throw new TexError(COMPONENT, 'MissingArgFor', parser.currentCS); + texError(TEX_COMPONENT, 'MissingArgFor', parser.currentCS); } if (!right) { const empty = parser.create('node', 'mrow'); @@ -343,12 +344,12 @@ const PhysicsMethods: { [key: string]: ParseMethod } = { big = parser.GetCS(); if (!big.match(biggs)) { // Actually a commutator error arg1 error. - throw new TexError(COMPONENT, 'MissingArgFor', parser.currentCS); + texError(TEX_COMPONENT, 'MissingArgFor', parser.currentCS); } next = parser.GetNext(); } if (next !== '{') { - throw new TexError(COMPONENT, 'MissingArgFor', parser.currentCS); + texError(TEX_COMPONENT, 'MissingArgFor', parser.currentCS); } const arg1 = parser.GetArgument(name); const arg2 = parser.GetArgument(name); @@ -878,7 +879,7 @@ const PhysicsMethods: { [key: string]: ParseMethod } = { const arg = parser.GetArgument(name); const size = parseInt(arg, 10); if (isNaN(size)) { - throw new TexError(COMPONENT, 'InvalidNumber'); + texError(COMPONENT, 'InvalidNumber'); } if (size <= 1) { parser.string = '1' + parser.string.slice(parser.i); @@ -915,7 +916,7 @@ const PhysicsMethods: { [key: string]: ParseMethod } = { m.toString() !== arg3 || n.toString() !== arg2 ) { - throw new TexError(COMPONENT, 'InvalidNumber'); + texError(COMPONENT, 'InvalidNumber'); } n = n < 1 ? 1 : n; m = m < 1 ? 1 : m; diff --git a/ts/input/tex/physics/__locales__/de.json b/ts/input/tex/physics/__locales__/de.json index 684dc244e..46ac00177 100644 --- a/ts/input/tex/physics/__locales__/de.json +++ b/ts/input/tex/physics/__locales__/de.json @@ -1,4 +1,4 @@ { "InvalidNumber": "Ungültige Zahl", - + "ExtraOrMissingDelims": "Extra open or missing close delimiter" } diff --git a/ts/input/tex/physics/__locales__/en.json b/ts/input/tex/physics/__locales__/en.json index ed021475d..0b659d22f 100644 --- a/ts/input/tex/physics/__locales__/en.json +++ b/ts/input/tex/physics/__locales__/en.json @@ -1,4 +1,4 @@ { "InvalidNumber": "Invalid number", - + "ExtraOrMissingDelims": "Extra open or missing close delimiter" } diff --git a/ts/input/tex/require/RequireConfiguration.ts b/ts/input/tex/require/RequireConfiguration.ts index 88cb08bc9..95e3e6356 100644 --- a/ts/input/tex/require/RequireConfiguration.ts +++ b/ts/input/tex/require/RequireConfiguration.ts @@ -30,7 +30,7 @@ import { import TexParser from '../TexParser.js'; import { CommandMap } from '../TokenMap.js'; import { ParseMethod } from '../Types.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { TeX } from '../../tex.js'; import { MathJax } from '../../../components/startup.js'; @@ -172,7 +172,7 @@ export function RequireLoad(parser: TexParser, name: string) { ? allow[name] : options.defaultAllow; if (!allowed) { - throw new TexError(COMPONENT, 'BadRequire', extension); + texError(COMPONENT, 'BadRequire', extension); } const data = Package.packages.get(extension); if (!data) { @@ -183,7 +183,7 @@ export function RequireLoad(parser: TexParser, name: string) { ); } if (data.hasFailed) { - throw new TexError(COMPONENT, 'RequireFail', name); + texError(COMPONENT, 'RequireFail', name); } const require = LOADERCONFIG[extension]?.rendererExtensions; const menu = (MathJax.startup.document as MenuMathDocument)?.menu; @@ -233,7 +233,7 @@ export const RequireMethods: { [key: string]: ParseMethod } = { Require(parser: TexParser, name: string) { const required = parser.GetArgument(name); if (required.match(/[^_a-zA-Z0-9]/) || required === '') { - throw new TexError(COMPONENT, 'BadPackageName', name); + texError(COMPONENT, 'BadPackageName', name); } RequireLoad(parser, required); parser.Push(parser.itemFactory.create('null')); diff --git a/ts/input/tex/setoptions/SetOptionsConfiguration.ts b/ts/input/tex/setoptions/SetOptionsConfiguration.ts index 969d1cf0c..b33595ed1 100644 --- a/ts/input/tex/setoptions/SetOptionsConfiguration.ts +++ b/ts/input/tex/setoptions/SetOptionsConfiguration.ts @@ -30,7 +30,7 @@ import { import { TeX } from '../../tex.js'; import TexParser from '../TexParser.js'; import { CommandMap } from '../TokenMap.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { ParseUtil } from '../ParseUtil.js'; import { Macro } from '../Token.js'; import BaseMethods from '../base/BaseMethods.js'; @@ -49,7 +49,7 @@ export const SetOptionsUtil = { */ filterPackage(parser: TexParser, extension: string): boolean { if (extension !== 'tex' && !ConfigurationHandler.get(extension)) { - throw new TexError(COMPONENT, 'NotAPackage', extension); + texError(COMPONENT, 'NotAPackage', extension); } const config = parser.options.setoptions; const options = config.allowOptions[extension]; @@ -57,7 +57,7 @@ export const SetOptionsUtil = { (options === undefined && !config.allowPackageDefault) || options === false ) { - throw new TexError(COMPONENT, 'PackageNotSettable', extension); + texError(COMPONENT, 'PackageNotSettable', extension); } return true; }, @@ -80,17 +80,17 @@ export const SetOptionsUtil = { : null; if (allow === false || (allow === null && !config.allowOptionsDefault)) { if (isTex) { - throw new TexError(COMPONENT, 'TeXOptionNotSettable', option); + texError(COMPONENT, 'TeXOptionNotSettable', option); } else { - throw new TexError(COMPONENT, 'OptionNotSettable', option, extension); + texError(COMPONENT, 'OptionNotSettable', option, extension); } } const extOptions = isTex ? parser.options : parser.options[extension]; if (!extOptions || !Object.hasOwn(extOptions, option)) { if (isTex) { - throw new TexError(COMPONENT, 'InvalidTexOption', option); + texError(COMPONENT, 'InvalidTexOption', option); } else { - throw new TexError(COMPONENT, 'InvalidOptionKey', option, extension); + texError(COMPONENT, 'InvalidOptionKey', option, extension); } } return true; diff --git a/ts/input/tex/texhtml/TexHtmlConfiguration.ts b/ts/input/tex/texhtml/TexHtmlConfiguration.ts index 422cd580e..adb05ce32 100644 --- a/ts/input/tex/texhtml/TexHtmlConfiguration.ts +++ b/ts/input/tex/texhtml/TexHtmlConfiguration.ts @@ -27,13 +27,12 @@ import TexParser from '../TexParser.js'; import { MacroMap } from '../TokenMap.js'; import { ParseMethod } from '../Types.js'; import ParseOptions from '../ParseOptions.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { HTMLDocument } from '../../../handlers/html/HTMLDocument.js'; import { HtmlNode } from '../../../core/MmlTree/MmlNodes/HtmlNode.js'; import { HTMLDomStrings } from '../../../handlers/html/HTMLDomStrings.js'; import { DOMAdaptor } from '../../../core/DOMAdaptor.js'; -import { COMPONENT } from './__locales__/Component.js'; -export { COMPONENT }; +import { COMPONENT } from '../__locales__/Component.js'; export const HtmlNodeMethods: { [key: string]: ParseMethod } = { /** @@ -61,12 +60,7 @@ export const HtmlNodeMethods: { [key: string]: ParseMethod } = { const end = (match[1] ? `` : '') + ''; const i = parser.string.slice(parser.i).indexOf(end); if (i < 0) { - throw new TexError( - COMPONENT, - 'TokenNotFoundForCommand', - end, - '<' + match[0] - ); + texError(COMPONENT, 'TokenNotFoundForCommand', end, '<' + match[0]); } const html = parser.string.substring(parser.i, parser.i + i).trim(); parser.i += i + 11 + (match[1] ? 3 + match[1].length : 0); diff --git a/ts/input/tex/textmacros/TextMacrosMethods.ts b/ts/input/tex/textmacros/TextMacrosMethods.ts index be6227ad0..102c330d4 100644 --- a/ts/input/tex/textmacros/TextMacrosMethods.ts +++ b/ts/input/tex/textmacros/TextMacrosMethods.ts @@ -27,6 +27,7 @@ import { retryAfter } from '../../../util/Retries.js'; import { TextParser } from './TextParser.js'; import BaseMethods from '../base/BaseMethods.js'; +import { COMPONENT as TEX_COMPONENT } from '../__locales__/Component.js'; import { COMPONENT } from './__locales__/Component.js'; /** @@ -91,13 +92,13 @@ export const TextMacrosMethods = { case '}': if (braces === 0) { - parser.Error(COMPONENT, 'ExtraCloseMissingOpen'); + parser.Error(TEX_COMPONENT, 'ExtraCloseMissingOpen'); } braces--; break; } } - parser.Error(COMPONENT, 'MathNotTerminated'); + parser.Error(TEX_COMPONENT, 'MathNotTerminated'); }, /** @@ -113,7 +114,7 @@ export const TextMacrosMethods = { * @param {string} c The character that called this function */ Misplaced(parser: TextParser, c: string) { - parser.Error(COMPONENT, 'Misplaced', c); + parser.Error(TEX_COMPONENT, 'Misplaced', c); }, /** @@ -142,7 +143,7 @@ export const TextMacrosMethods = { parser.saveText(); parser.stack.env = parser.envStack.pop(); } else { - parser.Error(COMPONENT, 'ExtraCloseMissingOpen'); + parser.Error(TEX_COMPONENT, 'ExtraCloseMissingOpen'); } }, diff --git a/ts/input/tex/textmacros/TextParser.ts b/ts/input/tex/textmacros/TextParser.ts index 339fd5eb9..e364fe736 100644 --- a/ts/input/tex/textmacros/TextParser.ts +++ b/ts/input/tex/textmacros/TextParser.ts @@ -22,7 +22,7 @@ */ import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import ParseOptions from '../ParseOptions.js'; import { ParseUtil } from '../ParseUtil.js'; import { StackItem } from '../StackItem.js'; @@ -237,6 +237,6 @@ export class TextParser extends TexParser { * @param {string[]} args Any substitution args for the message */ public Error(component: string, id: string, ...args: string[]) { - throw new TexError(component, id, ...args); + texError(component, id, ...args); } } diff --git a/ts/input/tex/unicode/UnicodeConfiguration.ts b/ts/input/tex/unicode/UnicodeConfiguration.ts index edc41b1f9..786e10443 100644 --- a/ts/input/tex/unicode/UnicodeConfiguration.ts +++ b/ts/input/tex/unicode/UnicodeConfiguration.ts @@ -25,13 +25,14 @@ import { HandlerType, ConfigurationType } from '../HandlerTypes.js'; import { Configuration } from '../Configuration.js'; import { EnvList } from '../StackItem.js'; import TexParser from '../TexParser.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; import { CommandMap } from '../TokenMap.js'; import { ParseMethod } from '../Types.js'; import { UnitUtil } from '../UnitUtil.js'; import NodeUtil from '../NodeUtil.js'; import { numeric } from '../../../util/Entities.js'; import { Other } from '../base/BaseConfiguration.js'; +import { COMPONENT as TEX_COMPONENT } from '../__locales__/Component.js'; import { COMPONENT } from './__locales__/Component.js'; export { COMPONENT }; @@ -60,11 +61,11 @@ const UnicodeMethods: { [key: string]: ParseMethod } = { } } if (font.match(/;/)) { - throw new TexError(COMPONENT, 'BadFont', parser.currentCS); + texError(COMPONENT, 'BadFont', parser.currentCS); } const n = UnitUtil.trimSpaces(parser.GetArgument(name)).replace(/^0x/, 'x'); if (!n.match(/^(x[0-9A-Fa-f]+|[0-9]+)$/)) { - throw new TexError(COMPONENT, 'BadUnicode', parser.currentCS); + texError(COMPONENT, 'BadUnicode', parser.currentCS); } const N = parseInt(n.match(/^x/) ? '0' + n : n); if (!UnicodeCache[N]) { @@ -105,7 +106,7 @@ const UnicodeMethods: { [key: string]: ParseMethod } = { RawUnicode(parser: TexParser, name: string) { const hex = parser.GetArgument(name).trim(); if (!hex.match(/^[0-9A-F]{1,6}$/)) { - throw new TexError(COMPONENT, 'BadRawUnicode', parser.currentCS); + texError(TEX_COMPONENT, 'BadRawUnicode', parser.currentCS); } const n = parseInt(hex, 16); parser.string = String.fromCodePoint(n) + parser.string.substring(parser.i); @@ -146,11 +147,7 @@ const UnicodeMethods: { [key: string]: ParseMethod } = { parser.i += 2; const cs = [...parser.GetCS()]; if (cs.length > 1) { - throw new TexError( - COMPONENT, - 'InvalidAlphanumeric', - parser.currentCS - ); + texError(COMPONENT, 'InvalidAlphanumeric', parser.currentCS); } c = cs[0]; match = ['']; @@ -163,7 +160,7 @@ const UnicodeMethods: { [key: string]: ParseMethod } = { } } if (!c) { - throw new TexError(COMPONENT, 'MissingNumber', parser.currentCS); + texError(COMPONENT, 'MissingNumber', parser.currentCS); } parser.i += match[0].length; if (c >= '0' && c <= '9') { diff --git a/ts/input/tex/verb/VerbConfiguration.ts b/ts/input/tex/verb/VerbConfiguration.ts index 4b4bd012c..905193cb2 100644 --- a/ts/input/tex/verb/VerbConfiguration.ts +++ b/ts/input/tex/verb/VerbConfiguration.ts @@ -27,7 +27,8 @@ import { TexConstant } from '../TexConstants.js'; import TexParser from '../TexParser.js'; import { CommandMap } from '../TokenMap.js'; import { ParseMethod } from '../Types.js'; -import TexError from '../TexError.js'; +import { texError } from '../TexError.js'; +import { COMPONENT as TEX_COMPONENT } from '../__locales__/Component.js'; import { COMPONENT } from './__locales__/Component.js'; export { COMPONENT }; @@ -43,7 +44,7 @@ const VerbMethods: { [key: string]: ParseMethod } = { const c = parser.GetNext(); const start = ++parser.i; if (c === '') { - throw new TexError(COMPONENT, 'MissingArgFor', name); + texError(TEX_COMPONENT, 'MissingArgFor', name); } while ( parser.i < parser.string.length && @@ -52,7 +53,7 @@ const VerbMethods: { [key: string]: ParseMethod } = { parser.i++; } if (parser.i === parser.string.length) { - throw new TexError(COMPONENT, 'NoClosingDelim', parser.currentCS); + texError(COMPONENT, 'NoClosingDelim', parser.currentCS); } const text = parser.string.slice(start, parser.i).replace(/ /g, '\u00A0'); parser.i++; diff --git a/ts/util/Locale.ts b/ts/util/Locale.ts index 1ac72a89d..75f955662 100644 --- a/ts/util/Locale.ts +++ b/ts/util/Locale.ts @@ -133,17 +133,33 @@ export class Locale { data: string | namedData = {}, ...args: string[] ): string { - let message = ''; if (component) { - message = this.lookupMessage(component, id); - } else { - if (typeof data !== 'string') { - return ''; - } - message = data; - data = args.shift()?.toString() ?? {}; + const message = this.lookupMessage(component, id); + return this.processMessage(message, data, ...args); + } + if (typeof data !== 'string') { + return ''; } - if (typeof data === 'string') { + return this.processMessage(data, ...args); + } + + /** + * Process a message string by substituting the given arguments. The arguments + * can be positional, or a data mapping of names to values. + * + * @param {string} message The message string to process. + * @param {string | namedData = {}} data The first argument or the object of + * names arguments + * @param {string[]} ...args Additional arguments (if data is a string) + * @param {...any} args + * @returns {string} The processed message string with arguments substituted + */ + public static processMessage( + message: string, + data: string | namedData = {}, + ...args: string[] + ): string { + if (typeof data !== 'object') { data = { 1: data }; for (let i = 0; i < args.length; i++) { data[i + 2] = args[i];