@zzish/math-rich-input 0.1.5 → 0.1.7

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.
@@ -1,10 +1,10 @@
1
- import React from 'react'
1
+ import React from "react";
2
2
 
3
3
  import katex from "katex";
4
- import {setupKatex} from "./katexHelper"
4
+ import { setupKatex } from "./katexHelper";
5
5
 
6
- import EquationEditorModal from './EquationEditorModal';
7
- import Toolbar from './Toolbar'
6
+ import EquationEditorModal from "./EquationEditorModal";
7
+ import Toolbar from "./Toolbar";
8
8
 
9
9
  import {
10
10
  isKatexNode,
@@ -12,7 +12,7 @@ import {
12
12
  removeEncodingIfPlainText,
13
13
  rawTextToHtml,
14
14
  getLatex,
15
- setRangeParams,
15
+ setRangeParams,
16
16
  getRangeParams,
17
17
  getNodeTextLength,
18
18
  findNodeWithIndex,
@@ -25,51 +25,50 @@ import {
25
25
  replaceStringBeforeMarks,
26
26
  insertCharacterBeforeMarks,
27
27
  removeMarks,
28
- replaceMarksWithMath}
29
- from './mathRichInputHelper';
28
+ replaceMarksWithMath,
29
+ } from "./mathRichInputHelper";
30
30
 
31
- import './MathRichInput.css';
32
- import AccentBar from './AccentBar';
31
+ import "./MathRichInput.css";
32
+ import AccentBar from "./AccentBar";
33
33
 
34
- const MIME_TYPE_PLAIN_TEXT = "text/plain"
35
- const MIME_TYPE_HTML = "text/html"
36
- const MIME_TYPE_TEX = "application/x-tex"
37
- const MIME_TYPE_ZZISH_HTML_MATH = "application/x-zzish-html-math"
34
+ const MIME_TYPE_PLAIN_TEXT = "text/plain";
35
+ const MIME_TYPE_HTML = "text/html";
36
+ const MIME_TYPE_TEX = "application/x-tex";
37
+ const MIME_TYPE_ZZISH_HTML_MATH = "application/x-zzish-html-math";
38
38
 
39
- const SMALL_SPACE_CHAR_CODE = 8203
40
- const SMALL_SPACE = String.fromCharCode(SMALL_SPACE_CHAR_CODE)
41
- const SMALL_SPACE_LENGTH = SMALL_SPACE.length
39
+ const SMALL_SPACE_CHAR_CODE = 8203;
40
+ const SMALL_SPACE = String.fromCharCode(SMALL_SPACE_CHAR_CODE);
41
+ const SMALL_SPACE_LENGTH = SMALL_SPACE.length;
42
42
  // const SMALL_SPACE_REG_EXP = new RegExp(SMALL_SPACE, "g")
43
43
 
44
- const MARK = "_M_A_R_K_"
45
- const MARK_REG_EXP = new RegExp(MARK, "g")
44
+ const MARK = "_M_A_R_K_";
45
+ const MARK_REG_EXP = new RegExp(MARK, "g");
46
46
 
47
47
  // const LATEX_MARKER_START = "<annotation encoding=\"application/x-tex\">"
48
48
  // const LATEX_MARKER_END = "</annotation>"
49
49
 
50
- const MAX_HISTORY_LENGTH = 100
50
+ const MAX_HISTORY_LENGTH = 100;
51
51
 
52
52
  const DEFAULT_OPTIONS = {
53
- useExpertMode:false,
54
- selectedTab: null
55
- }
53
+ useExpertMode: false,
54
+ selectedTab: null,
55
+ };
56
56
 
57
57
  export default class MathRichInput extends React.Component {
58
-
59
58
  constructor(props) {
60
59
  super(props);
61
60
  this.state = {
62
61
  showEquationEditor: false,
63
62
  equationEditorLatex: "",
64
- showAccentBar:false,
63
+ showAccentBar: false,
65
64
  activeButtons: {
66
65
  bold: false,
67
66
  italic: false,
68
67
  underline: false,
69
68
  subscript: false,
70
- superscript: false
69
+ superscript: false,
71
70
  },
72
- keyPressed:""
71
+ keyPressed: "",
73
72
  };
74
73
 
75
74
  // this.handleInput = this.handleInput.bind(this);
@@ -77,66 +76,81 @@ export default class MathRichInput extends React.Component {
77
76
  // this.handleKeyUp = this.handleKeyUp.bind(this);
78
77
 
79
78
  // Remember the last key pressed
80
- this.keyPressed = null;
79
+ this.keyPressed = null;
81
80
  this.keyPressStartTime = -1;
82
81
 
83
82
  // This gets updated in coomponent did mount, used to position the toolbar correctly
84
- this.translateToolbar = "";
83
+ this.translateToolbar = "";
85
84
 
86
85
  // Whether the text contains HTML or Maths
87
- this.isHtml = false
88
- this.hasMath = false
86
+ this.isHtml = false;
87
+ this.hasMath = false;
89
88
 
90
89
  // Elements that need to be set before the equation editor is shown
91
- this.markedRawText = null
92
- this.oldRangeParams = {startNodeIndex:0,startOffset:0,endNodeIndex:0,endOffset:0};
93
- this.moveCursorOnInsert = false
90
+ this.markedRawText = null;
91
+ this.oldRangeParams = {
92
+ startNodeIndex: 0,
93
+ startOffset: 0,
94
+ endNodeIndex: 0,
95
+ endOffset: 0,
96
+ };
97
+ this.moveCursorOnInsert = false;
94
98
 
95
99
  // Elements defining the current state of range
96
- this.rangeParamsToSetAfterComponentUpdate = null // Set this to update the selection after rendering
97
- this.lastSetRangeParmas = null // This is set automatically each time the range params are set with setRangeParams
100
+ this.rangeParamsToSetAfterComponentUpdate = null; // Set this to update the selection after rendering
101
+ this.lastSetRangeParmas = null; // This is set automatically each time the range params are set with setRangeParams
98
102
 
99
- this.lastSetActiveButtons = null
103
+ this.lastSetActiveButtons = null;
100
104
 
101
- this.onChangeCallback = this.props.onChange
105
+ this.onChangeCallback = this.props.onChange;
102
106
 
103
107
  // set the initialHistoryState the first time an action is done that allows us to identify the cursor position
104
108
  // 1. When the first mouse click is released (see onMouseUp)
105
109
  // 2. When the first key is pressed (see handleKeyDown)
106
- this.initialHistoryState = null
107
- this.undoHistory = []
108
- this.redoHistory = []
110
+ this.initialHistoryState = null;
111
+ this.undoHistory = [];
112
+ this.redoHistory = [];
109
113
  }
110
114
 
111
115
  enableFontStyling() {
112
- if (this.props.outputTex !== null && this.props.outputTex !== undefined &&
113
- this.props.outputTex === true)
114
- return false
115
- else if (this.props.enableFontStyling !== null && this.props.enableFontStyling !== undefined)
116
- return this.props.enableFontStyling
117
- else
118
- return true
116
+ if (
117
+ this.props.outputTex !== null &&
118
+ this.props.outputTex !== undefined &&
119
+ this.props.outputTex === true
120
+ )
121
+ return false;
122
+ else if (
123
+ this.props.enableFontStyling !== null &&
124
+ this.props.enableFontStyling !== undefined
125
+ )
126
+ return this.props.enableFontStyling;
127
+ else return true;
119
128
  }
120
129
 
121
130
  enableMultiline() {
122
- if (this.props.outputTex !== null && this.props.outputTex !== undefined &&
123
- this.props.outputTex === true)
124
- return false
125
- else if (this.props.enableMultiline !== null && this.props.enableMultiline !== undefined)
126
- return this.props.enableMultiline
127
- else
128
- return true
131
+ if (
132
+ this.props.outputTex !== null &&
133
+ this.props.outputTex !== undefined &&
134
+ this.props.outputTex === true
135
+ )
136
+ return false;
137
+ else if (
138
+ this.props.enableMultiline !== null &&
139
+ this.props.enableMultiline !== undefined
140
+ )
141
+ return this.props.enableMultiline;
142
+ else return true;
129
143
  }
130
144
 
131
145
  enableHtml() {
132
- let outputTex = this.props.outputTex ?? false
133
- return !outputTex
146
+ let outputTex = this.props.outputTex ?? false;
147
+ return !outputTex;
134
148
  }
135
149
 
136
150
  enableMath() {
137
151
  if (this.props.enableMath !== null && this.props.enableMath !== undefined)
138
- return this.props.enableMath
139
- return true
152
+ return this.props.enableMath;
153
+ return true;
140
154
  }
141
155
 
142
156
  // static isHtml(text) {
@@ -147,33 +161,34 @@ export default class MathRichInput extends React.Component {
147
161
  // /<\s*sup[^>]*>(.*?)<\s*\/\s*sup\s*>/i.test(text) ||
148
162
  // /<\s*sub[^>]*>(.*?)<\s*\/\s*sub\s*>/i.test(text)
149
163
  // }
150
-
164
+
151
165
  getMimeType(hasHtml, hasMath) {
152
- let outputTex = this.props.outputTex ?? false
153
- let outputPlainText = this.props.outputPlainText ?? false
154
-
166
+ let outputTex = this.props.outputTex ?? false;
167
+ let outputPlainText = this.props.outputPlainText ?? false;
168
+
155
169
  if (outputTex) {
156
- if (hasMath || !outputPlainText)
157
- return MIME_TYPE_TEX
158
- else
159
- return MIME_TYPE_PLAIN_TEXT
170
+ if (hasMath || !outputPlainText) return MIME_TYPE_TEX;
171
+ else return MIME_TYPE_PLAIN_TEXT;
160
172
  }
161
173
 
162
- if (hasMath)
163
- return MIME_TYPE_ZZISH_HTML_MATH
164
- if (hasHtml || !outputPlainText)
165
- return MIME_TYPE_HTML
174
+ if (hasMath) return MIME_TYPE_ZZISH_HTML_MATH;
175
+ if (hasHtml || !outputPlainText) return MIME_TYPE_HTML;
166
176
 
167
- return MIME_TYPE_PLAIN_TEXT
177
+ return MIME_TYPE_PLAIN_TEXT;
168
178
  }
169
179
 
170
180
  _countNodeTypes = () => {
171
- return countNodeTypes(this.editableDiv)
172
- }
173
-
174
- applyChangesToComponent = (value, mimeType, rangeParams,
175
- isExpertMode, selectedTab) => {
176
- console.log("applyChangesToComponent")
181
+ return countNodeTypes(this.editableDiv);
182
+ };
183
+
184
+ applyChangesToComponent = (
185
+ value,
186
+ mimeType,
187
+ rangeParams,
188
+ isExpertMode,
189
+ selectedTab
190
+ ) => {
191
+ console.log("applyChangesToComponent");
177
192
 
178
193
  // if (this.props.outputTex !== null && this.props.outputTex !== undefined && this.props.outputTex) {
179
194
  // if (mimeType === MIME_TYPE_HTML) {
@@ -185,163 +200,179 @@ export default class MathRichInput extends React.Component {
185
200
  // mimeType = MIME_TYPE_TEX
186
201
  // }
187
202
  // }
188
-
203
+
189
204
  // rangeParams, isExpertMode and selectedTab can be null, in which case we will set them
190
- if (rangeParams === null)
191
- rangeParams = this.lastSetRangeParams
192
- else
193
- this.rangeParamsToSetAfterComponentUpdate = rangeParams
194
-
195
- let options = this.props.options || DEFAULT_OPTIONS
196
- if (isExpertMode === null)
197
- isExpertMode = options.isExpertMode
198
- if (selectedTab === null)
199
- selectedTab = options.selectedTab
200
-
205
+ if (rangeParams === null) rangeParams = this.lastSetRangeParams;
206
+ else this.rangeParamsToSetAfterComponentUpdate = rangeParams;
207
+
208
+ let options = this.props.options || DEFAULT_OPTIONS;
209
+ if (isExpertMode === null) isExpertMode = options.isExpertMode;
210
+ if (selectedTab === null) selectedTab = options.selectedTab;
211
+
201
212
  // Add this to the history
202
- this.undoHistory.push({value, mimeType, rangeParams})
203
- if (this.undoHistory.length > MAX_HISTORY_LENGTH)
204
- this.undoHistory.shift()
213
+ this.undoHistory.push({ value, mimeType, rangeParams });
214
+ if (this.undoHistory.length > MAX_HISTORY_LENGTH) this.undoHistory.shift();
205
215
 
206
216
  // Call the parent handler to apply the changes
207
- this.onChangeCallback({value, mimeType},
208
- {isExpertMode, selectedTab})
209
- }
217
+ this.onChangeCallback({ value, mimeType }, { isExpertMode, selectedTab });
218
+ };
210
219
 
211
220
  initialiseHistory = () => {
212
221
  if (this.initialHistoryState == null)
213
- this.initialHistoryState = {value:this.props.value,
214
- mimeType:this.props.mimeType,
215
- rangeParams:this._getRangeParams()}
216
- }
222
+ this.initialHistoryState = {
223
+ value: this.props.value,
224
+ mimeType: this.props.mimeType,
225
+ rangeParams: this._getRangeParams(),
226
+ };
227
+ };
217
228
 
218
229
  resetHistoryRedo = () => {
219
- this.redoHistory = []
220
- }
230
+ this.redoHistory = [];
231
+ };
221
232
 
222
233
  deepEqual = (v1, v2) => {
223
- if (v1 === v2) return true
234
+ if (v1 === v2) return true;
235
+
236
+ if (
237
+ v1 == null ||
238
+ v2 == null ||
239
+ typeof v1 != "object" ||
240
+ typeof v2 != "object"
241
+ )
242
+ return false;
224
243
 
225
- if (v1 == null || v2 == null || typeof v1 != "object" || typeof v2 != "object") return false
244
+ let v1keys = Object.keys(v1);
245
+ let v2keys = Object.keys(v2);
246
+ if (v1keys.length !== v2keys.length) return false;
226
247
 
227
- let v1keys = Object.keys(v1)
228
- let v2keys = Object.keys(v2)
229
- if (v1keys.length !== v2keys.length) return false
230
-
231
248
  for (let key of v1keys) {
232
- if (!v2keys.includes(key) || !this.deepEqual(v1[key], v2[key])) return false
249
+ if (!v2keys.includes(key) || !this.deepEqual(v1[key], v2[key]))
250
+ return false;
233
251
  }
234
- return true
235
- }
252
+ return true;
253
+ };
236
254
 
