okno 1.0.0-alpha.2 → 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/acorn-CZBJD705.js +3143 -0
- package/dist/boot.d.ts +88 -0
- package/dist/boot.d.ts.map +1 -0
- package/dist/boot.js +98 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +22 -0
- package/dist/codegen/generate.d.ts +5 -1
- package/dist/codegen/generate.d.ts.map +1 -1
- package/dist/codegen/scan-imports.d.ts +9 -0
- package/dist/codegen/scan-imports.d.ts.map +1 -0
- package/dist/content-encode-DoojdsVU.js +80 -0
- package/dist/core/content-encode.d.ts +44 -0
- package/dist/core/content-encode.d.ts.map +1 -0
- package/dist/core/order.d.ts +18 -0
- package/dist/core/order.d.ts.map +1 -0
- package/dist/core/parse.d.ts +15 -0
- package/dist/core/parse.d.ts.map +1 -0
- package/dist/editor/index.js +29645 -15293
- package/dist/index-B1PShnsc.js +132 -0
- package/dist/index-B2WzdTzI.js +14263 -0
- package/dist/index-ButdD9Pf.js +1825 -0
- package/dist/index-DKF0siIz.js +5497 -0
- package/dist/index-q-7MEoHz.js +47 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/init.d.ts +39 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +221 -0
- package/dist/mcp.d.ts +4 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +140 -0
- package/dist/okno.css +1 -0
- package/dist/order-bAkdncZC.js +21 -0
- package/dist/plugin-Cy62173B.js +1080 -0
- package/dist/runtime/wrap.d.ts +48 -1
- package/dist/runtime/wrap.d.ts.map +1 -1
- package/dist/runtime/wrap.js +274 -0
- package/dist/types/fields.d.ts +54 -6
- package/dist/types/fields.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/permissions.d.ts +22 -0
- package/dist/types/permissions.d.ts.map +1 -0
- package/dist/types/schema.d.ts +41 -6
- package/dist/types/schema.d.ts.map +1 -1
- package/dist/vite/dev-server.d.ts +8 -0
- package/dist/vite/dev-server.d.ts.map +1 -1
- package/dist/vite/index.js +1 -1
- package/dist/vite/local-engine.d.ts +34 -0
- package/dist/vite/local-engine.d.ts.map +1 -0
- package/dist/vite/plugin.d.ts.map +1 -1
- package/package.json +42 -11
- package/skills/connect-okno/SKILL.md +367 -0
- package/src/runtime/wrap.test.ts +82 -0
- package/src/runtime/wrap.ts +684 -0
- package/dist/plugin-Cwwh6E1P.js +0 -440
package/dist/runtime/wrap.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compose a localized value from the default-locale `base` and a map of
|
|
3
|
+
* per-locale override objects: `{ ...base, <loc>: deepMerge(base, override) }`.
|
|
4
|
+
* The default stays flat at the root; each locale inherits the default then
|
|
5
|
+
* applies its overrides. Generated by the Vite plugin for localized content.
|
|
6
|
+
*/
|
|
7
|
+
export declare function __oknoLocalize(base: Record<string, unknown>, overrides: Record<string, Record<string, unknown>>): Record<string, unknown>;
|
|
1
8
|
/**
|
|
2
9
|
* Wraps content data in a Proxy that:
|
|
3
10
|
* - Returns `data-okno` attribute when spread ({...value})
|
|
@@ -7,5 +14,45 @@
|
|
|
7
14
|
* - Returns empty proxies for non-existing fields
|
|
8
15
|
* - Supports .on(callback) for reactive change subscriptions
|
|
9
16
|
*/
|
|
10
|
-
export declare function __oknoWrap(data: unknown, prefix: string): any;
|
|
17
|
+
export declare function __oknoWrap(data: unknown, prefix: string, slot?: string): any;
|
|
18
|
+
/**
|
|
19
|
+
* Replace reference fields (id or id[]) on a raw record with `__oknoRef` markers
|
|
20
|
+
* carrying the resolved collection item's RAW data + its `<collection>.<id>`
|
|
21
|
+
* path. Driven by the entry's schema `fields` (emitted by the build plugin);
|
|
22
|
+
* `collections` is the `okno:collections` namespace. Non-reference fields pass
|
|
23
|
+
* through untouched. Resolution is one level deep — a referenced item's own
|
|
24
|
+
* references are not re-resolved (avoids cycles).
|
|
25
|
+
*/
|
|
26
|
+
export declare function __oknoResolveRefs(raw: unknown, fields: Record<string, any> | undefined, collections: Record<string, any>): unknown;
|
|
27
|
+
export interface OknoStructureDetail {
|
|
28
|
+
/** The array field path, e.g. "home.block" or "home.featuredArticles". */
|
|
29
|
+
list: string;
|
|
30
|
+
op: "reorder" | "remove" | "insert";
|
|
31
|
+
/** reorder */
|
|
32
|
+
from?: number;
|
|
33
|
+
to?: number;
|
|
34
|
+
/** remove / insert — the affected index (insert position). */
|
|
35
|
+
index?: number;
|
|
36
|
+
/** insert (references only): remap the cloned template's CONTENT paths
|
|
37
|
+
* (`data-okno`) from one collection-item prefix to another, since a
|
|
38
|
+
* reference item's content lives at `<collection>.<slug>`, not under the
|
|
39
|
+
* list. Slot boundaries (`data-okno-item`) are always renumbered by list. */
|
|
40
|
+
remap?: {
|
|
41
|
+
from: string;
|
|
42
|
+
to: string;
|
|
43
|
+
};
|
|
44
|
+
/** insert: absolute content path → string value, used to fill the cloned
|
|
45
|
+
* item's text leaves (so a new reference shows the linked item's content;
|
|
46
|
+
* block defaults are empty so the clone is just cleared). */
|
|
47
|
+
values?: Record<string, string>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Apply a structural op to the live DOM. Attached to `okno:structure` by
|
|
51
|
+
* `__oknoInitStructure()`. The editor calls `updateField` for its optimistic
|
|
52
|
+
* state in the same tick; this keeps the rendered page in sync without a reload.
|
|
53
|
+
*/
|
|
54
|
+
export declare function __oknoApplyStructure(detail: OknoStructureDetail): void;
|
|
55
|
+
/** Attach the `okno:structure` listener once. Called by the editor (which is
|
|
56
|
+
* the reliable client-side presence) on scan; safe to call repeatedly. */
|
|
57
|
+
export declare function __oknoInitStructure(): void;
|
|
11
58
|
//# sourceMappingURL=wrap.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/runtime/wrap.ts"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
const y = /* @__PURE__ */ new Map();
|
|
2
|
+
let g = !1;
|
|
3
|
+
function T() {
|
|
4
|
+
const t = globalThis;
|
|
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
|
+
}));
|
|
9
|
+
}
|
|
10
|
+
const E = /* @__PURE__ */ new Set([
|
|
11
|
+
"src",
|
|
12
|
+
"href",
|
|
13
|
+
"alt",
|
|
14
|
+
"id",
|
|
15
|
+
"class",
|
|
16
|
+
"className",
|
|
17
|
+
"width",
|
|
18
|
+
"height",
|
|
19
|
+
"type",
|
|
20
|
+
"name",
|
|
21
|
+
"value"
|
|
22
|
+
]);
|
|
23
|
+
function j(t) {
|
|
24
|
+
return t.replace(/[-_]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim().replace(/^./, (r) => r.toUpperCase());
|
|
25
|
+
}
|
|
26
|
+
function b(t, r = "") {
|
|
27
|
+
if (t == null) {
|
|
28
|
+
if (!r) return "";
|
|
29
|
+
const i = r.split(".").pop() ?? "";
|
|
30
|
+
return !i || E.has(i) ? "" : j(i);
|
|
31
|
+
}
|
|
32
|
+
return typeof t != "object" ? String(t) : m(t) ? t.text ?? "" : "";
|
|
33
|
+
}
|
|
34
|
+
function A(t) {
|
|
35
|
+
return typeof t == "object" && t !== null && !Array.isArray(t) && "src" in t;
|
|
36
|
+
}
|
|
37
|
+
function m(t) {
|
|
38
|
+
return typeof t == "object" && t !== null && !Array.isArray(t) && "url" in t && "text" in t && "external" in t;
|
|
39
|
+
}
|
|
40
|
+
function k(t, r) {
|
|
41
|
+
if (r === void 0) return t;
|
|
42
|
+
if (t === null || typeof t != "object" || Array.isArray(t) || r === null || typeof r != "object" || Array.isArray(r))
|
|
43
|
+
return r;
|
|
44
|
+
const i = { ...t };
|
|
45
|
+
for (const s of Object.keys(r))
|
|
46
|
+
i[s] = k(t[s], r[s]);
|
|
47
|
+
return i;
|
|
48
|
+
}
|
|
49
|
+
function q(t, r) {
|
|
50
|
+
const i = { ...t };
|
|
51
|
+
for (const s of Object.keys(r))
|
|
52
|
+
i[s] = k(t, r[s]);
|
|
53
|
+
return i;
|
|
54
|
+
}
|
|
55
|
+
function p(t, r, i) {
|
|
56
|
+
const s = { __raw: t, __path: r, __slot: i };
|
|
57
|
+
return new Proxy(s, {
|
|
58
|
+
get(n, e) {
|
|
59
|
+
if (e === "data-okno") return n.__path;
|
|
60
|
+
if (e === "slot") return { "data-okno-item": n.__slot ?? n.__path };
|
|
61
|
+
if (e === Symbol.toPrimitive || e === "toString" || e === "valueOf")
|
|
62
|
+
return () => b(n.__raw, n.__path);
|
|
63
|
+
if (e === Symbol.iterator) {
|
|
64
|
+
const f = b(n.__raw, n.__path);
|
|
65
|
+
return function* () {
|
|
66
|
+
yield f;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (typeof e == "symbol") return;
|
|
70
|
+
if (e === "toJSON") return () => n.__raw;
|
|
71
|
+
if (e === "on")
|
|
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
|
+
};
|
|
78
|
+
};
|
|
79
|
+
if (e === "locale")
|
|
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
|
+
n.__path
|
|
85
|
+
) : p(c, n.__path);
|
|
86
|
+
};
|
|
87
|
+
const o = n.__raw, a = n.__path ? `${n.__path}.${String(e)}` : String(e);
|
|
88
|
+
if (m(o) && typeof e == "string") {
|
|
89
|
+
if (e === "href") return o.url ?? "";
|
|
90
|
+
if (e === "target" && o.external) return "_blank";
|
|
91
|
+
if (e === "rel" && o.external) return "noopener noreferrer";
|
|
92
|
+
}
|
|
93
|
+
if (o != null && typeof o != "object") {
|
|
94
|
+
const f = o[e];
|
|
95
|
+
return f !== void 0 ? typeof f == "function" ? (...c) => f.apply(o, c) : f : p(null, a);
|
|
96
|
+
}
|
|
97
|
+
if (o != null && typeof o == "object" && !Array.isArray(o)) {
|
|
98
|
+
const f = o[String(e)];
|
|
99
|
+
return f == null ? p(null, a) : $(f, a);
|
|
100
|
+
}
|
|
101
|
+
return p(null, a);
|
|
102
|
+
},
|
|
103
|
+
// For spread: expose data-okno, plus all keys for file objects (src, alt, width, height, etc.)
|
|
104
|
+
ownKeys(n) {
|
|
105
|
+
const e = n.__raw;
|
|
106
|
+
return A(e) ? [...Object.keys(e), "data-okno"] : m(e) ? e.external ? ["href", "target", "rel", "data-okno"] : ["href", "data-okno"] : ["data-okno"];
|
|
107
|
+
},
|
|
108
|
+
getOwnPropertyDescriptor(n, e) {
|
|
109
|
+
if (e === "data-okno")
|
|
110
|
+
return {
|
|
111
|
+
value: n.__path,
|
|
112
|
+
enumerable: !0,
|
|
113
|
+
configurable: !0
|
|
114
|
+
};
|
|
115
|
+
const o = n.__raw;
|
|
116
|
+
if (A(o) && typeof e == "string" && e in o)
|
|
117
|
+
return {
|
|
118
|
+
value: o[e],
|
|
119
|
+
enumerable: !0,
|
|
120
|
+
configurable: !0
|
|
121
|
+
};
|
|
122
|
+
if (m(o) && (e === "href" || o.external && (e === "target" || e === "rel")))
|
|
123
|
+
return { value: void 0, enumerable: !0, configurable: !0 };
|
|
124
|
+
},
|
|
125
|
+
has(n, e) {
|
|
126
|
+
if (e === "data-okno" || e === Symbol.toPrimitive || e === "toString") return !0;
|
|
127
|
+
const o = n.__raw;
|
|
128
|
+
return typeof o == "object" && o !== null ? e in o : o != null ? e in Object(o) : !1;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function w(t) {
|
|
133
|
+
return t !== null && typeof t == "object" && !Array.isArray(t) && "__oknoRef" in t;
|
|
134
|
+
}
|
|
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
|
+
}
|
|
140
|
+
if (Array.isArray(t)) {
|
|
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
|
+
enumerable: !1
|
|
145
|
+
}), s;
|
|
146
|
+
}
|
|
147
|
+
return p(t, r, i);
|
|
148
|
+
}
|
|
149
|
+
function z(t, r, i) {
|
|
150
|
+
if (!t || typeof t != "object" || Array.isArray(t) || !r) return t;
|
|
151
|
+
const s = { ...t };
|
|
152
|
+
for (const n of Object.keys(r)) {
|
|
153
|
+
const e = r[n];
|
|
154
|
+
if (!e || e.type !== "reference" || typeof e.collection != "string") continue;
|
|
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);
|
|
168
|
+
}
|
|
169
|
+
return s;
|
|
170
|
+
}
|
|
171
|
+
const _ = "data-okno-item", h = "data-okno", O = [h, _];
|
|
172
|
+
function d(t, r, i, s = O) {
|
|
173
|
+
if (r === i) return;
|
|
174
|
+
const n = (e) => {
|
|
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)));
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
n(t);
|
|
181
|
+
for (const e of s) t.querySelectorAll(`[${e}]`).forEach(n);
|
|
182
|
+
}
|
|
183
|
+
function x(t) {
|
|
184
|
+
if (typeof document > "u") return [];
|
|
185
|
+
const r = new RegExp(`^${t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.(\\d+)$`), i = /* @__PURE__ */ new Map();
|
|
186
|
+
document.querySelectorAll(`[${_}]`).forEach((n) => {
|
|
187
|
+
const e = n.getAttribute(_);
|
|
188
|
+
if (!e || !r.test(e) || !n.parentElement || !(n instanceof HTMLElement)) return;
|
|
189
|
+
const o = i.get(n.parentElement) ?? [];
|
|
190
|
+
o.push(n), i.set(n.parentElement, o);
|
|
191
|
+
});
|
|
192
|
+
const s = (n) => Number(n.getAttribute(_).match(r)[1]);
|
|
193
|
+
return [...i.entries()].map(([n, e]) => ({
|
|
194
|
+
parent: n,
|
|
195
|
+
wrappers: e.sort((o, a) => s(o) - s(a))
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
function L(t) {
|
|
199
|
+
t.querySelectorAll(`[${h}]`).forEach((r) => {
|
|
200
|
+
r.children.length === 0 && (r.textContent = "");
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function M(t, r) {
|
|
204
|
+
t.querySelectorAll(`[${h}]`).forEach((i) => {
|
|
205
|
+
const s = i.getAttribute(h);
|
|
206
|
+
s && s in r && i.children.length === 0 && (i.textContent = r[s] ?? "");
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function N() {
|
|
210
|
+
return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
211
|
+
}
|
|
212
|
+
function R(t) {
|
|
213
|
+
const r = document;
|
|
214
|
+
return typeof r.startViewTransition != "function" || N() ? (t(), Promise.resolve()) : r.startViewTransition(t).finished.catch(() => {
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
let C = 0;
|
|
218
|
+
function H(t) {
|
|
219
|
+
if (typeof document > "u" || !t?.list || !t.op) return;
|
|
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);
|
|
224
|
+
};
|
|
225
|
+
for (const u of s) for (const l of u.wrappers) e(l);
|
|
226
|
+
const o = document.documentElement;
|
|
227
|
+
o.classList.add("okno-vt-active");
|
|
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);
|
|
232
|
+
}).finally(() => {
|
|
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);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function I(t, r, i, s) {
|
|
238
|
+
const n = t.wrappers, e = n.length;
|
|
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);
|
|
246
|
+
}
|
|
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}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function V(t, r, i, s) {
|
|
255
|
+
const n = t.wrappers, e = n.length;
|
|
256
|
+
if (e === 0) return;
|
|
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);
|
|
258
|
+
for (let l = e - 1; l >= o; l--) d(n[l], `${r}.${l}`, `${r}.${l + 1}`);
|
|
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);
|
|
262
|
+
}
|
|
263
|
+
let v = !1;
|
|
264
|
+
function B() {
|
|
265
|
+
const t = globalThis;
|
|
266
|
+
v || typeof t.document > "u" || (v = !0, t.document.addEventListener("okno:structure", (r) => H(r.detail)));
|
|
267
|
+
}
|
|
268
|
+
export {
|
|
269
|
+
H as __oknoApplyStructure,
|
|
270
|
+
B as __oknoInitStructure,
|
|
271
|
+
q as __oknoLocalize,
|
|
272
|
+
z as __oknoResolveRefs,
|
|
273
|
+
p as __oknoWrap
|
|
274
|
+
};
|
package/dist/types/fields.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/** Base properties shared by all field types */
|
|
2
2
|
interface FieldBase {
|
|
3
|
+
/** Display label shown above the field in the editor (falls back to a
|
|
4
|
+
* humanized version of the field key). */
|
|
5
|
+
label?: string;
|
|
3
6
|
required?: boolean;
|
|
4
7
|
localized?: boolean;
|
|
5
8
|
hidden?: boolean;
|
|
@@ -9,6 +12,7 @@ interface FieldBase {
|
|
|
9
12
|
export interface StringField extends FieldBase {
|
|
10
13
|
type: "string";
|
|
11
14
|
default?: string;
|
|
15
|
+
placeholder?: string;
|
|
12
16
|
min?: number;
|
|
13
17
|
max?: number;
|
|
14
18
|
pattern?: string;
|
|
@@ -42,14 +46,39 @@ export interface EnumField extends FieldBase {
|
|
|
42
46
|
multiple?: boolean;
|
|
43
47
|
default?: string | string[];
|
|
44
48
|
}
|
|
45
|
-
/** Rich text / HTML content
|
|
49
|
+
/** Rich text / HTML content. `features` restricts what authors can apply
|
|
50
|
+
* (bold, italic, headings, links, lists…); omitted = a curated default set,
|
|
51
|
+
* an empty array = plain paragraphs only. Each value is a Tiptap mark/node
|
|
52
|
+
* key or a heading level (`h1`/`h2`/`h3`). */
|
|
46
53
|
export interface RichtextField extends FieldBase {
|
|
47
54
|
type: "richtext";
|
|
55
|
+
features?: string[];
|
|
48
56
|
}
|
|
49
|
-
/**
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
/** Media kinds a {@link MediaField} can accept. */
|
|
58
|
+
export type MediaKind = "image" | "video" | "audio" | "document";
|
|
59
|
+
/** Media field — image, video, audio, or file. `accept` restricts which kinds
|
|
60
|
+
* are allowed (omitted/empty = any kind). `multiple` turns it into a gallery
|
|
61
|
+
* (an array of media items instead of one). Replaces the old Image/Gallery/File
|
|
62
|
+
* split: a hero image is `{ accept: ["image"] }`, a photo+clip gallery is
|
|
63
|
+
* `{ accept: ["image", "video"], multiple: true }`, downloadable docs are
|
|
64
|
+
* `{ accept: ["document"], multiple: true }`. */
|
|
65
|
+
export interface MediaField extends FieldBase {
|
|
66
|
+
type: "media";
|
|
67
|
+
accept?: MediaKind[];
|
|
68
|
+
multiple?: boolean;
|
|
69
|
+
/** Files folder this field's uploads are saved to (folder id, "" = root). */
|
|
70
|
+
uploadFolder?: string;
|
|
71
|
+
}
|
|
72
|
+
/** Color field — stores a raw CSS color string (any valid CSS color). Edited
|
|
73
|
+
* via a dependency-free HSV picker. Foundation for the Theme global. */
|
|
74
|
+
export interface ColorField extends FieldBase {
|
|
75
|
+
type: "color";
|
|
76
|
+
default?: string;
|
|
77
|
+
}
|
|
78
|
+
/** Link field — stores `{ text, url, external }`. Spreads onto an `<a>`
|
|
79
|
+
* (url→href, +target/rel when external) and renders its text as the child. */
|
|
80
|
+
export interface LinkField extends FieldBase {
|
|
81
|
+
type: "link";
|
|
53
82
|
}
|
|
54
83
|
/** Auto-generated URL slug from another field */
|
|
55
84
|
export interface SlugField extends FieldBase {
|
|
@@ -67,7 +96,26 @@ export interface GroupField {
|
|
|
67
96
|
type: "group";
|
|
68
97
|
fields: Record<string, AnyField>;
|
|
69
98
|
}
|
|
99
|
+
/** One or more embedded instances of a reusable Block (a named field shape from
|
|
100
|
+
* `schema.blocks`). Each placement owns its OWN values — an embed, not a
|
|
101
|
+
* reference. `multiple` makes it a repeatable array of instances. */
|
|
102
|
+
export interface BlockField extends FieldBase {
|
|
103
|
+
type: "block";
|
|
104
|
+
block: string;
|
|
105
|
+
multiple?: boolean;
|
|
106
|
+
}
|
|
107
|
+
/** Editor-only section divider. Organizes the field list into labeled,
|
|
108
|
+
* collapsible sections; it does NOT nest or namespace the stored data (fields
|
|
109
|
+
* after it stay flat). Purely presentational — replaces nesting groups for the
|
|
110
|
+
* common "just break up the list" case. */
|
|
111
|
+
export interface DividerField {
|
|
112
|
+
type: "divider";
|
|
113
|
+
/** Section label shown in the editor. */
|
|
114
|
+
label?: string;
|
|
115
|
+
/** Start the section collapsed. */
|
|
116
|
+
collapsed?: boolean;
|
|
117
|
+
}
|
|
70
118
|
/** Union of all field types */
|
|
71
|
-
export type AnyField = StringField | NumberField | BooleanField | DateField | EnumField | RichtextField |
|
|
119
|
+
export type AnyField = StringField | NumberField | BooleanField | DateField | EnumField | RichtextField | MediaField | ColorField | LinkField | SlugField | ReferenceField | GroupField | BlockField | DividerField;
|
|
72
120
|
export {};
|
|
73
121
|
//# sourceMappingURL=fields.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/types/fields.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,UAAU,SAAS;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED,uBAAuB;AACvB,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC7C,IAAI,EAAE,QAAQ,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,oBAAoB;AACpB,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC7C,IAAI,EAAE,QAAQ,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,qBAAqB;AACrB,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC9C,IAAI,EAAE,SAAS,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,0BAA0B;AAC1B,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;CACxB;AAED,8BAA8B;AAC9B,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAC3B;AAED
|
|
1
|
+
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/types/fields.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export type { StringField, NumberField, BooleanField, DateField, EnumField, RichtextField,
|
|
2
|
-
export type { Fields, PageDef, CollectionDef, GlobalDef, OknoSchema, OknoConfig, } from "./schema.ts";
|
|
1
|
+
export type { StringField, NumberField, BooleanField, DateField, EnumField, RichtextField, MediaField, MediaKind, SlugField, ReferenceField, GroupField, BlockField, DividerField, AnyField, } from "./fields.ts";
|
|
2
|
+
export type { Fields, PageDef, CollectionDef, GlobalDef, BlockDef, OknoSchema, Schema, OknoConfig, } from "./schema.ts";
|
|
3
|
+
export type { ResourcePermissions, RolePermissions, PermissionsConfig } from "./permissions.ts";
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACT,aAAa,EACb,SAAS,EACT,SAAS,EACT,cAAc,EACd,UAAU,EACV,QAAQ,GACR,MAAM,aAAa,CAAA;AAEpB,YAAY,EACX,MAAM,EACN,OAAO,EACP,aAAa,EACb,SAAS,EACT,UAAU,EACV,UAAU,GACV,MAAM,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,SAAS,EACT,SAAS,EACT,cAAc,EACd,UAAU,EACV,UAAU,EACV,YAAY,EACZ,QAAQ,GACR,MAAM,aAAa,CAAA;AAEpB,YAAY,EACX,MAAM,EACN,OAAO,EACP,aAAa,EACb,SAAS,EACT,QAAQ,EACR,UAAU,EACV,MAAM,EACN,UAAU,GACV,MAAM,aAAa,CAAA;AAEpB,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** The actions a role may perform on a resource. Shape of every entry in
|
|
2
|
+
* `okno/permissions.ts`. */
|
|
3
|
+
export interface ResourcePermissions {
|
|
4
|
+
read: boolean;
|
|
5
|
+
write: boolean;
|
|
6
|
+
delete: boolean;
|
|
7
|
+
publish: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Per-resource permissions for a single role. */
|
|
10
|
+
export interface RolePermissions {
|
|
11
|
+
pages: ResourcePermissions;
|
|
12
|
+
collections: ResourcePermissions;
|
|
13
|
+
globals: ResourcePermissions;
|
|
14
|
+
users: ResourcePermissions;
|
|
15
|
+
permissions: ResourcePermissions;
|
|
16
|
+
}
|
|
17
|
+
/** The full permissions config users define in `okno/permissions.ts`
|
|
18
|
+
* (`export default { roles: { ... } } satisfies PermissionsConfig`). */
|
|
19
|
+
export interface PermissionsConfig {
|
|
20
|
+
roles: Record<string, RolePermissions>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/types/permissions.ts"],"names":[],"mappings":"AAAA;6BAC6B;AAC7B,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;CAChB;AAED,kDAAkD;AAClD,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,mBAAmB,CAAA;IAC1B,WAAW,EAAE,mBAAmB,CAAA;IAChC,OAAO,EAAE,mBAAmB,CAAA;IAC5B,KAAK,EAAE,mBAAmB,CAAA;IAC1B,WAAW,EAAE,mBAAmB,CAAA;CAChC;AAED;yEACyE;AACzE,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACtC"}
|
package/dist/types/schema.d.ts
CHANGED
|
@@ -1,33 +1,63 @@
|
|
|
1
|
-
import type { AnyField } from "./fields.ts";
|
|
1
|
+
import type { AnyField, SlugField } from "./fields.ts";
|
|
2
2
|
/** Fields definition - a record of field name to field config */
|
|
3
3
|
export type Fields = Record<string, AnyField>;
|
|
4
4
|
/** Page definition - a singleton content type */
|
|
5
5
|
export interface PageDef {
|
|
6
6
|
/** Display name shown in editor (sidebar, page title). Falls back to slug. */
|
|
7
7
|
name?: string;
|
|
8
|
+
/** Relative URL this page lives at on the live site (e.g. "/about"). Lets the
|
|
9
|
+
* editor deep-link to this page on open and offer a "Visit page" jump. */
|
|
10
|
+
url?: string;
|
|
8
11
|
fields: Fields;
|
|
9
12
|
}
|
|
10
13
|
/** Collection definition - multiple items with required slug */
|
|
11
14
|
export interface CollectionDef {
|
|
12
15
|
name?: string;
|
|
16
|
+
/** Manual item order, as a list of item slugs. okno owns no other ordering —
|
|
17
|
+
* any date/field sort is the dev's own `.sort()` before `.map()`. Items not
|
|
18
|
+
* listed here (e.g. added outside the editor) sort after, in file order. New
|
|
19
|
+
* items prepend, so the default reads newest-first. Maintained by the editor
|
|
20
|
+
* (drag-to-reorder, create, delete); drives `okno:collections` iteration. */
|
|
21
|
+
order?: string[];
|
|
22
|
+
/** Opt-in draft workflow. When true, items carry a `status` ("draft" | "live")
|
|
23
|
+
* the editor toggles, and items with `status: "draft"` are EXCLUDED from
|
|
24
|
+
* `okno:collections` at build (so references to them resolve to nothing too).
|
|
25
|
+
* Off → the collection has no status concept at all. Orthogonal to git publish:
|
|
26
|
+
* a draft item still lives in the repo, it just isn't served. */
|
|
27
|
+
drafts?: boolean;
|
|
28
|
+
/** Route pattern for this collection's items, with field-key tokens — e.g.
|
|
29
|
+
* `/blog/[category]/[slug]`. Drives the editor's "Visit page" link + deep-link
|
|
30
|
+
* routing (read in `app/editor/lib/urls.ts`). */
|
|
31
|
+
url?: string;
|
|
13
32
|
fields: Fields & {
|
|
14
|
-
slug:
|
|
15
|
-
type: "slug";
|
|
16
|
-
from: string;
|
|
17
|
-
};
|
|
33
|
+
slug: SlugField;
|
|
18
34
|
};
|
|
19
35
|
}
|
|
20
|
-
/** Global definition -
|
|
36
|
+
/** Global definition - a singleton content type. One shared entry with its own
|
|
37
|
+
* values at `globals/<slug>.ts`, read everywhere (Navigation, SEO defaults,
|
|
38
|
+
* Site Settings). Edited once, reflected across the whole site. */
|
|
21
39
|
export interface GlobalDef {
|
|
22
40
|
name?: string;
|
|
23
41
|
fields: Fields;
|
|
24
42
|
}
|
|
43
|
+
/** Block definition - a reusable field shape embedded into pages/collections
|
|
44
|
+
* via a Block field (`{ type: "block", block: "<key>" }`). Has NO standalone
|
|
45
|
+
* entry or content file; each placement owns its own values (an embed, not a
|
|
46
|
+
* reference). Use for repeating structures like cards or FAQ items. */
|
|
47
|
+
export interface BlockDef {
|
|
48
|
+
name?: string;
|
|
49
|
+
fields: Fields;
|
|
50
|
+
}
|
|
25
51
|
/** The full schema that users define in okno/schema.ts */
|
|
26
52
|
export interface OknoSchema {
|
|
27
53
|
pages?: Record<string, PageDef>;
|
|
28
54
|
collections?: Record<string, CollectionDef>;
|
|
29
55
|
globals?: Record<string, GlobalDef>;
|
|
56
|
+
blocks?: Record<string, BlockDef>;
|
|
30
57
|
}
|
|
58
|
+
/** Alias for {@link OknoSchema} — the name used in scaffolded `okno/schema.ts`
|
|
59
|
+
* files (`export default { ... } satisfies Schema`). */
|
|
60
|
+
export type Schema = OknoSchema;
|
|
31
61
|
/** Plugin configuration */
|
|
32
62
|
export interface OknoConfig {
|
|
33
63
|
/** Path to the okno content directory (default: "okno") */
|
|
@@ -36,6 +66,11 @@ export interface OknoConfig {
|
|
|
36
66
|
apiUrl?: string;
|
|
37
67
|
/** Whether this is the editor build (disables HMR on content changes) */
|
|
38
68
|
isEditor?: boolean;
|
|
69
|
+
/** Public demo mode: the editor boots login-less, reads content from a
|
|
70
|
+
* static `okno-demo.json` snapshot, and no-ops every write (nothing is
|
|
71
|
+
* persisted; a reload resets). For showcasing okno on a marketing site —
|
|
72
|
+
* see `docs/demo-mode.md`. A demo build never reaches the backend. */
|
|
73
|
+
demo?: boolean;
|
|
39
74
|
/** Localization configuration */
|
|
40
75
|
locales?: {
|
|
41
76
|
/** Default/base locale code (e.g. "en") */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEtD,iEAAiE;AACjE,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;AAE7C,iDAAiD;AACjD,MAAM,WAAW,OAAO;IACvB,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;+EAC2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACd;AAED,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;kFAI8E;IAC9E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB;;;;sEAIkE;IAClE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;sDAEkD;IAClD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,GAAG;QAChB,IAAI,EAAE,SAAS,CAAA;KACf,CAAA;CACD;AAED;;oEAEoE;AACpE,MAAM,WAAW,SAAS;IACzB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACd;AAED;;;wEAGwE;AACxE,MAAM,WAAW,QAAQ;IACxB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACd;AAED,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;CACjC;AAED;yDACyD;AACzD,MAAM,MAAM,MAAM,GAAG,UAAU,CAAA;AAE/B,2BAA2B;AAC3B,MAAM,WAAW,UAAU;IAC1B,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;2EAGuE;IACvE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,iCAAiC;IACjC,OAAO,CAAC,EAAE;QACT,2CAA2C;QAC3C,OAAO,EAAE,MAAM,CAAA;QACf,uDAAuD;QACvD,SAAS,EAAE,MAAM,EAAE,CAAA;KACnB,CAAA;CACD"}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import type { ViteDevServer } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a request path to a file strictly inside {oknoDir}/files, or null if
|
|
4
|
+
* it escapes (path traversal). Node's HTTP server does not normalize `..`, so
|
|
5
|
+
* `join(oknoDir, "files", rawPath)` alone would happily serve `../../secret`.
|
|
6
|
+
* We decode, then verify the canonical resolved path stays under the files
|
|
7
|
+
* root — a substring `..` check is not enough once decoding is in play.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveOknoFile(oknoDir: string, rawPath: string): string | null;
|
|
2
10
|
/**
|
|
3
11
|
* Dev server middleware: single endpoint for syncing local files with remote.
|
|
4
12
|
* All content CRUD goes through the backend. This just pulls changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../src/vite/dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../src/vite/dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAMzC;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc/E;AAcD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,QAoJrE"}
|
package/dist/vite/index.js
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local engine — dev-only content I/O straight to the working tree.
|
|
3
|
+
*
|
|
4
|
+
* In dev the editor talks to these `/__okno/api/*` routes instead of the hosted
|
|
5
|
+
* backend (`api.okno.build`). They mirror the backend's content/schema/publish
|
|
6
|
+
* request+response shapes 1:1 so the editor only swaps the base URL (see
|
|
7
|
+
* `Project.contentApiBase`). No GitHub, no network, no billing — content lives
|
|
8
|
+
* in the working tree on whatever branch is checked out, and "publish" is a
|
|
9
|
+
* local `git commit && push` of that branch.
|
|
10
|
+
*
|
|
11
|
+
* NOT a security boundary — localhost dev only.
|
|
12
|
+
*/
|
|
13
|
+
import type { ViteDevServer } from "vite";
|
|
14
|
+
export declare function markSelfWritten(abs: string): void;
|
|
15
|
+
/** True if `abs` was engine-written in the last few seconds. TTL-based (not
|
|
16
|
+
* delete-on-read) so a duplicate watcher event for the same write is still
|
|
17
|
+
* recognized; a genuine later edit (ts now stale) falls through to HMR. */
|
|
18
|
+
export declare function consumeSelfWritten(abs: string): boolean;
|
|
19
|
+
/** The full content snapshot the editor's load() consumes: raw `schema.ts`
|
|
20
|
+
* text, raw `users.json` text, and every content `.ts` keyed by relative path.
|
|
21
|
+
* Shared by the dev GET /content handler and the demo-mode build emit so both
|
|
22
|
+
* produce a byte-identical shape (see `docs/demo-mode.md`). */
|
|
23
|
+
export declare function snapshotContent(oknoDir: string): {
|
|
24
|
+
schema: string | null;
|
|
25
|
+
users: string | null;
|
|
26
|
+
content: Record<string, string>;
|
|
27
|
+
files: Array<{
|
|
28
|
+
path: string;
|
|
29
|
+
filename: string;
|
|
30
|
+
size: number;
|
|
31
|
+
}>;
|
|
32
|
+
};
|
|
33
|
+
export declare function registerLocalEngine(server: ViteDevServer, oknoDir: string): void;
|
|
34
|
+
//# sourceMappingURL=local-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-engine.d.ts","sourceRoot":"","sources":["../../src/vite/local-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAiBzC,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEjD;AACD;;4EAE4E;AAC5E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGvD;AAgCD;;;gEAGgE;AAChE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG;IACjD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC9D,CAYA;AAmQD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CA+XhF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/vite/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/vite/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAsEpD,wBAAgB,IAAI,CAAC,MAAM,GAAE,UAAe,GAAG,MAAM,CAyUpD"}
|