Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@neo4j-cypher/react-codemirror

Package Overview
Dependencies
Maintainers
0
Versions
131
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@neo4j-cypher/react-codemirror - npm Package Compare versions

Comparing version 2.0.0-canary-8399843 to 2.0.0-canary-84a12fc

dist/constants.d.ts

65

CHANGELOG.md
# @neo4j-cypher/react-codemirror
## 2.0.0-next.15
### Patch Changes
- adc5b64: using custom light color theme for the cypher editor
- Updated dependencies [88fbe63]
- Updated dependencies [22081b0]
- Updated dependencies [62ac442]
- @neo4j-cypher/language-support@2.0.0-next.12
## 2.0.0-next.14
### Patch Changes
- d85c1e0: Fixes bug with auto-completions
- Updated dependencies [bccf518]
- @neo4j-cypher/language-support@2.0.0-next.11
## 2.0.0-next.13
### Patch Changes
- Updated dependencies [8760c02]
- @neo4j-cypher/language-support@2.0.0-next.10
## 2.0.0-next.12
### Patch Changes
- dcbe67d: Expose moveFocusOnTab property on the CypherEditor component to conditionally disable tab keymappings
- e9621c8: Re-export language support from react codemirror
- Updated dependencies [2e72ac8]
- @neo4j-cypher/language-support@2.0.0-next.9
## 2.0.0-next.11
### Patch Changes
- Updated dependencies [05663bd]
- @neo4j-cypher/language-support@2.0.0-next.8
## 2.0.0-next.10
### Patch Changes
- bb7e9d3: Simplify detection and handling of value prop updates
## 2.0.0-next.9
### Patch Changes
- fbd5f7e: allow signature help panel to render below editor when there's not enough space above it
- 09dfae2: Add an ariaLabel prop to CypherEditor
- 7154e94: Fix bug causing debouncing to override value
- 62c152f: execute single line query on enter by default
- cbfc75e: Fix a bug causing debounced value updates to get cancelled erroneously
- 04ae35e: Set initial latestDispatchedValue and flush debounced changes onExecute
Add tests for debounce behaviour
- Updated dependencies [3661e9d]
- Updated dependencies [b76af58]
- Updated dependencies [21699b7]
- Updated dependencies [6afc0e3]
- Updated dependencies [39b924d]
- @neo4j-cypher/language-support@2.0.0-next.7
## 2.0.0-next.8

@@ -4,0 +69,0 @@

37

dist/CypherEditor.d.ts
import { EditorState, Extension } from '@codemirror/state';
import { EditorView, KeyBinding, ViewUpdate } from '@codemirror/view';
import type { DbSchema } from '@neo4j-cypher/language-support';
import { type DbSchema } from '@neo4j-cypher/language-support';
import { Component } from 'react';

@@ -25,2 +25,9 @@ type DomEventHandlers = Parameters<typeof EditorView.domEventHandlers>[0];

/**
* If true, pressing enter will add a new line to the editor and cmd/ctrl + enter will execute the query.
* Otherwise pressing enter on a single line will execute the query.
*
* @default false
*/
newLineOnEnter?: boolean;
/**
* The editor history navigable via up/down arrow keys. Order newest to oldest.

@@ -60,2 +67,17 @@ * Add to this list with the `onExecute` callback for REPL style history.

/**
* Whether the signature help tooltip should be shown below the text.
* If false, it will be shown above.
*
* @default true
*/
showSignatureTooltipBelow?: boolean;
/**
* Internal feature flags for the editor. Don't use in production
*
*/
featureFlags?: {
consoleCommands?: boolean;
signatureInfoOnAutoCompletions?: boolean;
};
/**
* The schema to use for autocompletion and linting.

@@ -117,2 +139,15 @@ *

readonly?: boolean;
/**
* String value to assign to the aria-label attribute of the editor.
*/
ariaLabel?: string;
/**
* Whether keybindings for inserting indents with the Tab key should be disabled.
*
* true will not create keybindings for inserting indents.
* false will create keybindings for inserting indents.
*
* @default false
*/
moveFocusOnTab?: boolean;
}

@@ -119,0 +154,0 @@ type CypherEditorState = {

import { jsx as _jsx } from "react/jsx-runtime";
import { insertNewline } from '@codemirror/commands';
import { Annotation, Compartment, EditorState, } from '@codemirror/state';

@@ -6,2 +7,3 @@ import { EditorView, keymap, lineNumbers, placeholder, } from '@codemirror/view';

import { Component, createRef } from 'react';
import { DEBOUNCE_TIME } from './constants';
import { replaceHistory, replMode as historyNavigation, } from './historyNavigation';

@@ -12,6 +14,20 @@ import { cypher } from './lang-cypher/langCypher';

import { getThemeExtension } from './themes';
const executeKeybinding = (onExecute) => onExecute
? [
{
const executeKeybinding = (onExecute, newLineOnEnter, flush) => {
const keybindings = {
'Shift-Enter': {
key: 'Shift-Enter',
run: insertNewline,
},
'Ctrl-Enter': {
key: 'Ctrl-Enter',
run: () => true,
},
Enter: {
key: 'Enter',
run: insertNewline,
},
};
if (onExecute) {
keybindings['Ctrl-Enter'] = {
key: 'Ctrl-Enter',
mac: 'Mod-Enter',

@@ -22,2 +38,3 @@ preventDefault: true,

if (doc.trim() !== '') {
flush?.();
onExecute(doc);

@@ -27,5 +44,25 @@ }

},
},
]
: [];
};
if (!newLineOnEnter) {
keybindings['Enter'] = {
key: 'Enter',
preventDefault: true,
run: (view) => {
const doc = view.state.doc.toString();
if (doc.includes('\n')) {
// Returning false means the event will mark the event
// as not handled and the default behavior will be executed
return false;
}
if (doc.trim() !== '') {
flush?.();
onExecute(doc);
}
return true;
},
};
}
}
return Object.values(keybindings);
};
const themeCompartment = new Compartment();

@@ -93,2 +130,3 @@ const keyBindingCompartment = new Compartment();

lineWrap: false,
showSignatureTooltipBelow: true,
extraKeybindings: [],

@@ -98,11 +136,20 @@ history: [],

