@@ -108,6 +108,16 @@ module Changelog =
108108 | Security s -> sprintf " Security: %s " s.CleanedText
109109 | Custom ( h, s) -> sprintf " %s : %s " h s.CleanedText
110110
111+ member x.ChangeText () =
112+ match x with
113+ | Added ( changeText)
114+ | Changed ( changeText)
115+ | Deprecated ( changeText)
116+ | Removed ( changeText)
117+ | Fixed ( changeText)
118+ | Security ( changeText)
119+ | Custom (_, changeText) -> changeText
120+
111121 /// Create a new change type changelog entry
112122 static member New ( header : string , line : string ) : Change =
113123 let text =
@@ -267,6 +277,32 @@ module Changelog =
267277
268278 assemblyVersion, nugetVersion
269279
280+ /// <summary>
281+ /// A version or "Unreleased"
282+ /// </summary>
283+ type ReferenceVersion =
284+ | SemVerRef of SemVerInfo
285+ | UnreleasedRef
286+
287+ override x.ToString () =
288+ match x with
289+ | SemVerRef ( semVerInfo) -> semVerInfo.ToString()
290+ | UnreleasedRef -> " Unreleased"
291+
292+ /// <summary>
293+ /// A reference from a version to a repository URL (e.g. a tag or a compare link)
294+ /// </summary>
295+ /// <code>
296+ /// [Unreleased]: https://github.com/user/MyCoolNewLib.git/compare/v0.1.0...HEAD
297+ /// [0.1.0]: https://github.com/user/MyCoolNewLib.git/releases/tag/v0.1.0
298+ /// </code>
299+ type Reference =
300+ { SemVer: ReferenceVersion
301+ RepoUrl: Uri }
302+
303+ override x.ToString () =
304+ sprintf " [%s ]: %s " ( x.SemVer.ToString()) ( x.RepoUrl.ToString())
305+
270306 /// <summary>
271307 /// Holds data for a changelog file, which include changelog entries an other metadata
272308 /// </summary>
@@ -283,17 +319,21 @@ module Changelog =
283319
284320 /// The change log entries
285321 Entries: ChangelogEntry list
322+
323+ /// The references to repository URLs
324+ References: Reference list
286325 }
287326
288327 /// the latest change log entry
289328 member x.LatestEntry = x.Entries |> Seq.head
290329
291330 /// Create a new changelog record from given data
292- static member New ( header , description , unreleased , entries ) =
331+ static member New ( header , description , unreleased , entries , references ) =
293332 { Header = header
294333 Description = description
295334 Unreleased = unreleased
296- Entries = entries }
335+ Entries = entries
336+ References = references }
297337
298338 /// Promote an unreleased changelog entry to a released one
299339 member x.PromoteUnreleased ( assemblyVersion : string , nugetVersion : string ) : Changelog =
@@ -311,7 +351,7 @@ module Changelog =
311351 )
312352
313353 let unreleased ' = Some { Description = None; Changes = [] }
314- Changelog.New( x.Header, x.Description, unreleased', newEntry :: x.Entries)
354+ Changelog.New( x.Header, x.Description, unreleased', newEntry :: x.Entries, x.References )
315355
316356 /// Promote an unreleased changelog entry to a released one using version number
317357 member x.PromoteUnreleased ( version : string ) : Changelog =
@@ -346,7 +386,10 @@ module Changelog =
346386 | " " -> " Changelog"
347387 | h -> h
348388
349- ( sprintf " # %s \n\n %s \n\n %s " header description entries)
389+ let references =
390+ x.References |> List.map ( fun reference -> reference.ToString()) |> joinLines
391+
392+ ( sprintf " # %s \n\n %s \n\n %s \n\n %s " header description entries references)
350393 |> fixMultipleNewlines
351394 |> String.trim
352395
@@ -358,8 +401,9 @@ module Changelog =
358401 /// <param name="description">the descriptive text for changelog</param>
359402 /// <param name="unreleased">the unreleased list of changelog entries</param>
360403 /// <param name="entries">the list of changelog entries</param>
361- let createWithCustomHeader header description unreleased entries =
362- Changelog.New( header, description, unreleased, entries)
404+ /// <param name="references">the list of references</param>
405+ let createWithCustomHeader header description unreleased entries references =
406+ Changelog.New( header, description, unreleased, entries, references)
363407
364408 /// <summary>
365409 /// Create a changelog with given data
@@ -368,16 +412,17 @@ module Changelog =
368412 /// <param name="description">the descriptive text for changelog </param>
369413 /// <param name="unreleased">the unreleased list of changelog entries</param>
370414 /// <param name="entries">the list of changelog entries</param>
371- let create description unreleased entries =
372- createWithCustomHeader " Changelog" description unreleased entries
415+ /// <param name="references">the list of references</param>
416+ let create description unreleased entries references =
417+ createWithCustomHeader " Changelog" description unreleased entries references
373418
374419 /// <summary>
375420 /// Create a changelog with given entries and default values for other data including
376421 /// header and description.
377422 /// </summary>
378423 ///
379424 /// <param name="entries">the list of changelog entries</param>
380- let fromEntries entries = create None None entries
425+ let fromEntries entries = create None None entries []
381426
382427 let internal isMainHeader line : bool = " # " <* line
383428 let internal isVersionHeader line : bool = " ## " <* line
@@ -538,7 +583,43 @@ module Changelog =
538583 | h :: _ -> h
539584 | _ -> " Changelog"
540585
541- Changelog.New( header, description, unreleased, entries)
586+ // Move references from last changelog entry into references.
587+ let entriesWithoutReferences , references =
588+ let referenceRegex =
589+ $""" ^\[(({nugetRegex.ToString()})|Unreleased)\]: +(http[s]://.+)$"""
590+ |> String.getRegEx
591+
592+ match entries with
593+ | [] -> [], []
594+ | entries ->
595+ let front , lastChange = entries |> List.splitAt ( List.length entries - 1 )
596+ let last = List.head lastChange
597+
598+ let refChanges , trueChanges =
599+ last.Changes
600+ |> List.partition ( fun ( change : Change ) ->
601+ referenceRegex.Match( change.ChangeText() .CleanedText) .Success)
602+
603+ let references =
604+ refChanges
605+ |> List.map ( fun change ->
606+ let referenceMatch = referenceRegex.Match( change.ChangeText() .CleanedText)
607+ let version = referenceMatch.Groups[ 1 ]. Value
608+ let uri = referenceMatch.Groups[ 6 ]. Value
609+
610+ { SemVer =
611+ if version = " Unreleased" then
612+ UnreleasedRef
613+ else
614+ SemVerRef( SemVer.parse version)
615+ RepoUrl = Uri( uri) })
616+
617+ let newLastEntry =
618+ ChangelogEntry.New( last.AssemblyVersion, last.NuGetVersion, trueChanges)
619+
620+ front @ [ newLastEntry ], references
621+
622+ Changelog.New( header, description, unreleased, entriesWithoutReferences, references)
542623
543624 /// <summary>
544625 /// Parses a Changelog text file and returns the latest changelog.
0 commit comments