@jmp-technologies/analytics 0.1.25 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -0
- package/bin/jmp-init.mjs +34 -0
- package/dist/astro/client.cjs +103 -0
- package/dist/astro/client.cjs.map +1 -1
- package/dist/astro/client.d.cts +2 -2
- package/dist/astro/client.d.ts +2 -2
- package/dist/astro/client.js +5 -3
- package/dist/astro/client.js.map +1 -1
- package/dist/astro/content.cjs +271 -1
- package/dist/astro/content.cjs.map +1 -1
- package/dist/astro/content.d.cts +9 -3
- package/dist/astro/content.d.ts +9 -3
- package/dist/astro/content.js +10 -3
- package/dist/astro/integration.cjs +56 -10
- package/dist/astro/integration.cjs.map +1 -1
- package/dist/astro/integration.js +4 -3
- package/dist/astro/integration.js.map +1 -1
- package/dist/astro/middleware.cjs.map +1 -1
- package/dist/astro/middleware.d.cts +2 -2
- package/dist/astro/middleware.d.ts +2 -2
- package/dist/astro/middleware.js +2 -2
- package/dist/astro/register.cjs +56 -10
- package/dist/astro/register.cjs.map +1 -1
- package/dist/astro/register.js +4 -3
- package/dist/{chunk-MOX7RJUU.js → chunk-A4RRTY5D.js} +1 -1
- package/dist/{chunk-MOX7RJUU.js.map → chunk-A4RRTY5D.js.map} +1 -1
- package/dist/{chunk-L67PVZYL.js → chunk-DNYJF7BG.js} +3 -24
- package/dist/chunk-DNYJF7BG.js.map +1 -0
- package/dist/{chunk-5GORAM7J.js → chunk-FNWE2DT5.js} +2 -2
- package/dist/{chunk-7MLPSL6T.js → chunk-HODG4NJQ.js} +2 -2
- package/dist/{chunk-OLWCYWVB.js → chunk-KZ4WVDGL.js} +3 -3
- package/dist/{chunk-AJ33NQVZ.js → chunk-PG3IOI5O.js} +42 -3
- package/dist/chunk-PG3IOI5O.js.map +1 -0
- package/dist/chunk-TCZ6TC2L.js +149 -0
- package/dist/chunk-TCZ6TC2L.js.map +1 -0
- package/dist/{chunk-VRDPVKAN.js → chunk-UVYF33XE.js} +213 -157
- package/dist/chunk-UVYF33XE.js.map +1 -0
- package/dist/chunk-YCVHRMM6.js +28 -0
- package/dist/chunk-YCVHRMM6.js.map +1 -0
- package/dist/{create-jmp-analytics-ClLOMb9p.d.cts → create-jmp-analytics-D4Qw_d6o.d.cts} +1 -1
- package/dist/{create-jmp-analytics-COxo3-yg.d.ts → create-jmp-analytics-DpG5Hdl5.d.ts} +1 -1
- package/dist/index.cjs +213 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -7
- package/dist/index.d.ts +22 -7
- package/dist/index.js +19 -3
- package/dist/next/content.cjs +274 -1
- package/dist/next/content.cjs.map +1 -1
- package/dist/next/content.d.cts +7 -4
- package/dist/next/content.d.ts +7 -4
- package/dist/next/content.js +13 -3
- package/dist/next/content.js.map +1 -1
- package/dist/next/instrumentation.cjs +56 -10
- package/dist/next/instrumentation.cjs.map +1 -1
- package/dist/next/instrumentation.js +3 -2
- package/dist/next/instrumentation.js.map +1 -1
- package/dist/next/landing-capture-script-server.cjs +61 -0
- package/dist/next/landing-capture-script-server.cjs.map +1 -0
- package/dist/next/landing-capture-script-server.d.cts +14 -0
- package/dist/next/landing-capture-script-server.d.ts +14 -0
- package/dist/next/landing-capture-script-server.js +8 -0
- package/dist/next/landing-capture-script-server.js.map +1 -0
- package/dist/next/landing-pages.cjs +659 -0
- package/dist/next/landing-pages.cjs.map +1 -0
- package/dist/next/landing-pages.d.cts +104 -0
- package/dist/next/landing-pages.d.ts +104 -0
- package/dist/next/landing-pages.js +299 -0
- package/dist/next/landing-pages.js.map +1 -0
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.d.cts +2 -2
- package/dist/next/middleware.d.ts +2 -2
- package/dist/next/middleware.js +2 -2
- package/dist/next/site-root-server.cjs +159 -23
- package/dist/next/site-root-server.cjs.map +1 -1
- package/dist/next/site-root-server.js +9 -4
- package/dist/next/site-root-server.js.map +1 -1
- package/dist/next.cjs +152 -70
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +7 -15
- package/dist/next.d.ts +7 -15
- package/dist/next.js +7 -7
- package/dist/react.cjs +103 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +4 -3
- package/dist/{site-config-BSMVyUjk.d.ts → site-config-CJqYnZm7.d.cts} +6 -3
- package/dist/{site-config-8TTHIW6w.d.cts → site-config-UTzDG-UG.d.ts} +6 -3
- package/dist/{track-page-view-DtxbdM5q.d.ts → track-page-view-CMAqyhD_.d.ts} +1 -1
- package/dist/{track-page-view-BweavmXz.d.cts → track-page-view-tX0Magkd.d.cts} +1 -1
- package/dist/{types-Bk0ST1aH.d.ts → types-B-111Wht.d.cts} +52 -5
- package/dist/{types-Bk0ST1aH.d.cts → types-B-111Wht.d.ts} +52 -5
- package/docs/astro-integration.md +1 -1
- package/package.json +16 -2
- package/dist/chunk-AJ33NQVZ.js.map +0 -1
- package/dist/chunk-L67PVZYL.js.map +0 -1
- package/dist/chunk-VRDPVKAN.js.map +0 -1
- /package/dist/{chunk-5GORAM7J.js.map → chunk-FNWE2DT5.js.map} +0 -0
- /package/dist/{chunk-7MLPSL6T.js.map → chunk-HODG4NJQ.js.map} +0 -0
- /package/dist/{chunk-OLWCYWVB.js.map → chunk-KZ4WVDGL.js.map} +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadLandingPageDetail,
|
|
3
|
+
loadLandingPages
|
|
4
|
+
} from "../chunk-PG3IOI5O.js";
|
|
5
|
+
import "../chunk-UVYF33XE.js";
|
|
6
|
+
import "../chunk-TCZ6TC2L.js";
|
|
7
|
+
import {
|
|
8
|
+
getJmpSiteDefinition
|
|
9
|
+
} from "../chunk-A4RRTY5D.js";
|
|
10
|
+
|
|
11
|
+
// src/next/landing-pages.tsx
|
|
12
|
+
import Link from "next/link";
|
|
13
|
+
import { notFound } from "next/navigation";
|
|
14
|
+
|
|
15
|
+
// src/landing-pages/hub.ts
|
|
16
|
+
var JMP_LANDING_HUB = {
|
|
17
|
+
location: {
|
|
18
|
+
title: "Areas we serve",
|
|
19
|
+
path: "/areas",
|
|
20
|
+
description: "Local pages for cities and regions we work in.",
|
|
21
|
+
breadcrumb: "Areas",
|
|
22
|
+
segment: "areas"
|
|
23
|
+
},
|
|
24
|
+
service: {
|
|
25
|
+
title: "Services",
|
|
26
|
+
path: "/services",
|
|
27
|
+
description: "What we offer and how we help.",
|
|
28
|
+
breadcrumb: "Services",
|
|
29
|
+
segment: "services"
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function jmpLandingKindSegment(kind) {
|
|
33
|
+
return JMP_LANDING_HUB[kind].segment;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/landing-pages/utils.ts
|
|
37
|
+
function plainTextFromMarkdown(input, maxLength = 5e3) {
|
|
38
|
+
return input.replace(/[#*_`[\]]/g, "").trim().slice(0, maxLength);
|
|
39
|
+
}
|
|
40
|
+
function resolveJmpSiteUrl(override) {
|
|
41
|
+
const fromArg = override?.trim().replace(/\/$/, "");
|
|
42
|
+
if (fromArg) return fromArg;
|
|
43
|
+
const fromConfig = getJmpSiteDefinition()?.siteUrl?.trim().replace(/\/$/, "");
|
|
44
|
+
return fromConfig || null;
|
|
45
|
+
}
|
|
46
|
+
function absoluteJmpSiteUrl(path, siteUrl) {
|
|
47
|
+
const base = resolveJmpSiteUrl(siteUrl);
|
|
48
|
+
if (!base) {
|
|
49
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
50
|
+
}
|
|
51
|
+
const normalized = path.startsWith("/") ? path : `/${path}`;
|
|
52
|
+
return `${base}${normalized}`;
|
|
53
|
+
}
|
|
54
|
+
function filterJmpLandingPagesForDefaultLocale(pages, kind) {
|
|
55
|
+
const segment = jmpLandingKindSegment(kind);
|
|
56
|
+
return pages.filter((page) => {
|
|
57
|
+
const parts = page.path.split("/").filter(Boolean);
|
|
58
|
+
return parts[0] === segment;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function filterJmpLandingPagesForLocalizedRoutes(pages, kind) {
|
|
62
|
+
const segment = jmpLandingKindSegment(kind);
|
|
63
|
+
return pages.filter((page) => {
|
|
64
|
+
const parts = page.path.split("/").filter(Boolean);
|
|
65
|
+
return parts.length >= 3 && parts[1] === segment;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function jmpLocalizedLandingStaticParams(pages, kind) {
|
|
69
|
+
const segment = jmpLandingKindSegment(kind);
|
|
70
|
+
return filterJmpLandingPagesForLocalizedRoutes(pages, kind).map((page) => {
|
|
71
|
+
const [locale, , slug] = page.path.split("/").filter(Boolean);
|
|
72
|
+
return { locale, slug };
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/landing-pages/json-ld.ts
|
|
77
|
+
function jmpBreadcrumbListJsonLd(items, siteUrl) {
|
|
78
|
+
return {
|
|
79
|
+
"@context": "https://schema.org",
|
|
80
|
+
"@type": "BreadcrumbList",
|
|
81
|
+
itemListElement: items.map((item, index) => ({
|
|
82
|
+
"@type": "ListItem",
|
|
83
|
+
position: index + 1,
|
|
84
|
+
name: item.name,
|
|
85
|
+
item: absoluteJmpSiteUrl(item.path, siteUrl)
|
|
86
|
+
}))
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/landing-pages/static-params.ts
|
|
91
|
+
async function generateJmpLandingStaticParams(kind) {
|
|
92
|
+
const pages = await loadLandingPages({ kind });
|
|
93
|
+
return filterJmpLandingPagesForDefaultLocale(pages, kind).map((page) => ({
|
|
94
|
+
slug: page.slug
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
async function generateJmpLocalizedLandingStaticParams(kind) {
|
|
98
|
+
const pages = await loadLandingPages({ kind });
|
|
99
|
+
return jmpLocalizedLandingStaticParams(pages, kind);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/landing-pages/sitemap.ts
|
|
103
|
+
function buildJmpLandingSitemapRoutes(entries, options) {
|
|
104
|
+
const { siteUrl, changeFrequency = "monthly" } = options;
|
|
105
|
+
const defaultPriority = {
|
|
106
|
+
location: 0.7,
|
|
107
|
+
service: 0.68
|
|
108
|
+
};
|
|
109
|
+
return entries.map((entry) => {
|
|
110
|
+
const priority = options.priorityByKind?.[entry.kind] ?? defaultPriority[entry.kind];
|
|
111
|
+
const languages = entry.alternates.length > 0 ? Object.fromEntries(
|
|
112
|
+
entry.alternates.map((alt) => [
|
|
113
|
+
alt.locale,
|
|
114
|
+
absoluteJmpSiteUrl(alt.path, siteUrl)
|
|
115
|
+
])
|
|
116
|
+
) : void 0;
|
|
117
|
+
return {
|
|
118
|
+
url: absoluteJmpSiteUrl(entry.path, siteUrl),
|
|
119
|
+
lastModified: entry.updated_at ? new Date(entry.updated_at) : void 0,
|
|
120
|
+
changeFrequency,
|
|
121
|
+
priority,
|
|
122
|
+
alternates: languages ? { languages } : void 0
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/next/landing-pages.tsx
|
|
128
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
129
|
+
async function buildJmpLandingMetadata({
|
|
130
|
+
kind,
|
|
131
|
+
slug,
|
|
132
|
+
locale,
|
|
133
|
+
siteUrl
|
|
134
|
+
}) {
|
|
135
|
+
const detail = await loadLandingPageDetail(kind, slug, locale);
|
|
136
|
+
if (!detail) {
|
|
137
|
+
return { title: "Not found" };
|
|
138
|
+
}
|
|
139
|
+
const { page, alternates } = detail;
|
|
140
|
+
const title = page.seo_title?.trim() || page.title;
|
|
141
|
+
const description = page.meta_description?.trim() || page.excerpt?.trim() || plainTextFromMarkdown(page.body, 160) || page.title;
|
|
142
|
+
const languages = {};
|
|
143
|
+
for (const alt of alternates) {
|
|
144
|
+
languages[alt.locale] = absoluteJmpSiteUrl(alt.path, siteUrl);
|
|
145
|
+
}
|
|
146
|
+
const canonical = absoluteJmpSiteUrl(page.path, siteUrl);
|
|
147
|
+
return {
|
|
148
|
+
title,
|
|
149
|
+
description,
|
|
150
|
+
alternates: {
|
|
151
|
+
canonical,
|
|
152
|
+
languages: Object.keys(languages).length > 0 ? languages : void 0
|
|
153
|
+
},
|
|
154
|
+
openGraph: {
|
|
155
|
+
title,
|
|
156
|
+
description,
|
|
157
|
+
type: "website",
|
|
158
|
+
url: canonical
|
|
159
|
+
},
|
|
160
|
+
twitter: {
|
|
161
|
+
card: "summary",
|
|
162
|
+
title,
|
|
163
|
+
description
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function buildJmpLandingIndexMetadata(kind, siteUrl) {
|
|
168
|
+
const hub = JMP_LANDING_HUB[kind];
|
|
169
|
+
return {
|
|
170
|
+
title: hub.title,
|
|
171
|
+
description: hub.description,
|
|
172
|
+
alternates: {
|
|
173
|
+
canonical: absoluteJmpSiteUrl(hub.path, siteUrl)
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function DefaultJsonLd({
|
|
178
|
+
data,
|
|
179
|
+
id
|
|
180
|
+
}) {
|
|
181
|
+
return /* @__PURE__ */ jsx(Fragment, { children: data.map((item, index) => /* @__PURE__ */ jsx(
|
|
182
|
+
"script",
|
|
183
|
+
{
|
|
184
|
+
type: "application/ld+json",
|
|
185
|
+
dangerouslySetInnerHTML: { __html: JSON.stringify(item) }
|
|
186
|
+
},
|
|
187
|
+
`${id}-${index}`
|
|
188
|
+
)) });
|
|
189
|
+
}
|
|
190
|
+
function DefaultBreadcrumbs({
|
|
191
|
+
items,
|
|
192
|
+
LinkComponent
|
|
193
|
+
}) {
|
|
194
|
+
return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx("ol", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem", listStyle: "none", padding: 0 }, children: items.map((item, index) => /* @__PURE__ */ jsxs("li", { children: [
|
|
195
|
+
index > 0 ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " / " }) : null,
|
|
196
|
+
index < items.length - 1 ? /* @__PURE__ */ jsx(LinkComponent, { href: item.path, children: item.name }) : /* @__PURE__ */ jsx("span", { children: item.name })
|
|
197
|
+
] }, item.path)) }) });
|
|
198
|
+
}
|
|
199
|
+
function resolveComponents(components) {
|
|
200
|
+
const LinkComponent = components?.Link ?? Link;
|
|
201
|
+
return {
|
|
202
|
+
Link: LinkComponent,
|
|
203
|
+
renderBody: components?.renderBody ?? ((body) => /* @__PURE__ */ jsx("article", { children: /* @__PURE__ */ jsx("pre", { style: { whiteSpace: "pre-wrap", fontFamily: "inherit" }, children: body }) })),
|
|
204
|
+
renderBreadcrumbs: components?.renderBreadcrumbs ?? ((items) => /* @__PURE__ */ jsx(DefaultBreadcrumbs, { items, LinkComponent })),
|
|
205
|
+
renderJsonLd: components?.renderJsonLd ?? ((data, id) => /* @__PURE__ */ jsx(DefaultJsonLd, { data, id }))
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
async function JmpLandingDetailPage({
|
|
209
|
+
kind,
|
|
210
|
+
slug,
|
|
211
|
+
locale,
|
|
212
|
+
siteUrl,
|
|
213
|
+
components,
|
|
214
|
+
className,
|
|
215
|
+
classNames
|
|
216
|
+
}) {
|
|
217
|
+
const detail = await loadLandingPageDetail(kind, slug, locale);
|
|
218
|
+
if (!detail) {
|
|
219
|
+
notFound();
|
|
220
|
+
}
|
|
221
|
+
const ui = resolveComponents(components);
|
|
222
|
+
const resolvedSiteUrl = resolveJmpSiteUrl(siteUrl) ?? void 0;
|
|
223
|
+
const { page, schema_json_ld } = detail;
|
|
224
|
+
const hub = JMP_LANDING_HUB[kind];
|
|
225
|
+
const displayTitle = page.headline?.trim() || page.title;
|
|
226
|
+
const breadcrumbItems = [
|
|
227
|
+
{ name: "Home", path: "/" },
|
|
228
|
+
{ name: hub.breadcrumb, path: hub.path },
|
|
229
|
+
{ name: page.title, path: page.path }
|
|
230
|
+
];
|
|
231
|
+
const related = filterJmpLandingPagesForDefaultLocale(
|
|
232
|
+
await loadLandingPages({ kind }),
|
|
233
|
+
kind
|
|
234
|
+
).filter((item) => item.id !== page.id && item.locale === page.locale);
|
|
235
|
+
const jsonLdBlocks = [
|
|
236
|
+
...schema_json_ld ?? [],
|
|
237
|
+
jmpBreadcrumbListJsonLd(breadcrumbItems, resolvedSiteUrl)
|
|
238
|
+
];
|
|
239
|
+
return /* @__PURE__ */ jsxs("main", { className, children: [
|
|
240
|
+
ui.renderJsonLd(jsonLdBlocks, `jmp-landing-${page.id}-ld-json`),
|
|
241
|
+
ui.renderBreadcrumbs(breadcrumbItems),
|
|
242
|
+
page.excerpt ? /* @__PURE__ */ jsx("p", { className: classNames?.excerpt, children: page.excerpt }) : null,
|
|
243
|
+
/* @__PURE__ */ jsx("h1", { className: classNames?.title, children: displayTitle }),
|
|
244
|
+
page.body ? ui.renderBody(page.body) : null,
|
|
245
|
+
related.length > 0 ? /* @__PURE__ */ jsxs("section", { children: [
|
|
246
|
+
/* @__PURE__ */ jsxs("h2", { className: classNames?.relatedTitle, children: [
|
|
247
|
+
"More ",
|
|
248
|
+
hub.breadcrumb.toLowerCase()
|
|
249
|
+
] }),
|
|
250
|
+
/* @__PURE__ */ jsx("ul", { className: classNames?.list, children: related.slice(0, 8).map((item) => /* @__PURE__ */ jsx("li", { className: classNames?.listItem, children: /* @__PURE__ */ jsx(ui.Link, { href: item.path, children: item.title }) }, item.id)) })
|
|
251
|
+
] }) : null
|
|
252
|
+
] });
|
|
253
|
+
}
|
|
254
|
+
async function JmpLandingIndexPage({
|
|
255
|
+
kind,
|
|
256
|
+
siteUrl,
|
|
257
|
+
components,
|
|
258
|
+
className,
|
|
259
|
+
classNames
|
|
260
|
+
}) {
|
|
261
|
+
const ui = resolveComponents(components);
|
|
262
|
+
const hub = JMP_LANDING_HUB[kind];
|
|
263
|
+
const pages = filterJmpLandingPagesForDefaultLocale(
|
|
264
|
+
await loadLandingPages({ kind }),
|
|
265
|
+
kind
|
|
266
|
+
);
|
|
267
|
+
const breadcrumbItems = [
|
|
268
|
+
{ name: "Home", path: "/" },
|
|
269
|
+
{ name: hub.breadcrumb, path: hub.path }
|
|
270
|
+
];
|
|
271
|
+
return /* @__PURE__ */ jsxs("main", { className, children: [
|
|
272
|
+
ui.renderBreadcrumbs(breadcrumbItems),
|
|
273
|
+
/* @__PURE__ */ jsx("h1", { className: classNames?.title, children: hub.title }),
|
|
274
|
+
/* @__PURE__ */ jsx("p", { className: classNames?.hubDescription, children: hub.description }),
|
|
275
|
+
pages.length > 0 ? /* @__PURE__ */ jsx("ul", { className: classNames?.list, children: pages.map((page) => /* @__PURE__ */ jsxs("li", { className: classNames?.listItem, children: [
|
|
276
|
+
/* @__PURE__ */ jsx(ui.Link, { href: page.path, children: page.title }),
|
|
277
|
+
page.excerpt ? /* @__PURE__ */ jsx("p", { className: classNames?.excerpt, children: page.excerpt }) : null
|
|
278
|
+
] }, page.id)) }) : /* @__PURE__ */ jsx("p", { className: classNames?.emptyState, children: "Pages will appear here once published in the JMP dashboard." })
|
|
279
|
+
] });
|
|
280
|
+
}
|
|
281
|
+
export {
|
|
282
|
+
JMP_LANDING_HUB,
|
|
283
|
+
JmpLandingDetailPage,
|
|
284
|
+
JmpLandingIndexPage,
|
|
285
|
+
absoluteJmpSiteUrl,
|
|
286
|
+
buildJmpLandingIndexMetadata,
|
|
287
|
+
buildJmpLandingMetadata,
|
|
288
|
+
buildJmpLandingSitemapRoutes,
|
|
289
|
+
filterJmpLandingPagesForDefaultLocale,
|
|
290
|
+
filterJmpLandingPagesForLocalizedRoutes,
|
|
291
|
+
generateJmpLandingStaticParams,
|
|
292
|
+
generateJmpLocalizedLandingStaticParams,
|
|
293
|
+
jmpBreadcrumbListJsonLd,
|
|
294
|
+
jmpLandingKindSegment,
|
|
295
|
+
jmpLocalizedLandingStaticParams,
|
|
296
|
+
plainTextFromMarkdown,
|
|
297
|
+
resolveJmpSiteUrl
|
|
298
|
+
};
|
|
299
|
+
//# sourceMappingURL=landing-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/landing-pages.tsx","../../src/landing-pages/hub.ts","../../src/landing-pages/utils.ts","../../src/landing-pages/json-ld.ts","../../src/landing-pages/static-params.ts","../../src/landing-pages/sitemap.ts"],"sourcesContent":["import type { Metadata } from \"next\"\nimport Link from \"next/link\"\nimport { notFound } from \"next/navigation\"\nimport type { ComponentType, ReactNode } from \"react\"\n\nimport {\n loadLandingPageDetail,\n loadLandingPages,\n} from \"../content/site-content\"\nimport { JMP_LANDING_HUB } from \"../landing-pages/hub\"\nimport { jmpBreadcrumbListJsonLd } from \"../landing-pages/json-ld\"\nimport {\n buildJmpLandingSitemapRoutes,\n type BuildJmpLandingSitemapRoutesOptions,\n type JmpLandingSitemapRoute,\n} from \"../landing-pages/sitemap\"\nimport {\n generateJmpLandingStaticParams,\n generateJmpLocalizedLandingStaticParams,\n} from \"../landing-pages/static-params\"\nimport {\n absoluteJmpSiteUrl,\n filterJmpLandingPagesForDefaultLocale,\n plainTextFromMarkdown,\n resolveJmpSiteUrl,\n} from \"../landing-pages/utils\"\nimport type { JmpLandingPageKind } from \"../types\"\n\nexport {\n generateJmpLandingStaticParams,\n generateJmpLocalizedLandingStaticParams,\n} from \"../landing-pages/static-params\"\nexport {\n buildJmpLandingSitemapRoutes,\n type BuildJmpLandingSitemapRoutesOptions,\n type JmpLandingSitemapRoute,\n} from \"../landing-pages/sitemap\"\nexport {\n absoluteJmpSiteUrl,\n filterJmpLandingPagesForDefaultLocale,\n filterJmpLandingPagesForLocalizedRoutes,\n jmpLocalizedLandingStaticParams,\n plainTextFromMarkdown,\n resolveJmpSiteUrl,\n} from \"../landing-pages/utils\"\nexport { JMP_LANDING_HUB, jmpLandingKindSegment } from \"../landing-pages/hub\"\nexport { jmpBreadcrumbListJsonLd, type JmpBreadcrumbItem } from \"../landing-pages/json-ld\"\n\nexport type JmpLandingPageClassNames = {\n excerpt?: string\n title?: string\n relatedTitle?: string\n hubDescription?: string\n emptyState?: string\n list?: string\n listItem?: string\n}\n\nexport type JmpLandingDetailPageProps = {\n kind: JmpLandingPageKind\n slug: string\n locale?: string\n siteUrl?: string\n components?: JmpLandingPageComponents\n className?: string\n classNames?: JmpLandingPageClassNames\n}\n\nexport type JmpLandingIndexPageProps = {\n kind: JmpLandingPageKind\n siteUrl?: string\n components?: JmpLandingPageComponents\n className?: string\n classNames?: JmpLandingPageClassNames\n}\n\nexport type JmpLandingPageComponents = {\n Link?: ComponentType<{\n href: string\n className?: string\n children: ReactNode\n }>\n renderBody?: (body: string) => ReactNode\n renderBreadcrumbs?: (items: { name: string; path: string }[]) => ReactNode\n renderJsonLd?: (data: Record<string, unknown>[], id: string) => ReactNode\n}\n\nexport async function buildJmpLandingMetadata({\n kind,\n slug,\n locale,\n siteUrl,\n}: JmpLandingDetailPageProps): Promise<Metadata> {\n const detail = await loadLandingPageDetail(kind, slug, locale)\n if (!detail) {\n return { title: \"Not found\" }\n }\n\n const { page, alternates } = detail\n const title = page.seo_title?.trim() || page.title\n const description =\n page.meta_description?.trim() ||\n page.excerpt?.trim() ||\n plainTextFromMarkdown(page.body, 160) ||\n page.title\n\n const languages: Record<string, string> = {}\n for (const alt of alternates) {\n languages[alt.locale] = absoluteJmpSiteUrl(alt.path, siteUrl)\n }\n\n const canonical = absoluteJmpSiteUrl(page.path, siteUrl)\n\n return {\n title,\n description,\n alternates: {\n canonical,\n languages: Object.keys(languages).length > 0 ? languages : undefined,\n },\n openGraph: {\n title,\n description,\n type: \"website\",\n url: canonical,\n },\n twitter: {\n card: \"summary\",\n title,\n description,\n },\n }\n}\n\nexport function buildJmpLandingIndexMetadata(\n kind: JmpLandingPageKind,\n siteUrl?: string\n): Metadata {\n const hub = JMP_LANDING_HUB[kind]\n return {\n title: hub.title,\n description: hub.description,\n alternates: {\n canonical: absoluteJmpSiteUrl(hub.path, siteUrl),\n },\n }\n}\n\nfunction DefaultJsonLd({\n data,\n id,\n}: {\n data: Record<string, unknown>[]\n id: string\n}) {\n return (\n <>\n {data.map((item, index) => (\n <script\n key={`${id}-${index}`}\n type=\"application/ld+json\"\n dangerouslySetInnerHTML={{ __html: JSON.stringify(item) }}\n />\n ))}\n </>\n )\n}\n\nfunction DefaultBreadcrumbs({\n items,\n LinkComponent,\n}: {\n items: { name: string; path: string }[]\n LinkComponent: NonNullable<JmpLandingPageComponents[\"Link\"]>\n}) {\n return (\n <nav aria-label=\"Breadcrumb\">\n <ol style={{ display: \"flex\", flexWrap: \"wrap\", gap: \"0.5rem\", listStyle: \"none\", padding: 0 }}>\n {items.map((item, index) => (\n <li key={item.path}>\n {index > 0 ? <span aria-hidden=\"true\"> / </span> : null}\n {index < items.length - 1 ? (\n <LinkComponent href={item.path}>{item.name}</LinkComponent>\n ) : (\n <span>{item.name}</span>\n )}\n </li>\n ))}\n </ol>\n </nav>\n )\n}\n\nfunction resolveComponents(components?: JmpLandingPageComponents) {\n const LinkComponent = components?.Link ?? Link\n return {\n Link: LinkComponent,\n renderBody:\n components?.renderBody ??\n ((body: string) => (\n <article>\n <pre style={{ whiteSpace: \"pre-wrap\", fontFamily: \"inherit\" }}>{body}</pre>\n </article>\n )),\n renderBreadcrumbs:\n components?.renderBreadcrumbs ??\n ((items: { name: string; path: string }[]) => (\n <DefaultBreadcrumbs items={items} LinkComponent={LinkComponent} />\n )),\n renderJsonLd:\n components?.renderJsonLd ??\n ((data: Record<string, unknown>[], id: string) => (\n <DefaultJsonLd data={data} id={id} />\n )),\n }\n}\n\nexport async function JmpLandingDetailPage({\n kind,\n slug,\n locale,\n siteUrl,\n components,\n className,\n classNames,\n}: JmpLandingDetailPageProps) {\n const detail = await loadLandingPageDetail(kind, slug, locale)\n if (!detail) {\n notFound()\n }\n\n const ui = resolveComponents(components)\n const resolvedSiteUrl = resolveJmpSiteUrl(siteUrl) ?? undefined\n const { page, schema_json_ld } = detail\n const hub = JMP_LANDING_HUB[kind]\n const displayTitle = page.headline?.trim() || page.title\n const breadcrumbItems = [\n { name: \"Home\", path: \"/\" },\n { name: hub.breadcrumb, path: hub.path },\n { name: page.title, path: page.path },\n ]\n\n const related = filterJmpLandingPagesForDefaultLocale(\n await loadLandingPages({ kind }),\n kind\n ).filter((item) => item.id !== page.id && item.locale === page.locale)\n\n const jsonLdBlocks: Record<string, unknown>[] = [\n ...(schema_json_ld ?? []),\n jmpBreadcrumbListJsonLd(breadcrumbItems, resolvedSiteUrl),\n ]\n\n return (\n <main className={className}>\n {ui.renderJsonLd(jsonLdBlocks, `jmp-landing-${page.id}-ld-json`)}\n {ui.renderBreadcrumbs(breadcrumbItems)}\n\n {page.excerpt ? (\n <p className={classNames?.excerpt}>{page.excerpt}</p>\n ) : null}\n\n <h1 className={classNames?.title}>{displayTitle}</h1>\n\n {page.body ? ui.renderBody(page.body) : null}\n\n {related.length > 0 ? (\n <section>\n <h2 className={classNames?.relatedTitle}>\n More {hub.breadcrumb.toLowerCase()}\n </h2>\n <ul className={classNames?.list}>\n {related.slice(0, 8).map((item) => (\n <li key={item.id} className={classNames?.listItem}>\n <ui.Link href={item.path}>{item.title}</ui.Link>\n </li>\n ))}\n </ul>\n </section>\n ) : null}\n </main>\n )\n}\n\nexport async function JmpLandingIndexPage({\n kind,\n siteUrl,\n components,\n className,\n classNames,\n}: JmpLandingIndexPageProps) {\n const ui = resolveComponents(components)\n const hub = JMP_LANDING_HUB[kind]\n const pages = filterJmpLandingPagesForDefaultLocale(\n await loadLandingPages({ kind }),\n kind\n )\n\n const breadcrumbItems = [\n { name: \"Home\", path: \"/\" },\n { name: hub.breadcrumb, path: hub.path },\n ]\n\n return (\n <main className={className}>\n {ui.renderBreadcrumbs(breadcrumbItems)}\n\n <h1 className={classNames?.title}>{hub.title}</h1>\n <p className={classNames?.hubDescription}>{hub.description}</p>\n\n {pages.length > 0 ? (\n <ul className={classNames?.list}>\n {pages.map((page) => (\n <li key={page.id} className={classNames?.listItem}>\n <ui.Link href={page.path}>{page.title}</ui.Link>\n {page.excerpt ? (\n <p className={classNames?.excerpt}>{page.excerpt}</p>\n ) : null}\n </li>\n ))}\n </ul>\n ) : (\n <p className={classNames?.emptyState}>\n Pages will appear here once published in the JMP dashboard.\n </p>\n )}\n </main>\n )\n}\n","import type { JmpLandingPageKind } from \"../types\"\n\nexport type JmpLandingHubConfig = {\n title: string\n path: string\n description: string\n breadcrumb: string\n segment: string\n}\n\nexport const JMP_LANDING_HUB: Record<JmpLandingPageKind, JmpLandingHubConfig> = {\n location: {\n title: \"Areas we serve\",\n path: \"/areas\",\n description: \"Local pages for cities and regions we work in.\",\n breadcrumb: \"Areas\",\n segment: \"areas\",\n },\n service: {\n title: \"Services\",\n path: \"/services\",\n description: \"What we offer and how we help.\",\n breadcrumb: \"Services\",\n segment: \"services\",\n },\n}\n\nexport function jmpLandingKindSegment(kind: JmpLandingPageKind): string {\n return JMP_LANDING_HUB[kind].segment\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 const segment = jmpLandingKindSegment(kind)\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 { absoluteJmpSiteUrl } from \"./utils\"\n\nexport type JmpBreadcrumbItem = { name: string; path: string }\n\nexport function jmpBreadcrumbListJsonLd(\n items: JmpBreadcrumbItem[],\n siteUrl?: string\n): Record<string, unknown> {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n itemListElement: items.map((item, index) => ({\n \"@type\": \"ListItem\",\n position: index + 1,\n name: item.name,\n item: absoluteJmpSiteUrl(item.path, siteUrl),\n })),\n }\n}\n","import { loadLandingPages } from \"../content/site-content\"\nimport type { JmpLandingPageKind } from \"../types\"\nimport {\n filterJmpLandingPagesForDefaultLocale,\n jmpLocalizedLandingStaticParams,\n} from \"./utils\"\n\n/** `generateStaticParams` for `app/{areas|services}/[slug]/page.tsx` (default locale). */\nexport async function generateJmpLandingStaticParams(\n kind: JmpLandingPageKind\n): Promise<{ slug: string }[]> {\n const pages = await loadLandingPages({ kind })\n return filterJmpLandingPagesForDefaultLocale(pages, kind).map((page) => ({\n slug: page.slug,\n }))\n}\n\n/** `generateStaticParams` for `app/[locale]/{areas|services}/[slug]/page.tsx`. */\nexport async function generateJmpLocalizedLandingStaticParams(\n kind: JmpLandingPageKind\n): Promise<{ locale: string; slug: string }[]> {\n const pages = await loadLandingPages({ kind })\n return jmpLocalizedLandingStaticParams(pages, kind)\n}\n","import type { JmpLandingPageKind, JmpLandingPageSitemapEntry } from \"../types\"\nimport { absoluteJmpSiteUrl } from \"./utils\"\n\nexport type JmpLandingSitemapRoute = {\n url: string\n lastModified?: Date\n changeFrequency?: \"always\" | \"hourly\" | \"daily\" | \"weekly\" | \"monthly\" | \"yearly\" | \"never\"\n priority?: number\n alternates?: { languages?: Record<string, string> }\n}\n\nexport type BuildJmpLandingSitemapRoutesOptions = {\n siteUrl: string\n /** Default 0.7 location, 0.68 service */\n priorityByKind?: Partial<Record<JmpLandingPageKind, number>>\n changeFrequency?: JmpLandingSitemapRoute[\"changeFrequency\"]\n}\n\nexport function buildJmpLandingSitemapRoutes(\n entries: JmpLandingPageSitemapEntry[],\n options: BuildJmpLandingSitemapRoutesOptions\n): JmpLandingSitemapRoute[] {\n const { siteUrl, changeFrequency = \"monthly\" } = options\n const defaultPriority: Record<JmpLandingPageKind, number> = {\n location: 0.7,\n service: 0.68,\n }\n\n return entries.map((entry) => {\n const priority =\n options.priorityByKind?.[entry.kind] ?? defaultPriority[entry.kind]\n const languages =\n entry.alternates.length > 0\n ? Object.fromEntries(\n entry.alternates.map((alt) => [\n alt.locale,\n absoluteJmpSiteUrl(alt.path, siteUrl),\n ])\n )\n : undefined\n\n return {\n url: absoluteJmpSiteUrl(entry.path, siteUrl),\n lastModified: entry.updated_at ? new Date(entry.updated_at) : undefined,\n changeFrequency,\n priority,\n alternates: languages ? { languages } : undefined,\n }\n })\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/middleware.ts","../../src/http.ts","../../src/server/page-view.ts","../../src/server/should-track-server-page-view.ts","../../src/env-public.ts","../../src/site-config.ts","../../src/server/track-page-view.ts"],"sourcesContent":["import type { JmpServerRequestLike } from \"../index\"\nimport { jmpTrackServerPageView } from \"../server/track-page-view\"\n\n/**\n * Default middleware matcher string for copy-paste into the client `middleware.ts`.\n * Do **not** spread this into `export const config` — Next.js requires a literal array there.\n */\nexport const JMP_MIDDLEWARE_MATCHER = [\n \"/((?!_next/static|_next/image|favicon.ico|.*\\\\.(?:ico|png|jpg|jpeg|gif|webp|svg|webm|mp4|css|js|woff2?|txt|xml)$).*)\",\n] as const\n\nexport { jmpTrackServerPageView } from \"../server/track-page-view\"\n\nexport type { JmpServerRequestLike }\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 getHeader,\n normalizeBaseUrl,\n pathFromRequestUrl,\n resolveFetch,\n} from \"../http\"\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> = {\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","import { getHeader } from \"../http\"\nimport type { JmpServerRequestLike } from \"../types\"\n\n/**\n * Returns true when middleware should not record a server page view.\n * Skips Next.js RSC flights, router prefetch, and non-document fetches so\n * {@link jmpTrackServerPageView} does not inflate counts alongside `JmpSiteRoot`.\n */\nexport function shouldSkipServerPageViewRequest(\n request: JmpServerRequestLike | undefined,\n): boolean {\n if (!request) {\n return false\n }\n\n const url = request.url\n if (url) {\n try {\n const parsed = new URL(url, \"https://jmp.local\")\n if (parsed.searchParams.has(\"_rsc\")) {\n return true\n }\n } catch {\n if (url.includes(\"_rsc=\")) {\n return true\n }\n }\n }\n\n const headers = request.headers\n\n if (\n getHeader(headers, \"next-router-prefetch\") === \"1\" ||\n getHeader(headers, \"purpose\") === \"prefetch\" ||\n getHeader(headers, \"x-middleware-prefetch\") === \"1\"\n ) {\n return true\n }\n\n const rsc = getHeader(headers, \"rsc\")\n if (rsc === \"1\") {\n return true\n }\n\n if (getHeader(headers, \"next-router-state-tree\")) {\n return true\n }\n\n const secDest = getHeader(headers, \"sec-fetch-dest\")\n if (secDest && secDest !== \"document\") {\n return true\n }\n\n return false\n}\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 { JmpContentConfig, JmpContentWrapper } from \"./types\"\nimport { readJmpPublicEnvFromProcess } from \"./env-public\"\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 hours?: string | null\n serviceArea?: string | null\n dashboardDemoUrl?: string\n profilePhotoSrc?: string\n privacyUrl?: string\n termsUrl?: string\n}\n\nexport type JmpSiteDefinition = {\n /** Content tabs this site uses — reported via instrumentation capabilities. */\n contentWrappers: JmpContentWrapper[]\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 }\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 return {\n baseUrl: analyticsUrl,\n trackingKey,\n contentWrappers: site?.contentWrappers ?? undefined,\n }\n}\n","import { trackJmpServerPageView } from \"./page-view\"\nimport { shouldSkipServerPageViewRequest } from \"./should-track-server-page-view\"\nimport type { JmpServerRequestLike } from \"../types\"\nimport { getJmpContentConfig } from \"../site-config\"\n\n/**\n * Records a server-side page view when JMP env is configured.\n * Framework-agnostic — pass any `Request`-like object (Next middleware, Astro `context.request`).\n *\n * Skips Next.js RSC/prefetch requests. When using {@link JmpSiteRoot} for browser\n * page views, do not call this from middleware — it duplicates counts and omits `sessionId`.\n */\nexport async function jmpTrackServerPageView(\n request: JmpServerRequestLike,\n): Promise<void> {\n if (shouldSkipServerPageViewRequest(request)) {\n return\n }\n const config = getJmpContentConfig()\n if (!config) {\n return\n }\n await trackJmpServerPageView(config, { request }).catch(() => {})\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/next/middleware.ts","../../src/http.ts","../../src/server/page-view.ts","../../src/server/should-track-server-page-view.ts","../../src/env-public.ts","../../src/site-config.ts","../../src/server/track-page-view.ts"],"sourcesContent":["import type { JmpServerRequestLike } from \"../index\"\nimport { jmpTrackServerPageView } from \"../server/track-page-view\"\n\n/**\n * Default middleware matcher string for copy-paste into the client `middleware.ts`.\n * Do **not** spread this into `export const config` — Next.js requires a literal array there.\n */\nexport const JMP_MIDDLEWARE_MATCHER = [\n \"/((?!_next/static|_next/image|favicon.ico|.*\\\\.(?:ico|png|jpg|jpeg|gif|webp|svg|webm|mp4|css|js|woff2?|txt|xml)$).*)\",\n] as const\n\nexport { jmpTrackServerPageView } from \"../server/track-page-view\"\n\nexport type { JmpServerRequestLike }\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 getHeader,\n normalizeBaseUrl,\n pathFromRequestUrl,\n resolveFetch,\n} from \"../http\"\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> = {\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","import { getHeader } from \"../http\"\nimport type { JmpServerRequestLike } from \"../types\"\n\n/**\n * Returns true when middleware should not record a server page view.\n * Skips Next.js RSC flights, router prefetch, and non-document fetches so\n * {@link jmpTrackServerPageView} does not inflate counts alongside `JmpSiteRoot`.\n */\nexport function shouldSkipServerPageViewRequest(\n request: JmpServerRequestLike | undefined,\n): boolean {\n if (!request) {\n return false\n }\n\n const url = request.url\n if (url) {\n try {\n const parsed = new URL(url, \"https://jmp.local\")\n if (parsed.searchParams.has(\"_rsc\")) {\n return true\n }\n } catch {\n if (url.includes(\"_rsc=\")) {\n return true\n }\n }\n }\n\n const headers = request.headers\n\n if (\n getHeader(headers, \"next-router-prefetch\") === \"1\" ||\n getHeader(headers, \"purpose\") === \"prefetch\" ||\n getHeader(headers, \"x-middleware-prefetch\") === \"1\"\n ) {\n return true\n }\n\n const rsc = getHeader(headers, \"rsc\")\n if (rsc === \"1\") {\n return true\n }\n\n if (getHeader(headers, \"next-router-state-tree\")) {\n return true\n }\n\n const secDest = getHeader(headers, \"sec-fetch-dest\")\n if (secDest && secDest !== \"document\") {\n return true\n }\n\n return false\n}\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 { JmpContentConfig, JmpContentWrapper } from \"./types\"\nimport { readJmpPublicEnvFromProcess } from \"./env-public\"\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 hours?: string | null\n serviceArea?: string | null\n dashboardDemoUrl?: string\n profilePhotoSrc?: string\n privacyUrl?: string\n termsUrl?: string\n}\n\nexport type JmpSiteDefinition = {\n /**\n * Optional override. Wrappers are auto-discovered when content loaders run\n * (`loadBlogPosts`, `loadFaqs`, etc.) and reported to the dashboard.\n */\n contentWrappers?: JmpContentWrapper[]\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 }\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 return {\n baseUrl: analyticsUrl,\n trackingKey,\n contentWrappers: site?.contentWrappers ?? undefined,\n }\n}\n","import { trackJmpServerPageView } from \"./page-view\"\nimport { shouldSkipServerPageViewRequest } from \"./should-track-server-page-view\"\nimport type { JmpServerRequestLike } from \"../types\"\nimport { getJmpContentConfig } from \"../site-config\"\n\n/**\n * Records a server-side page view when JMP env is configured.\n * Framework-agnostic — pass any `Request`-like object (Next middleware, Astro `context.request`).\n *\n * Skips Next.js RSC/prefetch requests. When using {@link JmpSiteRoot} for browser\n * page views, do not call this from middleware — it duplicates counts and omits `sessionId`.\n */\nexport async function jmpTrackServerPageView(\n request: JmpServerRequestLike,\n): Promise<void> {\n if (shouldSkipServerPageViewRequest(request)) {\n return\n }\n const config = getJmpContentConfig()\n if (!config) {\n return\n }\n await trackJmpServerPageView(config, { request }).catch(() => {})\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { j as jmpTrackServerPageView } from '../track-page-view-
|
|
1
|
+
export { k as JmpServerRequestLike } from '../types-B-111Wht.cjs';
|
|
2
|
+
export { j as jmpTrackServerPageView } from '../track-page-view-tX0Magkd.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Default middleware matcher string for copy-paste into the client `middleware.ts`.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { j as jmpTrackServerPageView } from '../track-page-view-
|
|
1
|
+
export { k as JmpServerRequestLike } from '../types-B-111Wht.js';
|
|
2
|
+
export { j as jmpTrackServerPageView } from '../track-page-view-CMAqyhD_.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Default middleware matcher string for copy-paste into the client `middleware.ts`.
|
package/dist/next/middleware.js
CHANGED