Skip to content

Commit 6d1a2ac

Browse files
authored
feat: update get_brand_color function support light/dark mode (#28)
1 parent 05f9575 commit 6d1a2ac

5 files changed

Lines changed: 175 additions & 41 deletions

File tree

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ You can also use the shorter syntax ([v1.1.1](../../releases/tag/1.1.1)):
3535

3636
Using colours from `_brand.yml` ([v1.1.0](../../releases/tag/1.1.0)):
3737

38-
```markdown
38+
```yaml
3939
color:
4040
palette:
4141
red: "#b22222"
@@ -46,6 +46,39 @@ color:
4646
[Red]{colour="brand-color.red" bg-colour="brand-color.primary"}
4747
```
4848

49+
Using colours from light/dark themes with Quarto CLI >=1.7.28 ([v1.2.0](../../releases/tag/1.2.0)):
50+
51+
- From document front matter:
52+
53+
```yaml
54+
brand:
55+
light:
56+
color:
57+
palette:
58+
fg: "#ffffff"
59+
bg: "#b22222"
60+
dark:
61+
color:
62+
palette:
63+
fg: "#b22222"
64+
bg: "#ffffff"
65+
```
66+
67+
- From `_quarto.yml` and `_brand.yml` file
68+
69+
```yaml
70+
brand:
71+
dark: _brand.yml
72+
```
73+
74+
```markdown
75+
[Light: White/Red | Dark: Red/White]{colour="brand-color.fg" bg-colour="brand-color.bg"}
76+
```
77+
78+
> [!NOTE]
79+
> Only the `html` support light/dark mode switching.
80+
> The other formats will use the light mode colours if available or the dark mode colours otherwise.
81+
4982
## Limitations
5083

5184
LaTeX `\colorbox` command does not support wrapping/line breaks in the text to be highlighted.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
title: Highlight Text
22
author: Mickaël Canouil
3-
version: 1.1.3
4-
quarto-required: ">=1.6.37"
3+
version: 1.2.0
4+
quarto-required: ">=1.7.28"
55
contributes:
66
filters:
77
- highlight-text.lua

_extensions/highlight-text/highlight-text.lua

Lines changed: 112 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@
2222
# SOFTWARE.
2323
]]
2424

25-
local function get_brand_color(colour)
25+
--- Gets a colour value from brand theme or formats it for later use
26+
--- @param theme string The brand theme to use (light/dark)
27+
--- @param colour string The colour value or brand colour reference
28+
--- @return string The processed colour value
29+
local function get_brand_colour(theme, colour)
2630
local brand = require('modules/brand/brand')
2731
if colour and colour:match("^brand%-color.") then
28-
colour = brand.get_color(colour:gsub("^brand%-color%.", ""))
32+
colour = brand.get_color(theme, colour:gsub("^brand%-color%.", ""))
2933
else
3034
if FORMAT:match 'typst' and colour ~= nil then
3135
colour = 'rgb("' .. colour .. '")'
@@ -34,28 +38,66 @@ local function get_brand_color(colour)
3438
return colour
3539
end
3640

37-
local function highlight_html(span, colour, bg_colour)
38-
if span.attributes['style'] == nil then
39-
span.attributes['style'] = ''
40-
elseif span.attributes['style']:sub(-1) ~= ";" then
41-
span.attributes['style'] = span.attributes['style'] .. ";"
42-
end
41+
--- Applies text and background colour styling for HTML-based outputs
42+
--- @param span table The span element to modify
43+
--- @param settings table The highlight settings containing colour and background colour
44+
--- @return table The modified span with HTML styling
45+
local function highlight_html(span, settings)
46+
local result = {}
47+
local theme_keys = {}
4348

44-
if colour ~= nil then
45-
span.attributes['colour'] = nil
46-
span.attributes['color'] = nil
47-
span.attributes['style'] = span.attributes['style'] .. 'color: ' .. colour .. ';'
49+
for key, _ in pairs(settings) do
50+
table.insert(theme_keys, key)
4851
end
4952

50-
if bg_colour ~= nil then
51-
span.attributes['bg-colour'] = nil
52-
span.attributes['bg-color'] = nil
53-
span.attributes['style'] = span.attributes['style'] .. 'border-radius: 0.2rem; padding: 0 0.2rem 0 0.2rem;' .. 'background-color: ' .. bg_colour .. ';'
53+
for _, theme in ipairs(theme_keys) do
54+
local theme_span = pandoc.Span(span.content)
55+
local colour = settings[theme].colour
56+
local bg_colour = settings[theme].bg_colour
57+
58+
for k, v in pairs(span.attributes) do
59+
theme_span.attributes[k] = v
60+
end
61+
62+
if theme_span.attributes['style'] == nil then
63+
theme_span.attributes['style'] = ''
64+
elseif theme_span.attributes['style']:sub(-1) ~= ";" then
65+
theme_span.attributes['style'] = theme_span.attributes['style'] .. ";"
66+
end
67+
68+
theme_span.classes = theme_span.classes or {}
69+
table.insert(theme_span.classes, "quarto-highlight-text-" .. theme)
70+
71+
if colour ~= nil then
72+
theme_span.attributes['colour'] = nil
73+
theme_span.attributes['color'] = nil
74+
theme_span.attributes['style'] = theme_span.attributes['style'] .. 'color: ' .. colour .. ';'
75+
end
76+
77+
if bg_colour ~= nil then
78+
theme_span.attributes['bg-colour'] = nil
79+
theme_span.attributes['bg-color'] = nil
80+
theme_span.attributes['style'] = theme_span.attributes['style'] ..
81+
'border-radius: 0.2rem; padding: 0 0.2rem 0 0.2rem;' .. 'background-color: ' .. bg_colour .. ';'
82+
end
83+
84+
table.insert(result, theme_span)
5485
end
5586

56-
return span
87+
-- Return a single span or a list of spans
88+
if #result == 1 then
89+
return result[1]
90+
else
91+
return result
92+
end
5793
end
5894

95+
--- Applies text and background colour styling for LaTeX-based outputs
96+
--- @param span table The span element to modify
97+
--- @param colour string The text colour to apply
98+
--- @param bg_colour string The background colour to apply
99+
--- @param par boolean Whether to wrap in a paragraph box
100+
--- @return table The span content with LaTeX markup
59101
local function highlight_latex(span, colour, bg_colour, par)
60102
if colour == nil then
61103
colour_open = ''
@@ -86,6 +128,11 @@ local function highlight_latex(span, colour, bg_colour, par)
86128
return span.content
87129
end
88130

131+
--- Applies text and background colour styling for Word documents
132+
--- @param span table The span element to modify
133+
--- @param colour string The text colour to apply
134+
--- @param bg_colour string The background colour to apply
135+
--- @return table The span content with OpenXML markup for Word
89136
local function highlight_openxml_docx(span, colour, bg_colour)
90137
local spec = '<w:r><w:rPr>'
91138
if bg_colour ~= nil then
@@ -102,6 +149,11 @@ local function highlight_openxml_docx(span, colour, bg_colour)
102149
return span.content
103150
end
104151

152+
--- Applies text and background colour styling for PowerPoint presentations
153+
--- @param span table The span element to modify
154+
--- @param colour string The text colour to apply
155+
--- @param bg_colour string The background colour to apply
156+
--- @return table Raw inline containing OpenXML markup for PowerPoint
105157
local function highlight_openxml_pptx(span, colour, bg_colour)
106158
local spec = '<a:r><a:rPr dirty="0">'
107159
if colour ~= nil then
@@ -123,6 +175,11 @@ local function highlight_openxml_pptx(span, colour, bg_colour)
123175
return pandoc.RawInline('openxml', spec .. span_content_string .. '</a:t></a:r>')
124176
end
125177

178+
--- Applies text and background colour styling for Typst output
179+
--- @param span table The span element to modify
180+
--- @param colour string The text colour to apply
181+
--- @param bg_colour string The background colour to apply
182+
--- @return table The span content with Typst markup
126183
local function highlight_typst(span, colour, bg_colour)
127184
if colour == nil then
128185
colour_open = ''
@@ -152,7 +209,11 @@ local function highlight_typst(span, colour, bg_colour)
152209
return span.content
153210
end
154211

155-
function Span(span)
212+
--- Main filter function that processes span elements and applies highlighting
213+
--- based on the output format and specified attributes
214+
--- @param span table The span element from the document
215+
--- @return table The modified span or span content with appropriate styling
216+
local function highlight(span)
156217
local colour = span.attributes['fg']
157218
if colour == nil then
158219
colour = span.attributes['colour']
@@ -169,10 +230,31 @@ function Span(span)
169230
bg_colour = span.attributes['bg-color']
170231
end
171232

172-
if colour == nil and bg_colour == nil then return span end
233+
local highlight_settings = {}
173234

174-
colour = get_brand_color(colour)
175-
bg_colour = get_brand_color(bg_colour)
235+
local modes = {"light", "dark"}
236+
for _, mode in ipairs(modes) do
237+
if quarto.brand.has_mode(mode) then
238+
highlight_settings[mode] = {
239+
colour = get_brand_colour(mode, colour),
240+
bg_colour = get_brand_colour(mode, bg_colour)
241+
}
242+
end
243+
end
244+
245+
if highlight_settings.light == nil and highlight_settings.dark == nil then
246+
return span
247+
end
248+
249+
if highlight_settings.light == nil then
250+
highlight_settings.light = highlight_settings.dark
251+
end
252+
253+
colour = highlight_settings.light.colour
254+
bg_colour = highlight_settings.light.bg_colour
255+
256+
quarto.log.output(highlight_settings)
257+
if colour == nil and bg_colour == nil then return span end
176258

177259
if span.attributes['par'] == nil then
178260
par = false
@@ -182,7 +264,11 @@ function Span(span)
182264
end
183265

184266
if FORMAT:match 'html' or FORMAT:match 'revealjs' then
185-
return highlight_html(span, colour, bg_colour)
267+
quarto.doc.add_html_dependency({
268+
name = 'badge',
269+
stylesheets = {"light-dark.css"}
270+
})
271+
return highlight_html(span, highlight_settings)
186272
elseif FORMAT:match 'latex' or FORMAT:match 'beamer' then
187273
return highlight_latex(span, colour, bg_colour, par)
188274
elseif FORMAT:match 'docx' then
@@ -195,3 +281,7 @@ function Span(span)
195281
return span
196282
end
197283
end
284+
285+
return {
286+
{ Span = highlight },
287+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
body.quarto-light .quarto-highlight-text-light,
2+
body.quarto-dark .quarto-highlight-text-dark {
3+
display: inline;
4+
}
5+
6+
body.quarto-light .quarto-highlight-text-dark,
7+
body.quarto-dark .quarto-highlight-text-light {
8+
display: none;
9+
}

example.qmd

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,20 @@ execute:
3131
filters:
3232
- highlight-text
3333
brand:
34-
color:
35-
palette:
36-
blue: "#0000ff"
37-
red: "#b22222"
38-
primary: "#ffffff"
34+
light:
35+
color:
36+
palette:
37+
fg: "#ffffff"
38+
bg: "#b22222"
39+
foreground: "#333333"
40+
background: "#fafafa"
41+
dark:
42+
color:
43+
palette:
44+
fg: "#b22222"
45+
bg: "#ffffff"
46+
foreground: "#fafafa"
47+
background: "#333333"
3948
---
4049

4150
This is a Quarto extension that allows to highlight text in a document for various format: HTML, LaTeX, Typst, and Docx.
@@ -127,20 +136,13 @@ Then you can use the span syntax markup to highlight text in your document.
127136
## `_brand.yml`
128137

129138
```markdown
130-
[White text, Red background]{
131-
colour="brand-color.primary" bg-colour="brand-color.red"
132-
}
133-
```
134-
135-
[White text, Red background]{colour="brand-color.primary" bg-colour="brand-color.red"}
136-
137-
```markdown
138-
[White text, Blue background]{
139-
color="brand-color.primary" bg-color="brand-color.blue"
139+
[Light: White/Red | Dark: Red/White]{
140+
colour="brand-color.fg"
141+
bg-colour="brand-color.bg"
140142
}
141143
```
142144

143-
[White text, Blue background]{color="brand-color.primary" bg-color="brand-color.blue"}
145+
[Light: White/Red | Dark: Red/White]{colour="brand-color.fg" bg-colour="brand-color.bg"}
144146

145147
## Limitations
146148

0 commit comments

Comments
 (0)