@zzish/math-rich-input 0.1.50 → 0.1.52
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 +1150 -196
- package/dist/math-rich-input.css +1 -1
- package/dist/standalone.js +1 -1
- package/package.json +3 -3
- package/src/EquationEditor.css +168 -160
- package/src/EquationEditorModal.css +143 -105
- package/src/EquationEditorModal.jsx +165 -24
- package/src/MathRichArea.jsx +5 -2
- package/src/MathRichInput.jsx +992 -207
- package/src/SymbolButton.css +1 -0
- package/src/Toolbar.jsx +3 -4
- package/src/mathRichInputDebug.js +98 -0
- package/src/mathRichInputHelper.js +128 -17
- package/src/standalone.js +6 -0
package/dist/index.js
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
+
var ReactDOM = require('react-dom');
|
|
6
7
|
|
|
7
8
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
9
|
|
|
9
10
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
11
|
+
var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
|
|
10
12
|
|
|
11
13
|
function _callSuper(t, o, e) {
|
|
12
14
|
return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
|
|
@@ -19311,31 +19313,50 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19311
19313
|
console.log("🔍 Focusing equation editor...");
|
|
19312
19314
|
if (_this.equationEditor) {
|
|
19313
19315
|
console.log("🔍 EquationEditor ref found");
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
19321
|
-
|
|
19322
|
-
|
|
19323
|
-
|
|
19324
|
-
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19328
|
-
|
|
19316
|
+
|
|
19317
|
+
// Prevent scroll jumping during focus
|
|
19318
|
+
var currentScrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
19319
|
+
try {
|
|
19320
|
+
if (_this.state.useExpertMode) {
|
|
19321
|
+
// Focus textarea in expert mode
|
|
19322
|
+
console.log("🔍 Expert mode - focusing latexInput");
|
|
19323
|
+
if (_this.equationEditor.latexInput) {
|
|
19324
|
+
// Use preventScroll option if available
|
|
19325
|
+
_this.equationEditor.latexInput.focus({
|
|
19326
|
+
preventScroll: true
|
|
19327
|
+
});
|
|
19328
|
+
console.log("✅ LatexInput focused");
|
|
19329
|
+
} else {
|
|
19330
|
+
console.log("❌ LatexInput not found");
|
|
19331
|
+
}
|
|
19329
19332
|
} else {
|
|
19330
|
-
|
|
19333
|
+
// Focus MathQuill in normal mode
|
|
19334
|
+
console.log("🔍 Normal mode - focusing mathQuill");
|
|
19335
|
+
if (_this.equationEditor.mathQuill) {
|
|
19336
|
+
_this.equationEditor.mathQuill.focus();
|
|
19337
|
+
console.log("✅ MathQuill focused");
|
|
19338
|
+
} else {
|
|
19339
|
+
console.log("❌ MathQuill not found");
|
|
19340
|
+
}
|
|
19331
19341
|
}
|
|
19342
|
+
} catch (error) {
|
|
19343
|
+
console.warn("🔍 Focus failed:", error);
|
|
19332
19344
|
}
|
|
19345
|
+
|
|
19346
|
+
// Ensure scroll position hasn't changed
|
|
19347
|
+
setTimeout(function () {
|
|
19348
|
+
var newScrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
19349
|
+
if (newScrollTop !== currentScrollTop) {
|
|
19350
|
+
window.scrollTo(0, currentScrollTop);
|
|
19351
|
+
}
|
|
19352
|
+
}, 10);
|
|
19333
19353
|
} else {
|
|
19334
19354
|
console.log("❌ EquationEditor ref not found");
|
|
19335
19355
|
}
|
|
19336
19356
|
});
|
|
19337
19357
|
_this.state = {
|
|
19338
|
-
useExpertMode: GLOBAL_lastSelectedExpertMode
|
|
19358
|
+
useExpertMode: GLOBAL_lastSelectedExpertMode,
|
|
19359
|
+
animationReady: false
|
|
19339
19360
|
};
|
|
19340
19361
|
_this.handleCloseCallback = props.handleClose;
|
|
19341
19362
|
_this.handleInsertCallback = props.handleInsert;
|
|
@@ -19346,20 +19367,117 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19346
19367
|
key: "componentDidMount",
|
|
19347
19368
|
value: function componentDidMount() {
|
|
19348
19369
|
var _this2 = this;
|
|
19349
|
-
//
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19370
|
+
// Store current scroll position to prevent jumping
|
|
19371
|
+
this.originalScrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
19372
|
+
|
|
19373
|
+
// Create portal container if it doesn't exist
|
|
19374
|
+
this.ensurePortalContainer();
|
|
19375
|
+
|
|
19376
|
+
// Lock body scroll to prevent jumping in transform containers
|
|
19377
|
+
this.lockBodyScroll();
|
|
19378
|
+
|
|
19379
|
+
// Enable animation after portal is ready (ensures smooth slide-in)
|
|
19380
|
+
// Need multiple RAF frames for proper CSS animation timing
|
|
19381
|
+
requestAnimationFrame(function () {
|
|
19382
|
+
requestAnimationFrame(function () {
|
|
19383
|
+
_this2.setState({
|
|
19384
|
+
animationReady: true
|
|
19385
|
+
}, function () {
|
|
19386
|
+
// Auto-focus after animation completes (0.3s CSS animation + buffer)
|
|
19387
|
+
setTimeout(function () {
|
|
19388
|
+
_this2.focusEquationEditor();
|
|
19389
|
+
}, 400); // Wait for animation to complete
|
|
19390
|
+
});
|
|
19391
|
+
});
|
|
19392
|
+
});
|
|
19393
|
+
}
|
|
19394
|
+
}, {
|
|
19395
|
+
key: "componentWillUnmount",
|
|
19396
|
+
value: function componentWillUnmount() {
|
|
19397
|
+
var _this3 = this;
|
|
19398
|
+
// Hide portal immediately to prevent flash
|
|
19399
|
+
if (this.portalContainer) {
|
|
19400
|
+
this.portalContainer.style.visibility = "hidden";
|
|
19401
|
+
}
|
|
19402
|
+
|
|
19403
|
+
// Unlock body scroll and restore original scroll position
|
|
19404
|
+
this.unlockBodyScroll();
|
|
19405
|
+
|
|
19406
|
+
// Clean up portal container after a small delay
|
|
19407
|
+
if (this.createdPortalContainer && this.portalContainer) {
|
|
19408
|
+
setTimeout(function () {
|
|
19409
|
+
if (_this3.portalContainer && _this3.portalContainer.parentNode) {
|
|
19410
|
+
document.body.removeChild(_this3.portalContainer);
|
|
19411
|
+
}
|
|
19412
|
+
}, 100);
|
|
19413
|
+
}
|
|
19414
|
+
}
|
|
19415
|
+
}, {
|
|
19416
|
+
key: "lockBodyScroll",
|
|
19417
|
+
value: function lockBodyScroll() {
|
|
19418
|
+
// Store original overflow styles and scroll position
|
|
19419
|
+
this.originalBodyOverflow = document.body.style.overflow;
|
|
19420
|
+
this.originalDocumentOverflow = document.documentElement.style.overflow;
|
|
19421
|
+
this.originalBodyPosition = document.body.style.position;
|
|
19422
|
+
this.originalBodyTop = document.body.style.top;
|
|
19423
|
+
this.originalBodyWidth = document.body.style.width;
|
|
19424
|
+
|
|
19425
|
+
// Get current scroll position
|
|
19426
|
+
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
19427
|
+
|
|
19428
|
+
// Apply position: fixed to prevent scrolling while preserving position
|
|
19429
|
+
document.body.style.position = "fixed";
|
|
19430
|
+
document.body.style.top = "-".concat(scrollTop, "px");
|
|
19431
|
+
document.body.style.width = "100%";
|
|
19432
|
+
document.body.style.overflow = "hidden";
|
|
19433
|
+
}
|
|
19434
|
+
}, {
|
|
19435
|
+
key: "unlockBodyScroll",
|
|
19436
|
+
value: function unlockBodyScroll() {
|
|
19437
|
+
// Get the scroll position from the fixed top value
|
|
19438
|
+
var scrollTop = Math.abs(parseInt(document.body.style.top) || 0);
|
|
19439
|
+
|
|
19440
|
+
// Restore original styles
|
|
19441
|
+
document.body.style.position = this.originalBodyPosition || "";
|
|
19442
|
+
document.body.style.top = this.originalBodyTop || "";
|
|
19443
|
+
document.body.style.width = this.originalBodyWidth || "";
|
|
19444
|
+
document.body.style.overflow = this.originalBodyOverflow || "";
|
|
19445
|
+
document.documentElement.style.overflow = this.originalDocumentOverflow || "";
|
|
19446
|
+
|
|
19447
|
+
// Restore scroll position smoothly
|
|
19448
|
+
if (scrollTop > 0) {
|
|
19449
|
+
window.scrollTo(0, scrollTop);
|
|
19450
|
+
}
|
|
19451
|
+
}
|
|
19452
|
+
}, {
|
|
19453
|
+
key: "ensurePortalContainer",
|
|
19454
|
+
value: function ensurePortalContainer() {
|
|
19455
|
+
// Look for existing portal container
|
|
19456
|
+
this.portalContainer = document.getElementById("math-rich-input-modal-portal");
|
|
19457
|
+
if (!this.portalContainer) {
|
|
19458
|
+
// Create new portal container
|
|
19459
|
+
this.portalContainer = document.createElement("div");
|
|
19460
|
+
this.portalContainer.id = "math-rich-input-modal-portal";
|
|
19461
|
+
// Portal container should not interfere with content positioning
|
|
19462
|
+
// Start invisible until animation is ready
|
|
19463
|
+
this.portalContainer.style.cssText = "position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 999990; visibility: hidden;";
|
|
19464
|
+
document.body.appendChild(this.portalContainer);
|
|
19465
|
+
this.createdPortalContainer = true;
|
|
19466
|
+
}
|
|
19354
19467
|
}
|
|
19355
19468
|
}, {
|
|
19356
19469
|
key: "componentDidUpdate",
|
|
19357
19470
|
value: function componentDidUpdate(prevProps, prevState) {
|
|
19358
|
-
var
|
|
19471
|
+
var _this4 = this;
|
|
19472
|
+
// Show portal container when animation is ready
|
|
19473
|
+
if (!prevState.animationReady && this.state.animationReady && this.portalContainer) {
|
|
19474
|
+
this.portalContainer.style.visibility = "visible";
|
|
19475
|
+
}
|
|
19476
|
+
|
|
19359
19477
|
// Re-focus when expert mode changes
|
|
19360
19478
|
if (prevState.useExpertMode !== this.state.useExpertMode) {
|
|
19361
19479
|
setTimeout(function () {
|
|
19362
|
-
|
|
19480
|
+
_this4.focusEquationEditor();
|
|
19363
19481
|
}, 100);
|
|
19364
19482
|
}
|
|
19365
19483
|
}
|
|
@@ -19379,16 +19497,27 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19379
19497
|
}, {
|
|
19380
19498
|
key: "render",
|
|
19381
19499
|
value: function render() {
|
|
19382
|
-
var
|
|
19500
|
+
var _this5 = this;
|
|
19383
19501
|
var useClass = "EquationEditorModal";
|
|
19384
19502
|
if (this.isMobile()) useClass = "EquationEditorModal-mobile";
|
|
19385
|
-
|
|
19386
|
-
|
|
19387
|
-
|
|
19503
|
+
|
|
19504
|
+
// Add support for disabling animations (useful for Svelte transitions)
|
|
19505
|
+
if (this.props.disableAnimation) {
|
|
19506
|
+
useClass += " no-animation";
|
|
19507
|
+
}
|
|
19508
|
+
var modalContent = /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement("div", {
|
|
19509
|
+
className: "EquationEditorModal-background".concat(this.props.disableAnimation ? " no-animation" : ""),
|
|
19510
|
+
onClick: this.handleClose,
|
|
19511
|
+
style: {
|
|
19512
|
+
pointerEvents: "auto"
|
|
19513
|
+
}
|
|
19388
19514
|
}), /*#__PURE__*/React__default["default"].createElement("div", {
|
|
19389
19515
|
className: useClass,
|
|
19390
19516
|
ref: function ref(r) {
|
|
19391
|
-
return
|
|
19517
|
+
return _this5.modalDiv = r;
|
|
19518
|
+
},
|
|
19519
|
+
style: {
|
|
19520
|
+
pointerEvents: "auto"
|
|
19392
19521
|
}
|
|
19393
19522
|
}, !this.isMobile() && /*#__PURE__*/React__default["default"].createElement("div", {
|
|
19394
19523
|
className: "title"
|
|
@@ -19399,23 +19528,31 @@ var EquationEditorModal = /*#__PURE__*/function (_React$Component) {
|
|
|
19399
19528
|
}, /*#__PURE__*/React__default["default"].createElement("input", {
|
|
19400
19529
|
type: "checkbox",
|
|
19401
19530
|
ref: function ref(r) {
|
|
19402
|
-
return
|
|
19531
|
+
return _this5.expertModeSwitch = r;
|
|
19403
19532
|
},
|
|
19404
19533
|
onChange: function onChange(e) {
|
|
19405
|
-
return
|
|
19534
|
+
return _this5.handleExpertModeSwitchChange(e);
|
|
19406
19535
|
},
|
|
19407
19536
|
checked: this.state.useExpertMode
|
|
19408
19537
|
}), /*#__PURE__*/React__default["default"].createElement("span", {
|
|
19409
19538
|
className: "slider round"
|
|
19410
19539
|
})))), /*#__PURE__*/React__default["default"].createElement(EquationEditor, {
|
|
19411
19540
|
ref: function ref(r) {
|
|
19412
|
-
return
|
|
19541
|
+
return _this5.equationEditor = r;
|
|
19413
19542
|
},
|
|
19414
19543
|
latex: this.props.latex,
|
|
19415
19544
|
useExpertMode: this.state.useExpertMode,
|
|
19416
19545
|
handleInsert: this.handleInsert,
|
|
19417
19546
|
handleCancel: this.handleClose
|
|
19418
19547
|
})));
|
|
19548
|
+
|
|
19549
|
+
// Use portal to render modal outside of parent container stacking context
|
|
19550
|
+
if (this.portalContainer && this.state.animationReady) {
|
|
19551
|
+
return /*#__PURE__*/ReactDOM__default["default"].createPortal(modalContent, this.portalContainer);
|
|
19552
|
+
}
|
|
19553
|
+
|
|
19554
|
+
// Show nothing until portal and animation are ready (prevents flash)
|
|
19555
|
+
return null;
|
|
19419
19556
|
}
|
|
19420
19557
|
}]);
|
|
19421
19558
|
}(React__default["default"].Component);
|
|
@@ -20146,9 +20283,6 @@ var Toolbar = /*#__PURE__*/function (_React$Component) {
|
|
|
20146
20283
|
var _this;
|
|
20147
20284
|
_classCallCheck(this, Toolbar);
|
|
20148
20285
|
_this = _callSuper(this, Toolbar, [props]);
|
|
20149
|
-
_defineProperty(_this, "handleButtonClick", function (event, buttonName) {
|
|
20150
|
-
_this.suppliedClickHandler(event, buttonName);
|
|
20151
|
-
});
|
|
20152
20286
|
_defineProperty(_this, "showAccentBar", function (event) {
|
|
20153
20287
|
if (!_this.state.showAccents) _this.accentLetter = _this.suppliedAccentLetterFetcher();
|
|
20154
20288
|
_this.setState({
|
|
@@ -20168,6 +20302,8 @@ var Toolbar = /*#__PURE__*/function (_React$Component) {
|
|
|
20168
20302
|
});
|
|
20169
20303
|
});
|
|
20170
20304
|
_defineProperty(_this, "handleButtonClick", function (event, buttonName) {
|
|
20305
|
+
event.preventDefault();
|
|
20306
|
+
event.stopPropagation();
|
|
20171
20307
|
_this.suppliedClickHandler(event, buttonName);
|
|
20172
20308
|
});
|
|
20173
20309
|
_defineProperty(_this, "handleAccentButtonClick", function (event, oldCharacter, newCharacter) {
|
|
@@ -20342,6 +20478,9 @@ var Toolbar = /*#__PURE__*/function (_React$Component) {
|
|
|
20342
20478
|
}, "\xE1"), enableMath && /*#__PURE__*/React__default["default"].createElement("button", {
|
|
20343
20479
|
name: "Equation",
|
|
20344
20480
|
className: "Toolbar-button TB-wide",
|
|
20481
|
+
onClick: function onClick(e) {
|
|
20482
|
+
return e.preventDefault();
|
|
20483
|
+
},
|
|
20345
20484
|
onMouseDown: function onMouseDown(e) {
|
|
20346
20485
|
return _this2.handleButtonClick(e, "Equation");
|
|
20347
20486
|
}
|
|
@@ -20531,6 +20670,73 @@ function determineMimeType(text) {
|
|
|
20531
20670
|
{this.test("$a bcd> e$", "application/x-tex")}
|
|
20532
20671
|
*/
|
|
20533
20672
|
|
|
20673
|
+
var DEBUG_MATH_RICH_INPUT = false;
|
|
20674
|
+
function getNodePath(node) {
|
|
20675
|
+
var root = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
20676
|
+
if (!node) return null;
|
|
20677
|
+
var parts = [];
|
|
20678
|
+
var current = node;
|
|
20679
|
+
while (current && current !== root && parts.length < 8) {
|
|
20680
|
+
if (current.nodeType === 3) {
|
|
20681
|
+
parts.unshift("#text(\"".concat(current.nodeValue, "\")"));
|
|
20682
|
+
} else {
|
|
20683
|
+
var name = current.nodeName ? current.nodeName.toLowerCase() : "unknown";
|
|
20684
|
+
var className = current.className && typeof current.className === "string" ? ".".concat(current.className.split(" ").filter(Boolean).join(".")) : "";
|
|
20685
|
+
parts.unshift("".concat(name).concat(className));
|
|
20686
|
+
}
|
|
20687
|
+
current = current.parentNode;
|
|
20688
|
+
}
|
|
20689
|
+
if (root) parts.unshift("root");
|
|
20690
|
+
return parts.join(" > ");
|
|
20691
|
+
}
|
|
20692
|
+
function describeNode(node) {
|
|
20693
|
+
var root = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
20694
|
+
if (!node) return null;
|
|
20695
|
+
return {
|
|
20696
|
+
nodeName: node.nodeName,
|
|
20697
|
+
nodeType: node.nodeType,
|
|
20698
|
+
text: node.nodeType === 3 && typeof node.nodeValue === "string" ? node.nodeValue : undefined,
|
|
20699
|
+
textLength: node.nodeType === 3 && typeof node.nodeValue === "string" ? node.nodeValue.length : undefined,
|
|
20700
|
+
childCount: node.childNodes ? node.childNodes.length : undefined,
|
|
20701
|
+
path: getNodePath(node, root)
|
|
20702
|
+
};
|
|
20703
|
+
}
|
|
20704
|
+
function getSelectionSnapshot() {
|
|
20705
|
+
var editableDiv = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
20706
|
+
if (typeof window === "undefined" || !window.getSelection) return null;
|
|
20707
|
+
var selection = window.getSelection();
|
|
20708
|
+
if (!selection) return null;
|
|
20709
|
+
var snapshot = {
|
|
20710
|
+
activeElement: typeof document !== "undefined" && document.activeElement ? {
|
|
20711
|
+
nodeName: document.activeElement.nodeName,
|
|
20712
|
+
className: document.activeElement.className
|
|
20713
|
+
} : null,
|
|
20714
|
+
rangeCount: selection.rangeCount,
|
|
20715
|
+
isCollapsed: selection.isCollapsed,
|
|
20716
|
+
anchorOffset: selection.anchorOffset,
|
|
20717
|
+
focusOffset: selection.focusOffset,
|
|
20718
|
+
anchorNode: describeNode(selection.anchorNode, editableDiv),
|
|
20719
|
+
focusNode: describeNode(selection.focusNode, editableDiv)
|
|
20720
|
+
};
|
|
20721
|
+
if (selection.rangeCount > 0) {
|
|
20722
|
+
var range = selection.getRangeAt(0);
|
|
20723
|
+
snapshot.range = {
|
|
20724
|
+
collapsed: range.collapsed,
|
|
20725
|
+
startOffset: range.startOffset,
|
|
20726
|
+
endOffset: range.endOffset,
|
|
20727
|
+
startContainer: describeNode(range.startContainer, editableDiv),
|
|
20728
|
+
endContainer: describeNode(range.endContainer, editableDiv)
|
|
20729
|
+
};
|
|
20730
|
+
}
|
|
20731
|
+
return snapshot;
|
|
20732
|
+
}
|
|
20733
|
+
function debugMathRichInput(label) {
|
|
20734
|
+
return;
|
|
20735
|
+
}
|
|
20736
|
+
if (typeof window !== "undefined") {
|
|
20737
|
+
window.__MRI_DEBUG__ = DEBUG_MATH_RICH_INPUT;
|
|
20738
|
+
}
|
|
20739
|
+
|
|
20534
20740
|
var RAW_TEXT_MATH_START_TAG_TEX = "\\[";
|
|
20535
20741
|
var RAW_TEXT_MATH_END_TAG_TEX = "\\]";
|
|
20536
20742
|
var RAW_TEXT_MATH_START_TAG_HTML_MATH = "<math>";
|
|
@@ -21172,6 +21378,55 @@ function findFirstTextNode(node) {
|
|
|
21172
21378
|
}
|
|
21173
21379
|
return null;
|
|
21174
21380
|
}
|
|
21381
|
+
function findLastTextNode(node) {
|
|
21382
|
+
if (isTextNode(node)) return node;
|
|
21383
|
+
var nodes = node.childNodes;
|
|
21384
|
+
for (var i = nodes.length - 1; i >= 0; i--) {
|
|
21385
|
+
var found_node = findLastTextNode(nodes[i]);
|
|
21386
|
+
if (found_node !== null) return found_node;
|
|
21387
|
+
}
|
|
21388
|
+
return null;
|
|
21389
|
+
}
|
|
21390
|
+
function getTextPositionFromElementRangeEndpoint(container, offset) {
|
|
21391
|
+
if (isTextNode(container)) return {
|
|
21392
|
+
node: container,
|
|
21393
|
+
offset: offset
|
|
21394
|
+
};
|
|
21395
|
+
var nodes = container.childNodes;
|
|
21396
|
+
if (nodes === null || nodes === undefined || nodes.length === 0) return null;
|
|
21397
|
+
|
|
21398
|
+
// A collapsed selection inside contentEditable may report the editable SPAN
|
|
21399
|
+
// itself as the container and the child index as the offset. The previous
|
|
21400
|
+
// implementation always picked the first descendant text node, which moved
|
|
21401
|
+
// the caret to the beginning after React re-rendered the controlled input.
|
|
21402
|
+
if (offset > 0) {
|
|
21403
|
+
var previousChild = nodes[Math.min(offset - 1, nodes.length - 1)];
|
|
21404
|
+
var previousTextNode = findLastTextNode(previousChild);
|
|
21405
|
+
if (previousTextNode !== null) {
|
|
21406
|
+
return {
|
|
21407
|
+
node: previousTextNode,
|
|
21408
|
+
offset: previousTextNode.nodeValue.length
|
|
21409
|
+
};
|
|
21410
|
+
}
|
|
21411
|
+
}
|
|
21412
|
+
if (offset < nodes.length) {
|
|
21413
|
+
var nextTextNode = findFirstTextNode(nodes[offset]);
|
|
21414
|
+
if (nextTextNode !== null) {
|
|
21415
|
+
return {
|
|
21416
|
+
node: nextTextNode,
|
|
21417
|
+
offset: 0
|
|
21418
|
+
};
|
|
21419
|
+
}
|
|
21420
|
+
}
|
|
21421
|
+
var fallbackTextNode = findFirstTextNode(container);
|
|
21422
|
+
if (fallbackTextNode !== null) {
|
|
21423
|
+
return {
|
|
21424
|
+
node: fallbackTextNode,
|
|
21425
|
+
offset: 0
|
|
21426
|
+
};
|
|
21427
|
+
}
|
|
21428
|
+
return null;
|
|
21429
|
+
}
|
|
21175
21430
|
function findNodeAndOffsetForGlobalOffsetInEditableDiv(editableDiv, globalOffset) {
|
|
21176
21431
|
var result = {
|
|
21177
21432
|
offset: 0
|
|
@@ -21213,6 +21468,10 @@ function findNodeAndOffsetForGlobalOffsetInEditableDiv(editableDiv, globalOffset
|
|
|
21213
21468
|
function getRangeParams(editableDiv) {
|
|
21214
21469
|
// console.log ("getRangeParams")
|
|
21215
21470
|
// console.log("Inner html: "+editableDiv.innerHTML)
|
|
21471
|
+
debugMathRichInput("getRangeParams:start", {
|
|
21472
|
+
innerHTML: editableDiv ? editableDiv.innerHTML : null,
|
|
21473
|
+
selection: getSelectionSnapshot(editableDiv)
|
|
21474
|
+
});
|
|
21216
21475
|
var isSupported = typeof window.getSelection !== "undefined";
|
|
21217
21476
|
if (!isSupported) {
|
|
21218
21477
|
console.error("Can't get range params, browser does not support window.getSelection");
|
|
@@ -21224,15 +21483,27 @@ function getRangeParams(editableDiv) {
|
|
|
21224
21483
|
return null;
|
|
21225
21484
|
}
|
|
21226
21485
|
var range = selection.getRangeAt(0);
|
|
21486
|
+
debugMathRichInput("getRangeParams:range-before-normalize", {
|
|
21487
|
+
startContainer: describeNode(range.startContainer, editableDiv),
|
|
21488
|
+
startOffset: range.startOffset,
|
|
21489
|
+
endContainer: describeNode(range.endContainer, editableDiv),
|
|
21490
|
+
endOffset: range.endOffset
|
|
21491
|
+
});
|
|
21227
21492
|
|
|
21228
21493
|
// logAllDescendants(editableDiv)
|
|
21229
|
-
// If the range is not within a text node, move it to
|
|
21230
|
-
//
|
|
21494
|
+
// If the range is not within a text node, move it to the text node implied
|
|
21495
|
+
// by the element-container offset. This typically happens when the browser
|
|
21496
|
+
// reports a collapsed contentEditable selection as (SPAN, childIndex).
|
|
21231
21497
|
if (range.startContainer.nodeType !== 3) {
|
|
21232
|
-
var
|
|
21233
|
-
if (
|
|
21234
|
-
|
|
21235
|
-
|
|
21498
|
+
var textPosition = getTextPositionFromElementRangeEndpoint(range.startContainer, range.startOffset);
|
|
21499
|
+
if (textPosition !== null) {
|
|
21500
|
+
debugMathRichInput("getRangeParams:normalize-start-element", {
|
|
21501
|
+
from: describeNode(range.startContainer, editableDiv),
|
|
21502
|
+
fromOffset: range.startOffset,
|
|
21503
|
+
to: describeNode(textPosition.node, editableDiv),
|
|
21504
|
+
toOffset: textPosition.offset
|
|
21505
|
+
});
|
|
21506
|
+
range.setStart(textPosition.node, textPosition.offset);
|
|
21236
21507
|
} else {
|
|
21237
21508
|
// Handle empty content case - return default range params
|
|
21238
21509
|
// This is normal behavior after selecting all and deleting content
|
|
@@ -21248,10 +21519,15 @@ function getRangeParams(editableDiv) {
|
|
|
21248
21519
|
}
|
|
21249
21520
|
}
|
|
21250
21521
|
if (range.endContainer.nodeType !== 3) {
|
|
21251
|
-
var
|
|
21252
|
-
if (
|
|
21253
|
-
|
|
21254
|
-
|
|
21522
|
+
var _textPosition = getTextPositionFromElementRangeEndpoint(range.endContainer, range.endOffset);
|
|
21523
|
+
if (_textPosition !== null) {
|
|
21524
|
+
debugMathRichInput("getRangeParams:normalize-end-element", {
|
|
21525
|
+
from: describeNode(range.endContainer, editableDiv),
|
|
21526
|
+
fromOffset: range.endOffset,
|
|
21527
|
+
to: describeNode(_textPosition.node, editableDiv),
|
|
21528
|
+
toOffset: _textPosition.offset
|
|
21529
|
+
});
|
|
21530
|
+
range.setEnd(_textPosition.node, _textPosition.offset);
|
|
21255
21531
|
} else {
|
|
21256
21532
|
// Handle empty content case - return default range params
|
|
21257
21533
|
// This is normal behavior after selecting all and deleting content
|
|
@@ -21297,11 +21573,20 @@ function getRangeParams(editableDiv) {
|
|
|
21297
21573
|
startGlobalOffset: startResult.offset,
|
|
21298
21574
|
endGlobalOffset: endResult.offset
|
|
21299
21575
|
};
|
|
21576
|
+
debugMathRichInput("getRangeParams:result", {
|
|
21577
|
+
rangeParams: rangeParams,
|
|
21578
|
+
selection: getSelectionSnapshot(editableDiv)
|
|
21579
|
+
});
|
|
21300
21580
|
return rangeParams;
|
|
21301
21581
|
}
|
|
21302
21582
|
function setRangeParamsFromGlobalOffsets(editableDiv, params) {
|
|
21303
21583
|
var new_range = null;
|
|
21304
21584
|
try {
|
|
21585
|
+
debugMathRichInput("setRangeParamsFromGlobalOffsets:start", {
|
|
21586
|
+
params: params,
|
|
21587
|
+
innerHTML: editableDiv ? editableDiv.innerHTML : null,
|
|
21588
|
+
selectionBefore: getSelectionSnapshot(editableDiv)
|
|
21589
|
+
});
|
|
21305
21590
|
if (params === null || params === undefined) throw new Error("Can't set range params: params === " + params);
|
|
21306
21591
|
var startResult = findNodeAndOffsetForGlobalOffsetInEditableDiv(editableDiv, params.startGlobalOffset);
|
|
21307
21592
|
var endResult = findNodeAndOffsetForGlobalOffsetInEditableDiv(editableDiv, params.endGlobalOffset);
|
|
@@ -21321,6 +21606,18 @@ function setRangeParamsFromGlobalOffsets(editableDiv, params) {
|
|
|
21321
21606
|
var selection = window.getSelection();
|
|
21322
21607
|
selection.removeAllRanges();
|
|
21323
21608
|
selection.addRange(new_range);
|
|
21609
|
+
debugMathRichInput("setRangeParamsFromGlobalOffsets:after", {
|
|
21610
|
+
params: params,
|
|
21611
|
+
startResult: {
|
|
21612
|
+
node: describeNode(startResult.node, editableDiv),
|
|
21613
|
+
offset: startResult.offset
|
|
21614
|
+
},
|
|
21615
|
+
endResult: {
|
|
21616
|
+
node: describeNode(endResult.node, editableDiv),
|
|
21617
|
+
offset: endResult.offset
|
|
21618
|
+
},
|
|
21619
|
+
selectionAfter: getSelectionSnapshot(editableDiv)
|
|
21620
|
+
});
|
|
21324
21621
|
} catch (error) {
|
|
21325
21622
|
console.error(error);
|
|
21326
21623
|
console.log("Trying to set range:");
|
|
@@ -21334,6 +21631,11 @@ function setRangeParams(editableDiv, params) {
|
|
|
21334
21631
|
|
|
21335
21632
|
var new_range = null;
|
|
21336
21633
|
try {
|
|
21634
|
+
debugMathRichInput("setRangeParams:start", {
|
|
21635
|
+
params: params,
|
|
21636
|
+
innerHTML: editableDiv ? editableDiv.innerHTML : null,
|
|
21637
|
+
selectionBefore: getSelectionSnapshot(editableDiv)
|
|
21638
|
+
});
|
|
21337
21639
|
if (params === null || params === undefined) {
|
|
21338
21640
|
console.error("Can't set range params: params === " + params);
|
|
21339
21641
|
return;
|
|
@@ -21393,6 +21695,7 @@ function setRangeParams(editableDiv, params) {
|
|
|
21393
21695
|
startNode = findFirstTextNode(editableDiv);
|
|
21394
21696
|
startOffset = 0;
|
|
21395
21697
|
}
|
|
21698
|
+
if (startNode === null) return;
|
|
21396
21699
|
if (!isTextNode(startNode)) {
|
|
21397
21700
|
console.warn("Start node found for range start is not a text a node");
|
|
21398
21701
|
console.log(editableDiv.childNodes);
|
|
@@ -21408,6 +21711,7 @@ function setRangeParams(editableDiv, params) {
|
|
|
21408
21711
|
endNode = findFirstTextNode(editableDiv);
|
|
21409
21712
|
endOffset = 0;
|
|
21410
21713
|
}
|
|
21714
|
+
if (endNode === null) return;
|
|
21411
21715
|
if (!isTextNode(endNode)) {
|
|
21412
21716
|
console.warn("End node found for range start is not a text a node");
|
|
21413
21717
|
console.log(editableDiv.childNodes);
|
|
@@ -21420,7 +21724,7 @@ function setRangeParams(editableDiv, params) {
|
|
|
21420
21724
|
}
|
|
21421
21725
|
new_range = document.createRange();
|
|
21422
21726
|
if (startOffset > startNode.nodeValue.length) {
|
|
21423
|
-
console.warn("endOffset > endNode.nodeValue.length when setting range: " + startOffset + " > " + startNode.nodeValue.length + " - " +
|
|
21727
|
+
console.warn("endOffset > endNode.nodeValue.length when setting range: " + startOffset + " > " + startNode.nodeValue.length + " - " + startNode.nodeType + " - " + startNode.nodeValue);
|
|
21424
21728
|
startOffset = startNode.nodeValue.length;
|
|
21425
21729
|
}
|
|
21426
21730
|
new_range.setStart(startNode, startOffset);
|
|
@@ -21435,6 +21739,14 @@ function setRangeParams(editableDiv, params) {
|
|
|
21435
21739
|
var selection = window.getSelection();
|
|
21436
21740
|
selection.removeAllRanges();
|
|
21437
21741
|
selection.addRange(new_range);
|
|
21742
|
+
debugMathRichInput("setRangeParams:after", {
|
|
21743
|
+
params: params,
|
|
21744
|
+
startNode: describeNode(startNode, editableDiv),
|
|
21745
|
+
startOffset: startOffset,
|
|
21746
|
+
endNode: describeNode(endNode, editableDiv),
|
|
21747
|
+
endOffset: endOffset,
|
|
21748
|
+
selectionAfter: getSelectionSnapshot(editableDiv)
|
|
21749
|
+
});
|
|
21438
21750
|
} catch (error) {
|
|
21439
21751
|
console.error(error);
|
|
21440
21752
|
console.log("Trying to set range:");
|
|
@@ -21661,6 +21973,29 @@ var SMALL_SPACE_LENGTH = SMALL_SPACE.length;
|
|
|
21661
21973
|
// const SMALL_SPACE_REG_EXP = new RegExp(SMALL_SPACE, "g")
|
|
21662
21974
|
|
|
21663
21975
|
var MARK = getMark();
|
|
21976
|
+
var INLINE_STYLE_COMMANDS = {
|
|
21977
|
+
bold: "bold",
|
|
21978
|
+
italic: "italic",
|
|
21979
|
+
underline: "underline",
|
|
21980
|
+
subscript: "subscript",
|
|
21981
|
+
superscript: "superscript"
|
|
21982
|
+
};
|
|
21983
|
+
var INLINE_STYLE_TAGS = {
|
|
21984
|
+
bold: ["b", "strong"],
|
|
21985
|
+
italic: ["i", "em"],
|
|
21986
|
+
underline: ["u"],
|
|
21987
|
+
subscript: ["sub"],
|
|
21988
|
+
superscript: ["sup"]
|
|
21989
|
+
};
|
|
21990
|
+
var INLINE_STYLE_TAG_NAMES = ["b", "strong", "i", "em", "u", "sub", "sup"];
|
|
21991
|
+
var INLINE_STYLE_WRAPPER_TAGS = {
|
|
21992
|
+
bold: "strong",
|
|
21993
|
+
italic: "em",
|
|
21994
|
+
underline: "u",
|
|
21995
|
+
subscript: "sub",
|
|
21996
|
+
superscript: "sup"
|
|
21997
|
+
};
|
|
21998
|
+
var EMPTY_INLINE_FORMATTING_REG_EXP = /<(B|STRONG|I|EM|U|SUB|SUP)>(?:\s| |\u00a0|\u200b|\ufeff)*<\/\1>/gi;
|
|
21664
21999
|
|
|
21665
22000
|
// const LATEX_MARKER_START = "<annotation encoding=\"application/x-tex\">"
|
|
21666
22001
|
// const LATEX_MARKER_END = "</annotation>"
|
|
@@ -21802,12 +22137,34 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
21802
22137
|
return countNodeTypes(_this2.editableDiv);
|
|
21803
22138
|
});
|
|
21804
22139
|
_defineProperty(_this2, "applyChangesToComponent", function (value, mimeType, rangeParams, isExpertMode, selectedTab) {
|
|
22140
|
+
var applyOptions = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
|
|
21805
22141
|
// rangeParams, isExpertMode and selectedTab can be null, in which case we will set them
|
|
21806
22142
|
if (rangeParams === null) rangeParams = _this2.lastSetRangeParams;
|
|
21807
|
-
|
|
22143
|
+
debugMathRichInput("applyChangesToComponent:start", {
|
|
22144
|
+
value: value,
|
|
22145
|
+
mimeType: mimeType,
|
|
21808
22146
|
rangeParams: rangeParams,
|
|
21809
|
-
|
|
21810
|
-
|
|
22147
|
+
propsValue: _this2.props.value,
|
|
22148
|
+
propsMimeType: _this2.props.mimeType,
|
|
22149
|
+
innerHTML: _this2.editableDiv ? _this2.editableDiv.innerHTML : null,
|
|
22150
|
+
selection: getSelectionSnapshot(_this2.editableDiv),
|
|
22151
|
+
skipControlledRender: applyOptions.skipControlledRender === true
|
|
22152
|
+
});
|
|
22153
|
+
if (applyOptions.skipControlledRender === true) {
|
|
22154
|
+
// Native contenteditable input has already mutated the DOM and kept the
|
|
22155
|
+
// browser selection in the right place. Re-rendering the same value via
|
|
22156
|
+
// dangerouslySetInnerHTML can replace text nodes under React 19 and move
|
|
22157
|
+
// the caret to the beginning. Programmatic edits still use the normal
|
|
22158
|
+
// render-and-restore path.
|
|
22159
|
+
_this2.skipNextControlledValueRender = true;
|
|
22160
|
+
_this2.skipNextControlledValue = value;
|
|
22161
|
+
_this2.afterComponentUpdateData = null;
|
|
22162
|
+
} else {
|
|
22163
|
+
_this2.afterComponentUpdateData = {
|
|
22164
|
+
rangeParams: rangeParams,
|
|
22165
|
+
value: value
|
|
22166
|
+
};
|
|
22167
|
+
}
|
|
21811
22168
|
var options = _this2.props.options || DEFAULT_OPTIONS;
|
|
21812
22169
|
if (isExpertMode === null) isExpertMode = options.isExpertMode;
|
|
21813
22170
|
if (selectedTab === null) selectedTab = options.selectedTab;
|
|
@@ -21831,6 +22188,10 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
21831
22188
|
isExpertMode: isExpertMode,
|
|
21832
22189
|
selectedTab: selectedTab
|
|
21833
22190
|
});
|
|
22191
|
+
debugMathRichInput("applyChangesToComponent:after-onChange", {
|
|
22192
|
+
afterComponentUpdateData: _this2.afterComponentUpdateData,
|
|
22193
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
22194
|
+
});
|
|
21834
22195
|
});
|
|
21835
22196
|
_defineProperty(_this2, "initialiseHistory", function () {
|
|
21836
22197
|
if (_this2.initialHistoryState == null) _this2.initialHistoryState = {
|
|
@@ -21874,14 +22235,43 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
21874
22235
|
});
|
|
21875
22236
|
_defineProperty(_this2, "_setRangeParams", function (params) {
|
|
21876
22237
|
try {
|
|
22238
|
+
debugMathRichInput("MathRichInput:_setRangeParams:start", {
|
|
22239
|
+
params: params,
|
|
22240
|
+
selectionBefore: getSelectionSnapshot(_this2.editableDiv)
|
|
22241
|
+
});
|
|
21877
22242
|
setRangeParams(_this2.editableDiv, params);
|
|
21878
22243
|
_this2.setOldRangeParams(params);
|
|
21879
|
-
_this2.
|
|
22244
|
+
_this2.lastSetRangeParams = params;
|
|
22245
|
+
debugMathRichInput("MathRichInput:_setRangeParams:after", {
|
|
22246
|
+
params: params,
|
|
22247
|
+
oldRangeParams: _this2.oldRangeParams,
|
|
22248
|
+
selectionAfter: getSelectionSnapshot(_this2.editableDiv)
|
|
22249
|
+
});
|
|
21880
22250
|
} catch (error) {
|
|
21881
22251
|
console.error(error);
|
|
21882
22252
|
// console.log(this.editableDiv.childNodes);
|
|
21883
22253
|
}
|
|
21884
22254
|
});
|
|
22255
|
+
_defineProperty(_this2, "restoreRangeAfterBrowserWork", function (params, reason) {
|
|
22256
|
+
if (params === null || params === undefined) return;
|
|
22257
|
+
var restore = function restore(delay) {
|
|
22258
|
+
window.setTimeout(function () {
|
|
22259
|
+
if (_this2.state.showEquationEditor) return;
|
|
22260
|
+
if (!_this2.state.hasFocus && document.activeElement !== _this2.editableDiv) {
|
|
22261
|
+
return;
|
|
22262
|
+
}
|
|
22263
|
+
debugMathRichInput("restoreRangeAfterBrowserWork", {
|
|
22264
|
+
reason: reason,
|
|
22265
|
+
delay: delay,
|
|
22266
|
+
params: params,
|
|
22267
|
+
selectionBefore: getSelectionSnapshot(_this2.editableDiv)
|
|
22268
|
+
});
|
|
22269
|
+
_this2._setRangeParams(params);
|
|
22270
|
+
}, delay);
|
|
22271
|
+
};
|
|
22272
|
+
restore(0);
|
|
22273
|
+
restore(50);
|
|
22274
|
+
});
|
|
21885
22275
|
_defineProperty(_this2, "handleKeyDownBackspace", function (e) {
|
|
21886
22276
|
var rangeParams = _this2._getRangeParams();
|
|
21887
22277
|
var start_node_index = rangeParams.startNodeIndex;
|
|
@@ -22009,7 +22399,11 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22009
22399
|
_defineProperty(_this2, "isWordModifier", function (e) {
|
|
22010
22400
|
var _this2$getPlatformMod = _this2.getPlatformModifiers(),
|
|
22011
22401
|
isMac = _this2$getPlatformMod.isMac;
|
|
22012
|
-
|
|
22402
|
+
// Borough production is pinned to math-rich-input 0.1.48, where Option +
|
|
22403
|
+
// Arrow did not get custom word navigation. Keep Mac Option + Arrow as
|
|
22404
|
+
// normal character movement to preserve the editor's existing UX; Command +
|
|
22405
|
+
// Arrow is handled by isLineModifier below.
|
|
22406
|
+
return isMac ? false : e.ctrlKey;
|
|
22013
22407
|
});
|
|
22014
22408
|
// Check if line navigation modifier is pressed
|
|
22015
22409
|
_defineProperty(_this2, "isLineModifier", function (e) {
|
|
@@ -22466,6 +22860,17 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22466
22860
|
});
|
|
22467
22861
|
_defineProperty(_this2, "handleKeyDown", function (e) {
|
|
22468
22862
|
try {
|
|
22863
|
+
debugMathRichInput("handleKeyDown:start", {
|
|
22864
|
+
key: e.key,
|
|
22865
|
+
altKey: e.altKey,
|
|
22866
|
+
metaKey: e.metaKey,
|
|
22867
|
+
ctrlKey: e.ctrlKey,
|
|
22868
|
+
shiftKey: e.shiftKey,
|
|
22869
|
+
hasFocus: _this2.state.hasFocus,
|
|
22870
|
+
propsValue: _this2.props.value,
|
|
22871
|
+
innerHTML: _this2.editableDiv ? _this2.editableDiv.innerHTML : null,
|
|
22872
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
22873
|
+
});
|
|
22469
22874
|
// Lets set up or update the undo redo history
|
|
22470
22875
|
_this2.initialiseHistory();
|
|
22471
22876
|
if ((e.key === "z" || e.key === "Z") && (e.ctrlKey || e.metaKey)) {
|
|
@@ -22522,7 +22927,9 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22522
22927
|
}
|
|
22523
22928
|
}
|
|
22524
22929
|
}
|
|
22525
|
-
|
|
22930
|
+
var _this2$getPlatformMod3 = _this2.getPlatformModifiers(),
|
|
22931
|
+
isMac = _this2$getPlatformMod3.isMac;
|
|
22932
|
+
if (!isMac && e.altKey && e.key === "Alt") {
|
|
22526
22933
|
var key = _this2.fetchAccentLetter();
|
|
22527
22934
|
if (key === "a" || key === "e" || key === "i" || key === "o" || key === "u" || key === "c" || key === "l" || key === "n" || key === "s" || key === "?" || key === "!") {
|
|
22528
22935
|
// console.log("showing/hiding accent bar");
|
|
@@ -22539,9 +22946,11 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22539
22946
|
return;
|
|
22540
22947
|
}
|
|
22541
22948
|
_this2.keyPressed = e.key; // store for use in methods
|
|
22542
|
-
_this2.
|
|
22543
|
-
|
|
22544
|
-
|
|
22949
|
+
if (_this2.state.showAccentBar) {
|
|
22950
|
+
_this2.setState({
|
|
22951
|
+
keyPressed: e.key
|
|
22952
|
+
});
|
|
22953
|
+
}
|
|
22545
22954
|
|
|
22546
22955
|
// Hide the accent bar if a key is typed except when it is an automatic key repeat press
|
|
22547
22956
|
// If it is automatic key repeat, then keyPressStartTime will be greater than 0
|
|
@@ -22561,10 +22970,16 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22561
22970
|
}
|
|
22562
22971
|
if (e.key === "ArrowLeft") {
|
|
22563
22972
|
_this2.handleKeyDownArrowLeft(e);
|
|
22973
|
+
debugMathRichInput("handleKeyDown:after-arrow-left", {
|
|
22974
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
22975
|
+
});
|
|
22564
22976
|
return;
|
|
22565
22977
|
}
|
|
22566
22978
|
if (e.key === "ArrowRight") {
|
|
22567
22979
|
_this2.handleKeyDownArrowRight(e);
|
|
22980
|
+
debugMathRichInput("handleKeyDown:after-arrow-right", {
|
|
22981
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
22982
|
+
});
|
|
22568
22983
|
return;
|
|
22569
22984
|
}
|
|
22570
22985
|
if (e.key === "ArrowUp") {
|
|
@@ -22657,6 +23072,14 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22657
23072
|
});
|
|
22658
23073
|
_defineProperty(_this2, "handleKeyUp", function (e) {
|
|
22659
23074
|
try {
|
|
23075
|
+
debugMathRichInput("handleKeyUp:start", {
|
|
23076
|
+
key: e.key,
|
|
23077
|
+
altKey: e.altKey,
|
|
23078
|
+
metaKey: e.metaKey,
|
|
23079
|
+
ctrlKey: e.ctrlKey,
|
|
23080
|
+
shiftKey: e.shiftKey,
|
|
23081
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23082
|
+
});
|
|
22660
23083
|
_this2.keyPressed = e.key;
|
|
22661
23084
|
_this2.keyPressStartTime = -1;
|
|
22662
23085
|
|
|
@@ -22732,8 +23155,22 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22732
23155
|
try {
|
|
22733
23156
|
// console.log("handleInput")
|
|
22734
23157
|
if (_this2.isComposing) return;
|
|
23158
|
+
debugMathRichInput("handleInput:start", {
|
|
23159
|
+
inputType: event && event.nativeEvent ? event.nativeEvent.inputType : null,
|
|
23160
|
+
data: event && event.nativeEvent ? event.nativeEvent.data : null,
|
|
23161
|
+
propsValue: _this2.props.value,
|
|
23162
|
+
propsMimeType: _this2.props.mimeType,
|
|
23163
|
+
innerHTML: _this2.editableDiv ? _this2.editableDiv.innerHTML : null,
|
|
23164
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23165
|
+
});
|
|
23166
|
+
_this2.cleanupEmptyInlineFormattingElements();
|
|
22735
23167
|
var raw_text = elementToMarkedRawText(_this2.editableDiv, null, 0, _this2.enableHtml());
|
|
22736
23168
|
var params = _this2._getRangeParams();
|
|
23169
|
+
debugMathRichInput("handleInput:after-range", {
|
|
23170
|
+
raw_text: raw_text,
|
|
23171
|
+
params: params,
|
|
23172
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23173
|
+
});
|
|
22737
23174
|
if (params === null || params === undefined) {
|
|
22738
23175
|
// console.log(
|
|
22739
23176
|
// "handleInput: Empty content detected, using default range params"
|
|
@@ -22752,7 +23189,10 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22752
23189
|
var _mimeType = _this2.getMimeType(_nodeCounts.html > 0, _nodeCounts.math > 0);
|
|
22753
23190
|
var _raw_text = elementToMarkedRawText(_this2.editableDiv, null, 0, _this2.enableHtml());
|
|
22754
23191
|
_raw_text = removeEncodingIfPlainText(_raw_text, _mimeType, _this2.enableHtml());
|
|
22755
|
-
|
|
23192
|
+
_raw_text = _this2.stripEmptyInlineFormattingTags(_raw_text);
|
|
23193
|
+
_this2.applyChangesToComponent(_raw_text, _mimeType, defaultParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
|
|
23194
|
+
skipControlledRender: true
|
|
23195
|
+
});
|
|
22756
23196
|
return;
|
|
22757
23197
|
} else if (params.startNodeIndex === null || params.startNodeIndex === undefined) {
|
|
22758
23198
|
// console.log(
|
|
@@ -22773,6 +23213,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22773
23213
|
var hasMath = hasMathContent || nodeCounts.math > 0;
|
|
22774
23214
|
var mimeType = _this2.getMimeType(hasHtml, hasMath);
|
|
22775
23215
|
raw_text = removeEncodingIfPlainText(raw_text, mimeType, _this2.enableHtml());
|
|
23216
|
+
raw_text = _this2.stripEmptyInlineFormattingTags(raw_text);
|
|
22776
23217
|
|
|
22777
23218
|
// Use valid params or fallback to defaults
|
|
22778
23219
|
var validParams = params || {
|
|
@@ -22783,7 +23224,16 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22783
23224
|
startGlobalOffset: 0,
|
|
22784
23225
|
endGlobalOffset: 0
|
|
22785
23226
|
};
|
|
22786
|
-
_this2.
|
|
23227
|
+
_this2.setOldRangeParams(validParams);
|
|
23228
|
+
_this2.applyChangesToComponent(raw_text, mimeType, validParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
|
|
23229
|
+
skipControlledRender: true
|
|
23230
|
+
});
|
|
23231
|
+
debugMathRichInput("handleInput:after-apply", {
|
|
23232
|
+
raw_text: raw_text,
|
|
23233
|
+
mimeType: mimeType,
|
|
23234
|
+
validParams: validParams,
|
|
23235
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23236
|
+
});
|
|
22787
23237
|
} catch (error) {
|
|
22788
23238
|
console.error(error);
|
|
22789
23239
|
}
|
|
@@ -22828,44 +23278,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
22828
23278
|
});
|
|
22829
23279
|
return;
|
|
22830
23280
|
}
|
|
22831
|
-
var
|
|
22832
|
-
|
|
22833
|
-
var italic = false;
|
|
22834
|
-
var underline = false;
|
|
22835
|
-
var superscript = false;
|
|
22836
|
-
var subscript = false;
|
|
22837
|
-
do {
|
|
22838
|
-
if (node.nodeType === 1) {
|
|
22839
|
-
var nodeName = node.nodeName.toLowerCase();
|
|
22840
|
-
if (nodeName === "b" || nodeName === "strong") bold = true;else if (nodeName === "i" || nodeName === "em") italic = true;else if (nodeName === "u") underline = true;else if (nodeName === "sub") subscript = true;else if (nodeName === "sup") superscript = true;
|
|
22841
|
-
} else if (node.classList !== null && node.classList !== undefined && node.classList.contains("MathRichInput")) break;
|
|
22842
|
-
node = node.parentNode;
|
|
22843
|
-
} while (node !== null);
|
|
22844
|
-
var activeButtons = {
|
|
22845
|
-
bold: bold,
|
|
22846
|
-
italic: italic,
|
|
22847
|
-
underline: underline,
|
|
22848
|
-
subscript: subscript,
|
|
22849
|
-
superscript: superscript
|
|
22850
|
-
};
|
|
22851
|
-
// console.log(activeButtons)
|
|
22852
|
-
|
|
22853
|
-
var update = true;
|
|
22854
|
-
if (_this2.lastSetActiveButtons !== null) {
|
|
22855
|
-
update = false;
|
|
22856
|
-
for (var style in activeButtons) {
|
|
22857
|
-
if (activeButtons[style] !== _this2.lastSetActiveButtons[style]) {
|
|
22858
|
-
update = true;
|
|
22859
|
-
break;
|
|
22860
|
-
}
|
|
22861
|
-
}
|
|
22862
|
-
}
|
|
22863
|
-
if (update) {
|
|
22864
|
-
_this2.lastSetActiveButtons = activeButtons;
|
|
22865
|
-
_this2.setState({
|
|
22866
|
-
activeButtons: activeButtons
|
|
22867
|
-
});
|
|
22868
|
-
}
|
|
23281
|
+
var activeButtons = _this2.getActiveButtonsFromSelection(rangeParams);
|
|
23282
|
+
_this2.setActiveButtonsIfChanged(activeButtons);
|
|
22869
23283
|
} catch (error) {
|
|
22870
23284
|
console.error(error);
|
|
22871
23285
|
}
|
|
@@ -23100,6 +23514,14 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23100
23514
|
var node = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
23101
23515
|
try {
|
|
23102
23516
|
var rangeParams = _this2._getRangeParams();
|
|
23517
|
+
debugMathRichInput("showEquationEditor:start", {
|
|
23518
|
+
moveCursorOnInsert: moveCursorOnInsert,
|
|
23519
|
+
nodeProvided: Boolean(node),
|
|
23520
|
+
rangeParams: rangeParams,
|
|
23521
|
+
oldRangeParams: _this2.oldRangeParams,
|
|
23522
|
+
innerHTML: _this2.editableDiv ? _this2.editableDiv.innerHTML : null,
|
|
23523
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23524
|
+
});
|
|
23103
23525
|
if (rangeParams.startNodeIndex < 0) {
|
|
23104
23526
|
console.error("Could not find position of cursor in node list");
|
|
23105
23527
|
_this2.setOldRangeParams({
|
|
@@ -23142,6 +23564,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23142
23564
|
_this2.editingExistingEquation = false;
|
|
23143
23565
|
_this2.editingNode = null;
|
|
23144
23566
|
}
|
|
23567
|
+
_this2.setOldRangeParams(rangeParams);
|
|
23145
23568
|
_this2.markedRawText = elementToMarkedRawText(_this2.editableDiv, node, offset, _this2.enableHtml());
|
|
23146
23569
|
// console.log("Marked text:"+this.markedRawText)
|
|
23147
23570
|
_this2.moveCursorOnInsert = moveCursorOnInsert;
|
|
@@ -23149,11 +23572,21 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23149
23572
|
showEquationEditor: true,
|
|
23150
23573
|
equationEditorLatex: latex
|
|
23151
23574
|
});
|
|
23575
|
+
debugMathRichInput("showEquationEditor:after-setState", {
|
|
23576
|
+
rangeParams: rangeParams,
|
|
23577
|
+
markedRawText: _this2.markedRawText,
|
|
23578
|
+
latex: latex,
|
|
23579
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23580
|
+
});
|
|
23152
23581
|
} catch (error) {
|
|
23153
23582
|
console.error(error);
|
|
23154
23583
|
}
|
|
23155
23584
|
});
|
|
23156
23585
|
_defineProperty(_this2, "handleMouseDown", function (event) {
|
|
23586
|
+
_this2.isMouseDownInEditable = true;
|
|
23587
|
+
window.setTimeout(function () {
|
|
23588
|
+
_this2.isMouseDownInEditable = false;
|
|
23589
|
+
}, 0);
|
|
23157
23590
|
_this2.showEquationEditorOnMouseUp = false;
|
|
23158
23591
|
var node = null;
|
|
23159
23592
|
try {
|
|
@@ -23189,6 +23622,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23189
23622
|
// Clear selection anchor on mouse click
|
|
23190
23623
|
_this2.selectionAnchor = null;
|
|
23191
23624
|
var params = _this2._getRangeParams();
|
|
23625
|
+
_this2.setOldRangeParams(params);
|
|
23192
23626
|
var startNode = _this2._findNodeWithIndex(params.startNodeIndex);
|
|
23193
23627
|
var endNode = _this2._findNodeWithIndex(params.endNodeIndex);
|
|
23194
23628
|
if (startNode === null || endNode === null) {
|
|
@@ -23244,7 +23678,15 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23244
23678
|
_defineProperty(_this2, "handleEquationEditorInsert", function (latex) {
|
|
23245
23679
|
try {
|
|
23246
23680
|
// console.log("Inserting latex: "+latex)
|
|
23247
|
-
|
|
23681
|
+
debugMathRichInput("handleEquationEditorInsert:start", {
|
|
23682
|
+
latex: latex,
|
|
23683
|
+
markedRawText: _this2.markedRawText,
|
|
23684
|
+
oldRangeParams: _this2.getOldRangeParams(),
|
|
23685
|
+
moveCursorOnInsert: _this2.moveCursorOnInsert,
|
|
23686
|
+
propsValue: _this2.props.value,
|
|
23687
|
+
innerHTML: _this2.editableDiv ? _this2.editableDiv.innerHTML : null,
|
|
23688
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23689
|
+
});
|
|
23248
23690
|
var start_pos = _this2.markedRawText.indexOf(MARK);
|
|
23249
23691
|
var end_pos = _this2.markedRawText.indexOf(MARK, start_pos + MARK.length);
|
|
23250
23692
|
var oldRangeParams = _this2.getOldRangeParams();
|
|
@@ -23286,6 +23728,10 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23286
23728
|
_this2.applyChangesToComponent(_new_raw_text, _mimeType2, _new_rangeParams7, _this2.props.useExpertMode, _this2.props.selectedTab);
|
|
23287
23729
|
_this2.setState({
|
|
23288
23730
|
showEquationEditor: false
|
|
23731
|
+
}, function () {
|
|
23732
|
+
_this2.editableDiv.focus();
|
|
23733
|
+
_this2._setRangeParams(_new_rangeParams7);
|
|
23734
|
+
_this2.restoreRangeAfterBrowserWork(_new_rangeParams7, "equation-empty");
|
|
23289
23735
|
});
|
|
23290
23736
|
return;
|
|
23291
23737
|
}
|
|
@@ -23304,28 +23750,48 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23304
23750
|
endOffset: SMALL_SPACE_LENGTH
|
|
23305
23751
|
};
|
|
23306
23752
|
} else {
|
|
23307
|
-
//
|
|
23308
|
-
//
|
|
23309
|
-
|
|
23310
|
-
|
|
23311
|
-
|
|
23312
|
-
var
|
|
23753
|
+
// In this editor a rendered equation counts as one logical character
|
|
23754
|
+
// in global-offset space. Put the caret immediately after that math
|
|
23755
|
+
// character instead of guessing rendered child-node indexes.
|
|
23756
|
+
var _oldRangeParams = _this2.getOldRangeParams();
|
|
23757
|
+
if (_oldRangeParams !== null && _oldRangeParams.startGlobalOffset !== null && _oldRangeParams.startGlobalOffset !== undefined) {
|
|
23758
|
+
var afterInsertedMathOffset = _oldRangeParams.startGlobalOffset + 1;
|
|
23313
23759
|
new_rangeParams = {
|
|
23314
|
-
startGlobalOffset:
|
|
23315
|
-
endGlobalOffset:
|
|
23760
|
+
startGlobalOffset: afterInsertedMathOffset,
|
|
23761
|
+
endGlobalOffset: afterInsertedMathOffset
|
|
23762
|
+
};
|
|
23763
|
+
} else if (_oldRangeParams !== null && _oldRangeParams.startNodeIndex !== null && _oldRangeParams.startNodeIndex !== undefined) {
|
|
23764
|
+
new_rangeParams = {
|
|
23765
|
+
startNodeIndex: _oldRangeParams.startNodeIndex + 2,
|
|
23766
|
+
startOffset: SMALL_SPACE_LENGTH,
|
|
23767
|
+
endNodeIndex: _oldRangeParams.startNodeIndex + 2,
|
|
23768
|
+
endOffset: SMALL_SPACE_LENGTH
|
|
23316
23769
|
};
|
|
23317
23770
|
}
|
|
23318
|
-
// If
|
|
23771
|
+
// If old range params are unavailable, keep the current fallback.
|
|
23319
23772
|
}
|
|
23320
23773
|
}
|
|
23321
23774
|
// console.log("New cursor pos: "+new_rangeParams.startNodeIndex+"->"+new_rangeParams.startOffset)
|
|
23322
23775
|
_this2.setOldRangeParams(new_rangeParams);
|
|
23776
|
+
debugMathRichInput("handleEquationEditorInsert:before-apply", {
|
|
23777
|
+
new_raw_text: new_raw_text,
|
|
23778
|
+
new_rangeParams: new_rangeParams,
|
|
23779
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23780
|
+
});
|
|
23323
23781
|
var nodeCounts = _this2._countNodeTypes();
|
|
23324
23782
|
var mimeType = _this2.getMimeType(nodeCounts.html > 0, true);
|
|
23325
23783
|
new_raw_text = removeEncodingIfPlainText(new_raw_text, mimeType, _this2.enableHtml());
|
|
23326
23784
|
_this2.applyChangesToComponent(new_raw_text, mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
|
|
23327
23785
|
_this2.setState({
|
|
23328
23786
|
showEquationEditor: false
|
|
23787
|
+
}, function () {
|
|
23788
|
+
_this2.editableDiv.focus();
|
|
23789
|
+
_this2._setRangeParams(new_rangeParams);
|
|
23790
|
+
_this2.restoreRangeAfterBrowserWork(new_rangeParams, "equation-insert");
|
|
23791
|
+
debugMathRichInput("handleEquationEditorInsert:after-close-restore", {
|
|
23792
|
+
new_rangeParams: new_rangeParams,
|
|
23793
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
23794
|
+
});
|
|
23329
23795
|
});
|
|
23330
23796
|
} catch (error) {
|
|
23331
23797
|
console.error(error);
|
|
@@ -23342,13 +23808,22 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23342
23808
|
_defineProperty(_this2, "styleText", function (event, style) {
|
|
23343
23809
|
try {
|
|
23344
23810
|
style = style.toLowerCase();
|
|
23811
|
+
var command = _this2.getStyleCommand(style);
|
|
23812
|
+
var activeBefore = _this2.getActiveButtonsFromSelection();
|
|
23813
|
+
var selection = document.getSelection();
|
|
23814
|
+
var isCollapsed = selection === null || selection.rangeCount === 0 || selection.getRangeAt(0).collapsed;
|
|
23345
23815
|
var success = false;
|
|
23816
|
+
var insertedTypingStylePlaceholder = false;
|
|
23346
23817
|
|
|
23347
23818
|
// This first part is a workaround whereby executing subscript or superscript
|
|
23348
23819
|
// within an existing subscript or superscript makes the text even smaller instead
|
|
23349
23820
|
// of toggling it off. Thus we manually toggle it off with some jigerry pokery!
|
|
23350
|
-
if (
|
|
23351
|
-
|
|
23821
|
+
if (isCollapsed && activeBefore[style] && _this2.moveTrailingWhitespaceOutsideInlineStyle(style, command)) {
|
|
23822
|
+
success = true;
|
|
23823
|
+
} else if (isCollapsed && !activeBefore[style] && selection && selection.rangeCount > 0) {
|
|
23824
|
+
success = _this2.insertInlineStylePlaceholder(style);
|
|
23825
|
+
insertedTypingStylePlaceholder = success;
|
|
23826
|
+
} else if (style === "subscript" && activeBefore.subscript || style === "superscript" && activeBefore.superscript) {
|
|
23352
23827
|
var range = selection.getRangeAt(0);
|
|
23353
23828
|
if (range.endContainer === range.startContainer && range.endOffset === range.startOffset) {
|
|
23354
23829
|
success = document.execCommand("insertText", false, " ");
|
|
@@ -23357,78 +23832,21 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23357
23832
|
selection.addRange(range);
|
|
23358
23833
|
}
|
|
23359
23834
|
success = document.execCommand("removeFormat", false, null);
|
|
23360
|
-
if (
|
|
23361
|
-
if (
|
|
23362
|
-
if (
|
|
23835
|
+
if (activeBefore.bold) success = document.execCommand("bold", false, null);
|
|
23836
|
+
if (activeBefore.italic) success = document.execCommand("italic", false, null);
|
|
23837
|
+
if (activeBefore.underline) success = document.execCommand("underline", false, null);
|
|
23363
23838
|
} else {
|
|
23364
|
-
|
|
23365
|
-
|
|
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
|
-
}
|
|
23839
|
+
if (selection && selection.rangeCount > 0) {
|
|
23840
|
+
success = document.execCommand(command, false, null);
|
|
23422
23841
|
}
|
|
23423
23842
|
}
|
|
23424
|
-
var
|
|
23425
|
-
|
|
23426
|
-
|
|
23427
|
-
|
|
23428
|
-
|
|
23429
|
-
|
|
23430
|
-
|
|
23431
|
-
});
|
|
23843
|
+
var rangeParams = _this2._getRangeParams();
|
|
23844
|
+
var removedEmptyTags = !insertedTypingStylePlaceholder && _this2.cleanupEmptyInlineFormattingElements();
|
|
23845
|
+
if (removedEmptyTags && rangeParams !== null && rangeParams !== undefined) {
|
|
23846
|
+
_this2._setRangeParams(rangeParams);
|
|
23847
|
+
_this2.applyCurrentEditableDomToComponent(rangeParams);
|
|
23848
|
+
}
|
|
23849
|
+
_this2.setActiveButtonsIfChanged(_this2.getActiveButtonsFromSelection(rangeParams));
|
|
23432
23850
|
return success;
|
|
23433
23851
|
} catch (error) {
|
|
23434
23852
|
console.error(error);
|
|
@@ -23436,8 +23854,15 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23436
23854
|
});
|
|
23437
23855
|
_defineProperty(_this2, "handleToolbarButtonClick", function (event, buttonName) {
|
|
23438
23856
|
try {
|
|
23857
|
+
debugMathRichInput("handleToolbarButtonClick:start", {
|
|
23858
|
+
buttonName: buttonName,
|
|
23859
|
+
eventType: event ? event.type : null,
|
|
23860
|
+
selection: getSelectionSnapshot(_this2.editableDiv),
|
|
23861
|
+
oldRangeParams: _this2.oldRangeParams
|
|
23862
|
+
});
|
|
23439
23863
|
if (buttonName === "Equation") {
|
|
23440
23864
|
_this2.showEquationEditor(true);
|
|
23865
|
+
return;
|
|
23441
23866
|
}
|
|
23442
23867
|
var style = buttonName;
|
|
23443
23868
|
var success = _this2.styleText(event, style);
|
|
@@ -23749,13 +24174,36 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23749
24174
|
});
|
|
23750
24175
|
_defineProperty(_this2, "handleFocus", function (event) {
|
|
23751
24176
|
var onFocus = _this2.props.onFocus;
|
|
24177
|
+
var currentRangeParams = null;
|
|
24178
|
+
try {
|
|
24179
|
+
currentRangeParams = _this2._getRangeParams();
|
|
24180
|
+
} catch (error) {
|
|
24181
|
+
currentRangeParams = null;
|
|
24182
|
+
}
|
|
24183
|
+
var savedRangeParams = _this2.getOldRangeParams();
|
|
24184
|
+
var shouldRestoreSavedRange = !_this2.isMouseDownInEditable && _this2.props.value !== "" && _this2.rangeIsAtStart(currentRangeParams) && _this2.rangeHasNonZeroPosition(savedRangeParams);
|
|
24185
|
+
debugMathRichInput("handleFocus:start", {
|
|
24186
|
+
propsValue: _this2.props.value,
|
|
24187
|
+
oldRangeParams: _this2.oldRangeParams,
|
|
24188
|
+
currentRangeParams: currentRangeParams,
|
|
24189
|
+
shouldRestoreSavedRange: shouldRestoreSavedRange,
|
|
24190
|
+
innerHTML: _this2.editableDiv ? _this2.editableDiv.innerHTML : null,
|
|
24191
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
24192
|
+
});
|
|
23752
24193
|
if (onFocus != null) {
|
|
23753
24194
|
onFocus();
|
|
23754
24195
|
}
|
|
23755
24196
|
try {
|
|
23756
|
-
_this2._setRangeParams(_this2.getOldRangeParams());
|
|
23757
24197
|
_this2.setState({
|
|
23758
24198
|
hasFocus: true
|
|
24199
|
+
}, function () {
|
|
24200
|
+
if (shouldRestoreSavedRange) {
|
|
24201
|
+
_this2._setRangeParams(savedRangeParams);
|
|
24202
|
+
_this2.restoreRangeAfterBrowserWork(savedRangeParams, "focus-restore");
|
|
24203
|
+
}
|
|
24204
|
+
debugMathRichInput("handleFocus:after-setState", {
|
|
24205
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
24206
|
+
});
|
|
23759
24207
|
});
|
|
23760
24208
|
} catch (error) {
|
|
23761
24209
|
console.error(error);
|
|
@@ -23763,6 +24211,22 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23763
24211
|
});
|
|
23764
24212
|
_defineProperty(_this2, "handleBlur", function (event) {
|
|
23765
24213
|
var onBlur = _this2.props.onBlur;
|
|
24214
|
+
var currentRangeParams = null;
|
|
24215
|
+
try {
|
|
24216
|
+
currentRangeParams = _this2._getRangeParams();
|
|
24217
|
+
if (_this2.rangeHasNonZeroPosition(currentRangeParams)) {
|
|
24218
|
+
_this2.setOldRangeParams(currentRangeParams);
|
|
24219
|
+
}
|
|
24220
|
+
} catch (error) {
|
|
24221
|
+
currentRangeParams = null;
|
|
24222
|
+
}
|
|
24223
|
+
debugMathRichInput("handleBlur:start", {
|
|
24224
|
+
propsValue: _this2.props.value,
|
|
24225
|
+
oldRangeParams: _this2.oldRangeParams,
|
|
24226
|
+
currentRangeParams: currentRangeParams,
|
|
24227
|
+
innerHTML: _this2.editableDiv ? _this2.editableDiv.innerHTML : null,
|
|
24228
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
24229
|
+
});
|
|
23766
24230
|
if (onBlur != null) {
|
|
23767
24231
|
onBlur();
|
|
23768
24232
|
}
|
|
@@ -23772,6 +24236,9 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23772
24236
|
hasFocus: false,
|
|
23773
24237
|
showAccentBar: false
|
|
23774
24238
|
});
|
|
24239
|
+
debugMathRichInput("handleBlur:after-setState", {
|
|
24240
|
+
selection: getSelectionSnapshot(_this2.editableDiv)
|
|
24241
|
+
});
|
|
23775
24242
|
} catch (error) {
|
|
23776
24243
|
console.error(error);
|
|
23777
24244
|
}
|
|
@@ -23903,18 +24370,20 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
23903
24370
|
|
|
23904
24371
|
// Elements that need to be set before the equation editor is shown
|
|
23905
24372
|
_this2.markedRawText = null;
|
|
23906
|
-
|
|
23907
|
-
|
|
23908
|
-
|
|
23909
|
-
|
|
23910
|
-
endOffset: 0
|
|
23911
|
-
};
|
|
24373
|
+
// No selection has been captured yet. Do not default this to the start of
|
|
24374
|
+
// the editor: React 19 focus/click ordering makes handleFocus restore that
|
|
24375
|
+
// synthetic 0,0 range and moves the caret to the beginning on every click.
|
|
24376
|
+
_this2.oldRangeParams = null;
|
|
23912
24377
|
_this2.moveCursorOnInsert = false;
|
|
23913
24378
|
|
|
23914
24379
|
// Elements defining the current state of range
|
|
23915
24380
|
_this2.afterComponentUpdateData = null; // Set this to update the selection after rendering
|
|
23916
|
-
_this2.
|
|
23917
|
-
|
|
24381
|
+
_this2.lastSetRangeParams = null; // This is set automatically each time the range params are set with setRangeParams
|
|
24382
|
+
_this2.skipNextControlledValueRender = false;
|
|
24383
|
+
_this2.skipNextControlledValue = null;
|
|
24384
|
+
_this2.isMouseDownInEditable = false;
|
|
24385
|
+
_this2.lastRenderedEditableHtml = null;
|
|
24386
|
+
_this2.preserveNativeDomRangeParams = null;
|
|
23918
24387
|
_this2.lastSetActiveButtons = null;
|
|
23919
24388
|
_this2.onChangeCallback = _this2.props.onChange;
|
|
23920
24389
|
|
|
@@ -24004,12 +24473,403 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
24004
24473
|
var params = _objectSpread2({}, this.oldRangeParams);
|
|
24005
24474
|
return params;
|
|
24006
24475
|
}
|
|
24476
|
+
}, {
|
|
24477
|
+
key: "rangeIsAtStart",
|
|
24478
|
+
value: function rangeIsAtStart(params) {
|
|
24479
|
+
if (params === null || params === undefined) return false;
|
|
24480
|
+
if (params.startGlobalOffset !== null && params.startGlobalOffset !== undefined && params.endGlobalOffset !== null && params.endGlobalOffset !== undefined) {
|
|
24481
|
+
return params.startGlobalOffset === 0 && params.endGlobalOffset === 0;
|
|
24482
|
+
}
|
|
24483
|
+
return params.startNodeIndex === 0 && params.endNodeIndex === 0 && params.startOffset === 0 && params.endOffset === 0;
|
|
24484
|
+
}
|
|
24485
|
+
}, {
|
|
24486
|
+
key: "rangeHasNonZeroPosition",
|
|
24487
|
+
value: function rangeHasNonZeroPosition(params) {
|
|
24488
|
+
if (params === null || params === undefined) return false;
|
|
24489
|
+
if (params.startGlobalOffset !== null && params.startGlobalOffset !== undefined) {
|
|
24490
|
+
return params.startGlobalOffset > 0;
|
|
24491
|
+
}
|
|
24492
|
+
return params.startNodeIndex > 0 || params.endNodeIndex > 0 || params.startOffset > 0 || params.endOffset > 0;
|
|
24493
|
+
}
|
|
24494
|
+
}, {
|
|
24495
|
+
key: "getCurrentRawTextForProps",
|
|
24496
|
+
value: function getCurrentRawTextForProps(nextProps) {
|
|
24497
|
+
if (!this.editableDiv) return null;
|
|
24498
|
+
try {
|
|
24499
|
+
var rawText = elementToMarkedRawText(this.editableDiv, null, 0, this.enableHtml());
|
|
24500
|
+
rawText = this.stripEmptyInlineFormattingTags(rawText);
|
|
24501
|
+
return removeEncodingIfPlainText(rawText, nextProps.mimeType, this.enableHtml());
|
|
24502
|
+
} catch (error) {
|
|
24503
|
+
debugMathRichInput("getCurrentRawTextForProps:error", {
|
|
24504
|
+
error: error,
|
|
24505
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24506
|
+
});
|
|
24507
|
+
return null;
|
|
24508
|
+
}
|
|
24509
|
+
}
|
|
24510
|
+
}, {
|
|
24511
|
+
key: "shouldSkipRedundantFocusedRender",
|
|
24512
|
+
value: function shouldSkipRedundantFocusedRender(nextProps, nextState) {
|
|
24513
|
+
if (!this.editableDiv) return false;
|
|
24514
|
+
if (nextState !== this.state) return false;
|
|
24515
|
+
if (nextState.hasFocus !== true) return false;
|
|
24516
|
+
if (this.afterComponentUpdateData !== null && this.afterComponentUpdateData !== undefined) {
|
|
24517
|
+
return false;
|
|
24518
|
+
}
|
|
24519
|
+
var currentRawText = this.getCurrentRawTextForProps(nextProps);
|
|
24520
|
+
var shouldSkip = currentRawText === nextProps.value;
|
|
24521
|
+
debugMathRichInput("shouldComponentUpdate:redundant-focused-check", {
|
|
24522
|
+
shouldSkip: shouldSkip,
|
|
24523
|
+
currentRawText: currentRawText,
|
|
24524
|
+
nextValue: nextProps.value,
|
|
24525
|
+
currentPropsValue: this.props.value,
|
|
24526
|
+
nextMimeType: nextProps.mimeType,
|
|
24527
|
+
currentMimeType: this.props.mimeType,
|
|
24528
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24529
|
+
});
|
|
24530
|
+
if (shouldSkip) {
|
|
24531
|
+
var currentRangeParams = this.getRangeParamsPreservingInlinePlaceholder();
|
|
24532
|
+
if (this.rangeHasNonZeroPosition(currentRangeParams)) {
|
|
24533
|
+
this.setOldRangeParams(currentRangeParams);
|
|
24534
|
+
}
|
|
24535
|
+
}
|
|
24536
|
+
return shouldSkip;
|
|
24537
|
+
}
|
|
24538
|
+
}, {
|
|
24539
|
+
key: "isSelectionInsideInlinePlaceholder",
|
|
24540
|
+
value: function isSelectionInsideInlinePlaceholder() {
|
|
24541
|
+
if (typeof document === "undefined") return false;
|
|
24542
|
+
var selection = document.getSelection ? document.getSelection() : null;
|
|
24543
|
+
if (!selection || selection.rangeCount === 0) return false;
|
|
24544
|
+
var range = selection.getRangeAt(0);
|
|
24545
|
+
if (!range.collapsed) return false;
|
|
24546
|
+
var node = range.startContainer;
|
|
24547
|
+
if (!node || node.nodeType !== 3) return false;
|
|
24548
|
+
if (node.nodeValue !== SMALL_SPACE) return false;
|
|
24549
|
+
if (range.startOffset !== SMALL_SPACE_LENGTH) return false;
|
|
24550
|
+
var parent = node.parentNode;
|
|
24551
|
+
if (!parent || parent.nodeType !== 1) return false;
|
|
24552
|
+
var tagName = parent.nodeName.toLowerCase();
|
|
24553
|
+
if (!INLINE_STYLE_TAG_NAMES.includes(tagName)) return false;
|
|
24554
|
+
return parent.textContent === SMALL_SPACE;
|
|
24555
|
+
}
|
|
24556
|
+
}, {
|
|
24557
|
+
key: "getRangeParamsPreservingInlinePlaceholder",
|
|
24558
|
+
value: function getRangeParamsPreservingInlinePlaceholder() {
|
|
24559
|
+
var selectionInsideInlinePlaceholder = this.isSelectionInsideInlinePlaceholder();
|
|
24560
|
+
var rangeParams = this._getRangeParams();
|
|
24561
|
+
if (!selectionInsideInlinePlaceholder || !rangeParams) {
|
|
24562
|
+
return rangeParams;
|
|
24563
|
+
}
|
|
24564
|
+
|
|
24565
|
+
// Global offsets ignore the zero-width placeholder; node index preserves it.
|
|
24566
|
+
return _objectSpread2(_objectSpread2({}, rangeParams), {}, {
|
|
24567
|
+
startGlobalOffset: null,
|
|
24568
|
+
endGlobalOffset: null
|
|
24569
|
+
});
|
|
24570
|
+
}
|
|
24571
|
+
}, {
|
|
24572
|
+
key: "getEditableHtmlForRender",
|
|
24573
|
+
value: function getEditableHtmlForRender(html) {
|
|
24574
|
+
var currentRawText = this.editableDiv ? this.getCurrentRawTextForProps(this.props) : null;
|
|
24575
|
+
var liveEditableHtml = this.editableDiv ? this.editableDiv.innerHTML : null;
|
|
24576
|
+
var canPreserveNativeDom = this.state.hasFocus === true && this.editableDiv !== null && this.editableDiv !== undefined && (this.afterComponentUpdateData === null || this.afterComponentUpdateData === undefined) && this.lastRenderedEditableHtml !== null && currentRawText === this.props.value;
|
|
24577
|
+
var preserveRangeParams = canPreserveNativeDom ? this.getRangeParamsPreservingInlinePlaceholder() : null;
|
|
24578
|
+
debugMathRichInput("render:editable-html", {
|
|
24579
|
+
canPreserveNativeDom: canPreserveNativeDom,
|
|
24580
|
+
selectionInsideInlinePlaceholder: this.isSelectionInsideInlinePlaceholder(),
|
|
24581
|
+
propsValue: this.props.value,
|
|
24582
|
+
generatedHtml: html,
|
|
24583
|
+
renderedHtml: canPreserveNativeDom ? liveEditableHtml : html,
|
|
24584
|
+
liveEditableHtml: liveEditableHtml,
|
|
24585
|
+
lastRenderedEditableHtml: this.lastRenderedEditableHtml,
|
|
24586
|
+
currentRawText: currentRawText,
|
|
24587
|
+
preserveRangeParams: preserveRangeParams,
|
|
24588
|
+
afterComponentUpdateData: this.afterComponentUpdateData,
|
|
24589
|
+
hasFocus: this.state.hasFocus,
|
|
24590
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24591
|
+
});
|
|
24592
|
+
if (canPreserveNativeDom) {
|
|
24593
|
+
this.lastRenderedEditableHtml = liveEditableHtml;
|
|
24594
|
+
this.preserveNativeDomRangeParams = preserveRangeParams;
|
|
24595
|
+
return liveEditableHtml;
|
|
24596
|
+
}
|
|
24597
|
+
this.lastRenderedEditableHtml = html;
|
|
24598
|
+
this.preserveNativeDomRangeParams = null;
|
|
24599
|
+
return html;
|
|
24600
|
+
}
|
|
24601
|
+
}, {
|
|
24602
|
+
key: "stripEmptyInlineFormattingTags",
|
|
24603
|
+
value: function stripEmptyInlineFormattingTags(rawText) {
|
|
24604
|
+
if (rawText === null || rawText === undefined) return rawText;
|
|
24605
|
+
var cleaned = rawText;
|
|
24606
|
+
var previous = null;
|
|
24607
|
+
while (previous !== cleaned) {
|
|
24608
|
+
previous = cleaned;
|
|
24609
|
+
cleaned = cleaned.replace(EMPTY_INLINE_FORMATTING_REG_EXP, "");
|
|
24610
|
+
}
|
|
24611
|
+
return cleaned;
|
|
24612
|
+
}
|
|
24613
|
+
}, {
|
|
24614
|
+
key: "cleanupEmptyInlineFormattingElements",
|
|
24615
|
+
value: function cleanupEmptyInlineFormattingElements() {
|
|
24616
|
+
if (!this.editableDiv) return false;
|
|
24617
|
+
var removed = false;
|
|
24618
|
+
this.editableDiv.querySelectorAll("b,strong,i,em,u,sub,sup").forEach(function (node) {
|
|
24619
|
+
var text = node.textContent || "";
|
|
24620
|
+
var hasMeaningfulText = text.replace(/[\s\u00a0\u200b\ufeff]/g, "") !== "";
|
|
24621
|
+
var hasProtectedContent = node.querySelector("br,img,math,.katex") !== null;
|
|
24622
|
+
if (!hasMeaningfulText && !hasProtectedContent) {
|
|
24623
|
+
node.remove();
|
|
24624
|
+
removed = true;
|
|
24625
|
+
}
|
|
24626
|
+
});
|
|
24627
|
+
if (removed) {
|
|
24628
|
+
this.editableDiv.normalize();
|
|
24629
|
+
}
|
|
24630
|
+
return removed;
|
|
24631
|
+
}
|
|
24632
|
+
}, {
|
|
24633
|
+
key: "getStyleCommand",
|
|
24634
|
+
value: function getStyleCommand(style) {
|
|
24635
|
+
return INLINE_STYLE_COMMANDS[style] || style;
|
|
24636
|
+
}
|
|
24637
|
+
}, {
|
|
24638
|
+
key: "insertInlineStylePlaceholder",
|
|
24639
|
+
value: function insertInlineStylePlaceholder(style) {
|
|
24640
|
+
var wrapperTag = INLINE_STYLE_WRAPPER_TAGS[style] || "span";
|
|
24641
|
+
var selection = document.getSelection();
|
|
24642
|
+
if (!selection || selection.rangeCount === 0) return false;
|
|
24643
|
+
var range = selection.getRangeAt(0);
|
|
24644
|
+
if (!range.collapsed) return false;
|
|
24645
|
+
range.deleteContents();
|
|
24646
|
+
var wrapper = document.createElement(wrapperTag);
|
|
24647
|
+
var textNode = document.createTextNode(SMALL_SPACE);
|
|
24648
|
+
wrapper.appendChild(textNode);
|
|
24649
|
+
range.insertNode(wrapper);
|
|
24650
|
+
var nextRange = document.createRange();
|
|
24651
|
+
nextRange.setStart(textNode, SMALL_SPACE_LENGTH);
|
|
24652
|
+
nextRange.collapse(true);
|
|
24653
|
+
selection.removeAllRanges();
|
|
24654
|
+
selection.addRange(nextRange);
|
|
24655
|
+
var rangeParams = this.getRangeParamsPreservingInlinePlaceholder();
|
|
24656
|
+
if (rangeParams) this.setOldRangeParams(rangeParams);
|
|
24657
|
+
debugMathRichInput("insertInlineStylePlaceholder:after", {
|
|
24658
|
+
style: style,
|
|
24659
|
+
wrapperTag: wrapperTag,
|
|
24660
|
+
innerHTML: this.editableDiv ? this.editableDiv.innerHTML : null,
|
|
24661
|
+
rangeParams: rangeParams,
|
|
24662
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24663
|
+
});
|
|
24664
|
+
return true;
|
|
24665
|
+
}
|
|
24666
|
+
}, {
|
|
24667
|
+
key: "getActiveButtonsFromCommandState",
|
|
24668
|
+
value: function getActiveButtonsFromCommandState() {
|
|
24669
|
+
var query = function query(command) {
|
|
24670
|
+
try {
|
|
24671
|
+
return document.queryCommandState(command);
|
|
24672
|
+
} catch (error) {
|
|
24673
|
+
return false;
|
|
24674
|
+
}
|
|
24675
|
+
};
|
|
24676
|
+
return {
|
|
24677
|
+
bold: query("bold"),
|
|
24678
|
+
italic: query("italic"),
|
|
24679
|
+
underline: query("underline"),
|
|
24680
|
+
subscript: query("subscript"),
|
|
24681
|
+
superscript: query("superscript")
|
|
24682
|
+
};
|
|
24683
|
+
}
|
|
24684
|
+
}, {
|
|
24685
|
+
key: "isSelectionCollapsed",
|
|
24686
|
+
value: function isSelectionCollapsed() {
|
|
24687
|
+
var selection = document.getSelection();
|
|
24688
|
+
if (!selection || selection.rangeCount === 0) return true;
|
|
24689
|
+
return selection.getRangeAt(0).collapsed;
|
|
24690
|
+
}
|
|
24691
|
+
}, {
|
|
24692
|
+
key: "getActiveButtonsFromAncestorState",
|
|
24693
|
+
value: function getActiveButtonsFromAncestorState() {
|
|
24694
|
+
var rangeParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
24695
|
+
if (rangeParams === null || rangeParams === undefined) {
|
|
24696
|
+
rangeParams = this._getRangeParams();
|
|
24697
|
+
}
|
|
24698
|
+
var activeButtons = {
|
|
24699
|
+
bold: false,
|
|
24700
|
+
italic: false,
|
|
24701
|
+
underline: false,
|
|
24702
|
+
subscript: false,
|
|
24703
|
+
superscript: false
|
|
24704
|
+
};
|
|
24705
|
+
if (rangeParams === null || rangeParams === undefined || rangeParams.startNodeIndex < 0) {
|
|
24706
|
+
return activeButtons;
|
|
24707
|
+
}
|
|
24708
|
+
var node = this._findNodeWithIndex(rangeParams.startNodeIndex);
|
|
24709
|
+
if (node === null || node === undefined) return activeButtons;
|
|
24710
|
+
do {
|
|
24711
|
+
if (node.nodeType === 1) {
|
|
24712
|
+
var nodeName = node.nodeName.toLowerCase();
|
|
24713
|
+
if (nodeName === "b" || nodeName === "strong") activeButtons.bold = true;else if (nodeName === "i" || nodeName === "em") activeButtons.italic = true;else if (nodeName === "u") activeButtons.underline = true;else if (nodeName === "sub") activeButtons.subscript = true;else if (nodeName === "sup") activeButtons.superscript = true;
|
|
24714
|
+
} else if (node.classList !== null && node.classList !== undefined && node.classList.contains("MathRichInput")) break;
|
|
24715
|
+
node = node.parentNode;
|
|
24716
|
+
} while (node !== null);
|
|
24717
|
+
return activeButtons;
|
|
24718
|
+
}
|
|
24719
|
+
}, {
|
|
24720
|
+
key: "getActiveButtonsFromSelection",
|
|
24721
|
+
value: function getActiveButtonsFromSelection() {
|
|
24722
|
+
var rangeParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
24723
|
+
var commandState = this.getActiveButtonsFromCommandState();
|
|
24724
|
+
var ancestorState = this.getActiveButtonsFromAncestorState(rangeParams);
|
|
24725
|
+
return {
|
|
24726
|
+
bold: commandState.bold || ancestorState.bold,
|
|
24727
|
+
italic: commandState.italic || ancestorState.italic,
|
|
24728
|
+
underline: commandState.underline || ancestorState.underline,
|
|
24729
|
+
subscript: commandState.subscript || ancestorState.subscript,
|
|
24730
|
+
superscript: commandState.superscript || ancestorState.superscript
|
|
24731
|
+
};
|
|
24732
|
+
}
|
|
24733
|
+
}, {
|
|
24734
|
+
key: "setActiveButtonsIfChanged",
|
|
24735
|
+
value: function setActiveButtonsIfChanged(activeButtons) {
|
|
24736
|
+
var update = true;
|
|
24737
|
+
if (this.lastSetActiveButtons !== null) {
|
|
24738
|
+
update = false;
|
|
24739
|
+
for (var style in activeButtons) {
|
|
24740
|
+
if (activeButtons[style] !== this.lastSetActiveButtons[style]) {
|
|
24741
|
+
update = true;
|
|
24742
|
+
break;
|
|
24743
|
+
}
|
|
24744
|
+
}
|
|
24745
|
+
}
|
|
24746
|
+
if (update) {
|
|
24747
|
+
this.lastSetActiveButtons = activeButtons;
|
|
24748
|
+
this.setState({
|
|
24749
|
+
activeButtons: activeButtons
|
|
24750
|
+
});
|
|
24751
|
+
}
|
|
24752
|
+
}
|
|
24753
|
+
}, {
|
|
24754
|
+
key: "getInlineStyleAncestor",
|
|
24755
|
+
value: function getInlineStyleAncestor(style) {
|
|
24756
|
+
var tags = INLINE_STYLE_TAGS[style];
|
|
24757
|
+
if (!tags) return null;
|
|
24758
|
+
var selection = document.getSelection();
|
|
24759
|
+
if (!selection || selection.rangeCount === 0) return null;
|
|
24760
|
+
var node = selection.getRangeAt(0).startContainer;
|
|
24761
|
+
if (node.nodeType === Node.TEXT_NODE) node = node.parentNode;
|
|
24762
|
+
while (node && node !== this.editableDiv) {
|
|
24763
|
+
if (node.nodeType === Node.ELEMENT_NODE && tags.includes(node.nodeName.toLowerCase())) {
|
|
24764
|
+
return node;
|
|
24765
|
+
}
|
|
24766
|
+
node = node.parentNode;
|
|
24767
|
+
}
|
|
24768
|
+
return null;
|
|
24769
|
+
}
|
|
24770
|
+
}, {
|
|
24771
|
+
key: "isRangeAtEndOfNode",
|
|
24772
|
+
value: function isRangeAtEndOfNode(range, node) {
|
|
24773
|
+
try {
|
|
24774
|
+
var afterRange = document.createRange();
|
|
24775
|
+
afterRange.setStart(range.startContainer, range.startOffset);
|
|
24776
|
+
afterRange.setEnd(node, node.childNodes.length);
|
|
24777
|
+
var textAfterCaret = afterRange.toString().replace(/[\s\u00a0\u200b\ufeff]/g, "");
|
|
24778
|
+
if (textAfterCaret === "") return true;
|
|
24779
|
+
} catch (error) {
|
|
24780
|
+
// Fall back to boundary comparison below if the browser rejects the range.
|
|
24781
|
+
}
|
|
24782
|
+
var nodeEndRange = document.createRange();
|
|
24783
|
+
nodeEndRange.selectNodeContents(node);
|
|
24784
|
+
nodeEndRange.collapse(false);
|
|
24785
|
+
return range.compareBoundaryPoints(Range.START_TO_START, nodeEndRange) === 0;
|
|
24786
|
+
}
|
|
24787
|
+
}, {
|
|
24788
|
+
key: "moveTrailingWhitespaceOutsideInlineStyle",
|
|
24789
|
+
value: function moveTrailingWhitespaceOutsideInlineStyle(style, command) {
|
|
24790
|
+
var selection = document.getSelection();
|
|
24791
|
+
if (!selection || selection.rangeCount === 0) return false;
|
|
24792
|
+
var range = selection.getRangeAt(0);
|
|
24793
|
+
if (!range.collapsed) return false;
|
|
24794
|
+
var ancestor = this.getInlineStyleAncestor(style);
|
|
24795
|
+
if (!ancestor || !this.isRangeAtEndOfNode(range, ancestor)) return false;
|
|
24796
|
+
if (range.startContainer.nodeType !== Node.TEXT_NODE) return false;
|
|
24797
|
+
var textNode = range.startContainer;
|
|
24798
|
+
var text = textNode.nodeValue || "";
|
|
24799
|
+
var moveStart = range.startOffset;
|
|
24800
|
+
while (moveStart > 0) {
|
|
24801
|
+
var _char = text.charAt(moveStart - 1);
|
|
24802
|
+
if (_char !== " " && _char !== "\xA0") break;
|
|
24803
|
+
moveStart -= 1;
|
|
24804
|
+
}
|
|
24805
|
+
if (moveStart === range.startOffset) return false;
|
|
24806
|
+
var movedText = text.substring(moveStart, range.startOffset);
|
|
24807
|
+
textNode.nodeValue = text.substring(0, moveStart) + text.substring(range.startOffset);
|
|
24808
|
+
var outsideNode = ancestor.nextSibling;
|
|
24809
|
+
if (!outsideNode || outsideNode.nodeType !== Node.TEXT_NODE) {
|
|
24810
|
+
outsideNode = document.createTextNode(movedText);
|
|
24811
|
+
ancestor.parentNode.insertBefore(outsideNode, ancestor.nextSibling);
|
|
24812
|
+
} else {
|
|
24813
|
+
outsideNode.nodeValue = movedText + outsideNode.nodeValue;
|
|
24814
|
+
}
|
|
24815
|
+
var nextRange = document.createRange();
|
|
24816
|
+
nextRange.setStart(outsideNode, movedText.length);
|
|
24817
|
+
nextRange.collapse(true);
|
|
24818
|
+
selection.removeAllRanges();
|
|
24819
|
+
selection.addRange(nextRange);
|
|
24820
|
+
try {
|
|
24821
|
+
if (document.queryCommandState(command)) {
|
|
24822
|
+
document.execCommand(command, false, null);
|
|
24823
|
+
}
|
|
24824
|
+
} catch (error) {
|
|
24825
|
+
// DOM position is the source of truth here; command state is best effort.
|
|
24826
|
+
}
|
|
24827
|
+
var rangeParams = this._getRangeParams();
|
|
24828
|
+
if (rangeParams) {
|
|
24829
|
+
this.setOldRangeParams(rangeParams);
|
|
24830
|
+
this.applyCurrentEditableDomToComponent(rangeParams);
|
|
24831
|
+
}
|
|
24832
|
+
debugMathRichInput("moveTrailingWhitespaceOutsideInlineStyle:after", {
|
|
24833
|
+
style: style,
|
|
24834
|
+
command: command,
|
|
24835
|
+
movedText: movedText,
|
|
24836
|
+
innerHTML: this.editableDiv ? this.editableDiv.innerHTML : null,
|
|
24837
|
+
rangeParams: rangeParams,
|
|
24838
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24839
|
+
});
|
|
24840
|
+
return true;
|
|
24841
|
+
}
|
|
24842
|
+
}, {
|
|
24843
|
+
key: "applyCurrentEditableDomToComponent",
|
|
24844
|
+
value: function applyCurrentEditableDomToComponent() {
|
|
24845
|
+
var rangeParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
24846
|
+
if (!this.editableDiv) return;
|
|
24847
|
+
if (rangeParams === null || rangeParams === undefined) {
|
|
24848
|
+
rangeParams = this._getRangeParams();
|
|
24849
|
+
}
|
|
24850
|
+
if (rangeParams === null || rangeParams === undefined) return;
|
|
24851
|
+
var rawText = elementToMarkedRawText(this.editableDiv, null, 0, this.enableHtml());
|
|
24852
|
+
rawText = this.stripEmptyInlineFormattingTags(rawText);
|
|
24853
|
+
var nodeCounts = this._countNodeTypes();
|
|
24854
|
+
var hasMath = /<math>/i.test(rawText) || nodeCounts.math > 0;
|
|
24855
|
+
var hasHtml = nodeCounts.html > 0 || /<[^>]+>/i.test(rawText);
|
|
24856
|
+
var mimeType = this.getMimeType(hasHtml, hasMath);
|
|
24857
|
+
rawText = removeEncodingIfPlainText(rawText, mimeType, this.enableHtml());
|
|
24858
|
+
rawText = this.stripEmptyInlineFormattingTags(rawText);
|
|
24859
|
+
this.applyChangesToComponent(rawText, mimeType, rangeParams, this.props.useExpertMode, this.props.selectedTab, {
|
|
24860
|
+
skipControlledRender: true
|
|
24861
|
+
});
|
|
24862
|
+
}
|
|
24007
24863
|
}, {
|
|
24008
24864
|
key: "_getRangeParams",
|
|
24009
24865
|
value: function _getRangeParams() {
|
|
24010
24866
|
var editableDiv = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
24011
24867
|
if (editableDiv === null) editableDiv = this.editableDiv;
|
|
24012
24868
|
var rangeParams = getRangeParams(editableDiv);
|
|
24869
|
+
debugMathRichInput("MathRichInput:_getRangeParams", {
|
|
24870
|
+
rangeParams: rangeParams,
|
|
24871
|
+
selection: getSelectionSnapshot(editableDiv)
|
|
24872
|
+
});
|
|
24013
24873
|
return rangeParams;
|
|
24014
24874
|
}
|
|
24015
24875
|
}, {
|
|
@@ -24038,6 +24898,14 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
24038
24898
|
value: function componentDidMount() {
|
|
24039
24899
|
try {
|
|
24040
24900
|
setupKatex();
|
|
24901
|
+
debugMathRichInput("componentDidMount", {
|
|
24902
|
+
propsValue: this.props.value,
|
|
24903
|
+
propsMimeType: this.props.mimeType,
|
|
24904
|
+
autofocus: this.props.autofocus,
|
|
24905
|
+
autoFocus: this.props.autoFocus,
|
|
24906
|
+
innerHTML: this.editableDiv ? this.editableDiv.innerHTML : null,
|
|
24907
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24908
|
+
});
|
|
24041
24909
|
this.editableDiv.addEventListener("keydown", this.handleKeyDown);
|
|
24042
24910
|
this.editableDiv.addEventListener("keyup", this.handleKeyUp);
|
|
24043
24911
|
this.editableDiv.addEventListener("paste", this.handlePaste);
|
|
@@ -24059,14 +24927,70 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
24059
24927
|
console.error(error);
|
|
24060
24928
|
}
|
|
24061
24929
|
}
|
|
24930
|
+
}, {
|
|
24931
|
+
key: "shouldComponentUpdate",
|
|
24932
|
+
value: function shouldComponentUpdate(nextProps, nextState) {
|
|
24933
|
+
if (this.skipNextControlledValueRender === true) {
|
|
24934
|
+
var canSkip = nextProps.value === this.skipNextControlledValue && nextState === this.state;
|
|
24935
|
+
debugMathRichInput("shouldComponentUpdate:native-input-gate", {
|
|
24936
|
+
canSkip: canSkip,
|
|
24937
|
+
nextValue: nextProps.value,
|
|
24938
|
+
skipNextControlledValue: this.skipNextControlledValue,
|
|
24939
|
+
currentPropsValue: this.props.value,
|
|
24940
|
+
stateChanged: nextState !== this.state,
|
|
24941
|
+
innerHTML: this.editableDiv ? this.editableDiv.innerHTML : null,
|
|
24942
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24943
|
+
});
|
|
24944
|
+
this.skipNextControlledValueRender = false;
|
|
24945
|
+
this.skipNextControlledValue = null;
|
|
24946
|
+
if (canSkip) return false;
|
|
24947
|
+
}
|
|
24948
|
+
if (this.shouldSkipRedundantFocusedRender(nextProps, nextState)) {
|
|
24949
|
+
debugMathRichInput("shouldComponentUpdate:skip-redundant-focused-render", {
|
|
24950
|
+
nextValue: nextProps.value,
|
|
24951
|
+
currentPropsValue: this.props.value,
|
|
24952
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24953
|
+
});
|
|
24954
|
+
return false;
|
|
24955
|
+
}
|
|
24956
|
+
return true;
|
|
24957
|
+
}
|
|
24062
24958
|
}, {
|
|
24063
24959
|
key: "componentDidUpdate",
|
|
24064
24960
|
value: function componentDidUpdate() {
|
|
24065
24961
|
try {
|
|
24962
|
+
debugMathRichInput("componentDidUpdate:start", {
|
|
24963
|
+
propsValue: this.props.value,
|
|
24964
|
+
propsMimeType: this.props.mimeType,
|
|
24965
|
+
afterComponentUpdateData: this.afterComponentUpdateData,
|
|
24966
|
+
hasFocus: this.state.hasFocus,
|
|
24967
|
+
showEquationEditor: this.state.showEquationEditor,
|
|
24968
|
+
innerHTML: this.editableDiv ? this.editableDiv.innerHTML : null,
|
|
24969
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24970
|
+
});
|
|
24066
24971
|
if (this.afterComponentUpdateData !== null && this.afterComponentUpdateData !== undefined && this.afterComponentUpdateData.value === this.props.value) {
|
|
24972
|
+
debugMathRichInput("componentDidUpdate:restore-before", {
|
|
24973
|
+
rangeParams: this.afterComponentUpdateData.rangeParams,
|
|
24974
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24975
|
+
});
|
|
24067
24976
|
this._setRangeParams(this.afterComponentUpdateData.rangeParams);
|
|
24068
24977
|
this.afterComponentUpdateData = null;
|
|
24069
24978
|
this.updateActiveButtons();
|
|
24979
|
+
debugMathRichInput("componentDidUpdate:restore-after", {
|
|
24980
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24981
|
+
});
|
|
24982
|
+
}
|
|
24983
|
+
if (this.preserveNativeDomRangeParams !== null && this.preserveNativeDomRangeParams !== undefined && this.state.hasFocus === true) {
|
|
24984
|
+
var rangeParams = this.preserveNativeDomRangeParams;
|
|
24985
|
+
this.preserveNativeDomRangeParams = null;
|
|
24986
|
+
debugMathRichInput("componentDidUpdate:preserve-restore-before", {
|
|
24987
|
+
rangeParams: rangeParams,
|
|
24988
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24989
|
+
});
|
|
24990
|
+
this._setRangeParams(rangeParams);
|
|
24991
|
+
debugMathRichInput("componentDidUpdate:preserve-restore-after", {
|
|
24992
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
24993
|
+
});
|
|
24070
24994
|
}
|
|
24071
24995
|
} catch (error) {
|
|
24072
24996
|
console.error(error);
|
|
@@ -24079,20 +25003,31 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
24079
25003
|
if (rangeParams === null || rangeParams === undefined) rangeParams = this._getRangeParams();
|
|
24080
25004
|
if (rangeParams.startOffset !== 0) console.warn("Unexpected startOffset " + rangeParams.startOffset + " in insertAfterSmallSpace");
|
|
24081
25005
|
var node = this._findNodeWithIndex(rangeParams.startNodeIndex);
|
|
24082
|
-
|
|
24083
|
-
|
|
24084
|
-
|
|
24085
|
-
|
|
25006
|
+
if (node === null || node === undefined || node.nodeValue === null) {
|
|
25007
|
+
console.warn("Could not find small-space text node");
|
|
25008
|
+
return;
|
|
25009
|
+
}
|
|
25010
|
+
|
|
25011
|
+
// The initial empty editor contains a hidden zero-width space. Handling
|
|
25012
|
+
// the first printable key by re-rendering through React replaces the
|
|
25013
|
+
// text node and drops Chrome's selection to the start under React 19.
|
|
25014
|
+
// Mutate the already-focused DOM node, then skip the matching controlled
|
|
25015
|
+
// render exactly like the normal contenteditable input path.
|
|
25016
|
+
node.nodeValue = node.nodeValue.substring(0, 1) + new_char + node.nodeValue.substring(1);
|
|
24086
25017
|
var new_rangeParams = {
|
|
24087
25018
|
startNodeIndex: rangeParams.startNodeIndex,
|
|
24088
|
-
|
|
25019
|
+
startOffset: 1 + new_char.length,
|
|
24089
25020
|
endNodeIndex: rangeParams.startNodeIndex,
|
|
24090
|
-
|
|
25021
|
+
endOffset: 1 + new_char.length,
|
|
24091
25022
|
startGlobalOffset: rangeParams.startGlobalOffset + new_char.length,
|
|
24092
25023
|
endGlobalOffset: rangeParams.endGlobalOffset + new_char.length
|
|
24093
25024
|
};
|
|
25025
|
+
this._setRangeParams(new_rangeParams);
|
|
25026
|
+
var new_raw_text = elementToMarkedRawText(this.editableDiv, null, 0, this.enableHtml());
|
|
24094
25027
|
new_raw_text = removeEncodingIfPlainText(new_raw_text, this.props.mimeType, this.enableHtml());
|
|
24095
|
-
this.applyChangesToComponent(new_raw_text, this.props.mimeType, new_rangeParams, this.props.useExpertMode, this.props.selectedTab
|
|
25028
|
+
this.applyChangesToComponent(new_raw_text, this.props.mimeType, new_rangeParams, this.props.useExpertMode, this.props.selectedTab, {
|
|
25029
|
+
skipControlledRender: true
|
|
25030
|
+
});
|
|
24096
25031
|
} catch (error) {
|
|
24097
25032
|
console.error(error);
|
|
24098
25033
|
}
|
|
@@ -24106,6 +25041,23 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
24106
25041
|
console.log(this.props);
|
|
24107
25042
|
}
|
|
24108
25043
|
var html = rawTextToHtml(katex$1, this.props.value || "", this.props.mimeType);
|
|
25044
|
+
var editableHtml = this.getEditableHtmlForRender(html);
|
|
25045
|
+
debugMathRichInput("render", {
|
|
25046
|
+
propsValue: this.props.value,
|
|
25047
|
+
propsMimeType: this.props.mimeType,
|
|
25048
|
+
html: html,
|
|
25049
|
+
editableHtml: editableHtml,
|
|
25050
|
+
state: {
|
|
25051
|
+
hasFocus: this.state.hasFocus,
|
|
25052
|
+
showEquationEditor: this.state.showEquationEditor,
|
|
25053
|
+
showAccentBar: this.state.showAccentBar,
|
|
25054
|
+
keyPressed: this.state.keyPressed
|
|
25055
|
+
},
|
|
25056
|
+
afterComponentUpdateData: this.afterComponentUpdateData,
|
|
25057
|
+
oldRangeParams: this.oldRangeParams,
|
|
25058
|
+
editableInnerHTML: this.editableDiv ? this.editableDiv.innerHTML : null,
|
|
25059
|
+
selection: getSelectionSnapshot(this.editableDiv)
|
|
25060
|
+
});
|
|
24109
25061
|
|
|
24110
25062
|
// Debug render math
|
|
24111
25063
|
// if (this.props.value && this.props.value.includes("<math>")) {
|
|
@@ -24164,7 +25116,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
24164
25116
|
onCompositionStart: this.handleCompositionStart,
|
|
24165
25117
|
onCompositionEnd: this.handleCompositionEnd,
|
|
24166
25118
|
dangerouslySetInnerHTML: {
|
|
24167
|
-
__html:
|
|
25119
|
+
__html: editableHtml
|
|
24168
25120
|
},
|
|
24169
25121
|
"data-placeholder": this.props.placeholder || ""
|
|
24170
25122
|
}))), this.state.showEquationEditor && /*#__PURE__*/React__default["default"].createElement(EquationEditorModal, {
|
|
@@ -24173,7 +25125,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
24173
25125
|
},
|
|
24174
25126
|
handleClose: this.handleEquationEditorClose,
|
|
24175
25127
|
handleInsert: this.handleEquationEditorInsert,
|
|
24176
|
-
latex: this.state.equationEditorLatex
|
|
25128
|
+
latex: this.state.equationEditorLatex,
|
|
25129
|
+
disableAnimation: this.props.disableAnimation
|
|
24177
25130
|
}));
|
|
24178
25131
|
}
|
|
24179
25132
|
}]);
|
|
@@ -24182,7 +25135,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
|
|
|
24182
25135
|
function getAllTextNodes(node) {
|
|
24183
25136
|
var nodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
24184
25137
|
if (node === null) {
|
|
24185
|
-
console.warn("
|
|
25138
|
+
console.warn("Developer supplied a null node. Ignoring");
|
|
24186
25139
|
return nodes;
|
|
24187
25140
|
}
|
|
24188
25141
|
if (nodes === null) {
|
|
@@ -24207,8 +25160,9 @@ function getAllTextNodes(node) {
|
|
|
24207
25160
|
return nodes;
|
|
24208
25161
|
}
|
|
24209
25162
|
function renderMathInNode(node) {
|
|
25163
|
+
if (node === null || node === undefined) return;
|
|
24210
25164
|
try {
|
|
24211
|
-
var textNodes = getAllTextNodes(node);
|
|
25165
|
+
var textNodes = getAllTextNodes(node, []);
|
|
24212
25166
|
for (var i = 0; i < textNodes.length; i++) {
|
|
24213
25167
|
try {
|
|
24214
25168
|
var text = textNodes[i].nodeValue;
|