Skip to content

Commit 21980e4

Browse files
authored
Merge pull request #9904 from quarto-dev/bugfix/9903
Shortcodes - resolve inside element attributes
2 parents 13d3126 + 4871572 commit 21980e4

File tree

6 files changed

+76
-3
lines changed

6 files changed

+76
-3
lines changed

news/changelog-1.5.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ All changes included in 1.5:
126126
- ([#9664](https://github.com/quarto-dev/quarto-cli/pull/9664)): Add `placeholder` shortcode to produce placeholder images.
127127
- ([#9665](https://github.com/quarto-dev/quarto-cli/issues/9665)): Fix issue with key-value arguments of shortcode handlers in code contexts.
128128
- ([#9793](https://github.com/quarto-dev/quarto-cli/issues/9793)): `embed` shortcode now correctly retrieve svg image from embdedded cell.
129+
- ([#9903](https://github.com/quarto-dev/quarto-cli/issues/9903)): Allow shortcode resolution inside element attributes (currently headers, divs, spans, images, links). Currently, this requires attributes to be specified with single quotes, see issue for details.
129130

130131
## Lightbox Images
131132

src/core/markdown-pipeline.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ export function processMarkdownRenderEnvelope(
9898
const markdownEnvelopeWriter = (envelopeId: string) => {
9999
const renderList: string[] = [];
100100
const hiddenSpan = (id: string, contents: string) => {
101-
return `[${contents}]{.hidden render-id="${id}"}`;
101+
return `[${contents}]{.hidden .quarto-markdown-envelope-contents render-id="${id}"}`;
102102
};
103103

104104
const hiddenDiv = (id: string, contents: string) => {
105-
return `\n:::{.hidden render-id="${id}"}\n${contents}\n:::\n`;
105+
return `\n:::{.hidden .quarto-markdown-envelope-contents render-id="${id}"}\n${contents}\n:::\n`;
106106
};
107107

108108
return {

src/resources/filters/customnodes/shortcodes.lua

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,15 @@ function shortcodes_filter()
265265
return el
266266
end
267267

268+
local attr_handler = function(el)
269+
for k,v in pairs(el.attributes) do
270+
if type(v) == "string" then
271+
el.attributes[k] = shortcode_lpeg.wrap_lpeg_match(code_shortcode, v)
272+
end
273+
end
274+
return el
275+
end
276+
268277
filter = {
269278
Pandoc = function(doc)
270279
-- first walk them in block context
@@ -274,22 +283,42 @@ function shortcodes_filter()
274283
Code = code_handler,
275284
RawBlock = code_handler,
276285
CodeBlock = code_handler,
286+
Header = attr_handler,
287+
Div = function(el)
288+
if el.classes:includes("quarto-markdown-envelope-contents") then
289+
return nil
290+
end
291+
if el.classes:includes("quarto-shortcode__-escaped") then
292+
return pandoc.Plain(pandoc.Str(el.attributes["data-value"]))
293+
else
294+
el = attr_handler(el)
295+
return el
296+
end
297+
end,
277298
})
278299

279300
doc = _quarto.ast.walk(doc, {
280301
Shortcode = inline_handler,
281302
RawInline = code_handler,
282303
Image = function(el)
304+
el = attr_handler(el)
283305
el.src = shortcode_lpeg.wrap_lpeg_match(code_shortcode, el.src)
284306
return el
285307
end,
286308
Link = function(el)
309+
el = attr_handler(el)
287310
el.target = shortcode_lpeg.wrap_lpeg_match(code_shortcode, el.target)
288311
return el
289312
end,
290313
Span = function(el)
314+
if el.classes:includes("quarto-markdown-envelope-contents") then
315+
return nil
316+
end
291317
if el.classes:includes("quarto-shortcode__-escaped") then
292318
return pandoc.Str(el.attributes["data-value"])
319+
else
320+
el = attr_handler(el)
321+
return el
293322
end
294323
end,
295324
})

src/resources/pandoc/datadir/lpegshortcode.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ md_shortcode = make_shortcode_parser({
194194
keyvalue = md_keyvalue_param,
195195
shortcode = md_shortcode,
196196

197-
ignore_pattern = lpeg.P("{.hidden render-id=\"") * (lpeg.P(1) - lpeg.P("\"}"))^1 * lpeg.P("\"}")
197+
ignore_pattern = lpeg.P("{.hidden .quarto-markdown-envelope-contents render-id=\"") * (lpeg.P(1) - lpeg.P("\"}"))^1 * lpeg.P("\"}")
198198
})
199199

200200
local escaped_string = into_string(

src/resources/pandoc/datadir/readqmd.lua

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ local function readqmd(txt, opts)
154154
return c
155155
end
156156

157+
local function filter_attrs(el)
158+
for k,v in pairs(el.attributes) do
159+
if type(v) == "string" and v:match("data%-is%-shortcode%=%\"1%\"") then
160+
local new_v = md_shortcode.unparse_md_shortcode(v)
161+
el.attributes[k] = new_v
162+
end
163+
end
164+
return el
165+
end
166+
157167
local doc = pandoc.read(txt or "", flavor, opts):walk {
158168
CodeBlock = function (cb)
159169
cb.classes = cb.classes:map(restore_invalid_tags)
@@ -166,13 +176,18 @@ local function readqmd(txt, opts)
166176
Code = unshortcode_text,
167177
RawInline = unshortcode_text,
168178
RawBlock = unshortcode_text,
179+
Header = filter_attrs,
180+
Span = filter_attrs,
181+
Div = filter_attrs,
169182
Link = function (l)
183+
l = filter_attrs(l)
170184
if l.target:match("data%-is%-shortcode%=%%221%%22") then
171185
l.target = md_shortcode.unparse_md_shortcode(urldecode(l.target))
172186
return l
173187
end
174188
end,
175189
Image = function (i)
190+
i = filter_attrs(i)
176191
if i.src:match("data%-is%-shortcode%=%%221%%22") then
177192
i.src = md_shortcode.unparse_md_shortcode(urldecode(i.src))
178193
return i
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
format: html
3+
htmllink: "https://www.example.com"
4+
_quarto:
5+
tests:
6+
html:
7+
ensureHtmlElements:
8+
-
9+
- "h2[data-background-iframe='https://www.example.com']"
10+
- "a[data-attr='https://www.example.com']"
11+
- "span#foo[data-attr='https://www.example.com']"
12+
- "div#div-1[data-attr='https://www.example.com']"
13+
- []
14+
---
15+
16+
## Slide Title {background-iframe='{{< meta htmllink >}}'}
17+
18+
[A link]({{< meta htmllink >}}){attr='{{< meta htmllink >}}'}.
19+
20+
![An image]({{< placeholder >}}){attr='{{< meta htmllink >}}'}
21+
22+
[A span]{#foo attr='{{< meta htmllink >}}'}.
23+
24+
::: {#div-1 attr='{{< meta htmllink >}}'}
25+
26+
A div.
27+
28+
:::

0 commit comments

Comments
 (0)