@rainstormy/comet 2.0.0-beta.0

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/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Rainstorm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # Comet ☄️
2
+
3
+ A linter to ensure that Git commit messages conform to certain standards and conventions declared by a customisable set of rules.
4
+
5
+ > [!CAUTION]
6
+ > Comet v2 is currently in development with an expected release later in 2026.
7
+
8
+ ## Command-Line Interface (CLI)
9
+ ### Installation
10
+ Install [`@rainstormy/comet`](https://www.npmjs.com/package/@rainstormy/comet)
11
+ with a package manager of your choice, for example:
12
+
13
+ ```shell
14
+ pnpm add --save-dev @rainstormy/comet
15
+ ```
16
+
17
+ ### Usage
18
+ <mark>TODO</mark>
19
+
20
+ ## GitHub Actions
21
+ ### Usage
22
+ <mark>TODO</mark>
23
+
24
+ ## Rules
25
+ | Key | Description |
26
+ |-----------------------------------|-------------------|
27
+ | [`noBlankSubjectLines`]() | <mark>TODO</mark> |
28
+ | [`noExcessiveCommitsPerBranch`]() | <mark>TODO</mark> |
29
+ | [`noExcessiveWhitespace`]() | <mark>TODO</mark> |
30
+ | [`noMergeCommits`]() | <mark>TODO</mark> |
31
+ | [`noRepeatedSubjectLines`]() | <mark>TODO</mark> |
32
+ | [`noRestrictedTrailers`]() | <mark>TODO</mark> |
33
+ | [`noRevertRevertCommits`]() | <mark>TODO</mark> |
34
+ | [`noSingleWordSubjectLines`]() | <mark>TODO</mark> |
35
+ | [`noSquashMarkers`]() | <mark>TODO</mark> |
36
+ | [`noUnexpectedPunctuation`]() | <mark>TODO</mark> |
37
+ | [`useAuthorEmailPatterns`]() | <mark>TODO</mark> |
38
+ | [`useAuthorNamePatterns`]() | <mark>TODO</mark> |
39
+ | [`useCapitalisedSubjectLines`]() | <mark>TODO</mark> |
40
+ | [`useCommitterEmailPatterns`]() | <mark>TODO</mark> |
41
+ | [`useCommitterNamePatterns`]() | <mark>TODO</mark> |
42
+ | [`useConciseSubjectLines`]() | <mark>TODO</mark> |
43
+ | [`useEmptyLineBeforeBodyLines`]() | <mark>TODO</mark> |
44
+ | [`useImperativeSubjectLines`]() | <mark>TODO</mark> |
45
+ | [`useIssueLinks`]() | <mark>TODO</mark> |
46
+ | [`useLineWrapping`]() | <mark>TODO</mark> |
47
+ | [`useSignedCommits`]() | <mark>TODO</mark> |
48
+
49
+ ## Configuration
50
+ <mark>TODO</mark>
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import e,{argv as t}from"node:process";import*as n from"valibot";import{spawn as r}from"node:child_process";import{access as i,constants as a,readFile as o}from"node:fs/promises";import{dirname as s,isAbsolute as c,normalize as l,relative as u,resolve as d}from"node:path";import{bold as f,gray as p,red as m}from"ansis";function ee(e){return e!=null}function te(e){let[,t]=e;return t!=null}function h(e){return e!==``}function ne(e){return e.length>0}const g=(e,t)=>e.localeCompare(t,`en`);function re(e,t){let n=e[Symbol.iterator](),r=n.next().value;for(let e of n)t(e,r)<0&&(r=e);return r}function _(e,t){function n(r,i){let a=Math.floor((r+i)/2),o=t.localeCompare(e[a]??``,`en`);return o===0?a:r>=i?-1:o<0?n(r,a-1):n(a+1,i)}return n(0,e.length-1)}function v(e){return[...new Set(e)]}function ie(e,t){let n=new Set;return e.filter(e=>{let r=t(e);return!n.has(r)&&(n.add(r),!0)})}var y=class extends Error{exitCode;constructor(e){super([`Command 'git ${e.args.join(` `)}' failed`,e.exitCode===0?``:` with exit code ${e.exitCode}`,e.stderr===void 0?``:`:\n\n${e.stderr.trim()}`].join(``),{cause:e.cause}),this.name=`GitCommandError`,this.exitCode=e.exitCode}};async function b(e){return new Promise((t,n)=>{let i=``,a=``,o=r(`git`,e);o.stdout.on(`data`,e=>{i+=e.toString()}),o.stderr.on(`data`,e=>{a+=e.toString()}),o.on(`close`,r=>{r===0?t(i.trim()):n(new y({args:e,exitCode:r??-1,stderr:a}))}),o.on(`error`,t=>{n(new y({args:e,exitCode:-1,cause:t}))})})}async function ae(){return(await b([`remote`])).split(`
3
+ `).filter(h)}async function oe(){let e=await se();if(e!==null){let t=await b([`rev-parse`,`--abbrev-ref`,`${e}/HEAD`]);if(t)return t}return ce()}async function se(){let e=await ae();return ne(e)?e.includes(`origin`)?`origin`:re(e,g):null}async function ce(){return await le(`main`)?`main`:await le(`master`)?`master`:null}async function le(e){try{return await b([`rev-parse`,`--verify`,`--quiet`,e]),!0}catch(e){if(e instanceof y&&e.exitCode!==0)return!1;throw e}}async function ue(e,t){let n=`${e}..${t}`,r=await b([`--no-pager`,`log`,`--format=raw`,`--no-color`,n]);if(r===``)return[];let[i,...a]=r.split(`
4
+ `);return me(i,n),de(i,a)}function de(e,t){let n=[],r=fe(e.slice(7)),i=r.commit;function a(e){n.push(pe(e))}function o(e){i[i.length-1]+=`${e}\n`}for(let e of t)if(e.startsWith(`commit `))a(r),r=fe(e.slice(7)),i=r.commit;else if(e.startsWith(` `))i=r.message,o(e.slice(4));else if(e.startsWith(` `))o(e.slice(1));else if(e.includes(` `)){let t=e.indexOf(` `),n=e.slice(0,t),a=`${e.slice(t+1)}\n`;r[n]===void 0?r[n]=[a]:r[n].push(a),i=r[n]}else o(``);return a(r),n}function fe(e){return{author:[],commit:[`${e}\n`],committer:[],gpgsig:[],message:[``],parent:[]}}function pe(e){return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,t.map(e=>e.endsWith(`
5
+
6
+ `)?e.slice(0,-2):e.slice(0,-1))]))}function me(e,t){if(e===void 0||!e.startsWith(`commit `))throw Error(`Unexpected line in the Git log of ${t}: ${e}`)}async function he(){let e=await oe();if(e===null)throw Error(`Expected a default remote branch (e.g. 'origin/main') or a local branch named 'main' or 'master'`);return(await ue(e,`HEAD`)).map(ge).toReversed()}function ge(e){let[t,n]=_e(e.author.at(0)),[r,i]=_e(e.committer.at(0));return{sha:e.commit[0],parents:e.parent,authorName:t,authorEmail:n,committerName:r,committerEmail:i,message:e.message[0],signature:e.gpgsig[0]??``}}function _e(e){if(e===void 0)return[``,``];let t=e.lastIndexOf(` `),n=e.lastIndexOf(` `,t-1);if(n===-1)return[``,``];let r=e.slice(0,n),i=r.lastIndexOf(`<`),a=r.lastIndexOf(`>`);if(i!==-1&&a>i){let e=r.slice(0,i),t=r.slice(i+1,a);return[i>0?ve(e):``,t]}return[ve(r),``]}function ve(e){return e.endsWith(` `)?e.slice(0,-1):e}const ye={noBlankSubjectLines:{level:`error`,options:{}},noExcessiveCommitsPerBranch:{level:`error`,options:{maxCommits:10}},noExcessiveWhitespace:{level:`error`,options:{}},noMergeCommits:{level:`error`,options:{}},noRepeatedSubjectLines:{level:`error`,options:{}},noRestrictedTrailers:{level:`error`,options:{restrictedKeys:[]}},noRevertRevertCommits:{level:`error`,options:{}},noSingleWordSubjectLines:{level:`error`,options:{}},noSquashMarkers:{level:`error`,options:{}},noUnexpectedPunctuation:{level:`error`,options:{}},useAuthorEmailPatterns:{level:`error`,options:{patterns:[]}},useAuthorNamePatterns:{level:`error`,options:{patterns:[]}},useCapitalisedSubjectLines:{level:`error`,options:{}},useCommitterEmailPatterns:{level:`error`,options:{patterns:[]}},useCommitterNamePatterns:{level:`error`,options:{patterns:[]}},useConciseSubjectLines:{level:`error`,options:{maxLength:50}},useEmptyLineBeforeBodyLines:{level:`error`,options:{}},useImperativeSubjectLines:{level:`error`,options:{whitelist:[]}},useIssueLinks:{level:`error`,options:{position:`anywhere`}},useLineWrapping:{level:`error`,options:{maxLength:72}},useSignedCommits:{level:`error`,options:{}}};function x(e,t){let n={...e};for(let e in t)if(Object.hasOwn(t,e)&&t[e]!==void 0){let r=n[e],i=t[e];n[e]=Array.isArray(r)&&Array.isArray(i)?[...r,...i]:be(r)&&be(i)?x(r,i):i}return n}function be(e){return typeof e==`object`&&!!e}const xe={tokens:{issueLinks:{prefixes:[],wildcards:[]}},rules:x(ye,{noRepeatedSubjectLines:{level:`off`},noRestrictedTrailers:{level:`off`},noRevertRevertCommits:{level:`off`},noSquashMarkers:{level:`off`},useAuthorEmailPatterns:{level:`off`},useAuthorNamePatterns:{level:`off`},useCommitterEmailPatterns:{level:`off`},useCommitterNamePatterns:{level:`off`},useIssueLinks:{level:`off`}})};function S(e){let t=e?.minValue===0?`a non-negative integer`:`a positive integer`;return n.pipe(n.number(t),n.integer(t),n.minValue(e?.minValue??1,t))}function C(){let e=`an array of strings`;return n.array(n.string(e),e)}const Se=n.picklist([`error`,`off`],`'error' or 'off'`),w=T({}),Ce=n.strictObject({noBlankSubjectLines:w,noExcessiveCommitsPerBranch:T({maxCommits:S()}),noExcessiveWhitespace:w,noMergeCommits:w,noRepeatedSubjectLines:w,noRestrictedTrailers:T({restrictedKeys:C()}),noRevertRevertCommits:w,noSingleWordSubjectLines:w,noSquashMarkers:w,noUnexpectedPunctuation:w,useAuthorEmailPatterns:T({patterns:C()}),useAuthorNamePatterns:T({patterns:C()}),useCapitalisedSubjectLines:w,useCommitterEmailPatterns:T({patterns:C()}),useCommitterNamePatterns:T({patterns:C()}),useConciseSubjectLines:T({maxLength:S()}),useEmptyLineBeforeBodyLines:w,useImperativeSubjectLines:T({whitelist:C()}),useIssueLinks:T({position:n.picklist([`anywhere`,`prefix`,`suffix`],`'anywhere', 'prefix', or 'suffix'`)}),useLineWrapping:T({maxLength:S()}),useSignedCommits:w});function T(e){return n.strictObject({level:Se,options:n.strictObject(e)})}const we=n.strictObject({issueLinks:n.exactOptional(n.strictObject({prefixes:n.exactOptional(C()),wildcards:n.exactOptional(C())}))}),Te=n.strictObject(Object.fromEntries(Object.entries(Ce.entries).map(([e,t])=>[e,n.exactOptional(n.union([Se,t],`'error', 'off', or an object of 'level' and 'options'`))]))),Ee=n.strictObject({$schema:n.exactOptional(n.unknown()),extends:n.exactOptional(n.string()),rules:n.exactOptional(Te),tokens:n.exactOptional(we)});function E(e,t){return De(e,t),e}function De(e,t=e=>`Expected a not-nullish value, but got ${e}`){if(e==null)throw Error(t(e))}function Oe(e){if(!(e instanceof Error))throw e}async function ke(e){try{return await i(e,a.R_OK),!0}catch{return!1}}function Ae(t,n){if(c(t))return l(t);let r=n===void 0?t:d(s(n),t);return l(u(e.cwd(),r))}async function je(e){try{let t=await o(e,`utf8`);return JSON.parse(t)}catch(t){throw t instanceof SyntaxError?TypeError(`Failed to parse '${e}' as JSON: ${t.message}`,{cause:t}):(Oe(t),Error(`Failed to read '${e}': ${t.message}`,{cause:t}))}}function Me(e){return e.charAt(0).toUpperCase()+e.slice(1)}function Ne(e){return e.replaceAll(/\s+/gu,` `)}function D(e,t,n){return`${e} ${e===1?t:n}`}function O(e,t){return Pe(e,` `.repeat(t))}function k(e,t,n){return e===1?t:n??`${t}s`}function Pe(e,t){return t+e.replaceAll(`
7
+ `,`\n${t}`)}function Fe(e,t){return e.length<=t?e:`${e.slice(0,t)}…`}function Ie(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=Ie(r),i={issue:e.issue,path:[...t.path,...e.path]};n===t&&i.path.length>t.path.length&&(n=i)}return n}async function Le(e){let t=await je(e);try{return n.parse(Ee,t)}catch(t){throw t instanceof n.ValiError?TypeError(`Failed to parse '${e}' as a Comet configuration: ${Re(t.issues[0])}`,{cause:t}):t}}function Re(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`:Ge(t)}`;let{issue:n,path:r}=Ie(e);return n.expected===`never`?ze(r):n.input===void 0?Be(r):`${Ve(r)} ${He(n)}, but it ${We(r)?`contains`:`is`} ${Ge(n.input)}`}function ze(e){let t=A(e),n=E(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=j(t).at(-2)??``;return`'${n}' is not a valid option${r?` of '${r}'`:``}`}function Be(e){let t=A(e),n=E(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=j(t).at(-2)??``;return e?`'${n}' of '${e}' is missing`:`'${n}' is missing`}return`'${n}' is missing in '${r}'`}function Ve(e){let t=j(A(e));We(e)&&t.pop();let n=E(t.at(-1),()=>`Unnamed configuration property: ${JSON.stringify(e)}`),r=t.at(-2)??``;return r?`'${n}' of '${r}'`:`'${n}'`}function A(e){return e.map(e=>e.key).filter(ee).map(String)}function j(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 He(e){return`must be ${Ue(e)}`}function Ue(e){if(!e.message.startsWith(`Invalid `))return e.message;let t=E(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 We(e){return e.at(-1)?.type===`array`}function Ge(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: ${Ke(e)}`:`an object: ${Ke(e)}`;case`string`:return`a string: ${Fe(e,30)}`;case`bigint`:case`function`:case`symbol`:case`undefined`:return`an unexpected type: ${typeof e}`}}function Ke(e){return Fe(Ne(JSON.stringify(e,void 0,` `)),30)}async function qe(e){let t=[],n=Ae(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 Le(n);r=x({tokens:Je(e.tokens),rules:Ye(e.rules)},r),n=e.extends===void 0?null:Ae(e.extends,n)}return Xe(r)}function Je(e){return e?.issueLinks===void 0?{}:{issueLinks:{prefixes:e.issueLinks.prefixes??[],wildcards:e.issueLinks.wildcards??[]}}}function Ye(e){return e===void 0?{}:Object.fromEntries(Object.entries(e).filter(te).map(([e,t])=>[e,typeof t==`string`?{level:t}:t]))}function Xe(e){let t=e.tokens?.issueLinks??null;return t===null?e:{...e,tokens:{issueLinks:{prefixes:v(t.prefixes??[]),wildcards:v(t.wildcards??[])}}}}async function Ze(e){return e??await Qe()}async function Qe(){return await ke(`comet.json`)?`comet.json`:null}function M(e,t=0){return N(`codeblock`,e,t)}function N(e,t,n=0){return{type:e,value:t,range:[n,n+t.length]}}function P(...e){return t=>e.includes(t.type)}function F(...e){return t=>!e.includes(t.type)}function I(e){return e.at(-1)?.range[1]??0}function $e(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 et(e){return e.filter(h).map(e=>RegExp.escape(e)).join(`|`)}function L(e,t={}){let n=t.preserveCapturingGroups??!1,r=e.filter(h);return n?r.join(`|`):r.map(e=>`(?:${e})`).join(`|`)}const tt=String.raw`(?<code>${"`"}[^${"`"}]*${"`"})`,R=String.raw`(?<hyperlink>(?:https://|mailto:|ssh://)\S*[^\s.,!?"')\]}])`,z=String.raw`(?<punctuation>[\p{P}\p{S}])`,nt=String.raw`(?<revert>(?i:revert))(?=\s*")`,rt=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,]|"|$)`,it=String.raw`(?<squash>(?i:amend!+|fixup!+|squash!+|!+amend\b|!+fixup\b|!+squash\b))`,at=String.raw`(?<=^\s*)(?<trailerkey>(?i:[a-z0-9-]+|breaking change))(?=\s*:)`,B=String.raw`(?<whitespace>\s+)`,ot=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}])`,V=String.raw`(?<word>${ot}|(?<=')[-']*[\p{L}\p{N}]+(?:[-']+[\p{L}\p{N}]+)*(?=')|(?!'[-']*[\p{L}\p{N}]+(?:[-']+[\p{L}\p{N}]+)*[-']*')[-']*[\p{L}\p{N}]+(?:[-']+[\p{L}\p{N}]+)*[-']*)`,st=new RegExp(at,`u`),ct=new RegExp(L([R,at,V,B,z],{preserveCapturingGroups:!0}),`gu`);function lt(e){let t=et(e.issueLinks.prefixes),n=et(e.issueLinks.wildcards);if(t===``&&n===``)return``;let r=t?String.raw`[([{<]*(?:${t})\d+[)\]}>]*:?`:``;return String.raw`(?<issuelink>${L([r,n])})`}function ut(e,t){let n=[it,nt,tt,R,rt,t.issueLink,V,B,z];return pt(e,new RegExp(L(n,{preserveCapturingGroups:!0}),`gu`))}function dt(e,t){let n=[tt,R,t.issueLink,V,B,z],r=new RegExp(L(n,{preserveCapturingGroups:!0}),`gu`),i=ft(e),a=[],o=null;for(let[t,n]of e.entries())o===null?n.startsWith("````")?(a.push([M(n)]),o="````"):n.startsWith("```")?(a.push([M(n)]),o="```"):a.push(pt(n,t<i?r:ct)):(a.push([M(n)]),n===o&&(o=null));return a}function ft(e){for(let t=e.length-1;t>=0;--t){let n=e[t]??``;if(n.trim()!==``&&!st.test(n))return t+1}return 0}function pt(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(N(`word`,l,e.index)):c===`squash`&&!a?r.push(...mt(l,e.index)):c===`punctuation`&&u?.type===`punctuation`?(u.value+=l,u.range[1]+=1):r.push(N(c,l,e.index))}return r}function mt(e,t){if(e.startsWith(`!`)){let n=e.lastIndexOf(`!`);return[N(`punctuation`,e.slice(0,n+1),t),N(`word`,e.slice(n+1),t+n+1)]}let n=e.indexOf(`!`),r=e.slice(n);return[N(`word`,e.slice(0,n),t),N(`punctuation`,r,t+n)]}function ht(e,t){let[n=``,...r]=e.message.split(`
8
+ `),i={issueLink:lt(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,subjectLine:ut(n,i),bodyLines:dt(r,i)}}function H(e,t,n){return{location:`subject-line`,key:`${t}:C${n.range[0]}-${n.range[1]}:${e}`,rule:e,commitSha:t,...n}}function gt(e,t){return t>e?[e,t]:[e,e+1]}function _t(e,t){return[Math.min(e[0],t[0]),Math.max(e[1],t[1])]}function*vt(e,t){let n=`noBlankSubjectLines`;if(t[n].level!==`off`)for(let t of e){if(t.subjectLine.some(P(`hyperlink`,`semver`,`word`))||t.subjectLine.some(e=>e.type===`code`&&e.value!=="``"))continue;let e=t.subjectLine.findLastIndex(P(`issuelink`,`revert`,`squash`))+1,r=I(t.subjectLine),i=e===-1?0:t.subjectLine[e]?.range[0]??r;yield H(n,t.sha,{range:gt(i,r)})}}function U(e,t){return{location:`commit`,key:`${t}:A:${e}`,rule:e,commitSha:t}}function*yt(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.subjectLine.some(P(`squash`))||(a+=1,a>i&&(yield U(n,t.sha)))}function W(e,t,n){return{location:`body-line`,key:`${t}:L${n.line}:C${n.range[0]}-${n.range[1]}:${e}`,rule:e,commitSha:t,...n}}function*bt(e,t){let n=`noExcessiveWhitespace`;if(t[n].level!==`off`)for(let t of e){let e=t.subjectLine[0],r=t.subjectLine.at(-1);e?.type===`whitespace`&&(yield H(n,t.sha,{range:e.range}));for(let e of xt(t.subjectLine))yield H(n,t.sha,{range:e.range});r?.type===`whitespace`&&(yield H(n,t.sha,{range:r.range}));for(let[e,r]of t.bodyLines.entries())for(let i of xt(r))yield W(n,t.sha,{line:e,range:i.range})}}function xt(e){let t=e[0],n=e.at(-1);return e.filter(P(`whitespace`)).filter(e=>e.value.length>1&&e!==t&&e!==n)}function*St(e,t){let n=`noMergeCommits`;if(t[n].level!==`off`)for(let t of e)t.isMergeCommit&&(yield U(n,t.sha))}function*Ct(e,t){let n=`noRepeatedSubjectLines`;if(t[n].level===`off`)return;let r=new Set;for(let t of e){if(t.subjectLine.some(P(`revert`,`squash`)))continue;let e=t.subjectLine.filter(F(`whitespace`)).map(e=>e.value).join(``).toLowerCase();r.has(e)&&!t.isMergeCommit&&(yield U(n,t.sha)),r.add(e)}}function*wt(e,t){let n=`noRestrictedTrailers`,r=t[n];if(r.level===`off`)return;let i=new Set(r.options.restrictedKeys.map(Tt).filter(h));if(i.size!==0)for(let t of e)for(let[e,r]of t.bodyLines.entries()){let a=r.find(P(`trailerkey`))??null;a!==null&&i.has(a.value.toLowerCase())&&(yield W(n,t.sha,{line:e,range:a.range}))}}function Tt(e){let t=e.trim().toLowerCase();return t.endsWith(`:`)?t.slice(0,-1).trimEnd():t}function*Et(e,t){let n=`noRevertRevertCommits`;if(t[n].level!==`off`)for(let t of e){let e=t.subjectLine.find(P(`revert`)),r=t.subjectLine.findLast(P(`revert`));e&&r&&e!==r&&(yield H(n,t.sha,{range:_t(e.range,r.range)}))}}function*Dt(e,t){let n=`noSingleWordSubjectLines`;if(t[n].level!==`off`)for(let t of e){if(t.subjectLine.some(P(`revert`)))continue;let e=t.subjectLine.filter(P(`code`,`hyperlink`,`semver`,`word`)),r=e.length===1?e[0]:null;r&&(yield H(n,t.sha,{range:r.range}))}}function*Ot(e,t){let n=`noSquashMarkers`;if(t[n].level!==`off`)for(let t of e){let e=t.subjectLine.find(P(`squash`));if(e){let r=t.subjectLine.findLast(P(`squash`))??e;yield H(n,t.sha,{range:_t(e.range,r.range)})}}}const kt=/(?:\(.+\)|\[.+\]|\{.+\}|<.+>|'.+'|".+"|`.+`|«.+»|».+«|\d+[%"+!])$/u,At=/:\w+:$/u;function*jt(e,t){let n=`noUnexpectedPunctuation`;if(t[n].level!==`off`)for(let t of e){if(t.subjectLine.some(P(`revert`)))continue;let e=t.subjectLine.findLastIndex(F(`issuelink`,`whitespace`)),r=t.subjectLine[e];if(r?.type===`punctuation`){let i=t.subjectLine.slice(0,e+1).map(e=>e.value).join(``);if(!kt.test(i)){let e=At.exec(i),a=e===null?r.range:[e.index,e.index+e[0].length];yield H(n,t.sha,{range:a})}}}}function G(e,t,n){return{location:`user-identity`,key:`${t}:B:${n.field}:${e}`,rule:e,commitSha:t,...n}}function*Mt(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(`^${L(i)}$`,`u`),o={field:`author:email`};for(let t of e)a.test(t.authorEmail)||(yield G(n,t.sha,o))}function*Nt(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(`^${L(i)}$`,`u`),o={field:`author:name`};for(let t of e)a.test(t.authorName)||(yield G(n,t.sha,o))}function*Pt(e,t){let n=`useCapitalisedSubjectLines`;if(t[n].level!==`off`)for(let t of e){let e=t.subjectLine.find(P(`hyperlink`,`punctuation`,`revert`,`word`));if(e&&e.type!==`hyperlink`&&Ft(e)){let r=e.range[0];yield H(n,t.sha,{range:[r,r+1]})}}}function Ft(e){let t=e.value.trimStart()[0]??``;return t!==t.toUpperCase()}function*It(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(`^${L(i)}$`,`u`),o={field:`committer:email`};for(let t of e)a.test(t.committerEmail)||(yield G(n,t.sha,o))}function*Lt(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(`^${L(i)}$`,`u`),o={field:`committer:name`};for(let t of e)a.test(t.committerName)||(yield G(n,t.sha,o))}function*Rt(e,t){let n=`useConciseSubjectLines`,r=t[n];if(r.level===`off`)return;let i=r.options.maxLength;for(let t of e){if(t.isMergeCommit||t.subjectLine.some(P(`revert`,`semver`,`squash`)))continue;let e=$e(t.subjectLine.filter(F(`code`,`hyperlink`,`issuelink`)),i);e!==null&&(yield H(n,t.sha,{range:e}))}}function*zt(e,t){let n=`useEmptyLineBeforeBodyLines`;if(t[n].level!==`off`){for(let t of e)for(let[e,r]of t.bodyLines.entries())if(r.some(F(`whitespace`))){e===0&&(yield W(n,t.sha,{line:0,range:[0,1]})),e>1&&(yield W(n,t.sha,{line:e-1,range:[0,1]}));break}}}const Bt=`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.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.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.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.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.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.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 Vt(e){return _(Bt,e)!==-1}function*Ht(e,t){let n=`useImperativeSubjectLines`,r=t[n];if(r.level===`off`)return;let i=new Set(r.options.whitelist.map(e=>e.trim().toLowerCase()).filter(h));for(let t of e){if(t.subjectLine.some(P(`revert`)))continue;let e=t.subjectLine.find(F(`issuelink`,`squash`,`whitespace`))??null;if(e!==null){let r=e.value.toLowerCase();(e.type!==`word`||!(i.has(r)||Vt(r)))&&(yield H(n,t.sha,{range:e.range}))}}}function*Ut(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.subjectLine.some(P(`issuelink`,`revert`,`semver`)))continue;let e=t.subjectLine.find(F(`squash`,`whitespace`))?.range[0]??I(t.subjectLine);yield H(n,t.sha,{range:[e,e+1]})}return}if(i===`prefix`){for(let t of e){if(t.isMergeCommit||t.subjectLine.some(P(`revert`,`semver`)))continue;let e=t.subjectLine.find(F(`squash`,`whitespace`));if(e?.type!==`issuelink`){let r=e?.range[0]??I(t.subjectLine);yield H(n,t.sha,{range:[r,r+1]})}}return}for(let t of e)if(!(t.isMergeCommit||t.subjectLine.some(P(`revert`,`semver`)))&&t.subjectLine.findLast(F(`whitespace`))?.type!==`issuelink`){let e=I(t.subjectLine);yield H(n,t.sha,{range:[e,e+1]})}}function*Wt(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(P(`codeblock`,`trailerkey`)))continue;let a=$e(r.filter(F(`code`,`hyperlink`,`issuelink`)),i);a!==null&&(yield W(n,t.sha,{line:e,range:a}))}}function*Gt(e,t){let n=`useSignedCommits`;if(t[n].level!==`off`)for(let t of e)t.hasSignature||(yield U(n,t.sha))}function Kt(e,t){let n=ie([...vt(e,t),...yt(e,t),...bt(e,t),...St(e,t),...Ct(e,t),...wt(e,t),...Et(e,t),...Dt(e,t),...Ot(e,t),...jt(e,t),...Mt(e,t),...Nt(e,t),...Pt(e,t),...It(e,t),...Lt(e,t),...Rt(e,t),...zt(e,t),...Ht(e,t),...Ut(e,t),...Wt(e,t),...Gt(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}):E(r.get(e.commitSha),()=>`Concerned commit ${e.commitSha} not found`)-E(r.get(t.commitSha),()=>`Concerned commit ${t.commitSha} not found`))}function qt(e,t,n){return e.map(e=>Yt(e,Jt(e,t),n)).join(`
9
+
10
+ `)}function Jt(e,t){return E(t.find(({sha:t})=>t===e.commitSha),()=>`Concerned commit ${e.commitSha} not found`)}function Yt(e,t,n){switch(e.location){case`body-line`:return $t(e,t,n);case`commit`:return Zt(e,t,n);case`subject-line`:return Qt(e,t,n);case`user-identity`:return en(e,t,n)}}const Xt=`╭─`,K=`╰─`;function Zt(e,t,n){let r=cn(e,n),i=J(t),a=tn(t);return`${i} ${a}\n${O(m`${Xt+`─`.repeat(a.length)}`,6)}\n${Y(r,6)}`}function Qt(e,t,n){let r=on(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`${J(t)} ${Z(t.subjectLine)}\n${O(an(e.range,d),s)}\n${d?Y(r,s+c-u,!0):Y(r,s+l)}`}function $t(e,t,n){let r=sn(e,n),[i,a]=e.range,o=a-i,s=Math.ceil(Math.log10(e.line+2))+3,c=O(p`· `,s),l=s+2+i,u=Math.trunc(o/2),d=o-u-1,f=r.violation.length+2,m=f<l+u,ee=J(t),te=Z(t.subjectLine),h=q(t.bodyLines,e.line-1,s),ne=`${O(p`╭──`,s)}\n${h}`,g=q(t.bodyLines,e.line,s,!0),re=`${c}${O(an(e.range,m),i)}`,_=m?Y(r,i+u-f,!0):Y(r,i+d),v=q(t.bodyLines,e.line+1,s),ie=`${v}${O(p`╰──`,s)}`;return`${ee} ${te}\n${ne}${g}${re}\n${Pe(v===``?_.trimEnd():_,c)}\n${ie}`}function q(e,t,n,r=!1){let i=e[t]??null;if(i===null)return``;let a=(t+1).toString().padStart(n-3,` `),o=Z(i);return r?`${m`•`} ${p`${f`${a}`} │`} ${o}\n`:` ${p`${a} │ ${o}`}\n`}function en(e,t,n){let r=ln(e,n),i=J(t),a=tn(t),o=nn(e),s=rn(e,t),c=o.length-1,l=O(m`${Xt+`─`.repeat(s.length)}`,c),u=Y(r,c);return`${i} ${a}\n${p`${o}`} ${s}\n${l}\n${u}`}function J(e){return p`${e.sha.slice(0,7)}`}function tn(e){return Z(e.subjectLine)}function nn(e){switch(e.field){case`author:email`:case`author:name`:return`${K} authored by:`;case`committer:email`:case`committer:name`:return`${K} committed by:`}}function rn(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 an(e,t){let[n,r]=e,i=r-n;if(i===1)return m`┬`;let a=Math.trunc(i/2),o=i-a-1,s=`─`.repeat(a),c=`─`.repeat(o);return t?m`${s}┬${c}`:m`${c}┬${s}`}function Y(e,t,n=!1){let r=`(${e.rule})${e.sidenote?`\n\n${e.sidenote}`:``}`;return O(n?m`${e.violation} ${`─╯`}\n${r}`:m`${K} ${e.violation}\n${O(r,3)}`,t)}function on(e,t,n){let r=e.rule;function i(e,t=``){return{rule:r,violation:e,sidenote:t}}switch(r){case`noBlankSubjectLines`:return i(`Subject lines must contain at least one non-whitespace character.`);case`noExcessiveWhitespace`:return i(`Subject lines must not ${e.range[0]===0?`start with`:e.range[1]===I(t.subjectLine)?`end with`:`contain excessive`} whitespace.`);case`noRevertRevertCommits`:return i(`Cherry-pick the original commit instead of reverting it over.`);case`noSingleWordSubjectLines`:return i(`Subject lines must contain at least two words.`);case`noSquashMarkers`:return i(`Combine squash commits with their ancestors.`);case`noUnexpectedPunctuation`:return i(`Subject lines must not end with punctuation.`);case`useCapitalisedSubjectLines`:return i(`The first letter in subject lines must be in uppercase.`);case`useConciseSubjectLines`:return i(`Subject lines must not exceed ${D(X(r,n).maxLength,`character`,`characters`)}.`);case`useImperativeSubjectLines`:return i(`Subject lines must start with a verb in the imperative mood.`);case`useIssueLinks`:{let e=X(r,n),t=e.position===`prefix`?`start with`:e.position===`suffix`?`end with`:`include`,a=n.tokens.issueLinks.prefixes,o=n.tokens.issueLinks.wildcards,s=[...a.map(e=>`${e}123`),...o],c=k(s.length,`Example`);return i(`Subject lines must ${t} an issue link.`,s.length>0?`${c}: ${s.join(`, `)}`:``)}}}function sn(e,t){let n=e.rule;function r(e,t=``){return{rule:n,violation:e,sidenote:t}}switch(n){case`noExcessiveWhitespace`:return r(`Message bodies must not contain excessive whitespace.`);case`noRestrictedTrailers`:return r(`Message bodies must not contain disallowed trailers.`,Q(`Disallowed trailers:`,[...X(n,t).restrictedKeys].map(e=>Me(Tt(e))).filter(h).toSorted(g),`
11
+ `));case`useEmptyLineBeforeBodyLines`:return r(`Subject lines and message bodies must be separated by exactly one empty line.`);case`useLineWrapping`:return r(`Message body lines must not exceed ${D(X(n,t).maxLength,`character`,`characters`)}.`)}}function cn(e,t){let n=e.rule;function r(e,t=``){return{rule:n,violation:e,sidenote:t}}switch(n){case`noExcessiveCommitsPerBranch`:return r(`Branches must not contain more than ${D(X(n,t).maxCommits,`commit`,`commits`)}.`);case`noMergeCommits`:return r(`Merge commits are not allowed.`);case`noRepeatedSubjectLines`:return r(`Commits must have unique subject lines within a branch.`);case`useSignedCommits`:return r(`Commits must be signed cryptographically with a signing key.`)}}function ln(e,t){let n=e.rule;function r(e,t=``){return{rule:n,violation:e,sidenote:t}}switch(n){case`useAuthorEmailPatterns`:return r(`Email addresses of commit authors must match an accepted pattern.`,Q(`Accepted patterns:`,X(n,t).patterns));case`useAuthorNamePatterns`:return r(`Names of commit authors must match an accepted pattern.`,Q(`Accepted patterns:`,X(n,t).patterns));case`useCommitterEmailPatterns`:return r(`Email addresses of committers must match an accepted pattern.`,Q(`Accepted patterns:`,X(n,t).patterns));case`useCommitterNamePatterns`:return r(`Names of committers must match an accepted pattern.`,Q(`Accepted patterns:`,X(n,t).patterns))}}function X(e,t){return t.rules[e].options}function Z(e){return e.map(e=>e.value).join(``)}function Q(e,t,n=``){return t.length>0?`${e}${t.map(e=>`\n ∙ ${e}`).join(``)}${n}`:``}function $(e){console.log(e)}function un(e){console.error(m`${e}`)}async function dn(e,t){let n=e.map(e=>ht(e,t.tokens)),r=Kt(n,t.rules);return r.length>0?($(qt(r,n,t)),1):0}function fn(e,t){let n={},r=null;for(let e of t)e.startsWith(`-`)?(r=e,n[r]??=[]):r!==null&&n[r]?.push(e);return pn(e,n),mn(e,n),hn(e,n),gn(e,n),_n(e,n),n}function pn(e,t){for(let n of Object.keys(t))if(!(n in e))throw TypeError(`Unknown option '${n}'`)}function mn(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 hn(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} ${k(t,`argument`)}`;throw TypeError(`'${e}' requires ${n}, but got ${a}`)}}}}function gn(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} ${k(t,`argument`)}`;throw TypeError(`'${e}' requires ${n}, but got ${i}`)}}}}function _n(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} ${k(t,`argument`)}`;throw TypeError(`'${e}' requires ${n}, but got ${i}`)}}}}function vn(e){return e}var yn=`2.0.0-beta.0`;function bn(){return yn}const xn=vn({"--config":{args:{min:1,max:1}}});async function Sn(e){if(e.includes(`--help`)||e.includes(`-h`))return $(Cn()),0;if(e.includes(`--version`)||e.includes(`-v`))return $(bn()),0;try{let t=fn(xn,e)[`--config`]?.[0]??null,[n,r]=await Promise.all([he(),wn(t)]);return await dn(n,r)}catch(e){return Oe(e),un(e.message),e instanceof TypeError?2:1}}function Cn(){return`Usage: comet [options]`}async function wn(e){let t=xe,n=await Ze(e);return n===null?t:x(t,await qe(n))}const Tn=await Sn(t.slice(2));e.exit(Tn);export{};
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/package.json",
3
+ "name": "@rainstormy/comet",
4
+ "version": "2.0.0-beta.0",
5
+ "description": "A linter to ensure that Git commit messages conform to certain standards and conventions declared by a customisable set of rules.",
6
+ "keywords": [
7
+ "actions",
8
+ "commit",
9
+ "conventions",
10
+ "git",
11
+ "github",
12
+ "history",
13
+ "lint",
14
+ "pull-request",
15
+ "standards"
16
+ ],
17
+ "bugs": "https://github.com/rainstormy/comet/issues",
18
+ "license": "MIT",
19
+ "author": "Steffen Diswal",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/rainstormy/comet.git"
23
+ },
24
+ "bin": {
25
+ "comet": "dist/main-cli.mjs"
26
+ },
27
+ "files": [
28
+ "dist/main-cli.mjs"
29
+ ],
30
+ "type": "module",
31
+ "imports": {
32
+ "#*": "./src/*"
33
+ },
34
+ "dependencies": {
35
+ "ansis": "4.3.1",
36
+ "valibot": "1.4.2"
37
+ },
38
+ "devDependencies": {
39
+ "@rainstormy/presets-web": "1.0.0-rc.2",
40
+ "@types/node": "24.13.3",
41
+ "typescript": "7.0.2",
42
+ "vite-plus": "0.2.9",
43
+ "vitest": "4.1.10",
44
+ "node": "runtime:24.19.0"
45
+ },
46
+ "devEngines": {
47
+ "packageManager": {
48
+ "name": "pnpm",
49
+ "version": "11.22.0",
50
+ "onFail": "download"
51
+ },
52
+ "runtime": {
53
+ "name": "node",
54
+ "version": "24.19.0",
55
+ "onFail": "download"
56
+ }
57
+ }
58
+ }