@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunkinfrunkin/mdcat",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "View markdown files beautifully in your terminal",
5
5
  "type": "module",
6
6
  "bin": {
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
50
+ }
51
+
48
52
  function openInBrowser(title, content) {
49
- const html = marked.parse(content);
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(/&gt;/g, ">")
105
105
  .replace(/&quot;/g, '"')
106
106
  .replace(/&#39;/g, "'")
107
- .replace(/&nbsp;/g, " ");
107
+ .replace(/&nbsp;/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(/&gt;/g, ">")
96
96
  .replace(/&quot;/g, '"')
97
97
  .replace(/&#39;/g, "'")
98
- .replace(/&nbsp;/g, " ");
98
+ .replace(/&nbsp;/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("┌─") +