This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new d6ab1aad3c6 Register TypeScript, Java and Go grammars for the Dag Code
tab (#74231)
d6ab1aad3c6 is described below
commit d6ab1aad3c68298817e898e8c612b6aabf03c3dd
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Mon Oct 5 15:45:54 2026 +0200
Register TypeScript, Java and Go grammars for the Dag Code tab (#74231)
* Register TypeScript, Java and Go grammars for the Dag Code tab
The Code tab already asks Monaco for whichever language the Dag source
reports (Python, TypeScript, Java, Go), but the editor's minimal entry
point only ever registered Python's tokenizer. A Dag authored in one of
the other three languages fell back to Monaco's unhighlighted default
rendering instead of real syntax coloring.
* Simplify Monaco language registration to one loop
Two near-identical registration blocks, one for Python and one for the
rest, made it read as if Python were the odd one out needing no patch.
It is the only one that does.
---
.../src/components/MonacoEditor/configureMonaco.ts | 122 +++++++++++++++------
airflow-core/src/airflow/ui/src/vite-env.d.ts | 23 +++-
2 files changed, 113 insertions(+), 32 deletions(-)
diff --git
a/airflow-core/src/airflow/ui/src/components/MonacoEditor/configureMonaco.ts
b/airflow-core/src/airflow/ui/src/components/MonacoEditor/configureMonaco.ts
index 3a2ff3d506b..ee574c0ca0a 100644
--- a/airflow-core/src/airflow/ui/src/components/MonacoEditor/configureMonaco.ts
+++ b/airflow-core/src/airflow/ui/src/components/MonacoEditor/configureMonaco.ts
@@ -58,17 +58,48 @@ const loadMonacoModules = async () => {
),
]);
- // The JSON feature registers its language as a side effect. Python is
registered
- // manually below from its grammar module instead of importing its register
module,
- // whose lazy tokens provider would overwrite our patched grammar on first
use.
- // The runtime guard below fails loudly if the grammar export shape changes.
+ // The JSON feature registers its language as a side effect. The
Dag-authoring languages
+ // are registered manually below from their grammar modules instead: Python
needs its
+ // patched grammar (triple-quoted f-string support) applied before
registering, which
+ // importing its register module instead would not allow, and the others are
registered
+ // the same way for consistency.
+ // The runtime guard below fails loudly if a grammar export shape changes.
const jsonContribution =
import("monaco-editor/languages/features/json/register");
const pythonGrammar =
import("monaco-editor/languages/definitions/python/python");
+ const typescriptGrammar =
import("monaco-editor/languages/definitions/typescript/typescript");
+ const javaGrammar = import("monaco-editor/languages/definitions/java/java");
+ const goGrammar = import("monaco-editor/languages/definitions/go/go");
- const [monaco, [editorWorkerUrl, jsonWorkerUrl], { conf: pythonConf,
language: pythonLanguage }] =
- await Promise.all([monacoApi, workerUrls, pythonGrammar,
jsonContribution]);
+ const [
+ monaco,
+ [editorWorkerUrl, jsonWorkerUrl],
+ { conf: pythonConf, language: pythonLanguage },
+ { conf: typescriptConf, language: typescriptLanguage },
+ { conf: javaConf, language: javaLanguage },
+ { conf: goConf, language: goLanguage },
+ ] = await Promise.all([
+ monacoApi,
+ workerUrls,
+ pythonGrammar,
+ typescriptGrammar,
+ javaGrammar,
+ goGrammar,
+ jsonContribution,
+ ]);
- return { editorWorkerUrl, jsonWorkerUrl, monaco, pythonConf, pythonLanguage
};
+ return {
+ editorWorkerUrl,
+ goConf,
+ goLanguage,
+ javaConf,
+ javaLanguage,
+ jsonWorkerUrl,
+ monaco,
+ pythonConf,
+ pythonLanguage,
+ typescriptConf,
+ typescriptLanguage,
+ };
};
const createWorkerFromUrl = (workerUrl: string): Worker => {
@@ -85,30 +116,59 @@ export const configureMonaco = () => {
}
configurationPromise = loadMonacoModules()
- .then(({ editorWorkerUrl, jsonWorkerUrl, monaco, pythonConf,
pythonLanguage }) => {
- Reflect.set(globalThis, "MonacoEnvironment", {
- getWorker: (_moduleId: string, label: string) =>
- createWorkerFromUrl(label === "json" ? jsonWorkerUrl :
editorWorkerUrl),
- } satisfies MonacoEnvironment);
-
- // Register Python with the patched grammar (triple-quoted f-string
support). The
- // editor always sets `language="python"` explicitly, so no
extensions/firstLine
- // auto-detection metadata is needed. Guard the internal grammar export
shape: if a
- // monaco upgrade drops these, fail loudly here rather than silently
disabling
- // Python highlighting (`setMonarchTokensProvider("python", undefined)`).
- // The `conf`/`language` types come from a hand-written ambient
declaration, so
- // TypeScript believes they are always defined; this guard checks the
real runtime
- // shape the types cannot vouch for.
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- if (pythonConf === undefined || pythonLanguage === undefined) {
- throw new Error("monaco Python grammar module changed shape: missing
`conf`/`language` export");
- }
- monaco.languages.register({ id: "python" });
- monaco.languages.setLanguageConfiguration("python", pythonConf);
- monaco.languages.setMonarchTokensProvider("python",
patchPythonFStrings(pythonLanguage));
-
- loader.config({ monaco });
- })
+ .then(
+ ({
+ editorWorkerUrl,
+ goConf,
+ goLanguage,
+ javaConf,
+ javaLanguage,
+ jsonWorkerUrl,
+ monaco,
+ pythonConf,
+ pythonLanguage,
+ typescriptConf,
+ typescriptLanguage,
+ }) => {
+ Reflect.set(globalThis, "MonacoEnvironment", {
+ getWorker: (_moduleId: string, label: string) =>
+ createWorkerFromUrl(label === "json" ? jsonWorkerUrl :
editorWorkerUrl),
+ } satisfies MonacoEnvironment);
+
+ // The editor always sets the Dag's own language explicitly, so no
extensions/firstLine
+ // auto-detection metadata is needed for any of these. Guard the
internal grammar
+ // export shape: if a monaco upgrade drops these, fail loudly here
rather than
+ // silently disabling highlighting (`setMonarchTokensProvider(id,
undefined)`).
+ // The `conf`/`language` types come from hand-written ambient
declarations, so
+ // TypeScript believes they are always defined; this guard checks the
real runtime
+ // shape the types cannot vouch for.
+ const grammars = [
+ { conf: pythonConf, id: "python", language: pythonLanguage },
+ { conf: typescriptConf, id: "typescript", language:
typescriptLanguage },
+ { conf: javaConf, id: "java", language: javaLanguage },
+ { conf: goConf, id: "go", language: goLanguage },
+ ] as const;
+
+ for (const grammar of grammars) {
+ // eslint-disable-next-line
@typescript-eslint/no-unnecessary-condition
+ if (grammar.conf === undefined || grammar.language === undefined) {
+ throw new Error(
+ `monaco ${grammar.id} grammar module changed shape: missing
\`conf\`/\`language\` export`,
+ );
+ }
+ monaco.languages.register({ id: grammar.id });
+ monaco.languages.setLanguageConfiguration(grammar.id, grammar.conf);
+ // Python needs the patched grammar (triple-quoted f-string
support); the rest
+ // register as monaco ships them.
+ monaco.languages.setMonarchTokensProvider(
+ grammar.id,
+ grammar.id === "python" ? patchPythonFStrings(grammar.language) :
grammar.language,
+ );
+ }
+
+ loader.config({ monaco });
+ },
+ )
.catch((error: unknown) => {
configurationPromise = undefined;
// eslint-disable-next-line no-console
diff --git a/airflow-core/src/airflow/ui/src/vite-env.d.ts
b/airflow-core/src/airflow/ui/src/vite-env.d.ts
index 0efa1e9c8b0..cc1756f032a 100644
--- a/airflow-core/src/airflow/ui/src/vite-env.d.ts
+++ b/airflow-core/src/airflow/ui/src/vite-env.d.ts
@@ -25,7 +25,7 @@ interface ImportMeta {
readonly env: ImportMetaEnv;
}
-// The Python language definition exports its Monarch grammar (`conf` /
`language`)
+// Each of these language definitions exports its Monarch grammar (`conf` /
`language`)
// but ships no `.d.ts` of its own.
declare module "monaco-editor/languages/definitions/python/python" {
// `import(...)` type syntax is required here: a top-level `import type`
would turn this
@@ -35,3 +35,24 @@ declare module
"monaco-editor/languages/definitions/python/python" {
export const language: import("monaco-editor").languages.IMonarchLanguage;
/* eslint-enable @typescript-eslint/consistent-type-imports */
}
+
+declare module "monaco-editor/languages/definitions/typescript/typescript" {
+ /* eslint-disable @typescript-eslint/consistent-type-imports */
+ export const conf: import("monaco-editor").languages.LanguageConfiguration;
+ export const language: import("monaco-editor").languages.IMonarchLanguage;
+ /* eslint-enable @typescript-eslint/consistent-type-imports */
+}
+
+declare module "monaco-editor/languages/definitions/java/java" {
+ /* eslint-disable @typescript-eslint/consistent-type-imports */
+ export const conf: import("monaco-editor").languages.LanguageConfiguration;
+ export const language: import("monaco-editor").languages.IMonarchLanguage;
+ /* eslint-enable @typescript-eslint/consistent-type-imports */
+}
+
+declare module "monaco-editor/languages/definitions/go/go" {
+ /* eslint-disable @typescript-eslint/consistent-type-imports */
+ export const conf: import("monaco-editor").languages.LanguageConfiguration;
+ export const language: import("monaco-editor").languages.IMonarchLanguage;
+ /* eslint-enable @typescript-eslint/consistent-type-imports */
+}