mirror of
https://github.com/morten-olsen/http.md.git
synced 2026-02-08 00:46:28 +01:00
refact: ink based terminal view (#17)
This commit is contained in:
@@ -51,7 +51,7 @@ Create a file named `example.md`:
|
||||
|
||||
::raw-md[./examples/getting-started.md]
|
||||
|
||||
### Rendering Documents
|
||||
### Rendering Document
|
||||
|
||||
You have two primary ways to render your `http.md` file:
|
||||
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
"@pnpm/find-workspace-packages": "^6.0.9",
|
||||
"@types/blessed": "^0.1.25",
|
||||
"@types/chai": "^5.2.2",
|
||||
"@types/ink": "^2.0.3",
|
||||
"@types/marked-terminal": "^6.1.1",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/terminal-kit": "^2.5.7",
|
||||
"tsx": "^4.19.4",
|
||||
"typescript": "^5.8.3"
|
||||
@@ -44,11 +46,13 @@
|
||||
"eventemitter3": "^5.0.1",
|
||||
"handlebars": "^4.7.8",
|
||||
"hastscript": "^9.0.1",
|
||||
"ink": "^5.2.1",
|
||||
"marked": "^15.0.11",
|
||||
"marked-terminal": "^7.3.0",
|
||||
"mdast-util-to-markdown": "^2.1.2",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"mdast-util-toc": "^7.1.0",
|
||||
"react": "^18.3.1",
|
||||
"rehype-stringify": "^10.0.1",
|
||||
"remark-behead": "^3.1.0",
|
||||
"remark-directive": "^4.0.0",
|
||||
@@ -59,6 +63,7 @@
|
||||
"terminal-kit": "^3.1.2",
|
||||
"unified": "^11.0.5",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"wrap-ansi": "^9.0.0",
|
||||
"yaml": "^2.8.0"
|
||||
}
|
||||
}
|
||||
|
||||
337
pnpm-lock.yaml
generated
337
pnpm-lock.yaml
generated
@@ -32,6 +32,9 @@ importers:
|
||||
hastscript:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
ink:
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1(@types/react@18.3.21)(react@18.3.1)
|
||||
marked:
|
||||
specifier: ^15.0.11
|
||||
version: 15.0.11
|
||||
@@ -47,6 +50,9 @@ importers:
|
||||
mdast-util-toc:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
react:
|
||||
specifier: ^18.3.1
|
||||
version: 18.3.1
|
||||
rehype-stringify:
|
||||
specifier: ^10.0.1
|
||||
version: 10.0.1
|
||||
@@ -77,6 +83,9 @@ importers:
|
||||
unist-util-visit:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
wrap-ansi:
|
||||
specifier: ^9.0.0
|
||||
version: 9.0.0
|
||||
yaml:
|
||||
specifier: ^2.8.0
|
||||
version: 2.8.0
|
||||
@@ -90,6 +99,9 @@ importers:
|
||||
'@types/chai':
|
||||
specifier: ^5.2.2
|
||||
version: 5.2.2
|
||||
'@types/ink':
|
||||
specifier: ^2.0.3
|
||||
version: 2.0.3(@types/react@18.3.21)(react@18.3.1)
|
||||
'@types/marked-terminal':
|
||||
specifier: ^6.1.1
|
||||
version: 6.1.1
|
||||
@@ -99,6 +111,9 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^22.15.18
|
||||
version: 22.15.18
|
||||
'@types/react':
|
||||
specifier: ^18.3.12
|
||||
version: 18.3.21
|
||||
'@types/terminal-kit':
|
||||
specifier: ^2.5.7
|
||||
version: 2.5.7
|
||||
@@ -111,6 +126,10 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@alcalzone/ansi-tokenize@0.1.3':
|
||||
resolution: {integrity: sha512-3yWxPTq3UQ/FY9p1ErPxIyfT64elWaMvM9lIHnaqpyft63tkxodF5aUElYHrdisWve5cETkh1+KBw1yJuW0aRw==}
|
||||
engines: {node: '>=14.13.1'}
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -455,6 +474,10 @@ packages:
|
||||
'@types/hast@3.0.4':
|
||||
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
|
||||
|
||||
'@types/ink@2.0.3':
|
||||
resolution: {integrity: sha512-DYKIKEJqhsGfQ/jgX0t9BzfHmBJ/9dBBT2MDsHAQRAfOPhEe7LZm5QeNBx1J34/e108StCPuJ3r4bh1y38kCJA==}
|
||||
deprecated: This is a stub types definition. ink provides its own type definitions, so you do not need this installed.
|
||||
|
||||
'@types/marked-terminal@6.1.1':
|
||||
resolution: {integrity: sha512-DfoUqkmFDCED7eBY9vFUhJ9fW8oZcMAK5EwRDQ9drjTbpQa+DnBTQQCwWhTFVf4WsZ6yYcJTI8D91wxTWXRZZQ==}
|
||||
|
||||
@@ -470,6 +493,12 @@ packages:
|
||||
'@types/node@22.15.18':
|
||||
resolution: {integrity: sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==}
|
||||
|
||||
'@types/prop-types@15.7.14':
|
||||
resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
|
||||
|
||||
'@types/react@18.3.21':
|
||||
resolution: {integrity: sha512-gXLBtmlcRJeT09/sI4PxVwyrku6SaNUj/6cMubjE6T6XdY1fDmBL7r0nX0jbSZPU/Xr0KuwLLZh6aOYY5d91Xw==}
|
||||
|
||||
'@types/ssri@7.1.5':
|
||||
resolution: {integrity: sha512-odD/56S3B51liILSk5aXJlnYt99S6Rt9EFDDqGtJM26rKHApHcwyU/UoYHrzKkdkHMAIquGWCuHtQTbes+FRQw==}
|
||||
|
||||
@@ -522,6 +551,10 @@ packages:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@6.2.1:
|
||||
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
any-promise@1.3.0:
|
||||
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
|
||||
|
||||
@@ -538,6 +571,10 @@ packages:
|
||||
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
auto-bind@5.0.1:
|
||||
resolution: {integrity: sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
bail@2.0.2:
|
||||
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
|
||||
|
||||
@@ -619,10 +656,18 @@ packages:
|
||||
resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
cli-boxes@3.0.0:
|
||||
resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
cli-columns@4.0.0:
|
||||
resolution: {integrity: sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
cli-cursor@4.0.0:
|
||||
resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
cli-highlight@2.1.11:
|
||||
resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==}
|
||||
engines: {node: '>=8.0.0', npm: '>=5.0.0'}
|
||||
@@ -632,6 +677,10 @@ packages:
|
||||
resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
|
||||
engines: {node: 10.* || >= 12.*}
|
||||
|
||||
cli-truncate@4.0.0:
|
||||
resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
cliui@7.0.4:
|
||||
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
|
||||
|
||||
@@ -639,6 +688,10 @@ packages:
|
||||
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
|
||||
engines: {node: '>=0.8'}
|
||||
|
||||
code-excerpt@4.0.0:
|
||||
resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
@@ -656,6 +709,10 @@ packages:
|
||||
config-chain@1.1.13:
|
||||
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
|
||||
|
||||
convert-to-spaces@2.0.1:
|
||||
resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -664,6 +721,9 @@ packages:
|
||||
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
cwise-compiler@1.1.3:
|
||||
resolution: {integrity: sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ==}
|
||||
|
||||
@@ -704,6 +764,9 @@ packages:
|
||||
resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
emoji-regex@10.4.0:
|
||||
resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==}
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
@@ -717,6 +780,9 @@ packages:
|
||||
error-ex@1.3.2:
|
||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||
|
||||
es-toolkit@1.38.0:
|
||||
resolution: {integrity: sha512-OT3AxczYYd3W50bCj4V0hKoOAfqIy9tof0leNQYekEDxVKir3RTVTJOLij7VAe6fsCNsGhC0JqIkURpMXTCSEA==}
|
||||
|
||||
esbuild@0.25.4:
|
||||
resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -726,6 +792,10 @@ packages:
|
||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
escape-string-regexp@2.0.0:
|
||||
resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
escape-string-regexp@4.0.0:
|
||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -770,6 +840,10 @@ packages:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
get-east-asian-width@1.3.0:
|
||||
resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
get-source@2.0.12:
|
||||
resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==}
|
||||
|
||||
@@ -828,6 +902,10 @@ packages:
|
||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||
engines: {node: '>=0.8.19'}
|
||||
|
||||
indent-string@5.0.0:
|
||||
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
individual@3.0.0:
|
||||
resolution: {integrity: sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==}
|
||||
|
||||
@@ -841,6 +919,19 @@ packages:
|
||||
resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
|
||||
ink@5.2.1:
|
||||
resolution: {integrity: sha512-BqcUyWrG9zq5HIwW6JcfFHsIYebJkWWb4fczNah1goUO0vv5vneIlfwuS85twyJ5hYR/y18FlAYUxrO9ChIWVg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@types/react': '>=18.0.0'
|
||||
react: '>=18.0.0'
|
||||
react-devtools-core: ^4.19.1
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
react-devtools-core:
|
||||
optional: true
|
||||
|
||||
iota-array@1.0.0:
|
||||
resolution: {integrity: sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==}
|
||||
|
||||
@@ -867,6 +958,14 @@ packages:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-fullwidth-code-point@4.0.0:
|
||||
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
is-fullwidth-code-point@5.0.0:
|
||||
resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
is-glob@4.0.3:
|
||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -874,6 +973,11 @@ packages:
|
||||
is-hexadecimal@2.0.1:
|
||||
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
|
||||
|
||||
is-in-ci@1.0.0:
|
||||
resolution: {integrity: sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
is-number@7.0.0:
|
||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
@@ -939,6 +1043,10 @@ packages:
|
||||
longest-streak@3.1.0:
|
||||
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||
hasBin: true
|
||||
|
||||
loupe@3.1.3:
|
||||
resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==}
|
||||
|
||||
@@ -1210,6 +1318,10 @@ packages:
|
||||
parse5@6.0.1:
|
||||
resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
|
||||
|
||||
patch-console@2.0.0:
|
||||
resolution: {integrity: sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
path-absolute@1.0.1:
|
||||
resolution: {integrity: sha512-gds5iRhSeOcDtj8gfWkRHLtZKTPsFVuh7utbjYtvnclw4XM+ffRzJrwqMhOD1PVqef7nBLmgsu1vIujjvAJrAw==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -1264,6 +1376,16 @@ packages:
|
||||
resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
react-reconciler@0.29.2:
|
||||
resolution: {integrity: sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
peerDependencies:
|
||||
react: ^18.3.1
|
||||
|
||||
react@18.3.1:
|
||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
read-ini-file@4.0.0:
|
||||
resolution: {integrity: sha512-zz4qv/sKETv7nAkATqSJ9YMbKD8NXRPuA8d17VdYCuNYrVstB1S6UAMU6aytf5vRa9MESbZN7jLZdcmrOxz4gg==}
|
||||
engines: {node: '>=14.6'}
|
||||
@@ -1309,6 +1431,10 @@ packages:
|
||||
resolve-pkg-maps@1.0.0:
|
||||
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
|
||||
|
||||
restore-cursor@4.0.0:
|
||||
resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
reusify@1.1.0:
|
||||
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
@@ -1331,6 +1457,9 @@ packages:
|
||||
resolution: {integrity: sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
scheduler@0.23.2:
|
||||
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
||||
|
||||
semver@7.7.2:
|
||||
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -1362,6 +1491,14 @@ packages:
|
||||
resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
slice-ansi@5.0.0:
|
||||
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
slice-ansi@7.1.0:
|
||||
resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
sort-keys@4.2.0:
|
||||
resolution: {integrity: sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1376,6 +1513,10 @@ packages:
|
||||
split2@3.2.2:
|
||||
resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==}
|
||||
|
||||
stack-utils@2.0.6:
|
||||
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
stacktracey@2.1.8:
|
||||
resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==}
|
||||
|
||||
@@ -1391,6 +1532,10 @@ packages:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
string-width@7.2.0:
|
||||
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
string_decoder@1.3.0:
|
||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
||||
|
||||
@@ -1401,6 +1546,10 @@ packages:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-ansi@7.1.0:
|
||||
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-bom@4.0.0:
|
||||
resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1464,6 +1613,10 @@ packages:
|
||||
resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
type-fest@4.41.0:
|
||||
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
typescript@5.8.3:
|
||||
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
|
||||
engines: {node: '>=14.17'}
|
||||
@@ -1563,6 +1716,10 @@ packages:
|
||||
resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
widest-line@5.0.0:
|
||||
resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
wordwrap@1.0.0:
|
||||
resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
|
||||
|
||||
@@ -1570,6 +1727,10 @@ packages:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
wrap-ansi@9.0.0:
|
||||
resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
write-file-atomic@5.0.1:
|
||||
resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||
@@ -1578,6 +1739,18 @@ packages:
|
||||
resolution: {integrity: sha512-FdNA4RyH1L43TlvGG8qOMIfcEczwA5ij+zLXUy3Z83CjxhLvcV7/Q/8pk22wnCgYw7PJhtK+7lhO+qqyT4NdvQ==}
|
||||
engines: {node: '>=16.14'}
|
||||
|
||||
ws@8.18.2:
|
||||
resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: '>=5.0.2'
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -1595,11 +1768,19 @@ packages:
|
||||
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
yoga-layout@3.2.1:
|
||||
resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==}
|
||||
|
||||
zwitch@2.0.4:
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||
|
||||
snapshots:
|
||||
|
||||
'@alcalzone/ansi-tokenize@0.1.3':
|
||||
dependencies:
|
||||
ansi-styles: 6.2.1
|
||||
is-fullwidth-code-point: 4.0.0
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.27.1
|
||||
@@ -1965,6 +2146,16 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
'@types/ink@2.0.3(@types/react@18.3.21)(react@18.3.1)':
|
||||
dependencies:
|
||||
ink: 5.2.1(@types/react@18.3.21)(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
- bufferutil
|
||||
- react
|
||||
- react-devtools-core
|
||||
- utf-8-validate
|
||||
|
||||
'@types/marked-terminal@6.1.1':
|
||||
dependencies:
|
||||
'@types/cardinal': 2.1.1
|
||||
@@ -1984,6 +2175,13 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/prop-types@15.7.14': {}
|
||||
|
||||
'@types/react@18.3.21':
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.14
|
||||
csstype: 3.1.3
|
||||
|
||||
'@types/ssri@7.1.5':
|
||||
dependencies:
|
||||
'@types/node': 22.15.18
|
||||
@@ -2031,6 +2229,8 @@ snapshots:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
ansi-styles@6.2.1: {}
|
||||
|
||||
any-promise@1.3.0: {}
|
||||
|
||||
archy@1.0.0: {}
|
||||
@@ -2043,6 +2243,8 @@ snapshots:
|
||||
|
||||
assertion-error@2.0.1: {}
|
||||
|
||||
auto-bind@5.0.1: {}
|
||||
|
||||
bail@2.0.2: {}
|
||||
|
||||
better-path-resolve@1.0.0:
|
||||
@@ -2118,11 +2320,17 @@ snapshots:
|
||||
|
||||
cli-boxes@2.2.1: {}
|
||||
|
||||
cli-boxes@3.0.0: {}
|
||||
|
||||
cli-columns@4.0.0:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
cli-cursor@4.0.0:
|
||||
dependencies:
|
||||
restore-cursor: 4.0.0
|
||||
|
||||
cli-highlight@2.1.11:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
@@ -2138,6 +2346,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@colors/colors': 1.5.0
|
||||
|
||||
cli-truncate@4.0.0:
|
||||
dependencies:
|
||||
slice-ansi: 5.0.0
|
||||
string-width: 7.2.0
|
||||
|
||||
cliui@7.0.4:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
@@ -2146,6 +2359,10 @@ snapshots:
|
||||
|
||||
clone@1.0.4: {}
|
||||
|
||||
code-excerpt@4.0.0:
|
||||
dependencies:
|
||||
convert-to-spaces: 2.0.1
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
@@ -2161,6 +2378,8 @@ snapshots:
|
||||
ini: 1.3.8
|
||||
proto-list: 1.2.4
|
||||
|
||||
convert-to-spaces@2.0.1: {}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
@@ -2169,6 +2388,8 @@ snapshots:
|
||||
|
||||
crypto-random-string@2.0.0: {}
|
||||
|
||||
csstype@3.1.3: {}
|
||||
|
||||
cwise-compiler@1.1.3:
|
||||
dependencies:
|
||||
uniq: 1.0.1
|
||||
@@ -2199,6 +2420,8 @@ snapshots:
|
||||
|
||||
dotenv@16.5.0: {}
|
||||
|
||||
emoji-regex@10.4.0: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
emojilib@2.4.0: {}
|
||||
@@ -2209,6 +2432,8 @@ snapshots:
|
||||
dependencies:
|
||||
is-arrayish: 0.2.1
|
||||
|
||||
es-toolkit@1.38.0: {}
|
||||
|
||||
esbuild@0.25.4:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.4
|
||||
@@ -2239,6 +2464,8 @@ snapshots:
|
||||
|
||||
escalade@3.2.0: {}
|
||||
|
||||
escape-string-regexp@2.0.0: {}
|
||||
|
||||
escape-string-regexp@4.0.0: {}
|
||||
|
||||
escape-string-regexp@5.0.0: {}
|
||||
@@ -2284,6 +2511,8 @@ snapshots:
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
get-east-asian-width@1.3.0: {}
|
||||
|
||||
get-source@2.0.12:
|
||||
dependencies:
|
||||
data-uri-to-buffer: 2.0.2
|
||||
@@ -2354,6 +2583,8 @@ snapshots:
|
||||
|
||||
imurmurhash@0.1.4: {}
|
||||
|
||||
indent-string@5.0.0: {}
|
||||
|
||||
individual@3.0.0: {}
|
||||
|
||||
inherits@2.0.4: {}
|
||||
@@ -2362,6 +2593,39 @@ snapshots:
|
||||
|
||||
ini@3.0.1: {}
|
||||
|
||||
ink@5.2.1(@types/react@18.3.21)(react@18.3.1):
|
||||
dependencies:
|
||||
'@alcalzone/ansi-tokenize': 0.1.3
|
||||
ansi-escapes: 7.0.0
|
||||
ansi-styles: 6.2.1
|
||||
auto-bind: 5.0.1
|
||||
chalk: 5.4.1
|
||||
cli-boxes: 3.0.0
|
||||
cli-cursor: 4.0.0
|
||||
cli-truncate: 4.0.0
|
||||
code-excerpt: 4.0.0
|
||||
es-toolkit: 1.38.0
|
||||
indent-string: 5.0.0
|
||||
is-in-ci: 1.0.0
|
||||
patch-console: 2.0.0
|
||||
react: 18.3.1
|
||||
react-reconciler: 0.29.2(react@18.3.1)
|
||||
scheduler: 0.23.2
|
||||
signal-exit: 3.0.7
|
||||
slice-ansi: 7.1.0
|
||||
stack-utils: 2.0.6
|
||||
string-width: 7.2.0
|
||||
type-fest: 4.41.0
|
||||
widest-line: 5.0.0
|
||||
wrap-ansi: 9.0.0
|
||||
ws: 8.18.2
|
||||
yoga-layout: 3.2.1
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.21
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
iota-array@1.0.0: {}
|
||||
|
||||
is-alphabetical@2.0.1: {}
|
||||
@@ -2381,12 +2645,20 @@ snapshots:
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
|
||||
is-fullwidth-code-point@4.0.0: {}
|
||||
|
||||
is-fullwidth-code-point@5.0.0:
|
||||
dependencies:
|
||||
get-east-asian-width: 1.3.0
|
||||
|
||||
is-glob@4.0.3:
|
||||
dependencies:
|
||||
is-extglob: 2.1.1
|
||||
|
||||
is-hexadecimal@2.0.1: {}
|
||||
|
||||
is-in-ci@1.0.0: {}
|
||||
|
||||
is-number@7.0.0: {}
|
||||
|
||||
is-plain-obj@2.1.0: {}
|
||||
@@ -2432,6 +2704,10 @@ snapshots:
|
||||
|
||||
longest-streak@3.1.0: {}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
|
||||
loupe@3.1.3: {}
|
||||
|
||||
map-age-cleaner@0.1.3:
|
||||
@@ -2906,6 +3182,8 @@ snapshots:
|
||||
|
||||
parse5@6.0.1: {}
|
||||
|
||||
patch-console@2.0.0: {}
|
||||
|
||||
path-absolute@1.0.1: {}
|
||||
|
||||
path-key@3.1.1: {}
|
||||
@@ -2940,6 +3218,16 @@ snapshots:
|
||||
|
||||
quick-lru@4.0.1: {}
|
||||
|
||||
react-reconciler@0.29.2(react@18.3.1):
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
react: 18.3.1
|
||||
scheduler: 0.23.2
|
||||
|
||||
react@18.3.1:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
read-ini-file@4.0.0:
|
||||
dependencies:
|
||||
ini: 3.0.1
|
||||
@@ -3019,6 +3307,11 @@ snapshots:
|
||||
|
||||
resolve-pkg-maps@1.0.0: {}
|
||||
|
||||
restore-cursor@4.0.0:
|
||||
dependencies:
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
|
||||
reusify@1.1.0: {}
|
||||
|
||||
right-pad@1.1.1: {}
|
||||
@@ -3039,6 +3332,10 @@ snapshots:
|
||||
execa: 5.1.1
|
||||
path-name: 1.0.0
|
||||
|
||||
scheduler@0.23.2:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
semver@7.7.2: {}
|
||||
|
||||
setimmediate@1.0.5: {}
|
||||
@@ -3061,6 +3358,16 @@ snapshots:
|
||||
dependencies:
|
||||
unicode-emoji-modifier-base: 1.0.0
|
||||
|
||||
slice-ansi@5.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.1
|
||||
is-fullwidth-code-point: 4.0.0
|
||||
|
||||
slice-ansi@7.1.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.1
|
||||
is-fullwidth-code-point: 5.0.0
|
||||
|
||||
sort-keys@4.2.0:
|
||||
dependencies:
|
||||
is-plain-obj: 2.1.0
|
||||
@@ -3073,6 +3380,10 @@ snapshots:
|
||||
dependencies:
|
||||
readable-stream: 3.6.2
|
||||
|
||||
stack-utils@2.0.6:
|
||||
dependencies:
|
||||
escape-string-regexp: 2.0.0
|
||||
|
||||
stacktracey@2.1.8:
|
||||
dependencies:
|
||||
as-table: 1.0.55
|
||||
@@ -3091,6 +3402,12 @@ snapshots:
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
string-width@7.2.0:
|
||||
dependencies:
|
||||
emoji-regex: 10.4.0
|
||||
get-east-asian-width: 1.3.0
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
string_decoder@1.3.0:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
@@ -3104,6 +3421,10 @@ snapshots:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
strip-ansi@7.1.0:
|
||||
dependencies:
|
||||
ansi-regex: 6.1.0
|
||||
|
||||
strip-bom@4.0.0: {}
|
||||
|
||||
strip-comments-strings@1.2.0: {}
|
||||
@@ -3165,6 +3486,8 @@ snapshots:
|
||||
|
||||
type-fest@0.6.0: {}
|
||||
|
||||
type-fest@4.41.0: {}
|
||||
|
||||
typescript@5.8.3: {}
|
||||
|
||||
uglify-js@3.19.3:
|
||||
@@ -3289,6 +3612,10 @@ snapshots:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
|
||||
widest-line@5.0.0:
|
||||
dependencies:
|
||||
string-width: 7.2.0
|
||||
|
||||
wordwrap@1.0.0: {}
|
||||
|
||||
wrap-ansi@7.0.0:
|
||||
@@ -3297,6 +3624,12 @@ snapshots:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
wrap-ansi@9.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.1
|
||||
string-width: 7.2.0
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
write-file-atomic@5.0.1:
|
||||
dependencies:
|
||||
imurmurhash: 0.1.4
|
||||
@@ -3307,6 +3640,8 @@ snapshots:
|
||||
js-yaml: 4.1.0
|
||||
write-file-atomic: 5.0.1
|
||||
|
||||
ws@8.18.2: {}
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
||||
yaml@2.8.0: {}
|
||||
@@ -3323,4 +3658,6 @@ snapshots:
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 20.2.9
|
||||
|
||||
yoga-layout@3.2.1: {}
|
||||
|
||||
zwitch@2.0.4: {}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { program } from 'commander';
|
||||
import { resolve } from 'node:path';
|
||||
import { Marked } from 'marked';
|
||||
import { markedTerminal } from 'marked-terminal';
|
||||
import { execute } from '../execution/execution.js';
|
||||
import { Context } from '../context/context.js';
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
import { Watcher } from '../watcher/watcher.js';
|
||||
import { UI } from './ui/ui.js';
|
||||
import { wrapBody } from '../theme/theme.html.js';
|
||||
import { loadInputFiles } from '../utils/input.js';
|
||||
import { InvalidFormatError } from '../utils/errors.js';
|
||||
import { renderUI, State } from './ui/ui.js';
|
||||
import { Marked } from 'marked';
|
||||
|
||||
|
||||
|
||||
@@ -16,23 +17,27 @@ program
|
||||
.argument('<name>', 'http.md file name')
|
||||
.description('Run a http.md document')
|
||||
.option('-w, --watch', 'watch for changes')
|
||||
.option('-f, --file <file...>', 'input files (-f foo.js -f bar.json)')
|
||||
.option('-i, --input <input...>', 'input variables (-i foo=bar -i baz=qux)')
|
||||
.action(async (name, options) => {
|
||||
const marked = new Marked();
|
||||
marked.use(markedTerminal() as any);
|
||||
const {
|
||||
file: f = [],
|
||||
watch = false,
|
||||
input: i = [],
|
||||
} = options;
|
||||
|
||||
const ui = new UI();
|
||||
|
||||
const input = Object.fromEntries(
|
||||
const input = {
|
||||
...Object.fromEntries(
|
||||
i.map((item: string) => {
|
||||
const [key, value] = item.split('=');
|
||||
return [key, value];
|
||||
})
|
||||
);
|
||||
),
|
||||
...loadInputFiles(f),
|
||||
};
|
||||
const state = new State<any>({
|
||||
markdown: 'Loading',
|
||||
});
|
||||
const filePath = resolve(process.cwd(), name);
|
||||
|
||||
const build = async () => {
|
||||
@@ -43,8 +48,10 @@ program
|
||||
context,
|
||||
});
|
||||
|
||||
const markdown = await marked.parse(result.markdown);
|
||||
ui.content = markdown;
|
||||
state.setState({
|
||||
error: result.error ? result.error instanceof Error ? result.error.message : result.error : undefined,
|
||||
markdown: result.markdown,
|
||||
});
|
||||
|
||||
return {
|
||||
...result,
|
||||
@@ -53,10 +60,7 @@ program
|
||||
}
|
||||
|
||||
const result = await build();
|
||||
|
||||
ui.screen.key(['r'], () => {
|
||||
build();
|
||||
});
|
||||
renderUI(state);
|
||||
|
||||
if (watch) {
|
||||
const watcher = new Watcher();
|
||||
@@ -75,23 +79,28 @@ program
|
||||
.argument('<name>', 'http.md file name')
|
||||
.argument('<output>', 'output file name')
|
||||
.description('Run a http.md document')
|
||||
.option('-f, --format <format>', 'output format (html, markdown)')
|
||||
.option('-f, --file <file...>', 'input files (-f foo.js -f bar.json)')
|
||||
.option('--format <format>', 'output format (html, markdown)')
|
||||
.option('-w, --watch', 'watch for changes')
|
||||
.option('-i, --input <input...>', 'input variables (-i foo=bar -i baz=qux)')
|
||||
.action(async (name, output, options) => {
|
||||
const {
|
||||
watch = false,
|
||||
file: f = [],
|
||||
input: i = [],
|
||||
format = 'markdown',
|
||||
} = options;
|
||||
|
||||
|
||||
const input = Object.fromEntries(
|
||||
const input = {
|
||||
...Object.fromEntries(
|
||||
i.map((item: string) => {
|
||||
const [key, value] = item.split('=');
|
||||
return [key, value];
|
||||
})
|
||||
);
|
||||
),
|
||||
...loadInputFiles(f),
|
||||
}
|
||||
const filePath = resolve(process.cwd(), name);
|
||||
|
||||
const build = async () => {
|
||||
@@ -102,6 +111,10 @@ program
|
||||
context,
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
console.error(result.error);
|
||||
}
|
||||
|
||||
if (format === 'html') {
|
||||
const marked = new Marked();
|
||||
const html = await marked.parse(result.markdown);
|
||||
@@ -109,7 +122,7 @@ program
|
||||
} else if (format === 'markdown') {
|
||||
await writeFile(output, result.markdown);
|
||||
} else {
|
||||
throw new Error('Invalid format');
|
||||
throw new InvalidFormatError('Invalid format');
|
||||
}
|
||||
return {
|
||||
...result,
|
||||
@@ -119,6 +132,10 @@ program
|
||||
|
||||
const result = await build();
|
||||
|
||||
if (result.error && !watch) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (watch) {
|
||||
const watcher = new Watcher();
|
||||
watcher.watchFiles(Array.from(result.context.files));
|
||||
|
||||
55
src/cli/ui/components/scrollable-markdown.tsx
Normal file
55
src/cli/ui/components/scrollable-markdown.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { Box, Text, useInput } from 'ink';
|
||||
import { marked } from 'marked';
|
||||
import TerminalRenderer from 'marked-terminal';
|
||||
import wrapAnsi from 'wrap-ansi';
|
||||
import os from 'os';
|
||||
import { useTerminalHeight, useTerminalWidth } from '../hooks/terminal.js';
|
||||
|
||||
type ScrollableMarkdownProps = {
|
||||
markdownContent: string;
|
||||
};
|
||||
|
||||
const renderer = new TerminalRenderer({});
|
||||
marked.setOptions({ renderer: renderer as any });
|
||||
|
||||
const ScrollableMarkdown = ({ markdownContent }: ScrollableMarkdownProps) => {
|
||||
const [scrollPosition, setScrollPosition] = React.useState(0);
|
||||
const terminalHeight = useTerminalHeight()
|
||||
const terminalWidth = useTerminalWidth();
|
||||
const rendered = useMemo(() => {
|
||||
return marked(markdownContent) as string;
|
||||
}, [markdownContent]);
|
||||
const wrapped = useMemo(() => {
|
||||
return wrapAnsi(rendered, terminalWidth, {
|
||||
hard: true,
|
||||
trim: false,
|
||||
wordWrap: true,
|
||||
}).split(os.EOL);
|
||||
}, [rendered, terminalWidth]);
|
||||
|
||||
const buffer = useMemo(() => {
|
||||
return wrapped.slice(scrollPosition, scrollPosition + terminalHeight).join(os.EOL);
|
||||
}, [wrapped, scrollPosition, terminalHeight]);
|
||||
|
||||
useInput((input, key) => {
|
||||
if (key.downArrow) {
|
||||
setScrollPosition(prev => prev + 1);
|
||||
}
|
||||
if (key.upArrow) {
|
||||
setScrollPosition(prev => Math.max(0, prev - 1));
|
||||
}
|
||||
if (key.escape) {
|
||||
process.exit(0);
|
||||
}
|
||||
console.error('a', input, key);
|
||||
});
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" flexShrink={1} flexGrow={1} overflow="hidden">
|
||||
<Text>{buffer}</Text>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export { ScrollableMarkdown };
|
||||
39
src/cli/ui/hooks/terminal.ts
Normal file
39
src/cli/ui/hooks/terminal.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
const useTerminalWidth = () => {
|
||||
const [width, setWidth] = useState(process.stdout.columns || 80);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
setWidth(process.stdout.columns);
|
||||
};
|
||||
|
||||
process.stdout.on("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
process.stdout.off("resize", handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
const useTerminalHeight = () => {
|
||||
const [height, setHeight] = useState(process.stdout.rows || 24);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
setHeight(process.stdout.rows);
|
||||
};
|
||||
|
||||
process.stdout.on("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
process.stdout.off("resize", handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
export { useTerminalWidth, useTerminalHeight }
|
||||
80
src/cli/ui/state/state.tsx
Normal file
80
src/cli/ui/state/state.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import React, { createContext, useRef, useState, useSyncExternalStore } from "react";
|
||||
|
||||
type StateEvents = {
|
||||
update: () => void;
|
||||
}
|
||||
|
||||
class State<T = any> extends EventEmitter<StateEvents> {
|
||||
state: T;
|
||||
|
||||
constructor(initialState: T) {
|
||||
super();
|
||||
this.state = initialState;
|
||||
}
|
||||
|
||||
public get value() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public setState = (state: T) => {
|
||||
this.state = state;
|
||||
this.emit('update');
|
||||
}
|
||||
|
||||
public subscribe = (callback: () => void) => {
|
||||
this.on('update', callback);
|
||||
return () => {
|
||||
this.off('update', callback);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
type StateContextValue<T> = {
|
||||
state: State<T>;
|
||||
}
|
||||
|
||||
const StateContext = createContext<StateContextValue<any> | null>(null);
|
||||
|
||||
type StateProviderProps<T> = {
|
||||
state: State<T>;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const StateProvider = <T,>({ state, children }: StateProviderProps<T>) => {
|
||||
return (
|
||||
<StateContext.Provider value={{ state }}>
|
||||
{children}
|
||||
</StateContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const useStateContext = <T = any>() => {
|
||||
const context = React.useContext(StateContext);
|
||||
if (!context) {
|
||||
throw new Error("useStateContext must be used within a StateProvider");
|
||||
}
|
||||
return context as StateContextValue<T>;
|
||||
}
|
||||
|
||||
const useStateValue = <T = any>(
|
||||
selector: (state: T) => any = (state) => state,
|
||||
) => {
|
||||
const context = useStateContext<T>();
|
||||
const value = useRef<T>(selector(context.state.value));
|
||||
useSyncExternalStore(
|
||||
context.state.subscribe,
|
||||
() => {
|
||||
const next = selector(context.state.value);
|
||||
if (next !== value.current) {
|
||||
value.current = next;
|
||||
}
|
||||
return value.current;
|
||||
},
|
||||
() => value.current,
|
||||
);
|
||||
|
||||
return value.current;
|
||||
}
|
||||
|
||||
export { State, StateProvider, useStateContext, useStateValue };
|
||||
@@ -1,70 +0,0 @@
|
||||
import blessed from 'blessed';
|
||||
import chalk from 'chalk';
|
||||
|
||||
class UI {
|
||||
#box: blessed.Widgets.BoxElement;
|
||||
#screen: blessed.Widgets.Screen;
|
||||
|
||||
constructor() {
|
||||
const screen = blessed.screen({
|
||||
smartCSR: true,
|
||||
title: 'Markdown Viewer'
|
||||
});
|
||||
const scrollableBox = blessed.box({ // Or blessed.scrollablebox
|
||||
parent: screen,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
content: '',
|
||||
scrollable: true,
|
||||
alwaysScroll: true,
|
||||
keys: true,
|
||||
vi: true, // vi-like keybindings
|
||||
mouse: true,
|
||||
scrollbar: {
|
||||
ch: ' ',
|
||||
track: {
|
||||
bg: 'cyan'
|
||||
},
|
||||
style: {
|
||||
inverse: true
|
||||
}
|
||||
},
|
||||
style: {
|
||||
fg: 'white',
|
||||
bg: 'black'
|
||||
}
|
||||
});
|
||||
this.#box = scrollableBox;
|
||||
this.#screen = screen;
|
||||
|
||||
screen.key(['escape', 'q', 'C-c'], () => {
|
||||
return process.exit(0);
|
||||
});
|
||||
|
||||
scrollableBox.focus();
|
||||
screen.render();
|
||||
}
|
||||
|
||||
public get screen() {
|
||||
return this.#screen;
|
||||
}
|
||||
|
||||
public set content(content: string) {
|
||||
const originalLines = content.split('\n');
|
||||
const maxLineNoDigits = String(originalLines.length).length; // For padding
|
||||
|
||||
const linesWithNumbers = originalLines.map((line, index) => {
|
||||
const lineNumber = String(index + 1).padStart(maxLineNoDigits, ' ');
|
||||
const styledLineNumber = chalk.dim.yellow(`${lineNumber} | `);
|
||||
return `${styledLineNumber}${line}`;
|
||||
});
|
||||
|
||||
const contentWithLineNumbers = linesWithNumbers.join('\n');
|
||||
this.#box.setContent(contentWithLineNumbers);
|
||||
this.#screen.render();
|
||||
}
|
||||
}
|
||||
|
||||
export { UI };
|
||||
69
src/cli/ui/ui.tsx
Normal file
69
src/cli/ui/ui.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { Box, render, Text, useApp, useInput } from "ink"
|
||||
import { ScrollableMarkdown } from './components/scrollable-markdown.js';
|
||||
import { useStateValue, State, StateProvider } from './state/state.js';
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTerminalHeight } from "./hooks/terminal.js";
|
||||
|
||||
const MarkdownView = () => {
|
||||
const markdown = useStateValue((state) => state.markdown);
|
||||
const error = useStateValue((state) => state.error);
|
||||
|
||||
return (
|
||||
<Box flexGrow={1} flexDirection="column">
|
||||
<Box flexDirection="column" flexGrow={1} overflow="hidden">
|
||||
<ScrollableMarkdown markdownContent={markdown} />
|
||||
</Box>
|
||||
{error && (
|
||||
<Box flexDirection="column" padding={1}>
|
||||
<Text color="red">{error}</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const App = () => {
|
||||
const { exit } = useApp();
|
||||
const height = useTerminalHeight();
|
||||
useInput((_input, key) => {
|
||||
if (key.escape) {
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
useEffect(
|
||||
() => {
|
||||
const enterAltScreenCommand = "\x1b[?1049h";
|
||||
const leaveAltScreenCommand = "\x1b[?1049l";
|
||||
process.stdout.write(enterAltScreenCommand);
|
||||
const onExit = () => {
|
||||
exit();
|
||||
process.stdout.write(leaveAltScreenCommand);
|
||||
}
|
||||
process.on("exit", onExit);
|
||||
return () => {
|
||||
process.stdout.write(leaveAltScreenCommand);
|
||||
process.off("exit", onExit);
|
||||
}
|
||||
}, []
|
||||
);
|
||||
|
||||
return (
|
||||
<Box height={height} flexDirection="column">
|
||||
<MarkdownView />
|
||||
<Box>
|
||||
<Text>Press esc to exit</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const renderUI = (state: State) => {
|
||||
|
||||
render(
|
||||
<StateProvider state={state}>
|
||||
<App />
|
||||
</StateProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export { renderUI, State }
|
||||
@@ -51,6 +51,7 @@ type ExexutionExecuteOptions = {
|
||||
}
|
||||
|
||||
const execute = async (file: string, options: ExexutionExecuteOptions) => {
|
||||
let error: unknown | undefined;
|
||||
const { context } = options;
|
||||
context.files.add(file);
|
||||
const content = await readFile(file, 'utf-8');
|
||||
@@ -94,6 +95,7 @@ const execute = async (file: string, options: ExexutionExecuteOptions) => {
|
||||
});
|
||||
|
||||
for (const step of steps) {
|
||||
try {
|
||||
const { node, action } = step;
|
||||
const options: ExecutionStepOptions = {
|
||||
file,
|
||||
@@ -103,11 +105,16 @@ const execute = async (file: string, options: ExexutionExecuteOptions) => {
|
||||
root,
|
||||
};
|
||||
await action(options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const markdown = parser.stringify(root);
|
||||
|
||||
return {
|
||||
error,
|
||||
root,
|
||||
markdown,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { toString } from 'mdast-util-to-string';
|
||||
import { type ExecutionHandler } from '../execution.js';
|
||||
import { ParsingError, RequiredError } from '../../utils/errors.js';
|
||||
|
||||
const inputHandler: ExecutionHandler = ({
|
||||
addStep,
|
||||
@@ -15,7 +16,7 @@ const inputHandler: ExecutionHandler = ({
|
||||
const name = toString(node);
|
||||
|
||||
if (node.attributes?.required === '' && context.input[name] === undefined) {
|
||||
throw new Error(`Input "${name}" is required`);
|
||||
throw new RequiredError(name);
|
||||
}
|
||||
|
||||
if (node.attributes?.default !== undefined && context.input[name] === undefined) {
|
||||
@@ -27,7 +28,7 @@ const inputHandler: ExecutionHandler = ({
|
||||
if (format === 'number') {
|
||||
context.input[name] = Number(context.input[name]);
|
||||
if (context.input[name] !== undefined && isNaN(Number(context.input[name]))) {
|
||||
throw new Error(`Input "${name}" must be a number, but got "${context.input[name]}"`);
|
||||
throw new ParsingError(`Input "${name}" must be a number, but got "${context.input[name]}"`);
|
||||
}
|
||||
}
|
||||
if (format === 'boolean') {
|
||||
@@ -40,14 +41,14 @@ const inputHandler: ExecutionHandler = ({
|
||||
try {
|
||||
context.input[name] = JSON.parse(String(context.input[name]));
|
||||
} catch (error) {
|
||||
throw new Error(`Input "${name}" must be a valid JSON, but got "${context.input[name]}"`);
|
||||
throw new ParsingError(`Input "${name}" must be a valid JSON, but got "${context.input[name]}"`);
|
||||
}
|
||||
}
|
||||
|
||||
if (format === 'date') {
|
||||
const date = new Date(context.input[name] as string);
|
||||
if (isNaN(date.getTime())) {
|
||||
throw new Error(`Input "${name}" must be a valid date, but got "${context.input[name]}"`);
|
||||
throw new ParsingError(`Input "${name}" must be a valid date, but got "${context.input[name]}"`);
|
||||
}
|
||||
context.input[name] = date;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import Handlebars from "handlebars";
|
||||
import YAML from "yaml";
|
||||
import { should, expect, assert } from 'chai';
|
||||
import { ExecutionHandler } from "../execution.js";
|
||||
import { ScriptError } from "../../utils/errors.js";
|
||||
|
||||
const javascriptHandler: ExecutionHandler = ({
|
||||
node,
|
||||
@@ -60,7 +61,7 @@ const javascriptHandler: ExecutionHandler = ({
|
||||
meta: undefined,
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
throw new ScriptError(error instanceof Error ? error.message : String(error))
|
||||
}
|
||||
}
|
||||
if (options.hidden === true && parent && index !== undefined) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { dirname, resolve } from 'path';
|
||||
import { toString } from 'mdast-util-to-string'
|
||||
import { execute, type ExecutionHandler } from '../execution.js';
|
||||
import { FileNotFoundError } from '../../utils/errors.js';
|
||||
import { existsSync } from 'fs';
|
||||
|
||||
const fileHandler: ExecutionHandler = ({
|
||||
addStep,
|
||||
@@ -18,8 +20,8 @@ const fileHandler: ExecutionHandler = ({
|
||||
dirname(file),
|
||||
toString(node)
|
||||
);
|
||||
if (!filePath) {
|
||||
throw new Error('File path is required');
|
||||
if (!existsSync(filePath)) {
|
||||
throw new FileNotFoundError(filePath);
|
||||
}
|
||||
const { root: newRoot } = await execute(filePath, {
|
||||
context,
|
||||
|
||||
@@ -3,6 +3,8 @@ import { Context } from '../../context/context.js';
|
||||
import { execute, type ExecutionHandler } from '../execution.js';
|
||||
import { dirname, resolve } from 'path';
|
||||
import { toString } from 'mdast-util-to-string';
|
||||
import { FileNotFoundError } from '../../utils/errors.js';
|
||||
import { existsSync } from 'fs';
|
||||
|
||||
const rawMdHandler: ExecutionHandler = ({
|
||||
addStep,
|
||||
@@ -20,6 +22,9 @@ const rawMdHandler: ExecutionHandler = ({
|
||||
dirname(file),
|
||||
toString(node),
|
||||
);
|
||||
if (!existsSync(name)) {
|
||||
throw new FileNotFoundError(name);
|
||||
}
|
||||
const context = new Context({
|
||||
input: {},
|
||||
});
|
||||
|
||||
44
src/utils/errors.ts
Normal file
44
src/utils/errors.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
class BaseError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
}
|
||||
|
||||
class FileNotFoundError extends BaseError {
|
||||
constructor(filePath: string) {
|
||||
super(`File not found: ${filePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
class InvalidFileError extends BaseError {
|
||||
constructor(filePath: string) {
|
||||
super(`Invalid file: ${filePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
class InvalidFormatError extends BaseError {
|
||||
constructor(format: string) {
|
||||
super(`Invalid format: ${format}`);
|
||||
}
|
||||
}
|
||||
|
||||
class ScriptError extends BaseError {
|
||||
constructor(message: string) {
|
||||
super(`Script error: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
class ParsingError extends BaseError {
|
||||
constructor(message: string) {
|
||||
super(`Parsing error: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
class RequiredError extends BaseError {
|
||||
constructor(name: string) {
|
||||
super(`Required input "${name}" is missing`);
|
||||
}
|
||||
}
|
||||
|
||||
export { BaseError, FileNotFoundError, InvalidFileError, InvalidFormatError, ScriptError, ParsingError, RequiredError };
|
||||
60
src/utils/input.ts
Normal file
60
src/utils/input.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { extname } from "path";
|
||||
import { FileNotFoundError, InvalidFileError } from "./errors.js";
|
||||
import { existsSync } from "fs";
|
||||
import YAML from "yaml";
|
||||
import { readFile } from "fs/promises";
|
||||
|
||||
const loadJsonFile = async (filePath: string) => {
|
||||
const content = await readFile(filePath, "utf-8");
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
const loadYamlFile = async (filePath: string) => {
|
||||
const content = await readFile(filePath, "utf-8");
|
||||
return YAML.parse(content);
|
||||
}
|
||||
|
||||
const loadJsFile = async (filePath: string) => {
|
||||
const { default: content } = await import(filePath);
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
const loadInputFiles = async (filePaths: string[]) => {
|
||||
let inputs: Record<string, unknown> = {};
|
||||
for (const filePath of filePaths) {
|
||||
const type = extname(filePath);
|
||||
if (!existsSync(filePath)) {
|
||||
throw new FileNotFoundError(filePath);
|
||||
}
|
||||
try {
|
||||
switch (type) {
|
||||
case ".json":
|
||||
inputs = {
|
||||
...inputs,
|
||||
...(await loadJsonFile(filePath)),
|
||||
};
|
||||
break;
|
||||
case ".yaml":
|
||||
case ".yml":
|
||||
inputs = {
|
||||
...inputs,
|
||||
...(await loadYamlFile(filePath)),
|
||||
};
|
||||
break;
|
||||
case ".js":
|
||||
inputs = {
|
||||
...inputs,
|
||||
...(await loadJsFile(filePath)),
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new InvalidFileError(filePath);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new InvalidFileError(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { loadInputFiles };
|
||||
@@ -10,7 +10,11 @@
|
||||
"resolveJsonModule": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "dist"
|
||||
"outDir": "dist",
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/cli/ui/ui.tsx"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user