react-codemirror-editor 0.1.2 → 0.2.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.
Files changed (41) hide show
  1. package/README.md +155 -16
  2. package/dist/core/diagnostics/json/index.d.ts.map +1 -0
  3. package/dist/core/diagnostics/{jsonDiagnostics.d.ts → json/jsonDiagnostics.d.ts} +1 -1
  4. package/dist/core/diagnostics/json/jsonDiagnostics.d.ts.map +1 -0
  5. package/dist/core/diagnostics/json/jsonDiagnostics.js +32 -0
  6. package/dist/core/diagnostics/json/jsonLinter.d.ts +4 -0
  7. package/dist/core/diagnostics/json/jsonLinter.d.ts.map +1 -0
  8. package/dist/core/diagnostics/json/jsonLinter.js +42 -0
  9. package/dist/core/diagnostics/json/jsonValidation.d.ts +4 -0
  10. package/dist/core/diagnostics/json/jsonValidation.d.ts.map +1 -0
  11. package/dist/core/diagnostics/json/jsonValidation.js +8 -0
  12. package/dist/core/diagnostics/json/safeJsonCompletion.d.ts +3 -0
  13. package/dist/core/diagnostics/json/safeJsonCompletion.d.ts.map +1 -0
  14. package/dist/core/diagnostics/json/safeJsonCompletion.js +8 -0
  15. package/dist/core/editor/createEditor.d.ts +1 -1
  16. package/dist/core/editor/createEditor.d.ts.map +1 -1
  17. package/dist/core/editor/createEditor.js +3 -2
  18. package/dist/core/editor/editorController.d.ts.map +1 -1
  19. package/dist/core/editor/editorController.js +19 -1
  20. package/dist/core/extensions/fold.d.ts.map +1 -1
  21. package/dist/core/extensions/fold.js +14 -2
  22. package/dist/core/extensions/index.d.ts +1 -0
  23. package/dist/core/extensions/index.d.ts.map +1 -1
  24. package/dist/core/extensions/index.js +1 -0
  25. package/dist/core/extensions/search.d.ts +11 -0
  26. package/dist/core/extensions/search.d.ts.map +1 -0
  27. package/dist/core/extensions/search.js +54 -0
  28. package/dist/core/languages/buildExtensions.js +1 -1
  29. package/dist/types/editor.d.ts +17 -0
  30. package/dist/types/editor.d.ts.map +1 -1
  31. package/dist/ui/CodeEditor.d.ts.map +1 -1
  32. package/dist/ui/CodeEditor.js +2 -2
  33. package/dist/ui/EditorContainer.d.ts +1 -1
  34. package/dist/ui/EditorContainer.d.ts.map +1 -1
  35. package/dist/ui/EditorContainer.js +2 -1
  36. package/package.json +9 -1
  37. package/dist/core/diagnostics/index.d.ts.map +0 -1
  38. package/dist/core/diagnostics/jsonDiagnostics.d.ts.map +0 -1
  39. package/dist/core/diagnostics/jsonDiagnostics.js +0 -78
  40. /package/dist/core/diagnostics/{index.d.ts → json/index.d.ts} +0 -0
  41. /package/dist/core/diagnostics/{index.js → json/index.js} +0 -0
