chore: Move editor into codebase (#2930)

This commit is contained in:
Tom Moor
2022-01-19 18:43:15 -08:00
committed by GitHub
parent 266f8c96c4
commit 062016b164
216 changed files with 12417 additions and 382 deletions

View File

@@ -0,0 +1,33 @@
import { Node } from "prosemirror-model";
import { findBlockNodes, NodeWithPos } from "prosemirror-utils";
export default function findCollapsedNodes(doc: Node): NodeWithPos[] {
const blocks = findBlockNodes(doc);
const nodes: NodeWithPos[] = [];
let withinCollapsedHeading;
for (const block of blocks) {
if (block.node.type.name === "heading") {
if (
!withinCollapsedHeading ||
block.node.attrs.level <= withinCollapsedHeading
) {
if (block.node.attrs.collapsed) {
if (!withinCollapsedHeading) {
withinCollapsedHeading = block.node.attrs.level;
}
} else {
withinCollapsedHeading = undefined;
}
continue;
}
}
if (withinCollapsedHeading) {
nodes.push(block);
}
}
return nodes;
}

View File

@@ -0,0 +1,9 @@
import { CellSelection } from "prosemirror-tables";
export default function getColumnIndex(selection: CellSelection) {
const isColSelection = selection.isColSelection && selection.isColSelection();
if (!isColSelection) return undefined;
const path = (selection.$from as any).path;
return path[path.length - 5];
}

View File

@@ -0,0 +1,40 @@
import { ResolvedPos, MarkType } from "prosemirror-model";
export default function getMarkRange($pos?: ResolvedPos, type?: MarkType) {
if (!$pos || !type) {
return false;
}
const start = $pos.parent.childAfter($pos.parentOffset);
if (!start.node) {
return false;
}
const mark = start.node.marks.find((mark) => mark.type === type);
if (!mark) {
return false;
}
let startIndex = $pos.index();
let startPos = $pos.start() + start.offset;
let endIndex = startIndex + 1;
let endPos = startPos + start.node.nodeSize;
while (
startIndex > 0 &&
mark.isInSet($pos.parent.child(startIndex - 1).marks)
) {
startIndex -= 1;
startPos -= $pos.parent.child(startIndex).nodeSize;
}
while (
endIndex < $pos.parent.childCount &&
mark.isInSet($pos.parent.child(endIndex).marks)
) {
endPos += $pos.parent.child(endIndex).nodeSize;
endIndex += 1;
}
return { from: startPos, to: endPos, mark };
}

View File

@@ -0,0 +1,14 @@
import { Node } from "prosemirror-model";
import { EditorState } from "prosemirror-state";
export default function getParentListItem(
state: EditorState
): [Node, number] | void {
const $head = state.selection.$head;
for (let d = $head.depth; d > 0; d--) {
const node = $head.node(d);
if (["list_item", "checkbox_item"].includes(node.type.name)) {
return [node, $head.before(d)];
}
}
}

View File

@@ -0,0 +1,9 @@
import { CellSelection } from "prosemirror-tables";
export default function getRowIndex(selection: CellSelection) {
const isRowSelection = selection.isRowSelection && selection.isRowSelection();
if (!isRowSelection) return undefined;
const path = (selection.$from as any).path;
return path[path.length - 8];
}

View File

@@ -0,0 +1,15 @@
import { EditorState } from "prosemirror-state";
import isMarkActive from "./isMarkActive";
export default function isInCode(state: EditorState): boolean {
if (state.schema.nodes.code_block) {
const $head = state.selection.$head;
for (let d = $head.depth; d > 0; d--) {
if ($head.node(d).type === state.schema.nodes.code_block) {
return true;
}
}
}
return isMarkActive(state.schema.marks.code_inline)(state);
}

View File

@@ -0,0 +1,16 @@
import { EditorState } from "prosemirror-state";
export default function isInList(state: EditorState) {
const $head = state.selection.$head;
for (let d = $head.depth; d > 0; d--) {
if (
["ordered_list", "bullet_list", "checkbox_list"].includes(
$head.node(d).type.name
)
) {
return true;
}
}
return false;
}

View File

@@ -0,0 +1,9 @@
import { Node, Schema } from "prosemirror-model";
export default function isList(node: Node, schema: Schema) {
return (
node.type === schema.nodes.bullet_list ||
node.type === schema.nodes.ordered_list ||
node.type === schema.nodes.checkbox_list
);
}

View File

@@ -0,0 +1,16 @@
import { MarkType } from "prosemirror-model";
import { EditorState } from "prosemirror-state";
const isMarkActive = (type: MarkType) => (state: EditorState): boolean => {
if (!type) {
return false;
}
const { from, $from, to, empty } = state.selection;
return !!(empty
? type.isInSet(state.storedMarks || $from.marks())
: state.doc.rangeHasMark(from, to, type));
};
export default isMarkActive;

View File

@@ -0,0 +1,23 @@
import { NodeType } from "prosemirror-model";
import { EditorState } from "prosemirror-state";
import { findParentNode, findSelectedNodeOfType } from "prosemirror-utils";
const isNodeActive = (type: NodeType, attrs: Record<string, any> = {}) => (
state: EditorState
) => {
if (!type) {
return false;
}
const node =
findSelectedNodeOfType(type)(state.selection) ||
findParentNode((node) => node.type === type)(state.selection);
if (!Object.keys(attrs).length || !node) {
return !!node;
}
return node.node.hasMarkup(type, { ...node.node.attrs, ...attrs });
};
export default isNodeActive;