Files
outline/shared/editor/nodes/Math.ts
T

104 lines
2.6 KiB
TypeScript

import {
mathBackspaceCmd,
insertMathCmd,
mathSchemaSpec,
} from "@benrbray/prosemirror-math";
import type { PluginSimple } from "markdown-it";
import type {
NodeSpec,
NodeType,
Schema,
Node as ProsemirrorNode,
} from "prosemirror-model";
import type { Command, Plugin } from "prosemirror-state";
import MathPlugin from "../extensions/Math";
import type { MarkdownSerializerState } from "../lib/markdown/serializer";
import mathRule, { REGEX_INLINE_MATH_DOLLARS } from "../rules/math";
import Node from "./Node";
import { InputRule } from "prosemirror-inputrules";
import { isInCode } from "../queries/isInCode";
export default class Math extends Node {
get name() {
return "math_inline";
}
get schema(): NodeSpec {
return mathSchemaSpec.nodes.math_inline;
}
commands({ type }: { type: NodeType }) {
return (): Command => (state, dispatch) => {
dispatch?.(state.tr.replaceSelectionWith(type.create()).scrollIntoView());
return true;
};
}
inputRules({ schema }: { schema: Schema }) {
return [
new InputRule(REGEX_INLINE_MATH_DOLLARS, (state, match, start, end) => {
if (isInCode(state)) {
return null;
}
let $start = state.doc.resolve(start);
let index = $start.index();
let $end = state.doc.resolve(end);
// check if replacement valid
if (
!$start.parent.canReplaceWith(
index,
$end.index(),
schema.nodes.math_inline
)
) {
return null;
}
// perform replacement
return state.tr.replaceRangeWith(
start,
end,
schema.nodes.math_inline.create(
undefined,
schema.nodes.math_inline.schema.text(match[1])
)
);
}),
];
}
keys({ type }: { type: NodeType }) {
return {
"Mod-Space": insertMathCmd(type),
Backspace: mathBackspaceCmd,
};
}
get plugins(): Plugin[] {
return [MathPlugin];
}
get rulePlugins(): PluginSimple[] {
return [mathRule];
}
toMarkdown(state: MarkdownSerializerState, node: ProsemirrorNode) {
state.write("$");
// Pipes inside math would otherwise be mistaken for cell delimiters when
// the math appears within a table, so escape them here.
const content = state.inTable
? node.textContent.replace(/\|/g, "\\$&")
: node.textContent;
state.text(content, false);
state.write("$");
}
parseMarkdown() {
return {
node: "math_inline",
block: "math_inline",
noCloseToken: true,
};
}
}