How to select direct children of elements in `show` rules?

Is there a canonical way to select direct children of a given element in typst?

For example, I already have a show rule putting every link into a box.
Now, I want all boxed links that are outline entries to have a different stroke color.

The full hierarchy would be: outline.entrylinkbox.

How can I set box(stroke: (paint: green)), only if it is a direct descendant of link, only if that is a direct descendant of outline.entry?

I’m used to CSS which has a broad range of selectors, so knowing the Typst equivalent would be very helpful to me.

Technically, it would be this:

#show outline.entry: it => {
  show link: set box(stroke: green)
  it
}

With Ancestry/inside/within selector · Issue #1926 · typst/typst · GitHub implemented:

#show selector(link).inside(outline.entry): set box(stroke: green)

But default outline.entry doesn’t have link…that is customizable: Can't select `link` from `outline.entry` · Issue #7317 · typst/typst · GitHub. This can be fixed by adding:

#show outline.entry: it => link(
  it.element.location(),
  it.indented(it.prefix(), it.inner()),
)

But default link doesn’t have box…unless you add one:

#show outline.entry: it => {
  show link: box.with(stroke: green)
  it
}

However, a better/alternative way would be to style the block, that is the size of the link, but not styling the nested blocks (Show-set rules should not apply recursively · Issue #7266 · typst/typst · GitHub):

#show outline.entry: set block(stroke: green)
#show outline.entry: it => {
  show block: it => {
    set block(stroke: none)
    it
  }
  it
}

#show outline.entry: set block(stroke: green)
#show outline.entry: it => {
  show block: it => {
    set block(stroke: none)
    it
  }
  it
}

#set heading(numbering: "1.")

#outline()

= Heading
== Heading

2 Likes