@bettercms-ai/kit 2.0.0-next.0 → 2.0.0-next.2
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/adapters/lossy.d.ts +9 -1
- package/dist/adapters/lossy.js +16 -5
- package/dist/adapters/lossy.js.map +1 -1
- package/dist/adapters/prod-types.d.ts +9 -22
- package/dist/adapters/prod-types.js +36 -35
- package/dist/adapters/prod-types.js.map +1 -1
- package/dist/adapters/schema.js +84 -39
- package/dist/adapters/schema.js.map +1 -1
- package/dist/context.d.ts +39 -0
- package/dist/context.js +40 -1
- package/dist/context.js.map +1 -1
- package/dist/controls/link.js +112 -196
- package/dist/controls/link.js.map +1 -1
- package/dist/controls/location.js +3 -8
- package/dist/controls/location.js.map +1 -1
- package/dist/controls/media.d.ts +0 -14
- package/dist/controls/media.js +52 -95
- package/dist/controls/media.js.map +1 -1
- package/dist/controls/rich-text/article-shell.d.ts +145 -0
- package/dist/controls/rich-text/article-shell.js +510 -0
- package/dist/controls/rich-text/article-shell.js.map +1 -0
- package/dist/controls/rich-text/author.d.ts +25 -0
- package/dist/controls/rich-text/author.js +104 -0
- package/dist/controls/rich-text/author.js.map +1 -0
- package/dist/controls/rich-text/blocks.d.ts +19 -2
- package/dist/controls/rich-text/blocks.js +273 -638
- package/dist/controls/rich-text/blocks.js.map +1 -1
- package/dist/controls/rich-text/button.d.ts +23 -0
- package/dist/controls/rich-text/button.js +85 -0
- package/dist/controls/rich-text/button.js.map +1 -0
- package/dist/controls/rich-text/catalog.d.ts +2 -5
- package/dist/controls/rich-text/catalog.js +120 -6
- package/dist/controls/rich-text/catalog.js.map +1 -1
- package/dist/controls/rich-text/checklist.d.ts +24 -0
- package/dist/controls/rich-text/checklist.js +115 -0
- package/dist/controls/rich-text/checklist.js.map +1 -0
- package/dist/controls/rich-text/codec.d.ts +10 -1
- package/dist/controls/rich-text/codec.js +11 -1
- package/dist/controls/rich-text/codec.js.map +1 -1
- package/dist/controls/rich-text/columns.d.ts +41 -0
- package/dist/controls/rich-text/columns.js +181 -0
- package/dist/controls/rich-text/columns.js.map +1 -0
- package/dist/controls/rich-text/control.js +1 -0
- package/dist/controls/rich-text/control.js.map +1 -1
- package/dist/controls/rich-text/dom.d.ts +84 -4
- package/dist/controls/rich-text/dom.js +171 -10
- package/dist/controls/rich-text/dom.js.map +1 -1
- package/dist/controls/rich-text/editor.d.ts +4 -2
- package/dist/controls/rich-text/editor.js +184 -12
- package/dist/controls/rich-text/editor.js.map +1 -1
- package/dist/controls/rich-text/embed.d.ts +28 -0
- package/dist/controls/rich-text/embed.js +210 -0
- package/dist/controls/rich-text/embed.js.map +1 -0
- package/dist/controls/rich-text/footnote.d.ts +41 -0
- package/dist/controls/rich-text/footnote.js +185 -0
- package/dist/controls/rich-text/footnote.js.map +1 -0
- package/dist/controls/rich-text/gallery.d.ts +28 -0
- package/dist/controls/rich-text/gallery.js +167 -0
- package/dist/controls/rich-text/gallery.js.map +1 -0
- package/dist/controls/rich-text/link-form.d.ts +3 -1
- package/dist/controls/rich-text/link-form.js +2 -2
- package/dist/controls/rich-text/link-form.js.map +1 -1
- package/dist/controls/rich-text/ops.js +6 -0
- package/dist/controls/rich-text/ops.js.map +1 -1
- package/dist/controls/rich-text/related.d.ts +36 -0
- package/dist/controls/rich-text/related.js +213 -0
- package/dist/controls/rich-text/related.js.map +1 -0
- package/dist/controls/rich-text/toc.d.ts +47 -0
- package/dist/controls/rich-text/toc.js +160 -0
- package/dist/controls/rich-text/toc.js.map +1 -0
- package/dist/core/core.d.ts +11 -3
- package/dist/core/core.js +24 -6
- package/dist/core/core.js.map +1 -1
- package/dist/core/facets.d.ts +16 -0
- package/dist/core/facets.js +17 -1
- package/dist/core/facets.js.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/index.js +4 -4
- package/dist/library/kit-catalog.json +47 -44
- package/dist/schema/types.d.ts +15 -0
- package/dist/schema/types.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/ui/autocomplete.d.ts +29 -1
- package/dist/ui/autocomplete.js +102 -47
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/button.js +3 -5
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/toast.js +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { slugify } from "@bettercms-ai/types";
|
|
2
|
+
import type { TypeSchema } from "../../schema/types";
|
|
3
|
+
import type { IslandCtx } from "./blocks";
|
|
4
|
+
import { type IslandEl } from "./dom";
|
|
5
|
+
export interface TocModel {
|
|
6
|
+
title: string;
|
|
7
|
+
depth: "2" | "3";
|
|
8
|
+
}
|
|
9
|
+
export declare const TOC_LABEL = "Table of contents";
|
|
10
|
+
export declare const tocDefault: () => TocModel;
|
|
11
|
+
/** The popover form (V2 ARTICLE_SCHEMAS.toc). Two settings → the shell's popover (D54). */
|
|
12
|
+
export declare const TOC_SCHEMA: TypeSchema;
|
|
13
|
+
export interface OutlineItem {
|
|
14
|
+
id: string;
|
|
15
|
+
text: string;
|
|
16
|
+
depth: 2 | 3;
|
|
17
|
+
}
|
|
18
|
+
/** V2 article.ts:250-251, the one heading-id rule the site stamps too (types heading-id.ts, plan RT5). */
|
|
19
|
+
export { slugify };
|
|
20
|
+
/** The body's H2 and H3, top level only, in order, with stable de-duplicated ids. */
|
|
21
|
+
export declare function outlineOf(root: ParentNode): OutlineItem[];
|
|
22
|
+
export declare const tocVisible: (outline: OutlineItem[], depth: TocModel["depth"]) => OutlineItem[];
|
|
23
|
+
/** One live outline per editor: the editor sets it after each input, every TOC preview subscribes. */
|
|
24
|
+
export interface OutlineStore {
|
|
25
|
+
get: () => OutlineItem[];
|
|
26
|
+
subscribe: (fn: () => void) => () => void;
|
|
27
|
+
set: (next: OutlineItem[]) => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function createOutlineStore(): OutlineStore;
|
|
30
|
+
export declare const NO_OUTLINE: OutlineStore;
|
|
31
|
+
/** `host` is the TOC's island element; its parent is the editor surface whose headings it lists. */
|
|
32
|
+
export declare function TocPreview({ m, outline, host }: {
|
|
33
|
+
m: TocModel;
|
|
34
|
+
outline: OutlineStore;
|
|
35
|
+
host: HTMLElement;
|
|
36
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
37
|
+
export interface TocBlockProps {
|
|
38
|
+
m: TocModel;
|
|
39
|
+
set: (fn: (m: TocModel) => TocModel, label?: string) => void;
|
|
40
|
+
el: IslandEl;
|
|
41
|
+
/** the editor's live outline rides the island context */
|
|
42
|
+
ctx: IslandCtx & {
|
|
43
|
+
outline?: OutlineStore;
|
|
44
|
+
};
|
|
45
|
+
autoFocus: boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare function TocBlock({ m, set, el, ctx, autoFocus }: TocBlockProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn.js";
|
|
2
|
+
import { ArticlePopoverBlock } from "./article-shell.js";
|
|
3
|
+
import { placeCaret } from "./dom.js";
|
|
4
|
+
import { slugify } from "@bettercms-ai/types";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/controls/rich-text/toc.tsx
|
|
8
|
+
/**
|
|
9
|
+
* RICH TEXT · Table of contents (kit-richtext-ui-spec.md §5): V2's article block, stored as the PT block object
|
|
10
|
+
* `{ _type: "tableOfContents", title?, depth: "2" | "3" }`. The list is derived from the same body's top-level H2/H3,
|
|
11
|
+
* never stored.
|
|
12
|
+
*
|
|
13
|
+
* form V2 article.ts:137-156: Title (max 40, default "In this article"), Headings H2 | H2 and H3 (segmented)
|
|
14
|
+
* outline V2 article.ts:248-266: the body's top-level non-empty H2/H3 in order, ids slugified and de-duplicated
|
|
15
|
+
* (x, x-2, …), the same ids the site stamps on its headings
|
|
16
|
+
* preview V2 article-blocks.tsx:537-568: the nav as the reader sees it; each entry a button that scrolls the
|
|
17
|
+
* heading to the centre and puts the caret in it; "No headings yet." when there are none
|
|
18
|
+
* store V2 article-blocks.tsx:45-66: one live outline per editor, so every TOC follows the headings as they are typed
|
|
19
|
+
*
|
|
20
|
+
* The block itself (card, chip, popover at its corner) is the shared article shell (article-shell.tsx, kit-40); it
|
|
21
|
+
* opens on a fresh insert by focusing the card only (V2 article-blocks.tsx:131).
|
|
22
|
+
*/
|
|
23
|
+
var TOC_LABEL = "Table of contents";
|
|
24
|
+
var tocDefault = () => ({
|
|
25
|
+
title: "In this article",
|
|
26
|
+
depth: "3"
|
|
27
|
+
});
|
|
28
|
+
/** The popover form (V2 ARTICLE_SCHEMAS.toc). Two settings → the shell's popover (D54). */
|
|
29
|
+
var TOC_SCHEMA = {
|
|
30
|
+
name: "tableOfContents",
|
|
31
|
+
title: TOC_LABEL,
|
|
32
|
+
kind: "object",
|
|
33
|
+
icon: "list-tree",
|
|
34
|
+
fields: [{
|
|
35
|
+
name: "title",
|
|
36
|
+
title: "Title",
|
|
37
|
+
type: "string",
|
|
38
|
+
validation: { max: 40 }
|
|
39
|
+
}, {
|
|
40
|
+
name: "depth",
|
|
41
|
+
title: "Headings",
|
|
42
|
+
type: "select",
|
|
43
|
+
layout: "segmented",
|
|
44
|
+
initialValue: "3",
|
|
45
|
+
options: [{
|
|
46
|
+
value: "2",
|
|
47
|
+
label: "H2"
|
|
48
|
+
}, {
|
|
49
|
+
value: "3",
|
|
50
|
+
label: "H2 and H3"
|
|
51
|
+
}]
|
|
52
|
+
}]
|
|
53
|
+
};
|
|
54
|
+
/** The body's H2 and H3, top level only, in order, with stable de-duplicated ids. */
|
|
55
|
+
function outlineOf(root) {
|
|
56
|
+
const used = /* @__PURE__ */ new Set();
|
|
57
|
+
const out = [];
|
|
58
|
+
root.querySelectorAll(":scope > h2, :scope > h3").forEach((h) => {
|
|
59
|
+
const text = (h.textContent ?? "").replace(//g, "").trim();
|
|
60
|
+
if (!text) return;
|
|
61
|
+
let id = slugify(text);
|
|
62
|
+
for (let n = 2; used.has(id); n++) id = `${slugify(text)}-${n}`;
|
|
63
|
+
used.add(id);
|
|
64
|
+
out.push({
|
|
65
|
+
id,
|
|
66
|
+
text,
|
|
67
|
+
depth: h.tagName === "H2" ? 2 : 3
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
var tocVisible = (outline, depth) => outline.filter((o) => o.depth === 2 || depth === "3");
|
|
73
|
+
function createOutlineStore() {
|
|
74
|
+
let cur = [];
|
|
75
|
+
const subs = /* @__PURE__ */ new Set();
|
|
76
|
+
return {
|
|
77
|
+
get: () => cur,
|
|
78
|
+
subscribe: (fn) => (subs.add(fn), () => void subs.delete(fn)),
|
|
79
|
+
set: (next) => {
|
|
80
|
+
if (JSON.stringify(next) === JSON.stringify(cur)) return;
|
|
81
|
+
cur = next;
|
|
82
|
+
subs.forEach((f) => f());
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
var NO_OUTLINE = {
|
|
87
|
+
get: () => [],
|
|
88
|
+
subscribe: () => () => {},
|
|
89
|
+
set: () => {}
|
|
90
|
+
};
|
|
91
|
+
/** `host` is the TOC's island element; its parent is the editor surface whose headings it lists. */
|
|
92
|
+
function TocPreview({ m, outline, host }) {
|
|
93
|
+
const all = React.useSyncExternalStore(outline.subscribe, outline.get, outline.get);
|
|
94
|
+
const items = tocVisible(all, m.depth);
|
|
95
|
+
const go = (it) => {
|
|
96
|
+
const root = host.parentElement;
|
|
97
|
+
if (!root) return;
|
|
98
|
+
const h = Array.from(root.querySelectorAll(":scope > h2, :scope > h3")).filter((h) => (h.textContent ?? "").replace(//g, "").trim())[all.indexOf(it)];
|
|
99
|
+
if (!h) return;
|
|
100
|
+
h.scrollIntoView?.({
|
|
101
|
+
block: "center",
|
|
102
|
+
behavior: "smooth"
|
|
103
|
+
});
|
|
104
|
+
root.focus({ preventScroll: true });
|
|
105
|
+
placeCaret(h);
|
|
106
|
+
};
|
|
107
|
+
return /* @__PURE__ */ jsxs("nav", {
|
|
108
|
+
"aria-label": m.title || "Table of contents",
|
|
109
|
+
className: "rounded-kit-lg border border-kit-line bg-kit-surface px-4 py-3",
|
|
110
|
+
children: [m.title ? /* @__PURE__ */ jsx("p", {
|
|
111
|
+
"data-field": "title",
|
|
112
|
+
className: "mb-1.5 text-kit-sm font-semibold text-kit-fg",
|
|
113
|
+
children: m.title
|
|
114
|
+
}) : null, items.length ? /* @__PURE__ */ jsx("ol", {
|
|
115
|
+
className: "m-0 flex list-none flex-col gap-0.5 p-0 text-kit-sm",
|
|
116
|
+
children: items.map((it, i) => /* @__PURE__ */ jsx("li", {
|
|
117
|
+
className: cn(it.depth === 3 && "pl-4"),
|
|
118
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
119
|
+
type: "button",
|
|
120
|
+
onClick: (e) => (e.stopPropagation(), go(it)),
|
|
121
|
+
className: "max-w-full truncate rounded-kit-sm text-left text-kit-fg-2 hover:text-kit-fg hover:underline",
|
|
122
|
+
children: it.text
|
|
123
|
+
})
|
|
124
|
+
}, `${it.id}-${i}`))
|
|
125
|
+
}) : /* @__PURE__ */ jsx("p", {
|
|
126
|
+
className: "text-kit-sm text-kit-fg-3",
|
|
127
|
+
children: "No headings yet."
|
|
128
|
+
})]
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function TocBlock({ m, set, el, ctx, autoFocus }) {
|
|
132
|
+
return /* @__PURE__ */ jsx(ArticlePopoverBlock, {
|
|
133
|
+
label: TOC_LABEL,
|
|
134
|
+
kind: "toc",
|
|
135
|
+
schema: TOC_SCHEMA,
|
|
136
|
+
m,
|
|
137
|
+
set,
|
|
138
|
+
el,
|
|
139
|
+
ctx,
|
|
140
|
+
autoFocus,
|
|
141
|
+
openOnInsert: false,
|
|
142
|
+
toForm: (x) => ({
|
|
143
|
+
title: x.title,
|
|
144
|
+
depth: x.depth
|
|
145
|
+
}),
|
|
146
|
+
fromForm: (v) => ({
|
|
147
|
+
title: String(v.title ?? ""),
|
|
148
|
+
depth: v.depth === "2" ? "2" : "3"
|
|
149
|
+
}),
|
|
150
|
+
children: () => /* @__PURE__ */ jsx(TocPreview, {
|
|
151
|
+
m,
|
|
152
|
+
outline: ctx.outline ?? NO_OUTLINE,
|
|
153
|
+
host: el
|
|
154
|
+
})
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
158
|
+
export { NO_OUTLINE, TOC_LABEL, TOC_SCHEMA, TocBlock, TocPreview, createOutlineStore, outlineOf, slugify, tocDefault, tocVisible };
|
|
159
|
+
|
|
160
|
+
//# sourceMappingURL=toc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toc.js","names":[],"sources":["../../../src/controls/rich-text/toc.tsx"],"sourcesContent":["/**\n * RICH TEXT · Table of contents (kit-richtext-ui-spec.md §5): V2's article block, stored as the PT block object\n * `{ _type: \"tableOfContents\", title?, depth: \"2\" | \"3\" }`. The list is derived from the same body's top-level H2/H3,\n * never stored.\n *\n * form V2 article.ts:137-156: Title (max 40, default \"In this article\"), Headings H2 | H2 and H3 (segmented)\n * outline V2 article.ts:248-266: the body's top-level non-empty H2/H3 in order, ids slugified and de-duplicated\n * (x, x-2, …), the same ids the site stamps on its headings\n * preview V2 article-blocks.tsx:537-568: the nav as the reader sees it; each entry a button that scrolls the\n * heading to the centre and puts the caret in it; \"No headings yet.\" when there are none\n * store V2 article-blocks.tsx:45-66: one live outline per editor, so every TOC follows the headings as they are typed\n *\n * The block itself (card, chip, popover at its corner) is the shared article shell (article-shell.tsx, kit-40); it\n * opens on a fresh insert by focusing the card only (V2 article-blocks.tsx:131).\n */\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { slugify } from \"@bettercms-ai/types\";\nimport type { TypeSchema } from \"../../schema/types\";\nimport { ArticlePopoverBlock } from \"./article-shell\";\nimport type { IslandCtx } from \"./blocks\";\nimport { placeCaret, type IslandEl } from \"./dom\";\n\nexport interface TocModel {\n title: string;\n depth: \"2\" | \"3\";\n}\nexport const TOC_LABEL = \"Table of contents\";\nexport const tocDefault = (): TocModel => ({ title: \"In this article\", depth: \"3\" });\n\n/** The popover form (V2 ARTICLE_SCHEMAS.toc). Two settings → the shell's popover (D54). */\nexport const TOC_SCHEMA: TypeSchema = {\n name: \"tableOfContents\",\n title: TOC_LABEL,\n kind: \"object\",\n icon: \"list-tree\",\n fields: [\n { name: \"title\", title: \"Title\", type: \"string\", validation: { max: 40 } },\n {\n name: \"depth\",\n title: \"Headings\",\n type: \"select\",\n layout: \"segmented\",\n initialValue: \"3\",\n options: [\n { value: \"2\", label: \"H2\" },\n { value: \"3\", label: \"H2 and H3\" },\n ],\n },\n ],\n};\n\n/* ── Outline ───────────────────────────────────────────────────────── */\nexport interface OutlineItem {\n id: string;\n text: string;\n depth: 2 | 3;\n}\n/** V2 article.ts:250-251, the one heading-id rule the site stamps too (types heading-id.ts, plan RT5). */\nexport { slugify };\n\n/** The body's H2 and H3, top level only, in order, with stable de-duplicated ids. */\nexport function outlineOf(root: ParentNode): OutlineItem[] {\n const used = new Set<string>();\n const out: OutlineItem[] = [];\n root.querySelectorAll(\":scope > h2, :scope > h3\").forEach((h) => {\n const text = (h.textContent ?? \"\").replace(//g, \"\").trim();\n if (!text) return;\n let id = slugify(text);\n for (let n = 2; used.has(id); n++) id = `${slugify(text)}-${n}`;\n used.add(id);\n out.push({ id, text, depth: h.tagName === \"H2\" ? 2 : 3 });\n });\n return out;\n}\nexport const tocVisible = (outline: OutlineItem[], depth: TocModel[\"depth\"]) => outline.filter((o) => o.depth === 2 || depth === \"3\");\n\n/** One live outline per editor: the editor sets it after each input, every TOC preview subscribes. */\nexport interface OutlineStore {\n get: () => OutlineItem[];\n subscribe: (fn: () => void) => () => void;\n set: (next: OutlineItem[]) => void;\n}\nexport function createOutlineStore(): OutlineStore {\n let cur: OutlineItem[] = [];\n const subs = new Set<() => void>();\n return {\n get: () => cur,\n subscribe: (fn) => (subs.add(fn), () => void subs.delete(fn)),\n set: (next) => {\n if (JSON.stringify(next) === JSON.stringify(cur)) return;\n cur = next;\n subs.forEach((f) => f());\n },\n };\n}\nexport const NO_OUTLINE: OutlineStore = { get: () => [], subscribe: () => () => {}, set: () => {} };\n\n/* ── Preview (what the reader sees) ────────────────────────────────── */\n/** `host` is the TOC's island element; its parent is the editor surface whose headings it lists. */\nexport function TocPreview({ m, outline, host }: { m: TocModel; outline: OutlineStore; host: HTMLElement }) {\n const all = React.useSyncExternalStore(outline.subscribe, outline.get, outline.get);\n const items = tocVisible(all, m.depth);\n const go = (it: OutlineItem) => {\n const root = host.parentElement;\n if (!root) return;\n const hs = Array.from(root.querySelectorAll<HTMLElement>(\":scope > h2, :scope > h3\")).filter((h) => (h.textContent ?? \"\").replace(//g, \"\").trim());\n const h = hs[all.indexOf(it)];\n if (!h) return;\n h.scrollIntoView?.({ block: \"center\", behavior: \"smooth\" });\n root.focus({ preventScroll: true });\n placeCaret(h);\n };\n return (\n <nav aria-label={m.title || TOC_LABEL} className=\"rounded-kit-lg border border-kit-line bg-kit-surface px-4 py-3\">\n {m.title ? (\n <p data-field=\"title\" className=\"mb-1.5 text-kit-sm font-semibold text-kit-fg\">\n {m.title}\n </p>\n ) : null}\n {items.length ? (\n <ol className=\"m-0 flex list-none flex-col gap-0.5 p-0 text-kit-sm\">\n {items.map((it, i) => (\n <li key={`${it.id}-${i}`} className={cn(it.depth === 3 && \"pl-4\")}>\n <button type=\"button\" onClick={(e) => (e.stopPropagation(), go(it))} className=\"max-w-full truncate rounded-kit-sm text-left text-kit-fg-2 hover:text-kit-fg hover:underline\">\n {it.text}\n </button>\n </li>\n ))}\n </ol>\n ) : (\n <p className=\"text-kit-sm text-kit-fg-3\">No headings yet.</p>\n )}\n </nav>\n );\n}\n\n/* ── The block (V2 ArticleBlock, surface \"popover\") ────────────────── */\nexport interface TocBlockProps {\n m: TocModel;\n set: (fn: (m: TocModel) => TocModel, label?: string) => void;\n el: IslandEl;\n /** the editor's live outline rides the island context */\n ctx: IslandCtx & { outline?: OutlineStore };\n autoFocus: boolean;\n}\n\nexport function TocBlock({ m, set, el, ctx, autoFocus }: TocBlockProps) {\n return (\n <ArticlePopoverBlock<TocModel>\n label={TOC_LABEL}\n kind=\"toc\"\n schema={TOC_SCHEMA}\n m={m}\n set={set}\n el={el}\n ctx={ctx}\n autoFocus={autoFocus}\n openOnInsert={false}\n toForm={(x) => ({ title: x.title, depth: x.depth })}\n fromForm={(v) => ({ title: String(v.title ?? \"\"), depth: v.depth === \"2\" ? \"2\" : \"3\" })}\n >\n {() => <TocPreview m={m} outline={ctx.outline ?? NO_OUTLINE} host={el} />}\n </ArticlePopoverBlock>\n );\n}\n"],"mappings":"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"}
|
package/dist/core/core.d.ts
CHANGED
|
@@ -9,12 +9,15 @@
|
|
|
9
9
|
* Laws (PBT, src/core/__tests__): norm∘embed = id on C (P1); normProd(embedProd(c)) equals c except under the paths
|
|
10
10
|
* the adapter names (P2); prod zod accepts embedProd(c) (P3); every named loss is excluded, pending or out of its bound
|
|
11
11
|
* (P4); both normalisers are idempotent (P5); the hash is byte-stable (P6); one prod key per facet (P7); out-of-domain
|
|
12
|
-
* prod keys survive a write (P8).
|
|
12
|
+
* prod keys survive a write (P8). The hash is `core1:` + sha256 of types' canonicalJson.
|
|
13
13
|
*
|
|
14
14
|
* V2's equivalences folded by normV2 (what the V2 engine draws the same, so C cannot tell apart):
|
|
15
15
|
* - a list's itemNoun equal to the engine's fallback (lib/schema.ts itemNoun) is the absent one
|
|
16
16
|
* - a fieldset a field names but the schema does not declare is the declared { name, title: name } (engine/field-list
|
|
17
17
|
* arrange), appended after the declared ones in first-use order
|
|
18
|
+
* - a rich text's references naming neither posts nor authors are the absent ones
|
|
19
|
+
* - a rich text's features are read through types normaliseRichTextFeatures (an alias is its names: `headings` is
|
|
20
|
+
* h1–h6), each name once; naming every RICHTEXT_FEATURES entry, in any order, is the absent list (V2 offers them all)
|
|
18
21
|
*/
|
|
19
22
|
import { type AdapterTarget, type FromTypeSchemaResult, type ToTypeSchemaOptions } from "../adapters/schema";
|
|
20
23
|
import type { ProdComponent, ProdContentModel } from "../adapters/prod-types";
|
|
@@ -33,9 +36,14 @@ export declare function embedProd(c: CoreSchema, lane: "fields"): FromTypeSchema
|
|
|
33
36
|
export declare function embedProd(c: CoreSchema, lane: "props"): FromTypeSchemaResult<ProdComponent>;
|
|
34
37
|
export declare function embedProd(c: CoreSchema, lane: AdapterTarget): FromTypeSchemaResult<ProdContentModel | ProdComponent>;
|
|
35
38
|
export declare function normProd(prod: ProdContentModel | ProdComponent, lane: AdapterTarget, opts?: ToTypeSchemaOptions): CoreSchema;
|
|
36
|
-
/** Byte-stable serialisation of C:
|
|
39
|
+
/** Byte-stable serialisation of C: types' canonicalJson (the bytes the backend's schema_hash is taken over, same rules). */
|
|
37
40
|
export declare const coreJson: (c: CoreSchema) => string;
|
|
38
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* A Core hash's prefix: `core<v>:`. Disjoint from the backend's `schema_hash` prefix (`v<n>:`, taken over a stored
|
|
43
|
+
* definition, types' schemaHashInput), so a Core hash can never be read as, or compared with, a stored one.
|
|
44
|
+
*/
|
|
45
|
+
export declare const CORE_HASH_PREFIX: "core1:";
|
|
46
|
+
/** CORE_HASH_PREFIX + sha256 of coreJson (Web Crypto: the same in the browser, Node and Bun). */
|
|
39
47
|
export declare function coreHash(c: CoreSchema): Promise<string>;
|
|
40
48
|
/** The leaf paths where two JSON values differ ("/fields/0/title"); a missing object or list compares as an empty one. */
|
|
41
49
|
export declare function leafDiff(a: unknown, b: unknown, path?: string, out?: string[]): string[];
|
package/dist/core/core.js
CHANGED
|
@@ -2,6 +2,7 @@ import { SERVER_CONFIG_KEYS, isHostConfigKey } from "../adapters/lossy.js";
|
|
|
2
2
|
import { fromTypeSchema, propsToTypeSchema, toTypeSchema } from "../adapters/schema.js";
|
|
3
3
|
import { itemNoun } from "../lib/schema.js";
|
|
4
4
|
import { facetOf } from "./facets.js";
|
|
5
|
+
import { RICHTEXT_FEATURES, canonicalJson, normaliseRichTextFeatures } from "@bettercms-ai/types";
|
|
5
6
|
//#region src/core/core.ts
|
|
6
7
|
/**
|
|
7
8
|
* THE CORE SCHEMA `C` (P2 C1): one canonical, versioned form of a V2 schema that both directions meet in.
|
|
@@ -14,12 +15,15 @@ import { facetOf } from "./facets.js";
|
|
|
14
15
|
* Laws (PBT, src/core/__tests__): norm∘embed = id on C (P1); normProd(embedProd(c)) equals c except under the paths
|
|
15
16
|
* the adapter names (P2); prod zod accepts embedProd(c) (P3); every named loss is excluded, pending or out of its bound
|
|
16
17
|
* (P4); both normalisers are idempotent (P5); the hash is byte-stable (P6); one prod key per facet (P7); out-of-domain
|
|
17
|
-
* prod keys survive a write (P8).
|
|
18
|
+
* prod keys survive a write (P8). The hash is `core1:` + sha256 of types' canonicalJson.
|
|
18
19
|
*
|
|
19
20
|
* V2's equivalences folded by normV2 (what the V2 engine draws the same, so C cannot tell apart):
|
|
20
21
|
* - a list's itemNoun equal to the engine's fallback (lib/schema.ts itemNoun) is the absent one
|
|
21
22
|
* - a fieldset a field names but the schema does not declare is the declared { name, title: name } (engine/field-list
|
|
22
23
|
* arrange), appended after the declared ones in first-use order
|
|
24
|
+
* - a rich text's references naming neither posts nor authors are the absent ones
|
|
25
|
+
* - a rich text's features are read through types normaliseRichTextFeatures (an alias is its names: `headings` is
|
|
26
|
+
* h1–h6), each name once; naming every RICHTEXT_FEATURES entry, in any order, is the absent list (V2 offers them all)
|
|
23
27
|
*/
|
|
24
28
|
var CORE_VERSION = 1;
|
|
25
29
|
var isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
@@ -31,6 +35,8 @@ function canonical(v) {
|
|
|
31
35
|
for (const k of Object.keys(v).sort()) if (v[k] !== void 0) out[k] = canonical(v[k]);
|
|
32
36
|
return out;
|
|
33
37
|
}
|
|
38
|
+
/** Every feature, canonical: RICHTEXT_FEATURES through normaliseRichTextFeatures, so no alias is ever in it. */
|
|
39
|
+
var ALL_RICH_FEATURES = normaliseRichTextFeatures(RICHTEXT_FEATURES).features;
|
|
34
40
|
function foldField(f) {
|
|
35
41
|
const out = { ...f };
|
|
36
42
|
if (out.fields) out.fields = out.fields.map(foldField);
|
|
@@ -40,6 +46,13 @@ function foldField(f) {
|
|
|
40
46
|
...out,
|
|
41
47
|
itemNoun: void 0
|
|
42
48
|
})) delete out.itemNoun;
|
|
49
|
+
if (out.references && out.references.posts === void 0 && out.references.authors === void 0) delete out.references;
|
|
50
|
+
if (Array.isArray(out.features)) {
|
|
51
|
+
const { features, unknown } = normaliseRichTextFeatures(out.features.filter((x) => typeof x === "string"));
|
|
52
|
+
const names = [.../* @__PURE__ */ new Set([...features, ...unknown])];
|
|
53
|
+
if (unknown.length === 0 && ALL_RICH_FEATURES.every((x) => names.includes(x))) delete out.features;
|
|
54
|
+
else out.features = names;
|
|
55
|
+
}
|
|
43
56
|
return out;
|
|
44
57
|
}
|
|
45
58
|
/** The fieldsets fields name, depth first, the way the adapter visits them (fromTypeSchema propSetsFor / fieldsetsFor). */
|
|
@@ -76,11 +89,16 @@ function embedProd(c, lane) {
|
|
|
76
89
|
function normProd(prod, lane, opts = {}) {
|
|
77
90
|
return normV2(lane === "fields" ? toTypeSchema(prod, opts) : propsToTypeSchema(prod, opts));
|
|
78
91
|
}
|
|
79
|
-
/** Byte-stable serialisation of C:
|
|
80
|
-
var coreJson = (c) =>
|
|
81
|
-
/**
|
|
92
|
+
/** Byte-stable serialisation of C: types' canonicalJson (the bytes the backend's schema_hash is taken over, same rules). */
|
|
93
|
+
var coreJson = (c) => canonicalJson(c);
|
|
94
|
+
/**
|
|
95
|
+
* A Core hash's prefix: `core<v>:`. Disjoint from the backend's `schema_hash` prefix (`v<n>:`, taken over a stored
|
|
96
|
+
* definition, types' schemaHashInput), so a Core hash can never be read as, or compared with, a stored one.
|
|
97
|
+
*/
|
|
98
|
+
var CORE_HASH_PREFIX = `core1:`;
|
|
99
|
+
/** CORE_HASH_PREFIX + sha256 of coreJson (Web Crypto: the same in the browser, Node and Bun). */
|
|
82
100
|
async function coreHash(c) {
|
|
83
|
-
return
|
|
101
|
+
return `${CORE_HASH_PREFIX}${[...new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(coreJson(c))))].map((b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
84
102
|
}
|
|
85
103
|
/** The leaf paths where two JSON values differ ("/fields/0/title"); a missing object or list compares as an empty one. */
|
|
86
104
|
function leafDiff(a, b, path = "", out = []) {
|
|
@@ -166,6 +184,6 @@ function preserveOutOfDomain(written, stored, lane) {
|
|
|
166
184
|
};
|
|
167
185
|
}
|
|
168
186
|
//#endregion
|
|
169
|
-
export { CORE_VERSION, canonical, coreHash, coreJson, embedProd, embedV2, leafDiff, normProd, normV2, preserveOutOfDomain, roundTripCore };
|
|
187
|
+
export { CORE_HASH_PREFIX, CORE_VERSION, canonical, coreHash, coreJson, embedProd, embedV2, leafDiff, normProd, normV2, preserveOutOfDomain, roundTripCore };
|
|
170
188
|
|
|
171
189
|
//# sourceMappingURL=core.js.map
|
package/dist/core/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","names":[],"sources":["../../src/core/core.ts"],"sourcesContent":["/**\n * THE CORE SCHEMA `C` (P2 C1): one canonical, versioned form of a V2 schema that both directions meet in.\n *\n * normV2: V2 → C canonical JSON (sorted keys, no undefined) of the V2 schema, with V2's own equivalences folded\n * embedV2: C → V2 the schema C holds\n * embedProd: C → prod the prod adapter (fromTypeSchema, the façade) on embedV2(c)\n * normProd: prod → C normV2 of what the prod schema reads back as (toTypeSchema / propsToTypeSchema, the façades)\n *\n * Laws (PBT, src/core/__tests__): norm∘embed = id on C (P1); normProd(embedProd(c)) equals c except under the paths\n * the adapter names (P2); prod zod accepts embedProd(c) (P3); every named loss is excluded, pending or out of its bound\n * (P4); both normalisers are idempotent (P5); the hash is byte-stable (P6); one prod key per facet (P7); out-of-domain\n * prod keys survive a write (P8).\n *\n * V2's equivalences folded by normV2 (what the V2 engine draws the same, so C cannot tell apart):\n * - a list's itemNoun equal to the engine's fallback (lib/schema.ts itemNoun) is the absent one\n * - a fieldset a field names but the schema does not declare is the declared { name, title: name } (engine/field-list\n * arrange), appended after the declared ones in first-use order\n */\nimport { fromTypeSchema, propsToTypeSchema, toTypeSchema, type AdapterTarget, type FromTypeSchemaResult, type ToTypeSchemaOptions } from \"../adapters/schema\";\nimport { isHostConfigKey, SERVER_CONFIG_KEYS, type CatalogItem, type LossyItem } from \"../adapters/lossy\";\nimport type { ProdComponent, ProdContentModel } from \"../adapters/prod-types\";\nimport { itemNoun } from \"../lib/schema\";\nimport type { FieldSchema, TypeSchema } from \"../schema/types\";\nimport { facetOf, type FacetRow } from \"./facets\";\n\nexport const CORE_VERSION = 1 as const;\n\nexport interface CoreSchema {\n v: typeof CORE_VERSION;\n schema: TypeSchema;\n}\n\ntype Obj = Record<string, unknown>;\nconst isObj = (v: unknown): v is Obj => !!v && typeof v === \"object\" && !Array.isArray(v);\n\n/** Canonical JSON value: object keys sorted, undefined dropped, arrays in their order (order is meaning). */\nexport function canonical<T>(v: T): T {\n if (Array.isArray(v)) return v.map(canonical) as T;\n if (!isObj(v)) return v;\n const out: Obj = {};\n for (const k of Object.keys(v).sort()) if (v[k] !== undefined) out[k] = canonical(v[k]);\n return out as T;\n}\n\nfunction foldField(f: FieldSchema): FieldSchema {\n const out: FieldSchema = { ...f };\n if (out.fields) out.fields = out.fields.map(foldField);\n if (Array.isArray(out.of)) out.of = out.of.map(foldField);\n if (out.slotSettings) out.slotSettings = out.slotSettings.map(foldField);\n if (out.itemNoun !== undefined && out.itemNoun === itemNoun({ ...out, itemNoun: undefined })) delete out.itemNoun;\n return out;\n}\n\n/** The fieldsets fields name, depth first, the way the adapter visits them (fromTypeSchema propSetsFor / fieldsetsFor). */\nfunction namedSets(fields: FieldSchema[], out: string[] = []): string[] {\n for (const f of fields) {\n if (f.fieldset !== undefined && !out.includes(f.fieldset)) out.push(f.fieldset);\n if (f.fields) namedSets(f.fields, out);\n if (Array.isArray(f.of)) for (const i of f.of) if (i.fields) namedSets(i.fields, out);\n }\n return out;\n}\n\nexport function normV2(v2: TypeSchema): CoreSchema {\n const schema: TypeSchema = { ...v2, fields: v2.fields.map(foldField) };\n const declared = new Set((v2.fieldsets ?? []).map((s) => s.name));\n const undeclared = namedSets(v2.fields).filter((n) => !declared.has(n));\n if (undeclared.length) schema.fieldsets = [...(v2.fieldsets ?? []), ...undeclared.map((name) => ({ name, title: name }))];\n return { v: CORE_VERSION, schema: canonical(schema) };\n}\n\nexport const embedV2 = (c: CoreSchema): TypeSchema => structuredClone(c.schema);\n\nexport function embedProd(c: CoreSchema, lane: \"fields\"): FromTypeSchemaResult<ProdContentModel>;\nexport function embedProd(c: CoreSchema, lane: \"props\"): FromTypeSchemaResult<ProdComponent>;\nexport function embedProd(c: CoreSchema, lane: AdapterTarget): FromTypeSchemaResult<ProdContentModel | ProdComponent>;\nexport function embedProd(c: CoreSchema, lane: AdapterTarget) {\n return lane === \"fields\" ? fromTypeSchema(embedV2(c), \"fields\") : fromTypeSchema(embedV2(c), \"props\");\n}\n\nexport function normProd(prod: ProdContentModel | ProdComponent, lane: AdapterTarget, opts: ToTypeSchemaOptions = {}): CoreSchema {\n return normV2(lane === \"fields\" ? toTypeSchema(prod as ProdContentModel, opts) : propsToTypeSchema(prod as ProdComponent, opts));\n}\n\n/** Byte-stable serialisation of C: the hash input, and the form fixtures are frozen in. */\nexport const coreJson = (c: CoreSchema): string => JSON.stringify(canonical(c));\n\n/** `schema_hash`: \"v1:\" + sha256 of coreJson (Web Crypto: the same in the browser, Node and Bun). */\nexport async function coreHash(c: CoreSchema): Promise<string> {\n const bytes = new Uint8Array(await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(coreJson(c))));\n return `v${CORE_VERSION}:${[...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\n/** The leaf paths where two JSON values differ (\"/fields/0/title\"); a missing object or list compares as an empty one. */\nexport function leafDiff(a: unknown, b: unknown, path = \"\", out: string[] = []): string[] {\n const obj = (x: unknown) => x === undefined || isObj(x);\n const arr = (x: unknown) => x === undefined || Array.isArray(x);\n if ((isObj(a) || isObj(b)) && obj(a) && obj(b)) {\n const A = (a ?? {}) as Obj;\n const B = (b ?? {}) as Obj;\n for (const k of new Set([...Object.keys(A), ...Object.keys(B)])) leafDiff(A[k], B[k], `${path}/${k}`, out);\n } else if ((Array.isArray(a) || Array.isArray(b)) && arr(a) && arr(b)) {\n const A = (a ?? []) as unknown[];\n const B = (b ?? []) as unknown[];\n for (let i = 0; i < Math.max(A.length, B.length); i++) leafDiff(A[i], B[i], `${path}/${i}`, out);\n } else if (JSON.stringify(a) !== JSON.stringify(b)) out.push(path);\n return out;\n}\n\nconst under = (path: string, root: string) => path === root || path.startsWith(`${root}/`);\n\nexport interface CoreLossItem {\n path: string;\n feature: string;\n facet: FacetRow | undefined;\n}\n\nexport interface CoreRoundTrip {\n prod: ProdContentModel | ProdComponent;\n back: CoreSchema;\n /** the paths where C and normProd(embedProd(C)) differ */\n diffs: string[];\n /** loss(c): each item the adapter names that has a difference under it (an item C's equivalences absorb is no loss) */\n loss: CoreLossItem[];\n /** a difference no named item covers: a silent drop (P2 fails on any) */\n unreported: string[];\n}\n\n/** C through prod and back, against the lane's read: the oracle P2 and P4 assert on. */\nexport function roundTripCore(c: CoreSchema, lane: AdapterTarget): CoreRoundTrip {\n const r = embedProd(c, lane);\n const back = normProd(r.schema, lane, { blockModels: r.blockModels });\n // the props lane reads each top-level field's default-group placement back explicitly: compare it as such\n const want = lane === \"props\" ? normV2(withDefaultGroups(c.schema)).schema : c.schema;\n const diffs = leafDiff(want, back.schema);\n const named: (LossyItem | CatalogItem)[] = [...r.lossy, ...r.catalog];\n return {\n prod: r.schema,\n back,\n diffs,\n loss: named.filter((l) => diffs.some((d) => under(d, l.path))).map((l) => ({ path: l.path, feature: l.feature, facet: facetOf(l.feature) })),\n unreported: diffs.filter((d) => !named.some((l) => under(d, l.path))),\n };\n}\n\nfunction withDefaultGroups(s: TypeSchema): TypeSchema {\n const d = (s.groups?.find((g) => g.default) ?? s.groups?.[0])?.name;\n return d === undefined ? s : { ...s, fields: s.fields.map((f) => (f.group === undefined ? { ...f, group: d } : f)) };\n}\n\n/* ── P8: out-of-domain prod keys survive a write ── */\n\ntype ProdDef = Obj & { key?: string; type?: string; config?: Obj; fields?: ProdDef[] };\nconst OUT_OF_DOMAIN_KEYS = [\"target\", \"stale\", \"origin\"] as const;\n\n/** One written definition with the out-of-domain keys of the stored one it replaces (same key) carried over. */\nfunction carryDef(written: ProdDef, stored: ProdDef | undefined): ProdDef {\n if (!stored) return written;\n const out: ProdDef = { ...written };\n for (const k of OUT_OF_DOMAIN_KEYS) if (stored[k] !== undefined && out[k] === undefined) out[k] = stored[k];\n const type = String(written.type ?? \"\");\n const host = Object.entries(stored.config ?? {}).filter(([k, v]) => v !== undefined && (isHostConfigKey(type, k) || SERVER_CONFIG_KEYS.has(k)) && out.config?.[k] === undefined);\n if (host.length || out.config) out.config = { ...(out.config ?? {}), ...Object.fromEntries(host) };\n // nested definitions: a model field's fields, a prop's config.fields\n if (Array.isArray(written.fields)) out.fields = carryList(written.fields, stored.fields);\n const cf = out.config?.fields;\n if (Array.isArray(cf)) out.config = { ...out.config, fields: carryList(cf as ProdDef[], stored.config?.fields as ProdDef[] | undefined) };\n return out;\n}\n\nconst carryList = (written: ProdDef[], stored: ProdDef[] | undefined) => written.map((w) => carryDef(w, stored?.find((s) => s.key === w.key)));\n\n/**\n * A prod definition written from C, with every out-of-domain key (facets.ts OUT_OF_DOMAIN: a prop's binding, host and\n * server config) the stored definition held carried over by key. What write_schema stores (C6).\n */\nexport function preserveOutOfDomain<T extends ProdContentModel | ProdComponent>(written: T, stored: T | undefined, lane: AdapterTarget): T {\n if (!stored) return written;\n const list = lane === \"fields\" ? \"fields\" : \"props\";\n const w = written as unknown as Obj;\n const s = stored as unknown as Obj;\n return { ...w, [list]: carryList((w[list] as ProdDef[]) ?? [], s[list] as ProdDef[] | undefined) } as unknown as T;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core.js","names":[],"sources":["../../src/core/core.ts"],"sourcesContent":["/**\n * THE CORE SCHEMA `C` (P2 C1): one canonical, versioned form of a V2 schema that both directions meet in.\n *\n * normV2: V2 → C canonical JSON (sorted keys, no undefined) of the V2 schema, with V2's own equivalences folded\n * embedV2: C → V2 the schema C holds\n * embedProd: C → prod the prod adapter (fromTypeSchema, the façade) on embedV2(c)\n * normProd: prod → C normV2 of what the prod schema reads back as (toTypeSchema / propsToTypeSchema, the façades)\n *\n * Laws (PBT, src/core/__tests__): norm∘embed = id on C (P1); normProd(embedProd(c)) equals c except under the paths\n * the adapter names (P2); prod zod accepts embedProd(c) (P3); every named loss is excluded, pending or out of its bound\n * (P4); both normalisers are idempotent (P5); the hash is byte-stable (P6); one prod key per facet (P7); out-of-domain\n * prod keys survive a write (P8). The hash is `core1:` + sha256 of types' canonicalJson.\n *\n * V2's equivalences folded by normV2 (what the V2 engine draws the same, so C cannot tell apart):\n * - a list's itemNoun equal to the engine's fallback (lib/schema.ts itemNoun) is the absent one\n * - a fieldset a field names but the schema does not declare is the declared { name, title: name } (engine/field-list\n * arrange), appended after the declared ones in first-use order\n * - a rich text's references naming neither posts nor authors are the absent ones\n * - a rich text's features are read through types normaliseRichTextFeatures (an alias is its names: `headings` is\n * h1–h6), each name once; naming every RICHTEXT_FEATURES entry, in any order, is the absent list (V2 offers them all)\n */\nimport { fromTypeSchema, propsToTypeSchema, toTypeSchema, type AdapterTarget, type FromTypeSchemaResult, type ToTypeSchemaOptions } from \"../adapters/schema\";\nimport { isHostConfigKey, SERVER_CONFIG_KEYS, type CatalogItem, type LossyItem } from \"../adapters/lossy\";\nimport type { ProdComponent, ProdContentModel } from \"../adapters/prod-types\";\nimport { canonicalJson, normaliseRichTextFeatures, RICHTEXT_FEATURES, type RichTextFeature } from \"@bettercms-ai/types\";\nimport { itemNoun } from \"../lib/schema\";\nimport type { FieldSchema, TypeSchema } from \"../schema/types\";\nimport { facetOf, type FacetRow } from \"./facets\";\n\nexport const CORE_VERSION = 1 as const;\n\nexport interface CoreSchema {\n v: typeof CORE_VERSION;\n schema: TypeSchema;\n}\n\ntype Obj = Record<string, unknown>;\nconst isObj = (v: unknown): v is Obj => !!v && typeof v === \"object\" && !Array.isArray(v);\n\n/** Canonical JSON value: object keys sorted, undefined dropped, arrays in their order (order is meaning). */\nexport function canonical<T>(v: T): T {\n if (Array.isArray(v)) return v.map(canonical) as T;\n if (!isObj(v)) return v;\n const out: Obj = {};\n for (const k of Object.keys(v).sort()) if (v[k] !== undefined) out[k] = canonical(v[k]);\n return out as T;\n}\n\n/** Every feature, canonical: RICHTEXT_FEATURES through normaliseRichTextFeatures, so no alias is ever in it. */\nconst ALL_RICH_FEATURES = normaliseRichTextFeatures(RICHTEXT_FEATURES).features;\n\nfunction foldField(f: FieldSchema): FieldSchema {\n const out: FieldSchema = { ...f };\n if (out.fields) out.fields = out.fields.map(foldField);\n if (Array.isArray(out.of)) out.of = out.of.map(foldField);\n if (out.slotSettings) out.slotSettings = out.slotSettings.map(foldField);\n if (out.itemNoun !== undefined && out.itemNoun === itemNoun({ ...out, itemNoun: undefined })) delete out.itemNoun;\n if (out.references && out.references.posts === undefined && out.references.authors === undefined) delete out.references;\n if (Array.isArray(out.features)) {\n const { features, unknown } = normaliseRichTextFeatures(out.features.filter((x) => typeof x === \"string\"));\n const names = [...new Set<string>([...features, ...unknown])];\n if (unknown.length === 0 && ALL_RICH_FEATURES.every((x) => names.includes(x))) delete out.features;\n // an unknown name stays (a schema read from JSON can hold one): the write names it, it is never dropped silently\n else out.features = names as RichTextFeature[];\n }\n return out;\n}\n\n/** The fieldsets fields name, depth first, the way the adapter visits them (fromTypeSchema propSetsFor / fieldsetsFor). */\nfunction namedSets(fields: FieldSchema[], out: string[] = []): string[] {\n for (const f of fields) {\n if (f.fieldset !== undefined && !out.includes(f.fieldset)) out.push(f.fieldset);\n if (f.fields) namedSets(f.fields, out);\n if (Array.isArray(f.of)) for (const i of f.of) if (i.fields) namedSets(i.fields, out);\n }\n return out;\n}\n\nexport function normV2(v2: TypeSchema): CoreSchema {\n const schema: TypeSchema = { ...v2, fields: v2.fields.map(foldField) };\n const declared = new Set((v2.fieldsets ?? []).map((s) => s.name));\n const undeclared = namedSets(v2.fields).filter((n) => !declared.has(n));\n if (undeclared.length) schema.fieldsets = [...(v2.fieldsets ?? []), ...undeclared.map((name) => ({ name, title: name }))];\n return { v: CORE_VERSION, schema: canonical(schema) };\n}\n\nexport const embedV2 = (c: CoreSchema): TypeSchema => structuredClone(c.schema);\n\nexport function embedProd(c: CoreSchema, lane: \"fields\"): FromTypeSchemaResult<ProdContentModel>;\nexport function embedProd(c: CoreSchema, lane: \"props\"): FromTypeSchemaResult<ProdComponent>;\nexport function embedProd(c: CoreSchema, lane: AdapterTarget): FromTypeSchemaResult<ProdContentModel | ProdComponent>;\nexport function embedProd(c: CoreSchema, lane: AdapterTarget) {\n return lane === \"fields\" ? fromTypeSchema(embedV2(c), \"fields\") : fromTypeSchema(embedV2(c), \"props\");\n}\n\nexport function normProd(prod: ProdContentModel | ProdComponent, lane: AdapterTarget, opts: ToTypeSchemaOptions = {}): CoreSchema {\n return normV2(lane === \"fields\" ? toTypeSchema(prod as ProdContentModel, opts) : propsToTypeSchema(prod as ProdComponent, opts));\n}\n\n/** Byte-stable serialisation of C: types' canonicalJson (the bytes the backend's schema_hash is taken over, same rules). */\nexport const coreJson = (c: CoreSchema): string => canonicalJson(c);\n\n/**\n * A Core hash's prefix: `core<v>:`. Disjoint from the backend's `schema_hash` prefix (`v<n>:`, taken over a stored\n * definition, types' schemaHashInput), so a Core hash can never be read as, or compared with, a stored one.\n */\nexport const CORE_HASH_PREFIX = `core${CORE_VERSION}:` as const;\n\n/** CORE_HASH_PREFIX + sha256 of coreJson (Web Crypto: the same in the browser, Node and Bun). */\nexport async function coreHash(c: CoreSchema): Promise<string> {\n const bytes = new Uint8Array(await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(coreJson(c))));\n return `${CORE_HASH_PREFIX}${[...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\n/** The leaf paths where two JSON values differ (\"/fields/0/title\"); a missing object or list compares as an empty one. */\nexport function leafDiff(a: unknown, b: unknown, path = \"\", out: string[] = []): string[] {\n const obj = (x: unknown) => x === undefined || isObj(x);\n const arr = (x: unknown) => x === undefined || Array.isArray(x);\n if ((isObj(a) || isObj(b)) && obj(a) && obj(b)) {\n const A = (a ?? {}) as Obj;\n const B = (b ?? {}) as Obj;\n for (const k of new Set([...Object.keys(A), ...Object.keys(B)])) leafDiff(A[k], B[k], `${path}/${k}`, out);\n } else if ((Array.isArray(a) || Array.isArray(b)) && arr(a) && arr(b)) {\n const A = (a ?? []) as unknown[];\n const B = (b ?? []) as unknown[];\n for (let i = 0; i < Math.max(A.length, B.length); i++) leafDiff(A[i], B[i], `${path}/${i}`, out);\n } else if (JSON.stringify(a) !== JSON.stringify(b)) out.push(path);\n return out;\n}\n\nconst under = (path: string, root: string) => path === root || path.startsWith(`${root}/`);\n\nexport interface CoreLossItem {\n path: string;\n feature: string;\n facet: FacetRow | undefined;\n}\n\nexport interface CoreRoundTrip {\n prod: ProdContentModel | ProdComponent;\n back: CoreSchema;\n /** the paths where C and normProd(embedProd(C)) differ */\n diffs: string[];\n /** loss(c): each item the adapter names that has a difference under it (an item C's equivalences absorb is no loss) */\n loss: CoreLossItem[];\n /** a difference no named item covers: a silent drop (P2 fails on any) */\n unreported: string[];\n}\n\n/** C through prod and back, against the lane's read: the oracle P2 and P4 assert on. */\nexport function roundTripCore(c: CoreSchema, lane: AdapterTarget): CoreRoundTrip {\n const r = embedProd(c, lane);\n const back = normProd(r.schema, lane, { blockModels: r.blockModels });\n // the props lane reads each top-level field's default-group placement back explicitly: compare it as such\n const want = lane === \"props\" ? normV2(withDefaultGroups(c.schema)).schema : c.schema;\n const diffs = leafDiff(want, back.schema);\n const named: (LossyItem | CatalogItem)[] = [...r.lossy, ...r.catalog];\n return {\n prod: r.schema,\n back,\n diffs,\n loss: named.filter((l) => diffs.some((d) => under(d, l.path))).map((l) => ({ path: l.path, feature: l.feature, facet: facetOf(l.feature) })),\n unreported: diffs.filter((d) => !named.some((l) => under(d, l.path))),\n };\n}\n\nfunction withDefaultGroups(s: TypeSchema): TypeSchema {\n const d = (s.groups?.find((g) => g.default) ?? s.groups?.[0])?.name;\n return d === undefined ? s : { ...s, fields: s.fields.map((f) => (f.group === undefined ? { ...f, group: d } : f)) };\n}\n\n/* ── P8: out-of-domain prod keys survive a write ── */\n\ntype ProdDef = Obj & { key?: string; type?: string; config?: Obj; fields?: ProdDef[] };\nconst OUT_OF_DOMAIN_KEYS = [\"target\", \"stale\", \"origin\"] as const;\n\n/** One written definition with the out-of-domain keys of the stored one it replaces (same key) carried over. */\nfunction carryDef(written: ProdDef, stored: ProdDef | undefined): ProdDef {\n if (!stored) return written;\n const out: ProdDef = { ...written };\n for (const k of OUT_OF_DOMAIN_KEYS) if (stored[k] !== undefined && out[k] === undefined) out[k] = stored[k];\n const type = String(written.type ?? \"\");\n const host = Object.entries(stored.config ?? {}).filter(([k, v]) => v !== undefined && (isHostConfigKey(type, k) || SERVER_CONFIG_KEYS.has(k)) && out.config?.[k] === undefined);\n if (host.length || out.config) out.config = { ...(out.config ?? {}), ...Object.fromEntries(host) };\n // nested definitions: a model field's fields, a prop's config.fields\n if (Array.isArray(written.fields)) out.fields = carryList(written.fields, stored.fields);\n const cf = out.config?.fields;\n if (Array.isArray(cf)) out.config = { ...out.config, fields: carryList(cf as ProdDef[], stored.config?.fields as ProdDef[] | undefined) };\n return out;\n}\n\nconst carryList = (written: ProdDef[], stored: ProdDef[] | undefined) => written.map((w) => carryDef(w, stored?.find((s) => s.key === w.key)));\n\n/**\n * A prod definition written from C, with every out-of-domain key (facets.ts OUT_OF_DOMAIN: a prop's binding, host and\n * server config) the stored definition held carried over by key. What write_schema stores (C6).\n */\nexport function preserveOutOfDomain<T extends ProdContentModel | ProdComponent>(written: T, stored: T | undefined, lane: AdapterTarget): T {\n if (!stored) return written;\n const list = lane === \"fields\" ? \"fields\" : \"props\";\n const w = written as unknown as Obj;\n const s = stored as unknown as Obj;\n return { ...w, [list]: carryList((w[list] as ProdDef[]) ?? [], s[list] as ProdDef[] | undefined) } as unknown as T;\n}\n"],"mappings":"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"}
|
package/dist/core/facets.d.ts
CHANGED
|
@@ -341,6 +341,22 @@ export declare const FACETS: {
|
|
|
341
341
|
readonly "preview icon": FacetRow;
|
|
342
342
|
readonly "preview path": FacetRow;
|
|
343
343
|
readonly "unsupported key": FacetRow;
|
|
344
|
+
readonly "richtext references": {
|
|
345
|
+
readonly row: "B RT8";
|
|
346
|
+
readonly carrier: "value";
|
|
347
|
+
readonly props: readonly ["config.references"];
|
|
348
|
+
readonly fields: readonly ["config.references"];
|
|
349
|
+
readonly bound: "REFERENCES_MODEL_ID";
|
|
350
|
+
readonly status: "landed";
|
|
351
|
+
};
|
|
352
|
+
readonly "richtext features": {
|
|
353
|
+
readonly row: "B RT0";
|
|
354
|
+
readonly carrier: "value";
|
|
355
|
+
readonly props: readonly ["config.features"];
|
|
356
|
+
readonly fields: readonly ["config.features"];
|
|
357
|
+
readonly bound: "RICHTEXT_FEATURES";
|
|
358
|
+
readonly status: "landed";
|
|
359
|
+
};
|
|
344
360
|
};
|
|
345
361
|
export declare const facetOf: (feature: string) => FacetRow | undefined;
|
|
346
362
|
/** The owner-signed exclusions: what may be lost by design (shopify until its pipeline, and two deliberate backend rules). */
|
package/dist/core/facets.js
CHANGED
|
@@ -323,7 +323,23 @@ var FACETS = {
|
|
|
323
323
|
"item icon": corpusFix("ui.icon (list)", "ui.icon (list)", "DOCK_ICON_NAMES"),
|
|
324
324
|
"preview icon": corpusFix("ui.preview.icon", "ui.preview.icon", "DOCK_ICON_NAMES"),
|
|
325
325
|
"preview path": corpusFix("ui.preview.{title,subtitle,media}", "ui.preview.{title,subtitle,media}", "PREVIEW_PATH"),
|
|
326
|
-
"unsupported key": corpusFix("—", "—", "V2_SCHEMA_KEYS")
|
|
326
|
+
"unsupported key": corpusFix("—", "—", "V2_SCHEMA_KEYS"),
|
|
327
|
+
"richtext references": {
|
|
328
|
+
row: "B RT8",
|
|
329
|
+
carrier: "value",
|
|
330
|
+
props: ["config.references"],
|
|
331
|
+
fields: ["config.references"],
|
|
332
|
+
bound: "REFERENCES_MODEL_ID",
|
|
333
|
+
status: "landed"
|
|
334
|
+
},
|
|
335
|
+
"richtext features": {
|
|
336
|
+
row: "B RT0",
|
|
337
|
+
carrier: "value",
|
|
338
|
+
props: ["config.features"],
|
|
339
|
+
fields: ["config.features"],
|
|
340
|
+
bound: "RICHTEXT_FEATURES",
|
|
341
|
+
status: "landed"
|
|
342
|
+
}
|
|
327
343
|
};
|
|
328
344
|
var facetOf = (feature) => FACETS[feature];
|
|
329
345
|
/** The owner-signed exclusions: what may be lost by design (shopify until its pipeline, and two deliberate backend rules). */
|
package/dist/core/facets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"facets.js","names":[],"sources":["../../src/core/facets.ts"],"sourcesContent":["/**\n * THE FACET TABLE (kit-facet-table.v3.md, G0b closed 2026-10-23): every V2 schema facet the adapter can name, with the\n * ONE prod key per lane that stores it. `satisfies Record<V2Facet, FacetRow>` makes it total: a feature added to\n * FEATURES or CATALOG (adapters/lossy.ts) without a row here fails tsc.\n *\n * Carriers are `value` (an explicit stored key) and `excluded` (owner-signed). A `bound` names the one shared constant\n * the V2 authoring rule and the prod zod rule both read: a value inside it is carried, one outside it is refused with\n * the facet's name. `status` is \"landed\" when the adapter carries the facet today, else the step that lands it.\n * Prod-only keys V2 has no concept of are not facets: OUT_OF_DOMAIN, preserved on every write (PBT P8).\n */\nimport type { CatalogFeature, LossyFeature } from \"../adapters/lossy\";\n\n/** Prod keys with no V2 concept (facet table §B.1): never written from V2, carried through a write from the stored definition. */\nexport const OUT_OF_DOMAIN = {\n \"prop target\": \"a prop's binding: props[].target (+ stale, origin)\",\n \"host config\": \"HOST_CONFIG_KEYS + SERVER_CONFIG_KEYS in a field's or prop's config (adapters/lossy.ts)\",\n} as const satisfies Partial<Record<CatalogFeature, string>>;\nexport type OutOfDomainFeature = keyof typeof OUT_OF_DOMAIN;\n\nexport type V2Facet = Exclude<LossyFeature | CatalogFeature, OutOfDomainFeature>;\n\nexport interface FacetRow {\n /** facet table v3: an A row number, or the B group */\n row: string;\n carrier: \"value\" | \"excluded\";\n /** the prod key(s) per lane, one per shape the facet takes; [] = the facet does not arise in that lane */\n props: readonly string[];\n fields: readonly string[];\n /** the shared constant: inside it the facet is carried, outside it the facet is refused by name */\n bound?: string;\n status: \"landed\" | `pending:${string}`;\n /** a facet stored at another facet's key (kind:page is the shape facet's value \"page\") */\n foldedInto?: V2Facet;\n}\n\nconst corpusFix = (props: string, fields: string, bound: string): FacetRow => ({ row: \"B corpus-fix\", carrier: \"value\", props: [props], fields: [fields], bound, status: \"landed\" });\n\nexport const FACETS = {\n /* ── A: hit by the corpus ── */\n ai: { row: \"A1\", carrier: \"value\", props: [\"props[].ai\"], fields: [\"fields[].ai\"], status: \"pending:C3\" },\n category: { row: \"A2\", carrier: \"value\", props: [\"components.category\"], fields: [\"content_models.v2.category\"], bound: \"CATEGORY_ORDER\", status: \"pending:C3+C5\" },\n variants: {\n row: \"A3\",\n carrier: \"value\",\n props: [\"component_variant_groups (+ components.variant_group_id, variant_input_mappings; order/icon/description → component_variant_groups.v2.variants)\"],\n fields: [\"fields[_variant] select + showIf {field:_variant}; content_models.v2.variants{slug → {icon, description}}\"],\n status: \"pending:C4\",\n },\n \"block icon\": { row: \"A4\", carrier: \"value\", props: [\"components.icon\"], fields: [\"content_models.icon\"], bound: \"DOCK_ICON_NAMES\", status: \"pending:C1-model-settings\" },\n \"document preview\": { row: \"A5\", carrier: \"value\", props: [\"components.preview\"], fields: [\"content_models.list_preview\"], status: \"pending:C3\" },\n \"document preview path\": { row: \"B catalog\", carrier: \"value\", props: [\"components.preview (path rule widened)\"], fields: [], status: \"pending:C3\" },\n \"kind:global\": { row: \"A6\", carrier: \"value\", props: [\"components.v2.shape\"], fields: [\"content_models.v2.shape\"], status: \"pending:C5\" },\n \"kind:entry (props)\": { row: \"A6\", carrier: \"value\", props: [\"components.v2.shape\"], fields: [], status: \"pending:C5\", foldedInto: \"kind:global\" },\n \"kind:block (fields)\": { row: \"A6\", carrier: \"value\", props: [], fields: [\"content_models.v2.shape\"], status: \"pending:C5\", foldedInto: \"kind:global\" },\n \"kind:page\": { row: \"A22\", carrier: \"value\", props: [], fields: [\"content_models.v2.shape\"], status: \"pending:C5\", foldedInto: \"kind:global\" },\n \"kind:object\": { row: \"A6\", carrier: \"value\", props: [], fields: [\"content_models.v2.shape\"], status: \"pending:C5\", foldedInto: \"kind:global\" },\n \"groups>3\": { row: \"A7\", carrier: \"value\", props: [\"components.tabs\"], fields: [\"content_models.fieldsets[kind:tab]\"], bound: \"TAB_MAX\", status: \"pending:C3+C8\" },\n \"item openMode\": {\n row: \"A8\",\n carrier: \"value\",\n props: [\"config.item.openMode (object item)\", \"config.itemTypes[i].openMode (polymorphic)\"],\n fields: [\"ui.blocks[slug].openMode (modular)\"],\n status: \"pending:C3\",\n },\n \"reference target\": { row: \"A9\", carrier: \"value\", props: [\"config.targets\"], fields: [\"config.targets\"], bound: \"REF_TARGET_KINDS\", status: \"landed\" },\n \"type:slot\": { row: \"A10\", carrier: \"value\", props: [\"props[] type slot (config.allow)\"], fields: [\"fields[] type slot (config.blockSlugs)\"], bound: \"SLOT_BLOCK_SLUGS_REQUIRED\", status: \"landed\" },\n \"block model field\": { row: \"A11\", carrier: \"value\", props: [], fields: [\"kind:'block' model fields[]\"], bound: \"BLOCK_FIELD_TYPES\", status: \"pending:G7\" },\n \"shopify reference\": { row: \"A12\", carrier: \"excluded\", props: [], fields: [], status: \"landed\" },\n \"type:table\": { row: \"A13\", carrier: \"value\", props: [\"props[] type table (config.mode data)\"], fields: [\"fields[] type table\"], status: \"landed\" },\n \"group (nested)\": { row: \"A14\", carrier: \"value\", props: [\"ui.tab {id}\"], fields: [\"ui.tab {id} (nested field)\"], bound: \"TAB_MAX\", status: \"landed\" },\n \"fieldset collision\": { row: \"A15\", carrier: \"value\", props: [\"ui.group {id}\"], fields: [\"fieldsetId\"], bound: \"TAB_FIELDSET_ID_UNIQUE\", status: \"landed\" },\n \"segmented fallback\": { row: \"A16\", carrier: \"value\", props: [\"ui.control segmented\"], fields: [\"ui.control segmented\"], bound: \"SEGMENTED_MAX\", status: \"pending:C3\" },\n \"fieldset (derived)\": { row: \"A17\", carrier: \"value\", props: [\"ui.group (prop group)\"], fields: [\"content_models.fieldsets\"], status: \"landed\" },\n \"itemNoun (derived)\": { row: \"A18\", carrier: \"value\", props: [\"ui.itemLabel\"], fields: [\"ui.itemTitle\"], status: \"landed\" },\n \"reference filter\": { row: \"A19\", carrier: \"value\", props: [\"config.filter\"], fields: [\"config.filter\"], bound: \"REFERENCE_FILTER_MAX\", status: \"landed\" },\n condition: { row: \"A20\", carrier: \"value\", props: [\"showIf (+ scope)\"], fields: [\"showIf (+ scope)\"], bound: \"SHOW_IF_SCOPES\", status: \"pending:C3\" },\n openMode: { row: \"A21\", carrier: \"value\", props: [\"props[].openMode\"], fields: [\"fields[].openMode\"], bound: \"OPEN_MODE_TYPES\", status: \"pending:C9\" },\n \"slot allow\": { row: \"A23\", carrier: \"value\", props: [\"config.allow\"], fields: [\"config.blockSlugs\"], bound: \"SLOT_ALLOW\", status: \"landed\" },\n\n /* ── B: in the code, not hit by the corpus ── */\n \"type:polymorphic-array\": { row: \"B structural\", carrier: \"value\", props: [\"props[] type table (config.mode types)\"], fields: [\"fields[] type modular\"], status: \"pending:C3\" },\n \"item chrome (types)\": { row: \"B structural\", carrier: \"value\", props: [\"config.itemTypes[i] {icon, preview}\"], fields: [\"ui.blocks[slug] {icon, preview}\"], status: \"pending:C3\" },\n \"type:primitive-array\": { row: \"B decided\", carrier: \"value\", props: [\"config.itemType (widened)\"], fields: [\"config.itemType (widened)\"], status: \"pending:C3\" },\n \"depth>10\": { row: \"B decided\", carrier: \"value\", props: [\"nesting\"], fields: [\"nesting\"], bound: \"DEPTH_MAX\", status: \"landed\" },\n slotSettings: { row: \"B decided (BUILD)\", carrier: \"value\", props: [\"config.settings: FieldDef[]\"], fields: [\"config.settings: FieldDef[]\"], bound: \"SLOT_SETTINGS_MAX\", status: \"pending:C3\" },\n \"block placement\": { row: \"B catalog\", carrier: \"value\", props: [\"components.v2.placement\"], fields: [\"content_models.v2.placement\"], status: \"pending:C5\" },\n \"seeded instance\": { row: \"B catalog\", carrier: \"excluded\", props: [], fields: [], status: \"landed\" },\n \"not applicable (props)\": { row: \"B catalog\", carrier: \"excluded\", props: [], fields: [], status: \"landed\" },\n \"type name\": corpusFix(\"components.slug\", \"content_models.slug\", \"SLUG_RE\"),\n \"group name>40\": corpusFix(\"components.tabs[].id\", \"content_models.fieldsets[].id\", \"TAB_NAME_MAX\"),\n \"group title\": corpusFix(\"components.tabs[].name\", \"content_models.fieldsets[].name\", \"TAB_TITLE\"),\n \"group default\": corpusFix(\"components.tabs[0]\", \"content_models.fieldsets[0]\", \"TAB_DEFAULT_FIRST\"),\n \"group icon\": corpusFix(\"components.tabs[].icon\", \"content_models.fieldsets[].icon\", \"DOCK_ICON_NAMES\"),\n \"group name collision\": corpusFix(\"components.tabs[].name\", \"content_models.fieldsets[].name\", \"TAB_NAME_UNIQUE\"),\n \"prop tab limit\": corpusFix(\"components.tabs\", \"content_models.fieldsets\", \"PROP_TAB_MAX\"),\n \"fieldset spans groups\": corpusFix(\"ui.group.tab\", \"fieldsets[].tab\", \"FIELDSET_ONE_TAB\"),\n \"fieldset (props)\": corpusFix(\"ui.group (first prop)\", \"content_models.fieldsets\", \"PROP_GROUP_DEFINED_ON_USE\"),\n \"fieldset name>limit\": corpusFix(\"ui.group.label\", \"content_models.fieldsets[].name\", \"FIELDSET_NAME_MAX\"),\n \"duplicate name\": corpusFix(\"props[].key\", \"fields[].key\", \"KEY_UNIQUE\"),\n \"reserved name\": { row: \"B corpus-fix\", carrier: \"value\", props: [], fields: [\"fields[].key\"], bound: \"KEY_RESERVED + KEY_FORMAT\", status: \"landed\" },\n rows: corpusFix(\"ui.rows\", \"ui.rows\", \"UI_ROWS_MAX\"),\n synced: corpusFix(\"ui.synced\", \"ui.synced\", \"SYNCED_FROM_MAX\"),\n valueShape: corpusFix(\"ui.valueShape\", \"ui.valueShape\", \"VALUE_SHAPE_TYPES\"),\n \"default value\": corpusFix(\"props[].defaultValue\", \"fields[].defaultValue\", \"VALUE_SCHEMAS\"),\n icon: corpusFix(\"ui.icon\", \"ui.icon\", \"DOCK_ICON_NAMES\"),\n layout: corpusFix(\"ui.control / ui.layout\", \"ui.control / ui.layout\", \"CONTROL_TYPES\"),\n \"help>limit\": corpusFix(\"helpText / placeholder / helpMore\", \"helpText / ui.placeholder / helpMore\", \"HELP_CAPS\"),\n \"option icon\": corpusFix(\"options[].icon\", \"options[].icon\", \"DOCK_ICON_NAMES\"),\n \"option description\": corpusFix(\"options[].description\", \"options[].description\", \"OPTION_DESCRIPTION_MAX\"),\n access: corpusFix(\"ui.access\", \"ui.access\", \"ACCESS_CAPS\"),\n timezone: corpusFix(\"config.timezone\", \"config.timezone\", \"TIMEZONE\"),\n \"reference order\": corpusFix(\"config.contentModelId|allowedModelSlugs, config.targets\", \"config.contentModelId|allowedModelSlugs, config.targets\", \"REFERENCE_TO_ORDER\"),\n \"numeric unit\": corpusFix(\"config.unit\", \"config.unit\", \"NUMBER_UNIT_MAX\"),\n \"rating bounds\": corpusFix(\"config.min/max/step (rating)\", \"config.min/max/step (rating)\", \"RATING_BOUNDS\"),\n \"scale rules\": corpusFix(\"config.scale\", \"config.scale\", \"SCALE_RULES\"),\n \"validation.patternMessage\": corpusFix(\"config.patternMessage\", \"config.patternMessage\", \"PATTERN_MESSAGE_MAX\"),\n \"validation.pattern\": corpusFix(\"config.pattern\", \"config.pattern\", \"PATTERN_MAX\"),\n \"validation.length\": corpusFix(\"config.minLength/maxLength\", \"config.minLength/maxLength\", \"LENGTH_TYPES\"),\n \"validation.items\": corpusFix(\"config.minItems/maxItems\", \"config.minItems/maxItems\", \"LIST_ITEMS_CAP\"),\n \"validation.unique\": corpusFix(\"props[].unique\", \"fields[].unique\", \"UNIQUE_TYPES\"),\n \"validation.recommendedMax\": corpusFix(\"props[].recommendedMax\", \"fields[].recommendedMax\", \"RECOMMENDED_MAX\"),\n \"item identity\": corpusFix(\"ui.itemName / ui.itemTitle\", \"ui.itemName / ui.itemTitle\", \"ITEM_NAME_RE\"),\n \"item settings\": corpusFix(\"config.item\", \"config.item\", \"ARRAY_ITEM_SETTINGS\"),\n itemNoun: corpusFix(\"ui.itemLabel\", \"ui.itemLabel\", \"ITEM_LABEL_MAX\"),\n \"item icon\": corpusFix(\"ui.icon (list)\", \"ui.icon (list)\", \"DOCK_ICON_NAMES\"),\n \"preview icon\": corpusFix(\"ui.preview.icon\", \"ui.preview.icon\", \"DOCK_ICON_NAMES\"),\n \"preview path\": corpusFix(\"ui.preview.{title,subtitle,media}\", \"ui.preview.{title,subtitle,media}\", \"PREVIEW_PATH\"),\n \"unsupported key\": corpusFix(\"—\", \"—\", \"V2_SCHEMA_KEYS\"),\n} as const satisfies Record<V2Facet, FacetRow>;\n\nexport const facetOf = (feature: string): FacetRow | undefined => (FACETS as Record<string, FacetRow>)[feature];\n\n/** The owner-signed exclusions: what may be lost by design (shopify until its pipeline, and two deliberate backend rules). */\nexport const EXCLUDED: readonly V2Facet[] = (Object.keys(FACETS) as V2Facet[]).filter((f) => FACETS[f].carrier === \"excluded\");\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"facets.js","names":[],"sources":["../../src/core/facets.ts"],"sourcesContent":["/**\n * THE FACET TABLE (kit-facet-table.v3.md, G0b closed 2026-10-23): every V2 schema facet the adapter can name, with the\n * ONE prod key per lane that stores it. `satisfies Record<V2Facet, FacetRow>` makes it total: a feature added to\n * FEATURES or CATALOG (adapters/lossy.ts) without a row here fails tsc.\n *\n * Carriers are `value` (an explicit stored key) and `excluded` (owner-signed). A `bound` names the one shared constant\n * the V2 authoring rule and the prod zod rule both read: a value inside it is carried, one outside it is refused with\n * the facet's name. `status` is \"landed\" when the adapter carries the facet today, else the step that lands it.\n * Prod-only keys V2 has no concept of are not facets: OUT_OF_DOMAIN, preserved on every write (PBT P8).\n */\nimport type { CatalogFeature, LossyFeature } from \"../adapters/lossy\";\n\n/** Prod keys with no V2 concept (facet table §B.1): never written from V2, carried through a write from the stored definition. */\nexport const OUT_OF_DOMAIN = {\n \"prop target\": \"a prop's binding: props[].target (+ stale, origin)\",\n \"host config\": \"HOST_CONFIG_KEYS + SERVER_CONFIG_KEYS in a field's or prop's config (adapters/lossy.ts)\",\n} as const satisfies Partial<Record<CatalogFeature, string>>;\nexport type OutOfDomainFeature = keyof typeof OUT_OF_DOMAIN;\n\nexport type V2Facet = Exclude<LossyFeature | CatalogFeature, OutOfDomainFeature>;\n\nexport interface FacetRow {\n /** facet table v3: an A row number, or the B group */\n row: string;\n carrier: \"value\" | \"excluded\";\n /** the prod key(s) per lane, one per shape the facet takes; [] = the facet does not arise in that lane */\n props: readonly string[];\n fields: readonly string[];\n /** the shared constant: inside it the facet is carried, outside it the facet is refused by name */\n bound?: string;\n status: \"landed\" | `pending:${string}`;\n /** a facet stored at another facet's key (kind:page is the shape facet's value \"page\") */\n foldedInto?: V2Facet;\n}\n\nconst corpusFix = (props: string, fields: string, bound: string): FacetRow => ({ row: \"B corpus-fix\", carrier: \"value\", props: [props], fields: [fields], bound, status: \"landed\" });\n\nexport const FACETS = {\n /* ── A: hit by the corpus ── */\n ai: { row: \"A1\", carrier: \"value\", props: [\"props[].ai\"], fields: [\"fields[].ai\"], status: \"pending:C3\" },\n category: { row: \"A2\", carrier: \"value\", props: [\"components.category\"], fields: [\"content_models.v2.category\"], bound: \"CATEGORY_ORDER\", status: \"pending:C3+C5\" },\n variants: {\n row: \"A3\",\n carrier: \"value\",\n props: [\"component_variant_groups (+ components.variant_group_id, variant_input_mappings; order/icon/description → component_variant_groups.v2.variants)\"],\n fields: [\"fields[_variant] select + showIf {field:_variant}; content_models.v2.variants{slug → {icon, description}}\"],\n status: \"pending:C4\",\n },\n \"block icon\": { row: \"A4\", carrier: \"value\", props: [\"components.icon\"], fields: [\"content_models.icon\"], bound: \"DOCK_ICON_NAMES\", status: \"pending:C1-model-settings\" },\n \"document preview\": { row: \"A5\", carrier: \"value\", props: [\"components.preview\"], fields: [\"content_models.list_preview\"], status: \"pending:C3\" },\n \"document preview path\": { row: \"B catalog\", carrier: \"value\", props: [\"components.preview (path rule widened)\"], fields: [], status: \"pending:C3\" },\n \"kind:global\": { row: \"A6\", carrier: \"value\", props: [\"components.v2.shape\"], fields: [\"content_models.v2.shape\"], status: \"pending:C5\" },\n \"kind:entry (props)\": { row: \"A6\", carrier: \"value\", props: [\"components.v2.shape\"], fields: [], status: \"pending:C5\", foldedInto: \"kind:global\" },\n \"kind:block (fields)\": { row: \"A6\", carrier: \"value\", props: [], fields: [\"content_models.v2.shape\"], status: \"pending:C5\", foldedInto: \"kind:global\" },\n \"kind:page\": { row: \"A22\", carrier: \"value\", props: [], fields: [\"content_models.v2.shape\"], status: \"pending:C5\", foldedInto: \"kind:global\" },\n \"kind:object\": { row: \"A6\", carrier: \"value\", props: [], fields: [\"content_models.v2.shape\"], status: \"pending:C5\", foldedInto: \"kind:global\" },\n \"groups>3\": { row: \"A7\", carrier: \"value\", props: [\"components.tabs\"], fields: [\"content_models.fieldsets[kind:tab]\"], bound: \"TAB_MAX\", status: \"pending:C3+C8\" },\n \"item openMode\": {\n row: \"A8\",\n carrier: \"value\",\n props: [\"config.item.openMode (object item)\", \"config.itemTypes[i].openMode (polymorphic)\"],\n fields: [\"ui.blocks[slug].openMode (modular)\"],\n status: \"pending:C3\",\n },\n \"reference target\": { row: \"A9\", carrier: \"value\", props: [\"config.targets\"], fields: [\"config.targets\"], bound: \"REF_TARGET_KINDS\", status: \"landed\" },\n \"type:slot\": { row: \"A10\", carrier: \"value\", props: [\"props[] type slot (config.allow)\"], fields: [\"fields[] type slot (config.blockSlugs)\"], bound: \"SLOT_BLOCK_SLUGS_REQUIRED\", status: \"landed\" },\n \"block model field\": { row: \"A11\", carrier: \"value\", props: [], fields: [\"kind:'block' model fields[]\"], bound: \"BLOCK_FIELD_TYPES\", status: \"pending:G7\" },\n \"shopify reference\": { row: \"A12\", carrier: \"excluded\", props: [], fields: [], status: \"landed\" },\n \"type:table\": { row: \"A13\", carrier: \"value\", props: [\"props[] type table (config.mode data)\"], fields: [\"fields[] type table\"], status: \"landed\" },\n \"group (nested)\": { row: \"A14\", carrier: \"value\", props: [\"ui.tab {id}\"], fields: [\"ui.tab {id} (nested field)\"], bound: \"TAB_MAX\", status: \"landed\" },\n \"fieldset collision\": { row: \"A15\", carrier: \"value\", props: [\"ui.group {id}\"], fields: [\"fieldsetId\"], bound: \"TAB_FIELDSET_ID_UNIQUE\", status: \"landed\" },\n \"segmented fallback\": { row: \"A16\", carrier: \"value\", props: [\"ui.control segmented\"], fields: [\"ui.control segmented\"], bound: \"SEGMENTED_MAX\", status: \"pending:C3\" },\n \"fieldset (derived)\": { row: \"A17\", carrier: \"value\", props: [\"ui.group (prop group)\"], fields: [\"content_models.fieldsets\"], status: \"landed\" },\n \"itemNoun (derived)\": { row: \"A18\", carrier: \"value\", props: [\"ui.itemLabel\"], fields: [\"ui.itemTitle\"], status: \"landed\" },\n \"reference filter\": { row: \"A19\", carrier: \"value\", props: [\"config.filter\"], fields: [\"config.filter\"], bound: \"REFERENCE_FILTER_MAX\", status: \"landed\" },\n condition: { row: \"A20\", carrier: \"value\", props: [\"showIf (+ scope)\"], fields: [\"showIf (+ scope)\"], bound: \"SHOW_IF_SCOPES\", status: \"pending:C3\" },\n openMode: { row: \"A21\", carrier: \"value\", props: [\"props[].openMode\"], fields: [\"fields[].openMode\"], bound: \"OPEN_MODE_TYPES\", status: \"pending:C9\" },\n \"slot allow\": { row: \"A23\", carrier: \"value\", props: [\"config.allow\"], fields: [\"config.blockSlugs\"], bound: \"SLOT_ALLOW\", status: \"landed\" },\n\n /* ── B: in the code, not hit by the corpus ── */\n \"type:polymorphic-array\": { row: \"B structural\", carrier: \"value\", props: [\"props[] type table (config.mode types)\"], fields: [\"fields[] type modular\"], status: \"pending:C3\" },\n \"item chrome (types)\": { row: \"B structural\", carrier: \"value\", props: [\"config.itemTypes[i] {icon, preview}\"], fields: [\"ui.blocks[slug] {icon, preview}\"], status: \"pending:C3\" },\n \"type:primitive-array\": { row: \"B decided\", carrier: \"value\", props: [\"config.itemType (widened)\"], fields: [\"config.itemType (widened)\"], status: \"pending:C3\" },\n \"depth>10\": { row: \"B decided\", carrier: \"value\", props: [\"nesting\"], fields: [\"nesting\"], bound: \"DEPTH_MAX\", status: \"landed\" },\n slotSettings: { row: \"B decided (BUILD)\", carrier: \"value\", props: [\"config.settings: FieldDef[]\"], fields: [\"config.settings: FieldDef[]\"], bound: \"SLOT_SETTINGS_MAX\", status: \"pending:C3\" },\n \"block placement\": { row: \"B catalog\", carrier: \"value\", props: [\"components.v2.placement\"], fields: [\"content_models.v2.placement\"], status: \"pending:C5\" },\n \"seeded instance\": { row: \"B catalog\", carrier: \"excluded\", props: [], fields: [], status: \"landed\" },\n \"not applicable (props)\": { row: \"B catalog\", carrier: \"excluded\", props: [], fields: [], status: \"landed\" },\n \"type name\": corpusFix(\"components.slug\", \"content_models.slug\", \"SLUG_RE\"),\n \"group name>40\": corpusFix(\"components.tabs[].id\", \"content_models.fieldsets[].id\", \"TAB_NAME_MAX\"),\n \"group title\": corpusFix(\"components.tabs[].name\", \"content_models.fieldsets[].name\", \"TAB_TITLE\"),\n \"group default\": corpusFix(\"components.tabs[0]\", \"content_models.fieldsets[0]\", \"TAB_DEFAULT_FIRST\"),\n \"group icon\": corpusFix(\"components.tabs[].icon\", \"content_models.fieldsets[].icon\", \"DOCK_ICON_NAMES\"),\n \"group name collision\": corpusFix(\"components.tabs[].name\", \"content_models.fieldsets[].name\", \"TAB_NAME_UNIQUE\"),\n \"prop tab limit\": corpusFix(\"components.tabs\", \"content_models.fieldsets\", \"PROP_TAB_MAX\"),\n \"fieldset spans groups\": corpusFix(\"ui.group.tab\", \"fieldsets[].tab\", \"FIELDSET_ONE_TAB\"),\n \"fieldset (props)\": corpusFix(\"ui.group (first prop)\", \"content_models.fieldsets\", \"PROP_GROUP_DEFINED_ON_USE\"),\n \"fieldset name>limit\": corpusFix(\"ui.group.label\", \"content_models.fieldsets[].name\", \"FIELDSET_NAME_MAX\"),\n \"duplicate name\": corpusFix(\"props[].key\", \"fields[].key\", \"KEY_UNIQUE\"),\n \"reserved name\": { row: \"B corpus-fix\", carrier: \"value\", props: [], fields: [\"fields[].key\"], bound: \"KEY_RESERVED + KEY_FORMAT\", status: \"landed\" },\n rows: corpusFix(\"ui.rows\", \"ui.rows\", \"UI_ROWS_MAX\"),\n synced: corpusFix(\"ui.synced\", \"ui.synced\", \"SYNCED_FROM_MAX\"),\n valueShape: corpusFix(\"ui.valueShape\", \"ui.valueShape\", \"VALUE_SHAPE_TYPES\"),\n \"default value\": corpusFix(\"props[].defaultValue\", \"fields[].defaultValue\", \"VALUE_SCHEMAS\"),\n icon: corpusFix(\"ui.icon\", \"ui.icon\", \"DOCK_ICON_NAMES\"),\n layout: corpusFix(\"ui.control / ui.layout\", \"ui.control / ui.layout\", \"CONTROL_TYPES\"),\n \"help>limit\": corpusFix(\"helpText / placeholder / helpMore\", \"helpText / ui.placeholder / helpMore\", \"HELP_CAPS\"),\n \"option icon\": corpusFix(\"options[].icon\", \"options[].icon\", \"DOCK_ICON_NAMES\"),\n \"option description\": corpusFix(\"options[].description\", \"options[].description\", \"OPTION_DESCRIPTION_MAX\"),\n access: corpusFix(\"ui.access\", \"ui.access\", \"ACCESS_CAPS\"),\n timezone: corpusFix(\"config.timezone\", \"config.timezone\", \"TIMEZONE\"),\n \"reference order\": corpusFix(\"config.contentModelId|allowedModelSlugs, config.targets\", \"config.contentModelId|allowedModelSlugs, config.targets\", \"REFERENCE_TO_ORDER\"),\n \"numeric unit\": corpusFix(\"config.unit\", \"config.unit\", \"NUMBER_UNIT_MAX\"),\n \"rating bounds\": corpusFix(\"config.min/max/step (rating)\", \"config.min/max/step (rating)\", \"RATING_BOUNDS\"),\n \"scale rules\": corpusFix(\"config.scale\", \"config.scale\", \"SCALE_RULES\"),\n \"validation.patternMessage\": corpusFix(\"config.patternMessage\", \"config.patternMessage\", \"PATTERN_MESSAGE_MAX\"),\n \"validation.pattern\": corpusFix(\"config.pattern\", \"config.pattern\", \"PATTERN_MAX\"),\n \"validation.length\": corpusFix(\"config.minLength/maxLength\", \"config.minLength/maxLength\", \"LENGTH_TYPES\"),\n \"validation.items\": corpusFix(\"config.minItems/maxItems\", \"config.minItems/maxItems\", \"LIST_ITEMS_CAP\"),\n \"validation.unique\": corpusFix(\"props[].unique\", \"fields[].unique\", \"UNIQUE_TYPES\"),\n \"validation.recommendedMax\": corpusFix(\"props[].recommendedMax\", \"fields[].recommendedMax\", \"RECOMMENDED_MAX\"),\n \"item identity\": corpusFix(\"ui.itemName / ui.itemTitle\", \"ui.itemName / ui.itemTitle\", \"ITEM_NAME_RE\"),\n \"item settings\": corpusFix(\"config.item\", \"config.item\", \"ARRAY_ITEM_SETTINGS\"),\n itemNoun: corpusFix(\"ui.itemLabel\", \"ui.itemLabel\", \"ITEM_LABEL_MAX\"),\n \"item icon\": corpusFix(\"ui.icon (list)\", \"ui.icon (list)\", \"DOCK_ICON_NAMES\"),\n \"preview icon\": corpusFix(\"ui.preview.icon\", \"ui.preview.icon\", \"DOCK_ICON_NAMES\"),\n \"preview path\": corpusFix(\"ui.preview.{title,subtitle,media}\", \"ui.preview.{title,subtitle,media}\", \"PREVIEW_PATH\"),\n \"unsupported key\": corpusFix(\"—\", \"—\", \"V2_SCHEMA_KEYS\"),\n\n /* ── RT0 (kit-richtext-blocks-plan.md): a rich text's features, written as the full V2 set when V2 names none ── */\n \"richtext references\": { row: \"B RT8\", carrier: \"value\", props: [\"config.references\"], fields: [\"config.references\"], bound: \"REFERENCES_MODEL_ID\", status: \"landed\" },\n \"richtext features\": { row: \"B RT0\", carrier: \"value\", props: [\"config.features\"], fields: [\"config.features\"], bound: \"RICHTEXT_FEATURES\", status: \"landed\" },\n} as const satisfies Record<V2Facet, FacetRow>;\n\nexport const facetOf = (feature: string): FacetRow | undefined => (FACETS as Record<string, FacetRow>)[feature];\n\n/** The owner-signed exclusions: what may be lost by design (shopify until its pipeline, and two deliberate backend rules). */\nexport const EXCLUDED: readonly V2Facet[] = (Object.keys(FACETS) as V2Facet[]).filter((f) => FACETS[f].carrier === \"excluded\");\n"],"mappings":"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"}
|
package/dist/core/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { EXCLUDED, FACETS, OUT_OF_DOMAIN, facetOf } from "./facets.js";
|
|
2
|
-
import { CORE_VERSION, canonical, coreHash, coreJson, embedProd, embedV2, leafDiff, normProd, normV2, preserveOutOfDomain, roundTripCore } from "./core.js";
|
|
3
|
-
export { CORE_VERSION, EXCLUDED, FACETS, OUT_OF_DOMAIN, canonical, coreHash, coreJson, embedProd, embedV2, facetOf, leafDiff, normProd, normV2, preserveOutOfDomain, roundTripCore };
|
|
2
|
+
import { CORE_HASH_PREFIX, CORE_VERSION, canonical, coreHash, coreJson, embedProd, embedV2, leafDiff, normProd, normV2, preserveOutOfDomain, roundTripCore } from "./core.js";
|
|
3
|
+
export { CORE_HASH_PREFIX, CORE_VERSION, EXCLUDED, FACETS, OUT_OF_DOMAIN, canonical, coreHash, coreJson, embedProd, embedV2, facetOf, leafDiff, normProd, normV2, preserveOutOfDomain, roundTripCore };
|