2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Atomのlinter-markdownを.remarkrcで設定する方法

Last updated at Posted at 2017-03-04

最初に結論から

  • Atomのlinter-markdownプラグインは、内部的にremark-lintを使っている
  • デフォルト設定のまま使うときは、システムへのremark-lintインストールは不要
  • 設定ファイル名は.remarkrc(JSON)または.remarkrc.yaml(YAML)
  • 設定ファイルを作った場合はシステムへのremark-lintインストールが必須
    • プリセットのパッケージremark-preset-lint-consistentremark-preset-lint-recommendedも同時にインストールする
    • インストールはnpmを使ってローカル(.remarkrcと同じ階層)にインストール

インストールコマンドはこんな感じで。

% npm install remark-lint
% npm install remark-preset-lint-consistent
% npm install remark-preset-lint-recommended

JSONが好きな人は.remarkrcを作成

{
  "plugins": [
    "remark-preset-lint-consistent",
    "remark-preset-lint-recommended",
    ["remark-lint-list-item-indent", "space"],
    ["remark-lint-code-block-style", false],
    ["remark-lint-no-shortcut-reference-link", false]
  ]
}

YAMLが好きな人は.remarkrc.yamlを作成

plugins:
- remark-preset-lint-consistent
- remark-preset-lint-recommended
- # 箇条書きリストのインデントは(タブではなく)スペース
  - remark-lint-list-item-indent
  - space
- # Qiitaのコードブロックで警告が出ないように
  - remark-lint-code-block-style
  - false
- # Qiitaの注釈で警告が出ないように
  - remark-lint-no-shortcut-reference-link
  - false

同階層に.remarkrc.remarkrc.yamlが両方存在した場合は両方有効になりますが、設定項目がかぶった場合はJSONの.remarkrcが優先されるようです。

バージョン組み合わせ

Atomのlinter-markdownパッケージのバージョンと、remark-lintのバージョンの組み合わせに要注意です。

この記事を投稿した2017/3/3時点では、linter-markdown 3.1.0がremark-lint 6.0.0に対応しておらず、古いremark-lintをインストールする必要がありました。2017/4/18時点ではlinter-markdownが4.0.0にバージョンアップしており、remark-lintの最新版で動く事を確認済みです。

バージョン組み合わせ OK NG NG NG OK
linter-markdown 4.0.0 3.1.0 3.1.0 3.1.0 3.1.0
remark-lint 6.0.0 6.0.0 5.4.0 5.4.0 5.4.0
remark-preset-lint-consistent 2.0.0 2.0.0 2.0.0 1.0.0 1.0.0
remark-preset-lint-recommended 2.0.0 2.0.0 1.0.0 2.0.0 1.0.0

古いremark-lintのインストールコマンドと設定ファイルの記法も念のため残しておきます。特に設定ファイルの記法は最新版と違うので要注意。

古いバージョンのインストール

% npm install remark-lint@5.4.0
% npm install remark-preset-lint-consistent@1.0.0
% npm install remark-preset-lint-recommended@1.0.0

.remarkrc(古い記法)

{
  "presets": [
    "lint-consistent",
    "lint-recommended"
  ],
  "plugins": {
    "lint": {
      "list-item-indent": "space",
      "code-block-style": false,
      "no-shortcut-reference-link": false
    }
  }
}

.remarkrc.yaml(古い記法)

presets:
  - lint-consistent
  - lint-recommended
plugins:
  lint:
    list-item-indent: space
    code-block-style: false
    no-shortcut-reference-link: false

格闘記録(読み飛ばし可)

例のごとく、上記結論に至るまでの格闘記録を時系列で書きました。
興味があればどうぞ。

プロローグ

