mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
aadf47f2d7
CodeQL flagged incomplete string escaping: escaping pipes as \| without escaping pre-existing backslashes leaves the encoding ambiguous. Escape the backslash (the escape character) and pipe together in a single pass so cell content cannot break out of the column. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
75 lines
1.9 KiB
TypeScript
75 lines
1.9 KiB
TypeScript
import {
|
|
makeBlockMathInputRule,
|
|
mathSchemaSpec,
|
|
} from "@benrbray/prosemirror-math";
|
|
import type { PluginSimple } from "markdown-it";
|
|
import type {
|
|
NodeSpec,
|
|
NodeType,
|
|
Node as ProsemirrorNode,
|
|
} from "prosemirror-model";
|
|
import type { Command } from "prosemirror-state";
|
|
import { TextSelection } from "prosemirror-state";
|
|
import type { MarkdownSerializerState } from "../lib/markdown/serializer";
|
|
import mathRule, { REGEX_BLOCK_MATH_DOLLARS } from "../rules/math";
|
|
import Node from "./Node";
|
|
|
|
export default class MathBlock extends Node {
|
|
get name() {
|
|
return "math_block";
|
|
}
|
|
|
|
get schema(): NodeSpec {
|
|
return mathSchemaSpec.nodes.math_display;
|
|
}
|
|
|
|
get rulePlugins(): PluginSimple[] {
|
|
return [mathRule];
|
|
}
|
|
|
|
commands({ type }: { type: NodeType }) {
|
|
return (): Command => (state, dispatch) => {
|
|
const tr = state.tr.replaceSelectionWith(type.create());
|
|
dispatch?.(
|
|
tr
|
|
.setSelection(
|
|
TextSelection.near(tr.doc.resolve(state.selection.from - 1))
|
|
)
|
|
.scrollIntoView()
|
|
);
|
|
return true;
|
|
};
|
|
}
|
|
|
|
inputRules({ type }: { type: NodeType }) {
|
|
return [makeBlockMathInputRule(REGEX_BLOCK_MATH_DOLLARS, type)];
|
|
}
|
|
|
|
toMarkdown(state: MarkdownSerializerState, node: ProsemirrorNode) {
|
|
// Inside table cells literal newlines break the row structure, so encode
|
|
// the block on a single line using <br> for line breaks. Backslashes and
|
|
// pipes are escaped so the cell content cannot break out of the column.
|
|
if (state.inTable) {
|
|
const math = node.textContent
|
|
.replace(/[\\|]/g, "\\$&")
|
|
.replace(/\n/g, "<br>");
|
|
state.write("$$<br>" + math + "<br>$$");
|
|
return;
|
|
}
|
|
|
|
state.write("$$\n");
|
|
state.text(node.textContent, false);
|
|
state.ensureNewLine();
|
|
state.write("$$");
|
|
state.closeBlock(node);
|
|
}
|
|
|
|
parseMarkdown() {
|
|
return {
|
|
node: "math_block",
|
|
block: "math_block",
|
|
noCloseToken: true,
|
|
};
|
|
}
|
|
}
|