@caelo-cms/shared 0.10.72 → 0.11.1
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/ai-tools.d.ts +103 -142
- package/dist/ai-tools.d.ts.map +1 -1
- package/dist/ai-tools.js +79 -167
- package/dist/ai-tools.js.map +1 -1
- package/dist/build-page.d.ts +115 -35
- package/dist/build-page.d.ts.map +1 -1
- package/dist/build-page.js +31 -12
- package/dist/build-page.js.map +1 -1
- package/dist/content.d.ts +214 -102
- package/dist/content.d.ts.map +1 -1
- package/dist/content.js +219 -84
- package/dist/content.js.map +1 -1
- package/dist/css-scope-scan.js +1 -1
- package/dist/css-var-aliases.d.ts +20 -0
- package/dist/css-var-aliases.d.ts.map +1 -0
- package/dist/css-var-aliases.js +95 -0
- package/dist/css-var-aliases.js.map +1 -0
- package/dist/css-var-scan.d.ts +0 -16
- package/dist/css-var-scan.d.ts.map +1 -1
- package/dist/css-var-scan.js +24 -0
- package/dist/css-var-scan.js.map +1 -1
- package/dist/edit-markers.d.ts +41 -5
- package/dist/edit-markers.d.ts.map +1 -1
- package/dist/edit-markers.js +47 -50
- package/dist/edit-markers.js.map +1 -1
- package/dist/escaped-line-breaks.d.ts +44 -0
- package/dist/escaped-line-breaks.d.ts.map +1 -0
- package/dist/escaped-line-breaks.js +203 -0
- package/dist/escaped-line-breaks.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/interactions.js +6 -6
- package/dist/interactions.js.map +1 -1
- package/dist/link-canonicalise.d.ts.map +1 -1
- package/dist/link-canonicalise.js +7 -1
- package/dist/link-canonicalise.js.map +1 -1
- package/dist/link-refs.d.ts +1 -1
- package/dist/link-refs.js +3 -3
- package/dist/lists/address.d.ts +34 -0
- package/dist/lists/address.d.ts.map +1 -0
- package/dist/lists/address.js +43 -0
- package/dist/lists/address.js.map +1 -0
- package/dist/lists/default-types.d.ts +22 -0
- package/dist/lists/default-types.d.ts.map +1 -0
- package/dist/lists/default-types.js +127 -0
- package/dist/lists/default-types.js.map +1 -0
- package/dist/lists/fields.d.ts +152 -0
- package/dist/lists/fields.d.ts.map +1 -0
- package/dist/lists/fields.js +259 -0
- package/dist/lists/fields.js.map +1 -0
- package/dist/lists/index.d.ts +14 -0
- package/dist/lists/index.d.ts.map +1 -0
- package/dist/lists/index.js +15 -0
- package/dist/lists/index.js.map +1 -0
- package/dist/lists/item-attr.d.ts +26 -0
- package/dist/lists/item-attr.d.ts.map +1 -0
- package/dist/lists/item-attr.js +31 -0
- package/dist/lists/item-attr.js.map +1 -0
- package/dist/lists/items.d.ts +105 -0
- package/dist/lists/items.d.ts.map +1 -0
- package/dist/lists/items.js +304 -0
- package/dist/lists/items.js.map +1 -0
- package/dist/lists/list-type.d.ts +401 -0
- package/dist/lists/list-type.d.ts.map +1 -0
- package/dist/lists/list-type.js +275 -0
- package/dist/lists/list-type.js.map +1 -0
- package/dist/lists/model.d.ts +14 -0
- package/dist/lists/model.d.ts.map +1 -0
- package/dist/lists/model.js +15 -0
- package/dist/lists/model.js.map +1 -0
- package/dist/lists/page-type.d.ts +115 -0
- package/dist/lists/page-type.d.ts.map +1 -0
- package/dist/lists/page-type.js +66 -0
- package/dist/lists/page-type.js.map +1 -0
- package/dist/lists/refs.d.ts +13 -0
- package/dist/lists/refs.d.ts.map +1 -0
- package/dist/lists/refs.js +18 -0
- package/dist/lists/refs.js.map +1 -0
- package/dist/lists/render-data.d.ts +123 -0
- package/dist/lists/render-data.d.ts.map +1 -0
- package/dist/lists/render-data.js +3 -0
- package/dist/lists/render-data.js.map +1 -0
- package/dist/lists/render-deps.d.ts +69 -0
- package/dist/lists/render-deps.d.ts.map +1 -0
- package/dist/lists/render-deps.js +93 -0
- package/dist/lists/render-deps.js.map +1 -0
- package/dist/lists/resolve-values.d.ts +63 -0
- package/dist/lists/resolve-values.d.ts.map +1 -0
- package/dist/lists/resolve-values.js +181 -0
- package/dist/lists/resolve-values.js.map +1 -0
- package/dist/lists/resolve.d.ts +119 -0
- package/dist/lists/resolve.d.ts.map +1 -0
- package/dist/lists/resolve.js +970 -0
- package/dist/lists/resolve.js.map +1 -0
- package/dist/lists/scope.d.ts +81 -0
- package/dist/lists/scope.d.ts.map +1 -0
- package/dist/lists/scope.js +3 -0
- package/dist/lists/scope.js.map +1 -0
- package/dist/markup-structure.d.ts +8 -0
- package/dist/markup-structure.d.ts.map +1 -1
- package/dist/markup-structure.js +2 -0
- package/dist/markup-structure.js.map +1 -1
- package/dist/media.d.ts +1 -1
- package/dist/nested-module-render.d.ts +38 -20
- package/dist/nested-module-render.d.ts.map +1 -1
- package/dist/nested-module-render.js +156 -31
- package/dist/nested-module-render.js.map +1 -1
- package/dist/page-log.d.ts +1 -1
- package/dist/preview-compose.d.ts +24 -21
- package/dist/preview-compose.d.ts.map +1 -1
- package/dist/preview-compose.js +34 -118
- package/dist/preview-compose.js.map +1 -1
- package/dist/redirect-plan.d.ts +13 -0
- package/dist/redirect-plan.d.ts.map +1 -1
- package/dist/redirect-plan.js +22 -0
- package/dist/redirect-plan.js.map +1 -1
- package/dist/seo.d.ts +21 -0
- package/dist/seo.d.ts.map +1 -1
- package/dist/seo.js +32 -0
- package/dist/seo.js.map +1 -1
- package/dist/source-text-transport.d.ts +43 -0
- package/dist/source-text-transport.d.ts.map +1 -0
- package/dist/source-text-transport.js +79 -0
- package/dist/source-text-transport.js.map +1 -0
- package/dist/template-engine.d.ts +44 -31
- package/dist/template-engine.d.ts.map +1 -1
- package/dist/template-engine.js +75 -174
- package/dist/template-engine.js.map +1 -1
- package/dist/template-sections.d.ts +69 -0
- package/dist/template-sections.d.ts.map +1 -0
- package/dist/template-sections.js +436 -0
- package/dist/template-sections.js.map +1 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +8 -1
- package/src/__tests__/redos-hardening.test.ts +51 -16
- package/src/ai-tools-add-module-modes.test.ts +51 -1
- package/src/ai-tools.test.ts +7 -10
- package/src/ai-tools.ts +90 -180
- package/src/bug-intake.test.ts +1 -1
- package/src/build-page.test.ts +34 -3
- package/src/build-page.ts +34 -11
- package/src/content.test.ts +137 -4
- package/src/content.ts +230 -85
- package/src/css-scope-scan.ts +1 -1
- package/src/css-var-aliases.test.ts +61 -0
- package/src/css-var-aliases.ts +109 -0
- package/src/css-var-scan.ts +9 -0
- package/src/edit-markers.test.ts +37 -21
- package/src/edit-markers.ts +52 -20
- package/src/escaped-line-breaks.ts +221 -0
- package/src/index.ts +4 -1
- package/src/interactions.ts +6 -6
- package/src/link-canonicalise.test.ts +36 -6
- package/src/link-canonicalise.ts +6 -1
- package/src/link-refs.test.ts +67 -42
- package/src/link-refs.ts +3 -3
- package/src/lists/address.ts +75 -0
- package/src/lists/default-types.ts +141 -0
- package/src/lists/fields.ts +286 -0
- package/src/lists/index.ts +16 -0
- package/src/lists/item-attr.test.ts +36 -0
- package/src/lists/item-attr.ts +49 -0
- package/src/lists/items.ts +402 -0
- package/src/lists/list-fixtures.test.ts +308 -0
- package/src/lists/list-type.ts +306 -0
- package/src/lists/lists.test.ts +328 -0
- package/src/lists/model.ts +16 -0
- package/src/lists/page-type.ts +71 -0
- package/src/lists/refs.ts +21 -0
- package/src/lists/render-data.ts +134 -0
- package/src/lists/render-deps.test.ts +132 -0
- package/src/lists/render-deps.ts +147 -0
- package/src/lists/resolve-values.ts +224 -0
- package/src/lists/resolve.test.ts +472 -0
- package/src/lists/resolve.ts +1246 -0
- package/src/lists/scope.ts +69 -0
- package/src/lists-compose-parity.test.ts +262 -0
- package/src/markup-structure.ts +10 -0
- package/src/nested-module-render.test.ts +147 -74
- package/src/nested-module-render.ts +120 -48
- package/src/preview-compose.test.ts +55 -19
- package/src/preview-compose.ts +59 -154
- package/src/redirect-plan.test.ts +25 -0
- package/src/redirect-plan.ts +24 -0
- package/src/seo.test.ts +58 -0
- package/src/seo.ts +49 -0
- package/src/source-text-transport.test.ts +158 -0
- package/src/source-text-transport.ts +81 -0
- package/src/template-engine-lists.test.ts +608 -0
- package/src/template-engine.test.ts +62 -80
- package/src/template-engine.ts +102 -245
- package/src/template-sections.ts +514 -0
- package/src/version.ts +1 -1
- package/dist/structured-sets.d.ts +0 -70
- package/dist/structured-sets.d.ts.map +0 -1
- package/dist/structured-sets.js +0 -92
- package/dist/structured-sets.js.map +0 -1
- package/src/structured-sets.ts +0 -114
- package/src/template-engine-data-lists.test.ts +0 -90
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
import { describe, expect, it } from "bun:test";
|
|
14
14
|
import { fontFamilySlug, parseFontsCss } from "../fonts.js";
|
|
15
|
+
import { DEFAULT_LIST_TYPES } from "../lists/default-types.js";
|
|
16
|
+
import { createListRenderContext } from "../lists/resolve.js";
|
|
15
17
|
import { renderTemplate } from "../template-engine.js";
|
|
16
18
|
import { stripCssComments } from "../theme-importers/css-comments.js";
|
|
17
19
|
import { trimSlashes, trimTrailingSlashes } from "../url.js";
|
|
@@ -59,36 +61,69 @@ describe("stripCssComments (S4)", () => {
|
|
|
59
61
|
});
|
|
60
62
|
});
|
|
61
63
|
|
|
62
|
-
describe("renderTemplate
|
|
64
|
+
describe("renderTemplate sections (S4, epic #1107 tokenizer)", () => {
|
|
65
|
+
const lists = createListRenderContext({
|
|
66
|
+
listTypes: new Map(DEFAULT_LIST_TYPES.map((t) => [t.slug, { id: t.slug, def: t }])),
|
|
67
|
+
lists: new Map(),
|
|
68
|
+
pageTypes: new Map(),
|
|
69
|
+
pages: new Map(),
|
|
70
|
+
media: new Map(),
|
|
71
|
+
siteLanguage: "en",
|
|
72
|
+
homePageId: null,
|
|
73
|
+
}).forPage(null);
|
|
74
|
+
const navField = { name: "nav_items", kind: "list" as const, listType: "links" };
|
|
75
|
+
const entry = (n: number, label: string, href: string) => ({
|
|
76
|
+
id: `00000000-0000-4000-9000-${String(n).padStart(12, "0")}`,
|
|
77
|
+
node: "link",
|
|
78
|
+
values: { label, link: { href } },
|
|
79
|
+
});
|
|
80
|
+
|
|
63
81
|
it("scans a large closed section body linearly (no quadratic backtracking)", () => {
|
|
64
|
-
// A closed section with a 100k-char literal body
|
|
65
|
-
//
|
|
66
|
-
// the polynomial shape this guards against.
|
|
82
|
+
// A closed section with a 100k-char literal body: the section pass
|
|
83
|
+
// tokenizes once and pairs tags with a stack, no regex over the body.
|
|
67
84
|
const big = "x".repeat(100_000);
|
|
68
|
-
const html = `<nav>{{#nav_items}}${big}<a href="{{
|
|
85
|
+
const html = `<nav>{{#nav_items}}${big}<a href="{{link}}">{{label}}</a>{{/nav_items}}</nav>`;
|
|
69
86
|
expect(
|
|
70
87
|
underBudget(() =>
|
|
71
88
|
renderTemplate({
|
|
72
89
|
html,
|
|
73
|
-
fields: [
|
|
74
|
-
contentValues: { nav_items: [
|
|
90
|
+
fields: [navField],
|
|
91
|
+
contentValues: { nav_items: [entry(1, "Docs", "/docs")] },
|
|
92
|
+
lists,
|
|
75
93
|
}),
|
|
76
94
|
),
|
|
77
95
|
).toBeLessThan(BUDGET_MS);
|
|
78
96
|
});
|
|
79
97
|
|
|
98
|
+
it("thousands of unclosed sections cost one pass, not one scan each", () => {
|
|
99
|
+
// Unclosed opens stay unpaired (the later Mustache pass reports them);
|
|
100
|
+
// pairing must not rescan the rest of the document per open.
|
|
101
|
+
const html = "{{#a}}".repeat(5_000) + "x".repeat(50_000);
|
|
102
|
+
expect(
|
|
103
|
+
underBudget(() => {
|
|
104
|
+
try {
|
|
105
|
+
renderTemplate({
|
|
106
|
+
html,
|
|
107
|
+
fields: [{ name: "a", kind: "text" }],
|
|
108
|
+
contentValues: { a: "1" },
|
|
109
|
+
});
|
|
110
|
+
} catch {
|
|
111
|
+
// Mustache refuses the unclosed sections; only the cost matters here.
|
|
112
|
+
}
|
|
113
|
+
}),
|
|
114
|
+
).toBeLessThan(BUDGET_MS);
|
|
115
|
+
});
|
|
116
|
+
|
|
80
117
|
it("still iterates a closed section the same way", () => {
|
|
81
118
|
const out = renderTemplate({
|
|
82
|
-
html: '<nav>{{#nav_items}}<a href="{{
|
|
83
|
-
fields: [
|
|
84
|
-
contentValues: {
|
|
85
|
-
|
|
86
|
-
{ label: "Docs", href: "/docs" },
|
|
87
|
-
{ label: "Blog", href: "/blog" },
|
|
88
|
-
],
|
|
89
|
-
},
|
|
119
|
+
html: '<nav>{{#nav_items}}<a href="{{link}}">{{label}}</a>{{/nav_items}}</nav>',
|
|
120
|
+
fields: [navField],
|
|
121
|
+
contentValues: { nav_items: [entry(1, "Docs", "/docs"), entry(2, "Blog", "/blog")] },
|
|
122
|
+
lists,
|
|
90
123
|
});
|
|
91
|
-
expect(out.html
|
|
124
|
+
expect(out.html.replace(/ data-caelo-list-item="[^"]*"/g, "")).toBe(
|
|
125
|
+
'<nav><a href="/docs">Docs</a><a href="/blog">Blog</a></nav>',
|
|
126
|
+
);
|
|
92
127
|
});
|
|
93
128
|
});
|
|
94
129
|
|
|
@@ -71,7 +71,7 @@ describe("addModuleToolInput modes (issue #159)", () => {
|
|
|
71
71
|
it("TOLERATES a moduleId call carrying authoring keys (incl. structural html) — placement-only, handler surfaces the ignored-authoring info", () => {
|
|
72
72
|
// §1A/§11 — a valid placement must never fail over an extra authoring
|
|
73
73
|
// field. moduleId + html passes; the tool handler (not the schema)
|
|
74
|
-
// reports that html was not applied and points at
|
|
74
|
+
// reports that html was not applied and points at update_modules_many.
|
|
75
75
|
const r = addModuleToolInput.safeParse({
|
|
76
76
|
...BASE,
|
|
77
77
|
moduleId: "11111111-1111-4111-8111-111111111102",
|
|
@@ -104,3 +104,53 @@ describe("addModuleToolInput modes (issue #159)", () => {
|
|
|
104
104
|
expect(r.success).toBe(false);
|
|
105
105
|
});
|
|
106
106
|
});
|
|
107
|
+
|
|
108
|
+
describe("addModuleToolInput — list fields carry their own content (PR #1121 e2e)", () => {
|
|
109
|
+
const LIST = "caelo:list/22222222-2222-4222-8222-222222222222";
|
|
110
|
+
const footer = (fields: unknown[]) =>
|
|
111
|
+
addModuleToolInput.safeParse({
|
|
112
|
+
...BASE,
|
|
113
|
+
target: "layout" as const,
|
|
114
|
+
targetRef: "site-default",
|
|
115
|
+
blockName: "footer",
|
|
116
|
+
displayName: "Footer",
|
|
117
|
+
html: '<nav>{{#footer_links}}<a href="{{link}}">{{label}}</a>{{/footer_links}}</nav>',
|
|
118
|
+
fields,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("accepts a footer bound to a shared list without values or defaults", () => {
|
|
122
|
+
const r = footer([
|
|
123
|
+
{
|
|
124
|
+
name: "footer_links",
|
|
125
|
+
kind: "list",
|
|
126
|
+
label: "Links",
|
|
127
|
+
listType: "menu",
|
|
128
|
+
bind: "shared",
|
|
129
|
+
list: LIST,
|
|
130
|
+
},
|
|
131
|
+
]);
|
|
132
|
+
expect(r.success).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("accepts a list fed by a source", () => {
|
|
136
|
+
const r = footer([
|
|
137
|
+
{
|
|
138
|
+
name: "footer_links",
|
|
139
|
+
kind: "list",
|
|
140
|
+
label: "Crumbs",
|
|
141
|
+
listType: "links",
|
|
142
|
+
bind: "source",
|
|
143
|
+
source: { kind: "system", name: "breadcrumbs" },
|
|
144
|
+
},
|
|
145
|
+
]);
|
|
146
|
+
expect(r.success).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("still refuses a shared list field with no list and no value, naming the list route", () => {
|
|
150
|
+
const r = footer([
|
|
151
|
+
{ name: "footer_links", kind: "list", label: "Links", listType: "menu", bind: "shared" },
|
|
152
|
+
]);
|
|
153
|
+
expect(r.success).toBe(false);
|
|
154
|
+
expect(r.error?.issues[0]?.message).toContain("upsert_lists_many");
|
|
155
|
+
});
|
|
156
|
+
});
|
package/src/ai-tools.test.ts
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MPL-2.0
|
|
2
2
|
|
|
3
3
|
import { describe, expect, it } from "bun:test";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
chatSendMessageInput,
|
|
7
|
-
editModuleToolInput,
|
|
8
|
-
siteMemoryProposeToolInput,
|
|
9
|
-
} from "./ai-tools.js";
|
|
4
|
+
import { chatPublishInput, chatSendMessageInput, siteMemoryProposeToolInput } from "./ai-tools.js";
|
|
5
|
+
import { moduleUpdateSchema } from "./content.js";
|
|
10
6
|
|
|
11
7
|
const UUID = "11111111-1111-4111-8111-111111111111";
|
|
12
8
|
const UUID_2 = "22222222-2222-4222-8222-222222222222";
|
|
13
9
|
|
|
14
|
-
|
|
10
|
+
// The per-item shape of update_modules_many (the module-edit tool extends it).
|
|
11
|
+
describe("moduleUpdateSchema (update_modules_many item)", () => {
|
|
15
12
|
it("accepts a minimal valid edit", () => {
|
|
16
|
-
const r =
|
|
13
|
+
const r = moduleUpdateSchema.safeParse({ moduleId: UUID, html: "<p>x</p>" });
|
|
17
14
|
expect(r.success).toBe(true);
|
|
18
15
|
});
|
|
19
16
|
|
|
20
17
|
it("rejects unknown keys (.strict)", () => {
|
|
21
|
-
const r =
|
|
18
|
+
const r = moduleUpdateSchema.safeParse({
|
|
22
19
|
moduleId: UUID,
|
|
23
20
|
html: "<p>x</p>",
|
|
24
21
|
pageId: UUID_2,
|
|
@@ -27,7 +24,7 @@ describe("editModuleToolInput", () => {
|
|
|
27
24
|
});
|
|
28
25
|
|
|
29
26
|
it("rejects oversized html", () => {
|
|
30
|
-
const r =
|
|
27
|
+
const r = moduleUpdateSchema.safeParse({
|
|
31
28
|
moduleId: UUID,
|
|
32
29
|
html: "x".repeat(300_000),
|
|
33
30
|
});
|