@perses-dev/loki-plugin 0.5.0-rc.0 → 0.5.0
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/__mf/js/{Loki.21b585d6.js → Loki.2bd94c1e.js} +3 -3
- package/__mf/js/async/1728.326f0c08.js +1 -0
- package/__mf/js/async/1750.eba509e1.js +1 -0
- package/__mf/js/async/392.2c7c202d.js +2 -0
- package/__mf/js/async/54.b3492a7a.js +22 -0
- package/__mf/js/async/5440.995ad0c5.js +2 -0
- package/__mf/js/async/{5440.3fedd5ea.js.LICENSE.txt → 5440.995ad0c5.js.LICENSE.txt} +3 -3
- package/__mf/js/async/6710.a94fd362.js +2 -0
- package/__mf/js/async/7958.f25f7332.js +7 -0
- package/__mf/js/async/9010.44bf2927.js +2 -0
- package/__mf/js/async/{1238.71fd7843.js → 9249.d90da2ad.js} +1 -1
- package/__mf/js/async/9389.29616aa6.js +2 -0
- package/__mf/js/async/9877.b76d1711.js +38 -0
- package/__mf/js/async/{__federation_expose_LokiDatasource.44ac1fa6.js → __federation_expose_LokiDatasource.3fe6141d.js} +2 -2
- package/__mf/js/async/{__federation_expose_LokiLogQuery.22f7c517.js → __federation_expose_LokiLogQuery.6591d0db.js} +1 -1
- package/__mf/js/async/{__federation_expose_LokiTimeSeriesQuery.4909566f.js → __federation_expose_LokiTimeSeriesQuery.2a9b451a.js} +1 -1
- package/__mf/js/{main.59f3d316.js → main.4d84b446.js} +3 -3
- package/lib/bootstrap.js +12 -0
- package/lib/bootstrap.js.map +1 -1
- package/lib/cjs/bootstrap.js +12 -0
- package/lib/cjs/components/complete.js +260 -34
- package/lib/cjs/components/index.js +1 -1
- package/lib/cjs/components/logql-editor.js +1 -1
- package/lib/cjs/components/logql-extension.js +1 -1
- package/lib/cjs/components/logql-highlight.js +1 -1
- package/lib/cjs/datasources/index.js +1 -1
- package/lib/cjs/datasources/loki-datasource/LokiDatasource.js +1 -1
- package/lib/cjs/datasources/loki-datasource/LokiDatasourceEditor.js +1 -1
- package/lib/cjs/datasources/loki-datasource/index.js +1 -1
- package/lib/cjs/datasources/loki-datasource/loki-datasource-types.js +1 -1
- package/lib/cjs/env.d.js +12 -0
- package/lib/cjs/getPluginModule.js +12 -0
- package/lib/cjs/index-federation.js +12 -0
- package/lib/cjs/index.js +12 -0
- package/lib/cjs/model/index.js +1 -1
- package/lib/cjs/model/loki-client-types.js +1 -1
- package/lib/cjs/model/loki-client.js +1 -1
- package/lib/cjs/model/loki-data-types.js +1 -1
- package/lib/cjs/model/loki-selectors.js +1 -1
- package/lib/cjs/queries/constants.js +12 -0
- package/lib/cjs/queries/index.js +1 -1
- package/lib/cjs/queries/loki-log-query/LokiLogQuery.js +12 -0
- package/lib/cjs/queries/loki-log-query/LokiLogQueryEditor.js +1 -1
- package/lib/cjs/queries/loki-log-query/get-loki-log-data.js +12 -0
- package/lib/cjs/queries/loki-log-query/index.js +12 -0
- package/lib/cjs/queries/loki-log-query/log-query-plugin-interface.js +12 -0
- package/lib/cjs/queries/loki-log-query/loki-log-query-types.js +12 -0
- package/lib/cjs/queries/loki-time-series-query/LokiTimeSeriesQuery.js +1 -1
- package/lib/cjs/queries/loki-time-series-query/LokiTimeSeriesQueryEditor.js +1 -1
- package/lib/cjs/queries/loki-time-series-query/get-loki-time-series-data.js +1 -1
- package/lib/cjs/queries/loki-time-series-query/index.js +1 -1
- package/lib/cjs/queries/loki-time-series-query/loki-time-series-query-types.js +1 -1
- package/lib/cjs/queries/query-editor-model.js +1 -1
- package/lib/cjs/setup-tests.js +12 -0
- package/lib/components/complete.d.ts +5 -0
- package/lib/components/complete.d.ts.map +1 -1
- package/lib/components/complete.js +259 -33
- package/lib/components/complete.js.map +1 -1
- package/lib/components/index.js +1 -1
- package/lib/components/index.js.map +1 -1
- package/lib/components/logql-editor.js +1 -1
- package/lib/components/logql-editor.js.map +1 -1
- package/lib/components/logql-extension.js +1 -1
- package/lib/components/logql-extension.js.map +1 -1
- package/lib/components/logql-highlight.js +1 -1
- package/lib/components/logql-highlight.js.map +1 -1
- package/lib/datasources/index.js +1 -1
- package/lib/datasources/index.js.map +1 -1
- package/lib/datasources/loki-datasource/LokiDatasource.js +1 -1
- package/lib/datasources/loki-datasource/LokiDatasource.js.map +1 -1
- package/lib/datasources/loki-datasource/LokiDatasourceEditor.js +1 -1
- package/lib/datasources/loki-datasource/LokiDatasourceEditor.js.map +1 -1
- package/lib/datasources/loki-datasource/index.js +1 -1
- package/lib/datasources/loki-datasource/index.js.map +1 -1
- package/lib/datasources/loki-datasource/loki-datasource-types.js +1 -1
- package/lib/datasources/loki-datasource/loki-datasource-types.js.map +1 -1
- package/lib/env.d.js +12 -0
- package/lib/env.d.js.map +1 -1
- package/lib/getPluginModule.d.ts.map +1 -1
- package/lib/getPluginModule.js +12 -0
- package/lib/getPluginModule.js.map +1 -1
- package/lib/index-federation.js +12 -0
- package/lib/index-federation.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +12 -0
- package/lib/index.js.map +1 -1
- package/lib/model/index.js +1 -1
- package/lib/model/index.js.map +1 -1
- package/lib/model/loki-client-types.js +1 -1
- package/lib/model/loki-client-types.js.map +1 -1
- package/lib/model/loki-client.js +1 -1
- package/lib/model/loki-client.js.map +1 -1
- package/lib/model/loki-data-types.js +1 -1
- package/lib/model/loki-data-types.js.map +1 -1
- package/lib/model/loki-selectors.js +1 -1
- package/lib/model/loki-selectors.js.map +1 -1
- package/lib/queries/constants.d.ts.map +1 -1
- package/lib/queries/constants.js +12 -0
- package/lib/queries/constants.js.map +1 -1
- package/lib/queries/index.js +1 -1
- package/lib/queries/index.js.map +1 -1
- package/lib/queries/loki-log-query/LokiLogQuery.d.ts.map +1 -1
- package/lib/queries/loki-log-query/LokiLogQuery.js +12 -0
- package/lib/queries/loki-log-query/LokiLogQuery.js.map +1 -1
- package/lib/queries/loki-log-query/LokiLogQueryEditor.js +1 -1
- package/lib/queries/loki-log-query/LokiLogQueryEditor.js.map +1 -1
- package/lib/queries/loki-log-query/get-loki-log-data.d.ts.map +1 -1
- package/lib/queries/loki-log-query/get-loki-log-data.js +12 -0
- package/lib/queries/loki-log-query/get-loki-log-data.js.map +1 -1
- package/lib/queries/loki-log-query/index.d.ts.map +1 -1
- package/lib/queries/loki-log-query/index.js +12 -0
- package/lib/queries/loki-log-query/index.js.map +1 -1
- package/lib/queries/loki-log-query/log-query-plugin-interface.d.ts.map +1 -1
- package/lib/queries/loki-log-query/log-query-plugin-interface.js +12 -0
- package/lib/queries/loki-log-query/log-query-plugin-interface.js.map +1 -1
- package/lib/queries/loki-log-query/loki-log-query-types.d.ts.map +1 -1
- package/lib/queries/loki-log-query/loki-log-query-types.js +12 -0
- package/lib/queries/loki-log-query/loki-log-query-types.js.map +1 -1
- package/lib/queries/loki-time-series-query/LokiTimeSeriesQuery.js +1 -1
- package/lib/queries/loki-time-series-query/LokiTimeSeriesQuery.js.map +1 -1
- package/lib/queries/loki-time-series-query/LokiTimeSeriesQueryEditor.js +1 -1
- package/lib/queries/loki-time-series-query/LokiTimeSeriesQueryEditor.js.map +1 -1
- package/lib/queries/loki-time-series-query/get-loki-time-series-data.js +1 -1
- package/lib/queries/loki-time-series-query/get-loki-time-series-data.js.map +1 -1
- package/lib/queries/loki-time-series-query/index.js +1 -1
- package/lib/queries/loki-time-series-query/index.js.map +1 -1
- package/lib/queries/loki-time-series-query/loki-time-series-query-types.js +1 -1
- package/lib/queries/loki-time-series-query/loki-time-series-query-types.js.map +1 -1
- package/lib/queries/query-editor-model.js +1 -1
- package/lib/queries/query-editor-model.js.map +1 -1
- package/lib/setup-tests.d.ts.map +1 -1
- package/lib/setup-tests.js +12 -0
- package/lib/setup-tests.js.map +1 -1
- package/mf-manifest.json +46 -46
- package/mf-stats.json +46 -46
- package/package.json +6 -6
- package/__mf/js/async/1490.5aa6cbcc.js +0 -22
- package/__mf/js/async/1501.f1011a16.js +0 -1
- package/__mf/js/async/1728.516fcaaf.js +0 -1
- package/__mf/js/async/3849.89f86737.js +0 -7
- package/__mf/js/async/392.c0f9d49a.js +0 -2
- package/__mf/js/async/5440.3fedd5ea.js +0 -2
- package/__mf/js/async/5501.929e6257.js +0 -2
- package/__mf/js/async/6498.903f2a94.js +0 -2
- package/__mf/js/async/8035.8dab4893.js +0 -38
- package/__mf/js/async/9389.a8ea42a0.js +0 -2
- /package/__mf/js/async/{392.c0f9d49a.js.LICENSE.txt → 392.2c7c202d.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{1490.5aa6cbcc.js.LICENSE.txt → 54.b3492a7a.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{6498.903f2a94.js.LICENSE.txt → 6710.a94fd362.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{3849.89f86737.js.LICENSE.txt → 7958.f25f7332.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{5501.929e6257.js.LICENSE.txt → 9010.44bf2927.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{9389.a8ea42a0.js.LICENSE.txt → 9389.29616aa6.js.LICENSE.txt} +0 -0
- /package/__mf/js/async/{__federation_expose_LokiDatasource.44ac1fa6.js.LICENSE.txt → __federation_expose_LokiDatasource.3fe6141d.js.LICENSE.txt} +0 -0
package/lib/cjs/setup-tests.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// Copyright The Perses Authors
|
|
2
|
+
// Licensed under the Apache License, Version 2.0 (the \"License\");
|
|
3
|
+
// you may not use this file except in compliance with the License.
|
|
4
|
+
// You may obtain a copy of the License at
|
|
5
|
+
//
|
|
6
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
//
|
|
8
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
// distributed under the License is distributed on an \"AS IS\" BASIS,
|
|
10
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
// See the License for the specific language governing permissions and
|
|
12
|
+
// limitations under the License.
|
|
1
13
|
"use strict";
|
|
2
14
|
Object.defineProperty(exports, "__esModule", {
|
|
3
15
|
value: true
|
|
@@ -9,6 +9,11 @@ type CompletionScope = {
|
|
|
9
9
|
} | {
|
|
10
10
|
kind: 'LabelValue';
|
|
11
11
|
label: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'PipeFunction';
|
|
14
|
+
afterPipe: boolean;
|
|
15
|
+
hasSpace: boolean;
|
|
16
|
+
afterExclamation: boolean;
|
|
12
17
|
};
|
|
13
18
|
/**
|
|
14
19
|
* CompletionInfo specifies the identified scope and position of the completion in the current editor text.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../../src/components/complete.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAwB,MAAM,0BAA0B,CAAC;AAEjH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"complete.d.ts","sourceRoot":"","sources":["../../../src/components/complete.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAwB,MAAM,0BAA0B,CAAC;AAEjH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAc,IAAI,EAAE,MAAM,eAAe,CAAC;AAajD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,oGAAoG;AACpG,KAAK,eAAe,GAChB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,CAAC;AAE/F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAMD,wBAAsB,QAAQ,CAC5B,aAAa,EAAE,gBAAgB,EAC/B,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,iBAAiB,GAChC,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAWlC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,cAAc,GAAG,SAAS,CA6D1G;AA8SD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAmB9G"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright
|
|
1
|
+
// Copyright The Perses Authors
|
|
2
2
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
3
|
// you may not use this file except in compliance with the License.
|
|
4
4
|
// You may obtain a copy of the License at
|
|
@@ -12,13 +12,14 @@
|
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { insertCompletionText } from '@codemirror/autocomplete';
|
|
14
14
|
import { syntaxTree } from '@codemirror/language';
|
|
15
|
-
import { Selector, Matchers, Matcher, Identifier, Eq, Neq, Re, Nre, String as StringType } from '@grafana/lezer-logql';
|
|
16
|
-
import { toUnixSeconds } from '../model
|
|
15
|
+
import { Selector, Matchers, Matcher, Identifier, Eq, Neq, Re, Nre, String as StringType, Pipe } from '@grafana/lezer-logql';
|
|
16
|
+
import { toUnixSeconds } from '../model';
|
|
17
17
|
const quoteChars = [
|
|
18
18
|
'"',
|
|
19
19
|
'`'
|
|
20
20
|
];
|
|
21
21
|
const defaultQuoteChar = '"';
|
|
22
|
+
const ERROR_NODE = 0; // Lezer parser creates error nodes for incomplete/malformed syntax
|
|
22
23
|
export async function complete(completionCfg, { state, pos }) {
|
|
23
24
|
// First, identify the completion scope
|
|
24
25
|
const completion = identifyCompletion(state, pos, syntaxTree(state));
|
|
@@ -40,12 +41,98 @@ export async function complete(completionCfg, { state, pos }) {
|
|
|
40
41
|
* Function is exported for tests only.
|
|
41
42
|
*/ export function identifyCompletion(state, pos, tree) {
|
|
42
43
|
const node = tree.resolveInner(pos, -1);
|
|
44
|
+
switch(node.type.id){
|
|
45
|
+
case Selector:
|
|
46
|
+
case Matchers:
|
|
47
|
+
case Matcher:
|
|
48
|
+
case Identifier:
|
|
49
|
+
case Eq:
|
|
50
|
+
case Neq:
|
|
51
|
+
case Re:
|
|
52
|
+
case Nre:
|
|
53
|
+
case StringType:
|
|
54
|
+
{
|
|
55
|
+
const labelCompletion = detectLabelCompletion(state, pos, node);
|
|
56
|
+
if (labelCompletion) return labelCompletion;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case ERROR_NODE:
|
|
60
|
+
{
|
|
61
|
+
// Check for pipe context first
|
|
62
|
+
const pipeCompletion = detectPipeCompletion(state, node);
|
|
63
|
+
if (pipeCompletion) return pipeCompletion;
|
|
64
|
+
// Then check for label completion in error nodes
|
|
65
|
+
const labelCompletion = detectLabelCompletion(state, pos, node);
|
|
66
|
+
if (labelCompletion) return labelCompletion;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case Pipe:
|
|
70
|
+
{
|
|
71
|
+
// Pipe operator: suggest parser functions and line filters
|
|
72
|
+
// Examples: {job="nginx"} |▯ or {job="nginx"} | ▯
|
|
73
|
+
const hasSpaceAfterPipe = state.sliceDoc(pos - 1, pos) === ' ';
|
|
74
|
+
return {
|
|
75
|
+
scope: {
|
|
76
|
+
kind: 'PipeFunction',
|
|
77
|
+
afterPipe: true,
|
|
78
|
+
hasSpace: hasSpaceAfterPipe,
|
|
79
|
+
afterExclamation: false
|
|
80
|
+
},
|
|
81
|
+
from: pos
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Fallback checks for contexts not directly on a node
|
|
86
|
+
const textBeforeCursor = state.sliceDoc(0, pos).trim();
|
|
87
|
+
const hasSpace = state.sliceDoc(pos - 1, pos).match(/\s/) !== null;
|
|
88
|
+
// Check if cursor is after a pipe operator followed by whitespace
|
|
89
|
+
// This enables autocomplete after: {job="nginx"} | ▯
|
|
90
|
+
if (textBeforeCursor.endsWith('|') && hasSpace) {
|
|
91
|
+
return {
|
|
92
|
+
scope: {
|
|
93
|
+
kind: 'PipeFunction',
|
|
94
|
+
afterPipe: true,
|
|
95
|
+
hasSpace: true,
|
|
96
|
+
afterExclamation: false
|
|
97
|
+
},
|
|
98
|
+
from: pos
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// Check if cursor is after a closing brace (stream selector) followed by whitespace
|
|
102
|
+
// This enables autocomplete after: {job="nginx"} ▯
|
|
103
|
+
if (textBeforeCursor.endsWith('}') && hasSpace) {
|
|
104
|
+
return {
|
|
105
|
+
scope: {
|
|
106
|
+
kind: 'PipeFunction',
|
|
107
|
+
afterPipe: false,
|
|
108
|
+
hasSpace: true,
|
|
109
|
+
afterExclamation: false
|
|
110
|
+
},
|
|
111
|
+
from: pos
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Retrieve completion options based on the identified completion scope.
|
|
117
|
+
*/ async function retrieveOptions(completionCfg, completion) {
|
|
118
|
+
switch(completion.kind){
|
|
119
|
+
case 'LabelName':
|
|
120
|
+
return completeLabelName(completionCfg);
|
|
121
|
+
case 'LabelValue':
|
|
122
|
+
return completeLabelValue(completionCfg, completion.label);
|
|
123
|
+
case 'PipeFunction':
|
|
124
|
+
return completePipeFunctions(completion.afterPipe, completion.hasSpace, completion.afterExclamation);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Detect label name or value completion contexts within selectors.
|
|
129
|
+
*/ function detectLabelCompletion(state, pos, node) {
|
|
43
130
|
switch(node.type.id){
|
|
44
131
|
case Selector:
|
|
45
132
|
// Selector is the entire {label matchers} expression
|
|
46
133
|
// Autocomplete at start: {▯ or empty: {}
|
|
47
134
|
// Do not autocomplete if cursor is after closing brace: {job="mysql"}▯
|
|
48
|
-
if ((node.firstChild === null || node.firstChild?.type.id ===
|
|
135
|
+
if ((node.firstChild === null || node.firstChild?.type.id === ERROR_NODE) && !state.sliceDoc(node.from, pos).includes('}')) {
|
|
49
136
|
return {
|
|
50
137
|
scope: {
|
|
51
138
|
kind: 'LabelName'
|
|
@@ -130,7 +217,7 @@ export async function complete(completionCfg, { state, pos }) {
|
|
|
130
217
|
}
|
|
131
218
|
}
|
|
132
219
|
break;
|
|
133
|
-
case
|
|
220
|
+
case ERROR_NODE:
|
|
134
221
|
// Error nodes represent incomplete or malformed syntax
|
|
135
222
|
// Autocomplete incomplete value after operator: { job=mys▯ or { job="mys▯
|
|
136
223
|
if ((node.prevSibling?.type.id === Eq || node.prevSibling?.type.id === Neq || node.prevSibling?.type.id === Re || node.prevSibling?.type.id === Nre) && node.parent?.type.id === Matcher) {
|
|
@@ -159,16 +246,132 @@ export async function complete(completionCfg, { state, pos }) {
|
|
|
159
246
|
}
|
|
160
247
|
break;
|
|
161
248
|
}
|
|
249
|
+
return undefined;
|
|
162
250
|
}
|
|
163
251
|
/**
|
|
164
|
-
*
|
|
165
|
-
*/
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
252
|
+
* Detect pipe function completion contexts (line filters, parsers, formatters).
|
|
253
|
+
*/ function detectPipeCompletion(state, node) {
|
|
254
|
+
// Check if we're in an error node right after a pipe operator
|
|
255
|
+
// This handles cases like: {job="nginx"} | !▯
|
|
256
|
+
if (node.prevSibling?.type.id === Pipe) {
|
|
257
|
+
return {
|
|
258
|
+
scope: {
|
|
259
|
+
kind: 'PipeFunction',
|
|
260
|
+
afterPipe: true,
|
|
261
|
+
hasSpace: true,
|
|
262
|
+
afterExclamation: false
|
|
263
|
+
},
|
|
264
|
+
from: node.from
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
// Check if we're after selector with space and text starts with !
|
|
268
|
+
// This handles cases like: {job="nginx"} !▯
|
|
269
|
+
const errorText = state.sliceDoc(node.from, node.to);
|
|
270
|
+
if (errorText.startsWith('!')) {
|
|
271
|
+
const textBeforeError = state.sliceDoc(0, node.from).trim();
|
|
272
|
+
if (textBeforeError.endsWith('}')) {
|
|
273
|
+
return {
|
|
274
|
+
scope: {
|
|
275
|
+
kind: 'PipeFunction',
|
|
276
|
+
afterPipe: false,
|
|
277
|
+
hasSpace: true,
|
|
278
|
+
afterExclamation: true
|
|
279
|
+
},
|
|
280
|
+
from: node.from
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Complete LogQL pipe functions, line filters, and parser functions.
|
|
288
|
+
* Context-aware suggestions based on LogQL syntax:
|
|
289
|
+
* - After "{} ": Show all line filters (|=, !=, |~, !~) + parsers (with | prefix)
|
|
290
|
+
* - After "{} !": Show ONLY != and !~
|
|
291
|
+
* - After "{} |": Show only pipe-based filters WITHOUT the | (=, ~) + parsers
|
|
292
|
+
* - After "{} | ": Show ONLY parsers, NO line filters
|
|
293
|
+
*/ function completePipeFunctions(afterPipe, hasSpace, afterExclamation) {
|
|
294
|
+
const completions = [];
|
|
295
|
+
// Line filter operators that START with pipe: |= and |~
|
|
296
|
+
const pipeLineFilters = [
|
|
297
|
+
{
|
|
298
|
+
operator: '|=',
|
|
299
|
+
detail: 'Line contains'
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
operator: '|~',
|
|
303
|
+
detail: 'Line matches regex'
|
|
304
|
+
}
|
|
305
|
+
];
|
|
306
|
+
// Line filter operators that DON'T start with pipe: != and !~
|
|
307
|
+
const nonPipeLineFilters = [
|
|
308
|
+
{
|
|
309
|
+
operator: '!=',
|
|
310
|
+
detail: 'Line does not contain'
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
operator: '!~',
|
|
314
|
+
detail: 'Line does not match regex'
|
|
315
|
+
}
|
|
316
|
+
];
|
|
317
|
+
// Context: After "{} !" - Show ONLY != and !~
|
|
318
|
+
if (afterExclamation) {
|
|
319
|
+
nonPipeLineFilters.forEach(({ operator, detail })=>{
|
|
320
|
+
completions.push(createLineFilterCompletion(operator, detail));
|
|
321
|
+
});
|
|
322
|
+
return completions; // Don't show parsers after !
|
|
171
323
|
}
|
|
324
|
+
// Context 1: After "{} | " (pipe + space) - ONLY parsers, NO line filters
|
|
325
|
+
if (afterPipe && hasSpace) {
|
|
326
|
+
// Don't show any line filters
|
|
327
|
+
} else if (afterPipe && !hasSpace) {
|
|
328
|
+
pipeLineFilters.forEach(({ operator, detail })=>{
|
|
329
|
+
// Strip the | since user already typed it
|
|
330
|
+
const strippedOp = operator.replace('|', '');
|
|
331
|
+
completions.push(createLineFilterCompletion(strippedOp, detail));
|
|
332
|
+
});
|
|
333
|
+
} else {
|
|
334
|
+
[
|
|
335
|
+
...pipeLineFilters,
|
|
336
|
+
...nonPipeLineFilters
|
|
337
|
+
].forEach(({ operator, detail })=>{
|
|
338
|
+
completions.push(createLineFilterCompletion(operator, detail));
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
// Parser functions and pipe operations: always show
|
|
342
|
+
// Add pipe prefix when not after pipe (e.g., "{} " needs "| json" not " json")
|
|
343
|
+
const parserPrefix = !afterPipe ? '| ' : hasSpace ? '' : ' ';
|
|
344
|
+
// Parsing expressions: Extract structured data
|
|
345
|
+
const parsingExpressions = [
|
|
346
|
+
'json',
|
|
347
|
+
'logfmt',
|
|
348
|
+
'pattern',
|
|
349
|
+
'regexp',
|
|
350
|
+
'unpack',
|
|
351
|
+
'unwrap'
|
|
352
|
+
];
|
|
353
|
+
parsingExpressions.forEach((parser)=>{
|
|
354
|
+
completions.push({
|
|
355
|
+
label: `${parserPrefix}${parser}`,
|
|
356
|
+
type: 'function',
|
|
357
|
+
boost: 5
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
// Formatting and labels expressions: Format output and manipulate labels
|
|
361
|
+
const formattingAndLabels = [
|
|
362
|
+
'line_format',
|
|
363
|
+
'label_format',
|
|
364
|
+
'decolorize',
|
|
365
|
+
'drop',
|
|
366
|
+
'keep'
|
|
367
|
+
];
|
|
368
|
+
formattingAndLabels.forEach((expr)=>{
|
|
369
|
+
completions.push({
|
|
370
|
+
label: `${parserPrefix}${expr}`,
|
|
371
|
+
type: 'method'
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
return completions;
|
|
172
375
|
}
|
|
173
376
|
async function completeLabelName(completionCfg) {
|
|
174
377
|
if (!completionCfg.client) {
|
|
@@ -189,6 +392,50 @@ async function completeLabelName(completionCfg) {
|
|
|
189
392
|
return [];
|
|
190
393
|
}
|
|
191
394
|
}
|
|
395
|
+
async function completeLabelValue(completionCfg, label) {
|
|
396
|
+
if (!completionCfg.client) {
|
|
397
|
+
return [];
|
|
398
|
+
}
|
|
399
|
+
const start = completionCfg.timeRange?.start ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime()) : undefined;
|
|
400
|
+
const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;
|
|
401
|
+
try {
|
|
402
|
+
const response = await completionCfg.client.labelValues(label, start, end);
|
|
403
|
+
if (response.status === 'success') {
|
|
404
|
+
return response.data.map((value)=>({
|
|
405
|
+
label: value ?? '',
|
|
406
|
+
displayLabel: value ?? '(empty string)',
|
|
407
|
+
apply: applyQuotedCompletion
|
|
408
|
+
}));
|
|
409
|
+
}
|
|
410
|
+
return [];
|
|
411
|
+
} catch (error) {
|
|
412
|
+
console.error(`Error fetching values for label ${label}:`, error);
|
|
413
|
+
return [];
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Create a line filter completion with consistent cursor positioning.
|
|
418
|
+
*/ function createLineFilterCompletion(operator, detail) {
|
|
419
|
+
return {
|
|
420
|
+
label: `${operator} ""`,
|
|
421
|
+
detail,
|
|
422
|
+
apply: (view, _completion, from, to)=>{
|
|
423
|
+
const insert = `${operator} ""`;
|
|
424
|
+
view.dispatch({
|
|
425
|
+
changes: {
|
|
426
|
+
from,
|
|
427
|
+
to,
|
|
428
|
+
insert
|
|
429
|
+
},
|
|
430
|
+
selection: {
|
|
431
|
+
anchor: from + insert.length - 1
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
},
|
|
435
|
+
type: 'text',
|
|
436
|
+
boost: 10
|
|
437
|
+
};
|
|
438
|
+
}
|
|
192
439
|
function escapeString(input, quoteChar) {
|
|
193
440
|
// do not escape raw strings (when using backticks)
|
|
194
441
|
if (quoteChar === '`') {
|
|
@@ -224,26 +471,5 @@ function escapeString(input, quoteChar) {
|
|
|
224
471
|
const insertText = `${quoteChar}${escapeString(completion.label, quoteChar)}${quoteChar}`;
|
|
225
472
|
view.dispatch(insertCompletionText(view.state, insertText, from, to));
|
|
226
473
|
}
|
|
227
|
-
async function completeLabelValue(completionCfg, label) {
|
|
228
|
-
if (!completionCfg.client) {
|
|
229
|
-
return [];
|
|
230
|
-
}
|
|
231
|
-
const start = completionCfg.timeRange?.start ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime()) : undefined;
|
|
232
|
-
const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;
|
|
233
|
-
try {
|
|
234
|
-
const response = await completionCfg.client.labelValues(label, start, end);
|
|
235
|
-
if (response.status === 'success') {
|
|
236
|
-
return response.data.map((value)=>({
|
|
237
|
-
label: value ?? '',
|
|
238
|
-
displayLabel: value ?? '(empty string)',
|
|
239
|
-
apply: applyQuotedCompletion
|
|
240
|
-
}));
|
|
241
|
-
}
|
|
242
|
-
return [];
|
|
243
|
-
} catch (error) {
|
|
244
|
-
console.error(`Error fetching values for label ${label}:`, error);
|
|
245
|
-
return [];
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
474
|
|
|
249
475
|
//# sourceMappingURL=complete.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/complete.ts"],"sourcesContent":["// Copyright 2025 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Completion, CompletionContext, CompletionResult, insertCompletionText } from '@codemirror/autocomplete';\nimport { syntaxTree } from '@codemirror/language';\nimport { EditorState } from '@codemirror/state';\nimport { Tree } from '@lezer/common';\nimport { Selector, Matchers, Matcher, Identifier, Eq, Neq, Re, Nre, String as StringType } from '@grafana/lezer-logql';\nimport { EditorView } from '@uiw/react-codemirror';\nimport { toUnixSeconds } from '../model/loki-client';\nimport { CompletionConfig } from './logql-extension';\n\n/** CompletionScope specifies the completion kind, e.g. whether to complete label names or values */\ntype CompletionScope = { kind: 'LabelName' } | { kind: 'LabelValue'; label: string };\n\n/**\n * CompletionInfo specifies the identified scope and position of the completion in the current editor text.\n */\nexport interface CompletionInfo {\n scope: CompletionScope;\n from: number;\n to?: number;\n}\n\nconst quoteChars = ['\"', '`'];\nconst defaultQuoteChar = '\"';\n\nexport async function complete(\n completionCfg: CompletionConfig,\n { state, pos }: CompletionContext\n): Promise<CompletionResult | null> {\n // First, identify the completion scope\n const completion = identifyCompletion(state, pos, syntaxTree(state));\n if (!completion) {\n // No completion scope found for current cursor position.\n return null;\n }\n\n // Then, retrieve completion options for the identified scope (from the Loki API).\n const options = await retrieveOptions(completionCfg, completion.scope);\n return { options, from: completion.from, to: completion.to };\n}\n\n/**\n * Identify completion scope (e.g. LabelName, LabelValue) and position, based on the current node in the syntax tree.\n *\n * Function is exported for tests only.\n */\nexport function identifyCompletion(state: EditorState, pos: number, tree: Tree): CompletionInfo | undefined {\n const node = tree.resolveInner(pos, -1);\n\n switch (node.type.id) {\n case Selector:\n // Selector is the entire {label matchers} expression\n // Autocomplete at start: {▯ or empty: {}\n // Do not autocomplete if cursor is after closing brace: {job=\"mysql\"}▯\n if (\n (node.firstChild === null || node.firstChild?.type.id === 0) &&\n !state.sliceDoc(node.from, pos).includes('}')\n ) {\n return {\n scope: { kind: 'LabelName' },\n from: pos,\n };\n }\n break;\n\n case Matchers: {\n // Matchers node contains all label matchers inside {}\n // Autocomplete after comma: { job=\"mysql\",▯ or { job=\"mysql\", ▯\n const text = state.sliceDoc(node.from, pos);\n if (text.endsWith(',') || text.endsWith(', ')) {\n return {\n scope: { kind: 'LabelName' },\n from: pos,\n };\n }\n break;\n }\n\n case Matcher:\n // Single matcher like job=\"mysql\"\n // Autocomplete when cursor is after a complete matcher: { job=\"mysql\" ▯\n if (node.parent?.type.id === Matchers) {\n return {\n scope: { kind: 'LabelName' },\n from: pos,\n };\n }\n break;\n\n case Identifier:\n // Identifier is a label name being typed\n // Autocomplete partial label names: { jo▯ or { job=\"mysql\", na▯\n if (node.parent?.type.id === Matcher) {\n return {\n scope: { kind: 'LabelName' },\n from: node.from,\n };\n }\n break;\n\n case Eq:\n case Neq:\n case Re:\n case Nre:\n // Operators for label matching: =, !=, =~, !~\n // Autocomplete label values right after operator: { job=▯ or { job!=▯\n if (node.parent?.type.id === Matcher) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n return { scope: { kind: 'LabelValue', label }, from: pos };\n }\n }\n break;\n\n case StringType:\n // String value in a matcher: { job=\"▯\n // Do not autocomplete if cursor is after closing quotes: { job=\"\"▯\n if (node.parent?.type.id === Matcher && !/^\".*\"$/.test(state.sliceDoc(node.from, pos))) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n return { scope: { kind: 'LabelValue', label }, from: node.from + 1 }; // +1 to skip opening quote\n }\n }\n break;\n\n case 0 /* error node */:\n // Error nodes represent incomplete or malformed syntax\n // Autocomplete incomplete value after operator: { job=mys▯ or { job=\"mys▯\n if (\n (node.prevSibling?.type.id === Eq ||\n node.prevSibling?.type.id === Neq ||\n node.prevSibling?.type.id === Re ||\n node.prevSibling?.type.id === Nre) &&\n node.parent?.type.id === Matcher\n ) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n // Skip leading quote if present: { name=\"HT▯\n const from = quoteChars.includes(state.sliceDoc(node.from, node.from + 1)) ? node.from + 1 : node.from;\n return { scope: { kind: 'LabelValue', label }, from };\n }\n }\n\n // Autocomplete partial label name: { j▯ or { job=\"mysql\", n▯\n if (node.parent?.type.id === Selector || node.parent?.type.id === Matchers) {\n return {\n scope: { kind: 'LabelName' },\n from: node.from,\n };\n }\n break;\n }\n}\n\n/**\n * Retrieve completion options based on the identified completion scope.\n */\nasync function retrieveOptions(completionCfg: CompletionConfig, completion: CompletionScope): Promise<Completion[]> {\n switch (completion.kind) {\n case 'LabelName':\n return completeLabelName(completionCfg);\n\n case 'LabelValue':\n return completeLabelValue(completionCfg, completion.label);\n }\n}\n\nasync function completeLabelName(completionCfg: CompletionConfig): Promise<Completion[]> {\n if (!completionCfg.client) {\n return [];\n }\n\n const start = completionCfg.timeRange?.start\n ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime())\n : undefined;\n const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;\n\n try {\n const response = await completionCfg.client.labels(start, end);\n if (response.status === 'success') {\n return response.data.map((label: string) => ({ label }));\n }\n return [];\n } catch (error) {\n console.error('Error fetching label names:', error);\n return [];\n }\n}\n\nfunction escapeString(input: string, quoteChar: string) {\n // do not escape raw strings (when using backticks)\n if (quoteChar === '`') {\n return input;\n }\n\n let escaped = input;\n // escape backslashes and quotes\n escaped = escaped.replaceAll('\\\\', '\\\\\\\\');\n escaped = escaped.replaceAll('\"', '\\\\\"');\n return escaped;\n}\n\n/**\n * Add quotes to the completion text in case quotes are not present already.\n * This handles the following cases:\n * { name=HTTP\n * { name=\"x\n * { name=\"x\" where cursor is after the 'x'\n */\nexport function applyQuotedCompletion(view: EditorView, completion: Completion, from: number, to: number): void {\n let quoteChar = defaultQuoteChar;\n if (quoteChars.includes(view.state.sliceDoc(from - 1, from))) {\n quoteChar = view.state.sliceDoc(from - 1, from);\n from--;\n }\n if (quoteChars.includes(view.state.sliceDoc(to, to + 1))) {\n quoteChar = view.state.sliceDoc(to, to + 1);\n to++;\n }\n\n // When using raw strings (`), we cannot escape a backtick.\n // Therefore, switch the quote character.\n if (completion.label.includes('`')) {\n quoteChar = '\"';\n }\n\n const insertText = `${quoteChar}${escapeString(completion.label, quoteChar)}${quoteChar}`;\n view.dispatch(insertCompletionText(view.state, insertText, from, to));\n}\n\nasync function completeLabelValue(completionCfg: CompletionConfig, label: string): Promise<Completion[]> {\n if (!completionCfg.client) {\n return [];\n }\n\n const start = completionCfg.timeRange?.start\n ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime())\n : undefined;\n const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;\n\n try {\n const response = await completionCfg.client.labelValues(label, start, end);\n if (response.status === 'success') {\n return response.data.map((value: string) => ({\n label: value ?? '',\n displayLabel: value ?? '(empty string)',\n apply: applyQuotedCompletion,\n }));\n }\n return [];\n } catch (error) {\n console.error(`Error fetching values for label ${label}:`, error);\n return [];\n }\n}\n"],"names":["insertCompletionText","syntaxTree","Selector","Matchers","Matcher","Identifier","Eq","Neq","Re","Nre","String","StringType","toUnixSeconds","quoteChars","defaultQuoteChar","complete","completionCfg","state","pos","completion","identifyCompletion","options","retrieveOptions","scope","from","to","tree","node","resolveInner","type","id","firstChild","sliceDoc","includes","kind","text","endsWith","parent","labelNode","label","test","prevSibling","completeLabelName","completeLabelValue","client","start","timeRange","Date","getTime","undefined","end","response","labels","status","data","map","error","console","escapeString","input","quoteChar","escaped","replaceAll","applyQuotedCompletion","view","insertText","dispatch","labelValues","value","displayLabel","apply"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/complete.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Completion, CompletionContext, CompletionResult, insertCompletionText } from '@codemirror/autocomplete';\nimport { syntaxTree } from '@codemirror/language';\nimport { EditorState } from '@codemirror/state';\nimport { SyntaxNode, Tree } from '@lezer/common';\nimport {\n Selector,\n Matchers,\n Matcher,\n Identifier,\n Eq,\n Neq,\n Re,\n Nre,\n String as StringType,\n Pipe,\n} from '@grafana/lezer-logql';\nimport { EditorView } from '@uiw/react-codemirror';\nimport { toUnixSeconds } from '../model';\nimport { CompletionConfig } from './logql-extension';\n\n/** CompletionScope specifies the completion kind, e.g. whether to complete label names or values */\ntype CompletionScope =\n | { kind: 'LabelName' }\n | { kind: 'LabelValue'; label: string }\n | { kind: 'PipeFunction'; afterPipe: boolean; hasSpace: boolean; afterExclamation: boolean };\n\n/**\n * CompletionInfo specifies the identified scope and position of the completion in the current editor text.\n */\nexport interface CompletionInfo {\n scope: CompletionScope;\n from: number;\n to?: number;\n}\n\nconst quoteChars = ['\"', '`'];\nconst defaultQuoteChar = '\"';\nconst ERROR_NODE = 0; // Lezer parser creates error nodes for incomplete/malformed syntax\n\nexport async function complete(\n completionCfg: CompletionConfig,\n { state, pos }: CompletionContext\n): Promise<CompletionResult | null> {\n // First, identify the completion scope\n const completion = identifyCompletion(state, pos, syntaxTree(state));\n if (!completion) {\n // No completion scope found for current cursor position.\n return null;\n }\n\n // Then, retrieve completion options for the identified scope (from the Loki API).\n const options = await retrieveOptions(completionCfg, completion.scope);\n return { options, from: completion.from, to: completion.to };\n}\n\n/**\n * Identify completion scope (e.g. LabelName, LabelValue) and position, based on the current node in the syntax tree.\n *\n * Function is exported for tests only.\n */\nexport function identifyCompletion(state: EditorState, pos: number, tree: Tree): CompletionInfo | undefined {\n const node = tree.resolveInner(pos, -1);\n\n switch (node.type.id) {\n case Selector:\n case Matchers:\n case Matcher:\n case Identifier:\n case Eq:\n case Neq:\n case Re:\n case Nre:\n case StringType: {\n const labelCompletion = detectLabelCompletion(state, pos, node);\n if (labelCompletion) return labelCompletion;\n break;\n }\n\n case ERROR_NODE: {\n // Check for pipe context first\n const pipeCompletion = detectPipeCompletion(state, node);\n if (pipeCompletion) return pipeCompletion;\n\n // Then check for label completion in error nodes\n const labelCompletion = detectLabelCompletion(state, pos, node);\n if (labelCompletion) return labelCompletion;\n break;\n }\n\n case Pipe: {\n // Pipe operator: suggest parser functions and line filters\n // Examples: {job=\"nginx\"} |▯ or {job=\"nginx\"} | ▯\n const hasSpaceAfterPipe = state.sliceDoc(pos - 1, pos) === ' ';\n return {\n scope: { kind: 'PipeFunction', afterPipe: true, hasSpace: hasSpaceAfterPipe, afterExclamation: false },\n from: pos,\n };\n }\n }\n\n // Fallback checks for contexts not directly on a node\n const textBeforeCursor = state.sliceDoc(0, pos).trim();\n const hasSpace = state.sliceDoc(pos - 1, pos).match(/\\s/) !== null;\n\n // Check if cursor is after a pipe operator followed by whitespace\n // This enables autocomplete after: {job=\"nginx\"} | ▯\n if (textBeforeCursor.endsWith('|') && hasSpace) {\n return {\n scope: { kind: 'PipeFunction', afterPipe: true, hasSpace: true, afterExclamation: false },\n from: pos,\n };\n }\n\n // Check if cursor is after a closing brace (stream selector) followed by whitespace\n // This enables autocomplete after: {job=\"nginx\"} ▯\n if (textBeforeCursor.endsWith('}') && hasSpace) {\n return {\n scope: { kind: 'PipeFunction', afterPipe: false, hasSpace: true, afterExclamation: false },\n from: pos,\n };\n }\n}\n\n/**\n * Retrieve completion options based on the identified completion scope.\n */\nasync function retrieveOptions(completionCfg: CompletionConfig, completion: CompletionScope): Promise<Completion[]> {\n switch (completion.kind) {\n case 'LabelName':\n return completeLabelName(completionCfg);\n\n case 'LabelValue':\n return completeLabelValue(completionCfg, completion.label);\n\n case 'PipeFunction':\n return completePipeFunctions(completion.afterPipe, completion.hasSpace, completion.afterExclamation);\n }\n}\n\n/**\n * Detect label name or value completion contexts within selectors.\n */\nfunction detectLabelCompletion(state: EditorState, pos: number, node: SyntaxNode): CompletionInfo | undefined {\n switch (node.type.id) {\n case Selector:\n // Selector is the entire {label matchers} expression\n // Autocomplete at start: {▯ or empty: {}\n // Do not autocomplete if cursor is after closing brace: {job=\"mysql\"}▯\n if (\n (node.firstChild === null || node.firstChild?.type.id === ERROR_NODE) &&\n !state.sliceDoc(node.from, pos).includes('}')\n ) {\n return { scope: { kind: 'LabelName' }, from: pos };\n }\n break;\n\n case Matchers: {\n // Matchers node contains all label matchers inside {}\n // Autocomplete after comma: { job=\"mysql\",▯ or { job=\"mysql\", ▯\n const text = state.sliceDoc(node.from, pos);\n if (text.endsWith(',') || text.endsWith(', ')) {\n return { scope: { kind: 'LabelName' }, from: pos };\n }\n break;\n }\n\n case Matcher:\n // Single matcher like job=\"mysql\"\n // Autocomplete when cursor is after a complete matcher: { job=\"mysql\" ▯\n if (node.parent?.type.id === Matchers) {\n return { scope: { kind: 'LabelName' }, from: pos };\n }\n break;\n\n case Identifier:\n // Identifier is a label name being typed\n // Autocomplete partial label names: { jo▯ or { job=\"mysql\", na▯\n if (node.parent?.type.id === Matcher) {\n return { scope: { kind: 'LabelName' }, from: node.from };\n }\n break;\n\n case Eq:\n case Neq:\n case Re:\n case Nre:\n // Operators for label matching: =, !=, =~, !~\n // Autocomplete label values right after operator: { job=▯ or { job!=▯\n if (node.parent?.type.id === Matcher) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n return { scope: { kind: 'LabelValue', label }, from: pos };\n }\n }\n break;\n\n case StringType:\n // String value in a matcher: { job=\"▯\n // Do not autocomplete if cursor is after closing quotes: { job=\"\"▯\n if (node.parent?.type.id === Matcher && !/^\".*\"$/.test(state.sliceDoc(node.from, pos))) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n return { scope: { kind: 'LabelValue', label }, from: node.from + 1 }; // +1 to skip opening quote\n }\n }\n break;\n\n case ERROR_NODE:\n // Error nodes represent incomplete or malformed syntax\n // Autocomplete incomplete value after operator: { job=mys▯ or { job=\"mys▯\n if (\n (node.prevSibling?.type.id === Eq ||\n node.prevSibling?.type.id === Neq ||\n node.prevSibling?.type.id === Re ||\n node.prevSibling?.type.id === Nre) &&\n node.parent?.type.id === Matcher\n ) {\n const labelNode = node.parent.firstChild;\n if (labelNode?.type.id === Identifier) {\n const label = state.sliceDoc(labelNode.from, labelNode.to);\n // Skip leading quote if present: { name=\"HT▯\n const from = quoteChars.includes(state.sliceDoc(node.from, node.from + 1)) ? node.from + 1 : node.from;\n return { scope: { kind: 'LabelValue', label }, from };\n }\n }\n\n // Autocomplete partial label name: { j▯ or { job=\"mysql\", n▯\n if (node.parent?.type.id === Selector || node.parent?.type.id === Matchers) {\n return { scope: { kind: 'LabelName' }, from: node.from };\n }\n break;\n }\n\n return undefined;\n}\n\n/**\n * Detect pipe function completion contexts (line filters, parsers, formatters).\n */\nfunction detectPipeCompletion(state: EditorState, node: SyntaxNode): CompletionInfo | undefined {\n // Check if we're in an error node right after a pipe operator\n // This handles cases like: {job=\"nginx\"} | !▯\n if (node.prevSibling?.type.id === Pipe) {\n return {\n scope: { kind: 'PipeFunction', afterPipe: true, hasSpace: true, afterExclamation: false },\n from: node.from,\n };\n }\n\n // Check if we're after selector with space and text starts with !\n // This handles cases like: {job=\"nginx\"} !▯\n const errorText = state.sliceDoc(node.from, node.to);\n if (errorText.startsWith('!')) {\n const textBeforeError = state.sliceDoc(0, node.from).trim();\n if (textBeforeError.endsWith('}')) {\n return {\n scope: { kind: 'PipeFunction', afterPipe: false, hasSpace: true, afterExclamation: true },\n from: node.from,\n };\n }\n }\n\n return undefined;\n}\n\n/**\n * Complete LogQL pipe functions, line filters, and parser functions.\n * Context-aware suggestions based on LogQL syntax:\n * - After \"{} \": Show all line filters (|=, !=, |~, !~) + parsers (with | prefix)\n * - After \"{} !\": Show ONLY != and !~\n * - After \"{} |\": Show only pipe-based filters WITHOUT the | (=, ~) + parsers\n * - After \"{} | \": Show ONLY parsers, NO line filters\n */\nfunction completePipeFunctions(afterPipe: boolean, hasSpace: boolean, afterExclamation: boolean): Completion[] {\n const completions: Completion[] = [];\n\n // Line filter operators that START with pipe: |= and |~\n const pipeLineFilters = [\n { operator: '|=', detail: 'Line contains' },\n { operator: '|~', detail: 'Line matches regex' },\n ];\n\n // Line filter operators that DON'T start with pipe: != and !~\n const nonPipeLineFilters = [\n { operator: '!=', detail: 'Line does not contain' },\n { operator: '!~', detail: 'Line does not match regex' },\n ];\n\n // Context: After \"{} !\" - Show ONLY != and !~\n if (afterExclamation) {\n nonPipeLineFilters.forEach(({ operator, detail }) => {\n completions.push(createLineFilterCompletion(operator, detail));\n });\n return completions; // Don't show parsers after !\n }\n\n // Context 1: After \"{} | \" (pipe + space) - ONLY parsers, NO line filters\n if (afterPipe && hasSpace) {\n // Don't show any line filters\n }\n // Context 2: After \"{} |\" (pipe, no space) - Show = and ~ (without pipe prefix)\n else if (afterPipe && !hasSpace) {\n pipeLineFilters.forEach(({ operator, detail }) => {\n // Strip the | since user already typed it\n const strippedOp = operator.replace('|', '');\n completions.push(createLineFilterCompletion(strippedOp, detail));\n });\n }\n // Context 3: After \"{} \" (no pipe) - Show ALL line filters with full syntax\n else {\n [...pipeLineFilters, ...nonPipeLineFilters].forEach(({ operator, detail }) => {\n completions.push(createLineFilterCompletion(operator, detail));\n });\n }\n\n // Parser functions and pipe operations: always show\n // Add pipe prefix when not after pipe (e.g., \"{} \" needs \"| json\" not \" json\")\n const parserPrefix = !afterPipe ? '| ' : hasSpace ? '' : ' ';\n\n // Parsing expressions: Extract structured data\n const parsingExpressions = ['json', 'logfmt', 'pattern', 'regexp', 'unpack', 'unwrap'];\n parsingExpressions.forEach((parser) => {\n completions.push({\n label: `${parserPrefix}${parser}`,\n type: 'function',\n boost: 5,\n });\n });\n\n // Formatting and labels expressions: Format output and manipulate labels\n const formattingAndLabels = ['line_format', 'label_format', 'decolorize', 'drop', 'keep'];\n formattingAndLabels.forEach((expr) => {\n completions.push({\n label: `${parserPrefix}${expr}`,\n type: 'method',\n });\n });\n\n return completions;\n}\n\nasync function completeLabelName(completionCfg: CompletionConfig): Promise<Completion[]> {\n if (!completionCfg.client) {\n return [];\n }\n\n const start = completionCfg.timeRange?.start\n ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime())\n : undefined;\n const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;\n\n try {\n const response = await completionCfg.client.labels(start, end);\n if (response.status === 'success') {\n return response.data.map((label: string) => ({ label }));\n }\n return [];\n } catch (error) {\n console.error('Error fetching label names:', error);\n return [];\n }\n}\n\nasync function completeLabelValue(completionCfg: CompletionConfig, label: string): Promise<Completion[]> {\n if (!completionCfg.client) {\n return [];\n }\n\n const start = completionCfg.timeRange?.start\n ? toUnixSeconds(new Date(completionCfg.timeRange.start).getTime())\n : undefined;\n const end = completionCfg.timeRange?.end ? toUnixSeconds(new Date(completionCfg.timeRange.end).getTime()) : undefined;\n\n try {\n const response = await completionCfg.client.labelValues(label, start, end);\n if (response.status === 'success') {\n return response.data.map((value: string) => ({\n label: value ?? '',\n displayLabel: value ?? '(empty string)',\n apply: applyQuotedCompletion,\n }));\n }\n return [];\n } catch (error) {\n console.error(`Error fetching values for label ${label}:`, error);\n return [];\n }\n}\n\n/**\n * Create a line filter completion with consistent cursor positioning.\n */\nfunction createLineFilterCompletion(operator: string, detail: string): Completion {\n return {\n label: `${operator} \"\"`,\n detail,\n apply: (view, _completion, from, to) => {\n const insert = `${operator} \"\"`;\n view.dispatch({\n changes: { from, to, insert },\n selection: { anchor: from + insert.length - 1 },\n });\n },\n type: 'text',\n boost: 10,\n };\n}\n\nfunction escapeString(input: string, quoteChar: string) {\n // do not escape raw strings (when using backticks)\n if (quoteChar === '`') {\n return input;\n }\n\n let escaped = input;\n // escape backslashes and quotes\n escaped = escaped.replaceAll('\\\\', '\\\\\\\\');\n escaped = escaped.replaceAll('\"', '\\\\\"');\n return escaped;\n}\n\n/**\n * Add quotes to the completion text in case quotes are not present already.\n * This handles the following cases:\n * { name=HTTP\n * { name=\"x\n * { name=\"x\" where cursor is after the 'x'\n */\nexport function applyQuotedCompletion(view: EditorView, completion: Completion, from: number, to: number): void {\n let quoteChar = defaultQuoteChar;\n if (quoteChars.includes(view.state.sliceDoc(from - 1, from))) {\n quoteChar = view.state.sliceDoc(from - 1, from);\n from--;\n }\n if (quoteChars.includes(view.state.sliceDoc(to, to + 1))) {\n quoteChar = view.state.sliceDoc(to, to + 1);\n to++;\n }\n\n // When using raw strings (`), we cannot escape a backtick.\n // Therefore, switch the quote character.\n if (completion.label.includes('`')) {\n quoteChar = '\"';\n }\n\n const insertText = `${quoteChar}${escapeString(completion.label, quoteChar)}${quoteChar}`;\n view.dispatch(insertCompletionText(view.state, insertText, from, to));\n}\n"],"names":["insertCompletionText","syntaxTree","Selector","Matchers","Matcher","Identifier","Eq","Neq","Re","Nre","String","StringType","Pipe","toUnixSeconds","quoteChars","defaultQuoteChar","ERROR_NODE","complete","completionCfg","state","pos","completion","identifyCompletion","options","retrieveOptions","scope","from","to","tree","node","resolveInner","type","id","labelCompletion","detectLabelCompletion","pipeCompletion","detectPipeCompletion","hasSpaceAfterPipe","sliceDoc","kind","afterPipe","hasSpace","afterExclamation","textBeforeCursor","trim","match","endsWith","completeLabelName","completeLabelValue","label","completePipeFunctions","firstChild","includes","text","parent","labelNode","test","prevSibling","undefined","errorText","startsWith","textBeforeError","completions","pipeLineFilters","operator","detail","nonPipeLineFilters","forEach","push","createLineFilterCompletion","strippedOp","replace","parserPrefix","parsingExpressions","parser","boost","formattingAndLabels","expr","client","start","timeRange","Date","getTime","end","response","labels","status","data","map","error","console","labelValues","value","displayLabel","apply","applyQuotedCompletion","view","_completion","insert","dispatch","changes","selection","anchor","length","escapeString","input","quoteChar","escaped","replaceAll","insertText"],"mappings":"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"}
|
package/lib/components/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/index.ts"],"sourcesContent":["// Copyright
|
|
1
|
+
{"version":3,"sources":["../../../src/components/index.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nexport { LogQLEditor } from './logql-editor';\nexport type { LogQLEditorProps } from './logql-editor';\n"],"names":["LogQLEditor"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,WAAW,QAAQ,iBAAiB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// Copyright
|
|
2
|
+
// Copyright The Perses Authors
|
|
3
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
// you may not use this file except in compliance with the License.
|
|
5
5
|
// You may obtain a copy of the License at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/logql-editor.tsx"],"sourcesContent":["// Copyright
|
|
1
|
+
{"version":3,"sources":["../../../src/components/logql-editor.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { ReactElement, useMemo } from 'react';\nimport { useTheme } from '@mui/material';\nimport CodeMirror, { EditorView, ReactCodeMirrorProps } from '@uiw/react-codemirror';\nimport { LogQLExtension, CompletionConfig } from './logql-extension';\n\nexport type LogQLEditorProps = Omit<ReactCodeMirrorProps, 'theme' | 'extensions'> & {\n completionConfig?: CompletionConfig;\n};\n\nexport function LogQLEditor(props: LogQLEditorProps): ReactElement {\n const { completionConfig, ...codemirrorProps } = props;\n const theme = useTheme();\n const isDarkMode = theme.palette.mode === 'dark';\n\n const logqlExtension = useMemo(() => {\n return LogQLExtension(completionConfig);\n }, [completionConfig]);\n\n const codemirrorTheme = useMemo(() => {\n const borderColor = theme.palette.mode === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)';\n\n return EditorView.theme({\n '&': {\n backgroundColor: 'transparent !important', // required for dark mode\n border: `1px solid ${borderColor}`,\n borderRadius: `${theme.shape.borderRadius}px`,\n },\n '&.cm-focused.cm-editor': {\n outline: 'none',\n },\n '.cm-content': {\n padding: '8px',\n },\n });\n }, [theme]);\n\n return (\n <CodeMirror\n {...codemirrorProps}\n theme={isDarkMode ? 'dark' : 'light'}\n basicSetup={{\n lineNumbers: false,\n highlightActiveLine: false,\n highlightActiveLineGutter: false,\n foldGutter: false,\n syntaxHighlighting: true,\n }}\n extensions={[EditorView.lineWrapping, logqlExtension, codemirrorTheme]}\n placeholder='Example: {job=\"my-service\"} |= \"error\"'\n />\n );\n}\n"],"names":["useMemo","useTheme","CodeMirror","EditorView","LogQLExtension","LogQLEditor","props","completionConfig","codemirrorProps","theme","isDarkMode","palette","mode","logqlExtension","codemirrorTheme","borderColor","backgroundColor","border","borderRadius","shape","outline","padding","basicSetup","lineNumbers","highlightActiveLine","highlightActiveLineGutter","foldGutter","syntaxHighlighting","extensions","lineWrapping","placeholder"],"mappings":";AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAAuBA,OAAO,QAAQ,QAAQ;AAC9C,SAASC,QAAQ,QAAQ,gBAAgB;AACzC,OAAOC,cAAcC,UAAU,QAA8B,wBAAwB;AACrF,SAASC,cAAc,QAA0B,oBAAoB;AAMrE,OAAO,SAASC,YAAYC,KAAuB;IACjD,MAAM,EAAEC,gBAAgB,EAAE,GAAGC,iBAAiB,GAAGF;IACjD,MAAMG,QAAQR;IACd,MAAMS,aAAaD,MAAME,OAAO,CAACC,IAAI,KAAK;IAE1C,MAAMC,iBAAiBb,QAAQ;QAC7B,OAAOI,eAAeG;IACxB,GAAG;QAACA;KAAiB;IAErB,MAAMO,kBAAkBd,QAAQ;QAC9B,MAAMe,cAAcN,MAAME,OAAO,CAACC,IAAI,KAAK,UAAU,wBAAwB;QAE7E,OAAOT,WAAWM,KAAK,CAAC;YACtB,KAAK;gBACHO,iBAAiB;gBACjBC,QAAQ,CAAC,UAAU,EAAEF,aAAa;gBAClCG,cAAc,GAAGT,MAAMU,KAAK,CAACD,YAAY,CAAC,EAAE,CAAC;YAC/C;YACA,0BAA0B;gBACxBE,SAAS;YACX;YACA,eAAe;gBACbC,SAAS;YACX;QACF;IACF,GAAG;QAACZ;KAAM;IAEV,qBACE,KAACP;QACE,GAAGM,eAAe;QACnBC,OAAOC,aAAa,SAAS;QAC7BY,YAAY;YACVC,aAAa;YACbC,qBAAqB;YACrBC,2BAA2B;YAC3BC,YAAY;YACZC,oBAAoB;QACtB;QACAC,YAAY;YAACzB,WAAW0B,YAAY;YAAEhB;YAAgBC;SAAgB;QACtEgB,aAAY;;AAGlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/logql-extension.ts"],"sourcesContent":["// Copyright
|
|
1
|
+
{"version":3,"sources":["../../../src/components/logql-extension.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { LRLanguage } from '@codemirror/language';\nimport { parser } from '@grafana/lezer-logql';\nimport { CompletionContext } from '@codemirror/autocomplete';\nimport { Extension } from '@uiw/react-codemirror';\nimport { AbsoluteTimeRange } from '@perses-dev/core';\nimport { LokiClient } from '../model';\nimport { logqlHighlight } from './logql-highlight';\nimport { complete } from './complete';\n\nfunction logqlLanguage(): LRLanguage {\n return LRLanguage.define({\n parser: parser.configure({\n props: [logqlHighlight],\n }),\n languageData: {\n closeBrackets: { brackets: ['(', '[', '{', \"'\", '\"', '`'] },\n commentTokens: { line: '#' },\n },\n });\n}\n\nexport interface CompletionConfig {\n /** a LokiClient instance, can be created with LokiDatasource.createClient() */\n client?: LokiClient;\n\n /** search for label values in a given time range */\n timeRange?: AbsoluteTimeRange;\n}\n\nexport function LogQLExtension(completionCfg?: CompletionConfig): Array<LRLanguage | Extension> {\n const language = logqlLanguage();\n\n // Only add autocomplete if config is provided\n if (completionCfg) {\n const completion = language.data.of({\n autocomplete: (ctx: CompletionContext) =>\n complete(completionCfg, ctx).catch((e) => {\n console.error('error during LogQL auto-complete', e);\n return null;\n }),\n });\n return [language, completion];\n }\n\n return [language];\n}\n"],"names":["LRLanguage","parser","logqlHighlight","complete","logqlLanguage","define","configure","props","languageData","closeBrackets","brackets","commentTokens","line","LogQLExtension","completionCfg","language","completion","data","of","autocomplete","ctx","catch","e","console","error"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,UAAU,QAAQ,uBAAuB;AAClD,SAASC,MAAM,QAAQ,uBAAuB;AAK9C,SAASC,cAAc,QAAQ,oBAAoB;AACnD,SAASC,QAAQ,QAAQ,aAAa;AAEtC,SAASC;IACP,OAAOJ,WAAWK,MAAM,CAAC;QACvBJ,QAAQA,OAAOK,SAAS,CAAC;YACvBC,OAAO;gBAACL;aAAe;QACzB;QACAM,cAAc;YACZC,eAAe;gBAAEC,UAAU;oBAAC;oBAAK;oBAAK;oBAAK;oBAAK;oBAAK;iBAAI;YAAC;YAC1DC,eAAe;gBAAEC,MAAM;YAAI;QAC7B;IACF;AACF;AAUA,OAAO,SAASC,eAAeC,aAAgC;IAC7D,MAAMC,WAAWX;IAEjB,8CAA8C;IAC9C,IAAIU,eAAe;QACjB,MAAME,aAAaD,SAASE,IAAI,CAACC,EAAE,CAAC;YAClCC,cAAc,CAACC,MACbjB,SAASW,eAAeM,KAAKC,KAAK,CAAC,CAACC;oBAClCC,QAAQC,KAAK,CAAC,oCAAoCF;oBAClD,OAAO;gBACT;QACJ;QACA,OAAO;YAACP;YAAUC;SAAW;IAC/B;IAEA,OAAO;QAACD;KAAS;AACnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/logql-highlight.ts"],"sourcesContent":["// Copyright
|
|
1
|
+
{"version":3,"sources":["../../../src/components/logql-highlight.ts"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { styleTags, tags } from '@lezer/highlight';\n\nexport const logqlHighlight = styleTags({\n LineComment: tags.comment,\n 'Identifier StreamSelector': tags.labelName,\n 'LabelName LabelMatcher': tags.labelName,\n String: tags.string,\n 'Number Float Duration': tags.number,\n 'LogRangeAggregation VectorAggregation': tags.function(tags.keyword),\n 'And Or Unless': tags.logicOperator,\n 'Eq Neq Re Nre Gt Lt Gte Lte': tags.compareOperator,\n 'Add Sub Mul Div Mod Pow': tags.arithmeticOperator,\n Pipe: tags.operator,\n 'By Without': tags.keyword,\n '( )': tags.paren,\n '[ ]': tags.squareBracket,\n '{ }': tags.brace,\n '⚠': tags.invalid,\n});\n"],"names":["styleTags","tags","logqlHighlight","LineComment","comment","labelName","String","string","number","function","keyword","logicOperator","compareOperator","arithmeticOperator","Pipe","operator","paren","squareBracket","brace","invalid"],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,SAASA,SAAS,EAAEC,IAAI,QAAQ,mBAAmB;AAEnD,OAAO,MAAMC,iBAAiBF,UAAU;IACtCG,aAAaF,KAAKG,OAAO;IACzB,6BAA6BH,KAAKI,SAAS;IAC3C,0BAA0BJ,KAAKI,SAAS;IACxCC,QAAQL,KAAKM,MAAM;IACnB,yBAAyBN,KAAKO,MAAM;IACpC,yCAAyCP,KAAKQ,QAAQ,CAACR,KAAKS,OAAO;IACnE,iBAAiBT,KAAKU,aAAa;IACnC,+BAA+BV,KAAKW,eAAe;IACnD,2BAA2BX,KAAKY,kBAAkB;IAClDC,MAAMb,KAAKc,QAAQ;IACnB,cAAcd,KAAKS,OAAO;IAC1B,OAAOT,KAAKe,KAAK;IACjB,OAAOf,KAAKgB,aAAa;IACzB,OAAOhB,KAAKiB,KAAK;IACjB,KAAKjB,KAAKkB,OAAO;AACnB,GAAG"}
|
package/lib/datasources/index.js
CHANGED