size: 4 KiB
| 1 | --- @module 'djot' |
| 2 | --- Parse and render djot light markup format. See https://djot.net. |
| 3 | --- |
| 4 | --- @usage |
| 5 | --- local djot = require("djot") |
| 6 | --- local input = "This is *djot*" |
| 7 | --- local doc = djot.parse(input) |
| 8 | --- -- render as HTML: |
| 9 | --- print(djot.render_html(doc)) |
| 10 | --- |
| 11 | --- -- render as AST: |
| 12 | --- print(djot.render_ast_pretty(doc)) |
| 13 | --- |
| 14 | --- -- or in JSON: |
| 15 | --- print(djot.render_ast_json(doc)) |
| 16 | --- |
| 17 | --- -- alter the AST with a filter: |
| 18 | --- local src = "return { str = function(e) e.text = e.text:upper() end }" |
| 19 | --- -- subordinate modules like filter can be accessed as fields |
| 20 | --- -- and are lazily loaded. |
| 21 | --- local filter = djot.filter.load_filter(src) |
| 22 | --- djot.filter.apply_filter(doc, filter) |
| 23 | --- |
| 24 | --- -- streaming parser: |
| 25 | --- for startpos, endpos, annotation in djot.parse_events("*hello there*") do |
| 26 | --- print(startpos, endpos, annotation) |
| 27 | --- end |
| 28 | |
| 29 | local unpack = unpack or table.unpack |
| 30 | local Parser = require("djot.block").Parser |
| 31 | local ast = require("djot.ast") |
| 32 | local html = require("djot.html") |
| 33 | local json = require("djot.json") |
| 34 | local filter = require("djot.filter") |
| 35 | |
| 36 | --- @class StringHandle |
| 37 | local StringHandle = {} |
| 38 | |
| 39 | --- @return (StringHandle) |
| 40 | function StringHandle:new() |
| 41 | local buffer = {} |
| 42 | setmetatable(buffer, StringHandle) |
| 43 | StringHandle.__index = StringHandle |
| 44 | return buffer |
| 45 | end |
| 46 | |
| 47 | --- @param s (string) |
| 48 | function StringHandle:write(s) |
| 49 | self[#self + 1] = s |
| 50 | end |
| 51 | |
| 52 | --- @return (string) |
| 53 | function StringHandle:flush() |
| 54 | return table.concat(self) |
| 55 | end |
| 56 | |
| 57 | --- Parse a djot text and construct an abstract syntax tree (AST) |
| 58 | --- representing the document. |
| 59 | --- @param input (string) input string |
| 60 | --- @param sourcepos (boolean) if true, source positions are included in the AST |
| 61 | --- @param warn (function) function that processes a warning, accepting a warning |
| 62 | --- object with `pos` and `message` fields. |
| 63 | --- @return (AST) |
| 64 | local function parse(input, sourcepos, warn) |
| 65 | local parser = Parser:new(input, warn) |
| 66 | return ast.to_ast(parser, sourcepos) |
| 67 | end |
| 68 | |
| 69 | --- Parses a djot text and returns an iterator over events, consisting |
| 70 | --- of a start position (bytes), and an position (bytes), and an |
| 71 | --- annotation. |
| 72 | --- @param input (string) input string |
| 73 | --- @param warn (function) function that processes a warning, accepting a warning |
| 74 | --- object with `pos` and `message` fields. |
| 75 | --- @return integer, integer, string an iterator over events. |
| 76 | --- |
| 77 | --- for startpos, endpos, annotation in djot.parse_events("hello *world") do |
| 78 | --- ... |
| 79 | --- end |
| 80 | local function parse_events(input, warn) |
| 81 | return Parser:new(input):events() |
| 82 | end |
| 83 | |
| 84 | --- Render a document's AST in human-readable form. |
| 85 | --- @param doc (AST) the AST |
| 86 | --- @return (string) rendered AST |
| 87 | local function render_ast_pretty(doc) |
| 88 | local handle = StringHandle:new() |
| 89 | ast.render(doc, handle) |
| 90 | return handle:flush() |
| 91 | end |
| 92 | |
| 93 | --- Render a document's AST in JSON. |
| 94 | --- @param doc (AST) the AST |
| 95 | --- @return (string) rendered AST (JSON string) |
| 96 | local function render_ast_json(doc) |
| 97 | return json.encode(doc) .. "\n" |
| 98 | end |
| 99 | |
| 100 | --- Render a document as HTML. |
| 101 | --- @param doc (AST) the AST |
| 102 | --- @return (string) rendered document (HTML string) |
| 103 | local function render_html(doc) |
| 104 | local handle = StringHandle:new() |
| 105 | local renderer = html.Renderer:new() |
| 106 | renderer:render(doc, handle) |
| 107 | return handle:flush() |
| 108 | end |
| 109 | |
| 110 | --- Render an event as a JSON array. |
| 111 | --- @param startpos (integer) starting byte position |
| 112 | --- @param endpos (integer) ending byte position |
| 113 | --- @param annotation (string) annotation of event |
| 114 | --- @return (string) rendered event (JSON string) |
| 115 | local function render_event(startpos, endpos, annotation) |
| 116 | return string.format("[%q,%d,%d]", annotation, startpos, endpos) |
| 117 | end |
| 118 | |
| 119 | --- Parse a document and render as a JSON array of events. |
| 120 | --- @param input (string) the djot document |
| 121 | --- @param warn (function) function that emits warnings, taking as argumnet |
| 122 | --- an object with fields 'message' and 'pos' |
| 123 | --- @return (string) rendered events (JSON string) |
| 124 | local function parse_and_render_events(input, warn) |
| 125 | local handle = StringHandle:new() |
| 126 | local idx = 0 |
| 127 | for startpos, endpos, annotation in parse_events(input, warn) do |
| 128 | idx = idx + 1 |
| 129 | if idx == 1 then |
| 130 | handle:write("[") |
| 131 | else |
| 132 | handle:write(",") |
| 133 | end |
| 134 | handle:write(render_event(startpos, endpos, annotation) .. "\n") |
| 135 | end |
| 136 | handle:write("]\n") |
| 137 | return handle:flush() |
| 138 | end |
| 139 | |
| 140 | --- djot version (string) |
| 141 | local version = "0.2.1" |
| 142 | |
| 143 | --- @export |
| 144 | local G = { |
| 145 | parse = parse, |
| 146 | parse_events = parse_events, |
| 147 | parse_and_render_events = parse_and_render_events, |
| 148 | render_html = render_html, |
| 149 | render_ast_pretty = render_ast_pretty, |
| 150 | render_ast_json = render_ast_json, |
| 151 | render_event = render_event, |
| 152 | version = version |
| 153 | } |
| 154 | |
| 155 | -- Lazily load submodules, e.g. djot.filter |
| 156 | setmetatable(G,{ __index = function(t,name) |
| 157 | local mod = require("djot." .. name) |
| 158 | rawset(t,name,mod) |
| 159 | return t[name] |
| 160 | end }) |
| 161 | |
| 162 | return G |