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