@soybeanjs/changelog 0.3.3 → 0.3.5

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/dist/index.cjs CHANGED
@@ -1,19 +1,26 @@
1
- "use strict";const cliProgress=require("cli-progress"),promises=require("fs/promises"),ofetch=require("ofetch"),w$1=require("dayjs"),fs=require("fs"),convertGitmoji=require("convert-gitmoji");function _interopDefaultCompat(t){return t&&typeof t=="object"&&"default"in t?t.default:t}const w__default=_interopDefaultCompat(w$1);async function execCommand(t,n,e){const{execa:o}=await import("execa");return(await o(t,n,e))?.stdout?.trim()||""}function notNullish(t){return t!=null}function partition(t,...n){const e=new Array(n.length+1).fill(null).map(()=>[]);return t.forEach((o,a,s)=>{let r=0;for(const i of n){if(i(o,a,s)){e[r].push(o);return}r+=1}e[r].push(o)}),e}function groupBy(t,n,e={}){for(const o of t){const a=o[n];e[a]=e[a]||[],e[a].push(o)}return e}function capitalize(t){return t.charAt(0).toUpperCase()+t.slice(1)}function join(t,n=", ",e=" and "){return!t||t.length===0?"":t.length===1?t[0]:t.length===2?t.join(e):`${t.slice(0,-1).join(n)}${e}${t.slice(-1)}`}const VERSION_REG=/v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/,VERSION_REG_OF_MARKDOWN=/## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g,VERSION_WITH_RELEASE=/release\sv\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;async function getTotalGitTags(){return(await execCommand("git",["--no-pager","tag","-l","--sort=creatordate"])).split(`
2
- `)}async function getTagDateMap(){const t=await execCommand("git",["--no-pager","log","--tags","--simplify-by-decoration","--pretty=format:%ci %d"]),n="tag: ",e=new Map;return t.split(`
3
- `).filter(o=>o.includes(n)).forEach(o=>{const[a,s]=o.split(n),r=w__default(a).format("YYYY-MM-DD"),i=s.match(VERSION_REG)?.[0];i&&r&&e.set(i.trim(),r)}),e}function getFromToTags(t){const n=[];return t.forEach((e,o)=>{o<t.length-1&&n.push({from:e,to:t[o+1]})}),n}async function getLastGitTag(t=0){const n=await getTotalGitTags();return n[n.length+t-1]}async function b$1(){return await execCommand("git",["rev-parse","--abbrev-ref","HEAD"])}async function getCurrentGitBranch(){const t=await execCommand("git",["tag","--points-at","HEAD"]),n=b$1();return t||n}async function getGitHubRepo(){const t=await execCommand("git",["config","--get","remote.origin.url"]),n=t.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);if(!n)throw new Error(`Can not parse GitHub repo from url ${t}`);return`${n[1]}/${n[2]}`}function isPrerelease(t){return!/^[^.]*[\d.]+$/.test(t)}function getFirstGitCommit(){return execCommand("git",["rev-list","--max-parents=0","HEAD"])}async function v(t,n="HEAD"){return(await execCommand("git",["--no-pager","log",`${t?`${t}...`:""}${n}`,'--pretty="----%n%s|%h|%an|%ae%n%b"',"--name-status"])).split(`----
4
- `).splice(1).map(e=>{const[o,...a]=e.split(`
5
- `),[s,r,i,p]=o.split("|");return{message:s,shortHash:r,author:{name:i,email:p},body:a.join(`
6
- `)}})}function E(t){const n=/(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i,e=/co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim,o=/\([a-z]*(#\d+)\s*\)/gm,a=/(#\d+)/gm,s=t.message.match(n);if(!s?.groups)return null;const r=s.groups.type,i=s.groups.scope||"",p=!!s.groups.breaking;let h=s.groups.description;const c=[];for(const g of h.matchAll(o))c.push({type:"pull-request",value:g[1]});for(const g of h.matchAll(a))c.some(m=>m.value===g[1])||c.push({type:"issue",value:g[1]});c.push({value:t.shortHash,type:"hash"}),h=h.replace(o,"").trim();const f=[t.author],l=t.body.matchAll(e);for(const g of l){const{name:m="",email:y=""}=g.groups||{},F={name:m.trim(),email:y.trim()};f.push(F)}return{...t,authors:f,resolvedAuthors:[],description:h,type:r,scope:i,references:c,isBreaking:p}}async function getGitCommits(t,n="HEAD"){return(await v(t,n)).map(e=>E(e)).filter(notNullish)}function G$1(t){return{accept:"application/vnd.github.v3+json",authorization:`token ${t}`}}async function x$1(t,n,e){let o="";try{o=(await ofetch.ofetch(`https://ungh.cc/users/find/${e}`))?.user?.username||""}catch(r){console.log("e: ",r)}if(o)return o;const{repo:a,token:s}=t;if(!s)return o;if(n.length)try{o=(await ofetch.ofetch(`https://api.github.com/repos/${a}/commits/${n[0]}`,{headers:G$1(s)}))?.author?.login||""}catch(r){console.log("e: ",r)}if(o)return o;try{o=(await ofetch.ofetch(`https://api.github.com/search/users?q=${encodeURIComponent(e)}`,{headers:G$1(s)})).items[0].login}catch(r){console.log("e: ",r)}return o}async function getGitCommitsAndResolvedAuthors(t,n,e){const o=[],a=new Map;for await(const s of t){const r=[];for await(const[p,h]of s.authors.entries()){const{email:c,name:f}=h;if(c&&f){const l=[];p===0&&l.push(s.shortHash);const g={name:f,email:c,commits:l,login:""};if(e?.has(c)){const m=e?.get(c)||"";g.login=m}else{const m=await x$1(n,l,c);g.login=m,e?.set(c,m)}r.push(g),a.has(c)||a.set(c,g)}}const i={...s,resolvedAuthors:r};o.push(i)}return{commits:o,contributors:Array.from(a.values())}}function u(){return{cwd:process.cwd(),types:{feat:"\u{1F680} Features",fix:"\u{1F41E} Bug Fixes",perf:"\u{1F525} Performance",refactor:"\u{1F485} Refactors",docs:"\u{1F4D6} Documentation",build:"\u{1F4E6} Build",types:"\u{1F30A} Types",chore:"\u{1F3E1} Chore",examples:"\u{1F3C0} Examples",test:"\u2705 Tests",style:"\u{1F3A8} Styles",ci:"\u{1F916} CI"},github:{repo:"",token:process.env.GITHUB_TOKEN||""},from:"",to:"",tags:[],tagDateMap:new Map,capitalize:!1,emoji:!0,titles:{breakingChanges:"\u{1F6A8} Breaking Changes"},output:"CHANGELOG.md",regenerate:!1,newVersion:""}}async function w(t){let n="";try{const e=await promises.readFile(`${t}/package.json`,"utf-8");n=JSON.parse(e)?.version||""}catch{}return{newVersion:n}}async function createOptions(t){var n;const e=u();Object.assign(e,t);const{newVersion:o}=await w(e.cwd);if((n=e.github).repo||(n.repo=await getGitHubRepo()),e.newVersion||(e.newVersion=`v${o}`),e.from||(e.from=await getLastGitTag()),e.to||(e.to=await getCurrentGitBranch()),e.to===e.from){const a=await getLastGitTag(-1),s=await getFirstGitCommit();e.from=a||s}return e.tags=await getTotalGitTags(),e.tagDateMap=await getTagDateMap(),e.prerelease=e.prerelease??isPrerelease(e.to),e}function $(t,n,e){const o=t.filter(s=>e==="issues"?s.type==="issue"||s.type==="pull-request":s.type==="hash").map(s=>n?s.type==="pull-request"||s.type==="issue"?`https://github.com/${n}/issues/${s.value.slice(1)}`:`[<samp>(${s.value.slice(0,5)})</samp>](https://github.com/${n}/commit/${s.value})`:s.value),a=join(o).trim();return e==="issues"?a&&`in ${a}`:a}function G(t,n){const e=$(t.references,n.github.repo,"issues"),o=$(t.references,n.github.repo,"hash");let a=join([...new Set(t.resolvedAuthors.map(r=>r.login?`@${r.login}`:`**${r.name}**`))]).trim();a&&(a=`by ${a}`);let s=[a,e,o].filter(r=>r?.trim()).join(" ");return s&&(s=`&nbsp;-&nbsp; ${s}`),[n.capitalize?capitalize(t.description):t.description,s].filter(r=>r?.trim()).join(" ")}function k(t,n){const e=/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;let o=t.trim();return n.emoji||(o=t.replace(e,"").trim()),`### &nbsp;&nbsp;&nbsp;${o}`}function b(t,n,e){if(!t.length)return[];const o=["",k(n,e),""],a=groupBy(t,"scope");let s=!0;return Object.entries(a).some(([r,i])=>r&&i.length>1)||(s=!1),Object.keys(a).sort().forEach(r=>{let i="",p="";const h=`**${r}**`;r&&s?(o.push(`- ${h}:`),i=" "):r&&(p=`${h}: `),o.push(...a[r].reverse().map(c=>`${i}- ${p}${G(c,e)}`))}),o}function d(t){return`https://github.com/${t}`}function x(t){return`${d(t)}.png?size=48`}function M(t){let n="",e="";return t.forEach((o,a)=>{const{name:s,email:r,login:i}=o;if(i){const p=d(i),h=x(i);n+=`[![${i}](${h})](${p})&nbsp;&nbsp;`}else{let p=`[${s}](mailto:${r})`;a<t.length-1&&(p+=",&nbsp;"),e+=p}}),`${n}
7
- ${e}`}function generateMarkdown(t){const{options:n,showTitle:e,contributors:o}=t,a=t.commits.filter(l=>l.description.match(VERSION_WITH_RELEASE)===null),s=[],r=!VERSION_REG.test(n.to),i=r?n.newVersion:n.to,p=`https://github.com/${n.github.repo}/compare/${n.from}...${i}`;if(e){const l=r?w__default().format("YY-MM-DD"):n.tagDateMap.get(n.to);let g=`## [${i}](${p})`;l&&(g+=` (${l})`),s.push(g)}const[h,c]=partition(a,l=>l.isBreaking),f=groupBy(c,"type");s.push(...b(h,n.titles.breakingChanges,n));for(const l of Object.keys(n.types)){const g=f[l]||[];s.push(...b(g,n.types[l],n))}if(s.length||s.push("*No significant changes*"),e||s.push("",`##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](${p})`),e){s.push("","### &nbsp;&nbsp;&nbsp;\u2764\uFE0F Contributors","");const l=M(o);s.push(l)}return convertGitmoji.convert(s.join(`
8
- `).trim(),!0)}async function isVersionInMarkdown(t,n){let e=!1;const o=await promises.readFile(n,"utf8");if(o){const a=o.match(VERSION_REG_OF_MARKDOWN);if(a?.length){const s=`## [${t}]`;e=a.includes(s)}}return e}async function writeMarkdown(t,n,e=!1){let o;const a="# Changelog";!e&&fs.existsSync(n)?(o=await promises.readFile(n,"utf8"),o.startsWith(a)||(o=`${a}
1
+ "use strict";const cliProgress=require("cli-progress"),r=require("node:process"),promises=require("node:fs/promises"),ofetch=require("ofetch"),A=require("dayjs"),node_fs=require("node:fs"),convertGitmoji=require("convert-gitmoji");function _interopDefaultCompat(o){return o&&typeof o=="object"&&"default"in o?o.default:o}const r__default=_interopDefaultCompat(r),A__default=_interopDefaultCompat(A),LogLevels={silent:Number.NEGATIVE_INFINITY,fatal:0,error:0,warn:1,log:2,info:3,success:3,fail:3,ready:3,start:3,box:3,debug:4,trace:5,verbose:Number.POSITIVE_INFINITY},LogTypes={silent:{level:-1},fatal:{level:LogLevels.fatal},error:{level:LogLevels.error},warn:{level:LogLevels.warn},log:{level:LogLevels.log},info:{level:LogLevels.info},success:{level:LogLevels.success},fail:{level:LogLevels.fail},ready:{level:LogLevels.info},start:{level:LogLevels.info},box:{level:LogLevels.info},debug:{level:LogLevels.debug},trace:{level:LogLevels.trace},verbose:{level:LogLevels.verbose}};function isObject(o){return o!==null&&typeof o=="object"}function _defu(o,t,e=".",s){if(!isObject(t))return _defu(o,{},e,s);const n=Object.assign({},t);for(const i in o){if(i==="__proto__"||i==="constructor")continue;const a=o[i];a!=null&&(s&&s(n,i,a,e)||(Array.isArray(a)&&Array.isArray(n[i])?n[i]=[...a,...n[i]]:isObject(a)&&isObject(n[i])?n[i]=_defu(a,n[i],(e?`${e}.`:"")+i.toString(),s):n[i]=a))}return n}function createDefu(o){return(...t)=>t.reduce((e,s)=>_defu(e,s,"",o),{})}const defu=createDefu();function isPlainObject(o){return Object.prototype.toString.call(o)==="[object Object]"}function isLogObj(o){return!(!isPlainObject(o)||!o.message&&!o.args||o.stack)}let paused=!1;const queue=[];class Consola{constructor(t={}){const e=t.types||LogTypes;this.options=defu({...t,defaults:{...t.defaults},level:_normalizeLogLevel(t.level,e),reporters:[...t.reporters||[]]},{types:LogTypes,throttle:1e3,throttleMin:5,formatOptions:{date:!0,colors:!1,compact:!0}});for(const s in e){const n={type:s,...this.options.defaults,...e[s]};this[s]=this._wrapLogFn(n),this[s].raw=this._wrapLogFn(n,!0)}this.options.mockFn&&this.mockTypes(),this._lastLog={}}get level(){return this.options.level}set level(t){this.options.level=_normalizeLogLevel(t,this.options.types,this.options.level)}prompt(t,e){if(!this.options.prompt)throw new Error("prompt is not supported!");return this.options.prompt(t,e)}create(t){const e=new Consola({...this.options,...t});return this._mockFn&&e.mockTypes(this._mockFn),e}withDefaults(t){return this.create({...this.options,defaults:{...this.options.defaults,...t}})}withTag(t){return this.withDefaults({tag:this.options.defaults.tag?this.options.defaults.tag+":"+t:t})}addReporter(t){return this.options.reporters.push(t),this}removeReporter(t){if(t){const e=this.options.reporters.indexOf(t);if(e>=0)return this.options.reporters.splice(e,1)}else this.options.reporters.splice(0);return this}setReporters(t){return this.options.reporters=Array.isArray(t)?t:[t],this}wrapAll(){this.wrapConsole(),this.wrapStd()}restoreAll(){this.restoreConsole(),this.restoreStd()}wrapConsole(){for(const t in this.options.types)console["__"+t]||(console["__"+t]=console[t]),console[t]=this[t].raw}restoreConsole(){for(const t in this.options.types)console["__"+t]&&(console[t]=console["__"+t],delete console["__"+t])}wrapStd(){this._wrapStream(this.options.stdout,"log"),this._wrapStream(this.options.stderr,"log")}_wrapStream(t,e){t&&(t.__write||(t.__write=t.write),t.write=s=>{this[e].raw(String(s).trim())})}restoreStd(){this._restoreStream(this.options.stdout),this._restoreStream(this.options.stderr)}_restoreStream(t){t&&t.__write&&(t.write=t.__write,delete t.__write)}pauseLogs(){paused=!0}resumeLogs(){paused=!1;const t=queue.splice(0);for(const e of t)e[0]._logFn(e[1],e[2])}mockTypes(t){const e=t||this.options.mockFn;if(this._mockFn=e,typeof e=="function")for(const s in this.options.types)this[s]=e(s,this.options.types[s])||this[s],this[s].raw=this[s]}_wrapLogFn(t,e){return(...s)=>{if(paused){queue.push([this,t,s,e]);return}return this._logFn(t,s,e)}}_logFn(t,e,s){if((t.level||0)>this.level)return!1;const n={date:new Date,args:[],...t,level:_normalizeLogLevel(t.level,this.options.types)};!s&&e.length===1&&isLogObj(e[0])?Object.assign(n,e[0]):n.args=[...e],n.message&&(n.args.unshift(n.message),delete n.message),n.additional&&(Array.isArray(n.additional)||(n.additional=n.additional.split(`
2
+ `)),n.args.push(`
3
+ `+n.additional.join(`
4
+ `)),delete n.additional),n.type=typeof n.type=="string"?n.type.toLowerCase():"log",n.tag=typeof n.tag=="string"?n.tag:"";const i=(c=!1)=>{const l=(this._lastLog.count||0)-this.options.throttleMin;if(this._lastLog.object&&l>0){const u=[...this._lastLog.object.args];l>1&&u.push(`(repeated ${l} times)`),this._log({...this._lastLog.object,args:u}),this._lastLog.count=1}c&&(this._lastLog.object=n,this._log(n))};clearTimeout(this._lastLog.timeout);const a=this._lastLog.time&&n.date?n.date.getTime()-this._lastLog.time.getTime():0;if(this._lastLog.time=n.date,a<this.options.throttle)try{const c=JSON.stringify([n.type,n.tag,n.args]),l=this._lastLog.serialized===c;if(this._lastLog.serialized=c,l&&(this._lastLog.count=(this._lastLog.count||0)+1,this._lastLog.count>this.options.throttleMin)){this._lastLog.timeout=setTimeout(i,this.options.throttle);return}}catch{}i(!0)}_log(t){for(const e of this.options.reporters)e.log(t,{options:this.options})}}function _normalizeLogLevel(o,t={},e=3){return o===void 0?e:typeof o=="number"?o:t[o]&&t[o].level!==void 0?t[o].level:e}Consola.prototype.add=Consola.prototype.addReporter,Consola.prototype.remove=Consola.prototype.removeReporter,Consola.prototype.clear=Consola.prototype.removeReporter,Consola.prototype.withScope=Consola.prototype.withTag,Consola.prototype.mock=Consola.prototype.mockTypes,Consola.prototype.pause=Consola.prototype.pauseLogs,Consola.prototype.resume=Consola.prototype.resumeLogs;function createConsola$1(o={}){return new Consola(o)}class BrowserReporter{constructor(t){this.options={...t},this.defaultColor="#7f8c8d",this.levelColorMap={0:"#c0392b",1:"#f39c12",3:"#00BCD4"},this.typeColorMap={success:"#2ecc71"}}_getLogFn(t){return t<1?console.__error||console.error:t===1?console.__warn||console.warn:console.__log||console.log}log(t){const e=this._getLogFn(t.level),s=t.type==="log"?"":t.type,n=t.tag||"",a=`
5
+ background: ${this.typeColorMap[t.type]||this.levelColorMap[t.level]||this.defaultColor};
6
+ border-radius: 0.5em;
7
+ color: white;
8
+ font-weight: bold;
9
+ padding: 2px 0.5em;
10
+ `,c=`%c${[n,s].filter(Boolean).join(":")}`;typeof t.args[0]=="string"?e(`${c}%c ${t.args[0]}`,a,"",...t.args.slice(1)):e(c,a,...t.args)}}function createConsola(o={}){return createConsola$1({reporters:o.reporters||[new BrowserReporter({})],prompt(e,s={}){return s.type==="confirm"?Promise.resolve(confirm(e)):Promise.resolve(prompt(e))},...o})}const consola=createConsola();async function execCommand(o,t,e){const{execa:s}=await import("execa");return(await s(o,t,e))?.stdout?.trim()||""}function notNullish(o){return o!=null}function partition(o,...t){const e=Array.from({length:t.length+1}).fill(null).map(()=>[]);return o.forEach((s,n,i)=>{let a=0;for(const c of t){if(c(s,n,i)){e[a].push(s);return}a+=1}e[a].push(s)}),e}function groupBy(o,t,e={}){for(const s of o){const n=s[t];e[n]||(e[n]=[]),e[n].push(s)}return e}function capitalize(o){return o.charAt(0).toUpperCase()+o.slice(1)}function join(o,t=", ",e=" and "){return!o||o.length===0?"":o.length===1?o[0]:o.length===2?o.join(e):`${o.slice(0,-1).join(t)}${e}${o.slice(-1)}`}const VERSION_REG=/v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/,VERSION_REG_OF_MARKDOWN=/## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g,VERSION_WITH_RELEASE=/release\sv\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;async function getTotalGitTags(){return(await execCommand("git",["--no-pager","tag","-l","--sort=creatordate"])).split(`
11
+ `)}async function getTagDateMap(){const o=await execCommand("git",["--no-pager","log","--tags","--simplify-by-decoration","--pretty=format:%ci %d"]),t="tag: ",e=new Map;return o.split(`
12
+ `).filter(s=>s.includes(t)).forEach(s=>{const[n,i]=s.split(t),a=A__default(n).format("YYYY-MM-DD"),c=i.match(VERSION_REG)?.[0];c&&a&&e.set(c.trim(),a)}),e}function getFromToTags(o){const t=[];return o.forEach((e,s)=>{s<o.length-1&&t.push({from:e,to:o[s+1]})}),t}async function getLastGitTag(o=0){const t=await getTotalGitTags();return t[t.length+o-1]}async function v$1(){return await execCommand("git",["rev-parse","--abbrev-ref","HEAD"])}async function getCurrentGitBranch(){const o=await execCommand("git",["tag","--points-at","HEAD"]),t=v$1();return o||t}async function getGitHubRepo(){const o=await execCommand("git",["config","--get","remote.origin.url"]),t=o.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);if(!t)throw new Error(`Can not parse GitHub repo from url ${o}`);return`${t[1]}/${t[2]}`}function isPrerelease(o){return!/^[^.]*[\d.]+$/.test(o)}function getFirstGitCommit(){return execCommand("git",["rev-list","--max-parents=0","HEAD"])}async function E(o,t="HEAD"){return(await execCommand("git",["--no-pager","log",`${o?`${o}...`:""}${t}`,'--pretty="----%n%s|%h|%an|%ae%n%b"',"--name-status"])).split(`----
13
+ `).splice(1).map(e=>{const[s,...n]=e.split(`
14
+ `),[i,a,c,l]=s.split("|");return{message:i,shortHash:a,author:{name:c,email:l},body:n.join(`
15
+ `)}})}function x$1(o){const t=/(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i,e=/co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim,s=/\([a-z]*(#\d+)\s*\)/gm,n=/(#\d+)/gm,i=o.message.match(t);if(!i?.groups)return null;const a=i.groups.type,c=i.groups.scope||"",l=!!i.groups.breaking;let u=i.groups.description;const p=[];for(const g of u.matchAll(s))p.push({type:"pull-request",value:g[1]});for(const g of u.matchAll(n))p.some(_=>_.value===g[1])||p.push({type:"issue",value:g[1]});p.push({value:o.shortHash,type:"hash"}),u=u.replace(s,"").trim();const m=[o.author],f=o.body.matchAll(e);for(const g of f){const{name:_="",email:b=""}=g.groups||{},F={name:_.trim(),email:b.trim()};m.push(F)}return{...o,authors:m,resolvedAuthors:[],description:u,type:a,scope:c,references:p,isBreaking:l}}async function getGitCommits(o,t="HEAD"){return(await E(o,t)).map(e=>x$1(e)).filter(notNullish)}function C(o){return{accept:"application/vnd.github.v3+json",authorization:`token ${o}`}}async function $(o,t,e){let s="";try{s=(await ofetch.ofetch(`https://ungh.cc/users/find/${e}`))?.user?.username||""}catch(a){consola.log("e: ",a)}if(s)return s;const{repo:n,token:i}=o;if(!i)return s;if(t.length)try{s=(await ofetch.ofetch(`https://api.github.com/repos/${n}/commits/${t[0]}`,{headers:C(i)}))?.author?.login||""}catch(a){consola.log("e: ",a)}if(s)return s;try{s=(await ofetch.ofetch(`https://api.github.com/search/users?q=${encodeURIComponent(e)}`,{headers:C(i)})).items[0].login}catch(a){consola.log("e: ",a)}return s}async function getGitCommitsAndResolvedAuthors(o,t,e){const s=[],n=new Map;for await(const i of o){const a=[];for await(const[l,u]of i.authors.entries()){const{email:p,name:m}=u;if(p&&m){const f=[];l===0&&f.push(i.shortHash);const g={name:m,email:p,commits:f,login:""};if(e?.has(p)){const _=e?.get(p)||"";g.login=_}else{const _=await $(t,f,p);g.login=_,e?.set(p,_)}a.push(g),n.has(p)||n.set(p,g)}}const c={...i,resolvedAuthors:a};s.push(c)}return{commits:s,contributors:Array.from(n.values())}}function w(){return{cwd:r__default.cwd(),types:{feat:"\u{1F680} Features",fix:"\u{1F41E} Bug Fixes",perf:"\u{1F525} Performance",refactor:"\u{1F485} Refactors",docs:"\u{1F4D6} Documentation",build:"\u{1F4E6} Build",types:"\u{1F30A} Types",chore:"\u{1F3E1} Chore",examples:"\u{1F3C0} Examples",test:"\u2705 Tests",style:"\u{1F3A8} Styles",ci:"\u{1F916} CI"},github:{repo:"",token:r__default.env.GITHUB_TOKEN||""},from:"",to:"",tags:[],tagDateMap:new Map,capitalize:!1,emoji:!0,titles:{breakingChanges:"\u{1F6A8} Breaking Changes"},output:"CHANGELOG.md",regenerate:!1,newVersion:""}}async function h(o){let t="";try{const e=await promises.readFile(`${o}/package.json`,"utf-8");t=JSON.parse(e)?.version||""}catch{}return{newVersion:t}}async function createOptions(o){var t;const e=w();Object.assign(e,o);const{newVersion:s}=await h(e.cwd);if((t=e.github).repo||(t.repo=await getGitHubRepo()),e.newVersion||(e.newVersion=`v${s}`),e.from||(e.from=await getLastGitTag()),e.to||(e.to=await getCurrentGitBranch()),e.to===e.from){const n=await getLastGitTag(-1),i=await getFirstGitCommit();e.from=n||i}return e.tags=await getTotalGitTags(),e.tagDateMap=await getTagDateMap(),e.prerelease||(e.prerelease=isPrerelease(e.to)),e}function d(o,t,e){const s=o.filter(i=>e==="issues"?i.type==="issue"||i.type==="pull-request":i.type==="hash").map(i=>t?i.type==="pull-request"||i.type==="issue"?`https://github.com/${t}/issues/${i.value.slice(1)}`:`[<samp>(${i.value.slice(0,5)})</samp>](https://github.com/${t}/commit/${i.value})`:i.value),n=join(s).trim();return e==="issues"?n&&`in ${n}`:n}function j(o,t){const e=d(o.references,t.github.repo,"issues"),s=d(o.references,t.github.repo,"hash");let n=join([...new Set(o.resolvedAuthors.map(a=>a.login?`@${a.login}`:`**${a.name}**`))]).trim();n&&(n=`by ${n}`);let i=[n,e,s].filter(a=>a?.trim()).join(" ");return i&&(i=`&nbsp;-&nbsp; ${i}`),[t.capitalize?capitalize(o.description):o.description,i].filter(a=>a?.trim()).join(" ")}function G(o,t){const e=/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;let s=o.trim();return t.emoji||(s=o.replace(e,"").trim()),`### &nbsp;&nbsp;&nbsp;${s}`}function y(o,t,e){if(!o.length)return[];const s=["",G(t,e),""],n=groupBy(o,"scope");let i=!0;return Object.entries(n).some(([a,c])=>a&&c.length>1)||(i=!1),Object.keys(n).sort().forEach(a=>{let c="",l="";const u=`**${a}**`;a&&i?(s.push(`- ${u}:`),c=" "):a&&(l=`${u}: `),s.push(...n[a].reverse().map(p=>`${c}- ${l}${j(p,e)}`))}),s}function v(o){return`https://github.com/${o}`}function k(o){return`${v(o)}.png?size=48`}function x(o){let t="",e="";const s=new Map;return o.forEach(n=>{s.set(n.email,n)}),Array.from(s.values()).forEach((n,i)=>{const{name:a,email:c,login:l}=n;if(l){const u=v(l),p=k(l);t+=`[![${l}](${p})](${u})&nbsp;&nbsp;`}else{let u=`[${a}](mailto:${c})`;i<o.length-1&&(u+=",&nbsp;"),e+=u}}),`${t}
16
+ ${e}`}function generateMarkdown(o){const{options:t,showTitle:e,contributors:s}=o,n=o.commits.filter(f=>f.description.match(VERSION_WITH_RELEASE)===null),i=[],a=!VERSION_REG.test(t.to),c=a?t.newVersion:t.to,l=`https://github.com/${t.github.repo}/compare/${t.from}...${c}`;if(e){const f=a?A__default().format("YY-MM-DD"):t.tagDateMap.get(t.to);let g=`## [${c}](${l})`;f&&(g+=` (${f})`),i.push(g)}const[u,p]=partition(n,f=>f.isBreaking),m=groupBy(p,"type");i.push(...y(u,t.titles.breakingChanges,t));for(const f of Object.keys(t.types)){const g=m[f]||[];i.push(...y(g,t.types[f],t))}if(i.length||i.push("*No significant changes*"),e||i.push("",`##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](${l})`),e){i.push("","### &nbsp;&nbsp;&nbsp;\u2764\uFE0F Contributors","");const f=x(s);i.push(f)}return convertGitmoji.convert(i.join(`
17
+ `).trim(),!0)}async function isVersionInMarkdown(o,t){let e=!1;const s=await promises.readFile(t,"utf8");if(s){const n=s.match(VERSION_REG_OF_MARKDOWN);if(n?.length){const i=`## [${o}]`;e=n.includes(i)}}return e}async function writeMarkdown(o,t,e=!1){let s="";const n="# Changelog";node_fs.existsSync(t)||await promises.writeFile(t,n,"utf8"),e||(s=await promises.readFile(t,"utf8")),s.startsWith(n)||(s=`${n}
9
18
 
