@netnodeag/kraftwerk 0.65.0 → 0.66.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 (75) hide show
  1. package/README.md +93 -23
  2. package/dist/acp.js +3 -1
  3. package/dist/cli/daemon.d.ts +14 -0
  4. package/dist/cli/daemon.js +60 -0
  5. package/dist/cli/doctor.js +9 -1
  6. package/dist/cli/init.js +1 -0
  7. package/dist/cli/kraftwerk.js +4 -0
  8. package/dist/cli/ui.d.ts +8 -0
  9. package/dist/cli/ui.js +35 -8
  10. package/dist/cli/workspaces.js +5 -3
  11. package/dist/client/index.d.ts +8 -0
  12. package/dist/client/index.js +2 -1
  13. package/dist/client/live.d.ts +1 -2
  14. package/dist/client/live.js +2 -1
  15. package/dist/client/routes.d.ts +3 -0
  16. package/dist/client/routes.js +3 -0
  17. package/dist/config.d.ts +16 -0
  18. package/dist/config.js +23 -1
  19. package/dist/core/chat/pi.js +2 -1
  20. package/dist/core/chat/sessions.d.ts +1 -1
  21. package/dist/core/chat/sessions.js +1 -1
  22. package/dist/core/chat/state.d.ts +2 -0
  23. package/dist/core/chat/state.js +5 -0
  24. package/dist/core/daemon.d.ts +27 -0
  25. package/dist/core/daemon.js +61 -0
  26. package/dist/core/env.d.ts +16 -0
  27. package/dist/core/env.js +45 -0
  28. package/dist/core/git.d.ts +2 -0
  29. package/dist/core/git.js +20 -4
  30. package/dist/core/instances.d.ts +32 -12
  31. package/dist/core/instances.js +136 -64
  32. package/dist/core/routines.d.ts +6 -0
  33. package/dist/core/routines.js +11 -0
  34. package/dist/core/runner.js +7 -3
  35. package/dist/core/vibeables.d.ts +2 -0
  36. package/dist/core/vibeables.js +17 -5
  37. package/dist/core/workspace.d.ts +13 -0
  38. package/dist/core/workspace.js +25 -0
  39. package/dist/server/api/hub.d.ts +25 -0
  40. package/dist/server/api/hub.js +32 -0
  41. package/dist/server/api/index.d.ts +24 -1
  42. package/dist/server/api/index.js +2 -0
  43. package/dist/server/api/socket.d.ts +9 -1
  44. package/dist/server/api/socket.js +27 -7
  45. package/dist/server/api/workspace.d.ts +1 -0
  46. package/dist/server/api/workspace.js +2 -1
  47. package/dist/server/cloud.d.ts +5 -1
  48. package/dist/server/cloud.js +86 -54
  49. package/dist/server/hub-context.d.ts +7 -0
  50. package/dist/server/hub-context.js +18 -0
  51. package/dist/server/live.d.ts +2 -0
  52. package/dist/server/live.js +9 -0
  53. package/dist/server/preview.js +2 -1
  54. package/dist/server/server.d.ts +52 -1
  55. package/dist/server/server.js +249 -52
  56. package/dist/server/target.d.ts +20 -0
  57. package/dist/server/target.js +18 -0
  58. package/package.json +1 -1
  59. package/schema/kraftwerk.schema.json +5 -0
  60. package/web/dist/assets/{dist-CAWmDGJC.js → dist-1bNkaWWA.js} +1 -1
  61. package/web/dist/assets/dist-BU1SOB5S.js +1 -0
  62. package/web/dist/assets/{dist-BCfXUgtf.js → dist-Bk3f-J5U.js} +1 -1
  63. package/web/dist/assets/{dist-DnMgiPT1.js → dist-Bx99Puvv.js} +1 -1
  64. package/web/dist/assets/{dist-v6-49xpW.js → dist-C0M2aITo.js} +1 -1
  65. package/web/dist/assets/{dist-C-CclD1E.js → dist-C0z19Zge.js} +1 -1
  66. package/web/dist/assets/{dist-nA7q2-h7.js → dist-COEgBKG6.js} +1 -1
  67. package/web/dist/assets/{dist-Bnxg6V5L.js → dist-CYRrdlae.js} +1 -1
  68. package/web/dist/assets/{dist-hevbMnoj.js → dist-CbEFnSCD.js} +1 -1
  69. package/web/dist/assets/{dist-DS1R2xKJ.js → dist-DCYVKU-H.js} +1 -1
  70. package/web/dist/assets/{dist-10uPVFvu.js → dist-XyTHWtoN.js} +1 -1
  71. package/web/dist/assets/{editor-C8yy8YS9.js → editor-DPcGvSPy.js} +3 -3
  72. package/web/dist/assets/index-DKLJdwYE.js +229 -0
  73. package/web/dist/index.html +1 -1
  74. package/web/dist/assets/dist-yoh47aAL.js +0 -1
  75. package/web/dist/assets/index-DWS1u71Y.js +0 -229
@@ -2,13 +2,16 @@ import { promises as fs } from "node:fs";
2
2
  import http from "node:http";
3
3
  import path from "node:path";
4
4
  import { setDefaultWorkspace, Workspace } from "../core/workspace.js";
5
- import { cloudGoodbye, startCloudSync, stopCloudSync } from "./cloud.js";
6
- import { disposeAllBackends } from "../core/chat/sessions.js";
5
+ import { cloudGoodbye, cloudGoodbyeAll, startCloudSync, stopCloudSync } from "./cloud.js";
6
+ import { disposeAllBackends, disposeWorkspaceBackends } from "../core/chat/sessions.js";
7
7
  import { markWorkspaceStopped, registerInstance, registerWorkspace, unregisterInstance } from "../core/instances.js";
8
- import { startGitSync } from "../core/git.js";
9
- import { disposeAllDevs } from "../core/vibeables.js";
8
+ import { startGitSync, stopGitSync } from "../core/git.js";
9
+ import { disposeAllDevs, disposeWorkspaceDevs } from "../core/vibeables.js";
10
10
  import { proxyUpgrade, serveVibeable } from "./preview.js";
11
- import { startRoutineScheduler } from "../core/routines.js";
11
+ import { startRoutineScheduler, stopRoutineScheduler } from "../core/routines.js";
12
+ import { readWorkspaceDotenv } from "../core/env.js";
13
+ import { closeWatches } from "./live.js";
14
+ import { MACHINE_PATHS, runInHub } from "./hub-context.js";
12
15
  import { apiRouter } from "./api/index.js";
13
16
  import { serveSocket } from "./api/socket.js";
14
17
  import { acceptWebSocket } from "./ws.js";
@@ -16,6 +19,8 @@ import { json } from "./api/router.js";
16
19
  import { MIME } from "./api/mime.js";
17
20
  import { getPkgVersion, RESTART_EXIT_CODE } from "./version.js";
18
21
  import { trustOf } from "./trust.js";
22
+ import { targetOf } from "./target.js";
23
+ import { isDir, resolveWorkspace, workspaceSlug } from "../config.js";
19
24
  export { RESTART_EXIT_CODE };
20
25
  import { IN_CONTAINER, INSPECTOR_HOST, LOOPBACK_BIND, LOOPBACK_NAMES } from "./bind.js";
21
26
  /**
@@ -120,93 +125,285 @@ async function serveStatic(res, staticDir, pathname) {
120
125
  const TRUST_NETWORK = IN_CONTAINER || process.env.KRAFTWERK_UI_TRUST_NETWORK === "1";
121
126
  /** Every request pairs, this machine's too — behind a local reverse proxy that does not send X-Forwarded-* headers. */
122
127
  const REQUIRE_PAIRING = process.env.KRAFTWERK_UI_REQUIRE_PAIRING === "1";
