Hello. I have question regarding templates and images.
I made this template . The code sits in this repo .
The template is a cover page and some parts of it are made up of images. A set of images is provided with the template (located in ./template/logos
).
The package structure is:
.
├── lib.typ
├── template
│ ├── logos
│ │ ├── archi.png
│ │ ├── FNR.png
│ │ ├── FNRS-en.png
│ │ └── FNRS-fr.png
│ └── main.typ
└── typst.toml
When creating a new project from the template in the Typst app, the #show
function in main.typ
does not allow making use of images outside the template
folder.
This is the working default:
#import "@preview/lumen:0.1.0": cover
#show: cover(
logo: "template/logos/archi.png",
[...]
fund-logo: "template/logos/FNRS-fr.png",
)
But what I try to make possible is that the user can upload own images and use them in the #show
function:
#import "@preview/lumen:0.1.0": cover
#show: cover(
logo: "science.png",
[...]
fund-logo: "new-fund.png",
)
Basically I need some help to understand how assets and link to images work for templates.
Thanks !
Hi there,
I believe this PR contains the answer to your question. It’s not released yet but you can access it: packages/docs/resources.md at 07b827f8915838224b2ff9aee162cf0e0c86d092 · typst/packages · GitHub
The proper way to let the people using your template overwrite the file to use is to take content as an argument directly, not a string. For example, you should replace this:
#let cover-page(logo-path: "logo.png", title) = {
image(logo-path)
heading(title)
}
With something like:
#let cover-page(logo: image("logo.png"), title) = {
logo
heading(title)
}
EDIT: Also this:
Packages cannot access project files, unless the package is installed inside of the project
If you want to pass an image to your template, you will have to read it in your project and pass the image object to the template
#let img = image("my_nice_image.png")
#show: my-template.with(img)
3 Likes
This is true for basic usage, but for something more complex a closure hack by @SillyFreak can be used:
#let cover(logo: none, doc) = {
[Logo: #image(logo(), width: 69%)]
doc
}
#import "@local/name:0.0.0": cover
#show: cover.with(logo: () => read("tiger.jpg", encoding: none))
You either have to mandate that users provide the closure or check the type and do stuff accordingly to it.
To make it slightly better, define an additional read function:
#let read-image = read.with(encoding: none)
#let cover(logo: none, doc) = {
[Logo: #image(logo(), width: 69%)]
doc
}
#import "@local/name:0.0.0": cover, read-image
#show: cover.with(logo: () => read-image("tiger.jpg"))
This is still not very complex, so here, if you just need to edit image
settings, you can pass image.with("file")
:
#show: cover.with(logo: image.with("tiger.jpg"))
#let cover(logo: none, doc) = {
[Logo: #logo(width: 69%)]
doc
}
If you want, for example (package structure does have 4 predefined logo file names), to override a directory full of assets, then I’m pretty sure logo: image => read("localdir/" + image)
should work and is complex enough for the hack to be actually useful.
Thanks, that is exactly the explanation I was looking for !
I changed the image path strings with an image object each in this commit . I’ll stil have to make tests to see if it works as expected.
1 Like
Hi @mononym , glad you got a satisfying answer! Please don’t forget to mark it as the solution, so that others can more easily find it later. Thanks!