diff options
| -rwxr-xr-x | notYetAnotherWiki.lua | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/notYetAnotherWiki.lua b/notYetAnotherWiki.lua index 1343739..3bcc7d9 100755 --- a/notYetAnotherWiki.lua +++ b/notYetAnotherWiki.lua | |||
| @@ -1,9 +1,12 @@ | |||
| 1 | #!/usr/bin/env luajit | 1 | #!/usr/bin/env luajit |
| 2 | 2 | ||
| 3 | local lcmark = require("lcmark") | 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 | ||
| 5 | local lcmark = require("lcmark") -- https://github.com/jgm/lcmark | ||
| 5 | 6 | ||
| 6 | 7 | ||
| 8 | |||
| 9 | -- Some global data. | ||
| 7 | local globalData = { | 10 | local globalData = { |
| 8 | ['_'] = ' ', ['dlr'] = '$', ['karenpurple'] = '#8800ff', | 11 | ['_'] = ' ', ['dlr'] = '$', ['karenpurple'] = '#8800ff', |
| 9 | favicon = 'nYAW_icon.png', logo = 'nYAW.png', header = '', --menu = '', | 12 | favicon = 'nYAW_icon.png', logo = 'nYAW.png', header = '', --menu = '', |
| @@ -12,15 +15,18 @@ local globalData = { | |||
| 12 | local Sites, Files, Subs = {}, {}, {} | 15 | local Sites, Files, Subs = {}, {}, {} |
| 13 | 16 | ||
| 14 | 17 | ||
| 18 | |||
| 19 | -- Useful functions, part 0. | ||
| 20 | |||
| 21 | -- A simple table.subtable = subtable wont work, you end up with a reference so that changes to the later get applaid to the former. | ||
| 15 | local copyTable = function(t, strip) | 22 | local copyTable = function(t, strip) |
| 16 | -- A simple table.subtable = subtable wont work, you end up with a reference so that changes to the later get applaid to the former. | ||
| 17 | local argh = {} | 23 | local argh = {} |
| 18 | for l, y in ipairs(t) do | 24 | for l, y in ipairs(t) do if (l ~= y.name) and strip then table.insert(argh, y) end end |
| 19 | if (l ~= y.name) and strip then table.insert(argh, y) end | ||
| 20 | end | ||
| 21 | return argh | 25 | return argh |
| 22 | end | 26 | end |
| 23 | 27 | ||
| 28 | |||
| 29 | -- String together the bits array into a path string. | ||
| 24 | local stringBits = function(l) | 30 | local stringBits = function(l) |
| 25 | local bits = {} | 31 | local bits = {} |
| 26 | local last = 1 | 32 | local last = 1 |
| @@ -35,6 +41,9 @@ end | |||
| 35 | 41 | ||
| 36 | 42 | ||
| 37 | 43 | ||
| 44 | -- Actually start doing things. | ||
| 45 | |||
| 46 | -- Scan the subdirectories looking for .md files. | ||
| 38 | local directory = arg[1] | 47 | local directory = arg[1] |
| 39 | if nil == directory then directory = '.' end | 48 | if nil == directory then directory = '.' end |
| 40 | if '.' ~= directory then | 49 | if '.' ~= directory then |
| @@ -42,6 +51,7 @@ if '.' ~= directory then | |||
| 42 | Files[string.gsub(l, '%.md$', '')] = {} | 51 | Files[string.gsub(l, '%.md$', '')] = {} |
| 43 | end | 52 | end |
| 44 | end | 53 | end |
| 54 | -- Can add in a distant directory to, for putting it's results in the current directory. | ||
| 45 | for l in io.popen('find ' .. directory .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do | 55 | for l in io.popen('find ' .. directory .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do |
| 46 | local n = string.gsub(l, '%.md$', '') | 56 | local n = string.gsub(l, '%.md$', '') |
| 47 | if nil == Files[n] then Files[n] = {} end | 57 | if nil == Files[n] then Files[n] = {} end |
| @@ -54,6 +64,7 @@ for name, file in pairs(Files) do | |||
| 54 | local bits, bit = stringBits(name) | 64 | local bits, bit = stringBits(name) |
| 55 | local ln = #bits | 65 | local ln = #bits |
| 56 | 66 | ||
| 67 | -- Go through our bits, construct Subs with bits. | ||
| 57 | Files[name].bits = bits | 68 | Files[name].bits = bits |
| 58 | Files[name].bit = bit | 69 | Files[name].bit = bit |
| 59 | if ln > 0 then bitter = bits[1] end | 70 | if ln > 0 then bitter = bits[1] end |
| @@ -67,16 +78,20 @@ for name, file in pairs(Files) do | |||
| 67 | if i < ln then table.remove(Subs[path].bits, #bits) end | 78 | if i < ln then table.remove(Subs[path].bits, #bits) end |
| 68 | end | 79 | end |
| 69 | 80 | ||
| 81 | -- Start the file parsing here, coz we need it's metadata. | ||
| 70 | print('Parsing ' .. name .. '.md') | 82 | print('Parsing ' .. name .. '.md') |
| 71 | local h = io.open(name .. '.md', 'r') | 83 | local h = io.open(name .. '.md', 'r') |
| 72 | -- TODO - should bail here on error? | 84 | -- TODO - should bail here on error? |
| 73 | if nil ~= h then file.cm = h:read('*a') ; h:close() else print('oops! No such name ' .. name) end | 85 | if nil ~= h then file.cm = h:read('*a') ; h:close() else print('oops! No such name ' .. name) end |
| 86 | -- Convert the CommonMark to HTML, including the metadata. | ||
| 74 | local body, metadata, err = lcmark.convert(file.cm, "html", {smart = true, yaml_metadata = true, columns = 0}) | 87 | local body, metadata, err = lcmark.convert(file.cm, "html", {smart = true, yaml_metadata = true, columns = 0}) |
| 75 | if nil == body then print('oops! ' .. err) | 88 | if nil == body then print('oops! ' .. err) |
| 76 | elseif '' == body then | 89 | elseif '' == body then |
| 90 | -- This is a metadata only file, no content, stash the matadata in it's directory. | ||
| 77 | Subs[path].metadata = metadata | 91 | Subs[path].metadata = metadata |
| 78 | Files[name] = nil | 92 | Files[name] = nil |
| 79 | else | 93 | else |
| 94 | -- Ordinary md file, stash it's metadata and parsed body. | ||
| 80 | file.metadata = metadata | 95 | file.metadata = metadata |
| 81 | file.body = body | 96 | file.body = body |
| 82 | table.insert(Subs[path].files, bit) | 97 | table.insert(Subs[path].files, bit) |
| @@ -86,10 +101,13 @@ end | |||
| 86 | 101 | ||
| 87 | 102 | ||
| 88 | -- These functions assume the above file and sub scan has completed. | 103 | -- These functions assume the above file and sub scan has completed. |
| 104 | |||
| 105 | -- Which page in this directory should we show? | ||
| 89 | local whichPage = function(f) | 106 | local whichPage = function(f) |
| 90 | local fl = '' | 107 | local fl = '' |
| 91 | if (nil ~= Subs[f]) then | 108 | if (nil ~= Subs[f]) then |
| 92 | if 1 == #(Subs[f].files) then fl = Subs[f].files[1] .. '.HTML' else | 109 | if 1 == #(Subs[f].files) then fl = Subs[f].files[1] .. '.HTML' else |
| 110 | -- Standard files to search for. | ||
| 93 | for i, v in ipairs{'README', 'readme', 'INDEX', 'index'} do | 111 | for i, v in ipairs{'README', 'readme', 'INDEX', 'index'} do |
| 94 | for j, w in ipairs(Subs[f].files) do | 112 | for j, w in ipairs(Subs[f].files) do |
| 95 | if v == w then | 113 | if v == w then |
| @@ -106,6 +124,7 @@ local whichPage = function(f) | |||
| 106 | end | 124 | end |
| 107 | 125 | ||
| 108 | 126 | ||
| 127 | -- Calculate a link from the source directory to the destination directory. | ||
| 109 | local linkFrom = function(source, dest) | 128 | local linkFrom = function(source, dest) |
| 110 | local depth = 0 | 129 | local depth = 0 |
| 111 | local link = '' | 130 | local link = '' |
| @@ -133,6 +152,9 @@ end | |||
| 133 | 152 | ||
| 134 | 153 | ||
| 135 | 154 | ||
| 155 | -- More of this actually doing things nonsense. | ||
| 156 | |||
| 157 | -- Loop through the files we found and actually create their HTML files. | ||
| 136 | for name, file in pairs(Files) do | 158 | for name, file in pairs(Files) do |
| 137 | local path, result = '', '' | 159 | local path, result = '', '' |
| 138 | local body, metadata = Files[name].body, Files[name].metadata | 160 | local body, metadata = Files[name].body, Files[name].metadata |
| @@ -142,6 +164,7 @@ for name, file in pairs(Files) do | |||
| 142 | path = table.concat(bits, '/', 1, ln) | 164 | path = table.concat(bits, '/', 1, ln) |
| 143 | 165 | ||
| 144 | if '' ~= body then | 166 | if '' ~= body then |
| 167 | -- Continue the parsing and conversion. Start by turning our parsed body into something the lcmark template system can grock. | ||
| 145 | local bod, err = lcmark.compile_template(body) | 168 | local bod, err = lcmark.compile_template(body) |
| 146 | if nil == bod then print('oops! ' .. err) else | 169 | if nil == bod then print('oops! ' .. err) else |
| 147 | local templateFile = metadata.template | 170 | local templateFile = metadata.template |
| @@ -149,6 +172,7 @@ for name, file in pairs(Files) do | |||
| 149 | file.template = templateFile .. '.template' | 172 | file.template = templateFile .. '.template' |
| 150 | end | 173 | end |
| 151 | 174 | ||
| 175 | -- Copy any metadata found in parent directories. | ||
| 152 | local pth = '' | 176 | local pth = '' |
| 153 | for i, d in ipairs(bits) do | 177 | for i, d in ipairs(bits) do |
| 154 | if '' ~= pth then pth = pth .. '/' end | 178 | if '' ~= pth then pth = pth .. '/' end |
| @@ -158,17 +182,19 @@ for name, file in pairs(Files) do | |||
| 158 | for m, x in pairs(Subs[pth].metadata) do | 182 | for m, x in pairs(Subs[pth].metadata) do |
| 159 | if nil == metadata[m] then | 183 | if nil == metadata[m] then |
| 160 | metadata[m] = x | 184 | metadata[m] = x |
| 161 | else | 185 | end |
| 162 | end | 186 | end |
| 163 | end | 187 | end |
| 164 | end | 188 | end |
| 165 | end | 189 | end |
| 166 | end | 190 | -- Root directory needs to be handled separately, for now. |
| 167 | |||
| 168 | if nil ~= Subs[''].metadata then | 191 | if nil ~= Subs[''].metadata then |
| 169 | for m, x in pairs(Subs[''].metadata) do if nil == metadata[m] then metadata[m] = x end end | 192 | for m, x in pairs(Subs[''].metadata) do if nil == metadata[m] then metadata[m] = x end end |
| 170 | end | 193 | end |
| 194 | |||
| 171 | for m, x in pairs(globalData) do if nil == metadata[m] then metadata[m] = x end end | 195 | for m, x in pairs(globalData) do if nil == metadata[m] then metadata[m] = x end end |
| 196 | |||
| 197 | -- Inherit these images from most recent parent directory that defines them. | ||
| 172 | for n, y in ipairs{'favicon', 'logo'} do | 198 | for n, y in ipairs{'favicon', 'logo'} do |
| 173 | local pith = '' | 199 | local pith = '' |
| 174 | if nil ~= metadata[y] then | 200 | if nil ~= metadata[y] then |
| @@ -185,6 +211,7 @@ for name, file in pairs(Files) do | |||
| 185 | end | 211 | end |
| 186 | end | 212 | end |
| 187 | 213 | ||
| 214 | -- Figure out this pages header links. | ||
| 188 | metadata.header = '' | 215 | metadata.header = '' |
| 189 | local pth = '' | 216 | local pth = '' |
| 190 | for i, f in pairs(Subs[path].subs) do | 217 | for i, f in pairs(Subs[path].subs) do |
| @@ -204,6 +231,7 @@ for name, file in pairs(Files) do | |||
| 204 | -- end | 231 | -- end |
| 205 | end | 232 | end |
| 206 | 233 | ||
| 234 | -- Figure out this pages menu links. | ||
| 207 | metadata.menu = '' | 235 | metadata.menu = '' |
| 208 | if nil ~= Subs[path].files then table.sort(Subs[path].files) end | 236 | if nil ~= Subs[path].files then table.sort(Subs[path].files) end |
| 209 | for i, f in ipairs(Subs[path].files) do | 237 | for i, f in ipairs(Subs[path].files) do |
| @@ -214,6 +242,7 @@ for name, file in pairs(Files) do | |||
| 214 | end | 242 | end |
| 215 | end | 243 | end |
| 216 | 244 | ||
| 245 | -- Figure out this pages trail links. | ||
| 217 | metadata.trail = '' | 246 | metadata.trail = '' |
| 218 | for i, b in ipairs(bits) do | 247 | for i, b in ipairs(bits) do |
| 219 | if i < #bits then | 248 | if i < #bits then |
| @@ -225,14 +254,17 @@ for name, file in pairs(Files) do | |||
| 225 | end | 254 | end |
| 226 | -- if '' == metadata.trail then metadata.trail = '<a href="' .. string.rep('../', ln) .. '/' .. whichPage('') .. '">home</a> ' end | 255 | -- if '' == metadata.trail then metadata.trail = '<a href="' .. string.rep('../', ln) .. '/' .. whichPage('') .. '">home</a> ' end |
| 227 | 256 | ||
| 257 | -- Figure out this pages footer links. | ||
| 228 | if nil ~= metadata.pagehistory then metadata.history = '<p>Page <a href="' .. metadata.pagehistory .. '">history</a></p>' end | 258 | if nil ~= metadata.pagehistory then metadata.history = '<p>Page <a href="' .. metadata.pagehistory .. '">history</a></p>' end |
| 229 | if nil ~= metadata.sourcecode then metadata.footer = '<a href="' .. metadata.sourcecode .. '">source code</a> ' .. metadata.footer end | 259 | if nil ~= metadata.sourcecode then metadata.footer = '<a href="' .. metadata.sourcecode .. '">source code</a> ' .. metadata.footer end |
| 230 | if nil ~= metadata.feedatom then metadata.footer = '<a href="' .. metadata.feedatom .. '">atom feed</a> ' .. metadata.footer end | 260 | if nil ~= metadata.feedatom then metadata.footer = '<a href="' .. metadata.feedatom .. '">atom feed</a> ' .. metadata.footer end |
| 231 | if metadata.footer ~= globalData.footer then metadata.footer = 'Web site ' .. metadata.footer end | 261 | if metadata.footer ~= globalData.footer then metadata.footer = 'Web site ' .. metadata.footer end |
| 232 | metadata.footer = '<p>' .. metadata.footer .. '</p>' | 262 | metadata.footer = '<p>' .. metadata.footer .. '</p>' |
| 233 | 263 | ||
| 264 | -- Apply the template to the body. | ||
| 234 | metadata.body = lcmark.apply_template(bod, metadata) | 265 | metadata.body = lcmark.apply_template(bod, metadata) |
| 235 | 266 | ||
| 267 | -- Put it all in the template. | ||
| 236 | local tm = '' | 268 | local tm = '' |
| 237 | if nil ~= file.template then | 269 | if nil ~= file.template then |
| 238 | local h = io.open(file.template, 'r') | 270 | local h = io.open(file.template, 'r') |
| @@ -243,6 +275,7 @@ for name, file in pairs(Files) do | |||
| 243 | print('oops! No such file ' .. file.template) | 275 | print('oops! No such file ' .. file.template) |
| 244 | end | 276 | end |
| 245 | 277 | ||
| 278 | -- TODO - Um not sure why this is here AND at the top of the loop. Here makes more sense. | ||
| 246 | local template, err = lcmark.compile_template(tm) | 279 | local template, err = lcmark.compile_template(tm) |
| 247 | if nil == template then print('oops! ' .. err) else | 280 | if nil == template then print('oops! ' .. err) else |
| 248 | result = lcmark.apply_template(template, metadata) | 281 | result = lcmark.apply_template(template, metadata) |
| @@ -251,6 +284,7 @@ for name, file in pairs(Files) do | |||
| 251 | result = body | 284 | result = body |
| 252 | end | 285 | end |
| 253 | 286 | ||
| 287 | -- Write the file. | ||
| 254 | if '' ~= result then | 288 | if '' ~= result then |
| 255 | local base = name .. '.HTML' | 289 | local base = name .. '.HTML' |
| 256 | print('From ' .. name .. '.md -> ' .. base) | 290 | print('From ' .. name .. '.md -> ' .. base) |
