@popcorn245/cornfield-components 0.52.1 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/chunks/around-BcnegEdS.js +99 -0
- package/dist/chunks/connection-KDiWvV19.js +23 -0
- package/dist/chunks/{engine-BmXtSISH.js → engine-xmHJvQY9.js} +1188 -1186
- package/dist/chunks/{layers-Bj4Tluxe.js → layers-ho10a2y7.js} +48 -48
- package/dist/chunks/{map-BZRFOYkt.js → map-DbfPgQRe.js} +385 -385
- package/dist/chunks/node-panel-CC8UrSzJ.js +410 -0
- package/dist/chunks/panel-review-ih7RlfkH.js +884 -0
- package/dist/chunks/review-pieces-DtRxCDMr.js +2523 -0
- package/dist/chunks/{review-source-CK5tYIqk.js → review-source-CmbwaPCM.js} +1 -1
- package/dist/chunks/scope-2m2VmJXn.js +185 -0
- package/dist/chunks/scope-proposal-T06ndbin.js +116 -0
- package/dist/chunks/{sheets-D-sMZzSs.js → sheets-BWANwtZP.js} +7 -2
- package/dist/chunks/source-address-DXanAREm.js +57 -0
- package/dist/chunks/{status-DI5QLlAp.js → status-DM-iIEsg.js} +4 -3
- package/dist/corn-changes.js +43 -0
- package/dist/corn-decision.js +52 -0
- package/dist/corn-layers.js +275 -1
- package/dist/corn-map.js +125 -1
- package/dist/corn-node-panel.js +42 -1
- package/dist/corn-proposal.js +50 -0
- package/dist/corn-review.js +425 -1
- package/dist/corn-scope.js +33 -9
- package/dist/corn-search.js +484 -1
- package/dist/index.js +11 -8
- package/dist/manifest.json +95 -70
- package/dist/tokens.css +6 -0
- package/dist/types/components.d.ts +111 -5
- package/dist/types/corn-changes.d.ts +2 -0
- package/dist/types/corn-decision.d.ts +2 -0
- package/dist/types/corn-proposal.d.ts +2 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/version.json +1 -1
- package/package.json +17 -5
- package/dist/chunks/around-BFqYTZ0K.js +0 -78
- package/dist/chunks/corn-layers-Cni5rISZ.js +0 -275
- package/dist/chunks/corn-map-B2-YxiEL.js +0 -125
- package/dist/chunks/corn-node-panel-BkvJThlp.js +0 -42
- package/dist/chunks/corn-review-5wf7AT4o.js +0 -2900
- package/dist/chunks/corn-search-CXs5d06S.js +0 -484
- package/dist/chunks/node-panel-BdvFvWCE.js +0 -1291
- package/dist/chunks/scope-CqPbHcKL.js +0 -137
- package/dist/chunks/source-address-C70zNPIj.js +0 -79
|
@@ -1,1291 +0,0 @@
|
|
|
1
|
-
import { t as e } from "./rolldown-runtime-CGnMp29N.js";
|
|
2
|
-
import { At as t, Ct as n, Dn as r, Dt as i, En as a, Et as o, Jt as s, Kt as c, Lt as l, Ot as u, St as d, Tn as f, an as p, bt as m, dn as h, fn as g, in as _, jn as v, jt as y, kt as b, nn as x, on as S, qt as C, rn as ee, sn as w, wt as T, xn as E, xt as D, yn as O, yt as k, zt as A } from "./engine-BmXtSISH.js";
|
|
3
|
-
import { a as j, c as te, d as ne, i as re, n as M, o as ie, u as ae } from "./sheets-D-sMZzSs.js";
|
|
4
|
-
var N = 0;
|
|
5
|
-
function P(e, t = 5) {
|
|
6
|
-
if (e.length <= t + 1) return e.join("");
|
|
7
|
-
let n = `hx-more-${++N}`, r = e.length - t;
|
|
8
|
-
return `${e.slice(0, t).join("")}<div class="hx-more" id="${n}" hidden>${e.slice(t).join("")}</div><button data-corn="more" data-corn-kind="quiet" type="button" class="hx-btn hx-btn--quiet hx-textact hx-more-btn" data-more="${n}" data-rest="${r}" aria-expanded="false" aria-controls="${n}">and ${r} more</button>`;
|
|
9
|
-
}
|
|
10
|
-
function oe(e) {
|
|
11
|
-
let t = e.closest && e.closest("[data-more]");
|
|
12
|
-
if (!t) return !1;
|
|
13
|
-
let n = t.previousElementSibling, r = n && n.id === t.dataset.more ? n : null, i = t.getAttribute("aria-expanded") !== "true";
|
|
14
|
-
return r && (r.hidden = !i), t.setAttribute("aria-expanded", String(i)), t.textContent = i ? "Show fewer" : `and ${t.dataset.rest} more`, !0;
|
|
15
|
-
}
|
|
16
|
-
// ../explorer/engine/flow-ui.js
|
|
17
|
-
function se(e, t) {
|
|
18
|
-
let { state: n } = e, r = (e) => (n.nodes.find((t) => t.id === e) || { label: e }).label, i = n.edges.filter((e) => e.kind === "flow" && (e.from === t.id || e.to === t.id)), a = (e, t, n) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${e}</div><div class="hx-fact-v">${P(t.map((e) => `<div class="hx-line"><span><span class="hx-name">${c(r(n ? e.to : e.from))}</span> · ${c(e.label)}${e.status === "live" ? "" : " <span class=\"hx-warn\">(proposed)</span>"}</span></div>`))}</div></div>` : "";
|
|
19
|
-
return a("Sends to", i.filter((e) => e.from === t.id), !0) + a("Gets from", i.filter((e) => e.to === t.id && e.from !== t.id), !1);
|
|
20
|
-
}
|
|
21
|
-
// ../explorer/corn-state.js
|
|
22
|
-
var F = Object.freeze([
|
|
23
|
-
"open",
|
|
24
|
-
"merged",
|
|
25
|
-
"closed",
|
|
26
|
-
"draft",
|
|
27
|
-
"queued",
|
|
28
|
-
"running",
|
|
29
|
-
"requested",
|
|
30
|
-
"claimed",
|
|
31
|
-
"working",
|
|
32
|
-
"waiting",
|
|
33
|
-
"done",
|
|
34
|
-
"failed",
|
|
35
|
-
"stopped",
|
|
36
|
-
"success",
|
|
37
|
-
"failure",
|
|
38
|
-
"added",
|
|
39
|
-
"changed",
|
|
40
|
-
"removed",
|
|
41
|
-
"edit",
|
|
42
|
-
"sent-back"
|
|
43
|
-
]), I = Object.freeze([
|
|
44
|
-
"added",
|
|
45
|
-
"changed",
|
|
46
|
-
"removed",
|
|
47
|
-
"edit"
|
|
48
|
-
]);
|
|
49
|
-
Object.freeze([
|
|
50
|
-
"requested",
|
|
51
|
-
"claimed",
|
|
52
|
-
"working",
|
|
53
|
-
"waiting",
|
|
54
|
-
"done",
|
|
55
|
-
"failed",
|
|
56
|
-
"stopped"
|
|
57
|
-
]);
|
|
58
|
-
var ce = Object.freeze({
|
|
59
|
-
quiet: "waiting",
|
|
60
|
-
"stop-requested": "stopped",
|
|
61
|
-
neutral: "done",
|
|
62
|
-
skipped: "done",
|
|
63
|
-
cancelled: "stopped",
|
|
64
|
-
approved: "success",
|
|
65
|
-
unreviewed: "waiting",
|
|
66
|
-
changed: "waiting",
|
|
67
|
-
missing: "failure",
|
|
68
|
-
allowed: "success",
|
|
69
|
-
refused: "failure",
|
|
70
|
-
mismatch: "failure",
|
|
71
|
-
pending: "running",
|
|
72
|
-
ok: "success",
|
|
73
|
-
bad: "failure",
|
|
74
|
-
stale: "waiting",
|
|
75
|
-
off: "stopped",
|
|
76
|
-
error: "failure",
|
|
77
|
-
idle: "running"
|
|
78
|
-
});
|
|
79
|
-
function L(e) {
|
|
80
|
-
let t = String(e || "");
|
|
81
|
-
return ce[t] || (F.includes(t) && !I.includes(t) ? t : "");
|
|
82
|
-
}
|
|
83
|
-
function le(e) {
|
|
84
|
-
let t = String(e || "");
|
|
85
|
-
return I.includes(t) ? t : "";
|
|
86
|
-
}
|
|
87
|
-
function R(e) {
|
|
88
|
-
let t = le(e);
|
|
89
|
-
return t ? ` data-corn-state="${t}"` : "";
|
|
90
|
-
}
|
|
91
|
-
function z(e) {
|
|
92
|
-
let t = L(e);
|
|
93
|
-
return t ? ` data-corn-state="${t}"` : "";
|
|
94
|
-
}
|
|
95
|
-
Object.freeze({
|
|
96
|
-
requested: "<circle cx=\"6\" cy=\"6\" r=\"4.2\" stroke-dasharray=\"2 1.8\"/>",
|
|
97
|
-
queued: "<circle cx=\"6\" cy=\"6\" r=\"4.2\" stroke-dasharray=\"2 1.8\"/>",
|
|
98
|
-
claimed: "<circle cx=\"6\" cy=\"6\" r=\"4.2\"/><circle cx=\"6\" cy=\"6\" r=\"1.4\" fill=\"currentColor\" stroke=\"none\"/>",
|
|
99
|
-
working: "<path class=\"hx-state-spin\" d=\"M6 1.8a4.2 4.2 0 1 1-4.2 4.2\"/>",
|
|
100
|
-
running: "<path class=\"hx-state-spin\" d=\"M6 1.8a4.2 4.2 0 1 1-4.2 4.2\"/>",
|
|
101
|
-
waiting: "<path d=\"M6 1.2L11 10.4H1Z\" stroke-linejoin=\"round\"/><path d=\"M6 4.6v2.7M6 8.6v.1\"/>",
|
|
102
|
-
done: "<path d=\"M2 6.4l2.6 2.6L10 3.4\"/>",
|
|
103
|
-
success: "<path d=\"M2 6.4l2.6 2.6L10 3.4\"/>",
|
|
104
|
-
failed: "<path d=\"M2.6 2.6l6.8 6.8M9.4 2.6L2.6 9.4\"/>",
|
|
105
|
-
failure: "<path d=\"M2.6 2.6l6.8 6.8M9.4 2.6L2.6 9.4\"/>",
|
|
106
|
-
stopped: "<rect x=\"2.4\" y=\"2.4\" width=\"7.2\" height=\"7.2\" rx=\"1\" fill=\"currentColor\"/>",
|
|
107
|
-
neutral: "<path d=\"M2.4 6h7.2\"/>",
|
|
108
|
-
skipped: "<path d=\"M2.4 6h7.2\"/>",
|
|
109
|
-
cancelled: "<circle cx=\"6\" cy=\"6\" r=\"4.2\"/><path d=\"M3 9L9 3\"/>",
|
|
110
|
-
"sent-back": "<path d=\"M4.6 2.2L2 4.8l2.6 2.6\"/><path d=\"M2.2 4.8H7a2.8 2.8 0 0 1 0 5.6H4.6\"/>"
|
|
111
|
-
}), Object.freeze([
|
|
112
|
-
["code", "Code: a branch and a pull request"],
|
|
113
|
-
["summary", "Summary of the conversation"],
|
|
114
|
-
["brief", "A brief for another run"],
|
|
115
|
-
["proposal", "A proposal drafted from the thread"]
|
|
116
|
-
]), Object.freeze({
|
|
117
|
-
merged: "done",
|
|
118
|
-
closed: "stopped",
|
|
119
|
-
quiet: "waiting",
|
|
120
|
-
"stop-requested": "stopped"
|
|
121
|
-
});
|
|
122
|
-
function ue(e) {
|
|
123
|
-
let t = Math.max(0, Math.round(e / 1e3));
|
|
124
|
-
return t < 60 ? `${t} s` : t < 3600 ? `${Math.floor(t / 60)} min` : `${Math.floor(t / 3600)} h`;
|
|
125
|
-
}
|
|
126
|
-
Object.freeze([
|
|
127
|
-
"minutes",
|
|
128
|
-
"turns",
|
|
129
|
-
"cost",
|
|
130
|
-
"tokens"
|
|
131
|
-
]), Object.freeze([
|
|
132
|
-
{
|
|
133
|
-
key: "decide",
|
|
134
|
-
title: "toDecide"
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
key: "agent",
|
|
138
|
-
title: "withAgent"
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
key: "approved",
|
|
142
|
-
title: "approvedGroup"
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
key: "drafts",
|
|
146
|
-
title: "drafts"
|
|
147
|
-
}
|
|
148
|
-
]), Object.freeze([
|
|
149
|
-
{
|
|
150
|
-
key: "needs",
|
|
151
|
-
title: "needsYou"
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
key: "motion",
|
|
155
|
-
title: "inMotion"
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
key: "finished",
|
|
159
|
-
title: "finished"
|
|
160
|
-
}
|
|
161
|
-
]), Object.freeze([
|
|
162
|
-
"to-decide",
|
|
163
|
-
"changed",
|
|
164
|
-
"sent-back",
|
|
165
|
-
"approved",
|
|
166
|
-
"draft-pr",
|
|
167
|
-
"local",
|
|
168
|
-
"unknown"
|
|
169
|
-
]), Object.freeze({
|
|
170
|
-
"to-decide": "To decide",
|
|
171
|
-
changed: "Changed since approved",
|
|
172
|
-
"sent-back": "Sent back",
|
|
173
|
-
approved: "Approved",
|
|
174
|
-
"draft-pr": "Draft PR",
|
|
175
|
-
local: "Local",
|
|
176
|
-
unknown: "Review state unknown"
|
|
177
|
-
}), Object.freeze({
|
|
178
|
-
"to-decide": "waiting",
|
|
179
|
-
changed: "waiting",
|
|
180
|
-
"sent-back": "sent-back",
|
|
181
|
-
approved: "success",
|
|
182
|
-
"draft-pr": "draft",
|
|
183
|
-
local: "draft",
|
|
184
|
-
unknown: "failure"
|
|
185
|
-
});
|
|
186
|
-
function de(e) {
|
|
187
|
-
let t = e && e.report && typeof e.report.note == "string" ? e.report.note.replace(/\s+/g, " ").trim() : "", n = t.length > 90 ? `${t.slice(0, 89).trimEnd()}\u2026` : t;
|
|
188
|
-
return `A run is waiting on you${n ? `: ${n}` : ""}`;
|
|
189
|
-
}
|
|
190
|
-
// ../explorer/proposal-model.js
|
|
191
|
-
var fe = [
|
|
192
|
-
"before",
|
|
193
|
-
"diff",
|
|
194
|
-
"after"
|
|
195
|
-
], pe = [
|
|
196
|
-
"added",
|
|
197
|
-
"changed",
|
|
198
|
-
"removed"
|
|
199
|
-
];
|
|
200
|
-
function me(e) {
|
|
201
|
-
let t = he({
|
|
202
|
-
...e,
|
|
203
|
-
scenarios: 0
|
|
204
|
-
}).filter((e) => e.mark).map((e) => e.text.replace(/^\+/, ""));
|
|
205
|
-
return t.length ? t.join(" · ") : "No changes";
|
|
206
|
-
}
|
|
207
|
-
function he(e) {
|
|
208
|
-
let t = (t) => e?.[t] || 0, n = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`, r = (r) => {
|
|
209
|
-
let i = e?.nodes?.[r] || 0, a = e?.edges?.[r] || 0;
|
|
210
|
-
return !e?.nodes || i + a !== t(r) ? `${r === "added" ? "+" : ""}${t(r)} ${r}` : `${[i && n(i, "node"), a && n(a, "edge")].filter(Boolean).join(", ")} ${r}`;
|
|
211
|
-
}, i = pe.filter((e) => t(e) > 0).map((e) => ({
|
|
212
|
-
mark: e,
|
|
213
|
-
text: r(e)
|
|
214
|
-
}));
|
|
215
|
-
return t("scenarios") > 0 && i.push({
|
|
216
|
-
mark: null,
|
|
217
|
-
text: `${t("scenarios")} ${t("scenarios") === 1 ? "scenario" : "scenarios"}`
|
|
218
|
-
}), i.length ? i : [{
|
|
219
|
-
mark: null,
|
|
220
|
-
text: "No changes"
|
|
221
|
-
}];
|
|
222
|
-
}
|
|
223
|
-
var ge = (e) => `${e === "before" ? "Before" : e === "after" ? "After" : "Diff"} view`, _e = (e, t) => `${t}, ${String(e).toLowerCase()}. The map is on it.`, ve = /^[A-Za-z0-9][A-Za-z0-9._-]*$/, ye = 200, be = (e) => typeof e == "string" && e.length <= ye && ve.test(e);
|
|
224
|
-
function xe(e) {
|
|
225
|
-
let t = String(e ?? ""), n = t.length > 60 ? `${t.slice(0, 59)}\u2026` : t;
|
|
226
|
-
return n.trim() ? `\u201c${n}\u201d is not a proposal's name.` : "That is not a proposal's name.";
|
|
227
|
-
}
|
|
228
|
-
function Se(e) {
|
|
229
|
-
return e == null ? "" : typeof e == "string" ? e : JSON.stringify(e);
|
|
230
|
-
}
|
|
231
|
-
var Ce = [
|
|
232
|
-
"mark",
|
|
233
|
-
"editOp",
|
|
234
|
-
"before",
|
|
235
|
-
"why",
|
|
236
|
-
"x",
|
|
237
|
-
"y",
|
|
238
|
-
"r",
|
|
239
|
-
"baseR",
|
|
240
|
-
"degree",
|
|
241
|
-
"scaleDelta",
|
|
242
|
-
"color",
|
|
243
|
-
"from",
|
|
244
|
-
"to"
|
|
245
|
-
];
|
|
246
|
-
function we(e) {
|
|
247
|
-
return y(e) === "added" ? Object.keys(e).filter((t) => !Ce.includes(t) && e[t] !== void 0).map((t) => ({
|
|
248
|
-
field: t,
|
|
249
|
-
before: "",
|
|
250
|
-
after: Se(e[t])
|
|
251
|
-
})) : e.mark === "changed" && e.before ? Object.keys(e.before).map((t) => ({
|
|
252
|
-
field: t,
|
|
253
|
-
before: Se(e.before[t]),
|
|
254
|
-
after: Se(e[t])
|
|
255
|
-
})) : [];
|
|
256
|
-
}
|
|
257
|
-
var B = {
|
|
258
|
-
added: "Added",
|
|
259
|
-
changed: "Changed",
|
|
260
|
-
removed: "Removed",
|
|
261
|
-
edit: "Your edit"
|
|
262
|
-
};
|
|
263
|
-
function Te(e) {
|
|
264
|
-
if (!t(e)) return "";
|
|
265
|
-
let n = we(e).map((t) => e.mark === "changed" ? `<div class="hx-change" data-corn="field-change"><span class="hx-change-field">${c(t.field)}</span><span class="hx-change-before">${c(t.before) || "<em>nothing</em>"}</span><span class="hx-change-arrow" aria-hidden="true">→</span><span class="hx-change-after">${c(t.after) || "<em>nothing</em>"}</span></div>` : `<div class="hx-change" data-corn="field-change"><span class="hx-change-field">${c(t.field)}</span><span class="hx-change-after">${c(t.after)}</span></div>`).join("");
|
|
266
|
-
return `<div class="hx-sec hx-proposal-sec hx-proposal-sec--${c(e.mark)}" data-proposal-mark="${c(e.mark)}" data-corn="section">
|
|
267
|
-
<strong class="hx-strong"><span class="hx-mark-dot hx-mark-dot--${c(e.mark)}" data-corn="mark-dot"${R(e.mark)}></span>${c(e.mark === "edit" ? `${e.editOp === "removed" ? "Removed" : "Added"} by your edit` : `${B[e.mark] || e.mark} by this proposal`)}</strong>
|
|
268
|
-
${e.why ? `<div class="hx-why">${c(e.why)}</div>` : ""}
|
|
269
|
-
${n}
|
|
270
|
-
</div>`;
|
|
271
|
-
}
|
|
272
|
-
var Ee = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`;
|
|
273
|
-
function De(e) {
|
|
274
|
-
if (!Array.isArray(e) || e.length === 0) return "no checks";
|
|
275
|
-
let t = (t) => e.filter((e) => t.includes(e.state)).length, n = t(["failure"]), r = t(["cancelled"]), i = t(["running", "queued"]), a = [];
|
|
276
|
-
return n && a.push(`${Ee(n, "check")} failed`), r && a.push(`${Ee(r, "check")} cancelled`), i && a.push(`${Ee(i, "check")} running`), a.length ? a.join(", ") : e.length === 1 ? "1 check passed" : `all ${e.length} checks passed`;
|
|
277
|
-
}
|
|
278
|
-
function V(e) {
|
|
279
|
-
let t = typeof e == "string" ? /^pull\/([1-9]\d{0,8})$/.exec(e) : null;
|
|
280
|
-
return t ? Number(t[1]) : null;
|
|
281
|
-
}
|
|
282
|
-
function Oe(e) {
|
|
283
|
-
let t = V(e);
|
|
284
|
-
return t ? `PR #${t}` : !e || e === "checkout" ? "the checkout" : `worktree ${e}`;
|
|
285
|
-
}
|
|
286
|
-
function ke(e, t = null, n = null) {
|
|
287
|
-
let r = V(e);
|
|
288
|
-
if (!r) {
|
|
289
|
-
let t = !e || e === "checkout" ? "in the checkout" : `in worktree ${e}`;
|
|
290
|
-
return {
|
|
291
|
-
text: `Local draft \u00b7 ${t}`,
|
|
292
|
-
href: null,
|
|
293
|
-
state: "draft",
|
|
294
|
-
label: `This is a local draft, ${t}, not a pull request`
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
let i = [`PR #${r}`], a = t ? t.state === "merged" || t.state === "closed" ? t.state : typeof t.draft == "boolean" ? t.draft ? "draft" : "open" : "" : "";
|
|
298
|
-
return a && i.push(a), Array.isArray(n) && i.push(De(n)), {
|
|
299
|
-
text: i.join(" · "),
|
|
300
|
-
href: t && typeof t.url == "string" ? t.url : null,
|
|
301
|
-
state: a,
|
|
302
|
-
label: `Reviewing spec pull request: ${i.join(", ")}`
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
function Ae(e, t, n = null) {
|
|
306
|
-
return t ? V(t) || t === "checkout" || n && n.has(t) && ve.test(t) ? `There is no proposal called ${e} in ${Oe(t)}.` : `There is no proposal called ${e}. This link's source is not a PR, the checkout or a worktree.` : `There is no proposal called ${e}.`;
|
|
307
|
-
}
|
|
308
|
-
function je(e) {
|
|
309
|
-
let t = new URLSearchParams(e || "");
|
|
310
|
-
if (!t.has("proposal")) return null;
|
|
311
|
-
let n = t.get("proposal") || "";
|
|
312
|
-
return ve.test(n) ? null : n.trim() ? `This link does not name a proposal: ${xe(n)}` : "This link does not name a proposal.";
|
|
313
|
-
}
|
|
314
|
-
function Me(e, t, n) {
|
|
315
|
-
return Array.isArray(e) ? e.filter((e) => e && e.slug === t && e.source !== n && !e.error).sort((e, t) => +!!V(t.source) - !!V(e.source)).map((e) => ({
|
|
316
|
-
slug: e.slug,
|
|
317
|
-
source: e.source,
|
|
318
|
-
label: V(e.source) ? `Open the copy in PR #${V(e.source)}${e.pull && e.pull.draft ? " (draft)" : ""}` : `Open the copy ${e.source === "checkout" ? "in the checkout" : `in worktree ${e.source}`}`
|
|
319
|
-
})) : [];
|
|
320
|
-
}
|
|
321
|
-
function Ne(e, t = !1) {
|
|
322
|
-
let n = Array.isArray(e) ? e : [];
|
|
323
|
-
if (!n.length) return "";
|
|
324
|
-
let r = (e) => n.filter((t) => t && e.includes(t.op)).length, i = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`, a = [];
|
|
325
|
-
r(["add-node"]) && a.push(`+${i(r(["add-node"]), "node")}`), r(["add-edge"]) && a.push(`+${i(r(["add-edge"]), "edge")}`), r(["remove-node"]) && a.push(`\u2212${i(r(["remove-node"]), "node")}`), r(["remove-edge"]) && a.push(`\u2212${i(r(["remove-edge"]), "edge")}`);
|
|
326
|
-
let o = r([
|
|
327
|
-
"add-step",
|
|
328
|
-
"reword-step",
|
|
329
|
-
"delete-step",
|
|
330
|
-
"move-step"
|
|
331
|
-
]);
|
|
332
|
-
o && a.push(`${i(o, "step")} changed`);
|
|
333
|
-
let s = n.length - r([
|
|
334
|
-
"add-node",
|
|
335
|
-
"add-edge",
|
|
336
|
-
"remove-node",
|
|
337
|
-
"remove-edge",
|
|
338
|
-
"add-step",
|
|
339
|
-
"reword-step",
|
|
340
|
-
"delete-step",
|
|
341
|
-
"move-step"
|
|
342
|
-
]);
|
|
343
|
-
return s > 0 && a.push(i(s, "other edit")), `yours: ${a.join(", ")}${t ? " (hidden)" : ""}`;
|
|
344
|
-
}
|
|
345
|
-
// ../core/proposal.js
|
|
346
|
-
var Pe = [
|
|
347
|
-
"version",
|
|
348
|
-
"spec",
|
|
349
|
-
"title",
|
|
350
|
-
"summary",
|
|
351
|
-
"nodes",
|
|
352
|
-
"edges",
|
|
353
|
-
"mockups",
|
|
354
|
-
"scenarios"
|
|
355
|
-
], Fe = [
|
|
356
|
-
"node",
|
|
357
|
-
"path",
|
|
358
|
-
"title"
|
|
359
|
-
], Ie = [
|
|
360
|
-
"png",
|
|
361
|
-
"jpg",
|
|
362
|
-
"jpeg",
|
|
363
|
-
"webp",
|
|
364
|
-
"svg",
|
|
365
|
-
"html"
|
|
366
|
-
], Le = [
|
|
367
|
-
"id",
|
|
368
|
-
"title",
|
|
369
|
-
"steps",
|
|
370
|
-
"stepMs",
|
|
371
|
-
"linkNodes",
|
|
372
|
-
"actor",
|
|
373
|
-
"down"
|
|
374
|
-
], Re = [
|
|
375
|
-
"node",
|
|
376
|
-
"edge",
|
|
377
|
-
"text",
|
|
378
|
-
"ms",
|
|
379
|
-
"actor",
|
|
380
|
-
"at",
|
|
381
|
-
"check",
|
|
382
|
-
"expect"
|
|
383
|
-
], ze = [
|
|
384
|
-
"GET",
|
|
385
|
-
"POST",
|
|
386
|
-
"PUT",
|
|
387
|
-
"PATCH",
|
|
388
|
-
"DELETE"
|
|
389
|
-
], Be = [
|
|
390
|
-
"read",
|
|
391
|
-
"write",
|
|
392
|
-
"delete"
|
|
393
|
-
], Ve = [
|
|
394
|
-
"own",
|
|
395
|
-
"household",
|
|
396
|
-
"others",
|
|
397
|
-
"shared-read",
|
|
398
|
-
"shared-write"
|
|
399
|
-
], He = ["allowed", "refused"], Ue = /^[a-z0-9]+(?:-[a-z0-9]+)*$/, We = `live-room-<id>, live-floor-<id> or live-device-<kind>-<id> (kind one of ${k.join(", ")})`, Ge = [
|
|
400
|
-
"add",
|
|
401
|
-
"change",
|
|
402
|
-
"remove"
|
|
403
|
-
], Ke = ["mark", "before"], qe = [
|
|
404
|
-
"mark",
|
|
405
|
-
"before",
|
|
406
|
-
"why"
|
|
407
|
-
], Je = [
|
|
408
|
-
"from",
|
|
409
|
-
"to",
|
|
410
|
-
"kind",
|
|
411
|
-
"flow"
|
|
412
|
-
], H = (e) => typeof e == "object" && !!e && !Array.isArray(e), U = (e) => typeof e == "string" && e.trim() !== "", W = (e) => e === void 0 ? e : JSON.parse(JSON.stringify(e)), G = (e) => Array.isArray(e) ? e : [], Ye = (e) => typeof e == "number" && Number.isFinite(e) && e > 0;
|
|
413
|
-
function Xe(e, t) {
|
|
414
|
-
if (e === t) return !0;
|
|
415
|
-
if (!e || !t || typeof e != "object" || typeof t != "object" || Array.isArray(e) !== Array.isArray(t)) return !1;
|
|
416
|
-
let n = Object.keys(e);
|
|
417
|
-
return n.length === Object.keys(t).length && n.every((n) => Xe(e[n], t[n]));
|
|
418
|
-
}
|
|
419
|
-
function Ze(e) {
|
|
420
|
-
if (typeof e != "string" || e.trim() === "") return "\"path\" must be the file's path, relative to the proposals folder.";
|
|
421
|
-
if (e.length > 200) return "\"path\" is at most 200 characters.";
|
|
422
|
-
if (/[\\\u0000-\u001f:%?#]/.test(e)) return "\"path\" has a character a plain relative path does not (a backslash, a colon, a control character, %, ? or #).";
|
|
423
|
-
if (e.startsWith("/")) return "\"path\" is relative to the proposals folder; it does not start with a slash.";
|
|
424
|
-
let t = e.split("/");
|
|
425
|
-
if (t.some((e) => e === "" || e === "." || e === "..")) return "\"path\" stays inside the proposals folder: no \"..\", no \".\" and no empty parts.";
|
|
426
|
-
if (t.some((e) => e.startsWith("."))) return "\"path\" has a hidden part (one that starts with a dot).";
|
|
427
|
-
let n = t[t.length - 1].split(".").length > 1 ? t[t.length - 1].split(".").pop().toLowerCase() : "";
|
|
428
|
-
return Ie.includes(n) ? null : `A mockup is one of: ${Ie.join(", ")}.`;
|
|
429
|
-
}
|
|
430
|
-
function Qe(e) {
|
|
431
|
-
if (!H(e) || !Array.isArray(e.mockups)) return [];
|
|
432
|
-
let t = [];
|
|
433
|
-
return e.mockups.slice(0, 40).forEach((e, n) => {
|
|
434
|
-
H(e) && U(e.node) && U(e.title) && Ze(e.path) === null && t.push({
|
|
435
|
-
index: n,
|
|
436
|
-
node: e.node,
|
|
437
|
-
path: e.path,
|
|
438
|
-
title: e.title.trim()
|
|
439
|
-
});
|
|
440
|
-
}), t;
|
|
441
|
-
}
|
|
442
|
-
function K(e) {
|
|
443
|
-
return `${e.from}|${e.to}|${e.kind === "flow" ? `flow:${e.flow}` : e.kind || "own"}`;
|
|
444
|
-
}
|
|
445
|
-
var $e = (e) => ({
|
|
446
|
-
from: e.parent,
|
|
447
|
-
to: e.id
|
|
448
|
-
});
|
|
449
|
-
function et(e, t) {
|
|
450
|
-
let r = [], a = (e, t, n) => r.push(n ? {
|
|
451
|
-
path: e,
|
|
452
|
-
message: t,
|
|
453
|
-
state: n
|
|
454
|
-
} : {
|
|
455
|
-
path: e,
|
|
456
|
-
message: t
|
|
457
|
-
});
|
|
458
|
-
if (!H(t)) return a("", "A proposal is a JSON object."), r;
|
|
459
|
-
for (let e of Object.keys(t)) Pe.includes(e) || a(e, `Unknown key "${e}". A proposal has: ${Pe.join(", ")}.`);
|
|
460
|
-
t.version !== 1 && a("version", `"version" must be the number 1 (got ${JSON.stringify(t.version)}).`), U(t.title) || a("title", "\"title\" must be a non-empty string."), U(t.summary) || a("summary", "\"summary\" must be a non-empty string: the one sentence the maintainer reads first."), t.spec !== void 0 && !U(t.spec) && a("spec", "\"spec\" must be the spec number as a string, like \"0013\".");
|
|
461
|
-
let s = (e) => {
|
|
462
|
-
let n = t[e];
|
|
463
|
-
if (n === void 0) return {
|
|
464
|
-
add: [],
|
|
465
|
-
change: [],
|
|
466
|
-
remove: []
|
|
467
|
-
};
|
|
468
|
-
if (!H(n)) return a(e, `"${e}" must be an object with add, change and remove lists.`), {
|
|
469
|
-
add: [],
|
|
470
|
-
change: [],
|
|
471
|
-
remove: []
|
|
472
|
-
};
|
|
473
|
-
let r = {};
|
|
474
|
-
for (let t of Object.keys(n)) Ge.includes(t) || a(`${e}.${t}`, `Unknown key "${t}" in "${e}". Use add, change or remove.`);
|
|
475
|
-
for (let t of Ge) n[t] === void 0 ? r[t] = [] : Array.isArray(n[t]) ? r[t] = n[t] : (a(`${e}.${t}`, `"${e}.${t}" must be a list.`), r[t] = []);
|
|
476
|
-
return r;
|
|
477
|
-
}, c = s("nodes"), l = s("edges"), f = new Map(G(e?.nodes).map((e) => [e.id, e])), p = new Set(G(e?.edges).map(K)), h = /* @__PURE__ */ new Map();
|
|
478
|
-
c.add.forEach((e, t) => {
|
|
479
|
-
H(e) && U(e.id) && !h.has(e.id) && h.set(e.id, t);
|
|
480
|
-
});
|
|
481
|
-
let g = new Set(c.remove.filter((e) => H(e) && U(e.id)).map((e) => e.id)), _ = (e) => f.has(e) || h.has(e), v = /* @__PURE__ */ new Set(), y = /* @__PURE__ */ new Map();
|
|
482
|
-
c.add.forEach((e, t) => {
|
|
483
|
-
let r = `nodes.add[${t}]`;
|
|
484
|
-
if (!H(e)) return a(r, "An added node is an object with an id, a label and a type.");
|
|
485
|
-
U(e.id) ? f.has(e.id) ? a(`${r}.id`, `Node "${e.id}" already exists in the map. Use nodes.change to change it.`, "exists") : v.has(e.id) && a(`${r}.id`, `Node "${e.id}" is added twice.`) : a(`${r}.id`, "An added node needs an \"id\"."), U(e.id) && v.add(e.id), U(e.label) || a(`${r}.label`, "An added node needs a \"label\"."), U(e.type) ? T[e.type] ? e.type === "page" && U(e.label) && (e.label.startsWith("/") || a(`${r}.label`, `A page label "${e.label}" must start with a slash route (like "/meals"), as topology validate demands.`), e.label.includes(".html") && a(`${r}.label`, `A page label "${e.label}" must not contain ".html".`)) : a(`${r}.type`, `Unknown node type "${e.type}". Valid types: ${Object.keys(T).join(", ")}.`) : a(`${r}.type`, "An added node needs a \"type\".");
|
|
486
|
-
for (let t of Ke) t in e && a(`${r}.${t}`, `"${t}" is set when the proposal is applied; leave it out.`);
|
|
487
|
-
if (e.type === "device" && !k.includes(e.kind) && a(`${r}.kind`, `A device needs "kind", one of: ${k.join(", ")}.`), e.type === "external" && e.kind !== void 0 && !D.includes(e.kind) && a(`${r}.kind`, `An external's "kind" is one of: ${D.join(", ")} (or none, until the registry draws it).`), U(e.id) && T[e.type] && i(e)) {
|
|
488
|
-
let t = u(e.id), i = e.type === "device" ? `live-device-${k.includes(e.kind) ? e.kind : "<kind>"}-<id>` : `live-${e.type}-<id>`;
|
|
489
|
-
!t || t.type !== e.type ? a(`${r}.id`, [
|
|
490
|
-
"floor",
|
|
491
|
-
"room",
|
|
492
|
-
"device"
|
|
493
|
-
].includes(e.type) ? `"${e.id}" is a ${e.type} only the live layer draws${e.type === "device" ? " (no code file derives it)" : ""}: its id must be ${i}.` : `"${e.id}" starts with "${n}", which only the live layer's floors, rooms and devices use (${We}).`) : t.kind && k.includes(e.kind) && t.kind !== e.kind && a(`${r}.kind`, `"${e.id}" names the kind "${t.kind}" but the node says "${e.kind}".`);
|
|
494
|
-
}
|
|
495
|
-
e.parent !== void 0 && (U(e.parent) ? e.parent === e.id ? a(`${r}.parent`, "A node cannot be its own parent.") : _(e.parent) ? g.has(e.parent) ? a(`${r}.parent`, `Parent "${e.parent}" is a node this proposal removes.`) : U(e.id) && y.set(K($e(e)), `nodes.add[${t}].parent`) : a(`${r}.parent`, `Parent "${e.parent}" is in neither the map nor the added nodes.`, "dangling") : a(`${r}.parent`, "\"parent\" must be the id of a node."));
|
|
496
|
-
});
|
|
497
|
-
let x = /* @__PURE__ */ new Set();
|
|
498
|
-
c.change.forEach((e, t) => {
|
|
499
|
-
let n = `nodes.change[${t}]`;
|
|
500
|
-
if (!H(e)) return a(n, "A changed node is an object with an id, a set and a why.");
|
|
501
|
-
if (U(e.id) ? h.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is added by this proposal: change its entry in nodes.add instead.`) : f.has(e.id) ? x.has(e.id) && a(`${n}.id`, `Node "${e.id}" is changed twice: merge the two sets.`) : a(`${n}.id`, `Node "${e.id}" does not exist in the map, so it cannot be changed.`, "missing-target") : a(`${n}.id`, "A changed node needs an \"id\"."), U(e.id) && x.add(e.id), !H(e.set) || Object.keys(e.set).length === 0) a(`${n}.set`, "\"set\" must be an object of the fields to change.");
|
|
502
|
-
else {
|
|
503
|
-
"id" in e.set && a(`${n}.set.id`, "A change cannot set \"id\": it names the node."), "parent" in e.set && a(`${n}.set.parent`, "\"parent\" is not a node field: remove the ownership edge and add a new one.");
|
|
504
|
-
for (let t of qe) t in e.set && a(`${n}.set.${t}`, `"${t}" is set when the proposal is applied; leave it out of "set".`);
|
|
505
|
-
"type" in e.set && !T[e.set.type] && a(`${n}.set.type`, `Unknown node type "${e.set.type}". Valid types: ${Object.keys(T).join(", ")}.`);
|
|
506
|
-
}
|
|
507
|
-
U(e.why) || a(`${n}.why`, "A change needs a \"why\": the reason the maintainer reads.");
|
|
508
|
-
});
|
|
509
|
-
let S = /* @__PURE__ */ new Set();
|
|
510
|
-
c.remove.forEach((e, t) => {
|
|
511
|
-
let n = `nodes.remove[${t}]`;
|
|
512
|
-
if (!H(e)) return a(n, "A removed node is an object with an id and a why.");
|
|
513
|
-
U(e.id) ? h.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is added by this proposal: drop its entry from nodes.add instead of removing it.`) : f.has(e.id) ? S.has(e.id) ? a(`${n}.id`, `Node "${e.id}" is removed twice.`) : x.has(e.id) && a(`${n}.id`, `Node "${e.id}" is both changed and removed.`) : a(`${n}.id`, `Node "${e.id}" does not exist in the map, so it cannot be removed.`, "missing-target") : a(`${n}.id`, "A removed node needs an \"id\"."), U(e.id) && S.add(e.id), U(e.why) || a(`${n}.why`, "A removal needs a \"why\".");
|
|
514
|
-
});
|
|
515
|
-
let C = new Map(c.change.filter((e) => H(e) && U(e.id) && H(e.set)).map((e) => [e.id, e.set])), ee = new Map(c.add.filter((e) => H(e) && U(e.id)).map((e) => [e.id, e])), w = (e) => ee.get(e) || (f.has(e) ? {
|
|
516
|
-
...f.get(e),
|
|
517
|
-
...C.get(e) || {}
|
|
518
|
-
} : void 0), E = (e, t) => {
|
|
519
|
-
U(e.from) || a(`${t}.from`, "An edge needs a \"from\" node id."), U(e.to) || a(`${t}.to`, "An edge needs a \"to\" node id.");
|
|
520
|
-
let n = U(e.from) && U(e.to);
|
|
521
|
-
return e.kind !== void 0 && !m.includes(e.kind) && (a(`${t}.kind`, `Unknown edge kind "${e.kind}". Valid kinds: ${m.join(", ")} (or none, for ownership).`), n = !1), e.kind === "flow" ? d.includes(e.flow) || (a(`${t}.flow`, `A flow edge needs "flow", one of: ${d.join(", ")}.`), n = !1) : e.flow !== void 0 && a(`${t}.flow`, "\"flow\" only goes on an edge of kind \"flow\"."), n ? K(e) : null;
|
|
522
|
-
}, O = (e) => `${e.from} -> ${e.to}${e.kind ? ` (${e.kind === "flow" ? `flow ${e.flow}` : e.kind})` : " (ownership)"}`, A = new Map([...y]);
|
|
523
|
-
l.add.forEach((e, t) => {
|
|
524
|
-
let n = `edges.add[${t}]`;
|
|
525
|
-
if (!H(e)) return a(n, "An added edge is an object with from, to and optionally a kind.");
|
|
526
|
-
let r = E(e, n);
|
|
527
|
-
for (let t of Ke) t in e && a(`${n}.${t}`, `"${t}" is set when the proposal is applied; leave it out.`);
|
|
528
|
-
for (let t of ["from", "to"]) U(e[t]) && (_(e[t]) ? g.has(e[t]) && a(`${n}.${t}`, `Node "${e[t]}" is a node this proposal removes, so an edge cannot be added to it.`) : a(`${n}.${t}`, `Node "${e[t]}" is in neither the map nor the added nodes.`, "dangling"));
|
|
529
|
-
let i = w(e.from), s = w(e.to);
|
|
530
|
-
if (i && s) {
|
|
531
|
-
for (let t of ["when", "side"]) if (e[t] !== void 0) for (let r of o({
|
|
532
|
-
kind: e.kind,
|
|
533
|
-
[t]: e[t]
|
|
534
|
-
}, i, s)) a(`${n}.${t}`, `The edge ${r}`);
|
|
535
|
-
}
|
|
536
|
-
r && (p.has(r) ? a(n, `Edge ${O(e)} already exists in the map.`, "exists") : A.has(r) && a(n, `Edge ${O(e)} is already added by ${A.get(r)}.`), A.set(r, A.get(r) || n));
|
|
537
|
-
});
|
|
538
|
-
let j = /* @__PURE__ */ new Map(), te = (e, t, n) => {
|
|
539
|
-
let r = E(e, t);
|
|
540
|
-
return r ? (p.has(r) ? j.has(r) ? a(t, `Edge ${O(e)} is already ${j.get(r)} by this proposal.`) : j.set(r, n === "change" ? "changed" : "removed") : a(t, `Edge ${O(e)} does not exist in the map, so it cannot be ${n === "change" ? "changed" : "removed"}.`, "missing-target"), r) : null;
|
|
541
|
-
};
|
|
542
|
-
l.change.forEach((e, t) => {
|
|
543
|
-
let n = `edges.change[${t}]`;
|
|
544
|
-
if (!H(e)) return a(n, "A changed edge is an object with from, to, set and why.");
|
|
545
|
-
if (te(e, n, "change"), !H(e.set) || Object.keys(e.set).length === 0) a(`${n}.set`, "\"set\" must be an object of the fields to change.");
|
|
546
|
-
else {
|
|
547
|
-
for (let t of Je) t in e.set && a(`${n}.set.${t}`, `A change cannot set "${t}": it names the edge. Remove the edge and add a new one.`);
|
|
548
|
-
for (let t of qe) t in e.set && a(`${n}.set.${t}`, `"${t}" is set when the proposal is applied; leave it out of "set".`);
|
|
549
|
-
}
|
|
550
|
-
U(e.why) || a(`${n}.why`, "A change needs a \"why\".");
|
|
551
|
-
}), l.remove.forEach((e, t) => {
|
|
552
|
-
let n = `edges.remove[${t}]`;
|
|
553
|
-
if (!H(e)) return a(n, "A removed edge is an object with from, to and why.");
|
|
554
|
-
te(e, n, "remove"), U(e.why) || a(`${n}.why`, "A removal needs a \"why\".");
|
|
555
|
-
});
|
|
556
|
-
function ne(e, t) {
|
|
557
|
-
if (!U(e) || !Ue.test(e)) return a(t, `"actor" must be a persona id: lower-case words joined by dashes, like "child" (got ${JSON.stringify(e)}).`);
|
|
558
|
-
let n = b(e);
|
|
559
|
-
_(n) || a(t, `Actor "${e}" is no persona: "${n}" is in neither the map nor the added nodes.`, "dangling");
|
|
560
|
-
}
|
|
561
|
-
function re(e, t) {
|
|
562
|
-
if (!U(e)) return a(t, `"at" must be a node id or a live id (${We}).`);
|
|
563
|
-
_(e) || u(e) || (e.startsWith("live-") ? a(t, `"${e}" is not a live id: write ${We}.`) : a(t, `Step happens nowhere: "${e}" is in neither the map nor the added nodes, and is not a live id.`, "dangling"));
|
|
564
|
-
}
|
|
565
|
-
let M = "A check is { route, method } or { table, op, row? }";
|
|
566
|
-
function ie(e, t) {
|
|
567
|
-
if (!H(e)) return a(t, `${M}.`);
|
|
568
|
-
let n = "route" in e || "method" in e, r = "table" in e || "op" in e || "row" in e;
|
|
569
|
-
if (n && r) return a(t, `${M}: either one, not both.`);
|
|
570
|
-
if (!n && !r) return a(t, `${M}.`);
|
|
571
|
-
let i = n ? ["route", "method"] : [
|
|
572
|
-
"table",
|
|
573
|
-
"op",
|
|
574
|
-
"row"
|
|
575
|
-
];
|
|
576
|
-
for (let r of Object.keys(e)) i.includes(r) || a(`${t}.${r}`, `Unknown key "${r}" in a ${n ? "route" : "table"} check. It has: ${i.join(", ")}.`);
|
|
577
|
-
n ? (U(e.route) && e.route.startsWith("/") || a(`${t}.route`, "\"route\" must be a path starting with a slash, as the map labels it (\"/api/v1/rooms/[id]\") or a concrete one."), ze.includes(e.method) || a(`${t}.method`, `"method" must be one of: ${ze.join(", ")}.`)) : (U(e.table) || a(`${t}.table`, "\"table\" must be the SQL table name."), Be.includes(e.op) || a(`${t}.op`, `"op" must be one of: ${Be.join(", ")}.`), e.row !== void 0 && !Ve.includes(e.row) && a(`${t}.row`, `"row" must be one of: ${Ve.join(", ")}.`));
|
|
578
|
-
}
|
|
579
|
-
function ae(e, t) {
|
|
580
|
-
Array.isArray(e) ? e.forEach((e, n) => ie(e, `${t}[${n}]`)) : ie(e, t);
|
|
581
|
-
}
|
|
582
|
-
function N(e, t) {
|
|
583
|
-
if (!Array.isArray(e)) return a(t, "\"down\" must be a list of the cloud node ids the scenario takes down.");
|
|
584
|
-
if (e.length === 0) return a(t, "\"down\" needs at least one cloud node id; leave it out for a scenario that is no outage.");
|
|
585
|
-
let n = /* @__PURE__ */ new Set();
|
|
586
|
-
e.forEach((e, r) => {
|
|
587
|
-
let i = `${t}[${r}]`;
|
|
588
|
-
if (!U(e)) return a(i, "\"down\" holds node ids: strings like \"ext-cloudflare\".");
|
|
589
|
-
if (n.has(e)) return a(i, `"${e}" is down twice.`);
|
|
590
|
-
n.add(e);
|
|
591
|
-
let o = w(e);
|
|
592
|
-
if (!o) return a(i, `Down node "${e}" is in neither the map nor the added nodes.`, g.has(e) ? "missing-target" : "dangling");
|
|
593
|
-
if (o.type !== "external" || o.kind !== "cloud") {
|
|
594
|
-
let t = o.type === "external" ? o.kind === void 0 ? "an external with no kind" : `an external of kind ${o.kind}` : `a ${o.type}`;
|
|
595
|
-
a(i, `"${e}" is ${t}: only an external of kind cloud can be down (a container, a stack or a machine is the House view's; the public web is never down as a whole).`);
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
let P = new Set(l.remove.filter((e) => H(e) && U(e.from) && U(e.to)).map(K)), oe = (e, t) => P.has(e) || g.has(t.from) || g.has(t.to);
|
|
600
|
-
t.scenarios !== void 0 && !Array.isArray(t.scenarios) && a("scenarios", "\"scenarios\" must be a list.");
|
|
601
|
-
let se = /* @__PURE__ */ new Set();
|
|
602
|
-
if (G(t.scenarios).forEach((e, t) => {
|
|
603
|
-
let n = `scenarios[${t}]`;
|
|
604
|
-
if (!H(e)) return a(n, "A scenario is an object with an id, a title and steps.");
|
|
605
|
-
U(e.id) ? se.has(e.id) && a(`${n}.id`, `Scenario id "${e.id}" is used twice.`) : a(`${n}.id`, "A scenario needs an \"id\"."), U(e.id) && se.add(e.id), U(e.title) || a(`${n}.title`, "A scenario needs a \"title\".");
|
|
606
|
-
for (let t of Object.keys(e)) Le.includes(t) || a(`${n}.${t}`, `Unknown key "${t}" in a scenario. A scenario has: ${Le.join(", ")}.`);
|
|
607
|
-
if (e.stepMs !== void 0 && !Ye(e.stepMs) && a(`${n}.stepMs`, "\"stepMs\" must be a positive number of milliseconds."), e.linkNodes !== void 0 && typeof e.linkNodes != "boolean" && a(`${n}.linkNodes`, "\"linkNodes\" must be true or false."), e.actor !== void 0 && ne(e.actor, `${n}.actor`), e.down !== void 0 && N(e.down, `${n}.down`), !Array.isArray(e.steps)) return a(`${n}.steps`, "\"steps\" must be a list.");
|
|
608
|
-
if (e.steps.length === 0) return a(`${n}.steps`, "A scenario needs at least one step.");
|
|
609
|
-
e.steps.forEach((t, r) => {
|
|
610
|
-
let i = `${n}.steps[${r}]`;
|
|
611
|
-
if (!H(t)) return a(i, "A step is an object with a \"node\" or an \"edge\", and some \"text\".");
|
|
612
|
-
for (let e of Object.keys(t)) Re.includes(e) || a(`${i}.${e}`, `Unknown key "${e}" in a step. A step has "node" or "edge", and "text"; optionally ${Re.slice(3).join(", ")}.`);
|
|
613
|
-
if (U(t.text) || a(`${i}.text`, "A step needs \"text\": what happens at this point."), t.ms !== void 0 && !Ye(t.ms) && a(`${i}.ms`, "\"ms\" must be a positive number of milliseconds."), t.actor !== void 0 && ne(t.actor, `${i}.actor`), t.at !== void 0 && re(t.at, `${i}.at`), t.check !== void 0 && ae(t.check, `${i}.check`), t.expect !== void 0 && (He.includes(t.expect) ? t.actor === void 0 && e.actor === void 0 && a(`${i}.expect`, "\"expect\" needs an actor, on the step or its scenario: a step with no actor is never checked.") : a(`${i}.expect`, `"expect" must be one of: ${He.join(", ")}.`)), t.node === void 0 == (t.edge === void 0) && a(i, "A step points at exactly one of \"node\" or \"edge\"."), t.node !== void 0 && (U(t.node) ? _(t.node) || a(`${i}.node`, `Step points at nothing: node "${t.node}" is in neither the map nor the added nodes.`, g.has(t.node) ? "missing-target" : "dangling") : a(`${i}.node`, "\"node\" must be a node id.")), t.edge !== void 0) {
|
|
614
|
-
if (!H(t.edge)) return a(`${i}.edge`, "\"edge\" must be an object with from and to.");
|
|
615
|
-
let e = E(t.edge, `${i}.edge`);
|
|
616
|
-
e && !p.has(e) && !A.has(e) && a(`${i}.edge`, `Step points at nothing: edge ${O(t.edge)} is in neither the map nor the added edges.`, oe(e, t.edge) ? "missing-target" : "dangling");
|
|
617
|
-
}
|
|
618
|
-
});
|
|
619
|
-
}), t.mockups !== void 0 && !Array.isArray(t.mockups)) a("mockups", "\"mockups\" must be a list.");
|
|
620
|
-
else if (Array.isArray(t.mockups)) {
|
|
621
|
-
t.mockups.length > 40 && a("mockups", "At most 40 mockups in one proposal.");
|
|
622
|
-
let e = /* @__PURE__ */ new Set([
|
|
623
|
-
...h.keys(),
|
|
624
|
-
...g,
|
|
625
|
-
...c.change.filter((e) => H(e) && U(e.id)).map((e) => e.id)
|
|
626
|
-
]), n = /* @__PURE__ */ new Set();
|
|
627
|
-
t.mockups.forEach((t, r) => {
|
|
628
|
-
let i = `mockups[${r}]`;
|
|
629
|
-
if (!H(t)) return a(i, "A mockup is an object with a node, a path and a title.");
|
|
630
|
-
for (let e of Object.keys(t)) Fe.includes(e) || a(`${i}.${e}`, `Unknown key "${e}" in a mockup. A mockup has: ${Fe.join(", ")}.`);
|
|
631
|
-
U(t.title) || a(`${i}.title`, "A mockup needs a \"title\": what the screen is. It is also its alt text.");
|
|
632
|
-
let o = Ze(t.path);
|
|
633
|
-
o ? a(`${i}.path`, o) : n.has(`${t.node}|${t.path}`) ? a(i, `Mockup "${t.path}" is listed twice for node "${t.node}".`) : n.add(`${t.node}|${t.path}`), U(t.node) ? e.has(t.node) || a(`${i}.node`, `Mockup is beside node "${t.node}", which this proposal does not add, change or remove. Name a node the proposal touches.`) : a(`${i}.node`, "A mockup needs the \"node\" it belongs to.");
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
|
-
return r;
|
|
637
|
-
}
|
|
638
|
-
var tt = T.external;
|
|
639
|
-
function nt(e, t) {
|
|
640
|
-
let n = e.nodes.map((e) => ({
|
|
641
|
-
...e,
|
|
642
|
-
mark: "none"
|
|
643
|
-
})), r = e.edges.map((e) => ({
|
|
644
|
-
...e,
|
|
645
|
-
mark: "none"
|
|
646
|
-
})), i = new Map(n.map((e) => [e.id, e])), a = /* @__PURE__ */ new Map();
|
|
647
|
-
for (let e of r) {
|
|
648
|
-
let t = K(e);
|
|
649
|
-
a.has(t) || a.set(t, []), a.get(t).push(e);
|
|
650
|
-
}
|
|
651
|
-
let o = (e) => ({
|
|
652
|
-
add: G(t[e]?.add),
|
|
653
|
-
change: G(t[e]?.change),
|
|
654
|
-
remove: G(t[e]?.remove)
|
|
655
|
-
}), s = o("nodes"), c = o("edges"), l = (e, t, n) => {
|
|
656
|
-
let r = {}, i = (t, n) => {
|
|
657
|
-
Xe(e[t], n) || (r[t] = e[t] === void 0 ? null : e[t], e[t] = W(n));
|
|
658
|
-
};
|
|
659
|
-
for (let [e, n] of Object.entries(t || {})) i(e, n);
|
|
660
|
-
e.mark = "changed", e.before = r, e.why = n;
|
|
661
|
-
};
|
|
662
|
-
for (let e of s.change) {
|
|
663
|
-
let t = i.get(e.id);
|
|
664
|
-
if (!t) continue;
|
|
665
|
-
let n = { ...e.set }, r = T[n.type];
|
|
666
|
-
r && ("color" in n || (n.color = r.color), "r" in n || (n.r = r.r)), l(t, n, e.why);
|
|
667
|
-
}
|
|
668
|
-
for (let e of c.change) for (let t of a.get(K(e)) || []) l(t, e.set, e.why);
|
|
669
|
-
for (let e of c.remove) for (let t of a.get(K(e)) || []) delete t.before, t.mark = "removed", t.why = e.why;
|
|
670
|
-
for (let e of s.remove) {
|
|
671
|
-
let t = i.get(e.id);
|
|
672
|
-
if (t) {
|
|
673
|
-
t.mark = "removed", t.why = e.why;
|
|
674
|
-
for (let t of r) (t.from === e.id || t.to === e.id) && t.mark !== "removed" && (delete t.before, t.mark = "removed", t.why = e.why);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
let u = [], d = (e) => {
|
|
678
|
-
let t = a.get(K(e));
|
|
679
|
-
t ? t.forEach((e) => {
|
|
680
|
-
e.mark === "none" && (e.mark = "added");
|
|
681
|
-
}) : r.push({
|
|
682
|
-
...W(e),
|
|
683
|
-
mark: "added"
|
|
684
|
-
});
|
|
685
|
-
};
|
|
686
|
-
for (let e of s.add) {
|
|
687
|
-
let { parent: t, ...r } = W(e), a = T[e.type] || tt, o = i.get(e.id);
|
|
688
|
-
o ? o.mark === "none" && (o.mark = "added") : n.push({
|
|
689
|
-
...r,
|
|
690
|
-
color: a.color,
|
|
691
|
-
r: e.r ?? a.r,
|
|
692
|
-
mark: "added"
|
|
693
|
-
}), t && u.push({
|
|
694
|
-
from: t,
|
|
695
|
-
to: e.id
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
for (let e of u) d(e);
|
|
699
|
-
for (let e of c.add) d(e);
|
|
700
|
-
return {
|
|
701
|
-
nodes: n,
|
|
702
|
-
edges: r
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
function rt(e, t) {
|
|
706
|
-
let n = new Map(e.nodes.map((e) => [e.id, e])), r = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
|
|
707
|
-
for (let t of e.edges) {
|
|
708
|
-
let e = K(t);
|
|
709
|
-
r.has(e) || r.set(e, t);
|
|
710
|
-
let n = `${t.from}|${t.to}`;
|
|
711
|
-
a.has(n) || a.set(n, /* @__PURE__ */ new Set()), a.get(n).add(e), !t.kind && !t.dashed && (o.has(t.to) || o.set(t.to, /* @__PURE__ */ new Set()), o.get(t.to).add(t.from));
|
|
712
|
-
}
|
|
713
|
-
let s = (e, t) => Object.entries(t || {}).every(([t, n]) => Xe(e[t], n)), c = (e, n) => G(t?.[e]?.[n]), l = new Set(c("nodes", "add").filter((e) => H(e) && i(e)).map((e) => e.id)), u = (e) => l.has(e) || typeof e == "string" && e.startsWith("live-"), d = [], f = (e, t, n, r) => d.push({
|
|
714
|
-
kind: e,
|
|
715
|
-
op: t,
|
|
716
|
-
key: n,
|
|
717
|
-
status: r
|
|
718
|
-
});
|
|
719
|
-
for (let e of c("nodes", "add")) {
|
|
720
|
-
if (l.has(e.id)) {
|
|
721
|
-
f("node", "add", e.id, "live");
|
|
722
|
-
continue;
|
|
723
|
-
}
|
|
724
|
-
let t = n.get(e.id);
|
|
725
|
-
f("node", "add", e.id, t ? t.type !== e.type || e.parent && !o.get(e.id)?.has(e.parent) ? "diverged" : "landed" : "pending");
|
|
726
|
-
}
|
|
727
|
-
for (let e of c("nodes", "change")) {
|
|
728
|
-
let t = n.get(e.id);
|
|
729
|
-
f("node", "change", e.id, t ? s(t, e.set) ? "landed" : "pending" : "diverged");
|
|
730
|
-
}
|
|
731
|
-
for (let e of c("nodes", "remove")) f("node", "remove", e.id, n.has(e.id) ? "pending" : "landed");
|
|
732
|
-
for (let e of c("edges", "add")) {
|
|
733
|
-
let t = K(e);
|
|
734
|
-
if (u(e.from) || u(e.to)) {
|
|
735
|
-
f("edge", "add", t, "live");
|
|
736
|
-
continue;
|
|
737
|
-
}
|
|
738
|
-
let n = [...a.get(`${e.from}|${e.to}`) || []].some((e) => e !== t);
|
|
739
|
-
f("edge", "add", t, r.has(t) ? "landed" : n ? "diverged" : "pending");
|
|
740
|
-
}
|
|
741
|
-
for (let e of c("edges", "change")) {
|
|
742
|
-
let t = K(e), n = r.get(t);
|
|
743
|
-
f("edge", "change", t, n ? s(n, e.set) ? "landed" : "pending" : "diverged");
|
|
744
|
-
}
|
|
745
|
-
for (let e of c("edges", "remove")) {
|
|
746
|
-
let t = K(e);
|
|
747
|
-
f("edge", "remove", t, r.has(t) ? "pending" : "landed");
|
|
748
|
-
}
|
|
749
|
-
let p = {
|
|
750
|
-
total: d.length,
|
|
751
|
-
pending: 0,
|
|
752
|
-
landed: 0,
|
|
753
|
-
diverged: 0,
|
|
754
|
-
live: 0
|
|
755
|
-
};
|
|
756
|
-
for (let e of d) p[e.status]++;
|
|
757
|
-
return {
|
|
758
|
-
items: d,
|
|
759
|
-
summary: p
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
function it(e, t) {
|
|
763
|
-
let n = et(e, t), r = !1;
|
|
764
|
-
if (n.some((e) => e.state === "exists" || e.state === "missing-target")) try {
|
|
765
|
-
r = rt(e, t).items.some((e) => e.op === "add" && e.status === "landed");
|
|
766
|
-
} catch {}
|
|
767
|
-
return {
|
|
768
|
-
errors: r ? n.filter((e) => e.state !== "exists" && e.state !== "missing-target") : n,
|
|
769
|
-
building: r
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
function at(e) {
|
|
773
|
-
let t = (e) => ({
|
|
774
|
-
added: G(e?.add).length,
|
|
775
|
-
changed: G(e?.change).length,
|
|
776
|
-
removed: G(e?.remove).length
|
|
777
|
-
}), n = t(e?.nodes), r = t(e?.edges);
|
|
778
|
-
return {
|
|
779
|
-
added: n.added + r.added,
|
|
780
|
-
changed: n.changed + r.changed,
|
|
781
|
-
removed: n.removed + r.removed,
|
|
782
|
-
scenarios: G(e?.scenarios).length,
|
|
783
|
-
nodes: n,
|
|
784
|
-
edges: r
|
|
785
|
-
};
|
|
786
|
-
}
|
|
787
|
-
// ../explorer/mockups-model.js
|
|
788
|
-
var ot = {
|
|
789
|
-
approved: "Reviewed",
|
|
790
|
-
changed: "Changed since you approved",
|
|
791
|
-
unreviewed: "Not reviewed yet",
|
|
792
|
-
missing: "File not found"
|
|
793
|
-
}, st = (e) => ot[e] || ot.unreviewed, ct = (e) => /\.html$/i.test(String(e)) ? "page" : "image";
|
|
794
|
-
function lt(e, t, n) {
|
|
795
|
-
return `/proposals/${encodeURIComponent(e)}/mockups/${n}${t ? `?source=${encodeURIComponent(t)}` : ""}`;
|
|
796
|
-
}
|
|
797
|
-
function ut(e, t, n, r, i = {}) {
|
|
798
|
-
return !e || !t ? [] : Qe(e).filter((e) => e.node === r).map((e) => ({
|
|
799
|
-
...e,
|
|
800
|
-
type: ct(e.path),
|
|
801
|
-
url: lt(t, n, e.index),
|
|
802
|
-
state: i[e.index] || "unreviewed"
|
|
803
|
-
}));
|
|
804
|
-
}
|
|
805
|
-
function dt(e) {
|
|
806
|
-
if (!e.length) return "";
|
|
807
|
-
let t = e.map((e) => `<li class="hx-mockup-item" data-corn="row">
|
|
808
|
-
<button data-corn-kind="secondary" type="button" class="hx-btn hx-mockup-open" data-mockup="${e.index}" aria-haspopup="dialog">${c(e.title)}<span class="hx-sr-only"> (${e.type === "page" ? "page" : "image"}, opens in a window)</span></button>
|
|
809
|
-
<span class="hx-mockup-state hx-mockup-state--${c(e.state)}" data-corn="state-pill"${z(e.state)}>${c(st(e.state))}</span>
|
|
810
|
-
</li>`).join("");
|
|
811
|
-
return `<div class="hx-sec hx-mockups" data-mockups data-corn="section">
|
|
812
|
-
<h3 class="hx-sec-title" id="hx-mockups-h">${e.length === 1 ? "Mockup" : "Mockups"}</h3>
|
|
813
|
-
<ul class="hx-mockup-list" aria-labelledby="hx-mockups-h">${t}</ul>
|
|
814
|
-
</div>`;
|
|
815
|
-
}
|
|
816
|
-
function ft(e, t) {
|
|
817
|
-
return dt(ut(e.proposal, e.proposalSlug, e.proposalSource, t, e.mockupStates || {}));
|
|
818
|
-
}
|
|
819
|
-
// ../explorer/camera-frame.js
|
|
820
|
-
var pt = .18;
|
|
821
|
-
function mt(e, t, n, r = 0) {
|
|
822
|
-
return e.every((e) => {
|
|
823
|
-
let i = t.x + e.x * t.zoom, a = t.y + e.y * t.zoom;
|
|
824
|
-
return i >= n.x + r && i <= n.x + n.width - r && a >= n.y + r && a <= n.y + n.height - r;
|
|
825
|
-
});
|
|
826
|
-
}
|
|
827
|
-
function ht(e, t, { padding: n = 40, minZoom: r = pt } = {}) {
|
|
828
|
-
if (e.length < 2) return e;
|
|
829
|
-
let i = E(n, t), a = (t.width - i * 2) / r, o = (t.height - i * 2) / r, s = e.map(O), c = (t, n) => e.filter((e, r) => s[r].left >= t && s[r].right <= t + a && s[r].top >= n && s[r].bottom <= n + o), l = s.map((e) => e.left), u = s.map((e) => e.top), d = [], f = e.length <= 120 ? l.flatMap((e) => u.map((t) => [e, t])) : s.map((e) => [e.left, e.top]);
|
|
830
|
-
for (let [t, n] of f) {
|
|
831
|
-
if (d.length === e.length) break;
|
|
832
|
-
let r = c(t, n);
|
|
833
|
-
r.length > d.length && (d = r);
|
|
834
|
-
}
|
|
835
|
-
return d.length ? d : [e[0]];
|
|
836
|
-
}
|
|
837
|
-
function gt(e, t, n, r = 0) {
|
|
838
|
-
let i = e.x + t.x * e.zoom, a = e.y + t.y * e.zoom, o = Math.min(r, (n.right - n.left) / 2), s = Math.min(r, (n.bottom - n.top) / 2), c = i < n.left + o || i > n.right - o, l = a < n.top + s || a > n.bottom - s;
|
|
839
|
-
return !c && !l ? null : {
|
|
840
|
-
x: c ? (n.left + n.right) / 2 - t.x * e.zoom : e.x,
|
|
841
|
-
y: l ? (n.top + n.bottom) / 2 - t.y * e.zoom : e.y,
|
|
842
|
-
zoom: e.zoom
|
|
843
|
-
};
|
|
844
|
-
}
|
|
845
|
-
// ../explorer/cloud-panel.js
|
|
846
|
-
var q = {
|
|
847
|
-
free: "Free",
|
|
848
|
-
paid: "Paid",
|
|
849
|
-
unknown: "Plan unknown",
|
|
850
|
-
off: "Off"
|
|
851
|
-
};
|
|
852
|
-
function _t(e) {
|
|
853
|
-
return !e || !q[e.tier] ? "" : e.note ? `${q[e.tier]} · ${e.note}` : q[e.tier];
|
|
854
|
-
}
|
|
855
|
-
var vt = {
|
|
856
|
-
container: ["container", "containers"],
|
|
857
|
-
machine: ["machine", "machines"],
|
|
858
|
-
app: ["app", "apps"],
|
|
859
|
-
service: ["service", "services"],
|
|
860
|
-
page: ["endpoint", "endpoints"],
|
|
861
|
-
external: ["cloud service", "cloud services"]
|
|
862
|
-
}, yt = (e, t) => {
|
|
863
|
-
let n = vt[e] || [e, `${e}s`];
|
|
864
|
-
return t === 1 ? n[0] : n[1];
|
|
865
|
-
};
|
|
866
|
-
function bt(e, t, n) {
|
|
867
|
-
let r = new Map(t.map((e) => [e.id, e])), i = new Map(Object.keys(l).map((e) => [e, /* @__PURE__ */ new Map()]));
|
|
868
|
-
for (let t of n) {
|
|
869
|
-
if (t.kind !== "calls" || t.to !== e.id) continue;
|
|
870
|
-
let n = i.get(A(t)), a = r.get(t.from) || {
|
|
871
|
-
id: t.from,
|
|
872
|
-
label: t.from,
|
|
873
|
-
type: "node"
|
|
874
|
-
}, o = n.get(t.from) || {
|
|
875
|
-
id: t.from,
|
|
876
|
-
label: String(a.label || t.from),
|
|
877
|
-
type: a.type,
|
|
878
|
-
vias: [],
|
|
879
|
-
browser: !1
|
|
880
|
-
};
|
|
881
|
-
t.label && !o.vias.includes(t.label) && o.vias.push(t.label), t.side === "browser" && (o.browser = !0), n.set(t.from, o);
|
|
882
|
-
}
|
|
883
|
-
let a = [];
|
|
884
|
-
for (let [e, t] of i) {
|
|
885
|
-
if (t.size === 0) continue;
|
|
886
|
-
let n = /* @__PURE__ */ new Map();
|
|
887
|
-
for (let { vias: e, ...r } of t.values()) n.has(r.type) || n.set(r.type, []), n.get(r.type).push({
|
|
888
|
-
...r,
|
|
889
|
-
via: e.join(", ")
|
|
890
|
-
});
|
|
891
|
-
let r = [...n].map(([e, t]) => ({
|
|
892
|
-
type: e,
|
|
893
|
-
noun: yt(e, 1),
|
|
894
|
-
items: t.sort((e, t) => e.label.localeCompare(t.label))
|
|
895
|
-
})).sort((e, t) => t.items.length - e.items.length || e.type.localeCompare(t.type)), { title: i, color: o } = l[e];
|
|
896
|
-
a.push({
|
|
897
|
-
when: e,
|
|
898
|
-
title: i,
|
|
899
|
-
color: o,
|
|
900
|
-
count: t.size,
|
|
901
|
-
types: r
|
|
902
|
-
});
|
|
903
|
-
}
|
|
904
|
-
return a;
|
|
905
|
-
}
|
|
906
|
-
var xt = {
|
|
907
|
-
run: "Breaks now",
|
|
908
|
-
deploy: "Breaks on deploy",
|
|
909
|
-
renew: "Breaks on renewal"
|
|
910
|
-
}, J = (e, t) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${c(e)}</div><div class="hx-fact-v">${P(t)}</div></div>` : "", Y = (e) => `<div class="hx-line">${e}</div>`, X = (e) => `<span class="hx-name">${c(e)}</span>`;
|
|
911
|
-
function St(e, t) {
|
|
912
|
-
let n = e.browser ? " <span class=\"hx-cloud-browser\">(browser)</span>" : "", r = [t ? yt(e.type, 1) : "", e.via].filter(Boolean);
|
|
913
|
-
return Y(`<span>${X(e.label)}${n}${r.length ? `<span class="hx-faint"> · ${c(r.join(" · "))}</span>` : ""}</span>`);
|
|
914
|
-
}
|
|
915
|
-
var Ct = (e) => `<button data-corn-kind="quiet" type="button" class="hx-btn hx-btn--quiet hx-cloud-play" data-action="play-outage" data-id="${c(e.id)}">Play: ${c(String(e.label || e.id))} is down</button>`;
|
|
916
|
-
function wt(e, t, n) {
|
|
917
|
-
let r = new Map(t.map((e) => [e.id, e])), i = (e) => String((r.get(e) || { label: e }).label || e), a = e.kind === "web", o = a ? [] : e.roles || [], s = bt(e, t, n).map((e) => {
|
|
918
|
-
let t = e.types.length > 1;
|
|
919
|
-
return J(xt[e.when], e.types.flatMap((e) => e.items.map((e) => St(e, t))));
|
|
920
|
-
}).join("") || J("Used by", [Y("<span class=\"hx-faint\">Nothing on the map uses it.</span>")]), l = n.filter((t) => t.kind === "calls" && t.from === e.id && (r.get(t.to) || {}).type === "external").map((e) => Y(`<span>${X(i(e.to))}${e.label ? `<span class="hx-faint"> · ${c(e.label)}</span>` : ""}</span>`)), u = n.filter((t) => t.kind === "delivers" && t.from === e.id).map((e) => Y(X(i(e.to))));
|
|
921
|
-
return (a ? "" : J("Plan", [Y(c(_t(e.plan) || q.unknown))])) + J("Roles", o.length ? [Y(c(o.join(", ")))] : []) + J("If it's down", [Y(c(e.breaks || "Not described yet."))]) + s + J("Relies on", l) + J("Pushes to", u) + (a ? "" : Ct(e));
|
|
922
|
-
}
|
|
923
|
-
// ../explorer/file-url.js
|
|
924
|
-
var Tt = {
|
|
925
|
-
github: "blob",
|
|
926
|
-
forgejo: "src/branch"
|
|
927
|
-
};
|
|
928
|
-
function Et(e) {
|
|
929
|
-
if (typeof e != "string" || !e || /[\\\u0000-\u001f\u007f]/.test(e) || e.startsWith("/") || /^[A-Za-z][A-Za-z0-9+.-]*:/.test(e)) return null;
|
|
930
|
-
let t = e.split("/");
|
|
931
|
-
return t.every((e) => e && e !== "." && e !== "..") ? t : null;
|
|
932
|
-
}
|
|
933
|
-
function Dt(e, t, n) {
|
|
934
|
-
let r = e && Object.hasOwn(Tt, e.type) && Tt[e.type], i = Et(t), a = Et(n || "HEAD"), o = Et(e && e.repo);
|
|
935
|
-
if (!r || !i || !a || !o || o.length !== 2) return null;
|
|
936
|
-
try {
|
|
937
|
-
let t = new URL(e.url);
|
|
938
|
-
if (t.protocol !== "https:" || t.username || t.password || String(e.url).includes("\\")) return null;
|
|
939
|
-
let n = (e) => e.map(encodeURIComponent).join("/");
|
|
940
|
-
return t.pathname = `${t.pathname.replace(/\/+$/, "")}/${n(o)}/${r}/${n(a)}/${n(i)}`, t.search = "", t.hash = "", t.href;
|
|
941
|
-
} catch {
|
|
942
|
-
return null;
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
// ../explorer/engine/feedback.js
|
|
946
|
-
var Ot = 6e3, kt = (e) => e.slot("feedback", () => /* @__PURE__ */ new Map());
|
|
947
|
-
function At(e, t, n, r = !0) {
|
|
948
|
-
kt(e).set(t, {
|
|
949
|
-
text: n,
|
|
950
|
-
ok: r
|
|
951
|
-
}), C(e, n);
|
|
952
|
-
}
|
|
953
|
-
function jt(e, t) {
|
|
954
|
-
kt(e).delete(t);
|
|
955
|
-
}
|
|
956
|
-
function Mt(e, t, n) {
|
|
957
|
-
if (!t) return;
|
|
958
|
-
let r = kt(e).get(n);
|
|
959
|
-
t.hidden = !r, t.textContent = r ? r.text : "", r ? t.dataset.cornState = r.ok ? "success" : "failure" : delete t.dataset.cornState;
|
|
960
|
-
}
|
|
961
|
-
// ../explorer/selection-words.js
|
|
962
|
-
var Nt = [
|
|
963
|
-
"ownership",
|
|
964
|
-
"usage",
|
|
965
|
-
"flow",
|
|
966
|
-
"reads",
|
|
967
|
-
"writes",
|
|
968
|
-
"calls",
|
|
969
|
-
"triggers",
|
|
970
|
-
"delivers",
|
|
971
|
-
"runs-on",
|
|
972
|
-
"uses",
|
|
973
|
-
"extends"
|
|
974
|
-
], Pt = (e) => Object.hasOwn(p, e) ? p[e].panel : String(e);
|
|
975
|
-
function Ft(e) {
|
|
976
|
-
let t = (e) => {
|
|
977
|
-
let t = Nt.indexOf(e);
|
|
978
|
-
return t < 0 ? Nt.length : t;
|
|
979
|
-
};
|
|
980
|
-
return [...e.kinds.entries()].sort((e, n) => t(e[0]) - t(n[0]) || (e[0] < n[0] ? -1 : +(e[0] > n[0]))).map(([e, t]) => ({
|
|
981
|
-
kind: e,
|
|
982
|
-
count: t,
|
|
983
|
-
word: Pt(e)
|
|
984
|
-
}));
|
|
985
|
-
}
|
|
986
|
-
function It(e, t) {
|
|
987
|
-
let n = [], r = /* @__PURE__ */ new Set();
|
|
988
|
-
for (let i of e.edges) {
|
|
989
|
-
if (w(i) !== t) continue;
|
|
990
|
-
let a = i.from === e.selectedId, o = a ? i.to : i.from;
|
|
991
|
-
r.has(o) || (r.add(o), n.push({
|
|
992
|
-
id: o,
|
|
993
|
-
out: a
|
|
994
|
-
}));
|
|
995
|
-
}
|
|
996
|
-
return n;
|
|
997
|
-
}
|
|
998
|
-
function Lt(e, t) {
|
|
999
|
-
return t > 0 ? `${e} connected · ${t} off screen` : `${e} connected · all on screen`;
|
|
1000
|
-
}
|
|
1001
|
-
// ../explorer/pieces/node-panel.js
|
|
1002
|
-
var Rt = /* @__PURE__ */ e({
|
|
1003
|
-
LINES_CAP: () => 12,
|
|
1004
|
-
copySpec: () => Jt,
|
|
1005
|
-
diffPillWords: () => Gt,
|
|
1006
|
-
markup: () => Kt,
|
|
1007
|
-
mount: () => Xt
|
|
1008
|
-
}), Z = (e) => `<code class="hx-code">${c(e)}</code>`, Q = (e) => `<div class="hx-line">${e}</div>`, zt = {
|
|
1009
|
-
"Uses design tokens": "Tokens",
|
|
1010
|
-
"Loaded by the server per request": "Loaded by",
|
|
1011
|
-
"Domains served (Caddyfile → service)": "Domains",
|
|
1012
|
-
"Compose file": "File",
|
|
1013
|
-
"Baked pages": "Baked",
|
|
1014
|
-
"Reads tables": "Reads",
|
|
1015
|
-
"Writes tables": "Writes",
|
|
1016
|
-
"Self-hosted": "Role",
|
|
1017
|
-
"Pushes to (webhook)": "Pushes to",
|
|
1018
|
-
"Calls outside": "Calls",
|
|
1019
|
-
"Client modules": "Modules",
|
|
1020
|
-
"Data flows": "Flows"
|
|
1021
|
-
}, Bt = /^(?:Defines )?\d+ (?:CSS )?(variable|service)\(s\)$/, Vt = (e) => {
|
|
1022
|
-
let t = e.replace(/:$/, ""), n = Bt.exec(t);
|
|
1023
|
-
return n ? n[1] === "service" ? "Services" : t.startsWith("Defines") ? "Defines" : "Variables" : zt[t] || t;
|
|
1024
|
-
}, $ = (e, t) => t.length ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${c(Vt(e))}</div><div class="hx-fact-v">${P(t)}</div></div>` : "", Ht = (e) => `<div class="hx-chips">${P(e.map((e) => `<code class="hx-var">${c(e)}</code>`))}</div>`;
|
|
1025
|
-
function Ut(e) {
|
|
1026
|
-
if (e.type === "external" && e.kind) return e.kind === "web" ? "Public web" : "Cloud";
|
|
1027
|
-
let t = e.type.charAt(0).toUpperCase() + e.type.slice(1);
|
|
1028
|
-
return typeof e.kind == "string" && e.kind ? `${t} · ${e.kind}` : t;
|
|
1029
|
-
}
|
|
1030
|
-
function Wt(e) {
|
|
1031
|
-
if (e.url) try {
|
|
1032
|
-
return new URL(e.url).host;
|
|
1033
|
-
} catch {}
|
|
1034
|
-
return e.host || "";
|
|
1035
|
-
}
|
|
1036
|
-
function Gt(e, t) {
|
|
1037
|
-
let n = e && e.mark;
|
|
1038
|
-
if (!n || n === "none") return "";
|
|
1039
|
-
if (n === "edit") return `${e.editOp === "removed" ? "Removed" : "Added"} by your edit`;
|
|
1040
|
-
let r = t && typeof t.title == "string" ? t.title : "";
|
|
1041
|
-
return r ? `${B[n] || n} by ${r}` : `${B[n] || n} by this proposal`;
|
|
1042
|
-
}
|
|
1043
|
-
var Kt = () => ({
|
|
1044
|
-
drawer: "<aside id=\"spec-drawer\" class=\"hx-drawer glass\" aria-label=\"Node details\" inert data-corn=\"node-panel\"><div class=\"hx-drawer-body\"><div class=\"hx-drawer-head\"><div class=\"hx-drawer-id\"><p class=\"hx-kicker\"><span id=\"drawer-badge\" data-corn=\"badge\">Atom</span><span id=\"drawer-host\" data-corn=\"node-host\"></span><span id=\"drawer-diff\" class=\"hx-diffpill\" data-corn=\"diff-pill\" hidden></span></p><h2 id=\"drawer-title\" class=\"hx-drawer-title\" data-corn=\"node-title\"><pop-button></h2></div><button type=\"button\" class=\"hx-close\" data-action=\"close-drawer\" aria-label=\"Close\" data-corn-kind=\"icon\">✕</button></div><p id=\"drawer-description\" class=\"hx-lead\" hidden></p><div class=\"hx-block\"><div id=\"drawer-meta-list\" class=\"hx-meta\"></div></div></div><div class=\"hx-drawer-foot\" data-corn=\"node-foot\"><a data-corn=\"open-link\" id=\"drawer-file-btn\" data-corn-kind=\"primary\" class=\"hx-open\" href=\"#\" target=\"_blank\" rel=\"noreferrer\" hidden>Open file ↗</a><a data-corn=\"open-link\" id=\"drawer-open-btn\" data-corn-kind=\"primary\" class=\"hx-open\" href=\"#\" target=\"_blank\" rel=\"noreferrer\" hidden>Open route ↗</a><button data-corn-kind=\"secondary\" type=\"button\" id=\"drawer-run-btn\" class=\"hx-btn hx-foot-btn\" data-action=\"start-run\" data-corn-string=\"startRun\" hidden>Start a run</button><button data-corn-kind=\"quiet\" type=\"button\" class=\"hx-btn hx-btn--quiet hx-foot-btn\" data-action=\"copy-spec\" data-corn-string=\"copySpec\">Copy Spec</button><p id=\"copy-spec-result\" class=\"hx-forge-result\" data-corn=\"result\" hidden></p></div></aside>",
|
|
1045
|
-
backdrop: "<div id=\"drawer-backdrop\" class=\"hx-backdrop\" data-action=\"close-drawer\" hidden data-corn=\"backdrop\"></div>"
|
|
1046
|
-
}), qt = (e) => e.slot("copy-spec", () => ({ timer: 0 }));
|
|
1047
|
-
async function Jt(e, t) {
|
|
1048
|
-
let { state: n } = e;
|
|
1049
|
-
if (!n.selectedNode) return;
|
|
1050
|
-
let r = qt(e), i = JSON.stringify({ node: n.selectedNode }, null, 2);
|
|
1051
|
-
clearTimeout(r.timer), jt(e, "copy-spec");
|
|
1052
|
-
try {
|
|
1053
|
-
await e.win.navigator.clipboard.writeText(i), At(e, "copy-spec", `Copied the spec of ${n.selectedNode.label || n.selectedNode.id} to the clipboard.`, !0);
|
|
1054
|
-
} catch {
|
|
1055
|
-
At(e, "copy-spec", "The browser did not allow copying, so nothing was copied. Allow clipboard access for this page, then press Copy Spec again.", !1);
|
|
1056
|
-
}
|
|
1057
|
-
Mt(e, t, "copy-spec"), r.timer = setTimeout(() => {
|
|
1058
|
-
jt(e, "copy-spec"), Mt(e, t, "copy-spec");
|
|
1059
|
-
}, Ot);
|
|
1060
|
-
}
|
|
1061
|
-
function Yt(e) {
|
|
1062
|
-
let { state: t } = e, n = (e) => t.nodes.find((t) => t.id === e), r = (e) => (n(e) || { label: e }).label, i = (e) => `<span class="hx-name">${c(r(e))}</span>`, a = (e, n, r) => t.edges.filter((t) => t.kind === e && t[n] === r);
|
|
1063
|
-
function o(e) {
|
|
1064
|
-
let o = t.edges.filter((e) => e.kind === "reads"), s = t.edges.filter((e) => e.kind === "writes"), l = t.edges.filter((t) => t.kind === "uses" && t.from === e.id), u = $("Extends:", t.edges.filter((t) => t.kind === "extends" && t.from === e.id).map((e) => Q(i(e.to)))) + $("Uses design tokens:", l.map((e) => Q(`${i(e.to)} · ${e.vars.length}${Ht(e.vars)}`))) + (e.type !== "token" && e.vars ? $(`Defines ${e.vars.length} CSS variable(s):`, [Ht(e.vars)]) : "");
|
|
1065
|
-
if (e.type === "app") {
|
|
1066
|
-
let n = e.deployed ? Q(`${/^https?:\/\//.test(e.url) ? `<a data-corn="text-link" class="hx-link" href="${c(e.url)}" target="_blank" rel="noreferrer">${c(e.url)}</a>` : Z(e.url)} → ${(e.upstreams || []).map(Z).join(" ")}${e.stack ? ` <span class="hx-faint">[${c(e.stack)}]</span>` : ""}`) : Q("Not deployed by any stack in this repo"), r = t.edges.filter((t) => t.kind === "runs-on" && t.from === e.id).map((e) => Q(`${i(e.to)}${(e.mappings || []).map((e) => `<div class="hx-faint">${Z(e.host)} → ${Z(e.upstream)}${e.service ? ` = ${Z(e.service)}` : ""}</div>`).join("")}`));
|
|
1067
|
-
return $("Served:", [n]) + $("Runs on:", r) + $("Loaded by the server per request:", o.filter((t) => t.to === e.id).map((e) => Q(i(e.from)))) + u;
|
|
1068
|
-
}
|
|
1069
|
-
if (e.type === "token") {
|
|
1070
|
-
let n = t.edges.filter((t) => t.kind === "uses" && t.to === e.id);
|
|
1071
|
-
return $(`${e.vars.length} variable(s):`, [Ht(e.vars)]) + $("Used by:", n.map((e) => Q(`${i(e.from)} · ${c(e.vars.join(" "))}`)));
|
|
1072
|
-
}
|
|
1073
|
-
if ([
|
|
1074
|
-
"atom",
|
|
1075
|
-
"molecule",
|
|
1076
|
-
"core"
|
|
1077
|
-
].includes(e.type)) {
|
|
1078
|
-
let n = t.edges.filter((t) => t.dashed && t.to === e.id).map((e) => Q(i(e.from)));
|
|
1079
|
-
return (e.table ? $("Record of:", [Q(`${c(e.model)} · table ${Z(e.table)}`)]) : "") + $("Rendered by:", n) + u;
|
|
1080
|
-
}
|
|
1081
|
-
if (e.type === "stack") return $("Domains served (Caddyfile → service):", t.edges.filter((t) => t.kind === "runs-on" && t.to === e.id).flatMap((e) => (e.mappings || []).map((e) => Q(`<span class="hx-name">${c(e.host)}</span> → ${Z(e.upstream)}${e.service ? ` = ${Z(e.service)}` : ""}`)))) + $(`${(e.services || []).length} service(s):`, (e.services || []).map((e) => Q(`<span class="hx-name">${c(e.name)}</span>${e.image ? ` <span class="hx-faint">${c(e.image)}</span>` : ""}${e.ports.length ? `<div>${e.ports.map(Z).join(" ")}</div>` : ""}${e.volumes.length ? `<div class="hx-faint">${e.volumes.map(c).join("<br>")}</div>` : ""}`))) + $("Compose file:", [Q(Z(e.file))]);
|
|
1082
|
-
if (e.type === "table") {
|
|
1083
|
-
let t = o.filter((t) => t.from === e.id), a = s.filter((t) => t.to === e.id), l = t.filter((e) => (n(e.to) || {}).render?.rom === "bake");
|
|
1084
|
-
return (e.model ? $("Model:", [Q(c(e.model))]) : "") + $("Read by:", t.map((e) => Q(`${i(e.to)} · ${e.keys.map(Z).join(" ")}`))) + $("Written by:", a.map((e) => Q(`${i(e.from)} · ${c(e.label)}`))) + (l.length ? $("Baked pages:", [Q(`a write here re-bakes <span class="hx-rom hx-bold">${l.length}</span> file(s): ${l.map((e) => c(r(e.to))).join(", ")}`)]) : "");
|
|
1085
|
-
}
|
|
1086
|
-
if (e.type === "service") {
|
|
1087
|
-
let t = (e, t) => `${i(e[t])}${e.label && e.label !== "imports" ? ` · ${c(e.label)}` : ""}`;
|
|
1088
|
-
return (e.summary && !String(e.desc || "").includes(e.summary) ? $("Summary:", [Q(`<span class="hx-faint">${c(e.summary)}</span>`)]) : "") + $("Started by:", [...(e.triggers || []).map((e) => Q(c(e))), ...a("triggers", "to", e.id).map((e) => Q(t(e, "from")))]) + $("Jobs:", (e.jobs || []).map((e) => Q(`${Z(e.name)} · cron ${Z(e.cron)}`))) + $("Runs:", a("triggers", "from", e.id).map((e) => Q(t(e, "to")))) + $("Calls:", a("calls", "from", e.id).map((e) => Q(t(e, "to")))) + $("Called by:", a("calls", "to", e.id).map((e) => Q(t(e, "from")))) + $("Reads tables:", o.filter((t) => t.to === e.id).map((e) => Q(i(e.from)))) + $("Writes tables:", s.filter((t) => t.from === e.id).map((e) => Q(i(e.to)))) + $("Mechanisms:", (e.mechanisms || []).map((e) => Q(c(e))));
|
|
1089
|
-
}
|
|
1090
|
-
if (e.type === "container" && e.selfHosted) {
|
|
1091
|
-
let a = (e, t) => `${i(e[t])}${e.label && e.label !== "calls" ? ` · ${c(e.label)}` : ""}`, o = t.edges.filter((t) => t.to === e.id && (t.kind === "calls" || t.kind === "flow" && t.flow === "api")), s = (e) => o.filter((t) => n(t.from)?.type === e).map((e) => Q(a(e, "from"))), l = new Set(t.nodes.filter((t) => t.type === "container" && t.stack === e.stack).map((e) => e.id));
|
|
1092
|
-
return $("Self-hosted:", [Q(c(e.summary || ""))]) + $("Called by services:", s("service")) + $("Called by endpoints:", s("page")) + $("Called by apps:", s("app")) + $("Pushes to (webhook):", t.edges.filter((e) => e.kind === "delivers" && l.has(e.from) && n(e.to)?.type === "page").map((t) => Q(`${i(t.to)}${t.from === e.id ? "" : ` <span class="hx-faint">from ${c(r(t.from))}</span>`}`)));
|
|
1093
|
-
}
|
|
1094
|
-
if (e.type === "external" && e.kind) return wt(e, t.nodes, t.edges);
|
|
1095
|
-
if (e.type === "external") {
|
|
1096
|
-
let t = (t) => a("calls", "to", e.id).filter((e) => n(e.from)?.type === t);
|
|
1097
|
-
return $("System:", [Q(`${c(e.summary || "")}${e.host ? `<div class="hx-faint">Runs here as ${Z(e.host)}</div>` : "<div class=\"hx-faint\">Not run by this stack</div>"}`)]) + $("Client modules:", (e.modules || []).map((e) => Q(Z(e)))) + $("Called by services:", t("service").map((e) => Q(i(e.from)))) + $("Called by endpoints:", t("page").map((e) => Q(i(e.from)))) + $("Pushes to (webhook):", a("delivers", "from", e.id).map((e) => Q(i(e.to))));
|
|
1098
|
-
}
|
|
1099
|
-
if (e.type === "page") {
|
|
1100
|
-
let n = e.render, r = t.edges.filter((t) => t.dashed && t.from === e.id).map((e) => Q(i(e.to)));
|
|
1101
|
-
return (e.methods ? $("Methods:", [Q(e.methods.map(Z).join(" "))]) : "") + (e.render_fn ? $("Rendered by:", [Q(`${Z(e.render_fn)} · ${c(e.file)}`)]) : "") + $("Calls outside:", a("calls", "from", e.id).map((e) => Q(i(e.to)))) + $("Pushed to by:", a("delivers", "to", e.id).map((e) => Q(`${i(e.from)} · ${c(e.label)}`))) + $("Starts:", a("triggers", "from", e.id).map((e) => Q(`${i(e.to)} · ${c(e.label)}`))) + $("Renders:", r) + $("Reads:", o.filter((t) => t.to === e.id).map((e) => Q(`${i(e.from)} · ${e.keys.map(Z).join(" ")}`))) + $("Writes:", s.filter((t) => t.from === e.id).map((e) => Q(`${i(e.to)} · ${c(e.label)}`))) + (n ? $("Render:", [Q(`today: ${Z(n.now)} · ROM: ${n.rom === "bake" ? "<span class=\"hx-rom hx-bold\">bake</span>" : "<span class=\"hx-faint\">skip (per request)</span>"}${n.note ? `<div class="hx-faint">${c(n.note)}</div>` : ""}`)]) : "");
|
|
1102
|
-
}
|
|
1103
|
-
return "";
|
|
1104
|
-
}
|
|
1105
|
-
function s(t) {
|
|
1106
|
-
let n = e.ask("threads:index", t.id);
|
|
1107
|
-
if (!n) return "";
|
|
1108
|
-
let r = n.threads, i = n.start ? `<button data-corn-kind="quiet" type="button" class="hx-btn hx-btn--quiet hx-textact" data-thread-start="${c(t.id)}" aria-label="Start a thread about this: opens the New idea form for ${c(n.forge)}, with this node mentioned">Start a thread about this</button>` : "";
|
|
1109
|
-
return !r || !r.length ? i : `<div class="hx-sec-block" data-corn="section"><h3 class="hx-sec-title">Threads</h3><ul class="hx-rows">${r.map((e) => {
|
|
1110
|
-
let t = Number(e.comments) || 0;
|
|
1111
|
-
return `<li><button type="button" class="hx-row hx-thread-open" data-thread-open="${c(e.number)}" data-corn="row" aria-label="Open thread #${c(e.number)}, ${c(e.title)}, ${t} ${t === 1 ? "comment" : "comments"}, in the issues and pull requests panel"><span class="hx-row-title">${c(e.title)}</span><span class="hx-row-meta">#${c(e.number)} · ${t}</span></button></li>`;
|
|
1112
|
-
}).join("")}</ul>${i}</div>`;
|
|
1113
|
-
}
|
|
1114
|
-
function l(e) {
|
|
1115
|
-
let n = y(e);
|
|
1116
|
-
if (!Gt(e, t.proposal)) return "";
|
|
1117
|
-
let r = (e, t) => `<div class="hx-diff-k">${c(e)}</div><div class="hx-diff-v">${t}</div>`, i = [r("id", c(e.id))], a = t.edges.find((t) => !t.kind && !t.dashed && t.to === e.id);
|
|
1118
|
-
a && i.push(r("parent", c(a.from)));
|
|
1119
|
-
let o = t.edges.filter((t) => t.from === e.id || t.to === e.id), s = o.filter((e) => y(e) === "added").length, l = o.filter((e) => y(e) === "removed").length;
|
|
1120
|
-
if ((s || l) && i.push(r("edges", c([s ? `+${s}` : "", l ? `−${l}` : ""].filter(Boolean).join(" ")))), n === "changed") for (let t of we(e)) i.push(r(t.field, `<span class="hx-change-before">${c(t.before) || "<em>nothing</em>"}</span> <span aria-hidden="true">→</span><span class="hx-sr-only"> became </span> <span class="hx-change-after">${c(t.after) || "<em>nothing</em>"}</span>`));
|
|
1121
|
-
return `<div class="hx-sec-block" data-proposal-mark="${c(e.mark)}" data-corn="section"><h3 class="hx-sec-title">In this proposal</h3>${e.why ? `<p class="hx-why">${c(e.why)}</p>` : ""}<div class="hx-diff hx-diff--${c(n)}" data-corn="diff-block"${R(e.mark)}>${i.join("")}</div></div>`;
|
|
1122
|
-
}
|
|
1123
|
-
return {
|
|
1124
|
-
dataSummary: o,
|
|
1125
|
-
threadsSection: s,
|
|
1126
|
-
diffSection: l,
|
|
1127
|
-
nameOf: r,
|
|
1128
|
-
nodeById: n
|
|
1129
|
-
};
|
|
1130
|
-
}
|
|
1131
|
-
function Xt(e, t, n = {}) {
|
|
1132
|
-
let { state: i } = t, o = r(t), l = Yt(t), u = n.inline === !0, d = [...a(t, e, Kt().drawer, n.slots, "drawer"), ...u ? a(t, e, `<p class="hx-panel-empty" data-corn="empty">${c(v(t, "nodePanelEmpty"))}</p>`, null, "empty") : a(t, e, Kt().backdrop, n.slots, "backdrop")], p = (e) => {
|
|
1133
|
-
for (let t of d) {
|
|
1134
|
-
if (t.id === e) return t;
|
|
1135
|
-
let n = t.querySelector(`[id="${e}"]`);
|
|
1136
|
-
if (n) return n;
|
|
1137
|
-
}
|
|
1138
|
-
return null;
|
|
1139
|
-
};
|
|
1140
|
-
o.keepParts(...d);
|
|
1141
|
-
let m = p("spec-drawer"), y = u ? { hidden: !0 } : p("drawer-backdrop"), b = u ? d.find((e) => e.matches("[data-corn=\"empty\"]")) : null, w = (e) => {
|
|
1142
|
-
b && (b.hidden = !e);
|
|
1143
|
-
}, T = !1, E = () => S(i.selectedNode, t.viewEdges(), {
|
|
1144
|
-
throughChildren: i.throughChildren,
|
|
1145
|
-
kind: i.selectedKind
|
|
1146
|
-
});
|
|
1147
|
-
function D(e) {
|
|
1148
|
-
let n = E();
|
|
1149
|
-
if (!n || !n.kinds.size) return "";
|
|
1150
|
-
let r = Ft(n).map(({ kind: e, count: t, word: r }) => `<button type="button" class="hx-lines-kind" data-corn="lines-kind" data-corn-kind="quiet" data-lines-kind="${c(e)}" data-focus-key="kind:${c(e)}" aria-pressed="${n.kind === e}">${c(r)} <span class="hx-lines-count" data-corn="count">${t}</span></button>`).join(""), a = n.kind ? It(n, n.kind).map((e) => `<button type="button" class="hx-linkbtn" data-corn="node-link" data-action="select-node" data-id="${c(e.id)}"><span class="hx-sr-only">${e.out ? "to " : "from "}</span><span aria-hidden="true">${e.out ? "→" : "←"}</span> ${c(l.nameOf(e.id))}</button>`) : [], o = a.length ? `<div class="hx-lines-list">${P(a, 12)}</div>` : "", s = S(e, t.viewEdges(), { throughChildren: !1 }).childIds.size > 0 ? `<label class="hx-lines-switch"><input type="checkbox" data-corn="lines-switch" data-lines-switch data-focus-key="switch"${i.throughChildren ? " checked" : ""}> <span>${c(v(t, "throughChildren"))}</span></label>` : "", { connected: u, off: d } = _(t);
|
|
1151
|
-
return `<div class="hx-sec-block hx-lines" id="drawer-lines" data-corn="lines-by-kind"><h3 class="hx-sec-title">Lines</h3><div class="hx-chips" role="group" aria-label="Lit lines by kind">${r}</div>${o}${s}<div class="hx-lines-reach"><span data-lines-reach>${c(Lt(u, d))}</span> <button type="button" data-corn="frame-button" data-corn-kind="secondary" class="hx-btn hx-btn--secondary" data-action="frame-selection" data-focus-key="frame">${c(v(t, "frame"))}</button></div></div>`;
|
|
1152
|
-
}
|
|
1153
|
-
function O() {
|
|
1154
|
-
let e = p("drawer-lines");
|
|
1155
|
-
if (!e || !i.selectedNode) return;
|
|
1156
|
-
let n = t.active(), r = n && e.contains(n) ? n.dataset.focusKey : "", a = t.doc.createElement("div");
|
|
1157
|
-
a.innerHTML = D(i.selectedNode), f(a);
|
|
1158
|
-
let o = a.firstElementChild;
|
|
1159
|
-
if (o ? e.replaceWith(o) : e.remove(), r) {
|
|
1160
|
-
let e = p("drawer-lines"), t = e && [...e.querySelectorAll("[data-focus-key]")].find((e) => e.dataset.focusKey === r);
|
|
1161
|
-
t && t.focus();
|
|
1162
|
-
}
|
|
1163
|
-
}
|
|
1164
|
-
function k(e) {
|
|
1165
|
-
let n = e.target.closest && e.target.closest("[data-lines-kind]");
|
|
1166
|
-
if (!n || !i.selectedNode) return !1;
|
|
1167
|
-
let r = n.dataset.linesKind;
|
|
1168
|
-
i.selectedKind = i.selectedKind === r ? null : r, t.touchScene(), t.map.render(), O();
|
|
1169
|
-
let a = E();
|
|
1170
|
-
return C(t, a && a.kind ? `Showing ${Pt(a.kind).toLowerCase()} only: ${a.edges.length} ${a.edges.length === 1 ? "line" : "lines"}` : "Showing every kind of line"), !0;
|
|
1171
|
-
}
|
|
1172
|
-
function A(e) {
|
|
1173
|
-
let n = e.target.closest && e.target.closest("[data-lines-switch]");
|
|
1174
|
-
if (!n || !i.selectedNode) return;
|
|
1175
|
-
i.throughChildren = !!n.checked, i.selectedKind = null, t.touchScene(), t.map.render(), O();
|
|
1176
|
-
let r = E();
|
|
1177
|
-
C(t, `${i.throughChildren ? "Including" : "Not including"} its children's lines: ${r ? r.connectedNodeIds.size - 1 : 0} connected`);
|
|
1178
|
-
}
|
|
1179
|
-
let N = p("drawer-meta-list");
|
|
1180
|
-
o.listen(N, "click", (e) => {
|
|
1181
|
-
k(e) || oe(e.target);
|
|
1182
|
-
}), o.listen(N, "change", A), o.own(t.map.onPaint(() => {
|
|
1183
|
-
if (!i.selectedNode) return;
|
|
1184
|
-
let e = m.querySelector("[data-lines-reach]");
|
|
1185
|
-
if (!e) return;
|
|
1186
|
-
let { connected: n, off: r } = _(t), a = Lt(n, r);
|
|
1187
|
-
e.textContent !== a && (e.textContent = a);
|
|
1188
|
-
}));
|
|
1189
|
-
function F() {
|
|
1190
|
-
let e = p("drawer-threads");
|
|
1191
|
-
e && i.selectedNode && (e.innerHTML = l.threadsSection(i.selectedNode), f(e));
|
|
1192
|
-
}
|
|
1193
|
-
function I(e, { frame: n = !1 } = {}) {
|
|
1194
|
-
if (!e || T) return;
|
|
1195
|
-
let r = p("drawer-title");
|
|
1196
|
-
r.textContent = e.tag ? `<${e.tag}>` : e.label, r.classList.toggle("hx-mono", e.type === "page" || !!e.tag), p("drawer-badge").textContent = Ut(e);
|
|
1197
|
-
let a = Wt(e);
|
|
1198
|
-
p("drawer-host").textContent = a ? ` · ${a}` : "";
|
|
1199
|
-
let o = Gt(e, i.proposal), s = p("drawer-diff");
|
|
1200
|
-
s.textContent = o, s.hidden = !o;
|
|
1201
|
-
let c = le(o ? e.mark : "");
|
|
1202
|
-
c ? s.dataset.cornState = c : delete s.dataset.cornState;
|
|
1203
|
-
let d = p("drawer-description");
|
|
1204
|
-
d.textContent = e.desc || "", d.hidden = !e.desc;
|
|
1205
|
-
let h = `${e.file ? $("File", [Z(e.file)]) : ""}${se(t, e)}${l.dataSummary(e)}`, g = t.ask("live:section", e) || "";
|
|
1206
|
-
N.innerHTML = `${D(e)}${h ? `<div class="hx-facts">${h}</div>` : ""}
|
|
1207
|
-
<div id="drawer-live">${g}</div>
|
|
1208
|
-
${ft(i, e.id)}
|
|
1209
|
-
<div id="drawer-threads">${l.threadsSection(e)}</div>
|
|
1210
|
-
${l.diffSection(e)}`, f(N), t.emit("threads:ensure"), t.emit("live:hydrate", p("drawer-live"));
|
|
1211
|
-
let _ = p("drawer-file-btn"), b = p("drawer-open-btn"), x = e.file && i.forge ? Dt(i.forge, e.file, i.forge.baseBranch) : null;
|
|
1212
|
-
_.hidden = !x, x ? _.href = x : _.removeAttribute("href");
|
|
1213
|
-
let S = !!(e.url && /^https?:\/\//.test(e.url));
|
|
1214
|
-
S ? b.href = e.url : b.removeAttribute("href"), b.hidden = !S, b.className = x ? "hx-btn hx-btn--quiet hx-foot-btn" : "hx-open", x ? b.dataset.cornKind = "quiet" : b.dataset.cornKind = "primary", b.textContent = `${v(t, "openRoute")} ↗`, _.textContent = `${v(t, "openFile")} ↗`, p("drawer-run-btn").hidden = !(i.proposalSlug && t.ask("forge:can-start")), m.classList.add("drawer-open"), m.inert = !1, y.hidden = !1, w(!1), u || ae(t, "drawer"), !n && !u && L(), t.emit("node:painted", { node: e });
|
|
1215
|
-
}
|
|
1216
|
-
function ce(e) {
|
|
1217
|
-
if (!e || T) return;
|
|
1218
|
-
let t = (e, t) => t ? `<div class="hx-fact" data-corn="section"><div class="hx-fact-k">${c(e)}</div><div class="hx-fact-v">${c(t)}</div></div>` : "", n = t("Kind", e.kind || (e.dashed ? "usage" : "ownership")) + t("Flow", e.flow) + t("Label", e.label) + t("Reads", Array.isArray(e.keys) ? e.keys.join(", ") : ""), r = p("drawer-title");
|
|
1219
|
-
r.textContent = `${l.nameOf(e.from)} → ${l.nameOf(e.to)}`, r.classList.remove("hx-mono"), p("drawer-badge").textContent = "Edge", p("drawer-host").textContent = "", p("drawer-diff").hidden = !0;
|
|
1220
|
-
let i = p("drawer-description");
|
|
1221
|
-
i.textContent = "", i.hidden = !0, N.innerHTML = `${n ? `<div class="hx-facts">${n}</div>` : ""}
|
|
1222
|
-
<div class="hx-facts">
|
|
1223
|
-
<div class="hx-fact" data-corn="section"><div class="hx-fact-k">From</div><div class="hx-fact-v"><button data-corn="node-link" type="button" class="hx-linkbtn" data-action="select-node" data-id="${c(e.from)}">${c(l.nameOf(e.from))}</button></div></div>
|
|
1224
|
-
<div class="hx-fact" data-corn="section"><div class="hx-fact-k">To</div><div class="hx-fact-v"><button data-corn="node-link" type="button" class="hx-linkbtn" data-action="select-node" data-id="${c(e.to)}">${c(l.nameOf(e.to))}</button></div></div>
|
|
1225
|
-
</div>${Te(e)}`, f(N), p("drawer-open-btn").hidden = !0, p("drawer-file-btn").hidden = !0, p("drawer-run-btn").hidden = !0, m.classList.add("drawer-open"), m.inert = !1, y.hidden = !1, w(!1);
|
|
1226
|
-
}
|
|
1227
|
-
function L() {
|
|
1228
|
-
let e = i.selectedNode;
|
|
1229
|
-
if (!e || !i.width || !h(t) || T) return;
|
|
1230
|
-
let n = g(t), r = gt(i.camera, e, {
|
|
1231
|
-
left: 0,
|
|
1232
|
-
top: 0,
|
|
1233
|
-
right: i.width,
|
|
1234
|
-
bottom: i.height - n
|
|
1235
|
-
}, e.r * i.camera.zoom + 16);
|
|
1236
|
-
r && (Object.assign(i.camera, r), t.map.render());
|
|
1237
|
-
}
|
|
1238
|
-
function R() {
|
|
1239
|
-
m.classList.remove("drawer-open"), m.inert = !0, y.hidden = !0, w(!0), u || M(t, "drawer");
|
|
1240
|
-
}
|
|
1241
|
-
function z() {
|
|
1242
|
-
i.proposalSlug && t.emit("forge:start", {
|
|
1243
|
-
slug: i.proposalSlug,
|
|
1244
|
-
returnTo: "#drawer-run-btn"
|
|
1245
|
-
});
|
|
1246
|
-
}
|
|
1247
|
-
o.own(() => clearTimeout(qt(t).timer));
|
|
1248
|
-
let ue = {
|
|
1249
|
-
"close-drawer": () => x(t, { source: "tap" }),
|
|
1250
|
-
"copy-spec": () => Jt(t, p("copy-spec-result")),
|
|
1251
|
-
"start-run": () => z(),
|
|
1252
|
-
"select-node": (e) => ee(t, l.nodeById(e.dataset.id), {
|
|
1253
|
-
frame: !0,
|
|
1254
|
-
source: "link"
|
|
1255
|
-
}),
|
|
1256
|
-
"frame-selection": () => s(t)
|
|
1257
|
-
};
|
|
1258
|
-
return o.listen(m, "click", (e) => {
|
|
1259
|
-
let t = e.target.closest && e.target.closest("[data-action]");
|
|
1260
|
-
if (!t) return;
|
|
1261
|
-
let n = ue[t.dataset.action];
|
|
1262
|
-
n && n(t), t.dataset.action === "close-drawer" && i.canvas && o.timeout(() => i.canvas.focus(), 0);
|
|
1263
|
-
}), o.listen(m, "click", (e) => {
|
|
1264
|
-
let n = e.target.closest && e.target.closest("[data-thread-open]");
|
|
1265
|
-
n ? t.emit("thread:open", { number: Number(n.dataset.threadOpen) }) : e.target.closest && e.target.closest("[data-thread-start]") && i.selectedNode && t.emit("thread:start", { node: i.selectedNode });
|
|
1266
|
-
}), o.on("threads:changed", () => F()), u || o.listen(y, "click", (e) => {
|
|
1267
|
-
h(t) ? j(t, e) : x(t, { source: "tap" });
|
|
1268
|
-
}, !0), o.listen(m, "keydown", (e) => {
|
|
1269
|
-
e.key !== "Escape" || e.defaultPrevented || e.target.closest && e.target.closest("select, input, textarea") || (e.preventDefault(), x(t, { source: "keyboard" }), i.canvas && i.canvas.focus(), C(t, "Panel closed"));
|
|
1270
|
-
}), o.on("panel:present", () => !0), o.on("panel:covers", () => !u && !T && !m.hidden && m.classList.contains("drawer-open") ? { right: m.offsetWidth } : void 0), o.on("node:show", ({ node: e, frame: t }) => I(e, { frame: t })), o.on("node:close", R), o.on("node:show-edge", ({ edge: e }) => ce(e)), o.on("node:focus", () => {
|
|
1271
|
-
let e = p("drawer-title");
|
|
1272
|
-
if (!e) return;
|
|
1273
|
-
let n = t.active();
|
|
1274
|
-
u && n && n !== e && typeof n.matches == "function" && n.matches("[data-corn=\"node-title\"]") || (e.setAttribute("tabindex", "-1"), e.focus());
|
|
1275
|
-
}), u || (o.own(ie(t, () => L())), re(t), te(t, "drawer", m, { stub: () => ({ title: p("drawer-title") && p("drawer-title").textContent || "Node" }) }), o.own(() => ne(t, "drawer"))), i.selectedNode && I(i.selectedNode, { frame: !1 }), o.own(() => {
|
|
1276
|
-
T = !0, d.forEach((e) => e.remove());
|
|
1277
|
-
}), {
|
|
1278
|
-
elements: d,
|
|
1279
|
-
show: I,
|
|
1280
|
-
close: R,
|
|
1281
|
-
repaintThreads: F,
|
|
1282
|
-
copySpec: () => Jt(t, p("copy-spec-result")),
|
|
1283
|
-
startRun: z,
|
|
1284
|
-
keepSelectedInView: L,
|
|
1285
|
-
update(e) {
|
|
1286
|
-
e && "node" in e ? e.node ? ee(t, e.node, { source: "api" }) : x(t, { source: "api" }) : i.selectedNode && m.classList.contains("drawer-open") && I(i.selectedNode, { frame: !1 });
|
|
1287
|
-
},
|
|
1288
|
-
destroy: () => o.destroy()
|
|
1289
|
-
};
|
|
1290
|
-
}
|
|
1291
|
-
export { R as A, V as C, de as D, Ne as E, ue as O, Me as S, ge as T, be as _, pt as a, xe as b, nt as c, at as d, pe as f, me as g, he as h, yt as i, L as k, K as l, fe as m, Rt as n, mt as o, B as p, bt as r, ht as s, Xt as t, it as u, _e as v, ke as w, Ae as x, je as y };
|