├── .all-contributorsrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .gitignore ├── .gitmojirc ├── .huskyrc ├── .lintstagedrc ├── .node-version ├── .npmrc ├── .nycrc ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── LICENSE ├── README-jp.md ├── README.md ├── ava.config.js ├── gifs ├── commit.gif ├── init.gif ├── list.gif ├── remove.gif └── search.gif ├── package.json ├── renovate.json ├── src ├── commands │ ├── commit │ │ ├── index.ts │ │ ├── withClient.ts │ │ └── withHook.ts │ ├── hook │ │ ├── create │ │ │ └── index.ts │ │ ├── hook.ts │ │ ├── index.ts │ │ └── remove │ │ │ └── index.ts │ ├── index.ts │ └── list │ │ └── index.ts └── index.ts ├── tsconfig.json └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "customizable-gitmoji-cli", 3 | "projectOwner": "SnO2WMaN", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": ["README.md", "README-jp.md"], 7 | "imageSize": 100, 8 | "commit": true, 9 | "commitConvention": "gitmoji", 10 | "contributors": [ 11 | { 12 | "login": "SnO2WMaN", 13 | "name": "SnO₂WMaN", 14 | "avatar_url": "https://avatars3.githubusercontent.com/u/15155608?v=4", 15 | "profile": "https://sno2wman.dev/", 16 | "contributions": ["code", "maintenance"] 17 | }, 18 | { 19 | "login": "renovate-bot", 20 | "name": "Renovate Bot", 21 | "avatar_url": "https://avatars0.githubusercontent.com/u/25180681?v=4", 22 | "profile": "https://renovatebot.com", 23 | "contributions": ["infra"] 24 | }, 25 | { 26 | "login": "carloscuesta", 27 | "name": "Carlos Cuesta", 28 | "avatar_url": "https://avatars1.githubusercontent.com/u/7629661?v=4", 29 | "profile": "https://carloscuesta.me", 30 | "contributions": ["ideas"] 31 | }, 32 | { 33 | "login": "0918nobita", 34 | "name": "0918nobita", 35 | "avatar_url": "https://avatars1.githubusercontent.com/u/8453302?v=4", 36 | "profile": "https://twitter.com/0918nobita", 37 | "contributions": ["bug", "security"] 38 | } 39 | ], 40 | "contributorsPerLine": 7 41 | } 42 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | [*] 3 | indent_style = space 4 | indent_size = 2 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.yml] 11 | indent_style = space 12 | 13 | [.node-version] 14 | insert_final_newline = false 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | dist/ 4 | lib/ 5 | 6 | coverage/ 7 | snapshots/ 8 | 9 | .nyc_output/ 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": [ 4 | "@sno2wman/eslint-config-typescript", 5 | "@sno2wman/eslint-config/+ava" 6 | ], 7 | "parserOptions": { 8 | "project": "./tsconfig.json" 9 | }, 10 | "settings": { 11 | "import/resolver": { 12 | "typescript": { 13 | "alwaysTryTypes": true 14 | } 15 | } 16 | }, 17 | "rules": { 18 | "import/extensions": 0, 19 | "unicorn/filename-case": [ 20 | 2, 21 | { "cases": { "pascalCase": true, "camelCase": true } } 22 | ], 23 | "unicorn/no-process-exit": 0, 24 | "@typescript-eslint/restrict-template-expressions": [ 25 | 2, 26 | { "allowNumber": true } 27 | ] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: SnO2WMaN 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: SnO2WMaN 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Hello @SnO2WMaN! 2 | 3 | ### Issue 4 | 5 | ### Env 6 | 7 | - **OS**: 8 | - **gitmoji-cli -v**: 9 | - **node -v**: 10 | 11 | ### .gitmojirc 12 | 13 | ```json 14 | 15 | ``` 16 | 17 | ### Error message 18 | 19 | ``` 20 | 21 | ``` 22 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Issue: # 4 | 5 | ## Tests 6 | 7 | - [ ] All tests passed. 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | default: 7 | runs-on: ubuntu-latest 8 | env: 9 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Get Node.js version 13 | id: node-version 14 | run: echo "::set-output name=version::$(cat .node-version)" 15 | - name: Setup Node.js 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ steps.node-version.version }} 19 | - name: Setup yarn 20 | run: | 21 | curl -o- -L https://yarnpkg.com/install.sh | bash 22 | export PATH="$HOME/.yarn/bin:$PATH" 23 | - name: Get yarn cache dir 24 | id: yarn-cache 25 | run: echo "::set-output name=dir::$(yarn cache dir)" 26 | - name: Cache 27 | uses: actions/cache@v1 28 | with: 29 | path: ${{ steps.yarn-cache.outputs.dir }} 30 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 31 | restore-keys: | 32 | ${{ runner.os }}-yarn- 33 | - name: Install dependencies 34 | run: yarn --frozen-lockfile 35 | - name: Lint 36 | run: npm run lint 37 | env: 38 | CI: true 39 | - name: Build 40 | run: npm run build 41 | env: 42 | CI: true 43 | - name: Codecov 44 | run: npx codecov 45 | env: 46 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 47 | - name: Publish 48 | run: npm publish 49 | if: contains(github.ref, 'tags/v') 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | dist/ 4 | lib/ 5 | 6 | coverage/ 7 | 8 | .env 9 | .envrc 10 | 11 | *.log 12 | *.cache 13 | 14 | .nyc_output/ 15 | -------------------------------------------------------------------------------- /.gitmojirc: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "gitmojis": [ 4 | { 5 | "emoji": "✨", 6 | "description": "Introduce new features.", 7 | "name": "sparkles", 8 | "tags": [ 9 | "feat" 10 | ] 11 | }, 12 | { 13 | "emoji": "👍", 14 | "description": "Improve features.", 15 | "name": "thumbsup", 16 | "tags": [ 17 | "improve", 18 | "update" 19 | ] 20 | }, 21 | { 22 | "emoji": "⚡️", 23 | "description": "Update about performance.", 24 | "name": "zap", 25 | "tags": [ 26 | "performance" 27 | ] 28 | }, 29 | { 30 | "emoji": "🐛", 31 | "description": "Fix bugs.", 32 | "name": "bug", 33 | "tags": [ 34 | "bug", 35 | "fix" 36 | ] 37 | }, 38 | { 39 | "emoji": "🚑", 40 | "description": "Create a hotfix.", 41 | "name": "ambulance", 42 | "tags": [ 43 | "bug", 44 | "fix", 45 | "hotfix" 46 | ] 47 | }, 48 | { 49 | "emoji": "♻️", 50 | "description": "Refactor codes.", 51 | "name": "recycle", 52 | "tags": [ 53 | "refactor" 54 | ] 55 | }, 56 | { 57 | "emoji": "🔧", 58 | "description": "Update configurations.", 59 | "name": "wrench", 60 | "tags": [ 61 | "config", 62 | "setting" 63 | ], 64 | "scopes": [ 65 | "eslint", 66 | "stylelint", 67 | "prettier", 68 | "lint-staged", 69 | "husky", 70 | "gitmoji", 71 | "typescript" 72 | ] 73 | }, 74 | { 75 | "emoji": "🎨", 76 | "description": "Update UI/UX.", 77 | "name": "art", 78 | "tags": [ 79 | "ui", 80 | "ux" 81 | ] 82 | }, 83 | { 84 | "emoji": "🔥", 85 | "description": "Remove codes.", 86 | "name": "fire", 87 | "tags": [ 88 | "remove" 89 | ] 90 | }, 91 | { 92 | "emoji": "🚨", 93 | "description": "Add/Update tests.", 94 | "name": "warning", 95 | "tags": [ 96 | "test" 97 | ] 98 | }, 99 | { 100 | "emoji": "🏗", 101 | "description": "Update structures.", 102 | "name": "building_construction", 103 | "tags": [ 104 | "structure" 105 | ] 106 | }, 107 | { 108 | "emoji": "🔒", 109 | "description": "Update security.", 110 | "name": "lock", 111 | "tags": [ 112 | "security" 113 | ] 114 | }, 115 | { 116 | "emoji": "🚥", 117 | "description": "Resolve Linter warning.", 118 | "name": "traffic_light", 119 | "tags": [ 120 | "lint" 121 | ] 122 | }, 123 | { 124 | "emoji": "🚧", 125 | "description": "Work in progress.", 126 | "name": "construction", 127 | "tags": [ 128 | "wip" 129 | ] 130 | }, 131 | { 132 | "emoji": "⚓️", 133 | "description": "Salvage old features.", 134 | "name": "anchor", 135 | "tags": [ 136 | "salvage" 137 | ] 138 | }, 139 | { 140 | "emoji": "💥", 141 | "description": "make a breaking change.", 142 | "name": "boom", 143 | "tags": [ 144 | "breaking" 145 | ] 146 | }, 147 | { 148 | "emoji": "🧪", 149 | "description": "Add experimental features.", 150 | "name": "test_tube", 151 | "tags": [ 152 | "beta", 153 | "experimental" 154 | ] 155 | }, 156 | { 157 | "emoji": "👷", 158 | "description": "Maintain infrastructure.", 159 | "name": "construction_worker", 160 | "tags": [ 161 | "infra", 162 | "ci" 163 | ], 164 | "scopes": [ 165 | "circle ci", 166 | "renovate", 167 | "github actions" 168 | ] 169 | }, 170 | { 171 | "emoji": "🌐", 172 | "description": "Translate.", 173 | "name": "globe_with_meridians", 174 | "tags": [ 175 | "translate", 176 | "i18n", 177 | "l10n" 178 | ], 179 | "scopes": [ 180 | { 181 | "name": "ja", 182 | "description": "Japanese" 183 | }, 184 | { 185 | "name": "en", 186 | "description": "English" 187 | } 188 | ] 189 | }, 190 | { 191 | "emoji": "📖", 192 | "description": "Write docs.", 193 | "name": "open_book", 194 | "tags": [ 195 | "docs", 196 | "readme" 197 | ] 198 | }, 199 | { 200 | "emoji": "💬", 201 | "description": "Update literal or text.", 202 | "name": "speech_balloon", 203 | "tags": [ 204 | "text", 205 | "literal" 206 | ] 207 | }, 208 | { 209 | "emoji": "🚚", 210 | "description": "Transfer files.", 211 | "name": "truck", 212 | "tags": [ 213 | "move" 214 | ] 215 | }, 216 | { 217 | "emoji": "🍱", 218 | "description": "Add assets.", 219 | "name": "bento", 220 | "tags": [ 221 | "assets", 222 | "images" 223 | ] 224 | }, 225 | { 226 | "emoji": "📷", 227 | "description": "Update snapshots.", 228 | "name": "camera", 229 | "tags": [ 230 | "snapshots", 231 | "test" 232 | ] 233 | }, 234 | { 235 | "emoji": "🧹", 236 | "description": "Format codes.", 237 | "name": "bloom", 238 | "tags": [ 239 | "format", 240 | "prettier" 241 | ] 242 | }, 243 | { 244 | "emoji": "⬆️", 245 | "description": "Updgrade dependencies.", 246 | "name": "arrow_up", 247 | "tags": [ 248 | "dependencies", 249 | "upgrade" 250 | ] 251 | }, 252 | { 253 | "emoji": "⬇️", 254 | "description": "Downgrade dependencies.", 255 | "name": "arrow_down", 256 | "tags": [ 257 | "dependencies", 258 | "downgrade" 259 | ] 260 | }, 261 | { 262 | "emoji": "➕", 263 | "description": "Add dependencies.", 264 | "name": "heavy_plus_sign", 265 | "tags": [ 266 | "dependencies", 267 | "add" 268 | ] 269 | }, 270 | { 271 | "emoji": "➖", 272 | "description": "Remove dependencies.", 273 | "name": "heavy_minus_sign", 274 | "tags": [ 275 | "dependencies", 276 | "remove" 277 | ] 278 | }, 279 | { 280 | "emoji": "📌", 281 | "description": "Pin dependencies to specific versions.", 282 | "name": "pushpin", 283 | "tags": [ 284 | "dependencies", 285 | "pin" 286 | ] 287 | }, 288 | { 289 | "emoji": "🆗", 290 | "description": "OK for the review.", 291 | "name": "ok", 292 | "tags": [ 293 | "review" 294 | ] 295 | }, 296 | { 297 | "emoji": "⏪", 298 | "description": "Revert changes.", 299 | "name": "rewind", 300 | "tags": [ 301 | "rewind" 302 | ] 303 | }, 304 | { 305 | "emoji": "🔀", 306 | "description": "Merge branches.", 307 | "name": "twisted_rightwards_arrows", 308 | "tags": [ 309 | "merge" 310 | ] 311 | }, 312 | { 313 | "emoji": "📄", 314 | "description": "Attach a license.", 315 | "name": "page_facing_up", 316 | "tags": [ 317 | "license" 318 | ] 319 | }, 320 | { 321 | "emoji": "🔖", 322 | "description": "Release.", 323 | "name": "bookmark", 324 | "tags": [ 325 | "version" 326 | ] 327 | }, 328 | { 329 | "emoji": "🚀", 330 | "description": "Deploy.", 331 | "name": "rocket", 332 | "tags": [ 333 | "deploy" 334 | ] 335 | }, 336 | { 337 | "emoji": "🙈", 338 | "description": "Ignore things.", 339 | "name": "see_no_evil", 340 | "tags": [ 341 | "ignore" 342 | ] 343 | }, 344 | { 345 | "emoji": "👥", 346 | "description": "Add a contributor.", 347 | "name": "busts_in_silhouette", 348 | "tags": [ 349 | "contributor" 350 | ] 351 | }, 352 | { 353 | "emoji": "💵", 354 | "description": "Add financial things.", 355 | "name": "dollar", 356 | "tags": [ 357 | "funding" 358 | ] 359 | }, 360 | { 361 | "emoji": "🔺", 362 | "description": "Use as a commit separator.", 363 | "name": "small_red_triangle" 364 | }, 365 | { 366 | "emoji": "🎉", 367 | "description": "Init.", 368 | "name": "tada", 369 | "tags": [ 370 | "init" 371 | ] 372 | } 373 | ] 374 | } 375 | -------------------------------------------------------------------------------- /.huskyrc: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "pre-commit": "lint-staged" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.md": [ 3 | "prettier --write", 4 | "git add" 5 | ], 6 | "*.{js,ts}": [ 7 | "eslint --fix", 8 | "prettier --write", 9 | "git add" 10 | ], 11 | "*.yml": [ 12 | "prettier --write", 13 | "git add" 14 | ], 15 | "*.json": [ 16 | "prettier --write", 17 | "git add" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 12.14.0 -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | message="🔖 %s" 2 | //registry.npmjs.org/:_authToken=${NPM_TOKEN} 3 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src/**/*.ts"], 3 | "extension": [".ts"], 4 | "require": ["ts-node/register"], 5 | "reporter": ["text", "text-summary", "html"], 6 | "sourceMap": true 7 | } 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | dist/ 4 | lib/ 5 | 6 | coverage/ 7 | snapshots/ 8 | 9 | .nyc_output/ 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | "@sno2wman/prettier-config" 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 SnO₂WMaN 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-jp.md: -------------------------------------------------------------------------------- 1 |

