@lapis-notes/api 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/CHANGELOG.md +304 -13
  2. package/README.md +19 -0
  3. package/dist/__tests__/fixtures/indexed-mutations.json +6862 -0
  4. package/dist/__tests__/fixtures/memory-storage.json +309 -0
  5. package/dist/__tests__/fixtures/native-facade-contract.json +3224 -0
  6. package/dist/__tests__/fixtures/projection-query.json +195 -0
  7. package/dist/__tests__/fixtures/projection-values.json +60 -0
  8. package/dist/__tests__/fixtures/search-preparation.json +1513 -0
  9. package/dist/__tests__/fixtures/search-retrieval.json +15409 -0
  10. package/dist/__tests__/fixtures/search-semantic-model.json +3691 -0
  11. package/dist/__tests__/fixtures/search-semantic-retrieval.json +6603 -0
  12. package/dist/__tests__/fixtures/search-storage.json +409 -0
  13. package/dist/__tests__/fixtures/task-projection.json +428 -0
  14. package/dist/__tests__/indexed-mutation-support.js +262 -0
  15. package/dist/__tests__/projection-query-support.js +40 -0
  16. package/dist/__tests__/search-retrieval-support.js +47 -0
  17. package/dist/app-database-host.d.ts +1 -0
  18. package/dist/app-shell-plugin-persistence.d.ts +3 -2
  19. package/dist/app-shell-plugin-persistence.js +37 -3
  20. package/dist/cache.svelte.d.ts +8 -1
  21. package/dist/cache.svelte.js +103 -5
  22. package/dist/command.svelte.js +29 -2
  23. package/dist/components/editor/editor.css +4 -0
  24. package/dist/components/editor/editor.svelte +24 -11
  25. package/dist/components/editor/embedded-editor-surface.js +3 -1
  26. package/dist/components/editor/inline-title-alignment.d.ts +3 -0
  27. package/dist/components/editor/inline-title-alignment.js +57 -0
  28. package/dist/configuration.svelte.d.ts +270 -206
  29. package/dist/configuration.svelte.js +161 -86
  30. package/dist/context.svelte.d.ts +23 -3
  31. package/dist/context.svelte.js +68 -30
  32. package/dist/diagnostics.d.ts +8 -0
  33. package/dist/diagnostics.js +6 -0
  34. package/dist/editor-save-context.d.ts +35 -0
  35. package/dist/editor-save-context.js +132 -0
  36. package/dist/editor-view-registry.d.ts +10 -0
  37. package/dist/editor-view-registry.js +44 -4
  38. package/dist/editor.svelte.d.ts +19 -1
  39. package/dist/editor.svelte.js +528 -55
  40. package/dist/embed-registry.d.ts +10 -0
  41. package/dist/embed-registry.js +15 -0
  42. package/dist/file-editing-failures.d.ts +2 -0
  43. package/dist/file-editing-failures.js +29 -0
  44. package/dist/file-editing-native-issues.d.ts +19 -0
  45. package/dist/file-editing-native-issues.js +65 -0
  46. package/dist/file-editing-sessions.d.ts +76 -0
  47. package/dist/file-editing-sessions.js +367 -0
  48. package/dist/file-manager.d.ts +9 -1
  49. package/dist/file-manager.js +45 -3
  50. package/dist/file-state-store.d.ts +5 -0
  51. package/dist/file-state-store.js +34 -0
  52. package/dist/file-text-conflicts.d.ts +25 -0
  53. package/dist/file-text-conflicts.js +35 -0
  54. package/dist/file-text-mutation.d.ts +13 -0
  55. package/dist/file-text-mutation.js +100 -0
  56. package/dist/file-text-persistence.d.ts +36 -0
  57. package/dist/file-text-persistence.js +234 -0
  58. package/dist/file-text-state-writer.d.ts +34 -0
  59. package/dist/file-text-state-writer.js +183 -0
  60. package/dist/files-configuration.d.ts +20 -0
  61. package/dist/files-configuration.js +47 -0
  62. package/dist/generated/plugin-host-modules.schema.generated.d.ts +114 -34
  63. package/dist/generated/plugin-host-modules.schema.generated.js +132 -34
  64. package/dist/glob.d.ts +3 -0
  65. package/dist/glob.js +2 -1
  66. package/dist/icons/changes.d.ts +3 -0
  67. package/dist/icons/changes.js +16 -0
  68. package/dist/icons/index.d.ts +5 -1
  69. package/dist/icons/index.js +44 -3
  70. package/dist/icons/registry.d.ts +35 -0
  71. package/dist/icons/registry.js +154 -0
  72. package/dist/icons/safe-svg.d.ts +2 -0
  73. package/dist/icons/safe-svg.js +44 -0
  74. package/dist/index.d.ts +6 -1
  75. package/dist/index.js +4 -1
  76. package/dist/lapis-extension.d.ts +6 -2
  77. package/dist/lapis-extension.js +2 -0
  78. package/dist/metadata-store.d.ts +23 -0
  79. package/dist/metadata-store.js +1 -0
  80. package/dist/metadata.svelte.js +45 -2
  81. package/dist/native-background-indexing.d.ts +48 -0
  82. package/dist/native-background-indexing.js +208 -0
  83. package/dist/native-database-protocol.d.ts +29 -0
  84. package/dist/native-database-protocol.js +1 -0
  85. package/dist/native-editing-intent-lease.d.ts +17 -0
  86. package/dist/native-editing-intent-lease.js +188 -0
  87. package/dist/native-editing-intents-protocol.d.ts +70 -0
  88. package/dist/native-editing-intents-protocol.js +1 -0
  89. package/dist/native-editing-intents.d.ts +8 -0
  90. package/dist/native-editing-intents.js +1 -0
  91. package/dist/native-editing-problems.d.ts +3 -0
  92. package/dist/native-editing-problems.js +180 -0
  93. package/dist/native-editing-recovery.d.ts +24 -0
  94. package/dist/native-editing-recovery.js +198 -0
  95. package/dist/native-editing-session.d.ts +51 -0
  96. package/dist/native-editing-session.js +251 -0
  97. package/dist/native-history-index-protocol.d.ts +80 -0
  98. package/dist/native-history-index-protocol.js +1 -0
  99. package/dist/native-history-index.d.ts +6 -0
  100. package/dist/native-history-index.js +1 -0
  101. package/dist/native-indexing-protocol.d.ts +63 -0
  102. package/dist/native-indexing-protocol.js +1 -0
  103. package/dist/native-participant-protocol.d.ts +67 -0
  104. package/dist/native-participant-protocol.js +3 -0
  105. package/dist/native-queue-protocol.d.ts +73 -0
  106. package/dist/native-queue-protocol.js +3 -0
  107. package/dist/native-tasks-protocol.d.ts +264 -0
  108. package/dist/native-tasks-protocol.js +1 -0
  109. package/dist/native-tasks.d.ts +35 -0
  110. package/dist/native-tasks.js +79 -0
  111. package/dist/native-turn-protocol.d.ts +81 -0
  112. package/dist/native-turn-protocol.js +1 -0
  113. package/dist/native-turns.d.ts +29 -0
  114. package/dist/native-turns.js +2 -0
  115. package/dist/plugin-asset-server.js +3 -2
  116. package/dist/plugin-dependency-resolver.d.ts +1 -1
  117. package/dist/plugin-distribution/compatibility.d.ts +1 -1
  118. package/dist/plugin-distribution/compatibility.js +10 -5
  119. package/dist/plugin-distribution/installed-plugin-state.js +2 -1
  120. package/dist/plugin-distribution/installer.d.ts +6 -0
  121. package/dist/plugin-distribution/installer.js +90 -37
  122. package/dist/plugin-distribution/manager.d.ts +4 -1
  123. package/dist/plugin-distribution/manager.js +12 -5
  124. package/dist/plugin-distribution/registry-cache.js +2 -1
  125. package/dist/plugin-distribution/registry-source-state.js +2 -1
  126. package/dist/plugin-distribution/schemas.d.ts +26 -8
  127. package/dist/plugin-distribution/schemas.js +2 -1
  128. package/dist/plugin-distribution/types.d.ts +4 -0
  129. package/dist/plugin-manager.d.ts +21 -5
  130. package/dist/plugin-manager.js +228 -64
  131. package/dist/plugin-runtime-entry.d.ts +1 -1
  132. package/dist/plugin-runtime-entry.js +16 -0
  133. package/dist/plugin.d.ts +19 -3
  134. package/dist/plugin.js +110 -44
  135. package/dist/registry-schema/catalog-v1.d.ts +60 -9
  136. package/dist/registry-schema/catalog-v1.js +2 -1
  137. package/dist/registry-schema/catalog-v2.d.ts +60 -9
  138. package/dist/registry-schema/catalog-v2.js +1 -1
  139. package/dist/search-result-provider.d.ts +95 -0
  140. package/dist/search-result-provider.js +42 -0
  141. package/dist/status-bar.svelte.d.ts +26 -20
  142. package/dist/status-bar.svelte.js +1 -0
  143. package/dist/storage/app-database.d.ts +9 -23
  144. package/dist/storage/app-database.js +41 -34
  145. package/dist/storage/desktop-native.d.ts +5 -3
  146. package/dist/storage/desktop-native.js +59 -6
  147. package/dist/storage/directory-watcher.d.ts +27 -0
  148. package/dist/storage/directory-watcher.js +201 -0
  149. package/dist/storage/fs.d.ts +14 -27
  150. package/dist/storage/fs.js +2 -168
  151. package/dist/storage/index-projection.js +33 -15
  152. package/dist/storage/memory-vault-adapter.d.ts +2 -0
  153. package/dist/storage/memory-vault-adapter.js +14 -1
  154. package/dist/storage/path.d.ts +6 -2
  155. package/dist/storage/path.js +8 -2
  156. package/dist/storage/projection-query-candidates.d.ts +3 -0
  157. package/dist/storage/projection-query-candidates.js +69 -0
  158. package/dist/storage/remote-app-database.d.ts +2 -2
  159. package/dist/storage/remote-app-database.js +1 -1
  160. package/dist/storage/runtime.d.ts +3 -0
  161. package/dist/storage/runtime.js +3 -0
  162. package/dist/storage/search-embedding-record.d.ts +3 -0
  163. package/dist/storage/search-embedding-record.js +18 -0
  164. package/dist/storage/turso-app-database.d.ts +2 -0
  165. package/dist/storage/turso-app-database.js +67 -30
  166. package/dist/storage/vault-listing.d.ts +3 -0
  167. package/dist/storage/vault-listing.js +36 -0
  168. package/dist/storage/vault-reconciliation.d.ts +19 -0
  169. package/dist/storage/vault-reconciliation.js +137 -0
  170. package/dist/storage/vault-session.d.ts +8 -0
  171. package/dist/storage/vault-session.js +10 -2
  172. package/dist/storage/vault.svelte.d.ts +53 -4
  173. package/dist/storage/vault.svelte.js +223 -87
  174. package/dist/sync-editor-flush.d.ts +6 -0
  175. package/dist/sync-editor-flush.js +22 -0
  176. package/dist/sync-host-local.d.ts +15 -0
  177. package/dist/sync-host-local.js +228 -0
  178. package/dist/sync-host-security.d.ts +24 -9
  179. package/dist/sync-host-security.js +47 -14
  180. package/dist/sync-host.d.ts +33 -4
  181. package/dist/sync-host.js +160 -10
  182. package/dist/sync-repository.d.ts +106 -0
  183. package/dist/sync-repository.js +18 -0
  184. package/dist/vault-change-views.d.ts +4 -0
  185. package/dist/vault-change-views.js +43 -0
  186. package/dist/vault-changes.d.ts +37 -0
  187. package/dist/vault-changes.js +228 -0
  188. package/dist/view.svelte.d.ts +182 -149
  189. package/dist/view.svelte.js +39 -21
  190. package/dist/workspace-close-guard.d.ts +3 -0
  191. package/dist/workspace-close-guard.js +35 -0
  192. package/dist/workspace-host-internal.js +10 -2
  193. package/dist/workspace-layout-normalizer.d.ts +4 -2
  194. package/dist/workspace-layout-normalizer.js +5 -5
  195. package/dist/workspace-view-document.d.ts +3 -0
  196. package/dist/workspace-view-document.js +12 -0
  197. package/dist/workspace.svelte.d.ts +13 -2
  198. package/dist/workspace.svelte.js +371 -82
  199. package/package.json +61 -8