237
255
  undo = () => {
238
- console.log("undo")
239
- console.log(this.undoHistory)
240
- const currentState = this.undoHistory.pop()
241
-
242
- let previousState = this.undoHistory.pop()
256
+ console.log("undo");
257
+ console.log(this.undoHistory);
258
+ const currentState = this.undoHistory.pop();
259
+
260
+ let previousState = this.undoHistory.pop();
243
261
  if (previousState === null || previousState === undefined) {
244
- previousState = this.initialHistoryState
262
+ previousState = this.initialHistoryState;
245
263
  }
246
264
 
247
265
  if (this.redoHistory.length > 0) {
248
- let redoLast = this.redoHistory[this.redoHistory.length-1]
266
+ let redoLast = this.redoHistory[this.redoHistory.length - 1];
249
267
  if (!this.deepEqual(redoLast, currentState))
250
- this.redoHistory.push(currentState)
251
- } else
252
- this.redoHistory.push(currentState)
253
-
254
- console.log(previousState)
268
+ this.redoHistory.push(currentState);
269
+ } else this.redoHistory.push(currentState);
255
270
 
256
- this.applyChangesToComponent(previousState.value, previousState.mimeType, previousState.rangeParams)
257
- }
271
+ console.log(previousState);
272
+
273
+ this.applyChangesToComponent(
274
+ previousState.value,
275
+ previousState.mimeType,
276
+ previousState.rangeParams
277
+ );
278
+ };
258
279
 
259
280
  redo = () => {
260
- const redoState = this.redoHistory.pop()
261
- if (redoState !== null & redoState !== undefined) {
262
- this.applyChangesToComponent(redoState.value, redoState.mimeType, redoState.rangeParams)
281
+ const redoState = this.redoHistory.pop();
282
+ if ((redoState !== null) & (redoState !== undefined)) {
283
+ this.applyChangesToComponent(
284
+ redoState.value,
285
+ redoState.mimeType,
286
+ redoState.rangeParams
287
+ );
263
288
  }
264
- }
289
+ };
265
290
 
266
291
  setOldRangeParams(params) {
267
292
  // console.log("Setting old range params: "+params.startNodeIndex+"->"+params.startOffset)
268
- this.oldRangeParams = params
293
+ this.oldRangeParams = params;
269
294
  }
270
295
 
271
296
  getOldRangeParams() {
272
297
  if (this.oldRangeParams === null || this.oldRangeParams === undefined)
273
- return null
274
- let params = {...this.oldRangeParams}
298
+ return null;
299
+ let params = { ...this.oldRangeParams };
275
300
  // console.log("Getting old range params: "+params.startNodeIndex+"->"+params.startOffset)
276
- return params
301
+ return params;
277
302
  }
278
303
 
279
- _getRangeParams(editableDiv=null) {
304
+ _getRangeParams(editableDiv = null) {
280
305
  // console.log("_getRangeParams")
281
- if (editableDiv === null)
282
- editableDiv = this.editableDiv
283
- let rangeParams = getRangeParams(editableDiv)
306
+ if (editableDiv === null) editableDiv = this.editableDiv;
307
+ let rangeParams = getRangeParams(editableDiv);
284
308
  // console.log(rangeParams)
285
- return rangeParams
309
+ return rangeParams;
286
310
  }
287
311
 
288
312
  _setRangeParams = (params) => {
289
313
  try {
290
- console.log("_setRangeParams")
291
- console.log(params)
292
- setRangeParams(this.editableDiv, params)
314
+ console.log("_setRangeParams");
315
+ console.log(params);
316
+ setRangeParams(this.editableDiv, params);
293
317
 
294
- this.setOldRangeParams(params)
295
- this.lastSetRangeParmas = params
318
+ this.setOldRangeParams(params);
319
+ this.lastSetRangeParmas = params;
296
320
  } catch (error) {
297
- console.error(error)
298
- console.log(this.editableDiv.childNodes)
321
+ console.error(error);
322
+ console.log(this.editableDiv.childNodes);
299
323
  }
300
- }
324
+ };
301
325
 
302
326
  _findNodeWithIndex(index) {
303
- return findNodeWithIndex(this.editableDiv, index)
327
+ return findNodeWithIndex(this.editableDiv, index);
304
328
  }
305
329
 
306
330
  _findIndexOfNode(node) {
307
- return findIndexOfNode(this.editableDiv, node)
331
+ return findIndexOfNode(this.editableDiv, node);
308
332
  }
309
333
 
310
334
  _findFirstTextNode() {
311
- return findFirstTextNode(this.editableDiv)
335
+ return findFirstTextNode(this.editableDiv);
312
336
  }
313
337
 
314
338
  handleKeyDownBackspace = (e) => {
315
- let rangeParams = this._getRangeParams()
316
- let start_node_index = rangeParams.startNodeIndex
317
- let end_node_index = rangeParams.endNodeIndex
318
- let start_offset = rangeParams.startOffset
319
- let end_offset = rangeParams.endOffset
320
-
321
- if (start_node_index < 0) // Empty input field
322
- return
323
-
324
- let startNode = this._findNodeWithIndex(start_node_index)
325
- let endNode = this._findNodeWithIndex(end_node_index)
326
-
339
+ let rangeParams = this._getRangeParams();
340
+ let start_node_index = rangeParams.startNodeIndex;
341
+ let end_node_index = rangeParams.endNodeIndex;
342
+ let start_offset = rangeParams.startOffset;
343
+ let end_offset = rangeParams.endOffset;
344
+
345
+ if (start_node_index < 0)
346
+ // Empty input field
347
+ return;
348
+
349
+ let startNode = this._findNodeWithIndex(start_node_index);
350
+ let endNode = this._findNodeWithIndex(end_node_index);
351
+
327
352
  // Prevent backspace if start or end of selected region is in a katex node
328
353
  if (isKatexNode(startNode) || isKatexNode(endNode)) {
329
- console.error("Backspace inside latex node. This shouln't happen.")
330
- e.preventDefault()
354
+ console.error("Backspace inside latex node. This shouln't happen.");
355
+ e.preventDefault();
331
356
  }
332
357
 
333
358
  // Handle special case of deleting last character when in bold etc text
334
359
  // in order to resolve a bug
335
- let deleteToEmpty = false
336
- if (start_node_index === 0 && start_offset === 1 &&
337
- end_node_index === 0 && end_offset === 1) {
360
+ let deleteToEmpty = false;
361
+ if (
362
+ start_node_index === 0 &&
363
+ start_offset === 1 &&
364
+ end_node_index === 0 &&
365
+ end_offset === 1
366
+ ) {
338
367
  if (!isKatexNode(startNode) && getNodeTextLength(startNode) === 1)
339
- deleteToEmpty = true
368
+ deleteToEmpty = true;
340
369
  }
341
370
  if (start_node_index === 0 && start_offset === 0 && end_node_index !== 0) {
342
- if (getNodeTextLength(endNode) === end_offset &&
343
- this._findNodeWithIndex(end_node_index + 1) === null)
344
- deleteToEmpty = true
371
+ if (
372
+ getNodeTextLength(endNode) === end_offset &&
373
+ this._findNodeWithIndex(end_node_index + 1) === null
374
+ )
375
+ deleteToEmpty = true;
345
376
  }
346
377
 
347
378
  if (deleteToEmpty) {
@@ -349,32 +380,37 @@ export default class MathRichInput extends React.Component {
349
380
  startNodeIndex: 0,
350
381
  startOffset: 0,
351
382
  endNodeIndex: 0,
352
- endOffset: 0
353
- }
354
- this.applyChangesToComponent("", MIME_TYPE_PLAIN_TEXT, new_rangeParams,
355
- this.props.useExpertMode, this.props.selectedTab)
356
- return
383
+ endOffset: 0,
384
+ };
385
+ this.applyChangesToComponent(
386
+ "",
387
+ MIME_TYPE_PLAIN_TEXT,
388
+ new_rangeParams,
389
+ this.props.useExpertMode,
390
+ this.props.selectedTab
391
+ );
392
+ return;
357
393
  }
358
394
 
359
395
  // Treat backspace normally in the following situations
360
- if (start_offset > 1)
361
- return
362
- if (start_node_index <= 0)
363
- return
364
- if (start_node_index !== rangeParams.endNodeIndex ||
365
- start_offset !== rangeParams.endOffset)
366
- return
367
-
396
+ if (start_offset > 1) return;
397
+ if (start_node_index <= 0) return;
398
+ if (
399
+ start_node_index !== rangeParams.endNodeIndex ||
400
+ start_offset !== rangeParams.endOffset
401
+ )
402
+ return;
403
+
368
404
  // At this point we must have start_offset === 0 or 1 and a previous node
369
405
 
370
- let prevNode = this._findNodeWithIndex(start_node_index-1)
406
+ let prevNode = this._findNodeWithIndex(start_node_index - 1);
371
407
 
372
408
  if (!isKatexNode(prevNode)) {
373
409
  if (this.nodeStartsWithSmallSpace(startNode)) {
374
- this.removeNewLine()
375
- e.preventDefault()
410
+ this.removeNewLine();
411
+ e.preventDefault();
376
412
  }
377
- return
413
+ return;
378
414
  }
379
415
 
380
416
  // The previous node is a katex node
@@ -383,994 +419,1120 @@ export default class MathRichInput extends React.Component {
383
419
  // console.log("Deleting content before: "+start_node_index+"->"+start_offset)
384
420
  // console.log(rangeParams)
385
421
 
386
- let node = prevNode
422
+ let node = prevNode;
387
423
  let new_index = 0;
388
424
  let new_offset = 0;
389
425
 
390
- // Note that if startNodeIndex == 2, then that means that the latex node is at the start
426
+ // Note that if startNodeIndex == 2, then that means that the latex node is at the start
391
427
  // of the whole input at index 1. This is because we insert a SMALL_SPACE
392
428
  // at the beginning in index 0, if the whole input starts with a latex node
393
429
  if (start_node_index === 2) {
394
430
  if (this.inputStartsWithSmallSpace()) {
395
- new_index = 0
396
- new_offset = 0
431
+ new_index = 0;
432
+ new_offset = 0;
397
433
  } else {
398
- new_index = 0
399
- new_offset = getNodeTextLength(this._findFirstTextNode())
434
+ new_index = 0;
435
+ new_offset = getNodeTextLength(this._findFirstTextNode());
400
436
  }
401
437
  } else {
402
- new_index = start_node_index - 2
403
- let new_node = this._findNodeWithIndex(new_index)
438
+ new_index = start_node_index - 2;
439
+ let new_node = this._findNodeWithIndex(new_index);
404
440
  if (isKatexNode(new_node)) {
405
- console.error("Two adjacent latex nodes. This should not happen!")
406
- new_index = 0
407
- new_offset = 0
441
+ console.error("Two adjacent latex nodes. This should not happen!");
442
+ new_index = 0;
443
+ new_offset = 0;
408
444
  }
409
- new_node = this._findNodeWithIndex(new_index)
410
- new_offset = getNodeTextLength(new_node)
411
- if (new_offset < 0)
412
- new_offset = 0
445
+ new_node = this._findNodeWithIndex(new_index);
446
+ new_offset = getNodeTextLength(new_node);
447
+ if (new_offset < 0) new_offset = 0;
413
448
  }
414
449
 
415
450
  let new_rangeParams = {
416
451
  startNodeIndex: new_index,
417
452
  startOffset: new_offset,
418
453
  endNodeIndex: new_index,
419
- endOffset: new_offset
420
- }
454
+ endOffset: new_offset,
455
+ };
421
456
 
422
457
  // OK, time to delete the katex node!
423
- node.parentNode.removeChild(node)
424
- let raw_text = elementToMarkedRawText(this.editableDiv, null, 0, this.enableHtml())
458
+ node.parentNode.removeChild(node);
459
+ let raw_text = elementToMarkedRawText(
460
+ this.editableDiv,
461
+ null,
462
+ 0,
463
+ this.enableHtml()
464
+ );
425
465
  // console.log("After deleting katex: "+raw_text)
426
466
 
427
- let nodeCounts = this._countNodeTypes()
428
- let mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.math > 0)
429
- raw_text = removeEncodingIfPlainText(raw_text, mimeType, this.enableHtml())
467
+ let nodeCounts = this._countNodeTypes();
468
+ let mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.math > 0);
469
+ raw_text = removeEncodingIfPlainText(raw_text, mimeType, this.enableHtml());
470
+
471
+ this.applyChangesToComponent(
472
+ raw_text,
473
+ mimeType,
474
+ new_rangeParams,
475
+ this.props.useExpertMode,
476
+ this.props.selectedTab
477
+ );
430
478
 
431
- this.applyChangesToComponent(raw_text, mimeType, new_rangeParams,
432
- this.props.useExpertMode, this.props.selectedTab)
433
-
434
479
  // Consume the event
435
- e.preventDefault()
436
- }
480
+ e.preventDefault();
481
+ };
437
482
 
438
483
  nodeStartsWithSmallSpace(node) {
439
- if(node.nodeValue !== null && node.nodeValue !== undefined && node.nodeValue.length > 0 &&
440
- node.nodeValue.charAt(0) === SMALL_SPACE)
441
- return true
442
-
443
- return false
484
+ if (
485
+ node.nodeValue !== null &&
486
+ node.nodeValue !== undefined &&
487
+ node.nodeValue.length > 0 &&
488
+ node.nodeValue.charAt(0) === SMALL_SPACE
489
+ )
490
+ return true;
491
+
492
+ return false;
444
493
  }
445
494
 
446
495
  inputStartsWithSmallSpace = () => {
447
- return startsWithSmallSpace(this.editableDiv)
448
- }
496
+ return startsWithSmallSpace(this.editableDiv);
497
+ };
449
498
 
450
499
  handleKeyDownArrowLeft = (e) => {
451
- let rangeParams = this._getRangeParams()
452
- let index = rangeParams.startNodeIndex
453
- let offset = rangeParams.startOffset
500
+ let rangeParams = this._getRangeParams();
501
+ let index = rangeParams.startNodeIndex;
502
+ let offset = rangeParams.startOffset;
454
503
 
455
504
  // console.log("Old: "+index+"->"+offset)
456
-
505
+
457
506
  // The user shouldn't be in a katex node, but lets deal with it anyway
458
- let node = this._findNodeWithIndex(index)
507
+ let node = this._findNodeWithIndex(index);
459
508
  if (isKatexNode(node)) {
460
- console.warn("Cursor is inside katex node")
461
- let new_index = index-1 // Jump out of the latex node
462
- let prev_node = this._findNodeWithIndex(index-1)
463
- let new_offset = getNodeTextLength(prev_node)
509
+ console.warn("Cursor is inside katex node");
510
+ let new_index = index - 1; // Jump out of the latex node
511
+ let prev_node = this._findNodeWithIndex(index - 1);
512
+ let new_offset = getNodeTextLength(prev_node);
464
513
 
465
514
  let new_rangeParams = {
466
515
  startNodeIndex: new_index,
467
516
  startOffset: new_offset,
468
517
  endNodeIndex: new_index,
469
- endOffset: new_offset
470
- }
471
- this._setRangeParams(new_rangeParams)
472
- e.preventDefault()
473
- return
518
+ endOffset: new_offset,
519
+ };
520
+ this._setRangeParams(new_rangeParams);
521
+ e.preventDefault();
522
+ return;
474
523
  }
