okno 1.0.0-alpha.20 → 1.0.0-alpha.21
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/dist/editor/index.js +7957 -7612
- package/dist/runtime/wrap.d.ts.map +1 -1
- package/dist/runtime/wrap.js +123 -121
- package/package.json +3 -3
- package/src/runtime/wrap.test.ts +82 -0
- package/src/runtime/wrap.ts +6 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/runtime/wrap.ts"],"names":[],"mappings":"AAyGA;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG,CA2L5E;AAoDD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC9B,OAAO,
|
|
1
|
+
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/runtime/wrap.ts"],"names":[],"mappings":"AAyGA;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAChD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG,CA2L5E;AAoDD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC9B,OAAO,CA8BT;AAiBD,MAAM,WAAW,mBAAmB;IACnC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACnC,cAAc;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;kFAG8E;IAC9E,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACpC;;kEAE8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B;AAsGD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CA6DtE;AA6DD;2EAC2E;AAC3E,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C"}
|
package/dist/runtime/wrap.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const y = /* @__PURE__ */ new Map();
|
|
2
|
-
let
|
|
3
|
-
function
|
|
2
|
+
let g = !1;
|
|
3
|
+
function T() {
|
|
4
4
|
const t = globalThis;
|
|
5
|
-
|
|
6
|
-
const { path: i, value:
|
|
7
|
-
y.get(i)?.forEach((n) => n(
|
|
5
|
+
g || typeof t.document > "u" || (g = !0, t.document.addEventListener("okno:change", (r) => {
|
|
6
|
+
const { path: i, value: s } = r.detail;
|
|
7
|
+
y.get(i)?.forEach((n) => n(s));
|
|
8
8
|
}));
|
|
9
9
|
}
|
|
10
|
-
const
|
|
10
|
+
const E = /* @__PURE__ */ new Set([
|
|
11
11
|
"src",
|
|
12
12
|
"href",
|
|
13
13
|
"alt",
|
|
@@ -20,90 +20,90 @@ const j = /* @__PURE__ */ new Set([
|
|
|
20
20
|
"name",
|
|
21
21
|
"value"
|
|
22
22
|
]);
|
|
23
|
-
function
|
|
23
|
+
function j(t) {
|
|
24
24
|
return t.replace(/[-_]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim().replace(/^./, (r) => r.toUpperCase());
|
|
25
25
|
}
|
|
26
|
-
function
|
|
26
|
+
function b(t, r = "") {
|
|
27
27
|
if (t == null) {
|
|
28
28
|
if (!r) return "";
|
|
29
29
|
const i = r.split(".").pop() ?? "";
|
|
30
|
-
return !i ||
|
|
30
|
+
return !i || E.has(i) ? "" : j(i);
|
|
31
31
|
}
|
|
32
32
|
return typeof t != "object" ? String(t) : m(t) ? t.text ?? "" : "";
|
|
33
33
|
}
|
|
34
|
-
function
|
|
34
|
+
function A(t) {
|
|
35
35
|
return typeof t == "object" && t !== null && !Array.isArray(t) && "src" in t;
|
|
36
36
|
}
|
|
37
37
|
function m(t) {
|
|
38
38
|
return typeof t == "object" && t !== null && !Array.isArray(t) && "url" in t && "text" in t && "external" in t;
|
|
39
39
|
}
|
|
40
|
-
function
|
|
40
|
+
function k(t, r) {
|
|
41
41
|
if (r === void 0) return t;
|
|
42
42
|
if (t === null || typeof t != "object" || Array.isArray(t) || r === null || typeof r != "object" || Array.isArray(r))
|
|
43
43
|
return r;
|
|
44
44
|
const i = { ...t };
|
|
45
|
-
for (const
|
|
46
|
-
i[
|
|
45
|
+
for (const s of Object.keys(r))
|
|
46
|
+
i[s] = k(t[s], r[s]);
|
|
47
47
|
return i;
|
|
48
48
|
}
|
|
49
|
-
function
|
|
49
|
+
function q(t, r) {
|
|
50
50
|
const i = { ...t };
|
|
51
|
-
for (const
|
|
52
|
-
i[
|
|
51
|
+
for (const s of Object.keys(r))
|
|
52
|
+
i[s] = k(t, r[s]);
|
|
53
53
|
return i;
|
|
54
54
|
}
|
|
55
|
-
function
|
|
56
|
-
const
|
|
57
|
-
return new Proxy(
|
|
55
|
+
function p(t, r, i) {
|
|
56
|
+
const s = { __raw: t, __path: r, __slot: i };
|
|
57
|
+
return new Proxy(s, {
|
|
58
58
|
get(n, e) {
|
|
59
59
|
if (e === "data-okno") return n.__path;
|
|
60
60
|
if (e === "slot") return { "data-okno-item": n.__slot ?? n.__path };
|
|
61
61
|
if (e === Symbol.toPrimitive || e === "toString" || e === "valueOf")
|
|
62
|
-
return () =>
|
|
62
|
+
return () => b(n.__raw, n.__path);
|
|
63
63
|
if (e === Symbol.iterator) {
|
|
64
|
-
const
|
|
64
|
+
const f = b(n.__raw, n.__path);
|
|
65
65
|
return function* () {
|
|
66
|
-
yield
|
|
66
|
+
yield f;
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
if (typeof e == "symbol") return;
|
|
70
70
|
if (e === "toJSON") return () => n.__raw;
|
|
71
71
|
if (e === "on")
|
|
72
|
-
return (
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
return y.has(
|
|
76
|
-
y.get(
|
|
72
|
+
return (f) => {
|
|
73
|
+
T();
|
|
74
|
+
const c = n.__path;
|
|
75
|
+
return y.has(c) || y.set(c, /* @__PURE__ */ new Set()), y.get(c).add(f), () => {
|
|
76
|
+
y.get(c)?.delete(f), y.get(c)?.size === 0 && y.delete(c);
|
|
77
77
|
};
|
|
78
78
|
};
|
|
79
79
|
if (e === "locale")
|
|
80
|
-
return (
|
|
81
|
-
const
|
|
82
|
-
return
|
|
83
|
-
|
|
80
|
+
return (f) => {
|
|
81
|
+
const c = n.__raw;
|
|
82
|
+
return f && c !== null && typeof c == "object" && !Array.isArray(c) && typeof c[f] == "object" && c[f] !== null ? p(
|
|
83
|
+
c[f],
|
|
84
84
|
n.__path
|
|
85
|
-
) :
|
|
85
|
+
) : p(c, n.__path);
|
|
86
86
|
};
|
|
87
|
-
const o = n.__raw,
|
|
87
|
+
const o = n.__raw, a = n.__path ? `${n.__path}.${String(e)}` : String(e);
|
|
88
88
|
if (m(o) && typeof e == "string") {
|
|
89
89
|
if (e === "href") return o.url ?? "";
|
|
90
90
|
if (e === "target" && o.external) return "_blank";
|
|
91
91
|
if (e === "rel" && o.external) return "noopener noreferrer";
|
|
92
92
|
}
|
|
93
93
|
if (o != null && typeof o != "object") {
|
|
94
|
-
const
|
|
95
|
-
return
|
|
94
|
+
const f = o[e];
|
|
95
|
+
return f !== void 0 ? typeof f == "function" ? (...c) => f.apply(o, c) : f : p(null, a);
|
|
96
96
|
}
|
|
97
97
|
if (o != null && typeof o == "object" && !Array.isArray(o)) {
|
|
98
|
-
const
|
|
99
|
-
return
|
|
98
|
+
const f = o[String(e)];
|
|
99
|
+
return f == null ? p(null, a) : $(f, a);
|
|
100
100
|
}
|
|
101
|
-
return
|
|
101
|
+
return p(null, a);
|
|
102
102
|
},
|
|
103
103
|
// For spread: expose data-okno, plus all keys for file objects (src, alt, width, height, etc.)
|
|
104
104
|
ownKeys(n) {
|
|
105
105
|
const e = n.__raw;
|
|
106
|
-
return
|
|
106
|
+
return A(e) ? [...Object.keys(e), "data-okno"] : m(e) ? e.external ? ["href", "target", "rel", "data-okno"] : ["href", "data-okno"] : ["data-okno"];
|
|
107
107
|
},
|
|
108
108
|
getOwnPropertyDescriptor(n, e) {
|
|
109
109
|
if (e === "data-okno")
|
|
@@ -113,7 +113,7 @@ function _(t, r, i) {
|
|
|
113
113
|
configurable: !0
|
|
114
114
|
};
|
|
115
115
|
const o = n.__raw;
|
|
116
|
-
if (
|
|
116
|
+
if (A(o) && typeof e == "string" && e in o)
|
|
117
117
|
return {
|
|
118
118
|
value: o[e],
|
|
119
119
|
enumerable: !0,
|
|
@@ -129,144 +129,146 @@ function _(t, r, i) {
|
|
|
129
129
|
}
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
|
-
function
|
|
132
|
+
function w(t) {
|
|
133
133
|
return t !== null && typeof t == "object" && !Array.isArray(t) && "__oknoRef" in t;
|
|
134
134
|
}
|
|
135
|
-
function
|
|
136
|
-
if (
|
|
137
|
-
const { path:
|
|
138
|
-
return
|
|
135
|
+
function $(t, r, i) {
|
|
136
|
+
if (w(t)) {
|
|
137
|
+
const { path: s, data: n } = t.__oknoRef;
|
|
138
|
+
return p(n, s, i ?? s);
|
|
139
139
|
}
|
|
140
140
|
if (Array.isArray(t)) {
|
|
141
|
-
const
|
|
142
|
-
return Object.defineProperty(
|
|
143
|
-
value: () => t.map((n) =>
|
|
141
|
+
const s = t.map((n, e) => $(n, `${r}.${e}`, `${r}.${e}`));
|
|
142
|
+
return Object.defineProperty(s, "toJSON", {
|
|
143
|
+
value: () => t.map((n) => w(n) ? n.__oknoRef.data : n),
|
|
144
144
|
enumerable: !1
|
|
145
|
-
}),
|
|
145
|
+
}), s;
|
|
146
146
|
}
|
|
147
|
-
return
|
|
147
|
+
return p(t, r, i);
|
|
148
148
|
}
|
|
149
|
-
function
|
|
149
|
+
function z(t, r, i) {
|
|
150
150
|
if (!t || typeof t != "object" || Array.isArray(t) || !r) return t;
|
|
151
|
-
const
|
|
151
|
+
const s = { ...t };
|
|
152
152
|
for (const n of Object.keys(r)) {
|
|
153
153
|
const e = r[n];
|
|
154
154
|
if (!e || e.type !== "reference" || typeof e.collection != "string") continue;
|
|
155
|
-
const o = i?.[e.collection] ?? i?.[e.collection.replace(/-/g, "_")] ?? [],
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (!
|
|
162
|
-
const l =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
155
|
+
const o = i?.[e.collection] ?? i?.[e.collection.replace(/-/g, "_")] ?? [], a = /* @__PURE__ */ new Map();
|
|
156
|
+
for (const u of o) {
|
|
157
|
+
const l = typeof u?.toJSON == "function" ? u.toJSON() : u;
|
|
158
|
+
l && typeof l == "object" && typeof l.slug == "string" && a.set(l.slug, u);
|
|
159
|
+
}
|
|
160
|
+
const f = (u) => {
|
|
161
|
+
if (typeof u != "string" || !u) return null;
|
|
162
|
+
const l = a.get(u);
|
|
163
|
+
if (!l) return null;
|
|
164
|
+
const S = typeof l.toJSON == "function" ? l.toJSON() : l;
|
|
165
|
+
return { __oknoRef: { path: `${e.collection}.${u}`, data: S } };
|
|
166
|
+
}, c = t[n];
|
|
167
|
+
s[n] = Array.isArray(c) ? c.map(f).filter(Boolean) : f(c);
|
|
166
168
|
}
|
|
167
|
-
return
|
|
169
|
+
return s;
|
|
168
170
|
}
|
|
169
|
-
const
|
|
170
|
-
function d(t, r, i,
|
|
171
|
+
const _ = "data-okno-item", h = "data-okno", O = [h, _];
|
|
172
|
+
function d(t, r, i, s = O) {
|
|
171
173
|
if (r === i) return;
|
|
172
174
|
const n = (e) => {
|
|
173
|
-
for (const o of
|
|
174
|
-
const
|
|
175
|
-
|
|
175
|
+
for (const o of s) {
|
|
176
|
+
const a = e.getAttribute(o);
|
|
177
|
+
a != null && (a === r ? e.setAttribute(o, i) : a.startsWith(r + ".") && e.setAttribute(o, i + a.slice(r.length)));
|
|
176
178
|
}
|
|
177
179
|
};
|
|
178
180
|
n(t);
|
|
179
|
-
for (const e of
|
|
181
|
+
for (const e of s) t.querySelectorAll(`[${e}]`).forEach(n);
|
|
180
182
|
}
|
|
181
|
-
function
|
|
183
|
+
function x(t) {
|
|
182
184
|
if (typeof document > "u") return [];
|
|
183
185
|
const r = new RegExp(`^${t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.(\\d+)$`), i = /* @__PURE__ */ new Map();
|
|
184
|
-
document.querySelectorAll(`[${
|
|
185
|
-
const e = n.getAttribute(
|
|
186
|
+
document.querySelectorAll(`[${_}]`).forEach((n) => {
|
|
187
|
+
const e = n.getAttribute(_);
|
|
186
188
|
if (!e || !r.test(e) || !n.parentElement || !(n instanceof HTMLElement)) return;
|
|
187
189
|
const o = i.get(n.parentElement) ?? [];
|
|
188
190
|
o.push(n), i.set(n.parentElement, o);
|
|
189
191
|
});
|
|
190
|
-
const
|
|
192
|
+
const s = (n) => Number(n.getAttribute(_).match(r)[1]);
|
|
191
193
|
return [...i.entries()].map(([n, e]) => ({
|
|
192
194
|
parent: n,
|
|
193
|
-
wrappers: e.sort((o,
|
|
195
|
+
wrappers: e.sort((o, a) => s(o) - s(a))
|
|
194
196
|
}));
|
|
195
197
|
}
|
|
196
|
-
function
|
|
198
|
+
function L(t) {
|
|
197
199
|
t.querySelectorAll(`[${h}]`).forEach((r) => {
|
|
198
200
|
r.children.length === 0 && (r.textContent = "");
|
|
199
201
|
});
|
|
200
202
|
}
|
|
201
|
-
function
|
|
203
|
+
function M(t, r) {
|
|
202
204
|
t.querySelectorAll(`[${h}]`).forEach((i) => {
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
+
const s = i.getAttribute(h);
|
|
206
|
+
s && s in r && i.children.length === 0 && (i.textContent = r[s] ?? "");
|
|
205
207
|
});
|
|
206
208
|
}
|
|
207
|
-
function
|
|
209
|
+
function N() {
|
|
208
210
|
return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
209
211
|
}
|
|
210
|
-
function
|
|
212
|
+
function R(t) {
|
|
211
213
|
const r = document;
|
|
212
|
-
return typeof r.startViewTransition != "function" ||
|
|
214
|
+
return typeof r.startViewTransition != "function" || N() ? (t(), Promise.resolve()) : r.startViewTransition(t).finished.catch(() => {
|
|
213
215
|
});
|
|
214
216
|
}
|
|
215
|
-
let
|
|
216
|
-
function
|
|
217
|
+
let C = 0;
|
|
218
|
+
function H(t) {
|
|
217
219
|
if (typeof document > "u" || !t?.list || !t.op) return;
|
|
218
|
-
const { list: r, op: i } = t,
|
|
219
|
-
if (i === "insert" &&
|
|
220
|
-
const n = [], e = (
|
|
221
|
-
|
|
220
|
+
const { list: r, op: i } = t, s = x(r);
|
|
221
|
+
if (i === "insert" && s.every((u) => u.wrappers.length === 0) || s.length === 0) return;
|
|
222
|
+
const n = [], e = (u) => {
|
|
223
|
+
u.style.viewTransitionName = `okno-vt-${++C}`, n.push(u);
|
|
222
224
|
};
|
|
223
|
-
for (const
|
|
225
|
+
for (const u of s) for (const l of u.wrappers) e(l);
|
|
224
226
|
const o = document.documentElement;
|
|
225
227
|
o.classList.add("okno-vt-active");
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
for (const
|
|
229
|
-
i === "reorder" ?
|
|
228
|
+
const a = document.getElementById("okno-shadow-root"), f = a instanceof HTMLElement ? a.style.cssText : null;
|
|
229
|
+
a instanceof HTMLElement && (a.style.cssText = `${f};position:fixed;inset:0;pointer-events:none;view-transition-name:okno-editor`), R(() => {
|
|
230
|
+
for (const u of s)
|
|
231
|
+
i === "reorder" ? I(u, r, t.from, t.to) : i === "remove" ? J(u, r, t.index) : i === "insert" && V(u, r, t, e);
|
|
230
232
|
}).finally(() => {
|
|
231
|
-
for (const
|
|
232
|
-
o.classList.remove("okno-vt-active"),
|
|
233
|
+
for (const u of n) u.style.viewTransitionName = "";
|
|
234
|
+
o.classList.remove("okno-vt-active"), a instanceof HTMLElement && f !== null && (a.style.cssText = f);
|
|
233
235
|
});
|
|
234
236
|
}
|
|
235
|
-
function
|
|
237
|
+
function I(t, r, i, s) {
|
|
236
238
|
const n = t.wrappers, e = n.length;
|
|
237
|
-
if (i < 0 || i >= e ||
|
|
238
|
-
const o = n.slice(), [
|
|
239
|
-
o.splice(
|
|
240
|
-
const
|
|
241
|
-
o.forEach((
|
|
242
|
-
const
|
|
243
|
-
for (const
|
|
239
|
+
if (i < 0 || i >= e || s < 0 || s >= e || i === s) return;
|
|
240
|
+
const o = n.slice(), [a] = o.splice(i, 1);
|
|
241
|
+
o.splice(s, 0, a);
|
|
242
|
+
const f = o.map((u) => u.getAttribute(_));
|
|
243
|
+
o.forEach((u, l) => d(u, f[l], `${r}.${l}`));
|
|
244
|
+
const c = n[e - 1].nextSibling;
|
|
245
|
+
for (const u of o) t.parent.insertBefore(u, c);
|
|
244
246
|
}
|
|
245
|
-
function
|
|
246
|
-
const
|
|
247
|
-
if (!(i < 0 || i >=
|
|
248
|
-
|
|
249
|
-
for (let n = i + 1; n <
|
|
247
|
+
function J(t, r, i) {
|
|
248
|
+
const s = t.wrappers;
|
|
249
|
+
if (!(i < 0 || i >= s.length)) {
|
|
250
|
+
s[i].remove();
|
|
251
|
+
for (let n = i + 1; n < s.length; n++) d(s[n], `${r}.${n}`, `${r}.${n - 1}`);
|
|
250
252
|
}
|
|
251
253
|
}
|
|
252
|
-
function
|
|
254
|
+
function V(t, r, i, s) {
|
|
253
255
|
const n = t.wrappers, e = n.length;
|
|
254
256
|
if (e === 0) return;
|
|
255
|
-
const o = Math.max(0, Math.min(i.index ?? e, e)),
|
|
257
|
+
const o = Math.max(0, Math.min(i.index ?? e, e)), a = o < e ? o : e - 1, f = n[a].getAttribute(_), c = n[a].cloneNode(!0);
|
|
256
258
|
for (let l = e - 1; l >= o; l--) d(n[l], `${r}.${l}`, `${r}.${l + 1}`);
|
|
257
|
-
d(
|
|
258
|
-
const
|
|
259
|
-
t.parent.insertBefore(
|
|
259
|
+
d(c, f, `${r}.${o}`), i.remap && d(c, i.remap.from, i.remap.to, [h]), i.values ? M(c, i.values) : L(c), c.style.viewTransitionName = "", s(c);
|
|
260
|
+
const u = o < e ? n[o] : n[e - 1].nextSibling;
|
|
261
|
+
t.parent.insertBefore(c, u);
|
|
260
262
|
}
|
|
261
|
-
let
|
|
262
|
-
function
|
|
263
|
+
let v = !1;
|
|
264
|
+
function B() {
|
|
263
265
|
const t = globalThis;
|
|
264
|
-
|
|
266
|
+
v || typeof t.document > "u" || (v = !0, t.document.addEventListener("okno:structure", (r) => H(r.detail)));
|
|
265
267
|
}
|
|
266
268
|
export {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
H as __oknoApplyStructure,
|
|
270
|
+
B as __oknoInitStructure,
|
|
271
|
+
q as __oknoLocalize,
|
|
272
|
+
z as __oknoResolveRefs,
|
|
273
|
+
p as __oknoWrap
|
|
272
274
|
};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "okno",
|
|
3
3
|
"description": "Git-backed CMS with live editing for any Vite framework",
|
|
4
4
|
"author": "Gabriel Uhlíř",
|
|
5
|
-
"version": "1.0.0-alpha.
|
|
5
|
+
"version": "1.0.0-alpha.21",
|
|
6
6
|
"homepage": "https://okno.build",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"acorn": "^8.11.3",
|
|
58
58
|
"bits-ui": "^2.18.0",
|
|
59
59
|
"runed": "^0.23.0",
|
|
60
|
-
"simple-git": "^3.
|
|
60
|
+
"simple-git": "^3.32.0",
|
|
61
61
|
"svelte": "^5.55.0",
|
|
62
62
|
"svelte-dnd-action": "^0.9.69"
|
|
63
63
|
},
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"tailwindcss": "^4.0.0",
|
|
74
74
|
"tailwindcss-animate": "^1.0.7",
|
|
75
75
|
"typescript": "^5.9.2",
|
|
76
|
-
"vite": "^6.4.
|
|
76
|
+
"vite": "^6.4.3"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"svelte": "^5.0.0",
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
import { __oknoResolveRefs } from "./wrap"
|
|
3
|
+
|
|
4
|
+
describe("__oknoResolveRefs", () => {
|
|
5
|
+
test("single ref happy path", () => {
|
|
6
|
+
const raw = { author: "jane" }
|
|
7
|
+
const fields = { author: { type: "reference", collection: "authors" } }
|
|
8
|
+
const collections = { authors: [{ slug: "jane", name: "Jane" }] }
|
|
9
|
+
const result = __oknoResolveRefs(raw, fields, collections) as any
|
|
10
|
+
expect(result.author).toEqual({
|
|
11
|
+
__oknoRef: { path: "authors.jane", data: { slug: "jane", name: "Jane" } },
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test("array refs with a missing id filtered out", () => {
|
|
16
|
+
const raw = { authors: ["jane", "unknown"] }
|
|
17
|
+
const fields = { authors: { type: "reference", collection: "authors" } }
|
|
18
|
+
const collections = { authors: [{ slug: "jane", name: "Jane" }] }
|
|
19
|
+
const result = __oknoResolveRefs(raw, fields, collections) as any
|
|
20
|
+
expect(result.authors).toHaveLength(1)
|
|
21
|
+
expect(result.authors[0].__oknoRef.path).toBe("authors.jane")
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test("item with toJSON method — data is toJSON output, match by toJSON slug", () => {
|
|
25
|
+
const item = {
|
|
26
|
+
_raw: { slug: "bob", name: "Bob" },
|
|
27
|
+
toJSON() {
|
|
28
|
+
return this._raw
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
const raw = { author: "bob" }
|
|
32
|
+
const fields = { author: { type: "reference", collection: "people" } }
|
|
33
|
+
const collections = { people: [item] }
|
|
34
|
+
const result = __oknoResolveRefs(raw, fields, collections) as any
|
|
35
|
+
expect(result.author.__oknoRef.data).toEqual({ slug: "bob", name: "Bob" })
|
|
36
|
+
expect(result.author.__oknoRef.path).toBe("people.bob")
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test("dash/underscore fallback — def.collection dashed, collections key underscored", () => {
|
|
40
|
+
const raw = { post: "hello" }
|
|
41
|
+
const fields = { post: { type: "reference", collection: "blog-posts" } }
|
|
42
|
+
const collections = { blog_posts: [{ slug: "hello", title: "Hello World" }] }
|
|
43
|
+
const result = __oknoResolveRefs(raw, fields, collections) as any
|
|
44
|
+
expect(result.post.__oknoRef.path).toBe("blog-posts.hello")
|
|
45
|
+
expect(result.post.__oknoRef.data).toEqual({ slug: "hello", title: "Hello World" })
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test("non-reference field passes through untouched", () => {
|
|
49
|
+
const raw = { title: "Hello", author: "jane" }
|
|
50
|
+
const fields = {
|
|
51
|
+
title: { type: "text" },
|
|
52
|
+
author: { type: "reference", collection: "authors" },
|
|
53
|
+
}
|
|
54
|
+
const collections = { authors: [{ slug: "jane", name: "Jane" }] }
|
|
55
|
+
const result = __oknoResolveRefs(raw, fields, collections) as any
|
|
56
|
+
expect(result.title).toBe("Hello")
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test("null id returns null (single ref)", () => {
|
|
60
|
+
const raw = { author: null }
|
|
61
|
+
const fields = { author: { type: "reference", collection: "authors" } }
|
|
62
|
+
const collections = { authors: [{ slug: "jane", name: "Jane" }] }
|
|
63
|
+
const result = __oknoResolveRefs(raw, fields, collections) as any
|
|
64
|
+
expect(result.author).toBeNull()
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test("empty string id returns null", () => {
|
|
68
|
+
const raw = { author: "" }
|
|
69
|
+
const fields = { author: { type: "reference", collection: "authors" } }
|
|
70
|
+
const collections = { authors: [{ slug: "jane", name: "Jane" }] }
|
|
71
|
+
const result = __oknoResolveRefs(raw, fields, collections) as any
|
|
72
|
+
expect(result.author).toBeNull()
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test("unknown id returns null (single ref)", () => {
|
|
76
|
+
const raw = { author: "nobody" }
|
|
77
|
+
const fields = { author: { type: "reference", collection: "authors" } }
|
|
78
|
+
const collections = { authors: [{ slug: "jane", name: "Jane" }] }
|
|
79
|
+
const result = __oknoResolveRefs(raw, fields, collections) as any
|
|
80
|
+
expect(result.author).toBeNull()
|
|
81
|
+
})
|
|
82
|
+
})
|
package/src/runtime/wrap.ts
CHANGED
|
@@ -392,12 +392,14 @@ export function __oknoResolveRefs(
|
|
|
392
392
|
const list: any[] =
|
|
393
393
|
collections?.[def.collection] ?? collections?.[def.collection.replace(/-/g, "_")] ?? []
|
|
394
394
|
|
|
395
|
+
const bySlug = new Map<string, any>()
|
|
396
|
+
for (const it of list) {
|
|
397
|
+
const r = typeof it?.toJSON === "function" ? it.toJSON() : it
|
|
398
|
+
if (r && typeof r === "object" && typeof r.slug === "string") bySlug.set(r.slug, it)
|
|
399
|
+
}
|
|
395
400
|
const resolve = (id: unknown): OknoRef | null => {
|
|
396
401
|
if (typeof id !== "string" || !id) return null
|
|
397
|
-
const item =
|
|
398
|
-
const r = typeof it?.toJSON === "function" ? it.toJSON() : it
|
|
399
|
-
return r && typeof r === "object" && r.slug === id
|
|
400
|
-
})
|
|
402
|
+
const item = bySlug.get(id)
|
|
401
403
|
if (!item) return null
|
|
402
404
|
const data = typeof item.toJSON === "function" ? item.toJSON() : item
|
|
403
405
|
return { __oknoRef: { path: `${def.collection}.${id}`, data } }
|