weml-monaco 0.5.2 → 0.7.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/dist/index.d.mts CHANGED
@@ -24,10 +24,11 @@ interface WemlActionOptions {
24
24
  }
25
25
  /** Wraps the current selection in `<tag [type=...]>…</tag>` (toolbar dropdown / hotkeys). */
26
26
  declare function wrapSelection(editor: monaco.editor.ICodeEditor, tag: string, type?: string): void;
27
- /** Inserts a snippet by its toolbar-button id (composite label or plain tag). */
27
+ /** Inserts a snippet by its id (`snippetBodyFor`: a composite label, the anchor, or a tag). */
28
28
  declare function insertSnippetById(editor: monaco.editor.ICodeEditor, id: string): void;
29
29
  /** Renumbers every `<div>` id in document order to a sequential 1..n. */
30
30
  declare function renumberDivIds(editor: monaco.editor.ICodeEditor, options?: WemlActionOptions): void;
31
+
31
32
  /**
32
33
  * Cycles the whole document between the standard HTML formatting (even steps) and
33
34
  * the canonical WEML normalizer (odd steps). The step counter advances on every
@@ -41,8 +42,8 @@ declare function cycleFormat(editor: monaco.editor.ICodeEditor, options?: WemlAc
41
42
  * (Ctrl+B / Ctrl+I / Ctrl+U). Returns an `IDisposable` that removes them.
42
43
  *
43
44
  * `editor.addAction` is per-editor (Monaco has no global command registry akin
44
- * to the VS Code extension host), so call this for every WEML editor — or just
45
- * use `createWemlToolbar`, which calls it for you.
45
+ * to the VS Code extension host), so call this for every WEML editor (the deprecated
46
+ * `createWemlToolbar` calls it for you; the WEML panel does not).
46
47
  */
47
48
  declare function registerWemlEditorActions(m: typeof monaco, editor: monaco.editor.IStandaloneCodeEditor, options?: WemlActionOptions): monaco.IDisposable;
48
49
 
