The numbering parameter can also take a custom function. This is what you want to use in this case. I wrote an example below with some comments on what is happening. I hope that it all makes sense!
#set page(width: 5cm, height: auto)
// The function is passed a variable
// number of arguments (e.g. 1, 1, 2).
// The `..nums` is an argument sink,
// which collects all excess arguments
// in `nums`.
#set heading(numbering: (..nums) => {
// We want the positional arguments
// from `nums`.
// `numbers` is now an array of ints
// e.g. a level one heading `= ...` could be (1,)
// e.g. a level two heading `== ...` could be (2, 1)
// e.g. a level three heading `=== ...` could be (1, 0, 2)
let numbers = nums.pos()
// Top level (level 1) headings will have a single
// int like (1,), as mentioned above. So we check
// if the array's length is 1 for level one headings.
if numbers.len() == 1 {
numbering("TOP 1:", ..numbers)
} else {
// Everything else
numbering("1.1", ..numbers)
}
})
= Test
== Test
=== Test
== Test
== Test
= Test
=== Test