@mongodb-js/compass-editor 0.70.0 → 0.72.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.
@@ -1,7 +1,9 @@
1
1
  import type { CompletionSource } from '@codemirror/autocomplete';
2
2
  /**
3
- * Autocompleter for the document object, only autocompletes field names in the
4
- * appropriate format (either escaped or not) both for javascript and json modes
3
+ * Autocompleter for the document object. Completes field names in the
4
+ * appropriate format (either escaped or not) both for javascript and json
5
+ * modes, and bson constructors (`ObjectId()`, `ISODate()`, ...) in value
6
+ * position, which are only valid outside of json mode.
5
7
  */
6
8
  export declare const createDocumentAutocompleter: (fields: string[]) => CompletionSource;
7
9
  //# sourceMappingURL=document-autocompleter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"document-autocompleter.d.ts","sourceRoot":"","sources":["../../src/codemirror/document-autocompleter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AA2BjE;;;GAGG;AACH,eAAO,MAAM,2BAA2B,GACtC,QAAQ,MAAM,EAAE,KACf,gBAqCF,CAAC"}
1
+ {"version":3,"file":"document-autocompleter.d.ts","sourceRoot":"","sources":["../../src/codemirror/document-autocompleter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAgCjE;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,GACtC,QAAQ,MAAM,EAAE,KACf,gBAiEF,CAAC"}
@@ -23,14 +23,18 @@ function isJavaScriptPropertyName(token) {
23
23
  (!token.prevSibling || token.prevSibling.name === '['));
24
24
  }
25
25
  /**
26
- * Autocompleter for the document object, only autocompletes field names in the
27
- * appropriate format (either escaped or not) both for javascript and json modes
26
+ * Autocompleter for the document object. Completes field names in the
27
+ * appropriate format (either escaped or not) both for javascript and json
28
+ * modes, and bson constructors (`ObjectId()`, `ISODate()`, ...) in value
29
+ * position, which are only valid outside of json mode.
28
30
  */
29
31
  const createDocumentAutocompleter = (fields) => {
30
32
  const completions = (0, autocompleter_1.completer)('', { fields, meta: ['field:identifier'] });
33
+ const bsonCompletions = (0, autocompleter_1.completer)('', { meta: ['bson'] });
31
34
  return (context) => {
32
35
  const token = (0, utils_1.resolveTokenAtCursor)(context);
33
- const shouldAlwaysEscapeProperty = context.state.facet(editor_1.languageName)[0] === 'json';
36
+ const isJSON = context.state.facet(editor_1.languageName)[0] === 'json';
37
+ const shouldAlwaysEscapeProperty = isJSON;
34
38
  if (isJSONPropertyName(token) || isJavaScriptPropertyName(token)) {
35
39
  const prefix = context.state
36
40
  .sliceDoc(token.from, context.pos)
@@ -55,6 +59,27 @@ const createDocumentAutocompleter = (fields) => {
55
59
  filter: false,
56
60
  };
57
61
  }
62
+ if (!isJSON && token.type.name !== 'String' && (0, utils_1.isPropertyValue)(token)) {
63
+ const prefix = context.state.sliceDoc(token.from, context.pos);
64
+ if (!prefix) {
65
+ return null;
66
+ }
67
+ return {
68
+ from: token.from,
69
+ to: token.to,
70
+ options: bsonCompletions
71
+ .filter((completion) => {
72
+ return completion.value
73
+ .toLowerCase()
74
+ .startsWith(prefix.toLowerCase());
75
+ })
76
+ .map((completion) => {
77
+ // bson constructors are expressions, never quoted like a field name
78
+ return (0, utils_1.mapMongoDBCompletionToCodemirrorCompletion)(completion, 'never');
79
+ }),
80
+ filter: false,
81
+ };
82
+ }
58
83
  return (0, utils_1.completeWordsInString)(context);
59
84
  };
60
85
  };
