@@ -19,6 +19,7 @@ import { createInterface } from "readline/promises";
1919import fs from "fs" ;
2020import readline from "readline" ;
2121import open from "open" ;
22+ import { convert } from "html-to-text" ;
2223
2324function displayPadEnd ( content : string , length : number ) : string {
2425 // Account for full width characters
@@ -120,9 +121,16 @@ function createConsoleClientIO(rl?: readline.promises.Interface): ClientIO {
120121 ) : void {
121122 const time = new Date ( timestamp ) . toLocaleTimeString ( ) ;
122123
123- // Format the notification with timestamp and source
124124 const header = chalk . dim ( `[${ time } ] ${ source } :` ) ;
125- const content = formatDisplayContent ( data ) ;
125+
126+ let content : string ;
127+ if ( isHtmlContent ( data ) ) {
128+ const htmlContent = extractHtmlString ( data ) ;
129+ content = convertHtmlToText ( htmlContent ) ;
130+ } else {
131+ content = formatDisplayContent ( data ) ;
132+ }
133+
126134 const formattedMessage = `${ header } \n ${ content } ` ;
127135
128136 displayContent ( formattedMessage ) ;
@@ -268,6 +276,77 @@ function initializeConsole(rl?: readline.promises.Interface) {
268276 readline . emitKeypressEvents ( process . stdin ) ;
269277}
270278
279+ function isHtmlContent ( data : string | DisplayContent ) : boolean {
280+ if ( typeof data === "object" && data !== null && "type" in data ) {
281+ return data . type === "html" ;
282+ }
283+ if ( typeof data === "string" ) {
284+ return / < [ ^ > ] + > / . test ( data ) ;
285+ }
286+ if ( typeof data === "object" && data !== null && "content" in data ) {
287+ const content = data . content ;
288+ if ( typeof content === "string" ) {
289+ return / < [ ^ > ] + > / . test ( content ) ;
290+ }
291+ }
292+ return false ;
293+ }
294+
295+ function extractHtmlString ( data : string | DisplayContent ) : string {
296+ if ( typeof data === "string" ) {
297+ return data ;
298+ }
299+ if ( typeof data === "object" && data !== null && "content" in data ) {
300+ if ( typeof data . content === "string" ) {
301+ return data . content ;
302+ }
303+ }
304+ return String ( data ) ;
305+ }
306+
307+ function convertHtmlToText ( html : string ) : string {
308+ try {
309+ const result = convert ( html , {
310+ wordwrap : 80 ,
311+ preserveNewlines : false ,
312+ selectors : [
313+ {
314+ selector : "div" ,
315+ format : "block" ,
316+ options : { leadingLineBreaks : 1 , trailingLineBreaks : 1 } ,
317+ } ,
318+ {
319+ selector : "p" ,
320+ format : "block" ,
321+ options : { leadingLineBreaks : 1 , trailingLineBreaks : 1 } ,
322+ } ,
323+ {
324+ selector : 'div[style*="font-weight: 600"]' ,
325+ format : "block" ,
326+ options : { leadingLineBreaks : 1 , trailingLineBreaks : 1 } ,
327+ } ,
328+ {
329+ selector : "a" ,
330+ format : "inline" ,
331+ options : {
332+ linkBrackets : false ,
333+ hideLinkHrefIfSameAsText : true ,
334+ ignoreHref : true ,
335+ } ,
336+ } ,
337+ ] ,
338+ } ) ;
339+
340+ return result . replace ( / \n { 3 , } / g, "\n\n" ) . trim ( ) ;
341+ } catch ( error ) {
342+ console . warn ( "HTML-to-text conversion failed:" , error ) ;
343+ return extractHtmlString ( html )
344+ . replace ( / < [ ^ > ] * > / g, " " )
345+ . replace ( / \s + / g, " " )
346+ . trim ( ) ;
347+ }
348+ }
349+
271350function formatDisplayContent ( content : string | DisplayContent ) : string {
272351 if ( typeof content === "string" ) {
273352 return content ;
0 commit comments