Skip to content

Commit 72a4cbe

Browse files
committed
lua - move html bootstrap renderer to module
1 parent 7d24d71 commit 72a4cbe

File tree

2 files changed

+144
-143
lines changed

2 files changed

+144
-143
lines changed

src/resources/filters/customnodes/callout.lua

Lines changed: 1 addition & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
-- Copyright (C) 2021-2022 Posit Software, PBC
33

44
function _callout_main()
5-
local calloutidx = 1
6-
75
local function calloutType(div)
86
for _, class in ipairs(div.attr.classes) do
97
if _quarto.modules.classpredicates.isCallout(class) then
@@ -33,146 +31,6 @@ function _callout_main()
3331
end
3432
end
3533

36-
-- an HTML callout div
37-
local function calloutDiv(node)
38-
node = _quarto.modules.callouts.decorate_callout_title_with_crossref(node)
39-
40-
-- the first heading is the title
41-
local div = pandoc.Div({})
42-
local c = quarto.utils.as_blocks(node.content)
43-
if pandoc.utils.type(c) == "Blocks" then
44-
div.content:extend(c)
45-
else
46-
div.content:insert(c)
47-
end
48-
local title = quarto.utils.as_inlines(node.title)
49-
local callout_type = node.type
50-
local calloutAppearance = node.appearance
51-
local icon = node.icon
52-
local collapse = node.collapse
53-
local found = false
54-
55-
_quarto.ast.walk(title, {
56-
RawInline = function(_)
57-
found = true
58-
end,
59-
RawBlock = function(_)
60-
found = true
61-
end
62-
})
63-
64-
if calloutAppearance == _quarto.modules.constants.kCalloutAppearanceDefault and pandoc.utils.stringify(title) == "" and not found then
65-
title = quarto.utils.as_inlines(pandoc.Plain(_quarto.modules.callouts.displayName(node.type)))
66-
end
67-
68-
-- Make an outer card div and transfer classes and id
69-
local calloutDiv = pandoc.Div({})
70-
calloutDiv.attr = node.attr:clone()
71-
72-
local identifier = node.attr.identifier
73-
if identifier ~= "" then
74-
node.attr.identifier = ""
75-
calloutDiv.attr.identifier = identifier
76-
-- inject an anchor so callouts can be linked to
77-
-- local attr = pandoc.Attr(identifier, {}, {})
78-
-- local anchor = pandoc.Link({}, "", "", attr)
79-
-- title:insert(1, anchor)
80-
end
81-
82-
div.attr.classes = pandoc.List()
83-
div.attr.classes:insert("callout-body-container")
84-
85-
-- add card attribute
86-
calloutDiv.attr.classes:insert("callout")
87-
calloutDiv.attr.classes:insert("callout-style-" .. calloutAppearance)
88-
if node.type ~= nil then
89-
calloutDiv.attr.classes:insert("callout-" .. node.type)
90-
end
91-
92-
-- the image placeholder
93-
local noicon = ""
94-
95-
-- Check to see whether this is a recognized type
96-
if icon == false or not _quarto.modules.callouts.isBuiltInType(callout_type) or type == nil then
97-
noicon = " no-icon"
98-
calloutDiv.attr.classes:insert("no-icon")
99-
end
100-
local imgPlaceholder = pandoc.Plain({pandoc.RawInline("html", "<i class='callout-icon" .. noicon .. "'></i>")});
101-
local imgDiv = pandoc.Div({imgPlaceholder}, pandoc.Attr("", {"callout-icon-container"}));
102-
103-
-- show a titled callout
104-
if title ~= nil and (pandoc.utils.type(title) == "string" or next(title) ~= nil) then
105-
106-
-- mark the callout as being titleed
107-
calloutDiv.attr.classes:insert("callout-titled")
108-
109-
-- create a unique id for the callout
110-
local calloutid = "callout-" .. calloutidx
111-
calloutidx = calloutidx + 1
112-
113-
-- create the header to contain the title
114-
-- title should expand to fill its space
115-
local titleDiv = pandoc.Div(pandoc.Plain(title), pandoc.Attr("", {"callout-title-container", "flex-fill"}))
116-
local headerDiv = pandoc.Div({imgDiv, titleDiv}, pandoc.Attr("", {"callout-header", "d-flex", "align-content-center"}))
117-
local bodyDiv = div
118-
bodyDiv.attr.classes:insert("callout-body")
119-
120-
if collapse ~= nil then
121-
122-
-- collapse default value
123-
local expandedAttrVal = "true"
124-
if collapse == "true" or collapse == true then
125-
expandedAttrVal = "false"
126-
end
127-
128-
-- create the collapse button
129-
local btnClasses = "callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"
130-
local btnIcon = "<i class='callout-toggle'></i>"
131-
local toggleButton = pandoc.RawInline("html", "<div class='" .. btnClasses .. "'>" .. btnIcon .. "</div>")
132-
headerDiv.content:insert(pandoc.Plain(toggleButton));
133-
134-
-- configure the header div for collapse
135-
local bsTargetClz = calloutid .. "-contents"
136-
headerDiv.attr.attributes["bs-toggle"] = "collapse"
137-
headerDiv.attr.attributes["bs-target"] = "." .. bsTargetClz
138-
headerDiv.attr.attributes["aria-controls"] = calloutid
139-
headerDiv.attr.attributes["aria-expanded"] = expandedAttrVal
140-
headerDiv.attr.attributes["aria-label"] = 'Toggle callout'
141-
142-
-- configure the body div for collapse
143-
local collapseDiv = pandoc.Div({})
144-
collapseDiv.attr.identifier = calloutid
145-
collapseDiv.attr.classes:insert(bsTargetClz)
146-
collapseDiv.attr.classes:insert("callout-collapse")
147-
collapseDiv.attr.classes:insert("collapse")
148-
if expandedAttrVal == "true" then
149-
collapseDiv.attr.classes:insert("show")
150-
end
151-
152-
-- add the current body to the collapse div and use the collapse div instead
153-
collapseDiv.content:insert(bodyDiv)
154-
bodyDiv = collapseDiv
155-
end
156-
157-
-- add the header and body to the div
158-
calloutDiv.content:insert(headerDiv)
159-
calloutDiv.content:insert(bodyDiv)
160-
else
161-
-- show an untitleed callout
162-
163-
-- create a card body
164-
local containerDiv = pandoc.Div({imgDiv, div}, pandoc.Attr("", {"callout-body"}))
165-
containerDiv.attr.classes:insert("d-flex")
166-
167-
-- add the container to the callout card
168-
calloutDiv.content:insert(containerDiv)
169-
end
170-
171-
return calloutDiv
172-
end
173-
174-
175-
17634
_quarto.ast.add_handler({
17735
-- use either string or array of strings
17836
class_name = { "callout", "callout-note", "callout-warning", "callout-important", "callout-caution", "callout-tip" },
@@ -276,7 +134,7 @@ function _callout_main()
276134

277135
_quarto.ast.add_renderer("Callout", function(_)
278136
return _quarto.format.isHtmlOutput() and hasBootstrap()
279-
end, calloutDiv)
137+
end, _quarto.modules.callouts.render_to_bootstrap_div)
280138

281139
_quarto.ast.add_renderer("Callout", function(_)
282140
return _quarto.format.isEpubOutput() or _quarto.format.isRevealJsOutput()

src/resources/filters/modules/callouts.lua

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,153 @@ local function displayName(type)
181181
return param("callout-" .. type .. "-title", defaultName)
182182
end
183183

184+
local calloutidx = 1
185+
186+
-- an HTML callout div
187+
local function calloutDiv(node)
188+
node = decorate_callout_title_with_crossref(node)
189+
190+
-- the first heading is the title
191+
local div = pandoc.Div({})
192+
local c = quarto.utils.as_blocks(node.content)
193+
if pandoc.utils.type(c) == "Blocks" then
194+
div.content:extend(c)
195+
else
196+
div.content:insert(c)
197+
end
198+
local title = quarto.utils.as_inlines(node.title)
199+
local callout_type = node.type
200+
local calloutAppearance = node.appearance
201+
local icon = node.icon
202+
local collapse = node.collapse
203+
local found = false
204+
205+
_quarto.ast.walk(title, {
206+
RawInline = function(_)
207+
found = true
208+
end,
209+
RawBlock = function(_)
210+
found = true
211+
end
212+
})
213+
214+
if calloutAppearance == _quarto.modules.constants.kCalloutAppearanceDefault and pandoc.utils.stringify(title) == "" and not found then
215+
title = quarto.utils.as_inlines(pandoc.Plain(displayName(node.type)))
216+
end
217+
218+
-- Make an outer card div and transfer classes and id
219+
local calloutDiv = pandoc.Div({})
220+
calloutDiv.attr = node.attr:clone()
221+
222+
local identifier = node.attr.identifier
223+
if identifier ~= "" then
224+
node.attr.identifier = ""
225+
calloutDiv.attr.identifier = identifier
226+
-- inject an anchor so callouts can be linked to
227+
-- local attr = pandoc.Attr(identifier, {}, {})
228+
-- local anchor = pandoc.Link({}, "", "", attr)
229+
-- title:insert(1, anchor)
230+
end
231+
232+
div.attr.classes = pandoc.List()
233+
div.attr.classes:insert("callout-body-container")
234+
235+
-- add card attribute
236+
calloutDiv.attr.classes:insert("callout")
237+
calloutDiv.attr.classes:insert("callout-style-" .. calloutAppearance)
238+
if node.type ~= nil then
239+
calloutDiv.attr.classes:insert("callout-" .. node.type)
240+
end
241+
242+
-- the image placeholder
243+
local noicon = ""
244+
245+
-- Check to see whether this is a recognized type
246+
if icon == false or not isBuiltInType(callout_type) or type == nil then
247+
noicon = " no-icon"
248+
calloutDiv.attr.classes:insert("no-icon")
249+
end
250+
local imgPlaceholder = pandoc.Plain({pandoc.RawInline("html", "<i class='callout-icon" .. noicon .. "'></i>")});
251+
local imgDiv = pandoc.Div({imgPlaceholder}, pandoc.Attr("", {"callout-icon-container"}));
252+
253+
-- show a titled callout
254+
if title ~= nil and (pandoc.utils.type(title) == "string" or next(title) ~= nil) then
255+
256+
-- mark the callout as being titleed
257+
calloutDiv.attr.classes:insert("callout-titled")
258+
259+
-- create a unique id for the callout
260+
local calloutid = "callout-" .. calloutidx
261+
calloutidx = calloutidx + 1
262+
263+
-- create the header to contain the title
264+
-- title should expand to fill its space
265+
local titleDiv = pandoc.Div(pandoc.Plain(title), pandoc.Attr("", {"callout-title-container", "flex-fill"}))
266+
local headerDiv = pandoc.Div({imgDiv, titleDiv}, pandoc.Attr("", {"callout-header", "d-flex", "align-content-center"}))
267+
local bodyDiv = div
268+
bodyDiv.attr.classes:insert("callout-body")
269+
270+
if collapse ~= nil then
271+
272+
-- collapse default value
273+
local expandedAttrVal = "true"
274+
if collapse == "true" or collapse == true then
275+
expandedAttrVal = "false"
276+
end
277+
278+
-- create the collapse button
279+
local btnClasses = "callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"
280+
local btnIcon = "<i class='callout-toggle'></i>"
281+
local toggleButton = pandoc.RawInline("html", "<div class='" .. btnClasses .. "'>" .. btnIcon .. "</div>")
282+
headerDiv.content:insert(pandoc.Plain(toggleButton));
283+
284+
-- configure the header div for collapse
285+
local bsTargetClz = calloutid .. "-contents"
286+
headerDiv.attr.attributes["bs-toggle"] = "collapse"
287+
headerDiv.attr.attributes["bs-target"] = "." .. bsTargetClz
288+
headerDiv.attr.attributes["aria-controls"] = calloutid
289+
headerDiv.attr.attributes["aria-expanded"] = expandedAttrVal
290+
headerDiv.attr.attributes["aria-label"] = 'Toggle callout'
291+
292+
-- configure the body div for collapse
293+
local collapseDiv = pandoc.Div({})
294+
collapseDiv.attr.identifier = calloutid
295+
collapseDiv.attr.classes:insert(bsTargetClz)
296+
collapseDiv.attr.classes:insert("callout-collapse")
297+
collapseDiv.attr.classes:insert("collapse")
298+
if expandedAttrVal == "true" then
299+
collapseDiv.attr.classes:insert("show")
300+
end
301+
302+
-- add the current body to the collapse div and use the collapse div instead
303+
collapseDiv.content:insert(bodyDiv)
304+
bodyDiv = collapseDiv
305+
end
306+
307+
-- add the header and body to the div
308+
calloutDiv.content:insert(headerDiv)
309+
calloutDiv.content:insert(bodyDiv)
310+
else
311+
-- show an untitleed callout
312+
313+
-- create a card body
314+
local containerDiv = pandoc.Div({imgDiv, div}, pandoc.Attr("", {"callout-body"}))
315+
containerDiv.attr.classes:insert("d-flex")
316+
317+
-- add the container to the callout card
318+
calloutDiv.content:insert(containerDiv)
319+
end
320+
321+
return calloutDiv
322+
end
323+
324+
184325
return {
185326
decorate_callout_title_with_crossref = decorate_callout_title_with_crossref,
186327
callout_attrs = callout_attrs,
187328

329+
render_to_bootstrap_div = calloutDiv,
330+
188331
-- TODO capitalization
189332
resolveCalloutContents = resolveCalloutContents,
190333
docxCalloutImage = docxCalloutImage,

0 commit comments

Comments
 (0)