aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/notYetAnotherWiki.lua
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xnotYetAnotherWiki.lua213
1 files changed, 145 insertions, 68 deletions
diff --git a/notYetAnotherWiki.lua b/notYetAnotherWiki.lua
index 7268170..8c9a5c9 100755
--- a/notYetAnotherWiki.lua
+++ b/notYetAnotherWiki.lua
@@ -2,13 +2,63 @@
2 2
3-- Read the README file for what this is all about. If there is no README or similar, then you can find the link to the source below. 3-- Read the README file for what this is all about. If there is no README or similar, then you can find the link to the source below.
4 4
5local lcmark = require("lcmark") -- https://github.com/jgm/lcmark 5local lunamark = require("lunamark") -- https://github.com/jgm/lunamark
6
7local opts = {
8 layout='compact',
9-- This list is copied from the lunamark source code, until I discover a way to discover it. The descriptions are useful to.
10 containers=false, -- Put sections in containers (e.g. div or section tags)
11 slides=false, -- Like containers, but do not nest them
12 startnum=true, -- Start number of an ordered list is significant
13 smart=false, -- Smart typography (quotes, dashes, ellipses)
14 preserve_tabs=true, -- Don't expand tabs to spaces
15 notes=true, -- Footnotes
16 inline_notes=true, -- Inline footnotes
17 definition_lists=true, -- Definition lists
18 citations=true, -- Citations
19 citation_nbsps=true, -- Turn spacing into non-breaking spaces in citations
20 fenced_code_blocks=true, -- Fenced code blocks
21 lua_metadata=true, -- Lua metadata
22 pandoc_title_blocks=true, -- Pandoc style title blocks
23 hash_enumerators=true, -- may be used as ordered list enumerator
24 require_blank_before_blockquote=false,
25 require_blank_before_header=false,
26 require_blank_before_fenced_code_block=false,
27 fancy_lists=true, -- Pandoc style fancy lists
28 task_list=true, -- GitHub-Flavored Markdown task list
29 strikeout=true, -- Strike-through with double tildes
30 mark=true, -- Highlight with double equals
31 subscript=true, -- Subscripted text between tildes
32 superscript=true, -- Superscripted text between circumflexes
33 bracketed_spans=true, -- Spans with attributes
34 fenced_divs=true, -- Divs with attributes
35 raw_attribute=true, -- Raw pass-through on code elements
36 fenced_code_attributes=true, -- Fenced code block attributes
37 link_attributes=true, -- Link attributes
38 pipe_tables=true, -- PHP Markdown Extra pipe table support
39 table_captions=true, -- Table caption syntax extension
40 header_attributes=true, -- Header attributes
41 line_blocks=true, -- Line blocks
42 escaped_line_breaks=true, -- Pandoc-style escaped hard line breaks
43}
44local writer = lunamark.writer.html5.new(opts)
45local template = ''
46local h = io.open("default.template", 'r')
47if nil ~= h then
48 template = h:read('*a')
49 h:close()
50else
51 print('oops! No such file ' .. 'default.template')
52end
53-- Can override the various writer functions, there's something for each of the basic HTML elements.
54-- Override anything that's generic.
55local parse = lunamark.reader.markdown.new(writer, opts)
6 56
7 57
8 58
9-- Some global data. 59-- Some global data.
10local globalData = { 60local globalData = {
11 ['_'] = ' ', ['dlr'] = '$', 61 ['s'] = ' ', ['_'] = ' ', ['dlr'] = '$',
12 ['devuanCinnabarDark'] = '#310202', ['devuanCinnabarLight'] = '#510505', 62 ['devuanCinnabarDark'] = '#310202', ['devuanCinnabarLight'] = '#510505',
13 ['devuanDarkPurpyDark'] = '#33313b', ['devuanDarkPurpyLight'] = '#3c3a45', 63 ['devuanDarkPurpyDark'] = '#33313b', ['devuanDarkPurpyLight'] = '#3c3a45',
14 ['devuanDeepSeaDark'] = '#132f40', ['devuanDeepSeaLight'] = '#1a4562', 64 ['devuanDeepSeaDark'] = '#132f40', ['devuanDeepSeaLight'] = '#1a4562',
@@ -23,7 +73,7 @@ local Sites, Files, Subs = {}, {}, {}
23 73
24-- Useful functions, part 0. 74-- Useful functions, part 0.
25 75
26-- A simple table.subtable = subtable wont work, you end up with a reference so that changes to the later get applaid to the former. 76-- A simple table.subtable = subtable wont work, you end up with a reference so that changes to the later get applied to the former.
27local derefiTable = function(t, strip) 77local derefiTable = function(t, strip)
28 local argh = {} 78 local argh = {}
29 for l, y in ipairs(t) do if (l ~= y.name) and strip then table.insert(argh, y) end end 79 for l, y in ipairs(t) do if (l ~= y.name) and strip then table.insert(argh, y) end end
@@ -50,29 +100,47 @@ local stringBits = function(l)
50end 100end
51 101
52 102
103-- Put a value into the Files or Subs table, creating things if needed.
104local toFile = function(name, key, value)
105 if nil == Files[name] then Files[name] = {} end
106 if nil ~= key then Files[name][key] = value end
107 for i, v in ipairs{'metadata', 'bits', } do
108 if nil == Files[name][v] then Files[name][v] = {} end
109 end
110end
111local toSub = function(name, key, value)
112 if nil == Subs[name] then Subs[name] = {} end
113 if nil ~= key then Subs[name][key] = value end
114 for i, v in ipairs{'metadata', 'bits', 'files', 'subs'} do
115 if nil == Subs[name][v] then Subs[name][v] = {} end
116 end
117end
118
119
53 120
54-- Actually start doing things. 121-- Actually start doing things.
55 122
56-- Scan the subdirectories looking for .md files. 123-- Scan the subdirectories looking for .md files.
57local directory = arg[1] 124local directory = arg[1]
125toSub('') --Subs[''] = {files = {}, subs = {}, bits = {}}
58if nil == directory then directory = '.' end 126if nil == directory then directory = '.' end
59if '.' ~= directory then 127if '.' ~= directory then
60 for l in io.popen('find . -name "*.md" -type f,l -printf "%P\n"'):lines() do 128 for l in io.popen('find . -name "*.md" -type f,l -printf "%P\n"'):lines() do
61 Files[string.gsub(l, '%.md$', '')] = {} 129 toFile(string.gsub(l, '%.md$', ''))
62 end 130 end
63end 131end
64-- Can add in a distant directory to, for putting it's results in the current directory. 132-- Can add in a distant directory to, for putting it's results in the current directory.
65for l in io.popen('find ' .. directory .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do 133for l in io.popen('find ' .. directory .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do
66 local n = string.gsub(l, '%.md$', '') 134 local n = string.gsub(l, '%.md$', '')
67 if nil == Files[n] then Files[n] = {} end 135 if nil == Files[n] then toFile(n) end
68end 136end
69 137
70-- Gotta figure out all the files and subs first. File and sub metadata comes along for the ride. 138-- Gotta figure out all the files and subs first. File and sub metadata comes along for the ride.
71Subs[''] = {files = {}, subs = {}, bits = {}}
72for name, file in pairs(Files) do 139for name, file in pairs(Files) do
73 local bitter, path = '', '' 140 local bitter, path = '', ''
74 local bits, bit = stringBits(name) 141 local bits, bit = stringBits(name)
75 local ln = #bits 142 local ln = #bits
143 local body, metadata = '', {}
76 144
77 -- Go through our bits, construct Subs with bits. 145 -- Go through our bits, construct Subs with bits.
78 Files[name].bits = bits 146 Files[name].bits = bits
@@ -82,41 +150,61 @@ for name, file in pairs(Files) do
82 for i, d in ipairs(bits) do 150 for i, d in ipairs(bits) do
83 if '' ~= path then path = path .. '/' end 151 if '' ~= path then path = path .. '/' end
84 path = path .. d 152 path = path .. d
85 if nil == Subs[path] then Subs[path] = {files = {}, subs = {}} end 153 toSub(path, 'bits', derefiTable(bits, true))
86 if i < ln then Subs[path].subs[bits[i + 1]] = bits[i + 1] end 154 if i < ln then Subs[path].subs[bits[i + 1]] = bits[i + 1] end
87 Subs[path].bits = derefiTable(bits, true)
88 if i < ln then table.remove(Subs[path].bits, #bits) end 155 if i < ln then table.remove(Subs[path].bits, #bits) end
89 end 156 end
90 157
91 -- Start the file parsing here, coz we need it's metadata. 158 if '.md' == string.sub(name, -3, -1) then
92-- print('Parsing ' .. name .. '.md') 159 -- This is a metadata only file, no content, stash the matadata.
93 local h = io.open(name .. '.md', 'r') 160 for l in io.open(name .. '.md'):lines() do
94-- TODO - should bail here on error? 161 for k, v in string.gmatch(l, "(%w+)%s*=%s*(.+)") do metadata[k] = v end
95 if nil ~= h then file.cm = h:read('*a') ; h:close() else print('oops! No such name ' .. name) end 162 end
96 -- Convert the CommonMark to HTML, including the metadata. 163 if '.md' == name then toSub(path, 'metadata', metadata)
97 local body, metadata, err = lcmark.convert(file.cm, "html", {smart = true, yaml_metadata = true, columns = 0}) 164 elseif '/.md' == string.sub(name, -4, -1) then toSub(path, 'metadata', metadata)
98 if nil == body then print('oops! ' .. err) 165 else toFile(string.sub(name, 1, -4), 'metadata', metadata)
99 elseif '' == body then 166 end
100 -- This is a metadata only file, no content, stash the matadata in it's directory.
101 Subs[path].metadata = metadata
102 Files[name] = nil 167 Files[name] = nil
103 else 168 else
104 -- Ordinary md file, stash it's metadata and parsed body. 169
105 -- I need cmark-gfm, coz lcmark doesn't support tables and stuff, it only does basic cmark. 170 -- Start the file parsing here, coz we need it's metadata.
106 local out = '' 171-- print('Parsing ' .. name .. '.md')
107 h = io.popen('if which cmark-gfm ; then echo "found" ; fi | tail -n 1') 172 h = io.open(name .. '.md', 'r')
108 if nil ~= h then out = h:read('*a') ; h:close() end 173 if nil ~= h then
109 if 'found\n' == out then 174 body = h:read('*a') ; h:close()
110 -- Have to strip out the metadata first, coz cmark-gfm doesn't grok that. 175 local f0, f1, token
111 h = io.popen('cp "' .. name .. '.md" "' .. name .. '02" ; csplit -ksz -f "' .. name .. '" "' .. name .. '.md" "/^---$/+1" "{1}" 2>/dev/null ; rm "' .. name .. '00" ; rm "' .. name .. '01" 2>/dev/null') 176 -- Deal with my typical double spaced sentence endings.
112 if nil ~= h then h:close() end 177 local result = ''
113 h = io.popen('cmark-gfm -t html -e footnotes -e table -e strikethrough -e autolink -e tagfilter -e tasklist "' .. name .. '02" ; rm "' .. name .. '02"') 178 local start = 1
114 if nil ~= h then body = h:read('*a') ; h:close() end 179 repeat
115 else 180 f0, f1, token = string.find(body, '([%.%?%!] )', start)
116 print('cmark-gfm not found') 181 if fail ~= f0 then
182 result = result .. string.sub(body, start, f0)
183 if ' ' == string.sub(body, f1 + 1, f1 + 1) then
184 result = result .. '$s$ ' -- '&nbsp;' gets turned into hex 0xA0 by parse(). So feed it another metadata token that gets translated to &nbsp;.
185 else
186 result = result .. ' '
187 end
188 start = f1 + 1
189 end
190 until fail == f0
191 result = result .. string.sub(body, start)
192 -- Do the same for fixing the \' \" \| etc mess pandoc left that sed can't fix.
193 body = result
194 result = ''
195 start = 1
196 repeat
197 f0, f1, token = string.find(body, '(%\\[%"%\'%|%$])', start)
198 if fail ~= f0 then
199 result = result .. string.sub(body, start, f0 - 1)
200 start = f1
201 end
202 until fail == f0
203 result = result .. string.sub(body, start)
204
205 body = parse(result)
117 end 206 end
118 Files[name].metadata = metadata 207 toFile(name, 'body', body)
119 Files[name].body = body
120 table.insert(Subs[path].files, bit) 208 table.insert(Subs[path].files, bit)
121 end 209 end
122end 210end
@@ -181,6 +269,10 @@ end
181 269
182 270
183 271
272-- TODO - loop through Subs, doing whichPage and inheritance.
273
274
275
184-- More of this actually doing things nonsense. 276-- More of this actually doing things nonsense.
185 277
186-- Loop through the files we found and actually create their HTML files. 278-- Loop through the files we found and actually create their HTML files.
@@ -193,14 +285,6 @@ for name, file in pairs(Files) do
193 path = table.concat(bits, '/', 1, ln) 285 path = table.concat(bits, '/', 1, ln)
194 286
195 if '' ~= body then 287 if '' ~= body then
196 -- Continue the parsing and conversion. Start by turning our parsed body into something the lcmark template system can grock.
197 local bod, err = lcmark.compile_template(body)
198 if nil == bod then print('oops! ' .. err) else
199 local templateFile = metadata.template
200 if nil == templateFile then templateFile = 'default' end
201 file.template = templateFile .. '.template'
202 end
203
204 -- Copy any metadata found in parent directories. 288 -- Copy any metadata found in parent directories.
205 local pth = '' 289 local pth = ''
206 for i, d in ipairs(bits) do 290 for i, d in ipairs(bits) do
@@ -287,7 +371,6 @@ for name, file in pairs(Files) do
287 metadata.trail = metadata.trail .. b .. ' &nbsp; ' 371 metadata.trail = metadata.trail .. b .. ' &nbsp; '
288 end 372 end
289 end 373 end
290-- if '' == metadata.trail then metadata.trail = '<a href="' .. string.rep('../', ln) .. '/' .. whichPage('') .. '">home</a> &nbsp; ' end
291 374
292 -- Figure out this pages footer links. 375 -- Figure out this pages footer links.
293 if nil ~= metadata.pagehistory then metadata.history = '<p>Page&nbsp;<a href="' .. metadata.pagehistory .. '/' .. name .. '.md">history</a></p>' end 376 if nil ~= metadata.pagehistory then metadata.history = '<p>Page&nbsp;<a href="' .. metadata.pagehistory .. '/' .. name .. '.md">history</a></p>' end
@@ -296,29 +379,26 @@ for name, file in pairs(Files) do
296 if metadata.footer ~= globalData.footer then metadata.footer = 'Web site ' .. metadata.footer end 379 if metadata.footer ~= globalData.footer then metadata.footer = 'Web site ' .. metadata.footer end
297 metadata.footer = '<p>' .. metadata.footer .. '</p>' 380 metadata.footer = '<p>' .. metadata.footer .. '</p>'
298 381
299 -- Apply the template to the body. 382 -- Do our own metadata replacement, it's simple and works better.
300 metadata.body = lcmark.apply_template(bod, metadata) 383 local temp = template
301 384 local start = 1
302 -- Put it all in the template. 385 metadata.body = nil
303 local tm = '' 386 local f0, f1, token
304 if nil ~= file.template then 387 -- Toss the body in first, so the scan can deal with it to.
305 local h = io.open(file.template, 'r') 388 f0, f1, token = string.find(temp, '%$(body)%$')
306 if nil ~= h then 389 if fail ~= f0 then
307 tm = tm .. h:read('*a') 390 temp = string.sub(temp, 1, f0 - 1) .. body .. string.sub(temp, f1 + 1)
308 h:close()
309 else
310 print('oops! No such file ' .. file.template)
311 end
312
313-- TODO - Um not sure why this is here AND at the top of the loop. Here makes more sense.
314 local template, err = lcmark.compile_template(tm)
315 if nil == template then print('oops! ' .. err) else
316 result = lcmark.apply_template(template, metadata)
317 end
318 else
319 print('No template for ' .. name)
320 result = body
321 end 391 end
392 -- The actual metadata replacement scan.
393 result = ''
394 repeat
395 f0, f1, token = string.find(temp, '%$([%w_]+)%$', start)
396 if fail ~= f0 then
397 if nil ~= metadata[token] then result = result .. string.sub(temp, start, f0 - 1) .. metadata[token] end
398 start = f1 + 1
399 end
400 until fail == f0
401 result = result .. string.sub(temp, start)
322 402
323 -- Write the file. 403 -- Write the file.
324 if '' ~= result then 404 if '' ~= result then
@@ -330,9 +410,6 @@ for name, file in pairs(Files) do
330 a:close() 410 a:close()
331 end 411 end
332 end 412 end
333
334-- else
335-- print('')
336 end 413 end
337end 414end
338 415