@407dev/cms-astro 0.1.0
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/README.md +69 -0
- package/dist/chunk-2TKIQIOE.js +118 -0
- package/dist/chunk-2TKIQIOE.js.map +1 -0
- package/dist/chunk-53OQ5RXJ.js +912 -0
- package/dist/chunk-53OQ5RXJ.js.map +1 -0
- package/dist/chunk-56OMNQLH.js +1013 -0
- package/dist/chunk-56OMNQLH.js.map +1 -0
- package/dist/chunk-5AOOMQ7K.js +1031 -0
- package/dist/chunk-5AOOMQ7K.js.map +1 -0
- package/dist/chunk-5XRUCFDC.js +743 -0
- package/dist/chunk-5XRUCFDC.js.map +1 -0
- package/dist/chunk-62ZHCOLZ.js +25 -0
- package/dist/chunk-62ZHCOLZ.js.map +1 -0
- package/dist/chunk-6AZLRSYA.js +126 -0
- package/dist/chunk-6AZLRSYA.js.map +1 -0
- package/dist/chunk-6L3ZTCFB.js +14 -0
- package/dist/chunk-6L3ZTCFB.js.map +1 -0
- package/dist/chunk-6O7ZNNDT.js +697 -0
- package/dist/chunk-6O7ZNNDT.js.map +1 -0
- package/dist/chunk-6PQIXTMK.js +697 -0
- package/dist/chunk-6PQIXTMK.js.map +1 -0
- package/dist/chunk-7AW6M7QW.js +1013 -0
- package/dist/chunk-7AW6M7QW.js.map +1 -0
- package/dist/chunk-7E3XJLKX.js +73 -0
- package/dist/chunk-7E3XJLKX.js.map +1 -0
- package/dist/chunk-7LM54OTA.js +1031 -0
- package/dist/chunk-7LM54OTA.js.map +1 -0
- package/dist/chunk-7LMUFCWX.js +126 -0
- package/dist/chunk-7LMUFCWX.js.map +1 -0
- package/dist/chunk-A3OGL4OX.js +706 -0
- package/dist/chunk-A3OGL4OX.js.map +1 -0
- package/dist/chunk-AO4UAWOV.js +1030 -0
- package/dist/chunk-AO4UAWOV.js.map +1 -0
- package/dist/chunk-B4YYLS7Y.js +14 -0
- package/dist/chunk-B4YYLS7Y.js.map +1 -0
- package/dist/chunk-BDFVGXM2.js +697 -0
- package/dist/chunk-BDFVGXM2.js.map +1 -0
- package/dist/chunk-CXM7NZVX.js +1031 -0
- package/dist/chunk-CXM7NZVX.js.map +1 -0
- package/dist/chunk-DMLOBKYE.js +96 -0
- package/dist/chunk-DMLOBKYE.js.map +1 -0
- package/dist/chunk-DXJSYGS6.js +743 -0
- package/dist/chunk-DXJSYGS6.js.map +1 -0
- package/dist/chunk-EFUSAQZM.js +72 -0
- package/dist/chunk-EFUSAQZM.js.map +1 -0
- package/dist/chunk-F7KDGPBN.js +1013 -0
- package/dist/chunk-F7KDGPBN.js.map +1 -0
- package/dist/chunk-FBSQT45X.js +126 -0
- package/dist/chunk-FBSQT45X.js.map +1 -0
- package/dist/chunk-FEPDOMVH.js +697 -0
- package/dist/chunk-FEPDOMVH.js.map +1 -0
- package/dist/chunk-FQDOL2QW.js +25 -0
- package/dist/chunk-FQDOL2QW.js.map +1 -0
- package/dist/chunk-GB3LGQJM.js +109 -0
- package/dist/chunk-GB3LGQJM.js.map +1 -0
- package/dist/chunk-HCNP6R3P.js +736 -0
- package/dist/chunk-HCNP6R3P.js.map +1 -0
- package/dist/chunk-J6WEJDRI.js +743 -0
- package/dist/chunk-J6WEJDRI.js.map +1 -0
- package/dist/chunk-JHEAPNJ2.js +117 -0
- package/dist/chunk-JHEAPNJ2.js.map +1 -0
- package/dist/chunk-JOJDJ6GW.js +25 -0
- package/dist/chunk-JOJDJ6GW.js.map +1 -0
- package/dist/chunk-KTDV6WYB.js +202 -0
- package/dist/chunk-KTDV6WYB.js.map +1 -0
- package/dist/chunk-KZWJBKPC.js +734 -0
- package/dist/chunk-KZWJBKPC.js.map +1 -0
- package/dist/chunk-LEAQBGL6.js +109 -0
- package/dist/chunk-LEAQBGL6.js.map +1 -0
- package/dist/chunk-LGZJL2Q7.js +697 -0
- package/dist/chunk-LGZJL2Q7.js.map +1 -0
- package/dist/chunk-LQPBU46R.js +109 -0
- package/dist/chunk-LQPBU46R.js.map +1 -0
- package/dist/chunk-M55NNUTY.js +1013 -0
- package/dist/chunk-M55NNUTY.js.map +1 -0
- package/dist/chunk-M6NCYCC3.js +1013 -0
- package/dist/chunk-M6NCYCC3.js.map +1 -0
- package/dist/chunk-MGN7OZAU.js +109 -0
- package/dist/chunk-MGN7OZAU.js.map +1 -0
- package/dist/chunk-MGYZOX4K.js +1013 -0
- package/dist/chunk-MGYZOX4K.js.map +1 -0
- package/dist/chunk-MY4IEKJS.js +1031 -0
- package/dist/chunk-MY4IEKJS.js.map +1 -0
- package/dist/chunk-NCQRGAB4.js +705 -0
- package/dist/chunk-NCQRGAB4.js.map +1 -0
- package/dist/chunk-NI4NHXI4.js +697 -0
- package/dist/chunk-NI4NHXI4.js.map +1 -0
- package/dist/chunk-NPI5N7AU.js +14 -0
- package/dist/chunk-NPI5N7AU.js.map +1 -0
- package/dist/chunk-QN4CPMJF.js +126 -0
- package/dist/chunk-QN4CPMJF.js.map +1 -0
- package/dist/chunk-QYUVAKMC.js +1013 -0
- package/dist/chunk-QYUVAKMC.js.map +1 -0
- package/dist/chunk-RAAT6PDT.js +25 -0
- package/dist/chunk-RAAT6PDT.js.map +1 -0
- package/dist/chunk-RDPO5VPS.js +1013 -0
- package/dist/chunk-RDPO5VPS.js.map +1 -0
- package/dist/chunk-RQHIW2PF.js +25 -0
- package/dist/chunk-RQHIW2PF.js.map +1 -0
- package/dist/chunk-RREVHA52.js +722 -0
- package/dist/chunk-RREVHA52.js.map +1 -0
- package/dist/chunk-S7PT4PZN.js +25 -0
- package/dist/chunk-S7PT4PZN.js.map +1 -0
- package/dist/chunk-SUXV5M32.js +109 -0
- package/dist/chunk-SUXV5M32.js.map +1 -0
- package/dist/chunk-SZEORUY6.js +696 -0
- package/dist/chunk-SZEORUY6.js.map +1 -0
- package/dist/chunk-T7NGGWGY.js +25 -0
- package/dist/chunk-T7NGGWGY.js.map +1 -0
- package/dist/chunk-UEVWP5VE.js +696 -0
- package/dist/chunk-UEVWP5VE.js.map +1 -0
- package/dist/chunk-UJNKNP7U.js +748 -0
- package/dist/chunk-UJNKNP7U.js.map +1 -0
- package/dist/chunk-V4XVFWFI.js +1013 -0
- package/dist/chunk-V4XVFWFI.js.map +1 -0
- package/dist/chunk-VJU2CIKZ.js +729 -0
- package/dist/chunk-VJU2CIKZ.js.map +1 -0
- package/dist/chunk-VRQUP5L3.js +202 -0
- package/dist/chunk-VRQUP5L3.js.map +1 -0
- package/dist/chunk-WBJ5E7CL.js +742 -0
- package/dist/chunk-WBJ5E7CL.js.map +1 -0
- package/dist/chunk-XJPVYMZM.js +24 -0
- package/dist/chunk-XJPVYMZM.js.map +1 -0
- package/dist/chunk-Y3Q65C7R.js +14 -0
- package/dist/chunk-Y3Q65C7R.js.map +1 -0
- package/dist/chunk-YHEGFPTR.js +1030 -0
- package/dist/chunk-YHEGFPTR.js.map +1 -0
- package/dist/chunk-ZDLBN46C.js +697 -0
- package/dist/chunk-ZDLBN46C.js.map +1 -0
- package/dist/dev/index.d.ts +122 -0
- package/dist/dev/index.js +662 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/fields/collections.d.ts +18 -0
- package/dist/fields/collections.js +37 -0
- package/dist/fields/collections.js.map +1 -0
- package/dist/index.d.ts +235 -0
- package/dist/index.js +956 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/index.d.ts +8 -0
- package/dist/middleware/index.js +13 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/preview-BEkLMD6N.d.ts +23 -0
- package/dist/preview-D9yewK8x.d.ts +24 -0
- package/dist/preview-DJEA4fj7.d.ts +23 -0
- package/dist/preview-DeD1Jn7U.d.ts +23 -0
- package/dist/toolbar/app.d.ts +28 -0
- package/dist/toolbar/app.js +1176 -0
- package/dist/toolbar/app.js.map +1 -0
- package/dist/types-15jfCQKb.d.ts +141 -0
- package/dist/types-BREdL9Gx.d.ts +140 -0
- package/dist/types-C6sUZNa2.d.ts +104 -0
- package/dist/types-CEYS5Fzc.d.ts +112 -0
- package/dist/types-DpeHpobR.d.ts +104 -0
- package/dist/types-NaKJe6Pg.d.ts +140 -0
- package/package.json +90 -0
- package/src/CmsHead.astro +25 -0
- package/src/CmsImage.astro +62 -0
- package/src/CmsVideo.astro +185 -0
- package/src/RichText.astro +32 -0
- package/src/client.test.ts +227 -0
- package/src/client.ts +164 -0
- package/src/dev/config.test.ts +258 -0
- package/src/dev/config.ts +319 -0
- package/src/dev/index.ts +5 -0
- package/src/dev/preview-token.ts +39 -0
- package/src/dev/routes.test.ts +354 -0
- package/src/dev/routes.ts +245 -0
- package/src/dev/token.test.ts +280 -0
- package/src/dev/token.ts +201 -0
- package/src/dev/verifier.test.ts +63 -0
- package/src/dev/verifier.ts +161 -0
- package/src/fields/attrs.ts +24 -0
- package/src/fields/collection.ts +72 -0
- package/src/fields/collections.ts +35 -0
- package/src/fields/entryScope.test.ts +62 -0
- package/src/fields/entryScope.ts +240 -0
- package/src/fields/group.ts +51 -0
- package/src/fields/helpers.test.ts +51 -0
- package/src/fields/helpers.ts +214 -0
- package/src/fields/index.ts +46 -0
- package/src/fields/scope.ts +21 -0
- package/src/fields/types.ts +119 -0
- package/src/head.test.ts +74 -0
- package/src/head.ts +123 -0
- package/src/image.test.ts +42 -0
- package/src/image.ts +64 -0
- package/src/index.test.ts +76 -0
- package/src/index.ts +13 -0
- package/src/integration.ts +218 -0
- package/src/jwt.ts +131 -0
- package/src/middleware/index.ts +4 -0
- package/src/middleware/preview.test.ts +184 -0
- package/src/middleware/preview.ts +206 -0
- package/src/preview/bridge-script.test.ts +683 -0
- package/src/preview/bridge-script.ts +763 -0
- package/src/preview/origins.ts +29 -0
- package/src/preview.ts +49 -0
- package/src/richtext/RichTextNode.astro +130 -0
- package/src/richtext/render.ts +248 -0
- package/src/richtext.test.ts +139 -0
- package/src/runtime/bundle.ts +28 -0
- package/src/runtime/store.ts +130 -0
- package/src/siteFiles.test.ts +93 -0
- package/src/siteFiles.ts +111 -0
- package/src/toolbar/app.test.ts +191 -0
- package/src/toolbar/app.ts +1091 -0
- package/src/toolbar/icon.ts +5 -0
- package/src/toolbar/widgets.test.ts +153 -0
- package/src/toolbar/widgets.ts +365 -0
- package/src/types.test.ts +154 -0
- package/src/types.ts +163 -0
- package/src/version.ts +3 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,956 @@
|
|
|
1
|
+
import { mintDevPreviewToken } from './chunk-7LMUFCWX.js';
|
|
2
|
+
export { signPreviewToken, verifyPreviewToken } from './chunk-7LMUFCWX.js';
|
|
3
|
+
import { collectionPaths, defineCollection, getEntry, getEntries, markBundleReady } from './chunk-7E3XJLKX.js';
|
|
4
|
+
export { bundleReady, collectionPaths, defineCollection, getEntries, getEntry, isBundleReady, markBundleReady } from './chunk-7E3XJLKX.js';
|
|
5
|
+
import { initCmsClient, buildBridgeScript, getClient } from './chunk-QYUVAKMC.js';
|
|
6
|
+
export { createCmsClient, createPreviewMiddleware, getClient, initCmsClient, setClient } from './chunk-QYUVAKMC.js';
|
|
7
|
+
import './chunk-B4YYLS7Y.js';
|
|
8
|
+
import { getActiveBundle, recordMissingField, getMissingFieldWarnings, clearMissingFieldWarnings } from './chunk-DMLOBKYE.js';
|
|
9
|
+
export { clearMissingFieldWarnings, getActiveBundle, getBuildBundle, getMissingFieldWarnings, isDraftMode, recordMissingField, runWithDraftBundle, setActiveDraftBundle, setBuildBundle, updateBundleFieldValue } from './chunk-DMLOBKYE.js';
|
|
10
|
+
import './chunk-2TKIQIOE.js';
|
|
11
|
+
export { DEFAULT_EDITOR_ORIGINS, resolveEditorOrigins } from './chunk-XJPVYMZM.js';
|
|
12
|
+
import { listFieldTypes, getFieldType, isValidLinkHref } from '@407dev/field-types';
|
|
13
|
+
import { createComponent, spreadAttributes, renderTemplate, markHTMLString } from 'astro/runtime/server/index.js';
|
|
14
|
+
export { z } from '@407dev/blocks';
|
|
15
|
+
import fs from 'fs';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
import { fileURLToPath } from 'url';
|
|
18
|
+
|
|
19
|
+
function escapeHtml(str) {
|
|
20
|
+
if (typeof str !== "string") return "";
|
|
21
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
22
|
+
}
|
|
23
|
+
var KNOWN_NODES = /* @__PURE__ */ new Set([
|
|
24
|
+
"doc",
|
|
25
|
+
"paragraph",
|
|
26
|
+
"heading",
|
|
27
|
+
"bulletList",
|
|
28
|
+
"orderedList",
|
|
29
|
+
"listItem",
|
|
30
|
+
"blockquote",
|
|
31
|
+
"codeBlock",
|
|
32
|
+
"hardBreak",
|
|
33
|
+
"horizontalRule",
|
|
34
|
+
"text",
|
|
35
|
+
"image"
|
|
36
|
+
]);
|
|
37
|
+
var KNOWN_MARKS = /* @__PURE__ */ new Set(["bold", "italic", "underline", "strike", "code", "link"]);
|
|
38
|
+
function parseRichTextDoc(value) {
|
|
39
|
+
if (!value) return null;
|
|
40
|
+
let parsed = value;
|
|
41
|
+
if (typeof value === "string") {
|
|
42
|
+
try {
|
|
43
|
+
parsed = JSON.parse(value);
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
49
|
+
const root = parsed;
|
|
50
|
+
if (root.type !== "doc" && !Array.isArray(root.content)) return null;
|
|
51
|
+
return root;
|
|
52
|
+
}
|
|
53
|
+
function renderMarksOnly(text, marks) {
|
|
54
|
+
let out = escapeHtml(text || "");
|
|
55
|
+
if (!Array.isArray(marks)) return out;
|
|
56
|
+
for (const mark of marks) {
|
|
57
|
+
if (!mark || typeof mark !== "object" || mark.type === "link" || !KNOWN_MARKS.has(mark.type)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (mark.type === "bold") out = `<strong>${out}</strong>`;
|
|
61
|
+
else if (mark.type === "italic") out = `<em>${out}</em>`;
|
|
62
|
+
else if (mark.type === "underline") out = `<u>${out}</u>`;
|
|
63
|
+
else if (mark.type === "strike") out = `<s>${out}</s>`;
|
|
64
|
+
else if (mark.type === "code") out = `<code>${out}</code>`;
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
function getLinkMarkAttrs(marks) {
|
|
69
|
+
if (!Array.isArray(marks)) return null;
|
|
70
|
+
const linkMark = marks.find((m) => m && typeof m === "object" && m.type === "link");
|
|
71
|
+
if (!linkMark) return null;
|
|
72
|
+
const rawHref = linkMark.attrs?.href;
|
|
73
|
+
if (typeof rawHref !== "string" || !isValidLinkHref(rawHref)) return null;
|
|
74
|
+
const target = typeof linkMark.attrs?.target === "string" ? linkMark.attrs.target : void 0;
|
|
75
|
+
const rel = typeof linkMark.attrs?.rel === "string" ? linkMark.attrs.rel : target === "_blank" ? "noopener noreferrer" : void 0;
|
|
76
|
+
const title = typeof linkMark.attrs?.title === "string" ? linkMark.attrs.title : void 0;
|
|
77
|
+
return { href: rawHref, target, rel, title };
|
|
78
|
+
}
|
|
79
|
+
function renderRichTextHtml(doc, options = {}) {
|
|
80
|
+
if (!doc) return "";
|
|
81
|
+
let parsedDoc = doc;
|
|
82
|
+
if (typeof doc === "string") {
|
|
83
|
+
try {
|
|
84
|
+
parsedDoc = JSON.parse(doc);
|
|
85
|
+
} catch {
|
|
86
|
+
return `<p>${escapeHtml(doc)}</p>`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (typeof parsedDoc !== "object" || parsedDoc === null) {
|
|
90
|
+
return "";
|
|
91
|
+
}
|
|
92
|
+
const root = parsedDoc;
|
|
93
|
+
if (root.type !== "doc" && !Array.isArray(root.content)) {
|
|
94
|
+
return "";
|
|
95
|
+
}
|
|
96
|
+
const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
97
|
+
const maxDepth = options.maxDepth ?? 50;
|
|
98
|
+
function renderNode(node, depth = 0) {
|
|
99
|
+
if (depth > maxDepth) return "";
|
|
100
|
+
if (!node || typeof node !== "object") return "";
|
|
101
|
+
const n = node;
|
|
102
|
+
const nodeType = n.type || "";
|
|
103
|
+
if (!KNOWN_NODES.has(nodeType)) {
|
|
104
|
+
if (isDev) {
|
|
105
|
+
console.warn(`[RichText] Skipped unknown node type: "${nodeType}"`);
|
|
106
|
+
}
|
|
107
|
+
return "";
|
|
108
|
+
}
|
|
109
|
+
if (nodeType === "text") {
|
|
110
|
+
let text = escapeHtml(n.text || "");
|
|
111
|
+
if (Array.isArray(n.marks)) {
|
|
112
|
+
for (const mark of n.marks) {
|
|
113
|
+
if (!mark || typeof mark !== "object") continue;
|
|
114
|
+
const markType = mark.type;
|
|
115
|
+
if (!KNOWN_MARKS.has(markType)) {
|
|
116
|
+
if (isDev) {
|
|
117
|
+
console.warn(`[RichText] Skipped unknown mark type: "${markType}"`);
|
|
118
|
+
}
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (markType === "bold") {
|
|
122
|
+
text = `<strong>${text}</strong>`;
|
|
123
|
+
} else if (markType === "italic") {
|
|
124
|
+
text = `<em>${text}</em>`;
|
|
125
|
+
} else if (markType === "underline") {
|
|
126
|
+
text = `<u>${text}</u>`;
|
|
127
|
+
} else if (markType === "strike") {
|
|
128
|
+
text = `<s>${text}</s>`;
|
|
129
|
+
} else if (markType === "code") {
|
|
130
|
+
text = `<code>${text}</code>`;
|
|
131
|
+
} else if (markType === "link") {
|
|
132
|
+
const rawHref = mark.attrs?.href;
|
|
133
|
+
if (typeof rawHref === "string" && isValidLinkHref(rawHref)) {
|
|
134
|
+
const href = escapeHtml(rawHref);
|
|
135
|
+
const target = typeof mark.attrs?.target === "string" ? ` target="${escapeHtml(mark.attrs.target)}"` : "";
|
|
136
|
+
const rel = typeof mark.attrs?.rel === "string" ? ` rel="${escapeHtml(mark.attrs.rel)}"` : target.includes("_blank") ? ' rel="noopener noreferrer"' : "";
|
|
137
|
+
text = `<a href="${href}"${target}${rel}>${text}</a>`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return text;
|
|
143
|
+
}
|
|
144
|
+
const children = Array.isArray(n.content) ? n.content.map((c) => renderNode(c, depth + 1)).join("") : "";
|
|
145
|
+
switch (nodeType) {
|
|
146
|
+
case "doc":
|
|
147
|
+
return children;
|
|
148
|
+
case "paragraph":
|
|
149
|
+
return `<p>${children}</p>`;
|
|
150
|
+
case "heading": {
|
|
151
|
+
const rawLevel = n.attrs?.level;
|
|
152
|
+
const level = typeof rawLevel === "number" && rawLevel >= 1 && rawLevel <= 6 ? rawLevel : 2;
|
|
153
|
+
return `<h${level}>${children}</h${level}>`;
|
|
154
|
+
}
|
|
155
|
+
case "bulletList":
|
|
156
|
+
return `<ul>${children}</ul>`;
|
|
157
|
+
case "orderedList": {
|
|
158
|
+
const start = n.attrs?.start || n.attrs?.order;
|
|
159
|
+
const startAttr = typeof start === "number" && start !== 1 ? ` start="${start}"` : "";
|
|
160
|
+
return `<ol${startAttr}>${children}</ol>`;
|
|
161
|
+
}
|
|
162
|
+
case "listItem":
|
|
163
|
+
return `<li>${children}</li>`;
|
|
164
|
+
case "blockquote":
|
|
165
|
+
return `<blockquote>${children}</blockquote>`;
|
|
166
|
+
case "codeBlock": {
|
|
167
|
+
const lang = typeof n.attrs?.language === "string" ? ` data-language="${escapeHtml(n.attrs.language)}"` : "";
|
|
168
|
+
return `<pre><code${lang}>${children}</code></pre>`;
|
|
169
|
+
}
|
|
170
|
+
case "hardBreak":
|
|
171
|
+
return "<br />";
|
|
172
|
+
case "horizontalRule":
|
|
173
|
+
return "<hr />";
|
|
174
|
+
case "image": {
|
|
175
|
+
if (options.components?.image) {
|
|
176
|
+
const src = typeof n.attrs?.src === "string" ? escapeHtml(n.attrs.src) : "";
|
|
177
|
+
const alt = typeof n.attrs?.alt === "string" ? escapeHtml(n.attrs.alt) : "";
|
|
178
|
+
return `<img src="${src}" alt="${alt}" />`;
|
|
179
|
+
}
|
|
180
|
+
return "";
|
|
181
|
+
}
|
|
182
|
+
default:
|
|
183
|
+
return children;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return renderNode(root);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/fields/attrs.ts
|
|
190
|
+
function cmsFieldAttr(key) {
|
|
191
|
+
return { "data-cms-field": key };
|
|
192
|
+
}
|
|
193
|
+
function cmsGroupAttr(groupName, prefix) {
|
|
194
|
+
return { "data-cms-group": `${groupName}:${prefix}` };
|
|
195
|
+
}
|
|
196
|
+
function cmsEntryAttr(collectionKey, slug) {
|
|
197
|
+
if (slug) {
|
|
198
|
+
return {
|
|
199
|
+
"data-cms-collection": collectionKey,
|
|
200
|
+
"data-cms-entry": slug
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
return { "data-cms-collection": collectionKey };
|
|
204
|
+
}
|
|
205
|
+
function cmsEntryFieldAttr(path2) {
|
|
206
|
+
return { "data-cms-entry-field": path2 };
|
|
207
|
+
}
|
|
208
|
+
var DEFAULT_TAGS = {
|
|
209
|
+
text: "span",
|
|
210
|
+
number: "span",
|
|
211
|
+
toggle: "span",
|
|
212
|
+
select: "span",
|
|
213
|
+
image: "img",
|
|
214
|
+
img: "img",
|
|
215
|
+
video: "video",
|
|
216
|
+
vid: "video",
|
|
217
|
+
richtext: "div",
|
|
218
|
+
richText: "div"
|
|
219
|
+
};
|
|
220
|
+
function getPlaceholderForType(typeId, fullKey) {
|
|
221
|
+
const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
222
|
+
if (isDev) {
|
|
223
|
+
return `[${fullKey}]`;
|
|
224
|
+
}
|
|
225
|
+
const typeDef = getFieldType(typeId);
|
|
226
|
+
if (typeDef && typeDef.defaultValue !== void 0) {
|
|
227
|
+
return typeDef.defaultValue;
|
|
228
|
+
}
|
|
229
|
+
switch (typeId) {
|
|
230
|
+
case "number":
|
|
231
|
+
return 0;
|
|
232
|
+
case "toggle":
|
|
233
|
+
return false;
|
|
234
|
+
case "image":
|
|
235
|
+
case "video":
|
|
236
|
+
return null;
|
|
237
|
+
case "richtext":
|
|
238
|
+
return null;
|
|
239
|
+
default:
|
|
240
|
+
return "";
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function createDualCallableHelper(typeId, publicName, prefix = "", defaultKey = "") {
|
|
244
|
+
const typeDef = getFieldType(typeId) || getFieldType(publicName);
|
|
245
|
+
const defaultTag = DEFAULT_TAGS[typeId] || DEFAULT_TAGS[publicName] || typeDef?.renderHint?.tag || "span";
|
|
246
|
+
const componentFactory = createComponent(async ($$result, $$props, _slots) => {
|
|
247
|
+
const rawKey = $$props?.k ?? $$props?.key ?? defaultKey;
|
|
248
|
+
const fullKey = prefix ? rawKey ? `${prefix}.${rawKey}` : prefix : rawKey;
|
|
249
|
+
const tag = $$props?.as || $$props?.tag || defaultTag;
|
|
250
|
+
const defaultValue = $$props?.defaultValue;
|
|
251
|
+
const bundle = getActiveBundle();
|
|
252
|
+
const rawVal = fullKey ? bundle?.fields?.[fullKey] : void 0;
|
|
253
|
+
let displayVal = rawVal;
|
|
254
|
+
if (displayVal === void 0 || displayVal === null) {
|
|
255
|
+
if (defaultValue !== void 0) {
|
|
256
|
+
displayVal = defaultValue;
|
|
257
|
+
} else {
|
|
258
|
+
if (fullKey) {
|
|
259
|
+
recordMissingField(fullKey);
|
|
260
|
+
}
|
|
261
|
+
displayVal = getPlaceholderForType(typeId, fullKey);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const {
|
|
265
|
+
k: _k,
|
|
266
|
+
key: _key,
|
|
267
|
+
defaultValue: _def,
|
|
268
|
+
as: _as,
|
|
269
|
+
tag: _tag,
|
|
270
|
+
components: _comp,
|
|
271
|
+
...htmlProps
|
|
272
|
+
} = $$props || {};
|
|
273
|
+
const attrs = {
|
|
274
|
+
...htmlProps
|
|
275
|
+
};
|
|
276
|
+
if (fullKey) {
|
|
277
|
+
attrs["data-cms-field"] = fullKey;
|
|
278
|
+
}
|
|
279
|
+
if (!attrs["data-cms-kind"]) {
|
|
280
|
+
attrs["data-cms-kind"] = typeId;
|
|
281
|
+
}
|
|
282
|
+
if (typeId === "image" || publicName === "img") {
|
|
283
|
+
if (displayVal && typeof displayVal === "object") {
|
|
284
|
+
const asset = displayVal;
|
|
285
|
+
if (asset.url && !attrs.src) attrs.src = asset.url;
|
|
286
|
+
if (asset.alt && !attrs.alt) attrs.alt = asset.alt;
|
|
287
|
+
if (asset.width && !attrs.width) attrs.width = asset.width;
|
|
288
|
+
if (asset.height && !attrs.height) attrs.height = asset.height;
|
|
289
|
+
} else if (typeof displayVal === "string" && displayVal) {
|
|
290
|
+
if (!attrs.src) attrs.src = displayVal;
|
|
291
|
+
}
|
|
292
|
+
return renderTemplate`<img${spreadAttributes(attrs)}>`;
|
|
293
|
+
}
|
|
294
|
+
if (typeId === "video" || publicName === "vid") {
|
|
295
|
+
if (displayVal && typeof displayVal === "object") {
|
|
296
|
+
const asset = displayVal;
|
|
297
|
+
if (asset.url && !attrs.src) attrs.src = asset.url;
|
|
298
|
+
if (asset.poster && !attrs.poster) attrs.poster = asset.poster;
|
|
299
|
+
if (asset.width && !attrs.width) attrs.width = asset.width;
|
|
300
|
+
if (asset.height && !attrs.height) attrs.height = asset.height;
|
|
301
|
+
} else if (typeof displayVal === "string" && displayVal) {
|
|
302
|
+
if (!attrs.src) attrs.src = displayVal;
|
|
303
|
+
}
|
|
304
|
+
if (attrs.controls === void 0) attrs.controls = true;
|
|
305
|
+
return renderTemplate`<video${spreadAttributes(attrs)}></video>`;
|
|
306
|
+
}
|
|
307
|
+
if (typeId === "richtext" || publicName === "richText") {
|
|
308
|
+
const html = renderRichTextHtml(displayVal, { components: $$props?.components });
|
|
309
|
+
return renderTemplate`<${tag}${spreadAttributes(attrs)}>${markHTMLString(html)}</${tag}>`;
|
|
310
|
+
}
|
|
311
|
+
return renderTemplate`<${tag}${spreadAttributes(attrs)}>${displayVal !== null && displayVal !== void 0 ? String(displayVal) : ""}</${tag}>`;
|
|
312
|
+
});
|
|
313
|
+
const fn = (arg0, ...rest) => {
|
|
314
|
+
const isComponentCall = arg0 && typeof arg0 === "object" && "styles" in arg0 && "scripts" in arg0;
|
|
315
|
+
if (!isComponentCall) {
|
|
316
|
+
let rawKey = defaultKey;
|
|
317
|
+
let options = {};
|
|
318
|
+
if (typeof arg0 === "string") {
|
|
319
|
+
rawKey = arg0;
|
|
320
|
+
options = rest[0] || {};
|
|
321
|
+
} else if (arg0 && typeof arg0 === "object") {
|
|
322
|
+
options = arg0;
|
|
323
|
+
}
|
|
324
|
+
const fullKey = prefix ? rawKey ? `${prefix}.${rawKey}` : prefix : rawKey;
|
|
325
|
+
const bundle = getActiveBundle();
|
|
326
|
+
const val = fullKey ? bundle?.fields?.[fullKey] : void 0;
|
|
327
|
+
if (val !== void 0 && val !== null) {
|
|
328
|
+
return val;
|
|
329
|
+
}
|
|
330
|
+
if (options.defaultValue !== void 0) {
|
|
331
|
+
return options.defaultValue;
|
|
332
|
+
}
|
|
333
|
+
if (fullKey) {
|
|
334
|
+
recordMissingField(fullKey);
|
|
335
|
+
}
|
|
336
|
+
return getPlaceholderForType(typeId, fullKey);
|
|
337
|
+
}
|
|
338
|
+
return componentFactory(arg0, rest[0], rest[1]);
|
|
339
|
+
};
|
|
340
|
+
Object.assign(fn, {
|
|
341
|
+
isAstroComponentFactory: true,
|
|
342
|
+
typeId,
|
|
343
|
+
publicName,
|
|
344
|
+
prefix,
|
|
345
|
+
defaultKey
|
|
346
|
+
});
|
|
347
|
+
return fn;
|
|
348
|
+
}
|
|
349
|
+
function generateAllFieldHelpers(prefix = "") {
|
|
350
|
+
const helpers = {};
|
|
351
|
+
const types = listFieldTypes();
|
|
352
|
+
for (const def of types) {
|
|
353
|
+
helpers[def.id] = createDualCallableHelper(def.id, def.id, prefix);
|
|
354
|
+
if (def.aliases) {
|
|
355
|
+
for (const alias of def.aliases) {
|
|
356
|
+
helpers[alias] = createDualCallableHelper(def.id, alias, prefix);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return helpers;
|
|
361
|
+
}
|
|
362
|
+
var createFieldHelpersMap = generateAllFieldHelpers;
|
|
363
|
+
|
|
364
|
+
// src/fields/entryScope.ts
|
|
365
|
+
var DEFAULT_TAGS2 = {
|
|
366
|
+
text: "span",
|
|
367
|
+
number: "span",
|
|
368
|
+
toggle: "span",
|
|
369
|
+
select: "span",
|
|
370
|
+
image: "img",
|
|
371
|
+
img: "img",
|
|
372
|
+
video: "video",
|
|
373
|
+
vid: "video",
|
|
374
|
+
richtext: "div",
|
|
375
|
+
richText: "div"
|
|
376
|
+
};
|
|
377
|
+
function getNestedValue(obj, path2) {
|
|
378
|
+
if (!obj || typeof obj !== "object" || !path2) return void 0;
|
|
379
|
+
if (path2 in obj) {
|
|
380
|
+
return obj[path2];
|
|
381
|
+
}
|
|
382
|
+
const parts = path2.split(".");
|
|
383
|
+
let current = obj;
|
|
384
|
+
for (const part of parts) {
|
|
385
|
+
if (current === null || current === void 0 || typeof current !== "object") {
|
|
386
|
+
return void 0;
|
|
387
|
+
}
|
|
388
|
+
current = current[part];
|
|
389
|
+
}
|
|
390
|
+
return current;
|
|
391
|
+
}
|
|
392
|
+
function createEntryDualCallableHelper(typeId, publicName, collectionKey, slug, defaultPath = "") {
|
|
393
|
+
const typeDef = getFieldType(typeId) || getFieldType(publicName);
|
|
394
|
+
const defaultTag = DEFAULT_TAGS2[typeId] || DEFAULT_TAGS2[publicName] || typeDef?.renderHint?.tag || "span";
|
|
395
|
+
const componentFactory = createComponent(async ($$result, $$props, _slots) => {
|
|
396
|
+
const rawPath = $$props?.k ?? $$props?.key ?? defaultPath;
|
|
397
|
+
const tag = $$props?.as || $$props?.tag || defaultTag;
|
|
398
|
+
const defaultValue = $$props?.defaultValue;
|
|
399
|
+
const bundle = getActiveBundle();
|
|
400
|
+
const entries = bundle?.entries?.[collectionKey] || [];
|
|
401
|
+
const entry = entries.find((e) => e.slug === slug);
|
|
402
|
+
const rawVal = entry?.content ? getNestedValue(entry.content, rawPath) : void 0;
|
|
403
|
+
let displayVal = rawVal;
|
|
404
|
+
if (displayVal === void 0 || displayVal === null) {
|
|
405
|
+
if (defaultValue !== void 0) {
|
|
406
|
+
displayVal = defaultValue;
|
|
407
|
+
} else {
|
|
408
|
+
displayVal = getPlaceholderForType(typeId, rawPath);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
const {
|
|
412
|
+
k: _k,
|
|
413
|
+
key: _key,
|
|
414
|
+
defaultValue: _def,
|
|
415
|
+
as: _as,
|
|
416
|
+
tag: _tag,
|
|
417
|
+
components: _comp,
|
|
418
|
+
...htmlProps
|
|
419
|
+
} = $$props || {};
|
|
420
|
+
const attrs = {
|
|
421
|
+
...htmlProps
|
|
422
|
+
};
|
|
423
|
+
if (rawPath) {
|
|
424
|
+
attrs["data-cms-entry-field"] = rawPath;
|
|
425
|
+
}
|
|
426
|
+
if (!attrs["data-cms-kind"]) {
|
|
427
|
+
attrs["data-cms-kind"] = typeId;
|
|
428
|
+
}
|
|
429
|
+
if (typeId === "image" || publicName === "img") {
|
|
430
|
+
if (displayVal && typeof displayVal === "object") {
|
|
431
|
+
const asset = displayVal;
|
|
432
|
+
if (asset.url && !attrs.src) attrs.src = asset.url;
|
|
433
|
+
if (asset.alt && !attrs.alt) attrs.alt = asset.alt;
|
|
434
|
+
if (asset.width && !attrs.width) attrs.width = asset.width;
|
|
435
|
+
if (asset.height && !attrs.height) attrs.height = asset.height;
|
|
436
|
+
} else if (typeof displayVal === "string" && displayVal) {
|
|
437
|
+
if (!attrs.src) attrs.src = displayVal;
|
|
438
|
+
}
|
|
439
|
+
return renderTemplate`<img${spreadAttributes(attrs)}>`;
|
|
440
|
+
}
|
|
441
|
+
if (typeId === "video" || publicName === "vid") {
|
|
442
|
+
if (displayVal && typeof displayVal === "object") {
|
|
443
|
+
const asset = displayVal;
|
|
444
|
+
if (asset.url && !attrs.src) attrs.src = asset.url;
|
|
445
|
+
if (asset.poster && !attrs.poster) attrs.poster = asset.poster;
|
|
446
|
+
if (asset.width && !attrs.width) attrs.width = asset.width;
|
|
447
|
+
if (asset.height && !attrs.height) attrs.height = asset.height;
|
|
448
|
+
} else if (typeof displayVal === "string" && displayVal) {
|
|
449
|
+
if (!attrs.src) attrs.src = displayVal;
|
|
450
|
+
}
|
|
451
|
+
if (attrs.controls === void 0) attrs.controls = true;
|
|
452
|
+
return renderTemplate`<video${spreadAttributes(attrs)}></video>`;
|
|
453
|
+
}
|
|
454
|
+
if (typeId === "richtext" || publicName === "richText") {
|
|
455
|
+
const html = renderRichTextHtml(displayVal, { components: $$props?.components });
|
|
456
|
+
return renderTemplate`<${tag}${spreadAttributes(attrs)}>${markHTMLString(html)}</${tag}>`;
|
|
457
|
+
}
|
|
458
|
+
return renderTemplate`<${tag}${spreadAttributes(attrs)}>${displayVal !== null && displayVal !== void 0 ? String(displayVal) : ""}</${tag}>`;
|
|
459
|
+
});
|
|
460
|
+
const fn = (arg0, ...rest) => {
|
|
461
|
+
const isComponentCall = arg0 && typeof arg0 === "object" && "styles" in arg0 && "scripts" in arg0;
|
|
462
|
+
if (!isComponentCall) {
|
|
463
|
+
let rawPath = defaultPath;
|
|
464
|
+
let options = {};
|
|
465
|
+
if (typeof arg0 === "string") {
|
|
466
|
+
rawPath = arg0;
|
|
467
|
+
options = rest[0] || {};
|
|
468
|
+
} else if (arg0 && typeof arg0 === "object") {
|
|
469
|
+
options = arg0;
|
|
470
|
+
}
|
|
471
|
+
const bundle = getActiveBundle();
|
|
472
|
+
const entries = bundle?.entries?.[collectionKey] || [];
|
|
473
|
+
const entry = entries.find((e) => e.slug === slug);
|
|
474
|
+
const val = entry?.content ? getNestedValue(entry.content, rawPath) : void 0;
|
|
475
|
+
if (val !== void 0 && val !== null) {
|
|
476
|
+
return val;
|
|
477
|
+
}
|
|
478
|
+
if (options.defaultValue !== void 0) {
|
|
479
|
+
return options.defaultValue;
|
|
480
|
+
}
|
|
481
|
+
return getPlaceholderForType(typeId, rawPath);
|
|
482
|
+
}
|
|
483
|
+
return componentFactory(arg0, rest[0], rest[1]);
|
|
484
|
+
};
|
|
485
|
+
Object.assign(fn, {
|
|
486
|
+
isAstroComponentFactory: true,
|
|
487
|
+
typeId,
|
|
488
|
+
publicName,
|
|
489
|
+
collectionKey,
|
|
490
|
+
slug,
|
|
491
|
+
defaultPath
|
|
492
|
+
});
|
|
493
|
+
return fn;
|
|
494
|
+
}
|
|
495
|
+
function createEntryScope(handleOrKey, slug) {
|
|
496
|
+
const collectionKey = typeof handleOrKey === "string" ? handleOrKey : handleOrKey.key;
|
|
497
|
+
const boundHelpers = {};
|
|
498
|
+
const types = listFieldTypes();
|
|
499
|
+
for (const def of types) {
|
|
500
|
+
boundHelpers[def.id] = createEntryDualCallableHelper(def.id, def.id, collectionKey, slug);
|
|
501
|
+
if (def.aliases) {
|
|
502
|
+
for (const alias of def.aliases) {
|
|
503
|
+
boundHelpers[alias] = createEntryDualCallableHelper(def.id, alias, collectionKey, slug);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const accessor = {
|
|
508
|
+
...boundHelpers,
|
|
509
|
+
attrs: () => cmsEntryAttr(collectionKey, slug),
|
|
510
|
+
collectionKey,
|
|
511
|
+
slug
|
|
512
|
+
};
|
|
513
|
+
return accessor;
|
|
514
|
+
}
|
|
515
|
+
var entryScope = createEntryScope;
|
|
516
|
+
|
|
517
|
+
// src/fields/group.ts
|
|
518
|
+
function defineGroup(nameOrShape, shapeOrUndefined) {
|
|
519
|
+
const groupName = typeof nameOrShape === "string" ? nameOrShape : "Group";
|
|
520
|
+
const shape = typeof nameOrShape === "string" ? shapeOrUndefined || {} : nameOrShape;
|
|
521
|
+
const groupDef = (scopeKey) => {
|
|
522
|
+
const accessorFn = (key) => {
|
|
523
|
+
return scopeKey ? `${scopeKey}.${key}` : key;
|
|
524
|
+
};
|
|
525
|
+
const boundHelpers = {};
|
|
526
|
+
for (const [key, helperDef] of Object.entries(shape)) {
|
|
527
|
+
const helperObj = helperDef;
|
|
528
|
+
const typeId = helperObj?.typeId || helperObj?.publicName;
|
|
529
|
+
if (!typeId) {
|
|
530
|
+
throw new Error(
|
|
531
|
+
`f.group('${groupName}', ...) field '${key}' must reference a field helper (e.g. f.text, f.img), got ${typeof helperDef}`
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
const publicName = helperObj?.publicName || typeId;
|
|
535
|
+
boundHelpers[key] = createDualCallableHelper(typeId, publicName, scopeKey, key);
|
|
536
|
+
}
|
|
537
|
+
Object.assign(accessorFn, boundHelpers, {
|
|
538
|
+
attrs: () => cmsGroupAttr(groupName, scopeKey),
|
|
539
|
+
key: (key) => scopeKey ? `${scopeKey}.${key}` : key,
|
|
540
|
+
groupName,
|
|
541
|
+
prefix: scopeKey
|
|
542
|
+
});
|
|
543
|
+
return accessorFn;
|
|
544
|
+
};
|
|
545
|
+
Object.assign(groupDef, {
|
|
546
|
+
groupName,
|
|
547
|
+
shape
|
|
548
|
+
});
|
|
549
|
+
return groupDef;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// src/fields/scope.ts
|
|
553
|
+
function createScope(prefix = "") {
|
|
554
|
+
const helpers = generateAllFieldHelpers(prefix);
|
|
555
|
+
const scopeFn = (key) => {
|
|
556
|
+
return prefix ? `${prefix}.${key}` : key;
|
|
557
|
+
};
|
|
558
|
+
Object.assign(scopeFn, helpers, {
|
|
559
|
+
key: (key) => prefix ? `${prefix}.${key}` : key,
|
|
560
|
+
scope: (subPrefix) => {
|
|
561
|
+
const nextPrefix = prefix ? `${prefix}.${subPrefix}` : subPrefix;
|
|
562
|
+
return createScope(nextPrefix);
|
|
563
|
+
},
|
|
564
|
+
prefix
|
|
565
|
+
});
|
|
566
|
+
return scopeFn;
|
|
567
|
+
}
|
|
568
|
+
var baseHelpers = createFieldHelpersMap("");
|
|
569
|
+
var f = {
|
|
570
|
+
...baseHelpers,
|
|
571
|
+
scope: createScope,
|
|
572
|
+
entryScope: createEntryScope,
|
|
573
|
+
group: defineGroup,
|
|
574
|
+
entries: getEntries,
|
|
575
|
+
entry: getEntry,
|
|
576
|
+
defineCollection,
|
|
577
|
+
collectionPaths
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
// src/head.ts
|
|
581
|
+
function buildHeadTags(route, siteConfig, options) {
|
|
582
|
+
const tags = [];
|
|
583
|
+
const defaultSeo = siteConfig?.default_seo || {};
|
|
584
|
+
const routeSeo = route?.seo || {};
|
|
585
|
+
const title = routeSeo.title || defaultSeo.title || route?.title || "";
|
|
586
|
+
if (title) {
|
|
587
|
+
tags.push({ tag: "title", content: title });
|
|
588
|
+
}
|
|
589
|
+
const description = routeSeo.description || defaultSeo.description;
|
|
590
|
+
if (description) {
|
|
591
|
+
tags.push({
|
|
592
|
+
tag: "meta",
|
|
593
|
+
attrs: { name: "description", content: description }
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
const siteUrl = options?.siteUrl ? options.siteUrl.replace(/\/+$/, "") : "";
|
|
597
|
+
let canonical = routeSeo.canonical || defaultSeo.canonical;
|
|
598
|
+
if (!canonical && siteUrl && route?.path) {
|
|
599
|
+
const normPath = route.path === "/" ? "" : route.path.startsWith("/") ? route.path : `/${route.path}`;
|
|
600
|
+
canonical = `${siteUrl}${normPath}`;
|
|
601
|
+
}
|
|
602
|
+
if (canonical) {
|
|
603
|
+
tags.push({
|
|
604
|
+
tag: "link",
|
|
605
|
+
attrs: { rel: "canonical", href: canonical }
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
if (routeSeo.noindex || defaultSeo.noindex) {
|
|
609
|
+
tags.push({
|
|
610
|
+
tag: "meta",
|
|
611
|
+
attrs: { name: "robots", content: "noindex, nofollow" }
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
const ogTitle = routeSeo.og_title || routeSeo.title || defaultSeo.og_title || defaultSeo.title || route?.title;
|
|
615
|
+
if (ogTitle) {
|
|
616
|
+
tags.push({
|
|
617
|
+
tag: "meta",
|
|
618
|
+
attrs: { property: "og:title", content: ogTitle }
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
const ogDescription = routeSeo.og_description || routeSeo.description || defaultSeo.og_description || defaultSeo.description;
|
|
622
|
+
if (ogDescription) {
|
|
623
|
+
tags.push({
|
|
624
|
+
tag: "meta",
|
|
625
|
+
attrs: { property: "og:description", content: ogDescription }
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
const rawOgImage = routeSeo.og_image || defaultSeo.og_image;
|
|
629
|
+
const ogImageUrl = typeof rawOgImage === "object" && rawOgImage !== null && "url" in rawOgImage ? rawOgImage.url : rawOgImage;
|
|
630
|
+
if (ogImageUrl) {
|
|
631
|
+
tags.push({
|
|
632
|
+
tag: "meta",
|
|
633
|
+
attrs: { property: "og:image", content: ogImageUrl }
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
if (canonical) {
|
|
637
|
+
tags.push({
|
|
638
|
+
tag: "meta",
|
|
639
|
+
attrs: { property: "og:url", content: canonical }
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
const twitterCard = routeSeo.twitter_card || defaultSeo.twitter_card || "summary_large_image";
|
|
643
|
+
tags.push({
|
|
644
|
+
tag: "meta",
|
|
645
|
+
attrs: { name: "twitter:card", content: twitterCard }
|
|
646
|
+
});
|
|
647
|
+
return tags;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// src/image.ts
|
|
651
|
+
function isCdnTransformableUrl(url) {
|
|
652
|
+
if (!url || typeof url !== "string") return false;
|
|
653
|
+
if (url.startsWith("data:") || url.startsWith("blob:")) return false;
|
|
654
|
+
if (url.includes("localhost") || url.includes("127.0.0.1") || url.includes(".r2.dev")) {
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
return url.startsWith("http://") || url.startsWith("https://");
|
|
658
|
+
}
|
|
659
|
+
function buildCdnImageUrl(url, options = {}) {
|
|
660
|
+
if (!isCdnTransformableUrl(url)) {
|
|
661
|
+
return url;
|
|
662
|
+
}
|
|
663
|
+
const params = [];
|
|
664
|
+
if (options.width !== void 0 && options.width !== null) {
|
|
665
|
+
params.push(`width=${options.width}`);
|
|
666
|
+
}
|
|
667
|
+
if (options.height !== void 0 && options.height !== null) {
|
|
668
|
+
params.push(`height=${options.height}`);
|
|
669
|
+
}
|
|
670
|
+
params.push(`format=${options.format || "auto"}`);
|
|
671
|
+
if (options.fit) {
|
|
672
|
+
params.push(`fit=${options.fit}`);
|
|
673
|
+
}
|
|
674
|
+
if (options.quality !== void 0 && options.quality !== null) {
|
|
675
|
+
params.push(`quality=${options.quality}`);
|
|
676
|
+
}
|
|
677
|
+
const optionString = params.join(",");
|
|
678
|
+
return `/cdn-cgi/image/${optionString}/${url}`;
|
|
679
|
+
}
|
|
680
|
+
function buildSrcSet(url, widths = [400, 800, 1200, 1600], options = {}) {
|
|
681
|
+
if (!url) return "";
|
|
682
|
+
if (!isCdnTransformableUrl(url)) return "";
|
|
683
|
+
return widths.map((w) => `${buildCdnImageUrl(url, { ...options, width: w })} ${w}w`).join(", ");
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// src/toolbar/icon.ts
|
|
687
|
+
var CMS_TOOLBAR_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
688
|
+
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/>
|
|
689
|
+
<path d="M4 10h16"/>
|
|
690
|
+
<path d="M10 4v16"/>
|
|
691
|
+
</svg>`;
|
|
692
|
+
|
|
693
|
+
// src/integration.ts
|
|
694
|
+
function deriveRouteFromComponent(componentPath) {
|
|
695
|
+
let route = componentPath.replace(/\\/g, "/").replace(/^.*src\/pages\/?/, "/").replace(/\.(astro|mdx|md|ts|js|jsx|tsx)$/, "").replace(/\/index$/, "");
|
|
696
|
+
if (!route.startsWith("/")) {
|
|
697
|
+
route = `/${route}`;
|
|
698
|
+
}
|
|
699
|
+
return route === "" ? "/" : route;
|
|
700
|
+
}
|
|
701
|
+
function cmsAstro(options = {}) {
|
|
702
|
+
return {
|
|
703
|
+
name: "@407dev/cms-astro",
|
|
704
|
+
hooks: {
|
|
705
|
+
"astro:config:setup": async ({
|
|
706
|
+
updateConfig,
|
|
707
|
+
command,
|
|
708
|
+
injectScript,
|
|
709
|
+
addMiddleware,
|
|
710
|
+
addDevToolbarApp,
|
|
711
|
+
logger
|
|
712
|
+
}) => {
|
|
713
|
+
addMiddleware({
|
|
714
|
+
entrypoint: "@407dev/cms-astro/middleware",
|
|
715
|
+
order: "pre"
|
|
716
|
+
});
|
|
717
|
+
if (options.client) {
|
|
718
|
+
initCmsClient({ client: options.client });
|
|
719
|
+
} else {
|
|
720
|
+
initCmsClient({
|
|
721
|
+
siteId: options.siteId,
|
|
722
|
+
contentUrl: options.contentUrl,
|
|
723
|
+
previewSecret: options.previewSecret
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
const effectiveSiteId = options.siteId || process.env.CMS_SITE_ID || "";
|
|
727
|
+
const effectiveContentUrl = options.contentUrl || process.env.CMS_CONTENT_URL || "";
|
|
728
|
+
const effectivePreviewSecret = options.previewSecret || process.env.CMS_PREVIEW_SECRET || "";
|
|
729
|
+
if (command !== "dev" && (options.previewSecret || process.env.CMS_PREVIEW_SECRET)) {
|
|
730
|
+
logger.warn(
|
|
731
|
+
"previewSecret and CMS_PREVIEW_SECRET are deprecated and ignored outside astro dev. Site hosts no longer verify preview tokens."
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
if (effectiveContentUrl || effectiveSiteId) {
|
|
735
|
+
updateConfig({
|
|
736
|
+
vite: {
|
|
737
|
+
define: {
|
|
738
|
+
"import.meta.env.CMS_CONTENT_URL": JSON.stringify(effectiveContentUrl),
|
|
739
|
+
"import.meta.env.CMS_SITE_ID": JSON.stringify(effectiveSiteId)
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
if (command === "dev") {
|
|
745
|
+
injectScript(
|
|
746
|
+
"page",
|
|
747
|
+
buildBridgeScript({
|
|
748
|
+
editorOrigins: options.editorOrigins
|
|
749
|
+
})
|
|
750
|
+
);
|
|
751
|
+
const devModulePath = "./dev/index.js";
|
|
752
|
+
const { resolveDevConfig, createVerifier, cmsDevApiPlugin } = await import(
|
|
753
|
+
/* @vite-ignore */
|
|
754
|
+
devModulePath
|
|
755
|
+
);
|
|
756
|
+
const devConfig = await resolveDevConfig({
|
|
757
|
+
siteId: options.siteId,
|
|
758
|
+
apiUrl: options.apiUrl,
|
|
759
|
+
siteDir: process.cwd()
|
|
760
|
+
});
|
|
761
|
+
if (devConfig.status === "refused") {
|
|
762
|
+
logger.error(`CMS dev routes disabled: ${devConfig.reason}`);
|
|
763
|
+
}
|
|
764
|
+
if (devConfig.status === "read-only") {
|
|
765
|
+
logger.warn(
|
|
766
|
+
`CMS dev toolbar is READ-ONLY: ${devConfig.mismatch?.source} (${devConfig.mismatch?.actual}) \u2260 site rendered (${devConfig.mismatch?.expected})`
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
const verifier = await createVerifier({
|
|
770
|
+
siteDir: process.cwd(),
|
|
771
|
+
siteId: devConfig.siteId
|
|
772
|
+
});
|
|
773
|
+
addDevToolbarApp({
|
|
774
|
+
id: "cms-content",
|
|
775
|
+
name: "CMS Content",
|
|
776
|
+
icon: CMS_TOOLBAR_ICON,
|
|
777
|
+
entrypoint: fileURLToPath(new URL("./toolbar/app.js", import.meta.url))
|
|
778
|
+
});
|
|
779
|
+
updateConfig({
|
|
780
|
+
vite: {
|
|
781
|
+
plugins: [
|
|
782
|
+
cmsDevApiPlugin({
|
|
783
|
+
devConfig,
|
|
784
|
+
client: getClient(),
|
|
785
|
+
verifier,
|
|
786
|
+
previewSecret: effectivePreviewSecret,
|
|
787
|
+
editorOrigins: options.editorOrigins
|
|
788
|
+
})
|
|
789
|
+
]
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
const activeClient = getClient();
|
|
794
|
+
if (activeClient) {
|
|
795
|
+
try {
|
|
796
|
+
const devPreviewToken = command === "dev" ? await mintDevPreviewToken(activeClient.siteId, effectivePreviewSecret) : null;
|
|
797
|
+
const bundle = await activeClient.getBundle(
|
|
798
|
+
devPreviewToken ? { previewToken: devPreviewToken } : void 0
|
|
799
|
+
);
|
|
800
|
+
markBundleReady(bundle);
|
|
801
|
+
const cmsDir = path.resolve(process.cwd(), ".cms");
|
|
802
|
+
if (!fs.existsSync(cmsDir)) {
|
|
803
|
+
fs.mkdirSync(cmsDir, { recursive: true });
|
|
804
|
+
}
|
|
805
|
+
fs.writeFileSync(
|
|
806
|
+
path.join(cmsDir, "bundle.json"),
|
|
807
|
+
JSON.stringify(bundle, null, 2),
|
|
808
|
+
"utf-8"
|
|
809
|
+
);
|
|
810
|
+
} catch {
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
},
|
|
814
|
+
"astro:routes:resolved": async ({ routes }) => {
|
|
815
|
+
try {
|
|
816
|
+
const cmsDir = path.resolve(process.cwd(), ".cms");
|
|
817
|
+
if (!fs.existsSync(cmsDir)) {
|
|
818
|
+
fs.mkdirSync(cmsDir, { recursive: true });
|
|
819
|
+
}
|
|
820
|
+
const serializedRoutes = routes.map(
|
|
821
|
+
(r) => {
|
|
822
|
+
const comp = r.component || r.entrypoint || "";
|
|
823
|
+
let routePattern = r.route || r.pathname || "";
|
|
824
|
+
if (!routePattern && comp) {
|
|
825
|
+
routePattern = deriveRouteFromComponent(comp);
|
|
826
|
+
}
|
|
827
|
+
return {
|
|
828
|
+
route: routePattern,
|
|
829
|
+
component: comp,
|
|
830
|
+
type: r.type || "page",
|
|
831
|
+
params: r.params || []
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
);
|
|
835
|
+
fs.writeFileSync(
|
|
836
|
+
path.join(cmsDir, "routes.json"),
|
|
837
|
+
JSON.stringify(serializedRoutes, null, 2),
|
|
838
|
+
"utf-8"
|
|
839
|
+
);
|
|
840
|
+
} catch {
|
|
841
|
+
}
|
|
842
|
+
},
|
|
843
|
+
"astro:build:done": async ({ logger }) => {
|
|
844
|
+
const missing = getMissingFieldWarnings();
|
|
845
|
+
if (missing.length > 0) {
|
|
846
|
+
logger.warn(
|
|
847
|
+
`CMS Build Warning: ${missing.length} field(s) were rendered with empty/missing values: ${missing.join(", ")}`
|
|
848
|
+
);
|
|
849
|
+
clearMissingFieldWarnings();
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
var cms = cmsAstro;
|
|
856
|
+
|
|
857
|
+
// src/preview.ts
|
|
858
|
+
async function getPreviewData(options) {
|
|
859
|
+
const { previewToken, client } = options;
|
|
860
|
+
if (!previewToken) {
|
|
861
|
+
return {
|
|
862
|
+
ok: false,
|
|
863
|
+
status: 404,
|
|
864
|
+
error: "Preview token is required"
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
try {
|
|
868
|
+
const bundle = await client.getBundle({ previewToken });
|
|
869
|
+
return {
|
|
870
|
+
ok: true,
|
|
871
|
+
status: 200,
|
|
872
|
+
bundle
|
|
873
|
+
};
|
|
874
|
+
} catch (_err) {
|
|
875
|
+
return {
|
|
876
|
+
ok: false,
|
|
877
|
+
status: 404,
|
|
878
|
+
error: "Preview token is not valid for this site"
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// src/siteFiles.ts
|
|
884
|
+
function renderRedirectsFile(redirects = []) {
|
|
885
|
+
const lines = redirects.filter((r) => r.enabled !== false && r.from_path && r.to_path).map((r) => `${r.from_path} ${r.to_path} ${r.status_code || 301}`);
|
|
886
|
+
return lines.length > 0 ? `${lines.join("\n")}
|
|
887
|
+
` : "";
|
|
888
|
+
}
|
|
889
|
+
function renderRobotsTxt(config, options) {
|
|
890
|
+
if (config?.robots?.raw) {
|
|
891
|
+
return `${config.robots.raw.trim()}
|
|
892
|
+
`;
|
|
893
|
+
}
|
|
894
|
+
const lines = [];
|
|
895
|
+
const rules = config?.robots?.rules || [{ user_agent: "*", allow: ["/"] }];
|
|
896
|
+
for (const rule of rules) {
|
|
897
|
+
lines.push(`User-agent: ${rule.user_agent || "*"}`);
|
|
898
|
+
if (rule.allow && rule.allow.length > 0) {
|
|
899
|
+
for (const path2 of rule.allow) {
|
|
900
|
+
lines.push(`Allow: ${path2}`);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
if (rule.disallow && rule.disallow.length > 0) {
|
|
904
|
+
for (const path2 of rule.disallow) {
|
|
905
|
+
lines.push(`Disallow: ${path2}`);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
lines.push("");
|
|
909
|
+
}
|
|
910
|
+
const siteUrl = options?.siteUrl ? options.siteUrl.replace(/\/+$/, "") : "";
|
|
911
|
+
if (siteUrl && config?.robots?.sitemap !== false) {
|
|
912
|
+
lines.push(`Sitemap: ${siteUrl}/sitemap.xml`);
|
|
913
|
+
}
|
|
914
|
+
return `${lines.join("\n").trim()}
|
|
915
|
+
`;
|
|
916
|
+
}
|
|
917
|
+
function renderSitemapXml(routes, options) {
|
|
918
|
+
const siteUrl = options.siteUrl.replace(/\/+$/, "");
|
|
919
|
+
const config = options.siteConfig;
|
|
920
|
+
const excludes = new Set(config?.sitemap?.exclude || []);
|
|
921
|
+
if (config?.not_found_path) {
|
|
922
|
+
excludes.add(config.not_found_path);
|
|
923
|
+
}
|
|
924
|
+
const filtered = routes.filter((r) => {
|
|
925
|
+
if (r.path && excludes.has(r.path) || r.id && excludes.has(r.id)) {
|
|
926
|
+
return false;
|
|
927
|
+
}
|
|
928
|
+
if ("seo" in r && r.seo && typeof r.seo === "object") {
|
|
929
|
+
const seoObj = r.seo;
|
|
930
|
+
if (seoObj.noindex) {
|
|
931
|
+
return false;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
return true;
|
|
935
|
+
});
|
|
936
|
+
const urlEntries = filtered.map((r) => {
|
|
937
|
+
const rawPath = r.path || "/";
|
|
938
|
+
const normPath = rawPath.startsWith("/") ? rawPath : `/${rawPath}`;
|
|
939
|
+
const loc = `${siteUrl}${normPath}`;
|
|
940
|
+
const dateStr = "published_at" in r && r.published_at || r.updated_at || (/* @__PURE__ */ new Date()).toISOString();
|
|
941
|
+
const lastmod = dateStr.split("T")[0];
|
|
942
|
+
return ` <url>
|
|
943
|
+
<loc>${loc}</loc>
|
|
944
|
+
<lastmod>${lastmod}</lastmod>
|
|
945
|
+
</url>`;
|
|
946
|
+
});
|
|
947
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
948
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
949
|
+
${urlEntries.join("\n")}
|
|
950
|
+
</urlset>
|
|
951
|
+
`;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
export { KNOWN_NODES, buildCdnImageUrl, buildHeadTags, buildSrcSet, cms, cmsAstro, cmsEntryAttr, cmsEntryFieldAttr, cmsFieldAttr, cmsGroupAttr, createEntryDualCallableHelper, createEntryScope, createScope, defineGroup, entryScope, escapeHtml, f, getLinkMarkAttrs, getPreviewData, isCdnTransformableUrl, parseRichTextDoc, renderMarksOnly, renderRedirectsFile, renderRichTextHtml, renderRobotsTxt, renderSitemapXml };
|
|
955
|
+
//# sourceMappingURL=index.js.map
|
|
956
|
+
//# sourceMappingURL=index.js.map
|