AstroJS と Expressive Code でシンタックスハイライトを表示する

heroImage

1. はじめに

AstroJS では、デフォルトで ShikiJS とPrismJS が組み込まれているため、追加のパッケージをインストールすることなく、Markdown 内のコードブロックでシンタックスハイライトを表示させることが出来ます。しかし、タイトルやマーカー、コピーボタンを表示されるには、追加でパッケージをインストールしたり、コードを追加しなくてはなりません。

Expressive Code は、シンタックスハイライトに加えて、タイトルやマーカー、コピーボタンの表示など、コードブロックを強化する様々な機能を提供しているパッケージです。本記事では、AstroJS と Expressive Code をインテグレーションする方法と簡単な使い方について記述します。また、本記事は Node.js と Yarn がインストールされている前提で記述しています。

Terminal window
1
$ node -v
2
v20.11.0
3
$ yarn -v
4
1.22.21

2. インストール

AstroJS と Expressive Code をインテグレーションする方法は簡単です。Expressive Code が公開しているインストールガイド 1 に従って、[1] yarn create astro コマンドと [2] yarn astro add astro-expressive-code コマンドを実行します。既に AstroJS プロジェクトが存在している場合は yarn create astro コマンドを省略してください。

Terminal window
1
$ yarn create astro
2
yarn create v1.22.21
3
[1/4] Resolving packages...
4
[2/4] Fetching packages...
5
[3/4] Linking dependencies...
6
[4/4] Building fresh packages...
7
8
success Installed "create-astro@4.7.2" with binaries:
9
- create-astro
10
[########################################] 40/40
11
astro Launch sequence initiated.
12
13
dir Where should we create your new project?
14
./wandering-wasp
15
16
tmpl How would you like to start your new project?
17
Use blog template
18
19
ts Do you plan to write TypeScript?
20
Yes
21
22
use How strict should TypeScript be?
23
Strict
24
25
deps Install dependencies?
26
Yes
27
28
git Initialize a new git repository?
29
No
30
Sounds good! You can always run git init manually.
31
32
Project initialized!
33
Template copied
34
TypeScript customized
35
Dependencies installed
36
37
next Liftoff confirmed. Explore your project!
38
39
Enter your project directory using cd ./wandering-wasp
40
Run yarn dev to start the dev server. CTRL+C to stop.
41
Add frameworks like react or tailwind using astro add.
42
43
Stuck? Join us at https://astro.build/chat
44
45
╭─────╮ Houston:
46
Good luck out there, astronaut! 🚀
47
╰─────╯
48
$ cd terrestrial-trappist/
49
$ yarn astro add astro-expressive-code
50
yarn run v1.22.21
51
warning package.json: No license field
52
$ astro add astro-expressive-code
53
astro-expressive-code is not an official Astro package. Use at your own risk!
54
Continue? yes
55
Resolving with third party packages...
56
02:54:07
57
Astro will run the following command:
58
If you skip this step, you can always run it yourself later
59
60
╭─────────────────────────────────────────╮
61
yarn add astro-expressive-code@^0.32.4
62
╰─────────────────────────────────────────╯
63
64
Continue? yes
65
Installing dependencies...
66
02:54:09
67
success Configuration up-to-date.

マニュアルでインストールする場合は、astro-expressive-code パッケージをインストールして、astro.config.mjs に以下のコードを追加すれば完了です。

Terminal window
1
$ yarn add astro-expressive-code
astro.config.mjs
1
import { defineConfig } from 'astro/config'
2
import expressiveCode from 'astro-expressive-code'
3
4
export default defineConfig({
5
integrations: [expressiveCode()],
6
})

3. 基本的な使い方

``` でコードを囲うことで、コードブロックが表示されます。また、言語を指定することで、シンタックスハイライトが表示されます。下記の例では JavaScript を指定していますが、その他に対応している言語に関しては、ShikiJS の README 2 を参照ください。Expressive Code では、デフォルトでコピーボタンは付与されるので、ユーザーはマウスオーバーして表示されるボタンをクリックすることで、コードを簡単にコピーすることが出来ます。また、オプションコードを追記することで、タイトルとマーカーを表示させることが出来ます。

*.md
1
```js title="line-markers.js" del={2} ins={3-4} {6}
2
function demo() {
3
console.log('this line is marked as deleted')
4
// This line and the next one are marked as inserted
5
console.log('this is the second inserted line')
6
7
return 'this line uses the neutral default marker type'
8
}
9
```
line-markers.js
1
function demo() {
2
console.log('this line is marked as deleted')
3
// This line and the next one are marked as inserted
4
console.log('this is the second inserted line')
5
6
return 'this line uses the neutral default marker type'
7
}

上記の例では行単位でマーカーを表示させていますが、Expressive Code では、文字単位でマーカーを表示させることも出来ます。

*.md
1
```js "return true;" ins="inserted" del="deleted"
2
function demo() {
3
console.log('These are inserted and deleted marker types')
4
// The return statement uses the default marker type
5
return true
6
}
7
```
1
function demo() {
2
console.log('These are inserted and deleted marker types')
3
// The return statement uses the default marker type
4
return true
5
}

また、Expressive Code では、言語に Bash や PowerShell などのスクリプト言語を設定すると、自動的にフレームがターミナル風のものに差し替えられます。オシャレで素敵ですね。ちなみに、本ブログサイトで表示される macOS 風ターミナルフレームは、ろぼいん氏のブログ記事 3 を参考にカスタマイズしています。

1
```bash
2
echo "This terminal frame has no title"
3
```
4
5
```powershell title="PowerShell terminal example"
6
Write-Output "This one has a title!"
7
```
Terminal window
1
echo "This terminal frame has no title"
PowerShell terminal example
1
Write-Output "This one has a title!"

上記で挙げた例は、Expressive Code が提供している機能の一部です。更に詳しい機能や仕様を知りたい方は、Expressive Code の公式ドキュメント 4 を参照ください。

4. 行番号を表示する

Expressive Code は、デフォルトで行番号を表示する機能が組み込まれていません。ですが、公式のプラグインを使用することで、行番号を表示させることが出来ます。まずは、公式ドキュメント 5 に従って、プラグインをインストールします。

Terminal window
1
$ yarn add @expressive-code/plugin-line-numbers

次に、astro.config.mjs にコードを追記して、プラグインを読み込みます。

astro.config.mjs
1
import { defineConfig } from 'astro/config'
2
import astroExpressiveCode from 'astro-expressive-code'
3
import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers'
4
5
export default defineConfig({
6
integrations: [
7
astroExpressiveCode({
8
plugins: [pluginLineNumbers()],
9
}),
10
],
11
})

これで、行番号がデフォルトで表示されるようになります。また、行番号を非表示にしたい場合は、showLineNumbers=false を追記することで可能です。

1
```js
2
console.log('Greetings from line 2!')
3
console.log('I am on line 3')
4
```
5
6
```js showLineNumbers=false
7
console.log('Hello?')
8
console.log('Sorry, do you know what line I am on?')
9
```
1
console.log('Greetings from line 2!')
2
console.log('I am on line 3')
console.log('Hello?')
console.log('Sorry, do you know what line I am on?')

開始行番号を変更したい場合は、startLineNumber=N を追記することで変更可能です。

1
```js showLineNumbers startLineNumber=5
2
console.log('Greetings from line 5!')
3
console.log('I am on line 6')
4
```
5
console.log('Greetings from line 5!')
6
console.log('I am on line 6')

行番号をデフォルトで非表示にしたい場合は、astro.config.mjs に以下のコードを追加することで可能です。

astro.config.mjs
1
import { defineConfig } from 'astro/config'
2
import astroExpressiveCode from 'astro-expressive-code'
3
import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers'
4
5
export default defineConfig({
6
integrations: [
7
astroExpressiveCode({
8
plugins: [pluginLineNumbers()],
9
defaultProps: {
10
showLineNumbers: false,
11
},
12
}),
13
],
14
})

更に詳しい情報については、Line Numbers Plugin の公式ドキュメント 5 を参照ください。

5. おわりに

Expressive Code は、PrismJS に追加パッケージをインストールして、CSS をチクチク書いていた頃と比較すると、コマンド一発で全てが揃うのは革命的に便利です。

唯一惜しいところは、行番号を表示させる機能が実装されていない点です。ですが、現在進行形で議論 6 が進んでいます。そのため、近い将来に実装されると思います。

2024-02-22 追記:2024-02-21 に Expressive Code から行番号を表示する公式プラグインの Line Numbers がリリースされました。それに伴い、Line Numbers に関する記述も追加しました。


  1. Expressive Code, Installing Expressive Code:https://expressive-code.com/installation/

  2. GitHub, ShikiJS, tm-grammars:https://github.com/shikijs/textmate-grammars-themes/blob/main/packages/tm-grammars/README.md

  3. Markdownでリッチなコードブロックを実現する「Expressive Code」:https://roboin.io/article/2023/12/16/how-to-use-expressive-code-in-markdown-and-astro/

  4. Expressive Code:https://expressive-code.com/

  5. Expressive Code, Line Numbers:https://expressive-code.com/plugins/line-numbers/ 2

  6. GitHub, Feature: Number of Lines, Issue #37:https://github.com/expressive-code/expressive-code/issues/37