1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

nodeでテンプレートエンジンっぽいものを作った

Posted at

背景

同じようなページを複製したいけど、それだけのためにEJSやPugを入れるのも面倒。。。
じゃあ自分でサクッと作ろう!

環境

node 20.10.0
npm 10.2.3

前提

以下のポケモン151匹のデータが入ったJSONをもとに、 (JSONは記事最下部に記載)

pokeData.json
[
  {
    "no": 1,
    "name": "フシギダネ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 45,
      "attack": 49,
      "defense": 49,
      "spAttack": 65,
      "spDefense": 65,
      "speed": 45
    }
  },
  {
    "no": 2,
    "name": "フシギソウ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 60,
      "attack": 62,
      "defense": 63,
      "spAttack": 80,
      "spDefense": 80,
      "speed": 60
    }
  },
  {
    "no": 3,
    "name": "フシギバナ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 80,
      "attack": 82,
      "defense": 83,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 80
    }
  },
  ......
  {
    "no": 151,
    "name": "ミュウ",
    "abilities": ["シンクロ"],
    "stats": {
      "hp": 100,
      "attack": 100,
      "defense": 100,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 100
    }
  }
]

以下のようなファイルを量産します。
(タイトル、h1、ulの中身、dlの中身が変化)

1.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>フシギダネ</title>
</head>
<body>
  <h1>フシギダネ</h1>
  <ul>
    <li>しんりょく</li>
  </ul>
  <dl>
    <dt>HP</dt>
    <dd>45</dd>
    <dt>こうげき</dt>
    <dd>49</dd>
    <dt>ぼうぎょ</dt>
    <dd>49</dd>
    <dt>とくこう</dt>
    <dd>65</dd>
    <dt>とくぼう</dt>
    <dd>65</dd>
    <dt>すばやさ</dt>
    <dd>45</dd>
  </dl>
</body>
</html>

実装

まずは1ページ作成してみる

プロジェクトルートにmain.jsとbuildディレクトリを作成して、main.jsに以下を記述します
(都合上、ulは後ほど追記します)

main.js
const fs = require('fs');

// pokeData.jsonを読み込む
const pokeData = require('./pokeData.json');

// pokeDataの配列の要素を引数に取り、htmlを生成する
const generatePage = ({no, name, stats}) => {
  const html = `
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>フシギダネ</title>
</head>
<body>
  <h1>フシギダネ</h1>
  <dl>
    <dt>HP</dt>
    <dd>45</dd>
    <dt>こうげき</dt>
    <dd>49</dd>
    <dt>ぼうぎょ</dt>
    <dd>49</dd>
    <dt>とくこう</dt>
    <dd>65</dd>
    <dt>とくぼう</dt>
    <dd>65</dd>
    <dt>すばやさ</dt>
    <dd>45</dd>
  </dl>
</body>
</html>
`

  fs.writeFileSync(`./build/${no}.html`,html);
}

// pokeDataの1番初め(フシギダネ)のページを作成
generatePage(pokeData[0])

fs.writeFileSyncを用い、第1引数に書き出すファイルパス、第2引数に書き込むデータを指定することでファイルを作成することができます。

コードを実行します。

node main.js

buildディレクトリに1.htmlが生成されているはずです。

151ページ作成してみる

変数を使用して各項目がページごとに変わるようにします。
また、pokeDataをforEachで回して、151ページ分生成します。

main.js
  const fs = require('fs');

  const pokeData = require('./pokeData.json');


  const generatePage = ({no, name, stats}) => {
    const html = `
  <!DOCTYPE html>
  <html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-   <title>フシギダネ</title>
+   <title>${name}</title>
  </head>
  <body>
-   <h1>フシギダネ</h1>
+   <h1>${name}</h1>
    <dl>
      <dt>HP</dt>
-     <dd>45</dd>
+     <dd>${stats.hp}</dd>
      <dt>こうげき</dt>
-     <dd>49</dd>
+     <dd>${stats.attack}</dd>
      <dt>ぼうぎょ</dt>
-     <dd>49</dd>
+     <dd>${stats.defense}</dd>
      <dt>とくこう</dt>
-     <dd>65</dd>
+     <dd>${stats.spAttack}</dd>
      <dt>とくぼう</dt>
-     <dd>65</dd>
+     <dd>${stats.spDefense}</dd>
      <dt>すばやさ</dt>
-     <dd>45</dd>
+     <dd>${stats.speed}</dd>
    </dl>
  </body>
  </html>
  `

    fs.writeFileSync(`./build/${no}.html`,html)
  }
  
- generatePage(pokeData[0])
+ pokeData.forEach(generatePage)

  // 追記:上記forEachは下記とおなじ。
  // pokeData.forEach(pokemon => {
  //  generatePage(pokemon);
  // })

コードを実行すると151ページ分生成されているかと思います。

ループを組み込んでみる

指定の箇所を変えるだけであれば上記で済むのですが、途中にループ処理が入るとやや面倒になります。
今回はポケモンの特性(abilities)の数だけループを回してliタグを生成するようにします。

main.js
  const fs = require('fs');

  const pokeData = require('./pokeData.json');


