opencode-rules-md 0.6.6 → 0.8.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 (47) hide show
  1. package/README.md +13 -3
  2. package/dist/src/active-rules-state.js +1 -1
  3. package/dist/src/active-rules-state.js.map +1 -1
  4. package/dist/src/rule-discovery.d.ts +1 -1
  5. package/dist/src/rule-discovery.d.ts.map +1 -1
  6. package/dist/src/rule-discovery.js +2 -2
  7. package/dist/src/rule-discovery.js.map +1 -1
  8. package/dist/tui/data/rules.d.ts +1 -1
  9. package/dist/tui/data/rules.d.ts.map +1 -1
  10. package/dist/tui/data/rules.js +2 -2
  11. package/dist/tui/data/rules.js.map +1 -1
  12. package/dist/tui/index.js +1 -1
  13. package/dist/tui/index.js.map +1 -1
  14. package/dist/tui/slots/sidebar-content.js +1 -1
  15. package/dist/tui/slots/sidebar-content.js.map +1 -1
  16. package/package.json +24 -11
  17. package/src/active-rules-state.ts +1 -1
  18. package/src/rule-discovery.ts +2 -2
  19. package/tui/data/rules.ts +3 -3
  20. package/tui/index.tsx +1 -1
  21. package/tui/slots/sidebar-content.tsx +1 -1
  22. package/dist/cli.mjs +0 -454
  23. package/dist/src/cli/config.d.ts +0 -74
  24. package/dist/src/cli/config.d.ts.map +0 -1
  25. package/dist/src/cli/config.js +0 -292
  26. package/dist/src/cli/config.js.map +0 -1
  27. package/dist/src/cli/install.d.ts +0 -33
  28. package/dist/src/cli/install.d.ts.map +0 -1
  29. package/dist/src/cli/install.js +0 -99
  30. package/dist/src/cli/install.js.map +0 -1
  31. package/dist/src/cli/main.d.ts +0 -19
  32. package/dist/src/cli/main.d.ts.map +0 -1
  33. package/dist/src/cli/main.js +0 -149
  34. package/dist/src/cli/main.js.map +0 -1
  35. package/dist/src/cli/real-fs.d.ts +0 -26
  36. package/dist/src/cli/real-fs.d.ts.map +0 -1
  37. package/dist/src/cli/real-fs.js +0 -42
  38. package/dist/src/cli/real-fs.js.map +0 -1
  39. package/dist/src/cli/status.d.ts +0 -34
  40. package/dist/src/cli/status.d.ts.map +0 -1
  41. package/dist/src/cli/status.js +0 -67
  42. package/dist/src/cli/status.js.map +0 -1
  43. package/src/cli/config.ts +0 -364
  44. package/src/cli/install.ts +0 -171
  45. package/src/cli/main.ts +0 -178
  46. package/src/cli/real-fs.ts +0 -65
  47. package/src/cli/status.ts +0 -99
