I use the bundle feature to build a website. I want to include an outline on every page, that links to the different headers on the current document. Is there a way to do that?
This document:
#document("page1.html")[
#outline()
= Page 1, header 1
= Page 1, header 2
]
#document("page2.html")[
= Page 2, header 1
= Page 2, header 2
]
Compiles to:
<nav>
<h2>Contents</h2>
<ol style="list-style-type: none">
<li><a href="#loc-1">Page 1, header 1</a></li>
<li><a href="#loc-2">Page 1, header 2</a></li>
<li><a href="page2.html#loc-1">Page 2, header 1</a></li>
<li><a href="page2.html#loc-2">Page 2, header 2</a></li>
</ol>
</nav>
<h2 id="loc-1">Page 1, header 1</h2>
<h2 id="loc-2">Page 1, header 2</h2>
Where I would have wanted:
<nav>
<h2>Contents</h2>
<ol style="list-style-type: none">
<li><a href="#loc-1">Page 1, header 1</a></li>
<li><a href="#loc-2">Page 1, header 2</a></li>
</ol>
</nav>
<h2 id="loc-1">Page 1, header 1</h2>
<h2 id="loc-2">Page 1, header 2</h2>
I would need something like
#context outline(target: selector(heading).within(selector(document).parent(here())))
But selectors donât have anything like a parent() method.
A workaround is to wrap the whole document in a context, and use here() in the outlineâs target selector. It is somewhat fragile though, because there cannot be another context as the outlineâs parents.
#document("page1.html", context [
#outline(target: selector(heading).within(here()))
= Page 1, header 1
= Page 1, header 2
]) // works
#document("page2.html", context [
#context outline(target: selector(heading).within(here()))
= Page 2, header 1
= Page 2, header 2
]) // doesn't work (outline is empty)
1 Like
You could query the location of the current document:
#context outline(target: selector(heading).within(
query(selector(document).before(here()))
.last()
.location()
))
Because locations are unique identifiers for elements, you may use it inside within(...) 
2 Likes
ha, thatâs the same exact solution! thanks for the reference 
1 Like
That works, thank you very much. I didnât think before() would also select the current element, shouldnât that be specified in the documentation? I guess thatâs what inclusive is for, but that isnât very clear.
Actually, inclusive doesnât matter here (you can set inclusive to false, and it produces the same output). Since the layout of the document is something like
#document[
#context(...)
...
]
The document occurs strictly before the context block even if the context block is nested inside the document. Meaning, when we call .before(here()), there is a document before the start of the context block, which gets matched.
The inclusive field would be relevant in a scenario like
#document("index.html")[
#context query(selector(document).before(label("test"), inclusive: false))
]<test>
Since in this example, once we label âindex.htmlâ with the label <test>, the document occurs at the same location as the label. This is what the documentation means with
inclusive: Whether end itself should match or not. This is only relevant if both selectors match the same type of element. Defaults to true.
But I agree that it can be a little confusing. The fact that one needs to use .location() to go from an element to an identifier for that same element could also be elaborated on, since that is a âtrickâ that can be easily missed.
1 Like