Skip to content

Commit c892ab4

Browse files
Improve notification display on CLI when source is HTML (#1756)
1 parent affdf2d commit c892ab4

File tree

3 files changed

+103
-15
lines changed

3 files changed

+103
-15
lines changed

ts/packages/dispatcher/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"exifreader": "^4.30.1",
6161
"file-size": "^1.0.0",
6262
"glob": "^10.3.12",
63+
"html-to-text": "^9.0.5",
6364
"image-memory": "workspace:*",
6465
"knowledge-processor": "workspace:*",
6566
"knowpro": "workspace:*",
@@ -76,6 +77,7 @@
7677
"@types/debug": "^4.1.12",
7778
"@types/file-size": "^1.0.3",
7879
"@types/glob": "^8.1.0",
80+
"@types/html-to-text": "^9.0.4",
7981
"@types/jest": "^29.5.7",
8082
"@types/proper-lockfile": "^4.1.4",
8183
"@types/ws": "^8.5.10",

ts/packages/dispatcher/src/helpers/console.ts

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { createInterface } from "readline/promises";
1919
import fs from "fs";
2020
import readline from "readline";
2121
import open from "open";
22+
import { convert } from "html-to-text";
2223

2324
function 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+
271350
function formatDisplayContent(content: string | DisplayContent): string {
272351
if (typeof content === "string") {
273352
return content;

ts/pnpm-lock.yaml

Lines changed: 20 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)