Files
outline/shared/editor/nodes/OrderedList.ts
2023-07-29 23:42:58 -04:00

87 lines
2.1 KiB
TypeScript

import Token from "markdown-it/lib/token";
import { wrappingInputRule } from "prosemirror-inputrules";
import {
NodeSpec,
NodeType,
Schema,
Node as ProsemirrorNode,
} from "prosemirror-model";
import toggleList from "../commands/toggleList";
import { MarkdownSerializerState } from "../lib/markdown/serializer";
import Node from "./Node";
export default class OrderedList extends Node {
get name() {
return "ordered_list";
}
get schema(): NodeSpec {
return {
attrs: {
order: {
default: 1,
},
},
content: "list_item+",
group: "block list",
parseDOM: [
{
tag: "ol",
getAttrs: (dom: HTMLOListElement) => ({
order: dom.hasAttribute("start")
? parseInt(dom.getAttribute("start") || "1", 10)
: 1,
}),
},
],
toDOM: (node) =>
node.attrs.order === 1
? ["ol", 0]
: ["ol", { start: node.attrs.order }, 0],
};
}
commands({ type, schema }: { type: NodeType; schema: Schema }) {
return () => toggleList(type, schema.nodes.list_item);
}
keys({ type, schema }: { type: NodeType; schema: Schema }) {
return {
"Shift-Ctrl-9": toggleList(type, schema.nodes.list_item),
};
}
inputRules({ type }: { type: NodeType }) {
return [
wrappingInputRule(
/^(\d+)\.\s$/,
type,
(match) => ({ order: +match[1] }),
(match, node) => node.childCount + node.attrs.order === +match[1]
),
];
}
toMarkdown(state: MarkdownSerializerState, node: ProsemirrorNode) {
state.write("\n");
const start = node.attrs.order !== undefined ? node.attrs.order : 1;
const maxW = `${start + node.childCount - 1}`.length;
const space = state.repeat(" ", maxW + 2);
state.renderList(node, space, (index: number) => {
const nStr = `${start + index}`;
return state.repeat(" ", maxW - nStr.length) + nStr + ". ";
});
}
parseMarkdown() {
return {
block: "ordered_list",
getAttrs: (tok: Token) => ({
order: parseInt(tok.attrGet("start") || "1", 10),
}),
};
}
}