10
- ${o}`)):o=`${a}
19
+ ${s}`);const i=s.match(/^###?\s+.*$/m);i?s+=`${s.slice(0,i.index)+o}
11
20
 
12
- `;const s=o.match(/^###?\s+.*$/m);s?o=`${o.slice(0,s.index)+t}
21
+ ${s.slice(i.index)}`:s+=`
22
+ ${o}
13
23
 
14
- ${o.slice(s.index)}`:o+=`
15
- ${t}
24
+ `,await promises.writeFile(t,s)}async function getChangelogMarkdown(o,t=!0){const e=await createOptions(o),s=await getGitCommits(e.from,e.to),{commits:n,contributors:i}=await getGitCommitsAndResolvedAuthors(s,e.github);return{markdown:generateMarkdown({commits:n,options:e,showTitle:t,contributors:i}),commits:n,options:e}}async function getTotalChangelogMarkdown(o,t=!0){const e=await createOptions(o);let s=null;t&&(s=new cliProgress.SingleBar({format:"generate total changelog: [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}"},cliProgress.Presets.shades_classic));const n=getFromToTags(e.tags);if(n.length===0){const{markdown:c}=await getChangelogMarkdown(e);return c}s?.start(n.length,0);let i="";const a=new Map;for await(const[c,l]of n.entries()){const{from:u,to:p}=l,m=await getGitCommits(u,p),{commits:f,contributors:g}=await getGitCommitsAndResolvedAuthors(m,e.github,a);i=`${generateMarkdown({commits:f,options:{...e,from:u,to:p},showTitle:!0,contributors:g})}
16
25
 
