Is it possible to create a link to a heading by using the label alone?

For more information about hedgehogs, see the section about #link(<wrds>)[wyrdies].

= Wyrdies and Their Friends
<wrds>

Wyrdies, commonly known as unicorns, have many friends. Among them are hedgehogs and kangaroos.

This works. Output:

For more information about hedgehogs, see the section about wyrdies.

But is it possible to create a link to a heading without specifying its name, by using the label alone?

For more information about hedgehogs, see “#link(<wrds>)”.

Output:

For more information about hedgehogs, see “Wyrdies and Their Friends”.

I tried #link(<wrds>) and #link(<wrds>)[], but it doesn’t seem to work.

I think usually you would use @wrds

For more information about hedgehogs, see @wrds.

= Wyrdies and Their Friends<wrds>

Wyrdies, commonly known as unicorns, have many friends. Among them are hedgehogs and kangaroos.

But this requires to use numbering, right?

#set heading(numbering: "1.")

And even with numbering, the section is mentioned by its generic name, that is, as “Section”:

For more information about hedgehogs, see “Section 1”.

The problem there is that then the heading needs to have a numbering and @jsx97 wants the ref to return a clickable title and not “Section X”.

You can achieve this with a show-rule on link, but you still need to call it with the empty square brackets as the body argument is required unless it’s a URL:

#show link.where(body: []): l => {
  let heading-elem = query(l.dest).first()
  link(l.dest, heading-elem.body)
}

For more information about hedgehogs, see the section about #link(<wrds>)[].

= Wyrdies and Their Friends<wrds>

Wyrdies, commonly known as unicorns, have many friends. Among them are hedgehogs and kangaroos.

PS: It is probably a good idea to check if type(l.dest) == label in the first place but assuming you only use the #link(...)[] syntax for this purpose, it’s fine.

1 Like

This works, thanks. But there is one minor issue: currently, the link inherits the inline styling of its heading. That is, if you have

For more information about hedgehogs, see “#link(<wrds>)[]”.

= Wyrdies #strong[and Their Friends]<wrds>

the output will be

For more information about hedgehogs, see “Wyrdies and Their Friends”.

Could you show how to fix it?

Oh yea for sure. Assuming your headings are always just text and dont, for example, include a random #rect() or styling in general, use heading-elem.body.text instead.

If the heading is not just text but has styling like bold, it will be a sequence and you can access the textual part through .children() which you will have to combine to plain text.

EDIT: For example, in your case, “Wyrdies and Their Friends” would be represented as sequence([Wyrdies], [ ], strong(body: [and Their Friends])) and could be extracted as follows:

#show link.where(body: []): l => {
  let heading-elem = query(l.dest).first()
  link(l.dest, heading-elem.body.children.map(c => {
    if c.has("text") { c.text }
    else if c.has("body") { c.body }
    else { c }
  }).join())
}

(This probably does not cover all cases.)

1 Like