Closed15

remark-cli を試す

hankei6kmhankei6km

remote-cms-contnt で Markdown をファイルへ保存するときに remark のプラグインを使いたくなる。

方針としては以下の 2 つが考えられる。

  • nuxt-content のように外部の remark プラグインを利用する設定項目を作る
  • remark-cli を使う

設定項目を作る場合、現時点では ESM と CJS 混在などでの面倒が多そう。
よって、remark-cli を試してみることにする。

hankei6kmhankei6km

インストール

$ mkdir test-remark-cli
$ cd test-remark-cli/
$ npm init -y
$ npm install remark-cli
$ npx remark-cli --version
remark: 14.0.2, remark-cli: 10.0.1
hankei6kmhankei6km

使ってみる

test.md
# テストのファイル

remark-cli のテスト用 Maarkdonw ファイル。

## 整形される様子を確認

段落の区切りを多めにとってみる。



2 つめの段落。

見出しの記述方法
--------

見出しを `---` で記述してみる。

まずは Markdown を 標準入力から渡すだけ

$ npx remark-cli < test.md
# テストのファイル

remark-cli のテスト用 Maarkdonw ファイル。

## 整形される様子を確認

段落の区切りを多めにとってみる。

2 つめの段落。

## 見出しの記述方法

見出しを `---` で記述してみる。
<stdin>: no issues found

表記のゆれ的なものは取り除かれる。
また最後にメッセージが表示される。

結果をリダイレクトする

$ npx remark-cli < test.md > output.md
<stdin>: no issues found
$ cat output.md
# テストのファイル

remark-cli のテスト用 Maarkdonw ファイル。

## 整形される様子を確認

段落の区切りを多めにとってみる。

2 つめの段落。

## 見出しの記述方法

見出しを `---` で記述してみる。

とくに違いはない。
メッセージは stderr に出しているもよう。

ファイルを上書き

入力ファイル名を引数で渡し、-o で出力ファイル名を渡さないと入力ファイルを上書きする(sed -i 的な動作)。

$ npx remark-cli test.md -o
test.md: written
$ cat test.md
# テストのファイル

remark-cli のテスト用 Maarkdonw ファイル。

## 整形される様子を確認

段落の区切りを多めにとってみる。

2 つめの段落。

## 見出しの記述方法

見出しを `---` で記述してみる。
hankei6kmhankei6km

プラグインを使ってみる

手軽なのは --use でプラグイン名を指定。

$ cat test.md
# テストのファイル

プラグインのテスト :dog: :+1: :-)
$ npx remark-cli --quiet --use remark-emoji  < test.md
# テストのファイル

プラグインのテスト 🐶 👍 :-)

オプションはプラグイン名の後に = を付けてから --setting の記法で指定。

$ npx remark-cli --quiet --use 'remark-emoji=emoticon:true'  < test.md
# テストのファイル

プラグインのテスト 🐶 👍 😃
hankei6kmhankei6km

.remarkrc.js でプラグインなどを設定

設定ファイルはいくつか記述方法がある

とりあえず .remarkrc.js で設定。

.remarkrc.js
import emoji from 'remark-emoji'

const remarkConfig = {
  plugins: [
    [emoji, {emoticon: true}]
  ]
}

export default remarkConfig

これを実行するには package.json"type": "module" が必要。

$ npx remark-cli --quiet < test.md
# テストのファイル

プラグインのテスト 🐶 👍 😃
hankei6kmhankei6km

tree での出力

$ npx remark-cli --quiet --tree-out < test.md > output.json
output.json
{
  "type": "root",
  "children": [
    {
      "type": "heading",
      "depth": 1,
      "children": [
        {
          "type": "text",
          "value": "テストのファイル",
          "position": {
            "start": {
              "line": 1,
              "column": 3,
              "offset": 2
            },
            "end": {
              "line": 1,
              "column": 11,
              "offset": 10
            }
          }
        }
      ],
      "position": {
        "start": {
          "line": 1,
          "column": 1,
          "offset": 0
        },
        "end": {
          "line": 1,
          "column": 11,
          "offset": 10
        }
      }
    },
    {
      "type": "paragraph",
      "children": [
        {
          "type": "text",
          "value": "プラグインのテスト 🐶 👍 😃",
          "position": {
            "start": {
              "line": 3,
              "column": 1,
              "offset": 12
            },
            "end": {
              "line": 3,
              "column": 19,
              "offset": 30
            }
          }
        }
      ],
      "position": {
        "start": {
          "line": 3,
          "column": 1,
          "offset": 12
        },
        "end": {
          "line": 3,
          "column": 19,
          "offset": 30
        }
      }
    }
  ],
  "position": {
    "start": {
      "line": 1,
      "column": 1,
      "offset": 0
    },
    "end": {
      "line": 4,
      "column": 1,
      "offset": 31
    }
  }
}

hankei6kmhankei6km

tree での入力

$ npx remark-cli --quiet --tree-out < test.md | npx remark-cli --quiet --tree-in
# テストのファイル

プラグインのテスト 🐶 👍 😃
hankei6kmhankei6km

jq で見出しの 2 と 3 だけにする

grep も少しだけ使う(空行の除去)。

test.md
# テストのファイル

