I ran into a problem where I need to style a link in my html. However, I could only do so indirectly like this (using Tailwind CSS w/ typhoon):
#html.div(
"*:px-2 *:py-1.5 *:bg-white *:no-underline",
link(<some-label>)[foo bar baz]
)
And this will generate the following HTML:
<div class="*:px-2 *:py-1.5 *:bg-white *:no-underline">
<a href="...#some-label">foo bar baz</a>
</div>
The problem is that I couldn’t directly attach attributes to the <a> elem in the final HTML output. This becomes a problem when writing a11y stuff such as ARIA labels or styling. Nevertheless, I discovered a way to extract and write new info yesterday:
// put the show rule in a specific block so it won't leak
#{
show html.elem.where(tag: "a"): set html.elem(attrs: (
class: "px-2 py-1.5 bg-white no-underline",
role: "foo bar",
aria-foo-bar-baz: "something else",
// basically attach whatever you want here
))
link(<some-label>)[foo bar]
}
The HTML:
<a
class="px-2 py-1.5 bg-white no-underline"
href="#some-label"
role= ..>
foo bar
</a>
Even better, you can extract info from links:
#let doc-urls = state("doc-urls-foo-bar", ())
#document(...) <post-1>
#document(...) <post-2>
// ...
#document(...) <post-n>
#document("index.html", {
for i in range(n) {
// the hrefs here will be relative to `index.html`
show html.elem.where(tag: "a"): a => {
doc-urls.update(arr => arr + (a.attrs.href,))
}
link(label("post-" + str(i + 1)))[]
}
// place your regular content after this point
#title[My Awesome Site]
})
// Make an RSS or Atom feed, for example
#context asset("feed.xml", {
let urls = doc-urls.final()
for url in urls {
// generate posts here
}
})
This is useful for generating RSS or Atom feeds (I also have a package that generates XML and Atom). Additionally, the extracted URL can be used in html elements that accept a url or an href, such as img, a, iframe, and link (currently they don’t directly accept Typst labels).