@appsoftwareltd/etherpk-extension-api 0.11.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/assets.d.ts +23 -0
- package/dist/assets.js +5 -0
- package/dist/context.d.ts +70 -5
- package/dist/documents.d.ts +146 -0
- package/dist/documents.js +12 -0
- package/dist/editor.d.ts +110 -0
- package/dist/index.d.ts +7 -3
- package/dist/menus.d.ts +24 -0
- package/dist/records.d.ts +29 -0
- package/dist/records.js +7 -0
- package/dist/settings-sections.d.ts +56 -0
- package/dist/settings-sections.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -259,6 +259,10 @@ The third argument to `registerFence` adds options:
|
|
|
259
259
|
that would end the fence is changed so it can't.
|
|
260
260
|
- `publish`, which says how a published site shows the fence, as a picture or a link card. An SVG
|
|
261
261
|
picture is cleaned of scripts, event handlers and links that run code before the site gets it.
|
|
262
|
+
- `quote`, which says how the Backlinks panel shows the fence where a reference's block holds it,
|
|
263
|
+
in the same shapes as `publish`, with the theme to draw a picture in. The widget is never mounted
|
|
264
|
+
there. Without `quote`, an ordinary fence shows as code and an Extension Fence as a note. A link's
|
|
265
|
+
picture is loaded from the web as the panel shows it, so give one only where the person agreed.
|
|
262
266
|
- `identify`, which finds a fence again by an id in its body, so it can open in a tab.
|
|
263
267
|
- `keepsHistory`, which leaves Mod+Z to the widget while it has the keyboard.
|
|
264
268
|
|
package/dist/assets.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Images an extension hands to the open graph (ADR 0147): made smaller the way a pasted image is,
|
|
3
|
+
* and kept as one of the graph's assets, so a document can show it.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The open graph's assets, as far as an extension may add to them.
|
|
7
|
+
*
|
|
8
|
+
* @beta
|
|
9
|
+
*/
|
|
10
|
+
export interface ExtensionAssets {
|
|
11
|
+
/**
|
|
12
|
+
* An image made ready to send or keep, as a pasted image is: a large photo or screenshot is
|
|
13
|
+
* scaled down and re-encoded, and an image that is small enough comes back as it was. Rejects
|
|
14
|
+
* when the bytes are not an image the browser can read.
|
|
15
|
+
*/
|
|
16
|
+
prepareImage(image: Blob): Promise<Blob>;
|
|
17
|
+
/**
|
|
18
|
+
* Keep an image as one of the graph's assets, and answer the markdown that shows it in a
|
|
19
|
+
* document, such as ``. Null where the graph keeps no assets here,
|
|
20
|
+
* or the image was refused.
|
|
21
|
+
*/
|
|
22
|
+
saveImage(image: Blob, name: string): Promise<string | null>;
|
|
23
|
+
}
|
package/dist/assets.js
ADDED
package/dist/context.d.ts
CHANGED
|
@@ -7,14 +7,18 @@
|
|
|
7
7
|
* only through the index's answers and its own fences, and changes them only through its fences,
|
|
8
8
|
* the blocks it puts at the caret and the Client's Commands.
|
|
9
9
|
*/
|
|
10
|
+
import type { ExtensionAssets } from './assets';
|
|
10
11
|
import type { ExtensionAuth } from './auth';
|
|
11
12
|
import type { ExtensionDialogs } from './dialogs';
|
|
13
|
+
import type { ExtensionDocuments } from './documents';
|
|
12
14
|
import type { ExtensionEditor } from './editor';
|
|
13
15
|
import type { ExtensionEmbeds } from './embeds';
|
|
14
16
|
import type { ExtensionEvents } from './events';
|
|
15
17
|
import type { ExtensionIndex } from './graph-index';
|
|
16
18
|
import type { ExtensionJournalPanels } from './journal';
|
|
17
|
-
import type { CommandMenuItem, ContextMenuItem, GraphSidebarButton } from './menus';
|
|
19
|
+
import type { CommandBarButton, CommandMenuItem, ContextMenuItem, GraphSidebarButton } from './menus';
|
|
20
|
+
import type { ExtensionGraphRecords } from './records';
|
|
21
|
+
import type { SettingsSection } from './settings-sections';
|
|
18
22
|
import type { ViewContribution, ViewRef } from './views';
|
|
19
23
|
/**
|
|
20
24
|
* A Command's handler. What it returns, or resolves to, is what `execute` resolves to.
|
|
@@ -73,6 +77,16 @@ export interface ExtensionCommandMenu {
|
|
|
73
77
|
/** Add a row, its id under the extension's id. */
|
|
74
78
|
register(item: CommandMenuItem): () => void;
|
|
75
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Adding buttons to the Command Bar, the row of buttons across the bottom of a phone's screen:
|
|
82
|
+
* after the editing buttons that scroll, or in the pinned group at its right end.
|
|
83
|
+
*
|
|
84
|
+
* @beta
|
|
85
|
+
*/
|
|
86
|
+
export interface ExtensionCommandBar {
|
|
87
|
+
/** Add a button, its id under the extension's id. */
|
|
88
|
+
register(button: CommandBarButton): () => void;
|
|
89
|
+
}
|
|
76
90
|
/**
|
|
77
91
|
* Adding buttons to the Graph Sidebar's group of action buttons, after Search and today's date.
|
|
78
92
|
*
|
|
@@ -146,6 +160,26 @@ export interface ExtensionLayout {
|
|
|
146
160
|
activeDocument(): string | null;
|
|
147
161
|
/** True while the desktop presenter is showing, 1024 pixels wide and more. */
|
|
148
162
|
isDesktop(): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* Draw something over the whole EtherPK window, with a heading and a close button the Client
|
|
165
|
+
* draws, as a fence's widget opens over the window. One at a time: opening another closes the
|
|
166
|
+
* one before. The close button, Escape and `close` all close it, and `onClose` is told once.
|
|
167
|
+
*
|
|
168
|
+
* @beta
|
|
169
|
+
*/
|
|
170
|
+
openWindow(options: {
|
|
171
|
+
/** The heading the Client draws beside the close button. */
|
|
172
|
+
title: string;
|
|
173
|
+
/** Draw into `host`, which fills the window under the heading. */
|
|
174
|
+
mount(host: HTMLElement, window: {
|
|
175
|
+
close(): void;
|
|
176
|
+
}): {
|
|
177
|
+
destroy(): void;
|
|
178
|
+
};
|
|
179
|
+
onClose?(): void;
|
|
180
|
+
}): {
|
|
181
|
+
close(): void;
|
|
182
|
+
};
|
|
149
183
|
}
|
|
150
184
|
/**
|
|
151
185
|
* The rules for naming a concept, which every index answer follows.
|
|
@@ -203,15 +237,15 @@ export interface ExtensionSettings {
|
|
|
203
237
|
}
|
|
204
238
|
/**
|
|
205
239
|
* The extension's own records, kept with the person (ADR 0140): on this device, and where the
|
|
206
|
-
* person's account syncs a graph, in that account's
|
|
207
|
-
* person's own devices can read them. So a record follows the person to their other devices, as
|
|
240
|
+
* person's account syncs a graph, in that account's Settings Vault too, encrypted on the device so
|
|
241
|
+
* only the person's own devices can read them. So a record follows the person to their other devices, as
|
|
208
242
|
* Extension Settings do, such as what signing in to another service gave the extension. The person
|
|
209
243
|
* never sees these records, and uninstalling the extension clears them on every device.
|
|
210
244
|
*
|
|
211
245
|
* Each record is kept as JSON, at most 64 KB of it. Between two devices the later change to a
|
|
212
246
|
* record wins, record by record. A record is readable on the device by any code in the page, as
|
|
213
|
-
* localStorage is
|
|
214
|
-
* the
|
|
247
|
+
* localStorage is. A Headless Client signed in to the same account cannot read it: the Sync Server
|
|
248
|
+
* never gives an agent token the Settings Vault (ADR 0148).
|
|
215
249
|
*
|
|
216
250
|
* @public
|
|
217
251
|
*/
|
|
@@ -335,6 +369,12 @@ export interface ExtensionContext {
|
|
|
335
369
|
readonly commandMenu: ExtensionCommandMenu;
|
|
336
370
|
/** Adding buttons to the Graph Sidebar. */
|
|
337
371
|
readonly graphSidebar: ExtensionGraphSidebar;
|
|
372
|
+
/**
|
|
373
|
+
* Adding buttons to the phone's Command Bar.
|
|
374
|
+
*
|
|
375
|
+
* @beta
|
|
376
|
+
*/
|
|
377
|
+
readonly commandBar: ExtensionCommandBar;
|
|
338
378
|
/** Adding panels beneath each Journal Entry. */
|
|
339
379
|
readonly journalPanels: ExtensionJournalPanels;
|
|
340
380
|
/**
|
|
@@ -357,6 +397,24 @@ export interface ExtensionContext {
|
|
|
357
397
|
* @beta
|
|
358
398
|
*/
|
|
359
399
|
readonly index: ExtensionIndex;
|
|
400
|
+
/**
|
|
401
|
+
* Reading the open graph's documents, with every Protected Document left out, name and all.
|
|
402
|
+
*
|
|
403
|
+
* @beta
|
|
404
|
+
*/
|
|
405
|
+
readonly documents: ExtensionDocuments;
|
|
406
|
+
/**
|
|
407
|
+
* The extension's records for the open graph, kept on this device only.
|
|
408
|
+
*
|
|
409
|
+
* @beta
|
|
410
|
+
*/
|
|
411
|
+
readonly records: ExtensionGraphRecords;
|
|
412
|
+
/**
|
|
413
|
+
* Images kept as the open graph's assets.
|
|
414
|
+
*
|
|
415
|
+
* @beta
|
|
416
|
+
*/
|
|
417
|
+
readonly assets: ExtensionAssets;
|
|
360
418
|
/** Opening Views and documents. */
|
|
361
419
|
readonly layout: ExtensionLayout;
|
|
362
420
|
/**
|
|
@@ -402,4 +460,11 @@ export interface ExtensionModule {
|
|
|
402
460
|
* called after that, for anything else the extension holds.
|
|
403
461
|
*/
|
|
404
462
|
activate(context: ExtensionContext): void | (() => void);
|
|
463
|
+
/**
|
|
464
|
+
* Sections the extension adds to the Client's settings tabs, which the Client mounts while the
|
|
465
|
+
* extension is switched on, whether or not a graph is open.
|
|
466
|
+
*
|
|
467
|
+
* @beta
|
|
468
|
+
*/
|
|
469
|
+
settingsSections?: readonly SettingsSection[];
|
|
405
470
|
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the open graph's documents, as a language model may read them for a person (ADR 0147).
|
|
3
|
+
*
|
|
4
|
+
* Every answer leaves out a [[Protected Document]] entirely: not its content, and not its name
|
|
5
|
+
* either, even while the person holds the Protection Key. That is stricter than the index's
|
|
6
|
+
* answers (`context.index`), which list a Protected Document by name, because what an extension
|
|
7
|
+
* reads here may be sent to a model provider. A document whose text holds an encrypted fence
|
|
8
|
+
* anywhere counts as protected here too.
|
|
9
|
+
*
|
|
10
|
+
* Every answer is bounded: a list is paged, and a document's text is cut at a cap and says so.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* A document as a listing names it.
|
|
14
|
+
*
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
export interface DocumentSummary {
|
|
18
|
+
/** The document's name: a page's title, or a journal entry's day, `YYYY-MM-DD`. */
|
|
19
|
+
name: string;
|
|
20
|
+
/** A page or a journal entry. */
|
|
21
|
+
kind: 'page' | 'journal';
|
|
22
|
+
/** The page's other names. */
|
|
23
|
+
aliases: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A document's text, as {@link ExtensionDocuments.read} answers.
|
|
27
|
+
*
|
|
28
|
+
* @beta
|
|
29
|
+
*/
|
|
30
|
+
export interface DocumentText extends DocumentSummary {
|
|
31
|
+
/** The body: the text after the frontmatter block, cut at the cap. */
|
|
32
|
+
text: string;
|
|
33
|
+
/** True when the text was cut at the cap. */
|
|
34
|
+
truncated: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* One document a search matched, with the lines that matched.
|
|
38
|
+
*
|
|
39
|
+
* @beta
|
|
40
|
+
*/
|
|
41
|
+
export interface DocumentSearchResult extends Omit<DocumentSummary, 'aliases'> {
|
|
42
|
+
/** How many lines matched. */
|
|
43
|
+
matches: number;
|
|
44
|
+
/** The matching lines, best first. */
|
|
45
|
+
hits: {
|
|
46
|
+
/** The line's number in the document's text, from 0. */
|
|
47
|
+
line: number;
|
|
48
|
+
/** The labels of the blocks the line sits under, outermost first. */
|
|
49
|
+
breadcrumb: string[];
|
|
50
|
+
/** The line's text around the match. */
|
|
51
|
+
snippet: string;
|
|
52
|
+
}[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* One document whose text links to the concept asked about, with each place it does.
|
|
56
|
+
*
|
|
57
|
+
* @beta
|
|
58
|
+
*/
|
|
59
|
+
export interface DocumentBacklink extends Omit<DocumentSummary, 'aliases'> {
|
|
60
|
+
references: {
|
|
61
|
+
/** The line's number in the source's text, from 0. */
|
|
62
|
+
line: number;
|
|
63
|
+
/** The labels of the blocks the reference sits under, outermost first. */
|
|
64
|
+
breadcrumb: string[];
|
|
65
|
+
/** The block holding the link with its children, or the prose around it. */
|
|
66
|
+
text: string;
|
|
67
|
+
}[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* One task, as the Tasks View lists it.
|
|
71
|
+
*
|
|
72
|
+
* @beta
|
|
73
|
+
*/
|
|
74
|
+
export interface DocumentTask extends Omit<DocumentSummary, 'aliases'> {
|
|
75
|
+
/** The task's line in the document's text, from 0. */
|
|
76
|
+
line: number;
|
|
77
|
+
/** The task's words, without the checkbox. */
|
|
78
|
+
text: string;
|
|
79
|
+
status: 'open' | 'doing' | 'waiting' | 'done' | 'cancelled';
|
|
80
|
+
/** 1 is the highest; null when the task has none. */
|
|
81
|
+
priority: 1 | 2 | 3 | null;
|
|
82
|
+
/** `YYYY-MM-DD`, or null. */
|
|
83
|
+
due: string | null;
|
|
84
|
+
/** `YYYY-MM-DD`, or null. */
|
|
85
|
+
scheduled: string | null;
|
|
86
|
+
/** The labels of the blocks the task sits under, outermost first. */
|
|
87
|
+
breadcrumb: string[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Reading the open graph's documents.
|
|
91
|
+
*
|
|
92
|
+
* @beta
|
|
93
|
+
*/
|
|
94
|
+
export interface ExtensionDocuments {
|
|
95
|
+
/** Pages and journal entries, journals newest first and then pages by name, a page at a time. */
|
|
96
|
+
list(options?: {
|
|
97
|
+
kind?: 'page' | 'journal';
|
|
98
|
+
offset?: number;
|
|
99
|
+
limit?: number;
|
|
100
|
+
}): Promise<{
|
|
101
|
+
documents: DocumentSummary[];
|
|
102
|
+
total: number;
|
|
103
|
+
hasMore: boolean;
|
|
104
|
+
}>;
|
|
105
|
+
/**
|
|
106
|
+
* A document's text by its name or an alias, or null when there is no such document or it is
|
|
107
|
+
* protected. The text is the document as it is now, edits not yet saved included.
|
|
108
|
+
*/
|
|
109
|
+
read(name: string): Promise<DocumentText | null>;
|
|
110
|
+
/**
|
|
111
|
+
* The names of the documents a document's wikilinks name directly, in the order they first
|
|
112
|
+
* appear, each once. Names with no document, and protected documents, are left out. Null when
|
|
113
|
+
* the document cannot be read.
|
|
114
|
+
*/
|
|
115
|
+
links(name: string): Promise<string[] | null>;
|
|
116
|
+
/** The documents whose text matches the words, best first, a page at a time. */
|
|
117
|
+
search(query: string, options?: {
|
|
118
|
+
offset?: number;
|
|
119
|
+
limit?: number;
|
|
120
|
+
}): Promise<{
|
|
121
|
+
results: DocumentSearchResult[];
|
|
122
|
+
total: number;
|
|
123
|
+
hasMore: boolean;
|
|
124
|
+
}>;
|
|
125
|
+
/** The documents that link to a concept, or null when the concept is a protected document. */
|
|
126
|
+
backlinks(name: string): Promise<DocumentBacklink[] | null>;
|
|
127
|
+
/**
|
|
128
|
+
* How the graph's documents are written, as the Client describes it to agents: names and
|
|
129
|
+
* wikilinks, the outline, tasks and the rest of the syntax, in markdown. The same words the
|
|
130
|
+
* `AGENTS.md` of a graph folder carries, less what is about files on a disk, so a model reading
|
|
131
|
+
* the graph's text understands it and names documents as `[[Name]]`.
|
|
132
|
+
*/
|
|
133
|
+
formatGuide(): string;
|
|
134
|
+
/** Tasks, open ones unless asked otherwise, of one concept or of the whole graph, a page at a time. */
|
|
135
|
+
tasks(options?: {
|
|
136
|
+
/** Only the tasks that answer to this concept. */
|
|
137
|
+
concept?: string;
|
|
138
|
+
statuses?: DocumentTask['status'][];
|
|
139
|
+
offset?: number;
|
|
140
|
+
limit?: number;
|
|
141
|
+
}): Promise<{
|
|
142
|
+
tasks: DocumentTask[];
|
|
143
|
+
total: number;
|
|
144
|
+
hasMore: boolean;
|
|
145
|
+
}>;
|
|
146
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the open graph's documents, as a language model may read them for a person (ADR 0147).
|
|
3
|
+
*
|
|
4
|
+
* Every answer leaves out a [[Protected Document]] entirely: not its content, and not its name
|
|
5
|
+
* either, even while the person holds the Protection Key. That is stricter than the index's
|
|
6
|
+
* answers (`context.index`), which list a Protected Document by name, because what an extension
|
|
7
|
+
* reads here may be sent to a model provider. A document whose text holds an encrypted fence
|
|
8
|
+
* anywhere counts as protected here too.
|
|
9
|
+
*
|
|
10
|
+
* Every answer is bounded: a list is paged, and a document's text is cut at a cap and says so.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
package/dist/editor.d.ts
CHANGED
|
@@ -167,6 +167,22 @@ export type PublishedFence = {
|
|
|
167
167
|
height?: number;
|
|
168
168
|
};
|
|
169
169
|
};
|
|
170
|
+
/**
|
|
171
|
+
* A fence as the Client hands it to the extension to quote it read-only: in the Backlinks panel and in
|
|
172
|
+
* the backlinks under a document, where a reference's block holds the fence.
|
|
173
|
+
*
|
|
174
|
+
* @public
|
|
175
|
+
*/
|
|
176
|
+
export interface QuoteFenceRequest {
|
|
177
|
+
/** The fence's info word. */
|
|
178
|
+
readonly info: string;
|
|
179
|
+
/** The fence's body lines. */
|
|
180
|
+
readonly body: readonly string[];
|
|
181
|
+
/** The document the fence is in, by its concept. */
|
|
182
|
+
readonly document: string;
|
|
183
|
+
/** Whether the dark theme shows: a picture is drawn for it. */
|
|
184
|
+
readonly dark: boolean;
|
|
185
|
+
}
|
|
170
186
|
/**
|
|
171
187
|
* Options for a fence registration.
|
|
172
188
|
*
|
|
@@ -195,6 +211,20 @@ export interface FenceOptions {
|
|
|
195
211
|
* off), an Extension Fence is left out and an ordinary fence is published as code.
|
|
196
212
|
*/
|
|
197
213
|
publish?(fence: PublishFenceRequest): PublishedFence | null | Promise<PublishedFence | null>;
|
|
214
|
+
/**
|
|
215
|
+
* How a read-only quote of the fence shows it, such as a reference in the Backlinks panel: a
|
|
216
|
+
* picture, drawn in the theme asked for, or a link. Null, or no `quote`, shows what the quote
|
|
217
|
+
* shows without the extension: an ordinary fence's text as code, and for an Extension Fence a note
|
|
218
|
+
* naming the extension. The Client never mounts the widget in a quote.
|
|
219
|
+
*
|
|
220
|
+
* Called as a quote shows the fence, and again when its text, the theme or one of the extension's
|
|
221
|
+
* own settings changes. The Client keeps the last answers it was given, so a reference shown
|
|
222
|
+
* again does not ask again, and it treats an answer that takes more than 30 seconds as a failure.
|
|
223
|
+
* A link's picture is loaded from the web as the quote shows it, so give one only where the
|
|
224
|
+
* person has agreed to that, as a setting for thumbnails does. An SVG picture is cleaned first, as
|
|
225
|
+
* one for a published site is.
|
|
226
|
+
*/
|
|
227
|
+
quote?(fence: QuoteFenceRequest): PublishedFence | null | Promise<PublishedFence | null>;
|
|
198
228
|
/**
|
|
199
229
|
* The fence's own id, read from its body, or null. A fence with an id can be opened in a tab or a
|
|
200
230
|
* window, where the Client finds it again by the id after every change.
|
|
@@ -206,6 +236,72 @@ export interface FenceOptions {
|
|
|
206
236
|
*/
|
|
207
237
|
keepsHistory?: boolean;
|
|
208
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* A panel an extension draws in a document, beneath one of its lines, which is not part of the
|
|
241
|
+
* document's text: nothing of it is saved, synced or seen on another device (ADR 0147).
|
|
242
|
+
*
|
|
243
|
+
* The panel follows its line as the document changes, here or on another device, and moves with
|
|
244
|
+
* the editor when the editor is rebuilt (a Draft becoming a document, say). It closes when the
|
|
245
|
+
* person closes it, or when the document's editor closes for good: the panel lasts for the visit.
|
|
246
|
+
*
|
|
247
|
+
* @beta
|
|
248
|
+
*/
|
|
249
|
+
export interface InlinePanel {
|
|
250
|
+
/** The document the panel is in, by its concept. */
|
|
251
|
+
readonly document: string | null;
|
|
252
|
+
/** False once the panel has closed. */
|
|
253
|
+
readonly isOpen: boolean;
|
|
254
|
+
/**
|
|
255
|
+
* Put a block at the panel's line, by the rule {@link ExtensionEditor.insertBlock} follows at the
|
|
256
|
+
* caret: an empty line is replaced, an empty bullet takes an outline's place at its own
|
|
257
|
+
* indentation (or any other block as its content), and after any other line the block goes on new
|
|
258
|
+
* lines beneath at the line's content column. The panel then sits beneath the block, and the next
|
|
259
|
+
* block goes after it at the indentation of its first line. One undoable change. False where
|
|
260
|
+
* nothing was put in: the panel is closed, its editor has closed, or its line is now in the
|
|
261
|
+
* frontmatter, a fenced block or a table.
|
|
262
|
+
*/
|
|
263
|
+
insertBlock(text: string): boolean;
|
|
264
|
+
/** Bring the panel into view. */
|
|
265
|
+
focus(): void;
|
|
266
|
+
/**
|
|
267
|
+
* Give the panel a new height in CSS pixels, which its content scrolls inside: the lines below
|
|
268
|
+
* it move once. Grow it when there is more to show, rather than on every change.
|
|
269
|
+
*/
|
|
270
|
+
resize(height: number): void;
|
|
271
|
+
/**
|
|
272
|
+
* The outline around the panel's line, as the document writes it: the line's ancestors, each its
|
|
273
|
+
* own lines without its other children, and its siblings with their branches, the line's own
|
|
274
|
+
* branch among them while the line has text. A block the panel put in is left out. Null when
|
|
275
|
+
* the line is not a bullet, or the panel is closed or under the document's last line.
|
|
276
|
+
*/
|
|
277
|
+
outline(): string | null;
|
|
278
|
+
/** Close the panel. Its `onClose` is told. */
|
|
279
|
+
close(): void;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* What an inline panel is drawn with.
|
|
283
|
+
*
|
|
284
|
+
* @beta
|
|
285
|
+
*/
|
|
286
|
+
export interface InlinePanelOptions {
|
|
287
|
+
/**
|
|
288
|
+
* The panel's height in CSS pixels, which its content scrolls inside, so the lines below never
|
|
289
|
+
* move as its content grows. {@link InlinePanel.resize} changes it.
|
|
290
|
+
*/
|
|
291
|
+
height?: number;
|
|
292
|
+
/**
|
|
293
|
+
* Draw the panel into `host`, which the Client owns and places. Called once, when the panel is
|
|
294
|
+
* first drawn: the host keeps its content while the panel is scrolled out of view and when the
|
|
295
|
+
* editor is rebuilt, and `destroy` is called when the panel closes. Events inside the host are
|
|
296
|
+
* the panel's own: the editor neither types nor moves its caret for them, but Mod+Z and Mod+Y
|
|
297
|
+
* outside a text field undo and redo in the document.
|
|
298
|
+
*/
|
|
299
|
+
mount(host: HTMLElement, panel: InlinePanel): {
|
|
300
|
+
destroy(): void;
|
|
301
|
+
};
|
|
302
|
+
/** Told once, when the panel closes for any reason. */
|
|
303
|
+
onClose?(): void;
|
|
304
|
+
}
|
|
209
305
|
/**
|
|
210
306
|
* The document editor, as far as an extension may reach it.
|
|
211
307
|
*
|
|
@@ -233,4 +329,18 @@ export interface ExtensionEditor {
|
|
|
233
329
|
insertBlock(text: string, options?: {
|
|
234
330
|
focus?: boolean;
|
|
235
331
|
}): boolean;
|
|
332
|
+
/**
|
|
333
|
+
* Draw a panel beneath the caret's line in the editor the person is working in, from where the
|
|
334
|
+
* line's text starts, or beside the dot of an empty bullet, as a code block opened there is. With
|
|
335
|
+
* `at` `end`, it is drawn beneath the document's last line, at the editor's left edge, a line's
|
|
336
|
+
* height clear of it. With `caret-or-end`, at the caret while the person is typing in the
|
|
337
|
+
* document (the editor has the keyboard, as a Command Bar button leaves it), else at the end: for
|
|
338
|
+
* a button pressed from outside the text. Null where no panel can go: no editor, a Protected
|
|
339
|
+
* Document, or a caret in the frontmatter, a fenced block or a table.
|
|
340
|
+
*
|
|
341
|
+
* @beta
|
|
342
|
+
*/
|
|
343
|
+
openPanel(options: InlinePanelOptions & {
|
|
344
|
+
at?: 'caret' | 'end' | 'caret-or-end';
|
|
345
|
+
}): InlinePanel | null;
|
|
236
346
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,15 +14,19 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @packageDocumentation
|
|
16
16
|
*/
|
|
17
|
-
export type { CommandHandler, ExtensionCommandMenu, ExtensionCommands, ExtensionConcepts, ExtensionContext, ExtensionContextMenu, ExtensionContributions, ExtensionGraphSidebar, ExtensionIcons, ExtensionKeybindings, ExtensionLayout, ExtensionModule, ExtensionPersonStorage, ExtensionSettings, ExtensionStorage, ExtensionTheme, ExtensionViews, IconMarkup, Keybinding, } from './context';
|
|
17
|
+
export type { CommandHandler, ExtensionCommandBar, ExtensionCommandMenu, ExtensionCommands, ExtensionConcepts, ExtensionContext, ExtensionContextMenu, ExtensionContributions, ExtensionGraphSidebar, ExtensionIcons, ExtensionKeybindings, ExtensionLayout, ExtensionModule, ExtensionPersonStorage, ExtensionSettings, ExtensionStorage, ExtensionTheme, ExtensionViews, IconMarkup, Keybinding, } from './context';
|
|
18
|
+
export type { ExtensionAssets } from './assets';
|
|
18
19
|
export type { AuthorizeOptions, ExtensionAuth } from './auth';
|
|
19
20
|
export type { ExtensionDialogs, PromptOptions } from './dialogs';
|
|
20
|
-
export type {
|
|
21
|
+
export type { DocumentBacklink, DocumentSearchResult, DocumentSummary, DocumentTask, DocumentText, ExtensionDocuments } from './documents';
|
|
22
|
+
export type { ExtensionEditor, FenceContext, FenceEdit, FenceInfo, FenceOptions, FencePresentation, FenceWidget, InlinePanel, InlinePanelOptions, MountedFence, PublishedFence, PublishFenceRequest, QuoteFenceRequest, } from './editor';
|
|
21
23
|
export type { ExtensionEmbeds, FrameOptions } from './embeds';
|
|
22
24
|
export type { ExtensionEventName, ExtensionEventPayloads, ExtensionEvents } from './events';
|
|
23
25
|
export type { ConceptCandidate, ConceptKind, ExtensionIndex, IndexUpdate, LinkGraph, LinkGraphConcept, LinkGraphLink } from './graph-index';
|
|
24
26
|
export type { ExtensionJournalPanels, JournalPanel, JournalPanelProps, MountedJournalPanel } from './journal';
|
|
25
27
|
export type { ExtensionIsolation, ExtensionManifest, ExtensionPackage, ReadExtensionPackageResult, SettingDeclaration, ViewDeclaration, ViewRegion, } from './manifest';
|
|
26
28
|
export { readExtensionPackage } from './manifest';
|
|
27
|
-
export type { CommandMenuContext, CommandMenuItem, ContextMenuItem, DocumentMenuTarget, ExtensionMenuTarget, GraphSidebarButton, MenuTarget, TabMenuTarget, WikilinkMenuTarget, } from './menus';
|
|
29
|
+
export type { CommandBarButton, CommandMenuContext, CommandMenuItem, ContextMenuItem, DocumentMenuTarget, ExtensionMenuTarget, GraphSidebarButton, MenuTarget, TabMenuTarget, WikilinkMenuTarget, } from './menus';
|
|
30
|
+
export type { ExtensionGraphRecords } from './records';
|
|
31
|
+
export type { MountedSettingsSection, SettingsSection, SettingsSectionContext, SettingsSectionTab } from './settings-sections';
|
|
28
32
|
export type { MountedView, ViewContribution, ViewMountProps, ViewRef, ViewVisibility } from './views';
|
package/dist/menus.d.ts
CHANGED
|
@@ -149,6 +149,30 @@ export interface CommandMenuItem {
|
|
|
149
149
|
*/
|
|
150
150
|
args?: unknown;
|
|
151
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* A button on the Command Bar, the row of buttons across the bottom of a phone's screen. Pressing
|
|
154
|
+
* it runs `command` and leaves the keyboard where it was, so a Command can tell whether the caret
|
|
155
|
+
* is in the document.
|
|
156
|
+
*
|
|
157
|
+
* @beta
|
|
158
|
+
*/
|
|
159
|
+
export interface CommandBarButton {
|
|
160
|
+
/** Under the extension's id. */
|
|
161
|
+
id: string;
|
|
162
|
+
/** The button's name, said to a screen reader and shown as its tooltip: the bar shows icons only. */
|
|
163
|
+
title: string;
|
|
164
|
+
/** Its icon: the extension's own or one of the Client's. */
|
|
165
|
+
icon: string;
|
|
166
|
+
/**
|
|
167
|
+
* In the bar's pinned group at its right end, which never scrolls away, rather than after the
|
|
168
|
+
* editing buttons that scroll. For an action a person reaches for often.
|
|
169
|
+
*/
|
|
170
|
+
pinned?: boolean;
|
|
171
|
+
/** The Command the button runs. */
|
|
172
|
+
command: string;
|
|
173
|
+
/** What the Command is given. */
|
|
174
|
+
args?: unknown;
|
|
175
|
+
}
|
|
152
176
|
/**
|
|
153
177
|
* A button in the Graph Sidebar's group of action buttons, after Search and today's date: a way in
|
|
154
178
|
* to what the extension shows for the whole graph, such as the Graph Map. Pressing it runs
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Records an extension keeps on this device for the open graph alone (ADR 0147): never synced,
|
|
3
|
+
* never seen by another device or another member, and deleted when the graph's data is removed
|
|
4
|
+
* from the device. For what is the person's work on this device, such as a chat they have not
|
|
5
|
+
* saved, rather than a preference that should follow them (`personStorage`).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* The extension's records for the open graph on this device.
|
|
9
|
+
*
|
|
10
|
+
* Each record is stored as the browser's structured clone of the value, so it may hold a `Blob`,
|
|
11
|
+
* an `ArrayBuffer`, a `Date` or plain data, but no function. Records live in the browser's
|
|
12
|
+
* IndexedDB, which a private window or a full disk may refuse: a refused write rejects, and a
|
|
13
|
+
* refused read answers as if there were nothing.
|
|
14
|
+
*
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
export interface ExtensionGraphRecords {
|
|
18
|
+
/** The record under `key`, or undefined when there is none. */
|
|
19
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
20
|
+
/**
|
|
21
|
+
* Keep a record under `key`: letters, digits, `.`, `_`, `:` and `-`, at most 200 of them.
|
|
22
|
+
* Rejects when the key is not one of those or the browser refuses the write.
|
|
23
|
+
*/
|
|
24
|
+
set(key: string, value: unknown): Promise<void>;
|
|
25
|
+
/** Remove the record under `key`. */
|
|
26
|
+
remove(key: string): Promise<void>;
|
|
27
|
+
/** The keys of every record the extension keeps for the open graph, sorted. */
|
|
28
|
+
keys(): Promise<string[]>;
|
|
29
|
+
}
|
package/dist/records.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Records an extension keeps on this device for the open graph alone (ADR 0147): never synced,
|
|
3
|
+
* never seen by another device or another member, and deleted when the graph's data is removed
|
|
4
|
+
* from the device. For what is the person's work on this device, such as a chat they have not
|
|
5
|
+
* saved, rather than a preference that should follow them (`personStorage`).
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An extension's own section in one of the Client's settings tabs (ADR 0134, amended 2026-10-15),
|
|
3
|
+
* which the Client mounts with or without a graph open: on the Graphs page, and in a graph's
|
|
4
|
+
* settings. For settings that belong to the person and need more than the fields a manifest can
|
|
5
|
+
* declare, such as a list of accounts with a button that connects one.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExtensionAuth } from './auth';
|
|
8
|
+
import type { ExtensionPersonStorage, ExtensionSettings, ExtensionTheme } from './context';
|
|
9
|
+
/**
|
|
10
|
+
* The tabs an extension's settings section can go in.
|
|
11
|
+
*
|
|
12
|
+
* @beta
|
|
13
|
+
*/
|
|
14
|
+
export type SettingsSectionTab = 'agents';
|
|
15
|
+
/**
|
|
16
|
+
* What a settings section is mounted with: what belongs to the person, and nothing from a graph,
|
|
17
|
+
* since there may be no graph open.
|
|
18
|
+
*
|
|
19
|
+
* @beta
|
|
20
|
+
*/
|
|
21
|
+
export interface SettingsSectionContext {
|
|
22
|
+
/** The extension's id, from its manifest. */
|
|
23
|
+
readonly extensionId: string;
|
|
24
|
+
/** The person's answers to the settings the manifest declares. */
|
|
25
|
+
readonly settings: ExtensionSettings;
|
|
26
|
+
/** The extension's records kept with the person. */
|
|
27
|
+
readonly personStorage: ExtensionPersonStorage;
|
|
28
|
+
/** Signing in to another service. */
|
|
29
|
+
readonly auth: ExtensionAuth;
|
|
30
|
+
/** The Client's light or dark theme. */
|
|
31
|
+
readonly theme: ExtensionTheme;
|
|
32
|
+
/** Say something in passing, as the Client's own notices do. */
|
|
33
|
+
notify(text: string): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A section the section's host element shows, as the Client drives it.
|
|
37
|
+
*
|
|
38
|
+
* @beta
|
|
39
|
+
*/
|
|
40
|
+
export interface MountedSettingsSection {
|
|
41
|
+
/** The tab closed, or the extension was switched off. */
|
|
42
|
+
destroy(): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* One settings section an extension adds.
|
|
46
|
+
*
|
|
47
|
+
* @beta
|
|
48
|
+
*/
|
|
49
|
+
export interface SettingsSection {
|
|
50
|
+
/** Unique within the extension. */
|
|
51
|
+
id: string;
|
|
52
|
+
/** The tab it goes in. */
|
|
53
|
+
tab: SettingsSectionTab;
|
|
54
|
+
/** Draw the section into `element`, which is empty and is the extension's alone. */
|
|
55
|
+
mount(element: HTMLElement, context: SettingsSectionContext): MountedSettingsSection;
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsoftwareltd/etherpk-extension-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "The API an EtherPK extension is written against: the context it is started with, its manifest, and the contract its Views follow.",
|
|
6
6
|
"type": "module",
|