Tags: hakyll
Block,constructor 是
Para [Inline]。而 Inline
包含了所有需要考虑的其他元素。 所以只需要在一个 Inline list
当中检查每个 element 内部是否需要空格,以及 list
两个元素之间是否需要空格。我们并不关心遍历 AST 的时候上一个 leaf
是什么。
1 Python → Haskell
在元旦假期终于开始写。计划是从 python 版本迁移过来,因为 vinta 实现 pangu 的那些语言里我只看得懂 python。 我发现貌似作者自己也没总结出什么中英文排版加空格、换全角或中文标点的规则(也可能是因为 ww 和大陆习惯也不同),而且正则表达式里漏洞很多。 pangu.hs 需要根据一些规则来替换字符和删减空格,所以应该把这些规则写下来然后弄一个存放规则的 list,程序根据这个 list 里的规则来调整文本,同时用户见到自己不想要的 rule 也可以直接 comment 它。 我没有在 Haskell 中使用正则表达式的经验,于是求助 Gemini 和 ChatGPT。相比于 regex 他们更推荐用 megaparsec。 如果要 find and replace,就需要用streamEdit.
这函数会找所有不重叠的 section,完成替换任务。
type Parser = Parsec Void Text
type Rule = Parser Text
type RuleSet = [Rule]
applyUntilFixed :: Rule -> Text -> Text
applyUntilFixed rule =
fix
( \loop current ->
let next = streamEdit (try rule) id current
in if next == current then next else loop next
)
applyRulesRecursively :: RuleSet -> Text -> Text
applyRulesRecursively rules input =
foldl (flip applyUntilFixed) input rules
applyRules :: RuleSet -> Text -> Text
applyRules rules input = foldl (flip applyOnce) input rules
where
applyOnce rule = streamEdit (try rule) id
然后即可这样选择要启用哪些Rule
recursiveRules :: RuleSet
recursiveRules =
[ fullwidthCJKsymCJK,
fullwidthCJKsym
]
onepassRules :: RuleSet
onepassRules =
[ dotsCJK,
fixCJKcolAN,
cjkquote,
quoteCJK,
fixQuote,
cjkpossessivequote,
-- singlequoteCJK,
fixPossessivequote,
hashANSCJKhash,
cjkhash,
-- hashcjk,
anscjk,
cjkans,
empty -- a dummy rule
]
pangu :: Text -> Text
pangu input =
applyRules onepassRules $ applyRulesRecursively recursiveRules input2 Pandoc filter
现在想要在 hakyll 里使用这个包。 这部分很简单,只要实现上文说的想法就好了。 pandoc-types 提供了很多方便写 filter 的函数,我们实现好处理[Inline] 的 filter 就好了。
panguFilter :: Pandoc -> Pandoc
panguFilter = walk transformBlocks
where
transformBlocks :: Block -> Block
transformBlocks (Para inlines) = Para (panguInlines inlines)
transformBlocks x = x3 CSS
text-autospace
一月九号才在知乎看到 CSS
也支持类似的功能: text-autospace
2025 年九月份就已经在主流浏览器上可用。