17
- `,await promises.writeFile(n,o)}async function getChangelogMarkdown(t,n=!0){const e=await createOptions(t),o=await getGitCommits(e.from,e.to),{commits:a,contributors:s}=await getGitCommitsAndResolvedAuthors(o,e.github);return{markdown:generateMarkdown({commits:a,options:e,showTitle:n,contributors:s}),commits:a,options:e}}async function getTotalChangelogMarkdown(t,n=!0){const e=await createOptions(t);let o=null;n&&(o=new cliProgress.SingleBar({format:"generate total changelog: [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}"},cliProgress.Presets.shades_classic));const a=getFromToTags(e.tags);if(a.length===0){const{markdown:i}=await getChangelogMarkdown(e);return i}o?.start(a.length,0);let s="";const r=new Map;for await(const[i,p]of a.entries()){const{from:h,to:c}=p,f=await getGitCommits(h,c),{commits:l,contributors:g}=await getGitCommitsAndResolvedAuthors(f,e.github,r);s=`${generateMarkdown({commits:l,options:{...e,from:h,to:c},showTitle:!0,contributors:g})}
18
-
19
- ${s}`,o?.update(i+1)}return o?.stop(),s}async function generateChangelog(t){const n=await createOptions(t),e=await isVersionInMarkdown(n.to,n.output);if(!n.regenerate&&e)return;const{markdown:o}=await getChangelogMarkdown(n);await writeMarkdown(o,n.output,n.regenerate)}async function generateTotalChangelog(t,n=!0){const e=await createOptions(t),o=await getTotalChangelogMarkdown(e,n);await writeMarkdown(o,e.output,!0)}exports.generateChangelog=generateChangelog,exports.generateTotalChangelog=generateTotalChangelog,exports.getChangelogMarkdown=getChangelogMarkdown,exports.getTotalChangelogMarkdown=getTotalChangelogMarkdown;
26
+ ${i}`,s?.update(c+1)}return s?.stop(),i}async function generateChangelog(o){const t=await createOptions(o),e=await isVersionInMarkdown(t.to,t.output);if(!t.regenerate&&e)return;const{markdown:s}=await getChangelogMarkdown(t);await writeMarkdown(s,t.output,t.regenerate)}async function generateTotalChangelog(o,t=!0){const e=await createOptions(o),s=await getTotalChangelogMarkdown(e,t);await writeMarkdown(s,e.output,!0)}exports.generateChangelog=generateChangelog,exports.generateTotalChangelog=generateTotalChangelog,exports.getChangelogMarkdown=getChangelogMarkdown,exports.getTotalChangelogMarkdown=getTotalChangelogMarkdown;
package/dist/index.d.cts CHANGED
@@ -1,182 +1,120 @@
1
- /**
2
- * the commit author
3
- */
1
+ /** The commit author */
4
2
  interface GitCommitAuthor {
5
- /**
6
- * the author name
7
- */
3
+ /** The author name */
8
4
  name: string;
9
- /**
10
- * the author email
11
- */
5
+ /** The author email */
12
6
  email: string;
13
7
  }
