@neo4j-cypher/react-codemirror 2.0.0-next.7 → 2.0.0-next.9

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 (74) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/CypherEditor.d.ts +60 -2
  3. package/dist/CypherEditor.js +115 -20
  4. package/dist/CypherEditor.js.map +1 -1
  5. package/dist/e2e_tests/autoCompletion.spec.js +112 -17
  6. package/dist/e2e_tests/autoCompletion.spec.js.map +1 -1
  7. package/dist/e2e_tests/configuration.spec.d.ts +1 -0
  8. package/dist/e2e_tests/configuration.spec.js +83 -0
  9. package/dist/e2e_tests/configuration.spec.js.map +1 -0
  10. package/dist/e2e_tests/debounce.spec.d.ts +1 -0
  11. package/dist/e2e_tests/debounce.spec.js +63 -0
  12. package/dist/e2e_tests/debounce.spec.js.map +1 -0
  13. package/dist/e2e_tests/e2eUtils.js +9 -1
  14. package/dist/e2e_tests/e2eUtils.js.map +1 -1
  15. package/dist/e2e_tests/extraKeybindings.spec.js +0 -1
  16. package/dist/e2e_tests/extraKeybindings.spec.js.map +1 -1
  17. package/dist/e2e_tests/historyNavigation.spec.js +107 -16
  18. package/dist/e2e_tests/historyNavigation.spec.js.map +1 -1
  19. package/dist/e2e_tests/sanityChecks.spec.js +0 -10
  20. package/dist/e2e_tests/sanityChecks.spec.js.map +1 -1
  21. package/dist/e2e_tests/signatureHelp.spec.js +43 -15
  22. package/dist/e2e_tests/signatureHelp.spec.js.map +1 -1
  23. package/dist/e2e_tests/snippets.spec.d.ts +1 -0
  24. package/dist/e2e_tests/snippets.spec.js +62 -0
  25. package/dist/e2e_tests/snippets.spec.js.map +1 -0
  26. package/dist/e2e_tests/syntaxHighlighting.spec.js +0 -1
  27. package/dist/e2e_tests/syntaxHighlighting.spec.js.map +1 -1
  28. package/dist/e2e_tests/syntaxValidation.spec.js +3 -3
  29. package/dist/e2e_tests/syntaxValidation.spec.js.map +1 -1
  30. package/dist/historyNavigation.js +1 -1
  31. package/dist/historyNavigation.js.map +1 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/lang-cypher/autocomplete.d.ts +4 -1
  36. package/dist/lang-cypher/autocomplete.js +79 -17
  37. package/dist/lang-cypher/autocomplete.js.map +1 -1
  38. package/dist/lang-cypher/contants.test.js +2 -2
  39. package/dist/lang-cypher/contants.test.js.map +1 -1
  40. package/dist/lang-cypher/createCypherTheme.js +34 -2
  41. package/dist/lang-cypher/createCypherTheme.js.map +1 -1
  42. package/dist/lang-cypher/langCypher.d.ts +5 -0
  43. package/dist/lang-cypher/langCypher.js +11 -5
  44. package/dist/lang-cypher/langCypher.js.map +1 -1
  45. package/dist/lang-cypher/signatureHelp.js +39 -22
  46. package/dist/lang-cypher/signatureHelp.js.map +1 -1
  47. package/dist/lang-cypher/utils.d.ts +2 -0
  48. package/dist/lang-cypher/utils.js +10 -0
  49. package/dist/lang-cypher/utils.js.map +1 -0
  50. package/dist/neo4jSetup.js +35 -1
  51. package/dist/neo4jSetup.js.map +1 -1
  52. package/dist/tsconfig.tsbuildinfo +1 -1
  53. package/package.json +9 -9
  54. package/src/CypherEditor.tsx +233 -31
  55. package/src/e2e_tests/autoCompletion.spec.tsx +189 -18
  56. package/src/e2e_tests/configuration.spec.tsx +111 -0
  57. package/src/e2e_tests/debounce.spec.tsx +100 -0
  58. package/src/e2e_tests/e2eUtils.ts +11 -1
  59. package/src/e2e_tests/extraKeybindings.spec.tsx +0 -2
  60. package/src/e2e_tests/historyNavigation.spec.tsx +136 -17
  61. package/src/e2e_tests/sanityChecks.spec.tsx +0 -16
  62. package/src/e2e_tests/signatureHelp.spec.tsx +86 -18
  63. package/src/e2e_tests/snippets.spec.tsx +92 -0
  64. package/src/e2e_tests/syntaxHighlighting.spec.tsx +0 -2
  65. package/src/e2e_tests/syntaxValidation.spec.tsx +3 -3
  66. package/src/historyNavigation.ts +1 -1
  67. package/src/index.ts +4 -1
  68. package/src/lang-cypher/autocomplete.ts +95 -19
  69. package/src/lang-cypher/contants.test.ts +5 -2
  70. package/src/lang-cypher/createCypherTheme.ts +34 -2
  71. package/src/lang-cypher/langCypher.ts +17 -5
  72. package/src/lang-cypher/signatureHelp.ts +61 -30
  73. package/src/lang-cypher/utils.ts +9 -0
  74. package/src/neo4jSetup.tsx +51 -1
