@elastic/monaco-esql 3.1.15 → 3.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,9 +19,7 @@ monaco.languages.setMonarchTokensProvider("esql", monarchLanguage);
19
19
 
20
20
  ## Releasing
21
21
 
22
- To release a new version add a `publish` label to the PR.
23
-
24
- There is no need to bump the version manually, release-it does it automatically.
22
+ To release a new version, bump the `version` field in the `package.json` and add a `publish` label to the PR.
25
23
 
26
24
  ## License
27
25
 
@@ -194,6 +194,7 @@ exports.delimiters = [
194
194
  "/",
195
195
  ".",
196
196
  ",",
197
+ ";",
197
198
  "=~",
198
199
  "<=",
199
200
  ">=",
package/lib/monarch.js CHANGED
@@ -9,6 +9,7 @@
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.create = void 0;
12
+ const promql_1 = require("./promql");
12
13
  const create = (deps = {}) => {
13
14
  const { headerCommands = [], sourceCommands = [], processingCommands = [], options = [], literals = [], functions = [], delimiters = [], temporalUnits = [], } = deps;
14
15
  const timeUnits = withLowercaseVariants(temporalUnits.flat()).sort((a, b) => a > b ? -1 : 1);
@@ -42,7 +43,30 @@ const create = (deps = {}) => {
42
43
  { open: "<", close: ">", token: "delimiter.angle" },
43
44
  ],
44
45
  tokenizer: {
45
- root: [
46
+ root: [{ include: "@firstCommandName" }, { include: "@restOfQuery" }],
47
+ // This block matches the first command name in the query, and identifies it as a source command.
48
+ // Except if it's a header command.
49
+ // This is useful to color querys that starts with "From" instead of "FROM".
50
+ firstCommandName: [
51
+ { include: "@whitespace" },
52
+ [
53
+ /[a-zA-Z]+/,
54
+ {
55
+ cases: {
56
+ "PROMQL|promql": {
57
+ token: "keyword.command.source.promql",
58
+ switchTo: "@promQLCommand",
59
+ },
60
+ "@headerCommands": { token: "keyword.command.header.$0" },
61
+ "@default": {
62
+ token: "keyword.command.source.$0",
63
+ switchTo: "@restOfQuery",
64
+ },
65
+ },
66
+ },
67
+ ],
68
+ ],
69
+ restOfQuery: [
46
70
  { include: "@whitespace" },
47
71
  // Keywords
48
72
  [
@@ -64,6 +88,9 @@ const create = (deps = {}) => {
64
88
  },
65
89
  ],
66
90
  { include: "@expression" },
91
+ // If we found a semicolon, means a header command finished.
92
+ // We go back to root to parse the query.
93
+ [/;/, { token: "delimiter", switchTo: "@root" }],
67
94
  { include: "@processingCommand" },
68
95
  [/\[|\(|\)|\]/, "@brackets"],
69
96
  [
@@ -115,25 +142,32 @@ const create = (deps = {}) => {
115
142
  ["", { token: "", switchTo: "@commandName" }],
116
143
  ],
117
144
  exactCommandName: [
145
+ [
146
+ "PROMQL|promql",
147
+ {
148
+ token: "keyword.command.source.promql",
149
+ switchTo: "@promQLCommand",
150
+ },
151
+ ],
118
152
  [
119
153
  withLowercaseVariants(headerCommands).join("|"),
120
- { token: "keyword.command.header.$0", switchTo: "@root" },
154
+ { token: "keyword.command.header.$0", switchTo: "@restOfQuery" },
121
155
  ],
122
156
  [
123
157
  withLowercaseVariants(sourceCommands).join("|"),
124
- { token: "keyword.command.source.$0", switchTo: "@root" },
158
+ { token: "keyword.command.source.$0", switchTo: "@restOfQuery" },
125
159
  ],
126
160
  [
127
161
  withLowercaseVariants(processingCommands).join("|"),
128
- { token: "keyword.command.processing.$0", switchTo: "@root" },
162
+ { token: "keyword.command.processing.$0", switchTo: "@restOfQuery" },
129
163
  ],
130
164
  ],
131
165
  firstCommandNameInSubQuery: [
132
166
  { include: "@whitespace" },
133
167
  // Try to match an exact command name
134
168
  { include: "@exactCommandName" },
135
- // If not matched, go to root
136
- { include: "@root" },
169
+ // If not matched, go to restOfQuery
170
+ { include: "@restOfQuery" },
137
171
  ],
138
172
  // Matches *command name*, i.e. the mnemonic.
139
173
  commandName: [
@@ -142,7 +176,7 @@ const create = (deps = {}) => {
142
176
  // If command name is not well known, just matches the first word.
143
177
  [
144
178
  /\w+\b/,
145
- { token: "keyword.command.processing.$0", switchTo: "@root" },
179
+ { token: "keyword.command.processing.$0", switchTo: "@restOfQuery" },
146
180
  ],
147
181
  ],
148
182
  // ------------------------------------------------------------- Expressions
@@ -208,6 +242,8 @@ const create = (deps = {}) => {
208
242
  [/\\./, "string.escape.invalid"],
209
243
  [/`/, "string", "@pop"],
210
244
  ],
245
+ // ------------------------------------------------------------- PROMQL
246
+ ...promql_1.promQLStates,
211
247
  },
212
248
  };
213
249
  };
@@ -0,0 +1,36 @@
1
+ import type { languages } from "monaco-editor";
2
+ /**
3
+ * In order to handle the PROMQL command we need to solve two problems:
4
+ * 1. Detect when the params section ends and the query starts, so we can apply the promql query embedding.
5
+ * For this we tokenize the params section with dedicated states, before delegating to the promql query embedding.
6
+ *
7
+ * 2. We need to correctly tokenize ES|QL comments syntax within a promql query.
8
+ * For this we use the promQLQuery state, which is applied while tokenizing the query content.
9
+ * It will tell the embedded language when the query ends (when a pipe is found).
10
+ * And will switch to dedicated states for handling comments.
11
+ */
12
+ /** Main state for PROMQL command. */
13
+ export declare const promQLCommand: languages.IMonarchLanguageRule[];
14
+ /**
15
+ * State to tokenize param name, then switch to value
16
+ */
17
+ export declare const promqlParam: languages.IMonarchLanguageRule[];
18
+ /**
19
+ * State to parse param values.
20
+ * The way of detecting a param value ended is by detecting whitespaces that are not followed by a comma.
21
+ * Example of a value that contains a list of indexes: index-*, `index`, index::selector, ?param, "index"
22
+ */
23
+ export declare const promqlParamValue: languages.IMonarchLanguageRule[];
24
+ /**
25
+ * These rules are applied while tokenizing the query content (inside the embedding language).
26
+ * They run "in parallel" with the rules from the embedded language.
27
+ * We use them the tell the embedded language when the query ends (when a pipe is found).
28
+ * And to be able to tokenize ES|QL comments within the PROMQL query.
29
+ */
30
+ export declare const promQLQuery: languages.IMonarchLanguageRule[];
31
+ /**
32
+ * All PromQL tokenizer states needed to tokenize a PROMQL command bundled in one object.
33
+ */
34
+ export declare const promQLStates: {
35
+ [name: string]: languages.IMonarchLanguageRule[];
36
+ };
package/lib/promql.js ADDED
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.promQLStates = exports.promQLQuery = exports.promqlParamValue = exports.promqlParam = exports.promQLCommand = void 0;
4
+ /**
5
+ * In order to handle the PROMQL command we need to solve two problems:
6
+ * 1. Detect when the params section ends and the query starts, so we can apply the promql query embedding.
7
+ * For this we tokenize the params section with dedicated states, before delegating to the promql query embedding.
8
+ *
9
+ * 2. We need to correctly tokenize ES|QL comments syntax within a promql query.
10
+ * For this we use the promQLQuery state, which is applied while tokenizing the query content.
11
+ * It will tell the embedded language when the query ends (when a pipe is found).
12
+ * And will switch to dedicated states for handling comments.
13
+ */
14
+ /** Main state for PROMQL command. */
15
+ exports.promQLCommand = [
16
+ { include: "@whitespace" },
17
+ // Match param pattern: paramName = ...
18
+ [/[a-zA-Z0-9_*?"`-]+\s*=\s*/, { token: "@rematch", next: "@promqlParam" }],
19
+ // Start PromQL query embedding (no more params)
20
+ [
21
+ /.+/,
22
+ { token: "@rematch", switchTo: "@promQLQuery", nextEmbedded: "promql" },
23
+ ],
24
+ ];
25
+ /**
26
+ * State to tokenize param name, then switch to value
27
+ */
28
+ exports.promqlParam = [
29
+ // Match param name
30
+ { include: "@expression" },
31
+ // Tokenize assignment and go to value
32
+ [/=\s*/, { token: "delimiter.assignment", switchTo: "@promqlParamValue" }],
33
+ ];
34
+ /**
35
+ * State to parse param values.
36
+ * The way of detecting a param value ended is by detecting whitespaces that are not followed by a comma.
37
+ * Example of a value that contains a list of indexes: index-*, `index`, index::selector, ?param, "index"
38
+ */
39
+ exports.promqlParamValue = [
40
+ // Whitespace handling: comma continues list, otherwise pop
41
+ [/\s+(?=,)/, ""], // Whitespace before comma - continue
42
+ [/\s+/, { token: "", next: "@pop" }], // Whitespace not before comma - pop (query or next param)
43
+ // Match value content
44
+ { include: "@expression" },
45
+ // Comma continues the list
46
+ [/,\s*/, "delimiter.comma"],
47
+ // Fallback: pop if nothing else matches
48
+ ["", { token: "", next: "@pop" }],
49
+ ];
50
+ /**
51
+ * These rules are applied while tokenizing the query content (inside the embedding language).
52
+ * They run "in parallel" with the rules from the embedded language.
53
+ * We use them the tell the embedded language when the query ends (when a pipe is found).
54
+ * And to be able to tokenize ES|QL comments within the PROMQL query.
55
+ */
56
+ exports.promQLQuery = [
57
+ // Rules to delegate comments to ES|QL
58
+ [
59
+ /\/\*\*(?!\/)/,
60
+ {
61
+ token: "comment.doc",
62
+ next: "@promqlDocComment",
63
+ nextEmbedded: "@pop",
64
+ },
65
+ ],
66
+ [/\/\*/, { token: "comment", next: "@promqlComment", nextEmbedded: "@pop" }],
67
+ [
68
+ /\/\//,
69
+ {
70
+ token: "comment",
71
+ next: "@promqlLineComment",
72
+ nextEmbedded: "@pop",
73
+ },
74
+ ],
75
+ // Exit condition
76
+ [
77
+ /\|/,
78
+ {
79
+ token: "delimiter.pipe",
80
+ switchTo: "@beforeMnemonicWhitespace",
81
+ nextEmbedded: "@pop",
82
+ },
83
+ ],
84
+ ];
85
+ /**
86
+ * These states are used for returning the control the promql embedding after a comment ends.
87
+ */
88
+ const promQLQueryOverrideRules = {
89
+ promqlDocComment: [
90
+ [/[^/*]+/, "comment.doc"],
91
+ [/\*\//, { token: "comment.doc", next: "@pop", nextEmbedded: "promql" }],
92
+ [/[/*]/, "comment.doc"],
93
+ ],
94
+ promqlComment: [
95
+ [/[^/*]+/, "comment"],
96
+ [/\*\//, { token: "comment", next: "@pop", nextEmbedded: "promql" }],
97
+ [/[/*]/, "comment"],
98
+ ],
99
+ promqlLineComment: [
100
+ [/.*$/, { token: "comment", next: "@pop", nextEmbedded: "promql" }],
101
+ ],
102
+ };
103
+ /**
104
+ * All PromQL tokenizer states needed to tokenize a PROMQL command bundled in one object.
105
+ */
106
+ exports.promQLStates = {
107
+ promQLCommand: exports.promQLCommand,
108
+ promqlParam: exports.promqlParam,
109
+ promqlParamValue: exports.promqlParamValue,
110
+ promQLQuery: exports.promQLQuery,
111
+ ...promQLQueryOverrideRules,
112
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elastic/monaco-esql",
3
- "version": "3.1.15",
3
+ "version": "3.1.17",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -24,7 +24,7 @@
24
24
  "build": "yarn build:es2020",
25
25
  "storybook": "storybook dev -p 6006",
26
26
  "build-storybook": "storybook build",
27
- "release": "npx release-it --ci",
27
+ "release": "npx release-it --ci --no-increment",
28
28
  "prepare": "husky"
29
29
  },
30
30
  "license": "MIT",
@@ -49,35 +49,42 @@
49
49
  },
50
50
  "homepage": "https://github.com/elastic/monaco-esql",
51
51
  "peerDependencies": {
52
- "monaco-editor": "*"
52
+ "monaco-editor": "*",
53
+ "monaco-promql": "*"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "monaco-promql": {
57
+ "optional": true
58
+ }
53
59
  },
54
60
  "devDependencies": {
55
- "@babel/eslint-parser": "7.28.5",
61
+ "@babel/eslint-parser": "7.28.6",
56
62
  "@biomejs/biome": "2.3.11",
57
- "@chromatic-com/storybook": "4.1.3",
63
+ "@chromatic-com/storybook": "5.0.0",
58
64
  "@eslint/js": "9.39.2",
59
65
  "@monaco-editor/react": "4.7.0",
60
- "@storybook/addon-docs": "10.1.11",
61
- "@storybook/addon-onboarding": "10.1.11",
62
- "@storybook/addon-vitest": "10.1.11",
63
- "@storybook/react-vite": "10.1.11",
64
- "@types/react": "19.2.7",
65
- "@vitest/browser": "4.0.16",
66
- "@vitest/browser-playwright": "4.0.16",
67
- "@vitest/coverage-v8": "4.0.16",
66
+ "@storybook/addon-docs": "10.2.6",
67
+ "@storybook/addon-onboarding": "10.2.6",
68
+ "@storybook/addon-vitest": "10.2.6",
69
+ "@storybook/react-vite": "10.2.6",
70
+ "@types/react": "19.2.9",
71
+ "@vitest/browser": "4.0.18",
72
+ "@vitest/browser-playwright": "4.0.18",
73
+ "@vitest/coverage-v8": "4.0.18",
68
74
  "eslint": "9.39.2",
69
75
  "eslint-plugin-react": "7.37.5",
70
- "globals": "17.0.0",
76
+ "globals": "17.3.0",
71
77
  "husky": "9.1.7",
72
78
  "lint-staged": "16.2.7",
73
79
  "monaco-editor": "0.55.1",
80
+ "monaco-promql": "1.8.0",
74
81
  "playwright": "1.57.0",
75
82
  "react": "19.2.3",
76
83
  "react-dom": "19.2.3",
77
- "storybook": "10.1.11",
84
+ "storybook": "10.2.6",
78
85
  "typescript": "5.9.3",
79
- "typescript-eslint": "8.52.0",
80
- "vitest": "4.0.16"
86
+ "typescript-eslint": "8.54.0",
87
+ "vitest": "4.0.18"
81
88
  },
82
89
  "lint-staged": {
83
90
  "*.{js,ts,tsx,mjs}": [