## 見出し 2-1

段落

### 見出し 3-1

段落

#### 見出し 3-1

段落

### 見出し 3-2

```markdown
## コードブロック内の見出し 2-1

段落

### コードブロック内の見出し 3-1
```

見出し 2-2
----------

段落

## おわりに

段落
$ npx remark-cli --quiet --tree-out < test.md | jq '.children |=  map(select(.type == "heading" and .depth >=2 and .depth <=3))' | npx remark-cli --quiet --tree-in | grep -v '^$'
## 見出し 2-1
### 見出し 3-1
### 見出し 3-2
## 見出し 2-2
## おわりに
hankei6kmhankei6km

FrontMatter 上手くいかないパターン

test.md
test.md
---
id: preview-zenn-article-toc-in-terminal
title: Zenn 記事の目次をターミナル内でプレビュー
emoji: "\U0001F30A"
type: idea
topics:
  - zenn
  - markdown
  - cli
  - terminal
published: true
---
# テストのファイル

FrontMatter のテスト。
$ npx remark-cli --quiet < test.md
***

id: preview-zenn-article-toc-in-terminal
title: Zenn 記事の目次をターミナル内でプレビュー
emoji: "\U0001F30A"
type: idea
topics:

*   zenn
*   markdown
*   cli
*   terminal
    published: true

***

# テストのファイル

FrontMatter のテスト。
hankei6kmhankei6km

FrontMatter プラグインで対応

$ npm install remark-frontmatter
.remarkrc.js
import emoji from 'remark-emoji';
import remarkFrontmatter from 'remark-frontmatter';

const remarkConfig = {
  plugins: [
    [emoji, {emoticon: true}],
    remarkFrontmatter
  ]
}

export default remarkConfig
$ npx remark-cli --quiet < test.md
---
id: preview-zenn-article-toc-in-terminal
title: Zenn 記事の目次をターミナル内でプレビュー
emoji: "\U0001F30A"
type: idea
topics:
  - zenn
  - markdown
  - cli
  - terminal
published: true
---

# テストのファイル

FrontMatter のテスト。
hankei6kmhankei6km

検討事項

FrontMatter の設定をしていて気が付いたが、
remote-cms-content で利用しているプラグインはおそらくはすべて設定しておく必要がある。
そして「オプションもすべて同一」にする必要がある。

これは少し面倒かな。

hankei6kmhankei6km

確認しておきたいことはできたので、とりずここまで。

hankei6kmhankei6km

remark-directive

:::message などを node にできるのではと思って試してみたが、:::details タイトル は書式が異なっているので paragraph 扱いになる。

https://github.com/micromark/micromark-extension-directive#syntax

.remarkrc.js
import remarkDirective from 'remark-directive';

const remarkConfig = {
  plugins: [
    remarkDirective
  ]
}

export default remarkConfig
test.md
# テスト

:::message
ここにメッセージ
:::

:::details 詳細
ここにメッセージ
:::
$ npx remark --quiet --tree-out < test.md > output.json
実行結果
output.json
{
  "type": "root",
  "children": [
    {
      "type": "heading",
      "depth": 1,
      "children": [
        {
          "type": "text",
          "value": "テスト",
          "position": {
            "start": {
              "line": 1,
              "column": 3,
              "offset": 2
            },
            "end": {
              "line": 1,
              "column": 6,
              "offset": 5
            }
          }
        }
      ],
      "position": {
        "start": {
          "line": 1,
          "column": 1,
          "offset": 0
        },
        "end": {
          "line": 1,
          "column": 6,
          "offset": 5
        }
      }
    },
    {
      "type": "containerDirective",
      "name": "message",
      "attributes": {},
      "children": [
        {
          "type": "paragraph",
          "children": [
            {
              "type": "text",
              "value": "ここにメッセージ",
              "position": {
                "start": {
                  "line": 4,
                  "column": 1,
                  "offset": 18
                },
                "end": {
                  "line": 4,
                  "column": 9,
                  "offset": 26
                }
              }
            }
          ],
          "position": {
            "start": {
              "line": 4,
              "column": 1,
              "offset": 18
            },
            "end": {
              "line": 4,
              "column": 9,
              "offset": 26
            }
          }
        }
      ],
      "position": {
        "start": {
          "line": 3,
          "column": 1,
          "offset": 7
        },
        "end": {
          "line": 5,
          "column": 4,
          "offset": 30
        }
      }
    },
    {
      "type": "paragraph",
      "children": [
        {
          "type": "text",
          "value": ":::details 詳細\nここにメッセージ\n:::",
          "position": {
            "start": {
              "line": 7,
              "column": 1,
              "offset": 32
            },
            "end": {
              "line": 9,
              "column": 4,
              "offset": 58
            }
          }
        }
      ],
      "position": {
        "start": {
          "line": 7,
          "column": 1,
          "offset": 32
        },
        "end": {
          "line": 9,
          "column": 4,
          "offset": 58
        }
      }
    }
  ],
  "position": {
    "start": {
      "line": 1,
      "column": 1,
      "offset": 0
    },
    "end": {
      "line": 10,
      "column": 1,
      "offset": 59
    }
  }
}
このスクラップは2021/12/31にクローズされました