diff --git a/src/lib/components/editor/MonacoEditor.svelte b/src/lib/components/editor/MonacoEditor.svelte index 65a57c93..953e40e2 100644 --- a/src/lib/components/editor/MonacoEditor.svelte +++ b/src/lib/components/editor/MonacoEditor.svelte @@ -2,11 +2,7 @@ import { onMount, onDestroy } from 'svelte'; import { browser } from '$app/environment'; import { theme } from '$lib/theme.svelte'; - import { - registerTrinoSql, - setCompletionDefaultsGetter, - TRINO_SQL_LANGUAGE_ID - } from '$lib/editor/trinosql'; + import { TRINO_SQL_LANGUAGE_ID } from '$lib/editor/language-id'; let { value = $bindable(), @@ -134,6 +130,8 @@ // Guarded by `browser` because SvelteKit evaluates component scripts on the server too. const workerImport = browser ? import('monaco-editor/esm/vs/editor/editor.worker?worker') : null; const monacoImport = browser ? import('monaco-editor') : null; + // The Trino SQL language pulls in the ANTLR parser (~1 MB); load it lazily alongside Monaco. + const trinoSqlImport = browser ? import('$lib/editor/trinosql') : null; function toMonacoTheme(t: string): string { return t === 'dark' ? 'vs-dark' : 'vs'; @@ -151,6 +149,7 @@ }; monaco = await monacoImport!; + const { registerTrinoSql, setCompletionDefaultsGetter } = await trinoSqlImport!; setCompletionDefaultsGetter(() => ({ catalog: defaultCatalog || undefined, diff --git a/src/lib/editor/language-id.ts b/src/lib/editor/language-id.ts new file mode 100644 index 00000000..ecd52a40 --- /dev/null +++ b/src/lib/editor/language-id.ts @@ -0,0 +1,3 @@ +// Kept separate from trinosql.ts so it can be imported without pulling in the +// ANTLR lexer/parser, which are only loaded client-side together with Monaco. +export const TRINO_SQL_LANGUAGE_ID = 'trinosql'; diff --git a/src/lib/editor/trinosql.ts b/src/lib/editor/trinosql.ts index ab345730..9db59e6c 100644 --- a/src/lib/editor/trinosql.ts +++ b/src/lib/editor/trinosql.ts @@ -6,13 +6,12 @@ import type * as Monaco from 'monaco-editor'; import { CharStream } from 'antlr4ng'; import { SqlBaseLexer } from './generated/SqlBaseLexer.js'; import { tokenMap } from './tokenMap'; +import { TRINO_SQL_LANGUAGE_ID } from './language-id.js'; import { createCompletionProvider, type CompletionDefaults } from './completion/completion-provider.js'; -const LANGUAGE_ID = 'trinosql'; - class TrinoSqlTokenizerState implements Monaco.languages.IState { clone(): Monaco.languages.IState { return new TrinoSqlTokenizerState(); @@ -39,20 +38,20 @@ export interface RegisterOptions { } export function registerTrinoSql(monaco: typeof Monaco, options: RegisterOptions = {}): void { - if (monaco.languages.getLanguages().some((lang) => lang.id === LANGUAGE_ID)) { + if (monaco.languages.getLanguages().some((lang) => lang.id === TRINO_SQL_LANGUAGE_ID)) { return; } - monaco.languages.register({ id: LANGUAGE_ID }); + monaco.languages.register({ id: TRINO_SQL_LANGUAGE_ID }); if (options.completionEnabled !== false) { monaco.languages.registerCompletionItemProvider( - LANGUAGE_ID, + TRINO_SQL_LANGUAGE_ID, createCompletionProvider(monaco, () => defaultsGetter()) ); } - monaco.languages.setTokensProvider(LANGUAGE_ID, { + monaco.languages.setTokensProvider(TRINO_SQL_LANGUAGE_ID, { getInitialState: () => new TrinoSqlTokenizerState(), tokenize: (line: string, state: Monaco.languages.IState) => { const inputStream = CharStream.fromString(line); @@ -73,5 +72,3 @@ export function registerTrinoSql(monaco: typeof Monaco, options: RegisterOptions } }); } - -export { LANGUAGE_ID as TRINO_SQL_LANGUAGE_ID };