@zaly/tui 0.0.12 → 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 +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-Dc4D4uSf.d.mts → actions--ODlgCQ5.d.mts} +4 -4
- package/dist/{actions-Dc4D4uSf.d.mts.map → actions--ODlgCQ5.d.mts.map} +1 -1
- package/dist/{ansi-DZlXaItJ.mjs → ansi-CMv71xVr.mjs} +3 -31
- package/dist/ansi-CMv71xVr.mjs.map +1 -0
- package/dist/ansi.d.mts +1 -1
- package/dist/ansi.mjs +1 -1
- package/dist/{autocomplete-StW1QJZJ.d.mts → autocomplete-CD30kSe_.d.mts} +4 -4
- package/dist/{autocomplete-StW1QJZJ.d.mts.map → autocomplete-CD30kSe_.d.mts.map} +1 -1
- package/dist/{box-BkP4MF82.mjs → box-C_N_7ChP.mjs} +2 -2
- package/dist/{box-BkP4MF82.mjs.map → box-C_N_7ChP.mjs.map} +1 -1
- package/dist/builder-Chwtk0nQ.mjs +196 -0
- package/dist/builder-Chwtk0nQ.mjs.map +1 -0
- package/dist/{callbacks-BwWTCqPJ.mjs → callbacks-DLecWn7G.mjs} +4 -4
- package/dist/{callbacks-BwWTCqPJ.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-B7BmPUCD.mjs → ctx-BaQ2hP5u.mjs} +3 -3
- package/dist/{ctx-B7BmPUCD.mjs.map → ctx-BaQ2hP5u.mjs.map} +1 -1
- package/dist/ctx-CndlTp1T.mjs +1 -0
- package/dist/{divider-TSx9NhI_.mjs → divider-BlNNN2OS.mjs} +2 -2
- package/dist/{divider-TSx9NhI_.mjs.map → divider-BlNNN2OS.mjs.map} +1 -1
- package/dist/{files-7DUYSeNc.d.mts → files-B_5HDBPp.d.mts} +3 -3
- package/dist/{files-7DUYSeNc.d.mts.map → files-B_5HDBPp.d.mts.map} +1 -1
- package/dist/{github-C1KfXk98.d.mts → github-CyRwUQ3y.d.mts} +3 -3
- package/dist/{github-C1KfXk98.d.mts.map → github-CyRwUQ3y.d.mts.map} +1 -1
- package/dist/{image-VaT7AN-S.d.mts → image-BLls2F4t.d.mts} +2 -2
- package/dist/{image-VaT7AN-S.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-BGTTujDN.mjs → input-ET2YEMcl.mjs} +2 -2
- package/dist/{input-BGTTujDN.mjs.map → input-ET2YEMcl.mjs.map} +1 -1
- package/dist/{input-BAYux7qo.d.mts → input-NuD8TH8N.d.mts} +3 -3
- package/dist/{input-BAYux7qo.d.mts.map → input-NuD8TH8N.d.mts.map} +1 -1
- package/dist/{inspect-CfNydMgO.d.mts → inspect-B1uXxdKC.d.mts} +2 -2
- package/dist/{inspect-CfNydMgO.d.mts.map → inspect-B1uXxdKC.d.mts.map} +1 -1
- package/dist/{inspect-jG_W4njH.mjs → inspect-Cxzs-W0g.mjs} +2 -2
- package/dist/{inspect-jG_W4njH.mjs.map → inspect-Cxzs-W0g.mjs.map} +1 -1
- package/dist/kitty-DKQYsQfH.mjs +1 -0
- package/dist/{log-ByKlM4iI.mjs → log-B4djzy2m.mjs} +4 -4
- package/dist/{log-ByKlM4iI.mjs.map → log-B4djzy2m.mjs.map} +1 -1
- package/dist/{logger-DSQb0sLP.mjs → logger-CvJCITzP.mjs} +3 -3
- package/dist/{logger-DSQb0sLP.mjs.map → logger-CvJCITzP.mjs.map} +1 -1
- package/dist/{markdown-CwRmWuU6.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-BnvOKtGT.mjs → overlay-LvOjG7kn.mjs} +2 -2
- package/dist/{overlay-BnvOKtGT.mjs.map → overlay-LvOjG7kn.mjs.map} +1 -1
- package/dist/{picker-DQs_IW77.d.mts → picker-B-OxKKnD.d.mts} +5 -5
- package/dist/{picker-DQs_IW77.d.mts.map → picker-B-OxKKnD.d.mts.map} +1 -1
- package/dist/{picker-Dh5IUrTk.mjs → picker-f6xjgACX.mjs} +2 -2
- package/dist/{picker-Dh5IUrTk.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-BDX8mcl5.d.mts → queries-C75-wG1B.d.mts} +19 -4
- package/dist/{queries-BDX8mcl5.d.mts.map → queries-C75-wG1B.d.mts.map} +1 -1
- package/dist/{registry-D-suU3g0.mjs → registry-DUWpSPoo.mjs} +202 -57
- package/dist/registry-DUWpSPoo.mjs.map +1 -0
- package/dist/{render-DEIUNLkh.mjs → render-B7LfNM5K.mjs} +2 -2
- package/dist/{render-DEIUNLkh.mjs.map → render-B7LfNM5K.mjs.map} +1 -1
- package/dist/{renderer-zDNlAovy.mjs → renderer-BLsd-wrG.mjs} +110 -14
- package/dist/renderer-BLsd-wrG.mjs.map +1 -0
- package/dist/renderer-YHbR7JZ4.mjs +1 -0
- package/dist/{renderer-MQue4Da5.mjs → renderer-aAtkFgll.mjs} +8 -7
- package/dist/renderer-aAtkFgll.mjs.map +1 -0
- package/dist/{select-J2KtwxyK.d.mts → select-BKE5LzdN.d.mts} +3 -3
- package/dist/{select-J2KtwxyK.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-CkQ7Irmt.mjs → text-BoJdKXLU.mjs} +2 -2
- package/dist/{text-CkQ7Irmt.mjs.map → text-BoJdKXLU.mjs.map} +1 -1
- package/dist/{text-CCYs9RB2.d.mts → text-CmxbA8lk.d.mts} +3 -3
- package/dist/{text-CCYs9RB2.d.mts.map → text-CmxbA8lk.d.mts.map} +1 -1
- package/dist/{text-XvPfweeg.mjs → text-DPrhma4x.mjs} +2 -2
- package/dist/{text-XvPfweeg.mjs.map → text-DPrhma4x.mjs.map} +1 -1
- 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-DJl5W_B7.d.mts → tree-CTvSpF9b.d.mts} +3 -3
- package/dist/{tree-DJl5W_B7.d.mts.map → tree-CTvSpF9b.d.mts.map} +1 -1
- package/dist/{types-D2EYlzmK.d.mts → types-C9ceMsbJ.d.mts} +136 -128
- package/dist/types-C9ceMsbJ.d.mts.map +1 -0
- package/dist/{widget-DPqBbB57.d.mts → widget-DlF32PRp.d.mts} +2 -2
- package/dist/{widget-DPqBbB57.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 +2 -2
- 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 +2 -2
- 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 -100
- package/assets/themes/github-dark.json +0 -104
- package/assets/themes/github-light.json +0 -104
- package/dist/ansi-DZlXaItJ.mjs.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/image-Cm5T-uw-.mjs +0 -108
- package/dist/image-Cm5T-uw-.mjs.map +0 -1
- package/dist/markdown-CwRmWuU6.mjs.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/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/theme.config-B3Yx--C2.mjs +0 -855
- package/dist/theme.config-B3Yx--C2.mjs.map +0 -1
- package/dist/types-D2EYlzmK.d.mts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.mjs","names":[],"sources":["../../src/widgets/diff.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Accessor, Reactive } from \"../core/reactive.ts\"\nimport type { Layout, State } from \"../core/state.ts\"\nimport type { WrapMode } from \"../layout/text.ts\"\n\nimport { splitAnsi, stringWidth, wrapAnsi } from \"@zaly/shared/ansi\"\nimport { basename, extname } from \"pathe\"\n// oxlint-disable no-nested-ternary\n// oxlint-disable typescript/no-unnecessary-condition\nimport { Node } from \"../core/node.ts\"\nimport { createAsync, memo, unwrap, useContext } from \"../core/reactive.ts\"\nimport { RenderContext } from \"../core/render.ts\"\nimport { calcLayout, countLines } from \"../layout/text.ts\"\nimport { codeToAnsi } from \"../shiki/shiki.ts\"\n\nexport interface DiffState {\n /** Pre-state file content. Plain string or reactive accessor —\n * pass a signal to live-update the diff as either side changes. */\n original: Reactive<string>\n /** Post-state file content. The widget runs `diffLines` between\n * `original` and `modified` and renders the resulting hunks. */\n modified: Reactive<string>\n /** Optional file path. Drives the default `lang` (extension or\n * basename — shiki recognises both `.ts` and `Dockerfile`-style\n * names) and `title` when those aren't set explicitly. */\n path?: Reactive<string>\n /** Language for syntax highlighting (any shiki-bundled name or\n * alias). Defaults from `path` when set. */\n lang?: string\n /** Lines of surrounding context per hunk. Default: 3. */\n context?: number\n wrap?: WrapMode\n}\n\ntype DiffOpts = {\n original: string[]\n originalHi: string[]\n modified: string[]\n modifiedHi: string[]\n context: number\n ctx: RenderCtx\n}\n\n/**\n * Show a unified diff between two file contents with syntax-highlighted\n * rows. Added rows carry a green backdrop and `+` prefix; removed rows\n * carry a red backdrop and `-` prefix; context rows show both line\n * numbers with a neutral gutter.\n *\n * Both sides are highlighted as complete files (via shiki) before the\n * diff is assembled, so context around an edit tokenizes the way it\n * would in the actual file — multi-line strings, block comments, etc.\n * don't get truncated by the hunk window.\n */\nexport class Diff extends Node<DiffState> {\n #lang: Accessor<string | undefined>\n #highlighted: Accessor<{ original: string; modified: string }>\n\n constructor(state: DiffState) {\n super({ wrap: \"word\", ...state })\n\n this.#lang = memo(() => {\n const path = unwrap(this.state.path)\n return this.state.lang ?? (path !== undefined ? langFromPath(path) : undefined)\n })\n\n const context = useContext(RenderContext)\n this.#highlighted = createAsync(\n async () => {\n const lang = this.#lang()\n const input = this.input\n if (!lang) return input\n const theme = context?.style().theme.shiki\n const [original, modified] = await Promise.all([\n codeToAnsi(input.original, lang, { theme }),\n codeToAnsi(input.modified, lang, { theme }),\n ])\n return { modified, original }\n },\n {\n initialValue: this.input,\n }\n )\n }\n\n #norm(s: string): string {\n return s.replaceAll(\"\\r\\n\", \"\\n\").replaceAll(\"\\r\", \"\")\n }\n\n get input(): { original: string; modified: string } {\n return {\n modified: this.#norm(unwrap(this.state.modified)),\n original: this.#norm(unwrap(this.state.original)),\n }\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n const highlighted = this.#highlighted()\n const input = this.input\n const layout = this.layout()\n const width = Math.min(ctx.width, layout.width)\n\n const opts: DiffOpts = {\n context: this.state.context ?? 3,\n ctx: { ...ctx, width },\n modified: input.modified.split(\"\\n\"),\n modifiedHi: highlighted.modified.split(\"\\n\"),\n original: input.original.split(\"\\n\"),\n originalHi: highlighted.original.split(\"\\n\"),\n }\n\n this.state.wrap ??= \"word\"\n return await buildDiffRows(opts)\n }\n\n override layout(): Layout {\n const input = this.input\n const original = calcLayout(input.original, { wrap: this.state.wrap })\n const modified = calcLayout(input.modified, { wrap: this.state.wrap })\n const numWidth = Math.max(\n 1,\n countLines(unwrap(this.state.original)),\n countLines(unwrap(this.state.modified))\n ).toString().length\n const padding = numWidth * 2 + 4 + 4\n return {\n minWidth: Math.max(original.minWidth, modified.minWidth) + padding,\n width: Math.max(original.width, modified.width) + padding,\n }\n }\n}\n\n/**\n * Factory for `Diff`.\n *\n * ```ts\n * diff({\n * original: \"function foo() {}\\n\",\n * modified: \"function foo(x) {}\\n\",\n * path: \"foo.ts\",\n * })\n * ```\n */\nexport function diff(state: State<DiffState>): Diff {\n return new Diff(state)\n}\n\n// ---------- internals ----------\n\ntype DiffRow =\n | { type: \"context\"; origNum: number; newNum: number; content: string }\n | { type: \"remove\"; origNum: number; content: string }\n | { type: \"add\"; newNum: number; content: string }\n\nasync function buildDiffRows(opts: DiffOpts): Promise<string[]> {\n const context = opts.context\n // Async-import keeps cold start snappy — only the diff widget pulls\n // in the library, and it lands at first render rather than at module\n // load.\n const { diffArrays } = await import(\"diff\")\n const segments = diffArrays(opts.original, opts.modified)\n const {\n original: origLines,\n modified: modLines,\n originalHi: origHi,\n modifiedHi: modHi,\n ctx,\n } = opts\n\n // Annotate each line in the diff with its kind + (orig, mod) indices.\n // The flattened list is the row-order the diff would print without\n // any hunking; we compute hunks (with surrounding context) on top.\n interface Annotated {\n kind: \"equal\" | \"remove\" | \"add\"\n origIdx?: number\n modIdx?: number\n }\n const ann: Annotated[] = []\n let oI = 0\n let mI = 0\n for (const seg of segments) {\n if (seg.added) {\n for (const _ of seg.value) ann.push({ kind: \"add\", modIdx: mI++ })\n } else if (seg.removed) {\n for (const _ of seg.value) ann.push({ kind: \"remove\", origIdx: oI++ })\n } else {\n for (const _ of seg.value) ann.push({ kind: \"equal\", modIdx: mI++, origIdx: oI++ })\n }\n }\n\n // Find hunks: ranges around each non-equal line, expanded by `context`,\n // merged when adjacent ranges touch.\n const ranges: { start: number; end: number }[] = []\n for (let i = 0; i < ann.length; i++) {\n if (ann[i].kind === \"equal\") continue\n const start = Math.max(0, i - context)\n const end = Math.min(ann.length - 1, i + context)\n const last = ranges.at(-1)\n if (last && start <= last.end + 1) last.end = Math.max(last.end, end)\n else ranges.push({ end, start })\n }\n if (ranges.length === 0) return [] // nothing changed\n\n // Emit rows for each hunk. (Between hunks we just skip the equal\n // lines — a `…` divider is a future polish.)\n const rows: DiffRow[] = []\n for (const r of ranges) {\n for (let i = r.start; i <= r.end; i++) {\n const a = ann[i]\n if (a.kind === \"equal\") {\n rows.push({\n content: modHi[a.modIdx!] ?? origHi[a.origIdx!] ?? \"\",\n newNum: a.modIdx! + 1,\n origNum: a.origIdx! + 1,\n type: \"context\",\n })\n } else if (a.kind === \"remove\") {\n rows.push({\n content: origHi[a.origIdx!] ?? \"\",\n origNum: a.origIdx! + 1,\n type: \"remove\",\n })\n } else {\n rows.push({\n content: modHi[a.modIdx!] ?? \"\",\n newNum: a.modIdx! + 1,\n type: \"add\",\n })\n }\n }\n }\n\n return renderRows(ctx, rows, origLines.length, modLines.length)\n}\n\nfunction renderRows(\n ctx: RenderCtx,\n rows: DiffRow[],\n origTotal: number,\n modTotal: number\n): string[] {\n const numWidth = Math.max(String(origTotal).length, String(modTotal).length, 1)\n const s = ctx.style\n\n // Two-column gutter: original line number | new line number | space.\n // - Context rows show both numbers.\n // - Remove rows show only the original number; new column blank.\n // - Add rows show only the new number; original column blank.\n // Wrapped continuation lines reuse the row style but emit a blank\n // gutter so the line number isn't repeated per visual row.\n const gutterWidth = numWidth * 2 + 4 // \"<orig> <new> \"\n const contentWidth = Math.max(0, ctx.width - gutterWidth)\n const blankGutter = \" \".repeat(gutterWidth - 2) + s.dim(\"↪ \")\n\n const styles = {\n add: \"diffAdd\",\n context: \"diffContext\",\n remove: \"diffDel\",\n } as const\n\n const out: string[] = []\n for (const r of rows) {\n const origStr = r.type === \"add\" ? \"\" : String(r.origNum)\n const newStr = r.type === \"remove\" ? \"\" : String(r.newNum)\n const gutterStyle = s.bg(`${styles[r.type]}+10`)\n const gutter = gutterStyle(` ${pad(origStr, numWidth)} ${pad(newStr, numWidth)} `)\n\n const prefix = r.type === \"add\" ? \" + \" : r.type === \"remove\" ? \" - \" : \" \"\n const innerWidth = Math.max(0, contentWidth - stringWidth(prefix) - 1)\n\n // Hard-wrap the content. Char-wrap (vs. word-wrap) keeps code\n // diffs honest — splitting by word boundaries would shift columns\n // mid-line and make alignment confusing.\n const wrapped =\n innerWidth > 0 && stringWidth(r.content) > innerWidth\n ? splitAnsi(wrapAnsi(r.content, innerWidth, { mode: \"word\" }))\n : [r.content]\n\n const rowStyle = s.bg(styles[r.type])\n for (let i = 0; i < wrapped.length; i++) {\n const wline = wrapped[i]\n const pw = Math.max(0, innerWidth - stringWidth(wline) + 1)\n const bodyLine = (i === 0 ? prefix : \" \") + wline + \" \".repeat(pw)\n const styledBody = rowStyle?.(bodyLine) ?? bodyLine\n out.push((i === 0 ? gutter : gutterStyle(blankGutter)) + styledBody)\n }\n }\n return out\n}\n\nfunction pad(s: string, width: number): string {\n return s.length >= width ? s : \" \".repeat(width - s.length) + s\n}\n\n/** Resolve a file path to a shiki language identifier. Falls back from\n * extension to basename — shiki natively recognises `dockerfile`,\n * `makefile`, `cmakelists.txt`, etc. */\nfunction langFromPath(path: string): string | undefined {\n const ext = extname(path).slice(1).toLowerCase()\n if (ext) return ext\n const base = basename(path).toLowerCase()\n return base || undefined\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"diff.mjs","names":[],"sources":["../../src/widgets/diff.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Accessor, Reactive } from \"../core/reactive.ts\"\nimport type { Layout, State } from \"../core/state.ts\"\nimport type { WrapMode } from \"../layout/text.ts\"\n\nimport { splitAnsi, stringWidth, wrapAnsi } from \"@zaly/shared/ansi\"\nimport { basename, extname } from \"pathe\"\n// oxlint-disable no-nested-ternary\n// oxlint-disable typescript/no-unnecessary-condition\nimport { Node } from \"../core/node.ts\"\nimport { createAsync, memo, unwrap, useContext } from \"../core/reactive.ts\"\nimport { RenderContext } from \"../core/render.ts\"\nimport { calcLayout } from \"../layout/text.ts\"\nimport { codeToAnsi } from \"../shiki/shiki.ts\"\nimport { shikiTheme } from \"../shiki/theme.ts\"\n\nexport interface DiffState {\n /** Pre-state file content. Plain string or reactive accessor —\n * pass a signal to live-update the diff as either side changes. */\n original: Reactive<string>\n /** Post-state file content. The widget runs `diffLines` between\n * `original` and `modified` and renders the resulting hunks. */\n modified: Reactive<string>\n /** Optional file path. Drives the default `lang` (extension or\n * basename — shiki recognises both `.ts` and `Dockerfile`-style\n * names) and `title` when those aren't set explicitly. */\n path?: Reactive<string>\n /** Language for syntax highlighting (any shiki-bundled name or\n * alias). Defaults from `path` when set. */\n lang?: string\n /** Lines of surrounding context per hunk. Default: 3. */\n context?: number\n wrap?: WrapMode\n}\n\nconst NO_NEWLINE = String.raw`\`\n\ntype DiffLine = { text: string; terminated: boolean }\n\ntype DiffOpts = {\n original: DiffLine[]\n originalHi: string[]\n modified: DiffLine[]\n modifiedHi: string[]\n context: number\n ctx: RenderCtx\n}\n\n/**\n * Show a unified diff between two file contents with syntax-highlighted\n * rows. Added rows carry a green backdrop and `+` prefix; removed rows\n * carry a red backdrop and `-` prefix; context rows show both line\n * numbers with a neutral gutter.\n *\n * Both sides are highlighted as complete files (via shiki) before the\n * diff is assembled, so context around an edit tokenizes the way it\n * would in the actual file — multi-line strings, block comments, etc.\n * don't get truncated by the hunk window.\n */\nexport class Diff extends Node<DiffState> {\n #lang: Accessor<string | undefined>\n #highlighted: Accessor<{ original: string; modified: string }>\n\n constructor(state: DiffState) {\n super({ wrap: \"word\", ...state })\n\n this.#lang = memo(() => {\n const path = unwrap(this.state.path)\n return this.state.lang ?? (path !== undefined ? langFromPath(path) : undefined)\n })\n\n const context = useContext(RenderContext)\n this.#highlighted = createAsync(\n async () => {\n const lang = this.#lang()\n const input = this.input\n if (!lang) return input\n const theme = context ? shikiTheme(context.style().theme) : undefined\n const [original, modified] = await Promise.all([\n codeToAnsi(input.original, lang, { theme }),\n codeToAnsi(input.modified, lang, { theme }),\n ])\n return { modified, original }\n },\n {\n initialValue: this.input,\n }\n )\n }\n\n #norm(s: string): string {\n return s.replaceAll(\"\\r\\n\", \"\\n\").replaceAll(\"\\r\", \"\")\n }\n\n get input(): { original: string; modified: string } {\n return {\n modified: this.#norm(unwrap(this.state.modified)),\n original: this.#norm(unwrap(this.state.original)),\n }\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n const highlighted = this.#highlighted()\n const input = this.input\n const layout = this.layout()\n const width = Math.min(ctx.width, layout.width)\n\n const original = splitLines(input.original)\n const modified = splitLines(input.modified)\n const opts: DiffOpts = {\n context: this.state.context ?? 3,\n ctx: { ...ctx, width },\n modified,\n modifiedHi: splitAnsi(highlighted.modified).slice(0, modified.length),\n original,\n originalHi: splitAnsi(highlighted.original).slice(0, original.length),\n }\n\n this.state.wrap ??= \"word\"\n return await buildDiffRows(opts)\n }\n\n override layout(): Layout {\n const input = this.input\n const original = calcLayout(input.original, { wrap: this.state.wrap })\n const modified = calcLayout(input.modified, { wrap: this.state.wrap })\n const numWidth = Math.max(\n 1,\n splitLines(input.original).length,\n splitLines(input.modified).length\n ).toString().length\n const markerWidth = [input.original, input.modified].some((s) => s !== \"\" && !s.endsWith(\"\\n\"))\n ? stringWidth(NO_NEWLINE)\n : 0\n const padding = numWidth * 2 + 4 + 4\n return {\n minWidth: Math.max(original.minWidth, modified.minWidth) + padding,\n width: Math.max(original.width, modified.width, markerWidth) + padding,\n }\n }\n}\n\n/**\n * Factory for `Diff`.\n *\n * ```ts\n * diff({\n * original: \"function foo() {}\\n\",\n * modified: \"function foo(x) {}\\n\",\n * path: \"foo.ts\",\n * })\n * ```\n */\nexport function diff(state: State<DiffState>): Diff {\n return new Diff(state)\n}\n\n// ---------- internals ----------\n\nfunction splitLines(text: string): DiffLine[] {\n if (text === \"\") return []\n const terminated = text.endsWith(\"\\n\")\n const lines = text.split(\"\\n\")\n if (terminated) lines.pop()\n return lines.map((line, i) => ({ terminated: i < lines.length - 1 || terminated, text: line }))\n}\n\ntype DiffRow = { terminated: boolean } & (\n | { type: \"context\"; origNum: number; newNum: number; content: string }\n | { type: \"remove\"; origNum: number; content: string }\n | { type: \"add\"; newNum: number; content: string }\n)\n\nasync function buildDiffRows(opts: DiffOpts): Promise<string[]> {\n const context = opts.context\n // Async-import keeps cold start snappy — only the diff widget pulls\n // in the library, and it lands at first render rather than at module\n // load.\n const { diffArrays } = await import(\"diff\")\n const segments = diffArrays(opts.original, opts.modified, {\n comparator: (a, b) => a.text === b.text && a.terminated === b.terminated,\n })\n const {\n original: origLines,\n modified: modLines,\n originalHi: origHi,\n modifiedHi: modHi,\n ctx,\n } = opts\n\n // Annotate each line in the diff with its kind + (orig, mod) indices.\n // The flattened list is the row-order the diff would print without\n // any hunking; we compute hunks (with surrounding context) on top.\n interface Annotated {\n kind: \"equal\" | \"remove\" | \"add\"\n origIdx?: number\n modIdx?: number\n }\n const ann: Annotated[] = []\n let oI = 0\n let mI = 0\n for (const seg of segments) {\n if (seg.added) {\n for (const _ of seg.value) ann.push({ kind: \"add\", modIdx: mI++ })\n } else if (seg.removed) {\n for (const _ of seg.value) ann.push({ kind: \"remove\", origIdx: oI++ })\n } else {\n for (const _ of seg.value) ann.push({ kind: \"equal\", modIdx: mI++, origIdx: oI++ })\n }\n }\n\n // Find hunks: ranges around each non-equal line, expanded by `context`,\n // merged when adjacent ranges touch.\n const ranges: { start: number; end: number }[] = []\n for (let i = 0; i < ann.length; i++) {\n if (ann[i].kind === \"equal\") continue\n const start = Math.max(0, i - context)\n const end = Math.min(ann.length - 1, i + context)\n const last = ranges.at(-1)\n if (last && start <= last.end + 1) last.end = Math.max(last.end, end)\n else ranges.push({ end, start })\n }\n if (ranges.length === 0) return [] // nothing changed\n\n // Emit rows for each hunk. (Between hunks we just skip the equal\n // lines — a `…` divider is a future polish.)\n const rows: DiffRow[] = []\n for (const r of ranges) {\n for (let i = r.start; i <= r.end; i++) {\n const a = ann[i]\n if (a.kind === \"equal\") {\n rows.push({\n content: modHi[a.modIdx!] ?? origHi[a.origIdx!] ?? \"\",\n newNum: a.modIdx! + 1,\n origNum: a.origIdx! + 1,\n terminated: modLines[a.modIdx!].terminated,\n type: \"context\",\n })\n } else if (a.kind === \"remove\") {\n rows.push({\n content: origHi[a.origIdx!] ?? \"\",\n origNum: a.origIdx! + 1,\n terminated: origLines[a.origIdx!].terminated,\n type: \"remove\",\n })\n } else {\n rows.push({\n content: modHi[a.modIdx!] ?? \"\",\n newNum: a.modIdx! + 1,\n terminated: modLines[a.modIdx!].terminated,\n type: \"add\",\n })\n }\n }\n }\n\n return renderRows(ctx, rows, origLines.length, modLines.length)\n}\n\nfunction renderRows(\n ctx: RenderCtx,\n rows: DiffRow[],\n origTotal: number,\n modTotal: number\n): string[] {\n const numWidth = Math.max(String(origTotal).length, String(modTotal).length, 1)\n const s = ctx.style\n\n // Two-column gutter: original line number | new line number | space.\n // - Context rows show both numbers.\n // - Remove rows show only the original number; new column blank.\n // - Add rows show only the new number; original column blank.\n // Wrapped continuation lines reuse the row style but emit a blank\n // gutter so the line number isn't repeated per visual row.\n const gutterWidth = numWidth * 2 + 4 // \"<orig> <new> \"\n const contentWidth = Math.max(0, ctx.width - gutterWidth)\n const blankGutter = \" \".repeat(gutterWidth - 2) + s.dim(\"↪ \")\n\n const styles = {\n add: \"diffAdd\",\n context: \"diffContext\",\n remove: \"diffDel\",\n } as const\n\n const out: string[] = []\n for (const r of rows) {\n const origStr = r.type === \"add\" ? \"\" : String(r.origNum)\n const newStr = r.type === \"remove\" ? \"\" : String(r.newNum)\n\n const gutterStyle = s[`${styles[r.type]}Num`] ?? ((x: string) => x)\n const gutter = gutterStyle(` ${pad(origStr, numWidth)} ${pad(newStr, numWidth)} `)\n\n const prefix = r.type === \"add\" ? \" + \" : r.type === \"remove\" ? \" - \" : \" \"\n const innerWidth = Math.max(0, contentWidth - stringWidth(prefix) - 1)\n\n // Hard-wrap the content. Char-wrap (vs. word-wrap) keeps code\n // diffs honest — splitting by word boundaries would shift columns\n // mid-line and make alignment confusing.\n const wrapped =\n innerWidth > 0 && stringWidth(r.content) > innerWidth\n ? splitAnsi(wrapAnsi(r.content, innerWidth, { mode: \"word\" }))\n : [r.content]\n\n const rowStyle = s.bg(styles[r.type])\n for (let i = 0; i < wrapped.length; i++) {\n const wline = wrapped[i]\n const pw = Math.max(0, innerWidth - stringWidth(wline) + 1)\n const bodyLine = (i === 0 ? prefix : \" \") + wline + \" \".repeat(pw)\n const styledBody = rowStyle?.(bodyLine) ?? bodyLine\n out.push((i === 0 ? gutter : gutterStyle(blankGutter)) + styledBody)\n }\n if (!r.terminated) {\n const marker = wrapAnsi(NO_NEWLINE, Math.max(1, contentWidth), { mode: \"word\" })\n for (const line of splitAnsi(marker)) out.push(\" \".repeat(gutterWidth) + s.dim(line))\n }\n }\n return out\n}\n\nfunction pad(s: string, width: number): string {\n return s.length >= width ? s : \" \".repeat(width - s.length) + s\n}\n\n/** Resolve a file path to a shiki language identifier. Falls back from\n * extension to basename — shiki natively recognises `dockerfile`,\n * `makefile`, `cmakelists.txt`, etc. */\nfunction langFromPath(path: string): string | undefined {\n const ext = extname(path).slice(1).toLowerCase()\n if (ext) return ext\n const base = basename(path).toLowerCase()\n return base || undefined\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { u as Style } from "../types-C9ceMsbJ.mjs";
|
|
2
|
+
import { W as Text } from "../queries-C75-wG1B.mjs";
|
|
3
3
|
//#region src/widgets/divider.d.ts
|
|
4
4
|
export type DividerState = Style<false> & {
|
|
5
5
|
char?: string;
|
package/dist/widgets/divider.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as divider } from "../divider-
|
|
1
|
+
export { t as divider } from "../divider-BlNNN2OS.mjs";
|
package/dist/widgets/image.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as ImageState, r as image, t as Image } from "../image-
|
|
1
|
+
import { n as ImageState, r as image, t as Image } from "../image-BLls2F4t.mjs";
|
|
2
2
|
export { Image, ImageState, image };
|
package/dist/widgets/image.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as unwrap, w as useContext } from "../reactive-f7NpAi69.mjs";
|
|
2
2
|
import { t as Node } from "../node-BZ7f6HzU.mjs";
|
|
3
|
-
import { t as RenderContext } from "../render-
|
|
3
|
+
import { t as RenderContext } from "../render-B7LfNM5K.mjs";
|
|
4
4
|
import { s as loadKittyGraphics } from "../kitty-JbCJC0iQ.mjs";
|
|
5
5
|
import { fileDetect } from "@zaly/shared/detect";
|
|
6
6
|
import { imageInfo } from "@zaly/shared/image";
|
|
@@ -31,7 +31,7 @@ var Image = class extends Node {
|
|
|
31
31
|
const detected = await fileDetect(this.state.src);
|
|
32
32
|
if (detected?.type !== "image") return this.fallback;
|
|
33
33
|
const img = await imageInfo(detected);
|
|
34
|
-
const { cols, rows } = dims(this.state, img,
|
|
34
|
+
const { cols, rows } = dims(this.state, img, ctx.width);
|
|
35
35
|
const t = await kitty.transmitOnce(img);
|
|
36
36
|
if (!t) return this.fallback;
|
|
37
37
|
const p = kitty.placement(t.imageId, {
|
|
@@ -61,9 +61,9 @@ function image(first, style) {
|
|
|
61
61
|
function dims(state, meta, available) {
|
|
62
62
|
const cellAspect = state.cellAspect ?? 2;
|
|
63
63
|
const aspect = meta.height / meta.width;
|
|
64
|
-
let cols = state.width;
|
|
64
|
+
let cols = state.width === void 0 ? void 0 : Math.max(1, Math.min(state.width, available));
|
|
65
65
|
let rows = state.height;
|
|
66
|
-
if (cols === void 0 && rows === void 0) cols = Math.max(1, available);
|
|
66
|
+
if (cols === void 0 && rows === void 0) cols = Math.max(1, Math.min(available, 80));
|
|
67
67
|
if (cols !== void 0 && rows === void 0) rows = Math.max(1, Math.round(cols * aspect / cellAspect));
|
|
68
68
|
else if (rows !== void 0 && cols === void 0) cols = Math.max(1, Math.round(rows * cellAspect / aspect));
|
|
69
69
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.mjs","names":[],"sources":["../../src/widgets/image.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Accessor } from \"../core/reactive.ts\"\nimport type { Layout } from \"../core/state.ts\"\n\nimport { fileDetect } from \"@zaly/shared/detect\"\nimport { imageInfo } from \"@zaly/shared/image\"\nimport { Node } from \"../core/node.ts\"\nimport { unwrap, useContext } from \"../core/reactive.ts\"\nimport { RenderContext } from \"../core/render.ts\"\nimport { loadKittyGraphics } from \"../image/kitty.ts\"\n\nexport interface ImageState {\n /**\n * Path to an image file. PNG passes through with zero decoding; other\n * formats (JPEG/WebP/GIF/AVIF/SVG) are read via image-meta for\n * dimensions and — for KGP terminals — converted once to a cached\n * temp PNG via sharp. iTerm2 accepts all formats natively.\n */\n src: string\n /** Display width in terminal cells. Defaults to `ctx.width`. */\n width?: number\n /**\n * Display height in terminal cells. When omitted, computed from the\n * source aspect ratio + `cellAspect`.\n */\n height?: number\n /** Fallback text shown on terminals without an image protocol. */\n alt?: string\n /**\n * Character cell aspect ratio (cellHeight / cellWidth). Most terminals\n * land around 2.0. Tweak if aspect-preserved images look stretched.\n */\n cellAspect?: number\n}\n\nexport class Image extends Node<ImageState> {\n #delete?: () => void\n #enabled?: Accessor<boolean>\n\n constructor(state: ImageState) {\n super(state)\n this.on(\"unmount\", () => this.#delete?.())\n const context = useContext(RenderContext)\n this.#enabled = context?.images\n }\n\n get fallback(): string[] {\n return [this.state.alt ?? `[Image: ${this.state.src}]`]\n }\n\n override layout(): Layout {\n return { minWidth: 50, width: 100 }\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n if (unwrap(this.#enabled) === false) return this.fallback\n\n const queries = this.ctx?.input.queries\n const kitty = queries ? await loadKittyGraphics(queries) : undefined\n if (!kitty?.supported) return this.fallback\n\n const detected = await fileDetect(this.state.src)\n if (detected?.type !== \"image\") return this.fallback\n const img = await imageInfo(detected)\n\n const { cols, rows } = dims(this.state, img,
|
|
1
|
+
{"version":3,"file":"image.mjs","names":[],"sources":["../../src/widgets/image.ts"],"sourcesContent":["import type { RenderCtx } from \"../core/ctx.ts\"\nimport type { Accessor } from \"../core/reactive.ts\"\nimport type { Layout } from \"../core/state.ts\"\n\nimport { fileDetect } from \"@zaly/shared/detect\"\nimport { imageInfo } from \"@zaly/shared/image\"\nimport { Node } from \"../core/node.ts\"\nimport { unwrap, useContext } from \"../core/reactive.ts\"\nimport { RenderContext } from \"../core/render.ts\"\nimport { loadKittyGraphics } from \"../image/kitty.ts\"\n\nexport interface ImageState {\n /**\n * Path to an image file. PNG passes through with zero decoding; other\n * formats (JPEG/WebP/GIF/AVIF/SVG) are read via image-meta for\n * dimensions and — for KGP terminals — converted once to a cached\n * temp PNG via sharp. iTerm2 accepts all formats natively.\n */\n src: string\n /** Display width in terminal cells. Defaults to `ctx.width`. */\n width?: number\n /**\n * Display height in terminal cells. When omitted, computed from the\n * source aspect ratio + `cellAspect`.\n */\n height?: number\n /** Fallback text shown on terminals without an image protocol. */\n alt?: string\n /**\n * Character cell aspect ratio (cellHeight / cellWidth). Most terminals\n * land around 2.0. Tweak if aspect-preserved images look stretched.\n */\n cellAspect?: number\n}\n\nexport class Image extends Node<ImageState> {\n #delete?: () => void\n #enabled?: Accessor<boolean>\n\n constructor(state: ImageState) {\n super(state)\n this.on(\"unmount\", () => this.#delete?.())\n const context = useContext(RenderContext)\n this.#enabled = context?.images\n }\n\n get fallback(): string[] {\n return [this.state.alt ?? `[Image: ${this.state.src}]`]\n }\n\n override layout(): Layout {\n return { minWidth: 50, width: 100 }\n }\n\n protected async _render(ctx: RenderCtx): Promise<string[]> {\n if (unwrap(this.#enabled) === false) return this.fallback\n\n const queries = this.ctx?.input.queries\n const kitty = queries ? await loadKittyGraphics(queries) : undefined\n if (!kitty?.supported) return this.fallback\n\n const detected = await fileDetect(this.state.src)\n if (detected?.type !== \"image\") return this.fallback\n const img = await imageInfo(detected)\n\n const { cols, rows } = dims(this.state, img, ctx.width)\n\n const t = await kitty.transmitOnce(img)\n if (!t) return this.fallback\n const p = kitty.placement(t.imageId, { cols, rows })\n if (!p) return this.fallback\n this.#delete = () =>\n p.placementId ? kitty.deletePlacement(t.imageId, p.placementId) : undefined\n // Route the transmit bytes through the side-channel queue (mount\n // ctx → terminal). Cached rows then hold pure placement ANSI,\n // which is safe to reuse across repaints. If we're rendering\n // before mount (rare — tests, headless previews), fall back to\n // inlining the transmit into the lead so the picture still\n // shows correctly the first time.\n if (t.transmit) {\n ctx.transmit(t.transmit)\n if (p.inline) ctx.transmit(p.seq)\n }\n\n if (p.inline) return p.data\n\n const ret = [...p.data]\n if (!ret.length) return this.fallback\n ret[0] = p.seq + ret[0]\n return ret\n }\n}\n\nexport function image(src: string, style?: Omit<ImageState, \"src\">): Image\nexport function image(state: ImageState): Image\nexport function image(first: string | ImageState, style?: Omit<ImageState, \"src\">): Image {\n if (typeof first === \"string\") return new Image({ src: first, ...style })\n return new Image(first)\n}\n\nfunction dims(\n state: ImageState,\n meta: { width: number; height: number },\n available: number\n): { cols: number; rows: number } {\n const cellAspect = state.cellAspect ?? 2\n const aspect = meta.height / meta.width\n let cols = state.width === undefined ? undefined : Math.max(1, Math.min(state.width, available))\n let rows = state.height\n if (cols === undefined && rows === undefined) cols = Math.max(1, Math.min(available, 80))\n if (cols !== undefined && rows === undefined) {\n rows = Math.max(1, Math.round((cols * aspect) / cellAspect))\n } else if (rows !== undefined && cols === undefined) {\n cols = Math.max(1, Math.round((rows * cellAspect) / aspect))\n }\n return { cols: cols ?? available, rows: rows ?? 1 }\n}\n"],"mappings":";;;;;;;AAmCA,IAAa,QAAb,cAA2B,KAAiB;CAC1C;CACA;CAEA,YAAY,OAAmB;EAC7B,MAAM,KAAK;EACX,KAAK,GAAG,iBAAiB,KAAK,UAAU,CAAC;EACzC,MAAM,UAAU,WAAW,aAAa;EACxC,KAAK,WAAW,SAAS;CAC3B;CAEA,IAAI,WAAqB;EACvB,OAAO,CAAC,KAAK,MAAM,OAAO,WAAW,KAAK,MAAM,IAAI,EAAE;CACxD;CAEA,SAA0B;EACxB,OAAO;GAAE,UAAU;GAAI,OAAO;EAAI;CACpC;CAEA,MAAgB,QAAQ,KAAmC;EACzD,IAAI,OAAO,KAAK,QAAQ,MAAM,OAAO,OAAO,KAAK;EAEjD,MAAM,UAAU,KAAK,KAAK,MAAM;EAChC,MAAM,QAAQ,UAAU,MAAM,kBAAkB,OAAO,IAAI,KAAA;EAC3D,IAAI,CAAC,OAAO,WAAW,OAAO,KAAK;EAEnC,MAAM,WAAW,MAAM,WAAW,KAAK,MAAM,GAAG;EAChD,IAAI,UAAU,SAAS,SAAS,OAAO,KAAK;EAC5C,MAAM,MAAM,MAAM,UAAU,QAAQ;EAEpC,MAAM,EAAE,MAAM,SAAS,KAAK,KAAK,OAAO,KAAK,IAAI,KAAK;EAEtD,MAAM,IAAI,MAAM,MAAM,aAAa,GAAG;EACtC,IAAI,CAAC,GAAG,OAAO,KAAK;EACpB,MAAM,IAAI,MAAM,UAAU,EAAE,SAAS;GAAE;GAAM;EAAK,CAAC;EACnD,IAAI,CAAC,GAAG,OAAO,KAAK;EACpB,KAAK,gBACH,EAAE,cAAc,MAAM,gBAAgB,EAAE,SAAS,EAAE,WAAW,IAAI,KAAA;EAOpE,IAAI,EAAE,UAAU;GACd,IAAI,SAAS,EAAE,QAAQ;GACvB,IAAI,EAAE,QAAQ,IAAI,SAAS,EAAE,GAAG;EAClC;EAEA,IAAI,EAAE,QAAQ,OAAO,EAAE;EAEvB,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI;EACtB,IAAI,CAAC,IAAI,QAAQ,OAAO,KAAK;EAC7B,IAAI,KAAK,EAAE,MAAM,IAAI;EACrB,OAAO;CACT;AACF;AAIA,SAAgB,MAAM,OAA4B,OAAwC;CACxF,IAAI,OAAO,UAAU,UAAU,OAAO,IAAI,MAAM;EAAE,KAAK;EAAO,GAAG;CAAM,CAAC;CACxE,OAAO,IAAI,MAAM,KAAK;AACxB;AAEA,SAAS,KACP,OACA,MACA,WACgC;CAChC,MAAM,aAAa,MAAM,cAAc;CACvC,MAAM,SAAS,KAAK,SAAS,KAAK;CAClC,IAAI,OAAO,MAAM,UAAU,KAAA,IAAY,KAAA,IAAY,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,OAAO,SAAS,CAAC;CAC/F,IAAI,OAAO,MAAM;CACjB,IAAI,SAAS,KAAA,KAAa,SAAS,KAAA,GAAW,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,EAAE,CAAC;CACxF,IAAI,SAAS,KAAA,KAAa,SAAS,KAAA,GACjC,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,OAAO,SAAU,UAAU,CAAC;MACtD,IAAI,SAAS,KAAA,KAAa,SAAS,KAAA,GACxC,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,OAAO,aAAc,MAAM,CAAC;CAE7D,OAAO;EAAE,MAAM,QAAQ;EAAW,MAAM,QAAQ;CAAE;AACpD"}
|
package/dist/widgets/input.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as InputValue, i as InputState, n as InputAttachment, o as input, r as InputEvents, t as Input } from "../input-
|
|
1
|
+
import { a as InputValue, i as InputState, n as InputAttachment, o as input, r as InputEvents, t as Input } from "../input-NuD8TH8N.mjs";
|
|
2
2
|
export { Input, InputAttachment, InputEvents, InputState, InputValue, input };
|
package/dist/widgets/input.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as Input, n as input } from "../input-
|
|
1
|
+
export { t as Input, n as input } from "../input-ET2YEMcl.mjs";
|
package/dist/widgets/log.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { M as LogState, N as LogStyle, P as log } from "../queries-C75-wG1B.mjs";
|
|
2
2
|
export { LogState, LogStyle, log };
|
package/dist/widgets/log.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as log } from "../log-
|
|
1
|
+
export { t as log } from "../log-B4djzy2m.mjs";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { t as WrapMode } from "../text-
|
|
1
|
+
import { i as AnyStyle } from "../types-C9ceMsbJ.mjs";
|
|
2
|
+
import { G as TextContent, I as RenderCtx, Q as State, X as Layout, h as Node } from "../queries-C75-wG1B.mjs";
|
|
3
|
+
import { t as WrapMode } from "../text-CmxbA8lk.mjs";
|
|
4
4
|
import { n as MdOptions } from "../types-D3jk1rtk.mjs";
|
|
5
|
-
import { t as Image } from "../image-
|
|
5
|
+
import { t as Image } from "../image-BLls2F4t.mjs";
|
|
6
6
|
//#region src/widgets/markdown.d.ts
|
|
7
7
|
export interface MarkdownState {
|
|
8
8
|
/** Markdown source. Accepts a plain string or a reactive accessor —
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.mts","names":["_$___core_state_ts0.Layout"],"sources":["../../src/widgets/markdown.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"markdown.d.mts","names":["_$___core_state_ts0.Layout"],"sources":["../../src/widgets/markdown.ts"],"mappings":";;;;;;iBAqBiB;;;;EAIf,SAAS;;EAET,UAAU;;;;;;;EAOV;EACA,OAAO;EACP,QAAQ;;qBAcG,iBAAiB,KAAK;;WAKxB,QAAM,YAAA;EASf,YAAY,OAAO,MAAM;YAwDT,QAAQ,KAAK,YAAY;EA0C1B,OAAO,KAAK,YAAS,QAATA;;;;;;;;;;;;wBAeb,SACd,SAAS,aACT,QAAQ,KAAK,MAAM,6BAClB;wBACa,SAAS,OAAO,MAAM,iBAAiB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as Markdown, n as markdown } from "../markdown-
|
|
1
|
+
export { t as Markdown, n as markdown } from "../markdown-D3ZtRn6C.mjs";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { L as Overlay, R as OverlayState, z as overlay } from "../queries-C75-wG1B.mjs";
|
|
2
2
|
export { Overlay, OverlayState, overlay };
|
package/dist/widgets/overlay.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as overlay } from "../overlay-
|
|
1
|
+
export { t as overlay } from "../overlay-LvOjG7kn.mjs";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as picker, i as PickerTreeProps, n as PickerItem, r as PickerSelectProps, t as PickerActions } from "../picker-
|
|
1
|
+
import { a as picker, i as PickerTreeProps, n as PickerItem, r as PickerSelectProps, t as PickerActions } from "../picker-B-OxKKnD.mjs";
|
|
2
2
|
export { PickerActions, PickerItem, PickerSelectProps, PickerTreeProps, picker };
|
package/dist/widgets/picker.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as picker } from "../picker-
|
|
1
|
+
export { t as picker } from "../picker-f6xjgACX.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { o as Color } from "../types-C9ceMsbJ.mjs";
|
|
2
|
+
import { Ft as Size, I as RenderCtx, Q as State, h as Node, it as Reactive } from "../queries-C75-wG1B.mjs";
|
|
3
3
|
//#region src/widgets/progress.d.ts
|
|
4
4
|
export interface ProgressState {
|
|
5
5
|
/** Current value. Clamped to `[0, total]`. Accepts a signal accessor
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SelectEvents, i as Select, n as OptionRender, o as SelectState, r as OptionRenderCtx, s as select, t as Option } from "../select-
|
|
1
|
+
import { a as SelectEvents, i as Select, n as OptionRender, o as SelectState, r as OptionRenderCtx, s as select, t as Option } from "../select-BKE5LzdN.mjs";
|
|
2
2
|
export { Option, OptionRender, OptionRenderCtx, Select, SelectEvents, SelectState, select };
|
package/dist/widgets/show.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { i as AnyStyle } from "../types-C9ceMsbJ.mjs";
|
|
2
|
+
import { I as RenderCtx, Q as State, h as Node, it as Reactive } from "../queries-C75-wG1B.mjs";
|
|
3
3
|
//#region src/widgets/spinner.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Frame sets from the common terminal-spinner vocabulary. Pick one to taste.
|
package/dist/widgets/text.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { G as
|
|
1
|
+
import { G as TextContent, J as textContent, K as TextStyle, W as Text, q as text } from "../queries-C75-wG1B.mjs";
|
|
2
2
|
export { Text, TextContent, TextStyle, text, textContent };
|
package/dist/widgets/text.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as Text, n as text, r as textContent } from "../text-
|
|
1
|
+
export { t as Text, n as text, r as textContent } from "../text-DPrhma4x.mjs";
|
package/dist/widgets/tree.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as tree, n as TreeNode, r as TreeProps, t as TreeItem } from "../tree-
|
|
1
|
+
import { i as tree, n as TreeNode, r as TreeProps, t as TreeItem } from "../tree-CTvSpF9b.mjs";
|
|
2
2
|
export { TreeItem, TreeNode, TreeProps, tree };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as Widget, r as widget, t as Props } from "../widget-
|
|
1
|
+
import { n as Widget, r as widget, t as Props } from "../widget-DlF32PRp.mjs";
|
|
2
2
|
export { Props, Widget, widget };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zaly/tui",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Terminal UI framework used by zaly.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ansi",
|
|
@@ -79,18 +79,20 @@
|
|
|
79
79
|
"access": "public"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"@
|
|
82
|
+
"@mathjax/src": "^4.1.3",
|
|
83
|
+
"@zaly/shared": "0.1.0",
|
|
83
84
|
"diff": "^9.0.0",
|
|
84
85
|
"marked": "^18.1.1",
|
|
85
86
|
"pathe": "^2.0.3",
|
|
86
87
|
"shiki": "^4.5.0"
|
|
87
88
|
},
|
|
88
89
|
"devDependencies": {
|
|
90
|
+
"@shikijs/vscode-textmate": "10.1.0",
|
|
89
91
|
"ghostty-web": "^0.4.0",
|
|
90
92
|
"mitata": "^1.0.34",
|
|
91
93
|
"slice-ansi": "^9.0.1",
|
|
92
94
|
"string-width": "^8.3.0",
|
|
93
|
-
"
|
|
95
|
+
"typebox": "^1.4.2",
|
|
94
96
|
"wrap-ansi": "^10.0.2"
|
|
95
97
|
},
|
|
96
98
|
"optionalDependencies": {
|
|
@@ -100,14 +102,10 @@
|
|
|
100
102
|
"bun": ">=1.2",
|
|
101
103
|
"node": ">=22.18.0"
|
|
102
104
|
},
|
|
103
|
-
"inlinedDependencies": {
|
|
104
|
-
"typia": "15.1.0"
|
|
105
|
-
},
|
|
106
105
|
"scripts": {
|
|
107
106
|
"bench": "z bench",
|
|
108
107
|
"build": "z build",
|
|
109
108
|
"build:themes-1-shiki": "bun scripts/themes-shiki.ts",
|
|
110
|
-
"build:themes-2-nvim": "exit 0; nvim -l scripts/themes-nvim.lua",
|
|
111
109
|
"build:themes-3-tokyonight": "bun scripts/themes-tokyonight.ts",
|
|
112
110
|
"build:themes-4-builtin": "bun scripts/themes-builtin.ts && oxfmt src/themes/builtin.ts",
|
|
113
111
|
"docs:api": "typedoc",
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "file:./../schemas/theme.schema.json",
|
|
3
|
-
"id": "dracula-soft",
|
|
4
|
-
"name": "Dracula Theme Soft",
|
|
5
|
-
"shiki": "dracula-soft",
|
|
6
|
-
"fg": "#f6f6f4",
|
|
7
|
-
"bg": "#282A36",
|
|
8
|
-
"primary": "#bf9eee",
|
|
9
|
-
"accent": "#f286c4",
|
|
10
|
-
"success": "#62e884",
|
|
11
|
-
"info": "#97e1f1",
|
|
12
|
-
"warn": "#97e1f1",
|
|
13
|
-
"error": "#ee6666",
|
|
14
|
-
"muted": "#7b7f8b",
|
|
15
|
-
"border": "#bf9eee",
|
|
16
|
-
"selection": {
|
|
17
|
-
"bg": "#44475A"
|
|
18
|
-
},
|
|
19
|
-
"diffAdd": {
|
|
20
|
-
"bg": "#2d443f",
|
|
21
|
-
"fg": "#62e884"
|
|
22
|
-
},
|
|
23
|
-
"diffDel": {
|
|
24
|
-
"bg": "#6b3740",
|
|
25
|
-
"fg": "#ee6666"
|
|
26
|
-
},
|
|
27
|
-
"diffTitle": {
|
|
28
|
-
"fg": "#7b7f8b"
|
|
29
|
-
},
|
|
30
|
-
"comment": {
|
|
31
|
-
"fg": "#7b7f8b"
|
|
32
|
-
},
|
|
33
|
-
"syntaxNumber": {
|
|
34
|
-
"fg": "#bf9eee"
|
|
35
|
-
},
|
|
36
|
-
"syntaxString": {
|
|
37
|
-
"fg": "#e7ee98"
|
|
38
|
-
},
|
|
39
|
-
"syntaxBoolean": {
|
|
40
|
-
"fg": "#bf9eee"
|
|
41
|
-
},
|
|
42
|
-
"syntaxFunction": {
|
|
43
|
-
"fg": "#62e884"
|
|
44
|
-
},
|
|
45
|
-
"syntaxField": {
|
|
46
|
-
"fg": "#f6f6f4"
|
|
47
|
-
},
|
|
48
|
-
"syntaxConstant": {
|
|
49
|
-
"fg": "#bf9eee"
|
|
50
|
-
},
|
|
51
|
-
"syntaxSpecial": {
|
|
52
|
-
"fg": "#f286c4"
|
|
53
|
-
},
|
|
54
|
-
"mdHeading": {
|
|
55
|
-
"bold": true,
|
|
56
|
-
"fg": "#bf9eee"
|
|
57
|
-
},
|
|
58
|
-
"mdHeading1": {
|
|
59
|
-
"bold": true,
|
|
60
|
-
"fg": "#bf9eee"
|
|
61
|
-
},
|
|
62
|
-
"mdHeading2": {
|
|
63
|
-
"bold": true,
|
|
64
|
-
"fg": "#bf9eee"
|
|
65
|
-
},
|
|
66
|
-
"mdHeading3": {
|
|
67
|
-
"bold": true,
|
|
68
|
-
"fg": "#bf9eee"
|
|
69
|
-
},
|
|
70
|
-
"mdHeading4": {
|
|
71
|
-
"bold": true,
|
|
72
|
-
"fg": "#bf9eee"
|
|
73
|
-
},
|
|
74
|
-
"mdHeading5": {
|
|
75
|
-
"bold": true,
|
|
76
|
-
"fg": "#bf9eee"
|
|
77
|
-
},
|
|
78
|
-
"mdHeading6": {
|
|
79
|
-
"bold": true,
|
|
80
|
-
"fg": "#bf9eee"
|
|
81
|
-
},
|
|
82
|
-
"mdBold": {
|
|
83
|
-
"bold": true,
|
|
84
|
-
"fg": "#FFB86C"
|
|
85
|
-
},
|
|
86
|
-
"mdItalic": {
|
|
87
|
-
"italic": true,
|
|
88
|
-
"fg": "#e7ee98"
|
|
89
|
-
},
|
|
90
|
-
"mdLink": {
|
|
91
|
-
"fg": "#97e1f1"
|
|
92
|
-
},
|
|
93
|
-
"mdQuote": {
|
|
94
|
-
"italic": true,
|
|
95
|
-
"fg": "#e7ee98"
|
|
96
|
-
},
|
|
97
|
-
"mdHr": {
|
|
98
|
-
"fg": "#7b7f8b"
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "file:./../schemas/theme.schema.json",
|
|
3
|
-
"id": "github-dark",
|
|
4
|
-
"name": "GitHub Dark",
|
|
5
|
-
"shiki": "github-dark",
|
|
6
|
-
"fg": "#e1e4e8",
|
|
7
|
-
"bg": "#24292e",
|
|
8
|
-
"primary": "#79b8ff",
|
|
9
|
-
"accent": "#c8e1ff",
|
|
10
|
-
"success": "#34d058",
|
|
11
|
-
"info": "#39c5cf",
|
|
12
|
-
"warn": "#ffea7f",
|
|
13
|
-
"error": "#f97583",
|
|
14
|
-
"muted": "#959da5",
|
|
15
|
-
"border": "#1b1f23",
|
|
16
|
-
"selection": {
|
|
17
|
-
"bg": "#284566"
|
|
18
|
-
},
|
|
19
|
-
"diffAdd": {
|
|
20
|
-
"bg": "#254132",
|
|
21
|
-
"fg": "#85e89d"
|
|
22
|
-
},
|
|
23
|
-
"diffDel": {
|
|
24
|
-
"bg": "#462c33",
|
|
25
|
-
"fg": "#fdaeb7"
|
|
26
|
-
},
|
|
27
|
-
"diffTitle": {
|
|
28
|
-
"fg": "#fdaeb7",
|
|
29
|
-
"bg": "#86181d"
|
|
30
|
-
},
|
|
31
|
-
"comment": {
|
|
32
|
-
"fg": "#6a737d"
|
|
33
|
-
},
|
|
34
|
-
"syntaxNumber": {
|
|
35
|
-
"fg": "#79b8ff"
|
|
36
|
-
},
|
|
37
|
-
"syntaxString": {
|
|
38
|
-
"fg": "#9ecbff"
|
|
39
|
-
},
|
|
40
|
-
"syntaxBoolean": {
|
|
41
|
-
"fg": "#79b8ff"
|
|
42
|
-
},
|
|
43
|
-
"syntaxFunction": {
|
|
44
|
-
"fg": "#b392f0"
|
|
45
|
-
},
|
|
46
|
-
"syntaxField": {
|
|
47
|
-
"fg": "#e1e4e8"
|
|
48
|
-
},
|
|
49
|
-
"syntaxConstant": {
|
|
50
|
-
"fg": "#79b8ff"
|
|
51
|
-
},
|
|
52
|
-
"syntaxSpecial": {
|
|
53
|
-
"fg": "#f97583"
|
|
54
|
-
},
|
|
55
|
-
"mdHeading": {
|
|
56
|
-
"bold": true,
|
|
57
|
-
"fg": "#79b8ff"
|
|
58
|
-
},
|
|
59
|
-
"mdHeading1": {
|
|
60
|
-
"bold": true,
|
|
61
|
-
"fg": "#79b8ff"
|
|
62
|
-
},
|
|
63
|
-
"mdHeading2": {
|
|
64
|
-
"bold": true,
|
|
65
|
-
"fg": "#79b8ff"
|
|
66
|
-
},
|
|
67
|
-
"mdHeading3": {
|
|
68
|
-
"bold": true,
|
|
69
|
-
"fg": "#79b8ff"
|
|
70
|
-
},
|
|
71
|
-
"mdHeading4": {
|
|
72
|
-
"bold": true,
|
|
73
|
-
"fg": "#79b8ff"
|
|
74
|
-
},
|
|
75
|
-
"mdHeading5": {
|
|
76
|
-
"bold": true,
|
|
77
|
-
"fg": "#79b8ff"
|
|
78
|
-
},
|
|
79
|
-
"mdHeading6": {
|
|
80
|
-
"bold": true,
|
|
81
|
-
"fg": "#79b8ff"
|
|
82
|
-
},
|
|
83
|
-
"mdBold": {
|
|
84
|
-
"bold": true,
|
|
85
|
-
"fg": "#e1e4e8"
|
|
86
|
-
},
|
|
87
|
-
"mdItalic": {
|
|
88
|
-
"italic": true,
|
|
89
|
-
"fg": "#e1e4e8"
|
|
90
|
-
},
|
|
91
|
-
"mdStrikethrough": {
|
|
92
|
-
"strikethrough": true
|
|
93
|
-
},
|
|
94
|
-
"mdLink": {
|
|
95
|
-
"underline": true
|
|
96
|
-
},
|
|
97
|
-
"mdQuote": {
|
|
98
|
-
"fg": "#85e89d"
|
|
99
|
-
},
|
|
100
|
-
"mdHr": {
|
|
101
|
-
"bold": true,
|
|
102
|
-
"fg": "#79b8ff"
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "file:./../schemas/theme.schema.json",
|
|
3
|
-
"id": "github-light",
|
|
4
|
-
"name": "GitHub Light",
|
|
5
|
-
"shiki": "github-light",
|
|
6
|
-
"fg": "#24292e",
|
|
7
|
-
"bg": "#fff",
|
|
8
|
-
"primary": "#0366d6",
|
|
9
|
-
"accent": "#005cc5",
|
|
10
|
-
"success": "#28a745",
|
|
11
|
-
"info": "#1b7c83",
|
|
12
|
-
"warn": "#f9c513",
|
|
13
|
-
"error": "#cb2431",
|
|
14
|
-
"muted": "#959da5",
|
|
15
|
-
"border": "#e1e4e8",
|
|
16
|
-
"selection": {
|
|
17
|
-
"bg": "#dae9f9"
|
|
18
|
-
},
|
|
19
|
-
"diffAdd": {
|
|
20
|
-
"bg": "#e4f9e9",
|
|
21
|
-
"fg": "#22863a"
|
|
22
|
-
},
|
|
23
|
-
"diffDel": {
|
|
24
|
-
"bg": "#fae5e7",
|
|
25
|
-
"fg": "#b31d28"
|
|
26
|
-
},
|
|
27
|
-
"diffTitle": {
|
|
28
|
-
"fg": "#b31d28",
|
|
29
|
-
"bg": "#ffeef0"
|
|
30
|
-
},
|
|
31
|
-
"comment": {
|
|
32
|
-
"fg": "#6a737d"
|
|
33
|
-
},
|
|
34
|
-
"syntaxNumber": {
|
|
35
|
-
"fg": "#005cc5"
|
|
36
|
-
},
|
|
37
|
-
"syntaxString": {
|
|
38
|
-
"fg": "#032f62"
|
|
39
|
-
},
|
|
40
|
-
"syntaxBoolean": {
|
|
41
|
-
"fg": "#005cc5"
|
|
42
|
-
},
|
|
43
|
-
"syntaxFunction": {
|
|
44
|
-
"fg": "#6f42c1"
|
|
45
|
-
},
|
|
46
|
-
"syntaxField": {
|
|
47
|
-
"fg": "#24292e"
|
|
48
|
-
},
|
|
49
|
-
"syntaxConstant": {
|
|
50
|
-
"fg": "#005cc5"
|
|
51
|
-
},
|
|
52
|
-
"syntaxSpecial": {
|
|
53
|
-
"fg": "#d73a49"
|
|
54
|
-
},
|
|
55
|
-
"mdHeading": {
|
|
56
|
-
"bold": true,
|
|
57
|
-
"fg": "#005cc5"
|
|
58
|
-
},
|
|
59
|
-
"mdHeading1": {
|
|
60
|
-
"bold": true,
|
|
61
|
-
"fg": "#005cc5"
|
|
62
|
-
},
|
|
63
|
-
"mdHeading2": {
|
|
64
|
-
"bold": true,
|
|
65
|
-
"fg": "#005cc5"
|
|
66
|
-
},
|
|
67
|
-
"mdHeading3": {
|
|
68
|
-
"bold": true,
|
|
69
|
-
"fg": "#005cc5"
|
|
70
|
-
},
|
|
71
|
-
"mdHeading4": {
|
|
72
|
-
"bold": true,
|
|
73
|
-
"fg": "#005cc5"
|
|
74
|
-
},
|
|
75
|
-
"mdHeading5": {
|
|
76
|
-
"bold": true,
|
|
77
|
-
"fg": "#005cc5"
|
|
78
|
-
},
|
|
79
|
-
"mdHeading6": {
|
|
80
|
-
"bold": true,
|
|
81
|
-
"fg": "#005cc5"
|
|
82
|
-
},
|
|
83
|
-
"mdBold": {
|
|
84
|
-
"bold": true,
|
|
85
|
-
"fg": "#24292e"
|
|
86
|
-
},
|
|
87
|
-
"mdItalic": {
|
|
88
|
-
"italic": true,
|
|
89
|
-
"fg": "#24292e"
|
|
90
|
-
},
|
|
91
|
-
"mdStrikethrough": {
|
|
92
|
-
"strikethrough": true
|
|
93
|
-
},
|
|
94
|
-
"mdLink": {
|
|
95
|
-
"underline": true
|
|
96
|
-
},
|
|
97
|
-
"mdQuote": {
|
|
98
|
-
"fg": "#22863a"
|
|
99
|
-
},
|
|
100
|
-
"mdHr": {
|
|
101
|
-
"bold": true,
|
|
102
|
-
"fg": "#005cc5"
|
|
103
|
-
}
|
|
104
|
-
}
|