@zaly/tui 0.0.11 → 0.1.0
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 +227 -732
- package/assets/themes/andromeeda.json +97 -0
- package/assets/themes/ayu-dark.json +31 -44
- package/assets/themes/ayu-light.json +106 -0
- package/assets/themes/ayu-mirage.json +106 -0
- package/assets/themes/catppuccin-frappe.json +44 -60
- package/assets/themes/catppuccin-latte.json +44 -60
- package/assets/themes/catppuccin-macchiato.json +44 -60
- package/assets/themes/catppuccin-mocha.json +44 -60
- package/assets/themes/dark-plus.json +99 -0
- package/assets/themes/dracula.json +47 -66
- package/assets/themes/everforest-dark.json +28 -45
- package/assets/themes/everforest-light.json +28 -45
- 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 -48
- 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 -68
- package/assets/themes/kanagawa-lotus.json +105 -0
- package/assets/themes/kanagawa-wave.json +55 -68
- 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 -64
- package/assets/themes/material-theme.json +102 -0
- package/assets/themes/min-dark.json +67 -28
- package/assets/themes/min-light.json +67 -32
- package/assets/themes/monokai.json +55 -67
- package/assets/themes/night-owl-light.json +105 -0
- package/assets/themes/night-owl.json +57 -68
- package/assets/themes/nord.json +53 -55
- package/assets/themes/one-dark-pro.json +46 -57
- package/assets/themes/one-light.json +52 -59
- package/assets/themes/poimandres.json +51 -68
- package/assets/themes/rose-pine-dawn.json +99 -0
- package/assets/themes/rose-pine-moon.json +99 -0
- package/assets/themes/rose-pine.json +51 -50
- package/assets/themes/solarized-dark.json +39 -51
- package/assets/themes/solarized-light.json +40 -52
- package/assets/themes/synthwave-84.json +48 -50
- package/assets/themes/tokyonight-day.json +6 -7
- package/assets/themes/tokyonight-moon.json +6 -6
- package/assets/themes/tokyonight-night.json +6 -6
- package/assets/themes/tokyonight-storm.json +6 -6
- package/assets/themes/vesper.json +51 -58
- package/assets/themes/vitesse-black.json +103 -0
- package/assets/themes/vitesse-dark.json +26 -49
- package/assets/themes/vitesse-light.json +26 -49
- package/dist/{actions-DFboj3g5.d.mts → actions--ODlgCQ5.d.mts} +4 -4
- package/dist/{actions-DFboj3g5.d.mts.map → actions--ODlgCQ5.d.mts.map} +1 -1
- package/dist/{ansi-Clq0ozyA.mjs → ansi-CMv71xVr.mjs} +38 -31
- package/dist/ansi-CMv71xVr.mjs.map +1 -0
- package/dist/ansi.d.mts +3 -1
- package/dist/ansi.d.mts.map +1 -1
- package/dist/ansi.mjs +1 -1
- package/dist/{autocomplete-CxzetPOo.d.mts → autocomplete-CD30kSe_.d.mts} +4 -4
- package/dist/{autocomplete-CxzetPOo.d.mts.map → autocomplete-CD30kSe_.d.mts.map} +1 -1
- package/dist/{box-DLEcEvDH.mjs → box-C_N_7ChP.mjs} +2 -2
- package/dist/box-C_N_7ChP.mjs.map +1 -0
- package/dist/builder-Chwtk0nQ.mjs +196 -0
- package/dist/builder-Chwtk0nQ.mjs.map +1 -0
- package/dist/{callbacks-D132G8dy.mjs → callbacks-DLecWn7G.mjs} +4 -4
- package/dist/{callbacks-D132G8dy.mjs.map → callbacks-DLecWn7G.mjs.map} +1 -1
- package/dist/client-CNGt-dOt.mjs +1 -0
- package/dist/{client-C2GXKfJ1.mjs → client-D7qz4TZt.mjs} +7 -3
- package/dist/client-D7qz4TZt.mjs.map +1 -0
- package/dist/color-DBMQLv4Y.mjs +37 -0
- package/dist/color-DBMQLv4Y.mjs.map +1 -0
- package/dist/{ctx-8Nuf5BrN.mjs → ctx-BaQ2hP5u.mjs} +3 -3
- package/dist/{ctx-8Nuf5BrN.mjs.map → ctx-BaQ2hP5u.mjs.map} +1 -1
- package/dist/ctx-CndlTp1T.mjs +1 -0
- package/dist/{divider-l0-JPEIm.mjs → divider-BlNNN2OS.mjs} +2 -2
- package/dist/divider-BlNNN2OS.mjs.map +1 -0
- package/dist/{files-BUsa-RVl.d.mts → files-B_5HDBPp.d.mts} +3 -3
- package/dist/{files-BUsa-RVl.d.mts.map → files-B_5HDBPp.d.mts.map} +1 -1
- package/dist/github-Cy2hfWJ7.mjs.map +1 -1
- package/dist/{github-D89A3F9U.d.mts → github-CyRwUQ3y.d.mts} +3 -3
- package/dist/{github-D89A3F9U.d.mts.map → github-CyRwUQ3y.d.mts.map} +1 -1
- package/dist/{image-34bU73bW.d.mts → image-BLls2F4t.d.mts} +2 -2
- package/dist/{image-34bU73bW.d.mts.map → image-BLls2F4t.d.mts.map} +1 -1
- package/dist/image-Cqtj3yRA.mjs +178 -0
- package/dist/image-Cqtj3yRA.mjs.map +1 -0
- package/dist/image.d.mts +1 -1
- package/dist/index.d.mts +13 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +8 -7
- package/dist/index.mjs.map +1 -1
- package/dist/{input-D7fQEUdt.mjs → input-ET2YEMcl.mjs} +16 -11
- package/dist/input-ET2YEMcl.mjs.map +1 -0
- package/dist/{input-Dylds_sI.d.mts → input-NuD8TH8N.d.mts} +3 -3
- package/dist/{input-Dylds_sI.d.mts.map → input-NuD8TH8N.d.mts.map} +1 -1
- package/dist/{inspect-DPLRum7L.d.mts → inspect-B1uXxdKC.d.mts} +11 -15
- package/dist/inspect-B1uXxdKC.d.mts.map +1 -0
- package/dist/{inspect-CcgiZ_F9.mjs → inspect-Cxzs-W0g.mjs} +2 -2
- package/dist/{inspect-CcgiZ_F9.mjs.map → inspect-Cxzs-W0g.mjs.map} +1 -1
- package/dist/kitty-DKQYsQfH.mjs +1 -0
- package/dist/{log-Dy_QnPZF.mjs → log-B4djzy2m.mjs} +5 -5
- package/dist/log-B4djzy2m.mjs.map +1 -0
- package/dist/{logger-DvuX9DPS.mjs → logger-CvJCITzP.mjs} +3 -3
- package/dist/{logger-DvuX9DPS.mjs.map → logger-CvJCITzP.mjs.map} +1 -1
- package/dist/{markdown-BGPa7UzD.mjs → markdown-D3ZtRn6C.mjs} +9 -8
- package/dist/markdown-D3ZtRn6C.mjs.map +1 -0
- package/dist/markdown.d.mts +1 -1
- package/dist/markdown.d.mts.map +1 -1
- package/dist/markdown.mjs +1 -1
- package/dist/math-CU0wmC9N.mjs +1 -0
- package/dist/math-Dd7a1irv.mjs +206 -0
- package/dist/math-Dd7a1irv.mjs.map +1 -0
- package/dist/oklch-Bsh5swbC.mjs +99 -0
- package/dist/oklch-Bsh5swbC.mjs.map +1 -0
- package/dist/{overlay-9WXYiGgW.mjs → overlay-LvOjG7kn.mjs} +2 -2
- package/dist/{overlay-9WXYiGgW.mjs.map → overlay-LvOjG7kn.mjs.map} +1 -1
- package/dist/{picker-JL8lZfRH.d.mts → picker-B-OxKKnD.d.mts} +5 -5
- package/dist/{picker-JL8lZfRH.d.mts.map → picker-B-OxKKnD.d.mts.map} +1 -1
- package/dist/{picker-BqHINl_a.mjs → picker-f6xjgACX.mjs} +2 -2
- package/dist/{picker-BqHINl_a.mjs.map → picker-f6xjgACX.mjs.map} +1 -1
- package/dist/{queries-B_lOwEiE.mjs → queries-BUkBxkuM.mjs} +66 -3
- package/dist/queries-BUkBxkuM.mjs.map +1 -0
- package/dist/{queries-Cvalgu6P.d.mts → queries-C75-wG1B.d.mts} +42 -11
- package/dist/queries-C75-wG1B.d.mts.map +1 -0
- package/dist/{registry-3hLzS4ks.mjs → registry-DUWpSPoo.mjs} +208 -68
- package/dist/registry-DUWpSPoo.mjs.map +1 -0
- package/dist/{render-f7M2856V.mjs → render-B7LfNM5K.mjs} +2 -2
- package/dist/{render-f7M2856V.mjs.map → render-B7LfNM5K.mjs.map} +1 -1
- package/dist/{renderer-V6AGjbyf.mjs → renderer-BLsd-wrG.mjs} +167 -20
- package/dist/renderer-BLsd-wrG.mjs.map +1 -0
- package/dist/renderer-YHbR7JZ4.mjs +1 -0
- package/dist/{renderer-DesbRwjQ.mjs → renderer-aAtkFgll.mjs} +8 -7
- package/dist/renderer-aAtkFgll.mjs.map +1 -0
- package/dist/{select-zGd5pbiB.d.mts → select-BKE5LzdN.d.mts} +3 -3
- package/dist/{select-zGd5pbiB.d.mts.map → select-BKE5LzdN.d.mts.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 -1
- package/dist/services/notifier.mjs +2 -2
- package/dist/services/picker.d.mts +5 -5
- package/dist/services/picker.mjs +6 -6
- package/dist/services/prompt.d.mts +4 -4
- package/dist/services/prompt.mjs +5 -5
- package/dist/shiki/server.mjs +37 -14
- package/dist/shiki/server.mjs.map +1 -1
- package/dist/shiki-B4U0s8jT.mjs +635 -0
- package/dist/shiki-B4U0s8jT.mjs.map +1 -0
- package/dist/shiki-CJauRusM.mjs +20 -0
- package/dist/shiki-CJauRusM.mjs.map +1 -0
- package/dist/style-DslRHzI4.mjs +109 -0
- package/dist/style-DslRHzI4.mjs.map +1 -0
- package/dist/style.d.mts +4 -3
- package/dist/style.d.mts.map +1 -1
- package/dist/style.mjs +4 -4
- package/dist/{text-CRZD9KTN.mjs → text-BoJdKXLU.mjs} +2 -2
- package/dist/{text-CRZD9KTN.mjs.map → text-BoJdKXLU.mjs.map} +1 -1
- package/dist/{text-BefiXAFW.d.mts → text-CmxbA8lk.d.mts} +3 -3
- package/dist/{text-BefiXAFW.d.mts.map → text-CmxbA8lk.d.mts.map} +1 -1
- package/dist/{text-BLz1tRoC.mjs → text-DPrhma4x.mjs} +2 -2
- package/dist/text-DPrhma4x.mjs.map +1 -0
- package/dist/text.d.mts +1 -1
- package/dist/text.mjs +1 -1
- package/dist/theme-C8LkcoaK.mjs +61 -0
- package/dist/theme-C8LkcoaK.mjs.map +1 -0
- package/dist/theme-DVX8dvGG.mjs +1794 -0
- package/dist/theme-DVX8dvGG.mjs.map +1 -0
- package/dist/themes.d.mts +213 -73
- package/dist/themes.d.mts.map +1 -1
- package/dist/themes.mjs +1 -1
- package/dist/{tree-CArtDRec.d.mts → tree-CTvSpF9b.d.mts} +3 -3
- package/dist/{tree-CArtDRec.d.mts.map → tree-CTvSpF9b.d.mts.map} +1 -1
- package/dist/{types-C0EOLZDc.d.mts → types-C9ceMsbJ.d.mts} +137 -137
- package/dist/types-C9ceMsbJ.d.mts.map +1 -0
- package/dist/{widget-DtJU2-BJ.d.mts → widget-DlF32PRp.d.mts} +2 -2
- package/dist/{widget-DtJU2-BJ.d.mts.map → widget-DlF32PRp.d.mts.map} +1 -1
- package/dist/widgets/autocomplete.d.mts +1 -1
- package/dist/widgets/autocomplete.mjs +2 -2
- package/dist/widgets/box.d.mts +1 -1
- package/dist/widgets/box.mjs +1 -1
- package/dist/widgets/code.d.mts +4 -2
- package/dist/widgets/code.d.mts.map +1 -1
- package/dist/widgets/code.mjs +8 -7
- package/dist/widgets/code.mjs.map +1 -1
- package/dist/widgets/completions/actions.d.mts +1 -1
- package/dist/widgets/completions/files.d.mts +1 -1
- package/dist/widgets/completions/github.d.mts +1 -1
- package/dist/widgets/completions/index.d.mts +3 -3
- package/dist/widgets/diff.d.mts +2 -2
- package/dist/widgets/diff.d.mts.map +1 -1
- package/dist/widgets/diff.mjs +35 -12
- package/dist/widgets/diff.mjs.map +1 -1
- package/dist/widgets/divider.d.mts +3 -3
- package/dist/widgets/divider.mjs +1 -1
- package/dist/widgets/image.d.mts +1 -1
- package/dist/widgets/image.mjs +4 -4
- 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 +4 -4
- 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 +4 -4
- package/dist/widgets/progress.mjs.map +1 -1
- package/dist/widgets/select.d.mts +1 -1
- package/dist/widgets/show.d.mts +1 -1
- package/dist/widgets/spinner.d.mts +2 -2
- 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/widget.d.mts +1 -1
- package/package.json +5 -7
- package/assets/themes/dracula-soft.json +0 -119
- package/assets/themes/github-dark.json +0 -123
- package/assets/themes/github-light.json +0 -123
- package/dist/ansi-Clq0ozyA.mjs.map +0 -1
- package/dist/box-DLEcEvDH.mjs.map +0 -1
- package/dist/builder-DC9byAmK.mjs +0 -386
- package/dist/builder-DC9byAmK.mjs.map +0 -1
- package/dist/client-C2GXKfJ1.mjs.map +0 -1
- package/dist/client-bzdHIDL2.mjs +0 -1
- package/dist/ctx-k0wTqeql.mjs +0 -1
- package/dist/divider-l0-JPEIm.mjs.map +0 -1
- package/dist/image-Cm5T-uw-.mjs +0 -108
- package/dist/image-Cm5T-uw-.mjs.map +0 -1
- package/dist/input-D7fQEUdt.mjs.map +0 -1
- package/dist/inspect-DPLRum7L.d.mts.map +0 -1
- package/dist/log-Dy_QnPZF.mjs.map +0 -1
- package/dist/markdown-BGPa7UzD.mjs.map +0 -1
- package/dist/queries-B_lOwEiE.mjs.map +0 -1
- package/dist/queries-Cvalgu6P.d.mts.map +0 -1
- package/dist/registry-3hLzS4ks.mjs.map +0 -1
- package/dist/renderer-BSMOuiLM.mjs +0 -1
- package/dist/renderer-DesbRwjQ.mjs.map +0 -1
- package/dist/renderer-V6AGjbyf.mjs.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-BLz1tRoC.mjs.map +0 -1
- package/dist/theme.config-BKXX_noZ.mjs +0 -863
- package/dist/theme.config-BKXX_noZ.mjs.map +0 -1
- package/dist/types-C0EOLZDc.d.mts.map +0 -1
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as BrightAnsiColorName, d as ThemeKey, f as Theme, i as AnyStyle, n as AnsiColorName, o as Color } from "./types-C9ceMsbJ.mjs";
|
|
2
2
|
//#region src/style/builder.d.ts
|
|
3
3
|
type AttrName = "bold" | "dim" | "italic" | "underline" | "inverse" | "strikethrough";
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
type FgChainKey = AnsiColorName | BrightAnsiColorName | ChainSlot;
|
|
7
|
-
type BgChainKey = `bg${Capitalize<FgChainKey>}`;
|
|
8
|
-
type FgExtractKey = `fg${Capitalize<FgChainKey>}`;
|
|
9
|
-
type StyleBuilder = {
|
|
4
|
+
type ChainSlot<Ansi extends boolean = true> = Exclude<ThemeKey, "fg" | "bg" | AttrName> | (Ansi extends true ? AnsiColorName : never) | (Ansi extends true ? BrightAnsiColorName : never);
|
|
5
|
+
type StyleBuilder<Ansi extends boolean = false> = {
|
|
10
6
|
theme: Theme;
|
|
11
7
|
(text: string): string;
|
|
12
|
-
fg: (color: Color) => StyleBuilder
|
|
13
|
-
bg: (color: Color) => StyleBuilder
|
|
14
|
-
add: (slot?:
|
|
15
|
-
lighten: (n: number) => StyleBuilder
|
|
16
|
-
darken: (n: number) => StyleBuilder
|
|
17
|
-
} & { readonly [K in AttrName |
|
|
8
|
+
fg: (color: Color<Ansi>) => StyleBuilder<Ansi>;
|
|
9
|
+
bg: (color: Color<Ansi>) => StyleBuilder<Ansi>;
|
|
10
|
+
add: (slot?: ThemeKey | AnyStyle) => StyleBuilder<Ansi>;
|
|
11
|
+
lighten: (n: number) => StyleBuilder<Ansi>;
|
|
12
|
+
darken: (n: number) => StyleBuilder<Ansi>;
|
|
13
|
+
} & { readonly [K in AttrName | ChainSlot<Ansi> | `bg${Capitalize<ChainSlot<Ansi>>}` | `fg${Capitalize<ChainSlot<Ansi>>}`]: StyleBuilder<Ansi>; };
|
|
18
14
|
/**
|
|
19
15
|
* Build styled strings via chainable property access.
|
|
20
16
|
*
|
|
@@ -37,7 +33,7 @@ type StyleBuilder = {
|
|
|
37
33
|
*
|
|
38
34
|
* Calling an empty builder is a no-op: `styleBuilder()("x")` returns `"x"` unchanged.
|
|
39
35
|
*/
|
|
40
|
-
declare function styleBuilder(theme?: Theme | false): StyleBuilder
|
|
36
|
+
declare function styleBuilder<Ansi extends boolean = false>(theme?: Theme | false): StyleBuilder<Ansi>;
|
|
41
37
|
//#endregion
|
|
42
38
|
//#region src/style/inspect.d.ts
|
|
43
39
|
interface InspectOpts {
|
|
@@ -64,4 +60,4 @@ declare function inspectFormat(msg: unknown[], opts?: InspectOpts): string;
|
|
|
64
60
|
declare function inspect(value: unknown, opts?: InspectOpts): string;
|
|
65
61
|
//#endregion
|
|
66
62
|
export { StyleBuilder as a, isMarkdown as i, inspect as n, styleBuilder as o, inspectFormat as r, InspectOpts as t };
|
|
67
|
-
//# sourceMappingURL=inspect-
|
|
63
|
+
//# sourceMappingURL=inspect-B1uXxdKC.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect-B1uXxdKC.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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as styleBuilder } from "./builder-
|
|
1
|
+
import { t as styleBuilder } from "./builder-Chwtk0nQ.mjs";
|
|
2
2
|
import { hasAnsi } from "@zaly/shared/ansi";
|
|
3
3
|
import { hasColors } from "@zaly/shared/env";
|
|
4
4
|
import { formatWithOptions, inspect } from "node:util";
|
|
@@ -98,4 +98,4 @@ function inspect$1(value, opts = {}) {
|
|
|
98
98
|
//#endregion
|
|
99
99
|
export { inspectFormat as n, isMarkdown as r, inspect$1 as t };
|
|
100
100
|
|
|
101
|
-
//# sourceMappingURL=inspect-
|
|
101
|
+
//# sourceMappingURL=inspect-Cxzs-W0g.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-
|
|
1
|
+
{"version":3,"file":"inspect-Cxzs-W0g.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":";;;;;AAmBA,MAAM,QAAQ;AACd,MAAM,UAAU;AAGhB,MAAM,YAAY;;;;AAKlB,SAAgB,WAAW,GAAoB;CAC7C,OAAO,MAAM,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,KAAK,CAAC;AACxD;AAEA,MAAM,kBAAkB,MACtB,OAAO,MAAM,YAAY,UAAU,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;;;;;;;AAQ1D,SAAgB,cAAc,KAAgB,OAAoB,CAAC,GAAW;CAC5E,MAAM,OAAO,KAAK,aAAa,MAAM,IAAI,KAAK,MAAO,aAAa,QAAQ,EAAE,UAAU,CAAE;CACxF,OAAO;EAAE,QAAQ;EAAW,GAAG;CAAK;CAEpC,IAAI,MAAiB,CAAC;CAEtB,KAAK,IAAI,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,KAAK;EACzC,MAAM,OAAO,KAAK;EAClB,IAAI,eAAe,IAAI,GAAG,MAAM,CAAC,kBAAkB,MAAM,MAAM,GAAG,GAAG,CAAC;OACjE,IAAI,QAAQ,IAAI;CACvB;CAEA,IAAI,IAAI,SAAS,KAAK,eAAe,IAAI,EAAE,GAAG,OAAO,kBAAkB,MAAM,GAAG,GAAG;CACnF,OAAO,IAAI,KAAK,MAAO,OAAO,MAAM,WAAW,IAAIA,UAAQ,GAAG,IAAI,CAAE,CAAC,CAAC,KAAK,GAAG;AAChF;AAEA,SAAS,cAAc,OAAuB;CAC5C,OAAO,IAAI,KAAK,aAAa,SAAS;EACpC,UAAU;EACV,aAAa;CACf,CAAC,CAAC,CACC,OAAO,KAAK,CAAC,CACb,QAAQ,MAAM,GAAG;AACtB;AAEA,SAAS,aAAa,KAAa,GAAyB;CAC1D,IAAI,6BAA6B,KAAK,GAAG,GAAG,OAAO,EAAE,YAAY,GAAG;CACpE,OAAO,EAAE,aAAa,KAAK,UAAU,GAAG,CAAC;AAC3C;AAEA,SAAgBA,UAAQ,OAAgB,OAAoB,CAAC,GAAW;CACtE,OAAO;EAAE,QAAQ;EAAW,MAAM;EAAM,WAAW;EAAM,GAAG;CAAK;CACjE,MAAM,SAAS,KAAK,UAAU;CAC9B,MAAM,IAAI,KAAK,SAAU,KAAK,SAAS,aAAa,IAAK,aAAa,KAAK;CAC3E,MAAM,MAAM;EACV,KAAK,EAAE,gBAAgB,GAAG;EAC1B,KAAK,EAAE,gBAAgB,GAAG;EAC1B,KAAK,EAAE,cAAc,GAAG;EACxB,KAAK,EAAE,cAAc,GAAG;EACxB,KAAK,EAAE,cAAc,GAAG;EACxB,KAAK,EAAE,cAAc,GAAG;CAC1B;CACA,MAAM,uBAAO,IAAI,IAAI;CAErB,MAAM,YAAY,GAAY,UAA0B;EACtD,IAAI,KAAK,IAAI,CAAC,GAAG,OAAO,EAAE,KAAK,YAAY;EAC3C,IAAI,OAAO,MAAM,YAAY,MAAM,MAAM,KAAK,IAAI,CAAC;EACnD,IAAI,MAAM,MAAM,OAAO,EAAE,eAAe,MAAM;EAC9C,QAAQ,OAAO,GAAf;GACE,KAAK,WACH,OAAO,EAAE,cAAc,OAAO,CAAC,CAAC;GAElC,KAAK,UACH,OAAO,EAAE,aAAa,GAAG,EAAE,EAAE;GAE/B,KAAK,UACH,OAAO,EAAE,aAAa,cAAc,CAAC,CAAC;GAExC,KAAK,UACH,OAAO,EAAE,aAAa,KAAK,UAAU,CAAC,CAAC;GAEzC,KAAK,UACH,OAAO,EAAE,cAAc,OAAO,CAAC,CAAC;GAElC,KAAK,YACH,OAAO,EAAE,eAAe,YAAY,EAAE,OAAO,KAAK,EAAE,SAAS,GAAG,EAAE;GAEpE,KAAK,aACH,OAAO,EAAE,eAAe,WAAW;GAErC,KAAK,UAAU;IACb,IAAI,MAAM,QAAQ,CAAC,GAAG;KACpB,MAAM,QAAQ,EAAE,KAAK,SAAS,SAAS,MAAM,QAAQ,CAAC,CAAC;KACvD,OAAO,GAAG,IAAI,KAAK,GAAG,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,EAAE,GAAG,IAAI;IAC1D;IAEA,IAAI,EADkB,OAAO,eAAe,CAAC,MAAM,OAAO,YACtC;IACpB,MAAM,UAAU,OAAO,QAAQ,CAAC,CAAC,CAC9B,QACE,GAAG,SAAS,EAAG,QAAQ,KAAA,KAAa,CAAC,KAAK,aAAe,QAAQ,QAAQ,CAAC,KAAK,KAClF,CAAC,CACA,KAAK,CAAC,KAAK,SAAS,GAAG,aAAa,KAAK,CAAC,EAAE,IAAI,SAAS,KAAK,QAAQ,CAAC,GAAG;IAC7E,IAAI,QAAQ;KACV,MAAM,UAAU,IAAI,OAAO,SAAS,KAAK;KACzC,OAAO,GAAG,IAAI,KAAK,IAAI,UAAU,QAAQ,KAAK,GAAG,IAAI,KAAK,IAAI,SAAS,EAAE,IAAI,IAAI,OAAO,UAAU,QAAQ,EAAE,IAAI,IAAI;IACtH;IACA,OAAO,GAAG,IAAI,KAAK,GAAG,QAAQ,KAAK,GAAG,IAAI,KAAK,EAAE,EAAE,GAAG,IAAI;GAC5D;EACF;EACA,OAAOC,QAAY,GAAG;GAAE,QAAQ;GAAM,SAAS;EAAK,CAAC;CACvD;CACA,OAAO,SAAS,OAAO,CAAC;AAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { s as loadKittyGraphics } from "./kitty-JbCJC0iQ.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as box } from "./box-
|
|
2
|
-
import { n as text } from "./text-
|
|
3
|
-
import { n as markdown } from "./markdown-
|
|
1
|
+
import { n as box } from "./box-C_N_7ChP.mjs";
|
|
2
|
+
import { n as text } from "./text-DPrhma4x.mjs";
|
|
3
|
+
import { n as markdown } from "./markdown-D3ZtRn6C.mjs";
|
|
4
4
|
import { t as widget } from "./widget-BkMwhY2p.mjs";
|
|
5
5
|
import { stringWidth } from "@zaly/shared/ansi";
|
|
6
6
|
import { hasColors } from "@zaly/shared/env";
|
|
@@ -74,7 +74,7 @@ function renderPrefix(s, ctx) {
|
|
|
74
74
|
icon = icon === "" ? "" : `${icon}${" ".repeat(2 - stringWidth(icon))}`;
|
|
75
75
|
const color = s.color ?? base.color ?? "inherit";
|
|
76
76
|
let styledPrefix = "";
|
|
77
|
-
if (ls === "badge") styledPrefix = style.bg(color).
|
|
77
|
+
if (ls === "badge") styledPrefix = style.bg(color).bold(` ${s.level} `);
|
|
78
78
|
else if (ls === "icon") styledPrefix = style.fg(color)(icon);
|
|
79
79
|
else if (ls === "prompt") styledPrefix = style.fg(color).bold(`${icon} ${s.level}`);
|
|
80
80
|
else if (ls === "title") styledPrefix = style.fg(color).bold(`${s.level}:`);
|
|
@@ -127,4 +127,4 @@ const log = widget((state, ...children) => {
|
|
|
127
127
|
//#endregion
|
|
128
128
|
export { log as t };
|
|
129
129
|
|
|
130
|
-
//# sourceMappingURL=log-
|
|
130
|
+
//# sourceMappingURL=log-B4djzy2m.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-B4djzy2m.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,6 +1,6 @@
|
|
|
1
1
|
import { t as Node } from "./node-BZ7f6HzU.mjs";
|
|
2
|
-
import { n as inspectFormat, r as isMarkdown } from "./inspect-
|
|
3
|
-
import { t as log } from "./log-
|
|
2
|
+
import { n as inspectFormat, r as isMarkdown } from "./inspect-Cxzs-W0g.mjs";
|
|
3
|
+
import { t as log } from "./log-B4djzy2m.mjs";
|
|
4
4
|
//#region src/services/logger.ts
|
|
5
5
|
const ERR_LEVELS = /* @__PURE__ */ new Set([
|
|
6
6
|
"error",
|
|
@@ -68,4 +68,4 @@ var TuiReporter = class {
|
|
|
68
68
|
//#endregion
|
|
69
69
|
export { TuiReporter as t };
|
|
70
70
|
|
|
71
|
-
//# sourceMappingURL=logger-
|
|
71
|
+
//# sourceMappingURL=logger-CvJCITzP.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger-
|
|
1
|
+
{"version":3,"file":"logger-CvJCITzP.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,10 +1,11 @@
|
|
|
1
1
|
import { S as unwrap, r as createAsync, w as useContext, y as signal } from "./reactive-f7NpAi69.mjs";
|
|
2
2
|
import { t as Node } from "./node-BZ7f6HzU.mjs";
|
|
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
|
|
3
|
+
import { i as expandTabs, o as formatText, t as calcLayout } from "./text-BoJdKXLU.mjs";
|
|
4
|
+
import { r as textContent } from "./text-DPrhma4x.mjs";
|
|
5
|
+
import { t as RenderContext } from "./render-B7LfNM5K.mjs";
|
|
6
|
+
import { n as shikiWorker } from "./client-D7qz4TZt.mjs";
|
|
7
|
+
import { t as codeToAnsi } from "./shiki-CJauRusM.mjs";
|
|
8
|
+
import { t as shikiTheme } from "./theme-C8LkcoaK.mjs";
|
|
8
9
|
import { hasColors } from "@zaly/shared/env";
|
|
9
10
|
//#region src/widgets/markdown.ts
|
|
10
11
|
var Markdown = class extends Node {
|
|
@@ -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-YHbR7JZ4.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) {
|
|
@@ -121,4 +122,4 @@ function markdown(first, style) {
|
|
|
121
122
|
//#endregion
|
|
122
123
|
export { markdown as n, Markdown as t };
|
|
123
124
|
|
|
124
|
-
//# sourceMappingURL=markdown-
|
|
125
|
+
//# sourceMappingURL=markdown-D3ZtRn6C.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-D3ZtRn6C.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,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { I as RenderCtx, h as Node } from "./queries-C75-wG1B.mjs";
|
|
2
2
|
import { n as MdOptions, r as RenderMarkdown } from "./types-D3jk1rtk.mjs";
|
|
3
3
|
//#region src/markdown/renderer.d.ts
|
|
4
4
|
export type MarkdownOptions = MdOptions & {
|
package/dist/markdown.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;;;;;;
|
|
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-aAtkFgll.mjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as mathImage } from "./math-Dd7a1irv.mjs";
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { hash } from "@zaly/shared";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "pathe";
|
|
4
|
+
import { tmpdir, userInfo } from "node:os";
|
|
5
|
+
import { mkdir, rename, writeFile } from "node:fs/promises";
|
|
6
|
+
/** Protect math before Markdown consumes its escapes. Code and incomplete spans stay intact. */
|
|
7
|
+
function replaceMath(source, replace) {
|
|
8
|
+
if (!/[$\\]|^ {0,3}(?:`{3,}|~{3,})\s*math\s*$/m.test(source)) return source;
|
|
9
|
+
let out = "";
|
|
10
|
+
let i = 0;
|
|
11
|
+
const escaped = (pos) => {
|
|
12
|
+
let count = 0;
|
|
13
|
+
while (pos > 0 && source[--pos] === "\\") count++;
|
|
14
|
+
return count % 2 === 1;
|
|
15
|
+
};
|
|
16
|
+
while (i < source.length) {
|
|
17
|
+
if (i === 0 || source[i - 1] === "\n") {
|
|
18
|
+
const lineEnd = source.indexOf("\n", i);
|
|
19
|
+
const line = source.slice(i, lineEnd === -1 ? source.length : lineEnd);
|
|
20
|
+
const fence = /^ {0,3}(`{3,}|~{3,})([^\n]*)$/.exec(line);
|
|
21
|
+
if (fence) {
|
|
22
|
+
const close = new RegExp(`^ {0,3}${fence[1][0]}{${fence[1].length},}[ \\t]*$`, "gm");
|
|
23
|
+
close.lastIndex = lineEnd === -1 ? source.length : lineEnd + 1;
|
|
24
|
+
const end = close.exec(source);
|
|
25
|
+
const stop = end ? end.index + end[0].length : source.length;
|
|
26
|
+
const raw = source.slice(i, stop);
|
|
27
|
+
out += end && fence[2].trim() === "math" ? replace({
|
|
28
|
+
display: true,
|
|
29
|
+
source: raw,
|
|
30
|
+
tex: source.slice(lineEnd + 1, end.index).trim()
|
|
31
|
+
}) : raw;
|
|
32
|
+
i = stop;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (/^(?: {4}|\t)|^ {0,3}\[[^\]]+\]:/.test(line)) {
|
|
36
|
+
out += line;
|
|
37
|
+
i += line.length;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (source[i] === "<") {
|
|
42
|
+
const html = /^(?:<(pre|code|script|style)\b[^>]*>[\s\S]*?<\/\1\s*>|<[^>\n]*>)/i.exec(source.slice(i));
|
|
43
|
+
if (html) {
|
|
44
|
+
out += html[0];
|
|
45
|
+
i += html[0].length;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (source.startsWith("![", i)) {
|
|
50
|
+
let end = i + 2;
|
|
51
|
+
let depth = 1;
|
|
52
|
+
for (; end < source.length && depth > 0; end++) {
|
|
53
|
+
if (escaped(end)) continue;
|
|
54
|
+
if (source[end] === "[") depth++;
|
|
55
|
+
else if (source[end] === "]") depth--;
|
|
56
|
+
}
|
|
57
|
+
out += source.slice(i, end);
|
|
58
|
+
i = end;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (source[i] === "(" && source[i - 1] === "]") {
|
|
62
|
+
let end = i + 1;
|
|
63
|
+
let depth = 1;
|
|
64
|
+
for (; end < source.length && depth > 0; end++) {
|
|
65
|
+
if (escaped(end)) continue;
|
|
66
|
+
if (source[end] === "(") depth++;
|
|
67
|
+
else if (source[end] === ")") depth--;
|
|
68
|
+
}
|
|
69
|
+
out += source.slice(i, end);
|
|
70
|
+
i = end;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
let open;
|
|
74
|
+
let close = "";
|
|
75
|
+
let display = false;
|
|
76
|
+
if (source.startsWith(String.raw`\[`, i)) {
|
|
77
|
+
open = String.raw`\[`;
|
|
78
|
+
close = String.raw`\]`;
|
|
79
|
+
display = true;
|
|
80
|
+
} else if (source.startsWith(String.raw`\(`, i)) {
|
|
81
|
+
open = String.raw`\(`;
|
|
82
|
+
close = String.raw`\)`;
|
|
83
|
+
} else if (source.startsWith("$$", i)) {
|
|
84
|
+
open = "$$";
|
|
85
|
+
close = "$$";
|
|
86
|
+
display = true;
|
|
87
|
+
} else if (source.startsWith("$`", i)) {
|
|
88
|
+
open = "$`";
|
|
89
|
+
close = "`$";
|
|
90
|
+
} else if (source[i] === "$" && /\S/.test(source[i + 1] ?? "")) {
|
|
91
|
+
open = "$";
|
|
92
|
+
close = "$";
|
|
93
|
+
}
|
|
94
|
+
if (open) {
|
|
95
|
+
let end = i + open.length;
|
|
96
|
+
for (; end < source.length; end++) {
|
|
97
|
+
if (!display && source[end] === "\n") break;
|
|
98
|
+
if (!source.startsWith(close, end) || escaped(end)) continue;
|
|
99
|
+
if (close === "$" && (/\s/.test(source[end - 1]) || /[\d$]/.test(source[end + 1] ?? ""))) continue;
|
|
100
|
+
const stop = end + close.length;
|
|
101
|
+
const tex = source.slice(i + open.length, end);
|
|
102
|
+
if (!tex.trim()) break;
|
|
103
|
+
out += replace({
|
|
104
|
+
display,
|
|
105
|
+
source: source.slice(i, stop),
|
|
106
|
+
tex
|
|
107
|
+
});
|
|
108
|
+
i = stop;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
if (i === end + close.length) continue;
|
|
112
|
+
out += source.slice(i, end);
|
|
113
|
+
i = end;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (source[i] === "`") {
|
|
117
|
+
const ticks = /^`+/.exec(source.slice(i))[0];
|
|
118
|
+
let end = source.indexOf(ticks, i + ticks.length);
|
|
119
|
+
while (end >= 0 && (source[end - 1] === "`" || source[end + ticks.length] === "`")) end = source.indexOf(ticks, end + ticks.length);
|
|
120
|
+
const stop = end < 0 ? source.length : end + ticks.length;
|
|
121
|
+
out += source.slice(i, stop);
|
|
122
|
+
i = stop;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (source[i] === "\\" && i + 1 < source.length) {
|
|
126
|
+
out += source.slice(i, i + 2);
|
|
127
|
+
i += 2;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
out += source[i++];
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
async function createTypesetter() {
|
|
135
|
+
const [{ mathjax }, { TeX }, { SVG }, { liteAdaptor }, { RegisterHTMLHandler }] = await Promise.all([
|
|
136
|
+
import("@mathjax/src/js/mathjax.js"),
|
|
137
|
+
import("@mathjax/src/js/input/tex.js"),
|
|
138
|
+
import("@mathjax/src/js/output/svg.js"),
|
|
139
|
+
import("@mathjax/src/js/adaptors/liteAdaptor.js"),
|
|
140
|
+
import("@mathjax/src/js/handlers/html.js"),
|
|
141
|
+
import("@mathjax/src/js/input/tex/ams/AmsConfiguration.js"),
|
|
142
|
+
import("@mathjax/src/js/util/asyncLoad/esm.js")
|
|
143
|
+
]);
|
|
144
|
+
const adaptor = liteAdaptor();
|
|
145
|
+
RegisterHTMLHandler(adaptor);
|
|
146
|
+
const doc = mathjax.document("", {
|
|
147
|
+
InputJax: new TeX({
|
|
148
|
+
formatError: (_jax, error) => {
|
|
149
|
+
throw error;
|
|
150
|
+
},
|
|
151
|
+
maxBuffer: 2e4,
|
|
152
|
+
packages: ["base", "ams"]
|
|
153
|
+
}),
|
|
154
|
+
OutputJax: new SVG({
|
|
155
|
+
fontCache: "none",
|
|
156
|
+
linebreaks: { inline: false }
|
|
157
|
+
})
|
|
158
|
+
});
|
|
159
|
+
return async (math, color) => {
|
|
160
|
+
const node = await mathjax.handleRetriesFor(() => doc.convert(math.tex, { display: math.display }));
|
|
161
|
+
const svg = adaptor.firstChild(node);
|
|
162
|
+
if (!("attributes" in svg) || svg.kind !== "svg") throw new Error("MathJax did not produce SVG");
|
|
163
|
+
for (const dimension of ["width", "height"]) {
|
|
164
|
+
const ex = Number.parseFloat(adaptor.getAttribute(svg, dimension));
|
|
165
|
+
adaptor.setAttribute(svg, dimension, String(Math.max(1, Math.ceil(ex * 24))));
|
|
166
|
+
}
|
|
167
|
+
const xml = adaptor.serializeXML(svg);
|
|
168
|
+
if (xml.includes("data-mml-node=\"merror\"")) throw new Error("Invalid math expression");
|
|
169
|
+
return xml.replaceAll("currentColor", color);
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
let typesetter;
|
|
173
|
+
const files = /* @__PURE__ */ new Map();
|
|
174
|
+
/** Theme-dependent, self-contained SVG paths shared by repeated occurrences and re-renders. */
|
|
175
|
+
function mathImage(math, color) {
|
|
176
|
+
if (math.tex.length > 2e4) return Promise.reject(/* @__PURE__ */ new Error("Math expression is too large"));
|
|
177
|
+
const key = hash(JSON.stringify([
|
|
178
|
+
"svg-v3",
|
|
179
|
+
math.tex,
|
|
180
|
+
math.display,
|
|
181
|
+
color
|
|
182
|
+
]));
|
|
183
|
+
const cached = files.get(key);
|
|
184
|
+
if (cached) return cached;
|
|
185
|
+
const pending = (async () => {
|
|
186
|
+
const dir = join(tmpdir(), `zaly-math-${userInfo().uid}`);
|
|
187
|
+
const path = join(dir, `${key}.svg`);
|
|
188
|
+
if (existsSync(path)) return path;
|
|
189
|
+
const svg = await (await (typesetter ??= createTypesetter()))(math, color);
|
|
190
|
+
await mkdir(dir, {
|
|
191
|
+
mode: 448,
|
|
192
|
+
recursive: true
|
|
193
|
+
});
|
|
194
|
+
const temporary = join(dir, `${key}-${process.pid}-${Math.random().toString(36).slice(2)}.svg`);
|
|
195
|
+
await writeFile(temporary, svg, { mode: 384 });
|
|
196
|
+
await rename(temporary, path);
|
|
197
|
+
return path;
|
|
198
|
+
})();
|
|
199
|
+
if (files.size >= 128) files.delete(files.keys().next().value);
|
|
200
|
+
files.set(key, pending);
|
|
201
|
+
return pending;
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
204
|
+
export { replaceMath as n, mathImage as t };
|
|
205
|
+
|
|
206
|
+
//# sourceMappingURL=math-Dd7a1irv.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"math-Dd7a1irv.mjs","names":[],"sources":["../src/markdown/math.ts"],"sourcesContent":["import { hash } from \"@zaly/shared\"\nimport { existsSync } from \"node:fs\"\nimport { mkdir, rename, writeFile } from \"node:fs/promises\"\nimport { tmpdir, userInfo } from \"node:os\"\nimport { join } from \"pathe\"\n\n// Rasterize at three times an 8px cell width, independently of terminal placement size.\nexport const MATH_PIXELS_PER_CELL = 24\n\nexport interface MathExpression {\n tex: string\n display: boolean\n source: string\n}\n\n/** Protect math before Markdown consumes its escapes. Code and incomplete spans stay intact. */\nexport function replaceMath(source: string, replace: (math: MathExpression) => string): string {\n if (!/[$\\\\]|^ {0,3}(?:`{3,}|~{3,})\\s*math\\s*$/m.test(source)) return source\n let out = \"\"\n let i = 0\n const escaped = (pos: number) => {\n let count = 0\n while (pos > 0 && source[--pos] === \"\\\\\") count++\n return count % 2 === 1\n }\n while (i < source.length) {\n if (i === 0 || source[i - 1] === \"\\n\") {\n const lineEnd = source.indexOf(\"\\n\", i)\n const line = source.slice(i, lineEnd === -1 ? source.length : lineEnd)\n const fence = /^ {0,3}(`{3,}|~{3,})([^\\n]*)$/.exec(line)\n if (fence) {\n const close = new RegExp(`^ {0,3}${fence[1][0]}{${fence[1].length},}[ \\\\t]*$`, \"gm\")\n close.lastIndex = lineEnd === -1 ? source.length : lineEnd + 1\n const end = close.exec(source)\n const stop = end ? end.index + end[0].length : source.length\n const raw = source.slice(i, stop)\n out +=\n end && fence[2].trim() === \"math\"\n ? replace({\n display: true,\n source: raw,\n tex: source.slice(lineEnd + 1, end.index).trim(),\n })\n : raw\n i = stop\n continue\n }\n if (/^(?: {4}|\\t)|^ {0,3}\\[[^\\]]+\\]:/.test(line)) {\n out += line\n i += line.length\n continue\n }\n }\n // Existing destinations and raw HTML must not become math or acquire image markers.\n if (source[i] === \"<\") {\n const html = /^(?:<(pre|code|script|style)\\b[^>]*>[\\s\\S]*?<\\/\\1\\s*>|<[^>\\n]*>)/i.exec(\n source.slice(i)\n )\n if (html) {\n out += html[0]\n i += html[0].length\n continue\n }\n }\n if (source.startsWith(\"![\", i)) {\n let end = i + 2\n let depth = 1\n for (; end < source.length && depth > 0; end++) {\n if (escaped(end)) continue\n if (source[end] === \"[\") depth++\n else if (source[end] === \"]\") depth--\n }\n out += source.slice(i, end)\n i = end\n continue\n }\n if (source[i] === \"(\" && source[i - 1] === \"]\") {\n let end = i + 1\n let depth = 1\n for (; end < source.length && depth > 0; end++) {\n if (escaped(end)) continue\n if (source[end] === \"(\") depth++\n else if (source[end] === \")\") depth--\n }\n out += source.slice(i, end)\n i = end\n continue\n }\n let open: string | undefined\n let close = \"\"\n let display = false\n if (source.startsWith(String.raw`\\[`, i)) {\n open = String.raw`\\[`\n close = String.raw`\\]`\n display = true\n } else if (source.startsWith(String.raw`\\(`, i)) {\n open = String.raw`\\(`\n close = String.raw`\\)`\n } else if (source.startsWith(\"$$\", i)) {\n open = \"$$\"\n close = \"$$\"\n display = true\n } else if (source.startsWith(\"$`\", i)) {\n open = \"$`\"\n close = \"`$\"\n } else if (source[i] === \"$\" && /\\S/.test(source[i + 1] ?? \"\")) {\n open = \"$\"\n close = \"$\"\n }\n if (open) {\n let end = i + open.length\n for (; end < source.length; end++) {\n if (!display && source[end] === \"\\n\") break\n if (!source.startsWith(close, end) || escaped(end)) continue\n if (close === \"$\" && (/\\s/.test(source[end - 1]) || /[\\d$]/.test(source[end + 1] ?? \"\")))\n continue\n const stop = end + close.length\n const tex = source.slice(i + open.length, end)\n if (!tex.trim()) break\n out += replace({ display, source: source.slice(i, stop), tex })\n i = stop\n break\n }\n if (i === end + close.length) continue\n // Keep incomplete spans intact, without rescanning every nested opener while streaming.\n out += source.slice(i, end)\n i = end\n continue\n }\n if (source[i] === \"`\") {\n const ticks = /^`+/.exec(source.slice(i))![0]\n let end = source.indexOf(ticks, i + ticks.length)\n while (end >= 0 && (source[end - 1] === \"`\" || source[end + ticks.length] === \"`\"))\n end = source.indexOf(ticks, end + ticks.length)\n const stop = end < 0 ? source.length : end + ticks.length\n out += source.slice(i, stop)\n i = stop\n continue\n }\n if (source[i] === \"\\\\\" && i + 1 < source.length) {\n out += source.slice(i, i + 2)\n i += 2\n continue\n }\n out += source[i++]\n }\n return out\n}\n\nasync function createTypesetter() {\n const [{ mathjax }, { TeX }, { SVG }, { liteAdaptor }, { RegisterHTMLHandler }] =\n await Promise.all([\n import(\"@mathjax/src/js/mathjax.js\"),\n import(\"@mathjax/src/js/input/tex.js\"),\n import(\"@mathjax/src/js/output/svg.js\"),\n import(\"@mathjax/src/js/adaptors/liteAdaptor.js\"),\n import(\"@mathjax/src/js/handlers/html.js\"),\n import(\"@mathjax/src/js/input/tex/ams/AmsConfiguration.js\"),\n import(\"@mathjax/src/js/util/asyncLoad/esm.js\"),\n ])\n const adaptor = liteAdaptor()\n // oxlint-disable-next-line new-cap -- MathJax registration API.\n RegisterHTMLHandler(adaptor)\n const doc = mathjax.document(\"\", {\n InputJax: new TeX({\n formatError: (_jax: unknown, error: Error) => {\n throw error\n },\n maxBuffer: 20_000,\n packages: [\"base\", \"ams\"],\n }),\n OutputJax: new SVG({ fontCache: \"none\", linebreaks: { inline: false } }),\n })\n return async (math: MathExpression, color: string) => {\n const node = await mathjax.handleRetriesFor(() =>\n doc.convert(math.tex, { display: math.display })\n )\n const svg = adaptor.firstChild(node)\n if (!(\"attributes\" in svg) || svg.kind !== \"svg\") throw new Error(\"MathJax did not produce SVG\")\n // Explicit pixel dimensions work with both image-meta and sharp, unlike MathJax's ex units.\n for (const dimension of [\"width\", \"height\"]) {\n const ex = Number.parseFloat(adaptor.getAttribute(svg, dimension))\n adaptor.setAttribute(\n svg,\n dimension,\n String(Math.max(1, Math.ceil(ex * MATH_PIXELS_PER_CELL)))\n )\n }\n const xml = adaptor.serializeXML(svg)\n if (xml.includes('data-mml-node=\"merror\"')) throw new Error(\"Invalid math expression\")\n return xml.replaceAll(\"currentColor\", color)\n }\n}\n\nlet typesetter: ReturnType<typeof createTypesetter> | undefined\nconst files = new Map<string, Promise<string>>()\n\n/** Theme-dependent, self-contained SVG paths shared by repeated occurrences and re-renders. */\nexport function mathImage(math: MathExpression, color: string): Promise<string> {\n if (math.tex.length > 20_000) return Promise.reject(new Error(\"Math expression is too large\"))\n const key = hash(JSON.stringify([\"svg-v3\", math.tex, math.display, color]))\n const cached = files.get(key)\n if (cached) return cached\n const pending = (async () => {\n const dir = join(tmpdir(), `zaly-math-${userInfo().uid}`)\n const path = join(dir, `${key}.svg`)\n if (existsSync(path)) return path\n const render = await (typesetter ??= createTypesetter())\n const svg = await render(math, color)\n await mkdir(dir, { mode: 0o700, recursive: true })\n const temporary = join(dir, `${key}-${process.pid}-${Math.random().toString(36).slice(2)}.svg`)\n await writeFile(temporary, svg, { mode: 0o600 })\n await rename(temporary, path)\n return path\n })()\n if (files.size >= 128) files.delete(files.keys().next().value!)\n files.set(key, pending)\n return pending\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { i as toHex, r as parseHex } from "./color-DBMQLv4Y.mjs";
|
|
2
|
+
import { clamp } from "@zaly/shared";
|
|
3
|
+
//#region src/style/oklch.ts
|
|
4
|
+
const cache = /* @__PURE__ */ new Map();
|
|
5
|
+
function srgbToLinear(c) {
|
|
6
|
+
return c <= .04045 ? c / 12.92 : ((c + .055) / 1.055) ** 2.4;
|
|
7
|
+
}
|
|
8
|
+
function linearToSrgb(c) {
|
|
9
|
+
return c <= .0031308 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - .055;
|
|
10
|
+
}
|
|
11
|
+
function hexToOklch(hex) {
|
|
12
|
+
const [r8, g8, b8] = parseHex(hex);
|
|
13
|
+
const r = srgbToLinear(r8 / 255);
|
|
14
|
+
const g = srgbToLinear(g8 / 255);
|
|
15
|
+
const b = srgbToLinear(b8 / 255);
|
|
16
|
+
const l = .4122214708 * r + .5363325363 * g + .0514459929 * b;
|
|
17
|
+
const m = .2119034982 * r + .6806995451 * g + .1073969566 * b;
|
|
18
|
+
const s = .0883024619 * r + .2817188376 * g + .6299787005 * b;
|
|
19
|
+
const lp = Math.cbrt(l);
|
|
20
|
+
const mp = Math.cbrt(m);
|
|
21
|
+
const sp = Math.cbrt(s);
|
|
22
|
+
const L = .2104542553 * lp + .793617785 * mp - .0040720468 * sp;
|
|
23
|
+
const a = 1.9779984951 * lp - 2.428592205 * mp + .4505937099 * sp;
|
|
24
|
+
const b2 = .0259040371 * lp + .7827717662 * mp - .808675766 * sp;
|
|
25
|
+
return {
|
|
26
|
+
C: Math.hypot(a, b2),
|
|
27
|
+
L,
|
|
28
|
+
h: (Math.atan2(b2, a) * 180 / Math.PI + 360) % 360
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Convert OKLCH → linear sRGB (unclamped — callers can test for gamut). */
|
|
32
|
+
function oklchToLinearRgb({ L, C, h }) {
|
|
33
|
+
const hr = h * Math.PI / 180;
|
|
34
|
+
const a = C * Math.cos(hr);
|
|
35
|
+
const b2 = C * Math.sin(hr);
|
|
36
|
+
const lp = L + .3963377774 * a + .2158037573 * b2;
|
|
37
|
+
const mp = L - .1055613458 * a - .0638541728 * b2;
|
|
38
|
+
const sp = L - .0894841775 * a - 1.291485548 * b2;
|
|
39
|
+
const l = lp ** 3;
|
|
40
|
+
const m = mp ** 3;
|
|
41
|
+
const s = sp ** 3;
|
|
42
|
+
return [
|
|
43
|
+
4.0767416621 * l - 3.3077115913 * m + .2309699292 * s,
|
|
44
|
+
-1.2684380046 * l + 2.6097574011 * m - .3413193965 * s,
|
|
45
|
+
-.0041960863 * l - .7034186147 * m + 1.707614701 * s
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
function inGamut([r, g, b], eps = .001) {
|
|
49
|
+
return r >= -eps && r <= 1 + eps && g >= -eps && g <= 1 + eps && b >= -eps && b <= 1 + eps;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Convert OKLCH → hex, reducing chroma via binary search when the
|
|
53
|
+
* straightforward conversion falls outside sRGB. The search keeps `L`
|
|
54
|
+
* and `h` fixed and shrinks `C` toward the achromatic axis until the
|
|
55
|
+
* color fits, which is the CSS Color Level 4-recommended behavior.
|
|
56
|
+
*/
|
|
57
|
+
function oklchToHex(oklch) {
|
|
58
|
+
let rgb = oklchToLinearRgb(oklch);
|
|
59
|
+
if (!inGamut(rgb)) {
|
|
60
|
+
let lo = 0;
|
|
61
|
+
let hi = oklch.C;
|
|
62
|
+
for (let i = 0; i < 24; i++) {
|
|
63
|
+
const mid = (lo + hi) / 2;
|
|
64
|
+
if (inGamut(oklchToLinearRgb({
|
|
65
|
+
...oklch,
|
|
66
|
+
C: mid
|
|
67
|
+
}))) lo = mid;
|
|
68
|
+
else hi = mid;
|
|
69
|
+
}
|
|
70
|
+
rgb = oklchToLinearRgb({
|
|
71
|
+
...oklch,
|
|
72
|
+
C: lo
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const [r, g, b] = rgb.map((c) => linearToSrgb(Math.max(0, Math.min(1, c))));
|
|
76
|
+
return toHex(r * 255, g * 255, b * 255);
|
|
77
|
+
}
|
|
78
|
+
function shiftLightness(hex, delta) {
|
|
79
|
+
const key = `${hex}:${delta}`;
|
|
80
|
+
let ret = cache.get(key);
|
|
81
|
+
if (ret) return ret;
|
|
82
|
+
const okl = hexToOklch(hex);
|
|
83
|
+
const L = clamp(okl.L + delta, 0, 1);
|
|
84
|
+
const margin = Math.min(L, 1 - L);
|
|
85
|
+
const C = okl.C * Math.min(1, margin / .1);
|
|
86
|
+
cache.set(key, ret = oklchToHex({
|
|
87
|
+
...okl,
|
|
88
|
+
C,
|
|
89
|
+
L
|
|
90
|
+
}));
|
|
91
|
+
return ret;
|
|
92
|
+
}
|
|
93
|
+
function isDark(hex) {
|
|
94
|
+
return hexToOklch(hex).L < .6;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
export { shiftLightness as n, isDark as t };
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=oklch-Bsh5swbC.mjs.map
|