@gosalesdeal/blog 0.1.0 → 0.3.0

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 (50) hide show
  1. package/README.md +265 -34
  2. package/dist/client/blogClient.js +79 -13
  3. package/dist/client/blogClient.js.map +1 -1
  4. package/dist/components/BlogPost.d.ts +12 -1
  5. package/dist/components/BlogPost.js +27 -16
  6. package/dist/components/BlogPost.js.map +1 -1
  7. package/dist/components/BlogPostHeader.d.ts +15 -0
  8. package/dist/components/BlogPostHeader.js +41 -0
  9. package/dist/components/BlogPostHeader.js.map +1 -0
  10. package/dist/components/landing/BlogLayoutComponents.d.ts +14 -0
  11. package/dist/components/landing/BlogLayoutComponents.js +198 -0
  12. package/dist/components/landing/BlogLayoutComponents.js.map +1 -0
  13. package/dist/components/landing/FlexibleLayoutComponent.d.ts +40 -0
  14. package/dist/components/landing/FlexibleLayoutComponent.js +352 -0
  15. package/dist/components/landing/FlexibleLayoutComponent.js.map +1 -0
  16. package/dist/components/landing/HeroFeatureBanner.d.ts +36 -0
  17. package/dist/components/landing/HeroFeatureBanner.js +88 -0
  18. package/dist/components/landing/HeroFeatureBanner.js.map +1 -0
  19. package/dist/components/landing/HeroFeatureBannerComponent.d.ts +4 -0
  20. package/dist/components/landing/HeroFeatureBannerComponent.js +100 -0
  21. package/dist/components/landing/HeroFeatureBannerComponent.js.map +1 -0
  22. package/dist/components/landing/HeroFeatureBannerVideo.d.ts +34 -0
  23. package/dist/components/landing/HeroFeatureBannerVideo.js +261 -0
  24. package/dist/components/landing/HeroFeatureBannerVideo.js.map +1 -0
  25. package/dist/components/landing/HeroFeatureBannerVideoComponent.d.ts +5 -0
  26. package/dist/components/landing/HeroFeatureBannerVideoComponent.js +69 -0
  27. package/dist/components/landing/HeroFeatureBannerVideoComponent.js.map +1 -0
  28. package/dist/components/landing/VarietyReviewslistComponent.d.ts +4 -0
  29. package/dist/components/landing/VarietyReviewslistComponent.js +172 -0
  30. package/dist/components/landing/VarietyReviewslistComponent.js.map +1 -0
  31. package/dist/index.d.ts +13 -0
  32. package/dist/index.js +25 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/lib/postUtils.d.ts +3 -0
  35. package/dist/lib/postUtils.js +8 -0
  36. package/dist/lib/postUtils.js.map +1 -0
  37. package/dist/lib/resolveMediaSrc.d.ts +2 -0
  38. package/dist/lib/resolveMediaSrc.js +21 -0
  39. package/dist/lib/resolveMediaSrc.js.map +1 -0
  40. package/dist/render/BlockRenderer.js +5 -0
  41. package/dist/render/BlockRenderer.js.map +1 -1
  42. package/dist/render/LandingPageRenderer.d.ts +5 -0
  43. package/dist/render/LandingPageRenderer.js +50 -0
  44. package/dist/render/LandingPageRenderer.js.map +1 -0
  45. package/dist/render/landingPageHtml.d.ts +28 -0
  46. package/dist/render/landingPageHtml.js +205 -0
  47. package/dist/render/landingPageHtml.js.map +1 -0
  48. package/dist/styles.css +27 -0
  49. package/dist/types/blog.d.ts +8 -2
  50. package/package.json +13 -3
