@dunkinfrunkin/mdcat 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli.js +16 -2
- package/src/docx.js +3 -1
- package/src/render.js +12 -7
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -45,14 +45,28 @@ if (args[0] === "--version" || args[0] === "-v") {
|
|
|
45
45
|
|
|
46
46
|
const MAX_COLS = 100;
|
|
47
47
|
|
|
48
|
+
function escapeHtml(s) {
|
|
49
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
50
|
+
}
|
|
51
|
+
|
|
48
52
|
function openInBrowser(title, content) {
|
|
49
|
-
|
|
53
|
+
// Use a custom renderer that escapes raw HTML tokens so bare <tag> in
|
|
54
|
+
// markdown text isn't swallowed by the browser.
|
|
55
|
+
const webMarked = new marked.Marked({ gfm: true });
|
|
56
|
+
webMarked.use({
|
|
57
|
+
renderer: {
|
|
58
|
+
html(token) {
|
|
59
|
+
return escapeHtml(token.text);
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
const html = webMarked.parse(content);
|
|
50
64
|
const page = `<!DOCTYPE html>
|
|
51
65
|
<html lang="en">
|
|
52
66
|
<head>
|
|
53
67
|
<meta charset="UTF-8">
|
|
54
68
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
55
|
-
<title>${title}</title>
|
|
69
|
+
<title>${escapeHtml(title)}</title>
|
|
56
70
|
<style>
|
|
57
71
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
58
72
|
body {
|
package/src/docx.js
CHANGED
|
@@ -104,7 +104,9 @@ function htmlDecode(s) {
|
|
|
104
104
|
.replace(/>/g, ">")
|
|
105
105
|
.replace(/"/g, '"')
|
|
106
106
|
.replace(/'/g, "'")
|
|
107
|
-
.replace(/ /g, " ")
|
|
107
|
+
.replace(/ /g, " ")
|
|
108
|
+
.replace(/&#(\d+);/g, (_, n) => String.fromCharCode(Number(n)))
|
|
109
|
+
.replace(/&#x([0-9a-fA-F]+);/g, (_, h) => String.fromCharCode(parseInt(h, 16)));
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
// ─── Block token → Paragraph[] ──────────────────────────────────────────────
|
package/src/render.js
CHANGED
|
@@ -95,7 +95,9 @@ function htmlDecode(s) {
|
|
|
95
95
|
.replace(/>/g, ">")
|
|
96
96
|
.replace(/"/g, '"')
|
|
97
97
|
.replace(/'/g, "'")
|
|
98
|
-
.replace(/ /g, " ")
|
|
98
|
+
.replace(/ /g, " ")
|
|
99
|
+
.replace(/&#(\d+);/g, (_, n) => String.fromCharCode(Number(n)))
|
|
100
|
+
.replace(/&#x([0-9a-fA-F]+);/g, (_, h) => String.fromCharCode(parseInt(h, 16)));
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
// ─── Inline renderer ───────────────────────────────────────────────────────────
|
|
@@ -202,11 +204,6 @@ function code(tok, w) {
|
|
|
202
204
|
// Expand tabs to 2 spaces
|
|
203
205
|
const rawText = (tok.text ?? "").replace(/\t/g, " ");
|
|
204
206
|
|
|
205
|
-
// innerW = content width between borders (1 space padding each side)
|
|
206
|
-
const innerW = w - 2;
|
|
207
|
-
// borderW = total inner span for the box (includes the 1px padding each side)
|
|
208
|
-
const borderW = innerW + 2;
|
|
209
|
-
|
|
210
207
|
let rawLines;
|
|
211
208
|
if (rawText === "") {
|
|
212
209
|
rawLines = [""];
|
|
@@ -239,13 +236,21 @@ function code(tok, w) {
|
|
|
239
236
|
// Pad to same length just in case highlight produced different line count
|
|
240
237
|
while (highlighted.length < rawLines.length) highlighted.push("");
|
|
241
238
|
|
|
239
|
+
// Size the box to the longest line (capped at terminal width)
|
|
240
|
+
const maxLineW = highlighted.reduce((m, l) => Math.max(m, vlen(l)), 0);
|
|
241
|
+
const langTagLen = lang ? 1 + lang.length + 1 : 0; // " lang " visual chars
|
|
242
|
+
// innerW = content area between pipes (1 space padding each side)
|
|
243
|
+
// Must fit: longest line, lang tag in top border, and minimum 4 chars
|
|
244
|
+
const innerW = Math.min(w - 2, Math.max(maxLineW, langTagLen + 2, 4));
|
|
245
|
+
// borderW = total inner span for the box (includes the 1-char padding each side)
|
|
246
|
+
const borderW = innerW + 2;
|
|
247
|
+
|
|
242
248
|
const lines = [""];
|
|
243
249
|
|
|
244
250
|
// Top border: ┌─ lang ─────┐ or ┌──────────────┐
|
|
245
251
|
let top;
|
|
246
252
|
if (lang) {
|
|
247
253
|
const langTag = " " + c.codeLang(lang) + " ";
|
|
248
|
-
const langTagLen = 1 + lang.length + 1; // visual chars
|
|
249
254
|
const fill = Math.max(0, borderW - langTagLen - 1); // -1 for leading "─"
|
|
250
255
|
top =
|
|
251
256
|
c.border("┌─") +
|