@@ -81,10 +81,26 @@ local FormatDefaults = {
8181}
8282
8383
84- -- # State
85-
86- local out_format
87- local write_rules
84+ -- # Options
85+
86+ local Options = {
87+ format = ' pandoc-format' ,
88+ rules = nil ,
89+ type_map = {},
90+ types = {
91+ -- core (all formats)
92+ note = true , warning = true , tip = true , caution = true , important = true ,
93+ -- extended (obsidian, mkdocs, admonition ecosystems)
94+ info = true , success = true , question = true , failure = true , danger = true ,
95+ bug = true , example = true , quote = true , abstract = true , hint = true ,
96+ check = true , done = true , error = true , help = true , faq = true ,
97+ attention = true ,
98+ -- sphinx/myst
99+ seealso = true , todo = true ,
100+ -- vitepress
101+ details = true ,
102+ },
103+ }
88104
89105
90106-- # Helpers
@@ -94,9 +110,9 @@ local function get_type(div)
94110end
95111
96112local function format_type (type_str )
97- if write_rules .TypeCase == TypeCase .lower then
113+ if Options . rules .TypeCase == TypeCase .lower then
98114 return type_str :lower ()
99- elseif write_rules .TypeCase == TypeCase .upper then
115+ elseif Options . rules .TypeCase == TypeCase .upper then
100116 return type_str :upper ()
101117 else
102118 return type_str
@@ -115,13 +131,13 @@ end
115131local function write_div (div )
116132 local kind = format_type (get_type (div ))
117133 local title = div .attributes .title -- nil if absent, '' if explicitly empty
118- if out_format == ' pandoc-md' then
134+ if Options . format == ' pandoc-md' then
119135 -- intermediate: class only, preserve title attribute as-is
120136 div .classes = { kind }
121137 return div
122- elseif write_rules .Prefix then
138+ elseif Options . rules .Prefix then
123139 -- Quarto: omit title attribute if nil, Quarto auto-generates from class
124- div .classes = { write_rules .Prefix .. kind }
140+ div .classes = { Options . rules .Prefix .. kind }
125141 if title and title ~= ' ' then
126142 div .attributes .title = title
127143 else
@@ -146,7 +162,7 @@ local function write_blockquote(div)
146162 local kind = format_type (get_type (div ))
147163 local title = div .attributes .title
148164 local collapse = div .attributes .collapse
149- local suffix = write_rules .Collapse
165+ local suffix = Options . rules .Collapse
150166 and (collapse == ' true' and ' -' or collapse == ' false' and ' +' or ' ' )
151167 or ' '
152168 -- marker as RawInline to prevent Pandoc from escaping the brackets
166182
167183local function write_fence (div )
168184 local kind = format_type (get_type (div ))
169- local title = write_rules .HasTitle and (div .attributes .title or ' ' ) or ' '
170- local collapse = write_rules .Collapse and div .attributes .collapse == ' true'
185+ local title = Options . rules .HasTitle and (div .attributes .title or ' ' ) or ' '
186+ local collapse = Options . rules .Collapse and div .attributes .collapse == ' true'
171187 local cls = collapse and ' dropdown' or kind
172188 local open = pandoc .RawBlock (' markdown' , ' ```{' .. cls .. ' } ' .. title )
173189 local close = pandoc .RawBlock (' markdown' , ' ```' )
@@ -176,16 +192,16 @@ end
176192
177193local function write_admonition (div )
178194 local kind = format_type (get_type (div ))
179- local title = write_rules .HasTitle and (' "' .. (div .attributes .title or ' ' ) .. ' "' ) or ' '
180- local collapse = write_rules .Collapse and div .attributes .collapse == ' true'
195+ local title = Options . rules .HasTitle and (' "' .. (div .attributes .title or ' ' ) .. ' "' ) or ' '
196+ local collapse = Options . rules .Collapse and div .attributes .collapse == ' true'
181197 local marker = collapse and ' ???' or ' !!!'
182198 local open = pandoc .RawBlock (' markdown' , marker .. ' ' .. kind .. title )
183199 return { open , indent_content (div .content ) }
184200end
185201
186202local function write_directive (div )
187203 local kind = format_type (get_type (div ))
188- local title = write_rules .HasTitle and (div .attributes .title or ' ' ) or ' '
204+ local title = Options . rules .HasTitle and (div .attributes .title or ' ' ) or ' '
189205 local open = pandoc .RawBlock (' rst' , ' .. ' .. kind .. ' :: ' .. title )
190206 return { open , indent_content (div .content ) }
191207end
199215
200216local function write_colon (div )
201217 local kind = format_type (get_type (div ))
202- local title = write_rules .HasTitle and (div .attributes .title or ' ' ) or ' '
203- local collapse = write_rules .Collapse and div .attributes .collapse == ' true'
218+ local title = Options . rules .HasTitle and (div .attributes .title or ' ' ) or ' '
219+ local collapse = Options . rules .Collapse and div .attributes .collapse == ' true'
204220 local open = collapse
205221 and pandoc .RawBlock (' markdown' , ' :::details ' .. title )
206222 or pandoc .RawBlock (' markdown' , ' :::' .. kind .. ' ' .. title )
@@ -222,35 +238,18 @@ local Writers = {
222238}
223239
224240local function write_callout (div )
225- local writer = Writers [write_rules .Container ]
241+ local writer = Writers [Options . rules .Container ]
226242 if not writer then
227- error (' No writer for container: ' .. tostring (write_rules .Container ), 2 )
243+ error (' No writer for container: ' .. tostring (Options . rules .Container ), 2 )
228244 end
229245 return writer (div )
230246end
231247
232248
233249-- # Normalizers
234250
235- local TypeMap = {} -- optional kind remapping, e.g. info -> note
236-
237- --- Known callout types for Pandoc/Sphinx plain div detection.
238- local CalloutTypes = {
239- -- core (all formats)
240- note = true , warning = true , tip = true , caution = true , important = true ,
241- -- extended (obsidian, mkdocs, admonition ecosystems)
242- info = true , success = true , question = true , failure = true , danger = true ,
243- bug = true , example = true , quote = true , abstract = true , hint = true ,
244- check = true , done = true , error = true , help = true , faq = true ,
245- attention = true ,
246- -- sphinx/myst
247- seealso = true , todo = true ,
248- -- vitepress
249- details = true ,
250- }
251-
252251local function make_div (kind , blocks , title , collapse )
253- kind = TypeMap [kind ] or kind
252+ kind = Options . type_map [kind ] or kind
254253 local attrs = {}
255254 if title and title ~= ' ' then attrs .title = title end
256255 if collapse == true then attrs .collapse = ' true' end
261260--- GitHub / Obsidian: > [!WORD] or > [!word] — any casing accepted.
262261--- [!NOTE]+ expanded, [!NOTE]- collapsed.
263262local function normalize_github (bq )
264- if out_format == ' github-format' or out_format == ' obsidian-format' then return nil end
263+ if Options . format == ' github-format' or Options . format == ' obsidian-format' then return nil end
265264 local first = bq .content [1 ]
266265 if not first or first .t ~= ' Para' then return nil end
267266 local marker = first .content [1 ]
@@ -305,18 +304,18 @@ end
305304--- Quarto / Pandoc 3.9 / Sphinx / pandoc-md divs.
306305local function normalize_div (div )
307306 -- Quarto: :::{.callout-*} — title and collapse already in attributes
308- if out_format ~= ' quarto-format' then
307+ if Options . format ~= ' quarto-format' then
309308 local kind = div .classes [1 ] and div .classes [1 ]:match (' ^callout%-(.+)$' )
310309 if kind then
311310 div .classes = { kind }
312311 return write_callout (div )
313312 end
314313 end
315314 -- Pandoc 3.9 / Sphinx / pandoc-md: :::{.note} — title from attribute or .title child
316- if out_format ~= ' sphinx-format' and out_format ~= ' pandoc-format'
317- and out_format ~= ' pandoc-md' then
315+ if Options . format ~= ' sphinx-format' and Options . format ~= ' pandoc-format'
316+ and Options . format ~= ' pandoc-md' then
318317 local kind = div .classes [1 ]
319- if kind and CalloutTypes [kind ] then
318+ if kind and Options . types [kind ] then
320319 local title = div .attributes .title or nil
321320 local collapse_str = div .attributes .collapse
322321 local collapse = collapse_str == ' true' and true or nil
@@ -342,37 +341,37 @@ local function process_metadata(meta)
342341
343342 if not cfg then
344343 -- auto-detect
345- out_format = quarto ~= nil and ' quarto-format' or ' pandoc-format'
344+ Options . format = quarto ~= nil and ' quarto-format' or ' pandoc-format'
346345 elseif type (cfg ) == ' string' then
347346 -- alerts-normalize: pandoc-format
348- out_format = cfg
347+ Options . format = cfg
349348 else
350349 -- alerts-normalize:
351350 -- out-format: pandoc-format
352351 -- custom-types:
353352 -- - spoiler
354353 -- - info: note
355354 local fmt = cfg [' out-format' ]
356- out_format = fmt and pandoc .utils .stringify (fmt )
355+ Options . format = fmt and pandoc .utils .stringify (fmt )
357356 or (quarto ~= nil and ' quarto-format' or ' pandoc-format' )
358357 local types = cfg [' custom-types' ]
359358 if types then
360359 for _ , v in ipairs (types ) do
361360 if type (v ) == ' table' then
362361 -- mapping form: { info: note }
363362 for src , dst in pairs (v ) do
364- CalloutTypes [src ] = true
365- TypeMap [src ] = pandoc .utils .stringify (dst )
363+ Options . types [src ] = true
364+ Options . type_map [src ] = pandoc .utils .stringify (dst )
366365 end
367366 else
368367 -- plain string: spoiler
369- CalloutTypes [pandoc .utils .stringify (v )] = true
368+ Options . types [pandoc .utils .stringify (v )] = true
370369 end
371370 end
372371 end
373372 end
374373
375- write_rules = FormatDefaults [out_format ] or FormatDefaults [' pandoc-format' ]
374+ Options . rules = FormatDefaults [Options . format ] or FormatDefaults [' pandoc-format' ]
376375end
377376
378377return {
0 commit comments