@@ -4,7 +4,12 @@ import type { Menu } from "./menu.svelte";
4
4
  import { Editor } from "./editor.svelte";
5
5
  import type { App } from "./context.svelte";
6
6
  import "./enhance";
7
- import { EventDispatcher, type EventNames, type EventRef, type ValidEventTypes } from "./events";
7
+ import {
8
+ EventDispatcher,
9
+ type EventNames,
10
+ type EventRef,
11
+ type ValidEventTypes,
12
+ } from "./events";
8
13
  import type { Scope } from "./command.svelte";
9
14
  /**
10
15
  * Base lifecycle helper used throughout the public API.
@@ -14,70 +19,89 @@ import type { Scope } from "./command.svelte";
14
19
  *
15
20
  * @public
16
21
  */
17
- export declare abstract class Component<Events extends ValidEventTypes = Record<string, any>> extends EventDispatcher<Events> {
18
- children: Component[];
19
- private unloaders;
20
- loaded: boolean;
21
- protected _containerEl: HTMLElement;
22
- get containerEl(): HTMLElement;
23
- set containerEl(el: HTMLElement);
24
- /**
25
- * Load this component and its children
26
- *
27
- * @public
28
- */
29
- load(): void;
30
- /**
31
- * Override this to load your component
32
- *
33
- * @abstract
34
- * @public
35
- */
36
- onload(): Promise<void> | void;
37
- protected loadAsync(): Promise<void>;
38
- /**
39
- * Unload this component and its children
40
- *
41
- * @public
42
- */
43
- unload(): void;
44
- protected unloadAsync(): Promise<void>;
45
- /**
46
- * Override this to unload your component
47
- *
48
- * @abstract
49
- * @public
50
- */
51
- onunload(): void;
52
- private cleanupAsync;
53
- /**
54
- * Adds a child component, loading it if this component is loaded
55
- *
56
- * @public
57
- */
58
- addChild<T extends Component>(component: T): T;
59
- /**
60
- * Removes a child component, unloading it
61
- *
62
- * @public
63
- */
64
- removeChild<T extends Component>(component: T): T;
65
- /**
66
- * Registers a callback to be called when unloading
67
- *
68
- * @public
69
- */
70
- register(cb: () => any): void;
71
- registerEvent<T extends ValidEventTypes, K extends EventNames<T>>(eventRef: EventRef<T, K, any>): void;
72
- registerInterval(id: ReturnType<typeof setInterval>): void;
73
- /**
74
- * Registers an DOM event to be detached when unloading
75
- *
76
- * @public
77
- */
78
- registerDomEvent<K extends keyof HTMLElementEventMap>(el: HTMLElement, type: K, callback: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
79
- registerDomEvent<K extends keyof DocumentEventMap>(el: Document, type: K, callback: (this: HTMLElement, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
80
- registerDomEvent<K extends keyof WindowEventMap>(el: Window, type: K, callback: (this: HTMLElement, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
22
+ export declare abstract class Component<
23
+ Events extends ValidEventTypes = Record<string, any>,
24
+ > extends EventDispatcher<Events> {
25
+ children: Component[];
26
+ private unloaders;
27
+ loaded: boolean;
28
+ protected _containerEl: HTMLElement;
29
+ get containerEl(): HTMLElement;
30
+ set containerEl(el: HTMLElement);
31
+ /**
32
+ * Load this component and its children
33
+ *
34
+ * @public
35
+ */
36
+ load(): void;
37
+ /**
38
+ * Override this to load your component
39
+ *
40
+ * @abstract
41
+ * @public
42
+ */
43
+ onload(): Promise<void> | void;
44
+ protected loadAsync(): Promise<void>;
45
+ /**
46
+ * Unload this component and its children
47
+ *
48
+ * @public
49
+ */
50
+ unload(): void;
51
+ protected unloadAsync(): Promise<void>;
52
+ /**
53
+ * Override this to unload your component
54
+ *
55
+ * @abstract
56
+ * @public
57
+ */
58
+ onunload(): void;
59
+ private cleanupAsync;
60
+ /**
61
+ * Adds a child component, loading it if this component is loaded
62
+ *
63
+ * @public
64
+ */
65
+ addChild<T extends Component>(component: T): T;
66
+ /**
67
+ * Removes a child component, unloading it
68
+ *
69
+ * @public
70
+ */
71
+ removeChild<T extends Component>(component: T): T;
72
+ /**
73
+ * Registers a callback to be called when unloading
74
+ *
75
+ * @public
76
+ */
77
+ register(cb: () => any): void;
78
+ registerEvent<T extends ValidEventTypes, K extends EventNames<T>>(
79
+ eventRef: EventRef<T, K, any>,
80
+ ): void;
81
+ registerInterval(id: ReturnType<typeof setInterval>): void;
82
+ /**
83
+ * Registers an DOM event to be detached when unloading
84
+ *
85
+ * @public
86
+ */
87
+ registerDomEvent<K extends keyof HTMLElementEventMap>(
88
+ el: HTMLElement,
89
+ type: K,
90
+ callback: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,
91
+ options?: boolean | AddEventListenerOptions,
92
+ ): void;
93
+ registerDomEvent<K extends keyof DocumentEventMap>(
94
+ el: Document,
95
+ type: K,
96
+ callback: (this: HTMLElement, ev: DocumentEventMap[K]) => any,
97
+ options?: boolean | AddEventListenerOptions,
98
+ ): void;
99
+ registerDomEvent<K extends keyof WindowEventMap>(
100
+ el: Window,
101
+ type: K,
102
+ callback: (this: HTMLElement, ev: WindowEventMap[K]) => any,
103
+ options?: boolean | AddEventListenerOptions,
104
+ ): void;
81
105
  }
82
106
  /**
83
107
  * Additional metadata returned from view-state transitions.
@@ -85,13 +109,13 @@ export declare abstract class Component<Events extends ValidEventTypes = Record<
85
109
  * @public
86
110
  */
87
111
  export interface ViewStateResult {
88
- /**
89
- * Set this to true to indicate that there is a state change which should be
90
- * recorded in the navigation history.
91
- *
92
- * @public
93
- */
94
- history: boolean;
112
+ /**
113
+ * Set this to true to indicate that there is a state change which should be
114
+ * recorded in the navigation history.
115
+ *
116
+ * @public
117
+ */
118
+ history: boolean;
95
119
  }
96
120
  /**
97
121
  * Serialized workspace state for a single leaf.
@@ -99,27 +123,27 @@ export interface ViewStateResult {
99
123
  * @public
100
124
  */
101
125
  export interface ViewState {
102
- /** @public */
103
- type: string;
104
- /** @public */
105
- state?: Record<string, unknown>;
106
- /** @public */
107
- active?: boolean;
108
- /** @public */
109
- pinned?: boolean;
110
- /** @public */
111
- group?: WorkspaceLeaf;
126
+ /** @public */
127
+ type: string;
128
+ /** @public */
129
+ state?: Record<string, unknown>;
130
+ /** @public */
131
+ active?: boolean;
132
+ /** @public */
133
+ pinned?: boolean;
134
+ /** @public */
135
+ group?: WorkspaceLeaf;
112
136
  }
113
137
  /**
114
- * Header breadcrumb contributed by a view. Keep the leaf filename in the
115
- * header title rather than this list.
138
+ * Header breadcrumb contributed by a view. Keep the leaf filename in the header
139
+ * title rather than this list.
116
140
  *
117
141
  * @public
118
142
  */
119
143
  export interface ViewBreadcrumb {
120
- id: string;
121
- label: string;
122
- onSelect?: () => void;
144
+ id: string;
145
+ label: string;
146
+ onSelect?: () => void;
123
147
  }
124
148
  /**
125
149
  * Base class for anything that can be mounted inside a workspace leaf.
@@ -127,37 +151,41 @@ export interface ViewBreadcrumb {
127
151
  * @public
128
152
  */
129
153
  export declare abstract class View extends Component {
130
- icon: string;
131
- leaf: WorkspaceLeaf;
132
- scope: Scope | null;
133
- protected state: Record<string, unknown>;
134
- constructor(leaf?: WorkspaceLeaf);
135
- get containerEl(): HTMLElement;
136
- get app(): App;
137
- /** @public */
138
- protected abstract onOpen(): Promise<void>;
139
- /** @public */
140
- protected abstract onClose(): Promise<void>;
141
- /** @public */
142
- abstract getViewType(): string;
143
- getState(): Record<string, unknown>;
144
- setState(state: Record<string, unknown>, result?: ViewStateResult): Promise<void>;
145
- getIcon(): string;
146
- abstract getDisplayText(): string;
147
- getBreadcrumbFilePath(): string | null;
148
- getBreadcrumbs(): ViewBreadcrumb[];
149
- onPaneMenu(menu: Menu, source: "more-options" | "tab-header" | string): void;
154
+ icon: string;
155
+ leaf: WorkspaceLeaf;
156
+ scope: Scope | null;
157
+ protected state: Record<string, unknown>;
158
+ constructor(leaf?: WorkspaceLeaf);
159
+ get containerEl(): HTMLElement;
160
+ get app(): App;
161
+ /** @public */
162
+ protected abstract onOpen(): Promise<void>;
163
+ /** @public */
164
+ protected abstract onClose(): Promise<void>;
165
+ /** @public */
166
+ abstract getViewType(): string;
167
+ getState(): Record<string, unknown>;
168
+ setState(
169
+ state: Record<string, unknown>,
170
+ result?: ViewStateResult,
171
+ ): Promise<void>;
172
+ getIcon(): string;
173
+ abstract getDisplayText(): string;
174
+ getClosePersistenceScope(): "application" | "layout";
175
+ getBreadcrumbFilePath(): string | null;
176
+ getBreadcrumbs(): ViewBreadcrumb[];
177
+ onPaneMenu(menu: Menu, source: "more-options" | "tab-header" | string): void;
150
178
  }
151
179
  export declare class EmptyView extends View {
152
- private component;
153
- constructor(leaf?: WorkspaceLeaf);
154
- protected onOpen(): Promise<void>;
155
- protected onClose(): Promise<void>;
156
- load(): void;
157
- unload(): void;
158
- getViewType(): string;
159
- getDisplayText(): string;
160
- getIcon(): string;
180
+ private component;
181
+ constructor(leaf?: WorkspaceLeaf);
182
+ protected onOpen(): Promise<void>;
183
+ protected onClose(): Promise<void>;
184
+ load(): void;
185
+ unload(): void;
186
+ getViewType(): string;
187
+ getDisplayText(): string;
188
+ getIcon(): string;
161
189
  }
162
190
  /**
163
191
  * View base class with an action bar and content area.
@@ -165,20 +193,25 @@ export declare class EmptyView extends View {
165
193
  * @public
166
194
  */
167
195
  export declare abstract class ItemView extends View {
168
- actions: Array<{
169
- icon: string;
170
- title: string;
171
- callback: (evt: MouseEvent) => any;
172
- disabled?: boolean;
173
- }>;
174
- constructor(leaf?: WorkspaceLeaf);
175
- get contentEl(): HTMLElement;
176
- unload(): void;
177
- addAction(icon: string, title: string, callback: (evt: MouseEvent) => any, options?: {
178
- disabled?: boolean;
179
- }): void;
180
- protected onOpen(): Promise<void>;
181
- protected onClose(): Promise<void>;
196
+ actions: Array<{
197
+ icon: string;
198
+ title: string;
199
+ callback: (evt: MouseEvent) => any;
200
+ disabled?: boolean;
201
+ }>;
202
+ constructor(leaf?: WorkspaceLeaf);
203
+ get contentEl(): HTMLElement;
204
+ unload(): void;
205
+ addAction(
206
+ icon: string,
207
+ title: string,
208
+ callback: (evt: MouseEvent) => any,
209
+ options?: {
210
+ disabled?: boolean;
211
+ },
212
+ ): void;
213
+ protected onOpen(): Promise<void>;
214
+ protected onClose(): Promise<void>;
182
215
  }
183
216
  /**
184
217
  * Item view base class that is backed by a vault file.
@@ -186,13 +219,13 @@ export declare abstract class ItemView extends View {
186
219
  * @public
187
220
  */
188
221
  export declare abstract class FileView extends ItemView {
189
- file: TFile | null;
190
- constructor(leaf?: WorkspaceLeaf);
191
- getBreadcrumbFilePath(): string | null;
192
- abstract onLoadFile(file: TFile): Promise<void>;
193
- abstract onUnloadFile(file: TFile): Promise<void>;
194
- abstract onRename(file: TFile): Promise<void>;
195
- abstract canAcceptExtension(extension: string): boolean;
222
+ file: TFile | null;
223
+ constructor(leaf?: WorkspaceLeaf);
224
+ getBreadcrumbFilePath(): string | null;
225
+ abstract onLoadFile(file: TFile): Promise<void>;
226
+ abstract onUnloadFile(file: TFile): Promise<void>;
227
+ abstract onRename(file: TFile): Promise<void>;
228
+ abstract canAcceptExtension(extension: string): boolean;
196
229
  }
197
230
  /**
198
231
  * File view base class for text-backed editors.
@@ -200,16 +233,16 @@ export declare abstract class FileView extends ItemView {
200
233
  * @public
201
234
  */
202
235
  export declare abstract class TextFileView extends FileView {
203
- editor: Editor;
204
- data: string;
205
- constructor(leaf?: WorkspaceLeaf);
206
- get adapter(): DataAdapter;
207
- abstract getViewData(): string;
208
- abstract setViewData(data: string, clear?: boolean): void;
209
- abstract clear(): void;
210
- onLoadFile(file: TFile): Promise<void>;
211
- getIcon(): string;
212
- onRename(file: TFile): Promise<void>;
213
- onUnloadFile(file: TFile): Promise<void>;
214
- save(clear?: boolean): Promise<void>;
236
+ editor: Editor;
237
+ data: string;
238
+ constructor(leaf?: WorkspaceLeaf);
239
+ get adapter(): DataAdapter;
240
+ abstract getViewData(): string;
241
+ abstract setViewData(data: string, clear?: boolean): void;
242
+ abstract clear(): void;
243
+ onLoadFile(file: TFile): Promise<void>;
244
+ getIcon(): string;
245
+ onRename(file: TFile): Promise<void>;
246
+ onUnloadFile(file: TFile): Promise<void>;
247
+ save(clear?: boolean): Promise<void>;
215
248
  }
@@ -1,5 +1,4 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import { DateTime } from "luxon";
3
2
  import { Editor } from "./editor.svelte";
4
3
  import { mount, unmount } from "svelte";
5
4
  import EmptyViewComponent from "./components/empty-view/empty-view.svelte";
@@ -209,8 +208,17 @@ export class View extends Component {
209
208
  return this.icon;
210
209
  }
211
210
  /**
212
- * Vault path used for parent-path header breadcrumbs. File views return
213
- * the open file; other views MAY return a related path or null.
211
+ * Layout-only views own no file writers and retain staged state outside their
212
+ * UI. Every other view keeps the complete application writer close guard.
213
+ *
214
+ * @public
215
+ */
216
+ getClosePersistenceScope() {
217
+ return "application";
218
+ }
219
+ /**
220
+ * Vault path used for parent-path header breadcrumbs. File views return the
221
+ * open file; other views MAY return a related path or null.
214
222
  *
215
223
  * @public
216
224
  */
@@ -330,22 +338,34 @@ export class TextFileView extends FileView {
330
338
  return this.app.vault.adapter;
331
339
  }
332
340
  async onLoadFile(file) {
333
- return this.app.telemetry.measureAsync("view.text_file.on_load_file", async (span) => {
341
+ const application = this.app;
342
+ return application.telemetry.measureAsync("view.text_file.on_load_file", async (span) => {
334
343
  span.setAttribute("view.type", this.getViewType());
335
344
  span.setAttribute("file.extension", file.extension);
336
- const contents = await this.app.telemetry.measureAsync("vault.read", async () => this.app.vault.read(file), {
345
+ const published = await this.editor.loadDocument(file, () => application.telemetry.measureAsync("vault.read", async () => application.vault.read(file), {
337
346
  attributes: {
338
347
  "file.extension": file.extension,
339
348
  "view.type": this.getViewType(),
340
349
  },
341
350
  slowThresholdMs: 100,
351
+ }), (contents) => {
352
+ if (this.app !== application || this.editor.app !== application)
353
+ throw new Error("Editor document load authority changed");
354
+ const previousFile = this.file, previousData = this.data;
355
+ try {
356
+ this.file = file.copy();
357
+ this.editor.extensions = application.editorExtensions(file.extension, { ...this.getState(), file: file.path });
358
+ this.data = contents;
359
+ this.setViewData(contents, true);
360
+ }
361
+ catch (error) {
362
+ this.file = previousFile;
363
+ this.data = previousData;
364
+ throw error;
365
+ }
342
366
  });
343
- this.file = file.copy();
344
- this.editor.file = file;
345
- await this.setState({ ...this.getState(), file: file.path });
346
- this.editor.extensions = this.app.editorExtensions(this.file.extension, this.getState());
347
- this.data = contents;
348
- this.setViewData(contents, true);
367
+ if (published && this.editor.file === file)
368
+ await this.setState({ ...this.getState(), file: file.path });
349
369
  }, {
350
370
  attributes: {
351
371
  "view.type": this.getViewType(),
@@ -364,18 +384,16 @@ export class TextFileView extends FileView {
364
384
  return Promise.resolve();
365
385
  }
366
386
  onUnloadFile(file) {
387
+ this.editor.cancelDocumentLoad();
367
388
  this.setState({ ...this.getState(), file: "" });
368
389
  return Promise.resolve();
369
390
  }
370
- save(clear) {
371
- return this.app.vault
372
- .modify(this.file, this.data, {
373
- mtime: DateTime.now().toMillis(),
374
- })
375
- .then(() => {
376
- if (clear) {
377
- this.clear();
378
- }
379
- });
391
+ async save(clear) {
392
+ const target = this.editor.file;
393
+ this.editor.save();
394
+ await this.editor.flushChanges();
395
+ this.data = this.editor.data;
396
+ if (clear && this.editor.file === target)
397
+ this.clear();
380
398
  }
381
399
  }
@@ -0,0 +1,3 @@
1
+ import type { Workspace } from "./workspace.svelte";
2
+ /** Keep the App's persistence barrier held through destructive shell changes. */
3
+ export declare function workspaceCloseGuard(workspace: Workspace, hostDocuments?: () => Document[]): (ids: string[], remove: () => void) => Promise<void>;
@@ -0,0 +1,35 @@
1
+ import { tick } from "svelte";
2
+ /** Keep the App's persistence barrier held through destructive shell changes. */
3
+ export function workspaceCloseGuard(workspace, hostDocuments = () => []) {
4
+ return async (ids, remove) => {
5
+ const targets = ids.map((id) => {
6
+ const leaf = workspace.getLeafById(id);
7
+ const view = leaf?.view;
8
+ return { id, leaf, view, scope: view?.getClosePersistenceScope?.() };
9
+ });
10
+ const documents = new Set(ids.map((id) => workspace.getCommandHostDocument(workspace.getCommandHostIdForLeaf(workspace.getLeafById(id)))));
11
+ for (const doc of hostDocuments())
12
+ documents.add(doc);
13
+ for (const doc of documents) {
14
+ const active = doc?.activeElement;
15
+ active?.blur?.();
16
+ }
17
+ await tick();
18
+ const registry = workspace.app.fileEditingSessions;
19
+ await registry.settleOperations();
20
+ await workspace.flushLayout();
21
+ const layoutOnly = targets.length > 0 &&
22
+ targets.every(({ id, leaf, view, scope }) => scope === "layout" &&
23
+ leaf &&
24
+ workspace.getLeafById(id) === leaf &&
25
+ leaf.view === view &&
26
+ view?.getClosePersistenceScope?.() === "layout");
27
+ if (layoutOnly) {
28
+ remove();
29
+ return;
30
+ }
31
+ await registry.guard(undefined, async () => {
32
+ remove();
33
+ });
34
+ };
35
+ }
@@ -1,7 +1,15 @@
1
+ const HOST_BINDING = Symbol.for("lapis.workspaceHostBinding");
1
2
  const workspaceHostBindings = new WeakMap();
2
3
  export function setWorkspaceHostBinding(workspace, binding) {
3
- workspaceHostBindings.set(workspace, Object.freeze(binding));
4
+ const frozen = Object.freeze(binding);
5
+ workspaceHostBindings.set(workspace, frozen);
6
+ Object.defineProperty(workspace, HOST_BINDING, {
7
+ configurable: true,
8
+ enumerable: false,
9
+ value: frozen,
10
+ });
4
11
  }
5
12
  export function resolveWorkspaceHostBinding(workspace) {
6
- return workspaceHostBindings.get(workspace);
13
+ return (workspaceHostBindings.get(workspace) ??
14
+ workspace[HOST_BINDING]);
7
15
  }
@@ -62,7 +62,7 @@ type WorkspaceBottomPanelJson = WorkspaceTabsJson & {
62
62
  type WorkspaceWindowJson = {
63
63
  id: string;
64
64
  type: "floating";
65
- mode?: "floating";
65
+ mode?: "floating" | "popout";
66
66
  displayState?: "collapsed" | "minimized";
67
67
  direction: "horizontal" | "vertical";
68
68
  sizes: number[];
@@ -88,5 +88,7 @@ export type WorkspaceJson = {
88
88
  * Always returns a structurally valid {@link WorkspaceJson} even when the input
89
89
  * is `null`, empty, partial, or corrupted.
90
90
  */
91
- export declare function normalizeWorkspaceJson(raw: unknown): WorkspaceJson;
91
+ export declare function normalizeWorkspaceJson(raw: unknown, options?: {
92
+ preservePopouts?: boolean;
93
+ }): WorkspaceJson;
92
94
  export {};
@@ -226,14 +226,14 @@ function normalizeBottomPanel(raw) {
226
226
  : "0px",
227
227
  };
228
228
  }
229
- function normalizeFloatingWindow(raw) {
229
+ function normalizeFloatingWindow(raw, preservePopouts = false) {
230
230
  if (!raw || typeof raw !== "object")
231
231
  return null;
232
232
  const r = raw;
233
233
  if (r.type !== "floating")
234
234
  return null;
235
235
  // Popout windows cannot be restored across sessions — drop them.
236
- if (r.mode === "popout")
236
+ if (r.mode === "popout" && !preservePopouts)
237
237
  return null;
238
238
  const children = (Array.isArray(r.children) ? r.children : [])
239
239
  .map(normalizeSplitChild)
@@ -249,7 +249,7 @@ function normalizeFloatingWindow(raw) {
249
249
  return {
250
250
  id: ensureId(r.id),
251
251
  type: "floating",
252
- mode: "floating",
252
+ mode: r.mode === "popout" ? "popout" : "floating",
253
253
  ...(displayState !== undefined ? { displayState } : {}),
254
254
  direction: ensureDirection(r.direction),
255
255
  sizes: repairSizes(r.sizes, children.length),
@@ -283,11 +283,11 @@ function hasAnyLeaf(nodes) {
283
283
  * Always returns a structurally valid {@link WorkspaceJson} even when the input
284
284
  * is `null`, empty, partial, or corrupted.
285
285
  */
286
- export function normalizeWorkspaceJson(raw) {
286
+ export function normalizeWorkspaceJson(raw, options = {}) {
287
287
  const r = raw && typeof raw === "object" ? raw : {};
288
288
  const floating = Array.isArray(r.floating)
289
289
  ? r.floating
290
- .map(normalizeFloatingWindow)
290
+ .map((window) => normalizeFloatingWindow(window, options.preservePopouts))
291
291
  .filter((w) => w !== null)
292
292
  : [];
293
293
  return {
@@ -0,0 +1,3 @@
1
+ import type { WorkspaceLeaf } from "./workspace.svelte";
2
+ /** Retarget a retained editor's DOM services when its view changes document. */
3
+ export declare function attachWorkspaceView(target: HTMLElement, leaf: WorkspaceLeaf): void;
@@ -0,0 +1,12 @@
1
+ /** Retarget a retained editor's DOM services when its view changes document. */
2
+ export function attachWorkspaceView(target, leaf) {
3
+ target.replaceChildren(leaf.containerEl);
4
+ const editor = leaf.view.editor;
5
+ const node = target.getRootNode();
6
+ const root = node.nodeType === 9 || node.nodeType === 11
7
+ ? node
8
+ : target.ownerDocument;
9
+ if (editor?.view && editor.view.root !== root) {
10
+ editor.view.setRoot(root);
11
+ }
12
+ }