I imagine you're projecting how LaTeX works onto Typst, though despite years of use and a PhD in PL I never really figured out how LaTeX works so I'm not certain.
I don't think Typst has a lot of global state to get corrupted. Like, if one package defines a variable `foo` and another package defines a variable `foo`, and you use both of them (and don't try to import `foo` from both), it's not like those `foo`s are going to conflict with each other. Is that the sort of issue that LaTeX packages run into?
Likewise, you don't modify typesetting in Typst by modifying global state like you do in Latex. You use `set` and `show`, which are locally scoped. You never need to, like, set the font size, then write some stuff, then remember to set it back. You just put `set font(size)` around precisely the stuff you want to be bigger.
In general, with the TeX "engine", you can locally scope most changes by simply wrapping them in braces {}.
However, if you have a need to override something globally (eg. a global heading font, or spacing at the paragraph level), there is really no way to do it other than doing it globally.
How would Typst solve this without having the same problem? Eg. how can I have a package that sets every "the" in red colour, without it interfering with a package that sets every "the" in blue or titlecase?
Perhaps it's structured better (I would hope so, with ~40 years of learnings since TeX was introduced), but the problem seems unavoidable if you allow things like the above.
>how can I have a package that sets every "the" in red colour, without it interfering with a package that sets every "the" in blue or titlecase?
Exactly.
Broadly, the things you might want a package/plugin to do can be categorised as "local" (e.g., add some new type of content in a fixed-size box that the layout engine can then treat the same way as it treats any other such box) or "global" (e.g., change where floats appear). Making local effects play together can be easily handled with standard PL ideas like lexical scoping, but doing the same for global things is much harder: it strongly depends on exactly what knobs (API) the base typesetting engine provides. We now have design patterns like Observer to help make creating such "global" effects simpler, assuming that their effects are genuinely orthogonal, but what if they aren't?
A plugin that sets each "the" to red clearly conflicts with a plugin that sets each "the" to blue: at most one of them can "win", so which is it? Does it depend on which plugin was loaded first? If so, that's no better than LaTeX, and will become an ever-growing headache as the ecosystem grows.
OTOH, a plugin that sets each "the" in italics can sensibly interoperate with a package that sets each "the" in bold -- and can even produce the same results regardless of which was loaded first, because these effects "commute". These effects could be implemented by having the base engine expose an event that can be listened to by any interested plugin.
ETA: The main reason LaTeX is a pain is because it makes no real attempt (that I can see) to manage any of the inevitable complexity of "global" effects. (Admittedly, this is a tough design problem.) I don't yet see signs of anything better from Typst, thus I assume it will become roughly as painful as LaTeX in time.
I disagree with the assumption that the red/blue conflict should produce an error. In real life most of the time you want one style to override the other. So in this simplistic example at least, having the result determined by the order is the correct behavior (and it's what typst does).
More generally, if your system generates errors left and right, you end up making it hard for users to find a combination of packages that work. It's better to make them work error-free as much as possible. And the concept of "overriding" is natural and useful.
I think typst does make a nice attempt at managing global effects. It's nowhere near perfect but works pretty well already. For example it's super easy to implement your example with two packages, one applying bold and the other applying italic:
Template from package A: #show regex("\bthe\b"): set text(style: "italic")
Template from package B: #show regex("\bthe\b"): set text(weight: "bold")
You can use both templates in any order, typst will correctly render "the" in italic bold.
> A plugin that sets each "the" to red clearly conflicts with a plugin that sets each "the" to blue: at most one of them can "win", so which is it? Does it depend on which plugin was loaded first? If so, that's no better than LaTeX, and will become an ever-growing headache as the ecosystem grows.
Just loading a package in Typst won't perform side-effects. Instead what they can do is giving you some function that will apply the styling to any content passed to it. It will be up to you to choose to wrap your whole document in such functions in order have them apply globally, which can be done conveniently with something like `#show: foo_template`, where `foo_template` is the aforementioned function.
This still has a chance of "incompatibility", like in the blue/red example, because you might do this with two functions from two different plugins. However it is up to you to do this, and it will hopefully be clear that you're modifying global styles in two different ways with a specific order between them.
To be fair though I should mention that some packages will expect you to use `#show` with their functions, so sometimes it will be difficult to avoid using it multiple times.
I don't think Typst has a lot of global state to get corrupted. Like, if one package defines a variable `foo` and another package defines a variable `foo`, and you use both of them (and don't try to import `foo` from both), it's not like those `foo`s are going to conflict with each other. Is that the sort of issue that LaTeX packages run into?
Likewise, you don't modify typesetting in Typst by modifying global state like you do in Latex. You use `set` and `show`, which are locally scoped. You never need to, like, set the font size, then write some stuff, then remember to set it back. You just put `set font(size)` around precisely the stuff you want to be bigger.