Skip to content

Commit dcd1c09

Browse files
committed
Further refine markdown tools
1 parent c7e4444 commit dcd1c09

File tree

5 files changed

+53
-24
lines changed

5 files changed

+53
-24
lines changed

src/chapter.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<script src="js/ejs.js"></script>
1111
<<if $in.chap_num || $in.load_files>>
1212
<script>
13-
<<if $in.chap_num>>var chapNum = <<h chap_num>>;<</if>>
13+
<<if $in.chap_num>>var chapNum = <<h $in.chap_num>>;<</if>>
1414
<<if $in.load_files>>var sandboxLoadFiles = <<h JSON.stringify($in.load_files)>>;<</if>>
1515
</script>
1616
<</if>>

src/convert.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,40 @@ function processIndexTerm(term) {
88
return terms.length == 1 ? terms[0] : "[" + terms.join(", ") + "]"
99
}
1010

11+
function maybeQuote(value) {
12+
return /\W/.test(value) ? JSON.stringify(value) : value
13+
}
14+
1115
text = text
1216
.replace(/^(:\w+:\s*.+\n)+/, function(meta) {
1317
let re = /(?:^|\n):(\w+):\s*(.+)/g, m, props = []
14-
while (m = re.exec(meta)) props.push(m[1] + ": " + m[2])
15-
return `{{meta {${props.join(", ")}}}}`
18+
while (m = re.exec(meta)) props.push(m[1] + ": " + (m[1] == "load_files" ? m[2] : maybeQuote(m[2])))
19+
return `{{meta {${props.join(", ")}}}}\n`
1620
})
1721
.replace(/\n(=+) (.*?) =+\n/g, function(_, depth, title) {
1822
return "\n" + "#".repeat(depth.length) + " " + title + "\n"
1923
})
20-
.replace(/\nimage::([^\]]+)\[(.*?)\]/g, function(_, url, meta) {
21-
return "\n{{figure {url: " + JSON.stringify(url) + ", " + meta.replace(/="/g, ": \"") + "}}}"
24+
.replace(/\nimage::([^\[]+)\[(.*?)\]\n/g, function(_, url, meta) {
25+
return "\n{{figure {url: " + JSON.stringify(url) + ", " + meta.replace(/="/g, ": \"") + "}}}\n"
2226
})
23-
.replace(/\n(\[chapterquote=.*?\]\n)?\[quote, ([^\]]+)\]\n____\n([^]*?)____\n/g, function(_, chapter, author, content) {
24-
let match = /([^,]+), (.+)/.exec(author), title = null
25-
if (match) { title = match[2]; author = match[1] }
26-
return "\n{{quote {" + (chapter ? "chapter: true, " : "") + "author: " + JSON.stringify(author) +
27-
(title ? ", title: " + JSON.stringify(title) : "") + "}\n\n" + content + "\n}}\n"
27+
.replace(/\n(\[chapterquote=.*?\]\n)?(?:\[quote,\s*([^\]]+)\]\n)?___+\n([^]*?)___+\n/g, function(_, chapter, author, content) {
28+
let props = []
29+
if (author) {
30+
let match = /([^,]+), (.+)/.exec(author), title = null
31+
if (match) props.push(`author: ${JSON.stringify(match[1])}`, `title: ${JSON.stringify(match[2])}`)
32+
else props.push(`author: ${JSON.stringify(author)}`)
33+
}
34+
if (chapter) props.push("chapter: true")
35+
return `\n{{quote${props.length ? " {" + props.join(", ") + "}" : ""}\n\n${content}\nquote}}\n`
2836
})
29-
.replace(/\n\n+((?:(?!\n\n)[^])*?\(\(\((?:(?!\n\n)[^])*)/g, function(_, para) {
37+
.replace(/\n\n+((?:(?!\n\n)[^])*?\(\(\((?:(?!\n\n)[^])*)/g, function(all, para) {
3038
let terms = []
3139
para = para.replace(/\(\(\(((?:\([^\)]*\)|[^])*?)\)\)\)/g, function(_, content) {
3240
terms.push(content)
3341
return ""
3442
}).replace(/^\s*/, "")
35-
return "\n\n{{index " + terms.map(processIndexTerm).join(", ") + "}}\n\n" + para
43+
if (terms.length) return "\n\n{{index " + terms.map(processIndexTerm).join(", ") + "}}\n\n" + para
44+
else return all
3645
})
3746
.replace(/\bindexsee:\[(.*?),\s*(.*?)\]\s*/g, function(_, term, ref) {
3847
return "{{indexsee " + processIndexTerm(term) + ", " + processIndexTerm(ref) + "}}\n\n"
@@ -44,16 +53,16 @@ text = text
4453
if (sandbox) params.push("sandbox-" + sandbox)
4554
return "\n```" + params.join(" ") + "\n" + content + "\n```\n"
4655
})
47-
.replace(/\n\/\/ (?:(start_code)|test: (.*)|include_code (.*))/g, function(_, startCode, test, includeCode) {
48-
if (startCode) return "\n{{startCode}}"
56+
.replace(/\n\/\/ (?:(start_code(?: (.*))?)|test: (.*)|include_code (.*))/g, function(_, startCode, startCodeParam, test, includeCode) {
57+
if (startCode) return `\n{{startCode${startCodeParam ? " " + JSON.stringify(startCodeParam) : ""}}}`
4958
if (test) return "\n{{test " + test + "}}"
5059
return "\n{{includeCode " + JSON.stringify(includeCode) + "}}"
5160
})
5261
.replace(/\blink:([^\[]+)\[(.*?)\]/g, function(_, url, content) {
5362
return "[" + content + "](" + url + ")"
5463
})
5564
.replace(/\nifdef::(\w+?)_target\[\]\n([^]*?)\nendif::.*/g, function(_, type, content) {
56-
return "\n{{if " + type + "\n" + content + "\n}}"
65+
return "\n{{if " + type + "\n" + content + "\nif}}"
5766
})
5867
.replace(/\+\+(?! |\))((?:(?!\n\n)[^])+)\+\+/g, function(_, text) {
5968
return "_" + text + "_"
@@ -62,7 +71,10 @@ text = text
6271
return "_" + text + "_"
6372
})
6473
.replace(/\n\[\[(.*?)\]\]\n/g, function(_, name) {
65-
return `\n{{id ${/\W/.test(name) ? JSON.stringify(name) : name}}}\n`
74+
return `\n{{id ${maybeQuote(name)}}}\n`
75+
})
76+
.replace(/\n!!hint!!\n([^]+?)\n!!hint!!/g, function(_, content) {
77+
return `\n{{hint\n${content}\nhint}}`
6678
})
6779
.replace(/\[sic]/, "\\[sic]")
6880

src/markdown.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,14 @@ function parseBlockMeta(state, startLine, endLine) {
3737
let data = parseData(content)
3838
if (!data) return false
3939

40-
let line = startLine + 1, depth = 0
40+
let line = startLine + 1, close = data.tag + "}}", open = new RegExp("^\\{\\{" + data.tag + "(\\s|$)"), depth = 0
4141
for (; line < endLine; line++) {
4242
if (line == endLine) throw new SyntaxError("Unterminated meta block")
4343
let start = state.bMarks[line] + state.tShift[line]
44-
let after = state.src.slice(start, start + 2)
45-
if (after == "{{" && !/\}\}\s*$/.test(state.src.slice(start, state.eMarks[line]))) depth++
46-
else if (after == "}}") {
44+
let lineText = state.src.slice(start, state.eMarks[line])
45+
if (open.test(lineText)) {
46+
depth++
47+
} else if (lineText == close) {
4748
if (depth) depth--
4849
else break
4950
}

src/render_html.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function anchor(token) {
3232
}
3333

3434
function attrs(token) {
35-
return token.attrs ? token.attrs.map(([name, val]) => ` ${name}="${escape(val)}"`).join("") : ""
35+
return token.attrs ? token.attrs.map(([name, val]) => ` ${name}="${escape(String(val))}"`).join("") : ""
3636
}
3737

3838
let renderer = {
@@ -61,6 +61,18 @@ let renderer = {
6161

6262
heading_close(token) { return `</${token.tag}>` },
6363

64+
bullet_list_open(token) { return `\n\n<ul${attrs(token)}>` },
65+
66+
bullet_list_close() { return `</ul>` },
67+
68+
ordered_list_open(token) { return `\n\n<ol${attrs(token)}>` },
69+
70+
ordered_list_close() { return `\n\n</ol>` },
71+
72+
list_item_open() { return "\n\n<li>" },
73+
74+
list_item_close() { return "</li>" },
75+
6476
strong_open() { return "<strong>" },
6577

6678
strong_close() { return "</strong>" },
@@ -86,10 +98,14 @@ let renderer = {
8698
meta_quote_open() { return "\n\n<blockquote>" },
8799

88100
meta_quote_close(token) {
89-
let {author, title} = token.args[0]
101+
let {author, title} = token.args[0] || {}
90102
return (author ? `\n\n<footer>${escape(author)}${title ? `, <cite>${escape(title)}</cite>` : ""}` : "") +
91103
"\n\n</blockquote>"
92-
}
104+
},
105+
106+
meta_hint_open() { return "\n\n<div class=solution><div class=solution-text>" },
107+
108+
meta_hint_close() { return "\n\n</div></div>" }
93109
}
94110

95111
function renderArray(tokens) {

src/transform.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ exports.transformTokens = function(tokens, options) {
6464
for (let i = 0; i < tokens.length; i++) {
6565
let tok = tokens[i], type = tok.type
6666
if (type == "meta_meta") {
67-
for (let prop in tok.args[0]) if (prop != "_") meta[prop] = tok.args[0][prop]
67+
for (let prop in tok.args[0]) meta[prop] = tok.args[0][prop]
6868
} else if (type == "meta_id") {
6969
for (let j = i + 1; j < tokens.length; j++) if (tokens[j].tag) {
7070
;(tokens[j].attrs || (tokens[j].attrs = [])).push(["id", tok.args[0]])

0 commit comments

Comments
 (0)