14
- /**
15
- * the raw git commit
16
- */
8
+ /** The raw git commit */
17
9
  interface RawGitCommit {
18
- /**
19
- * the commit message
20
- */
10
+ /** The commit message */
21
11
  message: string;
22
- /**
23
- * the commit body
24
- */
12
+ /** The commit body */
25
13
  body: string;
26
- /**
27
- * the commit hash
28
- */
14
+ /** The commit hash */
29
15
  shortHash: string;
30
- /**
31
- * the commit author
32
- */
16
+ /** The commit author */
33
17
  author: GitCommitAuthor;
34
18
  }
35
- /**
36
- * the reference of the commit
37
- */
19
+ /** The reference of the commit */
38
20
  interface Reference {
39
- /**
40
- * the reference type
41
- */
21
+ /** The reference type */
42
22
  type: 'hash' | 'issue' | 'pull-request';
43
- /**
44
- * the reference value
45
- */
23
+ /** The reference value */
46
24
  value: string;
47
25
  }
48
- /**
49
- * the resolved github author
50
- */
26
+ /** The resolved github author */
51
27
  interface ResolvedAuthor extends GitCommitAuthor {
52
- /**
53
- * the git commit of the author
54
- */
28
+ /** The git commit of the author */
55
29
  commits: string[];
56
- /**
57
- * the github logged username of the author
58
- */
30
+ /** The github logged username of the author */
59
31
  login: string;
60
32
  }
61
- /**
62
- * git commit config
63
- */
33
+ /** Git commit config */
64
34
  interface GitCommit extends RawGitCommit {
65
- /**
66
- * the commit description
67
- */
35
+ /** The commit description */
68
36
  description: string;
69
- /**
70
- * the commit scope type
71
- */
37
+ /** The commit scope type */
72
38
  type: string;
73
- /**
74
- * the commit scope
75
- */
39
+ /** The commit scope */
76
40
  scope: string;
77
- /**
78
- * the commit references
79
- */
41
+ /** The commit references */
80
42
  references: Reference[];
81
- /**
82
- * the commit authors
83
- */
43
+ /** The commit authors */
84
44
  authors: GitCommitAuthor[];
85
- /**
86
- * the resolved authors
87
- */
45
+ /** The resolved authors */
88
46
  resolvedAuthors: ResolvedAuthor[];
89
- /**
90
- * the commit breaking changes
91
- */
47
+ /** The commit breaking changes */
92
48
  isBreaking: boolean;
93
49
  }
94
- /**
95
- * github config
96
- */
50
+ /** Github config */
97
51
  interface GithubConfig {
98
52
  /**
99
- * the github repository name
100
- * @example soybeanjs/changelog
53
+ * The github repository name
54
+ *
55
+ * @example
56
+ * soybeanjs / changelog;
101
57
  */
102
58
  repo: string;
103
- /**
104
- * the github token
105
- */
59
+ /** The github token */
106
60
  token: string;
107
61
  }
108
62
  interface ChangelogOption {
109
63
  /**
110
- * the directory of the project
64
+ * The directory of the project
65
+ *
111
66
  * @default process.cwd()
112
67
  */
113
68
  cwd: string;
114
- /**
115
- * the commit scope types
116
- */
69
+ /** The commit scope types */
117
70
  types: Record<string, string>;
118
- /**
119
- * github config
120
- */
71
+ /** Github config */
121
72
  github: GithubConfig;
122
- /**
123
- * the commit hash or tag
124
- */
73
+ /** The commit hash or tag */
125
74
  from: string;
126
- /**
127
- * the commit hash or tag
128
- */
75
+ /** The commit hash or tag */
129
76
  to: string;
130
- /**
131
- * the whole commit tags
132
- */
77
+ /** The whole commit tags */
133
78
  tags: string[];
134
- /**
135
- * the commit tag and date map
136
- */
79
+ /** The commit tag and date map */
137
80
  tagDateMap: Map<string, string>;
138
- /**
139
- * Whether to capitalize the first letter of the commit type
140
- */
81
+ /** Whether to capitalize the first letter of the commit type */
141
82
  capitalize: boolean;
142
83
  /**
143
84
  * Use emojis in section titles
85
+ *
144
86
  * @default true
145
87
  */
146
88
  emoji: boolean;
147
- /**
148
- * the section titles
149
- */
89
+ /** The section titles */
150
90
  titles: {
151
- /**
152
- * the title of breaking changes section
153
- */
91
+ /** The title of breaking changes section */
154
92
  breakingChanges: string;
155
93
  };
156
- /**
157
- * the output file path of the changelog
158
- */
94
+ /** The output file path of the changelog */
159
95
  output: string;
160
96
  /**
161
97
  * Whether to regenerate the changelog if it already exists
162
- * @example the changelog already exists the content of v0.0.1, but you want to regenerate it
98
+ *
99
+ * @example
100
+ * the changelog already exists the content of v0.0.1, but you want to regenerate it
163
101
  */
164
102
  regenerate: boolean;
165
103
  /**
166
- * version from package.json, with prefix "v"
167
- * @description if the options "to" is not specified, the version will be used
104
+ * Version from package.json, with prefix "v"
105
+ *
106
+ * If the options "to" is not specified, the version will be used
168
107
  */
169
108
  newVersion: string;
170
- /**
171
- * Mark the release as prerelease
172
- */
109
+ /** Mark the release as prerelease */
173
110
  prerelease?: boolean;
174
111
  }
175
112
 
176
113
  /**
177
- * get the changelog markdown by two git tags
178
- * @param options the changelog options
179
- * @param showTitle whither show the title
114
+ * Get the changelog markdown by two git tags
115
+ *
116
+ * @param options The changelog options
117
+ * @param showTitle Whither show the title
180
118
  */