- const generatePage = ({no, name, stats}) => {
+ const generatePage = ({no, name, abilities, stats}) => {
+
+   const abilitiesList = () => {
+     let list = '';
+
+     for(const ability of abilities) {
+       list += `
+     <li>${ability}</li>
+ `;
+     }
+     return list;
+   }



    const html = `
  <!DOCTYPE html>
  <html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>${name}</title>
  </head>
  <body>
    <h1>${name}</h1>
+   <ul>
+ ${abilitiesList()}
+   </ul>
    <dl>
      <dt>HP</dt>
      <dd>${stats.hp}</dd>
      <dt>こうげき</dt>
      <dd>${stats.attack}</dd>
      <dt>ぼうぎょ</dt>
      <dd>${stats.defense}</dd>
      <dt>とくこう</dt>
      <dd>${stats.spAttack}</dd>
      <dt>とくぼう</dt>
      <dd>${stats.spDefense}</dd>
      <dt>すばやさ</dt>
      <dd>${stats.speed}</dd>
    </dl>
  </body>
  </html>
  `
    


    fs.writeFileSync(`./build/${no}.html`,html)
  }

  pokeData.forEach(generatePage)

まず、ループする箇所を関数として切り出します( abilitiesList関数 )
関数内部でループを回し、htmlを出力させます。今回はabilitiesの要素の数だけループを回し、その分のliタグを出力しています。

コードを実行すると151ページ分が更新され、特性の分だけliタグが出力されています。

結果

簡単なものであれば自力でページを複製することができました。
ただし、ループの処理がややこしくなるため、ループ箇所が多い場合はかなりしんどくなりそうです。
いずれにせよ「量産できればそれでOK」といった場合でなければやはりテンプレートエンジンをつかうべきですね...。

今回使用したJSONデータ

pokeData.json

[
  {
    "no": 1,
    "name": "フシギダネ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 45,
      "attack": 49,
      "defense": 49,
      "spAttack": 65,
      "spDefense": 65,
      "speed": 45
    }
  },
  {
    "no": 2,
    "name": "フシギソウ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 60,
      "attack": 62,
      "defense": 63,
      "spAttack": 80,
      "spDefense": 80,
      "speed": 60
    }
  },
  {
    "no": 3,
    "name": "フシギバナ",
    "abilities": ["しんりょく"],
    "stats": {
      "hp": 80,
      "attack": 82,
      "defense": 83,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 80
    }
  },
  {
    "no": 4,
    "name": "ヒトカゲ",
    "abilities": ["もうか"],
    "stats": {
      "hp": 39,
      "attack": 52,
      "defense": 43,
      "spAttack": 60,
      "spDefense": 50,
      "speed": 65
    }
  },
  {
    "no": 5,
    "name": "リザード",
    "abilities": ["もうか"],
    "stats": {
      "hp": 58,
      "attack": 64,
      "defense": 58,
      "spAttack": 80,
      "spDefense": 65,
      "speed": 80
    }
  },
  {
    "no": 6,
    "name": "リザードン",
    "abilities": ["もうか"],
    "stats": {
      "hp": 78,
      "attack": 84,
      "defense": 78,
      "spAttack": 109,
      "spDefense": 85,
      "speed": 100
    }
  },
  {
    "no": 7,
    "name": "ゼニガメ",
    "abilities": ["げきりゅう"],
    "stats": {
      "hp": 44,
      "attack": 48,
      "defense": 65,
      "spAttack": 50,
      "spDefense": 64,
      "speed": 43
    }
  },
  {
    "no": 8,
    "name": "カメール",
    "abilities": ["げきりゅう"],
    "stats": {
      "hp": 59,
      "attack": 63,
      "defense": 80,
      "spAttack": 65,
      "spDefense": 80,
      "speed": 58
    }
  },
  {
    "no": 9,
    "name": "カメックス",
    "abilities": ["げきりゅう"],
    "stats": {
      "hp": 79,
      "attack": 83,
      "defense": 100,
      "spAttack": 85,
      "spDefense": 105,
      "speed": 78
    }
  },
  {
    "no": 10,
    "name": "キャタピー",
    "abilities": ["りんぷん"],
    "stats": {
      "hp": 45,
      "attack": 30,
      "defense": 35,
      "spAttack": 20,
      "spDefense": 20,
      "speed": 45
    }
  },
  {
    "no": 11,
    "name": "トランセル",
    "abilities": ["だっぴ"],
    "stats": {
      "hp": 50,
      "attack": 20,
      "defense": 55,
      "spAttack": 25,
      "spDefense": 25,
      "speed": 30
    }
  },
  {
    "no": 12,
    "name": "バタフリー",
    "abilities": ["ふくがん"],
    "stats": {
      "hp": 60,
      "attack": 45,
      "defense": 50,
      "spAttack": 90,
      "spDefense": 80,
      "speed": 70
    }
  },
  {
    "no": 13,
    "name": "ビードル",
    "abilities": ["りんぷん"],
    "stats": {
      "hp": 40,
      "attack": 35,
      "defense": 30,
      "spAttack": 20,
      "spDefense": 20,
      "speed": 50
    }
  },
  {
    "no": 14,
    "name": "コクーン",
    "abilities": ["だっぴ"],
    "stats": {
      "hp": 45,
      "attack": 25,
      "defense": 50,
      "spAttack": 25,
      "spDefense": 25,
      "speed": 35
    }
  },
  {
    "no": 15,
    "name": "スピアー",
    "abilities": ["むしのしらせ"],
    "stats": {
      "hp": 65,
      "attack": 90,
      "defense": 40,
      "spAttack": 45,
      "spDefense": 80,
      "speed": 75
    }
  },
  {
    "no": 16,
    "name": "ポッポ",
    "abilities": ["するどいめ", "ちどりあし"],
    "stats": {
      "hp": 40,
      "attack": 45,
      "defense": 40,
      "spAttack": 35,
      "spDefense": 35,
      "speed": 56
    }
  },
  {
    "no": 17,
    "name": "ピジョン",
    "abilities": ["するどいめ", "ちどりあし"],
    "stats": {
      "hp": 63,
      "attack": 60,
      "defense": 55,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 71
    }
  },
  {
    "no": 18,
    "name": "ピジョット",
    "abilities": ["するどいめ", "ちどりあし"],
    "stats": {
      "hp": 83,
      "attack": 80,
      "defense": 75,
      "spAttack": 70,
      "spDefense": 70,
      "speed": 101
    }
  },
  {
    "no": 19,
    "name": "コラッタ",
    "abilities": ["にげあし", "こんじょう"],
    "stats": {
      "hp": 30,
      "attack": 56,
      "defense": 35,
      "spAttack": 25,
      "spDefense": 35,
      "speed": 72
    }
  },
  {
    "no": 20,
    "name": "ラッタ",
    "abilities": ["にげあし", "こんじょう"],
    "stats": {
      "hp": 55,
      "attack": 81,
      "defense": 60,
      "spAttack": 50,
      "spDefense": 70,
      "speed": 97
    }
  },
  {
    "no": 21,
    "name": "オニスズメ",
    "abilities": ["するどいめ"],
    "stats": {
      "hp": 40,
      "attack": 60,
      "defense": 30,
      "spAttack": 31,
      "spDefense": 31,
      "speed": 70
    }
  },
  {
    "no": 22,
    "name": "オニドリル",
    "abilities": ["するどいめ"],
    "stats": {
      "hp": 65,
      "attack": 90,
      "defense": 65,
      "spAttack": 61,
      "spDefense": 61,
      "speed": 100
    }
  },
  {
    "no": 23,
    "name": "アーボ",
    "abilities": ["いかく", "だっぴ"],
    "stats": {
      "hp": 35,
      "attack": 60,
      "defense": 44,
      "spAttack": 40,
      "spDefense": 54,
      "speed": 55
    }
  },
  {
    "no": 24,
    "name": "アーボック",
    "abilities": ["いかく", "だっぴ"],
    "stats": {
      "hp": 60,
      "attack": 95,
      "defense": 69,
      "spAttack": 65,
      "spDefense": 79,
      "speed": 80
    }
  },
  {
    "no": 25,
    "name": "ピカチュウ",
    "abilities": ["せいでんき"],
    "stats": {
      "hp": 35,
      "attack": 55,
      "defense": 40,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 90
    }
  },
  {
    "no": 26,
    "name": "ライチュウ",
    "abilities": ["せいでんき"],
    "stats": {
      "hp": 60,
      "attack": 90,
      "defense": 55,
      "spAttack": 90,
      "spDefense": 80,
      "speed": 110
    }
  },
  {
    "no": 27,
    "name": "サンド",
    "abilities": ["すながくれ"],
    "stats": {
      "hp": 50,
      "attack": 75,
      "defense": 85,
      "spAttack": 20,
      "spDefense": 30,
      "speed": 40
    }
  },
  {
    "no": 28,
    "name": "サンドパン",
    "abilities": ["すながくれ"],
    "stats": {
      "hp": 75,
      "attack": 100,
      "defense": 110,
      "spAttack": 45,
      "spDefense": 55,
      "speed": 65
    }
  },
  {
    "no": 29,
    "name": "ニドラン♀",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 55,
      "attack": 47,
      "defense": 52,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 41
    }
  },
  {
    "no": 30,
    "name": "ニドリーナ",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 70,
      "attack": 62,
      "defense": 67,
      "spAttack": 55,
      "spDefense": 55,
      "speed": 56
    }
  },
  {
    "no": 31,
    "name": "ニドクイン",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 90,
      "attack": 92,
      "defense": 87,
      "spAttack": 75,
      "spDefense": 85,
      "speed": 76
    }
  },
  {
    "no": 32,
    "name": "ニドラン♂",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 46,
      "attack": 57,
      "defense": 40,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 50
    }
  },
  {
    "no": 33,
    "name": "ニドリーノ",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 61,
      "attack": 72,
      "defense": 57,
      "spAttack": 55,
      "spDefense": 55,
      "speed": 65
    }
  },
  {
    "no": 34,
    "name": "ニドキング",
    "abilities": ["どくのトゲ", "とうそうしん"],
    "stats": {
      "hp": 81,
      "attack": 102,
      "defense": 77,
      "spAttack": 85,
      "spDefense": 75,
      "speed": 85
    }
  },
  {
    "no": 35,
    "name": "ピッピ",
    "abilities": ["メロメロボディ", "マジックガード"],
    "stats": {
      "hp": 70,
      "attack": 45,
      "defense": 48,
      "spAttack": 60,
      "spDefense": 65,
      "speed": 35
    }
  },
  {
    "no": 36,
    "name": "ピクシー",
    "abilities": ["メロメロボディ", "マジックガード"],
    "stats": {
      "hp": 95,
      "attack": 70,
      "defense": 73,
      "spAttack": 95,
      "spDefense": 90,
      "speed": 60
    }
  },
  {
    "no": 37,
    "name": "ロコン",
    "abilities": ["もらいび"],
    "stats": {
      "hp": 38,
      "attack": 41,
      "defense": 40,
      "spAttack": 50,
      "spDefense": 65,
      "speed": 65
    }
  },
  {
    "no": 38,
    "name": "キュウコン",
    "abilities": ["もらいび"],
    "stats": {
      "hp": 73,
      "attack": 76,
      "defense": 75,
      "spAttack": 81,
      "spDefense": 100,
      "speed": 100
    }
  },
  {
    "no": 39,
    "name": "プリン",
    "abilities": ["メロメロボディ", "かちき"],
    "stats": {
      "hp": 115,
      "attack": 45,
      "defense": 20,
      "spAttack": 45,
      "spDefense": 25,
      "speed": 20
    }
  },
  {
    "no": 40,
    "name": "プクリン",
    "abilities": ["メロメロボディ", "かちき"],
    "stats": {
      "hp": 140,
      "attack": 70,
      "defense": 45,
      "spAttack": 85,
      "spDefense": 50,
      "speed": 45
    }
  },
  {
    "no": 41,
    "name": "ズバット",
    "abilities": ["せいしんりょく"],
    "stats": {
      "hp": 40,
      "attack": 45,
      "defense": 35,
      "spAttack": 30,
      "spDefense": 40,
      "speed": 55
    }
  },
  {
    "no": 42,
    "name": "ゴルバット",
    "abilities": ["せいしんりょく"],
    "stats": {
      "hp": 75,
      "attack": 80,
      "defense": 70,
      "spAttack": 65,
      "spDefense": 75,
      "speed": 90
    }
  },
  {
    "no": 43,
    "name": "ナゾノクサ",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 45,
      "attack": 50,
      "defense": 55,
      "spAttack": 75,
      "spDefense": 65,
      "speed": 30
    }
  },
  {
    "no": 44,
    "name": "クサイハナ",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 60,
      "attack": 65,
      "defense": 70,
      "spAttack": 85,
      "spDefense": 75,
      "speed": 40
    }
  },
  {
    "no": 45,
    "name": "ラフレシア",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 75,
      "attack": 80,
      "defense": 85,
      "spAttack": 110,
      "spDefense": 90,
      "speed": 50
    }
  },
  {
    "no": 46,
    "name": "パラス",
    "abilities": ["ほうし", "かんそうはだ"],
    "stats": {
      "hp": 35,
      "attack": 70,
      "defense": 55,
      "spAttack": 45,
      "spDefense": 55,
      "speed": 25
    }
  },
  {
    "no": 47,
    "name": "パラセクト",
    "abilities": ["ほうし", "かんそうはだ"],
    "stats": {
      "hp": 60,
      "attack": 95,
      "defense": 80,
      "spAttack": 60,
      "spDefense": 80,
      "speed": 30
    }
  },
  {
    "no": 48,
    "name": "コンパン",
    "abilities": ["ふくがん", "いろめがね"],
    "stats": {
      "hp": 60,
      "attack": 55,
      "defense": 50,
      "spAttack": 40,
      "spDefense": 55,
      "speed": 45
    }
  },
  {
    "no": 49,
    "name": "モルフォン",
    "abilities": ["りんぷん", "いろめがね"],
    "stats": {
      "hp": 70,
      "attack": 65,
      "defense": 60,
      "spAttack": 90,
      "spDefense": 75,
      "speed": 90
    }
  },
  {
    "no": 50,
    "name": "ディグダ",
    "abilities": ["すながくれ", "ありじごく"],
    "stats": {
      "hp": 10,
      "attack": 55,
      "defense": 25,
      "spAttack": 35,
      "spDefense": 45,
      "speed": 95
    }
  },
  {
    "no": 51,
    "name": "ダグトリオ",
    "abilities": ["すながくれ", "ありじごく"],
    "stats": {
      "hp": 35,
      "attack": 100,
      "defense": 50,
      "spAttack": 50,
      "spDefense": 70,
      "speed": 120
    }
  },
  {
    "no": 52,
    "name": "ニャース",
    "abilities": ["ものひろい", "テクニシャン"],
    "stats": {
      "hp": 40,
      "attack": 45,
      "defense": 35,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 90
    }
  },
  {
    "no": 53,
    "name": "ペルシアン",
    "abilities": ["じゅうなん", "テクニシャン"],
    "stats": {
      "hp": 65,
      "attack": 70,
      "defense": 60,
      "spAttack": 65,
      "spDefense": 65,
      "speed": 115
    }
  },
  {
    "no": 54,
    "name": "コダック",
    "abilities": ["しめりけ", "ノーてんき"],
    "stats": {
      "hp": 50,
      "attack": 52,
      "defense": 48,
      "spAttack": 65,
      "spDefense": 50,
      "speed": 55
    }
  },
  {
    "no": 55,
    "name": "ゴルダック",
    "abilities": ["しめりけ", "ノーてんき"],
    "stats": {
      "hp": 80,
      "attack": 82,
      "defense": 78,
      "spAttack": 95,
      "spDefense": 80,
      "speed": 85
    }
  },
  {
    "no": 56,
    "name": "マンキー",
    "abilities": ["やるき", "いかりのつぼ"],
    "stats": {
      "hp": 40,
      "attack": 80,
      "defense": 35,
      "spAttack": 35,
      "spDefense": 45,
      "speed": 70
    }
  },
  {
    "no": 57,
    "name": "オコリザル",
    "abilities": ["やるき", "いかりのつぼ"],
    "stats": {
      "hp": 65,
      "attack": 105,
      "defense": 60,
      "spAttack": 60,
      "spDefense": 70,
      "speed": 95
    }
  },
  {
    "no": 58,
    "name": "ガーディ",
    "abilities": ["いかく", "もらいび"],
    "stats": {
      "hp": 55,
      "attack": 70,
      "defense": 45,
      "spAttack": 70,
      "spDefense": 50,
      "speed": 60
    }
  },
  {
    "no": 59,
    "name": "ウインディ",
    "abilities": ["いかく", "もらいび"],
    "stats": {
      "hp": 90,
      "attack": 110,
      "defense": 80,
      "spAttack": 100,
      "spDefense": 80,
      "speed": 95
    }
  },
  {
    "no": 60,
    "name": "ニョロモ",
    "abilities": ["ちょすい", "しめりけ"],
    "stats": {
      "hp": 40,
      "attack": 50,
      "defense": 40,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 90
    }
  },
  {
    "no": 61,
    "name": "ニョロゾ",
    "abilities": ["ちょすい", "しめりけ"],
    "stats": {
      "hp": 65,
      "attack": 65,
      "defense": 65,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 90
    }
  },
  {
    "no": 62,
    "name": "ニョロボン",
    "abilities": ["ちょすい", "しめりけ"],
    "stats": {
      "hp": 90,
      "attack": 95,
      "defense": 95,
      "spAttack": 70,
      "spDefense": 90,
      "speed": 70
    }
  },
  {
    "no": 63,
    "name": "ケーシィ",
    "abilities": ["シンクロ", "せいしんりょく"],
    "stats": {
      "hp": 25,
      "attack": 20,
      "defense": 15,
      "spAttack": 105,
      "spDefense": 55,
      "speed": 90
    }
  },
  {
    "no": 64,
    "name": "ユンゲラー",
    "abilities": ["シンクロ", "せいしんりょく"],
    "stats": {
      "hp": 40,
      "attack": 35,
      "defense": 30,
      "spAttack": 120,
      "spDefense": 70,
      "speed": 105
    }
  },
  {
    "no": 65,
    "name": "フーディン",
    "abilities": ["シンクロ", "せいしんりょく"],
    "stats": {
      "hp": 55,
      "attack": 50,
      "defense": 45,
      "spAttack": 135,
      "spDefense": 95,
      "speed": 120
    }
  },
  {
    "no": 66,
    "name": "ワンリキー",
    "abilities": ["こんじょう", "ノーガード"],
    "stats": {
      "hp": 70,
      "attack": 80,
      "defense": 50,
      "spAttack": 35,
      "spDefense": 35,
      "speed": 35
    }
  },
  {
    "no": 67,
    "name": "ゴーリキー",
    "abilities": ["こんじょう", "ノーガード"],
    "stats": {
      "hp": 80,
      "attack": 100,
      "defense": 70,
      "spAttack": 50,
      "spDefense": 60,
      "speed": 45
    }
  },
  {
    "no": 68,
    "name": "カイリキー",
    "abilities": ["こんじょう", "ノーガード"],
    "stats": {
      "hp": 90,
      "attack": 130,
      "defense": 80,
      "spAttack": 65,
      "spDefense": 85,
      "speed": 55
    }
  },
  {
    "no": 69,
    "name": "マダツボミ",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 50,
      "attack": 75,
      "defense": 35,
      "spAttack": 70,
      "spDefense": 30,
      "speed": 40
    }
  },
  {
    "no": 70,
    "name": "ウツドン",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 65,
      "attack": 90,
      "defense": 50,
      "spAttack": 85,
      "spDefense": 45,
      "speed": 55
    }
  },
  {
    "no": 71,
    "name": "ウツボット",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 80,
      "attack": 105,
      "defense": 65,
      "spAttack": 100,
      "spDefense": 70,
      "speed": 70
    }
  },
  {
    "no": 72,
    "name": "メノクラゲ",
    "abilities": ["クリアボディ", "ヘドロえき"],
    "stats": {
      "hp": 40,
      "attack": 40,
      "defense": 35,
      "spAttack": 50,
      "spDefense": 100,
      "speed": 70
    }
  },
  {
    "no": 73,
    "name": "ドククラゲ",
    "abilities": ["クリアボディ", "ヘドロえき"],
    "stats": {
      "hp": 80,
      "attack": 70,
      "defense": 65,
      "spAttack": 80,
      "spDefense": 120,
      "speed": 100
    }
  },
  {
    "no": 74,
    "name": "イシツブテ",
    "abilities": ["いしあたま", "がんじょう"],
    "stats": {
      "hp": 40,
      "attack": 80,
      "defense": 100,
      "spAttack": 30,
      "spDefense": 30,
      "speed": 20
    }
  },
  {
    "no": 75,
    "name": "ゴローン",
    "abilities": ["いしあたま", "がんじょう"],
    "stats": {
      "hp": 55,
      "attack": 95,
      "defense": 115,
      "spAttack": 45,
      "spDefense": 45,
      "speed": 35
    }
  },
  {
    "no": 76,
    "name": "ゴローニャ",
    "abilities": ["いしあたま", "がんじょう"],
    "stats": {
      "hp": 80,
      "attack": 120,
      "defense": 130,
      "spAttack": 55,
      "spDefense": 65,
      "speed": 45
    }
  },
  {
    "no": 77,
    "name": "ポニータ",
    "abilities": ["にげあし", "もらいび"],
    "stats": {
      "hp": 50,
      "attack": 85,
      "defense": 55,
      "spAttack": 65,
      "spDefense": 65,
      "speed": 90
    }
  },
  {
    "no": 78,
    "name": "ギャロップ",
    "abilities": ["にげあし", "もらいび"],
    "stats": {
      "hp": 65,
      "attack": 100,
      "defense": 70,
      "spAttack": 80,
      "spDefense": 80,
      "speed": 105
    }
  },
  {
    "no": 79,
    "name": "ヤドン",
    "abilities": ["どんかん", "マイペース"],
    "stats": {
      "hp": 90,
      "attack": 65,
      "defense": 65,
      "spAttack": 40,
      "spDefense": 40,
      "speed": 15
    }
  },
  {
    "no": 80,
    "name": "ヤドラン",
    "abilities": ["どんかん", "マイペース"],
    "stats": {
      "hp": 95,
      "attack": 75,
      "defense": 110,
      "spAttack": 100,
      "spDefense": 80,
      "speed": 30
    }
  },
  {
    "no": 81,
    "name": "コイル",
    "abilities": ["じりょく", "がんじょう"],
    "stats": {
      "hp": 25,
      "attack": 35,
      "defense": 70,
      "spAttack": 95,
      "spDefense": 55,
      "speed": 45
    }
  },
  {
    "no": 82,
    "name": "レアコイル",
    "abilities": ["じりょく", "がんじょう"],
    "stats": {
      "hp": 50,
      "attack": 60,
      "defense": 95,
      "spAttack": 120,
      "spDefense": 70,
      "speed": 70
    }
  },
  {
    "no": 83,
    "name": "カモネギ",
    "abilities": ["するどいめ", "せいしんりょく"],
    "stats": {
      "hp": 52,
      "attack": 90,
      "defense": 55,
      "spAttack": 58,
      "spDefense": 62,
      "speed": 60
    }
  },
  {
    "no": 84,
    "name": "ドードー",
    "abilities": ["にげあし", "はやおき"],
    "stats": {
      "hp": 35,
      "attack": 85,
      "defense": 45,
      "spAttack": 35,
      "spDefense": 35,
      "speed": 75
    }
  },
  {
    "no": 85,
    "name": "ドードリオ",
    "abilities": ["にげあし", "はやおき"],
    "stats": {
      "hp": 60,
      "attack": 110,
      "defense": 70,
      "spAttack": 60,
      "spDefense": 60,
      "speed": 110
    }
  },
  {
    "no": 86,
    "name": "パウワウ",
    "abilities": ["あついしぼう", "うるおいボディ"],
    "stats": {
      "hp": 65,
      "attack": 45,
      "defense": 55,
      "spAttack": 45,
      "spDefense": 70,
      "speed": 45
    }
  },
  {
    "no": 87,
    "name": "ジュゴン",
    "abilities": ["あついしぼう", "うるおいボディ"],
    "stats": {
      "hp": 90,
      "attack": 70,
      "defense": 80,
      "spAttack": 70,
      "spDefense": 95,
      "speed": 70
    }
  },
  {
    "no": 88,
    "name": "ベトベター",
    "abilities": ["あくしゅう", "ねんちゃく"],
    "stats": {
      "hp": 80,
      "attack": 80,
      "defense": 50,
      "spAttack": 40,
      "spDefense": 50,
      "speed": 25
    }
  },
  {
    "no": 89,
    "name": "ベトベトン",
    "abilities": ["あくしゅう", "ねんちゃく"],
    "stats": {
      "hp": 105,
      "attack": 105,
      "defense": 75,
      "spAttack": 65,
      "spDefense": 100,
      "speed": 50
    }
  },
  {
    "no": 90,
    "name": "シェルダー",
    "abilities": ["シェルアーマー", "スキルリンク"],
    "stats": {
      "hp": 30,
      "attack": 65,
      "defense": 100,
      "spAttack": 45,
      "spDefense": 25,
      "speed": 40
    }
  },
  {
    "no": 91,
    "name": "パルシェン",
    "abilities": ["シェルアーマー", "スキルリンク"],
    "stats": {
      "hp": 50,
      "attack": 95,
      "defense": 180,
      "spAttack": 85,
      "spDefense": 45,
      "speed": 70
    }
  },
  {
    "no": 92,
    "name": "ゴース",
    "abilities": ["ふゆう"],
    "stats": {
      "hp": 30,
      "attack": 35,
      "defense": 30,
      "spAttack": 100,
      "spDefense": 35,
      "speed": 80
    }
  },
  {
    "no": 93,
    "name": "ゴースト",
    "abilities": ["ふゆう"],
    "stats": {
      "hp": 45,
      "attack": 50,
      "defense": 45,
      "spAttack": 115,
      "spDefense": 55,
      "speed": 95
    }
  },
  {
    "no": 94,
    "name": "ゲンガー",
    "abilities": ["のろわれボディ"],
    "stats": {
      "hp": 60,
      "attack": 65,
      "defense": 60,
      "spAttack": 130,
      "spDefense": 75,
      "speed": 110
    }
  },
  {
    "no": 95,
    "name": "イワーク",
    "abilities": ["いしあたま", "がんじょう"],
    "stats": {
      "hp": 35,
      "attack": 45,
      "defense": 160,
      "spAttack": 30,
      "spDefense": 45,
      "speed": 70
    }
  },
  {
    "no": 96,
    "name": "スリープ",
    "abilities": ["ふみん", "よちむ"],
    "stats": {
      "hp": 60,
      "attack": 48,
      "defense": 45,
      "spAttack": 43,
      "spDefense": 90,
      "speed": 42
    }
  },
  {
    "no": 97,
    "name": "スリーパー",
    "abilities": ["ふみん", "よちむ"],
    "stats": {
      "hp": 85,
      "attack": 73,
      "defense": 70,
      "spAttack": 73,
      "spDefense": 115,
      "speed": 67
    }
  },
  {
    "no": 98,
    "name": "クラブ",
    "abilities": ["かいりきバサミ", "シェルアーマー"],
    "stats": {
      "hp": 30,
      "attack": 105,
      "defense": 90,
      "spAttack": 25,
      "spDefense": 25,
      "speed": 50
    }
  },
  {
    "no": 99,
    "name": "キングラー",
    "abilities": ["かいりきバサミ", "シェルアーマー"],
    "stats": {
      "hp": 55,
      "attack": 130,
      "defense": 115,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 75
    }
  },
  {
    "no": 100,
    "name": "ビリリダマ",
    "abilities": ["ぼうおん", "せいでんき"],
    "stats": {
      "hp": 40,
      "attack": 30,
      "defense": 50,
      "spAttack": 55,
      "spDefense": 55,
      "speed": 100
    }
  },
  {
    "no": 101,
    "name": "マルマイン",
    "abilities": ["ぼうおん", "せいでんき"],
    "stats": {
      "hp": 60,
      "attack": 50,
      "defense": 70,
      "spAttack": 80,
      "spDefense": 80,
      "speed": 150
    }
  },
  {
    "no": 102,
    "name": "タマタマ",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 60,
      "attack": 40,
      "defense": 80,
      "spAttack": 60,
      "spDefense": 45,
      "speed": 40
    }
  },
  {
    "no": 103,
    "name": "ナッシー",
    "abilities": ["ようりょくそ"],
    "stats": {
      "hp": 95,
      "attack": 95,
      "defense": 85,
      "spAttack": 125,
      "spDefense": 75,
      "speed": 55
    }
  },
  {
    "no": 104,
    "name": "カラカラ",
    "abilities": ["いしあたま", "ひらいしん"],
    "stats": {
      "hp": 50,
      "attack": 50,
      "defense": 95,
      "spAttack": 40,
      "spDefense": 50,
      "speed": 35
    }
  },
  {
    "no": 105,
    "name": "ガラガラ",
    "abilities": ["いしあたま", "ひらいしん"],
    "stats": {
      "hp": 60,
      "attack": 80,
      "defense": 110,
      "spAttack": 50,
      "spDefense": 80,
      "speed": 45
    }
  },
  {
    "no": 106,
    "name": "サワムラー",
    "abilities": ["じゅうなん", "すてみ"],
    "stats": {
      "hp": 50,
      "attack": 120,
      "defense": 53,
      "spAttack": 35,
      "spDefense": 110,
      "speed": 87
    }
  },
  {
    "no": 107,
    "name": "エビワラー",
    "abilities": ["するどいめ", "てつのこぶし"],
    "stats": {
      "hp": 50,
      "attack": 105,
      "defense": 79,
      "spAttack": 35,
      "spDefense": 110,
      "speed": 76
    }
  },
  {
    "no": 108,
    "name": "ベロリンガ",
    "abilities": ["マイペース", "どんかん"],
    "stats": {
      "hp": 90,
      "attack": 55,
      "defense": 75,
      "spAttack": 60,
      "spDefense": 75,
      "speed": 30
    }
  },
  {
    "no": 109,
    "name": "ドガース",
    "abilities": ["ふゆう"],
    "stats": {
      "hp": 40,
      "attack": 65,
      "defense": 95,
      "spAttack": 60,
      "spDefense": 45,
      "speed": 35
    }
  },
  {
    "no": 110,
    "name": "マタドガス",
    "abilities": ["ふゆう"],
    "stats": {
      "hp": 65,
      "attack": 90,
      "defense": 120,
      "spAttack": 85,
      "spDefense": 70,
      "speed": 60
    }
  },
  {
    "no": 111,
    "name": "サイホーン",
    "abilities": ["ひらいしん", "いしあたま"],
    "stats": {
      "hp": 80,
      "attack": 85,
      "defense": 95,
      "spAttack": 30,
      "spDefense": 30,
      "speed": 25
    }
  },
  {
    "no": 112,
    "name": "サイドン",
    "abilities": ["ひらいしん", "いしあたま"],
    "stats": {
      "hp": 105,
      "attack": 130,
      "defense": 120,
      "spAttack": 45,
      "spDefense": 45,
      "speed": 40
    }
  },
  {
    "no": 113,
    "name": "ラッキー",
    "abilities": ["しぜんかいふく", "てんのめぐみ"],
    "stats": {
      "hp": 250,
      "attack": 5,
      "defense": 5,
      "spAttack": 35,
      "spDefense": 105,
      "speed": 50
    }
  },
  {
    "no": 114,
    "name": "モンジャラ",
    "abilities": ["ようりょくそ", "リーフガード"],
    "stats": {
      "hp": 65,
      "attack": 55,
      "defense": 115,
      "spAttack": 100,
      "spDefense": 40,
      "speed": 60
    }
  },
  {
    "no": 115,
    "name": "ガルーラ",
    "abilities": ["はやおき", "きもったま"],
    "stats": {
      "hp": 105,
      "attack": 95,
      "defense": 80,
      "spAttack": 40,
      "spDefense": 80,
      "speed": 90
    }
  },
  {
    "no": 116,
    "name": "タッツー",
    "abilities": ["すいすい", "スナイパー"],
    "stats": {
      "hp": 30,
      "attack": 40,
      "defense": 70,
      "spAttack": 70,
      "spDefense": 25,
      "speed": 60
    }
  },
  {
    "no": 117,
    "name": "シードラ",
    "abilities": ["どくのトゲ", "スナイパー"],
    "stats": {
      "hp": 55,
      "attack": 65,
      "defense": 95,
      "spAttack": 95,
      "spDefense": 45,
      "speed": 85
    }
  },
  {
    "no": 118,
    "name": "トサキント",
    "abilities": ["すいすい", "みずのベール"],
    "stats": {
      "hp": 45,
      "attack": 67,
      "defense": 60,
      "spAttack": 35,
      "spDefense": 50,
      "speed": 63
    }
  },
  {
    "no": 119,
    "name": "アズマオウ",
    "abilities": ["すいすい", "みずのベール"],
    "stats": {
      "hp": 80,
      "attack": 92,
      "defense": 65,
      "spAttack": 65,
      "spDefense": 80,
      "speed": 68
    }
  },
  {
    "no": 120,
    "name": "ヒトデマン",
    "abilities": ["はっこう", "しぜんかいふく"],
    "stats": {
      "hp": 30,
      "attack": 45,
      "defense": 55,
      "spAttack": 70,
      "spDefense": 55,
      "speed": 85
    }
  },
  {
    "no": 121,
    "name": "スターミー",
    "abilities": ["はっこう", "しぜんかいふく"],
    "stats": {
      "hp": 60,
      "attack": 75,
      "defense": 85,
      "spAttack": 100,
      "spDefense": 85,
      "speed": 115
    }
  },
  {
    "no": 122,
    "name": "バリヤード",
    "abilities": ["ぼうおん", "フィルター"],
    "stats": {
      "hp": 40,
      "attack": 45,
      "defense": 65,
      "spAttack": 100,
      "spDefense": 120,
      "speed": 90
    }
  },
  {
    "no": 123,
    "name": "ストライク",
    "abilities": ["むしのしらせ", "テクニシャン"],
    "stats": {
      "hp": 70,
      "attack": 110,
      "defense": 80,
      "spAttack": 55,
      "spDefense": 80,
      "speed": 105
    }
  },
  {
    "no": 124,
    "name": "ルージュラ",
    "abilities": ["どんかん", "よちむ"],
    "stats": {
      "hp": 65,
      "attack": 50,
      "defense": 35,
      "spAttack": 115,
      "spDefense": 95,
      "speed": 95
    }
  },
  {
    "no": 125,
    "name": "エレブー",
    "abilities": ["せいでんき"],
    "stats": {
      "hp": 65,
      "attack": 83,
      "defense": 57,
      "spAttack": 95,
      "spDefense": 85,
      "speed": 105
    }
  },
  {
    "no": 126,
    "name": "ブーバー",
    "abilities": ["ほのおのからだ"],
    "stats": {
      "hp": 65,
      "attack": 95,
      "defense": 57,
      "spAttack": 100,
      "spDefense": 85,
      "speed": 93
    }
  },
  {
    "no": 127,
    "name": "カイロス",
    "abilities": ["かいりきバサミ", "かたやぶり"],
    "stats": {
      "hp": 65,
      "attack": 125,
      "defense": 100,
      "spAttack": 55,
      "spDefense": 70,
      "speed": 85
    }
  },
  {
    "no": 128,
    "name": "ケンタロス",
    "abilities": ["いかく", "いかりのつぼ"],
    "stats": {
      "hp": 75,
      "attack": 100,
      "defense": 95,
      "spAttack": 40,
      "spDefense": 70,
      "speed": 110
    }
  },
  {
    "no": 129,
    "name": "コイキング",
    "abilities": ["すいすい"],
    "stats": {
      "hp": 20,
      "attack": 10,
      "defense": 55,
      "spAttack": 15,
      "spDefense": 20,
      "speed": 80
    }
  },
  {
    "no": 130,
    "name": "ギャラドス",
    "abilities": ["いかく"],
    "stats": {
      "hp": 95,
      "attack": 125,
      "defense": 79,
      "spAttack": 60,
      "spDefense": 100,
      "speed": 81
    }
  },
  {
    "no": 131,
    "name": "ラプラス",
    "abilities": ["ちょすい", "シェルアーマー"],
    "stats": {
      "hp": 130,
      "attack": 85,
      "defense": 80,
      "spAttack": 85,
      "spDefense": 95,
      "speed": 60
    }
  },
  {
    "no": 132,
    "name": "メタモン",
    "abilities": ["じゅうなん"],
    "stats": {
      "hp": 48,
      "attack": 48,
      "defense": 48,
      "spAttack": 48,
      "spDefense": 48,
      "speed": 48
    }
  },
  {
    "no": 133,
    "name": "イーブイ",
    "abilities": ["にげあし", "てきおうりょく"],
    "stats": {
      "hp": 55,
      "attack": 55,
      "defense": 50,
      "spAttack": 45,
      "spDefense": 65,
      "speed": 55
    }
  },
  {
    "no": 134,
    "name": "シャワーズ",
    "abilities": ["ちょすい"],
    "stats": {
      "hp": 130,
      "attack": 65,
      "defense": 60,
      "spAttack": 110,
      "spDefense": 95,
      "speed": 65
    }
  },
  {
    "no": 135,
    "name": "サンダース",
    "abilities": ["ちくでん"],
    "stats": {
      "hp": 65,
      "attack": 65,
      "defense": 60,
      "spAttack": 110,
      "spDefense": 95,
      "speed": 130
    }
  },
  {
    "no": 136,
    "name": "ブースター",
    "abilities": ["もらいび"],
    "stats": {
      "hp": 65,
      "attack": 130,
      "defense": 60,
      "spAttack": 95,
      "spDefense": 110,
      "speed": 65
    }
  },
  {
    "no": 137,
    "name": "ポリゴン",
    "abilities": ["トレース", "ダウンロード"],
    "stats": {
      "hp": 65,
      "attack": 60,
      "defense": 70,
      "spAttack": 85,
      "spDefense": 75,
      "speed": 40
    }
  },
  {
    "no": 138,
    "name": "オムナイト",
    "abilities": ["すいすい", "シェルアーマー"],
    "stats": {
      "hp": 35,
      "attack": 40,
      "defense": 100,
      "spAttack": 90,
      "spDefense": 55,
      "speed": 35
    }
  },
  {
    "no": 139,
    "name": "オムスター",
    "abilities": ["すいすい", "シェルアーマー"],
    "stats": {
      "hp": 70,
      "attack": 60,
      "defense": 125,
      "spAttack": 115,
      "spDefense": 70,
      "speed": 55
    }
  },
  {
    "no": 140,
    "name": "カブト",
    "abilities": ["すいすい", "カブトアーマー"],
    "stats": {
      "hp": 30,
      "attack": 80,
      "defense": 90,
      "spAttack": 55,
      "spDefense": 45,
      "speed": 55
    }
  },
  {
    "no": 141,
    "name": "カブトプス",
    "abilities": ["すいすい", "カブトアーマー"],
    "stats": {
      "hp": 60,
      "attack": 115,
      "defense": 105,
      "spAttack": 65,
      "spDefense": 70,
      "speed": 80
    }
  },
  {
    "no": 142,
    "name": "プテラ",
    "abilities": ["いしあたま", "プレッシャー"],
    "stats": {
      "hp": 80,
      "attack": 105,
      "defense": 65,
      "spAttack": 60,
      "spDefense": 75,
      "speed": 130
    }
  },
  {
    "no": 143,
    "name": "カビゴン",
    "abilities": ["めんえき", "あついしぼう"],
    "stats": {
      "hp": 160,
      "attack": 110,
      "defense": 65,
      "spAttack": 65,
      "spDefense": 110,
      "speed": 30
    }
  },
  {
    "no": 144,
    "name": "フリーザー",
    "abilities": ["プレッシャー"],
    "stats": {
      "hp": 90,
      "attack": 85,
      "defense": 100,
      "spAttack": 95,
      "spDefense": 125,
      "speed": 85
    }
  },
  {
    "no": 145,
    "name": "サンダー",
    "abilities": ["プレッシャー"],
    "stats": {
      "hp": 90,
      "attack": 90,
      "defense": 85,
      "spAttack": 125,
      "spDefense": 90,
      "speed": 100
    }
  },
  {
    "no": 146,
    "name": "ファイヤー",
    "abilities": ["プレッシャー"],
    "stats": {
      "hp": 90,
      "attack": 100,
      "defense": 90,
      "spAttack": 125,
      "spDefense": 85,
      "speed": 90
    }
  },
  {
    "no": 147,
    "name": "ミニリュウ",
    "abilities": ["だっび"],
    "stats": {
      "hp": 41,
      "attack": 64,
      "defense": 45,
      "spAttack": 50,
      "spDefense": 50,
      "speed": 50
    }
  },
  {
    "no": 148,
    "name": "ハクリュー",
    "abilities": ["だっび"],
    "stats": {
      "hp": 61,
      "attack": 84,
      "defense": 65,
      "spAttack": 70,
      "spDefense": 70,
      "speed": 70
    }
  },
  {
    "no": 149,
    "name": "カイリュー",
    "abilities": ["せいしんりょく"],
    "stats": {
      "hp": 91,
      "attack": 134,
      "defense": 95,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 80
    }
  },
  {
    "no": 150,
    "name": "ミュウツー",
    "abilities": ["プレッシャー"],
    "stats": {
      "hp": 106,
      "attack": 110,
      "defense": 90,
      "spAttack": 154,
      "spDefense": 90,
      "speed": 130
    }
  },
  {
    "no": 151,
    "name": "ミュウ",
    "abilities": ["シンクロ"],
    "stats": {
      "hp": 100,
      "attack": 100,
      "defense": 100,
      "spAttack": 100,
      "spDefense": 100,
      "speed": 100
    }
  }
]
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?