@mints-cloud/cxf-codegen 1.0.3 → 1.0.5

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 CHANGED
@@ -26,6 +26,44 @@ export default function App(props: AppProps) {
26
26
  }
27
27
  ```
28
28
 
29
+ ### Configure assets query params from variants
30
+
31
+ Configure this in `pages/_app.tsx` by passing dynamic asset query params to `CxfApp`.
32
+ These params are synced to a cookie and automatically appended by `pages/api/assets/[...path].ts` proxy requests.
33
+ Your `pages/api/assets/[...path].ts` file should stay a thin wrapper:
34
+
35
+ ```ts
36
+ export { default } from '@mints-cloud/cxf-codegen/pages/api/assets';
37
+ ```
38
+
39
+ ```tsx
40
+ import '@/styles/globals.css'
41
+ import '@mints-cloud/cxf-codegen/register';
42
+ import type { AppProps } from 'next/app';
43
+ import CxfApp from '@mints-cloud/cxf-codegen/pages/app';
44
+ import projectcss from '../components/plasmic/<your-project>/plasmic.module.css';
45
+ import { useScreenVariants } from '../components/plasmic/<your-project>/PlasmicGlobalVariant__Screen';
46
+
47
+ export default function App(props: AppProps) {
48
+ const screenVariants = useScreenVariants();
49
+ const variation = screenVariants.includes('mobile')
50
+ ? 'mobile'
51
+ : screenVariants.includes('tablet')
52
+ ? 'tablet'
53
+ : undefined;
54
+
55
+ return (
56
+ <CxfApp
57
+ {...props}
58
+ tokenClass={projectcss.plasmic_tokens}
59
+ assetsQueryParams={variation ? { variation } : undefined}
60
+ />
61
+ );
62
+ }
63
+ ```
64
+
65
+ `assetsQueryParams` accepts any query keys/values, so you can map any Plasmic variant naming to any asset param names you need.
66
+
29
67
  ### `pages/api/[...path].ts`
30
68
 
31
69
  ```ts
@@ -42,15 +80,21 @@ export { default } from '@mints-cloud/cxf-codegen/pages/api/assets';
42
80
 
43
81
  ```tsx
44
82
  import '@mints-cloud/cxf-codegen/register';
45
- import { PlasmicHost } from '@mints-cloud/cxf-codegen/pages/plasmic-host';
83
+ import {
84
+ PlasmicHost,
85
+ getPlasmicHostServerSideProps,
86
+ } from '@mints-cloud/cxf-codegen/pages/plasmic-host';
46
87
  import projectcss from '../components/plasmic/<your-project>/plasmic.module.css';
47
88
 
48
89
  export default function MyPlasmicHost() {
49
90
  return <PlasmicHost tokenClass={projectcss.plasmic_tokens} />;
50
91
  }
92
+
93
+ export const getServerSideProps = getPlasmicHostServerSideProps;
51
94
  ```
52
95
 
53
96
  The `tokenClass` prop ensures Plasmic design tokens are applied correctly in the canvas.
97
+ `getPlasmicHostServerSideProps` returns `notFound: true` when host is disabled.
54
98
 
55
99
  ### `next.config.mjs`
56
100
 
@@ -73,8 +117,15 @@ Optional:
73
117
  ```
74
118
  CXF_DEV_API_KEY=your-dev-api-key
75
119
  CXF_USER_API_KEY=your-user-api-key
120
+ NEXT_PUBLIC_ENABLE_PLASMIC_HOST=true
76
121
  ```
77
122
 
123
+ `NEXT_PUBLIC_ENABLE_PLASMIC_HOST` controls `/plasmic-host` availability:
124
+
125
+ - In `production`, host is disabled by default
126
+ - In non-production, host is enabled by default
127
+ - Set to `true/false` (also supports `1/0`, `yes/no`, `on/off`) to override defaults
128
+
78
129
  ## Usage
79
130
 
80
131
  ### ApiCall Component
