@neo4j-cypher/react-codemirror 2.0.0-alpha.0 → 2.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/LICENSE.md +201 -0
- package/README.md +24 -4
- package/dist/{index.cjs → cjs/index.cjs} +187 -74
- package/dist/cjs/index.cjs.map +7 -0
- package/{esm → dist/esm}/index.mjs +196 -66
- package/dist/esm/index.mjs.map +7 -0
- package/dist/types/CypherEditor.d.ts +118 -0
- package/dist/types/e2e_tests/auto-completion.spec.d.ts +1 -0
- package/dist/types/e2e_tests/e2e-utils.d.ts +12 -0
- package/dist/types/e2e_tests/extra-keybindings.spec.d.ts +1 -0
- package/dist/types/e2e_tests/history-navigation.spec.d.ts +1 -0
- package/dist/types/e2e_tests/mock-data.d.ts +3779 -0
- package/dist/types/e2e_tests/performance-test.spec.d.ts +1 -0
- package/dist/types/e2e_tests/sanity-checks.spec.d.ts +1 -0
- package/dist/types/e2e_tests/syntax-highlighting.spec.d.ts +1 -0
- package/dist/types/e2e_tests/syntax-validation.spec.d.ts +1 -0
- package/dist/types/icons.d.ts +2 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/lang-cypher/ParserAdapter.d.ts +14 -0
- package/dist/types/lang-cypher/autocomplete.d.ts +3 -0
- package/dist/types/lang-cypher/constants.d.ts +31 -0
- package/dist/types/lang-cypher/contants.test.d.ts +1 -0
- package/dist/types/lang-cypher/create-cypher-theme.d.ts +26 -0
- package/dist/types/lang-cypher/lang-cypher.d.ts +7 -0
- package/dist/types/lang-cypher/syntax-validation.d.ts +3 -0
- package/dist/types/lang-cypher/theme-icons.d.ts +7 -0
- package/dist/types/ndl-tokens-copy.d.ts +379 -0
- package/dist/types/ndl-tokens-copy.test.d.ts +1 -0
- package/dist/types/neo4j-setup.d.ts +2 -0
- package/dist/types/repl-mode.d.ts +8 -0
- package/dist/types/themes.d.ts +11 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +48 -15
- package/src/CypherEditor.tsx +316 -0
- package/src/e2e_tests/auto-completion.spec.tsx +232 -0
- package/src/e2e_tests/e2e-utils.ts +75 -0
- package/src/e2e_tests/extra-keybindings.spec.tsx +57 -0
- package/src/e2e_tests/history-navigation.spec.tsx +144 -0
- package/src/e2e_tests/mock-data.ts +4310 -0
- package/src/e2e_tests/performance-test.spec.tsx +71 -0
- package/src/e2e_tests/sanity-checks.spec.tsx +87 -0
- package/src/e2e_tests/syntax-highlighting.spec.tsx +198 -0
- package/src/e2e_tests/syntax-validation.spec.tsx +157 -0
- package/src/icons.ts +87 -0
- package/src/index.ts +4 -0
- package/src/lang-cypher/ParserAdapter.ts +92 -0
- package/src/lang-cypher/autocomplete.ts +65 -0
- package/src/lang-cypher/constants.ts +61 -0
- package/src/lang-cypher/contants.test.ts +104 -0
- package/src/lang-cypher/create-cypher-theme.ts +207 -0
- package/src/lang-cypher/lang-cypher.ts +32 -0
- package/src/lang-cypher/syntax-validation.ts +24 -0
- package/src/lang-cypher/theme-icons.ts +27 -0
- package/src/ndl-tokens-copy.test.ts +11 -0
- package/src/ndl-tokens-copy.ts +379 -0
- package/src/neo4j-setup.tsx +129 -0
- package/src/repl-mode.ts +214 -0
- package/src/themes.ts +130 -0
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { CypherParser, parse } from "@neo4j-cypher/language-support";
|
|
3
|
-
import * as ReactCodemirror from "@uiw/react-codemirror";
|
|
4
3
|
|
|
5
4
|
// src/CypherEditor.tsx
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import {
|
|
6
|
+
Annotation,
|
|
7
|
+
Compartment,
|
|
8
|
+
EditorState as EditorState2
|
|
9
|
+
} from "@codemirror/state";
|
|
10
|
+
import {
|
|
11
|
+
EditorView as EditorView4,
|
|
12
|
+
keymap as keymap3,
|
|
13
|
+
lineNumbers
|
|
14
|
+
} from "@codemirror/view";
|
|
15
|
+
import { Component, createRef } from "react";
|
|
9
16
|
|
|
10
17
|
// src/lang-cypher/lang-cypher.ts
|
|
11
18
|
import {
|
|
@@ -47,8 +54,7 @@ var completionKindToCodemirrorIcon = (c) => {
|
|
|
47
54
|
};
|
|
48
55
|
return map[c];
|
|
49
56
|
};
|
|
50
|
-
var
|
|
51
|
-
var cypherAutocomplete = (schema) => (context) => {
|
|
57
|
+
var cypherAutocomplete = (config) => (context) => {
|
|
52
58
|
const textUntilCursor = context.state.doc.toString().slice(0, context.pos);
|
|
53
59
|
const triggerCharacters = [".", ":", "{", "$"];
|
|
54
60
|
const lastCharacter = textUntilCursor.slice(-1);
|
|
@@ -58,7 +64,7 @@ var cypherAutocomplete = (schema) => (context) => {
|
|
|
58
64
|
if (!shouldTriggerCompletion) {
|
|
59
65
|
return null;
|
|
60
66
|
}
|
|
61
|
-
const options = autocomplete(textUntilCursor, schema ??
|
|
67
|
+
const options = autocomplete(textUntilCursor, config.schema ?? {});
|
|
62
68
|
return {
|
|
63
69
|
from: context.matchBefore(/(\w|\$)*$/).from,
|
|
64
70
|
options: options.map((o) => ({
|
|
@@ -202,17 +208,18 @@ var ParserAdapter = class extends Parser {
|
|
|
202
208
|
import { linter } from "@codemirror/lint";
|
|
203
209
|
import { validateSyntax } from "@neo4j-cypher/language-support";
|
|
204
210
|
import { DiagnosticSeverity } from "vscode-languageserver-types";
|
|
205
|
-
var cypherLinter = (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
211
|
+
var cypherLinter = (config) => linter((view) => {
|
|
212
|
+
if (!config.lint) {
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
return validateSyntax(view.state.doc.toString(), config.schema).map(
|
|
216
|
+
(diagnostic) => ({
|
|
209
217
|
from: diagnostic.offsets.start,
|
|
210
218
|
to: diagnostic.offsets.end,
|
|
211
219
|
severity: diagnostic.severity === DiagnosticSeverity.Error ? "error" : "warning",
|
|
212
220
|
message: diagnostic.message
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
return diagnostics;
|
|
221
|
+
})
|
|
222
|
+
);
|
|
216
223
|
});
|
|
217
224
|
|
|
218
225
|
// src/lang-cypher/lang-cypher.ts
|
|
@@ -222,12 +229,12 @@ var facet = defineLanguageFacet({
|
|
|
222
229
|
});
|
|
223
230
|
var parserAdapter = new ParserAdapter(facet);
|
|
224
231
|
var cypherLanguage = new Language(facet, parserAdapter, [], "cypher");
|
|
225
|
-
function cypher(
|
|
232
|
+
function cypher(config) {
|
|
226
233
|
return new LanguageSupport(cypherLanguage, [
|
|
227
234
|
cypherLanguage.data.of({
|
|
228
|
-
autocomplete: cypherAutocomplete(
|
|
235
|
+
autocomplete: cypherAutocomplete(config)
|
|
229
236
|
}),
|
|
230
|
-
|
|
237
|
+
cypherLinter(config)
|
|
231
238
|
]);
|
|
232
239
|
}
|
|
233
240
|
|
|
@@ -262,7 +269,6 @@ import {
|
|
|
262
269
|
EditorView,
|
|
263
270
|
highlightSpecialChars,
|
|
264
271
|
keymap,
|
|
265
|
-
lineNumbers,
|
|
266
272
|
rectangularSelection
|
|
267
273
|
} from "@codemirror/view";
|
|
268
274
|
import { lintKeymap } from "@codemirror/lint";
|
|
@@ -346,7 +352,7 @@ var insertTab = (cmd) => {
|
|
|
346
352
|
}
|
|
347
353
|
return true;
|
|
348
354
|
};
|
|
349
|
-
var basicNeo4jSetup = (
|
|
355
|
+
var basicNeo4jSetup = () => {
|
|
350
356
|
const keymaps = [
|
|
351
357
|
closeBracketsKeymap,
|
|
352
358
|
defaultKeymap,
|
|
@@ -372,16 +378,6 @@ var basicNeo4jSetup = (prompt) => {
|
|
|
372
378
|
}
|
|
373
379
|
].flat();
|
|
374
380
|
const extensions = [];
|
|
375
|
-
extensions.push(
|
|
376
|
-
lineNumbers({
|
|
377
|
-
formatNumber(a, state) {
|
|
378
|
-
if (state.doc.lines === 1 && prompt !== void 0) {
|
|
379
|
-
return prompt;
|
|
380
|
-
}
|
|
381
|
-
return a.toString();
|
|
382
|
-
}
|
|
383
|
-
})
|
|
384
|
-
);
|
|
385
381
|
extensions.push(highlightSpecialChars());
|
|
386
382
|
extensions.push(history());
|
|
387
383
|
extensions.push(drawSelection());
|
|
@@ -396,6 +392,7 @@ var basicNeo4jSetup = (prompt) => {
|
|
|
396
392
|
extensions.push(
|
|
397
393
|
autocompletion({
|
|
398
394
|
icons: false,
|
|
395
|
+
interactionDelay: 5,
|
|
399
396
|
addToOptions: [
|
|
400
397
|
{
|
|
401
398
|
render(completion, state) {
|
|
@@ -538,8 +535,7 @@ var replMode = ({
|
|
|
538
535
|
onExecute?.(doc);
|
|
539
536
|
onNewHistoryEntry?.(doc);
|
|
540
537
|
view.dispatch({
|
|
541
|
-
effects: pushToHistory.of(doc)
|
|
542
|
-
changes: { from: 0, to: view.state.doc.length, insert: "" }
|
|
538
|
+
effects: pushToHistory.of(doc)
|
|
543
539
|
});
|
|
544
540
|
}
|
|
545
541
|
return true;
|
|
@@ -1286,51 +1282,185 @@ function getThemeExtension(theme, inheritBgColor) {
|
|
|
1286
1282
|
|
|
1287
1283
|
// src/CypherEditor.tsx
|
|
1288
1284
|
import { jsx } from "react/jsx-runtime";
|
|
1289
|
-
var
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1285
|
+
var themeCompartment = new Compartment();
|
|
1286
|
+
var keyBindingCompartment = new Compartment();
|
|
1287
|
+
var ExternalEdit = Annotation.define();
|
|
1288
|
+
var CypherEditor = class extends Component {
|
|
1289
|
+
/**
|
|
1290
|
+
* The codemirror editor container.
|
|
1291
|
+
*/
|
|
1292
|
+
editorContainer = createRef();
|
|
1293
|
+
/**
|
|
1294
|
+
* The codemirror editor state.
|
|
1295
|
+
*/
|
|
1296
|
+
editorState = createRef();
|
|
1297
|
+
/**
|
|
1298
|
+
* The codemirror editor view.
|
|
1299
|
+
*/
|
|
1300
|
+
editorView = createRef();
|
|
1301
|
+
schemaRef = createRef();
|
|
1302
|
+
/**
|
|
1303
|
+
* Focus the editor
|
|
1304
|
+
*/
|
|
1305
|
+
focus() {
|
|
1306
|
+
this.editorView.current?.focus();
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* Move the cursor to the supplied position.
|
|
1310
|
+
* For example, to move the cursor to the end of the editor, use `value.length`
|
|
1311
|
+
*/
|
|
1312
|
+
updateCursorPosition(position) {
|
|
1313
|
+
this.editorView.current?.dispatch({
|
|
1314
|
+
selection: { anchor: position, head: position }
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Externally set the editor value and focus the editor.
|
|
1319
|
+
*/
|
|
1320
|
+
setValueAndFocus(value = "") {
|
|
1321
|
+
const currentCmValue = this.editorView.current.state?.doc.toString() ?? "";
|
|
1322
|
+
this.editorView.current.dispatch({
|
|
1323
|
+
changes: {
|
|
1324
|
+
from: 0,
|
|
1325
|
+
to: currentCmValue.length,
|
|
1326
|
+
insert: value
|
|
1327
|
+
},
|
|
1328
|
+
selection: { anchor: value.length, head: value.length }
|
|
1329
|
+
});
|
|
1330
|
+
this.editorView.current?.focus();
|
|
1331
|
+
}
|
|
1332
|
+
static defaultProps = {
|
|
1333
|
+
lint: true,
|
|
1334
|
+
schema: {},
|
|
1335
|
+
overrideThemeBackgroundColor: false,
|
|
1336
|
+
lineWrap: false,
|
|
1337
|
+
extraKeybindings: [],
|
|
1338
|
+
initialHistory: [],
|
|
1339
|
+
theme: "light"
|
|
1340
|
+
};
|
|
1341
|
+
componentDidMount() {
|
|
1342
|
+
const {
|
|
1343
|
+
theme,
|
|
1344
|
+
onExecute,
|
|
1345
|
+
initialHistory,
|
|
1346
|
+
onNewHistoryEntry,
|
|
1347
|
+
extraKeybindings,
|
|
1348
|
+
lineWrap,
|
|
1349
|
+
overrideThemeBackgroundColor,
|
|
1350
|
+
schema,
|
|
1351
|
+
lint,
|
|
1352
|
+
onChange
|
|
1353
|
+
} = this.props;
|
|
1354
|
+
this.schemaRef.current = { schema, lint };
|
|
1355
|
+
const maybeReplMode = onExecute ? replMode({
|
|
1356
|
+
onExecute,
|
|
1357
|
+
initialHistory,
|
|
1358
|
+
onNewHistoryEntry
|
|
1359
|
+
}) : [];
|
|
1360
|
+
const themeExtension = getThemeExtension(
|
|
1361
|
+
theme,
|
|
1362
|
+
overrideThemeBackgroundColor
|
|
1363
|
+
);
|
|
1364
|
+
const changeListener = onChange ? [
|
|
1365
|
+
EditorView4.updateListener.of((upt) => {
|
|
1366
|
+
const wasUserEdit = !upt.transactions.some(
|
|
1367
|
+
(tr) => tr.annotation(ExternalEdit)
|
|
1368
|
+
);
|
|
1369
|
+
if (upt.docChanged && wasUserEdit) {
|
|
1370
|
+
const doc = upt.state.doc;
|
|
1371
|
+
const value = doc.toString();
|
|
1372
|
+
onChange(value, upt);
|
|
1373
|
+
}
|
|
1374
|
+
})
|
|
1375
|
+
] : [];
|
|
1376
|
+
this.editorState.current = EditorState2.create({
|
|
1314
1377
|
extensions: [
|
|
1315
|
-
cypher({ lint, schema }),
|
|
1316
|
-
keymap3.of(extraKeybindings),
|
|
1317
1378
|
maybeReplMode,
|
|
1318
|
-
basicNeo4jSetup(
|
|
1379
|
+
basicNeo4jSetup(),
|
|
1380
|
+
themeCompartment.of(themeExtension),
|
|
1381
|
+
changeListener,
|
|
1382
|
+
cypher(this.schemaRef.current),
|
|
1383
|
+
keyBindingCompartment.of(keymap3.of(extraKeybindings)),
|
|
1319
1384
|
lineWrap ? EditorView4.lineWrapping : [],
|
|
1320
|
-
|
|
1385
|
+
lineNumbers({
|
|
1386
|
+
formatNumber: (a, state) => {
|
|
1387
|
+
if (state.doc.lines === 1 && this.props.prompt !== void 0) {
|
|
1388
|
+
return this.props.prompt;
|
|
1389
|
+
}
|
|
1390
|
+
return a.toString();
|
|
1391
|
+
}
|
|
1392
|
+
})
|
|
1321
1393
|
],
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1394
|
+
doc: this.props.value
|
|
1395
|
+
});
|
|
1396
|
+
this.editorView.current = new EditorView4({
|
|
1397
|
+
state: this.editorState.current,
|
|
1398
|
+
parent: this.editorContainer.current
|
|
1399
|
+
});
|
|
1400
|
+
if (this.props.autofocus) {
|
|
1401
|
+
this.focus();
|
|
1402
|
+
if (this.props.value) {
|
|
1403
|
+
this.updateCursorPosition(this.props.value.length);
|
|
1404
|
+
}
|
|
1325
1405
|
}
|
|
1326
|
-
|
|
1327
|
-
|
|
1406
|
+
}
|
|
1407
|
+
componentDidUpdate(prevProps) {
|
|
1408
|
+
if (!this.editorView.current) {
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
const currentCmValue = this.editorView.current.state?.doc.toString() ?? "";
|
|
1412
|
+
if (this.props.value !== void 0 && currentCmValue !== this.props.value) {
|
|
1413
|
+
this.editorView.current.dispatch({
|
|
1414
|
+
changes: {
|
|
1415
|
+
from: 0,
|
|
1416
|
+
to: currentCmValue.length,
|
|
1417
|
+
insert: this.props.value ?? ""
|
|
1418
|
+
},
|
|
1419
|
+
annotations: [ExternalEdit.of(true)]
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
const didChangeTheme = prevProps.theme !== this.props.theme || prevProps.overrideThemeBackgroundColor !== this.props.overrideThemeBackgroundColor;
|
|
1423
|
+
if (didChangeTheme) {
|
|
1424
|
+
this.editorView.current.dispatch({
|
|
1425
|
+
effects: themeCompartment.reconfigure(
|
|
1426
|
+
getThemeExtension(
|
|
1427
|
+
this.props.theme,
|
|
1428
|
+
this.props.overrideThemeBackgroundColor
|
|
1429
|
+
)
|
|
1430
|
+
)
|
|
1431
|
+
});
|
|
1432
|
+
}
|
|
1433
|
+
if (prevProps.extraKeybindings !== this.props.extraKeybindings) {
|
|
1434
|
+
this.editorView.current.dispatch({
|
|
1435
|
+
effects: keyBindingCompartment.reconfigure(
|
|
1436
|
+
keymap3.of(this.props.extraKeybindings)
|
|
1437
|
+
)
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
this.schemaRef.current.schema = this.props.schema;
|
|
1441
|
+
this.schemaRef.current.lint = this.props.lint;
|
|
1442
|
+
}
|
|
1443
|
+
componentWillUnmount() {
|
|
1444
|
+
this.editorView.current?.destroy();
|
|
1445
|
+
}
|
|
1446
|
+
render() {
|
|
1447
|
+
const { className, theme } = this.props;
|
|
1448
|
+
const themeClass = typeof theme === "string" ? `cm-theme-${theme}` : "cm-theme";
|
|
1449
|
+
return /* @__PURE__ */ jsx(
|
|
1450
|
+
"div",
|
|
1451
|
+
{
|
|
1452
|
+
ref: this.editorContainer,
|
|
1453
|
+
className: `${themeClass}${className ? ` ${className}` : ""}`
|
|
1454
|
+
}
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
1328
1458
|
export {
|
|
1329
1459
|
CypherEditor,
|
|
1330
1460
|
CypherParser,
|
|
1331
|
-
ReactCodemirror,
|
|
1332
1461
|
cypher,
|
|
1333
1462
|
darkThemeConstants,
|
|
1334
1463
|
lightThemeConstants,
|
|
1335
1464
|
parse
|
|
1336
1465
|
};
|
|
1466
|
+
//# sourceMappingURL=index.mjs.map
|