@prosemark/spellcheck-frontend 0.0.1

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/main.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ import * as _codemirror_state2 from "@codemirror/state";
2
+ import { Facet, RangeSet, RangeValue, StateField } from "@codemirror/state";
3
+ import * as _codemirror_view0 from "@codemirror/view";
4
+ import { EditorView, Tooltip } from "@codemirror/view";
5
+
6
+ //#region lib/tooltip.d.ts
7
+ interface SpellcheckAction {
8
+ label: string;
9
+ execute: (word: string, view: EditorView) => void | Promise<void>;
10
+ }
11
+ interface SpellcheckActionsConfig {
12
+ actions: SpellcheckAction[];
13
+ }
14
+ declare const suggestionFetcher: Facet<(word: string) => Promise<Suggestion[]>, readonly ((word: string) => Promise<Suggestion[]>)[]>;
15
+ declare const spellcheckActions: Facet<(word: string) => SpellcheckActionsConfig, (word: string) => SpellcheckActionsConfig>;
16
+ declare const setTooltip: _codemirror_state2.StateEffectType<Tooltip | null>;
17
+ declare const tooltipState: StateField<Tooltip | null>;
18
+ declare function showSpellcheckTooltip(view: EditorView, pos: number): boolean;
19
+ declare const contextMenuHandler: _codemirror_state2.Extension;
20
+ declare const spellcheckKeymap: _codemirror_state2.Extension;
21
+ declare const closeTooltipHandlers: _codemirror_state2.Extension[];
22
+ declare const spellcheckTooltipTheme: _codemirror_state2.Extension;
23
+ declare const spellcheckTooltipExtension: (_codemirror_state2.Extension | StateField<Tooltip | null>)[];
24
+ //#endregion
25
+ //#region lib/main.d.ts
26
+ interface Suggestion {
27
+ word: string;
28
+ isPreferred?: boolean;
29
+ }
30
+ declare class SpellcheckIssue extends RangeValue {
31
+ text: string;
32
+ suggestions?: Suggestion[] | undefined;
33
+ constructor(text: string, suggestions?: Suggestion[] | undefined);
34
+ eq(other: SpellcheckIssue): boolean;
35
+ }
36
+ declare const spellcheckIssues: Facet<RangeSet<SpellcheckIssue>, RangeSet<SpellcheckIssue>>;
37
+ declare const spellcheckExtension: (_codemirror_state2.Extension | (_codemirror_state2.Extension | _codemirror_state2.StateField<_codemirror_view0.Tooltip | null>)[])[];
38
+ //#endregion
39
+ export { type SpellcheckAction, type SpellcheckActionsConfig, SpellcheckIssue, Suggestion, closeTooltipHandlers, contextMenuHandler, setTooltip, showSpellcheckTooltip, spellcheckActions, spellcheckExtension, spellcheckIssues, spellcheckKeymap, spellcheckTooltipExtension, spellcheckTooltipTheme, suggestionFetcher, tooltipState };
40
+ //# sourceMappingURL=main.d.ts.map
package/dist/main.js ADDED
@@ -0,0 +1,345 @@
1
+ import { Facet, RangeSet, RangeSetBuilder, RangeValue, StateEffect, StateField } from "@codemirror/state";
2
+ import { Decoration, EditorView, ViewPlugin, keymap, showTooltip } from "@codemirror/view";
3
+
4
+ //#region lib/tooltip.ts
5
+ const suggestionFetcher = Facet.define();
6
+ const spellcheckActions = Facet.define({ combine(configs) {
7
+ return (word) => {
8
+ const allActions = [];
9
+ for (const provider of configs) {
10
+ const config = provider(word);
11
+ allActions.push(...config.actions);
12
+ }
13
+ return { actions: allActions };
14
+ };
15
+ } });
16
+ const setTooltip = StateEffect.define();
17
+ var SpellcheckTooltipView = class {
18
+ dom;
19
+ #issue;
20
+ #from;
21
+ #to;
22
+ #fetchSuggestions;
23
+ constructor(issue, from, to, view, fetchSuggestions) {
24
+ this.#issue = issue;
25
+ this.#from = from;
26
+ this.#to = to;
27
+ this.#fetchSuggestions = fetchSuggestions;
28
+ this.dom = document.createElement("div");
29
+ this.dom.className = "cm-spellcheck-tooltip";
30
+ this.#initializeContent(view);
31
+ }
32
+ #initializeContent(view) {
33
+ const wrapper = document.createElement("div");
34
+ const actionsSection = this.#createActionsSection(view);
35
+ if (actionsSection) wrapper.appendChild(actionsSection);
36
+ const suggestionsSection = this.#createSuggestionsSection(view);
37
+ wrapper.appendChild(suggestionsSection);
38
+ this.dom.appendChild(wrapper);
39
+ }
40
+ #createSuggestionsSection(view) {
41
+ const container = document.createElement("div");
42
+ if (this.#issue.suggestions && Array.isArray(this.#issue.suggestions) && this.#issue.suggestions.length > 0) {
43
+ container.appendChild(this.#createSuggestionsList(this.#issue.suggestions, view));
44
+ return container;
45
+ }
46
+ if (this.#fetchSuggestions) {
47
+ const loading = document.createElement("div");
48
+ loading.className = "cm-spellcheck-tooltip-loading";
49
+ loading.textContent = "Loading suggestions...";
50
+ container.appendChild(loading);
51
+ this.#fetchSuggestions(this.#issue.text).then((suggestions) => {
52
+ container.innerHTML = "";
53
+ if (!Array.isArray(suggestions) || suggestions.length === 0) {
54
+ container.appendChild(this.#createNoSuggestionsMessage());
55
+ return;
56
+ }
57
+ container.appendChild(this.#createSuggestionsList(suggestions, view));
58
+ }).catch((error) => {
59
+ container.innerHTML = "";
60
+ container.appendChild(this.#createErrorMessage());
61
+ if (error instanceof Error) console.error("Failed to fetch suggestions:", error);
62
+ else console.error("Failed to fetch suggestions:", String(error));
63
+ });
64
+ return container;
65
+ }
66
+ container.appendChild(this.#createNoSuggestionsMessage());
67
+ return container;
68
+ }
69
+ #createActionsSection(view) {
70
+ const config = view.state.facet(spellcheckActions)(this.#issue.text);
71
+ if (config.actions.length === 0) return null;
72
+ const allActions = config.actions;
73
+ const actionsContainer = document.createElement("div");
74
+ actionsContainer.className = "cm-spellcheck-tooltip-actions-container";
75
+ const actionsHeading = document.createElement("div");
76
+ actionsHeading.className = "cm-spellcheck-tooltip-heading";
77
+ actionsHeading.textContent = "Actions";
78
+ actionsContainer.appendChild(actionsHeading);
79
+ const actionsList = document.createElement("div");
80
+ actionsList.className = "cm-spellcheck-tooltip-actions";
81
+ for (const action of allActions) {
82
+ const item = document.createElement("button");
83
+ item.className = "cm-spellcheck-tooltip-item";
84
+ item.textContent = action.label;
85
+ item.onclick = async (e) => {
86
+ e.preventDefault();
87
+ e.stopPropagation();
88
+ try {
89
+ await action.execute(this.#issue.text, view);
90
+ } catch (error) {
91
+ if (error instanceof Error) console.error("Failed to execute action:", error);
92
+ else console.error("Failed to execute action:", String(error));
93
+ } finally {
94
+ view.dispatch({ effects: setTooltip.of(null) });
95
+ }
96
+ };
97
+ actionsList.appendChild(item);
98
+ }
99
+ actionsContainer.appendChild(actionsList);
100
+ return actionsContainer;
101
+ }
102
+ #createSuggestionsList(suggestions, view) {
103
+ const container = document.createElement("div");
104
+ container.className = "cm-spellcheck-tooltip-suggestions-container";
105
+ const heading = document.createElement("div");
106
+ heading.className = "cm-spellcheck-tooltip-heading";
107
+ heading.textContent = "Suggestions";
108
+ container.appendChild(heading);
109
+ const suggestionsList = document.createElement("div");
110
+ suggestionsList.className = "cm-spellcheck-tooltip-suggestions";
111
+ for (const suggestion of suggestions) {
112
+ const item = document.createElement("button");
113
+ item.className = "cm-spellcheck-tooltip-item";
114
+ if (suggestion.isPreferred) item.classList.add("cm-spellcheck-tooltip-item-preferred");
115
+ item.textContent = suggestion.word;
116
+ item.onclick = (e) => {
117
+ e.preventDefault();
118
+ e.stopPropagation();
119
+ this.#onSelect(suggestion.word, view);
120
+ };
121
+ suggestionsList.appendChild(item);
122
+ }
123
+ container.appendChild(suggestionsList);
124
+ return container;
125
+ }
126
+ #createNoSuggestionsMessage() {
127
+ const noSuggestions = document.createElement("div");
128
+ noSuggestions.className = "cm-spellcheck-tooltip-empty";
129
+ noSuggestions.textContent = "No suggestions available";
130
+ return noSuggestions;
131
+ }
132
+ #createErrorMessage() {
133
+ const errorMsg = document.createElement("div");
134
+ errorMsg.className = "cm-spellcheck-tooltip-error";
135
+ errorMsg.textContent = "Failed to load suggestions";
136
+ return errorMsg;
137
+ }
138
+ #onSelect(word, view) {
139
+ view.dispatch({
140
+ changes: {
141
+ from: this.#from,
142
+ to: this.#to,
143
+ insert: word
144
+ },
145
+ selection: { anchor: this.#from + word.length }
146
+ });
147
+ view.dispatch({ effects: setTooltip.of(null) });
148
+ }
149
+ };
150
+ const tooltipState = StateField.define({
151
+ create: () => null,
152
+ update(value, tr) {
153
+ if (tr.docChanged) return null;
154
+ for (const effect of tr.effects) if (effect.is(setTooltip)) return effect.value;
155
+ return value;
156
+ },
157
+ provide: (f) => showTooltip.from(f)
158
+ });
159
+ function showSpellcheckTooltip(view, pos) {
160
+ const issues = view.state.facet(spellcheckIssues);
161
+ let tooltipShown = false;
162
+ issues.between(pos, pos, (from, to, issue) => {
163
+ if (pos < from || pos > to) return false;
164
+ const fetchers = view.state.facet(suggestionFetcher);
165
+ const fetchSuggestions = fetchers.length > 0 ? fetchers[0] : void 0;
166
+ const tooltip = {
167
+ pos,
168
+ end: pos,
169
+ above: false,
170
+ create(view$1) {
171
+ return new SpellcheckTooltipView(issue, from, to, view$1, fetchSuggestions);
172
+ }
173
+ };
174
+ view.dispatch({ effects: setTooltip.of(tooltip) });
175
+ tooltipShown = true;
176
+ return false;
177
+ });
178
+ return tooltipShown;
179
+ }
180
+ const contextMenuHandler = EditorView.domEventHandlers({ contextmenu(event, view) {
181
+ const pos = view.posAtCoords({
182
+ x: event.clientX,
183
+ y: event.clientY
184
+ });
185
+ if (pos == null) return false;
186
+ if (showSpellcheckTooltip(view, pos)) {
187
+ event.preventDefault();
188
+ return true;
189
+ }
190
+ return false;
191
+ } });
192
+ const showSuggestionsCommand = (view) => {
193
+ const pos = view.state.selection.main.head;
194
+ return showSpellcheckTooltip(view, pos);
195
+ };
196
+ const spellcheckKeymap = keymap.of([{
197
+ key: "Ctrl-.",
198
+ run: showSuggestionsCommand
199
+ }]);
200
+ const closeTooltipHandlers = [EditorView.domEventHandlers({ mousedown(event, view) {
201
+ if (event.target.closest(".cm-spellcheck-tooltip")) return false;
202
+ if (view.state.field(tooltipState)) view.dispatch({ effects: setTooltip.of(null) });
203
+ return false;
204
+ } }), keymap.of([{
205
+ key: "Escape",
206
+ run: (view) => {
207
+ if (view.state.field(tooltipState)) {
208
+ view.dispatch({ effects: setTooltip.of(null) });
209
+ return true;
210
+ }
211
+ return false;
212
+ }
213
+ }])];
214
+ const spellcheckTooltipTheme = EditorView.theme({
215
+ ".cm-spellcheck-tooltip": {
216
+ backgroundColor: "var(--pm-spellcheck-tooltip-background, #fff) !important",
217
+ border: "1px solid var(--pm-spellcheck-tooltip-border, #ccc) !important",
218
+ borderRadius: "4px",
219
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
220
+ padding: "2px",
221
+ maxWidth: "300px",
222
+ maxHeight: "50vh",
223
+ overflowY: "auto",
224
+ zIndex: "1000",
225
+ fontSize: "var(--pm-spellcheck-tooltip-font-size, 0.9rem)"
226
+ },
227
+ ".cm-spellcheck-tooltip-empty": {
228
+ padding: "4px 6px",
229
+ color: "var(--pm-spellcheck-tooltip-text, #666)",
230
+ fontSize: "inherit"
231
+ },
232
+ ".cm-spellcheck-tooltip-loading": {
233
+ padding: "4px 6px",
234
+ color: "var(--pm-spellcheck-tooltip-text, #666)",
235
+ fontSize: "inherit",
236
+ fontStyle: "italic"
237
+ },
238
+ ".cm-spellcheck-tooltip-error": {
239
+ padding: "4px 6px",
240
+ color: "var(--pm-spellcheck-tooltip-error, #d32f2f)",
241
+ fontSize: "inherit"
242
+ },
243
+ ".cm-spellcheck-tooltip-suggestions-container": {
244
+ display: "flex",
245
+ flexDirection: "column"
246
+ },
247
+ ".cm-spellcheck-tooltip-heading": {
248
+ padding: "4px 6px",
249
+ color: "var(--pm-spellcheck-tooltip-text, #666)",
250
+ fontSize: "0.85em",
251
+ fontWeight: "600",
252
+ borderBottom: "1px solid var(--pm-spellcheck-tooltip-border, #ccc)",
253
+ marginBottom: "2px"
254
+ },
255
+ ".cm-spellcheck-tooltip-suggestions": {
256
+ display: "flex",
257
+ flexDirection: "column",
258
+ gap: "1px"
259
+ },
260
+ ".cm-spellcheck-tooltip-actions-container": {
261
+ display: "flex",
262
+ flexDirection: "column",
263
+ borderBottom: "1px solid var(--pm-spellcheck-tooltip-actions-border, var(--pm-spellcheck-tooltip-border, #ccc))",
264
+ marginBottom: "4px",
265
+ paddingBottom: "4px"
266
+ },
267
+ ".cm-spellcheck-tooltip-actions": {
268
+ display: "flex",
269
+ flexDirection: "column",
270
+ gap: "1px"
271
+ },
272
+ ".cm-spellcheck-tooltip-item": {
273
+ padding: "3px 6px",
274
+ textAlign: "left",
275
+ border: "none",
276
+ background: "transparent",
277
+ cursor: "pointer",
278
+ fontSize: "inherit",
279
+ color: "var(--pm-spellcheck-tooltip-text, #333)",
280
+ borderRadius: "2px",
281
+ transition: "background-color 0.1s"
282
+ },
283
+ ".cm-spellcheck-tooltip-item:hover": { backgroundColor: "var(--pm-spellcheck-tooltip-hover, #f0f0f0)" },
284
+ ".cm-spellcheck-tooltip-item-preferred": { fontWeight: "600" }
285
+ });
286
+ const spellcheckTooltipExtension = [
287
+ tooltipState,
288
+ contextMenuHandler,
289
+ spellcheckKeymap,
290
+ ...closeTooltipHandlers,
291
+ spellcheckTooltipTheme
292
+ ];
293
+
294
+ //#endregion
295
+ //#region lib/main.ts
296
+ var SpellcheckIssue = class extends RangeValue {
297
+ constructor(text, suggestions) {
298
+ super();
299
+ this.text = text;
300
+ this.suggestions = suggestions;
301
+ }
302
+ eq(other) {
303
+ return this.text === other.text && this.startSide === other.startSide && this.endSide === other.endSide && JSON.stringify(this.suggestions) === JSON.stringify(other.suggestions);
304
+ }
305
+ };
306
+ const spellcheckIssues = Facet.define({ combine(issues) {
307
+ return issues.length > 0 ? issues[issues.length - 1] : RangeSet.of([]);
308
+ } });
309
+ const underlineMark = Decoration.mark({ class: "cm-spellcheck-issue" });
310
+ function buildDecorations(view, issues) {
311
+ if (!issues) return Decoration.none;
312
+ const builder = new RangeSetBuilder();
313
+ issues.between(0, view.state.doc.length, (from, to) => {
314
+ builder.add(from, to, underlineMark);
315
+ });
316
+ return builder.finish();
317
+ }
318
+ const spellcheckDecorations = ViewPlugin.fromClass(class SpellcheckDecorations {
319
+ decorations;
320
+ constructor(view) {
321
+ this.view = view;
322
+ this.decorations = buildDecorations(view, view.state.facet(spellcheckIssues));
323
+ }
324
+ update(update) {
325
+ if (update.startState.facet(spellcheckIssues) !== update.state.facet(spellcheckIssues)) {
326
+ const issues = update.state.facet(spellcheckIssues);
327
+ this.decorations = buildDecorations(update.view, issues);
328
+ }
329
+ }
330
+ }, { decorations: (v) => v.decorations });
331
+ const spellcheckTheme = EditorView.baseTheme({ ".cm-spellcheck-issue": {
332
+ textDecoration: "underline",
333
+ textDecorationColor: "var(--pm-spellcheck-issue-underline-color, #037bfc)",
334
+ backgroundColor: "var(--pm-spellcheck-issue-background-color)",
335
+ textDecorationStyle: "wavy"
336
+ } });
337
+ const spellcheckExtension = [
338
+ spellcheckDecorations,
339
+ spellcheckTheme,
340
+ spellcheckTooltipExtension
341
+ ];
342
+
343
+ //#endregion
344
+ export { SpellcheckIssue, closeTooltipHandlers, contextMenuHandler, setTooltip, showSpellcheckTooltip, spellcheckActions, spellcheckExtension, spellcheckIssues, spellcheckKeymap, spellcheckTooltipExtension, spellcheckTooltipTheme, suggestionFetcher, tooltipState };
345
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","names":["allActions: SpellcheckAction[]","#issue","#from","#to","#fetchSuggestions","#initializeContent","#createActionsSection","#createSuggestionsSection","#createSuggestionsList","#createNoSuggestionsMessage","#createErrorMessage","#onSelect","tooltip: Tooltip","view","showSuggestionsCommand: Command","text: string","suggestions?: Suggestion[]","view: EditorView"],"sources":["../lib/tooltip.ts","../lib/main.ts"],"sourcesContent":["import { Facet, StateEffect, StateField } from '@codemirror/state';\nimport {\n EditorView,\n showTooltip,\n type Tooltip,\n type TooltipView,\n keymap,\n type Command,\n} from '@codemirror/view';\nimport { SpellcheckIssue, spellcheckIssues, type Suggestion } from './main';\n\nexport interface SpellcheckAction {\n label: string;\n execute: (word: string, view: EditorView) => void | Promise<void>;\n}\n\nexport interface SpellcheckActionsConfig {\n actions: SpellcheckAction[];\n}\n\n// Facet for providing a callback to fetch suggestions asynchronously\nexport const suggestionFetcher =\n Facet.define<(word: string) => Promise<Suggestion[]>>();\n\n// Facet for providing extra actions to show in the tooltip\nexport const spellcheckActions = Facet.define<\n (word: string) => SpellcheckActionsConfig,\n (word: string) => SpellcheckActionsConfig\n>({\n combine(configs) {\n return (word: string): SpellcheckActionsConfig => {\n const allActions: SpellcheckAction[] = [];\n for (const provider of configs) {\n const config = provider(word);\n allActions.push(...config.actions);\n }\n return { actions: allActions };\n };\n },\n});\n\n// Tooltip state management using a StateField\nexport const setTooltip = StateEffect.define<Tooltip | null>();\n\n// Class that implements TooltipView to manage spellcheck tooltip content\nclass SpellcheckTooltipView implements TooltipView {\n public readonly dom: HTMLElement;\n readonly #issue: SpellcheckIssue;\n readonly #from: number;\n readonly #to: number;\n readonly #fetchSuggestions:\n | ((word: string) => Promise<Suggestion[]>)\n | undefined;\n\n constructor(\n issue: SpellcheckIssue,\n from: number,\n to: number,\n view: EditorView,\n fetchSuggestions?: (word: string) => Promise<Suggestion[]>,\n ) {\n this.#issue = issue;\n this.#from = from;\n this.#to = to;\n this.#fetchSuggestions = fetchSuggestions;\n\n this.dom = document.createElement('div');\n this.dom.className = 'cm-spellcheck-tooltip';\n\n this.#initializeContent(view);\n }\n\n #initializeContent(view: EditorView): void {\n const wrapper = document.createElement('div');\n\n // Build actions section first (independent of suggestions)\n const actionsSection = this.#createActionsSection(view);\n if (actionsSection) {\n wrapper.appendChild(actionsSection);\n }\n\n // Build suggestions section (independent of actions)\n const suggestionsSection = this.#createSuggestionsSection(view);\n wrapper.appendChild(suggestionsSection);\n\n this.dom.appendChild(wrapper);\n }\n\n #createSuggestionsSection(view: EditorView): HTMLElement {\n const container = document.createElement('div');\n\n // If suggestions are already available, show them\n if (\n this.#issue.suggestions &&\n Array.isArray(this.#issue.suggestions) &&\n this.#issue.suggestions.length > 0\n ) {\n container.appendChild(\n this.#createSuggestionsList(this.#issue.suggestions, view),\n );\n return container;\n }\n\n // If we have a fetcher, show loading and fetch\n if (this.#fetchSuggestions) {\n const loading = document.createElement('div');\n loading.className = 'cm-spellcheck-tooltip-loading';\n loading.textContent = 'Loading suggestions...';\n container.appendChild(loading);\n\n // Fetch suggestions asynchronously\n this.#fetchSuggestions(this.#issue.text)\n .then((suggestions) => {\n // Replace loading message\n container.innerHTML = '';\n\n // Ensure suggestions is an array\n if (!Array.isArray(suggestions) || suggestions.length === 0) {\n container.appendChild(this.#createNoSuggestionsMessage());\n return;\n }\n\n container.appendChild(this.#createSuggestionsList(suggestions, view));\n })\n .catch((error: unknown) => {\n // Replace loading message with error\n container.innerHTML = '';\n container.appendChild(this.#createErrorMessage());\n if (error instanceof Error) {\n console.error('Failed to fetch suggestions:', error);\n } else {\n console.error('Failed to fetch suggestions:', String(error));\n }\n });\n\n return container;\n }\n\n // No suggestions and no fetcher\n container.appendChild(this.#createNoSuggestionsMessage());\n return container;\n }\n\n #createActionsSection(view: EditorView): HTMLElement | null {\n const actionProvider = view.state.facet(spellcheckActions);\n\n const config = actionProvider(this.#issue.text);\n if (config.actions.length === 0) {\n return null;\n }\n\n const allActions = config.actions;\n\n const actionsContainer = document.createElement('div');\n actionsContainer.className = 'cm-spellcheck-tooltip-actions-container';\n\n const actionsHeading = document.createElement('div');\n actionsHeading.className = 'cm-spellcheck-tooltip-heading';\n actionsHeading.textContent = 'Actions';\n actionsContainer.appendChild(actionsHeading);\n\n const actionsList = document.createElement('div');\n actionsList.className = 'cm-spellcheck-tooltip-actions';\n\n for (const action of allActions) {\n const item = document.createElement('button');\n item.className = 'cm-spellcheck-tooltip-item';\n item.textContent = action.label;\n item.onclick = async (e) => {\n e.preventDefault();\n e.stopPropagation();\n try {\n await action.execute(this.#issue.text, view);\n } catch (error) {\n if (error instanceof Error) {\n console.error('Failed to execute action:', error);\n } else {\n console.error('Failed to execute action:', String(error));\n }\n } finally {\n view.dispatch({ effects: setTooltip.of(null) });\n }\n };\n actionsList.appendChild(item);\n }\n\n actionsContainer.appendChild(actionsList);\n return actionsContainer;\n }\n\n #createSuggestionsList(\n suggestions: Suggestion[],\n view: EditorView,\n ): HTMLElement {\n const container = document.createElement('div');\n container.className = 'cm-spellcheck-tooltip-suggestions-container';\n\n const heading = document.createElement('div');\n heading.className = 'cm-spellcheck-tooltip-heading';\n heading.textContent = 'Suggestions';\n container.appendChild(heading);\n\n const suggestionsList = document.createElement('div');\n suggestionsList.className = 'cm-spellcheck-tooltip-suggestions';\n\n for (const suggestion of suggestions) {\n const item = document.createElement('button');\n item.className = 'cm-spellcheck-tooltip-item';\n if (suggestion.isPreferred) {\n item.classList.add('cm-spellcheck-tooltip-item-preferred');\n }\n item.textContent = suggestion.word;\n item.onclick = (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.#onSelect(suggestion.word, view);\n };\n suggestionsList.appendChild(item);\n }\n\n container.appendChild(suggestionsList);\n return container;\n }\n\n #createNoSuggestionsMessage(): HTMLElement {\n const noSuggestions = document.createElement('div');\n noSuggestions.className = 'cm-spellcheck-tooltip-empty';\n noSuggestions.textContent = 'No suggestions available';\n return noSuggestions;\n }\n\n #createErrorMessage(): HTMLElement {\n const errorMsg = document.createElement('div');\n errorMsg.className = 'cm-spellcheck-tooltip-error';\n errorMsg.textContent = 'Failed to load suggestions';\n return errorMsg;\n }\n\n #onSelect(word: string, view: EditorView): void {\n // Replace the misspelled word with the selected suggestion\n view.dispatch({\n changes: { from: this.#from, to: this.#to, insert: word },\n selection: { anchor: this.#from + word.length },\n });\n // Close tooltip\n view.dispatch({ effects: setTooltip.of(null) });\n }\n}\n\nexport const tooltipState = StateField.define<Tooltip | null>({\n create: () => null,\n update(value, tr) {\n // Close tooltip on document changes (when text is edited)\n if (tr.docChanged) {\n return null;\n }\n // Update tooltip if setTooltip effect is dispatched\n for (const effect of tr.effects) {\n if (effect.is(setTooltip)) {\n return effect.value;\n }\n }\n return value;\n },\n provide: (f) => showTooltip.from(f),\n});\n\n// Function to show tooltip at a position\nexport function showSpellcheckTooltip(view: EditorView, pos: number): boolean {\n const issues = view.state.facet(spellcheckIssues);\n let tooltipShown = false;\n\n issues.between(pos, pos, (from, to, issue) => {\n if (pos < from || pos > to) return false;\n // Get suggestion fetcher from facet if available\n const fetchers = view.state.facet(suggestionFetcher);\n const fetchSuggestions = fetchers.length > 0 ? fetchers[0] : undefined;\n\n // Create tooltip\n const tooltip: Tooltip = {\n pos: pos,\n end: pos,\n above: false,\n create(view) {\n return new SpellcheckTooltipView(\n issue,\n from,\n to,\n view,\n fetchSuggestions,\n );\n },\n };\n\n view.dispatch({ effects: setTooltip.of(tooltip) });\n\n tooltipShown = true;\n return false;\n });\n\n return tooltipShown;\n}\n\n// Right-click handler\nexport const contextMenuHandler = EditorView.domEventHandlers({\n contextmenu(event, view) {\n const pos = view.posAtCoords({ x: event.clientX, y: event.clientY });\n if (pos == null) return false;\n\n const tooltipShown = showSpellcheckTooltip(view, pos);\n if (tooltipShown) {\n event.preventDefault();\n return true;\n }\n\n return false;\n },\n});\n\n// Ctrl+. keyboard shortcut handler\nconst showSuggestionsCommand: Command = (view) => {\n const pos = view.state.selection.main.head;\n return showSpellcheckTooltip(view, pos);\n};\n\nexport const spellcheckKeymap = keymap.of([\n {\n key: 'Ctrl-.',\n run: showSuggestionsCommand,\n },\n]);\n\n// Close tooltip on click outside or escape key\nexport const closeTooltipHandlers = [\n EditorView.domEventHandlers({\n mousedown(event, view) {\n // Don't close if clicking inside the tooltip\n const target = event.target as HTMLElement;\n if (target.closest('.cm-spellcheck-tooltip')) {\n return false;\n }\n // Close tooltip if clicking outside\n const tooltip = view.state.field(tooltipState);\n if (tooltip) {\n view.dispatch({ effects: setTooltip.of(null) });\n }\n return false;\n },\n }),\n keymap.of([\n {\n key: 'Escape',\n run: (view) => {\n const tooltip = view.state.field(tooltipState);\n if (tooltip) {\n view.dispatch({ effects: setTooltip.of(null) });\n return true;\n }\n return false;\n },\n },\n ]),\n];\n\nexport const spellcheckTooltipTheme = EditorView.theme({\n '.cm-spellcheck-tooltip': {\n backgroundColor: 'var(--pm-spellcheck-tooltip-background, #fff) !important',\n border: '1px solid var(--pm-spellcheck-tooltip-border, #ccc) !important',\n borderRadius: '4px',\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n padding: '2px',\n maxWidth: '300px',\n maxHeight: '50vh',\n overflowY: 'auto',\n zIndex: '1000',\n fontSize: 'var(--pm-spellcheck-tooltip-font-size, 0.9rem)',\n },\n '.cm-spellcheck-tooltip-empty': {\n padding: '4px 6px',\n color: 'var(--pm-spellcheck-tooltip-text, #666)',\n fontSize: 'inherit',\n },\n '.cm-spellcheck-tooltip-loading': {\n padding: '4px 6px',\n color: 'var(--pm-spellcheck-tooltip-text, #666)',\n fontSize: 'inherit',\n fontStyle: 'italic',\n },\n '.cm-spellcheck-tooltip-error': {\n padding: '4px 6px',\n color: 'var(--pm-spellcheck-tooltip-error, #d32f2f)',\n fontSize: 'inherit',\n },\n '.cm-spellcheck-tooltip-suggestions-container': {\n display: 'flex',\n flexDirection: 'column',\n },\n '.cm-spellcheck-tooltip-heading': {\n padding: '4px 6px',\n color: 'var(--pm-spellcheck-tooltip-text, #666)',\n fontSize: '0.85em',\n fontWeight: '600',\n borderBottom: '1px solid var(--pm-spellcheck-tooltip-border, #ccc)',\n marginBottom: '2px',\n },\n '.cm-spellcheck-tooltip-suggestions': {\n display: 'flex',\n flexDirection: 'column',\n gap: '1px',\n },\n '.cm-spellcheck-tooltip-actions-container': {\n display: 'flex',\n flexDirection: 'column',\n borderBottom:\n '1px solid var(--pm-spellcheck-tooltip-actions-border, var(--pm-spellcheck-tooltip-border, #ccc))',\n marginBottom: '4px',\n paddingBottom: '4px',\n },\n '.cm-spellcheck-tooltip-actions': {\n display: 'flex',\n flexDirection: 'column',\n gap: '1px',\n },\n '.cm-spellcheck-tooltip-item': {\n padding: '3px 6px',\n textAlign: 'left',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n fontSize: 'inherit',\n color: 'var(--pm-spellcheck-tooltip-text, #333)',\n borderRadius: '2px',\n transition: 'background-color 0.1s',\n },\n '.cm-spellcheck-tooltip-item:hover': {\n backgroundColor: 'var(--pm-spellcheck-tooltip-hover, #f0f0f0)',\n },\n '.cm-spellcheck-tooltip-item-preferred': {\n fontWeight: '600',\n },\n});\n\nexport const spellcheckTooltipExtension = [\n tooltipState,\n contextMenuHandler,\n spellcheckKeymap,\n ...closeTooltipHandlers,\n spellcheckTooltipTheme,\n];\n","import {\n RangeSet,\n RangeValue,\n RangeSetBuilder,\n Facet,\n} from '@codemirror/state';\nimport {\n Decoration,\n type DecorationSet,\n EditorView,\n ViewPlugin,\n ViewUpdate,\n} from '@codemirror/view';\n// Import tooltip-related exports\nimport { spellcheckTooltipExtension } from './tooltip';\n\nexport interface Suggestion {\n word: string;\n isPreferred?: boolean;\n}\n\nexport class SpellcheckIssue extends RangeValue {\n constructor(\n public text: string,\n public suggestions?: Suggestion[],\n ) {\n super();\n }\n\n eq(other: SpellcheckIssue): boolean {\n return (\n this.text === other.text &&\n this.startSide === other.startSide &&\n this.endSide === other.endSide &&\n JSON.stringify(this.suggestions) === JSON.stringify(other.suggestions)\n );\n }\n}\n\nexport const spellcheckIssues = Facet.define<\n RangeSet<SpellcheckIssue>,\n RangeSet<SpellcheckIssue>\n>({\n combine(issues) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return issues.length > 0 ? issues[issues.length - 1]! : RangeSet.of([]);\n },\n});\n\n// Decoration to apply to misspelled ranges\nconst underlineMark = Decoration.mark({ class: 'cm-spellcheck-issue' });\n\nfunction buildDecorations(\n view: EditorView,\n issues?: RangeSet<SpellcheckIssue>,\n): DecorationSet {\n if (!issues) return Decoration.none;\n const builder = new RangeSetBuilder<Decoration>();\n issues.between(0, view.state.doc.length, (from, to) => {\n builder.add(from, to, underlineMark);\n });\n return builder.finish();\n}\n\nconst spellcheckDecorations = ViewPlugin.fromClass(\n class SpellcheckDecorations {\n decorations;\n constructor(public view: EditorView) {\n const issues = view.state.facet(spellcheckIssues);\n this.decorations = buildDecorations(view, issues);\n }\n update(update: ViewUpdate) {\n // Rebuild decorations when doc changes or when issues are updated\n if (\n update.startState.facet(spellcheckIssues) !==\n update.state.facet(spellcheckIssues)\n ) {\n const issues = update.state.facet(spellcheckIssues);\n this.decorations = buildDecorations(update.view, issues);\n }\n }\n },\n {\n decorations: (v) => v.decorations,\n },\n);\n\nconst spellcheckTheme = EditorView.baseTheme({\n '.cm-spellcheck-issue': {\n textDecoration: 'underline',\n textDecorationColor: 'var(--pm-spellcheck-issue-underline-color, #037bfc)',\n backgroundColor: 'var(--pm-spellcheck-issue-background-color)',\n textDecorationStyle: 'wavy',\n },\n});\n\nexport const spellcheckExtension = [\n spellcheckDecorations,\n spellcheckTheme,\n spellcheckTooltipExtension,\n];\n\n// Re-export tooltip-related exports\nexport {\n setTooltip,\n tooltipState,\n showSpellcheckTooltip,\n contextMenuHandler,\n spellcheckKeymap,\n closeTooltipHandlers,\n type SpellcheckAction,\n type SpellcheckActionsConfig,\n suggestionFetcher,\n spellcheckActions,\n spellcheckTooltipTheme,\n spellcheckTooltipExtension,\n} from './tooltip';\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@prosemark/spellcheck-frontend",
3
+ "version": "0.0.1",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "repository": {
8
+ "url": "https://github.com/jsimonrichard/ProseMark",
9
+ "type": "github"
10
+ },
11
+ "author": {
12
+ "name": "J. Simon Richard",
13
+ "url": "https://jsimonrichard.com"
14
+ },
15
+ "license": "MIT",
16
+ "type": "module",
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "main": "./dist/main.js",
21
+ "module": "./dist/main.js",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/main.d.ts",
25
+ "import": "./dist/main.js"
26
+ }
27
+ },
28
+ "scripts": {
29
+ "dev": "tsdown --watch",
30
+ "build": "tsdown",
31
+ "lint": "eslint --max-warnings=0",
32
+ "check-types": "tsc",
33
+ "ci:publish": "bash ../../scripts/ci-publish.sh"
34
+ },
35
+ "keywords": [],
36
+ "dependencies": {
37
+ "@codemirror/state": "^6.5.2",
38
+ "@codemirror/view": "^6.38.0",
39
+ "@prosemark/core": "0.0.4"
40
+ }
41
+ }