@jmp-technologies/analytics 0.1.40 → 0.1.41

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.
Files changed (48) hide show
  1. package/README.md +2 -2
  2. package/dist/astro/client.cjs +1 -1
  3. package/dist/astro/client.cjs.map +1 -1
  4. package/dist/astro/client.js +1 -1
  5. package/dist/astro/content.cjs +1 -1
  6. package/dist/astro/content.cjs.map +1 -1
  7. package/dist/astro/content.js +2 -2
  8. package/dist/astro/integration.cjs +1 -1
  9. package/dist/astro/integration.cjs.map +1 -1
  10. package/dist/astro/integration.js +2 -2
  11. package/dist/astro/register.cjs +1 -1
  12. package/dist/astro/register.cjs.map +1 -1
  13. package/dist/astro/register.js +2 -2
  14. package/dist/{chunk-JC3G4XNR.js → chunk-5SXVGQVW.js} +2 -2
  15. package/dist/{chunk-JC3G4XNR.js.map → chunk-5SXVGQVW.js.map} +1 -1
  16. package/dist/{chunk-BRLCGVFJ.js → chunk-GCEIT2ON.js} +2 -2
  17. package/dist/{chunk-IY6Y636W.js → chunk-L6IUBEUV.js} +2 -2
  18. package/dist/{chunk-VSZRQSUN.js → chunk-MEG7QGRF.js} +2 -2
  19. package/dist/{chunk-34LFIP3R.js → chunk-QSKTA7JD.js} +2 -2
  20. package/dist/index.cjs +1 -1
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.js +1 -1
  23. package/dist/next/content.cjs +1 -1
  24. package/dist/next/content.cjs.map +1 -1
  25. package/dist/next/content.js +2 -2
  26. package/dist/next/instrumentation.cjs +1 -1
  27. package/dist/next/instrumentation.cjs.map +1 -1
  28. package/dist/next/instrumentation.js +1 -1
  29. package/dist/next/landing-pages.cjs +1 -1
  30. package/dist/next/landing-pages.cjs.map +1 -1
  31. package/dist/next/landing-pages.js +2 -2
  32. package/dist/next/locations.cjs +1 -1
  33. package/dist/next/locations.cjs.map +1 -1
  34. package/dist/next/locations.js +2 -2
  35. package/dist/next/site-root-server.cjs +1 -1
  36. package/dist/next/site-root-server.cjs.map +1 -1
  37. package/dist/next/site-root-server.js +3 -3
  38. package/dist/next.cjs +1 -1
  39. package/dist/next.cjs.map +1 -1
  40. package/dist/next.js +3 -3
  41. package/dist/react.cjs +1 -1
  42. package/dist/react.cjs.map +1 -1
  43. package/dist/react.js +2 -2
  44. package/package.json +1 -1
  45. /package/dist/{chunk-BRLCGVFJ.js.map → chunk-GCEIT2ON.js.map} +0 -0
  46. /package/dist/{chunk-IY6Y636W.js.map → chunk-L6IUBEUV.js.map} +0 -0
  47. /package/dist/{chunk-VSZRQSUN.js.map → chunk-MEG7QGRF.js.map} +0 -0
  48. /package/dist/{chunk-34LFIP3R.js.map → chunk-QSKTA7JD.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/landing-capture.ts","../src/contact-link-classifier.ts","../package.json","../src/constants.ts","../src/consent.ts","../src/tracker/page-view-dedupe.ts","../src/http.ts","../src/tracker/helpers.ts","../src/tracker/create-jmp-analytics.ts","../src/env-public.ts","../src/site-config.ts","../src/landing-pages/utils.ts","../src/request-origin.ts","../src/server/page-view.ts","../src/content/manifest.ts","../src/content/fetch.ts","../src/content/wrapper-discovery.ts","../src/content/api.ts","../ai-crawler-agents.json","../src/ai-crawlers.ts","../src/content/client.ts","../src/env/browser.ts"],"sourcesContent":["export { buildLandingCaptureInlineScript } from \"./landing-capture\"\nexport {\n classifyContactHref,\n BOOKING_LINK_HOSTS,\n} from \"./contact-link-classifier\"\nexport type {\n ContactLinkChannel,\n ClassifiedContactLink,\n} from \"./contact-link-classifier\"\n\nexport {\n JMP_ANALYTICS_SDK_VERSION,\n JMP_TRACKING_CONSENT_STORAGE_KEY,\n DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,\n JMP_CONTENT_CACHE_TAG,\n JMP_CONTENT_REVALIDATE_SECONDS,\n} from \"./constants\"\n\nexport {\n isJmpTrackingConsentGranted,\n subscribeJmpTrackingConsent,\n setJmpTrackingConsent,\n} from \"./consent\"\n\nexport type {\n JmpEventType,\n JmpAnalyticsConfig,\n JmpContentConfig,\n JmpContentWrapper,\n JmpContentWrapperReportMode,\n JmpBlogPost,\n JmpBlogPostDetail,\n JmpFaqItem,\n JmpFaqItemDetail,\n JmpLegalDocument,\n JmpPopularPage,\n JmpPopularPagesResult,\n JmpContentLocaleAlternate,\n JmpLandingPage,\n JmpLandingPageDetail,\n JmpLandingPageKind,\n JmpLandingPageSitemapEntry,\n JmpWebsiteLocation,\n JmpWebsiteLocationDetail,\n JmpTrustSummary,\n JmpTestimonial,\n JmpTrustStat,\n JmpPartnerLogo,\n JmpCredential,\n JmpTrustBundle,\n JmpSiteProfile,\n TrackPageViewOptions,\n TrackLeadOptions,\n LeadMetadataValue,\n LeadMetadata,\n JmpServerRequestLike,\n TrackServerPageViewOptions,\n} from \"./types\"\n\nexport { createJmpAnalytics, type JmpAnalytics } from \"./tracker/create-jmp-analytics\"\nexport { trackJmpServerPageView } from \"./server/page-view\"\nexport {\n normalizeJmpContentManifest,\n stableJmpManifestFingerprint,\n type JmpContentManifest,\n type JmpContentRouteManifest,\n type JmpTrustBlockManifest,\n type JmpContactExtraManifest,\n type JmpTrustSection,\n} from \"./content/manifest\"\n\nexport {\n getJmpBlogPosts,\n getJmpBlogPost,\n getJmpBlogPostDetail,\n getJmpFaqs,\n getJmpFaqDetail,\n getJmpLegalDocument,\n getJmpLegalDocuments,\n getJmpLandingPages,\n getJmpLandingPageDetail,\n getJmpLandingPageSitemap,\n getJmpLocations,\n getJmpLocationDetail,\n getJmpTrustBundle,\n getJmpSiteProfile,\n getJmpRobotsTxt,\n registerJmpContentWrappers,\n getJmpPopularPages,\n getDiscoveredContentWrappers,\n inferTrustWrapperSlots,\n markContentWrapper,\n resetContentWrapperDiscoveryForTests,\n} from \"./content/api\"\nexport {\n AI_CRAWLER_ROBOTS_USER_AGENTS,\n JMP_AI_CRAWLER_WAF_USER_AGENTS,\n buildAiCrawlerRobotsTxt,\n jmpAiCrawlerVercelWafRoute,\n jmpAiCrawlerWafUserAgentPattern,\n mergeJmpRobotsTxt,\n} from \"./ai-crawlers\"\nexport { createJmpContentClient, type JmpContentClient } from \"./content/client\"\nexport {\n getJmpBrowserAnalyticsConfigFromEnv,\n getJmpServerContentConfigFromEnv,\n isJmpBrowserAnalyticsEnvConfigured,\n isJmpServerContentEnvConfigured,\n getOrCreateJmpAnalyticsFromBrowserEnv,\n createJmpContentClientFromServerEnv,\n} from \"./env/browser\"\n\nexport { readJmpPublicEnvFromProcess } from \"./env-public\"\nexport type { JmpPublicEnv } from \"./env-public\"\n\nexport {\n defineJmpSite,\n getJmpSiteDefinition,\n getJmpContentConfig,\n type JmpSiteDefinition,\n type JmpSiteContactFallback,\n} from \"./site-config\"\n","/** First-party landing attribution captured before React / useEffect (sessionStorage). */\n\nexport const JMP_SESSION_ID_KEY = \"jmp_analytics_sid\"\nexport const JMP_LANDING_REFERER_KEY = \"jmp_analytics_landing_referer\"\n/** Cross-subdomain landing referrer (www ↔ apex share sessionStorage origins). */\nexport const JMP_LANDING_REFERER_COOKIE = \"jmp_lr\"\nexport const JMP_UTM_SESSION_KEY = \"jmp_analytics_utm\"\n\nconst LANDING_REFERER_COOKIE_MAX_AGE_SEC = 30 * 60\n\nexport const JMP_UTM_PARAM_KEYS = [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_content\",\n \"utm_term\",\n] as const\n\nfunction refererHostFromUrl(referer: string): string | null {\n const trimmed = referer.trim()\n try {\n return new URL(trimmed).hostname.replace(/^www\\./i, \"\").toLowerCase()\n } catch {\n try {\n return new URL(`https://${trimmed}`).hostname\n .replace(/^www\\./i, \"\")\n .toLowerCase()\n } catch {\n return null\n }\n }\n}\n\nexport function isExternalReferrerUrl(\n referer: string,\n siteHostname: string\n): boolean {\n const refHost = refererHostFromUrl(referer)\n if (!refHost) {\n return false\n }\n const site = siteHostname.replace(/^www\\./i, \"\").toLowerCase()\n return refHost !== site && !refHost.endsWith(`.${site}`)\n}\n\n/** Apex hostname used for `Domain=.example.com` cookies (www + apex). */\nexport function registrableSiteDomain(siteHostname: string): string | null {\n const site = siteHostname.replace(/^www\\./i, \"\").toLowerCase()\n if (!site || site === \"localhost\" || site.endsWith(\".local\")) {\n return null\n }\n if (!site.includes(\".\")) {\n return null\n }\n return site\n}\n\nexport function readLandingRefererCookie(siteHostname: string): string | null {\n if (typeof document === \"undefined\") {\n return null\n }\n\n const apex = registrableSiteDomain(siteHostname)\n if (!apex) {\n return null\n }\n\n const prefix = `${JMP_LANDING_REFERER_COOKIE}=`\n for (const part of document.cookie.split(\";\")) {\n const trimmed = part.trim()\n if (!trimmed.startsWith(prefix)) {\n continue\n }\n try {\n const value = decodeURIComponent(trimmed.slice(prefix.length)).trim()\n return value.length > 0 ? value : null\n } catch {\n return null\n }\n }\n\n return null\n}\n\nexport function writeLandingRefererCookie(\n referer: string,\n siteHostname: string\n): void {\n if (typeof document === \"undefined\") {\n return\n }\n\n const apex = registrableSiteDomain(siteHostname)\n if (!apex) {\n return\n }\n\n const value = encodeURIComponent(referer.trim().slice(0, 2048))\n const secure =\n typeof window !== \"undefined\" && window.location.protocol === \"https:\"\n ? \"; Secure\"\n : \"\"\n\n document.cookie = `${JMP_LANDING_REFERER_COOKIE}=${value}; Domain=.${apex}; Path=/; Max-Age=${LANDING_REFERER_COOKIE_MAX_AGE_SEC}; SameSite=Lax${secure}`\n}\n\nexport function captureLandingAttribution(siteHostname: string): {\n landingReferer: string | null\n utm: Record<string, string>\n} {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n return { landingReferer: null, utm: {} }\n }\n\n let landingReferer: string | null = null\n let utm: Record<string, string> = {}\n\n try {\n const storedReferer =\n sessionStorage.getItem(JMP_LANDING_REFERER_KEY)?.trim() || null\n const cookieReferer = readLandingRefererCookie(siteHostname)\n const preservedReferer = storedReferer || cookieReferer\n const currentReferer = document.referrer?.trim() || null\n\n if (\n currentReferer &&\n isExternalReferrerUrl(currentReferer, siteHostname)\n ) {\n sessionStorage.setItem(JMP_LANDING_REFERER_KEY, currentReferer)\n writeLandingRefererCookie(currentReferer, siteHostname)\n landingReferer = currentReferer\n } else if (preservedReferer) {\n landingReferer = preservedReferer\n if (!storedReferer) {\n sessionStorage.setItem(JMP_LANDING_REFERER_KEY, preservedReferer)\n }\n }\n\n const params = new URLSearchParams(window.location.search)\n const rawUtm = sessionStorage.getItem(JMP_UTM_SESSION_KEY)\n if (rawUtm) {\n const parsed = JSON.parse(rawUtm) as unknown\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n utm = parsed as Record<string, string>\n }\n }\n\n let updated = false\n for (const key of JMP_UTM_PARAM_KEYS) {\n const value = params.get(key)?.trim()\n if (value) {\n utm[key] = value\n updated = true\n }\n }\n\n if (updated) {\n sessionStorage.setItem(JMP_UTM_SESSION_KEY, JSON.stringify(utm))\n }\n } catch {\n }\n\n return { landingReferer, utm }\n}\n\nexport function getOrCreateSessionIdFromStorage(): string | undefined {\n if (typeof window === \"undefined\" || !globalThis.crypto?.randomUUID) {\n return undefined\n }\n try {\n let id = sessionStorage.getItem(JMP_SESSION_ID_KEY)\n if (!id) {\n id = crypto.randomUUID()\n sessionStorage.setItem(JMP_SESSION_ID_KEY, id)\n }\n return id\n } catch {\n return undefined\n }\n}\n\n/** Inline script for Next.js `beforeInteractive` — capture referrer/UTM only (no network). */\nexport function buildLandingCaptureInlineScript(): string {\n const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC)\n\n return `(function(){try{var h=location.hostname;var ref=document.referrer||'';function rh(u){try{return new URL(u).hostname.replace(/^www\\\\./i,'').toLowerCase()}catch(e){try{return new URL('https://'+u).hostname.replace(/^www\\\\./i,'').toLowerCase()}catch(e2){return null}}}function ext(r){var x=rh(r);if(!x)return false;var s=h.replace(/^www\\\\./i,'').toLowerCase();return x!==s&&x.slice(-('.'+s).length)!==('.'+s)}function apexDom(hn){var s=hn.replace(/^www\\\\./i,'').toLowerCase();if(!s||s==='localhost'||/\\\\.local$/i.test(s)||s.indexOf('.')<0)return null;return s}function readCk(hn){var apex=apexDom(hn);if(!apex)return '';var pre='${JMP_LANDING_REFERER_COOKIE}=';var parts=document.cookie.split(';');for(var i=0;i<parts.length;i++){var t=parts[i].trim();if(t.indexOf(pre)===0){try{return decodeURIComponent(t.slice(pre.length)).trim()}catch(e){return ''}}}return ''}function writeCk(r,hn){var apex=apexDom(hn);if(!apex)return;var sec=location.protocol==='https:'?'; Secure':'';document.cookie='${JMP_LANDING_REFERER_COOKIE}='+encodeURIComponent(r.slice(0,2048))+'; Domain=.'+apex+'; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax'+sec}var stored=sessionStorage.getItem('${JMP_LANDING_REFERER_KEY}')||'';var ck=readCk(h);var preserved=stored||ck;var lr='';if(ref&&ext(ref)){sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',ref);writeCk(ref,h);lr=ref}else{lr=preserved||'';if(lr&&!stored)sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',lr)}var sid=sessionStorage.getItem('${JMP_SESSION_ID_KEY}');if(!sid&&crypto&&crypto.randomUUID){sid=crypto.randomUUID();sessionStorage.setItem('${JMP_SESSION_ID_KEY}',sid)}try{var sp=new URLSearchParams(location.search);var utm={};var updated=false;['utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach(function(n){var v=sp.get(n);if(v){utm[n]=v;updated=true}});if(updated)sessionStorage.setItem('${JMP_UTM_SESSION_KEY}',JSON.stringify(utm))}catch(e){}}catch(e){}})();`\n}\n","/**\n * Classify outbound contact links for auto-tracking.\n *\n * Keep channel set in sync with `lib/ingest/contact-click.ts` on the dashboard side.\n *\n * Channels detected from `href` alone (no widget / iframe detection):\n *\n * - `call` — `tel:` (delegates to existing `trackCallClick`)\n * - `email` — `mailto:` (delegates to existing `trackEmailClick`)\n * - `sms` — `sms:` / `smsto:`\n * - `whatsapp` — `wa.me`, `api.whatsapp.com`, `whatsapp.com/send`\n * - `maps` — Google Maps, Apple Maps, `maps.app.goo.gl`, `geo:`\n * - `booking` — fixed allowlist of common scheduling hosts (see {@link BOOKING_LINK_HOSTS})\n *\n * `linkHost` returned in `contact_click` results is the hostname only — never the full URL\n * (avoids leaking phone numbers in `tel:`/`sms:` URLs and PII-laden booking query strings).\n */\n\nexport type ContactLinkChannel = \"sms\" | \"whatsapp\" | \"maps\" | \"booking\"\n\nexport type ClassifiedContactLink =\n | { kind: \"call\" }\n | { kind: \"email\" }\n | { kind: \"contact_click\"; channel: ContactLinkChannel; linkHost: string | null }\n\n/** v1 booking hosts (~80%+ SMB coverage). Add hosts here when a client uses something rare. */\nexport const BOOKING_LINK_HOSTS = [\n \"calendly.com\",\n \"cal.com\",\n \"acuityscheduling.com\",\n \"calendar.google.com\",\n \"calendar.app.google\",\n \"bookings.microsoft.com\",\n \"outlook.office.com\",\n \"outlook.office365.com\",\n \"book.ms\",\n \"setmore.com\",\n \"simplybook.me\",\n \"oncehub.com\",\n \"scheduleonce.com\",\n \"youcanbook.me\",\n \"savvycal.com\",\n \"tidycal.com\",\n \"zohobookings.com\",\n \"square.site\",\n \"squareup.com\",\n \"meetings.hubspot.com\",\n \"jobber.com\",\n \"housecallpro.com\",\n \"servicetitan.com\",\n \"thryv.com\",\n \"honeybook.com\",\n \"dubsado.com\",\n \"fresha.com\",\n \"booksy.com\",\n \"vagaro.com\",\n \"mindbodyonline.com\",\n \"mindbody.io\",\n \"janeapp.com\",\n \"cliniko.com\",\n \"practicebetter.io\",\n] as const\n\nconst WHATSAPP_HOSTS = [\"wa.me\", \"api.whatsapp.com\", \"whatsapp.com\"] as const\n\nexport function hostnameMatches(host: string, pattern: string): boolean {\n const h = host.toLowerCase()\n const p = pattern.toLowerCase()\n return h === p || h.endsWith(`.${p}`)\n}\n\nfunction isMapsHost(host: string, pathname: string): boolean {\n if (hostnameMatches(host, \"maps.apple.com\")) {\n return true\n }\n if (hostnameMatches(host, \"maps.app.goo.gl\")) {\n return true\n }\n if (hostnameMatches(host, \"google.com\") || hostnameMatches(host, \"google.co\")) {\n return pathname === \"/maps\" || pathname.startsWith(\"/maps/\") || pathname.startsWith(\"/local\")\n }\n return false\n}\n\nfunction isWhatsAppHost(host: string, pathname: string): boolean {\n for (const pattern of WHATSAPP_HOSTS) {\n if (!hostnameMatches(host, pattern)) {\n continue\n }\n if (pattern === \"whatsapp.com\") {\n return pathname.startsWith(\"/send\")\n }\n return true\n }\n return false\n}\n\nfunction isBookingHost(host: string): boolean {\n for (const pattern of BOOKING_LINK_HOSTS) {\n if (hostnameMatches(host, pattern)) {\n return true\n }\n }\n return false\n}\n\nexport function classifyContactHref(href: string): ClassifiedContactLink | null {\n const raw = href.trim()\n if (!raw || raw.startsWith(\"#\") || raw.startsWith(\"javascript:\")) {\n return null\n }\n\n const lower = raw.toLowerCase()\n\n if (lower.startsWith(\"tel:\")) {\n return { kind: \"call\" }\n }\n if (lower.startsWith(\"mailto:\")) {\n return { kind: \"email\" }\n }\n if (lower.startsWith(\"sms:\") || lower.startsWith(\"smsto:\")) {\n return { kind: \"contact_click\", channel: \"sms\", linkHost: null }\n }\n if (lower.startsWith(\"geo:\")) {\n return { kind: \"contact_click\", channel: \"maps\", linkHost: null }\n }\n\n // Skip anchors/relative paths that aren't a known contact scheme.\n if (raw.startsWith(\"/\") || raw.startsWith(\"?\")) {\n return null\n }\n\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n return null\n }\n\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return null\n }\n\n const host = url.hostname.toLowerCase()\n const pathname = url.pathname.toLowerCase()\n\n if (isWhatsAppHost(host, pathname)) {\n return { kind: \"contact_click\", channel: \"whatsapp\", linkHost: host }\n }\n if (isMapsHost(host, pathname)) {\n return { kind: \"contact_click\", channel: \"maps\", linkHost: host }\n }\n if (isBookingHost(host)) {\n return { kind: \"contact_click\", channel: \"booking\", linkHost: host }\n }\n\n return null\n}\n\n/** Phone number from a `tel:` href (for CRM logs — not sent on `contact_click`). */\nexport function extractTelTarget(href: string): string | null {\n const raw = href.trim()\n if (!raw.toLowerCase().startsWith(\"tel:\")) {\n return null\n }\n const target = decodeURIComponent(\n raw.slice(4).split(\"?\")[0]?.split(\";\")[0] ?? \"\"\n ).trim()\n return target || null\n}\n\n/** Email address from a `mailto:` href (for CRM logs). */\nexport function extractMailtoTarget(href: string): string | null {\n const raw = href.trim()\n if (!raw.toLowerCase().startsWith(\"mailto:\")) {\n return null\n }\n const target = decodeURIComponent(\n raw.slice(7).split(\"?\")[0]?.split(\",\")[0] ?? \"\"\n ).trim()\n return target || null\n}\n","{\n \"name\": \"@jmp-technologies/analytics\",\n \"version\": \"0.1.40\",\n \"description\": \"JMP Analytics tracking plus blog, FAQ, trust content, and site contact profile for client websites\",\n \"license\": \"UNLICENSED\",\n \"keywords\": [\n \"jmp\",\n \"analytics\",\n \"tracking\",\n \"jmp-analytics\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/jmp-technologies/jmp-dashboard.git\",\n \"directory\": \"packages/jmp-technologies-analytics\"\n },\n \"homepage\": \"https://github.com/jmp-technologies/jmp-dashboard/tree/main/packages/jmp-technologies-analytics#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/jmp-technologies/jmp-dashboard/issues\"\n },\n \"type\": \"module\",\n \"bin\": {\n \"jmp-init\": \"./bin/jmp-init.mjs\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./react\": {\n \"types\": \"./dist/react.d.ts\",\n \"import\": \"./dist/react.js\",\n \"require\": \"./dist/react.cjs\"\n },\n \"./next\": {\n \"types\": \"./dist/next.d.ts\",\n \"import\": \"./dist/next.js\",\n \"require\": \"./dist/next.cjs\"\n },\n \"./next/site-root-server\": {\n \"types\": \"./dist/next/site-root-server.d.ts\",\n \"import\": \"./dist/next/site-root-server.js\",\n \"require\": \"./dist/next/site-root-server.cjs\"\n },\n \"./next/landing-capture-script-server\": {\n \"types\": \"./dist/next/landing-capture-script-server.d.ts\",\n \"import\": \"./dist/next/landing-capture-script-server.js\",\n \"require\": \"./dist/next/landing-capture-script-server.cjs\"\n },\n \"./next/middleware\": {\n \"types\": \"./dist/next/middleware.d.ts\",\n \"import\": \"./dist/next/middleware.js\",\n \"require\": \"./dist/next/middleware.cjs\"\n },\n \"./next/instrumentation\": {\n \"types\": \"./dist/next/instrumentation.d.ts\",\n \"import\": \"./dist/next/instrumentation.js\",\n \"require\": \"./dist/next/instrumentation.cjs\"\n },\n \"./next/content\": {\n \"types\": \"./dist/next/content.d.ts\",\n \"import\": \"./dist/next/content.js\",\n \"require\": \"./dist/next/content.cjs\"\n },\n \"./next/landing-pages\": {\n \"types\": \"./dist/next/landing-pages.d.ts\",\n \"import\": \"./dist/next/landing-pages.js\",\n \"require\": \"./dist/next/landing-pages.cjs\"\n },\n \"./next/locations\": {\n \"types\": \"./dist/next/locations.d.ts\",\n \"import\": \"./dist/next/locations.js\",\n \"require\": \"./dist/next/locations.cjs\"\n },\n \"./astro/content\": {\n \"types\": \"./dist/astro/content.d.ts\",\n \"import\": \"./dist/astro/content.js\",\n \"require\": \"./dist/astro/content.cjs\"\n },\n \"./astro/client\": {\n \"types\": \"./dist/astro/client.d.ts\",\n \"import\": \"./dist/astro/client.js\",\n \"require\": \"./dist/astro/client.cjs\"\n },\n \"./astro/middleware\": {\n \"types\": \"./dist/astro/middleware.d.ts\",\n \"import\": \"./dist/astro/middleware.js\",\n \"require\": \"./dist/astro/middleware.cjs\"\n },\n \"./astro/register\": {\n \"types\": \"./dist/astro/register.d.ts\",\n \"import\": \"./dist/astro/register.js\",\n \"require\": \"./dist/astro/register.cjs\"\n },\n \"./astro/integration\": {\n \"types\": \"./dist/astro/integration.d.ts\",\n \"import\": \"./dist/astro/integration.js\",\n \"require\": \"./dist/astro/integration.cjs\"\n }\n },\n \"files\": [\n \"dist\",\n \"bin\",\n \"docs\",\n \"ai-crawler-agents.json\",\n \"README.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup src/index.ts src/react.tsx src/next.tsx src/next/google-tag.tsx src/next/landing-capture-script-server.tsx src/next/site-root-server.tsx src/next/middleware.ts src/next/instrumentation.ts src/next/content.ts src/next/landing-pages.tsx src/next/locations.tsx src/astro/content.ts src/astro/client.ts src/astro/middleware.ts src/astro/register.ts src/astro/integration.ts --format esm,cjs --dts --clean --sourcemap --external react --external react-dom --external next\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"peerDependencies\": {\n \"next\": \">=14\",\n \"react\": \">=18\",\n \"react-dom\": \">=18\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"next\": {\n \"optional\": true\n },\n \"astro\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/react\": \"^19\",\n \"@types/react-dom\": \"^19\",\n \"next\": \"^16.2.3\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\"\n },\n \"dependencies\": {}\n}\n","import { version as packageVersion } from \"../package.json\"\n\n/** Published package version — sent with capabilities for admin readiness. */\nexport const JMP_ANALYTICS_SDK_VERSION = packageVersion\n\n/** `localStorage` key when {@link JmpAnalyticsConfig.requireConsent} is enabled. */\nexport const JMP_TRACKING_CONSENT_STORAGE_KEY = \"jmp_analytics_consent_v1\"\n\n/** Default `pageViewDedupeMs` when resolving browser config from env (Strict Mode / SPA). */\nexport const DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 2500\n\n/** Marks links tracked explicitly — skips delegated `autoTrackContactLinks` handler. */\nexport const JMP_TRACKED_LINK_ATTR = \"data-jmp-tracked\"\n\n/** Next.js `fetch` / Vercel CDN tag for JMP public content. Client webhooks revalidate this tag. */\nexport const JMP_CONTENT_CACHE_TAG = \"jmp-content\"\n\n/** Fallback TTL for tagged JMP content fetches when on-demand revalidation does not run. */\nexport const JMP_CONTENT_REVALIDATE_SECONDS = 3600\n","import { captureLandingAttribution } from \"./landing-capture\"\nimport { JMP_TRACKING_CONSENT_STORAGE_KEY } from \"./constants\"\n\nlet moduleTrackingConsentGranted = true\nconst trackingConsentListeners = new Set<() => void>()\n\nfunction readStoredTrackingConsent(): boolean {\n if (typeof window === \"undefined\") {\n return false\n }\n try {\n return (\n localStorage.getItem(JMP_TRACKING_CONSENT_STORAGE_KEY) === \"granted\"\n )\n } catch {\n return false\n }\n}\n\n/** Initialize consent gate when creating a tracker (browser only). */\nexport function initJmpTrackingConsent(requireConsent: boolean | undefined): void {\n moduleTrackingConsentGranted = requireConsent\n ? readStoredTrackingConsent()\n : true\n}\n\n/** Whether analytics events may be sent (after CMP / cookie banner). */\nexport function isJmpTrackingConsentGranted(): boolean {\n return moduleTrackingConsentGranted\n}\n\n/** Subscribe to consent changes (for React `useSyncExternalStore`). */\nexport function subscribeJmpTrackingConsent(listener: () => void): () => void {\n trackingConsentListeners.add(listener)\n return () => {\n trackingConsentListeners.delete(listener)\n }\n}\n\n/**\n * Grant or deny analytics. Persists in `localStorage` when `requireConsent` is used.\n * Call from your cookie banner before tracking runs.\n */\nexport function setJmpTrackingConsent(granted: boolean): void {\n if (moduleTrackingConsentGranted === granted) {\n return\n }\n moduleTrackingConsentGranted = granted\n if (typeof window !== \"undefined\") {\n try {\n localStorage.setItem(\n JMP_TRACKING_CONSENT_STORAGE_KEY,\n granted ? \"granted\" : \"denied\"\n )\n } catch {\n // private mode\n }\n if (granted) {\n captureLandingAttribution(window.location.hostname)\n }\n }\n for (const listener of trackingConsentListeners) {\n listener()\n }\n}\n","export const JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY = \"jmp_analytics_last_pv\"\n\nlet moduleLastPath = \"\"\nlet moduleLastAt = 0\n\n/**\n * Suppress duplicate browser `page_view` within `dedupeMs` (Strict Mode, App Router\n * searchParams resolution, multiple bundles). Uses pathname-only as the dedupe key.\n */\nexport function shouldDedupeBrowserPageView(\n pathname: string,\n dedupeMs: number,\n storage: Pick<Storage, \"getItem\" | \"setItem\"> | null = null,\n): boolean {\n if (dedupeMs <= 0) {\n return false\n }\n\n const now = Date.now()\n if (pathname === moduleLastPath && now - moduleLastAt < dedupeMs) {\n return true\n }\n\n try {\n const raw = storage?.getItem(JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY)\n if (raw) {\n const prev = JSON.parse(raw) as { path: string; at: number }\n if (prev.path === pathname && now - prev.at < dedupeMs) {\n return true\n }\n }\n storage?.setItem(\n JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY,\n JSON.stringify({ path: pathname, at: now }),\n )\n } catch {\n // private mode / disabled storage\n }\n\n moduleLastPath = pathname\n moduleLastAt = now\n return false\n}\n\n/** @internal test helper */\nexport function resetBrowserPageViewDedupeForTests(): void {\n moduleLastPath = \"\"\n moduleLastAt = 0\n}\n","import type { JmpServerRequestLike } from \"./types\"\n\n/** CDN / Next.js often return HTML error pages; API errors are JSON */\nexport function responseLooksLikeHtml(body: string): boolean {\n const s = body.trimStart()\n return (\n s.startsWith(\"<!\") ||\n s.toLowerCase().startsWith(\"<html\") ||\n (s.startsWith(\"<\") && /<html[\\s>]/i.test(s.slice(0, 500)))\n )\n}\n\nexport function normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/$/, \"\")\n}\n\nexport function getHeader(\n headers: JmpServerRequestLike[\"headers\"] | undefined,\n key: string\n): string | null {\n if (!headers) {\n return null\n }\n if (typeof (headers as Pick<Headers, \"get\">).get === \"function\") {\n return (headers as Pick<Headers, \"get\">).get(key)\n }\n const record = headers as Record<string, string | string[] | undefined | null>\n const direct = record[key] ?? record[key.toLowerCase()]\n if (Array.isArray(direct)) {\n return direct[0] ?? null\n }\n return direct ?? null\n}\n\nexport function pathFromRequestUrl(url: string | undefined): string {\n if (!url) {\n return \"/\"\n }\n try {\n const u = new URL(url)\n return `${u.pathname}${u.search}`\n } catch {\n return url.startsWith(\"/\") ? url : \"/\"\n }\n}\n\nexport function resolveFetch(\n fetchImpl: typeof fetch | undefined,\n context: string\n): typeof fetch {\n const resolved =\n fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n if (!resolved) {\n throw new Error(`${context}: fetch is not available; pass fetchImpl in config`)\n }\n return resolved\n}\n\ntype ApiErrorJson = {\n error?: string\n code?: string\n hint?: string\n expectedDomain?: string\n}\n\nexport function formatApiErrorMessage(\n status: number,\n text: string,\n prefix: string\n): string {\n if (responseLooksLikeHtml(text)) {\n return `${prefix} HTTP ${status} — response was HTML (not the JSON API). Check baseUrl points at the JMP Analytics dashboard.`\n }\n let parsed: ApiErrorJson = {}\n try {\n parsed = JSON.parse(text) as ApiErrorJson\n } catch {\n parsed = { error: text }\n }\n const detail = parsed.error ?? text\n return [\n `${prefix} HTTP ${status}`,\n parsed.code ? `[${parsed.code}]` : null,\n detail,\n parsed.hint ? `Hint: ${parsed.hint}` : null,\n parsed.expectedDomain\n ? `Domain in JMP admin: ${parsed.expectedDomain}`\n : null,\n ]\n .filter(Boolean)\n .join(\" — \")\n}\n","import {\n captureLandingAttribution,\n JMP_UTM_PARAM_KEYS,\n} from \"../landing-capture\"\n\nexport function captureAndGetLandingReferer(): string | null {\n if (typeof window === \"undefined\") {\n return null\n }\n return captureLandingAttribution(window.location.hostname).landingReferer\n}\n\nexport function mergeSessionUtms(metadata: Record<string, unknown>) {\n if (typeof window === \"undefined\") {\n return\n }\n const { utm } = captureLandingAttribution(window.location.hostname)\n for (const key of JMP_UTM_PARAM_KEYS) {\n if (metadata[key] === undefined && utm[key]) {\n metadata[key] = utm[key]\n }\n }\n}\n\nexport function splitPathAndSearch(pathInput: string): {\n pathname: string\n search: string\n} {\n const qIndex = pathInput.indexOf(\"?\")\n if (qIndex === -1) {\n return { pathname: pathInput || \"/\", search: \"\" }\n }\n return {\n pathname: pathInput.slice(0, qIndex) || \"/\",\n search: pathInput.slice(qIndex + 1),\n }\n}\n\nexport function inferDevice(): string {\n if (typeof window === \"undefined\") {\n return \"unknown\"\n }\n return window.innerWidth < 768 ? \"mobile\" : \"desktop\"\n}\n","import { DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS } from \"../constants\"\nimport {\n captureLandingAttribution,\n getOrCreateSessionIdFromStorage,\n JMP_UTM_PARAM_KEYS,\n} from \"../landing-capture\"\nimport { shouldDedupeBrowserPageView } from \"./page-view-dedupe\"\nimport { classifyContactHref, extractMailtoTarget, extractTelTarget } from \"../contact-link-classifier\"\nimport type { ContactLinkChannel } from \"../contact-link-classifier\"\nimport {\n initJmpTrackingConsent,\n isJmpTrackingConsentGranted,\n setJmpTrackingConsent,\n} from \"../consent\"\nimport {\n formatApiErrorMessage,\n normalizeBaseUrl,\n resolveFetch,\n} from \"../http\"\nimport type {\n JmpAnalyticsConfig,\n JmpEventType,\n TrackLeadOptions,\n TrackPageViewOptions,\n} from \"../types\"\nimport {\n captureAndGetLandingReferer,\n inferDevice,\n mergeSessionUtms,\n splitPathAndSearch,\n} from \"./helpers\"\n\nexport function createJmpAnalytics(config: JmpAnalyticsConfig) {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const fetchFn = resolveFetch(config.fetchImpl, \"createJmpAnalytics\")\n\n initJmpTrackingConsent(config.requireConsent)\n\n function canSend(): boolean {\n return isJmpTrackingConsentGranted()\n }\n\n async function send(body: Record<string, unknown>) {\n if (!canSend()) {\n return\n }\n\n const url = `${baseUrl}/api/events`\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-JMP-Tracking-Key\": config.trackingKey,\n }\n\n if (body.type === \"page_view\" && typeof window !== \"undefined\") {\n const landingReferer = captureAndGetLandingReferer()\n if (landingReferer) {\n headers[\"X-JMP-Visitor-Referer\"] = landingReferer\n }\n }\n\n const sid = getOrCreateSessionIdFromStorage()\n const payload = { ...body, ...(sid ? { sessionId: sid } : {}) }\n\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, payload)\n }\n\n const res = await fetchFn(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n keepalive: true,\n })\n\n if (!res.ok) {\n const text = await res.text()\n const message = formatApiErrorMessage(res.status, text, \"JMP Analytics\")\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"error response\", { status: res.status, raw: text })\n }\n throw new Error(message)\n }\n }\n\n async function sendLead(body: Record<string, unknown>) {\n if (!canSend()) {\n return\n }\n\n const url = `${baseUrl}/api/leads`\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-JMP-Tracking-Key\": config.trackingKey,\n }\n\n const sid = getOrCreateSessionIdFromStorage()\n const payload = { ...body, ...(sid ? { sessionId: sid } : {}) }\n\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, payload)\n }\n\n const res = await fetchFn(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n keepalive: true,\n })\n\n if (!res.ok) {\n const text = await res.text()\n const message = formatApiErrorMessage(res.status, text, \"JMP Analytics\")\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"error response\", { status: res.status, raw: text })\n }\n throw new Error(message)\n }\n }\n\n function trackPageView(options?: TrackPageViewOptions) {\n if (!canSend()) {\n return Promise.resolve()\n }\n\n const pathFromOptions = options?.path?.trim()\n let pathname = \"/\"\n let search = \"\"\n\n if (pathFromOptions) {\n const split = splitPathAndSearch(pathFromOptions)\n pathname = split.pathname\n search = split.search\n } else if (typeof window !== \"undefined\") {\n pathname = window.location.pathname\n search = window.location.search.replace(/^\\?/, \"\")\n }\n\n if (!search && typeof window !== \"undefined\") {\n search = window.location.search.replace(/^\\?/, \"\")\n }\n\n const path = search ? `${pathname}?${search}` : pathname\n\n const dedupeMs =\n config.pageViewDedupeMs ?? DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS\n const storage =\n typeof window !== \"undefined\" ? window.sessionStorage : null\n if (shouldDedupeBrowserPageView(pathname, dedupeMs, storage)) {\n return Promise.resolve()\n }\n\n const metadata: Record<string, unknown> =\n options?.metadata && typeof options.metadata === \"object\"\n ? { ...options.metadata }\n : {}\n\n if (typeof window !== \"undefined\") {\n metadata.pageHostname = window.location.hostname\n const params = new URLSearchParams(\n search ? `?${search}` : window.location.search\n )\n for (const key of JMP_UTM_PARAM_KEYS) {\n const v = params.get(key)\n if (v && metadata[key] === undefined) {\n metadata[key] = v\n }\n }\n mergeSessionUtms(metadata)\n const landingReferer = captureAndGetLandingReferer()\n if (landingReferer && metadata.referer === undefined) {\n metadata.referer = landingReferer\n }\n }\n\n return send({\n type: \"page_view\",\n path: path || \"/\",\n device: options?.device ?? inferDevice(),\n country: options?.country,\n metadata,\n })\n }\n\n function trackFormSubmit(\n path: string,\n metadata?: Record<string, unknown>\n ) {\n return send({\n type: \"form_submit\",\n path: path || \"/\",\n metadata: metadata ?? {},\n })\n }\n\n function trackCallClick(\n path: string,\n metadata?: Record<string, unknown>\n ) {\n return send({\n type: \"call_click\",\n path: path || \"/\",\n metadata: metadata ?? {},\n })\n }\n\n function trackEmailClick(\n path: string,\n metadata?: Record<string, unknown>\n ) {\n return send({\n type: \"email_click\",\n path: path || \"/\",\n metadata: metadata ?? {},\n })\n }\n\n function trackContactClick(\n path: string,\n options: {\n channel: ContactLinkChannel\n linkHost?: string | null\n metadata?: Record<string, unknown>\n }\n ) {\n const metadata: Record<string, unknown> = {\n ...(options.metadata && typeof options.metadata === \"object\"\n ? options.metadata\n : {}),\n channel: options.channel,\n }\n if (options.linkHost) {\n metadata.linkHost = options.linkHost\n }\n return send({\n type: \"contact_click\",\n path: path || \"/\",\n metadata,\n })\n }\n\n function trackLead(options?: TrackLeadOptions) {\n const path =\n options?.path ??\n (typeof window !== \"undefined\" ? window.location.pathname : \"/\")\n\n const body: Record<string, unknown> = { path: path || \"/\" }\n if (options?.name) body.name = options.name\n if (options?.email) body.email = options.email\n if (options?.phone) body.phone = options.phone\n if (options?.company) body.company = options.company\n if (options?.website) body.website = options.website\n if (options?.subject) body.subject = options.subject\n if (options?.message) body.message = options.message\n if (options?.metadata && typeof options.metadata === \"object\") {\n body.metadata = options.metadata\n }\n if (options?.sessionId) body.sessionId = options.sessionId\n\n return sendLead(body)\n }\n\n function track(\n type: JmpEventType,\n payload: {\n path: string\n metadata?: Record<string, unknown>\n source?: string\n device?: string\n country?: string\n }\n ) {\n if (type === \"page_view\") {\n return trackPageView({\n path: payload.path,\n source: payload.source,\n device: payload.device,\n country: payload.country,\n metadata: payload.metadata,\n })\n }\n if (type === \"form_submit\") {\n return trackFormSubmit(payload.path, payload.metadata)\n }\n if (type === \"call_click\") {\n return trackCallClick(payload.path, payload.metadata)\n }\n if (type === \"email_click\") {\n return trackEmailClick(payload.path, payload.metadata)\n }\n const meta = payload.metadata ?? {}\n const channel = typeof meta.channel === \"string\" ? meta.channel : \"\"\n const linkHost =\n typeof meta.linkHost === \"string\" ? (meta.linkHost as string) : null\n if (\n channel !== \"sms\" &&\n channel !== \"whatsapp\" &&\n channel !== \"maps\" &&\n channel !== \"booking\"\n ) {\n return Promise.resolve()\n }\n return trackContactClick(payload.path, {\n channel: channel as ContactLinkChannel,\n linkHost,\n metadata: meta,\n })\n }\n\n /**\n * Fire `page_view` on browser back/forward and when `history.pushState` /\n * `replaceState` are used (many SPAs). Call once after creating the tracker.\n * Returns an unsubscribe function.\n */\n function subscribeToSpaNavigation(): () => void {\n if (typeof window === \"undefined\") {\n return () => {}\n }\n\n let lastPath = window.location.pathname\n\n const run = () => {\n const path = window.location.pathname\n if (path !== lastPath) {\n lastPath = path\n void trackPageView({ path })\n }\n }\n\n window.addEventListener(\"popstate\", run)\n\n const push = history.pushState.bind(history)\n const replace = history.replaceState.bind(history)\n\n history.pushState = (...args: Parameters<History[\"pushState\"]>) => {\n const r = push(...args)\n queueMicrotask(run)\n return r\n }\n history.replaceState = (...args: Parameters<History[\"replaceState\"]>) => {\n const r = replace(...args)\n queueMicrotask(run)\n return r\n }\n\n return () => {\n window.removeEventListener(\"popstate\", run)\n history.pushState = push\n history.replaceState = replace\n }\n }\n\n let lastContactClickKey = \"\"\n let lastContactClickAt = 0\n\n /**\n * Capture-phase `click` listener that classifies outgoing links and records\n * the corresponding contact event. Returns an unsubscribe function. Safe to\n * call only in the browser; no-op on the server.\n */\n function subscribeContactLinkAutoTrack(): () => void {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return () => {}\n }\n\n const handler = (event: MouseEvent) => {\n if (!canSend()) {\n return\n }\n const target = event.target\n if (!(target instanceof Element)) {\n return\n }\n const anchor = target.closest(\"a[href]\")\n if (!(anchor instanceof HTMLAnchorElement)) {\n return\n }\n if (\n anchor.closest(\"[data-jmp-no-track]\") ||\n anchor.closest(\"[data-jmp-tracked]\")\n ) {\n return\n }\n\n const href = anchor.getAttribute(\"href\") ?? \"\"\n const classified = classifyContactHref(href)\n if (!classified) {\n return\n }\n\n const path = window.location.pathname\n\n if (classified.kind === \"call\") {\n if (dedupeContactClick(`call_click:${path}`)) {\n return\n }\n const contactTarget = extractTelTarget(href)\n void trackCallClick(\n path,\n contactTarget ? { contactTarget } : undefined\n )\n return\n }\n if (classified.kind === \"email\") {\n if (dedupeContactClick(`email_click:${path}`)) {\n return\n }\n const contactTarget = extractMailtoTarget(href)\n void trackEmailClick(\n path,\n contactTarget ? { contactTarget } : undefined\n )\n return\n }\n if (dedupeContactClick(`contact_click:${classified.channel}:${path}`)) {\n return\n }\n void trackContactClick(path, {\n channel: classified.channel,\n linkHost: classified.linkHost,\n })\n }\n\n document.addEventListener(\"click\", handler, { capture: true })\n return () => {\n document.removeEventListener(\"click\", handler, { capture: true } as EventListenerOptions)\n }\n }\n\n function dedupeContactClick(key: string): boolean {\n const now = Date.now()\n if (key === lastContactClickKey && now - lastContactClickAt < 1000) {\n return true\n }\n lastContactClickKey = key\n lastContactClickAt = now\n return false\n }\n\n if (typeof window !== \"undefined\" && canSend()) {\n captureLandingAttribution(window.location.hostname)\n }\n\n if (\n typeof window !== \"undefined\" &&\n config.autoTrackContactLinks &&\n canSend()\n ) {\n subscribeContactLinkAutoTrack()\n }\n\n return {\n track,\n trackPageView,\n trackFormSubmit,\n trackCallClick,\n trackEmailClick,\n trackContactClick,\n trackLead,\n subscribeToSpaNavigation,\n subscribeContactLinkAutoTrack,\n setTrackingConsent: setJmpTrackingConsent,\n isTrackingConsentGranted: isJmpTrackingConsentGranted,\n }\n}\n\nexport type JmpAnalytics = ReturnType<typeof createJmpAnalytics>\n","/**\n * Public env vars for JMP — supports Next.js (`NEXT_PUBLIC_*`) and Astro (`PUBLIC_*`).\n * Server/build: `process.env`. Astro client bundles: pass overrides from `import.meta.env`.\n */\n\nexport type JmpPublicEnv = {\n analyticsUrl?: string\n trackingKey?: string\n requireConsent?: boolean\n autoContactLinks?: boolean\n}\n\nfunction firstDefined(...values: (string | undefined)[]): string | undefined {\n for (const v of values) {\n if (v) return v\n }\n return undefined\n}\n\n/** Static reads so Next.js / Vite inline `NEXT_PUBLIC_*` into client bundles. */\nfunction readJmpPublicEnvFromProcessEnv(): Omit<JmpPublicEnv, never> {\n if (typeof process === \"undefined\" || !process.env) {\n return {}\n }\n const { env } = process\n const analyticsUrl = firstDefined(\n env.NEXT_PUBLIC_JMP_ANALYTICS_URL,\n env.PUBLIC_JMP_ANALYTICS_URL,\n )\n const trackingKey = firstDefined(\n env.NEXT_PUBLIC_JMP_TRACKING_KEY,\n env.PUBLIC_JMP_TRACKING_KEY,\n )\n const requireConsentRaw = firstDefined(\n env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,\n env.PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,\n )\n const autoContactRaw = firstDefined(\n env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS,\n env.PUBLIC_JMP_AUTO_CONTACT_LINKS,\n )\n\n return {\n analyticsUrl,\n trackingKey,\n requireConsent: requireConsentRaw === \"true\",\n autoContactLinks: autoContactRaw === \"true\",\n }\n}\n\n/** Read dashboard URL + tracking key from Node / build-time env. */\nexport function readJmpPublicEnvFromProcess(\n overrides?: Partial<JmpPublicEnv>,\n): JmpPublicEnv {\n const fromEnv = readJmpPublicEnvFromProcessEnv()\n\n return {\n analyticsUrl: firstDefined(overrides?.analyticsUrl, fromEnv.analyticsUrl),\n trackingKey: firstDefined(overrides?.trackingKey, fromEnv.trackingKey),\n requireConsent: overrides?.requireConsent ?? fromEnv.requireConsent,\n autoContactLinks:\n overrides?.autoContactLinks ?? fromEnv.autoContactLinks,\n }\n}\n\n/** Read from Astro/Vite `import.meta.env` in client scripts. */\nexport function readJmpPublicEnvFromImportMeta(\n meta: Record<string, unknown> | undefined,\n overrides?: Partial<JmpPublicEnv>,\n): JmpPublicEnv {\n const get = (key: string): string | undefined => {\n const v = meta?.[key]\n return typeof v === \"string\" && v.length > 0 ? v : undefined\n }\n\n const analyticsUrl = firstDefined(\n overrides?.analyticsUrl,\n get(\"PUBLIC_JMP_ANALYTICS_URL\"),\n get(\"NEXT_PUBLIC_JMP_ANALYTICS_URL\"),\n )\n const trackingKey = firstDefined(\n overrides?.trackingKey,\n get(\"PUBLIC_JMP_TRACKING_KEY\"),\n get(\"NEXT_PUBLIC_JMP_TRACKING_KEY\"),\n )\n const requireConsentRaw = firstDefined(\n overrides?.requireConsent !== undefined\n ? String(overrides.requireConsent)\n : undefined,\n get(\"PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT\"),\n get(\"NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT\"),\n )\n const autoContactRaw = firstDefined(\n overrides?.autoContactLinks !== undefined\n ? String(overrides.autoContactLinks)\n : undefined,\n get(\"PUBLIC_JMP_AUTO_CONTACT_LINKS\"),\n get(\"NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS\"),\n )\n\n return {\n analyticsUrl,\n trackingKey,\n requireConsent: requireConsentRaw === \"true\",\n autoContactLinks: autoContactRaw === \"true\",\n }\n}\n","import type { JmpContentManifest } from \"./content/manifest\"\nimport type { JmpContentConfig, JmpContentWrapper } from \"./types\"\nimport { readJmpPublicEnvFromProcess } from \"./env-public\"\n\nexport type JmpSiteSocialLinks = {\n linkedin: string | null\n instagram: string | null\n facebook: string | null\n x: string | null\n youtube: string | null\n}\n\n/** Per-site values used when the dashboard profile is missing or fields are empty. */\nexport type JmpSiteContactFallback = {\n displayName?: string\n founderName?: string\n email?: string\n phone?: string | null\n linkedin?: string | null\n instagram?: string | null\n facebook?: string | null\n x?: string | null\n youtube?: string | null\n hours?: string | null\n serviceArea?: string | null\n address?: string | null\n googleMapsUrl?: string | null\n googleMapsEmbedUrl?: string | null\n dashboardDemoUrl?: string\n profilePhotoSrc?: string\n privacyUrl?: string\n termsUrl?: string\n}\n\nexport type JmpSiteDefinition = {\n /**\n * Content areas this site actually renders. When set, capabilities report\n * this list (manual mode) so unused dashboard editors stay hidden.\n * List granular Trust slots (`trust.summary`, `trust.reviews`) instead of\n * a bare `trust` wrapper.\n */\n contentWrappers?: JmpContentWrapper[]\n /**\n * Override report mode. Defaults to `manual` when `contentWrappers` is set.\n */\n contentWrapperMode?: JmpContentConfig[\"contentWrapperMode\"]\n /**\n * Routes, trust block order, and contact extras for dashboard layout sync.\n * Reported with capabilities when the site loads content from the portal.\n */\n contentManifest?: JmpContentManifest\n /**\n * Public site origin (no trailing slash), e.g. `https://example.com`.\n * Used to resolve relative profile image paths in structured data.\n */\n siteUrl?: string\n /**\n * JMP dashboard origin (no trailing slash), e.g. `https://portal.example.com`.\n * Fallback when `NEXT_PUBLIC_JMP_ANALYTICS_URL` is missing from the client bundle.\n */\n analyticsPortalUrl?: string\n contactFallback?: JmpSiteContactFallback\n /**\n * `extras` keys to read from the dashboard site profile (hyphenated keys from admin).\n */\n contactExtraKeys?: {\n founderName?: readonly string[]\n dashboardDemoUrl?: readonly string[]\n profilePhotoSrc?: readonly string[]\n hours?: readonly string[]\n serviceArea?: readonly string[]\n googleMapsEmbedUrl?: readonly string[]\n }\n}\n\nlet registeredSite: JmpSiteDefinition | null = null\n\n/**\n * Register site-specific JMP integration options once (typically from `jmp.config.ts`).\n * Call at module load time before server content or instrumentation runs.\n */\nexport function defineJmpSite(definition: JmpSiteDefinition): JmpSiteDefinition {\n registeredSite = definition\n return definition\n}\n\nexport function getJmpSiteDefinition(): JmpSiteDefinition | null {\n return registeredSite\n}\n\n/** Server content + lead config: env vars + wrappers from {@link defineJmpSite}. */\nexport function getJmpContentConfig(): JmpContentConfig | null {\n const { analyticsUrl, trackingKey } = readJmpPublicEnvFromProcess()\n if (!analyticsUrl || !trackingKey) {\n return null\n }\n const site = getJmpSiteDefinition()\n const contentWrappers = site?.contentWrappers ?? undefined\n const inferredMode =\n contentWrappers && contentWrappers.length > 0 ? \"manual\" : undefined\n return {\n baseUrl: analyticsUrl,\n trackingKey,\n contentWrappers,\n contentManifest: site?.contentManifest ?? undefined,\n contentWrapperMode: site?.contentWrapperMode ?? inferredMode,\n }\n}\n","import { getJmpSiteDefinition } from \"../site-config\"\nimport type { JmpLandingPage, JmpLandingPageKind } from \"../types\"\nimport { jmpLandingKindSegment } from \"./hub\"\n\n/** Strip lightweight markdown for meta descriptions and schema text fields. */\nexport function plainTextFromMarkdown(input: string, maxLength = 5000): string {\n return input.replace(/[#*_`[\\]]/g, \"\").trim().slice(0, maxLength)\n}\n\nexport function resolveJmpSiteUrl(override?: string): string | null {\n const fromArg = override?.trim().replace(/\\/$/, \"\")\n if (fromArg) return fromArg\n const fromConfig = getJmpSiteDefinition()?.siteUrl?.trim().replace(/\\/$/, \"\")\n return fromConfig || null\n}\n\nexport function absoluteJmpSiteUrl(path: string, siteUrl?: string): string {\n const base = resolveJmpSiteUrl(siteUrl)\n if (!base) {\n return path.startsWith(\"/\") ? path : `/${path}`\n }\n const normalized = path.startsWith(\"/\") ? path : `/${path}`\n return `${base}${normalized}`\n}\n\nexport function filterJmpLandingPagesForDefaultLocale(\n pages: JmpLandingPage[],\n kind: JmpLandingPageKind\n): JmpLandingPage[] {\n const segment = jmpLandingKindSegment(kind)\n return pages.filter((page) => {\n const parts = page.path.split(\"/\").filter(Boolean)\n return parts[0] === segment\n })\n}\n\n/** Pages whose path is `/{locale}/{areas|services}/{slug}` (three+ segments). */\nexport function filterJmpLandingPagesForLocalizedRoutes(\n pages: JmpLandingPage[],\n kind: JmpLandingPageKind\n): JmpLandingPage[] {\n const segment = jmpLandingKindSegment(kind)\n return pages.filter((page) => {\n const parts = page.path.split(\"/\").filter(Boolean)\n return parts.length >= 3 && parts[1] === segment\n })\n}\n\nexport function jmpLocalizedLandingStaticParams(\n pages: JmpLandingPage[],\n kind: JmpLandingPageKind\n): { locale: string; slug: string }[] {\n return filterJmpLandingPagesForLocalizedRoutes(pages, kind).map((page) => {\n const [locale, , slug] = page.path.split(\"/\").filter(Boolean)\n return { locale: locale!, slug: slug! }\n })\n}\n","import { resolveJmpSiteUrl } from \"./landing-pages/utils\"\n\n/**\n * Site origin for server-to-server JMP API calls (content + ingest).\n * Prefer `defineJmpSite({ siteUrl })`, then `NEXT_PUBLIC_SITE_URL`.\n */\nexport function resolveJmpRequestOrigin(): string | null {\n const fromSite = resolveJmpSiteUrl()\n if (fromSite) {\n return fromSite\n }\n if (typeof process === \"undefined\") {\n return null\n }\n return process.env.NEXT_PUBLIC_SITE_URL?.trim().replace(/\\/$/, \"\") || null\n}\n\n/** Adds `Origin` when a site URL is known (required for production write/ingest checks). */\nexport function withJmpOriginHeader(\n headers: Record<string, string>\n): Record<string, string> {\n const origin = resolveJmpRequestOrigin()\n if (!origin) {\n return headers\n }\n return { ...headers, Origin: origin }\n}\n","import {\n getHeader,\n normalizeBaseUrl,\n pathFromRequestUrl,\n} from \"../http\"\nimport { withJmpOriginHeader } from \"../request-origin\"\nimport type { JmpContentConfig, TrackServerPageViewOptions } from \"../types\"\n\nexport async function trackJmpServerPageView(\n config: JmpContentConfig,\n options: TrackServerPageViewOptions = {}\n): Promise<void> {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const resolvedFetch =\n config.fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n\n if (!resolvedFetch) {\n throw new Error(\"JMP server analytics: fetch is not available; pass fetchImpl in config\")\n }\n\n const visitorUserAgent =\n options.userAgent ?? getHeader(options.request?.headers, \"user-agent\")\n const visitorReferer =\n options.referer ?? getHeader(options.request?.headers, \"referer\")\n const path = options.path ?? pathFromRequestUrl(options.request?.url)\n\n const headers: Record<string, string> = withJmpOriginHeader({\n \"Content-Type\": \"application/json\",\n \"X-JMP-Tracking-Key\": config.trackingKey,\n })\n if (visitorUserAgent) {\n headers[\"X-JMP-Visitor-User-Agent\"] = visitorUserAgent\n }\n if (visitorReferer) {\n headers[\"X-JMP-Visitor-Referer\"] = visitorReferer\n }\n\n const payload: Record<string, unknown> = {\n type: \"page_view\",\n path: path || \"/\",\n metadata:\n options.metadata && typeof options.metadata === \"object\"\n ? options.metadata\n : {},\n }\n if (options.sessionId) {\n payload.sessionId = options.sessionId\n }\n\n const url = `${baseUrl}/api/events`\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, payload)\n }\n\n const res = await resolvedFetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!res.ok) {\n const text = await res.text()\n throw new Error(`JMP server analytics HTTP ${res.status} — ${text}`)\n }\n}\n","/** Mirrors jmp-dashboard `lib/content/wrappers/client-manifest.ts` (keep in sync). */\n\nexport const JMP_CONTENT_MANIFEST_VERSION = 1\n\nexport type JmpTrustSection =\n | \"summary\"\n | \"testimonials\"\n | \"reviews\"\n | \"stats\"\n | \"logos\"\n | \"credentials\"\n\nexport type JmpContentRouteManifest = {\n wrapper: string\n pattern: string\n index?: string\n label?: string\n}\n\nexport type JmpTrustBlockManifest = {\n section: JmpTrustSection\n label?: string\n}\n\nexport type JmpContactExtraManifest = {\n key: string\n label: string\n}\n\nexport type JmpLeadInboxManifest = {\n list?: string[]\n detail?: string[]\n labels?: Record<string, string>\n}\n\nexport type JmpExternalSanitySourceManifest = {\n studioUrl?: string\n}\n\nexport type JmpExternalShopifySourceManifest = {\n adminUrl?: string\n storeUrl?: string\n}\n\nexport type JmpExternalAdminLinkManifest = {\n id: string\n label: string\n url: string\n}\n\nexport type JmpExternalSourcesManifest = {\n sanity?: JmpExternalSanitySourceManifest\n shopify?: JmpExternalShopifySourceManifest\n links?: JmpExternalAdminLinkManifest[]\n}\n\nexport type JmpContentManifest = {\n version?: number\n routes?: JmpContentRouteManifest[]\n externalSources?: JmpExternalSourcesManifest\n trust?: {\n blocks?: JmpTrustBlockManifest[]\n labels?: Partial<Record<JmpTrustSection, string>>\n mergeTestimonialsReviews?: boolean\n }\n contact?: {\n extras?: JmpContactExtraManifest[]\n leadInbox?: JmpLeadInboxManifest\n }\n defaults?: {\n contact?: {\n displayName?: string\n email?: string\n phone?: string\n address?: string\n hours?: string\n serviceArea?: string\n googleMapsUrl?: string\n linkedinUrl?: string\n instagramUrl?: string\n facebookUrl?: string\n xUrl?: string\n youtubeUrl?: string\n extras?: Record<string, string>\n }\n faq?: Array<{ question: string; answer: string; category?: string }>\n trust?: {\n googleReviewsUrl?: string\n googlePlaceId?: string\n yelpUrl?: string\n trustpilotUrl?: string\n disclaimer?: string\n }\n }\n}\n\nconst TRUST_SECTIONS = new Set<string>([\n \"summary\",\n \"testimonials\",\n \"reviews\",\n \"stats\",\n \"logos\",\n \"credentials\",\n])\n\nfunction normalizeKey(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n}\n\nfunction isValidExtraKey(key: string): boolean {\n return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(key)\n}\n\nconst MAX_EXTERNAL_ADMIN_LINKS = 10\nconst MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH = 80\nconst EXTERNAL_ADMIN_LINK_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\nfunction tryNormalizeHttpUrl(input: unknown): string | null {\n if (typeof input !== \"string\" || !input.trim()) {\n return null\n }\n try {\n const url = new URL(input.trim())\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n return null\n }\n return url.toString().replace(/\\/$/, \"\")\n } catch {\n return null\n }\n}\n\nfunction normalizeShopifyExternalSource(\n shopify: JmpExternalShopifySourceManifest | undefined\n): JmpExternalShopifySourceManifest | null {\n if (!shopify || typeof shopify !== \"object\") {\n return null\n }\n const adminUrl = tryNormalizeHttpUrl(shopify.adminUrl)\n const storeUrl = tryNormalizeHttpUrl(shopify.storeUrl)\n if (!adminUrl && !storeUrl) {\n return null\n }\n return {\n ...(adminUrl ? { adminUrl } : {}),\n ...(storeUrl ? { storeUrl } : {}),\n }\n}\n\nfunction normalizeExternalAdminLinkEntries(\n links: JmpExternalAdminLinkManifest[] | undefined\n): JmpExternalAdminLinkManifest[] {\n if (!Array.isArray(links)) {\n return []\n }\n const seenIds = new Set<string>()\n const out: JmpExternalAdminLinkManifest[] = []\n for (const raw of links) {\n if (!raw || typeof raw !== \"object\" || out.length >= MAX_EXTERNAL_ADMIN_LINKS) {\n continue\n }\n const id =\n typeof raw.id === \"string\"\n ? raw.id.trim().toLowerCase().replace(/[^a-z0-9-]+/g, \"-\").replace(/^-+|-+$/g, \"\")\n : \"\"\n const label =\n typeof raw.label === \"string\"\n ? raw.label.trim().slice(0, MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH)\n : \"\"\n const url = tryNormalizeHttpUrl(raw.url)\n if (\n !id ||\n !label ||\n !url ||\n !EXTERNAL_ADMIN_LINK_ID_PATTERN.test(id) ||\n seenIds.has(id)\n ) {\n continue\n }\n seenIds.add(id)\n out.push({ id, label, url })\n }\n return out\n}\n\nfunction normalizeExternalSources(\n externalSources: JmpExternalSourcesManifest | undefined\n): JmpExternalSourcesManifest | null {\n if (!externalSources || typeof externalSources !== \"object\") {\n return null\n }\n const studioUrl = tryNormalizeHttpUrl(externalSources.sanity?.studioUrl)\n const shopify = normalizeShopifyExternalSource(externalSources.shopify)\n const links = normalizeExternalAdminLinkEntries(externalSources.links)\n if (!studioUrl && !shopify && links.length === 0) {\n return null\n }\n return {\n ...(studioUrl ? { sanity: { studioUrl } } : {}),\n ...(shopify ? { shopify } : {}),\n ...(links.length > 0 ? { links } : {}),\n }\n}\n\nexport function normalizeJmpContentManifest(\n input: JmpContentManifest | null | undefined\n): JmpContentManifest | null {\n if (!input || typeof input !== \"object\") {\n return null\n }\n\n const routes = normalizeRoutes(input.routes)\n const externalSources = normalizeExternalSources(input.externalSources)\n const trust = normalizeTrust(input.trust)\n const contact = normalizeContact(input.contact)\n const defaults = normalizeManifestDefaults(input.defaults)\n\n if (\n routes.length === 0 &&\n !externalSources &&\n !trust &&\n !contact &&\n !defaults\n ) {\n return null\n }\n\n return {\n version: JMP_CONTENT_MANIFEST_VERSION,\n ...(routes.length > 0 ? { routes } : {}),\n ...(externalSources ? { externalSources } : {}),\n ...(trust ? { trust } : {}),\n ...(contact ? { contact } : {}),\n ...(defaults ? { defaults } : {}),\n }\n}\n\nfunction normalizeRoutes(\n routes: JmpContentRouteManifest[] | undefined\n): JmpContentRouteManifest[] {\n if (!Array.isArray(routes)) {\n return []\n }\n const seen = new Set<string>()\n const out: JmpContentRouteManifest[] = []\n for (const raw of routes) {\n if (!raw || typeof raw !== \"object\") continue\n const wrapper =\n typeof raw.wrapper === \"string\" ? raw.wrapper.trim().toLowerCase() : \"\"\n const pattern =\n typeof raw.pattern === \"string\" ? raw.pattern.trim() : \"\"\n if (!wrapper || !pattern) continue\n const dedupe = `${wrapper}:${pattern}`\n if (seen.has(dedupe)) continue\n seen.add(dedupe)\n out.push({\n wrapper,\n pattern,\n ...(typeof raw.index === \"string\" && raw.index.trim()\n ? { index: raw.index.trim() }\n : {}),\n ...(typeof raw.label === \"string\" && raw.label.trim()\n ? { label: raw.label.trim() }\n : {}),\n })\n }\n return out\n}\n\nfunction normalizeTrust(\n trust: JmpContentManifest[\"trust\"] | undefined\n): JmpContentManifest[\"trust\"] | null {\n if (!trust || typeof trust !== \"object\") return null\n const blocks = normalizeTrustBlocks(trust.blocks)\n const labels = normalizeTrustLabels(trust.labels)\n const mergeTestimonialsReviews = trust.mergeTestimonialsReviews === true\n if (blocks.length === 0 && !labels && !mergeTestimonialsReviews) return null\n return {\n ...(blocks.length > 0 ? { blocks } : {}),\n ...(labels ? { labels } : {}),\n ...(mergeTestimonialsReviews ? { mergeTestimonialsReviews: true } : {}),\n }\n}\n\nfunction normalizeTrustBlocks(\n blocks: JmpTrustBlockManifest[] | undefined\n): JmpTrustBlockManifest[] {\n if (!Array.isArray(blocks)) return []\n const seen = new Set<string>()\n const out: JmpTrustBlockManifest[] = []\n for (const raw of blocks) {\n if (!raw || typeof raw !== \"object\") continue\n const section =\n typeof raw.section === \"string\" ? raw.section.trim().toLowerCase() : \"\"\n if (!TRUST_SECTIONS.has(section) || seen.has(section)) continue\n seen.add(section)\n out.push({\n section: section as JmpTrustSection,\n ...(typeof raw.label === \"string\" && raw.label.trim()\n ? { label: raw.label.trim() }\n : {}),\n })\n }\n return out\n}\n\nfunction normalizeTrustLabels(\n labels: Partial<Record<JmpTrustSection, string>> | undefined\n): Partial<Record<JmpTrustSection, string>> | null {\n if (!labels || typeof labels !== \"object\") return null\n const out: Partial<Record<JmpTrustSection, string>> = {}\n for (const [key, value] of Object.entries(labels)) {\n if (TRUST_SECTIONS.has(key) && typeof value === \"string\" && value.trim()) {\n out[key as JmpTrustSection] = value.trim()\n }\n }\n return Object.keys(out).length > 0 ? out : null\n}\n\nfunction readDefaultText(value: unknown, max = 500): string | undefined {\n if (typeof value !== \"string\") return undefined\n const trimmed = value.trim()\n if (!trimmed) return undefined\n return trimmed.slice(0, max)\n}\n\nfunction normalizeManifestDefaults(\n defaults: JmpContentManifest[\"defaults\"] | undefined\n): JmpContentManifest[\"defaults\"] | null {\n if (!defaults || typeof defaults !== \"object\") return null\n\n const contactRaw = defaults.contact\n const contact: NonNullable<JmpContentManifest[\"defaults\"]>[\"contact\"] = {}\n if (contactRaw && typeof contactRaw === \"object\") {\n const displayName = readDefaultText(contactRaw.displayName, 120)\n const email = readDefaultText(contactRaw.email, 200)\n const phone = readDefaultText(contactRaw.phone, 40)\n const address = readDefaultText(contactRaw.address, 400)\n const hours = readDefaultText(contactRaw.hours, 400)\n const serviceArea = readDefaultText(contactRaw.serviceArea, 200)\n const googleMapsUrl = readDefaultText(contactRaw.googleMapsUrl, 2048)\n const linkedinUrl = readDefaultText(contactRaw.linkedinUrl, 2048)\n const instagramUrl = readDefaultText(contactRaw.instagramUrl, 2048)\n const facebookUrl = readDefaultText(contactRaw.facebookUrl, 2048)\n const xUrl = readDefaultText(contactRaw.xUrl, 2048)\n const youtubeUrl = readDefaultText(contactRaw.youtubeUrl, 2048)\n if (displayName) contact.displayName = displayName\n if (email) contact.email = email\n if (phone) contact.phone = phone\n if (address) contact.address = address\n if (hours) contact.hours = hours\n if (serviceArea) contact.serviceArea = serviceArea\n if (googleMapsUrl) contact.googleMapsUrl = googleMapsUrl\n if (linkedinUrl) contact.linkedinUrl = linkedinUrl\n if (instagramUrl) contact.instagramUrl = instagramUrl\n if (facebookUrl) contact.facebookUrl = facebookUrl\n if (xUrl) contact.xUrl = xUrl\n if (youtubeUrl) contact.youtubeUrl = youtubeUrl\n if (contactRaw.extras && typeof contactRaw.extras === \"object\") {\n const extras: Record<string, string> = {}\n for (const [rawKey, rawValue] of Object.entries(contactRaw.extras)) {\n if (Object.keys(extras).length >= 10) break\n const key = normalizeKey(rawKey)\n const value = readDefaultText(rawValue, 200)\n if (key && isValidExtraKey(key) && value) extras[key] = value\n }\n if (Object.keys(extras).length > 0) contact.extras = extras\n }\n }\n\n const faq: NonNullable<JmpContentManifest[\"defaults\"]>[\"faq\"] = []\n if (Array.isArray(defaults.faq)) {\n for (const raw of defaults.faq) {\n if (!raw || typeof raw !== \"object\" || faq.length >= 40) continue\n const question = readDefaultText(raw.question, 300)\n const answer = readDefaultText(raw.answer, 8000)\n if (!question || !answer) continue\n const category = readDefaultText(raw.category, 80)\n faq.push({ question, answer, ...(category ? { category } : {}) })\n }\n }\n\n const trustRaw = defaults.trust\n const trust: NonNullable<JmpContentManifest[\"defaults\"]>[\"trust\"] = {}\n if (trustRaw && typeof trustRaw === \"object\") {\n const assign = (\n key: keyof NonNullable<typeof trust>,\n max: number\n ) => {\n const value = readDefaultText(trustRaw[key], max)\n if (value) trust[key] = value\n }\n assign(\"googleReviewsUrl\", 2048)\n assign(\"googlePlaceId\", 128)\n assign(\"yelpUrl\", 2048)\n assign(\"trustpilotUrl\", 2048)\n assign(\"disclaimer\", 1000)\n }\n\n const hasContact = Object.keys(contact).length > 0\n const hasTrust = Object.keys(trust).length > 0\n if (!hasContact && faq.length === 0 && !hasTrust) return null\n\n return {\n ...(hasContact ? { contact } : {}),\n ...(faq.length > 0 ? { faq } : {}),\n ...(hasTrust ? { trust } : {}),\n }\n}\n\nfunction normalizeContact(\n contact: JmpContentManifest[\"contact\"] | undefined\n): JmpContentManifest[\"contact\"] | null {\n if (!contact || typeof contact !== \"object\") return null\n const extras = normalizeContactExtras(contact.extras)\n const leadInbox = normalizeLeadInbox(contact.leadInbox)\n if (extras.length === 0 && !leadInbox) return null\n return {\n ...(extras.length > 0 ? { extras } : {}),\n ...(leadInbox ? { leadInbox } : {}),\n }\n}\n\nfunction normalizeLeadInbox(\n raw: JmpLeadInboxManifest | undefined\n): JmpLeadInboxManifest | null {\n if (!raw || typeof raw !== \"object\") return null\n const list = normalizeInboxKeyList(raw.list, 8)\n const detail = normalizeInboxKeyList(raw.detail, 24)\n const labels = normalizeInboxLabels(raw.labels)\n if (!list && !detail && !labels) return null\n return {\n ...(list ? { list } : {}),\n ...(detail ? { detail } : {}),\n ...(labels ? { labels } : {}),\n }\n}\n\nfunction normalizeInboxKeyList(\n raw: string[] | undefined,\n max: number\n): string[] | undefined {\n if (!Array.isArray(raw)) return undefined\n const seen = new Set<string>()\n const out: string[] = []\n for (const item of raw) {\n if (typeof item !== \"string\" || out.length >= max) continue\n const key = item.trim()\n const token = key.replace(/[^a-zA-Z0-9]+/g, \"\").toLowerCase()\n if (!key || !token || seen.has(token)) continue\n seen.add(token)\n out.push(key)\n }\n return out.length > 0 ? out : undefined\n}\n\nfunction normalizeInboxLabels(\n raw: Record<string, string> | undefined\n): Record<string, string> | undefined {\n if (!raw || typeof raw !== \"object\") return undefined\n const out: Record<string, string> = {}\n for (const [key, value] of Object.entries(raw)) {\n if (typeof value !== \"string\") continue\n const label = value.trim().slice(0, 60)\n const token = key.trim()\n if (!token || !label) continue\n out[token] = label\n }\n return Object.keys(out).length > 0 ? out : undefined\n}\n\nfunction normalizeContactExtras(\n extras: JmpContactExtraManifest[] | undefined\n): JmpContactExtraManifest[] {\n if (!Array.isArray(extras)) return []\n const seen = new Set<string>()\n const out: JmpContactExtraManifest[] = []\n for (const raw of extras) {\n if (!raw || typeof raw !== \"object\") continue\n const label = typeof raw.label === \"string\" ? raw.label.trim() : \"\"\n const key = normalizeKey(\n typeof raw.key === \"string\" && raw.key.trim() ? raw.key : label\n )\n if (!key || !label || !isValidExtraKey(key) || seen.has(key)) continue\n seen.add(key)\n out.push({ key, label })\n }\n return out\n}\n\nexport function stableJmpManifestFingerprint(\n manifest: JmpContentManifest | null\n): string {\n return manifest ? JSON.stringify(manifest) : \"\"\n}\n\nexport function inferWrapperSlotsFromManifest(\n manifest: JmpContentManifest | null\n): string[] {\n const slots = new Set<string>()\n for (const route of manifest?.routes ?? []) {\n slots.add(route.wrapper)\n }\n for (const block of manifest?.trust?.blocks ?? []) {\n slots.add(`trust.${block.section}`)\n slots.add(\"trust\")\n }\n if (manifest?.contact?.extras?.length || manifest?.contact?.leadInbox) {\n slots.add(\"contact\")\n }\n return [...slots]\n}\n","import {\n JMP_CONTENT_CACHE_TAG,\n JMP_CONTENT_REVALIDATE_SECONDS,\n} from \"../constants\"\nimport { normalizeBaseUrl, responseLooksLikeHtml } from \"../http\"\nimport { withJmpOriginHeader } from \"../request-origin\"\nimport type { JmpContentConfig } from \"../types\"\n\n/**\n * Headers for server content API calls. Sends `Origin` from siteUrl /\n * NEXT_PUBLIC_SITE_URL when available (required for capabilities writes in\n * production; helpful for content reads).\n */\nexport function jmpContentRequestHeaders(\n config: JmpContentConfig\n): Record<string, string> {\n return withJmpOriginHeader({\n \"X-JMP-Tracking-Key\": config.trackingKey,\n })\n}\n\nexport async function getContent<T>(\n config: JmpContentConfig,\n path: string\n): Promise<T> {\n const text = await getContentText(config, path)\n\n try {\n return JSON.parse(text) as T\n } catch {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const url = `${baseUrl}${path}`\n throw new Error(`JMP content HTTP 200 — ${url} returned invalid JSON.`)\n }\n}\n\nexport async function getContentText(\n config: JmpContentConfig,\n path: string\n): Promise<string> {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const resolvedFetch =\n config.fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n\n if (!resolvedFetch) {\n throw new Error(\"JMP content: fetch is not available; pass fetchImpl in config\")\n }\n\n const url = `${baseUrl}${path}`\n\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"GET\", url)\n }\n\n const res = await resolvedFetch(url, {\n method: \"GET\",\n headers: jmpContentRequestHeaders(config),\n next: {\n revalidate: JMP_CONTENT_REVALIDATE_SECONDS,\n tags: [JMP_CONTENT_CACHE_TAG],\n },\n })\n\n const text = await res.text()\n\n if (!res.ok) {\n if (responseLooksLikeHtml(text)) {\n throw new Error(\n `JMP content HTTP ${res.status} — ${url} returned HTML (not the JSON API). ` +\n `Set baseUrl to your JMP Analytics dashboard origin.`\n )\n }\n\n let parsed: { error?: string; hint?: string } = {}\n try {\n parsed = JSON.parse(text) as typeof parsed\n } catch {\n parsed = { error: text }\n }\n\n throw new Error(\n [`JMP content HTTP ${res.status}`, parsed.error, parsed.hint]\n .filter(Boolean)\n .join(\" — \")\n )\n }\n\n return text\n}\n","import {\n inferWrapperSlotsFromManifest,\n normalizeJmpContentManifest,\n type JmpContentManifest,\n} from \"./manifest\"\nimport type { JmpContentConfig, JmpContentWrapper, JmpTrustBundle } from \"../types\"\nimport {\n getJmpSiteDefinition,\n type JmpSiteContactFallback,\n} from \"../site-config\"\n\n/** Stable report order (matches dashboard `CLIENT_REPORTABLE_WRAPPER_SLOTS`). */\nconst WRAPPER_SLOT_ORDER: readonly string[] = [\n \"blog\",\n \"faq\",\n \"contact\",\n \"legal\",\n \"trust\",\n \"trust.summary\",\n \"trust.testimonials\",\n \"trust.reviews\",\n \"trust.stats\",\n \"trust.logos\",\n \"trust.credentials\",\n]\n\nconst discovered = new Set<string>()\nlet syncTimer: ReturnType<typeof setTimeout> | null = null\nlet pendingSyncConfig: JmpContentConfig | null = null\n\nconst reportedDedupeKeys = new Set<string>()\nlet syncHandler: ((config: JmpContentConfig) => Promise<unknown>) | null = null\n\nexport function markContentWrapper(slot: JmpContentWrapper | string): void {\n const normalized = slot.trim().toLowerCase()\n if (!normalized) {\n return\n }\n discovered.add(normalized)\n}\n\nexport function markTrustBundleWrappers(bundle: JmpTrustBundle): void {\n for (const slot of inferTrustWrapperSlots(bundle)) {\n discovered.add(slot)\n }\n}\n\nexport function inferTrustWrapperSlots(bundle: JmpTrustBundle): string[] {\n const slots = new Set<string>()\n const { summary, testimonials, stats, logos, credentials } = bundle\n\n const hasSummary =\n summary.google_rating != null ||\n summary.google_review_count != null ||\n Boolean(summary.google_reviews_url?.trim()) ||\n Boolean(summary.yelp_url?.trim()) ||\n Boolean(summary.trustpilot_url?.trim()) ||\n Boolean(summary.disclaimer?.trim())\n\n if (hasSummary) {\n slots.add(\"trust.summary\")\n }\n\n let hasTestimonials = false\n let hasReviews = false\n for (const item of testimonials) {\n const bucket = item.placement?.trim().toLowerCase()\n if (bucket === \"reviews\") {\n hasReviews = true\n } else {\n hasTestimonials = true\n }\n }\n if (hasTestimonials) {\n slots.add(\"trust.testimonials\")\n }\n if (hasReviews) {\n slots.add(\"trust.reviews\")\n }\n if (stats.length > 0) {\n slots.add(\"trust.stats\")\n }\n if (logos.length > 0) {\n slots.add(\"trust.logos\")\n }\n if (credentials.length > 0) {\n slots.add(\"trust.credentials\")\n }\n\n return sortWrapperSlots([...slots])\n}\n\nexport function getDiscoveredContentWrappers(): string[] {\n return sortWrapperSlots([...discovered])\n}\n\nexport function resolveContentManifestForReport(\n config: JmpContentConfig\n): JmpContentManifest | null {\n const site = getJmpSiteDefinition()\n const fallback = site?.contactFallback\n const existing = config.contentManifest\n const fromFallback = fallbackToManifestDefaults(fallback)\n if (!existing && !fromFallback) {\n return null\n }\n const merged: JmpContentManifest = {\n ...(existing ?? {}),\n defaults: {\n ...(fromFallback ?? {}),\n ...(existing?.defaults ?? {}),\n contact: {\n ...(fromFallback?.contact ?? {}),\n ...(existing?.defaults?.contact ?? {}),\n extras: {\n ...(fromFallback?.contact?.extras ?? {}),\n ...(existing?.defaults?.contact?.extras ?? {}),\n },\n },\n trust: {\n ...(fromFallback?.trust ?? {}),\n ...(existing?.defaults?.trust ?? {}),\n },\n faq: existing?.defaults?.faq?.length\n ? existing.defaults.faq\n : fromFallback?.faq,\n },\n }\n return normalizeJmpContentManifest(merged)\n}\n\nfunction fallbackToManifestDefaults(\n fallback: JmpSiteContactFallback | undefined\n): JmpContentManifest[\"defaults\"] | null {\n if (!fallback) return null\n const contact: NonNullable<JmpContentManifest[\"defaults\"]>[\"contact\"] = {}\n if (fallback.displayName?.trim()) contact.displayName = fallback.displayName.trim()\n if (fallback.email?.trim()) contact.email = fallback.email.trim()\n if (typeof fallback.phone === \"string\" && fallback.phone.trim()) {\n contact.phone = fallback.phone.trim()\n }\n if (fallback.address?.trim()) contact.address = fallback.address.trim()\n if (fallback.hours?.trim()) contact.hours = fallback.hours.trim()\n if (fallback.serviceArea?.trim()) contact.serviceArea = fallback.serviceArea.trim()\n if (fallback.googleMapsUrl?.trim()) {\n contact.googleMapsUrl = fallback.googleMapsUrl.trim()\n }\n if (fallback.linkedin?.trim()) contact.linkedinUrl = fallback.linkedin.trim()\n if (fallback.instagram?.trim()) contact.instagramUrl = fallback.instagram.trim()\n if (fallback.facebook?.trim()) contact.facebookUrl = fallback.facebook.trim()\n if (fallback.x?.trim()) contact.xUrl = fallback.x.trim()\n if (fallback.youtube?.trim()) contact.youtubeUrl = fallback.youtube.trim()\n const trust: NonNullable<JmpContentManifest[\"defaults\"]>[\"trust\"] = {}\n if (fallback.googleMapsUrl?.trim()) {\n trust.googleReviewsUrl = fallback.googleMapsUrl.trim()\n }\n const hasContact = Object.keys(contact).length > 0\n const hasTrust = Object.keys(trust).length > 0\n if (!hasContact && !hasTrust) return null\n return {\n ...(hasContact ? { contact } : {}),\n ...(hasTrust ? { trust } : {}),\n }\n}\n\nexport function resolveContentWrappersForReport(\n config: JmpContentConfig\n): string[] {\n const explicit = config.contentWrappers ?? []\n const auto = getDiscoveredContentWrappers()\n const fromManifest = inferWrapperSlotsFromManifest(\n resolveContentManifestForReport(config)\n )\n\n if (config.contentWrapperMode === \"manual\") {\n return sortWrapperSlots([...explicit, ...fromManifest])\n }\n\n if (config.contentWrapperMode === \"explicit-only\") {\n return sortWrapperSlots([...explicit, ...fromManifest])\n }\n\n const merged = new Set<string>([...explicit, ...auto, ...fromManifest])\n return sortWrapperSlots([...merged])\n}\n\nexport function hasReportedContentWrappers(dedupeKey: string): boolean {\n return reportedDedupeKeys.has(dedupeKey)\n}\n\nexport function rememberReportedContentWrappers(dedupeKey: string): void {\n reportedDedupeKeys.add(dedupeKey)\n}\n\nexport function setContentWrapperSyncHandler(\n handler: (config: JmpContentConfig) => Promise<unknown>\n): void {\n syncHandler = handler\n}\n\n/**\n * Debounced POST after content APIs run (build SSG, first page hit, etc.).\n */\nexport function scheduleContentWrapperSync(config: JmpContentConfig): void {\n if (!syncHandler) {\n return\n }\n pendingSyncConfig = config\n if (syncTimer) {\n clearTimeout(syncTimer)\n }\n syncTimer = setTimeout(() => {\n syncTimer = null\n const cfg = pendingSyncConfig\n pendingSyncConfig = null\n if (!cfg || !syncHandler) {\n return\n }\n void syncHandler(cfg).catch(() => {})\n }, 750)\n}\n\nexport function resetContentWrapperDiscoveryForTests(): void {\n discovered.clear()\n reportedDedupeKeys.clear()\n syncHandler = null\n if (syncTimer) {\n clearTimeout(syncTimer)\n syncTimer = null\n }\n pendingSyncConfig = null\n}\n\nfunction sortWrapperSlots(slots: string[]): string[] {\n const order = new Map(WRAPPER_SLOT_ORDER.map((slot, index) => [slot, index]))\n return [...new Set(slots)].sort((a, b) => {\n const ai = order.get(a) ?? 999\n const bi = order.get(b) ?? 999\n if (ai !== bi) {\n return ai - bi\n }\n return a.localeCompare(b)\n })\n}\n","import { JMP_ANALYTICS_SDK_VERSION } from \"../constants\"\nimport { normalizeBaseUrl } from \"../http\"\nimport type {\n JmpBlogPost,\n JmpContentConfig,\n JmpFaqItem,\n JmpLandingPage,\n JmpLandingPageDetail,\n JmpLandingPageKind,\n JmpLandingPageSitemapEntry,\n JmpLegalDocument,\n JmpPopularPagesResult,\n JmpSiteProfile,\n JmpTrustBundle,\n JmpWebsiteLocation,\n JmpWebsiteLocationDetail,\n} from \"../types\"\nimport { getContent, getContentText, jmpContentRequestHeaders } from \"./fetch\"\nimport {\n stableJmpManifestFingerprint,\n type JmpContentManifest,\n} from \"./manifest\"\nimport {\n hasReportedContentWrappers,\n markContentWrapper,\n markTrustBundleWrappers,\n rememberReportedContentWrappers,\n resolveContentManifestForReport,\n resolveContentWrappersForReport,\n scheduleContentWrapperSync,\n setContentWrapperSyncHandler,\n} from \"./wrapper-discovery\"\n\nexport {\n getDiscoveredContentWrappers,\n inferTrustWrapperSlots,\n markContentWrapper,\n markTrustBundleWrappers,\n resetContentWrapperDiscoveryForTests,\n} from \"./wrapper-discovery\"\n\nfunction afterContentWrapperUse(config: JmpContentConfig): void {\n scheduleContentWrapperSync(config)\n}\n\nexport async function getJmpBlogPosts(\n config: JmpContentConfig,\n filters?: { locale?: string }\n): Promise<JmpBlogPost[]> {\n const params = new URLSearchParams()\n if (filters?.locale) {\n params.set(\"locale\", filters.locale)\n }\n const query = params.toString()\n const data = await getContent<{ posts: JmpBlogPost[] }>(\n config,\n `/api/content/blog${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"blog\")\n afterContentWrapperUse(config)\n return data.posts\n}\n\nexport async function getJmpBlogPost(\n config: JmpContentConfig,\n slug: string,\n locale?: string\n): Promise<JmpBlogPost | null> {\n try {\n const params = new URLSearchParams()\n if (locale) {\n params.set(\"locale\", locale)\n }\n const query = params.toString()\n const data = await getContent<{ post: JmpBlogPost; alternates?: unknown }>(\n config,\n `/api/content/blog/${encodeURIComponent(slug)}${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"blog\")\n afterContentWrapperUse(config)\n return data.post\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpBlogPostDetail(\n config: JmpContentConfig,\n slug: string,\n locale?: string\n): Promise<import(\"../types\").JmpBlogPostDetail | null> {\n try {\n const params = new URLSearchParams()\n if (locale) {\n params.set(\"locale\", locale)\n }\n const query = params.toString()\n const data = await getContent<import(\"../types\").JmpBlogPostDetail>(\n config,\n `/api/content/blog/${encodeURIComponent(slug)}${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"blog\")\n afterContentWrapperUse(config)\n return data\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpFaqs(\n config: JmpContentConfig,\n filters?: { locale?: string }\n): Promise<JmpFaqItem[]> {\n const params = new URLSearchParams()\n if (filters?.locale) {\n params.set(\"locale\", filters.locale)\n }\n const query = params.toString()\n const data = await getContent<{ faqs: JmpFaqItem[] }>(\n config,\n `/api/content/faqs${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"faq\")\n afterContentWrapperUse(config)\n return data.faqs\n}\n\nexport async function getJmpLegalDocument(\n config: JmpContentConfig,\n slug: string\n): Promise<JmpLegalDocument | null> {\n const key = slug.trim().toLowerCase()\n if (!key) {\n return null\n }\n try {\n const data = await getContent<{ document: JmpLegalDocument }>(\n config,\n `/api/content/legal?slug=${encodeURIComponent(key)}`\n )\n markContentWrapper(\"legal\")\n afterContentWrapperUse(config)\n return data.document\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpLegalDocuments(\n config: JmpContentConfig\n): Promise<JmpLegalDocument[]> {\n const data = await getContent<{ documents: JmpLegalDocument[] }>(\n config,\n \"/api/content/legal\"\n )\n markContentWrapper(\"legal\")\n afterContentWrapperUse(config)\n return data.documents\n}\n\nexport async function getJmpFaqDetail(\n config: JmpContentConfig,\n slug: string,\n locale?: string\n): Promise<import(\"../types\").JmpFaqItemDetail | null> {\n try {\n const params = new URLSearchParams()\n if (locale) {\n params.set(\"locale\", locale)\n }\n const query = params.toString()\n const data = await getContent<import(\"../types\").JmpFaqItemDetail>(\n config,\n `/api/content/faqs/${encodeURIComponent(slug)}${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"faq\")\n afterContentWrapperUse(config)\n return data\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpLandingPages(\n config: JmpContentConfig,\n filters?: { kind?: JmpLandingPageKind; locale?: string }\n): Promise<JmpLandingPage[]> {\n const params = new URLSearchParams()\n if (filters?.kind) {\n params.set(\"kind\", filters.kind)\n }\n if (filters?.locale) {\n params.set(\"locale\", filters.locale)\n }\n const query = params.toString()\n const data = await getContent<{ pages: JmpLandingPage[] }>(\n config,\n `/api/content/landing-pages${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"landing\")\n afterContentWrapperUse(config)\n return data.pages\n}\n\nexport async function getJmpLandingPageDetail(\n config: JmpContentConfig,\n kind: JmpLandingPageKind,\n slug: string,\n locale?: string\n): Promise<JmpLandingPageDetail | null> {\n const params = new URLSearchParams()\n if (locale) {\n params.set(\"locale\", locale)\n }\n const query = params.toString()\n try {\n const detail = await getContent<JmpLandingPageDetail>(\n config,\n `/api/content/landing-pages/${encodeURIComponent(kind)}/${encodeURIComponent(slug)}${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"landing\")\n afterContentWrapperUse(config)\n return detail\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpLandingPageSitemap(\n config: JmpContentConfig\n): Promise<JmpLandingPageSitemapEntry[]> {\n const data = await getContent<{ entries: JmpLandingPageSitemapEntry[] }>(\n config,\n \"/api/content/landing-pages/sitemap\"\n )\n markContentWrapper(\"landing\")\n afterContentWrapperUse(config)\n return data.entries\n}\n\nexport async function getJmpLocations(\n config: JmpContentConfig\n): Promise<JmpWebsiteLocation[]> {\n const data = await getContent<{ locations: JmpWebsiteLocation[] }>(\n config,\n \"/api/content/locations\"\n )\n markContentWrapper(\"locations\")\n afterContentWrapperUse(config)\n return data.locations\n}\n\nexport async function getJmpLocationDetail(\n config: JmpContentConfig,\n slug: string\n): Promise<JmpWebsiteLocationDetail | null> {\n const normalized = slug.trim()\n if (!normalized) {\n return null\n }\n try {\n const detail = await getContent<JmpWebsiteLocationDetail>(\n config,\n `/api/content/locations/${encodeURIComponent(normalized)}`\n )\n markContentWrapper(\"locations\")\n afterContentWrapperUse(config)\n return detail\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpTrustBundle(\n config: JmpContentConfig\n): Promise<JmpTrustBundle> {\n const bundle = await getContent<JmpTrustBundle>(config, \"/api/content/trust\")\n markTrustBundleWrappers(bundle)\n afterContentWrapperUse(config)\n return bundle\n}\n\nexport async function getJmpSiteProfile(\n config: JmpContentConfig\n): Promise<JmpSiteProfile> {\n const data = await getContent<{ site: JmpSiteProfile }>(\n config,\n \"/api/content/site\"\n )\n markContentWrapper(\"contact\")\n afterContentWrapperUse(config)\n return data.site\n}\n\nexport async function getJmpRobotsTxt(config: JmpContentConfig): Promise<string> {\n return getContentText(config, \"/api/content/robots\")\n}\n\nexport async function getJmpPopularPages(\n config: JmpContentConfig,\n filters?: {\n prefix?: string\n days?: number\n limit?: number\n }\n): Promise<JmpPopularPagesResult> {\n const params = new URLSearchParams()\n if (filters?.prefix) {\n params.set(\"prefix\", filters.prefix)\n }\n if (typeof filters?.days === \"number\") {\n params.set(\"days\", String(filters.days))\n }\n if (typeof filters?.limit === \"number\") {\n params.set(\"limit\", String(filters.limit))\n }\n const query = params.toString()\n return getContent<JmpPopularPagesResult>(\n config,\n `/api/content/popular-pages${query ? `?${query}` : \"\"}`\n )\n}\n\n/**\n * Tell the JMP dashboard which content wrappers this site wires (blog, faq, trust.*, contact).\n * Uses auto-discovered slots from content API usage unless `contentWrapperMode` is `manual`.\n * Safe to call on every cold start; dedupes by tracking key + wrapper list.\n */\nexport async function registerJmpContentWrappers(\n config: JmpContentConfig\n): Promise<\n { ok: true; wrappers: string[] } | { ok: false; skipped: true }\n> {\n const wrappers = resolveContentWrappersForReport(config)\n if (!wrappers.length) {\n return { ok: false, skipped: true }\n }\n\n const manifest = resolveContentManifestForReport(config)\n const dedupeKey = `${config.trackingKey}:${[...wrappers].sort().join(\",\")}:${stableJmpManifestFingerprint(manifest)}`\n if (hasReportedContentWrappers(dedupeKey)) {\n return { ok: true, wrappers }\n }\n\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const resolvedFetch =\n config.fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n\n if (!resolvedFetch) {\n throw new Error(\n \"JMP content wrappers: fetch is not available; pass fetchImpl in config\"\n )\n }\n\n const url = `${baseUrl}/api/content/capabilities`\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, {\n wrappers,\n manifest,\n })\n }\n\n const body: {\n wrappers: string[]\n sdkVersion: string\n manifest?: JmpContentManifest\n } = {\n wrappers,\n sdkVersion: JMP_ANALYTICS_SDK_VERSION,\n }\n if (manifest) {\n body.manifest = manifest\n }\n\n const res = await resolvedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...jmpContentRequestHeaders(config),\n },\n body: JSON.stringify(body),\n })\n\n const text = await res.text()\n if (!res.ok) {\n let parsed: { error?: string; hint?: string } = {}\n try {\n parsed = JSON.parse(text) as typeof parsed\n } catch {\n parsed = { error: text }\n }\n throw new Error(\n [`JMP content wrappers HTTP ${res.status}`, parsed.error, parsed.hint]\n .filter(Boolean)\n .join(\" — \")\n )\n }\n\n rememberReportedContentWrappers(dedupeKey)\n const data = JSON.parse(text) as { wrappers?: string[] }\n return { ok: true, wrappers: data.wrappers ?? wrappers }\n}\n\nsetContentWrapperSyncHandler(registerJmpContentWrappers)\n","{\n \"robotsUserAgents\": [\n \"GPTBot\",\n \"ChatGPT-User\",\n \"OAI-SearchBot\",\n \"OAI-AdsBot\",\n \"ClaudeBot\",\n \"Claude-User\",\n \"Claude-SearchBot\",\n \"Claude-Web\",\n \"PerplexityBot\",\n \"Perplexity-User\",\n \"Google-Extended\",\n \"GoogleOther\",\n \"GoogleOther-Image\",\n \"GoogleOther-Video\",\n \"Google-CloudVertexBot\",\n \"Meta-ExternalAgent\",\n \"Meta-ExternalFetcher\",\n \"FacebookBot\",\n \"Applebot\",\n \"Applebot-Extended\",\n \"CCBot\",\n \"Bytespider\",\n \"cohere-ai\",\n \"cohere-training-data-crawler\",\n \"YouBot\",\n \"MistralAI-User\",\n \"GrokBot\",\n \"Grok-DeepSearch\",\n \"xAI-Grok\",\n \"xAI-Bot\"\n ],\n \"wafUserAgents\": [\n \"GPTBot\",\n \"ChatGPT-User\",\n \"OAI-SearchBot\",\n \"OAI-AdsBot\",\n \"ClaudeBot\",\n \"Claude-User\",\n \"Claude-SearchBot\",\n \"Claude-Web\",\n \"PerplexityBot\",\n \"Perplexity-User\",\n \"Google-Extended\",\n \"GoogleOther\",\n \"Google-CloudVertexBot\",\n \"Meta-ExternalAgent\",\n \"Meta-ExternalFetcher\",\n \"FacebookBot\",\n \"Applebot-Extended\",\n \"CCBot\",\n \"Bytespider\",\n \"cohere-ai\",\n \"cohere-training-data-crawler\",\n \"YouBot\",\n \"MistralAI-User\",\n \"GrokBot\",\n \"Grok-DeepSearch\",\n \"xAI-Grok\",\n \"xAI-Bot\"\n ]\n}\n","import agentLists from \"../ai-crawler-agents.json\"\n\nexport const AI_CRAWLER_ROBOTS_USER_AGENTS = agentLists.robotsUserAgents\n\n/** UA tokens denied at the Vercel WAF. Omits generic Applebot so Apple Search can still crawl. */\nexport const JMP_AI_CRAWLER_WAF_USER_AGENTS = agentLists.wafUserAgents\n\nexport function buildAiCrawlerRobotsTxt(blockAiCrawlers: boolean): string {\n if (!blockAiCrawlers) {\n return [\n \"# JMP AI crawler policy\",\n \"# AI crawler blocking is disabled for this website.\",\n \"\",\n ].join(\"\\n\")\n }\n\n return [\n \"# JMP AI crawler policy\",\n \"# Blocks known AI training, answer, and fetch bots that honor robots.txt.\",\n ...AI_CRAWLER_ROBOTS_USER_AGENTS.flatMap((agent) => [\n `User-agent: ${agent}`,\n \"Disallow: /\",\n \"\",\n ]),\n ].join(\"\\n\")\n}\n\nexport function jmpAiCrawlerWafUserAgentPattern(): string {\n return JMP_AI_CRAWLER_WAF_USER_AGENTS.map(escapeRegExp).join(\"|\")\n}\n\n/** `vercel.json` mitigate route. Safe for Googlebot / generic Applebot. */\nexport function jmpAiCrawlerVercelWafRoute(): {\n src: string\n has: Array<{ type: \"header\"; key: string; value: string }>\n mitigate: { action: \"deny\" }\n} {\n return {\n src: \"/(.*)\",\n has: [\n {\n type: \"header\",\n key: \"user-agent\",\n value: `(?i).*(${jmpAiCrawlerWafUserAgentPattern()}).*`,\n },\n ],\n mitigate: { action: \"deny\" },\n }\n}\n\nexport function mergeJmpRobotsTxt(\n jmpBody: string,\n options: {\n siteUrl: string\n privatePathPrefixes?: readonly string[]\n /** When true, always include AI Disallow rules even if JMP left blocking off. */\n ensureAiCrawlerDisallows?: boolean\n },\n): string {\n const trimmed = jmpBody.trim()\n const sitemapLine = `Sitemap: ${options.siteUrl.replace(/\\/$/, \"\")}/sitemap.xml`\n const hasSitemap = /(?:^|\\n)\\s*Sitemap:/i.test(trimmed)\n const prefixes = options.privatePathPrefixes ?? []\n const missingDisallows = prefixes.filter(\n (prefix) => !trimmed.includes(`Disallow: ${prefix}`),\n )\n\n const parts = [trimmed]\n if (\n options.ensureAiCrawlerDisallows &&\n !/User-agent:\\s*GPTBot/i.test(trimmed)\n ) {\n parts.unshift(buildAiCrawlerRobotsTxt(true).trim())\n }\n if (missingDisallows.length > 0) {\n const lines = prefixes.map((prefix) => `Disallow: ${prefix}`)\n parts.push(`User-agent: *\\n${lines.join(\"\\n\")}`)\n }\n if (!hasSitemap) {\n parts.push(sitemapLine)\n }\n\n return `${parts.join(\"\\n\\n\")}\\n`\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n","import {\n getJmpBlogPost,\n getJmpBlogPosts,\n getJmpFaqs,\n getJmpLegalDocument,\n getJmpLegalDocuments,\n getJmpLandingPageDetail,\n getJmpLandingPages,\n getJmpLandingPageSitemap,\n getJmpPopularPages,\n getJmpRobotsTxt,\n getJmpSiteProfile,\n getJmpTrustBundle,\n registerJmpContentWrappers,\n} from \"./api\"\nimport type { JmpContentConfig } from \"../types\"\n\nexport function createJmpContentClient(config: JmpContentConfig) {\n return {\n getBlogPosts: (filters?: { locale?: string }) => getJmpBlogPosts(config, filters),\n getBlogPost: (slug: string, locale?: string) => getJmpBlogPost(config, slug, locale),\n getFaqs: (filters?: { locale?: string }) => getJmpFaqs(config, filters),\n getLegalDocument: (slug: string) => getJmpLegalDocument(config, slug),\n getLegalDocuments: () => getJmpLegalDocuments(config),\n getLandingPages: (filters?: Parameters<typeof getJmpLandingPages>[1]) =>\n getJmpLandingPages(config, filters),\n getLandingPageDetail: (\n kind: Parameters<typeof getJmpLandingPageDetail>[1],\n slug: string,\n locale?: string\n ) => getJmpLandingPageDetail(config, kind, slug, locale),\n getLandingPageSitemap: () => getJmpLandingPageSitemap(config),\n getTrustBundle: () => getJmpTrustBundle(config),\n getSiteProfile: () => getJmpSiteProfile(config),\n getRobotsTxt: () => getJmpRobotsTxt(config),\n getPopularPages: (filters?: Parameters<typeof getJmpPopularPages>[1]) =>\n getJmpPopularPages(config, filters),\n registerContentWrappers: () => registerJmpContentWrappers(config),\n }\n}\n\nexport type JmpContentClient = ReturnType<typeof createJmpContentClient>\n","import {\n createJmpAnalytics,\n type JmpAnalytics,\n} from \"../tracker/create-jmp-analytics\"\nimport { DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS } from \"../constants\"\nimport { readJmpPublicEnvFromProcess } from \"../env-public\"\nimport { getJmpSiteDefinition } from \"../site-config\"\nimport type { JmpAnalyticsConfig, JmpContentConfig } from \"../types\"\nimport { createJmpContentClient, type JmpContentClient } from \"../content/client\"\n\n/**\n * Browser / client bundle: reads `NEXT_PUBLIC_*` or Astro `PUBLIC_*` vars.\n * Use for `createJmpAnalytics` on the client. Returns `null` if incomplete.\n */\nexport function getJmpBrowserAnalyticsConfigFromEnv(\n overrides?: Partial<JmpAnalyticsConfig>\n): JmpAnalyticsConfig | null {\n const pub = readJmpPublicEnvFromProcess()\n const site = getJmpSiteDefinition()\n const baseUrl =\n overrides?.baseUrl ?? pub.analyticsUrl ?? site?.analyticsPortalUrl\n const trackingKey = overrides?.trackingKey ?? pub.trackingKey\n if (!baseUrl || !trackingKey) return null\n return {\n baseUrl,\n trackingKey,\n pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,\n ...overrides,\n requireConsent: overrides?.requireConsent ?? pub.requireConsent,\n autoTrackContactLinks:\n overrides?.autoTrackContactLinks ?? pub.autoContactLinks,\n }\n}\n\n/**\n * Server / Node (SSR, Route Handlers, `getStaticProps`, etc.):\n * Same **`NEXT_PUBLIC_*`** vars as the browser (`NEXT_PUBLIC_JMP_ANALYTICS_URL` +\n * `NEXT_PUBLIC_JMP_TRACKING_KEY`). Next.js injects these on the server for RSC/fetches.\n * Returns `null` if incomplete.\n */\nexport function getJmpServerContentConfigFromEnv(\n overrides?: Partial<JmpContentConfig>\n): JmpContentConfig | null {\n const pub = readJmpPublicEnvFromProcess()\n const baseUrl = overrides?.baseUrl ?? pub.analyticsUrl\n const trackingKey = overrides?.trackingKey ?? pub.trackingKey\n if (!baseUrl || !trackingKey) return null\n return { baseUrl, trackingKey, ...overrides }\n}\n\nexport function isJmpBrowserAnalyticsEnvConfigured(): boolean {\n const pub = readJmpPublicEnvFromProcess()\n return Boolean(pub.analyticsUrl && pub.trackingKey)\n}\n\nexport function isJmpServerContentEnvConfigured(): boolean {\n return isJmpBrowserAnalyticsEnvConfigured()\n}\n\nlet jmpAnalyticsBrowserSingleton: JmpAnalytics | null = null\n\n/**\n * One `JmpAnalytics` instance per browser tab (module singleton). Safe for page views and events.\n * Returns `null` on the server or when public env vars are missing.\n */\nexport function getOrCreateJmpAnalyticsFromBrowserEnv(\n overrides?: Partial<JmpAnalyticsConfig>\n): JmpAnalytics | null {\n if (typeof window === \"undefined\") return null\n if (jmpAnalyticsBrowserSingleton) return jmpAnalyticsBrowserSingleton\n const config = getJmpBrowserAnalyticsConfigFromEnv(overrides)\n if (!config) return null\n jmpAnalyticsBrowserSingleton = createJmpAnalytics(config)\n return jmpAnalyticsBrowserSingleton\n}\n\n/**\n * `createJmpContentClient` using server env resolution. Returns `null` if env is incomplete.\n */\nexport function createJmpContentClientFromServerEnv(\n overrides?: Partial<JmpContentConfig>\n): JmpContentClient | null {\n const config = getJmpServerContentConfigFromEnv(overrides)\n if (!config) return null\n return createJmpContentClient(config)\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/landing-capture.ts","../src/contact-link-classifier.ts","../package.json","../src/constants.ts","../src/consent.ts","../src/tracker/page-view-dedupe.ts","../src/http.ts","../src/tracker/helpers.ts","../src/tracker/create-jmp-analytics.ts","../src/env-public.ts","../src/site-config.ts","../src/landing-pages/utils.ts","../src/request-origin.ts","../src/server/page-view.ts","../src/content/manifest.ts","../src/content/fetch.ts","../src/content/wrapper-discovery.ts","../src/content/api.ts","../ai-crawler-agents.json","../src/ai-crawlers.ts","../src/content/client.ts","../src/env/browser.ts"],"sourcesContent":["export { buildLandingCaptureInlineScript } from \"./landing-capture\"\nexport {\n classifyContactHref,\n BOOKING_LINK_HOSTS,\n} from \"./contact-link-classifier\"\nexport type {\n ContactLinkChannel,\n ClassifiedContactLink,\n} from \"./contact-link-classifier\"\n\nexport {\n JMP_ANALYTICS_SDK_VERSION,\n JMP_TRACKING_CONSENT_STORAGE_KEY,\n DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,\n JMP_CONTENT_CACHE_TAG,\n JMP_CONTENT_REVALIDATE_SECONDS,\n} from \"./constants\"\n\nexport {\n isJmpTrackingConsentGranted,\n subscribeJmpTrackingConsent,\n setJmpTrackingConsent,\n} from \"./consent\"\n\nexport type {\n JmpEventType,\n JmpAnalyticsConfig,\n JmpContentConfig,\n JmpContentWrapper,\n JmpContentWrapperReportMode,\n JmpBlogPost,\n JmpBlogPostDetail,\n JmpFaqItem,\n JmpFaqItemDetail,\n JmpLegalDocument,\n JmpPopularPage,\n JmpPopularPagesResult,\n JmpContentLocaleAlternate,\n JmpLandingPage,\n JmpLandingPageDetail,\n JmpLandingPageKind,\n JmpLandingPageSitemapEntry,\n JmpWebsiteLocation,\n JmpWebsiteLocationDetail,\n JmpTrustSummary,\n JmpTestimonial,\n JmpTrustStat,\n JmpPartnerLogo,\n JmpCredential,\n JmpTrustBundle,\n JmpSiteProfile,\n TrackPageViewOptions,\n TrackLeadOptions,\n LeadMetadataValue,\n LeadMetadata,\n JmpServerRequestLike,\n TrackServerPageViewOptions,\n} from \"./types\"\n\nexport { createJmpAnalytics, type JmpAnalytics } from \"./tracker/create-jmp-analytics\"\nexport { trackJmpServerPageView } from \"./server/page-view\"\nexport {\n normalizeJmpContentManifest,\n stableJmpManifestFingerprint,\n type JmpContentManifest,\n type JmpContentRouteManifest,\n type JmpTrustBlockManifest,\n type JmpContactExtraManifest,\n type JmpTrustSection,\n} from \"./content/manifest\"\n\nexport {\n getJmpBlogPosts,\n getJmpBlogPost,\n getJmpBlogPostDetail,\n getJmpFaqs,\n getJmpFaqDetail,\n getJmpLegalDocument,\n getJmpLegalDocuments,\n getJmpLandingPages,\n getJmpLandingPageDetail,\n getJmpLandingPageSitemap,\n getJmpLocations,\n getJmpLocationDetail,\n getJmpTrustBundle,\n getJmpSiteProfile,\n getJmpRobotsTxt,\n registerJmpContentWrappers,\n getJmpPopularPages,\n getDiscoveredContentWrappers,\n inferTrustWrapperSlots,\n markContentWrapper,\n resetContentWrapperDiscoveryForTests,\n} from \"./content/api\"\nexport {\n AI_CRAWLER_ROBOTS_USER_AGENTS,\n JMP_AI_CRAWLER_WAF_USER_AGENTS,\n buildAiCrawlerRobotsTxt,\n jmpAiCrawlerVercelWafRoute,\n jmpAiCrawlerWafUserAgentPattern,\n mergeJmpRobotsTxt,\n} from \"./ai-crawlers\"\nexport { createJmpContentClient, type JmpContentClient } from \"./content/client\"\nexport {\n getJmpBrowserAnalyticsConfigFromEnv,\n getJmpServerContentConfigFromEnv,\n isJmpBrowserAnalyticsEnvConfigured,\n isJmpServerContentEnvConfigured,\n getOrCreateJmpAnalyticsFromBrowserEnv,\n createJmpContentClientFromServerEnv,\n} from \"./env/browser\"\n\nexport { readJmpPublicEnvFromProcess } from \"./env-public\"\nexport type { JmpPublicEnv } from \"./env-public\"\n\nexport {\n defineJmpSite,\n getJmpSiteDefinition,\n getJmpContentConfig,\n type JmpSiteDefinition,\n type JmpSiteContactFallback,\n} from \"./site-config\"\n","/** First-party landing attribution captured before React / useEffect (sessionStorage). */\n\nexport const JMP_SESSION_ID_KEY = \"jmp_analytics_sid\"\nexport const JMP_LANDING_REFERER_KEY = \"jmp_analytics_landing_referer\"\n/** Cross-subdomain landing referrer (www ↔ apex share sessionStorage origins). */\nexport const JMP_LANDING_REFERER_COOKIE = \"jmp_lr\"\nexport const JMP_UTM_SESSION_KEY = \"jmp_analytics_utm\"\n\nconst LANDING_REFERER_COOKIE_MAX_AGE_SEC = 30 * 60\n\nexport const JMP_UTM_PARAM_KEYS = [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_content\",\n \"utm_term\",\n] as const\n\nfunction refererHostFromUrl(referer: string): string | null {\n const trimmed = referer.trim()\n try {\n return new URL(trimmed).hostname.replace(/^www\\./i, \"\").toLowerCase()\n } catch {\n try {\n return new URL(`https://${trimmed}`).hostname\n .replace(/^www\\./i, \"\")\n .toLowerCase()\n } catch {\n return null\n }\n }\n}\n\nexport function isExternalReferrerUrl(\n referer: string,\n siteHostname: string\n): boolean {\n const refHost = refererHostFromUrl(referer)\n if (!refHost) {\n return false\n }\n const site = siteHostname.replace(/^www\\./i, \"\").toLowerCase()\n return refHost !== site && !refHost.endsWith(`.${site}`)\n}\n\n/** Apex hostname used for `Domain=.example.com` cookies (www + apex). */\nexport function registrableSiteDomain(siteHostname: string): string | null {\n const site = siteHostname.replace(/^www\\./i, \"\").toLowerCase()\n if (!site || site === \"localhost\" || site.endsWith(\".local\")) {\n return null\n }\n if (!site.includes(\".\")) {\n return null\n }\n return site\n}\n\nexport function readLandingRefererCookie(siteHostname: string): string | null {\n if (typeof document === \"undefined\") {\n return null\n }\n\n const apex = registrableSiteDomain(siteHostname)\n if (!apex) {\n return null\n }\n\n const prefix = `${JMP_LANDING_REFERER_COOKIE}=`\n for (const part of document.cookie.split(\";\")) {\n const trimmed = part.trim()\n if (!trimmed.startsWith(prefix)) {\n continue\n }\n try {\n const value = decodeURIComponent(trimmed.slice(prefix.length)).trim()\n return value.length > 0 ? value : null\n } catch {\n return null\n }\n }\n\n return null\n}\n\nexport function writeLandingRefererCookie(\n referer: string,\n siteHostname: string\n): void {\n if (typeof document === \"undefined\") {\n return\n }\n\n const apex = registrableSiteDomain(siteHostname)\n if (!apex) {\n return\n }\n\n const value = encodeURIComponent(referer.trim().slice(0, 2048))\n const secure =\n typeof window !== \"undefined\" && window.location.protocol === \"https:\"\n ? \"; Secure\"\n : \"\"\n\n document.cookie = `${JMP_LANDING_REFERER_COOKIE}=${value}; Domain=.${apex}; Path=/; Max-Age=${LANDING_REFERER_COOKIE_MAX_AGE_SEC}; SameSite=Lax${secure}`\n}\n\nexport function captureLandingAttribution(siteHostname: string): {\n landingReferer: string | null\n utm: Record<string, string>\n} {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n return { landingReferer: null, utm: {} }\n }\n\n let landingReferer: string | null = null\n let utm: Record<string, string> = {}\n\n try {\n const storedReferer =\n sessionStorage.getItem(JMP_LANDING_REFERER_KEY)?.trim() || null\n const cookieReferer = readLandingRefererCookie(siteHostname)\n const preservedReferer = storedReferer || cookieReferer\n const currentReferer = document.referrer?.trim() || null\n\n if (\n currentReferer &&\n isExternalReferrerUrl(currentReferer, siteHostname)\n ) {\n sessionStorage.setItem(JMP_LANDING_REFERER_KEY, currentReferer)\n writeLandingRefererCookie(currentReferer, siteHostname)\n landingReferer = currentReferer\n } else if (preservedReferer) {\n landingReferer = preservedReferer\n if (!storedReferer) {\n sessionStorage.setItem(JMP_LANDING_REFERER_KEY, preservedReferer)\n }\n }\n\n const params = new URLSearchParams(window.location.search)\n const rawUtm = sessionStorage.getItem(JMP_UTM_SESSION_KEY)\n if (rawUtm) {\n const parsed = JSON.parse(rawUtm) as unknown\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n utm = parsed as Record<string, string>\n }\n }\n\n let updated = false\n for (const key of JMP_UTM_PARAM_KEYS) {\n const value = params.get(key)?.trim()\n if (value) {\n utm[key] = value\n updated = true\n }\n }\n\n if (updated) {\n sessionStorage.setItem(JMP_UTM_SESSION_KEY, JSON.stringify(utm))\n }\n } catch {\n }\n\n return { landingReferer, utm }\n}\n\nexport function getOrCreateSessionIdFromStorage(): string | undefined {\n if (typeof window === \"undefined\" || !globalThis.crypto?.randomUUID) {\n return undefined\n }\n try {\n let id = sessionStorage.getItem(JMP_SESSION_ID_KEY)\n if (!id) {\n id = crypto.randomUUID()\n sessionStorage.setItem(JMP_SESSION_ID_KEY, id)\n }\n return id\n } catch {\n return undefined\n }\n}\n\n/** Inline script for Next.js `beforeInteractive` — capture referrer/UTM only (no network). */\nexport function buildLandingCaptureInlineScript(): string {\n const cookieMaxAge = String(LANDING_REFERER_COOKIE_MAX_AGE_SEC)\n\n return `(function(){try{var h=location.hostname;var ref=document.referrer||'';function rh(u){try{return new URL(u).hostname.replace(/^www\\\\./i,'').toLowerCase()}catch(e){try{return new URL('https://'+u).hostname.replace(/^www\\\\./i,'').toLowerCase()}catch(e2){return null}}}function ext(r){var x=rh(r);if(!x)return false;var s=h.replace(/^www\\\\./i,'').toLowerCase();return x!==s&&x.slice(-('.'+s).length)!==('.'+s)}function apexDom(hn){var s=hn.replace(/^www\\\\./i,'').toLowerCase();if(!s||s==='localhost'||/\\\\.local$/i.test(s)||s.indexOf('.')<0)return null;return s}function readCk(hn){var apex=apexDom(hn);if(!apex)return '';var pre='${JMP_LANDING_REFERER_COOKIE}=';var parts=document.cookie.split(';');for(var i=0;i<parts.length;i++){var t=parts[i].trim();if(t.indexOf(pre)===0){try{return decodeURIComponent(t.slice(pre.length)).trim()}catch(e){return ''}}}return ''}function writeCk(r,hn){var apex=apexDom(hn);if(!apex)return;var sec=location.protocol==='https:'?'; Secure':'';document.cookie='${JMP_LANDING_REFERER_COOKIE}='+encodeURIComponent(r.slice(0,2048))+'; Domain=.'+apex+'; Path=/; Max-Age=${cookieMaxAge}; SameSite=Lax'+sec}var stored=sessionStorage.getItem('${JMP_LANDING_REFERER_KEY}')||'';var ck=readCk(h);var preserved=stored||ck;var lr='';if(ref&&ext(ref)){sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',ref);writeCk(ref,h);lr=ref}else{lr=preserved||'';if(lr&&!stored)sessionStorage.setItem('${JMP_LANDING_REFERER_KEY}',lr)}var sid=sessionStorage.getItem('${JMP_SESSION_ID_KEY}');if(!sid&&crypto&&crypto.randomUUID){sid=crypto.randomUUID();sessionStorage.setItem('${JMP_SESSION_ID_KEY}',sid)}try{var sp=new URLSearchParams(location.search);var utm={};var updated=false;['utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach(function(n){var v=sp.get(n);if(v){utm[n]=v;updated=true}});if(updated)sessionStorage.setItem('${JMP_UTM_SESSION_KEY}',JSON.stringify(utm))}catch(e){}}catch(e){}})();`\n}\n","/**\n * Classify outbound contact links for auto-tracking.\n *\n * Keep channel set in sync with `lib/ingest/contact-click.ts` on the dashboard side.\n *\n * Channels detected from `href` alone (no widget / iframe detection):\n *\n * - `call` — `tel:` (delegates to existing `trackCallClick`)\n * - `email` — `mailto:` (delegates to existing `trackEmailClick`)\n * - `sms` — `sms:` / `smsto:`\n * - `whatsapp` — `wa.me`, `api.whatsapp.com`, `whatsapp.com/send`\n * - `maps` — Google Maps, Apple Maps, `maps.app.goo.gl`, `geo:`\n * - `booking` — fixed allowlist of common scheduling hosts (see {@link BOOKING_LINK_HOSTS})\n *\n * `linkHost` returned in `contact_click` results is the hostname only — never the full URL\n * (avoids leaking phone numbers in `tel:`/`sms:` URLs and PII-laden booking query strings).\n */\n\nexport type ContactLinkChannel = \"sms\" | \"whatsapp\" | \"maps\" | \"booking\"\n\nexport type ClassifiedContactLink =\n | { kind: \"call\" }\n | { kind: \"email\" }\n | { kind: \"contact_click\"; channel: ContactLinkChannel; linkHost: string | null }\n\n/** v1 booking hosts (~80%+ SMB coverage). Add hosts here when a client uses something rare. */\nexport const BOOKING_LINK_HOSTS = [\n \"calendly.com\",\n \"cal.com\",\n \"acuityscheduling.com\",\n \"calendar.google.com\",\n \"calendar.app.google\",\n \"bookings.microsoft.com\",\n \"outlook.office.com\",\n \"outlook.office365.com\",\n \"book.ms\",\n \"setmore.com\",\n \"simplybook.me\",\n \"oncehub.com\",\n \"scheduleonce.com\",\n \"youcanbook.me\",\n \"savvycal.com\",\n \"tidycal.com\",\n \"zohobookings.com\",\n \"square.site\",\n \"squareup.com\",\n \"meetings.hubspot.com\",\n \"jobber.com\",\n \"housecallpro.com\",\n \"servicetitan.com\",\n \"thryv.com\",\n \"honeybook.com\",\n \"dubsado.com\",\n \"fresha.com\",\n \"booksy.com\",\n \"vagaro.com\",\n \"mindbodyonline.com\",\n \"mindbody.io\",\n \"janeapp.com\",\n \"cliniko.com\",\n \"practicebetter.io\",\n] as const\n\nconst WHATSAPP_HOSTS = [\"wa.me\", \"api.whatsapp.com\", \"whatsapp.com\"] as const\n\nexport function hostnameMatches(host: string, pattern: string): boolean {\n const h = host.toLowerCase()\n const p = pattern.toLowerCase()\n return h === p || h.endsWith(`.${p}`)\n}\n\nfunction isMapsHost(host: string, pathname: string): boolean {\n if (hostnameMatches(host, \"maps.apple.com\")) {\n return true\n }\n if (hostnameMatches(host, \"maps.app.goo.gl\")) {\n return true\n }\n if (hostnameMatches(host, \"google.com\") || hostnameMatches(host, \"google.co\")) {\n return pathname === \"/maps\" || pathname.startsWith(\"/maps/\") || pathname.startsWith(\"/local\")\n }\n return false\n}\n\nfunction isWhatsAppHost(host: string, pathname: string): boolean {\n for (const pattern of WHATSAPP_HOSTS) {\n if (!hostnameMatches(host, pattern)) {\n continue\n }\n if (pattern === \"whatsapp.com\") {\n return pathname.startsWith(\"/send\")\n }\n return true\n }\n return false\n}\n\nfunction isBookingHost(host: string): boolean {\n for (const pattern of BOOKING_LINK_HOSTS) {\n if (hostnameMatches(host, pattern)) {\n return true\n }\n }\n return false\n}\n\nexport function classifyContactHref(href: string): ClassifiedContactLink | null {\n const raw = href.trim()\n if (!raw || raw.startsWith(\"#\") || raw.startsWith(\"javascript:\")) {\n return null\n }\n\n const lower = raw.toLowerCase()\n\n if (lower.startsWith(\"tel:\")) {\n return { kind: \"call\" }\n }\n if (lower.startsWith(\"mailto:\")) {\n return { kind: \"email\" }\n }\n if (lower.startsWith(\"sms:\") || lower.startsWith(\"smsto:\")) {\n return { kind: \"contact_click\", channel: \"sms\", linkHost: null }\n }\n if (lower.startsWith(\"geo:\")) {\n return { kind: \"contact_click\", channel: \"maps\", linkHost: null }\n }\n\n // Skip anchors/relative paths that aren't a known contact scheme.\n if (raw.startsWith(\"/\") || raw.startsWith(\"?\")) {\n return null\n }\n\n let url: URL\n try {\n url = new URL(raw)\n } catch {\n return null\n }\n\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return null\n }\n\n const host = url.hostname.toLowerCase()\n const pathname = url.pathname.toLowerCase()\n\n if (isWhatsAppHost(host, pathname)) {\n return { kind: \"contact_click\", channel: \"whatsapp\", linkHost: host }\n }\n if (isMapsHost(host, pathname)) {\n return { kind: \"contact_click\", channel: \"maps\", linkHost: host }\n }\n if (isBookingHost(host)) {\n return { kind: \"contact_click\", channel: \"booking\", linkHost: host }\n }\n\n return null\n}\n\n/** Phone number from a `tel:` href (for CRM logs — not sent on `contact_click`). */\nexport function extractTelTarget(href: string): string | null {\n const raw = href.trim()\n if (!raw.toLowerCase().startsWith(\"tel:\")) {\n return null\n }\n const target = decodeURIComponent(\n raw.slice(4).split(\"?\")[0]?.split(\";\")[0] ?? \"\"\n ).trim()\n return target || null\n}\n\n/** Email address from a `mailto:` href (for CRM logs). */\nexport function extractMailtoTarget(href: string): string | null {\n const raw = href.trim()\n if (!raw.toLowerCase().startsWith(\"mailto:\")) {\n return null\n }\n const target = decodeURIComponent(\n raw.slice(7).split(\"?\")[0]?.split(\",\")[0] ?? \"\"\n ).trim()\n return target || null\n}\n","{\n \"name\": \"@jmp-technologies/analytics\",\n \"version\": \"0.1.41\",\n \"description\": \"JMP Analytics tracking plus blog, FAQ, trust content, and site contact profile for client websites\",\n \"license\": \"UNLICENSED\",\n \"keywords\": [\n \"jmp\",\n \"analytics\",\n \"tracking\",\n \"jmp-analytics\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/jmp-technologies/jmp-dashboard.git\",\n \"directory\": \"packages/jmp-technologies-analytics\"\n },\n \"homepage\": \"https://github.com/jmp-technologies/jmp-dashboard/tree/main/packages/jmp-technologies-analytics#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/jmp-technologies/jmp-dashboard/issues\"\n },\n \"type\": \"module\",\n \"bin\": {\n \"jmp-init\": \"./bin/jmp-init.mjs\"\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./react\": {\n \"types\": \"./dist/react.d.ts\",\n \"import\": \"./dist/react.js\",\n \"require\": \"./dist/react.cjs\"\n },\n \"./next\": {\n \"types\": \"./dist/next.d.ts\",\n \"import\": \"./dist/next.js\",\n \"require\": \"./dist/next.cjs\"\n },\n \"./next/site-root-server\": {\n \"types\": \"./dist/next/site-root-server.d.ts\",\n \"import\": \"./dist/next/site-root-server.js\",\n \"require\": \"./dist/next/site-root-server.cjs\"\n },\n \"./next/landing-capture-script-server\": {\n \"types\": \"./dist/next/landing-capture-script-server.d.ts\",\n \"import\": \"./dist/next/landing-capture-script-server.js\",\n \"require\": \"./dist/next/landing-capture-script-server.cjs\"\n },\n \"./next/middleware\": {\n \"types\": \"./dist/next/middleware.d.ts\",\n \"import\": \"./dist/next/middleware.js\",\n \"require\": \"./dist/next/middleware.cjs\"\n },\n \"./next/instrumentation\": {\n \"types\": \"./dist/next/instrumentation.d.ts\",\n \"import\": \"./dist/next/instrumentation.js\",\n \"require\": \"./dist/next/instrumentation.cjs\"\n },\n \"./next/content\": {\n \"types\": \"./dist/next/content.d.ts\",\n \"import\": \"./dist/next/content.js\",\n \"require\": \"./dist/next/content.cjs\"\n },\n \"./next/landing-pages\": {\n \"types\": \"./dist/next/landing-pages.d.ts\",\n \"import\": \"./dist/next/landing-pages.js\",\n \"require\": \"./dist/next/landing-pages.cjs\"\n },\n \"./next/locations\": {\n \"types\": \"./dist/next/locations.d.ts\",\n \"import\": \"./dist/next/locations.js\",\n \"require\": \"./dist/next/locations.cjs\"\n },\n \"./astro/content\": {\n \"types\": \"./dist/astro/content.d.ts\",\n \"import\": \"./dist/astro/content.js\",\n \"require\": \"./dist/astro/content.cjs\"\n },\n \"./astro/client\": {\n \"types\": \"./dist/astro/client.d.ts\",\n \"import\": \"./dist/astro/client.js\",\n \"require\": \"./dist/astro/client.cjs\"\n },\n \"./astro/middleware\": {\n \"types\": \"./dist/astro/middleware.d.ts\",\n \"import\": \"./dist/astro/middleware.js\",\n \"require\": \"./dist/astro/middleware.cjs\"\n },\n \"./astro/register\": {\n \"types\": \"./dist/astro/register.d.ts\",\n \"import\": \"./dist/astro/register.js\",\n \"require\": \"./dist/astro/register.cjs\"\n },\n \"./astro/integration\": {\n \"types\": \"./dist/astro/integration.d.ts\",\n \"import\": \"./dist/astro/integration.js\",\n \"require\": \"./dist/astro/integration.cjs\"\n }\n },\n \"files\": [\n \"dist\",\n \"bin\",\n \"docs\",\n \"ai-crawler-agents.json\",\n \"README.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"tsup src/index.ts src/react.tsx src/next.tsx src/next/google-tag.tsx src/next/landing-capture-script-server.tsx src/next/site-root-server.tsx src/next/middleware.ts src/next/instrumentation.ts src/next/content.ts src/next/landing-pages.tsx src/next/locations.tsx src/astro/content.ts src/astro/client.ts src/astro/middleware.ts src/astro/register.ts src/astro/integration.ts --format esm,cjs --dts --clean --sourcemap --external react --external react-dom --external next\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"peerDependencies\": {\n \"next\": \">=14\",\n \"react\": \">=18\",\n \"react-dom\": \">=18\"\n },\n \"peerDependenciesMeta\": {\n \"react\": {\n \"optional\": true\n },\n \"react-dom\": {\n \"optional\": true\n },\n \"next\": {\n \"optional\": true\n },\n \"astro\": {\n \"optional\": true\n }\n },\n \"devDependencies\": {\n \"@types/react\": \"^19\",\n \"@types/react-dom\": \"^19\",\n \"next\": \"^16.2.3\",\n \"react\": \"^19.2.0\",\n \"react-dom\": \"^19.2.0\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\"\n },\n \"dependencies\": {}\n}\n","import { version as packageVersion } from \"../package.json\"\n\n/** Published package version — sent with capabilities for admin readiness. */\nexport const JMP_ANALYTICS_SDK_VERSION = packageVersion\n\n/** `localStorage` key when {@link JmpAnalyticsConfig.requireConsent} is enabled. */\nexport const JMP_TRACKING_CONSENT_STORAGE_KEY = \"jmp_analytics_consent_v1\"\n\n/** Default `pageViewDedupeMs` when resolving browser config from env (Strict Mode / SPA). */\nexport const DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS = 2500\n\n/** Marks links tracked explicitly — skips delegated `autoTrackContactLinks` handler. */\nexport const JMP_TRACKED_LINK_ATTR = \"data-jmp-tracked\"\n\n/** Next.js `fetch` / Vercel CDN tag for JMP public content. Client webhooks revalidate this tag. */\nexport const JMP_CONTENT_CACHE_TAG = \"jmp-content\"\n\n/** Fallback TTL for tagged JMP content fetches when on-demand revalidation does not run. */\nexport const JMP_CONTENT_REVALIDATE_SECONDS = 3600\n","import { captureLandingAttribution } from \"./landing-capture\"\nimport { JMP_TRACKING_CONSENT_STORAGE_KEY } from \"./constants\"\n\nlet moduleTrackingConsentGranted = true\nconst trackingConsentListeners = new Set<() => void>()\n\nfunction readStoredTrackingConsent(): boolean {\n if (typeof window === \"undefined\") {\n return false\n }\n try {\n return (\n localStorage.getItem(JMP_TRACKING_CONSENT_STORAGE_KEY) === \"granted\"\n )\n } catch {\n return false\n }\n}\n\n/** Initialize consent gate when creating a tracker (browser only). */\nexport function initJmpTrackingConsent(requireConsent: boolean | undefined): void {\n moduleTrackingConsentGranted = requireConsent\n ? readStoredTrackingConsent()\n : true\n}\n\n/** Whether analytics events may be sent (after CMP / cookie banner). */\nexport function isJmpTrackingConsentGranted(): boolean {\n return moduleTrackingConsentGranted\n}\n\n/** Subscribe to consent changes (for React `useSyncExternalStore`). */\nexport function subscribeJmpTrackingConsent(listener: () => void): () => void {\n trackingConsentListeners.add(listener)\n return () => {\n trackingConsentListeners.delete(listener)\n }\n}\n\n/**\n * Grant or deny analytics. Persists in `localStorage` when `requireConsent` is used.\n * Call from your cookie banner before tracking runs.\n */\nexport function setJmpTrackingConsent(granted: boolean): void {\n if (moduleTrackingConsentGranted === granted) {\n return\n }\n moduleTrackingConsentGranted = granted\n if (typeof window !== \"undefined\") {\n try {\n localStorage.setItem(\n JMP_TRACKING_CONSENT_STORAGE_KEY,\n granted ? \"granted\" : \"denied\"\n )\n } catch {\n // private mode\n }\n if (granted) {\n captureLandingAttribution(window.location.hostname)\n }\n }\n for (const listener of trackingConsentListeners) {\n listener()\n }\n}\n","export const JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY = \"jmp_analytics_last_pv\"\n\nlet moduleLastPath = \"\"\nlet moduleLastAt = 0\n\n/**\n * Suppress duplicate browser `page_view` within `dedupeMs` (Strict Mode, App Router\n * searchParams resolution, multiple bundles). Uses pathname-only as the dedupe key.\n */\nexport function shouldDedupeBrowserPageView(\n pathname: string,\n dedupeMs: number,\n storage: Pick<Storage, \"getItem\" | \"setItem\"> | null = null,\n): boolean {\n if (dedupeMs <= 0) {\n return false\n }\n\n const now = Date.now()\n if (pathname === moduleLastPath && now - moduleLastAt < dedupeMs) {\n return true\n }\n\n try {\n const raw = storage?.getItem(JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY)\n if (raw) {\n const prev = JSON.parse(raw) as { path: string; at: number }\n if (prev.path === pathname && now - prev.at < dedupeMs) {\n return true\n }\n }\n storage?.setItem(\n JMP_PAGE_VIEW_DEDUPE_STORAGE_KEY,\n JSON.stringify({ path: pathname, at: now }),\n )\n } catch {\n // private mode / disabled storage\n }\n\n moduleLastPath = pathname\n moduleLastAt = now\n return false\n}\n\n/** @internal test helper */\nexport function resetBrowserPageViewDedupeForTests(): void {\n moduleLastPath = \"\"\n moduleLastAt = 0\n}\n","import type { JmpServerRequestLike } from \"./types\"\n\n/** CDN / Next.js often return HTML error pages; API errors are JSON */\nexport function responseLooksLikeHtml(body: string): boolean {\n const s = body.trimStart()\n return (\n s.startsWith(\"<!\") ||\n s.toLowerCase().startsWith(\"<html\") ||\n (s.startsWith(\"<\") && /<html[\\s>]/i.test(s.slice(0, 500)))\n )\n}\n\nexport function normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/$/, \"\")\n}\n\nexport function getHeader(\n headers: JmpServerRequestLike[\"headers\"] | undefined,\n key: string\n): string | null {\n if (!headers) {\n return null\n }\n if (typeof (headers as Pick<Headers, \"get\">).get === \"function\") {\n return (headers as Pick<Headers, \"get\">).get(key)\n }\n const record = headers as Record<string, string | string[] | undefined | null>\n const direct = record[key] ?? record[key.toLowerCase()]\n if (Array.isArray(direct)) {\n return direct[0] ?? null\n }\n return direct ?? null\n}\n\nexport function pathFromRequestUrl(url: string | undefined): string {\n if (!url) {\n return \"/\"\n }\n try {\n const u = new URL(url)\n return `${u.pathname}${u.search}`\n } catch {\n return url.startsWith(\"/\") ? url : \"/\"\n }\n}\n\nexport function resolveFetch(\n fetchImpl: typeof fetch | undefined,\n context: string\n): typeof fetch {\n const resolved =\n fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n if (!resolved) {\n throw new Error(`${context}: fetch is not available; pass fetchImpl in config`)\n }\n return resolved\n}\n\ntype ApiErrorJson = {\n error?: string\n code?: string\n hint?: string\n expectedDomain?: string\n}\n\nexport function formatApiErrorMessage(\n status: number,\n text: string,\n prefix: string\n): string {\n if (responseLooksLikeHtml(text)) {\n return `${prefix} HTTP ${status} — response was HTML (not the JSON API). Check baseUrl points at the JMP Analytics dashboard.`\n }\n let parsed: ApiErrorJson = {}\n try {\n parsed = JSON.parse(text) as ApiErrorJson\n } catch {\n parsed = { error: text }\n }\n const detail = parsed.error ?? text\n return [\n `${prefix} HTTP ${status}`,\n parsed.code ? `[${parsed.code}]` : null,\n detail,\n parsed.hint ? `Hint: ${parsed.hint}` : null,\n parsed.expectedDomain\n ? `Domain in JMP admin: ${parsed.expectedDomain}`\n : null,\n ]\n .filter(Boolean)\n .join(\" — \")\n}\n","import {\n captureLandingAttribution,\n JMP_UTM_PARAM_KEYS,\n} from \"../landing-capture\"\n\nexport function captureAndGetLandingReferer(): string | null {\n if (typeof window === \"undefined\") {\n return null\n }\n return captureLandingAttribution(window.location.hostname).landingReferer\n}\n\nexport function mergeSessionUtms(metadata: Record<string, unknown>) {\n if (typeof window === \"undefined\") {\n return\n }\n const { utm } = captureLandingAttribution(window.location.hostname)\n for (const key of JMP_UTM_PARAM_KEYS) {\n if (metadata[key] === undefined && utm[key]) {\n metadata[key] = utm[key]\n }\n }\n}\n\nexport function splitPathAndSearch(pathInput: string): {\n pathname: string\n search: string\n} {\n const qIndex = pathInput.indexOf(\"?\")\n if (qIndex === -1) {\n return { pathname: pathInput || \"/\", search: \"\" }\n }\n return {\n pathname: pathInput.slice(0, qIndex) || \"/\",\n search: pathInput.slice(qIndex + 1),\n }\n}\n\nexport function inferDevice(): string {\n if (typeof window === \"undefined\") {\n return \"unknown\"\n }\n return window.innerWidth < 768 ? \"mobile\" : \"desktop\"\n}\n","import { DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS } from \"../constants\"\nimport {\n captureLandingAttribution,\n getOrCreateSessionIdFromStorage,\n JMP_UTM_PARAM_KEYS,\n} from \"../landing-capture\"\nimport { shouldDedupeBrowserPageView } from \"./page-view-dedupe\"\nimport { classifyContactHref, extractMailtoTarget, extractTelTarget } from \"../contact-link-classifier\"\nimport type { ContactLinkChannel } from \"../contact-link-classifier\"\nimport {\n initJmpTrackingConsent,\n isJmpTrackingConsentGranted,\n setJmpTrackingConsent,\n} from \"../consent\"\nimport {\n formatApiErrorMessage,\n normalizeBaseUrl,\n resolveFetch,\n} from \"../http\"\nimport type {\n JmpAnalyticsConfig,\n JmpEventType,\n TrackLeadOptions,\n TrackPageViewOptions,\n} from \"../types\"\nimport {\n captureAndGetLandingReferer,\n inferDevice,\n mergeSessionUtms,\n splitPathAndSearch,\n} from \"./helpers\"\n\nexport function createJmpAnalytics(config: JmpAnalyticsConfig) {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const fetchFn = resolveFetch(config.fetchImpl, \"createJmpAnalytics\")\n\n initJmpTrackingConsent(config.requireConsent)\n\n function canSend(): boolean {\n return isJmpTrackingConsentGranted()\n }\n\n async function send(body: Record<string, unknown>) {\n if (!canSend()) {\n return\n }\n\n const url = `${baseUrl}/api/events`\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-JMP-Tracking-Key\": config.trackingKey,\n }\n\n if (body.type === \"page_view\" && typeof window !== \"undefined\") {\n const landingReferer = captureAndGetLandingReferer()\n if (landingReferer) {\n headers[\"X-JMP-Visitor-Referer\"] = landingReferer\n }\n }\n\n const sid = getOrCreateSessionIdFromStorage()\n const payload = { ...body, ...(sid ? { sessionId: sid } : {}) }\n\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, payload)\n }\n\n const res = await fetchFn(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n keepalive: true,\n })\n\n if (!res.ok) {\n const text = await res.text()\n const message = formatApiErrorMessage(res.status, text, \"JMP Analytics\")\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"error response\", { status: res.status, raw: text })\n }\n throw new Error(message)\n }\n }\n\n async function sendLead(body: Record<string, unknown>) {\n if (!canSend()) {\n return\n }\n\n const url = `${baseUrl}/api/leads`\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-JMP-Tracking-Key\": config.trackingKey,\n }\n\n const sid = getOrCreateSessionIdFromStorage()\n const payload = { ...body, ...(sid ? { sessionId: sid } : {}) }\n\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, payload)\n }\n\n const res = await fetchFn(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n keepalive: true,\n })\n\n if (!res.ok) {\n const text = await res.text()\n const message = formatApiErrorMessage(res.status, text, \"JMP Analytics\")\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"error response\", { status: res.status, raw: text })\n }\n throw new Error(message)\n }\n }\n\n function trackPageView(options?: TrackPageViewOptions) {\n if (!canSend()) {\n return Promise.resolve()\n }\n\n const pathFromOptions = options?.path?.trim()\n let pathname = \"/\"\n let search = \"\"\n\n if (pathFromOptions) {\n const split = splitPathAndSearch(pathFromOptions)\n pathname = split.pathname\n search = split.search\n } else if (typeof window !== \"undefined\") {\n pathname = window.location.pathname\n search = window.location.search.replace(/^\\?/, \"\")\n }\n\n if (!search && typeof window !== \"undefined\") {\n search = window.location.search.replace(/^\\?/, \"\")\n }\n\n const path = search ? `${pathname}?${search}` : pathname\n\n const dedupeMs =\n config.pageViewDedupeMs ?? DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS\n const storage =\n typeof window !== \"undefined\" ? window.sessionStorage : null\n if (shouldDedupeBrowserPageView(pathname, dedupeMs, storage)) {\n return Promise.resolve()\n }\n\n const metadata: Record<string, unknown> =\n options?.metadata && typeof options.metadata === \"object\"\n ? { ...options.metadata }\n : {}\n\n if (typeof window !== \"undefined\") {\n metadata.pageHostname = window.location.hostname\n const params = new URLSearchParams(\n search ? `?${search}` : window.location.search\n )\n for (const key of JMP_UTM_PARAM_KEYS) {\n const v = params.get(key)\n if (v && metadata[key] === undefined) {\n metadata[key] = v\n }\n }\n mergeSessionUtms(metadata)\n const landingReferer = captureAndGetLandingReferer()\n if (landingReferer && metadata.referer === undefined) {\n metadata.referer = landingReferer\n }\n }\n\n return send({\n type: \"page_view\",\n path: path || \"/\",\n device: options?.device ?? inferDevice(),\n country: options?.country,\n metadata,\n })\n }\n\n function trackFormSubmit(\n path: string,\n metadata?: Record<string, unknown>\n ) {\n return send({\n type: \"form_submit\",\n path: path || \"/\",\n metadata: metadata ?? {},\n })\n }\n\n function trackCallClick(\n path: string,\n metadata?: Record<string, unknown>\n ) {\n return send({\n type: \"call_click\",\n path: path || \"/\",\n metadata: metadata ?? {},\n })\n }\n\n function trackEmailClick(\n path: string,\n metadata?: Record<string, unknown>\n ) {\n return send({\n type: \"email_click\",\n path: path || \"/\",\n metadata: metadata ?? {},\n })\n }\n\n function trackContactClick(\n path: string,\n options: {\n channel: ContactLinkChannel\n linkHost?: string | null\n metadata?: Record<string, unknown>\n }\n ) {\n const metadata: Record<string, unknown> = {\n ...(options.metadata && typeof options.metadata === \"object\"\n ? options.metadata\n : {}),\n channel: options.channel,\n }\n if (options.linkHost) {\n metadata.linkHost = options.linkHost\n }\n return send({\n type: \"contact_click\",\n path: path || \"/\",\n metadata,\n })\n }\n\n function trackLead(options?: TrackLeadOptions) {\n const path =\n options?.path ??\n (typeof window !== \"undefined\" ? window.location.pathname : \"/\")\n\n const body: Record<string, unknown> = { path: path || \"/\" }\n if (options?.name) body.name = options.name\n if (options?.email) body.email = options.email\n if (options?.phone) body.phone = options.phone\n if (options?.company) body.company = options.company\n if (options?.website) body.website = options.website\n if (options?.subject) body.subject = options.subject\n if (options?.message) body.message = options.message\n if (options?.metadata && typeof options.metadata === \"object\") {\n body.metadata = options.metadata\n }\n if (options?.sessionId) body.sessionId = options.sessionId\n\n return sendLead(body)\n }\n\n function track(\n type: JmpEventType,\n payload: {\n path: string\n metadata?: Record<string, unknown>\n source?: string\n device?: string\n country?: string\n }\n ) {\n if (type === \"page_view\") {\n return trackPageView({\n path: payload.path,\n source: payload.source,\n device: payload.device,\n country: payload.country,\n metadata: payload.metadata,\n })\n }\n if (type === \"form_submit\") {\n return trackFormSubmit(payload.path, payload.metadata)\n }\n if (type === \"call_click\") {\n return trackCallClick(payload.path, payload.metadata)\n }\n if (type === \"email_click\") {\n return trackEmailClick(payload.path, payload.metadata)\n }\n const meta = payload.metadata ?? {}\n const channel = typeof meta.channel === \"string\" ? meta.channel : \"\"\n const linkHost =\n typeof meta.linkHost === \"string\" ? (meta.linkHost as string) : null\n if (\n channel !== \"sms\" &&\n channel !== \"whatsapp\" &&\n channel !== \"maps\" &&\n channel !== \"booking\"\n ) {\n return Promise.resolve()\n }\n return trackContactClick(payload.path, {\n channel: channel as ContactLinkChannel,\n linkHost,\n metadata: meta,\n })\n }\n\n /**\n * Fire `page_view` on browser back/forward and when `history.pushState` /\n * `replaceState` are used (many SPAs). Call once after creating the tracker.\n * Returns an unsubscribe function.\n */\n function subscribeToSpaNavigation(): () => void {\n if (typeof window === \"undefined\") {\n return () => {}\n }\n\n let lastPath = window.location.pathname\n\n const run = () => {\n const path = window.location.pathname\n if (path !== lastPath) {\n lastPath = path\n void trackPageView({ path })\n }\n }\n\n window.addEventListener(\"popstate\", run)\n\n const push = history.pushState.bind(history)\n const replace = history.replaceState.bind(history)\n\n history.pushState = (...args: Parameters<History[\"pushState\"]>) => {\n const r = push(...args)\n queueMicrotask(run)\n return r\n }\n history.replaceState = (...args: Parameters<History[\"replaceState\"]>) => {\n const r = replace(...args)\n queueMicrotask(run)\n return r\n }\n\n return () => {\n window.removeEventListener(\"popstate\", run)\n history.pushState = push\n history.replaceState = replace\n }\n }\n\n let lastContactClickKey = \"\"\n let lastContactClickAt = 0\n\n /**\n * Capture-phase `click` listener that classifies outgoing links and records\n * the corresponding contact event. Returns an unsubscribe function. Safe to\n * call only in the browser; no-op on the server.\n */\n function subscribeContactLinkAutoTrack(): () => void {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return () => {}\n }\n\n const handler = (event: MouseEvent) => {\n if (!canSend()) {\n return\n }\n const target = event.target\n if (!(target instanceof Element)) {\n return\n }\n const anchor = target.closest(\"a[href]\")\n if (!(anchor instanceof HTMLAnchorElement)) {\n return\n }\n if (\n anchor.closest(\"[data-jmp-no-track]\") ||\n anchor.closest(\"[data-jmp-tracked]\")\n ) {\n return\n }\n\n const href = anchor.getAttribute(\"href\") ?? \"\"\n const classified = classifyContactHref(href)\n if (!classified) {\n return\n }\n\n const path = window.location.pathname\n\n if (classified.kind === \"call\") {\n if (dedupeContactClick(`call_click:${path}`)) {\n return\n }\n const contactTarget = extractTelTarget(href)\n void trackCallClick(\n path,\n contactTarget ? { contactTarget } : undefined\n )\n return\n }\n if (classified.kind === \"email\") {\n if (dedupeContactClick(`email_click:${path}`)) {\n return\n }\n const contactTarget = extractMailtoTarget(href)\n void trackEmailClick(\n path,\n contactTarget ? { contactTarget } : undefined\n )\n return\n }\n if (dedupeContactClick(`contact_click:${classified.channel}:${path}`)) {\n return\n }\n void trackContactClick(path, {\n channel: classified.channel,\n linkHost: classified.linkHost,\n })\n }\n\n document.addEventListener(\"click\", handler, { capture: true })\n return () => {\n document.removeEventListener(\"click\", handler, { capture: true } as EventListenerOptions)\n }\n }\n\n function dedupeContactClick(key: string): boolean {\n const now = Date.now()\n if (key === lastContactClickKey && now - lastContactClickAt < 1000) {\n return true\n }\n lastContactClickKey = key\n lastContactClickAt = now\n return false\n }\n\n if (typeof window !== \"undefined\" && canSend()) {\n captureLandingAttribution(window.location.hostname)\n }\n\n if (\n typeof window !== \"undefined\" &&\n config.autoTrackContactLinks &&\n canSend()\n ) {\n subscribeContactLinkAutoTrack()\n }\n\n return {\n track,\n trackPageView,\n trackFormSubmit,\n trackCallClick,\n trackEmailClick,\n trackContactClick,\n trackLead,\n subscribeToSpaNavigation,\n subscribeContactLinkAutoTrack,\n setTrackingConsent: setJmpTrackingConsent,\n isTrackingConsentGranted: isJmpTrackingConsentGranted,\n }\n}\n\nexport type JmpAnalytics = ReturnType<typeof createJmpAnalytics>\n","/**\n * Public env vars for JMP — supports Next.js (`NEXT_PUBLIC_*`) and Astro (`PUBLIC_*`).\n * Server/build: `process.env`. Astro client bundles: pass overrides from `import.meta.env`.\n */\n\nexport type JmpPublicEnv = {\n analyticsUrl?: string\n trackingKey?: string\n requireConsent?: boolean\n autoContactLinks?: boolean\n}\n\nfunction firstDefined(...values: (string | undefined)[]): string | undefined {\n for (const v of values) {\n if (v) return v\n }\n return undefined\n}\n\n/** Static reads so Next.js / Vite inline `NEXT_PUBLIC_*` into client bundles. */\nfunction readJmpPublicEnvFromProcessEnv(): Omit<JmpPublicEnv, never> {\n if (typeof process === \"undefined\" || !process.env) {\n return {}\n }\n const { env } = process\n const analyticsUrl = firstDefined(\n env.NEXT_PUBLIC_JMP_ANALYTICS_URL,\n env.PUBLIC_JMP_ANALYTICS_URL,\n )\n const trackingKey = firstDefined(\n env.NEXT_PUBLIC_JMP_TRACKING_KEY,\n env.PUBLIC_JMP_TRACKING_KEY,\n )\n const requireConsentRaw = firstDefined(\n env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,\n env.PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,\n )\n const autoContactRaw = firstDefined(\n env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS,\n env.PUBLIC_JMP_AUTO_CONTACT_LINKS,\n )\n\n return {\n analyticsUrl,\n trackingKey,\n requireConsent: requireConsentRaw === \"true\",\n autoContactLinks: autoContactRaw === \"true\",\n }\n}\n\n/** Read dashboard URL + tracking key from Node / build-time env. */\nexport function readJmpPublicEnvFromProcess(\n overrides?: Partial<JmpPublicEnv>,\n): JmpPublicEnv {\n const fromEnv = readJmpPublicEnvFromProcessEnv()\n\n return {\n analyticsUrl: firstDefined(overrides?.analyticsUrl, fromEnv.analyticsUrl),\n trackingKey: firstDefined(overrides?.trackingKey, fromEnv.trackingKey),\n requireConsent: overrides?.requireConsent ?? fromEnv.requireConsent,\n autoContactLinks:\n overrides?.autoContactLinks ?? fromEnv.autoContactLinks,\n }\n}\n\n/** Read from Astro/Vite `import.meta.env` in client scripts. */\nexport function readJmpPublicEnvFromImportMeta(\n meta: Record<string, unknown> | undefined,\n overrides?: Partial<JmpPublicEnv>,\n): JmpPublicEnv {\n const get = (key: string): string | undefined => {\n const v = meta?.[key]\n return typeof v === \"string\" && v.length > 0 ? v : undefined\n }\n\n const analyticsUrl = firstDefined(\n overrides?.analyticsUrl,\n get(\"PUBLIC_JMP_ANALYTICS_URL\"),\n get(\"NEXT_PUBLIC_JMP_ANALYTICS_URL\"),\n )\n const trackingKey = firstDefined(\n overrides?.trackingKey,\n get(\"PUBLIC_JMP_TRACKING_KEY\"),\n get(\"NEXT_PUBLIC_JMP_TRACKING_KEY\"),\n )\n const requireConsentRaw = firstDefined(\n overrides?.requireConsent !== undefined\n ? String(overrides.requireConsent)\n : undefined,\n get(\"PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT\"),\n get(\"NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT\"),\n )\n const autoContactRaw = firstDefined(\n overrides?.autoContactLinks !== undefined\n ? String(overrides.autoContactLinks)\n : undefined,\n get(\"PUBLIC_JMP_AUTO_CONTACT_LINKS\"),\n get(\"NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS\"),\n )\n\n return {\n analyticsUrl,\n trackingKey,\n requireConsent: requireConsentRaw === \"true\",\n autoContactLinks: autoContactRaw === \"true\",\n }\n}\n","import type { JmpContentManifest } from \"./content/manifest\"\nimport type { JmpContentConfig, JmpContentWrapper } from \"./types\"\nimport { readJmpPublicEnvFromProcess } from \"./env-public\"\n\nexport type JmpSiteSocialLinks = {\n linkedin: string | null\n instagram: string | null\n facebook: string | null\n x: string | null\n youtube: string | null\n}\n\n/** Per-site values used when the dashboard profile is missing or fields are empty. */\nexport type JmpSiteContactFallback = {\n displayName?: string\n founderName?: string\n email?: string\n phone?: string | null\n linkedin?: string | null\n instagram?: string | null\n facebook?: string | null\n x?: string | null\n youtube?: string | null\n hours?: string | null\n serviceArea?: string | null\n address?: string | null\n googleMapsUrl?: string | null\n googleMapsEmbedUrl?: string | null\n dashboardDemoUrl?: string\n profilePhotoSrc?: string\n privacyUrl?: string\n termsUrl?: string\n}\n\nexport type JmpSiteDefinition = {\n /**\n * Content areas this site actually renders. When set, capabilities report\n * this list (manual mode) so unused dashboard editors stay hidden.\n * List granular Trust slots (`trust.summary`, `trust.reviews`) instead of\n * a bare `trust` wrapper.\n */\n contentWrappers?: JmpContentWrapper[]\n /**\n * Override report mode. Defaults to `manual` when `contentWrappers` is set.\n */\n contentWrapperMode?: JmpContentConfig[\"contentWrapperMode\"]\n /**\n * Routes, trust block order, and contact extras for dashboard layout sync.\n * Reported with capabilities when the site loads content from the portal.\n */\n contentManifest?: JmpContentManifest\n /**\n * Public site origin (no trailing slash), e.g. `https://example.com`.\n * Used to resolve relative profile image paths in structured data.\n */\n siteUrl?: string\n /**\n * JMP dashboard origin (no trailing slash), e.g. `https://portal.example.com`.\n * Fallback when `NEXT_PUBLIC_JMP_ANALYTICS_URL` is missing from the client bundle.\n */\n analyticsPortalUrl?: string\n contactFallback?: JmpSiteContactFallback\n /**\n * `extras` keys to read from the dashboard site profile (hyphenated keys from admin).\n */\n contactExtraKeys?: {\n founderName?: readonly string[]\n dashboardDemoUrl?: readonly string[]\n profilePhotoSrc?: readonly string[]\n hours?: readonly string[]\n serviceArea?: readonly string[]\n googleMapsEmbedUrl?: readonly string[]\n }\n}\n\nlet registeredSite: JmpSiteDefinition | null = null\n\n/**\n * Register site-specific JMP integration options once (typically from `jmp.config.ts`).\n * Call at module load time before server content or instrumentation runs.\n */\nexport function defineJmpSite(definition: JmpSiteDefinition): JmpSiteDefinition {\n registeredSite = definition\n return definition\n}\n\nexport function getJmpSiteDefinition(): JmpSiteDefinition | null {\n return registeredSite\n}\n\n/** Server content + lead config: env vars + wrappers from {@link defineJmpSite}. */\nexport function getJmpContentConfig(): JmpContentConfig | null {\n const { analyticsUrl, trackingKey } = readJmpPublicEnvFromProcess()\n if (!analyticsUrl || !trackingKey) {\n return null\n }\n const site = getJmpSiteDefinition()\n const contentWrappers = site?.contentWrappers ?? undefined\n const inferredMode =\n contentWrappers && contentWrappers.length > 0 ? \"manual\" : undefined\n return {\n baseUrl: analyticsUrl,\n trackingKey,\n contentWrappers,\n contentManifest: site?.contentManifest ?? undefined,\n contentWrapperMode: site?.contentWrapperMode ?? inferredMode,\n }\n}\n","import { getJmpSiteDefinition } from \"../site-config\"\nimport type { JmpLandingPage, JmpLandingPageKind } from \"../types\"\nimport { jmpLandingKindSegment } from \"./hub\"\n\n/** Strip lightweight markdown for meta descriptions and schema text fields. */\nexport function plainTextFromMarkdown(input: string, maxLength = 5000): string {\n return input.replace(/[#*_`[\\]]/g, \"\").trim().slice(0, maxLength)\n}\n\nexport function resolveJmpSiteUrl(override?: string): string | null {\n const fromArg = override?.trim().replace(/\\/$/, \"\")\n if (fromArg) return fromArg\n const fromConfig = getJmpSiteDefinition()?.siteUrl?.trim().replace(/\\/$/, \"\")\n return fromConfig || null\n}\n\nexport function absoluteJmpSiteUrl(path: string, siteUrl?: string): string {\n const base = resolveJmpSiteUrl(siteUrl)\n if (!base) {\n return path.startsWith(\"/\") ? path : `/${path}`\n }\n const normalized = path.startsWith(\"/\") ? path : `/${path}`\n return `${base}${normalized}`\n}\n\nexport function filterJmpLandingPagesForDefaultLocale(\n pages: JmpLandingPage[],\n kind: JmpLandingPageKind\n): JmpLandingPage[] {\n const segment = jmpLandingKindSegment(kind)\n return pages.filter((page) => {\n const parts = page.path.split(\"/\").filter(Boolean)\n return parts[0] === segment\n })\n}\n\n/** Pages whose path is `/{locale}/{areas|services}/{slug}` (three+ segments). */\nexport function filterJmpLandingPagesForLocalizedRoutes(\n pages: JmpLandingPage[],\n kind: JmpLandingPageKind\n): JmpLandingPage[] {\n const segment = jmpLandingKindSegment(kind)\n return pages.filter((page) => {\n const parts = page.path.split(\"/\").filter(Boolean)\n return parts.length >= 3 && parts[1] === segment\n })\n}\n\nexport function jmpLocalizedLandingStaticParams(\n pages: JmpLandingPage[],\n kind: JmpLandingPageKind\n): { locale: string; slug: string }[] {\n return filterJmpLandingPagesForLocalizedRoutes(pages, kind).map((page) => {\n const [locale, , slug] = page.path.split(\"/\").filter(Boolean)\n return { locale: locale!, slug: slug! }\n })\n}\n","import { resolveJmpSiteUrl } from \"./landing-pages/utils\"\n\n/**\n * Site origin for server-to-server JMP API calls (content + ingest).\n * Prefer `defineJmpSite({ siteUrl })`, then `NEXT_PUBLIC_SITE_URL`.\n */\nexport function resolveJmpRequestOrigin(): string | null {\n const fromSite = resolveJmpSiteUrl()\n if (fromSite) {\n return fromSite\n }\n if (typeof process === \"undefined\") {\n return null\n }\n return process.env.NEXT_PUBLIC_SITE_URL?.trim().replace(/\\/$/, \"\") || null\n}\n\n/** Adds `Origin` when a site URL is known (required for production write/ingest checks). */\nexport function withJmpOriginHeader(\n headers: Record<string, string>\n): Record<string, string> {\n const origin = resolveJmpRequestOrigin()\n if (!origin) {\n return headers\n }\n return { ...headers, Origin: origin }\n}\n","import {\n getHeader,\n normalizeBaseUrl,\n pathFromRequestUrl,\n} from \"../http\"\nimport { withJmpOriginHeader } from \"../request-origin\"\nimport type { JmpContentConfig, TrackServerPageViewOptions } from \"../types\"\n\nexport async function trackJmpServerPageView(\n config: JmpContentConfig,\n options: TrackServerPageViewOptions = {}\n): Promise<void> {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const resolvedFetch =\n config.fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n\n if (!resolvedFetch) {\n throw new Error(\"JMP server analytics: fetch is not available; pass fetchImpl in config\")\n }\n\n const visitorUserAgent =\n options.userAgent ?? getHeader(options.request?.headers, \"user-agent\")\n const visitorReferer =\n options.referer ?? getHeader(options.request?.headers, \"referer\")\n const path = options.path ?? pathFromRequestUrl(options.request?.url)\n\n const headers: Record<string, string> = withJmpOriginHeader({\n \"Content-Type\": \"application/json\",\n \"X-JMP-Tracking-Key\": config.trackingKey,\n })\n if (visitorUserAgent) {\n headers[\"X-JMP-Visitor-User-Agent\"] = visitorUserAgent\n }\n if (visitorReferer) {\n headers[\"X-JMP-Visitor-Referer\"] = visitorReferer\n }\n\n const payload: Record<string, unknown> = {\n type: \"page_view\",\n path: path || \"/\",\n metadata:\n options.metadata && typeof options.metadata === \"object\"\n ? options.metadata\n : {},\n }\n if (options.sessionId) {\n payload.sessionId = options.sessionId\n }\n\n const url = `${baseUrl}/api/events`\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, payload)\n }\n\n const res = await resolvedFetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!res.ok) {\n const text = await res.text()\n throw new Error(`JMP server analytics HTTP ${res.status} — ${text}`)\n }\n}\n","/** Mirrors jmp-dashboard `lib/content/wrappers/client-manifest.ts` (keep in sync). */\n\nexport const JMP_CONTENT_MANIFEST_VERSION = 1\n\nexport type JmpTrustSection =\n | \"summary\"\n | \"testimonials\"\n | \"reviews\"\n | \"stats\"\n | \"logos\"\n | \"credentials\"\n\nexport type JmpContentRouteManifest = {\n wrapper: string\n pattern: string\n index?: string\n label?: string\n}\n\nexport type JmpTrustBlockManifest = {\n section: JmpTrustSection\n label?: string\n}\n\nexport type JmpContactExtraManifest = {\n key: string\n label: string\n}\n\nexport type JmpLeadInboxManifest = {\n list?: string[]\n detail?: string[]\n labels?: Record<string, string>\n}\n\nexport type JmpExternalSanitySourceManifest = {\n studioUrl?: string\n}\n\nexport type JmpExternalShopifySourceManifest = {\n adminUrl?: string\n storeUrl?: string\n}\n\nexport type JmpExternalAdminLinkManifest = {\n id: string\n label: string\n url: string\n}\n\nexport type JmpExternalSourcesManifest = {\n sanity?: JmpExternalSanitySourceManifest\n shopify?: JmpExternalShopifySourceManifest\n links?: JmpExternalAdminLinkManifest[]\n}\n\nexport type JmpContentManifest = {\n version?: number\n routes?: JmpContentRouteManifest[]\n externalSources?: JmpExternalSourcesManifest\n trust?: {\n blocks?: JmpTrustBlockManifest[]\n labels?: Partial<Record<JmpTrustSection, string>>\n mergeTestimonialsReviews?: boolean\n }\n contact?: {\n extras?: JmpContactExtraManifest[]\n leadInbox?: JmpLeadInboxManifest\n }\n defaults?: {\n contact?: {\n displayName?: string\n email?: string\n phone?: string\n address?: string\n hours?: string\n serviceArea?: string\n googleMapsUrl?: string\n linkedinUrl?: string\n instagramUrl?: string\n facebookUrl?: string\n xUrl?: string\n youtubeUrl?: string\n extras?: Record<string, string>\n }\n faq?: Array<{ question: string; answer: string; category?: string }>\n trust?: {\n googleReviewsUrl?: string\n googlePlaceId?: string\n yelpUrl?: string\n trustpilotUrl?: string\n disclaimer?: string\n }\n }\n}\n\nconst TRUST_SECTIONS = new Set<string>([\n \"summary\",\n \"testimonials\",\n \"reviews\",\n \"stats\",\n \"logos\",\n \"credentials\",\n])\n\nfunction normalizeKey(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n}\n\nfunction isValidExtraKey(key: string): boolean {\n return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(key)\n}\n\nconst MAX_EXTERNAL_ADMIN_LINKS = 10\nconst MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH = 80\nconst EXTERNAL_ADMIN_LINK_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\nfunction tryNormalizeHttpUrl(input: unknown): string | null {\n if (typeof input !== \"string\" || !input.trim()) {\n return null\n }\n try {\n const url = new URL(input.trim())\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n return null\n }\n return url.toString().replace(/\\/$/, \"\")\n } catch {\n return null\n }\n}\n\nfunction normalizeShopifyExternalSource(\n shopify: JmpExternalShopifySourceManifest | undefined\n): JmpExternalShopifySourceManifest | null {\n if (!shopify || typeof shopify !== \"object\") {\n return null\n }\n const adminUrl = tryNormalizeHttpUrl(shopify.adminUrl)\n const storeUrl = tryNormalizeHttpUrl(shopify.storeUrl)\n if (!adminUrl && !storeUrl) {\n return null\n }\n return {\n ...(adminUrl ? { adminUrl } : {}),\n ...(storeUrl ? { storeUrl } : {}),\n }\n}\n\nfunction normalizeExternalAdminLinkEntries(\n links: JmpExternalAdminLinkManifest[] | undefined\n): JmpExternalAdminLinkManifest[] {\n if (!Array.isArray(links)) {\n return []\n }\n const seenIds = new Set<string>()\n const out: JmpExternalAdminLinkManifest[] = []\n for (const raw of links) {\n if (!raw || typeof raw !== \"object\" || out.length >= MAX_EXTERNAL_ADMIN_LINKS) {\n continue\n }\n const id =\n typeof raw.id === \"string\"\n ? raw.id.trim().toLowerCase().replace(/[^a-z0-9-]+/g, \"-\").replace(/^-+|-+$/g, \"\")\n : \"\"\n const label =\n typeof raw.label === \"string\"\n ? raw.label.trim().slice(0, MAX_EXTERNAL_ADMIN_LINK_LABEL_LENGTH)\n : \"\"\n const url = tryNormalizeHttpUrl(raw.url)\n if (\n !id ||\n !label ||\n !url ||\n !EXTERNAL_ADMIN_LINK_ID_PATTERN.test(id) ||\n seenIds.has(id)\n ) {\n continue\n }\n seenIds.add(id)\n out.push({ id, label, url })\n }\n return out\n}\n\nfunction normalizeExternalSources(\n externalSources: JmpExternalSourcesManifest | undefined\n): JmpExternalSourcesManifest | null {\n if (!externalSources || typeof externalSources !== \"object\") {\n return null\n }\n const studioUrl = tryNormalizeHttpUrl(externalSources.sanity?.studioUrl)\n const shopify = normalizeShopifyExternalSource(externalSources.shopify)\n const links = normalizeExternalAdminLinkEntries(externalSources.links)\n if (!studioUrl && !shopify && links.length === 0) {\n return null\n }\n return {\n ...(studioUrl ? { sanity: { studioUrl } } : {}),\n ...(shopify ? { shopify } : {}),\n ...(links.length > 0 ? { links } : {}),\n }\n}\n\nexport function normalizeJmpContentManifest(\n input: JmpContentManifest | null | undefined\n): JmpContentManifest | null {\n if (!input || typeof input !== \"object\") {\n return null\n }\n\n const routes = normalizeRoutes(input.routes)\n const externalSources = normalizeExternalSources(input.externalSources)\n const trust = normalizeTrust(input.trust)\n const contact = normalizeContact(input.contact)\n const defaults = normalizeManifestDefaults(input.defaults)\n\n if (\n routes.length === 0 &&\n !externalSources &&\n !trust &&\n !contact &&\n !defaults\n ) {\n return null\n }\n\n return {\n version: JMP_CONTENT_MANIFEST_VERSION,\n ...(routes.length > 0 ? { routes } : {}),\n ...(externalSources ? { externalSources } : {}),\n ...(trust ? { trust } : {}),\n ...(contact ? { contact } : {}),\n ...(defaults ? { defaults } : {}),\n }\n}\n\nfunction normalizeRoutes(\n routes: JmpContentRouteManifest[] | undefined\n): JmpContentRouteManifest[] {\n if (!Array.isArray(routes)) {\n return []\n }\n const seen = new Set<string>()\n const out: JmpContentRouteManifest[] = []\n for (const raw of routes) {\n if (!raw || typeof raw !== \"object\") continue\n const wrapper =\n typeof raw.wrapper === \"string\" ? raw.wrapper.trim().toLowerCase() : \"\"\n const pattern =\n typeof raw.pattern === \"string\" ? raw.pattern.trim() : \"\"\n if (!wrapper || !pattern) continue\n const dedupe = `${wrapper}:${pattern}`\n if (seen.has(dedupe)) continue\n seen.add(dedupe)\n out.push({\n wrapper,\n pattern,\n ...(typeof raw.index === \"string\" && raw.index.trim()\n ? { index: raw.index.trim() }\n : {}),\n ...(typeof raw.label === \"string\" && raw.label.trim()\n ? { label: raw.label.trim() }\n : {}),\n })\n }\n return out\n}\n\nfunction normalizeTrust(\n trust: JmpContentManifest[\"trust\"] | undefined\n): JmpContentManifest[\"trust\"] | null {\n if (!trust || typeof trust !== \"object\") return null\n const blocks = normalizeTrustBlocks(trust.blocks)\n const labels = normalizeTrustLabels(trust.labels)\n const mergeTestimonialsReviews = trust.mergeTestimonialsReviews === true\n if (blocks.length === 0 && !labels && !mergeTestimonialsReviews) return null\n return {\n ...(blocks.length > 0 ? { blocks } : {}),\n ...(labels ? { labels } : {}),\n ...(mergeTestimonialsReviews ? { mergeTestimonialsReviews: true } : {}),\n }\n}\n\nfunction normalizeTrustBlocks(\n blocks: JmpTrustBlockManifest[] | undefined\n): JmpTrustBlockManifest[] {\n if (!Array.isArray(blocks)) return []\n const seen = new Set<string>()\n const out: JmpTrustBlockManifest[] = []\n for (const raw of blocks) {\n if (!raw || typeof raw !== \"object\") continue\n const section =\n typeof raw.section === \"string\" ? raw.section.trim().toLowerCase() : \"\"\n if (!TRUST_SECTIONS.has(section) || seen.has(section)) continue\n seen.add(section)\n out.push({\n section: section as JmpTrustSection,\n ...(typeof raw.label === \"string\" && raw.label.trim()\n ? { label: raw.label.trim() }\n : {}),\n })\n }\n return out\n}\n\nfunction normalizeTrustLabels(\n labels: Partial<Record<JmpTrustSection, string>> | undefined\n): Partial<Record<JmpTrustSection, string>> | null {\n if (!labels || typeof labels !== \"object\") return null\n const out: Partial<Record<JmpTrustSection, string>> = {}\n for (const [key, value] of Object.entries(labels)) {\n if (TRUST_SECTIONS.has(key) && typeof value === \"string\" && value.trim()) {\n out[key as JmpTrustSection] = value.trim()\n }\n }\n return Object.keys(out).length > 0 ? out : null\n}\n\nfunction readDefaultText(value: unknown, max = 500): string | undefined {\n if (typeof value !== \"string\") return undefined\n const trimmed = value.trim()\n if (!trimmed) return undefined\n return trimmed.slice(0, max)\n}\n\nfunction normalizeManifestDefaults(\n defaults: JmpContentManifest[\"defaults\"] | undefined\n): JmpContentManifest[\"defaults\"] | null {\n if (!defaults || typeof defaults !== \"object\") return null\n\n const contactRaw = defaults.contact\n const contact: NonNullable<JmpContentManifest[\"defaults\"]>[\"contact\"] = {}\n if (contactRaw && typeof contactRaw === \"object\") {\n const displayName = readDefaultText(contactRaw.displayName, 120)\n const email = readDefaultText(contactRaw.email, 200)\n const phone = readDefaultText(contactRaw.phone, 40)\n const address = readDefaultText(contactRaw.address, 400)\n const hours = readDefaultText(contactRaw.hours, 400)\n const serviceArea = readDefaultText(contactRaw.serviceArea, 200)\n const googleMapsUrl = readDefaultText(contactRaw.googleMapsUrl, 2048)\n const linkedinUrl = readDefaultText(contactRaw.linkedinUrl, 2048)\n const instagramUrl = readDefaultText(contactRaw.instagramUrl, 2048)\n const facebookUrl = readDefaultText(contactRaw.facebookUrl, 2048)\n const xUrl = readDefaultText(contactRaw.xUrl, 2048)\n const youtubeUrl = readDefaultText(contactRaw.youtubeUrl, 2048)\n if (displayName) contact.displayName = displayName\n if (email) contact.email = email\n if (phone) contact.phone = phone\n if (address) contact.address = address\n if (hours) contact.hours = hours\n if (serviceArea) contact.serviceArea = serviceArea\n if (googleMapsUrl) contact.googleMapsUrl = googleMapsUrl\n if (linkedinUrl) contact.linkedinUrl = linkedinUrl\n if (instagramUrl) contact.instagramUrl = instagramUrl\n if (facebookUrl) contact.facebookUrl = facebookUrl\n if (xUrl) contact.xUrl = xUrl\n if (youtubeUrl) contact.youtubeUrl = youtubeUrl\n if (contactRaw.extras && typeof contactRaw.extras === \"object\") {\n const extras: Record<string, string> = {}\n for (const [rawKey, rawValue] of Object.entries(contactRaw.extras)) {\n if (Object.keys(extras).length >= 10) break\n const key = normalizeKey(rawKey)\n const value = readDefaultText(rawValue, 200)\n if (key && isValidExtraKey(key) && value) extras[key] = value\n }\n if (Object.keys(extras).length > 0) contact.extras = extras\n }\n }\n\n const faq: NonNullable<JmpContentManifest[\"defaults\"]>[\"faq\"] = []\n if (Array.isArray(defaults.faq)) {\n for (const raw of defaults.faq) {\n if (!raw || typeof raw !== \"object\" || faq.length >= 40) continue\n const question = readDefaultText(raw.question, 300)\n const answer = readDefaultText(raw.answer, 8000)\n if (!question || !answer) continue\n const category = readDefaultText(raw.category, 80)\n faq.push({ question, answer, ...(category ? { category } : {}) })\n }\n }\n\n const trustRaw = defaults.trust\n const trust: NonNullable<JmpContentManifest[\"defaults\"]>[\"trust\"] = {}\n if (trustRaw && typeof trustRaw === \"object\") {\n const assign = (\n key: keyof NonNullable<typeof trust>,\n max: number\n ) => {\n const value = readDefaultText(trustRaw[key], max)\n if (value) trust[key] = value\n }\n assign(\"googleReviewsUrl\", 2048)\n assign(\"googlePlaceId\", 128)\n assign(\"yelpUrl\", 2048)\n assign(\"trustpilotUrl\", 2048)\n assign(\"disclaimer\", 1000)\n }\n\n const hasContact = Object.keys(contact).length > 0\n const hasTrust = Object.keys(trust).length > 0\n if (!hasContact && faq.length === 0 && !hasTrust) return null\n\n return {\n ...(hasContact ? { contact } : {}),\n ...(faq.length > 0 ? { faq } : {}),\n ...(hasTrust ? { trust } : {}),\n }\n}\n\nfunction normalizeContact(\n contact: JmpContentManifest[\"contact\"] | undefined\n): JmpContentManifest[\"contact\"] | null {\n if (!contact || typeof contact !== \"object\") return null\n const extras = normalizeContactExtras(contact.extras)\n const leadInbox = normalizeLeadInbox(contact.leadInbox)\n if (extras.length === 0 && !leadInbox) return null\n return {\n ...(extras.length > 0 ? { extras } : {}),\n ...(leadInbox ? { leadInbox } : {}),\n }\n}\n\nfunction normalizeLeadInbox(\n raw: JmpLeadInboxManifest | undefined\n): JmpLeadInboxManifest | null {\n if (!raw || typeof raw !== \"object\") return null\n const list = normalizeInboxKeyList(raw.list, 8)\n const detail = normalizeInboxKeyList(raw.detail, 24)\n const labels = normalizeInboxLabels(raw.labels)\n if (!list && !detail && !labels) return null\n return {\n ...(list ? { list } : {}),\n ...(detail ? { detail } : {}),\n ...(labels ? { labels } : {}),\n }\n}\n\nfunction normalizeInboxKeyList(\n raw: string[] | undefined,\n max: number\n): string[] | undefined {\n if (!Array.isArray(raw)) return undefined\n const seen = new Set<string>()\n const out: string[] = []\n for (const item of raw) {\n if (typeof item !== \"string\" || out.length >= max) continue\n const key = item.trim()\n const token = key.replace(/[^a-zA-Z0-9]+/g, \"\").toLowerCase()\n if (!key || !token || seen.has(token)) continue\n seen.add(token)\n out.push(key)\n }\n return out.length > 0 ? out : undefined\n}\n\nfunction normalizeInboxLabels(\n raw: Record<string, string> | undefined\n): Record<string, string> | undefined {\n if (!raw || typeof raw !== \"object\") return undefined\n const out: Record<string, string> = {}\n for (const [key, value] of Object.entries(raw)) {\n if (typeof value !== \"string\") continue\n const label = value.trim().slice(0, 60)\n const token = key.trim()\n if (!token || !label) continue\n out[token] = label\n }\n return Object.keys(out).length > 0 ? out : undefined\n}\n\nfunction normalizeContactExtras(\n extras: JmpContactExtraManifest[] | undefined\n): JmpContactExtraManifest[] {\n if (!Array.isArray(extras)) return []\n const seen = new Set<string>()\n const out: JmpContactExtraManifest[] = []\n for (const raw of extras) {\n if (!raw || typeof raw !== \"object\") continue\n const label = typeof raw.label === \"string\" ? raw.label.trim() : \"\"\n const key = normalizeKey(\n typeof raw.key === \"string\" && raw.key.trim() ? raw.key : label\n )\n if (!key || !label || !isValidExtraKey(key) || seen.has(key)) continue\n seen.add(key)\n out.push({ key, label })\n }\n return out\n}\n\nexport function stableJmpManifestFingerprint(\n manifest: JmpContentManifest | null\n): string {\n return manifest ? JSON.stringify(manifest) : \"\"\n}\n\nexport function inferWrapperSlotsFromManifest(\n manifest: JmpContentManifest | null\n): string[] {\n const slots = new Set<string>()\n for (const route of manifest?.routes ?? []) {\n slots.add(route.wrapper)\n }\n for (const block of manifest?.trust?.blocks ?? []) {\n slots.add(`trust.${block.section}`)\n slots.add(\"trust\")\n }\n if (manifest?.contact?.extras?.length || manifest?.contact?.leadInbox) {\n slots.add(\"contact\")\n }\n return [...slots]\n}\n","import {\n JMP_CONTENT_CACHE_TAG,\n JMP_CONTENT_REVALIDATE_SECONDS,\n} from \"../constants\"\nimport { normalizeBaseUrl, responseLooksLikeHtml } from \"../http\"\nimport { withJmpOriginHeader } from \"../request-origin\"\nimport type { JmpContentConfig } from \"../types\"\n\n/**\n * Headers for server content API calls. Sends `Origin` from siteUrl /\n * NEXT_PUBLIC_SITE_URL when available (required for capabilities writes in\n * production; helpful for content reads).\n */\nexport function jmpContentRequestHeaders(\n config: JmpContentConfig\n): Record<string, string> {\n return withJmpOriginHeader({\n \"X-JMP-Tracking-Key\": config.trackingKey,\n })\n}\n\nexport async function getContent<T>(\n config: JmpContentConfig,\n path: string\n): Promise<T> {\n const text = await getContentText(config, path)\n\n try {\n return JSON.parse(text) as T\n } catch {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const url = `${baseUrl}${path}`\n throw new Error(`JMP content HTTP 200 — ${url} returned invalid JSON.`)\n }\n}\n\nexport async function getContentText(\n config: JmpContentConfig,\n path: string\n): Promise<string> {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const resolvedFetch =\n config.fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n\n if (!resolvedFetch) {\n throw new Error(\"JMP content: fetch is not available; pass fetchImpl in config\")\n }\n\n const url = `${baseUrl}${path}`\n\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"GET\", url)\n }\n\n const res = await resolvedFetch(url, {\n method: \"GET\",\n headers: jmpContentRequestHeaders(config),\n next: {\n revalidate: JMP_CONTENT_REVALIDATE_SECONDS,\n tags: [JMP_CONTENT_CACHE_TAG],\n },\n })\n\n const text = await res.text()\n\n if (!res.ok) {\n if (responseLooksLikeHtml(text)) {\n throw new Error(\n `JMP content HTTP ${res.status} — ${url} returned HTML (not the JSON API). ` +\n `Set baseUrl to your JMP Analytics dashboard origin.`\n )\n }\n\n let parsed: { error?: string; hint?: string } = {}\n try {\n parsed = JSON.parse(text) as typeof parsed\n } catch {\n parsed = { error: text }\n }\n\n throw new Error(\n [`JMP content HTTP ${res.status}`, parsed.error, parsed.hint]\n .filter(Boolean)\n .join(\" — \")\n )\n }\n\n return text\n}\n","import {\n inferWrapperSlotsFromManifest,\n normalizeJmpContentManifest,\n type JmpContentManifest,\n} from \"./manifest\"\nimport type { JmpContentConfig, JmpContentWrapper, JmpTrustBundle } from \"../types\"\nimport {\n getJmpSiteDefinition,\n type JmpSiteContactFallback,\n} from \"../site-config\"\n\n/** Stable report order (matches dashboard `CLIENT_REPORTABLE_WRAPPER_SLOTS`). */\nconst WRAPPER_SLOT_ORDER: readonly string[] = [\n \"blog\",\n \"faq\",\n \"contact\",\n \"legal\",\n \"trust\",\n \"trust.summary\",\n \"trust.testimonials\",\n \"trust.reviews\",\n \"trust.stats\",\n \"trust.logos\",\n \"trust.credentials\",\n]\n\nconst discovered = new Set<string>()\nlet syncTimer: ReturnType<typeof setTimeout> | null = null\nlet pendingSyncConfig: JmpContentConfig | null = null\n\nconst reportedDedupeKeys = new Set<string>()\nlet syncHandler: ((config: JmpContentConfig) => Promise<unknown>) | null = null\n\nexport function markContentWrapper(slot: JmpContentWrapper | string): void {\n const normalized = slot.trim().toLowerCase()\n if (!normalized) {\n return\n }\n discovered.add(normalized)\n}\n\nexport function markTrustBundleWrappers(bundle: JmpTrustBundle): void {\n for (const slot of inferTrustWrapperSlots(bundle)) {\n discovered.add(slot)\n }\n}\n\nexport function inferTrustWrapperSlots(bundle: JmpTrustBundle): string[] {\n const slots = new Set<string>()\n const { summary, testimonials, stats, logos, credentials } = bundle\n\n const hasSummary =\n summary.google_rating != null ||\n summary.google_review_count != null ||\n Boolean(summary.google_reviews_url?.trim()) ||\n Boolean(summary.yelp_url?.trim()) ||\n Boolean(summary.trustpilot_url?.trim()) ||\n Boolean(summary.disclaimer?.trim())\n\n if (hasSummary) {\n slots.add(\"trust.summary\")\n }\n\n let hasTestimonials = false\n let hasReviews = false\n for (const item of testimonials) {\n const bucket = item.placement?.trim().toLowerCase()\n if (bucket === \"reviews\") {\n hasReviews = true\n } else {\n hasTestimonials = true\n }\n }\n if (hasTestimonials) {\n slots.add(\"trust.testimonials\")\n }\n if (hasReviews) {\n slots.add(\"trust.reviews\")\n }\n if (stats.length > 0) {\n slots.add(\"trust.stats\")\n }\n if (logos.length > 0) {\n slots.add(\"trust.logos\")\n }\n if (credentials.length > 0) {\n slots.add(\"trust.credentials\")\n }\n\n return sortWrapperSlots([...slots])\n}\n\nexport function getDiscoveredContentWrappers(): string[] {\n return sortWrapperSlots([...discovered])\n}\n\nexport function resolveContentManifestForReport(\n config: JmpContentConfig\n): JmpContentManifest | null {\n const site = getJmpSiteDefinition()\n const fallback = site?.contactFallback\n const existing = config.contentManifest\n const fromFallback = fallbackToManifestDefaults(fallback)\n if (!existing && !fromFallback) {\n return null\n }\n const merged: JmpContentManifest = {\n ...(existing ?? {}),\n defaults: {\n ...(fromFallback ?? {}),\n ...(existing?.defaults ?? {}),\n contact: {\n ...(fromFallback?.contact ?? {}),\n ...(existing?.defaults?.contact ?? {}),\n extras: {\n ...(fromFallback?.contact?.extras ?? {}),\n ...(existing?.defaults?.contact?.extras ?? {}),\n },\n },\n trust: {\n ...(fromFallback?.trust ?? {}),\n ...(existing?.defaults?.trust ?? {}),\n },\n faq: existing?.defaults?.faq?.length\n ? existing.defaults.faq\n : fromFallback?.faq,\n },\n }\n return normalizeJmpContentManifest(merged)\n}\n\nfunction fallbackToManifestDefaults(\n fallback: JmpSiteContactFallback | undefined\n): JmpContentManifest[\"defaults\"] | null {\n if (!fallback) return null\n const contact: NonNullable<JmpContentManifest[\"defaults\"]>[\"contact\"] = {}\n if (fallback.displayName?.trim()) contact.displayName = fallback.displayName.trim()\n if (fallback.email?.trim()) contact.email = fallback.email.trim()\n if (typeof fallback.phone === \"string\" && fallback.phone.trim()) {\n contact.phone = fallback.phone.trim()\n }\n if (fallback.address?.trim()) contact.address = fallback.address.trim()\n if (fallback.hours?.trim()) contact.hours = fallback.hours.trim()\n if (fallback.serviceArea?.trim()) contact.serviceArea = fallback.serviceArea.trim()\n if (fallback.googleMapsUrl?.trim()) {\n contact.googleMapsUrl = fallback.googleMapsUrl.trim()\n }\n if (fallback.linkedin?.trim()) contact.linkedinUrl = fallback.linkedin.trim()\n if (fallback.instagram?.trim()) contact.instagramUrl = fallback.instagram.trim()\n if (fallback.facebook?.trim()) contact.facebookUrl = fallback.facebook.trim()\n if (fallback.x?.trim()) contact.xUrl = fallback.x.trim()\n if (fallback.youtube?.trim()) contact.youtubeUrl = fallback.youtube.trim()\n const trust: NonNullable<JmpContentManifest[\"defaults\"]>[\"trust\"] = {}\n if (fallback.googleMapsUrl?.trim()) {\n trust.googleReviewsUrl = fallback.googleMapsUrl.trim()\n }\n const hasContact = Object.keys(contact).length > 0\n const hasTrust = Object.keys(trust).length > 0\n if (!hasContact && !hasTrust) return null\n return {\n ...(hasContact ? { contact } : {}),\n ...(hasTrust ? { trust } : {}),\n }\n}\n\nexport function resolveContentWrappersForReport(\n config: JmpContentConfig\n): string[] {\n const explicit = config.contentWrappers ?? []\n const auto = getDiscoveredContentWrappers()\n const fromManifest = inferWrapperSlotsFromManifest(\n resolveContentManifestForReport(config)\n )\n\n if (config.contentWrapperMode === \"manual\") {\n return sortWrapperSlots([...explicit, ...fromManifest])\n }\n\n if (config.contentWrapperMode === \"explicit-only\") {\n return sortWrapperSlots([...explicit, ...fromManifest])\n }\n\n const merged = new Set<string>([...explicit, ...auto, ...fromManifest])\n return sortWrapperSlots([...merged])\n}\n\nexport function hasReportedContentWrappers(dedupeKey: string): boolean {\n return reportedDedupeKeys.has(dedupeKey)\n}\n\nexport function rememberReportedContentWrappers(dedupeKey: string): void {\n reportedDedupeKeys.add(dedupeKey)\n}\n\nexport function setContentWrapperSyncHandler(\n handler: (config: JmpContentConfig) => Promise<unknown>\n): void {\n syncHandler = handler\n}\n\n/**\n * Debounced POST after content APIs run (build SSG, first page hit, etc.).\n */\nexport function scheduleContentWrapperSync(config: JmpContentConfig): void {\n if (!syncHandler) {\n return\n }\n pendingSyncConfig = config\n if (syncTimer) {\n clearTimeout(syncTimer)\n }\n syncTimer = setTimeout(() => {\n syncTimer = null\n const cfg = pendingSyncConfig\n pendingSyncConfig = null\n if (!cfg || !syncHandler) {\n return\n }\n void syncHandler(cfg).catch(() => {})\n }, 750)\n}\n\nexport function resetContentWrapperDiscoveryForTests(): void {\n discovered.clear()\n reportedDedupeKeys.clear()\n syncHandler = null\n if (syncTimer) {\n clearTimeout(syncTimer)\n syncTimer = null\n }\n pendingSyncConfig = null\n}\n\nfunction sortWrapperSlots(slots: string[]): string[] {\n const order = new Map(WRAPPER_SLOT_ORDER.map((slot, index) => [slot, index]))\n return [...new Set(slots)].sort((a, b) => {\n const ai = order.get(a) ?? 999\n const bi = order.get(b) ?? 999\n if (ai !== bi) {\n return ai - bi\n }\n return a.localeCompare(b)\n })\n}\n","import { JMP_ANALYTICS_SDK_VERSION } from \"../constants\"\nimport { normalizeBaseUrl } from \"../http\"\nimport type {\n JmpBlogPost,\n JmpContentConfig,\n JmpFaqItem,\n JmpLandingPage,\n JmpLandingPageDetail,\n JmpLandingPageKind,\n JmpLandingPageSitemapEntry,\n JmpLegalDocument,\n JmpPopularPagesResult,\n JmpSiteProfile,\n JmpTrustBundle,\n JmpWebsiteLocation,\n JmpWebsiteLocationDetail,\n} from \"../types\"\nimport { getContent, getContentText, jmpContentRequestHeaders } from \"./fetch\"\nimport {\n stableJmpManifestFingerprint,\n type JmpContentManifest,\n} from \"./manifest\"\nimport {\n hasReportedContentWrappers,\n markContentWrapper,\n markTrustBundleWrappers,\n rememberReportedContentWrappers,\n resolveContentManifestForReport,\n resolveContentWrappersForReport,\n scheduleContentWrapperSync,\n setContentWrapperSyncHandler,\n} from \"./wrapper-discovery\"\n\nexport {\n getDiscoveredContentWrappers,\n inferTrustWrapperSlots,\n markContentWrapper,\n markTrustBundleWrappers,\n resetContentWrapperDiscoveryForTests,\n} from \"./wrapper-discovery\"\n\nfunction afterContentWrapperUse(config: JmpContentConfig): void {\n scheduleContentWrapperSync(config)\n}\n\nexport async function getJmpBlogPosts(\n config: JmpContentConfig,\n filters?: { locale?: string }\n): Promise<JmpBlogPost[]> {\n const params = new URLSearchParams()\n if (filters?.locale) {\n params.set(\"locale\", filters.locale)\n }\n const query = params.toString()\n const data = await getContent<{ posts: JmpBlogPost[] }>(\n config,\n `/api/content/blog${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"blog\")\n afterContentWrapperUse(config)\n return data.posts\n}\n\nexport async function getJmpBlogPost(\n config: JmpContentConfig,\n slug: string,\n locale?: string\n): Promise<JmpBlogPost | null> {\n try {\n const params = new URLSearchParams()\n if (locale) {\n params.set(\"locale\", locale)\n }\n const query = params.toString()\n const data = await getContent<{ post: JmpBlogPost; alternates?: unknown }>(\n config,\n `/api/content/blog/${encodeURIComponent(slug)}${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"blog\")\n afterContentWrapperUse(config)\n return data.post\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpBlogPostDetail(\n config: JmpContentConfig,\n slug: string,\n locale?: string\n): Promise<import(\"../types\").JmpBlogPostDetail | null> {\n try {\n const params = new URLSearchParams()\n if (locale) {\n params.set(\"locale\", locale)\n }\n const query = params.toString()\n const data = await getContent<import(\"../types\").JmpBlogPostDetail>(\n config,\n `/api/content/blog/${encodeURIComponent(slug)}${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"blog\")\n afterContentWrapperUse(config)\n return data\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpFaqs(\n config: JmpContentConfig,\n filters?: { locale?: string }\n): Promise<JmpFaqItem[]> {\n const params = new URLSearchParams()\n if (filters?.locale) {\n params.set(\"locale\", filters.locale)\n }\n const query = params.toString()\n const data = await getContent<{ faqs: JmpFaqItem[] }>(\n config,\n `/api/content/faqs${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"faq\")\n afterContentWrapperUse(config)\n return data.faqs\n}\n\nexport async function getJmpLegalDocument(\n config: JmpContentConfig,\n slug: string\n): Promise<JmpLegalDocument | null> {\n const key = slug.trim().toLowerCase()\n if (!key) {\n return null\n }\n try {\n const data = await getContent<{ document: JmpLegalDocument }>(\n config,\n `/api/content/legal?slug=${encodeURIComponent(key)}`\n )\n markContentWrapper(\"legal\")\n afterContentWrapperUse(config)\n return data.document\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpLegalDocuments(\n config: JmpContentConfig\n): Promise<JmpLegalDocument[]> {\n const data = await getContent<{ documents: JmpLegalDocument[] }>(\n config,\n \"/api/content/legal\"\n )\n markContentWrapper(\"legal\")\n afterContentWrapperUse(config)\n return data.documents\n}\n\nexport async function getJmpFaqDetail(\n config: JmpContentConfig,\n slug: string,\n locale?: string\n): Promise<import(\"../types\").JmpFaqItemDetail | null> {\n try {\n const params = new URLSearchParams()\n if (locale) {\n params.set(\"locale\", locale)\n }\n const query = params.toString()\n const data = await getContent<import(\"../types\").JmpFaqItemDetail>(\n config,\n `/api/content/faqs/${encodeURIComponent(slug)}${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"faq\")\n afterContentWrapperUse(config)\n return data\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpLandingPages(\n config: JmpContentConfig,\n filters?: { kind?: JmpLandingPageKind; locale?: string }\n): Promise<JmpLandingPage[]> {\n const params = new URLSearchParams()\n if (filters?.kind) {\n params.set(\"kind\", filters.kind)\n }\n if (filters?.locale) {\n params.set(\"locale\", filters.locale)\n }\n const query = params.toString()\n const data = await getContent<{ pages: JmpLandingPage[] }>(\n config,\n `/api/content/landing-pages${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"landing\")\n afterContentWrapperUse(config)\n return data.pages\n}\n\nexport async function getJmpLandingPageDetail(\n config: JmpContentConfig,\n kind: JmpLandingPageKind,\n slug: string,\n locale?: string\n): Promise<JmpLandingPageDetail | null> {\n const params = new URLSearchParams()\n if (locale) {\n params.set(\"locale\", locale)\n }\n const query = params.toString()\n try {\n const detail = await getContent<JmpLandingPageDetail>(\n config,\n `/api/content/landing-pages/${encodeURIComponent(kind)}/${encodeURIComponent(slug)}${query ? `?${query}` : \"\"}`\n )\n markContentWrapper(\"landing\")\n afterContentWrapperUse(config)\n return detail\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpLandingPageSitemap(\n config: JmpContentConfig\n): Promise<JmpLandingPageSitemapEntry[]> {\n const data = await getContent<{ entries: JmpLandingPageSitemapEntry[] }>(\n config,\n \"/api/content/landing-pages/sitemap\"\n )\n markContentWrapper(\"landing\")\n afterContentWrapperUse(config)\n return data.entries\n}\n\nexport async function getJmpLocations(\n config: JmpContentConfig\n): Promise<JmpWebsiteLocation[]> {\n const data = await getContent<{ locations: JmpWebsiteLocation[] }>(\n config,\n \"/api/content/locations\"\n )\n markContentWrapper(\"locations\")\n afterContentWrapperUse(config)\n return data.locations\n}\n\nexport async function getJmpLocationDetail(\n config: JmpContentConfig,\n slug: string\n): Promise<JmpWebsiteLocationDetail | null> {\n const normalized = slug.trim()\n if (!normalized) {\n return null\n }\n try {\n const detail = await getContent<JmpWebsiteLocationDetail>(\n config,\n `/api/content/locations/${encodeURIComponent(normalized)}`\n )\n markContentWrapper(\"locations\")\n afterContentWrapperUse(config)\n return detail\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"HTTP 404\")) {\n return null\n }\n throw error\n }\n}\n\nexport async function getJmpTrustBundle(\n config: JmpContentConfig\n): Promise<JmpTrustBundle> {\n const bundle = await getContent<JmpTrustBundle>(config, \"/api/content/trust\")\n markTrustBundleWrappers(bundle)\n afterContentWrapperUse(config)\n return bundle\n}\n\nexport async function getJmpSiteProfile(\n config: JmpContentConfig\n): Promise<JmpSiteProfile> {\n const data = await getContent<{ site: JmpSiteProfile }>(\n config,\n \"/api/content/site\"\n )\n markContentWrapper(\"contact\")\n afterContentWrapperUse(config)\n return data.site\n}\n\nexport async function getJmpRobotsTxt(config: JmpContentConfig): Promise<string> {\n return getContentText(config, \"/api/content/robots\")\n}\n\nexport async function getJmpPopularPages(\n config: JmpContentConfig,\n filters?: {\n prefix?: string\n days?: number\n limit?: number\n }\n): Promise<JmpPopularPagesResult> {\n const params = new URLSearchParams()\n if (filters?.prefix) {\n params.set(\"prefix\", filters.prefix)\n }\n if (typeof filters?.days === \"number\") {\n params.set(\"days\", String(filters.days))\n }\n if (typeof filters?.limit === \"number\") {\n params.set(\"limit\", String(filters.limit))\n }\n const query = params.toString()\n return getContent<JmpPopularPagesResult>(\n config,\n `/api/content/popular-pages${query ? `?${query}` : \"\"}`\n )\n}\n\n/**\n * Tell the JMP dashboard which content wrappers this site wires (blog, faq, trust.*, contact).\n * Uses auto-discovered slots from content API usage unless `contentWrapperMode` is `manual`.\n * Safe to call on every cold start; dedupes by tracking key + wrapper list.\n */\nexport async function registerJmpContentWrappers(\n config: JmpContentConfig\n): Promise<\n { ok: true; wrappers: string[] } | { ok: false; skipped: true }\n> {\n const wrappers = resolveContentWrappersForReport(config)\n if (!wrappers.length) {\n return { ok: false, skipped: true }\n }\n\n const manifest = resolveContentManifestForReport(config)\n const dedupeKey = `${config.trackingKey}:${[...wrappers].sort().join(\",\")}:${stableJmpManifestFingerprint(manifest)}`\n if (hasReportedContentWrappers(dedupeKey)) {\n return { ok: true, wrappers }\n }\n\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const resolvedFetch =\n config.fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n\n if (!resolvedFetch) {\n throw new Error(\n \"JMP content wrappers: fetch is not available; pass fetchImpl in config\"\n )\n }\n\n const url = `${baseUrl}/api/content/capabilities`\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, {\n wrappers,\n manifest,\n })\n }\n\n const body: {\n wrappers: string[]\n sdkVersion: string\n manifest?: JmpContentManifest\n } = {\n wrappers,\n sdkVersion: JMP_ANALYTICS_SDK_VERSION,\n }\n if (manifest) {\n body.manifest = manifest\n }\n\n const res = await resolvedFetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...jmpContentRequestHeaders(config),\n },\n body: JSON.stringify(body),\n })\n\n const text = await res.text()\n if (!res.ok) {\n let parsed: { error?: string; hint?: string } = {}\n try {\n parsed = JSON.parse(text) as typeof parsed\n } catch {\n parsed = { error: text }\n }\n throw new Error(\n [`JMP content wrappers HTTP ${res.status}`, parsed.error, parsed.hint]\n .filter(Boolean)\n .join(\" — \")\n )\n }\n\n rememberReportedContentWrappers(dedupeKey)\n const data = JSON.parse(text) as { wrappers?: string[] }\n return { ok: true, wrappers: data.wrappers ?? wrappers }\n}\n\nsetContentWrapperSyncHandler(registerJmpContentWrappers)\n","{\n \"robotsUserAgents\": [\n \"GPTBot\",\n \"ChatGPT-User\",\n \"OAI-SearchBot\",\n \"OAI-AdsBot\",\n \"ClaudeBot\",\n \"Claude-User\",\n \"Claude-SearchBot\",\n \"Claude-Web\",\n \"PerplexityBot\",\n \"Perplexity-User\",\n \"Google-Extended\",\n \"GoogleOther\",\n \"GoogleOther-Image\",\n \"GoogleOther-Video\",\n \"Google-CloudVertexBot\",\n \"Meta-ExternalAgent\",\n \"Meta-ExternalFetcher\",\n \"FacebookBot\",\n \"Applebot\",\n \"Applebot-Extended\",\n \"CCBot\",\n \"Bytespider\",\n \"cohere-ai\",\n \"cohere-training-data-crawler\",\n \"YouBot\",\n \"MistralAI-User\",\n \"GrokBot\",\n \"Grok-DeepSearch\",\n \"xAI-Grok\",\n \"xAI-Bot\"\n ],\n \"wafUserAgents\": [\n \"GPTBot\",\n \"ChatGPT-User\",\n \"OAI-SearchBot\",\n \"OAI-AdsBot\",\n \"ClaudeBot\",\n \"Claude-User\",\n \"Claude-SearchBot\",\n \"Claude-Web\",\n \"PerplexityBot\",\n \"Perplexity-User\",\n \"Google-Extended\",\n \"GoogleOther\",\n \"Google-CloudVertexBot\",\n \"Meta-ExternalAgent\",\n \"Meta-ExternalFetcher\",\n \"FacebookBot\",\n \"Applebot-Extended\",\n \"CCBot\",\n \"Bytespider\",\n \"cohere-ai\",\n \"cohere-training-data-crawler\",\n \"YouBot\",\n \"MistralAI-User\",\n \"GrokBot\",\n \"Grok-DeepSearch\",\n \"xAI-Grok\",\n \"xAI-Bot\"\n ]\n}\n","import agentLists from \"../ai-crawler-agents.json\"\n\nexport const AI_CRAWLER_ROBOTS_USER_AGENTS = agentLists.robotsUserAgents\n\n/** UA tokens denied at the Vercel WAF. Omits generic Applebot so Apple Search can still crawl. */\nexport const JMP_AI_CRAWLER_WAF_USER_AGENTS = agentLists.wafUserAgents\n\nexport function buildAiCrawlerRobotsTxt(blockAiCrawlers: boolean): string {\n if (!blockAiCrawlers) {\n return [\n \"# JMP AI crawler policy\",\n \"# AI crawler blocking is disabled for this website.\",\n \"\",\n ].join(\"\\n\")\n }\n\n return [\n \"# JMP AI crawler policy\",\n \"# Blocks known AI training, answer, and fetch bots that honor robots.txt.\",\n ...AI_CRAWLER_ROBOTS_USER_AGENTS.flatMap((agent) => [\n `User-agent: ${agent}`,\n \"Disallow: /\",\n \"\",\n ]),\n ].join(\"\\n\")\n}\n\nexport function jmpAiCrawlerWafUserAgentPattern(): string {\n return JMP_AI_CRAWLER_WAF_USER_AGENTS.map(escapeRegExp).join(\"|\")\n}\n\n/** `vercel.json` mitigate route. Safe for Googlebot / generic Applebot. */\nexport function jmpAiCrawlerVercelWafRoute(): {\n src: string\n has: Array<{ type: \"header\"; key: string; value: string }>\n mitigate: { action: \"deny\" }\n} {\n return {\n src: \"/(.*)\",\n has: [\n {\n type: \"header\",\n key: \"user-agent\",\n value: `(?i).*(${jmpAiCrawlerWafUserAgentPattern()}).*`,\n },\n ],\n mitigate: { action: \"deny\" },\n }\n}\n\nexport function mergeJmpRobotsTxt(\n jmpBody: string,\n options: {\n siteUrl: string\n privatePathPrefixes?: readonly string[]\n /** When true, always include AI Disallow rules even if JMP left blocking off. */\n ensureAiCrawlerDisallows?: boolean\n },\n): string {\n const trimmed = jmpBody.trim()\n const sitemapLine = `Sitemap: ${options.siteUrl.replace(/\\/$/, \"\")}/sitemap.xml`\n const hasSitemap = /(?:^|\\n)\\s*Sitemap:/i.test(trimmed)\n const prefixes = options.privatePathPrefixes ?? []\n const missingDisallows = prefixes.filter(\n (prefix) => !trimmed.includes(`Disallow: ${prefix}`),\n )\n\n const parts = [trimmed]\n if (\n options.ensureAiCrawlerDisallows &&\n !/User-agent:\\s*GPTBot/i.test(trimmed)\n ) {\n parts.unshift(buildAiCrawlerRobotsTxt(true).trim())\n }\n if (missingDisallows.length > 0) {\n const lines = prefixes.map((prefix) => `Disallow: ${prefix}`)\n parts.push(`User-agent: *\\n${lines.join(\"\\n\")}`)\n }\n if (!hasSitemap) {\n parts.push(sitemapLine)\n }\n\n return `${parts.join(\"\\n\\n\")}\\n`\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n","import {\n getJmpBlogPost,\n getJmpBlogPosts,\n getJmpFaqs,\n getJmpLegalDocument,\n getJmpLegalDocuments,\n getJmpLandingPageDetail,\n getJmpLandingPages,\n getJmpLandingPageSitemap,\n getJmpPopularPages,\n getJmpRobotsTxt,\n getJmpSiteProfile,\n getJmpTrustBundle,\n registerJmpContentWrappers,\n} from \"./api\"\nimport type { JmpContentConfig } from \"../types\"\n\nexport function createJmpContentClient(config: JmpContentConfig) {\n return {\n getBlogPosts: (filters?: { locale?: string }) => getJmpBlogPosts(config, filters),\n getBlogPost: (slug: string, locale?: string) => getJmpBlogPost(config, slug, locale),\n getFaqs: (filters?: { locale?: string }) => getJmpFaqs(config, filters),\n getLegalDocument: (slug: string) => getJmpLegalDocument(config, slug),\n getLegalDocuments: () => getJmpLegalDocuments(config),\n getLandingPages: (filters?: Parameters<typeof getJmpLandingPages>[1]) =>\n getJmpLandingPages(config, filters),\n getLandingPageDetail: (\n kind: Parameters<typeof getJmpLandingPageDetail>[1],\n slug: string,\n locale?: string\n ) => getJmpLandingPageDetail(config, kind, slug, locale),\n getLandingPageSitemap: () => getJmpLandingPageSitemap(config),\n getTrustBundle: () => getJmpTrustBundle(config),\n getSiteProfile: () => getJmpSiteProfile(config),\n getRobotsTxt: () => getJmpRobotsTxt(config),\n getPopularPages: (filters?: Parameters<typeof getJmpPopularPages>[1]) =>\n getJmpPopularPages(config, filters),\n registerContentWrappers: () => registerJmpContentWrappers(config),\n }\n}\n\nexport type JmpContentClient = ReturnType<typeof createJmpContentClient>\n","import {\n createJmpAnalytics,\n type JmpAnalytics,\n} from \"../tracker/create-jmp-analytics\"\nimport { DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS } from \"../constants\"\nimport { readJmpPublicEnvFromProcess } from \"../env-public\"\nimport { getJmpSiteDefinition } from \"../site-config\"\nimport type { JmpAnalyticsConfig, JmpContentConfig } from \"../types\"\nimport { createJmpContentClient, type JmpContentClient } from \"../content/client\"\n\n/**\n * Browser / client bundle: reads `NEXT_PUBLIC_*` or Astro `PUBLIC_*` vars.\n * Use for `createJmpAnalytics` on the client. Returns `null` if incomplete.\n */\nexport function getJmpBrowserAnalyticsConfigFromEnv(\n overrides?: Partial<JmpAnalyticsConfig>\n): JmpAnalyticsConfig | null {\n const pub = readJmpPublicEnvFromProcess()\n const site = getJmpSiteDefinition()\n const baseUrl =\n overrides?.baseUrl ?? pub.analyticsUrl ?? site?.analyticsPortalUrl\n const trackingKey = overrides?.trackingKey ?? pub.trackingKey\n if (!baseUrl || !trackingKey) return null\n return {\n baseUrl,\n trackingKey,\n pageViewDedupeMs: DEFAULT_JMP_BROWSER_PAGE_VIEW_DEDUPE_MS,\n ...overrides,\n requireConsent: overrides?.requireConsent ?? pub.requireConsent,\n autoTrackContactLinks:\n overrides?.autoTrackContactLinks ?? pub.autoContactLinks,\n }\n}\n\n/**\n * Server / Node (SSR, Route Handlers, `getStaticProps`, etc.):\n * Same **`NEXT_PUBLIC_*`** vars as the browser (`NEXT_PUBLIC_JMP_ANALYTICS_URL` +\n * `NEXT_PUBLIC_JMP_TRACKING_KEY`). Next.js injects these on the server for RSC/fetches.\n * Returns `null` if incomplete.\n */\nexport function getJmpServerContentConfigFromEnv(\n overrides?: Partial<JmpContentConfig>\n): JmpContentConfig | null {\n const pub = readJmpPublicEnvFromProcess()\n const baseUrl = overrides?.baseUrl ?? pub.analyticsUrl\n const trackingKey = overrides?.trackingKey ?? pub.trackingKey\n if (!baseUrl || !trackingKey) return null\n return { baseUrl, trackingKey, ...overrides }\n}\n\nexport function isJmpBrowserAnalyticsEnvConfigured(): boolean {\n const pub = readJmpPublicEnvFromProcess()\n return Boolean(pub.analyticsUrl && pub.trackingKey)\n}\n\nexport function isJmpServerContentEnvConfigured(): boolean {\n return isJmpBrowserAnalyticsEnvConfigured()\n}\n\nlet jmpAnalyticsBrowserSingleton: JmpAnalytics | null = null\n\n/**\n * One `JmpAnalytics` instance per browser tab (module singleton). Safe for page views and events.\n * Returns `null` on the server or when public env vars are missing.\n */\nexport function getOrCreateJmpAnalyticsFromBrowserEnv(\n overrides?: Partial<JmpAnalyticsConfig>\n): JmpAnalytics | null {\n if (typeof window === \"undefined\") return null\n if (jmpAnalyticsBrowserSingleton) return jmpAnalyticsBrowserSingleton\n const config = getJmpBrowserAnalyticsConfigFromEnv(overrides)\n if (!config) return null\n jmpAnalyticsBrowserSingleton = createJmpAnalytics(config)\n return jmpAnalyticsBrowserSingleton\n}\n\n/**\n * `createJmpContentClient` using server env resolution. Returns `null` if env is incomplete.\n */\nexport function createJmpContentClientFromServerEnv(\n overrides?: Partial<JmpContentConfig>\n): JmpContentClient | null {\n const config = getJmpServerContentConfigFromEnv(overrides)\n if (!config) return null\n return createJmpContentClient(config)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B;AAEhC,IAAM,6BAA6B;AACnC,IAAM,sBAAsB;AAEnC,IAAM,qCAAqC,KAAK;AAEzC,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,mBAAmB,SAAgC;AAC1D,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI;AACF,WAAO,IAAI,IAAI,OAAO,EAAE,SAAS,QAAQ,WAAW,EAAE,EAAE,YAAY;AAAA,EACtE,QAAQ;AACN,QAAI;AACF,aAAO,IAAI,IAAI,WAAW,OAAO,EAAE,EAAE,SAClC,QAAQ,WAAW,EAAE,EACrB,YAAY;AAAA,IACjB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEO,SAAS,sBACd,SACA,cACS;AACT,QAAM,UAAU,mBAAmB,OAAO;AAC1C,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,QAAM,OAAO,aAAa,QAAQ,WAAW,EAAE,EAAE,YAAY;AAC7D,SAAO,YAAY,QAAQ,CAAC,QAAQ,SAAS,IAAI,IAAI,EAAE;AACzD;AAGO,SAAS,sBAAsB,cAAqC;AACzE,QAAM,OAAO,aAAa,QAAQ,WAAW,EAAE,EAAE,YAAY;AAC7D,MAAI,CAAC,QAAQ,SAAS,eAAe,KAAK,SAAS,QAAQ,GAAG;AAC5D,WAAO;AAAA,EACT;AACA,MAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,yBAAyB,cAAqC;AAC5E,MAAI,OAAO,aAAa,aAAa;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,sBAAsB,YAAY;AAC/C,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,GAAG,0BAA0B;AAC5C,aAAW,QAAQ,SAAS,OAAO,MAAM,GAAG,GAAG;AAC7C,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,QAAQ,WAAW,MAAM,GAAG;AAC/B;AAAA,IACF;AACA,QAAI;AACF,YAAM,QAAQ,mBAAmB,QAAQ,MAAM,OAAO,MAAM,CAAC,EAAE,KAAK;AACpE,aAAO,MAAM,SAAS,IAAI,QAAQ;AAAA,IACpC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,0BACd,SACA,cACM;AACN,MAAI,OAAO,aAAa,aAAa;AACnC;AAAA,EACF;AAEA,QAAM,OAAO,sBAAsB,YAAY;AAC/C,MAAI,CAAC,MAAM;AACT;AAAA,EACF;AAEA,QAAM,QAAQ,mBAAmB,QAAQ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;AAC9D,QAAM,SACJ,OAAO,WAAW,eAAe,OAAO,SAAS,aAAa,WAC1D,aACA;AAEN,WAAS,SAAS,GAAG,0BAA0B,IAAI,KAAK,aAAa,IAAI,qBAAqB,kCAAkC,iBAAiB,MAAM;AACzJ;AAEO,SAAS,0BAA0B,cAGxC;AACA,MAAI,OAAO,aAAa,eAAe,OAAO,WAAW,aAAa;AACpE,WAAO,EAAE,gBAAgB,MAAM,KAAK,CAAC,EAAE;AAAA,EACzC;AAEA,MAAI,iBAAgC;AACpC,MAAI,MAA8B,CAAC;AAEnC,MAAI;AACF,UAAM,gBACJ,eAAe,QAAQ,uBAAuB,GAAG,KAAK,KAAK;AAC7D,UAAM,gBAAgB,yBAAyB,YAAY;AAC3D,UAAM,mBAAmB,iBAAiB;AAC1C,UAAM,iBAAiB,SAAS,UAAU,KAAK,KAAK;AAEpD,QACE,kBACA,sBAAsB,gBAAgB,YAAY,GAClD;AACA,qBAAe,QAAQ,yBAAyB,cAAc;AAC9D,gCAA0B,gBAAgB,YAAY;AACtD,uBAAiB;AAAA,IACnB,WAAW,kBAAkB;AAC3B,uBAAiB;AACjB,UAAI,CAAC,eAAe;AAClB,uBAAe,QAAQ,yBAAyB,gBAAgB;AAAA,MAClE;AAAA,IACF;AAEA,UAAM,SAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM;AACzD,UAAM,SAAS,eAAe,QAAQ,mBAAmB;AACzD,QAAI,QAAQ;AACV,YAAM,SAAS,KAAK,MAAM,MAAM;AAChC,UAAI,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,GAAG;AAClE,cAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,UAAU;AACd,eAAW,OAAO,oBAAoB;AACpC,YAAM,QAAQ,OAAO,IAAI,GAAG,GAAG,KAAK;AACpC,UAAI,OAAO;AACT,YAAI,GAAG,IAAI;AACX,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,QAAI,SAAS;AACX,qBAAe,QAAQ,qBAAqB,KAAK,UAAU,GAAG,CAAC;AAAA,IACjE;AAAA,EACF,QAAQ;AAAA,EACR;AAEA,SAAO,EAAE,gBAAgB,IAAI;AAC/B;AAEO,SAAS,kCAAsD;AACpE,MAAI,OAAO,WAAW,eAAe,CAAC,WAAW,QAAQ,YAAY;AACnE,WAAO;AAAA,EACT;AACA,MAAI;AACF,QAAI,KAAK,eAAe,QAAQ,kBAAkB;AAClD,QAAI,CAAC,IAAI;AACP,WAAK,OAAO,WAAW;AACvB,qBAAe,QAAQ,oBAAoB,EAAE;AAAA,IAC/C;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,kCAA0C;AACxD,QAAM,eAAe,OAAO,kCAAkC;AAE9D,SAAO,qnBAAqnB,0BAA0B,iVAAiV,0BAA0B,+EAA+E,YAAY,0DAA0D,uBAAuB,wGAAwG,uBAAuB,6FAA6F,uBAAuB,yCAAyC,kBAAkB,0FAA0F,kBAAkB,iQAAiQ,mBAAmB;AAC71D;;;AChKO,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB,CAAC,SAAS,oBAAoB,cAAc;AAE5D,SAAS,gBAAgB,MAAc,SAA0B;AACtE,QAAM,IAAI,KAAK,YAAY;AAC3B,QAAM,IAAI,QAAQ,YAAY;AAC9B,SAAO,MAAM,KAAK,EAAE,SAAS,IAAI,CAAC,EAAE;AACtC;AAEA,SAAS,WAAW,MAAc,UAA2B;AAC3D,MAAI,gBAAgB,MAAM,gBAAgB,GAAG;AAC3C,WAAO;AAAA,EACT;AACA,MAAI,gBAAgB,MAAM,iBAAiB,GAAG;AAC5C,WAAO;AAAA,EACT;AACA,MAAI,gBAAgB,MAAM,YAAY,KAAK,gBAAgB,MAAM,WAAW,GAAG;AAC7E,WAAO,aAAa,WAAW,SAAS,WAAW,QAAQ,KAAK,SAAS,WAAW,QAAQ;AAAA,EAC9F;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAAc,UAA2B;AAC/D,aAAW,WAAW,gBAAgB;AACpC,QAAI,CAAC,gBAAgB,MAAM,OAAO,GAAG;AACnC;AAAA,IACF;AACA,QAAI,YAAY,gBAAgB;AAC9B,aAAO,SAAS,WAAW,OAAO;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,cAAc,MAAuB;AAC5C,aAAW,WAAW,oBAAoB;AACxC,QAAI,gBAAgB,MAAM,OAAO,GAAG;AAClC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,oBAAoB,MAA4C;AAC9E,QAAM,MAAM,KAAK,KAAK;AACtB,MAAI,CAAC,OAAO,IAAI,WAAW,GAAG,KAAK,IAAI,WAAW,aAAa,GAAG;AAChE,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,IAAI,YAAY;AAE9B,MAAI,MAAM,WAAW,MAAM,GAAG;AAC5B,WAAO,EAAE,MAAM,OAAO;AAAA,EACxB;AACA,MAAI,MAAM,WAAW,SAAS,GAAG;AAC/B,WAAO,EAAE,MAAM,QAAQ;AAAA,EACzB;AACA,MAAI,MAAM,WAAW,MAAM,KAAK,MAAM,WAAW,QAAQ,GAAG;AAC1D,WAAO,EAAE,MAAM,iBAAiB,SAAS,OAAO,UAAU,KAAK;AAAA,EACjE;AACA,MAAI,MAAM,WAAW,MAAM,GAAG;AAC5B,WAAO,EAAE,MAAM,iBAAiB,SAAS,QAAQ,UAAU,KAAK;AAAA,EAClE;AAGA,MAAI,IAAI,WAAW,GAAG,KAAK,IAAI,WAAW,GAAG,GAAG;AAC9C,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,GAAG;AAAA,EACnB,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI,IAAI,aAAa,WAAW,IAAI,aAAa,UAAU;AACzD,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,IAAI,SAAS,YAAY;AACtC,QAAM,WAAW,IAAI,SAAS,YAAY;AAE1C,MAAI,eAAe,MAAM,QAAQ,GAAG;AAClC,WAAO,EAAE,MAAM,iBAAiB,SAAS,YAAY,UAAU,KAAK;AAAA,EACtE;AACA,MAAI,WAAW,MAAM,QAAQ,GAAG;AAC9B,WAAO,EAAE,MAAM,iBAAiB,SAAS,QAAQ,UAAU,KAAK;AAAA,EAClE;AACA,MAAI,cAAc,IAAI,GAAG;AACvB,WAAO,EAAE,MAAM,iBAAiB,SAAS,WAAW,UAAU,KAAK;AAAA,EACrE;AAEA,SAAO;AACT;AAGO,SAAS,iBAAiB,MAA6B;AAC5D,QAAM,MAAM,KAAK,KAAK;AACtB,MAAI,CAAC,IAAI,YAAY,EAAE,WAAW,MAAM,GAAG;AACzC,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AAAA,IACb,IAAI,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,EAC/C,EAAE,KAAK;AACP,SAAO,UAAU;AACnB;AAGO,SAAS,oBAAoB,MAA6B;AAC/D,QAAM,MAAM,KAAK,KAAK;AACtB,MAAI,CAAC,IAAI,YAAY,EAAE,WAAW,SAAS,GAAG;AAC5C,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AAAA,IACb,IAAI,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,EAC/C,EAAE,KAAK;AACP,SAAO,UAAU;AACnB;;;ACnLE,cAAW;;;ACCN,IAAM,4BAA4B;AAGlC,IAAM,mCAAmC;AAGzC,IAAM,0CAA0C;AAMhD,IAAM,wBAAwB;AAG9B,IAAM,iCAAiC;;;ACf9C,IAAI,+BAA+B;AACnC,IAAM,2BAA2B,oBAAI,IAAgB;AAErD,SAAS,4BAAqC;AAC5C,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AACA,MAAI;AACF,WACE,aAAa,QAAQ,gCAAgC,MAAM;AAAA,EAE/D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,uBAAuB,gBAA2C;AAChF,iCAA+B,iBAC3B,0BAA0B,IAC1B;AACN;AAGO,SAAS,8BAAuC;AACrD,SAAO;AACT;AAGO,SAAS,4BAA4B,UAAkC;AAC5E,2BAAyB,IAAI,QAAQ;AACrC,SAAO,MAAM;AACX,6BAAyB,OAAO,QAAQ;AAAA,EAC1C;AACF;AAMO,SAAS,sBAAsB,SAAwB;AAC5D,MAAI,iCAAiC,SAAS;AAC5C;AAAA,EACF;AACA,iCAA+B;AAC/B,MAAI,OAAO,WAAW,aAAa;AACjC,QAAI;AACF,mBAAa;AAAA,QACX;AAAA,QACA,UAAU,YAAY;AAAA,MACxB;AAAA,IACF,QAAQ;AAAA,IAER;AACA,QAAI,SAAS;AACX,gCAA0B,OAAO,SAAS,QAAQ;AAAA,IACpD;AAAA,EACF;AACA,aAAW,YAAY,0BAA0B;AAC/C,aAAS;AAAA,EACX;AACF;;;AChEO,IAAM,mCAAmC;AAEhD,IAAI,iBAAiB;AACrB,IAAI,eAAe;AAMZ,SAAS,4BACd,UACA,UACA,UAAuD,MAC9C;AACT,MAAI,YAAY,GAAG;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,KAAK,IAAI;AACrB,MAAI,aAAa,kBAAkB,MAAM,eAAe,UAAU;AAChE,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,MAAM,SAAS,QAAQ,gCAAgC;AAC7D,QAAI,KAAK;AACP,YAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,UAAI,KAAK,SAAS,YAAY,MAAM,KAAK,KAAK,UAAU;AACtD,eAAO;AAAA,MACT;AAAA,IACF;AACA,aAAS;AAAA,MACP;AAAA,MACA,KAAK,UAAU,EAAE,MAAM,UAAU,IAAI,IAAI,CAAC;AAAA,IAC5C;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,mBAAiB;AACjB,iBAAe;AACf,SAAO;AACT;;;ACvCO,SAAS,sBAAsB,MAAuB;AAC3D,QAAM,IAAI,KAAK,UAAU;AACzB,SACE,EAAE,WAAW,IAAI,KACjB,EAAE,YAAY,EAAE,WAAW,OAAO,KACjC,EAAE,WAAW,GAAG,KAAK,cAAc,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;AAE5D;AAEO,SAAS,iBAAiB,SAAyB;AACxD,SAAO,QAAQ,QAAQ,OAAO,EAAE;AAClC;AAEO,SAAS,UACd,SACA,KACe;AACf,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,MAAI,OAAQ,QAAiC,QAAQ,YAAY;AAC/D,WAAQ,QAAiC,IAAI,GAAG;AAAA,EAClD;AACA,QAAM,SAAS;AACf,QAAM,SAAS,OAAO,GAAG,KAAK,OAAO,IAAI,YAAY,CAAC;AACtD,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,WAAO,OAAO,CAAC,KAAK;AAAA,EACtB;AACA,SAAO,UAAU;AACnB;AAEO,SAAS,mBAAmB,KAAiC;AAClE,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,IAAI,IAAI,IAAI,GAAG;AACrB,WAAO,GAAG,EAAE,QAAQ,GAAG,EAAE,MAAM;AAAA,EACjC,QAAQ;AACN,WAAO,IAAI,WAAW,GAAG,IAAI,MAAM;AAAA,EACrC;AACF;AAEO,SAAS,aACd,WACA,SACc;AACd,QAAM,WACJ,cACC,OAAO,eAAe,eAAe,WAAW,QAC7C,WAAW,MAAM,KAAK,UAAU,IAChC;AACN,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,GAAG,OAAO,oDAAoD;AAAA,EAChF;AACA,SAAO;AACT;AASO,SAAS,sBACd,QACA,MACA,QACQ;AACR,MAAI,sBAAsB,IAAI,GAAG;AAC/B,WAAO,GAAG,MAAM,SAAS,MAAM;AAAA,EACjC;AACA,MAAI,SAAuB,CAAC;AAC5B,MAAI;AACF,aAAS,KAAK,MAAM,IAAI;AAAA,EAC1B,QAAQ;AACN,aAAS,EAAE,OAAO,KAAK;AAAA,EACzB;AACA,QAAM,SAAS,OAAO,SAAS;AAC/B,SAAO;AAAA,IACL,GAAG,MAAM,SAAS,MAAM;AAAA,IACxB,OAAO,OAAO,IAAI,OAAO,IAAI,MAAM;AAAA,IACnC;AAAA,IACA,OAAO,OAAO,SAAS,OAAO,IAAI,KAAK;AAAA,IACvC,OAAO,iBACH,wBAAwB,OAAO,cAAc,KAC7C;AAAA,EACN,EACG,OAAO,OAAO,EACd,KAAK,UAAK;AACf;;;ACzFO,SAAS,8BAA6C;AAC3D,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AACA,SAAO,0BAA0B,OAAO,SAAS,QAAQ,EAAE;AAC7D;AAEO,SAAS,iBAAiB,UAAmC;AAClE,MAAI,OAAO,WAAW,aAAa;AACjC;AAAA,EACF;AACA,QAAM,EAAE,IAAI,IAAI,0BAA0B,OAAO,SAAS,QAAQ;AAClE,aAAW,OAAO,oBAAoB;AACpC,QAAI,SAAS,GAAG,MAAM,UAAa,IAAI,GAAG,GAAG;AAC3C,eAAS,GAAG,IAAI,IAAI,GAAG;AAAA,IACzB;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,WAGjC;AACA,QAAM,SAAS,UAAU,QAAQ,GAAG;AACpC,MAAI,WAAW,IAAI;AACjB,WAAO,EAAE,UAAU,aAAa,KAAK,QAAQ,GAAG;AAAA,EAClD;AACA,SAAO;AAAA,IACL,UAAU,UAAU,MAAM,GAAG,MAAM,KAAK;AAAA,IACxC,QAAQ,UAAU,MAAM,SAAS,CAAC;AAAA,EACpC;AACF;AAEO,SAAS,cAAsB;AACpC,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AACA,SAAO,OAAO,aAAa,MAAM,WAAW;AAC9C;;;ACXO,SAAS,mBAAmB,QAA4B;AAC7D,QAAM,UAAU,iBAAiB,OAAO,OAAO;AAC/C,QAAM,UAAU,aAAa,OAAO,WAAW,oBAAoB;AAEnE,yBAAuB,OAAO,cAAc;AAE5C,WAAS,UAAmB;AAC1B,WAAO,4BAA4B;AAAA,EACrC;AAEA,iBAAe,KAAK,MAA+B;AACjD,QAAI,CAAC,QAAQ,GAAG;AACd;AAAA,IACF;AAEA,UAAM,MAAM,GAAG,OAAO;AACtB,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,sBAAsB,OAAO;AAAA,IAC/B;AAEA,QAAI,KAAK,SAAS,eAAe,OAAO,WAAW,aAAa;AAC9D,YAAM,iBAAiB,4BAA4B;AACnD,UAAI,gBAAgB;AAClB,gBAAQ,uBAAuB,IAAI;AAAA,MACrC;AAAA,IACF;AAEA,UAAM,MAAM,gCAAgC;AAC5C,UAAM,UAAU,EAAE,GAAG,MAAM,GAAI,MAAM,EAAE,WAAW,IAAI,IAAI,CAAC,EAAG;AAE9D,QAAI,OAAO,OAAO;AAChB,cAAQ,MAAM,iCAAiC,QAAQ,KAAK,OAAO;AAAA,IACrE;AAEA,UAAM,MAAM,MAAM,QAAQ,KAAK;AAAA,MAC7B,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,MAC5B,WAAW;AAAA,IACb,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAM,UAAU,sBAAsB,IAAI,QAAQ,MAAM,eAAe;AACvE,UAAI,OAAO,OAAO;AAChB,gBAAQ,MAAM,iCAAiC,kBAAkB,EAAE,QAAQ,IAAI,QAAQ,KAAK,KAAK,CAAC;AAAA,MACpG;AACA,YAAM,IAAI,MAAM,OAAO;AAAA,IACzB;AAAA,EACF;AAEA,iBAAe,SAAS,MAA+B;AACrD,QAAI,CAAC,QAAQ,GAAG;AACd;AAAA,IACF;AAEA,UAAM,MAAM,GAAG,OAAO;AACtB,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,sBAAsB,OAAO;AAAA,IAC/B;AAEA,UAAM,MAAM,gCAAgC;AAC5C,UAAM,UAAU,EAAE,GAAG,MAAM,GAAI,MAAM,EAAE,WAAW,IAAI,IAAI,CAAC,EAAG;AAE9D,QAAI,OAAO,OAAO;AAChB,cAAQ,MAAM,iCAAiC,QAAQ,KAAK,OAAO;AAAA,IACrE;AAEA,UAAM,MAAM,MAAM,QAAQ,KAAK;AAAA,MAC7B,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,MAC5B,WAAW;AAAA,IACb,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAM,UAAU,sBAAsB,IAAI,QAAQ,MAAM,eAAe;AACvE,UAAI,OAAO,OAAO;AAChB,gBAAQ,MAAM,iCAAiC,kBAAkB,EAAE,QAAQ,IAAI,QAAQ,KAAK,KAAK,CAAC;AAAA,MACpG;AACA,YAAM,IAAI,MAAM,OAAO;AAAA,IACzB;AAAA,EACF;AAEA,WAAS,cAAc,SAAgC;AACrD,QAAI,CAAC,QAAQ,GAAG;AACd,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,UAAM,kBAAkB,SAAS,MAAM,KAAK;AAC5C,QAAI,WAAW;AACf,QAAI,SAAS;AAEb,QAAI,iBAAiB;AACnB,YAAM,QAAQ,mBAAmB,eAAe;AAChD,iBAAW,MAAM;AACjB,eAAS,MAAM;AAAA,IACjB,WAAW,OAAO,WAAW,aAAa;AACxC,iBAAW,OAAO,SAAS;AAC3B,eAAS,OAAO,SAAS,OAAO,QAAQ,OAAO,EAAE;AAAA,IACnD;AAEA,QAAI,CAAC,UAAU,OAAO,WAAW,aAAa;AAC5C,eAAS,OAAO,SAAS,OAAO,QAAQ,OAAO,EAAE;AAAA,IACnD;AAEA,UAAM,OAAO,SAAS,GAAG,QAAQ,IAAI,MAAM,KAAK;AAEhD,UAAM,WACJ,OAAO,oBAAoB;AAC7B,UAAM,UACJ,OAAO,WAAW,cAAc,OAAO,iBAAiB;AAC1D,QAAI,4BAA4B,UAAU,UAAU,OAAO,GAAG;AAC5D,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,UAAM,WACJ,SAAS,YAAY,OAAO,QAAQ,aAAa,WAC7C,EAAE,GAAG,QAAQ,SAAS,IACtB,CAAC;AAEP,QAAI,OAAO,WAAW,aAAa;AACjC,eAAS,eAAe,OAAO,SAAS;AACxC,YAAM,SAAS,IAAI;AAAA,QACjB,SAAS,IAAI,MAAM,KAAK,OAAO,SAAS;AAAA,MAC1C;AACA,iBAAW,OAAO,oBAAoB;AACpC,cAAM,IAAI,OAAO,IAAI,GAAG;AACxB,YAAI,KAAK,SAAS,GAAG,MAAM,QAAW;AACpC,mBAAS,GAAG,IAAI;AAAA,QAClB;AAAA,MACF;AACA,uBAAiB,QAAQ;AACzB,YAAM,iBAAiB,4BAA4B;AACnD,UAAI,kBAAkB,SAAS,YAAY,QAAW;AACpD,iBAAS,UAAU;AAAA,MACrB;AAAA,IACF;AAEA,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd,QAAQ,SAAS,UAAU,YAAY;AAAA,MACvC,SAAS,SAAS;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAAS,gBACP,MACA,UACA;AACA,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd,UAAU,YAAY,CAAC;AAAA,IACzB,CAAC;AAAA,EACH;AAEA,WAAS,eACP,MACA,UACA;AACA,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd,UAAU,YAAY,CAAC;AAAA,IACzB,CAAC;AAAA,EACH;AAEA,WAAS,gBACP,MACA,UACA;AACA,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd,UAAU,YAAY,CAAC;AAAA,IACzB,CAAC;AAAA,EACH;AAEA,WAAS,kBACP,MACA,SAKA;AACA,UAAM,WAAoC;AAAA,MACxC,GAAI,QAAQ,YAAY,OAAO,QAAQ,aAAa,WAChD,QAAQ,WACR,CAAC;AAAA,MACL,SAAS,QAAQ;AAAA,IACnB;AACA,QAAI,QAAQ,UAAU;AACpB,eAAS,WAAW,QAAQ;AAAA,IAC9B;AACA,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAAS,UAAU,SAA4B;AAC7C,UAAM,OACJ,SAAS,SACR,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAE9D,UAAM,OAAgC,EAAE,MAAM,QAAQ,IAAI;AAC1D,QAAI,SAAS,KAAM,MAAK,OAAO,QAAQ;AACvC,QAAI,SAAS,MAAO,MAAK,QAAQ,QAAQ;AACzC,QAAI,SAAS,MAAO,MAAK,QAAQ,QAAQ;AACzC,QAAI,SAAS,QAAS,MAAK,UAAU,QAAQ;AAC7C,QAAI,SAAS,QAAS,MAAK,UAAU,QAAQ;AAC7C,QAAI,SAAS,QAAS,MAAK,UAAU,QAAQ;AAC7C,QAAI,SAAS,QAAS,MAAK,UAAU,QAAQ;AAC7C,QAAI,SAAS,YAAY,OAAO,QAAQ,aAAa,UAAU;AAC7D,WAAK,WAAW,QAAQ;AAAA,IAC1B;AACA,QAAI,SAAS,UAAW,MAAK,YAAY,QAAQ;AAEjD,WAAO,SAAS,IAAI;AAAA,EACtB;AAEA,WAAS,MACP,MACA,SAOA;AACA,QAAI,SAAS,aAAa;AACxB,aAAO,cAAc;AAAA,QACnB,MAAM,QAAQ;AAAA,QACd,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA,QAChB,SAAS,QAAQ;AAAA,QACjB,UAAU,QAAQ;AAAA,MACpB,CAAC;AAAA,IACH;AACA,QAAI,SAAS,eAAe;AAC1B,aAAO,gBAAgB,QAAQ,MAAM,QAAQ,QAAQ;AAAA,IACvD;AACA,QAAI,SAAS,cAAc;AACzB,aAAO,eAAe,QAAQ,MAAM,QAAQ,QAAQ;AAAA,IACtD;AACA,QAAI,SAAS,eAAe;AAC1B,aAAO,gBAAgB,QAAQ,MAAM,QAAQ,QAAQ;AAAA,IACvD;AACA,UAAM,OAAO,QAAQ,YAAY,CAAC;AAClC,UAAM,UAAU,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAClE,UAAM,WACJ,OAAO,KAAK,aAAa,WAAY,KAAK,WAAsB;AAClE,QACE,YAAY,SACZ,YAAY,cACZ,YAAY,UACZ,YAAY,WACZ;AACA,aAAO,QAAQ,QAAQ;AAAA,IACzB;AACA,WAAO,kBAAkB,QAAQ,MAAM;AAAA,MACrC;AAAA,MACA;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAOA,WAAS,2BAAuC;AAC9C,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAEA,QAAI,WAAW,OAAO,SAAS;AAE/B,UAAM,MAAM,MAAM;AAChB,YAAM,OAAO,OAAO,SAAS;AAC7B,UAAI,SAAS,UAAU;AACrB,mBAAW;AACX,aAAK,cAAc,EAAE,KAAK,CAAC;AAAA,MAC7B;AAAA,IACF;AAEA,WAAO,iBAAiB,YAAY,GAAG;AAEvC,UAAM,OAAO,QAAQ,UAAU,KAAK,OAAO;AAC3C,UAAM,UAAU,QAAQ,aAAa,KAAK,OAAO;AAEjD,YAAQ,YAAY,IAAI,SAA2C;AACjE,YAAM,IAAI,KAAK,GAAG,IAAI;AACtB,qBAAe,GAAG;AAClB,aAAO;AAAA,IACT;AACA,YAAQ,eAAe,IAAI,SAA8C;AACvE,YAAM,IAAI,QAAQ,GAAG,IAAI;AACzB,qBAAe,GAAG;AAClB,aAAO;AAAA,IACT;AAEA,WAAO,MAAM;AACX,aAAO,oBAAoB,YAAY,GAAG;AAC1C,cAAQ,YAAY;AACpB,cAAQ,eAAe;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,sBAAsB;AAC1B,MAAI,qBAAqB;AAOzB,WAAS,gCAA4C;AACnD,QAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAEA,UAAM,UAAU,CAAC,UAAsB;AACrC,UAAI,CAAC,QAAQ,GAAG;AACd;AAAA,MACF;AACA,YAAM,SAAS,MAAM;AACrB,UAAI,EAAE,kBAAkB,UAAU;AAChC;AAAA,MACF;AACA,YAAM,SAAS,OAAO,QAAQ,SAAS;AACvC,UAAI,EAAE,kBAAkB,oBAAoB;AAC1C;AAAA,MACF;AACA,UACE,OAAO,QAAQ,qBAAqB,KACpC,OAAO,QAAQ,oBAAoB,GACnC;AACA;AAAA,MACF;AAEA,YAAM,OAAO,OAAO,aAAa,MAAM,KAAK;AAC5C,YAAM,aAAa,oBAAoB,IAAI;AAC3C,UAAI,CAAC,YAAY;AACf;AAAA,MACF;AAEA,YAAM,OAAO,OAAO,SAAS;AAE7B,UAAI,WAAW,SAAS,QAAQ;AAC9B,YAAI,mBAAmB,cAAc,IAAI,EAAE,GAAG;AAC5C;AAAA,QACF;AACA,cAAM,gBAAgB,iBAAiB,IAAI;AAC3C,aAAK;AAAA,UACH;AAAA,UACA,gBAAgB,EAAE,cAAc,IAAI;AAAA,QACtC;AACA;AAAA,MACF;AACA,UAAI,WAAW,SAAS,SAAS;AAC/B,YAAI,mBAAmB,eAAe,IAAI,EAAE,GAAG;AAC7C;AAAA,QACF;AACA,cAAM,gBAAgB,oBAAoB,IAAI;AAC9C,aAAK;AAAA,UACH;AAAA,UACA,gBAAgB,EAAE,cAAc,IAAI;AAAA,QACtC;AACA;AAAA,MACF;AACA,UAAI,mBAAmB,iBAAiB,WAAW,OAAO,IAAI,IAAI,EAAE,GAAG;AACrE;AAAA,MACF;AACA,WAAK,kBAAkB,MAAM;AAAA,QAC3B,SAAS,WAAW;AAAA,QACpB,UAAU,WAAW;AAAA,MACvB,CAAC;AAAA,IACH;AAEA,aAAS,iBAAiB,SAAS,SAAS,EAAE,SAAS,KAAK,CAAC;AAC7D,WAAO,MAAM;AACX,eAAS,oBAAoB,SAAS,SAAS,EAAE,SAAS,KAAK,CAAyB;AAAA,IAC1F;AAAA,EACF;AAEA,WAAS,mBAAmB,KAAsB;AAChD,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,QAAQ,uBAAuB,MAAM,qBAAqB,KAAM;AAClE,aAAO;AAAA,IACT;AACA,0BAAsB;AACtB,yBAAqB;AACrB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,WAAW,eAAe,QAAQ,GAAG;AAC9C,8BAA0B,OAAO,SAAS,QAAQ;AAAA,EACpD;AAEA,MACE,OAAO,WAAW,eAClB,OAAO,yBACP,QAAQ,GACR;AACA,kCAA8B;AAAA,EAChC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,IACpB,0BAA0B;AAAA,EAC5B;AACF;;;ACncA,SAAS,gBAAgB,QAAoD;AAC3E,aAAW,KAAK,QAAQ;AACtB,QAAI,EAAG,QAAO;AAAA,EAChB;AACA,SAAO;AACT;AAGA,SAAS,iCAA4D;AACnE,MAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,KAAK;AAClD,WAAO,CAAC;AAAA,EACV;AACA,QAAM,EAAE,IAAI,IAAI;AAChB,QAAM,eAAe;AAAA,IACnB,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AACA,QAAM,cAAc;AAAA,IAClB,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AACA,QAAM,oBAAoB;AAAA,IACxB,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AACA,QAAM,iBAAiB;AAAA,IACrB,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,gBAAgB,sBAAsB;AAAA,IACtC,kBAAkB,mBAAmB;AAAA,EACvC;AACF;AAGO,SAAS,4BACd,WACc;AACd,QAAM,UAAU,+BAA+B;AAE/C,SAAO;AAAA,IACL,cAAc,aAAa,WAAW,cAAc,QAAQ,YAAY;AAAA,IACxE,aAAa,aAAa,WAAW,aAAa,QAAQ,WAAW;AAAA,IACrE,gBAAgB,WAAW,kBAAkB,QAAQ;AAAA,IACrD,kBACE,WAAW,oBAAoB,QAAQ;AAAA,EAC3C;AACF;;;ACYA,IAAI,iBAA2C;AAMxC,SAAS,cAAc,YAAkD;AAC9E,mBAAiB;AACjB,SAAO;AACT;AAEO,SAAS,uBAAiD;AAC/D,SAAO;AACT;AAGO,SAAS,sBAA+C;AAC7D,QAAM,EAAE,cAAc,YAAY,IAAI,4BAA4B;AAClE,MAAI,CAAC,gBAAgB,CAAC,aAAa;AACjC,WAAO;AAAA,EACT;AACA,QAAM,OAAO,qBAAqB;AAClC,QAAM,kBAAkB,MAAM,mBAAmB;AACjD,QAAM,eACJ,mBAAmB,gBAAgB,SAAS,IAAI,WAAW;AAC7D,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,oBAAoB,MAAM,sBAAsB;AAAA,EAClD;AACF;;;AClGO,SAAS,kBAAkB,UAAkC;AAClE,QAAM,UAAU,UAAU,KAAK,EAAE,QAAQ,OAAO,EAAE;AAClD,MAAI,QAAS,QAAO;AACpB,QAAM,aAAa,qBAAqB,GAAG,SAAS,KAAK,EAAE,QAAQ,OAAO,EAAE;AAC5E,SAAO,cAAc;AACvB;;;ACRO,SAAS,0BAAyC;AACvD,QAAM,WAAW,kBAAkB;AACnC,MAAI,UAAU;AACZ,WAAO;AAAA,EACT;AACA,MAAI,OAAO,YAAY,aAAa;AAClC,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,IAAI,sBAAsB,KAAK,EAAE,QAAQ,OAAO,EAAE,KAAK;AACxE;AAGO,SAAS,oBACd,SACwB;AACxB,QAAM,SAAS,wBAAwB;AACvC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,SAAO,EAAE,GAAG,SAAS,QAAQ,OAAO;AACtC;;;AClBA,eAAsB,uBACpB,QACA,UAAsC,CAAC,GACxB;AACf,QAAM,UAAU,iBAAiB,OAAO,OAAO;AAC/C,QAAM,gBACJ,OAAO,cACN,OAAO,eAAe,eAAe,WAAW,QAC7C,WAAW,MAAM,KAAK,UAAU,IAChC;AAEN,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC1F;AAEA,QAAM,mBACJ,QAAQ,aAAa,UAAU,QAAQ,SAAS,SAAS,YAAY;AACvE,QAAM,iBACJ,QAAQ,WAAW,UAAU,QAAQ,SAAS,SAAS,SAAS;AAClE,QAAM,OAAO,QAAQ,QAAQ,mBAAmB,QAAQ,SAAS,GAAG;AAEpE,QAAM,UAAkC,oBAAoB;AAAA,IAC1D,gBAAgB;AAAA,IAChB,sBAAsB,OAAO;AAAA,EAC/B,CAAC;AACD,MAAI,kBAAkB;AACpB,YAAQ,0BAA0B,IAAI;AAAA,EACxC;AACA,MAAI,gBAAgB;AAClB,YAAQ,uBAAuB,IAAI;AAAA,EACrC;AAEA,QAAM,UAAmC;AAAA,IACvC,MAAM;AAAA,IACN,MAAM,QAAQ;AAAA,IACd,UACE,QAAQ,YAAY,OAAO,QAAQ,aAAa,WAC5C,QAAQ,WACR,CAAC;AAAA,EACT;AACA,MAAI,QAAQ,WAAW;AACrB,YAAQ,YAAY,QAAQ;AAAA,EAC9B;AAEA,QAAM,MAAM,GAAG,OAAO;AACtB,MAAI,OAAO,OAAO;AAChB,YAAQ,MAAM,iCAAiC,QAAQ,KAAK,OAAO;AAAA,EACrE;AAEA,QAAM,MAAM,MAAM,cAAc,KAAK;AAAA,IACnC,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU,OAAO;AAAA,EAC9B,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAM,IAAI,MAAM,6BAA6B,IAAI,MAAM,WAAM,IAAI,EAAE;AAAA,EACrE;AACF;;;ACjEO,IAAM,+BAA+B;AA8F5C,IAAM,iBAAiB,oBAAI,IAAY;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,aAAa,OAAuB;AAC3C,SAAO,MACJ,KAAK,EACL,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAC3B;AAEA,SAAS,gBAAgB,KAAsB;AAC7C,SAAO,6BAA6B,KAAK,GAAG;AAC9C;AAEA,IAAM,2BAA2B;AACjC,IAAM,uCAAuC;AAC7C,IAAM,iCAAiC;AAEvC,SAAS,oBAAoB,OAA+B;AAC1D,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,GAAG;AAC9C,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC;AAChC,QAAI,IAAI,aAAa,YAAY,IAAI,aAAa,SAAS;AACzD,aAAO;AAAA,IACT;AACA,WAAO,IAAI,SAAS,EAAE,QAAQ,OAAO,EAAE;AAAA,EACzC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,+BACP,SACyC;AACzC,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,WAAO;AAAA,EACT;AACA,QAAM,WAAW,oBAAoB,QAAQ,QAAQ;AACrD,QAAM,WAAW,oBAAoB,QAAQ,QAAQ;AACrD,MAAI,CAAC,YAAY,CAAC,UAAU;AAC1B,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,EACjC;AACF;AAEA,SAAS,kCACP,OACgC;AAChC,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO,CAAC;AAAA,EACV;AACA,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,MAAsC,CAAC;AAC7C,aAAW,OAAO,OAAO;AACvB,QAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,IAAI,UAAU,0BAA0B;AAC7E;AAAA,IACF;AACA,UAAM,KACJ,OAAO,IAAI,OAAO,WACd,IAAI,GAAG,KAAK,EAAE,YAAY,EAAE,QAAQ,gBAAgB,GAAG,EAAE,QAAQ,YAAY,EAAE,IAC/E;AACN,UAAM,QACJ,OAAO,IAAI,UAAU,WACjB,IAAI,MAAM,KAAK,EAAE,MAAM,GAAG,oCAAoC,IAC9D;AACN,UAAM,MAAM,oBAAoB,IAAI,GAAG;AACvC,QACE,CAAC,MACD,CAAC,SACD,CAAC,OACD,CAAC,+BAA+B,KAAK,EAAE,KACvC,QAAQ,IAAI,EAAE,GACd;AACA;AAAA,IACF;AACA,YAAQ,IAAI,EAAE;AACd,QAAI,KAAK,EAAE,IAAI,OAAO,IAAI,CAAC;AAAA,EAC7B;AACA,SAAO;AACT;AAEA,SAAS,yBACP,iBACmC;AACnC,MAAI,CAAC,mBAAmB,OAAO,oBAAoB,UAAU;AAC3D,WAAO;AAAA,EACT;AACA,QAAM,YAAY,oBAAoB,gBAAgB,QAAQ,SAAS;AACvE,QAAM,UAAU,+BAA+B,gBAAgB,OAAO;AACtE,QAAM,QAAQ,kCAAkC,gBAAgB,KAAK;AACrE,MAAI,CAAC,aAAa,CAAC,WAAW,MAAM,WAAW,GAAG;AAChD,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,GAAI,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC;AAAA,IAC7C,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAI,MAAM,SAAS,IAAI,EAAE,MAAM,IAAI,CAAC;AAAA,EACtC;AACF;AAEO,SAAS,4BACd,OAC2B;AAC3B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,gBAAgB,MAAM,MAAM;AAC3C,QAAM,kBAAkB,yBAAyB,MAAM,eAAe;AACtE,QAAM,QAAQ,eAAe,MAAM,KAAK;AACxC,QAAM,UAAU,iBAAiB,MAAM,OAAO;AAC9C,QAAM,WAAW,0BAA0B,MAAM,QAAQ;AAEzD,MACE,OAAO,WAAW,KAClB,CAAC,mBACD,CAAC,SACD,CAAC,WACD,CAAC,UACD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,GAAI,OAAO,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,IACtC,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,IAC7C,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IACzB,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,EACjC;AACF;AAEA,SAAS,gBACP,QAC2B;AAC3B,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,WAAO,CAAC;AAAA,EACV;AACA,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAiC,CAAC;AACxC,aAAW,OAAO,QAAQ;AACxB,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,UAAM,UACJ,OAAO,IAAI,YAAY,WAAW,IAAI,QAAQ,KAAK,EAAE,YAAY,IAAI;AACvE,UAAM,UACJ,OAAO,IAAI,YAAY,WAAW,IAAI,QAAQ,KAAK,IAAI;AACzD,QAAI,CAAC,WAAW,CAAC,QAAS;AAC1B,UAAM,SAAS,GAAG,OAAO,IAAI,OAAO;AACpC,QAAI,KAAK,IAAI,MAAM,EAAG;AACtB,SAAK,IAAI,MAAM;AACf,QAAI,KAAK;AAAA,MACP;AAAA,MACA;AAAA,MACA,GAAI,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,KAAK,IAChD,EAAE,OAAO,IAAI,MAAM,KAAK,EAAE,IAC1B,CAAC;AAAA,MACL,GAAI,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,KAAK,IAChD,EAAE,OAAO,IAAI,MAAM,KAAK,EAAE,IAC1B,CAAC;AAAA,IACP,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,eACP,OACoC;AACpC,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,SAAS,qBAAqB,MAAM,MAAM;AAChD,QAAM,SAAS,qBAAqB,MAAM,MAAM;AAChD,QAAM,2BAA2B,MAAM,6BAA6B;AACpE,MAAI,OAAO,WAAW,KAAK,CAAC,UAAU,CAAC,yBAA0B,QAAO;AACxE,SAAO;AAAA,IACL,GAAI,OAAO,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,IACtC,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,2BAA2B,EAAE,0BAA0B,KAAK,IAAI,CAAC;AAAA,EACvE;AACF;AAEA,SAAS,qBACP,QACyB;AACzB,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACpC,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAA+B,CAAC;AACtC,aAAW,OAAO,QAAQ;AACxB,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,UAAM,UACJ,OAAO,IAAI,YAAY,WAAW,IAAI,QAAQ,KAAK,EAAE,YAAY,IAAI;AACvE,QAAI,CAAC,eAAe,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,EAAG;AACvD,SAAK,IAAI,OAAO;AAChB,QAAI,KAAK;AAAA,MACP;AAAA,MACA,GAAI,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,KAAK,IAChD,EAAE,OAAO,IAAI,MAAM,KAAK,EAAE,IAC1B,CAAC;AAAA,IACP,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,qBACP,QACiD;AACjD,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,MAAgD,CAAC;AACvD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,eAAe,IAAI,GAAG,KAAK,OAAO,UAAU,YAAY,MAAM,KAAK,GAAG;AACxE,UAAI,GAAsB,IAAI,MAAM,KAAK;AAAA,IAC3C;AAAA,EACF;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAC7C;AAEA,SAAS,gBAAgB,OAAgB,MAAM,KAAyB;AACtE,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,QAAQ,MAAM,GAAG,GAAG;AAC7B;AAEA,SAAS,0BACP,UACuC;AACvC,MAAI,CAAC,YAAY,OAAO,aAAa,SAAU,QAAO;AAEtD,QAAM,aAAa,SAAS;AAC5B,QAAM,UAAkE,CAAC;AACzE,MAAI,cAAc,OAAO,eAAe,UAAU;AAChD,UAAM,cAAc,gBAAgB,WAAW,aAAa,GAAG;AAC/D,UAAM,QAAQ,gBAAgB,WAAW,OAAO,GAAG;AACnD,UAAM,QAAQ,gBAAgB,WAAW,OAAO,EAAE;AAClD,UAAM,UAAU,gBAAgB,WAAW,SAAS,GAAG;AACvD,UAAM,QAAQ,gBAAgB,WAAW,OAAO,GAAG;AACnD,UAAM,cAAc,gBAAgB,WAAW,aAAa,GAAG;AAC/D,UAAM,gBAAgB,gBAAgB,WAAW,eAAe,IAAI;AACpE,UAAM,cAAc,gBAAgB,WAAW,aAAa,IAAI;AAChE,UAAM,eAAe,gBAAgB,WAAW,cAAc,IAAI;AAClE,UAAM,cAAc,gBAAgB,WAAW,aAAa,IAAI;AAChE,UAAM,OAAO,gBAAgB,WAAW,MAAM,IAAI;AAClD,UAAM,aAAa,gBAAgB,WAAW,YAAY,IAAI;AAC9D,QAAI,YAAa,SAAQ,cAAc;AACvC,QAAI,MAAO,SAAQ,QAAQ;AAC3B,QAAI,MAAO,SAAQ,QAAQ;AAC3B,QAAI,QAAS,SAAQ,UAAU;AAC/B,QAAI,MAAO,SAAQ,QAAQ;AAC3B,QAAI,YAAa,SAAQ,cAAc;AACvC,QAAI,cAAe,SAAQ,gBAAgB;AAC3C,QAAI,YAAa,SAAQ,cAAc;AACvC,QAAI,aAAc,SAAQ,eAAe;AACzC,QAAI,YAAa,SAAQ,cAAc;AACvC,QAAI,KAAM,SAAQ,OAAO;AACzB,QAAI,WAAY,SAAQ,aAAa;AACrC,QAAI,WAAW,UAAU,OAAO,WAAW,WAAW,UAAU;AAC9D,YAAM,SAAiC,CAAC;AACxC,iBAAW,CAAC,QAAQ,QAAQ,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AAClE,YAAI,OAAO,KAAK,MAAM,EAAE,UAAU,GAAI;AACtC,cAAM,MAAM,aAAa,MAAM;AAC/B,cAAM,QAAQ,gBAAgB,UAAU,GAAG;AAC3C,YAAI,OAAO,gBAAgB,GAAG,KAAK,MAAO,QAAO,GAAG,IAAI;AAAA,MAC1D;AACA,UAAI,OAAO,KAAK,MAAM,EAAE,SAAS,EAAG,SAAQ,SAAS;AAAA,IACvD;AAAA,EACF;AAEA,QAAM,MAA0D,CAAC;AACjE,MAAI,MAAM,QAAQ,SAAS,GAAG,GAAG;AAC/B,eAAW,OAAO,SAAS,KAAK;AAC9B,UAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,IAAI,UAAU,GAAI;AACzD,YAAM,WAAW,gBAAgB,IAAI,UAAU,GAAG;AAClD,YAAM,SAAS,gBAAgB,IAAI,QAAQ,GAAI;AAC/C,UAAI,CAAC,YAAY,CAAC,OAAQ;AAC1B,YAAM,WAAW,gBAAgB,IAAI,UAAU,EAAE;AACjD,UAAI,KAAK,EAAE,UAAU,QAAQ,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,QAAM,WAAW,SAAS;AAC1B,QAAM,QAA8D,CAAC;AACrE,MAAI,YAAY,OAAO,aAAa,UAAU;AAC5C,UAAM,SAAS,CACb,KACA,QACG;AACH,YAAM,QAAQ,gBAAgB,SAAS,GAAG,GAAG,GAAG;AAChD,UAAI,MAAO,OAAM,GAAG,IAAI;AAAA,IAC1B;AACA,WAAO,oBAAoB,IAAI;AAC/B,WAAO,iBAAiB,GAAG;AAC3B,WAAO,WAAW,IAAI;AACtB,WAAO,iBAAiB,IAAI;AAC5B,WAAO,cAAc,GAAI;AAAA,EAC3B;AAEA,QAAM,aAAa,OAAO,KAAK,OAAO,EAAE,SAAS;AACjD,QAAM,WAAW,OAAO,KAAK,KAAK,EAAE,SAAS;AAC7C,MAAI,CAAC,cAAc,IAAI,WAAW,KAAK,CAAC,SAAU,QAAO;AAEzD,SAAO;AAAA,IACL,GAAI,aAAa,EAAE,QAAQ,IAAI,CAAC;AAAA,IAChC,GAAI,IAAI,SAAS,IAAI,EAAE,IAAI,IAAI,CAAC;AAAA,IAChC,GAAI,WAAW,EAAE,MAAM,IAAI,CAAC;AAAA,EAC9B;AACF;AAEA,SAAS,iBACP,SACsC;AACtC,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAM,SAAS,uBAAuB,QAAQ,MAAM;AACpD,QAAM,YAAY,mBAAmB,QAAQ,SAAS;AACtD,MAAI,OAAO,WAAW,KAAK,CAAC,UAAW,QAAO;AAC9C,SAAO;AAAA,IACL,GAAI,OAAO,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,IACtC,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,EACnC;AACF;AAEA,SAAS,mBACP,KAC6B;AAC7B,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,OAAO,sBAAsB,IAAI,MAAM,CAAC;AAC9C,QAAM,SAAS,sBAAsB,IAAI,QAAQ,EAAE;AACnD,QAAM,SAAS,qBAAqB,IAAI,MAAM;AAC9C,MAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAQ,QAAO;AACxC,SAAO;AAAA,IACL,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,EAC7B;AACF;AAEA,SAAS,sBACP,KACA,KACsB;AACtB,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO;AAChC,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAgB,CAAC;AACvB,aAAW,QAAQ,KAAK;AACtB,QAAI,OAAO,SAAS,YAAY,IAAI,UAAU,IAAK;AACnD,UAAM,MAAM,KAAK,KAAK;AACtB,UAAM,QAAQ,IAAI,QAAQ,kBAAkB,EAAE,EAAE,YAAY;AAC5D,QAAI,CAAC,OAAO,CAAC,SAAS,KAAK,IAAI,KAAK,EAAG;AACvC,SAAK,IAAI,KAAK;AACd,QAAI,KAAK,GAAG;AAAA,EACd;AACA,SAAO,IAAI,SAAS,IAAI,MAAM;AAChC;AAEA,SAAS,qBACP,KACoC;AACpC,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,QAAI,OAAO,UAAU,SAAU;AAC/B,UAAM,QAAQ,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE;AACtC,UAAM,QAAQ,IAAI,KAAK;AACvB,QAAI,CAAC,SAAS,CAAC,MAAO;AACtB,QAAI,KAAK,IAAI;AAAA,EACf;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAC7C;AAEA,SAAS,uBACP,QAC2B;AAC3B,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACpC,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAiC,CAAC;AACxC,aAAW,OAAO,QAAQ;AACxB,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,UAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,MAAM,KAAK,IAAI;AACjE,UAAM,MAAM;AAAA,MACV,OAAO,IAAI,QAAQ,YAAY,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM;AAAA,IAC5D;AACA,QAAI,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,GAAG,KAAK,KAAK,IAAI,GAAG,EAAG;AAC9D,SAAK,IAAI,GAAG;AACZ,QAAI,KAAK,EAAE,KAAK,MAAM,CAAC;AAAA,EACzB;AACA,SAAO;AACT;AAEO,SAAS,6BACd,UACQ;AACR,SAAO,WAAW,KAAK,UAAU,QAAQ,IAAI;AAC/C;AAEO,SAAS,8BACd,UACU;AACV,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,SAAS,UAAU,UAAU,CAAC,GAAG;AAC1C,UAAM,IAAI,MAAM,OAAO;AAAA,EACzB;AACA,aAAW,SAAS,UAAU,OAAO,UAAU,CAAC,GAAG;AACjD,UAAM,IAAI,SAAS,MAAM,OAAO,EAAE;AAClC,UAAM,IAAI,OAAO;AAAA,EACnB;AACA,MAAI,UAAU,SAAS,QAAQ,UAAU,UAAU,SAAS,WAAW;AACrE,UAAM,IAAI,SAAS;AAAA,EACrB;AACA,SAAO,CAAC,GAAG,KAAK;AAClB;;;ACtfO,SAAS,yBACd,QACwB;AACxB,SAAO,oBAAoB;AAAA,IACzB,sBAAsB,OAAO;AAAA,EAC/B,CAAC;AACH;AAEA,eAAsB,WACpB,QACA,MACY;AACZ,QAAM,OAAO,MAAM,eAAe,QAAQ,IAAI;AAE9C,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,UAAM,UAAU,iBAAiB,OAAO,OAAO;AAC/C,UAAM,MAAM,GAAG,OAAO,GAAG,IAAI;AAC7B,UAAM,IAAI,MAAM,+BAA0B,GAAG,yBAAyB;AAAA,EACxE;AACF;AAEA,eAAsB,eACpB,QACA,MACiB;AACjB,QAAM,UAAU,iBAAiB,OAAO,OAAO;AAC/C,QAAM,gBACJ,OAAO,cACN,OAAO,eAAe,eAAe,WAAW,QAC7C,WAAW,MAAM,KAAK,UAAU,IAChC;AAEN,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AAEA,QAAM,MAAM,GAAG,OAAO,GAAG,IAAI;AAE7B,MAAI,OAAO,OAAO;AAChB,YAAQ,MAAM,iCAAiC,OAAO,GAAG;AAAA,EAC3D;AAEA,QAAM,MAAM,MAAM,cAAc,KAAK;AAAA,IACnC,QAAQ;AAAA,IACR,SAAS,yBAAyB,MAAM;AAAA,IACxC,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,MAAM,CAAC,qBAAqB;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,QAAM,OAAO,MAAM,IAAI,KAAK;AAE5B,MAAI,CAAC,IAAI,IAAI;AACX,QAAI,sBAAsB,IAAI,GAAG;AAC/B,YAAM,IAAI;AAAA,QACR,oBAAoB,IAAI,MAAM,WAAM,GAAG;AAAA,MAEzC;AAAA,IACF;AAEA,QAAI,SAA4C,CAAC;AACjD,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,eAAS,EAAE,OAAO,KAAK;AAAA,IACzB;AAEA,UAAM,IAAI;AAAA,MACR,CAAC,oBAAoB,IAAI,MAAM,IAAI,OAAO,OAAO,OAAO,IAAI,EACzD,OAAO,OAAO,EACd,KAAK,UAAK;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;;;AC/EA,IAAM,qBAAwC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,aAAa,oBAAI,IAAY;AACnC,IAAI,YAAkD;AACtD,IAAI,oBAA6C;AAEjD,IAAM,qBAAqB,oBAAI,IAAY;AAC3C,IAAI,cAAuE;AAEpE,SAAS,mBAAmB,MAAwC;AACzE,QAAM,aAAa,KAAK,KAAK,EAAE,YAAY;AAC3C,MAAI,CAAC,YAAY;AACf;AAAA,EACF;AACA,aAAW,IAAI,UAAU;AAC3B;AAEO,SAAS,wBAAwB,QAA8B;AACpE,aAAW,QAAQ,uBAAuB,MAAM,GAAG;AACjD,eAAW,IAAI,IAAI;AAAA,EACrB;AACF;AAEO,SAAS,uBAAuB,QAAkC;AACvE,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,EAAE,SAAS,cAAc,OAAO,OAAO,YAAY,IAAI;AAE7D,QAAM,aACJ,QAAQ,iBAAiB,QACzB,QAAQ,uBAAuB,QAC/B,QAAQ,QAAQ,oBAAoB,KAAK,CAAC,KAC1C,QAAQ,QAAQ,UAAU,KAAK,CAAC,KAChC,QAAQ,QAAQ,gBAAgB,KAAK,CAAC,KACtC,QAAQ,QAAQ,YAAY,KAAK,CAAC;AAEpC,MAAI,YAAY;AACd,UAAM,IAAI,eAAe;AAAA,EAC3B;AAEA,MAAI,kBAAkB;AACtB,MAAI,aAAa;AACjB,aAAW,QAAQ,cAAc;AAC/B,UAAM,SAAS,KAAK,WAAW,KAAK,EAAE,YAAY;AAClD,QAAI,WAAW,WAAW;AACxB,mBAAa;AAAA,IACf,OAAO;AACL,wBAAkB;AAAA,IACpB;AAAA,EACF;AACA,MAAI,iBAAiB;AACnB,UAAM,IAAI,oBAAoB;AAAA,EAChC;AACA,MAAI,YAAY;AACd,UAAM,IAAI,eAAe;AAAA,EAC3B;AACA,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,IAAI,aAAa;AAAA,EACzB;AACA,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,IAAI,aAAa;AAAA,EACzB;AACA,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,IAAI,mBAAmB;AAAA,EAC/B;AAEA,SAAO,iBAAiB,CAAC,GAAG,KAAK,CAAC;AACpC;AAEO,SAAS,+BAAyC;AACvD,SAAO,iBAAiB,CAAC,GAAG,UAAU,CAAC;AACzC;AAEO,SAAS,gCACd,QAC2B;AAC3B,QAAM,OAAO,qBAAqB;AAClC,QAAM,WAAW,MAAM;AACvB,QAAM,WAAW,OAAO;AACxB,QAAM,eAAe,2BAA2B,QAAQ;AACxD,MAAI,CAAC,YAAY,CAAC,cAAc;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,SAA6B;AAAA,IACjC,GAAI,YAAY,CAAC;AAAA,IACjB,UAAU;AAAA,MACR,GAAI,gBAAgB,CAAC;AAAA,MACrB,GAAI,UAAU,YAAY,CAAC;AAAA,MAC3B,SAAS;AAAA,QACP,GAAI,cAAc,WAAW,CAAC;AAAA,QAC9B,GAAI,UAAU,UAAU,WAAW,CAAC;AAAA,QACpC,QAAQ;AAAA,UACN,GAAI,cAAc,SAAS,UAAU,CAAC;AAAA,UACtC,GAAI,UAAU,UAAU,SAAS,UAAU,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL,GAAI,cAAc,SAAS,CAAC;AAAA,QAC5B,GAAI,UAAU,UAAU,SAAS,CAAC;AAAA,MACpC;AAAA,MACA,KAAK,UAAU,UAAU,KAAK,SAC1B,SAAS,SAAS,MAClB,cAAc;AAAA,IACpB;AAAA,EACF;AACA,SAAO,4BAA4B,MAAM;AAC3C;AAEA,SAAS,2BACP,UACuC;AACvC,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,UAAkE,CAAC;AACzE,MAAI,SAAS,aAAa,KAAK,EAAG,SAAQ,cAAc,SAAS,YAAY,KAAK;AAClF,MAAI,SAAS,OAAO,KAAK,EAAG,SAAQ,QAAQ,SAAS,MAAM,KAAK;AAChE,MAAI,OAAO,SAAS,UAAU,YAAY,SAAS,MAAM,KAAK,GAAG;AAC/D,YAAQ,QAAQ,SAAS,MAAM,KAAK;AAAA,EACtC;AACA,MAAI,SAAS,SAAS,KAAK,EAAG,SAAQ,UAAU,SAAS,QAAQ,KAAK;AACtE,MAAI,SAAS,OAAO,KAAK,EAAG,SAAQ,QAAQ,SAAS,MAAM,KAAK;AAChE,MAAI,SAAS,aAAa,KAAK,EAAG,SAAQ,cAAc,SAAS,YAAY,KAAK;AAClF,MAAI,SAAS,eAAe,KAAK,GAAG;AAClC,YAAQ,gBAAgB,SAAS,cAAc,KAAK;AAAA,EACtD;AACA,MAAI,SAAS,UAAU,KAAK,EAAG,SAAQ,cAAc,SAAS,SAAS,KAAK;AAC5E,MAAI,SAAS,WAAW,KAAK,EAAG,SAAQ,eAAe,SAAS,UAAU,KAAK;AAC/E,MAAI,SAAS,UAAU,KAAK,EAAG,SAAQ,cAAc,SAAS,SAAS,KAAK;AAC5E,MAAI,SAAS,GAAG,KAAK,EAAG,SAAQ,OAAO,SAAS,EAAE,KAAK;AACvD,MAAI,SAAS,SAAS,KAAK,EAAG,SAAQ,aAAa,SAAS,QAAQ,KAAK;AACzE,QAAM,QAA8D,CAAC;AACrE,MAAI,SAAS,eAAe,KAAK,GAAG;AAClC,UAAM,mBAAmB,SAAS,cAAc,KAAK;AAAA,EACvD;AACA,QAAM,aAAa,OAAO,KAAK,OAAO,EAAE,SAAS;AACjD,QAAM,WAAW,OAAO,KAAK,KAAK,EAAE,SAAS;AAC7C,MAAI,CAAC,cAAc,CAAC,SAAU,QAAO;AACrC,SAAO;AAAA,IACL,GAAI,aAAa,EAAE,QAAQ,IAAI,CAAC;AAAA,IAChC,GAAI,WAAW,EAAE,MAAM,IAAI,CAAC;AAAA,EAC9B;AACF;AAEO,SAAS,gCACd,QACU;AACV,QAAM,WAAW,OAAO,mBAAmB,CAAC;AAC5C,QAAM,OAAO,6BAA6B;AAC1C,QAAM,eAAe;AAAA,IACnB,gCAAgC,MAAM;AAAA,EACxC;AAEA,MAAI,OAAO,uBAAuB,UAAU;AAC1C,WAAO,iBAAiB,CAAC,GAAG,UAAU,GAAG,YAAY,CAAC;AAAA,EACxD;AAEA,MAAI,OAAO,uBAAuB,iBAAiB;AACjD,WAAO,iBAAiB,CAAC,GAAG,UAAU,GAAG,YAAY,CAAC;AAAA,EACxD;AAEA,QAAM,SAAS,oBAAI,IAAY,CAAC,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;AACtE,SAAO,iBAAiB,CAAC,GAAG,MAAM,CAAC;AACrC;AAEO,SAAS,2BAA2B,WAA4B;AACrE,SAAO,mBAAmB,IAAI,SAAS;AACzC;AAEO,SAAS,gCAAgC,WAAyB;AACvE,qBAAmB,IAAI,SAAS;AAClC;AAEO,SAAS,6BACd,SACM;AACN,gBAAc;AAChB;AAKO,SAAS,2BAA2B,QAAgC;AACzE,MAAI,CAAC,aAAa;AAChB;AAAA,EACF;AACA,sBAAoB;AACpB,MAAI,WAAW;AACb,iBAAa,SAAS;AAAA,EACxB;AACA,cAAY,WAAW,MAAM;AAC3B,gBAAY;AACZ,UAAM,MAAM;AACZ,wBAAoB;AACpB,QAAI,CAAC,OAAO,CAAC,aAAa;AACxB;AAAA,IACF;AACA,SAAK,YAAY,GAAG,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACtC,GAAG,GAAG;AACR;AAEO,SAAS,uCAA6C;AAC3D,aAAW,MAAM;AACjB,qBAAmB,MAAM;AACzB,gBAAc;AACd,MAAI,WAAW;AACb,iBAAa,SAAS;AACtB,gBAAY;AAAA,EACd;AACA,sBAAoB;AACtB;AAEA,SAAS,iBAAiB,OAA2B;AACnD,QAAM,QAAQ,IAAI,IAAI,mBAAmB,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;AAC5E,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACxC,UAAM,KAAK,MAAM,IAAI,CAAC,KAAK;AAC3B,UAAM,KAAK,MAAM,IAAI,CAAC,KAAK;AAC3B,QAAI,OAAO,IAAI;AACb,aAAO,KAAK;AAAA,IACd;AACA,WAAO,EAAE,cAAc,CAAC;AAAA,EAC1B,CAAC;AACH;;;AC1MA,SAAS,uBAAuB,QAAgC;AAC9D,6BAA2B,MAAM;AACnC;AAEA,eAAsB,gBACpB,QACA,SACwB;AACxB,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,SAAS,QAAQ;AACnB,WAAO,IAAI,UAAU,QAAQ,MAAM;AAAA,EACrC;AACA,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA,oBAAoB,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,EAC9C;AACA,qBAAmB,MAAM;AACzB,yBAAuB,MAAM;AAC7B,SAAO,KAAK;AACd;AAEA,eAAsB,eACpB,QACA,MACA,QAC6B;AAC7B,MAAI;AACF,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,QAAQ;AACV,aAAO,IAAI,UAAU,MAAM;AAAA,IAC7B;AACA,UAAM,QAAQ,OAAO,SAAS;AAC9B,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA,qBAAqB,mBAAmB,IAAI,CAAC,GAAG,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,IAC1E;AACA,uBAAmB,MAAM;AACzB,2BAAuB,MAAM;AAC7B,WAAO,KAAK;AAAA,EACd,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,UAAU,GAAG;AAChE,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,qBACpB,QACA,MACA,QACsD;AACtD,MAAI;AACF,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,QAAQ;AACV,aAAO,IAAI,UAAU,MAAM;AAAA,IAC7B;AACA,UAAM,QAAQ,OAAO,SAAS;AAC9B,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA,qBAAqB,mBAAmB,IAAI,CAAC,GAAG,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,IAC1E;AACA,uBAAmB,MAAM;AACzB,2BAAuB,MAAM;AAC7B,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,UAAU,GAAG;AAChE,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,WACpB,QACA,SACuB;AACvB,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,SAAS,QAAQ;AACnB,WAAO,IAAI,UAAU,QAAQ,MAAM;AAAA,EACrC;AACA,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA,oBAAoB,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,EAC9C;AACA,qBAAmB,KAAK;AACxB,yBAAuB,MAAM;AAC7B,SAAO,KAAK;AACd;AAEA,eAAsB,oBACpB,QACA,MACkC;AAClC,QAAM,MAAM,KAAK,KAAK,EAAE,YAAY;AACpC,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA,2BAA2B,mBAAmB,GAAG,CAAC;AAAA,IACpD;AACA,uBAAmB,OAAO;AAC1B,2BAAuB,MAAM;AAC7B,WAAO,KAAK;AAAA,EACd,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,UAAU,GAAG;AAChE,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,qBACpB,QAC6B;AAC7B,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACA,qBAAmB,OAAO;AAC1B,yBAAuB,MAAM;AAC7B,SAAO,KAAK;AACd;AAEA,eAAsB,gBACpB,QACA,MACA,QACqD;AACrD,MAAI;AACF,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,QAAQ;AACV,aAAO,IAAI,UAAU,MAAM;AAAA,IAC7B;AACA,UAAM,QAAQ,OAAO,SAAS;AAC9B,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA,qBAAqB,mBAAmB,IAAI,CAAC,GAAG,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,IAC1E;AACA,uBAAmB,KAAK;AACxB,2BAAuB,MAAM;AAC7B,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,UAAU,GAAG;AAChE,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,mBACpB,QACA,SAC2B;AAC3B,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,SAAS,MAAM;AACjB,WAAO,IAAI,QAAQ,QAAQ,IAAI;AAAA,EACjC;AACA,MAAI,SAAS,QAAQ;AACnB,WAAO,IAAI,UAAU,QAAQ,MAAM;AAAA,EACrC;AACA,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA,6BAA6B,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,EACvD;AACA,qBAAmB,SAAS;AAC5B,yBAAuB,MAAM;AAC7B,SAAO,KAAK;AACd;AAEA,eAAsB,wBACpB,QACA,MACA,MACA,QACsC;AACtC,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,QAAQ;AACV,WAAO,IAAI,UAAU,MAAM;AAAA,EAC7B;AACA,QAAM,QAAQ,OAAO,SAAS;AAC9B,MAAI;AACF,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,8BAA8B,mBAAmB,IAAI,CAAC,IAAI,mBAAmB,IAAI,CAAC,GAAG,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,IAC/G;AACA,uBAAmB,SAAS;AAC5B,2BAAuB,MAAM;AAC7B,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,UAAU,GAAG;AAChE,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,yBACpB,QACuC;AACvC,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACA,qBAAmB,SAAS;AAC5B,yBAAuB,MAAM;AAC7B,SAAO,KAAK;AACd;AAEA,eAAsB,gBACpB,QAC+B;AAC/B,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACA,qBAAmB,WAAW;AAC9B,yBAAuB,MAAM;AAC7B,SAAO,KAAK;AACd;AAEA,eAAsB,qBACpB,QACA,MAC0C;AAC1C,QAAM,aAAa,KAAK,KAAK;AAC7B,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,0BAA0B,mBAAmB,UAAU,CAAC;AAAA,IAC1D;AACA,uBAAmB,WAAW;AAC9B,2BAAuB,MAAM;AAC7B,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,UAAU,GAAG;AAChE,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,kBACpB,QACyB;AACzB,QAAM,SAAS,MAAM,WAA2B,QAAQ,oBAAoB;AAC5E,0BAAwB,MAAM;AAC9B,yBAAuB,MAAM;AAC7B,SAAO;AACT;AAEA,eAAsB,kBACpB,QACyB;AACzB,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACA,qBAAmB,SAAS;AAC5B,yBAAuB,MAAM;AAC7B,SAAO,KAAK;AACd;AAEA,eAAsB,gBAAgB,QAA2C;AAC/E,SAAO,eAAe,QAAQ,qBAAqB;AACrD;AAEA,eAAsB,mBACpB,QACA,SAKgC;AAChC,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,SAAS,QAAQ;AACnB,WAAO,IAAI,UAAU,QAAQ,MAAM;AAAA,EACrC;AACA,MAAI,OAAO,SAAS,SAAS,UAAU;AACrC,WAAO,IAAI,QAAQ,OAAO,QAAQ,IAAI,CAAC;AAAA,EACzC;AACA,MAAI,OAAO,SAAS,UAAU,UAAU;AACtC,WAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AAAA,EAC3C;AACA,QAAM,QAAQ,OAAO,SAAS;AAC9B,SAAO;AAAA,IACL;AAAA,IACA,6BAA6B,QAAQ,IAAI,KAAK,KAAK,EAAE;AAAA,EACvD;AACF;AAOA,eAAsB,2BACpB,QAGA;AACA,QAAM,WAAW,gCAAgC,MAAM;AACvD,MAAI,CAAC,SAAS,QAAQ;AACpB,WAAO,EAAE,IAAI,OAAO,SAAS,KAAK;AAAA,EACpC;AAEA,QAAM,WAAW,gCAAgC,MAAM;AACvD,QAAM,YAAY,GAAG,OAAO,WAAW,IAAI,CAAC,GAAG,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,IAAI,6BAA6B,QAAQ,CAAC;AACnH,MAAI,2BAA2B,SAAS,GAAG;AACzC,WAAO,EAAE,IAAI,MAAM,SAAS;AAAA,EAC9B;AAEA,QAAM,UAAU,iBAAiB,OAAO,OAAO;AAC/C,QAAM,gBACJ,OAAO,cACN,OAAO,eAAe,eAAe,WAAW,QAC7C,WAAW,MAAM,KAAK,UAAU,IAChC;AAEN,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,GAAG,OAAO;AACtB,MAAI,OAAO,OAAO;AAChB,YAAQ,MAAM,iCAAiC,QAAQ,KAAK;AAAA,MAC1D;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,OAIF;AAAA,IACF;AAAA,IACA,YAAY;AAAA,EACd;AACA,MAAI,UAAU;AACZ,SAAK,WAAW;AAAA,EAClB;AAEA,QAAM,MAAM,MAAM,cAAc,KAAK;AAAA,IACnC,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,GAAG,yBAAyB,MAAM;AAAA,IACpC;AAAA,IACA,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AAED,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,CAAC,IAAI,IAAI;AACX,QAAI,SAA4C,CAAC;AACjD,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,eAAS,EAAE,OAAO,KAAK;AAAA,IACzB;AACA,UAAM,IAAI;AAAA,MACR,CAAC,6BAA6B,IAAI,MAAM,IAAI,OAAO,OAAO,OAAO,IAAI,EAClE,OAAO,OAAO,EACd,KAAK,UAAK;AAAA,IACf;AAAA,EACF;AAEA,kCAAgC,SAAS;AACzC,QAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,SAAO,EAAE,IAAI,MAAM,UAAU,KAAK,YAAY,SAAS;AACzD;AAEA,6BAA6B,0BAA0B;;;ACxavD;AAAA,EACE,kBAAoB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,eAAiB;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC5DO,IAAM,gCAAgC,0BAAW;AAGjD,IAAM,iCAAiC,0BAAW;AAElD,SAAS,wBAAwB,iBAAkC;AACxE,MAAI,CAAC,iBAAiB;AACpB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAG,8BAA8B,QAAQ,CAAC,UAAU;AAAA,MAClD,eAAe,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,kCAA0C;AACxD,SAAO,+BAA+B,IAAI,YAAY,EAAE,KAAK,GAAG;AAClE;AAGO,SAAS,6BAId;AACA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,MACH;AAAA,QACE,MAAM;AAAA,QACN,KAAK;AAAA,QACL,OAAO,UAAU,gCAAgC,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,IACA,UAAU,EAAE,QAAQ,OAAO;AAAA,EAC7B;AACF;AAEO,SAAS,kBACd,SACA,SAMQ;AACR,QAAM,UAAU,QAAQ,KAAK;AAC7B,QAAM,cAAc,YAAY,QAAQ,QAAQ,QAAQ,OAAO,EAAE,CAAC;AAClE,QAAM,aAAa,uBAAuB,KAAK,OAAO;AACtD,QAAM,WAAW,QAAQ,uBAAuB,CAAC;AACjD,QAAM,mBAAmB,SAAS;AAAA,IAChC,CAAC,WAAW,CAAC,QAAQ,SAAS,aAAa,MAAM,EAAE;AAAA,EACrD;AAEA,QAAM,QAAQ,CAAC,OAAO;AACtB,MACE,QAAQ,4BACR,CAAC,wBAAwB,KAAK,OAAO,GACrC;AACA,UAAM,QAAQ,wBAAwB,IAAI,EAAE,KAAK,CAAC;AAAA,EACpD;AACA,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,QAAQ,SAAS,IAAI,CAAC,WAAW,aAAa,MAAM,EAAE;AAC5D,UAAM,KAAK;AAAA,EAAkB,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,EACjD;AACA,MAAI,CAAC,YAAY;AACf,UAAM,KAAK,WAAW;AAAA,EACxB;AAEA,SAAO,GAAG,MAAM,KAAK,MAAM,CAAC;AAAA;AAC9B;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;;;ACtEO,SAAS,uBAAuB,QAA0B;AAC/D,SAAO;AAAA,IACL,cAAc,CAAC,YAAkC,gBAAgB,QAAQ,OAAO;AAAA,IAChF,aAAa,CAAC,MAAc,WAAoB,eAAe,QAAQ,MAAM,MAAM;AAAA,IACnF,SAAS,CAAC,YAAkC,WAAW,QAAQ,OAAO;AAAA,IACtE,kBAAkB,CAAC,SAAiB,oBAAoB,QAAQ,IAAI;AAAA,IACpE,mBAAmB,MAAM,qBAAqB,MAAM;AAAA,IACpD,iBAAiB,CAAC,YAChB,mBAAmB,QAAQ,OAAO;AAAA,IACpC,sBAAsB,CACpB,MACA,MACA,WACG,wBAAwB,QAAQ,MAAM,MAAM,MAAM;AAAA,IACvD,uBAAuB,MAAM,yBAAyB,MAAM;AAAA,IAC5D,gBAAgB,MAAM,kBAAkB,MAAM;AAAA,IAC9C,gBAAgB,MAAM,kBAAkB,MAAM;AAAA,IAC9C,cAAc,MAAM,gBAAgB,MAAM;AAAA,IAC1C,iBAAiB,CAAC,YAChB,mBAAmB,QAAQ,OAAO;AAAA,IACpC,yBAAyB,MAAM,2BAA2B,MAAM;AAAA,EAClE;AACF;;;ACzBO,SAAS,oCACd,WAC2B;AAC3B,QAAM,MAAM,4BAA4B;AACxC,QAAM,OAAO,qBAAqB;AAClC,QAAM,UACJ,WAAW,WAAW,IAAI,gBAAgB,MAAM;AAClD,QAAM,cAAc,WAAW,eAAe,IAAI;AAClD,MAAI,CAAC,WAAW,CAAC,YAAa,QAAO;AACrC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB,GAAG;AAAA,IACH,gBAAgB,WAAW,kBAAkB,IAAI;AAAA,IACjD,uBACE,WAAW,yBAAyB,IAAI;AAAA,EAC5C;AACF;AAQO,SAAS,iCACd,WACyB;AACzB,QAAM,MAAM,4BAA4B;AACxC,QAAM,UAAU,WAAW,WAAW,IAAI;AAC1C,QAAM,cAAc,WAAW,eAAe,IAAI;AAClD,MAAI,CAAC,WAAW,CAAC,YAAa,QAAO;AACrC,SAAO,EAAE,SAAS,aAAa,GAAG,UAAU;AAC9C;AAEO,SAAS,qCAA8C;AAC5D,QAAM,MAAM,4BAA4B;AACxC,SAAO,QAAQ,IAAI,gBAAgB,IAAI,WAAW;AACpD;AAEO,SAAS,kCAA2C;AACzD,SAAO,mCAAmC;AAC5C;AAEA,IAAI,+BAAoD;AAMjD,SAAS,sCACd,WACqB;AACrB,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI,6BAA8B,QAAO;AACzC,QAAM,SAAS,oCAAoC,SAAS;AAC5D,MAAI,CAAC,OAAQ,QAAO;AACpB,iCAA+B,mBAAmB,MAAM;AACxD,SAAO;AACT;AAKO,SAAS,oCACd,WACyB;AACzB,QAAM,SAAS,iCAAiC,SAAS;AACzD,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,uBAAuB,MAAM;AACtC;","names":[]}