!!! 更新:官方已经支持这个特性,更完善。

Typst的par函数有一个justify(齐整,两端对齐)字段,设置为true后,可以自动整空格的大小,使行首尾对齐边框。但汉字间没有空格,标点前/后的空格不多,所以效果有限,常常很难看:

做了一个简单的简单函数,插入fraction(TeX叫无限拉伸胶),使justify常有足够的空格可用,效果就比较自然。这样做可能有副作用:影响fraction的一般使用情形。效果如下:

代码如后。可在这里在线体验:

使Typst par能调整汉字间距

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
#set page(height: auto, width: 8.9cm)
#set text(
  font: "Noto Serif CJK SC",
  size: 11.5pt
)

/*
= 最初尝试的方法

不能处理嵌套问题。这个思路源自LuaTeX节点列表。

//两端对齐
#set par(justify: true)
// 汉字及其标点(不完善)
#let chinese_set = regex("[\u4E00-\u9FA5、,。;:“”!?‘’]")

// 处理此下所有内容
#show : (rest) => {
    for i in rest.children {
        if i.has("text") {
            for c in i.text {
                if chinese_set in c {
                    // 汉字及其标点后插入1份无限拉伸胶
                    c + [#h(1fr)] 
                }else{
                    c
                }
            }
        } else {
            if i==parbreak() {
                // 段末插入100000无限拉伸胶,经验值
                // 可能有副作用
                [#h(100000fr)]
            }
            i
        }
    }
}

= 正确的做法

还不能不能处理单元格中的段落。

*/


#show : (rest) => {
     set par(justify: true)

     // 汉字及其标点(不完善)后加无限拉伸胶
     let chinese_set = regex("[\u4E00-\u9FA5、,。;:“”!?‘’]")
     show chinese_set: c => c + [#h(0.00001fr)] 

     // 不满的行(末行)后加胶
     let end_fr = [#h(1fr)]
     show parbreak : b => end_fr + b
     show linebreak : b => end_fr + b
     show enum : it => {
       for i in it.children {
         i.body + end_fr
       }
     }
     show list : it => {
       for i in it.children {
         i.body + end_fr
       }
     }
     //TODO 文末加end_fr
     rest
}

//还不能处理嵌套中的内容,如表格
#table(
  columns: (1fr,1fr),
  [#set par(justify: true)
  你来了你来了你来了你来了

  你来了你来了你来了你来了

  // 末尾必须有空行
  ],
  [#set par(justify: true)
   #lorem(10)],
)

+  你来了你来了你来了你来了
+  你来了你来了你来了你来了
-  你来了你来了你来了你来了
-  你来了你来了你来了你来了

#lorem(20)

排版元素可以旋转位移\
可以手动堆叠成行成列\
元素间可以放置正值或负值的空白
这么说可以做标点压缩竖排双行夹注等功能

但目前似乎没有操作底层数据的接口比如获取字体和字模信息操作抽象语法树模块树框架树

另外它的分行组段的算法似乎比较简陋不知道后面会不会移植 Knuth-Plass 的算法这个说法是错误的Typst 有一个optimized Knuth-Plass style)。
目前汉字间没有像 LuaTeX 那样加入零宽度的胶所以行校正时可拉伸点较少只能用标点前后的空格),拉得太狠很难看

// 末尾必须有空行

评论