475
524
 
476
- if (offset > 2)
477
- return
525
+ if (offset > 2) return;
478
526
 
479
- let new_index = -1
480
- let new_offset = -1
527
+ let new_index = -1;
528
+ let new_offset = -1;
481
529
 
482
530
  // Deal with case of inserted small space at start of <p> element or after katex node
483
531
  if (offset === 2) {
484
- new_index = index
532
+ new_index = index;
485
533
  if (this.nodeStartsWithSmallSpace(node)) {
486
- if (index > 0 && isKatexNode(this._findNodeWithIndex(index-1)))
487
- new_offset = 1
488
- else
489
- new_offset = 0
490
- } else
491
- new_offset = 1
534
+ if (index > 0 && isKatexNode(this._findNodeWithIndex(index - 1)))
535
+ new_offset = 1;
536
+ else new_offset = 0;
537
+ } else new_offset = 1;
492
538
  }
493
-
539
+
494
540
  if (offset === 1) {
495
541
  if (this.nodeStartsWithSmallSpace(node)) {
496
542
  if (index === 0) {
497
- e.preventDefault()
498
- return
543
+ e.preventDefault();
544
+ return;
499
545
  }
500
- let prev_node = this._findNodeWithIndex(index-1)
501
- if (index >= 2 && isKatexNode(prev_node))
502
- new_index = index - 2
503
- else
504
- new_index = index - 1
546
+ let prev_node = this._findNodeWithIndex(index - 1);
547
+ if (index >= 2 && isKatexNode(prev_node)) new_index = index - 2;
548
+ else new_index = index - 1;
505
549
 
506
- let new_node = this._findNodeWithIndex(new_index)
507
- new_offset = getNodeTextLength(new_node)
550
+ let new_node = this._findNodeWithIndex(new_index);
551
+ new_offset = getNodeTextLength(new_node);
508
552
  } else {
509
- new_index = index
510
- new_offset = 0
553
+ new_index = index;
554
+ new_offset = 0;
511
555
  }
512
556
  }
513
557
 
514
558
  if (offset === 0) {
515
- let prev_node = this._findNodeWithIndex(index-1)
516
- if (index >= 2 && isKatexNode(prev_node))
517
- new_index = index - 2
518
- else
519
- new_index = index - 1
520
- let new_node = this._findNodeWithIndex(new_index)
521
- new_offset = getNodeTextLength(new_node)
559
+ let prev_node = this._findNodeWithIndex(index - 1);
560
+ if (index >= 2 && isKatexNode(prev_node)) new_index = index - 2;
561
+ else new_index = index - 1;
562
+ let new_node = this._findNodeWithIndex(new_index);
563
+ new_offset = getNodeTextLength(new_node);
522
564
  if (new_offset === 1) {
523
565
  if (this.nodeStartsWithSmallSpace(new_node)) {
524
- if (index > 0 && isKatexNode(this._findNodeWithIndex(index-1)))
525
- new_offset = 1
526
- else
527
- new_offset = 0
566
+ if (index > 0 && isKatexNode(this._findNodeWithIndex(index - 1)))
567
+ new_offset = 1;
568
+ else new_offset = 0;
528
569
  }
529
570
  }
530
571
  }
531
572
 
532
-
533
573
  // Move cursor to start of field if in starting small space
534
- if (new_index === 0 && new_offset === 1 && this.inputStartsWithSmallSpace()) {
535
- new_offset = 0
574
+ if (
575
+ new_index === 0 &&
576
+ new_offset === 1 &&
577
+ this.inputStartsWithSmallSpace()
578
+ ) {
579
+ new_offset = 0;
536
580
  }
537
581
 
538
- if (new_index === -1 || new_offset === -1)
539
- return
582
+ if (new_index === -1 || new_offset === -1) return;
540
583
 
541
584
  let new_rangeParams = {
542
585
  startNodeIndex: new_index,
543
586
  startOffset: new_offset,
544
587
  endNodeIndex: new_index,
545
- endOffset: new_offset
546
- }
547
- this._setRangeParams(new_rangeParams)
588
+ endOffset: new_offset,
589
+ };
590
+ this._setRangeParams(new_rangeParams);
548
591
 
549
- e.preventDefault()
550
- }
592
+ e.preventDefault();
593
+ };
551
594
 
552
595
  handleKeyDownArrowRight = (e) => {
553
596
  // console.log("handleKeyDownArrowRight")
554
- let rangeParams = this._getRangeParams()
555
- let index = rangeParams.startNodeIndex
556
- let offset = rangeParams.startOffset
597
+ let rangeParams = this._getRangeParams();
598
+ let index = rangeParams.startNodeIndex;
599
+ let offset = rangeParams.startOffset;
557
600
 
558
- if (index < 0) // Empty input field
559
- return
601
+ if (index < 0)
602
+ // Empty input field
603
+ return;
560
604
 
561
- let node = this._findNodeWithIndex(index)
562
- let length = getNodeTextLength(node)
605
+ let node = this._findNodeWithIndex(index);
606
+ let length = getNodeTextLength(node);
563
607
 
564
608
  // The user shouldn't be in a katex node, but lets deal with it anyway
565
609
  if (isKatexNode(node)) {
566
- console.warn("Cursor is inside katex node")
567
- let new_index = index+1 // Jump out of the latex node
568
- let new_offset = SMALL_SPACE_LENGTH // As there will be a SMALL_SPACE at the start of the text node
610
+ console.warn("Cursor is inside katex node");
611
+ let new_index = index + 1; // Jump out of the latex node
612
+ let new_offset = SMALL_SPACE_LENGTH; // As there will be a SMALL_SPACE at the start of the text node
569
613
 
570
614
  let new_rangeParams = {
571
615
  startNodeIndex: new_index,
572
616
  startOffset: new_offset,
573
617
  endNodeIndex: new_index,
574
- endOffset: new_offset
575
- }
576
- this._setRangeParams(new_rangeParams)
577
- e.preventDefault()
578
- return
618
+ endOffset: new_offset,
619
+ };
620
+ this._setRangeParams(new_rangeParams);
621
+ e.preventDefault();
622
+ return;
579
623
  }
580
624
 
581
625
  // Deal with case of inserted small space at start of <p> element
582
626
  if (offset === 0) {
583
627
  if (this.nodeStartsWithSmallSpace(node)) {
584
- console.log("Offset = 0 and node starts with small space")
585
- let new_index = -1
586
- let new_offset = -1
587
-
628
+ console.log("Offset = 0 and node starts with small space");
629
+ let new_index = -1;
630
+ let new_offset = -1;
631
+
588
632
  if (node.nodeValue.length > 1) {
589
- new_index = index
590
- new_offset = SMALL_SPACE_LENGTH + 1
633
+ new_index = index;
634
+ new_offset = SMALL_SPACE_LENGTH + 1;
591
635
  } else {
592
- new_index = index + 1
593
- let next_node = this._findNodeWithIndex(new_index)
636
+ new_index = index + 1;
637
+ let next_node = this._findNodeWithIndex(new_index);
594
638
  if (next_node !== null) {
595
639
  if (isKatexNode(next_node)) {
596
- new_index = index + 2
597
- new_offset = SMALL_SPACE_LENGTH
640
+ new_index = index + 2;
641
+ new_offset = SMALL_SPACE_LENGTH;
598
642
  } else {
599
- new_index = index + 1
600
- new_offset = 0
643
+ new_index = index + 1;
644
+ new_offset = 0;
601
645
  }
602
646
  } else {
603
- new_index = index
604
- new_offset = offset
605
- }
647
+ new_index = index;
648
+ new_offset = offset;
649
+ }
606
650
  }
607
651
  let new_rangeParams = {
608
652
  startNodeIndex: new_index,
609
653
  startOffset: new_offset,
610
654
  endNodeIndex: new_index,
611
- endOffset: new_offset
612
- }
613
- console.log(new_rangeParams)
614
- this._setRangeParams(new_rangeParams)
615
-
616
- e.preventDefault()
617
- return
655
+ endOffset: new_offset,
656
+ };
657
+ console.log(new_rangeParams);
658
+ this._setRangeParams(new_rangeParams);
659
+
660
+ e.preventDefault();
661
+ return;
618
662
  }
619
663
  }
620
664
 
621
-
622
665
  // If at the end of a text node
623
- if (offset === length || (index === 0 && this.inputStartsWithSmallSpace())) {
624
- let next_node = this._findNodeWithIndex(index+1)
666
+ if (
667
+ offset === length ||
668
+ (index === 0 && this.inputStartsWithSmallSpace())
669
+ ) {
670
+ let next_node = this._findNodeWithIndex(index + 1);
625
671
 
626
672
  // If there is no next node, then we can't move, so do the default action
627
673
  // If the next node is a normal node, do the default action
628
- if (next_node === null || !isKatexNode(next_node))
629
- return
674
+ if (next_node === null || !isKatexNode(next_node)) return;
630
675
 
631
- let new_index = index+2 // Jump over the latex node
632
- let new_offset = SMALL_SPACE_LENGTH // As there will be a SMALL_SPACE at the start of the text node
676
+ let new_index = index + 2; // Jump over the latex node
677
+ let new_offset = SMALL_SPACE_LENGTH; // As there will be a SMALL_SPACE at the start of the text node
633
678
 
634
679
  let new_rangeParams = {
635
680
  startNodeIndex: new_index,
636
681
  startOffset: new_offset,
637
682
  endNodeIndex: new_index,
638
- endOffset: new_offset
639
- }
640
- this._setRangeParams(new_rangeParams)
683
+ endOffset: new_offset,
684
+ };
685
+ this._setRangeParams(new_rangeParams);
641
686
 
642
- e.preventDefault()
643
- return
687
+ e.preventDefault();
688
+ return;
644
689
  }
645
- }
690
+ };
646
691
 
647
692
  editableDivIsPlainText = () => {
648
- return this.editableDiv.childNodes === null || this.editableDiv.childNodes.length === 0
649
- }
693
+ return (
694
+ this.editableDiv.childNodes === null ||
695
+ this.editableDiv.childNodes.length === 0
696
+ );
697
+ };
650
698
 
651
699
  handleKeyDownDollar = (e) => {
652
-
653
700
  // This method automatically converts text between a pair of typed dollars into
654
701
  // a latex math component. It only does this when the second dollar is preceded by certain
655
702
  // characters and NOT when the second dollar is preceded by a space.
656
- //
657
- // This is because when the user actually wants actual dollar symbols for ammounts
703
+ //
704
+ // This is because when the user actually wants actual dollar symbols for ammounts
658
705
  // the dollar symbol will usually be preceded by a space, eg:
659
706
  //
660
- // "The pie was $3.50 and the cheese was $1.30"
707
+ // "The pie was $3.50 and the cheese was $1.30"
661
708
  //
662
709
  // will not be converted as the $1.30 is preceded by a space.
663
710
  //
664
711
  try {
665
- let params = this._getRangeParams()
666
- let node = this._findNodeWithIndex(params.startNodeIndex)
667
- if (node.nodeType !== 3) // text node
668
- return
669
- let text = node.nodeValue
712
+ let params = this._getRangeParams();
713
+ let node = this._findNodeWithIndex(params.startNodeIndex);
714
+ if (node.nodeType !== 3)
715
+ // text node
716
+ return;
717
+ let text = node.nodeValue;
670
718
  // Look for starting dollar to match this new second dollar
671
- let first_dollar_pos = text.indexOf("$")
672
- if (first_dollar_pos < 0)
673
- return
674
- if (first_dollar_pos >= params.startOffset)
675
- return
676
- let second_dollar_pos = params.startOffset
677
-
678
- let c = text.charAt(second_dollar_pos-1)
679
- let convert_to_latex = false
680
- if ((c >= 'a' && c <= 'z') ||
681
- (c >= 'A' && c <= 'Z') ||
682
- (c >= '0' && c <= '9') ||
683
- c === ')' || c === '}') {
684
- convert_to_latex = true
719
+ let first_dollar_pos = text.indexOf("$");
720
+ if (first_dollar_pos < 0) return;
721
+ if (first_dollar_pos >= params.startOffset) return;
722
+ let second_dollar_pos = params.startOffset;
723
+
724
+ let c = text.charAt(second_dollar_pos - 1);
725
+ let convert_to_latex = false;
726
+ if (
727
+ (c >= "a" && c <= "z") ||
728
+ (c >= "A" && c <= "Z") ||
729
+ (c >= "0" && c <= "9") ||
730
+ c === ")" ||
731
+ c === "}"
732
+ ) {
733
+ convert_to_latex = true;
685
734
  }
686
- if (!convert_to_latex)
687
- return
688
-
689
- node.nodeValue =
690
- node.nodeValue.substring(0,first_dollar_pos) + MARK +
691
- node.nodeValue.substring(first_dollar_pos+1, second_dollar_pos) + MARK +
692
- node.nodeValue.substring(second_dollar_pos)
735
+ if (!convert_to_latex) return;
736
+
737
+ node.nodeValue =
738
+ node.nodeValue.substring(0, first_dollar_pos) +
739
+ MARK +
740
+ node.nodeValue.substring(first_dollar_pos + 1, second_dollar_pos) +
741
+ MARK +
742
+ node.nodeValue.substring(second_dollar_pos);
743
+
744
+ let raw_text = elementToMarkedRawText(
745
+ e.target,
746
+ null,
747
+ 0,
748
+ this.enableHtml()
749
+ );
750
+ raw_text = raw_text.replace(MARK_REG_EXP, "$");
693
751
 
694
- let raw_text = elementToMarkedRawText(e.target, null, 0, this.enableHtml())
695
- raw_text = raw_text.replace(MARK_REG_EXP,"$")
696
-
697
752
  // We are turning one node into three and want the cursor at the start of the third node
698
753
  let new_rangeParams = {
699
754
  startNodeIndex: params.startNodeIndex + 2,
700
755
  startOffset: SMALL_SPACE_LENGTH,
701
756
  endNodeIndex: params.startNodeIndex + 2,
702
- endOffset: SMALL_SPACE_LENGTH
703
- }
704
-
705
- let nodeCounts = this._countNodeTypes()
706
- let mimeType = this.getMimeType(nodeCounts.html > 0, true)
707
- raw_text = removeEncodingIfPlainText(raw_text, mimeType, this.enableHtml())
708
-
709
- this.applyChangesToComponent(raw_text,
710
- mimeType,
711
- new_rangeParams,
712
- this.props.useExpertMode,
713
- this.props.selectedTab)
757
+ endOffset: SMALL_SPACE_LENGTH,
758
+ };
759
+
760
+ let nodeCounts = this._countNodeTypes();
761
+ let mimeType = this.getMimeType(nodeCounts.html > 0, true);
762
+ raw_text = removeEncodingIfPlainText(
763
+ raw_text,
764
+ mimeType,
765
+ this.enableHtml()
766
+ );
767
+
768
+ this.applyChangesToComponent(
769
+ raw_text,
770
+ mimeType,
771
+ new_rangeParams,
772
+ this.props.useExpertMode,
773
+ this.props.selectedTab
774
+ );
714
775
  } catch (error) {
715
- console.error(error)
776
+ console.error(error);
716
777
  }
717
778
 
718
- e.preventDefault()
719
- }
779
+ e.preventDefault();
780
+ };
720
781
 