@@ -1 +1 @@
1
- {"version":3,"file":"ApiCall.d.ts","sourceRoot":"","sources":["../../src/components/ApiCall.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACjC;;;OAGG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAsBD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,kDAyD1C;AAED,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"ApiCall.d.ts","sourceRoot":"","sources":["../../src/components/ApiCall.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,cAAc,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACjC;;;OAGG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAgCD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,kDA0D1C;AAED,eAAe,OAAO,CAAC"}
@@ -38,6 +38,18 @@ const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const React = __importStar(require("react"));
39
39
  const host_1 = require("@plasmicapp/host");
40
40
  const api_call_hooks_1 = require("../lib/api-call-hooks");
41
+ function parseAutoFetch(value) {
42
+ if (typeof value === "boolean")
43
+ return value;
44
+ if (typeof value === "string") {
45
+ const normalized = value.trim().toLowerCase();
46
+ if (normalized === "true")
47
+ return true;
48
+ if (normalized === "false")
49
+ return false;
50
+ }
51
+ return undefined;
52
+ }
41
53
  function trimSlashes(p) {
42
54
  return String(p || "").replace(/^\/+|\/+$/g, "");
43
55
  }
@@ -59,7 +71,8 @@ function buildEndpointPath(apiType, rawPath) {
59
71
  function ApiCall(props) {
60
72
  const { apiType = "contact", path, method = "GET", params, body, initialData, autoFetch, trigger, onSuccess, onError, loadingContent, canvasAutoFetchCooldownMs, children, } = props;
61
73
  const endpointPath = React.useMemo(() => buildEndpointPath(apiType, path), [apiType, path]);
62
- const shouldAutoFetch = autoFetch !== undefined ? autoFetch : method === "GET";
74
+ const explicitAutoFetch = parseAutoFetch(autoFetch);
75
+ const shouldAutoFetch = explicitAutoFetch ?? method === "GET";
63
76
  const { preloaded, hasExactPreload } = (0, api_call_hooks_1.useIsrPrefetch)(endpointPath, params, method, initialData);
64
77
  const { data, error, loading } = (0, api_call_hooks_1.useApiFetch)({
65
78
  endpointPath,
@@ -0,0 +1,104 @@
1
+ import type { PageMeta, SiteSettings } from "./MetadataOverrides";
2
+ type MaybeString = string | null | undefined;
3
+ type MaybeStringList = string[] | string | null | undefined;
4
+ type JsonLdPayload = Record<string, unknown> | unknown[];
5
+ interface FaqItem {
6
+ question?: MaybeString;
7
+ answer?: MaybeString;
8
+ }
9
+ interface BlogAuthor {
10
+ name?: MaybeString;
11
+ url?: MaybeString;
12
+ type?: MaybeString;
13
+ }
14
+ interface BlogCoverImage {
15
+ slug?: MaybeString;
16
+ title?: MaybeString;
17
+ alt_text?: MaybeString;
18
+ mime_type?: MaybeString;
19
+ public_path?: MaybeString;
20
+ id?: MaybeString;
21
+ }
22
+ interface BlogVersionDefault {
23
+ lecture_time?: MaybeString;
24
+ cover_image?: BlogCoverImage;
25
+ blurb?: MaybeString;
26
+ body?: MaybeString;
27
+ }
28
+ interface BlogPageMeta {
29
+ page_title?: MaybeString;
30
+ permalink?: MaybeString;
31
+ page_type?: MaybeString;
32
+ }
33
+ interface BlogSeoPerPage {
34
+ page_meta_title?: MaybeString;
35
+ page_meta_description?: MaybeString;
36
+ page_robots_follow?: MaybeString;
37
+ page_robots_indexing?: MaybeString;
38
+ page_canonical_url?: MaybeString;
39
+ keywords?: MaybeStringList;
40
+ }
41
+ interface BlogSocialAndSharing {
42
+ page_open_graph_title?: MaybeString;
43
+ page_open_graph_description?: MaybeString;
44
+ page_open_graph_image?: {
45
+ public_path?: MaybeString;
46
+ alt_text?: MaybeString;
47
+ };
48
+ }
49
+ interface BlogVersion {
50
+ created_at?: MaybeString;
51
+ updated_at?: MaybeString;
52
+ title?: MaybeString;
53
+ slug?: MaybeString;
54
+ default?: BlogVersionDefault;
55
+ page_meta?: BlogPageMeta;
56
+ seo_per_page?: BlogSeoPerPage;
57
+ social_and_sharing?: BlogSocialAndSharing;
58
+ }
59
+ interface MetadataSourceInput {
60
+ siteSettings?: SiteSettings | string | null;
61
+ pageMeta?: PageMeta | string | null;
62
+ }
63
+ interface BlogInfo {
64
+ headline?: MaybeString;
65
+ description?: MaybeString;
66
+ image?: MaybeString;
67
+ datePublished?: MaybeString;
68
+ dateModified?: MaybeString;
69
+ articleSection?: MaybeString;
70
+ articleBody?: MaybeString;
71
+ wordCount?: number | string | null;
72
+ keywords?: MaybeStringList;
73
+ schemaId?: MaybeString;
74
+ id?: MaybeString;
75
+ seo_per_page?: BlogSeoPerPage;
76
+ version?: BlogVersion;
77
+ }
78
+ interface BlogAuthorGroup {
79
+ name?: MaybeString;
80
+ url?: MaybeString;
81
+ type?: MaybeString;
82
+ authors?: BlogAuthor[] | string | null;
83
+ }
84
+ export interface FaqJsonLdProps {
85
+ items?: FaqItem[] | string | null;
86
+ metadataSource?: MetadataSourceInput | string | null;
87
+ schemaId?: MaybeString;
88
+ scriptKey?: MaybeString;
89
+ }
90
+ export interface BlogPostingJsonLdProps {
91
+ blog?: BlogInfo | string | null;
92
+ author?: BlogAuthorGroup | string | null;
93
+ metadataSource?: MetadataSourceInput | string | null;
94
+ scriptKey?: MaybeString;
95
+ }
96
+ export interface CustomJsonLdProps {
97
+ schema?: JsonLdPayload | string | null;
98
+ scriptKey?: MaybeString;
99
+ }
100
+ export declare function FaqJsonLd(props: FaqJsonLdProps): import("react/jsx-runtime").JSX.Element | null;
101
+ export declare function BlogPostingJsonLd(props: BlogPostingJsonLdProps): import("react/jsx-runtime").JSX.Element | null;
102
+ export declare function CustomJsonLd(props: CustomJsonLdProps): import("react/jsx-runtime").JSX.Element | null;
103
+ export {};
104
+ //# sourceMappingURL=JsonLdSchemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonLdSchemas.d.ts","sourceRoot":"","sources":["../../src/components/JsonLdSchemas.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FaqJsonLd = FaqJsonLd;
40
+ exports.BlogPostingJsonLd = BlogPostingJsonLd;
41
+ exports.CustomJsonLd = CustomJsonLd;
42
+ const jsx_runtime_1 = require("react/jsx-runtime");
43
+ const React = __importStar(require("react"));
44
+ const head_1 = __importDefault(require("next/head"));
45
+ const seo_utils_1 = require("../lib/seo-utils");
46
+ function resolveMetadataDefaults(metadataSource) {
47
+ const source = (0, seo_utils_1.parseObject)(metadataSource, {
48
+ parseJson: seo_utils_1.tryParseLooseJson
49
+ }) ?? undefined;
50
+ const siteSettings = (0, seo_utils_1.parseObject)(source?.siteSettings, {
51
+ parseJson: seo_utils_1.tryParseLooseJson
52
+ }) ?? undefined;
53
+ const pageMeta = (0, seo_utils_1.parseObject)(source?.pageMeta, {
54
+ parseJson: seo_utils_1.tryParseLooseJson
55
+ }) ?? undefined;
56
+ const canonicalBase = (0, seo_utils_1.pickFirstString)(siteSettings?.seo_defaults?.canonical_base, siteSettings?.domains_and_locales?.primary_domain);
57
+ const url = (0, seo_utils_1.pickFirstString)(pageMeta?.seo_per_page?.page_canonical_url, (0, seo_utils_1.toAbsoluteUrl)(pageMeta?.default?.permalink, canonicalBase), canonicalBase);
58
+ const inLanguage = (0, seo_utils_1.pickFirstString)(siteSettings?.domains_and_locales?.default_locale);
59
+ const canonicalAssetBaseUrl = (0, seo_utils_1.pickFirstString)((0, seo_utils_1.resolveUrlBase)(canonicalBase, url), canonicalBase, url);
60
+ const currentOrigin = (0, seo_utils_1.getCurrentOrigin)();
61
+ const assetBaseUrl = (0, seo_utils_1.pickFirstString)((0, seo_utils_1.resolveUrlBase)(currentOrigin, canonicalAssetBaseUrl), currentOrigin, canonicalAssetBaseUrl);
62
+ return { url, inLanguage, assetBaseUrl };
63
+ }
64
+ function resolveOrganizationId(metadataSource) {
65
+ const source = (0, seo_utils_1.parseObject)(metadataSource, {
66
+ parseJson: seo_utils_1.tryParseLooseJson
67
+ }) ?? undefined;
68
+ const siteSettings = (0, seo_utils_1.parseObject)(source?.siteSettings, {
69
+ parseJson: seo_utils_1.tryParseLooseJson
70
+ }) ?? undefined;
71
+ const pageMeta = (0, seo_utils_1.parseObject)(source?.pageMeta, {
72
+ parseJson: seo_utils_1.tryParseLooseJson
73
+ }) ?? undefined;
74
+ const organizationBase = (0, seo_utils_1.pickFirstString)((0, seo_utils_1.resolveUrlBase)(siteSettings?.seo_defaults?.canonical_base, siteSettings?.domains_and_locales?.primary_domain, pageMeta?.seo_per_page?.page_canonical_url), siteSettings?.seo_defaults?.canonical_base, siteSettings?.domains_and_locales?.primary_domain, pageMeta?.seo_per_page?.page_canonical_url);
75
+ return (0, seo_utils_1.buildOrganizationId)(organizationBase);
76
+ }
77
+ function resolveBlogEntryUrl(blog, metadataDefaults) {
78
+ const canonicalFromBlog = (0, seo_utils_1.cleanString)(blog.version?.seo_per_page?.page_canonical_url ?? blog.seo_per_page?.page_canonical_url);
79
+ if (canonicalFromBlog) {
80
+ return canonicalFromBlog;
81
+ }
82
+ const permalink = (0, seo_utils_1.cleanString)(blog.version?.page_meta?.permalink);
83
+ if (permalink) {
84
+ return (0, seo_utils_1.toAbsoluteUrl)(permalink, metadataDefaults.assetBaseUrl ?? metadataDefaults.url);
85
+ }
86
+ return metadataDefaults.url;
87
+ }
88
+ function toNumber(value) {
89
+ if (typeof value === "number" && Number.isFinite(value)) {
90
+ return value;
91
+ }
92
+ if (typeof value === "string") {
93
+ const trimmed = value.trim();
94
+ if (!trimmed) {
95
+ return undefined;
96
+ }
97
+ const parsed = Number(trimmed);
98
+ if (Number.isFinite(parsed)) {
99
+ return parsed;
100
+ }
101
+ }
102
+ return undefined;
103
+ }
104
+ function decodeHtmlEntities(input) {
105
+ const namedEntities = {
106
+ amp: "&",
107
+ lt: "<",
108
+ gt: ">",
109
+ quot: "\"",
110
+ apos: "'",
111
+ nbsp: " ",
112
+ aacute: "\u00e1",
113
+ eacute: "\u00e9",
114
+ iacute: "\u00ed",
115
+ oacute: "\u00f3",
116
+ uacute: "\u00fa",
117
+ Aacute: "\u00c1",
118
+ Eacute: "\u00c9",
119
+ Iacute: "\u00cd",
120
+ Oacute: "\u00d3",
121
+ Uacute: "\u00da",
122
+ ntilde: "\u00f1",
123
+ Ntilde: "\u00d1",
124
+ uuml: "\u00fc",
125
+ Uuml: "\u00dc"
126
+ };
127
+ return input
128
+ .replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => {
129
+ const code = Number.parseInt(hex, 16);
130
+ return Number.isFinite(code) ? String.fromCodePoint(code) : _;
131
+ })
132
+ .replace(/&#([0-9]+);/g, (_, dec) => {
133
+ const code = Number.parseInt(dec, 10);
134
+ return Number.isFinite(code) ? String.fromCodePoint(code) : _;
135
+ })
136
+ .replace(/&([a-zA-Z][a-zA-Z0-9]+);/g, (entity, name) => namedEntities[name] ?? entity);
137
+ }
138
+ function stripHtmlToText(value) {
139
+ const raw = (0, seo_utils_1.cleanString)(value);
140
+ if (!raw) {
141
+ return undefined;
142
+ }
143
+ const withoutScripts = raw
144
+ .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, " ")
145
+ .replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, " ");
146
+ const withoutTags = withoutScripts.replace(/<[^>]+>/g, " ");
147
+ const decoded = decodeHtmlEntities(withoutTags);
148
+ const normalized = decoded.replace(/\s+/g, " ").trim();
149
+ return normalized || undefined;
150
+ }
151
+ function countWords(value) {
152
+ const text = stripHtmlToText(value) ?? (0, seo_utils_1.cleanString)(value);
153
+ if (!text) {
154
+ return undefined;
155
+ }
156
+ const words = text.split(/\s+/).filter(Boolean);
157
+ return words.length > 0 ? words.length : undefined;
158
+ }
159
+ function uniqStrings(values) {
160
+ return Array.from(new Set(values.map((value) => value.trim()).filter(Boolean)));
161
+ }
162
+ function parseJsonLdPayload(value) {
163
+ if (value == null) {
164
+ return undefined;
165
+ }
166
+ if (typeof value === "object") {
167
+ return value;
168
+ }
169
+ const trimmed = value.trim();
170
+ if (!trimmed) {
171
+ return undefined;
172
+ }
173
+ try {
174
+ const parsed = JSON.parse(trimmed);
175
+ if (parsed && typeof parsed === "object") {
176
+ return parsed;
177
+ }
178
+ }
179
+ catch {
180
+ return undefined;
181
+ }
182
+ return undefined;
183
+ }
184
+ function buildJsonLdKey(prefix, scriptKey, schemaId) {
185
+ const suffix = (0, seo_utils_1.cleanString)(scriptKey) ?? (0, seo_utils_1.cleanString)(schemaId) ?? "default";
186
+ return `jsonld-${prefix}-${suffix}`;
187
+ }
188
+ function JsonLdScript(props) {
189
+ const { payload, headKey } = props;
190
+ const json = React.useMemo(() => (0, seo_utils_1.safeJsonForInlineScript)(payload), [payload]);
191
+ const scriptId = (0, seo_utils_1.toDomId)(headKey);
192
+ React.useEffect(() => {
193
+ const cleanup = () => {
194
+ (0, seo_utils_1.removeDuplicateJsonLdScripts)(scriptId, headKey, json);
195
+ };
196
+ cleanup();
197
+ if (typeof document === "undefined" || typeof MutationObserver === "undefined") {
198
+ return undefined;
199
+ }
200
+ let rafId = null;
201
+ const observer = new MutationObserver(() => {
202
+ if (rafId != null) {
203
+ return;
204
+ }
205
+ rafId = window.requestAnimationFrame(() => {
206
+ rafId = null;
207
+ cleanup();
208
+ });
209
+ });
210
+ observer.observe(document.documentElement, {
211
+ childList: true,
212
+ subtree: true
213
+ });
214
+ return () => {
215
+ observer.disconnect();
216
+ if (rafId != null) {
217
+ window.cancelAnimationFrame(rafId);
218
+ }
219
+ };
220
+ }, [headKey, json, scriptId]);
221
+ return ((0, jsx_runtime_1.jsx)(head_1.default, { children: (0, jsx_runtime_1.jsx)("script", { id: scriptId, type: "application/ld+json", "data-jsonld-key": headKey, dangerouslySetInnerHTML: { __html: json } }, headKey) }));
222
+ }
223
+ function FaqJsonLd(props) {
224
+ const faqItems = React.useMemo(() => (0, seo_utils_1.parseObjectArray)(props.items, { parseJson: seo_utils_1.tryParseLooseJson }), [props.items]);
225
+ const metadataDefaults = React.useMemo(() => resolveMetadataDefaults(props.metadataSource), [props.metadataSource]);
226
+ const inLanguage = metadataDefaults.inLanguage;
227
+ const url = metadataDefaults.url;
228
+ const schemaId = (0, seo_utils_1.cleanString)(props.schemaId) ?? (url ? `${url.replace(/#.*$/, "")}#faq` : undefined);
229
+ const mainEntity = faqItems
230
+ .map((item) => {
231
+ const question = (0, seo_utils_1.cleanString)(item.question);
232
+ const answer = (0, seo_utils_1.cleanString)(item.answer);
233
+ if (!question || !answer) {
234
+ return null;
235
+ }
236
+ return {
237
+ "@type": "Question",
238
+ name: question,
239
+ acceptedAnswer: {
240
+ "@type": "Answer",
241
+ text: answer
242
+ }
243
+ };
244
+ })
245
+ .filter((item) => Boolean(item));
246
+ if (mainEntity.length === 0) {
247
+ return null;
248
+ }
249
+ const schema = {
250
+ "@context": "https://schema.org",
251
+ "@type": "FAQPage",
252
+ mainEntity
253
+ };
254
+ if (schemaId) {
255
+ schema["@id"] = schemaId;
256
+ }
257
+ if (url) {
258
+ schema.url = url;
259
+ }
260
+ if (inLanguage) {
261
+ schema.inLanguage = inLanguage;
262
+ }
263
+ return ((0, jsx_runtime_1.jsx)(JsonLdScript, { payload: schema, headKey: buildJsonLdKey("faq", props.scriptKey, schemaId) }));
264
+ }
265
+ function BlogPostingJsonLd(props) {
266
+ const blog = React.useMemo(() => (0, seo_utils_1.parseObject)(props.blog, { parseJson: seo_utils_1.tryParseLooseJson }) ?? {}, [props.blog]);
267
+ const authorGroup = React.useMemo(() => (0, seo_utils_1.parseObject)(props.author, { parseJson: seo_utils_1.tryParseLooseJson }) ?? {}, [props.author]);
268
+ const metadataDefaults = React.useMemo(() => resolveMetadataDefaults(props.metadataSource), [props.metadataSource]);
269
+ const organizationId = React.useMemo(() => resolveOrganizationId(props.metadataSource), [props.metadataSource]);
270
+ const headline = (0, seo_utils_1.pickFirstString)(blog.version?.social_and_sharing?.page_open_graph_title, blog.version?.seo_per_page?.page_meta_title, blog.seo_per_page?.page_meta_title, blog.version?.page_meta?.page_title, blog.version?.title, blog.headline);
271
+ if (!headline) {
272
+ return null;
273
+ }
274
+ const description = (0, seo_utils_1.pickFirstString)(blog.version?.social_and_sharing?.page_open_graph_description, blog.version?.seo_per_page?.page_meta_description, blog.seo_per_page?.page_meta_description, stripHtmlToText(blog.version?.default?.blurb), stripHtmlToText(blog.version?.default?.body));
275
+ const url = resolveBlogEntryUrl(blog, metadataDefaults);
276
+ const assetBaseUrl = (0, seo_utils_1.pickFirstString)((0, seo_utils_1.resolveUrlBase)(url, metadataDefaults.assetBaseUrl, metadataDefaults.url), metadataDefaults.assetBaseUrl, metadataDefaults.url, url);
277
+ const image = (0, seo_utils_1.toAbsoluteUrl)((0, seo_utils_1.pickFirstString)(blog.version?.social_and_sharing?.page_open_graph_image?.public_path, blog.version?.default?.cover_image?.public_path, blog.image), assetBaseUrl);
278
+ const datePublished = (0, seo_utils_1.pickFirstString)(blog.version?.created_at, blog.datePublished);
279
+ const dateModified = (0, seo_utils_1.pickFirstString)(blog.version?.updated_at, blog.dateModified);
280
+ const inLanguage = metadataDefaults.inLanguage;
281
+ const articleSection = (0, seo_utils_1.pickFirstString)(blog.articleSection, blog.version?.page_meta?.page_type);
282
+ const articleBody = (0, seo_utils_1.pickFirstString)(stripHtmlToText(blog.articleBody), stripHtmlToText(blog.version?.default?.body), (0, seo_utils_1.cleanString)(blog.articleBody), (0, seo_utils_1.cleanString)(blog.version?.default?.body));
283
+ const wordCount = toNumber(blog.wordCount) ?? countWords(articleBody ?? blog.version?.default?.body);
284
+ const blogId = (0, seo_utils_1.cleanString)(blog.id);
285
+ const schemaId = (0, seo_utils_1.cleanString)(blog.schemaId) ??
286
+ (blogId && url ? `${url.replace(/#.*$/, "")}#blog-posting-${blogId}` : undefined);
287
+ const seoKeywords = (0, seo_utils_1.parseStringList)(blog.version?.seo_per_page?.keywords ?? blog.seo_per_page?.keywords);
288
+ const explicitKeywords = (0, seo_utils_1.parseStringList)(blog.keywords);
289
+ const keywords = uniqStrings([...seoKeywords, ...explicitKeywords]);
290
+ const parsedAuthors = (0, seo_utils_1.parseObjectArray)(authorGroup.authors, {
291
+ parseJson: seo_utils_1.tryParseLooseJson
292
+ });
293
+ const fallbackAuthorName = (0, seo_utils_1.cleanString)(authorGroup.name);
294
+ const fallbackAuthorUrl = (0, seo_utils_1.cleanString)(authorGroup.url);
295
+ const fallbackAuthorType = (0, seo_utils_1.cleanString)(authorGroup.type) ?? "Person";
296
+ const authorNodes = parsedAuthors
297
+ .map((author) => {
298
+ const authorName = (0, seo_utils_1.cleanString)(author.name);
299
+ if (!authorName) {
300
+ return null;
301
+ }
302
+ const authorUrl = (0, seo_utils_1.cleanString)(author.url);
303
+ const authorType = (0, seo_utils_1.cleanString)(author.type) ?? "Person";
304
+ return {
305
+ "@type": authorType,
306
+ name: authorName,
307
+ ...(authorUrl ? { url: authorUrl } : {})
308
+ };
309
+ })
310
+ .filter((item) => Boolean(item));
311
+ if (authorNodes.length === 0 && fallbackAuthorName) {
312
+ authorNodes.push({
313
+ "@type": fallbackAuthorType,
314
+ name: fallbackAuthorName,
315
+ ...(fallbackAuthorUrl ? { url: fallbackAuthorUrl } : {})
316
+ });
317
+ }
318
+ const schema = {
319
+ "@context": "https://schema.org",
320
+ "@type": "BlogPosting",
321
+ headline
322
+ };
323
+ if (schemaId) {
324
+ schema["@id"] = schemaId;
325
+ }
326
+ if (description) {
327
+ schema.description = description;
328
+ }
329
+ if (url) {
330
+ schema.url = url;
331
+ schema.mainEntityOfPage = {
332
+ "@type": "WebPage",
333
+ "@id": url
334
+ };
335
+ }
336
+ if (image) {
337
+ schema.image = image;
338
+ }
339
+ if (datePublished) {
340
+ schema.datePublished = datePublished;
341
+ }
342
+ if (dateModified) {
343
+ schema.dateModified = dateModified;
344
+ }
345
+ if (inLanguage) {
346
+ schema.inLanguage = inLanguage;
347
+ }
348
+ if (articleSection) {
349
+ schema.articleSection = articleSection;
350
+ }
351
+ if (articleBody) {
352
+ schema.articleBody = articleBody;
353
+ }
354
+ if (wordCount !== undefined) {
355
+ schema.wordCount = wordCount;
356
+ }
357
+ if (keywords.length > 0) {
358
+ schema.keywords = keywords;
359
+ }
360
+ if (authorNodes.length === 1) {
361
+ schema.author = authorNodes[0];
362
+ }
363
+ else if (authorNodes.length > 1) {
364
+ schema.author = authorNodes;
365
+ }
366
+ if (organizationId) {
367
+ schema.publisher = {
368
+ "@id": organizationId
369
+ };
370
+ }
371
+ return ((0, jsx_runtime_1.jsx)(JsonLdScript, { payload: schema, headKey: buildJsonLdKey("blog", props.scriptKey, schemaId) }));
372
+ }
373
+ function CustomJsonLd(props) {
374
+ const payload = React.useMemo(() => parseJsonLdPayload(props.schema), [props.schema]);
375
+ if (!payload) {
376
+ return null;
377
+ }
378
+ const headKey = buildJsonLdKey("custom", props.scriptKey);
379
+ return (0, jsx_runtime_1.jsx)(JsonLdScript, { payload: payload, headKey: headKey });
380
+ }