Path: blob/master/src/packages/frontend/editors/slate/leaf-to-markdown.ts
1691 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Text } from "slate";6import { markInlineText, markdownEscape } from "./util";7import { startswith } from "@cocalc/util/misc";8import { Info } from "./slate-to-markdown";910export function serializeLeaf(node: Text, info: Info): string {11let text = node.text;1213if (text.length > 0) {14// Only apply formatting if the text is non-empty; otherwise, it's pointless and confusing.1516/*17TODO: Markdown escaping is confusing when one user is18working in the source side and the other in slatejs at the same time.19I don't know any solution for that yet.20NOTE: disabling this would have interesting implications for being able to type markdown21into slatej, and have it autoconvert to rendered (e.g., backticks --> code).22*/23if (24!info.no_escape &&25!node.code &&26info.parent?.["type"] != "code_block"27) {28text = markdownEscape(text, info.index == 0);29}3031const marks: { left: string; right?: string }[] = [];32// Proper markdown annotation.33if (node.code) {34// code *must* be first, since in markdown ~~`var`~~ is completely different than `~~var~~`.35marks.push({ left: "`" });36}37if (node.bold) {38marks.push({ left: "**" });39}40if (node.italic) {41marks.push({ left: "_" });42}43if (node.strikethrough) {44marks.push({ left: "~~" });45}46if (node.tt) {47// tt is deprecated, so we don't want to encourage it; we automatically48// normalize it to equivalent span.49marks.push({50left: "<span style='font-family:monospace'>",51right: "</span>",52});53}5455// Using html to provide some things markdown doesn't provide,56// but they can be VERY useful in practice for our users.57if (node.underline) {58marks.push({ left: "<u>", right: "</u>" });59}60for (const c of ["sup", "sub", "small"]) {61if (node[c]) {62marks.push({ left: `<${c}>`, right: `</${c}>` });63}64}65// colors and fonts66for (const mark in node) {67if (!node[mark]) continue; // only if true68for (const c of ["color", "font-family", "font-size"]) {69if (startswith(mark, `${c}:`)) {70marks.push({71left: `<span style='${mark}'>`,72right: "</span>",73});74}75}76}77for (const mark of marks) {78text = markInlineText(text, mark.left, mark.right);79}80}8182if (info.hook != null) {83// always do this (even if text empty), e.g., it could be putting a special marker in.84const h = info.hook(node);85if (h != null) return h(text);86}8788return text;89}909192