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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ jobs:
- name: Compile MathJax
run: |
pnpm -s mjs:compile
components/bin/makeAll --mjs --terse --build components/mjs
pnpm -s copy:assets mjs
components/bin/makeAll --mjs --terse --build --copy components/mjs
pnpm -s cjs:compile
pnpm -s cjs:components:src:build
components/bin/makeAll --cjs --terse --build components/cjs
pnpm -s copy:assets cjs
components/bin/makeAll --cjs --terse --build --copy components/cjs
pnpm -s copy:pkg cjs

- name: Build tests
Expand Down
2 changes: 2 additions & 0 deletions components/json.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module.exports.json = async function (file) {return require(file)};
module.exports.require = require;
17 changes: 13 additions & 4 deletions components/mjs/core/core.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import './locale.js';
import './lib/core.js';

import {HTMLHandler} from '#js/handlers/html/HTMLHandler.js';
import {browserAdaptor} from '#js/adaptors/browserAdaptor.js';
import {Package} from '#js/components/package.js';

if (MathJax.startup) {
MathJax.startup.registerConstructor('HTMLHandler', HTMLHandler);
Expand All @@ -11,9 +13,16 @@ if (MathJax.startup) {
}
if (MathJax.loader) {
const config = MathJax.config.loader;
MathJax._.mathjax.mathjax.asyncLoad = (
(name) => name.substring(0, 5) === 'node:'
const {mathjax} = MathJax._.mathjax;
mathjax.asyncLoad = (name => {
if (name.match(/\.json$/)) {
if (name.charAt(0) === '[') {
name = Package.resolvePath(name);
}
return (config.json || mathjax.json)(name).then((data) => data.default ?? data);
}
return name.substring(0, 5) === 'node:'
? config.require(name)
: MathJax.loader.load(name).then(result => result[0])
);
: MathJax.loader.load(name).then(result => result[0]);
});
}
4 changes: 4 additions & 0 deletions components/mjs/core/locale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {Locale} from '#js/util/Locale.js';

Locale.isComponent = true;

5 changes: 5 additions & 0 deletions components/mjs/input/tex/extensions/bbox/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
"component": "input/tex/extensions/bbox",
"targets": ["input/tex/bbox"]
},
"copy": {
"to": "[bundle]/input/tex/extensions/bbox",
"from": "[ts]/input/tex/bbox",
"copy": ["locales"]
},
"webpack": {
"name": "input/tex/extensions/bbox",
"libs": [
Expand Down
31 changes: 17 additions & 14 deletions components/mjs/node-main/node-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@

import '../startup/init.js';
import {Loader, CONFIG} from '#js/components/loader.js';
import {Package} from '#js/components/package.js';
import {combineDefaults, combineConfig} from '#js/components/global.js';
import {MathJax, combineDefaults, combineConfig} from '#js/components/global.js';
import {resolvePath} from '#js/util/AsyncLoad.js';
import {context} from '#js/util/context.js';
import '../core/core.js';
import '../adaptors/liteDOM/liteDOM.js';
import {source} from '../source.js';

const MathJax = global.MathJax;

const path = eval('require("path")'); // get path from node, not webpack
const REQUIRE = eval('require'); // get require from node, not webpack
const path = REQUIRE("path");
const fs = REQUIRE("fs").promises;
const dir = context.path(MathJax.config.__dirname); // set up by node-main.mjs or node-main.cjs

/*
Expand All @@ -48,23 +48,26 @@ combineDefaults(MathJax.config, 'output', {font: 'mathjax-newcm'});
*/
Loader.preLoaded('loader', 'startup', 'core', 'adaptors/liteDOM');

/*
* Set the paths.
*/
if (path.basename(dir) === 'node-main') {
CONFIG.paths.esm = CONFIG.paths.mathjax;
CONFIG.paths.sre = '[esm]/sre';
CONFIG.paths.mathjax = path.dirname(dir);
CONFIG.paths.mathjax = path.resolve(dir, '..', '..', '..', 'bundle');
combineDefaults(CONFIG, 'source', source);
} else {
CONFIG.paths.mathjax = dir;
}
//
// Set the asynchronous loader to use the js directory, so we can load
// other files like entity definitions
//
const ROOT = path.resolve(dir, '..', '..', '..', path.basename(path.dirname(dir)));
const REQUIRE = MathJax.config.loader.require;

/*
* Set the asynchronous loader to handle json files
*/
MathJax._.mathjax.mathjax.asyncLoad = function (name) {
return REQUIRE(name.charAt(0) === '.' ? path.resolve(ROOT, name) :
name.charAt(0) === '[' ? Package.resolvePath(name) : name);
const file = resolvePath(name, (name) => path.resolve(CONFIG.paths.mathjax, name));
return file.match(/\.json$/)
? fs.readFile(REQUIRE.resolve(file)).then((json) => JSON.parse(json))
: REQUIRE(file);
};

/*
Expand Down
3 changes: 2 additions & 1 deletion components/mjs/require/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"to": "[bundle]",
"from": "../..",
"copy": [
"require.mjs"
"require.mjs",
"json.cjs"
]
}
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@
"clean:lib": "clean() { pnpm -s log:single \"Cleaning $1 component libs\"; pnpm rimraf -g components/$1'/**/lib'; }; clean",
"clean:mod": "clean() { pnpm -s log:comp \"Cleaning $1 module\"; pnpm -s clean:dir $1 && pnpm -s clean:lib $1; }; clean",
"=============================================================================== copy": "",
"copy:assets": "pnpm -s log:comp 'Copying assets'; copy() { pnpm -s copy:mj2 $1 && pnpm -s copy:mml3 $1 && pnpm -s copy:html $1; }; copy",
"copy:assets": "pnpm -s log:comp 'Copying assets'; copy() { pnpm -s copy:locales $1 && pnpm -s copy:mj2 $1 && pnpm -s copy:mml3 $1 && pnpm -s copy:html $1; }; copy",
"copy:html": "copy() { pnpm -s log:single 'Copying sre auxiliary files'; pnpm copyfiles -u 1 'ts/a11y/sre/*.html' 'ts/a11y/sre/require.*' $1; }; copy",
"copy:locales": "pnpm -s log:single 'Copying TeX extension locales'; copy() { pnpm copyfiles -u 3 'ts/input/tex/*/locales/*.json' $1/input/tex/extensions; }; copy",
"copy:mj2": "copy() { pnpm -s log:single 'Copying legacy code AsciiMath'; pnpm copyfiles -u 1 'ts/input/asciimath/legacy/**/*' $1; }; copy",
"copy:mml3": "copy() { pnpm -s log:single 'Copying legacy code MathML3'; pnpm copyfiles -u 1 ts/input/mathml/mml3/mml3.sef.json $1; }; copy",
"copy:mml3": "copy() { pnpm -s log:single 'Copying MathML3 extension json'; pnpm copyfiles -u 1 ts/input/mathml/mml3/mml3.sef.json $1; }; copy",
"copy:pkg": "copy() { pnpm -s log:single \"Copying package.json to $1\"; pnpm copyfiles -u 2 components/bin/package.json $1; }; copy",
"=============================================================================== log": "",
"log:comp": "log() { echo \u001b[32m$1\u001b[0m; }; log",
Expand Down
3 changes: 3 additions & 0 deletions testsuite/lib/AsyncLoad.child.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"json": true
}
3 changes: 3 additions & 0 deletions testsuite/lib/component/locales/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Id1": "Test of %1 in %2"
}
8 changes: 8 additions & 0 deletions testsuite/lib/component/locales/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"test1": "Has %% percent",
"test2": "Has %1 one",
"test3": "Order %2 %1 reversed",
"test4": "Skip %1 %3",
"test5": "Named %{hello} %world",
"error": "Error in %1"
}
2 changes: 1 addition & 1 deletion testsuite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"dependencies": {
"@jest/globals": "^29.7.0",
"@mathjax/mathjax-bbm-font-extension": "^4.0.0",
"@mathjax/mathjax-bbm-font-extension": "^4.1.0",
"@types/jest": "^29.5.14",
"jest": "^29.7.0",
"ts-jest": "^29.3.4",
Expand Down
10 changes: 5 additions & 5 deletions testsuite/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions testsuite/src/node-main.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module '#source/node-main/node-main.mjs' {
export function init(config: any): any;
}
8 changes: 4 additions & 4 deletions testsuite/src/setupTex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@ import {mathjax} from '#js/mathjax.js';
import {OptionList} from '#js/util/Options.js';
import {tmpJsonFile} from '#src/constants.js';
import * as fs from 'fs';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import {init} from '#source/node-main/node-main.mjs';
import {expect} from '@jest/globals';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import {source} from '#source/source.js';
import {Locale} from '#js/util/Locale.js';

declare const MathJax: any;
type MATHITEM = MathItem<any, any, any>;
Expand Down Expand Up @@ -165,6 +162,7 @@ export function setupTex(packages: PackageList = ['base'], options: OptionList =
const html = new HTMLDocument('', adaptor, {InputJax: tex});
convert = (expr: string, display: boolean) =>
toMathML(html.convert(expr, {display: display, end: STATE.CONVERT}));
return Locale.setLocale();
}

/**
Expand All @@ -189,6 +187,7 @@ export function setupTexRender(packages: PackageList = ['base'], options: Option
html.findMath().compile();
return toMathML((Array.from(html.math)[0] as MATHITEM).root);
}
return Locale.setLocale();
}

/**
Expand Down Expand Up @@ -263,6 +262,7 @@ export function setupTexWithOutput(packages: string[] = ['base'], options: Optio
const toMathML = ((node: MmlNode) => visitor.visitTree(node));
convert = (expr: string, display: boolean) =>
toMathML(html.convert(expr, {display: display, end: STATE.CONVERT}));
return Locale.setLocale();
}

/*********************************************************************/
Expand Down
3 changes: 3 additions & 0 deletions testsuite/src/source.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module '#source/source.js' {
export const source: {[name: string]: string};
}
4 changes: 2 additions & 2 deletions testsuite/tests/input/tex/Bbox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { afterAll, beforeEach, describe, it } from '@jest/globals';
import { getTokens, toXmlMatch, setupTex, tex2mml, expectTexError } from '#helpers';
import '#js/input/tex/bbox/BboxConfiguration';

beforeEach(() => setupTex(['base', 'bbox']));
beforeEach(async () => setupTex(['base', 'bbox']));

/**********************************************************************************/
/**********************************************************************************/
Expand Down Expand Up @@ -118,7 +118,7 @@ describe('Bbox', () => {

it('Bbox-General-Error', () => {
expectTexError('\\bbox[22-11=color]{a}')
.toBe(`"22-11=color" doesn't look like a color, a padding dimension, or a style`);
.toBe(`'22-11=color' doesn't look like a color, a padding dimension, or a style`);
});

/********************************************************************************/
Expand Down
2 changes: 1 addition & 1 deletion testsuite/tests/input/tex/Require.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ setupComponents({
loader: {
load: ['input/tex-base', '[tex]/require'],
source: {
'[tex]/error': '../../testsuite/lib/error.js'
'[tex]/error': '../testsuite/lib/error.js'
},
dependencies: {
'[tex]/upgreek': ['input/tex-base', '[tex]/error']
Expand Down
26 changes: 25 additions & 1 deletion testsuite/tests/util/AsyncLoad.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, test, expect } from '@jest/globals';
import {asyncLoad} from '#js/util/AsyncLoad.js';
import {asyncLoad, resolvePath} from '#js/util/AsyncLoad.js';
import {mathjax} from '#js/mathjax.js';

describe('asyncLoad()', () => {
Expand Down Expand Up @@ -36,4 +36,28 @@ describe('asyncLoad()', () => {

});

test('resolvePath', () => {
//
// Test resolvePath woth Pacakge path resolution
//
(global as any).MathJax = {
_: {
components: {
package: {
Package: {
resolvePath: (file: string) => 'test:' + file,
}
}
}
}
};
expect(resolvePath('[x]/y.js', (file) => file)).toBe('test:[x]/y.js');

//
// Remove MathJax._ and test relative and absolute paths
//
(global as any).MathJax = {}
expect(resolvePath('./x.js', (file) => `rel:${file.substring(2)}`, (file) => `abs:${file}`)).toBe('rel:x.js');
expect(resolvePath('x.js', (file) => `rel:${file.substring(2)}`, (file) => `abs:${file}`)).toBe('abs:x.js');
});
});
74 changes: 74 additions & 0 deletions testsuite/tests/util/Locale.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { describe, test, expect } from '@jest/globals';
import {Locale} from '#js/util/Locale.js';
import '#js/util/asyncLoad/esm.js';

/**********************************************************************************/
/**********************************************************************************/

describe('Locale', () => {

/********************************************************************************/

test('Set locale', async () => {
expect(Locale.current).toBe('en');
await Locale.setLocale();
expect(Locale.current).toBe('en');
await Locale.setLocale('de');
expect(Locale.current).toBe('de');
await Locale.setLocale('en');
expect(Locale.current).toBe('en');
});

/********************************************************************************/

test('Register a component', async () => {
const locale = Locale as any;
Locale.registerLocaleFiles('component', '../testsuite/lib/component');
expect(locale.locations.component).toEqual(['../testsuite/lib/component/locales', new Set()]);
const error = console.error;
console.error = (message) => {throw message};
await expect(Locale.setLocale('de')).rejects
.toMatch("MathJax(component): Can't load 'de.json': ENOENT: no such file or directory");
console.error = error;
await Locale.setLocale('en');
expect(locale.data.component).toEqual({en: {Id1: 'Test of %1 in %2'}});
expect(Locale.message('component', 'Id1', 'message', 'Locale')).toBe('Test of message in Locale');
});

/********************************************************************************/

test('Messages', async () => {
Locale.registerLocaleFiles('component', '../testsuite/lib/component');
await Locale.setLocale('en'); // load English backups
await Locale.setLocale('test');
expect(Locale.message('component', 'test1')).toBe('Has % percent');
expect(Locale.message('component', 'test2', 'x')).toBe('Has x one');
expect(Locale.message('component', 'test3', 'a', 'b')).toBe('Order b a reversed');
expect(Locale.message('component', 'test4', 'a', 'b', 'c')).toBe('Skip a c');
expect(Locale.message('component', 'test4')).toBe('Skip ');
expect(Locale.message('component', 'test5', {hello: 'HELLO', world: 'WORLD'})).toBe('Named HELLO WORLD');
expect(Locale.message('component', 'Id1', 'a', 'b')).toBe('Test of a in b');
expect(Locale.message('component', 'Id2'))
.toBe("No localized or default version for message with id 'Id2' from 'component'");
expect(Locale.message('undefined', 'Id1'))
.toBe("No localized or default version for message with id 'Id1' from 'undefined'");
expect(() => Locale.error('component', 'error', 'x')).toThrow('Error in x');
});

/********************************************************************************/

test('isComponent', async () => {
Locale.isComponent = true;
Locale.registerLocaleFiles('../testsuite/lib/component', 'notfound');
await Locale.setLocale('test');
expect(Locale.message('component', 'test1')).toBe('Has % percent');
Locale.isComponent = false;
});

/********************************************************************************/

});


/**********************************************************************************/
/**********************************************************************************/
Loading