带有 Rouge 和 KaTeX 的 Jekyll 不能在代码中有 $
Jekyll with Rouge and KaTeX cannot have $ in code
我正在创建一个新的 Jekyll 博客设置,我想在其中自行托管并生成服务器端的一切(所以基本上除了 Disqus 和 Google Analytics 之外的一切)。我希望我的网站即使在关闭 JS 的浏览器上也能正常运行,这就是为什么我转向 Kramdown+Rouge 进行语法高亮和 KaTex 用于在网站生成过程中渲染 TeX 公式。
不过我发现了一个问题。当我有这样的例子时:
```bash
$ echo test
test
```
它会在 KaTeX 命令内部中断:
{% katexmm %}
{{ content }}
{% endkatexmm %}
我找到原因了:
- rouge 将片段变成类似
<span class="gp">$</span>
的内容
katexmm
期望每个 $
与另一个 $
配对或转义为 $
我想知道的是如何解决这个问题,例如通过转义 pre
内的所有 $
,但保留其他 $
(旨在用作实际的 LaTeX 片段)完好无损。或者以某种方式配置 jekyll-katex 以忽略未配对的 $
? (throw_error: false
选项在文本已经使用美元符号匹配后起作用,所以它没有帮助)。
我想在配置中修复此问题或代替应用 katexmm
,这样我就不必修改任何 post.
的内容
我设法通过从 jekyll-katex
修改 tag 来解决 code
(内联,使用单波浪号)和 pre code
(使用缩进或 3 个波浪号):
# frozen_string_literal: true
require 'jekyll'
require 'jekyll-katex/configuration'
require 'jekyll-katex/katex_js'
require 'nokogiri'
module Jekyll
module Tags
# Defines the custom Liquid tag for compile-time rendering of KaTeX math.
# This differs from the katex tag in that it allows use of `$` and `$$` fencing to mark math mode blocks similar to
# standard latex.
# {% katexmm %}
# This is a mixed environment where you can write text as normal but fence off latex math using `$`. Escape
# using `$`. For example.
# $latex math with $$
# $$display mode latex$$
# {% endkatexmm %}
class KatexMathModeFixed < Liquid::Block
LOG_TOPIC = 'KatexMathModeFixed:'
KATEX ||= Jekyll::Katex::KATEX_JS
LATEX_TOKEN_PATTERN = /(?<!\)([$]{2}|[$]{1})(.+?)(?<!\)/m
def initialize(tag_name, markup, tokens)
super
@markup = markup
@tokens = tokens
@display_mode_rendering = Jekyll::Katex::Configuration.global_rendering_options.merge(displayMode: true)
@inline_mode_rendering = Jekyll::Katex::Configuration.global_rendering_options.merge(displayMode: false)
end
def render(context)
enclosed_block = super
fixed_block = fix_code(enclosed_block)
rendered_str = fixed_block.to_s.gsub(LATEX_TOKEN_PATTERN) do |match|
display_mode = match.to_s.start_with? '$$'
rendering_options = display_mode ? @display_mode_rendering : @inline_mode_rendering
Jekyll.logger.debug LOG_TOPIC, "Rendering matched block - #{match}"
KATEX.call('katex.renderToString', Regexp.last_match(2), rendering_options)
end
# KaTeX should fix escaped `$` within fenced blocks, this addresses instances outside of math mode
rendered_str.to_s.gsub(/\[$]/, '$').to_s
end
def fix_code(input)
updated = false
html = Nokogiri::HTML.fragment(input)
Jekyll.logger.debug LOG_TOPIC, "Fixing - #{input}"
html.css("code, code span").each do |c|
if c.css('*').empty? && c.content['$']
updated = true
Jekyll.logger.debug LOG_TOPIC, "current tag - #{c}"
content = c.content
content['$'] = '$'
c.content = content
Jekyll.logger.debug LOG_TOPIC, "current tag now - #{c}/#{content}"
end
end
output = html.to_s
Jekyll.logger.debug LOG_TOPIC, "Fixed - #{output}"
if updated then html.to_s else input end
end
end
end
end
Liquid::Template.register_tag('katexmmx', Jekyll::Tags::KatexMathModeFixed)
它可以安装在 _plugins
目录中。
问题是,这仍然存在问题 - 默认情况下,kramdown 仍会尝试使用 mathjax 引擎并生成 <script type="math/tex">
,因此必须进行更改。当我调查如何时,我发现 kramdown 也支持 math_engine: katex
- 这样我只需要添加字体和 CSS,并且 jekyll-katex
变得完全过时(以及我的解决方法,如果有人好奇,我会离开这里)。
我正在创建一个新的 Jekyll 博客设置,我想在其中自行托管并生成服务器端的一切(所以基本上除了 Disqus 和 Google Analytics 之外的一切)。我希望我的网站即使在关闭 JS 的浏览器上也能正常运行,这就是为什么我转向 Kramdown+Rouge 进行语法高亮和 KaTex 用于在网站生成过程中渲染 TeX 公式。
不过我发现了一个问题。当我有这样的例子时:
```bash
$ echo test
test
```
它会在 KaTeX 命令内部中断:
{% katexmm %}
{{ content }}
{% endkatexmm %}
我找到原因了:
- rouge 将片段变成类似
<span class="gp">$</span>
的内容
katexmm
期望每个$
与另一个$
配对或转义为$
我想知道的是如何解决这个问题,例如通过转义 pre
内的所有 $
,但保留其他 $
(旨在用作实际的 LaTeX 片段)完好无损。或者以某种方式配置 jekyll-katex 以忽略未配对的 $
? (throw_error: false
选项在文本已经使用美元符号匹配后起作用,所以它没有帮助)。
我想在配置中修复此问题或代替应用 katexmm
,这样我就不必修改任何 post.
我设法通过从 jekyll-katex
修改 tag 来解决 code
(内联,使用单波浪号)和 pre code
(使用缩进或 3 个波浪号):
# frozen_string_literal: true
require 'jekyll'
require 'jekyll-katex/configuration'
require 'jekyll-katex/katex_js'
require 'nokogiri'
module Jekyll
module Tags
# Defines the custom Liquid tag for compile-time rendering of KaTeX math.
# This differs from the katex tag in that it allows use of `$` and `$$` fencing to mark math mode blocks similar to
# standard latex.
# {% katexmm %}
# This is a mixed environment where you can write text as normal but fence off latex math using `$`. Escape
# using `$`. For example.
# $latex math with $$
# $$display mode latex$$
# {% endkatexmm %}
class KatexMathModeFixed < Liquid::Block
LOG_TOPIC = 'KatexMathModeFixed:'
KATEX ||= Jekyll::Katex::KATEX_JS
LATEX_TOKEN_PATTERN = /(?<!\)([$]{2}|[$]{1})(.+?)(?<!\)/m
def initialize(tag_name, markup, tokens)
super
@markup = markup
@tokens = tokens
@display_mode_rendering = Jekyll::Katex::Configuration.global_rendering_options.merge(displayMode: true)
@inline_mode_rendering = Jekyll::Katex::Configuration.global_rendering_options.merge(displayMode: false)
end
def render(context)
enclosed_block = super
fixed_block = fix_code(enclosed_block)
rendered_str = fixed_block.to_s.gsub(LATEX_TOKEN_PATTERN) do |match|
display_mode = match.to_s.start_with? '$$'
rendering_options = display_mode ? @display_mode_rendering : @inline_mode_rendering
Jekyll.logger.debug LOG_TOPIC, "Rendering matched block - #{match}"
KATEX.call('katex.renderToString', Regexp.last_match(2), rendering_options)
end
# KaTeX should fix escaped `$` within fenced blocks, this addresses instances outside of math mode
rendered_str.to_s.gsub(/\[$]/, '$').to_s
end
def fix_code(input)
updated = false
html = Nokogiri::HTML.fragment(input)
Jekyll.logger.debug LOG_TOPIC, "Fixing - #{input}"
html.css("code, code span").each do |c|
if c.css('*').empty? && c.content['$']
updated = true
Jekyll.logger.debug LOG_TOPIC, "current tag - #{c}"
content = c.content
content['$'] = '$'
c.content = content
Jekyll.logger.debug LOG_TOPIC, "current tag now - #{c}/#{content}"
end
end
output = html.to_s
Jekyll.logger.debug LOG_TOPIC, "Fixed - #{output}"
if updated then html.to_s else input end
end
end
end
end
Liquid::Template.register_tag('katexmmx', Jekyll::Tags::KatexMathModeFixed)
它可以安装在 _plugins
目录中。
问题是,这仍然存在问题 - 默认情况下,kramdown 仍会尝试使用 mathjax 引擎并生成 <script type="math/tex">
,因此必须进行更改。当我调查如何时,我发现 kramdown 也支持 math_engine: katex
- 这样我只需要添加字体和 CSS,并且 jekyll-katex
变得完全过时(以及我的解决方法,如果有人好奇,我会离开这里)。