721
782
  showEquationEditorOnKeyDown = (e) => {
722
- this.showEquationEditor(true)
723
- e.preventDefault()
724
- }
783
+ this.showEquationEditor(true);
784
+ e.preventDefault();
785
+ };
725
786
 
726
787
  handleKeyDownEnter = (e) => {
727
788
  try {
728
- console.log("handleKeyDownEnter")
729
- if (this.enableMultiline())
730
- this.insertNewLine(e)
789
+ console.log("handleKeyDownEnter");
790
+ if (this.enableMultiline()) this.insertNewLine(e);
731
791
  } catch (error) {
732
- console.error(error)
792
+ console.error(error);
733
793
  }
734
- e.preventDefault()
735
- }
794
+ e.preventDefault();
795
+ };
736
796
 
737
797
  handleKeyDown = (e) => {
738
798
  try {
739
799
  // Lets set up or update the undo redo history
740
- this.initialiseHistory()
800
+ this.initialiseHistory();
741
801
 
742
802
  if ((e.key === "z" || e.key === "Z") && (e.ctrlKey || e.metaKey)) {
743
- if (e.shiftKey)
744
- this.redo()
745
- else
746
- this.undo()
747
- e.preventDefault()
748
- return
803
+ if (e.shiftKey) this.redo();
804
+ else this.undo();
805
+ e.preventDefault();
806
+ return;
749
807
  }
750
-
751
- if (!(e.ctrlKey || e.metaKey))
752
- this.resetHistoryRedo()
753
-
754
- if ((e.metaKey || e.ctrlKey) &&
755
- (e.key === "b" || e.key === "i" || e.key === "u" ||
756
- e.key === "6" || e.key === "^" ||
757
- e.key === "-" || e.key === "_")) {
808
+
809
+ if (!(e.ctrlKey || e.metaKey)) this.resetHistoryRedo();
810
+
811
+ if (
812
+ (e.metaKey || e.ctrlKey) &&
813
+ (e.key === "b" ||
814
+ e.key === "i" ||
815
+ e.key === "u" ||
816
+ e.key === "6" ||
817
+ e.key === "^" ||
818
+ e.key === "-" ||
819
+ e.key === "_")
820
+ ) {
758
821
  if (!this.enableHtml()) {
759
- e.preventDefault()
760
- return
822
+ e.preventDefault();
823
+ return;
761
824
  }
762
- if (e.key === "b")
763
- this.styleText(e, "Bold")
764
- if (e.key === "i")
765
- this.styleText(e, "Italic")
766
- if (e.key === "u")
767
- this.styleText(e, "Underline")
768
- if (e.key === "6" || e.key === "^")
769
- this.styleText(e, "Superscript")
825
+ if (e.key === "b") this.styleText(e, "Bold");
826
+ if (e.key === "i") this.styleText(e, "Italic");
827
+ if (e.key === "u") this.styleText(e, "Underline");
828
+ if (e.key === "6" || e.key === "^") this.styleText(e, "Superscript");
770
829
 
771
830
  // don't apply subscript if it is the browser command key for "smaller"
772
- if (/(Win)/i.test(window.navigator.platform) && e.ctrlKey && e.key === "-")
773
- return
774
- if (/(Mac)/i.test(window.navigator.platform) && e.metaKey && e.key === "-")
775
- return
831
+ if (
832
+ /(Win)/i.test(window.navigator.platform) &&
833
+ e.ctrlKey &&
834
+ e.key === "-"
835
+ )
836
+ return;
837
+ if (
838
+ /(Mac)/i.test(window.navigator.platform) &&
839
+ e.metaKey &&
840
+ e.key === "-"
841
+ )
842
+ return;
776
843
  // otherwise
777
- if (e.key === "-" || e.key === "_")
778
- this.styleText(e, "Subscript")
844
+ if (e.key === "-" || e.key === "_") this.styleText(e, "Subscript");
779
845
 
780
- e.preventDefault()
781
- return
846
+ e.preventDefault();
847
+ return;
782
848
  }
783
849
 
784
-
785
850
  // Ignore automatic key repeat presses on Windows so that we can show an accent bar on
786
851
  // long key press
787
852
  if (!/(Win)/i.test(window.navigator.platform)) {
788
853
  if (e.key === this.keyPressed && this.keyPressStartTime > 0) {
789
- if (e.key.length === 1 && (
790
- ("a" <= e.key && e.key <= "z") ||
791
- ("A" <= e.key && e.key <= "Z") ||
854
+ if (
855
+ e.key.length === 1 &&
856
+ (("a" <= e.key && e.key <= "z") ||
857
+ ("A" <= e.key && e.key <= "Z") ||
792
858
  e.key === "!" ||
793
- e.key === "?")) {
794
- e.preventDefault()
795
- return
859
+ e.key === "?")
860
+ ) {
861
+ e.preventDefault();
862
+ return;
796
863
  }
797
864
  }
798
865
  }
799
866
 
800
867
  if (e.altKey && e.key === "Alt") {
801
- let key = this.fetchAccentLetter()
802
- if (key === "a" || key === "e" || key === "i" || key === "o" || key === "u" ||
803
- key === "c" || key === "l" || key === "n" || key === "s" || key === "?" || key === "!") {
804
- this.setState({showAccentBar:!this.state.showAccentBar})
868
+ let key = this.fetchAccentLetter();
869
+ if (
870
+ key === "a" ||
871
+ key === "e" ||
872
+ key === "i" ||
873
+ key === "o" ||
874
+ key === "u" ||
875
+ key === "c" ||
876
+ key === "l" ||
877
+ key === "n" ||
878
+ key === "s" ||
879
+ key === "?" ||
880
+ key === "!"
881
+ ) {
882
+ this.setState({ showAccentBar: !this.state.showAccentBar });
805
883
  } else {
806
- this.setState({showAccentBar:false})
884
+ this.setState({ showAccentBar: false });
807
885
  }
808
- return
886
+ return;
809
887
  }
810
888
 
811
- this.keyPressed = e.key // store for use in methods
812
- this.setState({keyPressed:e.key})
889
+ this.keyPressed = e.key; // store for use in methods
890
+ this.setState({ keyPressed: e.key });
813
891
 
814
892
  // Hide the accent bar if a key is typed except when it is an automatic key repeat press
815
- // If it is automatic key repeat, then keyPressStartTime will be greater than 0
893
+ // If it is automatic key repeat, then keyPressStartTime will be greater than 0
816
894
  // (keyPressStartTime is reset to -1 on key up)
817
- if (this.keyPressStartTime < 0) {
818
- this.keyPressStartTime = Date.now()
819
- if (this.state.showAccentBar)
820
- this.setState({showAccentBar:false})
895
+ if (this.keyPressStartTime < 0) {
896
+ this.keyPressStartTime = Date.now();
897
+ if (this.state.showAccentBar) this.setState({ showAccentBar: false });
821
898
  }
822
899
 
823
900
  if (e.key === "Backspace") {
824
- this.handleKeyDownBackspace(e)
825
- return
901
+ this.handleKeyDownBackspace(e);
902
+ return;
826
903
  }
827
904
  if (e.key === "ArrowLeft") {
828
- this.handleKeyDownArrowLeft(e)
829
- return
905
+ this.handleKeyDownArrowLeft(e);
906
+ return;
830
907
  }
831
908
  if (e.key === "ArrowRight") {
832
- this.handleKeyDownArrowRight(e)
833
- return
909
+ this.handleKeyDownArrowRight(e);
910
+ return;
834
911
  }
835
912
  if (e.key === "$") {
836
- this.handleKeyDownDollar(e)
837
- return
913
+ this.handleKeyDownDollar(e);
914
+ return;
838
915
  }
839
916
 
840
917
  // Implement special command + keys
841
918
  if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
842
- this.showEquationEditorOnKeyDown(e)
843
- return
919
+ this.showEquationEditorOnKeyDown(e);
920
+ return;
844
921
  } else if (/(Mac)/i.test(window.navigator.platform)) {
845
- if (e.ctrlKey && e.key === "=") { // CTRL+= inserts equation in Word on Mac
846
- this.showEquationEditorOnKeyDown(e)
847
- return
922
+ if (e.ctrlKey && e.key === "=") {
923
+ // CTRL+= inserts equation in Word on Mac
924
+ this.showEquationEditorOnKeyDown(e);
925
+ return;
848
926
  }
849
927
  } else if (/(Win)/i.test(window.navigator.platform)) {
850
- if (e.altKey && e.key === "=") { // ALT+= inserts equation in Word on PC
851
- this.showEquationEditorOnKeyDown(e)
852
- return
928
+ if (e.altKey && e.key === "=") {
929
+ // ALT+= inserts equation in Word on PC
930
+ this.showEquationEditorOnKeyDown(e);
931
+ return;
853
932
  }
854
933
  }
855
-
934
+
856
935
  // Lets handle the enter key (new line) ourselves
857
936
  if (e.key === "Enter") {
858
- this.handleKeyDownEnter(e)
859
- return
937
+ this.handleKeyDownEnter(e);
938
+ return;
860
939
  }
861
940
 
862
941
  // Show the accent bar on long key presses
863
942
  if (/(Win)/i.test(window.navigator.platform)) {
864
- let key= e.key.toLowerCase()
865
- if (key === "a" || key === "e" || key === "i" || key === "o" || key === "u" ||
866
- key === "c" || key === "l" || key === "n" || key === "s" || key === "?" || key === "!") {
867
- let _this = this
868
- setTimeout(function(){
869
- console.log(Date.now() - _this.keyPressStartTime)
943
+ let key = e.key.toLowerCase();
944
+ if (
945
+ key === "a" ||
946
+ key === "e" ||
947
+ key === "i" ||
948
+ key === "o" ||
949
+ key === "u" ||
950
+ key === "c" ||
951
+ key === "l" ||
952
+ key === "n" ||
953
+ key === "s" ||
954
+ key === "?" ||
955
+ key === "!"
956
+ ) {
957
+ let _this = this;
958
+ setTimeout(function () {
959
+ console.log(Date.now() - _this.keyPressStartTime);
870
960
  if (_this.keyPressStartTime > 0)
871
961
  if (Date.now() - _this.keyPressStartTime > 450)
872
- _this.setState({showAccentBar:true})
962
+ _this.setState({ showAccentBar: true });
873
963
  }, 500);
874
964
  }
875
965
  }
876
-
966
+
877
967
  // Stop editing if within rendered katex node, if somehow the cursor ends up there (it shouldn't)
878
- let params = this._getRangeParams()
879
- let startNode = this._findNodeWithIndex(params.startNodeIndex)
880
- let endNode = this._findNodeWithIndex(params.endNodeIndex)
968
+ let params = this._getRangeParams();
969
+ let startNode = this._findNodeWithIndex(params.startNodeIndex);
970
+ let endNode = this._findNodeWithIndex(params.endNodeIndex);
881
971
  if (!this.editableDivIsPlainText()) {
882
972
  // console.log(params)
883
973
  if (params.startNodeIndex === -1) {
884
- console.error("Couldn't get range params")
885
- return
974
+ console.error("Couldn't get range params");
975
+ return;
886
976
  }
887
977
  // console.log("Start node: "+startNode)
888
978
  // console.log("End node: "+endNode)
889
-
979
+
890
980
  if (isKatexNode(startNode) || isKatexNode(endNode)) {
891
- console.error("User trying to edit inside latex node")
892
- e.preventDefault()
893
- return
981
+ console.error("User trying to edit inside latex node");
982
+ e.preventDefault();
983
+ return;
894
984
  }
895
- }
985
+ }
896
986
 
897
987
  // Check if inserting character in element that starts with small space
898
- if (e.key.length === 1 && params.startOffset === 0 && this.nodeStartsWithSmallSpace(startNode)) {
899
- this.replaceNextLetter(e.key)
900
- e.preventDefault()
901
- return
988
+ if (
989
+ e.key.length === 1 &&
990
+ params.startOffset === 0 &&
991
+ this.nodeStartsWithSmallSpace(startNode)
992
+ ) {
993
+ this.replaceNextLetter(e.key);
994
+ e.preventDefault();
995
+ return;
902
996
  }
903
-
904
997
  } catch (error) {
905
- console.error(error)
906
- console.log("Key pressed: " +
907
- (e.metaKey ? "META+" : "") +
908
- (e.ctrlKey ? "CTRL+" : "") +
909
- (e.altKey ? "ALT+" : "") +
910
- (e.shiftKey ? "SHIFT+" : "") +
911
- e.key
912
- )
998
+ console.error(error);
999
+ console.log(
1000
+ "Key pressed: " +
1001
+ (e.metaKey ? "META+" : "") +
1002
+ (e.ctrlKey ? "CTRL+" : "") +
1003
+ (e.altKey ? "ALT+" : "") +
1004
+ (e.shiftKey ? "SHIFT+" : "") +
1005
+ e.key
1006
+ );
913
1007
  }
914
- }
1008
+ };
915
1009
 
916
1010
  handleKeyUp = (e) => {
917
1011
  try {
918
- this.keyPressed = e.key
919
- this.keyPressStartTime = -1
1012
+ this.keyPressed = e.key;
1013
+ this.keyPressStartTime = -1;
920
1014
 
921
1015
  // If the cursor is in a katex node, then move it to the next node (unless there is no
922
1016
  // net node in which case move it to the previous node)
923
1017
  if (e.key === "ArrowRight") {
924
- let rangeParams = this._getRangeParams()
925
- let index = rangeParams.startNodeIndex
1018
+ let rangeParams = this._getRangeParams();
1019
+ let index = rangeParams.startNodeIndex;
926
1020
 
927
1021
  if (index >= 0) {
928
1022
  if (isKatexNode(this._findNodeWithIndex(index))) {
929
- let new_index = 0
930
- let new_offset = 0
1023
+ let new_index = 0;
1024
+ let new_offset = 0;
931
1025
 
932
- let nextNode = this._findNodeWithIndex(index+1)
1026
+ let nextNode = this._findNodeWithIndex(index + 1);
933
1027
  if (nextNode === null) {
934
- new_index = index + 1
935
- new_offset = SMALL_SPACE_LENGTH // Nominally should be 0, but 1 due to inserted SMALL_SPACE
1028
+ new_index = index + 1;
1029
+ new_offset = SMALL_SPACE_LENGTH; // Nominally should be 0, but 1 due to inserted SMALL_SPACE
936
1030
  } else {
937
- new_index = index - 1
938
- new_offset = getNodeTextLength(this._findNodeWithIndex(new_index))
939
- if (new_offset < 0)
940
- {
941
- console.error("Failed to get node text length")
942
- new_offset = 0
1031
+ new_index = index - 1;
1032
+ new_offset = getNodeTextLength(
1033
+ this._findNodeWithIndex(new_index)
1034
+ );
1035
+ if (new_offset < 0) {
1036
+ console.error("Failed to get node text length");
1037
+ new_offset = 0;
943
1038
  }
944
1039
  }
945
1040
 
946
1041
  let new_rangeParams = {
947
- startNodeIndex:new_index,
1042
+ startNodeIndex: new_index,
948
1043
  startOffset: new_offset,
949
1044
  endNodeIndex: new_index,
950
- endOffset: new_offset
951
- }
952
- this._setRangeParams(new_rangeParams)
1045
+ endOffset: new_offset,
1046
+ };
1047
+ this._setRangeParams(new_rangeParams);
953
1048
  }
954
1049
  }
955
1050
  }
956
1051
 
957
1052
  if (e.key === "ArrowLeft") {
958
- let rangeParams = this._getRangeParams()
959
- let index = rangeParams.startNodeIndex
1053
+ let rangeParams = this._getRangeParams();
1054
+ let index = rangeParams.startNodeIndex;
960
1055
 
961
1056
  // If the cursor is in a katex node, then move it to the previous node (unless there is no
962
1057
  // previous node in which case move it to the next node)
963
1058
  if (index >= 0) {
964
1059
  if (isKatexNode(this._findNodeWithIndex(index))) {
965
- let new_index = 0
966
- let new_offset = 0
1060
+ let new_index = 0;
1061
+ let new_offset = 0;
967
1062
 
968
1063
  if (index - 1 >= 0) {
969
- new_index = index - 1
970
- new_offset = getNodeTextLength(this._findNodeWithIndex(new_index))
971
- if (new_offset < 0)
972
- {
973
- console.error("Failed to get node text length")
974
- new_offset = 0
1064
+ new_index = index - 1;
1065
+ new_offset = getNodeTextLength(
1066
+ this._findNodeWithIndex(new_index)
1067
+ );
1068
+ if (new_offset < 0) {
1069
+ console.error("Failed to get node text length");
1070
+ new_offset = 0;
975
1071
  }
976
1072
  } else {
977
- new_index = index + 1
978
- new_offset = SMALL_SPACE_LENGTH
1073
+ new_index = index + 1;
1074
+ new_offset = SMALL_SPACE_LENGTH;
979
1075
  }
980
1076
 
981
1077
  let new_rangeParams = {
982
- startNodeIndex:new_index,
1078
+ startNodeIndex: new_index,
983
1079
  startOffset: new_offset,
984
1080
  endNodeIndex: new_index,
985
- endOffset: new_offset
986
- }
1081
+ endOffset: new_offset,
1082
+ };
987
1083
  // console.log(new_rangeParams)
988
- this._setRangeParams(new_rangeParams)
1084
+ this._setRangeParams(new_rangeParams);
989
1085
  }
990
1086
  }
991
1087
  }
992
1088
 
993
- this.updateActiveButtons()
1089
+ this.updateActiveButtons();
994
1090
  } catch (error) {
995
- console.error(error)
1091
+ console.error(error);
996
1092
  }
997
- }
1093
+ };
998
1094
 
999
1095
  handleInput = (event) => {
1000
1096
  try {
1001
1097
  // console.log("handleInput")
1002
- let raw_text = elementToMarkedRawText(this.editableDiv, null, 0, this.enableHtml())
1003
- const params = this._getRangeParams()
1098
+ let raw_text = elementToMarkedRawText(
1099
+ this.editableDiv,
1100
+ null,
1101
+ 0,
1102
+ this.enableHtml()
1103
+ );
1104
+ const params = this._getRangeParams();
1004
1105
  if (params === null || params === undefined)
1005
- console.error("Could not get range params from input field")
1006
- else if (params.startNodeIndex === null || params.startNodeIndex === undefined)
1007
- console.error("Could not get range params from input field, startNodeIndex==="+params.startNodeIndex)
1106
+ console.error("Could not get range params from input field");
1107
+ else if (
1108
+ params.startNodeIndex === null ||
1109
+ params.startNodeIndex === undefined
1110
+ )
1111
+ console.error(
1112
+ "Could not get range params from input field, startNodeIndex===" +
1113
+ params.startNodeIndex
1114
+ );
1008
1115
  else {
1009
1116
  // console.log("Current range params:")
1010
1117
  // console.log(params)
1011
1118
  }
1012
1119
 
1013
- let nodeCounts = this._countNodeTypes()
1014
- let mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.math > 0)
1015
- raw_text = removeEncodingIfPlainText(raw_text, mimeType, this.enableHtml())
1016
-
1017
- this.applyChangesToComponent(raw_text, mimeType, params,
1018
- this.props.useExpertMode, this.props.selectedTab)
1120
+ let nodeCounts = this._countNodeTypes();
1121
+ let mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.math > 0);
1122
+ raw_text = removeEncodingIfPlainText(
1123
+ raw_text,
1124
+ mimeType,
1125
+ this.enableHtml()
1126
+ );
1127
+
1128
+ this.applyChangesToComponent(
1129
+ raw_text,
1130
+ mimeType,
1131
+ params,
1132
+ this.props.useExpertMode,
1133
+ this.props.selectedTab
1134
+ );
1019
1135
  } catch (error) {
1020
- console.error(error)
1136
+ console.error(error);
1021
1137
  }
1022
- }
1138
+ };
1023
1139
 
1024
1140
  updateActiveButtons = () => {
1025
1141
  try {
1026
- let rangeParams = this._getRangeParams()
1027
- if (rangeParams.startNodeIndex < 0)
1028
- return
1029
- let node = this._findNodeWithIndex(rangeParams.startNodeIndex)
1030
- let bold = false
1031
- let italic = false
1032
- let underline = false
1033
- let superscript = false
1034
- let subscript = false
1142
+ let rangeParams = this._getRangeParams();
1143
+ if (rangeParams.startNodeIndex < 0) return;
1144
+ let node = this._findNodeWithIndex(rangeParams.startNodeIndex);
1145
+ let bold = false;
1146
+ let italic = false;
1147
+ let underline = false;
1148
+ let superscript = false;
1149
+ let subscript = false;
1035
1150
  do {
1036
1151
  if (node.nodeType === 1) {
1037
- let nodeName = node.nodeName.toLowerCase()
1038
- if (nodeName === "b" || nodeName === "strong")
1039
- bold = true
1040
- else if (nodeName === "i" || nodeName === "em")
1041
- italic = true
1042
- else if (nodeName === "u")
1043
- underline = true
1044
- else if (nodeName === "sub")
1045
- subscript = true
1046
- else if (nodeName === "sup")
1047
- superscript = true
1048
- }
1049
- else if (node.classList !== null && node.classList !== undefined &&
1050
- node.classList.contains("MathRichInput"))
1051
- break
1052
- node = node.parentNode
1053
- } while (node !== null)
1152
+ let nodeName = node.nodeName.toLowerCase();
1153
+ if (nodeName === "b" || nodeName === "strong") bold = true;
1154
+ else if (nodeName === "i" || nodeName === "em") italic = true;
1155
+ else if (nodeName === "u") underline = true;
1156
+ else if (nodeName === "sub") subscript = true;
1157
+ else if (nodeName === "sup") superscript = true;
1158
+ } else if (
1159
+ node.classList !== null &&
1160
+ node.classList !== undefined &&
1161
+ node.classList.contains("MathRichInput")
1162
+ )
1163
+ break;
1164
+ node = node.parentNode;
1165
+ } while (node !== null);
1054
1166
 
1055
- let activeButtons = {bold, italic, underline, subscript, superscript}
1167
+ let activeButtons = { bold, italic, underline, subscript, superscript };
1056
1168
  // console.log(activeButtons)
1057
1169
 
1058
- let update = true
1170
+ let update = true;
1059
1171
  if (this.lastSetActiveButtons !== null) {
1060
- update = false
1061
- for(var style in activeButtons) {
1062
- if(activeButtons[style] !== this.lastSetActiveButtons[style]) {
1063
- update = true
1064
- break
1172
+ update = false;
1173
+ for (var style in activeButtons) {
1174
+ if (activeButtons[style] !== this.lastSetActiveButtons[style]) {
1175
+ update = true;
1176
+ break;
1065
1177
  }
1066
1178
  }
1067
1179
  }
1068
1180
  if (update) {
1069
- this.lastSetActiveButtons = activeButtons
1070
- this.setState({activeButtons:activeButtons})
1181
+ this.lastSetActiveButtons = activeButtons;
1182
+ this.setState({ activeButtons: activeButtons });
1071
1183
  }
1072
1184
  } catch (error) {
1073
- console.error(error)
1185
+ console.error(error);
1074
1186
  }
1075
- }
1187
+ };
1076
1188
 
1077
- componentDidMount(){
1189
+ componentDidMount() {
1078
1190
  try {
1079
- setupKatex()
1191
+ setupKatex();
1080
1192
 
1081
- this.editableDiv.addEventListener('keydown',this.handleKeyDown);
1082
- this.editableDiv.addEventListener('keyup',this.handleKeyUp);
1193
+ this.editableDiv.addEventListener("keydown", this.handleKeyDown);
1194
+ this.editableDiv.addEventListener("keyup", this.handleKeyUp);
1083
1195
  } catch (error) {
1084
- console.error(error)
1196
+ console.error(error);
1085
1197
  }
1086
1198
  }
1087
1199
 
1088
- componentWillUnmount(){
1200
+ componentWillUnmount() {
1089
1201
  try {
1090
- this.editableDiv.removeEventListener('keydown',this.handleKeyDown);
1091
- this.editableDiv.removeEventListener('keyup',this.handleKeyUp);
1202
+ this.editableDiv.removeEventListener("keydown", this.handleKeyDown);
1203
+ this.editableDiv.removeEventListener("keyup", this.handleKeyUp);
1092
1204
  } catch (error) {
1093
- console.error(error)
1205
+ console.error(error);
1094
1206
  }
1095
1207
  }
1096
1208
 
1097
1209
  componentDidUpdate() {
1098
- try {
1210
+ try {
1099
1211
  // console.log("Component updated:")
1100
1212
  // console.log(this.editableDiv.childNodes)
1101
- if (this.rangeParamsToSetAfterComponentUpdate !== null &&
1102
- this.rangeParamsToSetAfterComponentUpdate !== undefined ) {
1103
- this._setRangeParams(this.rangeParamsToSetAfterComponentUpdate)
1104
- this.rangeParamsToSetAfterComponentUpdate = null
1105
- this.updateActiveButtons()
1213
+ if (
1214
+ this.rangeParamsToSetAfterComponentUpdate !== null &&
1215
+ this.rangeParamsToSetAfterComponentUpdate !== undefined
1216
+ ) {
1217
+ this._setRangeParams(this.rangeParamsToSetAfterComponentUpdate);
1218
+ this.rangeParamsToSetAfterComponentUpdate = null;
1219
+ this.updateActiveButtons();
1106
1220
  }
1107
1221
  } catch (error) {
1108
- console.error(error)
1222
+ console.error(error);
1109
1223
  }
1110
1224
  }
1111
1225
 
1112
- showEquationEditor = (moveCursorOnInsert=false, node=null) => {
1226
+ showEquationEditor = (moveCursorOnInsert = false, node = null) => {
1113
1227
  try {
1114
- let rangeParams = this._getRangeParams()
1228
+ let rangeParams = this._getRangeParams();
1115
1229
  if (rangeParams.startNodeIndex < 0) {
1116
- console.error("Could not find position of cursor in node list")
1117
- console.log(rangeParams)
1118
- console.log(this.editableDiv.childNodes)
1119
-
1120
- this.setOldRangeParams({startNodeIndex:2, startOffset:1,
1121
- endNodeIndex:2, endOffset:1})
1122
- this.markedRawText = MARK + " " + MARK
1123
- this.moveCursorOnInsert = moveCursorOnInsert
1230
+ console.error("Could not find position of cursor in node list");
1231
+ console.log(rangeParams);
1232
+ console.log(this.editableDiv.childNodes);
1233
+
1234
+ this.setOldRangeParams({
1235
+ startNodeIndex: 2,
1236
+ startOffset: 1,
1237
+ endNodeIndex: 2,
1238
+ endOffset: 1,
1239
+ });
1240
+ this.markedRawText = MARK + " " + MARK;
1241
+ this.moveCursorOnInsert = moveCursorOnInsert;
1124
1242
  this.setState({
1125
- showEquationEditor:true,
1126
- equationEditorLatex:""
1127
- });
1128
- return
1243
+ showEquationEditor: true,
1244
+ equationEditorLatex: "",
1245
+ });
1246
+ return;
1129
1247
  }
1130
1248
 
1131
- let latex = ""
1132
- let offset = 0
1249
+ let latex = "";
1250
+ let offset = 0;
1133
1251
 
1134
- if (node === null)
1135
- node = this._findNodeWithIndex(rangeParams.startNodeIndex)
1252
+ if (node === null)
1253
+ node = this._findNodeWithIndex(rangeParams.startNodeIndex);
1136
1254
 
1137
1255
  // console.log(rangeParams)
1138
1256
  // console.log(this.editableDiv.childNodes)
1139
1257
  // console.log(node)
1140
1258
 
1141
1259
  if (node === null || node === undefined) {
1142
- console.error("Could not find node with index: "+rangeParams.startNodeIndex)
1143
- console.log("Child nodes:")
1144
- console.log(this.editableDiv.childNodes)
1145
- node = this._findFirstTextNode()
1146
- offset = 0
1260
+ console.error(
1261
+ "Could not find node with index: " + rangeParams.startNodeIndex
1262
+ );
1263
+ console.log("Child nodes:");
1264
+ console.log(this.editableDiv.childNodes);
1265
+ node = this._findFirstTextNode();
1266
+ offset = 0;
1147
1267
  }
1148
-
1149
- if (isKatexNode(node)){
1150
- latex = getLatex(node)
1151
- offset = 0
1152
- this.editingExistingEquation = true
1153
- this.editingNode = node
1268
+
1269
+ if (isKatexNode(node)) {
1270
+ latex = getLatex(node);
1271
+ offset = 0;
1272
+ this.editingExistingEquation = true;
1273
+ this.editingNode = node;
1154
1274
  } else {
1155
- latex = ""
1156
- offset = rangeParams.startOffset
1157
- this.editingExistingEquation = false
1158
- this.editingNode = null
1275
+ latex = "";
1276
+ offset = rangeParams.startOffset;
1277
+ this.editingExistingEquation = false;
1278
+ this.editingNode = null;
1159
1279
  }
1160
-
1161
- this.markedRawText = elementToMarkedRawText(this.editableDiv, node, offset, this.enableHtml())
1280
+
1281
+ this.markedRawText = elementToMarkedRawText(
1282
+ this.editableDiv,
1283
+ node,
1284
+ offset,
1285
+ this.enableHtml()
1286
+ );
1162
1287
  // console.log("Marked text:"+this.markedRawText)
1163
- this.moveCursorOnInsert = moveCursorOnInsert
1288
+ this.moveCursorOnInsert = moveCursorOnInsert;
1164
1289
  this.setState({
1165
- showEquationEditor:true,
1166
- equationEditorLatex:latex
1167
- });
1290
+ showEquationEditor: true,
1291
+ equationEditorLatex: latex,
1292
+ });
1168
1293
  } catch (error) {
1169
- console.error(error)
1294
+ console.error(error);
1170
1295
  }
1171
- }
1296
+ };
1172
1297
 
1173
- handleMouseDown = (event) => {
1174
- this.showEquationEditorOnMouseUp = false
1175
- let node = null
1298
+ handleMouseDown = (event) => {
1299
+ this.showEquationEditorOnMouseUp = false;
1300
+ let node = null;
1176
1301
  try {
1177
- node = event.target
1178
- let isLatex = false
1302
+ node = event.target;
1303
+ let isLatex = false;
1179
1304
  do {
1180
1305
  if (isKatexNode(node)) {
1181
- isLatex = true
1182
- break
1306
+ isLatex = true;
1307
+ break;
1183
1308
  }
1184
- node = node.parentNode
1185
- } while (node !== this.editableDiv && node !== null)
1309
+ node = node.parentNode;
1310
+ } while (node !== this.editableDiv && node !== null);
1186
1311
 
1187
- if (!isLatex)
1188
- return
1312
+ if (!isLatex) return;
1189
1313
 
1190
- this.showEquationEditorOnMouseUp = true
1314
+ this.showEquationEditorOnMouseUp = true;
1191
1315
  // Save current range parameters so that we can restore them later if we wish
1192
- this.setOldRangeParams(this._getRangeParams())
1316
+ this.setOldRangeParams(this._getRangeParams());
1193
1317
 
1194
1318
  // this.editableDiv.focus()
1195
1319
  // this.showEquationEditor(false, node)
1196
1320
 
1197
1321
  // event.preventDefault()
1198
1322
  } catch (error) {
1199
- console.error(error)
1200
- console.log(node)
1323
+ console.error(error);
1324
+ console.log(node);
1201
1325
  }
1202
- }
1326
+ };
1203
1327
 
1204
1328
  handleMouseUp = (event) => {
1205
1329
  try {
1206
- this.initialiseHistory()
1330
+ this.initialiseHistory();
1331
+
1332
+ let params = this._getRangeParams();
1333
+ let startNode = this._findNodeWithIndex(params.startNodeIndex);
1334
+ let endNode = this._findNodeWithIndex(params.endNodeIndex);
1207
1335
 
1208
- let params = this._getRangeParams()
1209
- let startNode = this._findNodeWithIndex(params.startNodeIndex)
1210
- let endNode = this._findNodeWithIndex(params.endNodeIndex)
1211
-
1212
1336
  if (startNode === null || endNode === null) {
1213
- console.warn("Start or end node was null")
1214
- return
1337
+ console.warn("Start or end node was null");
1338
+ return;
1215
1339
  }
1216
1340
 
1217
- if (params.startNodeIndex === params.endNodeIndex &&
1341
+ if (
1342
+ params.startNodeIndex === params.endNodeIndex &&
1218
1343
  params.startOffset === params.endOffset &&
1219
- this.showEquationEditorOnMouseUp) {
1220
- this.editableDiv.focus()
1221
- this.showEquationEditor(false, startNode)
1222
- return
1223
- }
1344
+ this.showEquationEditorOnMouseUp
1345
+ ) {
1346
+ this.editableDiv.focus();
1347
+ this.showEquationEditor(false, startNode);
1348
+ return;
1349
+ }
1224
1350
 
1225
1351
  // If our range starts or ends inside a katex node, move it out
1226
- let new_rangeParams = null
1352
+ let new_rangeParams = null;
1227
1353
  if (isKatexNode(startNode)) {
1228
- if (new_rangeParams === null)
1229
- new_rangeParams = {...params}
1230
- if (params.startNodeIndex === params.endNodeIndex &&
1231
- params.startOffset === params.endOffset) {
1232
- new_rangeParams.startNodeIndex = params.startNodeIndex + 1
1233
- new_rangeParams.startOffset = SMALL_SPACE_LENGTH
1354
+ if (new_rangeParams === null) new_rangeParams = { ...params };
1355
+ if (
1356
+ params.startNodeIndex === params.endNodeIndex &&
1357
+ params.startOffset === params.endOffset
1358
+ ) {
1359
+ new_rangeParams.startNodeIndex = params.startNodeIndex + 1;
1360
+ new_rangeParams.startOffset = SMALL_SPACE_LENGTH;
1234
1361
  } else {
1235
- new_rangeParams.startNodeIndex = params.startNodeIndex - 1
1236
- let prev_node = this._findNodeWithIndex(params.startNodeIndex - 1)
1237
- new_rangeParams.startOffset = getNodeTextLength(prev_node)
1362
+ new_rangeParams.startNodeIndex = params.startNodeIndex - 1;
1363
+ let prev_node = this._findNodeWithIndex(params.startNodeIndex - 1);
1364
+ new_rangeParams.startOffset = getNodeTextLength(prev_node);
1238
1365
  }
1239
1366
  }
1240
1367
  if (isKatexNode(endNode)) {
1241
- if (new_rangeParams === null)
1242
- new_rangeParams = {...params}
1243
- new_rangeParams.endNodeIndex = params.endNodeIndex + 1
1244
- new_rangeParams.endOffset = SMALL_SPACE_LENGTH
1368
+ if (new_rangeParams === null) new_rangeParams = { ...params };
1369
+ new_rangeParams.endNodeIndex = params.endNodeIndex + 1;
1370
+ new_rangeParams.endOffset = SMALL_SPACE_LENGTH;
1245
1371
  }
1246
1372
 
1247
1373
  if (new_rangeParams !== null) {
1248
- this._setRangeParams(new_rangeParams)
1249
- event.preventDefault()
1250
- return
1374
+ this._setRangeParams(new_rangeParams);
1375
+ event.preventDefault();
1376
+ return;
1251
1377
  }
1252
1378
 
1253
- this.updateActiveButtons()
1379
+ this.updateActiveButtons();
1254
1380
  } catch (error) {
1255
- console.error(error)
1381
+ console.error(error);
1256
1382
  }
1257
-
1258
- }
1383
+ };
1259
1384
 
1260
1385
  handleEquationEditorClose = () => {
1261
1386
  try {
1262
- this.setState({showEquationEditor:false}, () => {
1263
- this.editableDiv.focus()
1387
+ this.setState({ showEquationEditor: false }, () => {
1388
+ this.editableDiv.focus();
1264
1389
  // this._setRangeParams(getOldRangeParams)
1265
- })
1390
+ });
1266
1391
  } catch (error) {
1267
- console.error(error)
1392
+ console.error(error);
1268
1393
  }
1269
- }
1394
+ };
1270
1395
 
1271
1396
  handleEquationEditorInsert = (latex) => {
1272
1397
  try {
1273
1398
  // console.log("Inserting latex: "+latex)
1274
-
1275
- let start_pos = this.markedRawText.indexOf(MARK)
1276
- let end_pos = this.markedRawText.indexOf(MARK, start_pos + MARK.length)
1277
- let oldRangeParams = this.getOldRangeParams()
1278
-
1399
+
1400
+ let start_pos = this.markedRawText.indexOf(MARK);
1401
+ let end_pos = this.markedRawText.indexOf(MARK, start_pos + MARK.length);
1402
+ let oldRangeParams = this.getOldRangeParams();
1403
+
1279
1404
  // Handle case of empty string returned
1280
1405
  if (latex === "") {
1281
1406
  // console.log("Empty latex returned from equation editor")
1282
- let new_raw_text =
1283
- this.markedRawText.substring(0,start_pos) +
1284
- this.markedRawText.substring(end_pos + MARK.length)
1407
+ let new_raw_text =
1408
+ this.markedRawText.substring(0, start_pos) +
1409
+ this.markedRawText.substring(end_pos + MARK.length);
1285
1410
 
1286
1411
  // Delete node if it was a latex node
1287
- let new_index = -1
1288
- let new_offset = -1
1412
+ let new_index = -1;
1413
+ let new_offset = -1;
1289
1414
  if (this.editingExistingEquation) {
1290
-
1291
- let indexOfEditedNode = this._findIndexOfNode(this.editingNode)
1415
+ let indexOfEditedNode = this._findIndexOfNode(this.editingNode);
1292
1416
 
1293
1417
  if (oldRangeParams.startNodeIndex === indexOfEditedNode + 1) {
1294
- new_index = oldRangeParams.startNodeIndex-2
1295
- new_offset = getNodeTextLength(this._findNodeWithIndex(new_index))
1418
+ new_index = oldRangeParams.startNodeIndex - 2;
1419
+ new_offset = getNodeTextLength(this._findNodeWithIndex(new_index));
1296
1420
  } else if (oldRangeParams.startNodeIndex > indexOfEditedNode + 1) {
1297
- new_index = oldRangeParams.startNodeIndex-2
1298
- new_offset = oldRangeParams.startOffset
1421
+ new_index = oldRangeParams.startNodeIndex - 2;
1422
+ new_offset = oldRangeParams.startOffset;
1299
1423
  } else {
1300
- new_index = oldRangeParams.startNodeIndex
1301
- new_offset = oldRangeParams.startOffset
1424
+ new_index = oldRangeParams.startNodeIndex;
1425
+ new_offset = oldRangeParams.startOffset;
1302
1426
  }
1303
1427
  }
1304
1428
 
1305
1429
  let new_rangeParams = {
1306
- startNodeIndex:new_index,
1307
- startOffset:new_offset,
1308
- endNodeIndex:new_index,
1309
- endOffset:new_offset}
1310
- this.setOldRangeParams(new_rangeParams)
1311
-
1312
- let nodeCounts = this._countNodeTypes()
1313
- let mimeType = null
1430
+ startNodeIndex: new_index,
1431
+ startOffset: new_offset,
1432
+ endNodeIndex: new_index,
1433
+ endOffset: new_offset,
1434
+ };
1435
+ this.setOldRangeParams(new_rangeParams);
1436
+
1437
+ let nodeCounts = this._countNodeTypes();
1438
+ let mimeType = null;
1314
1439
  if (this.editingExistingEquation)
1315
- mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.katex > 1)
1440
+ mimeType = this.getMimeType(
1441
+ nodeCounts.html > 0,
1442
+ nodeCounts.katex > 1
1443
+ );
1316
1444
  else
1317
- mimeType = this.getMimeType(nodeCounts.html > 0, nodeCounts.katex > 0)
1318
- new_raw_text = removeEncodingIfPlainText(new_raw_text, mimeType, this.enableHtml())
1319
-
1320
- this.applyChangesToComponent(new_raw_text, mimeType, new_rangeParams,
1321
- this.props.useExpertMode, this.props.selectedTab)
1322
- this.setState({showEquationEditor:false})
1323
- return
1445
+ mimeType = this.getMimeType(
1446
+ nodeCounts.html > 0,
1447
+ nodeCounts.katex > 0
1448
+ );
1449
+ new_raw_text = removeEncodingIfPlainText(
1450
+ new_raw_text,
1451
+ mimeType,
1452
+ this.enableHtml()
1453
+ );
1454
+
1455
+ this.applyChangesToComponent(
1456
+ new_raw_text,
1457
+ mimeType,
1458
+ new_rangeParams,
1459
+ this.props.useExpertMode,
1460
+ this.props.selectedTab
1461
+ );
1462
+ this.setState({ showEquationEditor: false });
1463
+ return;
1324
1464
  }
1325
1465
 
1326
1466
  // Handle case of latex returned, in which case we update the katex node
1327
1467
  // console.log("Latex returned from equation editor: "+latex)
1328
- let new_raw_text = replaceMarksWithMath(this.markedRawText, latex, this.enableHtml())
1329
- // let new_raw_text =
1330
- // this.markedRawText.substring(0,start_pos) +
1468
+ let new_raw_text = replaceMarksWithMath(
1469
+ this.markedRawText,
1470
+ latex,
1471
+ this.enableHtml()
1472
+ );
1473
+ // let new_raw_text =
1474
+ // this.markedRawText.substring(0,start_pos) +
1331
1475
  // RAW_TEXT_MATH_START_TAG + latex + RAW_TEXT_MATH_END_TAG +
1332
1476
  // this.markedRawText.substring(end_pos + MARK.length)
1333
1477
 
1334
- console.log("Old cursor pos: "+oldRangeParams.startNodeIndex+"->"+oldRangeParams.startOffset)
1335
- console.log("Old raw text: "+this.props.value)
1336
- console.log("Old raw text length: "+this.props.value.length)
1337
- console.log("Old marked raw text:"+this.markedRawText)
1338
- console.log("New raw text: "+new_raw_text)
1339
-
1340
- let new_rangeParams = this.getOldRangeParams()
1478
+ console.log(
1479
+ "Old cursor pos: " +
1480
+ oldRangeParams.startNodeIndex +
1481
+ "->" +
1482
+ oldRangeParams.startOffset
1483
+ );
1484
+ console.log("Old raw text: " + this.props.value);
1485
+ console.log("Old raw text length: " + this.props.value.length);
1486
+ console.log("Old marked raw text:" + this.markedRawText);
1487
+ console.log("New raw text: " + new_raw_text);
1488
+
1489
+ let new_rangeParams = this.getOldRangeParams();
1341
1490
  if (this.moveCursorOnInsert) {
1342
- if (this.props.value === "") // Special case of previously empty text input
1491
+ if (this.props.value === "")
1492
+ // Special case of previously empty text input
1343
1493
  new_rangeParams = {
1344
- startNodeIndex:2,
1345
- startOffset:SMALL_SPACE_LENGTH,
1346
- endNodeIndex:2,
1347
- endOffset:SMALL_SPACE_LENGTH }
1348
- else // normal case
1494
+ startNodeIndex: 2,
1495
+ startOffset: SMALL_SPACE_LENGTH,
1496
+ endNodeIndex: 2,
1497
+ endOffset: SMALL_SPACE_LENGTH,
1498
+ };
1499
+ // normal case
1500
+ else
1349
1501
  new_rangeParams = {
1350
- startNodeIndex:oldRangeParams.startNodeIndex+2,
1351
- startOffset:SMALL_SPACE_LENGTH,
1352
- endNodeIndex:oldRangeParams.startNodeIndex+2,
1353
- endOffset:SMALL_SPACE_LENGTH }
1502
+ startNodeIndex: oldRangeParams.startNodeIndex + 2,
1503
+ startOffset: SMALL_SPACE_LENGTH,
1504
+ endNodeIndex: oldRangeParams.startNodeIndex + 2,
1505
+ endOffset: SMALL_SPACE_LENGTH,
1506
+ };
1354
1507
  }
