Path: blob/master/src/packages/frontend/editors/slate/markdown-to-slate/handle-close.ts
1697 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Descendant } from "slate";6import { State } from "./types";7import { getMarkdownToSlate } from "../elements/register";8import { register } from "./register";9import { parse } from "./parse";10import getSource from "./source";11import { setCache } from "./cache";1213function handleClose({ token, state, cache }) {14if (!state.close_type) return;15if (state.contents == null) {16throw Error("bug -- state.contents must not be null");17}1819// Currently collecting the contents to parse when we hit the close_type.2021if (token.type == state.open_type) {22// Hitting same open type *again* (it's nested), so increase nesting.23state.nesting += 1;24}2526if (token.type === state.close_type) {27// Hit the close_type28if (state.nesting > 0) {29// We're nested, so just go up one.30state.nesting -= 1;31} else {32// Not nested, so done: parse the accumulated array of children33// using a new state:34const child_state: State = {35nesting: 0,36marks: state.marks,37lines: state.lines,38};39const children: Descendant[] = [];40let isEmpty = true;41// Note a RULE: "Block nodes can only contain other blocks, or inline and text nodes."42// See https://docs.slatejs.org/concepts/10-normalizing43// This means that all children nodes here have to be either *inline/text* or they44// all have to be blocks themselves -- no mixing. Our markdown parser I think also45// does this, except for one weird special case which involves hidden:true that is46// used for tight lists.4748state.tight = false;49for (const token2 of state.contents) {50for (const node of parse(token2, child_state, cache)) {51if (child_state.tight) {52state.tight = true;53}54isEmpty = false;55children.push(node);56}57}58// console.log("children = ", JSON.stringify(children), isEmpty);59if (isEmpty) {60// it is illegal for the children to be empty.61if (token.type == "list_item_close") {62// This is to match with the rule in ../normalize defined in63// ensureListContainsListItems that "if the the children of the64// list item are leaves, wrap them all in a paragraph".65children.push({ children: [{ text: "" }], type: "paragraph" });66} else {67children.push({ text: "" });68}69}70const i = state.close_type.lastIndexOf("_");71const type = state.close_type.slice(0, i);72delete state.close_type;73delete state.contents;7475const markdownToSlate = getMarkdownToSlate(type);76const node = markdownToSlate({77type,78token,79children,80state,81isEmpty,82cache,83});84if (type == "bullet_list" || type == "ordered_list") {85// tight-ness is ONLY used by lists and we only want it to propagate86// up to the enclosing list.87delete state.tight;88}89if (node == null) {90return [];91}92if (93cache != null &&94state.open_token?.level === 0 &&95state.open_token?.map != null96) {97const markdown = getSource({98start: state.open_token.map[0],99end: state.open_token.map[1],100lines: state.lines,101});102setCache({ cache, node, markdown });103}104return [node];105}106}107108state.contents.push(token);109return [];110}111112register(handleClose);113114115