diff --git a/README.md b/README.md index 1545092..1f2e00c 100644 --- a/README.md +++ b/README.md @@ -40,57 +40,28 @@ https://github.com/tidbcloud/tisqleditor/assets/1284531/732b600f-5b4e-45d3-a3d2- See [editor.tsx](./packages/playground/src/components/biz/editor-panel/editor.tsx) or [editor-example.tsx](./packages/playground/src/examples/editor-example.tsx) to get more details. +```shell +pnpm add @tidbcloud/tisqleditor-react @tidbcloud/codemirror-extension-themes @tidbcloud/codemirror-extension-cur-sql-gutter +``` + ```tsx import { SQLEditor } from '@tidbcloud/tisqleditor-react' -import { bbedit, oneDark } from '@tidbcloud/codemirror-extension-themes' -import { saveHelper } from '@tidbcloud/codemirror-extension-save-helper' +import { oneDark } from '@tidbcloud/codemirror-extension-themes' import { curSqlGutter } from '@tidbcloud/codemirror-extension-cur-sql-gutter' -import { - useDbLinter, - fullWidthCharLinter -} from '@tidbcloud/codemirror-extension-linters' -import { sqlAutoCompletion } from '@tidbcloud/codemirror-extension-sql-autocomplete' -import { - aiWidget, - isUnifiedMergeViewActive -} from '@tidbcloud/codemirror-extension-ai-widget' export function Editor() { - const extraExts = [ - saveHelper({ - save: (view: EditorView) => { - saveFile(activeFile.id, view.state.doc.toString()) - } - }), - sqlAutoCompletion(), - curSqlGutter({ - whenHide: (view) => { - return isUnifiedMergeViewActive(view.state) - } - }), - useDbLinter(), - fullWidthCharLinter(), - aiWidget({ - chat(view, chatId, req) { - return chatCtx.chat(chatId, req) - }, - cancelChat: chatCtx.cancelChat, - onEvent(_view, type, payload) { - chatCtx.onEvent(type, payload) - }, - getDbList: getDbListRef.current! - }) - ] - return ( ) } @@ -127,6 +98,10 @@ Before you create a pull request, please check whether your commits comply with - refactor: any code related change that is not a fix nor a feature - chore: all changes to the repository that do not fit into any of the above categories +### Test + +To run the test, execute the command `pnpm test` + ### Release - Checkout from the latest main branch. diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index edfcea5..e68aa9c 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,15 @@ # @tidbcloud/tisqleditor +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params +- Updated dependencies [122f217] + - @tidbcloud/codemirror-extension-basic-setup@0.0.4 + - @tidbcloud/codemirror-extension-cur-sql@0.0.4 + - @tidbcloud/codemirror-extension-sql-parser@0.0.4 + ## 0.0.3 ### Patch Changes diff --git a/packages/core/README.md b/packages/core/README.md index db79a91..8fd89e2 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -2,7 +2,7 @@ This package provides the `SQLEditorInstance` and `EditorCache` implementation. -`SQLEditorInstance` creates EditorView instance with pre-configured extensions to make it available to edit SQL code. +`SQLEditorInstance` creates EditorView instance with pre-configured extensions to make it available to edit SQL code, likes `@codemirror/lang-sql`, `@tidbcloud/codemirror-extension-sql-parser`, `@tidbcloud/codemirror-extension-cur-sql`. `EditorCache` stores the `SQLEditorInstance` in a map. @@ -33,6 +33,14 @@ const editorInst = createSQLEditorInstance({ cache.addEditor(editorId, editorInst) ``` +The package installs the cur-sql and sql-parser extensions default, can use the following methods: + +```ts +const curSql = editorInst.getCurStatements() +const allSqls = editorInst.getAllStatements() +const nearbySql = editorInst.getNearbyStatement() +``` + ## API ### createSQLEditorInstance diff --git a/packages/core/package.json b/packages/core/package.json index fef6d9c..6ed85b8 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/tisqleditor", - "version": "0.0.3", + "version": "0.0.4", "description": "editor instance and editor cache", "type": "module", "main": "dist/index.js", diff --git a/packages/core/src/test/cache.test.ts b/packages/core/src/test/cache.test.ts index da23f4a..a842f81 100644 --- a/packages/core/src/test/cache.test.ts +++ b/packages/core/src/test/cache.test.ts @@ -1,26 +1,36 @@ import { createSQLEditorInstance, EditorCache } from '..' -test('editor instance cache works fine', () => { +describe('editor instance cache works fine', () => { const cache = new EditorCache() const editorInst = createSQLEditorInstance({ editorId: '111', doc: 'select * from test;' }) - expect(cache.getEditor('111')).toBe(undefined) + test('no cache added', () => { + expect(cache.getEditor('111')).toBe(undefined) + }) - cache.addEditor('111', editorInst) - expect(cache.getEditor('111')).toBe(editorInst) + test('add one instance 111 to cache', () => { + cache.addEditor('111', editorInst) + expect(cache.getEditor('111')).toBe(editorInst) + }) - cache.deleteEditor('222') - expect(cache.getEditor('111')).toBe(editorInst) + test('remove instance 222 from cache', () => { + cache.deleteEditor('222') + expect(cache.getEditor('111')).toBe(editorInst) + }) - cache.deleteEditor('111') - expect(cache.getEditor('111')).toBe(undefined) + test('remove instance 111 from cache', () => { + cache.deleteEditor('111') + expect(cache.getEditor('111')).toBe(undefined) + }) - cache.addEditor('111', editorInst) - expect(cache.getEditor('111')).toBe(editorInst) + test('clear cache', () => { + cache.addEditor('111', editorInst) + expect(cache.getEditor('111')).toBe(editorInst) - cache.clearEditors() - expect(cache.getEditor('111')).toBe(undefined) + cache.clearEditors() + expect(cache.getEditor('111')).toBe(undefined) + }) }) diff --git a/packages/core/src/test/instance.test.ts b/packages/core/src/test/instance.test.ts index 80b4f6a..2753902 100644 --- a/packages/core/src/test/instance.test.ts +++ b/packages/core/src/test/instance.test.ts @@ -9,56 +9,94 @@ ORDER BY sector, companies DESC;` const DOC = `\n${LINE_1}\n\n${LINE_2}\n\n` -test('editor instance works fine', () => { - const editorInst = createSQLEditorInstance({ - editorId: '111', - doc: DOC +describe('editor instance works fine', () => { + let editorInst + + beforeAll(() => { + editorInst = createSQLEditorInstance({ + editorId: '111', + doc: DOC + }) }) - expect(editorInst.editorId).toBe('111') + test('editorId should be correct', () => + expect(editorInst.editorId).toBe('111')) - editorInst.editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + describe('dispatch a empty selection action', () => { + let curSql, nearbySql, allSql - const allSql = editorInst.getAllStatements() - expect(allSql.length).toBe(2) - expect(allSql[0].content).toBe(LINE_1) - expect(allSql[1].content).toBe(LINE_2) + beforeAll(() => { + editorInst.editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + curSql = editorInst.getCurStatements() + nearbySql = editorInst.getNearbyStatement() + allSql = editorInst.getAllStatements() + }) - let curSql = editorInst.getCurStatements() - expect(curSql[0].content).toBe('') + test('the content and length of statement is correct', () => { + expect(allSql.length).toBe(2) + expect(allSql[0].content).toBe(LINE_1) + expect(allSql[1].content).toBe(LINE_2) + }) - let nearbySql = editorInst.getNearbyStatement() - expect(nearbySql?.content).toBe(LINE_1) + test('current sql is empty', () => { + expect(curSql[0].content).toBe('') + }) - editorInst.editorView.dispatch({ - selection: { anchor: 1, head: 2 } + test('nearby sql is line1', () => { + expect(nearbySql?.content).toBe(LINE_1) + }) }) - curSql = editorInst.getCurStatements() - expect(curSql[0].content).toBe(LINE_1) - - nearbySql = editorInst.getNearbyStatement() - expect(nearbySql?.content).toBe(LINE_1) - - editorInst.editorView.dispatch({ - selection: { anchor: DOC.length, head: DOC.length } + describe('dispatch a selection action', () => { + let curSql, nearbySql + + beforeAll(() => { + editorInst.editorView.dispatch({ + selection: { anchor: 1, head: 2 } + }) + curSql = editorInst.getCurStatements() + nearbySql = editorInst.getNearbyStatement() + }) + + test('current sql is line1, nearby sql is line1', () => { + expect(curSql[0].content).toBe(LINE_1) + expect(nearbySql?.content).toBe(LINE_1) + }) }) - curSql = editorInst.getCurStatements() - expect(curSql[0].content).toBe('') - - nearbySql = editorInst.getNearbyStatement() - expect(nearbySql?.content).toBe(LINE_2) - - editorInst.editorView.dispatch({ - selection: { anchor: 2, head: 2 + LINE_1.length + 5 } + describe('dispatch a selection action', () => { + let curSql, nearbySql + + beforeAll(() => { + editorInst.editorView.dispatch({ + selection: { anchor: DOC.length, head: DOC.length } + }) + curSql = editorInst.getCurStatements() + nearbySql = editorInst.getNearbyStatement() + }) + + test('current sql is empty, nearby sql is line2', () => { + expect(curSql[0].content).toBe('') + expect(nearbySql?.content).toBe(LINE_2) + }) }) - curSql = editorInst.getCurStatements() - expect(curSql.length).toBe(2) - expect(curSql[0].content).toBe(LINE_1) - expect(curSql[1].content).toBe(LINE_2) - - nearbySql = editorInst.getNearbyStatement() - expect(nearbySql?.content).toBe(LINE_1) + describe('dispatch a selection action', () => { + let curSql, nearbySql + + beforeAll(() => { + editorInst.editorView.dispatch({ + selection: { anchor: 2, head: 2 + LINE_1.length + 5 } + }) + curSql = editorInst.getCurStatements() + nearbySql = editorInst.getNearbyStatement() + }) + + test('current sql length is 2, nearby sql is line1', () => { + expect(curSql.length).toBe(2) + expect(curSql[0].content).toBe(LINE_1) + expect(curSql[1].content).toBe(LINE_2) + expect(nearbySql?.content).toBe(LINE_1) + }) + }) }) diff --git a/packages/extensions/ai-widget/CHANGELOG.md b/packages/extensions/ai-widget/CHANGELOG.md index 215fd69..5e13854 100644 --- a/packages/extensions/ai-widget/CHANGELOG.md +++ b/packages/extensions/ai-widget/CHANGELOG.md @@ -1,5 +1,13 @@ # @tidbcloud/codemirror-extension-ai-widget +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params +- Updated dependencies [122f217] + - @tidbcloud/codemirror-extension-cur-sql@0.0.4 + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/ai-widget/README.md b/packages/extensions/ai-widget/README.md index 4578c7f..8161cf4 100644 --- a/packages/extensions/ai-widget/README.md +++ b/packages/extensions/ai-widget/README.md @@ -1,6 +1,6 @@ # @tidbcloud/codemirror-extension-ai-widget -A codemirror extension provides a widget to chat with AI to help you write or refine SQL. (work with other languages wip) +A codemirror extension provides a widget to chat with AI to help you write or refine SQL. (will support to work with other languages later) https://github.com/tidbcloud/tisqleditor/assets/1284531/46684333-7efa-4925-bf58-9ab3fb45f692 @@ -22,10 +22,10 @@ https://github.com/tidbcloud/tisqleditor/assets/1284531/46684333-7efa-4925-bf58- npm install @tidbcloud/codemirror-extension-ai-widget ``` -You need to install its peer dependencies as well: +You need to install its dependencies as well: ```shell -npm install @codemirror/view @codemirror/state @codemirror/merge @codemirror/lang-sql +npm install @codemirror/view @codemirror/state @codemirror/merge @codemirror/lang-sql @tidbcloud/codemirror-extension-sql-parser @tidbcloud/codemirror-extension-cur-sql ``` ## Usage diff --git a/packages/extensions/ai-widget/package.json b/packages/extensions/ai-widget/package.json index 383a351..dda843f 100644 --- a/packages/extensions/ai-widget/package.json +++ b/packages/extensions/ai-widget/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-ai-widget", - "version": "0.0.3", + "version": "0.0.4", "description": "ai widget extension for codemirror", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/basic-setup/CHANGELOG.md b/packages/extensions/basic-setup/CHANGELOG.md index c3355f3..60f1d3c 100644 --- a/packages/extensions/basic-setup/CHANGELOG.md +++ b/packages/extensions/basic-setup/CHANGELOG.md @@ -1,5 +1,11 @@ # @tidbcloud/codemirror-extension-basic-setup +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/basic-setup/README.md b/packages/extensions/basic-setup/README.md index 53ff06f..95953ce 100644 --- a/packages/extensions/basic-setup/README.md +++ b/packages/extensions/basic-setup/README.md @@ -1,6 +1,7 @@ # @tidbcloud/codemirror-extension-basic-setup Default basic configuration for codemirror. +This package depends on most of the codemirror core library packages and exports extension bundles to help set up a simple editor in a few lines of code. ## Installation @@ -8,7 +9,7 @@ Default basic configuration for codemirror. npm install @tidbcloud/codemirror-extension-basic-setup ``` -You need to install its peer dependencies as well: +⚠️ You need to install its peer dependencies as well: ```shell npm install @codemirror/state @codemirror/view @codemirror/autocomplete @codemirror/commands @codemirror/language @codemirror/lint @codemirror/search @@ -36,6 +37,26 @@ const editorView = new EditorView({ }) ``` +If you have used @tidbcloud/tisqleditor component, as it used baisc-setup and has some default config values, to override the default values, you can use basicSetupOptions, it has a higher priority, and can config it like this: + +```ts +import { EditorView } from '@codemirror/view' +import { EditorState } from '@codemirror/state' +import { createSQLEditorInstance } from '@tidbcloud/tisqleditor' + +const editorInst = createSQLEditorInstance({ + editorId, + doc, + basicSetupOptions: { + foldGutter: false, + foldKeymap: false, + searchKeymap: true, + autocompletion: false, + history: false + } +}) +``` + ## API ```ts diff --git a/packages/extensions/basic-setup/package.json b/packages/extensions/basic-setup/package.json index 327853b..5e9086f 100644 --- a/packages/extensions/basic-setup/package.json +++ b/packages/extensions/basic-setup/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-basic-setup", - "version": "0.0.3", + "version": "0.0.4", "description": "basic setup extension for codemirror", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/basic-setup/src/index.ts b/packages/extensions/basic-setup/src/index.ts index ffc26f7..e199489 100644 --- a/packages/extensions/basic-setup/src/index.ts +++ b/packages/extensions/basic-setup/src/index.ts @@ -1,7 +1,3 @@ -// edit from -// - https://github.com/uiwjs/react-codemirror/blob/master/extensions/basic-setup/src/index.ts -// - https://github.com/codemirror/basic-setup/blob/main/src/codemirror.ts - import { autocompletion, completionKeymap, diff --git a/packages/extensions/cur-sql-gutter/CHANGELOG.md b/packages/extensions/cur-sql-gutter/CHANGELOG.md index 1cf95b2..51774ec 100644 --- a/packages/extensions/cur-sql-gutter/CHANGELOG.md +++ b/packages/extensions/cur-sql-gutter/CHANGELOG.md @@ -1,5 +1,14 @@ # @tidbcloud/codemirror-extension-cur-sql-gutter +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params +- Updated dependencies [122f217] + - @tidbcloud/codemirror-extension-cur-sql@0.0.4 + - @tidbcloud/codemirror-extension-sql-parser@0.0.4 + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/cur-sql-gutter/README.md b/packages/extensions/cur-sql-gutter/README.md index dbab793..1654d47 100644 --- a/packages/extensions/cur-sql-gutter/README.md +++ b/packages/extensions/cur-sql-gutter/README.md @@ -13,10 +13,10 @@ A codemirror extension listens the editor selection change, and shows gutter for npm install @tidbcloud/codemirror-extension-cur-sql-gutter ``` -You need to install its peer dependencies as well: +You need to install its dependencies as well: ```shell -npm install @codemirror/view @codemirror/state @codemirror/lang-sql +npm install @codemirror/view @codemirror/state @codemirror/lang-sql @tidbcloud/codemirror-extension-sql-parser @tidbcloud/codemirror/extension-cur-sql ``` ## Usage diff --git a/packages/extensions/cur-sql-gutter/package.json b/packages/extensions/cur-sql-gutter/package.json index 2432771..40f0c49 100644 --- a/packages/extensions/cur-sql-gutter/package.json +++ b/packages/extensions/cur-sql-gutter/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-cur-sql-gutter", - "version": "0.0.3", + "version": "0.0.4", "description": "codemirror extension to show gutter for current selected sql", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/cur-sql/CHANGELOG.md b/packages/extensions/cur-sql/CHANGELOG.md index 93d632c..398f4d1 100644 --- a/packages/extensions/cur-sql/CHANGELOG.md +++ b/packages/extensions/cur-sql/CHANGELOG.md @@ -1,5 +1,13 @@ # @tidbcloud/codemirror-extension-cur-sql +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params +- Updated dependencies [122f217] + - @tidbcloud/codemirror-extension-sql-parser@0.0.4 + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/cur-sql/README.md b/packages/extensions/cur-sql/README.md index e72578c..099eaa0 100644 --- a/packages/extensions/cur-sql/README.md +++ b/packages/extensions/cur-sql/README.md @@ -10,12 +10,10 @@ This extension is installed internally inside the `SQLEditorInstance`. npm install @tidbcloud/codemirror-extension-cur-sql ``` -It will auto install `@tidbcloud/codemirror-extension-sql-parser` as its dependency. - -You need to install its peer dependencies as well: +You need to install its dependencies as well: ```shell -npm install @codemirror/view @codemirror/state @codemirror/language @codemirro/lang-sql +npm install @codemirror/view @codemirror/state @codemirror/language @codemirror/lang-sql @tidbcloud/codemirror-extension-sql-parser ``` ## Usage diff --git a/packages/extensions/cur-sql/package.json b/packages/extensions/cur-sql/package.json index 5ef897d..f3a97b1 100644 --- a/packages/extensions/cur-sql/package.json +++ b/packages/extensions/cur-sql/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-cur-sql", - "version": "0.0.3", + "version": "0.0.4", "description": "codemirror extension to get current selected sql", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/cur-sql/src/test/cursql.test.ts b/packages/extensions/cur-sql/src/test/cursql.test.ts index b29dea6..c331a98 100644 --- a/packages/extensions/cur-sql/src/test/cursql.test.ts +++ b/packages/extensions/cur-sql/src/test/cursql.test.ts @@ -16,22 +16,31 @@ LIMIT const DOC = `${LINE_1}\n${LINE_2}` -test('test getCurStatements', () => { - const editorView = new EditorView({ - state: EditorState.create({ - doc: DOC, - extensions: [sqlParser(), sql({ dialect: MySQL }), curSql()] +describe('test getCurStatements', () => { + let editorView: EditorView = new EditorView() + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: DOC, + extensions: [sqlParser(), sql({ dialect: MySQL }), curSql()] + }) }) }) - editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + test('select 0 to 0, the firstSqlStatement should to be LINE_1', () => { + editorView.dispatch({ selection: { anchor: 0, head: 0 } }) - const firstSqlStatement = getCurStatements(editorView.state) - expect(firstSqlStatement[0].content).toBe(LINE_1) + const firstSqlStatement = getCurStatements(editorView.state) + expect(firstSqlStatement[0].content).toBe(LINE_1) + }) + + test('select from DOC.length to DOC.length, the lastSqlStatement should to be LINE_2', () => { + editorView.dispatch({ + selection: { anchor: DOC.length, head: DOC.length } + }) - editorView.dispatch({ - selection: { anchor: DOC.length, head: DOC.length } + const lastSqlStatement = getCurStatements(editorView.state) + expect(lastSqlStatement[0].content).toBe(LINE_2) }) - const lastSqlStatement = getCurStatements(editorView.state) - expect(lastSqlStatement[0].content).toBe(LINE_2) }) diff --git a/packages/extensions/events/CHANGELOG.md b/packages/extensions/events/CHANGELOG.md index 0c91887..12f8a10 100644 --- a/packages/extensions/events/CHANGELOG.md +++ b/packages/extensions/events/CHANGELOG.md @@ -1,5 +1,11 @@ # @tidbcloud/codemirror-extension-events +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/events/package.json b/packages/extensions/events/package.json index bde83aa..556746d 100644 --- a/packages/extensions/events/package.json +++ b/packages/extensions/events/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-events", - "version": "0.0.3", + "version": "0.0.4", "description": "codemirror extension to listen doc and selection changes event", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/events/src/test/doc-change.test.ts b/packages/extensions/events/src/test/doc-change.test.ts index 225a0c5..988ed67 100644 --- a/packages/extensions/events/src/test/doc-change.test.ts +++ b/packages/extensions/events/src/test/doc-change.test.ts @@ -13,25 +13,50 @@ LIMIT const DOC = `${LINE_1}\n${LINE_2}` -test('test change event', () => { - let doc = '' - - const editorView = new EditorView({ - state: EditorState.create({ - doc: '', - extensions: [ - onDocChange((_view, content) => { - doc = content +describe('test change event', () => { + describe('a empty doc, insert LINE_1', () => { + let doc = '', + editorView: EditorView = new EditorView() + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: '', + extensions: [ + onDocChange((_view, content) => { + doc = content + }) + ] }) - ] + }) + + editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) }) + + test('doc should to be LINE_1', () => expect(doc).toBe(LINE_1)) }) - editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) - expect(doc).toBe(LINE_1) + describe('a doc has LINE_1 and insert LINE_2 after LINE_1', () => { + let doc = '', + editorView: EditorView = new EditorView() + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: LINE_1, + extensions: [ + onDocChange((_view, content) => { + doc = content + }) + ] + }) + }) + + editorView.dispatch({ + changes: { from: LINE_1.length, insert: `\n${LINE_2}` } + }) + }) - editorView.dispatch({ - changes: { from: LINE_1.length, insert: `\n${LINE_2}` } + test('doc should to be DOC', () => expect(doc).toBe(DOC)) }) - expect(doc).toBe(DOC) }) diff --git a/packages/extensions/events/src/test/selection-change.test.ts b/packages/extensions/events/src/test/selection-change.test.ts index e242c4d..15e7399 100644 --- a/packages/extensions/events/src/test/selection-change.test.ts +++ b/packages/extensions/events/src/test/selection-change.test.ts @@ -3,8 +3,6 @@ import { EditorState } from '@codemirror/state' import { onSelectionChange, SelectionRange } from '..' -jest.useFakeTimers() - const LINE_1 = 'USE game;' const LINE_2 = `SELECT * @@ -15,31 +13,44 @@ LIMIT const DOC = `${LINE_1}\n${LINE_2}` -test('test selection change event', async () => { +describe('test selection change event', () => { let selRanges: SelectionRange[] = [] - - const editorView = new EditorView({ - state: EditorState.create({ - doc: '', - extensions: [ - onSelectionChange((_view, ranges) => { - selRanges = ranges - }) - ] + let editorView: EditorView = new EditorView() + + beforeAll(() => { + jest.useFakeTimers() + + editorView = new EditorView({ + state: EditorState.create({ + doc: '', + extensions: [ + onSelectionChange((_view, ranges) => { + selRanges = ranges + }) + ] + }) }) + + editorView.dispatch({ changes: { from: 0, insert: DOC } }) }) - editorView.dispatch({ changes: { from: 0, insert: DOC } }) + afterAll(() => jest.useRealTimers()) + + test('select 0 to LINE_1.length, the selectionRange is correct', async () => { + editorView.dispatch({ selection: { anchor: 0, head: LINE_1.length } }) + await jest.advanceTimersByTime(100) - editorView.dispatch({ selection: { anchor: 0, head: LINE_1.length } }) - await jest.advanceTimersByTime(100) - expect(selRanges[0].from).toBe(0) - expect(selRanges[0].to).toBe(LINE_1.length) + expect(selRanges[0].from).toBe(0) + expect(selRanges[0].to).toBe(LINE_1.length) + }) + + test('select LINE_1.length to DOC.length, the selectionRange is correct', async () => { + editorView.dispatch({ + selection: { anchor: LINE_1.length, head: DOC.length } + }) + await jest.advanceTimersByTime(100) - editorView.dispatch({ - selection: { anchor: LINE_1.length, head: DOC.length } + expect(selRanges[0].from).toBe(LINE_1.length) + expect(selRanges[0].to).toBe(DOC.length) }) - await jest.advanceTimersByTime(100) - expect(selRanges[0].from).toBe(LINE_1.length) - expect(selRanges[0].to).toBe(DOC.length) }) diff --git a/packages/extensions/linters/CHANGELOG.md b/packages/extensions/linters/CHANGELOG.md index c5f334c..0834900 100644 --- a/packages/extensions/linters/CHANGELOG.md +++ b/packages/extensions/linters/CHANGELOG.md @@ -1,5 +1,13 @@ # @tidbcloud/codemirror-extension-linters +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params +- Updated dependencies [122f217] + - @tidbcloud/codemirror-extension-sql-parser@0.0.4 + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/linters/README.md b/packages/extensions/linters/README.md index 77c9171..2720180 100644 --- a/packages/extensions/linters/README.md +++ b/packages/extensions/linters/README.md @@ -17,10 +17,10 @@ npm install @tidbcloud/codemirror-extension-linters ``` -You need to install its peer dependencies as well: +You need to install its dependencies as well: ```shell -npm install @codemirror/view @codemirror/state @codemirror/lint @codemirror/lang-sql +npm install @codemirror/view @codemirror/state @codemirror/lint @codemirror/lang-sql @tidbcloud/codemirror-extension-sql-parser ``` ## Usage @@ -54,9 +54,17 @@ const editorView = new EditorView({ }), regexMatchLinter([ { - reg: /[a-z]/, - title: 'test reg error', - message: 'test reg error content' + reg: /\$\{page\}/g, + level: 'warning', + title: 'Code Error', + message: pageTips + }, + { + reg: /\$\{page_size\}/g, + level: 'error', + title: 'Code Error', + message: + 'page and page_size are built-in paging variables in the system, please replace the name of parameters.' } ]) ] diff --git a/packages/extensions/linters/package.json b/packages/extensions/linters/package.json index cbb607e..6167a88 100644 --- a/packages/extensions/linters/package.json +++ b/packages/extensions/linters/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-linters", - "version": "0.0.3", + "version": "0.0.4", "description": "codemirror linter extensions", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/linters/src/regex-match-linter.ts b/packages/extensions/linters/src/regex-match-linter.ts index 36a38c6..1f33e3f 100644 --- a/packages/extensions/linters/src/regex-match-linter.ts +++ b/packages/extensions/linters/src/regex-match-linter.ts @@ -7,6 +7,7 @@ export interface RegexpItem { reg: RegExp title: string message: string + level?: 'error' | 'warning' } const regexMatchParser = (regs: RegexpItem[]) => @@ -18,6 +19,7 @@ const regexMatchParser = (regs: RegexpItem[]) => const matches: { title: string message: string + level?: 'error' | 'warning' matchArr: RegExpMatchArray }[] = [] @@ -27,6 +29,7 @@ const regexMatchParser = (regs: RegexpItem[]) => ...cur.map((item) => ({ title: reg.title, message: reg.message, + level: reg.level, matchArr: item })) ) @@ -38,7 +41,7 @@ const regexMatchParser = (regs: RegexpItem[]) => diagnostics.push({ from: index, to: index + match.matchArr[0].length, - severity: 'error', + severity: match.level || 'error', renderMessage: () => { return hintEle(match.title, match.message) }, diff --git a/packages/extensions/linters/src/test/full-width-char-linter.test.ts b/packages/extensions/linters/src/test/full-width-char-linter.test.ts index 26c5977..f5f14d1 100644 --- a/packages/extensions/linters/src/test/full-width-char-linter.test.ts +++ b/packages/extensions/linters/src/test/full-width-char-linter.test.ts @@ -7,36 +7,49 @@ import { sqlParser } from '@tidbcloud/codemirror-extension-sql-parser' import { fullWidthCharLinter } from '..' -jest.useFakeTimers() - const LINE_1 = 'SELECT * from test LIMIT 1;\n' const LINE_2 = 'USE game;\n' -test('test full width char linter', async () => { - const container = document.createElement('div') - container.style.height = '100px' - const editorView = new EditorView({ - state: EditorState.create({ - doc: '', - extensions: [sql({ dialect: MySQL }), sqlParser(), fullWidthCharLinter()] - }), - parent: container +describe('test full width char linter', () => { + let container: HTMLDivElement, + editorView: EditorView = new EditorView() + + beforeAll(() => { + jest.useFakeTimers() + + container = document.createElement('div') + container.style.height = '100px' + + editorView = new EditorView({ + state: EditorState.create({ + doc: '', + extensions: [ + sql({ dialect: MySQL }), + sqlParser(), + fullWidthCharLinter() + ] + }), + parent: container + }) + }) + + afterAll(() => jest.useRealTimers()) + + test('add LINE_1', async () => { + editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) + await jest.advanceTimersByTime(1000) + expect(diagnosticCount(editorView.state)).toBe(0) }) - editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) - await jest.advanceTimersByTime(1000) - expect(diagnosticCount(editorView.state)).toBe(0) - - // dispatch changes transaction to make `diagnosticCount(editorView.state)` update - editorView.dispatch({ changes: { from: LINE_1.length, insert: LINE_2 } }) - await jest.advanceTimersByTime(1000) - // TODO: fix - // don't why, diagnosticCount should expect to be 1, but always get 0 - // expect(diagnosticCount(editorView.state)).toBe(1) - expect(diagnosticCount(editorView.state)).toBe(0) - forEachDiagnostic(editorView.state, (d, from, to) => { - expect(d.severity).toBe('error') - expect(from).toBe(26) - expect(to).toBe(27) + test('add LINE_2 after LINE_1', async () => { + // dispatch changes transaction to make `diagnosticCount(editorView.state)` update + editorView.dispatch({ changes: { from: LINE_1.length, insert: LINE_2 } }) + await jest.advanceTimersByTime(1000) + expect(diagnosticCount(editorView.state)).toBe(1) + forEachDiagnostic(editorView.state, (d, from, to) => { + expect(d.severity).toBe('error') + expect(from).toBe(26) + expect(to).toBe(27) + }) }) }) diff --git a/packages/extensions/linters/src/test/use-db-linter.test.ts b/packages/extensions/linters/src/test/use-db-linter.test.ts index 0d49660..f3dfb94 100644 --- a/packages/extensions/linters/src/test/use-db-linter.test.ts +++ b/packages/extensions/linters/src/test/use-db-linter.test.ts @@ -7,36 +7,48 @@ import { sqlParser } from '@tidbcloud/codemirror-extension-sql-parser' import { useDbLinter } from '..' -jest.useFakeTimers() - const LINE_1 = 'SELECT * from test LIMIT 1;\n' const LINE_2 = 'USE game;\n' -test('test usb db linter', async () => { - const container = document.createElement('div') - container.style.height = '100px' - const editorView = new EditorView({ - state: EditorState.create({ - doc: '', - extensions: [sql({ dialect: MySQL }), sqlParser(), useDbLinter()] - }), - parent: container +describe('test usb db linter', () => { + let container: HTMLDivElement, + editorView: EditorView = new EditorView() + + beforeAll(() => { + jest.useFakeTimers() + + container = document.createElement('div') + container.style.height = '100px' + + editorView = new EditorView({ + state: EditorState.create({ + doc: '', + extensions: [sql({ dialect: MySQL }), sqlParser(), useDbLinter()] + }), + parent: container + }) }) - editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) - await jest.advanceTimersByTime(1000) - expect(diagnosticCount(editorView.state)).toBe(0) - - // dispatch changes transaction to make `diagnosticCount(editorView.state)` update - editorView.dispatch({ changes: { from: LINE_1.length, insert: LINE_2 } }) - await jest.advanceTimersByTime(1000) - // TODO: fix - // don't why, diagnosticCount should expect to be 1, but always get 0 - // expect(diagnosticCount(editorView.state)).toBe(1) - expect(diagnosticCount(editorView.state)).toBe(0) - forEachDiagnostic(editorView.state, (d, from, to) => { - expect(d.severity).toBe('warning') - expect(from).toBe(0) - expect(to).toBe(LINE_1.length) + afterAll(() => jest.useRealTimers()) + + test('add LINE_1', async () => { + editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) + await jest.advanceTimersByTime(1000) + + expect(diagnosticCount(editorView.state)).toBe(0) + }) + + test('add LINE_2 after LINE_1', async () => { + // dispatch changes transaction to make `diagnosticCount(editorView.state)` update + editorView.dispatch({ changes: { from: LINE_1.length, insert: LINE_2 } }) + await jest.advanceTimersByTime(1000) + + expect(diagnosticCount(editorView.state)).toBe(1) + forEachDiagnostic(editorView.state, (d, from, to) => { + expect(d.severity).toBe('warning') + expect(from).toBe(0) + // i feel the length shouldn't inlcude '\n' + expect(to).toBe(LINE_1.length - 1) + }) }) }) diff --git a/packages/extensions/save-helper/CHANGELOG.md b/packages/extensions/save-helper/CHANGELOG.md index cf71e0e..115367b 100644 --- a/packages/extensions/save-helper/CHANGELOG.md +++ b/packages/extensions/save-helper/CHANGELOG.md @@ -1,5 +1,11 @@ # @tidbcloud/codemirror-extension-save-helper +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/save-helper/package.json b/packages/extensions/save-helper/package.json index 035842f..f11aca1 100644 --- a/packages/extensions/save-helper/package.json +++ b/packages/extensions/save-helper/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-save-helper", - "version": "0.0.3", + "version": "0.0.4", "description": "codemiror extension to help save editor content", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/save-helper/src/test/1.test.ts b/packages/extensions/save-helper/src/test/1.test.ts deleted file mode 100644 index 1fdd31d..0000000 --- a/packages/extensions/save-helper/src/test/1.test.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { EditorView } from '@codemirror/view' -import { EditorState } from '@codemirror/state' - -import { saveHelper } from '..' - -const LINE_1 = `USE sp500insight;` -const LINE_2 = `SELECT * from companies LIMIT 10;` - -const INIT_DOC = `\n${LINE_1}\n\n` - -jest.useFakeTimers() - -test('test auto save after content changes without any delay', async () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - save(view) { - latestContent = view.state.doc.toString() - }, - delay: 0 - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - expect(latestContent).toBe(``) - - await jest.advanceTimersByTime(0) - expect(latestContent).toBe(`${LINE_2}${INIT_DOC}`) -}) - -test('test auto save after content changes without 1s delay', async () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - save(view) { - latestContent = view.state.doc.toString() - }, - delay: 1000 - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - expect(latestContent).toBe(``) - - await jest.advanceTimersByTime(100) - expect(latestContent).toBe(``) - - await jest.advanceTimersByTime(1000) - expect(latestContent).toBe(`${LINE_2}${INIT_DOC}`) -}) - -test('test turn off auto save', async () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - auto: false, - save(view) { - latestContent = view.state.doc.toString() - }, - delay: 0 - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - await jest.advanceTimersByTime(100) - expect(latestContent).toBe(``) -}) - -test('test manual save with default hotkey', () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - auto: false, - save(view) { - latestContent = view.state.doc.toString() - } - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - // TODO - // press Mod-s - - expect(latestContent).toBe(``) -}) - -test('test manual save with a non-default hotkey', () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - auto: false, - hotkey: 'Mod-i', - save(view) { - latestContent = view.state.doc.toString() - } - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - // TODO - // press Mod-i - - expect(latestContent).toBe(``) -}) - -test('test turn off manual save', () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - auto: false, - hotkey: '', - save(view) { - latestContent = view.state.doc.toString() - } - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - // TODO - // press Mod-i - - expect(latestContent).toBe(``) -}) diff --git a/packages/extensions/save-helper/src/test/save.test.ts b/packages/extensions/save-helper/src/test/save.test.ts new file mode 100644 index 0000000..65dc857 --- /dev/null +++ b/packages/extensions/save-helper/src/test/save.test.ts @@ -0,0 +1,89 @@ +import { EditorView } from '@codemirror/view' +import { EditorState } from '@codemirror/state' + +import { saveHelper } from '..' + +const LINE_1 = `USE sp500insight;` +const LINE_2 = `SELECT * from companies LIMIT 10;` + +const INIT_DOC = `\n${LINE_1}\n\n` + +describe.each([ + { delay: 0, auto: true, expected: `${LINE_2}${INIT_DOC}` }, + { delay: 1000, auto: true, expected: `${LINE_2}${INIT_DOC}` }, + { delay: 0, auto: false, expected: '' } +])('test auto save', ({ delay, auto, expected }) => { + let latestContent = '', + editorView + + beforeAll(() => { + jest.useFakeTimers() + editorView = new EditorView({ + state: EditorState.create({ + doc: INIT_DOC, + extensions: [ + saveHelper({ + auto, + save(view) { + latestContent = view.state.doc.toString() + }, + delay + }) + ] + }) + }) + + editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) + }) + + afterAll(() => { + jest.useRealTimers() + }) + + test('content should be empty', () => { + expect(latestContent).toBe('') + }) + + if (delay > 0) { + test('wait for half specfic millseconds, content should be empty', async () => { + await jest.advanceTimersByTime(delay / 2) + expect(latestContent).toBe('') + }) + } + + test('wait for specfic millseconds, content should be equal to expected value', async () => { + await jest.advanceTimersByTime(delay) + expect(latestContent).toBe(expected) + }) +}) + +describe.each([{ hotkey: undefined }, { hotkey: 'Mod-i' }, { hotkey: '' }])( + 'test manual save', + ({ hotkey }) => { + let latestContent = '', + editorView + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: INIT_DOC, + extensions: [ + saveHelper({ + auto: false, + hotkey, + save(view) { + latestContent = view.state.doc.toString() + } + }) + ] + }) + }) + + editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) + }) + + test('content should be empty', () => { + expect(latestContent).toBe(``) + }) + } +) diff --git a/packages/extensions/sql-autocomplete/CHANGELOG.md b/packages/extensions/sql-autocomplete/CHANGELOG.md index f0b524b..d0f8eba 100644 --- a/packages/extensions/sql-autocomplete/CHANGELOG.md +++ b/packages/extensions/sql-autocomplete/CHANGELOG.md @@ -1,5 +1,11 @@ # @tidbcloud/codemirror-extension-sql-autocomplete +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/sql-autocomplete/package.json b/packages/extensions/sql-autocomplete/package.json index f9f1bad..e36c3a4 100644 --- a/packages/extensions/sql-autocomplete/package.json +++ b/packages/extensions/sql-autocomplete/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-sql-autocomplete", - "version": "0.0.3", + "version": "0.0.4", "description": "codemiror extension for SQL keyword and database schema autocompletion with customized style", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/sql-autocomplete/src/index.ts b/packages/extensions/sql-autocomplete/src/index.ts index 2604645..dc18bb8 100644 --- a/packages/extensions/sql-autocomplete/src/index.ts +++ b/packages/extensions/sql-autocomplete/src/index.ts @@ -209,7 +209,8 @@ const baseTheme = EditorView.baseTheme({ alignItems: 'center' }, '.cm-autocomplete-item > div.icon': { - marginRight: '10px' + marginRight: '10px', + verticalAlign: 'middle' }, '.cm-autocomplete-item .cm-completionIcon-keyword': { paddingRight: '24px' diff --git a/packages/extensions/sql-parser/CHANGELOG.md b/packages/extensions/sql-parser/CHANGELOG.md index 733b7b5..db4f76b 100644 --- a/packages/extensions/sql-parser/CHANGELOG.md +++ b/packages/extensions/sql-parser/CHANGELOG.md @@ -1,5 +1,11 @@ # @tidbcloud/codemirror-extension-sql-parser +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/sql-parser/package.json b/packages/extensions/sql-parser/package.json index 8c80573..8846d0a 100644 --- a/packages/extensions/sql-parser/package.json +++ b/packages/extensions/sql-parser/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-sql-parser", - "version": "0.0.3", + "version": "0.0.4", "description": "codemiror extension to parser editor content to SQL statements", "type": "module", "main": "dist/index.js", diff --git a/packages/extensions/sql-parser/src/test/1.test.ts b/packages/extensions/sql-parser/src/test/1.test.ts deleted file mode 100644 index 703eb6b..0000000 --- a/packages/extensions/sql-parser/src/test/1.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { EditorView } from '@codemirror/view' -import { EditorState } from '@codemirror/state' -import { MySQL, sql } from '@codemirror/lang-sql' - -import { sqlParser, getSqlStatements, getNearbyStatement } from '..' - -const LINE_1 = `USE sp500insight;` -const LINE_2 = `SELECT sector, industry, COUNT(*) AS companies -FROM companies c -WHERE c.stock_symbol IN (SELECT stock_symbol FROM index_compositions WHERE index_symbol = "SP500") -GROUP BY sector, industry -ORDER BY sector, companies DESC;` - -const DOC = `\n${LINE_1}\n\n${LINE_2}\n\n` - -test('test getSqlStatements', () => { - const editorView = new EditorView({ - state: EditorState.create({ - doc: DOC, - extensions: [sql({ dialect: MySQL }), sqlParser()] - }) - }) - - // dispatch any a transaction to trigger update event for editor - editorView.dispatch({ selection: { anchor: 0, head: 0 } }) - - const allStatements = getSqlStatements(editorView.state) - expect(allStatements.length).toBe(2) - - const firstStatement = allStatements[0] - expect(firstStatement.content).toBe(LINE_1) - expect(firstStatement.database).toBe('sp500insight') - expect(firstStatement.type).toBe('use') - expect(firstStatement.from).toBe(1) - expect(firstStatement.to).toBe(1 + LINE_1.length) - expect(firstStatement.lineFrom).toBe(2) - expect(firstStatement.lineTo).toBe(2) - - const secondStatement = allStatements[1] - expect(secondStatement.content).toBe(LINE_2) - expect(secondStatement.database).toBe('sp500insight') - expect(secondStatement.type).toBe('other') - expect(secondStatement.from).toBe(1 + LINE_1.length + 2) - expect(secondStatement.to).toBe(1 + LINE_1.length + 2 + LINE_2.length) - expect(secondStatement.lineFrom).toBe(4) - expect(secondStatement.lineTo).toBe(8) -}) - -test('test getNearbyStatement', () => { - const editorView = new EditorView({ - state: EditorState.create({ - doc: DOC, - extensions: [sql({ dialect: MySQL }), sqlParser()] - }) - }) - - // dispatch any a transaction to trigger update event for editor - editorView.dispatch({ selection: { anchor: 0, head: 0 } }) - - let nearestStatement = getNearbyStatement(editorView.state, 0) - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement(editorView.state, 10) - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement(editorView.state, 1 + LINE_1.length) // 18 - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement(editorView.state, 1 + LINE_1.length + 1) // 19 - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement( - editorView.state, - 1 + LINE_1.length + 10 - ) // 28 - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement( - editorView.state, - 1 + LINE_1.length + 2 + LINE_2.length - ) // 241 - expect(nearestStatement?.content).toBe(LINE_2) - - nearestStatement = getNearbyStatement( - editorView.state, - 1 + LINE_1.length + 2 + LINE_2.length - ) // 241 - expect(nearestStatement?.content).toBe(LINE_2) - - nearestStatement = getNearbyStatement( - editorView.state, - 1 + LINE_1.length + 2 + LINE_2.length + 2 - ) // 243 - expect(nearestStatement?.content).toBe(LINE_2) -}) diff --git a/packages/extensions/sql-parser/src/test/statement.test.ts b/packages/extensions/sql-parser/src/test/statement.test.ts new file mode 100644 index 0000000..eef7a6e --- /dev/null +++ b/packages/extensions/sql-parser/src/test/statement.test.ts @@ -0,0 +1,122 @@ +import { EditorState } from '@codemirror/state' +import { MySQL, sql } from '@codemirror/lang-sql' + +import { + sqlParser, + getSqlStatements, + getNearbyStatement, + SqlStatement +} from '..' +import { EditorView } from '@codemirror/view' + +const LINE_1 = `USE sp500insight;` +const LINE_2 = `SELECT sector, industry, COUNT(*) AS companies +FROM companies c +WHERE c.stock_symbol IN (SELECT stock_symbol FROM index_compositions WHERE index_symbol = "SP500") +GROUP BY sector, industry +ORDER BY sector, companies DESC;` + +const DOC = `\n${LINE_1}\n\n${LINE_2}\n\n` + +describe('test getSqlStatements', () => { + let editorView: EditorView, + allStatements: SqlStatement[], + firstStatement: SqlStatement, + secondStatement: SqlStatement + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: DOC, + extensions: [sql({ dialect: MySQL }), sqlParser()] + }) + }) + + // dispatch any a transaction to trigger update event for editor + editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + allStatements = getSqlStatements(editorView.state) + firstStatement = allStatements[0] + secondStatement = allStatements[1] + }) + + test('getSqlStatements works well', () => { + expect(allStatements.length).toBe(2) + + expect(firstStatement.content).toBe(LINE_1) + expect(firstStatement.database).toBe('sp500insight') + expect(firstStatement.type).toBe('use') + expect(firstStatement.from).toBe(1) + expect(firstStatement.to).toBe(1 + LINE_1.length) + expect(firstStatement.lineFrom).toBe(2) + expect(firstStatement.lineTo).toBe(2) + + expect(secondStatement.content).toBe(LINE_2) + expect(secondStatement.database).toBe('sp500insight') + expect(secondStatement.type).toBe('other') + expect(secondStatement.from).toBe(1 + LINE_1.length + 2) + expect(secondStatement.to).toBe(1 + LINE_1.length + 2 + LINE_2.length) + expect(secondStatement.lineFrom).toBe(4) + expect(secondStatement.lineTo).toBe(8) + }) +}) + +describe('test getNearbyStatement', () => { + let editorView: EditorView = new EditorView() + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: DOC, + extensions: [sql({ dialect: MySQL }), sqlParser()] + }) + }) + + // dispatch any a transaction to trigger update event for editor + editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + }) + + test('getNearbyStatement works well', () => { + expect(getNearbyStatement(editorView.state, 0)?.content).toBe(LINE_1) + + expect(getNearbyStatement(editorView.state, 10)?.content).toBe(LINE_1) + + // 18 + expect( + getNearbyStatement(editorView.state, 1 + LINE_1.length)?.content + ).toBe(LINE_1) + + // 19 + expect( + getNearbyStatement(editorView.state, 1 + LINE_1.length + 1)?.content + ).toBe(LINE_1) + + // 28 + expect( + getNearbyStatement(editorView.state, 1 + LINE_1.length + 10)?.content + ).toBe(LINE_1) + + // 241 + expect( + getNearbyStatement( + editorView.state, + 1 + LINE_1.length + 2 + LINE_2.length + )?.content + ).toBe(LINE_2) + + // 241 + expect( + getNearbyStatement( + editorView.state, + 1 + LINE_1.length + 2 + LINE_2.length + )?.content + ).toBe(LINE_2) + + // 243 + expect( + getNearbyStatement( + editorView.state, + 1 + LINE_1.length + 2 + LINE_2.length + 2 + )?.content + ).toBe(LINE_2) + }) +}) diff --git a/packages/extensions/themes/CHANGELOG.md b/packages/extensions/themes/CHANGELOG.md index 8d24a2e..ba6c240 100644 --- a/packages/extensions/themes/CHANGELOG.md +++ b/packages/extensions/themes/CHANGELOG.md @@ -1,5 +1,11 @@ # @tidbcloud/codemirror-extension-themes +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params + ## 0.0.3 ### Patch Changes diff --git a/packages/extensions/themes/package.json b/packages/extensions/themes/package.json index 928b156..c25640c 100644 --- a/packages/extensions/themes/package.json +++ b/packages/extensions/themes/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/codemirror-extension-themes", - "version": "0.0.3", + "version": "0.0.4", "description": "2 simple codemirror themes", "type": "module", "main": "dist/index.js", diff --git a/packages/playground/CHANGELOG.md b/packages/playground/CHANGELOG.md index 298ee21..343648b 100644 --- a/packages/playground/CHANGELOG.md +++ b/packages/playground/CHANGELOG.md @@ -1,5 +1,21 @@ # @tidbcloud/tisqleditor-playground +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params +- Updated dependencies [122f217] + - @tidbcloud/codemirror-extension-ai-widget@0.0.4 + - @tidbcloud/codemirror-extension-cur-sql@0.0.4 + - @tidbcloud/codemirror-extension-cur-sql-gutter@0.0.4 + - @tidbcloud/codemirror-extension-linters@0.0.4 + - @tidbcloud/codemirror-extension-save-helper@0.0.4 + - @tidbcloud/codemirror-extension-sql-autocomplete@0.0.4 + - @tidbcloud/codemirror-extension-sql-parser@0.0.4 + - @tidbcloud/codemirror-extension-themes@0.0.4 + - @tidbcloud/tisqleditor-react@0.0.4 + ## 0.0.3 ### Patch Changes diff --git a/packages/playground/package.json b/packages/playground/package.json index ef6afb9..ab9dce3 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -1,7 +1,7 @@ { "name": "@tidbcloud/tisqleditor-playground", "private": true, - "version": "0.0.3", + "version": "0.0.4", "type": "module", "scripts": { "dev": "vite", diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index e498c7c..1e4fa1a 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,13 @@ # @tidbcloud/tisqleditor-react +## 0.0.4 + +### Patch Changes + +- 122f217: fix: update readme & some config params +- Updated dependencies [122f217] + - @tidbcloud/tisqleditor@0.0.4 + ## 0.0.3 ### Patch Changes diff --git a/packages/react/README.md b/packages/react/README.md index 2d2517f..9ea1511 100644 --- a/packages/react/README.md +++ b/packages/react/README.md @@ -110,4 +110,4 @@ export function OpenedFilesTabs() { - `doc`: editor initial content - `sqlConfig`: config for SQL dialect, schemas, tables - `theme`: editor theme, `@tidbcloud/codemirror-extensions-themes` provides 2 simple themes, `bbedit` for light mode, `oneDark` for dark mode, you can choose any other themes from third-party libraries or customize it by self -- `extraExts`: any other extra CodeMirror extensions you want to use, `@tidbcloud/tisqleditor-react` install some builtin extensions, likes `@tidbcloud/codemirror-extension-sql-parser`, `@tidbcloud/codemirror-extension-cur-sql` +- `extraExts`: any other extra CodeMirror extensions you want to use, `@tidbcloud/tisqleditor-react` install some builtin extensions, likes `@codemirror/lang-sql`, `@tidbcloud/codemirror-extension-sql-parser`, `@tidbcloud/codemirror-extension-cur-sql` diff --git a/packages/react/package.json b/packages/react/package.json index c6e264b..19a8152 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@tidbcloud/tisqleditor-react", - "version": "0.0.3", + "version": "0.0.4", "description": "tisqleditor react component", "type": "module", "main": "dist/index.js",