@wiris/mathtype-viewer 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/WIRISplugins.js +7572 -0
- package/dist/app.d.ts +2 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/latex.d.ts +3 -0
- package/dist/latex.d.ts.map +1 -0
- package/dist/mathml.d.ts +3 -0
- package/dist/mathml.d.ts.map +1 -0
- package/dist/properties.d.ts +41 -0
- package/dist/properties.d.ts.map +1 -0
- package/dist/retro.d.ts +3 -0
- package/dist/retro.d.ts.map +1 -0
- package/dist/services.d.ts +16 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/docs/spec.md +73 -0
- package/index.html +1 -1
- package/package.json +3 -3
- package/project.json +29 -0
- package/src/app.ts +30 -23
- package/src/latex.ts +10 -8
- package/src/mathml.ts +17 -13
- package/src/properties.ts +53 -61
- package/src/retro.ts +255 -0
- package/src/utils.ts +45 -0
- package/typings/module-name.d.ts +2 -0
package/src/properties.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { configurationJson, StatusError } from './services';
|
|
2
2
|
|
|
3
3
|
// Helper types for Config below
|
|
4
|
-
type Viewer = 'image' | '
|
|
4
|
+
type Viewer = 'none' | 'image' | 'mathml' | 'latex';
|
|
5
5
|
type Wirispluginperformance = 'true' | 'false';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -41,20 +41,25 @@ const defaultValues: Config = {
|
|
|
41
41
|
/**
|
|
42
42
|
* This class will handle the parameters defined by the user.
|
|
43
43
|
*/
|
|
44
|
-
export
|
|
44
|
+
export class Properties {
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
render: () => Promise<void> = async () => {};
|
|
47
47
|
|
|
48
|
-
//
|
|
49
|
-
|
|
48
|
+
// Get URL properties (retrocompatibility).
|
|
49
|
+
config: Config = defaultValues;
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Do not use this method. Instead, use {@link Properties.generate}.
|
|
53
|
+
* Constructors cannot be async so we make it private and force instantiation through an alternative static method.
|
|
54
|
+
*/
|
|
55
|
+
private new() {}
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Creates and sets up a new instance of class Properties
|
|
59
|
+
*/
|
|
60
|
+
static async generate(): Promise<Properties> {
|
|
61
|
+
|
|
62
|
+
const instance = new Properties();
|
|
58
63
|
|
|
59
64
|
// Get URL parameters from <script>
|
|
60
65
|
const pluginName = 'WIRISplugins.js';
|
|
@@ -67,69 +72,58 @@ export abstract class Properties {
|
|
|
67
72
|
const urlParams = new URLSearchParams(params);
|
|
68
73
|
|
|
69
74
|
if (urlParams.get('dpi') !== null && urlParams.get('dpi') !== undefined) {
|
|
70
|
-
|
|
75
|
+
instance.config.dpi = +urlParams.get('dpi');
|
|
71
76
|
}
|
|
72
77
|
if (urlParams.get('element') !== null && urlParams.get('element') !== undefined) {
|
|
73
|
-
|
|
78
|
+
instance.config.element = urlParams.get('element');
|
|
74
79
|
}
|
|
75
80
|
if (urlParams.get('lang') !== null && urlParams.get('lang') !== undefined) {
|
|
76
|
-
|
|
81
|
+
instance.config.lang = urlParams.get('lang');
|
|
77
82
|
}
|
|
78
83
|
if (urlParams.get('viewer') !== null && urlParams.get('viewer') !== undefined) {
|
|
79
|
-
|
|
84
|
+
instance.config.viewer = (urlParams.get('viewer') as Viewer);
|
|
80
85
|
}
|
|
81
86
|
if (urlParams.get('zoom') !== null && urlParams.get('zoom') !== undefined) {
|
|
82
|
-
|
|
87
|
+
instance.config.zoom = +urlParams.get('zoom');
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
// Get backend parameters calling the configurationjson service
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
throw e;
|
|
101
|
-
}
|
|
102
|
-
} finally {
|
|
103
|
-
// Stop looking for the backend (even if the request fails)
|
|
104
|
-
this.backendObtained = true;
|
|
93
|
+
try {
|
|
94
|
+
instance.config.backendConfig = await configurationJson(
|
|
95
|
+
['wirispluginperformance', 'wiriseditormathmlattribute'],
|
|
96
|
+
instance.editorServicesRoot,
|
|
97
|
+
instance.editorServicesExtension,
|
|
98
|
+
);
|
|
99
|
+
} catch(e) {
|
|
100
|
+
if (e instanceof StatusError) {
|
|
101
|
+
// Do nothing; leave default values.
|
|
102
|
+
console.error(e);
|
|
103
|
+
} else {
|
|
104
|
+
throw e;
|
|
105
105
|
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
}
|
|
106
|
+
}
|
|
109
107
|
|
|
110
|
-
|
|
111
|
-
* Set the config values manually.
|
|
112
|
-
*/
|
|
113
|
-
static init(config: Config) {
|
|
114
|
-
Properties.config = {...defaultValues, ...config};
|
|
108
|
+
return instance;
|
|
115
109
|
}
|
|
116
110
|
|
|
117
|
-
|
|
111
|
+
get editorServicesRoot(): string {
|
|
118
112
|
return this.config.editorServicesRoot ||
|
|
119
113
|
defaultValues.editorServicesRoot;
|
|
120
114
|
}
|
|
121
115
|
|
|
122
|
-
|
|
116
|
+
set editorServicesRoot(editorServicesRoot: string) {
|
|
123
117
|
this.config.editorServicesRoot = editorServicesRoot;
|
|
124
118
|
this.render();
|
|
125
119
|
}
|
|
126
120
|
|
|
127
|
-
|
|
121
|
+
get editorServicesExtension(): string {
|
|
128
122
|
return this.config.editorServicesExtension ||
|
|
129
123
|
defaultValues.editorServicesExtension;
|
|
130
124
|
}
|
|
131
125
|
|
|
132
|
-
|
|
126
|
+
set editorServicesExtension(editorServicesExtension: string) {
|
|
133
127
|
this.config.editorServicesExtension = editorServicesExtension;
|
|
134
128
|
this.render();
|
|
135
129
|
}
|
|
@@ -143,7 +137,7 @@ export abstract class Properties {
|
|
|
143
137
|
* - English, by default.
|
|
144
138
|
* @returns {string} Encoded language string.
|
|
145
139
|
*/
|
|
146
|
-
|
|
140
|
+
get lang(): string {
|
|
147
141
|
const configLang = (this.config.lang === 'inherit') ? null : this.config.lang;
|
|
148
142
|
return configLang ||
|
|
149
143
|
document.getElementsByTagName('html')[0].lang ||
|
|
@@ -151,7 +145,7 @@ export abstract class Properties {
|
|
|
151
145
|
defaultValues.lang;
|
|
152
146
|
}
|
|
153
147
|
|
|
154
|
-
|
|
148
|
+
set lang(lang: string) {
|
|
155
149
|
this.config.lang = lang;
|
|
156
150
|
this.render();
|
|
157
151
|
}
|
|
@@ -162,12 +156,12 @@ export abstract class Properties {
|
|
|
162
156
|
* - The viewer parameter set in the <script> (WIRISplugin.js?viewer=...)
|
|
163
157
|
* - none, by default.
|
|
164
158
|
*/
|
|
165
|
-
|
|
159
|
+
get viewer(): Viewer {
|
|
166
160
|
return this.config.viewer ||
|
|
167
161
|
defaultValues.viewer;
|
|
168
162
|
}
|
|
169
163
|
|
|
170
|
-
|
|
164
|
+
set viewer(viewer: Viewer) {
|
|
171
165
|
this.config.viewer = viewer;
|
|
172
166
|
this.render();
|
|
173
167
|
}
|
|
@@ -178,12 +172,12 @@ export abstract class Properties {
|
|
|
178
172
|
* - The dpi parameter set in the <script> (WIRISplugin.js?dpi=...)
|
|
179
173
|
* - 96, by default.
|
|
180
174
|
*/
|
|
181
|
-
|
|
175
|
+
get dpi(): number {
|
|
182
176
|
return this.config.dpi ||
|
|
183
177
|
defaultValues.dpi;
|
|
184
178
|
}
|
|
185
179
|
|
|
186
|
-
|
|
180
|
+
set dpi(dpi: number) {
|
|
187
181
|
this.config.dpi = dpi;
|
|
188
182
|
this.render();
|
|
189
183
|
}
|
|
@@ -194,12 +188,12 @@ export abstract class Properties {
|
|
|
194
188
|
* - The zoom parameter set in the <script> (WIRISplugin.js?zoom=...)
|
|
195
189
|
* - 1, by default.
|
|
196
190
|
*/
|
|
197
|
-
|
|
191
|
+
get zoom(): number {
|
|
198
192
|
return this.config.zoom ||
|
|
199
193
|
defaultValues.zoom;
|
|
200
194
|
}
|
|
201
195
|
|
|
202
|
-
|
|
196
|
+
set zoom(zoom: number) {
|
|
203
197
|
this.config.zoom = zoom;
|
|
204
198
|
this.render();
|
|
205
199
|
}
|
|
@@ -210,12 +204,12 @@ export abstract class Properties {
|
|
|
210
204
|
* - The zoom parameter set in the <script> (WIRISplugin.js?element=...)
|
|
211
205
|
* - 'body', by default.
|
|
212
206
|
*/
|
|
213
|
-
|
|
207
|
+
get element(): string {
|
|
214
208
|
return this.config.element ||
|
|
215
209
|
defaultValues.element;
|
|
216
210
|
}
|
|
217
211
|
|
|
218
|
-
|
|
212
|
+
set element(element: string) {
|
|
219
213
|
this.config.element = element;
|
|
220
214
|
this.render();
|
|
221
215
|
}
|
|
@@ -226,13 +220,12 @@ export abstract class Properties {
|
|
|
226
220
|
* - The backend configuration of the parameter.
|
|
227
221
|
* - true, by default.
|
|
228
222
|
*/
|
|
229
|
-
|
|
230
|
-
this.waitForBackend();
|
|
223
|
+
get wirispluginperformance(): Wirispluginperformance {
|
|
231
224
|
return this.config.backendConfig.wirispluginperformance ||
|
|
232
225
|
defaultValues.backendConfig.wirispluginperformance;
|
|
233
226
|
}
|
|
234
227
|
|
|
235
|
-
|
|
228
|
+
set wirispluginperformance(wirispluginperformance: Wirispluginperformance) {
|
|
236
229
|
this.config.backendConfig.wirispluginperformance = wirispluginperformance;
|
|
237
230
|
this.render();
|
|
238
231
|
}
|
|
@@ -243,13 +236,12 @@ export abstract class Properties {
|
|
|
243
236
|
* - The backend configuration of the parameter.
|
|
244
237
|
* - data-mathml, by default.
|
|
245
238
|
*/
|
|
246
|
-
|
|
247
|
-
this.waitForBackend();
|
|
239
|
+
get wiriseditormathmlattribute(): string {
|
|
248
240
|
return this.config.backendConfig.wiriseditormathmlattribute ||
|
|
249
241
|
defaultValues.backendConfig.wiriseditormathmlattribute;
|
|
250
242
|
}
|
|
251
243
|
|
|
252
|
-
|
|
244
|
+
set wiriseditormathmlattribute(wiriseditormathmlattribute: string) {
|
|
253
245
|
this.config.backendConfig.wiriseditormathmlattribute = wiriseditormathmlattribute;
|
|
254
246
|
this.render();
|
|
255
247
|
}
|
package/src/retro.ts
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { renderLatex } from "./latex";
|
|
2
|
+
import { renderMathML } from "./mathml";
|
|
3
|
+
import { Properties } from "./properties";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Exposes the {@link JsPluginViewer} singleton instance as window.com.wiris.js.JsPluginViewer.
|
|
7
|
+
* @param {Properties} properties - Properties of the viewer.
|
|
8
|
+
* @param {Window} w - Instance of the global window.
|
|
9
|
+
* @deprecated Consider using {@link renderLatex} or {@link renderMathML}.
|
|
10
|
+
*/
|
|
11
|
+
export function bypassEncapsulation(properties: Properties, w: Window) {
|
|
12
|
+
const wany = w as any;
|
|
13
|
+
|
|
14
|
+
if (typeof wany.com === 'undefined') {
|
|
15
|
+
wany.com = {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (typeof wany.com.wiris === 'undefined') {
|
|
19
|
+
wany.com.wiris = {};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof wany.com.wiris.js === 'undefined') {
|
|
23
|
+
wany.com.wiris.js = {};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (typeof wany.com.wiris.js.JsPluginViewer === 'undefined') {
|
|
27
|
+
wany.com.wiris.js.JsPluginViewer = JsPluginViewer.getInstance();
|
|
28
|
+
JsPluginViewer.properties = properties;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* This class is a compatibility layer with the old Viewer.
|
|
34
|
+
* See haxe/src-haxe/com/wiris/js/JsPluginViewer.hx in in the repo wiris/plugins previous to commit df1248a.
|
|
35
|
+
*
|
|
36
|
+
* WARNING: the methods in this class may contain direct references to globals such as window and document.
|
|
37
|
+
*
|
|
38
|
+
* @deprecated Consider using {@link renderLatex} or {@link renderMathML}.
|
|
39
|
+
*/
|
|
40
|
+
class JsPluginViewer {
|
|
41
|
+
static instance: JsPluginViewer;
|
|
42
|
+
static properties: Properties;
|
|
43
|
+
|
|
44
|
+
static getInstance(): JsPluginViewer {
|
|
45
|
+
if (JsPluginViewer.instance == null) {
|
|
46
|
+
JsPluginViewer.instance = new JsPluginViewer();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return JsPluginViewer.instance;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Render all the formulas written in SafeMathML inside the given element.
|
|
54
|
+
* @param {HTMLElement} element - Element wherein to render SafeMathML formulas.
|
|
55
|
+
* @param asynchronously - Currently ignored, only included for retrocompatibility purposes.
|
|
56
|
+
* @param callbackFunc - Currently ignored, only included for retrocompatibility purposes.
|
|
57
|
+
* @deprecated There is currently no replacement for rendering SafeMathML formulas.
|
|
58
|
+
* Please consider using {@link renderLatex} or {@link renderMathML}.
|
|
59
|
+
*/
|
|
60
|
+
parseSafeMathMLElement(element: HTMLElement, asynchronously?: boolean, callbackFunc?: () => void): void {
|
|
61
|
+
var mathmlPositions = [];
|
|
62
|
+
JsPluginViewer.getMathMLPositionsAtElementAndChildren(element, mathmlPositions);
|
|
63
|
+
for (let i = 0; i < mathmlPositions.length; i++) {
|
|
64
|
+
var mathmlPosition = mathmlPositions[i];
|
|
65
|
+
var newNode = document.createElement("math");
|
|
66
|
+
mathmlPosition.nextElement.parentNode.insertBefore(newNode, mathmlPosition.nextElement);
|
|
67
|
+
newNode.outerHTML = JsPluginViewer.decodeSafeMathML(mathmlPosition.safeMML);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Render all the formulas in the document.
|
|
73
|
+
* @param asynchronously - Currently ignored, only included for retrocompatibility purposes.
|
|
74
|
+
* @param callbackFunc - Currently ignored, only included for retrocompatibility purposes.
|
|
75
|
+
* @param safeXml - Currently ignored, only included for retrocompatibility purposes.
|
|
76
|
+
* @deprecated Please consider using {@link renderMathML}.
|
|
77
|
+
*/
|
|
78
|
+
async parseDocument(asynchronously?: boolean, callbackFunc?: () => void, safeXml?: boolean): Promise<void> {
|
|
79
|
+
return renderMathML(JsPluginViewer.properties, document.documentElement);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Render all the formulas inside the given element.
|
|
84
|
+
* @param {HTMLElement} element - Element wherein to render formulas.
|
|
85
|
+
* @param asynchronously - Currently ignored, only included for retrocompatibility purposes.
|
|
86
|
+
* @param callbackFunc - Currently ignored, only included for retrocompatibility purposes.
|
|
87
|
+
* @deprecated Please consider using {@link renderMathML}.
|
|
88
|
+
*/
|
|
89
|
+
async parseElement(element: HTMLElement, asynchronously?: boolean, callbackFunc?: () => void): Promise<void> {
|
|
90
|
+
return renderMathML(JsPluginViewer.properties, element);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Convert all the LaTeX formulas in the document to MathML.
|
|
95
|
+
* @param asynchronously - Currently ignored, only included for retrocompatibility purposes.
|
|
96
|
+
* @param callbackFunc - Currently ignored, only included for retrocompatibility purposes.
|
|
97
|
+
* @deprecated Please consider using {@link renderLatex}.
|
|
98
|
+
*/
|
|
99
|
+
async parseLatexDocument(asynchronously?: boolean, callbackFunc?: () => void): Promise<void> {
|
|
100
|
+
return renderLatex(JsPluginViewer.properties, document.documentElement);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Convert all the LaTeX formulas inside the given element to MathML.
|
|
105
|
+
* @param {HTMLElement} element - Element wherein to convert formulas.
|
|
106
|
+
* @param asynchronously - Currently ignored, only included for retrocompatibility purposes.
|
|
107
|
+
* @param callbackFunc - Currently ignored, only included for retrocompatibility purposes.
|
|
108
|
+
* @deprecated Please consider using {@link renderLatex}.
|
|
109
|
+
*/
|
|
110
|
+
async parseLatexElement(element: HTMLElement, asynchronously?: boolean, callbackFunc?: () => void): Promise<void> {
|
|
111
|
+
return renderLatex(JsPluginViewer.properties, element);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private static decodeSafeMathML(input: string): string {
|
|
115
|
+
var safeXMLCharactersEntities = JsCharacters.getSafeXMLCharactersEntities();
|
|
116
|
+
var xmlCharacters = JsCharacters.getXMLCharacters();
|
|
117
|
+
var safeXMLCharacters = JsCharacters.getSafeXMLCharacters();
|
|
118
|
+
|
|
119
|
+
var tagOpenerEntity = safeXMLCharactersEntities.tagOpener;
|
|
120
|
+
var tagCloserEntity = safeXMLCharactersEntities.tagCloser;
|
|
121
|
+
var doubleQuoteEntity = safeXMLCharactersEntities.doubleQuote;
|
|
122
|
+
var realDoubleQuoteEntity = safeXMLCharactersEntities.realDoubleQuote;
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
// Important to not change function parameter.
|
|
126
|
+
var inputCopy = input.slice();
|
|
127
|
+
|
|
128
|
+
// Decoding entities.
|
|
129
|
+
inputCopy = inputCopy.split(tagOpenerEntity).join(safeXMLCharacters.tagOpener);
|
|
130
|
+
inputCopy = inputCopy.split(tagCloserEntity).join(safeXMLCharacters.tagCloser);
|
|
131
|
+
inputCopy = inputCopy.split(doubleQuoteEntity).join(safeXMLCharacters.doubleQuote);
|
|
132
|
+
inputCopy = inputCopy.split(realDoubleQuoteEntity).join(safeXMLCharacters.realDoubleQuote);
|
|
133
|
+
|
|
134
|
+
var tagOpener = safeXMLCharacters.tagOpener;
|
|
135
|
+
var tagCloser = safeXMLCharacters.tagCloser;
|
|
136
|
+
var doubleQuote = safeXMLCharacters.doubleQuote;
|
|
137
|
+
var realDoubleQuote = safeXMLCharacters.realDoubleQuote;
|
|
138
|
+
var ampersand = safeXMLCharacters.ampersand;
|
|
139
|
+
var quote = safeXMLCharacters.quote;
|
|
140
|
+
|
|
141
|
+
// Decoding characters.
|
|
142
|
+
inputCopy = inputCopy.split(tagOpener).join(xmlCharacters.tagOpener);
|
|
143
|
+
inputCopy = inputCopy.split(tagCloser).join(xmlCharacters.tagCloser);
|
|
144
|
+
inputCopy = inputCopy.split(doubleQuote).join(xmlCharacters.doubleQuote);
|
|
145
|
+
inputCopy = inputCopy.split(ampersand).join(xmlCharacters.ampersand);
|
|
146
|
+
inputCopy = inputCopy.split(quote).join(xmlCharacters.quote);
|
|
147
|
+
|
|
148
|
+
// We are replacing $ by & when its part of an entity for retrocompatibility.
|
|
149
|
+
// Now, the standard is replace § by &.
|
|
150
|
+
var returnValue = '';
|
|
151
|
+
var currentEntity = null;
|
|
152
|
+
|
|
153
|
+
var i = 0;
|
|
154
|
+
while (i < inputCopy.length) {
|
|
155
|
+
var character = inputCopy.charAt(i);
|
|
156
|
+
if (currentEntity == null) {
|
|
157
|
+
if (character == '$') {
|
|
158
|
+
currentEntity = '';
|
|
159
|
+
} else {
|
|
160
|
+
returnValue += character;
|
|
161
|
+
}
|
|
162
|
+
} else if (character == ';') {
|
|
163
|
+
returnValue += '&' + currentEntity;
|
|
164
|
+
currentEntity = null;
|
|
165
|
+
} else if (character.match(/([a-zA-Z0-9#._-] | '-')/)) { // Character is part of an entity.
|
|
166
|
+
currentEntity += character;
|
|
167
|
+
} else {
|
|
168
|
+
returnValue += '$' + 'currentEntity'; // Is not an entity.
|
|
169
|
+
currentEntity = null;
|
|
170
|
+
i -= 1; // Parse again the current character.
|
|
171
|
+
}
|
|
172
|
+
i++;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return returnValue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private static getMathMLPositionsAtElementAndChildren(element: Node, mathmlPositions) {
|
|
179
|
+
JsPluginViewer.getMathMLPositionsAtNode(element, mathmlPositions);
|
|
180
|
+
// Copy current children because DOM will be changed and element.childNodes won't be
|
|
181
|
+
// consistent on call getMathMLPositionsAtElementAndChildren().
|
|
182
|
+
var childNodes = Array.from(element.childNodes);
|
|
183
|
+
if (childNodes.length > 0) {
|
|
184
|
+
for (let i = 0; i < childNodes.length; i++) {
|
|
185
|
+
var child = childNodes[i];
|
|
186
|
+
JsPluginViewer.getMathMLPositionsAtElementAndChildren(child, mathmlPositions);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private static getMathMLPositionsAtNode(node: Node, mathmlPositions) {
|
|
192
|
+
var safeXMLCharacters = JsCharacters.getSafeXMLCharacters();
|
|
193
|
+
if(node.nodeType == 3) {
|
|
194
|
+
var startMathmlTag = safeXMLCharacters.tagOpener + "math";
|
|
195
|
+
var endMathmlTag = safeXMLCharacters.tagOpener + "/math" + safeXMLCharacters.tagCloser;
|
|
196
|
+
var start = node.textContent.indexOf(startMathmlTag);
|
|
197
|
+
var end = 0;
|
|
198
|
+
while(start != -1) {
|
|
199
|
+
end = node.textContent.indexOf(endMathmlTag,start + startMathmlTag.length);
|
|
200
|
+
|
|
201
|
+
if(end == -1) break;
|
|
202
|
+
|
|
203
|
+
var nextMathML = node.textContent.indexOf(startMathmlTag,end + endMathmlTag.length);
|
|
204
|
+
|
|
205
|
+
if(nextMathML >= 0 && end > nextMathML) break;
|
|
206
|
+
|
|
207
|
+
var safeMathml = node.textContent.substring(start,end + endMathmlTag.length);
|
|
208
|
+
|
|
209
|
+
node.textContent = node.textContent.substring(0,start) + node.textContent.substring(end + endMathmlTag.length);
|
|
210
|
+
node = (node as Text).splitText(start);
|
|
211
|
+
start = node.textContent.indexOf(startMathmlTag);
|
|
212
|
+
|
|
213
|
+
mathmlPositions.push({
|
|
214
|
+
safeMML: safeMathml,
|
|
215
|
+
nextElement: node
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
class JsCharacters {
|
|
224
|
+
static getSafeXMLCharactersEntities(): any {
|
|
225
|
+
return {
|
|
226
|
+
tagOpener: '«',
|
|
227
|
+
tagCloser: '»',
|
|
228
|
+
doubleQuote: '¨',
|
|
229
|
+
realDoubleQuote: '"',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
static getXMLCharacters(): any {
|
|
234
|
+
return {
|
|
235
|
+
id: 'xmlCharacters',
|
|
236
|
+
tagOpener: '<', // Hex: \x3C.
|
|
237
|
+
tagCloser: '>', // Hex: \x3E.
|
|
238
|
+
doubleQuote: '"', // Hex: \x22.
|
|
239
|
+
ampersand: '&', // Hex: \x26.
|
|
240
|
+
quote: '\'', // Hex: \x27.
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
static getSafeXMLCharacters(): any {
|
|
245
|
+
return {
|
|
246
|
+
id: 'safeXmlCharacters',
|
|
247
|
+
tagOpener: '«', // Hex: \xAB.
|
|
248
|
+
tagCloser: '»', // Hex: \xBB.
|
|
249
|
+
doubleQuote: '¨', // Hex: \xA8.
|
|
250
|
+
ampersand: '§', // Hex: \xA7.
|
|
251
|
+
quote: '`', // Hex: \x60.
|
|
252
|
+
realDoubleQuote: '¨',
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Takes a string possibly containing encoded entities (e.g.  ) and
|
|
3
|
+
* returns the same string with these replaced by the UTF-8 characters they represent
|
|
4
|
+
* @param {string} text - the string with encoded entities
|
|
5
|
+
* @returns the same string with the entities decoded
|
|
6
|
+
*/
|
|
7
|
+
function decodeEntities(text: string): string {
|
|
8
|
+
const element = document.createElement('textarea');
|
|
9
|
+
element.innerHTML = text;
|
|
10
|
+
return element.value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Takes a string possibly containing encoded named HTML entities (e.g. ) and
|
|
15
|
+
* returns the same string with these replaced by the encoding that uses numbers (e.g.  ).
|
|
16
|
+
* By its implementation, this method also possibly encodes special characters that were
|
|
17
|
+
* previously unencoded.
|
|
18
|
+
* @param {string} text - the string with encoded entities
|
|
19
|
+
* @returns the same string with the entities decoded
|
|
20
|
+
*/
|
|
21
|
+
export function htmlEntitiesToXmlEntities(text: string): string {
|
|
22
|
+
text = decodeEntities(text);
|
|
23
|
+
|
|
24
|
+
// Replaces the < & > characters to its HTMLEntity to avoid render issues.
|
|
25
|
+
text = text.split('"<"').join('"<"')
|
|
26
|
+
.split('">"')
|
|
27
|
+
.join('">"')
|
|
28
|
+
.split('><<')
|
|
29
|
+
.join('><<');
|
|
30
|
+
|
|
31
|
+
let result = '';
|
|
32
|
+
for (let i = 0; i < text.length; i++) {
|
|
33
|
+
const character = text.charAt(i);
|
|
34
|
+
if (text.charCodeAt(i) > 128) {
|
|
35
|
+
result += '&#' + text.charCodeAt(i) + ';';
|
|
36
|
+
} else {
|
|
37
|
+
result += character;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Set of mathml and characters which don't have an accessible text associated
|
|
44
|
+
// and can not be translated or transformed to LaTeX.
|
|
45
|
+
export const corruptMathML = ['⟦', '⟦', '⟧', '⟧', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow'];
|