@@ -0,0 +1,172 @@
1
+ "use client";
2
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
+ import React, { useState } from "react";
4
+ const resolveContainerMargin = (position) => {
5
+ switch (position) {
6
+ case "left":
7
+ return { marginLeft: 0, marginRight: "auto" };
8
+ case "right":
9
+ return { marginLeft: "auto", marginRight: 0 };
10
+ default:
11
+ return { marginLeft: "auto", marginRight: "auto" };
12
+ }
13
+ };
14
+ const StarRating = ({
15
+ rating,
16
+ total,
17
+ color,
18
+ size
19
+ }) => /* @__PURE__ */ jsx(Fragment, { children: Array.from({ length: total }).map((_, i) => /* @__PURE__ */ jsx(
20
+ "svg",
21
+ {
22
+ width: size,
23
+ height: size,
24
+ viewBox: "0 0 20 20",
25
+ fill: i < rating ? color : "#d1d5db",
26
+ style: { marginRight: "2px" },
27
+ xmlns: "http://www.w3.org/2000/svg",
28
+ children: /* @__PURE__ */ jsx("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.286 3.967a1 1 0 00.95.69h4.174c.969 0 1.371 1.24.588 1.81l-3.377 2.454a1 1 0 00-.364 1.118l1.286 3.967c.3.921-.755 1.688-1.54 1.118L10 14.347l-3.377 2.454c-.784.57-1.838-.197-1.54-1.118l1.287-3.967a1 1 0 00-.364-1.118L2.629 9.394c-.783-.57-.38-1.81.588-1.81h4.174a1 1 0 00.95-.69l1.287-3.967z" })
29
+ },
30
+ i
31
+ )) });
32
+ const QARow = ({ item, props, isLast }) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
33
+ /* @__PURE__ */ jsxs("div", { style: { paddingTop: props.qaRowPaddingY, paddingBottom: props.qaRowPaddingY }, children: [
34
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "flex-start", marginBottom: "6px" }, children: [
35
+ /* @__PURE__ */ jsxs("span", { style: {
36
+ color: props.qaLabelColor,
37
+ fontSize: props.qaLabelFontSize,
38
+ fontWeight: props.qaLabelFontWeight,
39
+ minWidth: "20px",
40
+ marginRight: "6px",
41
+ flexShrink: 0
42
+ }, children: [
43
+ props.qaLabelQ,
44
+ ":"
45
+ ] }),
46
+ /* @__PURE__ */ jsx("span", { style: {
47
+ color: props.qaQuestionColor,
48
+ fontSize: props.qaQuestionFontSize,
49
+ fontWeight: props.qaQuestionFontWeight || "700",
50
+ lineHeight: "1.5"
51
+ }, children: item.question })
52
+ ] }),
53
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "flex-start", marginBottom: "8px" }, children: [
54
+ /* @__PURE__ */ jsxs("span", { style: {
55
+ color: props.qaLabelColor,
56
+ fontSize: props.qaLabelFontSize,
57
+ fontWeight: props.qaLabelFontWeight,
58
+ minWidth: "20px",
59
+ marginRight: "6px",
60
+ flexShrink: 0
61
+ }, children: [
62
+ props.qaLabelA,
63
+ ":"
64
+ ] }),
65
+ /* @__PURE__ */ jsx("span", { style: {
66
+ color: props.qaAnswerColor,
67
+ fontSize: props.qaAnswerFontSize,
68
+ lineHeight: "1.5"
69
+ }, children: item.answer })
70
+ ] }),
71
+ /* @__PURE__ */ jsxs("div", { style: {
72
+ color: props.qaAskedByColor,
73
+ fontSize: props.qaAskedByFontSize,
74
+ display: "flex",
75
+ alignItems: "center",
76
+ gap: "4px"
77
+ }, children: [
78
+ /* @__PURE__ */ jsx("span", { children: props.qaAskedByPrefix }),
79
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: "600", color: props.qaAskedByColor }, children: item.author }),
80
+ /* @__PURE__ */ jsx("span", { children: props.qaMetaSeparator }),
81
+ /* @__PURE__ */ jsx("span", { children: item.date })
82
+ ] })
83
+ ] }),
84
+ !isLast && /* @__PURE__ */ jsx("div", { style: { height: props.dividerHeight, backgroundColor: props.dividerColor, width: "100%" } })
85
+ ] });
86
+ const ReviewsListRender = ({ props }) => {
87
+ const [activeTab, setActiveTab] = useState(props.activeTabKey || "reviews");
88
+ const [currentPage, setCurrentPage] = useState(1);
89
+ const reviews = props.reviews || [];
90
+ const qaItems = props.qa || [];
91
+ const containerMargin = resolveContainerMargin(props.containerPosition || "center");
92
+ return /* @__PURE__ */ jsx("section", { className: props.sectionClassName, style: { backgroundColor: props.sectionBgColor }, children: /* @__PURE__ */ jsxs(
93
+ "div",
94
+ {
95
+ className: props.containerClassName,
96
+ style: { maxWidth: props.containerMaxWidth, ...containerMargin },
97
+ children: [
98
+ props.tabsEnabled && props.tabs?.length > 0 && /* @__PURE__ */ jsx("div", { className: props.tabsWrapperClassName, children: props.tabs.map((tab) => {
99
+ const isActive = activeTab === tab.key;
100
+ return /* @__PURE__ */ jsx(
101
+ "span",
102
+ {
103
+ onClick: () => setActiveTab(tab.key),
104
+ className: isActive ? props.activeTabClassName : props.inactiveTabClassName,
105
+ style: {
106
+ color: isActive ? props.activeTabColor : props.inactiveTabColor,
107
+ fontSize: isActive ? props.activeTabFontSize : props.inactiveTabFontSize,
108
+ borderBottomColor: isActive ? props.activeTabBorderColor : "transparent",
109
+ borderBottomStyle: "solid",
110
+ borderBottomWidth: isActive ? "2px" : "0",
111
+ paddingBottom: "8px",
112
+ marginRight: "16px",
113
+ cursor: "pointer",
114
+ display: "inline-block",
115
+ userSelect: "none"
116
+ },
117
+ children: tab.label
118
+ },
119
+ tab.key
120
+ );
121
+ }) }),
122
+ activeTab === "reviews" && /* @__PURE__ */ jsxs(Fragment, { children: [
123
+ reviews.map((review, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
124
+ /* @__PURE__ */ jsxs(
125
+ "div",
126
+ {
127
+ className: props.reviewRowClassName,
128
+ style: { display: "flex", paddingTop: "16px", paddingBottom: "16px" },
129
+ children: [
130
+ /* @__PURE__ */ jsx("div", { className: props.leftColumnClassName, style: { width: props.leftColumnWidth, flexShrink: 0 }, children: /* @__PURE__ */ jsx("span", { className: props.reviewerNameClassName, style: { color: props.reviewerNameColor, fontSize: props.reviewerNameFontSize, display: "block" }, children: review.reviewer }) }),
131
+ /* @__PURE__ */ jsxs("div", { className: props.middleColumnClassName, style: { flex: 1, paddingLeft: "12px", paddingRight: "12px" }, children: [
132
+ /* @__PURE__ */ jsx("div", { className: props.starsWrapperClassName, style: { display: "flex", alignItems: "center", marginBottom: "4px" }, children: /* @__PURE__ */ jsx(StarRating, { rating: review.rating, total: props.starCount || 5, color: props.starColor, size: props.starSize }) }),
133
+ /* @__PURE__ */ jsx("div", { className: props.reviewTitleClassName, style: { color: props.reviewTitleColor, fontSize: props.reviewTitleFontSize, fontWeight: "700", marginBottom: "4px" }, children: review.title }),
134
+ /* @__PURE__ */ jsx("div", { className: props.reviewBodyClassName, style: { color: props.reviewBodyColor, fontSize: props.reviewBodyFontSize, lineHeight: "1.5" }, children: review.body })
135
+ ] }),
136
+ /* @__PURE__ */ jsxs("div", { className: props.rightColumnClassName, style: { width: props.rightColumnWidth, flexShrink: 0, textAlign: "right" }, children: [
137
+ /* @__PURE__ */ jsx("div", { className: props.dateClassName, style: { color: props.dateColor, fontSize: props.dateFontSize, marginBottom: "4px" }, children: review.date }),
138
+ props.verifiedBadgeEnabled && review.verified && /* @__PURE__ */ jsx("div", { className: props.verifiedBadgeClassName, style: { color: props.verifiedBadgeColor, fontSize: props.verifiedBadgeFontSize }, children: props.verifiedBadgeText })
139
+ ] })
140
+ ]
141
+ }
142
+ ),
143
+ index < reviews.length - 1 && /* @__PURE__ */ jsx("div", { style: { height: props.dividerHeight, backgroundColor: props.dividerColor, width: "100%" } })
144
+ ] }, index)),
145
+ props.paginationEnabled && props.totalPages > 1 && /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", gap: "6px", paddingTop: "16px", paddingBottom: "8px" }, children: Array.from({ length: props.totalPages }).map((_, i) => {
146
+ const page = i + 1;
147
+ const isActive = currentPage === page;
148
+ return /* @__PURE__ */ jsx("button", { onClick: () => setCurrentPage(page), style: {
149
+ width: props.paginationSize,
150
+ height: props.paginationSize,
151
+ borderRadius: props.paginationBorderRadius,
152
+ fontSize: props.paginationFontSize,
153
+ backgroundColor: isActive ? props.paginationActiveBgColor : props.paginationInactiveBgColor,
154
+ color: isActive ? props.paginationActiveColor : props.paginationInactiveColor,
155
+ border: "none",
156
+ cursor: "pointer",
157
+ display: "flex",
158
+ alignItems: "center",
159
+ justifyContent: "center",
160
+ fontWeight: isActive ? "700" : "500"
161
+ }, children: page }, page);
162
+ }) })
163
+ ] }),
164
+ activeTab === "qa" && /* @__PURE__ */ jsx(Fragment, { children: qaItems.length === 0 ? /* @__PURE__ */ jsx("div", { style: { color: "#9ca3af", fontSize: "0.9rem", padding: "24px 0" }, children: "No questions yet." }) : qaItems.map((item, index) => /* @__PURE__ */ jsx(QARow, { item, props, isLast: index === qaItems.length - 1 }, index)) })
165
+ ]
166
+ }
167
+ ) });
168
+ };
169
+ export {
170
+ ReviewsListRender
171
+ };
172
+ //# sourceMappingURL=VarietyReviewslistComponent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VarietyReviewslistComponent.js","sources":["../../../src/components/landing/VarietyReviewslistComponent.tsx"],"sourcesContent":["\"use client\"\nimport React, { useState } from \"react\";\n\n\n\n\nconst resolveContainerMargin = (position: string): React.CSSProperties => {\n switch (position) {\n case \"left\": return { marginLeft: 0, marginRight: \"auto\" };\n case \"right\": return { marginLeft: \"auto\", marginRight: 0 };\n default: return { marginLeft: \"auto\", marginRight: \"auto\" }; // center\n }\n};\n\n// ─── Star renderer ────────────────────────────────────────────────────────────\nconst StarRating: React.FC<{ rating: number; total: number; color: string; size: string }> = ({\n rating, total, color, size,\n}) => (\n <>\n {Array.from({ length: total }).map((_, i) => (\n <svg key={i} width={size} height={size} viewBox=\"0 0 20 20\"\n fill={i < rating ? color : \"#d1d5db\"}\n style={{ marginRight: \"2px\" }}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.286 3.967a1 1 0 00.95.69h4.174c.969 0 1.371 1.24.588 1.81l-3.377 2.454a1 1 0 00-.364 1.118l1.286 3.967c.3.921-.755 1.688-1.54 1.118L10 14.347l-3.377 2.454c-.784.57-1.838-.197-1.54-1.118l1.287-3.967a1 1 0 00-.364-1.118L2.629 9.394c-.783-.57-.38-1.81.588-1.81h4.174a1 1 0 00.95-.69l1.287-3.967z\" />\n </svg>\n ))}\n </>\n);\n\n// ─── Q&A row ─────────────────────────────────────────────────────────────────\nconst QARow: React.FC<{ item: any; props: any; isLast: boolean }> = ({ item, props, isLast }) => (\n <React.Fragment>\n <div style={{ paddingTop: props.qaRowPaddingY, paddingBottom: props.qaRowPaddingY }}>\n\n {/* Q line */}\n <div style={{ display: \"flex\", alignItems: \"flex-start\", marginBottom: \"6px\" }}>\n <span style={{\n color: props.qaLabelColor,\n fontSize: props.qaLabelFontSize,\n fontWeight: props.qaLabelFontWeight,\n minWidth: \"20px\",\n marginRight: \"6px\",\n flexShrink: 0,\n }}>\n {props.qaLabelQ}:\n </span>\n <span style={{\n color: props.qaQuestionColor,\n fontSize: props.qaQuestionFontSize,\n fontWeight: props.qaQuestionFontWeight || \"700\",\n lineHeight: \"1.5\",\n }}>\n {item.question}\n </span>\n </div>\n\n {/* A line */}\n <div style={{ display: \"flex\", alignItems: \"flex-start\", marginBottom: \"8px\" }}>\n <span style={{\n color: props.qaLabelColor,\n fontSize: props.qaLabelFontSize,\n fontWeight: props.qaLabelFontWeight,\n minWidth: \"20px\",\n marginRight: \"6px\",\n flexShrink: 0,\n }}>\n {props.qaLabelA}:\n </span>\n <span style={{\n color: props.qaAnswerColor,\n fontSize: props.qaAnswerFontSize,\n lineHeight: \"1.5\",\n }}>\n {item.answer}\n </span>\n </div>\n\n {/* Meta — \"Asked by Ahmed • 12/08/25\" */}\n <div style={{\n color: props.qaAskedByColor,\n fontSize: props.qaAskedByFontSize,\n display: \"flex\",\n alignItems: \"center\",\n gap: \"4px\",\n }}>\n <span>{props.qaAskedByPrefix}</span>\n <span style={{ fontWeight: \"600\", color: props.qaAskedByColor }}>{item.author}</span>\n <span>{props.qaMetaSeparator}</span>\n <span>{item.date}</span>\n </div>\n </div>\n\n {/* Divider */}\n {!isLast && (\n <div style={{ height: props.dividerHeight, backgroundColor: props.dividerColor, width: \"100%\" }} />\n )}\n </React.Fragment>\n);\n\n// ─── Main render ──────────────────────────────────────────────────────────────\nexport const ReviewsListRender: React.FC<{ props: Record<string, any> }> = ({ props }) => {\n\n const [activeTab, setActiveTab] = useState<string>(props.activeTabKey || \"reviews\");\n const [currentPage, setCurrentPage] = useState<number>(1);\n\n const reviews: any[] = props.reviews || [];\n const qaItems: any[] = props.qa || [];\n\n const containerMargin = resolveContainerMargin(props.containerPosition || \"center\");\n\n return (\n <section className={props.sectionClassName} style={{ backgroundColor: props.sectionBgColor }}>\n <div\n className={props.containerClassName}\n style={{ maxWidth: props.containerMaxWidth, ...containerMargin }}\n >\n {/* ── Tabs ── */}\n {props.tabsEnabled && props.tabs?.length > 0 && (\n <div className={props.tabsWrapperClassName}>\n {props.tabs.map((tab: { label: string; key: string }) => {\n const isActive = activeTab === tab.key;\n return (\n <span\n key={tab.key}\n onClick={() => setActiveTab(tab.key)}\n className={isActive ? props.activeTabClassName : props.inactiveTabClassName}\n style={{\n color: isActive ? props.activeTabColor : props.inactiveTabColor,\n fontSize: isActive ? props.activeTabFontSize : props.inactiveTabFontSize,\n borderBottomColor: isActive ? props.activeTabBorderColor : \"transparent\",\n borderBottomStyle: \"solid\",\n borderBottomWidth: isActive ? \"2px\" : \"0\",\n paddingBottom: \"8px\",\n marginRight: \"16px\",\n cursor: \"pointer\",\n display: \"inline-block\",\n userSelect: \"none\",\n }}\n >\n {tab.label}\n </span>\n );\n })}\n </div>\n )}\n\n {/* ── Reviews tab ── */}\n {activeTab === \"reviews\" && (\n <>\n {reviews.map((review: any, index: number) => (\n <React.Fragment key={index}>\n <div\n className={props.reviewRowClassName}\n style={{ display: \"flex\", paddingTop: \"16px\", paddingBottom: \"16px\" }}\n >\n {/* Left — Reviewer name */}\n <div className={props.leftColumnClassName} style={{ width: props.leftColumnWidth, flexShrink: 0 }}>\n <span className={props.reviewerNameClassName} style={{ color: props.reviewerNameColor, fontSize: props.reviewerNameFontSize, display: \"block\" }}>\n {review.reviewer}\n </span>\n </div>\n\n {/* Middle — Stars, title, body */}\n <div className={props.middleColumnClassName} style={{ flex: 1, paddingLeft: \"12px\", paddingRight: \"12px\" }}>\n <div className={props.starsWrapperClassName} style={{ display: \"flex\", alignItems: \"center\", marginBottom: \"4px\" }}>\n <StarRating rating={review.rating} total={props.starCount || 5} color={props.starColor} size={props.starSize} />\n </div>\n <div className={props.reviewTitleClassName} style={{ color: props.reviewTitleColor, fontSize: props.reviewTitleFontSize, fontWeight: \"700\", marginBottom: \"4px\" }}>\n {review.title}\n </div>\n <div className={props.reviewBodyClassName} style={{ color: props.reviewBodyColor, fontSize: props.reviewBodyFontSize, lineHeight: \"1.5\" }}>\n {review.body}\n </div>\n </div>\n\n {/* Right — Date + Verified */}\n <div className={props.rightColumnClassName} style={{ width: props.rightColumnWidth, flexShrink: 0, textAlign: \"right\" }}>\n <div className={props.dateClassName} style={{ color: props.dateColor, fontSize: props.dateFontSize, marginBottom: \"4px\" }}>\n {review.date}\n </div>\n {props.verifiedBadgeEnabled && review.verified && (\n <div className={props.verifiedBadgeClassName} style={{ color: props.verifiedBadgeColor, fontSize: props.verifiedBadgeFontSize }}>\n {props.verifiedBadgeText}\n </div>\n )}\n </div>\n </div>\n\n {index < reviews.length - 1 && (\n <div style={{ height: props.dividerHeight, backgroundColor: props.dividerColor, width: \"100%\" }} />\n )}\n </React.Fragment>\n ))}\n\n {/* Pagination */}\n {props.paginationEnabled && props.totalPages > 1 && (\n <div style={{ display: \"flex\", justifyContent: \"center\", alignItems: \"center\", gap: \"6px\", paddingTop: \"16px\", paddingBottom: \"8px\" }}>\n {Array.from({ length: props.totalPages }).map((_, i) => {\n const page = i + 1;\n const isActive = currentPage === page;\n return (\n <button key={page} onClick={() => setCurrentPage(page)} style={{\n width: props.paginationSize,\n height: props.paginationSize,\n borderRadius: props.paginationBorderRadius,\n fontSize: props.paginationFontSize,\n backgroundColor: isActive ? props.paginationActiveBgColor : props.paginationInactiveBgColor,\n color: isActive ? props.paginationActiveColor : props.paginationInactiveColor,\n border: \"none\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontWeight: isActive ? \"700\" : \"500\",\n }}>\n {page}\n </button>\n );\n })}\n </div>\n )}\n </>\n )}\n\n {/* ── Q&A tab ── */}\n {activeTab === \"qa\" && (\n <>\n {qaItems.length === 0 ? (\n <div style={{ color: \"#9ca3af\", fontSize: \"0.9rem\", padding: \"24px 0\" }}>\n No questions yet.\n </div>\n ) : (\n qaItems.map((item: any, index: number) => (\n <QARow key={index} item={item} props={props} isLast={index === qaItems.length - 1} />\n ))\n )}\n </>\n )}\n </div>\n </section>\n );\n};"],"names":[],"mappings":";;;AAMA,MAAM,yBAAyB,CAAC,aAA0C;AACtE,UAAQ,UAAA;AAAA,IACJ,KAAK;AAAS,aAAO,EAAE,YAAY,GAAO,aAAa,OAAA;AAAA,IACvD,KAAK;AAAS,aAAO,EAAE,YAAY,QAAQ,aAAa,EAAA;AAAA,IACxD;AAAc,aAAO,EAAE,YAAY,QAAQ,aAAa,OAAA;AAAA,EAAO;AAEvE;AAGA,MAAM,aAAuF,CAAC;AAAA,EAC1F;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAO;AAC1B,MACI,oBAAA,UAAA,EACK,UAAA,MAAM,KAAK,EAAE,QAAQ,MAAA,CAAO,EAAE,IAAI,CAAC,GAAG,MACnC;AAAA,EAAC;AAAA,EAAA;AAAA,IAAY,OAAO;AAAA,IAAM,QAAQ;AAAA,IAAM,SAAQ;AAAA,IAC5C,MAAM,IAAI,SAAS,QAAQ;AAAA,IAC3B,OAAO,EAAE,aAAa,MAAA;AAAA,IACtB,OAAM;AAAA,IAEN,UAAA,oBAAC,QAAA,EAAK,GAAE,iVAAA,CAAiV;AAAA,EAAA;AAAA,EALnV;AAMV,CACH,GACL;AAIJ,MAAM,QAA8D,CAAC,EAAE,MAAM,OAAO,aAChF,qBAAC,MAAM,UAAN,EACG,UAAA;AAAA,EAAA,qBAAC,OAAA,EAAI,OAAO,EAAE,YAAY,MAAM,eAAe,eAAe,MAAM,cAAA,GAGhE,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,cAAc,cAAc,MAAA,GACnE,UAAA;AAAA,MAAA,qBAAC,UAAK,OAAO;AAAA,QACT,OAAY,MAAM;AAAA,QAClB,UAAY,MAAM;AAAA,QAClB,YAAY,MAAM;AAAA,QAClB,UAAY;AAAA,QACZ,aAAa;AAAA,QACb,YAAY;AAAA,MAAA,GAEX,UAAA;AAAA,QAAA,MAAM;AAAA,QAAS;AAAA,MAAA,GACpB;AAAA,MACA,oBAAC,UAAK,OAAO;AAAA,QACT,OAAY,MAAM;AAAA,QAClB,UAAY,MAAM;AAAA,QAClB,YAAY,MAAM,wBAAwB;AAAA,QAC1C,YAAY;AAAA,MAAA,GAEX,eAAK,SAAA,CACV;AAAA,IAAA,GACJ;AAAA,IAGA,qBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,YAAY,cAAc,cAAc,MAAA,GACnE,UAAA;AAAA,MAAA,qBAAC,UAAK,OAAO;AAAA,QACT,OAAY,MAAM;AAAA,QAClB,UAAY,MAAM;AAAA,QAClB,YAAY,MAAM;AAAA,QAClB,UAAY;AAAA,QACZ,aAAa;AAAA,QACb,YAAY;AAAA,MAAA,GAEX,UAAA;AAAA,QAAA,MAAM;AAAA,QAAS;AAAA,MAAA,GACpB;AAAA,MACA,oBAAC,UAAK,OAAO;AAAA,QACT,OAAU,MAAM;AAAA,QAChB,UAAU,MAAM;AAAA,QAChB,YAAY;AAAA,MAAA,GAEX,eAAK,OAAA,CACV;AAAA,IAAA,GACJ;AAAA,IAGA,qBAAC,SAAI,OAAO;AAAA,MACR,OAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAU;AAAA,MACV,YAAY;AAAA,MACZ,KAAK;AAAA,IAAA,GAEL,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAM,gBAAM,gBAAA,CAAgB;AAAA,MAC7B,oBAAC,QAAA,EAAK,OAAO,EAAE,YAAY,OAAO,OAAO,MAAM,eAAA,GAAmB,UAAA,KAAK,OAAA,CAAO;AAAA,MAC9E,oBAAC,QAAA,EAAM,UAAA,MAAM,gBAAA,CAAgB;AAAA,MAC7B,oBAAC,QAAA,EAAM,UAAA,KAAK,KAAA,CAAK;AAAA,IAAA,EAAA,CACrB;AAAA,EAAA,GACJ;AAAA,EAGC,CAAC,UACE,oBAAC,OAAA,EAAI,OAAO,EAAE,QAAQ,MAAM,eAAe,iBAAiB,MAAM,cAAc,OAAO,SAAO,CAAG;AAAA,GAEzG;AAIG,MAAM,oBAA8D,CAAC,EAAE,YAAY;AAEtF,QAAM,CAAC,WAAW,YAAY,IAAI,SAAiB,MAAM,gBAAgB,SAAS;AAClF,QAAM,CAAC,aAAa,cAAc,IAAI,SAAiB,CAAC;AAExD,QAAM,UAAiB,MAAM,WAAW,CAAA;AACxC,QAAM,UAAiB,MAAM,MAAM,CAAA;AAEnC,QAAM,kBAAkB,uBAAuB,MAAM,qBAAqB,QAAQ;AAElF,SACI,oBAAC,WAAA,EAAQ,WAAW,MAAM,kBAAkB,OAAO,EAAE,iBAAiB,MAAM,eAAA,GACxE,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,WAAW,MAAM;AAAA,MACjB,OAAO,EAAE,UAAU,MAAM,mBAAmB,GAAG,gBAAA;AAAA,MAG9C,UAAA;AAAA,QAAA,MAAM,eAAe,MAAM,MAAM,SAAS,KACvC,oBAAC,OAAA,EAAI,WAAW,MAAM,sBACjB,UAAA,MAAM,KAAK,IAAI,CAAC,QAAwC;AACrD,gBAAM,WAAW,cAAc,IAAI;AACnC,iBACI;AAAA,YAAC;AAAA,YAAA;AAAA,cAEG,SAAS,MAAM,aAAa,IAAI,GAAG;AAAA,cACnC,WAAW,WAAW,MAAM,qBAAqB,MAAM;AAAA,cACvD,OAAO;AAAA,gBACH,OAAmB,WAAW,MAAM,iBAAsB,MAAM;AAAA,gBAChE,UAAmB,WAAW,MAAM,oBAAsB,MAAM;AAAA,gBAChE,mBAAmB,WAAW,MAAM,uBAAuB;AAAA,gBAC3D,mBAAmB;AAAA,gBACnB,mBAAmB,WAAW,QAAQ;AAAA,gBACtC,eAAmB;AAAA,gBACnB,aAAmB;AAAA,gBACnB,QAAmB;AAAA,gBACnB,SAAmB;AAAA,gBACnB,YAAmB;AAAA,cAAA;AAAA,cAGtB,UAAA,IAAI;AAAA,YAAA;AAAA,YAhBA,IAAI;AAAA,UAAA;AAAA,QAmBrB,CAAC,EAAA,CACL;AAAA,QAIH,cAAc,aACX,qBAAA,UAAA,EACK,UAAA;AAAA,UAAA,QAAQ,IAAI,CAAC,QAAa,UACvB,qBAAC,MAAM,UAAN,EACG,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACG,WAAW,MAAM;AAAA,gBACjB,OAAO,EAAE,SAAS,QAAQ,YAAY,QAAQ,eAAe,OAAA;AAAA,gBAG7D,UAAA;AAAA,kBAAA,oBAAC,OAAA,EAAI,WAAW,MAAM,qBAAqB,OAAO,EAAE,OAAO,MAAM,iBAAiB,YAAY,EAAA,GAC1F,8BAAC,QAAA,EAAK,WAAW,MAAM,uBAAuB,OAAO,EAAE,OAAO,MAAM,mBAAmB,UAAU,MAAM,sBAAsB,SAAS,WACjI,UAAA,OAAO,UACZ,GACJ;AAAA,kBAGA,qBAAC,OAAA,EAAI,WAAW,MAAM,uBAAuB,OAAO,EAAE,MAAM,GAAG,aAAa,QAAQ,cAAc,UAC9F,UAAA;AAAA,oBAAA,oBAAC,OAAA,EAAI,WAAW,MAAM,uBAAuB,OAAO,EAAE,SAAS,QAAQ,YAAY,UAAU,cAAc,MAAA,GACvG,UAAA,oBAAC,YAAA,EAAW,QAAQ,OAAO,QAAQ,OAAO,MAAM,aAAa,GAAG,OAAO,MAAM,WAAW,MAAM,MAAM,SAAA,CAAU,GAClH;AAAA,wCACC,OAAA,EAAI,WAAW,MAAM,sBAAsB,OAAO,EAAE,OAAO,MAAM,kBAAkB,UAAU,MAAM,qBAAqB,YAAY,OAAO,cAAc,MAAA,GACrJ,iBAAO,OACZ;AAAA,wCACC,OAAA,EAAI,WAAW,MAAM,qBAAqB,OAAO,EAAE,OAAO,MAAM,iBAAiB,UAAU,MAAM,oBAAoB,YAAY,MAAA,GAC7H,iBAAO,KAAA,CACZ;AAAA,kBAAA,GACJ;AAAA,kBAGA,qBAAC,OAAA,EAAI,WAAW,MAAM,sBAAsB,OAAO,EAAE,OAAO,MAAM,kBAAkB,YAAY,GAAG,WAAW,WAC1G,UAAA;AAAA,oBAAA,oBAAC,SAAI,WAAW,MAAM,eAAe,OAAO,EAAE,OAAO,MAAM,WAAW,UAAU,MAAM,cAAc,cAAc,MAAA,GAC7G,iBAAO,MACZ;AAAA,oBACC,MAAM,wBAAwB,OAAO,YAClC,oBAAC,OAAA,EAAI,WAAW,MAAM,wBAAwB,OAAO,EAAE,OAAO,MAAM,oBAAoB,UAAU,MAAM,yBACnG,gBAAM,kBAAA,CACX;AAAA,kBAAA,EAAA,CAER;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAGH,QAAQ,QAAQ,SAAS,KACtB,oBAAC,SAAI,OAAO,EAAE,QAAQ,MAAM,eAAe,iBAAiB,MAAM,cAAc,OAAO,SAAO,CAAG;AAAA,UAAA,EAAA,GAvCpF,KAyCrB,CACH;AAAA,UAGA,MAAM,qBAAqB,MAAM,aAAa,KAC3C,oBAAC,OAAA,EAAI,OAAO,EAAE,SAAS,QAAQ,gBAAgB,UAAU,YAAY,UAAU,KAAK,OAAO,YAAY,QAAQ,eAAe,MAAA,GACzH,gBAAM,KAAK,EAAE,QAAQ,MAAM,YAAY,EAAE,IAAI,CAAC,GAAG,MAAM;AACpD,kBAAM,OAAO,IAAI;AACjB,kBAAM,WAAW,gBAAgB;AACjC,uCACK,UAAA,EAAkB,SAAS,MAAM,eAAe,IAAI,GAAG,OAAO;AAAA,cAC3D,OAAiB,MAAM;AAAA,cACvB,QAAiB,MAAM;AAAA,cACvB,cAAiB,MAAM;AAAA,cACvB,UAAiB,MAAM;AAAA,cACvB,iBAAiB,WAAW,MAAM,0BAA4B,MAAM;AAAA,cACpE,OAAiB,WAAW,MAAM,wBAA4B,MAAM;AAAA,cACpE,QAAiB;AAAA,cACjB,QAAiB;AAAA,cACjB,SAAiB;AAAA,cACjB,YAAiB;AAAA,cACjB,gBAAiB;AAAA,cACjB,YAAiB,WAAW,QAAQ;AAAA,YAAA,GAEnC,kBAdQ,IAeb;AAAA,UAER,CAAC,EAAA,CACL;AAAA,QAAA,GAER;AAAA,QAIH,cAAc,QACX,oBAAA,UAAA,EACK,UAAA,QAAQ,WAAW,IAChB,oBAAC,OAAA,EAAI,OAAO,EAAE,OAAO,WAAW,UAAU,UAAU,SAAS,SAAA,GAAY,UAAA,oBAAA,CAEzE,IAEA,QAAQ,IAAI,CAAC,MAAW,8BACnB,OAAA,EAAkB,MAAY,OAAc,QAAQ,UAAU,QAAQ,SAAS,EAAA,GAApE,KAAuE,CACtF,EAAA,CAET;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAGZ;AAER;"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,22 @@
1
1
  export { BlogPost, type BlogPostProps } from './components/BlogPost';
