Jekyll с Rouge и KaTeX не может иметь $ в коде

Я создаю новую настройку блога Jekyll, в которой я хочу самостоятельно размещать и генерировать на стороне сервера все, что могу (так в основном все, кроме Disqus и Google Analytics). Я хочу, чтобы мой сайт работал хорошо даже в браузерах с отключенным JS, поэтому я обратился к Kramdown+Rouge для подсветки синтаксиса и KaTex для рендеринга формулы TeX во время генерации сайта.

Я нашел проблему, хотя. Когда у меня есть пример, как:

```bash
$ echo test
test
```

Он сломается внутри команды KaTeX:

{% katexmm %}
{{ content }}
{% endkatexmm %}

Я выяснил причину:

  • Руж превращает фрагмент в нечто вроде <span class="gp">$</span>
  • katexmm расширяет, что каждый $ в паре с другим $ или сбежал как \$

Я хочу знать, как это исправить, например, избегая всех $ внутри pre, но оставив других $ (которые предназначены для использования в качестве фактических фрагментов LaTeX) без изменений. Или, может быть, как-то настроить Jekyll-Katex, чтобы игнорировать непарный $? (throw_error: false Опция работает после того, как текст уже сопоставлен с использованием знаков доллара, поэтому это не помогает).

Я хочу исправить это в конфиге или вместо применения katexmm, чтобы мне не пришлось изменять содержание любого поста.

1 ответ

Решение

Мне удалось избавиться от ошибок, изменив тег jekyll-katex обойти 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})(.+?)(?<!\\)\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 стать полностью устаревшим (а также мой обходной путь, который я оставлю здесь, если кому-то будет любопытно).

Другие вопросы по тегам