1355
1508
  // console.log("New cursor pos: "+new_rangeParams.startNodeIndex+"->"+new_rangeParams.startOffset)
1356
- this.setOldRangeParams(new_rangeParams)
1357
-
1358
- let nodeCounts = this._countNodeTypes()
1359
- let mimeType = this.getMimeType(nodeCounts.html > 0, true)
1360
- new_raw_text = removeEncodingIfPlainText(new_raw_text, mimeType, this.enableHtml())
1361
-
1362
- this.applyChangesToComponent(new_raw_text, mimeType, new_rangeParams,
1363
- this.props.useExpertMode, this.props.selectedTab)
1364
- this.setState({showEquationEditor:false})
1509
+ this.setOldRangeParams(new_rangeParams);
1510
+
1511
+ let nodeCounts = this._countNodeTypes();
1512
+ let mimeType = this.getMimeType(nodeCounts.html > 0, true);
1513
+ new_raw_text = removeEncodingIfPlainText(
1514
+ new_raw_text,
1515
+ mimeType,
1516
+ this.enableHtml()
1517
+ );
1518
+
1519
+ this.applyChangesToComponent(
1520
+ new_raw_text,
1521
+ mimeType,
1522
+ new_rangeParams,
1523
+ this.props.useExpertMode,
1524
+ this.props.selectedTab
1525
+ );
1526
+ this.setState({ showEquationEditor: false });
1365
1527
  } catch (error) {
1366
- console.error(error)
1528
+ console.error(error);
1367
1529
  }