2
+ export { BlogPostHeader, type BlogPostHeaderProps } from './components/BlogPostHeader';
2
3
  export { BlogList, type BlogListProps } from './components/BlogList';
3
4
  export { JsonLd } from './components/JsonLd';
5
+ export { default as HeroFeatureBanner } from './components/landing/HeroFeatureBanner';
6
+ export type { HeroFeatureBannerProps, HeroBullet } from './components/landing/HeroFeatureBanner';
7
+ export { HeroFeatureBannerComponent } from './components/landing/HeroFeatureBannerComponent';
8
+ export { default as HeroFeatureBannerVideo } from './components/landing/HeroFeatureBannerVideo';
9
+ export type { HeroFeatureBannerVideoProps } from './components/landing/HeroFeatureBannerVideo';
10
+ export { HeroFeatureBannerVideoComponent } from './components/landing/HeroFeatureBannerVideoComponent';
11
+ export { ReviewsListRender } from './components/landing/VarietyReviewslistComponent';
12
+ export { BlogTwoColumnComponent, BlogThreeColumnComponent, BlogContainerComponent, } from './components/landing/BlogLayoutComponents';
13
+ export { FlexibleLayoutComponent } from './components/landing/FlexibleLayoutComponent';
4
14
  export { BlockRenderer, renderBlocks, type BlockRendererProps } from './render/BlockRenderer';
