@@ -9,15 +9,17 @@ use crate::clean::PrimitiveType;
9
9
use crate :: html:: escape:: Escape ;
10
10
use crate :: html:: render:: Context ;
11
11
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 } ;
14
15
15
16
use rustc_lexer:: { LiteralKind , TokenKind } ;
16
17
use rustc_span:: edition:: Edition ;
17
18
use rustc_span:: symbol:: Symbol ;
18
19
use rustc_span:: { BytePos , Span , DUMMY_SP } ;
19
20
20
21
use super :: format:: { self , Buffer } ;
22
+ use super :: markdown:: Line ;
21
23
use super :: render:: LinkFromSrc ;
22
24
23
25
/// 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> {
31
33
}
32
34
33
35
/// Highlights `src`, returning the HTML output.
34
- crate fn render_with_highlighting (
36
+ crate fn render_source_with_highlighting (
35
37
src : & str ,
36
38
out : & mut Buffer ,
37
39
class : Option < & str > ,
@@ -41,7 +43,31 @@ crate fn render_with_highlighting(
41
43
extra_content : Option < Buffer > ,
42
44
context_info : Option < ContextInfo < ' _ , ' _ , ' _ > > ,
43
45
) {
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) ;
45
71
if let Some ( ( edition_info, class) ) = tooltip {
46
72
write ! (
47
73
out,
@@ -56,7 +82,7 @@ crate fn render_with_highlighting(
56
82
}
57
83
58
84
write_header ( out, class, extra_content) ;
59
- write_code ( out, & src, edition, context_info) ;
85
+ write_code ( out, src, edition, context_info) ;
60
86
write_footer ( out, playground_button) ;
61
87
}
62
88
@@ -86,24 +112,50 @@ fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option<Buf
86
112
/// More explanations about spans and how we use them here are provided in the
87
113
fn write_code (
88
114
out : & mut Buffer ,
89
- src : & str ,
115
+ src : impl Iterator < Item = Line < ' a > > ,
90
116
edition : Edition ,
91
117
context_info : Option < ContextInfo < ' _ , ' _ , ' _ > > ,
92
118
) {
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
+ }
103
147
}
104
148
105
149
fn 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
+ ) ;
107
159
}
108
160
109
161
/// How a span of text is classified. Mostly corresponds to token kinds.
0 commit comments