Skip to content

Commit b67b640

Browse files
committed
Update puppeteer examples to v4
1 parent a5bf8ef commit b67b640

5 files changed

Lines changed: 996 additions & 137 deletions

File tree

puppeteer/Puppeteer.js

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import puppeteer from 'puppeteer';
2+
import path from 'node:path';
3+
4+
//
5+
// Load the needed utilities.
6+
//
7+
import {Typeset} from '../mjs/util/Typeset.js';
8+
import {Util} from '../mjs/util/Util.js';
9+
import {Tex} from '../mjs/util/Tex.js';
10+
import {Mml} from '../mjs/util/Mml.js';
11+
import {Am} from '../mjs/util/Am.js';
12+
import {Chtml} from '../mjs/util/Chtml.js';
13+
import {Svg} from '../mjs/util/Svg.js';
14+
import {Sre} from '../mjs/util/Sre.js';
15+
16+
Util.altDOM = true;
17+
Util.puppet = true;
18+
19+
export const Puppeteer = {
20+
//
21+
// HTML shell file (need a file:// URL so we can load other files).
22+
//
23+
html: new URL('./puppeteer.html', import.meta.url).href,
24+
25+
//
26+
// Path to MathJax component to load
27+
//
28+
startup: new URL(import.meta.resolve('@mathjax/src/bundle/startup.js')),
29+
30+
//
31+
// Create the MathJax configuration
32+
//
33+
config(args) {
34+
//
35+
// Start with the standard Typeset configuration.
36+
//
37+
const MathJax = Typeset.config(args);
38+
//
39+
// Set the root.
40+
//
41+
MathJax.loader.paths.mathjax = new URL('.', this.startup).href.replace(/\/$/, '');
42+
//
43+
// Remove the liteDOM and sources, if present.
44+
//
45+
MathJax.loader.load = MathJax.loader.load.filter((name) => name !== 'adaptors/liteDOM');
46+
delete MathJax.loader.source;
47+
//
48+
// Set the font path, if not the default.
49+
//
50+
if (args.font && args.font !== 'mathjax-newcm') {
51+
MathJax.loader.paths[args.font] =
52+
new URL('.', import.meta.resolve(`@mathjax/${args.font}-font/package.json`)).href;
53+
}
54+
//
55+
// Remove the document (it will be loaded in typeset below)
56+
//
57+
delete MathJax.startup.document;
58+
if (args.file) {
59+
const wd = new URL(process.cwd() + '/', import.meta.url).href;
60+
args.file = new URL(args.file, wd).href;
61+
}
62+
//
63+
// Remove unneeded functions.
64+
//
65+
delete MathJax.loader.require;
66+
delete MathJax.startup.ready;
67+
//
68+
// Return the adjusted configuration.
69+
//
70+
return MathJax;
71+
},
72+
73+
//
74+
// Remove any functions from the configuration and define them later
75+
//
76+
removeFunctions(MathJax, args) {
77+
const declarations = [];
78+
//
79+
// Move the loader.failed function.
80+
//
81+
declarations.push(`MathJax.loader.failed = ${MathJax.loader.failed.toString()};`);
82+
delete MathJax.loader.failed;
83+
//
84+
// Move the tex.formatError function.
85+
//
86+
if (MathJax.tex) {
87+
declarations.push(`MathJax.tex.formatError = ${MathJax.tex.formatError.toString()};`);
88+
delete MathJax.tex.formatError;
89+
}
90+
//
91+
// Move the MathML renderAction functions.
92+
//
93+
if (args.output === 'mml' && args.file) {
94+
const action = MathJax.options.renderActions.typeset;
95+
declarations.push(`MathJax.options.renderActions.typeset[1] = ${action[1].toString()};`);
96+
declarations.push(`MathJax.options.renderActions.typeset[2] = ${action[2].toString()};`);
97+
action[1] = action[2] = null;
98+
}
99+
return declarations;
100+
},
101+
102+
//
103+
// Create the MathJax configuration script.
104+
//
105+
configScript(args) {
106+
const MathJax = this.config(args);
107+
const declarations = this.removeFunctions(MathJax, args);
108+
return 'MathJax = ' + JSON.stringify(MathJax) + '\n' + declarations.join('\n');
109+
110+
},
111+
112+
//
113+
// The function that runs in the puppet.
114+
//
115+
async convert(options, args) {
116+
window.args = args; // Make the arguments global (needed in some ready scripts)
117+
await MathJax.startup.promise; // Wait for MathJax to set up
118+
Util.startup(args); // Run the startup scripts
119+
if (args.file) {
120+
Util.removeScripts(); // Arrange to remove any scripts MathJax added
121+
}
122+
//
123+
// Do the actual typesetting and conversion
124+
//
125+
return Util.typeset(args, Util[args.output], MathJax.startup.document, options);
126+
},
127+
128+
//
129+
// Reporter for console messages from the puppet.
130+
//
131+
async report(msg) {
132+
const msgs = await Promise.all(
133+
msg.args().map(
134+
(arg) => arg.evaluate((arg) => (arg instanceof Error) ? arg.stack : arg.message || arg)
135+
)
136+
);
137+
if (msgs.join(',') === '_die_') process.exit(1);
138+
if (msgs.length) {
139+
console[msg.type()](`[${msg.type().toUpperCase()}]`, ...msgs);
140+
if (msg.type() === 'error' && this['fatal-errors']) process.exit(1);
141+
}
142+
},
143+
144+
//
145+
// Report an error from the typeset script.
146+
//
147+
error(e, prefix = 'Script error:') {
148+
if (e.stack) {
149+
console.error(prefix, e.stack);
150+
} else {
151+
console.log(e);
152+
}
153+
},
154+
155+
//
156+
// Perform the typesetting in the puppet.
157+
//
158+
async typeset(args, config, options, component, convert) {
159+
config ??= Puppeteer.configScript(args);
160+
options ??= Typeset.convertOptions(args);
161+
component ??= this.startup.pathname;
162+
convert ??= Puppeteer.convert;
163+
164+
const browser = await puppeteer.launch(); // launch the browser
165+
const page = await browser.newPage(); // and get a new page
166+
page.on('console', Puppeteer.report.bind(args)); // report messages from chrome
167+
await page.goto(args.file || this.html); // open the HTML page
168+
await page.addScriptTag({path: 'util.js'}); // load the util script
169+
await page.addScriptTag({content: config}); // configure MathJax
170+
await page.addScriptTag({path: component}); // load the MathJax conponent
171+
return page.evaluate(convert, options, args) // perform the conversion
172+
.then((output) => [output, null]) // and return its output
173+
.catch((err) => [null, err]) // pasing on any errors
174+
.then(async ([result, err]) => { // error or not:
175+
const output = result; // make local copy
176+
await browser.close(); // close the browser
177+
if (err) throw err; // throw any error again
178+
return output; // return the output
179+
});
180+
},
181+
};