181
119
  declare function getChangelogMarkdown(options?: Partial<ChangelogOption>, showTitle?: boolean): Promise<{
182
120
  markdown: string;
@@ -184,20 +122,23 @@ declare function getChangelogMarkdown(options?: Partial<ChangelogOption>, showTi
184
122
  options: ChangelogOption;
185
123
  }>;
186
124
  /**
187
- * get the changelog markdown by the total git tags
188
- * @param options the changelog options
189
- * @param showProgress whither show the progress bar
125
+ * Get the changelog markdown by the total git tags
126
+ *
127
+ * @param options The changelog options
128
+ * @param showProgress Whither show the progress bar
190
129
  */
191
130
  declare function getTotalChangelogMarkdown(options?: Partial<ChangelogOption>, showProgress?: boolean): Promise<string>;
192
131
  /**
193
- * generate the changelog markdown by two git tags
194
- * @param options the changelog options
132
+ * Generate the changelog markdown by two git tags
133
+ *
134
+ * @param options The changelog options
195
135
  */
196
136
  declare function generateChangelog(options?: Partial<ChangelogOption>): Promise<void>;
197
137
  /**
198
- * generate the changelog markdown by the total git tags
199
- * @param options the changelog options
200
- * @param showProgress whither show the progress bar
138
+ * Generate the changelog markdown by the total git tags
139
+ *
140
+ * @param options The changelog options
141
+ * @param showProgress Whither show the progress bar
201
142
  */
202
143
  declare function generateTotalChangelog(options?: Partial<ChangelogOption>, showProgress?: boolean): Promise<void>;
203
144
 
package/dist/index.d.mts CHANGED
@@ -1,182 +1,120 @@
1
- /**
2
- * the commit author
3
- */
1
+ /** The commit author */
4
2
  interface GitCommitAuthor {
5
- /**
6
- * the author name
7
- */
3
+ /** The author name */
8
4
  name: string;
9
- /**
10
- * the author email
11
- */
5
+ /** The author email */
12
6
  email: string;
13
7
  }
14
- /**
15
- * the raw git commit
16
- */
8
+ /** The raw git commit */
17
9
  interface RawGitCommit {
18
- /**
19
- * the commit message
20
- */
10
+ /** The commit message */
21
11
  message: string;
22
- /**
23
- * the commit body
24
- */
12
+ /** The commit body */
25
13
  body: string;
26
- /**
27
- * the commit hash
28
- */
14
+ /** The commit hash */
29
15
  shortHash: string;
30
- /**
31
- * the commit author
32
- */
16
+ /** The commit author */
33
17
  author: GitCommitAuthor;
34
18
  }
35
- /**
36
- * the reference of the commit
37
- */
19
+ /** The reference of the commit */
38
20
  interface Reference {
39
- /**
40
- * the reference type
41
- */
21
+ /** The reference type */
42
22
  type: 'hash' | 'issue' | 'pull-request';
43
- /**
44
- * the reference value
45
- */
23
+ /** The reference value */
46
24
  value: string;
47
25
  }
48
- /**
49
- * the resolved github author
50
- */
26
+ /** The resolved github author */
51
27
  interface ResolvedAuthor extends GitCommitAuthor {
52
- /**
53
- * the git commit of the author
54
- */
28
+ /** The git commit of the author */
55
29
  commits: string[];
56
- /**
57
- * the github logged username of the author
58
- */
30
+ /** The github logged username of the author */
59
31
  login: string;
60
32
  }
61
- /**
62
- * git commit config
63
- */
33
+ /** Git commit config */
64
34
  interface GitCommit extends RawGitCommit {
65
- /**
66
- * the commit description
67
- */
35
+ /** The commit description */
68
36
  description: string;
69
- /**
70
- * the commit scope type
71
- */
37
+ /** The commit scope type */
72
38
  type: string;
73
- /**
74
- * the commit scope
75
- */
39
+ /** The commit scope */
76
40
  scope: string;
77
- /**
78
- * the commit references
79
- */
41
+ /** The commit references */
80
42
  references: Reference[];
81
- /**
82
- * the commit authors
83
- */
43
+ /** The commit authors */
84
44
  authors: GitCommitAuthor[];
85
- /**
86
- * the resolved authors
87
- */
45
+ /** The resolved authors */
88
46
  resolvedAuthors: ResolvedAuthor[];
89
- /**
90
- * the commit breaking changes
91
- */
47
+ /** The commit breaking changes */
92
48
  isBreaking: boolean;
93
49
  }
94
- /**
95
- * github config
96
- */
50
+ /** Github config */
97
51
  interface GithubConfig {
98
52
  /**
99
- * the github repository name
100
- * @example soybeanjs/changelog
53
+ * The github repository name
54
+ *
55
+ * @example
56
+ * soybeanjs / changelog;
101
57
  */
102
58
  repo: string;
103
- /**
104
- * the github token
105
- */
59
+ /** The github token */
106
60
  token: string;
107
61
  }
108
62
  interface ChangelogOption {
109
63
  /**
110
- * the directory of the project
64
+ * The directory of the project
65
+ *
111
66
  * @default process.cwd()
112
67
  */
113
68
  cwd: string;
114
- /**
115
- * the commit scope types
116
- */
69
+ /** The commit scope types */
117
70
  types: Record<string, string>;
118
- /**
119
- * github config
120
- */
71
+ /** Github config */
121
72
  github: GithubConfig;
122
- /**
123
- * the commit hash or tag
124
- */
73
+ /** The commit hash or tag */
125
74
  from: string;
126
- /**
127
- * the commit hash or tag
128
- */
75
+ /** The commit hash or tag */
129
76
  to: string;
130
- /**
131
- * the whole commit tags
132
- */
77
+ /** The whole commit tags */
133
78
  tags: string[];
134
- /**
135
- * the commit tag and date map
136
- */
79
+ /** The commit tag and date map */
137
80
  tagDateMap: Map<string, string>;
138
- /**
139
- * Whether to capitalize the first letter of the commit type
140
- */
81
+ /** Whether to capitalize the first letter of the commit type */
141
82
  capitalize: boolean;
142
83
  /**
143
84
  * Use emojis in section titles
85
+ *
144
86
  * @default true
145
87
  */
146
88
  emoji: boolean;
147
- /**
148
- * the section titles
149
- */
89
+ /** The section titles */
150
90
  titles: {
151
- /**
152
- * the title of breaking changes section
153
- */
91
+ /** The title of breaking changes section */
154
92
  breakingChanges: string;
155
93
  };
156
- /**
157
- * the output file path of the changelog
158
- */
94
+ /** The output file path of the changelog */
159
95
  output: string;
160
96
  /**
161
97
  * Whether to regenerate the changelog if it already exists
162
- * @example the changelog already exists the content of v0.0.1, but you want to regenerate it
98
+ *
99
+ * @example
100
+ * the changelog already exists the content of v0.0.1, but you want to regenerate it
163
101
  */
164
102
  regenerate: boolean;
165
103
  /**
166
- * version from package.json, with prefix "v"
167
- * @description if the options "to" is not specified, the version will be used
104
+ * Version from package.json, with prefix "v"
105
+ *
106
+ * If the options "to" is not specified, the version will be used
168
107
  */
169
108
  newVersion: string;
170
- /**
171
- * Mark the release as prerelease
172
- */
109
+ /** Mark the release as prerelease */
173
110
  prerelease?: boolean;
174
111
  }
175
112
 
176
113
  /**
177
- * get the changelog markdown by two git tags
178
- * @param options the changelog options
179
- * @param showTitle whither show the title
114
+ * Get the changelog markdown by two git tags
115
+ *
116
+ * @param options The changelog options
117
+ * @param showTitle Whither show the title
180
118
  */
181
119
  declare function getChangelogMarkdown(options?: Partial<ChangelogOption>, showTitle?: boolean): Promise<{
182
120
  markdown: string;
@@ -184,20 +122,23 @@ declare function getChangelogMarkdown(options?: Partial<ChangelogOption>, showTi
184
122
  options: ChangelogOption;
185
123
  }>;
186
124
  /**
187
- * get the changelog markdown by the total git tags
188
- * @param options the changelog options
189
- * @param showProgress whither show the progress bar
125
+ * Get the changelog markdown by the total git tags
126
+ *
127
+ * @param options The changelog options
128
+ * @param showProgress Whither show the progress bar
190
129
  */
191
130
  declare function getTotalChangelogMarkdown(options?: Partial<ChangelogOption>, showProgress?: boolean): Promise<string>;
192
131
  /**
193
- * generate the changelog markdown by two git tags
194
- * @param options the changelog options
132
+ * Generate the changelog markdown by two git tags
133
+ *
134
+ * @param options The changelog options
195
135
  */
196
136
  declare function generateChangelog(options?: Partial<ChangelogOption>): Promise<void>;
197
137
  /**
198
- * generate the changelog markdown by the total git tags
199
- * @param options the changelog options
200
- * @param showProgress whither show the progress bar
138
+ * Generate the changelog markdown by the total git tags
139
+ *
140
+ * @param options The changelog options
141
+ * @param showProgress Whither show the progress bar
201
142
  */
202
143
  declare function generateTotalChangelog(options?: Partial<ChangelogOption>, showProgress?: boolean): Promise<void>;
203
144
 
package/dist/index.d.ts CHANGED
@@ -1,182 +1,120 @@
1
- /**
2
- * the commit author
3
- */
1
+ /** The commit author */
4
2
  interface GitCommitAuthor {
5
- /**
6
- * the author name
7
- */
3
+ /** The author name */
8
4
  name: string;
9
- /**
10
- * the author email
11
- */
5
+ /** The author email */
12
6
  email: string;
13
7
  }
14
- /**
15
- * the raw git commit
16
- */
8
+ /** The raw git commit */
17
9
  interface RawGitCommit {
18
- /**
19
- * the commit message
20
- */
10
+ /** The commit message */
21
11
  message: string;
22
- /**
23
- * the commit body
24
- */
12
+ /** The commit body */
25
13
  body: string;
26
- /**
27
- * the commit hash
28
- */
14
+ /** The commit hash */
29
15
  shortHash: string;
30
- /**
31
- * the commit author
32
- */
16
+ /** The commit author */
33
17
  author: GitCommitAuthor;
34
18
  }
35
- /**
36
- * the reference of the commit
37
- */
19
+ /** The reference of the commit */
38
20
  interface Reference {
39
- /**
40
- * the reference type
41
- */
21
+ /** The reference type */
42
22
  type: 'hash' | 'issue' | 'pull-request';
43
- /**
44
- * the reference value
45
- */
23
+ /** The reference value */
46
24
  value: string;
47
25
  }
48
- /**
49
- * the resolved github author
50
- */
26
+ /** The resolved github author */
51
27
  interface ResolvedAuthor extends GitCommitAuthor {
52
- /**
53
- * the git commit of the author
54
- */
28
+ /** The git commit of the author */
55
29
  commits: string[];
56
- /**
57
- * the github logged username of the author
58
- */
30
+ /** The github logged username of the author */
59
31
  login: string;
60
32
  }
61
- /**
62
- * git commit config
63
- */
33
+ /** Git commit config */
64
34
  interface GitCommit extends RawGitCommit {
65
- /**
66
- * the commit description
67
- */
35
+ /** The commit description */
68
36
  description: string;
69
- /**
70
- * the commit scope type
71
- */
37
+ /** The commit scope type */
72
38
  type: string;
73
- /**
74
- * the commit scope
75
- */
39
+ /** The commit scope */
76
40
  scope: string;
77
- /**
78
- * the commit references
79
- */
41
+ /** The commit references */
80
42
  references: Reference[];
81
- /**
82
- * the commit authors
83
- */
43
+ /** The commit authors */
84
44
  authors: GitCommitAuthor[];
85
- /**
86
- * the resolved authors
87
- */
45
+ /** The resolved authors */
88
46
  resolvedAuthors: ResolvedAuthor[];
89
- /**
90
- * the commit breaking changes
91
- */
47
+ /** The commit breaking changes */
92
48
  isBreaking: boolean;
93
49
  }
94
- /**
95
- * github config
96
- */
50
+ /** Github config */
97
51
  interface GithubConfig {
98
52
  /**
99
- * the github repository name
100
- * @example soybeanjs/changelog
53
+ * The github repository name
54
+ *
55
+ * @example
56
+ * soybeanjs / changelog;
101
57
  */
102
58
  repo: string;
103
- /**
104
- * the github token
105
- */
59
+ /** The github token */
106
60
  token: string;
107
61
  }
108
62
  interface ChangelogOption {
109
63
  /**
110
- * the directory of the project
64
+ * The directory of the project
65
+ *
111
66
  * @default process.cwd()
112
67
  */
113
68
  cwd: string;
114
- /**
115
- * the commit scope types
116
- */
69
+ /** The commit scope types */
117
70
  types: Record<string, string>;
118
- /**
119
- * github config
120
- */
71
+ /** Github config */
121
72
  github: GithubConfig;
122
- /**
123
- * the commit hash or tag
124
- */
73
+ /** The commit hash or tag */
125
74
  from: string;
126
- /**
127
- * the commit hash or tag
128
- */
75
+ /** The commit hash or tag */
129
76
  to: string;
130
- /**
131
- * the whole commit tags
132
- */
77
+ /** The whole commit tags */
133
78
  tags: string[];
134
- /**
135
- * the commit tag and date map
136
- */
79
+ /** The commit tag and date map */
137
80
  tagDateMap: Map<string, string>;
138
- /**
139
- * Whether to capitalize the first letter of the commit type
140
- */
81
+ /** Whether to capitalize the first letter of the commit type */
141
82
  capitalize: boolean;
142
83
  /**
143
84
  * Use emojis in section titles
85
+ *
144
86
  * @default true
145
87
  */
146
88
  emoji: boolean;
147
- /**
148
- * the section titles
149
- */
89
+ /** The section titles */
150
90
  titles: {
151
- /**
152
- * the title of breaking changes section
153
- */
91
+ /** The title of breaking changes section */
154
92
  breakingChanges: string;
155
93
  };
156
- /**
157
- * the output file path of the changelog
158
- */
94
+ /** The output file path of the changelog */
159
95
  output: string;
160
96
  /**
161
97
  * Whether to regenerate the changelog if it already exists
162
- * @example the changelog already exists the content of v0.0.1, but you want to regenerate it
98
+ *
99
+ * @example
100
+ * the changelog already exists the content of v0.0.1, but you want to regenerate it
163
101
  */
164
102
  regenerate: boolean;
165
103
  /**
166
- * version from package.json, with prefix "v"
167
- * @description if the options "to" is not specified, the version will be used
104
+ * Version from package.json, with prefix "v"
105
+ *
106
+ * If the options "to" is not specified, the version will be used
168
107
  */
169
108
  newVersion: string;
170
- /**
171
- * Mark the release as prerelease
172
- */
109
+ /** Mark the release as prerelease */
173
110
  prerelease?: boolean;
174
111
  }
175
112
 
176
113
  /**
177
- * get the changelog markdown by two git tags
178
- * @param options the changelog options
179
- * @param showTitle whither show the title
114
+ * Get the changelog markdown by two git tags
115
+ *
116
+ * @param options The changelog options
117
+ * @param showTitle Whither show the title
180
118
  */
181
119
  declare function getChangelogMarkdown(options?: Partial<ChangelogOption>, showTitle?: boolean): Promise<{
182
120
  markdown: string;
@@ -184,20 +122,23 @@ declare function getChangelogMarkdown(options?: Partial<ChangelogOption>, showTi
184
122
  options: ChangelogOption;
185
123
  }>;
186
124
  /**
187
- * get the changelog markdown by the total git tags
188
- * @param options the changelog options
189
- * @param showProgress whither show the progress bar
125
+ * Get the changelog markdown by the total git tags
126
+ *
127
+ * @param options The changelog options
128
+ * @param showProgress Whither show the progress bar
190
129
  */
191
130
  declare function getTotalChangelogMarkdown(options?: Partial<ChangelogOption>, showProgress?: boolean): Promise<string>;
192
131
  /**
193
- * generate the changelog markdown by two git tags
194
- * @param options the changelog options
132
+ * Generate the changelog markdown by two git tags
133
+ *
134
+ * @param options The changelog options
195
135
  */
196
136
  declare function generateChangelog(options?: Partial<ChangelogOption>): Promise<void>;
197
137
  /**
198
- * generate the changelog markdown by the total git tags
199
- * @param options the changelog options
200
- * @param showProgress whither show the progress bar
138
+ * Generate the changelog markdown by the total git tags
139
+ *
140
+ * @param options The changelog options
141
+ * @param showProgress Whither show the progress bar
201
142
  */
202
143
  declare function generateTotalChangelog(options?: Partial<ChangelogOption>, showProgress?: boolean): Promise<void>;
203
144
 
package/dist/index.mjs CHANGED
@@ -1,19 +1,26 @@
1
- import{SingleBar as B,Presets as _}from"cli-progress";import{readFile as d,writeFile as N}from"fs/promises";import{ofetch as $}from"ofetch";import y from"dayjs";import{existsSync as S}from"fs";import{convert as I}from"convert-gitmoji";async function f(t,n,e){const{execa:o}=await import("execa");return(await o(t,n,e))?.stdout?.trim()||""}function z(t){return t!=null}function Y(t,...n){const e=new Array(n.length+1).fill(null).map(()=>[]);return t.forEach((o,a,s)=>{let r=0;for(const i of n){if(i(o,a,s)){e[r].push(o);return}r+=1}e[r].push(o)}),e}function F(t,n,e={}){for(const o of t){const a=o[n];e[a]=e[a]||[],e[a].push(o)}return e}function q(t){return t.charAt(0).toUpperCase()+t.slice(1)}function E(t,n=", ",e=" and "){return!t||t.length===0?"":t.length===1?t[0]:t.length===2?t.join(e):`${t.slice(0,-1).join(n)}${e}${t.slice(-1)}`}const v=/v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/,L=/## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g,P=/release\sv\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;async function D(){return(await f("git",["--no-pager","tag","-l","--sort=creatordate"])).split(`
2
- `)}async function U(){const t=await f("git",["--no-pager","log","--tags","--simplify-by-decoration","--pretty=format:%ci %d"]),n="tag: ",e=new Map;return t.split(`
3
- `).filter(o=>o.includes(n)).forEach(o=>{const[a,s]=o.split(n),r=y(a).format("YYYY-MM-DD"),i=s.match(v)?.[0];i&&r&&e.set(i.trim(),r)}),e}function W(t){const n=[];return t.forEach((e,o)=>{o<t.length-1&&n.push({from:e,to:t[o+1]})}),n}async function C(t=0){const n=await D();return n[n.length+t-1]}async function K(){return await f("git",["rev-parse","--abbrev-ref","HEAD"])}async function J(){const t=await f("git",["tag","--points-at","HEAD"]),n=K();return t||n}async function Q(){const t=await f("git",["config","--get","remote.origin.url"]),n=t.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);if(!n)throw new Error(`Can not parse GitHub repo from url ${t}`);return`${n[1]}/${n[2]}`}function X(t){return!/^[^.]*[\d.]+$/.test(t)}function Z(){return f("git",["rev-list","--max-parents=0","HEAD"])}async function tt(t,n="HEAD"){return(await f("git",["--no-pager","log",`${t?`${t}...`:""}${n}`,'--pretty="----%n%s|%h|%an|%ae%n%b"',"--name-status"])).split(`----
4
- `).splice(1).map(e=>{const[o,...a]=e.split(`
5
- `),[s,r,i,p]=o.split("|");return{message:s,shortHash:r,author:{name:i,email:p},body:a.join(`
6
- `)}})}function et(t){const n=/(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i,e=/co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim,o=/\([a-z]*(#\d+)\s*\)/gm,a=/(#\d+)/gm,s=t.message.match(n);if(!s?.groups)return null;const r=s.groups.type,i=s.groups.scope||"",p=!!s.groups.breaking;let g=s.groups.description;const c=[];for(const l of g.matchAll(o))c.push({type:"pull-request",value:l[1]});for(const l of g.matchAll(a))c.some(h=>h.value===l[1])||c.push({type:"issue",value:l[1]});c.push({value:t.shortHash,type:"hash"}),g=g.replace(o,"").trim();const m=[t.author],u=t.body.matchAll(e);for(const l of u){const{name:h="",email:R=""}=l.groups||{},V={name:h.trim(),email:R.trim()};m.push(V)}return{...t,authors:m,resolvedAuthors:[],description:g,type:r,scope:i,references:c,isBreaking:p}}async function A(t,n="HEAD"){return(await tt(t,n)).map(e=>et(e)).filter(z)}function k(t){return{accept:"application/vnd.github.v3+json",authorization:`token ${t}`}}async function nt(t,n,e){let o="";try{o=(await $(`https://ungh.cc/users/find/${e}`))?.user?.username||""}catch(r){console.log("e: ",r)}if(o)return o;const{repo:a,token:s}=t;if(!s)return o;if(n.length)try{o=(await $(`https://api.github.com/repos/${a}/commits/${n[0]}`,{headers:k(s)}))?.author?.login||""}catch(r){console.log("e: ",r)}if(o)return o;try{o=(await $(`https://api.github.com/search/users?q=${encodeURIComponent(e)}`,{headers:k(s)})).items[0].login}catch(r){console.log("e: ",r)}return o}async function M(t,n,e){const o=[],a=new Map;for await(const s of t){const r=[];for await(const[p,g]of s.authors.entries()){const{email:c,name:m}=g;if(c&&m){const u=[];p===0&&u.push(s.shortHash);const l={name:m,email:c,commits:u,login:""};if(e?.has(c)){const h=e?.get(c)||"";l.login=h}else{const h=await nt(n,u,c);l.login=h,e?.set(c,h)}r.push(l),a.has(c)||a.set(c,l)}}const i={...s,resolvedAuthors:r};o.push(i)}return{commits:o,contributors:Array.from(a.values())}}function ot(){return{cwd:process.cwd(),types:{feat:"\u{1F680} Features",fix:"\u{1F41E} Bug Fixes",perf:"\u{1F525} Performance",refactor:"\u{1F485} Refactors",docs:"\u{1F4D6} Documentation",build:"\u{1F4E6} Build",types:"\u{1F30A} Types",chore:"\u{1F3E1} Chore",examples:"\u{1F3C0} Examples",test:"\u2705 Tests",style:"\u{1F3A8} Styles",ci:"\u{1F916} CI"},github:{repo:"",token:process.env.GITHUB_TOKEN||""},from:"",to:"",tags:[],tagDateMap:new Map,capitalize:!1,emoji:!0,titles:{breakingChanges:"\u{1F6A8} Breaking Changes"},output:"CHANGELOG.md",regenerate:!1,newVersion:""}}async function st(t){let n="";try{const e=await d(`${t}/package.json`,"utf-8");n=JSON.parse(e)?.version||""}catch{}return{newVersion:n}}async function w(t){var n;const e=ot();Object.assign(e,t);const{newVersion:o}=await st(e.cwd);if((n=e.github).repo||(n.repo=await Q()),e.newVersion||(e.newVersion=`v${o}`),e.from||(e.from=await C()),e.to||(e.to=await J()),e.to===e.from){const a=await C(-1),s=await Z();e.from=a||s}return e.tags=await D(),e.tagDateMap=await U(),e.prerelease=e.prerelease??X(e.to),e}function T(t,n,e){const o=t.filter(s=>e==="issues"?s.type==="issue"||s.type==="pull-request":s.type==="hash").map(s=>n?s.type==="pull-request"||s.type==="issue"?`https://github.com/${n}/issues/${s.value.slice(1)}`:`[<samp>(${s.value.slice(0,5)})</samp>](https://github.com/${n}/commit/${s.value})`:s.value),a=E(o).trim();return e==="issues"?a&&`in ${a}`:a}function at(t,n){const e=T(t.references,n.github.repo,"issues"),o=T(t.references,n.github.repo,"hash");let a=E([...new Set(t.resolvedAuthors.map(r=>r.login?`@${r.login}`:`**${r.name}**`))]).trim();a&&(a=`by ${a}`);let s=[a,e,o].filter(r=>r?.trim()).join(" ");return s&&(s=`&nbsp;-&nbsp; ${s}`),[n.capitalize?q(t.description):t.description,s].filter(r=>r?.trim()).join(" ")}function rt(t,n){const e=/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;let o=t.trim();return n.emoji||(o=t.replace(e,"").trim()),`### &nbsp;&nbsp;&nbsp;${o}`}function G(t,n,e){if(!t.length)return[];const o=["",rt(n,e),""],a=F(t,"scope");let s=!0;return Object.entries(a).some(([r,i])=>r&&i.length>1)||(s=!1),Object.keys(a).sort().forEach(r=>{let i="",p="";const g=`**${r}**`;r&&s?(o.push(`- ${g}:`),i=" "):r&&(p=`${g}: `),o.push(...a[r].reverse().map(c=>`${i}- ${p}${at(c,e)}`))}),o}function j(t){return`https://github.com/${t}`}function it(t){return`${j(t)}.png?size=48`}function ct(t){let n="",e="";return t.forEach((o,a)=>{const{name:s,email:r,login:i}=o;if(i){const p=j(i),g=it(i);n+=`[![${i}](${g})](${p})&nbsp;&nbsp;`}else{let p=`[${s}](mailto:${r})`;a<t.length-1&&(p+=",&nbsp;"),e+=p}}),`${n}
7
- ${e}`}function H(t){const{options:n,showTitle:e,contributors:o}=t,a=t.commits.filter(u=>u.description.match(P)===null),s=[],r=!v.test(n.to),i=r?n.newVersion:n.to,p=`https://github.com/${n.github.repo}/compare/${n.from}...${i}`;if(e){const u=r?y().format("YY-MM-DD"):n.tagDateMap.get(n.to);let l=`## [${i}](${p})`;u&&(l+=` (${u})`),s.push(l)}const[g,c]=Y(a,u=>u.isBreaking),m=F(c,"type");s.push(...G(g,n.titles.breakingChanges,n));for(const u of Object.keys(n.types)){const l=m[u]||[];s.push(...G(l,n.types[u],n))}if(s.length||s.push("*No significant changes*"),e||s.push("",`##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](${p})`),e){s.push("","### &nbsp;&nbsp;&nbsp;\u2764\uFE0F Contributors","");const u=ct(o);s.push(u)}return I(s.join(`
8
- `).trim(),!0)}async function ut(t,n){let e=!1;const o=await d(n,"utf8");if(o){const a=o.match(L);if(a?.length){const s=`## [${t}]`;e=a.includes(s)}}return e}async function x(t,n,e=!1){let o;const a="# Changelog";!e&&S(n)?(o=await d(n,"utf8"),o.startsWith(a)||(o=`${a}
1
+ import{SingleBar as W,Presets as J}from"cli-progress";import A from"node:process";import{readFile as _,writeFile as E}from"node:fs/promises";import{ofetch as b}from"ofetch";import D from"dayjs";import{existsSync as K}from"node:fs";import{convert as Q}from"convert-gitmoji";const g={silent:Number.NEGATIVE_INFINITY,fatal:0,error:0,warn:1,log:2,info:3,success:3,fail:3,ready:3,start:3,box:3,debug:4,trace:5,verbose:Number.POSITIVE_INFINITY},T={silent:{level:-1},fatal:{level:g.fatal},error:{level:g.error},warn:{level:g.warn},log:{level:g.log},info:{level:g.info},success:{level:g.success},fail:{level:g.fail},ready:{level:g.info},start:{level:g.info},box:{level:g.info},debug:{level:g.debug},trace:{level:g.trace},verbose:{level:g.verbose}};function v(o){return o!==null&&typeof o=="object"}function $(o,t,e=".",s){if(!v(t))return $(o,{},e,s);const r=Object.assign({},t);for(const n in o){if(n==="__proto__"||n==="constructor")continue;const i=o[n];i!=null&&(s&&s(r,n,i,e)||(Array.isArray(i)&&Array.isArray(r[n])?r[n]=[...i,...r[n]]:v(i)&&v(r[n])?r[n]=$(i,r[n],(e?`${e}.`:"")+n.toString(),s):r[n]=i))}return r}function X(o){return(...t)=>t.reduce((e,s)=>$(e,s,"",o),{})}const Z=X();function tt(o){return Object.prototype.toString.call(o)==="[object Object]"}function et(o){return!(!tt(o)||!o.message&&!o.args||o.stack)}let F=!1;const M=[];class f{constructor(t={}){const e=t.types||T;this.options=Z({...t,defaults:{...t.defaults},level:C(t.level,e),reporters:[...t.reporters||[]]},{types:T,throttle:1e3,throttleMin:5,formatOptions:{date:!0,colors:!1,compact:!0}});for(const s in e){const r={type:s,...this.options.defaults,...e[s]};this[s]=this._wrapLogFn(r),this[s].raw=this._wrapLogFn(r,!0)}this.options.mockFn&&this.mockTypes(),this._lastLog={}}get level(){return this.options.level}set level(t){this.options.level=C(t,this.options.types,this.options.level)}prompt(t,e){if(!this.options.prompt)throw new Error("prompt is not supported!");return this.options.prompt(t,e)}create(t){const e=new f({...this.options,...t});return this._mockFn&&e.mockTypes(this._mockFn),e}withDefaults(t){return this.create({...this.options,defaults:{...this.options.defaults,...t}})}withTag(t){return this.withDefaults({tag:this.options.defaults.tag?this.options.defaults.tag+":"+t:t})}addReporter(t){return this.options.reporters.push(t),this}removeReporter(t){if(t){const e=this.options.reporters.indexOf(t);if(e>=0)return this.options.reporters.splice(e,1)}else this.options.reporters.splice(0);return this}setReporters(t){return this.options.reporters=Array.isArray(t)?t:[t],this}wrapAll(){this.wrapConsole(),this.wrapStd()}restoreAll(){this.restoreConsole(),this.restoreStd()}wrapConsole(){for(const t in this.options.types)console["__"+t]||(console["__"+t]=console[t]),console[t]=this[t].raw}restoreConsole(){for(const t in this.options.types)console["__"+t]&&(console[t]=console["__"+t],delete console["__"+t])}wrapStd(){this._wrapStream(this.options.stdout,"log"),this._wrapStream(this.options.stderr,"log")}_wrapStream(t,e){t&&(t.__write||(t.__write=t.write),t.write=s=>{this[e].raw(String(s).trim())})}restoreStd(){this._restoreStream(this.options.stdout),this._restoreStream(this.options.stderr)}_restoreStream(t){t&&t.__write&&(t.write=t.__write,delete t.__write)}pauseLogs(){F=!0}resumeLogs(){F=!1;const t=M.splice(0);for(const e of t)e[0]._logFn(e[1],e[2])}mockTypes(t){const e=t||this.options.mockFn;if(this._mockFn=e,typeof e=="function")for(const s in this.options.types)this[s]=e(s,this.options.types[s])||this[s],this[s].raw=this[s]}_wrapLogFn(t,e){return(...s)=>{if(F){M.push([this,t,s,e]);return}return this._logFn(t,s,e)}}_logFn(t,e,s){if((t.level||0)>this.level)return!1;const r={date:new Date,args:[],...t,level:C(t.level,this.options.types)};!s&&e.length===1&&et(e[0])?Object.assign(r,e[0]):r.args=[...e],r.message&&(r.args.unshift(r.message),delete r.message),r.additional&&(Array.isArray(r.additional)||(r.additional=r.additional.split(`
2
+ `)),r.args.push(`
3
+ `+r.additional.join(`
4
+ `)),delete r.additional),r.type=typeof r.type=="string"?r.type.toLowerCase():"log",r.tag=typeof r.tag=="string"?r.tag:"";const n=(a=!1)=>{const c=(this._lastLog.count||0)-this.options.throttleMin;if(this._lastLog.object&&c>0){const l=[...this._lastLog.object.args];c>1&&l.push(`(repeated ${c} times)`),this._log({...this._lastLog.object,args:l}),this._lastLog.count=1}a&&(this._lastLog.object=r,this._log(r))};clearTimeout(this._lastLog.timeout);const i=this._lastLog.time&&r.date?r.date.getTime()-this._lastLog.time.getTime():0;if(this._lastLog.time=r.date,i<this.options.throttle)try{const a=JSON.stringify([r.type,r.tag,r.args]),c=this._lastLog.serialized===a;if(this._lastLog.serialized=a,c&&(this._lastLog.count=(this._lastLog.count||0)+1,this._lastLog.count>this.options.throttleMin)){this._lastLog.timeout=setTimeout(n,this.options.throttle);return}}catch{}n(!0)}_log(t){for(const e of this.options.reporters)e.log(t,{options:this.options})}}function C(o,t={},e=3){return o===void 0?e:typeof o=="number"?o:t[o]&&t[o].level!==void 0?t[o].level:e}f.prototype.add=f.prototype.addReporter,f.prototype.remove=f.prototype.removeReporter,f.prototype.clear=f.prototype.removeReporter,f.prototype.withScope=f.prototype.withTag,f.prototype.mock=f.prototype.mockTypes,f.prototype.pause=f.prototype.pauseLogs,f.prototype.resume=f.prototype.resumeLogs;function ot(o={}){return new f(o)}class st{constructor(t){this.options={...t},this.defaultColor="#7f8c8d",this.levelColorMap={0:"#c0392b",1:"#f39c12",3:"#00BCD4"},this.typeColorMap={success:"#2ecc71"}}_getLogFn(t){return t<1?console.__error||console.error:t===1?console.__warn||console.warn:console.__log||console.log}log(t){const e=this._getLogFn(t.level),s=t.type==="log"?"":t.type,r=t.tag||"",i=`
5
+ background: ${this.typeColorMap[t.type]||this.levelColorMap[t.level]||this.defaultColor};
6
+ border-radius: 0.5em;
7
+ color: white;
8
+ font-weight: bold;
9
+ padding: 2px 0.5em;
10
+ `,a=`%c${[r,s].filter(Boolean).join(":")}`;typeof t.args[0]=="string"?e(`${a}%c ${t.args[0]}`,i,"",...t.args.slice(1)):e(a,i,...t.args)}}function rt(o={}){return ot({reporters:o.reporters||[new st({})],prompt(e,s={}){return s.type==="confirm"?Promise.resolve(confirm(e)):Promise.resolve(prompt(e))},...o})}const L=rt();async function w(o,t,e){const{execa:s}=await import("execa");return(await s(o,t,e))?.stdout?.trim()||""}function nt(o){return o!=null}function it(o,...t){const e=Array.from({length:t.length+1}).fill(null).map(()=>[]);return o.forEach((s,r,n)=>{let i=0;for(const a of t){if(a(s,r,n)){e[i].push(s);return}i+=1}e[i].push(s)}),e}function S(o,t,e={}){for(const s of o){const r=s[t];e[r]||(e[r]=[]),e[r].push(s)}return e}function at(o){return o.charAt(0).toUpperCase()+o.slice(1)}function j(o,t=", ",e=" and "){return!o||o.length===0?"":o.length===1?o[0]:o.length===2?o.join(e):`${o.slice(0,-1).join(t)}${e}${o.slice(-1)}`}const x=/v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/,ct=/## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g,lt=/release\sv\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;async function I(){return(await w("git",["--no-pager","tag","-l","--sort=creatordate"])).split(`
11
+ `)}async function ut(){const o=await w("git",["--no-pager","log","--tags","--simplify-by-decoration","--pretty=format:%ci %d"]),t="tag: ",e=new Map;return o.split(`
12
+ `).filter(s=>s.includes(t)).forEach(s=>{const[r,n]=s.split(t),i=D(r).format("YYYY-MM-DD"),a=n.match(x)?.[0];a&&i&&e.set(a.trim(),i)}),e}function pt(o){const t=[];return o.forEach((e,s)=>{s<o.length-1&&t.push({from:e,to:o[s+1]})}),t}async function N(o=0){const t=await I();return t[t.length+o-1]}async function ht(){return await w("git",["rev-parse","--abbrev-ref","HEAD"])}async function ft(){const o=await w("git",["tag","--points-at","HEAD"]),t=ht();return o||t}async function gt(){const o=await w("git",["config","--get","remote.origin.url"]),t=o.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);if(!t)throw new Error(`Can not parse GitHub repo from url ${o}`);return`${t[1]}/${t[2]}`}function mt(o){return!/^[^.]*[\d.]+$/.test(o)}function dt(){return w("git",["rev-list","--max-parents=0","HEAD"])}async function wt(o,t="HEAD"){return(await w("git",["--no-pager","log",`${o?`${o}...`:""}${t}`,'--pretty="----%n%s|%h|%an|%ae%n%b"',"--name-status"])).split(`----
13
+ `).splice(1).map(e=>{const[s,...r]=e.split(`
14
+ `),[n,i,a,c]=s.split("|");return{message:n,shortHash:i,author:{name:a,email:c},body:r.join(`
15
+ `)}})}function yt(o){const t=/(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i,e=/co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim,s=/\([a-z]*(#\d+)\s*\)/gm,r=/(#\d+)/gm,n=o.message.match(t);if(!n?.groups)return null;const i=n.groups.type,a=n.groups.scope||"",c=!!n.groups.breaking;let l=n.groups.description;const u=[];for(const h of l.matchAll(s))u.push({type:"pull-request",value:h[1]});for(const h of l.matchAll(r))u.some(d=>d.value===h[1])||u.push({type:"issue",value:h[1]});u.push({value:o.shortHash,type:"hash"}),l=l.replace(s,"").trim();const m=[o.author],p=o.body.matchAll(e);for(const h of p){const{name:d="",email:q=""}=h.groups||{},U={name:d.trim(),email:q.trim()};m.push(U)}return{...o,authors:m,resolvedAuthors:[],description:l,type:i,scope:a,references:u,isBreaking:c}}async function R(o,t="HEAD"){return(await wt(o,t)).map(e=>yt(e)).filter(nt)}function G(o){return{accept:"application/vnd.github.v3+json",authorization:`token ${o}`}}async function _t(o,t,e){let s="";try{s=(await b(`https://ungh.cc/users/find/${e}`))?.user?.username||""}catch(i){L.log("e: ",i)}if(s)return s;const{repo:r,token:n}=o;if(!n)return s;if(t.length)try{s=(await b(`https://api.github.com/repos/${r}/commits/${t[0]}`,{headers:G(n)}))?.author?.login||""}catch(i){L.log("e: ",i)}if(s)return s;try{s=(await b(`https://api.github.com/search/users?q=${encodeURIComponent(e)}`,{headers:G(n)})).items[0].login}catch(i){L.log("e: ",i)}return s}async function H(o,t,e){const s=[],r=new Map;for await(const n of o){const i=[];for await(const[c,l]of n.authors.entries()){const{email:u,name:m}=l;if(u&&m){const p=[];c===0&&p.push(n.shortHash);const h={name:m,email:u,commits:p,login:""};if(e?.has(u)){const d=e?.get(u)||"";h.login=d}else{const d=await _t(t,p,u);h.login=d,e?.set(u,d)}i.push(h),r.has(u)||r.set(u,h)}}const a={...n,resolvedAuthors:i};s.push(a)}return{commits:s,contributors:Array.from(r.values())}}function bt(){return{cwd:A.cwd(),types:{feat:"\u{1F680} Features",fix:"\u{1F41E} Bug Fixes",perf:"\u{1F525} Performance",refactor:"\u{1F485} Refactors",docs:"\u{1F4D6} Documentation",build:"\u{1F4E6} Build",types:"\u{1F30A} Types",chore:"\u{1F3E1} Chore",examples:"\u{1F3C0} Examples",test:"\u2705 Tests",style:"\u{1F3A8} Styles",ci:"\u{1F916} CI"},github:{repo:"",token:A.env.GITHUB_TOKEN||""},from:"",to:"",tags:[],tagDateMap:new Map,capitalize:!1,emoji:!0,titles:{breakingChanges:"\u{1F6A8} Breaking Changes"},output:"CHANGELOG.md",regenerate:!1,newVersion:""}}async function vt(o){let t="";try{const e=await _(`${o}/package.json`,"utf-8");t=JSON.parse(e)?.version||""}catch{}return{newVersion:t}}async function y(o){var t;const e=bt();Object.assign(e,o);const{newVersion:s}=await vt(e.cwd);if((t=e.github).repo||(t.repo=await gt()),e.newVersion||(e.newVersion=`v${s}`),e.from||(e.from=await N()),e.to||(e.to=await ft()),e.to===e.from){const r=await N(-1),n=await dt();e.from=r||n}return e.tags=await I(),e.tagDateMap=await ut(),e.prerelease||(e.prerelease=mt(e.to)),e}function O(o,t,e){const s=o.filter(n=>e==="issues"?n.type==="issue"||n.type==="pull-request":n.type==="hash").map(n=>t?n.type==="pull-request"||n.type==="issue"?`https://github.com/${t}/issues/${n.value.slice(1)}`:`[<samp>(${n.value.slice(0,5)})</samp>](https://github.com/${t}/commit/${n.value})`:n.value),r=j(s).trim();return e==="issues"?r&&`in ${r}`:r}function $t(o,t){const e=O(o.references,t.github.repo,"issues"),s=O(o.references,t.github.repo,"hash");let r=j([...new Set(o.resolvedAuthors.map(i=>i.login?`@${i.login}`:`**${i.name}**`))]).trim();r&&(r=`by ${r}`);let n=[r,e,s].filter(i=>i?.trim()).join(" ");return n&&(n=`&nbsp;-&nbsp; ${n}`),[t.capitalize?at(o.description):o.description,n].filter(i=>i?.trim()).join(" ")}function Ft(o,t){const e=/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;let s=o.trim();return t.emoji||(s=o.replace(e,"").trim()),`### &nbsp;&nbsp;&nbsp;${s}`}function B(o,t,e){if(!o.length)return[];const s=["",Ft(t,e),""],r=S(o,"scope");let n=!0;return Object.entries(r).some(([i,a])=>i&&a.length>1)||(n=!1),Object.keys(r).sort().forEach(i=>{let a="",c="";const l=`**${i}**`;i&&n?(s.push(`- ${l}:`),a=" "):i&&(c=`${l}: `),s.push(...r[i].reverse().map(u=>`${a}- ${c}${$t(u,e)}`))}),s}function V(o){return`https://github.com/${o}`}function Ct(o){return`${V(o)}.png?size=48`}function Lt(o){let t="",e="";const s=new Map;return o.forEach(r=>{s.set(r.email,r)}),Array.from(s.values()).forEach((r,n)=>{const{name:i,email:a,login:c}=r;if(c){const l=V(c),u=Ct(c);t+=`[![${c}](${u})](${l})&nbsp;&nbsp;`}else{let l=`[${i}](mailto:${a})`;n<o.length-1&&(l+=",&nbsp;"),e+=l}}),`${t}
16
+ ${e}`}function z(o){const{options:t,showTitle:e,contributors:s}=o,r=o.commits.filter(p=>p.description.match(lt)===null),n=[],i=!x.test(t.to),a=i?t.newVersion:t.to,c=`https://github.com/${t.github.repo}/compare/${t.from}...${a}`;if(e){const p=i?D().format("YY-MM-DD"):t.tagDateMap.get(t.to);let h=`## [${a}](${c})`;p&&(h+=` (${p})`),n.push(h)}const[l,u]=it(r,p=>p.isBreaking),m=S(u,"type");n.push(...B(l,t.titles.breakingChanges,t));for(const p of Object.keys(t.types)){const h=m[p]||[];n.push(...B(h,t.types[p],t))}if(n.length||n.push("*No significant changes*"),e||n.push("",`##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](${c})`),e){n.push("","### &nbsp;&nbsp;&nbsp;\u2764\uFE0F Contributors","");const p=Lt(s);n.push(p)}return Q(n.join(`
17
+ `).trim(),!0)}async function kt(o,t){let e=!1;const s=await _(t,"utf8");if(s){const r=s.match(ct);if(r?.length){const n=`## [${o}]`;e=r.includes(n)}}return e}async function Y(o,t,e=!1){let s="";const r="# Changelog";K(t)||await E(t,r,"utf8"),e||(s=await _(t,"utf8")),s.startsWith(r)||(s=`${r}
9
18
 
10
- ${o}`)):o=`${a}
19
+ ${s}`);const n=s.match(/^###?\s+.*$/m);n?s+=`${s.slice(0,n.index)+o}
11
20
 
12
- `;const s=o.match(/^###?\s+.*$/m);s?o=`${o.slice(0,s.index)+t}
21
+ ${s.slice(n.index)}`:s+=`
22
+ ${o}
13
23
 
14
- ${o.slice(s.index)}`:o+=`
15
- ${t}
24
+ `,await E(t,s)}async function k(o,t=!0){const e=await y(o),s=await R(e.from,e.to),{commits:r,contributors:n}=await H(s,e.github);return{markdown:z({commits:r,options:e,showTitle:t,contributors:n}),commits:r,options:e}}async function P(o,t=!0){const e=await y(o);let s=null;t&&(s=new W({format:"generate total changelog: [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}"},J.shades_classic));const r=pt(e.tags);if(r.length===0){const{markdown:a}=await k(e);return a}s?.start(r.length,0);let n="";const i=new Map;for await(const[a,c]of r.entries()){const{from:l,to:u}=c,m=await R(l,u),{commits:p,contributors:h}=await H(m,e.github,i);n=`${z({commits:p,options:{...e,from:l,to:u},showTitle:!0,contributors:h})}
16
25
 
17
- `,await N(n,o)}async function b(t,n=!0){const e=await w(t),o=await A(e.from,e.to),{commits:a,contributors:s}=await M(o,e.github);return{markdown:H({commits:a,options:e,showTitle:n,contributors:s}),commits:a,options:e}}async function O(t,n=!0){const e=await w(t);let o=null;n&&(o=new B({format:"generate total changelog: [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}"},_.shades_classic));const a=W(e.tags);if(a.length===0){const{markdown:i}=await b(e);return i}o?.start(a.length,0);let s="";const r=new Map;for await(const[i,p]of a.entries()){const{from:g,to:c}=p,m=await A(g,c),{commits:u,contributors:l}=await M(m,e.github,r);s=`${H({commits:u,options:{...e,from:g,to:c},showTitle:!0,contributors:l})}
18
-
19
- ${s}`,o?.update(i+1)}return o?.stop(),s}async function pt(t){const n=await w(t),e=await ut(n.to,n.output);if(!n.regenerate&&e)return;const{markdown:o}=await b(n);await x(o,n.output,n.regenerate)}async function lt(t,n=!0){const e=await w(t),o=await O(e,n);await x(o,e.output,!0)}export{pt as generateChangelog,lt as generateTotalChangelog,b as getChangelogMarkdown,O as getTotalChangelogMarkdown};
26
+ ${n}`,s?.update(a+1)}return s?.stop(),n}async function At(o){const t=await y(o),e=await kt(t.to,t.output);if(!t.regenerate&&e)return;const{markdown:s}=await k(t);await Y(s,t.output,t.regenerate)}async function Et(o,t=!0){const e=await y(o),s=await P(e,t);await Y(s,e.output,!0)}export{At as generateChangelog,Et as generateTotalChangelog,k as getChangelogMarkdown,P as getTotalChangelogMarkdown};
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@soybeanjs/changelog",
3
- "version": "0.3.3",
3
+ "type": "module",
4
+ "version": "0.3.5",
5
+ "packageManager": "pnpm@8.12.0",
4
6
  "description": "generate changelog form git tags and commits for github",
5
7
  "author": {
6
8
  "name": "Soybean",
7
- "email": "honghuangdc@gmail.com",
8
- "url": "https://github.com/honghuangdc"
9
+ "email": "soybeanjs@outlook.com",
10
+ "url": "https://github.com/soybeanjs"
9
11
  },
10
12
  "license": "MIT",
11
13
  "homepage": "https://github.com/soybeanjs/changelog",
@@ -18,11 +20,12 @@
18
20
  "publishConfig": {
19
21
  "registry": "https://registry.npmjs.org/"
20
22
  },
23
+ "sideEffects": false,
21
24
  "exports": {
22
25
  ".": {
26
+ "types": "./dist/index.d.ts",
23
27
  "import": "./dist/index.mjs",
24
- "require": "./dist/index.cjs",
25
- "types": "./dist/index.d.ts"
28
+ "require": "./dist/index.cjs"
26
29
  }
27
30
  },
28
31
  "main": "./dist/index.cjs",
@@ -32,38 +35,41 @@
32
35
  "dist"
33
36
  ],