1368
- }
1530
+ };
1369
1531
 
1370
1532
  // findEditableDiv = (node) => {
1371
1533
  // if (node === null)
1372
1534
  // return null
1373
- // if (node.classList !== null && node.classList !== undefined &&
1535
+ // if (node.classList !== null && node.classList !== undefined &&
1374
1536
  // node.classList.contains("MathRichInput"))
1375
1537
  // return node
1376
1538
  // return this.findEditableDiv(node.parentNode);
@@ -1378,294 +1540,393 @@ export default class MathRichInput extends React.Component {
1378
1540
 
1379
1541
  styleText = (event, style) => {
1380
1542
  try {
1381
- style = style.toLowerCase()
1382
- let success = document.execCommand(style,false, null)
1383
- let buttonState = this.state.activeButtons[style]
1384
- if (buttonState === null || buttonState === undefined)
1385
- return success
1386
-
1387
- buttonState = !buttonState
1388
- let new_activeButtons = {...this.state.activeButtons}
1389
- new_activeButtons[style] = buttonState
1390
- this.setState({activeButtons:new_activeButtons})
1391
- return success
1543
+ style = style.toLowerCase();
1544
+ let success = document.execCommand(style, false, null);
1545
+ let buttonState = this.state.activeButtons[style];
1546
+ if (buttonState === null || buttonState === undefined) return success;
1547
+
1548
+ buttonState = !buttonState;
1549
+ let new_activeButtons = { ...this.state.activeButtons };
1550
+ new_activeButtons[style] = buttonState;
1551
+ this.setState({ activeButtons: new_activeButtons });
1552
+ return success;
1392
1553
  } catch (error) {
1393
- console.error(error)
1554
+ console.error(error);
1394
1555
  }
1395
- }
1556
+ };
1396
1557
 
