@@ -418,7 +418,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
418
418
struct HeadingLinks < ' a , ' b , ' ids , I > {
419
419
inner : I ,
420
420
toc : Option < & ' b mut TocBuilder > ,
421
- buf : VecDeque < ( Event < ' a > , Range < usize > ) > ,
421
+ buf : VecDeque < Event < ' a > > ,
422
422
id_map : & ' ids mut IdMap ,
423
423
}
424
424
@@ -428,48 +428,48 @@ impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> {
428
428
}
429
429
}
430
430
431
- impl < ' a , ' b , ' ids , I : Iterator < Item = ( Event < ' a > , Range < usize > ) > > Iterator
432
- for HeadingLinks < ' a , ' b , ' ids , I >
433
- {
434
- type Item = ( Event < ' a > , Range < usize > ) ;
431
+ impl < ' a , ' b , ' ids , I : Iterator < Item = Event < ' a > > > Iterator for HeadingLinks < ' a , ' b , ' ids , I > {
432
+ type Item = Event < ' a > ;
435
433
436
434
fn next ( & mut self ) -> Option < Self :: Item > {
437
435
if let Some ( e) = self . buf . pop_front ( ) {
438
436
return Some ( e) ;
439
437
}
440
438
441
439
let event = self . inner . next ( ) ;
442
- if let Some ( ( Event :: Start ( Tag :: Heading ( level) ) , _ ) ) = event {
440
+ if let Some ( Event :: Start ( Tag :: Heading ( level) ) ) = event {
443
441
let mut id = String :: new ( ) ;
444
442
for event in & mut self . inner {
445
- match & event. 0 {
443
+ match & event {
446
444
Event :: End ( Tag :: Heading ( ..) ) => break ,
447
- Event :: Start ( Tag :: Link ( _, _, _) ) | Event :: End ( Tag :: Link ( ..) ) => { }
448
445
Event :: Text ( text) | Event :: Code ( text) => {
449
446
id. extend ( text. chars ( ) . filter_map ( slugify) ) ;
450
- self . buf . push_back ( event) ;
451
447
}
452
- _ => self . buf . push_back ( event) ,
448
+ _ => { }
449
+ }
450
+ match event {
451
+ Event :: Start ( Tag :: Link ( _, _, _) ) | Event :: End ( Tag :: Link ( ..) ) => { }
452
+ event => self . buf . push_back ( event) ,
453
453
}
454
454
}
455
455
let id = self . id_map . derive ( id) ;
456
456
457
457
if let Some ( ref mut builder) = self . toc {
458
458
let mut html_header = String :: new ( ) ;
459
- html:: push_html ( & mut html_header, self . buf . iter ( ) . map ( | ( ev , _ ) | ev . clone ( ) ) ) ;
459
+ html:: push_html ( & mut html_header, self . buf . iter ( ) . cloned ( ) ) ;
460
460
let sec = builder. push ( level as u32 , html_header, id. clone ( ) ) ;
461
- self . buf . push_front ( ( Event :: Html ( format ! ( "{} " , sec) . into ( ) ) , 0 .. 0 ) ) ;
461
+ self . buf . push_front ( Event :: Html ( format ! ( "{} " , sec) . into ( ) ) ) ;
462
462
}
463
463
464
- self . buf . push_back ( ( Event :: Html ( format ! ( "</a></h{}>" , level) . into ( ) ) , 0 .. 0 ) ) ;
464
+ self . buf . push_back ( Event :: Html ( format ! ( "</a></h{}>" , level) . into ( ) ) ) ;
465
465
466
466
let start_tags = format ! (
467
467
"<h{level} id=\" {id}\" class=\" section-header\" >\
468
468
<a href=\" #{id}\" >",
469
469
id = id,
470
470
level = level
471
471
) ;
472
- return Some ( ( Event :: Html ( start_tags. into ( ) ) , 0 .. 0 ) ) ;
472
+ return Some ( Event :: Html ( start_tags. into ( ) ) ) ;
473
473
}
474
474
event
475
475
}
@@ -560,23 +560,23 @@ impl<'a, I> Footnotes<'a, I> {
560
560
}
561
561
}
562
562
563
- impl < ' a , I : Iterator < Item = ( Event < ' a > , Range < usize > ) > > Iterator for Footnotes < ' a , I > {
564
- type Item = ( Event < ' a > , Range < usize > ) ;
563
+ impl < ' a , I : Iterator < Item = Event < ' a > > > Iterator for Footnotes < ' a , I > {
564
+ type Item = Event < ' a > ;
565
565
566
566
fn next ( & mut self ) -> Option < Self :: Item > {
567
567
loop {
568
568
match self . inner . next ( ) {
569
- Some ( ( Event :: FootnoteReference ( ref reference) , range ) ) => {
569
+ Some ( Event :: FootnoteReference ( ref reference) ) => {
570
570
let entry = self . get_entry ( & reference) ;
571
571
let reference = format ! (
572
572
"<sup id=\" fnref{0}\" ><a href=\" #fn{0}\" >{0}</a></sup>" ,
573
573
( * entry) . 1
574
574
) ;
575
- return Some ( ( Event :: Html ( reference. into ( ) ) , range ) ) ;
575
+ return Some ( Event :: Html ( reference. into ( ) ) ) ;
576
576
}
577
- Some ( ( Event :: Start ( Tag :: FootnoteDefinition ( def) ) , _ ) ) => {
577
+ Some ( Event :: Start ( Tag :: FootnoteDefinition ( def) ) ) => {
578
578
let mut content = Vec :: new ( ) ;
579
- for ( event, _ ) in & mut self . inner {
579
+ for event in & mut self . inner {
580
580
if let Event :: End ( Tag :: FootnoteDefinition ( ..) ) = event {
581
581
break ;
582
582
}
@@ -607,7 +607,7 @@ impl<'a, I: Iterator<Item = (Event<'a>, Range<usize>)>> Iterator for Footnotes<'
607
607
ret. push_str ( "</li>" ) ;
608
608
}
609
609
ret. push_str ( "</ol></div>" ) ;
610
- return Some ( ( Event :: Html ( ret. into ( ) ) , 0 .. 0 ) ) ;
610
+ return Some ( Event :: Html ( ret. into ( ) ) ) ;
611
611
} else {
612
612
return None ;
613
613
}
@@ -917,14 +917,13 @@ impl Markdown<'_> {
917
917
} ;
918
918
919
919
let p = Parser :: new_with_broken_link_callback ( md, opts ( ) , Some ( & mut replacer) ) ;
920
- let p = p. into_offset_iter ( ) ;
921
920
922
921
let mut s = String :: with_capacity ( md. len ( ) * 3 / 2 ) ;
923
922
924
923
let p = HeadingLinks :: new ( p, None , & mut ids) ;
925
- let p = Footnotes :: new ( p) ;
926
- let p = LinkReplacer :: new ( p. map ( |( ev, _) | ev) , links) ;
924
+ let p = LinkReplacer :: new ( p, links) ;
927
925
let p = CodeBlocks :: new ( p, codes, edition, playground) ;
926
+ let p = Footnotes :: new ( p) ;
928
927
html:: push_html ( & mut s, p) ;
929
928
930
929
s
@@ -935,16 +934,16 @@ impl MarkdownWithToc<'_> {
935
934
crate fn into_string ( self ) -> String {
936
935
let MarkdownWithToc ( md, mut ids, codes, edition, playground) = self ;
937
936
938
- let p = Parser :: new_ext ( md, opts ( ) ) . into_offset_iter ( ) ;
937
+ let p = Parser :: new_ext ( md, opts ( ) ) ;
939
938
940
939
let mut s = String :: with_capacity ( md. len ( ) * 3 / 2 ) ;
941
940
942
941
let mut toc = TocBuilder :: new ( ) ;
943
942
944
943
{
945
944
let p = HeadingLinks :: new ( p, Some ( & mut toc) , & mut ids) ;
945
+ let p = CodeBlocks :: new ( p, codes, edition, playground) ;
946
946
let p = Footnotes :: new ( p) ;
947
- let p = CodeBlocks :: new ( p. map ( |( ev, _) | ev) , codes, edition, playground) ;
948
947
html:: push_html ( & mut s, p) ;
949
948
}
950
949
@@ -960,19 +959,19 @@ impl MarkdownHtml<'_> {
960
959
if md. is_empty ( ) {
961
960
return String :: new ( ) ;
962
961
}
963
- let p = Parser :: new_ext ( md, opts ( ) ) . into_offset_iter ( ) ;
962
+ let p = Parser :: new_ext ( md, opts ( ) ) ;
964
963
965
964
// Treat inline HTML as plain text.
966
- let p = p. map ( |event| match event. 0 {
967
- Event :: Html ( text) => ( Event :: Text ( text) , event . 1 ) ,
965
+ let p = p. map ( |event| match event {
966
+ Event :: Html ( text) => Event :: Text ( text) ,
968
967
_ => event,
969
968
} ) ;
970
969
971
970
let mut s = String :: with_capacity ( md. len ( ) * 3 / 2 ) ;
972
971
973
972
let p = HeadingLinks :: new ( p, None , & mut ids) ;
973
+ let p = CodeBlocks :: new ( p, codes, edition, playground) ;
974
974
let p = Footnotes :: new ( p) ;
975
- let p = CodeBlocks :: new ( p. map ( |( ev, _) | ev) , codes, edition, playground) ;
976
975
html:: push_html ( & mut s, p) ;
977
976
978
977
s
@@ -1125,45 +1124,50 @@ crate fn plain_text_summary(md: &str) -> String {
1125
1124
s
1126
1125
}
1127
1126
1128
- crate fn markdown_links ( md : & str ) -> Vec < ( String , Range < usize > ) > {
1127
+ crate fn markdown_links ( md : & str ) -> Vec < ( String , Option < Range < usize > > ) > {
1129
1128
if md. is_empty ( ) {
1130
1129
return vec ! [ ] ;
1131
1130
}
1132
1131
1133
1132
let mut links = vec ! [ ] ;
1134
- // Used to avoid mutable borrow issues in the `push` closure
1135
- // Probably it would be more efficient to use a `RefCell` but it doesn't seem worth the churn.
1136
1133
let mut shortcut_links = vec ! [ ] ;
1137
1134
1138
- let span_for_link = |link : & str , span : Range < usize > | {
1139
- // Pulldown includes the `[]` as well as the URL. Only highlight the relevant span.
1140
- // NOTE: uses `rfind` in case the title and url are the same: `[Ok][Ok]`
1141
- match md[ span. clone ( ) ] . rfind ( link) {
1142
- Some ( start) => {
1143
- let start = span. start + start;
1144
- start..start + link. len ( )
1135
+ {
1136
+ let locate = |s : & str | unsafe {
1137
+ let s_start = s. as_ptr ( ) ;
1138
+ let s_end = s_start. add ( s. len ( ) ) ;
1139
+ let md_start = md. as_ptr ( ) ;
1140
+ let md_end = md_start. add ( md. len ( ) ) ;
1141
+ if md_start <= s_start && s_end <= md_end {
1142
+ let start = s_start. offset_from ( md_start) as usize ;
1143
+ let end = s_end. offset_from ( md_start) as usize ;
1144
+ Some ( start..end)
1145
+ } else {
1146
+ None
1147
+ }
1148
+ } ;
1149
+
1150
+ let mut push = |link : BrokenLink < ' _ > | {
1151
+ // FIXME: use `link.span` instead of `locate`
1152
+ // (doing it now includes the `[]` as well as the text)
1153
+ shortcut_links. push ( ( link. reference . to_owned ( ) , locate ( link. reference ) ) ) ;
1154
+ None
1155
+ } ;
1156
+ let p = Parser :: new_with_broken_link_callback ( md, opts ( ) , Some ( & mut push) ) ;
1157
+
1158
+ // There's no need to thread an IdMap through to here because
1159
+ // the IDs generated aren't going to be emitted anywhere.
1160
+ let mut ids = IdMap :: new ( ) ;
1161
+ let iter = Footnotes :: new ( HeadingLinks :: new ( p, None , & mut ids) ) ;
1162
+
1163
+ for ev in iter {
1164
+ if let Event :: Start ( Tag :: Link ( _, dest, _) ) = ev {
1165
+ debug ! ( "found link: {}" , dest) ;
1166
+ links. push ( match dest {
1167
+ CowStr :: Borrowed ( s) => ( s. to_owned ( ) , locate ( s) ) ,
1168
+ s @ ( CowStr :: Boxed ( ..) | CowStr :: Inlined ( ..) ) => ( s. into_string ( ) , None ) ,
1169
+ } ) ;
1145
1170
}
1146
- // This can happen for things other than intra-doc links, like `#1` expanded to `https://github.com/rust-lang/rust/issues/1`.
1147
- None => span,
1148
- }
1149
- } ;
1150
- let mut push = |link : BrokenLink < ' _ > | {
1151
- let span = span_for_link ( link. reference , link. span ) ;
1152
- shortcut_links. push ( ( link. reference . to_owned ( ) , span) ) ;
1153
- None
1154
- } ;
1155
- let p = Parser :: new_with_broken_link_callback ( md, opts ( ) , Some ( & mut push) ) ;
1156
-
1157
- // There's no need to thread an IdMap through to here because
1158
- // the IDs generated aren't going to be emitted anywhere.
1159
- let mut ids = IdMap :: new ( ) ;
1160
- let iter = Footnotes :: new ( HeadingLinks :: new ( p. into_offset_iter ( ) , None , & mut ids) ) ;
1161
-
1162
- for ev in iter {
1163
- if let Event :: Start ( Tag :: Link ( _, dest, _) ) = ev. 0 {
1164
- debug ! ( "found link: {}" , dest) ;
1165
- let span = span_for_link ( & dest, ev. 1 ) ;
1166
- links. push ( ( dest. into_string ( ) , span) ) ;
1167
1171
}
1168
1172
}
1169
1173
0 commit comments