diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index ddc2038b..4c37fb3e 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -27,6 +27,9 @@ env: jobs: run-busted: runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.sha }} + cancel-in-progress: true steps: - uses: actions/checkout@v4 with: diff --git a/.gitignore b/.gitignore index 5bca5319..69701567 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ dist/* web/dist/* web/dist-c/* +web/wiki/* web/node_modules/* .debug/* doc/scratch/ diff --git a/justfile b/justfile index 1be244fa..14ccf699 100644 --- a/justfile +++ b/justfile @@ -20,9 +20,9 @@ unit_test_brief: @{{MON}} -e 'lua' --exec 'echo -en "\n\n\n\n------------- BUSTED -------------\n"; busted tests -o tests/brief_output.lua' unit_test_tag TAG: @{{MON}} -e lua \ - --exec 'echo -en "\n\n\n\n------------- BUSTED -------------\n" ; busted tests --defer-print --tags {{TAG}}' + --exec 'echo -en "\n\n\n\n------------- BUSTED -------------\n" ; busted tests --defer-print --tags="{{TAG}}"' unit_test_ast: - @SHOW_AST=1 just unit_test_tag ast + @just unit_test_tag ast unit_test_src: @SHOW_CODE=1 just unit_test_tag src unit_test_parser: diff --git a/src/controller/consoleController.lua b/src/controller/consoleController.lua index d4b52d06..ee266acd 100644 --- a/src/controller/consoleController.lua +++ b/src/controller/consoleController.lua @@ -98,25 +98,24 @@ end --- @return boolean success --- @return string? errmsg local function run_user_code(f, cc, project_path) - local gfx = love.graphics local output = cc.model.output local env = cc:get_base_env() - gfx.setCanvas(cc:get_canvas()) local ok, call_err - if project_path then - env = cc:get_project_env() - end - ok, call_err = pcall(f) - if project_path and ok then -- user project exec - if love.PROFILE then - love.PROFILE.frame = 0 - love.PROFILE.report = {} + cc:use_canvas(function() + if project_path then + env = cc:get_project_env() end - cc.main_ctrl.set_user_handlers(env['love']) - end - output:restore_main() - gfx.setCanvas() + ok, call_err = pcall(f) + if project_path and ok then -- user project exec + if love.PROFILE then + love.PROFILE.frame = 0 + love.PROFILE.report = {} + end + cc.main_ctrl.set_user_handlers(env['love'], cc) + end + output:restore_main() + end) if not ok then local msg = LANG.get_call_error(call_err) return false, msg @@ -429,12 +428,19 @@ function ConsoleController.prepare_project_env(cc) project_env.stop = function() cc:stop_project_run() end + project_env.run = function() + if love.state.app_state == 'inspect' then + cc:stop_project_run() + cc:run_project() + end + end + project_env.run_project = project_env.run project_env.continue = function() if love.state.app_state == 'inspect' then -- resume love.state.app_state = 'running' - cc.main_ctrl.restore_user_handlers() + cc.main_ctrl.restore_user_handlers(cc) else print('No project halted') end @@ -766,8 +772,9 @@ end function ConsoleController:edit(name, state) if love.state.app_state == 'running' then return end - local PS = self.model.projects - local p = PS.current + local PS = self.model.projects + local p = PS.current + if not p then return end local filename -- if state and state.buffer then -- filename = state.buffer.filename @@ -1048,6 +1055,15 @@ function ConsoleController:get_canvas() return self.model.output.canvas end +--- @param f function +function ConsoleController:use_canvas(f) + local canvas = self.model.output.canvas + gfx.setCanvas(canvas) + local r = f() + gfx.setCanvas() + return r +end + --- @return ViewData function ConsoleController:get_viewdata() return { diff --git a/src/controller/controller.lua b/src/controller/controller.lua index de98d29a..1ec84949 100644 --- a/src/controller/controller.lua +++ b/src/controller/controller.lua @@ -43,27 +43,27 @@ local _supported = { 'touchreleased', } -local _C, _mode - +--- @param C ConsoleController --- @param msg string -local function user_error_handler(msg) +local function user_error_handler(C, msg) Log.debug('user error: ' .. msg) local err = LANG.get_call_error(msg) or '' local user_msg = messages.exec_error(err) - _C:suspend_run(user_msg) + C:suspend_run(user_msg) print(user_msg) end --- @param f function +--- @param C ConsoleController --- @param ... any --- @return boolean success --- @return any result --- @return any ... -local function wrap(f, ...) +local function wrap(f, C, ...) if _G.web then local ok, r = pcall(f, ...) if not ok then - user_error_handler(r) + user_error_handler(C, r) end return r else @@ -72,22 +72,29 @@ local function wrap(f, ...) end --- @param f function +--- @param C ConsoleController --- @return function -local function error_wrapper(f) +local function error_wrapper(f, C) return function(...) - return wrap(f, ...) + local args = { ... } + C:use_canvas( + function() + return wrap(f, C, unpack(args)) + end + ) end end --- @param userlove table -local set_handlers = function(userlove) +--- @param C ConsoleController +local set_handlers = function(userlove, C) --- @param key string local function hook_if_differs(key) local orig = Controller._defaults[key] local new = userlove[key] if orig and new and orig ~= new then --- @type function - love[key] = error_wrapper(new) + love[key] = error_wrapper(new, C) end end @@ -384,7 +391,7 @@ Controller = { local draw = function() if ldr then gfx.push('all') - wrap(ldr) + wrap(ldr, C) gfx.pop() end local ui = get_user_input() @@ -401,7 +408,9 @@ Controller = { local uup = Controller._userhandlers.update if user_update and uup then - wrap(uup, dt) + C:use_canvas(function() + wrap(uup, C, dt) + end) end if love.state.app_state == 'snapshot' then gfx.captureScreenshot(function(img) @@ -477,11 +486,6 @@ Controller = { ---------------- --- public --- ---------------- - --- @param CC ConsoleController - init = function(CC, mode) - _C = CC - _mode = mode - end, --- @param C ConsoleController --- @param CV ConsoleView set_default_handlers = function(C, CV) @@ -804,8 +808,9 @@ Controller = { save_if_differs('draw') end, - restore_user_handlers = function() - set_handlers(Controller._userhandlers) + --- @param C ConsoleController + restore_user_handlers = function(C) + set_handlers(Controller._userhandlers, C) end, clear_user_handlers = function() diff --git a/src/examples/tixy/mathlib.lua b/src/examples/tixy/mathlib.lua index f0269c6f..73d28249 100644 --- a/src/examples/tixy/mathlib.lua +++ b/src/examples/tixy/mathlib.lua @@ -7,7 +7,7 @@ function hypot(a, b) return math.sqrt(a ^ 2 + b ^ 2) end -require("bit") +local bit = require("bit") for k, v in pairs(bit or {}) do _G[k] = v end diff --git a/src/lib/metalua b/src/lib/metalua index 26eaa786..0c4c30de 160000 --- a/src/lib/metalua +++ b/src/lib/metalua @@ -1 +1 @@ -Subproject commit 26eaa786a330dc4ffc08be7c58c8a189d56e8950 +Subproject commit 0c4c30de0ab26860f37797ef51493a2819e536be diff --git a/src/main.lua b/src/main.lua index 5591a00d..29f21657 100644 --- a/src/main.lua +++ b/src/main.lua @@ -353,10 +353,11 @@ function love.load() local CC = ConsoleController(CM, ctrl) local CV = ConsoleView(baseconf, CC) - ctrl.init(CC, mode) ctrl.setup_callback_handlers(CC) ctrl.set_default_handlers(CC, CV) + gfx.setColor(0, 0, 0, 1) + if playback then local ok, err = CC:open_project('play', true) if not ok then diff --git a/src/model/editor/bufferModel.lua b/src/model/editor/bufferModel.lua index 207d063a..0dab6b09 100644 --- a/src/model/editor/bufferModel.lua +++ b/src/model/editor/bufferModel.lua @@ -232,7 +232,7 @@ function BufferModel:move_selection(dir, by, warp, move) end end if dir == 'down' then - if (cur + by) <= last then + if (cur + by) <= last + 1 then self.selection = cur + by return true end diff --git a/src/model/input/userInputModel.lua b/src/model/input/userInputModel.lua index 97d0d537..4613feec 100644 --- a/src/model/input/userInputModel.lua +++ b/src/model/input/userInputModel.lua @@ -857,7 +857,7 @@ function UserInputModel:get_wrapped_error() local we = string.wrap_array( e, self.visible.wrap_w) - table.insert(we, 1, 'Errors:') + table.insert(we, 1, 'Errors:') return we end end @@ -880,7 +880,10 @@ end --- @return boolean function UserInputModel:has_error() - return string.is_non_empty_string_array(self.error) + if self.error and #(self.error) > 0 then + return true + end + return false end --- @param eval Evaluator diff --git a/src/model/io/redirect.lua b/src/model/io/redirect.lua index 9dc89d54..e60bf94f 100644 --- a/src/model/io/redirect.lua +++ b/src/model/io/redirect.lua @@ -5,11 +5,11 @@ local function set_print(M) local origPrint = _G.print _G.orig_print = origPrint local magicPrint = function(...) - local arg = { ... } local out = '' - local l = #arg - for i, v in ipairs(arg) do - out = out .. tostring(v) + local l = select('#', ...) + local args = { ... } + for i = 1, l do + out = out .. tostring(args[i]) if i ~= l then out = out .. '\t' end end origPrint(out) diff --git a/src/model/lang/lua/parser.lua b/src/model/lang/lua/parser.lua index 714612ca..d253c443 100644 --- a/src/model/lang/lua/parser.lua +++ b/src/model/lang/lua/parser.lua @@ -7,11 +7,9 @@ require("util.dequeue") --- @class luaAST : token ---- @alias CPos 'first'|'last' - --- @class Comment --- @field text string ---- @field position CPos +--- @field position CommentPos --- @field idf integer --- @field idl integer --- @field first Cursor @@ -318,6 +316,10 @@ return function(lib) local idx = 1 -- block number local last = 0 -- last line number local comment_ids = {} + --- Create chunk from comment text and pos + --- @param ctext str + --- @param c Comment + --- @param range Range local add_comment_block = function(ctext, c, range) ret:insert( Chunk.new(ctext, range), @@ -326,7 +328,7 @@ return function(lib) comment_ids[c.idl] = true end --- @param comments Comment[] - --- @param pos CPos + --- @param pos CommentPos local get_comments = function(comments, pos) for _, c in ipairs(comments) do -- Log.warn('c', c.position) @@ -415,7 +417,7 @@ return function(lib) if ret:last().tag ~= 'empty' and ( - --- no empty line at EOF + --- no empty line at EOF not single --- there is an empty line at the end or single and (#string.lines(text) > last) diff --git a/src/util/debug.lua b/src/util/debug.lua index 4e22aa38..4241f491 100644 --- a/src/util/debug.lua +++ b/src/util/debug.lua @@ -199,9 +199,13 @@ local function terse_ast(ast, skip_lineinfo, style) if type(k) == 'table' then res = res .. dent .. terse(k, omit, style) .. assign - elseif type(k) == 'number' and style == 'lua' then - -- skip index - res = res .. dent .. '[' .. k .. '] ' .. assign + elseif type(k) == 'number' then + if style == 'lua' then + -- skip index + res = res .. dent .. '[' .. k .. '] ' .. assign + elseif style == 'json5' then + res = res .. dent .. '"' .. k .. '"' .. assign + end elseif type(k) == 'string' and not string.forall(k, Char.is_ascii) then @@ -320,7 +324,7 @@ Debug = { if type(t) == 'table' then local start = math.max(1, skip or 0) for i = start, #t do - local l = t[i] or '' + local l = tostring(t[i]) or '' local line = (function() if not no_ln then return string.format("#%02d: %s\n", i, text(l)) diff --git a/src/view/consoleView.lua b/src/view/consoleView.lua index 9c0d4f4e..0ae04d44 100644 --- a/src/view/consoleView.lua +++ b/src/view/consoleView.lua @@ -60,11 +60,13 @@ function ConsoleView:draw(terminal, canvas, snapshot) self.editor:draw() end + gfx.push('all') if love.state.app_state == 'editor' then drawEditor() else drawConsole() end + gfx.pop() end function ConsoleView:draw_placeholder() diff --git a/src/view/editor/editorView.lua b/src/view/editor/editorView.lua index 8d122dc5..6aeb4672 100644 --- a/src/view/editor/editorView.lua +++ b/src/view/editor/editorView.lua @@ -36,12 +36,16 @@ function EditorView:draw() local spec = mode == 'reorder' local bv = self:get_current_buffer() + gfx.push('all') if ViewUtils.conditional_draw('show_buffer') then bv:draw(spec) end if ViewUtils.conditional_draw('show_input') then + gfx.push('all') self.input:draw() + gfx.pop() end + gfx.pop() end end diff --git a/src/view/input/userInputView.lua b/src/view/input/userInputView.lua index 5617a225..f5ffe90a 100644 --- a/src/view/input/userInputView.lua +++ b/src/view/input/userInputView.lua @@ -144,6 +144,7 @@ function UserInputView:render_input(input, status) gfx.pop() if highlight then + gfx.push('all') local hl = highlight.hl local perr = highlight.parse_err local el, ec @@ -209,6 +210,7 @@ function UserInputView:render_input(input, status) char, color, colors.bg, selected) end end + gfx.pop() else gfx.push('all') gfx.setColor(colors.fg) @@ -264,11 +266,13 @@ function UserInputView:render(input, status) self.canvas:renderTo(function() gfx.clear(0, 0, 0, 1) + gfx.push('all') if isError then self:render_error(err_text) else self:render_input(input, status) end + gfx.pop() end) end @@ -280,8 +284,9 @@ function UserInputView:draw() local b = self.cfg.statusline_border / 2 local h = self.start_h - b gfx.push('all') + gfx.setColor(1, 1, 1, 1) gfx.setBlendMode("replace") - love.graphics.draw(self.canvas, 0, h) + gfx.draw(self.canvas, 0, h) gfx.setBlendMode("alpha") gfx.pop() end diff --git a/tests/editor/buffer_spec.lua b/tests/editor/buffer_spec.lua index c5823874..4d5d615d 100644 --- a/tests/editor/buffer_spec.lua +++ b/tests/editor/buffer_spec.lua @@ -51,8 +51,8 @@ describe('Buffer #editor', function() local buffer, bufcon local meat = [[function sierpinski(depth) lines = { '*' } - for i = 2, depth + 1 do - sp = string.rep(' ', 2 ^ (i - 2)) + for z = 2, depth + 1 do + sp = string.rep(' ', 2 ^ (z - 2)) tmp = {} -- comment for idx, line in ipairs(lines) do tmp[idx] = sp .. line .. sp diff --git a/tests/editor/chunker_inputs.lua b/tests/editor/chunker_inputs.lua index 339834b1..674e293f 100644 --- a/tests/editor/chunker_inputs.lua +++ b/tests/editor/chunker_inputs.lua @@ -11,8 +11,8 @@ end local sierp_code = [[function sierpinski(depth) lines = { '*' } - for i = 2, depth + 1 do - sp = string.rep(' ', 2 ^ (i - 2)) + for c = 2, depth + 1 do + sp = string.rep(' ', 2 ^ (c - 2)) tmp = {} -- comment for idx, line in ipairs(lines) do tmp[idx] = sp .. line .. sp @@ -26,8 +26,8 @@ end print(sierpinski(4))]] local sierp_code_2 = [[function sierpinski(depth) lines = { '*' } - for i = 2, depth + 1 do - sp = string.rep(' ', 2 ^ (i - 2)) + for c = 2, depth + 1 do + sp = string.rep(' ', 2 ^ (c - 2)) tmp = {} -- comment for idx, line in ipairs(lines) do tmp[idx] = sp .. line .. sp @@ -43,8 +43,8 @@ print(sierpinski(4))]] local sierp_res = { Chunk(string.lines([[function sierpinski(depth) lines = { '*' } - for i = 2, depth + 1 do - sp = string.rep(' ', 2 ^ (i - 2)) + for c = 2, depth + 1 do + sp = string.rep(' ', 2 ^ (c - 2)) tmp = {} -- comment for idx, line in ipairs(lines) do tmp[idx] = sp .. line .. sp @@ -201,4 +201,21 @@ y = 2]], { Empty(11), }), + prep([[--- luadoc comment +function chonky() + --- inline comment + return {"big", "chungus"} +end]], { + Chunk({ '--- luadoc comment' }, Range(1, 1)), + Chunk({ + 'function chonky()', + ' --- inline comment', + ' return {"big", "chungus"}', + 'end' + }, + Range(2, 5) + ), + Empty(6), + }) + } diff --git a/tests/editor/chunker_spec.lua b/tests/editor/chunker_spec.lua index d6d9b9ed..db226922 100644 --- a/tests/editor/chunker_spec.lua +++ b/tests/editor/chunker_spec.lua @@ -13,16 +13,15 @@ describe('parser.chunker #chunk', function() end describe('produces blocks', function() - for i, test in ipairs(inputs) do - local str = test[1] - local blk = test[2] + for i, test in ipairs(inputs) do + local str = test[1] + local blk = test[2] - local ok, output = chunker(str) - it('matches ' .. i, function() - assert.is_true(ok) - assert.same(blk, output) - end) - end + it('matches ' .. i, function() + local ok, output = chunker(str) + assert.is_true(ok) + assert.same(blk, output) + end) + end end) - end) diff --git a/tests/editor/editor_spec.lua b/tests/editor/editor_spec.lua index 2c93f036..d65064b2 100644 --- a/tests/editor/editor_spec.lua +++ b/tests/editor/editor_spec.lua @@ -49,8 +49,8 @@ describe('Editor #editor', function() local sierpinski = { "function sierpinski(depth)", " lines = { '*' }", - " for i = 2, depth + 1 do", - " sp, tmp = string.rep(' ', 2 ^ (i - 2))", + " for e = 2, depth + 1 do", + " sp, tmp = string.rep(' ', 2 ^ (e - 2))", " tmp = {}", " for idx, line in ipairs(lines) do", " tmp[idx] = sp .. line .. sp", @@ -362,7 +362,10 @@ describe('Editor #editor', function() assert.same(start_range, visible.range) mock.keystroke('down', press) mock.keystroke('down', press) - assert.same(start_range, visible.range) + assert.same(start_range:translate(3), visible.range) + mock.keystroke('down', press) + mock.keystroke('down', press) + assert.same(start_range:translate(3), visible.range) end) end) end) @@ -394,7 +397,7 @@ describe('Editor #editor', function() --- TODO -- assert.same(start_range, visible.range) assert.same(Range(19, 24), visible.range) - assert.is_not.same(sel, buffer:get_selection()) + -- assert.is_not.same(sel, buffer:get_selection()) end) it('to top', function() mock.keystroke('C-home', press) @@ -432,22 +435,20 @@ describe('Editor #editor', function() --- end plaintext describe('structured (lua) works', function() - local controller, press = wire(TU.mock_view_cfg()) - local save, savefile = TU.get_save_function(sierpinski) + it('changing single line', function() + local controller, press = wire(TU.mock_view_cfg()) + local save, savefile = TU.get_save_function(sierpinski) - controller:open('sierpinski.lua', sierpinski, save) + controller:open('sierpinski.lua', sierpinski, save) - local input = controller.input - local buffer = controller:get_active_buffer() - local cont = buffer:get_content() + local input = controller.input + local buffer = controller:get_active_buffer() + local cont = buffer:get_content() - assert.same('lua', buffer.content_type) - it('length is correct', function() + assert.same('lua', buffer.content_type) assert.same('block', cont:type()) assert.same(4, buffer:get_content_length()) - end) - it('changing single line', function() local modified = table.clone(sierpinski) local new_print = 'print(sierpinski(3))' mock.keystroke('up', press) diff --git a/tests/interpreter/analyzer_inputs.lua b/tests/interpreter/analyzer_inputs.lua index bf55daab..d10853c1 100644 --- a/tests/interpreter/analyzer_inputs.lua +++ b/tests/interpreter/analyzer_inputs.lua @@ -109,8 +109,8 @@ local simple = { local sierpinski = [[function sierpinski(depth) lines = { '*' } - for i = 2, depth + 1 do - sp = string.rep(' ', 2 ^ (i - 2)) + for a = 2, depth + 1 do + sp = string.rep(' ', 2 ^ (a - 2)) tmp = {} -- comment for idx, line in ipairs(lines) do tmp[idx] = sp .. line .. sp @@ -156,7 +156,7 @@ local meta = [[ --- @param node token --- @return table -function M:extract_comments(node) +function M:parse_comments(node) local lfi = node.lineinfo.first local lla = node.lineinfo.last local comments = {} @@ -315,7 +315,7 @@ local full = { { line = 21, name = 'color', type = 'global', }, }, {})), prep(meta, SemanticInfo({ - { line = 3, name = 'M:extract_comments', type = 'method', }, + { line = 3, name = 'M:parse_comments', type = 'method', }, { line = 4, name = 'lfi', type = 'local', }, { line = 5, name = 'lla', type = 'local', }, { line = 6, name = 'comments', type = 'local', }, diff --git a/tests/interpreter/analyzer_spec.lua b/tests/interpreter/analyzer_spec.lua index 37d62aec..97754efa 100644 --- a/tests/interpreter/analyzer_spec.lua +++ b/tests/interpreter/analyzer_spec.lua @@ -11,10 +11,6 @@ if not orig_print then _G.orig_print = print end --- when testing with Lua5.3 -if not _G.unpack then - _G.unpack = table.unpack -end local w = 64 @@ -88,6 +84,7 @@ describe('analyzer #analyzer', function() end local ct, _ = do_code(v, seen_comments) + for _, cl in ipairs(string.lines(ct) or {}) do table.insert(result, cl) end diff --git a/tests/interpreter/ast_spec.lua b/tests/interpreter/ast_spec.lua index 67fd1d34..38ed750b 100644 --- a/tests/interpreter/ast_spec.lua +++ b/tests/interpreter/ast_spec.lua @@ -68,38 +68,39 @@ describe('parser #ast', function() io.write(string.rep('=', 80)) print(Debug.text_table(input)) end - local has_lines = false - local seen_comments = {} - for _, v in ipairs(r) do - if show_ast then - local fn = string.format('%s_input_%d', tag, i) - local skip_lineinfo = true - local tree = Debug.terse_ast(r, skip_lineinfo) - local f = string.format('/*\n%s\n*/\n%s', - string.unlines(input), - tree - ) - FS.write_tempfile(f, 'json5', fn) - end + it('matches ' .. i, function() + local has_lines = false + local seen_comments = {} + for _, v in ipairs(r) do + if show_ast then + local fn = string.format('%s_input_%d', tag, i) + + local skip_lineinfo = false + local tree = Debug.terse_ast(r, skip_lineinfo) + local f = string.format('/*\n%s\n*/\n%s', + string.unlines(input), + tree + ) + FS.write_tempfile(f, 'json5', fn) + end - has_lines = true - local ct, _ = do_code(v, seen_comments) - for _, cl in ipairs(string.lines(ct) or {}) do - table.insert(result, cl) + has_lines = true + local ct, _ = do_code(v, seen_comments) + for _, cl in ipairs(string.lines(ct) or {}) do + table.insert(result, cl) + end + end + --- corner case, e.g comments only + --- it is valid code, but gets parsed a bit differently + if not has_lines then + result = string.lines(do_code(r)) or {} end - end - --- corner case, e.g comments only - --- it is valid code, but gets parsed a bit differently - if not has_lines then - result = string.lines(do_code(r)) or {} - end - --- remove trailing newline - if result[#result] == '' then - table.remove(result) - end - it('matches ' .. i, function() + --- remove trailing newline + if result[#result] == '' then + table.remove(result) + end assert.same(output, result) assert.is_true(parser.parse(output)) end) diff --git a/tests/util/string_spec.lua b/tests/util/string_spec.lua index 04751797..3849f30c 100644 --- a/tests/util/string_spec.lua +++ b/tests/util/string_spec.lua @@ -97,8 +97,8 @@ describe("StringUtils #string", function() local sierpinski = { 'sierpinski = function(depth)', ' lines = { "*" }', - ' for i = 2, depth + 1 do', - ' sp = string.rep(" ", 2 ^ (i - 2))', + ' for k = 2, depth + 1 do', + ' sp = string.rep(" ", 2 ^ (k - 2))', ' tmp = { }', ' -- comment', ' for idx, line in ipairs(lines) do', diff --git a/web/wiki/convert.sh b/web/wiki/convert.sh new file mode 100755 index 00000000..ffb48dc8 --- /dev/null +++ b/web/wiki/convert.sh @@ -0,0 +1,50 @@ +#!/bin/bash -e + +### sanity checks + +[ -z "$1" ] && { + echo 'Provide an export xml' > /dev/stderr + exit 13 +} + +which yq > /dev/null +which jq > /dev/null +which pandoc > /dev/null + +### + +IN="$(realpath "$1")" + +TMPDIR=$(mktemp -d) +echo "$TMPDIR" +cd "$TMPDIR" || exit + +WM=wmark +MD=md + +mkdir -p $WM +mkdir -p $MD + +TMP=$(mktemp XXXXX.json) +cat "$IN" | yq -p xml '.mediawiki.page' -ojson \ + | jq 'map( {title: .title, content: .revision.text."+content" } )' \ + > "$TMP" + +jq -c '.[]' "$TMP" | while read -r obj; do + key=$(echo "$obj" | jq -r '.title') + value=$(echo "$obj" | jq -r '.content') + + if [[ "$key" == */* ]] + then + echo "Warning: '/' in title $key" > /dev/stderr + else + printf "%s\n" "$value" > "$WM/${key}.mediawiki" + fi +done + +for m in "$WM"/* +do + NAME=$(basename "$m" mediawiki) + pandoc -f mediawiki -t markdown "$m" -o $MD/"$NAME".md \ + || echo 'parse error in' "$NAME" > /dev/stderr +done diff --git a/web/wiki/md/.gitkeep b/web/wiki/md/.gitkeep new file mode 100644 index 00000000..e69de29b