123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- import {
- BlockData,
- BlockType,
- DocumentState,
- NestedBlock,
- RangeSelectionState,
- TextDelta,
- TextSelection,
- } from '$app/interfaces/document';
- import { Descendant, Element, Text } from 'slate';
- import { BlockPB } from '@/services/backend';
- import { Log } from '$app/utils/log';
- import { nanoid } from 'nanoid';
- import { clone } from '$app/utils/tool';
- export function slateValueToDelta(slateNodes: Descendant[]) {
- const element = slateNodes[0] as Element;
- const children = element.children as Text[];
- return children.map((child) => {
- const { text, ...attributes } = child;
- return {
- insert: text,
- attributes,
- };
- });
- }
- export function deltaToSlateValue(delta: TextDelta[]) {
- const slateNode = {
- type: 'paragraph',
- children: [{ text: '' }],
- };
- const slateNodes = [slateNode];
- if (delta.length > 0) {
- slateNode.children = delta.map((d) => {
- return {
- ...d.attributes,
- text: d.insert,
- };
- });
- }
- return slateNodes;
- }
- export function getDeltaFromSlateNodes(slateNodes: Descendant[]) {
- const element = slateNodes[0] as Element;
- const children = element.children as Text[];
- return children.map((child) => {
- const { text, ...attributes } = child;
- return {
- insert: text,
- attributes,
- };
- });
- }
- export function blockPB2Node(block: BlockPB) {
- let data = {};
- try {
- data = JSON.parse(block.data);
- } catch {
- Log.error('[Document Open] json parse error', block.data);
- }
- const node = {
- id: block.id,
- type: block.ty as BlockType,
- parent: block.parent_id,
- children: block.children_id,
- data,
- };
- return node;
- }
- export function generateId() {
- return nanoid(10);
- }
- export function getPrevLineId(state: DocumentState, id: string) {
- const node = state.nodes[id];
- if (!node.parent) return;
- const parent = state.nodes[node.parent];
- const children = state.children[parent.children];
- const index = children.indexOf(id);
- const prevNodeId = children[index - 1];
- const prevNode = state.nodes[prevNodeId];
- if (!prevNode) {
- return parent.id;
- }
- // find prev line
- let prevLineId = prevNode.id;
- while (prevLineId) {
- const prevLineChildren = state.children[state.nodes[prevLineId].children];
- if (prevLineChildren.length === 0) break;
- prevLineId = prevLineChildren[prevLineChildren.length - 1];
- }
- return prevLineId || parent.id;
- }
- export function getNextLineId(state: DocumentState, id: string) {
- const node = state.nodes[id];
- if (!node.parent) return;
- const firstChild = state.children[node.children][0];
- if (firstChild) return firstChild;
- let nextNodeId = getNextNodeId(state, id);
- let parent: NestedBlock | null = state.nodes[node.parent];
- while (!nextNodeId && parent) {
- nextNodeId = getNextNodeId(state, parent.id);
- parent = parent.parent ? state.nodes[parent.parent] : null;
- }
- return nextNodeId;
- }
- export function getNextNodeId(state: DocumentState, id: string) {
- const node = state.nodes[id];
- if (!node.parent) return;
- const parent = state.nodes[node.parent];
- const children = state.children[parent.children];
- const index = children.indexOf(id);
- const nextNodeId = children[index + 1];
- return nextNodeId;
- }
- export function getPrevNodeId(state: DocumentState, id: string) {
- const node = state.nodes[id];
- if (!node.parent) return;
- const parent = state.nodes[node.parent];
- const children = state.children[parent.children];
- const index = children.indexOf(id);
- const prevNodeId = children[index - 1];
- return prevNodeId;
- }
- export function newBlock<Type>(type: BlockType, parentId: string, data: BlockData<Type>): NestedBlock<Type> {
- return {
- id: generateId(),
- type,
- parent: parentId,
- children: generateId(),
- data,
- };
- }
- export function getCollapsedRange(id: string, selection: TextSelection): RangeSelectionState {
- const point = {
- id,
- selection,
- };
- return {
- anchor: clone(point),
- focus: clone(point),
- isDragging: false,
- selection: [],
- };
- }
- export function iterateNodes(
- range: {
- startId: string;
- endId: string;
- },
- isForward: boolean,
- document: DocumentState,
- callback: (nodeId?: string) => boolean
- ) {
- const { startId, endId } = range;
- let currentId = startId;
- while (currentId && currentId !== endId) {
- if (isForward) {
- currentId = getNextLineId(document, currentId) || '';
- } else {
- currentId = getPrevLineId(document, currentId) || '';
- }
- if (callback(currentId)) {
- break;
- }
- }
- }
- export function getNodesInRange(
- range: {
- startId: string;
- endId: string;
- },
- isForward: boolean,
- document: DocumentState
- ) {
- const nodeIds: string[] = [];
- nodeIds.push(range.startId);
- iterateNodes(range, isForward, document, (nodeId) => {
- if (nodeId) {
- nodeIds.push(nodeId);
- return false;
- } else {
- return true;
- }
- });
- nodeIds.push(range.endId);
- return nodeIds;
- }
- export function nodeInRange(
- id: string,
- range: {
- startId: string;
- endId: string;
- },
- isForward: boolean,
- document: DocumentState
- ) {
- let match = false;
- iterateNodes(range, isForward, document, (nodeId) => {
- if (nodeId === id) {
- match = true;
- return true;
- }
- return false;
- });
- return match;
- }
|