Skip to content

Commit 8d49fb5

Browse files
authored
Merge pull request #1068 from mathjax/sre-menus
Update MathJax contextual menus for assistive tools
2 parents f5d4f54 + 2c3f17c commit 8d49fb5

File tree

14 files changed

+331
-163
lines changed

14 files changed

+331
-163
lines changed

components/bin/build

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const EXPORTPATTERN =
3939
/(^export(?:\s+default)?(?:\s+abstract)?\s+(?:[^ {*}]+\s+(?:enum\s+)?[a-zA-Z0-9_.$]+|\{.* as .*\}))/m;
4040

4141
const EXPORT_IGNORE = ['type', 'interface'];
42-
const EXPORT_PROCESS = ['let', 'const', 'var', 'function', 'class', 'namespace', 'as'];
42+
const EXPORT_PROCESS = ['let', 'const', 'var', 'function', 'class', 'namespace', 'enum', 'as'];
4343

4444
/**
4545
* The module type to use ('cjs' or 'mjs')
@@ -159,7 +159,7 @@ function processParts(parts) {
159159
for (let i = 1; i < parts.length; i += 2) {
160160
const words = parts[i].split(/\s+/);
161161
const n = words.length;
162-
const type = (words[n - 2] === 'enum' ? words[n - 3] : words[n - 2]);
162+
const type = (words[n - 2] === 'enum' && n > 3 ? words[n - 3] : words[n - 2]);
163163
const name = words[n - 1].replace(/\}$/, '');
164164

165165
if (words[1] === 'default' || type === 'default') {

components/mjs/a11y/explorer/config.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"webpack": {
77
"name": "a11y/explorer",
88
"libs": [
9-
"components/src/ui/menu/lib",
109
"components/src/a11y/semantic-enrich/lib",
1110
"components/src/a11y/sre/lib",
1211
"components/src/input/mml/lib",
Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,7 @@
11
import './lib/explorer.js';
22

3-
import {combineDefaults} from '#js/components/global.js';
43
import {ExplorerHandler} from '#js/a11y/explorer.js';
54

65
if (MathJax.startup && typeof window !== 'undefined') {
7-
if (MathJax.config.options && MathJax.config.options.enableExplorer !== false) {
8-
combineDefaults(MathJax.config, 'options', {
9-
menuOptions: {
10-
settings: {
11-
explorer: true
12-
}
13-
}
14-
});
15-
}
166
MathJax.startup.extendHandler(handler => ExplorerHandler(handler));
177
}

components/mjs/a11y/semantic-enrich/config.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
{
22
"build": {
33
"component": "a11y/semantic-enrich",
4-
"targets": ["a11y/semantic-enrich.ts"]
4+
"targets": [
5+
"a11y/semantic-enrich.ts",
6+
"a11y/speech/SpeechUtil.ts",
7+
"a11y/speech/GeneratorPool.ts"
8+
]
59
},
610
"webpack": {
711
"name": "a11y/semantic-enrich",

components/mjs/dependencies.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
export const dependencies = {
1919
'a11y/semantic-enrich': ['input/mml', 'a11y/sre'],
2020
'a11y/complexity': ['a11y/semantic-enrich'],
21-
'a11y/explorer': ['a11y/semantic-enrich', 'ui/menu'],
21+
'a11y/explorer': ['a11y/semantic-enrich'],
2222
'[mml]/mml3': ['input/mml'],
2323
'[tex]/all-packages': ['input/tex-base'],
2424
'[tex]/action': ['input/tex-base', '[tex]/newcommand'],

components/mjs/ui/menu/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"build": {
33
"component": "ui/menu",
4-
"targets": ["ui/menu"],
4+
"targets": ["ui/menu", "a11y/speech/SpeechMenu.ts"],
55
"excludeSubdirs": true
66
},
77
"webpack": {

ts/a11y/explorer.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ export function ExplorerMathDocumentMixin<B extends MathDocumentConstructor<HTML
203203
align: 'top', // placement of magnified expression
204204
backgroundColor: 'Blue', // color for background of selected sub-expression
205205
backgroundOpacity: 20, // opacity for background of selected sub-expression
206-
braille: false, // switch on Braille output
206+
braille: true, // switch on Braille output
207207
flame: false, // color collapsible sub-expressions
208208
foregroundColor: 'Black', // color to use for text of selected sub-expression
209209
foregroundOpacity: 100, // opacity for text of selected sub-expression
@@ -219,7 +219,7 @@ export function ExplorerMathDocumentMixin<B extends MathDocumentConstructor<HTML
219219
speech: true, // switch on speech output
220220
subtitles: true, // show speech as a subtitle
221221
treeColoring: false, // tree color expression
222-
viewBraille: false, // display Braille output as subtitles
222+
viewBraille: true, // display Braille output as subtitles
223223
voicing: false, // switch on speech output
224224
}
225225
};
@@ -257,12 +257,6 @@ export function ExplorerMathDocumentMixin<B extends MathDocumentConstructor<HTML
257257
* @return {ExplorerMathDocument} The MathDocument (so calls can be chained)
258258
*/
259259
public explorable(): ExplorerMathDocument {
260-
if (this.options.a11y.speech) {
261-
this.options.enableSpeech = true;
262-
}
263-
if (this.options.a11y.braille) {
264-
this.options.enableBraille = true;
265-
}
266260
if (!this.processed.isSet('explorer')) {
267261
if (this.options.enableExplorer) {
268262
if (!this.explorerRegions) {
@@ -325,18 +319,13 @@ export function setA11yOptions(document: HTMLDOCUMENT, options: {[key: string]:
325319
for (let key in options) {
326320
if (document.options.a11y[key] !== undefined) {
327321
setA11yOption(document, key, options[key]);
328-
if (key === 'locale') {
329-
document.options.sre[key] = options[key];
330-
}
331-
continue;
332-
}
333-
if (sreOptions[key] !== undefined) {
322+
} else if (sreOptions[key] !== undefined) {
334323
document.options.sre[key] = options[key];
335324
}
336325
}
337326
// Reinit explorers
338327
for (let item of document.math) {
339-
(item as ExplorerMathItem).explorers.attach();
328+
(item as ExplorerMathItem)?.explorers?.attach();
340329
}
341330
}
342331

@@ -392,6 +381,10 @@ export function setA11yOption(document: HTMLDOCUMENT, option: string, value: str
392381
break;
393382
}
394383
break;
384+
case 'locale':
385+
document.options.sre.locale = value;
386+
document.options.a11y.locale = value;
387+
break;
395388
default:
396389
document.options.a11y[option] = value;
397390
}

ts/a11y/explorer/ExplorerPool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export class ExplorerPool {
216216
public attach() {
217217
this.attached = [];
218218
let keyExplorers = [];
219+
const a11y = this.document.options.a11y;
219220
for (let [key, explorer] of Object.entries(this.explorers)) {
220221
if (explorer instanceof SpeechExplorer) {
221222
explorer.AddEvents();
@@ -230,7 +231,7 @@ export class ExplorerPool {
230231
}
231232
continue;
232233
}
233-
if (this.document.options.a11y[key]) {
234+
if (a11y[key] || (key === 'speech' && (a11y.braille || a11y.keyMagnifier))) {
234235
explorer.Attach();
235236
this.attached.push(key);
236237
} else {

ts/a11y/explorer/KeyExplorer.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -478,26 +478,25 @@ export class SpeechExplorer extends AbstractExplorer<string> implements KeyExplo
478478
// the root node by default.
479479
this.current = this.node.childNodes[0] as HTMLElement;
480480
}
481+
const options = this.document.options;
481482
let promise = Sre.sreReady();
482-
if (this.generators.update(this.document.options)) {
483+
if (this.generators.update(options)) {
483484
promise = promise.then(
484485
() => this.Speech()
485486
);
486487
};
487488
this.current.setAttribute('tabindex', '0');
488489
this.current.focus();
489490
super.Start();
490-
if (this.document.options.a11y.speech &&
491-
this.document.options.a11y.subtitles) {
491+
if (options.a11y.subtitles && options.a11y.speech && options.enableSpeech) {
492492
promise.then(
493493
() => this.region.Show(this.node, this.highlighter));
494494
}
495-
if (this.document.options.a11y.braille &&
496-
this.document.options.a11y.viewBraille) {
495+
if (options.a11y.viewBraille && options.a11y.braille && options.enableBraille) {
497496
promise.then(
498497
() => this.brailleRegion.Show(this.node, this.highlighter));
499498
}
500-
if (this.document.options.a11y.keyMagnifier) {
499+
if (options.a11y.keyMagnifier) {
501500
this.magnifyRegion.Show(this.node, this.highlighter);
502501
}
503502
this.Update();

ts/a11y/semantic-enrich.ts

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ export interface EnrichedMathItem<N, T, D> extends MathItem<N, T, D> {
118118
* @param {MathDocument} document The document where enrichment is occurring
119119
*/
120120
attachSpeech(document: MathDocument<N, T, D>): void;
121+
122+
/**
123+
* @param {MathDocument} document The MathDocument for the MathItem
124+
*/
125+
unEnrich(document: MathDocument<N, T, D>): void;
121126
}
122127

123128
/**
@@ -201,6 +206,19 @@ export function EnrichedMathItemMixin<N, T, D, B extends Constructor<AbstractMat
201206
this.state(STATE.ENRICHED);
202207
}
203208

209+
/**
210+
* @param {MathDocument} document The MathDocument for the MathItem
211+
*/
212+
public unEnrich(document: MathDocument<N, T, D>) {
213+
const mml = this.inputData.originalMml;
214+
if (!mml) return;
215+
const math = new document.options.MathItem('', MmlJax);
216+
math.math = mml;
217+
math.display = this.display;
218+
math.compile(document);
219+
this.root = math.root;
220+
}
221+
204222
/**
205223
* Correct the selection values for the maction items from the original MathML
206224
*/
@@ -248,25 +266,28 @@ export function EnrichedMathItemMixin<N, T, D, B extends Constructor<AbstractMat
248266
if (this.isEscaped || !document.options.enableEnrichment) return;
249267
let [speech, braille] = this.existingSpeech();
250268
let [newSpeech, newBraille] = ['', ''];
251-
if ((!speech && document.options.enableSpeech) ||
252-
(!braille && document.options.enableBraille)) {
269+
const options = document.options;
270+
if ((!speech && options.enableSpeech) ||
271+
(!braille && options.enableBraille)) {
253272
try {
254273
[newSpeech, newBraille] = this.generatorPool.computeSpeech(
255274
this.typesetRoot, this.toMathML(this.root, this));
256275
if (newSpeech) {
257276
newSpeech = buildSpeech(newSpeech)[0];
258277
}
259-
} catch (_e) { }
278+
} catch (err) {
279+
document.options.speechError(document, this, err);
280+
}
260281
}
261282
speech = speech || newSpeech;
262283
braille = braille || newBraille;
263284
if (!speech && !braille) return;
264285
const adaptor = document.adaptor;
265286
const node = this.typesetRoot;
266-
if (speech && document.options.enableSpeech) {
287+
if (speech && options.enableSpeech) {
267288
adaptor.setAttribute(node, 'aria-label', speech as string);
268289
}
269-
if (braille && document.options.enableBraille) {
290+
if (braille && options.enableBraille) {
270291
adaptor.setAttribute(node, 'aria-braillelabel', braille as string);
271292
}
272293
for (const child of adaptor.childNodes(node) as N[]) {
@@ -311,6 +332,13 @@ export interface EnrichedMathDocument<N, T, D> extends AbstractMathDocument<N, T
311332
* @param {Error} err The error being processed
312333
*/
313334
enrichError(doc: EnrichedMathDocument<N, T, D>, math: EnrichedMathItem<N, T, D>, err: Error): void;
335+
336+
/**
337+
* @param {EnrichedMathDocument} doc The MathDocument for the error
338+
* @paarm {EnrichedMathItem} math The MathItem causing the error
339+
* @param {Error} err The error being processed
340+
*/
341+
speechError(doc: EnrichedMathDocument<N, T, D>, math: EnrichedMathItem<N, T, D>, err: Error): void;
314342
}
315343

316344
/**
@@ -343,6 +371,9 @@ export function EnrichedMathDocumentMixin<N, T, D, B extends MathDocumentConstru
343371
enrichError: (doc: EnrichedMathDocument<N, T, D>,
344372
math: EnrichedMathItem<N, T, D>,
345373
err: Error) => doc.enrichError(doc, math, err),
374+
speechError: (doc: EnrichedMathDocument<N, T, D>,
375+
math: EnrichedMathItem<N, T, D>,
376+
err: Error) => doc.speechError(doc, math, err),
346377
renderActions: expandable({
347378
...BaseDocument.OPTIONS.renderActions,
348379
enrich: [STATE.ENRICHED],
@@ -416,13 +447,24 @@ export function EnrichedMathDocumentMixin<N, T, D, B extends MathDocumentConstru
416447
console.warn('Enrichment error:', err);
417448
}
418449

450+
/**
451+
*/
452+
public speechError(_doc: EnrichedMathDocument<N, T, D>, _math: EnrichedMathItem<N, T, D>, err: Error) {
453+
console.warn('Speech generation error:', err);
454+
}
455+
419456
/**
420457
* @override
421458
*/
422459
public state(state: number, restore: boolean = false) {
423460
super.state(state, restore);
424461
if (state < STATE.ENRICHED) {
425462
this.processed.clear('enriched');
463+
if (state >= STATE.COMPILED) {
464+
for (const item of this.math) {
465+
(item as EnrichedMathItem<N, T, D>).unEnrich(this);
466+
}
467+
}
426468
}
427469
if (state < STATE.ATTACHSPEECH) {
428470
this.processed.clear('attach-speech');

0 commit comments

Comments
 (0)