@zaly/tui 0.0.6 → 0.0.7
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/theme.schema.json +272 -270
- package/assets/themes/kanagawa-dragon.json +3 -0
- package/assets/themes/kanagawa-wave.json +3 -0
- package/dist/{actions-CnVzKVID.d.mts → actions-DFboj3g5.d.mts} +4 -4
- package/dist/{actions-CnVzKVID.d.mts.map → actions-DFboj3g5.d.mts.map} +1 -1
- package/dist/ansi.d.mts +10 -11
- package/dist/ansi.d.mts.map +1 -1
- package/dist/{autocomplete-Dfw-yQDa.d.mts → autocomplete-CxzetPOo.d.mts} +4 -4
- package/dist/{autocomplete-Dfw-yQDa.d.mts.map → autocomplete-CxzetPOo.d.mts.map} +1 -1
- package/dist/{box-DepqUtuo.mjs → box-DLEcEvDH.mjs} +18 -11
- package/dist/box-DLEcEvDH.mjs.map +1 -0
- package/dist/{builder-DTz5mppV.mjs → builder-BgEcjj8Z.mjs} +5 -4
- package/dist/builder-BgEcjj8Z.mjs.map +1 -0
- package/dist/{callbacks-DcMBGQEO.mjs → callbacks-D132G8dy.mjs} +7 -6
- package/dist/callbacks-D132G8dy.mjs.map +1 -0
- package/dist/client-BltmwI6G.mjs +2 -0
- package/dist/{client-BBdtbLp4.mjs → client-xnCHMO2_.mjs} +62 -8
- package/dist/client-xnCHMO2_.mjs.map +1 -0
- package/dist/{clipboard-l_TWxxTf.mjs → clipboard-CNPBTX7j.mjs} +9 -7
- package/dist/{clipboard-l_TWxxTf.mjs.map → clipboard-CNPBTX7j.mjs.map} +1 -1
- package/dist/clipboard.d.mts +6 -7
- package/dist/clipboard.d.mts.map +1 -1
- package/dist/clipboard.mjs +1 -1
- package/dist/{ctx-DjJ1zSbs.mjs → ctx-ChO3St_a.mjs} +3 -3
- package/dist/{ctx-DjJ1zSbs.mjs.map → ctx-ChO3St_a.mjs.map} +1 -1
- package/dist/ctx-DZHBHjsB.mjs +2 -0
- package/dist/{divider-cclEAdPx.mjs → divider-l0-JPEIm.mjs} +2 -2
- package/dist/{divider-cclEAdPx.mjs.map → divider-l0-JPEIm.mjs.map} +1 -1
- package/dist/{files-Aw3iWpXD.d.mts → files-BUsa-RVl.d.mts} +3 -3
- package/dist/{files-Aw3iWpXD.d.mts.map → files-BUsa-RVl.d.mts.map} +1 -1
- package/dist/{github-DS00VoOj.d.mts → github-D89A3F9U.d.mts} +3 -3
- package/dist/{github-DS00VoOj.d.mts.map → github-D89A3F9U.d.mts.map} +1 -1
- package/dist/{image-BTxDPPiT.d.mts → image-34bU73bW.d.mts} +2 -2
- package/dist/{image-BTxDPPiT.d.mts.map → image-34bU73bW.d.mts.map} +1 -1
- package/dist/image.d.mts +14 -15
- package/dist/image.d.mts.map +1 -1
- package/dist/index.d.mts +13 -13
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/{input-CRBuTrsL.mjs → input-D7fQEUdt.mjs} +3 -3
- package/dist/input-D7fQEUdt.mjs.map +1 -0
- package/dist/{input-B5Vy-iaa.d.mts → input-Dylds_sI.d.mts} +3 -3
- package/dist/input-Dylds_sI.d.mts.map +1 -0
- package/dist/{inspect-D6FW_QUo.d.mts → inspect-DPLRum7L.d.mts} +2 -2
- package/dist/{inspect-D6FW_QUo.d.mts.map → inspect-DPLRum7L.d.mts.map} +1 -1
- package/dist/{inspect-DE5goDzB.mjs → inspect-xdSq5Hjq.mjs} +3 -3
- package/dist/{inspect-DE5goDzB.mjs.map → inspect-xdSq5Hjq.mjs.map} +1 -1
- package/dist/kitty-JbCJC0iQ.mjs.map +1 -1
- package/dist/{log-Djvrxqk0.mjs → log-DrYLRdMW.mjs} +4 -4
- package/dist/{log-Djvrxqk0.mjs.map → log-DrYLRdMW.mjs.map} +1 -1
- package/dist/{logger-DDrt03So.mjs → logger-ClSgGf-a.mjs} +3 -3
- package/dist/logger-ClSgGf-a.mjs.map +1 -0
- package/dist/{markdown-CTlPe5ks.mjs → markdown-lRhc_4Cd.mjs} +7 -7
- package/dist/markdown-lRhc_4Cd.mjs.map +1 -0
- package/dist/markdown.d.mts +5 -5
- package/dist/markdown.d.mts.map +1 -1
- package/dist/markdown.mjs +1 -1
- package/dist/md.bun.d.mts +1 -2
- package/dist/md.bun.d.mts.map +1 -1
- package/dist/md.node.d.mts +1 -2
- package/dist/md.node.d.mts.map +1 -1
- package/dist/node-BZ7f6HzU.mjs.map +1 -1
- package/dist/{overlay-9xNgsuuy.mjs → overlay-9WXYiGgW.mjs} +2 -2
- package/dist/{overlay-9xNgsuuy.mjs.map → overlay-9WXYiGgW.mjs.map} +1 -1
- package/dist/{picker-cH-rc7-X.mjs → picker-BqHINl_a.mjs} +4 -4
- package/dist/picker-BqHINl_a.mjs.map +1 -0
- package/dist/{picker-D8OLb6kZ.d.mts → picker-JL8lZfRH.d.mts} +5 -5
- package/dist/{picker-D8OLb6kZ.d.mts.map → picker-JL8lZfRH.d.mts.map} +1 -1
- package/dist/queries-B_lOwEiE.mjs.map +1 -1
- package/dist/{queries-DH3bj74K.d.mts → queries-Cvalgu6P.d.mts} +3 -3
- package/dist/{queries-DH3bj74K.d.mts.map → queries-Cvalgu6P.d.mts.map} +1 -1
- package/dist/reactive-f7NpAi69.mjs.map +1 -1
- package/dist/{registry-w_w7gZr_.mjs → registry-CEpHcTa2.mjs} +2 -2
- package/dist/registry-CEpHcTa2.mjs.map +1 -0
- package/dist/{render-F8pVXN7h.mjs → render-DxIHVH9Y.mjs} +2 -2
- package/dist/{render-F8pVXN7h.mjs.map → render-DxIHVH9Y.mjs.map} +1 -1
- package/dist/{renderer-uMeDzF9B.mjs → renderer-Bz3tc2IT.mjs} +7 -7
- package/dist/renderer-Bz3tc2IT.mjs.map +1 -0
- package/dist/renderer-CuF4RYBZ.mjs +2 -0
- package/dist/{renderer-qSMVeNSV.mjs → renderer-DesbRwjQ.mjs} +2 -2
- package/dist/renderer-DesbRwjQ.mjs.map +1 -0
- package/dist/select-m7NE6Rwa.mjs.map +1 -1
- package/dist/{select-CbmAZdpt.d.mts → select-zGd5pbiB.d.mts} +3 -3
- package/dist/{select-CbmAZdpt.d.mts.map → select-zGd5pbiB.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 +3 -4
- package/dist/services/notifier.d.mts.map +1 -1
- package/dist/services/notifier.mjs +2 -2
- package/dist/services/notifier.mjs.map +1 -1
- package/dist/services/picker.d.mts +8 -9
- package/dist/services/picker.d.mts.map +1 -1
- package/dist/services/picker.mjs +10 -8
- package/dist/services/picker.mjs.map +1 -1
- package/dist/services/prompt.d.mts +8 -9
- package/dist/services/prompt.d.mts.map +1 -1
- package/dist/services/prompt.mjs +9 -7
- package/dist/services/prompt.mjs.map +1 -1
- package/dist/shiki/server.d.mts +1 -1
- package/dist/shiki/server.mjs +6 -2
- package/dist/shiki/server.mjs.map +1 -1
- package/dist/{shiki-BK-v9CtF.mjs → shiki-CcxiFWEF.mjs} +3 -3
- package/dist/{shiki-BK-v9CtF.mjs.map → shiki-CcxiFWEF.mjs.map} +1 -1
- package/dist/{shiki-B5NwIiot.mjs → shiki-D7l5--zz.mjs} +19 -5
- package/dist/shiki-D7l5--zz.mjs.map +1 -0
- package/dist/show-DR2x1YFc.mjs.map +1 -1
- package/dist/style.d.mts +7 -7
- package/dist/style.d.mts.map +1 -1
- package/dist/style.mjs +2 -2
- package/dist/{text-DILrol9j.mjs → text-BLz1tRoC.mjs} +4 -3
- package/dist/{text-DILrol9j.mjs.map → text-BLz1tRoC.mjs.map} +1 -1
- package/dist/{text-9lwQeqYr.d.mts → text-BefiXAFW.d.mts} +3 -3
- package/dist/{text-9lwQeqYr.d.mts.map → text-BefiXAFW.d.mts.map} +1 -1
- package/dist/{text-q26V6_Sc.mjs → text-CRZD9KTN.mjs} +3 -2
- package/dist/{text-q26V6_Sc.mjs.map → text-CRZD9KTN.mjs.map} +1 -1
- package/dist/text.d.mts +1 -1
- package/dist/text.mjs +1 -1
- package/dist/{theme.config-BptYUq4K.mjs → theme.config-DoW6LIcl.mjs} +250 -242
- package/dist/theme.config-DoW6LIcl.mjs.map +1 -0
- package/dist/themes.d.mts +8 -9
- package/dist/themes.d.mts.map +1 -1
- package/dist/themes.mjs +1 -1
- package/dist/tree-Bo1afYhe.mjs.map +1 -1
- package/dist/{tree-C28QOVIK.d.mts → tree-CArtDRec.d.mts} +3 -3
- package/dist/{tree-C28QOVIK.d.mts.map → tree-CArtDRec.d.mts.map} +1 -1
- package/dist/{types-B9Eh7k2v.d.mts → types-C0EOLZDc.d.mts} +7 -2
- package/dist/types-C0EOLZDc.d.mts.map +1 -0
- package/dist/{widget-M7jD8Rgg.d.mts → widget-DtJU2-BJ.d.mts} +2 -2
- package/dist/{widget-M7jD8Rgg.d.mts.map → widget-DtJU2-BJ.d.mts.map} +1 -1
- package/dist/widgets/autocomplete.d.mts +1 -1
- package/dist/widgets/autocomplete.mjs +2 -2
- package/dist/widgets/autocomplete.mjs.map +1 -1
- package/dist/widgets/box.d.mts +1 -1
- package/dist/widgets/box.mjs +1 -1
- package/dist/widgets/code.d.mts +4 -5
- package/dist/widgets/code.d.mts.map +1 -1
- package/dist/widgets/code.mjs +5 -5
- 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 +5 -6
- package/dist/widgets/diff.d.mts.map +1 -1
- package/dist/widgets/diff.mjs +3 -3
- package/dist/widgets/diff.mjs.map +1 -1
- package/dist/widgets/divider.d.mts +4 -5
- package/dist/widgets/divider.d.mts.map +1 -1
- package/dist/widgets/divider.mjs +1 -1
- package/dist/widgets/image.d.mts +1 -1
- package/dist/widgets/image.mjs +1 -1
- 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 +8 -9
- 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 +5 -6
- package/dist/widgets/progress.d.mts.map +1 -1
- package/dist/widgets/select.d.mts +1 -1
- package/dist/widgets/show.d.mts +7 -7
- package/dist/widgets/show.d.mts.map +1 -1
- package/dist/widgets/spinner.d.mts +7 -8
- package/dist/widgets/spinner.d.mts.map +1 -1
- package/dist/widgets/spinner.mjs.map +1 -1
- 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/dist/worker-T6SdPzUH.mjs.map +1 -1
- package/package.json +8 -9
- package/dist/box-DepqUtuo.mjs.map +0 -1
- package/dist/builder-DTz5mppV.mjs.map +0 -1
- package/dist/callbacks-DcMBGQEO.mjs.map +0 -1
- package/dist/client-BBdtbLp4.mjs.map +0 -1
- package/dist/client-cIckDgAj.mjs +0 -2
- package/dist/ctx-Bt4VlRPg.mjs +0 -2
- package/dist/input-B5Vy-iaa.d.mts.map +0 -1
- package/dist/input-CRBuTrsL.mjs.map +0 -1
- package/dist/logger-DDrt03So.mjs.map +0 -1
- package/dist/markdown-CTlPe5ks.mjs.map +0 -1
- package/dist/picker-cH-rc7-X.mjs.map +0 -1
- package/dist/registry-w_w7gZr_.mjs.map +0 -1
- package/dist/renderer-Dgj_qEOA.mjs +0 -2
- package/dist/renderer-qSMVeNSV.mjs.map +0 -1
- package/dist/renderer-uMeDzF9B.mjs.map +0 -1
- package/dist/shiki-B5NwIiot.mjs.map +0 -1
- package/dist/theme.config-BptYUq4K.mjs.map +0 -1
- package/dist/types-B9Eh7k2v.d.mts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-xnCHMO2_.mjs","names":[],"sources":["../src/shiki/client.ts"],"sourcesContent":["import type {\n ShikiJob,\n ShikiOpts,\n ShikiRequest,\n ShikiResult,\n ShikiWorkerMessage,\n ShikiWorkerRequest,\n} from \"./types.ts\"\nimport type { WorkerInstance } from \"./worker.ts\"\n\nimport { hash, toError } from \"@zaly/shared\"\nimport { hasColors } from \"@zaly/shared/env\"\nimport { isShikiLang } from \"../schemas/gen/shiki.ts\"\n\nfunction isJob(s: ShikiJob | ShikiResult): s is ShikiJob {\n return \"key\" in s && \"lang\" in s\n}\n\nconst MAX_CACHE_SIZE = 100\n// Max jobs posted to the worker. Worker still processes serially.\nconst MAX_RUNNING = 2\nconst REQUEST_TIMEOUT = 30_000\n\nexport class ShikiWorkerClient {\n #id = 0\n #cache = new Map<string, ShikiJob>()\n #queue = new Map<number, ShikiJob>()\n #running = new Map<number, ShikiJob>()\n #results: ShikiResult[] = []\n #timeouts = new Map<number, ReturnType<typeof setTimeout>>()\n #worker?: WorkerInstance<ShikiWorkerRequest, ShikiWorkerMessage>\n #workerPromise?: Promise<WorkerInstance<ShikiWorkerRequest, ShikiWorkerMessage>>\n #timeout: number\n #updateScheduled: Promise<void> | undefined = undefined\n #updatePending = false\n\n constructor(opts: { timeout?: number } = {}) {\n this.#timeout = opts.timeout ?? REQUEST_TIMEOUT\n }\n\n key(req: ShikiRequest): string {\n return req.key ?? hash(`${req.lang}:${req.code}:${req.theme ?? \"default\"}`)\n }\n\n toJob(req: ShikiRequest): ShikiJob | ShikiResult {\n const id = ++this.#id\n const key = this.key(req)\n if (!hasColors) return { error: \"terminal does not support colors\", id, key, value: req.code }\n if (!isShikiLang(req.lang))\n return { error: `unsupported language: ${req.lang}`, id, key, value: req.code }\n const cached = this.#cache.get(key)\n if (cached) {\n this.#cache.delete(key)\n this.#cache.set(key, cached) // bump to end of LRU\n return cached\n }\n while (this.#cache.size > MAX_CACHE_SIZE) this.#cache.delete(this.#cache.keys().next().value!)\n const ret: ShikiJob = { ...req, id, key, lang: req.lang, ...Promise.withResolvers() }\n this.#cache.set(key, ret)\n return ret\n }\n\n highlight(code: string, lang: string, opts: ShikiOpts = {}): Promise<ShikiResult> {\n const req: ShikiRequest = { code, lang, signal: opts.signal, theme: opts.theme }\n const job = this.toJob(req)\n if (!isJob(job)) return Promise.resolve(job)\n if (!job.scheduled) {\n this.#queue.set(job.id, job)\n job.signal?.addEventListener(\"abort\", () => this.update(), { once: true })\n this.update()\n }\n return job.promise\n }\n\n dispose(): void {\n const error = new Error(\"Shiki worker disposed\")\n this.#rejectAll(error)\n }\n\n async #request(job: ShikiJob): Promise<void> {\n job.scheduled = true\n this.#running.set(job.id, job)\n const worker = await this.#createWorker()\n const { signal: _s, promise: _prom, resolve: _res, reject: _rej, ...msg } = job\n const timeout = setTimeout(\n () =>\n this.#fail(\n new Error(`Shiki worker timed out after ${this.#timeout}ms (${job.lang}, ${job.key})`)\n ),\n this.#timeout\n )\n timeout.unref()\n this.#timeouts.set(job.id, timeout)\n // oxlint-disable-next-line unicorn/require-post-message-target-origin\n worker.postMessage(msg)\n }\n\n async #createWorker(): Promise<WorkerInstance<ShikiWorkerRequest, ShikiWorkerMessage>> {\n if (this.#worker) return this.#worker\n this.#workerPromise ??= (async () => {\n const { createWorker } = await import(\"./worker.ts\")\n const worker = await createWorker<ShikiWorkerRequest, ShikiWorkerMessage>()\n const ready = Promise.withResolvers<void>()\n let started = false\n const timeout = setTimeout(\n () => ready.reject(new Error(`Shiki worker did not start within ${this.#timeout}ms`)),\n this.#timeout\n )\n timeout.unref()\n worker.on(\"message\", (event) => {\n if (event.type === \"ready\") {\n started = true\n ready.resolve()\n return\n }\n this.#clearTimeout(event.id)\n this.#running.delete(event.id)\n this.#results.push(event)\n this.update()\n })\n worker.on(\"error\", (error) => {\n if (started) this.#fail(error)\n else ready.reject(error)\n })\n try {\n await ready.promise\n return worker\n } catch (error) {\n worker.terminate()\n throw error\n } finally {\n clearTimeout(timeout)\n }\n })()\n return (this.#worker = await this.#workerPromise)\n }\n\n update() {\n this.#updatePending = true\n if (this.#updateScheduled) return\n this.#updateScheduled = (async () => {\n while (this.#updatePending) {\n this.#updatePending = false\n // oxlint-disable-next-line no-await-in-loop\n await this.#update()\n }\n })()\n .catch((error) => this.#fail(error))\n .finally(() => {\n this.#updateScheduled = undefined\n if (this.#updatePending) this.update()\n })\n }\n\n async #update() {\n // Resolve pending results\n while (this.#results.length) {\n const result = this.#results.shift()!\n const job = this.#queue.get(result.id)\n if (job) {\n if (result.error) {\n const error = new Error(result.error)\n // oxlint-disable-next-line no-console\n console.error(\"Shiki highlighting failed:\", error)\n job.reject(error)\n } else job.resolve(result)\n\n // oxlint-disable-next-line no-await-in-loop\n await new Promise((resolve) => setImmediate(resolve)) // yield to event loop between batches\n this.#queue.delete(job.id)\n }\n }\n\n // Clean up aborted jobs\n for (const job of this.#queue.values()) {\n if (job.signal?.aborted && !job.scheduled) {\n job.reject(new Error(\"Job aborted\"))\n this.#queue.delete(job.id)\n this.#cache.delete(job.key)\n }\n }\n\n if (this.#running.size >= MAX_RUNNING || this.#queue.size === 0) return\n\n // Schedule new jobs up to concurrency limit, prioritizing the most recently requested ones (LIFO)\n const todo = [...this.#queue.values()]\n .filter((j) => !j.scheduled)\n .slice(-(MAX_RUNNING - this.#running.size))\n await Promise.all(todo.map((j) => this.#request(j)))\n }\n\n #clearTimeout(id: number): void {\n const timeout = this.#timeouts.get(id)\n if (timeout) clearTimeout(timeout)\n this.#timeouts.delete(id)\n }\n\n #fail(error: unknown): void {\n error = toError(error)\n // oxlint-disable-next-line no-console\n console.error(\"Shiki worker failed:\", error)\n this.#rejectAll(error)\n }\n\n #rejectAll(error: unknown): void {\n for (const { reject } of this.#queue.values()) reject(error)\n this.#cache.clear()\n this.#queue.clear()\n this.#running.clear()\n this.#results = []\n for (const timeout of this.#timeouts.values()) clearTimeout(timeout)\n this.#timeouts.clear()\n this.#updatePending = false\n this.#worker?.terminate()\n this.#worker = undefined\n this.#workerPromise = undefined\n }\n}\n\nexport const shikiWorker = new ShikiWorkerClient()\n"],"mappings":"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"}
|
|
@@ -337,15 +337,16 @@ async function windowsText() {
|
|
|
337
337
|
}
|
|
338
338
|
async function windowsImage() {
|
|
339
339
|
const tmp = writeTempPath("zaly-clip-", ".png");
|
|
340
|
+
const script = [
|
|
341
|
+
"Add-Type -AssemblyName System.Windows.Forms",
|
|
342
|
+
"$img = [System.Windows.Forms.Clipboard]::GetImage()",
|
|
343
|
+
`if ($img) { $img.Save('${tmp.replace(/\\/g, String.raw`\\`)}') }`
|
|
344
|
+
].join("; ");
|
|
340
345
|
await spawnText("powershell", [
|
|
341
346
|
"-NoProfile",
|
|
342
347
|
"-NoLogo",
|
|
343
348
|
"-Command",
|
|
344
|
-
|
|
345
|
-
"Add-Type -AssemblyName System.Windows.Forms",
|
|
346
|
-
"$img = [System.Windows.Forms.Clipboard]::GetImage()",
|
|
347
|
-
`if ($img) { $img.Save('${tmp.replace(/\\/g, String.raw`\\`)}') }`
|
|
348
|
-
].join("; ")
|
|
349
|
+
script
|
|
349
350
|
]);
|
|
350
351
|
if ((safeStat(tmp)?.size ?? 0) > 0) return {
|
|
351
352
|
kind: "image",
|
|
@@ -396,9 +397,10 @@ function parseUriList(raw) {
|
|
|
396
397
|
return out;
|
|
397
398
|
}
|
|
398
399
|
function writeTempPath(prefix, ext) {
|
|
399
|
-
|
|
400
|
+
const dir = mkdtempSync(join(tmpdir(), prefix));
|
|
401
|
+
return join(dir, `clip${ext}`);
|
|
400
402
|
}
|
|
401
403
|
//#endregion
|
|
402
404
|
export { clipboard as t };
|
|
403
405
|
|
|
404
|
-
//# sourceMappingURL=clipboard-
|
|
406
|
+
//# sourceMappingURL=clipboard-CNPBTX7j.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard-l_TWxxTf.mjs","names":[],"sources":["../src/input/clipboard.ts"],"sourcesContent":["import { safeStat } from \"@zaly/shared\"\nimport { isSSH } from \"@zaly/shared/env\"\nimport { Spawn, spawnText, spawnWithInput, which } from \"@zaly/shared/process\"\nimport { mkdtempSync, writeFileSync } from \"node:fs\"\nimport { tmpdir } from \"node:os\"\nimport { platform } from \"node:process\"\nimport { join } from \"pathe\"\n\n/**\n * Read text or image content from the system clipboard.\n *\n * Agent CLIs need this to make `ctrl-v` \"just work\" — most terminals\n * don't forward clipboard paste events (they only forward typed keys),\n * so the app has to query the OS clipboard itself via the platform's\n * native tool. The detection order mirrors Neovim's clipboard provider:\n *\n * 1. macOS → `pbpaste` + `osascript` (for images)\n * 2. Wayland → `wl-paste`\n * 3. X11 (xsel) → `xsel`\n * 4. X11 (xclip) → `xclip`\n * 5. WSL → `win32yank.exe`\n * 6. Windows → PowerShell `Get-Clipboard`\n *\n * The chosen provider is cached per process. Spawn primitives live in\n * `@zaly/shared/process` — this file is just glue plus the per-platform\n * AppleScript/PowerShell snippets.\n */\n\n// ---- types -----------------------------------------------------------\n\n/** Image bytes on the clipboard, already written to a temp PNG. */\nexport interface ClipboardImage {\n kind: \"image\"\n /** Absolute path to a temporary PNG file. Caller takes ownership. */\n path: string\n /** MIME type. PNG only for now; kept for future formats. */\n type: \"image/png\"\n}\n\n/** One or more file references on the clipboard — what you get when\n * the user copies a file in their file manager and pastes. */\nexport interface ClipboardFiles {\n kind: \"files\"\n /** Absolute filesystem paths. */\n paths: string[]\n}\n\n/** Plain text on the clipboard — the common case. */\nexport interface ClipboardText {\n kind: \"text\"\n text: string\n}\n\n/** Anything the clipboard can hold that this library surfaces. */\nexport type ClipboardContent = ClipboardImage | ClipboardFiles | ClipboardText\n\n/** One of the content kinds `ClipboardContent` can take. Derived from\n * the union so adding a new variant doesn't require updating this\n * alias separately. */\nexport type ClipboardKind = ClipboardContent[\"kind\"]\n\n/** Internal provider contract. Each backend owns its own \"probe types,\n * pick best, fetch once\" logic — on platforms like Wayland and X11\n * that can enumerate available types, this avoids doing three or four\n * probe round-trips for every paste.\n *\n * `read(kind?)` takes an optional hint: when specified, the backend\n * can skip type enumeration and fetch that kind directly (fast path\n * for callers that already know what they want). When omitted, the\n * backend returns the richest available content. `writeText` is\n * optional since not every backend supports writes. */\ninterface Provider {\n readonly id: string\n read: (kind?: ClipboardKind) => Promise<ClipboardContent | undefined>\n writeText?: (text: string) => Promise<boolean>\n}\n\n// ---- public API ------------------------------------------------------\n\nlet cached: Provider | undefined\nlet cacheResolved = false\n\n/** Detect + cache the clipboard provider for this process. Returns\n * `undefined` when no provider is available. */\nfunction getClipboard(): Provider | undefined {\n if (cacheResolved) return cached\n cached = detect()\n cacheResolved = true\n return cached\n}\n\n/**\n * Read the system clipboard, returning the richest content available.\n *\n * Priority order (decided by each backend internally):\n * 1. **image** — raw image bytes on the clipboard (e.g. a screenshot\n * from `cmd-shift-4`, or an image copied from a web page).\n * 2. **files** — file URIs (e.g. the user copied a PDF / video in\n * their file manager).\n * 3. **text** — plain text.\n *\n * Resolves to `undefined` when the clipboard is empty, no provider is\n * available, or every read fails. Never throws — clipboard access is\n * best-effort.\n */\nasync function readClipboard(): Promise<ClipboardContent | undefined>\nasync function readClipboard(kind: \"text\"): Promise<ClipboardText | undefined>\nasync function readClipboard(kind: \"image\"): Promise<ClipboardImage | undefined>\nasync function readClipboard(kind: \"files\"): Promise<ClipboardFiles | undefined>\nasync function readClipboard(kind?: ClipboardKind): Promise<ClipboardContent | undefined> {\n const p = getClipboard()\n if (!p) return undefined\n try {\n return await p.read(kind)\n } catch {\n return undefined\n }\n}\n\n/** Reset the cached provider — mostly for tests that want to force a\n * re-probe. Also useful if the environment changes (e.g. Wayland\n * display started after process boot). */\nfunction resetClipboardCache(): void {\n cached = undefined\n cacheResolved = false\n}\n\n/**\n * Copy text to the system clipboard.\n *\n * Policy:\n * - **SSH session** → always OSC 52. Native tools on the remote box\n * would write to the remote clipboard, which isn't what the user\n * wants. OSC 52 routes through the local terminal.\n * - **Native tool available** → use it (fast, silent, no prompts).\n * - **Neither** → OSC 52 anyway, fire-and-forget.\n *\n * Resolves to `true` on best-effort delivery; `false` only when we had\n * nothing to try. OSC 52 writes are silent by design — the terminal\n * never confirms receipt — so `true` means \"we emitted\" not \"the\n * user's clipboard definitely has it\".\n */\nasync function writeClipboardText(text: string): Promise<boolean> {\n if (isSSH) {\n writeOsc52(text)\n return true\n }\n const p = getClipboard()\n if (p?.writeText) {\n try {\n if (await p.writeText(text)) return true\n } catch {\n /* fall through to OSC 52 */\n }\n }\n writeOsc52(text)\n return true\n}\n\n/**\n * Namespace export for readable call sites:\n *\n * ```ts\n * import { clipboard } from \"@zaly/tui\"\n *\n * await clipboard.read()\n * await clipboard.read(\"text\")\n * await clipboard.write(\"hello\")\n * clipboard.reset()\n * ```\n */\nexport const clipboard = {\n read: readClipboard,\n reset: resetClipboardCache,\n write: writeClipboardText,\n}\n\n/** Emit an OSC 52 clipboard write. Fire-and-forget; some terminals\n * ignore or prompt on this, and there's no response channel. */\nfunction writeOsc52(text: string): void {\n const b64 = Buffer.from(text, \"utf8\").toString(\"base64\")\n // `\\x1b]52;c;<base64>\\x07` — `c` targets the system clipboard.\n process.stdout.write(`\\x1b]52;c;${b64}\\x07`)\n}\n\n// ---- detection -------------------------------------------------------\n\nfunction detect(): Provider | undefined {\n if (platform === \"darwin\" && which(\"pbpaste\")) return macos()\n\n // Wayland before X11 — XWayland means both vars can be set on a\n // Wayland session, and wl-paste is the right tool there.\n if (process.env.WAYLAND_DISPLAY && which(\"wl-paste\")) return wayland()\n\n // X11: prefer xsel (nicer selection handling, per Neovim), then xclip.\n if (process.env.DISPLAY) {\n if (which(\"xsel\")) return xsel()\n if (which(\"xclip\")) return xclip()\n }\n\n // WSL exposes Windows' clipboard via win32yank if the user installed it.\n if (which(\"win32yank.exe\")) return wsl()\n\n // Plain Windows: PowerShell is always present on supported versions.\n if (platform === \"win32\") return windows()\n\n return undefined\n}\n\n// ---- backends --------------------------------------------------------\n\nfunction macos(): Provider {\n return {\n id: \"pbpaste\",\n read: async (kind) => {\n // macOS has no cheap \"list types\" call, so when no kind is\n // specified we probe in richness order: image → files → text.\n // Each AppleScript is wrapped in `try…on error` so a miss is\n // an empty string, not a spawn failure.\n if (kind === \"image\") return macosImage()\n if (kind === \"files\") return macosFiles()\n if (kind === \"text\") return macosText()\n const img = await macosImage()\n if (img) return img\n const files = await macosFiles()\n if (files) return files\n return macosText()\n },\n writeText: (text) => spawnWithInput(\"pbcopy\", [], text),\n }\n}\n\nasync function macosText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"pbpaste\", [])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nasync function macosImage(): Promise<ClipboardImage | undefined> {\n const script = `\n try\n set png to (the clipboard as «class PNGf»)\n set b64 to do shell script \"base64\" with input (png as string)\n return b64\n on error\n return \"\"\n end try\n `\n const out = await spawnText(\"osascript\", [\"-e\", script])\n if (!out) return undefined\n return writeTempPng(Buffer.from(out.trim(), \"base64\"))\n}\n\nasync function macosFiles(): Promise<ClipboardFiles | undefined> {\n const script = `\n try\n set theClipboard to the clipboard as «class furl»\n return POSIX path of theClipboard\n on error\n try\n set theList to the clipboard as list\n set posix to \"\"\n repeat with item_ in theList\n try\n set posix to posix & (POSIX path of item_) & linefeed\n end try\n end repeat\n return posix\n on error\n return \"\"\n end try\n end try\n `\n const out = await spawnText(\"osascript\", [\"-e\", script])\n if (!out) return undefined\n const paths = out\n .split(/\\r?\\n/)\n .map((s) => s.trim())\n .filter((s) => s !== \"\")\n return paths.length > 0 ? { kind: \"files\", paths } : undefined\n}\n\nfunction wayland(): Provider {\n return {\n id: \"wl-paste\",\n read: async (kind) => {\n if (kind === \"image\") return waylandImage()\n if (kind === \"files\") return waylandFiles()\n if (kind === \"text\") return waylandText()\n // Richest-first: one `--list-types` call decides everything.\n const types = await spawnText(\"wl-paste\", [\"--list-types\"])\n if (!types) return undefined\n if (/\\bimage\\/png\\b/.test(types)) {\n const img = await waylandImage()\n if (img) return img\n }\n if (/\\btext\\/uri-list\\b/.test(types)) {\n const files = await waylandFiles()\n if (files) return files\n }\n return waylandText()\n },\n writeText: (text) => spawnWithInput(\"wl-copy\", [\"--type\", \"text/plain\"], text),\n }\n}\n\nasync function waylandImage(): Promise<ClipboardImage | undefined> {\n const r = await new Spawn(\"wl-paste\", [\"--type\", \"image/png\"]).result\n return r.code === 0 && r.stdout.length > 0 ? writeTempPng(r.stdout) : undefined\n}\n\nasync function waylandFiles(): Promise<ClipboardFiles | undefined> {\n const paths = parseUriList(await spawnText(\"wl-paste\", [\"--type\", \"text/uri-list\"]))\n return paths.length > 0 ? { kind: \"files\", paths } : undefined\n}\n\nasync function waylandText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"wl-paste\", [\"--no-newline\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nfunction xsel(): Provider {\n // xsel doesn't support MIME-typed targets (no image or file-list\n // reads). When xclip is also installed, delegate non-text reads to\n // it and keep xsel for text only.\n const xclipFallback = which(\"xclip\")\n return {\n id: xclipFallback ? \"xsel+xclip\" : \"xsel\",\n read: async (kind) => {\n if (kind === \"text\") return xselText()\n if (xclipFallback) {\n if (kind === \"image\") return xclipImage()\n if (kind === \"files\") return xclipFiles()\n const rich = await xclipRead()\n if (rich && rich.kind !== \"text\") return rich\n }\n return xselText()\n },\n writeText: (text) => spawnWithInput(\"xsel\", [\"--nodetach\", \"-i\", \"-b\"], text),\n }\n}\n\nfunction xclip(): Provider {\n return {\n id: \"xclip\",\n read: (kind) => {\n if (kind === \"image\") return xclipImage()\n if (kind === \"files\") return xclipFiles()\n if (kind === \"text\") return xclipText()\n return xclipRead()\n },\n writeText: (text) => spawnWithInput(\"xclip\", [\"-quiet\", \"-i\", \"-selection\", \"clipboard\"], text),\n }\n}\n\nasync function xclipRead(): Promise<ClipboardContent | undefined> {\n // One TARGETS call covers the whole decision tree.\n const targets = await spawnText(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"TARGETS\", \"-o\"])\n if (!targets) return undefined\n if (/\\bimage\\/png\\b/.test(targets)) {\n const img = await xclipImage()\n if (img) return img\n }\n if (/\\btext\\/uri-list\\b/.test(targets)) {\n const files = await xclipFiles()\n if (files) return files\n }\n return xclipText()\n}\n\nasync function xclipImage(): Promise<ClipboardImage | undefined> {\n const r = await new Spawn(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"image/png\", \"-o\"]).result\n return r.code === 0 && r.stdout.length > 0 ? writeTempPng(r.stdout) : undefined\n}\n\nasync function xclipFiles(): Promise<ClipboardFiles | undefined> {\n const paths = parseUriList(\n await spawnText(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"text/uri-list\", \"-o\"])\n )\n return paths.length > 0 ? { kind: \"files\", paths } : undefined\n}\n\nasync function xclipText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"xclip\", [\"-o\", \"-selection\", \"clipboard\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nasync function xselText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"xsel\", [\"-o\", \"-b\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nfunction wsl(): Provider {\n // win32yank is text-only; image / file paste from WSL would need a\n // different shim, so we only expose text here. `kind === \"image\"`\n // or `\"files\"` always resolves to undefined.\n return {\n id: \"win32yank\",\n read: async (kind) => {\n if (kind === \"image\" || kind === \"files\") return undefined\n const text = await spawnText(\"win32yank.exe\", [\"-o\", \"--lf\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n },\n writeText: (text) => spawnWithInput(\"win32yank.exe\", [\"-i\", \"--crlf\"], text),\n }\n}\n\nfunction windows(): Provider {\n return {\n id: \"powershell\",\n read: async (kind) => {\n if (kind === \"image\") return windowsImage()\n if (kind === \"files\") return windowsFiles()\n if (kind === \"text\") return windowsText()\n const img = await windowsImage()\n if (img) return img\n const files = await windowsFiles()\n if (files) return files\n return windowsText()\n },\n writeText: (text) => spawnWithInput(\"clip\", [], text),\n }\n}\n\nasync function windowsText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"powershell\", [\"-NoProfile\", \"-NoLogo\", \"-Command\", \"Get-Clipboard\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nasync function windowsImage(): Promise<ClipboardImage | undefined> {\n // PowerShell: fetch image from clipboard, save as PNG to a temp path.\n // Nothing on clipboard → the `if` skips and the file stays empty.\n const tmp = writeTempPath(\"zaly-clip-\", \".png\")\n const script = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n \"$img = [System.Windows.Forms.Clipboard]::GetImage()\",\n `if ($img) { $img.Save('${tmp.replace(/\\\\/g, String.raw`\\\\`)}') }`,\n ].join(\"; \")\n await spawnText(\"powershell\", [\"-NoProfile\", \"-NoLogo\", \"-Command\", script])\n if ((safeStat(tmp)?.size ?? 0) > 0) return { kind: \"image\", path: tmp, type: \"image/png\" }\n return undefined\n}\n\nasync function windowsFiles(): Promise<ClipboardFiles | undefined> {\n const out = await spawnText(\"powershell\", [\n \"-NoProfile\",\n \"-NoLogo\",\n \"-Command\",\n \"Get-Clipboard -Format FileDropList | ForEach-Object { $_.FullName }\",\n ])\n if (!out) return undefined\n const paths = out\n .split(/\\r?\\n/)\n .map((s) => s.trim())\n .filter((s) => s !== \"\")\n return paths.length > 0 ? { kind: \"files\", paths } : undefined\n}\n\n// ---- temp files + URI list parsing ----------------------------------\n\nfunction writeTempPng(bytes: Buffer): ClipboardImage {\n const path = writeTempPath(\"zaly-clip-\", \".png\")\n writeFileSync(path, bytes)\n return { kind: \"image\", path, type: \"image/png\" }\n}\n\n/** Parse a `text/uri-list` blob (RFC 2483): `file://…\\r\\n` lines, skip\n * blanks and comment lines (`#…`), decode percent-encoding. Returns\n * absolute filesystem paths. Non-`file://` URIs are dropped — we\n * can't hand a remote URL off as an attachment path. */\nfunction parseUriList(raw: string | undefined): string[] {\n if (!raw) return []\n const out: string[] = []\n for (const line of raw.split(/\\r?\\n/)) {\n const s = line.trim()\n if (s === \"\" || s.startsWith(\"#\")) continue\n if (!s.startsWith(\"file://\")) continue\n try {\n let path = decodeURIComponent(s.slice(\"file://\".length))\n // `file:///C:/foo` → `/C:/foo` after the slice. Strip the leading\n // slash so we end up with a real Windows path.\n if (/^\\/[A-Za-z]:\\//.test(path)) path = path.slice(1)\n out.push(path)\n } catch {\n /* malformed URI — skip */\n }\n }\n return out\n}\n\nfunction writeTempPath(prefix: string, ext: string): string {\n const dir = mkdtempSync(join(tmpdir(), prefix))\n return join(dir, `clip${ext}`)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"clipboard-CNPBTX7j.mjs","names":[],"sources":["../src/input/clipboard.ts"],"sourcesContent":["import { safeStat } from \"@zaly/shared\"\nimport { isSSH } from \"@zaly/shared/env\"\nimport { Spawn, spawnText, spawnWithInput, which } from \"@zaly/shared/process\"\nimport { mkdtempSync, writeFileSync } from \"node:fs\"\nimport { tmpdir } from \"node:os\"\nimport { platform } from \"node:process\"\nimport { join } from \"pathe\"\n\n/**\n * Read text or image content from the system clipboard.\n *\n * Agent CLIs need this to make `ctrl-v` \"just work\" — most terminals\n * don't forward clipboard paste events (they only forward typed keys),\n * so the app has to query the OS clipboard itself via the platform's\n * native tool. The detection order mirrors Neovim's clipboard provider:\n *\n * 1. macOS → `pbpaste` + `osascript` (for images)\n * 2. Wayland → `wl-paste`\n * 3. X11 (xsel) → `xsel`\n * 4. X11 (xclip) → `xclip`\n * 5. WSL → `win32yank.exe`\n * 6. Windows → PowerShell `Get-Clipboard`\n *\n * The chosen provider is cached per process. Spawn primitives live in\n * `@zaly/shared/process` — this file is just glue plus the per-platform\n * AppleScript/PowerShell snippets.\n */\n\n// ---- types -----------------------------------------------------------\n\n/** Image bytes on the clipboard, already written to a temp PNG. */\nexport interface ClipboardImage {\n kind: \"image\"\n /** Absolute path to a temporary PNG file. Caller takes ownership. */\n path: string\n /** MIME type. PNG only for now; kept for future formats. */\n type: \"image/png\"\n}\n\n/** One or more file references on the clipboard — what you get when\n * the user copies a file in their file manager and pastes. */\nexport interface ClipboardFiles {\n kind: \"files\"\n /** Absolute filesystem paths. */\n paths: string[]\n}\n\n/** Plain text on the clipboard — the common case. */\nexport interface ClipboardText {\n kind: \"text\"\n text: string\n}\n\n/** Anything the clipboard can hold that this library surfaces. */\nexport type ClipboardContent = ClipboardImage | ClipboardFiles | ClipboardText\n\n/** One of the content kinds `ClipboardContent` can take. Derived from\n * the union so adding a new variant doesn't require updating this\n * alias separately. */\nexport type ClipboardKind = ClipboardContent[\"kind\"]\n\n/** Internal provider contract. Each backend owns its own \"probe types,\n * pick best, fetch once\" logic — on platforms like Wayland and X11\n * that can enumerate available types, this avoids doing three or four\n * probe round-trips for every paste.\n *\n * `read(kind?)` takes an optional hint: when specified, the backend\n * can skip type enumeration and fetch that kind directly (fast path\n * for callers that already know what they want). When omitted, the\n * backend returns the richest available content. `writeText` is\n * optional since not every backend supports writes. */\ninterface Provider {\n readonly id: string\n read: (kind?: ClipboardKind) => Promise<ClipboardContent | undefined>\n writeText?: (text: string) => Promise<boolean>\n}\n\n// ---- public API ------------------------------------------------------\n\nlet cached: Provider | undefined\nlet cacheResolved = false\n\n/** Detect + cache the clipboard provider for this process. Returns\n * `undefined` when no provider is available. */\nfunction getClipboard(): Provider | undefined {\n if (cacheResolved) return cached\n cached = detect()\n cacheResolved = true\n return cached\n}\n\n/**\n * Read the system clipboard, returning the richest content available.\n *\n * Priority order (decided by each backend internally):\n * 1. **image** — raw image bytes on the clipboard (e.g. a screenshot\n * from `cmd-shift-4`, or an image copied from a web page).\n * 2. **files** — file URIs (e.g. the user copied a PDF / video in\n * their file manager).\n * 3. **text** — plain text.\n *\n * Resolves to `undefined` when the clipboard is empty, no provider is\n * available, or every read fails. Never throws — clipboard access is\n * best-effort.\n */\nasync function readClipboard(): Promise<ClipboardContent | undefined>\nasync function readClipboard(kind: \"text\"): Promise<ClipboardText | undefined>\nasync function readClipboard(kind: \"image\"): Promise<ClipboardImage | undefined>\nasync function readClipboard(kind: \"files\"): Promise<ClipboardFiles | undefined>\nasync function readClipboard(kind?: ClipboardKind): Promise<ClipboardContent | undefined> {\n const p = getClipboard()\n if (!p) return undefined\n try {\n return await p.read(kind)\n } catch {\n return undefined\n }\n}\n\n/** Reset the cached provider — mostly for tests that want to force a\n * re-probe. Also useful if the environment changes (e.g. Wayland\n * display started after process boot). */\nfunction resetClipboardCache(): void {\n cached = undefined\n cacheResolved = false\n}\n\n/**\n * Copy text to the system clipboard.\n *\n * Policy:\n * - **SSH session** → always OSC 52. Native tools on the remote box\n * would write to the remote clipboard, which isn't what the user\n * wants. OSC 52 routes through the local terminal.\n * - **Native tool available** → use it (fast, silent, no prompts).\n * - **Neither** → OSC 52 anyway, fire-and-forget.\n *\n * Resolves to `true` on best-effort delivery; `false` only when we had\n * nothing to try. OSC 52 writes are silent by design — the terminal\n * never confirms receipt — so `true` means \"we emitted\" not \"the\n * user's clipboard definitely has it\".\n */\nasync function writeClipboardText(text: string): Promise<boolean> {\n if (isSSH) {\n writeOsc52(text)\n return true\n }\n const p = getClipboard()\n if (p?.writeText) {\n try {\n if (await p.writeText(text)) return true\n } catch {\n /* fall through to OSC 52 */\n }\n }\n writeOsc52(text)\n return true\n}\n\n/**\n * Namespace export for readable call sites:\n *\n * ```ts\n * import { clipboard } from \"@zaly/tui\"\n *\n * await clipboard.read()\n * await clipboard.read(\"text\")\n * await clipboard.write(\"hello\")\n * clipboard.reset()\n * ```\n */\nexport const clipboard = {\n read: readClipboard,\n reset: resetClipboardCache,\n write: writeClipboardText,\n}\n\n/** Emit an OSC 52 clipboard write. Fire-and-forget; some terminals\n * ignore or prompt on this, and there's no response channel. */\nfunction writeOsc52(text: string): void {\n const b64 = Buffer.from(text, \"utf8\").toString(\"base64\")\n // `\\x1b]52;c;<base64>\\x07` — `c` targets the system clipboard.\n process.stdout.write(`\\x1b]52;c;${b64}\\x07`)\n}\n\n// ---- detection -------------------------------------------------------\n\nfunction detect(): Provider | undefined {\n if (platform === \"darwin\" && which(\"pbpaste\")) return macos()\n\n // Wayland before X11 — XWayland means both vars can be set on a\n // Wayland session, and wl-paste is the right tool there.\n if (process.env.WAYLAND_DISPLAY && which(\"wl-paste\")) return wayland()\n\n // X11: prefer xsel (nicer selection handling, per Neovim), then xclip.\n if (process.env.DISPLAY) {\n if (which(\"xsel\")) return xsel()\n if (which(\"xclip\")) return xclip()\n }\n\n // WSL exposes Windows' clipboard via win32yank if the user installed it.\n if (which(\"win32yank.exe\")) return wsl()\n\n // Plain Windows: PowerShell is always present on supported versions.\n if (platform === \"win32\") return windows()\n\n return undefined\n}\n\n// ---- backends --------------------------------------------------------\n\nfunction macos(): Provider {\n return {\n id: \"pbpaste\",\n read: async (kind) => {\n // macOS has no cheap \"list types\" call, so when no kind is\n // specified we probe in richness order: image → files → text.\n // Each AppleScript is wrapped in `try…on error` so a miss is\n // an empty string, not a spawn failure.\n if (kind === \"image\") return macosImage()\n if (kind === \"files\") return macosFiles()\n if (kind === \"text\") return macosText()\n const img = await macosImage()\n if (img) return img\n const files = await macosFiles()\n if (files) return files\n return macosText()\n },\n writeText: (text) => spawnWithInput(\"pbcopy\", [], text),\n }\n}\n\nasync function macosText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"pbpaste\", [])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nasync function macosImage(): Promise<ClipboardImage | undefined> {\n const script = `\n try\n set png to (the clipboard as «class PNGf»)\n set b64 to do shell script \"base64\" with input (png as string)\n return b64\n on error\n return \"\"\n end try\n `\n const out = await spawnText(\"osascript\", [\"-e\", script])\n if (!out) return undefined\n return writeTempPng(Buffer.from(out.trim(), \"base64\"))\n}\n\nasync function macosFiles(): Promise<ClipboardFiles | undefined> {\n const script = `\n try\n set theClipboard to the clipboard as «class furl»\n return POSIX path of theClipboard\n on error\n try\n set theList to the clipboard as list\n set posix to \"\"\n repeat with item_ in theList\n try\n set posix to posix & (POSIX path of item_) & linefeed\n end try\n end repeat\n return posix\n on error\n return \"\"\n end try\n end try\n `\n const out = await spawnText(\"osascript\", [\"-e\", script])\n if (!out) return undefined\n const paths = out\n .split(/\\r?\\n/)\n .map((s) => s.trim())\n .filter((s) => s !== \"\")\n return paths.length > 0 ? { kind: \"files\", paths } : undefined\n}\n\nfunction wayland(): Provider {\n return {\n id: \"wl-paste\",\n read: async (kind) => {\n if (kind === \"image\") return waylandImage()\n if (kind === \"files\") return waylandFiles()\n if (kind === \"text\") return waylandText()\n // Richest-first: one `--list-types` call decides everything.\n const types = await spawnText(\"wl-paste\", [\"--list-types\"])\n if (!types) return undefined\n if (/\\bimage\\/png\\b/.test(types)) {\n const img = await waylandImage()\n if (img) return img\n }\n if (/\\btext\\/uri-list\\b/.test(types)) {\n const files = await waylandFiles()\n if (files) return files\n }\n return waylandText()\n },\n writeText: (text) => spawnWithInput(\"wl-copy\", [\"--type\", \"text/plain\"], text),\n }\n}\n\nasync function waylandImage(): Promise<ClipboardImage | undefined> {\n const r = await new Spawn(\"wl-paste\", [\"--type\", \"image/png\"]).result\n return r.code === 0 && r.stdout.length > 0 ? writeTempPng(r.stdout) : undefined\n}\n\nasync function waylandFiles(): Promise<ClipboardFiles | undefined> {\n const paths = parseUriList(await spawnText(\"wl-paste\", [\"--type\", \"text/uri-list\"]))\n return paths.length > 0 ? { kind: \"files\", paths } : undefined\n}\n\nasync function waylandText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"wl-paste\", [\"--no-newline\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nfunction xsel(): Provider {\n // xsel doesn't support MIME-typed targets (no image or file-list\n // reads). When xclip is also installed, delegate non-text reads to\n // it and keep xsel for text only.\n const xclipFallback = which(\"xclip\")\n return {\n id: xclipFallback ? \"xsel+xclip\" : \"xsel\",\n read: async (kind) => {\n if (kind === \"text\") return xselText()\n if (xclipFallback) {\n if (kind === \"image\") return xclipImage()\n if (kind === \"files\") return xclipFiles()\n const rich = await xclipRead()\n if (rich && rich.kind !== \"text\") return rich\n }\n return xselText()\n },\n writeText: (text) => spawnWithInput(\"xsel\", [\"--nodetach\", \"-i\", \"-b\"], text),\n }\n}\n\nfunction xclip(): Provider {\n return {\n id: \"xclip\",\n read: (kind) => {\n if (kind === \"image\") return xclipImage()\n if (kind === \"files\") return xclipFiles()\n if (kind === \"text\") return xclipText()\n return xclipRead()\n },\n writeText: (text) => spawnWithInput(\"xclip\", [\"-quiet\", \"-i\", \"-selection\", \"clipboard\"], text),\n }\n}\n\nasync function xclipRead(): Promise<ClipboardContent | undefined> {\n // One TARGETS call covers the whole decision tree.\n const targets = await spawnText(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"TARGETS\", \"-o\"])\n if (!targets) return undefined\n if (/\\bimage\\/png\\b/.test(targets)) {\n const img = await xclipImage()\n if (img) return img\n }\n if (/\\btext\\/uri-list\\b/.test(targets)) {\n const files = await xclipFiles()\n if (files) return files\n }\n return xclipText()\n}\n\nasync function xclipImage(): Promise<ClipboardImage | undefined> {\n const r = await new Spawn(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"image/png\", \"-o\"]).result\n return r.code === 0 && r.stdout.length > 0 ? writeTempPng(r.stdout) : undefined\n}\n\nasync function xclipFiles(): Promise<ClipboardFiles | undefined> {\n const paths = parseUriList(\n await spawnText(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"text/uri-list\", \"-o\"])\n )\n return paths.length > 0 ? { kind: \"files\", paths } : undefined\n}\n\nasync function xclipText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"xclip\", [\"-o\", \"-selection\", \"clipboard\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nasync function xselText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"xsel\", [\"-o\", \"-b\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nfunction wsl(): Provider {\n // win32yank is text-only; image / file paste from WSL would need a\n // different shim, so we only expose text here. `kind === \"image\"`\n // or `\"files\"` always resolves to undefined.\n return {\n id: \"win32yank\",\n read: async (kind) => {\n if (kind === \"image\" || kind === \"files\") return undefined\n const text = await spawnText(\"win32yank.exe\", [\"-o\", \"--lf\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n },\n writeText: (text) => spawnWithInput(\"win32yank.exe\", [\"-i\", \"--crlf\"], text),\n }\n}\n\nfunction windows(): Provider {\n return {\n id: \"powershell\",\n read: async (kind) => {\n if (kind === \"image\") return windowsImage()\n if (kind === \"files\") return windowsFiles()\n if (kind === \"text\") return windowsText()\n const img = await windowsImage()\n if (img) return img\n const files = await windowsFiles()\n if (files) return files\n return windowsText()\n },\n writeText: (text) => spawnWithInput(\"clip\", [], text),\n }\n}\n\nasync function windowsText(): Promise<ClipboardText | undefined> {\n const text = await spawnText(\"powershell\", [\"-NoProfile\", \"-NoLogo\", \"-Command\", \"Get-Clipboard\"])\n return text === undefined ? undefined : { kind: \"text\", text }\n}\n\nasync function windowsImage(): Promise<ClipboardImage | undefined> {\n // PowerShell: fetch image from clipboard, save as PNG to a temp path.\n // Nothing on clipboard → the `if` skips and the file stays empty.\n const tmp = writeTempPath(\"zaly-clip-\", \".png\")\n const script = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n \"$img = [System.Windows.Forms.Clipboard]::GetImage()\",\n `if ($img) { $img.Save('${tmp.replace(/\\\\/g, String.raw`\\\\`)}') }`,\n ].join(\"; \")\n await spawnText(\"powershell\", [\"-NoProfile\", \"-NoLogo\", \"-Command\", script])\n if ((safeStat(tmp)?.size ?? 0) > 0) return { kind: \"image\", path: tmp, type: \"image/png\" }\n return undefined\n}\n\nasync function windowsFiles(): Promise<ClipboardFiles | undefined> {\n const out = await spawnText(\"powershell\", [\n \"-NoProfile\",\n \"-NoLogo\",\n \"-Command\",\n \"Get-Clipboard -Format FileDropList | ForEach-Object { $_.FullName }\",\n ])\n if (!out) return undefined\n const paths = out\n .split(/\\r?\\n/)\n .map((s) => s.trim())\n .filter((s) => s !== \"\")\n return paths.length > 0 ? { kind: \"files\", paths } : undefined\n}\n\n// ---- temp files + URI list parsing ----------------------------------\n\nfunction writeTempPng(bytes: Buffer): ClipboardImage {\n const path = writeTempPath(\"zaly-clip-\", \".png\")\n writeFileSync(path, bytes)\n return { kind: \"image\", path, type: \"image/png\" }\n}\n\n/** Parse a `text/uri-list` blob (RFC 2483): `file://…\\r\\n` lines, skip\n * blanks and comment lines (`#…`), decode percent-encoding. Returns\n * absolute filesystem paths. Non-`file://` URIs are dropped — we\n * can't hand a remote URL off as an attachment path. */\nfunction parseUriList(raw: string | undefined): string[] {\n if (!raw) return []\n const out: string[] = []\n for (const line of raw.split(/\\r?\\n/)) {\n const s = line.trim()\n if (s === \"\" || s.startsWith(\"#\")) continue\n if (!s.startsWith(\"file://\")) continue\n try {\n let path = decodeURIComponent(s.slice(\"file://\".length))\n // `file:///C:/foo` → `/C:/foo` after the slice. Strip the leading\n // slash so we end up with a real Windows path.\n if (/^\\/[A-Za-z]:\\//.test(path)) path = path.slice(1)\n out.push(path)\n } catch {\n /* malformed URI — skip */\n }\n }\n return out\n}\n\nfunction writeTempPath(prefix: string, ext: string): string {\n const dir = mkdtempSync(join(tmpdir(), prefix))\n return join(dir, `clip${ext}`)\n}\n"],"mappings":"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"}
|
package/dist/clipboard.d.mts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* AppleScript/PowerShell snippets.
|
|
20
20
|
*/
|
|
21
21
|
/** Image bytes on the clipboard, already written to a temp PNG. */
|
|
22
|
-
interface ClipboardImage {
|
|
22
|
+
export interface ClipboardImage {
|
|
23
23
|
kind: "image";
|
|
24
24
|
/** Absolute path to a temporary PNG file. Caller takes ownership. */
|
|
25
25
|
path: string;
|
|
@@ -28,22 +28,22 @@ interface ClipboardImage {
|
|
|
28
28
|
}
|
|
29
29
|
/** One or more file references on the clipboard — what you get when
|
|
30
30
|
* the user copies a file in their file manager and pastes. */
|
|
31
|
-
interface ClipboardFiles {
|
|
31
|
+
export interface ClipboardFiles {
|
|
32
32
|
kind: "files";
|
|
33
33
|
/** Absolute filesystem paths. */
|
|
34
34
|
paths: string[];
|
|
35
35
|
}
|
|
36
36
|
/** Plain text on the clipboard — the common case. */
|
|
37
|
-
interface ClipboardText {
|
|
37
|
+
export interface ClipboardText {
|
|
38
38
|
kind: "text";
|
|
39
39
|
text: string;
|
|
40
40
|
}
|
|
41
41
|
/** Anything the clipboard can hold that this library surfaces. */
|
|
42
|
-
type ClipboardContent = ClipboardImage | ClipboardFiles | ClipboardText;
|
|
42
|
+
export type ClipboardContent = ClipboardImage | ClipboardFiles | ClipboardText;
|
|
43
43
|
/** One of the content kinds `ClipboardContent` can take. Derived from
|
|
44
44
|
* the union so adding a new variant doesn't require updating this
|
|
45
45
|
* alias separately. */
|
|
46
|
-
type ClipboardKind = ClipboardContent["kind"];
|
|
46
|
+
export type ClipboardKind = ClipboardContent["kind"];
|
|
47
47
|
/**
|
|
48
48
|
* Read the system clipboard, returning the richest content available.
|
|
49
49
|
*
|
|
@@ -94,11 +94,10 @@ declare function writeClipboardText(text: string): Promise<boolean>;
|
|
|
94
94
|
* clipboard.reset()
|
|
95
95
|
* ```
|
|
96
96
|
*/
|
|
97
|
-
declare const clipboard: {
|
|
97
|
+
export declare const clipboard: {
|
|
98
98
|
read: typeof readClipboard;
|
|
99
99
|
reset: typeof resetClipboardCache;
|
|
100
100
|
write: typeof writeClipboardText;
|
|
101
101
|
};
|
|
102
102
|
//#endregion
|
|
103
|
-
export { ClipboardContent, ClipboardFiles, ClipboardImage, ClipboardKind, ClipboardText, clipboard };
|
|
104
103
|
//# sourceMappingURL=clipboard.d.mts.map
|
package/dist/clipboard.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.d.mts","names":[],"sources":["../src/input/clipboard.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"clipboard.d.mts","names":[],"sources":["../src/input/clipboard.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;iBA+BiB;EACf;;EAEA;;EAEA;;;;iBAKe;EACf;;EAEA;;;iBAIe;EACf;EACA;;;YAIU,mBAAmB,iBAAiB,iBAAiB;;;;YAKrD,gBAAgB;;;;;;;;;;;;;;;iBA8Cb,iBAAiB,QAAQ;iBACzB,cAAc,eAAe,QAAQ;iBACrC,cAAc,gBAAgB,QAAQ;iBACtC,cAAc,gBAAgB,QAAQ;;;;iBAc5C;;;;;;;;;;;;;;;;iBAoBM,mBAAmB,eAAe;;;;;;;;;;;;;qBA6BpC;EACX,aAAI;EACJ,cAAK;EACL,cAAK"}
|
package/dist/clipboard.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as clipboard } from "./clipboard-
|
|
1
|
+
import { t as clipboard } from "./clipboard-CNPBTX7j.mjs";
|
|
2
2
|
export { clipboard };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as defaultTheme } from "./registry-
|
|
2
|
-
import { t as styleBuilder } from "./builder-
|
|
1
|
+
import { t as defaultTheme } from "./registry-CEpHcTa2.mjs";
|
|
2
|
+
import { t as styleBuilder } from "./builder-BgEcjj8Z.mjs";
|
|
3
3
|
//#region src/core/ctx.ts
|
|
4
4
|
/**
|
|
5
5
|
* Current terminal width in cells. Returns `undefined` when stdout isn't a
|
|
@@ -40,4 +40,4 @@ function createCtx(opts = {}) {
|
|
|
40
40
|
//#endregion
|
|
41
41
|
export { createCtx as t };
|
|
42
42
|
|
|
43
|
-
//# sourceMappingURL=ctx-
|
|
43
|
+
//# sourceMappingURL=ctx-ChO3St_a.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ctx-
|
|
1
|
+
{"version":3,"file":"ctx-ChO3St_a.mjs","names":[],"sources":["../src/core/ctx.ts"],"sourcesContent":["import type { Emitter } from \"@zaly/shared\"\nimport type { Logger } from \"@zaly/shared/logger\"\nimport type { Actions } from \"../input/actions.ts\"\nimport type { TerminalQueries } from \"../input/queries.ts\"\nimport type { InputRouterEvents } from \"../input/router.ts\"\nimport type { SurfaceType } from \"../renderer/renderer.ts\"\nimport type { StyleBuilder } from \"../style/builder.ts\"\nimport type { Theme } from \"../themes/types.ts\"\nimport type { Overlay } from \"../widgets/overlay.ts\"\nimport type { Node } from \"./node.ts\"\n\nimport { styleBuilder } from \"../style/builder.ts\"\nimport { defaultTheme } from \"../themes/registry.ts\"\n\n/**\n * Passed to every `render(ctx)` call. Width flows in; height emerges from\n * the returned row count. Theme is ambient — children share the parent's.\n *\n * `style` is a theme-bound chainable builder made available to components so\n * they can produce inline-styled strings without re-binding the theme.\n *\n * `version` is a monotonic cache-key bumped by the `Renderer` whenever any\n * identity-relevant ctx field changes (resize, theme swap). Node caches\n * compare this integer — no hashing, no string keys.\n */\nexport interface RenderCtx {\n width: number\n style: StyleBuilder\n version: number\n /** Queue a side-channel ANSI payload (e.g. KGP image transmit) for\n * the renderer to flush before the next paint. Use this to keep\n * side-effecting bytes out of cached row strings — what `_render`\n * returns should be safe to reuse across paints, and transmit\n * bytes shouldn't be. */\n readonly transmit: (seq: string) => void\n}\n\n/**\n * Context handed to a node when it mounts onto a surface. Gives widget\n * authors a scoped handle to the services they legitimately need —\n * focus, overlays, tree lookups, out-of-band repaints — without\n * exposing the full Renderer.\n *\n * MountCtx is *per-lifetime*: set once when `mount()` is called and\n * cleared on `unmount()`. Distinct from `RenderCtx` (per-tick, carries\n * width/theme/version). If a node moves between surfaces, it receives\n * a fresh MountCtx via the subsequent `mount()` call.\n */\nexport interface MountCtx {\n /** Which surface owns this subtree. */\n readonly surface: SurfaceType\n\n /** Overlay capabilities — open/close an Overlay node from inside a\n * widget (e.g. a confirm dialog, autocomplete popover, tooltip). */\n readonly overlay: {\n readonly add: (o: () => Overlay) => void\n readonly remove: (o: Overlay) => void\n }\n\n /** Input capabilities — a narrow slice of the router. We deliberately\n * don't expose the full `InputRouter`: `setKeymap` / `dispatch` are\n * app-level concerns. Widgets legitimately need to install direct\n * global key bindings (autocomplete) and move focus. */\n readonly input: {\n readonly terminalFocus: boolean\n readonly events: Emitter<InputRouterEvents>\n readonly bind: Actions[\"bind\"]\n /** Move focus to `node`. Mirrors `router.focus(node)`. */\n readonly focus: (node: Node) => void\n /** Clear focus. */\n readonly blur: (node: Node) => void\n readonly queries: TerminalQueries\n }\n\n /** Action registry — widgets and plugins can `register` catalog\n * entries (with desc + default keys + optional `fn`) and `dispatch`\n * actions by id. The Router feeds key-triggered dispatches through\n * here; programmatic callers do the same. */\n readonly actions: Actions\n\n /** Look up a node anywhere in the tree by its `id`. First match\n * wins; `undefined` when nothing matches. Same semantics as\n * `Renderer.getNode`. */\n readonly getNode: (id: string) => Node | undefined\n /** Find every node matching a predicate. Strings match `node.type`;\n * pass a function for richer predicates. Same semantics as\n * `Renderer.findNode`. */\n readonly findNode: (match: string | ((n: Node) => boolean)) => Node[]\n\n logger: Logger\n}\n\n/**\n * Current terminal width in cells. Returns `undefined` when stdout isn't a\n * TTY (piped output, tests, non-Node/Bun runtimes) — callers should fall\n * back to a sensible default when this is `undefined`.\n *\n * @internal\n */\nfunction termWidth(): number | undefined {\n if (typeof process === \"undefined\") return undefined\n const cols = process.stdout.columns\n return typeof cols === \"number\" && cols > 0 ? cols : undefined\n}\n\n/**\n * Build a fresh `RenderCtx` from a resolved theme + width. Binds a `style`\n * builder to the theme so components can use `ctx.style.primary(...)`\n * without constructing their own.\n *\n * Width is clamped to the terminal's current column count (falling back to\n * 80 when stdout isn't a TTY). No width passed → terminal width is used\n * directly; an explicit `width` wider than the terminal is capped so\n * components never produce rows that wrap the display. Narrower explicit\n * widths (e.g. for fixed-layout tests) pass through unchanged.\n *\n * Dynamic theme loading (from a string name) lives in `themes/loadTheme`\n * — resolve the name first, then pass the `Theme` object here.\n */\nexport function createCtx(opts: Partial<RenderCtx> & { theme?: Theme } = {}): RenderCtx {\n const tw = termWidth() ?? 80\n return {\n style: opts.style ?? styleBuilder(opts.theme ?? defaultTheme),\n transmit: (data) => process.stdout.write(data),\n version: opts.version ?? 0,\n width: Math.min(opts.width ?? tw, tw),\n ...opts,\n }\n}\n"],"mappings":";;;;;;;;;;AAmGA,SAAS,YAAgC;CACvC,IAAI,OAAO,YAAY,aAAa,OAAO,KAAA;CAC3C,MAAM,OAAO,QAAQ,OAAO;CAC5B,OAAO,OAAO,SAAS,YAAY,OAAO,IAAI,OAAO,KAAA;AACvD;;;;;;;;;;;;;;;AAgBA,SAAgB,UAAU,OAA+C,CAAC,GAAc;CACtF,MAAM,KAAK,UAAU,KAAK;CAC1B,OAAO;EACL,OAAO,KAAK,SAAS,aAAa,KAAK,SAAS,YAAY;EAC5D,WAAW,SAAS,QAAQ,OAAO,MAAM,IAAI;EAC7C,SAAS,KAAK,WAAW;EACzB,OAAO,KAAK,IAAI,KAAK,SAAS,IAAI,EAAE;EACpC,GAAG;CACL;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as text } from "./text-
|
|
1
|
+
import { n as text } from "./text-BLz1tRoC.mjs";
|
|
2
2
|
//#region src/widgets/divider.ts
|
|
3
3
|
function divider(state = { style: "divider" }) {
|
|
4
4
|
return text((ctx) => (state.char ?? "─").repeat(state.length ?? ctx.width), state);
|
|
@@ -6,4 +6,4 @@ function divider(state = { style: "divider" }) {
|
|
|
6
6
|
//#endregion
|
|
7
7
|
export { divider as t };
|
|
8
8
|
|
|
9
|
-
//# sourceMappingURL=divider-
|
|
9
|
+
//# sourceMappingURL=divider-l0-JPEIm.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"divider-
|
|
1
|
+
{"version":3,"file":"divider-l0-JPEIm.mjs","names":[],"sources":["../src/widgets/divider.ts"],"sourcesContent":["import type { Style } from \"../style/types.ts\"\nimport type { Text } from \"./text.ts\"\n\nimport { text } from \"./text.ts\"\n\nexport type DividerState = Style & {\n char?: string\n length?: number\n}\n\nexport function divider(state: DividerState = { style: \"divider\" }): Text {\n return text((ctx) => (state.char ?? \"─\").repeat(state.length ?? ctx.width), state)\n}\n"],"mappings":";;AAUA,SAAgB,QAAQ,QAAsB,EAAE,OAAO,UAAU,GAAS;CACxE,OAAO,MAAM,SAAS,MAAM,QAAQ,IAAA,CAAK,OAAO,MAAM,UAAU,IAAI,KAAK,GAAG,KAAK;AACnF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as PickerItem } from "./picker-
|
|
2
|
-
import { o as CompletionSource } from "./autocomplete-
|
|
1
|
+
import { n as PickerItem } from "./picker-JL8lZfRH.mjs";
|
|
2
|
+
import { o as CompletionSource } from "./autocomplete-CxzetPOo.mjs";
|
|
3
3
|
import { FindOptions } from "@zaly/shared/find";
|
|
4
4
|
//#region src/widgets/completions/files.d.ts
|
|
5
5
|
interface FilesSourceOptions extends FindOptions {
|
|
@@ -26,4 +26,4 @@ type File = PickerItem & {
|
|
|
26
26
|
declare function filesSource(opts?: FilesSourceOptions): CompletionSource<File>;
|
|
27
27
|
//#endregion
|
|
28
28
|
export { filesSource as n, FilesSourceOptions as t };
|
|
29
|
-
//# sourceMappingURL=files-
|
|
29
|
+
//# sourceMappingURL=files-BUsa-RVl.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files-
|
|
1
|
+
{"version":3,"file":"files-BUsa-RVl.d.mts","names":[],"sources":["../src/widgets/completions/files.ts"],"mappings":";;;;UAQiB,2BAA2B;;;EAG1C;;;;EAIA,UAAU;;;;;;EAMV;EACA;;KAGG,OAAO;EAAe;;;;iBAIX,YAAY,OAAM,qBAA0B,iBAAiB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as PickerItem } from "./picker-
|
|
2
|
-
import { o as CompletionSource } from "./autocomplete-
|
|
1
|
+
import { n as PickerItem } from "./picker-JL8lZfRH.mjs";
|
|
2
|
+
import { o as CompletionSource } from "./autocomplete-CxzetPOo.mjs";
|
|
3
3
|
//#region src/widgets/completions/github.d.ts
|
|
4
4
|
/** A GitHub issue or pull request returned by `githubSource`. Shape
|
|
5
5
|
* mirrors the `gh` CLI's `--json number,title,state,author,url`
|
|
@@ -61,4 +61,4 @@ interface GithubSourceOptions {
|
|
|
61
61
|
declare function githubSource(opts?: GithubSourceOptions): CompletionSource<GithubItem>;
|
|
62
62
|
//#endregion
|
|
63
63
|
export { githubSource as a, GithubState as i, GithubItem as n, GithubSourceOptions as r, GithubFetcher as t };
|
|
64
|
-
//# sourceMappingURL=github-
|
|
64
|
+
//# sourceMappingURL=github-D89A3F9U.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-
|
|
1
|
+
{"version":3,"file":"github-D89A3F9U.d.mts","names":[],"sources":["../src/widgets/completions/github.ts"],"mappings":";;;;;;KAWY,aAAa;EACvB;EACA;;;EAGA;EACA;EACA;EACA;IAAW;;;KAGD;KAEA,iBAAiB,aAAa,OAAO,gBAAgB,QAAQ;UAExD;;;EAGf;;;EAGA,UAAU;;;EAGV;;EAEA,QAAQ;;EAER;;;;EAIA,UAAU;;;;;;;;;;;;;;;;;;;;;;;iBAwBI,aAAa,OAAM,sBAA2B,iBAAiB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { J as Layout, P as RenderCtx, p as Node } from "./queries-
|
|
1
|
+
import { J as Layout, P as RenderCtx, p as Node } from "./queries-Cvalgu6P.mjs";
|
|
2
2
|
//#region src/widgets/image.d.ts
|
|
3
3
|
interface ImageState {
|
|
4
4
|
/**
|
|
@@ -34,4 +34,4 @@ declare function image(src: string, style?: Omit<ImageState, "src">): Image;
|
|
|
34
34
|
declare function image(state: ImageState): Image;
|
|
35
35
|
//#endregion
|
|
36
36
|
export { ImageState as n, image as r, Image as t };
|
|
37
|
-
//# sourceMappingURL=image-
|
|
37
|
+
//# sourceMappingURL=image-34bU73bW.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-
|
|
1
|
+
{"version":3,"file":"image-34bU73bW.d.mts","names":[],"sources":["../src/widgets/image.ts"],"mappings":";;UAWiB;;;;;;;EAOf;;EAEA;;;;;EAKA;;EAEA;;;;;EAKA;;cAGW,cAAc,KAAK;;EAI9B,YAAY,OAAO;MAOf;EAIK,UAAU;YAIH,QAAQ,KAAK,YAAY;;iBAuC3B,MAAM,aAAa,QAAQ,KAAK,qBAAqB;iBACrD,MAAM,OAAO,aAAa"}
|
package/dist/image.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as TerminalQuery, t as TerminalQueries } from "./queries-
|
|
1
|
+
import { n as TerminalQuery, t as TerminalQueries } from "./queries-Cvalgu6P.mjs";
|
|
2
2
|
import { MaybePromise } from "@zaly/shared";
|
|
3
3
|
import { ImageInfo } from "@zaly/shared/image";
|
|
4
4
|
//#region src/image/kitty.d.ts
|
|
5
|
-
type KittyPlacement = {
|
|
5
|
+
export type KittyPlacement = {
|
|
6
6
|
imageId: number;
|
|
7
7
|
/** Placement ID. Omitted when this is an inline placement (U=1) */
|
|
8
8
|
placementId?: number;
|
|
@@ -13,7 +13,7 @@ type KittyPlacement = {
|
|
|
13
13
|
/** Rows to render (excluding the placement escape sequence) */
|
|
14
14
|
data: string[];
|
|
15
15
|
};
|
|
16
|
-
type ImageSupport = {
|
|
16
|
+
export type ImageSupport = {
|
|
17
17
|
terminal?: {
|
|
18
18
|
name: string;
|
|
19
19
|
version?: string;
|
|
@@ -37,7 +37,7 @@ type ImageSupport = {
|
|
|
37
37
|
};
|
|
38
38
|
inline?: boolean;
|
|
39
39
|
});
|
|
40
|
-
type KittyResponse = {
|
|
40
|
+
export type KittyResponse = {
|
|
41
41
|
attrs: Record<string, string | number>;
|
|
42
42
|
ok: true;
|
|
43
43
|
} | {
|
|
@@ -48,19 +48,19 @@ type KittyResponse = {
|
|
|
48
48
|
message: string;
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
|
-
type PlacementDims = {
|
|
51
|
+
export type PlacementDims = {
|
|
52
52
|
/** Display width in terminal cells. */
|
|
53
53
|
cols: number;
|
|
54
54
|
/** Display height in terminal cells. */
|
|
55
55
|
rows: number;
|
|
56
56
|
};
|
|
57
|
-
declare const DIACRITICS: string[];
|
|
58
|
-
declare const PLACEHOLDER: string;
|
|
57
|
+
export declare const DIACRITICS: string[];
|
|
58
|
+
export declare const PLACEHOLDER: string;
|
|
59
59
|
/** Allocate a fresh 24-bit image id (1..0xFFFFFFFE). */
|
|
60
|
-
declare function allocateImageId(): number;
|
|
60
|
+
export declare function allocateImageId(): number;
|
|
61
61
|
/** Allocate a fresh 24-bit placement id. */
|
|
62
|
-
declare function allocatePlacementId(): number;
|
|
63
|
-
declare class Kitty {
|
|
62
|
+
export declare function allocatePlacementId(): number;
|
|
63
|
+
export declare class Kitty {
|
|
64
64
|
#private;
|
|
65
65
|
constructor(support: ImageSupport);
|
|
66
66
|
get supported(): boolean;
|
|
@@ -111,13 +111,12 @@ declare class Kitty {
|
|
|
111
111
|
transmitBytes(id: number, png: Uint8Array): string;
|
|
112
112
|
}
|
|
113
113
|
/** Drop the per-src transmit cache. Mostly for tests. */
|
|
114
|
-
declare function resetTransmitCache(): void;
|
|
115
|
-
declare function resetKittyGraphics(): void;
|
|
116
|
-
declare function bumpPlacements(rows: string[]): undefined | {
|
|
114
|
+
export declare function resetTransmitCache(): void;
|
|
115
|
+
export declare function resetKittyGraphics(): void;
|
|
116
|
+
export declare function bumpPlacements(rows: string[]): undefined | {
|
|
117
117
|
delete: () => string;
|
|
118
118
|
rows: string[];
|
|
119
119
|
};
|
|
120
|
-
declare function loadKittyGraphics(tq: TerminalQueries): MaybePromise<Kitty>;
|
|
120
|
+
export declare function loadKittyGraphics(tq: TerminalQueries): MaybePromise<Kitty>;
|
|
121
121
|
//#endregion
|
|
122
|
-
export { DIACRITICS, ImageSupport, Kitty, KittyPlacement, KittyResponse, PLACEHOLDER, PlacementDims, allocateImageId, allocatePlacementId, bumpPlacements, loadKittyGraphics, resetKittyGraphics, resetTransmitCache };
|
|
123
122
|
//# sourceMappingURL=image.d.mts.map
|
package/dist/image.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.mts","names":[],"sources":["../src/image/kitty.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"image.d.mts","names":[],"sources":["../src/image/kitty.ts"],"mappings":";;;;YAqBY;EACV;;EAEA;;EAEA;;EAEA;;EAEA;;YAGU;EACV;IAAa;IAAc;;EAC3B;EACA,QAAQ;EACR;;EAGI;EACA;EACA;IAAa;IAAc;;;EAG3B;EACA;EACA;IAAY;IAAc;;EAC1B;;YAIM;EAEN,OAAO;EACP;;EAGA,OAAO;EACP;EACA;IAAS;IAAc;;;YAGjB;;EAEV;;EAEA;;qBAaW;qBACA;;wBAgBG;;wBAKA;qBAIH;;EAIX,YAAY,SAAS;MAKjB;MAIA;;EAKJ,QACE,OAAO,iCACP,gBAAgB,YAChB;IAAQ;;;EAcV,MACE,OAAO,iCACP,gBAAgB,YAChB;IAAQ;MACP;;EAaH;;EAKA,MAAM,cAAc;EAsBpB,UAAU,iBAAiB,MAAM,gBAAgB;;EA+BjD,YAAY;;EAOZ,gBAAgB,iBAAiB;;;;;;;;;;;EAc3B,aAAa,MAAM,YAAY;IAAU;IAAiB;;;;;;;;EAqChE,aAAa,YAAY;;;;;;EASzB,cAAc,YAAY,KAAK;;;wBAoBjB;wBAIA;wBAwCA,eACd;EACe;EAAsB;;wBAiFvB,kBAAkB,IAAI,kBAAkB,aAAa"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $ as Context, At as useContext, Bt as Actions, C as OverlaySurface, Ct as peek, Dt as untrack, Et as toAccessor, Ft as ActionCtx, Gt as KeyModifier, Ht as NodeAction, It as ActionDef, J as Layout, Jt as SpecialKeyName, Kt as KeyPattern, Lt as ActionFilter, Mt as withOwner, N as MountCtx, Ot as unwrap, P as RenderCtx, Pt as Action, Q as Accessor, Rt as ActionFn, S as Stream, St as onCleanup, Tt as signal, Ut as NodeActionMap, Vt as KeyBinding, Wt as KeyEvent, X as State, Xt as isKeyPattern, Y as LayoutState, Yt as canonical, Z as StyleState, Zt as keyMatches, _ as RenderStats, _t as createSuspenseBoundary, a as InputRouter, at as Signal, b as SurfaceType, bt as isAccessor, c as KeyPatterns, ct as SuspenseContext, d as RoutedPaste, dt as createIterable, et as Owner, f as BaseEvents, ft as createNode, g as RenderEvents, gt as createStore, h as NodeVisitor, ht as createRoot, i as parseAttrs, it as Setter, jt as withActiveNode, kt as useActiveOwner, l as KeymapEntry, lt as createAsync, m as isNode, mt as createRef, n as TerminalQuery, nt as Reactive, o as InputRouterEvents, ot as SignalStore, p as Node, pt as createProgressive, q as FlexState, qt as KeyPatternError, r as TerminalQueryOpts, rt as Ref, s as KeyHandler, st as SuspenseBoundary, t as TerminalQueries, tt as Progressive, u as RoutedKey, ut as createContext, v as Renderer, vt as effect, w as Terminal, wt as provideContext, x as UI, xt as memo, y as RendererOptions, yt as inRenderContextOf, zt as ActionMap } from "./queries-
|
|
2
|
-
import { _ as ShikiRequest, a as AnsiStyle, b as
|
|
3
|
-
import { a as StyleBuilder, i as isMarkdown, n as inspect, r as inspectFormat, t as InspectOpts } from "./inspect-
|
|
1
|
+
import { $ as Context, At as useContext, Bt as Actions, C as OverlaySurface, Ct as peek, Dt as untrack, Et as toAccessor, Ft as ActionCtx, Gt as KeyModifier, Ht as NodeAction, It as ActionDef, J as Layout, Jt as SpecialKeyName, Kt as KeyPattern, Lt as ActionFilter, Mt as withOwner, N as MountCtx, Ot as unwrap, P as RenderCtx, Pt as Action, Q as Accessor, Rt as ActionFn, S as Stream, St as onCleanup, Tt as signal, Ut as NodeActionMap, Vt as KeyBinding, Wt as KeyEvent, X as State, Xt as isKeyPattern, Y as LayoutState, Yt as canonical, Z as StyleState, Zt as keyMatches, _ as RenderStats, _t as createSuspenseBoundary, a as InputRouter, at as Signal, b as SurfaceType, bt as isAccessor, c as KeyPatterns, ct as SuspenseContext, d as RoutedPaste, dt as createIterable, et as Owner, f as BaseEvents, ft as createNode, g as RenderEvents, gt as createStore, h as NodeVisitor, ht as createRoot, i as parseAttrs, it as Setter, jt as withActiveNode, kt as useActiveOwner, l as KeymapEntry, lt as createAsync, m as isNode, mt as createRef, n as TerminalQuery, nt as Reactive, o as InputRouterEvents, ot as SignalStore, p as Node, pt as createProgressive, q as FlexState, qt as KeyPatternError, r as TerminalQueryOpts, rt as Ref, s as KeyHandler, st as SuspenseBoundary, t as TerminalQueries, tt as Progressive, u as RoutedKey, ut as createContext, v as Renderer, vt as effect, w as Terminal, wt as provideContext, x as UI, xt as memo, y as RendererOptions, yt as inRenderContextOf, zt as ActionMap } from "./queries-Cvalgu6P.mjs";
|
|
2
|
+
import { _ as ShikiRequest, a as AnsiStyle, b as ShikiWorkerMessage, c as Color, d as RGB, f as Style, g as ShikiOpts, h as ShikiLanguage, i as AnsiColorName, l as ColorLightness, m as ShikiJob, n as ThemeValue, o as AnyStyle, p as ThemeKey, r as AnsiColor, s as BrightAnsiColorName, t as Theme, u as HexColor, v as ShikiResult, x as ShikiWorkerRequest, y as ShikiTheme } from "./types-C0EOLZDc.mjs";
|
|
3
|
+
import { a as StyleBuilder, i as isMarkdown, n as inspect, r as inspectFormat, t as InspectOpts } from "./inspect-DPLRum7L.mjs";
|
|
4
4
|
import { ArgsOpts } from "@zaly/shared/args";
|
|
5
5
|
//#region src/input/index.d.ts
|
|
6
|
-
declare function defineAction<T extends ArgsOpts = ArgsOpts>(action: ActionDef<T>): ActionDef<T>;
|
|
7
|
-
declare function defineAction<T extends ArgsOpts = ArgsOpts>(action: Action<T>): Action<T>;
|
|
6
|
+
export declare function defineAction<T extends ArgsOpts = ArgsOpts>(action: ActionDef<T>): ActionDef<T>;
|
|
7
|
+
export declare function defineAction<T extends ArgsOpts = ArgsOpts>(action: Action<T>): Action<T>;
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region src/core/render.d.ts
|
|
10
10
|
/** Components-facing slice of the render environment — reactive
|
|
@@ -13,7 +13,7 @@ declare function defineAction<T extends ArgsOpts = ArgsOpts>(action: Action<T>):
|
|
|
13
13
|
* call (the place where `RenderCtx` is threaded in). Width is
|
|
14
14
|
* deliberately omitted — that's a per-render allotted-size concept,
|
|
15
15
|
* not an ambient one. */
|
|
16
|
-
type RenderContextValue = {
|
|
16
|
+
export type RenderContextValue = {
|
|
17
17
|
/** Active theme. Tracked — widgets that read it re-fire on swap. */
|
|
18
18
|
theme: Accessor<Theme>;
|
|
19
19
|
/** Theme-bound chainable style builder. Derived memo over `theme`. */
|
|
@@ -22,7 +22,7 @@ type RenderContextValue = {
|
|
|
22
22
|
images: Accessor<boolean>;
|
|
23
23
|
queries: TerminalQueries;
|
|
24
24
|
};
|
|
25
|
-
declare const RenderContext: Context<RenderContextValue | undefined>;
|
|
25
|
+
export declare const RenderContext: Context<RenderContextValue | undefined>;
|
|
26
26
|
/**
|
|
27
27
|
* Render a Node, draining `createAsync` work in its subtree before
|
|
28
28
|
* returning final rows. Two shapes:
|
|
@@ -43,22 +43,22 @@ declare const RenderContext: Context<RenderContextValue | undefined>;
|
|
|
43
43
|
* const rows = await createRender(() => markdown("**hi**"))
|
|
44
44
|
* ```
|
|
45
45
|
*/
|
|
46
|
-
declare function createRender(node: Node, ctx: RenderCtx & {
|
|
46
|
+
export declare function createRender(node: Node, ctx: RenderCtx & {
|
|
47
47
|
boundary: SuspenseBoundary;
|
|
48
48
|
}): Promise<string[]>;
|
|
49
|
-
declare function createRender(node: () => Node, ctx?: RenderCtx): Promise<string[]>;
|
|
49
|
+
export declare function createRender(node: () => Node, ctx?: RenderCtx): Promise<string[]>;
|
|
50
50
|
//#endregion
|
|
51
51
|
//#region src/core/index.d.ts
|
|
52
|
-
declare function createCtx(opts?: Partial<RenderCtx> & {
|
|
52
|
+
export declare function createCtx(opts?: Partial<RenderCtx> & {
|
|
53
53
|
theme?: Theme;
|
|
54
54
|
}): Promise<RenderCtx>;
|
|
55
55
|
//#endregion
|
|
56
56
|
//#region src/renderer/index.d.ts
|
|
57
57
|
/** Factory shorthand for `new Renderer(opts)`. */
|
|
58
|
-
declare function createRenderer(opts?: RendererOptions): Promise<Renderer>;
|
|
58
|
+
export declare function createRenderer(opts?: RendererOptions): Promise<Renderer>;
|
|
59
59
|
//#endregion
|
|
60
60
|
//#region src/shiki/shiki.d.ts
|
|
61
|
-
declare function codeToAnsi(code: string, lang: string, opts?: ShikiOpts): Promise<string>;
|
|
61
|
+
export declare function codeToAnsi(code: string, lang: string, opts?: ShikiOpts): Promise<string>;
|
|
62
62
|
//#endregion
|
|
63
|
-
export { Accessor, type Action, type ActionCtx, type ActionDef, type ActionFilter, type ActionFn, type ActionMap, type Actions, type AnsiColor, type AnsiColorName, type AnsiStyle, type AnyStyle, type BaseEvents, type BrightAnsiColorName, type Color, type ColorLightness, Context, type FlexState, type HexColor, type InputRouter, type InputRouterEvents, InspectOpts, type KeyBinding, KeyEvent, type KeyHandler, KeyModifier, KeyPattern, KeyPatternError, type KeyPatterns, type KeymapEntry, type Layout, type LayoutState, type MountCtx, type Node, type NodeAction, type NodeActionMap, type NodeVisitor, type OverlaySurface, Owner, Progressive, type RGB, Reactive, Ref,
|
|
63
|
+
export { Accessor, type Action, type ActionCtx, type ActionDef, type ActionFilter, type ActionFn, type ActionMap, type Actions, type AnsiColor, type AnsiColorName, type AnsiStyle, type AnyStyle, type BaseEvents, type BrightAnsiColorName, type Color, type ColorLightness, Context, type FlexState, type HexColor, type InputRouter, type InputRouterEvents, InspectOpts, type KeyBinding, KeyEvent, type KeyHandler, KeyModifier, KeyPattern, KeyPatternError, type KeyPatterns, type KeymapEntry, type Layout, type LayoutState, type MountCtx, type Node, type NodeAction, type NodeActionMap, type NodeVisitor, type OverlaySurface, Owner, Progressive, type RGB, Reactive, Ref, type RenderCtx, type RenderEvents, type RenderStats, type Renderer, type RendererOptions, type RoutedKey, type RoutedPaste, Setter, type ShikiJob, type ShikiLanguage, type ShikiOpts, type ShikiRequest, type ShikiResult, type ShikiTheme, type ShikiWorkerMessage, type ShikiWorkerRequest, Signal, SignalStore, SpecialKeyName, type State, type Stream, type Style, type StyleState, type SurfaceType, SuspenseBoundary, SuspenseContext, type Terminal, TerminalQueries, TerminalQuery, TerminalQueryOpts, type Theme, type ThemeKey, type ThemeValue, type UI, canonical, createAsync, createContext, createIterable, createNode, createProgressive, createRef, createRoot, createStore, createSuspenseBoundary, effect, inRenderContextOf, inspect, inspectFormat, isAccessor, isKeyPattern, isMarkdown, type isNode, keyMatches, memo, onCleanup, parseAttrs, peek, provideContext, signal, toAccessor, untrack, unwrap, useActiveOwner, useContext, withActiveNode, withOwner };
|
|
64
64
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/input/index.ts","../src/core/render.ts","../src/core/index.ts","../src/renderer/index.ts","../src/shiki/shiki.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/input/index.ts","../src/core/render.ts","../src/core/index.ts","../src/renderer/index.ts","../src/shiki/shiki.ts"],"mappings":";;;;;wBAGgB,aAAa,UAAU,WAAW,UAAU,QAAQ,UAAU,KAAK,UAAU;wBAC7E,aAAa,UAAU,WAAW,UAAU,QAAQ,OAAO,KAAK,OAAO;;;;;;;;;YCmB3E;;EAEV,OAAO,SAAS;;EAEhB,OAAO,SAAS;;EAEhB,QAAQ;EACR,SAAS;;qBAEE,eAAa,QAAA;;;;;;;;;;;;;;;;;;;;;wBAsBJ,aACpB,MAAM,MACN,KAAK;EAAc,UAAU;IAC5B;wBACmB,aAAa,YAAY,MAAM,MAAM,YAAY;;;wBC/CjD,UACpB,OAAM,QAAQ;EAAe,QAAQ;IACpC,QAAQ;;;;wBCJW,eAAe,OAAM,kBAAuB,QAAQ;;;wBCJpD,WAAW,cAAc,cAAc,OAAO,YAAY"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { C as useActiveOwner, E as withOwner, S as unwrap, T as withActiveNode, _ as peek, a as createIterable, b as toAccessor, c as createRef, d as createSuspenseBoundary, f as effect, g as onCleanup, h as memo, i as createContext, l as createRoot, m as isAccessor, n as SuspenseContext, o as createNode, p as inRenderContextOf, r as createAsync, s as createProgressive, t as Owner, u as createStore, v as provideContext, w as useContext, x as untrack, y as signal } from "./reactive-f7NpAi69.mjs";
|
|
2
|
-
import { n as inspectFormat, r as isMarkdown, t as inspect } from "./inspect-
|
|
3
|
-
import { n as createRender, t as RenderContext } from "./render-
|
|
4
|
-
import { t as codeToAnsi } from "./shiki-
|
|
2
|
+
import { n as inspectFormat, r as isMarkdown, t as inspect } from "./inspect-xdSq5Hjq.mjs";
|
|
3
|
+
import { n as createRender, t as RenderContext } from "./render-DxIHVH9Y.mjs";
|
|
4
|
+
import { t as codeToAnsi } from "./shiki-CcxiFWEF.mjs";
|
|
5
5
|
import { a as isKeyPattern, i as canonical, n as parseAttrs, o as keyMatches, r as KeyPatternError, t as TerminalQueries } from "./queries-B_lOwEiE.mjs";
|
|
6
6
|
//#region src/input/index.ts
|
|
7
7
|
function defineAction(action) {
|
|
@@ -10,14 +10,14 @@ function defineAction(action) {
|
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/core/index.ts
|
|
12
12
|
async function createCtx(opts = {}) {
|
|
13
|
-
const { createCtx: create } = await import("./ctx-
|
|
13
|
+
const { createCtx: create } = await import("./ctx-DZHBHjsB.mjs");
|
|
14
14
|
return create(opts);
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/renderer/index.ts
|
|
18
18
|
/** Factory shorthand for `new Renderer(opts)`. */
|
|
19
19
|
async function createRenderer(opts = {}) {
|
|
20
|
-
const { Renderer } = await import("./renderer-
|
|
20
|
+
const { Renderer } = await import("./renderer-Bz3tc2IT.mjs");
|
|
21
21
|
return new Renderer(opts);
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { S as unwrap, x as untrack } from "./reactive-f7NpAi69.mjs";
|
|
2
2
|
import { t as Node } from "./node-BZ7f6HzU.mjs";
|
|
3
|
-
import { o as formatText } from "./text-
|
|
4
|
-
import { t as clipboard } from "./clipboard-
|
|
3
|
+
import { o as formatText } from "./text-CRZD9KTN.mjs";
|
|
4
|
+
import { t as clipboard } from "./clipboard-CNPBTX7j.mjs";
|
|
5
5
|
import { hash, isPromiseLike } from "@zaly/shared";
|
|
6
6
|
import { sliceAnsi, splitAnsi, stringWidth } from "@zaly/shared/ansi";
|
|
7
7
|
import { basename } from "pathe";
|
|
@@ -494,4 +494,4 @@ function countLines(value) {
|
|
|
494
494
|
//#endregion
|
|
495
495
|
export { input as n, Input as t };
|
|
496
496
|
|
|
497
|
-
//# sourceMappingURL=input-
|
|
497
|
+
//# sourceMappingURL=input-D7fQEUdt.mjs.map
|