├── .DS_Store ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── README.md ├── commitlint.config.js ├── generator ├── .DS_Store ├── index.js └── template │ └── commitlint.config.js ├── index.js ├── lib ├── cz │ ├── engine.js │ └── index.js ├── lint │ └── index.js └── log │ ├── conventional-changelog.js │ ├── conventional-recommended-bump.js │ ├── index.js │ ├── parser-opts.js │ ├── templates │ ├── commit.hbs │ ├── footer.hbs │ ├── header.hbs │ └── template.hbs │ └── writer-opts.js ├── package.json ├── prompts.js └── public ├── changelog.png ├── commander.png └── prompt.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxue-victor/commitlint/cc625815f59062ffe1e62366183b0224fa9754b7/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.12 (2019-12-24) 2 | 3 | ### 🌟 新功能 4 | 范围|描述|commitId 5 | --|--|-- 6 | init | init | [8cd3d82](https://github.com/luoxue-victor/commitlint/commit/8cd3d82) 7 | package | 发布1.0.2版本 | [7bc2b42](https://github.com/luoxue-victor/commitlint/commit/7bc2b42) 8 | version | 增加1.0.7版本 | [6937136](https://github.com/luoxue-victor/commitlint/commit/6937136) 9 | 10 | 11 | ### 🐛 Bug 修复 12 | 范围|描述|commitId 13 | --|--|-- 14 | 测试 | 测试changelog | [dc0f29e](https://github.com/luoxue-victor/commitlint/commit/dc0f29e) 15 | changelog | 修复了 changelog 不兼容的判断问题 | [fa2feb2](https://github.com/luoxue-victor/commitlint/commit/fa2feb2) 16 | index.js | 在vue中没有index.js会报错 | [af85925](https://github.com/luoxue-victor/commitlint/commit/af85925) 17 | lib/cz/engine | 修改了引擎promp配置 | [dd36793](https://github.com/luoxue-victor/commitlint/commit/dd36793), closes [#1231231](https://github.com/luoxue-victor/commitlint/issues/1231231) 18 | log | 修改 changelog 生成格式 | [9e839ad](https://github.com/luoxue-victor/commitlint/commit/9e839ad) 19 | log | 修改log生成 | [eab1f7c](https://github.com/luoxue-victor/commitlint/commit/eab1f7c) 20 | path | 修改path | [3531162](https://github.com/luoxue-victor/commitlint/commit/3531162) 21 | publish | 发布新版本 1.0.4 | [fe484b8](https://github.com/luoxue-victor/commitlint/commit/fe484b8) 22 | version | 修改版本 | [025f7b0](https://github.com/luoxue-victor/commitlint/commit/025f7b0) 23 | version | 修改发布版本 | [2f841f0](https://github.com/luoxue-victor/commitlint/commit/2f841f0) 24 | 25 | 26 | ### 📝 文档 27 | 范围|描述|commitId 28 | --|--|-- 29 | changelog | 修改了chenglog 格式 | [9f59211](https://github.com/luoxue-victor/commitlint/commit/9f59211) 30 | changelog | 修改changelog | [9681573](https://github.com/luoxue-victor/commitlint/commit/9681573) 31 | doc | 修改readme | [1dc3afc](https://github.com/luoxue-victor/commitlint/commit/1dc3afc) 32 | doc | 增加 readme 使用文档 | [a48b805](https://github.com/luoxue-victor/commitlint/commit/a48b805) 33 | readme | 修改了readme | [49d50a4](https://github.com/luoxue-victor/commitlint/commit/49d50a4) 34 | readme | 修改了reame 文件 | [0f68758](https://github.com/luoxue-victor/commitlint/commit/0f68758) 35 | readme | 修改readme 格式 | [84b30fd](https://github.com/luoxue-victor/commitlint/commit/84b30fd) 36 | 37 | 38 | ### 💡 不兼容变更 39 | 40 | * **lib/cz/engine:** 不兼容1 41 | 不兼容2 42 | 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Git commit 规范 2 | 3 | 结合 `commitizen` `commitlint` `conventional-changelog-cli` `husky`,进行封装,一键安装,开箱即用的 `git commit` 规范。 4 | 5 | ## 功能 6 | 7 | 1. 自动检测 commit 是否规范,不规范不允许提交 8 | 2. 自动提示 commit 填写格式。不怕忘记规范怎么写 9 | 3. 集成 git add . && git commit 不需要在执行两个命令 10 | 4. 自动生成 changelog 11 | 12 | ## 配置 13 | 14 | 1. 如果您是 vue-cli3 的项目可以直接使用即可 15 | 16 | ```bash 17 | vue add commitlint 18 | ``` 19 | 20 | 2. 如果您不是 vue-cli3 的项目 21 | 22 | ```bash 23 | npm i vue-cli-plugin-commitlint commitizen commitlint conventional-changelog-cli husky -D 24 | ``` 25 | 26 | - 在 package.json 中添加 27 | 28 | ```json 29 | { 30 | "scripts": { 31 | "log": "conventional-changelog --config ./node_modules/vue-cli-plugin-commitlint/lib/log -i CHANGELOG.md -s -r 0", 32 | "cz": "npm run log && git add . && git cz" 33 | }, 34 | "husky": { 35 | "hooks": { 36 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 37 | } 38 | }, 39 | "config": { 40 | "commitizen": { 41 | "path": "./node_modules/vue-cli-plugin-commitlint/lib/cz" 42 | } 43 | } 44 | } 45 | ``` 46 | 47 | 增加 commitlint.config.js 文件 48 | 49 | ```js 50 | module.exports = { 51 | extends: ['./node_modules/vue-cli-plugin-commitlint/lib/lint'] 52 | }; 53 | ``` 54 | 55 | ## 使用 56 | 57 | ```bash 58 | npm run cz # git add . && git commit -m 'feat:(xxx): xxx' 59 | npm run log # 生成 CHANGELOG 60 | ``` 61 | 62 | 1. 代码提交 npm run cz 63 | 64 | ![commander](./public/commander.png) 65 | 66 | 2. 选择一个类型会自动询问 67 | 68 | 1. (非必填)本次提交的改变所影响的范围 69 | 2. (必填)写一个简短的变化描述 70 | 3. (非必填)提供更详细的变更描述 71 | 4. (非必填)是否存在不兼容变更? 72 | 5. (非必填)此次变更是否影响某些打开的 issue 73 | 74 | ![prompt](./public/prompt.png) 75 | 76 | ### changelog 演示 77 | 78 | ![changelog](./public/changelog.png) 79 | 80 | ## 规则 81 | 82 | | 规范名 | 描述 | 83 | | -------- | ------------------------------------------------------- | 84 | | docs | 仅仅修改了文档,比如 README, CHANGELOG, CONTRIBUTE 等等 | 85 | | chore | 改变构建流程、或者增加依赖库、工具等 | 86 | | feat | 新增 feature | 87 | | fix | 修复 bug | 88 | | merge | 合并分之 | 89 | | perf | 优化相关,比如提升性能、体验 | 90 | | refactor | 代码重构,没有加新功能或者修复 bug | 91 | | revert | 回滚到上一个版本 | 92 | | style | 仅仅修改了空格、格式缩进、都好等等,不改变代码逻辑 | 93 | | test | 测试用例,包括单元测试、集成测试等 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['./lib/lint'] 3 | }; -------------------------------------------------------------------------------- /generator/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxue-victor/commitlint/cc625815f59062ffe1e62366183b0224fa9754b7/generator/.DS_Store -------------------------------------------------------------------------------- /generator/index.js: -------------------------------------------------------------------------------- 1 | module.exports = (api, option) => { 2 | if (option.replace) { 3 | api.render('./template'); 4 | api.extendPackage({ 5 | devDependencies: { 6 | "commitizen": "^4.0.3", 7 | "commitlint": "^8.2.0", 8 | "conventional-changelog-cli": "^2.0.28", 9 | "husky": "^3.0.9" 10 | }, 11 | scripts: { 12 | "log": "conventional-changelog --config ./node_modules/vue-cli-plugin-commitlint/lib/log -i CHANGELOG.md -s -r 0", 13 | "cz": "npm run log && git add . && git cz" 14 | }, 15 | "husky": { 16 | "hooks": { 17 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 18 | } 19 | }, 20 | "config": { 21 | "commitizen": { 22 | "path": "./node_modules/vue-cli-plugin-commitlint/lib/cz" 23 | } 24 | } 25 | }) 26 | console.log('添加 vue-cli-plugin-commitlint 插件成功!') 27 | } else { 28 | console.log('添加 vue-cli-plugin-commitlint 插件失败!') 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /generator/template/commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['./node_modules/vue-cli-plugin-commitlint/lib/lint'] 3 | }; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {} -------------------------------------------------------------------------------- /lib/cz/engine.js: -------------------------------------------------------------------------------- 1 | 'format cjs'; 2 | 3 | const wrap = require('word-wrap'); 4 | const longest = require('longest'); 5 | const rightPad = require('right-pad'); 6 | const chalk = require('chalk'); 7 | 8 | const filter = (array) => { 9 | return array.filter((x) => { 10 | return x; 11 | }); 12 | }; 13 | 14 | // 获取选择列表 15 | const getList = (obj) => { 16 | const objLeng = longest(Object.keys(obj)).length * 2 + 1; 17 | 18 | return Object.keys(obj).map(key => ({ 19 | name: `${rightPad(`${key}:`, objLeng / 2, ' ')} ${obj[key].description}`, 20 | value: key 21 | })); 22 | }; 23 | 24 | module.exports = function (options) { 25 | const typeList = getList(options.types); 26 | 27 | return { 28 | prompter(cz, commit) { 29 | console.log(chalk.yellow('\n标题会在100个字符后进行裁剪。 主体内容每行会在100个字符后自动换行,手动换行请直接输入"\\n"。\n')); 30 | cz.prompt([ 31 | { 32 | type: 'list', 33 | name: 'type', 34 | message: '选择你提交的信息类型:', 35 | choices: typeList 36 | }, { 37 | type: 'string', 38 | name: 'scope', 39 | message: '(非必填)本次提交的改变所影响的范围?', 40 | }, { 41 | type: 'input', 42 | name: 'subject', 43 | validate(str) { 44 | const charLen = 3 45 | if (str.length > charLen) { 46 | return str.length > charLen 47 | } else { 48 | console.log(chalk.yellow(`字符长度大于${charLen}`)) 49 | } 50 | }, 51 | message: '(必填)写一个简短的变化描述:' 52 | }, { 53 | type: 'input', 54 | name: 'body', 55 | message: '(非必填)提供更详细的变更描述:' 56 | }, { 57 | type: 'confirm', 58 | name: 'isBreaking', 59 | message: '是否存在不兼容变更?', 60 | default: false 61 | }, { 62 | type: 'input', 63 | name: 'breaking', 64 | message: '列出所有的不兼容变更:\n', 65 | when(answers) { 66 | return answers.isBreaking; 67 | } 68 | }, { 69 | type: 'confirm', 70 | name: 'isIssueAffected', 71 | message: '此次变更是否影响某些打开的 issue ?', 72 | default: false 73 | }, { 74 | type: 'input', 75 | name: 'issues', 76 | message: '列出此次改动引用的所有 issues (如:"fix #123", "Closes #123, #124"):\n', 77 | when(answers) { 78 | return answers.isIssueAffected; 79 | } 80 | } 81 | ]) 82 | .then((answers) => { 83 | const maxLineWidth = 100; 84 | 85 | const wrapOptions = { 86 | trim: true, 87 | newline: '\n', 88 | indent: '', 89 | width: maxLineWidth 90 | }; 91 | 92 | // 判断影响范围是否输入 93 | const scope = answers.scope ? `(${answers.scope.trim()})` : ''; 94 | 95 | // 限制短描述为 100 个字符 96 | const head = (`${answers.type + scope}: ${answers.subject.trim()}`).slice(0, maxLineWidth); 97 | 98 | // 限制详细描述最长宽度为 100 个字符串 99 | const body = wrap(answers.body, wrapOptions); 100 | 101 | // Apply breaking change prefix, removing it if already present 102 | let breaking = answers.breaking ? answers.breaking.trim() : ''; 103 | 104 | // 如果手动输入了 不兼容变更,则过滤掉,最后进行长度限制 105 | breaking = breaking ? `不兼容变更: ${breaking.replace(/^不兼容变更: /, '')}` : ''; 106 | breaking = wrap(breaking, wrapOptions); 107 | 108 | const issues = answers.issues ? wrap(answers.issues, wrapOptions) : ''; 109 | 110 | const footer = filter([breaking, issues]).join('\n\n'); 111 | 112 | commit(`${head}\n\n${body}\n\n${footer}`); 113 | }); 114 | } 115 | }; 116 | }; 117 | -------------------------------------------------------------------------------- /lib/cz/index.js: -------------------------------------------------------------------------------- 1 | 'format cjs'; 2 | const engine = require('./engine'); 3 | 4 | module.exports = engine({ 5 | types: { 6 | feat: { 7 | description: '🌟 一个新功能', 8 | title: '🌟 新功能' 9 | }, 10 | fix: { 11 | description: '🐛 一个 bug 修复', 12 | title: '🐛 Bug 修复' 13 | }, 14 | perf: { 15 | description: '🚀 提升性能的代码更改', 16 | title: '🚀 性能优化' 17 | }, 18 | style: { 19 | description: '🎨 对代码含义无影响的改动(空格,格式化,等,非 UI 变动)', 20 | title: '🎨 代码样式' 21 | }, 22 | docs: { 23 | description: '📝 只有文档发生改变', 24 | title: '📝 文档' 25 | }, 26 | test: { 27 | description: '🔧 添加一些缺失的测试或者修正已存在的测试', 28 | title: '🔧 测试' 29 | }, 30 | refactor: { 31 | description: '🔨 既不是修复 bug 也不是添加新功能的代码更改', 32 | title: '🔨 代码重构' 33 | }, 34 | chore: { 35 | description: '🏠 影响构建系统或外部依赖的更改(例如:gulp,npm,webpack)', 36 | title: '🏠 构建' 37 | }, 38 | ci: { 39 | description: '📦 持续集成的配置文件和脚本的改变(例如: Travis, Circle)', 40 | title: '📦 持续集成' 41 | }, 42 | revert: { 43 | description: '🔙 撤销上一次的提交', 44 | title: '🔙 撤销' 45 | } 46 | }, 47 | scopes: { 48 | global: { 49 | description: '影响整个项目', 50 | title: 'global' 51 | }, 52 | ui: { 53 | description: 'UI 界面', 54 | title: 'ui' 55 | }, 56 | data: { 57 | description: '数据变化', 58 | title: 'data' 59 | }, 60 | component: { 61 | description: '影响公共组件使用', 62 | title: 'component' 63 | }, 64 | unknown: { 65 | description: '不知道影响范围', 66 | title: 'unknown' 67 | } 68 | } 69 | }); 70 | -------------------------------------------------------------------------------- /lib/lint/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserPreset: { 3 | parserOpts: { 4 | headerPattern: /^(\w*|[\u4e00-\u9fa5]*)(?:[\(\(](.*)[\)\)])?[\:\:] (.*)/, 5 | headerCorrespondence: [ 6 | 'type', 7 | 'scope', 8 | 'subject' 9 | ], 10 | referenceActions: [ 11 | 'close', 12 | 'closes', 13 | 'closed', 14 | 'fix', 15 | 'fixes', 16 | 'fixed', 17 | 'resolve', 18 | 'resolves', 19 | 'resolved' 20 | ], 21 | issuePrefixes: ['#'], 22 | noteKeywords: ['BREAKING CHANGE', '不兼容变更'], 23 | fieldPattern: /^-(.*?)-$/, 24 | revertPattern: /^Revert\s"([\s\S]*)"\s*This reverts commit (\w*)\./, 25 | revertCorrespondence: ['header', 'hash'], 26 | warn() {}, 27 | mergePattern: null, 28 | mergeCorrespondence: null 29 | }, 30 | }, 31 | rules: { 32 | 'body-leading-blank': [2, 'always'], 33 | 'footer-leading-blank': [1, 'always'], 34 | 'header-max-length': [2, 'always', 108], 35 | 'subject-empty': [2, 'never'], 36 | 'type-empty': [2, 'never'], 37 | 'type-enum': [ 38 | 2, 39 | 'always', 40 | [ 41 | 'feat', 42 | 'fix', 43 | 'perf', 44 | 'style', 45 | 'docs', 46 | 'test', 47 | 'refactor', 48 | 'build', 49 | 'ci', 50 | 'chore', 51 | 'revert' 52 | ], 53 | ], 54 | }, 55 | }; 56 | -------------------------------------------------------------------------------- /lib/log/conventional-changelog.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const Q = require('q'); 4 | const parserOpts = require('./parser-opts'); 5 | const writerOpts = require('./writer-opts'); 6 | 7 | module.exports = Q.all([parserOpts, writerOpts]) 8 | .spread((parserOpts, writerOpts) => { 9 | return { parserOpts, writerOpts }; 10 | }); 11 | -------------------------------------------------------------------------------- /lib/log/conventional-recommended-bump.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const parserOpts = require('./parser-opts'); 4 | 5 | module.exports = { 6 | parserOpts, 7 | 8 | whatBump: (commits) => { 9 | let level = 2; 10 | let breakings = 0; 11 | let features = 0; 12 | 13 | commits.forEach(commit => { 14 | console.log(commit); 15 | if (commit.notes.length > 0) { 16 | breakings += commit.notes.length; 17 | level = 0; 18 | } else if (commit.type === 'feat' || commit.type === '新功能') { 19 | features += 1; 20 | if (level === 2) { 21 | level = 1; 22 | } 23 | } 24 | }); 25 | 26 | return { 27 | level, 28 | reason: breakings === 1 29 | ? `There is ${breakings} BREAKING CHANGE and ${features} features` 30 | : `There are ${breakings} BREAKING CHANGES and ${features} features` 31 | }; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /lib/log/index.js: -------------------------------------------------------------------------------- 1 | const Q = require('q'); 2 | const conventionalChangelog = require('./conventional-changelog'); 3 | const parserOpts = require('./parser-opts'); 4 | const recommendedBumpOpts = require('./conventional-recommended-bump'); 5 | const writerOpts = require('./writer-opts'); 6 | 7 | module.exports = Q.all([conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts]) 8 | .spread((conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts) => { 9 | return { conventionalChangelog, parserOpts, recommendedBumpOpts, writerOpts }; 10 | }); 11 | -------------------------------------------------------------------------------- /lib/log/parser-opts.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = { 4 | headerPattern: /^(\w*|[\u4e00-\u9fa5]*)(?:[\(\(](.*)[\)\)])?[\:\:] (.*)$/, 5 | headerCorrespondence: [ 6 | 'type', 7 | 'scope', 8 | 'subject' 9 | ], 10 | noteKeywords: ['BREAKING CHANGE', '不兼容变更'], 11 | revertPattern: /^revert:\s([\s\S]*?)\s*This reverts commit (\w*)\./, 12 | revertCorrespondence: ['header', 'hash'] 13 | }; 14 | -------------------------------------------------------------------------------- /lib/log/templates/commit.hbs: -------------------------------------------------------------------------------- 1 | {{#if scope}} {{scope}} | 2 | {{~else}} - | 3 | {{~/if}} {{#if subject}} 4 | {{~subject}} 5 | {{~else}} 6 | {{~header}} 7 | {{~/if}} 8 | | 9 | {{~!-- commit link --}} {{#if @root.linkReferences~}} 10 | [{{hash}}]( 11 | {{~#if @root.repository}} 12 | {{~#if @root.host}} 13 | {{~@root.host}}/ 14 | {{~/if}} 15 | {{~#if @root.owner}} 16 | {{~@root.owner}}/ 17 | {{~/if}} 18 | {{~@root.repository}} 19 | {{~else}} 20 | {{~@root.repoUrl}} 21 | {{~/if}}/ 22 | {{~@root.commit}}/{{hash}}) 23 | {{~else}} 24 | {{~hash}} 25 | {{~/if}} 26 | 27 | {{~!-- commit references --}} 28 | {{~#if references~}} 29 | , closes 30 | {{~#each references}} {{#if @root.linkReferences~}} 31 | [ 32 | {{~#if this.owner}} 33 | {{~this.owner}}/ 34 | {{~/if}} 35 | {{~this.repository}}#{{this.issue}}]( 36 | {{~#if @root.repository}} 37 | {{~#if @root.host}} 38 | {{~@root.host}}/ 39 | {{~/if}} 40 | {{~#if this.repository}} 41 | {{~#if this.owner}} 42 | {{~this.owner}}/ 43 | {{~/if}} 44 | {{~this.repository}} 45 | {{~else}} 46 | {{~#if @root.owner}} 47 | {{~@root.owner}}/ 48 | {{~/if}} 49 | {{~@root.repository}} 50 | {{~/if}} 51 | {{~else}} 52 | {{~@root.repoUrl}} 53 | {{~/if}}/ 54 | {{~@root.issue}}/{{this.issue}}) 55 | {{~else}} 56 | {{~#if this.owner}} 57 | {{~this.owner}}/ 58 | {{~/if}} 59 | {{~this.repository}}#{{this.issue}} 60 | {{~/if}}{{/each}} 61 | {{~/if}} 62 | 63 | -------------------------------------------------------------------------------- /lib/log/templates/footer.hbs: -------------------------------------------------------------------------------- 1 | {{#if noteGroups}} 2 | {{#each noteGroups}} 3 | 4 | ### {{title}} 5 | 6 | {{#each notes}} 7 | * {{#if commit.scope}}**{{commit.scope}}:** {{/if}}{{text}} 8 | {{/each}} 9 | {{/each}} 10 | 11 | {{/if}} 12 | -------------------------------------------------------------------------------- /lib/log/templates/header.hbs: -------------------------------------------------------------------------------- 1 | {{#if isPatch~}} 2 | ## 3 | {{~else~}} 4 | # 5 | {{~/if}} {{#if @root.linkCompare~}} 6 | [{{version}}]( 7 | {{~#if @root.repository~}} 8 | {{~#if @root.host}} 9 | {{~@root.host}}/ 10 | {{~/if}} 11 | {{~#if @root.owner}} 12 | {{~@root.owner}}/ 13 | {{~/if}} 14 | {{~@root.repository}} 15 | {{~else}} 16 | {{~@root.repoUrl}} 17 | {{~/if~}} 18 | /compare/{{previousTag}}...{{currentTag}}) 19 | {{~else}} 20 | {{~version}} 21 | {{~/if}} 22 | {{~#if title}} "{{title}}" 23 | {{~/if}} 24 | {{~#if date}} ({{date}}) 25 | {{/if}} 26 | -------------------------------------------------------------------------------- /lib/log/templates/template.hbs: -------------------------------------------------------------------------------- 1 | {{> header}} 2 | {{#each commitGroups}} 3 | 4 | {{#if title}} 5 | ### {{title}} 6 | {{/if}} 7 | 范围|描述|commitId 8 | --|--|-- 9 | {{#each commits}} 10 | {{> commit root=@root}} 11 | {{/each}} 12 | 13 | {{/each}} 14 | {{> footer}} -------------------------------------------------------------------------------- /lib/log/writer-opts.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const compareFunc = require('compare-func'); 4 | const Q = require('q'); 5 | const readFile = Q.denodeify(require('fs').readFile); 6 | const resolve = require('path').resolve; 7 | 8 | module.exports = Q.all([ 9 | readFile(resolve(__dirname, './templates/template.hbs'), 'utf-8'), 10 | readFile(resolve(__dirname, './templates/header.hbs'), 'utf-8'), 11 | readFile(resolve(__dirname, './templates/commit.hbs'), 'utf-8'), 12 | readFile(resolve(__dirname, './templates/footer.hbs'), 'utf-8') 13 | ]) 14 | .spread((template, header, commit, footer) => { 15 | const writerOpts = getWriterOpts(); 16 | 17 | writerOpts.mainTemplate = template; 18 | writerOpts.headerPartial = header; 19 | writerOpts.commitPartial = commit; 20 | writerOpts.footerPartial = footer; 21 | 22 | return writerOpts; 23 | }); 24 | 25 | function getWriterOpts() { 26 | return { 27 | transform: (commit, context) => { 28 | let discard = false; 29 | const issues = []; 30 | 31 | commit.notes.forEach(note => { 32 | note.title = '💡 不兼容变更'; 33 | discard = true; 34 | }); 35 | 36 | if (commit.type === 'feat') { 37 | commit.type = '🌟 新功能'; 38 | } else if (commit.type === 'fix') { 39 | commit.type = '🐛 Bug 修复'; 40 | } else if (commit.type === 'perf') { 41 | commit.type = '🚀 性能优化'; 42 | } else if (commit.type === 'revert') { 43 | commit.type = '🔙 撤销'; 44 | } else if (discard) { 45 | return; 46 | } else if (commit.type === 'docs') { 47 | commit.type = '📝 文档'; 48 | } else if (commit.type === 'style') { 49 | commit.type = '🎨 代码样式'; 50 | } else if (commit.type === 'refactor') { 51 | commit.type = '🔨 代码重构'; 52 | } else if (commit.type === 'test') { 53 | commit.type = '🔧 测试'; 54 | } else if (commit.type === 'build') { 55 | commit.type = '🏠 构建系统'; 56 | } else if (commit.type === 'ci') { 57 | commit.type = '📦 持续集成'; 58 | } else if (commit.type === '杂') { 59 | commit.type = '🚴 杂'; 60 | } 61 | 62 | if (commit.scope === '*') { 63 | commit.scope = ''; 64 | } 65 | 66 | if (typeof commit.hash === 'string') { 67 | commit.hash = commit.hash.substring(0, 7); 68 | } 69 | 70 | if (typeof commit.subject === 'string') { 71 | let url = context.repository ? `${context.host}/${context.owner}/${context.repository}` : context.repoUrl; 72 | if (url) { 73 | url = `${url}/issues/`; 74 | // Issue URLs. 75 | commit.subject = commit.subject.replace(/#([0-9]+)/g, (_, issue) => { 76 | issues.push(issue); 77 | return `[#${issue}](${url}${issue})`; 78 | }); 79 | } 80 | if (context.host) { 81 | // User URLs. 82 | commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9]){0,38})/g, `[@$1](${context.host}/$1)`); 83 | } 84 | } 85 | 86 | // remove references that already appear in the subject 87 | commit.references = commit.references.filter(reference => { 88 | if (issues.indexOf(reference.issue) === -1) { 89 | return true; 90 | } 91 | return false; 92 | }); 93 | 94 | return commit; 95 | }, 96 | groupBy: 'type', 97 | commitGroupsSort: 'title', 98 | commitsSort: ['scope', 'subject'], 99 | noteGroupsSort: 'title', 100 | notesSort: compareFunc 101 | }; 102 | } 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-cli-plugin-commitlint", 3 | "version": "1.0.12", 4 | "description": "基于vue-cli3的代码提交检查规范", 5 | "main": "index.js", 6 | "scripts": { 7 | "log": "conventional-changelog --config ./lib/log -i CHANGELOG.md -s -r 0", 8 | "cz": "npm run log && git add . && git cz" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/luoxue-victor/commitlint.git" 13 | }, 14 | "author": "luoxue", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/luoxue-victor/commitlint/issues" 18 | }, 19 | "homepage": "https://github.com/luoxue-victor/commitlint#readme", 20 | "husky": { 21 | "hooks": { 22 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 23 | } 24 | }, 25 | "devDependencies": { 26 | "commitizen": "^4.0.3", 27 | "commitlint": "^8.2.0", 28 | "conventional-changelog-cli": "^2.0.28", 29 | "husky": "^3.0.9", 30 | "right-pad": "^1.0.1" 31 | }, 32 | "config": { 33 | "commitizen": { 34 | "path": "lib/cz" 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /prompts.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | type: 'confirm', 4 | name: 'replace', 5 | message: '是否添加 commitlint 插件?', 6 | default: true 7 | } 8 | ] -------------------------------------------------------------------------------- /public/changelog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxue-victor/commitlint/cc625815f59062ffe1e62366183b0224fa9754b7/public/changelog.png -------------------------------------------------------------------------------- /public/commander.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxue-victor/commitlint/cc625815f59062ffe1e62366183b0224fa9754b7/public/commander.png -------------------------------------------------------------------------------- /public/prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luoxue-victor/commitlint/cc625815f59062ffe1e62366183b0224fa9754b7/public/prompt.png --------------------------------------------------------------------------------