Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/core/brand/brand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
BrandColorLightDark,
BrandFont,
BrandLogoExplicitResource,
BrandLogoResource,
BrandLogoSingle,
BrandLogoUnified,
BrandNamedLogo,
Expand Down Expand Up @@ -143,11 +144,7 @@ export class Brand {
}
}
for (const [key, value] of Object.entries(data.logo?.images ?? {})) {
if (typeof value === "string") {
logo.images[key] = { path: value };
} else {
logo.images[key] = value;
}
logo.images[key] = this.resolvePath(value);
}

return {
Expand Down Expand Up @@ -240,11 +237,7 @@ export class Brand {
return fonts ?? [];
}

getLogoResource(name: string): BrandLogoExplicitResource {
const entry = this.data.logo?.images?.[name];
if (!entry) {
return { path: name };
}
resolvePath(entry: BrandLogoResource) {
const pathPrefix = relative(this.projectDir, this.brandDir);
if (typeof entry === "string") {
return { path: join(pathPrefix, entry) };
Expand All @@ -255,6 +248,13 @@ export class Brand {
};
}

getLogoResource(name: string): BrandLogoExplicitResource {
const entry = this.data.logo?.images?.[name];
if (!entry) {
return { path: name };
}
return this.resolvePath(entry);
}
getLogo(name: BrandNamedLogo): BrandLogoExplicitResource | undefined {
const entry = this.data.logo?.[name];
if (!entry) {
Expand Down
1 change: 1 addition & 0 deletions src/format/typst/format-typst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export function typstFormat(): Format {
partials: [
"definitions.typ",
"typst-template.typ",
"logo.typ",
"typst-show.typ",
"notes.typ",
"biblio.typ",
Expand Down
198 changes: 113 additions & 85 deletions src/resources/filters/quarto-post/typst-brand-yaml.lua
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,33 @@ function render_typst_brand_yaml()
local decl = '#let brand-color-background = ' .. to_typst_dict_indent(themebk)
quarto.doc.include_text('in-header', decl)
end
if brand.processedData.logo and next(brand.processedData.logo) then
local logo = brand.processedData.logo
if logo.images then
local declImage = {}
for name, image in pairs(logo.images) do
declImage[name] = {
path = quote_string(image.path):gsub('\\', '\\\\'),
alt = quote_string(image.alt),
}
end
if next(declImage) then
quarto.doc.include_text('in-header', '#let brand-logo-images = ' .. to_typst_dict_indent(declImage))
end
end
local declLogo = {}
for _, size in pairs({'small', 'medium', 'large'}) do
if logo[size] then
declLogo[size] = {
path = quote_string(logo[size].path):gsub('\\', '\\\\'),
alt = quote_string(logo[size].alt),
}
end
end
if next(declLogo) then
quarto.doc.include_text('in-header', '#let brand-logo = ' .. to_typst_dict_indent(declLogo))
end
end
local function conditional_entry(key, value, quote_strings)
if quote_strings == null then quote_strings = true end
if not value then return '' end
Expand Down Expand Up @@ -212,102 +239,103 @@ function render_typst_brand_yaml()
', content)'
}))
end

-- logo
local logo = param('logo')
local logoOptions = {}
local foundLogo = null
if logo then
if type(logo) == 'string' then
foundLogo = _quarto.modules.brand.get_logo(brandMode, logo) or {path=logo}
elseif type(logo) == 'table' then
for k, v in pairs(logo) do
logoOptions[k] = v
end
if logo.path then
foundLogo = _quarto.modules.brand.get_logo(brandMode, logo.path) or {path=logo}
end
end
end,
Meta = function(meta)
local brand = param('brand')
local brandMode = param('brand-mode') or 'light'
brand = brand and brand[brandMode]
-- it can contain the path but we want to store an object here
if not meta.brand or pandoc.utils.type(meta.brand) == 'Inlines' then
meta.brand = {}
end
-- logo
local logo = param('logo')
local logoOptions = {}
local foundLogo = null
if logo then
if type(logo) == 'string' then
foundLogo = _quarto.modules.brand.get_logo(brandMode, logo) or {path=logo}
elseif type(logo) == 'table' then
for k, v in pairs(logo) do
logoOptions[k] = v
end
if logo.path then
foundLogo = _quarto.modules.brand.get_logo(brandMode, logo.path) or {path=logo}
end
end
if not foundLogo and brand.processedData.logo then
local tries = {'large', 'small', 'medium'} -- low to high priority
foundLogo = _quarto.modules.brand.get_logo(brandMode, 'medium')
or _quarto.modules.brand.get_logo(brandMode, 'small')
or _quarto.modules.brand.get_logo(brandMode, 'large')
end
if foundLogo then
logoOptions.path = foundLogo.path
logoOptions.alt = foundLogo.alt
end
if not foundLogo and brand and brand.processedData and brand.processedData.logo then
foundLogo = _quarto.modules.brand.get_logo(brandMode, 'medium')
or _quarto.modules.brand.get_logo(brandMode, 'small')
or _quarto.modules.brand.get_logo(brandMode, 'large')
end
if foundLogo then
logoOptions.path = foundLogo.path
logoOptions.alt = foundLogo.alt

local pads = {}
for k, v in _quarto.utils.table.sortedPairs(logoOptions) do
if k == 'padding' then
local widths = {}
_quarto.modules.typst.css.parse_multiple(v, 5, function(s, start)
local width, newstart = _quarto.modules.typst.css.consume_width(s, start)
table.insert(widths, width)
return newstart
end)
local sides = _quarto.modules.typst.css.expand_side_shorthand(
widths,
'widths in padding list: ' .. v)
pads.top = sides.top
pads.right = sides.right
pads.bottom = sides.bottom
pads.left = sides.left
elseif k:find '^padding-' then
local _, ndash = k:gsub('-', '')
if ndash == 1 then
local side = k:match('^padding--(%a+)')
local padding_sides = {'left', 'top', 'right', 'bottom'}
if tcontains(padding_sides, side) then
pads[side] = _quarto.modules.typst.css.translate_length(v)
else
quarto.log.warning('invalid padding key ' .. k)
end
local pads = {}
for k, v in _quarto.utils.table.sortedPairs(logoOptions) do
if k == 'padding' then
local widths = {}
_quarto.modules.typst.css.parse_multiple(v, 5, function(s, start)
local width, newstart = _quarto.modules.typst.css.consume_width(s, start)
table.insert(widths, width)
return newstart
end)
local sides = _quarto.modules.typst.css.expand_side_shorthand(
widths,
'widths in padding list: ' .. v)
pads.top = sides.top
pads.right = sides.right
pads.bottom = sides.bottom
pads.left = sides.left
elseif k:find '^padding-' then
local _, ndash = k:gsub('-', '')
if ndash == 1 then
local side = k:match('^padding--(%a+)')
local padding_sides = {'left', 'top', 'right', 'bottom'}
if tcontains(padding_sides, side) then
pads[side] = _quarto.modules.typst.css.translate_length(v)
else
quarto.log.warning('invalid padding key ' .. k)
end
end
end
local inset = nil
if next(pads) then
if pads.top == pads.right and
pads.right == pads.bottom and
pads.bottom == pads.left
then
inset = pads.top
elseif pads.top == pads.bottom and pads.left == pads.right then
inset = _quarto.modules.typst.as_typst_dictionary({x = pads.left, y = pads.top})
else
inset = _quarto.modules.typst.as_typst_dictionary(pads)
quarto.log.warning('invalid padding key ' .. k)
end
else
inset = '0.75in'
end
logoOptions.width = _quarto.modules.typst.css.translate_length(logoOptions.width or '1.5in')
logoOptions.location = logoOptions.location and
location_to_typst_align(logoOptions.location) or 'left+top'
quarto.log.debug('logo options', logoOptions)
local altProp = logoOptions.alt and (', alt: "' .. logoOptions.alt .. '"') or ''
local imageFilename = logoOptions.path
if _quarto.modules.mediabag.should_mediabag(imageFilename) then
imageFilename = _quarto.modules.mediabag.resolved_url_cache[logoOptions.path] or _quarto.modules.mediabag.fetch_and_store_image(logoOptions.path)
imageFilename = _quarto.modules.mediabag.write_mediabag_entry(imageFilename) or imageFilename
end
local inset = nil
if next(pads) then
if pads.top == pads.right and
pads.right == pads.bottom and
pads.bottom == pads.left
then
inset = pads.top
elseif pads.top == pads.bottom and pads.left == pads.right then
inset = _quarto.modules.typst.as_typst_dictionary({x = pads.left, y = pads.top})
else
-- backslashes need to be doubled for Windows
imageFilename = string.gsub(imageFilename, '\\', '\\\\')
inset = _quarto.modules.typst.as_typst_dictionary(pads)
end
quarto.doc.include_text('in-header',
'#set page(background: align(' .. logoOptions.location .. ', box(inset: ' .. inset .. ', image("' .. imageFilename .. '", width: ' .. logoOptions.width .. altProp .. '))))')
end
end
end,
Meta = function(meta)
local brandMode = param('brand-mode') or 'light'
-- it can contain the path but we want to store an object here
if not meta.brand or pandoc.utils.type(meta.brand) == 'Inlines' then
meta.brand = {}
else
inset = '0.75in'
end
logoOptions.width = _quarto.modules.typst.css.translate_length(logoOptions.width or '1.5in')
logoOptions.inset = inset
logoOptions.location = logoOptions.location and
location_to_typst_align(logoOptions.location) or 'left+top'
quarto.log.debug('logo options', logoOptions)
local imageFilename = logoOptions.path
if _quarto.modules.mediabag.should_mediabag(imageFilename) then
imageFilename = _quarto.modules.mediabag.resolved_url_cache[logoOptions.path] or _quarto.modules.mediabag.fetch_and_store_image(logoOptions.path)
imageFilename = _quarto.modules.mediabag.write_mediabag_entry(imageFilename) or imageFilename
imageFilename = imageFilename and imageFilename:gsub('\\_', '_')
else
-- backslashes need to be doubled for Windows
imageFilename = string.gsub(imageFilename, '\\', '\\\\')
end
logoOptions.path = pandoc.RawInline('typst', imageFilename)
meta.logo = logoOptions
end
meta.brand.typography = meta.brand.typography or {}
local base = _quarto.modules.brand.get_typography(brandMode, 'base')
Expand Down
3 changes: 3 additions & 0 deletions src/resources/formats/typst/pandoc/quarto/logo.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$if(logo)$
#set page(background: align($logo.location$, box(inset: $logo.inset$, image("$logo.path$", width: $logo.width$$if(logo.alt)$, alt: "$logo.alt$"$endif$))))
$endif$
2 changes: 2 additions & 0 deletions src/resources/formats/typst/pandoc/quarto/template.typ
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ $for(header-includes)$
$header-includes$
$endfor$

$logo.typ()$

$typst-show.typ()$

$for(include-before)$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- '#let brand-logo-images = \(\s*brand-typst-with-good-padding: \(\s*path: "good-padding\.png"\s*\),\s*posit-logo-light-medium: \(\s*alt: "Posit Logo",\s*path: "posit-logo-2024.svg"\s*\)'
- '#let brand-logo = \(\s*medium: \(\s*alt: "Posit Logo",\s*path: "posit-logo-2024\.svg"\s*\)\s*\)'
- '#set page\(background: align\(left\+top, box\(inset: 0.75in, image\("posit-logo-2024.svg", width: 1.5in, alt: "Posit Logo"\)\)\)\)'
- []
---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ _quarto:
typst:
ensureTypstFileRegexMatches:
-
- '#let brand-logo-images = \(\s*large-light: \(\s*path: "brand_yaml(/|\\\\)resources(/|\\\\)quarto.png"\s*\)\s*\)'
- '#let brand-logo = \(\s*large: \(\s*path: "brand_yaml(/|\\\\)resources(/|\\\\)quarto.png"\s*\)\s*\)'
- '#set page\(background: align\(center\+top, box\(inset: 2em, image\("brand_yaml(/|\\\\)resources(/|\\\\)quarto.png", width: 225pt\)\)\)\)'
- '#image\(brand-logo-images\.large-light\.path, alt:"from brand-logo-images"\)'
- []
---

{{< lipsum 4 >}}

```{=typst}
#image(brand-logo-images.large-light.path, alt:"from brand-logo-images")
```
Loading