diff options
| author | dvs1 | 2025-02-19 17:40:48 +1000 |
|---|---|---|
| committer | dvs1 | 2025-02-19 17:40:48 +1000 |
| commit | c560ae0b2a0c714c9944fa988632527f4f2630b4 (patch) | |
| tree | a2fcfc3e0dc485321ac36605b021ec1099232e8c /notYetAnotherWiki.lua | |
| parent | TODO is tricksy. (diff) | |
| download | notYetAnotherWiki-c560ae0b2a0c714c9944fa988632527f4f2630b4.zip notYetAnotherWiki-c560ae0b2a0c714c9944fa988632527f4f2630b4.tar.gz notYetAnotherWiki-c560ae0b2a0c714c9944fa988632527f4f2630b4.tar.bz2 notYetAnotherWiki-c560ae0b2a0c714c9944fa988632527f4f2630b4.tar.xz | |
Major YAR!!
Moved the post download code from the SuckIt's to the main script, and
combined what's left.
Minor icon tweak.
Think I have almost figured out the HTML and CSS to get the layout to
behave.
Major rearrange of the main script.
Use more of lunamark and RE.
Moar colours!
Solved the generic colour shenanigans.
Solved a few other bugs.
Hidden directories.
Lots of things I forgot about.
Diffstat (limited to '')
| -rwxr-xr-x | notYetAnotherWiki.lua | 662 |
1 files changed, 422 insertions, 240 deletions
diff --git a/notYetAnotherWiki.lua b/notYetAnotherWiki.lua index bddf63a..88a69fe 100755 --- a/notYetAnotherWiki.lua +++ b/notYetAnotherWiki.lua | |||
| @@ -1,77 +1,49 @@ | |||
| 1 | #!/usr/bin/env luajit | 1 | #!/usr/bin/env luajit |
| 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. |
| 4 | If there is no README or similar, then you can find the link to the source below. | ||
| 4 | 5 | ||
| 5 | local lunamark = require("lunamark") -- https://github.com/jgm/lunamark | 6 | Normally I define functions and globals at the top, but here I'm interleaving them. |
| 7 | ]] | ||
| 6 | 8 | ||
| 7 | local opts = { | 9 | local Lunamark = require("lunamark") -- https://github.com/jgm/lunamark |
| 8 | layout='compact', | 10 | local Lpeg = require("lpeg") -- https://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html Lunamark uses this, so we can to. |
| 9 | -- This list is copied from the lunamark source code, until I discover a way to discover it. The descriptions are useful to. | 11 | local RE = require("re") -- Part of lpeg. https://www.inf.puc-rio.br/~roberto/lpeg/re.html |
| 10 | containers=false, -- Put sections in containers (e.g. div or section tags) | 12 | |
| 11 | slides=false, -- Like containers, but do not nest them | 13 | |
| 12 | startnum=true, -- Start number of an ordered list is significant | 14 | --------------------------------------------------------------------------------- |
| 13 | smart=false, -- Smart typography (quotes, dashes, ellipses) | 15 | -- Some global data. |
| 14 | preserve_tabs=true, -- Don't expand tabs to spaces | 16 | |
| 15 | notes=true, -- Footnotes | 17 | local GlobalMetaData = { |
| 16 | inline_notes=true, -- Inline footnotes | 18 | dlr = '$', perc = '%', |
| 17 | definition_lists=true, -- Definition lists | 19 | devuanCinnabarDark = '#310202', devuanCinnabarLight = '#510505', |
| 18 | citations=true, -- Citations | 20 | devuanDarkPurpyDark = '#33313b', devuanDarkPurpyLight = '#3c3a45', |
| 19 | citation_nbsps=true, -- Turn spacing into non-breaking spaces in citations | 21 | devuanDeepSeaDark = '#132f40', devuanDeepSeaLight = '#1a4562', |
| 20 | fenced_code_blocks=true, -- Fenced code blocks | 22 | devuanSaphireDark = '#004489', devuanSaphireLight = '#00509f', |
| 21 | lua_metadata=true, -- Lua metadata | 23 | devuanDevuanDark = '#000000', devuanDevuanLight = '#ffffff', |
| 22 | pandoc_title_blocks=true, -- Pandoc style title blocks | 24 | -- HTML link colours. Naturally HTML5 deprecated the simple version, replacing it with less simple CSS. |
| 23 | hash_enumerators=true, -- may be used as ordered list enumerator | 25 | -- <body> has alink, link, vlink; CSS has active, link, visited, and hover. |
| 24 | require_blank_before_blockquote=false, | 26 | devuanDevuanalink = '#03a4ff', devuanDevuanlink = '#0076b6', devuanDevuanvlink = '#6aa4db', devuanDevuanhlink = '#03a4ff', |
| 25 | require_blank_before_header=false, | 27 | devuanSDevuanalink = '#98c3db', devuanSDevuanlink = '#ffffff', devuanSDevuanvlink = '#ffffff', devuanSDevuanhlink = '#98c3db', |
| 26 | require_blank_before_fenced_code_block=false, | 28 | karenPurple = '#8800ff', onefangPurple = '#cc00ff', |
| 27 | fancy_lists=true, -- Pandoc style fancy lists | 29 | PinkFloyd = '#AA00AA', DeepPurple = '#220022', -- From an ancient site of mine, which went from PinkFloyd to DeepPurple as a background gradient. |
| 28 | task_list=true, -- GitHub-Flavored Markdown task list | 30 | favicon = 'nYAW_icon.png', logo = 'nYAW.png', |
| 29 | strikeout=true, -- Strike-through with double tildes | 31 | footer = 'Powered by <a href="https://sledjhamr.org/cgit/notYetAnotherWiki/about/">notYetAnotherWiki</a> version 0.0. ', |
| 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 | } | 32 | } |
| 44 | local writer = lunamark.writer.html5.new(opts) | 33 | |
| 45 | local template = '' | 34 | local Files, Subs, xLinks = {}, {}, {} |
| 35 | |||
| 36 | local Template = '' | ||
| 46 | local h = io.open("default.template", 'r') | 37 | local h = io.open("default.template", 'r') |
| 47 | if nil ~= h then | 38 | if nil ~= h then |
| 48 | template = h:read('*a') | 39 | Template = h:read('*a') |
| 49 | h:close() | 40 | h:close() |
| 50 | else | 41 | else |
| 51 | print('oops! No such file ' .. 'default.template') | 42 | print('oops! No such file ' .. 'default.template') |
| 52 | end | 43 | end |
| 53 | -- Can override the various writer functions, there's something for each of the basic HTML elements. | ||
| 54 | -- Override anything that's generic. | ||
| 55 | local parse = lunamark.reader.markdown.new(writer, opts) | ||
| 56 | |||
| 57 | |||
| 58 | |||
| 59 | -- Some global data. | ||
| 60 | local globalData = { | ||
| 61 | ['s'] = ' ', ['_'] = ' ', ['dlr'] = '$', | ||
| 62 | ['devuanCinnabarDark'] = '#310202', ['devuanCinnabarLight'] = '#510505', | ||
| 63 | ['devuanDarkPurpyDark'] = '#33313b', ['devuanDarkPurpyLight'] = '#3c3a45', | ||
| 64 | ['devuanDeepSeaDark'] = '#132f40', ['devuanDeepSeaLight'] = '#1a4562', | ||
| 65 | ['devuanSaphireDark'] = '#004489', ['devuanSaphireLight'] = '#00509f', | ||
| 66 | ['karenPurple'] = '#8800ff', ['onefangPurple'] = '#cc00ff', | ||
| 67 | favicon = 'nYAW_icon.png', logo = 'nYAW.png', | ||
| 68 | header = '', home = '', history = '', footer = 'Powered by <a href="https://sledjhamr.org/cgit/notYetAnotherWiki/about/">notYetAnotherWiki</a> version 0.0. ', | ||
| 69 | --menu = '', | ||
| 70 | } | ||
| 71 | local Files, Subs = {}, {} | ||
| 72 | |||
| 73 | 44 | ||
| 74 | 45 | ||
| 46 | --------------------------------------------------------------------------------- | ||
| 75 | -- Useful functions, part 0. | 47 | -- Useful functions, part 0. |
| 76 | 48 | ||
| 77 | -- A simple table.subtable = subtable wont work, you end up with a reference so that changes to the later get applied to the former. | 49 | -- A simple table.subtable = subtable wont work, you end up with a reference so that changes to the later get applied to the former. |
| @@ -87,6 +59,15 @@ local derefTable = function(t, strip) | |||
| 87 | end | 59 | end |
| 88 | 60 | ||
| 89 | 61 | ||
| 62 | local writeString = function(base, body) | ||
| 63 | local a, e = io.open(base, 'w') | ||
| 64 | if nil == a then print('Could not open ' .. base .. ' - ' .. e) else | ||
| 65 | a:write(body) | ||
| 66 | a:close() | ||
| 67 | end | ||
| 68 | end | ||
| 69 | |||
| 70 | |||
| 90 | -- String together the bits array into a path string. Or the other way around. lol | 71 | -- String together the bits array into a path string. Or the other way around. lol |
| 91 | local stringBits = function(l) | 72 | local stringBits = function(l) |
| 92 | local bits = {} | 73 | local bits = {} |
| @@ -115,14 +96,55 @@ local toFile = function(name, key, value) | |||
| 115 | end | 96 | end |
| 116 | Files[name].path = path | 97 | Files[name].path = path |
| 117 | -- Files[name].body = '' | 98 | -- Files[name].body = '' |
| 99 | if ("Foswiki" == bits[1]) or ("PmWiki" == bits[1]) then Files[name].ogWiki = bits[1] end | ||
| 118 | end | 100 | end |
| 119 | if nil ~= key then Files[name][key] = value end | 101 | if nil ~= key then Files[name][key] = value end |
| 120 | for i, v in ipairs{'metadata', 'bits', } do | 102 | for i, v in ipairs{'metadata', 'bits', } do |
| 121 | if nil == Files[name][v] then Files[name][v] = {} end | 103 | if nil == Files[name][v] then Files[name][v] = {} end |
| 122 | end | 104 | end |
| 105 | -- Open the files and do the initial cleanups. | ||
| 106 | local body = '' | ||
| 107 | if '.md' ~= string.sub(name, -3, -1) then | ||
| 108 | h = io.open(name .. '.md', 'r') | ||
| 109 | if nil ~= h then | ||
| 110 | -- print('Parsing ' .. name .. '.md') | ||
| 111 | body = h:read('*a') ; h:close() | ||
| 112 | -- Deal with my typical double spaced sentence endings, and other things. | ||
| 113 | local result = RE.compile( [=[{~ | ||
| 114 | ( | ||
| 115 | {[.?!]{" "}} -> '%1 ' / -- ' ' gets turned into hex 0xA0 by parse(). So feed it another metadata token that gets translated to . Seems we now skip this issue. | ||
| 116 | {[\\]{['"|$]}} -> '%2 ' / -- Do the same for fixing the \' \" \| etc mess pandoc left. | ||
| 117 | {"[" {([^]])+} "]{.foswiki" {([^FG}])+} "FG}" } -> "<span style='color: %3;'>%2</span>" / | ||
| 118 | {"::: {."[A-Za-z_. ]+"}"} -> '' / | ||
| 119 | {":::"} -> '' / | ||
| 120 | {"-noComment-"} -> ' -- ' / | ||
| 121 | {"{#"[A-Za-z_]+"}"} -> '' / | ||
| 122 | . | ||
| 123 | )* ~}]=], { } ):match(body) | ||
| 124 | body = result | ||
| 125 | -- {"<!--".*"-->"} -> '' / | ||
| 126 | -- {"[$]"} -> '$dlr$' / -- Replace $, coz otherwise it confuses things later. | ||
| 127 | body = RE.gsub(body, '{[$]}', '$dlr$') | ||
| 128 | -- {"[%]"} -> '$perc$' / -- Gotta be done after the %1's above. otherwise screws things up when included above. | ||
| 129 | -- body = RE.gsub(body, '{[%]}', '$perc$') -- Coz otherwise stray % trip up the capture part. | ||
| 130 | end | ||
| 131 | Files[name].body = body | ||
| 132 | end | ||
| 123 | end | 133 | end |
| 124 | local toSub = function(name, key, value) | 134 | local toSub = function(name, key, value) |
| 125 | if nil == Subs[name] then Subs[name] = {} end | 135 | if nil == Subs[name] then |
| 136 | local bits, bit = stringBits(name) | ||
| 137 | local path = '' | ||
| 138 | Subs[name] = {} | ||
| 139 | table.insert(bits, bit) | ||
| 140 | Subs[name].bits = bits | ||
| 141 | Subs[name].bit = bit | ||
| 142 | for i, d in ipairs(bits) do | ||
| 143 | if '' ~= path then path = path .. '/' end | ||
| 144 | path = path .. d | ||
| 145 | end | ||
| 146 | Subs[name].path = path | ||
| 147 | end | ||
| 126 | if nil ~= key then Subs[name][key] = value end | 148 | if nil ~= key then Subs[name][key] = value end |
| 127 | for i, v in ipairs{'metadata', 'bits', 'files', 'subs'} do | 149 | for i, v in ipairs{'metadata', 'bits', 'files', 'subs'} do |
| 128 | if nil == Subs[name][v] then Subs[name][v] = {} end | 150 | if nil == Subs[name][v] then Subs[name][v] = {} end |
| @@ -131,32 +153,108 @@ end | |||
| 131 | 153 | ||
| 132 | 154 | ||
| 133 | 155 | ||
| 156 | --------------------------------------------------------------------------------- | ||
| 134 | -- Actually start doing things. | 157 | -- Actually start doing things. |
| 135 | 158 | ||
| 136 | -- Create the base of everything.md here, so it gets picked up as usual in the file scan. | 159 | -- Create the base of everything.md here, so it gets picked up as usual in the file scan. |
| 137 | local body, h = '', io.open('everything.md', 'w') | 160 | h = io.open('everything.md', 'w') |
| 138 | h:write('# All the pages\n') | 161 | if nil ~= h then |
| 139 | h:close() | 162 | h:close() |
| 163 | else | ||
| 164 | print("Can't open everything.md for writing.") | ||
| 165 | end | ||
| 140 | 166 | ||
| 141 | 167 | ||
| 142 | -- Scan the subdirectories looking for .md files. | 168 | -- Scan the subdirectories looking for our files. |
| 143 | local directory = arg[1] | 169 | local Directory = arg[1] |
| 144 | toSub('') | 170 | toSub('') |
| 145 | if nil == directory then directory = '.' end | 171 | if nil == Directory then Directory = '.' end |
| 146 | if '.' ~= directory then | 172 | |
| 147 | for l in io.popen('find . -name "*.md" -type f,l -printf "%P\n"'):lines() do | 173 | for l in io.popen('find -L ' .. Directory .. ' -name "*.HTM" -type f,l -printf "%P\n"'):lines() do |
| 174 | -- print('pandoc converting ' .. l .. ' -> ' .. string.sub(l, 1, -4) .. 'md') | ||
| 175 | -- Open the HTM files and do the initial cleanups, then pandoc them. | ||
| 176 | h = io.open(l, 'r') | ||
| 177 | if nil ~= h then | ||
| 178 | local body = h:read('*a') ; h:close() | ||
| 179 | if 'Foswiki' == string.sub(l, 1, 7) then | ||
| 180 | -- Strip out the actual content. | ||
| 181 | local beg, en = RE.find(body, [['<div id="patternMainContents">']]) if nil ~= beg then body = string.sub(body, en + 1) end | ||
| 182 | beg, en = RE.find(body, [['<div class="patternContent">']]) if nil ~= beg then body = string.sub(body, en + 1) end | ||
| 183 | beg, en = RE.find(body, [['<div class="foswikiTopic">']]) if nil ~= beg then | ||
| 184 | if ' -- ' == string.sub(body, en + 1, en + 4) then | ||
| 185 | beg, en = RE.find(body, '[%nl]', en + 4) | ||
| 186 | body = string.sub(body, en + 1) | ||
| 187 | end | ||
| 188 | end | ||
| 189 | beg, en = RE.find(body, [['<div class="patternInfo">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | ||
| 190 | -- beg, en = RE.find(body, [['<div class="foswikiForm foswikiFormStep">']]) if nil ~= beg then body = string.sub(body, 1, en + 1) end | ||
| 191 | beg, en = RE.find(body, [['<div class="foswikiAttachments foswikiFormStep" style="overflow:auto">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | ||
| 192 | beg, en = RE.find(body, [['<div class="foswikiSearchResultsPager">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | ||
| 193 | -- Some clean ups. | ||
| 194 | local result = RE.compile( [[{~ | ||
| 195 | ( | ||
| 196 | {'class="foswikiCurrentTopicLink"'} -> blank / | ||
| 197 | {'class="foswikiNewLink"'} -> blank / | ||
| 198 | {" -- "} -> '-noComment-' / | ||
| 199 | -- {"-- " ([^%nl])* } -> blank / | ||
| 200 | {'<div class="foswikiTopic">'} -> blank / | ||
| 201 | {'rel="nofollow"'} -> blank / {"rel='nofollow'"} -> blank / | ||
| 202 | {"target='_blank'"} -> blank / | ||
| 203 | {"</div>" ([%nl])* } -> blank / | ||
| 204 | {'style="' ([^"])+ '"'} -> '' / {"style='" ([^'])+ "'"} -> '' / | ||
| 205 | . | ||
| 206 | )* ~}]], { blank = function(a) return '' end } ):match(body) | ||
| 207 | body = result | ||
| 208 | -- body = RE.gsub(body, [=[{"<!-- ".*"-->"}]=], '') -- FIXME | ||
| 209 | writeString(l .. '_NEW', body) | ||
| 210 | elseif 'PmWiki' == string.sub(l, 1, 6) then | ||
| 211 | local beg, en = RE.find(body, [['<!--PageText-->']]) if nil ~= beg then body = string.sub(body, en + 2) end | ||
| 212 | beg, en = RE.find(body, [["div id='wikitext'>"]]) if nil ~= beg then body = string.sub(body, en + 2) end | ||
| 213 | beg, en = RE.find(body, [["<div id='printfoot'>"]]) if nil ~= beg then body = string.sub(body, 1, beg - (2 + 9)) end -- There's a </div> to get rid of to. | ||
| 214 | beg, en = RE.find(body, [['<!--HTMLFooter-->']]) if nil ~= beg then body = string.sub(body, 1, beg - 2) end | ||
| 215 | local result = RE.compile( [[{~ | ||
| 216 | ( | ||
| 217 | {"class='categorylink'"} -> blank / | ||
| 218 | {"class='createlink'"} -> blank / | ||
| 219 | {"class='createlinktext'"} -> blank / | ||
| 220 | {"class='escaped'"} -> blank / | ||
| 221 | {"class='diffmarkup'"} -> blank / | ||
| 222 | {"class='selflink'"} -> blank / | ||
| 223 | {"class='urllink'"} -> blank / | ||
| 224 | {"<div class='vspace'></div><hr /> <a class='wikilink' href='https://wiki.devuan.org?n=Profiles." .* ([%nl])* } -> blank / | ||
| 225 | {"<a class='selflink' href='https://wiki.devuan.org?n=Profiles." .* ([%nl])* } -> blank / | ||
| 226 | {"<div class='vspace'></div><hr />"} -> blank / | ||
| 227 | {"<div class='vspace'></div>"} -> blank / | ||
| 228 | {"class='wikilink'"} -> blank / | ||
| 229 | {'rel="nofollow"'} -> blank / {"rel='nofollow'"} -> blank / | ||
| 230 | {"target='_blank'"} -> blank / | ||
| 231 | {'style="' ([^"])+ '"'} -> '' / {"style='" ([^'])+ "'"} -> '' / | ||
| 232 | {"<span class='hlt " {([a-z])+} "'></span><pre" } -> "<pre class='%2'" / | ||
| 233 | . | ||
| 234 | )* ~}]], { blank = function(a) return '' end } ):match(body) | ||
| 235 | body = result | ||
| 236 | writeString(l .. '_NEW', body) | ||
| 237 | end | ||
| 238 | end | ||
| 239 | |||
| 240 | ok, rslt, status = os.execute('pandoc -f html -t commonmark_x --self-contained ' .. l .. '_NEW' .. ' >' .. string.sub(l, 1, -4) .. 'md') | ||
| 241 | end | ||
| 242 | |||
| 243 | if '.' ~= Directory then | ||
| 244 | for l in io.popen('find -L . -name "*.md" -type f,l -printf "%P\n"'):lines() do | ||
| 148 | toFile(string.gsub(l, '%.md$', '')) | 245 | toFile(string.gsub(l, '%.md$', '')) |
| 149 | end | 246 | end |
| 150 | end | 247 | end |
| 248 | |||
| 151 | -- Can add in a distant directory to, for putting it's results in the current directory. | 249 | -- Can add in a distant directory to, for putting it's results in the current directory. |
| 152 | for l in io.popen('find ' .. directory .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do | 250 | for l in io.popen('find -L ' .. Directory .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do |
| 153 | local n = string.gsub(l, '%.md$', '') | 251 | local n = string.gsub(l, '%.md$', '') |
| 154 | if nil == Files[n] then toFile(n) end | 252 | if nil == Files[n] then toFile(n) end |
| 155 | end | 253 | end |
| 156 | 254 | ||
| 157 | 255 | ||
| 158 | -- Gotta figure out all the files and subs first. File and sub metadata comes along for the ride, coz we need them later. | 256 | -- Gotta figure out all the files and subs first. File and sub metadata comes along for the ride, coz we need them later. |
| 159 | local newMeta = {} | 257 | local NewMeta = {} |
| 160 | for name, file in pairs(Files) do | 258 | for name, file in pairs(Files) do |
| 161 | local bitter, path = '', '' | 259 | local bitter, path = '', '' |
| 162 | local bits, bit = file.bits, file.bit | 260 | local bits, bit = file.bits, file.bit |
| @@ -169,7 +267,7 @@ for name, file in pairs(Files) do | |||
| 169 | for i, d in ipairs(bits) do | 267 | for i, d in ipairs(bits) do |
| 170 | if '' ~= path then path = path .. '/' end | 268 | if '' ~= path then path = path .. '/' end |
| 171 | path = path .. d | 269 | path = path .. d |
| 172 | toSub(path, 'bits', derefiTable(bits, true)) | 270 | toSub(path) |
| 173 | if i < ln then | 271 | if i < ln then |
| 174 | Subs[path].subs[bits[i + 1]] = bits[i + 1] | 272 | Subs[path].subs[bits[i + 1]] = bits[i + 1] |
| 175 | table.remove(Subs[path].bits, #bits) | 273 | table.remove(Subs[path].bits, #bits) |
| @@ -178,121 +276,45 @@ for name, file in pairs(Files) do | |||
| 178 | 276 | ||
| 179 | if '.md' == string.sub(name, -3, -1) then | 277 | if '.md' == string.sub(name, -3, -1) then |
| 180 | -- This is a metadata only file, no content, stash the matadata. | 278 | -- This is a metadata only file, no content, stash the matadata. |
| 181 | for l in io.open(name .. '.md'):lines() do | 279 | local h1 = io.open(name .. '.md') |
| 182 | for k, v in string.gmatch(l, "(%w+)%s*=%s*(.+)") do | 280 | if nil == h1 then print('Could not open ' .. name .. '.md') else |
| 183 | if nil == v then | 281 | for l in h1:lines() do |
| 184 | print(name .. ' ' .. k) | 282 | for k, v in string.gmatch(l, "(%w+)%s*=%s*(.+)") do |
| 185 | else | 283 | if nil == v then |
| 186 | metadata[k] = v | 284 | print(name .. ' ' .. k) |
| 285 | else | ||
| 286 | metadata[k] = v | ||
| 287 | end | ||
| 187 | end | 288 | end |
| 188 | end | 289 | end |
| 189 | end | 290 | end |
| 190 | if '.md' == name then toSub(path, 'metadata', metadata) | 291 | if '.md' == name then toSub(path, 'metadata', metadata) |
| 191 | elseif '/.md' == string.sub(name, -4, -1) then toSub(path, 'metadata', metadata) | 292 | elseif '/.md' == string.sub(name, -4, -1) then toSub(path, 'metadata', metadata) |
| 192 | -- else toFile(string.sub(name, 1, -4), 'metadata', metadata) | 293 | -- else toFile(string.sub(name, 1, -4), 'metadata', metadata) |
| 193 | else newMeta[string.sub(name, 1, -4)] = metadata | 294 | else NewMeta[string.sub(name, 1, -4)] = metadata -- Coz we can't add to Files here. |
| 194 | end | 295 | end |
| 195 | Files[name] = nil | 296 | Files[name] = nil |
| 196 | end | 297 | end |
| 197 | end | 298 | end |
| 198 | 299 | ||
| 199 | -- FIXTHEM - Lua doesn't like modifying the thing you are pair()ing, like we want to do in the last loop. | 300 | -- FIXED - Lua doesn't like modifying the thing you are pair()ing, like we want to do in the last loop. |
| 200 | for name, file in pairs(newMeta) do | 301 | for name, file in pairs(NewMeta) do |
| 201 | if nil == Files[name] then toFile(name) end | 302 | if nil == Files[name] then toFile(name) end |
| 202 | if nil == Files[name].metadata then Files[name].metadata = {} end | ||
| 203 | for k, v in pairs(file) do | 303 | for k, v in pairs(file) do |
| 204 | if nil == Files[name].metadata[k] then Files[name].metadata[k] = v end | 304 | if nil == Files[name].metadata[k] then Files[name].metadata[k] = v end |
| 205 | end | 305 | end |
| 206 | end | 306 | end |
| 207 | 307 | ||
| 208 | -- Open the files and do the iniital cleanups. | 308 | -- Fix up subs now we have all the file bits. |
| 209 | for name, file in pairs(Files) do | 309 | for name, file in pairs(Files) do |
| 210 | if '.md' ~= string.sub(name, -3, -1) then | 310 | if '.md' ~= string.sub(name, -3, -1) then |
| 211 | -- print('Parsing ' .. name .. '.md') | 311 | table.insert(Subs[file.path].files, file.bit) |
| 212 | h = io.open(name .. '.md', 'r') | ||
| 213 | if nil ~= h then | ||
| 214 | body = h:read('*a') ; h:close() | ||
| 215 | local f0, f1, token | ||
| 216 | -- Deal with my typical double spaced sentence endings. | ||
| 217 | local result = '' | ||
| 218 | local start = 1 | ||
| 219 | repeat | ||
| 220 | f0, f1, token = string.find(body, '([%.%?%!] )', start) | ||
| 221 | if fail ~= f0 then | ||
| 222 | result = result .. string.sub(body, start, f0) | ||
| 223 | if ' ' == string.sub(body, f1 + 1, f1 + 1) then | ||
| 224 | result = result .. '$s$ ' -- ' ' gets turned into hex 0xA0 by parse(). So feed it another metadata token that gets translated to . | ||
| 225 | else | ||
| 226 | result = result .. ' ' | ||
| 227 | end | ||
| 228 | start = f1 + 1 | ||
| 229 | end | ||
| 230 | until fail == f0 | ||
| 231 | result = result .. string.sub(body, start) | ||
| 232 | -- Do the same for fixing the \' \" \| etc mess pandoc left that sed can't fix. | ||
| 233 | body = result | ||
| 234 | result = '' | ||
| 235 | start = 1 | ||
| 236 | repeat | ||
| 237 | f0, f1, token = string.find(body, '(%\\[%"%\'%|%$])', start) | ||
| 238 | if fail ~= f0 then | ||
| 239 | result = result .. string.sub(body, start, f0 - 1) | ||
| 240 | start = f1 | ||
| 241 | end | ||
| 242 | until fail == f0 | ||
| 243 | result = result .. string.sub(body, start) | ||
| 244 | body = result | ||
| 245 | end | ||
| 246 | Files[name].body = body | ||
| 247 | table.insert(Subs[Files[name].path].files, Files[name].bit) | ||
| 248 | end | ||
| 249 | end | ||
| 250 | |||
| 251 | |||
| 252 | |||
| 253 | -- Figure out the original title and link for the original wiki. | ||
| 254 | -- This functions assume the above file and sub scan has completed. | ||
| 255 | local whichWiki = function(metadata) | ||
| 256 | local title, link = '', '' | ||
| 257 | if 'PmWiki' == metadata.ogWiki then | ||
| 258 | title = '[' .. metadata.ogBase .. '.' .. metadata.ogFile .. ']' | ||
| 259 | link = '(' .. metadata.ogURL .. '/?n=' .. metadata.ogBase .. '.' .. metadata.ogFile .. ')' | ||
| 260 | end | ||
| 261 | if 'Foswiki' == metadata.ogWiki then | ||
| 262 | title = '[' .. metadata.ogBase .. '/' .. metadata.ogFile .. ']' | ||
| 263 | link = '(' .. metadata.ogURL .. '/' .. metadata.ogBase .. '/' .. metadata.ogFile .. ')' | ||
| 264 | end | ||
| 265 | return title, link | ||
| 266 | end | ||
| 267 | |||
| 268 | |||
| 269 | -- Create an "everything" page, for URL links to every file.HTML. | ||
| 270 | local bdy, h = Files['everything'].body, io.open('everything.md', 'a+') | ||
| 271 | bdy = bdy .. '\n\n| page | converted | original page | last edited UTC | \n| ---- | --------- | ------- | --------------- | ' | ||
| 272 | pages = {} | ||
| 273 | for name, file in pairs(Files) do | ||
| 274 | local metadata = derefTable(Files[name].metadata, true) | ||
| 275 | if 'everything' ~= name then | ||
| 276 | local ln, fw, pw, ts = 'DUNNO', '', '', '' | ||
| 277 | local title, link = whichWiki(metadata) | ||
| 278 | if 'PmWiki' == metadata.ogWiki then pw = 'PmWiki ' .. title .. link end | ||
| 279 | if 'Foswiki' == metadata.ogWiki then fw = 'Foswiki ' .. title .. link end | ||
| 280 | if nil ~= metadata.timestamp then ts = metadata.timestamp end | ||
| 281 | if nil ~= file.bit then ln = file.bit | ||
| 282 | end | ||
| 283 | table.insert(pages, '\n| ' .. name .. ' | [' .. ln .. '](<' .. name .. '.HTML>) | ' .. fw .. ' ' .. pw .. ' | ' .. ts .. ' |') | ||
| 284 | end | 312 | end |
| 285 | end | 313 | end |
| 286 | table.sort(pages, function(a, b) return (string.lower(a) < string.lower(b)) end) | ||
| 287 | for i, f in ipairs(pages) do | ||
| 288 | bdy = bdy .. f | ||
| 289 | end | ||
| 290 | h:write(bdy) | ||
| 291 | h:close() | ||
| 292 | toFile('everything', 'body', parse(bdy)) | ||
| 293 | 314 | ||
| 294 | 315 | ||
| 295 | 316 | ||
| 317 | --------------------------------------------------------------------------------- | ||
| 296 | -- These functions assume the above file and sub scan has completed. | 318 | -- These functions assume the above file and sub scan has completed. |
| 297 | 319 | ||
| 298 | -- Which page in this directory should we show? | 320 | -- Which page in this directory should we show? |
| @@ -323,93 +345,246 @@ local whichPage = function(f) | |||
| 323 | end | 345 | end |
| 324 | 346 | ||
| 325 | 347 | ||
| 348 | -- Figure out the original title and link for the original wiki. | ||
| 349 | local whichWiki = function(metadata) | ||
| 350 | local title, link = '', '' | ||
| 351 | if 'PmWiki' == metadata.ogWiki then | ||
| 352 | title = metadata.ogBase .. '.' .. metadata.ogFile | ||
| 353 | link = metadata.ogURL .. '/?n=' .. metadata.ogBase .. '.' .. metadata.ogFile | ||
| 354 | end | ||
| 355 | if 'Foswiki' == metadata.ogWiki then | ||
| 356 | title = metadata.ogBase .. '/' .. metadata.ogFile | ||
| 357 | link = metadata.ogURL .. '/' .. metadata.ogBase .. '/' .. metadata.ogFile | ||
| 358 | end | ||
| 359 | return title, link | ||
| 360 | end | ||
| 361 | |||
| 362 | |||
| 326 | -- Calculate a link from the source directory to the destination directory. | 363 | -- Calculate a link from the source directory to the destination directory. |
| 327 | local linkFrom = function(source, dest) | 364 | local linkFrom = function(source, dest) |
| 365 | -- Evil hacks! | ||
| 366 | if 'Profiles' == dest then dest = 'PmWiki/Profiles' end | ||
| 367 | if 'Onefang' == dest then dest = 'PmWiki/Onefang' end | ||
| 368 | |||
| 369 | if source == dest then return '' end | ||
| 328 | local depth = 0 | 370 | local depth = 0 |
| 329 | local link = '' | 371 | local lnk = '' |
| 330 | if source ~= dest then | 372 | if source ~= dest then |
| 331 | for i, v in ipairs(Subs[source].bits) do | 373 | if nil == Subs[source] then |
| 332 | if v ~= Subs[dest].bits[i] then | 374 | -- print('!!!! No idea where to find source ' .. source) |
| 333 | depth = i | 375 | return 'DUNNO' |
| 334 | break | 376 | end |
| 377 | if nil == Subs[dest] then | ||
| 378 | if dest == Subs[source].bit then | ||
| 379 | return '' | ||
| 380 | else | ||
| 381 | -- print('!!!! No idea where to find dest ' .. dest .. ' from ' .. Subs[source].path .. ' / ' .. Subs[source].bit) | ||
| 382 | return 'DUNNO' | ||
| 335 | end | 383 | end |
| 336 | end | 384 | end |
| 385 | local s = Subs[source].bits | ||
| 386 | local d = Subs[dest].bits | ||
| 387 | local sl = #s | ||
| 388 | local dl = #d | ||
| 337 | 389 | ||
| 338 | if #(Subs[dest].bits) >= #(Subs[source].bits) then | 390 | if 0 == dl then |
| 339 | depth = #(Subs[source].bits) | 391 | depth = sl |
| 340 | for i, v in ipairs(Subs[dest].bits) do | 392 | else |
| 341 | if i > depth then | 393 | for i, v in ipairs(s) do |
| 342 | if '' ~= link then link = link .. '/' end | 394 | if (nil == d[i]) or (v ~= d[i]) then |
| 343 | link = link .. Subs[dest].bits[i] | 395 | depth = i |
| 396 | break | ||
| 344 | end | 397 | end |
| 345 | end | 398 | end |
| 346 | if '' ~= link then link = link .. '/' end | ||
| 347 | else | ||
| 348 | depth = #(Subs[source].bits) - depth | ||
| 349 | depth = depth + 1 | ||
| 350 | link = string.rep('../', depth) | ||
| 351 | end | 399 | end |
| 400 | -- depth is where they DON'T match. | ||
| 401 | local m = depth - 1 | ||
| 402 | if 0 > m then m = 0 end | ||
| 403 | lnk = string.rep('../', sl - m) | ||
| 404 | if 0 ~= (m + 1) then lnk = lnk .. table.concat(d, '/', m + 1, dl) end | ||
| 352 | end | 405 | end |
| 353 | return link | 406 | return lnk |
| 354 | end | 407 | end |
| 355 | 408 | ||
| 356 | 409 | ||
| 410 | |||
| 411 | --------------------------------------------------------------------------------- | ||
| 357 | -- More of this actually doing things nonsense. | 412 | -- More of this actually doing things nonsense. |
| 358 | 413 | ||
| 414 | -- Create an "everything" page, for URL links to every file.HTML. | ||
| 415 | local Bdy = '# All the pages\n\n| page | converted | original page | last edited UTC | \n| ---- | --------- | ------- | --------------- | ' | ||
| 416 | Pages = {} | ||
| 417 | for name, file in pairs(Files) do | ||
| 418 | local metadata = derefTable(Files[name].metadata, true) | ||
| 419 | if ('everything' ~= name) then | ||
| 420 | local ln, fw, pw, ts = 'DUNNO', '', '', '' | ||
| 421 | local title, link = whichWiki(metadata) | ||
| 422 | link = string.gsub(link, 'https://', 'HTTPS://') -- Prevent this one from being converted. | ||
| 423 | if 'PmWiki' == metadata.ogWiki then pw = 'PmWiki [' .. title .. '](' .. link .. ')' end | ||
| 424 | if 'Foswiki' == metadata.ogWiki then fw = 'Foswiki [' .. title .. '](' .. link .. ')' end | ||
| 425 | if nil ~= metadata.timestamp then ts = metadata.timestamp end | ||
| 426 | if nil ~= file.bit then ln = file.bit | ||
| 427 | end | ||
| 428 | table.insert(Pages, '\n| ' .. name .. ' | [' .. ln .. '](<' .. name .. '.HTML>) | ' .. fw .. ' ' .. pw .. ' | ' .. ts .. ' |') | ||
| 429 | |||
| 430 | -- Track our external links. | ||
| 431 | if (nil ~= metadata.ogBase) and (nil ~= metadata.ogFile) then | ||
| 432 | local n = metadata.ogBase | ||
| 433 | if 'PmWiki' == metadata.ogWiki then n = n .. '.' else n = n .. '/' end | ||
| 434 | xLinks[n .. metadata.ogFile] = file.path | ||
| 435 | end | ||
| 436 | end | ||
| 437 | end | ||
| 438 | table.sort(Pages, function(a, b) return (string.lower(a) < string.lower(b)) end) | ||
| 439 | for i, f in ipairs(Pages) do | ||
| 440 | Bdy = Bdy .. f | ||
| 441 | end | ||
| 442 | h = io.open('everything.md', 'a+') | ||
| 443 | if nil ~= h then | ||
| 444 | h:write(Bdy) | ||
| 445 | h:close() | ||
| 446 | else | ||
| 447 | print("Can't open everything.md for writing.") | ||
| 448 | end | ||
| 449 | toFile('everything', 'body', Bdy) | ||
| 450 | |||
| 451 | |||
| 359 | -- Loop through Subs, doing whichPage and inheritance. | 452 | -- Loop through Subs, doing whichPage and inheritance. |
| 453 | -- It gets to testing/even/deeper BEFORE it gets to testing/even sometimes. So sort them. | ||
| 454 | SUBS = {} | ||
| 360 | for name, sub in pairs(Subs) do | 455 | for name, sub in pairs(Subs) do |
| 456 | table.insert(SUBS, sub) | ||
| 457 | end | ||
| 458 | table.sort(SUBS, function(a, b) return (string.lower(a.path) < string.lower(b.path)) end) | ||
| 459 | for n, sub in pairs(SUBS) do | ||
| 460 | local name = sub.path | ||
| 361 | sub.whichPage = whichPage(name) | 461 | sub.whichPage = whichPage(name) |
| 362 | local metadata = sub.metadata | 462 | local metadata = sub.metadata |
| 363 | for i, s in pairs(sub.subs) do | 463 | for i, s in pairs(sub.subs) do |
| 364 | local nm = i | 464 | local nm = i |
| 365 | if '' ~= name then nm = name .. '/' .. i end | 465 | if '' ~= name then nm = name .. '/' .. i end |
| 366 | ss = Subs[nm] | ||
| 367 | for k, v in pairs(metadata) do | 466 | for k, v in pairs(metadata) do |
| 368 | if nil == ss.metadata[k] then | 467 | if nil == Subs[nm].metadata[k] then |
| 369 | if ('favicon' == k) or ('logo' == k) then | 468 | if ('favicon' == k) or ('logo' == k) then |
| 370 | ss.metadata[k] = linkFrom(nm, name) .. v | 469 | Subs[nm].metadata[k] = linkFrom(nm, name) .. v |
| 371 | else | 470 | else |
| 372 | ss.metadata[k] = v | 471 | if 'hidden' ~= k then -- Don't inherit hidden. |
| 472 | Subs[nm].metadata[k] = v | ||
| 473 | end | ||
| 373 | end | 474 | end |
| 374 | end | 475 | end |
| 375 | end | 476 | end |
| 376 | end | 477 | end |
| 377 | end | 478 | end |
| 378 | 479 | ||
| 379 | -- Loop through the files we found and actually create their HTML files. | 480 | -- Files inheritance. |
| 380 | for name, file in pairs(Files) do | 481 | for name, file in pairs(Files) do |
| 381 | local path, result = '', '' | 482 | if '' ~= file.body then |
| 382 | local body, metadata = Files[name].body, derefTable(Files[name].metadata, true) | 483 | local mdata = Subs[file.path].metadata |
| 383 | local bits, bit = Files[name].bits, Files[name].bit | ||
| 384 | local ln = #bits | ||
| 385 | |||
| 386 | path = table.concat(bits, '/', 1, ln) | ||
| 387 | |||
| 388 | if '' ~= body then | ||
| 389 | -- Inherit stuff from sub and global. | ||
| 390 | local mdata = Subs[path].metadata | ||
| 391 | for k, v in pairs(mdata) do | 484 | for k, v in pairs(mdata) do |
| 392 | if nil == file.metadata[k] then | 485 | if nil == file.metadata[k] then |
| 393 | file.metadata[k] = v | 486 | Files[name].metadata[k] = v |
| 394 | end | 487 | end |
| 395 | end | 488 | end |
| 396 | Files[name].metadata = file.metadata | 489 | end |
| 397 | metadata = derefTable(Files[name].metadata, true) | 490 | end |
| 398 | for m, x in pairs(globalData) do if nil == metadata[m] then metadata[m] = x end end | ||
| 399 | 491 | ||
| 400 | if nil ~= metadata.ogURL then | 492 | |
| 401 | local title, link = whichWiki(metadata) | 493 | --------------------------------------------------------------------------------- |
| 402 | body = body .. '\n\n---\n\n[Original page]' .. link .. ', maybe you can edit it.\n' | 494 | -- Setup the lunarmark stuff. |
| 495 | local LunamarkOpts = { | ||
| 496 | layout='compact', | ||
| 497 | -- This list is copied from the lunamark source code, until I discover a way to discover it. The descriptions are useful to. | ||
| 498 | containers=false, -- Put sections in containers (e.g. div or section tags) | ||
| 499 | slides=false, -- Like containers, but do not nest them | ||
| 500 | startnum=true, -- Start number of an ordered list is significant | ||
| 501 | smart=false, -- Smart typography (quotes, dashes, ellipses) | ||
| 502 | preserve_tabs=true, -- Don't expand tabs to spaces | ||
| 503 | notes=true, -- Footnotes | ||
| 504 | inline_notes=true, -- Inline footnotes | ||
| 505 | definition_lists=true, -- Definition lists | ||
| 506 | citations=true, -- Citations | ||
| 507 | citation_nbsps=true, -- Turn spacing into non-breaking spaces in citations | ||
| 508 | fenced_code_blocks=true, -- Fenced code blocks | ||
| 509 | lua_metadata=true, -- Lua metadata | ||
| 510 | pandoc_title_blocks=true, -- Pandoc style title blocks | ||
| 511 | hash_enumerators=true, -- may be used as ordered list enumerator | ||
| 512 | require_blank_before_blockquote=false, | ||
| 513 | require_blank_before_header=false, | ||
| 514 | require_blank_before_fenced_code_block=false, | ||
| 515 | fancy_lists=true, -- Pandoc style fancy lists | ||
| 516 | task_list=true, -- GitHub-Flavored Markdown task list | ||
| 517 | strikeout=true, -- Strike-through with double tildes | ||
| 518 | mark=true, -- Highlight with double equals | ||
| 519 | subscript=true, -- Subscripted text between tildes | ||
| 520 | superscript=true, -- Superscripted text between circumflexes | ||
| 521 | bracketed_spans=true, -- Spans with attributes | ||
| 522 | fenced_divs=true, -- Divs with attributes | ||
| 523 | raw_attribute=true, -- Raw pass-through on code elements | ||
| 524 | fenced_code_attributes=true, -- Fenced code block attributes | ||
| 525 | link_attributes=true, -- Link attributes | ||
| 526 | pipe_tables=true, -- PHP Markdown Extra pipe table support | ||
| 527 | table_captions=true, -- Table caption syntax extension | ||
| 528 | header_attributes=true, -- Header attributes | ||
| 529 | line_blocks=true, -- Line blocks | ||
| 530 | escaped_line_breaks=true, -- Pandoc-style escaped hard line breaks | ||
| 531 | } | ||
| 532 | local Writer = Lunamark.writer.html5.new(LunamarkOpts) | ||
| 533 | |||
| 534 | -- Can override the various writer functions, there's something for each of the basic HTML elements. | ||
| 535 | local Context = {} -- Coz can't otherwise pass context through to the deeper Lunamark functions I'm overriding. | ||
| 536 | -- Fix up the links. | ||
| 537 | local OgWriterLink = Writer.link -- So we can call the original from within mine, we are just changing the URL. | ||
| 538 | function Writer.link(lab, url, tit) | ||
| 539 | if ('https://wiki.devuan.org/' ~= url) and ('https://fos.wiki.devuan.org/' ~= url) then | ||
| 540 | local label = lab | ||
| 541 | local uri = url | ||
| 542 | if 'string' ~= type(lab) then label = type(lab) end | ||
| 543 | for i, p in ipairs{'https://wiki.devuan.org/?n=', 'https://wiki.devuan.org?n=', 'https://fos.wiki.devuan.org/'} do | ||
| 544 | if p == string.sub(url, 1, #p) then | ||
| 545 | local ur = string.sub(url, #p + 1) | ||
| 546 | -- TODO - could probably replace some of this mess with RE.gsub() and friends. Meh, it works. | ||
| 547 | local f4, f5, tk1 = string.find(ur, '?', 1, true) | ||
| 548 | if fail ~= f4 then | ||
| 549 | local u = string.sub(ur, 1, f4 - 1) | ||
| 550 | ur = u | ||
| 551 | end | ||
| 552 | if nil == Context.path then | ||
| 553 | url = string.gsub(ur, '%.', '/', 1) | ||
| 554 | else | ||
| 555 | local xlnk = xLinks[string.gsub(ur, '%..*', '', 1)] | ||
| 556 | if nil == xlnk then xlnk = string.gsub(ur, '%..*', '', 1) end | ||
| 557 | if '' ~= Context.path then xlnk = linkFrom(Context.path, xlnk) end | ||
| 558 | if '/' == string.sub(xlnk, 1, 1) then xlnk = string.sub(xlnk, 2) end | ||
| 559 | if ('' ~= xlnk) and ('/' ~= string.sub(xlnk, -1)) then xlnk = xlnk .. '/' end | ||
| 560 | if 'DUNNO/' == xlnk then print('OOPS! Page not found - ' .. Context.path .. ' / ' .. Context.bit .. ' ' .. url .. ' -> ' .. xlnk .. ' ' .. string.gsub(ur, '.*%.', '', 1) .. '.HTML') end | ||
| 561 | url = xlnk .. string.gsub(ur, '.*%.', '', 1) .. '.HTML' | ||
| 562 | end | ||
| 563 | end | ||
| 403 | end | 564 | end |
| 565 | end | ||
| 566 | return OgWriterLink(lab, url, tit) | ||
| 567 | end | ||
| 568 | local Parse = Lunamark.reader.markdown.new(Writer, LunamarkOpts) | ||
| 569 | |||
| 404 | 570 | ||
| 571 | --------------------------------------------------------------------------------- | ||
| 572 | -- Loop through the files we found and actually create their HTML files. | ||
| 573 | for name, file in pairs(Files) do | ||
| 574 | local body, metadata = Files[name].body, derefTable(Files[name].metadata, true) | ||
| 575 | local bits, bit = Files[name].bits, Files[name].bit | ||
| 576 | local ln = #bits | ||
| 577 | local result = '' | ||
| 578 | |||
| 579 | if '' ~= body then | ||
| 405 | -- Figure out this pages trail links. | 580 | -- Figure out this pages trail links. |
| 406 | metadata.home = linkFrom(path, '') .. Subs[''].whichPage | 581 | metadata.home = linkFrom(file.path, '') .. Subs[''].whichPage |
| 407 | metadata.trail = '' | 582 | metadata.trail = '' |
| 408 | for i, b in ipairs(bits) do | 583 | for i, b in ipairs(bits) do |
| 409 | local p = table.concat(bits, '/', 1, i) | 584 | local p = table.concat(bits, '/', 1, i) |
| 410 | if i < #bits then | 585 | if i < #bits then |
| 411 | metadata.trail = metadata.trail .. '<a href="' .. linkFrom(path, p) .. Subs[p].whichPage .. '">' .. b .. '</a> 👣 ' | 586 | metadata.trail = metadata.trail .. '<a href="' .. linkFrom(file.path, p) .. Subs[p].whichPage .. '">' .. b .. '</a> 👣 ' |
| 412 | linkFrom(path, table.concat(bits, '/', 1, i)) | 587 | linkFrom(file.path, table.concat(bits, '/', 1, i)) |
| 413 | else | 588 | else |
| 414 | metadata.trail = metadata.trail .. b .. ' ' | 589 | metadata.trail = metadata.trail .. b .. ' ' |
| 415 | end | 590 | end |
| @@ -418,28 +593,30 @@ for name, file in pairs(Files) do | |||
| 418 | -- Figure out this pages header links. | 593 | -- Figure out this pages header links. |
| 419 | metadata.header = '' | 594 | metadata.header = '' |
| 420 | subs = {} | 595 | subs = {} |
| 421 | for i, f in pairs(Subs[path].subs) do | 596 | for i, f in pairs(Subs[file.path].subs) do |
| 422 | table.insert(subs, f) | 597 | table.insert(subs, f) |
| 423 | end | 598 | end |
| 424 | table.sort(subs, function(a, b) return (string.lower(a) < string.lower(b)) end) | 599 | table.sort(subs, function(a, b) return (string.lower(a) < string.lower(b)) end) |
| 425 | for i, f in ipairs(subs) do | 600 | for i, f in ipairs(subs) do |
| 426 | local pth = path | 601 | local pth = file.path |
| 427 | if '' ~= path then pth = path .. '/' end | 602 | if '' ~= file.path then pth = file.path .. '/' end |
| 428 | metadata.header = metadata.header .. '<a href="' .. f .. '/' .. whichPage(pth .. f) .. '">' .. f .. '</a> ' | 603 | if 'true' ~= Subs[pth .. f].metadata.hidden then |
| 604 | metadata.header = metadata.header .. '<a href="' .. f .. '/' .. whichPage(pth .. f) .. '">' .. f .. '</a> ' | ||
| 605 | end | ||
| 429 | end | 606 | end |
| 430 | 607 | ||
| 431 | -- Figure out this pages menu links. | 608 | -- Figure out this pages menu links. |
| 432 | metadata.menu = '' | 609 | metadata.menu = '' |
| 433 | if nil == metadata.title then metadata.title = bit end | 610 | if nil == metadata.title then metadata.title = bit end |
| 434 | if nil ~= Subs[path].files then table.sort(Subs[path].files, function(a, b) return (string.lower(a) < string.lower(b)) end) end | 611 | if nil ~= Subs[file.path].files then table.sort(Subs[file.path].files, function(a, b) return (string.lower(a) < string.lower(b)) end) end |
| 435 | for i, f in ipairs(Subs[path].files) do | 612 | for i, f in ipairs(Subs[file.path].files) do |
| 436 | local title, url = nil, nil | 613 | local title, url = nil, nil |
| 437 | if '' == path then | 614 | if '' == file.path then |
| 438 | title = Files[f].metadata.title | 615 | title = Files[f].metadata.title |
| 439 | url = Files[f].metadata.URL | 616 | url = Files[f].metadata.URL |
| 440 | else | 617 | else |
| 441 | title = Files[path .. '/' .. f].metadata.title | 618 | title = Files[file.path .. '/' .. f].metadata.title |
| 442 | url = Files[path .. '/' .. f].metadata.URL | 619 | url = Files[file.path .. '/' .. f].metadata.URL |
| 443 | end | 620 | end |
| 444 | if nil == title then title = f end | 621 | if nil == title then title = f end |
| 445 | if bit == f then metadata.menu = metadata.menu .. '<p>' .. title .. '</p>' | 622 | if bit == f then metadata.menu = metadata.menu .. '<p>' .. title .. '</p>' |
| @@ -451,42 +628,47 @@ for name, file in pairs(Files) do | |||
| 451 | end | 628 | end |
| 452 | 629 | ||
| 453 | -- Figure out this pages footer links. | 630 | -- Figure out this pages footer links. |
| 454 | if nil ~= metadata.pagehistory then metadata.history = '<p>Page <a href="' .. metadata.pagehistory .. '/' .. name .. '.md">history</a></p>' end | 631 | metadata.footer = GlobalMetaData.footer |
| 632 | if nil ~= metadata.pagehistory then metadata.history = '<p>Page <a href="' .. metadata.pagehistory .. '/' .. name .. '.md">history</a></p>' else metadata.history = '' end | ||
| 455 | if nil ~= metadata.sourcecode then metadata.footer = '<a href="' .. metadata.sourcecode .. '">source code</a> ' .. metadata.footer end | 633 | if nil ~= metadata.sourcecode then metadata.footer = '<a href="' .. metadata.sourcecode .. '">source code</a> ' .. metadata.footer end |
| 456 | if nil ~= metadata.feedatom then metadata.footer = '<a href="' .. metadata.feedatom .. '">atom feed</a> ' .. metadata.footer end | 634 | if nil ~= metadata.feedatom then metadata.footer = '<a href="' .. metadata.feedatom .. '">atom feed</a> ' .. metadata.footer end |
| 457 | if metadata.footer ~= globalData.footer then metadata.footer = 'Web site ' .. metadata.footer end | 635 | if metadata.footer ~= GlobalMetaData.footer then metadata.footer = 'Web site ' .. metadata.footer end |
| 636 | -- Add a link to the original page. | ||
| 637 | if nil ~= metadata.ogURL then | ||
| 638 | local title, link = whichWiki(metadata) | ||
| 639 | link = string.gsub(link, 'https://', 'HTTPS://') -- Prevent this one from being converted. | ||
| 640 | metadata.footer = '<a href="' .. link .. '">Original page</a>, maybe you can edit it. ' .. metadata.footer | ||
| 641 | end | ||
| 458 | metadata.footer = '<p>' .. metadata.footer .. '</p>' | 642 | metadata.footer = '<p>' .. metadata.footer .. '</p>' |
| 459 | 643 | ||
| 460 | -- Do our own metadata replacement, it's simple and works better. | 644 | -- Do our own metadata replacement, it's simple and works better. |
| 461 | local temp = template | 645 | local temp = Template |
| 462 | local start = 1 | ||
| 463 | local f0, f1, token | ||
| 464 | -- Toss the body in first, so the scan can deal with it to. | 646 | -- Toss the body in first, so the scan can deal with it to. |
| 465 | f0, f1, token = string.find(temp, '%$(body)%$') | 647 | -- NOTE - this is where we actually parse the markup into HTML. |
| 466 | if fail ~= f0 then | 648 | Context = file |
| 467 | -- NOTE - this is where we actually parse the markup into HTML. | 649 | local bd, md = Parse(body) -- The md is a table of extracted metadata, not likely to be any, and we wont do anything with it. |
| 468 | temp = string.sub(temp, 1, f0 - 1) .. parse(body) .. string.sub(temp, f1 + 1) | 650 | bd = RE.gsub(bd, '{[%]}', '$perc$') -- Coz otherwise stray % trip up the capture part. |
| 469 | end | 651 | temp = RE.gsub(temp, '"$body$"', bd) |
| 470 | -- The actual metadata replacement scan. | 652 | -- The actual metadata replacement. |
| 471 | result = '' | 653 | result = RE.compile ('{~ ({[$][A-Za-z_]+[$]} -> meta / .)* ~}', |
| 472 | repeat | 654 | { |
| 473 | f0, f1, token = string.find(temp, '%$([%w_]+)%$', start) | 655 | meta = function(a) |
| 474 | if fail ~= f0 then | 656 | a = string.sub(a, 2, -2) |
| 475 | if nil ~= metadata[token] then result = result .. string.sub(temp, start, f0 - 1) .. metadata[token] end | 657 | local md = metadata[a] |
| 476 | start = f1 + 1 | 658 | if nil == md then |
| 659 | md = GlobalMetaData[a] | ||
| 660 | if nil == md then | ||
| 661 | md = a | ||
| 662 | end | ||
| 663 | end | ||
| 664 | return md | ||
| 477 | end | 665 | end |
| 478 | until fail == f0 | 666 | } ):match(temp) |
| 479 | result = result .. string.sub(temp, start) | ||
| 480 | 667 | ||
| 481 | -- Write the file. | 668 | -- Write the file. |
| 482 | if '' ~= result then | 669 | if '' ~= result then |
| 483 | local base = name .. '.HTML' | ||
| 484 | -- print('From ' .. name .. '.md -> ' .. base) | 670 | -- print('From ' .. name .. '.md -> ' .. base) |
| 485 | local a, e = io.open(base, 'w') | 671 | writeString(name .. '.HTML', result) |
| 486 | if nil == a then print('Could not open ' .. base .. ' - ' .. e) else | ||
| 487 | a:write(result) | ||
| 488 | a:close() | ||
| 489 | end | ||
| 490 | end | 672 | end |
| 491 | end | 673 | end |
| 492 | end | 674 | end |
