@@ -109,13 +109,7 @@ function findVersionHeading(lines: string[], version: string): {index: number, l
109109 return null;
110110}
111111
112- // Lenient about heading shape: matches "# 1.2.3", "## v1.2.3", "## [1.2.3]",
113- // "## [1.2.3] - 2024-01-15", "## 1.2.3 (2024-01-15)", etc.
114- export function readChangelogEntry(content: string, version: string): string | null {
115- const lines = content.split(reNewline);
116- const head = findVersionHeading(lines, version);
117- if (!head) return null;
118-
112+ function extractEntry(lines: string[], head: {index: number, level: number}): string | null {
119113 let end = lines.length;
120114 for (let i = head.index + 1; i < lines.length; i++) {
121115 const m = reHeading.exec(lines[i]);
@@ -124,26 +118,46 @@ export function readChangelogEntry(content: string, version: string): string | n
124118 break;
125119 }
126120 }
127-
128121 return lines.slice(head.index + 1, end).join("\n").trim() || null;
129122}
130123
131- export function updateChangelogHeadingDate(content: string, version: string, date: string): string | null {
132- const lines = content.split(reNewline);
133- const head = findVersionHeading(lines, version);
134- if (!head) return null;
135-
136- const heading = lines[head.index];
124+ function updateHeadingDateInLines(lines: string[], index: number, date: string): string | null {
125+ const heading = lines[index];
137126 if (rePlaceholderDate.test(heading)) {
138- lines[head. index] = heading.replace(rePlaceholderDate, date);
127+ lines[index] = heading.replace(rePlaceholderDate, date);
139128 } else if (reDate.test(heading)) {
140129 return null;
141130 } else {
142- lines[head. index] = ` $ { heading . trimEnd ( ) } - $ { date} `;
131+ lines[index] = ` $ { heading . trimEnd ( ) } - $ { date} `;
143132 }
144133 return lines.join("\n");
145134}
146135
136+ // Lenient about heading shape: matches "# 1.2.3", "## v1.2.3", "## [1.2.3]",
137+ // "## [1.2.3] - 2024-01-15", "## 1.2.3 (2024-01-15)", etc.
138+ export function readChangelogEntry(content: string, version: string): string | null {
139+ const lines = content.split(reNewline);
140+ const head = findVersionHeading(lines, version);
141+ if (!head) return null;
142+ return extractEntry(lines, head);
143+ }
144+
145+ export function updateChangelogHeadingDate(content: string, version: string, date: string): string | null {
146+ const lines = content.split(reNewline);
147+ const head = findVersionHeading(lines, version);
148+ if (!head) return null;
149+ return updateHeadingDateInLines(lines, head.index, date);
150+ }
151+
152+ function processChangelog(content: string, version: string, date: string): {entry: string, updated: string | null} | null {
153+ const lines = content.split(reNewline);
154+ const head = findVersionHeading(lines, version);
155+ if (!head) return null;
156+ const entry = extractEntry(lines, head);
157+ if (!entry) return null;
158+ return {entry, updated: updateHeadingDateInLines(lines, head.index, date)};
159+ }
160+
147161export async function removeIgnoredFiles(files: Array<string>, cwd?: string): Promise<Array<string>> {
148162 let result: Result;
149163 try {
@@ -163,12 +177,12 @@ export type GetFileChangesOpts = {
163177 date?: string,
164178};
165179
166- export function getFileChanges({file, baseVersion, newVersion, replacements, date}: GetFileChangesOpts): [string, string | null, string | null] {
180+ export function getFileChanges({file, baseVersion, newVersion, replacements, date}: GetFileChangesOpts): [string | null, string | null] {
167181 const fileName = basename(file);
168182
169183 // unhandled lockfiles: blind search-and-replace would corrupt dependency versions
170184 if ((/lock/i.test(fileName) || fileName === "go.sum") && fileName !== "package-lock.json" && fileName !== "uv.lock") {
171- return [file, null, null];
185+ return [null, null];
172186 }
173187
174188 const oldData = readFileSync(file, "utf8");
@@ -207,7 +221,7 @@ export function getFileChanges({file, baseVersion, newVersion, replacements, dat
207221 }
208222 }
209223
210- return [ file , newData , oldData ] ;
224+ return [ newData , oldData ] ;
211225}
212226
213227export function write ( file : string , content : string ) : void {
@@ -600,9 +614,9 @@ async function main(): Promise<void> {
600614 } catch {
601615 return null ;
602616 }
603- const entry = readChangelogEntry ( original , newVersion ) ;
604- if ( ! entry ) return null ;
605- return { path, entry , original, updated : updateChangelogHeadingDate ( original , newVersion , today ) } ;
617+ const processed = processChangelog ( original , newVersion , today ) ;
618+ if ( ! processed ) return null ;
619+ return { path, original, entry : processed . entry , updated : processed . updated } ;
606620 } ) ( ) ;
607621
608622 const allFiles = changelogInfo ?. updated ? [ ...files , relative ( pwd , changelogInfo . path ) ] : files ;
@@ -659,11 +673,11 @@ async function main(): Promise<void> {
659673 for ( const [ file , content ] of originals ) write ( file, content) ;
660674 } ) ;
661675 for ( const file of files ) {
662- const [ filePath , newData , oldData ] = getFileChanges ( { file, baseVersion, newVersion, replacements, date} ) ;
676+ const [ newData , oldData ] = getFileChanges ( { file, baseVersion, newVersion, replacements, date} ) ;
663677 if ( newData !== null ) {
664- if ( ! originals . has ( filePath ) ) originals . set ( filePath , oldData ! ) ;
665- logVerbose ( `writing ${ filePath } ` ) ;
666- write ( filePath , newData ) ;
678+ if ( ! originals . has ( file ) ) originals . set ( file , oldData ! ) ;
679+ logVerbose ( `writing ${ file } ` ) ;
680+ write ( file , newData ) ;
667681 } else {
668682 logVerbose ( `skipping ${ file } (unhandled lockfile)` ) ;
669683 }
0 commit comments