Skip to content

Commit 4be9d2f

Browse files
committed
chore: docs, cleanup, remove dead code
1 parent b1d5f81 commit 4be9d2f

17 files changed

+281
-469
lines changed

demo/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { SQLDialect, StandardSQL, sql } from "@codemirror/lang-sql";
1+
import { StandardSQL, sql } from "@codemirror/lang-sql";
22
import { basicSetup, EditorView } from "codemirror";
33
import { cteCompletionSource } from "../src/sql/cte-completion-source.js";
44
import { sqlExtension } from "../src/sql/extension.js";
5-
import type { SqlKeywordInfo } from "../src/sql/hover.js";
65

76
// Default SQL content for the demo
87
const defaultSqlDoc = `-- Welcome to the SQL Editor Demo!

package.json

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
"demo": "vite build",
2020
"build": "tsc",
2121
"prepublishOnly": "pnpm run typecheck && pnpm run test && pnpm run build",
22-
"release": "pnpm version",
23-
"pre-commit": "lint-staged"
22+
"release": "pnpm version"
2423
},
2524
"keywords": [
2625
"codemirror",
@@ -38,9 +37,7 @@
3837
"@codemirror/view": "^6.36.2",
3938
"@vitest/coverage-v8": "3.1.3",
4039
"codemirror": "^6.0.1",
41-
"husky": "^9.1.7",
4240
"jsdom": "^26.0.0",
43-
"lint-staged": "^15.4.3",
4441
"typescript": "^5.7.3",
4542
"vite": "^7.0.0",
4643
"vitest": "^3.0.5"
@@ -65,16 +62,9 @@
6562
"node": "*"
6663
},
6764
"module": "./dist/index.js",
68-
"lint-staged": {
69-
"*.{ts,tsx}": [
70-
"biome check --write",
71-
"biome format --write",
72-
"vitest related --run"
73-
]
74-
},
7565
"dependencies": {
76-
"@codemirror/lint": "^6.0.0",
7766
"@codemirror/autocomplete": "^6.0.0",
67+
"@codemirror/lint": "^6.0.0",
7868
"node-sql-parser": "^5.3.10"
7969
}
8070
}

pnpm-lock.yaml

Lines changed: 2 additions & 340 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,49 @@
1+
import { Text } from "@codemirror/state";
2+
import type { EditorView } from "@codemirror/view";
13
import { describe, expect, it, vi } from "vitest";
24
import { sqlLinter } from "../diagnostics.js";
3-
import { SqlParser } from "../parser.js";
5+
6+
// Mock EditorView
7+
const _createMockView = (content: string) => {
8+
const doc = Text.of(content.split("\n"));
9+
return {
10+
state: { doc },
11+
} as EditorView;
12+
};
413

514
describe("sqlLinter", () => {
615
it("should create a linter extension", () => {
716
const linter = sqlLinter();
817
expect(linter).toBeDefined();
918
});
1019

11-
it("should use custom parser when provided", () => {
12-
const mockParser = vi.mocked(new SqlParser());
13-
mockParser.validateSql = vi.fn().mockReturnValue([]);
20+
it("should accept configuration with custom delay", () => {
21+
const linter = sqlLinter({ delay: 1000 });
22+
expect(linter).toBeDefined();
23+
});
24+
25+
it("should use custom parser if provided", () => {
26+
const mockParser = {
27+
validateSql: vi.fn(() => []),
28+
parseSql: vi.fn(() => ({ statements: [] })),
29+
} as any;
1430

1531
const linter = sqlLinter({ parser: mockParser });
1632
expect(linter).toBeDefined();
1733
});
1834

19-
it("should use default delay if not provided", () => {
35+
it("should use default delay when no delay provided", () => {
2036
const linter = sqlLinter();
2137
expect(linter).toBeDefined();
2238
});
2339

2440
it("should use custom delay when provided", () => {
25-
const linter = sqlLinter({ delay: 1000 });
41+
const linter = sqlLinter({ delay: 500 });
42+
expect(linter).toBeDefined();
43+
});
44+
45+
it("should use default parser when no parser provided", () => {
46+
const linter = sqlLinter();
2647
expect(linter).toBeDefined();
2748
});
2849
});
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { describe, expect, it } from "vitest";
2+
import { sqlExtension } from "../extension.js";
3+
4+
describe("sqlExtension", () => {
5+
it("should return an array of extensions with default config", () => {
6+
const extensions = sqlExtension();
7+
expect(Array.isArray(extensions)).toBe(true);
8+
expect(extensions.length).toBeGreaterThan(0);
9+
});
10+
11+
it("should return extensions with all features enabled by default", () => {
12+
const extensions = sqlExtension({});
13+
// Should include linter, gutter (4 parts), hover, and hover theme
14+
expect(extensions.length).toBeGreaterThan(2);
15+
});
16+
17+
it("should exclude linting when disabled", () => {
18+
const extensions = sqlExtension({ enableLinting: false });
19+
// Should include gutter, hover, and hover theme (no linter)
20+
expect(extensions.length).toBeGreaterThan(2);
21+
});
22+
23+
it("should exclude gutter markers when disabled", () => {
24+
const extensions = sqlExtension({ enableGutterMarkers: false });
25+
// Should include linter, hover, and hover theme (no gutter)
26+
expect(extensions.length).toBeGreaterThan(1);
27+
});
28+
29+
it("should exclude hover when disabled", () => {
30+
const extensions = sqlExtension({ enableHover: false });
31+
// Should include linter and gutter (no hover or hover theme)
32+
expect(extensions.length).toBeGreaterThan(0);
33+
});
34+
35+
it("should handle all features disabled", () => {
36+
const extensions = sqlExtension({
37+
enableLinting: false,
38+
enableGutterMarkers: false,
39+
enableHover: false,
40+
});
41+
expect(extensions).toEqual([]);
42+
});
43+
44+
it("should pass config objects to individual extensions", () => {
45+
const linterConfig = { delay: 500 };
46+
const gutterConfig = { backgroundColor: "#ff0000" };
47+
const hoverConfig = { hoverTime: 200 };
48+
49+
const extensions = sqlExtension({
50+
linterConfig,
51+
gutterConfig,
52+
hoverConfig,
53+
});
54+
55+
expect(extensions.length).toBeGreaterThan(2);
56+
});
57+
58+
it("should handle partial configuration", () => {
59+
const extensions = sqlExtension({
60+
enableLinting: true,
61+
linterConfig: { delay: 100 },
62+
});
63+
64+
expect(extensions.length).toBeGreaterThan(2);
65+
});
66+
});

src/sql/__tests__/hover-integration.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ describe("Hover Integration Tests", () => {
233233
});
234234

235235
it("should handle very long paths gracefully", () => {
236-
const longPath = "a.".repeat(20) + "final";
236+
const longPath = `${"a.".repeat(20)}final`;
237237
expect(() => {
238238
resolveNamespaceItem(testNamespace, longPath);
239239
}).not.toThrow();

src/sql/__tests__/namespace-utils.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
isArrayNamespace,
88
isObjectNamespace,
99
isSelfChildrenNamespace,
10-
type ResolvedNamespaceItem,
1110
resolveNamespaceItem,
1211
traverseNamespacePath,
1312
} from "../namespace-utils.js";
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { EditorState, Text } from "@codemirror/state";
2+
import type { EditorView } from "@codemirror/view";
3+
import { describe, expect, it } from "vitest";
4+
import { sqlStructureGutter } from "../structure-extension.js";
5+
6+
// Mock EditorView
7+
const _createMockView = (content: string, hasFocus = true) => {
8+
const doc = Text.of(content.split("\n"));
9+
const state = EditorState.create({
10+
doc,
11+
extensions: [sqlStructureGutter()],
12+
});
13+
14+
return {
15+
state,
16+
hasFocus,
17+
dispatch: () => {},
18+
} as any as EditorView;
19+
};
20+
21+
describe("sqlStructureGutter", () => {
22+
it("should create a gutter extension with default config", () => {
23+
const extensions = sqlStructureGutter();
24+
expect(Array.isArray(extensions)).toBe(true);
25+
expect(extensions.length).toBeGreaterThan(0);
26+
});
27+
28+
it("should accept custom configuration", () => {
29+
const config = {
30+
backgroundColor: "#ff0000",
31+
errorBackgroundColor: "#00ff00",
32+
width: 5,
33+
className: "custom-sql-gutter",
34+
showInvalid: false,
35+
inactiveOpacity: 0.5,
36+
hideWhenNotFocused: true,
37+
};
38+
39+
const extensions = sqlStructureGutter(config);
40+
expect(Array.isArray(extensions)).toBe(true);
41+
expect(extensions.length).toBeGreaterThan(0);
42+
});
43+
44+
it("should handle empty configuration", () => {
45+
const extensions = sqlStructureGutter({});
46+
expect(Array.isArray(extensions)).toBe(true);
47+
});
48+
49+
it("should create extensions for all required parts", () => {
50+
const extensions = sqlStructureGutter();
51+
// Should include state field, update listener, theme, and gutter
52+
expect(extensions.length).toBe(4);
53+
});
54+
55+
it("should handle unfocusedOpacity configuration", () => {
56+
const config = { unfocusedOpacity: 0.2 };
57+
const extensions = sqlStructureGutter(config);
58+
expect(extensions.length).toBe(4);
59+
});
60+
61+
it("should handle whenHide configuration", () => {
62+
const config = {
63+
whenHide: (view: EditorView) => view.state.doc.length === 0,
64+
};
65+
const extensions = sqlStructureGutter(config);
66+
expect(extensions.length).toBe(4);
67+
});
68+
69+
it("should work with minimal configuration", () => {
70+
const config = { width: 2 };
71+
const extensions = sqlStructureGutter(config);
72+
expect(extensions.length).toBe(4);
73+
});
74+
});

src/sql/cte-completion-source.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
import type { Completion, CompletionContext, CompletionSource } from "@codemirror/autocomplete";
22

3+
/**
4+
* A completion source for Common Table Expressions (CTEs) in SQL
5+
*
6+
* This function provides autocomplete suggestions for CTE references based on
7+
* WITH clauses found in the current SQL document.
8+
*
9+
* @param context The completion context from CodeMirror
10+
* @returns Completion result with CTE suggestions or null if no completions available
11+
*
12+
* @example
13+
* ```ts
14+
* import { cteCompletionSource } from '@marimo-team/codemirror-sql';
15+
* import { StandardSQL } from '@codemirror/lang-sql';
16+
*
17+
* // Add to SQL language configuration
18+
* StandardSQL.language.data.of({
19+
* autocomplete: cteCompletionSource,
20+
* })
21+
* ```
22+
*/
323
export const cteCompletionSource: CompletionSource = (context: CompletionContext) => {
424
const doc = context.state.doc.toString();
525
const cteNames = new Set<string>();

src/sql/diagnostics.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,19 @@ import { type SqlParseError, SqlParser } from "./parser.js";
55

66
const DEFAULT_DELAY = 750;
77

8+
/**
9+
* Configuration options for the SQL linter
10+
*/
811
export interface SqlLinterConfig {
12+
/** Delay in milliseconds before running validation (default: 750) */
913
delay?: number;
14+
/** Custom SQL parser instance to use for validation */
1015
parser?: SqlParser;
1116
}
1217

18+
/**
19+
* Converts a SQL parse error to a CodeMirror diagnostic
20+
*/
1321
function convertToCodeMirrorDiagnostic(error: SqlParseError, doc: Text): Diagnostic {
1422
const lineStart = doc.line(error.line).from;
1523
const from = lineStart + Math.max(0, error.column - 1);
@@ -24,6 +32,22 @@ function convertToCodeMirrorDiagnostic(error: SqlParseError, doc: Text): Diagnos
2432
};
2533
}
2634

35+
/**
36+
* Creates a SQL linter extension that validates SQL syntax and reports errors
37+
*
38+
* @param config Configuration options for the linter
39+
* @returns A CodeMirror linter extension
40+
*
41+
* @example
42+
* ```ts
43+
* import { sqlLinter } from '@marimo-team/codemirror-sql';
44+
*
45+
* const linter = sqlLinter({
46+
* delay: 500, // 500ms delay before validation
47+
* parser: new SqlParser() // custom parser instance
48+
* });
49+
* ```
50+
*/
2751
export function sqlLinter(config: SqlLinterConfig = {}) {
2852
const parser = config.parser || new SqlParser();
2953

0 commit comments

Comments
 (0)