1397
1558
  handleToolbarButtonClick = (event, buttonName) => {
1398
- console.log("button name: ",buttonName)
1559
+ console.log("button name: ", buttonName);
1399
1560
  try {
1400
1561
  if (buttonName === "Equation") {
1401
- this.showEquationEditor(true)
1562
+ this.showEquationEditor(true);
1402
1563
  }
1403
- let style = buttonName
1404
- let success = this.styleText(event, style)
1405
- if (!success)
1406
- console.warn("execCommand returned false: "+style)
1564
+ let style = buttonName;
1565
+ let success = this.styleText(event, style);
1566
+ if (!success) console.warn("execCommand returned false: " + style);
1407
1567
  } catch (error) {
1408
- console.error(error)
1568
+ console.error(error);
1409
1569
  }
1410
- }
1570
+ };
1411
1571
 
1412
1572
  fetchAccentLetter = (event) => {
1413
1573
  try {
1414
- let rangeParams = this._getRangeParams()
1574
+ let rangeParams = this._getRangeParams();
1415
1575
  if (rangeParams === null) {
1416
- console.error("Cound not get range params")
1417
- return null
1576
+ console.error("Cound not get range params");
1577
+ return null;
1418
1578
  }
1419
- let node = this._findNodeWithIndex(rangeParams.endNodeIndex)
1420
- let offset = rangeParams.endOffset
1579
+ let node = this._findNodeWithIndex(rangeParams.endNodeIndex);
1580
+ let offset = rangeParams.endOffset;
1421
1581
 
1422
- let raw_text = elementToMarkedRawText(this.editableDiv, node, offset, this.enableHtml())
1582
+ let raw_text = elementToMarkedRawText(
1583
+ this.editableDiv,
1584
+ node,
1585
+ offset,
1586
+ this.enableHtml()
1587
+ );
1423
1588
 
1424
- return getCharacterBeforeMarks(raw_text)
1589
+ return getCharacterBeforeMarks(raw_text);
1425
1590
  } catch (error) {
1426
- console.error(error)
1591
+ console.error(error);
1427
1592
  }
1428
- }
1593
+ };
1429
1594
 
1430
1595
  insertRawText = (event, new_text) => {
1431
1596
  try {
1432
- let rangeParams = this._getRangeParams()
1433
- let node = this._findNodeWithIndex(rangeParams.endNodeIndex)
1434
- let offset = rangeParams.endOffset
1435
-
1436
- let raw_text = elementToMarkedRawText(this.editableDiv, node, offset, this.enableHtml())
1437
- let new_raw_text = null
1438
- let new_rangeParams = {...rangeParams}
1439
- new_raw_text = removeMarks(insertCharacterBeforeMarks(raw_text, new_text))
1440
- if (rangeParams.startNodeIndex === rangeParams.endNodeIndex &&
1441
- rangeParams.startOffset === rangeParams.endOffset)
1442
- new_rangeParams.startOffset = new_rangeParams.startOffset + new_text.length
1443
- new_rangeParams.endOffset = new_rangeParams.endOffset + new_text.length
1444
-
1445
- new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1446
-
1447
- this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1448
- this.props.useExpertMode, this.props.selectedTab)
1597
+ let rangeParams = this._getRangeParams();
1598
+ let node = this._findNodeWithIndex(rangeParams.endNodeIndex);
1599
+ let offset = rangeParams.endOffset;
1600
+
1601
+ let raw_text = elementToMarkedRawText(
1602
+ this.editableDiv,
1603
+ node,
1604
+ offset,
1605
+ this.enableHtml()
1606
+ );
1607
+ let new_raw_text = null;
1608
+ let new_rangeParams = { ...rangeParams };
1609
+ new_raw_text = removeMarks(
1610
+ insertCharacterBeforeMarks(raw_text, new_text)
1611
+ );
1612
+ if (
1613
+ rangeParams.startNodeIndex === rangeParams.endNodeIndex &&
1614
+ rangeParams.startOffset === rangeParams.endOffset
1615
+ )
1616
+ new_rangeParams.startOffset =
1617
+ new_rangeParams.startOffset + new_text.length;
1618
+ new_rangeParams.endOffset = new_rangeParams.endOffset + new_text.length;
1619
+
1620
+ new_raw_text = removeEncodingIfPlainText(
1621
+ new_raw_text,
1622
+ this.state.mimeType,
1623
+ this.enableHtml()
1624
+ );
1625
+
1626
+ this.applyChangesToComponent(
1627
+ new_raw_text,
1628
+ this.state.mimeType,
1629
+ new_rangeParams,
1630
+ this.props.useExpertMode,
1631
+ this.props.selectedTab
1632
+ );
1449
1633
  } catch (error) {
1450
- console.error(error)
1451
- }
1452
- }
1634
+ console.error(error);
1635
+ }
1636
+ };
1453
1637
 
1454
1638
  removeNewLine = () => {
1455
1639
  try {
1456
- let rangeParams = this._getRangeParams()
1457
- let node = this._findNodeWithIndex(rangeParams.endNodeIndex)
1458
- let prevNode = this._findNodeWithIndex(rangeParams.endNodeIndex-1)
1459
- let offset = rangeParams.endOffset
1460
-
1461
- let raw_text = elementToMarkedRawText(this.editableDiv, node, offset, this.enableHtml())
1462
- let new_raw_text = null
1463
- new_raw_text = removeMarks(replaceStringBeforeMarks(raw_text, "</p><p>",""))
1464
-
1465
- let new_rangeParams = {...rangeParams}
1466
- let new_offset = getNodeTextLength(prevNode)
1467
- new_rangeParams.startNodeIndex = rangeParams.startNodeIndex - 1
1468
- new_rangeParams.startOffset = new_offset
1469
- new_rangeParams.endNodeIndex = rangeParams.endNodeIndex - 1
1470
- new_rangeParams.endOffset = new_offset
1471
-
1472
- console.log("About to apply new range params")
1473
- console.log(new_rangeParams)
1474
- console.log("Old nodes")
1475
- console.log(this.editableDiv.childNodes)
1476
-
1477
- new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1478
-
1479
- this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1480
- this.props.useExpertMode, this.props.selectedTab)
1640
+ let rangeParams = this._getRangeParams();
1641
+ let node = this._findNodeWithIndex(rangeParams.endNodeIndex);
1642
+ let prevNode = this._findNodeWithIndex(rangeParams.endNodeIndex - 1);
1643
+ let offset = rangeParams.endOffset;
1644
+
1645
+ let raw_text = elementToMarkedRawText(
1646
+ this.editableDiv,
1647
+ node,
1648
+ offset,
1649
+ this.enableHtml()
1650
+ );
1651
+ let new_raw_text = null;
1652
+ new_raw_text = removeMarks(
1653
+ replaceStringBeforeMarks(raw_text, "</p><p>", "")
1654
+ );
1655
+
1656
+ let new_rangeParams = { ...rangeParams };
1657
+ let new_offset = getNodeTextLength(prevNode);
1658
+ new_rangeParams.startNodeIndex = rangeParams.startNodeIndex - 1;
1659
+ new_rangeParams.startOffset = new_offset;
1660
+ new_rangeParams.endNodeIndex = rangeParams.endNodeIndex - 1;
1661
+ new_rangeParams.endOffset = new_offset;
1662
+
1663
+ console.log("About to apply new range params");
1664
+ console.log(new_rangeParams);
1665
+ console.log("Old nodes");
1666
+ console.log(this.editableDiv.childNodes);
1667
+
1668
+ new_raw_text = removeEncodingIfPlainText(
1669
+ new_raw_text,
1670
+ this.state.mimeType,
1671
+ this.enableHtml()
1672
+ );
1673
+
1674
+ this.applyChangesToComponent(
1675
+ new_raw_text,
1676
+ this.state.mimeType,
1677
+ new_rangeParams,
1678
+ this.props.useExpertMode,
1679
+ this.props.selectedTab
1680
+ );
1481
1681
  } catch (error) {
1482
- console.error(error)
1483
- }
1484
- }
1682
+ console.error(error);
1683
+ }
1684
+ };
1485
1685
 
1486
1686
  insertNewLine = () => {
1487
1687
  try {
1488
- let rangeParams = this._getRangeParams()
1489
- let node = this._findNodeWithIndex(rangeParams.endNodeIndex)
1490
- let offset = rangeParams.endOffset
1491
-
1492
- let raw_text = elementToMarkedRawText(this.editableDiv, node, offset, this.enableHtml())
1493
- let new_raw_text = null
1494
- let new_rangeParams = {...rangeParams}
1688
+ let rangeParams = this._getRangeParams();
1689
+ let node = this._findNodeWithIndex(rangeParams.endNodeIndex);
1690
+ let offset = rangeParams.endOffset;
1691
+
1692
+ let raw_text = elementToMarkedRawText(
1693
+ this.editableDiv,
1694
+ node,
1695
+ offset,
1696
+ this.enableHtml()
1697
+ );
1698
+ let new_raw_text = null;
1699
+ let new_rangeParams = { ...rangeParams };
1495
1700
 
1496
1701
  if (this.enableHtml()) {
1497
- new_raw_text = removeMarks(insertCharacterBeforeMarks(raw_text, "</p><p>"))
1498
- if (new_raw_text.substring(0,3).toLowerCase() !== "<p>")
1499
- new_raw_text = "<p>" + new_raw_text + "</p>"
1500
-
1501
- new_rangeParams.startNodeIndex = rangeParams.startNodeIndex + 1
1502
- new_rangeParams.startOffset = 0
1503
- new_rangeParams.endNodeIndex = rangeParams.endNodeIndex + 1
1504
- new_rangeParams.endOffset = 0
1702
+ new_raw_text = removeMarks(
1703
+ insertCharacterBeforeMarks(raw_text, "</p><p>")
1704
+ );
1705
+ if (new_raw_text.substring(0, 3).toLowerCase() !== "<p>")
1706
+ new_raw_text = "<p>" + new_raw_text + "</p>";
1707
+
1708
+ new_rangeParams.startNodeIndex = rangeParams.startNodeIndex + 1;
1709
+ new_rangeParams.startOffset = 0;
1710
+ new_rangeParams.endNodeIndex = rangeParams.endNodeIndex + 1;
1711
+ new_rangeParams.endOffset = 0;
1505
1712
  } else {
1506
- new_raw_text = removeMarks(insertCharacterBeforeMarks(raw_text, "\n"))
1507
- new_rangeParams.startOffset ++
1508
- new_rangeParams.endOffset ++
1713
+ new_raw_text = removeMarks(insertCharacterBeforeMarks(raw_text, "\n"));
1714
+ new_rangeParams.startOffset++;
1715
+ new_rangeParams.endOffset++;
1509
1716
  }
1510
1717
 
1511
-
1512
- console.log("About to apply new range params")
1513
- console.log(new_rangeParams)
1514
- console.log("Old nodes")
1515
- console.log(this.editableDiv.childNodes)
1516
-
1517
- new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1518
-
1519
- this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1520
- this.props.useExpertMode, this.props.selectedTab)
1718
+ console.log("About to apply new range params");
1719
+ console.log(new_rangeParams);
1720
+ console.log("Old nodes");
1721
+ console.log(this.editableDiv.childNodes);
1722
+
1723
+ new_raw_text = removeEncodingIfPlainText(
1724
+ new_raw_text,
1725
+ this.state.mimeType,
1726
+ this.enableHtml()
1727
+ );
1728
+
1729
+ this.applyChangesToComponent(
1730
+ new_raw_text,
1731
+ this.state.mimeType,
1732
+ new_rangeParams,
1733
+ this.props.useExpertMode,
1734
+ this.props.selectedTab
1735
+ );
1521
1736
  } catch (error) {
1522
- console.error(error)
1523
- }
1524
- }
1737
+ console.error(error);
1738
+ }
1739
+ };
1525
1740
 