lineNumbers: true,
newLineOnEnter: false,
moveFocusOnTab: false,
};
debouncedOnChange = this.props.onChange
? debounce(this.props.onChange, 200)
? debounce(((value, viewUpdate) => {
this.props.onChange(value, viewUpdate);
}), DEBOUNCE_TIME)
: undefined;
componentDidMount() {
const { theme, extraKeybindings, lineWrap, overrideThemeBackgroundColor, schema, lint, onExecute, } = this.props;
const { theme, extraKeybindings, lineWrap, overrideThemeBackgroundColor, schema, lint, showSignatureTooltipBelow, featureFlags, onExecute, newLineOnEnter, } = this.props;
this.schemaRef.current = {
schema,
lint,
showSignatureTooltipBelow,
featureFlags: {
consoleCommands: true,
...featureFlags,
},
useLightVersion: false,

@@ -130,5 +177,8 @@ setUseLightVersion: (newVal) => {

extensions: [
keyBindingCompartment.of(keymap.of([...executeKeybinding(onExecute), ...extraKeybindings])),
keyBindingCompartment.of(keymap.of([
...executeKeybinding(onExecute, newLineOnEnter, () => this.debouncedOnChange?.flush()),
...extraKeybindings,
])),
historyNavigation(this.props),
basicNeo4jSetup(),
basicNeo4jSetup(this.props),
themeCompartment.of(themeExtension),

@@ -146,2 +196,7 @@ changeListener,

: []),
this.props.ariaLabel
? EditorView.contentAttributes.of({
'aria-label': this.props.ariaLabel,
})
: [],
],

@@ -170,3 +225,6 @@ doc: this.props.value,

const currentCmValue = this.editorView.current.state?.doc.toString() ?? '';
if (this.props.value !== undefined && currentCmValue !== this.props.value) {
if (this.props.value !== undefined && // If the component becomes uncontolled, we just leave the value as is
this.props.value !== prevProps.value && // The value prop has changed, we need to update the editor
this.props.value !== currentCmValue // No need to dispatch an update if the value is the same
) {
this.editorView.current.dispatch({

@@ -212,3 +270,3 @@ changes: {

effects: keyBindingCompartment.reconfigure(keymap.of([
...executeKeybinding(this.props.onExecute),
...executeKeybinding(this.props.onExecute, this.props.newLineOnEnter, () => this.debouncedOnChange?.flush()),
...this.props.extraKeybindings,

@@ -241,2 +299,3 @@ ])),

this.schemaRef.current.lint = this.props.lint;
this.schemaRef.current.featureFlags = this.props.featureFlags;
}

@@ -243,0 +302,0 @@ componentWillUnmount() {

import { jsx as _jsx } from "react/jsx-runtime";
/* eslint-disable @typescript-eslint/unbound-method */
import { testData } from '@neo4j-cypher/language-support';
import { expect, test } from '@playwright/experimental-ct-react';
import { CypherEditor } from '../CypherEditor';
test.use({ viewport: { width: 500, height: 500 } });
test('hello world end 2 end test', async ({ mount }) => {

@@ -42,2 +42,20 @@ const component = await mount(_jsx(CypherEditor, { value: "hello world" }));

});
test('get completions when typing in controlled component', async ({ mount, page, }) => {
let value = '';
const onChange = (val) => {
value = val;
void component.update(_jsx(CypherEditor, { value: val, onChange: onChange }));
};
const component = await mount(_jsx(CypherEditor, { value: value, onChange: onChange }));
const textField = page.getByRole('textbox');
await textField.fill('RETU');
await page.waitForTimeout(500); // wait for debounce
await expect(page.locator('.cm-tooltip-autocomplete').getByText('RETURN')).toBeVisible();
// We need to wait for the editor to realise there is a completion open
// so that it does not just indent with tab key
await page.waitForTimeout(500);
await textField.press('Tab');
await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
await expect(component).toContainText('RETURN');
});
test('can complete labels', async ({ mount, page }) => {

@@ -53,2 +71,14 @@ const component = await mount(_jsx(CypherEditor, { schema: {

});
test('can complete properties with backticks', async ({ mount, page }) => {
const component = await mount(_jsx(CypherEditor, { schema: {
propertyKeys: ['foo bar'],
} }));
const textField = page.getByRole('textbox');
await textField.fill('MATCH (n) RETURN n.foo');
await textField.press('Escape');
await textField.press('Control+ ');
await page.locator('.cm-tooltip-autocomplete').getByText('foo bar').click();
await expect(page.locator('.cm-tooltip-autocomplete')).not.toBeVisible();
await expect(component).toContainText('MATCH (n) RETURN n.`foo bar`');
});
test('can update dbschema', async ({ mount, page }) => {

@@ -135,2 +165,112 @@ const component = await mount(_jsx(CypherEditor, { schema: {

});
async function getInfoTooltip(page, methodName) {
const infoTooltip = page.locator('.cm-completionInfo');
const firstOption = page.locator('li[aria-selected="true"]');
let selectedOption = firstOption;
while (!(await infoTooltip.textContent()).includes(methodName)) {
await page.keyboard.press('ArrowDown');
const currentSelected = page.locator('li[aria-selected="true"]');
expect(currentSelected).not.toBe(selectedOption);
expect(currentSelected).not.toBe(firstOption);
selectedOption = currentSelected;
}
return infoTooltip;
}
test('shows signature help information on auto-completion for procedures', async ({ page, mount, }) => {
await mount(_jsx(CypherEditor, { schema: testData.mockSchema, featureFlags: {
signatureInfoOnAutoCompletions: true,
} }));
const procName = 'apoc.periodic.iterate';
const procedure = testData.mockSchema.procedures[procName];
const textField = page.getByRole('textbox');
await textField.fill('CALL apoc.periodic.');
await expect(page.locator('.cm-tooltip-autocomplete')).toBeVisible();
const infoTooltip = await getInfoTooltip(page, procName);
await expect(infoTooltip).toContainText(procedure.signature);
await expect(infoTooltip).toContainText(procedure.description);
});
test('shows signature help information on auto-completion for functions', async ({ page, mount, }) => {
await mount(_jsx(CypherEditor, { schema: testData.mockSchema, featureFlags: {
signatureInfoOnAutoCompletions: true,
} }));
const fnName = 'apoc.coll.combinations';
const fn = testData.mockSchema.functions[fnName];
const textField = page.getByRole('textbox');
await textField.fill('RETURN apoc.coll.');
await expect(page.locator('.cm-tooltip-autocomplete')).toBeVisible();
const infoTooltip = await getInfoTooltip(page, fnName);
await expect(infoTooltip).toContainText(fn.signature);
await expect(infoTooltip).toContainText(fn.description);
});
test('shows deprecated procedures as strikethrough on auto-completion', async ({ page, mount, }) => {
const procName = 'apoc.trigger.resume';
await mount(_jsx(CypherEditor, { schema: {
procedures: { [procName]: testData.mockSchema.procedures[procName] },
}, featureFlags: {
signatureInfoOnAutoCompletions: true,
} }));
const textField = page.getByRole('textbox');
await textField.fill('CALL apoc.trigger.');
// We need to assert on the element having the right class
// and trusting the CSS is making this truly strikethrough
await expect(page.locator('.cm-deprecated-element')).toBeVisible();
});
test('shows deprecated function as strikethrough on auto-completion', async ({ page, mount, }) => {
const fnName = 'apoc.create.uuid';
await mount(_jsx(CypherEditor, { schema: {
functions: { [fnName]: testData.mockSchema.functions[fnName] },
}, featureFlags: {
signatureInfoOnAutoCompletions: true,
} }));
const textField = page.getByRole('textbox');
await textField.fill('RETURN apoc.create.');
// We need to assert on the element having the right class
// and trusting the CSS is making this truly strikethrough
await expect(page.locator('.cm-deprecated-element')).toBeVisible();
});
test('does not signature help information on auto-completion if docs and signature are empty', async ({ page, mount, }) => {
await mount(_jsx(CypherEditor, { schema: testData.mockSchema, featureFlags: {
signatureInfoOnAutoCompletions: true,
} }));
const textField = page.getByRole('textbox');
await textField.fill('C');
await expect(page.locator('.cm-tooltip-autocomplete')).toBeVisible();
await expect(page.locator('.cm-completionInfo')).not.toBeVisible();
});
test('shows signature help information on auto-completion if description is not empty, signature is', async ({ page, mount, }) => {
await mount(_jsx(CypherEditor, { schema: {
procedures: {
'db.ping': {
...testData.emptyProcedure,
description: 'foo',
signature: '',
name: 'db.ping',
},
},
}, featureFlags: {
signatureInfoOnAutoCompletions: true,
} }));
const textField = page.getByRole('textbox');
await textField.fill('CALL db.');
await expect(page.locator('.cm-tooltip-autocomplete')).toBeVisible();
await expect(page.locator('.cm-completionInfo')).toBeVisible();
});
test('shows signature help information on auto-completion if signature is not empty, description is', async ({ page, mount, }) => {
await mount(_jsx(CypherEditor, { schema: {
procedures: {
'db.ping': {
...testData.emptyProcedure,
description: '',
signature: 'foo',
name: 'db.ping',
},
},
}, featureFlags: {
signatureInfoOnAutoCompletions: true,
} }));
const textField = page.getByRole('textbox');
await textField.fill('CALL db.');
await expect(page.locator('.cm-tooltip-autocomplete')).toBeVisible();
await expect(page.locator('.cm-completionInfo')).toBeVisible();
});
//# sourceMappingURL=autoCompletion.spec.js.map
import { jsx as _jsx } from "react/jsx-runtime";
import { expect, test } from '@playwright/experimental-ct-react';
import { CypherEditor } from '../CypherEditor';
test.use({ viewport: { width: 500, height: 500 } });
test('prompt shows up', async ({ mount, page }) => {

@@ -73,2 +72,13 @@ const component = await mount(_jsx(CypherEditor, { prompt: "neo4j>" }));

});
test('aria-label is not set by default', async ({ mount, page }) => {
await mount(_jsx(CypherEditor, {}));
const textField = page.getByRole('textbox');
expect(await textField.getAttribute('aria-label')).toBeNull();
});
test('can set aria-label', async ({ mount, page }) => {
const ariaLabel = 'Cypher Editor';
await mount(_jsx(CypherEditor, { ariaLabel: ariaLabel }));
const textField = page.getByRole('textbox');
expect(await textField.getAttribute('aria-label')).toEqual(ariaLabel);
});
//# sourceMappingURL=configuration.spec.js.map

1

dist/e2e_tests/extraKeybindings.spec.js

@@ -5,3 +5,2 @@ import { jsx as _jsx } from "react/jsx-runtime";

import { CypherEditorPage } from './e2eUtils';
test.use({ viewport: { width: 500, height: 500 } });
test('can add extra keybinding statically', async ({ mount, page }) => {

@@ -8,0 +7,0 @@ const editorPage = new CypherEditorPage(page);

@@ -5,3 +5,2 @@ import { jsx as _jsx } from "react/jsx-runtime";

import { CypherEditorPage } from './e2eUtils';
test.use({ viewport: { width: 500, height: 500 } });
test('respects preloaded history', async ({ page, mount }) => {

@@ -19,3 +18,5 @@ const editorPage = new CypherEditorPage(page);

await expect(page.getByText('second')).toBeVisible();
// First arrow down is to get to end of line
await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowDown');
await expect(page.getByText('first')).toBeVisible();

@@ -25,4 +26,48 @@ await editorPage.getEditor().press('ArrowDown');

});
test('can execute queries and see them in history', async ({ page, mount }) => {
test('can add new lines without onExecute', async ({ page, mount }) => {
const editorPage = new CypherEditorPage(page);
const editorComponent = await mount(_jsx(CypherEditor, {}));
// Ctrl-Enter does nothing when onExecute is false
await editorPage.getEditor().press('Control+Enter');
await expect(editorComponent).toHaveText('1\n', {
useInnerText: true,
});
// Enter adds new lines
await editorPage.getEditor().fill('Brock');
await editorPage.getEditor().press('Enter');
await editorPage.getEditor().press('Enter');
await expect(editorComponent).toHaveText('1\n2\n3\nBrock', {
useInnerText: true,
});
// Shift-Enter adds new lines
await editorPage.getEditor().press('Shift+Enter');
await editorPage.getEditor().press('Shift+Enter');
await expect(editorComponent).toHaveText('1\n2\n3\n4\n5\nBrock', {
useInnerText: true,
});
});
test('can add new lines with newLineOnEnter and without onExecute', async ({ page, mount, }) => {
const editorPage = new CypherEditorPage(page);
const editorComponent = await mount(_jsx(CypherEditor, { newLineOnEnter: true }));
// Ctrl-Enter does nothing when onExecute is false
await editorPage.getEditor().press('Control+Enter');
await expect(editorComponent).toHaveText('1\n', {
useInnerText: true,
});
// Enter adds new lines
await editorPage.getEditor().fill('Brock');
await editorPage.getEditor().press('Enter');
await editorPage.getEditor().press('Enter');
await expect(editorComponent).toHaveText('1\n2\n3\nBrock', {
useInnerText: true,
});
// Shift-Enter adds new lines
await editorPage.getEditor().press('Shift+Enter');
await editorPage.getEditor().press('Shift+Enter');
await expect(editorComponent).toHaveText('1\n2\n3\n4\n5\nBrock', {
useInnerText: true,
});
});
test('can execute queries and see them in history with newLineOnEnter', async ({ page, mount, }) => {
const editorPage = new CypherEditorPage(page);
const initialValue = `MATCH (n)

@@ -34,3 +79,3 @@ RETURN n;`;

};
const editor = await mount(_jsx(CypherEditor, { value: initialValue, history: history, onExecute: onExecute }));
const editor = await mount(_jsx(CypherEditor, { value: initialValue, history: history, onExecute: onExecute, newLineOnEnter: true }));
// Execute initial query

@@ -45,3 +90,3 @@ await editorPage.getEditor().press('Control+Enter');

expect(history.length).toBe(1);
// Ensure only enter doesn't execute query
// Ensure cmd+enter is required in multiline
await editorPage.getEditor().fill('multiline');

@@ -51,3 +96,3 @@ await editorPage.getEditor().press('Enter');

await editorPage.getEditor().press('Enter');
await editorPage.getEditor().press('Enter');
await editorPage.getEditor().press('Shift+Enter');
await page.keyboard.type('entry');

@@ -74,2 +119,4 @@ expect(history.length).toBe(1);

// arrow movements don't matter until bottom is hit
await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowUp');

@@ -79,2 +126,5 @@ await editorPage.getEditor().press('ArrowUp');

await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowDown');
// editor still multiline

@@ -86,2 +136,43 @@ await expect(page.getByText('multiline')).toBeVisible();

});
test('can execute queries without newLineOnEnter', async ({ page, mount }) => {
const editorPage = new CypherEditorPage(page);
const initialValue = 'Brock';
const history = [];
const onExecute = (cmd) => {
history.unshift(cmd);
};
const editorComponent = await mount(_jsx(CypherEditor, { value: initialValue, onExecute: onExecute }));
// Cmd/Control still executes initial query
await editorPage.getEditor().press('Control+Enter');
await editorPage.getEditor().press('Meta+Enter');
expect(history.length).toBe(1);
// Ensure query execution doesn't fire if the query is only whitespace
await editorPage.getEditor().fill(' ');
await editorPage.getEditor().press('Control+Enter');
await editorPage.getEditor().press('Meta+Enter');
await editorPage.getEditor().press('Enter');
expect(history.length).toBe(1);
// Ensure enter executes query when in single line
await editorPage.getEditor().fill('Misty');
await editorPage.getEditor().press('Enter');
expect(history.length).toBe(2);
expect(history).toEqual(['Misty', 'Brock']);
// Ensure cmd+enter is required in multiline
await editorPage.getEditor().fill('multiline');
await editorPage.getEditor().press('Shift+Enter');
await editorPage.getEditor().press('Enter');
await editorPage.getEditor().press('A');
// line numbers and the text
await expect(editorComponent).toHaveText('1\n2\n3\nmultiline\nA', {
useInnerText: true,
});
await editorPage.getEditor().press('Enter');
await editorPage.getEditor().press('Enter');
await editorPage.getEditor().press('Enter');
await editorPage.getEditor().press('Enter');
expect(history.length).toBe(2);
await editorPage.getEditor().press('Control+Enter');
await editorPage.getEditor().press('Meta+Enter');
expect(history.length).toBe(3);
});
test('can navigate with cmd+up as well', async ({ page, mount }) => {

@@ -94,2 +185,3 @@ const editorPage = new CypherEditorPage(page);

await mount(_jsx(CypherEditor, { value: initialValue, history: [
'first',
`one

@@ -99,3 +191,2 @@ multiline

.`,
'second',
], onExecute: () => {

@@ -105,18 +196,18 @@ /* needed to turn on history movements */

await editorPage.getEditor().press(metaUp);
await expect(page.getByText('first')).toBeVisible();
// move in history
await editorPage.getEditor().press(metaUp);
await expect(page.getByText('multiline')).toBeVisible();
// Single meta up moves all the way to top of editor on mac
// Single meta down moves all the way to top of editor on mac
if (isMac) {
await editorPage.getEditor().press(metaUp);
await editorPage.getEditor().press(metaDown);
}
else {
await editorPage.getEditor().press('ArrowUp');
await editorPage.getEditor().press('ArrowUp');
await editorPage.getEditor().press('ArrowUp');
await editorPage.getEditor().press('ArrowUp');
await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowDown');
await editorPage.getEditor().press('ArrowDown');
}
// move in history
await editorPage.getEditor().press(metaUp);
await expect(page.getByText('second')).toBeVisible();
await editorPage.getEditor().press(metaDown);
await expect(page.getByText('multiline')).toBeVisible();
await expect(page.getByText('first')).toBeVisible();
});

@@ -123,0 +214,0 @@ test('test onExecute', async ({ page, mount }) => {

@@ -7,3 +7,4 @@ import { jsx as _jsx } from "react/jsx-runtime";

test.use({ viewport: { width: 1000, height: 500 } });
test('benchmarking & performance test session', async ({ mount, page }) => {
test('benchmarking & performance test session', async ({ browserName, mount, page, }) => {
test.skip(browserName !== 'chromium');
const client = await page.context().newCDPSession(page);

@@ -10,0 +11,0 @@ if (process.env.BENCHMARKING === 'true') {

import { jsx as _jsx } from "react/jsx-runtime";
import { expect, test } from '@playwright/experimental-ct-react';
import { CypherEditor } from '../CypherEditor';
test.use({ viewport: { width: 500, height: 500 } });
test('can mount the editor with text', async ({ mount }) => {

@@ -25,3 +24,5 @@ const component = await mount(_jsx(CypherEditor, { value: "MATCH (n) RETURN n;" }));

const textField = page.getByRole('textbox');
await textField.fill('');
await textField.fill('RETURN 12');
await expect(textField).toHaveText('RETURN 12');
// editor update is debounced, retry wait for debounced

@@ -31,6 +32,2 @@ await expect(() => {

}).toPass({ intervals: [300, 300, 1000] });
await page.keyboard.type('34');
await expect(() => {
expect(editorValueCopy).toBe('RETURN 12');
}).toPass({ intervals: [300, 300, 1000] });
});

@@ -37,0 +34,0 @@ test('can complete RETURN', async ({ page, mount }) => {

import { jsx as _jsx } from "react/jsx-runtime";
/* eslint-disable @typescript-eslint/unbound-method */
import { testData } from '@neo4j-cypher/language-support';

@@ -6,2 +7,3 @@ import { expect, test } from '@playwright/experimental-ct-react';

test.use({ viewport: { width: 1000, height: 500 } });
const importCsvProc = testData.mockSchema.procedures['apoc.import.csv'];
function testTooltip(tooltip, expectations) {

@@ -42,4 +44,5 @@ const includes = expectations.includes ?? [];

includes: [
'nodes :: LIST<MAP>',
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
testData.mockSchema.procedures['apoc.import.csv'].argumentDescription[0]
.description,
testData.mockSchema.procedures['apoc.import.csv'].description,
],

@@ -54,4 +57,4 @@ });

includes: [
'nodes :: LIST<MAP>',
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
importCsvProc.argumentDescription[0].description,
importCsvProc.description,
],

@@ -66,4 +69,4 @@ });

includes: [
'rels :: LIST<MAP>',
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
importCsvProc.argumentDescription[1].description,
importCsvProc.description,
],

@@ -78,4 +81,4 @@ });

includes: [
'rels :: LIST<MAP>',
'Imports `NODE` and `RELATIONSHIP` values with the given labels and types from the provided CSV file',
importCsvProc.argumentDescription[1].description,
importCsvProc.description,
],

@@ -157,2 +160,29 @@ });

});
test('Signature help is shown below the text by default', async ({ page, mount, }) => {
// We need to introduce new lines to make sure there's
// enough space to show the tooltip above
const query = '\n\n\n\n\n\n\nRETURN abs(';
await mount(_jsx(CypherEditor, { value: query, schema: testData.mockSchema, autofocus: true }));
await expect(page.locator('.cm-signature-help-panel.cm-tooltip-below')).toBeVisible({
timeout: 2000,
});
});
test('Setting showSignatureTooltipBelow to true shows the signature help above the text', async ({ page, mount, }) => {
// We need to introduce new lines to make sure there's
// enough space to show the tooltip above
const query = '\n\n\n\n\n\n\nRETURN abs(';
await mount(_jsx(CypherEditor, { value: query, schema: testData.mockSchema, showSignatureTooltipBelow: true, autofocus: true }));
await expect(page.locator('.cm-signature-help-panel.cm-tooltip-below')).toBeVisible({
timeout: 2000,
});
});
test('Setting showSignatureTooltipBelow to false shows the signature help above the text', async ({ page, mount, }) => {
// We need to introduce new lines to make sure there's
// enough space to show the tooltip above
const query = '\n\n\n\n\n\n\nRETURN abs(';
await mount(_jsx(CypherEditor, { value: query, schema: testData.mockSchema, showSignatureTooltipBelow: false, autofocus: true }));
await expect(page.locator('.cm-signature-help-panel.cm-tooltip-above')).toBeVisible({
timeout: 2000,
});
});
//# sourceMappingURL=signatureHelp.spec.js.map
import { jsx as _jsx } from "react/jsx-runtime";
import { expect, test } from '@playwright/experimental-ct-react';
import { CypherEditor } from '../CypherEditor';
test.use({ viewport: { width: 500, height: 500 } });
test('can complete pattern snippet', async ({ page, mount }) => {

@@ -6,0 +5,0 @@ await mount(_jsx(CypherEditor, {}));

@@ -6,3 +6,2 @@ import { jsx as _jsx } from "react/jsx-runtime";

import { CypherEditorPage } from './e2eUtils';
test.use({ viewport: { width: 500, height: 500 } });
test('light theme highlighting', async ({ page, mount }) => {

@@ -19,11 +18,11 @@ const editorPage = new CypherEditorPage(page);

const keywordcolors = await Promise.all(['MATCH', 'WHERE', 'RETURN'].map((kw) => editorPage.getHexColorOfLocator(page.getByText(kw))));
keywordcolors.every((kw) => expect(kw).toEqual(lightThemeConstants.highlightStyles.keyword));
keywordcolors.every((kw) => expect(kw).toEqual(lightThemeConstants.highlightStyles.keyword.toLowerCase()));
const labelReltype = await Promise.all(['Label', 'REL_TYPE'].map((kw) => editorPage.getHexColorOfLocator(page.getByText(kw))));
labelReltype.every((kw) => expect(kw).toEqual(lightThemeConstants.highlightStyles.label));
expect(await editorPage.getHexColorOfLocator(page.getByText('parameter'))).toEqual(lightThemeConstants.highlightStyles.paramValue);
expect(await editorPage.getHexColorOfLocator(page.getByText('property'))).toEqual(lightThemeConstants.highlightStyles.property);
expect(await editorPage.getHexColorOfLocator(page.getByText('false'))).toEqual(lightThemeConstants.highlightStyles.booleanLiteral);
expect(await editorPage.getHexColorOfLocator(page.getByText('String'))).toEqual(lightThemeConstants.highlightStyles.stringLiteral);
expect(await editorPage.getHexColorOfLocator(page.getByText('comment'))).toEqual(lightThemeConstants.highlightStyles.comment);
expect(await editorPage.getHexColorOfLocator(page.getByText('1234', { exact: true }))).toEqual(lightThemeConstants.highlightStyles.numberLiteral);
labelReltype.every((kw) => expect(kw).toEqual(lightThemeConstants.highlightStyles.label.toLowerCase()));
expect(await editorPage.getHexColorOfLocator(page.getByText('parameter'))).toEqual(lightThemeConstants.highlightStyles.paramValue.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('property'))).toEqual(lightThemeConstants.highlightStyles.property.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('false'))).toEqual(lightThemeConstants.highlightStyles.booleanLiteral.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('String'))).toEqual(lightThemeConstants.highlightStyles.stringLiteral.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('comment'))).toEqual(lightThemeConstants.highlightStyles.comment.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('1234', { exact: true }))).toEqual(lightThemeConstants.highlightStyles.numberLiteral.toLowerCase());
expect(await editorPage.editorBackgroundIsUnset()).toEqual(false);

@@ -42,11 +41,11 @@ });

const keywordcolors = await Promise.all(['MATCH', 'WHERE', 'RETURN'].map((kw) => editorPage.getHexColorOfLocator(page.getByText(kw))));
keywordcolors.every((kw) => expect(kw).toEqual(darkThemeConstants.highlightStyles.keyword));
keywordcolors.every((kw) => expect(kw).toEqual(darkThemeConstants.highlightStyles.keyword.toLowerCase()));
const labelReltype = await Promise.all(['Label', 'REL_TYPE'].map((kw) => editorPage.getHexColorOfLocator(page.getByText(kw))));
labelReltype.every((kw) => expect(kw).toEqual(darkThemeConstants.highlightStyles.label));
expect(await editorPage.getHexColorOfLocator(page.getByText('parameter'))).toEqual(darkThemeConstants.highlightStyles.paramValue);
expect(await editorPage.getHexColorOfLocator(page.getByText('property'))).toEqual(darkThemeConstants.highlightStyles.property);
expect(await editorPage.getHexColorOfLocator(page.getByText('false'))).toEqual(darkThemeConstants.highlightStyles.booleanLiteral);
expect(await editorPage.getHexColorOfLocator(page.getByText('String'))).toEqual(darkThemeConstants.highlightStyles.stringLiteral);
expect(await editorPage.getHexColorOfLocator(page.getByText('comment'))).toEqual(darkThemeConstants.highlightStyles.comment);
expect(await editorPage.getHexColorOfLocator(page.getByText('1234', { exact: true }))).toEqual(darkThemeConstants.highlightStyles.numberLiteral);
labelReltype.every((kw) => expect(kw).toEqual(darkThemeConstants.highlightStyles.label.toLowerCase()));
expect(await editorPage.getHexColorOfLocator(page.getByText('parameter'))).toEqual(darkThemeConstants.highlightStyles.paramValue.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('property'))).toEqual(darkThemeConstants.highlightStyles.property.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('false'))).toEqual(darkThemeConstants.highlightStyles.booleanLiteral.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('String'))).toEqual(darkThemeConstants.highlightStyles.stringLiteral.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('comment'))).toEqual(darkThemeConstants.highlightStyles.comment.toLowerCase());
expect(await editorPage.getHexColorOfLocator(page.getByText('1234', { exact: true }))).toEqual(darkThemeConstants.highlightStyles.numberLiteral.toLowerCase());
expect(await editorPage.editorBackgroundIsUnset()).toEqual(false);

@@ -57,5 +56,5 @@ });

const component = await mount(_jsx(CypherEditor, { theme: "light", value: "RETURN" }));
expect(await editorPage.getHexColorOfLocator(page.getByText('RETURN', { exact: true }))).toEqual(lightThemeConstants.highlightStyles.keyword);
expect(await editorPage.getHexColorOfLocator(page.getByText('RETURN', { exact: true }))).toEqual(lightThemeConstants.highlightStyles.keyword.toLowerCase());
await component.update(_jsx(CypherEditor, { theme: "dark", value: "RETURN" }));
expect(await editorPage.getHexColorOfLocator(page.getByText('RETURN', { exact: true }))).toEqual(darkThemeConstants.highlightStyles.keyword);
expect(await editorPage.getHexColorOfLocator(page.getByText('RETURN', { exact: true }))).toEqual(darkThemeConstants.highlightStyles.keyword.toLowerCase());
});

@@ -73,3 +72,3 @@ test('respects prop to allow overriding bkg color', async ({ page, mount }) => {

await mount(_jsx(CypherEditor, { theme: "light", value: query }));
expect(await editorPage.getHexColorOfLocator(page.getByText('multilinestring'))).toEqual(lightThemeConstants.highlightStyles.stringLiteral);
expect(await editorPage.getHexColorOfLocator(page.getByText('multilinestring'))).toEqual(lightThemeConstants.highlightStyles.stringLiteral.toLowerCase());
});

@@ -84,3 +83,3 @@ test('highlights multiline label correctly', async ({ page, mount }) => {

await mount(_jsx(CypherEditor, { theme: "light", value: query }));
expect(await editorPage.getHexColorOfLocator(page.getByText('Label'))).toEqual(lightThemeConstants.highlightStyles.label);
expect(await editorPage.getHexColorOfLocator(page.getByText('Label'))).toEqual(lightThemeConstants.highlightStyles.label.toLowerCase());
});

@@ -95,4 +94,4 @@ test('highlights multiline comment correctly', async ({ page, mount }) => {

await mount(_jsx(CypherEditor, { theme: "light", value: query }));
expect(await editorPage.getHexColorOfLocator(page.getByText('comment'))).toEqual(lightThemeConstants.highlightStyles.comment);
expect(await editorPage.getHexColorOfLocator(page.getByText('comment'))).toEqual(lightThemeConstants.highlightStyles.comment.toLowerCase());
});
//# sourceMappingURL=syntaxHighlighting.spec.js.map
import { jsx as _jsx } from "react/jsx-runtime";
import { testData } from '@neo4j-cypher/language-support';
import { expect, test } from '@playwright/experimental-ct-react';

@@ -46,2 +47,9 @@ import { CypherEditor } from '../CypherEditor';

});
test('Semantic errors work in firefox', async ({ browserName, page, mount, }) => {
test.skip(browserName !== 'firefox');
const editorPage = new CypherEditorPage(page);
const query = 'MATCH (n:OperationalPoint)--(m:OperationalPoint) RETURN s,m,n';
await mount(_jsx(CypherEditor, { value: query, schema: testData.mockSchema }));
await editorPage.checkErrorMessage('s,m,n', 'Variable `s` not defined');
});
test('Semantic errors are surfaced when there are no syntactic errors', async ({ page, mount, }) => {

@@ -80,2 +88,16 @@ const editorPage = new CypherEditorPage(page);

});
test('Strikethroughs are shown for deprecated functions', async ({ page, mount }) => {
const editorPage = new CypherEditorPage(page);
const query = `RETURN id()`;
await mount(_jsx(CypherEditor, { value: query, schema: testData.mockSchema }));
await expect(editorPage.page.locator('.cm-deprecated-element').last()).toBeVisible({ timeout: 3000 });
await editorPage.checkWarningMessage('id', "Function id is deprecated.");
});
test('Strikethroughs are shown for deprecated procedures', async ({ page, mount }) => {
const editorPage = new CypherEditorPage(page);
const query = `CALL apoc.create.uuids()`;
await mount(_jsx(CypherEditor, { value: query, schema: testData.mockSchema }));
await expect(editorPage.page.locator('.cm-deprecated-element').last()).toBeVisible({ timeout: 3000 });
await editorPage.checkWarningMessage('apoc.create.uuids', "Procedure apoc.create.uuids is deprecated.");
});
//# sourceMappingURL=syntaxValidation.spec.js.map

@@ -84,3 +84,3 @@ import { StateEffect } from '@codemirror/state';

effects: moveInHistory.of(direction),
selection: { anchor: view.state.doc.length },
selection: { anchor: direction === 'BACK' ? 0 : view.state.doc.length },
}));

@@ -87,0 +87,0 @@ const updatedHistory = view.state.field(historyState, false);

@@ -1,4 +0,4 @@

export { CypherParser } from '@neo4j-cypher/language-support';
export * as LanguageSupport from '@neo4j-cypher/language-support';
export { CypherEditor } from './CypherEditor';
export { cypher } from './lang-cypher/langCypher';
export { darkThemeConstants, lightThemeConstants } from './themes';

@@ -1,2 +0,2 @@

export { CypherParser } from '@neo4j-cypher/language-support';
export * as LanguageSupport from '@neo4j-cypher/language-support';
export { CypherEditor } from './CypherEditor';

@@ -3,0 +3,0 @@ export { cypher } from './lang-cypher/langCypher';

@@ -1,3 +0,6 @@

import { CompletionSource } from '@codemirror/autocomplete';
import { Completion, CompletionSource } from '@codemirror/autocomplete';
import type { CypherConfig } from './langCypher';
export declare const completionStyles: (completion: Completion & {
deprecated?: boolean;
}) => string;
export declare const cypherAutocomplete: (config: CypherConfig) => CompletionSource;

@@ -1,4 +0,5 @@

import { snippet } from '@codemirror/autocomplete';
import { snippet, } from '@codemirror/autocomplete';
import { autocomplete } from '@neo4j-cypher/language-support';
import { CompletionItemKind } from 'vscode-languageserver-types';
import { CompletionItemKind, CompletionItemTag, } from 'vscode-languageserver-types';
import { getDocString } from './utils';
const completionKindToCodemirrorIcon = (c) => {

@@ -35,6 +36,14 @@ const map = {

};
export const completionStyles = (completion) => {
if (completion.deprecated) {
return 'cm-deprecated-element';
}
else {
return null;
}
};
export const cypherAutocomplete = (config) => (context) => {
const textUntilCursor = context.state.doc.toString().slice(0, context.pos);
const documentText = context.state.doc.toString();
const triggerCharacters = ['.', ':', '{', '$', ')'];
const lastCharacter = textUntilCursor.slice(-1);
const lastCharacter = documentText.at(context.pos - 1);
const lastWord = context.matchBefore(/\w*/);

@@ -49,16 +58,55 @@ const inWord = lastWord.from !== lastWord.to;

}
const options = autocomplete(textUntilCursor, config.schema ?? {}, undefined, context.explicit);
const options = autocomplete(
// TODO This is a temporary hack because completions are not working well
documentText.slice(0, context.pos), config.schema ?? {}, context.pos, context.explicit);
return {
from: context.matchBefore(/(\w|\$)*$/).from,
options: options.map((o) => ({
label: o.label,
type: completionKindToCodemirrorIcon(o.kind),
apply: o.kind === CompletionItemKind.Snippet
? // codemirror requires an empty snippet space to be able to tab out of the completion
snippet((o.insertText ?? o.label) + '${}')
: undefined,
detail: o.detail,
})),
options: options.map((o) => {
let maybeInfo = {};
let emptyInfo = true;
const newDiv = document.createElement('div');
if (o.signature) {
const header = document.createElement('p');
header.setAttribute('class', 'cm-completionInfo-signature');
header.textContent = o.signature;
if (header.textContent.length > 0) {
emptyInfo = false;
newDiv.appendChild(header);
}
}
if (o.documentation) {
const paragraph = document.createElement('p');
paragraph.textContent = getDocString(o.documentation);
if (paragraph.textContent.length > 0) {
emptyInfo = false;
newDiv.appendChild(paragraph);
}
}
if (!emptyInfo) {
maybeInfo = {
info: () => Promise.resolve(newDiv),
};
}
const deprecated = o.tags?.find((tag) => tag === CompletionItemTag.Deprecated) ?? false;
// The negative boost moves the deprecation down the list
// so we offer the user the completions that are
// deprecated the last
const maybeDeprecated = deprecated
? { boost: -99, deprecated: true }
: {};
return {
label: o.insertText ? o.insertText : o.label,
displayLabel: o.label,
type: completionKindToCodemirrorIcon(o.kind),
apply: o.kind === CompletionItemKind.Snippet
? // codemirror requires an empty snippet space to be able to tab out of the completion
snippet((o.insertText ?? o.label) + '${}')
: undefined,
detail: o.detail,
...maybeDeprecated,
...maybeInfo,
};
}),
};
};
//# sourceMappingURL=autocomplete.js.map

@@ -35,2 +35,4 @@ import type { Facet } from '@codemirror/state';

number: NodeType;
setting: NodeType;
settingValue: NodeType;
};

@@ -37,0 +39,0 @@ export type PrismSpecificTokenType = 'class-name' | 'identifier' | 'string' | 'relationship' | 'boolean' | 'number';

@@ -40,2 +40,4 @@ import { languageDataProp } from '@codemirror/language';

number: NodeType.define({ id: 28, name: 'numberLiteral' }),
setting: NodeType.define({ id: 29, name: 'setting' }),
settingValue: NodeType.define({ id: 30, name: 'settingValue' }),
});

@@ -64,4 +66,6 @@ export const tokenTypeToStyleTag = {

consoleCommand: tags.macroName,
setting: tags.attributeName,
settingValue: tags.attributeValue,
};
export const parserAdapterNodeSet = (nodes) => new NodeSet(Object.values(nodes)).extend(styleTags(tokenTypeToStyleTag));
//# sourceMappingURL=constants.js.map
import { tags } from '@lezer/highlight';
import { applySyntaxColouring, CypherTokenType, } from '@neo4j-cypher/language-support';
import { expect, test } from 'vitest';
import { tokenTypeToStyleTag } from './constants';

@@ -4,0 +5,0 @@ const cypherQueryWithAllTokenTypes = `MATCH (variable :Label)-[:REL_TYPE]->()

@@ -79,5 +79,14 @@ import { HighlightStyle, syntaxHighlighting, } from '@codemirror/language';

},
'& .cm-signature-help-panel-arg-description': {
padding: '5px',
},
'& .cm-signature-help-panel-description': {
padding: '5px',
},
'.cm-completionInfo-signature': {
color: 'darkgrey',
},
'.cm-deprecated-element': {
'text-decoration': 'line-through',
},
'.cm-tooltip-autocomplete': {

@@ -84,0 +93,0 @@ maxWidth: '430px',

@@ -5,2 +5,6 @@ import { LanguageSupport } from '@codemirror/language';

lint?: boolean;
showSignatureTooltipBelow?: boolean;
featureFlags?: {
consoleCommands?: boolean;
};
schema?: DbSchema;

@@ -7,0 +11,0 @@ useLightVersion: boolean;

@@ -0,4 +1,5 @@

import { autocompletion } from '@codemirror/autocomplete';
import { defineLanguageFacet, Language, LanguageSupport, } from '@codemirror/language';
import { setConsoleCommandsEnabled, } from '@neo4j-cypher/language-support';
import { cypherAutocomplete } from './autocomplete';
import { _internalFeatureFlags, } from '@neo4j-cypher/language-support';
import { completionStyles, cypherAutocomplete } from './autocomplete';
import { ParserAdapter } from './parser-adapter';

@@ -12,8 +13,13 @@ import { signatureHelpTooltip } from './signatureHelp';

export function cypher(config) {
setConsoleCommandsEnabled(true);
const featureFlags = config.featureFlags;
// We allow to override the consoleCommands feature flag
if (featureFlags.consoleCommands !== undefined) {
_internalFeatureFlags.consoleCommands = featureFlags.consoleCommands;
}
const parserAdapter = new ParserAdapter(facet, config);
const cypherLanguage = new Language(facet, parserAdapter, [], 'cypher');
return new LanguageSupport(cypherLanguage, [
cypherLanguage.data.of({
autocomplete: cypherAutocomplete(config),
autocompletion({
override: [cypherAutocomplete(config)],
optionClass: completionStyles,
}),

@@ -20,0 +26,0 @@ cypherLinter(config),

@@ -5,2 +5,3 @@ import { StateField } from '@codemirror/state';

import { MarkupContent, } from 'vscode-languageserver-types';
import { getDocString } from './utils';
function getTriggerCharacter(query, caretPosition) {

@@ -16,10 +17,2 @@ let i = caretPosition - 1;

}
function getDocString(result) {
if (MarkupContent.is(result)) {
result.value;
}
else {
return result;
}
}
const createSignatureHelpElement = ({ signature, activeParameter, }) => () => {

@@ -35,7 +28,10 @@ const parameters = signature.parameters;

signatureLabel.className = 'cm-signature-help-panel-name';
signatureLabel.appendChild(document.createTextNode(`${signature.label}(`));
const methodName = signature.label.slice(0, signature.label.indexOf('('));
const returnType = signature.label.slice(signature.label.indexOf(')') + 1);
signatureLabel.appendChild(document.createTextNode(`${methodName}(`));
let currentParamDescription = undefined;
parameters.forEach((param, index) => {
if (typeof param.documentation === 'string') {
if (typeof param.label === 'string') {
const span = document.createElement('span');
span.appendChild(document.createTextNode(param.documentation));
span.appendChild(document.createTextNode(param.label));
if (index !== parameters.length - 1) {

@@ -46,2 +42,6 @@ span.appendChild(document.createTextNode(', '));

span.className = 'cm-signature-help-panel-current-argument';
const paramDoc = param.documentation;
currentParamDescription = MarkupContent.is(paramDoc)
? paramDoc.value
: paramDoc;
}

@@ -52,2 +52,3 @@ signatureLabel.appendChild(span);

signatureLabel.appendChild(document.createTextNode(')'));
signatureLabel.appendChild(document.createTextNode(returnType));
contents.appendChild(signatureLabel);

@@ -57,6 +58,12 @@ const separator = document.createElement('div');

contents.appendChild(separator);
const description = document.createElement('div');
description.className = 'cm-signature-help-panel-description';
description.appendChild(document.createTextNode(doc));
contents.appendChild(description);
if (currentParamDescription !== undefined) {
const argDescription = document.createElement('div');
argDescription.className = 'cm-signature-help-panel-arg-description';
argDescription.appendChild(document.createTextNode(currentParamDescription));
contents.appendChild(argDescription);
}
const methodDescription = document.createElement('div');
methodDescription.className = 'cm-signature-help-panel-description';
methodDescription.appendChild(document.createTextNode(doc));
contents.appendChild(methodDescription);
return { dom };

@@ -83,6 +90,7 @@ };

const signature = signatures[activeSignature];
const showSignatureTooltipBelow = config.showSignatureTooltipBelow ?? true;
result = [
{
pos: caretPosition,
above: true,
above: !showSignatureTooltipBelow,
arrow: true,

@@ -89,0 +97,0 @@ create: createSignatureHelpElement({ signature, activeParameter }),

import { linter } from '@codemirror/lint';
import { parserWrapper, validateSyntax } from '@neo4j-cypher/language-support';
import { DiagnosticSeverity } from 'vscode-languageserver-types';
import { DiagnosticSeverity, DiagnosticTag } from 'vscode-languageserver-types';
import workerpool from 'workerpool';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ignore: https://v3.vitejs.dev/guide/features.html#import-with-query-suffixes
import WorkerURL from './lintWorker?url&worker';
import WorkerURL from './lintWorker?worker&url';
const pool = workerpool.pool(WorkerURL, {

@@ -40,4 +38,3 @@ minWorkers: 2,

const statements = parse.statementsParsing;
const anySyntacticError = statements.filter((statement) => statement.diagnostics.length !== 0)
.length > 0;
const anySyntacticError = statements.some((statement) => statement.syntaxErrors.length !== 0);
if (anySyntacticError) {

@@ -53,10 +50,17 @@ return [];

const result = await lastSemanticJob;
return result.map((diag) => {
const a = result.map((diagnostic) => {
return {
from: diag.offsets.start,
to: diag.offsets.end,
severity: diag.severity === DiagnosticSeverity.Error ? 'error' : 'warning',
message: diag.message,
from: diagnostic.offsets.start,
to: diagnostic.offsets.end,
severity: diagnostic.severity === DiagnosticSeverity.Error
? 'error'
: 'warning',
message: diagnostic.message,
...(diagnostic.tags !== undefined &&
diagnostic.tags.includes(DiagnosticTag.Deprecated)
? { markClass: 'cm-deprecated-element' }
: {}),
};
});
return a;
}

@@ -63,0 +67,0 @@ catch (err) {

export declare const tokens: {
transitions: {
values: {
properties: {
default: string;
};
duration: {
quick: string;
slow: string;
};
'timing-function': {
default: string;
};
};
stripped: {
quick: string;
slow: string;
};
full: {
quick: string;
slow: string;
};
};
borderRadius: {
none: string;
sm: string;
md: string;
lg: string;
xl: string;
'1xl': string;

@@ -9,329 +36,472 @@ '2xl': string;

full: string;
lg: string;
md: string;
none: string;
sm: string;
xl: string;
};
boxShadow: {
l2: string;
l3: string;
l4: string;
l5: string;
};
breakpoints: {
'2xl': string;
xs: string;
sm: string;
md: string;
lg: string;
md: string;
sm: string;
xl: string;
xs: string;
'2xl': string;
};
palette: {
categorical: {
'1': string;
'2': string;
'3': string;
'4': string;
'5': string;
'6': string;
'7': string;
'8': string;
'9': string;
'10': string;
'11': string;
'12': string;
};
graph: {
'1': string;
'2': string;
'3': string;
'4': string;
'5': string;
'6': string;
'7': string;
'8': string;
'9': string;
'10': string;
'11': string;
'12': string;
};
};
colors: {
blueberry: {
baltic: {
'10': string;
'15': string;
'20': string;
'25': string;
'30': string;
'35': string;
'40': string;
'45': string;
'50': string;
'55': string;
'60': string;
'65': string;
'70': string;
'75': string;
'80': string;
};
danger: {
hibiscus: {
'10': string;
'15': string;
'20': string;
'25': string;
'30': string;
'35': string;
'40': string;
'45': string;
'50': string;
'55': string;
'60': string;
'65': string;
'70': string;
'75': string;
'80': string;
};
mint: {
forest: {
'10': string;
'15': string;
'20': string;
'25': string;
'30': string;
'35': string;
'40': string;
'45': string;
'50': string;
'55': string;
'60': string;
'65': string;
'70': string;
'75': string;
'80': string;
};
neutral: {
lemon: {
'10': string;
'15': string;
'20': string;
'25': string;
'30': string;
'35': string;
'40': string;
'45': string;
'50': string;
'55': string;
'60': string;
'65': string;
'70': string;
'75': string;
'80': string;
'90': string;
};
primary: {
lavender: {
'10': string;
'15': string;
'20': string;
'25': string;
'30': string;
'35': string;
'40': string;
'45': string;
'50': string;
'55': string;
'60': string;
'65': string;
'70': string;
'75': string;
'80': string;
};
success: {
marigold: {
'10': string;
'15': string;
'20': string;
'25': string;
'30': string;
'35': string;
'40': string;
'45': string;
'50': string;
'55': string;
'60': string;
'65': string;
'70': string;
'75': string;
'80': string;
};
warning: {
earth: {
'10': string;
'15': string;
'20': string;
'25': string;
'30': string;
'35': string;
'40': string;
'45': string;
'50': string;
'55': string;
'60': string;
'65': string;
'70': string;
'75': string;
'80': string;
};
};
font: {
size: {
'body-large': string;
'body-medium': string;
'body-small': string;
code: string;
h1: string;
h2: string;
h3: string;
h4: string;
h5: string;
h6: string;
label: string;
'subheading-large': string;
'subheading-medium': string;
'subheading-small': string;
neutral: {
'10': string;
'15': string;
'20': string;
'25': string;
'30': string;
'35': string;
'40': string;
'45': string;
'50': string;
'55': string;
'60': string;
'65': string;
'70': string;
'75': string;
'80': string;
};
weight: {
bold: string;
light: string;
medium: string;
normal: string;
semibold: string;
beige: {
'10': string;
'20': string;
'30': string;
'40': string;
'50': string;
'60': string;
'70': string;
};
highlights: {
yellow: string;
periwinkle: string;
};
};
palette: {
categorical: {
'1': string;
'10': string;
'11': string;
'12': string;
'2': string;
'3': string;
'4': string;
'5': string;
'6': string;
'7': string;
'8': string;
'9': string;
};
theme: {
dark: {
danger: {
bg: {
strong: string;
weak: string;
};
border: {
strong: string;
weak: string;
};
hover: {
strong: string;
weak: string;
};
icon: string;
pressed: {
strong: string;
weak: string;
};
text: string;
boxShadow: {
raised: string;
overlay: string;
};
neutral: {
bg: {
default: string;
strong: string;
strongest: string;
weak: string;
palette: {
neutral: {
text: {
weakest: string;
weaker: string;
weak: string;
default: string;
inverse: string;
};
icon: string;
bg: {
weak: string;
default: string;
strong: string;
stronger: string;
strongest: string;
status: string;
'on-bg-weak': string;
};
border: {
weak: string;
strong: string;
strongest: string;
};
hover: string;
pressed: string;
};
border: {
strong: string;
weak: string;
primary: {
text: string;
icon: string;
bg: {
weak: string;
strong: string;
status: string;
selected: string;
};
border: {
strong: string;
weak: string;
};
focus: string;
hover: {
weak: string;
strong: string;
};
pressed: {
weak: string;
strong: string;
};
};
hover: string;
icon: string;
pressed: string;
text: {
default: string;
inverse: string;
weak: string;
weaker: string;
weakest: string;
danger: {
text: string;
icon: string;
bg: {
strong: string;
weak: string;
status: string;
};
border: {
strong: string;
weak: string;
};
hover: {
weak: string;
strong: string;
};
pressed: {
weak: string;
strong: string;
};
};
};
primary: {
bg: {
strong: string;
weak: string;
warning: {
text: string;
icon: string;
bg: {
strong: string;
weak: string;
status: string;
};
border: {
strong: string;
weak: string;
};
};
border: {
strong: string;
weak: string;
success: {
text: string;
icon: string;
bg: {
strong: string;
weak: string;
status: string;
};
border: {
strong: string;
weak: string;
};
};
focus: string;
hover: {
strong: string;
weak: string;
discovery: {
text: string;
icon: string;
bg: {
strong: string;
weak: string;
status: string;
};
border: {
strong: string;
weak: string;
};
};
icon: string;
pressed: {
strong: string;
weak: string;
};
text: string;
};
success: {
bg: {
strong: string;
weak: string;
};
border: {
strong: string;
weak: string;
};
icon: string;
text: string;
};
warning: {
bg: {
strong: string;
weak: string;
};
border: {
strong: string;
weak: string;
};
icon: string;
text: string;
};
};
graph: {
'1': string;
'10': string;
'11': string;
'12': string;
'2': string;
'3': string;
'4': string;
'5': string;
'6': string;
'7': string;
'8': string;
'9': string;
};
light: {
danger: {
bg: {
strong: string;
weak: string;
};
border: {
strong: string;
weak: string;
};
hover: {
strong: string;
weak: string;
};
icon: string;
pressed: {
strong: string;
weak: string;
};
text: string;
boxShadow: {
raised: string;
overlay: string;
};
neutral: {
bg: {
default: string;
strong: string;
strongest: string;
weak: string;
palette: {
neutral: {
text: {
weakest: string;
weaker: string;
weak: string;
default: string;
inverse: string;
};
icon: string;
bg: {
weak: string;
default: string;
'on-bg-weak': string;
strong: string;
stronger: string;
strongest: string;
status: string;
};
border: {
weak: string;
strong: string;
strongest: string;
};
hover: string;
pressed: string;
};
border: {
strong: string;
weak: string;
primary: {
text: string;
icon: string;
bg: {
weak: string;
strong: string;
status: string;
selected: string;
};
border: {
strong: string;
weak: string;
};
focus: string;
hover: {
weak: string;
strong: string;
};
pressed: {
weak: string;
strong: string;
};
};
hover: string;
icon: string;
pressed: string;
text: {
default: string;
inverse: string;
weak: string;
weaker: string;
weakest: string;
danger: {
text: string;
icon: string;
bg: {
strong: string;
weak: string;
status: string;
};
border: {
strong: string;
weak: string;
};
hover: {
weak: string;
strong: string;
};
pressed: {
weak: string;
strong: string;
};
};
};
primary: {
bg: {
strong: string;
weak: string;
warning: {
text: string;
icon: string;
bg: {
strong: string;
weak: string;
status: string;
};
border: {
strong: string;
weak: string;
};
};
border: {
strong: string;
weak: string;
success: {
text: string;
icon: string;
bg: {
strong: string;
weak: string;
status: string;
};
border: {
strong: string;
weak: string;
};
};
focus: string;
hover: {
strong: string;
weak: string;
discovery: {
text: string;
icon: string;
bg: {
strong: string;
weak: string;
status: string;
};
border: {
strong: string;
weak: string;
};
};
icon: string;
pressed: {
strong: string;
weak: string;
};
text: string;
};
success: {
bg: {
strong: string;
weak: string;
};
border: {
strong: string;
weak: string;
};
icon: string;
text: string;
};
warning: {
bg: {
strong: string;
weak: string;
};
border: {
strong: string;
weak: string;
};
icon: string;
text: string;
};
};
};
font: {
size: {
h1: string;
h2: string;
h3: string;
h4: string;
h5: string;
h6: string;
'subheading-large': string;
'subheading-medium': string;
'subheading-small': string;
'body-large': string;
'body-medium': string;
'body-small': string;
code: string;
label: string;
};
weight: {
bold: string;
semibold: string;
normal: string;
medium: string;
light: string;
};
'font-family': {
h1: string;
h2: string;
h3: string;
h4: string;
h5: string;
h6: string;
'subheading-large': string;
'subheading-medium': string;
'subheading-small': string;
'body-large': string;
'body-medium': string;
'body-small': string;
code: string;
label: string;
};
};
space: {
'0': string;
'1': string;
'10': string;
'11': string;
'12': string;
'13': string;
'2': string;

@@ -345,18 +515,7 @@ '3': string;

'9': string;
'10': string;
'11': string;
'12': string;
'13': string;
};
transitions: {
default: string;
stripped: string;
values: {
duration: {
default: string;
};
properties: {
default: string;
};
'timing-function': {
default: string;
};
};
};
zIndex: {

@@ -370,13 +529,13 @@ '0': number;

'60': number;
deep: number;
auto: string;
alias: {
overlay: number;
banner: number;
blanket: number;
modal: number;
overlay: number;
popover: number;
tooltip: number;
modal: number;
};
auto: string;
deep: number;
};
};
export const tokens = {
transitions: {
values: {
properties: {
default: 'all',
},
duration: {
quick: '100ms',
slow: '250ms',
},
'timing-function': {
default: 'cubic-bezier(0.420, 0.000, 0.580, 1.000)',
},
},
stripped: {
quick: '100ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
slow: '250ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
},
full: {
quick: 'all 100ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
slow: 'all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
},
},
borderRadius: {
none: '0px',
sm: '4px',
md: '6px',
lg: '8px',
xl: '10px',
'1xl': '12px',

@@ -9,120 +36,14 @@ '2xl': '14px',

full: '9999px',
lg: '8px',
md: '6px',
none: '0px',
sm: '4px',
xl: '10px',
},
boxShadow: {
l2: '0px 1px 2px 0px rgba(12, 26, 37, 0.18)',
l3: '0px 4px 8px 0px rgba(12, 26, 37, 0.04)',
l4: '0px 4px 8px 0px rgba(12, 26, 37, 0.08)',
l5: '0px 8px 20px 0px rgba(12, 26, 37, 0.12)',
},
breakpoints: {
'2xl': '1536px',
xs: '450px',
sm: '640px',
md: '768px',
lg: '1024px',
md: '768px',
sm: '640px',
xl: '1280px',
xs: '450px',
'2xl': '1536px',
},
colors: {
blueberry: {
'10': '#E8EBF6',
'20': '#C4CCE9',
'30': '#9DABD9',
'40': '#768ACA',
'50': '#3557B4',
'60': '#25459E',
'70': '#0B297D',
},
danger: {
'10': '#ffe6e9',
'20': '#ffb8c4',
'30': '#ff668a',
'40': '#ed1252',
'50': '#cc254b',
'60': '#a1003b',
'70': '#7a0031',
},
mint: {
'10': '#F0FFFA',
'20': '#D1FFF4',
'30': '#A8FFEE',
'40': '#55F9E2',
'50': '#3DD4C5',
'60': '#2AADA5',
'70': '#116161',
},
neutral: {
'10': '#FFFFFF',
'20': '#F5F7FA',
'30': '#EEF1F6',
'40': '#E6E9EE',
'50': '#C4C8CD',
'60': '#B2B7BD',
'70': '#717780',
'80': '#535B66',
'90': '#151E29',
},
primary: {
'10': '#e6f8ff',
'20': '#a3e2ff',
'30': '#7ad1ff',
'40': '#018bff',
'50': '#006FD6',
'60': '#0056b3',
'70': '#004092',
},
success: {
'10': '#E1FAEF',
'20': '#98EDCB',
'30': '#44D4A4',
'40': '#00BA88',
'50': '#327D60',
'60': '#006E58',
'70': '#00473B',
},
warning: {
'10': '#FFFBDE',
'20': '#FFF4B5',
'30': '#FFEA8C',
'40': '#FFDE63',
'50': '#D9B54A',
'60': '#966c2e',
'70': '#664817',
},
},
font: {
size: {
'body-large': '1rem',
'body-medium': '0.875rem',
'body-small': '0.75rem',
code: '0.875rem',
h1: '3rem',
h2: '2.5rem',
h3: '1.875rem',
h4: '1.5rem',
h5: '1.25rem',
h6: '1rem',
label: '0.875rem',
'subheading-large': '1.25rem',
'subheading-medium': '1rem',
'subheading-small': '0.875rem',
},
weight: {
bold: '700',
light: '300',
medium: '500',
normal: '400',
semibold: '600',
},
},
palette: {
categorical: {
'1': '#55BDC5',
'10': '#BF732D',
'11': '#478A6E',
'12': '#ADE86B',
'2': '#4D49CB',

@@ -136,97 +57,8 @@ '3': '#DC8B39',

'9': '#DBBF40',
'10': '#BF732D',
'11': '#478A6E',
'12': '#ADE86B',
},
dark: {
danger: {
bg: {
strong: '#ffb8c4',
weak: '68, 61, 72',
},
border: {
strong: '#ffb8c4',
weak: '114, 91, 103',
},
hover: {
strong: '#ff668a',
weak: 'rgba(255, 102, 138,0.08)',
},
icon: '#ffb8c4',
pressed: {
strong: '#ff668a',
weak: 'rgba(255, 102, 138,0.12)',
},
text: '#ffb8c4',
},
neutral: {
bg: {
default: '#151E29',
strong: '45, 53, 63',
strongest: '#FFFFFF',
weak: '29, 38, 49',
},
border: {
strong: '#717780',
weak: '37, 47, 59',
},
hover: 'rgba(196, 200, 205,0.1)',
icon: '#C4C8CD',
pressed: 'rgba(196, 200, 205,0.2)',
text: {
default: '#F5F7FA',
inverse: '#151E29',
weak: '#C4C8CD',
weaker: '#B2B7BD',
weakest: '#717780',
},
},
primary: {
bg: {
strong: '#a3e2ff',
weak: '49, 69, 84',
},
border: {
strong: '#a3e2ff',
weak: '78, 108, 126',
},
focus: '#7ad1ff',
hover: {
strong: '#7ad1ff',
weak: 'rgba(122, 209, 255,0.08)',
},
icon: '#a3e2ff',
pressed: {
strong: '#7ad1ff',
weak: 'rgba(122, 209, 255,0.12)',
},
text: '#a3e2ff',
},
success: {
bg: {
strong: '#98EDCB',
weak: '47, 71, 73',
},
border: {
strong: '#98EDCB',
weak: '73, 113, 106',
},
icon: '#98EDCB',
text: '#98EDCB',
},
warning: {
bg: {
strong: '#FFEA8C',
weak: '68, 71, 60',
},
border: {
strong: '#FFEA8C',
weak: '114, 111, 80',
},
icon: '#FFEA8C',
text: '#FFEA8C',
},
},
graph: {
'1': '#FFDF81',
'10': '#FFC354',
'11': '#DA7294',
'12': '#579380',
'2': '#C990C0',

@@ -240,100 +72,438 @@ '3': '#F79767',

'9': '#4D8DDA',
'10': '#FFC354',
'11': '#DA7294',
'12': '#579380',
},
light: {
danger: {
bg: {
strong: '#cc254b',
weak: '#ffe6e9',
},
colors: {
baltic: {
'10': '#E7FAFB',
'15': '#C3F8FB',
'20': '#8FE3E8',
'25': '#5CC3C9',
'30': '#5DB3BF',
'35': '#51A6B1',
'40': '#4C99A4',
'45': '#30839D',
'50': '#0A6190',
'55': '#02507B',
'60': '#014063',
'65': '#262F31',
'70': '#081E2B',
'75': '#041823',
'80': '#01121C',
},
hibiscus: {
'10': '#FFE9E7',
'15': '#FFD7D2',
'20': '#FFAA97',
'25': '#FF8E6A',
'30': '#F96746',
'35': '#E84E2C',
'40': '#D43300',
'45': '#BB2D00',
'50': '#961200',
'55': '#730E00',
'60': '#432520',
'65': '#4E0900',
'70': '#3F0800',
'75': '#360700',
'80': '#280500',
},
forest: {
'10': '#E7FCD7',
'15': '#BCF194',
'20': '#90CB62',
'25': '#80BB53',
'30': '#6FA646',
'35': '#5B992B',
'40': '#4D8622',
'45': '#3F7824',
'50': '#296127',
'55': '#145439',
'60': '#0C4D31',
'65': '#0A4324',
'70': '#262D24',
'75': '#052618',
'80': '#021D11',
},
lemon: {
'10': '#FFFAD1',
'15': '#FFF8BD',
'20': '#FFF178',
'25': '#FFE500',
'30': '#FFD600',
'35': '#F4C318',
'40': '#D7AA0A',
'45': '#B48409',
'50': '#996E00',
'55': '#765500',
'60': '#614600',
'65': '#4D3700',
'70': '#312E1A',
'75': '#2E2100',
'80': '#251B00',
},
lavender: {
'10': '#F7F3FF',
'15': '#E9DEFF',
'20': '#CCB4FF',
'25': '#B38EFF',
'30': '#A07BEC',
'35': '#8C68D9',
'40': '#754EC8',
'45': '#5A34AA',
'50': '#4B2894',
'55': '#3B1982',
'60': '#2C2A34',
'65': '#220954',
'70': '#170146',
'75': '#0E002D',
'80': '#09001C',
},
marigold: {
'10': '#FFF0D2',
'15': '#FFDE9D',
'20': '#FFCF72',
'25': '#FFC450',
'30': '#FFB422',
'35': '#FFA901',
'40': '#EC9C00',
'45': '#DA9105',
'50': '#BA7A00',
'55': '#986400',
'60': '#795000',
'65': '#624100',
'70': '#543800',
'75': '#422C00',
'80': '#251900',
},
earth: {
'10': '#FFF7F0',
'15': '#FDEDDA',
'20': '#FFE1C5',
'25': '#F8D1AE',
'30': '#ECBF96',
'35': '#E0AE7F',
'40': '#D19660',
'45': '#AF7C4D',
'50': '#8D5D31',
'55': '#763F18',
'60': '#66310B',
'65': '#5B2B09',
'70': '#481F01',
'75': '#361700',
'80': '#220E00',
},
neutral: {
'10': '#FFFFFF',
'15': '#F5F6F6',
'20': '#E2E3E5',
'25': '#CFD1D4',
'30': '#BBBEC3',
'35': '#A8ACB2',
'40': '#959AA1',
'45': '#818790',
'50': '#6F757E',
'55': '#5E636A',
'60': '#4D5157',
'65': '#3C3F44',
'70': '#212325',
'75': '#1A1B1D',
'80': '#09090A',
},
beige: {
'10': '#FFFCF4',
'20': '#FFF7E3',
'30': '#F2EAD4',
'40': '#C1B9A0',
'50': '#999384',
'60': '#666050',
'70': '#3F3824',
},
highlights: {
yellow: '#FAFF00',
periwinkle: '#6A82FF',
},
},
theme: {
dark: {
boxShadow: {
raised: '0px 1px 2px 0px rgba(9, 9, 10, 0.50)',
overlay: '0px 8px 20px 0px rgba(9, 9, 10, 0.50)',
},
palette: {
neutral: {
text: {
weakest: '#818790',
weaker: '#A8ACB2',
weak: '#CFD1D4',
default: '#F5F6F6',
inverse: '#1A1B1D',
},
icon: '#CFD1D4',
bg: {
weak: '#212325',
default: '#1A1B1D',
strong: '#3C3F44',
stronger: '#6F757E',
strongest: '#F5F6F6',
status: '#A8ACB2',
'on-bg-weak': '#818790',
},
border: {
weak: '#3C3F44',
strong: '#6F757E',
strongest: '#BBBEC3',
},
hover: '#959AA1',
pressed: '#959AA1',
},
border: {
strong: '#cc254b',
weak: '#ffb8c4',
primary: {
text: '#8FE3E8',
icon: '#8FE3E8',
bg: {
weak: '#262F31',
strong: '#8FE3E8',
status: '#8FE3E8',
selected: '#262F31',
},
border: {
strong: '#8FE3E8',
weak: '#02507B',
},
focus: '#5DB3BF',
hover: {
weak: '#8FE3E8',
strong: '#5DB3BF',
},
pressed: {
weak: '#8FE3E8',
strong: '#4C99A4',
},
},
hover: {
strong: '#a1003b',
weak: 'rgba(237,18,82,0.08)',
danger: {
text: '#FFAA97',
icon: '#FFAA97',
bg: {
strong: '#FFAA97',
weak: '#432520',
status: '#FFAA97',
},
border: {
strong: '#FFAA97',
weak: '#730E00',
},
hover: {
weak: '#FFAA97',
strong: '#F96746',
},
pressed: {
weak: '#FFAA97',
strong: '#E84E2C',
},
},
icon: '#cc254b',
pressed: {
strong: '#7a0031',
weak: 'rgba(237,18,82,0.12)',
warning: {
text: '#FFD600',
icon: '#FFD600',
bg: {
strong: '#FFD600',
weak: '#312E1A',
status: '#FFD600',
},
border: {
strong: '#FFD600',
weak: '#765500',
},
},
text: '#cc254b',
},
neutral: {
bg: {
default: '#F5F7FA',
strong: '#E6E9EE',
strongest: '#535B66',
weak: '#FFFFFF',
success: {
text: '#90CB62',
icon: '#90CB62',
bg: {
strong: '#90CB62',
weak: '#262D24',
status: '#90CB62',
},
border: {
strong: '#90CB62',
weak: '#296127',
},
},
border: {
strong: '#C4C8CD',
weak: '#EEF1F6',
discovery: {
text: '#CCB4FF',
icon: '#CCB4FF',
bg: {
strong: '#CCB4FF',
weak: '#2C2A34',
status: '#CCB4FF',
},
border: {
strong: '#CCB4FF',
weak: '#4B2894',
},
},
hover: 'rgba(113,119,128,0.1)',
icon: '#535B66',
pressed: 'rgba(113,119,128,0.2)',
text: {
default: '#151E29',
inverse: '#FFFFFF',
weak: '#535B66',
weaker: '#717780',
weakest: '#B2B7BD',
},
},
primary: {
bg: {
strong: '#006FD6',
weak: '#e6f8ff',
},
light: {
boxShadow: {
raised: '0px 1px 2px 0px rgba(26, 27, 29, 0.18)',
overlay: '0px 4px 8px 0px rgba(26, 27, 29, 0.12)',
},
palette: {
neutral: {
text: {
weakest: '#A8ACB2',
weaker: '#5E636A',
weak: '#4D5157',
default: '#1A1B1D',
inverse: '#FFFFFF',
},
icon: '#4D5157',
bg: {
weak: '#FFFFFF',
default: '#F5F6F6',
'on-bg-weak': '#F5F6F6',
strong: '#E2E3E5',
stronger: '#A8ACB2',
strongest: '#3C3F44',
status: '#A8ACB2',
},
border: {
weak: '#E2E3E5',
strong: '#BBBEC3',
strongest: '#6F757E',
},
hover: '#6F757E',
pressed: '#6F757E',
},
border: {
strong: '#006FD6',
weak: '#7ad1ff',
primary: {
text: '#0A6190',
icon: '#0A6190',
bg: {
weak: '#E7FAFB',
strong: '#0A6190',
status: '#4C99A4',
selected: '#E7FAFB',
},
border: {
strong: '#0A6190',
weak: '#8FE3E8',
},
focus: '#30839D',
hover: {
weak: '#30839D',
strong: '#02507B',
},
pressed: {
weak: '#30839D',
strong: '#014063',
},
},
focus: '#018bff',
hover: {
strong: '#0056b3',
weak: 'rgba(1,139,255,0.08)',
danger: {
text: '#BB2D00',
icon: '#BB2D00',
bg: {
strong: '#BB2D00',
weak: '#FFE9E7',
status: '#E84E2C',
},
border: {
strong: '#BB2D00',
weak: '#FFAA97',
},
hover: {
weak: '#D43300',
strong: '#961200',
},
pressed: {
weak: '#D43300',
strong: '#730E00',
},
},
icon: '#006FD6',
pressed: {
strong: '#004092',
weak: 'rgba(1,139,255,0.12)',
warning: {
text: '#765500',
icon: '#765500',
bg: {
strong: '#765500',
weak: '#FFFAD1',
status: '#D7AA0A',
},
border: {
strong: '#996E00',
weak: '#FFD600',
},
},
text: '#006FD6',
},
success: {
bg: {
strong: '#327D60',
weak: '#E1FAEF',
success: {
text: '#3F7824',
icon: '#3F7824',
bg: {
strong: '#3F7824',
weak: '#E7FCD7',
status: '#5B992B',
},
border: {
strong: '#3F7824',
weak: '#90CB62',
},
},
border: {
strong: '#327D60',
weak: '#98EDCB',
discovery: {
text: '#5A34AA',
icon: '#5A34AA',
bg: {
strong: '#5A34AA',
weak: '#E9DEFF',
status: '#754EC8',
},
border: {
strong: '#5A34AA',
weak: '#B38EFF',
},
},
icon: '#327D60',
text: '#327D60',
},
warning: {
bg: {
strong: '#966c2e',
weak: '#FFFBDE',
},
border: {
strong: '#966c2e',
weak: '#FFEA8C',
},
icon: '#966c2e',
text: '#966c2e',
},
},
},
font: {
size: {
h1: '3rem',
h2: '2.5rem',
h3: '1.875rem',
h4: '1.5rem',
h5: '1.25rem',
h6: '1rem',
'subheading-large': '1.25rem',
'subheading-medium': '1rem',
'subheading-small': '0.875rem',
'body-large': '1rem',
'body-medium': '0.875rem',
'body-small': '0.75rem',
code: '0.875rem',
label: '0.875rem',
},
weight: {
bold: '700',
semibold: '600',
normal: '400',
medium: '500',
light: '300',
},
'font-family': {
h1: 'Syne Neo',
h2: 'Syne Neo',
h3: 'Public Sans',
h4: 'Public Sans',
h5: 'Public Sans',
h6: 'Public Sans',
'subheading-large': 'Public Sans',
'subheading-medium': 'Public Sans',
'subheading-small': 'Public Sans',
'body-large': 'Public Sans',
'body-medium': 'Public Sans',
'body-small': 'Public Sans',
code: 'Fira Code',
label: 'Public Sans',
},
},
space: {
'0': '0px',
'1': '1px',
'10': '64px',
'11': '96px',
'12': '128px',
'13': '320px',
'2': '2px',

@@ -347,18 +517,7 @@ '3': '4px',

'9': '48px',
'10': '64px',
'11': '96px',
'12': '128px',
'13': '320px',
},
transitions: {
default: 'all 100ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
stripped: '100ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
values: {
duration: {
default: '100ms',
},
properties: {
default: 'all',
},
'timing-function': {
default: 'cubic-bezier(0.420, 0.000, 0.580, 1.000)',
},
},
},
zIndex: {

@@ -372,14 +531,14 @@ '0': 0,

'60': 60,
deep: -999999,
auto: 'auto',
alias: {
overlay: 10,
banner: 20,
blanket: 30,
modal: 60,
overlay: 10,
popover: 40,
tooltip: 50,
modal: 60,
},
auto: 'auto',
deep: -999999,
},
};
//# sourceMappingURL=ndlTokensCopy.js.map
import { tokens } from '@neo4j-ndl/base';
import { expect, test } from 'vitest';
import { tokens as tokensCopy } from './ndlTokensCopy';

@@ -3,0 +4,0 @@ /*

import { Extension } from '@codemirror/state';
export declare const basicNeo4jSetup: () => Extension[];
type SetupProps = {
moveFocusOnTab?: boolean;
};
export declare const basicNeo4jSetup: ({ moveFocusOnTab, }: SetupProps) => Extension[];
export {};

@@ -27,3 +27,3 @@ import { acceptCompletion, autocompletion, clearSnippet, closeBrackets, closeBracketsKeymap, closeCompletion, completionKeymap, nextSnippetField, prevSnippetField, snippetKeymap, } from '@codemirror/autocomplete';

};
export const basicNeo4jSetup = () => {
export const basicNeo4jSetup = ({ moveFocusOnTab = false, }) => {
const keymaps = [

@@ -37,18 +37,18 @@ closeBracketsKeymap,

lintKeymap,
{
].flat();
if (!moveFocusOnTab) {
keymaps.push({
key: 'Tab',
preventDefault: true,
run: acceptCompletion,
},
{
}, {
key: 'Tab',
preventDefault: true,
run: insertTab,
},
{
}, {
key: 'Shift-Tab',
preventDefault: true,
run: indentLess,
},
].flat();
});
}
const extensions = [];

@@ -55,0 +55,0 @@ extensions.push(highlightSpecialChars());

@@ -1,26 +0,12 @@

import { light, mirage } from 'ayu';
import { mirage } from 'ayu';
import { createCypherTheme, } from './lang-cypher/createCypherTheme';
import { tokens } from './ndlTokensCopy';
/* ndl exports most tokens as hex colors but some tokens are exported as rgb colors, in the form of "10, 20, 30"
This should be fixed in version 2 of ndl.
Meanwhile we can use this function */
const convertToHex = (color) => {
if (color.startsWith('#')) {
return color;
}
const rgb = color.match(/\d+/g);
if (!rgb) {
return color;
}
const [r, g, b] = rgb;
return `#${Number(r).toString(16)}${Number(g).toString(16)}${Number(b).toString(16)}`;
};
export const lightThemeConstants = {
dark: false,
editorSettings: {
background: light.editor.bg.hex(),
foreground: light.editor.fg.hex(),
gutterForeground: light.editor.gutter.normal.hex(),
selection: light.editor.selection.active.hex(),
textMatchingSelection: light.editor.findMatch.active.hex(),
background: '#FEFEFE',
foreground: '#545454',
gutterForeground: '#a3a7ae',
selection: tokens.colors.neutral['20'],
textMatchingSelection: tokens.colors.lavender['15'],
cursor: '#000000',

@@ -33,24 +19,21 @@ autoCompletionPanel: {

searchPanel: {
background: tokens.palette.light.neutral.bg.default,
text: tokens.palette.light.neutral.text.default,
buttonHoverBackground: tokens.palette.light.neutral.bg.strong,
background: '#FEFEFE',
text: '#545454',
buttonHoverBackground: tokens.theme.light.palette.neutral.bg.strong,
},
},
highlightStyles: {
comment: light.syntax.comment.hex(),
keyword: light.syntax.keyword.hex(),
keywordLiteral: light.syntax.keyword.hex(),
label: light.syntax.markup.hex(),
predicateFunction: light.syntax.func.hex(),
function: light.syntax.func.hex(),
procedure: light.syntax.func.hex(),
stringLiteral: light.syntax.string.hex(),
numberLiteral: light.syntax.constant.hex(),
booleanLiteral: light.syntax.constant.hex(),
operator: light.syntax.operator.hex(),
property: light.syntax.tag.hex(),
paramDollar: light.syntax.regexp.hex(),
paramValue: light.syntax.regexp.hex(),
namespace: light.syntax.special.hex(),
consoleCommand: light.editor.fg.hex(),
comment: '#a3a7ae',
keyword: '#008561',
keywordLiteral: '#008561',
label: '#de064e',
predicateFunction: '#0177b8',
function: '#0177b8',
procedure: '#0177b8',
stringLiteral: '#8c6b41',
numberLiteral: '#9a4fcb',
booleanLiteral: '#9a4fcb',
operator: '#008561',
property: '#0055ae',
paramValue: '#9a4fcb',
},

@@ -73,5 +56,5 @@ };

searchPanel: {
background: convertToHex(tokens.palette.dark.neutral.bg.default),
text: convertToHex(tokens.palette.dark.neutral.text.default),
buttonHoverBackground: convertToHex(tokens.palette.dark.neutral.bg.strong),
background: tokens.theme.dark.palette.neutral.bg.default,
text: tokens.theme.dark.palette.neutral.text.default,
buttonHoverBackground: tokens.theme.dark.palette.neutral.bg.strong,
},

@@ -78,0 +61,0 @@ },

@@ -20,3 +20,3 @@ {

],
"version": "2.0.0-canary-8399843",
"version": "2.0.0-canary-84a12fc",
"main": "./dist/index.js",

@@ -29,3 +29,3 @@ "types": "./dist/index.d.ts",

"clean": "rm -rf dist",
"test": "jest",
"test": "vitest run",
"test:e2e": "playwright test -c playwright-ct.config.ts",

@@ -47,12 +47,12 @@ "test:e2e-ui": "playwright test -c playwright-ct.config.ts --ui",

"dependencies": {
"@codemirror/autocomplete": "^6.5.1",
"@codemirror/commands": "^6.2.2",
"@codemirror/language": "^6.6.0",
"@codemirror/lint": "^6.2.2",
"@codemirror/search": "^6.5.0",
"@codemirror/state": "^6.2.1",
"@codemirror/view": "^6.13.2",
"@codemirror/autocomplete": "^6.17.0",
"@codemirror/commands": "^6.6.0",
"@codemirror/language": "^6.10.2",
"@codemirror/lint": "^6.8.1",
"@codemirror/search": "^6.5.6",
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.29.1",
"@lezer/common": "^1.0.2",
"@lezer/highlight": "^1.1.3",
"@neo4j-cypher/language-support": "2.0.0-canary-8399843",
"@neo4j-cypher/language-support": "2.0.0-canary-84a12fc",
"@types/prismjs": "^1.26.3",

@@ -68,14 +68,16 @@ "@types/workerpool": "^6.4.7",

"devDependencies": {
"@neo4j-ndl/base": "^1.10.1",
"@playwright/experimental-ct-react": "^1.39.0",
"@playwright/test": "^1.36.2",
"@neo4j-ndl/base": "^3.0.10",
"@playwright/experimental-ct-react": "^1.45.3",
"@playwright/test": "^1.45.3",
"@types/lodash.debounce": "^4.0.9",
"@types/react": "^18.0.28",
"@vitejs/plugin-react": "^3.1.0",
"@vitejs/plugin-react": "^4.3.1",
"concurrently": "^8.2.1",
"esbuild": "^0.19.4",
"jsdom": "^24.1.1",
"lodash": "^4.17.21",
"playwright": "^1.36.2",
"playwright": "^1.45.3",
"react": "^18.2.0",
"typescript": "^4.9.5"
"typescript": "^4.9.5",
"vite": "^5.3.5"
},

@@ -82,0 +84,0 @@ "peerDependencies": {

@@ -100,3 +100,3 @@ import { Extension, StateEffect } from '@codemirror/state';

effects: moveInHistory.of(direction),
selection: { anchor: view.state.doc.length },
selection: { anchor: direction === 'BACK' ? 0 : view.state.doc.length },
}),

@@ -103,0 +103,0 @@ );

@@ -1,4 +0,4 @@

export { CypherParser } from '@neo4j-cypher/language-support';
export * as LanguageSupport from '@neo4j-cypher/language-support';
export { CypherEditor } from './CypherEditor';
export { cypher } from './lang-cypher/langCypher';
export { darkThemeConstants, lightThemeConstants } from './themes';

@@ -1,6 +0,14 @@

import { CompletionSource, snippet } from '@codemirror/autocomplete';
import {
Completion,
CompletionSource,
snippet,
} from '@codemirror/autocomplete';
import { autocomplete } from '@neo4j-cypher/language-support';
import { CompletionItemKind } from 'vscode-languageserver-types';
import {
CompletionItemKind,
CompletionItemTag,
} from 'vscode-languageserver-types';
import { CompletionItemIcons } from '../icons';
import type { CypherConfig } from './langCypher';
import { getDocString } from './utils';

@@ -40,8 +48,18 @@ const completionKindToCodemirrorIcon = (c: CompletionItemKind) => {

export const completionStyles: (
completion: Completion & { deprecated?: boolean },
) => string = (completion) => {
if (completion.deprecated) {
return 'cm-deprecated-element';
} else {
return null;
}
};
export const cypherAutocomplete: (config: CypherConfig) => CompletionSource =
(config) => (context) => {
const textUntilCursor = context.state.doc.toString().slice(0, context.pos);
const documentText = context.state.doc.toString();
const triggerCharacters = ['.', ':', '{', '$', ')'];
const lastCharacter = textUntilCursor.slice(-1);
const lastCharacter = documentText.at(context.pos - 1);

@@ -63,5 +81,6 @@ const lastWord = context.matchBefore(/\w*/);

const options = autocomplete(
textUntilCursor,
// TODO This is a temporary hack because completions are not working well
documentText.slice(0, context.pos),
config.schema ?? {},
undefined,
context.pos,
context.explicit,

@@ -72,13 +91,55 @@ );

from: context.matchBefore(/(\w|\$)*$/).from,
options: options.map((o) => ({
label: o.label,
type: completionKindToCodemirrorIcon(o.kind),
apply:
o.kind === CompletionItemKind.Snippet
? // codemirror requires an empty snippet space to be able to tab out of the completion
snippet((o.insertText ?? o.label) + '${}')
: undefined,
detail: o.detail,
})),
options: options.map((o) => {
let maybeInfo = {};
let emptyInfo = true;
const newDiv = document.createElement('div');
if (o.signature) {
const header = document.createElement('p');
header.setAttribute('class', 'cm-completionInfo-signature');
header.textContent = o.signature;
if (header.textContent.length > 0) {
emptyInfo = false;
newDiv.appendChild(header);
}
}
if (o.documentation) {
const paragraph = document.createElement('p');
paragraph.textContent = getDocString(o.documentation);
if (paragraph.textContent.length > 0) {
emptyInfo = false;
newDiv.appendChild(paragraph);
}
}
if (!emptyInfo) {
maybeInfo = {
info: () => Promise.resolve(newDiv),
};
}
const deprecated =
o.tags?.find((tag) => tag === CompletionItemTag.Deprecated) ?? false;
// The negative boost moves the deprecation down the list
// so we offer the user the completions that are
// deprecated the last
const maybeDeprecated = deprecated
? { boost: -99, deprecated: true }
: {};
return {
label: o.insertText ? o.insertText : o.label,
displayLabel: o.label,
type: completionKindToCodemirrorIcon(o.kind),
apply:
o.kind === CompletionItemKind.Snippet
? // codemirror requires an empty snippet space to be able to tab out of the completion
snippet((o.insertText ?? o.label) + '${}')
: undefined,
detail: o.detail,
...maybeDeprecated,
...maybeInfo,
};
}),
};
};

@@ -43,2 +43,4 @@ import { languageDataProp } from '@codemirror/language';

number: NodeType.define({ id: 28, name: 'numberLiteral' }),
setting: NodeType.define({ id: 29, name: 'setting' }),
settingValue: NodeType.define({ id: 30, name: 'settingValue' }),
});

@@ -82,2 +84,4 @@

consoleCommand: tags.macroName,
setting: tags.attributeName,
settingValue: tags.attributeValue,
};

