What's the difference between the argument body & str in #text()?

Hi everyone, love typst and i love what it tries to do.
my question is about the text function. from my limited understanding most function have normal named parameters e.g size and positional parameters that require no name. what i can’t seem to wrap my head around is what’s the difference between body and str parameters?

#text("hello typst") 

this would work just fine and i assume that the string maps to the positional str parameter. however if i type:

#text(body:["text"]) 

i get an error.
i like to be explicit when i write a function and i can’t understand the purpose of the body parameter or how to use it ( i see that it defaults to ).

btw, in the documentation body isn’t mentioned as position unlike str. but it say it is in the web app. see the figures bellow:

1 Like

To make it work, you have to type either

#text([Text])

or

#text[Text]

The main difference between string and content is that you can use Typst markup when you use content. For instance

#text(size: 2em)[*bold text*]
2 Likes

Thanks @maucejo. I understand that a content block allows for typst markup. I can see that the string positional argument is mandatory from the docs. can we combine them both? i tried and it fails. my rational is since they are both mentioned in the documentation we could use them both. Also, it seems from the webapp that body is positional parameter but the documentation doesn’t say that.

The short answer is that your string or content is the body of the text function. That is why you can’t use both simultaneously.

1 Like

The body parameter simply leaks from the internal rust implementation. There is no named body parameter, there is just one positional parameter that accepts string and content.

There is already a open issue (#7580) about it.

6 Likes

It looks to me like the documentation is wrong - or at least doesn’t match the code.

Issue 1 - What is the text parameter?
This is listed as a parameter of the text function in the documentation, but the web app does not list it:

Maybe they are mutually exclusive and text is used if the given content is str type and body is used for anything of type content. If that’s true then the documentation should make that clear or make body accept both types and remove text

Issue 2 - Is the body parameter positional?
Again, the documentation and web app disagree.

3 Likes

This makes sense now. THANK YOU and everyone who shimmed in on the question.

I agree with @gezepi, the documentation needs fixing.

1 Like

By the way, the source code explains why there’re two arguments in the first place.

    /// Content in which all text is styled according to the other arguments.
    #[external]
    #[required]
    pub body: Content,

    /// The text.
    #[required]
    pub text: EcoString,

Refer to elem in typst_macros - Rust for the meaning of attributes external and required.

impl Construct for TextElem {
    fn construct(engine: &mut Engine, args: &mut Args) -> SourceResult<Content> {
        // The text constructor is special: It doesn't create a text element.
        // Instead, it leaves the passed argument structurally unchanged, but
        // styles all text in it.
        let styles = Self::set(engine, args)?;
        let body = args.expect::<Content>("body")?;
        Ok(body.styled_with_map(styles))
    }
}
1 Like