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.

2 Likes

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_.]

4 Likes

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].

1 Like

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.

1 Like

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!

1 Like