1526
1741
  replaceNextLetter = (new_char) => {
1527
1742
  try {
1528
- console.log("Replace next letter")
1529
- let rangeParams = this._getRangeParams()
1530
- let node = this._findNodeWithIndex(rangeParams.endNodeIndex)
1531
- let offset = rangeParams.endOffset+1 // next letter
1532
-
1533
- let raw_text = elementToMarkedRawText(this.editableDiv, node, offset, this.enableHtml())
1534
- let new_raw_text = null
1535
- let new_rangeParams = {...rangeParams}
1536
- new_raw_text = removeMarks(insertCharacterBeforeMarks(raw_text, new_char))
1537
- if (rangeParams.startNodeIndex === rangeParams.endNodeIndex &&
1538
- rangeParams.startOffset === rangeParams.endOffset)
1539
- new_rangeParams.startOffset = new_rangeParams.startOffset + new_char.length + 1
1540
- new_rangeParams.endOffset = new_rangeParams.endOffset + new_char.length + 1
1541
-
1542
- new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1543
- this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1544
- this.props.useExpertMode, this.props.selectedTab)
1743
+ console.log("Replace next letter");
1744
+ let rangeParams = this._getRangeParams();
1745
+ let node = this._findNodeWithIndex(rangeParams.endNodeIndex);
1746
+ let offset = rangeParams.endOffset + 1; // next letter
1747
+
1748
+ let raw_text = elementToMarkedRawText(
1749
+ this.editableDiv,
1750
+ node,
1751
+ offset,
1752
+ this.enableHtml()
1753
+ );
1754
+ let new_raw_text = null;
1755
+ let new_rangeParams = { ...rangeParams };
1756
+ new_raw_text = removeMarks(
1757
+ insertCharacterBeforeMarks(raw_text, new_char)
1758
+ );
1759
+ if (
1760
+ rangeParams.startNodeIndex === rangeParams.endNodeIndex &&
1761
+ rangeParams.startOffset === rangeParams.endOffset
1762
+ )
1763
+ new_rangeParams.startOffset =
1764
+ new_rangeParams.startOffset + new_char.length + 1;
1765
+ new_rangeParams.endOffset =
1766
+ new_rangeParams.endOffset + new_char.length + 1;
1767
+
1768
+ new_raw_text = removeEncodingIfPlainText(
1769
+ new_raw_text,
1770
+ this.state.mimeType,
1771
+ this.enableHtml()
1772
+ );
1773
+ this.applyChangesToComponent(
1774
+ new_raw_text,
1775
+ this.state.mimeType,
1776
+ new_rangeParams,
1777
+ this.props.useExpertMode,
1778
+ this.props.selectedTab
1779
+ );
1545
1780
  } catch (error) {
1546
- console.error(error)
1781
+ console.error(error);
1547
1782
  }
1548
- }
1783
+ };
1549
1784
 
1550
1785
  insertAccentLetter = (event, old_char, new_char) => {
1551
1786
  try {
1552
- let rangeParams = this._getRangeParams()
1553
- let node = this._findNodeWithIndex(rangeParams.endNodeIndex)
1554
- let offset = rangeParams.endOffset
1555
-
1556
- let raw_text = elementToMarkedRawText(this.editableDiv, node, offset, this.enableHtml())
1557
- let new_raw_text = null
1558
- let new_rangeParams = {...rangeParams}
1787
+ let rangeParams = this._getRangeParams();
1788
+ let node = this._findNodeWithIndex(rangeParams.endNodeIndex);
1789
+ let offset = rangeParams.endOffset;
1790
+
1791
+ let raw_text = elementToMarkedRawText(
1792
+ this.editableDiv,
1793
+ node,
1794
+ offset,
1795
+ this.enableHtml()
1796
+ );
1797
+ let new_raw_text = null;
1798
+ let new_rangeParams = { ...rangeParams };
1559
1799
  if (old_char === null) {
1560
- new_raw_text = removeMarks(insertCharacterBeforeMarks(raw_text, new_char))
1561
- if (rangeParams.startNodeIndex === rangeParams.endNodeIndex &&
1562
- rangeParams.startOffset === rangeParams.endOffset)
1563
- new_rangeParams.startOffset = new_rangeParams.startOffset + new_char.length
1564
- new_rangeParams.endOffset = new_rangeParams.endOffset + new_char.length
1565
- }
1566
- else
1567
- new_raw_text = removeMarks(replaceCharacterBeforeMarks(raw_text, new_char))
1568
-
1569
- new_raw_text = removeEncodingIfPlainText(new_raw_text, this.state.mimeType, this.enableHtml())
1570
- this.applyChangesToComponent(new_raw_text, this.state.mimeType, new_rangeParams,
1571
- this.props.useExpertMode, this.props.selectedTab)
1800
+ new_raw_text = removeMarks(
1801
+ insertCharacterBeforeMarks(raw_text, new_char)
1802
+ );
1803
+ if (
1804
+ rangeParams.startNodeIndex === rangeParams.endNodeIndex &&
1805
+ rangeParams.startOffset === rangeParams.endOffset
1806
+ )
1807
+ new_rangeParams.startOffset =
1808
+ new_rangeParams.startOffset + new_char.length;
1809
+ new_rangeParams.endOffset = new_rangeParams.endOffset + new_char.length;
1810
+ } else
1811
+ new_raw_text = removeMarks(
1812
+ replaceCharacterBeforeMarks(raw_text, new_char)
1813
+ );
1814
+
1815
+ new_raw_text = removeEncodingIfPlainText(
1816
+ new_raw_text,
1817
+ this.state.mimeType,
1818
+ this.enableHtml()
1819
+ );
1820
+ this.applyChangesToComponent(
1821
+ new_raw_text,
1822
+ this.state.mimeType,
1823
+ new_rangeParams,
1824
+ this.props.useExpertMode,
1825
+ this.props.selectedTab
1826
+ );
1572
1827
  } catch (error) {
1573
- console.error(error)
1828
+ console.error(error);
1574
1829
  }
1575
- }
1830
+ };
1576
1831
 
1577
1832
  handleAccentButtonClick = (event, oldCharacter, newCharacter) => {
1578
1833
  try {
1579
- this.insertAccentLetter(event, oldCharacter, newCharacter)
1580
- this.setState({showAccentBar:false})
1834
+ this.insertAccentLetter(event, oldCharacter, newCharacter);
1835
+ this.setState({ showAccentBar: false });
1581
1836
  } catch (error) {
1582
- console.error(error)
1837
+ console.error(error);
1583
1838
  }
1584
- }
1585
-
1839
+ };
1586
1840
 
1587
1841
  handleFocus = (event) => {
1588
1842
  // console.log("handleFocus")
1589
1843
  try {
1590
- this._setRangeParams(this.getOldRangeParams())
1591
- this.setState({hasFocus:true})
1844
+ this._setRangeParams(this.getOldRangeParams());
1845
+ this.setState({ hasFocus: true });
1592
1846
  } catch (error) {
1593
- console.error(error)
1847
+ console.error(error);
1594
1848
  }
1595
- }
1849
+ };
1596
1850
 
1597
1851
  handleBlur = (event) => {
1598
1852
  try {
1599
- this.setState({hasFocus:false, showAccentBar:false})
1853
+ this.setState({ hasFocus: false, showAccentBar: false });
1600
1854
  } catch (error) {
1601
- console.error(error)
1855
+ console.error(error);
1602
1856
  }
1603
- }
1604
-
1857
+ };
1858
+
1605
1859
  render() {
1606
- console.log("Rendering MathRichInput. Latex: "+this.props.value)
1860
+ console.log("Rendering MathRichInput. Latex: " + this.props.value);
1607
1861
 
1608
- if (this.props.value === undefined ) {
1609
- console.error("MathRichInput must have prop called \"text\"")
1610
- console.log(this.props)
1862
+ if (this.props.value === undefined) {
1863
+ console.error('MathRichInput must have prop called "text"');
1864
+ console.log(this.props);
1611
1865
  }
1612
1866
 
1613
- const html = rawTextToHtml(katex, this.props.value || "", this.props.mimeType);
1867
+ const html = rawTextToHtml(
1868
+ katex,
1869
+ this.props.value || "",
1870
+ this.props.mimeType
1871
+ );
1614
1872
 
1615
- let useClassName = "MathRichInput-Container" // Don't change this name - used by various components to find node
1873
+ let useClassName = "MathRichInput-Container"; // Don't change this name - used by various components to find node
1616
1874
  if (this.props.className)
1617
- useClassName = this.props.className + " " + useClassName
1618
-
1619
- let accentLetter = null
1620
- if (this.state.showAccentBar)
1621
- accentLetter = this.fetchAccentLetter(null)
1622
-
1623
- return <>
1624
- <div className={useClassName}>
1625
- <div className="MathRichInput-scrollview">
1626
- {this.state.hasFocus &&
1627
- <Toolbar
1628
- className="Toolbar"
1629
- enableMath={this.enableMath()}
1630
- enableFontStyling={this.enableFontStyling()}
1631
- style={this.translateToolbar}
1632
- keyPressed={this.state.keyPressed}
1633
- activeButtons={this.state.activeButtons}
1634
- onButtonClick={this.handleToolbarButtonClick}
1635
- fetchAccentLetter={this.fetchAccentLetter}
1636
- insertAccentLetter={this.insertAccentLetter}
1637
- />
1638
- }
1639
- {this.state.showAccentBar &&
1640
- <AccentBar
1641
- compactMode={true}
1642
- accentLetter={accentLetter}
1643
- keyPressed={this.state.keyPressed}
1644
- fetchAccentLetter={this.fetchAccentLetter}
1645
- onButtonClick={(e, oldCharacter, newCharacter) =>
1646
- this.handleAccentButtonClick(e, oldCharacter, newCharacter)}/>
1647
- }
1648
- <span
1649
- className="MathRichInput" // Don't change this name - used to various components to find node
1650
- contentEditable="true"
1651
- ref={(r) => this.editableDiv = r}
1652
- onInput={this.handleInput}
1653
- onMouseDown={this.handleMouseDown}
1654
- onMouseUp={this.handleMouseUp}
1655
- onFocus={this.handleFocus}
1656
- onBlur={this.handleBlur}
1657
- dangerouslySetInnerHTML={{__html: html}}
1658
- >
1659
- </span>
1875
+ useClassName = this.props.className + " " + useClassName;
1876
+
1877
+ let accentLetter = null;
1878
+ if (this.state.showAccentBar) accentLetter = this.fetchAccentLetter(null);
1879
+
1880
+ return (
1881
+ <>
1882
+ <div className={useClassName}>
1883
+ <div className="MathRichInput-scrollview">
1884
+ {this.state.hasFocus && (
1885
+ <Toolbar
1886
+ className="Toolbar"
1887
+ enableMath={this.enableMath()}
1888
+ enableFontStyling={this.enableFontStyling()}
1889
+ style={this.translateToolbar}
1890
+ keyPressed={this.state.keyPressed}
1891
+ activeButtons={this.state.activeButtons}
1892
+ onButtonClick={this.handleToolbarButtonClick}
1893
+ fetchAccentLetter={this.fetchAccentLetter}
1894
+ insertAccentLetter={this.insertAccentLetter}
1895
+ />
1896
+ )}
1897
+ {this.state.showAccentBar && (
1898
+ <AccentBar
1899
+ compactMode={true}
1900
+ accentLetter={accentLetter}
1901
+ keyPressed={this.state.keyPressed}
1902
+ fetchAccentLetter={this.fetchAccentLetter}
1903
+ onButtonClick={(e, oldCharacter, newCharacter) =>
1904
+ this.handleAccentButtonClick(e, oldCharacter, newCharacter)
1905
+ }
1906
+ />
1907
+ )}
1908
+ <span
1909
+ className="MathRichInput" // Don't change this name - used to various components to find node
1910
+ contentEditable="true"
1911
+ ref={(r) => (this.editableDiv = r)}
1912
+ onInput={this.handleInput}
1913
+ onMouseDown={this.handleMouseDown}
1914
+ onMouseUp={this.handleMouseUp}
1915
+ onFocus={this.handleFocus}
1916
+ onBlur={this.handleBlur}
1917
+ dangerouslySetInnerHTML={{ __html: html }}
1918
+ ></span>
1919
+ </div>
1660
1920
  </div>
1661
- </div>
1662
- { this.state.showEquationEditor &&
1663
- <EquationEditorModal
1664
- ref={(r) => this.equationEditorModal = r}
1665
- handleClose={this.handleEquationEditorClose}
1666
- handleInsert={this.handleEquationEditorInsert}
1667
- latex={this.state.equationEditorLatex}/>
1668
- }
1669
- </>
1921
+ {this.state.showEquationEditor && (
1922
+ <EquationEditorModal
1923
+ ref={(r) => (this.equationEditorModal = r)}
1924
+ handleClose={this.handleEquationEditorClose}
1925
+ handleInsert={this.handleEquationEditorInsert}
1926
+ latex={this.state.equationEditorLatex}
1927
+ />
1928
+ )}
1929
+ </>
1930
+ );
1670
1931
  }
1671
- }
1932
+ }