package/README.md CHANGED
@@ -1,6 +1,10 @@
1
+ ![npm](https://img.shields.io/npm/v/react-code-editor)
2
+ ![downloads](https://img.shields.io/npm/dw/react-code-editor)
3
+ ![license](https://img.shields.io/npm/l/react-code-editor)
4
+
1
5
  # React Code Editor
2
6
 
3
- A modern, extensible **CodeMirror 6–based React code editor** featuring first-class TypeScript support, language-aware configuration, and optional diagnostics.
7
+ A modern, extensible **CodeMirror 6–based React code editor** featuring first-class TypeScript support, language-aware configuration, optional diagnostics, and search/validation support.
4
8
 
5
9
  This library is designed to scale from a simple embedded editor to a **multi-language, schema-aware editing platform**.
6
10
 
@@ -14,6 +18,8 @@ This library is designed to scale from a simple embedded editor to a **multi-lan
14
18
  - Optional diagnostics, completion, and hover
15
19
  - JSON Schema validation support
16
20
  - Light & dark themes
21
+ - Search & Replace support
22
+ - Validation state callback
17
23
  - Designed for future multi-language support
18
24
 
19
25
  ---
@@ -76,6 +82,140 @@ const [value, setValue] = useState('{}');
76
82
 
77
83
  ---
78
84
 
85
+ ## 🎮 Editor Controller API
86
+
87
+ The editor exposes a controller API that allows you to trigger actions programmatically.
88
+
89
+ ### ⚠️ Important design choice
90
+
91
+ This library does **not** impose formatting logic.
92
+ Instead, you **pass a callback function** that receives the current editor value and returns the formatted result.
93
+
94
+ This keeps the editor **language-agnostic** and flexible.
95
+
96
+ ### Available Controller Actions
97
+
98
+ - `copy()`
99
+ - `format(formatter)`
100
+ - `foldAll()`
101
+ - `unfoldAll()`
102
+ - `openSearch()`
103
+ - `closeSearch()`
104
+ - `findNext()`
105
+ - `findPrev()`
106
+ - `replace(replacement: string)`
107
+ - `replaceAll(replacement: string)`
108
+
109
+ ### 🧠 Format API (Callback-Based)
110
+
111
+ ```tsx
112
+ format(formatter: (value: string) => string): void
113
+ ```
114
+
115
+ - The editor passes the **current content**
116
+ - Your formatter returns the **new formatted content**
117
+ - The editor updates itself with the returned value
118
+
119
+ ### Example
120
+
121
+ ```tsx
122
+ import { useRef } from 'react';
123
+ import type { EditorController } from 'react-codemirror-editor';
124
+
125
+ const controllerRef = useRef<EditorController | null>(null);
126
+
127
+ <CodeEditor
128
+ language="json"
129
+ controllerRef={controllerRef}
130
+ />;
131
+
132
+ function formatJson(value: string) {
133
+ try {
134
+ return JSON.stringify(JSON.parse(value), null, 2);
135
+ } catch {
136
+ return value;
137
+ }
138
+ }
139
+
140
+ <button onClick={() => controllerRef.current?.format(formatJson)}>Format</button>
141
+ <button onClick={() => controllerRef.current?.copy()}>Copy</button>
142
+ <button onClick={() => controllerRef.current?.foldAll()}>Fold All</button>
143
+ <button onClick={() => controllerRef.current?.unfoldAll()}>Unfold All</button>
144
+ <button onClick={() => controllerRef.current?.openSearch()}>Search</button>
145
+ <button onClick={() => controllerRef.current?.closeSearch()}>Close Search</button>
146
+ ```
147
+
148
+ - Works for **any language**
149
+ - Supports **custom formatter functions**
150
+ - Search UI is **optional** and can be enabled via props
151
+
152
+ ### Example: Prettier Integration (Concept)
153
+
154
+ ```tsx
155
+ controllerRef.current?.format((code) =>
156
+ prettier.format(code, { parser: 'json' }),
157
+ );
158
+ ```
159
+
160
+ ---
161
+
162
+ ## 📋 Why Callback-Based Formatting?
163
+
164
+ - Keeps core editor **small**
165
+ - Avoids hard dependency on Prettier
166
+ - Supports **any language**
167
+ - Lets consumers decide formatting rules
168
+
169
+ This is a library-level design decision, not a limitation.
170
+
171
+ ---
172
+
173
+ ## 🔍 Search & Replace
174
+
175
+ The editor includes **search & replace functionality** via a controller API:
176
+
177
+ - `openSearch()` – Opens the search panel
178
+ - `closeSearch()` – Closes the search panel
179
+ - `findNext()` – Finds the next match
180
+ - `findPrev()` – Finds the previous match
181
+ - `replace(replacement: string)` – Replaces the current match
182
+ - `replaceAll(replacement: string)` – Replaces all matches
183
+
184
+ You can pass **search configuration**:
185
+
186
+ ```tsx
187
+ <CodeEditor
188
+ language="json"
189
+ searchOptions={{
190
+ top: true,
191
+ caseSensitive: false,
192
+ }}
193
+ />
194
+ ```
195
+
196
+ ---
197
+
198
+ ## ✅ JSON Validation State
199
+
200
+ You can track JSON validity and react to changes in real-time via `onValidationChange`:
201
+
202
+ ```tsx
203
+ <CodeEditor
204
+ language="json"
205
+ languageOptions={{
206
+ json: {
207
+ schema: myJsonSchema,
208
+ onValidationChange: (isValid) => console.log('Valid:', isValid),
209
+ },
210
+ }}
211
+ />
212
+ ```
213
+
214
+ - `isValid` is `true` if there are no syntax or schema errors
215
+ - Useful for enabling/disabling Save buttons or warnings in your UI
216
+
217
+ ---
218
+
79
219
  ## 🌍 Languages
80
220
 
81
221
  Languages are enabled explicitly using the `language` prop.
@@ -84,7 +224,7 @@ Languages are enabled explicitly using the `language` prop.
84
224
 
85
225
  - **JSON**
86
226
 
87
- The architecture is designed to support additional languages such as:
227
+ Future support for:
88
228
 
89
229
  - JavaScript
90
230
  - TypeScript
@@ -97,8 +237,6 @@ The architecture is designed to support additional languages such as:
97
237
 
98
238
  Language-specific behavior is configured via `languageOptions`.
99
239
 
100
- ### JSON Configuration Example
101
-
102
240
  ```tsx
103
241
  <CodeEditor
104
242
  language="json"
@@ -113,16 +251,17 @@ Language-specific behavior is configured via `languageOptions`.
113
251
  />
114
252
  ```
115
253
 
116
- ---
117
-
118
254
  ### JSON Options
119
255
 
120
- | Option | Description | Default |
121
- | ------------- | ---------------------------------- | ----------- |
122
- | **`schema`** | JSON Schema object for validation | `undefined` |
123
- | **`diagnostics`** | Enable JSON linting | `true` |
124
- | **`completion`** | Enable schema-based autocompletion | `true` |
125
- | **`hover`** | Enable schema hover tooltips | `true` |
256
+ | Option | Type | Default | Description |
257
+ | -------------------- | ---------------------------- | ------------------------- | ------------------------------------------------------ |
258
+ | `schema` | `object` | `undefined` | JSON Schema used for validation, completion, and hover |
259
+ | `diagnostics` | `boolean` | `true` | Enables JSON syntax diagnostics |
260
+ | `gutter` | `boolean` | `true` | Shows the diagnostics gutter (error markers) |
261
+ | `schemaLint` | `boolean` | `true if schema provided` | Enables schema-based validation |
262
+ | `hover` | `boolean` | `true if schema provided` | Enables hover tooltips from schema |
263
+ | `autocomplete` | `boolean` | `true if schema provided` | Enables schema-based autocompletion |
264
+ | `onValidationChange` | `(isValid: boolean) => void` | `undefined` | Callback called whenever JSON validity changes |
126
265
 
127
266
  > If no schema is provided, the editor still works normally with **syntax diagnostics only**.
128
267
 
@@ -132,12 +271,12 @@ Language-specific behavior is configured via `languageOptions`.
132
271
 
133
272
  Diagnostics are **configurable per language**.
134
273
 
135
- ### JSON diagnostics include:
274
+ ### JSON diagnostics include
136
275
 
137
276
  - Syntax errors
138
277
  - Schema validation errors (when schema is provided)
139
278
 
140
- You may disable diagnostics entirely:
279
+ Disable diagnostics:
141
280
 
142
281
  ```tsx
143
282
  languageOptions={{
@@ -187,7 +326,7 @@ To ensure a consistent height, define a height or `min-height` via CSS.
187
326
 
188
327
  - The editor always fills the container height
189
328
  - Padding, borders, and background should be applied to the container
190
- - This approach provides full control over responsive layouts
329
+ - Provides full control over responsive layouts
191
330
 
192
331
  ---
193
332
 
@@ -232,7 +371,7 @@ import type { ThemeName } from 'react-codemirror-editor';
232
371
 
233
372
  - Built on **CodeMirror 6**
234
373
  - Language features are isolated and composable
235
- - Diagnostics, completion, and hover are opt-in
374
+ - Diagnostics, completion, hover, and search are opt-in
236
375
  - Clean separation between core editor, languages, and UI
237
376
  - Designed for long-term multi-language expansion
238
377
 
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/diagnostics/json/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,4 +1,4 @@
1
1
  import { Extension } from '@codemirror/state';
2
- import { JsonEditorConfig } from '../../types';
2
+ import { JsonEditorConfig } from '../../../types';
3
3
  export declare const jsonDiagnosticsExtension: (options?: JsonEditorConfig) => Extension;
4
4
  //# sourceMappingURL=jsonDiagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonDiagnostics.d.ts","sourceRoot":"","sources":["../../../../src/core/diagnostics/json/jsonDiagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAa9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,eAAO,MAAM,wBAAwB,aACxB,gBAAgB,KAC1B,SA4CF,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { hoverTooltip } from '@codemirror/view';
2
+ import { linter, lintGutter } from '@codemirror/lint';
3
+ import { autocompletion } from '@codemirror/autocomplete';
4
+ import { jsonSchemaLinter, jsonSchemaHover, stateExtensions, } from 'codemirror-json-schema';
5
+ import { validation } from './jsonValidation';
6
+ import { jsonLinter } from './jsonLinter';
7
+ import { safeJsonCompletion } from './safeJsonCompletion';
8
+ export const jsonDiagnosticsExtension = (options = {}) => {
9
+ const { diagnostics = true, gutter = true, schema, schemaLint = !!schema, hover = !!schema, autocomplete = !!schema, onValidationChange, } = options;
10
+ const extensions = [];
11
+ if (diagnostics) {
12
+ extensions.push(linter(validation(jsonLinter, onValidationChange)));
13
+ if (gutter) {
14
+ extensions.push(lintGutter());
15
+ }
16
+ }
17
+ if (schema) {
18
+ extensions.push(stateExtensions(schema));
19
+ if (schemaLint) {
20
+ extensions.push(linter(validation(jsonSchemaLinter(schema), onValidationChange)));
21
+ }
22
+ if (hover) {
23
+ extensions.push(hoverTooltip(jsonSchemaHover(schema)));
24
+ }
25
+ if (autocomplete) {
26
+ extensions.push(autocompletion({
27
+ override: [safeJsonCompletion(schema)],
28
+ }));
29
+ }
30
+ }
31
+ return extensions;
32
+ };
@@ -0,0 +1,4 @@
1
+ import { EditorView } from '@codemirror/view';
2
+ import { Diagnostic } from '@codemirror/lint';
3
+ export declare const jsonLinter: (view: EditorView) => Diagnostic[];
4
+ //# sourceMappingURL=jsonLinter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonLinter.d.ts","sourceRoot":"","sources":["../../../../src/core/diagnostics/json/jsonLinter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA+B9C,eAAO,MAAM,UAAU,SAAU,UAAU,KAAG,UAAU,EAsBvD,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { syntaxTree } from '@codemirror/language';
2
+ const getErrorMessage = (view, from) => {
3
+ const doc = view.state.doc;
4
+ const charBefore = from > 0 ? doc.sliceString(from - 1, from) : '';
5
+ const charAfter = doc.sliceString(from, from + 1);
6
+ if (charBefore === ',') {
7
+ return 'Trailing comma is not allowed in JSON';
8
+ }
9
+ if (charAfter === '}' || charAfter === ']') {
10
+ return 'Missing value before closing bracket';
11
+ }
12
+ if (charAfter === ':') {
13
+ return 'Missing value after ":"';
14
+ }
15
+ if (charBefore === ':') {
16
+ return 'Missing value after ":"';
17
+ }
18
+ if (!charAfter) {
19
+ return 'Unexpected end of JSON input';
20
+ }
21
+ return 'Invalid JSON syntax';
22
+ };
23
+ export const jsonLinter = (view) => {
24
+ const diagnostics = [];
25
+ const tree = syntaxTree(view.state);
26
+ const docLength = view.state.doc.length;
27
+ tree.iterate({
28
+ enter(node) {
29
+ if (!node.type.isError)
30
+ return;
31
+ const from = node.from;
32
+ const to = Math.min(node.to, docLength);
33
+ diagnostics.push({
34
+ from,
35
+ to: from === to ? from + 1 : to,
36
+ severity: 'error',
37
+ message: getErrorMessage(view, from),
38
+ });
39
+ },
40
+ });
41
+ return diagnostics;
42
+ };
@@ -0,0 +1,4 @@
1
+ import { EditorView } from '@codemirror/view';
2
+ import { Diagnostic } from '@codemirror/lint';
3
+ export declare const validation: (linterFn: (view: EditorView) => Diagnostic[], onValidationChange?: (isValid: boolean) => void) => (view: EditorView) => Diagnostic[];
4
+ //# sourceMappingURL=jsonValidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonValidation.d.ts","sourceRoot":"","sources":["../../../../src/core/diagnostics/json/jsonValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,UAAU,aAEL,CAAC,IAAI,EAAE,UAAU,KAAK,UAAU,EAAE,uBACvB,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,YAE5C,UAAU,KAAG,UAAU,EAS7B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export const validation = (linterFn, onValidationChange) => (view) => {
2
+ const diagnostics = linterFn(view);
3
+ if (onValidationChange) {
4
+ const isValid = diagnostics.every((d) => d.severity !== 'error');
5
+ onValidationChange(isValid);
6
+ }
7
+ return diagnostics;
8
+ };
@@ -0,0 +1,3 @@
1
+ import { CompletionContext, CompletionResult } from '@codemirror/autocomplete';
2
+ export declare const safeJsonCompletion: (schema: Record<string, any>) => (ctx: CompletionContext) => CompletionResult | null;
3
+ //# sourceMappingURL=safeJsonCompletion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safeJsonCompletion.d.ts","sourceRoot":"","sources":["../../../../src/core/diagnostics/json/safeJsonCompletion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG/E,eAAO,MAAM,kBAAkB,WAAY,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,WAG7C,iBAAiB,KAAG,gBAAgB,GAAG,IAIvD,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsonCompletion } from 'codemirror-json-schema';
2
+ export const safeJsonCompletion = (schema) => {
3
+ const source = jsonCompletion(schema);
4
+ return (ctx) => {
5
+ const result = source(ctx);
6
+ return Array.isArray(result) ? null : result;
7
+ };
8
+ };
@@ -1,4 +1,4 @@
1
1
  import { EditorView } from '@codemirror/view';
2
2
  import { CreateEditorOptions } from '../../types';
3
- export declare const createEditor: ({ value, parent, theme, readOnly, language, languageOptions, onChange, }: CreateEditorOptions) => EditorView;
3
+ export declare const createEditor: ({ value, parent, theme, readOnly, language, languageOptions, search, onChange, }: CreateEditorOptions) => EditorView;
4
4
  //# sourceMappingURL=createEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createEditor.d.ts","sourceRoot":"","sources":["../../../src/core/editor/createEditor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAM9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,eAAO,MAAM,YAAY,6EAQtB,mBAAmB,eAoBrB,CAAC"}
1
+ {"version":3,"file":"createEditor.d.ts","sourceRoot":"","sources":["../../../src/core/editor/createEditor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAM9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,eAAO,MAAM,YAAY,qFAStB,mBAAmB,eAqBrB,CAAC"}
@@ -1,10 +1,10 @@
1
1
  import { EditorState } from '@codemirror/state';
2
2
  import { EditorView } from '@codemirror/view';
3
3
  import { basicSetup } from 'codemirror';
4
- import { readOnlyExtension } from '../extensions';
4
+ import { readOnlyExtension, searchExtensions } from '../extensions';
5
5
  import { buildLanguageExtensions } from '../languages';
6
6
  import { getThemeExtension } from '../themes';
7
- export const createEditor = ({ value, parent, theme, readOnly = false, language, languageOptions, onChange, }) => {
7
+ export const createEditor = ({ value, parent, theme, readOnly = false, language, languageOptions, search, onChange, }) => {
8
8
  const state = EditorState.create({
9
9
  doc: value,
10
10
  extensions: [
@@ -12,6 +12,7 @@ export const createEditor = ({ value, parent, theme, readOnly = false, language,
12
12
  ...buildLanguageExtensions(language, languageOptions),
13
13
  getThemeExtension(theme),
14
14
  readOnlyExtension(readOnly),
15
+ searchExtensions(search),
15
16
  EditorView.updateListener.of((update) => {
16
17
  if (update.docChanged) {
17
18
  onChange?.(update.state.doc.toString());
@@ -1 +1 @@
1
- {"version":3,"file":"editorController.d.ts","sourceRoot":"","sources":["../../../src/core/editor/editorController.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,wBAAgB,sBAAsB,IAAI,gBAAgB,CAuBzD"}
1
+ {"version":3,"file":"editorController.d.ts","sourceRoot":"","sources":["../../../src/core/editor/editorController.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,wBAAgB,sBAAsB,IAAI,gBAAgB,CAyCzD"}
@@ -1,4 +1,4 @@
1
- import { copyToClipboard, foldAllCode, unfoldAllCode, formatCode, } from '../extensions';
1
+ import { copyToClipboard, foldAllCode, unfoldAllCode, formatCode, openSearch, closeSearch, replace, replaceAllOccurrences, searchNext, searchPrevious, } from '../extensions';
2
2
  export function createEditorController() {
3
3
  let view = null;
4
4
  return {
@@ -20,5 +20,23 @@ export function createEditorController() {
20
20
  format(formatter) {
21
21
  return formatCode(view, formatter);
22
22
  },
23
+ openSearch() {
24
+ openSearch(view);
25
+ },
26
+ closeSearch() {
27
+ closeSearch(view);
28
+ },
29
+ searchNext() {
30
+ searchNext(view);
31
+ },
32
+ searchPrevious() {
33
+ searchPrevious(view);
34
+ },
35
+ replace() {
36
+ replace(view);
37
+ },
38
+ replaceAll() {
39
+ replaceAllOccurrences(view);
40
+ },
23
41
  };
24
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/fold.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,eAAO,MAAM,WAAW,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,YAI9D,CAAC;AAEF,eAAO,MAAM,aAAa,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,YAIhE,CAAC"}
1
+ {"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/fold.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AASnD,eAAO,MAAM,WAAW,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,YAmB9D,CAAC;AAEF,eAAO,MAAM,aAAa,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,YAIhE,CAAC"}
@@ -1,8 +1,20 @@
1
- import { foldAll, unfoldAll } from '@codemirror/language';
1
+ import { syntaxTree, foldable, foldEffect, unfoldAll, } from '@codemirror/language';
2
2
  export const foldAllCode = (view) => {
3
3
  if (!view)
4
4
  return false;
5
- return foldAll(view);
5
+ const effects = [];
6
+ syntaxTree(view.state).iterate({
7
+ enter(node) {
8
+ const range = foldable(view.state, node.from, node.to);
9
+ if (range) {
10
+ effects.push(foldEffect.of(range));
11
+ }
12
+ },
13
+ });
14
+ if (!effects.length)
15
+ return false;
16
+ view.dispatch({ effects });
17
+ return true;
6
18
  };
7
19
  export const unfoldAllCode = (view) => {
8
20
  if (!view)
@@ -2,4 +2,5 @@ export { copyToClipboard } from './copy';
2
2
  export { foldAllCode, unfoldAllCode } from './fold';
3
3
  export { formatCode } from './format';
4
4
  export { readOnlyExtension } from './readOnly';
5
+ export { openSearch, closeSearch, searchExtensions, searchNext, searchPrevious, replace, replaceAllOccurrences, } from './search';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EACH,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,OAAO,EACP,qBAAqB,GACxB,MAAM,UAAU,CAAC"}
@@ -2,3 +2,4 @@ export { copyToClipboard } from './copy';
2
2
  export { foldAllCode, unfoldAllCode } from './fold';
3
3
  export { formatCode } from './format';
4
4
  export { readOnlyExtension } from './readOnly';
5
+ export { openSearch, closeSearch, searchExtensions, searchNext, searchPrevious, replace, replaceAllOccurrences, } from './search';
@@ -0,0 +1,11 @@
1
+ import type { EditorView } from '@codemirror/view';
2
+ import { Extension } from '@codemirror/state';
3
+ import { SearchOptions } from '../../types';
4
+ export declare const openSearch: (view: EditorView | null | undefined) => void;
5
+ export declare const closeSearch: (view: EditorView | null | undefined) => void;
6
+ export declare const searchNext: (view: EditorView | null | undefined) => void;
7
+ export declare const searchPrevious: (view: EditorView | null | undefined) => void;
8
+ export declare const replace: (view: EditorView | null | undefined) => void;
9
+ export declare const replaceAllOccurrences: (view: EditorView | null | undefined) => void;
10
+ export declare const searchExtensions: (searchConfig?: boolean | SearchOptions) => Extension;
11
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAUnD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,UAAU,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,SAI7D,CAAC;AAEF,eAAO,MAAM,WAAW,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,SAI9D,CAAC;AAEF,eAAO,MAAM,UAAU,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,SAI7D,CAAC;AAEF,eAAO,MAAM,cAAc,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,SAIjE,CAAC;AAEF,eAAO,MAAM,OAAO,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,SAI1D,CAAC;AAEF,eAAO,MAAM,qBAAqB,SAAU,UAAU,GAAG,IAAI,GAAG,SAAS,SAIxE,CAAC;AAeF,eAAO,MAAM,gBAAgB,kBACX,OAAO,GAAG,aAAa,KACtC,SAkBF,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { openSearchPanel, closeSearchPanel, search, findPrevious, findNext, replaceNext, replaceAll, } from '@codemirror/search';
2
+ export const openSearch = (view) => {
3
+ if (!view)
4
+ return;
5
+ openSearchPanel(view);
6
+ };
7
+ export const closeSearch = (view) => {
8
+ if (!view)
9
+ return;
10
+ closeSearchPanel(view);
11
+ };
12
+ export const searchNext = (view) => {
13
+ if (!view)
14
+ return;
15
+ findNext(view);
16
+ };
17
+ export const searchPrevious = (view) => {
18
+ if (!view)
19
+ return;
20
+ findPrevious(view);
21
+ };
22
+ export const replace = (view) => {
23
+ if (!view)
24
+ return;
25
+ replaceNext(view);
26
+ };
27
+ export const replaceAllOccurrences = (view) => {
28
+ if (!view)
29
+ return;
30
+ replaceAll(view);
31
+ };
32
+ const resolveSearch = (search) => {
33
+ if (!search)
34
+ return { enabled: false };
35
+ if (search === true) {
36
+ return { enabled: true };
37
+ }
38
+ return {
39
+ enabled: search.enabled ?? true,
40
+ ...search,
41
+ };
42
+ };
43
+ export const searchExtensions = (searchConfig = {}) => {
44
+ const options = resolveSearch(searchConfig);
45
+ if (!options.enabled)
46
+ return [];
47
+ const { top = true, caseSensitive = false, regexp = false, wholeWord = false, } = options ?? {};
48
+ return search({
49
+ top,
50
+ caseSensitive,
51
+ regexp,
52
+ wholeWord,
53
+ });
54
+ };
@@ -1,5 +1,5 @@
1
1
  import { jsonLanguage } from '.';
2
- import { jsonDiagnosticsExtension } from '../diagnostics';
2
+ import { jsonDiagnosticsExtension } from '../diagnostics/json';
3
3
  export const buildLanguageExtensions = (language, options) => {
4
4
  switch (language) {
5
5
  case 'json':
@@ -11,6 +11,12 @@ export interface EditorController {
11
11
  foldAll(): boolean;
12
12
  unfoldAll(): boolean;
13
13
  format(formatter: (code: string) => string): boolean;
14
+ openSearch(): void;
15
+ closeSearch(): void;
16
+ searchNext(): void;
17
+ searchPrevious(): void;
18
+ replace(): void;
19
+ replaceAll(): void;
14
20
  }
15
21
  export interface CreateEditorOptions {
16
22
  parent: HTMLElement;
@@ -19,6 +25,7 @@ export interface CreateEditorOptions {
19
25
  readOnly?: boolean;
20
26
  language: EditorLanguage;
21
27
  languageOptions?: LanguageOptions;
28
+ search?: boolean | SearchOptions;
22
29
  onChange?: (value: string) => void;
23
30
  }
24
31
  export interface EditorContainerProps {
@@ -28,6 +35,7 @@ export interface EditorContainerProps {
28
35
  readOnly?: boolean;
29
36
  language: EditorLanguage;
30
37
  languageOptions?: LanguageOptions;
38
+ search?: boolean | SearchOptions;
31
39
  onChange?: (value: string) => void;
32
40
  }
33
41
  interface BaseCodeEditorProps {
@@ -35,6 +43,7 @@ interface BaseCodeEditorProps {
35
43
  readOnly?: boolean;
36
44
  language: EditorLanguage;
37
45
  languageOptions?: LanguageOptions;
46
+ search?: boolean | SearchOptions;
38
47
  onReady?: (controller: EditorController) => void;
39
48
  }
40
49
  interface ControlledCodeEditorProps {
@@ -59,6 +68,14 @@ export interface JsonEditorConfig {
59
68
  schemaLint?: boolean;
60
69
  hover?: boolean;
61
70
  autocomplete?: boolean;
71
+ onValidationChange?: (isValid: boolean) => void;
72
+ }
73
+ export interface SearchOptions {
74
+ enabled?: boolean;
75
+ top?: boolean;
76
+ caseSensitive?: boolean;
77
+ regexp?: boolean;
78
+ wholeWord?: boolean;
62
79
  }
63
80
  export {};
64
81
  //# sourceMappingURL=editor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/types/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,MAAM,SAAS,GACf,OAAO,GACP,MAAM,GACN,WAAW,GACX,cAAc,GACd,gBAAgB,GAChB,oBAAoB,GACpB,sBAAsB,GACtB,eAAe,GACf,gBAAgB,GAChB,WAAW,GACX,aAAa,GACb,gBAAgB,GAChB,cAAc,CAAC;AAErB,MAAM,MAAM,cAAc,GAAG,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC5B,IAAI,CAAC,EAAE,gBAAgB,CAAC;CAQ3B;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,IAAI,UAAU,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;IACvC,IAAI,IAAI,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IACrC,OAAO,IAAI,OAAO,CAAC;IACnB,SAAS,IAAI,OAAO,CAAC;IACrB,MAAM,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC;CACxD;AAED,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,oBAAoB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,gBAAgB,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,UAAU,mBAAmB;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACpD;AAED,UAAU,yBAAyB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,YAAY,CAAC,EAAE,KAAK,CAAC;CACxB;AAED,UAAU,2BAA2B;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC;CACpB;AAED,MAAM,MAAM,eAAe,GACrB,CAAC,mBAAmB,GAAG,yBAAyB,CAAC,GACjD,CAAC,mBAAmB,GAAG,2BAA2B,CAAC,CAAC;AAE1D,MAAM,WAAW,2BAA2B;IACxC,IAAI,EAAE,YAAY,GAAG,cAAc,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/types/editor.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../src/ui/CodeEditor.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAkChD,CAAC"}
1
+ {"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../src/ui/CodeEditor.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0ChD,CAAC"}
@@ -4,7 +4,7 @@ import { createEditorController } from '../core/editor';
4
4
  import { resolveControlledInvariant } from '../core/invariants';
5
5
  import { EditorContainer } from './';
6
6
  export const CodeEditor = (props) => {
7
- const { theme, readOnly, language, languageOptions, onChange, onReady } = props;
7
+ const { theme, readOnly, language, languageOptions, search, onChange, onReady, } = props;
8
8
  const { mode, value: resolvedContent } = resolveControlledInvariant(props);
9
9
  const [internalContent, setInternalContent] = useState(resolvedContent);
10
10
  const controller = useMemo(() => createEditorController(), []);
@@ -17,5 +17,5 @@ export const CodeEditor = (props) => {
17
17
  useEffect(() => {
18
18
  onReady?.(controller);
19
19
  }, [controller, onReady]);
20
- return (_jsx(EditorContainer, { value: mode === 'controlled' ? resolvedContent : internalContent, theme: theme, readOnly: readOnly, language: language, languageOptions: languageOptions, onChange: handleEditorChange, controller: controller }));
20
+ return (_jsx(EditorContainer, { value: mode === 'controlled' ? resolvedContent : internalContent, theme: theme, readOnly: readOnly, language: language, languageOptions: languageOptions, search: search, onChange: handleEditorChange, controller: controller }));
21
21
  };
@@ -1,3 +1,3 @@
1
1
  import { EditorContainerProps } from '../types';
2
- export declare const EditorContainer: ({ value, theme, readOnly, language, languageOptions, controller, onChange, }: EditorContainerProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const EditorContainer: ({ value, theme, readOnly, language, languageOptions, search, controller, onChange, }: EditorContainerProps) => import("react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=EditorContainer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditorContainer.d.ts","sourceRoot":"","sources":["../../src/ui/EditorContainer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,eAAO,MAAM,eAAe,iFAQzB,oBAAoB,4CA0CtB,CAAC"}
1
+ {"version":3,"file":"EditorContainer.d.ts","sourceRoot":"","sources":["../../src/ui/EditorContainer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD,eAAO,MAAM,eAAe,yFASzB,oBAAoB,4CA2CtB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useRef } from 'react';
3
3
  import { createEditor } from '../core/editor';
4
- export const EditorContainer = ({ value, theme, readOnly, language, languageOptions, controller, onChange, }) => {
4
+ export const EditorContainer = ({ value, theme, readOnly, language, languageOptions, search, controller, onChange, }) => {
5
5
  const editorRef = useRef(null);
6
6
  useEffect(() => {
7
7
  const editor = editorRef.current;
@@ -14,6 +14,7 @@ export const EditorContainer = ({ value, theme, readOnly, language, languageOpti
14
14
  readOnly,
15
15
  language,
16
16
  languageOptions,
17
+ search,
17
18
  onChange,
18
19
  });
19
20
  controller.setView(view);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-codemirror-editor",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "private": false,
5
5
  "description": "A modular, extensible React code editor built on CodeMirror 6 with first-class JSON support.",
6
6
  "type": "module",
@@ -11,6 +11,14 @@
11
11
  "dist"
12
12
  ],
13
13
  "sideEffects": false,
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/mihirmistry2/react-code-editor.git"
17
+ },
18
+ "homepage": "https://github.com/mihirmistry2/react-code-editor#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/mihirmistry2/react-code-editor/issues"
21
+ },
14
22
  "scripts": {
15
23
  "build": "tsc",
16
24
  "lint": "eslint .",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/diagnostics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsonDiagnostics.d.ts","sourceRoot":"","sources":["../../../src/core/diagnostics/jsonDiagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAS9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAsE/C,eAAO,MAAM,wBAAwB,aACxB,gBAAgB,KAC1B,SAuCF,CAAC"}
@@ -1,78 +0,0 @@
1
- import { hoverTooltip } from '@codemirror/view';
2
- import { linter, lintGutter } from '@codemirror/lint';
3
- import { autocompletion, } from '@codemirror/autocomplete';
4
- import { syntaxTree } from '@codemirror/language';
5
- import { jsonSchemaLinter, jsonSchemaHover, jsonCompletion, stateExtensions, } from 'codemirror-json-schema';
6
- const getErrorMessage = (view, from) => {
7
- const doc = view.state.doc;
8
- const charBefore = from > 0 ? doc.sliceString(from - 1, from) : '';
9
- const charAfter = doc.sliceString(from, from + 1);
10
- if (charBefore === ',') {
11
- return 'Trailing comma is not allowed in JSON';
12
- }
13
- if (charAfter === '}' || charAfter === ']') {
14
- return 'Missing value before closing bracket';
15
- }
16
- if (charAfter === ':') {
17
- return 'Missing value after ":"';
18
- }
19
- if (charBefore === ':') {
20
- return 'Missing value after ":"';
21
- }
22
- if (!charAfter) {
23
- return 'Unexpected end of JSON input';
24
- }
25
- return 'Invalid JSON syntax';
26
- };
27
- const jsonLinter = (view) => {
28
- const diagnostics = [];
29
- const tree = syntaxTree(view.state);
30
- const docLength = view.state.doc.length;
31
- tree.iterate({
32
- enter(node) {
33
- if (!node.type.isError)
34
- return;
35
- const from = node.from;
36
- const to = Math.min(node.to, docLength);
37
- diagnostics.push({
38
- from,
39
- to: from === to ? from + 1 : to,
40
- severity: 'error',
41
- message: getErrorMessage(view, from),
42
- });
43
- },
44
- });
45
- return diagnostics;
46
- };
47
- const safeJsonCompletion = (schema) => {
48
- const source = jsonCompletion(schema);
49
- return (ctx) => {
50
- const result = source(ctx);
51
- return Array.isArray(result) ? null : result;
52
- };
53
- };
54
- export const jsonDiagnosticsExtension = (options = {}) => {
55
- const { diagnostics = true, gutter = true, schema, schemaLint = !!schema, hover = !!schema, autocomplete = !!schema, } = options;
56
- const extensions = [];
57
- if (diagnostics) {
58
- extensions.push(linter(jsonLinter));
59
- if (gutter) {
60
- extensions.push(lintGutter());
61
- }
62
- }
63
- if (schema) {
64
- extensions.push(stateExtensions(schema));
65
- if (schemaLint) {
66
- extensions.push(linter(jsonSchemaLinter(schema)));
67
- }
68
- if (hover) {
69
- extensions.push(hoverTooltip(jsonSchemaHover(schema)));
70
- }
71
- if (autocomplete) {
72
- extensions.push(autocompletion({
73
- override: [safeJsonCompletion(schema)],
74
- }));
75
- }
76
- }
77
- return extensions;
78
- };