@@ -84,0 +88,0 @@

@@ -6,2 +6,3 @@ import { tags } from '@lezer/highlight';

} from '@neo4j-cypher/language-support';
import { expect, test } from 'vitest';
import { tokenTypeToStyleTag } from './constants';

@@ -8,0 +9,0 @@

@@ -124,6 +124,14 @@ import {

},
'& .cm-signature-help-panel-arg-description': {
padding: '5px',
},
'& .cm-signature-help-panel-description': {
padding: '5px',
},
'.cm-completionInfo-signature': {
color: 'darkgrey',
},
'.cm-deprecated-element': {
'text-decoration': 'line-through',
},
'.cm-tooltip-autocomplete': {

@@ -130,0 +138,0 @@ maxWidth: '430px',

@@ -0,1 +1,2 @@

import { autocompletion } from '@codemirror/autocomplete';
import {

@@ -7,6 +8,6 @@ defineLanguageFacet,

import {
setConsoleCommandsEnabled,
_internalFeatureFlags,
type DbSchema,
} from '@neo4j-cypher/language-support';
import { cypherAutocomplete } from './autocomplete';
import { completionStyles, cypherAutocomplete } from './autocomplete';
import { ParserAdapter } from './parser-adapter';

@@ -23,2 +24,6 @@ import { signatureHelpTooltip } from './signatureHelp';

lint?: boolean;
showSignatureTooltipBelow?: boolean;
featureFlags?: {
consoleCommands?: boolean;
};
schema?: DbSchema;

@@ -30,3 +35,8 @@ useLightVersion: boolean;

export function cypher(config: CypherConfig) {
setConsoleCommandsEnabled(true);
const featureFlags = config.featureFlags;
// We allow to override the consoleCommands feature flag
if (featureFlags.consoleCommands !== undefined) {
_internalFeatureFlags.consoleCommands = featureFlags.consoleCommands;
}
const parserAdapter = new ParserAdapter(facet, config);

@@ -37,4 +47,5 @@

return new LanguageSupport(cypherLanguage, [
cypherLanguage.data.of({
autocomplete: cypherAutocomplete(config),
autocompletion({
override: [cypherAutocomplete(config)],
optionClass: completionStyles,
}),

@@ -41,0 +52,0 @@ cypherLinter(config),

@@ -9,2 +9,3 @@ import { EditorState, StateField } from '@codemirror/state';

import { CypherConfig } from './langCypher';
import { getDocString } from './utils';

@@ -24,10 +25,2 @@ function getTriggerCharacter(query: string, caretPosition: number) {

function getDocString(result: string | MarkupContent): string {
if (MarkupContent.is(result)) {
result.value;
} else {
return result;
}
}
const createSignatureHelpElement =

@@ -53,8 +46,11 @@ ({

signatureLabel.className = 'cm-signature-help-panel-name';
signatureLabel.appendChild(document.createTextNode(`${signature.label}(`));
const methodName = signature.label.slice(0, signature.label.indexOf('('));
const returnType = signature.label.slice(signature.label.indexOf(')') + 1);
signatureLabel.appendChild(document.createTextNode(`${methodName}(`));
let currentParamDescription: string | undefined = undefined;
parameters.forEach((param, index) => {
if (typeof param.documentation === 'string') {
if (typeof param.label === 'string') {
const span = document.createElement('span');
span.appendChild(document.createTextNode(param.documentation));
span.appendChild(document.createTextNode(param.label));
if (index !== parameters.length - 1) {

@@ -66,2 +62,6 @@ span.appendChild(document.createTextNode(', '));

span.className = 'cm-signature-help-panel-current-argument';
const paramDoc = param.documentation;
currentParamDescription = MarkupContent.is(paramDoc)
? paramDoc.value
: paramDoc;
}

@@ -73,2 +73,3 @@ signatureLabel.appendChild(span);

signatureLabel.appendChild(document.createTextNode(')'));
signatureLabel.appendChild(document.createTextNode(returnType));

@@ -82,8 +83,15 @@ contents.appendChild(signatureLabel);

const description = document.createElement('div');
description.className = 'cm-signature-help-panel-description';
description.appendChild(document.createTextNode(doc));
if (currentParamDescription !== undefined) {
const argDescription = document.createElement('div');
argDescription.className = 'cm-signature-help-panel-arg-description';
argDescription.appendChild(
document.createTextNode(currentParamDescription),
);
contents.appendChild(argDescription);
}
const methodDescription = document.createElement('div');
methodDescription.className = 'cm-signature-help-panel-description';
methodDescription.appendChild(document.createTextNode(doc));
contents.appendChild(methodDescription);
contents.appendChild(description);
return { dom };

@@ -120,2 +128,4 @@ };

const signature = signatures[activeSignature];
const showSignatureTooltipBelow =
config.showSignatureTooltipBelow ?? true;

@@ -125,3 +135,3 @@ result = [

pos: caretPosition,
above: true,
above: !showSignatureTooltipBelow,
arrow: true,

@@ -128,0 +138,0 @@ create: createSignatureHelpElement({ signature, activeParameter }),

import { Diagnostic, linter } from '@codemirror/lint';
import { Extension } from '@codemirror/state';
import { parserWrapper, validateSyntax } from '@neo4j-cypher/language-support';
import { DiagnosticSeverity } from 'vscode-languageserver-types';
import { DiagnosticSeverity, DiagnosticTag } from 'vscode-languageserver-types';
import workerpool from 'workerpool';
import type { CypherConfig } from './langCypher';
import type { LinterTask, LintWorker } from './lintWorker';
import WorkerURL from './lintWorker?worker&url';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ignore: https://v3.vitejs.dev/guide/features.html#import-with-query-suffixes
import WorkerURL from './lintWorker?url&worker';
const pool = workerpool.pool(WorkerURL as string, {
const pool = workerpool.pool(WorkerURL, {
minWorkers: 2,

@@ -60,5 +57,5 @@ workerOpts: { type: 'module' },

const anySyntacticError =
statements.filter((statement) => statement.diagnostics.length !== 0)
.length > 0;
const anySyntacticError = statements.some(
(statement) => statement.syntaxErrors.length !== 0,
);

@@ -81,11 +78,18 @@ if (anySyntacticError) {

return result.map((diag) => {
const a: Diagnostic[] = result.map((diagnostic) => {
return {
from: diag.offsets.start,
to: diag.offsets.end,
from: diagnostic.offsets.start,
to: diagnostic.offsets.end,
severity:
diag.severity === DiagnosticSeverity.Error ? 'error' : 'warning',
message: diag.message,
diagnostic.severity === DiagnosticSeverity.Error
? 'error'
: 'warning',
message: diagnostic.message,
...(diagnostic.tags !== undefined &&
diagnostic.tags.includes(DiagnosticTag.Deprecated)
? { markClass: 'cm-deprecated-element' }
: {}),
};
});
return a;
} catch (err) {

@@ -92,0 +96,0 @@ if (!(err instanceof workerpool.Promise.CancellationError)) {

import { tokens } from '@neo4j-ndl/base';
import { expect, test } from 'vitest';
import { tokens as tokensCopy } from './ndlTokensCopy';

@@ -3,0 +4,0 @@

export const tokens = {
transitions: {
values: {
properties: {
default: 'all',
},
duration: {
quick: '100ms',
slow: '250ms',
},
'timing-function': {
default: 'cubic-bezier(0.420, 0.000, 0.580, 1.000)',
},
},
stripped: {
quick: '100ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
slow: '250ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
},
full: {
quick: 'all 100ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
slow: 'all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
},
},
borderRadius: {
none: '0px',
sm: '4px',
md: '6px',
lg: '8px',
xl: '10px',
'1xl': '12px',

@@ -9,120 +36,14 @@ '2xl': '14px',

full: '9999px',
lg: '8px',
md: '6px',
none: '0px',
sm: '4px',
xl: '10px',
},
boxShadow: {
l2: '0px 1px 2px 0px rgba(12, 26, 37, 0.18)',
l3: '0px 4px 8px 0px rgba(12, 26, 37, 0.04)',
l4: '0px 4px 8px 0px rgba(12, 26, 37, 0.08)',
l5: '0px 8px 20px 0px rgba(12, 26, 37, 0.12)',
},
breakpoints: {
'2xl': '1536px',
xs: '450px',
sm: '640px',
md: '768px',
lg: '1024px',
md: '768px',
sm: '640px',
xl: '1280px',
xs: '450px',
'2xl': '1536px',
},
colors: {
blueberry: {
'10': '#E8EBF6',
'20': '#C4CCE9',
'30': '#9DABD9',
'40': '#768ACA',
'50': '#3557B4',
'60': '#25459E',
'70': '#0B297D',
},
danger: {
'10': '#ffe6e9',
'20': '#ffb8c4',
'30': '#ff668a',
'40': '#ed1252',
'50': '#cc254b',
'60': '#a1003b',
'70': '#7a0031',
},
mint: {
'10': '#F0FFFA',
'20': '#D1FFF4',
'30': '#A8FFEE',
'40': '#55F9E2',
'50': '#3DD4C5',
'60': '#2AADA5',
'70': '#116161',
},
neutral: {
'10': '#FFFFFF',
'20': '#F5F7FA',
'30': '#EEF1F6',
'40': '#E6E9EE',
'50': '#C4C8CD',
'60': '#B2B7BD',
'70': '#717780',
'80': '#535B66',
'90': '#151E29',
},
primary: {
'10': '#e6f8ff',
'20': '#a3e2ff',
'30': '#7ad1ff',
'40': '#018bff',
'50': '#006FD6',
'60': '#0056b3',
'70': '#004092',
},
success: {
'10': '#E1FAEF',
'20': '#98EDCB',
'30': '#44D4A4',
'40': '#00BA88',
'50': '#327D60',
'60': '#006E58',
'70': '#00473B',
},
warning: {
'10': '#FFFBDE',
'20': '#FFF4B5',
'30': '#FFEA8C',
'40': '#FFDE63',
'50': '#D9B54A',
'60': '#966c2e',
'70': '#664817',
},
},
font: {
size: {
'body-large': '1rem',
'body-medium': '0.875rem',
'body-small': '0.75rem',
code: '0.875rem',
h1: '3rem',
h2: '2.5rem',
h3: '1.875rem',
h4: '1.5rem',
h5: '1.25rem',
h6: '1rem',
label: '0.875rem',
'subheading-large': '1.25rem',
'subheading-medium': '1rem',
'subheading-small': '0.875rem',
},
weight: {
bold: '700',
light: '300',
medium: '500',
normal: '400',
semibold: '600',
},
},
palette: {
categorical: {
'1': '#55BDC5',
'10': '#BF732D',
'11': '#478A6E',
'12': '#ADE86B',
'2': '#4D49CB',

@@ -136,97 +57,8 @@ '3': '#DC8B39',

'9': '#DBBF40',
'10': '#BF732D',
'11': '#478A6E',
'12': '#ADE86B',
},
dark: {
danger: {
bg: {
strong: '#ffb8c4',
weak: '68, 61, 72',
},
border: {
strong: '#ffb8c4',
weak: '114, 91, 103',
},
hover: {
strong: '#ff668a',
weak: 'rgba(255, 102, 138,0.08)',
},
icon: '#ffb8c4',
pressed: {
strong: '#ff668a',
weak: 'rgba(255, 102, 138,0.12)',
},
text: '#ffb8c4',
},
neutral: {
bg: {
default: '#151E29',
strong: '45, 53, 63',
strongest: '#FFFFFF',
weak: '29, 38, 49',
},
border: {
strong: '#717780',
weak: '37, 47, 59',
},
hover: 'rgba(196, 200, 205,0.1)',
icon: '#C4C8CD',
pressed: 'rgba(196, 200, 205,0.2)',
text: {
default: '#F5F7FA',
inverse: '#151E29',
weak: '#C4C8CD',
weaker: '#B2B7BD',
weakest: '#717780',
},
},
primary: {
bg: {
strong: '#a3e2ff',
weak: '49, 69, 84',
},
border: {
strong: '#a3e2ff',
weak: '78, 108, 126',
},
focus: '#7ad1ff',
hover: {
strong: '#7ad1ff',
weak: 'rgba(122, 209, 255,0.08)',
},
icon: '#a3e2ff',
pressed: {
strong: '#7ad1ff',
weak: 'rgba(122, 209, 255,0.12)',
},
text: '#a3e2ff',
},
success: {
bg: {
strong: '#98EDCB',
weak: '47, 71, 73',
},
border: {
strong: '#98EDCB',
weak: '73, 113, 106',
},
icon: '#98EDCB',
text: '#98EDCB',
},
warning: {
bg: {
strong: '#FFEA8C',
weak: '68, 71, 60',
},
border: {
strong: '#FFEA8C',
weak: '114, 111, 80',
},
icon: '#FFEA8C',
text: '#FFEA8C',
},
},
graph: {
'1': '#FFDF81',
'10': '#FFC354',
'11': '#DA7294',
'12': '#579380',
'2': '#C990C0',

@@ -240,100 +72,438 @@ '3': '#F79767',

'9': '#4D8DDA',
'10': '#FFC354',
'11': '#DA7294',
'12': '#579380',
},
light: {
danger: {
bg: {
strong: '#cc254b',
weak: '#ffe6e9',
},
colors: {
baltic: {
'10': '#E7FAFB',
'15': '#C3F8FB',
'20': '#8FE3E8',
'25': '#5CC3C9',
'30': '#5DB3BF',
'35': '#51A6B1',
'40': '#4C99A4',
'45': '#30839D',
'50': '#0A6190',
'55': '#02507B',
'60': '#014063',
'65': '#262F31',
'70': '#081E2B',
'75': '#041823',
'80': '#01121C',
},
hibiscus: {
'10': '#FFE9E7',
'15': '#FFD7D2',
'20': '#FFAA97',
'25': '#FF8E6A',
'30': '#F96746',
'35': '#E84E2C',
'40': '#D43300',
'45': '#BB2D00',
'50': '#961200',
'55': '#730E00',
'60': '#432520',
'65': '#4E0900',
'70': '#3F0800',
'75': '#360700',
'80': '#280500',
},
forest: {
'10': '#E7FCD7',
'15': '#BCF194',
'20': '#90CB62',
'25': '#80BB53',
'30': '#6FA646',
'35': '#5B992B',
'40': '#4D8622',
'45': '#3F7824',
'50': '#296127',
'55': '#145439',
'60': '#0C4D31',
'65': '#0A4324',
'70': '#262D24',
'75': '#052618',
'80': '#021D11',
},
lemon: {
'10': '#FFFAD1',
'15': '#FFF8BD',
'20': '#FFF178',
'25': '#FFE500',
'30': '#FFD600',
'35': '#F4C318',
'40': '#D7AA0A',
'45': '#B48409',
'50': '#996E00',
'55': '#765500',
'60': '#614600',
'65': '#4D3700',
'70': '#312E1A',
'75': '#2E2100',
'80': '#251B00',
},
lavender: {
'10': '#F7F3FF',
'15': '#E9DEFF',
'20': '#CCB4FF',
'25': '#B38EFF',
'30': '#A07BEC',
'35': '#8C68D9',
'40': '#754EC8',
'45': '#5A34AA',
'50': '#4B2894',
'55': '#3B1982',
'60': '#2C2A34',
'65': '#220954',
'70': '#170146',
'75': '#0E002D',
'80': '#09001C',
},
marigold: {
'10': '#FFF0D2',
'15': '#FFDE9D',
'20': '#FFCF72',
'25': '#FFC450',
'30': '#FFB422',
'35': '#FFA901',
'40': '#EC9C00',
'45': '#DA9105',
'50': '#BA7A00',
'55': '#986400',
'60': '#795000',
'65': '#624100',
'70': '#543800',
'75': '#422C00',
'80': '#251900',
},
earth: {
'10': '#FFF7F0',
'15': '#FDEDDA',
'20': '#FFE1C5',
'25': '#F8D1AE',
'30': '#ECBF96',
'35': '#E0AE7F',
'40': '#D19660',
'45': '#AF7C4D',
'50': '#8D5D31',
'55': '#763F18',
'60': '#66310B',
'65': '#5B2B09',
'70': '#481F01',
'75': '#361700',
'80': '#220E00',
},
neutral: {
'10': '#FFFFFF',
'15': '#F5F6F6',
'20': '#E2E3E5',
'25': '#CFD1D4',
'30': '#BBBEC3',
'35': '#A8ACB2',
'40': '#959AA1',
'45': '#818790',
'50': '#6F757E',
'55': '#5E636A',
'60': '#4D5157',
'65': '#3C3F44',
'70': '#212325',
'75': '#1A1B1D',
'80': '#09090A',
},
beige: {
'10': '#FFFCF4',
'20': '#FFF7E3',
'30': '#F2EAD4',
'40': '#C1B9A0',
'50': '#999384',
'60': '#666050',
'70': '#3F3824',
},
highlights: {
yellow: '#FAFF00',
periwinkle: '#6A82FF',
},
},
theme: {
dark: {
boxShadow: {
raised: '0px 1px 2px 0px rgba(9, 9, 10, 0.50)',
overlay: '0px 8px 20px 0px rgba(9, 9, 10, 0.50)',
},
palette: {
neutral: {
text: {
weakest: '#818790',
weaker: '#A8ACB2',
weak: '#CFD1D4',
default: '#F5F6F6',
inverse: '#1A1B1D',
},
icon: '#CFD1D4',
bg: {
weak: '#212325',
default: '#1A1B1D',
strong: '#3C3F44',
stronger: '#6F757E',
strongest: '#F5F6F6',
status: '#A8ACB2',
'on-bg-weak': '#818790',
},
border: {
weak: '#3C3F44',
strong: '#6F757E',
strongest: '#BBBEC3',
},
hover: '#959AA1',
pressed: '#959AA1',
},
border: {
strong: '#cc254b',
weak: '#ffb8c4',
primary: {
text: '#8FE3E8',
icon: '#8FE3E8',
bg: {
weak: '#262F31',
strong: '#8FE3E8',
status: '#8FE3E8',
selected: '#262F31',
},
border: {
strong: '#8FE3E8',
weak: '#02507B',
},
focus: '#5DB3BF',
hover: {
weak: '#8FE3E8',
strong: '#5DB3BF',
},
pressed: {
weak: '#8FE3E8',
strong: '#4C99A4',
},
},
hover: {
strong: '#a1003b',
weak: 'rgba(237,18,82,0.08)',
danger: {
text: '#FFAA97',
icon: '#FFAA97',
bg: {
strong: '#FFAA97',
weak: '#432520',
status: '#FFAA97',
},
border: {
strong: '#FFAA97',
weak: '#730E00',
},
hover: {
weak: '#FFAA97',
strong: '#F96746',
},
pressed: {
weak: '#FFAA97',
strong: '#E84E2C',
},
},
icon: '#cc254b',
pressed: {
strong: '#7a0031',
weak: 'rgba(237,18,82,0.12)',
warning: {
text: '#FFD600',
icon: '#FFD600',
bg: {
strong: '#FFD600',
weak: '#312E1A',
status: '#FFD600',
},
border: {
strong: '#FFD600',
weak: '#765500',
},
},
text: '#cc254b',
},
neutral: {
bg: {
default: '#F5F7FA',
strong: '#E6E9EE',
strongest: '#535B66',
weak: '#FFFFFF',
success: {
text: '#90CB62',
icon: '#90CB62',
bg: {
strong: '#90CB62',
weak: '#262D24',
status: '#90CB62',
},
border: {
strong: '#90CB62',
weak: '#296127',
},
},
border: {
strong: '#C4C8CD',
weak: '#EEF1F6',
discovery: {
text: '#CCB4FF',
icon: '#CCB4FF',
bg: {
strong: '#CCB4FF',
weak: '#2C2A34',
status: '#CCB4FF',
},
border: {
strong: '#CCB4FF',
weak: '#4B2894',
},
},
hover: 'rgba(113,119,128,0.1)',
icon: '#535B66',
pressed: 'rgba(113,119,128,0.2)',
text: {
default: '#151E29',
inverse: '#FFFFFF',
weak: '#535B66',
weaker: '#717780',
weakest: '#B2B7BD',
},
},
primary: {
bg: {
strong: '#006FD6',
weak: '#e6f8ff',
},
light: {
boxShadow: {
raised: '0px 1px 2px 0px rgba(26, 27, 29, 0.18)',
overlay: '0px 4px 8px 0px rgba(26, 27, 29, 0.12)',
},
palette: {
neutral: {
text: {
weakest: '#A8ACB2',
weaker: '#5E636A',
weak: '#4D5157',
default: '#1A1B1D',
inverse: '#FFFFFF',
},
icon: '#4D5157',
bg: {
weak: '#FFFFFF',
default: '#F5F6F6',
'on-bg-weak': '#F5F6F6',
strong: '#E2E3E5',
stronger: '#A8ACB2',
strongest: '#3C3F44',
status: '#A8ACB2',
},
border: {
weak: '#E2E3E5',
strong: '#BBBEC3',
strongest: '#6F757E',
},
hover: '#6F757E',
pressed: '#6F757E',
},
border: {
strong: '#006FD6',
weak: '#7ad1ff',
primary: {
text: '#0A6190',
icon: '#0A6190',
bg: {
weak: '#E7FAFB',
strong: '#0A6190',
status: '#4C99A4',
selected: '#E7FAFB',
},
border: {
strong: '#0A6190',
weak: '#8FE3E8',
},
focus: '#30839D',
hover: {
weak: '#30839D',
strong: '#02507B',
},
pressed: {
weak: '#30839D',
strong: '#014063',
},
},
focus: '#018bff',
hover: {
strong: '#0056b3',
weak: 'rgba(1,139,255,0.08)',
danger: {
text: '#BB2D00',
icon: '#BB2D00',
bg: {
strong: '#BB2D00',
weak: '#FFE9E7',
status: '#E84E2C',
},
border: {
strong: '#BB2D00',
weak: '#FFAA97',
},
hover: {
weak: '#D43300',
strong: '#961200',
},
pressed: {
weak: '#D43300',
strong: '#730E00',
},
},
icon: '#006FD6',
pressed: {
strong: '#004092',
weak: 'rgba(1,139,255,0.12)',
warning: {
text: '#765500',
icon: '#765500',
bg: {
strong: '#765500',
weak: '#FFFAD1',
status: '#D7AA0A',
},
border: {
strong: '#996E00',
weak: '#FFD600',
},
},
text: '#006FD6',
},
success: {
bg: {
strong: '#327D60',
weak: '#E1FAEF',
success: {
text: '#3F7824',
icon: '#3F7824',
bg: {
strong: '#3F7824',
weak: '#E7FCD7',
status: '#5B992B',
},
border: {
strong: '#3F7824',
weak: '#90CB62',
},
},
border: {
strong: '#327D60',
weak: '#98EDCB',
discovery: {
text: '#5A34AA',
icon: '#5A34AA',
bg: {
strong: '#5A34AA',
weak: '#E9DEFF',
status: '#754EC8',
},
border: {
strong: '#5A34AA',
weak: '#B38EFF',
},
},
icon: '#327D60',
text: '#327D60',
},
warning: {
bg: {
strong: '#966c2e',
weak: '#FFFBDE',
},
border: {
strong: '#966c2e',
weak: '#FFEA8C',
},
icon: '#966c2e',
text: '#966c2e',
},
},
},
font: {
size: {
h1: '3rem',
h2: '2.5rem',
h3: '1.875rem',
h4: '1.5rem',
h5: '1.25rem',
h6: '1rem',
'subheading-large': '1.25rem',
'subheading-medium': '1rem',
'subheading-small': '0.875rem',
'body-large': '1rem',
'body-medium': '0.875rem',
'body-small': '0.75rem',
code: '0.875rem',
label: '0.875rem',
},
weight: {
bold: '700',
semibold: '600',
normal: '400',
medium: '500',
light: '300',
},
'font-family': {
h1: 'Syne Neo',
h2: 'Syne Neo',
h3: 'Public Sans',
h4: 'Public Sans',
h5: 'Public Sans',
h6: 'Public Sans',
'subheading-large': 'Public Sans',
'subheading-medium': 'Public Sans',
'subheading-small': 'Public Sans',
'body-large': 'Public Sans',
'body-medium': 'Public Sans',
'body-small': 'Public Sans',
code: 'Fira Code',
label: 'Public Sans',
},
},
space: {
'0': '0px',
'1': '1px',
'10': '64px',
'11': '96px',
'12': '128px',
'13': '320px',
'2': '2px',

@@ -347,18 +517,7 @@ '3': '4px',

'9': '48px',
'10': '64px',
'11': '96px',
'12': '128px',
'13': '320px',
},
transitions: {
default: 'all 100ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
stripped: '100ms cubic-bezier(0.420, 0.000, 0.580, 1.000)',
values: {
duration: {
default: '100ms',
},
properties: {
default: 'all',
},
'timing-function': {
default: 'cubic-bezier(0.420, 0.000, 0.580, 1.000)',
},
},
},
zIndex: {

@@ -372,13 +531,13 @@ '0': 0,

'60': 60,
deep: -999999,
auto: 'auto',
alias: {
overlay: 10,
banner: 20,
blanket: 30,
modal: 60,
overlay: 10,
popover: 40,
tooltip: 50,
modal: 60,
},
auto: 'auto',
deep: -999999,
},
};
import { Extension } from '@codemirror/state';
import { light, mirage } from 'ayu';
import { mirage } from 'ayu';
import {

@@ -9,28 +9,10 @@ createCypherTheme,

/* ndl exports most tokens as hex colors but some tokens are exported as rgb colors, in the form of "10, 20, 30"
This should be fixed in version 2 of ndl.
Meanwhile we can use this function */
const convertToHex = (color: string) => {
if (color.startsWith('#')) {
return color;
}
const rgb = color.match(/\d+/g);
if (!rgb) {
return color;
}
const [r, g, b] = rgb;
return `#${Number(r).toString(16)}${Number(g).toString(16)}${Number(
b,
).toString(16)}`;
};
export const lightThemeConstants: ThemeOptions = {
dark: false,
editorSettings: {
background: light.editor.bg.hex(),
foreground: light.editor.fg.hex(),
gutterForeground: light.editor.gutter.normal.hex(),
selection: light.editor.selection.active.hex(),
textMatchingSelection: light.editor.findMatch.active.hex(),
background: '#FEFEFE',
foreground: '#545454',
gutterForeground: '#a3a7ae',
selection: tokens.colors.neutral['20'],
textMatchingSelection: tokens.colors.lavender['15'],
cursor: '#000000',

@@ -43,24 +25,21 @@ autoCompletionPanel: {

searchPanel: {
background: tokens.palette.light.neutral.bg.default,
text: tokens.palette.light.neutral.text.default,
buttonHoverBackground: tokens.palette.light.neutral.bg.strong,
background: '#FEFEFE',
text: '#545454',
buttonHoverBackground: tokens.theme.light.palette.neutral.bg.strong,
},
},
highlightStyles: {
comment: light.syntax.comment.hex(),
keyword: light.syntax.keyword.hex(),
keywordLiteral: light.syntax.keyword.hex(),
label: light.syntax.markup.hex(),
predicateFunction: light.syntax.func.hex(),
function: light.syntax.func.hex(),
procedure: light.syntax.func.hex(),
stringLiteral: light.syntax.string.hex(),
numberLiteral: light.syntax.constant.hex(),
booleanLiteral: light.syntax.constant.hex(),
operator: light.syntax.operator.hex(),
property: light.syntax.tag.hex(),
paramDollar: light.syntax.regexp.hex(),
paramValue: light.syntax.regexp.hex(),
namespace: light.syntax.special.hex(),
consoleCommand: light.editor.fg.hex(),
comment: '#a3a7ae',
keyword: '#008561',
keywordLiteral: '#008561',
label: '#de064e',
predicateFunction: '#0177b8',
function: '#0177b8',
procedure: '#0177b8',
stringLiteral: '#8c6b41',
numberLiteral: '#9a4fcb',
booleanLiteral: '#9a4fcb',
operator: '#008561',
property: '#0055ae',
paramValue: '#9a4fcb',
},

@@ -84,7 +63,5 @@ };

searchPanel: {
background: convertToHex(tokens.palette.dark.neutral.bg.default),
text: convertToHex(tokens.palette.dark.neutral.text.default),
buttonHoverBackground: convertToHex(
tokens.palette.dark.neutral.bg.strong,
),
background: tokens.theme.dark.palette.neutral.bg.default,
text: tokens.theme.dark.palette.neutral.text.default,
buttonHoverBackground: tokens.theme.dark.palette.neutral.bg.strong,
},

@@ -91,0 +68,0 @@ },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc