@orz/query 0.0.0-stage → 0.0.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/LICENSE +29 -0
- package/README.md +103 -2
- package/dist/braces.d.ts +32 -0
- package/dist/braces.d.ts.map +1 -0
- package/dist/braces.js +127 -0
- package/dist/braces.js.map +1 -0
- package/dist/commands.d.ts +109 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +260 -0
- package/dist/commands.js.map +1 -0
- package/dist/completion.d.ts +166 -0
- package/dist/completion.d.ts.map +1 -0
- package/dist/completion.js +400 -0
- package/dist/completion.js.map +1 -0
- package/dist/diagnostics.d.ts +20 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +63 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/query.d.ts +119 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +449 -0
- package/dist/query.js.map +1 -0
- package/dist/shell-words.d.ts +38 -0
- package/dist/shell-words.d.ts.map +1 -0
- package/dist/shell-words.js +136 -0
- package/dist/shell-words.js.map +1 -0
- package/dist/suggest.d.ts +7 -0
- package/dist/suggest.d.ts.map +1 -0
- package/dist/suggest.js +44 -0
- package/dist/suggest.js.map +1 -0
- package/dist/values.d.ts +70 -0
- package/dist/values.d.ts.map +1 -0
- package/dist/values.js +91 -0
- package/dist/values.js.map +1 -0
- package/package.json +32 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
package/dist/query.js
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A search query grammar over a schema the app supplies. The app's server
|
|
3
|
+
* parses `q` and executes it (authoritative); its web box parses the same
|
|
4
|
+
* string to colour it and to place completions; a CLI parses it to re-quote
|
|
5
|
+
* the values that carry spaces. One string carries the whole query, so "the
|
|
6
|
+
* same query gives the same results in the CLI and on the web" holds
|
|
7
|
+
* structurally instead of being a discipline two implementations have to
|
|
8
|
+
* keep.
|
|
9
|
+
*
|
|
10
|
+
* Nothing here decides whether a `named` value exists: `label:kind:bug`
|
|
11
|
+
* parses the same in a project that has that label and in one that does
|
|
12
|
+
* not. Names are resolved by the caller, which keeps this module a pure
|
|
13
|
+
* function on either side of the wire.
|
|
14
|
+
*/
|
|
15
|
+
import { BRACE_LIMIT, expandBraceChars, expandBraces, } from "./braces.js";
|
|
16
|
+
import { quoteShellWord, segmentValue, shellWords, } from "./shell-words.js";
|
|
17
|
+
const KEY_SPELLING = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
18
|
+
/**
|
|
19
|
+
* Throws on a malformed table: these are programmer errors in static data,
|
|
20
|
+
* caught at module load rather than on some reader's query.
|
|
21
|
+
*/
|
|
22
|
+
export function defineQuerySchema(schema) {
|
|
23
|
+
const keys = Object.keys(schema.qualifiers);
|
|
24
|
+
const spellings = new Map();
|
|
25
|
+
for (const key of keys) {
|
|
26
|
+
const spec = schema.qualifiers[key];
|
|
27
|
+
for (const spelling of [key, ...(spec.keyAliases ?? [])]) {
|
|
28
|
+
if (!KEY_SPELLING.test(spelling)) {
|
|
29
|
+
throw new Error(`query key "${spelling}" must match ${KEY_SPELLING}`);
|
|
30
|
+
}
|
|
31
|
+
const lower = spelling.toLowerCase();
|
|
32
|
+
const taken = spellings.get(lower);
|
|
33
|
+
if (taken !== undefined) {
|
|
34
|
+
throw new Error(`query key "${spelling}" of "${key}" is already a spelling of "${taken}"`);
|
|
35
|
+
}
|
|
36
|
+
spellings.set(lower, key);
|
|
37
|
+
}
|
|
38
|
+
const value = spec.value;
|
|
39
|
+
if (value.kind === "enum") {
|
|
40
|
+
for (const [alias, canonical] of Object.entries(value.aliases ?? {})) {
|
|
41
|
+
if (!value.values.includes(canonical)) {
|
|
42
|
+
throw new Error(`alias "${alias}" of "${key}" names "${canonical}", which is not one of its values`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
qualifiers: schema.qualifiers,
|
|
49
|
+
keys,
|
|
50
|
+
spellings,
|
|
51
|
+
escapes: schema.escapes ?? "plain",
|
|
52
|
+
braces: schema.braces ?? false,
|
|
53
|
+
maxFilters: schema.maxFilters,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const KEY_HEAD = /[A-Za-z]/;
|
|
57
|
+
const KEY_BODY = /[A-Za-z0-9_-]/;
|
|
58
|
+
const isSpace = (ch) => /\s/.test(ch);
|
|
59
|
+
function expandedOf(schema, word, value) {
|
|
60
|
+
if (!schema.braces)
|
|
61
|
+
return { expanded: [value] };
|
|
62
|
+
const expansion = expandBraces(word, { limit: BRACE_LIMIT });
|
|
63
|
+
return expansion.ok
|
|
64
|
+
? { expanded: expansion.words }
|
|
65
|
+
: { expanded: [value], error: expansion.reason };
|
|
66
|
+
}
|
|
67
|
+
function plainBraces(q, from) {
|
|
68
|
+
const closeOf = new Map();
|
|
69
|
+
const runs = new Map();
|
|
70
|
+
const stack = [];
|
|
71
|
+
let valueStart = from;
|
|
72
|
+
let i = from;
|
|
73
|
+
while (i < q.length) {
|
|
74
|
+
const ch = q[i];
|
|
75
|
+
if (isSpace(ch))
|
|
76
|
+
break;
|
|
77
|
+
const top = stack.at(-1);
|
|
78
|
+
if (ch === '"') {
|
|
79
|
+
if (i !== (top === undefined ? valueStart : top.alternative))
|
|
80
|
+
break;
|
|
81
|
+
const close = q.indexOf('"', i + 1);
|
|
82
|
+
if (close === -1)
|
|
83
|
+
break;
|
|
84
|
+
if (top !== undefined)
|
|
85
|
+
runs.set(i, close);
|
|
86
|
+
i = close + 1;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (ch === "{")
|
|
90
|
+
stack.push({ open: i, alternative: i + 1 });
|
|
91
|
+
else if (ch === "}") {
|
|
92
|
+
const open = stack.pop();
|
|
93
|
+
if (open !== undefined)
|
|
94
|
+
closeOf.set(open.open, i);
|
|
95
|
+
}
|
|
96
|
+
else if (ch === ",") {
|
|
97
|
+
if (top !== undefined)
|
|
98
|
+
top.alternative = i + 1;
|
|
99
|
+
else
|
|
100
|
+
valueStart = i + 1;
|
|
101
|
+
}
|
|
102
|
+
i += 1;
|
|
103
|
+
}
|
|
104
|
+
return { closeOf, runs };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A value: a quoted run, or one stretch of non-space, non-comma, non-quote.
|
|
108
|
+
* With braces on, a balanced `{…}` is absorbed commas, quoted alternatives
|
|
109
|
+
* and all. A quoted value is never expanded: quoting is how a brace is
|
|
110
|
+
* searched for literally.
|
|
111
|
+
*/
|
|
112
|
+
function scanPlainValue(q, at, braces) {
|
|
113
|
+
if (q[at] === '"') {
|
|
114
|
+
const close = q.indexOf('"', at + 1);
|
|
115
|
+
const inner = close === -1 ? q.length : close;
|
|
116
|
+
const end = close === -1 ? q.length : close + 1;
|
|
117
|
+
const value = q.slice(at + 1, inner);
|
|
118
|
+
return { start: at, end, raw: q.slice(at, end), value, expanded: [value] };
|
|
119
|
+
}
|
|
120
|
+
let end = at;
|
|
121
|
+
while (end < q.length) {
|
|
122
|
+
const ch = q[end];
|
|
123
|
+
if (isSpace(ch) || ch === "," || ch === '"')
|
|
124
|
+
break;
|
|
125
|
+
const close = braces?.closeOf.get(end);
|
|
126
|
+
end = close === undefined ? end + 1 : close + 1;
|
|
127
|
+
}
|
|
128
|
+
const raw = q.slice(at, end);
|
|
129
|
+
if (braces === null) {
|
|
130
|
+
return { start: at, end, raw, value: raw, expanded: [raw] };
|
|
131
|
+
}
|
|
132
|
+
const chars = [];
|
|
133
|
+
for (let i = at; i < end; i += 1) {
|
|
134
|
+
const close = braces.runs.get(i);
|
|
135
|
+
if (close === undefined) {
|
|
136
|
+
chars.push({ ch: q[i], active: true });
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
for (const ch of q.slice(i + 1, close))
|
|
140
|
+
chars.push({ ch, active: false });
|
|
141
|
+
i = close;
|
|
142
|
+
}
|
|
143
|
+
const value = chars.map((c) => c.ch).join("");
|
|
144
|
+
const expansion = expandBraceChars(chars, BRACE_LIMIT);
|
|
145
|
+
return {
|
|
146
|
+
start: at,
|
|
147
|
+
end,
|
|
148
|
+
raw,
|
|
149
|
+
value,
|
|
150
|
+
...(expansion.ok
|
|
151
|
+
? { expanded: expansion.words }
|
|
152
|
+
: { expanded: [value], error: expansion.reason }),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* `-?key:value-list` when `key` is one we know, null otherwise — and "null"
|
|
157
|
+
* is the load-bearing half. `area:web` and `kind:bug` are ordinary label
|
|
158
|
+
* names, `https://…` and a timestamp like `12:30` are ordinary things to
|
|
159
|
+
* search for. Rejecting an unrecognised key would turn such queries into
|
|
160
|
+
* syntax errors, so an unknown key falls through to plain text. Searching a
|
|
161
|
+
* known key literally is still possible by quoting the whole run:
|
|
162
|
+
* `"harness:"`.
|
|
163
|
+
*/
|
|
164
|
+
function scanPlainFilter(schema, q, at) {
|
|
165
|
+
let i = at;
|
|
166
|
+
const negated = q[i] === "-";
|
|
167
|
+
if (negated)
|
|
168
|
+
i += 1;
|
|
169
|
+
const keyStart = i;
|
|
170
|
+
if (i >= q.length || !KEY_HEAD.test(q[i]))
|
|
171
|
+
return null;
|
|
172
|
+
i += 1;
|
|
173
|
+
while (i < q.length && KEY_BODY.test(q[i]))
|
|
174
|
+
i += 1;
|
|
175
|
+
const keyEnd = i;
|
|
176
|
+
if (q[i] !== ":")
|
|
177
|
+
return null;
|
|
178
|
+
const key = schema.spellings.get(q.slice(keyStart, keyEnd).toLowerCase());
|
|
179
|
+
if (key === undefined)
|
|
180
|
+
return null;
|
|
181
|
+
i += 1;
|
|
182
|
+
const braces = schema.braces ? plainBraces(q, i) : null;
|
|
183
|
+
const values = [];
|
|
184
|
+
for (;;) {
|
|
185
|
+
const value = scanPlainValue(q, i, braces);
|
|
186
|
+
i = value.end;
|
|
187
|
+
// An empty value is someone mid-typing (`label:`), not an error and not a
|
|
188
|
+
// condition; the comma that may follow is still consumed so the scan
|
|
189
|
+
// advances.
|
|
190
|
+
if (value.value !== "")
|
|
191
|
+
values.push(value);
|
|
192
|
+
if (q[i] !== ",")
|
|
193
|
+
break;
|
|
194
|
+
i += 1;
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
kind: "filter",
|
|
198
|
+
start: at,
|
|
199
|
+
end: i,
|
|
200
|
+
raw: q.slice(at, i),
|
|
201
|
+
key,
|
|
202
|
+
negated,
|
|
203
|
+
keyStart,
|
|
204
|
+
keyEnd,
|
|
205
|
+
values,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* The scan is one pass with no backtracking, deciding at each position in
|
|
210
|
+
* this order: whitespace, a quoted run, a known qualifier, bare text.
|
|
211
|
+
*/
|
|
212
|
+
function parsePlain(schema, q) {
|
|
213
|
+
const parts = [];
|
|
214
|
+
let i = 0;
|
|
215
|
+
while (i < q.length) {
|
|
216
|
+
const ch = q[i];
|
|
217
|
+
if (isSpace(ch)) {
|
|
218
|
+
const start = i;
|
|
219
|
+
while (i < q.length && isSpace(q[i]))
|
|
220
|
+
i += 1;
|
|
221
|
+
parts.push({ kind: "space", start, end: i });
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (ch === '"') {
|
|
225
|
+
const close = q.indexOf('"', i + 1);
|
|
226
|
+
const inner = close === -1 ? q.length : close;
|
|
227
|
+
const end = close === -1 ? q.length : close + 1;
|
|
228
|
+
// An unclosed quote runs to the end rather than failing — the user is
|
|
229
|
+
// mid-typing, and there is exactly one thing they can mean.
|
|
230
|
+
parts.push({
|
|
231
|
+
kind: "text",
|
|
232
|
+
start: i,
|
|
233
|
+
end,
|
|
234
|
+
raw: q.slice(i, end),
|
|
235
|
+
term: q.slice(i + 1, inner),
|
|
236
|
+
});
|
|
237
|
+
i = end;
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const filter = scanPlainFilter(schema, q, i);
|
|
241
|
+
if (filter) {
|
|
242
|
+
parts.push(filter);
|
|
243
|
+
i = filter.end;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
let end = i;
|
|
247
|
+
// A quote ends a bare run: `ab"cd"` has been two terms since the first
|
|
248
|
+
// version of this scanner, and queries in the wild rely on it.
|
|
249
|
+
while (end < q.length && !isSpace(q[end]) && q[end] !== '"') {
|
|
250
|
+
end += 1;
|
|
251
|
+
}
|
|
252
|
+
const raw = q.slice(i, end);
|
|
253
|
+
parts.push({ kind: "text", start: i, end, raw, term: raw });
|
|
254
|
+
i = end;
|
|
255
|
+
}
|
|
256
|
+
return parts;
|
|
257
|
+
}
|
|
258
|
+
function unitsOf(word, from) {
|
|
259
|
+
const units = [];
|
|
260
|
+
for (const segment of word.segments) {
|
|
261
|
+
if (segment.end <= from)
|
|
262
|
+
continue;
|
|
263
|
+
if (segment.quoted !== "none") {
|
|
264
|
+
units.push({
|
|
265
|
+
start: segment.start,
|
|
266
|
+
end: segment.end,
|
|
267
|
+
bare: null,
|
|
268
|
+
segment,
|
|
269
|
+
});
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
for (let i = Math.max(segment.start, from); i < segment.end; i += 1) {
|
|
273
|
+
units.push({
|
|
274
|
+
start: i,
|
|
275
|
+
end: i + 1,
|
|
276
|
+
bare: word.raw[i - word.start] ?? "",
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return units;
|
|
281
|
+
}
|
|
282
|
+
/** Unit indexes inside a balanced bare `{…}`, where a comma does not split. */
|
|
283
|
+
function groupedUnits(units) {
|
|
284
|
+
// Depth deltas swept once, so nested pairs stay linear in the word's length.
|
|
285
|
+
const delta = new Array(units.length + 1).fill(0);
|
|
286
|
+
const stack = [];
|
|
287
|
+
for (let i = 0; i < units.length; i += 1) {
|
|
288
|
+
const bare = units[i]?.bare;
|
|
289
|
+
if (bare === "{")
|
|
290
|
+
stack.push(i);
|
|
291
|
+
else if (bare === "}" && stack.length > 0) {
|
|
292
|
+
const open = stack.pop();
|
|
293
|
+
delta[open + 1] = delta[open + 1] + 1;
|
|
294
|
+
delta[i] = delta[i] - 1;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const grouped = new Set();
|
|
298
|
+
let depth = 0;
|
|
299
|
+
for (let i = 0; i < units.length; i += 1) {
|
|
300
|
+
depth += delta[i];
|
|
301
|
+
if (depth > 0)
|
|
302
|
+
grouped.add(i);
|
|
303
|
+
}
|
|
304
|
+
return grouped;
|
|
305
|
+
}
|
|
306
|
+
/** One value of a shell-mode filter, as a word of its own. */
|
|
307
|
+
function shellValue(schema, q, units, start, end) {
|
|
308
|
+
const segments = [];
|
|
309
|
+
for (const unit of units) {
|
|
310
|
+
const last = segments.at(-1);
|
|
311
|
+
if (unit.bare !== null &&
|
|
312
|
+
last?.quoted === "none" &&
|
|
313
|
+
last.end === unit.start) {
|
|
314
|
+
last.end = unit.end;
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
segments.push(unit.bare === null
|
|
318
|
+
? { ...unit.segment }
|
|
319
|
+
: { start: unit.start, end: unit.end, quoted: "none" });
|
|
320
|
+
}
|
|
321
|
+
const raw = q.slice(start, end);
|
|
322
|
+
const piece = { start, end, raw, value: "", segments };
|
|
323
|
+
piece.value = segments.map((s) => segmentValue(piece, s)).join("");
|
|
324
|
+
return {
|
|
325
|
+
start,
|
|
326
|
+
end,
|
|
327
|
+
raw,
|
|
328
|
+
value: piece.value,
|
|
329
|
+
...expandedOf(schema, piece, piece.value),
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
const SHELL_KEY = /^(-?)([A-Za-z][A-Za-z0-9_-]*):/;
|
|
333
|
+
/**
|
|
334
|
+
* A qualifier needs `-?key:` bare at the start of a word, so `"label:x"` and
|
|
335
|
+
* `label\:x` are text: that is how a known key is searched for literally in
|
|
336
|
+
* this mode.
|
|
337
|
+
*/
|
|
338
|
+
function shellFilter(schema, q, word) {
|
|
339
|
+
const head = word.segments[0];
|
|
340
|
+
if (head === undefined || head.quoted !== "none")
|
|
341
|
+
return null;
|
|
342
|
+
const match = SHELL_KEY.exec(q.slice(head.start, head.end));
|
|
343
|
+
if (match === null)
|
|
344
|
+
return null;
|
|
345
|
+
const [, minus = "", typed = ""] = match;
|
|
346
|
+
const key = schema.spellings.get(typed.toLowerCase());
|
|
347
|
+
if (key === undefined)
|
|
348
|
+
return null;
|
|
349
|
+
const keyStart = word.start + minus.length;
|
|
350
|
+
const keyEnd = keyStart + typed.length;
|
|
351
|
+
const units = unitsOf(word, keyEnd + 1);
|
|
352
|
+
const grouped = schema.braces ? groupedUnits(units) : new Set();
|
|
353
|
+
const values = [];
|
|
354
|
+
let first = 0;
|
|
355
|
+
let start = keyEnd + 1;
|
|
356
|
+
for (let i = 0; i <= units.length; i += 1) {
|
|
357
|
+
const unit = units[i];
|
|
358
|
+
if (unit !== undefined && (unit.bare !== "," || grouped.has(i)))
|
|
359
|
+
continue;
|
|
360
|
+
const end = unit?.start ?? word.end;
|
|
361
|
+
const value = shellValue(schema, q, units.slice(first, i), start, end);
|
|
362
|
+
// Empty is someone mid-typing, as in plain mode.
|
|
363
|
+
if (value.value !== "")
|
|
364
|
+
values.push(value);
|
|
365
|
+
first = i + 1;
|
|
366
|
+
start = unit?.end ?? word.end;
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
kind: "filter",
|
|
370
|
+
start: word.start,
|
|
371
|
+
end: word.end,
|
|
372
|
+
raw: word.raw,
|
|
373
|
+
key,
|
|
374
|
+
negated: minus === "-",
|
|
375
|
+
keyStart,
|
|
376
|
+
keyEnd,
|
|
377
|
+
values,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
function parseShell(schema, q) {
|
|
381
|
+
const parts = [];
|
|
382
|
+
let at = 0;
|
|
383
|
+
for (const word of shellWords(q)) {
|
|
384
|
+
if (word.start > at)
|
|
385
|
+
parts.push({ kind: "space", start: at, end: word.start });
|
|
386
|
+
parts.push(shellFilter(schema, q, word) ?? {
|
|
387
|
+
kind: "text",
|
|
388
|
+
start: word.start,
|
|
389
|
+
end: word.end,
|
|
390
|
+
raw: word.raw,
|
|
391
|
+
term: word.value,
|
|
392
|
+
});
|
|
393
|
+
at = word.end;
|
|
394
|
+
}
|
|
395
|
+
if (at < q.length)
|
|
396
|
+
parts.push({ kind: "space", start: at, end: q.length });
|
|
397
|
+
return parts;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* `q` split into spans that tile it completely — every character of the input
|
|
401
|
+
* belongs to exactly one part, which is what lets a mirror layer render the
|
|
402
|
+
* string by walking this list.
|
|
403
|
+
*
|
|
404
|
+
* Never throws: a half-typed query is the normal case for a search box, and
|
|
405
|
+
* every shape of input has a reading.
|
|
406
|
+
*/
|
|
407
|
+
export function parseQuery(schema, q) {
|
|
408
|
+
return schema.escapes === "shell"
|
|
409
|
+
? parseShell(schema, q)
|
|
410
|
+
: parsePlain(schema, q);
|
|
411
|
+
}
|
|
412
|
+
/** The free-text terms, in source order; an empty `""` contributes nothing. */
|
|
413
|
+
export function queryTerms(parts) {
|
|
414
|
+
const terms = [];
|
|
415
|
+
for (const part of parts) {
|
|
416
|
+
if (part.kind === "text" && part.term !== "")
|
|
417
|
+
terms.push(part.term);
|
|
418
|
+
}
|
|
419
|
+
return terms;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Brace expansions are flattened, so `label:area:{web,ui}` reaches a server
|
|
423
|
+
* as `label:area:web,area:ui`, which it already reads as an OR.
|
|
424
|
+
*/
|
|
425
|
+
export function queryFilters(parts) {
|
|
426
|
+
const filters = [];
|
|
427
|
+
for (const part of parts) {
|
|
428
|
+
if (part.kind !== "filter")
|
|
429
|
+
continue;
|
|
430
|
+
filters.push({
|
|
431
|
+
key: part.key,
|
|
432
|
+
negated: part.negated,
|
|
433
|
+
values: part.values.flatMap((v) => v.expanded.filter((e) => e !== "")),
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
return filters;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* A value spelled so it reads back as one value. Plain mode has no way to
|
|
440
|
+
* spell a quote inside a value — a bare one ends the value — so inner quotes
|
|
441
|
+
* are dropped rather than preserved.
|
|
442
|
+
*/
|
|
443
|
+
export function quoteQueryValue(schema, value) {
|
|
444
|
+
if (schema.escapes === "shell")
|
|
445
|
+
return quoteShellWord(value);
|
|
446
|
+
const unsafe = schema.braces ? /[\s,"{}]/ : /[\s,"]/;
|
|
447
|
+
return unsafe.test(value) ? `"${value.replaceAll('"', "")}"` : value;
|
|
448
|
+
}
|
|
449
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell words: the subset of POSIX `sh` quoting that command lines use and
|
|
3
|
+
* that a query schema can opt into. Backslash escapes one character, `'…'`
|
|
4
|
+
* is literal, `"…"` allows `\"` and `\\`. There are no `$`, globs, `~`,
|
|
5
|
+
* pipes or comments: those characters are ordinary, so pasting a URL or a
|
|
6
|
+
* path needs no thought.
|
|
7
|
+
*/
|
|
8
|
+
export type ShellSegment = {
|
|
9
|
+
/** Offsets of the segment's source, quotes and backslash included. */
|
|
10
|
+
start: number;
|
|
11
|
+
end: number;
|
|
12
|
+
quoted: "none" | "single" | "double" | "escape";
|
|
13
|
+
};
|
|
14
|
+
export type ShellWord = {
|
|
15
|
+
/** Offsets in the scanned text, shifted by `offset`. */
|
|
16
|
+
start: number;
|
|
17
|
+
end: number;
|
|
18
|
+
raw: string;
|
|
19
|
+
/** Quotes and escapes removed. */
|
|
20
|
+
value: string;
|
|
21
|
+
/**
|
|
22
|
+
* Which characters were quoted or escaped. Brace expansion and painting
|
|
23
|
+
* read these, so the distinction survives quote removal.
|
|
24
|
+
*/
|
|
25
|
+
segments: ShellSegment[];
|
|
26
|
+
/** A quote was still open at the end. */
|
|
27
|
+
unclosed?: boolean;
|
|
28
|
+
};
|
|
29
|
+
/** Never throws: every string has a reading. */
|
|
30
|
+
export declare function shellWords(text: string, offset?: number): ShellWord[];
|
|
31
|
+
/**
|
|
32
|
+
* What one segment contributes to the word's value. `word` must be the word
|
|
33
|
+
* the segment belongs to.
|
|
34
|
+
*/
|
|
35
|
+
export declare function segmentValue(word: ShellWord, segment: ShellSegment): string;
|
|
36
|
+
/** Bare when safe, else `'…'`, else `"…"`. Round-trips through `shellWords`. */
|
|
37
|
+
export declare function quoteShellWord(value: string): string;
|
|
38
|
+
//# sourceMappingURL=shell-words.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-words.d.ts","sourceRoot":"","sources":["../src/shell-words.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,YAAY,GAAG;IACzB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAUF,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,SAAS,EAAE,CAuEhE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAkB3E;AAkBD,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpD"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell words: the subset of POSIX `sh` quoting that command lines use and
|
|
3
|
+
* that a query schema can opt into. Backslash escapes one character, `'…'`
|
|
4
|
+
* is literal, `"…"` allows `\"` and `\\`. There are no `$`, globs, `~`,
|
|
5
|
+
* pipes or comments: those characters are ordinary, so pasting a URL or a
|
|
6
|
+
* path needs no thought.
|
|
7
|
+
*/
|
|
8
|
+
const isSpace = (ch) => /\s/.test(ch);
|
|
9
|
+
/** Length of the code point at `i`, so `\` never splits a surrogate pair. */
|
|
10
|
+
function codePointLength(text, i) {
|
|
11
|
+
const cp = text.codePointAt(i);
|
|
12
|
+
return cp !== undefined && cp > 0xffff ? 2 : 1;
|
|
13
|
+
}
|
|
14
|
+
/** Never throws: every string has a reading. */
|
|
15
|
+
export function shellWords(text, offset = 0) {
|
|
16
|
+
const words = [];
|
|
17
|
+
let i = 0;
|
|
18
|
+
while (i < text.length) {
|
|
19
|
+
if (isSpace(text[i])) {
|
|
20
|
+
i += 1;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const start = i;
|
|
24
|
+
const segments = [];
|
|
25
|
+
let value = "";
|
|
26
|
+
let unclosed = false;
|
|
27
|
+
while (i < text.length && !isSpace(text[i])) {
|
|
28
|
+
const ch = text[i];
|
|
29
|
+
if (ch === "'") {
|
|
30
|
+
const close = text.indexOf("'", i + 1);
|
|
31
|
+
const end = close === -1 ? text.length : close + 1;
|
|
32
|
+
value += text.slice(i + 1, close === -1 ? end : close);
|
|
33
|
+
if (close === -1)
|
|
34
|
+
unclosed = true;
|
|
35
|
+
segments.push({ start: i, end, quoted: "single" });
|
|
36
|
+
i = end;
|
|
37
|
+
}
|
|
38
|
+
else if (ch === '"') {
|
|
39
|
+
let j = i + 1;
|
|
40
|
+
let closed = false;
|
|
41
|
+
while (j < text.length) {
|
|
42
|
+
const c = text[j];
|
|
43
|
+
if (c === '"') {
|
|
44
|
+
closed = true;
|
|
45
|
+
j += 1;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
const next = text[j + 1];
|
|
49
|
+
if (c === "\\" && (next === '"' || next === "\\")) {
|
|
50
|
+
value += next;
|
|
51
|
+
j += 2;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
value += c;
|
|
55
|
+
j += 1;
|
|
56
|
+
}
|
|
57
|
+
if (!closed)
|
|
58
|
+
unclosed = true;
|
|
59
|
+
segments.push({ start: i, end: j, quoted: "double" });
|
|
60
|
+
i = j;
|
|
61
|
+
}
|
|
62
|
+
else if (ch === "\\" && i + 1 < text.length) {
|
|
63
|
+
const len = 1 + codePointLength(text, i + 1);
|
|
64
|
+
value += text.slice(i + 1, i + len);
|
|
65
|
+
segments.push({ start: i, end: i + len, quoted: "escape" });
|
|
66
|
+
i += len;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// A trailing lone `\` has nothing to escape and stays literal.
|
|
70
|
+
const last = segments.at(-1);
|
|
71
|
+
if (last?.quoted === "none" && last.end === i)
|
|
72
|
+
last.end = i + 1;
|
|
73
|
+
else
|
|
74
|
+
segments.push({ start: i, end: i + 1, quoted: "none" });
|
|
75
|
+
value += ch;
|
|
76
|
+
i += 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
words.push({
|
|
80
|
+
start: start + offset,
|
|
81
|
+
end: i + offset,
|
|
82
|
+
raw: text.slice(start, i),
|
|
83
|
+
value,
|
|
84
|
+
segments: segments.map((s) => ({
|
|
85
|
+
...s,
|
|
86
|
+
start: s.start + offset,
|
|
87
|
+
end: s.end + offset,
|
|
88
|
+
})),
|
|
89
|
+
...(unclosed ? { unclosed: true } : {}),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return words;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* What one segment contributes to the word's value. `word` must be the word
|
|
96
|
+
* the segment belongs to.
|
|
97
|
+
*/
|
|
98
|
+
export function segmentValue(word, segment) {
|
|
99
|
+
const raw = word.raw.slice(segment.start - word.start, segment.end - word.start);
|
|
100
|
+
switch (segment.quoted) {
|
|
101
|
+
case "none":
|
|
102
|
+
return raw;
|
|
103
|
+
case "escape":
|
|
104
|
+
return raw.slice(1);
|
|
105
|
+
case "single":
|
|
106
|
+
return raw.slice(1, raw.endsWith("'") && raw.length > 1 ? -1 : undefined);
|
|
107
|
+
case "double": {
|
|
108
|
+
const closed = raw.length > 1 && raw.endsWith('"') && !endsEscaped(raw);
|
|
109
|
+
const inner = raw.slice(1, closed ? -1 : undefined);
|
|
110
|
+
return inner.replace(/\\(["\\])/g, "$1");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** Whether the closing `"` of a double-quoted segment is really `\"`. */
|
|
115
|
+
function endsEscaped(raw) {
|
|
116
|
+
let backslashes = 0;
|
|
117
|
+
for (let i = raw.length - 2; i >= 1 && raw[i] === "\\"; i -= 1) {
|
|
118
|
+
backslashes += 1;
|
|
119
|
+
}
|
|
120
|
+
return backslashes % 2 === 1;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Commas and braces are quoted too, although `shellWords` does not care
|
|
124
|
+
* about them: the word may land inside a brace group, where a bare one
|
|
125
|
+
* would split it.
|
|
126
|
+
*/
|
|
127
|
+
const SAFE = /^[^\s'"\\{},]+$/;
|
|
128
|
+
/** Bare when safe, else `'…'`, else `"…"`. Round-trips through `shellWords`. */
|
|
129
|
+
export function quoteShellWord(value) {
|
|
130
|
+
if (SAFE.test(value))
|
|
131
|
+
return value;
|
|
132
|
+
if (!value.includes("'"))
|
|
133
|
+
return `'${value}'`;
|
|
134
|
+
return `"${value.replace(/["\\]/g, "\\$&")}"`;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=shell-words.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-words.js","sourceRoot":"","sources":["../src/shell-words.ts"],"names":[],"mappings":"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"}
|