@zaly/tui 0.0.12 → 0.1.1
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/assets/schemas/shiki-language.schema.json +352 -0
- package/assets/schemas/shiki-theme.schema.json +71 -0
- package/assets/schemas/theme.schema.json +226 -1046
- package/assets/themes/andromeeda.json +97 -0
- package/assets/themes/ayu-dark.json +31 -25
- package/assets/themes/ayu-light.json +106 -0
- package/assets/themes/ayu-mirage.json +106 -0
- package/assets/themes/catppuccin-frappe.json +43 -40
- package/assets/themes/catppuccin-latte.json +43 -40
- package/assets/themes/catppuccin-macchiato.json +43 -40
- package/assets/themes/catppuccin-mocha.json +43 -40
- package/assets/themes/dark-plus.json +99 -0
- package/assets/themes/dracula.json +47 -47
- package/assets/themes/everforest-dark.json +28 -26
- package/assets/themes/everforest-light.json +28 -26
- package/assets/themes/github-dark-default.json +107 -0
- package/assets/themes/github-dark-dimmed.json +107 -0
- package/assets/themes/github-light-default.json +107 -0
- package/assets/themes/gruvbox-dark-hard.json +98 -0
- package/assets/themes/gruvbox-dark-medium.json +34 -29
- package/assets/themes/gruvbox-light-medium.json +98 -0
- package/assets/themes/horizon-bright.json +101 -0
- package/assets/themes/horizon.json +101 -0
- package/assets/themes/iterm2/LICENSE +25 -0
- package/assets/themes/iterm2/README.md +28 -0
- package/assets/themes/iterm2/catppuccin-latte.json +140 -0
- package/assets/themes/iterm2/catppuccin-mocha.json +140 -0
- package/assets/themes/iterm2/github-dark.json +140 -0
- package/assets/themes/iterm2/github.json +140 -0
- package/assets/themes/iterm2/gruvbox-dark.json +140 -0
- package/assets/themes/iterm2/gruvbox-light.json +140 -0
- package/assets/themes/iterm2/nord.json +140 -0
- package/assets/themes/iterm2/tokyonight-day.json +140 -0
- package/assets/themes/iterm2/tokyonight-moon.json +140 -0
- package/assets/themes/kanagawa-dragon.json +55 -49
- package/assets/themes/kanagawa-lotus.json +105 -0
- package/assets/themes/kanagawa-wave.json +56 -50
- package/assets/themes/light-plus.json +99 -0
- package/assets/themes/material-theme-lighter.json +102 -0
- package/assets/themes/material-theme-palenight.json +52 -45
- package/assets/themes/material-theme.json +102 -0
- package/assets/themes/min-dark.json +69 -14
- package/assets/themes/min-light.json +68 -17
- package/assets/themes/monokai.json +54 -47
- package/assets/themes/night-owl-light.json +105 -0
- package/assets/themes/night-owl.json +57 -49
- package/assets/themes/nord.json +53 -39
- package/assets/themes/one-dark-pro.json +46 -38
- package/assets/themes/one-light.json +52 -41
- package/assets/themes/poimandres.json +51 -49
- package/assets/themes/rose-pine-dawn.json +99 -0
- package/assets/themes/rose-pine-moon.json +99 -0
- package/assets/themes/rose-pine.json +50 -33
- package/assets/themes/solarized-dark.json +38 -31
- package/assets/themes/solarized-light.json +40 -33
- package/assets/themes/synthwave-84.json +47 -30
- package/assets/themes/tokyonight-day.json +3 -3
- package/assets/themes/tokyonight-moon.json +3 -2
- package/assets/themes/tokyonight-night.json +3 -2
- package/assets/themes/tokyonight-storm.json +3 -2
- package/assets/themes/vesper.json +50 -42
- package/assets/themes/vitesse-black.json +103 -0
- package/assets/themes/vitesse-dark.json +26 -30
- package/assets/themes/vitesse-light.json +26 -30
- package/dist/{actions-DEIKF2ts.mjs → actions-AY6avfEV.mjs} +2 -3
- package/dist/{actions-DEIKF2ts.mjs.map → actions-AY6avfEV.mjs.map} +1 -1
- package/dist/{actions-Dc4D4uSf.d.mts → actions-B0yyZ-Ww.d.mts} +4 -6
- package/dist/actions-B0yyZ-Ww.d.mts.map +1 -0
- package/dist/{ansi-DZlXaItJ.mjs → ansi-CxgRPLA2.mjs} +4 -33
- package/dist/ansi-CxgRPLA2.mjs.map +1 -0
- package/dist/ansi.d.mts +1 -3
- package/dist/ansi.d.mts.map +1 -1
- package/dist/ansi.mjs +1 -1
- package/dist/{autocomplete-StW1QJZJ.d.mts → autocomplete-wgceuhLr.d.mts} +5 -7
- package/dist/autocomplete-wgceuhLr.d.mts.map +1 -0
- package/dist/{box-BkP4MF82.mjs → box-DToDoXlU.mjs} +8 -10
- package/dist/{box-BkP4MF82.mjs.map → box-DToDoXlU.mjs.map} +1 -1
- package/dist/builder-BdYlK1Ew.mjs +195 -0
- package/dist/builder-BdYlK1Ew.mjs.map +1 -0
- package/dist/{callbacks-BwWTCqPJ.mjs → callbacks-DW8XKYKy.mjs} +9 -13
- package/dist/{callbacks-BwWTCqPJ.mjs.map → callbacks-DW8XKYKy.mjs.map} +1 -1
- package/dist/{client-C2GXKfJ1.mjs → client-BWm6dNZF.mjs} +9 -6
- package/dist/client-BWm6dNZF.mjs.map +1 -0
- package/dist/client-C69qWhMG.mjs +1 -0
- package/dist/{clipboard-CNPBTX7j.mjs → clipboard-UEoX9sup.mjs} +2 -3
- package/dist/{clipboard-CNPBTX7j.mjs.map → clipboard-UEoX9sup.mjs.map} +1 -1
- package/dist/clipboard.d.mts +0 -2
- package/dist/clipboard.d.mts.map +1 -1
- package/dist/clipboard.mjs +1 -1
- package/dist/color-Cr1VoL49.mjs +36 -0
- package/dist/color-Cr1VoL49.mjs.map +1 -0
- package/dist/ctx-CYEzzH-7.mjs +1 -0
- package/dist/{ctx-B7BmPUCD.mjs → ctx-DBeFcZt6.mjs} +4 -5
- package/dist/{ctx-B7BmPUCD.mjs.map → ctx-DBeFcZt6.mjs.map} +1 -1
- package/dist/{divider-TSx9NhI_.mjs → divider-qEj5prKE.mjs} +3 -4
- package/dist/{divider-TSx9NhI_.mjs.map → divider-qEj5prKE.mjs.map} +1 -1
- package/dist/{files-BvThQpOf.mjs → files-C3ZnFpvq.mjs} +3 -4
- package/dist/{files-BvThQpOf.mjs.map → files-C3ZnFpvq.mjs.map} +1 -1
- package/dist/{files-7DUYSeNc.d.mts → files-CdiDnwA_.d.mts} +3 -5
- package/dist/files-CdiDnwA_.d.mts.map +1 -0
- package/dist/{flex-Bguo-fUe.mjs → flex-CYp4etqn.mjs} +3 -4
- package/dist/{flex-Bguo-fUe.mjs.map → flex-CYp4etqn.mjs.map} +1 -1
- package/dist/{github-Cy2hfWJ7.mjs → github-CLveT9mq.mjs} +2 -3
- package/dist/{github-Cy2hfWJ7.mjs.map → github-CLveT9mq.mjs.map} +1 -1
- package/dist/{github-C1KfXk98.d.mts → github-DC0XemKa.d.mts} +3 -5
- package/dist/github-DC0XemKa.d.mts.map +1 -0
- package/dist/{image-VaT7AN-S.d.mts → image-DdRDv7q6.d.mts} +2 -4
- package/dist/image-DdRDv7q6.d.mts.map +1 -0
- package/dist/image-M--Bw4bs.mjs +177 -0
- package/dist/image-M--Bw4bs.mjs.map +1 -0
- package/dist/image.d.mts +1 -3
- package/dist/image.d.mts.map +1 -1
- package/dist/image.mjs +1 -1
- package/dist/index.d.mts +11 -14
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +12 -14
- package/dist/index.mjs.map +1 -1
- package/dist/{input-BGTTujDN.mjs → input-BkE4EpBw.mjs} +6 -7
- package/dist/{input-BGTTujDN.mjs.map → input-BkE4EpBw.mjs.map} +1 -1
- package/dist/{input-BAYux7qo.d.mts → input-C3kfYoEJ.d.mts} +3 -5
- package/dist/input-C3kfYoEJ.d.mts.map +1 -0
- package/dist/{inspect-jG_W4njH.mjs → inspect-Cli1beu8.mjs} +3 -4
- package/dist/{inspect-jG_W4njH.mjs.map → inspect-Cli1beu8.mjs.map} +1 -1
- package/dist/{inspect-CfNydMgO.d.mts → inspect-hSl3U2BD.d.mts} +2 -6
- package/dist/inspect-hSl3U2BD.d.mts.map +1 -0
- package/dist/kitty-0sJ8axU_.mjs +1 -0
- package/dist/{kitty-JbCJC0iQ.mjs → kitty-BH_eK6lz.mjs} +2 -3
- package/dist/{kitty-JbCJC0iQ.mjs.map → kitty-BH_eK6lz.mjs.map} +1 -1
- package/dist/{log-ByKlM4iI.mjs → log-96b1_J6G.mjs} +6 -7
- package/dist/{log-ByKlM4iI.mjs.map → log-96b1_J6G.mjs.map} +1 -1
- package/dist/{logger-DSQb0sLP.mjs → logger-DwfXp8LF.mjs} +5 -6
- package/dist/{logger-DSQb0sLP.mjs.map → logger-DwfXp8LF.mjs.map} +1 -1
- package/dist/{markdown-CwRmWuU6.mjs → markdown-CgRZBhIX.mjs} +12 -12
- package/dist/markdown-CgRZBhIX.mjs.map +1 -0
- package/dist/markdown.d.mts +2 -4
- package/dist/markdown.d.mts.map +1 -1
- package/dist/markdown.mjs +1 -1
- package/dist/math-Dk8hxbmz.mjs +1 -0
- package/dist/math-VPuwFCid.mjs +205 -0
- package/dist/math-VPuwFCid.mjs.map +1 -0
- package/dist/md.bun.d.mts +1 -3
- package/dist/md.bun.d.mts.map +1 -1
- package/dist/md.bun.mjs +2 -3
- package/dist/md.node.d.mts +1 -3
- package/dist/md.node.d.mts.map +1 -1
- package/dist/md.node.mjs +2 -3
- package/dist/{node-BZ7f6HzU.mjs → node-CXNobGaP.mjs} +3 -4
- package/dist/{node-BZ7f6HzU.mjs.map → node-CXNobGaP.mjs.map} +1 -1
- package/dist/oklch-Boh4YHEc.mjs +98 -0
- package/dist/oklch-Boh4YHEc.mjs.map +1 -0
- package/dist/{overlay-BnvOKtGT.mjs → overlay-CevDWgSF.mjs} +3 -4
- package/dist/{overlay-BnvOKtGT.mjs.map → overlay-CevDWgSF.mjs.map} +1 -1
- package/dist/{picker-Dh5IUrTk.mjs → picker-D9WrE3zF.mjs} +11 -16
- package/dist/{picker-Dh5IUrTk.mjs.map → picker-D9WrE3zF.mjs.map} +1 -1
- package/dist/{picker-DQs_IW77.d.mts → picker-DsB6--GN.d.mts} +6 -8
- package/dist/picker-DsB6--GN.d.mts.map +1 -0
- package/dist/{queries-B_lOwEiE.mjs → queries-BIniKnLL.mjs} +68 -7
- package/dist/queries-BIniKnLL.mjs.map +1 -0
- package/dist/{queries-BDX8mcl5.d.mts → queries-Dmd3IjSd.d.mts} +19 -52
- package/dist/queries-Dmd3IjSd.d.mts.map +1 -0
- package/dist/{reactive-f7NpAi69.mjs → reactive-DkP75TPk.mjs} +2 -3
- package/dist/{reactive-f7NpAi69.mjs.map → reactive-DkP75TPk.mjs.map} +1 -1
- package/dist/{registry-D-suU3g0.mjs → registry-CQU0VwpM.mjs} +205 -65
- package/dist/registry-CQU0VwpM.mjs.map +1 -0
- package/dist/{render-DEIUNLkh.mjs → render-Bp2N2i6J.mjs} +4 -5
- package/dist/{render-DEIUNLkh.mjs.map → render-Bp2N2i6J.mjs.map} +1 -1
- package/dist/{renderer-zDNlAovy.mjs → renderer-B9sAMA10.mjs} +123 -40
- package/dist/renderer-B9sAMA10.mjs.map +1 -0
- package/dist/{renderer-MQue4Da5.mjs → renderer-BYl2pbdx.mjs} +9 -9
- package/dist/renderer-BYl2pbdx.mjs.map +1 -0
- package/dist/renderer-Ctz0hv5o.mjs +1 -0
- package/dist/{search-FvGnswRl.d.mts → search-DsHzamic.d.mts} +1 -9
- package/dist/search-DsHzamic.d.mts.map +1 -0
- package/dist/{select-J2KtwxyK.d.mts → select-BZCFXdjp.d.mts} +3 -5
- package/dist/select-BZCFXdjp.d.mts.map +1 -0
- package/dist/{select-m7NE6Rwa.mjs → select-CUmAFKJh.mjs} +5 -6
- package/dist/{select-m7NE6Rwa.mjs.map → select-CUmAFKJh.mjs.map} +1 -1
- package/dist/services/logger.d.mts +1 -1
- package/dist/services/logger.mjs +1 -1
- package/dist/services/notifier.d.mts +1 -3
- package/dist/services/notifier.d.mts.map +1 -1
- package/dist/services/notifier.mjs +3 -4
- package/dist/services/picker.d.mts +5 -7
- package/dist/services/picker.d.mts.map +1 -1
- package/dist/services/picker.mjs +8 -9
- package/dist/services/prompt.d.mts +4 -6
- package/dist/services/prompt.d.mts.map +1 -1
- package/dist/services/prompt.mjs +7 -8
- package/dist/shiki/server.mjs +40 -19
- package/dist/shiki/server.mjs.map +1 -1
- package/dist/shiki-BAf9PdIc.mjs +19 -0
- package/dist/shiki-BAf9PdIc.mjs.map +1 -0
- package/dist/shiki-DUUAIE6f.mjs +632 -0
- package/dist/shiki-DUUAIE6f.mjs.map +1 -0
- package/dist/{show-DR2x1YFc.mjs → show-D5XNXgZf.mjs} +4 -5
- package/dist/{show-DR2x1YFc.mjs.map → show-D5XNXgZf.mjs.map} +1 -1
- package/dist/{size-D8JogYLy.mjs → size-BHRJuRk9.mjs} +2 -3
- package/dist/{size-D8JogYLy.mjs.map → size-BHRJuRk9.mjs.map} +1 -1
- package/dist/style-Cw_EuszU.mjs +108 -0
- package/dist/style-Cw_EuszU.mjs.map +1 -0
- package/dist/style.d.mts +4 -5
- package/dist/style.d.mts.map +1 -1
- package/dist/style.mjs +4 -4
- package/dist/{text-CkQ7Irmt.mjs → text-4arC3odI.mjs} +3 -4
- package/dist/{text-CkQ7Irmt.mjs.map → text-4arC3odI.mjs.map} +1 -1
- package/dist/{text-XvPfweeg.mjs → text-BArwVVkg.mjs} +5 -6
- package/dist/{text-XvPfweeg.mjs.map → text-BArwVVkg.mjs.map} +1 -1
- package/dist/{text-CCYs9RB2.d.mts → text-DdkJXgoC.d.mts} +3 -5
- package/dist/text-DdkJXgoC.d.mts.map +1 -0
- package/dist/text.d.mts +1 -1
- package/dist/text.mjs +1 -1
- package/dist/theme-B8hb1lPU.mjs +60 -0
- package/dist/theme-B8hb1lPU.mjs.map +1 -0
- package/dist/theme-BeSaXGNY.mjs +1792 -0
- package/dist/theme-BeSaXGNY.mjs.map +1 -0
- package/dist/themes.d.mts +211 -77
- package/dist/themes.d.mts.map +1 -1
- package/dist/themes.mjs +1 -1
- package/dist/{tree-DJl5W_B7.d.mts → tree-Berzv8Rz.d.mts} +3 -5
- package/dist/tree-Berzv8Rz.d.mts.map +1 -0
- package/dist/{tree-Bo1afYhe.mjs → tree-D6NvMQx8.mjs} +5 -6
- package/dist/{tree-Bo1afYhe.mjs.map → tree-D6NvMQx8.mjs.map} +1 -1
- package/dist/{types-D2EYlzmK.d.mts → types-ByMHEdCF.d.mts} +133 -131
- package/dist/types-ByMHEdCF.d.mts.map +1 -0
- package/dist/{types-D3jk1rtk.d.mts → types-CUVUJPz6.d.mts} +1 -3
- package/dist/types-CUVUJPz6.d.mts.map +1 -0
- package/dist/{utils-3M4D_AXZ.mjs → utils-DHXAegVW.mjs} +1 -2
- package/dist/{utils-3M4D_AXZ.mjs.map → utils-DHXAegVW.mjs.map} +1 -1
- package/dist/{widget-BkMwhY2p.mjs → widget-sFveyrZE.mjs} +3 -4
- package/dist/{widget-BkMwhY2p.mjs.map → widget-sFveyrZE.mjs.map} +1 -1
- package/dist/{widget-DPqBbB57.d.mts → widget-sPJaKVU2.d.mts} +2 -4
- package/dist/widget-sPJaKVU2.d.mts.map +1 -0
- package/dist/widgets/autocomplete.d.mts +1 -1
- package/dist/widgets/autocomplete.mjs +5 -6
- package/dist/widgets/box.d.mts +1 -1
- package/dist/widgets/box.mjs +1 -1
- package/dist/widgets/code.d.mts +4 -4
- package/dist/widgets/code.d.mts.map +1 -1
- package/dist/widgets/code.mjs +12 -12
- package/dist/widgets/code.mjs.map +1 -1
- package/dist/widgets/completions/actions.d.mts +1 -1
- package/dist/widgets/completions/actions.mjs +1 -1
- package/dist/widgets/completions/files.d.mts +1 -1
- package/dist/widgets/completions/files.mjs +1 -1
- package/dist/widgets/completions/github.d.mts +1 -1
- package/dist/widgets/completions/github.mjs +1 -1
- package/dist/widgets/completions/index.d.mts +3 -3
- package/dist/widgets/completions/index.mjs +3 -3
- package/dist/widgets/diff.d.mts +2 -4
- package/dist/widgets/diff.d.mts.map +1 -1
- package/dist/widgets/diff.mjs +38 -16
- package/dist/widgets/diff.mjs.map +1 -1
- package/dist/widgets/divider.d.mts +2 -4
- package/dist/widgets/divider.d.mts.map +1 -1
- package/dist/widgets/divider.mjs +1 -1
- package/dist/widgets/image.d.mts +1 -1
- package/dist/widgets/image.mjs +8 -9
- package/dist/widgets/image.mjs.map +1 -1
- package/dist/widgets/input.d.mts +1 -1
- package/dist/widgets/input.mjs +1 -1
- package/dist/widgets/log.d.mts +1 -1
- package/dist/widgets/log.mjs +1 -1
- package/dist/widgets/markdown.d.mts +5 -7
- package/dist/widgets/markdown.d.mts.map +1 -1
- package/dist/widgets/markdown.mjs +1 -1
- package/dist/widgets/overlay.d.mts +1 -1
- package/dist/widgets/overlay.mjs +1 -1
- package/dist/widgets/picker.d.mts +1 -1
- package/dist/widgets/picker.mjs +1 -1
- package/dist/widgets/progress.d.mts +2 -4
- package/dist/widgets/progress.d.mts.map +1 -1
- package/dist/widgets/progress.mjs +4 -5
- package/dist/widgets/select.d.mts +1 -1
- package/dist/widgets/select.mjs +1 -1
- package/dist/widgets/show.d.mts +1 -3
- package/dist/widgets/show.d.mts.map +1 -1
- package/dist/widgets/show.mjs +1 -1
- package/dist/widgets/spinner.d.mts +2 -4
- package/dist/widgets/spinner.d.mts.map +1 -1
- package/dist/widgets/spinner.mjs +3 -4
- package/dist/widgets/text.d.mts +1 -1
- package/dist/widgets/text.mjs +1 -1
- package/dist/widgets/tree.d.mts +1 -1
- package/dist/widgets/tree.mjs +1 -1
- package/dist/widgets/widget.d.mts +1 -1
- package/dist/widgets/widget.mjs +1 -1
- package/dist/{worker-T6SdPzUH.mjs → worker-CtEowucz.mjs} +2 -3
- package/dist/{worker-T6SdPzUH.mjs.map → worker-CtEowucz.mjs.map} +1 -1
- package/dist/worker-Mqi380Et.mjs +1 -0
- package/package.json +5 -7
- package/assets/themes/dracula-soft.json +0 -100
- package/assets/themes/github-dark.json +0 -104
- package/assets/themes/github-light.json +0 -104
- package/dist/actions-Dc4D4uSf.d.mts.map +0 -1
- package/dist/ansi-DZlXaItJ.mjs.map +0 -1
- package/dist/autocomplete-StW1QJZJ.d.mts.map +0 -1
- package/dist/builder-1z5ewEWK.mjs +0 -386
- package/dist/builder-1z5ewEWK.mjs.map +0 -1
- package/dist/client-C2GXKfJ1.mjs.map +0 -1
- package/dist/client-bzdHIDL2.mjs +0 -1
- package/dist/ctx-D_JgJ8Eo.mjs +0 -1
- package/dist/files-7DUYSeNc.d.mts.map +0 -1
- package/dist/github-C1KfXk98.d.mts.map +0 -1
- package/dist/image-Cm5T-uw-.mjs +0 -108
- package/dist/image-Cm5T-uw-.mjs.map +0 -1
- package/dist/image-VaT7AN-S.d.mts.map +0 -1
- package/dist/input-BAYux7qo.d.mts.map +0 -1
- package/dist/inspect-CfNydMgO.d.mts.map +0 -1
- package/dist/markdown-CwRmWuU6.mjs.map +0 -1
- package/dist/picker-DQs_IW77.d.mts.map +0 -1
- package/dist/queries-BDX8mcl5.d.mts.map +0 -1
- package/dist/queries-B_lOwEiE.mjs.map +0 -1
- package/dist/registry-D-suU3g0.mjs.map +0 -1
- package/dist/renderer-DhqbEVVR.mjs +0 -1
- package/dist/renderer-MQue4Da5.mjs.map +0 -1
- package/dist/renderer-zDNlAovy.mjs.map +0 -1
- package/dist/search-FvGnswRl.d.mts.map +0 -1
- package/dist/select-J2KtwxyK.d.mts.map +0 -1
- package/dist/shiki--ASSYv4_.mjs +0 -12
- package/dist/shiki--ASSYv4_.mjs.map +0 -1
- package/dist/shiki-D7l5--zz.mjs +0 -432
- package/dist/shiki-D7l5--zz.mjs.map +0 -1
- package/dist/text-CCYs9RB2.d.mts.map +0 -1
- package/dist/theme.config-B3Yx--C2.mjs +0 -855
- package/dist/theme.config-B3Yx--C2.mjs.map +0 -1
- package/dist/tree-DJl5W_B7.d.mts.map +0 -1
- package/dist/types-D2EYlzmK.d.mts.map +0 -1
- package/dist/types-D3jk1rtk.d.mts.map +0 -1
- package/dist/widget-DPqBbB57.d.mts.map +0 -1
- package/dist/worker-C01jK2Ip.mjs +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-
|
|
1
|
+
{"version":3,"file":"inspect-Cli1beu8.mjs","names":["inspect","nodeInspect"],"sources":["../src/style/inspect.ts"],"sourcesContent":["import type { StyleBuilder } from \"./builder.ts\"\n\nimport { hasAnsi } from \"@zaly/shared/ansi\"\nimport { hasColors } from \"@zaly/shared/env\"\nimport { formatWithOptions, inspect as nodeInspect } from \"node:util\"\nimport { styleBuilder } from \"./builder.ts\"\n\nexport interface InspectOpts {\n style?: StyleBuilder\n indent?: number\n undefined?: boolean\n null?: boolean\n /** When `true`, preserve Error stack traces. Default: `false` — Error\n * values are reduced to their `.message` so logs stay compact. */\n stacktrace?: boolean\n colors?: boolean\n}\n\n// Markdown-ish characters. Matches rekal's skip regex.\nconst MD_RE = /[`*_#[\\]\\->~|]/\nconst JSON_RE = /^\\s*[{[]/\n\n// `util.format` placeholder tokens (`%s`, `%d`, …).\nconst FORMAT_RE = /%[sdifjoOc%]/\n\n/** True when `s` looks like markdown we should render — contains MD\n * markers and isn't already ANSI-styled. Mirrors rekal's `Formatter.markdown`\n * skip test so we avoid double-rendering pre-styled strings. */\nexport function isMarkdown(s: string): boolean {\n return MD_RE.test(s) && !hasAnsi(s) && !JSON_RE.test(s)\n}\n\nconst isFormatString = (v: unknown): v is string =>\n typeof v === \"string\" && FORMAT_RE.test(v) && !hasAnsi(v)\n\n/**\n * Inspect a list of args the way `console.log` does, returning a single\n * string. Collapses `util.format` placeholders right-to-left, unwraps\n * `Error` values to their message (unless `stacktrace: true`), and falls\n * back to `util.formatWithOptions` for mixed values.\n */\nexport function inspectFormat(msg: unknown[], opts: InspectOpts = {}): string {\n const data = opts.stacktrace ? msg : msg.map((v) => (v instanceof Error ? v.message : v))\n opts = { colors: hasColors, ...opts }\n\n let ret: unknown[] = []\n // oxlint-disable-next-line oxc/no-accumulating-spread\n for (let i = data.length - 1; i >= 0; i--) {\n const item = data[i]\n if (isFormatString(item)) ret = [formatWithOptions(opts, item, ...ret)]\n else ret.unshift(item)\n }\n\n if (ret.length > 1 && isFormatString(ret[0])) return formatWithOptions(opts, ...ret)\n return ret.map((v) => (typeof v === \"string\" ? v : inspect(v, opts))).join(\" \")\n}\n\nfunction inspectNumber(value: number): string {\n return new Intl.NumberFormat(\"en-US\", {\n notation: \"standard\",\n useGrouping: true,\n })\n .format(value)\n .replace(/,/g, \"_\")\n}\n\nfunction inspectField(key: string, s: StyleBuilder): string {\n if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)) return s.syntaxField(key)\n return s.syntaxString(JSON.stringify(key))\n}\n\nexport function inspect(value: unknown, opts: InspectOpts = {}): string {\n opts = { colors: hasColors, null: true, undefined: true, ...opts }\n const indent = opts.indent ?? 2\n const s = opts.colors ? (opts.style ?? styleBuilder()) : styleBuilder(false)\n const sym = {\n \",\": s.syntaxDelimiter(\",\"),\n \":\": s.syntaxDelimiter(\":\"),\n \"[\": s.syntaxBracket(\"[\"),\n \"]\": s.syntaxBracket(\"]\"),\n \"{\": s.syntaxBracket(\"{\"),\n \"}\": s.syntaxBracket(\"}\"),\n }\n const seen = new Set()\n\n const $inspect = (v: unknown, depth: number): string => {\n if (seen.has(v)) return s.bold(\"[Circular]\")\n if (typeof v === \"object\" && v !== null) seen.add(v)\n if (v === null) return s.syntaxConstant(\"null\")\n switch (typeof v) {\n case \"boolean\": {\n return s.syntaxBoolean(String(v))\n }\n case \"bigint\": {\n return s.syntaxNumber(`${v}n`)\n }\n case \"number\": {\n return s.syntaxNumber(inspectNumber(v))\n }\n case \"string\": {\n return s.syntaxString(JSON.stringify(v))\n }\n case \"symbol\": {\n return s.syntaxSpecial(String(v))\n }\n case \"function\": {\n return s.syntaxFunction(`[Function${v.name ? `: ${v.name}` : \"\"}]`)\n }\n case \"undefined\": {\n return s.syntaxConstant(\"undefined\")\n }\n case \"object\": {\n if (Array.isArray(v)) {\n const items = v.map((item) => $inspect(item, depth + 1))\n return `${sym[\"[\"]} ${items.join(`${sym[\",\"]} `)} ${sym[\"]\"]}`\n }\n const isPlainObject = Object.getPrototypeOf(v) === Object.prototype\n if (!isPlainObject) break\n const entries = Object.entries(v)\n .filter(\n ([, val]) => !((val === undefined && !opts.undefined) || (val === null && !opts.null))\n )\n .map(([key, val]) => `${inspectField(key, s)}: ${$inspect(val, depth + 1)}`)\n if (indent) {\n const padding = \" \".repeat(indent * depth)\n return `${sym[\"{\"]}\\n${padding}${entries.join(`${sym[\",\"]}\\n${padding}`)}\\n${\" \".repeat(indent * (depth - 1))}${sym[\"}\"]}`\n }\n return `${sym[\"{\"]} ${entries.join(`${sym[\",\"]} `)} ${sym[\"}\"]}`\n }\n }\n return nodeInspect(v, { colors: true, compact: true })\n }\n return $inspect(value, 1)\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region src/style/builder.d.ts
|
|
1
|
+
import { a as BrightAnsiColorName, d as ThemeKey, f as Theme, i as AnyStyle, n as AnsiColorName, o as Color } from "./types-ByMHEdCF.mjs";
|
|
3
2
|
type AttrName = "bold" | "dim" | "italic" | "underline" | "inverse" | "strikethrough";
|
|
4
3
|
type ChainSlot<Ansi extends boolean = true> = Exclude<ThemeKey, "fg" | "bg" | AttrName> | (Ansi extends true ? AnsiColorName : never) | (Ansi extends true ? BrightAnsiColorName : never);
|
|
5
4
|
type StyleBuilder<Ansi extends boolean = false> = {
|
|
@@ -34,8 +33,6 @@ type StyleBuilder<Ansi extends boolean = false> = {
|
|
|
34
33
|
* Calling an empty builder is a no-op: `styleBuilder()("x")` returns `"x"` unchanged.
|
|
35
34
|
*/
|
|
36
35
|
declare function styleBuilder<Ansi extends boolean = false>(theme?: Theme | false): StyleBuilder<Ansi>;
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/style/inspect.d.ts
|
|
39
36
|
interface InspectOpts {
|
|
40
37
|
style?: StyleBuilder;
|
|
41
38
|
indent?: number;
|
|
@@ -58,6 +55,5 @@ declare function isMarkdown(s: string): boolean;
|
|
|
58
55
|
*/
|
|
59
56
|
declare function inspectFormat(msg: unknown[], opts?: InspectOpts): string;
|
|
60
57
|
declare function inspect(value: unknown, opts?: InspectOpts): string;
|
|
61
|
-
//#endregion
|
|
62
58
|
export { StyleBuilder as a, isMarkdown as i, inspect as n, styleBuilder as o, inspectFormat as r, InspectOpts as t };
|
|
63
|
-
//# sourceMappingURL=inspect-
|
|
59
|
+
//# sourceMappingURL=inspect-hSl3U2BD.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect-hSl3U2BD.d.mts","names":[],"sources":["../src/style/builder.ts","../src/style/inspect.ts"],"mappings":";KAcK;KAKA,UAAU,+BACX,QAAQ,wBAAwB,aAC/B,oBAAoB,0BACpB,oBAAoB;KAEb,aAAa;EACvB,OAAO;GACN;EACD,KAAK,OAAO,MAAM,UAAU,aAAa;EACzC,KAAK,OAAO,MAAM,UAAU,aAAa;EACzC,MAAM,OAAO,WAAW,aAAa,aAAa;EAClD,UAAU,cAAc,aAAa;EACrC,SAAS,cAAc,aAAa;gBAIlC,KACI,WACA,UAAU,aACL,WAAW,UAAU,gBACrB,WAAW,UAAU,WAC7B,aAAa;;;;;;;;;;;;;;;;;;;;;;;iBAyBF,aAAa,8BAC3B,QAAO,gBACN,aAAa;UC5DC;EACf,QAAQ;EACR;EACA;EACA;;;EAGA;EACA;;;;;iBAac,WAAW;;;;;;;iBAaX,cAAc,gBAAgB,OAAM;iBA8BpC,QAAQ,gBAAgB,OAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { s as loadKittyGraphics } from "./kitty-BH_eK6lz.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isSSH } from "@zaly/shared/env";
|
|
2
|
-
|
|
2
|
+
// src/image/kitty.ts
|
|
3
3
|
const DIACRITICS = [
|
|
4
4
|
773,
|
|
5
5
|
781,
|
|
@@ -667,7 +667,6 @@ function loadKittyGraphics(tq) {
|
|
|
667
667
|
prom ??= (async () => kitty = new Kitty(await detect(tq)))();
|
|
668
668
|
return prom;
|
|
669
669
|
}
|
|
670
|
-
//#endregion
|
|
671
670
|
export { allocatePlacementId as a, resetKittyGraphics as c, allocateImageId as i, resetTransmitCache as l, Kitty as n, bumpPlacements as o, PLACEHOLDER as r, loadKittyGraphics as s, DIACRITICS as t };
|
|
672
671
|
|
|
673
|
-
//# sourceMappingURL=kitty-
|
|
672
|
+
//# sourceMappingURL=kitty-BH_eK6lz.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kitty-JbCJC0iQ.mjs","names":[],"sources":["../src/image/kitty.ts"],"sourcesContent":["/**\n * Kitty Graphics Protocol — local-file transmission + native placements.\n *\n * Flow:\n * 1. Transmit once per src via `transmitFile(id, path)` (t=f). The\n * terminal loads the image bytes from the file path; nothing of the\n * image is transmitted over the wire beyond the path itself.\n * 2. On every render, emit `placement(imgId, placeId, { cols, rows })`\n * at the target cursor position. Re-sending a placement with the\n * same (image id, placement id) moves/resizes the existing placement\n * without flicker — ideal for re-renders.\n *\n * Reference: https://sw.kovidgoyal.net/kitty/graphics-protocol/\n */\n\nimport type { MaybePromise } from \"@zaly/shared\"\nimport type { ImageInfo } from \"@zaly/shared/image\"\nimport type { TerminalQueries, TerminalQuery } from \"../input/queries.ts\"\n\nimport { isSSH } from \"@zaly/shared/env\"\n\nexport type KittyPlacement = {\n imageId: number\n /** Placement ID. Omitted when this is an inline placement (U=1) */\n placementId?: number\n /** inline: placement using unicode placeholder (U=1) */\n inline?: boolean\n /** The KGP escape sequence to place the image */\n seq: string\n /** Rows to render (excluding the placement escape sequence) */\n data: string[]\n}\n\nexport type ImageSupport = {\n terminal?: { name: string; version?: string }\n remote?: boolean\n wrap?: (seq: string) => string\n tmux?: boolean\n} & (\n | {\n ok: false\n error: string\n terminal?: { name: string; version?: string }\n }\n | {\n ok: true\n error?: never\n terminal: { name: string; version?: string }\n inline?: boolean\n }\n)\n\nexport type KittyResponse =\n | {\n attrs: Record<string, string | number>\n ok: true\n }\n | {\n attrs: Record<string, string | number>\n ok: false\n error: { code: string; message: string }\n }\n\nexport type PlacementDims = {\n /** Display width in terminal cells. */\n cols: number\n /** Display height in terminal cells. */\n rows: number\n}\n\n// Per-src transmit cache. The first caller gets the full transmit sequence;\n// subsequent callers get undefined since the terminal already has the bytes.\ntype CacheEntry = {\n imageId: number\n seq: string\n sent: boolean\n}\n\n// oxfmt-ignore\n// oxlint-disable-next-line unicorn/numeric-separators-style\nexport const DIACRITICS = [ 0x0305, 0x030d, 0x030e, 0x0310, 0x0312, 0x033d, 0x033e, 0x033f, 0x0346, 0x034a, 0x034b, 0x034c, 0x0350, 0x0351, 0x0352, 0x0357, 0x035b, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0592, 0x0593, 0x0594, 0x0595, 0x0597, 0x0598, 0x0599, 0x059c, 0x059d, 0x059e, 0x059f, 0x05a0, 0x05a1, 0x05a8, 0x05a9, 0x05ab, 0x05ac, 0x05af, 0x05c4, 0x0610, 0x0611, 0x0612, 0x0613, 0x0614, 0x0615, 0x0616, 0x0617, 0x0657, 0x0658, 0x0659, 0x065a, 0x065b, 0x065d, 0x065e, 0x06d6, 0x06d7, 0x06d8, 0x06d9, 0x06da, 0x06db, 0x06dc, 0x06df, 0x06e0, 0x06e1, 0x06e2, 0x06e4, 0x06e7, 0x06e8, 0x06eb, 0x06ec, 0x0730, 0x0732, 0x0733, 0x0735, 0x0736, 0x073a, 0x073d, 0x073f, 0x0740, 0x0741, 0x0743, 0x0745, 0x0747, 0x0749, 0x074a, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3, 0x0816, 0x0817, 0x0818, 0x0819, 0x081b, 0x081c, 0x081d, 0x081e, 0x081f, 0x0820, 0x0821, 0x0822, 0x0823, 0x0825, 0x0826, 0x0827, 0x0829, 0x082a, 0x082b, 0x082c, 0x082d, 0x0951, 0x0953, 0x0954, 0x0f82, 0x0f83, 0x0f86, 0x0f87, 0x135d, 0x135e, 0x135f, 0x17dd, 0x193a, 0x1a17, 0x1a75, 0x1a76, 0x1a77, 0x1a78, 0x1a79, 0x1a7a, 0x1a7b, 0x1a7c, 0x1b6b, 0x1b6d, 0x1b6e, 0x1b6f, 0x1b70, 0x1b71, 0x1b72, 0x1b73, 0x1cd0, 0x1cd1, 0x1cd2, 0x1cda, 0x1cdb, 0x1ce0, 0x1dc0, 0x1dc1, 0x1dc3, 0x1dc4, 0x1dc5, 0x1dc6, 0x1dc7, 0x1dc8, 0x1dc9, 0x1dcb, 0x1dcc, 0x1dd1, 0x1dd2, 0x1dd3, 0x1dd4, 0x1dd5, 0x1dd6, 0x1dd7, 0x1dd8, 0x1dd9, 0x1dda, 0x1ddb, 0x1ddc, 0x1ddd, 0x1dde, 0x1ddf, 0x1de0, 0x1de1, 0x1de2, 0x1de3, 0x1de4, 0x1de5, 0x1de6, 0x1dfe, 0x20d0, 0x20d1, 0x20d4, 0x20d5, 0x20d6, 0x20d7, 0x20db, 0x20dc, 0x20e1, 0x20e7, 0x20e9, 0x20f0, 0x2cef, 0x2cf0, 0x2cf1, 0x2de0, 0x2de1, 0x2de2, 0x2de3, 0x2de4, 0x2de5, 0x2de6, 0x2de7, 0x2de8, 0x2de9, 0x2dea, 0x2deb, 0x2dec, 0x2ded, 0x2dee, 0x2def, 0x2df0, 0x2df1, 0x2df2, 0x2df3, 0x2df4, 0x2df5, 0x2df6, 0x2df7, 0x2df8, 0x2df9, 0x2dfa, 0x2dfb, 0x2dfc, 0x2dfd, 0x2dfe, 0x2dff, 0xa66f, 0xa67c, 0xa67d, 0xa6f0, 0xa6f1, 0xa8e0, 0xa8e1, 0xa8e2, 0xa8e3, 0xa8e4, 0xa8e5, 0xa8e6, 0xa8e7, 0xa8e8, 0xa8e9, 0xa8ea, 0xa8eb, 0xa8ec, 0xa8ed, 0xa8ee, 0xa8ef, 0xa8f0, 0xa8f1, 0xaab0, 0xaab2, 0xaab3, 0xaab7, 0xaab8, 0xaabe, 0xaabf, 0xaac1, 0xfe20, 0xfe21, 0xfe22, 0xfe23, 0xfe24, 0xfe25, 0xfe26, 0x10a0f, 0x10a38, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243, 0x1d244 ].map((c) => String.fromCodePoint(c))\nexport const PLACEHOLDER = String.fromCodePoint(0x10_ee_ee)\nconst CHUNK_SIZE = 4096\nconst transmitCache = new Map<string, CacheEntry>()\n\nconst known: Record<string, { inline?: boolean } | false | undefined> = {\n ghostty: { inline: true },\n kitty: { inline: true },\n rio: { inline: false },\n wezterm: { inline: false },\n}\n\nlet prom: Promise<Kitty> | undefined = undefined\nlet kitty: Kitty | undefined = undefined\nconst wrapTmux = (seq: string): string => `\\x1bPtmux;${seq.replaceAll(\"\\x1b\", \"\\x1b\\x1b\")}\\x1b\\\\`\n\n/** Allocate a fresh 24-bit image id (1..0xFFFFFFFE). */\nexport function allocateImageId(): number {\n return Math.floor(Math.random() * 0xff_ff_fd) + 1\n}\n\n/** Allocate a fresh 24-bit placement id. */\nexport function allocatePlacementId(): number {\n return Math.floor(Math.random() * 0xff_ff_fd) + 1\n}\n\nexport class Kitty {\n #support: ImageSupport\n #wrap: (seq: string) => string = (s) => s\n\n constructor(support: ImageSupport) {\n this.#support = support\n this.#wrap = support.wrap ?? ((s) => s)\n }\n\n get supported(): boolean {\n return this.#support.ok\n }\n\n get inline(): boolean {\n return this.#support.ok && this.#support.inline === true\n }\n\n /** Create a KGP request escape sequence */\n request(\n attrs: Record<string, string | number>,\n data?: string | Uint8Array,\n opts: { base64?: boolean } = {}\n ): string {\n const params = Object.entries(attrs)\n .map(([k, v]) => `${k}=${v}`)\n .join(\",\")\n let encoded: string | undefined\n if (opts.base64 === false && typeof data === \"string\") encoded = data\n else if (data)\n encoded = toBase64(typeof data === \"string\" ? new TextEncoder().encode(data) : data)\n const payload = encoded ? `;${encoded}` : \"\"\n return this.#wrap(`\\x1b_G${params}${payload}\\x1b\\\\`)\n }\n\n /** Create a TerminalQuery that requests a KGP operation and parses the response. */\n query(\n attrs: Record<string, string | number>,\n data?: string | Uint8Array,\n opts: { base64?: boolean } = {}\n ): TerminalQuery {\n return {\n match: (ev) => {\n if (ev.kind !== \"apc\") return\n const kr = this.parse(ev.sequence)\n if (!kr) return\n return { ...ev, ...kr }\n },\n request: this.request(attrs, data, opts),\n }\n }\n\n /** Probe the terminal for KGP support. Should return an error response. */\n probe(): string {\n return this.request({ i: 4_294_967_290, s: 10, t: \"s\", v: 2 }, \"<error>\")\n }\n\n /** Parse a KGP response escape sequence into a structured object. */\n parse(res: string): KittyResponse | undefined {\n if (!res.startsWith(\"\\x1b_G\") || !res.endsWith(\"\\x1b\\\\\")) return undefined\n const body = res.slice(3, -2)\n const m = body.match(/^([^;]+);(.*)?$/)\n if (!m) return undefined\n const [_, params, data] = m as [string, string, string | undefined]\n const attrs: Record<string, string | number> = {}\n for (const pair of params.split(\",\")) {\n const [k, v] = pair.split(\"=\", 2)\n if (k && v) attrs[k] = /^\\d+$/.test(v) ? parseInt(v, 10) : v\n }\n if (data === \"OK\") return { attrs, ok: true }\n const error = data?.match(/^([A-Z]+):\\s*(.*)$/)\n return {\n attrs,\n error: error\n ? { code: error[1], message: error[2] }\n : { code: \"UNKNOWN\", message: data ?? \"\" },\n ok: false,\n }\n }\n\n placement(imageId: number, dims: PlacementDims): KittyPlacement | undefined {\n if (!this.#support.ok) return\n if (this.#support.inline)\n return {\n data: unicodePlaceholder(imageId, dims),\n imageId,\n inline: true,\n seq: this.request({ U: 1, a: \"p\", c: dims.cols, i: imageId, q: 2, r: dims.rows }),\n }\n const blank = \" \".repeat(dims.cols)\n const placementId = allocatePlacementId()\n // NOTE: never sort this, since we need a deterministic order for bumping placements\n // oxlint-disable-next-line sort-keys\n const seq = this.request({\n a: \"p\",\n i: imageId,\n p: placementId,\n C: 1,\n c: dims.cols,\n q: 2,\n r: dims.rows,\n })\n return {\n data: Array.from<string>({ length: dims.rows }).fill(blank),\n imageId,\n placementId,\n seq,\n }\n }\n\n /** Delete an image and all its placements, or ALL images if `imageId` is omitted. */\n deleteImage(imageId?: number): string {\n return imageId === undefined\n ? this.request({ a: \"d\", d: \"A\", q: 2 })\n : this.request({ a: \"d\", d: \"I\", i: imageId, q: 2 })\n }\n\n /** Delete a placement (keeps image data so it can be re-placed cheaply). */\n deletePlacement(imageId: number, placementId: number): string {\n return this.request({ a: \"d\", d: \"i\", i: imageId, p: placementId, q: 2 })\n }\n\n /**\n * Ensure an image has been transmitted to the terminal at least once.\n * On the first call per `src`, returns the full `a=t,t=f` escape to be\n * prepended to the caller's first row — the APC payload has zero display\n * width, so layout sees through it. Subsequent calls return `transmit:\n * \"\"` since the terminal already has the bytes under `imageId`.\n *\n * The caller is expected to combine this with `placement(...)` on every\n * render to actually paint the image at the right cell rectangle.\n */\n async transmitOnce(info: ImageInfo): Promise<{ imageId: number; transmit?: string } | undefined> {\n if (!this.#support.ok) return undefined\n const { fileHash } = await import(\"@zaly/shared/detect\")\n const key = fileHash(info)\n let entry = transmitCache.get(key)\n if (entry === undefined) {\n const { imageConvert } = await import(\"@zaly/shared/image\")\n const png = await imageConvert(info, \"png\")\n if (!png) return undefined\n const id = allocateImageId()\n // Under SSH the terminal can't read files on the local side, so\n // fall back to bytes-in-band (`t=d`). Locally we pass a path and\n // the transmit payload stays under 1KB.\n entry = {\n imageId: id,\n sent: false,\n seq:\n this.#support.remote || !png.path\n ? this.transmitBytes(id, png.data)\n : this.transmitFile(id, png.path),\n }\n transmitCache.set(key, entry)\n }\n if (entry.sent) {\n entry.seq = \"\" // Clear the transmit memory\n return { imageId: entry.imageId }\n }\n entry.sent = true\n return { imageId: entry.imageId, transmit: entry.seq }\n }\n\n /**\n * Transmit an image to the terminal by file path (`t=f`). Near-zero cost\n * on the wire — the terminal opens and reads the file itself. `path`\n * must be absolute and must point to a regular file; symlinks are\n * followed by the terminal.\n */\n transmitFile(id: number, path: string): string {\n return this.request({ a: \"t\", f: 100, i: id, q: 2, t: \"f\" }, path)\n }\n\n /**\n * Remote/bytes transmission fallback (`t=d`) for when the terminal can't\n * read local files — typical of SSH sessions. Base64-encodes and chunks\n * the PNG payload at 4KB boundaries per the protocol.\n */\n transmitBytes(id: number, png: Uint8Array): string {\n const base64 = toBase64(png)\n const params = { a: \"t\", f: 100, i: id, q: 2, t: \"d\" }\n if (base64.length <= CHUNK_SIZE) return this.request(params, base64, { base64: false })\n\n const out: string[] = []\n let offset = 0\n let first = true\n while (offset < base64.length) {\n const chunk = base64.slice(offset, offset + CHUNK_SIZE)\n offset += CHUNK_SIZE\n const more = offset < base64.length ? 1 : 0\n out.push(this.request(first ? { ...params, m: more } : { m: more }, chunk, { base64: false }))\n first = false\n }\n return out.join(\"\")\n }\n}\n\n/** Drop the per-src transmit cache. Mostly for tests. */\nexport function resetTransmitCache(): void {\n transmitCache.clear()\n}\n\nexport function resetKittyGraphics(): void {\n resetTransmitCache()\n prom = undefined\n kitty = undefined\n}\n\nfunction intToRgb(color24bit: number): { r: number; g: number; b: number } {\n const r = (color24bit >> 16) & 0xff\n const g = (color24bit >> 8) & 0xff\n const b = color24bit & 0xff\n return { b, g, r }\n}\n\nfunction unicodePlaceholder(id: number, dims: PlacementDims): string[] {\n const rgb = intToRgb(id)\n const rows = Math.min(DIACRITICS.length, dims.rows)\n const cols = Math.min(DIACRITICS.length, dims.cols)\n const fg = `\\x1b[38;2;${rgb.r};${rgb.g};${rgb.b}m`\n const img: string[] = []\n for (let r = 0; r < rows; r++) {\n const line: string[] = []\n for (let c = 0; c < cols; c++) {\n line.push(fg)\n line.push(PLACEHOLDER)\n line.push(DIACRITICS[r])\n line.push(DIACRITICS[c])\n }\n line.push(\"\\x1b[39m\")\n img.push(line.join(\"\"))\n }\n return img\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") return Buffer.from(bytes).toString(\"base64\")\n let binary = \"\"\n for (const b of bytes) binary += String.fromCharCode(b)\n return btoa(binary)\n}\n\nexport function bumpPlacements(\n rows: string[]\n): undefined | { delete: () => string; rows: string[] } {\n // We only need to bump placements when:\n // - kitty graphics are loaded (when not loaded, there can't be any placements yet)\n // - we're not using inline placements (when using inline, the placement is part of the row and doesn't need to be bumped)\n if (!kitty || kitty.inline) return\n\n const placements: { i: number; p: number }[] = []\n const ret = rows.map((row) =>\n row.replace(/\\x1b_Ga=p,i=(\\d+),p=(\\d+)/g, (_, i) => {\n const imageId = parseInt(i, 10)\n const placementId = allocatePlacementId()\n placements.push({ i: imageId, p: placementId })\n return `\\x1b_Ga=p,i=${imageId},p=${placementId}`\n })\n )\n if (!placements.length) return\n const k = kitty\n return {\n delete: () => placements.map((p) => k.deletePlacement(p.i, p.p)).join(\"\"),\n rows: ret,\n }\n}\n\nasync function detect(tq: TerminalQueries): Promise<ImageSupport> {\n const support: Omit<ImageSupport, \"ok\" | \"error\"> = {\n remote: isSSH,\n tmux: !!process.env.TMUX,\n // Escape sequences must be wrapped in a special way for tmux to pass them\n // through to the underlying terminal.\n wrap: process.env.TMUX ? wrapTmux : undefined,\n }\n if (support.tmux) {\n try {\n const { spawnCmd } = await import(\"@zaly/shared/process\")\n // TMUX needs to have allow-passthrough set to all images to work properly\n await spawnCmd(\"tmux\", \"set\", \"-p\", \"allow-passthrough\", \"on\")\n support.wrap = wrapTmux\n } catch (error) {\n return {\n ...support,\n error: `Failed to set allow-passthrough in tmux: ${error instanceof Error ? error.message : String(error)}`,\n ok: false,\n }\n }\n }\n\n const v = await tq.xtVersion({ wrap: support.wrap })\n if (!v) return { error: \"Failed to query terminal name & version\", ok: false, ...support }\n\n support.terminal = { name: v.name, version: v.version }\n\n const kgp = known[v.name.toLowerCase()]\n if (kgp === false)\n return { error: `Terminal ${v.name} does not support KGP`, ok: false, ...support }\n\n if (kgp === undefined) {\n // Probe KGP support\n // Create a tmp Kitty instance to probe the terminal for KGP support.\n const k = new Kitty({ ...support, error: \"\", ok: false })\n const res = await tq.query({\n match: (ev) => {\n if (ev.kind === \"apc\" && ev.payload.startsWith(\"G\")) return { kgp: true, ...ev }\n if (ev.kind === \"csi\" && ev.final === \"c\" && ev.params.startsWith(\"?\"))\n return { kgp: false, ...ev }\n return\n },\n request: `${k.probe()}\\x1b[c`,\n timeout: 200,\n })\n if (res?.kgp !== true)\n return { error: \"Failed to query kitty graphics protocol\", ok: false, ...support }\n }\n\n return {\n ...support,\n inline: kgp?.inline,\n ok: true,\n terminal: { name: v.name, version: v.version },\n }\n}\n\nexport function loadKittyGraphics(tq: TerminalQueries): MaybePromise<Kitty> {\n if (kitty) return kitty\n prom ??= (async () => (kitty = new Kitty(await detect(tq))))()\n return prom\n}\n"],"mappings":";;AAgFA,MAAa,aAAa;CAAE;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CA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"}
|
|
1
|
+
{"version":3,"file":"kitty-BH_eK6lz.mjs","names":[],"sources":["../src/image/kitty.ts"],"sourcesContent":["/**\n * Kitty Graphics Protocol — local-file transmission + native placements.\n *\n * Flow:\n * 1. Transmit once per src via `transmitFile(id, path)` (t=f). The\n * terminal loads the image bytes from the file path; nothing of the\n * image is transmitted over the wire beyond the path itself.\n * 2. On every render, emit `placement(imgId, placeId, { cols, rows })`\n * at the target cursor position. Re-sending a placement with the\n * same (image id, placement id) moves/resizes the existing placement\n * without flicker — ideal for re-renders.\n *\n * Reference: https://sw.kovidgoyal.net/kitty/graphics-protocol/\n */\n\nimport type { MaybePromise } from \"@zaly/shared\"\nimport type { ImageInfo } from \"@zaly/shared/image\"\nimport type { TerminalQueries, TerminalQuery } from \"../input/queries.ts\"\n\nimport { isSSH } from \"@zaly/shared/env\"\n\nexport type KittyPlacement = {\n imageId: number\n /** Placement ID. Omitted when this is an inline placement (U=1) */\n placementId?: number\n /** inline: placement using unicode placeholder (U=1) */\n inline?: boolean\n /** The KGP escape sequence to place the image */\n seq: string\n /** Rows to render (excluding the placement escape sequence) */\n data: string[]\n}\n\nexport type ImageSupport = {\n terminal?: { name: string; version?: string }\n remote?: boolean\n wrap?: (seq: string) => string\n tmux?: boolean\n} & (\n | {\n ok: false\n error: string\n terminal?: { name: string; version?: string }\n }\n | {\n ok: true\n error?: never\n terminal: { name: string; version?: string }\n inline?: boolean\n }\n)\n\nexport type KittyResponse =\n | {\n attrs: Record<string, string | number>\n ok: true\n }\n | {\n attrs: Record<string, string | number>\n ok: false\n error: { code: string; message: string }\n }\n\nexport type PlacementDims = {\n /** Display width in terminal cells. */\n cols: number\n /** Display height in terminal cells. */\n rows: number\n}\n\n// Per-src transmit cache. The first caller gets the full transmit sequence;\n// subsequent callers get undefined since the terminal already has the bytes.\ntype CacheEntry = {\n imageId: number\n seq: string\n sent: boolean\n}\n\n// oxfmt-ignore\n// oxlint-disable-next-line unicorn/numeric-separators-style\nexport const DIACRITICS = [ 0x0305, 0x030d, 0x030e, 0x0310, 0x0312, 0x033d, 0x033e, 0x033f, 0x0346, 0x034a, 0x034b, 0x034c, 0x0350, 0x0351, 0x0352, 0x0357, 0x035b, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0592, 0x0593, 0x0594, 0x0595, 0x0597, 0x0598, 0x0599, 0x059c, 0x059d, 0x059e, 0x059f, 0x05a0, 0x05a1, 0x05a8, 0x05a9, 0x05ab, 0x05ac, 0x05af, 0x05c4, 0x0610, 0x0611, 0x0612, 0x0613, 0x0614, 0x0615, 0x0616, 0x0617, 0x0657, 0x0658, 0x0659, 0x065a, 0x065b, 0x065d, 0x065e, 0x06d6, 0x06d7, 0x06d8, 0x06d9, 0x06da, 0x06db, 0x06dc, 0x06df, 0x06e0, 0x06e1, 0x06e2, 0x06e4, 0x06e7, 0x06e8, 0x06eb, 0x06ec, 0x0730, 0x0732, 0x0733, 0x0735, 0x0736, 0x073a, 0x073d, 0x073f, 0x0740, 0x0741, 0x0743, 0x0745, 0x0747, 0x0749, 0x074a, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3, 0x0816, 0x0817, 0x0818, 0x0819, 0x081b, 0x081c, 0x081d, 0x081e, 0x081f, 0x0820, 0x0821, 0x0822, 0x0823, 0x0825, 0x0826, 0x0827, 0x0829, 0x082a, 0x082b, 0x082c, 0x082d, 0x0951, 0x0953, 0x0954, 0x0f82, 0x0f83, 0x0f86, 0x0f87, 0x135d, 0x135e, 0x135f, 0x17dd, 0x193a, 0x1a17, 0x1a75, 0x1a76, 0x1a77, 0x1a78, 0x1a79, 0x1a7a, 0x1a7b, 0x1a7c, 0x1b6b, 0x1b6d, 0x1b6e, 0x1b6f, 0x1b70, 0x1b71, 0x1b72, 0x1b73, 0x1cd0, 0x1cd1, 0x1cd2, 0x1cda, 0x1cdb, 0x1ce0, 0x1dc0, 0x1dc1, 0x1dc3, 0x1dc4, 0x1dc5, 0x1dc6, 0x1dc7, 0x1dc8, 0x1dc9, 0x1dcb, 0x1dcc, 0x1dd1, 0x1dd2, 0x1dd3, 0x1dd4, 0x1dd5, 0x1dd6, 0x1dd7, 0x1dd8, 0x1dd9, 0x1dda, 0x1ddb, 0x1ddc, 0x1ddd, 0x1dde, 0x1ddf, 0x1de0, 0x1de1, 0x1de2, 0x1de3, 0x1de4, 0x1de5, 0x1de6, 0x1dfe, 0x20d0, 0x20d1, 0x20d4, 0x20d5, 0x20d6, 0x20d7, 0x20db, 0x20dc, 0x20e1, 0x20e7, 0x20e9, 0x20f0, 0x2cef, 0x2cf0, 0x2cf1, 0x2de0, 0x2de1, 0x2de2, 0x2de3, 0x2de4, 0x2de5, 0x2de6, 0x2de7, 0x2de8, 0x2de9, 0x2dea, 0x2deb, 0x2dec, 0x2ded, 0x2dee, 0x2def, 0x2df0, 0x2df1, 0x2df2, 0x2df3, 0x2df4, 0x2df5, 0x2df6, 0x2df7, 0x2df8, 0x2df9, 0x2dfa, 0x2dfb, 0x2dfc, 0x2dfd, 0x2dfe, 0x2dff, 0xa66f, 0xa67c, 0xa67d, 0xa6f0, 0xa6f1, 0xa8e0, 0xa8e1, 0xa8e2, 0xa8e3, 0xa8e4, 0xa8e5, 0xa8e6, 0xa8e7, 0xa8e8, 0xa8e9, 0xa8ea, 0xa8eb, 0xa8ec, 0xa8ed, 0xa8ee, 0xa8ef, 0xa8f0, 0xa8f1, 0xaab0, 0xaab2, 0xaab3, 0xaab7, 0xaab8, 0xaabe, 0xaabf, 0xaac1, 0xfe20, 0xfe21, 0xfe22, 0xfe23, 0xfe24, 0xfe25, 0xfe26, 0x10a0f, 0x10a38, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243, 0x1d244 ].map((c) => String.fromCodePoint(c))\nexport const PLACEHOLDER = String.fromCodePoint(0x10_ee_ee)\nconst CHUNK_SIZE = 4096\nconst transmitCache = new Map<string, CacheEntry>()\n\nconst known: Record<string, { inline?: boolean } | false | undefined> = {\n ghostty: { inline: true },\n kitty: { inline: true },\n rio: { inline: false },\n wezterm: { inline: false },\n}\n\nlet prom: Promise<Kitty> | undefined = undefined\nlet kitty: Kitty | undefined = undefined\nconst wrapTmux = (seq: string): string => `\\x1bPtmux;${seq.replaceAll(\"\\x1b\", \"\\x1b\\x1b\")}\\x1b\\\\`\n\n/** Allocate a fresh 24-bit image id (1..0xFFFFFFFE). */\nexport function allocateImageId(): number {\n return Math.floor(Math.random() * 0xff_ff_fd) + 1\n}\n\n/** Allocate a fresh 24-bit placement id. */\nexport function allocatePlacementId(): number {\n return Math.floor(Math.random() * 0xff_ff_fd) + 1\n}\n\nexport class Kitty {\n #support: ImageSupport\n #wrap: (seq: string) => string = (s) => s\n\n constructor(support: ImageSupport) {\n this.#support = support\n this.#wrap = support.wrap ?? ((s) => s)\n }\n\n get supported(): boolean {\n return this.#support.ok\n }\n\n get inline(): boolean {\n return this.#support.ok && this.#support.inline === true\n }\n\n /** Create a KGP request escape sequence */\n request(\n attrs: Record<string, string | number>,\n data?: string | Uint8Array,\n opts: { base64?: boolean } = {}\n ): string {\n const params = Object.entries(attrs)\n .map(([k, v]) => `${k}=${v}`)\n .join(\",\")\n let encoded: string | undefined\n if (opts.base64 === false && typeof data === \"string\") encoded = data\n else if (data)\n encoded = toBase64(typeof data === \"string\" ? new TextEncoder().encode(data) : data)\n const payload = encoded ? `;${encoded}` : \"\"\n return this.#wrap(`\\x1b_G${params}${payload}\\x1b\\\\`)\n }\n\n /** Create a TerminalQuery that requests a KGP operation and parses the response. */\n query(\n attrs: Record<string, string | number>,\n data?: string | Uint8Array,\n opts: { base64?: boolean } = {}\n ): TerminalQuery {\n return {\n match: (ev) => {\n if (ev.kind !== \"apc\") return\n const kr = this.parse(ev.sequence)\n if (!kr) return\n return { ...ev, ...kr }\n },\n request: this.request(attrs, data, opts),\n }\n }\n\n /** Probe the terminal for KGP support. Should return an error response. */\n probe(): string {\n return this.request({ i: 4_294_967_290, s: 10, t: \"s\", v: 2 }, \"<error>\")\n }\n\n /** Parse a KGP response escape sequence into a structured object. */\n parse(res: string): KittyResponse | undefined {\n if (!res.startsWith(\"\\x1b_G\") || !res.endsWith(\"\\x1b\\\\\")) return undefined\n const body = res.slice(3, -2)\n const m = body.match(/^([^;]+);(.*)?$/)\n if (!m) return undefined\n const [_, params, data] = m as [string, string, string | undefined]\n const attrs: Record<string, string | number> = {}\n for (const pair of params.split(\",\")) {\n const [k, v] = pair.split(\"=\", 2)\n if (k && v) attrs[k] = /^\\d+$/.test(v) ? parseInt(v, 10) : v\n }\n if (data === \"OK\") return { attrs, ok: true }\n const error = data?.match(/^([A-Z]+):\\s*(.*)$/)\n return {\n attrs,\n error: error\n ? { code: error[1], message: error[2] }\n : { code: \"UNKNOWN\", message: data ?? \"\" },\n ok: false,\n }\n }\n\n placement(imageId: number, dims: PlacementDims): KittyPlacement | undefined {\n if (!this.#support.ok) return\n if (this.#support.inline)\n return {\n data: unicodePlaceholder(imageId, dims),\n imageId,\n inline: true,\n seq: this.request({ U: 1, a: \"p\", c: dims.cols, i: imageId, q: 2, r: dims.rows }),\n }\n const blank = \" \".repeat(dims.cols)\n const placementId = allocatePlacementId()\n // NOTE: never sort this, since we need a deterministic order for bumping placements\n // oxlint-disable-next-line sort-keys\n const seq = this.request({\n a: \"p\",\n i: imageId,\n p: placementId,\n C: 1,\n c: dims.cols,\n q: 2,\n r: dims.rows,\n })\n return {\n data: Array.from<string>({ length: dims.rows }).fill(blank),\n imageId,\n placementId,\n seq,\n }\n }\n\n /** Delete an image and all its placements, or ALL images if `imageId` is omitted. */\n deleteImage(imageId?: number): string {\n return imageId === undefined\n ? this.request({ a: \"d\", d: \"A\", q: 2 })\n : this.request({ a: \"d\", d: \"I\", i: imageId, q: 2 })\n }\n\n /** Delete a placement (keeps image data so it can be re-placed cheaply). */\n deletePlacement(imageId: number, placementId: number): string {\n return this.request({ a: \"d\", d: \"i\", i: imageId, p: placementId, q: 2 })\n }\n\n /**\n * Ensure an image has been transmitted to the terminal at least once.\n * On the first call per `src`, returns the full `a=t,t=f` escape to be\n * prepended to the caller's first row — the APC payload has zero display\n * width, so layout sees through it. Subsequent calls return `transmit:\n * \"\"` since the terminal already has the bytes under `imageId`.\n *\n * The caller is expected to combine this with `placement(...)` on every\n * render to actually paint the image at the right cell rectangle.\n */\n async transmitOnce(info: ImageInfo): Promise<{ imageId: number; transmit?: string } | undefined> {\n if (!this.#support.ok) return undefined\n const { fileHash } = await import(\"@zaly/shared/detect\")\n const key = fileHash(info)\n let entry = transmitCache.get(key)\n if (entry === undefined) {\n const { imageConvert } = await import(\"@zaly/shared/image\")\n const png = await imageConvert(info, \"png\")\n if (!png) return undefined\n const id = allocateImageId()\n // Under SSH the terminal can't read files on the local side, so\n // fall back to bytes-in-band (`t=d`). Locally we pass a path and\n // the transmit payload stays under 1KB.\n entry = {\n imageId: id,\n sent: false,\n seq:\n this.#support.remote || !png.path\n ? this.transmitBytes(id, png.data)\n : this.transmitFile(id, png.path),\n }\n transmitCache.set(key, entry)\n }\n if (entry.sent) {\n entry.seq = \"\" // Clear the transmit memory\n return { imageId: entry.imageId }\n }\n entry.sent = true\n return { imageId: entry.imageId, transmit: entry.seq }\n }\n\n /**\n * Transmit an image to the terminal by file path (`t=f`). Near-zero cost\n * on the wire — the terminal opens and reads the file itself. `path`\n * must be absolute and must point to a regular file; symlinks are\n * followed by the terminal.\n */\n transmitFile(id: number, path: string): string {\n return this.request({ a: \"t\", f: 100, i: id, q: 2, t: \"f\" }, path)\n }\n\n /**\n * Remote/bytes transmission fallback (`t=d`) for when the terminal can't\n * read local files — typical of SSH sessions. Base64-encodes and chunks\n * the PNG payload at 4KB boundaries per the protocol.\n */\n transmitBytes(id: number, png: Uint8Array): string {\n const base64 = toBase64(png)\n const params = { a: \"t\", f: 100, i: id, q: 2, t: \"d\" }\n if (base64.length <= CHUNK_SIZE) return this.request(params, base64, { base64: false })\n\n const out: string[] = []\n let offset = 0\n let first = true\n while (offset < base64.length) {\n const chunk = base64.slice(offset, offset + CHUNK_SIZE)\n offset += CHUNK_SIZE\n const more = offset < base64.length ? 1 : 0\n out.push(this.request(first ? { ...params, m: more } : { m: more }, chunk, { base64: false }))\n first = false\n }\n return out.join(\"\")\n }\n}\n\n/** Drop the per-src transmit cache. Mostly for tests. */\nexport function resetTransmitCache(): void {\n transmitCache.clear()\n}\n\nexport function resetKittyGraphics(): void {\n resetTransmitCache()\n prom = undefined\n kitty = undefined\n}\n\nfunction intToRgb(color24bit: number): { r: number; g: number; b: number } {\n const r = (color24bit >> 16) & 0xff\n const g = (color24bit >> 8) & 0xff\n const b = color24bit & 0xff\n return { b, g, r }\n}\n\nfunction unicodePlaceholder(id: number, dims: PlacementDims): string[] {\n const rgb = intToRgb(id)\n const rows = Math.min(DIACRITICS.length, dims.rows)\n const cols = Math.min(DIACRITICS.length, dims.cols)\n const fg = `\\x1b[38;2;${rgb.r};${rgb.g};${rgb.b}m`\n const img: string[] = []\n for (let r = 0; r < rows; r++) {\n const line: string[] = []\n for (let c = 0; c < cols; c++) {\n line.push(fg)\n line.push(PLACEHOLDER)\n line.push(DIACRITICS[r])\n line.push(DIACRITICS[c])\n }\n line.push(\"\\x1b[39m\")\n img.push(line.join(\"\"))\n }\n return img\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") return Buffer.from(bytes).toString(\"base64\")\n let binary = \"\"\n for (const b of bytes) binary += String.fromCharCode(b)\n return btoa(binary)\n}\n\nexport function bumpPlacements(\n rows: string[]\n): undefined | { delete: () => string; rows: string[] } {\n // We only need to bump placements when:\n // - kitty graphics are loaded (when not loaded, there can't be any placements yet)\n // - we're not using inline placements (when using inline, the placement is part of the row and doesn't need to be bumped)\n if (!kitty || kitty.inline) return\n\n const placements: { i: number; p: number }[] = []\n const ret = rows.map((row) =>\n row.replace(/\\x1b_Ga=p,i=(\\d+),p=(\\d+)/g, (_, i) => {\n const imageId = parseInt(i, 10)\n const placementId = allocatePlacementId()\n placements.push({ i: imageId, p: placementId })\n return `\\x1b_Ga=p,i=${imageId},p=${placementId}`\n })\n )\n if (!placements.length) return\n const k = kitty\n return {\n delete: () => placements.map((p) => k.deletePlacement(p.i, p.p)).join(\"\"),\n rows: ret,\n }\n}\n\nasync function detect(tq: TerminalQueries): Promise<ImageSupport> {\n const support: Omit<ImageSupport, \"ok\" | \"error\"> = {\n remote: isSSH,\n tmux: !!process.env.TMUX,\n // Escape sequences must be wrapped in a special way for tmux to pass them\n // through to the underlying terminal.\n wrap: process.env.TMUX ? wrapTmux : undefined,\n }\n if (support.tmux) {\n try {\n const { spawnCmd } = await import(\"@zaly/shared/process\")\n // TMUX needs to have allow-passthrough set to all images to work properly\n await spawnCmd(\"tmux\", \"set\", \"-p\", \"allow-passthrough\", \"on\")\n support.wrap = wrapTmux\n } catch (error) {\n return {\n ...support,\n error: `Failed to set allow-passthrough in tmux: ${error instanceof Error ? error.message : String(error)}`,\n ok: false,\n }\n }\n }\n\n const v = await tq.xtVersion({ wrap: support.wrap })\n if (!v) return { error: \"Failed to query terminal name & version\", ok: false, ...support }\n\n support.terminal = { name: v.name, version: v.version }\n\n const kgp = known[v.name.toLowerCase()]\n if (kgp === false)\n return { error: `Terminal ${v.name} does not support KGP`, ok: false, ...support }\n\n if (kgp === undefined) {\n // Probe KGP support\n // Create a tmp Kitty instance to probe the terminal for KGP support.\n const k = new Kitty({ ...support, error: \"\", ok: false })\n const res = await tq.query({\n match: (ev) => {\n if (ev.kind === \"apc\" && ev.payload.startsWith(\"G\")) return { kgp: true, ...ev }\n if (ev.kind === \"csi\" && ev.final === \"c\" && ev.params.startsWith(\"?\"))\n return { kgp: false, ...ev }\n return\n },\n request: `${k.probe()}\\x1b[c`,\n timeout: 200,\n })\n if (res?.kgp !== true)\n return { error: \"Failed to query kitty graphics protocol\", ok: false, ...support }\n }\n\n return {\n ...support,\n inline: kgp?.inline,\n ok: true,\n terminal: { name: v.name, version: v.version },\n }\n}\n\nexport function loadKittyGraphics(tq: TerminalQueries): MaybePromise<Kitty> {\n if (kitty) return kitty\n prom ??= (async () => (kitty = new Kitty(await detect(tq))))()\n return prom\n}\n"],"mappings":";;AAgFA,MAAa,aAAa;CAAE;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CAAQ;CA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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { n as box } from "./box-
|
|
2
|
-
import { n as text } from "./text-
|
|
3
|
-
import { n as markdown } from "./markdown-
|
|
4
|
-
import { t as widget } from "./widget-
|
|
1
|
+
import { n as box } from "./box-DToDoXlU.mjs";
|
|
2
|
+
import { n as text } from "./text-BArwVVkg.mjs";
|
|
3
|
+
import { n as markdown } from "./markdown-CgRZBhIX.mjs";
|
|
4
|
+
import { t as widget } from "./widget-sFveyrZE.mjs";
|
|
5
5
|
import { stringWidth } from "@zaly/shared/ansi";
|
|
6
6
|
import { hasColors } from "@zaly/shared/env";
|
|
7
|
-
|
|
7
|
+
// src/widgets/log.ts
|
|
8
8
|
/** Per-level default prefix style + icon + color. Matches rekal's
|
|
9
9
|
* `defaultStyles` table, adapted to zaly's theme slots. */
|
|
10
10
|
const defaultLogStyles = {
|
|
@@ -124,7 +124,6 @@ const log = widget((state, ...children) => {
|
|
|
124
124
|
gap: 1
|
|
125
125
|
}, ...children));
|
|
126
126
|
});
|
|
127
|
-
//#endregion
|
|
128
127
|
export { log as t };
|
|
129
128
|
|
|
130
|
-
//# sourceMappingURL=log-
|
|
129
|
+
//# sourceMappingURL=log-96b1_J6G.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-
|
|
1
|
+
{"version":3,"file":"log-96b1_J6G.mjs","names":[],"sources":["../src/widgets/log.ts"],"sourcesContent":["import type { LogLevel } from \"@zaly/shared/logger\"\nimport type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Node } from \"../core/node.ts\"\nimport type { State } from \"../core/state.ts\"\nimport type { Color } from \"../style/types.ts\"\nimport type { TextContent } from \"./text.ts\"\n\nimport { stringWidth } from \"@zaly/shared/ansi\"\nimport { hasColors } from \"@zaly/shared/env\"\nimport { box } from \"./box.ts\"\nimport { markdown } from \"./markdown.ts\"\nimport { text } from \"./text.ts\"\nimport { widget } from \"./widget.ts\"\n\nexport type LogStyle = \"badge\" | \"icon\" | \"prompt\" | \"title\" | \"text\" | \"notif\"\n\nexport interface LogState {\n level: LogLevel\n content: TextContent\n title?: string\n /** Rendering of the per-level prefix chunk. Defaults by level. */\n style?: LogStyle\n /** Single-glyph icon for `icon` / `prompt` styles. */\n icon?: string\n /** Theme slot or color name used to tint the prefix. */\n color?: Color<false>\n /** Extra plain text prepended to the auto prefix (unstyled). */\n prefix?: string\n /** Theme slot or color name for the body text. Defaults by level, except */\n textColor?: Color<false>\n markdown?: boolean\n}\n\ninterface LevelDefaults {\n style: LogStyle\n icon?: string\n color?: Color<false>\n textColor?: Color<false>\n}\n\n/** Per-level default prefix style + icon + color. Matches rekal's\n * `defaultStyles` table, adapted to zaly's theme slots. */\nconst defaultLogStyles: Record<LogLevel, LevelDefaults> = {\n cancel: { color: \"warn\", icon: \"✖ \", style: \"icon\" },\n debug: { color: \"info\", icon: \"⚙ \", style: \"prompt\" },\n error: { color: \"error\", icon: \"✖ \", style: \"badge\", textColor: \"error\" },\n fatal: { color: \"error\", icon: \"☢ \", style: \"badge\" },\n info: { color: \"info\", icon: \"ℹ \", style: \"icon\" },\n log: { color: \"muted\", icon: \"●\", style: \"icon\" },\n success: { color: \"success\", icon: \"✔ \", style: \"icon\" },\n trace: { color: \"muted\", icon: \"⠿\", style: \"icon\", textColor: \"muted\" },\n warn: { color: \"warn\", icon: \"⚠\", style: \"badge\", textColor: \"warn\" },\n}\n\nconst noColorStyles: Record<LogStyle, LogStyle> = {\n badge: \"title\",\n icon: \"text\",\n notif: \"text\",\n prompt: \"text\",\n text: \"text\",\n title: \"text\",\n}\n\nfunction renderPrefix(s: LogState, ctx: RenderCtx): string {\n const style = ctx.style\n\n const base = defaultLogStyles[s.level]\n let ls: LogStyle = s.style ?? base.style\n if (!hasColors) ls = noColorStyles[ls]\n\n let icon = s.icon ?? base.icon ?? \"\"\n icon = icon === \"\" ? \"\" : `${icon}${\" \".repeat(2 - stringWidth(icon))}`\n const color: Color<false> = s.color ?? base.color ?? \"inherit\"\n\n // text doesn't get a prefix\n let styledPrefix = \"\"\n if (ls === \"badge\") {\n styledPrefix = style.bg(color).bold(` ${s.level} `)\n } else if (ls === \"icon\") {\n styledPrefix = style.fg(color)(icon)\n } else if (ls === \"prompt\") {\n styledPrefix = style.fg(color).bold(`${icon} ${s.level}`)\n } else if (ls === \"title\") {\n styledPrefix = style.fg(color).bold(`${s.level}:`)\n } else if (ls === \"notif\") {\n styledPrefix = style.fg(color).bold(`${icon} ${s.title ?? s.level}`)\n }\n\n if (s.prefix) styledPrefix = s.prefix + styledPrefix\n if (s.title && ls !== \"notif\") styledPrefix += style.bold(` ${s.title}`)\n return styledPrefix\n}\n\n/**\n * A single log entry — level-styled prefix (icon / badge / prompt / title /\n * plain text) followed by the body content. The body can be any Node, so\n * callers can stack markdown, code, images, etc. inside a log line.\n *\n * ```ts\n * log({ level: \"info\", content: \"hello\" })\n * log({ level: \"error\", content: markdown(\"**boom**\") })\n * ```\n */\nexport const log = widget((state: State<LogState>, ...children: Node[]) => {\n const base = defaultLogStyles[state.level]\n const color: Color = state.color ?? base.color ?? \"inherit\"\n const s = state\n const textColor = state.textColor ?? (s.style === \"notif\" ? \"inherit\" : base.textColor)\n const style = {\n style: textColor\n ? {\n fg: textColor,\n }\n : undefined,\n width: \"fill\",\n } as const\n if (state.content !== \"\") {\n children = [\n (state.markdown ?? true) ? markdown(state.content, style) : text(state.content, style),\n ...children,\n ]\n }\n return box(\n {\n ...(s.style === \"notif\"\n ? {\n border: \"single\",\n borderStyle: { fg: color },\n borderTitle: (ctx) => renderPrefix(state, ctx),\n borderTitleAlign: \"center\",\n padding: [0, 1],\n //style: \"overlay\",\n width: \"fill\",\n }\n : undefined),\n flexDirection: \"row\",\n gap: 1,\n visible: state.visible,\n },\n s.style === \"notif\"\n ? undefined\n : text((ctx) => renderPrefix(state, ctx), { flexShrink: 0, wrap: \"none\" }),\n box({ flexDirection: \"column\", flexGrow: 1, gap: 1 }, ...children)\n )\n})\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as Node } from "./node-
|
|
2
|
-
import { n as inspectFormat, r as isMarkdown } from "./inspect-
|
|
3
|
-
import { t as log } from "./log-
|
|
4
|
-
|
|
1
|
+
import { t as Node } from "./node-CXNobGaP.mjs";
|
|
2
|
+
import { n as inspectFormat, r as isMarkdown } from "./inspect-Cli1beu8.mjs";
|
|
3
|
+
import { t as log } from "./log-96b1_J6G.mjs";
|
|
4
|
+
// src/services/logger.ts
|
|
5
5
|
const ERR_LEVELS = /* @__PURE__ */ new Set([
|
|
6
6
|
"error",
|
|
7
7
|
"fatal",
|
|
@@ -65,7 +65,6 @@ var TuiReporter = class {
|
|
|
65
65
|
(this.#opts.write ?? defaultWrite)(`${str}\n`, kind);
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
|
-
//#endregion
|
|
69
68
|
export { TuiReporter as t };
|
|
70
69
|
|
|
71
|
-
//# sourceMappingURL=logger-
|
|
70
|
+
//# sourceMappingURL=logger-DwfXp8LF.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger-
|
|
1
|
+
{"version":3,"file":"logger-DwfXp8LF.mjs","names":[],"sources":["../src/services/logger.ts"],"sourcesContent":["import type { LogEntry, LogLevel, LogReporter } from \"@zaly/shared/logger\"\nimport type { InspectOpts } from \"../style/inspect.ts\"\nimport type { LogState } from \"../widgets/log.ts\"\n\nimport { Node } from \"../core/node.ts\"\nimport { inspectFormat, isMarkdown } from \"../style/inspect.ts\"\nimport { log } from \"../widgets/log.ts\"\n\n/** Minimal stream surface the logger needs. Stream satisfies this. */\nexport interface LoggerStream {\n append: (node: () => Node) => unknown\n}\n\nexport type LogEntryFactory = (level: LogLevel, msg: unknown[]) => Node\n\nexport type LogStyleOverride = Omit<LogState, \"level\" | \"content\">\n\nexport interface TuiReporterOpts extends InspectOpts {\n /** Render string messages as markdown when they look like it.\n * Default: `true`. */\n markdown?: boolean\n /** Per-level overrides for the default `log()` widget style fields. */\n styles?: Partial<Record<LogLevel, LogStyleOverride>>\n /** Override the node produced per entry. Default uses `log()`. */\n factory?: LogEntryFactory\n wrap?: (node: Node) => Node\n /** Fallback writer for when no stream is attached. Defaults to\n * `process.stdout/stderr`. Injectable for tests. */\n write?: (text: string, kind: \"stdout\" | \"stderr\") => void\n}\n\nconst ERR_LEVELS = new Set<LogLevel>([\"error\", \"fatal\", \"warn\"])\n\nfunction defaultWrite(text: string, kind: \"stdout\" | \"stderr\"): void {\n if (typeof process === \"undefined\") return\n const stream = kind === \"stderr\" ? process.stderr : process.stdout\n stream.write(text)\n}\n\nexport class TuiReporter implements LogReporter {\n #stream?: LoggerStream\n #opts: TuiReporterOpts\n #factory: LogEntryFactory\n\n constructor(opts: TuiReporterOpts = {}) {\n this.#opts = opts\n this.#factory = opts.factory ?? ((level, msg) => this.#defaultFactory(level, msg))\n }\n\n attach(stream: LoggerStream): this {\n this.#stream = stream\n return this\n }\n\n detach(): this {\n this.#stream = undefined\n return this\n }\n\n $log({ level, msg }: LogEntry): void {\n if (this.#stream) {\n this.#stream.append(() => {\n const node = this.#factory(level, msg)\n return this.#opts.wrap?.(node) ?? node\n })\n return\n }\n this.#writeFallback(level, msg)\n }\n\n #defaultFactory(level: LogLevel, msg: unknown[]): Node {\n const nodes = msg.filter((m): m is Node => m instanceof Node)\n msg = msg.filter((m) => !(m instanceof Node))\n\n // Convert Error objects to their message unless stacktrace is requested.\n msg = this.#opts.stacktrace ? msg : msg.map((v) => (v instanceof Error ? v.message : v))\n\n // If all remaining messages are strings, join them into one string for the log content.\n if (msg.length && msg.every((m) => typeof m === \"string\")) msg = [msg.join(\" \")]\n\n // If there's exactly one string message, use it as the log content;\n // otherwise, leave it undefined to be formatted with `inspect()`.\n // Text allow markdown if the message looks like markdown and the option is enabled.\n let text = msg.length === 1 && typeof msg[0] === \"string\" ? msg[0] : undefined\n if (msg.length === 0) text = \"\"\n const markdown = (this.#opts.markdown ?? true) && text !== undefined && isMarkdown(text)\n const overrides = this.#opts.styles?.[level] ?? {}\n return log(\n {\n content: text ?? ((ctx) => inspectFormat(msg, { ...this.#opts, style: ctx.style })),\n level,\n markdown,\n ...overrides,\n },\n ...nodes\n )\n }\n\n /** String path for the no-stream fallback — builds a plain inspected\n * line (no prefix chrome) and writes it to stdout/stderr. Keeps the\n * fallback synchronous and ordered. */\n #writeFallback(level: LogLevel, msg: unknown[]): void {\n const str = inspectFormat(msg, this.#opts)\n const kind: \"stdout\" | \"stderr\" = ERR_LEVELS.has(level) ? \"stderr\" : \"stdout\"\n const write = this.#opts.write ?? defaultWrite\n write(`${str}\\n`, kind)\n }\n}\n"],"mappings":";;;;AA+BA,MAAM,6BAAa,IAAI,IAAc;CAAC;CAAS;CAAS;AAAM,CAAC;AAE/D,SAAS,aAAa,MAAc,MAAiC;CACnE,IAAI,OAAO,YAAY,aAAa;CAEpC,CADe,SAAS,WAAW,QAAQ,SAAS,QAAQ,OAAA,CACrD,MAAM,IAAI;AACnB;AAEA,IAAa,cAAb,MAAgD;CAC9C;CACA;CACA;CAEA,YAAY,OAAwB,CAAC,GAAG;EACtC,KAAK,QAAQ;EACb,KAAK,WAAW,KAAK,aAAa,OAAO,QAAQ,KAAK,gBAAgB,OAAO,GAAG;CAClF;CAEA,OAAO,QAA4B;EACjC,KAAK,UAAU;EACf,OAAO;CACT;CAEA,SAAe;EACb,KAAK,UAAU,KAAA;EACf,OAAO;CACT;CAEA,KAAK,EAAE,OAAO,OAAuB;EACnC,IAAI,KAAK,SAAS;GAChB,KAAK,QAAQ,aAAa;IACxB,MAAM,OAAO,KAAK,SAAS,OAAO,GAAG;IACrC,OAAO,KAAK,MAAM,OAAO,IAAI,KAAK;GACpC,CAAC;GACD;EACF;EACA,KAAK,eAAe,OAAO,GAAG;CAChC;CAEA,gBAAgB,OAAiB,KAAsB;EACrD,MAAM,QAAQ,IAAI,QAAQ,MAAiB,aAAa,IAAI;EAC5D,MAAM,IAAI,QAAQ,MAAM,EAAE,aAAa,KAAK;EAG5C,MAAM,KAAK,MAAM,aAAa,MAAM,IAAI,KAAK,MAAO,aAAa,QAAQ,EAAE,UAAU,CAAE;EAGvF,IAAI,IAAI,UAAU,IAAI,OAAO,MAAM,OAAO,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,KAAK,GAAG,CAAC;EAK/E,IAAI,OAAO,IAAI,WAAW,KAAK,OAAO,IAAI,OAAO,WAAW,IAAI,KAAK,KAAA;EACrE,IAAI,IAAI,WAAW,GAAG,OAAO;EAC7B,MAAM,YAAY,KAAK,MAAM,YAAY,SAAS,SAAS,KAAA,KAAa,WAAW,IAAI;EACvF,MAAM,YAAY,KAAK,MAAM,SAAS,UAAU,CAAC;EACjD,OAAO,IACL;GACE,SAAS,UAAU,QAAQ,cAAc,KAAK;IAAE,GAAG,KAAK;IAAO,OAAO,IAAI;GAAM,CAAC;GACjF;GACA;GACA,GAAG;EACL,GACA,GAAG,KACL;CACF;;;;CAKA,eAAe,OAAiB,KAAsB;EACpD,MAAM,MAAM,cAAc,KAAK,KAAK,KAAK;EACzC,MAAM,OAA4B,WAAW,IAAI,KAAK,IAAI,WAAW;EAErE,CADc,KAAK,MAAM,SAAS,aAAA,CAC5B,GAAG,IAAI,KAAK,IAAI;CACxB;AACF"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { S as unwrap, r as createAsync, w as useContext, y as signal } from "./reactive-
|
|
2
|
-
import { t as Node } from "./node-
|
|
3
|
-
import { i as expandTabs, o as formatText, t as calcLayout } from "./text-
|
|
4
|
-
import { r as textContent } from "./text-
|
|
5
|
-
import { t as RenderContext } from "./render-
|
|
6
|
-
import { n as shikiWorker } from "./client-
|
|
7
|
-
import { t as codeToAnsi } from "./shiki
|
|
1
|
+
import { S as unwrap, r as createAsync, w as useContext, y as signal } from "./reactive-DkP75TPk.mjs";
|
|
2
|
+
import { t as Node } from "./node-CXNobGaP.mjs";
|
|
3
|
+
import { i as expandTabs, o as formatText, t as calcLayout } from "./text-4arC3odI.mjs";
|
|
4
|
+
import { r as textContent } from "./text-BArwVVkg.mjs";
|
|
5
|
+
import { t as RenderContext } from "./render-Bp2N2i6J.mjs";
|
|
6
|
+
import { n as shikiWorker } from "./client-BWm6dNZF.mjs";
|
|
7
|
+
import { t as codeToAnsi } from "./shiki-BAf9PdIc.mjs";
|
|
8
|
+
import { t as shikiTheme } from "./theme-B8hb1lPU.mjs";
|
|
8
9
|
import { hasColors } from "@zaly/shared/env";
|
|
9
|
-
|
|
10
|
+
// src/widgets/markdown.ts
|
|
10
11
|
var Markdown = class extends Node {
|
|
11
12
|
images = /* @__PURE__ */ new Map();
|
|
12
13
|
#renderer;
|
|
@@ -73,7 +74,7 @@ var Markdown = class extends Node {
|
|
|
73
74
|
}
|
|
74
75
|
async _render(ctx) {
|
|
75
76
|
if (!this.#renderer) {
|
|
76
|
-
const { MarkdownRenderer } = await import("./renderer-
|
|
77
|
+
const { MarkdownRenderer } = await import("./renderer-Ctz0hv5o.mjs");
|
|
77
78
|
this.#renderer = new MarkdownRenderer({
|
|
78
79
|
...this.state.options,
|
|
79
80
|
parent: this
|
|
@@ -87,7 +88,7 @@ var Markdown = class extends Node {
|
|
|
87
88
|
this.#gen++;
|
|
88
89
|
formatted = await this.#renderer.render(source, {
|
|
89
90
|
...ctx,
|
|
90
|
-
highlight: (code, lang) => this.#highlight(code, lang, ctx.style.theme
|
|
91
|
+
highlight: (code, lang) => this.#highlight(code, lang, shikiTheme(ctx.style.theme)),
|
|
91
92
|
images: unwrap(this.#images) ?? true
|
|
92
93
|
});
|
|
93
94
|
for (const [k, c] of this.#code.entries()) if (c.gen !== this.#gen) {
|
|
@@ -118,7 +119,6 @@ function markdown(first, style) {
|
|
|
118
119
|
});
|
|
119
120
|
return new Markdown(first);
|
|
120
121
|
}
|
|
121
|
-
//#endregion
|
|
122
122
|
export { markdown as n, Markdown as t };
|
|
123
123
|
|
|
124
|
-
//# sourceMappingURL=markdown-
|
|
124
|
+
//# sourceMappingURL=markdown-CgRZBhIX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-CgRZBhIX.mjs","names":[],"sources":["../src/widgets/markdown.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Accessor } from \"../core/reactive.ts\"\nimport type { State } from \"../core/state.ts\"\nimport type { WrapMode } from \"../layout/text.ts\"\nimport type { MarkdownRenderer } from \"../markdown/renderer.ts\"\nimport type { MdOptions } from \"../markdown/types.ts\"\nimport type { ShikiThemeInput } from \"../shiki/types.ts\"\nimport type { AnyStyle } from \"../style/types.ts\"\nimport type { Image } from \"./image.ts\"\nimport type { TextContent } from \"./text.ts\"\n\nimport { hasColors } from \"@zaly/shared/env\"\nimport { Node } from \"../core/node.ts\"\nimport { createAsync, signal, unwrap, useContext } from \"../core/reactive.ts\"\nimport { RenderContext } from \"../core/render.ts\"\nimport { calcLayout, expandTabs, formatText } from \"../layout/text.ts\"\nimport { shikiWorker } from \"../shiki/client.ts\"\nimport { codeToAnsi } from \"../shiki/shiki.ts\"\nimport { shikiTheme } from \"../shiki/theme.ts\"\nimport { textContent } from \"./text.ts\"\n\nexport interface MarkdownState {\n /** Markdown source. Accepts a plain string or a reactive accessor —\n * pass `signal()` / `memo()` for streaming content that re-parses on\n * each render and subscribes the node to the signal. */\n content: TextContent\n /** Options forwarded to `renderMarkdown`. */\n options?: MdOptions\n /**\n * Enable shiki-backed syntax highlighting for fenced code blocks. Defaults\n * to `true` — code blocks get per-token colors from the shiki theme, with\n * `mdCodeBlock`'s bg applied as a backdrop. Unknown languages fall through\n * as plain text.\n */\n syntax?: boolean\n wrap?: WrapMode\n style?: AnyStyle\n}\n\ntype ShikiCode = {\n key: string\n code: string\n lang: string\n theme?: ShikiThemeInput\n inflight?: Promise<string>\n ac?: AbortController\n result?: string\n gen: number\n}\n\nexport class Markdown extends Node<MarkdownState> {\n // Image nodes cached per-src per-Markdown-instance. Re-rendering the\n // same markdown (streaming updates) reuses the same `Image` — same\n // `placementId`, which the KGP spec guarantees is a flicker-free\n // move/resize of the existing placement.\n readonly images = new Map<string, Image>()\n\n #renderer?: MarkdownRenderer\n #code = new Map<string, ShikiCode>()\n #update = signal(0)\n #gen = 0\n #worker: Accessor<number>\n #images?: Accessor<boolean>\n\n constructor(state: State<MarkdownState>) {\n super(state)\n\n const context = useContext(RenderContext)\n this.#images = context?.images\n\n this.#worker = createAsync(\n async () => {\n const update = this.#update.get() // track\n const todo = [...this.#code.values()].filter((c) => c.gen === this.#gen && !c.result)\n if (!todo.length) return update // nothing to do, skip\n await Promise.all(\n todo.map(async (req) => {\n req.ac ??= new AbortController()\n req.inflight ??= codeToAnsi(req.code, req.lang, {\n signal: req.ac.signal,\n theme: req.theme,\n })\n try {\n req.result = await req.inflight\n } catch (error) {\n if (req.ac.signal.aborted) {\n if (this.#code.get(req.key) === req) this.#code.delete(req.key)\n } else throw error\n }\n })\n )\n return update + 1\n },\n { initialValue: 0 }\n )\n }\n\n /** Find a highlighted result for a prefix of `code` in the cache. This\n * handles streaming updates where the full code block isn't available yet\n * and prevents flashing un-highlighted text on each update. */\n #streamingHighlight(code: string, lang: string, theme?: ShikiThemeInput) {\n let ret: ShikiCode | undefined\n for (const c of this.#code.values()) {\n if (!c.result || c.lang !== lang || c.theme !== theme) continue\n if (code.startsWith(c.code) && c.code.length > (ret?.code.length ?? 0)) ret = c\n }\n if (ret) ret.gen = this.#gen // bump gen to keep it alive in cache\n return ret?.result ? ret.result + code.slice(ret.code.length) : code\n }\n\n #highlight(code: string, lang?: string, theme?: ShikiThemeInput): string {\n if (!lang) return code\n const key = shikiWorker.key({ code, lang, theme })\n const ret = this.#code.get(key)\n if (ret) ret.gen = this.#gen // bump gen to keep it alive in cache\n if (ret?.result) return ret.result\n else if (!ret) this.#code.set(key, { code, gen: this.#gen, key, lang, theme })\n return this.#streamingHighlight(code, lang, theme)\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n if (!this.#renderer) {\n const { MarkdownRenderer } = await import(\"../markdown/renderer.ts\")\n this.#renderer = new MarkdownRenderer({ ...this.state.options, parent: this })\n }\n let source = await textContent(this.state.content, ctx)\n source = expandTabs(source)\n let formatted: string\n\n if (!hasColors) formatted = this.#renderer.normalizeEol(source, source)\n else {\n this.#gen++ // bump generation to track what is still used\n\n formatted = await this.#renderer.render(source, {\n ...ctx,\n highlight: (code, lang) => this.#highlight(code, lang, shikiTheme(ctx.style.theme)),\n images: unwrap(this.#images) ?? true,\n })\n\n // prune old entries\n for (const [k, c] of this.#code.entries())\n if (c.gen !== this.#gen) {\n c.ac?.abort()\n if (c.result !== undefined) this.#code.delete(k)\n }\n\n // Trigger the worker if needed\n if (this.#code.values().some((c) => !c.inflight)) {\n this.#update.set(this.#gen) // trigger worker\n this.#worker() // tracked\n }\n }\n\n return formatText(formatted, {\n indent: true,\n style: this.state.style ? ctx.style.add(this.state.style) : undefined,\n width: ctx.width,\n wrap: this.state.wrap,\n wrapBg: true,\n })\n }\n\n override async layout(ctx: RenderCtx) {\n return calcLayout(await textContent(this.state.content, ctx))\n }\n}\n\n/**\n * Render a markdown string as a TUI node. Produces ANSI-styled text that\n * resolves per-element styling through theme slots (`mdHeading1`, `mdCode`,\n * `mdLink`, …). Links become clickable in terminals that support OSC 8.\n *\n * ```ts\n * markdown(\"# Hello\\n\\nThis is **bold** and *italic*.\")\n * markdown({ content, wrap: \"word\", fg: \"fg\" })\n * ```\n */\nexport function markdown(\n content: TextContent,\n style?: Omit<State<MarkdownState>, \"content\">\n): Markdown\nexport function markdown(state: State<MarkdownState>): Markdown\nexport function markdown(\n first: TextContent | MarkdownState,\n style?: Omit<State<MarkdownState>, \"content\">\n): Markdown {\n // Plain strings and accessor functions go through the content path;\n // a non-function object is the full state form.\n if (typeof first === \"string\" || typeof first === \"function\") {\n return new Markdown({ content: first, ...style })\n }\n return new Markdown(first)\n}\n"],"mappings":"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"}
|
package/dist/markdown.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as MdOptions, r as RenderMarkdown } from "./types-
|
|
3
|
-
//#region src/markdown/renderer.d.ts
|
|
1
|
+
import { I as RenderCtx, h as Node } from "./queries-Dmd3IjSd.mjs";
|
|
2
|
+
import { n as MdOptions, r as RenderMarkdown } from "./types-CUVUJPz6.mjs";
|
|
4
3
|
export type MarkdownOptions = MdOptions & {
|
|
5
4
|
parent?: Node;
|
|
6
5
|
};
|
|
@@ -19,6 +18,5 @@ export declare class MarkdownRenderer {
|
|
|
19
18
|
/* they asked for it. */
|
|
20
19
|
normalizeEol(source: string, rendered: string): string;
|
|
21
20
|
}
|
|
22
|
-
//#endregion
|
|
23
21
|
export type { MdOptions, RenderMarkdown };
|
|
24
22
|
//# sourceMappingURL=markdown.d.mts.map
|
package/dist/markdown.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.mts","names":[],"sources":["../src/markdown/renderer.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"markdown.d.mts","names":[],"sources":["../src/markdown/renderer.ts"],"mappings":";;YAKY,kBAAkB;EAC5B,SAAS;;YAGC,cAAc;EACxB;EACA,aAAa,cAAc;;qBAGhB;;EAMX,YAAY,OAAM;EAKZ,OAAO,gBAAgB,KAAK,cAAc;;;;;;EAmChD,aAAa,gBAAgB"}
|
package/dist/markdown.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as MarkdownRenderer } from "./renderer-
|
|
1
|
+
export { t as MarkdownRenderer } from "./renderer-BYl2pbdx.mjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as mathImage } from "./math-VPuwFCid.mjs";
|