@bagelink/blox 1.15.213 → 1.15.215
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/PageRenderer.d.ts.map +1 -1
- package/dist/{PreviewApp-APyemzqx.cjs → PreviewApp-C2Cn1yH2.cjs} +1 -1
- package/dist/{PreviewApp-BKTydm92.js → PreviewApp-CNIVF6Xq.js} +1 -1
- package/dist/{PreviewApp.vue_vue_type_style_index_0_lang-C0ZVst7R.cjs → PreviewApp.vue_vue_type_style_index_0_lang-kv9T9yLc.cjs} +20 -12
- package/dist/{PreviewApp.vue_vue_type_style_index_0_lang-DHb-NJ4C.js → PreviewApp.vue_vue_type_style_index_0_lang-lotrZDHC.js} +20 -12
- package/dist/PreviewRenderer.d.ts.map +1 -1
- package/dist/api/types.d.ts +33 -2
- package/dist/api/types.d.ts.map +1 -1
- package/dist/bridge.d.ts +2 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/composables/useGlobalBlock.d.ts +14 -21
- package/dist/composables/useGlobalBlock.d.ts.map +1 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/defineBlock.d.ts +8 -0
- package/dist/defineBlock.d.ts.map +1 -1
- package/dist/index.cjs +16 -20
- package/dist/index.d.ts +3 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +45 -49
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/{prerender-BNFeuap-.cjs → prerender-BkTA1QZ6.cjs} +97 -64
- package/dist/{prerender-Bth9K3uz.js → prerender-wIuYNW6N.js} +97 -64
- package/dist/{routes-C97aL4cQ.cjs → routes-0bOKkut4.cjs} +5 -91
- package/dist/{routes-bhjTTXfU.js → routes-CHfoa2Mk.js} +38 -124
- package/dist/schema.d.ts +2 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/ssg/cli.cjs +1 -1
- package/dist/ssg/cli.mjs +1 -1
- package/dist/ssg/index.cjs +2 -2
- package/dist/ssg/index.d.ts +1 -1
- package/dist/ssg/index.d.ts.map +1 -1
- package/dist/ssg/index.mjs +3 -3
- package/dist/ssg/prerender.d.ts +5 -1
- package/dist/ssg/prerender.d.ts.map +1 -1
- package/dist/ssg/seo.d.ts +13 -27
- package/dist/ssg/seo.d.ts.map +1 -1
- package/dist/symbols.d.ts +0 -11
- package/dist/symbols.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/GlobalBlockHost.d.ts +0 -75
- package/dist/GlobalBlockHost.d.ts.map +0 -1
- package/dist/globalRef.d.ts +0 -9
- package/dist/globalRef.d.ts.map +0 -1
|
@@ -174,10 +174,12 @@ async function polyfillBloxSsgGlobals(options) {
|
|
|
174
174
|
g.window.location = _win.location;
|
|
175
175
|
g.window.document = _win.document;
|
|
176
176
|
}
|
|
177
|
-
function buildStructuredData(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
function buildStructuredData(sd, locale) {
|
|
178
|
+
var _a;
|
|
179
|
+
if (!sd) return "";
|
|
180
|
+
const perLocale = locale ? (_a = sd.org_by_locale) == null ? void 0 : _a[locale] : void 0;
|
|
181
|
+
const value = perLocale ?? sd.org;
|
|
182
|
+
if (value == null || typeof value === "string" && value === "") return "";
|
|
181
183
|
try {
|
|
182
184
|
const json = typeof value === "string" ? value : JSON.stringify(value);
|
|
183
185
|
return `<script type="application/ld+json">${json}${"<"}/script>`;
|
|
@@ -187,44 +189,46 @@ function buildStructuredData(meta, locale) {
|
|
|
187
189
|
}
|
|
188
190
|
function buildPageHead(options) {
|
|
189
191
|
var _a;
|
|
190
|
-
const { url, resolvedData, website, stateScript, locale, override } = options;
|
|
192
|
+
const { url, resolvedData, website, stateScript, locale, override, buildOrigin } = options;
|
|
191
193
|
const parts = [];
|
|
192
|
-
const
|
|
194
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
193
195
|
const page = resolvedData == null ? void 0 : resolvedData.page;
|
|
194
196
|
const ctx = extractPrimaryContext(resolvedData == null ? void 0 : resolvedData.contexts);
|
|
195
|
-
const
|
|
197
|
+
const siteName = seo.site_name || void 0;
|
|
198
|
+
const title = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || ((page == null ? void 0 : page.title) && siteName ? `${page.title} · ${siteName}` : null) || (page == null ? void 0 : page.title) || seo.default_meta_title;
|
|
196
199
|
if (title) {
|
|
197
200
|
const bare = (override == null ? void 0 : override.title) || ctx.title;
|
|
198
|
-
const fullTitle = bare &&
|
|
201
|
+
const fullTitle = bare && siteName && !bare.includes(siteName) ? `${esc(bare)} · ${esc(siteName)}` : esc(title);
|
|
199
202
|
parts.push(`<title>${fullTitle}</title>`);
|
|
200
203
|
}
|
|
201
|
-
const description = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description ||
|
|
204
|
+
const description = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description || seo.default_meta_description;
|
|
202
205
|
if (description) {
|
|
203
206
|
parts.push(`<meta name="description" content="${esc(description)}">`);
|
|
204
207
|
}
|
|
205
|
-
const canonicalBase = (
|
|
208
|
+
const canonicalBase = (seo.canonical_base_url || (website == null ? void 0 : website.domain) || buildOrigin || "").replace(/\/$/, "");
|
|
206
209
|
const pageCanonical = (_a = page == null ? void 0 : page.canonical_url) == null ? void 0 : _a.trim();
|
|
207
210
|
if (pageCanonical) {
|
|
208
211
|
parts.push(`<link rel="canonical" href="${esc(pageCanonical)}">`);
|
|
209
212
|
} else if (canonicalBase) {
|
|
210
213
|
parts.push(`<link rel="canonical" href="${esc(canonicalBase + url)}">`);
|
|
211
214
|
}
|
|
212
|
-
const ogTitle = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || (page == null ? void 0 : page.title) ||
|
|
213
|
-
const ogDesc = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description ||
|
|
214
|
-
const ogImage = absUrl((override == null ? void 0 : override.image) || (page == null ? void 0 : page.og_image) || ctx.image ||
|
|
215
|
-
const
|
|
215
|
+
const ogTitle = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || (page == null ? void 0 : page.title) || siteName || seo.default_meta_title;
|
|
216
|
+
const ogDesc = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description || seo.default_meta_description;
|
|
217
|
+
const ogImage = absUrl((override == null ? void 0 : override.image) || (page == null ? void 0 : page.og_image) || ctx.image || seo.default_og_image);
|
|
218
|
+
const isDetailPage = !!((resolvedData == null ? void 0 : resolvedData.contexts) && Object.values(resolvedData.contexts).some((c) => c != null));
|
|
219
|
+
const ogType = isDetailPage ? "article" : "website";
|
|
216
220
|
if (ogTitle) parts.push(`<meta property="og:title" content="${esc(ogTitle)}">`);
|
|
217
221
|
if (ogDesc) parts.push(`<meta property="og:description" content="${esc(ogDesc)}">`);
|
|
218
222
|
if (ogImage) parts.push(`<meta property="og:image" content="${esc(ogImage)}">`);
|
|
219
223
|
parts.push(`<meta property="og:type" content="${esc(ogType)}">`);
|
|
220
224
|
if (canonicalBase) parts.push(`<meta property="og:url" content="${esc(canonicalBase + url)}">`);
|
|
221
|
-
if (
|
|
222
|
-
const twitterCard =
|
|
225
|
+
if (siteName) parts.push(`<meta property="og:site_name" content="${esc(siteName)}">`);
|
|
226
|
+
const twitterCard = ogImage ? "summary_large_image" : "summary";
|
|
223
227
|
parts.push(`<meta name="twitter:card" content="${esc(twitterCard)}">`);
|
|
224
228
|
if (ogTitle) parts.push(`<meta name="twitter:title" content="${esc(ogTitle)}">`);
|
|
225
229
|
if (ogDesc) parts.push(`<meta name="twitter:description" content="${esc(ogDesc)}">`);
|
|
226
230
|
if (ogImage) parts.push(`<meta name="twitter:image" content="${esc(ogImage)}">`);
|
|
227
|
-
if (
|
|
231
|
+
if (seo.twitter_site) parts.push(`<meta name="twitter:site" content="${esc(seo.twitter_site)}">`);
|
|
228
232
|
const alternates = (override == null ? void 0 : override.alternates) && Object.keys(override.alternates).length ? override.alternates : resolvedData == null ? void 0 : resolvedData.alternates;
|
|
229
233
|
const defaultLocale = (website == null ? void 0 : website.default_locale) ?? "en";
|
|
230
234
|
if (alternates && canonicalBase) {
|
|
@@ -235,10 +239,10 @@ function buildPageHead(options) {
|
|
|
235
239
|
const defaultSlug = alternates[defaultLocale] ?? url;
|
|
236
240
|
parts.push(`<link rel="alternate" hreflang="x-default" href="${esc(canonicalBase + defaultSlug)}">`);
|
|
237
241
|
}
|
|
238
|
-
if (
|
|
242
|
+
if (seo.noindex || (page == null ? void 0 : page.noindex)) {
|
|
239
243
|
parts.push('<meta name="robots" content="noindex, nofollow">');
|
|
240
244
|
}
|
|
241
|
-
const structuredData = buildStructuredData(
|
|
245
|
+
const structuredData = buildStructuredData(website == null ? void 0 : website.structured_data, locale || (website == null ? void 0 : website.default_locale));
|
|
242
246
|
if (structuredData) parts.push(structuredData);
|
|
243
247
|
if (stateScript) {
|
|
244
248
|
parts.push(stateScript);
|
|
@@ -246,24 +250,25 @@ function buildPageHead(options) {
|
|
|
246
250
|
return parts.join("\n");
|
|
247
251
|
}
|
|
248
252
|
function buildSiteHead(website) {
|
|
253
|
+
var _a, _b, _c;
|
|
249
254
|
if (!website) return "";
|
|
250
255
|
const parts = [];
|
|
251
|
-
const
|
|
252
|
-
const favicon = absUrl(
|
|
256
|
+
const seo = website.seo ?? {};
|
|
257
|
+
const favicon = absUrl(seo.favicon_url);
|
|
253
258
|
if (favicon) {
|
|
254
259
|
parts.push(`<link rel="icon" href="${esc(favicon)}">`);
|
|
255
260
|
}
|
|
256
|
-
const webclip = absUrl(
|
|
261
|
+
const webclip = absUrl(seo.webclip);
|
|
257
262
|
if (webclip) {
|
|
258
263
|
parts.push(`<link rel="apple-touch-icon" sizes="180x180" href="${esc(webclip)}">`);
|
|
259
264
|
}
|
|
260
|
-
if (
|
|
261
|
-
parts.push(`<meta name="google-site-verification" content="${esc(
|
|
265
|
+
if ((_a = website.verification) == null ? void 0 : _a.google) {
|
|
266
|
+
parts.push(`<meta name="google-site-verification" content="${esc(website.verification.google)}">`);
|
|
262
267
|
}
|
|
263
|
-
if (
|
|
264
|
-
parts.push(`<meta name="msvalidate.01" content="${esc(
|
|
268
|
+
if ((_b = website.verification) == null ? void 0 : _b.bing) {
|
|
269
|
+
parts.push(`<meta name="msvalidate.01" content="${esc(website.verification.bing)}">`);
|
|
265
270
|
}
|
|
266
|
-
const plausibleId = website.plausible_site_id;
|
|
271
|
+
const plausibleId = (_c = website.integrations) == null ? void 0 : _c.plausible_site_id;
|
|
267
272
|
if (plausibleId) {
|
|
268
273
|
const host = "https://analytics.bagel.to";
|
|
269
274
|
parts.push(
|
|
@@ -273,13 +278,16 @@ function buildSiteHead(website) {
|
|
|
273
278
|
return parts.join("\n");
|
|
274
279
|
}
|
|
275
280
|
function generateSitemapXml(options) {
|
|
276
|
-
const { renderedPaths, canonicalBase, defaultChangefreq = "weekly", defaultPriority = "0.7" } = options;
|
|
281
|
+
const { renderedPaths, canonicalBase, defaultChangefreq = "weekly", defaultPriority = "0.7", lastmod = {} } = options;
|
|
277
282
|
const base = canonicalBase.replace(/\/$/, "");
|
|
278
283
|
const urls = renderedPaths.map((p) => {
|
|
279
284
|
const priority = p === "/" ? "1.0" : defaultPriority;
|
|
280
285
|
const changefreq = p === "/" ? "daily" : defaultChangefreq;
|
|
286
|
+
const mod = lastmod[p];
|
|
287
|
+
const modLine = mod ? `
|
|
288
|
+
<lastmod>${esc(mod)}</lastmod>` : "";
|
|
281
289
|
return ` <url>
|
|
282
|
-
<loc>${esc(base + p)}</loc
|
|
290
|
+
<loc>${esc(base + p)}</loc>${modLine}
|
|
283
291
|
<changefreq>${changefreq}</changefreq>
|
|
284
292
|
<priority>${priority}</priority>
|
|
285
293
|
</url>`;
|
|
@@ -329,10 +337,10 @@ function stripTemplateSeoTags(template, options = {}) {
|
|
|
329
337
|
return out.replace(/\n\s*\n\s*\n/g, "\n\n");
|
|
330
338
|
}
|
|
331
339
|
function getSiteIconFlags(website) {
|
|
332
|
-
const
|
|
340
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
333
341
|
return {
|
|
334
|
-
hasFavicon: !!absUrl(
|
|
335
|
-
hasWebclip: !!absUrl(
|
|
342
|
+
hasFavicon: !!absUrl(seo.favicon_url),
|
|
343
|
+
hasWebclip: !!absUrl(seo.webclip)
|
|
336
344
|
};
|
|
337
345
|
}
|
|
338
346
|
function extractPrimaryContext(contexts) {
|
|
@@ -370,12 +378,14 @@ async function prerender({
|
|
|
370
378
|
excludePaths = [],
|
|
371
379
|
failFast = false,
|
|
372
380
|
maxPages = 5e3,
|
|
381
|
+
concurrency = 6,
|
|
373
382
|
mode = "dir",
|
|
374
383
|
website = null,
|
|
375
384
|
websiteId = "",
|
|
376
385
|
redirects = [],
|
|
377
386
|
collections = {}
|
|
378
387
|
} = {}) {
|
|
388
|
+
var _a, _b;
|
|
379
389
|
const absRoot = path.resolve(root);
|
|
380
390
|
const absClient = path.resolve(absRoot, clientOutDir);
|
|
381
391
|
const absServerEntry = path.resolve(absRoot, serverEntry);
|
|
@@ -407,44 +417,67 @@ async function prerender({
|
|
|
407
417
|
const fontPreloads = await discoverFontPreloads(absClient);
|
|
408
418
|
const rendered = [];
|
|
409
419
|
const noindexPaths = /* @__PURE__ */ new Set();
|
|
420
|
+
const lastmod = {};
|
|
410
421
|
const failures = [];
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
422
|
+
async function renderOne(urlPath) {
|
|
423
|
+
const {
|
|
424
|
+
html,
|
|
425
|
+
head = "",
|
|
426
|
+
htmlAttrs = "",
|
|
427
|
+
lastmod: pageLastmod
|
|
428
|
+
} = await serverMod.render(urlPath, {
|
|
429
|
+
manifest,
|
|
430
|
+
template,
|
|
431
|
+
website,
|
|
432
|
+
websiteId,
|
|
433
|
+
collections
|
|
434
|
+
});
|
|
435
|
+
const outHtml = injectIntoTemplate(template, head, html, fontPreloads, htmlAttrs);
|
|
436
|
+
const outfile = outFilePath(absClient, urlPath, mode);
|
|
437
|
+
await fs.mkdir(path.dirname(outfile), { recursive: true });
|
|
438
|
+
await fs.writeFile(outfile, outHtml, "utf8");
|
|
439
|
+
rendered.push(urlPath);
|
|
440
|
+
if (pageLastmod) lastmod[urlPath] = pageLastmod;
|
|
441
|
+
if (/<meta[^>]+name=["']robots["'][^>]*noindex/i.test(head)) {
|
|
442
|
+
noindexPaths.add(urlPath);
|
|
443
|
+
}
|
|
444
|
+
if (crawl) {
|
|
445
|
+
for (const p of discoverInternalLinks(outHtml)) {
|
|
446
|
+
enqueue(p, queue, seen, isExcluded);
|
|
435
447
|
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
let stopped = false;
|
|
451
|
+
async function worker() {
|
|
452
|
+
while (!stopped) {
|
|
453
|
+
if (rendered.length >= maxPages) break;
|
|
454
|
+
const urlPath = queue.shift();
|
|
455
|
+
if (urlPath === void 0) break;
|
|
456
|
+
if (urlPath === "" || isExcluded(urlPath)) continue;
|
|
457
|
+
try {
|
|
458
|
+
await renderOne(urlPath);
|
|
459
|
+
} catch (err) {
|
|
460
|
+
failures.push({ path: urlPath, error: err });
|
|
461
|
+
if (failFast) {
|
|
462
|
+
stopped = true;
|
|
463
|
+
throw err;
|
|
464
|
+
}
|
|
465
|
+
console.warn(`[prerender] failed: ${urlPath}
|
|
440
466
|
`, err.stack ?? err);
|
|
467
|
+
}
|
|
441
468
|
}
|
|
442
469
|
}
|
|
443
|
-
|
|
444
|
-
|
|
470
|
+
while (queue.length && !stopped && rendered.length < maxPages) {
|
|
471
|
+
const workers = Array.from(
|
|
472
|
+
{ length: Math.min(concurrency, queue.length) },
|
|
473
|
+
() => worker()
|
|
474
|
+
);
|
|
475
|
+
await Promise.all(workers);
|
|
476
|
+
}
|
|
477
|
+
const canonicalBase = (((_a = website == null ? void 0 : website.seo) == null ? void 0 : _a.canonical_base_url) || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
445
478
|
const sitemapPaths = rendered.filter((p) => !noindexPaths.has(p));
|
|
446
479
|
if (canonicalBase && sitemapPaths.length > 0) {
|
|
447
|
-
const sitemap = generateSitemapXml({ renderedPaths: sitemapPaths, canonicalBase });
|
|
480
|
+
const sitemap = generateSitemapXml({ renderedPaths: sitemapPaths, canonicalBase, lastmod });
|
|
448
481
|
await fs.writeFile(path.join(absClient, "sitemap.xml"), sitemap, "utf8");
|
|
449
482
|
const skipped = noindexPaths.size > 0 ? ` (${noindexPaths.size} noindex excluded)` : "";
|
|
450
483
|
console.log(` Generated sitemap.xml (${sitemapPaths.length} URLs)${skipped}`);
|
|
@@ -452,7 +485,7 @@ async function prerender({
|
|
|
452
485
|
const robotsTxt = generateRobotsTxt({
|
|
453
486
|
robotsTxt: website == null ? void 0 : website.robots_txt,
|
|
454
487
|
canonicalBase,
|
|
455
|
-
noindex:
|
|
488
|
+
noindex: (_b = website == null ? void 0 : website.seo) == null ? void 0 : _b.noindex
|
|
456
489
|
});
|
|
457
490
|
await fs.writeFile(path.join(absClient, "robots.txt"), robotsTxt, "utf8");
|
|
458
491
|
console.log(" Generated robots.txt");
|
|
@@ -151,10 +151,12 @@ async function polyfillBloxSsgGlobals(options) {
|
|
|
151
151
|
g.window.location = _win.location;
|
|
152
152
|
g.window.document = _win.document;
|
|
153
153
|
}
|
|
154
|
-
function buildStructuredData(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
function buildStructuredData(sd, locale) {
|
|
155
|
+
var _a;
|
|
156
|
+
if (!sd) return "";
|
|
157
|
+
const perLocale = locale ? (_a = sd.org_by_locale) == null ? void 0 : _a[locale] : void 0;
|
|
158
|
+
const value = perLocale ?? sd.org;
|
|
159
|
+
if (value == null || typeof value === "string" && value === "") return "";
|
|
158
160
|
try {
|
|
159
161
|
const json = typeof value === "string" ? value : JSON.stringify(value);
|
|
160
162
|
return `<script type="application/ld+json">${json}${"<"}/script>`;
|
|
@@ -164,44 +166,46 @@ function buildStructuredData(meta, locale) {
|
|
|
164
166
|
}
|
|
165
167
|
function buildPageHead(options) {
|
|
166
168
|
var _a;
|
|
167
|
-
const { url, resolvedData, website, stateScript, locale, override } = options;
|
|
169
|
+
const { url, resolvedData, website, stateScript, locale, override, buildOrigin } = options;
|
|
168
170
|
const parts = [];
|
|
169
|
-
const
|
|
171
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
170
172
|
const page = resolvedData == null ? void 0 : resolvedData.page;
|
|
171
173
|
const ctx = extractPrimaryContext(resolvedData == null ? void 0 : resolvedData.contexts);
|
|
172
|
-
const
|
|
174
|
+
const siteName = seo.site_name || void 0;
|
|
175
|
+
const title = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || ((page == null ? void 0 : page.title) && siteName ? `${page.title} · ${siteName}` : null) || (page == null ? void 0 : page.title) || seo.default_meta_title;
|
|
173
176
|
if (title) {
|
|
174
177
|
const bare = (override == null ? void 0 : override.title) || ctx.title;
|
|
175
|
-
const fullTitle = bare &&
|
|
178
|
+
const fullTitle = bare && siteName && !bare.includes(siteName) ? `${esc(bare)} · ${esc(siteName)}` : esc(title);
|
|
176
179
|
parts.push(`<title>${fullTitle}</title>`);
|
|
177
180
|
}
|
|
178
|
-
const description = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description ||
|
|
181
|
+
const description = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description || seo.default_meta_description;
|
|
179
182
|
if (description) {
|
|
180
183
|
parts.push(`<meta name="description" content="${esc(description)}">`);
|
|
181
184
|
}
|
|
182
|
-
const canonicalBase = (
|
|
185
|
+
const canonicalBase = (seo.canonical_base_url || (website == null ? void 0 : website.domain) || buildOrigin || "").replace(/\/$/, "");
|
|
183
186
|
const pageCanonical = (_a = page == null ? void 0 : page.canonical_url) == null ? void 0 : _a.trim();
|
|
184
187
|
if (pageCanonical) {
|
|
185
188
|
parts.push(`<link rel="canonical" href="${esc(pageCanonical)}">`);
|
|
186
189
|
} else if (canonicalBase) {
|
|
187
190
|
parts.push(`<link rel="canonical" href="${esc(canonicalBase + url)}">`);
|
|
188
191
|
}
|
|
189
|
-
const ogTitle = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || (page == null ? void 0 : page.title) ||
|
|
190
|
-
const ogDesc = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description ||
|
|
191
|
-
const ogImage = absUrl((override == null ? void 0 : override.image) || (page == null ? void 0 : page.og_image) || ctx.image ||
|
|
192
|
-
const
|
|
192
|
+
const ogTitle = (override == null ? void 0 : override.title) || (page == null ? void 0 : page.meta_title) || ctx.title || (page == null ? void 0 : page.title) || siteName || seo.default_meta_title;
|
|
193
|
+
const ogDesc = (override == null ? void 0 : override.description) || (page == null ? void 0 : page.meta_description) || ctx.description || seo.default_meta_description;
|
|
194
|
+
const ogImage = absUrl((override == null ? void 0 : override.image) || (page == null ? void 0 : page.og_image) || ctx.image || seo.default_og_image);
|
|
195
|
+
const isDetailPage = !!((resolvedData == null ? void 0 : resolvedData.contexts) && Object.values(resolvedData.contexts).some((c) => c != null));
|
|
196
|
+
const ogType = isDetailPage ? "article" : "website";
|
|
193
197
|
if (ogTitle) parts.push(`<meta property="og:title" content="${esc(ogTitle)}">`);
|
|
194
198
|
if (ogDesc) parts.push(`<meta property="og:description" content="${esc(ogDesc)}">`);
|
|
195
199
|
if (ogImage) parts.push(`<meta property="og:image" content="${esc(ogImage)}">`);
|
|
196
200
|
parts.push(`<meta property="og:type" content="${esc(ogType)}">`);
|
|
197
201
|
if (canonicalBase) parts.push(`<meta property="og:url" content="${esc(canonicalBase + url)}">`);
|
|
198
|
-
if (
|
|
199
|
-
const twitterCard =
|
|
202
|
+
if (siteName) parts.push(`<meta property="og:site_name" content="${esc(siteName)}">`);
|
|
203
|
+
const twitterCard = ogImage ? "summary_large_image" : "summary";
|
|
200
204
|
parts.push(`<meta name="twitter:card" content="${esc(twitterCard)}">`);
|
|
201
205
|
if (ogTitle) parts.push(`<meta name="twitter:title" content="${esc(ogTitle)}">`);
|
|
202
206
|
if (ogDesc) parts.push(`<meta name="twitter:description" content="${esc(ogDesc)}">`);
|
|
203
207
|
if (ogImage) parts.push(`<meta name="twitter:image" content="${esc(ogImage)}">`);
|
|
204
|
-
if (
|
|
208
|
+
if (seo.twitter_site) parts.push(`<meta name="twitter:site" content="${esc(seo.twitter_site)}">`);
|
|
205
209
|
const alternates = (override == null ? void 0 : override.alternates) && Object.keys(override.alternates).length ? override.alternates : resolvedData == null ? void 0 : resolvedData.alternates;
|
|
206
210
|
const defaultLocale = (website == null ? void 0 : website.default_locale) ?? "en";
|
|
207
211
|
if (alternates && canonicalBase) {
|
|
@@ -212,10 +216,10 @@ function buildPageHead(options) {
|
|
|
212
216
|
const defaultSlug = alternates[defaultLocale] ?? url;
|
|
213
217
|
parts.push(`<link rel="alternate" hreflang="x-default" href="${esc(canonicalBase + defaultSlug)}">`);
|
|
214
218
|
}
|
|
215
|
-
if (
|
|
219
|
+
if (seo.noindex || (page == null ? void 0 : page.noindex)) {
|
|
216
220
|
parts.push('<meta name="robots" content="noindex, nofollow">');
|
|
217
221
|
}
|
|
218
|
-
const structuredData = buildStructuredData(
|
|
222
|
+
const structuredData = buildStructuredData(website == null ? void 0 : website.structured_data, locale || (website == null ? void 0 : website.default_locale));
|
|
219
223
|
if (structuredData) parts.push(structuredData);
|
|
220
224
|
if (stateScript) {
|
|
221
225
|
parts.push(stateScript);
|
|
@@ -223,24 +227,25 @@ function buildPageHead(options) {
|
|
|
223
227
|
return parts.join("\n");
|
|
224
228
|
}
|
|
225
229
|
function buildSiteHead(website) {
|
|
230
|
+
var _a, _b, _c;
|
|
226
231
|
if (!website) return "";
|
|
227
232
|
const parts = [];
|
|
228
|
-
const
|
|
229
|
-
const favicon = absUrl(
|
|
233
|
+
const seo = website.seo ?? {};
|
|
234
|
+
const favicon = absUrl(seo.favicon_url);
|
|
230
235
|
if (favicon) {
|
|
231
236
|
parts.push(`<link rel="icon" href="${esc(favicon)}">`);
|
|
232
237
|
}
|
|
233
|
-
const webclip = absUrl(
|
|
238
|
+
const webclip = absUrl(seo.webclip);
|
|
234
239
|
if (webclip) {
|
|
235
240
|
parts.push(`<link rel="apple-touch-icon" sizes="180x180" href="${esc(webclip)}">`);
|
|
236
241
|
}
|
|
237
|
-
if (
|
|
238
|
-
parts.push(`<meta name="google-site-verification" content="${esc(
|
|
242
|
+
if ((_a = website.verification) == null ? void 0 : _a.google) {
|
|
243
|
+
parts.push(`<meta name="google-site-verification" content="${esc(website.verification.google)}">`);
|
|
239
244
|
}
|
|
240
|
-
if (
|
|
241
|
-
parts.push(`<meta name="msvalidate.01" content="${esc(
|
|
245
|
+
if ((_b = website.verification) == null ? void 0 : _b.bing) {
|
|
246
|
+
parts.push(`<meta name="msvalidate.01" content="${esc(website.verification.bing)}">`);
|
|
242
247
|
}
|
|
243
|
-
const plausibleId = website.plausible_site_id;
|
|
248
|
+
const plausibleId = (_c = website.integrations) == null ? void 0 : _c.plausible_site_id;
|
|
244
249
|
if (plausibleId) {
|
|
245
250
|
const host = "https://analytics.bagel.to";
|
|
246
251
|
parts.push(
|
|
@@ -250,13 +255,16 @@ function buildSiteHead(website) {
|
|
|
250
255
|
return parts.join("\n");
|
|
251
256
|
}
|
|
252
257
|
function generateSitemapXml(options) {
|
|
253
|
-
const { renderedPaths, canonicalBase, defaultChangefreq = "weekly", defaultPriority = "0.7" } = options;
|
|
258
|
+
const { renderedPaths, canonicalBase, defaultChangefreq = "weekly", defaultPriority = "0.7", lastmod = {} } = options;
|
|
254
259
|
const base = canonicalBase.replace(/\/$/, "");
|
|
255
260
|
const urls = renderedPaths.map((p) => {
|
|
256
261
|
const priority = p === "/" ? "1.0" : defaultPriority;
|
|
257
262
|
const changefreq = p === "/" ? "daily" : defaultChangefreq;
|
|
263
|
+
const mod = lastmod[p];
|
|
264
|
+
const modLine = mod ? `
|
|
265
|
+
<lastmod>${esc(mod)}</lastmod>` : "";
|
|
258
266
|
return ` <url>
|
|
259
|
-
<loc>${esc(base + p)}</loc
|
|
267
|
+
<loc>${esc(base + p)}</loc>${modLine}
|
|
260
268
|
<changefreq>${changefreq}</changefreq>
|
|
261
269
|
<priority>${priority}</priority>
|
|
262
270
|
</url>`;
|
|
@@ -306,10 +314,10 @@ function stripTemplateSeoTags(template, options = {}) {
|
|
|
306
314
|
return out.replace(/\n\s*\n\s*\n/g, "\n\n");
|
|
307
315
|
}
|
|
308
316
|
function getSiteIconFlags(website) {
|
|
309
|
-
const
|
|
317
|
+
const seo = (website == null ? void 0 : website.seo) ?? {};
|
|
310
318
|
return {
|
|
311
|
-
hasFavicon: !!absUrl(
|
|
312
|
-
hasWebclip: !!absUrl(
|
|
319
|
+
hasFavicon: !!absUrl(seo.favicon_url),
|
|
320
|
+
hasWebclip: !!absUrl(seo.webclip)
|
|
313
321
|
};
|
|
314
322
|
}
|
|
315
323
|
function extractPrimaryContext(contexts) {
|
|
@@ -347,12 +355,14 @@ async function prerender({
|
|
|
347
355
|
excludePaths = [],
|
|
348
356
|
failFast = false,
|
|
349
357
|
maxPages = 5e3,
|
|
358
|
+
concurrency = 6,
|
|
350
359
|
mode = "dir",
|
|
351
360
|
website = null,
|
|
352
361
|
websiteId = "",
|
|
353
362
|
redirects = [],
|
|
354
363
|
collections = {}
|
|
355
364
|
} = {}) {
|
|
365
|
+
var _a, _b;
|
|
356
366
|
const absRoot = path.resolve(root);
|
|
357
367
|
const absClient = path.resolve(absRoot, clientOutDir);
|
|
358
368
|
const absServerEntry = path.resolve(absRoot, serverEntry);
|
|
@@ -384,44 +394,67 @@ async function prerender({
|
|
|
384
394
|
const fontPreloads = await discoverFontPreloads(absClient);
|
|
385
395
|
const rendered = [];
|
|
386
396
|
const noindexPaths = /* @__PURE__ */ new Set();
|
|
397
|
+
const lastmod = {};
|
|
387
398
|
const failures = [];
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
399
|
+
async function renderOne(urlPath) {
|
|
400
|
+
const {
|
|
401
|
+
html,
|
|
402
|
+
head = "",
|
|
403
|
+
htmlAttrs = "",
|
|
404
|
+
lastmod: pageLastmod
|
|
405
|
+
} = await serverMod.render(urlPath, {
|
|
406
|
+
manifest,
|
|
407
|
+
template,
|
|
408
|
+
website,
|
|
409
|
+
websiteId,
|
|
410
|
+
collections
|
|
411
|
+
});
|
|
412
|
+
const outHtml = injectIntoTemplate(template, head, html, fontPreloads, htmlAttrs);
|
|
413
|
+
const outfile = outFilePath(absClient, urlPath, mode);
|
|
414
|
+
await fs.mkdir(path.dirname(outfile), { recursive: true });
|
|
415
|
+
await fs.writeFile(outfile, outHtml, "utf8");
|
|
416
|
+
rendered.push(urlPath);
|
|
417
|
+
if (pageLastmod) lastmod[urlPath] = pageLastmod;
|
|
418
|
+
if (/<meta[^>]+name=["']robots["'][^>]*noindex/i.test(head)) {
|
|
419
|
+
noindexPaths.add(urlPath);
|
|
420
|
+
}
|
|
421
|
+
if (crawl) {
|
|
422
|
+
for (const p of discoverInternalLinks(outHtml)) {
|
|
423
|
+
enqueue(p, queue, seen, isExcluded);
|
|
412
424
|
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
let stopped = false;
|
|
428
|
+
async function worker() {
|
|
429
|
+
while (!stopped) {
|
|
430
|
+
if (rendered.length >= maxPages) break;
|
|
431
|
+
const urlPath = queue.shift();
|
|
432
|
+
if (urlPath === void 0) break;
|
|
433
|
+
if (urlPath === "" || isExcluded(urlPath)) continue;
|
|
434
|
+
try {
|
|
435
|
+
await renderOne(urlPath);
|
|
436
|
+
} catch (err) {
|
|
437
|
+
failures.push({ path: urlPath, error: err });
|
|
438
|
+
if (failFast) {
|
|
439
|
+
stopped = true;
|
|
440
|
+
throw err;
|
|
441
|
+
}
|
|
442
|
+
console.warn(`[prerender] failed: ${urlPath}
|
|
417
443
|
`, err.stack ?? err);
|
|
444
|
+
}
|
|
418
445
|
}
|
|
419
446
|
}
|
|
420
|
-
|
|
421
|
-
|
|
447
|
+
while (queue.length && !stopped && rendered.length < maxPages) {
|
|
448
|
+
const workers = Array.from(
|
|
449
|
+
{ length: Math.min(concurrency, queue.length) },
|
|
450
|
+
() => worker()
|
|
451
|
+
);
|
|
452
|
+
await Promise.all(workers);
|
|
453
|
+
}
|
|
454
|
+
const canonicalBase = (((_a = website == null ? void 0 : website.seo) == null ? void 0 : _a.canonical_base_url) || (website == null ? void 0 : website.domain) || "").replace(/\/$/, "");
|
|
422
455
|
const sitemapPaths = rendered.filter((p) => !noindexPaths.has(p));
|
|
423
456
|
if (canonicalBase && sitemapPaths.length > 0) {
|
|
424
|
-
const sitemap = generateSitemapXml({ renderedPaths: sitemapPaths, canonicalBase });
|
|
457
|
+
const sitemap = generateSitemapXml({ renderedPaths: sitemapPaths, canonicalBase, lastmod });
|
|
425
458
|
await fs.writeFile(path.join(absClient, "sitemap.xml"), sitemap, "utf8");
|
|
426
459
|
const skipped = noindexPaths.size > 0 ? ` (${noindexPaths.size} noindex excluded)` : "";
|
|
427
460
|
console.log(` Generated sitemap.xml (${sitemapPaths.length} URLs)${skipped}`);
|
|
@@ -429,7 +462,7 @@ async function prerender({
|
|
|
429
462
|
const robotsTxt = generateRobotsTxt({
|
|
430
463
|
robotsTxt: website == null ? void 0 : website.robots_txt,
|
|
431
464
|
canonicalBase,
|
|
432
|
-
noindex:
|
|
465
|
+
noindex: (_b = website == null ? void 0 : website.seo) == null ? void 0 : _b.noindex
|
|
433
466
|
});
|
|
434
467
|
await fs.writeFile(path.join(absClient, "robots.txt"), robotsTxt, "utf8");
|
|
435
468
|
console.log(" Generated robots.txt");
|