@markii/host 0.0.1 → 0.17.0-next.3
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/README.md +20 -2
- package/dist/browser-worker.js +639 -0
- package/dist/browser.d.ts +61 -0
- package/dist/browser.js +172 -0
- package/dist/conformance/host/01-plain-open/expected.json +5 -0
- package/dist/conformance/host/01-plain-open/note.mk.md +8 -0
- package/dist/conformance/host/01-plain-open/scenario.json +6 -0
- package/dist/conformance/host/02-run-manual-grant-accepted/expected.json +16 -0
- package/dist/conformance/host/02-run-manual-grant-accepted/note.mk.md +5 -0
- package/dist/conformance/host/02-run-manual-grant-accepted/scenario.json +14 -0
- package/dist/conformance/host/03-run-manual-grant-refused/expected.json +18 -0
- package/dist/conformance/host/03-run-manual-grant-refused/note.mk.md +5 -0
- package/dist/conformance/host/03-run-manual-grant-refused/scenario.json +14 -0
- package/dist/conformance/host/04-run-auto-write-denied/expected.json +16 -0
- package/dist/conformance/host/04-run-auto-write-denied/note.mk.md +10 -0
- package/dist/conformance/host/04-run-auto-write-denied/scenario.json +13 -0
- package/dist/conformance/host/05-export-html-pack-directive/expected.json +14 -0
- package/dist/conformance/host/05-export-html-pack-directive/note.mk.md +8 -0
- package/dist/conformance/host/05-export-html-pack-directive/scenario.json +6 -0
- package/dist/conformance/host/06-install-pack-then-render/expected.json +18 -0
- package/dist/conformance/host/06-install-pack-then-render/files/ana-1.0.0/pack.json +13 -0
- package/dist/conformance/host/06-install-pack-then-render/files/ana-1.0.0/webview.js +1 -0
- package/dist/conformance/host/06-install-pack-then-render/note.mk.md +5 -0
- package/dist/conformance/host/06-install-pack-then-render/scenario.json +15 -0
- package/dist/conformance/host/07-complete-in-directive/expected.json +14 -0
- package/dist/conformance/host/07-complete-in-directive/note.mk.md +3 -0
- package/dist/conformance/host/07-complete-in-directive/scenario.json +6 -0
- package/dist/conformance/host/08-hover-standard-component/expected.json +5 -0
- package/dist/conformance/host/08-hover-standard-component/note.mk.md +5 -0
- package/dist/conformance/host/08-hover-standard-component/scenario.json +6 -0
- package/dist/conformance/host/09-insert-skeleton/expected.json +5 -0
- package/dist/conformance/host/09-insert-skeleton/note.mk.md +4 -0
- package/dist/conformance/host/09-insert-skeleton/scenario.json +6 -0
- package/dist/conformance/host/10-scripts-disabled/expected.json +11 -0
- package/dist/conformance/host/10-scripts-disabled/note.mk.md +5 -0
- package/dist/conformance/host/10-scripts-disabled/scenario.json +9 -0
- package/dist/conformance/host/11-complete-closing-fence/expected.json +5 -0
- package/dist/conformance/host/11-complete-closing-fence/note.mk.md +5 -0
- package/dist/conformance/host/11-complete-closing-fence/scenario.json +12 -0
- package/dist/conformance/host/12-complete-nested-container/expected.json +5 -0
- package/dist/conformance/host/12-complete-nested-container/note.mk.md +5 -0
- package/dist/conformance/host/12-complete-nested-container/scenario.json +12 -0
- package/dist/conformance/host/13-install-pack-declined/expected.json +12 -0
- package/dist/conformance/host/13-install-pack-declined/files/ana-1.0.0/pack.json +13 -0
- package/dist/conformance/host/13-install-pack-declined/files/ana-1.0.0/webview.js +1 -0
- package/dist/conformance/host/13-install-pack-declined/note.mk.md +5 -0
- package/dist/conformance/host/13-install-pack-declined/scenario.json +10 -0
- package/dist/conformance/host/14-remove-pack/expected.json +14 -0
- package/dist/conformance/host/14-remove-pack/files/ana-1.0.0/pack.json +13 -0
- package/dist/conformance/host/14-remove-pack/files/ana-1.0.0/webview.js +1 -0
- package/dist/conformance/host/14-remove-pack/note.mk.md +5 -0
- package/dist/conformance/host/14-remove-pack/scenario.json +11 -0
- package/dist/conformance/host/15-load-packs-engine-views/expected.json +19 -0
- package/dist/conformance/host/15-load-packs-engine-views/files/duo-1.0.0/pack.json +9 -0
- package/dist/conformance/host/15-load-packs-engine-views/files/duo-1.0.0/webview.js +1 -0
- package/dist/conformance/host/15-load-packs-engine-views/note.mk.md +9 -0
- package/dist/conformance/host/15-load-packs-engine-views/scenario.json +10 -0
- package/dist/conformance/host/16-pack-trust/expected.json +37 -0
- package/dist/conformance/host/16-pack-trust/files/ana-1.0.0/pack.json +12 -0
- package/dist/conformance/host/16-pack-trust/files/ana-1.0.0/webview.js +1 -0
- package/dist/conformance/host/16-pack-trust/files/sneaky-1.0.0/pack.json +12 -0
- package/dist/conformance/host/16-pack-trust/files/sneaky-1.0.0/webview.js +1 -0
- package/dist/conformance/host/16-pack-trust/note.mk.md +5 -0
- package/dist/conformance/host/16-pack-trust/scenario.json +26 -0
- package/dist/conformance/host/README.md +221 -0
- package/dist/conformance.d.ts +2 -0
- package/dist/conformance.js +5 -0
- package/dist/diagnostics/render-diagnostics.d.ts +41 -0
- package/dist/diagnostics/render-diagnostics.js +46 -0
- package/dist/export/cascade.d.ts +98 -0
- package/dist/export/cascade.js +159 -0
- package/dist/export/export-zip.d.ts +19 -0
- package/dist/export/export-zip.js +38 -0
- package/dist/export/image-embed.d.ts +126 -0
- package/dist/export/image-embed.js +274 -0
- package/dist/export/note-export.d.ts +332 -0
- package/dist/export/note-export.js +366 -0
- package/dist/export/note-links.d.ts +83 -0
- package/dist/export/note-links.js +241 -0
- package/dist/glue.wasm +0 -0
- package/dist/host/adapter.d.ts +218 -0
- package/dist/host/adapter.js +9 -0
- package/dist/host/cascade-export-behavior.d.ts +120 -0
- package/dist/host/cascade-export-behavior.js +151 -0
- package/dist/host/conformance-runner.d.ts +159 -0
- package/dist/host/conformance-runner.js +632 -0
- package/dist/host/create-host.d.ts +251 -0
- package/dist/host/create-host.js +329 -0
- package/dist/host/editor-behavior.d.ts +153 -0
- package/dist/host/editor-behavior.js +223 -0
- package/dist/host/export/md-plain.d.ts +15 -0
- package/dist/host/export/md-plain.js +125 -0
- package/dist/host/export-behavior.d.ts +111 -0
- package/dist/host/export-behavior.js +257 -0
- package/dist/host/labels.d.ts +23 -0
- package/dist/host/labels.js +32 -0
- package/dist/host/pack-archive.d.ts +30 -0
- package/dist/host/pack-archive.js +62 -0
- package/dist/host/pack-install.d.ts +87 -0
- package/dist/host/pack-install.js +186 -0
- package/dist/host/pack-load.d.ts +71 -0
- package/dist/host/pack-load.js +57 -0
- package/dist/host/pack-remove.d.ts +21 -0
- package/dist/host/pack-remove.js +65 -0
- package/dist/host/pack-trust-behavior.d.ts +79 -0
- package/dist/host/pack-trust-behavior.js +262 -0
- package/dist/host/refresh-interval.d.ts +37 -0
- package/dist/host/refresh-interval.js +59 -0
- package/dist/host/run-behavior.d.ts +88 -0
- package/dist/host/run-behavior.js +189 -0
- package/dist/host/run-diagnostics.d.ts +26 -0
- package/dist/host/run-diagnostics.js +43 -0
- package/dist/host/script-execution.d.ts +72 -0
- package/dist/host/script-execution.js +68 -0
- package/dist/host/terminal-packs.d.ts +39 -0
- package/dist/host/terminal-packs.js +51 -0
- package/dist/html-engine.d.ts +2 -0
- package/dist/html-engine.js +29 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +69 -0
- package/dist/insert/component-catalog.d.ts +23 -0
- package/dist/insert/component-catalog.js +96 -0
- package/dist/node-fs.d.ts +14 -0
- package/dist/node-fs.js +70 -0
- package/dist/node-worker.js +20657 -0
- package/dist/node.d.ts +6 -0
- package/dist/node.js +13 -0
- package/dist/package.json +3 -0
- package/dist/packs/discover.d.ts +119 -0
- package/dist/packs/discover.js +266 -0
- package/dist/packs/pack-diagnostics.d.ts +79 -0
- package/dist/packs/pack-diagnostics.js +103 -0
- package/dist/packs/pack-paths.d.ts +53 -0
- package/dist/packs/pack-paths.js +105 -0
- package/dist/packs/pack-render-registry.d.ts +82 -0
- package/dist/packs/pack-render-registry.js +182 -0
- package/dist/packs/pack-scripts.d.ts +20 -0
- package/dist/packs/pack-scripts.js +96 -0
- package/dist/packs/pack-trust.d.ts +57 -0
- package/dist/packs/pack-trust.js +111 -0
- package/dist/packs/prebuilt.d.ts +49 -0
- package/dist/packs/prebuilt.js +97 -0
- package/dist/path-util.d.ts +24 -0
- package/dist/path-util.js +82 -0
- package/dist/run/browser-isolate.d.ts +45 -0
- package/dist/run/browser-isolate.js +85 -0
- package/dist/run/bundle-document.d.ts +29 -0
- package/dist/run/bundle-document.js +40 -0
- package/dist/run/bundle-run.d.ts +188 -0
- package/dist/run/bundle-run.js +232 -0
- package/dist/run/grant-flow.d.ts +232 -0
- package/dist/run/grant-flow.js +390 -0
- package/dist/run/ip-address.d.ts +41 -0
- package/dist/run/ip-address.js +255 -0
- package/dist/run/isolate.d.ts +59 -0
- package/dist/run/isolate.js +22 -0
- package/dist/run/lua-resolver.d.ts +21 -0
- package/dist/run/lua-resolver.js +63 -0
- package/dist/run/net-bridge-worker.d.ts +26 -0
- package/dist/run/net-bridge-worker.js +66 -0
- package/dist/run/net-bridge.d.ts +56 -0
- package/dist/run/net-bridge.js +59 -0
- package/dist/run/net-pinning.d.ts +82 -0
- package/dist/run/net-pinning.js +137 -0
- package/dist/run/net-provider.d.ts +72 -0
- package/dist/run/net-provider.js +303 -0
- package/dist/run/node-isolate.d.ts +22 -0
- package/dist/run/node-isolate.js +68 -0
- package/dist/run/run-flow.d.ts +186 -0
- package/dist/run/run-flow.js +323 -0
- package/dist/run/run-host.d.ts +107 -0
- package/dist/run/run-host.js +241 -0
- package/dist/run/run-job.d.ts +130 -0
- package/dist/run/run-job.js +279 -0
- package/dist/run/run-progress.d.ts +55 -0
- package/dist/run/run-progress.js +42 -0
- package/dist/run/run-trace.d.ts +44 -0
- package/dist/run/run-trace.js +36 -0
- package/dist/run/script-requirements.d.ts +98 -0
- package/dist/run/script-requirements.js +212 -0
- package/dist/run/snapshot-storage.d.ts +25 -0
- package/dist/run/snapshot-storage.js +31 -0
- package/dist/run/stale-values.d.ts +25 -0
- package/dist/run/stale-values.js +32 -0
- package/dist/run/worker-entry-browser.d.ts +62 -0
- package/dist/run/worker-entry-browser.js +172 -0
- package/dist/run/worker-entry.d.ts +1 -0
- package/dist/run/worker-entry.js +98 -0
- package/dist/values-failure.d.ts +17 -0
- package/dist/values-failure.js +1 -0
- package/dist/values-merge.d.ts +39 -0
- package/dist/values-merge.js +33 -0
- package/package.json +80 -4
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createMarkiiHost`: the behaviors every app calls instead of assembling
|
|
3
|
+
* its own run/export/pack/editor wiring. Everything it touches (files, prompts,
|
|
4
|
+
* the isolate) arrives through the adapter, so the main entry stays
|
|
5
|
+
* environment-neutral. VS Code's webview imports only the pure pieces and
|
|
6
|
+
* never calls this function.
|
|
7
|
+
*
|
|
8
|
+
* It provides `run`, `diagnostics`, `open`, `exportNote`, `installPack`, `loadPacks`, `completeAt`,
|
|
9
|
+
* `hoverAt`, and `insertComponent`, over the behavior modules (`./export-behavior.js`, `./pack-install.js`,
|
|
10
|
+
* `./pack-load.js`, `./editor-behavior.js`). Every one of them
|
|
11
|
+
* returns the shared `Unsupported` outcome, with one diagnostics line,
|
|
12
|
+
* when the adapter lacks the capability it needs — AGENTS.md's "clean is
|
|
13
|
+
* not silent": a decline is never a silent no-op.
|
|
14
|
+
*/
|
|
15
|
+
import type { HostAdapter, HostExportFormat, HostTextEdit } from './adapter.js';
|
|
16
|
+
import type { RunResult, SpawnRunRequest } from '../run/run-host.js';
|
|
17
|
+
import type { StoredValue } from '@markii/runtime';
|
|
18
|
+
import type { OnDiagnostic, UnavailableComponent } from '@markii/stdlib';
|
|
19
|
+
import type { CompletionItem, ComponentDocumentation, LineColumn } from '@markii/stdlib/editor';
|
|
20
|
+
import { type RunViaAdapterRequest, type RunViaAdapterResult } from './run-behavior.js';
|
|
21
|
+
import { type ArchiveExtractFs } from './pack-archive.js';
|
|
22
|
+
import { type PackDiscoveryIo } from './pack-load.js';
|
|
23
|
+
import type { HtmlExportEngine } from '../export/note-export.js';
|
|
24
|
+
import type { DiscoveredPack, SkippedPackFolder } from '../packs/discover.js';
|
|
25
|
+
import { type TerminalPackScript } from './terminal-packs.js';
|
|
26
|
+
import { type RemovePackOutcome } from './pack-remove.js';
|
|
27
|
+
import type { DisablePackOutcome, EnablePackOutcome, InstalledPacksListing } from './pack-trust-behavior.js';
|
|
28
|
+
/** The shared decline shape every behavior returns when the adapter lacks the capability it needs. */
|
|
29
|
+
export interface Unsupported {
|
|
30
|
+
readonly kind: 'unsupported';
|
|
31
|
+
readonly capability: 'isolate' | 'editor' | 'packs' | 'pack-trust' | 'export-format';
|
|
32
|
+
readonly detail?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface OpenRequest {
|
|
35
|
+
readonly path: string;
|
|
36
|
+
}
|
|
37
|
+
export type OpenOutcome = {
|
|
38
|
+
readonly kind: 'opened';
|
|
39
|
+
readonly text: string;
|
|
40
|
+
} | {
|
|
41
|
+
readonly kind: 'failed';
|
|
42
|
+
readonly reason: string;
|
|
43
|
+
};
|
|
44
|
+
export type RunRequest = RunViaAdapterRequest;
|
|
45
|
+
export type RunOutcome = ({
|
|
46
|
+
readonly kind: 'ran';
|
|
47
|
+
} & RunViaAdapterResult) | Unsupported;
|
|
48
|
+
export interface ExportRequest {
|
|
49
|
+
readonly format: HostExportFormat;
|
|
50
|
+
/** The note's own path, used to name the exported file. */
|
|
51
|
+
readonly notePath: string;
|
|
52
|
+
readonly text: string;
|
|
53
|
+
/** The note's last-run values, baked into an html/pdf export. Omitted or empty exports the note's standard empty states. */
|
|
54
|
+
readonly values?: Record<string, StoredValue>;
|
|
55
|
+
/**
|
|
56
|
+
* Installed pack components the static HTML engine cannot draw. A
|
|
57
|
+
* directive naming one is labeled "no HTML view" instead of "unknown
|
|
58
|
+
* component" in the exported file. Used only when the static engine
|
|
59
|
+
* renders the body.
|
|
60
|
+
*/
|
|
61
|
+
readonly unavailableComponents?: readonly UnavailableComponent[];
|
|
62
|
+
/** Receives the static engine's render diagnostics, such as the `no-engine-view` event. */
|
|
63
|
+
readonly onDiagnostic?: OnDiagnostic;
|
|
64
|
+
}
|
|
65
|
+
export type ExportOutcome = {
|
|
66
|
+
readonly kind: 'exported';
|
|
67
|
+
readonly path: string;
|
|
68
|
+
readonly bytes: number;
|
|
69
|
+
} | {
|
|
70
|
+
readonly kind: 'failed';
|
|
71
|
+
readonly reason: string;
|
|
72
|
+
}
|
|
73
|
+
/** `adapter.exports.resolveTarget`/`htmlToPdf`/an injected `renderAnsi` was unavailable at the moment of export — a picker cancel, or a seam this host declared but did not wire up. */
|
|
74
|
+
| {
|
|
75
|
+
readonly kind: 'cancelled';
|
|
76
|
+
} | Unsupported;
|
|
77
|
+
export interface InstallPackRequest {
|
|
78
|
+
readonly archiveBytes: Uint8Array;
|
|
79
|
+
/** The archive's own path or display name, used only in wording. Defaults to a generic phrase when omitted. */
|
|
80
|
+
readonly archivePath?: string;
|
|
81
|
+
}
|
|
82
|
+
export type InstallPackOutcome = {
|
|
83
|
+
readonly kind: 'installed';
|
|
84
|
+
readonly namespace: string;
|
|
85
|
+
readonly replaced: boolean;
|
|
86
|
+
} | {
|
|
87
|
+
readonly kind: 'declined';
|
|
88
|
+
readonly step: 'consent' | 'replace';
|
|
89
|
+
readonly namespace: string;
|
|
90
|
+
} | {
|
|
91
|
+
readonly kind: 'reserved';
|
|
92
|
+
readonly namespace: string;
|
|
93
|
+
} | {
|
|
94
|
+
readonly kind: 'rejected';
|
|
95
|
+
readonly reason: string;
|
|
96
|
+
} | Unsupported;
|
|
97
|
+
export type LoadPacksOutcome = {
|
|
98
|
+
readonly kind: 'loaded';
|
|
99
|
+
readonly namespaces: readonly string[];
|
|
100
|
+
/** The discovered, engine-gated packs themselves, for a host that loads their code. */
|
|
101
|
+
readonly packs: readonly DiscoveredPack[];
|
|
102
|
+
/** Folders that produced no usable pack, each with its reason. */
|
|
103
|
+
readonly skipped: readonly SkippedPackFolder[];
|
|
104
|
+
/** Every installed pack component with the engines it has a view for, dropped packs included. For an engine that draws no pack views. */
|
|
105
|
+
readonly components: readonly UnavailableComponent[];
|
|
106
|
+
/** The installed components with no view for this host's engine, for a renderer's `unavailableComponents` option. */
|
|
107
|
+
readonly unavailable: readonly UnavailableComponent[];
|
|
108
|
+
} | Unsupported;
|
|
109
|
+
export type LoadTerminalPacksOutcome = {
|
|
110
|
+
readonly kind: 'loaded';
|
|
111
|
+
readonly namespaces: readonly string[];
|
|
112
|
+
readonly packs: readonly DiscoveredPack[];
|
|
113
|
+
readonly skipped: readonly SkippedPackFolder[];
|
|
114
|
+
/** Every installed pack component with the engines it has a view for, dropped packs included. For an engine that draws no pack views. */
|
|
115
|
+
readonly components: readonly UnavailableComponent[];
|
|
116
|
+
/** The installed components with no view for the terminal engine, for its renderer's `unavailableComponents` option. */
|
|
117
|
+
readonly unavailable: readonly UnavailableComponent[];
|
|
118
|
+
/** Each terminal-capable pack's `terminal.js` text, for the engine's own loader. */
|
|
119
|
+
readonly scripts: readonly TerminalPackScript[];
|
|
120
|
+
/**
|
|
121
|
+
* The diagnostics lines that report a real failure (an unusable pack
|
|
122
|
+
* folder, a missing or unreadable `terminal.js`), as opposed to the
|
|
123
|
+
* informational ones. Every line is also written to the diagnostics
|
|
124
|
+
* surface; a host that gates informational lines behind a flag still
|
|
125
|
+
* shows these.
|
|
126
|
+
*/
|
|
127
|
+
readonly failureLines: readonly string[];
|
|
128
|
+
} | Unsupported;
|
|
129
|
+
export type RemovePackResult = RemovePackOutcome | Unsupported;
|
|
130
|
+
export type InstalledPacksOutcome = ({
|
|
131
|
+
readonly kind: 'listed';
|
|
132
|
+
} & InstalledPacksListing) | Unsupported;
|
|
133
|
+
export type EnablePackResult = EnablePackOutcome | Unsupported;
|
|
134
|
+
export type DisablePackResult = DisablePackOutcome | Unsupported;
|
|
135
|
+
export interface EditorPositionRequest {
|
|
136
|
+
readonly line: number;
|
|
137
|
+
readonly column: number;
|
|
138
|
+
/**
|
|
139
|
+
* The document the position belongs to. Omitted, the adapter's own
|
|
140
|
+
* `editor.documentText()` is read. A provider invoked for a document that
|
|
141
|
+
* is not the host's active editor (VS Code asks about any visible
|
|
142
|
+
* document) passes its own text here.
|
|
143
|
+
*/
|
|
144
|
+
readonly documentText?: string;
|
|
145
|
+
}
|
|
146
|
+
export type CompleteOutcome = {
|
|
147
|
+
readonly kind: 'completions';
|
|
148
|
+
readonly labels: readonly string[];
|
|
149
|
+
/** The full items, so a host can map them onto its own popup rows. */
|
|
150
|
+
readonly items: readonly CompletionItem[];
|
|
151
|
+
/** Zero-based columns an accepted item replaces. */
|
|
152
|
+
readonly replaceStart: number;
|
|
153
|
+
readonly replaceEnd: number;
|
|
154
|
+
/** Where the name token starts, for filtering. Equals `replaceStart` unless a colon run precedes the name. */
|
|
155
|
+
readonly tokenStart: number;
|
|
156
|
+
/** Fence rewrites to apply with an accepted container item, in one undo step, in pre-edit coordinates. Empty otherwise. */
|
|
157
|
+
readonly fenceEdits: readonly HostTextEdit[];
|
|
158
|
+
}
|
|
159
|
+
/** Nothing to offer here: no directive context, or a bare colon run closing an open container. Not a failure. */
|
|
160
|
+
| {
|
|
161
|
+
readonly kind: 'none';
|
|
162
|
+
} | Unsupported;
|
|
163
|
+
export type HoverOutcome = {
|
|
164
|
+
readonly kind: 'hover';
|
|
165
|
+
readonly text: string;
|
|
166
|
+
/** The structured documentation, for a host that renders its own markup. */
|
|
167
|
+
readonly documentation: ComponentDocumentation;
|
|
168
|
+
/** Zero-based columns of the hovered directive name, for the hover range. */
|
|
169
|
+
readonly start: number;
|
|
170
|
+
readonly end: number;
|
|
171
|
+
} | {
|
|
172
|
+
readonly kind: 'none';
|
|
173
|
+
} | Unsupported;
|
|
174
|
+
export interface InsertComponentRequest {
|
|
175
|
+
readonly name: string;
|
|
176
|
+
}
|
|
177
|
+
export type InsertOutcome = {
|
|
178
|
+
readonly kind: 'inserted';
|
|
179
|
+
/**
|
|
180
|
+
* Where a caller with its own selection/cursor concept (VS Code's
|
|
181
|
+
* `editor.selection`, Obsidian's `Editor.setCursor`) should place it
|
|
182
|
+
* once the edit lands: the position `insertComponentPlan` computed
|
|
183
|
+
* INSIDE the inserted skeleton (e.g. the blank line between a
|
|
184
|
+
* container's fences), not merely the end of the inserted text.
|
|
185
|
+
* `HostEditor.applyEdits` only reports success or failure, so this
|
|
186
|
+
* is the one place that offset survives the call.
|
|
187
|
+
*/
|
|
188
|
+
readonly cursor: LineColumn;
|
|
189
|
+
} | {
|
|
190
|
+
readonly kind: 'not-found';
|
|
191
|
+
readonly name: string;
|
|
192
|
+
} | {
|
|
193
|
+
readonly kind: 'failed';
|
|
194
|
+
} | Unsupported;
|
|
195
|
+
export interface MarkiiHost {
|
|
196
|
+
open(request: OpenRequest): Promise<OpenOutcome>;
|
|
197
|
+
run(request: RunRequest): Promise<RunOutcome>;
|
|
198
|
+
exportNote(request: ExportRequest): Promise<ExportOutcome>;
|
|
199
|
+
installPack(request: InstallPackRequest): Promise<InstallPackOutcome>;
|
|
200
|
+
loadPacks(): Promise<LoadPacksOutcome>;
|
|
201
|
+
/**
|
|
202
|
+
* `loadPacks` for a host running the terminal engine: also reads each
|
|
203
|
+
* pack's `terminal.js`. Unsupported unless the adapter's pack source
|
|
204
|
+
* declares the `ansi` engine.
|
|
205
|
+
*/
|
|
206
|
+
loadTerminalPacks(): Promise<LoadTerminalPacksOutcome>;
|
|
207
|
+
/** Removes one installed pack by namespace, through the install root. Writes its outcome to the diagnostics surface. Under `trust: 'device-list'` it also withdraws the namespace's trust entry. */
|
|
208
|
+
removePack(namespace: string): Promise<RemovePackResult>;
|
|
209
|
+
/**
|
|
210
|
+
* Under `trust: 'device-list'`: the install root's folders split into the
|
|
211
|
+
* ones this device has enabled and the ones merely present. Unsupported
|
|
212
|
+
* for a host that does not declare the trust list.
|
|
213
|
+
*/
|
|
214
|
+
installedPacks(): Promise<InstalledPacksOutcome>;
|
|
215
|
+
/** Asks the install consent prompt, then trusts an installed folder on this device. Unsupported without the trust list. */
|
|
216
|
+
enablePack(namespace: string): Promise<EnablePackResult>;
|
|
217
|
+
/** Withdraws a namespace's trust entry and leaves its folder in place. Unsupported without the trust list. */
|
|
218
|
+
disablePack(namespace: string): Promise<DisablePackResult>;
|
|
219
|
+
completeAt(request: EditorPositionRequest): Promise<CompleteOutcome>;
|
|
220
|
+
/**
|
|
221
|
+
* `completeAt` for a caller that must answer synchronously (Obsidian's
|
|
222
|
+
* `EditorSuggest.onTrigger`). Reads the cached catalog; while the cache
|
|
223
|
+
* is cold it answers from the standard set and starts warming the cache,
|
|
224
|
+
* so the next request sees installed packs.
|
|
225
|
+
*/
|
|
226
|
+
completeAtSync(request: EditorPositionRequest): CompleteOutcome;
|
|
227
|
+
/** Drops the cached completion/hover catalog, for a host whose pack folders just changed. `installPack` and `loadPacks` do this themselves. */
|
|
228
|
+
invalidateCatalog(): void;
|
|
229
|
+
hoverAt(request: EditorPositionRequest): Promise<HoverOutcome>;
|
|
230
|
+
insertComponent(request: InsertComponentRequest): Promise<InsertOutcome>;
|
|
231
|
+
diagnostics(line: string): void;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Injectables a test needs to make a run/export deterministic. Defaults
|
|
235
|
+
* are the real implementations; no option changes behavior for a real
|
|
236
|
+
* host.
|
|
237
|
+
*/
|
|
238
|
+
export interface MarkiiHostOptions {
|
|
239
|
+
readonly spawnRun?: (options: SpawnRunRequest) => Promise<RunResult>;
|
|
240
|
+
/** The `.mkp` extraction filesystem `installPack` writes through. Required for a host that installs packs (`createNodeArchiveExtractFs()` from `@markii/host/node`); without it `installPack` is `Unsupported`. */
|
|
241
|
+
readonly archiveExtractFs?: ArchiveExtractFs;
|
|
242
|
+
/** The static HTML engine behind the `html` and `pdf` exports (`createHtmlExportEngine()` from `@markii/host/node`). Without it those formats decline, like `renderAnsi` for `ansi`. */
|
|
243
|
+
readonly htmlEngine?: HtmlExportEngine;
|
|
244
|
+
/** Pack discovery's file reads. Defaults to reads through the adapter's own `readFile` and `listFolder`. */
|
|
245
|
+
readonly packDiscoveryIo?: PackDiscoveryIo;
|
|
246
|
+
/** `@markii/ansi`'s renderer, injected because this package never depends on `@markii/ansi` (a platform renderer, never a `@markii/host` dependency). A host declaring `'ansi'` in `adapter.exports.formats` without supplying this gets `Unsupported` at export time. */
|
|
247
|
+
readonly renderAnsi?: (text: string) => Promise<string>;
|
|
248
|
+
/** Composes a pack-aware render registry (webview registration, in-process evaluation, ...). Reserved for a future slice that renders through `exportNote`'s `html` path with packs; unused today, since `buildExportDocument`'s default (no `renderBody`) already produces a correct, pack-free static export. */
|
|
249
|
+
readonly buildPackRegistration?: unknown;
|
|
250
|
+
}
|
|
251
|
+
export declare function createMarkiiHost(adapter: HostAdapter, options?: MarkiiHostOptions): MarkiiHost;
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { runViaAdapter, } from './run-behavior.js';
|
|
2
|
+
import { installPackDiagnosticLines, installPackFromArchive, } from './pack-install.js';
|
|
3
|
+
import { loadPacksViaAdapter, packDiscoveryIoFromAdapter, } from './pack-load.js';
|
|
4
|
+
import { buildComponentCatalog } from '../insert/component-catalog.js';
|
|
5
|
+
import { formatPackDiagnosticLines, skippedPackFolderLine, } from '../packs/pack-diagnostics.js';
|
|
6
|
+
import { readTerminalPackScripts, } from './terminal-packs.js';
|
|
7
|
+
import { removePackDiagnosticLine, removePackViaAdapter, } from './pack-remove.js';
|
|
8
|
+
import { formatComponentDocumentation } from '@markii/stdlib/editor';
|
|
9
|
+
import { exportDiagnosticLines, exportNoteFileViaAdapter, } from './export-behavior.js';
|
|
10
|
+
import { disablePackDiagnosticLine, disablePackViaAdapter, enablePackDiagnosticLine, enablePackViaAdapter, forgetPackTrust, listInstalledPacks, notEnabledPackDiagnosticLine, trustedPackFolders, usesPackTrust, } from './pack-trust-behavior.js';
|
|
11
|
+
import { completionPlanAt, createCatalogCache, hoverAtViaEditor, insertComponentPlan, } from './editor-behavior.js';
|
|
12
|
+
function unsupported(adapter, capability, detail) {
|
|
13
|
+
adapter.diagnostics(`declined (${capability} unsupported on ${adapter.id}): ${detail}`);
|
|
14
|
+
return { kind: 'unsupported', capability, detail };
|
|
15
|
+
}
|
|
16
|
+
export function createMarkiiHost(adapter, options = {}) {
|
|
17
|
+
const packIo = options.packDiscoveryIo ?? packDiscoveryIoFromAdapter(adapter);
|
|
18
|
+
/**
|
|
19
|
+
* The pack source every load reads: under `trust: 'device-list'` the
|
|
20
|
+
* trusted installed folders are added to what the adapter authorizes, so
|
|
21
|
+
* an untrusted folder is never a candidate for discovery. Other hosts
|
|
22
|
+
* get their own source back unchanged.
|
|
23
|
+
*/
|
|
24
|
+
function packSource(packs) {
|
|
25
|
+
if (!usesPackTrust(adapter))
|
|
26
|
+
return packs;
|
|
27
|
+
return {
|
|
28
|
+
...packs,
|
|
29
|
+
authorizedFolders: async () => [
|
|
30
|
+
...(await packs.authorizedFolders()),
|
|
31
|
+
...(await trustedPackFolders(adapter)),
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** The pack-aware insert/completion catalog, built fresh from this host's currently authorized folders. Not cached here: `./editor-behavior.js`'s `createCatalogCache` is the caching seam, and a caller wiring a live editor (repeated completion/hover calls per keystroke) is expected to wrap this call in one. */
|
|
36
|
+
async function currentCatalog() {
|
|
37
|
+
if (!adapter.packs)
|
|
38
|
+
return buildComponentCatalog([]);
|
|
39
|
+
const { packs } = await loadPacksViaAdapter(packSource(adapter.packs), packIo);
|
|
40
|
+
return buildComponentCatalog([...(adapter.packs.bundledPacks?.() ?? []), ...packs], adapter.packs.engine);
|
|
41
|
+
}
|
|
42
|
+
/** Completion and hover fire per keystroke, so they read a cached catalog. `insertComponent` stays uncached: it runs once per command. */
|
|
43
|
+
const catalogCache = createCatalogCache(currentCatalog);
|
|
44
|
+
function documentTextFor(editor, request) {
|
|
45
|
+
return request.documentText ?? editor.documentText();
|
|
46
|
+
}
|
|
47
|
+
function completeWith(catalog, request, editor) {
|
|
48
|
+
const plan = completionPlanAt(documentTextFor(editor, request), request, catalog);
|
|
49
|
+
if (plan === undefined)
|
|
50
|
+
return { kind: 'none' };
|
|
51
|
+
return {
|
|
52
|
+
kind: 'completions',
|
|
53
|
+
labels: plan.items.map((item) => item.label),
|
|
54
|
+
items: plan.items,
|
|
55
|
+
replaceStart: plan.replaceStart,
|
|
56
|
+
replaceEnd: plan.replaceEnd,
|
|
57
|
+
tokenStart: plan.tokenStart,
|
|
58
|
+
fenceEdits: plan.fenceEdits,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
async open(request) {
|
|
63
|
+
try {
|
|
64
|
+
const bytes = await adapter.readFile(request.path);
|
|
65
|
+
return { kind: 'opened', text: new TextDecoder().decode(bytes) };
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
69
|
+
adapter.diagnostics(`could not open ${request.path}: ${reason}`);
|
|
70
|
+
return { kind: 'failed', reason };
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
async run(request) {
|
|
74
|
+
if (!adapter.isolate) {
|
|
75
|
+
return unsupported(adapter, 'isolate', 'no isolate is configured, so scripts cannot run.');
|
|
76
|
+
}
|
|
77
|
+
const result = await runViaAdapter(adapter, request, options.spawnRun);
|
|
78
|
+
return { kind: 'ran', ...result };
|
|
79
|
+
},
|
|
80
|
+
async exportNote(request) {
|
|
81
|
+
const formats = adapter.exports?.formats;
|
|
82
|
+
if (formats === undefined || !formats.has(request.format)) {
|
|
83
|
+
return unsupported(adapter, 'export-format', `export format "${request.format}" is not available on ${adapter.id}.`);
|
|
84
|
+
}
|
|
85
|
+
const outcome = await exportNoteFileViaAdapter(adapter, request.format, {
|
|
86
|
+
...(options.htmlEngine !== undefined
|
|
87
|
+
? { engine: options.htmlEngine }
|
|
88
|
+
: {}),
|
|
89
|
+
notePath: request.notePath,
|
|
90
|
+
text: request.text,
|
|
91
|
+
...(request.values !== undefined ? { values: request.values } : {}),
|
|
92
|
+
...(request.unavailableComponents !== undefined
|
|
93
|
+
? { unavailableComponents: request.unavailableComponents }
|
|
94
|
+
: {}),
|
|
95
|
+
...(request.onDiagnostic !== undefined
|
|
96
|
+
? { onDiagnostic: request.onDiagnostic }
|
|
97
|
+
: {}),
|
|
98
|
+
}, options.renderAnsi);
|
|
99
|
+
if (outcome === undefined) {
|
|
100
|
+
adapter.diagnostics(`export declined: format "${request.format}" has no working export path on ${adapter.id} (a cancelled picker, or a missing renderer/PDF seam).`);
|
|
101
|
+
return { kind: 'cancelled' };
|
|
102
|
+
}
|
|
103
|
+
for (const line of exportDiagnosticLines(outcome)) {
|
|
104
|
+
adapter.diagnostics(line);
|
|
105
|
+
}
|
|
106
|
+
if (outcome.kind === 'failed') {
|
|
107
|
+
return { kind: 'failed', reason: outcome.reason };
|
|
108
|
+
}
|
|
109
|
+
return { kind: 'exported', path: outcome.path, bytes: outcome.bytes };
|
|
110
|
+
},
|
|
111
|
+
async installPack(request) {
|
|
112
|
+
if (!adapter.packs?.installRoot) {
|
|
113
|
+
return unsupported(adapter, 'packs', 'this host has no pack-install destination configured.');
|
|
114
|
+
}
|
|
115
|
+
const archivePath = request.archivePath ?? 'the selected archive';
|
|
116
|
+
const extractFs = options.archiveExtractFs;
|
|
117
|
+
if (extractFs === undefined) {
|
|
118
|
+
return unsupported(adapter, 'packs', 'this host was given no archive extraction filesystem.');
|
|
119
|
+
}
|
|
120
|
+
const outcome = await installPackFromArchive(adapter, {
|
|
121
|
+
archiveBytes: request.archiveBytes,
|
|
122
|
+
archivePath,
|
|
123
|
+
installRoot: adapter.packs.installRoot(),
|
|
124
|
+
exists: (path) => adapter.exists(path),
|
|
125
|
+
extractFs,
|
|
126
|
+
reservedNamespaces: adapter.packs.reservedNamespaces(),
|
|
127
|
+
});
|
|
128
|
+
catalogCache.invalidate();
|
|
129
|
+
for (const line of installPackDiagnosticLines(outcome, archivePath)) {
|
|
130
|
+
adapter.diagnostics(line);
|
|
131
|
+
}
|
|
132
|
+
if (outcome.kind === 'installed') {
|
|
133
|
+
return {
|
|
134
|
+
kind: 'installed',
|
|
135
|
+
namespace: outcome.packName,
|
|
136
|
+
replaced: outcome.replaced,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (outcome.kind === 'declined') {
|
|
140
|
+
return {
|
|
141
|
+
kind: 'declined',
|
|
142
|
+
step: outcome.step,
|
|
143
|
+
namespace: outcome.packName,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
if (outcome.kind === 'reserved') {
|
|
147
|
+
return { kind: 'reserved', namespace: outcome.packName };
|
|
148
|
+
}
|
|
149
|
+
return { kind: 'rejected', reason: outcome.reason };
|
|
150
|
+
},
|
|
151
|
+
async loadPacks() {
|
|
152
|
+
if (!adapter.packs) {
|
|
153
|
+
return unsupported(adapter, 'packs', 'this host has no pack folders configured.');
|
|
154
|
+
}
|
|
155
|
+
catalogCache.invalidate();
|
|
156
|
+
const result = await loadPacksViaAdapter(packSource(adapter.packs), packIo);
|
|
157
|
+
for (const line of formatPackDiagnosticLines({
|
|
158
|
+
packs: result.packs,
|
|
159
|
+
skipped: result.skipped,
|
|
160
|
+
engine: adapter.packs.engine,
|
|
161
|
+
cssWarnings: [],
|
|
162
|
+
})) {
|
|
163
|
+
adapter.diagnostics(line);
|
|
164
|
+
}
|
|
165
|
+
if (usesPackTrust(adapter)) {
|
|
166
|
+
for (const namespace of (await listInstalledPacks(adapter))
|
|
167
|
+
.notEnabled) {
|
|
168
|
+
adapter.diagnostics(notEnabledPackDiagnosticLine(namespace, adapter.labels.deviceNoun));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
kind: 'loaded',
|
|
173
|
+
namespaces: result.namespaces,
|
|
174
|
+
packs: result.packs,
|
|
175
|
+
skipped: result.skipped,
|
|
176
|
+
components: result.components,
|
|
177
|
+
unavailable: result.unavailable,
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
async loadTerminalPacks() {
|
|
181
|
+
if (!adapter.packs) {
|
|
182
|
+
return unsupported(adapter, 'packs', 'this host has no pack folders configured.');
|
|
183
|
+
}
|
|
184
|
+
if (adapter.packs.engine !== 'ansi') {
|
|
185
|
+
return unsupported(adapter, 'packs', 'this host does not run the terminal engine, so it has no terminal packs.');
|
|
186
|
+
}
|
|
187
|
+
catalogCache.invalidate();
|
|
188
|
+
const result = await loadPacksViaAdapter(packSource(adapter.packs), packIo);
|
|
189
|
+
const read = await readTerminalPackScripts(adapter, result.packs);
|
|
190
|
+
for (const line of formatPackDiagnosticLines({
|
|
191
|
+
packs: result.packs,
|
|
192
|
+
skipped: result.skipped,
|
|
193
|
+
engine: 'ansi',
|
|
194
|
+
cssWarnings: [],
|
|
195
|
+
})) {
|
|
196
|
+
adapter.diagnostics(line);
|
|
197
|
+
}
|
|
198
|
+
for (const line of read.problems)
|
|
199
|
+
adapter.diagnostics(line);
|
|
200
|
+
const failureLines = [
|
|
201
|
+
...result.skipped
|
|
202
|
+
.filter((entry) => entry.engineUnsupported === undefined)
|
|
203
|
+
.map(skippedPackFolderLine),
|
|
204
|
+
...read.problems,
|
|
205
|
+
];
|
|
206
|
+
return {
|
|
207
|
+
kind: 'loaded',
|
|
208
|
+
namespaces: result.namespaces,
|
|
209
|
+
packs: result.packs,
|
|
210
|
+
skipped: result.skipped,
|
|
211
|
+
components: result.components,
|
|
212
|
+
unavailable: result.unavailable,
|
|
213
|
+
scripts: read.scripts,
|
|
214
|
+
failureLines,
|
|
215
|
+
};
|
|
216
|
+
},
|
|
217
|
+
async removePack(namespace) {
|
|
218
|
+
const packs = adapter.packs;
|
|
219
|
+
if (!packs?.installRoot || !packs.removeFolder) {
|
|
220
|
+
return unsupported(adapter, 'packs', 'this host has no pack-install destination configured.');
|
|
221
|
+
}
|
|
222
|
+
const outcome = await removePackViaAdapter(adapter, namespace, packs.installRoot(), packs.removeFolder.bind(packs), packs.reservedNamespaces());
|
|
223
|
+
catalogCache.invalidate();
|
|
224
|
+
// The trust entry goes whatever happened to the folder: this device
|
|
225
|
+
// has withdrawn its authorization, so the pack stops loading. Only a
|
|
226
|
+
// refused or malformed request leaves the list alone.
|
|
227
|
+
if (outcome.kind !== 'reserved' && outcome.kind !== 'invalid') {
|
|
228
|
+
await forgetPackTrust(adapter, namespace);
|
|
229
|
+
}
|
|
230
|
+
adapter.diagnostics(removePackDiagnosticLine(outcome));
|
|
231
|
+
return outcome;
|
|
232
|
+
},
|
|
233
|
+
async installedPacks() {
|
|
234
|
+
if (!usesPackTrust(adapter)) {
|
|
235
|
+
return unsupported(adapter, 'pack-trust', 'this host does not gate installed packs on a trust list.');
|
|
236
|
+
}
|
|
237
|
+
return { kind: 'listed', ...(await listInstalledPacks(adapter)) };
|
|
238
|
+
},
|
|
239
|
+
async enablePack(namespace) {
|
|
240
|
+
if (!usesPackTrust(adapter)) {
|
|
241
|
+
return unsupported(adapter, 'pack-trust', 'this host does not gate installed packs on a trust list.');
|
|
242
|
+
}
|
|
243
|
+
const outcome = await enablePackViaAdapter(adapter, namespace);
|
|
244
|
+
catalogCache.invalidate();
|
|
245
|
+
adapter.diagnostics(enablePackDiagnosticLine(outcome));
|
|
246
|
+
return outcome;
|
|
247
|
+
},
|
|
248
|
+
async disablePack(namespace) {
|
|
249
|
+
if (!usesPackTrust(adapter)) {
|
|
250
|
+
return unsupported(adapter, 'pack-trust', 'this host does not gate installed packs on a trust list.');
|
|
251
|
+
}
|
|
252
|
+
const outcome = await disablePackViaAdapter(adapter, namespace);
|
|
253
|
+
catalogCache.invalidate();
|
|
254
|
+
adapter.diagnostics(disablePackDiagnosticLine(outcome));
|
|
255
|
+
return outcome;
|
|
256
|
+
},
|
|
257
|
+
async completeAt(request) {
|
|
258
|
+
const editor = adapter.editor;
|
|
259
|
+
if (!editor) {
|
|
260
|
+
return unsupported(adapter, 'editor', 'completion is not available: this host has no live editor.');
|
|
261
|
+
}
|
|
262
|
+
return completeWith(await catalogCache.get(), request, editor);
|
|
263
|
+
},
|
|
264
|
+
completeAtSync(request) {
|
|
265
|
+
const editor = adapter.editor;
|
|
266
|
+
if (!editor) {
|
|
267
|
+
return unsupported(adapter, 'editor', 'completion is not available: this host has no live editor.');
|
|
268
|
+
}
|
|
269
|
+
const warm = catalogCache.peek();
|
|
270
|
+
if (warm === undefined)
|
|
271
|
+
void catalogCache.get();
|
|
272
|
+
return completeWith(warm ?? buildComponentCatalog([]), request, editor);
|
|
273
|
+
},
|
|
274
|
+
invalidateCatalog() {
|
|
275
|
+
catalogCache.invalidate();
|
|
276
|
+
},
|
|
277
|
+
async hoverAt(request) {
|
|
278
|
+
const editor = adapter.editor;
|
|
279
|
+
if (!editor) {
|
|
280
|
+
return unsupported(adapter, 'editor', 'hover is not available: this host has no live editor.');
|
|
281
|
+
}
|
|
282
|
+
const catalog = await catalogCache.get();
|
|
283
|
+
const hover = hoverAtViaEditor({ documentText: () => documentTextFor(editor, request) }, request, catalog);
|
|
284
|
+
if (hover === undefined)
|
|
285
|
+
return { kind: 'none' };
|
|
286
|
+
// The formatted text (summary, attributes, and the usage example),
|
|
287
|
+
// not the bare summary sentence: a component's description alone
|
|
288
|
+
// often never repeats its own directive name (see
|
|
289
|
+
// `./editor-behavior.js`'s `hoverDocumentationText` doc comment),
|
|
290
|
+
// while the usage example always does.
|
|
291
|
+
return {
|
|
292
|
+
kind: 'hover',
|
|
293
|
+
text: formatComponentDocumentation(hover.documentation),
|
|
294
|
+
documentation: hover.documentation,
|
|
295
|
+
start: hover.start,
|
|
296
|
+
end: hover.end,
|
|
297
|
+
};
|
|
298
|
+
},
|
|
299
|
+
async insertComponent(request) {
|
|
300
|
+
if (!adapter.editor) {
|
|
301
|
+
return unsupported(adapter, 'editor', 'insert component is not available: this host has no live editor.');
|
|
302
|
+
}
|
|
303
|
+
const catalog = await currentCatalog();
|
|
304
|
+
const component = catalog.find((entry) => entry.directiveName === request.name);
|
|
305
|
+
if (component === undefined) {
|
|
306
|
+
adapter.diagnostics(`insert component: no catalog entry named "${request.name}".`);
|
|
307
|
+
return { kind: 'not-found', name: request.name };
|
|
308
|
+
}
|
|
309
|
+
const cursor = adapter.editor.cursor();
|
|
310
|
+
const documentText = adapter.editor.documentText();
|
|
311
|
+
const plan = insertComponentPlan(component, documentText, cursor.line, cursor.column);
|
|
312
|
+
const edits = plan.edits.map((edit) => ({
|
|
313
|
+
line: edit.line,
|
|
314
|
+
startColumn: edit.startColumn,
|
|
315
|
+
endColumn: edit.endColumn,
|
|
316
|
+
text: edit.text,
|
|
317
|
+
}));
|
|
318
|
+
const applied = await adapter.editor.applyEdits(edits);
|
|
319
|
+
if (!applied) {
|
|
320
|
+
adapter.diagnostics(`insert component: the host declined to apply the edit for "${request.name}".`);
|
|
321
|
+
return { kind: 'failed' };
|
|
322
|
+
}
|
|
323
|
+
return { kind: 'inserted', cursor: plan.cursor };
|
|
324
|
+
},
|
|
325
|
+
diagnostics(line) {
|
|
326
|
+
adapter.diagnostics(line);
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
}
|