@rainstormy/comet 2.0.0-rc.0 → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -38
- package/main-cli.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,79 @@ A linter to ensure that Git commit messages conform to certain standards and con
|
|
|
5
5
|
> [!CAUTION]
|
|
6
6
|
> Comet v2 is currently in development with an expected release later in 2026.
|
|
7
7
|
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Why lint commit messages?
|
|
11
|
+
|
|
12
|
+
A commit is a permanent, durable record of a change.
|
|
13
|
+
Its diff shows the actual file changes while the commit message may include details about assumptions and constraints that are not apparent from the diff.
|
|
14
|
+
|
|
15
|
+
Some effort in useful commit messages now will help you and your team in the future:
|
|
16
|
+
|
|
17
|
+
- **Save investigation time.**
|
|
18
|
+
Knowing the motivation and circumstances behind a change helps you assess whether the change caused a regression or is safe to revert.
|
|
19
|
+
|
|
20
|
+
- **Share knowledge.**
|
|
21
|
+
Capturing context and decisions gives the whole team access to information that might otherwise remain with the author.
|
|
22
|
+
|
|
23
|
+
- **Find relevant changes.**
|
|
24
|
+
Consistent, predictable formatting makes commit messages easier for humans and agents to read and search.
|
|
25
|
+
|
|
26
|
+
- **Support agile workflows.**
|
|
27
|
+
Teams can agree on policies that streamline code reviews by encouraging small, short-lived branches and fixup commits.
|
|
28
|
+
|
|
29
|
+
- **Focus on code instead of conventions.**
|
|
30
|
+
Automated checks in local Git hooks and CI pipelines leave reviewers more time to focus on the change itself.
|
|
31
|
+
|
|
32
|
+
For example, this commit message follows the default subject and body style encouraged by Comet and explains the motivation and constraints behind the change:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Retry timed-out requests before payment
|
|
36
|
+
|
|
37
|
+
Transient network failures abort checkout before payment starts.
|
|
38
|
+
Retry these requests up to three times so customers can continue without
|
|
39
|
+
reloading the page.
|
|
40
|
+
|
|
41
|
+
Leave payment submissions unchanged to avoid duplicate charges.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Further reading:
|
|
45
|
+
|
|
46
|
+
- [Pro Git book: Commit guidelines](https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project#_commit_guidelines)
|
|
47
|
+
- [cbeams: How to Write a Git Commit Message](https://cbea.ms/git-commit)
|
|
48
|
+
- [Martijn Hols: How to write a good git commit message](https://martijnhols.nl/blog/how-to-write-a-good-git-commit-message)
|
|
49
|
+
|
|
50
|
+
## Rules
|
|
51
|
+
|
|
52
|
+
| Symbol | Explanation |
|
|
53
|
+
|----------------------------------------------|------------------------------------------------------------------------------------|
|
|
54
|
+
|  | The rule is enabled by default in the `comet` CLI on the command-line. |
|
|
55
|
+
|  | The rule is enabled by default in the `rainstormy/comet` action in GitHub Actions. |
|
|
56
|
+
|
|
57
|
+
| Name | Description | Default |
|
|
58
|
+
|----------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|
|
|
59
|
+
| [`noBlankSubjects`](docs/rules/NoBlankSubjects.md) | Rejects subjects without any alphanumeric characters. |   |
|
|
60
|
+
| [`noExcessiveCommitsPerBranch`](docs/rules/NoExcessiveCommitsPerBranch.md) | Rejects branches with more than a configured number of undelivered commits, encouraging short-lived branches and [stacked pull requests](https://docs.github.com/en/pull-requests/how-tos/create-pull-requests/creating-stacked-pull-requests). |  |
|
|
61
|
+
| [`noExcessiveWhitespace`](docs/rules/NoExcessiveWhitespace.md) | Rejects subjects with leading, trailing, or consecutive whitespace characters, and body lines with consecutive whitespace characters. |   |
|
|
62
|
+
| [`noMergeCommits`](docs/rules/NoMergeCommits.md) | Rejects commits with more than one parent commit, encouraging rebasing instead of merging to keep a branch up to date with the main branch. |   |
|
|
63
|
+
| [`noRepeatedSubjects`](docs/rules/NoRepeatedSubjects.md) | Rejects subjects equal to a previous subject in the current branch. |  |
|
|
64
|
+
| [`noRestrictedTrailers`](docs/rules/NoRestrictedTrailers.md) | Rejects configured [trailers](https://git-scm.com/docs/git-interpret-trailers) in the message body. | |
|
|
65
|
+
| [`noRevertReverts`](docs/rules/NoRevertReverts.md) | Rejects subjects with more than one revert marker, encouraging cherry-picking the original commit. |  |
|
|
66
|
+
| [`noSingleWordSubjects`](docs/rules/NoSingleWordSubjects.md) | Rejects subjects that contain only one word. |   |
|
|
67
|
+
| [`noSquashMarkers`](docs/rules/NoSquashMarkers.md) | Rejects subjects beginning with a squash marker like `amend!`, `fixup!`, and `squash!`, reminding you to squash temporary commits before merging pull requests. |  |
|
|
68
|
+
| [`noUnexpectedPunctuation`](docs/rules/NoUnexpectedPunctuation.md) | Rejects subjects with unexpected trailing punctuation. |   |
|
|
69
|
+
| [`useAuthorEmailPatterns`](docs/rules/UseAuthorEmailPatterns.md) | Rejects commits where the author's email address does not match one of the configured regex patterns. | |
|
|
70
|
+
| [`useAuthorNamePatterns`](docs/rules/UseAuthorNamePatterns.md) | Rejects commits where the author's name does not match one of the configured regex patterns. | |
|
|
71
|
+
| [`useCapitalisedSubjects`](docs/rules/UseCapitalisedSubjects.md) | Rejects subjects that start with a lowercase letter. |   |
|
|
72
|
+
| [`useCommitterEmailPatterns`](docs/rules/UseCommitterEmailPatterns.md) | Rejects commits where the committer's email address does not match one of the configured regex patterns. | |
|
|
73
|
+
| [`useCommitterNamePatterns`](docs/rules/UseCommitterNamePatterns.md) | Rejects commits where the committer's name does not match one of the configured regex patterns. | |
|
|
74
|
+
| [`useConciseSubjects`](docs/rules/UseConciseSubjects.md) | Rejects subjects longer than the configured character limit. |   |
|
|
75
|
+
| [`useEmptyLineBeforeBody`](docs/rules/UseEmptyLineBeforeBody.md) | Rejects commits whose message body is not separated from the subject (i.e. the first line) by exactly one empty line. |   |
|
|
76
|
+
| [`useImperativeSubjects`](docs/rules/UseImperativeSubjects.md) | Rejects subjects that do not start with a verb in the imperative mood. |   |
|
|
77
|
+
| [`useIssueLinks`](docs/rules/UseIssueLinks.md) | Rejects subjects without an issue link in the configured position. | |
|
|
78
|
+
| [`useLineWrapping`](docs/rules/UseLineWrapping.md) | Rejects body lines longer than the configured character limit. |   |
|
|
79
|
+
| [`useSignedCommits`](docs/rules/UseSignedCommits.md) | Rejects commits without a cryptographic signature. |   |
|
|
80
|
+
|
|
8
81
|
## Command-line interface (CLI)
|
|
9
82
|
|
|
10
83
|
The Comet CLI checks the commits on the current branch that have not been delivered to the default branch, i.e. the range `origin/HEAD..HEAD` for a remote named `origin`.
|
|
@@ -29,7 +102,7 @@ comet \
|
|
|
29
102
|
[--skip-missing-configs]
|
|
30
103
|
```
|
|
31
104
|
|
|
32
|
-
You can also define a custom task in `package.json` or `vite.config.ts` (with Vite+):
|
|
105
|
+
You can also define a custom task in `package.json` or `vite.config.ts` (with [Vite+](https://viteplus.dev)):
|
|
33
106
|
|
|
34
107
|
```json
|
|
35
108
|
{
|
|
@@ -39,7 +112,7 @@ You can also define a custom task in `package.json` or `vite.config.ts` (with Vi
|
|
|
39
112
|
}
|
|
40
113
|
```
|
|
41
114
|
|
|
42
|
-
Run it with your package manager
|
|
115
|
+
Run it with your package manager:
|
|
43
116
|
|
|
44
117
|
```shell
|
|
45
118
|
pnpm run lint-commits
|
|
@@ -51,6 +124,8 @@ Or with Vite+:
|
|
|
51
124
|
vpr lint-commits
|
|
52
125
|
```
|
|
53
126
|
|
|
127
|
+
You can also run this task in a `pre-push` Git hook to block pushes that contain poorly formatted commit messages.
|
|
128
|
+
|
|
54
129
|
### Usage with Deno
|
|
55
130
|
|
|
56
131
|
Install and run Comet directly with [Deno](https://deno.com):
|
|
@@ -75,9 +150,11 @@ It must run in workflows triggered by `pull_request` events.
|
|
|
75
150
|
|
|
76
151
|
The `github-token` needs `pull-requests: read` permissions to allow Comet to [list the pull request's commits](https://docs.github.com/en/rest/pulls/pulls?apiVersion=2026-03-10#list-commits-on-a-pull-request).
|
|
77
152
|
|
|
78
|
-
To load a configuration file,
|
|
153
|
+
To load a configuration file, include an `actions/checkout` step before the `rainstormy/comet` step and grant `contents: read` permissions to the `github-token`.
|
|
79
154
|
Use `config-path` to specify a custom configuration file path.
|
|
80
155
|
|
|
156
|
+
Example:
|
|
157
|
+
|
|
81
158
|
```yaml
|
|
82
159
|
name: CI
|
|
83
160
|
|
|
@@ -85,56 +162,30 @@ on: pull_request
|
|
|
85
162
|
|
|
86
163
|
jobs:
|
|
87
164
|
commit-messages:
|
|
165
|
+
# if: github.event_name == 'pull_request'
|
|
88
166
|
runs-on: ubuntu-latest
|
|
167
|
+
timeout-minutes: 1
|
|
89
168
|
permissions:
|
|
90
169
|
contents: read
|
|
91
170
|
pull-requests: read
|
|
92
171
|
steps:
|
|
93
|
-
- uses: actions/checkout@v7
|
|
172
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
94
173
|
with:
|
|
95
174
|
persist-credentials: false
|
|
96
|
-
- uses: rainstormy/comet@v2.0.0-
|
|
175
|
+
- uses: rainstormy/comet@10ac994454c2a81e76a4ff48f3d015086e708674 # v2.0.0-rc.0
|
|
97
176
|
with:
|
|
98
177
|
github-token: ${{ github.token }}
|
|
99
178
|
config-path: .github/comet.jsonc
|
|
100
179
|
```
|
|
101
180
|
|
|
102
|
-
##
|
|
181
|
+
## Configuration file
|
|
103
182
|
|
|
104
|
-
|
|
105
|
-
|----------------------------------------------------------------------------|
|
|
106
|
-
| [`noBlankSubjects`](docs/rules/NoBlankSubjects.md) |
|
|
107
|
-
| [`noExcessiveCommitsPerBranch`](docs/rules/NoExcessiveCommitsPerBranch.md) |
|
|
108
|
-
| [`noExcessiveWhitespace`](docs/rules/NoExcessiveWhitespace.md) |
|
|
109
|
-
| [`noMergeCommits`](docs/rules/NoMergeCommits.md) |
|
|
110
|
-
| [`noRepeatedSubjects`](docs/rules/NoRepeatedSubjects.md) |
|
|
111
|
-
| [`noRestrictedTrailers`](docs/rules/NoRestrictedTrailers.md) |
|
|
112
|
-
| [`noRevertReverts`](docs/rules/NoRevertReverts.md) |
|
|
113
|
-
| [`noSingleWordSubjects`](docs/rules/NoSingleWordSubjects.md) |
|
|
114
|
-
| [`noSquashMarkers`](docs/rules/NoSquashMarkers.md) |
|
|
115
|
-
| [`noUnexpectedPunctuation`](docs/rules/NoUnexpectedPunctuation.md) |
|
|
116
|
-
| [`useAuthorEmailPatterns`](docs/rules/UseAuthorEmailPatterns.md) |
|
|
117
|
-
| [`useAuthorNamePatterns`](docs/rules/UseAuthorNamePatterns.md) |
|
|
118
|
-
| [`useCapitalisedSubjects`](docs/rules/UseCapitalisedSubjects.md) |
|
|
119
|
-
| [`useCommitterEmailPatterns`](docs/rules/UseCommitterEmailPatterns.md) |
|
|
120
|
-
| [`useCommitterNamePatterns`](docs/rules/UseCommitterNamePatterns.md) |
|
|
121
|
-
| [`useConciseSubjects`](docs/rules/UseConciseSubjects.md) |
|
|
122
|
-
| [`useEmptyLineBeforeBody`](docs/rules/UseEmptyLineBeforeBody.md) |
|
|
123
|
-
| [`useImperativeSubjects`](docs/rules/UseImperativeSubjects.md) |
|
|
124
|
-
| [`useIssueLinks`](docs/rules/UseIssueLinks.md) |
|
|
125
|
-
| [`useLineWrapping`](docs/rules/UseLineWrapping.md) |
|
|
126
|
-
| [`useSignedCommits`](docs/rules/UseSignedCommits.md) |
|
|
127
|
-
|
|
128
|
-
## Configuration
|
|
129
|
-
|
|
130
|
-
Comet applies a reasonable default configuration of rules.
|
|
131
|
-
|
|
132
|
-
To customise the configuration, create a `comet.json` or `comet.jsonc` file in the project root directory.
|
|
183
|
+
To customise the configuration, create a `comet.json` (or `comet.jsonc`) file in the project root directory.
|
|
133
184
|
Override the settings you want to change, for example:
|
|
134
185
|
|
|
135
186
|
```json
|
|
136
187
|
{
|
|
137
|
-
"$schema": "https://unpkg.com/@rainstormy/comet@2.0.0-
|
|
188
|
+
"$schema": "https://unpkg.com/@rainstormy/comet@2.0.0-rc.0/schema.json",
|
|
138
189
|
"rules": {
|
|
139
190
|
"noMergeCommits": "error",
|
|
140
191
|
"useConciseSubjects": {
|
|
@@ -146,9 +197,26 @@ Override the settings you want to change, for example:
|
|
|
146
197
|
}
|
|
147
198
|
```
|
|
148
199
|
|
|
149
|
-
Use `--config <path>` in the CLI or `config-path` in GitHub Actions to
|
|
200
|
+
Use `--config <path>` in the CLI or `config-path` in GitHub Actions to select a different configuration path.
|
|
201
|
+
|
|
202
|
+
### `$schema`
|
|
150
203
|
|
|
151
|
-
|
|
204
|
+
Validate the configuration file and enable code completion with the official JSON schema:
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"$schema": "https://unpkg.com/@rainstormy/comet@2.0.0-rc.0/schema.json"
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### `extends`
|
|
213
|
+
|
|
214
|
+
Inherit settings from another configuration file.
|
|
215
|
+
|
|
216
|
+
The path is resolved relative to the configuration file declaring the `extends` field.
|
|
217
|
+
Settings in the declaring configuration override inherited settings, except arrays which are combined; hence, empty arrays will not clear inherited entries.
|
|
218
|
+
|
|
219
|
+
Example:
|
|
152
220
|
|
|
153
221
|
```json
|
|
154
222
|
{
|
|
@@ -158,3 +226,54 @@ A configuration file can inherit settings from another file with the `extends` p
|
|
|
158
226
|
}
|
|
159
227
|
}
|
|
160
228
|
```
|
|
229
|
+
|
|
230
|
+
### `git.defaultBranch`
|
|
231
|
+
|
|
232
|
+
Hardcode the 'from ref' of the checked commit range instead of computing it from `origin/HEAD`.
|
|
233
|
+
|
|
234
|
+
The `--default-branch` CLI flag takes precedence over `git.defaultBranch`.
|
|
235
|
+
|
|
236
|
+
Example (range of `origin/next..HEAD`):
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"git": {
|
|
241
|
+
"defaultBranch": "origin/next"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### `tokens.issueLinks`
|
|
247
|
+
|
|
248
|
+
Declare which words to recognise as issue links.
|
|
249
|
+
|
|
250
|
+
- `prefixes` (array of strings): Issue number prefixes. For instance, `#` and `NEOWISE-` will recognise issue links like `#123` and `NEOWISE-456`. Default value: `[]`.
|
|
251
|
+
- `wildcards` (array of strings): Literal labels such as `(no-issue)` and `[incident]`. Default value: `[]`.
|
|
252
|
+
|
|
253
|
+
If both arrays are empty, no issue links are recognised.
|
|
254
|
+
To require issue links in subjects, enable the [`useIssueLinks`](docs/rules/UseIssueLinks.md) rule.
|
|
255
|
+
|
|
256
|
+
Example (GitHub-style issue links with Renovate-style critical security upgrades):
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"tokens": {
|
|
261
|
+
"issueLinks": {
|
|
262
|
+
"prefixes": ["#", "GH-"],
|
|
263
|
+
"wildcards": ["[SECURITY]"]
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Example (Jira-style issue links):
|
|
270
|
+
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"tokens": {
|
|
274
|
+
"issueLinks": {
|
|
275
|
+
"prefixes": ["NEOWISE-"]
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
package/main-cli.mjs
CHANGED
|
@@ -28,7 +28,7 @@ function at(...e){return{...e[0],pipe:e,get"~standard"(){return/* @__PURE__ */ O
|
|
|
28
28
|
`&&(s+=e.slice(o,t),o=t,l=-1))}}let u=a===B?r(e,o):e.slice(o);return c+s+u}async function Yt(e){try{return await r(e,i.R_OK),!0}catch{return!1}}function Xt(t,n){if(c(t))return l(t);let r=n===void 0?t:d(o(n),t);return l(u(e.cwd(),r))}async function Zt(e){try{let t=await a(e,`utf8`);return JSON.parse(Qt(e,t))}catch(t){throw t instanceof SyntaxError?TypeError(`Failed to parse '${e}' as JSON: ${t.message}`,{cause:t}):(Ut(t),Error(`Failed to read '${e}': ${t.message}`,{cause:t}))}}function Qt(e,t){return s(e)===`.jsonc`?Jt(t):t}function $t(e){return e.charAt(0).toUpperCase()+e.slice(1)}function en(e){return e.replaceAll(/\s+/gu,` `)}function V(e,t,n){return`${e} ${e===1?t:n}`}function H(e,t){return tn(e,` `.repeat(t))}function U(e,t,n){return e===1?t:n??`${t}s`}function tn(e,t){return t+e.replaceAll(`
|
|
29
29
|
`,`\n${t}`)}function nn(e,t){return e.length<=t?e:`${e.slice(0,t)}…`}function rn(e){let t={issue:e,path:e.path??[]};if(e.issues===void 0)return t;let n=t;for(let r of e.issues){let e=rn(r),i={issue:e.issue,path:[...t.path,...e.path]};n===t&&i.path.length>t.path.length&&(n=i)}return n}async function an(e){let t=await Zt(e);try{return it(Vt,t)}catch(t){throw t instanceof qe?TypeError(`Failed to parse '${e}' as a Comet configuration: ${on(t.issues[0])}`,{cause:t}):t}}function on(e){let t=e.path?.[0]?.input??e.input;if(typeof t!=`object`||!t||Array.isArray(t))return`The configuration must be a JSON object, but it is ${t===``?`empty`:hn(t)}`;let{issue:n,path:r}=rn(e);return n.expected===`never`?sn(r):n.input===void 0?cn(r):`${ln(r)} ${fn(n)}, but it ${mn(r)?`contains`:`is`} ${hn(n.input)}`}function sn(e){let t=un(e),n=z(t.at(-1),()=>`Unnamed unknown configuration property: ${JSON.stringify(e)}`);if(t[0]===`rules`&&t.length===2)return`'${n}' is not a valid rule`;let r=dn(t).at(-2)??``;return`'${n}' is not a valid option${r?` of '${r}'`:``}`}function cn(e){let t=un(e),n=z(t.at(-1),()=>`Unnamed missing configuration property: ${JSON.stringify(e)}`),r=t.at(-2)??``;if(!r)return`'${n}' is missing`;if(r===`options`){let e=dn(t).at(-2)??``;return e?`'${n}' of '${e}' is missing`:`'${n}' is missing`}return`'${n}' is missing in '${r}'`}function ln(e){let t=dn(un(e));mn(e)&&t.pop();let n=z(t.at(-1),()=>`Unnamed configuration property: ${JSON.stringify(e)}`),r=t.at(-2)??``;return r?`'${n}' of '${r}'`:`'${n}'`}function un(e){return e.map(e=>e.key).filter(ot).map(String)}function dn(e){let t=[...e];return t.length>1&&(t[0]===`rules`||t[0]===`tokens`)&&t.shift(),t.filter((e,n)=>e!==`options`||n===t.length-1)}function fn(e){return`must be ${pn(e)}`}function pn(e){if(!e.message.startsWith(`Invalid `))return e.message;let t=z(e.expected,()=>`JSON configuration file schema expects an unknown type: ${JSON.stringify(e)}`);switch(t){case`Array`:return`an array`;case`Object`:return`an object`;case`boolean`:return`a boolean`;case`number`:return`a number`;case`string`:return`a string`;default:return t}}function mn(e){return e.at(-1)?.type===`array`}function hn(e){switch(typeof e){case`boolean`:return`a boolean: ${e}`;case`number`:return`a number: ${e}`;case`object`:return e===null?`null`:Array.isArray(e)?`an array: ${gn(e)}`:`an object: ${gn(e)}`;case`string`:return`a string: ${nn(e,30)}`;case`bigint`:case`function`:case`symbol`:case`undefined`:return`an unexpected type: ${typeof e}`}}function gn(e){return nn(en(JSON.stringify(e,void 0,` `)),30)}const _n=/* @__PURE__ */ `abandon.abase.abate.abbreviate.abdicate.abduct.aberrate.abhor.abide.abjure.abnegate.abolish.abominate.abort.abound.abridge.abscond.absolve.absorb.abstain.abstract.abuse.accede.accelerate.accent.accentuate.accept.access.accessorise.accessorize.acclaim.acclimate.acclimatise.acclimatize.accommodate.accompany.accomplish.accord.accost.account.accredit.accrue.acculturate.accumulate.accuse.accustom.acerbate.ache.achieve.achromatise.achromatize.acidify.acidulate.acknowledge.acquaint.acquiesce.acquire.acquit.act.activate.actualise.actualize.actuate.adapt.add.address.adduce.adhere.adjectify.adjectivise.adjectivize.adjoin.adjourn.adjudicate.adjust.administer.administrate.admire.admit.admonish.adopt.adore.adorn.adsorb.adulate.adulterate.advance.adventure.adverbialise.adverbialize.advertise.advise.advocate.aerate.affect.affiliate.affirm.affix.afflict.afford.afforest.affront.age.agglomerate.aggravate.aggregate.aggrieve.agitate.agonise.agonize.agree.aid.ail.aim.air.airbrush.airdrop.airlift.airmail.alarm.alert.alias.alienate.alight.align.allege.allegorise.allegorize.alleviate.allocate.allot.allow.allude.allure.ally.alphabetise.alphabetize.alter.alternate.amalgamate.amass.amaze.amble.ambulate.ambush.ameliorate.amend.amnesty.amortise.amortize.amount.amplify.amputate.amuse.analogise.analogize.analyse.analyze.anchor.anesthetise.anesthetize.anger.angle.anguish.animalise.animalize.animate.annex.annihilate.annotate.announce.annoy.annualise.annualize.annul.annunciate.anoint.answer.antagonise.antagonize.antedate.anticipate.antiquate.anycast.apologise.apologize.apostrophise.apostrophize.appal.appall.appeal.appear.appease.append.appertain.applaud.apply.appoint.appraise.appreciate.apprehend.apprentice.apprise.approach.appropriate.approve.approximate.arbitrage.arbitrate.arch.archive.argue.arise.arm.armor.armour.aromatise.aromatize.arraign.arrange.arrest.arrive.arrow.articulate.ascend.ascertain.ascribe.ask.asphalt.aspirate.aspire.assail.assassinate.assault.assay.assemble.assent.assert.assess.assign.assimilate.assist.associate.assort.assuage.assume.assure.astonish.astound.asynchronise.asynchronize.atomise.atomize.atone.atrophy.attach.attack.attain.attempt.attend.attenuate.attest.attract.attribute.attune.auction.audit.audition.augment.auscultate.authenticate.author.authorise.authorize.autobuild.autocompile.autocreate.autodelete.autofill.autofire.autofocus.autograph.autoindent.autojoin.automate.automerge.autoprefix.autorelease.autosquash.autoupdate.avail.avalanche.avenge.average.avert.aviate.avoid.avow.await.awake.awaken.award.ax.babble.baby.back.backbite.backdate.backfire.backhand.backpack.backpedal.backslap.backslide.backspace.backtrack.backwash.badger.badmouth.baffle.bag.bail.bait.bake.balance.bale.balk.ballast.balloon.ballyhoo.bamboozle.ban.band.bandage.banish.bank.bankroll.bankrupt.banter.bar.barbarise.barbarize.barbecue.bare.bargain.barge.bark.barnstorm.barrage.barricade.barter.base.bash.bask.baste.bat.batch.bath.bathe.batter.battle.bawl.be.beach.beam.bear.beat.beautify.beckon.become.bedazzle.beep.befriend.befuddle.beg.begin.begrudge.beguile.behave.behold.behoove.bejewel.belabor.belabour.beleaguer.believe.belittle.bellow.belong.belt.bemoan.bemuse.bend.benefit.benumb.bequeath.berate.bereave.beseech.beset.besiege.bespangle.bestow.bet.betray.better.bevel.beware.bewilder.bewitch.bias.bid.bide.bill.billow.bind.bisect.bite.blab.blacken.blacklist.blackmail.blame.blank.blast.blaze.blazon.bleach.bleat.bleed.blemish.blench.blend.bless.blight.blind.blindfold.blink.blister.bloat.block.bloody.bloom.blossom.blot.blow.blubber.blue.blunder.blur.blurt.blush.board.boast.boat.bob.boil.bolster.bolt.bomb.bombard.bond.boo.book.boom.boost.boot.border.bore.borrow.boss.botch.bother.bottle.bounce.bound.bow.bowl.box.boycott.brace.brag.braid.brainwash.brake.branch.brand.brave.brawl.breach.break.breakfast.breathe.breed.breeze.brew.bribe.bridge.brief.brighten.brim.bring.brisk.bristle.broach.broadcast.broaden.bronze.brood.brown.browse.bruise.brush.brutalise.brutalize.bubble.buck.buckle.bud.budge.budget.buff.buffer.bug.build.bulk.bully.bump.bunch.bundle.bungle.bunk.buoy.burden.burgeon.burgle.burn.burnish.burrow.burst.bury.bus.bust.bustle.busy.butcher.butter.button.buttress.buy.buzz.bypass.cable.cache.cackle.cage.cajole.cake.calcify.calculate.calibrate.call.calligraph.calm.camber.camouflage.camp.campaign.can.cancel.cane.cannonade.canonise.canonize.canvass.cap.caper.capitalise.capitalize.capitulate.capsize.captain.captivate.capture.carbonise.carbonize.card.care.careen.caress.caricature.carpet.carry.cart.carve.cascade.cash.cast.castigate.catalog.catapult.catch.categorise.categorize.cater.cause.cauterise.cauterize.caution.cave.caw.cease.ceil.celebrate.cement.censor.censure.center.centralise.centralize.centre.centuplicate.certify.chafe.chain.chair.chalk.challenge.chamfer.champion.chance.change.channel.chant.char.characterise.characterize.charge.charm.chart.charter.chase.chasten.chat.chatter.cheapen.cheat.check.cheer.cherish.cherry-pick.cherrypick.chew.chide.chill.chime.chip.chirp.choke.choose.chop.choreograph.chortle.chronicle.chuck.chuckle.chum.churn.circle.circulate.circumscribe.circumvent.cite.civilise.civilize.claim.clamber.clamp.clap.clarify.clash.clasp.classify.clatter.claw.clean.cleanse.clear.clench.click.climb.clinch.cling.clip.cloak.clock.clog.clone.close.clothe.cloud.clown.club.cluster.clutch.clutter.co-author.co-locate.co-pilot.coach.coagulate.coalesce.coarsen.coast.coat.coauthor.coax.cobble.code.codify.coerce.coexist.coffer.cogitate.cohabit.cohere.coil.coin.coincide.collab.collaborate.collapse.collar.collate.collect.collide.collocate.collude.colocate.colonise.colonize.color.colorise.colorize.colour.colourise.colourize.comb.combat.combine.combobulate.come.comfort.command.commandeer.commemorate.commence.commend.comment.commiserate.commission.commit.communicate.commute.compact.compare.compartmentalise.compartmentalize.compel.compensate.compete.compile.complain.complement.complete.complicate.compliment.comply.compose.composite.compound.comprehend.compress.comprise.compromise.compute.computerise.computerize.con.concatenate.conceal.concede.conceive.concentrate.conceptualise.conceptualize.concern.concert.conciliate.conclude.concoct.concur.condemn.condense.condescend.condition.condole.condone.conduct.confer.confess.confide.configure.confine.confirm.confiscate.conflict.conform.confound.confront.confuse.congeal.congest.conglomerate.conglutinate.congratulate.congregate.conjecture.conjugate.conjure.connect.conquer.consecrate.consent.conserve.consider.consign.consist.console.consolidate.conspire.constitute.constrain.constrict.construct.construe.consult.consume.contact.contain.contaminate.contemplate.contend.content.contest.contextualise.contextualize.continue.contort.contract.contradict.contrast.contravene.contribute.contrive.control.convalesce.convene.converge.converse.convert.convey.convict.convince.convulse.cook.cool.coop.cooperate.coordinate.cope.copilot.copperplate.copy.copyright.cork.corner.correct.correlate.correspond.corroborate.corrode.corrupt.cost.cotton.couch.cough.counsel.count.counter.counteract.counterbalance.counterfeit.countermark.countersign.couple.court.cover.covet.cower.crack.crackle.cradle.craft.cram.cramp.crane.crank.crash.crave.crawl.creak.crease.create.credit.creep.cremate.crenelate.crest.crimp.cringe.crinkle.cripple.crisscross.criticise.criticize.critique.croak.crop.cross.cross-check.cross-examine.crosscheck.crossexamine.crouch.crow.crowd.crown.crucify.cruise.crumb.crumble.crumple.crunch.crush.cry.crystallise.crystallize.cube.cuddle.cudgel.cuff.cull.culminate.cultivate.cup.curb.curdle.cure.curl.curse.curtail.curve.cushion.customise.customize.cut.cycle.dab.dabble.dally.dam.damage.dampen.dance.dandle.dangle.dare.darken.dart.dash.date.daunt.dawdle.dawn.daydream.daze.dazzle.deactivate.deaden.deadlock.deafen.deal.deallocate.deauthenticate.deauthorise.deauthorize.debase.debate.debit.debug.debunk.decamp.decay.deceive.decentralise.decentralize.decide.decimalise.decimalize.decimate.decipher.deck.declare.decline.decode.decommission.decompile.decompose.decompress.deconsolidate.decontextualise.decontextualize.decorate.decouple.decrease.decree.decry.dedent.dedicate.deduce.deduct.deduplicate.deed.deem.deepen.deface.defame.default.defeat.defect.defend.defer.define.deflagrate.deflate.deflect.deflower.defocus.defoliate.deforest.deform.defray.defreeze.defrost.defuse.defy.degenerate.degrade.dehumanise.dehumanize.dehydrate.deify.deign.delay.delegate.delete.deliberate.delight.delimit.delineate.deliver.delude.delve.demagnetise.demagnetize.demand.dematerialise.dematerialize.demobilise.demobilize.demolish.demonstrate.demoralise.demoralize.demote.demystify.denominate.denote.denounce.dent.deny.deorbit.deoxidise.deoxidize.depart.depend.depict.deplete.deplore.deploy.depopulate.deport.depose.deposit.deprave.deprecate.depreciate.depress.deprive.depute.dequeue.derail.derezz.deride.derive.derogate.descend.describe.deserialise.deserialize.desert.deserve.design.designate.desire.desolder.despair.despise.despond.destroy.destruct.destructure.detach.detail.detain.detect.deter.deteriorate.determine.detest.dethrone.detonate.detoxicate.detract.devalue.devastate.develop.deviate.devise.devitalise.devitalize.devolve.devote.devour.diagnose.dial.dice.dictate.die.diff.differ.differentiate.diffract.diffuse.dig.digest.digitalise.digitalize.digitise.digitize.dignify.dilapidate.dilate.dilute.dim.dimensionalise.dimensionalize.diminish.dine.dip.direct.dirty.disable.disabuse.disadvantage.disagree.disallow.disappear.disappoint.disapprove.disarm.disband.disburse.discard.discern.discharge.discipline.disclaim.disclose.discolor.discolour.discombobulate.discompose.disconcert.disconnect.discontinue.discount.discourage.discourse.discover.discredit.discriminate.discuss.disdain.disembark.disengage.disentangle.disfigure.disfocus.disgrace.disgruntle.disguise.disgust.dish.dishevel.dishonor.dishonour.disillusion.disinfect.disinherit.disintegrate.disinterest.disjoint.dislike.dislocate.dislodge.dismantle.dismay.dismiss.dismount.disobey.disorder.disorganise.disorganize.disorient.disorientate.disown.dispatch.dispel.dispense.disperse.displace.display.displease.dispose.dispossess.disprove.dispute.disqualify.disregard.disrespect.disrupt.dissatisfy.dissect.disseminate.dissipate.dissociate.dissolve.dissuade.distain.distance.distil.distill.distinguish.distort.distract.distress.distribute.distrust.disturb.disunite.ditch.dither.dive.diverge.diversify.divert.divest.divide.divorce.divulge.do.dock.dockerise.dockerize.doctor.document.dodge.dog.dole.domesticate.dominate.don.donate.doom.dope.dot.dote.double.doubt.douse.down.downgrade.download.downplay.doze.draft.drag.drain.dramatise.dramatize.drape.draw.drawl.dread.dream.dredge.drench.dress.dribble.drift.drill.drink.drip.drive.drizzle.drone.droop.drop.drown.drowse.drug.drum.dry.dub.duck.dulcify.dull.dump.dupe.duplicate.dust.dwarf.dwell.dwindle.dye.eager-load.eagerload.earn.ease.eat.eavesdrop.ebb.echo.eclipse.economise.economize.edge.edit.educate.efface.effect.egg.eject.eke.elaborate.elapse.elate.elbow.elect.electrify.electrocute.elevate.elicit.eliminate.elongate.elucidate.elude.emaciate.email.emanate.emancipate.embark.embarrass.embed.embellish.embitter.emblazon.embody.embolden.emboss.embrace.embroider.emend.emerge.emigrate.emit.empathise.empathize.emphasise.emphasize.employ.empower.empty.emulate.enable.enact.encapsulate.encase.enchant.encircle.enclose.encode.encompass.encounter.encourage.encroach.encrust.encrypt.encumber.end.endanger.endear.endeavor.endeavour.endorse.endow.endure.energise.energize.enervate.enfeeble.enfold.enforce.engage.engender.engineer.engrave.engross.engulf.enhance.enjoy.enlarge.enlighten.enlist.enliven.enmesh.ennoble.enqueue.enquire.enrage.enrapture.enrich.enrol.enroll.enshrine.ensnare.ensue.ensure.entail.entangle.enter.entertain.enthrone.enthuse.entice.entitle.entomb.entrap.entreat.entrench.entrust.entwine.enumerate.enunciate.envelop.environmentalise.environmentalize.envisage.envision.envy.epitomise.epitomize.equal.equalise.equalize.equate.equip.eradicate.erase.erect.erode.err.erupt.escalate.escape.eschew.escort.espouse.essentialise.essentialize.establish.esteem.estimate.estrange.etch.evacuate.evade.evaluate.evaporate.even.evict.evidence.evince.evoke.evolve.exacerbate.exact.exaggerate.exalt.examine.exasperate.excavate.exceed.excel.except.exchange.excise.excite.exclaim.exclude.excuse.execute.exemplify.exempt.exercise.exert.exfoliate.exhale.exhaust.exhibit.exhilarate.exhort.exhume.exile.exist.exit.exonerate.expand.expatriate.expect.expedite.expel.expend.experience.experiment.expire.explain.explode.exploit.explore.export.expose.expound.express.expropriate.expurgate.extend.exterminate.extinguish.extirpate.extol.extort.extract.extradite.extrapolate.extricate.exult.eye.fabricate.face.facilitate.factor.fade.fail.faint.fake.fall.falsify.falter.familiarise.familiarize.fan.fancy.fantasise.fantasize.fare.farm.fascinate.fashion.fasten.fate.fathom.fatigue.fatten.fault.favor.favour.fax.faze.fear.feast.feather.feature.federate.feed.feel.feign.fell.fence.fend.ferment.ferry.fertilise.fertilize.fetch.fiddle.fidget.field.fight.figure.filch.file.fill.film.filter.finalise.finalize.finance.find.fine.fine-tune.finetune.finger.finish.fire.firm.fish.fit.fix.fizz.fizzle.flabbergast.flag.flail.flake.flame.flank.flap.flare.flash.flatten.flatter.flaunt.flavor.flavour.flaw.fleck.flee.flesh.flex.flick.flicker.flinch.fling.flip.flirt.flit.float.flock.flog.flood.floor.flop.flounce.flounder.flourish.flout.flow.flower.fluctuate.flush.fluster.flute.flutter.fly.foam.focus.foil.foist.fold.foliate.follow.foment.fool.forbid.force.force-push.forcepush.ford.forebode.forecast.foresee.foreshadow.forestall.foretell.forfeit.forge.forget.forgive.forgo.fork.form.formalise.formalize.format.formulate.forsake.fortify.forward.fossilise.fossilize.foster.foul.found.fracture.fragment.frame.frank.fray.free.freeze.frequent.freshen.fret.friend.frighten.frill.fringe.front.frost.frown.fructify.frustrate.fry.fuel.fulfil.fulfill.fulgurate.fulminate.fumble.fume.fumigate.function.fund.furbish.furl.furnish.furrow.further.fuss.future-proof.futureproof.gain.gallop.galvanise.galvanize.gamble.game.gang.garner.garnish.gasp.gather.gauge.gaze.gear.generalise.generalize.generate.generify.gesticulate.gesture.get.ghost.gift.giggle.gild.give.gladden.glamorise.glamorize.glamourise.glamourize.glance.glare.glaze.gleam.glean.glide.glimmer.glimpse.glisten.glitter.gloat.globalise.globalize.glorify.gloss.glow.glue.gnaw.go.goad.gobble.goldplate.gossip.gouge.govern.grab.grace.grade.graduate.graft.grant.granulate.grapple.grasp.grate.gratify.gravitate.graze.grease.green.greet.grieve.grill.grimace.grin.grind.grip.gripe.grit.groom.groove.grope.ground.group.grow.growl.grumble.grunt.guarantee.guard.guess.guide.gulp.gush.gut.gyrate.gzip.habilitate.habituate.hack.haggle.hail.hale.hallucinate.halt.halve.ham.hammer.hamper.hand.handcraft.handcuff.handicap.handle.handstamp.handwrite.hang.happen.harass.harbor.harbour.hard-code.hardcode.harden.harm.harmonise.harmonize.harness.harp.harvest.hash.hasp.hassle.hasten.hatch.hate.haul.haunt.have.haw.hawk.hazard.haze.head.headline.headquarter.heal.heap.hear.hearten.heat.heave.heckle.hedge.heed.heel.heft.heighten.heist.helm.help.hem.herald.herd.hesitate.heterodyne.hew.hex.hibernate.hiccough.hiccup.hide.highlight.hijack.hike.hinder.hinge.hint.hire.hiss.hit.hitch.hitchhike.hoax.hobble.hog.hoist.hold.hole.hollow.home.homogenise.homogenize.hone.honeycomb.honor.honour.hood.hook.hoot.hoover.hop.hope.horrify.hose.hospitalise.hospitalize.host.hound.house.housekeep.hover.howl.huckster.huddle.hug.hulk.hull.hum.humanise.humanize.humble.humidify.humiliate.humor.humour.hunch.hunger.hunt.hurl.hurry.hurt.hurtle.hush.hustle.hybridise.hybridize.hydrate.hymn.hype.hyperbolise.hyperbolize.hyperventilate.hyphenate.hypnotise.hypnotize.hypothesise.hypothesize.ice.idealise.idealize.identify.idle.idolise.idolize.ignite.ignore.illegalise.illegalize.illuminate.illustrate.imagine.imbricate.imitate.immaterialise.immaterialize.immerse.immigrate.immobilise.immobilize.immortalise.immortalize.immunise.immunize.impair.impale.impart.impeach.impede.impel.imperil.impersonate.impinge.implant.implement.implicate.implode.implore.imply.import.impose.impound.impoverish.impress.imprint.imprison.improve.improvise.impute.inactivate.inaugurate.incapacitate.incarcerate.incense.inch.incinerate.incise.incite.incline.include.incommode.incorporate.increase.incriminate.incubate.inculcate.inculpate.incur.indebt.indent.index.indicate.indict.indispose.indite.individualise.individualize.induce.indulge.indurate.industrialise.industrialize.infect.infer.infest.infiltrate.infix.inflame.inflate.inflict.influence.inform.infract.infringe.infuriate.infuscate.infuse.ingest.ingrain.inhabit.inhale.inhere.inherit.inhibit.initial.initialise.initialize.initiate.inject.injure.ink.inlay.inline.innovate.input.inquire.inscribe.insert.insinuate.insist.insolate.inspect.inspire.install.instantiate.instigate.instil.instill.institute.institutionalise.institutionalize.instruct.instrument.insulate.insult.insure.integrate.intend.intensify.interact.intercept.interchange.interconnect.interest.interface.interfere.interiorise.interiorize.interject.interlace.interleave.interlink.interlock.intermediate.intermix.intern.internalise.internalize.internationalise.internationalize.interpolate.interpose.interpret.interrelate.interrogate.interrupt.intersect.intersperse.intertwine.intervene.interview.interweave.intimidate.intonate.intone.intoxicate.intrigue.introduce.intromit.introspect.introvert.intrude.intuit.inundate.inure.invade.invalidate.invent.inventory.invert.invest.investigate.invigilate.invigorate.invite.invoice.invoke.involve.ionise.ionize.irk.iron.irradiate.irrigate.irritate.isolate.issue.italicise.italicize.itch.itemise.itemize.iterate.jab.jail.jailbreak.jam.jar.jeer.jellify.jelly.jeopardise.jeopardize.jest.jet.jettison.jetty.jib.jig.jingle.jinx.jive.jog.join.joke.jolly.jolt.jostle.jot.journal.journey.jubilate.judge.juggle.jumble.jump.jump-start.jumpstart.justify.juxtapose.kamikaze.keep.kerb.kern.kick.kickstart.kid.kidnap.kill.kindle.kinescope.kiss.kite.knead.kneel.knight.knit.knock.knockdown.knot.know.knuckle.kudos.label.labor.labour.lace.lack.ladder.lag.lament.laminate.land.landscape.language.languish.lantern.lap.lapse.lash.lasso.last.latch.lateralise.lateralize.lattice.laud.laugh.launch.launder.lavish.lay.layer.lazy-load.lazyload.leach.lead.leak.lean.leap.leapfrog.learn.lease.leash.leave.lecture.leech.leer.left-align.legalise.legalize.legislate.legitimatise.legitimatize.legitimise.legitimize.lend.lengthen.lessen.let.level.lever.leverage.levitate.levy.lexicalise.lexicalize.liberate.license.lie.lift.light.lighten.like.liken.limit.limp.line.linearise.linearize.linger.link.lint.liquefy.liquidate.liquify.lisp.list.listen.lithograph.litigate.litter.live.load.loan.loathe.lob.lobby.localise.localize.locate.lock.lodge.log.loiter.long.look.loom.loop.loosen.loot.lose.louden.lounge.love.lower.lull.lullaby.lumber.luminate.luminesce.lump.lunge.lurch.lurk.lynch.magnetise.magnetize.magnify.mail.maim.maintain.make.man.manage.maneuver.mangle.manicure.manifest.manipulate.mantle.manufacture.map.march.marginalise.marginalize.marinate.mark.market.maroon.marry.marshal.marvel.mash.mask.masquerade.mass.massacre.massage.master.mastermind.match.materialise.materialize.matter.mature.maul.maximise.maximize.mean.meander.measure.meddle.mediate.meditate.meet.mellow.melt.memoise.memoize.memorise.memorize.mend.mention.mentor.merge.merit.mesmerise.mesmerize.mess.migrate.milk.mill.mimic.mince.mind.mine.mingle.minify.minimise.minimize.mint.mirror.misdirect.misinterpret.misjudge.mislay.mislead.mislexicalise.mislexicalize.misparse.misplace.misrepresent.miss.misspeak.misspell.mistake.mistokenise.mistokenize.mistreat.mistrust.misunderstand.misuse.mitigate.mix.mob.mobilise.mobilize.mock.model.moderate.modernise.modernize.modify.modularise.modularize.modulate.moisten.mold.monetise.monetize.monitor.monkey.monopolise.monopolize.moor.mop.mope.moralise.moralize.mortgage.mortify.motion.motivate.motorise.motorize.mount.mourn.mouth.move.mow.muddle.muffle.mug.multicast.multiply.mumble.murder.murmur.muscle.muse.muster.mutate.mute.mutilate.mutter.muzzle.mystify.nab.nag.nail.name.namedrop.namespace.nap.narrate.narrow.navigate.near.neaten.necessitate.need.needle.negate.neglect.negotiate.nerf.nest.nestle.net.network.neuralise.neuralize.neutralise.neutralize.nibble.nicen.nick.nickname.ninja.nip.nitpick.nix.nod.noiseproof.nomenclate.nominalise.nominalize.nominate.nondimensionalise.nondimensionalize.nonlinearise.nonlinearize.normalise.normalize.nose.nosedive.notch.note.notice.notify.nourish.novelise.novelize.nuance.nudge.nuke.nullify.numb.number.numerate.numericalise.numericalize.numericise.numericize.nurse.nurture.nuzzle.obey.obfuscate.object.objectify.obligate.oblige.obliterate.obscure.observe.obsess.obstruct.obtain.obtrude.obtund.obturate.obviate.occasion.occlude.occult.occupy.occur.offend.offer.officiate.offload.offset.oil.omit.ooze.opacify.open.operate.opine.oppose.oppress.opt.optimise.optimize.orange.orbit.orchestrate.ordain.order.ordinate.organise.organize.orient.orientate.originate.ornament.orphan.oscillate.oust.outclass.outdent.outfigure.outgrow.outguess.outlaw.outline.outlive.outmatch.outnumber.outperform.output.outrage.outrank.outrival.outrun.outscore.outsell.outshine.outsmart.outsource.outstretch.outthink.outweigh.overachieve.overact.overbid.overburden.overcharge.overclock.overcome.overcompensate.overcrowd.overdo.overdose.overdrive.overeat.overemphasise.overemphasize.overestimate.overexert.overflow.overgeneralise.overgeneralize.overgrow.overhaul.overhear.overheat.overindulge.overlap.overlay.overload.overlook.overplay.overpower.overproduce.overprotect.overrate.overreach.overreact.overrefine.override.overrule.overrun.oversaturate.oversee.overshadow.overshoot.oversimplify.oversleep.overspecialise.overspecialize.overspend.overstate.overstock.oversupply.overtake.overthrow.overturn.overuse.overvalue.overwhelm.overwrite.owe.own.oxidate.oxidise.oxidize.pace.pacify.pack.package.pad.paddle.padlock.page.paint.pair.palliate.palm.pamper.pan.panel.panic.pant.paper.parachute.parade.paragon.parallelise.parallelize.paralyse.paralyze.parameterise.parameterize.parametrise.parametrize.paraphrase.pardon.pare.park.parley.parody.parrot.parse.part.participate.partition.partner.pass.paste.pasteurise.pasteurize.pasture.pat.patch.patent.patrol.patronise.patronize.pattern.patternise.patternize.pause.pave.paw.pay.peak.peck.pedal.peek.peel.peep.peer.peg.pelt.penalise.penalize.pencil.penetrate.pension.pep.pepper.perambulate.perceive.perch.perfect.perform.perfume.perish.permeate.permit.permutate.perpetrate.perpetuate.perplex.persecute.persevere.persist.personalise.personalize.personify.persuade.pertain.perturb.peruse.pervade.pester.pet.petition.petrify.phase.phone.photocopy.photograph.phrase.pick.pickle.picture.pierce.pile.pillage.pilot.pin.pinch.pine.pinpoint.pioneer.pipe.pique.pirate.pit.pitch.pity.pivot.pixelate.placate.place.plagiarise.plagiarize.plague.plan.plant.plaster.plate.play.plead.please.pledge.plod.plot.plow.pluck.plug.plummet.plump.plunder.plunge.ply.poach.pocket.point.poise.poison.poke.polarise.polarize.police.polish.poll.pollute.polymerise.polymerize.ponder.pool.pop.popularise.popularize.populate.portray.pose.position.possess.post.postdate.postfix.postpone.postulate.pot.pounce.pound.pour.pout.powder.power.practice.praise.prattle.pray.pre-enact.pre-release.pre-render.preach.prebuild.precede.precipitate.preclude.precompile.predetermine.predicate.predict.predispose.predominate.preen.preenact.prefer.prefigure.prefill.prefix.prejudice.prelude.premeditate.preoccupy.prepare.prerelease.prerender.presage.prescribe.present.preserve.preside.press.pressure.pressurise.pressurize.presume.presuppose.pretend.prettify.pretty.prevail.prevaricate.prevent.preview.prey.price.prick.pride.prime.primp.print.prioritise.prioritize.prise.privatise.privatize.prize.probe.proceed.process.proclaim.procrastinate.procure.prod.produce.profess.professionalise.professionalize.profile.profit.program.progress.prohibit.project.proliferate.prolong.promise.promote.prompt.promulgate.pronounce.proofread.prop.propagate.propel.proportion.propose.propulse.proscribe.prosecute.prospect.prosper.protect.protest.protract.protrude.prove.provide.provision.provoke.prowl.proxy.prune.pry.publicise.publicize.publish.pucker.puff.puke.pull.pulp.pulverise.pulverize.pummel.pump.punch.punctuate.puncture.punish.purchase.purge.purify.purple.purport.purpose.purr.purse.pursue.push.put.puzzle.quack.quadruple.quake.qualify.quantify.quantise.quantize.quarantine.quarrel.quarter.quash.quave.quaver.quelch.quell.quench.query.question.queue.quibble.quick.quick-freeze.quicken.quickfreeze.quiet.quieten.quip.quirk.quirl.quit.quiver.quiz.quote.qwikify.race.rack.radiate.rage.raid.rail.rain.raise.rake.rally.ram.ramble.ramify.ramp.range.rank.ransack.rant.rap.rarefy.rasp.rat.rate.ratify.ration.rationalise.rationalize.rattle.ravage.rave.raze.re-check.re-embark.re-emerge.re-enable.re-enact.re-engage.re-enlist.re-enter.re-establish.re-evaluate.re-examine.re-read.re-release.reabsorb.reach.react.read.readjust.readmit.reaffirm.realign.realise.realize.reallocate.reambulate.reanimate.reap.reappear.reapply.rear.rearrange.reascend.reason.reassemble.reassert.reassess.reassign.reassume.reassure.rebase.rebel.reboot.rebound.rebuff.rebuild.rebuke.recall.recap.recapitulate.recapture.recast.recede.receive.recess.recharge.recheck.reciprocate.recite.reckon.reclaim.recline.recognise.recognize.recoil.recollapse.recollect.recombobulate.recommence.recommend.recommission.recommit.recompile.recompose.reconcile.recondition.reconfigure.reconfirm.reconquer.reconsider.reconsolidate.reconstitute.reconstruct.reconvene.reconvert.record.recount.recoup.recouple.recover.recreate.recriminate.recross.recruit.rectify.recuperate.recur.recut.recycle.redden.redeem.redefine.redeploy.redesign.redevelop.redirect.rediscover.redistribute.redo.redouble.redound.redraw.reduce.reel.reembark.reemerge.reenable.reenact.reengage.reenlist.reenter.reestablish.reevaluate.reexamine.refactor.refer.reference.refill.refine.refit.reflect.reform.reformat.refract.refrain.refresh.refrigerate.refund.refurbish.refuse.refute.regain.regard.regenerate.register.regress.regret.regrind.regroup.regularise.regularize.regulate.regurgitate.rehabilitate.rehearse.reheat.reify.reign.reimburse.reimplement.reimpose.rein.reincorporate.reinforce.reinsert.reinstall.reinstate.reinsure.reintegrate.reinterpret.reintroduce.reinvest.reissue.reiterate.reject.rejoice.rejoin.rejuvenate.rekindle.relapse.relate.relax.relay.relearn.release.relegate.relent.relieve.relinquish.relish.reload.relocate.rely.remain.remand.remark.remarry.remarshal.remedy.remember.remerge.remind.reminisce.remit.remix.remodel.remount.remove.remunerate.rename.render.renege.renegotiate.renew.renounce.renovate.rent.reoccupy.reopen.reorder.reorganise.reorganize.repack.repaint.repair.repay.repeal.repeat.repel.rephrase.replace.replant.replenish.replicate.reply.repolish.report.reposition.repossess.represent.repress.reprieve.reprimand.reprint.reproach.reprobate.reproduce.reprogram.republish.repudiate.repulse.repute.request.requeue.require.requisition.reread.rerelease.reroute.reschedule.rescind.rescue.research.reseat.resell.resemble.resent.reseparate.reserve.reset.reshape.reshuffle.reside.resign.resist.resize.resolder.resolve.resort.resound.resow.respect.respond.rest.restage.restart.restate.restore.restrain.restrict.restructure.result.resume.resupply.resurface.resurrect.resuscitate.retain.retake.retaliate.reteach.retell.rethink.retire.retort.retouch.retrace.retract.retranslate.retrap.retread.retreat.retrieve.retrograde.retry.return.reunite.reuse.rev.revalidate.revamp.reveal.revel.reverberate.revere.reverse.revert.review.revile.revise.revisit.revitalise.revitalize.revive.revoke.revolt.revolutionise.revolutionize.revolve.reward.rework.rewrite.rhyme.rib.rid.riddle.ride.ridge.ridicule.rig.right.right-align.ring.rinse.riot.rip.ripple.rise.risk.rival.rivet.roam.roar.roast.rob.robustify.rock.rocket.roll.rollback.romanise.romanize.romp.root.rope.rot.rotate.round.rouse.route.row.rub.ruffle.ruin.rule.rumble.ruminate.rummage.rumple.run.rupture.rush.rust.rustle.sabotage.sack.sacrifice.sadden.saddle.safeguard.sag.sail.salt.salute.salvage.sample.sanction.sandwich.sanitise.sanitize.sap.sass.satisfy.saturate.saunter.save.savor.savour.savvy.saw.say.scaffold.scald.scale.scamper.scan.scandalise.scandalize.scar.scare.scatter.scavenge.scent.schedule.school.scoff.scold.scoop.scorch.score.scorn.scour.scowl.scramble.scrap.scrape.scratch.scrawl.scream.screech.screen.screw.scribble.scroll.scrub.scrutinise.scrutinize.sculpt.scurry.scuttle.seal.search.season.seat.seclude.secrete.secure.seduce.see.seed.seek.seem.seep.seethe.segment.segregate.seize.select.sell.send.sense.sensitise.sensitize.sentence.sentinel.separate.sequence.serialise.serialize.serve.service.set.settle.sever.sew.shade.shadow.shake.shame.shape.share.sharpen.shatter.shave.shear.sheath.shed.shell.shelter.shelve.shepherd.shield.shift.shimmer.shine.ship.shiver.shock.shoot.shop.short-circuit.shortcircuit.shorten.shoulder.shout.shove.show.shower.shred.shriek.shrink.shrivel.shroud.shrug.shudder.shuffle.shun.shunt.shut.shutter.sicken.side.sideline.sidle.sift.sigh.sight.sign.signal.signify.silence.silhouette.simplify.simulate.sing.singe.single.sink.sip.sire.sit.situate.size.sizzle.skate.sketch.skew.ski.skid.skim.skin.skip.skirt.skyrocket.slacken.slam.slant.slap.slash.slate.slaughter.slay.sleep.slice.slide.sling.slink.slip.slit.slither.slope.slouch.slow.slug.slump.slur.smack.smash.smear.smell.smile.smirk.smoke.smooth.smoothen.smother.smudge.smuggle.snake.snap.snare.snarl.snatch.sneak.sneer.sneeze.snicker.sniff.snoop.snooze.snore.snort.snow.snub.snuff.snug.snuggle.soak.soar.sob.socialise.socialize.soften.soil.solder.solicit.solve.soothe.sophisticate.sort.sound.sour.sow.space.span.spare.spark.sparkle.spatialise.spatialize.spatter.spawn.speak.spear.spearhead.specialise.specialize.specify.speckle.speculate.speed.spell.spend.spice.spike.spill.spin.spiral.spirit.spit.spite.splash.splatter.splice.splinter.split.splutter.spoil.sponsor.spoon.sport.spot.sprawl.spray.spread.spring.sprinkle.sprint.sprout.spur.spurn.spurt.spy.squander.square.squash.squat.squeak.squeal.squeeze.squint.squirm.squirt.stab.stabilise.stabilize.stable.stack.staff.stage.stagger.stain.stake.stalk.stall.stammer.stamp.stand.standardise.standardize.stare.start.startle.starve.stash.state.station.stave.stay.steady.steal.steam.steer.stem.step.stereotype.sterilise.sterilize.stick.stiffen.stifle.stigmatise.stigmatize.stimulate.sting.stink.stipulate.stir.stitch.stock.stomp.stone.stoop.stop.store.storm.stow.straddle.straighten.strain.strand.strangle.strap.strategise.strategize.stratify.stray.streak.stream.streamline.strengthen.stress.stretch.stride.strike.string.stringify.strip.strive.stroke.stroll.structure.struggle.strut.stub.study.stuff.stumble.stump.stun.stunt.stutter.style.stylise.stylize.subdivide.subdue.subject.sublet.submerge.submit.subordinate.subscribe.subset.subside.subsidise.subsidize.substantiate.substantify.substantivise.substantivize.substitute.subsume.subtract.subvert.succeed.succumb.sue.suffer.suffice.suffix.suffocate.suggest.suit.summarise.summarize.summon.sunset.superimpose.supersede.supervise.supplant.supplement.supply.support.suppose.suppress.surface.surge.surmise.surmount.surpass.surprise.surrender.surround.survey.survive.suspect.suspend.sustain.swagger.swallow.swamp.swap.swarm.sway.swear.sweat.sweep.sweeten.swell.swerve.swim.swing.swirl.switch.swivel.swoop.symbolise.symbolize.symlink.sympathise.sympathize.synchronise.synchronize.synthesise.synthesize.systematise.systematize.systemise.systemize.table.tabulate.tack.tackle.tag.tail.tailor.taint.take.talk.tally.tame.tamper.tan.tangle.tap.tape.taper.tar.target.tarnish.tarry.taste.tatter.tattoo.taunt.tax.taxi.teach.team.tear.tease.telephone.televise.tell.tempt.tend.tender.tense.term.terminate.terrify.terrorise.terrorize.test.testify.tether.text.texture.thank.thatch.thaw.theorise.theorize.thicken.thin.think.thrash.thread.threaten.thrill.thrive.throb.throttle.throw.thrust.thud.thumb.thump.thunder.thwart.tick.tickle.tidy.tie.tighten.tile.till.tilt.time.tinge.tingle.tinker.tint.tip.tiptoe.tire.title.toast.toddle.toggle.toil.tokenise.tokenize.tolerate.toll.tone.top.topple.torment.torture.toss.total.totter.touch.toughen.tour.tout.tow.tower.toy.trace.track.trade.trail.train.tramp.trample.transact.transcend.transcribe.transfer.transfigure.transfix.transform.transfuse.translate.transmit.transmute.transpile.transpire.transplant.transport.transpose.trap.travel.traverse.tread.treasure.treat.tremble.trench.trespass.triage.triangulate.trick.trickle.trigger.trim.trip.triple.triumph.trot.trouble.troubleshoot.trudge.trump.truncate.truss.trust.try.tuck.tug.tumble.tune.turn.tutor.tweak.twinkle.twirl.twist.twitch.type.typify.tyrannise.tyrannize.unarm.unassign.unauthorise.unauthorize.unbalance.unbind.unblur.unbox.unbuckle.unbump.unbundle.unbutton.uncheck.unclog.uncollapse.uncommit.unconsolidate.uncouple.uncover.undeploy.underbid.undercut.underestimate.undergo.underline.undermine.underrate.underscore.undersell.understand.understate.undertake.undervalue.undo.undress.undulate.unearth.unfasten.unfocus.unfold.unfreeze.unfurl.ungroup.unhinge.unhitch.unhook.unicast.unify.unindent.uninstall.unite.universalise.universalize.unjoin.unknot.unlearn.unleash.unload.unlock.unmarshal.unmask.unmerge.unpack.unpair.unpick.unplug.unravel.unrelease.unresolve.unroll.unsaddle.unscrew.unseal.unselect.unserialise.unserialize.unset.unsettle.unsolder.unsquash.unstage.unsubscribe.untangle.untick.untie.untrap.unveil.unwind.unwrap.unzip.unzoom.up.update.upend.upgrade.uphold.upholster.uplift.upload.uproot.upsert.upset.upstage.urge.use.usher.usurp.utilise.utilize.utter.vacate.vaccinate.vacuum.validate.valuate.value.vandalise.vandalize.vanish.vaporise.vaporize.vapourise.vapourize.varnish.vary.vault.veer.vegetate.vendor.venerate.vent.ventilate.venture.verbalise.verbalize.verify.version.vest.vet.veto.vibrate.victimise.victimize.view.vindicate.violate.visit.visualise.visualize.vitalise.vitalize.vivify.voice.void.volunteer.vomit.vote.vouch.vow.wad.waddle.wade.waft.wag.wage.wail.wait.waive.wake.waken.walk.wall.waltz.wander.wane.want.warm.warn.warp.warrant.wash.waste.watch.water.waterlog.waterproof.wave.waver.wax.weaken.wean.wear.weather.weave.wed.wedge.weed.weep.weigh.welcome.weld.whack.wheedle.wheel.whimper.whine.whip.whirl.whisk.whisper.whistle.whitelist.whiten.whitewash.whittle.widen.wield.wiggle.will.wilt.win.wince.wind.wink.winnow.wipe.wire.wish.withdraw.wither.withhold.withstand.witness.wobble.wonder.woo.word.work.worry.worsen.worship.wound.wrap.wreck.wrench.wrestle.wriggle.wring.wrinkle.write.writhe.x-ray.xray.yak.yank.yawn.yearn.yell.yellow.yelp.yield.yodel.youthen.zap.zero.zigzag.zip.zone.zoom`.split(`.`);function vn(e){return dt(_n,e)!==-1}async function yn(e){let t=[],n=Xt(e),r={};for(;n!==null;){if(t.includes(n)){let e=[...t,n].map(e=>`'${e}'`).join(` -> `);throw TypeError(`Failed to parse '${n}' as a Comet configuration: 'extends' has a cyclic dependency in ${e}`)}t.push(n);let e=await an(n);r=F({git:bn(e.git),tokens:xn(e.tokens),rules:Sn(e.rules)},r),n=e.extends===void 0?null:Xt(e.extends,n)}return Cn(r)}function bn(e){return e?.defaultBranch===void 0?{}:{defaultBranch:e.defaultBranch}}function xn(e){return e?.issueLinks===void 0?{}:{issueLinks:{prefixes:e.issueLinks.prefixes??[],wildcards:e.issueLinks.wildcards??[]}}}function Sn(e){return e===void 0?{}:Object.fromEntries(Object.entries(e).filter(st).map(([e,t])=>[e,typeof t==`string`?{level:t}:t]))}function Cn(e){let t=e.tokens?.issueLinks??null;if(t===null)return e;let n=t.prefixes??[],r=t.wildcards??[],i=n.map(e=>e.trim()).filter(M),a=r.map(e=>e.trim()).filter(M);return{...e,tokens:{issueLinks:{prefixes:ft(i),wildcards:ft(a)}}}}async function wn(e,t){for(let n of e)if(!t||await Yt(n))return n;return Tn()}async function Tn(){return await Yt(`comet.json`)?`comet.json`:await Yt(`comet.jsonc`)?`comet.jsonc`:null}function En(e){let t=[...Dn(e)];if(t.length===0)return``;let n=V(t.length,`issue`,`issues`),r=t.map(e=>`- ${e}`).join(`
|
|
30
30
|
`);return`${S`${n} detected in the Comet configuration:`}\n${r}\n`}function*Dn(e){if(e.rules?.useImperativeSubjects?.level===`error`){let t=e.rules.useImperativeSubjects.options?.whitelist??[];if(t.length>0){let e=ft(t.map(e=>e.trim().toLowerCase()).filter(M).filter(vn));e.length>0&&(yield`'whitelist' of 'useImperativeSubjects' contains words that are already recognised as imperative verbs: ${e.join(`, `)}`)}}if(e.rules?.useIssueLinks?.level===`error`){let t=e.tokens?.issueLinks,n=t?.prefixes??[],r=t?.wildcards??[];t===void 0?yield`'issueLinks' in 'tokens' should be defined when 'useIssueLinks' is enabled`:n.length+r.length===0&&(yield`'issueLinks' in 'tokens' should contain at least one non-blank prefix or wildcard when 'useIssueLinks' is enabled`)}}function On(e,t=0){return W(`codeblock`,e,t)}function W(e,t,n=0){return{type:e,value:t,range:[n,n+t.length]}}function G(...e){return t=>e.includes(t.type)}function K(...e){return t=>!e.includes(t.type)}function q(e){return e.at(-1)?.range[1]??0}function kn(e,t){let n=0,r=0,i=0;for(let a of e)if(n+=a.value.length,n>t){if(r===0){let e=t-n+a.value.length;r=a.range[0]+e}i=a.range[1]}return i===r?null:[r,i]}function An(e){return e.filter(M).map(e=>RegExp.escape(e)).join(`|`)}function J(e,t={}){let n=t.preserveCapturingGroups??!1,r=e.filter(M);return n?r.join(`|`):r.map(e=>`(?:${e})`).join(`|`)}const jn=String.raw`(?<code>${"`"}[^${"`"}]*${"`"})`,Mn=String.raw`(?<hyperlink>(?:https://|mailto:|ssh://)\S*[^\s.,!?"')\]}])`,Nn=String.raw`(?<punctuation>[\p{P}\p{S}])`,Pn=String.raw`(?<revert>(?i:revert))(?=\s*")`,Fn=String.raw`(?<=\s)(?<semver>[0-9a-f]{7,}|v?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?)(?=[\s,]|"|$)`,In=String.raw`(?<squash>(?i:amend!+|fixup!+|squash!+|!+amend\b|!+fixup\b|!+squash\b))`,Ln=String.raw`(?<=^\s*)(?<trailerkey>(?i:[a-z0-9-]+|breaking change))(?=\s*:)`,Rn=String.raw`(?<whitespace>\s+)`,zn=String.raw`(?<![\p{L}\p{N}])(?:\.NET|ASP\.NET|C\+\+|C#|F#|F\*|Next\.js|Node\.js|VB\.NET|VDM\+\+|Vite\+)(?:[-']+[\p{L}\p{N}]+)*[-']*(?![\p{L}\p{N}])`,Bn=String.raw`(?<word>${zn}|(?<=')[-']*[\p{L}\p{N}]+(?:[-']+[\p{L}\p{N}]+)*(?=')|(?!'[-']*[\p{L}\p{N}]+(?:[-']+[\p{L}\p{N}]+)*[-']*')[-']*[\p{L}\p{N}]+(?:[-']+[\p{L}\p{N}]+)*[-']*)`,Vn=new RegExp(Ln,`u`),Hn=new RegExp(J([Mn,Ln,Bn,Rn,Nn],{preserveCapturingGroups:!0}),`gu`);function Un(e){let t=An(e.issueLinks.prefixes),n=An(e.issueLinks.wildcards);if(t===``&&n===``)return``;let r=t?String.raw`[([{<]*(?:${t})\d+[)\]}>]*:?`:``;return String.raw`(?<issuelink>${J([r,n])})`}function Wn(e,t){let n=[In,Pn,jn,Mn,Fn,t.issueLink,Bn,Rn,Nn];return qn(e,new RegExp(J(n,{preserveCapturingGroups:!0}),`gu`))}function Gn(e,t){let n=[jn,Mn,t.issueLink,Bn,Rn,Nn],r=new RegExp(J(n,{preserveCapturingGroups:!0}),`gu`),i=Kn(e),a=[],o=null;for(let[t,n]of e.entries())o===null?n.startsWith("````")?(a.push([On(n)]),o="````"):n.startsWith("```")?(a.push([On(n)]),o="```"):a.push(qn(n,t<i?r:Hn)):(a.push([On(n)]),n===o&&(o=null));return a}function Kn(e){for(let t=e.length-1;t>=0;--t){let n=e[t]??``;if(n.trim()!==``&&!Vn.test(n))return t+1}return 0}function qn(e,t){let n=e.matchAll(t),r=[],i=!0,a=!0;for(let e of n){let t=e.groups??{},n=Object.entries(t).find(([,e])=>e!==void 0)??null;if(n===null)continue;let[o,s]=n,c=o,l=s;i&&=c===`revert`||c===`squash`||c===`whitespace`||c===`punctuation`&&l===`"`&&r.length>0,a&&=c===`squash`||c===`whitespace`;let u=r.at(-1);c===`revert`&&!i?r.push(W(`word`,l,e.index)):c===`squash`&&!a?r.push(...Jn(l,e.index)):c===`punctuation`&&u?.type===`punctuation`?(u.value+=l,u.range[1]+=1):r.push(W(c,l,e.index))}return r}function Jn(e,t){if(e.startsWith(`!`)){let n=e.lastIndexOf(`!`);return[W(`punctuation`,e.slice(0,n+1),t),W(`word`,e.slice(n+1),t+n+1)]}let n=e.indexOf(`!`),r=e.slice(n);return[W(`word`,e.slice(0,n),t),W(`punctuation`,r,t+n)]}function Yn(e,t){let[n=``,...r]=e.message.split(`
|
|
31
|
-
`),i={issueLink:Un(t)};return{sha:e.sha,isMergeCommit:e.parents.length>1,hasSignature:e.signature!==``,authorName:e.authorName,authorEmail:e.authorEmail,committerName:e.committerName,committerEmail:e.committerEmail,subject:Wn(n,i),bodyLines:Gn(r,i)}}function Y(e,t,n){return{location:`subject`,key:`${t}:C${n.range[0]}-${n.range[1]}:${e}`,rule:e,commitSha:t,...n}}function Xn(e,t){return t>e?[e,t]:[e,e+1]}function Zn(e,t){return[Math.min(e[0],t[0]),Math.max(e[1],t[1])]}function*Qn(e,t){let n=`noBlankSubjects`;if(t[n].level!==`off`)for(let t of e){if(t.subject.some(G(`hyperlink`,`semver`,`word`))||t.subject.some(e=>e.type===`code`&&e.value!=="``"))continue;let e=t.subject.findLastIndex(G(`issuelink`,`revert`,`squash`))+1,r=q(t.subject),i=e===-1?0:t.subject[e]?.range[0]??r;yield Y(n,t.sha,{range:Xn(i,r)})}}function $n(e,t){return{location:`commit`,key:`${t}:A:${e}`,rule:e,commitSha:t}}function*er(e,t){let n=`noExcessiveCommitsPerBranch`,r=t[n];if(r.level===`off`)return;let i=r.options.maxCommits,a=0;for(let t of e)t.isMergeCommit||t.subject.some(G(`squash`))||(a+=1,a>i&&(yield $n(n,t.sha)))}function X(e,t,n){return{location:`body-line`,key:`${t}:L${n.lineNumber}:C${n.range[0]}-${n.range[1]}:${e}`,rule:e,commitSha:t,...n}}function*tr(e,t){let n=`noExcessiveWhitespace`;if(t[n].level!==`off`)for(let t of e){let e=t.subject[0],r=t.subject.at(-1);e?.type===`whitespace`&&(yield Y(n,t.sha,{range:e.range}));for(let e of nr(t.subject))yield Y(n,t.sha,{range:e.range});r?.type===`whitespace`&&(yield Y(n,t.sha,{range:r.range}));for(let[e,r]of t.bodyLines.entries())for(let i of nr(r))yield X(n,t.sha,{lineNumber:e,range:i.range})}}function nr(e){let t=e[0],n=e.at(-1);return e.filter(G(`whitespace`)).filter(e=>e.value.length>1&&e!==t&&e!==n)}function*rr(e,t){let n=`noMergeCommits`;if(t[n].level!==`off`)for(let t of e)t.isMergeCommit&&(yield $n(n,t.sha))}function*ir(e,t){let n=`noRepeatedSubjects`;if(t[n].level===`off`)return;let r=/* @__PURE__ */ new Set;for(let t of e){if(t.subject.some(G(`revert`,`squash`)))continue;let e=t.subject.filter(K(`whitespace`)).map(e=>e.value).join(``).toLowerCase();r.has(e)&&!t.isMergeCommit&&(yield $n(n,t.sha)),r.add(e)}}function*ar(e,t){let n=`noRestrictedTrailers`,r=t[n];if(r.level===`off`)return;let i=new Set(r.options.restrictedKeys.map(or).filter(M));if(i.size!==0)for(let t of e)for(let[e,r]of t.bodyLines.entries()){let a=r.find(G(`trailerkey`))??null;a!==null&&i.has(a.value.toLowerCase())&&(yield X(n,t.sha,{lineNumber:e,range:a.range}))}}function or(e){let t=e.trim().toLowerCase();return t.endsWith(`:`)?t.slice(0,-1).trimEnd():t}function*sr(e,t){let n=`noRevertReverts`;if(t[n].level!==`off`)for(let t of e){let e=t.subject.find(G(`revert`)),r=t.subject.findLast(G(`revert`));e&&r&&e!==r&&(yield Y(n,t.sha,{range:Zn(e.range,r.range)}))}}function*cr(e,t){let n=`noSingleWordSubjects`;if(t[n].level!==`off`)for(let t of e){if(t.subject.some(G(`revert`)))continue;let e=t.subject.filter(G(`code`,`hyperlink`,`semver`,`word`)),r=e.length===1?e[0]:null;r&&(yield Y(n,t.sha,{range:r.range}))}}function*lr(e,t){let n=`noSquashMarkers`;if(t[n].level!==`off`)for(let t of e){let e=t.subject.find(G(`squash`));if(e){let r=t.subject.findLast(G(`squash`))??e;yield Y(n,t.sha,{range:Zn(e.range,r.range)})}}}const ur=/(?:\(.+\)|\[.+\]|\{.+\}|<.+>|'.+'|".+"|`.+`|«.+»|».+«|\d+[%"+!])$/u,dr=/:\w+:$/u;function*fr(e,t){let n=`noUnexpectedPunctuation`;if(t[n].level!==`off`)for(let t of e){if(t.subject.some(G(`revert`)))continue;let e=t.subject.findLastIndex(K(`issuelink`,`whitespace`)),r=t.subject[e];if(r?.type===`punctuation`){let i=t.subject.slice(0,e+1).map(e=>e.value).join(``);if(!ur.test(i)){let e=dr.exec(i),a=e===null?r.range:[e.index,e.index+e[0].length];yield Y(n,t.sha,{range:a})}}}}function pr(e,t,n){return{location:`user-identity`,key:`${t}:B:${n.field}:${e}`,rule:e,commitSha:t,...n}}function*mr(e,t){let n=`useAuthorEmailPatterns`,r=t[n];if(r.level===`off`)return;let i=r.options.patterns;if(i.length===0)return;let a=RegExp(`^${J(i)}$`,`u`),o={field:`author:email`};for(let t of e)a.test(t.authorEmail)||(yield pr(n,t.sha,o))}function*hr(e,t){let n=`useAuthorNamePatterns`,r=t[n];if(r.level===`off`)return;let i=r.options.patterns;if(i.length===0)return;let a=RegExp(`^${J(i)}$`,`u`),o={field:`author:name`};for(let t of e)a.test(t.authorName)||(yield pr(n,t.sha,o))}function*gr(e,t){let n=`useCapitalisedSubjects`;if(t[n].level!==`off`)for(let t of e){let e=t.subject.find(G(`hyperlink`,`punctuation`,`revert`,`word`));if(e&&e.type!==`hyperlink`&&_r(e)){let r=e.range[0];yield Y(n,t.sha,{range:[r,r+1]})}}}function _r(e){let t=e.value.trimStart()[0]??``;return t!==t.toUpperCase()}function*vr(e,t){let n=`useCommitterEmailPatterns`,r=t[n];if(r.level===`off`)return;let i=r.options.patterns;if(i.length===0)return;let a=RegExp(`^${J(i)}$`,`u`),o={field:`committer:email`};for(let t of e)a.test(t.committerEmail)||(yield pr(n,t.sha,o))}function*yr(e,t){let n=`useCommitterNamePatterns`,r=t[n];if(r.level===`off`)return;let i=r.options.patterns;if(i.length===0)return;let a=RegExp(`^${J(i)}$`,`u`),o={field:`committer:name`};for(let t of e)a.test(t.committerName)||(yield pr(n,t.sha,o))}function*br(e,t){let n=`useConciseSubjects`,r=t[n];if(r.level===`off`)return;let i=r.options.maxLength;for(let t of e){if(t.isMergeCommit||t.subject.some(G(`revert`,`semver`,`squash`)))continue;let e=kn(t.subject.filter(K(`code`,`hyperlink`,`issuelink`)),i);e!==null&&(yield Y(n,t.sha,{range:e}))}}function*xr(e,t){let n=`useEmptyLineBeforeBody`;if(t[n].level!==`off`){for(let t of e)for(let[e,r]of t.bodyLines.entries())if(r.some(K(`whitespace`))){e===0&&(yield X(n,t.sha,{lineNumber:0,range:[0,1]})),e>1&&(yield X(n,t.sha,{lineNumber:e-1,range:[0,1]}));break}}}function*Sr(e,t){let n=`useImperativeSubjects`,r=t[n];if(r.level===`off`)return;let i=new Set(r.options.whitelist.map(e=>e.trim().toLowerCase()).filter(M));for(let t of e){if(t.subject.some(G(`revert`)))continue;let e=t.subject.find(K(`issuelink`,`squash`,`whitespace`))??null;if(e!==null){let r=e.value.toLowerCase();(e.type!==`word`||!(i.has(r)||vn(r)))&&(yield Y(n,t.sha,{range:e.range}))}}}function*Cr(e,t){let n=`useIssueLinks`,r=t[n];if(r.level===`off`)return;let i=r.options.position;if(i===`anywhere`){for(let t of e){if(t.isMergeCommit||t.subject.some(G(`issuelink`,`revert`,`semver`)))continue;let e=t.subject.find(K(`squash`,`whitespace`))?.range[0]??q(t.subject);yield Y(n,t.sha,{range:[e,e+1]})}return}if(i===`prefix`){for(let t of e){if(t.isMergeCommit||t.subject.some(G(`revert`,`semver`)))continue;let e=t.subject.find(K(`squash`,`whitespace`));if(e?.type!==`issuelink`){let r=e?.range[0]??q(t.subject);yield Y(n,t.sha,{range:[r,r+1]})}}return}for(let t of e)if(!(t.isMergeCommit||t.subject.some(G(`revert`,`semver`)))&&t.subject.findLast(K(`whitespace`))?.type!==`issuelink`){let e=q(t.subject);yield Y(n,t.sha,{range:[e,e+1]})}}function*wr(e,t){let n=`useLineWrapping`,r=t[n];if(r.level===`off`)return;let i=r.options.maxLength;for(let t of e)if(!t.isMergeCommit)for(let[e,r]of t.bodyLines.entries()){if(r.some(G(`codeblock`,`trailerkey`)))continue;let a=kn(r.filter(K(`code`,`hyperlink`,`issuelink`)),i);a!==null&&(yield X(n,t.sha,{lineNumber:e,range:a}))}}function*Tr(e,t){let n=`useSignedCommits`;if(t[n].level!==`off`)for(let t of e)t.hasSignature||(yield $n(n,t.sha))}function Er(e,t){let n=pt([...Qn(e,t),...er(e,t),...tr(e,t),...rr(e,t),...ir(e,t),...ar(e,t),...sr(e,t),...cr(e,t),...lr(e,t),...fr(e,t),...mr(e,t),...hr(e,t),...gr(e,t),...vr(e,t),...yr(e,t),...br(e,t),...xr(e,t),...Sr(e,t),...Cr(e,t),...wr(e,t),...Tr(e,t)],e=>e.key);if(n.length===0)return[];let r=new Map(e.map((e,t)=>[e.sha,t]));return n.toSorted((e,t)=>e.commitSha===t.commitSha?e.key.localeCompare(t.key,`en`,{numeric:!0}):z(r.get(e.commitSha),()=>`Concerned commit ${e.commitSha} not found`)-z(r.get(t.commitSha),()=>`Concerned commit ${t.commitSha} not found`))}var Dr=`2.0.0-rc.
|
|
31
|
+
`),i={issueLink:Un(t)};return{sha:e.sha,isMergeCommit:e.parents.length>1,hasSignature:e.signature!==``,authorName:e.authorName,authorEmail:e.authorEmail,committerName:e.committerName,committerEmail:e.committerEmail,subject:Wn(n,i),bodyLines:Gn(r,i)}}function Y(e,t,n){return{location:`subject`,key:`${t}:C${n.range[0]}-${n.range[1]}:${e}`,rule:e,commitSha:t,...n}}function Xn(e,t){return t>e?[e,t]:[e,e+1]}function Zn(e,t){return[Math.min(e[0],t[0]),Math.max(e[1],t[1])]}function*Qn(e,t){let n=`noBlankSubjects`;if(t[n].level!==`off`)for(let t of e){if(t.subject.some(G(`hyperlink`,`semver`,`word`))||t.subject.some(e=>e.type===`code`&&e.value!=="``"))continue;let e=t.subject.findLastIndex(G(`issuelink`,`revert`,`squash`))+1,r=q(t.subject),i=e===-1?0:t.subject[e]?.range[0]??r;yield Y(n,t.sha,{range:Xn(i,r)})}}function $n(e,t){return{location:`commit`,key:`${t}:A:${e}`,rule:e,commitSha:t}}function*er(e,t){let n=`noExcessiveCommitsPerBranch`,r=t[n];if(r.level===`off`)return;let i=r.options.maxCommits,a=0;for(let t of e)t.isMergeCommit||t.subject.some(G(`squash`))||(a+=1,a>i&&(yield $n(n,t.sha)))}function X(e,t,n){return{location:`body-line`,key:`${t}:L${n.lineNumber}:C${n.range[0]}-${n.range[1]}:${e}`,rule:e,commitSha:t,...n}}function*tr(e,t){let n=`noExcessiveWhitespace`;if(t[n].level!==`off`)for(let t of e){let e=t.subject[0],r=t.subject.at(-1);e?.type===`whitespace`&&(yield Y(n,t.sha,{range:e.range}));for(let e of nr(t.subject))yield Y(n,t.sha,{range:e.range});r?.type===`whitespace`&&(yield Y(n,t.sha,{range:r.range}));for(let[e,r]of t.bodyLines.entries())for(let i of nr(r))yield X(n,t.sha,{lineNumber:e,range:i.range})}}function nr(e){let t=e[0],n=e.at(-1);return e.filter(G(`whitespace`)).filter(e=>e.value.length>1&&e!==t&&e!==n)}function*rr(e,t){let n=`noMergeCommits`;if(t[n].level!==`off`)for(let t of e)t.isMergeCommit&&(yield $n(n,t.sha))}function*ir(e,t){let n=`noRepeatedSubjects`;if(t[n].level===`off`)return;let r=/* @__PURE__ */ new Set;for(let t of e){if(t.subject.some(G(`revert`,`squash`)))continue;let e=t.subject.filter(K(`whitespace`)).map(e=>e.value).join(``).toLowerCase();r.has(e)&&!t.isMergeCommit&&(yield $n(n,t.sha)),r.add(e)}}function*ar(e,t){let n=`noRestrictedTrailers`,r=t[n];if(r.level===`off`)return;let i=new Set(r.options.restrictedKeys.map(or).filter(M));if(i.size!==0)for(let t of e)for(let[e,r]of t.bodyLines.entries()){let a=r.find(G(`trailerkey`))??null;a!==null&&i.has(a.value.toLowerCase())&&(yield X(n,t.sha,{lineNumber:e,range:a.range}))}}function or(e){let t=e.trim().toLowerCase();return t.endsWith(`:`)?t.slice(0,-1).trimEnd():t}function*sr(e,t){let n=`noRevertReverts`;if(t[n].level!==`off`)for(let t of e){let e=t.subject.find(G(`revert`)),r=t.subject.findLast(G(`revert`));e&&r&&e!==r&&(yield Y(n,t.sha,{range:Zn(e.range,r.range)}))}}function*cr(e,t){let n=`noSingleWordSubjects`;if(t[n].level!==`off`)for(let t of e){if(t.subject.some(G(`revert`)))continue;let e=t.subject.filter(G(`code`,`hyperlink`,`semver`,`word`)),r=e.length===1?e[0]:null;r&&(yield Y(n,t.sha,{range:r.range}))}}function*lr(e,t){let n=`noSquashMarkers`;if(t[n].level!==`off`)for(let t of e){let e=t.subject.find(G(`squash`));if(e){let r=t.subject.findLast(G(`squash`))??e;yield Y(n,t.sha,{range:Zn(e.range,r.range)})}}}const ur=/(?:\(.+\)|\[.+\]|\{.+\}|<.+>|'.+'|".+"|`.+`|«.+»|».+«|\d+[%"+!])$/u,dr=/:\w+:$/u;function*fr(e,t){let n=`noUnexpectedPunctuation`;if(t[n].level!==`off`)for(let t of e){if(t.subject.some(G(`revert`)))continue;let e=t.subject.findLastIndex(K(`issuelink`,`whitespace`)),r=t.subject[e];if(r?.type===`punctuation`){let i=t.subject.slice(0,e+1).map(e=>e.value).join(``);if(!ur.test(i)){let e=dr.exec(i),a=e===null?r.range:[e.index,e.index+e[0].length];yield Y(n,t.sha,{range:a})}}}}function pr(e,t,n){return{location:`user-identity`,key:`${t}:B:${n.field}:${e}`,rule:e,commitSha:t,...n}}function*mr(e,t){let n=`useAuthorEmailPatterns`,r=t[n];if(r.level===`off`)return;let i=r.options.patterns;if(i.length===0)return;let a=RegExp(`^${J(i)}$`,`u`),o={field:`author:email`};for(let t of e)a.test(t.authorEmail)||(yield pr(n,t.sha,o))}function*hr(e,t){let n=`useAuthorNamePatterns`,r=t[n];if(r.level===`off`)return;let i=r.options.patterns;if(i.length===0)return;let a=RegExp(`^${J(i)}$`,`u`),o={field:`author:name`};for(let t of e)a.test(t.authorName)||(yield pr(n,t.sha,o))}function*gr(e,t){let n=`useCapitalisedSubjects`;if(t[n].level!==`off`)for(let t of e){let e=t.subject.find(G(`hyperlink`,`punctuation`,`revert`,`word`));if(e&&e.type!==`hyperlink`&&_r(e)){let r=e.range[0];yield Y(n,t.sha,{range:[r,r+1]})}}}function _r(e){let t=e.value.trimStart()[0]??``;return t!==t.toUpperCase()}function*vr(e,t){let n=`useCommitterEmailPatterns`,r=t[n];if(r.level===`off`)return;let i=r.options.patterns;if(i.length===0)return;let a=RegExp(`^${J(i)}$`,`u`),o={field:`committer:email`};for(let t of e)a.test(t.committerEmail)||(yield pr(n,t.sha,o))}function*yr(e,t){let n=`useCommitterNamePatterns`,r=t[n];if(r.level===`off`)return;let i=r.options.patterns;if(i.length===0)return;let a=RegExp(`^${J(i)}$`,`u`),o={field:`committer:name`};for(let t of e)a.test(t.committerName)||(yield pr(n,t.sha,o))}function*br(e,t){let n=`useConciseSubjects`,r=t[n];if(r.level===`off`)return;let i=r.options.maxLength;for(let t of e){if(t.isMergeCommit||t.subject.some(G(`revert`,`semver`,`squash`)))continue;let e=kn(t.subject.filter(K(`code`,`hyperlink`,`issuelink`)),i);e!==null&&(yield Y(n,t.sha,{range:e}))}}function*xr(e,t){let n=`useEmptyLineBeforeBody`;if(t[n].level!==`off`){for(let t of e)for(let[e,r]of t.bodyLines.entries())if(r.some(K(`whitespace`))){e===0&&(yield X(n,t.sha,{lineNumber:0,range:[0,1]})),e>1&&(yield X(n,t.sha,{lineNumber:e-1,range:[0,1]}));break}}}function*Sr(e,t){let n=`useImperativeSubjects`,r=t[n];if(r.level===`off`)return;let i=new Set(r.options.whitelist.map(e=>e.trim().toLowerCase()).filter(M));for(let t of e){if(t.subject.some(G(`revert`)))continue;let e=t.subject.find(K(`issuelink`,`squash`,`whitespace`))??null;if(e!==null){let r=e.value.toLowerCase();(e.type!==`word`||!(i.has(r)||vn(r)))&&(yield Y(n,t.sha,{range:e.range}))}}}function*Cr(e,t){let n=`useIssueLinks`,r=t[n];if(r.level===`off`)return;let i=r.options.position;if(i===`anywhere`){for(let t of e){if(t.isMergeCommit||t.subject.some(G(`issuelink`,`revert`,`semver`)))continue;let e=t.subject.find(K(`squash`,`whitespace`))?.range[0]??q(t.subject);yield Y(n,t.sha,{range:[e,e+1]})}return}if(i===`prefix`){for(let t of e){if(t.isMergeCommit||t.subject.some(G(`revert`,`semver`)))continue;let e=t.subject.find(K(`squash`,`whitespace`));if(e?.type!==`issuelink`){let r=e?.range[0]??q(t.subject);yield Y(n,t.sha,{range:[r,r+1]})}}return}for(let t of e)if(!(t.isMergeCommit||t.subject.some(G(`revert`,`semver`)))&&t.subject.findLast(K(`whitespace`))?.type!==`issuelink`){let e=q(t.subject);yield Y(n,t.sha,{range:[e,e+1]})}}function*wr(e,t){let n=`useLineWrapping`,r=t[n];if(r.level===`off`)return;let i=r.options.maxLength;for(let t of e)if(!t.isMergeCommit)for(let[e,r]of t.bodyLines.entries()){if(r.some(G(`codeblock`,`trailerkey`)))continue;let a=kn(r.filter(K(`code`,`hyperlink`,`issuelink`)),i);a!==null&&(yield X(n,t.sha,{lineNumber:e,range:a}))}}function*Tr(e,t){let n=`useSignedCommits`;if(t[n].level!==`off`)for(let t of e)t.hasSignature||(yield $n(n,t.sha))}function Er(e,t){let n=pt([...Qn(e,t),...er(e,t),...tr(e,t),...rr(e,t),...ir(e,t),...ar(e,t),...sr(e,t),...cr(e,t),...lr(e,t),...fr(e,t),...mr(e,t),...hr(e,t),...gr(e,t),...vr(e,t),...yr(e,t),...br(e,t),...xr(e,t),...Sr(e,t),...Cr(e,t),...wr(e,t),...Tr(e,t)],e=>e.key);if(n.length===0)return[];let r=new Map(e.map((e,t)=>[e.sha,t]));return n.toSorted((e,t)=>e.commitSha===t.commitSha?e.key.localeCompare(t.key,`en`,{numeric:!0}):z(r.get(e.commitSha),()=>`Concerned commit ${e.commitSha} not found`)-z(r.get(t.commitSha),()=>`Concerned commit ${t.commitSha} not found`))}var Dr=`2.0.0-rc.1`;function Or(){return Dr}function kr(e){let t=`https://github.com/rainstormy/comet/blob/v${Or()}/docs/rules/${$t(e)}.md`;return le(t,`(${e})`)}function Ar(e,t,n){if(e.length===0)return``;let r=e.map(e=>Mr(e,jr(e,t),n)).join(`
|
|
32
32
|
|
|
33
33
|
`),i=new Set(e.map(({commitSha:e})=>e)).size;return`${r}\n\n${`Found ${V(e.length,`concern`,`concerns`)} in ${V(i,`commit`,`commits`)}.`}`}function jr(e,t){return z(t.find(({sha:t})=>t===e.commitSha),()=>`Concerned commit ${e.commitSha} not found`)}function Mr(e,t,n){switch(e.location){case`body-line`:return Lr(e,t,n);case`commit`:return Fr(e,t,n);case`subject`:return Ir(e,t,n);case`user-identity`:return zr(e,t,n)}}const Nr=`╭─`,Pr=`╰─`;function Fr(e,t,n){let r=qr(e,n),i=Br(t),a=Vr(t);return`${i} ${a}\n${H(C`${Nr+`─`.repeat(a.length)}`,6)}\n${Z(r,6)}`}function Ir(e,t,n){let r=Gr(e,t,n),[i,a]=e.range,o=a-i,s=7+i+1,c=Math.trunc(o/2),l=o-c-1,u=r.violation.length+2,d=u<s+c;return`${Br(t)} ${Yr(t.subject)}\n${H(Wr(e.range,d),s)}\n${d?Z(r,s+c-u,!0):Z(r,s+l)}`}function Lr(e,t,n){let r=Kr(e,n),[i,a]=e.range,o=a-i,s=Math.ceil(Math.log10(e.lineNumber+2))+3,c=H(E`· `,s),l=Math.trunc(o/2),u=o-l-1,d=r.violation.length+2,f=i+l-d,p=f>=0,m=Br(t),h=Yr(t.subject),g=Rr(t.bodyLines,e.lineNumber-1,s),_=`${H(E`╭──`,s)}\n${g}`,v=Rr(t.bodyLines,e.lineNumber,s,!0),y=`${c}${H(Wr(e.range,p),i)}`,b=p?Z(r,f,!0):Z(r,i+u),x=Rr(t.bodyLines,e.lineNumber+1,s),ee=`${x}${H(E`╰──`,s)}`;return`${m} ${h}\n${_}${v}${y}\n${tn(x===``?b.trimEnd():b,c)}\n${ee}`}function Rr(e,t,n,r=!1){let i=e[t]??null;if(i===null)return``;let a=(t+1).toString().padStart(n-3,` `),o=Yr(i);return r?`${C`•`} ${E`${S`${a}`} │`} ${o}\n`:` ${E`${a} │ ${o}`}\n`}function zr(e,t,n){let r=Jr(e,n),i=Br(t),a=Vr(t),o=Hr(e),s=Ur(e,t),c=o.length-1,l=H(C`${Nr+`─`.repeat(s.length)}`,c),u=Z(r,c);return`${i} ${a}\n${E`${o}`} ${s}\n${l}\n${u}`}function Br(e){return E`${e.sha.slice(0,7)}`}function Vr(e){return Yr(e.subject)}function Hr(e){switch(e.field){case`author:email`:case`author:name`:return`${Pr} authored by:`;case`committer:email`:case`committer:name`:return`${Pr} committed by:`}}function Ur(e,t){switch(e.field){case`author:email`:return t.authorEmail;case`author:name`:return t.authorName;case`committer:email`:return t.committerEmail;case`committer:name`:return t.committerName}}function Wr(e,t){let[n,r]=e,i=r-n;if(i===1)return C`┬`;let a=Math.trunc(i/2),o=i-a-1,s=`─`.repeat(a),c=`─`.repeat(o);return t?C`${s}┬${c}`:C`${c}┬${s}`}function Z(e,t,n=!1){let r=`${kr(e.rule)}${e.sidenote?`\n\n${e.sidenote}`:``}`;return H(n?C`${e.violation} ${`─╯`}\n${r}`:C`${Pr} ${e.violation}\n${H(r,3)}`,t)}function Gr(e,t,n){let r=e.rule;function i(e,t=``){return{rule:r,violation:e,sidenote:t}}switch(r){case`noBlankSubjects`:return i(`Include a descriptive subject.`);case`noExcessiveWhitespace`:return i(e.range[0]===0?`Delete leading whitespace.`:e.range[1]===q(t.subject)?`Delete trailing whitespace.`:`Delete excessive whitespace.`);case`noRevertReverts`:return i(`Cherry-pick the original commit instead of reverting it over.`);case`noSingleWordSubjects`:return i(`Use at least two words in the subject.`);case`noSquashMarkers`:return i(`Rebase interactively to combine this commit with its target commit.`);case`noUnexpectedPunctuation`:return i(`Remove trailing punctuation.`);case`useCapitalisedSubjects`:return i(`Change the first letter to uppercase.`);case`useConciseSubjects`:return i(`Shorten the subject to ${V(Q(r,n).maxLength,`character`,`characters or less`)}.`);case`useImperativeSubjects`:return i(`Start the subject with a verb in the imperative mood.`);case`useIssueLinks`:{let e=Q(r,n),t=e.position===`prefix`?`Start the subject with an issue link.`:e.position===`suffix`?`End the subject with an issue link.`:`Include an issue link in the subject.`,a=n.tokens.issueLinks.prefixes,o=n.tokens.issueLinks.wildcards,s=[...a.map(e=>`${e}123`),...o],c=U(s.length,`Example`);return i(t,s.length>0?`${c}: ${s.join(`, `)}`:``)}}}function Kr(e,t){let n=e.rule;function r(e,t=``){return{rule:n,violation:e,sidenote:t}}switch(n){case`noExcessiveWhitespace`:return r(`Delete excessive whitespace.`);case`noRestrictedTrailers`:return r(`Delete disallowed trailers.`,$(`Disallowed trailers:`,[...Q(n,t).restrictedKeys].map(e=>$t(or(e))).filter(M).toSorted(lt),`
|
|
34
34
|
`));case`useEmptyLineBeforeBody`:return r(`Separate the subject and message body with one blank line.`);case`useLineWrapping`:return r(`Wrap message body lines at ${V(Q(n,t).maxLength,`character`,`characters or less`)}.`)}}function qr(e,t){let n=e.rule;function r(e,t=``){return{rule:n,violation:e,sidenote:t}}switch(n){case`noExcessiveCommitsPerBranch`:{let e=Q(n,t);return r(e.maxCommits>1?`Split the branch or reduce it to ${e.maxCommits} commits or fewer.`:`Reduce the branch to 1 commit.`)}case`noMergeCommits`:return r(`Rebase the branch and drop the merge commits.`);case`noRepeatedSubjects`:return r(`Use a unique subject.`);case`useSignedCommits`:return r(`Sign this commit cryptographically with your signing key.`)}}function Jr(e,t){let n=e.rule;function r(e,t=``){return{rule:n,violation:e,sidenote:t}}switch(n){case`useAuthorEmailPatterns`:return r(`Use an author email address that matches an accepted pattern.`,$(`Accepted patterns:`,Q(n,t).patterns));case`useAuthorNamePatterns`:return r(`Use an author name that matches an accepted pattern.`,$(`Accepted patterns:`,Q(n,t).patterns));case`useCommitterEmailPatterns`:return r(`Use a committer email address that matches an accepted pattern.`,$(`Accepted patterns:`,Q(n,t).patterns));case`useCommitterNamePatterns`:return r(`Use a committer name that matches an accepted pattern.`,$(`Accepted patterns:`,Q(n,t).patterns))}}function Q(e,t){return t.rules[e].options}function Yr(e){return e.map(e=>e.value).join(``)}function $(e,t,n=``){return t.length>0?`${e}${t.map(e=>`\n ∙ ${e}`).join(``)}${n}`:``}function Xr(e){console.log(e)}function Zr(e){console.error(C`${e}`)}function Qr(e){console.warn(ge`${e}`)}async function $r(e,t){let n=e.map(e=>Yn(e,t.tokens)),r=Er(n,t.rules);return r.length>0?(Xr(Ar(r,n,t)),40):0}function ei(e,t){let n={},r=null;for(let e of t)e.startsWith(`-`)?(r=e,n[r]??=[]):r!==null&&n[r]?.push(e);return ti(e,n),ni(e,n),ri(e,n),ii(e,n),ai(e,n),n}function ti(e,t){for(let n of Object.keys(t))if(!(n in e))throw TypeError(`Unknown option '${n}'`)}function ni(e,t){let n=Object.entries(e);for(let[e,{required:r}]of n)if(r&&!(e in t))throw TypeError(`${e} is required`)}function ri(e,t){let n=Object.entries(e);for(let[e,{args:r}]of n){let n=t[e];if(n!==void 0){let t=r.min??null,i=r.max??null,a=n.length;if(t!==null&&t===i&&a!==t){let n=`exactly ${t} ${U(t,`argument`)}`;throw TypeError(`'${e}' requires ${n}, but got ${a}`)}}}}function ii(e,t){let n=Object.entries(e);for(let[e,{args:r}]of n){let n=t[e];if(n!==void 0){let t=r.min??null,i=n.length;if(t!==null&&i<t){let n=`at least ${t} ${U(t,`argument`)}`;throw TypeError(`'${e}' requires ${n}, but got ${i}`)}}}}function ai(e,t){let n=Object.entries(e);for(let[e,{args:r}]of n){let n=t[e];if(n!==void 0){let t=r.max??null,i=n.length;if(t!==null&&i>t){let n=`at most ${t} ${U(t,`argument`)}`;throw TypeError(`'${e}' requires ${n}, but got ${i}`)}}}}function oi(e){return e}const si=oi({"--config":{args:{min:1}},"--default-branch":{args:{min:1,max:1}},"--skip-missing-configs":{args:{min:0,max:0}}});async function ci(e){if(e.includes(`--help`)||e.includes(`-h`))return Xr(li()),0;if(e.includes(`--version`)||e.includes(`-v`))return Xr(Or()),0;try{let t=ei(si,e),n=await ui(t[`--config`]??[],t[`--skip-missing-configs`]!==void 0);return await $r(await Ot(t[`--default-branch`]?.[0]??n.git.defaultBranch),n)}catch(e){return Ut(e),Zr(e.message),e instanceof TypeError?2:1}}function li(){return`${S`Usage:`} comet [options]
|
|
@@ -48,7 +48,7 @@ Use the official JSON schema to validate the configuration file and to enable
|
|
|
48
48
|
code completion, for example:
|
|
49
49
|
|
|
50
50
|
${E`{
|
|
51
|
-
"$schema": "
|
|
51
|
+
"$schema": "https://unpkg.com/@rainstormy/comet@${Or()}/schema.json",
|
|
52
52
|
"rules": {
|
|
53
53
|
"noMergeCommits": "error",
|
|
54
54
|
"noSquashCommits": "error",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@rainstormy/comet",
|
|
4
|
-
"version": "2.0.0-rc.
|
|
4
|
+
"version": "2.0.0-rc.1",
|
|
5
5
|
"description": "A linter to ensure that Git commit messages conform to certain standards and conventions declared by a customisable set of rules.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"actions",
|