How to split (heading) content into seperate strings/contents for styling

Hello

I am trying to find a way to style different parts of a heading body separately.

To do this I need to read the heading body content as a string → Locate the “:” character → Split the string → Render it with different styling:

#show heading.where(level: 5): it => {
  // str(it.body) // ERROR: content can not be converted to str
  // it.body.position(":") // ERROR: Element sequence has no method `position`

  // I need a way to split it.body into "SOLUTION:" and 
  // " Two and three is five" so I can style them separately.

  text(weight: 600, [SOLUTION: ])
  text(weight: 300, [ Two and three is five])
}

===== SOLUTION: Two and three is five

Needed output (first word is bold, the rest is regular text):

SOLUTION: Two and three is five

Further, if anyone knows how to output the different methods on an object I would be greatfull. E.g. what are the methods on the heading? (it.body, it.numbering… what else?)

Short description of my actual use-case:
I am typesetting a book written in markdown, using cmarker to read the markdown and convert to Typst. To style unique part of the markdown, I give it a heading as a handle to grab via Typst show rules, in this case heading with depth 5 is used for math solutions and math notes.

There’s no need to do any string manipulation, you can use regex to match the part of the body that comes after “:” and style that differently:

#show heading.where(level: 5): it => {
  set text(weight: 600)
  show ":": set text(weight: 600)  // undo matching of ":" in show rule
  show regex(":.*"): set text(weight: 300)
  
  it
}

(possibly the show rule matching only “:” could be combined into the regex one, but I am bad with regex…)

You can hover over variables to show what their methods are, this is useful for debugging (see: Tips on debugging Typst code, including the dark magic). Alternatively you can use the repr function.
For headings in particular, all of their methods are also outlined in the docs: Heading - Typst Documentation

heading(
  level: auto|int,
  depth: int,
  offset: int,
  numbering: none|str|function,
  supplement: none|auto|content|function,
  outlined: bool,
  bookmarked: auto|bool,
  hanging-indent: auto|length,
  content       // body
) → content

I don’t know exactly how cmarker works, but if it’s possible i’d pass this data to a custom solution function, instead of doing semi-hacky things with headings :smile: It works here, but for more complex tasks doing it this way is easier, and doesn’t lead to weird artefacts (e.g. you might not want that solutions are headings)

1 Like