puppeteer/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"name": "mathjax-puppeteer",
3-
"version": "3.2.0",
4-
"description": "MathJax v3 running in headless Chrome via puppeteer",
3+
"version": "4.0.0",
4+
"description": "MathJax v4 running in headless Chrome via puppeteer",
5+
"type": "module",
56
"dependencies": {
6-
"mathjax-full": "^3.2.0",
7-
"puppeteer": "^9.0.0",
8-
"yargs": "^17.0.1"
7+
"puppeteer": "^24.15.0",
8+
"yargs": "17.7.2"
99
},
1010
"repository": {
1111
"type": "git",

puppeteer/tex2svg

Lines changed: 0 additions & 132 deletions
This file was deleted.

puppeteer/typeset

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#! /usr/bin/env node
2+
3+
/*************************************************************************
4+
*
5+
* puppeteer/typeset
6+
*
7+
* Uses MathJax v4 to convert a any input format to any output format
8+
* inside a headless Chrome via puppeteer.
9+
*
10+
* ----------------------------------------------------------------------
11+
*
12+
* Copyright (c) 2020-2025 The MathJax Consortium
13+
*
14+
* Licensed under the Apache License, Version 2.0 (the "License");
15+
* you may not use this file except in compliance with the License.
16+
* You may obtain a copy of the License at
17+
*
18+
* http://www.apache.org/licenses/LICENSE-2.0
19+
*
20+
* Unless required by applicable law or agreed to in writing, software
21+
* distributed under the License is distributed on an "AS IS" BASIS,
22+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23+
* See the License for the specific language governing permissions and
24+
* limitations under the License.
25+
*/
26+
27+
//
28+
// Load the needed utilities.
29+
//
30+
import {Typeset} from '../mjs/util/Typeset.js';
31+
import {Util} from '../mjs/util/Util.js';
32+
import {Tex} from '../mjs/util/Tex.js';
33+
import {Mml} from '../mjs/util/Mml.js';
34+
import {Am} from '../mjs/util/Am.js';
35+
import {Chtml} from '../mjs/util/Chtml.js';
36+
import {Svg} from '../mjs/util/Svg.js';
37+
import {Sre} from '../mjs/util/Sre.js';
38+
39+
//
40+
// Load puppeteer support
41+
//
42+
import {Puppeteer} from './Puppeteer.js';
43+
44+
//
45+
// Get the command-line arguments.
46+
//
47+
const args = await Util.args(
48+
'"math or filename" > file',
49+
[Typeset, Tex, Mml.input, Am, Chtml, Svg, Mml.output, Sre, Puppeteer]
50+
);
51+
52+
Puppeteer.typeset(args)
53+
.then((output) => console.log(output))
54+
.catch(Puppeteer.error);

0 commit comments

Comments
 (0)