@@ -69,9 +70,23 @@ interface WemlToolbar extends monaco.IDisposable {
69
70
  *
70
71
  * Returns the root element plus a `dispose()` that removes the toolbar and its
71
72
  * actions.
73
+ *
74
+ * @deprecated Use the WEML panel (`createWemlPanel` from `weml-monaco/panel`, with
75
+ * `createMonacoPanelHost`): the same Tools and Search Suggestions as the VS Code
76
+ * extension. For the hotkeys alone, call `registerWemlEditorActions`.
72
77
  */
73
78
  declare function createWemlToolbar(m: typeof monaco, editor: monaco.editor.IStandaloneCodeEditor, options?: WemlToolbarOptions): WemlToolbar;
74
79
 
80
+ /**
81
+ * Builds a `<tag ...>SELECTION</tag>` snippet body for wrapping `selection`.
82
+ * - `type` (e.g. for `w-format`) fills `type="..."` directly.
83
+ * - `a` gets only `href="$1"` (it lists both href and id as required, but a
84
+ * wrapped selection is a link).
85
+ * - otherwise the tag's required attributes become `name="$1"` placeholders.
86
+ * An empty selection leaves a tab stop where the content goes.
87
+ */
88
+ declare function buildWrapSnippet(tag: string, type: string | undefined, selection: string): string;
89
+
75
90
  interface IdEdit {
76
91
  /** Replacement range in the source text (start === end means a pure insertion). */
77
92
  start: number;
@@ -85,15 +100,193 @@ interface IdEdit {
85
100
  */
86
101
  declare function planDivIdRenumber(text: string): IdEdit[];
87
102
 
103
+ interface WrapOption {
104
+ /** Encoded option value, e.g. "w-format:italic" or "w-lang". */
105
+ value: string;
106
+ label: string;
107
+ tag: string;
108
+ /** The `type` of `w-format`; absent for the other inlines. */
109
+ type?: string;
110
+ }
111
+ /** The documentation's sections the tool picker groups its items by, in order. */
112
+ declare const TOOL_GROUPS: readonly ["Containers", "Blocks", "Inlines"];
113
+ type ToolGroup = (typeof TOOL_GROUPS)[number];
114
+ /** What a tool item does: wrap the selection, or insert a snippet at the cursor. */
115
+ type ToolAction = {
116
+ kind: 'wrap';
117
+ option: WrapOption;
118
+ } | {
119
+ kind: 'insert';
120
+ snippetId: string;
121
+ };
122
+ interface ToolItem {
123
+ /** Unique: the wrap option's value, or the snippet's tag. */
124
+ value: string;
125
+ /** What the picker shows and searches: the tag (`w-format.bold` for a format). */
126
+ label: string;
127
+ group: ToolGroup;
128
+ action: ToolAction;
129
+ /**
130
+ * A new section of `<body>` (a `<div id>` with its container): only for a whole document, not
131
+ * for an editor of one paragraph, whose model is a single `<div>` already.
132
+ */
133
+ documentOnly?: boolean;
134
+ }
135
+ /** What is edited: a whole WEML document, or one paragraph (the content of one `<div>`). */
136
+ type ToolMode = 'file' | 'paragraph';
88
137
  /**
89
- * Builds a `<tag ...>SELECTION</tag>` snippet body for wrapping `selection`.
90
- * - `type` (e.g. for `w-format`) fills `type="..."` directly.
91
- * - `a` gets only `href="$1"` (it lists both href and id as required, but a
92
- * wrapped selection is a link).
93
- * - otherwise the tag's required attributes become `name="$1"` placeholders.
94
- * An empty selection leaves a tab stop where the content goes.
138
+ * One list of everything the Tools offer — the snippets to insert, then the inlines to wrap the
139
+ * selection in — grouped as the WEML documentation is (containers, blocks, inlines).
95
140
  */
96
- declare function buildWrapSnippet(tag: string, type: string | undefined, selection: string): string;
141
+ declare const TOOL_ITEMS: ToolItem[];
142
+ /** The tool items for what is edited: a paragraph has no sections to add. */
143
+ declare function toolItemsFor(mode?: ToolMode): ToolItem[];
144
+ /** A tool item that matches a query, with the matched ranges of its label (`[start, end)`). */
145
+ interface ToolMatch {
146
+ item: ToolItem;
147
+ matches: [number, number][];
148
+ }
149
+ /**
150
+ * The items whose label contains `query` (case-insensitive; an empty query matches all), in
151
+ * `TOOL_ITEMS` order, with the match to highlight.
152
+ */
153
+ declare function filterToolItems(query: string, items?: readonly ToolItem[]): ToolMatch[];
154
+
155
+ /** The panel's remembered state (collapsed panes, pane sizes, per-pane values). */
156
+ interface WemlPanelStorage {
157
+ get(): unknown;
158
+ set(value: unknown): void;
159
+ }
160
+ /** The Tools pane's actions. */
161
+ interface WemlPanelTools {
162
+ /** Wraps the selection in the option's tag (a `WRAP_OPTIONS` entry). */
163
+ wrap(option: WrapOption): void;
164
+ /** Inserts a snippet by its id (weml-language-core's `snippetBodyFor`: a tag, a composite, the anchor). */
165
+ insertSnippet(id: string): void;
166
+ /** Renumbers every `<div>` id to 1…n. */
167
+ renumber(): void;
168
+ }
169
+ /** Whether search can run, and as whom. */
170
+ type WemlSearchState =
171
+ /** Something is missing on the host's side; `message` says what. */
172
+ {
173
+ kind: 'not-configured';
174
+ message: string;
175
+ canOpenSettings?: boolean;
176
+ } | {
177
+ kind: 'signed-out';
178
+ defaultLanguage?: string;
179
+ } | {
180
+ kind: 'signed-in';
181
+ account?: string;
182
+ defaultLanguage?: string;
183
+ };
184
+ /** A search suggestion as the panel shows it. */
185
+ interface WemlSearchResult {
186
+ paraId: string;
187
+ bookCode: string;
188
+ title: string;
189
+ /** The `egw://` link for a paragraph, or null. */
190
+ link: string | null;
191
+ }
192
+ /** The Search Suggestions pane's backend. */
193
+ interface WemlPanelSearch {
194
+ getState(): WemlSearchState | Promise<WemlSearchState>;
195
+ /** Calls `listener` whenever the state may have changed; returns the unsubscribe. */
196
+ onDidChangeState(listener: () => void): () => void;
197
+ /**
198
+ * Searches. The host cancels a previous request itself; the panel ignores answers that arrive
199
+ * after a newer search started. Rejects with an Error whose message the panel shows.
200
+ */
201
+ search(query: string, lang: string): Promise<WemlSearchResult[]>;
202
+ /** Starts the sign-in; a rejection's message is shown under the Sign in button. */
203
+ signIn(): void | Promise<void>;
204
+ /** Shown as a link next to a "not configured" message when the state allows it. */
205
+ openSettings?(): void;
206
+ copy(text: string): void;
207
+ /** Inserts the link of the result at `index` (of the last answer) in place of the selection. */
208
+ insertLink(index: number): void;
209
+ }
210
+ interface WemlPanelHost {
211
+ tools: WemlPanelTools;
212
+ /** Without it the panel has no Search Suggestions pane. */
213
+ search?: WemlPanelSearch;
214
+ /** Without it nothing is remembered (in memory for this panel only). */
215
+ storage?: WemlPanelStorage;
216
+ }
217
+
218
+ /** The EGW search as a web host provides it: where the API is, and how to get the user's token. */
219
+ interface MonacoPanelSearchOptions {
220
+ /** Base URL of the EGW API (`<apiUrl>/search/suggestions`). */
221
+ apiUrl: string;
222
+ /** The signed-in user's access token, or undefined when signed out. */
223
+ getAccessToken(): string | undefined | Promise<string | undefined>;
224
+ /** Starts the host application's sign-in; a rejection's message is shown in the pane. */
225
+ signIn?(): void | Promise<void>;
226
+ /** Notifies the panel when the user signs in or out; returns the unsubscribe. */
227
+ onDidChangeSession?(listener: () => void): () => void;
228
+ /** The account's display name, if the host wants it shown (it is not shown while signed in). */
229
+ account?(): string | undefined;
230
+ /** The search language until the user picks one. Default: `en`. */
231
+ defaultLanguage?: string;
232
+ }
233
+ interface MonacoPanelHostOptions extends WemlActionOptions {
234
+ /**
235
+ * The EGW search. Omitted: the Search Suggestions pane says the search is not configured;
236
+ * `false`: no Search Suggestions pane at all.
237
+ */
238
+ search?: MonacoPanelSearchOptions | false;
239
+ /** What the "not configured" message says when `search` is omitted. */
240
+ notConfiguredMessage?: string;
241
+ /**
242
+ * Where the panel remembers its layout. Default: `localStorage` under `weml-panel`;
243
+ * `false`: nothing is remembered.
244
+ */
245
+ storage?: WemlPanelStorage | false;
246
+ /** Copies text for the Copy buttons. Default: `navigator.clipboard.writeText`. */
247
+ copy?(text: string): void;
248
+ }
249
+ /** A WemlPanelHost for a Monaco editor on a web page. */
250
+ declare function createMonacoPanelHost(editor: monaco.editor.ICodeEditor, options?: MonacoPanelHostOptions): WemlPanelHost;
251
+
252
+ interface EgwWebAuthOptions {
253
+ /** OIDC authority (issuer); `/.well-known/openid-configuration` is read from it. */
254
+ authority: string;
255
+ clientId: string;
256
+ /** Space-separated scopes (`openid offline_access search …`). */
257
+ scopes: string;
258
+ /**
259
+ * Where the server sends the popup back to, on this page's origin; the client must allow it.
260
+ * Default: `<origin>/auth-callback`. Any page will do — it is read from here, not run — so a
261
+ * blank one is best.
262
+ */
263
+ redirectUri?: string;
264
+ /** Optional login page the authorize request goes through: `loginPageUrl?next=<authorize path>`. */
265
+ loginPageUrl?: string;
266
+ /**
267
+ * Where the session is kept. `session` (default): this tab, until it closes; `local`: every tab,
268
+ * across restarts; `false`: memory only, until the page reloads.
269
+ */
270
+ storage?: 'session' | 'local' | false;
271
+ }
272
+ interface EgwWebAuth {
273
+ /** The access token, refreshed when it is about to expire; undefined when signed out. */
274
+ getAccessToken(): Promise<string | undefined>;
275
+ /**
276
+ * Opens the sign-in popup — call it from a click, or the browser blocks the popup. Resolves once
277
+ * signed in; rejects with a message to show (popup blocked, closed, refused by the server).
278
+ */
279
+ signIn(): Promise<void>;
280
+ signOut(): void;
281
+ /** Calls `listener` on sign-in, sign-out and refresh (in other tabs too, with `local`). */
282
+ onDidChangeSession(listener: () => void): () => void;
283
+ /** The signed-in account's name, or undefined. */
284
+ account(): string | undefined;
285
+ /** Closes a pending popup and stops listening. */
286
+ dispose(): void;
287
+ }
288
+ /** The EGW sign-in for a web page: see `EgwWebAuthOptions`. */
289
+ declare function createEgwWebAuth(options: EgwWebAuthOptions): EgwWebAuth;
97
290
 
98
291
  interface RegisterWemlOptions {
99
292
  /** File extensions to associate with the language (default: [".weml"]). */
@@ -105,4 +298,4 @@ interface RegisterWemlOptions {
105
298
  }
106
299
  declare function registerWeml(m: typeof monaco, options?: RegisterWemlOptions): monaco.IDisposable;
107
300
 
108
- export { type IdEdit, type RegisterWemlOptions, WEML_LANGUAGE_ID, type WemlActionOptions, type WemlNormalizationFailure, type WemlToolbar, type WemlToolbarOptions, buildWrapSnippet, canonicalFormattingFailureMessage, createWemlToolbar, cycleFormat, formatWemlText, insertSnippetById, isWemlNormalizationFailure, isWemlStructureValidationFailure, planDivIdRenumber, registerWeml, registerWemlEditorActions, renumberDivIds, validateWemlModel, wrapSelection };
301
+ export { type EgwWebAuth, type EgwWebAuthOptions, type IdEdit, type MonacoPanelHostOptions, type MonacoPanelSearchOptions, type RegisterWemlOptions, TOOL_GROUPS, TOOL_ITEMS, type ToolAction, type ToolGroup, type ToolItem, type ToolMatch, type ToolMode, WEML_LANGUAGE_ID, type WemlActionOptions, type WemlNormalizationFailure, type WemlToolbar, type WemlToolbarOptions, type WrapOption, buildWrapSnippet, canonicalFormattingFailureMessage, createEgwWebAuth, createMonacoPanelHost, createWemlToolbar, cycleFormat, filterToolItems, formatWemlText, insertSnippetById, isWemlNormalizationFailure, isWemlStructureValidationFailure, planDivIdRenumber, registerWeml, registerWemlEditorActions, renumberDivIds, toolItemsFor, validateWemlModel, wrapSelection };
package/dist/index.d.ts CHANGED
@@ -24,10 +24,11 @@ interface WemlActionOptions {
24
24
  }
25
25
  /** Wraps the current selection in `<tag [type=...]>…</tag>` (toolbar dropdown / hotkeys). */
26
26
  declare function wrapSelection(editor: monaco.editor.ICodeEditor, tag: string, type?: string): void;
27
- /** Inserts a snippet by its toolbar-button id (composite label or plain tag). */
27
+ /** Inserts a snippet by its id (`snippetBodyFor`: a composite label, the anchor, or a tag). */
28
28
  declare function insertSnippetById(editor: monaco.editor.ICodeEditor, id: string): void;
29
29
  /** Renumbers every `<div>` id in document order to a sequential 1..n. */
30
30
  declare function renumberDivIds(editor: monaco.editor.ICodeEditor, options?: WemlActionOptions): void;
31
+
31
32
  /**
32
33
  * Cycles the whole document between the standard HTML formatting (even steps) and
33
34
  * the canonical WEML normalizer (odd steps). The step counter advances on every
@@ -41,8 +42,8 @@ declare function cycleFormat(editor: monaco.editor.ICodeEditor, options?: WemlAc
41
42
  * (Ctrl+B / Ctrl+I / Ctrl+U). Returns an `IDisposable` that removes them.
42
43
  *
43
44
  * `editor.addAction` is per-editor (Monaco has no global command registry akin
44
- * to the VS Code extension host), so call this for every WEML editor — or just
45
- * use `createWemlToolbar`, which calls it for you.
45
+ * to the VS Code extension host), so call this for every WEML editor (the deprecated
46
+ * `createWemlToolbar` calls it for you; the WEML panel does not).
46
47
  */
47
48
  declare function registerWemlEditorActions(m: typeof monaco, editor: monaco.editor.IStandaloneCodeEditor, options?: WemlActionOptions): monaco.IDisposable;
48
49
 
@@ -69,9 +70,23 @@ interface WemlToolbar extends monaco.IDisposable {
69
70
  *
70
71
  * Returns the root element plus a `dispose()` that removes the toolbar and its
71
72
  * actions.
73
+ *
74
+ * @deprecated Use the WEML panel (`createWemlPanel` from `weml-monaco/panel`, with
75
+ * `createMonacoPanelHost`): the same Tools and Search Suggestions as the VS Code
76
+ * extension. For the hotkeys alone, call `registerWemlEditorActions`.
72
77
  */
73
78
  declare function createWemlToolbar(m: typeof monaco, editor: monaco.editor.IStandaloneCodeEditor, options?: WemlToolbarOptions): WemlToolbar;
74
79
 
80
+ /**
81
+ * Builds a `<tag ...>SELECTION</tag>` snippet body for wrapping `selection`.
82
+ * - `type` (e.g. for `w-format`) fills `type="..."` directly.
83
+ * - `a` gets only `href="$1"` (it lists both href and id as required, but a
84
+ * wrapped selection is a link).
85
+ * - otherwise the tag's required attributes become `name="$1"` placeholders.
86
+ * An empty selection leaves a tab stop where the content goes.
87
+ */
88
+ declare function buildWrapSnippet(tag: string, type: string | undefined, selection: string): string;
89
+
75
90
  interface IdEdit {
76
91
  /** Replacement range in the source text (start === end means a pure insertion). */
77
92
  start: number;
@@ -85,15 +100,193 @@ interface IdEdit {
85
100
  */
86
101
  declare function planDivIdRenumber(text: string): IdEdit[];
87
102
 
103
+ interface WrapOption {
104
+ /** Encoded option value, e.g. "w-format:italic" or "w-lang". */
105
+ value: string;
106
+ label: string;
107
+ tag: string;
108
+ /** The `type` of `w-format`; absent for the other inlines. */
109
+ type?: string;
110
+ }
111
+ /** The documentation's sections the tool picker groups its items by, in order. */
112
+ declare const TOOL_GROUPS: readonly ["Containers", "Blocks", "Inlines"];
113
+ type ToolGroup = (typeof TOOL_GROUPS)[number];
114
+ /** What a tool item does: wrap the selection, or insert a snippet at the cursor. */
115
+ type ToolAction = {
116
+ kind: 'wrap';
117
+ option: WrapOption;
118
+ } | {
119
+ kind: 'insert';
120
+ snippetId: string;
121
+ };
122
+ interface ToolItem {
123
+ /** Unique: the wrap option's value, or the snippet's tag. */
124
+ value: string;
125
+ /** What the picker shows and searches: the tag (`w-format.bold` for a format). */
126
+ label: string;
127
+ group: ToolGroup;
128
+ action: ToolAction;
129
+ /**
130
+ * A new section of `<body>` (a `<div id>` with its container): only for a whole document, not
131
+ * for an editor of one paragraph, whose model is a single `<div>` already.
132
+ */
133
+ documentOnly?: boolean;
134
+ }
135
+ /** What is edited: a whole WEML document, or one paragraph (the content of one `<div>`). */
136
+ type ToolMode = 'file' | 'paragraph';
88
137
  /**
89
- * Builds a `<tag ...>SELECTION</tag>` snippet body for wrapping `selection`.
90
- * - `type` (e.g. for `w-format`) fills `type="..."` directly.
91
- * - `a` gets only `href="$1"` (it lists both href and id as required, but a
92
- * wrapped selection is a link).
93
- * - otherwise the tag's required attributes become `name="$1"` placeholders.
94
- * An empty selection leaves a tab stop where the content goes.
138
+ * One list of everything the Tools offer — the snippets to insert, then the inlines to wrap the
139
+ * selection in — grouped as the WEML documentation is (containers, blocks, inlines).
95
140
  */
96
- declare function buildWrapSnippet(tag: string, type: string | undefined, selection: string): string;
141
+ declare const TOOL_ITEMS: ToolItem[];
142
+ /** The tool items for what is edited: a paragraph has no sections to add. */
143
+ declare function toolItemsFor(mode?: ToolMode): ToolItem[];
144
+ /** A tool item that matches a query, with the matched ranges of its label (`[start, end)`). */
145
+ interface ToolMatch {
146
+ item: ToolItem;
147
+ matches: [number, number][];
148
+ }
149
+ /**
150
+ * The items whose label contains `query` (case-insensitive; an empty query matches all), in
151
+ * `TOOL_ITEMS` order, with the match to highlight.
152
+ */
153
+ declare function filterToolItems(query: string, items?: readonly ToolItem[]): ToolMatch[];
154
+
155
+ /** The panel's remembered state (collapsed panes, pane sizes, per-pane values). */
156
+ interface WemlPanelStorage {
157
+ get(): unknown;
158
+ set(value: unknown): void;
159
+ }
160
+ /** The Tools pane's actions. */
161
+ interface WemlPanelTools {
162
+ /** Wraps the selection in the option's tag (a `WRAP_OPTIONS` entry). */
163
+ wrap(option: WrapOption): void;
164
+ /** Inserts a snippet by its id (weml-language-core's `snippetBodyFor`: a tag, a composite, the anchor). */
165
+ insertSnippet(id: string): void;
166
+ /** Renumbers every `<div>` id to 1…n. */
167
+ renumber(): void;
168
+ }
169
+ /** Whether search can run, and as whom. */
170
+ type WemlSearchState =
171
+ /** Something is missing on the host's side; `message` says what. */
172
+ {
173
+ kind: 'not-configured';
174
+ message: string;
175
+ canOpenSettings?: boolean;
176
+ } | {
177
+ kind: 'signed-out';
178
+ defaultLanguage?: string;
179
+ } | {
180
+ kind: 'signed-in';
181
+ account?: string;
182
+ defaultLanguage?: string;
183
+ };
184
+ /** A search suggestion as the panel shows it. */
185
+ interface WemlSearchResult {
186
+ paraId: string;
187
+ bookCode: string;
188
+ title: string;
189
+ /** The `egw://` link for a paragraph, or null. */
190
+ link: string | null;
191
+ }
192
+ /** The Search Suggestions pane's backend. */
193
+ interface WemlPanelSearch {
194
+ getState(): WemlSearchState | Promise<WemlSearchState>;
195
+ /** Calls `listener` whenever the state may have changed; returns the unsubscribe. */
196
+ onDidChangeState(listener: () => void): () => void;
197
+ /**
198
+ * Searches. The host cancels a previous request itself; the panel ignores answers that arrive
199
+ * after a newer search started. Rejects with an Error whose message the panel shows.
200
+ */
201
+ search(query: string, lang: string): Promise<WemlSearchResult[]>;
202
+ /** Starts the sign-in; a rejection's message is shown under the Sign in button. */
203
+ signIn(): void | Promise<void>;
204
+ /** Shown as a link next to a "not configured" message when the state allows it. */
205
+ openSettings?(): void;
206
+ copy(text: string): void;
207
+ /** Inserts the link of the result at `index` (of the last answer) in place of the selection. */
208
+ insertLink(index: number): void;
209
+ }
210
+ interface WemlPanelHost {
211
+ tools: WemlPanelTools;
212
+ /** Without it the panel has no Search Suggestions pane. */
213
+ search?: WemlPanelSearch;
214
+ /** Without it nothing is remembered (in memory for this panel only). */
215
+ storage?: WemlPanelStorage;
216
+ }
217
+
218
+ /** The EGW search as a web host provides it: where the API is, and how to get the user's token. */
219
+ interface MonacoPanelSearchOptions {
220
+ /** Base URL of the EGW API (`<apiUrl>/search/suggestions`). */
221
+ apiUrl: string;
222
+ /** The signed-in user's access token, or undefined when signed out. */
223
+ getAccessToken(): string | undefined | Promise<string | undefined>;
224
+ /** Starts the host application's sign-in; a rejection's message is shown in the pane. */
225
+ signIn?(): void | Promise<void>;
226
+ /** Notifies the panel when the user signs in or out; returns the unsubscribe. */
227
+ onDidChangeSession?(listener: () => void): () => void;
228
+ /** The account's display name, if the host wants it shown (it is not shown while signed in). */
229
+ account?(): string | undefined;
230
+ /** The search language until the user picks one. Default: `en`. */
231
+ defaultLanguage?: string;
232
+ }
233
+ interface MonacoPanelHostOptions extends WemlActionOptions {
234
+ /**
235
+ * The EGW search. Omitted: the Search Suggestions pane says the search is not configured;
236
+ * `false`: no Search Suggestions pane at all.
237
+ */
238
+ search?: MonacoPanelSearchOptions | false;
239
+ /** What the "not configured" message says when `search` is omitted. */
240
+ notConfiguredMessage?: string;
241
+ /**
242
+ * Where the panel remembers its layout. Default: `localStorage` under `weml-panel`;
243
+ * `false`: nothing is remembered.
244
+ */
245
+ storage?: WemlPanelStorage | false;
246
+ /** Copies text for the Copy buttons. Default: `navigator.clipboard.writeText`. */
247
+ copy?(text: string): void;
248
+ }
249
+ /** A WemlPanelHost for a Monaco editor on a web page. */
250
+ declare function createMonacoPanelHost(editor: monaco.editor.ICodeEditor, options?: MonacoPanelHostOptions): WemlPanelHost;
251
+
252
+ interface EgwWebAuthOptions {
253
+ /** OIDC authority (issuer); `/.well-known/openid-configuration` is read from it. */
254
+ authority: string;
255
+ clientId: string;
256
+ /** Space-separated scopes (`openid offline_access search …`). */
257
+ scopes: string;
258
+ /**
259
+ * Where the server sends the popup back to, on this page's origin; the client must allow it.
260
+ * Default: `<origin>/auth-callback`. Any page will do — it is read from here, not run — so a
261
+ * blank one is best.
262
+ */
263
+ redirectUri?: string;
264
+ /** Optional login page the authorize request goes through: `loginPageUrl?next=<authorize path>`. */
265
+ loginPageUrl?: string;
266
+ /**
267
+ * Where the session is kept. `session` (default): this tab, until it closes; `local`: every tab,
268
+ * across restarts; `false`: memory only, until the page reloads.
269
+ */
270
+ storage?: 'session' | 'local' | false;
271
+ }
272
+ interface EgwWebAuth {
273
+ /** The access token, refreshed when it is about to expire; undefined when signed out. */
274
+ getAccessToken(): Promise<string | undefined>;
275
+ /**
276
+ * Opens the sign-in popup — call it from a click, or the browser blocks the popup. Resolves once
277
+ * signed in; rejects with a message to show (popup blocked, closed, refused by the server).
278
+ */
279
+ signIn(): Promise<void>;
280
+ signOut(): void;
281
+ /** Calls `listener` on sign-in, sign-out and refresh (in other tabs too, with `local`). */
282
+ onDidChangeSession(listener: () => void): () => void;
283
+ /** The signed-in account's name, or undefined. */
284
+ account(): string | undefined;
285
+ /** Closes a pending popup and stops listening. */
286
+ dispose(): void;
287
+ }
288
+ /** The EGW sign-in for a web page: see `EgwWebAuthOptions`. */
289
+ declare function createEgwWebAuth(options: EgwWebAuthOptions): EgwWebAuth;
97
290
 
98
291
  interface RegisterWemlOptions {
99
292
  /** File extensions to associate with the language (default: [".weml"]). */
@@ -105,4 +298,4 @@ interface RegisterWemlOptions {
105
298
  }
106
299
  declare function registerWeml(m: typeof monaco, options?: RegisterWemlOptions): monaco.IDisposable;
107
300
 
108
- export { type IdEdit, type RegisterWemlOptions, WEML_LANGUAGE_ID, type WemlActionOptions, type WemlNormalizationFailure, type WemlToolbar, type WemlToolbarOptions, buildWrapSnippet, canonicalFormattingFailureMessage, createWemlToolbar, cycleFormat, formatWemlText, insertSnippetById, isWemlNormalizationFailure, isWemlStructureValidationFailure, planDivIdRenumber, registerWeml, registerWemlEditorActions, renumberDivIds, validateWemlModel, wrapSelection };
301
+ export { type EgwWebAuth, type EgwWebAuthOptions, type IdEdit, type MonacoPanelHostOptions, type MonacoPanelSearchOptions, type RegisterWemlOptions, TOOL_GROUPS, TOOL_ITEMS, type ToolAction, type ToolGroup, type ToolItem, type ToolMatch, type ToolMode, WEML_LANGUAGE_ID, type WemlActionOptions, type WemlNormalizationFailure, type WemlToolbar, type WemlToolbarOptions, type WrapOption, buildWrapSnippet, canonicalFormattingFailureMessage, createEgwWebAuth, createMonacoPanelHost, createWemlToolbar, cycleFormat, filterToolItems, formatWemlText, insertSnippetById, isWemlNormalizationFailure, isWemlStructureValidationFailure, planDivIdRenumber, registerWeml, registerWemlEditorActions, renumberDivIds, toolItemsFor, validateWemlModel, wrapSelection };