15
+ export { LandingPageRenderer } from './render/LandingPageRenderer';
5
16
  export { configureBlog, getDefaultConfig, resolveConfig, type BlogConfig } from './config';
6
17
  export { createBlogClient, getPostBySlug, getPosts, getPostsByCategory, getPublishedSlugs, getCategories, incrementView, type BlogClient, type GetPostsParams, } from './client/blogClient';
7
18
  export { generateBlogPostMetadata, generateBlogListMetadata, generateBlogPostJsonLd, generateBlogBreadcrumbJsonLd, type BlogMetadata, type SeoOptions, } from './seo';
8
19
  export { formatDate } from './lib/format';
20
+ export { resolveMediaSrc } from './lib/resolveMediaSrc';
21
+ export { postHasLandingPageBody } from './lib/postUtils';
9
22
  export type * from './types/blog';
package/dist/index.js CHANGED
@@ -1,16 +1,38 @@
1
1
  import { BlogPost } from "./components/BlogPost.js";
2
+ import { BlogPostHeader } from "./components/BlogPostHeader.js";
2
3
  import { BlogList } from "./components/BlogList.js";
3
4
  import { JsonLd } from "./components/JsonLd.js";
5
+ import { default as default2 } from "./components/landing/HeroFeatureBanner.js";
6
+ import { HeroFeatureBannerComponent } from "./components/landing/HeroFeatureBannerComponent.js";
7
+ import { default as default3 } from "./components/landing/HeroFeatureBannerVideo.js";
8
+ import { HeroFeatureBannerVideoComponent } from "./components/landing/HeroFeatureBannerVideoComponent.js";
9
+ import { ReviewsListRender } from "./components/landing/VarietyReviewslistComponent.js";
10
+ import { BlogContainerComponent, BlogThreeColumnComponent, BlogTwoColumnComponent } from "./components/landing/BlogLayoutComponents.js";
11
+ import { FlexibleLayoutComponent } from "./components/landing/FlexibleLayoutComponent.js";
4
12
  import { BlockRenderer, renderBlocks } from "./render/BlockRenderer.js";