customizable-gitmoji-cli

2 | 3 |

カスタマイズ可能なgitmoji-cli!

4 | 5 | --- 6 | 7 |

8 | npm version 9 | 10 |

11 |

12 | 13 | [![Github Action](https://github.com/SnO2WMaN/customizable-gitmoji-cli/workflows/Node%20CI/badge.svg)](https://github.com/SnO2WMaN/customizable-gitmoji-cli/actions) 14 | [![codecov](https://codecov.io/gh/SnO2WMaN/customizable-gitmoji-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/SnO2WMaN/customizable-gitmoji-cli) 15 | [![Maintainability](https://api.codeclimate.com/v1/badges/2cff863272e7a47dd100/maintainability)](https://codeclimate.com/github/SnO2WMaN/customizable-gitmoji-cli/maintainability) 16 | 17 |
18 |

19 | 20 |

21 |

22 | 23 | [![LICENSE](https://img.shields.io/github/license/conten2/eslint-config?style=flat-square)](https://www.npmjs.com/package/@conten2/eslint-config) 24 | [![Renovate](https://img.shields.io/badge/renovate-enabled-25c4c3.svg?style=flat-square)](https://renovatebot.com/) 25 | [![Gitmoji](https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square)](https://gitmoji.carloscuesta.me) 26 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) 27 | 28 |
29 |

30 | 31 |

32 |

33 | 34 | 35 | 36 | [![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-) 37 | 38 | 39 | 40 |
41 |

42 | 43 | --- 44 | 45 |

46 | 47 |

48 | 49 | [日本語](https://github.com/SnO2WMaN/customizable-gitmoji-cli/blob/master/README-jp.md) / [English](https://github.com/SnO2WMaN/customizable-gitmoji-cli#readme) 50 | 51 | **この`README-jp.md`を「正しい」英語に訳してくれる人間を探しています。** 52 | 53 |
54 | 55 |

56 | 57 | --- 58 | 59 | ## インストール 📥 60 | 61 | ```bash 62 | npm i -g customizable-gitmoji-cli 63 | 64 | yarn global add customizable-gitmoji-cli 65 | ``` 66 | 67 | 挙動について保証出来ないので、オリジナルの gitmoji-cli はアンインストールしてください。 68 | 69 | ```bash 70 | npm uninstall -g gitmoji-cli 71 | 72 | yarn global remove gitmoji-cli 73 | ``` 74 | 75 | ## 使用方法 🧰 76 | 77 | 任意の git プロジェクトで以下のコマンドを叩いてください。 78 | 79 | ```bash 80 | gitmoji init 81 | ``` 82 | 83 | ![gitmoji init](gifs/init.gif) 84 | 85 | コミット時に自動で gitmoji-cli が起動します。 86 | 87 | ![gitmoji init](gifs/commit.gif) 88 | 89 | ## コマンド ⌨️ 90 | 91 | ``` 92 | gitmoji v1.0.0 93 | 94 | Usage: 95 | $ gitmoji [options] 96 | 97 | Commands: 98 | init Initialize gitmoji as a commit hook 99 | remove Remove a previously initialized commit hook 100 | commit Interactively commit using the prompts 101 | list List all the available gitmojis 102 | search [query] Search gitmojis 103 | 104 | For more info, run any command with the `--help` flag: 105 | $ gitmoji init --help 106 | $ gitmoji remove --help 107 | $ gitmoji commit --help 108 | $ gitmoji list --help 109 | $ gitmoji search --help 110 | 111 | Options: 112 | -v, --version Display version number 113 | -h, --help Display this message 114 | ``` 115 | 116 | ### init 117 | 118 | コミット時に gitmoji プロンプトを起動するようにフックを掛けます。 119 | 120 | ### remove 121 | 122 | コミット時に起動する gitmoji プロンプトを解除します。 123 | 124 | ### commit 125 | 126 | gitmoji プロンプトをマニュアルで実行します。 127 | 128 | 特に理由がなければ `gitmoji init`でフックを掛けてください。 129 | 130 | ### list 131 | 132 | `.gitmojirc`から利用可能な全ての gitmoji を列挙します。 133 | 134 | ![gitmoji list](gifs/list.gif) 135 | 136 | ### search 137 | 138 | 条件に合致する gitmoji を探します。 139 | 140 | ![gitmoji search](gifs/search.gif) 141 | 142 | ## コンフィグファイル 🔧 143 | 144 | [cosmiconfig](https://github.com/davidtheclark/cosmiconfig)に基づいて、`.gitmojirc`などの設定ファイルを読み込みます。 145 | 146 | ### 例 147 | 148 | ```json 149 | { 150 | "emojiFormat": "code", 151 | "autoAdd": false, 152 | "signedCommit": false, 153 | "titleMaxLength": 48, 154 | "presets": "base" 155 | "rules": [ 156 | { 157 | "emoji": "🤡", 158 | "description": "Everything must go!!", 159 | "name": "clown_face" 160 | } 161 | ], 162 | "order": [ 163 | "ok_hand" 164 | ], 165 | "scopes": ["frontend", "backend"] 166 | } 167 | ``` 168 | 169 | ### `emojiFormat` 170 | 171 | コミット時に添付される絵文字のフォーマットを選択できます。 172 | 173 | - emoji 174 | - 👌, 🐶, 🔪 175 | - code 176 | - `:ok_hand:`, `:dog:`, `:knife:` 177 | 178 | のどちらかを使用できます。 179 | 180 | **デフォルト**: `code` 181 | 182 | ### `autoAdd` 183 | 184 | コミット時に自動で`git add .`を実行します。 185 | 186 | **デフォルト**: `false` 187 | 188 | ### `signedCommit` 189 | 190 | 署名付きコミットを行います。 191 | 192 | **デフォルト**: `false` 193 | 194 | ### `titleMaxLength` 195 | 196 | コミットメッセージの長さを設定します。72 文字以下で設定してください。 197 | 198 | **デフォルト**: `48` 199 | 200 | ### `presets` 201 | 202 | 読み込む`gitmoji-presets`を列挙します。 203 | 204 | **デフォルト**: `base` 205 | 206 | **TODO:詳細は今後記載します。** 207 | 208 | ### `rules` 209 | 210 | gitmoji を定義します。以下のように記載してください。 211 | 212 | [ikatyang/emoji-cheat-sheet](https://github.com/ikatyang/emoji-cheat-sheet)は役に立つでしょう。 213 | 214 | ```json 215 | { 216 | "emoji": "🦍", 217 | "description": "Feel good.", 218 | "name": "gorilla" 219 | } 220 | ``` 221 | 222 | ### `order` 223 | 224 | 順序を指定します。指定された gitmoji はより優先されます。 225 | 226 | ### `scopes` 227 | 228 | 選択できるスコープを列挙します。スコープを指定した場合、以下のようなコミットメッセージになります。 229 | 230 | ``` 231 | 📷(scope) commit message. 232 | 233 | :camera:(scope) commit message. 234 | ``` 235 | 236 | ## Contributors 👥 237 | 238 | 以下の方々には感謝しかありません ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 |
SnO₂WMaN
SnO₂WMaN

💻 🚧
Renovate Bot
Renovate Bot

🚇
Carlos Cuesta
Carlos Cuesta

🤔
0918nobita
0918nobita

🐛 🛡️
251 | 252 | 253 | 254 | 255 | 256 | 257 | このプロジェクトは [all-contributors](https://github.com/all-contributors/all-contributors) に準拠しています。どのような貢献もお待ちしています! 258 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

customizable-gitmoji-cli

2 | 3 |

Customizable gitmoji-cli.

4 | 5 | --- 6 | 7 |
8 | 9 |

10 | 11 | [![npm](https://img.shields.io/npm/v/cz-gitmoji-cli?logo=npm&style=for-the-badge)](https://www.npmjs.com/package/customizable-gitmoji-cli) 12 | 13 |

14 |

15 | 16 | [![Github Action](https://github.com/SnO2WMaN/customizable-gitmoji-cli/workflows/Node%20CI/badge.svg)](https://github.com/SnO2WMaN/customizable-gitmoji-cli/actions) 17 | [![codecov](https://codecov.io/gh/SnO2WMaN/customizable-gitmoji-cli/branch/master/graph/badge.svg)](https://codecov.io/gh/SnO2WMaN/customizable-gitmoji-cli) 18 | 19 |

20 |

21 | 22 | [![license](https://img.shields.io/npm/l/cz-gitmoji-cli?style=flat-square)](https://github.com/SnO2WMaN/customizable-gitmoji-cli/blob/master/LICENSE) 23 | [![Renovate](https://img.shields.io/badge/renovate-enabled-25c4c3.svg?style=flat-square)](https://renovatebot.com/) 24 | [![Gitmoji](https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square)](https://gitmoji.carloscuesta.me) 25 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) 26 | 27 |

28 |

29 | 30 | 31 | 32 | [![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-) 33 | 34 | 35 | 36 |

37 | 38 |
39 | 40 | --- 41 | 42 | ## Contributors ✨ 43 | 44 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
SnO₂WMaN
SnO₂WMaN

💻 🚧
Renovate Bot
Renovate Bot

🚇
Carlos Cuesta
Carlos Cuesta

🤔
0918nobita
0918nobita

🐛 🛡️
57 | 58 | 59 | 60 | 61 | 62 | 63 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 64 | -------------------------------------------------------------------------------- /ava.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | compileEnhancements: false, 3 | extensions: ['ts'], 4 | require: ['ts-node/register', 'tsconfig-paths/register'] 5 | } 6 | -------------------------------------------------------------------------------- /gifs/commit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnO2WMaN/customizable-gitmoji-cli/5b05f0ab1d28534df783b9aa538bd42fcd41489a/gifs/commit.gif -------------------------------------------------------------------------------- /gifs/init.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnO2WMaN/customizable-gitmoji-cli/5b05f0ab1d28534df783b9aa538bd42fcd41489a/gifs/init.gif -------------------------------------------------------------------------------- /gifs/list.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnO2WMaN/customizable-gitmoji-cli/5b05f0ab1d28534df783b9aa538bd42fcd41489a/gifs/list.gif -------------------------------------------------------------------------------- /gifs/remove.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnO2WMaN/customizable-gitmoji-cli/5b05f0ab1d28534df783b9aa538bd42fcd41489a/gifs/remove.gif -------------------------------------------------------------------------------- /gifs/search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnO2WMaN/customizable-gitmoji-cli/5b05f0ab1d28534df783b9aa538bd42fcd41489a/gifs/search.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "customizable-gitmoji-cli", 3 | "description": "Customizable gitmoji cli", 4 | "license": "MIT", 5 | "author": "SnO2WMaN (https://sno2wman.dev)", 6 | "homepage": "https://github.com/SnO2WMaN/customizable-gitmoji-cli#readme", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/SnO2WMaN/customizable-gitmoji-cli.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/SnO2WMaN/customizable-gitmoji-cli/issues" 13 | }, 14 | "version": "2.0.0-3", 15 | "bin": { 16 | "cz-gitmoji": "lib/index.js" 17 | }, 18 | "files": [ 19 | "lib" 20 | ], 21 | "dependencies": { 22 | "cac": "^6.5.3", 23 | "chalk": "^3.0.0", 24 | "cosmiconfig": "^6.0.0", 25 | "customizable-gitmoji-config-parser": "^0.0.1", 26 | "execa": "^4.0.0", 27 | "fs-extra": "^8.1.0", 28 | "inquirer": "6.5.2", 29 | "inquirer-autocomplete-prompt": "^1.0.1", 30 | "ora": "^4.0.3", 31 | "update-notifier": "^4.0.0" 32 | }, 33 | "devDependencies": { 34 | "@sno2wman/eslint-config": "^1.0.3", 35 | "@sno2wman/eslint-config-typescript": "^1.0.3", 36 | "@sno2wman/gitmoji-preset": "^1.0.1", 37 | "@sno2wman/prettier-config": "^1.0.2", 38 | "@sno2wman/prettier-package-json": "^2.0.2", 39 | "@types/cosmiconfig": "^5.0.3", 40 | "@types/fs-extra": "^8.0.1", 41 | "@types/inquirer": "^6.5.0", 42 | "@types/update-notifier": "^2.5.0", 43 | "all-contributors-cli": "^6.9.3", 44 | "ava": "^2.4.0", 45 | "codecov": "^3.6.1", 46 | "cpx": "^1.5.0", 47 | "eslint": "^6.5.1", 48 | "husky": "^3.0.8", 49 | "lint-staged": "^9.4.1", 50 | "nyc": "^14.1.1", 51 | "prettier": "^1.18.2", 52 | "rimraf": "^3.0.0", 53 | "ts-node": "^8.5.4", 54 | "tsconfig-paths": "^3.9.0", 55 | "typescript": "^3.7.3" 56 | }, 57 | "keywords": [ 58 | "commit", 59 | "emoji", 60 | "gitmoji" 61 | ], 62 | "engines": { 63 | "node": ">=10" 64 | }, 65 | "scripts": { 66 | "prebuild": "rimraf lib", 67 | "build": "tsc", 68 | "postbuild": "cpx 'lib/src/**' lib && rimraf lib/{src,test} lib/package.json", 69 | "fmt": "prettier **/*.{js,json,yml,md} --write", 70 | "lint": "eslint src . --ext .js,.ts --fix", 71 | "test": "nyc ava", 72 | "contributors:add": "all-contributors add", 73 | "contributors:generate": "all-contributors generate", 74 | "postversion": "git push origin --tags" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "github>sno2wman/renovate-config", 4 | ":timezone(Asia/Tokyo)", 5 | "schedule:weekly" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/commands/commit/index.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import inquirer from 'inquirer' 3 | import { GitmojiConfig } from 'customizable-gitmoji-config-parser' 4 | 5 | import withClient from './withClient' 6 | import withHook from './withHook' 7 | 8 | // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires 9 | inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt')) 10 | 11 | export default async (config: GitmojiConfig, hook: boolean) => { 12 | const longestDescription = config 13 | .list() 14 | .reduce((c, { description }) => Math.max(c, description.length), 0) 15 | const gitmojiAnswer = ( 16 | await inquirer.prompt([ 17 | { 18 | name: 'gitmoji', 19 | message: 'Choose a gitmoji:', 20 | type: 'autocomplete', 21 | source: (_: any, input?: string) => 22 | Promise.resolve( 23 | (input && input !== '' ? config.search(input) : config.list()).map( 24 | ({ emoji, name, description, tags }) => ({ 25 | name: [ 26 | emoji, 27 | ' '.repeat(2), 28 | ' │ ', 29 | description, 30 | ' '.repeat(longestDescription - description.length), 31 | ' │ ', 32 | tags.length === 0 33 | ? chalk.italic.grey('None') 34 | : tags.map(tag => chalk.italic.blue(`${tag}`)).join(', ') 35 | ].join(''), 36 | value: name 37 | }) 38 | ) 39 | ) 40 | } 41 | ]) 42 | ).gitmoji as string 43 | const details = config.getByName(gitmojiAnswer) 44 | const longestScope = details.scopes.reduce( 45 | (c, { name }) => Math.max(c, name.length), 46 | 0 47 | ) 48 | let scopeAnswer = ( 49 | await inquirer.prompt([ 50 | { 51 | name: 'scope', 52 | message: 'Choose a scope:', 53 | type: 'list', 54 | choices: [ 55 | ...details.scopes.map(({ name, description }) => ({ 56 | name: [ 57 | name, 58 | ' '.repeat(longestScope - name.length), 59 | ' │ ', 60 | description === '' 61 | ? chalk.gray('No description') 62 | : chalk.blue(description) 63 | ].join(''), 64 | value: name 65 | })), 66 | new inquirer.Separator(), 67 | { name: 'Custom.', value: '_custom' }, 68 | { name: 'None.', value: null } 69 | ] 70 | } 71 | ]) 72 | ).scope as string | null 73 | if (scopeAnswer === '_custom') { 74 | scopeAnswer = ( 75 | await inquirer.prompt([ 76 | { 77 | name: 'scope', 78 | message: 'Input custom scope:', 79 | type: 'input', 80 | validate: (scope: string) => 81 | !scope ? chalk.red('Enter a valid scope') : true 82 | } 83 | ]) 84 | ).scope 85 | } 86 | const maxTitleLength = 87 | 72 - 88 | (config.emojiFormat === 'code' ? gitmojiAnswer.length : 1) - // emoji 89 | (scopeAnswer ? scopeAnswer.length + 2 : 0) - // scope 90 | 1 // space 91 | const titleAnswer = ( 92 | await inquirer.prompt([ 93 | { 94 | name: 'title', 95 | message: 'Enter the commit title', 96 | validate: (title: string) => 97 | !title ? chalk.red('Enter a valid commit title') : true, 98 | transformer: (input: string) => { 99 | return `[${input.length}/${maxTitleLength}]: ${input}` 100 | } 101 | } 102 | ]) 103 | ).title as string 104 | const commitTitle = [ 105 | config.emojiFormat === 'code' ? details.name : details.emoji, 106 | scopeAnswer ? `(${scopeAnswer})` : '', 107 | ' ', 108 | titleAnswer 109 | ] 110 | .join('') 111 | .trim() 112 | 113 | if (hook) withHook(commitTitle) 114 | else await withClient(config, commitTitle) 115 | } 116 | -------------------------------------------------------------------------------- /src/commands/commit/withClient.ts: -------------------------------------------------------------------------------- 1 | import execa from 'execa' 2 | import { GitmojiConfig } from 'customizable-gitmoji-config-parser' 3 | 4 | export default async (config: GitmojiConfig, title: string) => { 5 | try { 6 | if (config.autoAdd) await execa('git', ['add', '.']) 7 | const { stdout } = await execa('git', [ 8 | 'commit', 9 | ...(config.signedCommit ? ['-S'] : []), 10 | '-m', 11 | `${title}` 12 | ]) 13 | console.log(stdout) 14 | } catch (error) { 15 | console.error(error) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/commands/commit/withHook.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | 3 | export default (title: string) => { 4 | try { 5 | fs.writeFileSync(process.argv[3], `${title}`) 6 | } catch (error) { 7 | console.error(error) 8 | process.exit(1) 9 | } finally { 10 | process.exit(0) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/commands/hook/create/index.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | import execa from 'execa' 3 | import ora from 'ora' 4 | 5 | import hook from '../hook' 6 | 7 | export default async () => { 8 | const spinner = ora('Creating the gitmoji commit hook').start() 9 | 10 | try { 11 | const { stdout } = await execa('git', ['rev-parse', '--absolute-git-dir']) 12 | await fs.writeFile(stdout + hook.path, hook.contents, { 13 | mode: hook.permissions 14 | }) 15 | spinner.succeed('Gitmoji commit hook created successfully') 16 | } catch (error) { 17 | spinner.fail(`Error: ${String(error)}`) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/commands/hook/hook.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | permissions: 0o775, 3 | path: '/hooks/prepare-commit-msg', 4 | contents: 5 | '#!/bin/sh\n# gitmoji as a commit hook\nexec < /dev/tty\ncz-gitmoji commit --hook $1\n' 6 | } 7 | -------------------------------------------------------------------------------- /src/commands/hook/index.ts: -------------------------------------------------------------------------------- 1 | import create from './create' 2 | import remove from './remove' 3 | 4 | export default { create, remove } 5 | -------------------------------------------------------------------------------- /src/commands/hook/remove/index.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | import execa from 'execa' 3 | import ora from 'ora' 4 | 5 | import hook from '../hook' 6 | 7 | export default async () => { 8 | const spinner = ora('Creating the gitmoji commit hook').start() 9 | 10 | try { 11 | const { stdout } = await execa('git', ['rev-parse', '--absolute-git-dir']) 12 | await fs.unlink(stdout + hook.path) 13 | spinner.succeed('Gitmoji commit hook removed successfully') 14 | } catch (error) { 15 | spinner.fail(`Error: ${String(error)}`) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/commands/index.ts: -------------------------------------------------------------------------------- 1 | import list from './list' 2 | import hook from './hook' 3 | import commit from './commit' 4 | 5 | export default { 6 | list, 7 | init: hook.create, 8 | remove: hook.remove, 9 | commit 10 | } 11 | -------------------------------------------------------------------------------- /src/commands/list/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import chalk from 'chalk' 3 | 4 | import { GitmojiConfig } from 'customizable-gitmoji-config-parser' 5 | 6 | export default async function(config: GitmojiConfig) { 7 | const list = config.list() 8 | const longestName = list.reduce((c, { name }) => Math.max(c, name.length), 0) 9 | const longestDescription = list.reduce( 10 | (c, { description }) => Math.max(c, description.length), 11 | 0 12 | ) 13 | const separator = ` ${chalk.grey('│')} ` 14 | list.forEach(({ emoji, name, description, tags, scopes }) => { 15 | console.log( 16 | [ 17 | emoji, 18 | ' '.repeat(2), 19 | chalk.bold.cyan(`:${name}:`), 20 | ' '.repeat(longestName - name.length), 21 | separator, 22 | description, 23 | ' '.repeat(longestDescription - description.length), 24 | separator, 25 | tags.length === 0 26 | ? chalk.italic.grey('None') 27 | : tags.map(tag => chalk.italic.blue(`${tag}`)).join(', ') 28 | ].join('') 29 | ) 30 | const longestScope = scopes.reduce( 31 | (c, { name: scopeName }) => Math.max(c, scopeName.length), 32 | 0 33 | ) 34 | scopes.forEach(({ name: scopeName, description: scopeDescription }, i) => { 35 | console.log( 36 | [ 37 | i === scopes.length - 1 ? '└' : '├', 38 | '─ ', 39 | chalk.blue(`(${scopeName})`), 40 | ' '.repeat(longestScope - scopeName.length), 41 | separator, 42 | scopeDescription === '' 43 | ? chalk.grey('No description') 44 | : chalk.white(scopeDescription) 45 | ].join('') 46 | ) 47 | }) 48 | }) 49 | } 50 | /* eslint-enable no-console */ 51 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import cac from 'cac' 4 | import updateNotifier from 'update-notifier' 5 | import { cosmiconfig } from 'cosmiconfig' 6 | import parser from 'customizable-gitmoji-config-parser' 7 | 8 | import package_ from '../package.json' 9 | 10 | import commands from './commands' 11 | 12 | updateNotifier({ pkg: package_ }).notify() 13 | 14 | const cli = cac('cz-gitmoji') 15 | 16 | async function getConfig() { 17 | const result = await cosmiconfig('gitmoji', { cache: false }).search() 18 | return parser(result?.config ?? {}) 19 | } 20 | 21 | cli.command('list', 'List all the available gitmojis').action(async () => { 22 | await commands.list(await getConfig()) 23 | }) 24 | 25 | cli.command('init', 'Initialize gitmoji as a commit hook').action(async () => { 26 | await commands.init() 27 | }) 28 | 29 | cli 30 | .command('remove', 'Remove a previously initialized commit hook') 31 | .action(async () => { 32 | await commands.remove() 33 | }) 34 | 35 | cli 36 | .command('commit', 'Interactively commit using the prompts') 37 | .option('--hook', 'DO NOT USE') 38 | .action(async ({ hook }) => { 39 | await commands.commit(await getConfig(), hook ?? false) 40 | }) 41 | 42 | cli.version(package_.version) 43 | cli.help() 44 | cli.parse() 45 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "commonjs", 5 | "lib": ["ESNext"], 6 | "strict": true, 7 | "sourceMap": true, 8 | "esModuleInterop": true, 9 | "resolveJsonModule": true, 10 | "baseUrl": ".", 11 | "sourceRoot": "src", 12 | "outDir": "lib", 13 | "paths": { 14 | "~/*": ["src/*"] 15 | } 16 | }, 17 | "exclude": ["lib"] 18 | } 19 | --------------------------------------------------------------------------------