fix(tui): render inline markdown formatting with ANSI codes
Block-level renderer methods (paragraph, heading, blockquote, list) were using raw token.text instead of this.parser.parseInline(tokens), causing bold, italic, and inline code to never render. Add table renderer with aligned columns and box-drawing separators. Remove unused marked-terminal dependency (incompatible with marked v17). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -28,7 +28,6 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/better-sqlite3": "^7.6.0",
|
"@types/better-sqlite3": "^7.6.0",
|
||||||
"@types/marked-terminal": "^6.1.1",
|
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/turndown": "^5.0.0",
|
"@types/turndown": "^5.0.0",
|
||||||
@@ -56,7 +55,6 @@
|
|||||||
"ink-text-input": "^6.0.0",
|
"ink-text-input": "^6.0.0",
|
||||||
"linkedom": "^0.18.0",
|
"linkedom": "^0.18.0",
|
||||||
"marked": "^17.0.1",
|
"marked": "^17.0.1",
|
||||||
"marked-terminal": "^7.3.0",
|
|
||||||
"ollama": "^0.5.0",
|
"ollama": "^0.5.0",
|
||||||
"openai": "^4.0.0",
|
"openai": "^4.0.0",
|
||||||
"puppeteer-core": "^24.37.2",
|
"puppeteer-core": "^24.37.2",
|
||||||
|
|||||||
Generated
-113
@@ -59,9 +59,6 @@ importers:
|
|||||||
marked:
|
marked:
|
||||||
specifier: ^17.0.1
|
specifier: ^17.0.1
|
||||||
version: 17.0.1
|
version: 17.0.1
|
||||||
marked-terminal:
|
|
||||||
specifier: ^7.3.0
|
|
||||||
version: 7.3.0(marked@17.0.1)
|
|
||||||
ollama:
|
ollama:
|
||||||
specifier: ^0.5.0
|
specifier: ^0.5.0
|
||||||
version: 0.5.18
|
version: 0.5.18
|
||||||
@@ -93,9 +90,6 @@ importers:
|
|||||||
'@types/better-sqlite3':
|
'@types/better-sqlite3':
|
||||||
specifier: ^7.6.0
|
specifier: ^7.6.0
|
||||||
version: 7.6.13
|
version: 7.6.13
|
||||||
'@types/marked-terminal':
|
|
||||||
specifier: ^6.1.1
|
|
||||||
version: 6.1.1
|
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.0.0
|
specifier: ^22.0.0
|
||||||
version: 22.19.7
|
version: 22.19.7
|
||||||
@@ -275,10 +269,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
|
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@colors/colors@1.5.0':
|
|
||||||
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
|
|
||||||
engines: {node: '>=0.1.90'}
|
|
||||||
|
|
||||||
'@discordjs/builders@1.13.1':
|
'@discordjs/builders@1.13.1':
|
||||||
resolution: {integrity: sha512-cOU0UDHc3lp/5nKByDxkmRiNZBpdp0kx55aarbiAfakfKJHlxv/yFW1zmIqCAmwH5CRlrH9iMFKJMpvW4DPB+w==}
|
resolution: {integrity: sha512-cOU0UDHc3lp/5nKByDxkmRiNZBpdp0kx55aarbiAfakfKJHlxv/yFW1zmIqCAmwH5CRlrH9iMFKJMpvW4DPB+w==}
|
||||||
engines: {node: '>=16.11.0'}
|
engines: {node: '>=16.11.0'}
|
||||||
@@ -708,10 +698,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==}
|
resolution: {integrity: sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==}
|
||||||
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
|
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
|
||||||
|
|
||||||
'@sindresorhus/is@4.6.0':
|
|
||||||
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
'@slack/bolt@4.6.0':
|
'@slack/bolt@4.6.0':
|
||||||
resolution: {integrity: sha512-xPgfUs2+OXSugz54Ky07pA890+Qydk22SYToi8uGpXeHSt1JWwFJkRyd/9Vlg5I1AdfdpGXExDpwnbuN9Q/2dQ==}
|
resolution: {integrity: sha512-xPgfUs2+OXSugz54Ky07pA890+Qydk22SYToi8uGpXeHSt1JWwFJkRyd/9Vlg5I1AdfdpGXExDpwnbuN9Q/2dQ==}
|
||||||
engines: {node: '>=18', npm: '>=8.6.0'}
|
engines: {node: '>=18', npm: '>=8.6.0'}
|
||||||
@@ -939,9 +925,6 @@ packages:
|
|||||||
'@types/body-parser@1.19.6':
|
'@types/body-parser@1.19.6':
|
||||||
resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
|
resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
|
||||||
|
|
||||||
'@types/cardinal@2.1.1':
|
|
||||||
resolution: {integrity: sha512-/xCVwg8lWvahHsV2wXZt4i64H1sdL+sN1Uoq7fAc8/FA6uYHjuIveDwPwvGUYp4VZiv85dVl6J/Bum3NDAOm8g==}
|
|
||||||
|
|
||||||
'@types/chai@5.2.3':
|
'@types/chai@5.2.3':
|
||||||
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
|
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
|
||||||
|
|
||||||
@@ -969,9 +952,6 @@ packages:
|
|||||||
'@types/jsonwebtoken@9.0.10':
|
'@types/jsonwebtoken@9.0.10':
|
||||||
resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
|
resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
|
||||||
|
|
||||||
'@types/marked-terminal@6.1.1':
|
|
||||||
resolution: {integrity: sha512-DfoUqkmFDCED7eBY9vFUhJ9fW8oZcMAK5EwRDQ9drjTbpQa+DnBTQQCwWhTFVf4WsZ6yYcJTI8D91wxTWXRZZQ==}
|
|
||||||
|
|
||||||
'@types/ms@2.1.0':
|
'@types/ms@2.1.0':
|
||||||
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||||
|
|
||||||
@@ -1292,10 +1272,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
|
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
|
||||||
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
|
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
|
||||||
|
|
||||||
char-regex@1.0.2:
|
|
||||||
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
check-error@2.1.3:
|
check-error@2.1.3:
|
||||||
resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
|
resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
|
||||||
engines: {node: '>= 16'}
|
engines: {node: '>= 16'}
|
||||||
@@ -1321,10 +1297,6 @@ packages:
|
|||||||
engines: {node: '>=8.0.0', npm: '>=5.0.0'}
|
engines: {node: '>=8.0.0', npm: '>=5.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
cli-table3@0.6.5:
|
|
||||||
resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
|
|
||||||
engines: {node: 10.* || >= 12.*}
|
|
||||||
|
|
||||||
cli-truncate@5.1.1:
|
cli-truncate@5.1.1:
|
||||||
resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==}
|
resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
@@ -1514,9 +1486,6 @@ packages:
|
|||||||
emoji-regex@8.0.0:
|
emoji-regex@8.0.0:
|
||||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||||
|
|
||||||
emojilib@2.4.0:
|
|
||||||
resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==}
|
|
||||||
|
|
||||||
encodeurl@2.0.0:
|
encodeurl@2.0.0:
|
||||||
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
|
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -2158,17 +2127,6 @@ packages:
|
|||||||
magic-string@0.30.21:
|
magic-string@0.30.21:
|
||||||
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
||||||
|
|
||||||
marked-terminal@7.3.0:
|
|
||||||
resolution: {integrity: sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==}
|
|
||||||
engines: {node: '>=16.0.0'}
|
|
||||||
peerDependencies:
|
|
||||||
marked: '>=1 <16'
|
|
||||||
|
|
||||||
marked@11.2.0:
|
|
||||||
resolution: {integrity: sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==}
|
|
||||||
engines: {node: '>= 18'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
marked@17.0.1:
|
marked@17.0.1:
|
||||||
resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==}
|
resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==}
|
||||||
engines: {node: '>= 20'}
|
engines: {node: '>= 20'}
|
||||||
@@ -2269,10 +2227,6 @@ packages:
|
|||||||
engines: {node: '>=10.5.0'}
|
engines: {node: '>=10.5.0'}
|
||||||
deprecated: Use your platform's native DOMException instead
|
deprecated: Use your platform's native DOMException instead
|
||||||
|
|
||||||
node-emoji@2.2.0:
|
|
||||||
resolution: {integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==}
|
|
||||||
engines: {node: '>=18'}
|
|
||||||
|
|
||||||
node-fetch@2.7.0:
|
node-fetch@2.7.0:
|
||||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||||
engines: {node: 4.x || >=6.0.0}
|
engines: {node: 4.x || >=6.0.0}
|
||||||
@@ -2610,10 +2564,6 @@ packages:
|
|||||||
simple-get@4.0.1:
|
simple-get@4.0.1:
|
||||||
resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
|
resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
|
||||||
|
|
||||||
skin-tone@2.0.0:
|
|
||||||
resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
slice-ansi@7.1.2:
|
slice-ansi@7.1.2:
|
||||||
resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
|
resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -2699,10 +2649,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
supports-hyperlinks@3.2.0:
|
|
||||||
resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==}
|
|
||||||
engines: {node: '>=14.18'}
|
|
||||||
|
|
||||||
tar-fs@2.1.4:
|
tar-fs@2.1.4:
|
||||||
resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==}
|
resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==}
|
||||||
|
|
||||||
@@ -2812,10 +2758,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==}
|
resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==}
|
||||||
engines: {node: '>=18.17'}
|
engines: {node: '>=18.17'}
|
||||||
|
|
||||||
unicode-emoji-modifier-base@1.0.0:
|
|
||||||
resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==}
|
|
||||||
engines: {node: '>=4'}
|
|
||||||
|
|
||||||
universalify@2.0.1:
|
universalify@2.0.1:
|
||||||
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
@@ -3473,9 +3415,6 @@ snapshots:
|
|||||||
|
|
||||||
'@babel/helper-validator-identifier@7.28.5': {}
|
'@babel/helper-validator-identifier@7.28.5': {}
|
||||||
|
|
||||||
'@colors/colors@1.5.0':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@discordjs/builders@1.13.1':
|
'@discordjs/builders@1.13.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@discordjs/formatters': 0.6.2
|
'@discordjs/formatters': 0.6.2
|
||||||
@@ -3797,8 +3736,6 @@ snapshots:
|
|||||||
|
|
||||||
'@sapphire/snowflake@3.5.3': {}
|
'@sapphire/snowflake@3.5.3': {}
|
||||||
|
|
||||||
'@sindresorhus/is@4.6.0': {}
|
|
||||||
|
|
||||||
'@slack/bolt@4.6.0(@types/express@5.0.6)':
|
'@slack/bolt@4.6.0(@types/express@5.0.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@slack/logger': 4.0.0
|
'@slack/logger': 4.0.0
|
||||||
@@ -4179,8 +4116,6 @@ snapshots:
|
|||||||
'@types/connect': 3.4.38
|
'@types/connect': 3.4.38
|
||||||
'@types/node': 22.19.7
|
'@types/node': 22.19.7
|
||||||
|
|
||||||
'@types/cardinal@2.1.1': {}
|
|
||||||
|
|
||||||
'@types/chai@5.2.3':
|
'@types/chai@5.2.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/deep-eql': 4.0.2
|
'@types/deep-eql': 4.0.2
|
||||||
@@ -4216,13 +4151,6 @@ snapshots:
|
|||||||
'@types/ms': 2.1.0
|
'@types/ms': 2.1.0
|
||||||
'@types/node': 22.19.7
|
'@types/node': 22.19.7
|
||||||
|
|
||||||
'@types/marked-terminal@6.1.1':
|
|
||||||
dependencies:
|
|
||||||
'@types/cardinal': 2.1.1
|
|
||||||
'@types/node': 22.19.7
|
|
||||||
chalk: 5.6.2
|
|
||||||
marked: 11.2.0
|
|
||||||
|
|
||||||
'@types/ms@2.1.0': {}
|
'@types/ms@2.1.0': {}
|
||||||
|
|
||||||
'@types/node-fetch@2.6.13':
|
'@types/node-fetch@2.6.13':
|
||||||
@@ -4584,8 +4512,6 @@ snapshots:
|
|||||||
|
|
||||||
chalk@5.6.2: {}
|
chalk@5.6.2: {}
|
||||||
|
|
||||||
char-regex@1.0.2: {}
|
|
||||||
|
|
||||||
check-error@2.1.3: {}
|
check-error@2.1.3: {}
|
||||||
|
|
||||||
chownr@1.1.4: {}
|
chownr@1.1.4: {}
|
||||||
@@ -4611,12 +4537,6 @@ snapshots:
|
|||||||
parse5-htmlparser2-tree-adapter: 6.0.1
|
parse5-htmlparser2-tree-adapter: 6.0.1
|
||||||
yargs: 16.2.0
|
yargs: 16.2.0
|
||||||
|
|
||||||
cli-table3@0.6.5:
|
|
||||||
dependencies:
|
|
||||||
string-width: 4.2.3
|
|
||||||
optionalDependencies:
|
|
||||||
'@colors/colors': 1.5.0
|
|
||||||
|
|
||||||
cli-truncate@5.1.1:
|
cli-truncate@5.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
slice-ansi: 7.1.2
|
slice-ansi: 7.1.2
|
||||||
@@ -4808,8 +4728,6 @@ snapshots:
|
|||||||
|
|
||||||
emoji-regex@8.0.0: {}
|
emoji-regex@8.0.0: {}
|
||||||
|
|
||||||
emojilib@2.4.0: {}
|
|
||||||
|
|
||||||
encodeurl@2.0.0: {}
|
encodeurl@2.0.0: {}
|
||||||
|
|
||||||
end-of-stream@1.4.5:
|
end-of-stream@1.4.5:
|
||||||
@@ -5551,19 +5469,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
marked-terminal@7.3.0(marked@17.0.1):
|
|
||||||
dependencies:
|
|
||||||
ansi-escapes: 7.3.0
|
|
||||||
ansi-regex: 6.2.2
|
|
||||||
chalk: 5.6.2
|
|
||||||
cli-highlight: 2.1.11
|
|
||||||
cli-table3: 0.6.5
|
|
||||||
marked: 17.0.1
|
|
||||||
node-emoji: 2.2.0
|
|
||||||
supports-hyperlinks: 3.2.0
|
|
||||||
|
|
||||||
marked@11.2.0: {}
|
|
||||||
|
|
||||||
marked@17.0.1: {}
|
marked@17.0.1: {}
|
||||||
|
|
||||||
math-intrinsics@1.1.0: {}
|
math-intrinsics@1.1.0: {}
|
||||||
@@ -5634,13 +5539,6 @@ snapshots:
|
|||||||
|
|
||||||
node-domexception@1.0.0: {}
|
node-domexception@1.0.0: {}
|
||||||
|
|
||||||
node-emoji@2.2.0:
|
|
||||||
dependencies:
|
|
||||||
'@sindresorhus/is': 4.6.0
|
|
||||||
char-regex: 1.0.2
|
|
||||||
emojilib: 2.4.0
|
|
||||||
skin-tone: 2.0.0
|
|
||||||
|
|
||||||
node-fetch@2.7.0:
|
node-fetch@2.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
@@ -6070,10 +5968,6 @@ snapshots:
|
|||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
simple-concat: 1.0.1
|
simple-concat: 1.0.1
|
||||||
|
|
||||||
skin-tone@2.0.0:
|
|
||||||
dependencies:
|
|
||||||
unicode-emoji-modifier-base: 1.0.0
|
|
||||||
|
|
||||||
slice-ansi@7.1.2:
|
slice-ansi@7.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 6.2.3
|
ansi-styles: 6.2.3
|
||||||
@@ -6166,11 +6060,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-flag: 4.0.0
|
has-flag: 4.0.0
|
||||||
|
|
||||||
supports-hyperlinks@3.2.0:
|
|
||||||
dependencies:
|
|
||||||
has-flag: 4.0.0
|
|
||||||
supports-color: 7.2.0
|
|
||||||
|
|
||||||
tar-fs@2.1.4:
|
tar-fs@2.1.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
chownr: 1.1.4
|
chownr: 1.1.4
|
||||||
@@ -6288,8 +6177,6 @@ snapshots:
|
|||||||
|
|
||||||
undici@6.21.3: {}
|
undici@6.21.3: {}
|
||||||
|
|
||||||
unicode-emoji-modifier-base@1.0.0: {}
|
|
||||||
|
|
||||||
universalify@2.0.1:
|
universalify@2.0.1:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,37 @@ describe('renderMarkdown', () => {
|
|||||||
expect(result).toContain('Hello world');
|
expect(result).toContain('Hello world');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders bold text', () => {
|
it('renders bold text with ANSI bold code', () => {
|
||||||
const result = renderMarkdown('This is **bold** text');
|
const result = renderMarkdown('This is **bold** text');
|
||||||
|
expect(result).toContain('\x1b[1m');
|
||||||
|
expect(result).toContain('bold');
|
||||||
|
expect(result).toContain('\x1b[0m');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders italic text with ANSI italic code', () => {
|
||||||
|
const result = renderMarkdown('This is *italic* text');
|
||||||
|
expect(result).toContain('\x1b[3m');
|
||||||
|
expect(result).toContain('italic');
|
||||||
|
expect(result).toContain('\x1b[0m');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders inline code with ANSI cyan code', () => {
|
||||||
|
const result = renderMarkdown('Use `console.log()` for debugging');
|
||||||
|
expect(result).toContain('\x1b[36m');
|
||||||
|
expect(result).toContain('console.log()');
|
||||||
|
expect(result).toContain('\x1b[0m');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders headings with bold + underline', () => {
|
||||||
|
const result = renderMarkdown('# My Heading');
|
||||||
|
expect(result).toContain('\x1b[1m\x1b[4m');
|
||||||
|
expect(result).toContain('My Heading');
|
||||||
|
expect(result).toContain('\x1b[0m');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders heading with inline formatting', () => {
|
||||||
|
const result = renderMarkdown('## A **bold** heading');
|
||||||
|
expect(result).toContain('\x1b[1m');
|
||||||
expect(result).toContain('bold');
|
expect(result).toContain('bold');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -18,14 +47,66 @@ describe('renderMarkdown', () => {
|
|||||||
expect(result).toContain('x');
|
expect(result).toContain('x');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders inline code', () => {
|
it('renders code blocks with unknown language without crashing', () => {
|
||||||
const result = renderMarkdown('Use `console.log()` for debugging');
|
const result = renderMarkdown('```madeuplang\nsome code\n```');
|
||||||
expect(result).toContain('console.log()');
|
expect(result).toContain('some code');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders lists', () => {
|
it('renders unordered lists', () => {
|
||||||
const result = renderMarkdown('- Item 1\n- Item 2');
|
const result = renderMarkdown('- Item 1\n- Item 2');
|
||||||
|
expect(result).toContain('•');
|
||||||
expect(result).toContain('Item 1');
|
expect(result).toContain('Item 1');
|
||||||
expect(result).toContain('Item 2');
|
expect(result).toContain('Item 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders inline formatting inside list items', () => {
|
||||||
|
const result = renderMarkdown('- **bold** item\n- `code` item');
|
||||||
|
expect(result).toContain('\x1b[1m');
|
||||||
|
expect(result).toContain('bold');
|
||||||
|
expect(result).toContain('\x1b[36m');
|
||||||
|
expect(result).toContain('code');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders blockquotes with │ prefix', () => {
|
||||||
|
const result = renderMarkdown('> This is a quote');
|
||||||
|
expect(result).toContain('│');
|
||||||
|
expect(result).toContain('This is a quote');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders inline formatting inside blockquotes', () => {
|
||||||
|
const result = renderMarkdown('> A **bold** quote');
|
||||||
|
expect(result).toContain('│');
|
||||||
|
expect(result).toContain('\x1b[1m');
|
||||||
|
expect(result).toContain('bold');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders tables with │ separator', () => {
|
||||||
|
const result = renderMarkdown('| Col A | Col B |\n|-------|-------|\n| 1 | 2 |\n| 3 | 4 |');
|
||||||
|
expect(result).toContain('│');
|
||||||
|
expect(result).toContain('Col A');
|
||||||
|
expect(result).toContain('Col B');
|
||||||
|
expect(result).toContain('1');
|
||||||
|
expect(result).toContain('4');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders table headers in bold', () => {
|
||||||
|
const result = renderMarkdown('| Name | Value |\n|------|-------|\n| a | b |');
|
||||||
|
// Header cells should have bold ANSI
|
||||||
|
const lines = result.split('\n');
|
||||||
|
const headerLine = lines[0];
|
||||||
|
expect(headerLine).toContain('\x1b[1m');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders horizontal rules', () => {
|
||||||
|
const result = renderMarkdown('---');
|
||||||
|
expect(result).toContain('─');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders links with underline and blue URL', () => {
|
||||||
|
const result = renderMarkdown('[click here](https://example.com)');
|
||||||
|
expect(result).toContain('\x1b[4m');
|
||||||
|
expect(result).toContain('click here');
|
||||||
|
expect(result).toContain('\x1b[34m');
|
||||||
|
expect(result).toContain('https://example.com');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ function convertHtmlToTerminal(text: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Custom renderer as an object for marked.use()
|
// Custom renderer as an object for marked.use()
|
||||||
|
// Methods that contain inline children use this.parser.parseInline(tokens)
|
||||||
|
// Methods that contain block children use this.parser.parse(tokens)
|
||||||
const terminalRenderer: RendererObject = {
|
const terminalRenderer: RendererObject = {
|
||||||
code({ text, lang }: Tokens.Code): string {
|
code({ text, lang }: Tokens.Code): string {
|
||||||
try {
|
try {
|
||||||
@@ -59,34 +61,85 @@ const terminalRenderer: RendererObject = {
|
|||||||
return `\x1b[3m${text}\x1b[0m`; // Italic
|
return `\x1b[3m${text}\x1b[0m`; // Italic
|
||||||
},
|
},
|
||||||
|
|
||||||
paragraph({ text }: Tokens.Paragraph): string {
|
paragraph({ tokens }: Tokens.Paragraph): string {
|
||||||
return text + '\n';
|
return this.parser.parseInline(tokens) + '\n';
|
||||||
},
|
},
|
||||||
|
|
||||||
list({ items, ordered }: Tokens.List): string {
|
list({ items, ordered, start }: Tokens.List): string {
|
||||||
let body = '';
|
let body = '';
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
const item = items[i];
|
const item = items[i];
|
||||||
const bullet = ordered ? `${i + 1}. ` : ' • ';
|
const bullet = ordered ? `${(start || 1) + i}. ` : ' • ';
|
||||||
body += bullet + item.text + '\n';
|
const content = this.parser.parse(item.tokens).replace(/\n$/, '');
|
||||||
|
body += bullet + content + '\n';
|
||||||
}
|
}
|
||||||
return body;
|
return body;
|
||||||
},
|
},
|
||||||
|
|
||||||
listitem({ text }: Tokens.ListItem): string {
|
listitem({ tokens }: Tokens.ListItem): string {
|
||||||
return text;
|
return this.parser.parse(tokens);
|
||||||
},
|
},
|
||||||
|
|
||||||
heading({ text }: Tokens.Heading): string {
|
heading({ tokens, depth }: Tokens.Heading): string {
|
||||||
return `\x1b[1m\x1b[4m${text}\x1b[0m\n`; // Bold + underline
|
const text = this.parser.parseInline(tokens);
|
||||||
|
const prefix = depth <= 2 ? '' : '#'.repeat(depth) + ' ';
|
||||||
|
return `\x1b[1m\x1b[4m${prefix}${text}\x1b[0m\n`; // Bold + underline
|
||||||
},
|
},
|
||||||
|
|
||||||
link({ text, href }: Tokens.Link): string {
|
link({ text, href }: Tokens.Link): string {
|
||||||
return `\x1b[4m${text}\x1b[0m (\x1b[34m${href}\x1b[0m)`; // Underline text, blue URL
|
return `\x1b[4m${text}\x1b[0m (\x1b[34m${href}\x1b[0m)`; // Underline text, blue URL
|
||||||
},
|
},
|
||||||
|
|
||||||
blockquote({ text }: Tokens.Blockquote): string {
|
blockquote({ tokens }: Tokens.Blockquote): string {
|
||||||
return text.split('\n').map((line: string) => ` │ ${line}`).join('\n') + '\n';
|
const body = this.parser.parse(tokens);
|
||||||
|
return body.split('\n').map((line: string) => ` │ ${line}`).join('\n') + '\n';
|
||||||
|
},
|
||||||
|
|
||||||
|
table({ header, rows, align }: Tokens.Table): string {
|
||||||
|
// Render cell contents
|
||||||
|
const headerTexts = header.map((cell: Tokens.TableCell) =>
|
||||||
|
this.parser.parseInline(cell.tokens)
|
||||||
|
);
|
||||||
|
const rowTexts = rows.map((row: Tokens.TableCell[]) =>
|
||||||
|
row.map((cell: Tokens.TableCell) => this.parser.parseInline(cell.tokens))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Calculate column widths (strip ANSI for measurement)
|
||||||
|
const stripAnsi = (s: string) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
||||||
|
const colWidths = headerTexts.map((h: string, i: number) => {
|
||||||
|
const cellWidths = rowTexts.map((row: string[]) => stripAnsi(row[i] || '').length);
|
||||||
|
return Math.max(stripAnsi(h).length, ...cellWidths);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pad cell to width respecting ANSI codes
|
||||||
|
const pad = (text: string, width: number, alignment: string | null) => {
|
||||||
|
const visible = stripAnsi(text).length;
|
||||||
|
const diff = width - visible;
|
||||||
|
if (diff <= 0) return text;
|
||||||
|
if (alignment === 'right') return ' '.repeat(diff) + text;
|
||||||
|
if (alignment === 'center') {
|
||||||
|
const left = Math.floor(diff / 2);
|
||||||
|
return ' '.repeat(left) + text + ' '.repeat(diff - left);
|
||||||
|
}
|
||||||
|
return text + ' '.repeat(diff);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Build header row
|
||||||
|
const headerRow = ' ' + headerTexts.map((h: string, i: number) =>
|
||||||
|
`\x1b[1m${pad(h, colWidths[i], align[i])}\x1b[0m`
|
||||||
|
).join(' │ ');
|
||||||
|
|
||||||
|
// Build separator
|
||||||
|
const separator = '─' + colWidths.map((w: number) => '─'.repeat(w)).join('─┼─') + '─';
|
||||||
|
|
||||||
|
// Build data rows
|
||||||
|
const dataRows = rowTexts.map((row: string[]) =>
|
||||||
|
' ' + row.map((cell: string, i: number) =>
|
||||||
|
pad(cell, colWidths[i], align[i])
|
||||||
|
).join(' │ ')
|
||||||
|
);
|
||||||
|
|
||||||
|
return [headerRow, separator, ...dataRows].join('\n') + '\n';
|
||||||
},
|
},
|
||||||
|
|
||||||
hr(): string {
|
hr(): string {
|
||||||
|
|||||||
Reference in New Issue
Block a user