@zzish/math-rich-input 0.1.47 → 0.1.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1040 -117
- package/dist/math-rich-input.css +1 -1
- package/dist/standalone.js +2 -0
- package/dist/standalone.js.LICENSE.txt +29 -0
- package/package.json +13 -3
- package/src/EquationEditor.jsx +557 -527
- package/src/EquationEditorModal.jsx +104 -58
- package/src/MathRichInput.jsx +2892 -1924
- package/src/Toolbar.jsx +234 -219
- package/src/mathRichInputHelper.js +787 -557
- package/src/standalone.js +110 -0
- package/webpack.standalone.config.js +63 -0
- package/dist/index.css +0 -1
package/dist/index.js
CHANGED
|
@@ -18845,7 +18845,6 @@ var EquationEditor = /*#__PURE__*/function (_React$Component) {
|
|
|
18845
18845
|
});
|
|
18846
18846
|
});
|
|
18847
18847
|
_defineProperty(_this, "handleKeyDown", function (e) {
|
|
18848
|
-
// console.log(e.key)
|
|
18849
18848
|
try {
|
|
18850
18849
|
if (!_this.props.useExpertMode && e.key === "Enter") {
|
|
18851
18850
|
_this.handleInsertCallback(_this.state.latex);
|
|
@@ -19108,7 +19107,6 @@ var EquationEditor = /*#__PURE__*/function (_React$Component) {
|
|
|
19108
19107
|
key: "mathquillDidMount",
|
|
19109
19108
|
value: function mathquillDidMount(mathQuill) {
|
|
19110
19109
|
this.mathQuill = mathQuill;
|
|
19111
|
-
mathQuill.focus();
|
|
19112
19110
|
}
|
|
19113
19111
|
}, {
|
|
19114
19112
|
key: "componentDidMount",
|
|
@@ -19309,6 +19307,33 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19309
19307
|
_defineProperty(_this, "handleClose", function () {
|
|
19310
19308
|
_this.handleCloseCallback();
|
|
19311
19309
|
});
|
|
19310
|
+
_defineProperty(_this, "focusEquationEditor", function () {
|
|
19311
|
+
console.log("🔍 Focusing equation editor...");
|
|
19312
|
+
if (_this.equationEditor) {
|
|
19313
|
+
console.log("🔍 EquationEditor ref found");
|
|
19314
|
+
if (_this.state.useExpertMode) {
|
|
19315
|
+
// Focus textarea in expert mode
|
|
19316
|
+
console.log("🔍 Expert mode - focusing latexInput");
|
|
19317
|
+
if (_this.equationEditor.latexInput) {
|
|
19318
|
+
_this.equationEditor.latexInput.focus();
|
|
19319
|
+
console.log("✅ LatexInput focused");
|
|
19320
|
+
} else {
|
|
19321
|
+
console.log("❌ LatexInput not found");
|
|
19322
|
+
}
|
|
19323
|
+
} else {
|
|
19324
|
+
// Focus MathQuill in normal mode
|
|
19325
|
+
console.log("🔍 Normal mode - focusing mathQuill");
|
|
19326
|
+
if (_this.equationEditor.mathQuill) {
|
|
19327
|
+
_this.equationEditor.mathQuill.focus();
|
|
19328
|
+
console.log("✅ MathQuill focused");
|
|
19329
|
+
} else {
|
|
19330
|
+
console.log("❌ MathQuill not found");
|
|
19331
|
+
}
|
|
19332
|
+
}
|
|
19333
|
+
} else {
|
|
19334
|
+
console.log("❌ EquationEditor ref not found");
|
|
19335
|
+
}
|
|
19336
|
+
});
|
|
19312
19337
|
_this.state = {
|
|
19313
19338
|
useExpertMode: GLOBAL_lastSelectedExpertMode
|
|
19314
19339
|
};
|
|
@@ -19319,7 +19344,25 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19319
19344
|
_inherits(EquationEditorModal, _React$Component);
|
|
19320
19345
|
return _createClass(EquationEditorModal, [{
|
|
19321
19346
|
key: "componentDidMount",
|
|
19322
|
-
value: function componentDidMount() {
|
|
19347
|
+
value: function componentDidMount() {
|
|
19348
|
+
var _this2 = this;
|
|
19349
|
+
// Auto-focus when modal opens
|
|
19350
|
+
// Use setTimeout to ensure child components are fully mounted
|
|
19351
|
+
setTimeout(function () {
|
|
19352
|
+
_this2.focusEquationEditor();
|
|
19353
|
+
}, 100);
|
|
19354
|
+
}
|
|
19355
|
+
}, {
|
|
19356
|
+
key: "componentDidUpdate",
|
|
19357
|
+
value: function componentDidUpdate(prevProps, prevState) {
|
|
19358
|
+
var _this3 = this;
|
|
19359
|
+
// Re-focus when expert mode changes
|
|
19360
|
+
if (prevState.useExpertMode !== this.state.useExpertMode) {
|
|
19361
|
+
setTimeout(function () {
|
|
19362
|
+
_this3.focusEquationEditor();
|
|
19363
|
+
}, 100);
|
|
19364
|
+
}
|
|
19365
|
+
}
|
|
19323
19366
|
}, {
|
|
19324
19367
|
key: "isMobile",
|
|
19325
19368
|
value: function isMobile() {
|
|
@@ -19336,7 +19379,7 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19336
19379
|
}, {
|
|
19337
19380
|
key: "render",
|
|
19338
19381
|
value: function render() {
|
|
19339
|
-
var
|
|
19382
|
+
var _this4 = this;
|
|
19340
19383
|
var useClass = "EquationEditorModal";
|
|
19341
19384
|
if (this.isMobile()) useClass = "EquationEditorModal-mobile";
|
|
19342
19385
|
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
|
|
@@ -19345,7 +19388,7 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19345
19388
|
}), /*#__PURE__*/React__default["default"].createElement("div", {
|
|
19346
19389
|
className: useClass,
|
|
19347
19390
|
ref: function ref(r) {
|
|
19348
|
-
return
|
|
19391
|
+
return _this4.modalDiv = r;
|
|
19349
19392
|
}
|
|
19350
19393
|
}, !this.isMobile() && /*#__PURE__*/React__default["default"].createElement("div", {
|
|
19351
19394
|
className: "title"
|
|
@@ -19356,17 +19399,17 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19356
19399
|
}, /*#__PURE__*/React__default["default"].createElement("input", {
|
|
19357
19400
|
type: "checkbox",
|
|
19358
19401
|
ref: function ref(r) {
|
|
19359
|
-
return
|
|
19402
|
+
return _this4.expertModeSwitch = r;
|
|
19360
19403
|
},
|
|
19361
19404
|
onChange: function onChange(e) {
|
|
19362
|
-
return
|
|
19405
|
+
return _this4.handleExpertModeSwitchChange(e);
|
|
19363
19406
|
},
|
|
19364
19407
|
checked: this.state.useExpertMode
|
|
19365
19408
|
}), /*#__PURE__*/React__default["default"].createElement("span", {
|
|
19366
19409
|
className: "slider round"
|
|
19367
19410
|
})))), /*#__PURE__*/React__default["default"].createElement(EquationEditor, {
|
|
19368
19411
|
ref: function ref(r) {
|
|
19369
|
-
return
|
|
19412
|
+
return _this4.equationEditor = r;
|
|
19370
19413
|
},
|
|
19371
19414
|
latex: this.props.latex,
|
|
19372
19415
|
useExpertMode: this.state.useExpertMode,
|
|
@@ -20503,7 +20546,7 @@ var BLOCK_TEX_REG_EXP = /\$\$[\s\S]+?\$\$|\\\[[\s\S]+?\\\]/g;
|
|
|
20503
20546
|
|
|
20504
20547
|
// const HTML_MATH_REG_EXP = /<math>.*?<\/math>/gi;
|
|
20505
20548
|
var HTML_MATH_REG_EXP = /<math>[\s\S]*?<\/math>/gi;
|
|
20506
|
-
var SPAN_OPEN_BASE =
|
|
20549
|
+
var SPAN_OPEN_BASE = '<span class="base">';
|
|
20507
20550
|
var SPAN_CLOSE = "</span>";
|
|
20508
20551
|
var MARK$1 = String.fromCharCode(0);
|
|
20509
20552
|
// const MARK = "_M_A_R_K_"
|
|
@@ -20642,11 +20685,25 @@ function getLatex(node) {
|
|
|
20642
20685
|
// Example:
|
|
20643
20686
|
// <annotation encoding="application/x-tex">L' = {L}{\sqrt{1-\frac{v^2}{c^2}}}</annotation>
|
|
20644
20687
|
var annotation = getFirstDescendentByTagName(node, "annotation");
|
|
20688
|
+
|
|
20689
|
+
// Defensive checks for corrupt KaTeX nodes
|
|
20690
|
+
if (!annotation) {
|
|
20691
|
+
console.warn("KaTeX node missing annotation element");
|
|
20692
|
+
return "error";
|
|
20693
|
+
}
|
|
20694
|
+
if (!annotation.childNodes || annotation.childNodes.length === 0) {
|
|
20695
|
+
console.warn("KaTeX annotation element has no child nodes");
|
|
20696
|
+
return "error";
|
|
20697
|
+
}
|
|
20698
|
+
if (!annotation.childNodes[0] || !annotation.childNodes[0].nodeValue) {
|
|
20699
|
+
console.warn("KaTeX annotation missing text content");
|
|
20700
|
+
return "error";
|
|
20701
|
+
}
|
|
20645
20702
|
var latex = annotation.childNodes[0].nodeValue;
|
|
20646
20703
|
return latex;
|
|
20647
20704
|
} catch (error) {
|
|
20648
|
-
console.error(error);
|
|
20649
|
-
console.log(node);
|
|
20705
|
+
console.error("Error extracting LaTeX from KaTeX node:", error);
|
|
20706
|
+
console.log("Problematic node:", node);
|
|
20650
20707
|
return "error";
|
|
20651
20708
|
}
|
|
20652
20709
|
}
|
|
@@ -20666,15 +20723,15 @@ var decodeFromHtml = function () {
|
|
|
20666
20723
|
var translate_re = /&(#36|quot|apos|lt|gt|amp|#44|#58|#124);/g,
|
|
20667
20724
|
translate = {
|
|
20668
20725
|
// 'nbsp': String.fromCharCode(160),
|
|
20669
|
-
|
|
20670
|
-
|
|
20671
|
-
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
|
|
20677
|
-
|
|
20726
|
+
"#36": "$",
|
|
20727
|
+
quot: '"',
|
|
20728
|
+
apos: "'",
|
|
20729
|
+
lt: "<",
|
|
20730
|
+
gt: ">",
|
|
20731
|
+
amp: "&",
|
|
20732
|
+
"#44": ",",
|
|
20733
|
+
"#58": ":",
|
|
20734
|
+
"#124": "|"
|
|
20678
20735
|
},
|
|
20679
20736
|
translator = function translator($0, $1) {
|
|
20680
20737
|
return translate[$1];
|
|
@@ -20766,6 +20823,11 @@ function addTextForNode(node, arrayOfText) {
|
|
|
20766
20823
|
arrayOfText.push(getLatex(node));
|
|
20767
20824
|
arrayOfText.push(useHtmlMath ? RAW_TEXT_MATH_END_TAG_HTML_MATH : RAW_TEXT_MATH_END_TAG_TEX);
|
|
20768
20825
|
if (mark) arrayOfText.push(MARK$1);
|
|
20826
|
+
} else if (isBrNode(node)) {
|
|
20827
|
+
// Handle BR tags as line breaks
|
|
20828
|
+
if (mark) arrayOfText.push(MARK$1);
|
|
20829
|
+
arrayOfText.push("\n");
|
|
20830
|
+
if (mark) arrayOfText.push(MARK$1);
|
|
20769
20831
|
} else {
|
|
20770
20832
|
console.error("Can't render node in editable div: Unknown node type");
|
|
20771
20833
|
console.log(node);
|
|
@@ -20794,7 +20856,12 @@ function elementToMarkedRawText(element) {
|
|
|
20794
20856
|
var useHtmlMath = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
|
20795
20857
|
// console.log("elementToMarkedRawText")
|
|
20796
20858
|
// console.log(element.innerHTML)
|
|
20797
|
-
|
|
20859
|
+
|
|
20860
|
+
// Handle empty content cases gracefully
|
|
20861
|
+
if (element.innerHTML === "<p><br></p>" || element.innerHTML === "<br>" || element.innerHTML === "") {
|
|
20862
|
+
return "";
|
|
20863
|
+
}
|
|
20864
|
+
|
|
20798
20865
|
// console.log("Node to mark:")
|
|
20799
20866
|
// console.log(nodeToMark)
|
|
20800
20867
|
var nodes = element.childNodes;
|
|
@@ -20810,7 +20877,7 @@ function elementToMarkedRawText(element) {
|
|
|
20810
20877
|
var raw_text = result.join("");
|
|
20811
20878
|
|
|
20812
20879
|
// remove any zero-width spaces we added to the html
|
|
20813
|
-
raw_text = raw_text.replace(SMALL_SPACE_REG_EXP,
|
|
20880
|
+
raw_text = raw_text.replace(SMALL_SPACE_REG_EXP, "");
|
|
20814
20881
|
return raw_text;
|
|
20815
20882
|
}
|
|
20816
20883
|
function replaceMarksWithMath(markedRawText, latex) {
|
|
@@ -21134,6 +21201,9 @@ function findNodeAndOffsetForGlobalOffsetInEditableDiv(editableDiv, globalOffset
|
|
|
21134
21201
|
console.log("Result:");
|
|
21135
21202
|
console.log(result);
|
|
21136
21203
|
console.log("result.offset > result.node.nodeValue.length");
|
|
21204
|
+
console.log("Node value: '" + result.node.nodeValue + "'");
|
|
21205
|
+
console.log("Node value length: " + result.node.nodeValue.length);
|
|
21206
|
+
console.log("Calculated offset: " + result.offset);
|
|
21137
21207
|
result.offset = result.node.nodeValue.length;
|
|
21138
21208
|
}
|
|
21139
21209
|
return result;
|
|
@@ -21164,8 +21234,17 @@ function getRangeParams(editableDiv) {
|
|
|
21164
21234
|
console.warn("Adjusting start pos in getRangeParams as container was of type: " + range.startContainer.nodeName);
|
|
21165
21235
|
range.setStart(textNode, 0);
|
|
21166
21236
|
} else {
|
|
21167
|
-
|
|
21168
|
-
|
|
21237
|
+
// Handle empty content case - return default range params
|
|
21238
|
+
// This is normal behavior after selecting all and deleting content
|
|
21239
|
+
console.log("getRangeParams: Empty content detected, using default range params. " + "Node type: " + range.startContainer.nodeName);
|
|
21240
|
+
return {
|
|
21241
|
+
startNodeIndex: 0,
|
|
21242
|
+
startOffset: 0,
|
|
21243
|
+
endNodeIndex: 0,
|
|
21244
|
+
endOffset: 0,
|
|
21245
|
+
startGlobalOffset: 0,
|
|
21246
|
+
endGlobalOffset: 0
|
|
21247
|
+
};
|
|
21169
21248
|
}
|
|
21170
21249
|
}
|
|
21171
21250
|
if (range.endContainer.nodeType !== 3) {
|
|
@@ -21174,8 +21253,17 @@ function getRangeParams(editableDiv) {
|
|
|
21174
21253
|
console.warn("Adjusting end pos in getRangeParams as container was of type: " + range.endContainer.nodeName);
|
|
21175
21254
|
range.setEnd(_textNode, 0);
|
|
21176
21255
|
} else {
|
|
21177
|
-
|
|
21178
|
-
|
|
21256
|
+
// Handle empty content case - return default range params
|
|
21257
|
+
// This is normal behavior after selecting all and deleting content
|
|
21258
|
+
console.log("getRangeParams: Empty content detected, using default range params. " + "Node type: " + range.endContainer.nodeName);
|
|
21259
|
+
return {
|
|
21260
|
+
startNodeIndex: 0,
|
|
21261
|
+
startOffset: 0,
|
|
21262
|
+
endNodeIndex: 0,
|
|
21263
|
+
endOffset: 0,
|
|
21264
|
+
startGlobalOffset: 0,
|
|
21265
|
+
endGlobalOffset: 0
|
|
21266
|
+
};
|
|
21179
21267
|
}
|
|
21180
21268
|
}
|
|
21181
21269
|
// Find the index of the start and end nodes
|
|
@@ -21361,6 +21449,11 @@ function sanitiseHtmlForElement(element) {
|
|
|
21361
21449
|
var clone = element.cloneNode(true);
|
|
21362
21450
|
return clone;
|
|
21363
21451
|
}
|
|
21452
|
+
// Preserve math tags - they should be processed as math content
|
|
21453
|
+
if (element.nodeType === 1 && element.tagName.toLowerCase() === "math") {
|
|
21454
|
+
var _clone = element.cloneNode(true);
|
|
21455
|
+
return _clone;
|
|
21456
|
+
}
|
|
21364
21457
|
if (element.tagName === "HEAD" || element.tagName === "STYLE" || element.tagName === "LINK") return null;
|
|
21365
21458
|
var new_element = null;
|
|
21366
21459
|
if (isBIUNode(element)) {
|
|
@@ -21368,10 +21461,10 @@ function sanitiseHtmlForElement(element) {
|
|
|
21368
21461
|
new_element = document.createElement(element.tagName);
|
|
21369
21462
|
} else if (element.nodeType === 1 && (element.tagName === "LI" || element.tagName === "DT" || element.tagName === "DD" || element.tagName === "THEAD" || element.tagName === "TR" || element.tagName === "H1" || element.tagName === "H2" || element.tagName === "H3" || element.tagName === "H4" || element.tagName === "H5" || element.tagName === "H6")) {
|
|
21370
21463
|
// console.log("Converting descendent: <"+element.tagName+">"+element.textContent)
|
|
21371
|
-
new_element = document.createElement(
|
|
21464
|
+
new_element = document.createElement("p");
|
|
21372
21465
|
} else {
|
|
21373
21466
|
// console.log("Stripping descendent: <"+element.tagName+">"+element.textContent)
|
|
21374
|
-
new_element = document.createElement(
|
|
21467
|
+
new_element = document.createElement("span");
|
|
21375
21468
|
}
|
|
21376
21469
|
if (element.hasChildNodes()) {
|
|
21377
21470
|
for (var i = 0; i < element.childNodes.length; i++) {
|
|
@@ -21388,7 +21481,7 @@ var SPAN_TAG = new RegExp("<span>|</span>", "g");
|
|
|
21388
21481
|
// const COMMENT_TAG_REG_EXP = new RegExp("(?=<!--([\s\S]*?)-->","g")
|
|
21389
21482
|
// const COMMENT_TAG_REG_EXP = new RegExp("<!--[\s\S]*?-->","gm")
|
|
21390
21483
|
// const MULTI_WHITE_SPACE_REG_EXP = new RegExp("\s{2,}","gm")
|
|
21391
|
-
var KATEX_START_HTML =
|
|
21484
|
+
var KATEX_START_HTML = '<span class="katex"';
|
|
21392
21485
|
var KATEX_END_HTML = "</span></span></span></span>";
|
|
21393
21486
|
function sanitiseHtml(s) {
|
|
21394
21487
|
// Remove all <br> tags (as some of these can be inside katex tags)
|
|
@@ -21396,7 +21489,7 @@ function sanitiseHtml(s) {
|
|
|
21396
21489
|
// console.log("After removing comments:")
|
|
21397
21490
|
// console.log(s)
|
|
21398
21491
|
// Next, convert all elements to supported elements
|
|
21399
|
-
var div = document.createElement(
|
|
21492
|
+
var div = document.createElement("div");
|
|
21400
21493
|
div.innerHTML = s;
|
|
21401
21494
|
var sanitisedElement = sanitiseHtmlForElement(div);
|
|
21402
21495
|
var sanitised = sanitisedElement.innerHTML;
|
|
@@ -21483,6 +21576,81 @@ function sanitiseHtml(s) {
|
|
|
21483
21576
|
return sanitised;
|
|
21484
21577
|
}
|
|
21485
21578
|
|
|
21579
|
+
// Helper functions for advanced text navigation
|
|
21580
|
+
function isWordBoundary(_char) {
|
|
21581
|
+
// Word boundaries are spaces, punctuation, or start/end of string
|
|
21582
|
+
return !_char || /[\s\.,;:!?\-\(\)\[\]{}'"]/g.test(_char);
|
|
21583
|
+
}
|
|
21584
|
+
function findWordBoundary(text, startPos, direction) {
|
|
21585
|
+
// direction: 1 for forward, -1 for backward
|
|
21586
|
+
var pos = startPos;
|
|
21587
|
+
var len = text.length;
|
|
21588
|
+
if (direction === 1) {
|
|
21589
|
+
// Moving forward - find end of current word, then skip whitespace
|
|
21590
|
+
while (pos < len && !isWordBoundary(text[pos])) {
|
|
21591
|
+
pos++;
|
|
21592
|
+
}
|
|
21593
|
+
while (pos < len && isWordBoundary(text[pos])) {
|
|
21594
|
+
pos++;
|
|
21595
|
+
}
|
|
21596
|
+
} else {
|
|
21597
|
+
// Moving backward - find start of current word, then skip whitespace
|
|
21598
|
+
if (pos > 0) pos--; // Move back one character first
|
|
21599
|
+
while (pos > 0 && isWordBoundary(text[pos])) {
|
|
21600
|
+
pos--;
|
|
21601
|
+
}
|
|
21602
|
+
while (pos > 0 && !isWordBoundary(text[pos - 1])) {
|
|
21603
|
+
pos--;
|
|
21604
|
+
}
|
|
21605
|
+
}
|
|
21606
|
+
return Math.max(0, Math.min(pos, len));
|
|
21607
|
+
}
|
|
21608
|
+
function findLineBoundary(text, startPos, direction) {
|
|
21609
|
+
// direction: 1 for end of line, -1 for start of line
|
|
21610
|
+
var pos = startPos;
|
|
21611
|
+
var len = text.length;
|
|
21612
|
+
if (direction === 1) {
|
|
21613
|
+
// Find end of current line
|
|
21614
|
+
while (pos < len && text[pos] !== "\n") {
|
|
21615
|
+
pos++;
|
|
21616
|
+
}
|
|
21617
|
+
} else {
|
|
21618
|
+
// Find start of current line
|
|
21619
|
+
while (pos > 0 && text[pos - 1] !== "\n") {
|
|
21620
|
+
pos--;
|
|
21621
|
+
}
|
|
21622
|
+
}
|
|
21623
|
+
return Math.max(0, Math.min(pos, len));
|
|
21624
|
+
}
|
|
21625
|
+
function getPlainTextFromEditableDiv(editableDiv) {
|
|
21626
|
+
// Convert the editable div content to plain text for boundary detection
|
|
21627
|
+
var text = elementToMarkedRawText(editableDiv, null, 0, false);
|
|
21628
|
+
text = removeMarks(text);
|
|
21629
|
+
// Remove HTML tags and convert to plain text
|
|
21630
|
+
text = text.replace(/<[^>]*>/g, "");
|
|
21631
|
+
text = text.replace(/ /g, " ");
|
|
21632
|
+
text = text.replace(/&/g, "&");
|
|
21633
|
+
text = text.replace(/</g, "<");
|
|
21634
|
+
text = text.replace(/>/g, ">");
|
|
21635
|
+
text = text.replace(/"/g, '"');
|
|
21636
|
+
text = text.replace(/'/g, "'");
|
|
21637
|
+
return text;
|
|
21638
|
+
}
|
|
21639
|
+
function globalOffsetToPlainTextOffset(editableDiv, globalOffset) {
|
|
21640
|
+
// Convert global offset to plain text offset for boundary detection
|
|
21641
|
+
var plainText = getPlainTextFromEditableDiv(editableDiv);
|
|
21642
|
+
// This is a simplified mapping - in a real implementation you'd want
|
|
21643
|
+
// to account for the difference between HTML and plain text offsets
|
|
21644
|
+
return Math.min(globalOffset, plainText.length);
|
|
21645
|
+
}
|
|
21646
|
+
function plainTextOffsetToGlobalOffset(editableDiv, plainTextOffset) {
|
|
21647
|
+
// Convert plain text offset back to global offset
|
|
21648
|
+
// This is a simplified mapping - in a real implementation you'd want
|
|
21649
|
+
// to account for the difference between HTML and plain text offsets
|
|
21650
|
+
var plainText = getPlainTextFromEditableDiv(editableDiv);
|
|
21651
|
+
return Math.min(plainTextOffset, plainText.length);
|
|
21652
|
+
}
|
|
21653
|
+
|
|
21486
21654
|
var MIME_TYPE_PLAIN_TEXT = "text/plain";
|
|
21487
21655
|
var MIME_TYPE_HTML = "text/html";
|
|
21488
21656
|
var MIME_TYPE_TEX = "application/x-tex";
|
|
@@ -21652,6 +21820,9 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
21652
21820
|
});
|
|
21653
21821
|
if (_this2.undoHistory.length > MAX_HISTORY_LENGTH) _this2.undoHistory.shift();
|
|
21654
21822
|
|
|
21823
|
+
// Debug what's being passed to parent
|
|
21824
|
+
// console.log("APPLY CHANGES:", { value, mimeType });
|
|
21825
|
+
|
|
21655
21826
|
// Call the parent handler to apply the changes
|
|
21656
21827
|
_this2.onChangeCallback({
|
|
21657
21828
|
value: value,
|
|
@@ -21708,7 +21879,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
21708
21879
|
_this2.lastSetRangeParmas = params;
|
|
21709
21880
|
} catch (error) {
|
|
21710
21881
|
console.error(error);
|
|
21711
|
-
console.log(
|
|
21882
|
+
// console.log(this.editableDiv.childNodes);
|
|
21712
21883
|
}
|
|
21713
21884
|
});
|
|
21714
21885
|
_defineProperty(_this2, "handleKeyDownBackspace", function (e) {
|
|
@@ -21825,47 +21996,317 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
21825
21996
|
_defineProperty(_this2, "inputStartsWithSmallSpace", function () {
|
|
21826
21997
|
return startsWithSmallSpace(_this2.editableDiv);
|
|
21827
21998
|
});
|
|
21999
|
+
// Platform detection helper
|
|
22000
|
+
_defineProperty(_this2, "getPlatformModifiers", function () {
|
|
22001
|
+
var isMac = /(Mac)/i.test(window.navigator.platform);
|
|
22002
|
+
var isWindows = /(Win)/i.test(window.navigator.platform);
|
|
22003
|
+
return {
|
|
22004
|
+
isMac: isMac,
|
|
22005
|
+
isWindows: isWindows
|
|
22006
|
+
};
|
|
22007
|
+
});
|
|
22008
|
+
// Check if word navigation modifier is pressed
|
|
22009
|
+
_defineProperty(_this2, "isWordModifier", function (e) {
|
|
22010
|
+
var _this2$getPlatformMod = _this2.getPlatformModifiers(),
|
|
22011
|
+
isMac = _this2$getPlatformMod.isMac;
|
|
22012
|
+
return isMac ? e.altKey : e.ctrlKey;
|
|
22013
|
+
});
|
|
22014
|
+
// Check if line navigation modifier is pressed
|
|
22015
|
+
_defineProperty(_this2, "isLineModifier", function (e) {
|
|
22016
|
+
var _this2$getPlatformMod2 = _this2.getPlatformModifiers(),
|
|
22017
|
+
isMac = _this2$getPlatformMod2.isMac;
|
|
22018
|
+
return isMac ? e.metaKey : e.ctrlKey;
|
|
22019
|
+
});
|
|
21828
22020
|
_defineProperty(_this2, "handleKeyDownArrowLeft", function (e) {
|
|
21829
22021
|
var rangeParams = _this2._getRangeParams();
|
|
21830
|
-
rangeParams.
|
|
21831
|
-
rangeParams.startOffset;
|
|
22022
|
+
var hasSelection = rangeParams.startGlobalOffset !== rangeParams.endGlobalOffset;
|
|
21832
22023
|
|
|
21833
|
-
//
|
|
21834
|
-
|
|
21835
|
-
|
|
22024
|
+
// If has selection and no shift, move cursor to LEFT end of selection
|
|
22025
|
+
if (!e.shiftKey && hasSelection) {
|
|
22026
|
+
_this2.selectionAnchor = null;
|
|
22027
|
+
var _new_rangeParams2 = {
|
|
22028
|
+
startGlobalOffset: rangeParams.startGlobalOffset,
|
|
22029
|
+
endGlobalOffset: rangeParams.startGlobalOffset
|
|
22030
|
+
};
|
|
22031
|
+
e.preventDefault();
|
|
22032
|
+
_this2._setRangeParams(_new_rangeParams2);
|
|
22033
|
+
return;
|
|
22034
|
+
}
|
|
22035
|
+
|
|
22036
|
+
// For left arrow, current position is at the start of selection (or cursor position)
|
|
22037
|
+
var currentGlobalOffset = hasSelection ? rangeParams.startGlobalOffset : rangeParams.endGlobalOffset;
|
|
22038
|
+
var newGlobalOffset = currentGlobalOffset;
|
|
22039
|
+
|
|
22040
|
+
// Determine movement type based on modifier keys
|
|
22041
|
+
if (_this2.isLineModifier(e)) {
|
|
22042
|
+
// Move to beginning of line
|
|
22043
|
+
var plainText = getPlainTextFromEditableDiv(_this2.editableDiv);
|
|
22044
|
+
var plainTextOffset = globalOffsetToPlainTextOffset(_this2.editableDiv, currentGlobalOffset);
|
|
22045
|
+
var lineStart = findLineBoundary(plainText, plainTextOffset, -1);
|
|
22046
|
+
newGlobalOffset = plainTextOffsetToGlobalOffset(_this2.editableDiv, lineStart);
|
|
22047
|
+
} else if (_this2.isWordModifier(e)) {
|
|
22048
|
+
// Move to beginning of word
|
|
22049
|
+
var _plainText = getPlainTextFromEditableDiv(_this2.editableDiv);
|
|
22050
|
+
var _plainTextOffset = globalOffsetToPlainTextOffset(_this2.editableDiv, currentGlobalOffset);
|
|
22051
|
+
var wordStart = findWordBoundary(_plainText, _plainTextOffset, -1);
|
|
22052
|
+
newGlobalOffset = plainTextOffsetToGlobalOffset(_this2.editableDiv, wordStart);
|
|
22053
|
+
} else {
|
|
22054
|
+
// Regular left arrow: Move one character
|
|
22055
|
+
newGlobalOffset = Math.max(0, currentGlobalOffset - 1);
|
|
22056
|
+
}
|
|
22057
|
+
|
|
22058
|
+
// Handle selection based on shift key
|
|
21836
22059
|
var new_rangeParams = null;
|
|
21837
|
-
if (e.shiftKey
|
|
22060
|
+
if (e.shiftKey) {
|
|
22061
|
+
// Set anchor if not already set
|
|
22062
|
+
if (_this2.selectionAnchor === null) {
|
|
22063
|
+
// Determine which end was the cursor position
|
|
22064
|
+
if (hasSelection) {
|
|
22065
|
+
// If we had a selection, we need to determine which end the cursor was at
|
|
22066
|
+
// For left arrow, we want to extend from the right end
|
|
22067
|
+
_this2.selectionAnchor = rangeParams.endGlobalOffset;
|
|
22068
|
+
} else {
|
|
22069
|
+
// No previous selection, current position becomes anchor
|
|
22070
|
+
_this2.selectionAnchor = currentGlobalOffset;
|
|
22071
|
+
}
|
|
22072
|
+
}
|
|
22073
|
+
|
|
22074
|
+
// Create selection from anchor to new position
|
|
21838
22075
|
new_rangeParams = {
|
|
21839
|
-
startGlobalOffset:
|
|
21840
|
-
endGlobalOffset:
|
|
22076
|
+
startGlobalOffset: Math.min(_this2.selectionAnchor, newGlobalOffset),
|
|
22077
|
+
endGlobalOffset: Math.max(_this2.selectionAnchor, newGlobalOffset)
|
|
21841
22078
|
};
|
|
21842
22079
|
} else {
|
|
22080
|
+
// Move cursor and clear anchor
|
|
22081
|
+
_this2.selectionAnchor = null;
|
|
21843
22082
|
new_rangeParams = {
|
|
21844
|
-
startGlobalOffset:
|
|
21845
|
-
endGlobalOffset:
|
|
22083
|
+
startGlobalOffset: newGlobalOffset,
|
|
22084
|
+
endGlobalOffset: newGlobalOffset
|
|
21846
22085
|
};
|
|
21847
22086
|
}
|
|
21848
|
-
// console.log(new_rangeParams)
|
|
21849
22087
|
e.preventDefault();
|
|
21850
22088
|
_this2._setRangeParams(new_rangeParams);
|
|
21851
22089
|
return;
|
|
21852
22090
|
});
|
|
21853
22091
|
_defineProperty(_this2, "handleKeyDownArrowRight", function (e) {
|
|
21854
|
-
// console.log("handleKeyDownArrowRight")
|
|
21855
22092
|
var rangeParams = _this2._getRangeParams();
|
|
21856
|
-
rangeParams.
|
|
21857
|
-
|
|
22093
|
+
var hasSelection = rangeParams.startGlobalOffset !== rangeParams.endGlobalOffset;
|
|
22094
|
+
|
|
22095
|
+
// If has selection and no shift, move cursor to RIGHT end of selection
|
|
22096
|
+
if (!e.shiftKey && hasSelection) {
|
|
22097
|
+
_this2.selectionAnchor = null;
|
|
22098
|
+
var _new_rangeParams3 = {
|
|
22099
|
+
startGlobalOffset: rangeParams.endGlobalOffset,
|
|
22100
|
+
endGlobalOffset: rangeParams.endGlobalOffset
|
|
22101
|
+
};
|
|
22102
|
+
e.preventDefault();
|
|
22103
|
+
_this2._setRangeParams(_new_rangeParams3);
|
|
22104
|
+
return;
|
|
22105
|
+
}
|
|
22106
|
+
|
|
22107
|
+
// For right arrow, current position is at the end of selection (or cursor position)
|
|
22108
|
+
var currentGlobalOffset = rangeParams.endGlobalOffset;
|
|
22109
|
+
var newGlobalOffset = currentGlobalOffset;
|
|
22110
|
+
|
|
22111
|
+
// Determine movement type based on modifier keys
|
|
22112
|
+
if (_this2.isLineModifier(e)) {
|
|
22113
|
+
// Move to end of line
|
|
22114
|
+
var plainText = getPlainTextFromEditableDiv(_this2.editableDiv);
|
|
22115
|
+
var plainTextOffset = globalOffsetToPlainTextOffset(_this2.editableDiv, currentGlobalOffset);
|
|
22116
|
+
var lineEnd = findLineBoundary(plainText, plainTextOffset, 1);
|
|
22117
|
+
newGlobalOffset = plainTextOffsetToGlobalOffset(_this2.editableDiv, lineEnd);
|
|
22118
|
+
} else if (_this2.isWordModifier(e)) {
|
|
22119
|
+
// Move to end of word
|
|
22120
|
+
var _plainText2 = getPlainTextFromEditableDiv(_this2.editableDiv);
|
|
22121
|
+
var _plainTextOffset2 = globalOffsetToPlainTextOffset(_this2.editableDiv, currentGlobalOffset);
|
|
22122
|
+
var wordEnd = findWordBoundary(_plainText2, _plainTextOffset2, 1);
|
|
22123
|
+
newGlobalOffset = plainTextOffsetToGlobalOffset(_this2.editableDiv, wordEnd);
|
|
22124
|
+
} else {
|
|
22125
|
+
// Regular right arrow: Move one character
|
|
22126
|
+
newGlobalOffset = currentGlobalOffset + 1;
|
|
22127
|
+
}
|
|
22128
|
+
|
|
22129
|
+
// Handle selection based on shift key
|
|
21858
22130
|
var new_rangeParams = null;
|
|
21859
|
-
|
|
21860
|
-
|
|
22131
|
+
if (e.shiftKey) {
|
|
22132
|
+
// Set anchor if not already set
|
|
22133
|
+
if (_this2.selectionAnchor === null) {
|
|
22134
|
+
// Determine which end was the cursor position
|
|
22135
|
+
if (hasSelection) {
|
|
22136
|
+
// If we had a selection, we need to determine which end the cursor was at
|
|
22137
|
+
// For right arrow, we want to extend from the left end
|
|
22138
|
+
_this2.selectionAnchor = rangeParams.startGlobalOffset;
|
|
22139
|
+
} else {
|
|
22140
|
+
// No previous selection, current position becomes anchor
|
|
22141
|
+
_this2.selectionAnchor = currentGlobalOffset;
|
|
22142
|
+
}
|
|
22143
|
+
}
|
|
22144
|
+
|
|
22145
|
+
// Create selection from anchor to new position
|
|
22146
|
+
new_rangeParams = {
|
|
22147
|
+
startGlobalOffset: Math.min(_this2.selectionAnchor, newGlobalOffset),
|
|
22148
|
+
endGlobalOffset: Math.max(_this2.selectionAnchor, newGlobalOffset)
|
|
22149
|
+
};
|
|
22150
|
+
} else {
|
|
22151
|
+
// Move cursor and clear anchor
|
|
22152
|
+
_this2.selectionAnchor = null;
|
|
21861
22153
|
new_rangeParams = {
|
|
22154
|
+
startGlobalOffset: newGlobalOffset,
|
|
22155
|
+
endGlobalOffset: newGlobalOffset
|
|
22156
|
+
};
|
|
22157
|
+
}
|
|
22158
|
+
e.preventDefault();
|
|
22159
|
+
_this2._setRangeParams(new_rangeParams);
|
|
22160
|
+
return;
|
|
22161
|
+
});
|
|
22162
|
+
_defineProperty(_this2, "handleKeyDownArrowUp", function (e) {
|
|
22163
|
+
var rangeParams = _this2._getRangeParams();
|
|
22164
|
+
var hasSelection = rangeParams.startGlobalOffset !== rangeParams.endGlobalOffset;
|
|
22165
|
+
|
|
22166
|
+
// If no selection and no shift, just move cursor to start of selection (if any)
|
|
22167
|
+
if (!e.shiftKey && hasSelection) {
|
|
22168
|
+
_this2.selectionAnchor = null;
|
|
22169
|
+
var _new_rangeParams4 = {
|
|
21862
22170
|
startGlobalOffset: rangeParams.startGlobalOffset,
|
|
21863
|
-
endGlobalOffset:
|
|
22171
|
+
endGlobalOffset: rangeParams.startGlobalOffset
|
|
22172
|
+
};
|
|
22173
|
+
e.preventDefault();
|
|
22174
|
+
_this2._setRangeParams(_new_rangeParams4);
|
|
22175
|
+
return;
|
|
22176
|
+
}
|
|
22177
|
+
|
|
22178
|
+
// For up arrow (backward movement), current position is at the start of selection
|
|
22179
|
+
var currentGlobalOffset = hasSelection ? rangeParams.startGlobalOffset : rangeParams.endGlobalOffset;
|
|
22180
|
+
var newGlobalOffset = currentGlobalOffset;
|
|
22181
|
+
|
|
22182
|
+
// Determine movement type based on modifier keys
|
|
22183
|
+
if (_this2.isLineModifier(e)) {
|
|
22184
|
+
// Move to beginning of document
|
|
22185
|
+
newGlobalOffset = 0;
|
|
22186
|
+
} else {
|
|
22187
|
+
// Regular up arrow: Move to previous line (or beginning if single line)
|
|
22188
|
+
var plainText = getPlainTextFromEditableDiv(_this2.editableDiv);
|
|
22189
|
+
var plainTextOffset = globalOffsetToPlainTextOffset(_this2.editableDiv, currentGlobalOffset);
|
|
22190
|
+
var lineStart = findLineBoundary(plainText, plainTextOffset, -1);
|
|
22191
|
+
if (lineStart === 0) {
|
|
22192
|
+
// Already at first line, move to beginning
|
|
22193
|
+
newGlobalOffset = 0;
|
|
22194
|
+
} else {
|
|
22195
|
+
// Find previous line and try to maintain column position
|
|
22196
|
+
var currentColumn = plainTextOffset - lineStart;
|
|
22197
|
+
var prevLineEnd = lineStart - 1;
|
|
22198
|
+
var prevLineStart = findLineBoundary(plainText, prevLineEnd, -1);
|
|
22199
|
+
var prevLineLength = prevLineEnd - prevLineStart;
|
|
22200
|
+
var targetColumn = Math.min(currentColumn, prevLineLength);
|
|
22201
|
+
newGlobalOffset = plainTextOffsetToGlobalOffset(_this2.editableDiv, prevLineStart + targetColumn);
|
|
22202
|
+
}
|
|
22203
|
+
}
|
|
22204
|
+
|
|
22205
|
+
// Handle selection based on shift key
|
|
22206
|
+
var new_rangeParams = null;
|
|
22207
|
+
if (e.shiftKey) {
|
|
22208
|
+
// Set anchor if not already set
|
|
22209
|
+
if (_this2.selectionAnchor === null) {
|
|
22210
|
+
// Determine which end was the cursor position
|
|
22211
|
+
if (hasSelection) {
|
|
22212
|
+
// If we had a selection, we need to determine which end the cursor was at
|
|
22213
|
+
// For up arrow (backward), we want to extend from the right end
|
|
22214
|
+
_this2.selectionAnchor = rangeParams.endGlobalOffset;
|
|
22215
|
+
} else {
|
|
22216
|
+
// No previous selection, current position becomes anchor
|
|
22217
|
+
_this2.selectionAnchor = currentGlobalOffset;
|
|
22218
|
+
}
|
|
22219
|
+
}
|
|
22220
|
+
|
|
22221
|
+
// Create selection from anchor to new position
|
|
22222
|
+
new_rangeParams = {
|
|
22223
|
+
startGlobalOffset: Math.min(_this2.selectionAnchor, newGlobalOffset),
|
|
22224
|
+
endGlobalOffset: Math.max(_this2.selectionAnchor, newGlobalOffset)
|
|
22225
|
+
};
|
|
22226
|
+
} else {
|
|
22227
|
+
// Move cursor and clear anchor
|
|
22228
|
+
_this2.selectionAnchor = null;
|
|
22229
|
+
new_rangeParams = {
|
|
22230
|
+
startGlobalOffset: newGlobalOffset,
|
|
22231
|
+
endGlobalOffset: newGlobalOffset
|
|
22232
|
+
};
|
|
22233
|
+
}
|
|
22234
|
+
e.preventDefault();
|
|
22235
|
+
_this2._setRangeParams(new_rangeParams);
|
|
22236
|
+
return;
|
|
22237
|
+
});
|
|
22238
|
+
_defineProperty(_this2, "handleKeyDownArrowDown", function (e) {
|
|
22239
|
+
var rangeParams = _this2._getRangeParams();
|
|
22240
|
+
var hasSelection = rangeParams.startGlobalOffset !== rangeParams.endGlobalOffset;
|
|
22241
|
+
|
|
22242
|
+
// If no selection and no shift, just move cursor to end of selection (if any)
|
|
22243
|
+
if (!e.shiftKey && hasSelection) {
|
|
22244
|
+
_this2.selectionAnchor = null;
|
|
22245
|
+
var _new_rangeParams5 = {
|
|
22246
|
+
startGlobalOffset: rangeParams.endGlobalOffset,
|
|
22247
|
+
endGlobalOffset: rangeParams.endGlobalOffset
|
|
22248
|
+
};
|
|
22249
|
+
e.preventDefault();
|
|
22250
|
+
_this2._setRangeParams(_new_rangeParams5);
|
|
22251
|
+
return;
|
|
22252
|
+
}
|
|
22253
|
+
|
|
22254
|
+
// For down arrow (forward movement), current position is at the end of selection
|
|
22255
|
+
var currentGlobalOffset = rangeParams.endGlobalOffset;
|
|
22256
|
+
var newGlobalOffset = currentGlobalOffset;
|
|
22257
|
+
|
|
22258
|
+
// Determine movement type based on modifier keys
|
|
22259
|
+
if (_this2.isLineModifier(e)) {
|
|
22260
|
+
// Move to end of document
|
|
22261
|
+
var plainText = getPlainTextFromEditableDiv(_this2.editableDiv);
|
|
22262
|
+
newGlobalOffset = plainTextOffsetToGlobalOffset(_this2.editableDiv, plainText.length);
|
|
22263
|
+
} else {
|
|
22264
|
+
// Regular down arrow: Move to next line (or end if single line)
|
|
22265
|
+
var _plainText3 = getPlainTextFromEditableDiv(_this2.editableDiv);
|
|
22266
|
+
var plainTextOffset = globalOffsetToPlainTextOffset(_this2.editableDiv, currentGlobalOffset);
|
|
22267
|
+
var lineStart = findLineBoundary(_plainText3, plainTextOffset, -1);
|
|
22268
|
+
var lineEnd = findLineBoundary(_plainText3, plainTextOffset, 1);
|
|
22269
|
+
if (lineEnd >= _plainText3.length) {
|
|
22270
|
+
// Already at last line, move to end
|
|
22271
|
+
newGlobalOffset = plainTextOffsetToGlobalOffset(_this2.editableDiv, _plainText3.length);
|
|
22272
|
+
} else {
|
|
22273
|
+
// Find next line and try to maintain column position
|
|
22274
|
+
var currentColumn = plainTextOffset - lineStart;
|
|
22275
|
+
var nextLineStart = lineEnd + 1;
|
|
22276
|
+
var nextLineEnd = findLineBoundary(_plainText3, nextLineStart, 1);
|
|
22277
|
+
var nextLineLength = nextLineEnd - nextLineStart;
|
|
22278
|
+
var targetColumn = Math.min(currentColumn, nextLineLength);
|
|
22279
|
+
newGlobalOffset = plainTextOffsetToGlobalOffset(_this2.editableDiv, nextLineStart + targetColumn);
|
|
22280
|
+
}
|
|
22281
|
+
}
|
|
22282
|
+
|
|
22283
|
+
// Handle selection based on shift key
|
|
22284
|
+
var new_rangeParams = null;
|
|
22285
|
+
if (e.shiftKey) {
|
|
22286
|
+
// Set anchor if not already set
|
|
22287
|
+
if (_this2.selectionAnchor === null) {
|
|
22288
|
+
// Determine which end was the cursor position
|
|
22289
|
+
if (hasSelection) {
|
|
22290
|
+
// If we had a selection, we need to determine which end the cursor was at
|
|
22291
|
+
// For down arrow (forward), we want to extend from the left end
|
|
22292
|
+
_this2.selectionAnchor = rangeParams.startGlobalOffset;
|
|
22293
|
+
} else {
|
|
22294
|
+
// No previous selection, current position becomes anchor
|
|
22295
|
+
_this2.selectionAnchor = currentGlobalOffset;
|
|
22296
|
+
}
|
|
22297
|
+
}
|
|
22298
|
+
|
|
22299
|
+
// Create selection from anchor to new position
|
|
22300
|
+
new_rangeParams = {
|
|
22301
|
+
startGlobalOffset: Math.min(_this2.selectionAnchor, newGlobalOffset),
|
|
22302
|
+
endGlobalOffset: Math.max(_this2.selectionAnchor, newGlobalOffset)
|
|
21864
22303
|
};
|
|
21865
22304
|
} else {
|
|
22305
|
+
// Move cursor and clear anchor
|
|
22306
|
+
_this2.selectionAnchor = null;
|
|
21866
22307
|
new_rangeParams = {
|
|
21867
|
-
startGlobalOffset:
|
|
21868
|
-
endGlobalOffset:
|
|
22308
|
+
startGlobalOffset: newGlobalOffset,
|
|
22309
|
+
endGlobalOffset: newGlobalOffset
|
|
21869
22310
|
};
|
|
21870
22311
|
}
|
|
21871
22312
|
e.preventDefault();
|
|
@@ -22033,7 +22474,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22033
22474
|
return;
|
|
22034
22475
|
}
|
|
22035
22476
|
if (!(e.ctrlKey || e.metaKey)) _this2.resetHistoryRedo();
|
|
22036
|
-
if ((e.metaKey || e.ctrlKey) && (e.key === "b" || e.key === "i" || e.key === "u" || e.key === "6" || e.key === "^" || e.key === "-" || e.key === "_" || e.key === "+" || e.key === "=") && _this2.
|
|
22477
|
+
if ((e.metaKey || e.ctrlKey) && (e.key === "b" || e.key === "i" || e.key === "u" || e.key === "6" || e.key === "^" || e.key === "-" || e.key === "_" || e.key === "+" || e.key === "=") && _this2.enableFontStyling()) {
|
|
22037
22478
|
if (e.key === "b") _this2.styleText(e, "Bold");
|
|
22038
22479
|
if (e.key === "i") _this2.styleText(e, "Italic");
|
|
22039
22480
|
if (e.key === "u") _this2.styleText(e, "Underline");
|
|
@@ -22084,12 +22525,12 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22084
22525
|
if (e.altKey && e.key === "Alt") {
|
|
22085
22526
|
var key = _this2.fetchAccentLetter();
|
|
22086
22527
|
if (key === "a" || key === "e" || key === "i" || key === "o" || key === "u" || key === "c" || key === "l" || key === "n" || key === "s" || key === "?" || key === "!") {
|
|
22087
|
-
console.log("showing/hiding accent bar");
|
|
22528
|
+
// console.log("showing/hiding accent bar");
|
|
22088
22529
|
_this2.setState({
|
|
22089
22530
|
showAccentBar: !_this2.state.showAccentBar
|
|
22090
22531
|
});
|
|
22091
22532
|
} else {
|
|
22092
|
-
console.log("hiding accent bar");
|
|
22533
|
+
// console.log("hiding accent bar");
|
|
22093
22534
|
_this2.setState({
|
|
22094
22535
|
showAccentBar: false
|
|
22095
22536
|
});
|
|
@@ -22108,7 +22549,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22108
22549
|
if (_this2.keyPressStartTime < 0) {
|
|
22109
22550
|
_this2.keyPressStartTime = Date.now();
|
|
22110
22551
|
if (_this2.state.showAccentBar) {
|
|
22111
|
-
console.log("Hiding accent bar 2");
|
|
22552
|
+
// console.log("Hiding accent bar 2");
|
|
22112
22553
|
_this2.setState({
|
|
22113
22554
|
showAccentBar: false
|
|
22114
22555
|
});
|
|
@@ -22126,6 +22567,14 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22126
22567
|
_this2.handleKeyDownArrowRight(e);
|
|
22127
22568
|
return;
|
|
22128
22569
|
}
|
|
22570
|
+
if (e.key === "ArrowUp") {
|
|
22571
|
+
_this2.handleKeyDownArrowUp(e);
|
|
22572
|
+
return;
|
|
22573
|
+
}
|
|
22574
|
+
if (e.key === "ArrowDown") {
|
|
22575
|
+
_this2.handleKeyDownArrowDown(e);
|
|
22576
|
+
return;
|
|
22577
|
+
}
|
|
22129
22578
|
if (e.key === "$") {
|
|
22130
22579
|
_this2.handleKeyDownDollar(e);
|
|
22131
22580
|
return;
|
|
@@ -22196,7 +22645,14 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22196
22645
|
}
|
|
22197
22646
|
} catch (error) {
|
|
22198
22647
|
console.error(error);
|
|
22199
|
-
console.log(
|
|
22648
|
+
// console.log(
|
|
22649
|
+
// "Key pressed: " +
|
|
22650
|
+
// (e.metaKey ? "META+" : "") +
|
|
22651
|
+
// (e.ctrlKey ? "CTRL+" : "") +
|
|
22652
|
+
// (e.altKey ? "ALT+" : "") +
|
|
22653
|
+
// (e.shiftKey ? "SHIFT+" : "") +
|
|
22654
|
+
// e.key
|
|
22655
|
+
// );
|
|
22200
22656
|
}
|
|
22201
22657
|
});
|
|
22202
22658
|
_defineProperty(_this2, "handleKeyUp", function (e) {
|
|
@@ -22256,14 +22712,14 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22256
22712
|
_new_index = _index + 1;
|
|
22257
22713
|
_new_offset = SMALL_SPACE_LENGTH;
|
|
22258
22714
|
}
|
|
22259
|
-
var
|
|
22715
|
+
var _new_rangeParams6 = {
|
|
22260
22716
|
startNodeIndex: _new_index,
|
|
22261
22717
|
startOffset: _new_offset,
|
|
22262
22718
|
endNodeIndex: _new_index,
|
|
22263
22719
|
endOffset: _new_offset
|
|
22264
22720
|
};
|
|
22265
22721
|
// console.log(new_rangeParams)
|
|
22266
|
-
_this2._setRangeParams(
|
|
22722
|
+
_this2._setRangeParams(_new_rangeParams6);
|
|
22267
22723
|
}
|
|
22268
22724
|
}
|
|
22269
22725
|
}
|
|
@@ -22278,14 +22734,56 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22278
22734
|
if (_this2.isComposing) return;
|
|
22279
22735
|
var raw_text = elementToMarkedRawText(_this2.editableDiv, null, 0, _this2.enableHtml());
|
|
22280
22736
|
var params = _this2._getRangeParams();
|
|
22281
|
-
if (params === null || params === undefined)
|
|
22737
|
+
if (params === null || params === undefined) {
|
|
22738
|
+
// console.log(
|
|
22739
|
+
// "handleInput: Empty content detected, using default range params"
|
|
22740
|
+
// );
|
|
22741
|
+
// Use default empty range params for graceful degradation
|
|
22742
|
+
var defaultParams = {
|
|
22743
|
+
startNodeIndex: 0,
|
|
22744
|
+
startOffset: 0,
|
|
22745
|
+
endNodeIndex: 0,
|
|
22746
|
+
endOffset: 0,
|
|
22747
|
+
startGlobalOffset: 0,
|
|
22748
|
+
endGlobalOffset: 0
|
|
22749
|
+
};
|
|
22750
|
+
// Continue with default params instead of crashing
|
|
22751
|
+
var _nodeCounts = _this2._countNodeTypes();
|
|
22752
|
+
var _mimeType = _this2.getMimeType(_nodeCounts.html > 0, _nodeCounts.math > 0);
|
|
22753
|
+
var _raw_text = elementToMarkedRawText(_this2.editableDiv, null, 0, _this2.enableHtml());
|
|
22754
|
+
_raw_text = removeEncodingIfPlainText(_raw_text, _mimeType, _this2.enableHtml());
|
|
22755
|
+
_this2.applyChangesToComponent(_raw_text, _mimeType, defaultParams, _this2.props.useExpertMode, _this2.props.selectedTab);
|
|
22756
|
+
return;
|
|
22757
|
+
} else if (params.startNodeIndex === null || params.startNodeIndex === undefined) {
|
|
22758
|
+
// console.log(
|
|
22759
|
+
// "handleInput: Invalid startNodeIndex detected: " +
|
|
22760
|
+
// params.startNodeIndex
|
|
22761
|
+
// );
|
|
22762
|
+
} else {
|
|
22282
22763
|
// console.log("Current range params:")
|
|
22283
22764
|
// console.log(params)
|
|
22284
22765
|
}
|
|
22766
|
+
|
|
22767
|
+
// Check for math content directly in raw text for more reliable detection
|
|
22768
|
+
var hasMathContent = /<math>/i.test(raw_text);
|
|
22285
22769
|
var nodeCounts = _this2._countNodeTypes();
|
|
22286
|
-
|
|
22770
|
+
|
|
22771
|
+
// Use raw text math detection if DOM counting fails (e.g., after paste)
|
|
22772
|
+
var hasHtml = nodeCounts.html > 0 || /<[^>]+>/i.test(raw_text);
|
|
22773
|
+
var hasMath = hasMathContent || nodeCounts.math > 0;
|
|
22774
|
+
var mimeType = _this2.getMimeType(hasHtml, hasMath);
|
|
22287
22775
|
raw_text = removeEncodingIfPlainText(raw_text, mimeType, _this2.enableHtml());
|
|
22288
|
-
|
|
22776
|
+
|
|
22777
|
+
// Use valid params or fallback to defaults
|
|
22778
|
+
var validParams = params || {
|
|
22779
|
+
startNodeIndex: 0,
|
|
22780
|
+
startOffset: 0,
|
|
22781
|
+
endNodeIndex: 0,
|
|
22782
|
+
endOffset: 0,
|
|
22783
|
+
startGlobalOffset: 0,
|
|
22784
|
+
endGlobalOffset: 0
|
|
22785
|
+
};
|
|
22786
|
+
_this2.applyChangesToComponent(raw_text, mimeType, validParams, _this2.props.useExpertMode, _this2.props.selectedTab);
|
|
22289
22787
|
} catch (error) {
|
|
22290
22788
|
console.error(error);
|
|
22291
22789
|
}
|
|
@@ -22295,11 +22793,39 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22295
22793
|
// console.log("updateActiveButtons")
|
|
22296
22794
|
var rangeParams = _this2._getRangeParams();
|
|
22297
22795
|
if (rangeParams === null || rangeParams === undefined) {
|
|
22298
|
-
console.
|
|
22796
|
+
// console.log(
|
|
22797
|
+
// "updateActiveButtons: Empty content detected, setting all buttons to inactive"
|
|
22798
|
+
// );
|
|
22799
|
+
// Set all buttons to inactive state for graceful degradation
|
|
22800
|
+
var _activeButtons = {
|
|
22801
|
+
bold: false,
|
|
22802
|
+
italic: false,
|
|
22803
|
+
underline: false,
|
|
22804
|
+
subscript: false,
|
|
22805
|
+
superscript: false
|
|
22806
|
+
};
|
|
22807
|
+
_this2.lastSetActiveButtons = _activeButtons;
|
|
22808
|
+
_this2.setState({
|
|
22809
|
+
activeButtons: _activeButtons
|
|
22810
|
+
});
|
|
22299
22811
|
return;
|
|
22300
22812
|
}
|
|
22301
22813
|
if (rangeParams.startNodeIndex < 0) {
|
|
22302
|
-
console.
|
|
22814
|
+
// console.log(
|
|
22815
|
+
// "updateActiveButtons: Empty content detected (startNodeIndex < 0), setting all buttons to inactive"
|
|
22816
|
+
// );
|
|
22817
|
+
// Set all buttons to inactive state for graceful degradation
|
|
22818
|
+
var _activeButtons2 = {
|
|
22819
|
+
bold: false,
|
|
22820
|
+
italic: false,
|
|
22821
|
+
underline: false,
|
|
22822
|
+
subscript: false,
|
|
22823
|
+
superscript: false
|
|
22824
|
+
};
|
|
22825
|
+
_this2.lastSetActiveButtons = _activeButtons2;
|
|
22826
|
+
_this2.setState({
|
|
22827
|
+
activeButtons: _activeButtons2
|
|
22828
|
+
});
|
|
22303
22829
|
return;
|
|
22304
22830
|
}
|
|
22305
22831
|
var node = _this2._findNodeWithIndex(rangeParams.startNodeIndex);
|
|
@@ -22344,37 +22870,229 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22344
22870
|
console.error(error);
|
|
22345
22871
|
}
|
|
22346
22872
|
});
|
|
22347
|
-
_defineProperty(_this2, "
|
|
22348
|
-
|
|
22349
|
-
|
|
22350
|
-
|
|
22351
|
-
|
|
22873
|
+
_defineProperty(_this2, "handleCopy", function (event) {
|
|
22874
|
+
try {
|
|
22875
|
+
var selection = window.getSelection();
|
|
22876
|
+
if (selection.rangeCount === 0) return;
|
|
22877
|
+
var range = selection.getRangeAt(0);
|
|
22878
|
+
var container = document.createElement("div");
|
|
22879
|
+
container.appendChild(range.cloneContents());
|
|
22880
|
+
|
|
22881
|
+
// Convert KaTeX nodes to raw LaTeX for clipboard
|
|
22882
|
+
var katexNodes = container.querySelectorAll(".katex");
|
|
22883
|
+
katexNodes.forEach(function (katexNode) {
|
|
22884
|
+
try {
|
|
22885
|
+
var latex = getLatex(katexNode);
|
|
22886
|
+
if (latex && latex !== "error") {
|
|
22887
|
+
// Replace KaTeX node with raw LaTeX in math tags
|
|
22888
|
+
var mathElement = document.createElement("span");
|
|
22889
|
+
mathElement.setAttribute("data-latex", latex);
|
|
22890
|
+
mathElement.textContent = "<math>".concat(latex, "</math>");
|
|
22891
|
+
katexNode.parentNode.replaceChild(mathElement, katexNode);
|
|
22892
|
+
}
|
|
22893
|
+
} catch (err) {
|
|
22894
|
+
console.warn("Failed to extract LaTeX during copy:", err);
|
|
22895
|
+
}
|
|
22896
|
+
});
|
|
22897
|
+
|
|
22898
|
+
// Set clipboard data
|
|
22899
|
+
var htmlContent = container.innerHTML;
|
|
22900
|
+
var textContent = container.textContent;
|
|
22901
|
+
if (event.clipboardData) {
|
|
22902
|
+
event.clipboardData.setData("text/html", htmlContent);
|
|
22903
|
+
event.clipboardData.setData("text/plain", textContent);
|
|
22904
|
+
event.preventDefault();
|
|
22905
|
+
}
|
|
22906
|
+
} catch (error) {
|
|
22907
|
+
console.error("Error during copy operation:", error);
|
|
22352
22908
|
}
|
|
22353
|
-
|
|
22354
|
-
|
|
22355
|
-
|
|
22356
|
-
|
|
22357
|
-
|
|
22358
|
-
|
|
22359
|
-
|
|
22360
|
-
if (pasteHtml !== null && pasteHtml.length > 0) {
|
|
22361
|
-
// console.log("** Paste html");
|
|
22362
|
-
// console.log(pasteHtml);
|
|
22363
|
-
pasteHtml = sanitiseHtml(pasteHtml);
|
|
22364
|
-
// console.log("** Santised paste html");
|
|
22365
|
-
// console.log(pasteHtml);
|
|
22366
|
-
_this2.insertHtml(pasteHtml);
|
|
22909
|
+
});
|
|
22910
|
+
_defineProperty(_this2, "handlePaste", function (event) {
|
|
22911
|
+
try {
|
|
22912
|
+
var clipboardData = event.clipboardData || window.clipboardData;
|
|
22913
|
+
if (!clipboardData) {
|
|
22914
|
+
return;
|
|
22915
|
+
}
|
|
22367
22916
|
event.preventDefault();
|
|
22368
|
-
|
|
22369
|
-
var
|
|
22917
|
+
var pasteHtml = clipboardData.getData("text/html");
|
|
22918
|
+
var pasteText = clipboardData.getData("text/plain");
|
|
22919
|
+
|
|
22920
|
+
// Get current cursor position
|
|
22921
|
+
var rangeParams = _this2._getRangeParams();
|
|
22922
|
+
if (!rangeParams) {
|
|
22923
|
+
console.warn("Could not get range params for paste");
|
|
22924
|
+
return;
|
|
22925
|
+
}
|
|
22926
|
+
|
|
22927
|
+
// Store old range params for cursor positioning (like equation editor)
|
|
22928
|
+
_this2.setOldRangeParams(rangeParams);
|
|
22929
|
+
|
|
22930
|
+
// Clear any existing selection
|
|
22370
22931
|
var selection = window.getSelection();
|
|
22371
|
-
if (
|
|
22372
|
-
|
|
22373
|
-
return false;
|
|
22932
|
+
if (selection.rangeCount > 0) {
|
|
22933
|
+
selection.deleteFromDocument();
|
|
22374
22934
|
}
|
|
22375
|
-
|
|
22376
|
-
|
|
22377
|
-
|
|
22935
|
+
var finalText = "";
|
|
22936
|
+
var finalMimeType = _this2.props.mimeType || "text/html";
|
|
22937
|
+
var hasMathContent = false;
|
|
22938
|
+
|
|
22939
|
+
// Process HTML paste first
|
|
22940
|
+
if (pasteHtml && pasteHtml.length > 0) {
|
|
22941
|
+
// console.log("PASTE DEBUG - HTML detected:", JSON.stringify(pasteHtml));
|
|
22942
|
+
var processedHtml = pasteHtml;
|
|
22943
|
+
|
|
22944
|
+
// Clean unwanted elements
|
|
22945
|
+
processedHtml = processedHtml.replace(/<meta[^>]*>/gi, "");
|
|
22946
|
+
processedHtml = processedHtml.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "");
|
|
22947
|
+
processedHtml = processedHtml.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
22948
|
+
processedHtml = processedHtml.replace(/<!\x2D\x2D[\s\S]*?\x2D\x2D>/g, "");
|
|
22949
|
+
|
|
22950
|
+
// Convert data-latex attributes to math tags
|
|
22951
|
+
processedHtml = processedHtml.replace(/<span[^>]*data-latex="([^"]*)"[^>]*>.*?<\/span>/gi, "<math>$1</math>");
|
|
22952
|
+
|
|
22953
|
+
// Convert KaTeX nodes to math tags
|
|
22954
|
+
processedHtml = processedHtml.replace(/<span[^>]*class="katex"[^>]*>.*?<annotation[^>]*encoding="application\/x-tex"[^>]*>([^<]*)<\/annotation>.*?<\/span>/gi, "<math>$1</math>");
|
|
22955
|
+
|
|
22956
|
+
// Extract raw text content, keeping math tags
|
|
22957
|
+
var rawTextContent = processedHtml;
|
|
22958
|
+
rawTextContent = rawTextContent.replace(/<(?!\/?(math)>)[^>]*>/gi, "");
|
|
22959
|
+
|
|
22960
|
+
// console.log(
|
|
22961
|
+
// "PASTE DEBUG - Extracted raw text:",
|
|
22962
|
+
// JSON.stringify(rawTextContent)
|
|
22963
|
+
// );
|
|
22964
|
+
|
|
22965
|
+
// Apply sanitiseHtml for security (like in the old version)
|
|
22966
|
+
if (typeof sanitiseHtml === "function") {
|
|
22967
|
+
rawTextContent = sanitiseHtml(rawTextContent);
|
|
22968
|
+
// console.log("PASTE DEBUG - After sanitiseHtml:", JSON.stringify(rawTextContent));
|
|
22969
|
+
}
|
|
22970
|
+
|
|
22971
|
+
// Check if we have math content
|
|
22972
|
+
var hasMathTags = /<math>/i.test(rawTextContent);
|
|
22973
|
+
// console.log("PASTE DEBUG - Has math tags:", hasMathTags);
|
|
22974
|
+
|
|
22975
|
+
// Also check for LaTeX patterns in the extracted text (in case HTML doesn't have math tags)
|
|
22976
|
+
var hasLatexPatterns = _this2.detectLatexPatterns(rawTextContent);
|
|
22977
|
+
// console.log("PASTE DEBUG - Has LaTeX patterns:", hasLatexPatterns);
|
|
22978
|
+
|
|
22979
|
+
if ((hasMathTags || hasLatexPatterns) && _this2.enableMath()) {
|
|
22980
|
+
// If we found LaTeX patterns but no math tags, wrap the content
|
|
22981
|
+
if (!hasMathTags && hasLatexPatterns) {
|
|
22982
|
+
finalText = "<math>".concat(rawTextContent, "</math>");
|
|
22983
|
+
// console.log(
|
|
22984
|
+
// "PASTE DEBUG - Wrapping extracted HTML content in math tags"
|
|
22985
|
+
// );
|
|
22986
|
+
} else {
|
|
22987
|
+
finalText = rawTextContent;
|
|
22988
|
+
}
|
|
22989
|
+
finalMimeType = "application/x-zzish-html-math";
|
|
22990
|
+
hasMathContent = true;
|
|
22991
|
+
} else {
|
|
22992
|
+
finalText = rawTextContent;
|
|
22993
|
+
finalMimeType = "text/html";
|
|
22994
|
+
}
|
|
22995
|
+
}
|
|
22996
|
+
// Process plain text paste
|
|
22997
|
+
else if (pasteText && pasteText.length > 0) {
|
|
22998
|
+
// Debug paste content
|
|
22999
|
+
// console.log("PASTE DEBUG - Original text:", JSON.stringify(pasteText));
|
|
23000
|
+
// console.log("PASTE DEBUG - Text length:", pasteText.length);
|
|
23001
|
+
|
|
23002
|
+
// Clean up paste text (remove excessive newlines that might interfere with detection)
|
|
23003
|
+
var cleanedPasteText = pasteText.replace(/\n{3,}/g, "\n").trim();
|
|
23004
|
+
// console.log(
|
|
23005
|
+
// "PASTE DEBUG - Cleaned text:",
|
|
23006
|
+
// JSON.stringify(cleanedPasteText)
|
|
23007
|
+
// );
|
|
23008
|
+
|
|
23009
|
+
// Use comprehensive LaTeX pattern detection
|
|
23010
|
+
var _hasLatexPatterns = _this2.detectLatexPatterns(cleanedPasteText);
|
|
23011
|
+
// console.log("PASTE DEBUG - LaTeX patterns detected:", hasLatexPatterns);
|
|
23012
|
+
|
|
23013
|
+
if (_hasLatexPatterns && _this2.enableMath()) {
|
|
23014
|
+
// Wrap entire paste content in math tags if LaTeX patterns detected
|
|
23015
|
+
finalText = "<math>".concat(cleanedPasteText, "</math>");
|
|
23016
|
+
finalMimeType = "application/x-zzish-html-math";
|
|
23017
|
+
hasMathContent = true;
|
|
23018
|
+
// console.log("PASTE DEBUG - Wrapping in math tags:", finalText);
|
|
23019
|
+
} else {
|
|
23020
|
+
finalText = cleanedPasteText;
|
|
23021
|
+
finalMimeType = "text/plain";
|
|
23022
|
+
// console.log("PASTE DEBUG - Using as plain text:", finalText);
|
|
23023
|
+
}
|
|
23024
|
+
} else {
|
|
23025
|
+
// Nothing to paste
|
|
23026
|
+
return;
|
|
23027
|
+
}
|
|
23028
|
+
|
|
23029
|
+
// Use the component's insert mechanism to handle paste properly
|
|
23030
|
+
if (finalText) {
|
|
23031
|
+
// Get current node and create marked text at cursor position
|
|
23032
|
+
var currentNode = _this2._findNodeWithIndex(rangeParams.startNodeIndex);
|
|
23033
|
+
var markedText = elementToMarkedRawText(_this2.editableDiv, currentNode, rangeParams.startOffset, _this2.enableHtml());
|
|
23034
|
+
|
|
23035
|
+
// Insert the new content at the marked position
|
|
23036
|
+
var newRawText = removeMarks(insertCharacterBeforeMarks(markedText, finalText));
|
|
23037
|
+
|
|
23038
|
+
// Convert any remaining \[...\] LaTeX expressions to <math>...</math> format
|
|
23039
|
+
// This ensures consistency when paste adds <math> tags alongside existing \[...\] expressions
|
|
23040
|
+
if (_this2.enableMath()) {
|
|
23041
|
+
newRawText = newRawText.replace(/\\\[([^\]]*?)\\\]/g, "<math>$1</math>");
|
|
23042
|
+
}
|
|
23043
|
+
|
|
23044
|
+
// Calculate cursor position exactly like equation editor does
|
|
23045
|
+
var newRangeParams = null;
|
|
23046
|
+
if (hasMathContent) {
|
|
23047
|
+
// Use same approach as equation editor for math content
|
|
23048
|
+
var oldRangeParams = _this2.getOldRangeParams();
|
|
23049
|
+
var mathTagCount = (finalText.match(/<math>/gi) || []).length;
|
|
23050
|
+
if (_this2.props.value === "") {
|
|
23051
|
+
// Special case of previously empty text input (like equation editor)
|
|
23052
|
+
newRangeParams = {
|
|
23053
|
+
startNodeIndex: mathTagCount * 2,
|
|
23054
|
+
startOffset: SMALL_SPACE_LENGTH,
|
|
23055
|
+
endNodeIndex: mathTagCount * 2,
|
|
23056
|
+
endOffset: SMALL_SPACE_LENGTH
|
|
23057
|
+
};
|
|
23058
|
+
} else {
|
|
23059
|
+
// Normal case - position cursor after inserted math content (like equation editor)
|
|
23060
|
+
newRangeParams = {
|
|
23061
|
+
startNodeIndex: oldRangeParams.startNodeIndex + mathTagCount * 2,
|
|
23062
|
+
startOffset: SMALL_SPACE_LENGTH,
|
|
23063
|
+
endNodeIndex: oldRangeParams.startNodeIndex + mathTagCount * 2,
|
|
23064
|
+
endOffset: SMALL_SPACE_LENGTH
|
|
23065
|
+
};
|
|
23066
|
+
}
|
|
23067
|
+
} else {
|
|
23068
|
+
// For text content, use global offset like before
|
|
23069
|
+
var newGlobalOffset = rangeParams.startGlobalOffset + finalText.length;
|
|
23070
|
+
newRangeParams = {
|
|
23071
|
+
startGlobalOffset: newGlobalOffset,
|
|
23072
|
+
endGlobalOffset: newGlobalOffset
|
|
23073
|
+
};
|
|
23074
|
+
}
|
|
23075
|
+
|
|
23076
|
+
// Determine final MIME type based on the complete content
|
|
23077
|
+
var actualMimeType = finalMimeType;
|
|
23078
|
+
if (/<math>/i.test(newRawText)) {
|
|
23079
|
+
actualMimeType = "application/x-zzish-html-math";
|
|
23080
|
+
} else if (_this2.enableHtml() && (/<[^>]+>/i.test(newRawText) || actualMimeType === "text/html")) {
|
|
23081
|
+
actualMimeType = "text/html";
|
|
23082
|
+
} else {
|
|
23083
|
+
actualMimeType = "text/plain";
|
|
23084
|
+
}
|
|
23085
|
+
|
|
23086
|
+
// Clean up the raw text for proper encoding
|
|
23087
|
+
var cleanedRawText = removeEncodingIfPlainText(newRawText, actualMimeType, _this2.enableHtml());
|
|
23088
|
+
|
|
23089
|
+
// Apply the change using the component's standard flow
|
|
23090
|
+
_this2.applyChangesToComponent(cleanedRawText, actualMimeType, newRangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
|
|
23091
|
+
}
|
|
23092
|
+
} catch (error) {
|
|
23093
|
+
console.error("Error in paste handler:", error);
|
|
23094
|
+
// Let default paste behavior handle it
|
|
23095
|
+
return true;
|
|
22378
23096
|
}
|
|
22379
23097
|
});
|
|
22380
23098
|
_defineProperty(_this2, "showEquationEditor", function () {
|
|
@@ -22467,6 +23185,9 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22467
23185
|
_defineProperty(_this2, "handleMouseUp", function (event) {
|
|
22468
23186
|
try {
|
|
22469
23187
|
_this2.initialiseHistory();
|
|
23188
|
+
|
|
23189
|
+
// Clear selection anchor on mouse click
|
|
23190
|
+
_this2.selectionAnchor = null;
|
|
22470
23191
|
var params = _this2._getRangeParams();
|
|
22471
23192
|
var startNode = _this2._findNodeWithIndex(params.startNodeIndex);
|
|
22472
23193
|
var endNode = _this2._findNodeWithIndex(params.endNodeIndex);
|
|
@@ -22551,18 +23272,18 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22551
23272
|
new_offset = oldRangeParams.startOffset;
|
|
22552
23273
|
}
|
|
22553
23274
|
}
|
|
22554
|
-
var
|
|
23275
|
+
var _new_rangeParams7 = {
|
|
22555
23276
|
startNodeIndex: new_index,
|
|
22556
23277
|
startOffset: new_offset,
|
|
22557
23278
|
endNodeIndex: new_index,
|
|
22558
23279
|
endOffset: new_offset
|
|
22559
23280
|
};
|
|
22560
|
-
_this2.setOldRangeParams(
|
|
22561
|
-
var
|
|
22562
|
-
var
|
|
22563
|
-
if (_this2.editingExistingEquation)
|
|
22564
|
-
_new_raw_text = removeEncodingIfPlainText(_new_raw_text,
|
|
22565
|
-
_this2.applyChangesToComponent(_new_raw_text,
|
|
23281
|
+
_this2.setOldRangeParams(_new_rangeParams7);
|
|
23282
|
+
var _nodeCounts2 = _this2._countNodeTypes();
|
|
23283
|
+
var _mimeType2 = null;
|
|
23284
|
+
if (_this2.editingExistingEquation) _mimeType2 = _this2.getMimeType(_nodeCounts2.html > 0, _nodeCounts2.math > 1);else _mimeType2 = _this2.getMimeType(_nodeCounts2.html > 0, _nodeCounts2.math > 0);
|
|
23285
|
+
_new_raw_text = removeEncodingIfPlainText(_new_raw_text, _mimeType2, _this2.enableHtml());
|
|
23286
|
+
_this2.applyChangesToComponent(_new_raw_text, _mimeType2, _new_rangeParams7, _this2.props.useExpertMode, _this2.props.selectedTab);
|
|
22566
23287
|
_this2.setState({
|
|
22567
23288
|
showEquationEditor: false
|
|
22568
23289
|
});
|
|
@@ -22574,7 +23295,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22574
23295
|
var new_raw_text = replaceMarksWithMath(_this2.markedRawText, latex, _this2.enableHtml());
|
|
22575
23296
|
var new_rangeParams = _this2.getOldRangeParams();
|
|
22576
23297
|
if (_this2.moveCursorOnInsert) {
|
|
22577
|
-
if (_this2.props.value === "")
|
|
23298
|
+
if (_this2.props.value === "") {
|
|
22578
23299
|
// Special case of previously empty text input
|
|
22579
23300
|
new_rangeParams = {
|
|
22580
23301
|
startNodeIndex: 2,
|
|
@@ -22582,13 +23303,20 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22582
23303
|
endNodeIndex: 2,
|
|
22583
23304
|
endOffset: SMALL_SPACE_LENGTH
|
|
22584
23305
|
};
|
|
22585
|
-
|
|
22586
|
-
|
|
22587
|
-
|
|
22588
|
-
|
|
22589
|
-
|
|
22590
|
-
|
|
22591
|
-
|
|
23306
|
+
} else {
|
|
23307
|
+
// Position cursor after the inserted math element using globalOffset
|
|
23308
|
+
// Find the position right after the last math tag in the content
|
|
23309
|
+
var mathTagMatches = _toConsumableArray(new_raw_text.matchAll(/<math>[^<]*<\/math>/gi));
|
|
23310
|
+
if (mathTagMatches.length > 0) {
|
|
23311
|
+
var lastMatch = mathTagMatches[mathTagMatches.length - 1];
|
|
23312
|
+
var afterMathOffset = lastMatch.index + lastMatch[0].length;
|
|
23313
|
+
new_rangeParams = {
|
|
23314
|
+
startGlobalOffset: afterMathOffset,
|
|
23315
|
+
endGlobalOffset: afterMathOffset
|
|
23316
|
+
};
|
|
23317
|
+
}
|
|
23318
|
+
// If no math tags found, keep old range params
|
|
23319
|
+
}
|
|
22592
23320
|
}
|
|
22593
23321
|
// console.log("New cursor pos: "+new_rangeParams.startNodeIndex+"->"+new_rangeParams.startOffset)
|
|
22594
23322
|
_this2.setOldRangeParams(new_rangeParams);
|
|
@@ -22615,6 +23343,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22615
23343
|
try {
|
|
22616
23344
|
style = style.toLowerCase();
|
|
22617
23345
|
var success = false;
|
|
23346
|
+
|
|
22618
23347
|
// This first part is a workaround whereby executing subscript or superscript
|
|
22619
23348
|
// within an existing subscript or superscript makes the text even smaller instead
|
|
22620
23349
|
// of toggling it off. Thus we manually toggle it off with some jigerry pokery!
|
|
@@ -22632,8 +23361,65 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22632
23361
|
if (_this2.state.activeButtons.italic) success = document.execCommand("italic", false, null);
|
|
22633
23362
|
if (_this2.state.activeButtons.underline) success = document.execCommand("underline", false, null);
|
|
22634
23363
|
} else {
|
|
22635
|
-
|
|
22636
|
-
|
|
23364
|
+
var _selection = document.getSelection();
|
|
23365
|
+
if (_selection && _selection.rangeCount > 0) {
|
|
23366
|
+
var _range = _selection.getRangeAt(0);
|
|
23367
|
+
if (_range.collapsed) {
|
|
23368
|
+
// For cursor position (no selection), use insertHTML with styled wrapper
|
|
23369
|
+
// This creates a formatted element that will maintain styling for future typing
|
|
23370
|
+
var isToggleOff = _this2.state.activeButtons[style];
|
|
23371
|
+
if (!isToggleOff) {
|
|
23372
|
+
// Turning style ON - insert a styled wrapper element
|
|
23373
|
+
var wrapperTag;
|
|
23374
|
+
switch (style) {
|
|
23375
|
+
case "bold":
|
|
23376
|
+
wrapperTag = "strong";
|
|
23377
|
+
break;
|
|
23378
|
+
case "italic":
|
|
23379
|
+
wrapperTag = "em";
|
|
23380
|
+
break;
|
|
23381
|
+
case "underline":
|
|
23382
|
+
wrapperTag = "u";
|
|
23383
|
+
break;
|
|
23384
|
+
case "subscript":
|
|
23385
|
+
wrapperTag = "sub";
|
|
23386
|
+
break;
|
|
23387
|
+
case "superscript":
|
|
23388
|
+
wrapperTag = "sup";
|
|
23389
|
+
break;
|
|
23390
|
+
default:
|
|
23391
|
+
wrapperTag = "span";
|
|
23392
|
+
break;
|
|
23393
|
+
}
|
|
23394
|
+
|
|
23395
|
+
// Insert an invisible character wrapped in the styled element
|
|
23396
|
+
// This provides a "landing zone" for future typing
|
|
23397
|
+
var styledElement = "<".concat(wrapperTag, ">\u200B</").concat(wrapperTag, ">");
|
|
23398
|
+
success = document.execCommand("insertHTML", false, styledElement);
|
|
23399
|
+
|
|
23400
|
+
// Move cursor inside the styled element
|
|
23401
|
+
setTimeout(function () {
|
|
23402
|
+
var newSelection = document.getSelection();
|
|
23403
|
+
if (newSelection && newSelection.rangeCount > 0) {
|
|
23404
|
+
var newRange = newSelection.getRangeAt(0);
|
|
23405
|
+
var styledNode = newRange.startContainer.parentElement;
|
|
23406
|
+
if (styledNode && styledNode.tagName.toLowerCase() === wrapperTag) {
|
|
23407
|
+
newRange.setStart(styledNode, 0);
|
|
23408
|
+
newRange.setEnd(styledNode, 0);
|
|
23409
|
+
newSelection.removeAllRanges();
|
|
23410
|
+
newSelection.addRange(newRange);
|
|
23411
|
+
}
|
|
23412
|
+
}
|
|
23413
|
+
}, 0);
|
|
23414
|
+
} else {
|
|
23415
|
+
// Turning style OFF - just apply execCommand normally
|
|
23416
|
+
success = document.execCommand(style, false, null);
|
|
23417
|
+
}
|
|
23418
|
+
} else {
|
|
23419
|
+
// For text selection, use regular execCommand
|
|
23420
|
+
success = document.execCommand(style, false, null);
|
|
23421
|
+
}
|
|
23422
|
+
}
|
|
22637
23423
|
}
|
|
22638
23424
|
var buttonState = _this2.state.activeButtons[style];
|
|
22639
23425
|
if (buttonState === null || buttonState === undefined) return success;
|
|
@@ -22676,7 +23462,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22676
23462
|
}
|
|
22677
23463
|
});
|
|
22678
23464
|
_defineProperty(_this2, "insertRawText", function (new_text) {
|
|
22679
|
-
var selectInsertedText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] :
|
|
23465
|
+
var selectInsertedText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
22680
23466
|
try {
|
|
22681
23467
|
var rangeParams = _this2._getRangeParams();
|
|
22682
23468
|
var node = _this2._findNodeWithIndex(rangeParams.endNodeIndex);
|
|
@@ -22739,10 +23525,11 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22739
23525
|
// Preserve the selection
|
|
22740
23526
|
if (lastNode) {
|
|
22741
23527
|
range = range.cloneRange();
|
|
22742
|
-
range.setStartAfter(lastNode);
|
|
22743
23528
|
if (selectPastedContent) {
|
|
22744
23529
|
range.setStartBefore(firstNode);
|
|
23530
|
+
range.setEndAfter(lastNode);
|
|
22745
23531
|
} else {
|
|
23532
|
+
range.setStartAfter(lastNode);
|
|
22746
23533
|
range.collapse(true);
|
|
22747
23534
|
}
|
|
22748
23535
|
sel.removeAllRanges();
|
|
@@ -22762,10 +23549,11 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22762
23549
|
}
|
|
22763
23550
|
});
|
|
22764
23551
|
_defineProperty(_this2, "insertHtml", function (new_html) {
|
|
23552
|
+
var selectPastedContent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
22765
23553
|
try {
|
|
22766
23554
|
// console.log("New html: "+new_html)
|
|
22767
23555
|
// console.log("inserting: "+new_html)
|
|
22768
|
-
_this2.pasteHtmlAtCaret(new_html,
|
|
23556
|
+
_this2.pasteHtmlAtCaret(new_html, selectPastedContent);
|
|
22769
23557
|
var new_rangeParams = null;
|
|
22770
23558
|
// console.log("New range params: ")
|
|
22771
23559
|
try {
|
|
@@ -22931,7 +23719,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22931
23719
|
_defineProperty(_this2, "handleAccentButtonClick", function (event, oldCharacter, newCharacter) {
|
|
22932
23720
|
try {
|
|
22933
23721
|
_this2.insertAccentLetter(event, oldCharacter, newCharacter);
|
|
22934
|
-
console.log("Hiding accent bar 3");
|
|
23722
|
+
// console.log("Hiding accent bar 3");
|
|
22935
23723
|
_this2.setState({
|
|
22936
23724
|
showAccentBar: false
|
|
22937
23725
|
});
|
|
@@ -22939,6 +23727,23 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22939
23727
|
console.error(error);
|
|
22940
23728
|
}
|
|
22941
23729
|
});
|
|
23730
|
+
_defineProperty(_this2, "cleanupCorruptedKatexNodes", function () {
|
|
23731
|
+
try {
|
|
23732
|
+
var katexNodes = _this2.editableDiv.querySelectorAll(".katex, .katex-error");
|
|
23733
|
+
katexNodes.forEach(function (node) {
|
|
23734
|
+
// Check if KaTeX node has proper structure
|
|
23735
|
+
var annotation = node.querySelector('annotation[encoding="application/x-tex"]');
|
|
23736
|
+
if (!annotation || !annotation.textContent) {
|
|
23737
|
+
console.warn("Removing corrupted KaTeX node:", node);
|
|
23738
|
+
// Replace corrupted node with placeholder text
|
|
23739
|
+
var textNode = document.createTextNode("[Math Error]");
|
|
23740
|
+
node.parentNode.replaceChild(textNode, node);
|
|
23741
|
+
}
|
|
23742
|
+
});
|
|
23743
|
+
} catch (error) {
|
|
23744
|
+
console.error("Error cleaning up corrupted KaTeX nodes:", error);
|
|
23745
|
+
}
|
|
23746
|
+
});
|
|
22942
23747
|
_defineProperty(_this2, "focus", function () {
|
|
22943
23748
|
_this2.editableDiv.focus();
|
|
22944
23749
|
});
|
|
@@ -22962,7 +23767,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22962
23767
|
onBlur();
|
|
22963
23768
|
}
|
|
22964
23769
|
try {
|
|
22965
|
-
console.log("Hiding accent bar 4");
|
|
23770
|
+
// console.log("Hiding accent bar 4");
|
|
22966
23771
|
_this2.setState({
|
|
22967
23772
|
hasFocus: false,
|
|
22968
23773
|
showAccentBar: false
|
|
@@ -22977,6 +23782,96 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22977
23782
|
_defineProperty(_this2, "handleCompositionEnd", function (event) {
|
|
22978
23783
|
_this2.isComposing = false;
|
|
22979
23784
|
});
|
|
23785
|
+
// Comprehensive LaTeX pattern detection and auto-wrapping in math tags
|
|
23786
|
+
// Comprehensive LaTeX pattern detection for paste auto-wrapping
|
|
23787
|
+
_defineProperty(_this2, "detectLatexPatterns", function (text) {
|
|
23788
|
+
if (!_this2.enableMath() || !text || typeof text !== "string") {
|
|
23789
|
+
// console.log("PATTERN DEBUG - Early return:", {
|
|
23790
|
+
// enableMath: this.enableMath(),
|
|
23791
|
+
// text: text,
|
|
23792
|
+
// type: typeof text,
|
|
23793
|
+
// });
|
|
23794
|
+
return false;
|
|
23795
|
+
}
|
|
23796
|
+
|
|
23797
|
+
// console.log("PATTERN DEBUG - Testing text:", JSON.stringify(text));
|
|
23798
|
+
|
|
23799
|
+
// Define comprehensive LaTeX patterns based on KaTeX documentation
|
|
23800
|
+
var latexPatterns = [
|
|
23801
|
+
// Complex expressions
|
|
23802
|
+
// Matrix environments
|
|
23803
|
+
/\\begin\s*\{\s*(matrix|pmatrix|bmatrix|Bmatrix|vmatrix|Vmatrix|array)\s*\}[\s\S]*?\\end\s*\{\s*\1\s*\}/,
|
|
23804
|
+
// Cases and aligned environments
|
|
23805
|
+
/\\begin\s*\{\s*(cases|aligned|align|gather|split)\s*\}[\s\S]*?\\end\s*\{\s*\1\s*\}/,
|
|
23806
|
+
// Fractions and roots with nested braces
|
|
23807
|
+
/\\frac\s*\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}\s*\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/, /\\sqrt\s*(?:\[[^\]]*\])?\s*\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/,
|
|
23808
|
+
// Text in math mode with braces
|
|
23809
|
+
/\\(text|textrm|textit|textbf|textsf|texttt|mathrm|mathit|mathbf|mathsf|mathtt|mathcal|mathscr|mathfrak|mathbb)\s*\{[^{}]*\}/,
|
|
23810
|
+
// Accents and modifiers with braces
|
|
23811
|
+
/\\(hat|check|breve|acute|grave|tilde|bar|vec|dot|ddot|widehat|widetilde|overline|underline|overbrace|underbrace)\s*\{[^{}]*\}/,
|
|
23812
|
+
// Number sets with braces
|
|
23813
|
+
/\\(mathbb|mathbf)\s*\{[NZQRCH]\}/,
|
|
23814
|
+
// Delimiters and brackets
|
|
23815
|
+
/\\(left|right|big|Big|bigg|Bigg)\s*[\(\)\[\]\\{\\}|\\.]/, /\\[lr](paren|brace|brack|vert|Vert|angle|langle|rangle|floor|ceil)/,
|
|
23816
|
+
// Greek letters (comprehensive list from KaTeX)
|
|
23817
|
+
/\\(alpha|beta|gamma|delta|epsilon|varepsilon|zeta|eta|theta|vartheta|iota|kappa|lambda|mu|nu|xi|omicron|pi|varpi|rho|varrho|sigma|varsigma|tau|upsilon|phi|varphi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)\b/,
|
|
23818
|
+
// Mathematical functions
|
|
23819
|
+
/\\(sin|cos|tan|sec|csc|cot|sinh|cosh|tanh|sech|csch|coth|arcsin|arccos|arctan|arcsec|arccsc|arccot|log|ln|lg|exp|lim|limsup|liminf|sup|inf|max|min|arg|ker|deg|gcd|det|hom|dim)\b/,
|
|
23820
|
+
// Mathematical operators and symbols
|
|
23821
|
+
/\\(pm|mp|times|div|cdot|ast|star|circ|bullet|cap|cup|uplus|sqcap|sqcup|vee|wedge|setminus|wr|diamond|bigtriangleup|bigtriangledown|triangleleft|triangleright|lhd|rhd|unlhd|unrhd|oplus|ominus|otimes|oslash|odot|bigcirc|dagger|ddagger|amalg)\b/,
|
|
23822
|
+
// Relation symbols
|
|
23823
|
+
/\\(leq|geq|equiv|models|prec|succ|sim|perp|preceq|succeq|simeq|mid|ll|gg|asymp|parallel|subset|supset|approx|bowtie|subseteq|supseteq|cong|smile|sqsubset|sqsupset|doteq|frown|sqsubseteq|sqsupseteq|propto|vdash|dashv|in|ni|notin)\b/,
|
|
23824
|
+
// Negated relations
|
|
23825
|
+
/\\(not|neq|ne|notin|nmid|nparallel|nleq|ngeq|nless|ngtr|nprec|nsucc|lneq|gneq|npreceq|nsucceq|precneqq|succneqq|lneqq|gneqq)\b/,
|
|
23826
|
+
// Arrows
|
|
23827
|
+
/\\(leftarrow|gets|rightarrow|to|leftrightarrow|uparrow|downarrow|updownarrow|Leftarrow|Rightarrow|Leftrightarrow|Uparrow|Downarrow|Updownarrow|mapsto|longmapsto|hookleftarrow|hookrightarrow|leftharpoonup|leftharpoondown|rightharpoonup|rightharpoondown|rightleftharpoons|iff)\b/,
|
|
23828
|
+
// Integrals, sums, products
|
|
23829
|
+
/\\(int|iint|iiint|oint|sum|prod|coprod|bigcup|bigcap|bigsqcup|bigvee|bigwedge|bigodot|bigotimes|bigoplus|biguplus)\b/,
|
|
23830
|
+
// Mathematical spacing and formatting
|
|
23831
|
+
/\\(quad|qquad|,|:|;|!|thinspace|medspace|thickspace|enspace|negspace)\b/,
|
|
23832
|
+
// Special characters and symbols
|
|
23833
|
+
/\\(infty|partial|nabla|pm|mp|emptyset|varnothing|complement|forall|exists|nexists|in|notin|ni|Re|Im|wp|angle|measuredangle|sphericalangle|top|bot|vdash|models|vDash|Vdash|Vvdash|nvdash|nvDash|nVdash|nVDash)\b/,
|
|
23834
|
+
// Single letter number sets
|
|
23835
|
+
/\\(N|Z|Q|R|C|H)\b/,
|
|
23836
|
+
// Simple expressions with operators and special characters
|
|
23837
|
+
/\d+\\surd\d+/,
|
|
23838
|
+
// Numbers with square root symbol
|
|
23839
|
+
/\\surd/,
|
|
23840
|
+
// Square root symbol alone
|
|
23841
|
+
|
|
23842
|
+
// Superscripts and subscripts (improved to catch simple formats)
|
|
23843
|
+
/\d+\^\d+/,
|
|
23844
|
+
// Number^number (e.g., 2^2, 10^3)
|
|
23845
|
+
/[a-zA-Z]\^\d+/,
|
|
23846
|
+
// Variable^number (e.g., x^2, y^3)
|
|
23847
|
+
/[a-zA-Z]\^[\{\d+\}]/,
|
|
23848
|
+
// Variable with superscript in braces (e.g., x^{2})
|
|
23849
|
+
/\d+_\d+/,
|
|
23850
|
+
// Number_number (e.g., H_2O becomes H_2O)
|
|
23851
|
+
/[a-zA-Z]_\d+/,
|
|
23852
|
+
// Variable_number (e.g., x_1, y_2)
|
|
23853
|
+
/[a-zA-Z]_[\{\d+\}]/,
|
|
23854
|
+
// Variable with subscript in braces (e.g., x_{12})
|
|
23855
|
+
|
|
23856
|
+
// Common mathematical expressions that should be wrapped
|
|
23857
|
+
/\d+\/\d+\s*[+\-*/]\s*\d+\/\d+/,
|
|
23858
|
+
// Fraction operations
|
|
23859
|
+
/[xy]\^2\s*[+\-]\s*\d+[xy]\s*[+\-]\s*\d+/ // Quadratic expressions
|
|
23860
|
+
];
|
|
23861
|
+
|
|
23862
|
+
// Check if any LaTeX patterns exist
|
|
23863
|
+
for (var i = 0; i < latexPatterns.length; i++) {
|
|
23864
|
+
var pattern = latexPatterns[i];
|
|
23865
|
+
var matches = pattern.test(text);
|
|
23866
|
+
if (matches) {
|
|
23867
|
+
// console.log(`PATTERN DEBUG - Pattern ${i} matched:`, pattern.source);
|
|
23868
|
+
return true;
|
|
23869
|
+
}
|
|
23870
|
+
}
|
|
23871
|
+
|
|
23872
|
+
// console.log("PATTERN DEBUG - No patterns matched");
|
|
23873
|
+
return false;
|
|
23874
|
+
});
|
|
22980
23875
|
_this2.state = {
|
|
22981
23876
|
showEquationEditor: false,
|
|
22982
23877
|
equationEditorLatex: "",
|
|
@@ -23033,18 +23928,27 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23033
23928
|
|
|
23034
23929
|
// keeps track of whether user is composing in an IME - see https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
|
|
23035
23930
|
_this2.isComposing = false;
|
|
23931
|
+
|
|
23932
|
+
// Track selection anchor for proper shift+arrow behavior
|
|
23933
|
+
_this2.selectionAnchor = null;
|
|
23036
23934
|
return _this2;
|
|
23037
23935
|
}
|
|
23038
23936
|
_inherits(MathRichInput, _React$Component);
|
|
23039
23937
|
return _createClass(MathRichInput, [{
|
|
23040
23938
|
key: "enableFontStyling",
|
|
23041
23939
|
value: function enableFontStyling() {
|
|
23042
|
-
|
|
23940
|
+
// Allow explicit override even in outputTex mode
|
|
23941
|
+
if (this.props.enableFontStyling !== null && this.props.enableFontStyling !== undefined) return this.props.enableFontStyling;
|
|
23942
|
+
// Don't disable font styling in outputTex mode anymore
|
|
23943
|
+
else return true;
|
|
23043
23944
|
}
|
|
23044
23945
|
}, {
|
|
23045
23946
|
key: "enableMultiline",
|
|
23046
23947
|
value: function enableMultiline() {
|
|
23047
|
-
|
|
23948
|
+
// Allow explicit override even in outputTex mode
|
|
23949
|
+
if (this.props.enableMultiline !== null && this.props.enableMultiline !== undefined) return this.props.enableMultiline;
|
|
23950
|
+
// Don't disable multiline in outputTex mode anymore
|
|
23951
|
+
else return true;
|
|
23048
23952
|
}
|
|
23049
23953
|
}, {
|
|
23050
23954
|
key: "enableHtml",
|
|
@@ -23074,11 +23978,18 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23074
23978
|
var _this$props$outputTex2, _this$props$outputPla;
|
|
23075
23979
|
var outputTex = (_this$props$outputTex2 = this.props.outputTex) !== null && _this$props$outputTex2 !== void 0 ? _this$props$outputTex2 : false;
|
|
23076
23980
|
var outputPlainText = (_this$props$outputPla = this.props.outputPlainText) !== null && _this$props$outputPla !== void 0 ? _this$props$outputPla : false;
|
|
23981
|
+
|
|
23982
|
+
// When outputTex is false, prioritize HTML formatting
|
|
23983
|
+
if (!outputTex) {
|
|
23984
|
+
if (hasMath) return MIME_TYPE_ZZISH_HTML_MATH;
|
|
23985
|
+
if (hasHtml || !outputPlainText) return MIME_TYPE_HTML;
|
|
23986
|
+
return MIME_TYPE_PLAIN_TEXT;
|
|
23987
|
+
}
|
|
23988
|
+
|
|
23989
|
+
// Original logic for outputTex = true
|
|
23077
23990
|
if (outputTex) {
|
|
23078
23991
|
if (hasMath || !outputPlainText) return MIME_TYPE_TEX;else return MIME_TYPE_PLAIN_TEXT;
|
|
23079
23992
|
}
|
|
23080
|
-
if (hasMath) return MIME_TYPE_ZZISH_HTML_MATH;
|
|
23081
|
-
if (hasHtml || !outputPlainText) return MIME_TYPE_HTML;
|
|
23082
23993
|
return MIME_TYPE_PLAIN_TEXT;
|
|
23083
23994
|
}
|
|
23084
23995
|
}, {
|
|
@@ -23130,6 +24041,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23130
24041
|
this.editableDiv.addEventListener("keydown", this.handleKeyDown);
|
|
23131
24042
|
this.editableDiv.addEventListener("keyup", this.handleKeyUp);
|
|
23132
24043
|
this.editableDiv.addEventListener("paste", this.handlePaste);
|
|
24044
|
+
this.editableDiv.addEventListener("copy", this.handleCopy);
|
|
23133
24045
|
if (this.props.autofocus === true) this.editableDiv.focus();
|
|
23134
24046
|
} catch (error) {
|
|
23135
24047
|
console.error(error);
|
|
@@ -23142,6 +24054,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23142
24054
|
this.editableDiv.removeEventListener("keydown", this.handleKeyDown);
|
|
23143
24055
|
this.editableDiv.removeEventListener("keyup", this.handleKeyUp);
|
|
23144
24056
|
this.editableDiv.removeEventListener("paste", this.handlePaste);
|
|
24057
|
+
this.editableDiv.removeEventListener("copy", this.handleCopy);
|
|
23145
24058
|
} catch (error) {
|
|
23146
24059
|
console.error(error);
|
|
23147
24060
|
}
|
|
@@ -23150,7 +24063,6 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23150
24063
|
key: "componentDidUpdate",
|
|
23151
24064
|
value: function componentDidUpdate() {
|
|
23152
24065
|
try {
|
|
23153
|
-
// console.log("componentDidUpdate")
|
|
23154
24066
|
if (this.afterComponentUpdateData !== null && this.afterComponentUpdateData !== undefined && this.afterComponentUpdateData.value === this.props.value) {
|
|
23155
24067
|
this._setRangeParams(this.afterComponentUpdateData.rangeParams);
|
|
23156
24068
|
this.afterComponentUpdateData = null;
|
|
@@ -23194,6 +24106,16 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23194
24106
|
console.log(this.props);
|
|
23195
24107
|
}
|
|
23196
24108
|
var html = rawTextToHtml(katex$1, this.props.value || "", this.props.mimeType);
|
|
24109
|
+
|
|
24110
|
+
// Debug render math
|
|
24111
|
+
// if (this.props.value && this.props.value.includes("<math>")) {
|
|
24112
|
+
// console.log("RENDER DEBUG:", {
|
|
24113
|
+
// propsValue: this.props.value,
|
|
24114
|
+
// propsMimeType: this.props.mimeType,
|
|
24115
|
+
// generatedHtml: html,
|
|
24116
|
+
// });
|
|
24117
|
+
// }
|
|
24118
|
+
|
|
23197
24119
|
var useClassName = "MathRichInput-Container"; // Don't change this name - used by various components to find node
|
|
23198
24120
|
if (this.props.className) useClassName = this.props.className + " " + useClassName;
|
|
23199
24121
|
var accentLetter = null;
|
|
@@ -23202,7 +24124,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23202
24124
|
if (this.props.className.includes("answer-edit-input")) {
|
|
23203
24125
|
toolbarExtraMargin = 20;
|
|
23204
24126
|
}
|
|
23205
|
-
console.log("Toolbar extra margin: " + toolbarExtraMargin);
|
|
24127
|
+
// console.log("Toolbar extra margin: " + toolbarExtraMargin);
|
|
24128
|
+
|
|
23206
24129
|
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
|
|
23207
24130
|
className: useClassName
|
|
23208
24131
|
}, /*#__PURE__*/React__default["default"].createElement("div", {
|