123
- /** Start the server; resolves once it listens. Runs until the process ends. */
124
- export async function startInspector(opts) {
125
- // Every request, timer and listener below runs in this workspace (see workspace.ts).
126
- const ws = setDefaultWorkspace(new Workspace({ outputDir: opts.outputDir, root: opts.root }));
127
- const trustOpts = { trustLoopback: opts.trustLoopback !== false && !REQUIRE_PAIRING, trustNetwork: TRUST_NETWORK };
128
- ws.run(() => {
129
- startRoutineScheduler();
130
- startGitSync();
128
+ const hubs = new Set();
129
+ let exitHandlers = false;
130
+ /** Every hub of this process lets go of its workspaces — on SIGINT/SIGTERM and exit (sync parts only there). */
131
+ function installExitHandlers() {
132
+ if (exitHandlers)
133
+ return;
134
+ exitHandlers = true;
135
+ // Something still running for a workspace that was closed (a late callback) finds its state gone and throws
136
+ // "workspace closed". That must not take the other workspaces down with it; anything else still crashes, as by default.
137
+ const closedOnly = (err) => err instanceof Error && err.message === "workspace closed";
138
+ process.on("unhandledRejection", (err) => {
139
+ if (closedOnly(err))
140
+ return;
141
+ throw err;
131
142
  });
132
- // Chat agent subprocesses must die with the server — signals bypass
133
- // "exit" handlers, so hook the signals themselves.
143
+ process.on("uncaughtException", (err) => {
144
+ if (closedOnly(err))
145
+ return;
146
+ console.error(err);
147
+ process.exit(1);
148
+ });
149
+ // Chat agent subprocesses must die with the server — signals bypass "exit" handlers, so hook the signals themselves.
134
150
  for (const sig of ["SIGINT", "SIGTERM"]) {
135
151
  process.once(sig, () => {
136
152
  disposeAllBackends();
137
153
  disposeAllDevs();
138
- unregisterInstance();
154
+ // Stamp first: unregistering forgets which workspaces this process served.
139
155
  markWorkspaceStopped();
140
- // The cloud goodbye is bounded (cloudGoodbye) and a no-op without cloud:, so the exit stays prompt.
141
- void cloudGoodbye().finally(() => process.exit(sig === "SIGINT" ? 130 : 143));
156
+ unregisterInstance();
157
+ // The cloud goodbye is bounded and a no-op without cloud:, so the exit stays prompt.
158
+ void cloudGoodbyeAll().finally(() => process.exit(sig === "SIGINT" ? 130 : 143));
142
159
  });
143
160
  }
144
161
  process.once("exit", (code) => {
145
162
  disposeAllBackends();
146
163
  disposeAllDevs();
147
- unregisterInstance();
148
- // A self-restart (new version) is not a stop — the project stays "running".
164
+ // A self-restart (new version) is not a stop — the workspaces stay "running".
149
165
  if (code !== RESTART_EXIT_CODE)
150
166
  markWorkspaceStopped();
167
+ unregisterInstance();
168
+ });
169
+ }
170
+ const listen = (server, port) => new Promise((resolve, reject) => {
171
+ server.once("error", reject);
172
+ server.listen(port, INSPECTOR_HOST, () => {
173
+ server.off("error", reject);
174
+ const addr = server.address();
175
+ resolve(typeof addr === "object" && addr ? addr.port : port);
151
176
  });
152
- const server = http.createServer((req, res) => ws.run(() => serve(req, res)));
153
- const serve = async (req, res) => {
177
+ });
178
+ /** A small page at a daemon's own address: the open workspaces, each a link. */
179
+ function hubPage(res, open) {
180
+ const esc = (s) => s.replace(/[&<>"]/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" })[c]);
181
+ const rows = open.length
182
+ ? open.map((o) => `<li><a href="${esc(o.url)}/">${esc(o.name)}</a> <code>${esc(o.slug)}</code></li>`).join("")
183
+ : "<li>No workspace is open. Run <code>kraftwerk ui</code> in a workspace folder.</li>";
184
+ res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
185
+ res.end(`<!doctype html><meta charset="utf-8"><title>kraftwerk</title><style>body{font:15px/1.6 system-ui,sans-serif;max-width:640px;margin:48px auto;padding:0 16px;color:#1b1b1f}code{color:#46464f}</style><h1>kraftwerk</h1><ul>${rows}</ul>`);
186
+ }
187
+ export async function startHub(opts) {
188
+ const trustOpts = { trustLoopback: opts.trustLoopback !== false && !REQUIRE_PAIRING, trustNetwork: TRUST_NETWORK };
189
+ const bySlug = new Map();
190
+ const aliasServers = new Map();
191
+ /** The workspace reached without a slug on the hub's own port (standalone: the one it serves). */
192
+ let fallback;
193
+ /** Open sockets and the workspace each was opened for: closing that workspace closes them. */
194
+ const sockets = new Set();
195
+ const version = await getPkgVersion();
196
+ installExitHandlers();
197
+ /** Which open workspace a request is for: its slug, else the port it came in on, else the default. */
198
+ const pick = (target, portDefault) => target.slug !== undefined ? bySlug.get(target.slug) : portDefault;
199
+ const handler = (portDefault) => async (req, res) => {
154
200
  try {
155
- const url = new URL(req.url ?? "/", "http://localhost");
156
201
  if (!hostAllowed(req))
157
202
  return json(res, { error: "unexpected Host header" }, 421);
203
+ const target = targetOf(req, new URL(req.url ?? "/", "http://localhost"));
204
+ const open = pick(target, portDefault());
205
+ if (target.slug !== undefined && !open)
206
+ return json(res, { error: `no workspace "${target.slug}" here` }, 404);
207
+ const { url } = target;
158
208
  const trust = await trustOf(req, url, trustOpts);
209
+ const run = (fn) => runInHub(hub, () => (open ? open.ws.run(fn) : fn()));
159
210
  if (url.pathname.startsWith("/api/")) {
160
211
  const method = req.method ?? "GET";
161
212
  if (method !== "GET" && method !== "HEAD" && !sameOrigin(req))
162
- json(res, { error: "cross-origin request refused" }, 403);
163
- else
164
- await apiRouter.handle(req, res, url, trust);
213
+ return json(res, { error: "cross-origin request refused" }, 403);
214
+ if (!open && !MACHINE_PATHS.test(url.pathname)) {
215
+ return json(res, { error: "name a workspace: <slug>.localhost or /w/<slug>/", workspaces: [...bySlug.keys()] }, 404);
216
+ }
217
+ return await run(() => apiRouter.handle(req, res, url, trust));
165
218
  }
166
219
  // /vibeables/<slug>/… is an app's own files, served for the preview pane — workspace data, so not for unpaired callers.
167
- else if (url.pathname === "/vibeables" || url.pathname.startsWith("/vibeables/")) {
220
+ if (url.pathname === "/vibeables" || url.pathname.startsWith("/vibeables/")) {
168
221
  if (trust.kind === "none")
169
- json(res, { error: "pair this device first", pair: true }, 401);
170
- else
171
- await serveVibeable(req, res, url);
222
+ return json(res, { error: "pair this device first", pair: true }, 401);
223
+ if (!open)
224
+ return json(res, { error: "name a workspace: <slug>.localhost or /w/<slug>/" }, 404);
225
+ return await run(() => serveVibeable(req, res, url));
172
226
  }
173
- // The web UI's shell is public: an unpaired browser needs it to show the pairing screen.
174
- else
175
- await serveStatic(res, opts.staticDir, url.pathname);
227
+ // A daemon's own address lists its workspaces; anywhere else, the web UI's shell (public: an unpaired browser needs it to pair).
228
+ if (!open && (url.pathname === "/" || url.pathname === "/index.html"))
229
+ return hubPage(res, [...bySlug.values()]);
230
+ await serveStatic(res, opts.staticDir, url.pathname);
176
231
  }
177
232
  catch (err) {
178
233
  json(res, { error: err.message }, 500);
179
234
  }
180
235
  };
181
236
  // WebSocket upgrades: the control plane's socket (/api/ws), and a vibeable's dev server (HMR).
182
- server.on("upgrade", (req, socket, head) => {
237
+ const upgrade = (portDefault) => (req, socket, head) => {
183
238
  if (!hostAllowed(req))
184
239
  return void socket.destroy();
185
- ws.run(() => (async () => {
186
- const url = new URL(req.url ?? "/", "http://localhost");
240
+ (async () => {
241
+ const target = targetOf(req, new URL(req.url ?? "/", "http://localhost"));
242
+ const open = pick(target, portDefault());
243
+ if (target.slug !== undefined && !open)
244
+ return void socket.end("HTTP/1.1 404 Not Found\r\nconnection: close\r\n\r\n");
245
+ const { url } = target;
187
246
  const trust = await trustOf(req, url, trustOpts, true);
188
247
  if (trust.kind === "none")
189
248
  return void socket.end("HTTP/1.1 401 Unauthorized\r\nconnection: close\r\n\r\n");
190
- if (url.pathname !== "/api/ws")
191
- return proxyUpgrade(req, socket, head);
249
+ if (url.pathname !== "/api/ws") {
250
+ if (!open)
251
+ return void socket.destroy();
252
+ // The dev server's HMR socket: what it sees is the path without the workspace prefix.
253
+ req.url = url.pathname + url.search;
254
+ return runInHub(hub, () => open.ws.run(() => proxyUpgrade(req, socket, head)));
255
+ }
192
256
  // A socket is not covered by CORS: a page from another site could open one, so the Origin must be ours.
193
257
  if (!sameOrigin(req))
194
258
  return void socket.end("HTTP/1.1 403 Forbidden\r\nconnection: close\r\n\r\n");
195
259
  const conn = acceptWebSocket(req, socket, head);
196
- if (conn)
197
- serveSocket(conn, ws, await getPkgVersion(), trust, () => trustOf(req, url, trustOpts, true));
198
- })().catch(() => socket.destroy()));
260
+ if (!conn)
261
+ return;
262
+ // The connection's workspace is the one it was opened for; a message may name another (`ws`).
263
+ // Looked up per message: a workspace closed meanwhile is not served, a reopened one is the new one.
264
+ const own = open?.slug;
265
+ const resolve = (slug) => bySlug.get(slug ?? own ?? "")?.ws;
266
+ const entry = { slug: own, close: () => conn.close(4404, "workspace closed") };
267
+ sockets.add(entry);
268
+ conn.onClose(() => sockets.delete(entry));
269
+ runInHub(hub, () => serveSocket(conn, resolve, version, trust, () => trustOf(req, url, trustOpts, true), hub));
270
+ })().catch(() => socket.destroy());
271
+ };
272
+ const server = http.createServer(handler(() => fallback));
273
+ server.on("upgrade", upgrade(() => fallback));
274
+ const port = await listen(server, opts.port);
275
+ server.once("close", () => {
276
+ for (const s of aliasServers.values())
277
+ s.close();
199
278
  });
200
- return new Promise((resolve, reject) => {
201
- server.once("error", reject);
202
- server.once("close", stopCloudSync);
203
- server.listen(opts.port, INSPECTOR_HOST, () => ws.run(() => {
204
- const addr = server.address();
205
- const port = typeof addr === "object" && addr ? addr.port : opts.port;
206
- void registerInstance(port, ws.root);
207
- void registerWorkspace(ws.root);
208
- void getPkgVersion().then((v) => startCloudSync(port, v));
209
- resolve(server);
279
+ const hub = {
280
+ server,
281
+ port,
282
+ daemon: !!opts.daemon,
283
+ list: () => [...bySlug.values()],
284
+ // One open or close at a time: two overlapping opens of a root (the daemon reopening while `kraftwerk ui`
285
+ // asks, two clicks) must find each other, not make two copies of the workspace.
286
+ open: (root, o = {}) => serial(() => openNow(root, o)),
287
+ close: (root) => serial(() => closeNow(root)),
288
+ async stop() {
289
+ // Closing for good, not one by one: what was open stays noted for the next start.
290
+ const notify = opts.onChange;
291
+ opts.onChange = undefined;
292
+ for (const o of [...bySlug.values()])
293
+ await hub.close(o.root);
294
+ opts.onChange = notify;
295
+ hubs.delete(hub);
296
+ // A connected browser tab (its socket, a keep-alive connection) must not hold the stop open.
297
+ for (const s of [...sockets])
298
+ s.close();
299
+ const closing = new Promise((r) => server.close(() => r()));
300
+ server.closeAllConnections();
301
+ for (const s of aliasServers.values())
302
+ s.closeAllConnections();
303
+ await closing;
304
+ },
305
+ };
306
+ let lock = Promise.resolve();
307
+ function serial(fn) {
308
+ const run = lock.then(fn, fn);
309
+ lock = run.catch(() => { });
310
+ return run;
311
+ }
312
+ /** Tell the daemon what is open; a failure there is reported, the workspace stays as it is. */
313
+ async function noteChange() {
314
+ try {
315
+ await opts.onChange?.(hub);
316
+ }
317
+ catch (err) {
318
+ console.error(`kraftwerk: could not note the open workspaces: ${err.message}`);
319
+ }
320
+ }
321
+ async function openNow(root, o) {
322
+ // A folder that is gone (or a kraftwerk.yml that does not parse) is refused, not served as an empty workspace.
323
+ if (!(await isDir(path.resolve(root))))
324
+ throw new Error(`no such folder: ${root}`);
325
+ const ws0 = await resolveWorkspace(root);
326
+ const abs = ws0.root;
327
+ const already = [...bySlug.values()].find((x) => x.root === abs);
328
+ if (already)
329
+ return already;
330
+ const slug = workspaceSlug(ws0);
331
+ const clash = bySlug.get(slug);
332
+ if (clash)
333
+ throw new Error(`slug "${slug}" is already served for ${clash.root} — set \`slug:\` in one of the two kraftwerk.yml files`);
334
+ const ws = new Workspace({ outputDir: o.outputDir ?? ws0.outputDir, root: abs, slug, env: readWorkspaceDotenv(abs) });
335
+ const name = ws0.config.name ?? path.basename(abs);
336
+ const entry = { slug, root: abs, name, ws, url: opts.daemon ? `http://${slug}.localhost:${port}` : `http://localhost:${port}` };
337
+ // A daemon also listens on the workspace's own port, so its old address keeps working — when that port is free.
338
+ const own = ws0.config.port;
339
+ if (opts.daemon && own && own !== port) {
340
+ const alias = http.createServer(handler(() => entry));
341
+ alias.on("upgrade", upgrade(() => entry));
342
+ try {
343
+ entry.aliasPort = await listen(alias, own);
344
+ aliasServers.set(abs, alias);
345
+ }
346
+ catch {
347
+ alias.close();
348
+ }
349
+ }
350
+ bySlug.set(slug, entry);
351
+ if (!opts.daemon)
352
+ fallback ??= entry;
353
+ runInHub(hub, () => ws.run(() => {
354
+ startRoutineScheduler();
355
+ startGitSync();
356
+ // Best-effort, in the background: none of them may hold up (or, failing, break) the open.
357
+ void registerInstance(entry.aliasPort ?? port, abs, opts.daemon ? { hub: true, slug, url: entry.url } : {}).catch(() => { });
358
+ void registerWorkspace(abs).catch(() => { });
359
+ void startCloudSync(entry.url, version).catch(() => { });
210
360
  }));
211
- });
361
+ await noteChange();
362
+ return entry;
363
+ }
364
+ async function closeNow(root) {
365
+ const abs = path.resolve(root);
366
+ const entry = [...bySlug.values()].find((x) => x.root === abs);
367
+ if (!entry)
368
+ return false;
369
+ bySlug.delete(entry.slug);
370
+ if (fallback === entry)
371
+ fallback = undefined;
372
+ for (const s of [...sockets])
373
+ if (s.slug === entry.slug)
374
+ s.close();
375
+ const alias = aliasServers.get(abs);
376
+ alias?.close();
377
+ alias?.closeAllConnections();
378
+ aliasServers.delete(abs);
379
+ await runInHub(hub, () => entry.ws.run(async () => {
380
+ stopRoutineScheduler();
381
+ stopGitSync();
382
+ closeWatches();
383
+ disposeWorkspaceBackends();
384
+ disposeWorkspaceDevs();
385
+ await cloudGoodbye();
386
+ stopCloudSync();
387
+ }));
388
+ unregisterInstance(abs);
389
+ markWorkspaceStopped(abs);
390
+ entry.ws.close();
391
+ await noteChange();
392
+ return true;
393
+ }
394
+ hubs.add(hub);
395
+ return hub;
396
+ }
397
+ /**
398
+ * A standalone server for one workspace (`kraftwerk ui`, tests): a hub
399
+ * serving it as its default, reached with or without its slug. Resolves
400
+ * once it listens.
401
+ */
402
+ export async function startInspector(opts) {
403
+ const hub = await startHub({ port: opts.port, staticDir: opts.staticDir, trustLoopback: opts.trustLoopback });
404
+ const open = await hub.open(opts.root ?? path.dirname(path.resolve(opts.outputDir)), { outputDir: opts.outputDir });
405
+ // Code that runs outside any request (the CLI side of this process) still finds its workspace.
406
+ setDefaultWorkspace(open.ws);
407
+ hub.server.once("close", () => void hub.stop());
408
+ return hub.server;
212
409
  }
@@ -0,0 +1,20 @@
1
+ import type http from "node:http";
2
+ /**
3
+ * Which workspace a request is for. A workspace is addressed by its slug
4
+ * (see workspaceSlug in config.ts), never by a port:
5
+ *
6
+ * - `<slug>.localhost[:port]` — the browser's form on this machine: every
7
+ * workspace its own origin, no setup (browsers resolve *.localhost here);
8
+ * - `/w/<slug>/…` — the path form, one origin for all (where a host name per
9
+ * workspace is not available); the prefix is stripped before routing;
10
+ * - neither — the server's own workspace (a port per workspace, as before).
11
+ *
12
+ * The socket names it per message instead (`ws`), see api/socket.ts.
13
+ */
14
+ export interface Target {
15
+ /** The slug the request named, if it named one. */
16
+ slug?: string;
17
+ /** The request's URL without the `/w/<slug>` prefix. */
18
+ url: URL;
19
+ }
20
+ export declare function targetOf(req: http.IncomingMessage, url: URL): Target;
@@ -0,0 +1,18 @@
1
+ const PATH = /^\/w\/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(\/.*)?$/;
2
+ export function targetOf(req, url) {
3
+ const m = PATH.exec(url.pathname);
4
+ if (m) {
5
+ const rest = new URL(url.href);
6
+ rest.pathname = m[2] ?? "/";
7
+ return { slug: m[1], url: rest };
8
+ }
9
+ const host = req.headers.host ?? "";
10
+ let name = "";
11
+ try {
12
+ name = new URL(`http://${host}`).hostname;
13
+ }
14
+ catch { }
15
+ const label = name.endsWith(".localhost") ? name.slice(0, -".localhost".length) : "";
16
+ // One label only: a.b.localhost names no workspace.
17
+ return label && !label.includes(".") ? { slug: label, url } : { url };
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netnodeag/kraftwerk",
3
- "version": "0.65.0",
3
+ "version": "0.66.0",
4
4
  "description": "Open-source agentic workspace for teams — where people and AI agents get work done together: agents (Claude Code, Codex, Pi), skills, shared knowledge, repeatable workflows, and deterministic verification",
5
5
  "keywords": [
6
6
  "agents",
@@ -10,6 +10,11 @@
10
10
  "type": "string",
11
11
  "description": "Display name of the project (\"environment\"), shown in the inspector header and browser tab"
12
12
  },
13
+ "slug": {
14
+ "type": "string",
15
+ "pattern": "^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$",
16
+ "description": "This workspace's address on this machine (<slug>.localhost, /w/<slug>/). Unique per machine. Default: the folder name. Unlike name, it changes only when you mean to move the workspace."
17
+ },
13
18
  "icon": {
14
19
  "type": "string",
15
20
  "description": "Emoji used as the inspector favicon (browser-tab icon), e.g. \"⚡\""
@@ -1 +1 @@
1
- import{C as e,D as t,F as n,L as r,R as i,Ut as a,V as o,n as s,r as c,s as l,u,v as d,vt as f}from"./dist-CYzOYk_e.js";import{n as p}from"./dist-Bnxg6V5L.js";var m=1,h=2,g=3,_=183,v=4,y=184,b=5,x=185,S=6;function C(e){return e>=65&&e<=90||e>=97&&e<=122}var w=new s(e=>{let t=e.pos;for(;;){let{next:n}=e;if(n<0)break;if(n==123){let n=e.peek(1);if(n==123){if(e.pos>t)break;e.acceptToken(m,2);return}if(n==37){if(e.pos>t)break;let n=2,r=2;for(;;){let t=e.peek(n);if(t==32||t==10)++n;else if(t==35)for(++n;;){let t=e.peek(n);if(t<0||t==10)break;n++}else if(t==45&&r==2)r=++n;else{let i=t==101&&e.peek(n+1)==110&&e.peek(n+2)==100;e.acceptToken(i?g:h,r);return}}}}if(e.advance(),n==10)break}e.pos>t&&e.acceptToken(_)});function T(e,t,n){return new s(r=>{let i=r.pos;for(;;){let{next:t}=r;if(t==123&&r.peek(1)==37){let t=2;for(;;t++){let e=r.peek(t);if(e!=32&&e!=10)break}let a=``;for(;;t++){let e=r.peek(t);if(!C(e))break;a+=String.fromCharCode(e)}if(a==e){if(r.pos>i)break;r.acceptToken(n,2);break}}else if(t<0)break;if(r.advance(),t==10)break}r.pos>i&&r.acceptToken(t)})}var E=T(`endcomment`,x,b),D=T(`endraw`,y,v),O=new s(e=>{if(e.next==35){for(e.advance();!(e.next==10||e.next<0||(e.next==37||e.next==125)&&e.peek(1)==125);)e.advance();e.acceptToken(S)}}),k={__proto__:null,contains:34,or:38,and:38,true:52,false:52,empty:54,forloop:57,tablerowloop:59,continue:61,in:135,with:199,for:201,as:203,if:239,endif:243,unless:249,endunless:253,elsif:257,else:261,case:267,endcase:271,when:275,endfor:283,tablerow:289,endtablerow:293,break:297,cycle:303,echo:307,render:311,include:315,assign:319,capture:325,endcapture:329,increment:333,decrement:337},A={__proto__:null,if:90,endif:94,elsif:98,else:102,unless:108,endunless:112,case:118,endcase:122,when:126,for:132,endfor:140,tablerow:146,endtablerow:150,break:154,continue:158,cycle:162,comment:168,endcomment:174,raw:180,endraw:186,echo:190,render:194,include:206,assign:210,capture:216,endcapture:220,increment:224,decrement:228,liquid:232},j=c.deserialize({version:14,states:"MfQYOPOOOOOP'#F}'#F}OhOaO'#CdOyQhO'#CfO!hQxO'#DUO$ROPO'#DXO$aOPO'#DbO$oOPO'#DgO$}OPO'#DnO%]OPO'#DuO%kOSO'#EQO%pOQO'#EWO%uOPO'#EjO&TQxO'#F{OOOP'#Gj'#GjOOOP'#G`'#G`OOOP'#F|'#F|QYOPOOOOOP-E9{-E9{OOQW'#Cg'#CgO&nQ!jO,59QO&uQ!jO'#GaOyQhO'#CtOOQW'#Ge'#GeOOQW'#Gf'#GfOOQW'#Gg'#GgOOQW'#Ga'#GaOOOP,59p,59pO*SQhO,59pOyQhO,59tOyQhO,59xO*^QhO,59zOyQhO,59}OyQhO,5:SOyQhO,5:WO!cQhO,5:ZO!cQhO,5:bO*cQhO,5:fO*hQhO,5:hO*mQhO,5:jO*rQhO,5:mO*wQhO,5:sOyQhO,5:xOyQhO,5:zOyQhO,5;QOyQhO,5;SOyQhO,5;VOyQhO,5;ZOyQhO,5;]O,WQhO,5;_O,_OPO'#CdOOOP,59s,59sO$ROPO,59sO,mQxO'#F{OOOP,59|,59|O$aOPO,59|O,uQxO'#F{OOOP,5:R,5:RO$oOPO,5:RO,}QxO'#F{OOOP,5:Y,5:YO$}OPO,5:YO-VQxO'#F{OOOP,5:a,5:aO%]OPO,5:aO-_QxO'#F{OOOS'#GT'#GTO-gOSO'#ETO-oOSO,5:lOOOQ'#GU'#GUO-tOQO'#EZO-|OQO,5:rOOOP,5;U,5;UO%uOPO,5;UO.RQxO'#F{O.ZQhO,5<gOOOP-E9z-E9zO.`Q#|O,59SOyQhO,59VOyQhO,59WOyQhO,59WO.eQhO'#C}OOQW'#GO'#GOO.jQhO1G.lOOOP1G.l1G.lOyQhO,59WOyQhO,59[O/TQ!jO,59`O/[Q!jO'#CgO1kQ!jO'#GiO3gQhO'#DROOQW'#Gi'#GiO3lQhO'#GhO5fQhO1G/[OOOP1G/[1G/[O5fQhO1G/[O5nQ!jO1G/`O5uQ!jO1G/dOOOP1G/f1G/fO5|Q!jO1G/iO6TQ!jO1G/nO6[Q!jO1G/rO6fQhO1G/uO6fQhO1G/|OOOP1G0Q1G0QOOOP1G0S1G0SO6kQhO1G0UOOOS1G0X1G0XOOOQ1G0_1G0_O6vQ!jO1G0dO6}Q!jO1G0fO7_Q!jO1G0lO7fQ!jO1G0nO7mQ!jO1G0qO7tQ!jO1G0uO7{Q!jO1G0wOOQW'#Gm'#GmOOQW'#Gp'#GpOyQhO'#EvO8SQhO'#EuOOQW'#Gr'#GrOyQhO'#E{O8ZQhO'#EzOOQW'#Gt'#GtOyQhO'#FPOOQW'#Gu'#GuOOQW'#FR'#FROOQW'#Gv'#GvOyQhO'#FUO8bQhO'#FTOOQW'#Gx'#GxOyQhO'#FYO!cQhO'#F]O8iQhO'#F[OOQW'#Gz'#GzO!cQhO'#FaO8pQhO'#F`OOQW'#G|'#G|OOQW'#Fe'#FeOOQW'#Fg'#FgOOQW'#G}'#G}O8wQhO'#FhOOQW'#HO'#HOOyQhO'#FjOOQW'#HP'#HPOyQhO'#FlOOQW'#HQ'#HQOyQhO'#FnOOQW'#HR'#HROyQhO'#FpOOQW'#HS'#HSOyQhO'#FsO8|QhO'#FrOOQW'#HU'#HUOyQhO'#FwOOQW'#HV'#HVOyQhO'#FyOOQW'#Go'#GoOOQW'#GW'#GWO9TQhO1G0yOOOP1G0y1G0yOOOP1G/_1G/_O9[QhO,59vOOOP1G/h1G/hO9aQhO,5:POOOP1G/m1G/mO9fQhO,5:UOOOP1G/t1G/tO9kQhO,5:_OOOP1G/{1G/{O9pQhO,5:dOOOS-E:R-E:ROOOP1G0W1G0WO9uQxO'#EUOOOQ-E:S-E:SOOOP1G0^1G0^O9zQxO'#E[OOOP1G0p1G0pO:PQhO,5;XOOOP1G2R1G2ROOQW1G.n1G.nO:UQ!jO1G.qO<uQ!jO1G.rO<|Q!jO1G.rOOQW'#DP'#DPO?[QhO,59iOOQW-E9|-E9|OOOP7+$W7+$WOAUQ!jO1G.rOA]Q!jO1G.vOyQhO1G.zOyQhO,59mO)eQhO'#GPOCkQhO,5=SOOOP7+$v7+$vOEeQhO7+$vOOOP7+$z7+$zOOOP7+%O7+%OOOOP7+%T7+%TOOOP7+%Y7+%YOyQhO'#GQOEmQhO7+%^OOOP7+%^7+%^OOQW'#Gk'#GkOyQhO7+%aOyQhO7+%hOEuQhO'#GSOEzQhO7+%pOOOP7+%p7+%pOFSQhO7+%pOFXQhO7+&OOOOP7+&O7+&OOOQW'#Gl'#GlO!cQhO'#EbOyQhO'#EbOOQW'#GV'#GVOFaQhO7+&QOOOP7+&Q7+&QOOOP7+&W7+&WOFoQhO7+&YOOOP7+&Y7+&YOOOP7+&]7+&]OOOP7+&a7+&aOOOP7+&c7+&cOFwQ!jO,5;bOOQW'#Gq'#GqOOQW'#Ex'#ExOOQW,5;a,5;aO8SQhO,5;aOHWQ!jO,5;gOOQW'#Gs'#GsOOQW'#E}'#E}OOQW,5;f,5;fO8ZQhO,5;fOIgQ!jO,5;kOKYQ!jO,5;pOOQW'#Gw'#GwOOQW'#FW'#FWOOQW,5;o,5;oO8bQhO,5;oOLiQ!jO,5;tO6fQhO,5;wOOQW'#Gy'#GyOOQW'#F^'#F^OOQW,5;v,5;vO8iQhO,5;vO6fQhO,5;{OOQW'#G{'#G{OOQW'#Fc'#FcOOQW,5;z,5;zO8pQhO,5;zON_QhO,5<SO!!UQ!jO,5<UO!#wQ!jO,5<WO!%pQ!jO,5<YO!'cQ!jO,5<[O!)UQ!jO,5<_OOQW'#HT'#HTOOQW'#Fu'#FuOOQW,5<^,5<^O8|QhO,5<^O!*eQ!jO,5<cO!,WQ!jO,5<eOOQW-E:U-E:UOOOP7+&e7+&eOOOP1G/b1G/bOOOP1G/k1G/kOOOP1G/p1G/pOOOP1G/y1G/yOOOP1G0O1G0OO!-yQhO,5:pO!.OQhO,5:vOOOP1G0s1G0sOOQW7+$]7+$]O)eQhO1G/TO!.TQ!jO7+$fO!.[Q!jO1G/XOOQW,5<k,5<kOOQW-E9}-E9}OOOP<<Hb<<HbO!0WQ!jO,5<lOOQW-E:O-E:OOOOP<<Hx<<HxO!1|Q!jO<<H{O!2WQ!jO<<ISOOQW,5<n,5<nOOQW-E:Q-E:QOOOP<<I[<<I[O!2bQhO<<I[OOOP<<Ij<<IjO!2jQhO,5:|O!2oQ!jO,5:|OOQW-E:T-E:TOOOP<<Il<<IlOOOP<<It<<ItOOQW1G0{1G0{OOQW1G1Q1G1QOOQW1G1Z1G1ZO!4kQhO1G1`OyQhO1G1cOOQW1G1b1G1bOyQhO1G1gOOQW1G1f1G1fO!6_QhO1G1nO!8RQhO1G1nO!8WQhO1G1pOOQW'#GX'#GXO!9zQhO1G1rO!;qQhO1G1vOOQW1G1x1G1xOOOP1G0[1G0[OOOP1G0b1G0bOOQW7+$o7+$oOOQW<<HQ<<HQOOQW'#DS'#DSO!=eQhO'#DrOOQW'#GR'#GRO!?OQhOAN>gOOOPAN>gAN>gO!?WQhOAN>nOOOPAN>nAN>nO!?`QhOAN>vOOOPAN>vAN>vOyQhO1G0hOOQW'#Gn'#GnO!cQhO1G0hO!?hQ!jO7+&}O!@zQ!jO7+'RO!B^QhO7+'YOOQW-E:V-E:VOyQhO,5:^OOQW-E:P-E:POOOPG24RG24ROOOPG24YG24YOOOPG24bG24bO!DQQ!jO7+&SOOQW7+&S7+&SO!EyQhO<<JiO!GZQhO<<JmO!HkQhO<<JtO!J_Q!jO1G/x",stateData:"!Kw~O%ROSUOS~OPROQSOR]O$}PO~O$}POPWXQWXRWX$|WX~OgfOjjOkjOlgOmhOniOojOpjO%UcO~OylOzkO}mO!RnO!ToO!WpO!]qO!arO!dsO!ktO!ouO!qvO!swO!vxO!|yO#RzO#T{O#Z|O#]}O#`!OO#d!PO#f!QO#h!RO~OPROQSOR!VO$}PO~OPROQSOR!YO$}PO~OPROQSOR!]O$}PO~OPROQSOR!`O$}PO~OPROQSOR!cO$}PO~O%P!dO~O%O!gO~OPROQSOR!lO$}PO~Oy!mO~O]!oOa!wOb!qOc!rOr!sO%W!pO~OX!vO~P&YOe!xOX%TX]%TXa%TXb%TXc%TXr%TX%W%TXi%TXw%TXz%TX#V%TX#W%TX%V%TXn%TX#k%TX#m%TX#p%TX#t%TX#v%TX#y%TX#}%TX$U%TX$Y%TX$]%TX$_%TX$a%TX$c%TX$e%TX$h%TX$l%TX$n%TX#r%TX#{%TX$j%TXf%TX%U%TX#X%TX$R%TX$W%TX~OgfOjjOkjOlgOmhOniOojOpjO%U!zO~Or!sOz#QO~P)eOz#UO~Oz#[O~Oz#]O~Oo#^O~Oz#_O~Oz#`O~OniO#W#hO#k#iO#p#lO#t#oO#v#qO#y#sO#}#vO$U#zO$Y#}O$]$QO$_$SO$a$UO$c$WO$e$YO$h$[O$l$_O$n$aO~Oz$fO~P*|O$}POPWXQWXRWX~Oy!mO!P$hO~Oy!mO!Y$jO~Oy!mO!_$lO~Oy!mO!h$nO~Oy!mO!m$pO~O%P!dOT!wX~OT$sO~O%O!gOS!}X~OS$vO~Oy!mO#b$xO~Oz$yO~O^$zO~O%U%OO~OX%ROr!sO~O]!oOa!wOb!qOc!rO%W!pO~Oi%UO~P.rO]ZXaZXbZXcZXeZXrZXtvXwZXzZX%WZXXZXnZX#WZX#kZX#pZX#tZX#vZX#yZX#}ZX$UZX$YZX$]ZX$_ZX$aZX$cZX$eZX$hZX$lZX$nZX#mZX#rZX#{ZX$RZX$WZX$jZX~Or%]Xw%]Xz%]XX%]Xn%]X#W%]X#k%]X#p%]X#t%]X#v%]X#y%]X#}%]X$U%]X$Y%]X$]%]X$_%]X$a%]X$c%]X$e%]X$h%]X$l%]X$n%]X#m%]X#r%]X#{%]X$R%]X$W%]X$j%]X~P.rOt%VO~Ow%WOr%[Xz%[XX%[Xn%[X#W%[X#k%[X#p%[X#t%[X#v%[X#y%[X#}%[X$U%[X$Y%[X$]%[X$_%[X$a%[X$c%[X$e%[X$h%[X$l%[X$n%[X#m%[X#r%[X#{%[X$R%[X$W%[X$j%[X~Or!sOz%YO~Oz%[O~P.rOz%]O~P.rOz%^O~P.rOz%_O~P.rOw%`Oz%bO~P.rO!e%cO~Ot%iOw%fOz%hO~Oz%kO~P&YOw%mOz%qO#V%lO#W#hO~P.rOz%rO~P.rOz%tO~P&YOz%uO~P.rOz%vO~P.rOz%wO~P.rO#m%yO~P*|O#r&OO~P*|O#{&UO~P*|O$R&[O~P*|O$W&aO~P*|Oo&eO~O$j&kO~P*|Oz&rO~P*|Oz&sO~Oz&tO~Oz&uO~Oz&vO~Oz&wO~O!y&xO~O#P&yO~Oz&zO~O%V&{O~P.rO]!oO%W!pOX`ia`ic`ir`ii`iw`iz`i#V`i#W`i%V`in`i#k`i#m`i#p`i#t`i#v`i#y`i#}`i$U`i$Y`i$]`i$_`i$a`i$c`i$e`i$h`i$l`i$n`i#r`i#{`i$j`if`i%U`i#X`i$R`i$W`i~Ob`i~P:]OX`ir`ii`iw`iz`i#V`i#W`i%V`in`i#k`i#m`i#p`i#t`i#v`i#y`i#}`i$U`i$Y`i$]`i$_`i$a`i$c`i$e`i$h`i$l`i$n`i#r`i#{`i$j`if`i%U`i#X`i$R`i$W`i~P.rOt&|OXqarqazqanqa#Wqa#kqa#pqa#tqa#vqa#yqa#}qa$Uqa$Yqa$]qa$_qa$aqa$cqa$eqa$hqa$lqa$nqa#mqa#rqa#{qa$Rqa$Wqa$jqa~Ob!qO~P:]OXdirdiidiwdizdi#Vdi#Wdi%Vdindi#kdi#mdi#pdi#tdi#vdi#ydi#}di$Udi$Ydi$]di$_di$adi$cdi$edi$hdi$ldi$ndi#rdi#{di$jdifdi%Udi#Xdi$Rdi$Wdi~P.rOw%WOr%[az%[aX%[an%[a#W%[a#k%[a#p%[a#t%[a#v%[a#y%[a#}%[a$U%[a$Y%[a$]%[a$_%[a$a%[a$c%[a$e%[a$h%[a$l%[a$n%[a#m%[a#r%[a#{%[a$R%[a$W%[a$j%[a~Or!sOz'RO~Ow%`Oz'UO~Oo'XO~Ow%fOz'ZO~Oo'[O~Or!sOz']O~Ow%mOz'aO#V%lO#W#hO~Or!sOz'bO~On#ja#W#ja#k#ja#m#ja#p#ja#t#ja#v#ja#y#ja#}#ja$U#ja$Y#ja$]#ja$_#ja$a#ja$c#ja$e#ja$h#ja$l#ja$n#ja~P.rOn#oa#W#oa#k#oa#p#oa#r#oa#t#oa#v#oa#y#oa#}#oa$U#oa$Y#oa$]#oa$_#oa$a#oa$c#oa$e#oa$h#oa$l#oa$n#oa~P.rOn#saz#sa#W#sa#k#sa#p#sa#t#sa#v#sa#y#sa#}#sa$U#sa$Y#sa$]#sa$_#sa$a#sa$c#sa$e#sa$h#sa$l#sa$n#sa#m#sa#r#sa#{#sa$R#sa$W#sa$j#sa~P.rOn#xa#W#xa#k#xa#p#xa#t#xa#v#xa#y#xa#{#xa#}#xa$U#xa$Y#xa$]#xa$_#xa$a#xa$c#xa$e#xa$h#xa$l#xa$n#xa~P.rOw%`On#|az#|a#W#|a#k#|a#p#|a#t#|a#v#|a#y#|a#}#|a$U#|a$Y#|a$]#|a$_#|a$a#|a$c#|a$e#|a$h#|a$l#|a$n#|a#m#|a#r#|a#{#|a$R#|a$W#|a$j#|a~P.rOt'lOw%fOn$[az$[a#W$[a#k$[a#p$[a#t$[a#v$[a#y$[a#}$[a$U$[a$Y$[a$]$[a$_$[a$a$[a$c$[a$e$[a$h$[a$l$[a$n$[a#m$[a#r$[a#{$[a$R$[a$W$[a$j$[a~On$^az$^a#W$^a#k$^a#p$^a#t$^a#v$^a#y$^a#}$^a$U$^a$Y$^a$]$^a$_$^a$a$^a$c$^a$e$^a$h$^a$l$^a$n$^a#m$^a#r$^a#{$^a$R$^a$W$^a$j$^a~P&YOw%mO#V%lO#W#hOn$`az$`a#k$`a#p$`a#t$`a#v$`a#y$`a#}$`a$U$`a$Y$`a$]$`a$_$`a$a$`a$c$`a$e$`a$h$`a$l$`a$n$`a#m$`a#r$`a#{$`a$R$`a$W$`a$j$`a~P.rOn$baz$ba#W$ba#k$ba#p$ba#t$ba#v$ba#y$ba#}$ba$U$ba$Y$ba$]$ba$_$ba$a$ba$c$ba$e$ba$h$ba$l$ba$n$ba#m$ba#r$ba#{$ba$R$ba$W$ba$j$ba~P.rOn$daz$da#W$da#k$da#p$da#t$da#v$da#y$da#}$da$U$da$Y$da$]$da$_$da$a$da$c$da$e$da$h$da$l$da$n$da#m$da#r$da#{$da$R$da$W$da$j$da~P&YOn$ga#W$ga#k$ga#p$ga#t$ga#v$ga#y$ga#}$ga$U$ga$Y$ga$]$ga$_$ga$a$ga$c$ga$e$ga$h$ga$j$ga$l$ga$n$ga~P.rOn$kaz$ka#W$ka#k$ka#p$ka#t$ka#v$ka#y$ka#}$ka$U$ka$Y$ka$]$ka$_$ka$a$ka$c$ka$e$ka$h$ka$l$ka$n$ka#m$ka#r$ka#{$ka$R$ka$W$ka$j$ka~P.rOn$maz$ma#W$ma#k$ma#p$ma#t$ma#v$ma#y$ma#}$ma$U$ma$Y$ma$]$ma$_$ma$a$ma$c$ma$e$ma$h$ma$l$ma$n$ma#m$ma#r$ma#{$ma$R$ma$W$ma$j$ma~P.rOz'rO~Oz'sO~Of'uO~P.rOruiwuizuiXuinui#Wui#kui#pui#tui#vui#yui#}ui$Uui$Yui$]ui$_ui$aui$cui$eui$hui$lui$nui#mui#rui#{ui$Rui$Wui$jui~P.rOw$taz$tan$ta#W$ta#k$ta#p$ta#t$ta#v$ta#y$ta#}$ta$U$ta$Y$ta$]$ta$_$ta$a$ta$c$ta$e$ta$h$ta$l$ta$n$ta#m$ta#r$ta#{$ta$R$ta$W$ta$j$ta~P.rOz'zO%U'vO~P.rOz'|O%U'vO~P.rOw%fOz(OO~Ot(PO~O#X(QOw#Uaz#Ua#V#Ua#W#Uan#Ua#k#Ua#p#Ua#t#Ua#v#Ua#y#Ua#}#Ua$U#Ua$Y#Ua$]#Ua$_#Ua$a#Ua$c#Ua$e#Ua$h#Ua$l#Ua$n#Ua#m#Ua#r#Ua#{#Ua$R#Ua$W#Ua$j#Ua~P.rOw%`On#|iz#|i#W#|i#k#|i#p#|i#t#|i#v#|i#y#|i#}#|i$U#|i$Y#|i$]#|i$_#|i$a#|i$c#|i$e#|i$h#|i$l#|i$n#|i#m#|i#r#|i#{#|i$R#|i$W#|i$j#|i~Ow%fOn$[iz$[i#W$[i#k$[i#p$[i#t$[i#v$[i#y$[i#}$[i$U$[i$Y$[i$]$[i$_$[i$a$[i$c$[i$e$[i$h$[i$l$[i$n$[i#m$[i#r$[i#{$[i$R$[i$W$[i$j$[i~Oo(UO~Or!sOn$^iz$^i#W$^i#k$^i#p$^i#t$^i#v$^i#y$^i#}$^i$U$^i$Y$^i$]$^i$_$^i$a$^i$c$^i$e$^i$h$^i$l$^i$n$^i#m$^i#r$^i#{$^i$R$^i$W$^i$j$^i~Ow%mO#V%lO#W#hOn$`iz$`i#k$`i#p$`i#t$`i#v$`i#y$`i#}$`i$U$`i$Y$`i$]$`i$_$`i$a$`i$c$`i$e$`i$h$`i$l$`i$n$`i#m$`i#r$`i#{$`i$R$`i$W$`i$j$`i~Or!sOn$diz$di#W$di#k$di#p$di#t$di#v$di#y$di#}$di$U$di$Y$di$]$di$_$di$a$di$c$di$e$di$h$di$l$di$n$di#m$di#r$di#{$di$R$di$W$di$j$di~Ot(WOz!fX%U!fXn!fX#W!fX#k!fX#p!fX#t!fX#v!fX#y!fX#}!fX$R!fX$U!fX$Y!fX$]!fX$_!fX$a!fX$c!fX$e!fX$h!fX$l!fX$n!fX$W!fX~Oz(YO%U'vO~Oz(ZO%U'vO~Ow%fOz([O~O%U'vOn$Pq#W$Pq#k$Pq#p$Pq#t$Pq#v$Pq#y$Pq#}$Pq$R$Pq$U$Pq$Y$Pq$]$Pq$_$Pq$a$Pq$c$Pq$e$Pq$h$Pq$l$Pq$n$Pq~P.rO%U'vOn$Tq#W$Tq#k$Tq#p$Tq#t$Tq#v$Tq#y$Tq#}$Tq$U$Tq$W$Tq$Y$Tq$]$Tq$_$Tq$a$Tq$c$Tq$e$Tq$h$Tq$l$Tq$n$Tq~P.rOw%fOn$[qz$[q#W$[q#k$[q#p$[q#t$[q#v$[q#y$[q#}$[q$U$[q$Y$[q$]$[q$_$[q$a$[q$c$[q$e$[q$h$[q$l$[q$n$[q#m$[q#r$[q#{$[q$R$[q$W$[q$j$[q~Ow#Uqz#Uq#V#Uq#W#Uqn#Uq#k#Uq#p#Uq#t#Uq#v#Uq#y#Uq#}#Uq$U#Uq$Y#Uq$]#Uq$_#Uq$a#Uq$c#Uq$e#Uq$h#Uq$l#Uq$n#Uq#m#Uq#r#Uq#{#Uq$R#Uq$W#Uq$j#Uq~P.rO%U'vOn$Py#W$Py#k$Py#p$Py#t$Py#v$Py#y$Py#}$Py$R$Py$U$Py$Y$Py$]$Py$_$Py$a$Py$c$Py$e$Py$h$Py$l$Py$n$Py~O%U'vOn$Ty#W$Ty#k$Ty#p$Ty#t$Ty#v$Ty#y$Ty#}$Ty$U$Ty$W$Ty$Y$Ty$]$Ty$_$Ty$a$Ty$c$Ty$e$Ty$h$Ty$l$Ty$n$Ty~Ow%fOn$[yz$[y#W$[y#k$[y#p$[y#t$[y#v$[y#y$[y#}$[y$U$[y$Y$[y$]$[y$_$[y$a$[y$c$[y$e$[y$h$[y$l$[y$n$[y#m$[y#r$[y#{$[y$R$[y$W$[y$j$[y~Oz!fi%U!fin!fi#W!fi#k!fi#p!fi#t!fi#v!fi#y!fi#}!fi$R!fi$U!fi$Y!fi$]!fi$_!fi$a!fi$c!fi$e!fi$h!fi$l!fi$n!fi$W!fi~P.rO",goto:"Ah%zPPPPPPPP%{P%{&]'oPP'o'oPPP'oPPP'oPPPPPPPP(oP)PP)S)XP)hPP)h)xP*YP)hP)hP)h*`P*pP)h*vP+WP)hP)h+^PP+n+xP)h,OP,`P)hP)hP)hP)h,fP,v,yP)h,|P-^-aP)hP)hP-dPPP)hP)hP)h-lP-|P)hP)hP)hP.S.dP.tP.S.zP/[P.SP.SP.S/bP/rP.SP.S/x0YP.S0`P0pP.SP.S.SP.SP.SP.SP.SP.S0vP1WP.SP.SP)h1^1|2d3S3Y3d3v4Y4`4f4l5[PPPPPP5b5rPPP'o'o8h9x:O%{:V:c:i;P;S;d;t;x<Y<^<n=O=`=d=t=x>Y>^>n?O?`?p@Q@b@r@vAWm_OTUVWX[a!U!X![!_!b!k!zeRflmnpqrz{|}!O!P!Q!p!q!r!w!x#j#m#p#t#w$T$V$X$Z$]$`$b%U%V%W%`%d%e%n&|'g'i(P(WQ#YsQ#ZtQ&Z#xQ&`#{Q'^%mR(^(R!{jRflmnpqrz{|}!O!P!Q!p!q!r!w!x#j#m#p#t#w$T$V$X$Z$]$`$b%U%V%W%`%d%e%n&|'g'i(P(Wm!tdl!u#P#R#a#d%Z%j%s&f&i'm'pR%P!sV!}l%W&|U!|l%W&|a'w'V'W'y'{(S(T(_(`m^OTUVWX[a!U!X![!_!b!kmTOTUVWX[a!U!X![!_!b!kQ!TTR$g!UmUOTUVWX[a!U!X![!_!b!kQ!WUR$i!XmVOTUVWX[a!U!X![!_!b!kQ!ZVR$k![mWOTUVWX[a!U!X![!_!b!ka'x'V'W'y'{(S(T(_(`Q!^WR$m!_mXOTUVWX[a!U!X![!_!b!kQ!aXR$o!bmYOTUVWX[a!U!X![!_!b!kR!fYR$r!fmZOTUVWX[a!U!X![!_!b!kR!iZR$u!iS%o#b%pT'n&g'om[OTUVWX[a!U!X![!_!b!kQ!j[R$w!km$c!R#k#n#u#y#|$^$e%|&R&X&_&d&nm#k!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ%{#kR'c%|m#n!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&Q#nR'd&Rm#u!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&W#uR'e&Xm#y!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&^#yR'h&_m#|!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&c#|R'j&dm$^!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&m$^R'q&nQaOQ!UTQ!XUQ![VQ!_WQ!bXQ!k[_!na!U!X![!_!b!kSQOaSbQ!Si!STUVWX[!U!X![!_!b!kQ!udQ#Pl^%Q!u#P%Z%j%s'm'pQ%Z#RQ%j#aQ%s#dQ'm&fR'p&iQ%X#OR'Q%XQ%a#XS'T%a'fR'f&YQ'y'VQ'{'WW(X'y'{(_(`Q(_(SR(`(TQ%g#^W'Y%g'k'}(aQ'k&eQ'}'[R(a(UQ!eYR$q!eQ!hZR$t!hQ%p#bR'`%pQ$e!RQ%|#kQ&R#nQ&X#uQ&_#yQ&d#|Q&n$^_&q$e%|&R&X&_&d&nQ'o&gR(V'om`OTUVWX[a!U!X![!_!b!kQdRQ!yfU!{l%W&|Q#SmQ#TnQ#VpQ#WqQ#XrQ#azQ#b{Q#c|Q#d}Q#e!OQ#f!PQ#g!QQ${!pQ$|!qQ$}!rQ%S!wQ%T!xQ%x#jQ%}#mQ&S#pQ&T#tQ&Y#wQ&f$TQ&g$VQ&h$XQ&i$ZQ&j$]Q&o$`Q&p$bQ&}%UQ'O%VQ'S%`Q'V%dQ'W%eQ'_%nQ(S'gQ(T'iQ(](PR(b(W!zjRflmnpqrz{|}!O!P!Q!p!q!r!w!x#j#m#p#t#w$T$V$X$Z$]$`$b%U%V%W%`%d%e%n&|'g'i(P(Wm$P!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ#RlR't&|S#Ol&|R'P%WQ%d#YQ%e#ZQ'g&ZR'i&`X%n#b%p&g'ol#x!R#k#n#u#y#|$^$e%|&R&X&_&d&nX%n#b%p&g'oR(R'_m$d!R#k#n#u#y#|$^$e%|&R&X&_&d&nm#j!R#k#n#u#y#|$^$e%|&R&X&_&d&nT%z#k%|m#m!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&P#n&Rm#p!R#k#n#u#y#|$^$e%|&R&X&_&d&nm#r!R#k#n#u#y#|$^$e%|&R&X&_&d&nm#t!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&V#u&Xm#w!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&]#y&_m#{!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&b#|&dm$O!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$R!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$T!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$V!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$X!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$Z!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$]!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&l$^&nm$`!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$b!R#k#n#u#y#|$^$e%|&R&X&_&d&n",nodeNames:`⚠ {{ {% {% {% {% InlineComment Template Text }} Interpolation VariableName MemberExpression . PropertyName SubscriptExpression BinaryExpression contains CompareOp LogicOp AssignmentExpression AssignOp ) ( RangeExpression .. BooleanLiteral empty forloop tablerowloop continue StringLiteral NumberLiteral Filter | FilterName : NamedArgument ParameterName , Tag TagName %} IfDirective Tag if EndTag endif Tag elsif Tag else UnlessDirective Tag unless EndTag endunless CaseDirective Tag case EndTag endcase Tag when ForDirective Tag for in Parameter EndTag endfor TableDirective Tag tablerow EndTag endtablerow Tag break Tag continue Tag cycle Comment Tag comment CommentText EndTag endcomment RawDirective Tag raw RawText EndTag endraw Tag echo Tag render RenderParameter with for as Tag include Tag assign CaptureDirective Tag capture EndTag endcapture Tag increment Tag decrement Tag liquid IfDirective Tag if EndTag endif UnlessDirective Tag unless EndTag endunless Tag elsif Tag else CaseDirective Tag case EndTag endcase Tag when ForDirective Tag EndTag endfor TableDirective Tag tablerow EndTag endtablerow Tag break Tag Tag cycle Tag echo Tag render Tag include Tag assign CaptureDirective Tag capture EndTag endcapture Tag increment Tag decrement EndTag`,maxTerm:225,nodeProps:[[`closedBy`,1,`}}`,-4,2,3,4,5,`%}`,23,`)`],[`openedBy`,9,`{{`,22,`(`,42,`{%`],[`group`,-13,11,12,15,16,20,24,26,27,28,29,30,31,32,`Expression`]],skippedNodes:[0,6],repeatNodeCount:12,tokenData:")e~RmXY!|YZ!|]^!|pq!|qr#_rs#juv$[wx$gxy%Syz%X{|%^|}&x}!O&}!O!P'Z!Q![&g![!]'k!^!_'p!_!`'x!`!a'p!c!}(Q!}#O(y#P#Q)O#R#S(Q#T#o(Q#p#q)T#q#r)Y%W;'S(Q;'S;:j(s<%lO(Q~#RS%R~XY!|YZ!|]^!|pq!|~#bP!_!`#e~#jOb~~#mUOY#jZr#jrs$Ps;'S#j;'S;=`$U<%lO#j~$UOo~~$XP;=`<%l#j~$_P#q#r$b~$gOz~~$jUOY$gZw$gwx$Px;'S$g;'S;=`$|<%lO$g~%PP;=`<%l$g~%XOg~~%^Of~P%aQ!O!P%g!Q![&gP%jP!Q![%mP%rRpP!Q![%m!g!h%{#X#Y%{P&OR{|&X}!O&X!Q![&_P&[P!Q![&_P&dPpP!Q![&_P&lSpP!O!P%g!Q![&g!g!h%{#X#Y%{~&}Ow~~'QRuv$[!O!P%g!Q![&g~'`Q]S!O!P'f!Q![%m~'kOi~~'pOt~~'uPb~!_!`#e~'}Pe~!_!`#e_(ZW^WyQ%UT}!O(Q!Q![(Q!c!}(Q#R#S(Q#T#o(Q%W;'S(Q;'S;:j(s<%lO(Q_(vP;=`<%l(Q~)OO%W~~)TO%V~~)YOr~~)]P#q#r)`~)eOX~",tokenizers:[w,D,E,O,0,1,2,3],topRules:{Template:[0,7]},dynamicPrecedences:{193:1,194:1,195:1,199:1,200:1,201:1,202:1,204:1,205:1,206:1,207:1,208:1,209:1,210:1,211:1,212:1,213:1,214:1,215:1,216:1,217:1,218:1,219:1,220:1,221:1,222:1,223:1,224:1,225:1},specialized:[{term:190,get:e=>k[e]||-1},{term:41,get:e=>A[e]||-1}],tokenPrec:0});function M(e,t){return e.split(` `).map(e=>({label:e,type:t}))}var N=M(`abs append at_least at_most capitalize ceil compact concat date default divided_by downcase escape escape_once first floor join last lstrip map minus modulo newline_to_br plus prepend remove remove_first replace replace_first reverse round rstrip size slice sort sort_natural split strip strip_html strip_newlines sum times truncate truncatewords uniq upcase url_decode url_encode where`,`function`),P=M(`cycle comment endcomment raw endraw echo increment decrement liquid if elsif else endif unless endunless case endcase for endfor tablerow endtablerow break continue assign capture endcapture render include`,`keyword`),F=M(`empty forloop tablerowloop in with as`,`keyword`),I=M(`first index index0 last length rindex`,`property`),L=M(`col col0 col_first col_last first index index0 last length rindex rindex0 row`,`property`);function R(e){let{state:t,pos:r}=e,i=n(t).resolveInner(r,-1).enterUnfinishedNodesBefore(r),a=i.childBefore(r)?.name||i.name;if(i.name==`FilterName`)return{type:`filter`,node:i};if(e.explicit&&a==`|`)return{type:`filter`};if(i.name==`TagName`)return{type:`tag`,node:i};if(e.explicit&&a==`{%`)return{type:`tag`};if(i.name==`PropertyName`&&i.parent.name==`MemberExpression`)return{type:`property`,node:i,target:i.parent};if(i.name==`.`&&i.parent.name==`MemberExpression`)return{type:`property`,target:i.parent};if(i.name==`MemberExpression`&&a==`.`)return{type:`property`,target:i};if(i.name==`VariableName`)return{type:`expression`,from:i.from};let o=e.matchBefore(/[\w\u00c0-\uffff]+$/);return o?{type:`expression`,from:o.from}:e.explicit&&i.name!=`CommentText`&&i.name!=`StringLiteral`&&i.name!=`NumberLiteral`&&i.name!=`InlineComment`?{type:`expression`}:null}function z(e,t,n,r){let i=[];for(;;){let n=t.getChild(`Expression`);if(!n)return[];if(n.name==`VariableName`||n.name==`forloop`||n.name==`tablerowloop`){let t=e.sliceDoc(n.from,n.to);if(t==`forloop`)return i.length?[]:I;if(t==`tablerowloop`)return i.length?[]:L;i.unshift(t);break}if(n.name==`MemberExpression`){let r=n.getChild(`PropertyName`);r&&i.unshift(e.sliceDoc(r.from,r.to)),t=n}else if(n.name==`SubscriptExpression`){let r=n.getChildren(`Expression`)[1];i.unshift(r?.name==`StringLiteral`?e.sliceDoc(r.from+1,r.to-1):`[]`),t=n}else return[]}return r?r(i,e,n):[]}function B(e={}){let t=e.filters?e.filters.concat(N):N,n=e.tags?e.tags.concat(P):P,r=e.variables?e.variables.concat(F):F,{properties:i}=e;return e=>{let a=R(e);if(!a)return null;let o=a.from??(a.node?a.node.from:e.pos),s;return s=a.type==`filter`?t:a.type==`tag`?n:a.type==`expression`?r:z(e.state,a.target,e,i),s.length?{options:s,from:o,validFor:/^[\w\u00c0-\uffff]*$/}:null}}var V=o.inputHandler.of((e,t,n,r)=>r!=`%`||t!=n||e.state.doc.sliceString(t-1,n+1)!=`{}`?!1:(e.dispatch(e.state.changeByRange(e=>({changes:{from:e.from,to:e.to,insert:`%%`},range:f.cursor(e.from+1)})),{scrollIntoView:!0,userEvent:`input.type`}),!0));function H(e){return t=>{let n=e.test(t.textAfter);return t.lineIndent(t.node.from)+(n?0:t.unit)}}var U=l.define({name:`liquid`,parser:j.configure({props:[r({"cycle comment endcomment raw endraw echo increment decrement liquid in with as":i.keyword,"empty forloop tablerowloop":i.atom,"if elsif else endif unless endunless case endcase for endfor tablerow endtablerow break continue":i.controlKeyword,"assign capture endcapture":i.definitionKeyword,contains:i.operatorKeyword,"render include":i.moduleKeyword,VariableName:i.variableName,TagName:i.keyword,FilterName:i.function(i.variableName),PropertyName:i.propertyName,ParameterName:i.attributeName,CompareOp:i.compareOperator,AssignOp:i.definitionOperator,LogicOp:i.logicOperator,NumberLiteral:i.number,StringLiteral:i.string,BooleanLiteral:i.bool,InlineComment:i.lineComment,CommentText:i.blockComment,"{% %} {{ }}":i.brace,"[ ]":i.bracket,"( )":i.paren,".":i.derefOperator,", .. : |":i.punctuation}),t.add({Tag:d({closing:`%}`}),"UnlessDirective ForDirective TablerowDirective CaptureDirective":H(/^\s*(\{%-?\s*)?end\w/),IfDirective:H(/^\s*(\{%-?\s*)?(endif|else|elsif)\b/),CaseDirective:H(/^\s*(\{%-?\s*)?(endcase|when)\b/)}),e.add({"UnlessDirective ForDirective TablerowDirective CaptureDirective IfDirective CaseDirective RawDirective Comment"(e){let t=e.firstChild,n=e.lastChild;return!t||t.name!=`Tag`?null:{from:t.to,to:n.name==`EndTag`?n.from:e.to}}})]}),languageData:{commentTokens:{line:`#`},indentOnInput:/^\s*{%-?\s*(?:end|elsif|else|when|)$/}}),W=p();function G(e){return U.configure({wrap:a(t=>t.type.isTop?{parser:e.parser,overlay:e=>e.name==`Text`||e.name==`RawText`}:null)},`liquid`)}var K=G(W.language);function q(e={}){let t=e.base||W,n=t.language==W.language?K:G(t.language);return new u(n,[t.support,n.data.of({autocomplete:B(e)}),t.language.data.of({closeBrackets:{brackets:[`{`]}}),V])}export{q as liquid};
1
+ import{C as e,D as t,F as n,L as r,R as i,Ut as a,V as o,n as s,r as c,s as l,u,v as d,vt as f}from"./dist-CYzOYk_e.js";import{n as p}from"./dist-CYRrdlae.js";var m=1,h=2,g=3,_=183,v=4,y=184,b=5,x=185,S=6;function C(e){return e>=65&&e<=90||e>=97&&e<=122}var w=new s(e=>{let t=e.pos;for(;;){let{next:n}=e;if(n<0)break;if(n==123){let n=e.peek(1);if(n==123){if(e.pos>t)break;e.acceptToken(m,2);return}if(n==37){if(e.pos>t)break;let n=2,r=2;for(;;){let t=e.peek(n);if(t==32||t==10)++n;else if(t==35)for(++n;;){let t=e.peek(n);if(t<0||t==10)break;n++}else if(t==45&&r==2)r=++n;else{let i=t==101&&e.peek(n+1)==110&&e.peek(n+2)==100;e.acceptToken(i?g:h,r);return}}}}if(e.advance(),n==10)break}e.pos>t&&e.acceptToken(_)});function T(e,t,n){return new s(r=>{let i=r.pos;for(;;){let{next:t}=r;if(t==123&&r.peek(1)==37){let t=2;for(;;t++){let e=r.peek(t);if(e!=32&&e!=10)break}let a=``;for(;;t++){let e=r.peek(t);if(!C(e))break;a+=String.fromCharCode(e)}if(a==e){if(r.pos>i)break;r.acceptToken(n,2);break}}else if(t<0)break;if(r.advance(),t==10)break}r.pos>i&&r.acceptToken(t)})}var E=T(`endcomment`,x,b),D=T(`endraw`,y,v),O=new s(e=>{if(e.next==35){for(e.advance();!(e.next==10||e.next<0||(e.next==37||e.next==125)&&e.peek(1)==125);)e.advance();e.acceptToken(S)}}),k={__proto__:null,contains:34,or:38,and:38,true:52,false:52,empty:54,forloop:57,tablerowloop:59,continue:61,in:135,with:199,for:201,as:203,if:239,endif:243,unless:249,endunless:253,elsif:257,else:261,case:267,endcase:271,when:275,endfor:283,tablerow:289,endtablerow:293,break:297,cycle:303,echo:307,render:311,include:315,assign:319,capture:325,endcapture:329,increment:333,decrement:337},A={__proto__:null,if:90,endif:94,elsif:98,else:102,unless:108,endunless:112,case:118,endcase:122,when:126,for:132,endfor:140,tablerow:146,endtablerow:150,break:154,continue:158,cycle:162,comment:168,endcomment:174,raw:180,endraw:186,echo:190,render:194,include:206,assign:210,capture:216,endcapture:220,increment:224,decrement:228,liquid:232},j=c.deserialize({version:14,states:"MfQYOPOOOOOP'#F}'#F}OhOaO'#CdOyQhO'#CfO!hQxO'#DUO$ROPO'#DXO$aOPO'#DbO$oOPO'#DgO$}OPO'#DnO%]OPO'#DuO%kOSO'#EQO%pOQO'#EWO%uOPO'#EjO&TQxO'#F{OOOP'#Gj'#GjOOOP'#G`'#G`OOOP'#F|'#F|QYOPOOOOOP-E9{-E9{OOQW'#Cg'#CgO&nQ!jO,59QO&uQ!jO'#GaOyQhO'#CtOOQW'#Ge'#GeOOQW'#Gf'#GfOOQW'#Gg'#GgOOQW'#Ga'#GaOOOP,59p,59pO*SQhO,59pOyQhO,59tOyQhO,59xO*^QhO,59zOyQhO,59}OyQhO,5:SOyQhO,5:WO!cQhO,5:ZO!cQhO,5:bO*cQhO,5:fO*hQhO,5:hO*mQhO,5:jO*rQhO,5:mO*wQhO,5:sOyQhO,5:xOyQhO,5:zOyQhO,5;QOyQhO,5;SOyQhO,5;VOyQhO,5;ZOyQhO,5;]O,WQhO,5;_O,_OPO'#CdOOOP,59s,59sO$ROPO,59sO,mQxO'#F{OOOP,59|,59|O$aOPO,59|O,uQxO'#F{OOOP,5:R,5:RO$oOPO,5:RO,}QxO'#F{OOOP,5:Y,5:YO$}OPO,5:YO-VQxO'#F{OOOP,5:a,5:aO%]OPO,5:aO-_QxO'#F{OOOS'#GT'#GTO-gOSO'#ETO-oOSO,5:lOOOQ'#GU'#GUO-tOQO'#EZO-|OQO,5:rOOOP,5;U,5;UO%uOPO,5;UO.RQxO'#F{O.ZQhO,5<gOOOP-E9z-E9zO.`Q#|O,59SOyQhO,59VOyQhO,59WOyQhO,59WO.eQhO'#C}OOQW'#GO'#GOO.jQhO1G.lOOOP1G.l1G.lOyQhO,59WOyQhO,59[O/TQ!jO,59`O/[Q!jO'#CgO1kQ!jO'#GiO3gQhO'#DROOQW'#Gi'#GiO3lQhO'#GhO5fQhO1G/[OOOP1G/[1G/[O5fQhO1G/[O5nQ!jO1G/`O5uQ!jO1G/dOOOP1G/f1G/fO5|Q!jO1G/iO6TQ!jO1G/nO6[Q!jO1G/rO6fQhO1G/uO6fQhO1G/|OOOP1G0Q1G0QOOOP1G0S1G0SO6kQhO1G0UOOOS1G0X1G0XOOOQ1G0_1G0_O6vQ!jO1G0dO6}Q!jO1G0fO7_Q!jO1G0lO7fQ!jO1G0nO7mQ!jO1G0qO7tQ!jO1G0uO7{Q!jO1G0wOOQW'#Gm'#GmOOQW'#Gp'#GpOyQhO'#EvO8SQhO'#EuOOQW'#Gr'#GrOyQhO'#E{O8ZQhO'#EzOOQW'#Gt'#GtOyQhO'#FPOOQW'#Gu'#GuOOQW'#FR'#FROOQW'#Gv'#GvOyQhO'#FUO8bQhO'#FTOOQW'#Gx'#GxOyQhO'#FYO!cQhO'#F]O8iQhO'#F[OOQW'#Gz'#GzO!cQhO'#FaO8pQhO'#F`OOQW'#G|'#G|OOQW'#Fe'#FeOOQW'#Fg'#FgOOQW'#G}'#G}O8wQhO'#FhOOQW'#HO'#HOOyQhO'#FjOOQW'#HP'#HPOyQhO'#FlOOQW'#HQ'#HQOyQhO'#FnOOQW'#HR'#HROyQhO'#FpOOQW'#HS'#HSOyQhO'#FsO8|QhO'#FrOOQW'#HU'#HUOyQhO'#FwOOQW'#HV'#HVOyQhO'#FyOOQW'#Go'#GoOOQW'#GW'#GWO9TQhO1G0yOOOP1G0y1G0yOOOP1G/_1G/_O9[QhO,59vOOOP1G/h1G/hO9aQhO,5:POOOP1G/m1G/mO9fQhO,5:UOOOP1G/t1G/tO9kQhO,5:_OOOP1G/{1G/{O9pQhO,5:dOOOS-E:R-E:ROOOP1G0W1G0WO9uQxO'#EUOOOQ-E:S-E:SOOOP1G0^1G0^O9zQxO'#E[OOOP1G0p1G0pO:PQhO,5;XOOOP1G2R1G2ROOQW1G.n1G.nO:UQ!jO1G.qO<uQ!jO1G.rO<|Q!jO1G.rOOQW'#DP'#DPO?[QhO,59iOOQW-E9|-E9|OOOP7+$W7+$WOAUQ!jO1G.rOA]Q!jO1G.vOyQhO1G.zOyQhO,59mO)eQhO'#GPOCkQhO,5=SOOOP7+$v7+$vOEeQhO7+$vOOOP7+$z7+$zOOOP7+%O7+%OOOOP7+%T7+%TOOOP7+%Y7+%YOyQhO'#GQOEmQhO7+%^OOOP7+%^7+%^OOQW'#Gk'#GkOyQhO7+%aOyQhO7+%hOEuQhO'#GSOEzQhO7+%pOOOP7+%p7+%pOFSQhO7+%pOFXQhO7+&OOOOP7+&O7+&OOOQW'#Gl'#GlO!cQhO'#EbOyQhO'#EbOOQW'#GV'#GVOFaQhO7+&QOOOP7+&Q7+&QOOOP7+&W7+&WOFoQhO7+&YOOOP7+&Y7+&YOOOP7+&]7+&]OOOP7+&a7+&aOOOP7+&c7+&cOFwQ!jO,5;bOOQW'#Gq'#GqOOQW'#Ex'#ExOOQW,5;a,5;aO8SQhO,5;aOHWQ!jO,5;gOOQW'#Gs'#GsOOQW'#E}'#E}OOQW,5;f,5;fO8ZQhO,5;fOIgQ!jO,5;kOKYQ!jO,5;pOOQW'#Gw'#GwOOQW'#FW'#FWOOQW,5;o,5;oO8bQhO,5;oOLiQ!jO,5;tO6fQhO,5;wOOQW'#Gy'#GyOOQW'#F^'#F^OOQW,5;v,5;vO8iQhO,5;vO6fQhO,5;{OOQW'#G{'#G{OOQW'#Fc'#FcOOQW,5;z,5;zO8pQhO,5;zON_QhO,5<SO!!UQ!jO,5<UO!#wQ!jO,5<WO!%pQ!jO,5<YO!'cQ!jO,5<[O!)UQ!jO,5<_OOQW'#HT'#HTOOQW'#Fu'#FuOOQW,5<^,5<^O8|QhO,5<^O!*eQ!jO,5<cO!,WQ!jO,5<eOOQW-E:U-E:UOOOP7+&e7+&eOOOP1G/b1G/bOOOP1G/k1G/kOOOP1G/p1G/pOOOP1G/y1G/yOOOP1G0O1G0OO!-yQhO,5:pO!.OQhO,5:vOOOP1G0s1G0sOOQW7+$]7+$]O)eQhO1G/TO!.TQ!jO7+$fO!.[Q!jO1G/XOOQW,5<k,5<kOOQW-E9}-E9}OOOP<<Hb<<HbO!0WQ!jO,5<lOOQW-E:O-E:OOOOP<<Hx<<HxO!1|Q!jO<<H{O!2WQ!jO<<ISOOQW,5<n,5<nOOQW-E:Q-E:QOOOP<<I[<<I[O!2bQhO<<I[OOOP<<Ij<<IjO!2jQhO,5:|O!2oQ!jO,5:|OOQW-E:T-E:TOOOP<<Il<<IlOOOP<<It<<ItOOQW1G0{1G0{OOQW1G1Q1G1QOOQW1G1Z1G1ZO!4kQhO1G1`OyQhO1G1cOOQW1G1b1G1bOyQhO1G1gOOQW1G1f1G1fO!6_QhO1G1nO!8RQhO1G1nO!8WQhO1G1pOOQW'#GX'#GXO!9zQhO1G1rO!;qQhO1G1vOOQW1G1x1G1xOOOP1G0[1G0[OOOP1G0b1G0bOOQW7+$o7+$oOOQW<<HQ<<HQOOQW'#DS'#DSO!=eQhO'#DrOOQW'#GR'#GRO!?OQhOAN>gOOOPAN>gAN>gO!?WQhOAN>nOOOPAN>nAN>nO!?`QhOAN>vOOOPAN>vAN>vOyQhO1G0hOOQW'#Gn'#GnO!cQhO1G0hO!?hQ!jO7+&}O!@zQ!jO7+'RO!B^QhO7+'YOOQW-E:V-E:VOyQhO,5:^OOQW-E:P-E:POOOPG24RG24ROOOPG24YG24YOOOPG24bG24bO!DQQ!jO7+&SOOQW7+&S7+&SO!EyQhO<<JiO!GZQhO<<JmO!HkQhO<<JtO!J_Q!jO1G/x",stateData:"!Kw~O%ROSUOS~OPROQSOR]O$}PO~O$}POPWXQWXRWX$|WX~OgfOjjOkjOlgOmhOniOojOpjO%UcO~OylOzkO}mO!RnO!ToO!WpO!]qO!arO!dsO!ktO!ouO!qvO!swO!vxO!|yO#RzO#T{O#Z|O#]}O#`!OO#d!PO#f!QO#h!RO~OPROQSOR!VO$}PO~OPROQSOR!YO$}PO~OPROQSOR!]O$}PO~OPROQSOR!`O$}PO~OPROQSOR!cO$}PO~O%P!dO~O%O!gO~OPROQSOR!lO$}PO~Oy!mO~O]!oOa!wOb!qOc!rOr!sO%W!pO~OX!vO~P&YOe!xOX%TX]%TXa%TXb%TXc%TXr%TX%W%TXi%TXw%TXz%TX#V%TX#W%TX%V%TXn%TX#k%TX#m%TX#p%TX#t%TX#v%TX#y%TX#}%TX$U%TX$Y%TX$]%TX$_%TX$a%TX$c%TX$e%TX$h%TX$l%TX$n%TX#r%TX#{%TX$j%TXf%TX%U%TX#X%TX$R%TX$W%TX~OgfOjjOkjOlgOmhOniOojOpjO%U!zO~Or!sOz#QO~P)eOz#UO~Oz#[O~Oz#]O~Oo#^O~Oz#_O~Oz#`O~OniO#W#hO#k#iO#p#lO#t#oO#v#qO#y#sO#}#vO$U#zO$Y#}O$]$QO$_$SO$a$UO$c$WO$e$YO$h$[O$l$_O$n$aO~Oz$fO~P*|O$}POPWXQWXRWX~Oy!mO!P$hO~Oy!mO!Y$jO~Oy!mO!_$lO~Oy!mO!h$nO~Oy!mO!m$pO~O%P!dOT!wX~OT$sO~O%O!gOS!}X~OS$vO~Oy!mO#b$xO~Oz$yO~O^$zO~O%U%OO~OX%ROr!sO~O]!oOa!wOb!qOc!rO%W!pO~Oi%UO~P.rO]ZXaZXbZXcZXeZXrZXtvXwZXzZX%WZXXZXnZX#WZX#kZX#pZX#tZX#vZX#yZX#}ZX$UZX$YZX$]ZX$_ZX$aZX$cZX$eZX$hZX$lZX$nZX#mZX#rZX#{ZX$RZX$WZX$jZX~Or%]Xw%]Xz%]XX%]Xn%]X#W%]X#k%]X#p%]X#t%]X#v%]X#y%]X#}%]X$U%]X$Y%]X$]%]X$_%]X$a%]X$c%]X$e%]X$h%]X$l%]X$n%]X#m%]X#r%]X#{%]X$R%]X$W%]X$j%]X~P.rOt%VO~Ow%WOr%[Xz%[XX%[Xn%[X#W%[X#k%[X#p%[X#t%[X#v%[X#y%[X#}%[X$U%[X$Y%[X$]%[X$_%[X$a%[X$c%[X$e%[X$h%[X$l%[X$n%[X#m%[X#r%[X#{%[X$R%[X$W%[X$j%[X~Or!sOz%YO~Oz%[O~P.rOz%]O~P.rOz%^O~P.rOz%_O~P.rOw%`Oz%bO~P.rO!e%cO~Ot%iOw%fOz%hO~Oz%kO~P&YOw%mOz%qO#V%lO#W#hO~P.rOz%rO~P.rOz%tO~P&YOz%uO~P.rOz%vO~P.rOz%wO~P.rO#m%yO~P*|O#r&OO~P*|O#{&UO~P*|O$R&[O~P*|O$W&aO~P*|Oo&eO~O$j&kO~P*|Oz&rO~P*|Oz&sO~Oz&tO~Oz&uO~Oz&vO~Oz&wO~O!y&xO~O#P&yO~Oz&zO~O%V&{O~P.rO]!oO%W!pOX`ia`ic`ir`ii`iw`iz`i#V`i#W`i%V`in`i#k`i#m`i#p`i#t`i#v`i#y`i#}`i$U`i$Y`i$]`i$_`i$a`i$c`i$e`i$h`i$l`i$n`i#r`i#{`i$j`if`i%U`i#X`i$R`i$W`i~Ob`i~P:]OX`ir`ii`iw`iz`i#V`i#W`i%V`in`i#k`i#m`i#p`i#t`i#v`i#y`i#}`i$U`i$Y`i$]`i$_`i$a`i$c`i$e`i$h`i$l`i$n`i#r`i#{`i$j`if`i%U`i#X`i$R`i$W`i~P.rOt&|OXqarqazqanqa#Wqa#kqa#pqa#tqa#vqa#yqa#}qa$Uqa$Yqa$]qa$_qa$aqa$cqa$eqa$hqa$lqa$nqa#mqa#rqa#{qa$Rqa$Wqa$jqa~Ob!qO~P:]OXdirdiidiwdizdi#Vdi#Wdi%Vdindi#kdi#mdi#pdi#tdi#vdi#ydi#}di$Udi$Ydi$]di$_di$adi$cdi$edi$hdi$ldi$ndi#rdi#{di$jdifdi%Udi#Xdi$Rdi$Wdi~P.rOw%WOr%[az%[aX%[an%[a#W%[a#k%[a#p%[a#t%[a#v%[a#y%[a#}%[a$U%[a$Y%[a$]%[a$_%[a$a%[a$c%[a$e%[a$h%[a$l%[a$n%[a#m%[a#r%[a#{%[a$R%[a$W%[a$j%[a~Or!sOz'RO~Ow%`Oz'UO~Oo'XO~Ow%fOz'ZO~Oo'[O~Or!sOz']O~Ow%mOz'aO#V%lO#W#hO~Or!sOz'bO~On#ja#W#ja#k#ja#m#ja#p#ja#t#ja#v#ja#y#ja#}#ja$U#ja$Y#ja$]#ja$_#ja$a#ja$c#ja$e#ja$h#ja$l#ja$n#ja~P.rOn#oa#W#oa#k#oa#p#oa#r#oa#t#oa#v#oa#y#oa#}#oa$U#oa$Y#oa$]#oa$_#oa$a#oa$c#oa$e#oa$h#oa$l#oa$n#oa~P.rOn#saz#sa#W#sa#k#sa#p#sa#t#sa#v#sa#y#sa#}#sa$U#sa$Y#sa$]#sa$_#sa$a#sa$c#sa$e#sa$h#sa$l#sa$n#sa#m#sa#r#sa#{#sa$R#sa$W#sa$j#sa~P.rOn#xa#W#xa#k#xa#p#xa#t#xa#v#xa#y#xa#{#xa#}#xa$U#xa$Y#xa$]#xa$_#xa$a#xa$c#xa$e#xa$h#xa$l#xa$n#xa~P.rOw%`On#|az#|a#W#|a#k#|a#p#|a#t#|a#v#|a#y#|a#}#|a$U#|a$Y#|a$]#|a$_#|a$a#|a$c#|a$e#|a$h#|a$l#|a$n#|a#m#|a#r#|a#{#|a$R#|a$W#|a$j#|a~P.rOt'lOw%fOn$[az$[a#W$[a#k$[a#p$[a#t$[a#v$[a#y$[a#}$[a$U$[a$Y$[a$]$[a$_$[a$a$[a$c$[a$e$[a$h$[a$l$[a$n$[a#m$[a#r$[a#{$[a$R$[a$W$[a$j$[a~On$^az$^a#W$^a#k$^a#p$^a#t$^a#v$^a#y$^a#}$^a$U$^a$Y$^a$]$^a$_$^a$a$^a$c$^a$e$^a$h$^a$l$^a$n$^a#m$^a#r$^a#{$^a$R$^a$W$^a$j$^a~P&YOw%mO#V%lO#W#hOn$`az$`a#k$`a#p$`a#t$`a#v$`a#y$`a#}$`a$U$`a$Y$`a$]$`a$_$`a$a$`a$c$`a$e$`a$h$`a$l$`a$n$`a#m$`a#r$`a#{$`a$R$`a$W$`a$j$`a~P.rOn$baz$ba#W$ba#k$ba#p$ba#t$ba#v$ba#y$ba#}$ba$U$ba$Y$ba$]$ba$_$ba$a$ba$c$ba$e$ba$h$ba$l$ba$n$ba#m$ba#r$ba#{$ba$R$ba$W$ba$j$ba~P.rOn$daz$da#W$da#k$da#p$da#t$da#v$da#y$da#}$da$U$da$Y$da$]$da$_$da$a$da$c$da$e$da$h$da$l$da$n$da#m$da#r$da#{$da$R$da$W$da$j$da~P&YOn$ga#W$ga#k$ga#p$ga#t$ga#v$ga#y$ga#}$ga$U$ga$Y$ga$]$ga$_$ga$a$ga$c$ga$e$ga$h$ga$j$ga$l$ga$n$ga~P.rOn$kaz$ka#W$ka#k$ka#p$ka#t$ka#v$ka#y$ka#}$ka$U$ka$Y$ka$]$ka$_$ka$a$ka$c$ka$e$ka$h$ka$l$ka$n$ka#m$ka#r$ka#{$ka$R$ka$W$ka$j$ka~P.rOn$maz$ma#W$ma#k$ma#p$ma#t$ma#v$ma#y$ma#}$ma$U$ma$Y$ma$]$ma$_$ma$a$ma$c$ma$e$ma$h$ma$l$ma$n$ma#m$ma#r$ma#{$ma$R$ma$W$ma$j$ma~P.rOz'rO~Oz'sO~Of'uO~P.rOruiwuizuiXuinui#Wui#kui#pui#tui#vui#yui#}ui$Uui$Yui$]ui$_ui$aui$cui$eui$hui$lui$nui#mui#rui#{ui$Rui$Wui$jui~P.rOw$taz$tan$ta#W$ta#k$ta#p$ta#t$ta#v$ta#y$ta#}$ta$U$ta$Y$ta$]$ta$_$ta$a$ta$c$ta$e$ta$h$ta$l$ta$n$ta#m$ta#r$ta#{$ta$R$ta$W$ta$j$ta~P.rOz'zO%U'vO~P.rOz'|O%U'vO~P.rOw%fOz(OO~Ot(PO~O#X(QOw#Uaz#Ua#V#Ua#W#Uan#Ua#k#Ua#p#Ua#t#Ua#v#Ua#y#Ua#}#Ua$U#Ua$Y#Ua$]#Ua$_#Ua$a#Ua$c#Ua$e#Ua$h#Ua$l#Ua$n#Ua#m#Ua#r#Ua#{#Ua$R#Ua$W#Ua$j#Ua~P.rOw%`On#|iz#|i#W#|i#k#|i#p#|i#t#|i#v#|i#y#|i#}#|i$U#|i$Y#|i$]#|i$_#|i$a#|i$c#|i$e#|i$h#|i$l#|i$n#|i#m#|i#r#|i#{#|i$R#|i$W#|i$j#|i~Ow%fOn$[iz$[i#W$[i#k$[i#p$[i#t$[i#v$[i#y$[i#}$[i$U$[i$Y$[i$]$[i$_$[i$a$[i$c$[i$e$[i$h$[i$l$[i$n$[i#m$[i#r$[i#{$[i$R$[i$W$[i$j$[i~Oo(UO~Or!sOn$^iz$^i#W$^i#k$^i#p$^i#t$^i#v$^i#y$^i#}$^i$U$^i$Y$^i$]$^i$_$^i$a$^i$c$^i$e$^i$h$^i$l$^i$n$^i#m$^i#r$^i#{$^i$R$^i$W$^i$j$^i~Ow%mO#V%lO#W#hOn$`iz$`i#k$`i#p$`i#t$`i#v$`i#y$`i#}$`i$U$`i$Y$`i$]$`i$_$`i$a$`i$c$`i$e$`i$h$`i$l$`i$n$`i#m$`i#r$`i#{$`i$R$`i$W$`i$j$`i~Or!sOn$diz$di#W$di#k$di#p$di#t$di#v$di#y$di#}$di$U$di$Y$di$]$di$_$di$a$di$c$di$e$di$h$di$l$di$n$di#m$di#r$di#{$di$R$di$W$di$j$di~Ot(WOz!fX%U!fXn!fX#W!fX#k!fX#p!fX#t!fX#v!fX#y!fX#}!fX$R!fX$U!fX$Y!fX$]!fX$_!fX$a!fX$c!fX$e!fX$h!fX$l!fX$n!fX$W!fX~Oz(YO%U'vO~Oz(ZO%U'vO~Ow%fOz([O~O%U'vOn$Pq#W$Pq#k$Pq#p$Pq#t$Pq#v$Pq#y$Pq#}$Pq$R$Pq$U$Pq$Y$Pq$]$Pq$_$Pq$a$Pq$c$Pq$e$Pq$h$Pq$l$Pq$n$Pq~P.rO%U'vOn$Tq#W$Tq#k$Tq#p$Tq#t$Tq#v$Tq#y$Tq#}$Tq$U$Tq$W$Tq$Y$Tq$]$Tq$_$Tq$a$Tq$c$Tq$e$Tq$h$Tq$l$Tq$n$Tq~P.rOw%fOn$[qz$[q#W$[q#k$[q#p$[q#t$[q#v$[q#y$[q#}$[q$U$[q$Y$[q$]$[q$_$[q$a$[q$c$[q$e$[q$h$[q$l$[q$n$[q#m$[q#r$[q#{$[q$R$[q$W$[q$j$[q~Ow#Uqz#Uq#V#Uq#W#Uqn#Uq#k#Uq#p#Uq#t#Uq#v#Uq#y#Uq#}#Uq$U#Uq$Y#Uq$]#Uq$_#Uq$a#Uq$c#Uq$e#Uq$h#Uq$l#Uq$n#Uq#m#Uq#r#Uq#{#Uq$R#Uq$W#Uq$j#Uq~P.rO%U'vOn$Py#W$Py#k$Py#p$Py#t$Py#v$Py#y$Py#}$Py$R$Py$U$Py$Y$Py$]$Py$_$Py$a$Py$c$Py$e$Py$h$Py$l$Py$n$Py~O%U'vOn$Ty#W$Ty#k$Ty#p$Ty#t$Ty#v$Ty#y$Ty#}$Ty$U$Ty$W$Ty$Y$Ty$]$Ty$_$Ty$a$Ty$c$Ty$e$Ty$h$Ty$l$Ty$n$Ty~Ow%fOn$[yz$[y#W$[y#k$[y#p$[y#t$[y#v$[y#y$[y#}$[y$U$[y$Y$[y$]$[y$_$[y$a$[y$c$[y$e$[y$h$[y$l$[y$n$[y#m$[y#r$[y#{$[y$R$[y$W$[y$j$[y~Oz!fi%U!fin!fi#W!fi#k!fi#p!fi#t!fi#v!fi#y!fi#}!fi$R!fi$U!fi$Y!fi$]!fi$_!fi$a!fi$c!fi$e!fi$h!fi$l!fi$n!fi$W!fi~P.rO",goto:"Ah%zPPPPPPPP%{P%{&]'oPP'o'oPPP'oPPP'oPPPPPPPP(oP)PP)S)XP)hPP)h)xP*YP)hP)hP)h*`P*pP)h*vP+WP)hP)h+^PP+n+xP)h,OP,`P)hP)hP)hP)h,fP,v,yP)h,|P-^-aP)hP)hP-dPPP)hP)hP)h-lP-|P)hP)hP)hP.S.dP.tP.S.zP/[P.SP.SP.S/bP/rP.SP.S/x0YP.S0`P0pP.SP.S.SP.SP.SP.SP.SP.S0vP1WP.SP.SP)h1^1|2d3S3Y3d3v4Y4`4f4l5[PPPPPP5b5rPPP'o'o8h9x:O%{:V:c:i;P;S;d;t;x<Y<^<n=O=`=d=t=x>Y>^>n?O?`?p@Q@b@r@vAWm_OTUVWX[a!U!X![!_!b!k!zeRflmnpqrz{|}!O!P!Q!p!q!r!w!x#j#m#p#t#w$T$V$X$Z$]$`$b%U%V%W%`%d%e%n&|'g'i(P(WQ#YsQ#ZtQ&Z#xQ&`#{Q'^%mR(^(R!{jRflmnpqrz{|}!O!P!Q!p!q!r!w!x#j#m#p#t#w$T$V$X$Z$]$`$b%U%V%W%`%d%e%n&|'g'i(P(Wm!tdl!u#P#R#a#d%Z%j%s&f&i'm'pR%P!sV!}l%W&|U!|l%W&|a'w'V'W'y'{(S(T(_(`m^OTUVWX[a!U!X![!_!b!kmTOTUVWX[a!U!X![!_!b!kQ!TTR$g!UmUOTUVWX[a!U!X![!_!b!kQ!WUR$i!XmVOTUVWX[a!U!X![!_!b!kQ!ZVR$k![mWOTUVWX[a!U!X![!_!b!ka'x'V'W'y'{(S(T(_(`Q!^WR$m!_mXOTUVWX[a!U!X![!_!b!kQ!aXR$o!bmYOTUVWX[a!U!X![!_!b!kR!fYR$r!fmZOTUVWX[a!U!X![!_!b!kR!iZR$u!iS%o#b%pT'n&g'om[OTUVWX[a!U!X![!_!b!kQ!j[R$w!km$c!R#k#n#u#y#|$^$e%|&R&X&_&d&nm#k!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ%{#kR'c%|m#n!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&Q#nR'd&Rm#u!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&W#uR'e&Xm#y!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&^#yR'h&_m#|!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&c#|R'j&dm$^!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ&m$^R'q&nQaOQ!UTQ!XUQ![VQ!_WQ!bXQ!k[_!na!U!X![!_!b!kSQOaSbQ!Si!STUVWX[!U!X![!_!b!kQ!udQ#Pl^%Q!u#P%Z%j%s'm'pQ%Z#RQ%j#aQ%s#dQ'm&fR'p&iQ%X#OR'Q%XQ%a#XS'T%a'fR'f&YQ'y'VQ'{'WW(X'y'{(_(`Q(_(SR(`(TQ%g#^W'Y%g'k'}(aQ'k&eQ'}'[R(a(UQ!eYR$q!eQ!hZR$t!hQ%p#bR'`%pQ$e!RQ%|#kQ&R#nQ&X#uQ&_#yQ&d#|Q&n$^_&q$e%|&R&X&_&d&nQ'o&gR(V'om`OTUVWX[a!U!X![!_!b!kQdRQ!yfU!{l%W&|Q#SmQ#TnQ#VpQ#WqQ#XrQ#azQ#b{Q#c|Q#d}Q#e!OQ#f!PQ#g!QQ${!pQ$|!qQ$}!rQ%S!wQ%T!xQ%x#jQ%}#mQ&S#pQ&T#tQ&Y#wQ&f$TQ&g$VQ&h$XQ&i$ZQ&j$]Q&o$`Q&p$bQ&}%UQ'O%VQ'S%`Q'V%dQ'W%eQ'_%nQ(S'gQ(T'iQ(](PR(b(W!zjRflmnpqrz{|}!O!P!Q!p!q!r!w!x#j#m#p#t#w$T$V$X$Z$]$`$b%U%V%W%`%d%e%n&|'g'i(P(Wm$P!R#k#n#u#y#|$^$e%|&R&X&_&d&nQ#RlR't&|S#Ol&|R'P%WQ%d#YQ%e#ZQ'g&ZR'i&`X%n#b%p&g'ol#x!R#k#n#u#y#|$^$e%|&R&X&_&d&nX%n#b%p&g'oR(R'_m$d!R#k#n#u#y#|$^$e%|&R&X&_&d&nm#j!R#k#n#u#y#|$^$e%|&R&X&_&d&nT%z#k%|m#m!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&P#n&Rm#p!R#k#n#u#y#|$^$e%|&R&X&_&d&nm#r!R#k#n#u#y#|$^$e%|&R&X&_&d&nm#t!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&V#u&Xm#w!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&]#y&_m#{!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&b#|&dm$O!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$R!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$T!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$V!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$X!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$Z!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$]!R#k#n#u#y#|$^$e%|&R&X&_&d&nT&l$^&nm$`!R#k#n#u#y#|$^$e%|&R&X&_&d&nm$b!R#k#n#u#y#|$^$e%|&R&X&_&d&n",nodeNames:`⚠ {{ {% {% {% {% InlineComment Template Text }} Interpolation VariableName MemberExpression . PropertyName SubscriptExpression BinaryExpression contains CompareOp LogicOp AssignmentExpression AssignOp ) ( RangeExpression .. BooleanLiteral empty forloop tablerowloop continue StringLiteral NumberLiteral Filter | FilterName : NamedArgument ParameterName , Tag TagName %} IfDirective Tag if EndTag endif Tag elsif Tag else UnlessDirective Tag unless EndTag endunless CaseDirective Tag case EndTag endcase Tag when ForDirective Tag for in Parameter EndTag endfor TableDirective Tag tablerow EndTag endtablerow Tag break Tag continue Tag cycle Comment Tag comment CommentText EndTag endcomment RawDirective Tag raw RawText EndTag endraw Tag echo Tag render RenderParameter with for as Tag include Tag assign CaptureDirective Tag capture EndTag endcapture Tag increment Tag decrement Tag liquid IfDirective Tag if EndTag endif UnlessDirective Tag unless EndTag endunless Tag elsif Tag else CaseDirective Tag case EndTag endcase Tag when ForDirective Tag EndTag endfor TableDirective Tag tablerow EndTag endtablerow Tag break Tag Tag cycle Tag echo Tag render Tag include Tag assign CaptureDirective Tag capture EndTag endcapture Tag increment Tag decrement EndTag`,maxTerm:225,nodeProps:[[`closedBy`,1,`}}`,-4,2,3,4,5,`%}`,23,`)`],[`openedBy`,9,`{{`,22,`(`,42,`{%`],[`group`,-13,11,12,15,16,20,24,26,27,28,29,30,31,32,`Expression`]],skippedNodes:[0,6],repeatNodeCount:12,tokenData:")e~RmXY!|YZ!|]^!|pq!|qr#_rs#juv$[wx$gxy%Syz%X{|%^|}&x}!O&}!O!P'Z!Q![&g![!]'k!^!_'p!_!`'x!`!a'p!c!}(Q!}#O(y#P#Q)O#R#S(Q#T#o(Q#p#q)T#q#r)Y%W;'S(Q;'S;:j(s<%lO(Q~#RS%R~XY!|YZ!|]^!|pq!|~#bP!_!`#e~#jOb~~#mUOY#jZr#jrs$Ps;'S#j;'S;=`$U<%lO#j~$UOo~~$XP;=`<%l#j~$_P#q#r$b~$gOz~~$jUOY$gZw$gwx$Px;'S$g;'S;=`$|<%lO$g~%PP;=`<%l$g~%XOg~~%^Of~P%aQ!O!P%g!Q![&gP%jP!Q![%mP%rRpP!Q![%m!g!h%{#X#Y%{P&OR{|&X}!O&X!Q![&_P&[P!Q![&_P&dPpP!Q![&_P&lSpP!O!P%g!Q![&g!g!h%{#X#Y%{~&}Ow~~'QRuv$[!O!P%g!Q![&g~'`Q]S!O!P'f!Q![%m~'kOi~~'pOt~~'uPb~!_!`#e~'}Pe~!_!`#e_(ZW^WyQ%UT}!O(Q!Q![(Q!c!}(Q#R#S(Q#T#o(Q%W;'S(Q;'S;:j(s<%lO(Q_(vP;=`<%l(Q~)OO%W~~)TO%V~~)YOr~~)]P#q#r)`~)eOX~",tokenizers:[w,D,E,O,0,1,2,3],topRules:{Template:[0,7]},dynamicPrecedences:{193:1,194:1,195:1,199:1,200:1,201:1,202:1,204:1,205:1,206:1,207:1,208:1,209:1,210:1,211:1,212:1,213:1,214:1,215:1,216:1,217:1,218:1,219:1,220:1,221:1,222:1,223:1,224:1,225:1},specialized:[{term:190,get:e=>k[e]||-1},{term:41,get:e=>A[e]||-1}],tokenPrec:0});function M(e,t){return e.split(` `).map(e=>({label:e,type:t}))}var N=M(`abs append at_least at_most capitalize ceil compact concat date default divided_by downcase escape escape_once first floor join last lstrip map minus modulo newline_to_br plus prepend remove remove_first replace replace_first reverse round rstrip size slice sort sort_natural split strip strip_html strip_newlines sum times truncate truncatewords uniq upcase url_decode url_encode where`,`function`),P=M(`cycle comment endcomment raw endraw echo increment decrement liquid if elsif else endif unless endunless case endcase for endfor tablerow endtablerow break continue assign capture endcapture render include`,`keyword`),F=M(`empty forloop tablerowloop in with as`,`keyword`),I=M(`first index index0 last length rindex`,`property`),L=M(`col col0 col_first col_last first index index0 last length rindex rindex0 row`,`property`);function R(e){let{state:t,pos:r}=e,i=n(t).resolveInner(r,-1).enterUnfinishedNodesBefore(r),a=i.childBefore(r)?.name||i.name;if(i.name==`FilterName`)return{type:`filter`,node:i};if(e.explicit&&a==`|`)return{type:`filter`};if(i.name==`TagName`)return{type:`tag`,node:i};if(e.explicit&&a==`{%`)return{type:`tag`};if(i.name==`PropertyName`&&i.parent.name==`MemberExpression`)return{type:`property`,node:i,target:i.parent};if(i.name==`.`&&i.parent.name==`MemberExpression`)return{type:`property`,target:i.parent};if(i.name==`MemberExpression`&&a==`.`)return{type:`property`,target:i};if(i.name==`VariableName`)return{type:`expression`,from:i.from};let o=e.matchBefore(/[\w\u00c0-\uffff]+$/);return o?{type:`expression`,from:o.from}:e.explicit&&i.name!=`CommentText`&&i.name!=`StringLiteral`&&i.name!=`NumberLiteral`&&i.name!=`InlineComment`?{type:`expression`}:null}function z(e,t,n,r){let i=[];for(;;){let n=t.getChild(`Expression`);if(!n)return[];if(n.name==`VariableName`||n.name==`forloop`||n.name==`tablerowloop`){let t=e.sliceDoc(n.from,n.to);if(t==`forloop`)return i.length?[]:I;if(t==`tablerowloop`)return i.length?[]:L;i.unshift(t);break}if(n.name==`MemberExpression`){let r=n.getChild(`PropertyName`);r&&i.unshift(e.sliceDoc(r.from,r.to)),t=n}else if(n.name==`SubscriptExpression`){let r=n.getChildren(`Expression`)[1];i.unshift(r?.name==`StringLiteral`?e.sliceDoc(r.from+1,r.to-1):`[]`),t=n}else return[]}return r?r(i,e,n):[]}function B(e={}){let t=e.filters?e.filters.concat(N):N,n=e.tags?e.tags.concat(P):P,r=e.variables?e.variables.concat(F):F,{properties:i}=e;return e=>{let a=R(e);if(!a)return null;let o=a.from??(a.node?a.node.from:e.pos),s;return s=a.type==`filter`?t:a.type==`tag`?n:a.type==`expression`?r:z(e.state,a.target,e,i),s.length?{options:s,from:o,validFor:/^[\w\u00c0-\uffff]*$/}:null}}var V=o.inputHandler.of((e,t,n,r)=>r!=`%`||t!=n||e.state.doc.sliceString(t-1,n+1)!=`{}`?!1:(e.dispatch(e.state.changeByRange(e=>({changes:{from:e.from,to:e.to,insert:`%%`},range:f.cursor(e.from+1)})),{scrollIntoView:!0,userEvent:`input.type`}),!0));function H(e){return t=>{let n=e.test(t.textAfter);return t.lineIndent(t.node.from)+(n?0:t.unit)}}var U=l.define({name:`liquid`,parser:j.configure({props:[r({"cycle comment endcomment raw endraw echo increment decrement liquid in with as":i.keyword,"empty forloop tablerowloop":i.atom,"if elsif else endif unless endunless case endcase for endfor tablerow endtablerow break continue":i.controlKeyword,"assign capture endcapture":i.definitionKeyword,contains:i.operatorKeyword,"render include":i.moduleKeyword,VariableName:i.variableName,TagName:i.keyword,FilterName:i.function(i.variableName),PropertyName:i.propertyName,ParameterName:i.attributeName,CompareOp:i.compareOperator,AssignOp:i.definitionOperator,LogicOp:i.logicOperator,NumberLiteral:i.number,StringLiteral:i.string,BooleanLiteral:i.bool,InlineComment:i.lineComment,CommentText:i.blockComment,"{% %} {{ }}":i.brace,"[ ]":i.bracket,"( )":i.paren,".":i.derefOperator,", .. : |":i.punctuation}),t.add({Tag:d({closing:`%}`}),"UnlessDirective ForDirective TablerowDirective CaptureDirective":H(/^\s*(\{%-?\s*)?end\w/),IfDirective:H(/^\s*(\{%-?\s*)?(endif|else|elsif)\b/),CaseDirective:H(/^\s*(\{%-?\s*)?(endcase|when)\b/)}),e.add({"UnlessDirective ForDirective TablerowDirective CaptureDirective IfDirective CaseDirective RawDirective Comment"(e){let t=e.firstChild,n=e.lastChild;return!t||t.name!=`Tag`?null:{from:t.to,to:n.name==`EndTag`?n.from:e.to}}})]}),languageData:{commentTokens:{line:`#`},indentOnInput:/^\s*{%-?\s*(?:end|elsif|else|when|)$/}}),W=p();function G(e){return U.configure({wrap:a(t=>t.type.isTop?{parser:e.parser,overlay:e=>e.name==`Text`||e.name==`RawText`}:null)},`liquid`)}var K=G(W.language);function q(e={}){let t=e.base||W,n=t.language==W.language?K:G(t.language);return new u(n,[t.support,n.data.of({autocomplete:B(e)}),t.language.data.of({closeBrackets:{brackets:[`{`]}}),V])}export{q as liquid};
@@ -0,0 +1 @@
1
+ import{a as e}from"./editor-DPcGvSPy.js";export{e as markdown};