@caelo-cms/shared 0.10.57 → 0.10.59
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 +30 -0
- package/dist/ai-tools.d.ts.map +1 -1
- package/dist/ai-tools.js +26 -9
- package/dist/ai-tools.js.map +1 -1
- package/dist/bug-intake.d.ts +176 -0
- package/dist/bug-intake.d.ts.map +1 -0
- package/dist/bug-intake.js +200 -0
- package/dist/bug-intake.js.map +1 -0
- package/dist/content.js +7 -7
- package/dist/edit-markers.d.ts +49 -0
- package/dist/edit-markers.d.ts.map +1 -0
- package/dist/edit-markers.js +225 -0
- package/dist/edit-markers.js.map +1 -0
- package/dist/google-oauth.d.ts +22 -0
- package/dist/google-oauth.d.ts.map +1 -0
- package/dist/google-oauth.js +25 -0
- package/dist/google-oauth.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/link-canonicalise.d.ts +109 -0
- package/dist/link-canonicalise.d.ts.map +1 -0
- package/dist/link-canonicalise.js +471 -0
- package/dist/link-canonicalise.js.map +1 -0
- package/dist/link-refs.d.ts +63 -8
- package/dist/link-refs.d.ts.map +1 -1
- package/dist/link-refs.js +80 -14
- package/dist/link-refs.js.map +1 -1
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +15 -0
- package/dist/media.js.map +1 -1
- package/dist/nested-module-render.d.ts +17 -0
- package/dist/nested-module-render.d.ts.map +1 -1
- package/dist/nested-module-render.js +45 -6
- package/dist/nested-module-render.js.map +1 -1
- package/dist/page-log.d.ts +1 -1
- package/dist/preview-compose.d.ts.map +1 -1
- package/dist/preview-compose.js +12 -2
- package/dist/preview-compose.js.map +1 -1
- package/dist/theme-normalize.d.ts.map +1 -1
- package/dist/theme-normalize.js +17 -2
- package/dist/theme-normalize.js.map +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/ai-tools.ts +29 -11
- package/src/bug-intake.test.ts +154 -0
- package/src/bug-intake.ts +256 -0
- package/src/content.ts +7 -7
- package/src/edit-markers.test.ts +111 -0
- package/src/edit-markers.ts +244 -0
- package/src/google-oauth.ts +27 -0
- package/src/index.ts +4 -0
- package/src/link-canonicalise.test.ts +387 -0
- package/src/link-canonicalise.ts +598 -0
- package/src/link-refs.test.ts +206 -0
- package/src/link-refs.ts +119 -21
- package/src/media.ts +16 -0
- package/src/nested-module-render.ts +59 -4
- package/src/preview-compose.ts +11 -2
- package/src/theme-normalize-typography-subfields.test.ts +54 -0
- package/src/theme-normalize.ts +19 -2
- package/src/version.ts +1 -1
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Write-time canonicalisation of internal links (epic #724, rollout C):
|
|
4
|
+
* the pure core. Authors — operators and the AI — keep writing `/about`,
|
|
5
|
+
* `https://<own domain>/about#team` or `/_caelo/media/hero`; this turns
|
|
6
|
+
* every such link into its stored reference (`caelo:page/<id>#team`,
|
|
7
|
+
* `caelo:media/<id>`) so renaming or moving the target changes no stored
|
|
8
|
+
* link. External URLs, `mailto:`, `tel:`, fragments, template
|
|
9
|
+
* placeholders and non-page files stay literal.
|
|
10
|
+
*
|
|
11
|
+
* Where a link can live, and what is looked at:
|
|
12
|
+
*
|
|
13
|
+
* - a WHOLE value that is a URL: `url` / `link` / `image` fields, any
|
|
14
|
+
* field or object key named `href` / `src` / `url` / `link` or ending
|
|
15
|
+
* in `_href` / `_url` / `_link` / `_src` (`primary_cta_href`), the
|
|
16
|
+
* `href` of `link-list` items and structured-set items (any depth);
|
|
17
|
+
* - HTML anywhere (module HTML, rich text, any string value carrying
|
|
18
|
+
* markup): `href` (pages and media), `src` / `poster` / `srcset`
|
|
19
|
+
* (media only — a `src="/x"` that is not media is not a page link).
|
|
20
|
+
*
|
|
21
|
+
* A plain text value is never canonicalised as a whole: "/month" in a
|
|
22
|
+
* price label is text, not a link.
|
|
23
|
+
*
|
|
24
|
+
* Failure policy (CLAUDE.md §2, §11): an internal path that matches no
|
|
25
|
+
* page, a media URL that matches no asset and a reference whose target
|
|
26
|
+
* is gone are collected as {@link LinkCanonicaliseIssue}s; the write op
|
|
27
|
+
* turns them into one AI-actionable error. Two exceptions keep editing
|
|
28
|
+
* possible around content that predates this rule:
|
|
29
|
+
*
|
|
30
|
+
* - grandfathering: a literal that was ALREADY in the stored value
|
|
31
|
+
* (pre-#724 content, rollout E migrates it) is left as it is — an
|
|
32
|
+
* edit must not introduce a broken link, but it need not fix an
|
|
33
|
+
* unrelated old one. The reference-integrity check (rollout F)
|
|
34
|
+
* reports those.
|
|
35
|
+
* - report mode: imports keep unresolved literals and report them
|
|
36
|
+
* (maintainer decision 3 on #724) instead of failing the import.
|
|
37
|
+
* - pending: while a chat rebuilds a site import, a link to a page of
|
|
38
|
+
* that run not built yet is kept and listed in `run.pending`; the
|
|
39
|
+
* caller records it and the run's finalisation converts it (or
|
|
40
|
+
* reports it) once the run's pages exist.
|
|
41
|
+
*/
|
|
42
|
+
import { findMalformedLinkRefs, formatLinkRef, LINK_REF_PART_PATTERNS, parseLinkRef, } from "./link-refs.js";
|
|
43
|
+
import { MEDIA_URL_PREFIX } from "./media.js";
|
|
44
|
+
/** Start a run. */
|
|
45
|
+
export function linkCanonicaliseRun(lookup, opts = {}) {
|
|
46
|
+
return {
|
|
47
|
+
lookup,
|
|
48
|
+
mode: opts.mode ?? "strict",
|
|
49
|
+
grandfathered: opts.grandfathered ?? new Set(),
|
|
50
|
+
issues: [],
|
|
51
|
+
pending: [],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// The reference grammar's own part patterns (link-refs.ts): a query,
|
|
55
|
+
// anchor or variant they accept always round-trips through
|
|
56
|
+
// `formatLinkRef`, and one they reject is an issue, never a throw (a
|
|
57
|
+
// thrown error would turn bad author input into a 500).
|
|
58
|
+
const QUERY_OK = LINK_REF_PART_PATTERNS.query;
|
|
59
|
+
const ANCHOR_OK = LINK_REF_PART_PATTERNS.anchor;
|
|
60
|
+
const VARIANT_RE = LINK_REF_PART_PATTERNS.variant;
|
|
61
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
62
|
+
const MEDIA_SEGMENT_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
63
|
+
// Text that starts like a reference. When the grammar rejects it, it is
|
|
64
|
+
// a broken reference, not some other URL (`malformed-link-ref`).
|
|
65
|
+
const REF_LIKE_RE = /^caelo:(?:page|media)\//;
|
|
66
|
+
// A last path segment with a file extension names a file, not a page —
|
|
67
|
+
// unless a page or an old-URL redirect answers it (`/about.html` an import
|
|
68
|
+
// redirected), which is checked first.
|
|
69
|
+
const FILE_EXT_RE = /\.[A-Za-z0-9]{1,8}$/;
|
|
70
|
+
// Files the static build itself serves at the site root; a link to one
|
|
71
|
+
// is a plain URL. Any other file path must come from the media library.
|
|
72
|
+
const SITE_SERVED_FILES = new Set(["/robots.txt", "/sitemap.xml"]);
|
|
73
|
+
/** Key / field names whose whole value is a URL. */
|
|
74
|
+
export function isLinkKeyName(name) {
|
|
75
|
+
const n = name.toLowerCase();
|
|
76
|
+
return (n === "href" ||
|
|
77
|
+
n === "src" ||
|
|
78
|
+
n === "url" ||
|
|
79
|
+
n === "link" ||
|
|
80
|
+
n.endsWith("_href") ||
|
|
81
|
+
n.endsWith("_url") ||
|
|
82
|
+
n.endsWith("_link") ||
|
|
83
|
+
n.endsWith("_src"));
|
|
84
|
+
}
|
|
85
|
+
/** Split `/a/b?q#h` into its parts (no URL parser: it must stay path-shaped). */
|
|
86
|
+
function splitPathTail(v) {
|
|
87
|
+
let rest = v;
|
|
88
|
+
let anchor = null;
|
|
89
|
+
const hash = rest.indexOf("#");
|
|
90
|
+
if (hash !== -1) {
|
|
91
|
+
anchor = rest.slice(hash + 1);
|
|
92
|
+
rest = rest.slice(0, hash);
|
|
93
|
+
}
|
|
94
|
+
let query = null;
|
|
95
|
+
const q = rest.indexOf("?");
|
|
96
|
+
if (q !== -1) {
|
|
97
|
+
query = rest.slice(q + 1);
|
|
98
|
+
rest = rest.slice(0, q);
|
|
99
|
+
}
|
|
100
|
+
return { path: rest, query: query === "" ? null : query, anchor: anchor === "" ? null : anchor };
|
|
101
|
+
}
|
|
102
|
+
/** `/a/b/` → `/a/b`; `/` stays `/`. Linear, no regex backtracking. */
|
|
103
|
+
export function normaliseLinkPath(path) {
|
|
104
|
+
let end = path.length;
|
|
105
|
+
while (end > 1 && path.charCodeAt(end - 1) === 47)
|
|
106
|
+
end -= 1;
|
|
107
|
+
return path.slice(0, end) || "/";
|
|
108
|
+
}
|
|
109
|
+
function issue(run, kind, value, where) {
|
|
110
|
+
run.issues.push({ kind, value, where });
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Record every malformed reference in `text` (HTML or a plain value).
|
|
114
|
+
* The render flags exactly these (`link-ref-malformed`, via the shared
|
|
115
|
+
* `findMalformedLinkRefs`), so a write that would ship one is refused up
|
|
116
|
+
* front. A snippet already recorded at the same position (the
|
|
117
|
+
* whole-value check in {@link canonicaliseUrl} saw it first) is not
|
|
118
|
+
* reported twice.
|
|
119
|
+
*/
|
|
120
|
+
function reportMalformedRefs(text, run, where) {
|
|
121
|
+
for (const raw of findMalformedLinkRefs(text)) {
|
|
122
|
+
if (run.grandfathered.has(raw))
|
|
123
|
+
continue;
|
|
124
|
+
const seen = run.issues.some((i) => i.kind === "malformed-link-ref" && i.where === where && i.value.startsWith(raw));
|
|
125
|
+
if (!seen)
|
|
126
|
+
issue(run, "malformed-link-ref", raw, where);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Canonicalise a `/_caelo/media/<slug>[/<variant>]` path, or null when it
|
|
131
|
+
* is not one.
|
|
132
|
+
*
|
|
133
|
+
* @param hasSuffix the link carries a `?query` or `#anchor`. A media
|
|
134
|
+
* reference cannot carry either (`caelo:media/<id>` has no suffix), so
|
|
135
|
+
* such a link is an `unsupported-link-form` issue instead of a
|
|
136
|
+
* reference that silently drops `#page=3`.
|
|
137
|
+
*/
|
|
138
|
+
function canonicaliseMediaPath(path, raw, hasSuffix, run, where) {
|
|
139
|
+
if (!path.startsWith(`${MEDIA_URL_PREFIX}/`))
|
|
140
|
+
return null;
|
|
141
|
+
const segs = path.slice(MEDIA_URL_PREFIX.length + 1).split("/");
|
|
142
|
+
const first = segs[0] ?? "";
|
|
143
|
+
const variant = segs[1] ?? null;
|
|
144
|
+
if (segs.length > 2 || !MEDIA_SEGMENT_RE.test(first) || (variant && !VARIANT_RE.test(variant))) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
// Legacy `/_caelo/media/<uuid>/<variant>` names the asset by id.
|
|
148
|
+
const id = UUID_RE.test(first) && variant ? first : run.lookup.mediaIdForSlug(first);
|
|
149
|
+
if (id === null || !run.lookup.mediaExists(id)) {
|
|
150
|
+
if (!run.grandfathered.has(raw))
|
|
151
|
+
issue(run, "unknown-media", raw, where);
|
|
152
|
+
return raw;
|
|
153
|
+
}
|
|
154
|
+
if (hasSuffix) {
|
|
155
|
+
if (!run.grandfathered.has(raw))
|
|
156
|
+
issue(run, "unsupported-link-form", raw, where);
|
|
157
|
+
return raw;
|
|
158
|
+
}
|
|
159
|
+
// `orig` is the original, which a reference expresses as no variant.
|
|
160
|
+
return formatLinkRef({
|
|
161
|
+
kind: "media",
|
|
162
|
+
mediaId: id,
|
|
163
|
+
variant: variant === "orig" ? null : variant,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Canonicalise one URL value. Returns the stored form: a reference, or
|
|
168
|
+
* the value unchanged (external, non-page, or an issue was recorded).
|
|
169
|
+
*
|
|
170
|
+
* @param scope `pages+media` for link positions (`href`, link fields);
|
|
171
|
+
* `media` for image positions (`src`, `srcset`, `poster`).
|
|
172
|
+
*/
|
|
173
|
+
export function canonicaliseUrl(value, run, where, scope = "pages+media") {
|
|
174
|
+
const v = value.trim();
|
|
175
|
+
if (v.length === 0 || v.includes("{{"))
|
|
176
|
+
return value;
|
|
177
|
+
const ref = parseLinkRef(v);
|
|
178
|
+
if (ref) {
|
|
179
|
+
if (!targetExists(ref, run.lookup) && !run.grandfathered.has(v)) {
|
|
180
|
+
issue(run, ref.kind === "page" ? "dangling-page-ref" : "dangling-media-ref", v, where);
|
|
181
|
+
}
|
|
182
|
+
return v;
|
|
183
|
+
}
|
|
184
|
+
// Starts like a reference but breaks the grammar (a truncated id,
|
|
185
|
+
// stray characters after it): passing it through would store a link
|
|
186
|
+
// no render resolves (CLAUDE.md §2).
|
|
187
|
+
if (REF_LIKE_RE.test(v)) {
|
|
188
|
+
if (!run.grandfathered.has(v))
|
|
189
|
+
issue(run, "malformed-link-ref", v, where);
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
let local;
|
|
193
|
+
if (/^https?:\/\//i.test(v)) {
|
|
194
|
+
let u;
|
|
195
|
+
try {
|
|
196
|
+
u = new URL(v);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return value;
|
|
200
|
+
}
|
|
201
|
+
if (!run.lookup.isOwnHost(u.host.toLowerCase()))
|
|
202
|
+
return value;
|
|
203
|
+
local = `${u.pathname}${u.search}${u.hash}`;
|
|
204
|
+
}
|
|
205
|
+
else if (v.startsWith("/") && !v.startsWith("//")) {
|
|
206
|
+
local = v;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
const { path, query, anchor } = splitPathTail(local);
|
|
212
|
+
const media = canonicaliseMediaPath(path, v, query !== null || anchor !== null, run, where);
|
|
213
|
+
if (media !== null)
|
|
214
|
+
return media;
|
|
215
|
+
if (scope === "media")
|
|
216
|
+
return value;
|
|
217
|
+
// Not a page: other reserved surfaces (`/_assets/…`, `/_caelo/fonts/…`)
|
|
218
|
+
// and the gateway (`/api/…`).
|
|
219
|
+
if (path.startsWith("/_") || path === "/api" || path.startsWith("/api/"))
|
|
220
|
+
return value;
|
|
221
|
+
const normalised = normaliseLinkPath(path);
|
|
222
|
+
const pageId = run.lookup.pageIdForPath(normalised);
|
|
223
|
+
if (pageId === null && run.lookup.isPendingPagePath?.(normalised)) {
|
|
224
|
+
// A page the import run will still build: kept as written and
|
|
225
|
+
// recorded by the caller; the run's finalisation converts it.
|
|
226
|
+
run.pending.push({ value: v, path: normalised, where });
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
if (pageId === null) {
|
|
230
|
+
const lastSegment = path.slice(path.lastIndexOf("/") + 1);
|
|
231
|
+
const isFile = FILE_EXT_RE.test(lastSegment);
|
|
232
|
+
if (isFile && SITE_SERVED_FILES.has(path))
|
|
233
|
+
return value;
|
|
234
|
+
if (!run.grandfathered.has(v))
|
|
235
|
+
issue(run, isFile ? "unknown-file" : "unknown-page-path", v, where);
|
|
236
|
+
return value;
|
|
237
|
+
}
|
|
238
|
+
if ((query !== null && !QUERY_OK.test(query)) || (anchor !== null && !ANCHOR_OK.test(anchor))) {
|
|
239
|
+
if (!run.grandfathered.has(v))
|
|
240
|
+
issue(run, "unsupported-link-form", v, where);
|
|
241
|
+
return value;
|
|
242
|
+
}
|
|
243
|
+
return formatLinkRef({ kind: "page", pageId, query, anchor });
|
|
244
|
+
}
|
|
245
|
+
function targetExists(ref, lookup) {
|
|
246
|
+
return ref.kind === "page" ? lookup.pageExists(ref.pageId) : lookup.mediaExists(ref.mediaId);
|
|
247
|
+
}
|
|
248
|
+
// Attribute scanner: `name="…"` / `name='…'` for the four link-bearing
|
|
249
|
+
// attributes. The value classes exclude their own quote, so each match
|
|
250
|
+
// is linear (no backtracking across attributes).
|
|
251
|
+
const ATTR_RE = /(\s(?:href|src|poster|srcset)\s*=\s*)(?:"([^"]*)"|'([^']*)')/gi;
|
|
252
|
+
/** Canonicalise the link-bearing attributes of an HTML fragment. */
|
|
253
|
+
export function canonicaliseHtmlLinks(html, run, where) {
|
|
254
|
+
if (!html.includes("=")) {
|
|
255
|
+
reportMalformedRefs(html, run, where);
|
|
256
|
+
return html;
|
|
257
|
+
}
|
|
258
|
+
// Attributes are only read inside a start tag, so escaped markup in a
|
|
259
|
+
// code sample (`<a href="/x">` is text, not a link) is left alone.
|
|
260
|
+
let out = "";
|
|
261
|
+
let from = 0;
|
|
262
|
+
for (const [start, end] of startTags(html)) {
|
|
263
|
+
out += html.slice(from, start) + canonicaliseTagAttributes(html.slice(start, end), run, where);
|
|
264
|
+
from = end;
|
|
265
|
+
}
|
|
266
|
+
// Broken references anywhere the render looks (any attribute, a srcset
|
|
267
|
+
// entry), not only in the four attributes canonicalised above.
|
|
268
|
+
reportMalformedRefs(html, run, where);
|
|
269
|
+
return from === 0 ? html : out + html.slice(from);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* `[start, end)` of every start tag (`<` + letter … `>`), quoted values
|
|
273
|
+
* allowed to contain `>`. One linear pass; an unterminated quote runs to
|
|
274
|
+
* the end of the input instead of being rescanned.
|
|
275
|
+
*/
|
|
276
|
+
function* startTags(html) {
|
|
277
|
+
let i = html.indexOf("<");
|
|
278
|
+
while (i !== -1 && i < html.length - 1) {
|
|
279
|
+
const c = html.charCodeAt(i + 1);
|
|
280
|
+
const isLetter = (c >= 65 && c <= 90) || (c >= 97 && c <= 122);
|
|
281
|
+
if (!isLetter) {
|
|
282
|
+
i = html.indexOf("<", i + 1);
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
let j = i + 2;
|
|
286
|
+
let quote = 0;
|
|
287
|
+
while (j < html.length) {
|
|
288
|
+
const ch = html.charCodeAt(j);
|
|
289
|
+
if (quote !== 0) {
|
|
290
|
+
if (ch === quote)
|
|
291
|
+
quote = 0;
|
|
292
|
+
}
|
|
293
|
+
else if (ch === 34 || ch === 39) {
|
|
294
|
+
quote = ch;
|
|
295
|
+
}
|
|
296
|
+
else if (ch === 62) {
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
j += 1;
|
|
300
|
+
}
|
|
301
|
+
const end = Math.min(j + 1, html.length);
|
|
302
|
+
yield [i, end];
|
|
303
|
+
i = html.indexOf("<", end);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function canonicaliseTagAttributes(tag, run, where) {
|
|
307
|
+
return tag.replace(ATTR_RE, (whole, prefix, dq, sq) => {
|
|
308
|
+
const quote = dq !== undefined ? '"' : "'";
|
|
309
|
+
const raw = (dq ?? sq);
|
|
310
|
+
const attr = prefix
|
|
311
|
+
.trim()
|
|
312
|
+
.replace(/\s*=\s*$/, "")
|
|
313
|
+
.toLowerCase();
|
|
314
|
+
let next;
|
|
315
|
+
if (attr === "href")
|
|
316
|
+
next = canonicaliseUrl(raw, run, where, "pages+media");
|
|
317
|
+
else if (attr === "srcset")
|
|
318
|
+
next = canonicaliseSrcset(raw, run, where);
|
|
319
|
+
else
|
|
320
|
+
next = canonicaliseUrl(raw, run, where, "media");
|
|
321
|
+
return next === raw ? whole : `${prefix}${quote}${next}${quote}`;
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/** `url 400w, url 800w` — each candidate URL is a media position. */
|
|
325
|
+
function canonicaliseSrcset(srcset, run, where) {
|
|
326
|
+
return srcset
|
|
327
|
+
.split(",")
|
|
328
|
+
.map((entry) => {
|
|
329
|
+
const lead = entry.length - entry.trimStart().length;
|
|
330
|
+
const body = entry.slice(lead);
|
|
331
|
+
const sp = body.search(/\s/);
|
|
332
|
+
const url = sp === -1 ? body : body.slice(0, sp);
|
|
333
|
+
const rest = sp === -1 ? "" : body.slice(sp);
|
|
334
|
+
const next = canonicaliseUrl(url, run, where, "media");
|
|
335
|
+
return `${entry.slice(0, lead)}${next}${rest}`;
|
|
336
|
+
})
|
|
337
|
+
.join(",");
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Canonicalise any JSON value: whole-value URLs where the key says so
|
|
341
|
+
* (`asUrl`), HTML attributes in every string, recursing through arrays
|
|
342
|
+
* and objects (object keys decide per {@link isLinkKeyName}).
|
|
343
|
+
*/
|
|
344
|
+
export function canonicaliseJsonLinks(value, run, where, asUrl = false) {
|
|
345
|
+
if (typeof value === "string") {
|
|
346
|
+
if (asUrl)
|
|
347
|
+
return canonicaliseUrl(value, run, where);
|
|
348
|
+
if (value.includes("<"))
|
|
349
|
+
return canonicaliseHtmlLinks(value, run, where);
|
|
350
|
+
// A text value is never a link as a whole, but one that starts like a
|
|
351
|
+
// reference and breaks the grammar renders as a dead `caelo:` href
|
|
352
|
+
// wherever a module puts it in an attribute.
|
|
353
|
+
reportMalformedRefs(value, run, where);
|
|
354
|
+
return value;
|
|
355
|
+
}
|
|
356
|
+
if (Array.isArray(value)) {
|
|
357
|
+
let changed = false;
|
|
358
|
+
const next = value.map((v, i) => {
|
|
359
|
+
const r = canonicaliseJsonLinks(v, run, `${where}[${i}]`, asUrl);
|
|
360
|
+
if (r !== v)
|
|
361
|
+
changed = true;
|
|
362
|
+
return r;
|
|
363
|
+
});
|
|
364
|
+
return changed ? next : value;
|
|
365
|
+
}
|
|
366
|
+
if (value !== null && typeof value === "object") {
|
|
367
|
+
let changed = false;
|
|
368
|
+
const out = {};
|
|
369
|
+
for (const [k, v] of Object.entries(value)) {
|
|
370
|
+
const r = canonicaliseJsonLinks(v, run, `${where}.${k}`, isLinkKeyName(k));
|
|
371
|
+
if (r !== v)
|
|
372
|
+
changed = true;
|
|
373
|
+
out[k] = r;
|
|
374
|
+
}
|
|
375
|
+
return changed ? out : value;
|
|
376
|
+
}
|
|
377
|
+
return value;
|
|
378
|
+
}
|
|
379
|
+
/** Field kinds whose whole value is a URL. */
|
|
380
|
+
const URL_KINDS = new Set(["url", "link", "image"]);
|
|
381
|
+
/** Field kinds that hold nested-module refs, never links. */
|
|
382
|
+
const NESTED_KINDS = new Set(["module", "module-list"]);
|
|
383
|
+
function canonicaliseFieldValue(field, name, value, run, where) {
|
|
384
|
+
if (field && NESTED_KINDS.has(field.kind))
|
|
385
|
+
return value;
|
|
386
|
+
const asUrl = (field !== undefined && URL_KINDS.has(field.kind)) || isLinkKeyName(name);
|
|
387
|
+
return canonicaliseJsonLinks(value, run, where, asUrl);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Canonicalise a content instance's values against its module's fields.
|
|
391
|
+
* Values without a declared field are still scanned (key-name rule +
|
|
392
|
+
* HTML) — a stale value renders nowhere today but may again tomorrow.
|
|
393
|
+
*/
|
|
394
|
+
export function canonicaliseContentValues(fields, values, run) {
|
|
395
|
+
const byName = new Map(fields.map((f) => [f.name, f]));
|
|
396
|
+
const out = {};
|
|
397
|
+
for (const [k, v] of Object.entries(values)) {
|
|
398
|
+
out[k] = canonicaliseFieldValue(byName.get(k), k, v, run, `values.${k}`);
|
|
399
|
+
}
|
|
400
|
+
return out;
|
|
401
|
+
}
|
|
402
|
+
/** Canonicalise every field's `default` (layout chrome content lives there). */
|
|
403
|
+
export function canonicaliseFieldDefaults(fields, run) {
|
|
404
|
+
return fields.map((f) => {
|
|
405
|
+
if (f.default === undefined || f.default === null)
|
|
406
|
+
return f;
|
|
407
|
+
const next = canonicaliseFieldValue(f, f.name, f.default, run, `fields.${f.name}.default`);
|
|
408
|
+
return next === f.default ? f : { ...f, default: next };
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Every link literal inside a stored state (values, defaults, set items,
|
|
413
|
+
* module HTML) — the {@link LinkCanonicaliseRun.grandfathered} set of the
|
|
414
|
+
* next write. Collected with a lookup that knows nothing, so every
|
|
415
|
+
* candidate surfaces as an "issue" carrying its raw value.
|
|
416
|
+
*/
|
|
417
|
+
export function collectLinkLiterals(state) {
|
|
418
|
+
const run = linkCanonicaliseRun(NOTHING_RESOLVES, { mode: "report" });
|
|
419
|
+
canonicaliseJsonLinks(state, run, "", false);
|
|
420
|
+
// Whole-value positions are only known with field context; strings
|
|
421
|
+
// that look like a link are therefore also taken verbatim.
|
|
422
|
+
const out = new Set(run.issues.map((i) => i.value));
|
|
423
|
+
collectStrings(state, out);
|
|
424
|
+
return out;
|
|
425
|
+
}
|
|
426
|
+
function collectStrings(value, out) {
|
|
427
|
+
if (typeof value === "string") {
|
|
428
|
+
const v = value.trim();
|
|
429
|
+
if (v.startsWith("/") || v.startsWith("caelo:") || /^https?:\/\//i.test(v))
|
|
430
|
+
out.add(v);
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
if (Array.isArray(value))
|
|
434
|
+
for (const v of value)
|
|
435
|
+
collectStrings(v, out);
|
|
436
|
+
else if (value !== null && typeof value === "object") {
|
|
437
|
+
for (const v of Object.values(value))
|
|
438
|
+
collectStrings(v, out);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
const NOTHING_RESOLVES = {
|
|
442
|
+
pageIdForPath: () => null,
|
|
443
|
+
mediaIdForSlug: () => null,
|
|
444
|
+
pageExists: () => false,
|
|
445
|
+
mediaExists: () => false,
|
|
446
|
+
isOwnHost: () => true,
|
|
447
|
+
};
|
|
448
|
+
const ISSUE_TEXT = {
|
|
449
|
+
"unknown-page-path": "is not the path of any page on this site",
|
|
450
|
+
"unknown-media": "names no image or file in the media library",
|
|
451
|
+
"dangling-page-ref": "links to a page that was deleted",
|
|
452
|
+
"dangling-media-ref": "links to an image or file that was deleted",
|
|
453
|
+
"unknown-file": "is a file path nothing on this site serves (files are served from the media library: upload it, then link its media URL from find_media)",
|
|
454
|
+
"unsupported-link-form": "has a query or #anchor a stored link cannot carry (page links allow plain query/anchor characters only; media links allow neither)",
|
|
455
|
+
"malformed-link-ref": "starts like an internal reference (caelo:page/ or caelo:media/) but is broken, e.g. a truncated id or extra characters after it; write the page's path (/about#team) or the media URL (/_caelo/media/<slug>) instead, never a caelo: reference",
|
|
456
|
+
};
|
|
457
|
+
/**
|
|
458
|
+
* One AI-actionable message for a refused write (CLAUDE.md §11): what is
|
|
459
|
+
* wrong with each link and the next step. Paths only — the author never
|
|
460
|
+
* sees reference ids except for a reference that is already broken.
|
|
461
|
+
*/
|
|
462
|
+
export function describeLinkIssues(issues) {
|
|
463
|
+
const lines = issues.slice(0, 10).map((i) => `${i.where}: "${i.value}" ${ISSUE_TEXT[i.kind]}`);
|
|
464
|
+
const more = issues.length > 10 ? ` (and ${issues.length - 10} more)` : "";
|
|
465
|
+
return (`Internal link check failed — ${lines.join("; ")}${more}. ` +
|
|
466
|
+
"Internal links must point at an existing page or media asset. Next step: use the exact path " +
|
|
467
|
+
"of an existing page (list_pages shows every page's path) or an existing media URL (find_media); " +
|
|
468
|
+
"if the page does not exist yet, create it first (or leave the link out and add it once the page " +
|
|
469
|
+
"exists). For a link to another site, write the full https:// URL.");
|
|
470
|
+
}
|
|
471
|
+
//# sourceMappingURL=link-canonicalise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-canonicalise.js","sourceRoot":"","sources":["../src/link-canonicalise.ts"],"names":[],"mappings":"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"}
|
package/dist/link-refs.d.ts
CHANGED
|
@@ -31,6 +31,18 @@ export type LinkRef = PageLinkRef | MediaLinkRef;
|
|
|
31
31
|
* grammar is left alone.
|
|
32
32
|
*/
|
|
33
33
|
export declare const LINK_REF_MALFORMED = "link-ref-malformed";
|
|
34
|
+
/**
|
|
35
|
+
* Whole-string tests for the query, anchor and media-variant parts of a
|
|
36
|
+
* reference — built from the grammar's own sources, so a writer that
|
|
37
|
+
* validates author input with them (write-time canonicalisation, #724
|
|
38
|
+
* rollout C) accepts exactly what {@link formatLinkRef} accepts and a bad
|
|
39
|
+
* suffix is a validation issue, never a thrown error.
|
|
40
|
+
*/
|
|
41
|
+
export declare const LINK_REF_PART_PATTERNS: Readonly<{
|
|
42
|
+
query: RegExp;
|
|
43
|
+
anchor: RegExp;
|
|
44
|
+
variant: RegExp;
|
|
45
|
+
}>;
|
|
34
46
|
/**
|
|
35
47
|
* Parse a string that IS exactly one reference (a whole field value).
|
|
36
48
|
* Returns null for anything else — a path, an external URL, or a string
|
|
@@ -98,15 +110,28 @@ export type LinkResolution =
|
|
|
98
110
|
/**
|
|
99
111
|
* The target exists but is not published, so a deploy build will not
|
|
100
112
|
* contain it. Rendered with its URL; the caller applies the
|
|
101
|
-
* environment's policy ({@link linkIssueSeverity}).
|
|
113
|
+
* environment's policy ({@link linkIssueSeverity}). `pageId` is the
|
|
114
|
+
* page the URL points at — the referenced page, or its sibling in the
|
|
115
|
+
* rendering page's variant.
|
|
102
116
|
*/
|
|
103
117
|
| {
|
|
104
118
|
readonly status: "unpublished";
|
|
105
119
|
readonly url: string;
|
|
120
|
+
readonly pageId: string;
|
|
106
121
|
}
|
|
107
122
|
/** No live target (never existed, deleted, another chat's branch). */
|
|
108
123
|
| {
|
|
109
124
|
readonly status: "missing";
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The target exists, but has no sibling in the rendering page's
|
|
128
|
+
* variant (a German page linking to a page that has no German
|
|
129
|
+
* version). Not rendered — linking into another variant instead is
|
|
130
|
+
* exactly the silent fallback CLAUDE.md §2 forbids.
|
|
131
|
+
*/
|
|
132
|
+
| {
|
|
133
|
+
readonly status: "no-variant";
|
|
134
|
+
readonly variant: string;
|
|
110
135
|
};
|
|
111
136
|
/**
|
|
112
137
|
* Turns references into URLs for ONE rendering page. Synchronous: the
|
|
@@ -139,8 +164,17 @@ export declare const LINK_TARGET_MISSING = "link-target-missing";
|
|
|
139
164
|
*/
|
|
140
165
|
export declare const LINK_RESOLVER_UNAVAILABLE = "link-resolver-unavailable";
|
|
141
166
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
167
|
+
* `missingSlots` marker for a page reference whose target has no sibling
|
|
168
|
+
* in the rendering page's variant:
|
|
169
|
+
* `link-variant-missing:page/<targetId>:<variant>` (variant = the
|
|
170
|
+
* rendering page's, e.g. a locale code). Blocks a deploy like a missing
|
|
171
|
+
* target.
|
|
172
|
+
*/
|
|
173
|
+
export declare const LINK_VARIANT_MISSING = "link-variant-missing";
|
|
174
|
+
/**
|
|
175
|
+
* True for every link failure marker: a missing target, a target with
|
|
176
|
+
* no version in the rendering page's variant, a malformed reference and
|
|
177
|
+
* a render without a resolver. The static generator's
|
|
144
178
|
* render gate and the nested-module echo filter both key on this, so a
|
|
145
179
|
* new marker added here blocks a deploy everywhere at once.
|
|
146
180
|
*/
|
|
@@ -165,7 +199,9 @@ export declare function resolveLinkRefsInHtml(html: string, resolver: LinkResolv
|
|
|
165
199
|
* cleanly (maintainer decision on #724): a missing target blocks
|
|
166
200
|
* everywhere; an unpublished one is a warning at Stage and blocks
|
|
167
201
|
* Publish live / promote. The editor preview shows drafts, so nothing
|
|
168
|
-
* there is an issue beyond a missing target.
|
|
202
|
+
* there is an issue beyond a missing target. A target without a sibling
|
|
203
|
+
* in the rendering page's variant counts as missing: there is no page
|
|
204
|
+
* the link could go to.
|
|
169
205
|
*/
|
|
170
206
|
export declare function linkIssueSeverity(env: LinkRenderEnv, status: LinkResolution["status"]): "block" | "warning" | null;
|
|
171
207
|
/** A page as the link index needs it. */
|
|
@@ -185,6 +221,16 @@ export interface LinkIndexMedia {
|
|
|
185
221
|
/** `media_assets.slug` — the URL the editor serves and the build rewrites. */
|
|
186
222
|
readonly slug: string;
|
|
187
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* One page's place in a plugin's page-variant partition (the
|
|
226
|
+
* `link-resolve` composition point): its `variant` (international-site:
|
|
227
|
+
* the locale code) and the `group` of pages that are versions of each
|
|
228
|
+
* other (null = the page has no versions besides itself).
|
|
229
|
+
*/
|
|
230
|
+
export interface LinkPageVariant {
|
|
231
|
+
readonly variant: string;
|
|
232
|
+
readonly group: string | null;
|
|
233
|
+
}
|
|
188
234
|
/** What a render-wide link index is built from. */
|
|
189
235
|
export interface SiteLinkIndexInput {
|
|
190
236
|
/** Every live (non-deleted) page visible to the render's scope, drafts included. */
|
|
@@ -198,6 +244,14 @@ export interface SiteLinkIndexInput {
|
|
|
198
244
|
* internal link, and byte-identical with the canonical (#590).
|
|
199
245
|
*/
|
|
200
246
|
readonly pageUrlStyle: PageUrlStyle;
|
|
247
|
+
/**
|
|
248
|
+
* The `link-resolve` composition point's answer: page id → its variant
|
|
249
|
+
* and variant group. Absent or empty = no plugin partitions the site,
|
|
250
|
+
* every page reference resolves to the referenced page. A page missing
|
|
251
|
+
* from a non-empty map is one no plugin has an opinion about: links
|
|
252
|
+
* FROM it resolve as referenced, and a link TO it is not remapped.
|
|
253
|
+
*/
|
|
254
|
+
readonly pageVariants?: ReadonlyMap<string, LinkPageVariant>;
|
|
201
255
|
}
|
|
202
256
|
/**
|
|
203
257
|
* The render-wide lookup tables, from which a per-page resolver is cut.
|
|
@@ -206,10 +260,11 @@ export interface SiteLinkIndexInput {
|
|
|
206
260
|
export interface SiteLinkIndex {
|
|
207
261
|
readonly env: LinkRenderEnv;
|
|
208
262
|
/**
|
|
209
|
-
* The resolver for rendering page `renderingPageId
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
* Each call returns a fresh
|
|
263
|
+
* The resolver for rendering page `renderingPageId`: page references
|
|
264
|
+
* resolve to the target's sibling in the rendering page's variant
|
|
265
|
+
* ({@link SiteLinkIndexInput.pageVariants}); null = a render outside
|
|
266
|
+
* any page, which maps nothing. Each call returns a fresh
|
|
267
|
+
* {@link RecordingLinkResolver}.
|
|
213
268
|
*/
|
|
214
269
|
forPage(renderingPageId: string | null): RecordingLinkResolver;
|
|
215
270
|
/** The page's public path (no style applied), or null when unknown. */
|
package/dist/link-refs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-refs.d.ts","sourceRoot":"","sources":["../src/link-refs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"link-refs.d.ts","sourceRoot":"","sources":["../src/link-refs.ts"],"names":[],"mappings":"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"}
|