@@ -0,0 +1,21 @@
1
+ import type { EditorRef } from '../types';
2
+ import type { Annotation } from './../editor';
3
+ import type { LintConfig } from '../linter';
4
+ export type SafeIntegerViolation = {
5
+ from: number;
6
+ to: number;
7
+ acceptsStringArgument: boolean;
8
+ };
9
+ type SafeIntegerLinterOptions = LintConfig & {
10
+ editorRef?: React.RefObject<EditorRef>;
11
+ onFixViolation?: (source: string) => string;
12
+ onViolationFixed: () => void;
13
+ externalAnnotations?: React.RefObject<Annotation[]>;
14
+ };
15
+ export declare function useSafeIntegerLinter({ editorRef, onFixViolation, onViolationFixed, externalAnnotations, lintDelay, tooltipExitDelay, theme, }: SafeIntegerLinterOptions): {
16
+ safeIntegerLinter: import("@codemirror/state").Extension;
17
+ violations: SafeIntegerViolation[];
18
+ onFixViolations: () => void;
19
+ };
20
+ export {};
21
+ //# sourceMappingURL=use-safe-integer-linter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-safe-integer-linter.d.ts","sourceRoot":"","sources":["../../src/codemirror/use-safe-integer-linter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAK5C,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IAIX,qBAAqB,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,KAAK,wBAAwB,GAAG,UAAU,GAAG;IAC3C,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACvC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC;CACrD,CAAC;AAuGF,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,cAAsC,EACtC,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,gBAAgB,EAChB,KAAK,GACN,EAAE,wBAAwB;;;;EAgG1B"}
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSafeIntegerLinter = useSafeIntegerLinter;
4
+ const react_1 = require("react");
5
+ const compass_components_1 = require("@mongodb-js/compass-components");
6
+ const linter_1 = require("../linter");
7
+ const lint_tooltip_exit_delay_1 = require("../lint-tooltip-exit-delay");
8
+ const defaultOnFixViolation = (source) => `Long("${source}")`;
9
+ const VIOLATION_MESSAGE = 'Exceeds safe integer range.';
10
+ // Constructors that accept a string and use the value. Anything else
11
+ // either changes meaning (`Date`) or still rounds the value (`Int32`,
12
+ // `Double`), so those get wrapped instead.
13
+ const STRING_ARGUMENT_CONSTRUCTORS = new Set([
14
+ 'Long',
15
+ 'NumberLong',
16
+ 'Int64',
17
+ 'Decimal128',
18
+ 'NumberDecimal',
19
+ ]);
20
+ function isUnsafeInteger(str) {
21
+ if (!/^-?\d+$/.test(str)) {
22
+ return false;
23
+ }
24
+ try {
25
+ const num = BigInt(str);
26
+ return (num > BigInt(Number.MAX_SAFE_INTEGER) ||
27
+ num < BigInt(Number.MIN_SAFE_INTEGER));
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ // A leading `-` is a unary expression around the literal rather than part of
34
+ // it, so it has to be pulled into the violation to fix `-123...` as
35
+ // `Long("-123...")` rather than `-Long("123...")`.
36
+ function negationOperator(node, doc) {
37
+ const operator = node.parent?.name === 'UnaryExpression' ? node.parent.firstChild : null;
38
+ return operator?.name === 'ArithOp' &&
39
+ doc.sliceString(operator.from, operator.to) === '-'
40
+ ? operator
41
+ : null;
42
+ }
43
+ function isStringConstructorArgument(node, doc) {
44
+ if (node.parent?.name !== 'ArgList') {
45
+ return false;
46
+ }
47
+ const callee = node.parent.prevSibling;
48
+ return (callee?.name === 'VariableName' &&
49
+ STRING_ARGUMENT_CONSTRUCTORS.has(doc.sliceString(callee.from, callee.to)));
50
+ }
51
+ function unsafeIntegerViolation(node, doc) {
52
+ if (!isUnsafeInteger(doc.sliceString(node.from, node.to))) {
53
+ return null;
54
+ }
55
+ const literal = negationOperator(node, doc)?.parent ?? node;
56
+ return {
57
+ from: literal.from,
58
+ to: literal.to,
59
+ acceptsStringArgument: isStringConstructorArgument(literal, doc),
60
+ };
61
+ }
62
+ function sameViolations(a, b) {
63
+ return (a.length === b.length &&
64
+ a.every((v, i) => v.from === b[i].from &&
65
+ v.to === b[i].to &&
66
+ v.acceptsStringArgument === b[i].acceptsStringArgument));
67
+ }
68
+ function applyFix(violation, source, { onFixViolation, onViolationFixed }) {
69
+ // The violation can span whitespace between a sign and its digits (`- 123`).
70
+ const literal = source.replace(/\s+/g, '');
71
+ onViolationFixed();
72
+ return violation.acceptsStringArgument
73
+ ? `"${literal}"`
74
+ : onFixViolation(literal);
75
+ }
76
+ function useSafeIntegerLinter({ editorRef, onFixViolation = defaultOnFixViolation, onViolationFixed, externalAnnotations, lintDelay, tooltipExitDelay, theme, }) {
77
+ const [violations, setViolations] = (0, react_1.useState)([]);
78
+ const optionsRef = (0, compass_components_1.useCurrentValueRef)({
79
+ onFixViolation,
80
+ onViolationFixed,
81
+ externalAnnotations,
82
+ });
83
+ const violationsRef = (0, compass_components_1.useCurrentValueRef)(violations);
84
+ const safeIntegerLinter = (0, react_1.useMemo)(() => {
85
+ return (0, linter_1.createCodemirrorLinter)((tree, view) => {
86
+ const violations = [];
87
+ tree.iterate({
88
+ enter: (node) => {
89
+ // Warn on any bare number literal, including one passed as a
90
+ // numeric argument to a constructor like `Long(123...)`: the
91
+ // literal is parsed as a JS double and loses precision before the
92
+ // constructor sees it.
93
+ if (node.name !== 'Number') {
94
+ return;
95
+ }
96
+ const violation = unsafeIntegerViolation(node.node, view.state.doc);
97
+ if (violation) {
98
+ violations.push(violation);
99
+ }
100
+ },
101
+ });
102
+ // Only update state when the violations actually changed, otherwise
103
+ // every lint pass re-renders the consumer with a new array identity.
104
+ if (!sameViolations(violationsRef.current, violations)) {
105
+ violationsRef.current = violations;
106
+ setViolations(violations);
107
+ }
108
+ const annotations = violations.map((violation) => {
109
+ const { from, to } = violation;
110
+ return {
111
+ from,
112
+ to,
113
+ severity: 'error',
114
+ message: VIOLATION_MESSAGE,
115
+ actions: [
116
+ {
117
+ name: 'Convert to Long',
118
+ apply: (view, from, to) => {
119
+ view.dispatch({
120
+ changes: {
121
+ from,
122
+ to,
123
+ insert: applyFix(violation, view.state.sliceDoc(from, to), optionsRef.current),
124
+ },
125
+ });
126
+ },
127
+ },
128
+ ],
129
+ };
130
+ });
131
+ return [
132
+ ...annotations.map(lint_tooltip_exit_delay_1.wrapLinterAnnotation),
133
+ ...(optionsRef.current.externalAnnotations?.current ?? []),
134
+ ];
135
+ }, { lintDelay, theme, tooltipExitDelay });
136
+ }, [lintDelay, theme, tooltipExitDelay]);
137
+ const onFixViolations = (0, react_1.useCallback)(() => {
138
+ const editor = editorRef?.current?.editor;
139
+ if (!editor || violations.length === 0) {
140
+ return;
141
+ }
142
+ editor.dispatch({
143
+ changes: violations.map((violation) => {
144
+ const { from, to } = violation;
145
+ return {
146
+ from,
147
+ to,
148
+ insert: applyFix(violation, editor.state.sliceDoc(from, to), optionsRef.current),
149
+ };
150
+ }),
151
+ });
152
+ setViolations([]);
153
+ }, [violations, editorRef]);
154
+ return { safeIntegerLinter, violations, onFixViolations };
155
+ }
package/dist/editor.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { KeyBinding } from '@codemirror/view';
3
3
  import { placeholder as codemirrorPlaceholder, EditorView } from '@codemirror/view';
4
+ import { syntaxTree } from '@codemirror/language';
4
5
  import type { Diagnostic } from '@codemirror/lint';
5
6
  import type { CompletionSource } from '@codemirror/autocomplete';
6
7
  import type { Extension } from '@codemirror/state';
@@ -33,6 +34,7 @@ export declare const editorPalette: {
33
34
  readonly autocompleteBorderColor: "#E8EDEB";
34
35
  readonly autocompleteMatchColor: "#00A35C";
35
36
  readonly autocompleteSelectedBackgroundColor: "#E8EDEB";
37
+ readonly linkColor: "#016BF8";
36
38
  };
37
39
  readonly dark: {
38
40
  readonly color: string;
@@ -57,14 +59,19 @@ export declare const editorPalette: {
57
59
  readonly autocompleteBorderColor: "#5C6C75";
58
60
  readonly autocompleteMatchColor: "#F9FBFA";
59
61
  readonly autocompleteSelectedBackgroundColor: "#3D4F58";
62
+ readonly linkColor: "#0498EC";
60
63
  };
61
64
  };
62
65
  declare const highlightStyles: {
63
66
  readonly light: HighlightStyle;
64
67
  readonly dark: HighlightStyle;
65
68
  };
66
- type EditorLanguage = 'json' | 'javascript' | 'javascript-expression';
67
- export type Annotation = Pick<Diagnostic, 'from' | 'to' | 'severity' | 'message'>;
69
+ export type EditorLanguage = 'json' | 'javascript' | 'javascript-expression';
70
+ /**
71
+ * *Note*: Action only works when linting has been enabled
72
+ */
73
+ export type Annotation = Pick<Diagnostic, 'from' | 'to' | 'severity' | 'message' | 'actions' | 'renderMessage'>;
74
+ export type Linter = (tree: ReturnType<typeof syntaxTree>, view: EditorView) => readonly Annotation[];
68
75
  type EditorProps = {
69
76
  language?: EditorLanguage;
70
77
  onChangeText?: (text: string, event?: any) => void;
@@ -83,6 +90,7 @@ type EditorProps = {
83
90
  'data-testid'?: string;
84
91
  annotations?: Annotation[];
85
92
  completer?: CompletionSource;
93
+ linter?: Extension;
86
94
  customExtensions?: Extension[];
87
95
  minLines?: number;
88
96
  maxLines?: number;
@@ -102,7 +110,7 @@ export declare const languages: Record<EditorLanguage, () => LanguageSupport>;
102
110
  export declare const languageName: Facet<EditorLanguage, readonly EditorLanguage[]>;
103
111
  declare const BaseEditor: React.ForwardRefExoticComponent<EditorProps & React.RefAttributes<EditorRef>>;
104
112
  export type { EditorView, KeyBinding as Command };
105
- type InlineEditorProps = Omit<EditorProps, 'text' | 'showLineNumbers' | 'showFoldGutter' | 'showAnnotationsGutter' | 'showScroll' | 'highlightActiveLine' | 'minLines' | 'annotations'> & ({
113
+ type InlineEditorProps = Omit<EditorProps, 'text' | 'showLineNumbers' | 'showFoldGutter' | 'showScroll' | 'highlightActiveLine' | 'minLines' | 'annotations'> & ({
106
114
  text: string;
107
115
  initialText?: never;
108
116
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.tsx"],"names":[],"mappings":"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"}
package/dist/editor.js CHANGED
@@ -55,13 +55,6 @@ const editorStyle = (0, compass_components_1.css)({
55
55
  fontSize: 13,
56
56
  fontFamily: compass_components_1.fontFamilies.code,
57
57
  });
58
- const disabledContainerStyles = (0, compass_components_1.css)({
59
- borderRadius: compass_components_1.spacing[100],
60
- boxShadow: `0 0 0 1px ${compass_components_1.palette.gray.light1}`,
61
- });
62
- const disabledContainerDarkModeStyles = (0, compass_components_1.css)({
63
- boxShadow: `0 0 0 1px ${compass_components_1.palette.gray.dark2}`,
64
- });
65
58
  const readOnlyStyle = (0, compass_components_1.css)({
66
59
  // We hide the blinking cursor in read only mode
67
60
  // as it can appear to users like the editor is editable.
@@ -142,6 +135,7 @@ exports.editorPalette = {
142
135
  autocompleteBorderColor: compass_components_1.palette.gray.light2,
143
136
  autocompleteMatchColor: compass_components_1.palette.green.dark1,
144
137
  autocompleteSelectedBackgroundColor: compass_components_1.palette.gray.light2,
138
+ linkColor: compass_components_1.palette.blue.base,
145
139
  },
146
140
  dark: {
147
141
  color: compass_components_1.codePalette.dark[3],
@@ -167,12 +161,26 @@ exports.editorPalette = {
167
161
  autocompleteBorderColor: compass_components_1.palette.gray.dark1,
168
162
  autocompleteMatchColor: compass_components_1.palette.gray.light3,
169
163
  autocompleteSelectedBackgroundColor: compass_components_1.palette.gray.dark2,
164
+ linkColor: compass_components_1.palette.blue.light1,
170
165
  },
171
166
  };
172
167
  const cmFontStyles = {
173
168
  fontSize: '13px',
174
169
  fontFamily: compass_components_1.fontFamilies.code,
175
170
  };
171
+ const disabledContainerStyles = (0, compass_components_1.css)({
172
+ borderRadius: compass_components_1.spacing[100],
173
+ overflow: 'hidden',
174
+ boxShadow: `0 0 0 1px ${compass_components_1.palette.gray.light1}`,
175
+ backgroundColor: exports.editorPalette.light.disabledBackgroundColor,
176
+ '& .cm-editor, & .cm-gutters, & .cm-content[contenteditable="false"]': {
177
+ backgroundColor: 'transparent',
178
+ },
179
+ });
180
+ const disabledContainerDarkModeStyles = (0, compass_components_1.css)({
181
+ boxShadow: `0 0 0 1px ${compass_components_1.palette.gray.dark2}`,
182
+ backgroundColor: exports.editorPalette.dark.disabledBackgroundColor,
183
+ });
176
184
  function getStylesForTheme(theme) {
177
185
  return view_1.EditorView.theme({
178
186
  '&': {
@@ -189,13 +197,9 @@ function getStylesForTheme(theme) {
189
197
  paddingBottom: `${compass_components_1.spacing[100]}px`,
190
198
  caretColor: exports.editorPalette[theme].cursorColor,
191
199
  },
192
- '[contenteditable="false"] ': {
193
- borderRadius: `${compass_components_1.spacing[100]}px`,
194
- },
195
200
  '.cm-content[contenteditable="false"] ': {
196
201
  cursor: 'not-allowed',
197
202
  color: exports.editorPalette[theme].disabledColor,
198
- backgroundColor: exports.editorPalette[theme].disabledBackgroundColor,
199
203
  },
200
204
  '& .cm-activeLine': {
201
205
  background: 'none',
@@ -405,6 +409,29 @@ function getStylesForTheme(theme) {
405
409
  '& .cm-tooltip .completion-info p:last-child': {
406
410
  marginBottom: 0,
407
411
  },
412
+ // Hide the inline underline @codemirror/lint error
413
+ '& .cm-lintRange-error': {
414
+ backgroundImage: 'none',
415
+ },
416
+ '& .cm-lintPoint::after': {
417
+ display: 'none',
418
+ },
419
+ '.cm-diagnosticAction': {
420
+ background: 'none',
421
+ display: 'inline',
422
+ margin: '0 0 0 8px',
423
+ padding: '0',
424
+ border: 'none',
425
+ color: exports.editorPalette[theme].linkColor,
426
+ cursor: 'pointer',
427
+ },
428
+ '& .cm-diagnosticAction:focus-visible': {
429
+ outline: 'none',
430
+ boxShadow: `0 0 0 2px ${compass_components_1.palette.blue.light1}`,
431
+ },
432
+ '& .cm-diagnosticAction:hover': {
433
+ textDecoration: 'underline',
434
+ },
408
435
  '& .cm-widgetBuffer': {
409
436
  // Default is text-top which causes weird 1px added to the line height
410
437
  // when widget (in our case this is placeholder widget) is shown in the
@@ -419,6 +446,9 @@ const themeStyles = {
419
446
  };
420
447
  // Base theme for autocomplete hover - applies to document root for tooltips
421
448
  const autocompleteHoverStyles = view_1.EditorView.baseTheme({
449
+ '.cm-tooltip': {
450
+ maxWidth: 'min(90vw, 500px)',
451
+ },
422
452
  '&light .cm-tooltip.cm-tooltip-autocomplete ul li:hover': {
423
453
  color: exports.editorPalette.light.autocompleteColor,
424
454
  backgroundColor: exports.editorPalette.light.autocompleteSelectedBackgroundColor,
@@ -578,7 +608,7 @@ function useCodemirrorExtensionCompartment(fn, value, editorViewRef) {
578
608
  }, value);
579
609
  return extensionCompartment;
580
610
  }
581
- const BaseEditor = react_1.default.forwardRef(function BaseEditor({ initialText: _initialText, text, onChangeText, language = 'json', showLineNumbers = true, showFoldGutter = true, showAnnotationsGutter = true, showScroll = true, highlightActiveLine: shouldHighlightActiveLine = true, annotations, completer, customExtensions, darkMode: _darkMode, disabled = false, className, readOnly = false, onLoad = () => {
611
+ const BaseEditor = react_1.default.forwardRef(function BaseEditor({ initialText: _initialText, text, onChangeText, language = 'json', showLineNumbers = true, showFoldGutter = true, showAnnotationsGutter = true, showScroll = true, highlightActiveLine: shouldHighlightActiveLine = true, annotations, completer, linter, customExtensions, darkMode: _darkMode, disabled = false, className, readOnly = false, onLoad = () => {
582
612
  /**/
583
613
  }, onFocus = () => {
584
614
  /**/
@@ -722,6 +752,9 @@ const BaseEditor = react_1.default.forwardRef(function BaseEditor({ initialText:
722
752
  })
723
753
  : [];
724
754
  }, completer, editorViewRef);
755
+ const linterExtension = useCodemirrorExtensionCompartment(() => {
756
+ return linter ? linter : [];
757
+ }, linter, editorViewRef);
725
758
  const placeholderExtension = useCodemirrorExtensionCompartment(() => {
726
759
  return placeholder ? (0, view_1.placeholder)(placeholder) : [];
727
760
  }, placeholder, editorViewRef);
@@ -771,6 +804,7 @@ const BaseEditor = react_1.default.forwardRef(function BaseEditor({ initialText:
771
804
  (0, language_1.bracketMatching)(),
772
805
  (0, autocomplete_1.closeBrackets)(),
773
806
  autocompletionExtension,
807
+ linterExtension,
774
808
  languageExtension,
775
809
  (0, language_2.syntaxHighlighting)(highlightStyles['light']),
776
810
  (0, language_2.syntaxHighlighting)(highlightStyles['dark']),
@@ -802,11 +836,14 @@ const BaseEditor = react_1.default.forwardRef(function BaseEditor({ initialText:
802
836
  ...autocomplete_1.completionKeymap,
803
837
  ...tabKeymap,
804
838
  ]),
805
- // Supply the document body as the tooltip parent
806
- // because we are using containment contexts for container
807
- // queries which offset things otherwise.
839
+ // Supply the tooltip parent explicitly because we are using
840
+ // containment contexts for container queries which offset things
841
+ // otherwise. When the editor is rendered inside a modal (a native
842
+ // <dialog> promoted to the top layer via showModal), the tooltip
843
+ // must be parented to that dialog so it renders in the same top
844
+ // layer instead of behind the modal.
808
845
  (0, view_1.tooltips)({
809
- parent: document.body,
846
+ parent: domNode.closest('dialog') ?? document.body,
810
847
  }),
811
848
  editableExtension,
812
849
  readOnlyExtension,
@@ -882,6 +919,7 @@ const BaseEditor = react_1.default.forwardRef(function BaseEditor({ initialText:
882
919
  readOnlyExtension,
883
920
  themeConfigExtension,
884
921
  autocompletionExtension,
922
+ linterExtension,
885
923
  lineHeightExtension,
886
924
  activeLineExtension,
887
925
  placeholderExtension,
@@ -1055,13 +1093,17 @@ const prettify = (editorView) => {
1055
1093
  }
1056
1094
  return false;
1057
1095
  };
1058
- const inlineStyles = (0, compass_components_1.css)({
1096
+ const inlineStylesLightMode = (0, compass_components_1.css)({
1059
1097
  '& .cm-editor': {
1060
- backgroundColor: 'transparent',
1098
+ backgroundColor: compass_components_1.palette.white,
1099
+ },
1100
+ '& .cm-gutters': {
1101
+ backgroundColor: `${compass_components_1.palette.white} !important`,
1061
1102
  },
1062
1103
  });
1063
- const InlineEditor = react_1.default.forwardRef(function InlineEditor({ className, ...props }, forwardRef) {
1064
- return (react_1.default.createElement(BaseEditor, { ref: forwardRef, maxLines: 10, showFoldGutter: false, showLineNumbers: false, showAnnotationsGutter: false, showScroll: false, highlightActiveLine: false, className: (0, compass_components_1.cx)(inlineStyles, className), language: "javascript-expression", ...props }));
1104
+ const InlineEditor = react_1.default.forwardRef(function InlineEditor({ className, showAnnotationsGutter, ...props }, forwardRef) {
1105
+ const darkMode = (0, compass_components_1.useDarkMode)();
1106
+ return (react_1.default.createElement(BaseEditor, { ref: forwardRef, maxLines: 10, showFoldGutter: false, showLineNumbers: false, showAnnotationsGutter: Boolean(showAnnotationsGutter), showScroll: false, highlightActiveLine: false, className: (0, compass_components_1.cx)(!darkMode && !props.disabled && inlineStylesLightMode, className), language: "javascript-expression", ...props }));
1065
1107
  });
1066
1108
  exports.CodemirrorInlineEditor = InlineEditor;
1067
1109
  const multilineEditorContainerStyle = (0, compass_components_1.css)({
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export { prettify } from './prettify';
3
3
  export type { FormatOptions } from './prettify';
4
4
  export { CodemirrorInlineEditor, CodemirrorMultilineEditor, setCodemirrorEditorValue, getCodemirrorEditorValue, } from './editor';
5
5
  export type { EditorView, Command, Annotation, Completer } from './editor';
6
+ export type { Extension } from '@codemirror/state';
6
7
  export type { Action } from './action-button';
7
8
  export { createDocumentAutocompleter } from './codemirror/document-autocompleter';
8
9
  export { createValidationAutocompleter } from './codemirror/validation-autocompleter';
@@ -14,4 +15,5 @@ export { createQueryHistoryAutocompleter, type SavedQuery, } from './codemirror/
14
15
  export { createQueryWithHistoryAutocompleter } from './codemirror/query-autocompleter-with-history';
15
16
  export { useJsonSchemaAutocompleter } from './use-json-schema-autocompleter';
16
17
  export type { JsonSchemaAutocompleterResult } from './use-json-schema-autocompleter';
18
+ export { useSafeIntegerLinter } from './codemirror/use-safe-integer-linter';
17
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC3E,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AACtF,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AACxF,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EACL,+BAA+B,EAC/B,KAAK,UAAU,GAChB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,YAAY,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC3E,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AACtF,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AACxF,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EACL,+BAA+B,EAC/B,KAAK,UAAU,GAChB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,YAAY,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useJsonSchemaAutocompleter = exports.createQueryWithHistoryAutocompleter = exports.createQueryHistoryAutocompleter = exports.createSearchIndexAutocompleter = exports.createAggregationAutocompleter = exports.createStageAutocompleter = exports.createQueryAutocompleter = exports.createValidationAutocompleter = exports.createDocumentAutocompleter = exports.getCodemirrorEditorValue = exports.setCodemirrorEditorValue = exports.CodemirrorMultilineEditor = exports.CodemirrorInlineEditor = exports.prettify = void 0;
3
+ exports.useSafeIntegerLinter = exports.useJsonSchemaAutocompleter = exports.createQueryWithHistoryAutocompleter = exports.createQueryHistoryAutocompleter = exports.createSearchIndexAutocompleter = exports.createAggregationAutocompleter = exports.createStageAutocompleter = exports.createQueryAutocompleter = exports.createValidationAutocompleter = exports.createDocumentAutocompleter = exports.getCodemirrorEditorValue = exports.setCodemirrorEditorValue = exports.CodemirrorMultilineEditor = exports.CodemirrorInlineEditor = exports.prettify = void 0;
4
4
  var prettify_1 = require("./prettify");
5
5
  Object.defineProperty(exports, "prettify", { enumerable: true, get: function () { return prettify_1.prettify; } });
6
6
  var editor_1 = require("./editor");
@@ -26,3 +26,5 @@ var query_autocompleter_with_history_1 = require("./codemirror/query-autocomplet
26
26
  Object.defineProperty(exports, "createQueryWithHistoryAutocompleter", { enumerable: true, get: function () { return query_autocompleter_with_history_1.createQueryWithHistoryAutocompleter; } });
27
27
  var use_json_schema_autocompleter_1 = require("./use-json-schema-autocompleter");
28
28
  Object.defineProperty(exports, "useJsonSchemaAutocompleter", { enumerable: true, get: function () { return use_json_schema_autocompleter_1.useJsonSchemaAutocompleter; } });
29
+ var use_safe_integer_linter_1 = require("./codemirror/use-safe-integer-linter");
30
+ Object.defineProperty(exports, "useSafeIntegerLinter", { enumerable: true, get: function () { return use_safe_integer_linter_1.useSafeIntegerLinter; } });
@@ -0,0 +1,7 @@
1
+ import { type Extension } from '@codemirror/state';
2
+ import type { Annotation } from './editor';
3
+ export declare const TOOLTIP_DATA_ATTR = "data-codemirror-linter";
4
+ export declare function wrapLinterAnnotation(annotation: Annotation): Annotation;
5
+ export declare const TOOLTIP_SELECTOR = ".cm-diagnostic:has([data-codemirror-linter=true])";
6
+ export declare function lintTooltipExitDelay(tooltipExitDelay?: number): Extension;
7
+ //# sourceMappingURL=lint-tooltip-exit-delay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-tooltip-exit-delay.d.ts","sourceRoot":"","sources":["../src/lint-tooltip-exit-delay.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,SAAS,EAGf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C,eAAO,MAAM,iBAAiB,2BAA2B,CAAC;AAE1D,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAcvE;AAED,eAAO,MAAM,gBAAgB,sDAAoD,CAAC;AAGlF,wBAAgB,oBAAoB,CAClC,gBAAgB,GAAE,MAAmC,GACpD,SAAS,CAwEX"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TOOLTIP_SELECTOR = exports.TOOLTIP_DATA_ATTR = void 0;
4
+ exports.wrapLinterAnnotation = wrapLinterAnnotation;
5
+ exports.lintTooltipExitDelay = lintTooltipExitDelay;
6
+ const view_1 = require("@codemirror/view");
7
+ const state_1 = require("@codemirror/state");
8
+ const delayedHide = state_1.Annotation.define();
9
+ const DEFAULT_TOOLTIP_EXIT_DELAY = 300;
10
+ exports.TOOLTIP_DATA_ATTR = 'data-codemirror-linter';
11
+ function wrapLinterAnnotation(annotation) {
12
+ return {
13
+ ...annotation,
14
+ renderMessage: (view) => {
15
+ const wrapper = document.createElement('span');
16
+ wrapper.setAttribute(exports.TOOLTIP_DATA_ATTR, 'true');
17
+ if (annotation.renderMessage) {
18
+ wrapper.appendChild(annotation.renderMessage(view));
19
+ }
20
+ else {
21
+ wrapper.textContent = annotation.message;
22
+ }
23
+ return wrapper;
24
+ },
25
+ };
26
+ }
27
+ exports.TOOLTIP_SELECTOR = `.cm-diagnostic:has([${exports.TOOLTIP_DATA_ATTR}=true])`;
28
+ const HOVER_SELECTOR = `${exports.TOOLTIP_SELECTOR}, .cm-lint-marker`;
29
+ function lintTooltipExitDelay(tooltipExitDelay = DEFAULT_TOOLTIP_EXIT_DELAY) {
30
+ let editorView;
31
+ let pendingTimeout;
32
+ let hideEffects;
33
+ const clearPendingTimeout = () => {
34
+ clearTimeout(pendingTimeout);
35
+ pendingTimeout = undefined;
36
+ };
37
+ const hideTooltip = () => {
38
+ pendingTimeout = undefined;
39
+ const effects = hideEffects;
40
+ hideEffects = undefined;
41
+ if (effects) {
42
+ editorView?.dispatch({ effects, annotations: delayedHide.of(true) });
43
+ }
44
+ };
45
+ const scheduleHide = () => {
46
+ clearPendingTimeout();
47
+ pendingTimeout = setTimeout(hideTooltip, tooltipExitDelay);
48
+ };
49
+ const onMouseMove = (event) => {
50
+ if (!hideEffects) {
51
+ return;
52
+ }
53
+ const target = event.target;
54
+ if (target?.closest?.(HOVER_SELECTOR)) {
55
+ // Pointer came back in time, keep the tooltip open until it leaves again.
56
+ clearPendingTimeout();
57
+ }
58
+ else if (!pendingTimeout) {
59
+ scheduleHide();
60
+ }
61
+ };
62
+ return [
63
+ view_1.ViewPlugin.define((view) => {
64
+ editorView = view;
65
+ // Listening on the window rather than through `domEventHandlers`: neither
66
+ // the gutter marker nor the tooltip is part of the editor content DOM.
67
+ window.addEventListener('mousemove', onMouseMove);
68
+ return {
69
+ destroy() {
70
+ window.removeEventListener('mousemove', onMouseMove);
71
+ clearPendingTimeout();
72
+ hideEffects = undefined;
73
+ editorView = undefined;
74
+ },
75
+ };
76
+ }),
77
+ state_1.EditorState.transactionFilter.of((tr) => {
78
+ if (tr.annotation(delayedHide) || tr.docChanged || !tr.effects.length) {
79
+ return tr;
80
+ }
81
+ const before = tr.startState.facet(view_1.showTooltip);
82
+ const stillShown = new Set(tr.state.facet(view_1.showTooltip).filter(Boolean));
83
+ const hidesTooltip = before.some((tooltip) => tooltip && !stillShown.has(tooltip));
84
+ if (!hidesTooltip || !document.querySelector(exports.TOOLTIP_SELECTOR)) {
85
+ return tr;
86
+ }
87
+ hideEffects = tr.effects;
88
+ scheduleHide();
89
+ return [];
90
+ }),
91
+ ];
92
+ }
@@ -0,0 +1,14 @@
1
+ import { syntaxTree } from '@codemirror/language';
2
+ import type { Annotation } from './editor';
3
+ import { EditorView } from '@codemirror/view';
4
+ import type { Extension } from '@codemirror/state';
5
+ export type LintConfig = {
6
+ lintDelay?: number;
7
+ tooltipExitDelay?: number;
8
+ theme?: {
9
+ spec: Parameters<typeof EditorView.theme>[0];
10
+ options?: Parameters<typeof EditorView.theme>[1];
11
+ };
12
+ };
13
+ export declare function createCodemirrorLinter(diagnosticsFn: (tree: ReturnType<typeof syntaxTree>, view: EditorView) => Annotation[], config?: LintConfig): Extension;
14
+ //# sourceMappingURL=linter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../src/linter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAOnD,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAI1B,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;KAClD,CAAC;CACH,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,CACb,IAAI,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,EACnC,IAAI,EAAE,UAAU,KACb,UAAU,EAAE,EACjB,MAAM,CAAC,EAAE,UAAU,GAClB,SAAS,CAgBX"}
package/dist/linter.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCodemirrorLinter = createCodemirrorLinter;
4
+ const lint_1 = require("@codemirror/lint");
5
+ const language_1 = require("@codemirror/language");
6
+ const view_1 = require("@codemirror/view");
7
+ const lint_tooltip_exit_delay_1 = require("./lint-tooltip-exit-delay");
8
+ // Do not show inline (on-hover) tooltips for linting errors,
9
+ // we will show them in the gutter instead
10
+ const noInlineTooltips = () => [];
11
+ function createCodemirrorLinter(diagnosticsFn, config) {
12
+ const lintExtension = (0, lint_1.linter)((view) => diagnosticsFn((0, language_1.syntaxTree)(view.state), view), {
13
+ delay: config?.lintDelay ?? 500,
14
+ tooltipFilter: noInlineTooltips,
15
+ });
16
+ const extensions = [
17
+ lintExtension,
18
+ (0, lint_tooltip_exit_delay_1.lintTooltipExitDelay)(config?.tooltipExitDelay),
19
+ ];
20
+ if (config?.theme) {
21
+ extensions.push(view_1.EditorView.theme(config.theme.spec, config.theme.options));
22
+ }
23
+ return extensions;
24
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"use-json-schema-autocompleter.d.ts","sourceRoot":"","sources":["../src/use-json-schema-autocompleter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAQnD,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,0BAA0B,CAAC;AAU7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAkM3C,MAAM,MAAM,6BAA6B,GAAG;IAC1C,uDAAuD;IACvD,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACxC,sFAAsF;IACtF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,iDAAiD;IACjD,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,GACX,6BAA6B,CA8U/B"}
1
+ {"version":3,"file":"use-json-schema-autocompleter.d.ts","sourceRoot":"","sources":["../src/use-json-schema-autocompleter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAQnD,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,0BAA0B,CAAC;AAU7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAkM3C,MAAM,MAAM,6BAA6B,GAAG;IAC1C,uDAAuD;IACvD,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACxC,sFAAsF;IACtF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,iDAAiD;IACjD,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,GACX,6BAA6B,CA6U/B"}
@@ -430,11 +430,12 @@ function useJsonSchemaAutocompleter(schema, text) {
430
430
  aborted = true;
431
431
  };
432
432
  }, [schema, text, editorConfig.extensions.length]);
433
- // Compute hasErrors from annotations - both error and warning severity block validation
433
+ // Compute hasErrors from annotations - only error severity blocks validation.
434
434
  // Note: vscode-json-languageservice reports schema violations (missing required fields,
435
- // type mismatches, etc.) as warnings, so we include them in validation blocking
435
+ // type mismatches, etc.) as warnings and only malformed JSON syntax as an error, so
436
+ // schema violations are surfaced as annotations without blocking the consumer's action.
436
437
  const hasErrors = (0, react_1.useMemo)(() => {
437
- return annotations.some((a) => a.severity === 'error' || a.severity === 'warning');
438
+ return annotations.some((a) => a.severity === 'error');
438
439
  }, [annotations]);
439
440
  return {
440
441
  completer: editorConfig.completer,
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "email": "compass@mongodb.com"
14
14
  },
15
15
  "homepage": "https://github.com/mongodb-js/compass",
16
- "version": "0.70.0",
16
+ "version": "0.72.0",
17
17
  "repository": {
18
18
  "type": "git",
19
19
  "url": "https://github.com/mongodb-js/compass.git"
@@ -46,10 +46,10 @@
46
46
  "reformat": "npm run eslint . -- --fix && npm run prettier -- --write ."
47
47
  },
48
48
  "devDependencies": {
49
- "@mongodb-js/eslint-config-compass": "^1.4.25",
50
- "@mongodb-js/mocha-config-compass": "^1.8.0",
49
+ "@mongodb-js/eslint-config-compass": "^1.4.27",
50
+ "@mongodb-js/mocha-config-compass": "^1.8.1",
51
51
  "@mongodb-js/prettier-config-compass": "^1.2.9",
52
- "@mongodb-js/testing-library-compass": "^1.6.0",
52
+ "@mongodb-js/testing-library-compass": "^1.7.1",
53
53
  "@mongodb-js/tsconfig-compass": "^1.3.1",
54
54
  "@types/chai": "^4.2.21",
55
55
  "@types/hast": "^3.0.4",
@@ -73,14 +73,14 @@
73
73
  "@codemirror/state": "^6.5.2",
74
74
  "@codemirror/view": "^6.38.0",
75
75
  "@lezer/highlight": "^1.2.1",
76
- "@mongodb-js/compass-components": "^1.68.0",
77
- "@mongodb-js/mongodb-constants": "^0.33.0",
76
+ "@mongodb-js/compass-components": "^1.70.0",
77
+ "@mongodb-js/mongodb-constants": "^0.34.8",
78
78
  "hast": "^0.0.2",
79
79
  "json-schema": "^0.4.0",
80
- "mongodb-query-parser": "^4.7.14",
80
+ "mongodb-query-parser": "^5.0.5",
81
81
  "polished": "^4.2.2",
82
82
  "prettier": "^2.7.1",
83
- "react": "^17.0.2",
83
+ "react": "^18.3.1",
84
84
  "rehype-sanitize": "^5.0.1",
85
85
  "rehype-stringify": "^9.0.4",
86
86
  "remark-parse": "^10.0.0",
@@ -89,5 +89,5 @@
89
89
  "vscode-json-languageservice": "^5.7.2",
90
90
  "vscode-languageserver-textdocument": "^1.0.12"
91
91
  },
92
- "gitHead": "b56c594288a4ee443a43a8907867401768ea5955"
92
+ "gitHead": "13069dd486790839d988fbef8ff12c1056fa86c8"
93
93
  }