@marvalt/digivalt-core 0.2.30 → 0.2.33
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/CHANGELOG.md +35 -0
- package/GLOBAL-SHORTCODES.md +7 -7
- package/README.md +10 -8
- package/bin/env-example-fragments.cjs +6 -0
- package/bin/init.cjs +44 -5
- package/dist/generators/index.d.ts +3 -0
- package/dist/generators/prerender-seo.d.ts +6 -0
- package/dist/generators/seo-manifest.d.ts +3 -0
- package/dist/generators/seo-urls.d.ts +29 -0
- package/dist/generators/sitemap-paths.d.ts +5 -9
- package/dist/generators.cjs +1005 -155
- package/dist/generators.cjs.map +1 -1
- package/dist/generators.d.ts +86 -6
- package/dist/generators.esm.js +992 -156
- package/dist/generators.esm.js.map +1 -1
- package/dist/index.cjs +1019 -156
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +103 -9
- package/dist/index.esm.js +1006 -157
- package/dist/index.esm.js.map +1 -1
- package/dist/registry/index.d.ts +20 -0
- package/dist/registry.cjs +1528 -0
- package/dist/registry.cjs.map +1 -0
- package/dist/registry.d.ts +26 -0
- package/dist/registry.esm.js +1523 -0
- package/dist/registry.esm.js.map +1 -0
- package/dist/seo/DigiValtRouteSeo.d.ts +12 -0
- package/dist/seo/DigiValtSeoHead.d.ts +2 -0
- package/dist/seo/buildPageJsonLd.d.ts +11 -0
- package/dist/seo/html.d.ts +8 -0
- package/dist/seo/index.d.ts +7 -0
- package/dist/seo/resolvePageSeo.d.ts +17 -0
- package/dist/seo/seoTypes.d.ts +57 -0
- package/dist/seo.cjs +307 -86
- package/dist/seo.cjs.map +1 -1
- package/dist/seo.d.ts +105 -2
- package/dist/seo.esm.js +300 -87
- package/dist/seo.esm.js.map +1 -1
- package/dist/static/wpStatic.d.ts +16 -0
- package/dist/static.cjs +10 -0
- package/dist/static.cjs.map +1 -1
- package/dist/static.d.ts +38 -2
- package/dist/static.esm.js +10 -1
- package/dist/static.esm.js.map +1 -1
- package/dist/utils/notifications.d.ts +3 -0
- package/docs/AI-LOCAL-WORDPRESS-BOOTSTRAP.md +7 -3
- package/docs/AI-MASTER-PROMPT.md +37 -0
- package/docs/ENVIRONMENT.md +3 -3
- package/docs/README.md +6 -4
- package/docs/SEO-AIO.md +59 -0
- package/docs/SEO-PERFORMANCE.md +44 -11
- package/docs/SHORTCODES.md +4 -5
- package/package.json +17 -6
- package/template/DIGIVALT_SETUP.md +14 -8
- package/template/functions/robots.txt.ts +27 -0
- package/template/functions/sitemap.xml.ts +143 -65
- package/template/scripts/generate.ts +3 -10
- package/template/scripts/prerender-seo.ts +10 -0
- package/docs/LOVABLE-MASTER-PROMPT.md +0 -140
package/dist/index.esm.js
CHANGED
|
@@ -361,21 +361,6 @@ async function generateGoogleReviewsData(options) {
|
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
363
|
|
|
364
|
-
const SITEMAP_SKIP_TOP_LEVEL_KEYS = new Set([
|
|
365
|
-
'config',
|
|
366
|
-
'site_settings',
|
|
367
|
-
'header',
|
|
368
|
-
'footer',
|
|
369
|
-
'theme_styles',
|
|
370
|
-
'navigation_menu',
|
|
371
|
-
'menus',
|
|
372
|
-
'categories',
|
|
373
|
-
'tags',
|
|
374
|
-
'generated_at',
|
|
375
|
-
'frontend_id',
|
|
376
|
-
'frontend_name',
|
|
377
|
-
'front_page',
|
|
378
|
-
]);
|
|
379
364
|
function normalizePathname(pathname) {
|
|
380
365
|
const decoded = decodeURIComponent(pathname);
|
|
381
366
|
if (!decoded || decoded === '/')
|
|
@@ -383,43 +368,265 @@ function normalizePathname(pathname) {
|
|
|
383
368
|
const stripped = decoded.replace(/\/+$/, '');
|
|
384
369
|
return stripped === '' ? '/' : stripped;
|
|
385
370
|
}
|
|
386
|
-
function
|
|
387
|
-
const
|
|
388
|
-
const
|
|
389
|
-
if (
|
|
390
|
-
|
|
391
|
-
|
|
371
|
+
function joinPath(prefix, slug) {
|
|
372
|
+
const p = prefix.replace(/\/+$/, '');
|
|
373
|
+
const s = slug.replace(/^\/+/, '');
|
|
374
|
+
if (!p || p === '/')
|
|
375
|
+
return normalizePathname(`/${s}`);
|
|
376
|
+
return normalizePathname(`${p.startsWith('/') ? p : `/${p}`}/${s}`);
|
|
377
|
+
}
|
|
378
|
+
function stripHtml(html) {
|
|
379
|
+
return html
|
|
380
|
+
.replace(/<script[\s\S]*?<\/script>/gi, ' ')
|
|
381
|
+
.replace(/<style[\s\S]*?<\/style>/gi, ' ')
|
|
382
|
+
.replace(/<[^>]+>/g, ' ')
|
|
383
|
+
.replace(/\s+/g, ' ')
|
|
384
|
+
.trim();
|
|
385
|
+
}
|
|
386
|
+
function sanitizeBodyHtml(html) {
|
|
387
|
+
return html
|
|
388
|
+
.replace(/<script[\s\S]*?<\/script>/gi, '')
|
|
389
|
+
.replace(/<style[\s\S]*?<\/style>/gi, '')
|
|
390
|
+
.replace(/\son\w+\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, '');
|
|
391
|
+
}
|
|
392
|
+
function renderedText(value) {
|
|
393
|
+
if (typeof value === 'string')
|
|
394
|
+
return stripHtml(value);
|
|
395
|
+
if (value && typeof value === 'object' && 'rendered' in value) {
|
|
396
|
+
const r = value.rendered;
|
|
397
|
+
if (typeof r === 'string')
|
|
398
|
+
return stripHtml(r);
|
|
399
|
+
}
|
|
400
|
+
return '';
|
|
401
|
+
}
|
|
402
|
+
function renderedHtml(value) {
|
|
403
|
+
if (typeof value === 'string')
|
|
404
|
+
return value;
|
|
405
|
+
if (value && typeof value === 'object' && 'rendered' in value) {
|
|
406
|
+
const r = value.rendered;
|
|
407
|
+
if (typeof r === 'string')
|
|
408
|
+
return r;
|
|
409
|
+
}
|
|
410
|
+
return '';
|
|
411
|
+
}
|
|
412
|
+
function escapeHtml(s) {
|
|
413
|
+
return s
|
|
414
|
+
.replace(/&/g, '&')
|
|
415
|
+
.replace(/</g, '<')
|
|
416
|
+
.replace(/>/g, '>')
|
|
417
|
+
.replace(/"/g, '"');
|
|
418
|
+
}
|
|
419
|
+
function escapeAttr(s) {
|
|
420
|
+
return escapeHtml(s).replace(/'/g, ''');
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const SITEMAP_URL_SHARD_SIZE = 45000;
|
|
424
|
+
function parseRoutePrefixes(raw) {
|
|
425
|
+
const out = {};
|
|
426
|
+
const src = (raw ?? process.env.VITE_SEO_ROUTE_PREFIXES ?? '').trim();
|
|
427
|
+
if (!src)
|
|
428
|
+
return out;
|
|
429
|
+
for (const part of src.split(',')) {
|
|
430
|
+
const trimmed = part.trim();
|
|
431
|
+
if (!trimmed)
|
|
432
|
+
continue;
|
|
433
|
+
const idx = trimmed.indexOf(':');
|
|
434
|
+
if (idx <= 0)
|
|
435
|
+
continue;
|
|
436
|
+
const key = trimmed.slice(0, idx).trim();
|
|
437
|
+
const prefix = trimmed.slice(idx + 1).trim();
|
|
438
|
+
if (key)
|
|
439
|
+
out[key] = prefix || '/';
|
|
440
|
+
}
|
|
441
|
+
return out;
|
|
442
|
+
}
|
|
443
|
+
function isPublishedEntity(item) {
|
|
444
|
+
const s = item.status;
|
|
445
|
+
if (s === undefined || s === null || s === '')
|
|
446
|
+
return true;
|
|
447
|
+
return s === 'publish';
|
|
448
|
+
}
|
|
449
|
+
function isNoindexEntity(item) {
|
|
450
|
+
return item.digivalt_seo?.robots_index === false;
|
|
451
|
+
}
|
|
452
|
+
function entityLastmod(item) {
|
|
453
|
+
const v = item.modified_gmt || item.modified || item.date_gmt || item.date;
|
|
454
|
+
return typeof v === 'string' && v.trim() ? v.trim() : undefined;
|
|
455
|
+
}
|
|
456
|
+
function entityImage(item) {
|
|
457
|
+
const v = item.digivalt_seo?.og_image ||
|
|
458
|
+
item.featured_media_cloudflare_url ||
|
|
459
|
+
item.featured_media_url;
|
|
460
|
+
return typeof v === 'string' && v.trim() ? v.trim() : undefined;
|
|
461
|
+
}
|
|
462
|
+
function getFrontPageRef(data) {
|
|
463
|
+
const fp = data.front_page;
|
|
464
|
+
const envSlug = (process.env.VITE_SEO_FRONT_PAGE_SLUG || '').trim();
|
|
465
|
+
let slug;
|
|
466
|
+
let id;
|
|
467
|
+
if (fp && typeof fp === 'object') {
|
|
468
|
+
const rec = fp;
|
|
469
|
+
if (typeof rec.slug === 'string' && rec.slug.trim())
|
|
470
|
+
slug = rec.slug.trim();
|
|
471
|
+
if (typeof rec.id === 'number')
|
|
472
|
+
id = rec.id;
|
|
473
|
+
else if (typeof rec.id === 'string')
|
|
474
|
+
id = Number(rec.id) || undefined;
|
|
475
|
+
}
|
|
476
|
+
if (envSlug)
|
|
477
|
+
slug = envSlug;
|
|
478
|
+
return { slug, id };
|
|
479
|
+
}
|
|
480
|
+
function getFrontPageSlug(data) {
|
|
481
|
+
return getFrontPageRef(data).slug;
|
|
482
|
+
}
|
|
483
|
+
function asRecord(item) {
|
|
484
|
+
if (!item || typeof item !== 'object')
|
|
485
|
+
return null;
|
|
486
|
+
return item;
|
|
487
|
+
}
|
|
488
|
+
function newsletterRouteBase() {
|
|
489
|
+
const raw = process.env.VITE_PHPLIST_NEWSLETTER_ROUTE_BASE || '/newsletters';
|
|
490
|
+
return normalizePathname(raw.startsWith('/') ? raw : `/${raw}`);
|
|
491
|
+
}
|
|
492
|
+
function collectSitemapUrls(args) {
|
|
493
|
+
const prefixes = args.prefixes ?? parseRoutePrefixes();
|
|
494
|
+
const front = args.wpData ? getFrontPageRef(args.wpData) : {};
|
|
495
|
+
const byPath = new Map();
|
|
496
|
+
const add = (entry) => {
|
|
497
|
+
const path = normalizePathname(entry.path);
|
|
498
|
+
if (!path)
|
|
499
|
+
return;
|
|
500
|
+
const prev = byPath.get(path);
|
|
501
|
+
if (!prev) {
|
|
502
|
+
byPath.set(path, { ...entry, path });
|
|
503
|
+
return;
|
|
392
504
|
}
|
|
393
|
-
|
|
394
|
-
|
|
505
|
+
byPath.set(path, {
|
|
506
|
+
path,
|
|
507
|
+
lastmod: entry.lastmod || prev.lastmod,
|
|
508
|
+
image: entry.image || prev.image,
|
|
509
|
+
});
|
|
510
|
+
};
|
|
511
|
+
add({ path: '/' });
|
|
512
|
+
for (const p of args.staticPaths) {
|
|
513
|
+
add({ path: p });
|
|
514
|
+
}
|
|
515
|
+
const pages = args.wpData && Array.isArray(args.wpData.pages) ? args.wpData.pages : [];
|
|
516
|
+
for (const raw of pages) {
|
|
517
|
+
const item = asRecord(raw);
|
|
518
|
+
if (!item || !isPublishedEntity(item) || isNoindexEntity(item))
|
|
519
|
+
continue;
|
|
520
|
+
const slug = typeof item.slug === 'string' ? item.slug.trim() : '';
|
|
521
|
+
if (!slug)
|
|
522
|
+
continue;
|
|
523
|
+
const isFront = (front.slug && slug === front.slug) ||
|
|
524
|
+
(typeof front.id === 'number' && typeof item.id === 'number' && item.id === front.id);
|
|
525
|
+
const path = isFront ? '/' : joinPath('/', slug);
|
|
526
|
+
add({
|
|
527
|
+
path,
|
|
528
|
+
lastmod: entityLastmod(item),
|
|
529
|
+
image: entityImage(item),
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
if (args.wpData) {
|
|
533
|
+
for (const [type, prefix] of Object.entries(prefixes)) {
|
|
534
|
+
if (type === 'pages' || type === 'page')
|
|
535
|
+
continue;
|
|
536
|
+
const arr = args.wpData[type];
|
|
537
|
+
if (!Array.isArray(arr))
|
|
538
|
+
continue;
|
|
539
|
+
for (const raw of arr) {
|
|
540
|
+
const item = asRecord(raw);
|
|
541
|
+
if (!item || !isPublishedEntity(item) || isNoindexEntity(item))
|
|
542
|
+
continue;
|
|
543
|
+
const slug = typeof item.slug === 'string' ? item.slug.trim() : '';
|
|
544
|
+
if (!slug)
|
|
545
|
+
continue;
|
|
546
|
+
add({
|
|
547
|
+
path: joinPath(prefix, slug),
|
|
548
|
+
lastmod: entityLastmod(item),
|
|
549
|
+
image: entityImage(item),
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
const newsletters = args.phplistData && Array.isArray(args.phplistData.newsletters)
|
|
555
|
+
? args.phplistData.newsletters
|
|
556
|
+
: [];
|
|
557
|
+
const nBase = newsletterRouteBase();
|
|
558
|
+
for (const raw of newsletters) {
|
|
559
|
+
if (!raw || typeof raw !== 'object')
|
|
560
|
+
continue;
|
|
561
|
+
const rec = raw;
|
|
562
|
+
if (typeof rec.slug !== 'string' || !rec.slug.trim())
|
|
563
|
+
continue;
|
|
564
|
+
add({
|
|
565
|
+
path: joinPath(nBase, rec.slug.trim()),
|
|
566
|
+
lastmod: typeof rec.sent_at === 'string' ? rec.sent_at : undefined,
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
const known = new Set(byPath.keys());
|
|
570
|
+
const considerMenu = (items) => {
|
|
571
|
+
if (!Array.isArray(items))
|
|
572
|
+
return;
|
|
573
|
+
for (const item of items) {
|
|
574
|
+
if (!item || typeof item !== 'object')
|
|
575
|
+
continue;
|
|
576
|
+
const rec = item;
|
|
577
|
+
if (typeof rec.url === 'string') {
|
|
578
|
+
const path = menuUrlToFrontendPath(rec.url, front.slug);
|
|
579
|
+
if (path && known.has(path)) {
|
|
580
|
+
add({ path });
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
considerMenu(rec.children);
|
|
395
584
|
}
|
|
585
|
+
};
|
|
586
|
+
if (args.wpData) {
|
|
587
|
+
const header = args.wpData.navigation_menu;
|
|
588
|
+
const footer = args.wpData.footer_navigation_menu;
|
|
589
|
+
considerMenu(header?.items);
|
|
590
|
+
considerMenu(footer?.items);
|
|
396
591
|
}
|
|
397
|
-
|
|
592
|
+
const sorted = [...byPath.values()].sort((a, b) => {
|
|
593
|
+
if (a.path === '/')
|
|
594
|
+
return -1;
|
|
595
|
+
if (b.path === '/')
|
|
596
|
+
return 1;
|
|
597
|
+
return a.path.localeCompare(b.path);
|
|
598
|
+
});
|
|
599
|
+
return sorted;
|
|
398
600
|
}
|
|
399
|
-
|
|
400
|
-
* When CMS host is unknown, accept any http(s) URL so local/offline merges still produce paths.
|
|
401
|
-
*/
|
|
402
|
-
function urlToPath(urlStr, allowedHosts) {
|
|
601
|
+
function menuUrlToFrontendPath(urlStr, frontSlug) {
|
|
403
602
|
const t = urlStr.trim();
|
|
404
603
|
if (!t || t === '#' || t.toLowerCase().startsWith('mailto:') || t.toLowerCase().startsWith('tel:')) {
|
|
405
604
|
return null;
|
|
406
605
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
let u;
|
|
411
|
-
try {
|
|
412
|
-
u = new URL(t);
|
|
606
|
+
let pathname;
|
|
607
|
+
if (t.startsWith('/')) {
|
|
608
|
+
pathname = normalizePathname(t.split('?')[0]);
|
|
413
609
|
}
|
|
414
|
-
|
|
415
|
-
|
|
610
|
+
else if (/^https?:\/\//i.test(t)) {
|
|
611
|
+
try {
|
|
612
|
+
pathname = normalizePathname(new URL(t).pathname);
|
|
613
|
+
}
|
|
614
|
+
catch {
|
|
615
|
+
return null;
|
|
616
|
+
}
|
|
416
617
|
}
|
|
417
|
-
|
|
618
|
+
else {
|
|
418
619
|
return null;
|
|
419
620
|
}
|
|
420
|
-
|
|
621
|
+
if (pathname === '/')
|
|
622
|
+
return '/';
|
|
623
|
+
const slug = pathname.replace(/^\//, '');
|
|
624
|
+
if (frontSlug && slug === frontSlug)
|
|
625
|
+
return '/';
|
|
626
|
+
return pathname;
|
|
421
627
|
}
|
|
422
|
-
|
|
628
|
+
|
|
629
|
+
function parseStaticPathsJson(raw) {
|
|
423
630
|
try {
|
|
424
631
|
const data = JSON.parse(raw);
|
|
425
632
|
if (Array.isArray(data)) {
|
|
@@ -434,130 +641,70 @@ function parsePathsJson(raw) {
|
|
|
434
641
|
}
|
|
435
642
|
return [];
|
|
436
643
|
}
|
|
437
|
-
function
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
const out = [];
|
|
445
|
-
for (const p of paths) {
|
|
446
|
-
if (p.startsWith('http://') || p.startsWith('https://')) {
|
|
447
|
-
const normalized = urlToPath(p, allowedHosts);
|
|
448
|
-
if (normalized)
|
|
449
|
-
out.push(normalized);
|
|
450
|
-
}
|
|
451
|
-
else {
|
|
452
|
-
out.push(normalizePathname(p));
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
return out;
|
|
456
|
-
}
|
|
457
|
-
function walkMenuItems(items, allowedHosts, out) {
|
|
458
|
-
if (!Array.isArray(items))
|
|
459
|
-
return;
|
|
460
|
-
for (const item of items) {
|
|
461
|
-
if (!item || typeof item !== 'object')
|
|
462
|
-
continue;
|
|
463
|
-
const rec = item;
|
|
464
|
-
if (typeof rec.url === 'string') {
|
|
465
|
-
const p = urlToPath(rec.url, allowedHosts);
|
|
466
|
-
if (p)
|
|
467
|
-
out.add(p);
|
|
468
|
-
}
|
|
469
|
-
if (Array.isArray(rec.children)) {
|
|
470
|
-
walkMenuItems(rec.children, allowedHosts, out);
|
|
644
|
+
function loadJson$1(full) {
|
|
645
|
+
if (!fs.existsSync(full))
|
|
646
|
+
return undefined;
|
|
647
|
+
try {
|
|
648
|
+
const data = JSON.parse(fs.readFileSync(full, 'utf8'));
|
|
649
|
+
if (data && typeof data === 'object' && !Array.isArray(data)) {
|
|
650
|
+
return data;
|
|
471
651
|
}
|
|
472
652
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
for (const item of arr) {
|
|
476
|
-
if (!item || typeof item !== 'object')
|
|
477
|
-
continue;
|
|
478
|
-
const link = item.link;
|
|
479
|
-
if (typeof link === 'string') {
|
|
480
|
-
const p = urlToPath(link, allowedHosts);
|
|
481
|
-
if (p)
|
|
482
|
-
out.add(p);
|
|
483
|
-
}
|
|
653
|
+
catch (e) {
|
|
654
|
+
console.warn('⚠️ Could not parse JSON for sitemap:', full, e.message);
|
|
484
655
|
}
|
|
656
|
+
return undefined;
|
|
485
657
|
}
|
|
486
|
-
function
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
const config = data.config;
|
|
493
|
-
const postTypeKeys = config?.post_types && typeof config.post_types === 'object'
|
|
494
|
-
? Object.keys(config.post_types)
|
|
495
|
-
: null;
|
|
496
|
-
if (postTypeKeys && postTypeKeys.length > 0) {
|
|
497
|
-
for (const key of postTypeKeys) {
|
|
498
|
-
const arr = data[key];
|
|
499
|
-
if (Array.isArray(arr)) {
|
|
500
|
-
collectLinksFromArray(arr, allowedHosts, out);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
else {
|
|
505
|
-
for (const [key, value] of Object.entries(data)) {
|
|
506
|
-
if (SITEMAP_SKIP_TOP_LEVEL_KEYS.has(key))
|
|
507
|
-
continue;
|
|
508
|
-
if (Array.isArray(value)) {
|
|
509
|
-
collectLinksFromArray(value, allowedHosts, out);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
return out;
|
|
658
|
+
function loadStaticPaths(cwd, staticInputPath) {
|
|
659
|
+
const full = path.join(cwd, staticInputPath);
|
|
660
|
+
if (!fs.existsSync(full))
|
|
661
|
+
return [];
|
|
662
|
+
return parseStaticPathsJson(fs.readFileSync(full, 'utf8')).map((p) => normalizePathname(p));
|
|
514
663
|
}
|
|
515
664
|
function writeFallback(cwd, outputPath) {
|
|
516
665
|
const full = path.join(cwd, outputPath);
|
|
517
666
|
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
518
|
-
|
|
667
|
+
const payload = { urls: [{ path: '/' }], paths: ['/'] };
|
|
668
|
+
fs.writeFileSync(full, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
|
|
669
|
+
}
|
|
670
|
+
function writeShard(full, urls) {
|
|
671
|
+
const paths = urls.map((u) => u.path);
|
|
672
|
+
fs.writeFileSync(full, `${JSON.stringify({ urls, paths }, null, 2)}\n`, 'utf8');
|
|
519
673
|
}
|
|
520
674
|
/**
|
|
521
|
-
* Merge
|
|
675
|
+
* Merge static app routes, WP pages (frontend paths), opt-in CPT prefixes, and PHPList issues.
|
|
522
676
|
*/
|
|
523
677
|
async function generateSitemapPaths(options = {}) {
|
|
524
678
|
dotenv.config();
|
|
525
679
|
dotenv.config({ path: '.env.local' });
|
|
526
680
|
const cwd = options.cwd ?? process.cwd();
|
|
527
681
|
const wpDataPath = options.wpDataPath ?? 'public/wordpress-data.json';
|
|
682
|
+
const phplistDataPath = options.phplistDataPath ?? 'public/phplist-data.json';
|
|
528
683
|
const staticInputPath = options.staticInputPath ?? 'public/sitemap-static-paths.json';
|
|
529
684
|
const outputPath = options.outputPath ?? 'public/sitemap-paths.json';
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
const wpFull = path.join(cwd, wpDataPath);
|
|
536
|
-
if (fs.existsSync(wpFull)) {
|
|
537
|
-
try {
|
|
538
|
-
const raw = fs.readFileSync(wpFull, 'utf8');
|
|
539
|
-
const data = JSON.parse(raw);
|
|
540
|
-
const fromWp = collectPathsFromWpData(data, allowedHosts);
|
|
541
|
-
for (const p of fromWp) {
|
|
542
|
-
merged.add(p);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
catch (e) {
|
|
546
|
-
console.warn('⚠️ Could not parse wordpress-data.json for sitemap paths:', e.message);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
merged.add('/');
|
|
550
|
-
const sorted = [...merged].sort((a, b) => {
|
|
551
|
-
if (a === '/')
|
|
552
|
-
return -1;
|
|
553
|
-
if (b === '/')
|
|
554
|
-
return 1;
|
|
555
|
-
return a.localeCompare(b);
|
|
685
|
+
const urls = collectSitemapUrls({
|
|
686
|
+
wpData: loadJson$1(path.join(cwd, wpDataPath)),
|
|
687
|
+
phplistData: loadJson$1(path.join(cwd, phplistDataPath)),
|
|
688
|
+
staticPaths: loadStaticPaths(cwd, staticInputPath),
|
|
689
|
+
prefixes: parseRoutePrefixes(),
|
|
556
690
|
});
|
|
557
691
|
const outFull = path.join(cwd, outputPath);
|
|
558
692
|
fs.mkdirSync(path.dirname(outFull), { recursive: true });
|
|
559
|
-
|
|
560
|
-
|
|
693
|
+
if (urls.length <= SITEMAP_URL_SHARD_SIZE) {
|
|
694
|
+
writeShard(outFull, urls);
|
|
695
|
+
console.log(`📍 Sitemap paths written (${urls.length} URLs): ${outFull}`);
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
const parts = Math.ceil(urls.length / SITEMAP_URL_SHARD_SIZE);
|
|
699
|
+
const dir = path.dirname(outFull);
|
|
700
|
+
const base = path.basename(outFull, path.extname(outFull));
|
|
701
|
+
const ext = path.extname(outFull) || '.json';
|
|
702
|
+
for (let i = 0; i < parts; i++) {
|
|
703
|
+
const slice = urls.slice(i * SITEMAP_URL_SHARD_SIZE, (i + 1) * SITEMAP_URL_SHARD_SIZE);
|
|
704
|
+
writeShard(path.join(dir, `${base}-${i}${ext}`), slice);
|
|
705
|
+
}
|
|
706
|
+
fs.writeFileSync(outFull, `${JSON.stringify({ index: true, parts }, null, 2)}\n`, 'utf8');
|
|
707
|
+
console.log(`📍 Sitemap index written (${urls.length} URLs, ${parts} parts): ${outFull}`);
|
|
561
708
|
}
|
|
562
709
|
async function generateSitemapPathsSafe(options = {}) {
|
|
563
710
|
try {
|
|
@@ -571,45 +718,747 @@ async function generateSitemapPathsSafe(options = {}) {
|
|
|
571
718
|
}
|
|
572
719
|
}
|
|
573
720
|
|
|
721
|
+
const getImportMetaEnv = () => {
|
|
722
|
+
try {
|
|
723
|
+
return typeof import.meta !== 'undefined' ? import.meta.env : undefined;
|
|
724
|
+
}
|
|
725
|
+
catch {
|
|
726
|
+
return undefined;
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
const getEnv = (key) => {
|
|
730
|
+
const viteEnv = getImportMetaEnv();
|
|
731
|
+
if (viteEnv && key in viteEnv) {
|
|
732
|
+
const value = viteEnv[key];
|
|
733
|
+
return value == null ? undefined : String(value);
|
|
734
|
+
}
|
|
735
|
+
if (typeof process !== 'undefined' && process.env && key in process.env) {
|
|
736
|
+
const value = process.env[key];
|
|
737
|
+
return value == null ? undefined : String(value);
|
|
738
|
+
}
|
|
739
|
+
return undefined;
|
|
740
|
+
};
|
|
741
|
+
const isDevEnvironment = () => {
|
|
742
|
+
const viteEnv = getImportMetaEnv();
|
|
743
|
+
if (viteEnv && 'DEV' in viteEnv) {
|
|
744
|
+
return Boolean(viteEnv.DEV);
|
|
745
|
+
}
|
|
746
|
+
return typeof process !== 'undefined' && process.env?.NODE_ENV === 'development';
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Integration Configuration
|
|
751
|
+
* Centralized configuration for all third-party integrations
|
|
752
|
+
*/
|
|
753
|
+
function envBool(key, defaultValue) {
|
|
754
|
+
const v = getEnv(key);
|
|
755
|
+
if (v === undefined || v === '')
|
|
756
|
+
return defaultValue;
|
|
757
|
+
const lower = v.toLowerCase();
|
|
758
|
+
if (lower === 'false' || lower === '0' || lower === 'no')
|
|
759
|
+
return false;
|
|
760
|
+
if (lower === 'true' || lower === '1' || lower === 'yes')
|
|
761
|
+
return true;
|
|
762
|
+
return defaultValue;
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Get integration configuration with environment variable fallbacks
|
|
766
|
+
*/
|
|
767
|
+
function getIntegrationConfig() {
|
|
768
|
+
isDevEnvironment();
|
|
769
|
+
return {
|
|
770
|
+
wordpress: {
|
|
771
|
+
enabled: true,
|
|
772
|
+
apiUrl: getEnv('VITE_WORDPRESS_API_URL') || '',
|
|
773
|
+
authMode: getEnv('VITE_AUTH_MODE') || 'direct',
|
|
774
|
+
},
|
|
775
|
+
supabase: {
|
|
776
|
+
enabled: getEnv('VITE_AUTH_MODE') === 'supabase_proxy',
|
|
777
|
+
url: getEnv('VITE_SUPABASE_URL') || '',
|
|
778
|
+
anonKey: getEnv('VITE_SUPABASE_ANON_KEY') || '',
|
|
779
|
+
serviceRoleKey: getEnv('VITE_SUPABASE_SERVICE_ROLE_KEY'),
|
|
780
|
+
},
|
|
781
|
+
gravityForms: {
|
|
782
|
+
enabled: !!(getEnv('VITE_CLOUDFLARE_WORKER_URL') || getEnv('VITE_WORDPRESS_API_URL')),
|
|
783
|
+
url: getEnv('VITE_WORDPRESS_API_URL'),
|
|
784
|
+
proxyUrl: getEnv('VITE_CLOUDFLARE_WORKER_URL'),
|
|
785
|
+
consumerKey: getEnv('VITE_GF_CONSUMER_KEY'),
|
|
786
|
+
consumerSecret: getEnv('VITE_GF_CONSUMER_SECRET'),
|
|
787
|
+
forms: {
|
|
788
|
+
'contact': {
|
|
789
|
+
name: 'Contact Form',
|
|
790
|
+
type: 'contact',
|
|
791
|
+
successMessage: 'Thank you for your message. We\'ll get back to you soon!',
|
|
792
|
+
},
|
|
793
|
+
'newsletter': {
|
|
794
|
+
name: 'Newsletter Signup',
|
|
795
|
+
type: 'newsletter',
|
|
796
|
+
successMessage: 'Thank you for subscribing to our newsletter!',
|
|
797
|
+
},
|
|
798
|
+
'support': {
|
|
799
|
+
name: 'Support Request',
|
|
800
|
+
type: 'support',
|
|
801
|
+
successMessage: 'Your support request has been submitted successfully.',
|
|
802
|
+
},
|
|
803
|
+
},
|
|
804
|
+
},
|
|
805
|
+
mautic: {
|
|
806
|
+
enabled: !!(getEnv('VITE_MAUTIC_PROXY_URL') || getEnv('VITE_MAUTIC_URL')),
|
|
807
|
+
url: getEnv('VITE_MAUTIC_URL') || '',
|
|
808
|
+
proxyUrl: getEnv('VITE_MAUTIC_PROXY_URL'),
|
|
809
|
+
forms: {
|
|
810
|
+
'1': {
|
|
811
|
+
name: 'Newsletter Signup',
|
|
812
|
+
type: 'newsletter',
|
|
813
|
+
successMessage: 'Thank you for subscribing to our newsletter!',
|
|
814
|
+
postAction: 'message',
|
|
815
|
+
postActionProperty: 'Thank you for your submission!'
|
|
816
|
+
},
|
|
817
|
+
'2': {
|
|
818
|
+
name: 'Contact Form',
|
|
819
|
+
type: 'contact',
|
|
820
|
+
successMessage: 'Thank you for contacting us! We\'ll get back to you soon.',
|
|
821
|
+
postAction: 'message',
|
|
822
|
+
postActionProperty: 'Thank you for your message!'
|
|
823
|
+
},
|
|
824
|
+
'3': {
|
|
825
|
+
name: 'Lead Capture',
|
|
826
|
+
type: 'lead',
|
|
827
|
+
successMessage: 'Thank you for your interest! We\'ll be in touch.',
|
|
828
|
+
postAction: 'message',
|
|
829
|
+
postActionProperty: 'Thank you for your submission!'
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
},
|
|
833
|
+
phplist: {
|
|
834
|
+
enabled: !!(getEnv('VITE_PHPLIST_URL') || getEnv('PHPLIST_URL')),
|
|
835
|
+
url: getEnv('VITE_PHPLIST_URL') || getEnv('PHPLIST_URL'),
|
|
836
|
+
proxyUrl: getEnv('VITE_PHPLIST_PROXY_URL') || getEnv('PHPLIST_PROXY_URL'),
|
|
837
|
+
listId: parseInt(getEnv('VITE_PHPLIST_LIST_ID') || getEnv('PHPLIST_LIST_ID') || '0', 10) || undefined,
|
|
838
|
+
subscribePageIds: (getEnv('VITE_PHPLIST_SUBSCRIBE_PAGE_IDS') || getEnv('PHPLIST_SUBSCRIBE_PAGE_IDS') || '')
|
|
839
|
+
.split(',')
|
|
840
|
+
.map((s) => parseInt(s.trim(), 10))
|
|
841
|
+
.filter((n) => !Number.isNaN(n)),
|
|
842
|
+
newsletterRouteBase: getEnv('VITE_PHPLIST_NEWSLETTER_ROUTE_BASE') || '/newsletters',
|
|
843
|
+
},
|
|
844
|
+
suiteCRM: {
|
|
845
|
+
enabled: !!(getEnv('VITE_SUITECRM_URL') && getEnv('VITE_SUITECRM_CLIENT_ID') && getEnv('VITE_SUITECRM_CLIENT_SECRET')),
|
|
846
|
+
url: getEnv('VITE_SUITECRM_URL'),
|
|
847
|
+
proxyUrl: getEnv('VITE_SUITECRM_PROXY_URL'),
|
|
848
|
+
appId: undefined,
|
|
849
|
+
workerSecret: undefined,
|
|
850
|
+
oauth2: {
|
|
851
|
+
clientId: getEnv('VITE_SUITECRM_CLIENT_ID'),
|
|
852
|
+
clientSecret: getEnv('VITE_SUITECRM_CLIENT_SECRET'),
|
|
853
|
+
username: getEnv('VITE_SUITECRM_USERNAME'),
|
|
854
|
+
password: getEnv('VITE_SUITECRM_PASSWORD'),
|
|
855
|
+
},
|
|
856
|
+
},
|
|
857
|
+
chatwoot: {
|
|
858
|
+
enabled: !!(getEnv('VITE_CHATWOOT_WEBSITE_TOKEN') && getEnv('VITE_CHATWOOT_BASE_URL')),
|
|
859
|
+
websiteToken: getEnv('VITE_CHATWOOT_WEBSITE_TOKEN') || '',
|
|
860
|
+
baseUrl: getEnv('VITE_CHATWOOT_BASE_URL') || '',
|
|
861
|
+
locale: 'en',
|
|
862
|
+
type: 'standard',
|
|
863
|
+
launcherTitle: 'Chat',
|
|
864
|
+
hideMessageBubble: false,
|
|
865
|
+
position: 'right',
|
|
866
|
+
showPopoutButton: false,
|
|
867
|
+
},
|
|
868
|
+
analytics: {
|
|
869
|
+
googleAnalytics: { enabled: false },
|
|
870
|
+
googleTagManager: { enabled: false },
|
|
871
|
+
facebookPixel: { enabled: false },
|
|
872
|
+
linkedinInsight: { enabled: false },
|
|
873
|
+
},
|
|
874
|
+
seo: (() => {
|
|
875
|
+
const opt = (key) => {
|
|
876
|
+
const v = getEnv(key);
|
|
877
|
+
if (v === undefined || v === '')
|
|
878
|
+
return undefined;
|
|
879
|
+
const t = v.trim();
|
|
880
|
+
return t || undefined;
|
|
881
|
+
};
|
|
882
|
+
const siteUrl = (getEnv('VITE_SEO_SITE_URL') || '').replace(/\/+$/, '').trim();
|
|
883
|
+
const siteName = (getEnv('VITE_SEO_SITE_NAME') || '').trim();
|
|
884
|
+
const defaultTitle = (getEnv('VITE_SEO_DEFAULT_TITLE') || '').trim() || siteName || '';
|
|
885
|
+
return {
|
|
886
|
+
defaultTitle,
|
|
887
|
+
defaultDescription: (getEnv('VITE_SEO_DEFAULT_DESCRIPTION') || '').trim(),
|
|
888
|
+
defaultKeywords: opt('VITE_SEO_DEFAULT_KEYWORDS'),
|
|
889
|
+
defaultImage: (getEnv('VITE_SEO_DEFAULT_OG_IMAGE') || '').trim(),
|
|
890
|
+
siteName,
|
|
891
|
+
siteUrl,
|
|
892
|
+
twitterHandle: opt('VITE_SEO_TWITTER_SITE'),
|
|
893
|
+
facebookAppId: opt('VITE_SEO_FACEBOOK_APP_ID'),
|
|
894
|
+
googleSiteVerification: opt('VITE_SEO_GOOGLE_SITE_VERIFICATION'),
|
|
895
|
+
bingSiteVerification: opt('VITE_SEO_BING_SITE_VERIFICATION'),
|
|
896
|
+
};
|
|
897
|
+
})(),
|
|
898
|
+
performance: {
|
|
899
|
+
enableLazyLoading: envBool('VITE_PERF_LAZY_LOADING', true),
|
|
900
|
+
enableImageOptimization: envBool('VITE_PERF_IMAGE_OPTIMIZATION', true),
|
|
901
|
+
enableCodeSplitting: envBool('VITE_PERF_CODE_SPLITTING', true),
|
|
902
|
+
enableServiceWorker: envBool('VITE_PERF_SERVICE_WORKER', false),
|
|
903
|
+
enableCaching: envBool('VITE_PERF_CACHING', true),
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
function getSEOConfig() {
|
|
908
|
+
return getIntegrationConfig().seo;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* SEO defaults from env-backed integration config (see `VITE_SEO_*` in docs).
|
|
913
|
+
*/
|
|
914
|
+
function getSeoDefaultsFromEnv() {
|
|
915
|
+
const seo = getSEOConfig();
|
|
916
|
+
return {
|
|
917
|
+
siteUrl: seo.siteUrl,
|
|
918
|
+
siteName: seo.siteName,
|
|
919
|
+
defaultTitle: seo.defaultTitle,
|
|
920
|
+
defaultDescription: seo.defaultDescription,
|
|
921
|
+
defaultKeywords: seo.defaultKeywords,
|
|
922
|
+
defaultImage: seo.defaultImage,
|
|
923
|
+
twitterHandle: seo.twitterHandle,
|
|
924
|
+
facebookAppId: seo.facebookAppId,
|
|
925
|
+
googleSiteVerification: seo.googleSiteVerification,
|
|
926
|
+
bingSiteVerification: seo.bingSiteVerification,
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
function firstNonEmpty(...values) {
|
|
931
|
+
for (const v of values) {
|
|
932
|
+
if (typeof v === 'string' && v.trim())
|
|
933
|
+
return v.trim();
|
|
934
|
+
}
|
|
935
|
+
return '';
|
|
936
|
+
}
|
|
937
|
+
function resolvePageSeo(entity, pathname, overrides) {
|
|
938
|
+
const d = getSeoDefaultsFromEnv();
|
|
939
|
+
const seo = entity?.digivalt_seo;
|
|
940
|
+
const title = firstNonEmpty(overrides?.title, seo?.title, renderedText(entity?.title), d.defaultTitle, d.siteName);
|
|
941
|
+
const description = firstNonEmpty(overrides?.description, seo?.description, renderedText(entity?.excerpt), d.defaultDescription);
|
|
942
|
+
const imageUrl = firstNonEmpty(overrides?.imageUrl, seo?.og_image, entity?.featured_media_cloudflare_url, entity?.featured_media_url, d.defaultImage);
|
|
943
|
+
const noindex = overrides?.noindex ?? seo?.robots_index === false;
|
|
944
|
+
const ogType = overrides?.ogType || seo?.og_type || 'website';
|
|
945
|
+
const canonicalUrl = firstNonEmpty(overrides?.canonicalUrl, seo?.canonical) || undefined;
|
|
946
|
+
const robotsFollow = seo?.robots_follow !== false;
|
|
947
|
+
let robots;
|
|
948
|
+
if (noindex && robotsFollow)
|
|
949
|
+
robots = 'noindex, follow';
|
|
950
|
+
else if (noindex)
|
|
951
|
+
robots = 'noindex, nofollow';
|
|
952
|
+
else if (!robotsFollow)
|
|
953
|
+
robots = 'index, nofollow';
|
|
954
|
+
return {
|
|
955
|
+
entity,
|
|
956
|
+
noindex,
|
|
957
|
+
head: {
|
|
958
|
+
pathname,
|
|
959
|
+
title: title || undefined,
|
|
960
|
+
description: description || undefined,
|
|
961
|
+
imageUrl: imageUrl || undefined,
|
|
962
|
+
canonicalUrl,
|
|
963
|
+
ogType,
|
|
964
|
+
noindex,
|
|
965
|
+
robots,
|
|
966
|
+
},
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
const createOrganizationSchema = (data) => ({
|
|
971
|
+
'@context': 'https://schema.org',
|
|
972
|
+
'@type': 'Organization',
|
|
973
|
+
name: data.name,
|
|
974
|
+
url: data.url,
|
|
975
|
+
...(data.logo && { logo: data.logo }),
|
|
976
|
+
...(data.description && { description: data.description }),
|
|
977
|
+
...(data.address && {
|
|
978
|
+
address: {
|
|
979
|
+
'@type': 'PostalAddress',
|
|
980
|
+
...data.address,
|
|
981
|
+
},
|
|
982
|
+
}),
|
|
983
|
+
...(data.contactPoint && {
|
|
984
|
+
contactPoint: {
|
|
985
|
+
'@type': 'ContactPoint',
|
|
986
|
+
...data.contactPoint,
|
|
987
|
+
},
|
|
988
|
+
}),
|
|
989
|
+
});
|
|
990
|
+
const createWebSiteSchema = (data) => ({
|
|
991
|
+
'@context': 'https://schema.org',
|
|
992
|
+
'@type': 'WebSite',
|
|
993
|
+
name: data.name,
|
|
994
|
+
url: data.url,
|
|
995
|
+
...(data.description && { description: data.description }),
|
|
996
|
+
...(data.publisher && { publisher: data.publisher }),
|
|
997
|
+
});
|
|
998
|
+
const createArticleSchema = (data) => ({
|
|
999
|
+
'@context': 'https://schema.org',
|
|
1000
|
+
'@type': 'Article',
|
|
1001
|
+
headline: data.headline,
|
|
1002
|
+
description: data.description,
|
|
1003
|
+
...(data.image && { image: data.image }),
|
|
1004
|
+
author: {
|
|
1005
|
+
'@type': 'Person',
|
|
1006
|
+
name: data.author,
|
|
1007
|
+
},
|
|
1008
|
+
publisher: {
|
|
1009
|
+
'@type': 'Organization',
|
|
1010
|
+
name: data.publisher,
|
|
1011
|
+
},
|
|
1012
|
+
datePublished: data.datePublished,
|
|
1013
|
+
...(data.dateModified && { dateModified: data.dateModified }),
|
|
1014
|
+
url: data.url,
|
|
1015
|
+
});
|
|
1016
|
+
const createServiceSchema = (data) => ({
|
|
1017
|
+
'@context': 'https://schema.org',
|
|
1018
|
+
'@type': 'Service',
|
|
1019
|
+
name: data.name,
|
|
1020
|
+
description: data.description,
|
|
1021
|
+
provider: {
|
|
1022
|
+
'@type': 'Organization',
|
|
1023
|
+
name: data.provider,
|
|
1024
|
+
},
|
|
1025
|
+
url: data.url,
|
|
1026
|
+
...(data.areaServed && { areaServed: data.areaServed }),
|
|
1027
|
+
...(data.serviceType && { serviceType: data.serviceType }),
|
|
1028
|
+
});
|
|
1029
|
+
const createFAQSchema = (faqs) => ({
|
|
1030
|
+
'@context': 'https://schema.org',
|
|
1031
|
+
'@type': 'FAQPage',
|
|
1032
|
+
mainEntity: faqs.map(faq => ({
|
|
1033
|
+
'@type': 'Question',
|
|
1034
|
+
name: faq.question,
|
|
1035
|
+
acceptedAnswer: {
|
|
1036
|
+
'@type': 'Answer',
|
|
1037
|
+
text: faq.answer,
|
|
1038
|
+
},
|
|
1039
|
+
})),
|
|
1040
|
+
});
|
|
1041
|
+
|
|
1042
|
+
function joinAbsoluteUrl(siteUrl, pathname) {
|
|
1043
|
+
const base = siteUrl.replace(/\/+$/, '');
|
|
1044
|
+
if (pathname === '/')
|
|
1045
|
+
return base || pathname;
|
|
1046
|
+
const p = pathname.startsWith('/') ? pathname : `/${pathname}`;
|
|
1047
|
+
return base ? `${base}${p}` : p;
|
|
1048
|
+
}
|
|
1049
|
+
function extraToList(extra) {
|
|
1050
|
+
if (!extra)
|
|
1051
|
+
return [];
|
|
1052
|
+
if (Array.isArray(extra)) {
|
|
1053
|
+
return extra.filter((x) => !!x && typeof x === 'object');
|
|
1054
|
+
}
|
|
1055
|
+
if (typeof extra === 'object')
|
|
1056
|
+
return [extra];
|
|
1057
|
+
return [];
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* JSON-LD for a route: WebSite + Organization (from env) plus page schema from DigiValt SEO fields.
|
|
1061
|
+
*/
|
|
1062
|
+
function buildPageJsonLd(entity, pathname, options) {
|
|
1063
|
+
const d = getSeoDefaultsFromEnv();
|
|
1064
|
+
const seo = entity?.digivalt_seo;
|
|
1065
|
+
const title = options?.title ||
|
|
1066
|
+
seo?.title ||
|
|
1067
|
+
renderedText(entity?.title) ||
|
|
1068
|
+
d.defaultTitle ||
|
|
1069
|
+
d.siteName;
|
|
1070
|
+
const description = options?.description ||
|
|
1071
|
+
seo?.description ||
|
|
1072
|
+
renderedText(entity?.excerpt) ||
|
|
1073
|
+
d.defaultDescription;
|
|
1074
|
+
const image = options?.imageUrl ||
|
|
1075
|
+
seo?.og_image ||
|
|
1076
|
+
entity?.featured_media_cloudflare_url ||
|
|
1077
|
+
entity?.featured_media_url ||
|
|
1078
|
+
d.defaultImage;
|
|
1079
|
+
const url = options?.canonicalUrl ||
|
|
1080
|
+
seo?.canonical ||
|
|
1081
|
+
(d.siteUrl ? joinAbsoluteUrl(d.siteUrl, pathname || '/') : pathname);
|
|
1082
|
+
const out = [];
|
|
1083
|
+
if (d.siteName && d.siteUrl) {
|
|
1084
|
+
out.push(createWebSiteSchema({
|
|
1085
|
+
name: d.siteName,
|
|
1086
|
+
url: d.siteUrl,
|
|
1087
|
+
description: d.defaultDescription || undefined,
|
|
1088
|
+
}));
|
|
1089
|
+
out.push(createOrganizationSchema({
|
|
1090
|
+
name: d.siteName,
|
|
1091
|
+
url: d.siteUrl,
|
|
1092
|
+
logo: d.defaultImage || undefined,
|
|
1093
|
+
description: d.defaultDescription || undefined,
|
|
1094
|
+
}));
|
|
1095
|
+
}
|
|
1096
|
+
const schemaType = seo?.schema_type || 'WebPage';
|
|
1097
|
+
if (schemaType === 'Article') {
|
|
1098
|
+
out.push(createArticleSchema({
|
|
1099
|
+
headline: title,
|
|
1100
|
+
description: description || title,
|
|
1101
|
+
image: image || undefined,
|
|
1102
|
+
author: d.siteName || 'Publisher',
|
|
1103
|
+
publisher: d.siteName || 'Publisher',
|
|
1104
|
+
datePublished: entity?.date_gmt || entity?.date || new Date().toISOString(),
|
|
1105
|
+
dateModified: entity?.modified_gmt || entity?.modified,
|
|
1106
|
+
url,
|
|
1107
|
+
}));
|
|
1108
|
+
}
|
|
1109
|
+
else if (schemaType === 'Service') {
|
|
1110
|
+
out.push(createServiceSchema({
|
|
1111
|
+
name: title,
|
|
1112
|
+
description: description || title,
|
|
1113
|
+
provider: d.siteName || title,
|
|
1114
|
+
url,
|
|
1115
|
+
}));
|
|
1116
|
+
}
|
|
1117
|
+
else if (schemaType === 'FAQPage' || (seo?.faq && seo.faq.length > 0)) {
|
|
1118
|
+
const faqs = (seo?.faq || []).filter((f) => f.question && f.answer);
|
|
1119
|
+
if (faqs.length) {
|
|
1120
|
+
out.push(createFAQSchema(faqs));
|
|
1121
|
+
}
|
|
1122
|
+
else {
|
|
1123
|
+
out.push({
|
|
1124
|
+
'@context': 'https://schema.org',
|
|
1125
|
+
'@type': 'WebPage',
|
|
1126
|
+
name: title,
|
|
1127
|
+
description: description || undefined,
|
|
1128
|
+
url,
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
out.push({
|
|
1134
|
+
'@context': 'https://schema.org',
|
|
1135
|
+
'@type': 'WebPage',
|
|
1136
|
+
name: title,
|
|
1137
|
+
description: description || undefined,
|
|
1138
|
+
url,
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
out.push(...extraToList(seo?.extra_json_ld));
|
|
1142
|
+
return out;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
function loadJson(full) {
|
|
1146
|
+
if (!fs.existsSync(full))
|
|
1147
|
+
return undefined;
|
|
1148
|
+
try {
|
|
1149
|
+
const data = JSON.parse(fs.readFileSync(full, 'utf8'));
|
|
1150
|
+
if (data && typeof data === 'object' && !Array.isArray(data)) {
|
|
1151
|
+
return data;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
catch {
|
|
1155
|
+
/* ignore */
|
|
1156
|
+
}
|
|
1157
|
+
return undefined;
|
|
1158
|
+
}
|
|
1159
|
+
function parseStaticPaths(full) {
|
|
1160
|
+
if (!fs.existsSync(full))
|
|
1161
|
+
return [];
|
|
1162
|
+
try {
|
|
1163
|
+
const data = JSON.parse(fs.readFileSync(full, 'utf8'));
|
|
1164
|
+
const list = Array.isArray(data)
|
|
1165
|
+
? data
|
|
1166
|
+
: data && typeof data === 'object' && Array.isArray(data.paths)
|
|
1167
|
+
? data.paths
|
|
1168
|
+
: [];
|
|
1169
|
+
return list.filter((p) => typeof p === 'string' && p.startsWith('/')).map(normalizePathname);
|
|
1170
|
+
}
|
|
1171
|
+
catch {
|
|
1172
|
+
return [];
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
function asEntity(item) {
|
|
1176
|
+
if (!item || typeof item !== 'object')
|
|
1177
|
+
return undefined;
|
|
1178
|
+
return item;
|
|
1179
|
+
}
|
|
1180
|
+
function findEntityForPath(pathname, wpData, phplistData) {
|
|
1181
|
+
const front = wpData ? getFrontPageRef(wpData) : {};
|
|
1182
|
+
const pages = wpData && Array.isArray(wpData.pages) ? wpData.pages : [];
|
|
1183
|
+
if (pathname === '/') {
|
|
1184
|
+
const hit = pages.find((p) => {
|
|
1185
|
+
const ent = asEntity(p);
|
|
1186
|
+
if (!ent)
|
|
1187
|
+
return false;
|
|
1188
|
+
if (front.slug && ent.slug === front.slug)
|
|
1189
|
+
return true;
|
|
1190
|
+
if (typeof front.id === 'number' && typeof p.id === 'number') {
|
|
1191
|
+
return p.id === front.id;
|
|
1192
|
+
}
|
|
1193
|
+
return false;
|
|
1194
|
+
});
|
|
1195
|
+
return asEntity(hit);
|
|
1196
|
+
}
|
|
1197
|
+
const pageSlug = pathname.replace(/^\//, '');
|
|
1198
|
+
const pageHit = pages.find((p) => asEntity(p)?.slug === pageSlug);
|
|
1199
|
+
if (pageHit)
|
|
1200
|
+
return asEntity(pageHit);
|
|
1201
|
+
const prefixes = parseRoutePrefixes();
|
|
1202
|
+
for (const [type, prefix] of Object.entries(prefixes)) {
|
|
1203
|
+
const normalizedPrefix = normalizePathname(prefix.startsWith('/') ? prefix : `/${prefix}`);
|
|
1204
|
+
if (pathname === normalizedPrefix)
|
|
1205
|
+
continue;
|
|
1206
|
+
if (!pathname.startsWith(`${normalizedPrefix}/`))
|
|
1207
|
+
continue;
|
|
1208
|
+
const slug = pathname.slice(normalizedPrefix.length).replace(/^\//, '');
|
|
1209
|
+
const arr = wpData?.[type];
|
|
1210
|
+
if (!Array.isArray(arr))
|
|
1211
|
+
continue;
|
|
1212
|
+
const hit = arr.find((p) => asEntity(p)?.slug === slug);
|
|
1213
|
+
if (hit)
|
|
1214
|
+
return asEntity(hit);
|
|
1215
|
+
}
|
|
1216
|
+
const nBase = newsletterRouteBase();
|
|
1217
|
+
if (pathname.startsWith(`${nBase}/`) || (nBase !== '/' && pathname.startsWith(`${nBase}/`))) {
|
|
1218
|
+
const slug = nBase === '/' ? pathname.replace(/^\//, '') : pathname.slice(nBase.length).replace(/^\//, '');
|
|
1219
|
+
const newsletters = phplistData && Array.isArray(phplistData.newsletters) ? phplistData.newsletters : [];
|
|
1220
|
+
const hit = newsletters.find((n) => n && typeof n === 'object' && n.slug === slug);
|
|
1221
|
+
if (hit && typeof hit === 'object') {
|
|
1222
|
+
const rec = hit;
|
|
1223
|
+
return {
|
|
1224
|
+
slug: rec.slug,
|
|
1225
|
+
title: { rendered: rec.subject || '' },
|
|
1226
|
+
excerpt: { rendered: rec.excerpt || '' },
|
|
1227
|
+
content: { rendered: rec.html || '' },
|
|
1228
|
+
date: rec.sent_at,
|
|
1229
|
+
modified: rec.sent_at,
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
return undefined;
|
|
1234
|
+
}
|
|
1235
|
+
async function generateSeoManifest(options = {}) {
|
|
1236
|
+
dotenv.config();
|
|
1237
|
+
dotenv.config({ path: '.env.local' });
|
|
1238
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1239
|
+
const wpDataPath = options.wpDataPath ?? 'public/wordpress-data.json';
|
|
1240
|
+
const phplistDataPath = options.phplistDataPath ?? 'public/phplist-data.json';
|
|
1241
|
+
const staticInputPath = options.staticInputPath ?? 'public/sitemap-static-paths.json';
|
|
1242
|
+
const manifestOutputPath = options.manifestOutputPath ?? 'public/seo-manifest.json';
|
|
1243
|
+
const wpData = loadJson(path.join(cwd, wpDataPath));
|
|
1244
|
+
const phplistData = loadJson(path.join(cwd, phplistDataPath));
|
|
1245
|
+
const staticPaths = parseStaticPaths(path.join(cwd, staticInputPath));
|
|
1246
|
+
const urls = collectSitemapUrls({
|
|
1247
|
+
wpData,
|
|
1248
|
+
phplistData,
|
|
1249
|
+
staticPaths,
|
|
1250
|
+
prefixes: parseRoutePrefixes(),
|
|
1251
|
+
});
|
|
1252
|
+
const defaults = getSeoDefaultsFromEnv();
|
|
1253
|
+
const entries = urls.map((u) => {
|
|
1254
|
+
const entity = findEntityForPath(u.path, wpData, phplistData);
|
|
1255
|
+
const resolved = resolvePageSeo(entity, u.path);
|
|
1256
|
+
const jsonLd = buildPageJsonLd(entity, u.path, {
|
|
1257
|
+
title: resolved.head.title,
|
|
1258
|
+
description: resolved.head.description,
|
|
1259
|
+
imageUrl: resolved.head.imageUrl,
|
|
1260
|
+
canonicalUrl: resolved.head.canonicalUrl,
|
|
1261
|
+
});
|
|
1262
|
+
const bodySource = (typeof entity?.content_cloudflare === 'string' && entity.content_cloudflare) ||
|
|
1263
|
+
renderedHtml(entity?.content);
|
|
1264
|
+
return {
|
|
1265
|
+
path: u.path,
|
|
1266
|
+
title: resolved.head.title || defaults.defaultTitle || defaults.siteName || '',
|
|
1267
|
+
description: resolved.head.description || defaults.defaultDescription || '',
|
|
1268
|
+
canonical: resolved.head.canonicalUrl,
|
|
1269
|
+
image: resolved.head.imageUrl || u.image,
|
|
1270
|
+
noindex: resolved.noindex,
|
|
1271
|
+
ogType: resolved.head.ogType,
|
|
1272
|
+
jsonLd,
|
|
1273
|
+
bodyHtml: bodySource ? sanitizeBodyHtml(bodySource) : '',
|
|
1274
|
+
};
|
|
1275
|
+
});
|
|
1276
|
+
const full = path.join(cwd, manifestOutputPath);
|
|
1277
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
1278
|
+
fs.writeFileSync(full, `${JSON.stringify({ generated_at: new Date().toISOString(), urls: entries }, null, 2)}\n`, 'utf8');
|
|
1279
|
+
console.log(`📍 SEO manifest written (${entries.length} URLs): ${full}`);
|
|
1280
|
+
}
|
|
1281
|
+
async function generateSeoManifestSafe(options = {}) {
|
|
1282
|
+
try {
|
|
1283
|
+
await generateSeoManifest(options);
|
|
1284
|
+
}
|
|
1285
|
+
catch (e) {
|
|
1286
|
+
console.error('❌ SEO manifest generation failed:', e.message);
|
|
1287
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1288
|
+
const manifestOutputPath = options.manifestOutputPath ?? 'public/seo-manifest.json';
|
|
1289
|
+
const full = path.join(cwd, manifestOutputPath);
|
|
1290
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
1291
|
+
fs.writeFileSync(full, `${JSON.stringify({ urls: [] }, null, 2)}\n`, 'utf8');
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
function upsertMeta(html, attrName, attrValue, content) {
|
|
1296
|
+
const re = new RegExp(`<meta\\s+[^>]*${attrName}=["']${attrValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}["'][^>]*>`, 'i');
|
|
1297
|
+
const tag = `<meta ${attrName}="${escapeAttr(attrValue)}" content="${escapeAttr(content)}" />`;
|
|
1298
|
+
if (re.test(html))
|
|
1299
|
+
return html.replace(re, tag);
|
|
1300
|
+
return html.replace(/<\/head>/i, ` ${tag}\n </head>`);
|
|
1301
|
+
}
|
|
1302
|
+
function upsertLink(html, rel, href) {
|
|
1303
|
+
const re = new RegExp(`<link\\s+[^>]*rel=["']${rel}["'][^>]*>`, 'i');
|
|
1304
|
+
const tag = `<link rel="${escapeAttr(rel)}" href="${escapeAttr(href)}" />`;
|
|
1305
|
+
if (re.test(html))
|
|
1306
|
+
return html.replace(re, tag);
|
|
1307
|
+
return html.replace(/<\/head>/i, ` ${tag}\n </head>`);
|
|
1308
|
+
}
|
|
1309
|
+
function injectJsonLd(html, blocks) {
|
|
1310
|
+
if (!blocks?.length)
|
|
1311
|
+
return html;
|
|
1312
|
+
const scripts = blocks
|
|
1313
|
+
.map((b) => `<script type="application/ld+json">${JSON.stringify(b).replace(/</g, '\\u003c')}</script>`)
|
|
1314
|
+
.join('\n ');
|
|
1315
|
+
return html.replace(/<\/head>/i, ` ${scripts}\n </head>`);
|
|
1316
|
+
}
|
|
1317
|
+
function applyEntry(html, entry) {
|
|
1318
|
+
let out = html;
|
|
1319
|
+
if (entry.title) {
|
|
1320
|
+
out = out.replace(/<title>[\s\S]*?<\/title>/i, `<title>${escapeHtml(entry.title)}</title>`);
|
|
1321
|
+
}
|
|
1322
|
+
if (entry.description) {
|
|
1323
|
+
out = upsertMeta(out, 'name', 'description', entry.description);
|
|
1324
|
+
out = upsertMeta(out, 'property', 'og:description', entry.description);
|
|
1325
|
+
}
|
|
1326
|
+
if (entry.title) {
|
|
1327
|
+
out = upsertMeta(out, 'property', 'og:title', entry.title);
|
|
1328
|
+
out = upsertMeta(out, 'name', 'twitter:title', entry.title);
|
|
1329
|
+
}
|
|
1330
|
+
if (entry.canonical) {
|
|
1331
|
+
out = upsertLink(out, 'canonical', entry.canonical);
|
|
1332
|
+
out = upsertMeta(out, 'property', 'og:url', entry.canonical);
|
|
1333
|
+
}
|
|
1334
|
+
if (entry.image) {
|
|
1335
|
+
out = upsertMeta(out, 'property', 'og:image', entry.image);
|
|
1336
|
+
out = upsertMeta(out, 'name', 'twitter:image', entry.image);
|
|
1337
|
+
}
|
|
1338
|
+
if (entry.ogType) {
|
|
1339
|
+
out = upsertMeta(out, 'property', 'og:type', entry.ogType);
|
|
1340
|
+
}
|
|
1341
|
+
if (entry.noindex) {
|
|
1342
|
+
out = upsertMeta(out, 'name', 'robots', 'noindex, nofollow');
|
|
1343
|
+
}
|
|
1344
|
+
out = injectJsonLd(out, entry.jsonLd);
|
|
1345
|
+
const snapshot = `<article data-digivalt-prerender><h1>${escapeHtml(entry.title || '')}</h1>${entry.description ? `<p>${escapeHtml(entry.description)}</p>` : ''}${entry.bodyHtml || ''}</article>`;
|
|
1346
|
+
if (/<div id="root"><\/div>/i.test(out)) {
|
|
1347
|
+
out = out.replace(/<div id="root"><\/div>/i, `<div id="root">${snapshot}</div>`);
|
|
1348
|
+
}
|
|
1349
|
+
else if (/<div id="root">[\s\S]*?<\/div>/i.test(out)) {
|
|
1350
|
+
out = out.replace(/<div id="root">[\s\S]*?<\/div>/i, `<div id="root">${snapshot}</div>`);
|
|
1351
|
+
}
|
|
1352
|
+
return out;
|
|
1353
|
+
}
|
|
1354
|
+
function distFileForPath(distAbs, urlPath) {
|
|
1355
|
+
if (urlPath === '/')
|
|
1356
|
+
return path.join(distAbs, 'index.html');
|
|
1357
|
+
const rel = urlPath.replace(/^\//, '');
|
|
1358
|
+
return path.join(distAbs, rel, 'index.html');
|
|
1359
|
+
}
|
|
1360
|
+
async function prerenderSeoHtml(options = {}) {
|
|
1361
|
+
dotenv.config();
|
|
1362
|
+
dotenv.config({ path: '.env.local' });
|
|
1363
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1364
|
+
const distDir = options.distDir ?? 'dist';
|
|
1365
|
+
const distAbs = path.join(cwd, distDir);
|
|
1366
|
+
const indexFile = path.join(distAbs, 'index.html');
|
|
1367
|
+
if (!fs.existsSync(indexFile)) {
|
|
1368
|
+
console.warn('⚠️ prerenderSeoHtml: dist/index.html missing; skip.');
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
const manifestCandidates = [
|
|
1372
|
+
options.manifestPath ? path.join(cwd, options.manifestPath) : '',
|
|
1373
|
+
path.join(distAbs, 'seo-manifest.json'),
|
|
1374
|
+
path.join(cwd, 'public', 'seo-manifest.json'),
|
|
1375
|
+
].filter(Boolean);
|
|
1376
|
+
let manifestRaw;
|
|
1377
|
+
for (const p of manifestCandidates) {
|
|
1378
|
+
if (fs.existsSync(p)) {
|
|
1379
|
+
manifestRaw = fs.readFileSync(p, 'utf8');
|
|
1380
|
+
break;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
if (!manifestRaw) {
|
|
1384
|
+
console.warn('⚠️ prerenderSeoHtml: seo-manifest.json missing; skip.');
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
let urls = [];
|
|
1388
|
+
try {
|
|
1389
|
+
const data = JSON.parse(manifestRaw);
|
|
1390
|
+
urls = Array.isArray(data.urls) ? data.urls : [];
|
|
1391
|
+
}
|
|
1392
|
+
catch (e) {
|
|
1393
|
+
console.warn('⚠️ prerenderSeoHtml: invalid manifest:', e.message);
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
const template = fs.readFileSync(indexFile, 'utf8');
|
|
1397
|
+
let written = 0;
|
|
1398
|
+
for (const entry of urls) {
|
|
1399
|
+
if (!entry?.path)
|
|
1400
|
+
continue;
|
|
1401
|
+
const html = applyEntry(template, entry);
|
|
1402
|
+
const dest = distFileForPath(distAbs, entry.path);
|
|
1403
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
1404
|
+
fs.writeFileSync(dest, html, 'utf8');
|
|
1405
|
+
written += 1;
|
|
1406
|
+
}
|
|
1407
|
+
console.log(`📍 Prerendered ${written} HTML snapshots into ${distAbs}`);
|
|
1408
|
+
}
|
|
1409
|
+
|
|
574
1410
|
async function generateAllData() {
|
|
575
|
-
// Load .env files if they exist (for local development)
|
|
576
1411
|
dotenv.config();
|
|
577
1412
|
dotenv.config({ path: '.env.local' });
|
|
578
1413
|
console.log('🚀 Starting DigiVAlt static data generation...');
|
|
579
1414
|
if (process.env.VITE_IS_LOVABLE === 'true') {
|
|
580
|
-
console.log('⚡
|
|
581
|
-
return;
|
|
1415
|
+
console.log('⚡ Fixture mode (`VITE_IS_LOVABLE`) enabled. Skipping remote fetch; refreshing sitemap and SEO manifest from committed JSON.');
|
|
582
1416
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
1417
|
+
else {
|
|
1418
|
+
const wpSuccess = await generateWordPressData();
|
|
1419
|
+
const gfSuccess = await generateGravityFormsData();
|
|
1420
|
+
await generateMauticData();
|
|
1421
|
+
await generatePhplistData();
|
|
1422
|
+
await generateSuiteCRMData();
|
|
1423
|
+
await generateGoogleReviewsData();
|
|
1424
|
+
if (!wpSuccess || !gfSuccess) {
|
|
1425
|
+
console.error('❌ Required generation failed (WordPress or Gravity Forms). See above for details.');
|
|
1426
|
+
process.exit(1);
|
|
1427
|
+
}
|
|
593
1428
|
}
|
|
594
1429
|
await generateSitemapPathsSafe();
|
|
1430
|
+
await generateSeoManifestSafe();
|
|
595
1431
|
console.log('✅ Generation complete!');
|
|
596
1432
|
}
|
|
597
1433
|
|
|
598
1434
|
var index = /*#__PURE__*/Object.freeze({
|
|
599
1435
|
__proto__: null,
|
|
600
1436
|
PSEUDO_POST_TYPES: PSEUDO_POST_TYPES,
|
|
1437
|
+
SITEMAP_URL_SHARD_SIZE: SITEMAP_URL_SHARD_SIZE,
|
|
1438
|
+
collectSitemapUrls: collectSitemapUrls,
|
|
1439
|
+
entityImage: entityImage,
|
|
1440
|
+
entityLastmod: entityLastmod,
|
|
601
1441
|
generateAllData: generateAllData,
|
|
602
1442
|
generateGoogleReviewsData: generateGoogleReviewsData,
|
|
603
1443
|
generateGravityFormsData: generateGravityFormsData,
|
|
604
1444
|
generateMauticData: generateMauticData,
|
|
605
1445
|
generatePhplistData: generatePhplistData,
|
|
1446
|
+
generateSeoManifest: generateSeoManifest,
|
|
1447
|
+
generateSeoManifestSafe: generateSeoManifestSafe,
|
|
606
1448
|
generateSitemapPaths: generateSitemapPaths,
|
|
607
1449
|
generateSitemapPathsSafe: generateSitemapPathsSafe,
|
|
608
1450
|
generateSuiteCRMData: generateSuiteCRMData,
|
|
609
1451
|
generateWordPressData: generateWordPressData,
|
|
1452
|
+
getFrontPageRef: getFrontPageRef,
|
|
1453
|
+
getFrontPageSlug: getFrontPageSlug,
|
|
610
1454
|
getWordPressPostTypes: getWordPressPostTypes,
|
|
611
1455
|
isGoogleReviewsEnabled: isGoogleReviewsEnabled,
|
|
612
|
-
|
|
1456
|
+
isNoindexEntity: isNoindexEntity,
|
|
1457
|
+
isPublishedEntity: isPublishedEntity,
|
|
1458
|
+
newsletterRouteBase: newsletterRouteBase,
|
|
1459
|
+
parseEnabledPostTypes: parseEnabledPostTypes,
|
|
1460
|
+
parseRoutePrefixes: parseRoutePrefixes,
|
|
1461
|
+
prerenderSeoHtml: prerenderSeoHtml
|
|
613
1462
|
});
|
|
614
1463
|
|
|
615
1464
|
/**
|
|
@@ -620,5 +1469,5 @@ const getDigiValtVersion = () => {
|
|
|
620
1469
|
return "0.2.6";
|
|
621
1470
|
};
|
|
622
1471
|
|
|
623
|
-
export { PSEUDO_POST_TYPES, generateAllData, generateGoogleReviewsData, generateGravityFormsData, generateMauticData, generatePhplistData, generateSitemapPaths, generateSitemapPathsSafe, generateSuiteCRMData, generateWordPressData, index as generators, getDigiValtVersion, getWordPressPostTypes, isGoogleReviewsEnabled, parseEnabledPostTypes };
|
|
1472
|
+
export { PSEUDO_POST_TYPES, SITEMAP_URL_SHARD_SIZE, collectSitemapUrls, entityImage, entityLastmod, generateAllData, generateGoogleReviewsData, generateGravityFormsData, generateMauticData, generatePhplistData, generateSeoManifest, generateSeoManifestSafe, generateSitemapPaths, generateSitemapPathsSafe, generateSuiteCRMData, generateWordPressData, index as generators, getDigiValtVersion, getFrontPageRef, getFrontPageSlug, getWordPressPostTypes, isGoogleReviewsEnabled, isNoindexEntity, isPublishedEntity, newsletterRouteBase, parseEnabledPostTypes, parseRoutePrefixes, prerenderSeoHtml };
|
|
624
1473
|
//# sourceMappingURL=index.esm.js.map
|