diff --git a/packages/editor/dist/components/button.d.ts b/packages/editor/dist/components/button.d.ts
index f118730d4..d585b4df9 100644
--- a/packages/editor/dist/components/button.d.ts
+++ b/packages/editor/dist/components/button.d.ts
@@ -1,3 +1,3 @@
///
import { ButtonProps } from "rebass";
-export declare const Button: import("react").ForwardRefExoticComponent & import("react").RefAttributes>;
+export declare const Button: import("react").ForwardRefExoticComponent & import("react").RefAttributes>;
diff --git a/packages/editor/dist/components/menu/usefocus.d.ts b/packages/editor/dist/components/menu/usefocus.d.ts
index 36b4ee2ca..66f324efc 100644
--- a/packages/editor/dist/components/menu/usefocus.d.ts
+++ b/packages/editor/dist/components/menu/usefocus.d.ts
@@ -1,4 +1,3 @@
-///
import { MenuItem } from "./types";
export declare function useFocus(items: MenuItem[], onAction: (event: KeyboardEvent) => void, onClose: (event: KeyboardEvent) => void): {
focusIndex: number;
diff --git a/packages/editor/dist/extensions/codemark/codemark.d.ts b/packages/editor/dist/extensions/codemark/codemark.d.ts
new file mode 100644
index 000000000..003c47b2f
--- /dev/null
+++ b/packages/editor/dist/extensions/codemark/codemark.d.ts
@@ -0,0 +1,2 @@
+import { Extension } from "@tiptap/core";
+export declare const Codemark: Extension;
diff --git a/packages/editor/dist/extensions/codemark/codemark.js b/packages/editor/dist/extensions/codemark/codemark.js
new file mode 100644
index 000000000..153f554ff
--- /dev/null
+++ b/packages/editor/dist/extensions/codemark/codemark.js
@@ -0,0 +1,9 @@
+import { Extension } from "@tiptap/core";
+import codemark from "prosemirror-codemark";
+// import "prosemirror-codemark/dist/codemark.css";
+export var Codemark = Extension.create({
+ name: "codemarkPlugin",
+ addProseMirrorPlugins: function () {
+ return codemark({ markType: this.editor.schema.marks.code });
+ },
+});
diff --git a/packages/editor/dist/extensions/codemark/index.d.ts b/packages/editor/dist/extensions/codemark/index.d.ts
new file mode 100644
index 000000000..8c4911b98
--- /dev/null
+++ b/packages/editor/dist/extensions/codemark/index.d.ts
@@ -0,0 +1,2 @@
+export * from "./code-mark";
+export { Codemark as default } from "./code-mark";
diff --git a/packages/editor/dist/extensions/codemark/index.js b/packages/editor/dist/extensions/codemark/index.js
new file mode 100644
index 000000000..8c4911b98
--- /dev/null
+++ b/packages/editor/dist/extensions/codemark/index.js
@@ -0,0 +1,2 @@
+export * from "./code-mark";
+export { Codemark as default } from "./code-mark";
diff --git a/packages/editor/dist/extensions/math/index.d.ts b/packages/editor/dist/extensions/math/index.d.ts
new file mode 100644
index 000000000..1331fdb01
--- /dev/null
+++ b/packages/editor/dist/extensions/math/index.d.ts
@@ -0,0 +1,2 @@
+export { MathInline } from "./math-inline";
+export { MathBlock } from "./math-block";
diff --git a/packages/editor/dist/extensions/math/index.js b/packages/editor/dist/extensions/math/index.js
new file mode 100644
index 000000000..1331fdb01
--- /dev/null
+++ b/packages/editor/dist/extensions/math/index.js
@@ -0,0 +1,2 @@
+export { MathInline } from "./math-inline";
+export { MathBlock } from "./math-block";
diff --git a/packages/editor/dist/extensions/math/mathblock.d.ts b/packages/editor/dist/extensions/math/mathblock.d.ts
new file mode 100644
index 000000000..419bb7458
--- /dev/null
+++ b/packages/editor/dist/extensions/math/mathblock.d.ts
@@ -0,0 +1,2 @@
+import { Node } from "@tiptap/core";
+export declare const MathBlock: Node;
diff --git a/packages/editor/dist/extensions/math/mathblock.js b/packages/editor/dist/extensions/math/mathblock.js
new file mode 100644
index 000000000..af36cedd1
--- /dev/null
+++ b/packages/editor/dist/extensions/math/mathblock.js
@@ -0,0 +1,31 @@
+import { Node, mergeAttributes } from "@tiptap/core";
+import { inputRules } from "prosemirror-inputrules";
+import { makeBlockMathInputRule, REGEX_BLOCK_MATH_DOLLARS, } from "./plugin";
+export var MathBlock = Node.create({
+ name: "math_display",
+ group: "block math",
+ content: "text*",
+ atom: true,
+ code: true,
+ parseHTML: function () {
+ return [
+ {
+ tag: "div[class*='math-display']", // important!
+ },
+ ];
+ },
+ renderHTML: function (_a) {
+ var HTMLAttributes = _a.HTMLAttributes;
+ return [
+ "div",
+ mergeAttributes({ class: "math-display math-node" }, HTMLAttributes),
+ 0,
+ ];
+ },
+ addProseMirrorPlugins: function () {
+ var inputRulePlugin = inputRules({
+ rules: [makeBlockMathInputRule(REGEX_BLOCK_MATH_DOLLARS, this.type)],
+ });
+ return [inputRulePlugin];
+ },
+});
diff --git a/packages/editor/dist/extensions/math/mathinline.d.ts b/packages/editor/dist/extensions/math/mathinline.d.ts
new file mode 100644
index 000000000..7b3a718d8
--- /dev/null
+++ b/packages/editor/dist/extensions/math/mathinline.d.ts
@@ -0,0 +1,3 @@
+import { Node } from "@tiptap/core";
+import "katex/dist/katex.min.css";
+export declare const MathInline: Node;
diff --git a/packages/editor/dist/extensions/math/mathinline.js b/packages/editor/dist/extensions/math/mathinline.js
new file mode 100644
index 000000000..de3fc67c9
--- /dev/null
+++ b/packages/editor/dist/extensions/math/mathinline.js
@@ -0,0 +1,33 @@
+import { Node, mergeAttributes } from "@tiptap/core";
+import { inputRules } from "prosemirror-inputrules";
+import { makeInlineMathInputRule, REGEX_INLINE_MATH_DOLLARS, mathPlugin, } from "./plugin";
+import "katex/dist/katex.min.css";
+export var MathInline = Node.create({
+ name: "math_inline",
+ group: "inline math",
+ content: "text*",
+ inline: true,
+ atom: true,
+ code: true,
+ parseHTML: function () {
+ return [
+ {
+ tag: "span[class*='math-inline']", // important!,
+ },
+ ];
+ },
+ renderHTML: function (_a) {
+ var HTMLAttributes = _a.HTMLAttributes;
+ return [
+ "span",
+ mergeAttributes({ class: "math-inline math-node" }, HTMLAttributes),
+ 0,
+ ];
+ },
+ addProseMirrorPlugins: function () {
+ var inputRulePlugin = inputRules({
+ rules: [makeInlineMathInputRule(REGEX_INLINE_MATH_DOLLARS, this.type)],
+ });
+ return [mathPlugin, inputRulePlugin];
+ },
+});
diff --git a/packages/editor/dist/extensions/math/plugin/commands/collapse-math-cmd.d.ts b/packages/editor/dist/extensions/math/plugin/commands/collapse-math-cmd.d.ts
new file mode 100644
index 000000000..c315ac00a
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/commands/collapse-math-cmd.d.ts
@@ -0,0 +1,16 @@
+import { Command } from "prosemirror-state";
+import { EditorView } from "prosemirror-view";
+/**
+ * A ProseMirror command for determining whether to exit a math block, based on
+ * specific conditions. Normally called when the user has
+ *
+ * @param outerView The main ProseMirror EditorView containing this math node.
+ * @param dir Used to indicate desired cursor position upon closing a math node.
+ * When set to -1, cursor will be placed BEFORE the math node.
+ * When set to +1, cursor will be placed AFTER the math node.
+ * @param borderMode An exit condition based on cursor position and direction.
+ * @param requireEmptySelection When TRUE, only exit the math node when the
+ * (inner) selection is empty.
+ * @returns A new ProseMirror command based on the input configuration.
+ */
+export declare function collapseMathCmd(outerView: EditorView, dir: 1 | -1, requireOnBorder: boolean, requireEmptySelection?: boolean): Command;
diff --git a/packages/editor/dist/extensions/math/plugin/commands/collapse-math-cmd.js b/packages/editor/dist/extensions/math/plugin/commands/collapse-math-cmd.js
new file mode 100644
index 000000000..617ed9838
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/commands/collapse-math-cmd.js
@@ -0,0 +1,51 @@
+import { TextSelection } from "prosemirror-state";
+/**
+ * A ProseMirror command for determining whether to exit a math block, based on
+ * specific conditions. Normally called when the user has
+ *
+ * @param outerView The main ProseMirror EditorView containing this math node.
+ * @param dir Used to indicate desired cursor position upon closing a math node.
+ * When set to -1, cursor will be placed BEFORE the math node.
+ * When set to +1, cursor will be placed AFTER the math node.
+ * @param borderMode An exit condition based on cursor position and direction.
+ * @param requireEmptySelection When TRUE, only exit the math node when the
+ * (inner) selection is empty.
+ * @returns A new ProseMirror command based on the input configuration.
+ */
+export function collapseMathCmd(outerView, dir, requireOnBorder, requireEmptySelection) {
+ if (requireEmptySelection === void 0) { requireEmptySelection = true; }
+ // create a new ProseMirror command based on the input conditions
+ return function (innerState, dispatch) {
+ // get selection info
+ var outerState = outerView.state;
+ var _a = outerState.selection, outerTo = _a.to, outerFrom = _a.from;
+ var _b = innerState.selection, innerTo = _b.to, innerFrom = _b.from;
+ // only exit math node when selection is empty
+ if (requireEmptySelection && innerTo !== innerFrom) {
+ return false;
+ }
+ var currentPos = dir > 0 ? innerTo : innerFrom;
+ // when requireOnBorder is TRUE, collapse only when cursor
+ // is about to leave the bounds of the math node
+ if (requireOnBorder) {
+ // (subtract two from nodeSize to account for start and end tokens)
+ var nodeSize = innerState.doc.nodeSize - 2;
+ // early return if exit conditions not met
+ if (dir > 0 && currentPos < nodeSize) {
+ return false;
+ }
+ if (dir < 0 && currentPos > 0) {
+ return false;
+ }
+ }
+ // all exit conditions met, so close the math node by moving the cursor outside
+ if (dispatch) {
+ // set outer selection to be outside of the nodeview
+ var targetPos = dir > 0 ? outerTo : outerFrom;
+ outerView.dispatch(outerState.tr.setSelection(TextSelection.create(outerState.doc, targetPos)));
+ // must return focus to the outer view, otherwise no cursor will appear
+ outerView.focus();
+ }
+ return true;
+ };
+}
diff --git a/packages/editor/dist/extensions/math/plugin/commands/insert-math-cmd.d.ts b/packages/editor/dist/extensions/math/plugin/commands/insert-math-cmd.d.ts
new file mode 100644
index 000000000..52e3b7a12
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/commands/insert-math-cmd.d.ts
@@ -0,0 +1,12 @@
+import { Command } from "prosemirror-state";
+import { NodeType } from "prosemirror-model";
+/**
+ * Returns a new command that can be used to inserts a new math node at the
+ * user's current document position, provided that the document schema actually
+ * allows a math node to be placed there.
+ *
+ * @param mathNodeType An instance for either your math_inline or math_display
+ * NodeType. Must belong to the same schema that your EditorState uses!
+ * @param initialText (optional) The initial source content for the math editor.
+ */
+export declare function insertMathCmd(mathNodeType: NodeType, initialText?: string): Command;
diff --git a/packages/editor/dist/extensions/math/plugin/commands/insert-math-cmd.js b/packages/editor/dist/extensions/math/plugin/commands/insert-math-cmd.js
new file mode 100644
index 000000000..ce7bfcf35
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/commands/insert-math-cmd.js
@@ -0,0 +1,27 @@
+import { NodeSelection } from "prosemirror-state";
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns a new command that can be used to inserts a new math node at the
+ * user's current document position, provided that the document schema actually
+ * allows a math node to be placed there.
+ *
+ * @param mathNodeType An instance for either your math_inline or math_display
+ * NodeType. Must belong to the same schema that your EditorState uses!
+ * @param initialText (optional) The initial source content for the math editor.
+ */
+export function insertMathCmd(mathNodeType, initialText) {
+ if (initialText === void 0) { initialText = ""; }
+ return function (state, dispatch) {
+ var $from = state.selection.$from, index = $from.index();
+ if (!$from.parent.canReplaceWith(index, index, mathNodeType)) {
+ return false;
+ }
+ if (dispatch) {
+ var mathNode = mathNodeType.create({}, initialText ? state.schema.text(initialText) : null);
+ var tr = state.tr.replaceSelectionWith(mathNode);
+ tr = tr.setSelection(NodeSelection.create(tr.doc, $from.pos));
+ dispatch(tr);
+ }
+ return true;
+ };
+}
diff --git a/packages/editor/dist/extensions/math/plugin/commands/move-cursor-cmd.d.ts b/packages/editor/dist/extensions/math/plugin/commands/move-cursor-cmd.d.ts
new file mode 100644
index 000000000..d1361e53e
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/commands/move-cursor-cmd.d.ts
@@ -0,0 +1,10 @@
+import { Command } from "prosemirror-state";
+/**
+ * Some browsers (cough firefox cough) don't properly handle cursor movement on
+ * the edges of a NodeView, so we need to make the desired behavior explicit.
+ *
+ * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1252108
+ */
+export declare function nudgeCursorCmd(dir: -1 | 0 | 1): Command;
+export declare const nudgeCursorForwardCmd: Command;
+export declare const nudgeCursorBackCmd: Command;
diff --git a/packages/editor/dist/extensions/math/plugin/commands/move-cursor-cmd.js b/packages/editor/dist/extensions/math/plugin/commands/move-cursor-cmd.js
new file mode 100644
index 000000000..2421f67fd
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/commands/move-cursor-cmd.js
@@ -0,0 +1,25 @@
+import { TextSelection } from "prosemirror-state";
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Some browsers (cough firefox cough) don't properly handle cursor movement on
+ * the edges of a NodeView, so we need to make the desired behavior explicit.
+ *
+ * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1252108
+ */
+export function nudgeCursorCmd(dir) {
+ return function (innerState, dispatch) {
+ var _a = innerState.selection, to = _a.to, from = _a.from;
+ // compute target position
+ var emptySelection = to === from;
+ var currentPos = dir < 0 ? from : to;
+ var increment = emptySelection ? dir : 0;
+ var nodeSize = innerState.doc.nodeSize;
+ var targetPos = Math.max(0, Math.min(nodeSize, currentPos + increment));
+ if (dispatch) {
+ dispatch(innerState.tr.setSelection(TextSelection.create(innerState.doc, targetPos)));
+ }
+ return true;
+ };
+}
+export var nudgeCursorForwardCmd = nudgeCursorCmd(+1);
+export var nudgeCursorBackCmd = nudgeCursorCmd(-1);
diff --git a/packages/editor/dist/extensions/math/plugin/index.d.ts b/packages/editor/dist/extensions/math/plugin/index.d.ts
new file mode 100644
index 000000000..aac183ae8
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/index.d.ts
@@ -0,0 +1,9 @@
+export { MathView, type ICursorPosObserver } from "./math-node-view";
+export { mathPlugin, createMathView, type IMathPluginState, } from "./math-plugin";
+export { mathSchemaSpec, createMathSchema } from "./math-schema";
+export { mathBackspaceCmd } from "./plugins/math-backspace";
+export { makeBlockMathInputRule, makeInlineMathInputRule, REGEX_BLOCK_MATH_DOLLARS, REGEX_INLINE_MATH_DOLLARS, REGEX_INLINE_MATH_DOLLARS_ESCAPED, } from "./plugins/math-input-rules";
+export { mathSelectPlugin } from "./plugins/math-select";
+export { insertMathCmd } from "./commands/insert-math-cmd";
+export { mathSerializer } from "./utils/text-serializer";
+export * from "./utils/types";
diff --git a/packages/editor/dist/extensions/math/plugin/index.js b/packages/editor/dist/extensions/math/plugin/index.js
new file mode 100644
index 000000000..5433d8045
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/index.js
@@ -0,0 +1,18 @@
+/*---------------------------------------------------------
+ * Author: Benjamin R. Bray
+ * License: MIT (see LICENSE in project root for details)
+ *--------------------------------------------------------*/
+// core functionality
+export { MathView } from "./math-node-view";
+export { mathPlugin, createMathView, } from "./math-plugin";
+export { mathSchemaSpec, createMathSchema } from "./math-schema";
+// recommended plugins
+export { mathBackspaceCmd } from "./plugins/math-backspace";
+export { makeBlockMathInputRule, makeInlineMathInputRule, REGEX_BLOCK_MATH_DOLLARS, REGEX_INLINE_MATH_DOLLARS, REGEX_INLINE_MATH_DOLLARS_ESCAPED, } from "./plugins/math-input-rules";
+// optional / experimental plugins
+export { mathSelectPlugin } from "./plugins/math-select";
+// commands
+export { insertMathCmd } from "./commands/insert-math-cmd";
+// utilities
+export { mathSerializer } from "./utils/text-serializer";
+export * from "./utils/types";
diff --git a/packages/editor/dist/extensions/math/plugin/math-nodeview.d.ts b/packages/editor/dist/extensions/math/plugin/math-nodeview.d.ts
new file mode 100644
index 000000000..b11bb5d34
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/math-nodeview.d.ts
@@ -0,0 +1,66 @@
+import { Node as ProseNode } from "prosemirror-model";
+import { EditorState, Transaction, PluginKey } from "prosemirror-state";
+import { NodeView, EditorView, Decoration, DecorationSource } from "prosemirror-view";
+import { IMathPluginState } from "./math-plugin";
+import { MathRenderFn } from "./renderers/types";
+export interface ICursorPosObserver {
+ /** indicates on which side cursor should appear when this node is selected */
+ cursorSide: "start" | "end";
+ /** */
+ updateCursorPos(state: EditorState): void;
+}
+interface IMathViewOptions {
+ /** Dom element name to use for this NodeView */
+ tagName?: string;
+ /** Used to render the Tex input */
+ renderer: MathRenderFn;
+ /** Should be true if node is inline */
+ inline?: boolean;
+}
+export declare class MathView implements NodeView, ICursorPosObserver {
+ private _node;
+ private _outerView;
+ private _getPos;
+ dom: HTMLElement;
+ private _mathRenderElt;
+ private _mathSrcElt;
+ private _innerView;
+ cursorSide: "start" | "end";
+ private _tagName;
+ private _isEditing;
+ private _mathPluginKey;
+ private options;
+ /**
+ * @param onDestroy Callback for when this NodeView is destroyed.
+ * This NodeView should unregister itself from the list of ICursorPosObservers.
+ *
+ * Math Views support the following options:
+ * @option displayMode If TRUE, will render math in display mode, otherwise in inline mode.
+ * @option tagName HTML tag name to use for this NodeView. If none is provided,
+ * will use the node name with underscores converted to hyphens.
+ */
+ constructor(node: ProseNode, view: EditorView, getPos: () => number, options: IMathViewOptions, mathPluginKey: PluginKey, onDestroy?: () => void);
+ destroy(): void;
+ /**
+ * Ensure focus on the inner editor whenever this node has focus.
+ * This helps to prevent accidental deletions of math blocks.
+ */
+ ensureFocus(): void;
+ update(node: ProseNode, _decorations: readonly Decoration[], _innerDecorations: DecorationSource): boolean;
+ updateCursorPos(state: EditorState): void;
+ selectNode(): void;
+ deselectNode(): void;
+ stopEvent(event: Event): boolean;
+ ignoreMutation(): boolean;
+ renderMath(): void;
+ dispatchInner(tr: Transaction): void;
+ openEditor(): void;
+ /**
+ * Called when the inner ProseMirror editor should close.
+ *
+ * @param render Optionally update the rendered math after closing. (which
+ * is generally what we want to do, since the user is done editing!)
+ */
+ closeEditor(render?: boolean): void;
+}
+export {};
diff --git a/packages/editor/dist/extensions/math/plugin/math-nodeview.js b/packages/editor/dist/extensions/math/plugin/math-nodeview.js
new file mode 100644
index 000000000..43e424707
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/math-nodeview.js
@@ -0,0 +1,282 @@
+/*---------------------------------------------------------
+ * Author: Benjamin R. Bray
+ * License: MIT (see LICENSE in project root for details)
+ *--------------------------------------------------------*/
+import { EditorState, TextSelection, } from "prosemirror-state";
+import { EditorView, } from "prosemirror-view";
+import { StepMap } from "prosemirror-transform";
+import { keymap } from "prosemirror-keymap";
+import { newlineInCode, chainCommands, deleteSelection, } from "prosemirror-commands";
+import { collapseMathCmd } from "./commands/collapse-math-cmd";
+var MathView = /** @class */ (function () {
+ // == Lifecycle ===================================== //
+ /**
+ * @param onDestroy Callback for when this NodeView is destroyed.
+ * This NodeView should unregister itself from the list of ICursorPosObservers.
+ *
+ * Math Views support the following options:
+ * @option displayMode If TRUE, will render math in display mode, otherwise in inline mode.
+ * @option tagName HTML tag name to use for this NodeView. If none is provided,
+ * will use the node name with underscores converted to hyphens.
+ */
+ function MathView(node, view, getPos, options, mathPluginKey, onDestroy) {
+ var _this = this;
+ // store arguments
+ this.options = options;
+ this._node = node;
+ this._outerView = view;
+ this._getPos = getPos;
+ this._mathPluginKey = mathPluginKey;
+ // editing state
+ this.cursorSide = "start";
+ this._isEditing = false;
+ // options
+ this._tagName = options.tagName || this._node.type.name.replace("_", "-");
+ // create dom representation of nodeview
+ this.dom = document.createElement(this._tagName);
+ if (options.inline)
+ this.dom.classList.add("math-inline");
+ else
+ this.dom.classList.add("math-display");
+ this.dom.classList.add("math-node");
+ this._mathRenderElt = document.createElement("span");
+ this._mathRenderElt.textContent = "";
+ this._mathRenderElt.classList.add("math-render");
+ this.dom.appendChild(this._mathRenderElt);
+ this._mathSrcElt = document.createElement("span");
+ this._mathSrcElt.classList.add("math-src");
+ this.dom.appendChild(this._mathSrcElt);
+ // ensure
+ this.dom.addEventListener("click", function () { return _this.ensureFocus(); });
+ // render initial content
+ this.renderMath();
+ }
+ MathView.prototype.destroy = function () {
+ // close the inner editor without rendering
+ this.closeEditor(false);
+ // clean up dom elements
+ if (this._mathRenderElt) {
+ this._mathRenderElt.remove();
+ delete this._mathRenderElt;
+ }
+ if (this._mathSrcElt) {
+ this._mathSrcElt.remove();
+ delete this._mathSrcElt;
+ }
+ this.dom.remove();
+ };
+ /**
+ * Ensure focus on the inner editor whenever this node has focus.
+ * This helps to prevent accidental deletions of math blocks.
+ */
+ MathView.prototype.ensureFocus = function () {
+ if (this._innerView && this._outerView.hasFocus()) {
+ this._innerView.focus();
+ }
+ };
+ // == Updates ======================================= //
+ MathView.prototype.update = function (node, _decorations, _innerDecorations) {
+ if (!node.sameMarkup(this._node))
+ return false;
+ this._node = node;
+ if (this._innerView) {
+ var state = this._innerView.state;
+ var start = node.content.findDiffStart(state.doc.content);
+ if (start != null) {
+ var diff = node.content.findDiffEnd(state.doc.content);
+ if (diff) {
+ var endA = diff.a, endB = diff.b;
+ var overlap = start - Math.min(endA, endB);
+ if (overlap > 0) {
+ endA += overlap;
+ endB += overlap;
+ }
+ this._innerView.dispatch(state.tr
+ .replace(start, endB, node.slice(start, endA))
+ .setMeta("fromOutside", true));
+ }
+ }
+ }
+ if (!this._isEditing) {
+ this.renderMath();
+ }
+ return true;
+ };
+ MathView.prototype.updateCursorPos = function (state) {
+ var pos = this._getPos();
+ var size = this._node.nodeSize;
+ var inPmSelection = state.selection.from < pos + size && pos < state.selection.to;
+ if (!inPmSelection) {
+ this.cursorSide = pos < state.selection.from ? "end" : "start";
+ }
+ };
+ // == Events ===================================== //
+ MathView.prototype.selectNode = function () {
+ if (!this._outerView.editable) {
+ return;
+ }
+ this.dom.classList.add("ProseMirror-selectednode");
+ if (!this._isEditing) {
+ this.openEditor();
+ }
+ };
+ MathView.prototype.deselectNode = function () {
+ this.dom.classList.remove("ProseMirror-selectednode");
+ if (this._isEditing) {
+ this.closeEditor();
+ }
+ };
+ MathView.prototype.stopEvent = function (event) {
+ return (this._innerView !== undefined &&
+ event.target !== undefined &&
+ this._innerView.dom.contains(event.target));
+ };
+ MathView.prototype.ignoreMutation = function () {
+ return true;
+ };
+ // == Rendering ===================================== //
+ MathView.prototype.renderMath = function () {
+ if (!this._mathRenderElt) {
+ return;
+ }
+ // get tex string to render
+ var content = this._node.content.content;
+ var texString = "";
+ if (content.length > 0 && content[0].textContent !== null) {
+ texString = content[0].textContent.trim();
+ }
+ // empty math?
+ if (texString.length < 1) {
+ this.dom.classList.add("empty-math");
+ // clear rendered math, since this node is in an invalid state
+ while (this._mathRenderElt.firstChild) {
+ this._mathRenderElt.firstChild.remove();
+ }
+ // do not render empty math
+ return;
+ }
+ else {
+ this.dom.classList.remove("empty-math");
+ }
+ // render katex, but fail gracefully
+ try {
+ this.options.renderer(texString, this._mathRenderElt);
+ this._mathRenderElt.classList.remove("parse-error");
+ this.dom.setAttribute("title", "");
+ }
+ catch (err) {
+ if (err instanceof Error) {
+ console.error(err);
+ this._mathRenderElt.classList.add("parse-error");
+ this.dom.setAttribute("title", err.toString());
+ }
+ }
+ };
+ // == Inner Editor ================================== //
+ MathView.prototype.dispatchInner = function (tr) {
+ if (!this._innerView) {
+ return;
+ }
+ var _a = this._innerView.state.applyTransaction(tr), state = _a.state, transactions = _a.transactions;
+ this._innerView.updateState(state);
+ if (!tr.getMeta("fromOutside")) {
+ var outerTr = this._outerView.state.tr, offsetMap = StepMap.offset(this._getPos() + 1);
+ for (var i = 0; i < transactions.length; i++) {
+ var steps = transactions[i].steps;
+ for (var j = 0; j < steps.length; j++) {
+ var mapped = steps[j].map(offsetMap);
+ if (!mapped) {
+ throw Error("step discarded!");
+ }
+ outerTr.step(mapped);
+ }
+ }
+ if (outerTr.docChanged)
+ this._outerView.dispatch(outerTr);
+ }
+ };
+ MathView.prototype.openEditor = function () {
+ var _this = this;
+ var _a;
+ if (this._innerView) {
+ throw Error("inner view should not exist!");
+ }
+ if (!this._mathSrcElt)
+ throw new Error("_mathSrcElt does not exist!");
+ // create a nested ProseMirror view
+ this._innerView = new EditorView(this._mathSrcElt, {
+ state: EditorState.create({
+ doc: this._node,
+ plugins: [
+ keymap({
+ Tab: function (state, dispatch) {
+ if (dispatch) {
+ dispatch(state.tr.insertText("\t"));
+ }
+ return true;
+ },
+ Backspace: chainCommands(deleteSelection, function (state, dispatch, tr_inner) {
+ // default backspace behavior for non-empty selections
+ if (!state.selection.empty) {
+ return false;
+ }
+ // default backspace behavior when math node is non-empty
+ if (_this._node.textContent.length > 0) {
+ return false;
+ }
+ // otherwise, we want to delete the empty math node and focus the outer view
+ _this._outerView.dispatch(_this._outerView.state.tr.insertText(""));
+ _this._outerView.focus();
+ return true;
+ }),
+ // "Ctrl-Backspace": (state, dispatch, tr_inner) => {
+ // // delete math node and focus the outer view
+ // this._outerView.dispatch(this._outerView.state.tr.insertText(""));
+ // this._outerView.focus();
+ // return true;
+ // },
+ Enter: chainCommands(newlineInCode, collapseMathCmd(this._outerView, +1, false)),
+ "Ctrl-Enter": collapseMathCmd(this._outerView, +1, false),
+ ArrowLeft: collapseMathCmd(this._outerView, -1, true),
+ ArrowRight: collapseMathCmd(this._outerView, +1, true),
+ ArrowUp: collapseMathCmd(this._outerView, -1, true),
+ ArrowDown: collapseMathCmd(this._outerView, +1, true),
+ }),
+ ],
+ }),
+ dispatchTransaction: this.dispatchInner.bind(this),
+ });
+ // focus element
+ var innerState = this._innerView.state;
+ this._innerView.focus();
+ // request outer cursor position before math node was selected
+ var maybePos = (_a = this._mathPluginKey.getState(this._outerView.state)) === null || _a === void 0 ? void 0 : _a.prevCursorPos;
+ if (maybePos === null || maybePos === undefined) {
+ console.error("[prosemirror-math] Error: Unable to fetch math plugin state from key.");
+ }
+ var prevCursorPos = maybePos !== null && maybePos !== void 0 ? maybePos : 0;
+ // compute position that cursor should appear within the expanded math node
+ var innerPos = prevCursorPos <= this._getPos() ? 0 : this._node.nodeSize - 2;
+ this._innerView.dispatch(innerState.tr.setSelection(TextSelection.create(innerState.doc, innerPos)));
+ this._isEditing = true;
+ };
+ /**
+ * Called when the inner ProseMirror editor should close.
+ *
+ * @param render Optionally update the rendered math after closing. (which
+ * is generally what we want to do, since the user is done editing!)
+ */
+ MathView.prototype.closeEditor = function (render) {
+ if (render === void 0) { render = true; }
+ if (this._innerView) {
+ this._innerView.destroy();
+ this._innerView = undefined;
+ }
+ if (render) {
+ this.renderMath();
+ }
+ this._isEditing = false;
+ };
+ return MathView;
+}());
+export { MathView };
diff --git a/packages/editor/dist/extensions/math/plugin/math-plugin.d.ts b/packages/editor/dist/extensions/math/plugin/math-plugin.d.ts
new file mode 100644
index 000000000..b7bd86a3f
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/math-plugin.d.ts
@@ -0,0 +1,24 @@
+import { Node as ProseNode } from "prosemirror-model";
+import { Plugin as ProsePlugin } from "prosemirror-state";
+import { MathView } from "./math-node-view";
+import { EditorView } from "prosemirror-view";
+export interface IMathPluginState {
+ macros: {
+ [cmd: string]: string;
+ };
+ /** A list of currently active `NodeView`s, in insertion order. */
+ activeNodeViews: MathView[];
+ /**
+ * Used to determine whether to place the cursor in the front- or back-most
+ * position when expanding a math node, without overriding the default arrow
+ * key behavior.
+ */
+ prevCursorPos: number;
+}
+/**
+ * Returns a function suitable for passing as a field in `EditorProps.nodeViews`.
+ * @param inline TRUE for block math, FALSE for inline math.
+ * @see https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews
+ */
+export declare function createMathView(inline: boolean): (node: ProseNode, view: EditorView, getPos: boolean | (() => number)) => MathView;
+export declare const mathPlugin: ProsePlugin;
diff --git a/packages/editor/dist/extensions/math/plugin/math-plugin.js b/packages/editor/dist/extensions/math/plugin/math-plugin.js
new file mode 100644
index 000000000..f5d52a27e
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/math-plugin.js
@@ -0,0 +1,71 @@
+/*---------------------------------------------------------
+ * Author: Benjamin R. Bray
+ * License: MIT (see LICENSE in project root for details)
+ *--------------------------------------------------------*/
+import { Plugin as ProsePlugin, PluginKey, } from "prosemirror-state";
+import { MathView } from "./math-node-view";
+import { KatexRenderer } from "./renderers/katex";
+// uniquely identifies the prosemirror-math plugin
+var MATH_PLUGIN_KEY = new PluginKey("prosemirror-math");
+/**
+ * Returns a function suitable for passing as a field in `EditorProps.nodeViews`.
+ * @param inline TRUE for block math, FALSE for inline math.
+ * @see https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews
+ */
+export function createMathView(inline) {
+ return function (node, view, getPos) {
+ /** @todo is this necessary?
+ * Docs says that for any function proprs, the current plugin instance
+ * will be bound to `this`. However, the typings don't reflect this.
+ */
+ var pluginState = MATH_PLUGIN_KEY.getState(view.state);
+ if (!pluginState) {
+ throw new Error("no math plugin!");
+ }
+ var nodeViews = pluginState.activeNodeViews;
+ // set up NodeView
+ var nodeView = new MathView(node, view, getPos, {
+ inline: inline,
+ renderer: inline ? KatexRenderer.inline : KatexRenderer.block,
+ tagName: inline ? "span" : "div",
+ }, MATH_PLUGIN_KEY, function () {
+ nodeViews.splice(nodeViews.indexOf(nodeView));
+ });
+ nodeViews.push(nodeView);
+ return nodeView;
+ };
+}
+var mathPluginSpec = {
+ key: MATH_PLUGIN_KEY,
+ state: {
+ init: function (config, instance) {
+ return {
+ macros: {},
+ activeNodeViews: [],
+ prevCursorPos: 0,
+ };
+ },
+ apply: function (tr, value, oldState, newState) {
+ // produce updated state field for this plugin
+ var newPos = newState.selection.from;
+ var oldPos = oldState.selection.from;
+ return {
+ // these values are left unchanged
+ activeNodeViews: value.activeNodeViews,
+ macros: value.macros,
+ // update with the second-most recent cursor pos
+ prevCursorPos: oldPos !== newPos ? oldPos : value.prevCursorPos,
+ };
+ },
+ /** @todo (8/21/20) implement serialization for math plugin */
+ // toJSON(value) { },
+ // fromJSON(config, value, state){ return {}; }
+ },
+ props: {
+ nodeViews: {
+ math_inline: createMathView(true),
+ math_display: createMathView(false),
+ },
+ },
+};
+export var mathPlugin = new ProsePlugin(mathPluginSpec);
diff --git a/packages/editor/dist/extensions/math/plugin/math-schema.d.ts b/packages/editor/dist/extensions/math/plugin/math-schema.d.ts
new file mode 100644
index 000000000..8331ba152
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/math-schema.d.ts
@@ -0,0 +1,45 @@
+import { MarkSpec, NodeSpec, Schema, SchemaSpec } from "prosemirror-model";
+import { SchemaSpecMarkT, SchemaSpecNodeT } from "./utils/types";
+/**
+ * Borrowed from ProseMirror typings, modified to exclude OrderedMaps in spec,
+ * in order to help with the schema-building functions below.
+ *
+ * NOTE: TypeScript's typings for the spread operator { ...a, ...b } are only
+ * an approximation to the true type, and have difficulty with optional fields.
+ * So, unlike the SchemaSpec type, the `marks` field is NOT optional here.
+ *
+ * function example(x: { [name in T]: string; } | null) {
+ * const s = { ...x }; // inferred to have type `{}`.
+ * }
+ *
+ * @see https://github.com/microsoft/TypeScript/issues/10727
+ */
+interface SchemaSpecJson extends SchemaSpec {
+ nodes: {
+ [name in N]: NodeSpec;
+ };
+ marks: {
+ [name in M]: MarkSpec;
+ };
+ topNode?: string;
+}
+declare type MathSpecNodeT = SchemaSpecNodeT;
+declare type MathSpecMarkT = SchemaSpecMarkT;
+export declare const mathSchemaSpec: SchemaSpecJson<"math_inline" | "paragraph" | "text" | "doc" | "math_display", "math_select">;
+/**
+ * Use the prosemirror-math default SchemaSpec to create a new Schema.
+ */
+export declare function createMathSchema(): Schema<"math_inline" | "paragraph" | "text" | "doc" | "math_display", "math_select">;
+/**
+ * Create a new SchemaSpec by adding math nodes to an existing spec.
+
+ * @deprecated This function is included for demonstration/testing only. For the
+ * time being, I highly recommend adding the math nodes manually to your own
+ * ProseMirror spec to avoid unexpected interactions between the math nodes
+ * and your own spec. Use the example spec for reference.
+ *
+ * @param baseSpec The SchemaSpec to extend. Must specify a `marks` field, and
+ * must be a raw object (not an OrderedMap).
+ */
+export declare function extendMathSchemaSpec(baseSpec: SchemaSpecJson): SchemaSpecJson;
+export {};
diff --git a/packages/editor/dist/extensions/math/plugin/math-schema.js b/packages/editor/dist/extensions/math/plugin/math-schema.js
new file mode 100644
index 000000000..b8384789e
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/math-schema.js
@@ -0,0 +1,114 @@
+/*---------------------------------------------------------
+ * Author: Benjamin R. Bray
+ * License: MIT (see LICENSE in project root for details)
+ *--------------------------------------------------------*/
+var __assign = (this && this.__assign) || function () {
+ __assign = Object.assign || function(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
+ t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
+};
+var __read = (this && this.__read) || function (o, n) {
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
+ if (!m) return o;
+ var i = m.call(o), r, ar = [], e;
+ try {
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
+ }
+ catch (error) { e = { error: error }; }
+ finally {
+ try {
+ if (r && !r.done && (m = i["return"])) m.call(i);
+ }
+ finally { if (e) throw e.error; }
+ }
+ return ar;
+};
+var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
+ if (ar || !(i in from)) {
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
+ ar[i] = from[i];
+ }
+ }
+ return to.concat(ar || Array.prototype.slice.call(from));
+};
+// prosemirror imports
+import { Schema, } from "prosemirror-model";
+import { defaultBlockMathParseRules, defaultInlineMathParseRules, } from "./plugins/math-paste-rules";
+////////////////////////////////////////////////////////////
+// force typescript to infer generic type arguments for SchemaSpec
+function createSchemaSpec(spec) {
+ return spec;
+}
+// bare minimum ProseMirror schema for working with math nodes
+export var mathSchemaSpec = createSchemaSpec({
+ nodes: {
+ // :: NodeSpec top-level document node
+ doc: {
+ content: "block+",
+ },
+ paragraph: {
+ content: "inline*",
+ group: "block",
+ parseDOM: [{ tag: "p" }],
+ toDOM: function () {
+ return ["p", 0];
+ },
+ },
+ math_inline: {
+ group: "inline math",
+ content: "text*",
+ inline: true,
+ atom: true,
+ toDOM: function () { return ["math-inline", { class: "math-node" }, 0]; },
+ parseDOM: __spreadArray([{ tag: "math-inline" }], __read(defaultInlineMathParseRules), false),
+ },
+ math_display: {
+ group: "block math",
+ content: "text*",
+ atom: true,
+ code: true,
+ toDOM: function () { return ["math-display", { class: "math-node" }, 0]; },
+ parseDOM: __spreadArray([{ tag: "math-display" }], __read(defaultBlockMathParseRules), false),
+ },
+ text: {
+ group: "inline",
+ },
+ },
+ marks: {
+ math_select: {
+ toDOM: function () {
+ return ["math-select", 0];
+ },
+ parseDOM: [{ tag: "math-select" }],
+ },
+ },
+});
+/**
+ * Use the prosemirror-math default SchemaSpec to create a new Schema.
+ */
+export function createMathSchema() {
+ return new Schema(mathSchemaSpec);
+}
+/**
+ * Create a new SchemaSpec by adding math nodes to an existing spec.
+
+ * @deprecated This function is included for demonstration/testing only. For the
+ * time being, I highly recommend adding the math nodes manually to your own
+ * ProseMirror spec to avoid unexpected interactions between the math nodes
+ * and your own spec. Use the example spec for reference.
+ *
+ * @param baseSpec The SchemaSpec to extend. Must specify a `marks` field, and
+ * must be a raw object (not an OrderedMap).
+ */
+export function extendMathSchemaSpec(baseSpec) {
+ var nodes = __assign(__assign({}, baseSpec.nodes), mathSchemaSpec.nodes);
+ var marks = __assign(__assign({}, baseSpec.marks), mathSchemaSpec.marks);
+ return { nodes: nodes, marks: marks, topNode: baseSpec.topNode };
+}
diff --git a/packages/editor/dist/extensions/math/plugin/plugins/math-backspace.d.ts b/packages/editor/dist/extensions/math/plugin/plugins/math-backspace.d.ts
new file mode 100644
index 000000000..634f31931
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/plugins/math-backspace.d.ts
@@ -0,0 +1,2 @@
+import { Command as ProseCommand } from "prosemirror-state";
+export declare const mathBackspaceCmd: ProseCommand;
diff --git a/packages/editor/dist/extensions/math/plugin/plugins/math-backspace.js b/packages/editor/dist/extensions/math/plugin/plugins/math-backspace.js
new file mode 100644
index 000000000..23646606f
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/plugins/math-backspace.js
@@ -0,0 +1,25 @@
+import { NodeSelection } from "prosemirror-state";
+export var mathBackspaceCmd = function (state, dispatch) {
+ // check node before
+ var $from = state.selection.$from;
+ var nodeBefore = $from.nodeBefore;
+ if (!nodeBefore) {
+ return false;
+ }
+ if (nodeBefore.type.name == "math_inline") {
+ // select math node
+ var index = $from.index($from.depth);
+ var $beforePos = state.doc.resolve($from.posAtIndex(index - 1));
+ if (dispatch) {
+ dispatch(state.tr.setSelection(new NodeSelection($beforePos)));
+ }
+ return true;
+ }
+ else if (nodeBefore.type.name == "math_block") {
+ /** @todo (8/1/20) implement backspace for math blocks
+ * check how code blocks behave when pressing backspace
+ */
+ return false;
+ }
+ return false;
+};
diff --git a/packages/editor/dist/extensions/math/plugin/plugins/math-inputrules.d.ts b/packages/editor/dist/extensions/math/plugin/plugins/math-inputrules.d.ts
new file mode 100644
index 000000000..92f1be7e5
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/plugins/math-inputrules.d.ts
@@ -0,0 +1,7 @@
+import { InputRule } from "prosemirror-inputrules";
+import { NodeType } from "prosemirror-model";
+export declare const REGEX_INLINE_MATH_DOLLARS: RegExp;
+export declare const REGEX_INLINE_MATH_DOLLARS_ESCAPED: RegExp;
+export declare const REGEX_BLOCK_MATH_DOLLARS: RegExp;
+export declare function makeInlineMathInputRule(pattern: RegExp, nodeType: NodeType, getAttrs?: (match: string[]) => any): InputRule;
+export declare function makeBlockMathInputRule(pattern: RegExp, nodeType: NodeType, getAttrs?: (match: string[]) => any): InputRule;
diff --git a/packages/editor/dist/extensions/math/plugin/plugins/math-inputrules.js b/packages/editor/dist/extensions/math/plugin/plugins/math-inputrules.js
new file mode 100644
index 000000000..6b4868f8f
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/plugins/math-inputrules.js
@@ -0,0 +1,55 @@
+/*---------------------------------------------------------
+ * Author: Benjamin R. Bray
+ * License: MIT (see LICENSE in project root for details)
+ *--------------------------------------------------------*/
+import { InputRule } from "prosemirror-inputrules";
+import { NodeSelection } from "prosemirror-state";
+////////////////////////////////////////////////////////////
+// ---- Inline Input Rules ------------------------------ //
+// simple input rule for inline math
+export var REGEX_INLINE_MATH_DOLLARS = /\$\$(.+)\$\$/; //new RegExp("\$(.+)\$", "i");
+// negative lookbehind regex notation allows for escaped \$ delimiters
+// (requires browser supporting ECMA2018 standard -- currently only Chrome / FF)
+// (see https://javascript.info/regexp-lookahead-lookbehind)
+export var REGEX_INLINE_MATH_DOLLARS_ESCAPED = (function () {
+ // attempt to create regex with negative lookbehind
+ try {
+ return new RegExp("(?... element, as below.
+ *
+ * - Evidently no CSS class is used to distinguish inline vs block math
+ * - Sometimes the `\displaystyle` TeX command is present even in inline math
+ *
+ * ```html
+ * -
+ *
+ *
+ *
+ *
+ *
+ * ```
+ */
+export declare const wikipediaBlockMathParseRule: ParseRule;
+/**
+ * Parse rule for inline math content on Wikipedia of the following form:
+ *
+ * ```html
+ *
+ *
+ *
+ *
+ *
+ *
+ * ```
+ */
+export declare const wikipediaInlineMathParseRule: ParseRule;
+export declare const defaultInlineMathParseRules: ParseRule[];
+export declare const defaultBlockMathParseRules: ParseRule[];
diff --git a/packages/editor/dist/extensions/math/plugin/plugins/math-paste-rules.js b/packages/editor/dist/extensions/math/plugin/plugins/math-paste-rules.js
new file mode 100644
index 000000000..bc92772b6
--- /dev/null
+++ b/packages/editor/dist/extensions/math/plugin/plugins/math-paste-rules.js
@@ -0,0 +1,193 @@
+/**
+ * Note that for some of the `ParseRule`s defined below,
+ * we define a `getAttrs` function, which, other than
+ * defining node attributes, can be used to describe complex
+ * match conditions for a rule.
+
+ * Returning `false` from `ParseRule.getAttrs` prevents the
+ * rule from matching, while returning `null` indicates that
+ * the default set of note attributes should be used.
+ */
+var __values = (this && this.__values) || function(o) {
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
+ if (m) return m.call(o);
+ if (o && typeof o.length === "number") return {
+ next: function () {
+ if (o && i >= o.length) o = void 0;
+ return { value: o && o[i++], done: !o };
+ }
+ };
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
+};
+import { Fragment, } from "prosemirror-model";
+////////////////////////////////////////////////////////////
+function getFirstMatch(root, rules) {
+ var e_1, _a;
+ try {
+ for (var rules_1 = __values(rules), rules_1_1 = rules_1.next(); !rules_1_1.done; rules_1_1 = rules_1.next()) {
+ var rule = rules_1_1.value;
+ var match = rule(root);
+ if (match !== false) {
+ return match;
+ }
+ }
+ }
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
+ finally {
+ try {
+ if (rules_1_1 && !rules_1_1.done && (_a = rules_1.return)) _a.call(rules_1);
+ }
+ finally { if (e_1) throw e_1.error; }
+ }
+ return false;
+}
+function makeTextFragment(text, schema) {
+ return Fragment.from(schema.text(text));
+}
+////////////////////////////////////////////////////////////
+// -- Wikipedia ----------------------------------------- //
+/**
+ * Look for a child node that matches the following template:
+ *
+ */
+function texFromMediaWikiFallbackImage(root) {
+ var _a;
+ var match = root.querySelector("img.mwe-math-fallback-image-inline[alt]");
+ return (_a = match === null || match === void 0 ? void 0 : match.getAttribute("alt")) !== null && _a !== void 0 ? _a : false;
+}
+/**
+ * Look for a child node that matches the following template:
+ *