Markdown文章は今までMacDownで書いてたんですが、メインエディタのAtomに統一したいなーと思いまして、この記事とか参考に一通りMarkdown用のプラグインを入れました。
[さんざん悩んだマークダウンエディタの最終決定は「Atom」快適に使えるようにする設定と必須のパッケージ 厳選18個]
(http://www.kotalog.net/archives/6038)

ついでならMarkdown用のLinterも入れようと思いlinter-markdownプラグインもインストールしたのですが、その設定でもう果てしなく果てしなくハマってしまいました。特に日本語の情報が少ない少ない。。。

AtomにもLinterにもNode.jsにもMarkdownにもまだ不慣れだったので、これを機に勉強がてらとことんハマって、日本語でQiita記事にまとめておく覚悟を決めたのでした。自分でQiitaに書いたこともなかったですし。

これは壮絶なるエラーとの格闘サーガ三部作、最終話となります!

Episode I
[Titaniumで自動インストールされたnodeやnpmが/usr/local配下に残っていた件] (http://qiita.com/the_red/items/aeee6d328995f557cfbf)
Episode II
[Homebrewでnodebrewのインストールに失敗した時の対処(Perl, CPAN絡み)] (http://qiita.com/the_red/items/fd04d97947b9b0bd7a57)
Anthology
[AtomのLinterでエラー内容をコピペできない時はGitHubの最新版をインストールしよう!] (http://qiita.com/the_red/items/ebbece2411f55450db72)
Episode III
Atomのlinter-markdownを.remarkrcで設定する方法 (本エントリ)

Atomのlinter-markdownと、npmのremark-lint

linter-markdown
このプラグインは、内部的にremark-lintというnpmパッケージを使っているっぽい。スタイルなどの設定変更は、設定ファイル.remarkrcを作成するとのこと。

.remarkrcを作成

Configuring remark-lint
まずはremark-lintのREADMEを読んで、サンプル通りに.remarkrc作ってホームディレクトリに置いてみる。YAMLじゃなくてJSON形式。

{
  "plugins": [
    "remark-preset-lint-recommended",
    ["remark-lint-list-item-indent", false]
  ]
}

するとLinterが動かずエラーになってしまった。
remark1.png

TypeError: name.charAt is not a function
 at resolvePlugin (/Users/$USER/.atom/packages/linter-markdown/node_modules/load-plugin/index.js:59:45)
 at merge (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:105:20)
 at required (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:266:3)
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:315:9
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/vfile-find-up/index.js:135:9
 at FSReqWrap.oncomplete (fs.js:123:15)

linter-markdownのREADMEをもっかい読んでみる。

If there is configuration for remark-lint, through .remarkrc files or remarkConfig in package.jsons, this linter works just like remark-cli but only uses the remark-lint plugin. Make sure remark-lint is installed in this case (optionally globally).

「.remarkrcで設定変更するときは、システムにremark-lintをインストールしてね」って仕様みたい。

逆に「デフォルト設定のまま使うときはシステムへのremark-lintインストールは不要」ってのが変わってるよね。Rubyのlinter-rubocopとか、普通はシステムに入ってるLinterをAtomから呼ぶ仕様なので。

というわけで、npmでremark-lintをインストールすることに。実はnpmコマンドを自分で叩くのが初めてだった。。。

Node.jsのアンインストール、再インストール

予想外にあんなことこんなことに苦労しまくって、ようやくnpmがまともに動くようになる。

remark-lintをnpmでインストール

linter-markdownのREADMEには「optionally globallyでインストールしてね」と書いてあったのでグローバルに入れてみるが、

% npm install -g remark-lint

結果変わらずエラー起きてしまうが内容は変わった。インストールしたremark-lintが認識されていないっぽい。
remark2.png

Error: Cannot find module `lint`
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/file-pipeline/configure.js:68:19
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:444:7
 at Array.forEach (native)
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:443:13
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:327:5
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/vfile-find-up/index.js:135:9
 at FSReqWrap.oncomplete (fs.js:123:15)

いろいろ調べたら、GitHubに似たようなIssue発見。まだOpenの状態だった。
[Cannot find module 'lint' (with global remark-lint install) #115]
(https://github.com/AtomLinter/linter-markdown/issues/115)

For now the solution is to use locally installed modules!

作者が「ローカルにインストールすれば解決するよ!」って言ってるのでやってみる。

% npm uninstall -g remark-lint
% npm install remark-lint

あれー、、、最初のエラーに戻ってしもた。。。
remark1.png

TypeError: name.charAt is not a function
 at resolvePlugin (/Users/$USER/.atom/packages/linter-markdown/node_modules/load-plugin/index.js:59:45)
 at merge (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:105:20)
 at required (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:266:3)
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:315:9
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/vfile-find-up/index.js:135:9
 at FSReqWrap.oncomplete (fs.js:123:15)

.remarkrc抜きでremark-lintと連携できるか試す

一旦.remarkrcを変名して設定無効化。

mv .remarkrc .Lemarkrc

するとエラー内容が変わった!
remark3.png

TypeError: Cannot read property 'use' of null at lint (/Users/$USER/node_modules/remark-lint/index.js:11:7)
 at Function.use (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified/index.js:318:25)
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/file-pipeline/configure.js:117:19
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:444:7
 at Array.forEach (native)
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:443:13
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:327:5
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/vfile-find-up/index.js:135:9
 at FSReqWrap.oncomplete (fs.js:123:15)

remark-lintパッケージ自体は認識してて、その内部のエラーっぽい。
んでここからが超ハマる。GitHubのIssueはじめ何を検索しても情報がない。JS詳しくないのでnullの原因を突き止めるのも無理。英語で新規Issueあげるまでの気もちょっと起きないし。。。

バージョンを下げてみる

かなり悩んだ挙句、「remark-lintのバージョンを下げてみたらどうじゃろ?」と思いつく。(もっと早く思いつけ俺!)
普通に入れると最新の6.0.0が入ったので、GitHubのtag確認して1つ前の5.4.0を入れてみる。

https://github.com/wooorm/remark-lint/tree/5.4.0

% npm uninstall remark-lint
% npm install remark-lint@5.4.0

お、動いた!
.remarkrcナシなので、remark-lint@5.4.0のデフォルト設定でLintしてる状態。
remark4.png

.remarkrcを有効に戻す

% mv .Lemarkrc .remarkrc

やっぱエラー。軽く絶望。
そして最初に起きたremark-lintが全く入っていない状態のエラーとまた同じ。。。
remark1.png

TypeError: name.charAt is not a function
 at resolvePlugin (/Users/$USER/.atom/packages/linter-markdown/node_modules/load-plugin/index.js:59:45)
 at merge (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:105:20)
 at required (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:266:3)
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:315:9
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/vfile-find-up/index.js:135:9
 at FSReqWrap.oncomplete (fs.js:123:15)

.remarkrcを前のバージョンの形式に

まだ色々と粘る。諦め悪いよねー。
6.0.0と5.4.0のREADMEを見比べたところ、.remarkrcのサンプルが違っていることに気づいたので、5.4.0のスタイルにまるっと書き直してみる。

https://github.com/wooorm/remark-lint/tree/5.4.0

{
  "presets": ["lint-recommended"],
  "plugins": {
    "lint": {
      "list-item-indent": false
    }
  }
}

またエラーが変わった!
remark5.png

Error: Cannot read configuration file: lint-recommended ENOENT: no such file or directory, open 'lint-recommended'
 at Error (native)
 at Object.fs.openSync (fs.js:640:18)
 at Object.module.(anonymous function) [as openSync] (ELECTRON_ASAR.js:168:20)
 at fs.readFileSync (fs.js:508:33)
 at fs.readFileSync (ELECTRON_ASAR.js:501:29)
 at load (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:213:13)
 at required (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:266:17)
 at preset (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:169:5)
 at merge (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:81:11)
 at required (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:266:3)
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:315:9
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/vfile-find-up/index.js:135:9
 at FSReqWrap.oncomplete (fs.js:123:15)

これは分りやすい。「lint-recommendedが見つからない」と言われてるので入れてみましょ。デフォルト設定で使われるプリセット一式のことやね。

https://github.com/wooorm/remark-lint#list-of-presets

If there is no configuration found for remark-lint, this linter runs remark-preset-lint-consistent and remark-preset-lint-recommended (both can be turned off).

この変から「行けそう!」って感覚になる。
少なくともバージョン6.0.0と5.4.0で.remarkrcの互換性がないことは間違いなさそう。バージョンに沿ったスタイルの.remarkrcを作る必要があるってことね。

remark-preset-lint-recommendedインストール

https://github.com/wooorm/remark-lint/tree/master/packages/remark-preset-lint-recommended

% npm install remark-preset-lint-recommended

またまたエラーが変わった。
remark6.png

TypeError: name.indexOf is not a function
 at resolvePlugin (/Users/$USER/.atom/packages/linter-markdown/node_modules/load-plugin/index.js:59:12)
 at merge (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:105:20)
 at required (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:266:3)
 at preset (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:169:5)
 at merge (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:81:11)
 at required (/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:266:3)
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:315:9
 at /Users/$USER/.atom/packages/linter-markdown/node_modules/vfile-find-up/index.js:135:9
 at FSReqWrap.oncomplete (fs.js:123:15)

ここは直感で「remark-preset-lint-recommendedもバージョンを合わせれば良さそう」と気づく。

remark-preset-lint-recommendedのバージョン下げる

remark-preset-lint-recommendedは、npmで普通に入れると2.0.0が入る。そのバージョン番号はこのソースに書いてあった。
https://github.com/wooorm/remark-lint/blob/master/packages/remark-preset-lint-recommended/package.json

  "version": "2.0.0",

GitHubリポジトリとしてはremark-lint配下のパッケージなのでtagは共通。tagを5.4.0に切り替えてみると、
https://github.com/wooorm/remark-lint/blob/5.4.0/packages/remark-preset-lint-recommended/package.json

  "version": "1.0.0",

ということでremark-preset-lint@5.4.0に対応するのはremark-preset-lint-recommended@1.0.0ってことだね!

% npm uninstall remark-preset-lint-recommended
% npm install remark-preset-lint-recommended@1.0.0

remark7.png

オッケー!!!動いたーーーーー!!!!!!

ついでにもう一つのプリセットremark-preset-lint-consistentもインストールしておく。バージョン体系は共通。

% npm install remark-preset-lint-consistent@1.0.0

最終的にnpm listの結果はこの状態でちゃんと動いてます。

% npm list
/Users/$USER
├─┬ remark-preset-lint-consistent@1.0.0
│ └─┬ remark-lint@5.4.0
│   ├── decamelize@1.2.0
│   ├─┬ load-plugin@2.1.0
│   │ ├─┬ npm-prefix@1.2.0
│   │ │ ├─┬ rc@1.1.7
│   │ │ │ ├── deep-extend@0.4.1
│   │ │ │ ├── ini@1.3.4
│   │ │ │ ├── minimist@1.2.0
│   │ │ │ └── strip-json-comments@2.0.1
│   │ │ ├── shellsubstitute@1.2.0
│   │ │ └─┬ untildify@2.1.0
│   │ │   └── os-homedir@1.0.2
│   │ └── resolve-from@2.0.0
│   ├── mdast-util-heading-style@1.0.2
│   ├── mdast-util-to-string@1.0.2
│   ├─┬ plur@2.1.2
│   │ └── irregular-plurals@1.2.0
│   ├─┬ remark-message-control@2.0.3
│   │ ├── mdast-comment-marker@1.0.1
│   │ └── trim@0.0.1
│   ├── trough@1.0.0
│   ├── unist-util-generated@1.1.0
│   ├── unist-util-position@3.0.0
│   ├── unist-util-visit@1.1.1
│   ├── vfile-location@2.0.1
│   ├── vfile-sort@2.0.0
│   └─┬ wrapped@1.0.1
│     ├── co@3.1.0
│     └── sliced@1.0.1
└── remark-preset-lint-recommended@1.0.0

yamlで.remarkrcを書く

.remarkrcのスタイルはJSON形式だけど、YAMLで書く方法ないものか探したら見つかった。拡張子を付けて.remarkrc.yamlとすることでYAMLで書けるようになる。(なぜか拡張子.ymlはダメだった)
YAML configuration file support #75

presets:
  - lint-recommended
plugins:
  lint:
    list-item-indent: false

同階層に.remarkrc.remarkrc.yamlを両方作って試してみたところ、設定項目がかぶった場合はJSONの.remarkrcが優先された。正式な仕様なのかは分からんので、どっちか片方だけ作る方が自然だとは思います。

Qiitaにまとめようとして

この辺でQiita記事を書こうと準備はじめたんですが、LinterのエラーメッセージをMarkdownにコピペしたいのに出来なくてイライラして、すんごい調べた結果Anthology記事が書けてしまいました(笑)

自分なりの設定を書く

やっと最初にやりたかったことが出来る(´;ω;`)

そもそもは、list-item-indentがデフォルトでtab-sizeだったのが嫌でspaceに直したかったのでした。サンプルの.remarkrcでたまたまlist-item-indent: falseと設定してあったのでspaceに変更。falseだとチェック自体が走らないので。

ついでにプリセットのlint-consistentも書いてみたり、Qiitaで記事を書くときに不都合な設定をfalseにしたりして、現時点の.remarkrc.yamlはこんな感じでちゃんと動いてます。これから少しずつ設定追加していくと思いますが。

presets:
  - lint-consistent
  - lint-recommended
plugins:
  lint:
    list-item-indent: space
    code-block-style: false # Qiitaのコードブロックで警告が出ないように
    no-shortcut-reference-link: false # Qiitaの注釈で警告が出ないように

おわりに

これにて本シリーズは一旦終了です!ほぼ自己満だけど長かった(´;ω;`)

Linterまだまだ使いこなしてないけど好きな分野なので、linter-markdownに関する日本語の情報が皆無な状態を何とかしたくて結構がんばりました。この記事を読んでAtomでMarkdownをLintする日本人が少しでも増えてくれますと、大悦至極に存じ奉ります。

日頃Qiitaとか他の記事とか読んで「たいていのノウハウは誰かが書いてくれてる」と思ってたんですが、「ニッチな分野では誰も書いてないノウハウがまだまだある」ってことが今回わかりました。誰も書いてないことが分かると「俺が書いてやろう!」って自然に燃えるので、今後もそういうタイミングで少しずつQiitaに投稿しようと思います。

そして僕の一番の課題は「細部にこだわりすぎてスピード遅すぎる」こと。今回はあえて思う存分時間かけましたが、ある程度の質でサクサク沢山書けるようになりたいっすねーマジで。ソースコードも同じなんだけど。。。

最後までお付き合いくださった方、どうもありがとうございました〜m(. .)m

2017/4/18 追記

linter-markdownが4.0.0にバージョンアップして、remark-lint@6.0.0に対応していました。それに伴ってremark-lint@5.4.0では動かなくなっており、Markdownを編集しようとするとこんなエラーが。

TypeError: remark.use is not a function at Function.lint 
(/Users/$USER/node_modules/remark-lint/lib/index.js:65:10) at freeze 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified/index.js:122:28) at Function.parse 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified/index.js:271:5) at parse 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/file-pipeline/parse.js:37:36) at wrapped 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/trough/index.js:128:19) at next 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/trough/index.js:81:24) at done 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/trough/index.js:163:12) at handleConfiguration 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/file-pipeline/configure.js:68:5) at done 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/configuration.js:77:14) at apply 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/find-up.js:176:7) at applyAll 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/find-up.js:166:7) at found 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/find-up.js:158:7) at apply 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/find-up.js:176:7) at applyAll 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/find-up.js:166:7) at found 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/find-up.js:158:7) at done 
(/Users/$USER/.atom/packages/linter-markdown/node_modules/unified-engine/lib/find-up.js:149:9) at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:445:3)

前回ハマりまくった経験があったので、今回は普通にnpmの最新版を入れて、設定ファイルの記法も変更して、短時間で解決できました。めでたし。

% npm install remark-lint
% npm install remark-preset-lint-consistent
% npm install remark-preset-lint-recommended
{
  "plugins": [
    "remark-preset-lint-consistent",
    "remark-preset-lint-recommended",
    ["remark-lint-list-item-indent", "space"],
    ["remark-lint-code-block-style", false],
    ["remark-lint-no-shortcut-reference-link", false]
  ]
}
plugins:
- remark-preset-lint-consistent
- remark-preset-lint-recommended
- # 箇条書きリストのインデントは(タブではなく)スペース
  - remark-lint-list-item-indent
  - space
- # Qiitaのコードブロックで警告が出ないように
  - remark-lint-code-block-style
  - false
- # Qiitaの注釈で警告が出ないように
  - remark-lint-no-shortcut-reference-link
  - false
2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?