@dorsk/tsumikit 0.9.1 → 0.9.2

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.
@@ -20,7 +20,13 @@ export interface SuggestState {
20
20
  span: [number, number];
21
21
  items: Suggestion[];
22
22
  }
23
- /** The whitespace-delimited token under the caret (quotes count as non-ws). */
23
+ /**
24
+ * The token under the caret. Whitespace ends a token EXCEPT inside an open
25
+ * quote, so a quoted value containing spaces (`album:"ok computer`) stays one
26
+ * token and keeps the caret in the value step rather than collapsing to an
27
+ * empty token (which would wrongly re-offer fields). A closed quote followed by
28
+ * whitespace starts a fresh token (so the next `field:` can be chained).
29
+ */
24
30
  export declare function activeToken(s: string, pos: number): {
25
31
  start: number;
26
32
  end: number;
@@ -9,14 +9,49 @@
9
9
  import { findField, operatorsFor, resolveValues, } from './schema';
10
10
  // Longest first so `>=`/`!:` win over `>`/`:`.
11
11
  const OP_CODES = ['!:', '!=', '>=', '<=', ':', '=', '>', '<'];
12
- /** The whitespace-delimited token under the caret (quotes count as non-ws). */
12
+ /**
13
+ * The token under the caret. Whitespace ends a token EXCEPT inside an open
14
+ * quote, so a quoted value containing spaces (`album:"ok computer`) stays one
15
+ * token and keeps the caret in the value step rather than collapsing to an
16
+ * empty token (which would wrongly re-offer fields). A closed quote followed by
17
+ * whitespace starts a fresh token (so the next `field:` can be chained).
18
+ */
13
19
  export function activeToken(s, pos) {
14
- let start = pos;
15
- while (start > 0 && !/\s/.test(s[start - 1]))
16
- start--;
20
+ // Walk from the start so we can track quote state; the last unquoted
21
+ // whitespace before the caret is the token boundary.
22
+ let start = 0;
23
+ let inQuote = false;
24
+ let q = '';
25
+ for (let i = 0; i < pos; i++) {
26
+ const c = s[i];
27
+ if (inQuote) {
28
+ if (c === q)
29
+ inQuote = false;
30
+ }
31
+ else if (c === '"' || c === "'") {
32
+ inQuote = true;
33
+ q = c;
34
+ }
35
+ else if (/\s/.test(c)) {
36
+ start = i + 1;
37
+ }
38
+ }
39
+ // Extend forward through the rest of the token, still respecting quotes.
17
40
  let end = pos;
18
- while (end < s.length && !/\s/.test(s[end]))
19
- end++;
41
+ for (let i = pos; i < s.length; i++) {
42
+ const c = s[i];
43
+ if (!inQuote && /\s/.test(c))
44
+ break;
45
+ if (inQuote) {
46
+ if (c === q)
47
+ inQuote = false;
48
+ }
49
+ else if (c === '"' || c === "'") {
50
+ inQuote = true;
51
+ q = c;
52
+ }
53
+ end = i + 1;
54
+ }
20
55
  return { start, end, raw: s.slice(start, end) };
21
56
  }
22
57
  /** Split a token into field / operator-code / value parts (earliest op wins). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dorsk/tsumikit",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Minimal, dependency-free Svelte 5 + pure-CSS UI kit. Token-driven atoms, molecules & layouts with theming out of the box.",
5
5
  "type": "module",
6
6
  "license": "MIT",