13
+ import { LandingPageRenderer } from "./render/LandingPageRenderer.js";
5
14
  import { configureBlog, getDefaultConfig, resolveConfig } from "./config.js";
6
15
  import { createBlogClient, getCategories, getPostBySlug, getPosts, getPostsByCategory, getPublishedSlugs, incrementView } from "./client/blogClient.js";
7
16
  import { generateBlogBreadcrumbJsonLd, generateBlogListMetadata, generateBlogPostJsonLd, generateBlogPostMetadata } from "./seo/index.js";
8
17
  import { formatDate } from "./lib/format.js";
18
+ import { resolveMediaSrc } from "./lib/resolveMediaSrc.js";
19
+ import { postHasLandingPageBody } from "./lib/postUtils.js";
9
20
  export {
10
21
  BlockRenderer,
22
+ BlogContainerComponent,
11
23
  BlogList,
12
24
  BlogPost,
25
+ BlogPostHeader,
26
+ BlogThreeColumnComponent,
27
+ BlogTwoColumnComponent,
28
+ FlexibleLayoutComponent,
29
+ default2 as HeroFeatureBanner,
30
+ HeroFeatureBannerComponent,
31
+ default3 as HeroFeatureBannerVideo,
32
+ HeroFeatureBannerVideoComponent,
13
33
  JsonLd,
34
+ LandingPageRenderer,
35
+ ReviewsListRender,
14
36
  configureBlog,
15
37
  createBlogClient,
16
38
  formatDate,
@@ -25,7 +47,9 @@ export {
25
47
  getPostsByCategory,
26
48
  getPublishedSlugs,
27
49
  incrementView,
50
+ postHasLandingPageBody,
28
51
  renderBlocks,
29
- resolveConfig
52
+ resolveConfig,
53
+ resolveMediaSrc
30
54
  };
31
55
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,3 @@
1
+ import { BlogPost } from '../types/blog';
2
+ /** True when the post body is rendered from the page-builder landing schema. */
3
+ export declare function postHasLandingPageBody(post: Pick<BlogPost, 'content_blocks' | 'landing_page_html'>): boolean;
@@ -0,0 +1,8 @@
1
+ function postHasLandingPageBody(post) {
2
+ const blocks = post.content_blocks ?? [];
3
+ return blocks.length === 0 && Boolean(post.landing_page_html);
4
+ }
5
+ export {
6
+ postHasLandingPageBody
7
+ };
8
+ //# sourceMappingURL=postUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postUtils.js","sources":["../../src/lib/postUtils.ts"],"sourcesContent":["import type { BlogPost } from '../types/blog';\n\n/** True when the post body is rendered from the page-builder landing schema. */\nexport function postHasLandingPageBody(\n post: Pick<BlogPost, 'content_blocks' | 'landing_page_html'>,\n): boolean {\n const blocks = post.content_blocks ?? [];\n return blocks.length === 0 && Boolean(post.landing_page_html);\n}\n"],"names":[],"mappings":"AAGO,SAAS,uBACd,MACS;AACT,QAAM,SAAS,KAAK,kBAAkB,CAAA;AACtC,SAAO,OAAO,WAAW,KAAK,QAAQ,KAAK,iBAAiB;AAC9D;"}
@@ -0,0 +1,2 @@
1
+ /** Resolve a media URL from a string field and/or its companion *New upload object. */
2
+ export declare function resolveMediaSrc(primary?: unknown, secondary?: unknown): string | undefined;
@@ -0,0 +1,21 @@
1
+ function urlFromValue(value) {
2
+ if (typeof value === "string") {
3
+ const trimmed = value.trim();
4
+ return trimmed || void 0;
5
+ }
6
+ if (value && typeof value === "object" && "url" in value) {
7
+ const url = value?.url;
8
+ if (typeof url === "string") {
9
+ const trimmed = url.trim();
10
+ return trimmed || void 0;
11
+ }
12
+ }
13
+ return void 0;
14
+ }
15
+ function resolveMediaSrc(primary, secondary) {
16
+ return urlFromValue(primary) ?? urlFromValue(secondary);
17
+ }
18
+ export {
19
+ resolveMediaSrc
20
+ };
21
+ //# sourceMappingURL=resolveMediaSrc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveMediaSrc.js","sources":["../../src/lib/resolveMediaSrc.ts"],"sourcesContent":["type MediaLike = { url?: unknown } | null | undefined;\n\nfunction urlFromValue(value: unknown): string | undefined {\n if (typeof value === 'string') {\n const trimmed = value.trim();\n return trimmed || undefined;\n }\n\n if (value && typeof value === 'object' && 'url' in value) {\n const url = (value as MediaLike)?.url;\n if (typeof url === 'string') {\n const trimmed = url.trim();\n return trimmed || undefined;\n }\n }\n\n return undefined;\n}\n\n/** Resolve a media URL from a string field and/or its companion *New upload object. */\nexport function resolveMediaSrc(primary?: unknown, secondary?: unknown): string | undefined {\n return urlFromValue(primary) ?? urlFromValue(secondary);\n}\n"],"names":[],"mappings":"AAEA,SAAS,aAAa,OAAoC;AACxD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,UAAU,MAAM,KAAA;AACtB,WAAO,WAAW;AAAA,EACpB;AAEA,MAAI,SAAS,OAAO,UAAU,YAAY,SAAS,OAAO;AACxD,UAAM,MAAO,OAAqB;AAClC,QAAI,OAAO,QAAQ,UAAU;AAC3B,YAAM,UAAU,IAAI,KAAA;AACpB,aAAO,WAAW;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AACT;AAGO,SAAS,gBAAgB,SAAmB,WAAyC;AAC1F,SAAO,aAAa,OAAO,KAAK,aAAa,SAAS;AACxD;"}
@@ -1,5 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { animationClass, blockSettingsToStyle } from "./blockStyle.js";
3
+ import { RichText } from "./RichText.js";
3
4
  import TextBlock from "./blocks/TextBlock.js";
4
5
  import HeadingBlock from "./blocks/HeadingBlock.js";
5
6
  import ImageBlock from "./blocks/ImageBlock.js";
@@ -41,6 +42,10 @@ function renderBlockContent(block) {
41
42
  return /* @__PURE__ */ jsx(ButtonBlock, { content: block.content });
42
43
  case "embed":
43
44
  return /* @__PURE__ */ jsx(EmbedBlock, { content: block.content });
45
+ case "html": {
46
+ const { html } = block.content ?? {};
47
+ return html ? /* @__PURE__ */ jsx(RichText, { className: "ggblog-html", html }) : null;
48
+ }
44
49
  case "gallery":
45
50
  return /* @__PURE__ */ jsx(GalleryBlock, { content: block.content });
46
51
  case "table":
@@ -1 +1 @@
1
- {"version":3,"file":"BlockRenderer.js","sources":["../../src/render/BlockRenderer.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type {\n ContentBlock,\n TextBlockContent,\n HeadingBlockContent,\n ImageBlockContent,\n VideoBlockContent,\n QuoteBlockContent,\n CodeBlockContent,\n ListBlockContent,\n ButtonBlockContent,\n EmbedBlockContent,\n GalleryBlockContent,\n TableBlockContent,\n AccordionBlockContent,\n TabsBlockContent,\n AlertBlockContent,\n ColumnsBlockContent,\n SpacerBlockContent,\n DividerBlockContent,\n} from '../types/blog';\nimport { blockSettingsToStyle, animationClass } from './blockStyle';\nimport TextBlock from './blocks/TextBlock';\nimport HeadingBlock from './blocks/HeadingBlock';\nimport ImageBlock from './blocks/ImageBlock';\nimport VideoBlock from './blocks/VideoBlock';\nimport DividerBlock from './blocks/DividerBlock';\nimport SpacerBlock from './blocks/SpacerBlock';\nimport QuoteBlock from './blocks/QuoteBlock';\nimport CodeBlock from './blocks/CodeBlock';\nimport ListBlock from './blocks/ListBlock';\nimport ButtonBlock from './blocks/ButtonBlock';\nimport EmbedBlock from './blocks/EmbedBlock';\nimport GalleryBlock from './blocks/GalleryBlock';\nimport TableBlock from './blocks/TableBlock';\nimport AlertBlock from './blocks/AlertBlock';\nimport ColumnsBlock from './blocks/ColumnsBlock';\nimport AccordionBlock from './blocks/AccordionBlock';\nimport TabsBlock from './blocks/TabsBlock';\n\n/** Maps a single block to its read-only renderer. */\nfunction renderBlockContent(block: ContentBlock): ReactNode {\n switch (block.type) {\n case 'text':\n return <TextBlock content={block.content as TextBlockContent} />;\n case 'heading':\n return <HeadingBlock content={block.content as HeadingBlockContent} />;\n case 'image':\n return <ImageBlock content={block.content as ImageBlockContent} />;\n case 'video':\n return <VideoBlock content={block.content as VideoBlockContent} />;\n case 'divider':\n return <DividerBlock content={block.content as DividerBlockContent} />;\n case 'spacer':\n return <SpacerBlock content={block.content as SpacerBlockContent} />;\n case 'quote':\n return <QuoteBlock content={block.content as QuoteBlockContent} />;\n case 'code':\n return <CodeBlock content={block.content as CodeBlockContent} />;\n case 'list':\n return <ListBlock content={block.content as ListBlockContent} />;\n case 'button':\n return <ButtonBlock content={block.content as ButtonBlockContent} />;\n case 'embed':\n return <EmbedBlock content={block.content as EmbedBlockContent} />;\n case 'gallery':\n return <GalleryBlock content={block.content as GalleryBlockContent} />;\n case 'table':\n return <TableBlock content={block.content as TableBlockContent} />;\n case 'alert':\n return <AlertBlock content={block.content as AlertBlockContent} />;\n case 'accordion':\n return <AccordionBlock content={block.content as AccordionBlockContent} />;\n case 'tabs':\n return <TabsBlock content={block.content as TabsBlockContent} />;\n case 'columns':\n return <ColumnsBlock content={block.content as ColumnsBlockContent} />;\n default:\n return null;\n }\n}\n\nexport interface BlockRendererProps {\n block: ContentBlock;\n}\n\n/** Renders one content block wrapped with its layout settings. */\nexport function BlockRenderer({ block }: BlockRendererProps) {\n const className = `ggblog-block ggblog-block-${block.type} ${animationClass(block.settings)}`.trim();\n return (\n <div\n className={className}\n style={blockSettingsToStyle(block.settings)}\n data-block-type={block.type}\n data-block-id={block.id}\n >\n {renderBlockContent(block)}\n </div>\n );\n}\n\n/** Renders an ordered list of content blocks (used by posts and columns). */\nexport function renderBlocks(blocks: ContentBlock[]): ReactNode {\n return blocks.map((block) => <BlockRenderer key={block.id} block={block} />);\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAyCA,SAAS,mBAAmB,OAAgC;AAC1D,UAAQ,MAAM,MAAA;AAAA,IACZ,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,SAAS,MAAM,QAAA,CAA+B;AAAA,IACpE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,SAAS,MAAM,QAAA,CAA+B;AAAA,IACpE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,gBAAA,EAAe,SAAS,MAAM,QAAA,CAAkC;AAAA,IAC1E,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE;AACE,aAAO;AAAA,EAAA;AAEb;AAOO,SAAS,cAAc,EAAE,SAA6B;AAC3D,QAAM,YAAY,6BAA6B,MAAM,IAAI,IAAI,eAAe,MAAM,QAAQ,CAAC,GAAG,KAAA;AAC9F,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAO,qBAAqB,MAAM,QAAQ;AAAA,MAC1C,mBAAiB,MAAM;AAAA,MACvB,iBAAe,MAAM;AAAA,MAEpB,6BAAmB,KAAK;AAAA,IAAA;AAAA,EAAA;AAG/B;AAGO,SAAS,aAAa,QAAmC;AAC9D,SAAO,OAAO,IAAI,CAAC,8BAAW,eAAA,EAA6B,MAAA,GAAV,MAAM,EAAkB,CAAE;AAC7E;"}
1
+ {"version":3,"file":"BlockRenderer.js","sources":["../../src/render/BlockRenderer.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type {\n ContentBlock,\n TextBlockContent,\n HeadingBlockContent,\n ImageBlockContent,\n VideoBlockContent,\n QuoteBlockContent,\n CodeBlockContent,\n ListBlockContent,\n ButtonBlockContent,\n EmbedBlockContent,\n HtmlBlockContent,\n GalleryBlockContent,\n TableBlockContent,\n AccordionBlockContent,\n TabsBlockContent,\n AlertBlockContent,\n ColumnsBlockContent,\n SpacerBlockContent,\n DividerBlockContent,\n} from '../types/blog';\nimport { blockSettingsToStyle, animationClass } from './blockStyle';\nimport { RichText } from './RichText';\nimport TextBlock from './blocks/TextBlock';\nimport HeadingBlock from './blocks/HeadingBlock';\nimport ImageBlock from './blocks/ImageBlock';\nimport VideoBlock from './blocks/VideoBlock';\nimport DividerBlock from './blocks/DividerBlock';\nimport SpacerBlock from './blocks/SpacerBlock';\nimport QuoteBlock from './blocks/QuoteBlock';\nimport CodeBlock from './blocks/CodeBlock';\nimport ListBlock from './blocks/ListBlock';\nimport ButtonBlock from './blocks/ButtonBlock';\nimport EmbedBlock from './blocks/EmbedBlock';\nimport GalleryBlock from './blocks/GalleryBlock';\nimport TableBlock from './blocks/TableBlock';\nimport AlertBlock from './blocks/AlertBlock';\nimport ColumnsBlock from './blocks/ColumnsBlock';\nimport AccordionBlock from './blocks/AccordionBlock';\nimport TabsBlock from './blocks/TabsBlock';\n\n/** Maps a single block to its read-only renderer. */\nfunction renderBlockContent(block: ContentBlock): ReactNode {\n switch (block.type) {\n case 'text':\n return <TextBlock content={block.content as TextBlockContent} />;\n case 'heading':\n return <HeadingBlock content={block.content as HeadingBlockContent} />;\n case 'image':\n return <ImageBlock content={block.content as ImageBlockContent} />;\n case 'video':\n return <VideoBlock content={block.content as VideoBlockContent} />;\n case 'divider':\n return <DividerBlock content={block.content as DividerBlockContent} />;\n case 'spacer':\n return <SpacerBlock content={block.content as SpacerBlockContent} />;\n case 'quote':\n return <QuoteBlock content={block.content as QuoteBlockContent} />;\n case 'code':\n return <CodeBlock content={block.content as CodeBlockContent} />;\n case 'list':\n return <ListBlock content={block.content as ListBlockContent} />;\n case 'button':\n return <ButtonBlock content={block.content as ButtonBlockContent} />;\n case 'embed':\n return <EmbedBlock content={block.content as EmbedBlockContent} />;\n case 'html': {\n const { html } = (block.content ?? {}) as HtmlBlockContent;\n return html ? <RichText className=\"ggblog-html\" html={html} /> : null;\n }\n case 'gallery':\n return <GalleryBlock content={block.content as GalleryBlockContent} />;\n case 'table':\n return <TableBlock content={block.content as TableBlockContent} />;\n case 'alert':\n return <AlertBlock content={block.content as AlertBlockContent} />;\n case 'accordion':\n return <AccordionBlock content={block.content as AccordionBlockContent} />;\n case 'tabs':\n return <TabsBlock content={block.content as TabsBlockContent} />;\n case 'columns':\n return <ColumnsBlock content={block.content as ColumnsBlockContent} />;\n default:\n return null;\n }\n}\n\nexport interface BlockRendererProps {\n block: ContentBlock;\n}\n\n/** Renders one content block wrapped with its layout settings. */\nexport function BlockRenderer({ block }: BlockRendererProps) {\n const className = `ggblog-block ggblog-block-${block.type} ${animationClass(block.settings)}`.trim();\n return (\n <div\n className={className}\n style={blockSettingsToStyle(block.settings)}\n data-block-type={block.type}\n data-block-id={block.id}\n >\n {renderBlockContent(block)}\n </div>\n );\n}\n\n/** Renders an ordered list of content blocks (used by posts and columns). */\nexport function renderBlocks(blocks: ContentBlock[]): ReactNode {\n return blocks.map((block) => <BlockRenderer key={block.id} block={block} />);\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AA2CA,SAAS,mBAAmB,OAAgC;AAC1D,UAAQ,MAAM,MAAA;AAAA,IACZ,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,SAAS,MAAM,QAAA,CAA+B;AAAA,IACpE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,SAAS,MAAM,QAAA,CAA+B;AAAA,IACpE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK,QAAQ;AACX,YAAM,EAAE,KAAA,IAAU,MAAM,WAAW,CAAA;AACnC,aAAO,OAAO,oBAAC,UAAA,EAAS,WAAU,eAAc,MAAY,IAAK;AAAA,IACnE;AAAA,IACA,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,gBAAA,EAAe,SAAS,MAAM,QAAA,CAAkC;AAAA,IAC1E,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE;AACE,aAAO;AAAA,EAAA;AAEb;AAOO,SAAS,cAAc,EAAE,SAA6B;AAC3D,QAAM,YAAY,6BAA6B,MAAM,IAAI,IAAI,eAAe,MAAM,QAAQ,CAAC,GAAG,KAAA;AAC9F,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAO,qBAAqB,MAAM,QAAQ;AAAA,MAC1C,mBAAiB,MAAM;AAAA,MACvB,iBAAe,MAAM;AAAA,MAEpB,6BAAmB,KAAK;AAAA,IAAA;AAAA,EAAA;AAG/B;AAGO,SAAS,aAAa,QAAmC;AAC9D,SAAO,OAAO,IAAI,CAAC,8BAAW,eAAA,EAA6B,MAAA,GAAV,MAAM,EAAkB,CAAE;AAC7E;"}
@@ -0,0 +1,5 @@
1
+ import { LandingPageSchema } from './landingPageHtml';
2
+ /** Render page-builder schema as React (with HTML fallback per component). */
3
+ export declare function LandingPageRenderer({ schema }: {
4
+ schema: LandingPageSchema;
5
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,50 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { HeroFeatureBannerComponent } from "../components/landing/HeroFeatureBannerComponent.js";
3
+ import { HeroFeatureBannerVideoComponent } from "../components/landing/HeroFeatureBannerVideoComponent.js";
4
+ import { ReviewsListRender } from "../components/landing/VarietyReviewslistComponent.js";
5
+ import { BlogContainerComponent, BlogThreeColumnComponent, BlogTwoColumnComponent } from "../components/landing/BlogLayoutComponents.js";
6
+ import { FlexibleLayoutComponent } from "../components/landing/FlexibleLayoutComponent.js";
7
+ import { RichText } from "./RichText.js";
8
+ import { generateHtmlFromSchema } from "./landingPageHtml.js";
9
+ function renderComponent(component) {
10
+ const { type, props = {} } = component;
11
+ if (!type) return null;
12
+ switch (type) {
13
+ case "hero_feature_banner":
14
+ return /* @__PURE__ */ jsx(HeroFeatureBannerComponent, { props }, component.id ?? type);
15
+ case "hero_feature_banner_video":
16
+ return /* @__PURE__ */ jsx(HeroFeatureBannerVideoComponent, { props }, component.id ?? type);
17
+ case "variety_reviews_lits":
18
+ return /* @__PURE__ */ jsx(ReviewsListRender, { props }, component.id ?? type);
19
+ case "blog_two_column":
20
+ return /* @__PURE__ */ jsx(BlogTwoColumnComponent, { props }, component.id ?? type);
21
+ case "blog_three_column":
22
+ return /* @__PURE__ */ jsx(BlogThreeColumnComponent, { props }, component.id ?? type);
23
+ case "blog_container":
24
+ return /* @__PURE__ */ jsx(BlogContainerComponent, { props }, component.id ?? type);
25
+ case "flexible_layout":
26
+ return /* @__PURE__ */ jsx(
27
+ FlexibleLayoutComponent,
28
+ {
29
+ props
30
+ },
31
+ component.id ?? type
32
+ );
33
+ default: {
34
+ const { html } = generateHtmlFromSchema({ components: [component] });
35
+ if (!html) return null;
36
+ return /* @__PURE__ */ jsx(RichText, { html }, component.id ?? type);
37
+ }
38
+ }
39
+ }
40
+ function LandingPageRenderer({ schema }) {
41
+ if (!schema.components?.length) return null;
42
+ return /* @__PURE__ */ jsxs("div", { className: "ggblog-landing-page", children: [
43
+ schema.settings?.customCss ? /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: schema.settings.customCss } }) : null,
44
+ /* @__PURE__ */ jsx("div", { className: "ggblog-landing-page-content", children: schema.components.map((component, index) => /* @__PURE__ */ jsx("div", { children: renderComponent(component) }, component.id ?? `${component.type}-${index}`)) })
45
+ ] });
46
+ }
47
+ export {
48
+ LandingPageRenderer
49
+ };
50
+ //# sourceMappingURL=LandingPageRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LandingPageRenderer.js","sources":["../../src/render/LandingPageRenderer.tsx"],"sourcesContent":["import type { ComponentProps, ReactNode } from 'react';\nimport { HeroFeatureBannerComponent } from '../components/landing/HeroFeatureBannerComponent';\nimport { HeroFeatureBannerVideoComponent } from '../components/landing/HeroFeatureBannerVideoComponent';\nimport { ReviewsListRender } from '../components/landing/VarietyReviewslistComponent';\nimport {\n BlogTwoColumnComponent,\n BlogThreeColumnComponent,\n BlogContainerComponent,\n} from '../components/landing/BlogLayoutComponents';\nimport { FlexibleLayoutComponent } from '../components/landing/FlexibleLayoutComponent';\nimport { RichText } from './RichText';\nimport { generateHtmlFromSchema, type LandingPageSchema } from './landingPageHtml';\n\nfunction renderComponent(component: {\n id?: string;\n type?: string;\n props?: Record<string, unknown>;\n}): ReactNode {\n const { type, props = {} } = component;\n if (!type) return null;\n\n switch (type) {\n case 'hero_feature_banner':\n return <HeroFeatureBannerComponent key={component.id ?? type} props={props} />;\n case 'hero_feature_banner_video':\n return <HeroFeatureBannerVideoComponent key={component.id ?? type} props={props} />;\n case 'variety_reviews_lits':\n return <ReviewsListRender key={component.id ?? type} props={props} />;\n case 'blog_two_column':\n return <BlogTwoColumnComponent key={component.id ?? type} props={props} />;\n case 'blog_three_column':\n return <BlogThreeColumnComponent key={component.id ?? type} props={props} />;\n case 'blog_container':\n return <BlogContainerComponent key={component.id ?? type} props={props} />;\n case 'flexible_layout':\n return (\n <FlexibleLayoutComponent\n key={component.id ?? type}\n props={props as ComponentProps<typeof FlexibleLayoutComponent>['props']}\n />\n );\n default: {\n const { html } = generateHtmlFromSchema({ components: [component] });\n if (!html) return null;\n return <RichText key={component.id ?? type} html={html} />;\n }\n }\n}\n\n/** Render page-builder schema as React (with HTML fallback per component). */\nexport function LandingPageRenderer({ schema }: { schema: LandingPageSchema }) {\n if (!schema.components?.length) return null;\n\n return (\n <div className=\"ggblog-landing-page\">\n {schema.settings?.customCss ? (\n <style dangerouslySetInnerHTML={{ __html: schema.settings.customCss }} />\n ) : null}\n <div className=\"ggblog-landing-page-content\">\n {schema.components.map((component, index) => (\n <div key={component.id ?? `${component.type}-${index}`}>\n {renderComponent(component)}\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAaA,SAAS,gBAAgB,WAIX;AACZ,QAAM,EAAE,MAAM,QAAQ,CAAA,MAAO;AAC7B,MAAI,CAAC,KAAM,QAAO;AAElB,UAAQ,MAAA;AAAA,IACN,KAAK;AACH,aAAO,oBAAC,4BAAA,EAAsD,MAAA,GAAtB,UAAU,MAAM,IAAoB;AAAA,IAC9E,KAAK;AACH,aAAO,oBAAC,iCAAA,EAA2D,MAAA,GAAtB,UAAU,MAAM,IAAoB;AAAA,IACnF,KAAK;AACH,aAAO,oBAAC,mBAAA,EAA6C,MAAA,GAAtB,UAAU,MAAM,IAAoB;AAAA,IACrE,KAAK;AACH,aAAO,oBAAC,wBAAA,EAAkD,MAAA,GAAtB,UAAU,MAAM,IAAoB;AAAA,IAC1E,KAAK;AACH,aAAO,oBAAC,0BAAA,EAAoD,MAAA,GAAtB,UAAU,MAAM,IAAoB;AAAA,IAC5E,KAAK;AACH,aAAO,oBAAC,wBAAA,EAAkD,MAAA,GAAtB,UAAU,MAAM,IAAoB;AAAA,IAC1E,KAAK;AACH,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC;AAAA,QAAA;AAAA,QADK,UAAU,MAAM;AAAA,MAAA;AAAA,IAI3B,SAAS;AACP,YAAM,EAAE,SAAS,uBAAuB,EAAE,YAAY,CAAC,SAAS,GAAG;AACnE,UAAI,CAAC,KAAM,QAAO;AAClB,aAAO,oBAAC,UAAA,EAAoC,KAAA,GAAtB,UAAU,MAAM,IAAkB;AAAA,IAC1D;AAAA,EAAA;AAEJ;AAGO,SAAS,oBAAoB,EAAE,UAAyC;AAC7E,MAAI,CAAC,OAAO,YAAY,OAAQ,QAAO;AAEvC,SACE,qBAAC,OAAA,EAAI,WAAU,uBACZ,UAAA;AAAA,IAAA,OAAO,UAAU,YAChB,oBAAC,SAAA,EAAM,yBAAyB,EAAE,QAAQ,OAAO,SAAS,UAAA,EAAU,CAAG,IACrE;AAAA,IACJ,oBAAC,OAAA,EAAI,WAAU,+BACZ,UAAA,OAAO,WAAW,IAAI,CAAC,WAAW,UACjC,oBAAC,OAAA,EACE,0BAAgB,SAAS,KADlB,UAAU,MAAM,GAAG,UAAU,IAAI,IAAI,KAAK,EAEpD,CACD,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
@@ -0,0 +1,28 @@
1
+ /** Page-builder schema shape stored on blog posts via landingPage.publishedVersion.schema_json. */
2
+ export interface LandingPageSchema {
3
+ components?: Array<{
4
+ id?: string;
5
+ type?: string;
6
+ props?: Record<string, unknown>;
7
+ }>;
8
+ settings?: {
9
+ customCss?: string;
10
+ maxWidth?: string;
11
+ backgroundColor?: string;
12
+ };
13
+ }
14
+ /** Convert a page-builder schema to trusted HTML (+ optional CSS) for blog post bodies. */
15
+ export declare function generateHtmlFromSchema(schema: LandingPageSchema | null | undefined): {
16
+ html: string;
17
+ css: string;
18
+ };
19
+ /** Read landing page schema from a blog post API payload. */
20
+ export declare function getLandingPageSchema(post: {
21
+ landingPage?: {
22
+ publishedVersion?: {
23
+ schema_json?: LandingPageSchema | string;
24
+ };
25
+ landing_page_schema?: LandingPageSchema | string;
26
+ };
27
+ landing_page_schema?: LandingPageSchema | string;
28
+ } | null | undefined): LandingPageSchema | null;