Skip to content

Commit 1e1e455

Browse files
authored
demo: adds a db language select (#17)
* wip * revert
1 parent c4e6c6c commit 1e1e455

2 files changed

Lines changed: 58 additions & 7 deletions

File tree

demo/index.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ <h2 class="text-2xl font-bold mb-4">SQL Editor with Diagnostics</h2>
3232
Try typing invalid SQL syntax to see real-time error highlighting and messages.
3333
Valid tables are: <span class="font-bold">users, posts, orders, customers, categories</span>
3434
</p>
35+
36+
<div class="flex justify-end items-center mb-2">
37+
<select id="dialect-select" class="border rounded-md p-1.5">
38+
<option value="PostgreSQL">PostgreSQL</option>
39+
<option value="MySQL">MySQL</option>
40+
<option value="SQLite">SQLite</option>
41+
<option value="MariaDB">MariaDB</option>
42+
<option value="Snowflake">Snowflake</option>
43+
</select>
44+
</div>
45+
3546
<div class="border rounded-lg bg-white shadow-sm">
3647
<div id="sql-editor" class="min-h-[400px] overflow-y-auto"></div>
3748
</div>

demo/index.ts

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { acceptCompletion } from "@codemirror/autocomplete";
2-
import { keywordCompletionSource, PostgreSQL, sql } from "@codemirror/lang-sql";
2+
import { keywordCompletionSource, MariaSQL, PostgreSQL, SQLite, sql } from "@codemirror/lang-sql";
3+
import { type EditorState, Facet, StateEffect, StateField } from "@codemirror/state";
34
import { keymap } from "@codemirror/view";
4-
55
import { basicSetup, EditorView } from "codemirror";
6+
import { NodeSqlParser } from "../src/index.js";
67
import { cteCompletionSource } from "../src/sql/cte-completion-source.js";
78
import { sqlExtension } from "../src/sql/extension.js";
89
import { DefaultSqlTooltipRenders } from "../src/sql/hover.js";
@@ -134,9 +135,6 @@ const defaultKeymap = [
134135

135136
// e.g. lazily load keyword docs
136137
const getKeywordDocs = async () => {
137-
// For compatibility with Vite and other bundlers, `import` returns a JS module and not a JSON object
138-
// So we need to nest the keywords under a json key to access them,
139-
// otherwise a keyword can conflict with a JS reserved keyword (e.g. `default` or `with`)
140138
const keywords = await import("@marimo-team/codemirror-sql/data/common-keywords.json");
141139
const duckdbKeywords = await import("@marimo-team/codemirror-sql/data/duckdb-keywords.json");
142140
return {
@@ -145,20 +143,43 @@ const getKeywordDocs = async () => {
145143
};
146144
};
147145

146+
const setDatabase = StateEffect.define<string>();
147+
148+
const databaseField = StateField.define({
149+
create: () => "PostgreSQL",
150+
update: (prevValue, transaction) => {
151+
for (const effect of transaction.effects) {
152+
if (effect.is(setDatabase)) {
153+
return effect.value;
154+
}
155+
}
156+
return prevValue;
157+
},
158+
});
159+
148160
// Initialize the SQL editor
149161
function initializeEditor() {
162+
// Use the same parser for linter and gutter
163+
const parser = new NodeSqlParser({
164+
getParserOptions: (state: EditorState) => {
165+
return {
166+
database: getDialect(state),
167+
};
168+
},
169+
});
170+
150171
const extensions = [
151172
basicSetup,
152173
EditorView.lineWrapping,
153174
keymap.of(defaultKeymap),
175+
databaseField,
154176
sql({
155177
dialect: dialect,
156178
// Example schema for autocomplete
157179
schema: schema,
158180
// Enable uppercase keywords for more traditional SQL style
159181
upperCaseKeywords: true,
160-
keywordCompletion: (label, type) => {
161-
// console.log("label", label, type);
182+
keywordCompletion: (label, _type) => {
162183
return {
163184
label,
164185
keyword: label,
@@ -182,13 +203,15 @@ function initializeEditor() {
182203
// Linter extension configuration
183204
linterConfig: {
184205
delay: 250, // Delay before running validation
206+
parser,
185207
},
186208

187209
// Gutter extension configuration
188210
gutterConfig: {
189211
backgroundColor: "#3b82f6", // Blue for current statement
190212
errorBackgroundColor: "#ef4444", // Red for invalid statements
191213
hideWhenNotFocused: true, // Hide gutter when editor loses focus
214+
parser,
192215
},
193216
// Hover extension configuration
194217
enableHover: true, // Enable hover tooltips
@@ -310,10 +333,27 @@ function setupExampleButtons() {
310333
});
311334
}
312335

336+
function getDialect(state: EditorState): string {
337+
return state.field(databaseField);
338+
}
339+
340+
function setupDialectSelect() {
341+
const select = document.querySelector("#dialect-select");
342+
if (select) {
343+
select.addEventListener("change", (e) => {
344+
const value = (e.target as HTMLSelectElement).value;
345+
editor.dispatch({
346+
effects: [setDatabase.of(value)],
347+
});
348+
});
349+
}
350+
}
351+
313352
// Initialize everything when the page loads
314353
document.addEventListener("DOMContentLoaded", () => {
315354
initializeEditor();
316355
setupExampleButtons();
356+
setupDialectSelect();
317357

318358
console.log("SQL Editor Demo initialized!");
319359
console.log("Features:");

0 commit comments

Comments
 (0)