@@ -1,7 +1,9 @@
1
1
  import { EditorState, StateField } from '@codemirror/state';
2
2
  import { showTooltip, Tooltip } from '@codemirror/view';
3
3
  import { signatureHelp } from '@neo4j-cypher/language-support';
4
+ import { SignatureInformation } from 'vscode-languageserver-types';
4
5
  import { CypherConfig } from './langCypher';
6
+ import { getDocString } from './utils';
5
7
 
6
8
  function getTriggerCharacter(query: string, caretPosition: number) {
7
9
  let i = caretPosition - 1;
@@ -16,6 +18,61 @@ function getTriggerCharacter(query: string, caretPosition: number) {
16
18
  return triggerCharacter;
17
19
  }
18
20
 
21
+ const createSignatureHelpElement =
22
+ ({
23
+ signature,
24
+ activeParameter,
25
+ }: {
26
+ signature: SignatureInformation;
27
+ activeParameter: number;
28
+ }) =>
29
+ () => {
30
+ const parameters = signature.parameters;
31
+ const doc = getDocString(signature.documentation);
32
+ const dom = document.createElement('div');
33
+ dom.className = 'cm-signature-help-panel';
34
+
35
+ const contents = document.createElement('div');
36
+ contents.className = 'cm-signature-help-panel-contents';
37
+ dom.appendChild(contents);
38
+
39
+ const signatureLabel = document.createElement('div');
40
+ signatureLabel.className = 'cm-signature-help-panel-name';
41
+ signatureLabel.appendChild(document.createTextNode(`${signature.label}(`));
42
+
43
+ parameters.forEach((param, index) => {
44
+ if (typeof param.documentation === 'string') {
45
+ const span = document.createElement('span');
46
+ span.appendChild(document.createTextNode(param.documentation));
47
+ if (index !== parameters.length - 1) {
48
+ span.appendChild(document.createTextNode(', '));
49
+ }
50
+
51
+ if (index === activeParameter) {
52
+ span.className = 'cm-signature-help-panel-current-argument';
53
+ }
54
+ signatureLabel.appendChild(span);
55
+ }
56
+ });
57
+
58
+ signatureLabel.appendChild(document.createTextNode(')'));
59
+
60
+ contents.appendChild(signatureLabel);
61
+
62
+ const separator = document.createElement('div');
63
+ separator.className = 'cm-signature-help-panel-separator';
64
+
65
+ contents.appendChild(separator);
66
+
67
+ const description = document.createElement('div');
68
+ description.className = 'cm-signature-help-panel-description';
69
+ description.appendChild(document.createTextNode(doc));
70
+
71
+ contents.appendChild(description);
72
+
73
+ return { dom };
74
+ };
75
+
19
76
  function getSignatureHelpTooltip(
20
77
  state: EditorState,
21
78
  config: CypherConfig,
@@ -44,41 +101,15 @@ function getSignatureHelpTooltip(
44
101
  signatures[activeSignature].documentation !== undefined
45
102
  ) {
46
103
  const signature = signatures[activeSignature];
47
- const parameters = signature.parameters;
48
- let doc = signature.documentation.toString();
49
-
50
- if (
51
- activeParameter >= 0 &&
52
- activeParameter <
53
- (signatures[activeSignature].parameters?.length ?? 0)
54
- ) {
55
- doc =
56
- parameters[activeParameter].documentation.toString() + '\n\n' + doc;
57
- }
104
+ const showSignatureTooltipBelow =
105
+ config.showSignatureTooltipBelow ?? true;
58
106
 
59
107
  result = [
60
108
  {
61
109
  pos: caretPosition,
62
- above: true,
63
- strictSide: true,
110
+ above: !showSignatureTooltipBelow,
64
111
  arrow: true,
65
- create: () => {
66
- const div = document.createElement('div');
67
- const methodName = document.createElement('div');
68
- const argPlusDescription = document.createElement('div');
69
- const separator = document.createElement('hr');
70
- const lineBreak = document.createElement('br');
71
-
72
- div.append(
73
- ...[methodName, separator, lineBreak, argPlusDescription],
74
- );
75
- div.className = 'cm-tooltip-signature-help';
76
-
77
- methodName.innerText = signature.label;
78
- argPlusDescription.innerText = doc;
79
-
80
- return { dom: div };
81
- },
112
+ create: createSignatureHelpElement({ signature, activeParameter }),
82
113
  },
83
114
  ];
84
115
  }
@@ -0,0 +1,9 @@
1
+ import { MarkupContent } from 'vscode-languageserver-types';
2
+
3
+ export function getDocString(result: string | MarkupContent): string {
4
+ if (MarkupContent.is(result)) {
5
+ result.value;
6
+ } else {
7
+ return result;
8
+ }
9
+ }
@@ -1,9 +1,14 @@
1
1
  import {
2
2
  acceptCompletion,
3
3
  autocompletion,
4
+ clearSnippet,
4
5
  closeBrackets,
5
6
  closeBracketsKeymap,
7
+ closeCompletion,
6
8
  completionKeymap,
9
+ nextSnippetField,
10
+ prevSnippetField,
11
+ snippetKeymap,
7
12
  } from '@codemirror/autocomplete';
8
13
  import {
9
14
  defaultKeymap,
@@ -22,11 +27,13 @@ import {
22
27
  import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
23
28
  import { EditorState, Extension, StateCommand } from '@codemirror/state';
24
29
  import {
30
+ Command,
25
31
  crosshairCursor,
26
32
  drawSelection,
27
33
  dropCursor,
28
34
  EditorView,
29
35
  highlightSpecialChars,
36
+ KeyBinding,
30
37
  keymap,
31
38
  rectangularSelection,
32
39
  } from '@codemirror/view';
@@ -55,7 +62,7 @@ const insertTab: StateCommand = (cmd) => {
55
62
  };
56
63
 
57
64
  export const basicNeo4jSetup = (): Extension[] => {
58
- const keymaps = [
65
+ const keymaps: KeyBinding[] = [
59
66
  closeBracketsKeymap,
60
67
  defaultKeymap,
61
68
  searchKeymap,
@@ -125,5 +132,48 @@ export const basicNeo4jSetup = (): Extension[] => {
125
132
 
126
133
  extensions.push(keymap.of(keymaps));
127
134
 
135
+ extensions.push(
136
+ snippetKeymap.of([
137
+ {
138
+ key: 'Tab',
139
+ run: acceptCompletionOrGotoNextSnippet,
140
+ shift: acceptCompletionOrGotoPrevSnippet,
141
+ },
142
+ { key: 'Escape', run: closeCompletionsOrClearSnippets },
143
+ ]),
144
+ );
145
+
128
146
  return extensions;
129
147
  };
148
+
149
+ // The logic to check if there's a completion open is surprisingly complex
150
+ // https://github.com/codemirror/autocomplete/blob/5ad2ebc861f2f61cdc943fc087a5bfb756a7d0fa/src/view.ts#L31
151
+ // For example it respects an interaction delay, so we can't just check if the completion is open
152
+ // instead we just run the acceptCompletion command which returns true if a completion was accepted
153
+ // in that case we know that we shouldn't move to the next snippet field
154
+ const acceptCompletionOrGotoNextSnippet: Command = (view: EditorView) => {
155
+ const didCompletion = acceptCompletion(view);
156
+ if (didCompletion) {
157
+ return true;
158
+ }
159
+
160
+ return nextSnippetField(view);
161
+ };
162
+
163
+ const acceptCompletionOrGotoPrevSnippet: Command = (view: EditorView) => {
164
+ const didCompletion = acceptCompletion(view);
165
+ if (didCompletion) {
166
+ return true;
167
+ }
168
+
169
+ return prevSnippetField(view);
170
+ };
171
+
172
+ const closeCompletionsOrClearSnippets: Command = (view: EditorView) => {
173
+ const closedCompletions = closeCompletion(view);
174
+ if (closedCompletions) {
175
+ return true;
176
+ }
177
+
178
+ return clearSnippet(view);
179
+ };