Corredor

ウェブ、プログラミングの勉強メモ。

Angular でシンタックスハイライトを実現する ngx-highlightjs

インクルーシブHTML+CSS & JavaScript 多様なユーザーニーズに応えるフロントエンドデザインパターン

インクルーシブHTML+CSS & JavaScript 多様なユーザーニーズに応えるフロントエンドデザインパターン

  • 作者: Heydon Pickering,太田良典,伊原力也,株式会社Bスプラウト
  • 出版社/メーカー: ボーンデジタル
  • 発売日: 2017/11/04
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

Angular アプリ上で、Highlight.js を使用したシンタックスハイライトを実現するために、ngx-highlightjs というライブラリを使った。導入方法がちょっと特殊だったので紹介。

Highlight.js の用意

このラッパーライブラリは、Highlight.js のアセットがないと動作しない。まずは Highlight.js の公式ページより、自分が必要な言語を選択して資材をダウンロードする。

ダウンロードした Zip ファイルを解凍すると、ルートに highlight.pack.js があり、styles ディレクトリに選択した言語の定義ファイルが配置されていることが確認できるはずだ。

コレを Angular アプリの ./src/assets/lib/hljs というディレクトリに配置する。ディレクトリパスは任意のものに変更可能だが、デフォルトでは上述のディレクトリを探そうとする。

ngx-highlightjs の導入

次に ngx-highlightjs を導入する。

$ npm i -S ngx-highlightjs

NgModule に以下のように HighlightModule を追加する。

import { HighlightModule } from 'ngx-highlightjs';

@NgModule({
  imports: [
    HighlightModule.forRoot()
  ]
})
export class AppModule { }

後は、シンタックスハイライトしたいところで以下のように実装する。

<pre [code]="someCode"></pre>
@Component({ /* 省略 */ })
export class ExampleComponent {
  /** サンプルコード */
  public someCode: string = `<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>サンプルコードです</title>
  </head>
  <body>
    <h1>サンプルコードです</h1>
  </body>
</html>`;
}

コレで pre 要素にシンタックスハイライトされた someCode の文字列が表示される。表示する言語は用意したアセットに応じて自動的に判別されるようだ。

アセットの格納先パスの変更方法

Highlight.js の資材をデフォルトの ./src/assets/lib/hljs/ 以外に置いた場合。例えば ./src/assets/highlight-js/ に置いた場合は、HighlightModule.forRoot() の記述部分で以下のようにパスを指定して変更できる。

HighlightModule.forRoot({
  path: 'assets/highlight-js/highlight'
})

./src/ 配下で適当な場所が指定できるようだ。

テーマの変更方法

Highlight.js はシンタックスハイライトのカラーテーマを変更できるが、この ngx-bootstrap でもテーマを指定できる。

やり方はアセットの格納先パスの変更方法と同様、HighlightModule で指定する。

HighlightModule.forRoot({
  theme: 'solarized-light'
})

サブ NgModule での利用方法

HighligheModule は、内部で使用しているディレクティブを exports していないためか、app.module.ts 配下にあるサブの NgModule でも imports してやらないと動かなかった。

ルートモジュール app.module.ts では HighlightModule.forRoot() と指定し、下位のサブモジュールでは HighlightModule とだけ書いて imports しておくことで問題なく動作した。