34
37
  "dependencies": {
38
+ "@soybeanjs/eslint-config": "^1.0.9",
35
39
  "cli-progress": "3.12.0",
36
40
  "convert-gitmoji": "0.1.3",
37
- "dayjs": "1.11.9",
41
+ "dayjs": "1.11.10",
38
42
  "execa": "8.0.1",
39
- "ofetch": "1.2.1"
43
+ "ofetch": "1.3.3"
40
44
  },
41
45
  "devDependencies": {
42
- "@soybeanjs/cli": "0.7.1",
43
- "@types/cli-progress": "3.11.0",
44
- "@types/node": "20.5.3",
45
- "eslint": "8.47.0",
46
- "eslint-config-soybeanjs": "0.5.6",
46
+ "@soybeanjs/cli": "0.8.8",
47
+ "@types/cli-progress": "3.11.5",
48
+ "@types/node": "20.10.4",
49
+ "eslint": "8.55.0",
50
+ "lint-staged": "15.2.0",
47
51
  "simple-git-hooks": "2.9.0",
48
- "tsx": "3.12.7",
49
- "typescript": "5.1.6",
52
+ "tsx": "4.6.2",
53
+ "typescript": "5.3.3",
50
54
  "unbuild": "2.0.0"
51
55
  },
52
56
  "simple-git-hooks": {
53
57
  "commit-msg": "pnpm soy git-commit-verify",
54
- "pre-commit": "pnpm typecheck && pnpm soy lint-staged"
58
+ "pre-commit": "pnpm typecheck && pnpm lint-staged"
59
+ },
60
+ "lint-staged": {
61
+ "*": "eslint --fix"
55
62
  },
56
63
  "scripts": {
57
- "build": "pnpm typecheck && unbuild && pnpm build-pkg",
64
+ "build": "unbuild && pnpm build-pkg",
58
65
  "build-pkg": "pnpm -r --filter='./packages/*' run build",
59
- "stub": "pnpm unbuild --stub",
60
- "lint": "eslint . --fix",
61
- "format": "soy prettier-write",
62
- "commit": "soy git-commit",
63
66
  "cleanup": "soy cleanup",
64
- "ncu": "soy ncu",
67
+ "commit": "soy git-commit",
68
+ "lint": "eslint . --fix",
65
69
  "publish-pkg": "pnpm -r publish --access public",
70
+ "release": "soy release",
71
+ "stub": "pnpm unbuild --stub",
66
72
  "typecheck": "tsc --noEmit --skipLibCheck",
67
- "release": "soy release && pnpm build && pnpm publish-pkg"
73
+ "update-pkg": "soy ncu"
68
74
  }
69
75
  }