Автоматическое выделение не работает для некоторых блоков кода

Это происходит в моей локальной среде разработки, на живом форуме Discourse https://discourse.gohugo.io/ и в песочнице Discourse.

В целом, когда у fenced-блока кода не указан язык, срабатывает автоопределение. В обычном использовании Highlight.JS (в Node.js или браузере) это всегда успешно завершается, выбирая какой-либо язык.

Кажется, Discourse сохраняет такие блоки как <code class="lang-auto">, что не является валидным языком :wink:

Я пообщался с AI-ботом ask.discourse.cm…30386:
on сказал, что вы делаете некоторую магию ВРЕМЯ ВЫПОЛНЕНИЯ, удаляя “lang-auto”, а затем позволяете highlight.js снова выполнить автоопределение. Похоже, что это обновление не всегда происходит ДО того, как highlight.JS обрабатывает код. Таким образом, это выглядит как особенность интеграции highlight.js и реализации автоопределения в Discourse.

Сброс языка по умолчанию также не поможет, потому что тогда “удаление lang-auto” не сработает, и похоже, что способ Discourse не перезапускает автоопределение.

  • ручное указание языка работает всегда — как для встроенных, так и для пользовательских (шаблоны Hugo) языков, добавленных через PluginAPI (registerHLJSLanguage) как компонент темы.
  • без указания языка происходит сбой в зависимости от гонки состояний content() и таймингов.

Установка языка по умолчанию в “text” не подойдет, потому что мы хотим, чтобы он подсвечивался, и нам нужно автоопределение для удобства (и оно работает…).

Вот пример Markdown, где второй блок кода не работает (конечно, только если язык по умолчанию установлен в “auto”). Легко воспроизводится на https://try.discourse.org/

и в течение 24 часов: Failed Discourse Autodetection breaks rendering of fenced code blocks - support - Discourse Demo

# Это работает

```
{{ $currentPagemd5 := md5 $currentPage.File.Path }}
    {{ $currentPagemd5ext := (print $currentPagemd5 ".json")}}
```

# Это не сработало и назначило "lang-auto"

```
{{ $currentPage := . }}
{{ $jsonFile := "" }}
{{ with $currentPage.File }}
    {{ $currentPagemd5 := md5 $currentPage.File.Path }}
    {{ $currentPagemd5ext := (print $currentPagemd5 ".json")}}
    {{ $files := readDir "data/commits/" }}
    {{if gt (len $files ) 0}}
        <div class="bord-bas"></div>
        <div>
        <details>
            <summary>Изменения на странице</summary>
            <div>
            {{ range $files }}
                {{ if eq .Name $currentPagemd5ext }}
                    {{ $jsonFile := $currentPagemd5 }}
                    {{ $data := index $.Site.Data.commits $jsonFile }}
                    <ul>
                    {{ range $data }}
                        <li>
                            {{ dateFormat "02/01/2006" .commit_date }} : {{ trim .message "\n" }} ({{ .author }})
                        </li>
                    {{ end }}
                    </ul>
                {{ end }}
            {{ end }}
            </div>
        </details>
        </div>
    {{ end }}
{{ end }}
```

Возможно, дело просто в том, что Discourse и HighlightJS не могут распознать язык, поэтому и отображают его таким образом.

здесь акцент делается на Discourse и Highlight.JS

  • Highlight.JS самостоятельно всегда распознает язык и выбирает его

  • В Discourse же без атрибута lang язык не всегда распознается во время выполнения.

Форум Hugo: пост 6 темы 57307:

Вот пост из форума: Proposal: Add highlighting support for Go/Hugo templates to Discourse - #6 by irkode - Meta - HUGO

  • первый блок кода начинается с ```hugo-html.
    это дает <code="lang-hugo-html>
  • второй блок начинается с ```
    это дает <code=“lang-auto”>

в обоих случаях подсветка работает корректно.

Форум Hugo: пост 2 темы 57367:

А вот еще один пример, где это не работает: How to capture/generate revisions of page? - #2 by Welsh - support - HUGO

здесь также назначается “lang-auto”, но автоматическое распознавание во время выполнения не работает.

Похоже, это связано с реализацией Discourse — возможно, зависит от содержимого из-за таймаутов, промисов и т.д.

Возможно, я неправильно понимаю, но вот что я вижу по первой ссылке, которую вы опубликовали:

Ни в одном из случаев не указано lang-auto, и оба блока подсвечены одинаковым образом, хотя для второго блока кода вы не указали язык.

Это консоль разработчика — она показывает код после того, как highlight.js успешно выполнил автоматическое определение языка.

Вам нужно посмотреть на источник страницы (Ctrl+u), где вы увидите lang-auto.

Затем сработает механизм автоматического подсвечивания Discourse, который удалит lang-auto и попытается определить язык заново. Проверьте второе сообщение, на которое я дал ссылку: там ситуация аналогична, но определение не срабатывает.

И да — без фреймворка Discourse это работает.

При переходе на чистый Highlight.JS:

  • код, заключённый в <code class="lang-auto">, не будет подсвечиваться, если у нас нет грамматики для “auto” :wink:

  • мы могли бы перезапустить автоматическое определение для тех, кто использует плагин:

    hljs.addPlugin({
       'before:highlight': (ctx) => {
          if (ctx.language === 'auto') {
             result = hljs.highlightAuto(ctx.code);
             ctx.language = result.language
             ctx.result = result
          }
       }
    });
    

Мне не удалось заставить это работать в Discourse из-за способа интеграции плагинов и грамматик с API, а также из-за изоляции DOM в движке и методах highlight.js

1 лайк