-- pandoc filter to output Graphviz DOT graph from gamebook -- Copyright 2021-2022 Pelle Nilsson -- MIT License -- source: https://github.com/lifelike/pangamebook -- version: 1.5.1 (2023-01-20) -- fossil hash: 7d95c4d608a9545a21e19a3a533617d069ef679641b7c03f3477f394c5ba83c8 function one_string_from_block(b) local result = "" local found_text = false pandoc.walk_block(b, { Str = function(s) if found_text then return "" else result = s.text end end }) return result end function is_gamebook_section_header(el) if not (el.t == "Header" and el.level == 1) then return false end local first = one_string_from_block(el) local as_number = tonumber(first) return as_number ~= null and as_number >= 1 end function dot_label_for_header(b) local label = one_string_from_block(b) local identifier = b.identifier if not (identifier == "section" or identifier:sub(1, 8) == "section-") then label = label .. '\\n' .. identifier end return '"' .. identifier .. '" [label=\"' ..label .. '"];\n' end function dot_link(from, to) return '"' .. from .. '" -> "' .. to .. '";\n' end local endstyle = '[shape=doubleoctagon]' function Pandoc(doc) if not FORMAT:match "plain" then return doc end local in_header = nil local links_out = false local identifiers = {} local output = "digraph gamebook {\nnode[shape=box];\n\n" for i,el in pairs(doc.blocks) do if is_gamebook_section_header(el) then output = output .. dot_label_for_header(el) identifiers["#" .. el.identifier] = el.identifier end end for i,el in pairs(doc.blocks) do if is_gamebook_section_header(el) then if in_section and not links_out then output = output .. '"' .. in_section .. '"' .. endstyle .. ';\n' end in_section = el.identifier links_out = false elseif el.t == "Para" and in_section then for j,c in pairs(el.content) do if c.t == "Link" then local target = identifiers[c.target] if target then output = output .. dot_link(in_section, target) links_out = true end end end end end if in_section and not links_out then output = output .. '"' .. in_section .. '"' .. endstyle .. ';\n' end output = output .. "}\n" local blocks = pandoc.Para(pandoc.Str(output)) return pandoc.Pandoc(blocks, doc.meta) end function Blocks(blocks) return blocks end return { {Pandoc = Pandoc}, }