How do I read the API documentation in regards to named parameters that act positionally?

The documentation for text indeed isn’t very clear about this, but here’s what’s going on:

  1. The most common named arguments for text - mostly unambiguous ones such as fill: and size: - can also be used positionally as an exception, just for convenience. These parameters are not separately listed as positional in the documentation at the moment. Note that you can implement this same behavior in your functions by taking and parsing arbitrary amounts of arguments (see Arguments Type – Typst Documentation).
  2. The two positional arguments you see (content and str) are currently misleading and need improvement. Basically, what’s going on here is that text is a special element, in that its element constructor (the #text(...)[stuff] function), instead of constructing a new text, applies the given parameters as local styles, as if you were applying a set rule on the given content. That is:
    #text(red, font: "Arial")[Hello world!]
    // is equivalent to
    #[
        #set text(red, font: "Arial")
        Hello world!
    ]
    
    This means that the whole #text() function (not the element itself, but its constructor) only exists as a convenience to apply text element set rules to the given content parameter, which is strictly positional. Therefore, that content you see is the content to apply the set rules to. (This is similar, for instance, to #align: #align(center)[abc] is more or less equivalent to #[ #set align(center); #block[abc]].)
    But then what is the str parameter? That’s where the text element part comes in: the real text elements are simple wrappers around strings. They contain no formatting at all - they are the most basic element of all text, so it is natural that any formatting would be done by elements (such as strong or emph) containing those more fundamental units, and not the other way around. So, this str “parameter” is actually the .text field of text elements (the contained text) “leaking” into the docs, but you can’t actually pass that parameter because you cannot construct text elements by yourself: they are automatically generated for you as you type text in a markup block. This means that #text("ABC") is actually the exact same as #text[ABC] which is also the exact same as #[ABC], since text, when used as a function, only applies styles to the text elements in ABC, but no styles are being configured so nothing happens. It’d certainly be much nicer if this could be displayed properly!

Hope this clears it up. Feel free to open an issue in GitHub - typst/typst: A new markup-based typesetting system that is powerful and easy to learn. to suggest an improvement to this doc page, if there isn’t already one!

Now, just to address your individual questions:

You’d have to look for arguments marked with #[parse] in the internal code, since those basically take the whole argument list into account (basically the same idea as using ..args in a function and manually extracting arguments however you want, as I hinted at above). Then, they might be pseudo-positional, or might accept more than one name (as seen in #pad(x: 5pt) being equivalent to #pad(left: 5pt, right: 5pt)), and so on.

text is simply an exception as it’s such a basic element. The same exception was not applied to highlight.

The relevant line is here: typst/crates/typst/src/text/mod.rs at e0d809680aed778443a4797bc044376dbe15347e · typst/typst · GitHub

Note the usage of named_or_find onto the argument list instead of just named.

1 Like