@@ -9,15 +9,17 @@ use crate::clean::PrimitiveType;
99use crate :: html:: escape:: Escape ;
1010use crate :: html:: render:: Context ;
1111
12- use std:: fmt:: { Display , Write } ;
13- use std:: iter:: Peekable ;
12+ use std:: borrow:: Cow ;
13+ use std:: fmt:: { Debug , Display , Write } ;
14+ use std:: iter:: { once, Peekable } ;
1415
1516use rustc_lexer:: { LiteralKind , TokenKind } ;
1617use rustc_span:: edition:: Edition ;
1718use rustc_span:: symbol:: Symbol ;
1819use rustc_span:: { BytePos , Span , DUMMY_SP } ;
1920
2021use super :: format:: { self , Buffer } ;
22+ use super :: markdown:: Line ;
2123use super :: render:: LinkFromSrc ;
2224
2325/// This type is needed in case we want to render links on items to allow to go to their definition.
@@ -31,7 +33,7 @@ crate struct ContextInfo<'a, 'b, 'c> {
3133}
3234
3335/// Highlights `src`, returning the HTML output.
34- crate fn render_with_highlighting (
36+ crate fn render_source_with_highlighting (
3537 src : & str ,
3638 out : & mut Buffer ,
3739 class : Option < & str > ,
@@ -41,7 +43,31 @@ crate fn render_with_highlighting(
4143 extra_content : Option < Buffer > ,
4244 context_info : Option < ContextInfo < ' _ , ' _ , ' _ > > ,
4345) {
44- debug ! ( "highlighting: ================\n {}\n ==============" , src) ;
46+ render_with_highlighting (
47+ once ( Line :: Shown ( Cow :: Borrowed ( src) ) ) ,
48+ out,
49+ class,
50+ playground_button,
51+ tooltip,
52+ edition,
53+ extra_content,
54+ context_info,
55+ )
56+ }
57+
58+ /// Highlights `src` containing potential hidden lines, returning the HTML output. If you don't have
59+ /// hidden lines, use [`render_source_with_highlighting`] instead.
60+ crate fn render_with_highlighting < ' a > (
61+ src : impl Iterator < Item = Line < ' a > > + Debug ,
62+ out : & mut Buffer ,
63+ class : Option < & str > ,
64+ playground_button : Option < & str > ,
65+ tooltip : Option < ( Option < Edition > , & str ) > ,
66+ edition : Edition ,
67+ extra_content : Option < Buffer > ,
68+ context_info : Option < ContextInfo < ' _ , ' _ , ' _ > > ,
69+ ) {
70+ debug ! ( "highlighting: ================\n {:?}\n ==============" , src) ;
4571 if let Some ( ( edition_info, class) ) = tooltip {
4672 write ! (
4773 out,
@@ -56,7 +82,7 @@ crate fn render_with_highlighting(
5682 }
5783
5884 write_header ( out, class, extra_content) ;
59- write_code ( out, & src, edition, context_info) ;
85+ write_code ( out, src, edition, context_info) ;
6086 write_footer ( out, playground_button) ;
6187}
6288
@@ -86,24 +112,50 @@ fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option<Buf
86112/// More explanations about spans and how we use them here are provided in the
87113fn write_code (
88114 out : & mut Buffer ,
89- src : & str ,
115+ src : impl Iterator < Item = Line < ' a > > ,
90116 edition : Edition ,
91117 context_info : Option < ContextInfo < ' _ , ' _ , ' _ > > ,
92118) {
93- // This replace allows to fix how the code source with DOS backline characters is displayed.
94- let src = src. replace ( "\r \n " , "\n " ) ;
95- Classifier :: new ( & src, edition, context_info. as_ref ( ) . map ( |c| c. file_span ) . unwrap_or ( DUMMY_SP ) )
96- . highlight ( & mut |highlight| {
97- match highlight {
98- Highlight :: Token { text, class } => string ( out, Escape ( text) , class, & context_info) ,
99- Highlight :: EnterSpan { class } => enter_span ( out, class) ,
100- Highlight :: ExitSpan => exit_span ( out) ,
101- } ;
102- } ) ;
119+ let mut iter = src. peekable ( ) ;
120+
121+ // For each `Line`, we replace DOS backlines with '\n'. This replace allows to fix how the code
122+ // source with DOS backline characters is displayed.
123+ while let Some ( line) = iter. next ( ) {
124+ match line {
125+ Line :: Hidden ( text) => {
126+ write ! (
127+ out,
128+ "<span class=\" hidden\" >{}{}</span>" ,
129+ Escape ( & text. replace( "\r \n " , "\n " ) ) ,
130+ if iter. peek( ) . is_some( ) && !text. ends_with( '\n' ) { "\n " } else { "" } ,
131+ ) ;
132+ }
133+ Line :: Shown ( text) => {
134+ Classifier :: new ( & text. replace ( "\r \n " , "\n " ) , edition, context_info. as_ref ( ) . map ( |c| c. file_span ) . unwrap_or ( DUMMY_SP ) ) . highlight ( & mut |highlight| {
135+ match highlight {
136+ Highlight :: Token { text, class } => string ( out, Escape ( text) , class) ,
137+ Highlight :: EnterSpan { class } => enter_span ( out, class) ,
138+ Highlight :: ExitSpan => exit_span ( out) ,
139+ } ;
140+ } ) ;
141+ if iter. peek ( ) . is_some ( ) && !text. ends_with ( '\n' ) {
142+ write ! ( out, "\n " ) ;
143+ }
144+ }
145+ }
146+ }
103147}
104148
105149fn write_footer ( out : & mut Buffer , playground_button : Option < & str > ) {
106- writeln ! ( out, "</code></pre>{}</div>" , playground_button. unwrap_or_default( ) ) ;
150+ writeln ! (
151+ out,
152+ "</code></pre>\
153+ <div class=\" code-buttons\" >\
154+ {}<button class=\" copy-code\" onclick=\" copyCode(this)\" ></button>\
155+ </div>\
156+ </div>",
157+ playground_button. unwrap_or_default( )
158+ ) ;
107159}
108160
109161/// How a span of text is classified. Mostly corresponds to token kinds.
0 commit comments