@bagelink/blox 1.12.22 → 1.12.23
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/CmsPageView.vue.d.ts.map +1 -1
- package/dist/PreviewApp-C2T03Jm9.cjs +4 -0
- package/dist/PreviewApp-CmThrLvv.js +4 -0
- package/dist/PreviewApp.vue.d.ts.map +1 -1
- package/dist/PreviewApp.vue_vue_type_style_index_0_lang-B0N5QbfS.js +157 -0
- package/dist/PreviewApp.vue_vue_type_style_index_0_lang-BTuE4GmT.cjs +156 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/bridge.d.ts +1 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/core-C3Iu5qa2.js +460 -0
- package/dist/core-_fnHoEZN.cjs +459 -0
- package/dist/core.d.ts.map +1 -1
- package/dist/createBloxApp.d.ts +107 -0
- package/dist/createBloxApp.d.ts.map +1 -0
- package/dist/defineBlock.d.ts +2 -0
- package/dist/defineBlock.d.ts.map +1 -1
- package/dist/index.cjs +79 -585
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +78 -583
- package/dist/{prerender-6jE_obPj.cjs → prerender-Bi7YtzSp.cjs} +246 -6
- package/dist/prerender-D3Q4jKXm.js +522 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/ssg/cli.cjs +48 -5
- package/dist/ssg/cli.mjs +48 -5
- package/dist/ssg/client.cjs +50 -3
- package/dist/ssg/client.d.ts +2 -1
- package/dist/ssg/client.d.ts.map +1 -1
- package/dist/ssg/client.mjs +49 -2
- package/dist/ssg/cms-routes.d.ts +21 -4
- package/dist/ssg/cms-routes.d.ts.map +1 -1
- package/dist/ssg/collection-cache.d.ts +53 -0
- package/dist/ssg/collection-cache.d.ts.map +1 -0
- package/dist/ssg/constants.d.ts +4 -0
- package/dist/ssg/constants.d.ts.map +1 -1
- package/dist/ssg/createSSREntry.d.ts +73 -0
- package/dist/ssg/createSSREntry.d.ts.map +1 -0
- package/dist/ssg/index.cjs +138 -6
- package/dist/ssg/index.d.ts +10 -3
- package/dist/ssg/index.d.ts.map +1 -1
- package/dist/ssg/index.mjs +124 -12
- package/dist/ssg/prerender.d.ts +19 -1
- package/dist/ssg/prerender.d.ts.map +1 -1
- package/dist/ssg/render-resolved-page.d.ts +13 -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/dist/style.css +20 -0
- package/dist/vite-plugin.cjs +142 -3
- package/dist/vite-plugin.d.ts +22 -21
- package/dist/vite-plugin.d.ts.map +1 -1
- package/dist/vite-plugin.mjs +142 -3
- package/package.json +4 -1
- package/dist/PreviewApp-BZNzZkit.js +0 -4
- package/dist/PreviewApp-C1WvJWI4.cjs +0 -4
- package/dist/constants-BIbQhd3z.js +0 -4
- package/dist/constants-fZvybj0k.cjs +0 -3
- package/dist/prerender-DYmDaqcz.js +0 -282
|
@@ -25,18 +25,44 @@ 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
|
+
const collections = extractCollectionRefs(pages);
|
|
55
|
+
return { websiteId: site.id, website, paths, redirects, collections };
|
|
56
|
+
}
|
|
57
|
+
async function fetchCmsPrerenderPaths(apiBase, websiteName) {
|
|
58
|
+
const { paths } = await fetchCmsSiteData(apiBase, websiteName);
|
|
59
|
+
return paths;
|
|
60
|
+
}
|
|
61
|
+
async function expandRoutes(apiBase, pages) {
|
|
37
62
|
const routes = [];
|
|
38
63
|
for (const page of pages) {
|
|
39
64
|
const slug = page.slug ?? "/";
|
|
65
|
+
if (page.status && page.status !== "published") continue;
|
|
40
66
|
if (slug.includes(":") && page.data_bindings) {
|
|
41
67
|
for (const [, binding] of Object.entries(page.data_bindings)) {
|
|
42
68
|
const b = binding;
|
|
@@ -50,7 +76,10 @@ async function fetchCmsPrerenderPaths(apiBase, websiteName) {
|
|
|
50
76
|
for (const item of items) {
|
|
51
77
|
const bindValue = item[b.bind_by];
|
|
52
78
|
if (bindValue != null && bindValue !== "") {
|
|
53
|
-
const concrete = slug.replace(
|
|
79
|
+
const concrete = slug.replace(
|
|
80
|
+
/:([a-z_]+)/g,
|
|
81
|
+
(_m, p) => p === b.bind_by ? String(bindValue) : String(item[p] ?? "")
|
|
82
|
+
);
|
|
54
83
|
routes.push(concrete);
|
|
55
84
|
}
|
|
56
85
|
}
|
|
@@ -65,6 +94,170 @@ async function fetchCmsPrerenderPaths(apiBase, websiteName) {
|
|
|
65
94
|
}
|
|
66
95
|
return [...new Set(routes)];
|
|
67
96
|
}
|
|
97
|
+
function extractCollectionRefs(pages) {
|
|
98
|
+
const seen = /* @__PURE__ */ new Set();
|
|
99
|
+
const refs = [];
|
|
100
|
+
for (const page of pages) {
|
|
101
|
+
if (!page.data_bindings) continue;
|
|
102
|
+
for (const binding of Object.values(page.data_bindings)) {
|
|
103
|
+
const b = binding;
|
|
104
|
+
if (b.adapter === "datastore" && b.collection != null && b.collection !== "" && b.store != null && b.store !== "") {
|
|
105
|
+
const key = `${b.store}/${b.collection}`;
|
|
106
|
+
if (!seen.has(key)) {
|
|
107
|
+
seen.add(key);
|
|
108
|
+
refs.push({ store: b.store, collection: b.collection });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return refs;
|
|
114
|
+
}
|
|
115
|
+
function buildPageHead(options) {
|
|
116
|
+
const { url, resolvedData, website, stateScript } = options;
|
|
117
|
+
const parts = [];
|
|
118
|
+
const meta = (website == null ? void 0 : website.meta) ?? {};
|
|
119
|
+
const page = resolvedData == null ? void 0 : resolvedData.page;
|
|
120
|
+
const ctx = extractPrimaryContext(resolvedData == null ? void 0 : resolvedData.contexts);
|
|
121
|
+
const title = (page == null ? void 0 : page.meta_title) || ctx.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;
|
|
122
|
+
if (title) {
|
|
123
|
+
const fullTitle = ctx.title && meta.og_site_name && !ctx.title.includes(meta.og_site_name) ? `${esc(ctx.title)} · ${esc(meta.og_site_name)}` : esc(title);
|
|
124
|
+
parts.push(`<title>${fullTitle}</title>`);
|
|
125
|
+
}
|
|
126
|
+
const description = (page == null ? void 0 : page.meta_description) || ctx.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) || ctx.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) || ctx.description || meta.og_description || meta.default_meta_description;
|
|
136
|
+
const ogImage = (page == null ? void 0 : page.og_image) || ctx.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 || (ogImage ? "summary_large_image" : "summary");
|
|
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()}
|
|
227
|
+
${sitemapLine}`;
|
|
228
|
+
}
|
|
229
|
+
return robotsTxt;
|
|
230
|
+
}
|
|
231
|
+
return `User-agent: *
|
|
232
|
+
Allow: /
|
|
233
|
+
${sitemapLine}`;
|
|
234
|
+
}
|
|
235
|
+
function generateNetlifyRedirects(redirects) {
|
|
236
|
+
if (redirects.length === 0) return "";
|
|
237
|
+
return `${redirects.map((r) => `${r.from_path} ${r.to_path} ${r.status_code}`).join("\n")}
|
|
238
|
+
`;
|
|
239
|
+
}
|
|
240
|
+
function stripTemplateSeoTags(template) {
|
|
241
|
+
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");
|
|
242
|
+
}
|
|
243
|
+
function extractPrimaryContext(contexts) {
|
|
244
|
+
const empty = { title: null, description: null, image: null };
|
|
245
|
+
if (!contexts || typeof contexts !== "object") return empty;
|
|
246
|
+
const ctx = Object.values(contexts).find((c) => c != null);
|
|
247
|
+
if (!ctx) return empty;
|
|
248
|
+
const str = (key) => {
|
|
249
|
+
const v = ctx[key];
|
|
250
|
+
return typeof v === "string" && v.trim() ? v.trim() : null;
|
|
251
|
+
};
|
|
252
|
+
return {
|
|
253
|
+
title: str("meta_title") || str("title"),
|
|
254
|
+
description: str("meta_description") || str("excerpt") || str("description") || str("blurb") || str("summary"),
|
|
255
|
+
image: str("og_image") || str("cover_image_url") || str("image_url") || str("image")
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function esc(s) {
|
|
259
|
+
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
260
|
+
}
|
|
68
261
|
async function polyfillBloxSsgGlobals(options) {
|
|
69
262
|
const { env } = await import("node:process");
|
|
70
263
|
const pageUrl = (options == null ? void 0 : options.pageUrl) ?? env.BAGELINK_API_URL ?? "https://example.com/";
|
|
@@ -118,13 +311,23 @@ async function prerender({
|
|
|
118
311
|
excludePaths = [],
|
|
119
312
|
failFast = false,
|
|
120
313
|
maxPages = 5e3,
|
|
121
|
-
mode = "dir"
|
|
314
|
+
mode = "dir",
|
|
315
|
+
website = null,
|
|
316
|
+
websiteId = "",
|
|
317
|
+
redirects = [],
|
|
318
|
+
collections = {}
|
|
122
319
|
} = {}) {
|
|
123
320
|
const absRoot = path.resolve(root);
|
|
124
321
|
const absClient = path.resolve(absRoot, clientOutDir);
|
|
125
322
|
const absServerEntry = path.resolve(absRoot, serverEntry);
|
|
126
323
|
const templatePath = path.join(absClient, "index.html");
|
|
127
|
-
const
|
|
324
|
+
const rawTemplate = await fs.readFile(templatePath, "utf8");
|
|
325
|
+
let template = stripTemplateSeoTags(rawTemplate);
|
|
326
|
+
const siteHead = buildSiteHead(website);
|
|
327
|
+
if (siteHead) {
|
|
328
|
+
template = template.replace("</head>", `${siteHead}
|
|
329
|
+
</head>`);
|
|
330
|
+
}
|
|
128
331
|
const serverMod = await import(node_url.pathToFileURL(absServerEntry).href);
|
|
129
332
|
if (typeof serverMod.render !== "function") {
|
|
130
333
|
throw new TypeError(
|
|
@@ -153,7 +356,10 @@ async function prerender({
|
|
|
153
356
|
try {
|
|
154
357
|
const { html, head = "", htmlAttrs = "" } = await serverMod.render(urlPath, {
|
|
155
358
|
manifest,
|
|
156
|
-
template
|
|
359
|
+
template,
|
|
360
|
+
website,
|
|
361
|
+
websiteId,
|
|
362
|
+
collections
|
|
157
363
|
});
|
|
158
364
|
const outHtml = injectIntoTemplate(template, head, html, fontPreloads, htmlAttrs);
|
|
159
365
|
const outfile = outFilePath(absClient, urlPath, mode);
|
|
@@ -171,6 +377,31 @@ async function prerender({
|
|
|
171
377
|
`, err.stack ?? err);
|
|
172
378
|
}
|
|
173
379
|
}
|
|
380
|
+
const websiteMeta = (website == null ? void 0 : website.meta) ?? {};
|
|
381
|
+
const canonicalBase = (websiteMeta.canonical_base_url || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
382
|
+
if (canonicalBase && rendered.length > 0) {
|
|
383
|
+
const sitemap = generateSitemapXml({ renderedPaths: rendered, canonicalBase });
|
|
384
|
+
await fs.writeFile(path.join(absClient, "sitemap.xml"), sitemap, "utf8");
|
|
385
|
+
console.log(` Generated sitemap.xml (${rendered.length} URLs)`);
|
|
386
|
+
}
|
|
387
|
+
const robotsTxt = generateRobotsTxt({
|
|
388
|
+
robotsTxt: website == null ? void 0 : website.robots_txt,
|
|
389
|
+
canonicalBase,
|
|
390
|
+
noindex: websiteMeta.noindex
|
|
391
|
+
});
|
|
392
|
+
await fs.writeFile(path.join(absClient, "robots.txt"), robotsTxt, "utf8");
|
|
393
|
+
console.log(" Generated robots.txt");
|
|
394
|
+
if (redirects.length > 0) {
|
|
395
|
+
const redirectsContent = generateNetlifyRedirects(redirects);
|
|
396
|
+
const redirectsPath = path.join(absClient, "_redirects");
|
|
397
|
+
let existing = "";
|
|
398
|
+
try {
|
|
399
|
+
existing = await fs.readFile(redirectsPath, "utf8");
|
|
400
|
+
} catch {
|
|
401
|
+
}
|
|
402
|
+
await fs.writeFile(redirectsPath, redirectsContent + existing, "utf8");
|
|
403
|
+
console.log(` Generated _redirects (${redirects.length} rules)`);
|
|
404
|
+
}
|
|
174
405
|
return {
|
|
175
406
|
rendered,
|
|
176
407
|
failures,
|
|
@@ -256,6 +487,9 @@ function injectIntoTemplate(template, head, appHtml, fontPreloads, htmlAttrs = "
|
|
|
256
487
|
</head>`);
|
|
257
488
|
}
|
|
258
489
|
if (head) {
|
|
490
|
+
if (/<title>/.test(head)) {
|
|
491
|
+
out = out.replace("<!--ssg:title-->", "");
|
|
492
|
+
}
|
|
259
493
|
const descTagRe = /<meta\s[^>]*name\s*=\s*["']description["'][^>]*>/gi;
|
|
260
494
|
const descMatches = [...head.matchAll(descTagRe)];
|
|
261
495
|
if (descMatches.length > 1) {
|
|
@@ -298,6 +532,12 @@ function discoverInternalLinks(html) {
|
|
|
298
532
|
}
|
|
299
533
|
return [...out];
|
|
300
534
|
}
|
|
535
|
+
exports.buildPageHead = buildPageHead;
|
|
536
|
+
exports.buildSiteHead = buildSiteHead;
|
|
301
537
|
exports.fetchCmsPrerenderPaths = fetchCmsPrerenderPaths;
|
|
538
|
+
exports.fetchCmsSiteData = fetchCmsSiteData;
|
|
539
|
+
exports.generateNetlifyRedirects = generateNetlifyRedirects;
|
|
540
|
+
exports.generateRobotsTxt = generateRobotsTxt;
|
|
541
|
+
exports.generateSitemapXml = generateSitemapXml;
|
|
302
542
|
exports.polyfillBloxSsgGlobals = polyfillBloxSsgGlobals;
|
|
303
543
|
exports.prerender = prerender;
|