Zola 的 RSS 模板中的 HTML 处理 (04-15)
我后来也不用 Zola 了,真难写,真不熟。
对于其他用途的 Zola(实际是 Tera)模板,要把内容作为 HTML 而非带着大于小于号的普通文字输出,需要加一层 | safe
的 filter。比如在 shortcode 里。
但是对于 RSS,这实际是多余的、甚至有害的操作。因为寻常的 HTML 标签并不是 RSS 的 XML 命名空间的一部分。可以理解成,一段 RSS 内容中的尖括号标签只是为了 RSS 本身而存在的,是 meta 的东西;作为其标签的内容、以纯文本形式存储的东西则不能与 RSS 本身的标签相提并论,必须遵循 XML 对于纯文本中 XML 的控制字符(<>
)的处理方式 escape 之,也就是 <>
。
唔姆,有的人可能会问“为什么不行呢?”那么比如说,如果这段文字里出现了一个 RSS 标签的终结标签的文本形式呢?当然,我想绝大多数人不至于这样愚钝,即使有,看到这里也不需要进一步解释来理解了。(又不是在写美式教材)
总之我把那个 safe
filter 删掉就好了。
Zola 的主页和 pinned (04-15)
本站的主页,现在可以看到,底下展示了五篇文章。可以注意到,这不完全是最新的几篇。情况是:我在源文件的 front matter 里加了个专有的域,叫 pinned;如果我愿意这篇文章显示在首页,就设置为 true
。但是主页要显示的文章数目恐怕是有限的;那么怎么筛选呢?
我以前还是想用 Zola 自带的分页器(paginator)的,但还是放弃了。因为 paginator 提取用于分页的列表的过程是干涉不了的,就目前版本而言我不能先把页面过滤好再喂给分页器,而只能在分页完成之后过滤;这样就导致分页实际还是按索引到的所有文章来分的,结果是每一页显示的文章数目会不尽相同,极端时甚至不显示。
放弃分页的方法意味着更早的、标注了 pinned 的文章是怎么也没法显示在首页了。不过这无所谓。五篇应该很够了。
具体的实现呢,只是把 paginator.pages
换回了 section.pages
。以及,加了个全局变量作为 counter,在循环时如果已经放上了5篇文章就结束。
我修改的这个模板迟早要开源……可是我想还得经历很多步骤,
- 整理样式,去掉冗余部分,裁剪和重写不是我写的部分
- 模块化,提供多种选择
- 在那之前总之在使用过程中慢慢 debug。
然后还得起个好名字呢。
但是在弄这个模板的事情之前,我得把 hugo-xmin 主题迁移到 Zola。
合适的希腊文衬线字体 (04-16)
我不会古希腊语,我只是在帮人排版的时候碰到这个问题。
实际是三天前的事情。我们知道(古)希腊文的 Unicode 表示还挺混乱的……多数带附加符号的字母有自己的码位,这很正常;不正常的是,当字母需要组合附标的时候,使用的 acute, grave, macron 等附标字符是和拉丁字母区共用的。很多字体没有想到希腊字母区这么随便,就没有专门做对应的组合情况的微调,导致这样的情况显示得很难看。就连老牌的 Gentium 系列字体都如此……所以那天我找了很久,看有没有显示效果合适的、免费的(最好还是开源的)希腊文衬线字体。无衬线字体里 Roboto 还不错;我其实喜欢 Inter 多过 Roboto 的,不过 Inter 毕竟没有 Roboto 老辣,也属于没有考虑到这层的字体之列。
Noto Serif 是支持的,但对于印刷来说有点丑了,而且行高太大。Times 类的专有字体不考虑,可是平替的 STIX Two Text 对 Polytonic Greek 的支持就是瘸腿的……
嘛,我尝试了有 EB Garamond,Roboto Serif 等等,都不是很合适。寻找的过程也许没有必要进一步说,总之我找到了 Galatia SIL:
唔姆,还是希腊式衬线,甚好!关于希腊式衬线,Minion 的网页有直观的例子。简单说就是因为传统上握笔时的笔尖角度不同导致的衬线形态和笔画粗细的方向不同。
它的西文部分是 Times 式的,也不错。
有趣的 Rust parser 库:Chumsky (04-16)
同样是三四天前看到的,还是该记录一下。
作者说这个库的主要目标是易用性,即使是基于组合子的。易用性包括 API 的设计、运行时的错误提示(这个是重头戏)、友好的文档。为了易用性可以牺牲一部分性能。
然后名字也满有意思的。
自制标记语言的二三想法 (04-16)
前略,不过我还是先用基于 PEG 的 Pest 做东西吧。之前让大语言模型帮忙写了基础的规则,姑且 parser 部分能跑了,接下来还是得从头看一下 PEG 以及其他例子,以及实现转换的过程。我设计的时候脑子里就禁不住想边缘情况,反正肯定要抽成几层()或者只抽一两层然后让 macro 发挥作用。
近日有一些命名这门新标记语言的想法,比如 Macro Markup,也许扩展名用 .mmu
,现在似乎没什么地方在用。或者 Macro Text Markup (.mtm
) 或者别的什么,因为都打算切开兼容 Markdown 的部分了也就不敢在名字上碰瓷 Markdown 了……
嘶,脑子里飞过一条 Macrodown。一搜有人用了这个名字,是 fork1 的 SATySFi。我上个月才读到关于 SATySFi 的东西(因为最近出了 Typst 所以又被人提起了),日本人确实有想法的。但一不小心就要变成符号学大师了,作为标记语言这样是否有点()
我的选择大概只会是用 \
做命令的控制符号吧。我的想法是,\{{命令标识符}}
只作为语法糖存在,实际会展开成一个函数调用,或者在第一轮 parse 变成中间形式。至于这个中间形式(以及前面语法糖的参数写法)我想用类似 Shell 的写法,或者干脆是 Nushell 的写法。毕竟 Shell 的写法是久经考验的高速写法……标记语言要的就是快。比如
\foo[bar --baz 123 --bob alice]{foobarfoobar}
等于这样的 Nushell 调用:
foo bar --baz 123 --bob alice --text-body "foobarfoobar"
没有像 Tera 模板那样强制出现的引号、参数名之类的了。
即使参数有空格也不用担心,可以这么处理:
def ruby [
...rubies: string
--text-body: string
] {
$text_body | split chars | each {{char: $in}} |
merge ($rubies | each {{ruby: $in}}) | # 唔姆,结构化数据,甚好!
each {|e| $"($e.char)<rp>\(</rp><rt>($e.ruby)</rt><rp>\)</rp>"} | str join |
'<ruby>' + $in + '</ruby>'
}
上述可以直接在 Nushell 里跑通。下面是假想的标记语言中的情况:
$ \ruby[pīn yīn]{拼音}
<ruby>拼<rp>(</rp><rt>pīn</rt><rp>)</rp>音<rp>(</rp><rt>yīn</rt><rp>)</rp></ruby>
效果:
拼音
当然,也许内部还可以有中间的对 XML 的抽象表示方法。……或许真得像 SATySFi 那样再加一组符号,比如说用 +
引导 XML 节点。
姑且把 The SATySFi Book 下下来了。这网站居然还得用 Pixiv 登录。
SATySFi 是用 OCaml 实现的,Rust 算是 OCaml 的子辈,Nushell 则是孙子辈了。还流着 ML 的血但已经不是符号学大师了,至少目前我看不到比套用 Nushell 这套语法和解释器更美的选择。
考虑的XML抽象之一:
def tag [
tag: string
content: string
--class (-c): list
--id (-i): string
--attr (a): record
]
那么上述的就可以改成
def ruby [
...rubies: string
--text-body: string
] {
# opening/closing <rp>
let rp_o = (tag rp '(')
let rp_c = (tag rp ')')
# assume ruby text to be added upon each char in text content
# text content -> list -> table
$text_body | split chars | each {{char: $in}} |
# merge with table of ruby text, assuming each are correspondent
merge ($rubies | each {{ruby: $in}}) |
# for each row of table, join the pair of char and ruby text
# If output is not HTML, $rp_o, $rp_c would be empty string
each {|e| $e.char + $rp_o + (tag rt $e.ruby) + $rp_c} | str join |
# Actual output would vary for different formats
tag ruby $in
}
ls | sort-by extension
, in Nushell (04-21)
Even ls --long
in Nushell don’t have a column for file extension, and the type
column only has file
and dir
. It’s okay for POSIX-compliant stuff, but in case we need it, we can sort by file extensions with
ls | insert extension {|c| $c.name | path parse | get extension } | sort-by extension
We can avoid assigning “extension” to directories by 1) using a filter beforehand or 2) remove any assigned ones thereafter. For better consistency, a possible option is to pick out the directories at first (if any), and insert them back to the top of the table afterwards.
Note that the behavior don’t align with that in a visual or command-line file explorer, for
path parse
takes the part after the final dot as the extension, so forfoo.tar.gz
it only takesgz
.- Apparently, it ignores magic number, XML filetype declaration vel sim., where decent file explorers like Dolphin and Broot don’t.
Note that clickable links (and colors) won’t be preserved: they are removed once they undergo a table operation.
A strange thing they didn’t choose to remove it on pipe: find
and then get
would yield ansi-colored string (i.e. with control characters) to stdout. This is mostly harmless, but unlike rg
, they are retained on pipe and (seemingly) impossible to remove within the shell.
更新:我错了,有 ansi strip
。
词源漫步:破天連 (04-23)
看动画听到的“破天連”这个词,感觉就像外来词,查了一下果然是。是葡语的 padre。这个尾音很可能加得没什么道理可说吧,但和拉丁语的宾格形式 patrem 倒是正好相合了,而且テ还是清辅音开头。但バ还是浊辅音开头呢,要假设存在一些额外的关联可没有充足的证据。总之这不多说。
padre 还借到了印地语里。印地语本身对神职人员的说法之一,Wiktionary 说是 पुरोहित (purohit)。这来自梵语的 purohita,来自 puras-hita 的连读音变(sandhi)。Wiktionary 说 hita 是动词 hinoti 的过去被动分词(对应拉丁语完成被动分词)形式,来自词根 √hi;可是 Monier-Williams 的梵语词典说 hita 与 dhita 是一样的,来自词根 √dhā(动词 dadhāti)。Wiktionary 没有 dhita 的单独条目,但出现在原始印欧语 *dh₃tós 的后代词汇列表里,和拉丁语的 datus 同源。那么 purohita 就该对应成 praeditus 了吗……“endowed, gifted, possessed of”,好像是这个意思。
……但不对劲。datus 是动词 dare 的完成被动分词,而 dare 在梵语中的对应是 √dā 词根的 dadāti!dadhāti 要对应拉丁语的 facere,虽然意思上多多少少有一些相似之处。我想总不会是异干互补,或许是刚好同型了。我现在困得不想查了……
总之保留了一种可能,是可以对应 praefectus,英语的 prefect。好像也很合理。
至于真的是来自 hinoti 的那种解释,似乎在拉丁语里也找不到同源词(PIE *ǵʰeyt- “dart, projectile”),就不管了。
Nushell 的 ansi
;ansi-to-html
(04-24)
Nushell 的 ansi
系列命令可以在控制台输出带有颜色或字体样式的字符,或者带有链接的字符串。
Node 的 ansi-to-html
可以把带有 ANSI 样式的字符串转成 HTML span。组合起来……
> 'Italic-crimson-to-blue' | ansi gradient -a '0xdc143c' -b '0x0062ac' | (ansi i) + $in | ansi-to-html
<i><span style="color:#dc143c">I<span style="color:#d21740">t<span style="color:#c81a45">a<span style="color:#be1e4a">l<span style="color:#b42150">i<span style="color:#aa2555">c<span style="color:#a02859">-<span style="color:#962c5e">c<span style="color:#8c2f64">r<span style="color:#823369">i<span style="color:#77366e">m<span style="color:#6e3b74">s<span style="color:#643e78">o<span style="color:#59417d">n<span style="color:#504582">-<span style="color:#464888">t<span style="color:#3b4c8d">o<span style="color:#314f91">-<span style="color:#275396">b<span style="color:#1d569c">l<span style="color:#135aa1">u<span style="color:#095da6">e</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></i>
Italic-crimson-to-blue
当然,这在样式和标记的语义上不如直接用 CSS linear-gradient
好;可是 linear-gradient
需要一定的技巧(比如 color: transparent; background-clip: text;
)而且在比如〇信公〇号这样落后于W3C标准的封闭平台,在大家都不讲语义化的地方,还是这样用用方便,哪怕未必合适。网络上的工具网站也能做到类似的显示效果(当然,一般不会像这个粗暴的转换结果一样是树状的嵌套,而是线性排布的若干 span);那些当然干净些、原理上不用这么绕弯。但这下我可以在命令行里做到这点了。总之增加了一个可能只在我的工具链里有用的小技巧。
顺便 ansi-to-html
来自 npm i -g ansi-to-html
。
notify-send
(04-28)
Nushell 0.79 新增了 std 库,其中就有 clip
。我也写过类似的,它这个增加了复制后的提示和系统通知。系统通知要用到 notify-send
,然后我发现我这居然没有预装,不知道是 Kubuntu 的原因还是 Ubuntu 就没有。
总之 sudo apt install libnotify-bin
了。
脚注
我就不喜欢叫“复刻”。但凡有个好点的中文译名呢。↩︎