@@ -13,7 +13,7 @@ pub struct Change {
1313 /// Something to uniquely identify a change.
1414 ///
1515 /// This is the name of the file (without the `.md` extension) which defines this changeset.
16- pub unique_id : String ,
16+ pub unique_id : UniqueId ,
1717 /// Describes how a changeset affects the relevant packages.
1818 pub versioning : Versioning ,
1919 /// The details of the change which will be written to a Changelog file
@@ -31,7 +31,7 @@ impl Change {
3131 /// If the file cannot be written, an [`std::io::Error`] is returned. This may happen if the
3232 /// directory does not exist.
3333 pub fn write_to_directory < T : AsRef < Path > > ( & self , path : T ) -> std:: io:: Result < PathBuf > {
34- let output_path = path. as_ref ( ) . join ( format ! ( "{}.md" , self . unique_id) ) ;
34+ let output_path = path. as_ref ( ) . join ( self . unique_id . to_file_name ( ) ) ;
3535 std:: fs:: write ( & output_path, self . to_string ( ) ) ?;
3636 Ok ( output_path)
3737 }
@@ -53,12 +53,12 @@ impl Change {
5353 let unique_id = file_name
5454 . strip_suffix ( ".md" )
5555 . ok_or ( LoadingError :: InvalidFileName ) ?
56- . to_string ( ) ;
56+ . into ( ) ;
5757 let contents = std:: fs:: read_to_string ( path) ?;
5858 Self :: from_str ( unique_id, & contents) . map_err ( LoadingError :: from)
5959 }
6060
61- fn from_str ( unique_id : String , content : & str ) -> Result < Self , ParsingError > {
61+ fn from_str ( unique_id : UniqueId , content : & str ) -> Result < Self , ParsingError > {
6262 let mut lines = content. lines ( ) ;
6363 let first_line = lines. next ( ) . ok_or ( ParsingError :: MissingFrontMatter ) ?;
6464 if first_line. trim ( ) != "---" {
@@ -106,6 +106,50 @@ impl Display for Change {
106106 }
107107}
108108
109+ /// The unique ID of a [`Change`], parsed from and used to set the file name of the Markdown file.
110+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
111+ pub struct UniqueId ( String ) ;
112+
113+ impl UniqueId {
114+ pub fn to_file_name ( & self ) -> String {
115+ format ! ( "{self}.md" )
116+ }
117+ }
118+
119+ impl < T : AsRef < str > > From < T > for UniqueId {
120+ fn from ( s : T ) -> Self {
121+ Self (
122+ s. as_ref ( )
123+ . chars ( )
124+ . filter_map ( |c| {
125+ if c. is_ascii_alphanumeric ( ) {
126+ Some ( c. to_ascii_lowercase ( ) )
127+ } else if c == ' ' {
128+ Some ( '_' )
129+ } else {
130+ None
131+ }
132+ } )
133+ . collect ( ) ,
134+ )
135+ }
136+ }
137+
138+ impl Display for UniqueId {
139+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
140+ write ! ( f, "{}" , self . 0 )
141+ }
142+ }
143+
144+ #[ cfg( test) ]
145+ #[ test]
146+ fn test_create_unique_id ( ) {
147+ assert_eq ! (
148+ UniqueId :: from( "`[i carry your heart with me(i carry it in]`" ) . to_string( ) ,
149+ "i_carry_your_heart_with_mei_carry_it_in"
150+ ) ;
151+ }
152+
109153#[ derive( Debug ) ]
110154pub enum ParsingError {
111155 MissingFrontMatter ,
0 commit comments