一部のフェンストコードブロックで自動ハイライトが失敗する

この問題は私の開発環境、本番の Discourse フォーラム https://discourse.gohugo.io/、および Discourse プレイグラウンドで発生しています。

一般的に、フェンシングコードブロックに言語が設定されていない場合、自動検出が行われます。通常の Highlight.JS の使用(Node.js またはブラウザ)では、常に何らかの言語を選択することで成功します。

Discourse はこのようなブロックを <code class="lang-auto"> として保存するようです。これは有効な言語ではありません :wink:

私は AI-Bot ask.discourse.cm…30386 と話しました:
彼によると、Discourse はランタイム時に “lang-auto” を削除する処理を行い、その後 highlight.js に自動検出を再実行させる魔法のようなことをしているとのことです。この更新が、highlight.js がコードに触れる前に常に実行されているわけではないようです。これは、Discourse 内の highlight.js 統合と自動検出実装における不具合のように見えます。

デフォルトの言語を解除しても機能しません。なぜなら、その場合 “lang-auto” の削除が機能せず、Discourse の方法では自動検出が再実行されないように見えるからです。

  • 言語を手動で設定すると、常に機能します。これは組み込み言語と、テーマコンポーネントとして PluginAPI (registerHLJSLanguage) を介して追加されたカスタム(Hugo テンプレート)言語の両方に当てはまります。
  • 言語が設定されていない場合、content() の競合状態やタイミングに応じて失敗します。

デフォルトの言語を “text” に設定する方法は採用できません。ハイライト表示を希望しているためです。また、使いやすさのために自動検出を希望しており、それは機能しています…

以下に Markdown の例を示します。2番目のコードブロックが失敗します(もちろん、デフォルトの言語が “auto” に設定されている場合のみ)。https://try.discourse.org/ で以下の Markdown を使用すると簡単に再現できます。

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 フォーラム: 投稿 57307 返信 6:

こちらがフォーラムからの投稿です: Proposal: Add highlighting support for Go/Hugo templates to Discourse - #6 by irkode - Meta - HUGO

  • 最初のコードブロックは ```hugo-html で開始されています。
    これにより <code="lang-hugo-html> が生成されます。
  • 2番目のブロックは ``` で開始されています。
    これにより <code=“lang-auto”> が生成されます。

どちらの場合も、シンタックスハイライトは正しく適用されています。

Hugo フォーラム: 投稿 57367 返信 2:

そして、こちらが機能しない別の例です: How to capture/generate revisions of page? - #2 by Welsh - support - HUGO

ここでも “lang-auto” が割り当てられていますが、実行時の自動検出が機能していません。

これは、Discourse の実装の何らかの側面に起因しているようです — 内容によってタイムアウトやプロミスなどが影響している可能性があります。

もしかしたら私の理解が間違っているかもしれませんが、あなたが投稿した1番目のリンクで私が目にしているのは次の通りです:

どちらも lang-auto を表示しておらず、2番目のコードブロックの言語を指定していないにもかかわらず、両方とも同じようにハイライトされています。

これがデベロッパーコンソールです。highlight.js が自動検出に成功したのコードを表示しています。

ページソース(Ctrl+u)を確認する必要があります。そこに lang-auto が表示されているはずです。

その後、lang-auto を削除して Discourse の自動ハイライト機能を再度試してみてください。私がリンクした2番目の投稿を確認してください。同じ状況ですが、検出が失敗しています。

そして、はい — 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 と統合されている方法、および highlight.js エンジンとメソッドの DOM カプセル化のため、さらにデフォルトの Discourse リブレンダリングとの競合状態が発生する可能性があるため、この方法が動作しませんでした。

「いいね!」 1