@bagelink/blox 1.12.22 → 1.13.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/dist/{prerender-DYmDaqcz.js → prerender-1I_qD2kp.js} +205 -7
- package/dist/{prerender-6jE_obPj.cjs → prerender-Br-vA3A0.cjs} +204 -6
- package/dist/ssg/cli.cjs +12 -4
- package/dist/ssg/cli.mjs +12 -4
- package/dist/ssg/cms-routes.d.ts +14 -4
- package/dist/ssg/cms-routes.d.ts.map +1 -1
- package/dist/ssg/index.cjs +19 -4
- package/dist/ssg/index.d.ts +6 -2
- package/dist/ssg/index.d.ts.map +1 -1
- package/dist/ssg/index.mjs +26 -10
- package/dist/ssg/prerender.d.ts +11 -1
- package/dist/ssg/prerender.d.ts.map +1 -1
- package/dist/ssg/render-resolved-page.d.ts +9 -3
- package/dist/ssg/render-resolved-page.d.ts.map +1 -1
- package/dist/ssg/seo.d.ts +66 -0
- package/dist/ssg/seo.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -2,18 +2,43 @@ import fs from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
|
-
async function
|
|
5
|
+
async function fetchCmsSiteData(apiBase, websiteName) {
|
|
6
6
|
const sitesRes = await fetch(`${apiBase}/cms/websites`);
|
|
7
7
|
const sitesData = await sitesRes.json();
|
|
8
8
|
const sites = Array.isArray(sitesData) ? sitesData : sitesData.data ?? [];
|
|
9
9
|
const site = sites.find((s) => s.name === websiteName);
|
|
10
10
|
if ((site == null ? void 0 : site.id) == null || site.id === "") throw new Error(`Website "${websiteName}" not found at ${apiBase}`);
|
|
11
|
-
|
|
11
|
+
let website = site;
|
|
12
|
+
try {
|
|
13
|
+
const wRes = await fetch(`${apiBase}/cms/websites/${site.id}`);
|
|
14
|
+
if (wRes.ok) website = await wRes.json();
|
|
15
|
+
} catch {
|
|
16
|
+
}
|
|
17
|
+
const pagesRes = await fetch(`${apiBase}/cms/websites/${site.id}/pages?locale=${website.default_locale || "en"}`);
|
|
12
18
|
const pagesData = await pagesRes.json();
|
|
13
19
|
const pages = Array.isArray(pagesData) ? pagesData : pagesData.data ?? [];
|
|
20
|
+
const paths = await expandRoutes(apiBase, pages);
|
|
21
|
+
let redirects = [];
|
|
22
|
+
try {
|
|
23
|
+
const rRes = await fetch(`${apiBase}/cms/websites/${site.id}/redirects`);
|
|
24
|
+
if (rRes.ok) {
|
|
25
|
+
const rData = await rRes.json();
|
|
26
|
+
const items = Array.isArray(rData) ? rData : rData.data ?? [];
|
|
27
|
+
redirects = items.filter((r) => r.from_path && r.to_path);
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
return { websiteId: site.id, website, paths, redirects };
|
|
32
|
+
}
|
|
33
|
+
async function fetchCmsPrerenderPaths(apiBase, websiteName) {
|
|
34
|
+
const { paths } = await fetchCmsSiteData(apiBase, websiteName);
|
|
35
|
+
return paths;
|
|
36
|
+
}
|
|
37
|
+
async function expandRoutes(apiBase, pages) {
|
|
14
38
|
const routes = [];
|
|
15
39
|
for (const page of pages) {
|
|
16
40
|
const slug = page.slug ?? "/";
|
|
41
|
+
if (page.status && page.status !== "published") continue;
|
|
17
42
|
if (slug.includes(":") && page.data_bindings) {
|
|
18
43
|
for (const [, binding] of Object.entries(page.data_bindings)) {
|
|
19
44
|
const b = binding;
|
|
@@ -27,7 +52,10 @@ async function fetchCmsPrerenderPaths(apiBase, websiteName) {
|
|
|
27
52
|
for (const item of items) {
|
|
28
53
|
const bindValue = item[b.bind_by];
|
|
29
54
|
if (bindValue != null && bindValue !== "") {
|
|
30
|
-
const concrete = slug.replace(
|
|
55
|
+
const concrete = slug.replace(
|
|
56
|
+
/:([a-z_]+)/g,
|
|
57
|
+
(_m, p) => p === b.bind_by ? String(bindValue) : String(item[p] ?? "")
|
|
58
|
+
);
|
|
31
59
|
routes.push(concrete);
|
|
32
60
|
}
|
|
33
61
|
}
|
|
@@ -86,6 +114,133 @@ async function polyfillBloxSsgGlobals(options) {
|
|
|
86
114
|
g.window.location = _win.location;
|
|
87
115
|
g.window.document = _win.document;
|
|
88
116
|
}
|
|
117
|
+
function buildPageHead(options) {
|
|
118
|
+
const { url, resolvedData, website, stateScript } = options;
|
|
119
|
+
const parts = [];
|
|
120
|
+
const meta = (website == null ? void 0 : website.meta) ?? {};
|
|
121
|
+
const page = resolvedData == null ? void 0 : resolvedData.page;
|
|
122
|
+
const title = (page == null ? void 0 : page.meta_title) || ((page == null ? void 0 : page.title) && meta.og_site_name ? `${page.title} · ${meta.og_site_name}` : null) || (page == null ? void 0 : page.title) || meta.default_meta_title;
|
|
123
|
+
if (title) {
|
|
124
|
+
parts.push(`<title>${esc(title)}</title>`);
|
|
125
|
+
}
|
|
126
|
+
const description = (page == null ? void 0 : page.meta_description) || meta.default_meta_description;
|
|
127
|
+
if (description) {
|
|
128
|
+
parts.push(`<meta name="description" content="${esc(description)}">`);
|
|
129
|
+
}
|
|
130
|
+
const canonicalBase = (meta.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
131
|
+
if (canonicalBase) {
|
|
132
|
+
parts.push(`<link rel="canonical" href="${esc(canonicalBase + url)}">`);
|
|
133
|
+
}
|
|
134
|
+
const ogTitle = (page == null ? void 0 : page.meta_title) || (page == null ? void 0 : page.title) || meta.og_site_name || meta.default_meta_title;
|
|
135
|
+
const ogDesc = (page == null ? void 0 : page.meta_description) || meta.og_description || meta.default_meta_description;
|
|
136
|
+
const ogImage = (page == null ? void 0 : page.og_image) || meta.default_og_image;
|
|
137
|
+
const ogType = meta.og_type || "website";
|
|
138
|
+
if (ogTitle) parts.push(`<meta property="og:title" content="${esc(ogTitle)}">`);
|
|
139
|
+
if (ogDesc) parts.push(`<meta property="og:description" content="${esc(ogDesc)}">`);
|
|
140
|
+
if (ogImage) parts.push(`<meta property="og:image" content="${esc(ogImage)}">`);
|
|
141
|
+
parts.push(`<meta property="og:type" content="${esc(ogType)}">`);
|
|
142
|
+
if (canonicalBase) parts.push(`<meta property="og:url" content="${esc(canonicalBase + url)}">`);
|
|
143
|
+
if (meta.og_site_name) parts.push(`<meta property="og:site_name" content="${esc(meta.og_site_name)}">`);
|
|
144
|
+
const twitterCard = meta.twitter_card || "summary_large_image";
|
|
145
|
+
parts.push(`<meta name="twitter:card" content="${esc(twitterCard)}">`);
|
|
146
|
+
if (ogTitle) parts.push(`<meta name="twitter:title" content="${esc(ogTitle)}">`);
|
|
147
|
+
if (ogDesc) parts.push(`<meta name="twitter:description" content="${esc(ogDesc)}">`);
|
|
148
|
+
if (ogImage) parts.push(`<meta name="twitter:image" content="${esc(ogImage)}">`);
|
|
149
|
+
if (meta.twitter_site) parts.push(`<meta name="twitter:site" content="${esc(meta.twitter_site)}">`);
|
|
150
|
+
const alternates = resolvedData == null ? void 0 : resolvedData.alternates;
|
|
151
|
+
if (alternates && canonicalBase) {
|
|
152
|
+
for (const [locale, slug] of Object.entries(alternates)) {
|
|
153
|
+
parts.push(`<link rel="alternate" hreflang="${esc(locale)}" href="${esc(canonicalBase + slug)}">`);
|
|
154
|
+
}
|
|
155
|
+
const defaultSlug = alternates[(website == null ? void 0 : website.default_locale) ?? "en"] ?? url;
|
|
156
|
+
parts.push(`<link rel="alternate" hreflang="x-default" href="${esc(canonicalBase + defaultSlug)}">`);
|
|
157
|
+
}
|
|
158
|
+
if (meta.noindex) {
|
|
159
|
+
parts.push('<meta name="robots" content="noindex, nofollow">');
|
|
160
|
+
}
|
|
161
|
+
if (stateScript) {
|
|
162
|
+
parts.push(stateScript);
|
|
163
|
+
}
|
|
164
|
+
return parts.join("\n");
|
|
165
|
+
}
|
|
166
|
+
function buildSiteHead(website) {
|
|
167
|
+
if (!website) return "";
|
|
168
|
+
const parts = [];
|
|
169
|
+
const meta = website.meta ?? {};
|
|
170
|
+
if (website.favicon_url) {
|
|
171
|
+
parts.push(`<link rel="icon" href="${esc(website.favicon_url)}">`);
|
|
172
|
+
}
|
|
173
|
+
if (meta.webclip) {
|
|
174
|
+
parts.push(`<link rel="apple-touch-icon" sizes="180x180" href="${esc(meta.webclip)}">`);
|
|
175
|
+
}
|
|
176
|
+
if (meta.verification_google) {
|
|
177
|
+
parts.push(`<meta name="google-site-verification" content="${esc(meta.verification_google)}">`);
|
|
178
|
+
}
|
|
179
|
+
if (meta.verification_bing) {
|
|
180
|
+
parts.push(`<meta name="msvalidate.01" content="${esc(meta.verification_bing)}">`);
|
|
181
|
+
}
|
|
182
|
+
if (meta.structured_data_org) {
|
|
183
|
+
try {
|
|
184
|
+
const json = typeof meta.structured_data_org === "string" ? meta.structured_data_org : JSON.stringify(meta.structured_data_org);
|
|
185
|
+
parts.push(`<script type="application/ld+json">${json}${"<"}/script>`);
|
|
186
|
+
} catch {
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const plausibleId = website.plausible_site_id;
|
|
190
|
+
if (plausibleId) {
|
|
191
|
+
parts.push(`<script defer data-domain="${esc(plausibleId)}" src="https://plausible.io/js/script.js"><${"/"}script>`);
|
|
192
|
+
}
|
|
193
|
+
return parts.join("\n");
|
|
194
|
+
}
|
|
195
|
+
function generateSitemapXml(options) {
|
|
196
|
+
const { renderedPaths, canonicalBase, defaultChangefreq = "weekly", defaultPriority = "0.7" } = options;
|
|
197
|
+
const base = canonicalBase.replace(/\/$/, "");
|
|
198
|
+
const urls = renderedPaths.map((p) => {
|
|
199
|
+
const priority = p === "/" ? "1.0" : defaultPriority;
|
|
200
|
+
const changefreq = p === "/" ? "daily" : defaultChangefreq;
|
|
201
|
+
return ` <url>
|
|
202
|
+
<loc>${esc(base + p)}</loc>
|
|
203
|
+
<changefreq>${changefreq}</changefreq>
|
|
204
|
+
<priority>${priority}</priority>
|
|
205
|
+
</url>`;
|
|
206
|
+
});
|
|
207
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
208
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
209
|
+
${urls.join("\n")}
|
|
210
|
+
</urlset>
|
|
211
|
+
`;
|
|
212
|
+
}
|
|
213
|
+
function generateRobotsTxt(options) {
|
|
214
|
+
const { robotsTxt, canonicalBase, noindex } = options;
|
|
215
|
+
if (noindex) {
|
|
216
|
+
return `User-agent: *
|
|
217
|
+
Disallow: /
|
|
218
|
+
`;
|
|
219
|
+
}
|
|
220
|
+
const base = (canonicalBase || "").replace(/\/$/, "");
|
|
221
|
+
const sitemapLine = base ? `
|
|
222
|
+
Sitemap: ${base}/sitemap.xml
|
|
223
|
+
` : "";
|
|
224
|
+
if (robotsTxt) {
|
|
225
|
+
if (sitemapLine && !robotsTxt.toLowerCase().includes("sitemap:")) {
|
|
226
|
+
return robotsTxt.trimEnd() + "\n" + sitemapLine;
|
|
227
|
+
}
|
|
228
|
+
return robotsTxt;
|
|
229
|
+
}
|
|
230
|
+
return `User-agent: *
|
|
231
|
+
Allow: /
|
|
232
|
+
${sitemapLine}`;
|
|
233
|
+
}
|
|
234
|
+
function generateNetlifyRedirects(redirects) {
|
|
235
|
+
if (redirects.length === 0) return "";
|
|
236
|
+
return redirects.map((r) => `${r.from_path} ${r.to_path} ${r.status_code}`).join("\n") + "\n";
|
|
237
|
+
}
|
|
238
|
+
function stripTemplateSeoTags(template) {
|
|
239
|
+
return template.replace(/<title>[^<]*<\/title>/gi, "<!--ssg:title-->").replace(/<meta\s[^>]*name\s*=\s*["']description["'][^>]*>/gi, "").replace(/<meta\s[^>]*property\s*=\s*["']og:[^"']*["'][^>]*>/gi, "").replace(/<meta\s[^>]*(?:property|name)\s*=\s*["']twitter:[^"']*["'][^>]*>/gi, "").replace(/<link\s[^>]*rel\s*=\s*["']apple-touch-icon["'][^>]*>/gi, "").replace(/<link\s[^>]*rel\s*=\s*["']icon["'][^>]*>/gi, "").replace(/\n\s*\n\s*\n/g, "\n\n");
|
|
240
|
+
}
|
|
241
|
+
function esc(s) {
|
|
242
|
+
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
243
|
+
}
|
|
89
244
|
async function prerender({
|
|
90
245
|
root = process.cwd(),
|
|
91
246
|
clientOutDir = "dist/client",
|
|
@@ -95,13 +250,21 @@ async function prerender({
|
|
|
95
250
|
excludePaths = [],
|
|
96
251
|
failFast = false,
|
|
97
252
|
maxPages = 5e3,
|
|
98
|
-
mode = "dir"
|
|
253
|
+
mode = "dir",
|
|
254
|
+
website = null,
|
|
255
|
+
redirects = []
|
|
99
256
|
} = {}) {
|
|
100
257
|
const absRoot = path.resolve(root);
|
|
101
258
|
const absClient = path.resolve(absRoot, clientOutDir);
|
|
102
259
|
const absServerEntry = path.resolve(absRoot, serverEntry);
|
|
103
260
|
const templatePath = path.join(absClient, "index.html");
|
|
104
|
-
const
|
|
261
|
+
const rawTemplate = await fs.readFile(templatePath, "utf8");
|
|
262
|
+
let template = stripTemplateSeoTags(rawTemplate);
|
|
263
|
+
const siteHead = buildSiteHead(website);
|
|
264
|
+
if (siteHead) {
|
|
265
|
+
template = template.replace("</head>", `${siteHead}
|
|
266
|
+
</head>`);
|
|
267
|
+
}
|
|
105
268
|
const serverMod = await import(pathToFileURL(absServerEntry).href);
|
|
106
269
|
if (typeof serverMod.render !== "function") {
|
|
107
270
|
throw new TypeError(
|
|
@@ -130,7 +293,8 @@ async function prerender({
|
|
|
130
293
|
try {
|
|
131
294
|
const { html, head = "", htmlAttrs = "" } = await serverMod.render(urlPath, {
|
|
132
295
|
manifest,
|
|
133
|
-
template
|
|
296
|
+
template,
|
|
297
|
+
website
|
|
134
298
|
});
|
|
135
299
|
const outHtml = injectIntoTemplate(template, head, html, fontPreloads, htmlAttrs);
|
|
136
300
|
const outfile = outFilePath(absClient, urlPath, mode);
|
|
@@ -148,6 +312,31 @@ async function prerender({
|
|
|
148
312
|
`, err.stack ?? err);
|
|
149
313
|
}
|
|
150
314
|
}
|
|
315
|
+
const websiteMeta = (website == null ? void 0 : website.meta) ?? {};
|
|
316
|
+
const canonicalBase = (websiteMeta.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
317
|
+
if (canonicalBase && rendered.length > 0) {
|
|
318
|
+
const sitemap = generateSitemapXml({ renderedPaths: rendered, canonicalBase });
|
|
319
|
+
await fs.writeFile(path.join(absClient, "sitemap.xml"), sitemap, "utf8");
|
|
320
|
+
console.log(` Generated sitemap.xml (${rendered.length} URLs)`);
|
|
321
|
+
}
|
|
322
|
+
const robotsTxt = generateRobotsTxt({
|
|
323
|
+
robotsTxt: website == null ? void 0 : website.robots_txt,
|
|
324
|
+
canonicalBase,
|
|
325
|
+
noindex: websiteMeta.noindex
|
|
326
|
+
});
|
|
327
|
+
await fs.writeFile(path.join(absClient, "robots.txt"), robotsTxt, "utf8");
|
|
328
|
+
console.log(" Generated robots.txt");
|
|
329
|
+
if (redirects.length > 0) {
|
|
330
|
+
const redirectsContent = generateNetlifyRedirects(redirects);
|
|
331
|
+
const redirectsPath = path.join(absClient, "_redirects");
|
|
332
|
+
let existing = "";
|
|
333
|
+
try {
|
|
334
|
+
existing = await fs.readFile(redirectsPath, "utf8");
|
|
335
|
+
} catch {
|
|
336
|
+
}
|
|
337
|
+
await fs.writeFile(redirectsPath, redirectsContent + existing, "utf8");
|
|
338
|
+
console.log(` Generated _redirects (${redirects.length} rules)`);
|
|
339
|
+
}
|
|
151
340
|
return {
|
|
152
341
|
rendered,
|
|
153
342
|
failures,
|
|
@@ -233,6 +422,9 @@ function injectIntoTemplate(template, head, appHtml, fontPreloads, htmlAttrs = "
|
|
|
233
422
|
</head>`);
|
|
234
423
|
}
|
|
235
424
|
if (head) {
|
|
425
|
+
if (/<title>/.test(head)) {
|
|
426
|
+
out = out.replace("<!--ssg:title-->", "");
|
|
427
|
+
}
|
|
236
428
|
const descTagRe = /<meta\s[^>]*name\s*=\s*["']description["'][^>]*>/gi;
|
|
237
429
|
const descMatches = [...head.matchAll(descTagRe)];
|
|
238
430
|
if (descMatches.length > 1) {
|
|
@@ -276,7 +468,13 @@ function discoverInternalLinks(html) {
|
|
|
276
468
|
return [...out];
|
|
277
469
|
}
|
|
278
470
|
export {
|
|
279
|
-
|
|
471
|
+
fetchCmsSiteData as a,
|
|
472
|
+
buildPageHead as b,
|
|
473
|
+
prerender as c,
|
|
474
|
+
buildSiteHead as d,
|
|
475
|
+
generateRobotsTxt as e,
|
|
280
476
|
fetchCmsPrerenderPaths as f,
|
|
477
|
+
generateNetlifyRedirects as g,
|
|
478
|
+
generateSitemapXml as h,
|
|
281
479
|
polyfillBloxSsgGlobals as p
|
|
282
480
|
};
|
|
@@ -25,18 +25,43 @@ const fs = require("node:fs/promises");
|
|
|
25
25
|
const path = require("node:path");
|
|
26
26
|
const process = require("node:process");
|
|
27
27
|
const node_url = require("node:url");
|
|
28
|
-
async function
|
|
28
|
+
async function fetchCmsSiteData(apiBase, websiteName) {
|
|
29
29
|
const sitesRes = await fetch(`${apiBase}/cms/websites`);
|
|
30
30
|
const sitesData = await sitesRes.json();
|
|
31
31
|
const sites = Array.isArray(sitesData) ? sitesData : sitesData.data ?? [];
|
|
32
32
|
const site = sites.find((s) => s.name === websiteName);
|
|
33
33
|
if ((site == null ? void 0 : site.id) == null || site.id === "") throw new Error(`Website "${websiteName}" not found at ${apiBase}`);
|
|
34
|
-
|
|
34
|
+
let website = site;
|
|
35
|
+
try {
|
|
36
|
+
const wRes = await fetch(`${apiBase}/cms/websites/${site.id}`);
|
|
37
|
+
if (wRes.ok) website = await wRes.json();
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
const pagesRes = await fetch(`${apiBase}/cms/websites/${site.id}/pages?locale=${website.default_locale || "en"}`);
|
|
35
41
|
const pagesData = await pagesRes.json();
|
|
36
42
|
const pages = Array.isArray(pagesData) ? pagesData : pagesData.data ?? [];
|
|
43
|
+
const paths = await expandRoutes(apiBase, pages);
|
|
44
|
+
let redirects = [];
|
|
45
|
+
try {
|
|
46
|
+
const rRes = await fetch(`${apiBase}/cms/websites/${site.id}/redirects`);
|
|
47
|
+
if (rRes.ok) {
|
|
48
|
+
const rData = await rRes.json();
|
|
49
|
+
const items = Array.isArray(rData) ? rData : rData.data ?? [];
|
|
50
|
+
redirects = items.filter((r) => r.from_path && r.to_path);
|
|
51
|
+
}
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
return { websiteId: site.id, website, paths, redirects };
|
|
55
|
+
}
|
|
56
|
+
async function fetchCmsPrerenderPaths(apiBase, websiteName) {
|
|
57
|
+
const { paths } = await fetchCmsSiteData(apiBase, websiteName);
|
|
58
|
+
return paths;
|
|
59
|
+
}
|
|
60
|
+
async function expandRoutes(apiBase, pages) {
|
|
37
61
|
const routes = [];
|
|
38
62
|
for (const page of pages) {
|
|
39
63
|
const slug = page.slug ?? "/";
|
|
64
|
+
if (page.status && page.status !== "published") continue;
|
|
40
65
|
if (slug.includes(":") && page.data_bindings) {
|
|
41
66
|
for (const [, binding] of Object.entries(page.data_bindings)) {
|
|
42
67
|
const b = binding;
|
|
@@ -50,7 +75,10 @@ async function fetchCmsPrerenderPaths(apiBase, websiteName) {
|
|
|
50
75
|
for (const item of items) {
|
|
51
76
|
const bindValue = item[b.bind_by];
|
|
52
77
|
if (bindValue != null && bindValue !== "") {
|
|
53
|
-
const concrete = slug.replace(
|
|
78
|
+
const concrete = slug.replace(
|
|
79
|
+
/:([a-z_]+)/g,
|
|
80
|
+
(_m, p) => p === b.bind_by ? String(bindValue) : String(item[p] ?? "")
|
|
81
|
+
);
|
|
54
82
|
routes.push(concrete);
|
|
55
83
|
}
|
|
56
84
|
}
|
|
@@ -109,6 +137,133 @@ async function polyfillBloxSsgGlobals(options) {
|
|
|
109
137
|
g.window.location = _win.location;
|
|
110
138
|
g.window.document = _win.document;
|
|
111
139
|
}
|
|
140
|
+
function buildPageHead(options) {
|
|
141
|
+
const { url, resolvedData, website, stateScript } = options;
|
|
142
|
+
const parts = [];
|
|
143
|
+
const meta = (website == null ? void 0 : website.meta) ?? {};
|
|
144
|
+
const page = resolvedData == null ? void 0 : resolvedData.page;
|
|
145
|
+
const title = (page == null ? void 0 : page.meta_title) || ((page == null ? void 0 : page.title) && meta.og_site_name ? `${page.title} · ${meta.og_site_name}` : null) || (page == null ? void 0 : page.title) || meta.default_meta_title;
|
|
146
|
+
if (title) {
|
|
147
|
+
parts.push(`<title>${esc(title)}</title>`);
|
|
148
|
+
}
|
|
149
|
+
const description = (page == null ? void 0 : page.meta_description) || meta.default_meta_description;
|
|
150
|
+
if (description) {
|
|
151
|
+
parts.push(`<meta name="description" content="${esc(description)}">`);
|
|
152
|
+
}
|
|
153
|
+
const canonicalBase = (meta.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
154
|
+
if (canonicalBase) {
|
|
155
|
+
parts.push(`<link rel="canonical" href="${esc(canonicalBase + url)}">`);
|
|
156
|
+
}
|
|
157
|
+
const ogTitle = (page == null ? void 0 : page.meta_title) || (page == null ? void 0 : page.title) || meta.og_site_name || meta.default_meta_title;
|
|
158
|
+
const ogDesc = (page == null ? void 0 : page.meta_description) || meta.og_description || meta.default_meta_description;
|
|
159
|
+
const ogImage = (page == null ? void 0 : page.og_image) || meta.default_og_image;
|
|
160
|
+
const ogType = meta.og_type || "website";
|
|
161
|
+
if (ogTitle) parts.push(`<meta property="og:title" content="${esc(ogTitle)}">`);
|
|
162
|
+
if (ogDesc) parts.push(`<meta property="og:description" content="${esc(ogDesc)}">`);
|
|
163
|
+
if (ogImage) parts.push(`<meta property="og:image" content="${esc(ogImage)}">`);
|
|
164
|
+
parts.push(`<meta property="og:type" content="${esc(ogType)}">`);
|
|
165
|
+
if (canonicalBase) parts.push(`<meta property="og:url" content="${esc(canonicalBase + url)}">`);
|
|
166
|
+
if (meta.og_site_name) parts.push(`<meta property="og:site_name" content="${esc(meta.og_site_name)}">`);
|
|
167
|
+
const twitterCard = meta.twitter_card || "summary_large_image";
|
|
168
|
+
parts.push(`<meta name="twitter:card" content="${esc(twitterCard)}">`);
|
|
169
|
+
if (ogTitle) parts.push(`<meta name="twitter:title" content="${esc(ogTitle)}">`);
|
|
170
|
+
if (ogDesc) parts.push(`<meta name="twitter:description" content="${esc(ogDesc)}">`);
|
|
171
|
+
if (ogImage) parts.push(`<meta name="twitter:image" content="${esc(ogImage)}">`);
|
|
172
|
+
if (meta.twitter_site) parts.push(`<meta name="twitter:site" content="${esc(meta.twitter_site)}">`);
|
|
173
|
+
const alternates = resolvedData == null ? void 0 : resolvedData.alternates;
|
|
174
|
+
if (alternates && canonicalBase) {
|
|
175
|
+
for (const [locale, slug] of Object.entries(alternates)) {
|
|
176
|
+
parts.push(`<link rel="alternate" hreflang="${esc(locale)}" href="${esc(canonicalBase + slug)}">`);
|
|
177
|
+
}
|
|
178
|
+
const defaultSlug = alternates[(website == null ? void 0 : website.default_locale) ?? "en"] ?? url;
|
|
179
|
+
parts.push(`<link rel="alternate" hreflang="x-default" href="${esc(canonicalBase + defaultSlug)}">`);
|
|
180
|
+
}
|
|
181
|
+
if (meta.noindex) {
|
|
182
|
+
parts.push('<meta name="robots" content="noindex, nofollow">');
|
|
183
|
+
}
|
|
184
|
+
if (stateScript) {
|
|
185
|
+
parts.push(stateScript);
|
|
186
|
+
}
|
|
187
|
+
return parts.join("\n");
|
|
188
|
+
}
|
|
189
|
+
function buildSiteHead(website) {
|
|
190
|
+
if (!website) return "";
|
|
191
|
+
const parts = [];
|
|
192
|
+
const meta = website.meta ?? {};
|
|
193
|
+
if (website.favicon_url) {
|
|
194
|
+
parts.push(`<link rel="icon" href="${esc(website.favicon_url)}">`);
|
|
195
|
+
}
|
|
196
|
+
if (meta.webclip) {
|
|
197
|
+
parts.push(`<link rel="apple-touch-icon" sizes="180x180" href="${esc(meta.webclip)}">`);
|
|
198
|
+
}
|
|
199
|
+
if (meta.verification_google) {
|
|
200
|
+
parts.push(`<meta name="google-site-verification" content="${esc(meta.verification_google)}">`);
|
|
201
|
+
}
|
|
202
|
+
if (meta.verification_bing) {
|
|
203
|
+
parts.push(`<meta name="msvalidate.01" content="${esc(meta.verification_bing)}">`);
|
|
204
|
+
}
|
|
205
|
+
if (meta.structured_data_org) {
|
|
206
|
+
try {
|
|
207
|
+
const json = typeof meta.structured_data_org === "string" ? meta.structured_data_org : JSON.stringify(meta.structured_data_org);
|
|
208
|
+
parts.push(`<script type="application/ld+json">${json}${"<"}/script>`);
|
|
209
|
+
} catch {
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const plausibleId = website.plausible_site_id;
|
|
213
|
+
if (plausibleId) {
|
|
214
|
+
parts.push(`<script defer data-domain="${esc(plausibleId)}" src="https://plausible.io/js/script.js"><${"/"}script>`);
|
|
215
|
+
}
|
|
216
|
+
return parts.join("\n");
|
|
217
|
+
}
|
|
218
|
+
function generateSitemapXml(options) {
|
|
219
|
+
const { renderedPaths, canonicalBase, defaultChangefreq = "weekly", defaultPriority = "0.7" } = options;
|
|
220
|
+
const base = canonicalBase.replace(/\/$/, "");
|
|
221
|
+
const urls = renderedPaths.map((p) => {
|
|
222
|
+
const priority = p === "/" ? "1.0" : defaultPriority;
|
|
223
|
+
const changefreq = p === "/" ? "daily" : defaultChangefreq;
|
|
224
|
+
return ` <url>
|
|
225
|
+
<loc>${esc(base + p)}</loc>
|
|
226
|
+
<changefreq>${changefreq}</changefreq>
|
|
227
|
+
<priority>${priority}</priority>
|
|
228
|
+
</url>`;
|
|
229
|
+
});
|
|
230
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
231
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
232
|
+
${urls.join("\n")}
|
|
233
|
+
</urlset>
|
|
234
|
+
`;
|
|
235
|
+
}
|
|
236
|
+
function generateRobotsTxt(options) {
|
|
237
|
+
const { robotsTxt, canonicalBase, noindex } = options;
|
|
238
|
+
if (noindex) {
|
|
239
|
+
return `User-agent: *
|
|
240
|
+
Disallow: /
|
|
241
|
+
`;
|
|
242
|
+
}
|
|
243
|
+
const base = (canonicalBase || "").replace(/\/$/, "");
|
|
244
|
+
const sitemapLine = base ? `
|
|
245
|
+
Sitemap: ${base}/sitemap.xml
|
|
246
|
+
` : "";
|
|
247
|
+
if (robotsTxt) {
|
|
248
|
+
if (sitemapLine && !robotsTxt.toLowerCase().includes("sitemap:")) {
|
|
249
|
+
return robotsTxt.trimEnd() + "\n" + sitemapLine;
|
|
250
|
+
}
|
|
251
|
+
return robotsTxt;
|
|
252
|
+
}
|
|
253
|
+
return `User-agent: *
|
|
254
|
+
Allow: /
|
|
255
|
+
${sitemapLine}`;
|
|
256
|
+
}
|
|
257
|
+
function generateNetlifyRedirects(redirects) {
|
|
258
|
+
if (redirects.length === 0) return "";
|
|
259
|
+
return redirects.map((r) => `${r.from_path} ${r.to_path} ${r.status_code}`).join("\n") + "\n";
|
|
260
|
+
}
|
|
261
|
+
function stripTemplateSeoTags(template) {
|
|
262
|
+
return template.replace(/<title>[^<]*<\/title>/gi, "<!--ssg:title-->").replace(/<meta\s[^>]*name\s*=\s*["']description["'][^>]*>/gi, "").replace(/<meta\s[^>]*property\s*=\s*["']og:[^"']*["'][^>]*>/gi, "").replace(/<meta\s[^>]*(?:property|name)\s*=\s*["']twitter:[^"']*["'][^>]*>/gi, "").replace(/<link\s[^>]*rel\s*=\s*["']apple-touch-icon["'][^>]*>/gi, "").replace(/<link\s[^>]*rel\s*=\s*["']icon["'][^>]*>/gi, "").replace(/\n\s*\n\s*\n/g, "\n\n");
|
|
263
|
+
}
|
|
264
|
+
function esc(s) {
|
|
265
|
+
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
266
|
+
}
|
|
112
267
|
async function prerender({
|
|
113
268
|
root = process.cwd(),
|
|
114
269
|
clientOutDir = "dist/client",
|
|
@@ -118,13 +273,21 @@ async function prerender({
|
|
|
118
273
|
excludePaths = [],
|
|
119
274
|
failFast = false,
|
|
120
275
|
maxPages = 5e3,
|
|
121
|
-
mode = "dir"
|
|
276
|
+
mode = "dir",
|
|
277
|
+
website = null,
|
|
278
|
+
redirects = []
|
|
122
279
|
} = {}) {
|
|
123
280
|
const absRoot = path.resolve(root);
|
|
124
281
|
const absClient = path.resolve(absRoot, clientOutDir);
|
|
125
282
|
const absServerEntry = path.resolve(absRoot, serverEntry);
|
|
126
283
|
const templatePath = path.join(absClient, "index.html");
|
|
127
|
-
const
|
|
284
|
+
const rawTemplate = await fs.readFile(templatePath, "utf8");
|
|
285
|
+
let template = stripTemplateSeoTags(rawTemplate);
|
|
286
|
+
const siteHead = buildSiteHead(website);
|
|
287
|
+
if (siteHead) {
|
|
288
|
+
template = template.replace("</head>", `${siteHead}
|
|
289
|
+
</head>`);
|
|
290
|
+
}
|
|
128
291
|
const serverMod = await import(node_url.pathToFileURL(absServerEntry).href);
|
|
129
292
|
if (typeof serverMod.render !== "function") {
|
|
130
293
|
throw new TypeError(
|
|
@@ -153,7 +316,8 @@ async function prerender({
|
|
|
153
316
|
try {
|
|
154
317
|
const { html, head = "", htmlAttrs = "" } = await serverMod.render(urlPath, {
|
|
155
318
|
manifest,
|
|
156
|
-
template
|
|
319
|
+
template,
|
|
320
|
+
website
|
|
157
321
|
});
|
|
158
322
|
const outHtml = injectIntoTemplate(template, head, html, fontPreloads, htmlAttrs);
|
|
159
323
|
const outfile = outFilePath(absClient, urlPath, mode);
|
|
@@ -171,6 +335,31 @@ async function prerender({
|
|
|
171
335
|
`, err.stack ?? err);
|
|
172
336
|
}
|
|
173
337
|
}
|
|
338
|
+
const websiteMeta = (website == null ? void 0 : website.meta) ?? {};
|
|
339
|
+
const canonicalBase = (websiteMeta.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
340
|
+
if (canonicalBase && rendered.length > 0) {
|
|
341
|
+
const sitemap = generateSitemapXml({ renderedPaths: rendered, canonicalBase });
|
|
342
|
+
await fs.writeFile(path.join(absClient, "sitemap.xml"), sitemap, "utf8");
|
|
343
|
+
console.log(` Generated sitemap.xml (${rendered.length} URLs)`);
|
|
344
|
+
}
|
|
345
|
+
const robotsTxt = generateRobotsTxt({
|
|
346
|
+
robotsTxt: website == null ? void 0 : website.robots_txt,
|
|
347
|
+
canonicalBase,
|
|
348
|
+
noindex: websiteMeta.noindex
|
|
349
|
+
});
|
|
350
|
+
await fs.writeFile(path.join(absClient, "robots.txt"), robotsTxt, "utf8");
|
|
351
|
+
console.log(" Generated robots.txt");
|
|
352
|
+
if (redirects.length > 0) {
|
|
353
|
+
const redirectsContent = generateNetlifyRedirects(redirects);
|
|
354
|
+
const redirectsPath = path.join(absClient, "_redirects");
|
|
355
|
+
let existing = "";
|
|
356
|
+
try {
|
|
357
|
+
existing = await fs.readFile(redirectsPath, "utf8");
|
|
358
|
+
} catch {
|
|
359
|
+
}
|
|
360
|
+
await fs.writeFile(redirectsPath, redirectsContent + existing, "utf8");
|
|
361
|
+
console.log(` Generated _redirects (${redirects.length} rules)`);
|
|
362
|
+
}
|
|
174
363
|
return {
|
|
175
364
|
rendered,
|
|
176
365
|
failures,
|
|
@@ -256,6 +445,9 @@ function injectIntoTemplate(template, head, appHtml, fontPreloads, htmlAttrs = "
|
|
|
256
445
|
</head>`);
|
|
257
446
|
}
|
|
258
447
|
if (head) {
|
|
448
|
+
if (/<title>/.test(head)) {
|
|
449
|
+
out = out.replace("<!--ssg:title-->", "");
|
|
450
|
+
}
|
|
259
451
|
const descTagRe = /<meta\s[^>]*name\s*=\s*["']description["'][^>]*>/gi;
|
|
260
452
|
const descMatches = [...head.matchAll(descTagRe)];
|
|
261
453
|
if (descMatches.length > 1) {
|
|
@@ -298,6 +490,12 @@ function discoverInternalLinks(html) {
|
|
|
298
490
|
}
|
|
299
491
|
return [...out];
|
|
300
492
|
}
|
|
493
|
+
exports.buildPageHead = buildPageHead;
|
|
494
|
+
exports.buildSiteHead = buildSiteHead;
|
|
301
495
|
exports.fetchCmsPrerenderPaths = fetchCmsPrerenderPaths;
|
|
496
|
+
exports.fetchCmsSiteData = fetchCmsSiteData;
|
|
497
|
+
exports.generateNetlifyRedirects = generateNetlifyRedirects;
|
|
498
|
+
exports.generateRobotsTxt = generateRobotsTxt;
|
|
499
|
+
exports.generateSitemapXml = generateSitemapXml;
|
|
302
500
|
exports.polyfillBloxSsgGlobals = polyfillBloxSsgGlobals;
|
|
303
501
|
exports.prerender = prerender;
|
package/dist/ssg/cli.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
"use strict";
|
|
3
3
|
const process = require("node:process");
|
|
4
|
-
const prerender = require("../prerender-
|
|
4
|
+
const prerender = require("../prerender-Br-vA3A0.cjs");
|
|
5
5
|
async function resolveApiBase(mode) {
|
|
6
6
|
if (process.env.BAGELINK_API_URL != null && process.env.BAGELINK_API_URL !== "") {
|
|
7
7
|
return { apiBase: process.env.BAGELINK_API_URL };
|
|
@@ -72,11 +72,17 @@ Environment:
|
|
|
72
72
|
const websiteName = process.env.WEBSITE_NAME ?? configWebsiteName ?? "default";
|
|
73
73
|
console.log(`Fetching routes from ${apiBase} (mode: ${mode}, site: ${websiteName})…`);
|
|
74
74
|
let paths = [];
|
|
75
|
+
let website = null;
|
|
76
|
+
let redirects = [];
|
|
75
77
|
try {
|
|
76
|
-
|
|
78
|
+
const siteData = await prerender.fetchCmsSiteData(apiBase, websiteName);
|
|
79
|
+
paths = siteData.paths;
|
|
80
|
+
website = siteData.website;
|
|
81
|
+
redirects = siteData.redirects;
|
|
77
82
|
console.log(` Found ${paths.length} CMS routes`);
|
|
83
|
+
if (redirects.length > 0) console.log(` Found ${redirects.length} redirects`);
|
|
78
84
|
} catch (err) {
|
|
79
|
-
console.error(" Failed to fetch CMS
|
|
85
|
+
console.error(" Failed to fetch CMS data:", err.message);
|
|
80
86
|
paths = ["/"];
|
|
81
87
|
}
|
|
82
88
|
for (const p of extraPaths) {
|
|
@@ -92,7 +98,9 @@ Environment:
|
|
|
92
98
|
crawl,
|
|
93
99
|
excludePaths,
|
|
94
100
|
maxPages: 5e3,
|
|
95
|
-
mode: "file"
|
|
101
|
+
mode: "file",
|
|
102
|
+
website,
|
|
103
|
+
redirects
|
|
96
104
|
});
|
|
97
105
|
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
98
106
|
console.log(`
|
package/dist/ssg/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import process from "node:process";
|
|
3
|
-
import { p as polyfillBloxSsgGlobals,
|
|
3
|
+
import { p as polyfillBloxSsgGlobals, a as fetchCmsSiteData, c as prerender } from "../prerender-1I_qD2kp.js";
|
|
4
4
|
async function resolveApiBase(mode) {
|
|
5
5
|
if (process.env.BAGELINK_API_URL != null && process.env.BAGELINK_API_URL !== "") {
|
|
6
6
|
return { apiBase: process.env.BAGELINK_API_URL };
|
|
@@ -71,11 +71,17 @@ Environment:
|
|
|
71
71
|
const websiteName = process.env.WEBSITE_NAME ?? configWebsiteName ?? "default";
|
|
72
72
|
console.log(`Fetching routes from ${apiBase} (mode: ${mode}, site: ${websiteName})…`);
|
|
73
73
|
let paths = [];
|
|
74
|
+
let website = null;
|
|
75
|
+
let redirects = [];
|
|
74
76
|
try {
|
|
75
|
-
|
|
77
|
+
const siteData = await fetchCmsSiteData(apiBase, websiteName);
|
|
78
|
+
paths = siteData.paths;
|
|
79
|
+
website = siteData.website;
|
|
80
|
+
redirects = siteData.redirects;
|
|
76
81
|
console.log(` Found ${paths.length} CMS routes`);
|
|
82
|
+
if (redirects.length > 0) console.log(` Found ${redirects.length} redirects`);
|
|
77
83
|
} catch (err) {
|
|
78
|
-
console.error(" Failed to fetch CMS
|
|
84
|
+
console.error(" Failed to fetch CMS data:", err.message);
|
|
79
85
|
paths = ["/"];
|
|
80
86
|
}
|
|
81
87
|
for (const p of extraPaths) {
|
|
@@ -91,7 +97,9 @@ Environment:
|
|
|
91
97
|
crawl,
|
|
92
98
|
excludePaths,
|
|
93
99
|
maxPages: 5e3,
|
|
94
|
-
mode: "file"
|
|
100
|
+
mode: "file",
|
|
101
|
+
website,
|
|
102
|
+
redirects
|
|
95
103
|
});
|
|
96
104
|
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(2);
|
|
97
105
|
console.log(`
|
package/dist/ssg/cms-routes.d.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
import { WebsiteRead } from '../api/types';
|
|
2
|
+
import { RedirectEntry } from './seo';
|
|
3
|
+
export interface CmsSiteData {
|
|
4
|
+
websiteId: string;
|
|
5
|
+
website: WebsiteRead;
|
|
6
|
+
paths: string[];
|
|
7
|
+
redirects: RedirectEntry[];
|
|
8
|
+
}
|
|
1
9
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
10
|
+
* Fetch everything the SSG needs from the CMS in one go:
|
|
11
|
+
* website settings, page routes, and redirects.
|
|
12
|
+
*/
|
|
13
|
+
export declare function fetchCmsSiteData(apiBase: string, websiteName: string): Promise<CmsSiteData>;
|
|
14
|
+
/**
|
|
15
|
+
* Legacy compat: fetch only prerender paths (no website/redirect data).
|
|
6
16
|
*/
|
|
7
17
|
export declare function fetchCmsPrerenderPaths(apiBase: string, websiteName: string): Promise<string[]>;
|
|
8
18
|
//# sourceMappingURL=cms-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cms-routes.d.ts","sourceRoot":"","sources":["../../src/ssg/cms-routes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC3C,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"cms-routes.d.ts","sourceRoot":"","sources":["../../src/ssg/cms-routes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAY1C,MAAM,WAAW,WAAW;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,WAAW,CAAA;IACpB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,EAAE,aAAa,EAAE,CAAA;CAC1B;AAMD;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,CAqCtB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC3C,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB"}
|
package/dist/ssg/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const prerender = require("../prerender-
|
|
3
|
+
const prerender = require("../prerender-Br-vA3A0.cjs");
|
|
4
4
|
const constants = require("../constants-fZvybj0k.cjs");
|
|
5
5
|
const ssg_client = require("./client.cjs");
|
|
6
6
|
async function renderBloxSsgPage(options) {
|
|
@@ -9,7 +9,8 @@ async function renderBloxSsgPage(options) {
|
|
|
9
9
|
resolvedData,
|
|
10
10
|
renderToString,
|
|
11
11
|
createAppForUrl,
|
|
12
|
-
stateWindowKey = constants.BLOX_STATE_WINDOW_KEY
|
|
12
|
+
stateWindowKey = constants.BLOX_STATE_WINDOW_KEY,
|
|
13
|
+
website = null
|
|
13
14
|
} = options;
|
|
14
15
|
const g = globalThis;
|
|
15
16
|
const prevState = g[stateWindowKey];
|
|
@@ -21,8 +22,16 @@ async function renderBloxSsgPage(options) {
|
|
|
21
22
|
await router.push(url);
|
|
22
23
|
await router.isReady();
|
|
23
24
|
const html = await renderToString(app);
|
|
24
|
-
const
|
|
25
|
-
|
|
25
|
+
const stateScript = resolvedData != null ? `<script>window[${JSON.stringify(stateWindowKey)}]=${JSON.stringify({ [url]: resolvedData })};${"<"}/script>` : "";
|
|
26
|
+
const head = prerender.buildPageHead({
|
|
27
|
+
url,
|
|
28
|
+
resolvedData,
|
|
29
|
+
website,
|
|
30
|
+
stateScript
|
|
31
|
+
});
|
|
32
|
+
const lang = (website == null ? void 0 : website.default_locale) || "en";
|
|
33
|
+
const htmlAttrs = `lang="${lang}"`;
|
|
34
|
+
return { html, head, htmlAttrs };
|
|
26
35
|
} finally {
|
|
27
36
|
if (prevState !== void 0) {
|
|
28
37
|
g[stateWindowKey] = prevState;
|
|
@@ -31,7 +40,13 @@ async function renderBloxSsgPage(options) {
|
|
|
31
40
|
}
|
|
32
41
|
}
|
|
33
42
|
}
|
|
43
|
+
exports.buildPageHead = prerender.buildPageHead;
|
|
44
|
+
exports.buildSiteHead = prerender.buildSiteHead;
|
|
34
45
|
exports.fetchCmsPrerenderPaths = prerender.fetchCmsPrerenderPaths;
|
|
46
|
+
exports.fetchCmsSiteData = prerender.fetchCmsSiteData;
|
|
47
|
+
exports.generateNetlifyRedirects = prerender.generateNetlifyRedirects;
|
|
48
|
+
exports.generateRobotsTxt = prerender.generateRobotsTxt;
|
|
49
|
+
exports.generateSitemapXml = prerender.generateSitemapXml;
|
|
35
50
|
exports.polyfillBloxSsgGlobals = prerender.polyfillBloxSsgGlobals;
|
|
36
51
|
exports.prerender = prerender.prerender;
|
|
37
52
|
exports.BLOX_STATE_WINDOW_KEY = constants.BLOX_STATE_WINDOW_KEY;
|
package/dist/ssg/index.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
export { fetchCmsPrerenderPaths } from './cms-routes';
|
|
1
|
+
export { fetchCmsPrerenderPaths, fetchCmsSiteData } from './cms-routes';
|
|
2
|
+
export type { CmsSiteData } from './cms-routes';
|
|
2
3
|
/**
|
|
3
4
|
* @bagelink/blox/ssg — Static Site Generation helpers for Blox CMS sites.
|
|
4
5
|
*
|
|
5
6
|
* Provides everything needed to prerender a Vue + Blox app at build time:
|
|
6
7
|
* - Browser global polyfills for Node.js
|
|
7
8
|
* - CMS route discovery (including template page expansion via data_bindings)
|
|
8
|
-
* -
|
|
9
|
+
* - Page renderer with state embedding and full SEO head
|
|
9
10
|
* - Client-side fetch interceptor for zero-API-call hydration
|
|
10
11
|
* - Full prerender orchestrator with crawl support
|
|
12
|
+
* - SEO asset generation (sitemap.xml, robots.txt, _redirects)
|
|
11
13
|
*/
|
|
12
14
|
export { BLOX_STATE_WINDOW_KEY } from './constants';
|
|
13
15
|
export { polyfillBloxSsgGlobals } from './polyfill-node';
|
|
@@ -15,5 +17,7 @@ export { prerender } from './prerender';
|
|
|
15
17
|
export type { PrerenderOptions, PrerenderResult, RenderContext, RenderResult } from './prerender';
|
|
16
18
|
export { renderBloxSsgPage } from './render-resolved-page';
|
|
17
19
|
export type { BloxSsgRouterLike } from './render-resolved-page';
|
|
20
|
+
export { buildPageHead, buildSiteHead, generateNetlifyRedirects, generateRobotsTxt, generateSitemapXml } from './seo';
|
|
21
|
+
export type { RedirectEntry, SeoPageData, WebsiteMeta } from './seo';
|
|
18
22
|
export { installBloxStateCache } from './state-cache';
|
|
19
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/ssg/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ssg/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ssg/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACvE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C;;;;;;;;;;GAUG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAA;AACrH,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/ssg/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as buildPageHead } from "../prerender-1I_qD2kp.js";
|
|
2
|
+
import { d, f, a, g, e, h, p, c } from "../prerender-1I_qD2kp.js";
|
|
2
3
|
import { B as BLOX_STATE_WINDOW_KEY } from "../constants-BIbQhd3z.js";
|
|
3
4
|
import { installBloxStateCache } from "./client.mjs";
|
|
4
5
|
async function renderBloxSsgPage(options) {
|
|
@@ -7,33 +8,48 @@ async function renderBloxSsgPage(options) {
|
|
|
7
8
|
resolvedData,
|
|
8
9
|
renderToString,
|
|
9
10
|
createAppForUrl,
|
|
10
|
-
stateWindowKey = BLOX_STATE_WINDOW_KEY
|
|
11
|
+
stateWindowKey = BLOX_STATE_WINDOW_KEY,
|
|
12
|
+
website = null
|
|
11
13
|
} = options;
|
|
12
|
-
const
|
|
13
|
-
const prevState =
|
|
14
|
+
const g2 = globalThis;
|
|
15
|
+
const prevState = g2[stateWindowKey];
|
|
14
16
|
if (resolvedData != null) {
|
|
15
|
-
|
|
17
|
+
g2[stateWindowKey] = { [url]: resolvedData };
|
|
16
18
|
}
|
|
17
19
|
try {
|
|
18
20
|
const { app, router } = createAppForUrl(url);
|
|
19
21
|
await router.push(url);
|
|
20
22
|
await router.isReady();
|
|
21
23
|
const html = await renderToString(app);
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
+
const stateScript = resolvedData != null ? `<script>window[${JSON.stringify(stateWindowKey)}]=${JSON.stringify({ [url]: resolvedData })};${"<"}/script>` : "";
|
|
25
|
+
const head = buildPageHead({
|
|
26
|
+
url,
|
|
27
|
+
resolvedData,
|
|
28
|
+
website,
|
|
29
|
+
stateScript
|
|
30
|
+
});
|
|
31
|
+
const lang = (website == null ? void 0 : website.default_locale) || "en";
|
|
32
|
+
const htmlAttrs = `lang="${lang}"`;
|
|
33
|
+
return { html, head, htmlAttrs };
|
|
24
34
|
} finally {
|
|
25
35
|
if (prevState !== void 0) {
|
|
26
|
-
|
|
36
|
+
g2[stateWindowKey] = prevState;
|
|
27
37
|
} else {
|
|
28
|
-
delete
|
|
38
|
+
delete g2[stateWindowKey];
|
|
29
39
|
}
|
|
30
40
|
}
|
|
31
41
|
}
|
|
32
42
|
export {
|
|
33
43
|
BLOX_STATE_WINDOW_KEY,
|
|
44
|
+
buildPageHead,
|
|
45
|
+
d as buildSiteHead,
|
|
34
46
|
f as fetchCmsPrerenderPaths,
|
|
47
|
+
a as fetchCmsSiteData,
|
|
48
|
+
g as generateNetlifyRedirects,
|
|
49
|
+
e as generateRobotsTxt,
|
|
50
|
+
h as generateSitemapXml,
|
|
35
51
|
installBloxStateCache,
|
|
36
52
|
p as polyfillBloxSsgGlobals,
|
|
37
|
-
|
|
53
|
+
c as prerender,
|
|
38
54
|
renderBloxSsgPage
|
|
39
55
|
};
|
package/dist/ssg/prerender.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { WebsiteRead } from '../api/types';
|
|
2
|
+
import { RedirectEntry } from './seo';
|
|
1
3
|
type ExcludeRule = string | RegExp | ((path: string) => boolean);
|
|
2
4
|
export interface PrerenderOptions {
|
|
3
5
|
root?: string;
|
|
@@ -9,10 +11,16 @@ export interface PrerenderOptions {
|
|
|
9
11
|
failFast?: boolean;
|
|
10
12
|
maxPages?: number;
|
|
11
13
|
mode?: 'dir' | 'file';
|
|
14
|
+
/** Website settings for SEO injection. */
|
|
15
|
+
website?: WebsiteRead | null;
|
|
16
|
+
/** Redirects to write as _redirects (Netlify). */
|
|
17
|
+
redirects?: RedirectEntry[];
|
|
12
18
|
}
|
|
13
19
|
export interface RenderContext {
|
|
14
20
|
manifest: Record<string, string[]> | null;
|
|
15
21
|
template: string;
|
|
22
|
+
/** Website settings passed through to the render function. */
|
|
23
|
+
website?: WebsiteRead | null;
|
|
16
24
|
}
|
|
17
25
|
export interface RenderResult {
|
|
18
26
|
html: string;
|
|
@@ -38,7 +46,9 @@ export interface PrerenderResult {
|
|
|
38
46
|
* - "crawl" (default true) discovers internal links in rendered HTML and queues them.
|
|
39
47
|
* - excludePaths can be strings, RegExp, or a predicate function.
|
|
40
48
|
* - Route-level failures are logged and skipped by default.
|
|
49
|
+
* - Generates sitemap.xml, robots.txt, and _redirects post-render.
|
|
50
|
+
* - Strips hardcoded SEO tags from template and injects per-page equivalents.
|
|
41
51
|
*/
|
|
42
|
-
export declare function prerender({ root, clientOutDir, serverEntry, paths, crawl, excludePaths, failFast, maxPages, mode, }?: PrerenderOptions): Promise<PrerenderResult>;
|
|
52
|
+
export declare function prerender({ root, clientOutDir, serverEntry, paths, crawl, excludePaths, failFast, maxPages, mode, website, redirects, }?: PrerenderOptions): Promise<PrerenderResult>;
|
|
43
53
|
export {};
|
|
44
54
|
//# sourceMappingURL=prerender.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/ssg/prerender.ts"],"names":[],"mappings":"AAKA,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAA;AAEhE,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,YAAY,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/ssg/prerender.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAS1C,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAA;AAEhE,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,YAAY,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;IACrB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,kDAAkD;IAClD,SAAS,CAAC,EAAE,aAAa,EAAE,CAAA;CAC3B;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAA;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;CACf;AAMD,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,SAAS,CAAC,EAC/B,IAAoB,EACpB,YAA4B,EAC5B,WAA0C,EAC1C,KAAU,EACV,KAAY,EACZ,YAAiB,EACjB,QAAgB,EAChB,QAAe,EACf,IAAY,EACZ,OAAc,EACd,SAAc,GACd,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CA0HlD"}
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
import { WebsiteRead } from '../api/types';
|
|
1
2
|
export interface BloxSsgRouterLike {
|
|
2
3
|
push: (url: string) => Promise<void>;
|
|
3
4
|
isReady: () => Promise<void>;
|
|
4
5
|
}
|
|
5
6
|
/**
|
|
6
|
-
* Render a Blox CMS page to static HTML with embedded state.
|
|
7
|
+
* Render a Blox CMS page to static HTML with embedded state and full SEO head.
|
|
7
8
|
*
|
|
8
9
|
* Sets `globalThis.__BLOX_STATE__` *before* rendering so that
|
|
9
10
|
* `CmsPageView` can hydrate synchronously from the embedded data
|
|
10
11
|
* instead of waiting for an async fetch.
|
|
11
12
|
*
|
|
12
|
-
* Returns `{ html, head }` where
|
|
13
|
-
* `
|
|
13
|
+
* Returns `{ html, head, htmlAttrs }` where:
|
|
14
|
+
* - `head` contains per-page `<title>`, meta tags, OG, canonical, hreflang,
|
|
15
|
+
* plus the `<script>` that sets `window.__BLOX_STATE__`
|
|
16
|
+
* - `htmlAttrs` contains the `lang` attribute
|
|
14
17
|
*/
|
|
15
18
|
export declare function renderBloxSsgPage<TApp>(options: {
|
|
16
19
|
url: string;
|
|
@@ -21,8 +24,11 @@ export declare function renderBloxSsgPage<TApp>(options: {
|
|
|
21
24
|
router: BloxSsgRouterLike;
|
|
22
25
|
};
|
|
23
26
|
stateWindowKey?: string;
|
|
27
|
+
/** Website settings for SEO tags. If omitted, only state script is emitted. */
|
|
28
|
+
website?: WebsiteRead | null;
|
|
24
29
|
}): Promise<{
|
|
25
30
|
html: string;
|
|
26
31
|
head?: string;
|
|
32
|
+
htmlAttrs?: string;
|
|
27
33
|
}>;
|
|
28
34
|
//# sourceMappingURL=render-resolved-page.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-resolved-page.d.ts","sourceRoot":"","sources":["../../src/ssg/render-resolved-page.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render-resolved-page.d.ts","sourceRoot":"","sources":["../../src/ssg/render-resolved-page.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAK/C,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE;IACtD,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,OAAO,GAAG,IAAI,CAAA;IAC5B,cAAc,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9C,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK;QAAE,GAAG,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,iBAAiB,CAAA;KAAE,CAAA;IAC1E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;CAC5B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkD/D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { PageRead, WebsiteRead } from '../api/types';
|
|
2
|
+
/** Resolved page data shape (subset of PageResolveRead). */
|
|
3
|
+
export interface SeoPageData {
|
|
4
|
+
page: PageRead;
|
|
5
|
+
alternates?: Record<string, string>;
|
|
6
|
+
contexts?: Record<string, Record<string, unknown> | null>;
|
|
7
|
+
}
|
|
8
|
+
/** Website meta bag (freeform JSON stored on WebsiteRead.meta). */
|
|
9
|
+
export interface WebsiteMeta {
|
|
10
|
+
default_meta_title?: string;
|
|
11
|
+
default_meta_description?: string;
|
|
12
|
+
default_og_image?: string;
|
|
13
|
+
webclip?: string;
|
|
14
|
+
og_site_name?: string;
|
|
15
|
+
og_description?: string;
|
|
16
|
+
og_type?: string;
|
|
17
|
+
twitter_card?: string;
|
|
18
|
+
twitter_site?: string;
|
|
19
|
+
canonical_base_url?: string;
|
|
20
|
+
noindex?: boolean;
|
|
21
|
+
verification_google?: string;
|
|
22
|
+
verification_bing?: string;
|
|
23
|
+
structured_data_org?: unknown;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
export interface RedirectEntry {
|
|
27
|
+
from_path: string;
|
|
28
|
+
to_path: string;
|
|
29
|
+
status_code: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Build a complete `<head>` fragment for a single page.
|
|
33
|
+
*
|
|
34
|
+
* Includes: title, meta description, OG tags, Twitter Card, canonical,
|
|
35
|
+
* hreflang alternates, noindex, and the __BLOX_STATE__ script.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildPageHead(options: {
|
|
38
|
+
url: string;
|
|
39
|
+
resolvedData: SeoPageData | null;
|
|
40
|
+
website: WebsiteRead | null;
|
|
41
|
+
stateScript?: string;
|
|
42
|
+
}): string;
|
|
43
|
+
/**
|
|
44
|
+
* Build site-wide `<head>` tags: verification, structured data, analytics, favicon.
|
|
45
|
+
* These replace hardcoded equivalents in the HTML template.
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildSiteHead(website: WebsiteRead | null): string;
|
|
48
|
+
export declare function generateSitemapXml(options: {
|
|
49
|
+
renderedPaths: string[];
|
|
50
|
+
canonicalBase: string;
|
|
51
|
+
defaultChangefreq?: string;
|
|
52
|
+
defaultPriority?: string;
|
|
53
|
+
}): string;
|
|
54
|
+
export declare function generateRobotsTxt(options: {
|
|
55
|
+
robotsTxt?: string | null;
|
|
56
|
+
canonicalBase?: string;
|
|
57
|
+
noindex?: boolean;
|
|
58
|
+
}): string;
|
|
59
|
+
export declare function generateNetlifyRedirects(redirects: RedirectEntry[]): string;
|
|
60
|
+
/**
|
|
61
|
+
* Strip hardcoded SEO tags from the HTML template so SSG can inject
|
|
62
|
+
* per-page equivalents. Removes: title, meta description, og:*, twitter:*,
|
|
63
|
+
* apple-touch-icon, and favicon.
|
|
64
|
+
*/
|
|
65
|
+
export declare function stripTemplateSeoTags(template: string): string;
|
|
66
|
+
//# sourceMappingURL=seo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../src/ssg/seo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAMzD,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,QAAQ,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;CACzD;AAED,mEAAmE;AACnE,MAAM,WAAW,WAAW;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;CACnB;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE;IACtC,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,WAAW,GAAG,IAAI,CAAA;IAChC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,MAAM,CAsET;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CA4CjE;AAMD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC3C,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,MAAM,CAmBT;AAMD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAC1C,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB,GAAG,MAAM,CAmBT;AAMD,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,CAK3E;AAMD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgB7D"}
|
package/package.json
CHANGED