@scalar/use-codemirror 0.11.101 → 0.11.103

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.
@@ -1,329 +1,363 @@
1
- import { autocompletion, completionKeymap, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
2
- import { history, historyKeymap, indentWithTab, insertNewline } from '@codemirror/commands';
3
- import { css } from '@codemirror/lang-css';
4
- import { html } from '@codemirror/lang-html';
5
- import { json } from '@codemirror/lang-json';
6
- import { xml } from '@codemirror/lang-xml';
7
- import { yaml } from '@codemirror/lang-yaml';
8
- import { syntaxHighlighting, defaultHighlightStyle, indentOnInput, bracketMatching, foldGutter } from '@codemirror/language';
9
- import { linter } from '@codemirror/lint';
10
- import { StateEffect } from '@codemirror/state';
11
- import { EditorView, highlightSpecialChars, keymap, placeholder, lineNumbers } from '@codemirror/view';
12
- import { ScalarIcon } from '@scalar/components';
13
- import { ref, computed, toValue, watch, onBeforeUnmount, h, render } from 'vue';
14
- import { customTheme } from '../themes/index.js';
15
- import { variables } from './variables.js';
16
-
17
- /** Check if the hook has a provider. In provider mode we ignore the content variable */
18
- const hasProvider = (params) => 'provider' in params && !!toValue(params.provider);
1
+ import { autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap } from "@codemirror/autocomplete";
2
+ import { indentWithTab, insertNewline } from "@codemirror/commands";
3
+ import { css } from "@codemirror/lang-css";
4
+ import { html } from "@codemirror/lang-html";
5
+ import { json } from "@codemirror/lang-json";
6
+ import { xml } from "@codemirror/lang-xml";
7
+ import { yaml } from "@codemirror/lang-yaml";
8
+ import {
9
+ bracketMatching,
10
+ defaultHighlightStyle,
11
+ foldGutter,
12
+ indentOnInput,
13
+ syntaxHighlighting
14
+ } from "@codemirror/language";
15
+ import { linter } from "@codemirror/lint";
16
+ import { StateEffect } from "@codemirror/state";
17
+ import {
18
+ EditorView,
19
+ highlightSpecialChars,
20
+ keymap,
21
+ lineNumbers as lineNumbersExtension,
22
+ placeholder as placeholderExtension
23
+ } from "@codemirror/view";
24
+ import { history, historyKeymap } from "@codemirror/commands";
25
+ import { ScalarIcon } from "@scalar/components";
26
+ import { computed, h, onBeforeUnmount, ref, render, toValue, watch } from "vue";
27
+ import { customTheme } from "../themes/index.js";
28
+ import { variables } from "./variables.js";
29
+ const hasProvider = (params) => "provider" in params && !!toValue(params.provider);
19
30
  const selectAllKeyBinding = {
20
- key: 'Mod-a',
21
- run: (view) => {
22
- // Select the entire content
23
- view.dispatch({
24
- selection: { anchor: 0, head: view.state.doc.length },
25
- scrollIntoView: false,
26
- });
27
- return true;
28
- },
31
+ key: "Mod-a",
32
+ run: (view) => {
33
+ view.dispatch({
34
+ selection: { anchor: 0, head: view.state.doc.length },
35
+ scrollIntoView: false
36
+ });
37
+ return true;
38
+ }
29
39
  };
30
- /** Reactive CodeMirror Integration */
31
40
  const useCodeMirror = (params) => {
32
- const codeMirror = ref(null);
33
- /** Set the codemirror content value */
34
- const setCodeMirrorContent = (newValue = '') => {
35
- if (!codeMirror.value) {
36
- return;
37
- }
38
- // No need to set the CodeMirror content if nothing has changed
39
- if (codeMirror.value.state.doc.toString() === newValue) {
40
- return;
41
- }
42
- codeMirror.value.dispatch({
43
- changes: {
44
- from: 0,
45
- to: codeMirror.value.state.doc.length,
46
- insert: newValue,
47
- },
48
- selection: {
49
- anchor: Math.min(codeMirror.value.state.selection.main.anchor, newValue.length),
50
- },
51
- });
52
- };
53
- // All options except provider
54
- const extensionConfig = computed(() => ({
55
- onChange: params.onChange,
56
- onBlur: params.onBlur,
57
- onFocus: params.onFocus,
58
- disableTabIndent: toValue(params.disableTabIndent),
59
- language: toValue(params.language),
60
- classes: toValue(params.classes),
61
- readOnly: toValue(params.readOnly),
62
- lineNumbers: toValue(params.lineNumbers),
63
- withVariables: toValue(params.withVariables),
64
- forceFoldGutter: toValue(params.forceFoldGutter),
65
- disableEnter: toValue(params.disableEnter),
66
- disableCloseBrackets: toValue(params.disableCloseBrackets),
67
- withoutTheme: toValue(params.withoutTheme),
68
- lint: toValue(params.lint),
69
- additionalExtensions: toValue(params.extensions),
70
- placeholder: toValue(params.placeholder),
71
- }));
72
- // Unmounts CodeMirror if it’s mounted already, and mounts CodeMirror, if the given ref exists.
73
- watch(params.codeMirrorRef, () => {
41
+ const codeMirror = ref(null);
42
+ const setCodeMirrorContent = (newValue = "") => {
43
+ if (!codeMirror.value) {
44
+ return;
45
+ }
46
+ if (codeMirror.value.state.doc.toString() === newValue) {
47
+ return;
48
+ }
49
+ codeMirror.value.dispatch({
50
+ changes: {
51
+ from: 0,
52
+ to: codeMirror.value.state.doc.length,
53
+ insert: newValue
54
+ },
55
+ selection: {
56
+ anchor: Math.min(codeMirror.value.state.selection.main.anchor, newValue.length)
57
+ }
58
+ });
59
+ };
60
+ const extensionConfig = computed(() => ({
61
+ onChange: params.onChange,
62
+ onBlur: params.onBlur,
63
+ onFocus: params.onFocus,
64
+ disableTabIndent: toValue(params.disableTabIndent),
65
+ language: toValue(params.language),
66
+ classes: toValue(params.classes),
67
+ readOnly: toValue(params.readOnly),
68
+ lineNumbers: toValue(params.lineNumbers),
69
+ withVariables: toValue(params.withVariables),
70
+ forceFoldGutter: toValue(params.forceFoldGutter),
71
+ disableEnter: toValue(params.disableEnter),
72
+ disableCloseBrackets: toValue(params.disableCloseBrackets),
73
+ withoutTheme: toValue(params.withoutTheme),
74
+ lint: toValue(params.lint),
75
+ additionalExtensions: toValue(params.extensions),
76
+ placeholder: toValue(params.placeholder)
77
+ }));
78
+ watch(
79
+ params.codeMirrorRef,
80
+ () => {
81
+ codeMirror.value?.destroy();
82
+ mountCodeMirror();
83
+ },
84
+ { immediate: true }
85
+ );
86
+ onBeforeUnmount(() => codeMirror.value?.destroy());
87
+ function mountCodeMirror() {
88
+ if (params.codeMirrorRef.value) {
89
+ const provider = hasProvider(params) ? toValue(params.provider) : null;
90
+ const extensions = getCodeMirrorExtensions({
91
+ ...extensionConfig.value,
92
+ provider
93
+ });
94
+ codeMirror.value = new EditorView({
95
+ parent: params.codeMirrorRef.value,
96
+ extensions
97
+ });
98
+ if (!hasProvider(params)) {
99
+ setCodeMirrorContent(toValue(params.content));
100
+ }
101
+ }
102
+ }
103
+ watch(
104
+ () => hasProvider(params) ? toValue(params.provider) : null,
105
+ () => {
106
+ if (hasProvider(params)) {
74
107
  codeMirror.value?.destroy();
75
108
  mountCodeMirror();
76
- }, { immediate: true });
77
- // Cleanup codemirror
78
- onBeforeUnmount(() => codeMirror.value?.destroy());
79
- // Initializes CodeMirror.
80
- function mountCodeMirror() {
81
- if (params.codeMirrorRef.value) {
82
- const provider = hasProvider(params) ? toValue(params.provider) : null;
83
- const extensions = getCodeMirrorExtensions({
84
- ...extensionConfig.value,
85
- provider,
86
- });
87
- codeMirror.value = new EditorView({
88
- parent: params.codeMirrorRef.value,
89
- extensions,
90
- });
91
- // Set the initial content if a provider is not in use
92
- if (!hasProvider(params)) {
93
- setCodeMirrorContent(toValue(params.content));
94
- }
95
- }
109
+ }
96
110
  }
97
- // ---------------------------------------------------------------------------
98
- // Provider must be watched separately because we need to restart codemirror if the provider changes
99
- watch(() => (hasProvider(params) ? toValue(params.provider) : null), () => {
100
- if (hasProvider(params)) {
101
- codeMirror.value?.destroy();
102
- mountCodeMirror();
103
- }
104
- });
105
- // Update the extensions whenever parameters changes
106
- watch(extensionConfig, () => {
107
- if (!codeMirror.value) {
108
- return;
109
- }
110
- // If a provider is
111
- const provider = hasProvider(params) ? toValue(params.provider) : null;
112
- const extensions = getCodeMirrorExtensions({
113
- ...extensionConfig.value,
114
- provider,
115
- });
116
- requestAnimationFrame(() => {
117
- codeMirror.value?.dispatch({
118
- effects: StateEffect.reconfigure.of(extensions),
119
- });
111
+ );
112
+ watch(
113
+ extensionConfig,
114
+ () => {
115
+ if (!codeMirror.value) {
116
+ return;
117
+ }
118
+ const provider = hasProvider(params) ? toValue(params.provider) : null;
119
+ const extensions = getCodeMirrorExtensions({
120
+ ...extensionConfig.value,
121
+ provider
122
+ });
123
+ requestAnimationFrame(() => {
124
+ codeMirror.value?.dispatch({
125
+ effects: StateEffect.reconfigure.of(extensions)
120
126
  });
121
- }, { immediate: true });
122
- // ---------------------------------------------------------------------------
123
- // Keep the content in sync when the content is managed externally
124
- watch(() => toValue(params.content), () => {
125
- // When a provider is in use we do not map the content value back to the codemirror instance
126
- if (hasProvider(params)) {
127
- return;
128
- }
129
- setCodeMirrorContent(toValue(params.content));
130
- }, { immediate: true });
131
- return {
132
- /** Replaces the current content with the given value. */
133
- setCodeMirrorContent,
134
- /** Codemirror instance */
135
- codeMirror,
136
- };
127
+ });
128
+ },
129
+ { immediate: true }
130
+ );
131
+ watch(
132
+ () => toValue(params.content),
133
+ () => {
134
+ if (hasProvider(params)) {
135
+ return;
136
+ }
137
+ setCodeMirrorContent(toValue(params.content));
138
+ },
139
+ { immediate: true }
140
+ );
141
+ return {
142
+ /** Replaces the current content with the given value. */
143
+ setCodeMirrorContent,
144
+ /** Codemirror instance */
145
+ codeMirror
146
+ };
137
147
  };
138
- // ---------------------------------------------------------------------------
139
148
  const languageExtensions = {
140
- html: html,
141
- json: json,
142
- yaml: yaml,
143
- css: css,
144
- xml: xml,
149
+ html,
150
+ json,
151
+ yaml,
152
+ css,
153
+ xml
145
154
  };
146
- /** Generate the list of extension from parameters */
147
- function getCodeMirrorExtensions({ onChange, onBlur, onFocus, provider, language, classes = [], readOnly = false, lineNumbers: lineNumbers$1 = false, withVariables = false, forceFoldGutter = false, disableEnter = false, disableCloseBrackets = false, disableTabIndent = false, withoutTheme = false, lint = false, additionalExtensions = [], placeholder: placeholder$1, }) {
148
- const extensions = [
149
- highlightSpecialChars(),
150
- history(),
151
- keymap.of(historyKeymap),
152
- syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
153
- EditorView.theme({
154
- '.cm-line': {
155
- lineHeight: '20px',
156
- padding: '0 2px 0 4px',
157
- },
158
- '.cm-gutterElement': {
159
- lineHeight: '20px',
160
- },
161
- '.cm-tooltip': {
162
- border: '1px solid #f5c6cb',
163
- fontSize: '12px',
164
- },
165
- '.cm-tooltip-lint': {
166
- backgroundColor: '#ffffff',
167
- },
168
- '.cm-diagnostic-error': {
169
- borderLeft: '0',
170
- color: '#dc1b19',
171
- },
172
- '.cm-foldPlaceholder': {
173
- background: 'var(--scalar-background-1)',
174
- border: 'none',
175
- fontFamily: 'var(--scalar-font)',
176
- },
177
- }),
178
- // Listen to updates
179
- EditorView.updateListener.of((v) => {
180
- if (!v.docChanged) {
181
- return;
182
- }
183
- onChange?.(v.state.doc.toString());
184
- }),
185
- EditorView.domEventHandlers({
186
- blur: (_event, view) => {
187
- onBlur?.(view.state.doc.toString());
188
- },
189
- focus: (_event, view) => {
190
- onFocus?.(view.state.doc.toString());
191
- },
192
- }),
193
- // Add Classes
194
- EditorView.editorAttributes.of({ class: classes.join(' ') }),
195
- ...additionalExtensions,
196
- ];
197
- // Enable the provider
198
- if (provider) {
199
- extensions.push(provider);
200
- }
201
- // Add the theme as needed
202
- if (!withoutTheme) {
203
- extensions.push(customTheme);
155
+ function getCodeMirrorExtensions({
156
+ onChange,
157
+ onBlur,
158
+ onFocus,
159
+ provider,
160
+ language,
161
+ classes = [],
162
+ readOnly = false,
163
+ lineNumbers = false,
164
+ withVariables = false,
165
+ forceFoldGutter = false,
166
+ disableEnter = false,
167
+ disableCloseBrackets = false,
168
+ disableTabIndent = false,
169
+ withoutTheme = false,
170
+ lint = false,
171
+ additionalExtensions = [],
172
+ placeholder
173
+ }) {
174
+ const extensions = [
175
+ highlightSpecialChars(),
176
+ history(),
177
+ keymap.of(historyKeymap),
178
+ syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
179
+ EditorView.theme({
180
+ ".cm-line": {
181
+ lineHeight: "20px",
182
+ padding: "0 2px 0 4px"
183
+ },
184
+ ".cm-gutterElement": {
185
+ lineHeight: "20px"
186
+ },
187
+ ".cm-tooltip": {
188
+ border: "1px solid #f5c6cb",
189
+ fontSize: "12px"
190
+ },
191
+ ".cm-tooltip-lint": {
192
+ backgroundColor: "#ffffff"
193
+ },
194
+ ".cm-diagnostic-error": {
195
+ borderLeft: "0",
196
+ color: "#dc1b19"
197
+ },
198
+ ".cm-foldPlaceholder": {
199
+ background: "var(--scalar-background-1)",
200
+ border: "none",
201
+ fontFamily: "var(--scalar-font)"
202
+ }
203
+ }),
204
+ // Listen to updates
205
+ EditorView.updateListener.of((v) => {
206
+ if (!v.docChanged) {
207
+ return;
208
+ }
209
+ onChange?.(v.state.doc.toString());
210
+ }),
211
+ EditorView.domEventHandlers({
212
+ blur: (_event, view) => {
213
+ onBlur?.(view.state.doc.toString());
214
+ },
215
+ focus: (_event, view) => {
216
+ onFocus?.(view.state.doc.toString());
217
+ }
218
+ }),
219
+ // Add Classes
220
+ EditorView.editorAttributes.of({ class: classes.join(" ") }),
221
+ ...additionalExtensions
222
+ ];
223
+ if (provider) {
224
+ extensions.push(provider);
225
+ }
226
+ if (!withoutTheme) {
227
+ extensions.push(customTheme);
228
+ }
229
+ if (readOnly) {
230
+ extensions.push(EditorView.editable.of(false));
231
+ } else {
232
+ extensions.push(
233
+ indentOnInput(),
234
+ bracketMatching(),
235
+ autocompletion(),
236
+ keymap.of([...completionKeymap, selectAllKeyBinding]),
237
+ bracketMatching()
238
+ );
239
+ if (!disableCloseBrackets) {
240
+ extensions.push(closeBrackets(), keymap.of([...closeBracketsKeymap]));
204
241
  }
205
- // Read only
206
- if (readOnly) {
207
- extensions.push(EditorView.editable.of(false));
242
+ if (disableTabIndent) {
243
+ extensions.push(
244
+ keymap.of([
245
+ {
246
+ key: "Tab",
247
+ run: () => false,
248
+ // Prevent default Tab behavior
249
+ shift: () => false
250
+ // Prevent default Shift+Tab behavior
251
+ }
252
+ ])
253
+ );
254
+ } else {
255
+ extensions.push(keymap.of([indentWithTab]));
208
256
  }
209
- else {
210
- extensions.push(indentOnInput(), bracketMatching(), autocompletion(), keymap.of([...completionKeymap, selectAllKeyBinding]), bracketMatching());
211
- if (!disableCloseBrackets) {
212
- extensions.push(closeBrackets(), keymap.of([...closeBracketsKeymap]));
257
+ }
258
+ if (placeholder) {
259
+ extensions.push(placeholderExtension(placeholder));
260
+ }
261
+ if (lineNumbers) {
262
+ extensions.push(lineNumbersExtension());
263
+ }
264
+ if (forceFoldGutter) {
265
+ extensions.push(
266
+ foldGutter({
267
+ markerDOM: (open) => {
268
+ const icon = document.createElement("div");
269
+ icon.classList.add("cm-foldMarker");
270
+ const vnode = h(ScalarIcon, {
271
+ icon: open ? "ChevronDown" : "ChevronRight",
272
+ size: "md"
273
+ });
274
+ render(vnode, icon);
275
+ return icon;
213
276
  }
214
- if (disableTabIndent) {
215
- extensions.push(keymap.of([
216
- {
217
- key: 'Tab',
218
- run: () => false, // Prevent default Tab behavior
219
- shift: () => false, // Prevent default Shift+Tab behavior
220
- },
221
- ]));
277
+ })
278
+ );
279
+ }
280
+ if (language && languageExtensions[language]) {
281
+ extensions.push(languageExtensions[language]());
282
+ if (!forceFoldGutter) {
283
+ extensions.push(
284
+ foldGutter({
285
+ markerDOM: (open) => {
286
+ const icon = document.createElement("div");
287
+ icon.classList.add("cm-foldMarker");
288
+ const vnode = h(ScalarIcon, {
289
+ icon: open ? "ChevronDown" : "ChevronRight",
290
+ size: "md"
291
+ });
292
+ render(vnode, icon);
293
+ return icon;
294
+ }
295
+ })
296
+ );
297
+ }
298
+ }
299
+ if (lint && language === "json") {
300
+ const jsonLinter = linter((view) => {
301
+ const diagnostics = [];
302
+ const content = view.state.doc.toString();
303
+ if (content.trim()) {
304
+ try {
305
+ JSON.parse(content);
306
+ } catch (e) {
307
+ if (e instanceof Error) {
308
+ diagnostics.push({
309
+ from: 0,
310
+ to: view.state.doc.length,
311
+ severity: "error",
312
+ message: e.message
313
+ });
314
+ }
222
315
  }
223
- else {
224
- extensions.push(keymap.of([indentWithTab]));
316
+ }
317
+ return diagnostics;
318
+ });
319
+ extensions.push(jsonLinter);
320
+ }
321
+ if (withVariables) {
322
+ extensions.push(variables());
323
+ }
324
+ if (disableEnter) {
325
+ extensions.push(
326
+ keymap.of([
327
+ {
328
+ key: "Enter",
329
+ run: () => {
330
+ return true;
331
+ }
332
+ },
333
+ {
334
+ key: "Ctrl-Enter",
335
+ mac: "Cmd-Enter",
336
+ run: () => {
337
+ return true;
338
+ }
339
+ },
340
+ {
341
+ key: "Shift-Enter",
342
+ run: () => {
343
+ return true;
344
+ }
225
345
  }
226
- }
227
- // Add placeholder extension if placeholder is provided
228
- if (placeholder$1) {
229
- extensions.push(placeholder(placeholder$1));
230
- }
231
- // Line numbers
232
- if (lineNumbers$1) {
233
- extensions.push(lineNumbers());
234
- }
235
- if (forceFoldGutter) {
236
- extensions.push(foldGutter({
237
- markerDOM: (open) => {
238
- const icon = document.createElement('div');
239
- icon.classList.add('cm-foldMarker');
240
- const vnode = h(ScalarIcon, {
241
- icon: open ? 'ChevronDown' : 'ChevronRight',
242
- size: 'md',
243
- });
244
- render(vnode, icon);
245
- return icon;
246
- },
247
- }));
248
- }
249
- // Syntax highlighting
250
- if (language && languageExtensions[language]) {
251
- extensions.push(languageExtensions[language]());
252
- if (!forceFoldGutter) {
253
- extensions.push(foldGutter({
254
- markerDOM: (open) => {
255
- const icon = document.createElement('div');
256
- icon.classList.add('cm-foldMarker');
257
- const vnode = h(ScalarIcon, {
258
- icon: open ? 'ChevronDown' : 'ChevronRight',
259
- size: 'md',
260
- });
261
- render(vnode, icon);
262
- return icon;
263
- },
264
- }));
346
+ ])
347
+ );
348
+ } else {
349
+ extensions.push(
350
+ keymap.of([
351
+ {
352
+ key: "Enter",
353
+ run: insertNewline
265
354
  }
266
- }
267
- // JSON Linter
268
- if (lint && language === 'json') {
269
- const jsonLinter = linter((view) => {
270
- const diagnostics = [];
271
- const content = view.state.doc.toString();
272
- if (content.trim()) {
273
- try {
274
- JSON.parse(content);
275
- }
276
- catch (e) {
277
- if (e instanceof Error) {
278
- diagnostics.push({
279
- from: 0,
280
- to: view.state.doc.length,
281
- severity: 'error',
282
- message: e.message,
283
- });
284
- }
285
- }
286
- }
287
- return diagnostics;
288
- });
289
- extensions.push(jsonLinter);
290
- }
291
- // Highlight variables
292
- if (withVariables) {
293
- extensions.push(variables());
294
- }
295
- if (disableEnter) {
296
- extensions.push(keymap.of([
297
- {
298
- key: 'Enter',
299
- run: () => {
300
- return true;
301
- },
302
- },
303
- {
304
- key: 'Ctrl-Enter',
305
- mac: 'Cmd-Enter',
306
- run: () => {
307
- return true;
308
- },
309
- },
310
- {
311
- key: 'Shift-Enter',
312
- run: () => {
313
- return true;
314
- },
315
- },
316
- ]));
317
- }
318
- else {
319
- extensions.push(keymap.of([
320
- {
321
- key: 'Enter',
322
- run: insertNewline,
323
- },
324
- ]));
325
- }
326
- return extensions;
355
+ ])
356
+ );
357
+ }
358
+ return extensions;
327
359
  }
328
-
329
- export { useCodeMirror };
360
+ export {
361
+ useCodeMirror
362
+ };
363
+ //# sourceMappingURL=useCodeMirror.js.map