@ai-matrx/kit 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.
Files changed (118) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/LICENSE +21 -0
  3. package/README.md +72 -0
  4. package/dist/autosave.cjs +92 -0
  5. package/dist/autosave.cjs.map +1 -0
  6. package/dist/autosave.d.cts +17 -0
  7. package/dist/autosave.d.ts +17 -0
  8. package/dist/autosave.js +72 -0
  9. package/dist/autosave.js.map +1 -0
  10. package/dist/clipboard.cjs +152 -0
  11. package/dist/clipboard.cjs.map +1 -0
  12. package/dist/clipboard.d.cts +17 -0
  13. package/dist/clipboard.d.ts +17 -0
  14. package/dist/clipboard.js +132 -0
  15. package/dist/clipboard.js.map +1 -0
  16. package/dist/color-util.cjs +790 -0
  17. package/dist/color-util.cjs.map +1 -0
  18. package/dist/color-util.d.cts +235 -0
  19. package/dist/color-util.d.ts +235 -0
  20. package/dist/color-util.js +767 -0
  21. package/dist/color-util.js.map +1 -0
  22. package/dist/concurrency.cjs +59 -0
  23. package/dist/concurrency.cjs.map +1 -0
  24. package/dist/concurrency.d.cts +19 -0
  25. package/dist/concurrency.d.ts +19 -0
  26. package/dist/concurrency.js +38 -0
  27. package/dist/concurrency.js.map +1 -0
  28. package/dist/confirm.cjs +344 -0
  29. package/dist/confirm.cjs.map +1 -0
  30. package/dist/confirm.d.cts +132 -0
  31. package/dist/confirm.d.ts +132 -0
  32. package/dist/confirm.js +312 -0
  33. package/dist/confirm.js.map +1 -0
  34. package/dist/delimiter-guard.cjs +172 -0
  35. package/dist/delimiter-guard.cjs.map +1 -0
  36. package/dist/delimiter-guard.d.cts +119 -0
  37. package/dist/delimiter-guard.d.ts +119 -0
  38. package/dist/delimiter-guard.js +151 -0
  39. package/dist/delimiter-guard.js.map +1 -0
  40. package/dist/drafts.cjs +223 -0
  41. package/dist/drafts.cjs.map +1 -0
  42. package/dist/drafts.d.cts +62 -0
  43. package/dist/drafts.d.ts +62 -0
  44. package/dist/drafts.js +201 -0
  45. package/dist/drafts.js.map +1 -0
  46. package/dist/idb-store.cjs +178 -0
  47. package/dist/idb-store.cjs.map +1 -0
  48. package/dist/idb-store.d.cts +111 -0
  49. package/dist/idb-store.d.ts +111 -0
  50. package/dist/idb-store.js +155 -0
  51. package/dist/idb-store.js.map +1 -0
  52. package/dist/idle-scheduler.cjs +268 -0
  53. package/dist/idle-scheduler.cjs.map +1 -0
  54. package/dist/idle-scheduler.d.cts +185 -0
  55. package/dist/idle-scheduler.d.ts +185 -0
  56. package/dist/idle-scheduler.js +246 -0
  57. package/dist/idle-scheduler.js.map +1 -0
  58. package/dist/index.cjs +3113 -0
  59. package/dist/index.cjs.map +1 -0
  60. package/dist/index.d.cts +897 -0
  61. package/dist/index.d.ts +897 -0
  62. package/dist/index.js +3088 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/invalidation.cjs +64 -0
  65. package/dist/invalidation.cjs.map +1 -0
  66. package/dist/invalidation.d.cts +52 -0
  67. package/dist/invalidation.d.ts +52 -0
  68. package/dist/invalidation.js +43 -0
  69. package/dist/invalidation.js.map +1 -0
  70. package/dist/json-format.cjs +319 -0
  71. package/dist/json-format.cjs.map +1 -0
  72. package/dist/json-format.d.cts +148 -0
  73. package/dist/json-format.d.ts +148 -0
  74. package/dist/json-format.js +286 -0
  75. package/dist/json-format.js.map +1 -0
  76. package/dist/latest-request.cjs +36 -0
  77. package/dist/latest-request.cjs.map +1 -0
  78. package/dist/latest-request.d.cts +29 -0
  79. package/dist/latest-request.d.ts +29 -0
  80. package/dist/latest-request.js +16 -0
  81. package/dist/latest-request.js.map +1 -0
  82. package/dist/qr.cjs +109 -0
  83. package/dist/qr.cjs.map +1 -0
  84. package/dist/qr.d.cts +47 -0
  85. package/dist/qr.d.ts +47 -0
  86. package/dist/qr.js +78 -0
  87. package/dist/qr.js.map +1 -0
  88. package/dist/react-tree.cjs +69 -0
  89. package/dist/react-tree.cjs.map +1 -0
  90. package/dist/react-tree.d.cts +38 -0
  91. package/dist/react-tree.d.ts +38 -0
  92. package/dist/react-tree.js +38 -0
  93. package/dist/react-tree.js.map +1 -0
  94. package/dist/search-scoring.cjs +116 -0
  95. package/dist/search-scoring.cjs.map +1 -0
  96. package/dist/search-scoring.d.cts +77 -0
  97. package/dist/search-scoring.d.ts +77 -0
  98. package/dist/search-scoring.js +95 -0
  99. package/dist/search-scoring.js.map +1 -0
  100. package/dist/text-case.cjs +313 -0
  101. package/dist/text-case.cjs.map +1 -0
  102. package/dist/text-case.d.cts +53 -0
  103. package/dist/text-case.d.ts +53 -0
  104. package/dist/text-case.js +292 -0
  105. package/dist/text-case.js.map +1 -0
  106. package/dist/toast.cjs +74 -0
  107. package/dist/toast.cjs.map +1 -0
  108. package/dist/toast.d.cts +92 -0
  109. package/dist/toast.d.ts +92 -0
  110. package/dist/toast.js +54 -0
  111. package/dist/toast.js.map +1 -0
  112. package/dist/url-state.cjs +212 -0
  113. package/dist/url-state.cjs.map +1 -0
  114. package/dist/url-state.d.cts +90 -0
  115. package/dist/url-state.d.ts +90 -0
  116. package/dist/url-state.js +199 -0
  117. package/dist/url-state.js.map +1 -0
  118. package/package.json +286 -0
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Canonical JSON value types + narrowing guards.
3
+ *
4
+ * Ported (the subset this subpath needs) from matrx-frontend `types/json.ts` —
5
+ * the honest names for "this is just JSON" that are NOT `any` and NOT a bare
6
+ * `unknown`. The package must stand alone, so the types live here; a Matrx
7
+ * host keeps using its own `@/types/json` for app code and the two are
8
+ * structurally identical.
9
+ */
10
+ type JsonPrimitive = string | number | boolean | null;
11
+ /**
12
+ * A JSON object. Values are `JsonValue | undefined` so optional keys read
13
+ * cleanly (mirrors Supabase's original generated `Json` object member).
14
+ */
15
+ interface JsonObject {
16
+ [key: string]: JsonValue | undefined;
17
+ }
18
+ type JsonArray = JsonValue[];
19
+ type JsonValue = JsonPrimitive | JsonObject | JsonArray;
20
+ /**
21
+ * Narrow an `unknown` (e.g. a bare JSONB column) to a `JsonObject`.
22
+ * Plain object only — arrays and `null` return false.
23
+ */
24
+ declare function isJsonObject(value: unknown): value is JsonObject;
25
+ /** Narrow an `unknown` to a `JsonArray`. */
26
+ declare function isJsonArray(value: unknown): value is JsonArray;
27
+ /** Narrow an `unknown` to a JSON primitive (string | number | boolean | null). */
28
+ declare function isJsonPrimitive(value: unknown): value is JsonPrimitive;
29
+
30
+ /**
31
+ * How the JSON is laid out.
32
+ *
33
+ * - `minify` — one line, zero optional whitespace. The smallest legal form.
34
+ * - `compact` — width-aware: any subtree that fits within `width` is inlined,
35
+ * and sibling entries that fit are packed onto shared lines.
36
+ * Readable AND small; this is the "scrunch it down" default.
37
+ * - `pretty` — classic one-entry-per-line indentation.
38
+ */
39
+ type JsonFormatStyle = "minify" | "compact" | "pretty";
40
+ /** What to do with the markdown code fence around the JSON. */
41
+ type JsonFenceMode =
42
+ /** Keep the fence exactly as it arrived (and add none if there was none). */
43
+ "preserve"
44
+ /** Remove the fence, leaving bare JSON. */
45
+ | "strip"
46
+ /** Ensure a ```json fence, adding one if the source was bare. */
47
+ | "add";
48
+ /** A markdown code fence wrapping the JSON payload. */
49
+ interface JsonFence {
50
+ /** The opening marker as written, e.g. "```" or "~~~~". */
51
+ marker: string;
52
+ /** Info string after the marker, e.g. "json" (empty when the fence was bare). */
53
+ lang: string;
54
+ /** Whitespace the opening fence line was indented by. */
55
+ indent: string;
56
+ /** False when the source ran out before a closing fence (unterminated). */
57
+ closed: boolean;
58
+ }
59
+ /** Which JSON container sits at the root of the payload. */
60
+ type JsonRootKind = "object" | "array" | "scalar";
61
+ /** How permissively the payload had to be parsed. */
62
+ type JsonParser =
63
+ /** Valid JSON — `JSON.parse` accepted it verbatim. */
64
+ "strict"
65
+ /** Only JSON5 accepted it: trailing commas, comments, unquoted keys, … */
66
+ | "tolerant";
67
+ interface JsonDetection {
68
+ /** The payload parsed (strictly or tolerantly) into a value. */
69
+ ok: boolean;
70
+ /**
71
+ * The text is JSON-SHAPED even if it did not parse — it opens with `{`/`[`
72
+ * and closes with the matching bracket, or it arrived in a ```json fence.
73
+ * This is the gate for OFFERING json actions; `ok` is the gate for running
74
+ * them.
75
+ */
76
+ looksLikeJson: boolean;
77
+ /** The parsed value. Present only when `ok`. */
78
+ value?: JsonValue | undefined;
79
+ parser?: JsonParser | undefined;
80
+ /** Human-readable parse failure. Present only when `!ok`. */
81
+ error?: string | undefined;
82
+ /** The fence that was stripped before parsing, when the source had one. */
83
+ fence: JsonFence | null;
84
+ /** Text before the payload (fence excluded) — preserved verbatim on format. */
85
+ leading: string;
86
+ /** Text after the payload (fence excluded) — preserved verbatim on format. */
87
+ trailing: string;
88
+ /** The JSON text itself: fence and surrounding whitespace removed. */
89
+ payload: string;
90
+ root?: JsonRootKind | undefined;
91
+ /** Lines the payload currently occupies. */
92
+ lineCount: number;
93
+ /** Characters the payload currently occupies. */
94
+ charCount: number;
95
+ }
96
+ interface JsonFormatOptions {
97
+ style: JsonFormatStyle;
98
+ /** Spaces per indent level for `compact` / `pretty`. Default 2. */
99
+ indent?: number | undefined;
100
+ /** Target line width for `compact`. Default 100. Ignored otherwise. */
101
+ width?: number | undefined;
102
+ /** Sort object keys alphabetically at every depth. Default false. */
103
+ sortKeys?: boolean | undefined;
104
+ /** Fence handling. Default "preserve". */
105
+ fence?: JsonFenceMode | undefined;
106
+ }
107
+ /** Size of a chunk of text, for before/after reporting. */
108
+ interface JsonTextSize {
109
+ lines: number;
110
+ chars: number;
111
+ }
112
+ interface JsonFormatResult {
113
+ /** False when the text could not be parsed; `text` is then the input, unchanged. */
114
+ ok: boolean;
115
+ /** The re-formatted text (full input: leading + fence + payload + trailing). */
116
+ text: string;
117
+ error?: string | undefined;
118
+ /** True when `text` differs from the input. */
119
+ changed: boolean;
120
+ detection: JsonDetection;
121
+ before: JsonTextSize;
122
+ after: JsonTextSize;
123
+ }
124
+
125
+ /**
126
+ * Detect JSON in `text`. Never throws; a non-JSON string comes back with
127
+ * `ok: false` and `looksLikeJson: false`, which is the signal to offer nothing.
128
+ */
129
+ declare function detectJson(text: string): JsonDetection;
130
+
131
+ declare const DEFAULT_JSON_INDENT = 2;
132
+ declare const DEFAULT_JSON_WIDTH = 100;
133
+ /**
134
+ * Serialize a JSON value in one of the three styles. This is the entry point
135
+ * for callers that already HAVE a value (a DB JSONB blob, an API frame) and
136
+ * just want it laid out; text callers want {@link formatJsonText}.
137
+ */
138
+ declare function stringifyJson(value: JsonValue, options: JsonFormatOptions): string;
139
+ /**
140
+ * Format the JSON found in `text`, preserving everything around it.
141
+ *
142
+ * Never throws. When the text does not parse, the result is `ok: false`,
143
+ * `changed: false`, and `text` is the input verbatim — a formatter that
144
+ * mangles text it did not understand is a data-loss bug.
145
+ */
146
+ declare function formatJsonText(text: string, options: JsonFormatOptions): JsonFormatResult;
147
+
148
+ export { DEFAULT_JSON_INDENT, DEFAULT_JSON_WIDTH, type JsonArray, type JsonDetection, type JsonFence, type JsonFenceMode, type JsonFormatOptions, type JsonFormatResult, type JsonFormatStyle, type JsonObject, type JsonParser, type JsonPrimitive, type JsonRootKind, type JsonTextSize, type JsonValue, detectJson, formatJsonText, isJsonArray, isJsonObject, isJsonPrimitive, stringifyJson };
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Canonical JSON value types + narrowing guards.
3
+ *
4
+ * Ported (the subset this subpath needs) from matrx-frontend `types/json.ts` —
5
+ * the honest names for "this is just JSON" that are NOT `any` and NOT a bare
6
+ * `unknown`. The package must stand alone, so the types live here; a Matrx
7
+ * host keeps using its own `@/types/json` for app code and the two are
8
+ * structurally identical.
9
+ */
10
+ type JsonPrimitive = string | number | boolean | null;
11
+ /**
12
+ * A JSON object. Values are `JsonValue | undefined` so optional keys read
13
+ * cleanly (mirrors Supabase's original generated `Json` object member).
14
+ */
15
+ interface JsonObject {
16
+ [key: string]: JsonValue | undefined;
17
+ }
18
+ type JsonArray = JsonValue[];
19
+ type JsonValue = JsonPrimitive | JsonObject | JsonArray;
20
+ /**
21
+ * Narrow an `unknown` (e.g. a bare JSONB column) to a `JsonObject`.
22
+ * Plain object only — arrays and `null` return false.
23
+ */
24
+ declare function isJsonObject(value: unknown): value is JsonObject;
25
+ /** Narrow an `unknown` to a `JsonArray`. */
26
+ declare function isJsonArray(value: unknown): value is JsonArray;
27
+ /** Narrow an `unknown` to a JSON primitive (string | number | boolean | null). */
28
+ declare function isJsonPrimitive(value: unknown): value is JsonPrimitive;
29
+
30
+ /**
31
+ * How the JSON is laid out.
32
+ *
33
+ * - `minify` — one line, zero optional whitespace. The smallest legal form.
34
+ * - `compact` — width-aware: any subtree that fits within `width` is inlined,
35
+ * and sibling entries that fit are packed onto shared lines.
36
+ * Readable AND small; this is the "scrunch it down" default.
37
+ * - `pretty` — classic one-entry-per-line indentation.
38
+ */
39
+ type JsonFormatStyle = "minify" | "compact" | "pretty";
40
+ /** What to do with the markdown code fence around the JSON. */
41
+ type JsonFenceMode =
42
+ /** Keep the fence exactly as it arrived (and add none if there was none). */
43
+ "preserve"
44
+ /** Remove the fence, leaving bare JSON. */
45
+ | "strip"
46
+ /** Ensure a ```json fence, adding one if the source was bare. */
47
+ | "add";
48
+ /** A markdown code fence wrapping the JSON payload. */
49
+ interface JsonFence {
50
+ /** The opening marker as written, e.g. "```" or "~~~~". */
51
+ marker: string;
52
+ /** Info string after the marker, e.g. "json" (empty when the fence was bare). */
53
+ lang: string;
54
+ /** Whitespace the opening fence line was indented by. */
55
+ indent: string;
56
+ /** False when the source ran out before a closing fence (unterminated). */
57
+ closed: boolean;
58
+ }
59
+ /** Which JSON container sits at the root of the payload. */
60
+ type JsonRootKind = "object" | "array" | "scalar";
61
+ /** How permissively the payload had to be parsed. */
62
+ type JsonParser =
63
+ /** Valid JSON — `JSON.parse` accepted it verbatim. */
64
+ "strict"
65
+ /** Only JSON5 accepted it: trailing commas, comments, unquoted keys, … */
66
+ | "tolerant";
67
+ interface JsonDetection {
68
+ /** The payload parsed (strictly or tolerantly) into a value. */
69
+ ok: boolean;
70
+ /**
71
+ * The text is JSON-SHAPED even if it did not parse — it opens with `{`/`[`
72
+ * and closes with the matching bracket, or it arrived in a ```json fence.
73
+ * This is the gate for OFFERING json actions; `ok` is the gate for running
74
+ * them.
75
+ */
76
+ looksLikeJson: boolean;
77
+ /** The parsed value. Present only when `ok`. */
78
+ value?: JsonValue | undefined;
79
+ parser?: JsonParser | undefined;
80
+ /** Human-readable parse failure. Present only when `!ok`. */
81
+ error?: string | undefined;
82
+ /** The fence that was stripped before parsing, when the source had one. */
83
+ fence: JsonFence | null;
84
+ /** Text before the payload (fence excluded) — preserved verbatim on format. */
85
+ leading: string;
86
+ /** Text after the payload (fence excluded) — preserved verbatim on format. */
87
+ trailing: string;
88
+ /** The JSON text itself: fence and surrounding whitespace removed. */
89
+ payload: string;
90
+ root?: JsonRootKind | undefined;
91
+ /** Lines the payload currently occupies. */
92
+ lineCount: number;
93
+ /** Characters the payload currently occupies. */
94
+ charCount: number;
95
+ }
96
+ interface JsonFormatOptions {
97
+ style: JsonFormatStyle;
98
+ /** Spaces per indent level for `compact` / `pretty`. Default 2. */
99
+ indent?: number | undefined;
100
+ /** Target line width for `compact`. Default 100. Ignored otherwise. */
101
+ width?: number | undefined;
102
+ /** Sort object keys alphabetically at every depth. Default false. */
103
+ sortKeys?: boolean | undefined;
104
+ /** Fence handling. Default "preserve". */
105
+ fence?: JsonFenceMode | undefined;
106
+ }
107
+ /** Size of a chunk of text, for before/after reporting. */
108
+ interface JsonTextSize {
109
+ lines: number;
110
+ chars: number;
111
+ }
112
+ interface JsonFormatResult {
113
+ /** False when the text could not be parsed; `text` is then the input, unchanged. */
114
+ ok: boolean;
115
+ /** The re-formatted text (full input: leading + fence + payload + trailing). */
116
+ text: string;
117
+ error?: string | undefined;
118
+ /** True when `text` differs from the input. */
119
+ changed: boolean;
120
+ detection: JsonDetection;
121
+ before: JsonTextSize;
122
+ after: JsonTextSize;
123
+ }
124
+
125
+ /**
126
+ * Detect JSON in `text`. Never throws; a non-JSON string comes back with
127
+ * `ok: false` and `looksLikeJson: false`, which is the signal to offer nothing.
128
+ */
129
+ declare function detectJson(text: string): JsonDetection;
130
+
131
+ declare const DEFAULT_JSON_INDENT = 2;
132
+ declare const DEFAULT_JSON_WIDTH = 100;
133
+ /**
134
+ * Serialize a JSON value in one of the three styles. This is the entry point
135
+ * for callers that already HAVE a value (a DB JSONB blob, an API frame) and
136
+ * just want it laid out; text callers want {@link formatJsonText}.
137
+ */
138
+ declare function stringifyJson(value: JsonValue, options: JsonFormatOptions): string;
139
+ /**
140
+ * Format the JSON found in `text`, preserving everything around it.
141
+ *
142
+ * Never throws. When the text does not parse, the result is `ok: false`,
143
+ * `changed: false`, and `text` is the input verbatim — a formatter that
144
+ * mangles text it did not understand is a data-loss bug.
145
+ */
146
+ declare function formatJsonText(text: string, options: JsonFormatOptions): JsonFormatResult;
147
+
148
+ export { DEFAULT_JSON_INDENT, DEFAULT_JSON_WIDTH, type JsonArray, type JsonDetection, type JsonFence, type JsonFenceMode, type JsonFormatOptions, type JsonFormatResult, type JsonFormatStyle, type JsonObject, type JsonParser, type JsonPrimitive, type JsonRootKind, type JsonTextSize, type JsonValue, detectJson, formatJsonText, isJsonArray, isJsonObject, isJsonPrimitive, stringifyJson };
@@ -0,0 +1,286 @@
1
+ // src/json-format/detect.ts
2
+ import JSON5 from "json5";
3
+ var FENCE_OPEN = /^([ \t]*)(`{3,}|~{3,})[ \t]*([^\s`~]*)[ \t]*$/;
4
+ var JSON_FENCE_LANGS = /* @__PURE__ */ new Set(["json", "jsonc", "json5", "geojson", "jsonl"]);
5
+ function splitFence(text) {
6
+ const lines = text.split("\n");
7
+ const openIdx = lines.findIndex((l) => FENCE_OPEN.test(l));
8
+ if (openIdx === -1) return null;
9
+ const open = FENCE_OPEN.exec(lines[openIdx] ?? "");
10
+ if (!open) return null;
11
+ const [, indent = "", marker = "```", lang = ""] = open;
12
+ const fenceChar = marker[0] ?? "`";
13
+ const closeRe = new RegExp(`^[ \\t]*\\${fenceChar}{${marker.length},}[ \\t]*$`);
14
+ let closeIdx = -1;
15
+ for (let i = openIdx + 1; i < lines.length; i++) {
16
+ if (closeRe.test(lines[i] ?? "")) {
17
+ closeIdx = i;
18
+ break;
19
+ }
20
+ }
21
+ const afterClose = closeIdx === -1 ? [] : lines.slice(closeIdx + 1);
22
+ if (afterClose.some((l) => FENCE_OPEN.test(l))) return null;
23
+ const bodyEnd = closeIdx === -1 ? lines.length : closeIdx;
24
+ return {
25
+ leading: openIdx > 0 ? `${lines.slice(0, openIdx).join("\n")}
26
+ ` : "",
27
+ payload: lines.slice(openIdx + 1, bodyEnd).join("\n"),
28
+ trailing: afterClose.length > 0 ? `
29
+ ${afterClose.join("\n")}` : "",
30
+ fence: {
31
+ marker,
32
+ lang: lang.toLowerCase(),
33
+ indent,
34
+ closed: closeIdx !== -1
35
+ }
36
+ };
37
+ }
38
+ function splitBare(text) {
39
+ const payload = text.trim();
40
+ if (payload === "") {
41
+ return { leading: text, payload: "", trailing: "", fence: null };
42
+ }
43
+ const start = text.indexOf(payload);
44
+ return {
45
+ leading: text.slice(0, start),
46
+ payload,
47
+ trailing: text.slice(start + payload.length),
48
+ fence: null
49
+ };
50
+ }
51
+ function rootKindOf(value) {
52
+ if (Array.isArray(value)) return "array";
53
+ if (typeof value === "object" && value !== null) return "object";
54
+ return "scalar";
55
+ }
56
+ function isBracketShaped(payload) {
57
+ const first = payload[0];
58
+ const last = payload[payload.length - 1];
59
+ if (payload.length < 2) return false;
60
+ return first === "{" && last === "}" || first === "[" && last === "]";
61
+ }
62
+ function errorMessage(err) {
63
+ return err instanceof Error ? err.message : "Invalid JSON";
64
+ }
65
+ function countLines(s) {
66
+ if (s === "") return 0;
67
+ let n = 1;
68
+ for (let i = 0; i < s.length; i++) if (s[i] === "\n") n++;
69
+ return n;
70
+ }
71
+ function detectJson(text) {
72
+ const split = splitFence(text) ?? splitBare(text);
73
+ const payload = split.fence ? split.payload.trim() : split.payload;
74
+ const fenceSaysJson = split.fence !== null && (split.fence.lang === "" || JSON_FENCE_LANGS.has(split.fence.lang));
75
+ const base = {
76
+ fence: split.fence,
77
+ leading: split.leading,
78
+ trailing: split.trailing,
79
+ payload,
80
+ lineCount: countLines(payload),
81
+ charCount: payload.length
82
+ };
83
+ if (payload === "") {
84
+ return { ...base, ok: false, looksLikeJson: false };
85
+ }
86
+ if (split.fence !== null && !fenceSaysJson) {
87
+ return { ...base, ok: false, looksLikeJson: false };
88
+ }
89
+ const shaped = isBracketShaped(payload);
90
+ let value;
91
+ let parser;
92
+ let error;
93
+ try {
94
+ value = JSON.parse(payload);
95
+ parser = "strict";
96
+ } catch (strictErr) {
97
+ try {
98
+ value = JSON5.parse(payload);
99
+ parser = "tolerant";
100
+ } catch {
101
+ error = errorMessage(strictErr);
102
+ }
103
+ }
104
+ if (value === void 0 || parser === void 0) {
105
+ return { ...base, ok: false, looksLikeJson: shaped, error };
106
+ }
107
+ const root = rootKindOf(value);
108
+ const worthOffering = root !== "scalar" || fenceSaysJson;
109
+ return { ...base, ok: true, looksLikeJson: worthOffering, value, parser, root };
110
+ }
111
+
112
+ // src/json-format/json-value.ts
113
+ function isJsonObject(value) {
114
+ return typeof value === "object" && value !== null && !Array.isArray(value);
115
+ }
116
+ function isJsonArray(value) {
117
+ return Array.isArray(value);
118
+ }
119
+ function isJsonPrimitive(value) {
120
+ return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
121
+ }
122
+
123
+ // src/json-format/format.ts
124
+ var DEFAULT_JSON_INDENT = 2;
125
+ var DEFAULT_JSON_WIDTH = 100;
126
+ function orderedKeys(obj, sortKeys) {
127
+ const keys = Object.keys(obj).filter((k) => obj[k] !== void 0);
128
+ return sortKeys ? [...keys].sort((a, b) => a.localeCompare(b)) : keys;
129
+ }
130
+ function writeScalar(value) {
131
+ return JSON.stringify(value) ?? "null";
132
+ }
133
+ function flatten(value, cfg) {
134
+ if (isJsonArray(value)) {
135
+ if (value.length === 0) return "[]";
136
+ const parts = value.map((v) => flatten(v ?? null, cfg));
137
+ return cfg.spaced ? `[${parts.join(", ")}]` : `[${parts.join(",")}]`;
138
+ }
139
+ if (isJsonObject(value)) {
140
+ const keys = orderedKeys(value, cfg.sortKeys);
141
+ if (keys.length === 0) return "{}";
142
+ const colon = cfg.spaced ? ": " : ":";
143
+ const parts = keys.map(
144
+ (k) => `${JSON.stringify(k)}${colon}${flatten(value[k] ?? null, cfg)}`
145
+ );
146
+ return cfg.spaced ? `{ ${parts.join(", ")} }` : `{${parts.join(",")}}`;
147
+ }
148
+ return writeScalar(value);
149
+ }
150
+ function layoutEntries(entries, pad, cfg) {
151
+ if (!cfg.pack) return entries.map((e) => pad + e);
152
+ const lines = [];
153
+ let current = "";
154
+ for (let i = 0; i < entries.length; i++) {
155
+ const entry = entries[i] ?? "";
156
+ const isLast = i === entries.length - 1;
157
+ const piece = isLast ? entry : `${entry},`;
158
+ if (entry.includes("\n")) {
159
+ if (current !== "") {
160
+ lines.push(pad + current);
161
+ current = "";
162
+ }
163
+ lines.push(pad + piece);
164
+ continue;
165
+ }
166
+ if (current === "") {
167
+ current = piece;
168
+ continue;
169
+ }
170
+ const merged = `${current} ${piece}`;
171
+ if (pad.length + merged.length <= cfg.width) {
172
+ current = merged;
173
+ } else {
174
+ lines.push(pad + current);
175
+ current = piece;
176
+ }
177
+ }
178
+ if (current !== "") lines.push(pad + current);
179
+ return lines;
180
+ }
181
+ function renderNode(value, level, used, cfg) {
182
+ const isContainer = isJsonArray(value) || isJsonObject(value);
183
+ if (!isContainer) return writeScalar(value);
184
+ const flat = flatten(value, cfg);
185
+ if (flat === "[]" || flat === "{}") return flat;
186
+ if (cfg.width >= 0 && used + flat.length <= cfg.width) return flat;
187
+ const pad = " ".repeat((level + 1) * cfg.indent);
188
+ const closePad = " ".repeat(level * cfg.indent);
189
+ if (isJsonArray(value)) {
190
+ const entries2 = value.map(
191
+ (v) => renderNode(v ?? null, level + 1, pad.length, cfg)
192
+ );
193
+ const body2 = layoutEntries(entries2, pad, cfg);
194
+ const joined2 = cfg.pack ? body2.join("\n") : body2.join(",\n");
195
+ return `[
196
+ ${joined2}
197
+ ${closePad}]`;
198
+ }
199
+ const keys = orderedKeys(value, cfg.sortKeys);
200
+ const entries = keys.map((k) => {
201
+ const prefix = `${JSON.stringify(k)}: `;
202
+ const rendered = renderNode(
203
+ value[k] ?? null,
204
+ level + 1,
205
+ pad.length + prefix.length,
206
+ cfg
207
+ );
208
+ return prefix + rendered;
209
+ });
210
+ const body = layoutEntries(entries, pad, cfg);
211
+ const joined = cfg.pack ? body.join("\n") : body.join(",\n");
212
+ return `{
213
+ ${joined}
214
+ ${closePad}}`;
215
+ }
216
+ function stringifyJson(value, options) {
217
+ const indent = options.indent ?? DEFAULT_JSON_INDENT;
218
+ const sortKeys = options.sortKeys ?? false;
219
+ if (options.style === "minify") {
220
+ return flatten(value, { indent, width: -1, pack: false, spaced: false, sortKeys });
221
+ }
222
+ const cfg = {
223
+ indent,
224
+ width: options.style === "pretty" ? -1 : options.width ?? DEFAULT_JSON_WIDTH,
225
+ pack: options.style === "compact",
226
+ spaced: true,
227
+ sortKeys
228
+ };
229
+ return renderNode(value, 0, 0, cfg);
230
+ }
231
+ function sizeOf(text) {
232
+ let lines = text === "" ? 0 : 1;
233
+ for (let i = 0; i < text.length; i++) if (text[i] === "\n") lines++;
234
+ return { lines, chars: text.length };
235
+ }
236
+ function reassemble(detection, payload, mode) {
237
+ const { fence, leading, trailing } = detection;
238
+ const keepFence = mode === "add" || mode === "preserve" && fence !== null;
239
+ if (!keepFence) {
240
+ return leading + payload + trailing;
241
+ }
242
+ const marker = fence?.marker ?? "```";
243
+ const lang = fence?.lang && fence.lang !== "" ? fence.lang : "json";
244
+ const indent = fence?.indent ?? "";
245
+ const body = indent ? payload.split("\n").map((l) => l === "" ? l : indent + l).join("\n") : payload;
246
+ const close = fence !== null && !fence.closed ? "" : `
247
+ ${indent}${marker}`;
248
+ return `${leading}${indent}${marker}${lang}
249
+ ${body}${close}${trailing}`;
250
+ }
251
+ function formatJsonText(text, options) {
252
+ const detection = detectJson(text);
253
+ const before = sizeOf(text);
254
+ if (!detection.ok || detection.value === void 0) {
255
+ return {
256
+ ok: false,
257
+ text,
258
+ error: detection.error ?? "Selection is not JSON.",
259
+ changed: false,
260
+ detection,
261
+ before,
262
+ after: before
263
+ };
264
+ }
265
+ const payload = stringifyJson(detection.value, options);
266
+ const next = reassemble(detection, payload, options.fence ?? "preserve");
267
+ return {
268
+ ok: true,
269
+ text: next,
270
+ changed: next !== text,
271
+ detection,
272
+ before,
273
+ after: sizeOf(next)
274
+ };
275
+ }
276
+ export {
277
+ DEFAULT_JSON_INDENT,
278
+ DEFAULT_JSON_WIDTH,
279
+ detectJson,
280
+ formatJsonText,
281
+ isJsonArray,
282
+ isJsonObject,
283
+ isJsonPrimitive,
284
+ stringifyJson
285
+ };
286
+ //# sourceMappingURL=json-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/json-format/detect.ts","../src/json-format/json-value.ts","../src/json-format/format.ts"],"sourcesContent":["// json-format/detect.ts\n//\n// \"Is this text JSON, and where exactly does the JSON start and stop?\"\n//\n// The answer has to survive real-world selections: a fenced ```json block, a\n// bare pasted object, an object with a stray blank line above it, a fence the\n// user only half-selected. So detection splits the text into three parts —\n// leading / payload / trailing — and only the payload is ever re-formatted.\n// Everything outside it is restored verbatim, because a formatter that eats\n// the prose around the JSON is worse than no formatter at all.\n//\n// Two parse tiers: `JSON.parse` first (strict — what the value really is), then\n// JSON5 (tolerant — trailing commas, comments, unquoted keys, single quotes),\n// because the JSON people paste out of logs and code is frequently not legal\n// JSON. Tolerant parsing is reported, never hidden: a consumer that re-emits a\n// tolerantly-parsed value is normalizing it, and the caller can say so.\n//\n// Pure: no React / DOM. Never throws.\n//\n// Ported verbatim from matrx-frontend `lib/json-format/detect.ts`.\n\nimport JSON5 from \"json5\";\nimport type { JsonValue } from \"./json-value\";\nimport type {\n JsonDetection,\n JsonFence,\n JsonParser,\n JsonRootKind,\n} from \"./types\";\n\n/** Opening fence line: optional indent, 3+ backticks or tildes, optional info. */\nconst FENCE_OPEN = /^([ \\t]*)(`{3,}|~{3,})[ \\t]*([^\\s`~]*)[ \\t]*$/;\n\n/** Languages we treat as \"this fence contains JSON\". */\nconst JSON_FENCE_LANGS = new Set([\"json\", \"jsonc\", \"json5\", \"geojson\", \"jsonl\"]);\n\ninterface Split {\n leading: string;\n payload: string;\n trailing: string;\n fence: JsonFence | null;\n}\n\n/** Peel a markdown code fence off the text, if the text IS a fenced block. */\nfunction splitFence(text: string): Split | null {\n const lines = text.split(\"\\n\");\n\n // The fence may sit anywhere in the selection (a user highlighting a block\n // plus the sentence above it is the common case) — but there must be exactly\n // ONE block. Two fenced blocks in one selection is not a single JSON payload,\n // and spanning them would splice unrelated content together.\n const openIdx = lines.findIndex((l) => FENCE_OPEN.test(l));\n if (openIdx === -1) return null;\n\n const open = FENCE_OPEN.exec(lines[openIdx] ?? \"\");\n if (!open) return null;\n const [, indent = \"\", marker = \"```\", lang = \"\"] = open;\n const fenceChar = marker[0] ?? \"`\";\n const closeRe = new RegExp(`^[ \\\\t]*\\\\${fenceChar}{${marker.length},}[ \\\\t]*$`);\n\n let closeIdx = -1;\n for (let i = openIdx + 1; i < lines.length; i++) {\n if (closeRe.test(lines[i] ?? \"\")) {\n closeIdx = i;\n break;\n }\n }\n\n const afterClose = closeIdx === -1 ? [] : lines.slice(closeIdx + 1);\n if (afterClose.some((l) => FENCE_OPEN.test(l))) return null;\n\n const bodyEnd = closeIdx === -1 ? lines.length : closeIdx;\n // The line separators bordering the fence belong to leading/trailing, so\n // reassembly is a plain concatenation and blank lines survive it.\n return {\n leading: openIdx > 0 ? `${lines.slice(0, openIdx).join(\"\\n\")}\\n` : \"\",\n payload: lines.slice(openIdx + 1, bodyEnd).join(\"\\n\"),\n trailing: afterClose.length > 0 ? `\\n${afterClose.join(\"\\n\")}` : \"\",\n fence: {\n marker,\n lang: lang.toLowerCase(),\n indent,\n closed: closeIdx !== -1,\n },\n };\n}\n\n/** Split bare (unfenced) text into surrounding whitespace + payload. */\nfunction splitBare(text: string): Split {\n const payload = text.trim();\n if (payload === \"\") {\n return { leading: text, payload: \"\", trailing: \"\", fence: null };\n }\n const start = text.indexOf(payload);\n return {\n leading: text.slice(0, start),\n payload,\n trailing: text.slice(start + payload.length),\n fence: null,\n };\n}\n\nfunction rootKindOf(value: JsonValue): JsonRootKind {\n if (Array.isArray(value)) return \"array\";\n if (typeof value === \"object\" && value !== null) return \"object\";\n return \"scalar\";\n}\n\n/** Bracket-shaped: opens and closes with a matching container delimiter. */\nfunction isBracketShaped(payload: string): boolean {\n const first = payload[0];\n const last = payload[payload.length - 1];\n if (payload.length < 2) return false;\n return (first === \"{\" && last === \"}\") || (first === \"[\" && last === \"]\");\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : \"Invalid JSON\";\n}\n\nfunction countLines(s: string): number {\n if (s === \"\") return 0;\n let n = 1;\n for (let i = 0; i < s.length; i++) if (s[i] === \"\\n\") n++;\n return n;\n}\n\n/**\n * Detect JSON in `text`. Never throws; a non-JSON string comes back with\n * `ok: false` and `looksLikeJson: false`, which is the signal to offer nothing.\n */\nexport function detectJson(text: string): JsonDetection {\n const split = splitFence(text) ?? splitBare(text);\n // A fenced block's body still carries its own indentation/blank lines.\n const payload = split.fence ? split.payload.trim() : split.payload;\n\n const fenceSaysJson =\n split.fence !== null &&\n (split.fence.lang === \"\" || JSON_FENCE_LANGS.has(split.fence.lang));\n\n const base = {\n fence: split.fence,\n leading: split.leading,\n trailing: split.trailing,\n payload,\n lineCount: countLines(payload),\n charCount: payload.length,\n };\n\n if (payload === \"\") {\n return { ...base, ok: false, looksLikeJson: false };\n }\n\n // A fence declaring a NON-JSON language is a hard no, even if the body would\n // parse — reformatting the inside of a ```python block is not our business.\n if (split.fence !== null && !fenceSaysJson) {\n return { ...base, ok: false, looksLikeJson: false };\n }\n\n const shaped = isBracketShaped(payload);\n\n let value: JsonValue | undefined;\n let parser: JsonParser | undefined;\n let error: string | undefined;\n try {\n value = JSON.parse(payload) as JsonValue;\n parser = \"strict\";\n } catch (strictErr) {\n try {\n value = JSON5.parse(payload) as JsonValue;\n parser = \"tolerant\";\n } catch {\n error = errorMessage(strictErr);\n }\n }\n\n if (value === undefined || parser === undefined) {\n // Unparseable. Still \"looks like JSON\" when it is bracket-shaped, so a\n // surface can show the actions and report the parse error on click rather\n // than pretending the selection is ordinary prose.\n return { ...base, ok: false, looksLikeJson: shaped, error };\n }\n\n const root = rootKindOf(value);\n // A bare scalar (\"hello\", 42, true) parses but is not worth offering JSON\n // actions on — every prose word that happens to be a number would qualify.\n const worthOffering = root !== \"scalar\" || fenceSaysJson;\n\n return { ...base, ok: true, looksLikeJson: worthOffering, value, parser, root };\n}\n","/**\n * Canonical JSON value types + narrowing guards.\n *\n * Ported (the subset this subpath needs) from matrx-frontend `types/json.ts` —\n * the honest names for \"this is just JSON\" that are NOT `any` and NOT a bare\n * `unknown`. The package must stand alone, so the types live here; a Matrx\n * host keeps using its own `@/types/json` for app code and the two are\n * structurally identical.\n */\n\nexport type JsonPrimitive = string | number | boolean | null;\n\n/**\n * A JSON object. Values are `JsonValue | undefined` so optional keys read\n * cleanly (mirrors Supabase's original generated `Json` object member).\n */\nexport interface JsonObject {\n [key: string]: JsonValue | undefined;\n}\n\nexport type JsonArray = JsonValue[];\n\nexport type JsonValue = JsonPrimitive | JsonObject | JsonArray;\n\n/**\n * Narrow an `unknown` (e.g. a bare JSONB column) to a `JsonObject`.\n * Plain object only — arrays and `null` return false.\n */\nexport function isJsonObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Narrow an `unknown` to a `JsonArray`. */\nexport function isJsonArray(value: unknown): value is JsonArray {\n return Array.isArray(value);\n}\n\n/** Narrow an `unknown` to a JSON primitive (string | number | boolean | null). */\nexport function isJsonPrimitive(value: unknown): value is JsonPrimitive {\n return (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n );\n}\n","// json-format/format.ts\n//\n// The JSON writer. Three styles over one recursive printer:\n//\n// minify — one line, no optional whitespace.\n// compact — width-aware FILL. Any subtree whose flat form fits the remaining\n// columns is inlined; a subtree that does not fit expands, but its\n// children are then PACKED onto shared lines while they fit. This\n// is what turns an 11-line reference blob into 3 lines without\n// turning it into an unreadable one-liner.\n// pretty — one entry per line (classic 2-space JSON).\n//\n// Why not `JSON.stringify(v, null, 2)`: it cannot inline, cannot pack, and\n// cannot sort keys. All three are the point.\n//\n// Pure: no React / DOM. Never throws — a parse failure comes back as a result\n// with `ok: false` and the input text unchanged.\n//\n// Ported verbatim from matrx-frontend `lib/json-format/format.ts`.\n\nimport type { JsonObject, JsonValue } from \"./json-value\";\nimport { isJsonArray, isJsonObject } from \"./json-value\";\nimport { detectJson } from \"./detect\";\nimport type {\n JsonDetection,\n JsonFormatOptions,\n JsonFormatResult,\n JsonTextSize,\n} from \"./types\";\n\nexport const DEFAULT_JSON_INDENT = 2;\nexport const DEFAULT_JSON_WIDTH = 100;\n\ninterface WriterConfig {\n indent: number;\n /** Target line width; `-1` disables inlining entirely (pretty). */\n width: number;\n /** Pack sibling entries onto shared lines (compact only). */\n pack: boolean;\n /** Spaces inside braces/brackets and after colons/commas. */\n spaced: boolean;\n sortKeys: boolean;\n}\n\nfunction orderedKeys(obj: JsonObject, sortKeys: boolean): string[] {\n // `undefined` values are not JSON — JSON.stringify drops them, so do we.\n const keys = Object.keys(obj).filter((k) => obj[k] !== undefined);\n return sortKeys ? [...keys].sort((a, b) => a.localeCompare(b)) : keys;\n}\n\n/** Serialize a scalar exactly as JSON does. */\nfunction writeScalar(value: JsonValue): string {\n // NaN / Infinity stringify to \"null\", matching JSON.stringify.\n return JSON.stringify(value) ?? \"null\";\n}\n\n/** The whole subtree on one line. */\nfunction flatten(value: JsonValue, cfg: WriterConfig): string {\n if (isJsonArray(value)) {\n if (value.length === 0) return \"[]\";\n const parts = value.map((v) => flatten(v ?? null, cfg));\n return cfg.spaced ? `[${parts.join(\", \")}]` : `[${parts.join(\",\")}]`;\n }\n if (isJsonObject(value)) {\n const keys = orderedKeys(value, cfg.sortKeys);\n if (keys.length === 0) return \"{}\";\n const colon = cfg.spaced ? \": \" : \":\";\n const parts = keys.map(\n (k) => `${JSON.stringify(k)}${colon}${flatten(value[k] ?? null, cfg)}`,\n );\n return cfg.spaced ? `{ ${parts.join(\", \")} }` : `{${parts.join(\",\")}}`;\n }\n return writeScalar(value);\n}\n\n/**\n * Lay out `entries` (already-rendered child texts) inside a container.\n * Single-line entries are packed together while they fit; a multi-line entry\n * always occupies its own line(s). Returns the body lines, unindented-prefixed\n * with `pad` already applied.\n */\nfunction layoutEntries(\n entries: string[],\n pad: string,\n cfg: WriterConfig,\n): string[] {\n if (!cfg.pack) return entries.map((e) => pad + e);\n\n const lines: string[] = [];\n let current = \"\";\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i] ?? \"\";\n const isLast = i === entries.length - 1;\n const piece = isLast ? entry : `${entry},`;\n\n if (entry.includes(\"\\n\")) {\n // Multi-line child: flush whatever is buffered, then stand alone.\n if (current !== \"\") {\n lines.push(pad + current);\n current = \"\";\n }\n lines.push(pad + piece);\n continue;\n }\n\n if (current === \"\") {\n current = piece;\n continue;\n }\n const merged = `${current} ${piece}`;\n if (pad.length + merged.length <= cfg.width) {\n current = merged;\n } else {\n lines.push(pad + current);\n current = piece;\n }\n }\n if (current !== \"\") lines.push(pad + current);\n return lines;\n}\n\n/**\n * Render `value` starting at column `used` on its current line, at nesting\n * `level`. `used` includes the indentation AND any key prefix already written,\n * so the width budget is honest about `\"items\": [` style prefixes.\n */\nfunction renderNode(\n value: JsonValue,\n level: number,\n used: number,\n cfg: WriterConfig,\n): string {\n const isContainer = isJsonArray(value) || isJsonObject(value);\n if (!isContainer) return writeScalar(value);\n\n const flat = flatten(value, cfg);\n if (flat === \"[]\" || flat === \"{}\") return flat;\n if (cfg.width >= 0 && used + flat.length <= cfg.width) return flat;\n\n const pad = \" \".repeat((level + 1) * cfg.indent);\n const closePad = \" \".repeat(level * cfg.indent);\n\n if (isJsonArray(value)) {\n const entries = value.map((v) =>\n renderNode(v ?? null, level + 1, pad.length, cfg),\n );\n const body = layoutEntries(entries, pad, cfg);\n const joined = cfg.pack ? body.join(\"\\n\") : body.join(\",\\n\");\n return `[\\n${joined}\\n${closePad}]`;\n }\n\n const keys = orderedKeys(value, cfg.sortKeys);\n const entries = keys.map((k) => {\n const prefix = `${JSON.stringify(k)}: `;\n const rendered = renderNode(\n value[k] ?? null,\n level + 1,\n pad.length + prefix.length,\n cfg,\n );\n return prefix + rendered;\n });\n const body = layoutEntries(entries, pad, cfg);\n const joined = cfg.pack ? body.join(\"\\n\") : body.join(\",\\n\");\n return `{\\n${joined}\\n${closePad}}`;\n}\n\n/**\n * Serialize a JSON value in one of the three styles. This is the entry point\n * for callers that already HAVE a value (a DB JSONB blob, an API frame) and\n * just want it laid out; text callers want {@link formatJsonText}.\n */\nexport function stringifyJson(\n value: JsonValue,\n options: JsonFormatOptions,\n): string {\n const indent = options.indent ?? DEFAULT_JSON_INDENT;\n const sortKeys = options.sortKeys ?? false;\n\n if (options.style === \"minify\") {\n return flatten(value, { indent, width: -1, pack: false, spaced: false, sortKeys });\n }\n\n const cfg: WriterConfig = {\n indent,\n width: options.style === \"pretty\" ? -1 : (options.width ?? DEFAULT_JSON_WIDTH),\n pack: options.style === \"compact\",\n spaced: true,\n sortKeys,\n };\n return renderNode(value, 0, 0, cfg);\n}\n\nfunction sizeOf(text: string): JsonTextSize {\n let lines = text === \"\" ? 0 : 1;\n for (let i = 0; i < text.length; i++) if (text[i] === \"\\n\") lines++;\n return { lines, chars: text.length };\n}\n\n/** Re-assemble the full text: leading + fence + formatted payload + trailing. */\nfunction reassemble(\n detection: JsonDetection,\n payload: string,\n mode: NonNullable<JsonFormatOptions[\"fence\"]>,\n): string {\n const { fence, leading, trailing } = detection;\n\n const keepFence =\n mode === \"add\" || (mode === \"preserve\" && fence !== null);\n if (!keepFence) {\n return leading + payload + trailing;\n }\n\n const marker = fence?.marker ?? \"```\";\n const lang = fence?.lang && fence.lang !== \"\" ? fence.lang : \"json\";\n const indent = fence?.indent ?? \"\";\n const body = indent\n ? payload\n .split(\"\\n\")\n .map((l) => (l === \"\" ? l : indent + l))\n .join(\"\\n\")\n : payload;\n\n // An unterminated source fence stays unterminated — inventing a closing fence\n // would change the surrounding document's structure, not just this block's.\n const close = fence !== null && !fence.closed ? \"\" : `\\n${indent}${marker}`;\n return `${leading}${indent}${marker}${lang}\\n${body}${close}${trailing}`;\n}\n\n/**\n * Format the JSON found in `text`, preserving everything around it.\n *\n * Never throws. When the text does not parse, the result is `ok: false`,\n * `changed: false`, and `text` is the input verbatim — a formatter that\n * mangles text it did not understand is a data-loss bug.\n */\nexport function formatJsonText(\n text: string,\n options: JsonFormatOptions,\n): JsonFormatResult {\n const detection = detectJson(text);\n const before = sizeOf(text);\n\n if (!detection.ok || detection.value === undefined) {\n return {\n ok: false,\n text,\n error: detection.error ?? \"Selection is not JSON.\",\n changed: false,\n detection,\n before,\n after: before,\n };\n }\n\n const payload = stringifyJson(detection.value, options);\n const next = reassemble(detection, payload, options.fence ?? \"preserve\");\n\n return {\n ok: true,\n text: next,\n changed: next !== text,\n detection,\n before,\n after: sizeOf(next),\n };\n}\n"],"mappings":";AAqBA,OAAO,WAAW;AAUlB,IAAM,aAAa;AAGnB,IAAM,mBAAmB,oBAAI,IAAI,CAAC,QAAQ,SAAS,SAAS,WAAW,OAAO,CAAC;AAU/E,SAAS,WAAW,MAA4B;AAC9C,QAAM,QAAQ,KAAK,MAAM,IAAI;AAM7B,QAAM,UAAU,MAAM,UAAU,CAAC,MAAM,WAAW,KAAK,CAAC,CAAC;AACzD,MAAI,YAAY,GAAI,QAAO;AAE3B,QAAM,OAAO,WAAW,KAAK,MAAM,OAAO,KAAK,EAAE;AACjD,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,CAAC,EAAE,SAAS,IAAI,SAAS,OAAO,OAAO,EAAE,IAAI;AACnD,QAAM,YAAY,OAAO,CAAC,KAAK;AAC/B,QAAM,UAAU,IAAI,OAAO,aAAa,SAAS,IAAI,OAAO,MAAM,YAAY;AAE9E,MAAI,WAAW;AACf,WAAS,IAAI,UAAU,GAAG,IAAI,MAAM,QAAQ,KAAK;AAC/C,QAAI,QAAQ,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG;AAChC,iBAAW;AACX;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,aAAa,KAAK,CAAC,IAAI,MAAM,MAAM,WAAW,CAAC;AAClE,MAAI,WAAW,KAAK,CAAC,MAAM,WAAW,KAAK,CAAC,CAAC,EAAG,QAAO;AAEvD,QAAM,UAAU,aAAa,KAAK,MAAM,SAAS;AAGjD,SAAO;AAAA,IACL,SAAS,UAAU,IAAI,GAAG,MAAM,MAAM,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IAAO;AAAA,IACnE,SAAS,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,KAAK,IAAI;AAAA,IACpD,UAAU,WAAW,SAAS,IAAI;AAAA,EAAK,WAAW,KAAK,IAAI,CAAC,KAAK;AAAA,IACjE,OAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,YAAY;AAAA,MACvB;AAAA,MACA,QAAQ,aAAa;AAAA,IACvB;AAAA,EACF;AACF;AAGA,SAAS,UAAU,MAAqB;AACtC,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,YAAY,IAAI;AAClB,WAAO,EAAE,SAAS,MAAM,SAAS,IAAI,UAAU,IAAI,OAAO,KAAK;AAAA,EACjE;AACA,QAAM,QAAQ,KAAK,QAAQ,OAAO;AAClC,SAAO;AAAA,IACL,SAAS,KAAK,MAAM,GAAG,KAAK;AAAA,IAC5B;AAAA,IACA,UAAU,KAAK,MAAM,QAAQ,QAAQ,MAAM;AAAA,IAC3C,OAAO;AAAA,EACT;AACF;AAEA,SAAS,WAAW,OAAgC;AAClD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,SAAO;AACT;AAGA,SAAS,gBAAgB,SAA0B;AACjD,QAAM,QAAQ,QAAQ,CAAC;AACvB,QAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,MAAI,QAAQ,SAAS,EAAG,QAAO;AAC/B,SAAQ,UAAU,OAAO,SAAS,OAAS,UAAU,OAAO,SAAS;AACvE;AAEA,SAAS,aAAa,KAAsB;AAC1C,SAAO,eAAe,QAAQ,IAAI,UAAU;AAC9C;AAEA,SAAS,WAAW,GAAmB;AACrC,MAAI,MAAM,GAAI,QAAO;AACrB,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,IAAK,KAAI,EAAE,CAAC,MAAM,KAAM;AACtD,SAAO;AACT;AAMO,SAAS,WAAW,MAA6B;AACtD,QAAM,QAAQ,WAAW,IAAI,KAAK,UAAU,IAAI;AAEhD,QAAM,UAAU,MAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,MAAM;AAE3D,QAAM,gBACJ,MAAM,UAAU,SACf,MAAM,MAAM,SAAS,MAAM,iBAAiB,IAAI,MAAM,MAAM,IAAI;AAEnE,QAAM,OAAO;AAAA,IACX,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf,UAAU,MAAM;AAAA,IAChB;AAAA,IACA,WAAW,WAAW,OAAO;AAAA,IAC7B,WAAW,QAAQ;AAAA,EACrB;AAEA,MAAI,YAAY,IAAI;AAClB,WAAO,EAAE,GAAG,MAAM,IAAI,OAAO,eAAe,MAAM;AAAA,EACpD;AAIA,MAAI,MAAM,UAAU,QAAQ,CAAC,eAAe;AAC1C,WAAO,EAAE,GAAG,MAAM,IAAI,OAAO,eAAe,MAAM;AAAA,EACpD;AAEA,QAAM,SAAS,gBAAgB,OAAO;AAEtC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAM,OAAO;AAC1B,aAAS;AAAA,EACX,SAAS,WAAW;AAClB,QAAI;AACF,cAAQ,MAAM,MAAM,OAAO;AAC3B,eAAS;AAAA,IACX,QAAQ;AACN,cAAQ,aAAa,SAAS;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,UAAU,UAAa,WAAW,QAAW;AAI/C,WAAO,EAAE,GAAG,MAAM,IAAI,OAAO,eAAe,QAAQ,MAAM;AAAA,EAC5D;AAEA,QAAM,OAAO,WAAW,KAAK;AAG7B,QAAM,gBAAgB,SAAS,YAAY;AAE3C,SAAO,EAAE,GAAG,MAAM,IAAI,MAAM,eAAe,eAAe,OAAO,QAAQ,KAAK;AAChF;;;ACjKO,SAAS,aAAa,OAAqC;AAChE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAGO,SAAS,YAAY,OAAoC;AAC9D,SAAO,MAAM,QAAQ,KAAK;AAC5B;AAGO,SAAS,gBAAgB,OAAwC;AACtE,SACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU;AAErB;;;ACfO,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAalC,SAAS,YAAY,KAAiB,UAA6B;AAEjE,QAAM,OAAO,OAAO,KAAK,GAAG,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,MAAS;AAChE,SAAO,WAAW,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC,IAAI;AACnE;AAGA,SAAS,YAAY,OAA0B;AAE7C,SAAO,KAAK,UAAU,KAAK,KAAK;AAClC;AAGA,SAAS,QAAQ,OAAkB,KAA2B;AAC5D,MAAI,YAAY,KAAK,GAAG;AACtB,QAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,UAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,GAAG,CAAC;AACtD,WAAO,IAAI,SAAS,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,EACnE;AACA,MAAI,aAAa,KAAK,GAAG;AACvB,UAAM,OAAO,YAAY,OAAO,IAAI,QAAQ;AAC5C,QAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,UAAM,QAAQ,IAAI,SAAS,OAAO;AAClC,UAAM,QAAQ,KAAK;AAAA,MACjB,CAAC,MAAM,GAAG,KAAK,UAAU,CAAC,CAAC,GAAG,KAAK,GAAG,QAAQ,MAAM,CAAC,KAAK,MAAM,GAAG,CAAC;AAAA,IACtE;AACA,WAAO,IAAI,SAAS,KAAK,MAAM,KAAK,IAAI,CAAC,OAAO,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,EACrE;AACA,SAAO,YAAY,KAAK;AAC1B;AAQA,SAAS,cACP,SACA,KACA,KACU;AACV,MAAI,CAAC,IAAI,KAAM,QAAO,QAAQ,IAAI,CAAC,MAAM,MAAM,CAAC;AAEhD,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,QAAQ,QAAQ,CAAC,KAAK;AAC5B,UAAM,SAAS,MAAM,QAAQ,SAAS;AACtC,UAAM,QAAQ,SAAS,QAAQ,GAAG,KAAK;AAEvC,QAAI,MAAM,SAAS,IAAI,GAAG;AAExB,UAAI,YAAY,IAAI;AAClB,cAAM,KAAK,MAAM,OAAO;AACxB,kBAAU;AAAA,MACZ;AACA,YAAM,KAAK,MAAM,KAAK;AACtB;AAAA,IACF;AAEA,QAAI,YAAY,IAAI;AAClB,gBAAU;AACV;AAAA,IACF;AACA,UAAM,SAAS,GAAG,OAAO,IAAI,KAAK;AAClC,QAAI,IAAI,SAAS,OAAO,UAAU,IAAI,OAAO;AAC3C,gBAAU;AAAA,IACZ,OAAO;AACL,YAAM,KAAK,MAAM,OAAO;AACxB,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,MAAI,YAAY,GAAI,OAAM,KAAK,MAAM,OAAO;AAC5C,SAAO;AACT;AAOA,SAAS,WACP,OACA,OACA,MACA,KACQ;AACR,QAAM,cAAc,YAAY,KAAK,KAAK,aAAa,KAAK;AAC5D,MAAI,CAAC,YAAa,QAAO,YAAY,KAAK;AAE1C,QAAM,OAAO,QAAQ,OAAO,GAAG;AAC/B,MAAI,SAAS,QAAQ,SAAS,KAAM,QAAO;AAC3C,MAAI,IAAI,SAAS,KAAK,OAAO,KAAK,UAAU,IAAI,MAAO,QAAO;AAE9D,QAAM,MAAM,IAAI,QAAQ,QAAQ,KAAK,IAAI,MAAM;AAC/C,QAAM,WAAW,IAAI,OAAO,QAAQ,IAAI,MAAM;AAE9C,MAAI,YAAY,KAAK,GAAG;AACtB,UAAMA,WAAU,MAAM;AAAA,MAAI,CAAC,MACzB,WAAW,KAAK,MAAM,QAAQ,GAAG,IAAI,QAAQ,GAAG;AAAA,IAClD;AACA,UAAMC,QAAO,cAAcD,UAAS,KAAK,GAAG;AAC5C,UAAME,UAAS,IAAI,OAAOD,MAAK,KAAK,IAAI,IAAIA,MAAK,KAAK,KAAK;AAC3D,WAAO;AAAA,EAAMC,OAAM;AAAA,EAAK,QAAQ;AAAA,EAClC;AAEA,QAAM,OAAO,YAAY,OAAO,IAAI,QAAQ;AAC5C,QAAM,UAAU,KAAK,IAAI,CAAC,MAAM;AAC9B,UAAM,SAAS,GAAG,KAAK,UAAU,CAAC,CAAC;AACnC,UAAM,WAAW;AAAA,MACf,MAAM,CAAC,KAAK;AAAA,MACZ,QAAQ;AAAA,MACR,IAAI,SAAS,OAAO;AAAA,MACpB;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB,CAAC;AACD,QAAM,OAAO,cAAc,SAAS,KAAK,GAAG;AAC5C,QAAM,SAAS,IAAI,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK;AAC3D,SAAO;AAAA,EAAM,MAAM;AAAA,EAAK,QAAQ;AAClC;AAOO,SAAS,cACd,OACA,SACQ;AACR,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,WAAW,QAAQ,YAAY;AAErC,MAAI,QAAQ,UAAU,UAAU;AAC9B,WAAO,QAAQ,OAAO,EAAE,QAAQ,OAAO,IAAI,MAAM,OAAO,QAAQ,OAAO,SAAS,CAAC;AAAA,EACnF;AAEA,QAAM,MAAoB;AAAA,IACxB;AAAA,IACA,OAAO,QAAQ,UAAU,WAAW,KAAM,QAAQ,SAAS;AAAA,IAC3D,MAAM,QAAQ,UAAU;AAAA,IACxB,QAAQ;AAAA,IACR;AAAA,EACF;AACA,SAAO,WAAW,OAAO,GAAG,GAAG,GAAG;AACpC;AAEA,SAAS,OAAO,MAA4B;AAC1C,MAAI,QAAQ,SAAS,KAAK,IAAI;AAC9B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,IAAK,KAAI,KAAK,CAAC,MAAM,KAAM;AAC5D,SAAO,EAAE,OAAO,OAAO,KAAK,OAAO;AACrC;AAGA,SAAS,WACP,WACA,SACA,MACQ;AACR,QAAM,EAAE,OAAO,SAAS,SAAS,IAAI;AAErC,QAAM,YACJ,SAAS,SAAU,SAAS,cAAc,UAAU;AACtD,MAAI,CAAC,WAAW;AACd,WAAO,UAAU,UAAU;AAAA,EAC7B;AAEA,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,OAAO,OAAO,QAAQ,MAAM,SAAS,KAAK,MAAM,OAAO;AAC7D,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,OAAO,SACT,QACG,MAAM,IAAI,EACV,IAAI,CAAC,MAAO,MAAM,KAAK,IAAI,SAAS,CAAE,EACtC,KAAK,IAAI,IACZ;AAIJ,QAAM,QAAQ,UAAU,QAAQ,CAAC,MAAM,SAAS,KAAK;AAAA,EAAK,MAAM,GAAG,MAAM;AACzE,SAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;AAAA,EAAK,IAAI,GAAG,KAAK,GAAG,QAAQ;AACxE;AASO,SAAS,eACd,MACA,SACkB;AAClB,QAAM,YAAY,WAAW,IAAI;AACjC,QAAM,SAAS,OAAO,IAAI;AAE1B,MAAI,CAAC,UAAU,MAAM,UAAU,UAAU,QAAW;AAClD,WAAO;AAAA,MACL,IAAI;AAAA,MACJ;AAAA,MACA,OAAO,UAAU,SAAS;AAAA,MAC1B,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,UAAU,cAAc,UAAU,OAAO,OAAO;AACtD,QAAM,OAAO,WAAW,WAAW,SAAS,QAAQ,SAAS,UAAU;AAEvE,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS,SAAS;AAAA,IAClB;AAAA,IACA;AAAA,IACA,OAAO,OAAO,IAAI;AAAA,EACpB;AACF;","names":["entries","body","joined"]}
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/latest-request.ts
23
+ var latest_request_exports = {};
24
+ __export(latest_request_exports, {
25
+ useLatestRequest: () => useLatestRequest
26
+ });
27
+ module.exports = __toCommonJS(latest_request_exports);
28
+ var import_react = require("react");
29
+ function useLatestRequest() {
30
+ const seqRef = (0, import_react.useRef)(0);
31
+ return (0, import_react.useCallback)(() => {
32
+ const mySeq = ++seqRef.current;
33
+ return () => mySeq === seqRef.current;
34
+ }, []);
35
+ }
36
+ //# sourceMappingURL=latest-request.cjs.map