-
Notifications
You must be signed in to change notification settings - Fork 801
/
Copy pathtransform.mjs
127 lines (113 loc) · 4.36 KB
/
transform.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
function childrenText(token) {
let text = ""
for (let i = 0; i < token.children.length; i++) {
let child = token.children[i];
if (child.type == "text" || child.type == "code_inlin") text += child.content
}
return text
}
import {createHash} from "crypto"
function hash(text) {
let sum = createHash("sha1")
sum.update(text)
return sum.digest("base64").slice(0, 10)
}
function startAndEnd(text) {
var words = text.split(/\W+/);
if (!words[0]) words.shift();
if (!words[words.length - 1]) words.pop();
if (words.length <= 6) return words.join(" ");
return words.slice(0, 3).concat(words.slice(words.length - 3)).join(" ");
}
function tokenText(token) {
if (token.type == "text" || token.type == "code_inline") return token.content
else if (token.type == "softbreak") return " "
else return ""
}
function smartQuotes(tokens, i, tex, moveQuotes) {
let text = tokens[i].content, from = 0
for (let j = i - 1, tt; j >= 0; j--) if (tt = tokenText(tokens[j])) {
text = tt + text
from = tt.length
break
}
let to = text.length
for (let j = i + 1, tt; j < tokens.length; j++) if (tt = tokenText(tokens[j])) {
text += tt
break
}
let quoted = text
.replace(/([\w\.,!?\)])'/g, "$1’")
.replace(/'(\w|\(\()/g, "‘$1")
.replace(/([\w\.,!?\)])"/g, "$1”")
.replace(/"(\w|\(\()/g, "“$1")
.slice(from, to)
if (moveQuotes) quoted = quoted.replace(/”([.!?:;,]+)/g, "$1”")
return tex ? quoted.replace(/‘/g, "`").replace(/’/g, "'").replace(/“/g, "``").replace(/”/g, "''") : quoted
}
function handleIf(tokens, i, options) {
let tag = tokens[i].args[0]
if (options.defined.indexOf(tag) > -1) return i
for (let j = i + 1; j < tokens.length; j++) if (tokens[j].type == "meta_if_close" && tokens[j].args[0] == tag)
return j
}
const titleCaseSmallWords = "a an the at by for in of on to up and as but with or nor if console.log".split(" ");
function capitalizeTitle(text) {
return text.split(" ")
.map(word => titleCaseSmallWords.includes(word) ? word : word[0].toUpperCase() + word.slice(1))
.join(" ")
}
function transformInline(tokens, options, prevType) {
let capitalize = options.capitalizeTitles && prevType == "heading_open"
let result = []
for (let i = 0; i < tokens.length; i++) {
let tok = tokens[i], type = tok.type
if (type == "meta_if_close" || (options.index === false && type == "meta_index")) {
// Drop
} else if (type == "meta_if_open") {
i = handleIf(tokens, i, options)
} else {
if (type == "text" && /[\'\"]/.test(tok.content)) tok.content = smartQuotes(tokens, i, options.texQuotes, options.moveQuotes)
if (capitalize) tok.content = capitalizeTitle(tok.content)
result.push(tok)
}
}
return result
}
function nextTag(tokens, i) {
for (let j = i + 1; j < tokens.length; j++) if (tokens[j].tag) return tokens[j];
}
export function transformTokens(tokens, options) {
let meta = {}, result = []
for (let i = 0; i < tokens.length; i++) {
let tok = tokens[i], type = tok.type
if (type == "meta_meta") {
for (let prop in tok.args[0]) meta[prop] = tok.args[0][prop]
} else if (type == "meta_id") {
let next = nextTag(tokens, i)
;(next.attrs || (next.attrs = [])).push(["id", tok.args[0]])
} else if (type == "meta_table") {
nextTag(tokens, i).tableData = tok.args[0]
} else if (type == "meta_if_open") {
i = handleIf(tokens, i, options)
} else if (type == "meta_hint_open" && options.strip === "hints") {
do { i++ } while (tokens[i].type != "meta_hint_close")
} else if (type == "meta_if_close" || (options.index === false && (type == "meta_indexsee" || type == "meta_index"))) {
// Drop
} else if (tok.tag == "h1" && options.takeTitle) {
if (tokens[i + 1].children.length != 1) throw new Error("Complex H1 not supported")
meta.title = tokens[i + 1].children[0].content
i += 2
} else {
if (type == "paragraph_open")
tok.hashID = "p-" + hash(startAndEnd(childrenText(tokens[i + 1])))
else if (type == "heading_open")
tok.hashID = (tok.tag == "h2" ? "h-" : "i-") + hash(childrenText(tokens[i + 1]))
else if (type == "fence")
tok.hashID = "c-" + hash(tok.content)
if (tok.children) tok.children = transformInline(tok.children, options, tokens[i - 1].type)
result.push(tok)
}
}
return {tokens: result, metadata: meta}
}