Why can't I show-set an emphasize element to have always "normal" style?

Consider the following code:

#show emph: set text(weight: "bold", style: "normal")
This is an _example_.

It turns out that “example” is printed in bold letters (which is not the default, so the show-set rule works) but is still italic. Can anyone explain why that is?

Note: I know I can achieve my goal e.g. by defining

#show emph: it => {
  text(weight: "bold", style: "normal", it.body)
}

but this is not the point of the question. Instead I’d just like to understand what is going on in the previous example.

This is not even an answer, but I’m sure it will be interesting :slight_smile:

#show emph: set text(weight: "bold", style: "italic")
This is an _example_.

This must be related to the fact that emph inverts itself - emphasis of emphasis reverts to normal text again.

This #emph[is an _example_.]

I haven’t looked into the implementation but it seems that emph works by recursively switching between style: "normal" and style: "italic" . The following code presents some examples:

#emph[Under emphasis 
  - #text(style: "normal")[this is italic] 
  - #text(style: "italic")[and this is 'normal'].
  ]

Now let’s do something really funky and transform all ‘normal’ text to ‘italic’:

#show text.where(style: "normal"): set text(style: "italic")
+ #text[This is italic]  // is equivalent to #text(style: "italic")[…]
+ #emph[This is not!]    // is equivalent to #emph[#text(style: "italic")[…])
+ #emph(text[Nor is this!]) // identical to above
+ #emph(text(style: "italic")[Not italic either]) // identical

Now let’s look at what your examples become. Under the show-set rule

#show emph: set text(style: X)

#emph[Text] becomes equivalent to #emph[#text(style: X)[Text]].

  • If X = "normal" then #emph evaluates to ‘emphasise normal’, i.e., italic
  • If X = "italic" then #emph evaluates to 'emphasise italic`, ie, normal.

An example is probably clearer:

#show emph: set text(style: "normal")
#emph[Italic] is equivalent to #emph(text(style: "normal")[Italic])
#show emph: set text(style: "italic")
#emph[Not italic] is equivalent to #emph(text(style: "italic")[Not italic])

The show-rule #show emph: it => do-something(it.body) completely destroys the emph element, so #emph[Text] becomes #do-something[Text].

Thanks, from this perspective it does make a lot more sense.

However, I’m now wondering whether this is desired behaviour. After all the emph element has a semantic meaning, so one might wish to change the formatting rules without destroying the element, e.g. for HTML-Export.

In this case I would like to emphasize a word by using bold instead of italic fonts. Of course, @bluss 's answer works in that regard but it is extremely counter-intuitive to put style: "italic" when one wants non-italic text and vice-versa.

I agree. Setting the style via #text(style: X) should override pre-existing emphasis. The problem, as I see it, is that the current implementation has (presumably) no way to distinguish between #text(style: "normal")[Text] and #text[Text]. One solution might be to allow style: "inherit" and make this default. Then any use of style: "normal" or style: "italic" can be honoured.

I encountered the same issue with using different fonts for maths elements like math.op. There is a GitHub issue tracking the problem: Overriding #emph for elements is whacky · Issue #6172 · typst/typst · GitHub . Perhaps you can add your ‘example’ to that issue.

The following show rule (based on one in the issue linked above) probably achieves your modification of emph behaviour:

#show emph: it => {
  if text.weight == "regular" {
    text(weight: "bold", it.body)
  } else {
    text(weight: "regular", it.body)
  }
}

I don’t think so. The emph behavior here seems correct to me, although maybe not intuitive if you’re unfamiliar with how show: set works.

For example when you write show heading: set text(red) it means “Use red as default text color for heading elements”. Similarly when you write show emph: set text(style: "normal") it means “use ‘normal’ as default text style for emph elements”.

Now the emph behavior is documented as applying italic if the current style is normal, and vice versa. So with

#show emph: set text(weight: "bold", style: "normal")
This is an _example_.

the current behavior is correct: setting the style to “normal” is not really doing anything since that’s already the default. Then emph is going to operate on a text with style “normal” so it will turn it into italic.

I’m not saying this situation is ideal, but it’s applying the rules consistently. Since the emph element works as a toggle (without any setting), the only way to change its behavior is to remove it, or to add another toggle which looks unintuitive.

@sijo I think you misunderstood me. Instead of ‘should’ I should(?) have written ‘ought’. The current implementation works as it should but not (in my opinion) as it ought :wink:.

But your explanation of show-set was clearer than mine!