markdown.lua

Sun, 06 Sep 2020 22:12:52 +0300

author
Tuomo Valkonen <tuomov@iki.fi>
date
Sun, 06 Sep 2020 22:12:52 +0300
changeset 35
2f927eae429b
parent 8
836dac92eced
permissions
-rw-r--r--

Don't auto-create directories that will be empty

8
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1 #!/usr/bin/env lua
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
2
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
3 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
4 -- Utility functions
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
5 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
6
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
7 local unpack = table.unpack or unpack
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
8
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
9 -- Returns the result of mapping the values in table t through the function f
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
10 local function map(t, f)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
11 local out = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
12 for k,v in pairs(t) do out[k] = f(v,k) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
13 return out
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
14 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
15
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
16 -- Functional style if statement. (NOTE: no short circuit evaluation)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
17 local function iff(t, a, b) if t then return a else return b end end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
18
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
19 -- Splits the text into an array of separate lines.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
20 local function split(text, sep)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
21 sep = sep or "\n"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
22 local lines = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
23 local pos = 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
24 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
25 local b,e = text:find(sep, pos)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
26 if not b then table.insert(lines, text:sub(pos)) break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
27 table.insert(lines, text:sub(pos, b-1))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
28 pos = e + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
29 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
30 return lines
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
31 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
32
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
33 -- Converts tabs to spaces
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
34 local function detab(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
35 local tab_width = 4
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
36 local function rep(match)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
37 local spaces = -match:len()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
38 while spaces<1 do spaces = spaces + tab_width end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
39 return match .. string.rep(" ", spaces)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
40 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
41 text = text:gsub("([^\n]-)\t", rep)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
42 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
43 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
44
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
45 -- Applies string.find for every pattern in the list and returns the first match
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
46 local function find_first(s, patterns, index)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
47 local res = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
48 for _,p in ipairs(patterns) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
49 local match = {s:find(p, index)}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
50 if #match>0 and (#res==0 or match[1] < res[1]) then res = match end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
51 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
52 return unpack(res)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
53 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
54
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
55 -- If a replacement array is specified, the range [start, stop] in the array is replaced
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
56 -- with the replacement array and the resulting array is returned. Without a replacement
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
57 -- array the section of the array between start and stop is returned.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
58 local function splice(array, start, stop, replacement)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
59 if replacement then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
60 local n = stop - start + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
61 while n > 0 do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
62 table.remove(array, start)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
63 n = n - 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
64 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
65 for _,v in ipairs(replacement) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
66 table.insert(array, start, v)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
67 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
68 return array
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
69 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
70 local res = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
71 for i = start,stop do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
72 table.insert(res, array[i])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
73 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
74 return res
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
75 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
76 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
77
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
78 -- Outdents the text one step.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
79 local function outdent(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
80 text = "\n" .. text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
81 text = text:gsub("\n ? ? ?", "\n")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
82 text = text:sub(2)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
83 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
84 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
85
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
86 -- Indents the text one step.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
87 local function indent(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
88 text = text:gsub("\n", "\n ")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
89 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
90 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
91
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
92 -- Does a simple tokenization of html data. Returns the data as a list of tokens.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
93 -- Each token is a table with a type field (which is either "tag" or "text") and
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
94 -- a text field (which contains the original token data).
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
95 local function tokenize_html(html)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
96 local tokens = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
97 local pos = 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
98 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
99 local start = find_first(html, {"<!%-%-", "<[a-z/!$]", "<%?"}, pos)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
100 if not start then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
101 table.insert(tokens, {type="text", text=html:sub(pos)})
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
102 break
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
103 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
104 if start ~= pos then table.insert(tokens, {type="text", text = html:sub(pos, start-1)}) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
105
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
106 local _, stop
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
107 if html:match("^<!%-%-", start) then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
108 _,stop = html:find("%-%->", start)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
109 elseif html:match("^<%?", start) then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
110 _,stop = html:find("?>", start)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
111 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
112 _,stop = html:find("%b<>", start)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
113 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
114 if not stop then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
115 -- error("Could not match html tag " .. html:sub(start,start+30))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
116 table.insert(tokens, {type="text", text=html:sub(start, start)})
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
117 pos = start + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
118 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
119 table.insert(tokens, {type="tag", text=html:sub(start, stop)})
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
120 pos = stop + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
121 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
122 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
123 return tokens
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
124 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
125
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
126 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
127 -- Hash
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
128 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
129
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
130 -- This is used to "hash" data into alphanumeric strings that are unique
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
131 -- in the document. (Note that this is not cryptographic hash, the hash
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
132 -- function is not one-way.) The hash procedure is used to protect parts
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
133 -- of the document from further processing.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
134
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
135 local HASH = {
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
136 -- Has the hash been inited.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
137 inited = false,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
138
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
139 -- The unique string prepended to all hash values. This is to ensure
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
140 -- that hash values do not accidently coincide with an actual existing
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
141 -- string in the document.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
142 identifier = "",
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
143
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
144 -- Counter that counts up for each new hash instance.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
145 counter = 0,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
146
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
147 -- Hash table.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
148 table = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
149 }
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
150
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
151 -- Inits hashing. Creates a hash_identifier that doesn't occur anywhere
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
152 -- in the text.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
153 local function init_hash(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
154 HASH.inited = true
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
155 HASH.identifier = ""
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
156 HASH.counter = 0
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
157 HASH.table = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
158
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
159 local s = "HASH"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
160 local counter = 0
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
161 local id
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
162 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
163 id = s .. counter
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
164 if not text:find(id, 1, true) then break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
165 counter = counter + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
166 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
167 HASH.identifier = id
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
168 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
169
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
170 -- Returns the hashed value for s.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
171 local function hash(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
172 assert(HASH.inited)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
173 if not HASH.table[s] then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
174 HASH.counter = HASH.counter + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
175 local id = HASH.identifier .. HASH.counter .. "X"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
176 HASH.table[s] = id
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
177 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
178 return HASH.table[s]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
179 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
180
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
181 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
182 -- Protection
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
183 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
184
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
185 -- The protection module is used to "protect" parts of a document
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
186 -- so that they are not modified by subsequent processing steps.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
187 -- Protected parts are saved in a table for later unprotection
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
188
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
189 -- Protection data
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
190 local PD = {
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
191 -- Saved blocks that have been converted
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
192 blocks = {},
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
193
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
194 -- Block level tags that will be protected
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
195 tags = {"p", "div", "h1", "h2", "h3", "h4", "h5", "h6", "blockquote",
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
196 "pre", "table", "dl", "ol", "ul", "script", "noscript", "form", "fieldset",
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
197 "iframe", "math", "ins", "del"}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
198 }
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
199
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
200 -- Pattern for matching a block tag that begins and ends in the leftmost
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
201 -- column and may contain indented subtags, i.e.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
202 -- <div>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
203 -- A nested block.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
204 -- <div>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
205 -- Nested data.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
206 -- </div>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
207 -- </div>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
208 local function block_pattern(tag)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
209 return "\n<" .. tag .. ".-\n</" .. tag .. ">[ \t]*\n"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
210 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
211
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
212 -- Pattern for matching a block tag that begins and ends with a newline
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
213 local function line_pattern(tag)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
214 return "\n<" .. tag .. ".-</" .. tag .. ">[ \t]*\n"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
215 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
216
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
217 -- Protects the range of characters from start to stop in the text and
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
218 -- returns the protected string.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
219 local function protect_range(text, start, stop)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
220 local s = text:sub(start, stop)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
221 local h = hash(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
222 PD.blocks[h] = s
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
223 text = text:sub(1,start) .. h .. text:sub(stop)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
224 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
225 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
226
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
227 -- Protect every part of the text that matches any of the patterns. The first
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
228 -- matching pattern is protected first, etc.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
229 local function protect_matches(text, patterns)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
230 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
231 local start, stop = find_first(text, patterns)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
232 if not start then break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
233 text = protect_range(text, start, stop)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
234 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
235 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
236 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
237
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
238 -- Protects blocklevel tags in the specified text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
239 local function protect(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
240 -- First protect potentially nested block tags
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
241 text = protect_matches(text, map(PD.tags, block_pattern))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
242 -- Then protect block tags at the line level.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
243 text = protect_matches(text, map(PD.tags, line_pattern))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
244 -- Protect <hr> and comment tags
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
245 text = protect_matches(text, {"\n<hr[^>]->[ \t]*\n"})
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
246 text = protect_matches(text, {"\n<!%-%-.-%-%->[ \t]*\n"})
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
247 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
248 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
249
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
250 -- Returns true if the string s is a hash resulting from protection
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
251 local function is_protected(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
252 return PD.blocks[s]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
253 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
254
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
255 -- Unprotects the specified text by expanding all the nonces
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
256 local function unprotect(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
257 for k,v in pairs(PD.blocks) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
258 v = v:gsub("%%", "%%%%")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
259 text = text:gsub(k, v)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
260 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
261 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
262 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
263
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
264
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
265 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
266 -- Block transform
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
267 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
268
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
269 -- The block transform functions transform the text on the block level.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
270 -- They work with the text as an array of lines rather than as individual
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
271 -- characters.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
272
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
273 -- Returns true if the line is a ruler of (char) characters.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
274 -- The line must contain at least three char characters and contain only spaces and
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
275 -- char characters.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
276 local function is_ruler_of(line, char)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
277 if not line:match("^[ %" .. char .. "]*$") then return false end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
278 if not line:match("%" .. char .. ".*%" .. char .. ".*%" .. char) then return false end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
279 return true
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
280 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
281
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
282 -- Identifies the block level formatting present in the line
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
283 local function classify(line)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
284 local info = {line = line, text = line}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
285
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
286 if line:match("^ ") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
287 info.type = "indented"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
288 info.outdented = line:sub(5)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
289 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
290 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
291
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
292 for _,c in ipairs({'*', '-', '_', '='}) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
293 if is_ruler_of(line, c) then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
294 info.type = "ruler"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
295 info.ruler_char = c
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
296 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
297 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
298 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
299
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
300 if line == "" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
301 info.type = "blank"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
302 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
303 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
304
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
305 if line:match("^(#+)[ \t]*(.-)[ \t]*#*[ \t]*$") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
306 local m1, m2 = line:match("^(#+)[ \t]*(.-)[ \t]*#*[ \t]*$")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
307 info.type = "header"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
308 info.level = m1:len()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
309 info.text = m2
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
310 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
311 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
312
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
313 if line:match("^ ? ? ?(%d+)%.[ \t]+(.+)") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
314 local number, text = line:match("^ ? ? ?(%d+)%.[ \t]+(.+)")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
315 info.type = "list_item"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
316 info.list_type = "numeric"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
317 info.number = 0 + number
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
318 info.text = text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
319 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
320 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
321
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
322 if line:match("^ ? ? ?([%*%+%-])[ \t]+(.+)") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
323 local bullet, text = line:match("^ ? ? ?([%*%+%-])[ \t]+(.+)")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
324 info.type = "list_item"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
325 info.list_type = "bullet"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
326 info.bullet = bullet
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
327 info.text= text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
328 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
329 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
330
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
331 if line:match("^>[ \t]?(.*)") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
332 info.type = "blockquote"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
333 info.text = line:match("^>[ \t]?(.*)")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
334 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
335 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
336
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
337 if is_protected(line) then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
338 info.type = "raw"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
339 info.html = unprotect(line)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
340 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
341 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
342
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
343 info.type = "normal"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
344 return info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
345 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
346
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
347 -- Find headers constisting of a normal line followed by a ruler and converts them to
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
348 -- header entries.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
349 local function headers(array)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
350 local i = 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
351 while i <= #array - 1 do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
352 if array[i].type == "normal" and array[i+1].type == "ruler" and
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
353 (array[i+1].ruler_char == "-" or array[i+1].ruler_char == "=") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
354 local info = {line = array[i].line}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
355 info.text = info.line
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
356 info.type = "header"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
357 info.level = iff(array[i+1].ruler_char == "=", 1, 2)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
358 table.remove(array, i+1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
359 array[i] = info
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
360 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
361 i = i + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
362 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
363 return array
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
364 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
365
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
366 -- Forward declarations
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
367 local block_transform, span_transform, encode_code
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
368
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
369 -- Convert lines to html code
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
370 local function blocks_to_html(lines, no_paragraphs)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
371 local out = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
372 local i = 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
373 while i <= #lines do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
374 local line = lines[i]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
375 if line.type == "ruler" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
376 table.insert(out, "<hr/>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
377 elseif line.type == "raw" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
378 table.insert(out, line.html)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
379 elseif line.type == "normal" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
380 local s = line.line
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
381
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
382 while i+1 <= #lines and lines[i+1].type == "normal" do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
383 i = i + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
384 s = s .. "\n" .. lines[i].line
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
385 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
386
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
387 if no_paragraphs then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
388 table.insert(out, span_transform(s))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
389 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
390 table.insert(out, "<p>" .. span_transform(s) .. "</p>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
391 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
392 elseif line.type == "header" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
393 local s = "<h" .. line.level .. ">" .. span_transform(line.text) .. "</h" .. line.level .. ">"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
394 table.insert(out, s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
395 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
396 table.insert(out, line.line)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
397 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
398 i = i + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
399 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
400 return out
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
401 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
402
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
403 -- Find list blocks and convert them to protected data blocks
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
404 local function lists(array, sublist)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
405 local function process_list(arr)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
406 local function any_blanks(arr)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
407 for i = 1, #arr do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
408 if arr[i].type == "blank" then return true end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
409 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
410 return false
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
411 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
412
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
413 local function split_list_items(arr)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
414 local acc = {arr[1]}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
415 local res = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
416 for i=2,#arr do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
417 if arr[i].type == "list_item" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
418 table.insert(res, acc)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
419 acc = {arr[i]}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
420 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
421 table.insert(acc, arr[i])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
422 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
423 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
424 table.insert(res, acc)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
425 return res
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
426 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
427
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
428 local function process_list_item(lines, block)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
429 while lines[#lines].type == "blank" do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
430 table.remove(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
431 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
432
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
433 local itemtext = lines[1].text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
434 for i=2,#lines do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
435 itemtext = itemtext .. "\n" .. outdent(lines[i].line)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
436 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
437 if block then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
438 itemtext = block_transform(itemtext, true)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
439 if not itemtext:find("<pre>") then itemtext = indent(itemtext) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
440 return " <li>" .. itemtext .. "</li>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
441 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
442 local lines = split(itemtext)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
443 lines = map(lines, classify)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
444 lines = lists(lines, true)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
445 lines = blocks_to_html(lines, true)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
446 itemtext = table.concat(lines, "\n")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
447 if not itemtext:find("<pre>") then itemtext = indent(itemtext) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
448 return " <li>" .. itemtext .. "</li>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
449 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
450 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
451
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
452 local block_list = any_blanks(arr)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
453 local items = split_list_items(arr)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
454 local out = ""
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
455 for _, item in ipairs(items) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
456 out = out .. process_list_item(item, block_list) .. "\n"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
457 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
458 if arr[1].list_type == "numeric" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
459 return "<ol>\n" .. out .. "</ol>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
460 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
461 return "<ul>\n" .. out .. "</ul>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
462 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
463 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
464
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
465 -- Finds the range of lines composing the first list in the array. A list
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
466 -- starts with (^ list_item) or (blank list_item) and ends with
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
467 -- (blank* $) or (blank normal).
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
468 --
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
469 -- A sublist can start with just (list_item) does not need a blank...
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
470 local function find_list(array, sublist)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
471 local function find_list_start(array, sublist)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
472 if array[1].type == "list_item" then return 1 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
473 if sublist then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
474 for i = 1,#array do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
475 if array[i].type == "list_item" then return i end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
476 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
477 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
478 for i = 1, #array-1 do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
479 if array[i].type == "blank" and array[i+1].type == "list_item" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
480 return i+1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
481 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
482 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
483 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
484 return nil
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
485 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
486 local function find_list_end(array, start)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
487 local pos = #array
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
488 for i = start, #array-1 do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
489 if array[i].type == "blank" and array[i+1].type ~= "list_item"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
490 and array[i+1].type ~= "indented" and array[i+1].type ~= "blank" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
491 pos = i-1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
492 break
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
493 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
494 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
495 while pos > start and array[pos].type == "blank" do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
496 pos = pos - 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
497 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
498 return pos
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
499 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
500
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
501 local start = find_list_start(array, sublist)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
502 if not start then return nil end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
503 return start, find_list_end(array, start)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
504 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
505
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
506 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
507 local start, stop = find_list(array, sublist)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
508 if not start then break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
509 local text = process_list(splice(array, start, stop))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
510 local info = {
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
511 line = text,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
512 type = "raw",
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
513 html = text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
514 }
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
515 array = splice(array, start, stop, {info})
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
516 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
517
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
518 -- Convert any remaining list items to normal
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
519 for _,line in ipairs(array) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
520 if line.type == "list_item" then line.type = "normal" end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
521 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
522
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
523 return array
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
524 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
525
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
526 -- Find and convert blockquote markers.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
527 local function blockquotes(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
528 local function find_blockquote(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
529 local start
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
530 for i,line in ipairs(lines) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
531 if line.type == "blockquote" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
532 start = i
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
533 break
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
534 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
535 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
536 if not start then return nil end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
537
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
538 local stop = #lines
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
539 for i = start+1, #lines do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
540 if lines[i].type == "blank" or lines[i].type == "blockquote" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
541 elseif lines[i].type == "normal" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
542 if lines[i-1].type == "blank" then stop = i-1 break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
543 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
544 stop = i-1 break
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
545 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
546 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
547 while lines[stop].type == "blank" do stop = stop - 1 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
548 return start, stop
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
549 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
550
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
551 local function process_blockquote(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
552 local raw = lines[1].text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
553 for i = 2,#lines do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
554 raw = raw .. "\n" .. lines[i].text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
555 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
556 local bt = block_transform(raw)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
557 if not bt:find("<pre>") then bt = indent(bt) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
558 return "<blockquote>\n " .. bt ..
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
559 "\n</blockquote>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
560 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
561
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
562 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
563 local start, stop = find_blockquote(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
564 if not start then break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
565 local text = process_blockquote(splice(lines, start, stop))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
566 local info = {
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
567 line = text,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
568 type = "raw",
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
569 html = text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
570 }
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
571 lines = splice(lines, start, stop, {info})
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
572 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
573 return lines
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
574 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
575
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
576 -- Find and convert codeblocks.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
577 local function codeblocks(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
578 local function find_codeblock(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
579 local start
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
580 for i,line in ipairs(lines) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
581 if line.type == "indented" then start = i break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
582 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
583 if not start then return nil end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
584
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
585 local stop = #lines
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
586 for i = start+1, #lines do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
587 if lines[i].type ~= "indented" and lines[i].type ~= "blank" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
588 stop = i-1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
589 break
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
590 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
591 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
592 while lines[stop].type == "blank" do stop = stop - 1 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
593 return start, stop
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
594 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
595
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
596 local function process_codeblock(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
597 local raw = detab(encode_code(outdent(lines[1].line)))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
598 for i = 2,#lines do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
599 raw = raw .. "\n" .. detab(encode_code(outdent(lines[i].line)))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
600 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
601 return "<pre><code>" .. raw .. "\n</code></pre>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
602 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
603
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
604 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
605 local start, stop = find_codeblock(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
606 if not start then break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
607 local text = process_codeblock(splice(lines, start, stop))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
608 local info = {
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
609 line = text,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
610 type = "raw",
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
611 html = text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
612 }
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
613 lines = splice(lines, start, stop, {info})
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
614 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
615 return lines
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
616 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
617
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
618 -- Perform all the block level transforms
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
619 function block_transform(text, sublist)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
620 local lines = split(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
621 lines = map(lines, classify)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
622 lines = headers(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
623 lines = lists(lines, sublist)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
624 lines = codeblocks(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
625 lines = blockquotes(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
626 lines = blocks_to_html(lines)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
627 local text = table.concat(lines, "\n")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
628 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
629 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
630
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
631 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
632 -- Span transform
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
633 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
634
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
635 -- Functions for transforming the text at the span level.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
636
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
637 -- These characters may need to be escaped because they have a special
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
638 -- meaning in markdown.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
639 local escape_chars = "'\\`*_{}[]()>#+-.!'"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
640 local escape_table = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
641
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
642 local function init_escape_table()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
643 escape_table = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
644 for i = 1,#escape_chars do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
645 local c = escape_chars:sub(i,i)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
646 escape_table[c] = hash(c)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
647 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
648 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
649
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
650 -- Adds a new escape to the escape table.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
651 local function add_escape(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
652 if not escape_table[text] then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
653 escape_table[text] = hash(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
654 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
655 return escape_table[text]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
656 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
657
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
658 -- Encode backspace-escaped characters in the markdown source.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
659 local function encode_backslash_escapes(t)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
660 for i=1,escape_chars:len() do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
661 local c = escape_chars:sub(i,i)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
662 t = t:gsub("\\%" .. c, escape_table[c])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
663 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
664 return t
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
665 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
666
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
667 -- Escape characters that should not be disturbed by markdown.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
668 local function escape_special_chars(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
669 local tokens = tokenize_html(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
670
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
671 local out = ""
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
672 for _, token in ipairs(tokens) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
673 local t = token.text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
674 if token.type == "tag" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
675 -- In tags, encode * and _ so they don't conflict with their use in markdown.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
676 t = t:gsub("%*", escape_table["*"])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
677 t = t:gsub("%_", escape_table["_"])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
678 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
679 t = encode_backslash_escapes(t)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
680 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
681 out = out .. t
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
682 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
683 return out
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
684 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
685
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
686 -- Unescape characters that have been encoded.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
687 local function unescape_special_chars(t)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
688 local tin = t
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
689 for k,v in pairs(escape_table) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
690 k = k:gsub("%%", "%%%%")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
691 t = t:gsub(v,k)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
692 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
693 if t ~= tin then t = unescape_special_chars(t) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
694 return t
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
695 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
696
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
697 -- Encode/escape certain characters inside Markdown code runs.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
698 -- The point is that in code, these characters are literals,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
699 -- and lose their special Markdown meanings.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
700 function encode_code(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
701 s = s:gsub("%&", "&amp;")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
702 s = s:gsub("<", "&lt;")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
703 s = s:gsub(">", "&gt;")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
704 for k,v in pairs(escape_table) do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
705 s = s:gsub("%"..k, v)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
706 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
707 return s
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
708 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
709
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
710 -- Handle backtick blocks.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
711 local function code_spans(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
712 s = s:gsub("\\\\", escape_table["\\"])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
713 s = s:gsub("\\`", escape_table["`"])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
714
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
715 local pos = 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
716 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
717 local start, stop = s:find("`+", pos)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
718 if not start then return s end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
719 local count = stop - start + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
720 -- Find a matching numbert of backticks
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
721 local estart, estop = s:find(string.rep("`", count), stop+1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
722 local brstart = s:find("\n", stop+1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
723 if estart and (not brstart or estart < brstart) then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
724 local code = s:sub(stop+1, estart-1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
725 code = code:gsub("^[ \t]+", "")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
726 code = code:gsub("[ \t]+$", "")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
727 code = code:gsub(escape_table["\\"], escape_table["\\"] .. escape_table["\\"])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
728 code = code:gsub(escape_table["`"], escape_table["\\"] .. escape_table["`"])
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
729 code = "<code>" .. encode_code(code) .. "</code>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
730 code = add_escape(code)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
731 s = s:sub(1, start-1) .. code .. s:sub(estop+1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
732 pos = start + code:len()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
733 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
734 pos = stop + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
735 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
736 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
737 return s
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
738 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
739
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
740 -- Encode alt text... enodes &, and ".
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
741 local function encode_alt(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
742 if not s then return s end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
743 s = s:gsub('&', '&amp;')
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
744 s = s:gsub('"', '&quot;')
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
745 s = s:gsub('<', '&lt;')
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
746 return s
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
747 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
748
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
749 -- Forward declaration for link_db as returned by strip_link_definitions.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
750 local link_database
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
751
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
752 -- Handle image references
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
753 local function images(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
754 local function reference_link(alt, id)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
755 alt = encode_alt(alt:match("%b[]"):sub(2,-2))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
756 id = id:match("%[(.*)%]"):lower()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
757 if id == "" then id = text:lower() end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
758 link_database[id] = link_database[id] or {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
759 if not link_database[id].url then return nil end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
760 local url = link_database[id].url or id
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
761 url = encode_alt(url)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
762 local title = encode_alt(link_database[id].title)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
763 if title then title = " title=\"" .. title .. "\"" else title = "" end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
764 return add_escape ('<img src="' .. url .. '" alt="' .. alt .. '"' .. title .. "/>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
765 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
766
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
767 local function inline_link(alt, link)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
768 alt = encode_alt(alt:match("%b[]"):sub(2,-2))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
769 local url, title = link:match("%(<?(.-)>?[ \t]*['\"](.+)['\"]")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
770 url = url or link:match("%(<?(.-)>?%)")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
771 url = encode_alt(url)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
772 title = encode_alt(title)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
773 if title then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
774 return add_escape('<img src="' .. url .. '" alt="' .. alt .. '" title="' .. title .. '"/>')
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
775 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
776 return add_escape('<img src="' .. url .. '" alt="' .. alt .. '"/>')
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
777 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
778 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
779
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
780 text = text:gsub("!(%b[])[ \t]*\n?[ \t]*(%b[])", reference_link)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
781 text = text:gsub("!(%b[])(%b())", inline_link)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
782 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
783 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
784
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
785 -- Handle anchor references
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
786 local function anchors(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
787 local function reference_link(text, id)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
788 text = text:match("%b[]"):sub(2,-2)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
789 id = id:match("%b[]"):sub(2,-2):lower()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
790 if id == "" then id = text:lower() end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
791 link_database[id] = link_database[id] or {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
792 if not link_database[id].url then return nil end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
793 local url = link_database[id].url or id
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
794 url = encode_alt(url)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
795 local title = encode_alt(link_database[id].title)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
796 if title then title = " title=\"" .. title .. "\"" else title = "" end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
797 return add_escape("<a href=\"" .. url .. "\"" .. title .. ">") .. text .. add_escape("</a>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
798 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
799
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
800 local function inline_link(text, link)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
801 text = text:match("%b[]"):sub(2,-2)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
802 local url, title = link:match("%(<?(.-)>?[ \t]*['\"](.+)['\"]")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
803 title = encode_alt(title)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
804 url = url or link:match("%(<?(.-)>?%)") or ""
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
805 url = encode_alt(url)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
806 if title then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
807 return add_escape("<a href=\"" .. url .. "\" title=\"" .. title .. "\">") .. text .. "</a>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
808 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
809 return add_escape("<a href=\"" .. url .. "\">") .. text .. add_escape("</a>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
810 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
811 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
812
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
813 text = text:gsub("(%b[])[ \t]*\n?[ \t]*(%b[])", reference_link)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
814 text = text:gsub("(%b[])(%b())", inline_link)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
815 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
816 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
817
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
818 -- Handle auto links, i.e. <http://www.google.com/>.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
819 local function auto_links(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
820 local function link(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
821 return add_escape("<a href=\"" .. s .. "\">") .. s .. "</a>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
822 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
823 -- Encode chars as a mix of dec and hex entitites to (perhaps) fool
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
824 -- spambots.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
825 local function encode_email_address(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
826 -- Use a deterministic encoding to make unit testing possible.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
827 -- Code 45% hex, 45% dec, 10% plain.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
828 local hex = {code = function(c) return "&#x" .. string.format("%x", c:byte()) .. ";" end, count = 1, rate = 0.45}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
829 local dec = {code = function(c) return "&#" .. c:byte() .. ";" end, count = 0, rate = 0.45}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
830 local plain = {code = function(c) return c end, count = 0, rate = 0.1}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
831 local codes = {hex, dec, plain}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
832 local function swap(t,k1,k2) local temp = t[k2] t[k2] = t[k1] t[k1] = temp end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
833
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
834 local out = ""
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
835 for i = 1,s:len() do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
836 for _,code in ipairs(codes) do code.count = code.count + code.rate end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
837 if codes[1].count < codes[2].count then swap(codes,1,2) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
838 if codes[2].count < codes[3].count then swap(codes,2,3) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
839 if codes[1].count < codes[2].count then swap(codes,1,2) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
840
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
841 local code = codes[1]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
842 local c = s:sub(i,i)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
843 -- Force encoding of "@" to make email address more invisible.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
844 if c == "@" and code == plain then code = codes[2] end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
845 out = out .. code.code(c)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
846 code.count = code.count - 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
847 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
848 return out
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
849 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
850 local function mail(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
851 s = unescape_special_chars(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
852 local address = encode_email_address("mailto:" .. s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
853 local text = encode_email_address(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
854 return add_escape("<a href=\"" .. address .. "\">") .. text .. "</a>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
855 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
856 -- links
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
857 text = text:gsub("<(https?:[^'\">%s]+)>", link)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
858 text = text:gsub("<(ftp:[^'\">%s]+)>", link)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
859
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
860 -- mail
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
861 text = text:gsub("<mailto:([^'\">%s]+)>", mail)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
862 text = text:gsub("<([-.%w]+%@[-.%w]+)>", mail)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
863 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
864 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
865
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
866 -- Encode free standing amps (&) and angles (<)... note that this does not
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
867 -- encode free >.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
868 local function amps_and_angles(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
869 -- encode amps not part of &..; expression
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
870 local pos = 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
871 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
872 local amp = s:find("&", pos)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
873 if not amp then break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
874 local semi = s:find(";", amp+1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
875 local stop = s:find("[ \t\n&]", amp+1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
876 if not semi or (stop and stop < semi) or (semi - amp) > 15 then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
877 s = s:sub(1,amp-1) .. "&amp;" .. s:sub(amp+1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
878 pos = amp+1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
879 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
880 pos = amp+1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
881 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
882 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
883
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
884 -- encode naked <'s
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
885 s = s:gsub("<([^a-zA-Z/?$!])", "&lt;%1")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
886 s = s:gsub("<$", "&lt;")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
887
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
888 -- what about >, nothing done in the original markdown source to handle them
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
889 return s
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
890 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
891
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
892 -- Handles emphasis markers (* and _) in the text.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
893 local function emphasis(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
894 for _, s in ipairs {"%*%*", "%_%_"} do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
895 text = text:gsub(s .. "([^%s][%*%_]?)" .. s, "<strong>%1</strong>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
896 text = text:gsub(s .. "([^%s][^<>]-[^%s][%*%_]?)" .. s, "<strong>%1</strong>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
897 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
898 for _, s in ipairs {"%*", "%_"} do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
899 text = text:gsub(s .. "([^%s_])" .. s, "<em>%1</em>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
900 text = text:gsub(s .. "(<strong>[^%s_]</strong>)" .. s, "<em>%1</em>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
901 text = text:gsub(s .. "([^%s_][^<>_]-[^%s_])" .. s, "<em>%1</em>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
902 text = text:gsub(s .. "([^<>_]-<strong>[^<>_]-</strong>[^<>_]-)" .. s, "<em>%1</em>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
903 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
904 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
905 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
906
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
907 -- Handles line break markers in the text.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
908 local function line_breaks(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
909 return text:gsub(" +\n", " <br/>\n")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
910 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
911
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
912 -- Perform all span level transforms.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
913 function span_transform(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
914 text = code_spans(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
915 text = escape_special_chars(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
916 text = images(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
917 text = anchors(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
918 text = auto_links(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
919 text = amps_and_angles(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
920 text = emphasis(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
921 text = line_breaks(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
922 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
923 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
924
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
925 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
926 -- Markdown
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
927 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
928
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
929 -- Cleanup the text by normalizing some possible variations to make further
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
930 -- processing easier.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
931 local function cleanup(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
932 -- Standardize line endings
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
933 text = text:gsub("\r\n", "\n") -- DOS to UNIX
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
934 text = text:gsub("\r", "\n") -- Mac to UNIX
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
935
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
936 -- Convert all tabs to spaces
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
937 text = detab(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
938
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
939 -- Strip lines with only spaces and tabs
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
940 while true do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
941 local subs
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
942 text, subs = text:gsub("\n[ \t]+\n", "\n\n")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
943 if subs == 0 then break end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
944 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
945
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
946 return "\n" .. text .. "\n"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
947 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
948
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
949 -- Strips link definitions from the text and stores the data in a lookup table.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
950 local function strip_link_definitions(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
951 local linkdb = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
952
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
953 local function link_def(id, url, title)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
954 id = id:match("%[(.+)%]"):lower()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
955 linkdb[id] = linkdb[id] or {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
956 linkdb[id].url = url or linkdb[id].url
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
957 linkdb[id].title = title or linkdb[id].title
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
958 return ""
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
959 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
960
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
961 local def_no_title = "\n ? ? ?(%b[]):[ \t]*\n?[ \t]*<?([^%s>]+)>?[ \t]*"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
962 local def_title1 = def_no_title .. "[ \t]+\n?[ \t]*[\"'(]([^\n]+)[\"')][ \t]*"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
963 local def_title2 = def_no_title .. "[ \t]*\n[ \t]*[\"'(]([^\n]+)[\"')][ \t]*"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
964 local def_title3 = def_no_title .. "[ \t]*\n?[ \t]+[\"'(]([^\n]+)[\"')][ \t]*"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
965
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
966 text = text:gsub(def_title1, link_def)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
967 text = text:gsub(def_title2, link_def)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
968 text = text:gsub(def_title3, link_def)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
969 text = text:gsub(def_no_title, link_def)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
970 return text, linkdb
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
971 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
972
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
973 -- Main markdown processing function
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
974 local function markdown(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
975 init_hash(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
976 init_escape_table()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
977
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
978 text = cleanup(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
979 text = protect(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
980 text, link_database = strip_link_definitions(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
981 text = block_transform(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
982 text = unescape_special_chars(text)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
983 return text
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
984 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
985
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
986 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
987 -- End of module
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
988 ----------------------------------------------------------------------
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
989
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
990 -- For compatibility, set markdown function as a global
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
991 _G.markdown = markdown
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
992
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
993 -- Class for parsing command-line options
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
994 local OptionParser = {}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
995 OptionParser.__index = OptionParser
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
996
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
997 -- Creates a new option parser
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
998 function OptionParser:new()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
999 local o = {short = {}, long = {}}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1000 setmetatable(o, self)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1001 return o
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1002 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1003
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1004 -- Calls f() whenever a flag with specified short and long name is encountered
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1005 function OptionParser:flag(short, long, f)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1006 local info = {type = "flag", f = f}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1007 if short then self.short[short] = info end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1008 if long then self.long[long] = info end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1009 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1010
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1011 -- Calls f(param) whenever a parameter flag with specified short and long name is encountered
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1012 function OptionParser:param(short, long, f)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1013 local info = {type = "param", f = f}
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1014 if short then self.short[short] = info end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1015 if long then self.long[long] = info end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1016 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1017
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1018 -- Calls f(v) for each non-flag argument
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1019 function OptionParser:arg(f)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1020 self.arg = f
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1021 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1022
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1023 -- Runs the option parser for the specified set of arguments. Returns true if all arguments
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1024 -- where successfully parsed and false otherwise.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1025 function OptionParser:run(args)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1026 local pos = 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1027 while pos <= #args do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1028 local arg = args[pos]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1029 if arg == "--" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1030 for i=pos+1,#args do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1031 if self.arg then self.arg(args[i]) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1032 return true
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1033 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1034 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1035 if arg:match("^%-%-") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1036 local info = self.long[arg:sub(3)]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1037 if not info then print("Unknown flag: " .. arg) return false end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1038 if info.type == "flag" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1039 info.f()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1040 pos = pos + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1041 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1042 local param = args[pos+1]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1043 if not param then print("No parameter for flag: " .. arg) return false end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1044 info.f(param)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1045 pos = pos+2
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1046 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1047 elseif arg:match("^%-") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1048 for i=2,arg:len() do
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1049 local c = arg:sub(i,i)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1050 local info = self.short[c]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1051 if not info then print("Unknown flag: -" .. c) return false end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1052 if info.type == "flag" then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1053 info.f()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1054 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1055 if i == arg:len() then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1056 local param = args[pos+1]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1057 if not param then print("No parameter for flag: -" .. c) return false end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1058 info.f(param)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1059 pos = pos + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1060 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1061 local param = arg:sub(i+1)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1062 info.f(param)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1063 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1064 break
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1065 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1066 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1067 pos = pos + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1068 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1069 if self.arg then self.arg(arg) end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1070 pos = pos + 1
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1071 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1072 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1073 return true
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1074 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1075
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1076 local function read_file(path, descr)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1077 local file = io.open(path) or error("Could not open " .. descr .. " file: " .. path)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1078 local contents = file:read("*a") or error("Could not read " .. descr .. " from " .. path)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1079 file:close()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1080 return contents
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1081 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1082
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1083 -- Handles the case when markdown is run from the command line
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1084 local function run_command_line(arg)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1085 -- Generate output for input s given options
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1086 local function run(s, options)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1087 s = markdown(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1088 if not options.wrap_header then return s end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1089 local header
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1090 if options.header then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1091 header = read_file(options.header, "header")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1092 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1093 header = [[
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1094 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1095 <html>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1096 <head>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1097 <meta http-equiv="content-type" content="text/html; charset=CHARSET" />
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1098 <title>TITLE</title>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1099 <link rel="stylesheet" type="text/css" href="STYLESHEET" />
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1100 </head>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1101 <body>
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1102 ]]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1103 local title = options.title or s:match("<h1>(.-)</h1>") or s:match("<h2>(.-)</h2>") or
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1104 s:match("<h3>(.-)</h3>") or "Untitled"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1105 header = header:gsub("TITLE", title)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1106 if options.inline_style then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1107 local style = read_file(options.stylesheet, "style sheet")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1108 header = header:gsub('<link rel="stylesheet" type="text/css" href="STYLESHEET" />',
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1109 "<style type=\"text/css\"><!--\n" .. style .. "\n--></style>")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1110 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1111 header = header:gsub("STYLESHEET", options.stylesheet)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1112 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1113 header = header:gsub("CHARSET", options.charset)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1114 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1115 local footer = "</body></html>"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1116 if options.footer then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1117 footer = read_file(options.footer, "footer")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1118 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1119 return header .. s .. footer
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1120 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1121
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1122 -- Generate output path name from input path name given options.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1123 local function outpath(path, options)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1124 if options.append then return path .. ".html" end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1125 local m = path:match("^(.+%.html)[^/\\]+$") if m then return m end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1126 m = path:match("^(.+%.)[^/\\]*$") if m and path ~= m .. "html" then return m .. "html" end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1127 return path .. ".html"
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1128 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1129
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1130 -- Default commandline options
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1131 local options = {
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1132 wrap_header = true,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1133 header = nil,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1134 footer = nil,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1135 charset = "utf-8",
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1136 title = nil,
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1137 stylesheet = "default.css",
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1138 inline_style = false
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1139 }
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1140 local help = [[
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1141 Usage: markdown.lua [OPTION] [FILE]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1142 Runs the markdown text markup to HTML converter on each file specified on the
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1143 command line. If no files are specified, runs on standard input.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1144
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1145 No header:
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1146 -n, --no-wrap Don't wrap the output in <html>... tags.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1147 Custom header:
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1148 -e, --header FILE Use content of FILE for header.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1149 -f, --footer FILE Use content of FILE for footer.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1150 Generated header:
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1151 -c, --charset SET Specifies charset (default utf-8).
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1152 -i, --title TITLE Specifies title (default from first <h1> tag).
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1153 -s, --style STYLE Specifies style sheet file (default default.css).
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1154 -l, --inline-style Include the style sheet file inline in the header.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1155 Generated files:
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1156 -a, --append Append .html extension (instead of replacing).
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1157 Other options:
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1158 -h, --help Print this help text.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1159 -t, --test Run the unit tests.
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1160 ]]
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1161
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1162 local run_stdin = true
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1163 local op = OptionParser:new()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1164 op:flag("n", "no-wrap", function () options.wrap_header = false end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1165 op:param("e", "header", function (x) options.header = x end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1166 op:param("f", "footer", function (x) options.footer = x end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1167 op:param("c", "charset", function (x) options.charset = x end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1168 op:param("i", "title", function(x) options.title = x end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1169 op:param("s", "style", function(x) options.stylesheet = x end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1170 op:flag("l", "inline-style", function() options.inline_style = true end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1171 op:flag("a", "append", function() options.append = true end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1172 op:flag("t", "test", function()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1173 local n = arg[0]:gsub("markdown%.lua", "markdown-tests.lua")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1174 local f = io.open(n)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1175 if f then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1176 f:close()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1177 package.loaded.markdown = markdown
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1178 dofile(n)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1179 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1180 error("Cannot find markdown-tests.lua")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1181 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1182 run_stdin = false
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1183 end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1184 op:flag("h", "help", function() print(help) run_stdin = false end)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1185 op:arg(function(path)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1186 local s = read_file(path, "input")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1187 s = run(s, options)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1188 local file = io.open(outpath(path, options), "w") or error("Could not open output file: " .. outpath(path, options))
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1189 file:write(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1190 file:close()
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1191 run_stdin = false
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1192 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1193 )
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1194
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1195 if not op:run(arg) then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1196 print(help)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1197 run_stdin = false
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1198 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1199
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1200 if run_stdin then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1201 local s = io.read("*a")
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1202 s = run(s, options)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1203 io.write(s)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1204 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1205 end
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1206
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1207 -- If we are being run from the command-line, act accordingly
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1208 if arg and arg[0]:find("markdown%.lua$") then
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1209 run_command_line(arg)
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1210 else
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1211 return markdown
836dac92eced Update markdown; now Lua 5.3 compatible
Tuomo Valkonen <tuomov@iki.fi>
parents: 6
diff changeset
1212 end

mercurial