@@ -92,18 +92,8 @@ impl Term {
9292
9393 let mut styled = adapter:: AnsiBytes :: new ( ) ;
9494 let mut elements = styled. extract_next ( ansi. as_bytes ( ) ) . collect :: < Vec < _ > > ( ) ;
95- let mut effects_in_use = anstyle:: Effects :: new ( ) ;
96- for element in & mut elements {
97- let style = & mut element. style ;
98- // Pre-process INVERT to make fg/bg calculations easier
99- if style. get_effects ( ) . contains ( anstyle:: Effects :: INVERT ) {
100- * style = style
101- . fg_color ( Some ( style. get_bg_color ( ) . unwrap_or ( self . bg_color ) ) )
102- . bg_color ( Some ( style. get_fg_color ( ) . unwrap_or ( self . fg_color ) ) )
103- . effects ( style. get_effects ( ) . remove ( anstyle:: Effects :: INVERT ) ) ;
104- }
105- effects_in_use |= style. get_effects ( ) ;
106- }
95+ preprocess_invert_style ( & mut elements, self . bg_color , self . fg_color ) ;
96+
10797 let styled_lines = split_lines ( & elements) ;
10898
10999 let fg_color = rgb_value ( self . fg_color , self . palette ) ;
@@ -152,60 +142,7 @@ impl Term {
152142 writeln ! ( & mut buffer, r#" padding: 0 10px;"# ) . unwrap ( ) ;
153143 writeln ! ( & mut buffer, r#" line-height: {line_height}px;"# ) . unwrap ( ) ;
154144 writeln ! ( & mut buffer, r#" }}"# ) . unwrap ( ) ;
155- if effects_in_use. contains ( anstyle:: Effects :: BOLD ) {
156- writeln ! ( & mut buffer, r#" .bold {{ font-weight: bold; }}"# ) . unwrap ( ) ;
157- }
158- if effects_in_use. contains ( anstyle:: Effects :: ITALIC ) {
159- writeln ! ( & mut buffer, r#" .italic {{ font-style: italic; }}"# ) . unwrap ( ) ;
160- }
161- if effects_in_use. contains ( anstyle:: Effects :: UNDERLINE ) {
162- writeln ! (
163- & mut buffer,
164- r#" .underline {{ text-decoration-line: underline; }}"#
165- )
166- . unwrap ( ) ;
167- }
168- if effects_in_use. contains ( anstyle:: Effects :: DOUBLE_UNDERLINE ) {
169- writeln ! (
170- & mut buffer,
171- r#" .double-underline {{ text-decoration-line: underline; text-decoration-style: double; }}"#
172- )
173- . unwrap ( ) ;
174- }
175- if effects_in_use. contains ( anstyle:: Effects :: CURLY_UNDERLINE ) {
176- writeln ! (
177- & mut buffer,
178- r#" .curly-underline {{ text-decoration-line: underline; text-decoration-style: wavy; }}"#
179- )
180- . unwrap ( ) ;
181- }
182- if effects_in_use. contains ( anstyle:: Effects :: DOTTED_UNDERLINE ) {
183- writeln ! (
184- & mut buffer,
185- r#" .dotted-underline {{ text-decoration-line: underline; text-decoration-style: dotted; }}"#
186- )
187- . unwrap ( ) ;
188- }
189- if effects_in_use. contains ( anstyle:: Effects :: DASHED_UNDERLINE ) {
190- writeln ! (
191- & mut buffer,
192- r#" .dashed-underline {{ text-decoration-line: underline; text-decoration-style: dashed; }}"#
193- )
194- . unwrap ( ) ;
195- }
196- if effects_in_use. contains ( anstyle:: Effects :: STRIKETHROUGH ) {
197- writeln ! (
198- & mut buffer,
199- r#" .strikethrough {{ text-decoration-line: line-through; }}"#
200- )
201- . unwrap ( ) ;
202- }
203- if effects_in_use. contains ( anstyle:: Effects :: DIMMED ) {
204- writeln ! ( & mut buffer, r#" .dimmed {{ opacity: 0.7; }}"# ) . unwrap ( ) ;
205- }
206- if effects_in_use. contains ( anstyle:: Effects :: HIDDEN ) {
207- writeln ! ( & mut buffer, r#" .hidden {{ opacity: 0; }}"# ) . unwrap ( ) ;
208- }
145+ write_effects_in_use ( & mut buffer, & elements) ;
209146 writeln ! ( & mut buffer, r#" tspan {{"# ) . unwrap ( ) ;
210147 writeln ! ( & mut buffer, r#" font: 14px {font_family};"# ) . unwrap ( ) ;
211148 writeln ! ( & mut buffer, r#" white-space: pre;"# ) . unwrap ( ) ;
@@ -237,7 +174,7 @@ impl Term {
237174 if element. text . is_empty ( ) {
238175 continue ;
239176 }
240- write_bg_span ( & mut buffer, & element. style , & element. text ) ;
177+ write_bg_span ( & mut buffer, "tspan" , & element. style , & element. text ) ;
241178 }
242179 // HACK: must close tspan on newline to include them in copy/paste
243180 writeln ! ( & mut buffer) . unwrap ( ) ;
@@ -249,7 +186,7 @@ impl Term {
249186 if element. text . is_empty ( ) {
250187 continue ;
251188 }
252- write_fg_span ( & mut buffer, element, & element. text ) ;
189+ write_fg_span ( & mut buffer, "tspan" , element, & element. text ) ;
253190 }
254191 // HACK: must close tspan on newline to include them in copy/paste
255192 writeln ! ( & mut buffer) . unwrap ( ) ;
@@ -268,7 +205,71 @@ impl Term {
268205const FG_COLOR : anstyle:: Color = anstyle:: Color :: Ansi ( anstyle:: AnsiColor :: White ) ;
269206const BG_COLOR : anstyle:: Color = anstyle:: Color :: Ansi ( anstyle:: AnsiColor :: Black ) ;
270207
271- fn write_fg_span ( buffer : & mut String , element : & adapter:: Element , fragment : & str ) {
208+ fn write_effects_in_use ( buffer : & mut String , elements : & [ adapter:: Element ] ) {
209+ use std:: fmt:: Write as _;
210+
211+ let mut effects_in_use = anstyle:: Effects :: new ( ) ;
212+ for element in elements {
213+ effects_in_use |= element. style . get_effects ( ) ;
214+ }
215+
216+ if effects_in_use. contains ( anstyle:: Effects :: BOLD ) {
217+ writeln ! ( buffer, r#" .bold {{ font-weight: bold; }}"# ) . unwrap ( ) ;
218+ }
219+ if effects_in_use. contains ( anstyle:: Effects :: ITALIC ) {
220+ writeln ! ( buffer, r#" .italic {{ font-style: italic; }}"# ) . unwrap ( ) ;
221+ }
222+ if effects_in_use. contains ( anstyle:: Effects :: UNDERLINE ) {
223+ writeln ! (
224+ buffer,
225+ r#" .underline {{ text-decoration-line: underline; }}"#
226+ )
227+ . unwrap ( ) ;
228+ }
229+ if effects_in_use. contains ( anstyle:: Effects :: DOUBLE_UNDERLINE ) {
230+ writeln ! (
231+ buffer,
232+ r#" .double-underline {{ text-decoration-line: underline; text-decoration-style: double; }}"#
233+ )
234+ . unwrap ( ) ;
235+ }
236+ if effects_in_use. contains ( anstyle:: Effects :: CURLY_UNDERLINE ) {
237+ writeln ! (
238+ buffer,
239+ r#" .curly-underline {{ text-decoration-line: underline; text-decoration-style: wavy; }}"#
240+ )
241+ . unwrap ( ) ;
242+ }
243+ if effects_in_use. contains ( anstyle:: Effects :: DOTTED_UNDERLINE ) {
244+ writeln ! (
245+ buffer,
246+ r#" .dotted-underline {{ text-decoration-line: underline; text-decoration-style: dotted; }}"#
247+ )
248+ . unwrap ( ) ;
249+ }
250+ if effects_in_use. contains ( anstyle:: Effects :: DASHED_UNDERLINE ) {
251+ writeln ! (
252+ buffer,
253+ r#" .dashed-underline {{ text-decoration-line: underline; text-decoration-style: dashed; }}"#
254+ )
255+ . unwrap ( ) ;
256+ }
257+ if effects_in_use. contains ( anstyle:: Effects :: STRIKETHROUGH ) {
258+ writeln ! (
259+ buffer,
260+ r#" .strikethrough {{ text-decoration-line: line-through; }}"#
261+ )
262+ . unwrap ( ) ;
263+ }
264+ if effects_in_use. contains ( anstyle:: Effects :: DIMMED ) {
265+ writeln ! ( buffer, r#" .dimmed {{ opacity: 0.7; }}"# ) . unwrap ( ) ;
266+ }
267+ if effects_in_use. contains ( anstyle:: Effects :: HIDDEN ) {
268+ writeln ! ( buffer, r#" .hidden {{ opacity: 0; }}"# ) . unwrap ( ) ;
269+ }
270+ }
271+
272+ fn write_fg_span ( buffer : & mut String , span : & str , element : & adapter:: Element , fragment : & str ) {
272273 use std:: fmt:: Write as _;
273274 let style = element. style ;
274275 let fg_color = style. get_fg_color ( ) . map ( |c| color_name ( FG_PREFIX , c) ) ;
@@ -329,7 +330,7 @@ fn write_fg_span(buffer: &mut String, element: &adapter::Element, fragment: &str
329330
330331 let mut need_closing_a = false ;
331332
332- write ! ( buffer, r#"<tspan "# ) . unwrap ( ) ;
333+ write ! ( buffer, r#"<{span} "# ) . unwrap ( ) ;
333334 if !classes. is_empty ( ) {
334335 let classes = classes. join ( " " ) ;
335336 write ! ( buffer, r#" class="{classes}""# ) . unwrap ( ) ;
@@ -343,10 +344,10 @@ fn write_fg_span(buffer: &mut String, element: &adapter::Element, fragment: &str
343344 if need_closing_a {
344345 write ! ( buffer, r#"</a>"# ) . unwrap ( ) ;
345346 }
346- write ! ( buffer, r#"</tspan >"# ) . unwrap ( ) ;
347+ write ! ( buffer, r#"</{span} >"# ) . unwrap ( ) ;
347348}
348349
349- fn write_bg_span ( buffer : & mut String , style : & anstyle:: Style , fragment : & str ) {
350+ fn write_bg_span ( buffer : & mut String , span : & str , style : & anstyle:: Style , fragment : & str ) {
350351 use std:: fmt:: Write as _;
351352 use unicode_width:: UnicodeWidthStr ;
352353
@@ -361,14 +362,14 @@ fn write_bg_span(buffer: &mut String, style: &anstyle::Style, fragment: &str) {
361362 if let Some ( class) = bg_color. as_deref ( ) {
362363 classes. push ( class) ;
363364 }
364- write ! ( buffer, r#"<tspan "# ) . unwrap ( ) ;
365+ write ! ( buffer, r#"<{span} "# ) . unwrap ( ) ;
365366 if !classes. is_empty ( ) {
366367 let classes = classes. join ( " " ) ;
367368 write ! ( buffer, r#" class="{classes}""# ) . unwrap ( ) ;
368369 }
369370 write ! ( buffer, r#">"# ) . unwrap ( ) ;
370371 write ! ( buffer, "{fragment}" ) . unwrap ( ) ;
371- write ! ( buffer, r#"</tspan >"# ) . unwrap ( ) ;
372+ write ! ( buffer, r#"</{span} >"# ) . unwrap ( ) ;
372373}
373374
374375impl Default for Term {
@@ -449,6 +450,23 @@ fn color_styles(
449450 colors. into_iter ( )
450451}
451452
453+ fn preprocess_invert_style (
454+ elements : & mut [ adapter:: Element ] ,
455+ bg_color : anstyle:: Color ,
456+ fg_color : anstyle:: Color ,
457+ ) {
458+ for element in elements {
459+ let style = & mut element. style ;
460+ // Pre-process INVERT to make fg/bg calculations easier
461+ if style. get_effects ( ) . contains ( anstyle:: Effects :: INVERT ) {
462+ * style = style
463+ . fg_color ( Some ( style. get_bg_color ( ) . unwrap_or ( bg_color) ) )
464+ . bg_color ( Some ( style. get_fg_color ( ) . unwrap_or ( fg_color) ) )
465+ . effects ( style. get_effects ( ) . remove ( anstyle:: Effects :: INVERT ) ) ;
466+ }
467+ }
468+ }
469+
452470fn split_lines ( styled : & [ adapter:: Element ] ) -> Vec < Vec < adapter:: Element > > {
453471 let mut lines = Vec :: new ( ) ;
454472 let mut current_line = Vec :: new ( ) ;
0 commit comments