@@ -8,7 +8,7 @@ use std::io::Read;
88use regex:: { Captures , Regex } ;
99
1010fn main ( ) {
11- write_md ( parse_links ( parse_references ( read_md ( ) ) ) ) ;
11+ write_md ( & parse_links ( parse_references ( & read_md ( ) ) ) ) ;
1212}
1313
1414fn read_md ( ) -> String {
@@ -19,32 +19,34 @@ fn read_md() -> String {
1919 }
2020}
2121
22- fn write_md ( output : String ) {
22+ fn write_md ( output : & str ) {
2323 print ! ( "{output}" ) ;
2424}
2525
26- fn parse_references ( buffer : String ) -> ( String , HashMap < String , String > ) {
26+ fn parse_references ( buffer : & str ) -> ( String , HashMap < String , String > ) {
2727 let mut ref_map = HashMap :: new ( ) ;
2828 // FIXME: currently doesn't handle "title" in following line.
29- let re = Regex :: new ( r### "(?m)\n?^ {0,3}\[([^]]+)\]:[[:blank:]]*(.*)$"### )
29+ let re = Regex :: new ( r"(?m)\n?^ {0,3}\[([^]]+)\]:[[:blank:]]*(.*)$" )
3030 . unwrap ( ) ;
3131 let output = re
32- . replace_all ( & buffer, |caps : & Captures < ' _ > | {
32+ . replace_all ( buffer, |caps : & Captures < ' _ > | {
3333 let key_def = caps. get ( 1 ) . unwrap ( ) . as_str ( ) ;
3434 let key = key_def. to_uppercase ( ) ;
3535 let val = caps. get ( 2 ) . unwrap ( ) . as_str ( ) . to_string ( ) ;
36- if ref_map. insert ( key, val) . is_some ( ) {
37- panic ! ( "unexpected page had duplicate reference for {key_def}" , ) ;
38- }
39- "" . to_string ( )
36+
37+ assert ! ( ref_map. insert( key, val) . is_none( ) , "unexpected page had duplicate reference for {key_def}" ) ;
38+
39+
40+ String :: new ( )
4041 } )
4142 . to_string ( ) ;
4243 ( output, ref_map)
4344}
4445
46+ #[ allow( clippy:: single_match_else) ]
4547fn parse_links ( ( buffer, ref_map) : ( String , HashMap < String , String > ) ) -> String {
4648 // FIXME: check which punctuation is allowed by spec.
47- let re = Regex :: new ( r### "(?:(?P<pre>(?:```(?:[^`]|`[^`])*`?\n```\n)|(?:[^\[]`[^`\n]+[\n]?[^`\n]*`))|(?:\[(?P<name>[^]]+)\](?:(?:\([[:blank:]]*(?P<val>[^")]*[^ ])(?:[[:blank:]]*"[^"]*")?\))|(?:\[(?P<key>[^]]*)\]))?))"## # ) . expect ( "could not create regex" ) ;
49+ let re = Regex :: new ( r#"(?:(?P<pre>(?:```(?:[^`]|`[^`])*`?\n```\n)|(?:[^\[]`[^`\n]+[\n]?[^`\n]*`))|(?:\[(?P<name>[^]]+)\](?:(?:\([[:blank:]]*(?P<val>[^")]*[^ ])(?:[[:blank:]]*"[^"]*")?\))|(?:\[(?P<key>[^]]*)\]))?))"# ) . expect ( "could not create regex" ) ;
4850 let output = re. replace_all ( & buffer, |caps : & Captures < ' _ > | {
4951 match caps. name ( "pre" ) {
5052 Some ( pre_section) => pre_section. as_str ( ) . to_string ( ) ,
@@ -80,75 +82,65 @@ fn parse_links((buffer, ref_map): (String, HashMap<String, String>)) -> String {
8082
8183#[ cfg( test) ]
8284mod tests {
83- fn parse ( source : String ) -> String {
85+ fn parse ( source : & str ) -> String {
8486 super :: parse_links ( super :: parse_references ( source) )
8587 }
8688
8789 #[ test]
8890 fn parses_inline_link ( ) {
8991 let source =
90- r"This is a [link](http://google.com) that should be expanded"
91- . to_string ( ) ;
92+ r"This is a [link](http://google.com) that should be expanded" ;
9293 let target =
93- r"This is a link at *http://google.com* that should be expanded"
94- . to_string ( ) ;
94+ r"This is a link at *http://google.com* that should be expanded" ;
9595 assert_eq ! ( parse( source) , target) ;
9696 }
9797
9898 #[ test]
9999 fn parses_multiline_links ( ) {
100100 let source = r"This is a [link](http://google.com) that
101- should appear expanded. Another [location](/here/) and [another](http://gogogo)"
102- . to_string ( ) ;
101+ should appear expanded. Another [location](/here/) and [another](http://gogogo)" ;
103102 let target = r"This is a link at *http://google.com* that
104- should appear expanded. Another location at */here/* and another at *http://gogogo*"
105- . to_string ( ) ;
103+ should appear expanded. Another location at */here/* and another at *http://gogogo*" ;
106104 assert_eq ! ( parse( source) , target) ;
107105 }
108106
109107 #[ test]
110108 fn parses_reference ( ) {
111109 let source = r"This is a [link][theref].
112110[theref]: http://example.com/foo
113- more text"
114- . to_string ( ) ;
111+ more text" ;
115112 let target = r"This is a link at *http://example.com/foo*.
116- more text"
117- . to_string ( ) ;
113+ more text" ;
118114 assert_eq ! ( parse( source) , target) ;
119115 }
120116
121117 #[ test]
122118 fn parses_implicit_link ( ) {
123119 let source = r"This is an [implicit][] link.
124- [implicit]: /The Link/"
125- . to_string ( ) ;
120+ [implicit]: /The Link/" ;
126121 let target = r"This is an implicit at */The Link/* link." . to_string ( ) ;
127122 assert_eq ! ( parse( source) , target) ;
128123 }
129124 #[ test]
130125 fn parses_refs_with_one_space_indentation ( ) {
131126 let source = r"This is a [link][ref]
132- [ref]: The link"
133- . to_string ( ) ;
127+ [ref]: The link" ;
134128 let target = r"This is a link at *The link*" . to_string ( ) ;
135129 assert_eq ! ( parse( source) , target) ;
136130 }
137131
138132 #[ test]
139133 fn parses_refs_with_two_space_indentation ( ) {
140134 let source = r"This is a [link][ref]
141- [ref]: The link"
142- . to_string ( ) ;
135+ [ref]: The link" ;
143136 let target = r"This is a link at *The link*" . to_string ( ) ;
144137 assert_eq ! ( parse( source) , target) ;
145138 }
146139
147140 #[ test]
148141 fn parses_refs_with_three_space_indentation ( ) {
149142 let source = r"This is a [link][ref]
150- [ref]: The link"
151- . to_string ( ) ;
143+ [ref]: The link" ;
152144 let target = r"This is a link at *The link*" . to_string ( ) ;
153145 assert_eq ! ( parse( source) , target) ;
154146 }
@@ -157,17 +149,15 @@ more text"
157149 #[ should_panic]
158150 fn rejects_refs_with_four_space_indentation ( ) {
159151 let source = r"This is a [link][ref]
160- [ref]: The link"
161- . to_string ( ) ;
152+ [ref]: The link" ;
162153 let target = r"This is a link at *The link*" . to_string ( ) ;
163154 assert_eq ! ( parse( source) , target) ;
164155 }
165156
166157 #[ test]
167158 fn ignores_optional_inline_title ( ) {
168159 let source =
169- r###"This is a titled [link](http://example.com "My title")."###
170- . to_string ( ) ;
160+ r###"This is a titled [link](http://example.com "My title")."### ;
171161 let target =
172162 r"This is a titled link at *http://example.com*." . to_string ( ) ;
173163 assert_eq ! ( parse( source) , target) ;
@@ -176,55 +166,51 @@ more text"
176166 #[ test]
177167 fn parses_title_with_puctuation ( ) {
178168 let source =
179- r###"[link](http://example.com "It's Title")"### . to_string ( ) ;
169+ r###"[link](http://example.com "It's Title")"### ;
180170 let target = r"link at *http://example.com*" . to_string ( ) ;
181171 assert_eq ! ( parse( source) , target) ;
182172 }
183173
184174 #[ test]
185175 fn parses_name_with_punctuation ( ) {
186- let source = r###"[I'm here](there)"### . to_string ( ) ;
176+ let source = r###"[I'm here](there)"### ;
187177 let target = r###"I'm here at *there*"### . to_string ( ) ;
188178 assert_eq ! ( parse( source) , target) ;
189179 }
190180 #[ test]
191181 fn parses_name_with_utf8 ( ) {
192- let source = r###"[user’s forum](the user’s forum)"### . to_string ( ) ;
182+ let source = r###"[user’s forum](the user’s forum)"### ;
193183 let target = r###"user’s forum at *the user’s forum*"### . to_string ( ) ;
194184 assert_eq ! ( parse( source) , target) ;
195185 }
196186
197187 #[ test]
198188 fn parses_reference_with_punctuation ( ) {
199189 let source = r###"[link][the ref-ref]
200- [the ref-ref]:http://example.com/ref-ref"###
201- . to_string ( ) ;
190+ [the ref-ref]:http://example.com/ref-ref"### ;
202191 let target = r###"link at *http://example.com/ref-ref*"### . to_string ( ) ;
203192 assert_eq ! ( parse( source) , target) ;
204193 }
205194
206195 #[ test]
207196 fn parses_reference_case_insensitively ( ) {
208197 let source = r"[link][Ref]
209- [ref]: The reference"
210- . to_string ( ) ;
198+ [ref]: The reference" ;
211199 let target = r"link at *The reference*" . to_string ( ) ;
212200 assert_eq ! ( parse( source) , target) ;
213201 }
214202 #[ test]
215203 fn parses_link_as_reference_when_reference_is_empty ( ) {
216204 let source = r"[link as reference][]
217- [link as reference]: the actual reference"
218- . to_string ( ) ;
205+ [link as reference]: the actual reference" ;
219206 let target = r"link as reference at *the actual reference*" . to_string ( ) ;
220207 assert_eq ! ( parse( source) , target) ;
221208 }
222209
223210 #[ test]
224211 fn does_not_parse_link_without_reference_as_reference ( ) {
225212 let source = r"[link] is alone
226- [link]: The contents"
227- . to_string ( ) ;
213+ [link]: The contents" ;
228214 let target = r"[link] is alone" . to_string ( ) ;
229215 assert_eq ! ( parse( source) , target) ;
230216 }
@@ -233,8 +219,7 @@ more text"
233219 #[ ignore]
234220 fn parses_link_without_reference_as_reference_with_asterisks ( ) {
235221 let source = r"*[link]* is alone
236- [link]: The contents"
237- . to_string ( ) ;
222+ [link]: The contents" ;
238223 let target = r"*link* at *The contents* is alone" . to_string ( ) ;
239224 assert_eq ! ( parse( source) , target) ;
240225 }
@@ -247,23 +232,21 @@ version = "0.1.0"
247232
248233[dependencies]
249234```
250- "###
251- . to_string ( ) ;
235+ "### ;
252236 let target = source. clone ( ) ;
253237 assert_eq ! ( parse( source) , target) ;
254238 }
255239
256240 #[ test]
257241 fn ignores_links_in_quoted_sections ( ) {
258- let source = r###"do not change `[package]`."### . to_string ( ) ;
242+ let source = r###"do not change `[package]`."### ;
259243 let target = source. clone ( ) ;
260244 assert_eq ! ( parse( source) , target) ;
261245 }
262246 #[ test]
263247 fn ignores_links_in_quoted_sections_containing_newlines ( ) {
264248 let source = r"do not change `this [package]
265- is still here` [link](ref)"
266- . to_string ( ) ;
249+ is still here` [link](ref)" ;
267250 let target = r"do not change `this [package]
268251is still here` link at *ref*"
269252 . to_string ( ) ;
@@ -282,8 +265,7 @@ version = "0.1.0"
282265Another [link][]
283266more text
284267[link]: http://gohere
285- "###
286- . to_string ( ) ;
268+ "### ;
287269 let target = r###"```toml
288270[package]
289271name = "hello_cargo"
@@ -311,14 +293,13 @@ src/main.rs:23:21: 23:35 note: found type `&_`
311293error: aborting due to previous error
312294Could not compile `guessing_game`.
313295```
314- "###
315- . to_string ( ) ;
296+ "### ;
316297 let target = source. clone ( ) ;
317298 assert_eq ! ( parse( source) , target) ;
318299 }
319300 #[ test]
320301 fn ignores_short_quotes ( ) {
321- let source = r"to `1` at index `[0]` i" . to_string ( ) ;
302+ let source = r"to `1` at index `[0]` i" ;
322303 let target = source. clone ( ) ;
323304 assert_eq ! ( parse( source) , target) ;
324305 }
@@ -338,7 +319,7 @@ note: `Point` cannot be formatted with the default formatter; try using `:?` ins
338319note: required by `std::fmt::Display::fmt`
339320```
340321`here` is another [link](the ref)
341- "### . to_string ( ) ;
322+ "### ;
342323 let target = r###"```bash
343324$ cargo run
344325 Compiling points v0.1.0 (file:///projects/points)
@@ -353,7 +334,7 @@ note: `Point` cannot be formatted with the default formatter; try using `:?` ins
353334note: required by `std::fmt::Display::fmt`
354335```
355336`here` is another link at *the ref*
356- "### . to_string ( ) ;
337+ "### ;
357338 assert_eq ! ( parse( source) , target) ;
358339 }
359340 #[ test]
@@ -378,8 +359,7 @@ Some text to show that the reference links can follow later.
378359
379360[arbitrary case-insensitive reference text]: https://www.mozilla.org
380361[1]: http://slashdot.org
381- [link text itself]: http://www.reddit.com"###
382- . to_string ( ) ;
362+ [link text itself]: http://www.reddit.com"### ;
383363
384364 let target = r###"I'm an inline-style link at *https://www.google.com*
385365
@@ -398,8 +378,7 @@ http://www.example.com or <http://www.example.com> and sometimes
398378example.com (but not on Github, for example).
399379
400380Some text to show that the reference links can follow later.
401- "###
402- . to_string ( ) ;
381+ "### ;
403382 assert_eq ! ( parse( source) , target) ;
404383 }
405384}
0 commit comments