You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Typst代码块添加语言标识后自定义加粗格式失效问题求助

Typst代码块指定语言后自定义加粗失效的解决方法

问题背景

我用Typst展示代码块时,想通过自定义方式高亮重要内容,实现了两个核心逻辑:

  • 自定义text_bold函数实现文本加粗(未用Markdown原生加粗语法)
  • 通过正则匹配#text_bold[xxx]标记,给对应内容应用加粗格式

未指定代码块语言时,自定义加粗正常生效:

dfir@dfir-mbp ~ % #text_bold[hello]

(效果:hello会被加粗)

但给代码块加上bash语言标识后,语言语法高亮会覆盖自定义加粗效果:

dfir@dfir-mbp ~ % #text_bold[hello]

(效果:#text_bold[hello]按bash语法高亮,hello未被加粗)

我的实现代码如下:

//------------------------------------------------------------
// Bold Function
//------------------------------------------------------------

#let text_bold(body) = {text( weight: "bold", [#body])}

//------------------------------------------------------------
// Raw converter Function
//------------------------------------------------------------

#let raw_converter(body) = {
  //----------------------------------------------------------
  // Find all matches with function #text_bold
  //----------------------------------------------------------
 
  let matches_text_bold = body.text.matches(regex("#text_bold\[[^]]+\]{1,10}"))

  //----------------------------------------------------------
  // Adding the rules
  //----------------------------------------------------------
  show raw.where(): show_rule => {
    //--------------------------------------------------------
    // Set the #text_bold rule
    //--------------------------------------------------------
    for it in range(matches_text_bold.len()) {
      // Creating the value inside the #text_bold function
      let text_value = matches_text_bold.at(it).text.replace("#text_bold[","").replace("]","")
      show_rule = {
        // Remove the function to only keep the text inside
        show matches_text_bold.at(it).text: text_bold(text_value)
        show_rule
      }
    }
    show_rule
  }
  
  body
}

#let terminalbox(
  title: "",
  body_box,
) = {
      [... Creating the header of the Box ...]
      //------------------------------------------------------
      //  Body of the Box
      //------------------------------------------------------
      rect(
        width: 100%, 
        radius: (bottom-right: 6pt, bottom-left: 6pt),
        fill: body_color,
        inset: (y: 8pt, x: 5pt),
        stroke: (top: 0.8pt + line_color),
        text(
          box_text_size, 
          raw_converter(body_box),
          fill: box_text_color, 
          font: box_text_type,
        ),
      ),
    )
}

#terminalbox(title: "Terminal",
```bash
dfir@dfir-mbp ~ % #text_bold[hello]
```)

问题原因

当代码块指定语言后,Typst会启用对应语言的语法高亮器,此时代码内容会被转换成语法高亮后的结构化元素,不再是原始的raw文本。而你的raw_converter函数仅通过show raw.where()规则处理原始文本,对语法高亮后的内容无效,导致自定义加粗被覆盖。

解决方案

方案1:预处理文本后再应用语法高亮

先把代码中的#text_bold[xxx]标记替换成加粗文本,再传递给语法高亮器,确保加粗效果优先生效:

#let text_bold(body) = text(weight: "bold", body)

#let terminalbox(
  title: "",
  body_box,
) = {
  // 预处理代码内容,替换#text_bold标记为加粗文本
  let processed_body = body_box.text.replace(
    regex(r"#text_bold\[([^\]]+)\]"),
    content(match) => text_bold(match[1])
  )
  
  // 保留原有的头部创建逻辑
  [... Creating the header of the Box ...]
  
  // 主体部分:传入预处理后的内容并指定bash语法
  rect(
    width: 100%, 
    radius: (bottom-right: 6pt, bottom-left: 6pt),
    fill: body_color,
    inset: (y: 8pt, x: 5pt),
    stroke: (top: 0.8pt + line_color),
    text(
      box_text_size, 
      code(lang: "bash", processed_body),
      fill: box_text_color, 
      font: box_text_type,
    ),
  )
}

// 使用示例
#terminalbox(title: "Terminal", body_box: "dfir@dfir-mbp ~ % #text_bold[hello]")

方案2:拦截语法高亮后的代码块

通过全局show规则拦截指定语言的代码块,对其中的自定义标记进行替换,确保加粗在语法高亮后生效:

#let text_bold(body) = text(weight: "bold", body)

// 全局规则:处理bash代码块中的#text_bold标记
show code.where(lang: "bash"): code_block => {
  let processed_content = code_block.body.replace(
    regex(r"#text_bold\[([^\]]+)\]"),
    content(match) => text_bold(match[1])
  )
  // 返回处理后的代码块
  code(lang: "bash", processed_content)
}

#let terminalbox(
  title: "",
  body_box,
) = {
      [... Creating the header of the Box ...]
      // 主体部分直接传入代码块
      rect(
        width: 100%, 
        radius: (bottom-right: 6pt, bottom-left: 6pt),
        fill: body_color,
        inset: (y: 8pt, x: 5pt),
        stroke: (top: 0.8pt + line_color),
        text(
          box_text_size, 
          body_box,
          fill: box_text_color, 
          font: box_text_type,
        ),
      ),
    )
}

// 使用示例
#terminalbox(title: "Terminal", body_box: code(lang: "bash", "dfir@dfir-mbp ~ % #text_bold[hello]"))

说明

  • 方案1适合需要快速替换标记的场景,预处理后再高亮不会冲突
  • 方案2更灵活,能保留语法高亮的同时,对指定内容单独加粗

内容的提问来源于stack exchange,提问作者greco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:06:05