dequel-editor 0.6.1 → 0.8.5
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/dist/{de-ChXK8h97.js → de-7qfktOGD.js} +0 -2
- package/dist/dequel-editor.js +5463 -4161
- package/dist/dequel-lang.js +163 -104
- package/package.json +2 -1
package/dist/dequel-lang.js
CHANGED
|
@@ -1,172 +1,231 @@
|
|
|
1
|
-
import { syntaxTree as
|
|
2
|
-
import {
|
|
3
|
-
import { buildParser as
|
|
4
|
-
import { Facet as
|
|
5
|
-
const
|
|
1
|
+
import { syntaxTree as N, LRLanguage as I, indentNodeProp as v, foldNodeProp as F, foldInside as P, HighlightStyle as A, LanguageSupport as L, syntaxHighlighting as k } from "@codemirror/language";
|
|
2
|
+
import { tags as i, Tag as f, styleTags as E } from "@lezer/highlight";
|
|
3
|
+
import { buildParser as W } from "@lezer/generator";
|
|
4
|
+
import { Facet as B, StateEffect as j, StateField as w } from "@codemirror/state";
|
|
5
|
+
const Q = W(`
|
|
6
6
|
@top QueryList { Query }
|
|
7
|
-
@skip { "
|
|
7
|
+
@skip { " " | " " | "
|
|
8
8
|
" | Comment }
|
|
9
|
+
@detectDelim
|
|
9
10
|
|
|
10
11
|
Query {
|
|
11
|
-
|
|
12
|
+
queryElement+
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
Condition
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
queryElement {
|
|
16
|
+
logicalOp | Condition | ExcludeCondition | Group | ObjectBlock
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
logicalOp { And | Or }
|
|
20
|
+
|
|
21
|
+
And { "&&" | andWord }
|
|
22
|
+
Or { "||" | orWord }
|
|
23
|
+
andWord[@name=And] { @specialize<Identifier, "AND"> | @specialize<Identifier, "and"> }
|
|
24
|
+
orWord[@name=Or] { @specialize<Identifier, "OR"> | @specialize<Identifier, "or"> }
|
|
25
|
+
|
|
26
|
+
Group { "(" Query ")" }
|
|
27
|
+
|
|
28
|
+
ObjectBlock { Identifier "{" Query "}" }
|
|
29
|
+
|
|
30
|
+
Condition { field ":" Predicate }
|
|
31
|
+
ExcludeCondition { "-" field ":" Predicate }
|
|
18
32
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
33
|
+
field[@name=Field] { Identifier }
|
|
34
|
+
|
|
35
|
+
Predicate {
|
|
36
|
+
NegatedPredicate |
|
|
37
|
+
RangePredicate |
|
|
38
|
+
ComparisonPredicate |
|
|
39
|
+
BracketPredicate |
|
|
40
|
+
ShorthandPredicate |
|
|
41
|
+
Command |
|
|
42
|
+
SimplePredicate
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
NegatedPredicate { Not (ComparisonPredicate | ShorthandPredicate | SimplePredicate) }
|
|
46
|
+
ComparisonPredicate { CompareOp Value }
|
|
47
|
+
RangePredicate { Value RangeSep Value }
|
|
48
|
+
BracketPredicate { "[" Value ("," Value)* "]" }
|
|
49
|
+
ShorthandPredicate { (Contains | StartsWith | EndsWith) Value }
|
|
50
|
+
SimplePredicate { Value }
|
|
51
|
+
|
|
52
|
+
Command { Identifier ~ambig "(" ArgList? ")" }
|
|
53
|
+
ArgList { Argument ("," Argument)* }
|
|
54
|
+
Argument { Identifier | Number | String | DateLiteral | DynamicValue }
|
|
55
|
+
|
|
56
|
+
Value { DynamicValue | DateLiteral | Number | String | Identifier ~ambig }
|
|
23
57
|
|
|
24
58
|
@tokens {
|
|
59
|
+
CompareOp { ">=" | "<=" | ">" | "<" }
|
|
60
|
+
RangeSep { ".." }
|
|
61
|
+
|
|
62
|
+
Contains { "*" }
|
|
63
|
+
StartsWith { "^" }
|
|
64
|
+
EndsWith { "$" }
|
|
65
|
+
Not { "!" }
|
|
66
|
+
|
|
67
|
+
DynamicValue { "@" ("today" | "tomorrow" | "yesterday" | "this-year" | "this-month-start" | "this-month-end" | "this-month") }
|
|
68
|
+
DateLiteral { std.digit std.digit std.digit std.digit "-" std.digit std.digit ("-" std.digit std.digit)? }
|
|
69
|
+
|
|
70
|
+
Number { "-"? std.digit+ ("." std.digit+)? }
|
|
71
|
+
String { '"' !["]* '"' }
|
|
72
|
+
|
|
25
73
|
":"
|
|
26
|
-
|
|
27
|
-
|
|
74
|
+
|
|
75
|
+
@precedence { DynamicValue, DateLiteral, Number, Identifier }
|
|
76
|
+
|
|
28
77
|
Identifier { $[a-zA-Z_]+ ("." $[a-zA-Z_]+)* }
|
|
29
|
-
|
|
30
|
-
String { '"' !["]* '"' }
|
|
31
|
-
Regex { RegexContent (RegexFlag)* }
|
|
32
|
-
RegexFlag { std.asciiLetter+ }
|
|
33
|
-
RegexContent { "/" (![/] | "\\/")* "/" }
|
|
78
|
+
|
|
34
79
|
Comment { "#" (![
|
|
35
80
|
])* }
|
|
81
|
+
|
|
82
|
+
"(" ")" "{" "}" "[" "]" "," "-" "&&" "||"
|
|
36
83
|
}
|
|
37
84
|
`), t = {
|
|
38
|
-
Condition:
|
|
39
|
-
Field:
|
|
40
|
-
Command:
|
|
41
|
-
Predicate:
|
|
42
|
-
Value:
|
|
43
|
-
Operator:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
i = i.parent;
|
|
85
|
+
Condition: f.define(i.keyword),
|
|
86
|
+
Field: f.define(i.propertyName),
|
|
87
|
+
Command: i.function(i.variableName),
|
|
88
|
+
Predicate: f.define(i.variableName),
|
|
89
|
+
Value: f.define(i.attributeValue),
|
|
90
|
+
Operator: f.define(i.operator),
|
|
91
|
+
DynamicValue: i.special(i.variableName)
|
|
92
|
+
}, R = B.define(), q = (e, n) => {
|
|
93
|
+
for (; n.parent; ) {
|
|
94
|
+
if (n.parent.name === e)
|
|
95
|
+
return n.parent;
|
|
96
|
+
n = n.parent;
|
|
51
97
|
}
|
|
52
98
|
return null;
|
|
53
99
|
};
|
|
54
|
-
async function
|
|
55
|
-
let
|
|
56
|
-
for (const
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
100
|
+
async function z(e, n, a) {
|
|
101
|
+
let o = n;
|
|
102
|
+
for (const d of e) {
|
|
103
|
+
const r = o.fields[d];
|
|
104
|
+
if (r?.type !== "relationship" || !r.schema)
|
|
59
105
|
return null;
|
|
60
|
-
|
|
106
|
+
o = await a.get(r.schema);
|
|
61
107
|
}
|
|
62
|
-
return
|
|
108
|
+
return o;
|
|
63
109
|
}
|
|
64
|
-
const
|
|
65
|
-
create: () => ({ fields:
|
|
66
|
-
update: (e,
|
|
67
|
-
for (const
|
|
68
|
-
if (
|
|
69
|
-
return
|
|
110
|
+
const T = j.define(), $ = w.define({
|
|
111
|
+
create: () => ({ fields: {} }),
|
|
112
|
+
update: (e, n) => {
|
|
113
|
+
for (const a of n.effects)
|
|
114
|
+
if (a.is(T))
|
|
115
|
+
return a.value;
|
|
70
116
|
return e;
|
|
71
117
|
}
|
|
72
|
-
}),
|
|
118
|
+
}), H = b.data.of({
|
|
73
119
|
autocomplete: async (e) => {
|
|
74
|
-
const
|
|
75
|
-
if (!
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
80
|
-
const
|
|
81
|
-
label:
|
|
120
|
+
const a = N(e.state).resolveInner(e.pos, -1), o = e.state.sliceDoc(a.from, e.pos), d = /[\w.]*$/.exec(o);
|
|
121
|
+
if (!d && !e.explicit) return null;
|
|
122
|
+
const r = d ? a.from + d.index : e.pos, s = e.state.field($, !1), h = e.state.facet(R)[0]?.schemaCache, y = q("Condition", a), u = y?.getChild("Field"), C = y?.getChild(":");
|
|
123
|
+
if (u && C && e.pos > C.to) {
|
|
124
|
+
const p = e.state.doc.sliceString(u.from, u.to), l = s?.fields[p]?.values;
|
|
125
|
+
if (l?.length) {
|
|
126
|
+
const g = l.map((c) => ({
|
|
127
|
+
label: c,
|
|
82
128
|
type: "value"
|
|
83
129
|
}));
|
|
84
130
|
return {
|
|
85
|
-
from:
|
|
86
|
-
options:
|
|
131
|
+
from: r,
|
|
132
|
+
options: g
|
|
87
133
|
};
|
|
88
134
|
}
|
|
89
135
|
}
|
|
90
|
-
if (
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
136
|
+
if (a.name === "Field" && s && Object.keys(s.fields).length) {
|
|
137
|
+
const p = e.state.doc.sliceString(a.from, e.pos), l = p.split(".");
|
|
138
|
+
if (l.length > 1 && h) {
|
|
139
|
+
const c = l.slice(0, -1), m = a.from + p.lastIndexOf(".") + 1, O = await z(
|
|
140
|
+
c,
|
|
141
|
+
s,
|
|
142
|
+
h
|
|
97
143
|
);
|
|
98
|
-
if (
|
|
99
|
-
const
|
|
100
|
-
label:
|
|
101
|
-
type:
|
|
102
|
-
info:
|
|
144
|
+
if (O) {
|
|
145
|
+
const V = Object.entries(O.fields).map(([D, S]) => ({
|
|
146
|
+
label: D,
|
|
147
|
+
type: S.type,
|
|
148
|
+
info: S.info
|
|
103
149
|
}));
|
|
104
150
|
return {
|
|
105
|
-
from:
|
|
106
|
-
options:
|
|
151
|
+
from: m,
|
|
152
|
+
options: V
|
|
107
153
|
};
|
|
108
154
|
}
|
|
109
155
|
return {
|
|
110
|
-
from:
|
|
156
|
+
from: m,
|
|
111
157
|
options: []
|
|
112
158
|
};
|
|
113
159
|
}
|
|
114
|
-
const
|
|
115
|
-
label:
|
|
116
|
-
type:
|
|
117
|
-
info:
|
|
160
|
+
const g = Object.entries(s.fields).map(([c, m]) => ({
|
|
161
|
+
label: c,
|
|
162
|
+
type: m.type,
|
|
163
|
+
info: m.info
|
|
118
164
|
}));
|
|
119
165
|
return {
|
|
120
|
-
from:
|
|
121
|
-
options:
|
|
166
|
+
from: r,
|
|
167
|
+
options: g
|
|
122
168
|
};
|
|
123
169
|
}
|
|
124
|
-
return
|
|
125
|
-
from:
|
|
170
|
+
return a.name === "Field" ? {
|
|
171
|
+
from: r,
|
|
126
172
|
options: []
|
|
127
173
|
} : null;
|
|
128
174
|
}
|
|
129
|
-
}),
|
|
175
|
+
}), G = A.define([
|
|
130
176
|
{ tag: t.Condition, class: "cnd" },
|
|
131
177
|
{ tag: t.Operator, class: "cnd-op" },
|
|
132
178
|
{ tag: t.Value, class: "cnd-val" },
|
|
133
179
|
{ tag: t.Command, class: "cnd-val cnd-cmd" },
|
|
134
180
|
{ tag: t.Field, class: "cnd-fld" },
|
|
135
|
-
{ tag: t.
|
|
136
|
-
{ tag:
|
|
137
|
-
{ tag:
|
|
138
|
-
|
|
181
|
+
{ tag: t.DynamicValue, class: "cnd-val cnd-dynamic" },
|
|
182
|
+
{ tag: i.string, class: "string" },
|
|
183
|
+
{ tag: i.number, class: "cnd-val" },
|
|
184
|
+
{ tag: i.lineComment, class: "comment" }
|
|
185
|
+
]), Z = Q.configure({
|
|
139
186
|
props: [
|
|
140
|
-
|
|
187
|
+
E({
|
|
188
|
+
// Condition structure
|
|
141
189
|
"Condition/:": t.Operator,
|
|
142
190
|
"ExcludeCondition/:": t.Operator,
|
|
143
191
|
"Condition/Field/...": t.Field,
|
|
144
|
-
|
|
192
|
+
Field: t.Field,
|
|
193
|
+
// Command and values
|
|
145
194
|
"Command!": t.Command,
|
|
195
|
+
"Value!": t.Value,
|
|
146
196
|
"Separator!": t.Operator,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
"
|
|
197
|
+
// Logical operators
|
|
198
|
+
"And Or": t.Operator,
|
|
199
|
+
// Comparison and range operators
|
|
200
|
+
"CompareOp Contains StartsWith EndsWith Not RangeSep": t.Operator,
|
|
201
|
+
// Special value types
|
|
202
|
+
DynamicValue: t.DynamicValue,
|
|
203
|
+
DateLiteral: i.number,
|
|
204
|
+
// Object blocks
|
|
205
|
+
"ObjectBlock/Identifier": t.Field,
|
|
206
|
+
// Comments
|
|
207
|
+
Comment: i.lineComment
|
|
151
208
|
}),
|
|
152
209
|
v.add({
|
|
153
|
-
Query: (e) => e.column(e.node.from) + e.unit
|
|
210
|
+
Query: (e) => e.column(e.node.from) + e.unit,
|
|
211
|
+
ObjectBlock: (e) => e.column(e.node.from) + e.unit
|
|
154
212
|
}),
|
|
155
|
-
|
|
156
|
-
Query:
|
|
213
|
+
F.add({
|
|
214
|
+
Query: P,
|
|
215
|
+
ObjectBlock: P
|
|
157
216
|
})
|
|
158
217
|
]
|
|
159
|
-
}),
|
|
160
|
-
parser:
|
|
218
|
+
}), b = I.define({
|
|
219
|
+
parser: Z,
|
|
161
220
|
languageData: {}
|
|
162
221
|
});
|
|
163
|
-
function
|
|
164
|
-
return new
|
|
165
|
-
|
|
166
|
-
|
|
222
|
+
function X() {
|
|
223
|
+
return new L(b, [
|
|
224
|
+
k(G),
|
|
225
|
+
H
|
|
167
226
|
]);
|
|
168
227
|
}
|
|
169
228
|
export {
|
|
170
|
-
|
|
171
|
-
|
|
229
|
+
X as DequelLang,
|
|
230
|
+
b as dequelParser
|
|
172
231
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dequel-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"description": "CodeMirror-based editor for Dequel query language",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/dequel-editor.js",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"eslint": "^8.57.1",
|
|
58
58
|
"gettext-parser": "^8.0.0",
|
|
59
59
|
"http-proxy-middleware": "^3.0.5",
|
|
60
|
+
"jsdom": "^28.1.0",
|
|
60
61
|
"tailwindcss": "^4.1.18",
|
|
61
62
|
"tsx": "^4.19.4",
|
|
62
63
|
"typescript": "^5.9.3",
|