package/dist/cli.mjs DELETED
@@ -1,454 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/cli/main.ts
4
- import { parseArgs } from "node:util";
5
- import { pathToFileURL } from "node:url";
6
- import { realpathSync } from "node:fs";
7
-
8
- // src/cli/config.ts
9
- import * as os from "node:os";
10
- import * as path from "node:path";
11
- var SERVER_CONFIG_FILENAME = "opencode.json";
12
- var TUI_CONFIG_FILENAME = "tui.json";
13
- function stripJsoncComments(content) {
14
- let result = "";
15
- let i = 0;
16
- let inString = false;
17
- let escaped = false;
18
- const len = content.length;
19
- while (i < len) {
20
- const char = content[i];
21
- if (inString) {
22
- result += char;
23
- if (escaped) {
24
- escaped = false;
25
- } else if (char === "\\") {
26
- escaped = true;
27
- } else if (char === '"') {
28
- inString = false;
29
- }
30
- i++;
31
- continue;
32
- }
33
- if (char === '"') {
34
- inString = true;
35
- result += char;
36
- i++;
37
- continue;
38
- }
39
- if (char === "/" && content[i + 1] === "/") {
40
- i += 2;
41
- while (i < len && content[i] !== `
42
- `)
43
- i++;
44
- continue;
45
- }
46
- if (char === "/" && content[i + 1] === "*") {
47
- i += 2;
48
- while (i < len && !(content[i] === "*" && content[i + 1] === "/"))
49
- i++;
50
- if (i < len)
51
- i += 2;
52
- continue;
53
- }
54
- result += char;
55
- i++;
56
- }
57
- let out = "";
58
- let inStr = false;
59
- let esc = false;
60
- let j = 0;
61
- const outLen = result.length;
62
- while (j < outLen) {
63
- const ch = result[j];
64
- if (inStr) {
65
- out += ch;
66
- if (esc) {
67
- esc = false;
68
- } else if (ch === "\\") {
69
- esc = true;
70
- } else if (ch === '"') {
71
- inStr = false;
72
- }
73
- j++;
74
- continue;
75
- }
76
- if (ch === '"') {
77
- inStr = true;
78
- out += ch;
79
- j++;
80
- continue;
81
- }
82
- if (ch === ",") {
83
- let k = j + 1;
84
- while (k < outLen && /\s/.test(result[k]))
85
- k++;
86
- if (k < outLen && /[}\]]/.test(result[k])) {
87
- j = k;
88
- continue;
89
- }
90
- }
91
- out += ch;
92
- j++;
93
- }
94
- return out;
95
- }
96
- function resolveGlobalConfigPath(fs, opts = {}) {
97
- const dir = resolveConfigDir();
98
- if (opts.ensureDir && !fs.existsSync(dir)) {
99
- fs.mkdirSync(dir, { recursive: true });
100
- }
101
- const filename = opts.filename ?? SERVER_CONFIG_FILENAME;
102
- return path.join(dir, filename);
103
- }
104
- function resolveConfigDir() {
105
- if (process.env.OPENCODE_CONFIG_DIR) {
106
- return process.env.OPENCODE_CONFIG_DIR;
107
- }
108
- if (process.env.XDG_CONFIG_HOME) {
109
- return path.join(process.env.XDG_CONFIG_HOME, "opencode");
110
- }
111
- const home = process.env.HOME || os.homedir();
112
- if (home) {
113
- return path.join(home, ".config", "opencode");
114
- }
115
- const appdata = process.env.APPDATA;
116
- if (appdata) {
117
- return path.join(appdata, "opencode");
118
- }
119
- throw new Error("Cannot resolve config dir: none of OPENCODE_CONFIG_DIR, XDG_CONFIG_HOME, HOME, or APPDATA is set");
120
- }
121
- function loadGlobalConfig(fs, opts = {}) {
122
- const configPath = resolveGlobalConfigPath(fs, opts.filename ? { filename: opts.filename } : {});
123
- if (!fs.existsSync(configPath)) {
124
- return { path: configPath, existed: false, config: {} };
125
- }
126
- try {
127
- const raw = fs.readFileSync(configPath);
128
- const stripped = stripJsoncComments(raw);
129
- if (stripped.trim() === "") {
130
- return { path: configPath, existed: true, config: {} };
131
- }
132
- const parsed = JSON.parse(stripped);
133
- return { path: configPath, existed: true, config: parsed };
134
- } catch (err) {
135
- const error = err instanceof Error ? err : new Error(String(err));
136
- return { path: configPath, existed: true, config: {}, parseError: error };
137
- }
138
- }
139
- function normalizePlugin(config) {
140
- const raw = Array.isArray(config["plugin"]) ? config["plugin"] : [];
141
- const seen = new Map;
142
- const result = [];
143
- for (const item of raw) {
144
- if (typeof item !== "string")
145
- continue;
146
- const prefix = getPluginPrefix(item);
147
- seen.set(prefix, result.length);
148
- result.push(item);
149
- }
150
- return collapseByPrefix(result, seen);
151
- }
152
- function removePlugin(config, prefix) {
153
- if (!Array.isArray(config["plugin"]))
154
- return;
155
- const raw = config["plugin"];
156
- config["plugin"] = raw.filter((item) => typeof item === "string" && !item.startsWith(prefix));
157
- }
158
- function addPlugin(config, specifier) {
159
- if (!Array.isArray(config["plugin"])) {
160
- config["plugin"] = [];
161
- }
162
- const plugin = config["plugin"];
163
- const prefix = getPluginPrefix(specifier);
164
- const removed = plugin.filter((p) => getPluginPrefix(p) !== prefix);
165
- removed.push(specifier);
166
- config["plugin"] = removed;
167
- }
168
- function rotateBackups(fs, configPath, _pluginName) {
169
- if (!fs.existsSync(configPath)) {
170
- return null;
171
- }
172
- const dir = path.dirname(configPath);
173
- const base = path.basename(configPath);
174
- const timestamp = Date.now();
175
- const newBak = path.join(dir, `${base}.bak.${timestamp}`);
176
- fs.copyFileSync(configPath, newBak);
177
- const entries = fs.readdirSync(dir);
178
- const bakFiles = entries.filter((e) => e.startsWith(base + ".bak.")).sort();
179
- while (bakFiles.length > 3) {
180
- const oldest = bakFiles.shift();
181
- fs.unlinkSync(path.join(dir, oldest));
182
- }
183
- return newBak;
184
- }
185
- function writeAtomically(fs, configPath, content) {
186
- const dir = path.dirname(configPath);
187
- const base = path.basename(configPath);
188
- const tmpPath = path.join(dir, `.${base}.tmp.${Date.now()}-${process.pid}`);
189
- fs.writeFileSync(tmpPath, content, "utf-8");
190
- fs.renameSync(tmpPath, configPath);
191
- }
192
- function getPluginPrefix(specifier) {
193
- const atIdx = specifier.indexOf("@");
194
- return atIdx === -1 ? specifier : specifier.substring(0, atIdx);
195
- }
196
- function collapseByPrefix(plugins, lastSeen) {
197
- const keptIndices = new Set([...lastSeen.values()]);
198
- return plugins.filter((_, idx) => keptIndices.has(idx));
199
- }
200
-
201
- // src/cli/real-fs.ts
202
- import * as fs from "node:fs";
203
- import * as nodePath from "node:path";
204
- var realFs = {
205
- readFileSync(filePath) {
206
- return fs.readFileSync(filePath, "utf-8");
207
- },
208
- writeFileSync(filePath, content, _encoding) {
209
- const dir = nodePath.dirname(filePath);
210
- if (!fs.existsSync(dir)) {
211
- fs.mkdirSync(dir, { recursive: true });
212
- }
213
- fs.writeFileSync(filePath, content, "utf-8");
214
- },
215
- renameSync(from, to) {
216
- fs.renameSync(from, to);
217
- },
218
- copyFileSync(from, to) {
219
- fs.copyFileSync(from, to);
220
- },
221
- unlinkSync(filePath) {
222
- fs.unlinkSync(filePath);
223
- },
224
- mkdirSync(filePath, opts) {
225
- fs.mkdirSync(filePath, opts);
226
- },
227
- readdirSync(filePath) {
228
- return fs.readdirSync(filePath);
229
- },
230
- existsSync(filePath) {
231
- return fs.existsSync(filePath);
232
- }
233
- };
234
-
235
- // src/cli/install.ts
236
- function runInstall(opts, fs2 = realFs) {
237
- const specifier = buildSpecifier(opts.version);
238
- const server = updateConfig(specifier, opts.dryRun ?? false, fs2);
239
- const tui = updateConfig(specifier, opts.dryRun ?? false, fs2, {
240
- filename: TUI_CONFIG_FILENAME
241
- });
242
- const aggregate = server.status === "wrote" || tui.status === "wrote" ? "wrote" : server.status === "planned" || tui.status === "planned" ? "planned" : "noop";
243
- printSummary(aggregate, specifier, server, tui);
244
- return { status: aggregate, specifier, server, tui };
245
- }
246
- function updateConfig(specifier, dryRun, fs2, opts = {}) {
247
- const loadResult = loadGlobalConfig(fs2, opts.filename ? { filename: opts.filename } : {});
248
- if (loadResult.parseError) {
249
- const filename = opts.filename ?? "opencode.json";
250
- const err = new Error(`opencode-rules-md: ${filename} is malformed — aborting to avoid data loss.
251
- ` + ` path: ${loadResult.path}
252
- ` + ` error: ${loadResult.parseError.message}`);
253
- err.configPath = loadResult.path;
254
- throw err;
255
- }
256
- const configPath = loadResult.path;
257
- const config = loadResult.config;
258
- config["plugin"] = normalizePlugin(config);
259
- const existing = config["plugin"] ?? [];
260
- if (existing.includes(specifier)) {
261
- return { status: "noop", path: configPath, specifier };
262
- }
263
- removePlugin(config, "opencode-rules-md");
264
- addPlugin(config, specifier);
265
- if (dryRun) {
266
- const planned = JSON.stringify(config, null, 2);
267
- console.log(`Planned ${configPath}:
268
- ${planned}`);
269
- return { status: "planned", path: configPath, specifier };
270
- }
271
- const backup = rotateBackups(fs2, configPath, "opencode-rules-md");
272
- const serialized = JSON.stringify(config, null, 2);
273
- writeAtomically(fs2, configPath, serialized);
274
- const result = { status: "wrote", path: configPath, specifier };
275
- if (backup)
276
- result.backup = backup;
277
- return result;
278
- }
279
- function buildSpecifier(version) {
280
- return version ? `opencode-rules-md@${version}` : "opencode-rules-md";
281
- }
282
- function printSummary(status, specifier, server, tui) {
283
- if (status === "noop") {
284
- console.log(`Already installed (${specifier})`);
285
- console.log(` server config: ${server.path}`);
286
- console.log(` tui config: ${tui.path}`);
287
- return;
288
- }
289
- if (status === "planned") {
290
- console.log("Dry run complete — no files written.");
291
- return;
292
- }
293
- console.log(`Installed ${specifier}`);
294
- console.log(` server config: ${server.path}`);
295
- if (server.backup)
296
- console.log(` backup: ${server.backup}`);
297
- console.log(` tui config: ${tui.path}`);
298
- if (tui.backup)
299
- console.log(` backup: ${tui.backup}`);
300
- }
301
-
302
- // src/cli/status.ts
303
- import * as fs2 from "node:fs";
304
- import * as path2 from "node:path";
305
- function runStatus(cliFs = realFs) {
306
- const serverLoad = loadGlobalConfig(cliFs);
307
- const tuiLoad = loadGlobalConfig(cliFs, { filename: TUI_CONFIG_FILENAME });
308
- const serverSpecifier = findSpecifier(serverLoad);
309
- const tuiSpecifier = findSpecifier(tuiLoad);
310
- const installed = serverSpecifier !== undefined && tuiSpecifier !== undefined;
311
- const result = {
312
- installed,
313
- serverPath: serverLoad.path,
314
- tuiPath: tuiLoad.path,
315
- serverExisted: serverLoad.existed,
316
- tuiExisted: tuiLoad.existed,
317
- version: getVersion()
318
- };
319
- if (serverSpecifier)
320
- result.serverSpecifier = serverSpecifier;
321
- if (tuiSpecifier)
322
- result.tuiSpecifier = tuiSpecifier;
323
- const parseError = serverLoad.parseError ?? tuiLoad.parseError;
324
- if (parseError)
325
- result.parseError = parseError;
326
- return result;
327
- }
328
- function findSpecifier(load) {
329
- if (load.parseError)
330
- return;
331
- const config = load.config;
332
- const pluginList = Array.isArray(config["plugin"]) ? config["plugin"] : [];
333
- return pluginList.find((p) => p.startsWith("opencode-rules-md"));
334
- }
335
- function getVersion() {
336
- try {
337
- const pkgPath = path2.resolve(process.cwd(), "package.json");
338
- const content = fs2.readFileSync(pkgPath, "utf-8");
339
- const pkg = JSON.parse(content);
340
- return pkg.version ?? "unknown";
341
- } catch {
342
- return "unknown";
343
- }
344
- }
345
-
346
- // src/cli/main.ts
347
- var HELP_TEXT = `opencode-rules-md CLI
348
-
349
- Usage: opencode-rules-md <command> [options]
350
-
351
- Commands:
352
- install Add opencode-rules-md to the global opencode + tui configs
353
- status Report whether opencode-rules-md is installed
354
-
355
- Options:
356
- --version <v> Specify a plugin version to install
357
- --latest Install the latest version (default)
358
- --dry-run Show what would be written, without changing files
359
- --yes Skip confirmation prompts (future use)
360
- -h, --help Show this help text
361
- `.trim();
362
- var USAGE_ERROR_TEXT = `Error: unknown command. Run 'opencode-rules-md --help' for usage.`.trim();
363
- function parseCliArgs(argv) {
364
- const { positionals, values } = parseArgs({
365
- args: argv,
366
- allowPositionals: true,
367
- options: {
368
- version: { type: "string" },
369
- latest: { type: "boolean" },
370
- "dry-run": { type: "boolean" },
371
- yes: { type: "boolean" },
372
- h: { type: "boolean" },
373
- help: { type: "boolean" }
374
- }
375
- });
376
- const command = positionals[0] ?? null;
377
- const options = {
378
- ...values.version !== undefined && { version: values.version },
379
- ...values.latest && { latest: true },
380
- ...values["dry-run"] && { dryRun: true },
381
- ...values.yes && { yes: true },
382
- ...(values.help || values.h) && { help: true }
383
- };
384
- const unknownFlags = [];
385
- return { command, options, unknownFlags };
386
- }
387
- async function runMain(argv, fs3 = realFs) {
388
- try {
389
- const { command, options, unknownFlags } = parseCliArgs(argv);
390
- if (options.help) {
391
- console.log(HELP_TEXT);
392
- return 0;
393
- }
394
- if (unknownFlags.length > 0) {
395
- console.error(`Error: unknown option(s): ${unknownFlags.join(", ")}`);
396
- console.error(USAGE_ERROR_TEXT);
397
- return 2;
398
- }
399
- if (!command) {
400
- console.error(USAGE_ERROR_TEXT);
401
- return 2;
402
- }
403
- switch (command) {
404
- case "install": {
405
- const installOpts = {};
406
- if (options.version !== undefined)
407
- installOpts.version = options.version;
408
- if (options.dryRun)
409
- installOpts.dryRun = true;
410
- runInstall(installOpts, fs3);
411
- return 0;
412
- }
413
- case "status": {
414
- const statusResult = runStatus(fs3);
415
- if (statusResult.installed) {
416
- const spec = statusResult.serverSpecifier ?? statusResult.tuiSpecifier;
417
- console.log(`opencode-rules-md is installed (${spec})`);
418
- } else {
419
- console.log("opencode-rules-md is not installed");
420
- }
421
- return 0;
422
- }
423
- default: {
424
- console.error(`Error: unknown command '${command}'`);
425
- console.error(USAGE_ERROR_TEXT);
426
- return 2;
427
- }
428
- }
429
- } catch (err) {
430
- const message = err instanceof Error ? err.message : String(err);
431
- console.error(`Error: ${message}`);
432
- return 1;
433
- }
434
- }
435
- function isInvokedAsMain() {
436
- if (!process.argv[1])
437
- return false;
438
- try {
439
- const realArgv = pathToFileURL(realpathSync(process.argv[1])).href;
440
- return import.meta.url === realArgv;
441
- } catch {
442
- try {
443
- return import.meta.url === pathToFileURL(process.argv[1]).href;
444
- } catch {
445
- return false;
446
- }
447
- }
448
- }
449
- if (isInvokedAsMain()) {
450
- runMain(process.argv.slice(2)).then((code) => process.exit(code));
451
- }
452
- export {
453
- runMain
454
- };
@@ -1,74 +0,0 @@
1
- /**
2
- * CLI config helpers: discovery, JSONC-safe parsing, plugin normalization,
3
- * backup rotation, and atomic write.
4
- *
5
- * All filesystem access goes through the CliFs interface so tests can inject
6
- * an in-memory implementation without touching real disk.
7
- */
8
- import type { CliFs } from './real-fs.js';
9
- /** npm package name for this plugin. */
10
- export declare const PLUGIN_NAME = "opencode-rules-md";
11
- /** Filename for the OpenCode server config. */
12
- export declare const SERVER_CONFIG_FILENAME = "opencode.json";
13
- /** Filename for the OpenCode TUI config. */
14
- export declare const TUI_CONFIG_FILENAME = "tui.json";
15
- export interface LoadResult {
16
- path: string;
17
- existed: boolean;
18
- config: Record<string, unknown>;
19
- parseError?: Error;
20
- }
21
- /**
22
- * Strip JSONC comments and trailing commas while preserving
23
- * comment-like sequences inside string literals.
24
- *
25
- * Pass 1: strip `//` and `/* * /` comments (string-aware).
26
- * Pass 2: strip trailing commas before `}` or `]`, skipping whitespace.
27
- */
28
- export declare function stripJsoncComments(content: string): string;
29
- /**
30
- * Resolve the global opencode config path using the same precedence as
31
- * opencode itself: OPENCODE_CONFIG_DIR → XDG_CONFIG_HOME → HOME fallback.
32
- *
33
- * On Windows, APPDATA is tried as a last resort when XDG_CONFIG_HOME and
34
- * HOME are both absent.
35
- */
36
- export declare function resolveGlobalConfigPath(fs: CliFs, opts?: {
37
- ensureDir?: boolean;
38
- filename?: string;
39
- }): string;
40
- /**
41
- * Load and parse a global OpenCode config file.
42
- * Treats a missing file as an empty config object (not an error).
43
- * Surfaces parse errors so callers can exit non-zero without corrupting data.
44
- */
45
- export declare function loadGlobalConfig(fs: CliFs, opts?: {
46
- filename?: string;
47
- }): LoadResult;
48
- /**
49
- * Return the plugin array with opencode-rules-md* entries deduplicated by
50
- * name prefix, keeping the last occurrence of each unique prefix.
51
- */
52
- export declare function normalizePlugin(config: Record<string, unknown>): string[];
53
- /**
54
- * Remove all plugins matching the given prefix (used to dedupe before append).
55
- */
56
- export declare function removePlugin(config: Record<string, unknown>, prefix: string): void;
57
- /**
58
- * Add a plugin specifier, removing any existing entry with the same prefix first
59
- * so it ends up at the specified position (default: end). This makes the operation
60
- * idempotent — re-adding the same specifier just moves it to the end.
61
- */
62
- export declare function addPlugin(config: Record<string, unknown>, specifier: string): void;
63
- /**
64
- * Write a timestamped backup of the given config path and rotate so at most
65
- * 3 backups are retained (oldest deleted first).
66
- * Returns the path of the newly created backup, or null if no backup was created.
67
- */
68
- export declare function rotateBackups(fs: CliFs, configPath: string, _pluginName: string): string | null;
69
- /**
70
- * Write content to a temporary sibling file then rename it into place.
71
- * The final path is never in a partially-written state.
72
- */
73
- export declare function writeAtomically(fs: CliFs, configPath: string, content: string): void;
74
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cli/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAM1C,wCAAwC;AACxC,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAE/C,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AAEtD,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAM9C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE,KAAK,CAAC;CACpB;AAMD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgG1D;AAMD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,KAAK,EACT,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,MAAM,CAOR;AA+BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,UAAU,CAuBxF;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,EAAE,CAcV;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,MAAM,GACb,IAAI,CAMN;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,SAAS,EAAE,MAAM,GAChB,IAAI,CAUN;AAMD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyB/F;AAMD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAOpF"}