@opinly/next 0.1.17 → 0.1.19
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/dist/components/author-page/index.cjs +51 -25
- package/dist/components/author-page/index.cjs.map +1 -1
- package/dist/components/author-page/index.js +52 -26
- package/dist/components/author-page/index.js.map +1 -1
- package/dist/components/blog-post/_components/content.cjs +5 -8
- package/dist/components/blog-post/_components/content.cjs.map +1 -1
- package/dist/components/blog-post/_components/content.js +5 -8
- package/dist/components/blog-post/_components/content.js.map +1 -1
- package/dist/components/blog-post/_components/faq.cjs +2 -2
- package/dist/components/blog-post/_components/faq.cjs.map +1 -1
- package/dist/components/blog-post/_components/faq.js +2 -2
- package/dist/components/blog-post/_components/faq.js.map +1 -1
- package/dist/components/blog-post/_components/table-of-contents.cjs +36 -9
- package/dist/components/blog-post/_components/table-of-contents.cjs.map +1 -1
- package/dist/components/blog-post/_components/table-of-contents.js +36 -9
- package/dist/components/blog-post/_components/table-of-contents.js.map +1 -1
- package/dist/components/blog-post/_helpers/extract-headings.cjs +2 -1
- package/dist/components/blog-post/_helpers/extract-headings.cjs.map +1 -1
- package/dist/components/blog-post/_helpers/extract-headings.d.cts +1 -0
- package/dist/components/blog-post/_helpers/extract-headings.d.ts +1 -0
- package/dist/components/blog-post/_helpers/extract-headings.js +2 -1
- package/dist/components/blog-post/_helpers/extract-headings.js.map +1 -1
- package/dist/components/blog-post/_helpers/json-ld.cjs +5 -12
- package/dist/components/blog-post/_helpers/json-ld.cjs.map +1 -1
- package/dist/components/blog-post/_helpers/json-ld.d.cts +6 -2
- package/dist/components/blog-post/_helpers/json-ld.d.ts +6 -2
- package/dist/components/blog-post/_helpers/json-ld.js +5 -12
- package/dist/components/blog-post/_helpers/json-ld.js.map +1 -1
- package/dist/components/blog-post/_helpers/reading-time.cjs +1 -1
- package/dist/components/blog-post/_helpers/reading-time.cjs.map +1 -1
- package/dist/components/blog-post/_helpers/reading-time.js +1 -1
- package/dist/components/blog-post/_helpers/reading-time.js.map +1 -1
- package/dist/components/blog-post/index.cjs +26 -22
- package/dist/components/blog-post/index.cjs.map +1 -1
- package/dist/components/blog-post/index.js +26 -22
- package/dist/components/blog-post/index.js.map +1 -1
- package/dist/components/bread-crumbs.cjs +1 -1
- package/dist/components/bread-crumbs.cjs.map +1 -1
- package/dist/components/bread-crumbs.js +1 -1
- package/dist/components/bread-crumbs.js.map +1 -1
- package/dist/components/folder-page/index.cjs +46 -11
- package/dist/components/folder-page/index.cjs.map +1 -1
- package/dist/components/folder-page/index.js +47 -12
- package/dist/components/folder-page/index.js.map +1 -1
- package/dist/components/home-page/folders.cjs +20 -10
- package/dist/components/home-page/folders.cjs.map +1 -1
- package/dist/components/home-page/folders.d.cts +4 -2
- package/dist/components/home-page/folders.d.ts +4 -2
- package/dist/components/home-page/folders.js +20 -10
- package/dist/components/home-page/folders.js.map +1 -1
- package/dist/components/home-page/index.cjs +5 -7
- package/dist/components/home-page/index.cjs.map +1 -1
- package/dist/components/home-page/index.d.cts +4 -5
- package/dist/components/home-page/index.d.ts +4 -5
- package/dist/components/home-page/index.js +5 -7
- package/dist/components/home-page/index.js.map +1 -1
- package/dist/components/home-page/pagination.cjs +23 -17
- package/dist/components/home-page/pagination.cjs.map +1 -1
- package/dist/components/home-page/pagination.d.cts +2 -3
- package/dist/components/home-page/pagination.d.ts +2 -3
- package/dist/components/home-page/pagination.js +23 -17
- package/dist/components/home-page/pagination.js.map +1 -1
- package/dist/components/home-page/top-posts.cjs +2 -19
- package/dist/components/home-page/top-posts.cjs.map +1 -1
- package/dist/components/home-page/top-posts.d.cts +4 -3
- package/dist/components/home-page/top-posts.d.ts +4 -3
- package/dist/components/home-page/top-posts.js +4 -21
- package/dist/components/home-page/top-posts.js.map +1 -1
- package/dist/components/opinly-blog.cjs +6 -6
- package/dist/components/opinly-blog.cjs.map +1 -1
- package/dist/components/opinly-blog.d.cts +4 -7
- package/dist/components/opinly-blog.d.ts +4 -7
- package/dist/components/opinly-blog.js +6 -6
- package/dist/components/opinly-blog.js.map +1 -1
- package/dist/components/post-preview.cjs +7 -6
- package/dist/components/post-preview.cjs.map +1 -1
- package/dist/components/post-preview.js +7 -6
- package/dist/components/post-preview.js.map +1 -1
- package/dist/{utils/with-opinly-config.cjs → config.cjs} +17 -9
- package/dist/config.cjs.map +1 -0
- package/dist/{utils/with-opinly-config.d.cts → config.d.cts} +3 -0
- package/dist/{utils/with-opinly-config.d.ts → config.d.ts} +3 -0
- package/dist/{utils/with-opinly-config.js → config.js} +14 -6
- package/dist/config.js.map +1 -0
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -3
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/pages/index.cjs +23 -0
- package/dist/pages/index.cjs.map +1 -0
- package/dist/pages/index.d.cts +3 -0
- package/dist/pages/index.d.ts +3 -0
- package/dist/pages/index.js +2 -0
- package/dist/pages/index.js.map +1 -0
- package/dist/pages/opinly-blog-pages.cjs +128 -0
- package/dist/pages/opinly-blog-pages.cjs.map +1 -0
- package/dist/pages/opinly-blog-pages.d.cts +9 -0
- package/dist/pages/opinly-blog-pages.d.ts +9 -0
- package/dist/pages/opinly-blog-pages.js +104 -0
- package/dist/pages/opinly-blog-pages.js.map +1 -0
- package/dist/utils/generate-metadata.cjs +1 -1
- package/dist/utils/generate-metadata.cjs.map +1 -1
- package/dist/utils/generate-metadata.d.cts +2 -4
- package/dist/utils/generate-metadata.d.ts +2 -4
- package/dist/utils/generate-metadata.js +1 -1
- package/dist/utils/generate-metadata.js.map +1 -1
- package/dist/utils/generate-sitemap-xml.cjs +42 -0
- package/dist/utils/generate-sitemap-xml.cjs.map +1 -0
- package/dist/utils/generate-sitemap-xml.d.cts +5 -0
- package/dist/utils/generate-sitemap-xml.d.ts +5 -0
- package/dist/utils/generate-sitemap-xml.js +18 -0
- package/dist/utils/generate-sitemap-xml.js.map +1 -0
- package/dist/utils/sdk-config.cjs +4 -2
- package/dist/utils/sdk-config.cjs.map +1 -1
- package/dist/utils/sdk-config.d.cts +2 -0
- package/dist/utils/sdk-config.d.ts +2 -0
- package/dist/utils/sdk-config.js +4 -2
- package/dist/utils/sdk-config.js.map +1 -1
- package/package.json +12 -3
- package/dist/components/not-found.cjs +0 -60
- package/dist/components/not-found.cjs.map +0 -1
- package/dist/components/not-found.d.cts +0 -5
- package/dist/components/not-found.d.ts +0 -5
- package/dist/components/not-found.js +0 -26
- package/dist/components/not-found.js.map +0 -1
- package/dist/utils/with-opinly-config.cjs.map +0 -1
- package/dist/utils/with-opinly-config.js.map +0 -1
|
@@ -5,13 +5,17 @@ import { opinlyConfig } from "../../../utils/sdk-config";
|
|
|
5
5
|
import { extractHeadings } from "../_helpers/extract-headings";
|
|
6
6
|
import { Share } from "./share";
|
|
7
7
|
import Link from "next/link";
|
|
8
|
+
const headingColorMap = {
|
|
9
|
+
2: "text-op-heading",
|
|
10
|
+
3: "text-op-body"
|
|
11
|
+
};
|
|
8
12
|
const TableOfContents = ({
|
|
9
13
|
content,
|
|
10
14
|
author,
|
|
11
15
|
post
|
|
12
16
|
}) => {
|
|
13
|
-
return /* @__PURE__ */ jsxs("
|
|
14
|
-
author && /* @__PURE__ */
|
|
17
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("w-full flex flex-col space-y-4"), children: [
|
|
18
|
+
author && /* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col space-y-2 mb-6 border p-4 rounded-md text-sm", children: [
|
|
15
19
|
author.fileKey && /* @__PURE__ */ jsx(
|
|
16
20
|
Image,
|
|
17
21
|
{
|
|
@@ -23,22 +27,45 @@ const TableOfContents = ({
|
|
|
23
27
|
className: "rounded-full"
|
|
24
28
|
}
|
|
25
29
|
),
|
|
26
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
30
|
+
/* @__PURE__ */ jsxs("div", { className: "w-full flex flex-col space-y-2", children: [
|
|
27
31
|
/* @__PURE__ */ jsx(
|
|
28
32
|
Link,
|
|
29
33
|
{
|
|
30
34
|
href: `${opinlyConfig.blogPrefix}/authors/${author.slug}`,
|
|
31
|
-
className: "text-
|
|
35
|
+
className: "text-lg text-op-heading font-bold",
|
|
32
36
|
children: author.name
|
|
33
37
|
}
|
|
34
38
|
),
|
|
35
|
-
/* @__PURE__ */
|
|
39
|
+
/* @__PURE__ */ jsxs("div", { className: "w-48 ", children: [
|
|
40
|
+
/* @__PURE__ */ jsx("span", { className: "text-op-muted text-sm w-56 break-words block md:hidden", children: author.bio && author.bio.length > 40 ? author.bio.slice(0, 40) + "..." : author.bio }),
|
|
41
|
+
/* @__PURE__ */ jsx("p", { className: "text-op-muted text-sm w-48 hidden md:block", children: author.bio })
|
|
42
|
+
] })
|
|
36
43
|
] })
|
|
37
|
-
] })
|
|
44
|
+
] }),
|
|
38
45
|
/* @__PURE__ */ jsx(Share, { post }),
|
|
39
|
-
/* @__PURE__ */ jsxs("div", { className: "border-l-4 border-
|
|
40
|
-
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold mb-2", children: "
|
|
41
|
-
/* @__PURE__ */ jsx("ul", { className: "text-sm
|
|
46
|
+
/* @__PURE__ */ jsxs("div", { className: "border-l-4 border-op-accent pl-4 mb-4", children: [
|
|
47
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold mb-2", children: "Table of Contents" }),
|
|
48
|
+
/* @__PURE__ */ jsx("ul", { className: "text-sm space-y-1", children: (extractHeadings(content) || []).map((heading) => /* @__PURE__ */ jsx(
|
|
49
|
+
"li",
|
|
50
|
+
{
|
|
51
|
+
className: cn(heading.level === 3 && "ml-2"),
|
|
52
|
+
children: /* @__PURE__ */ jsxs(
|
|
53
|
+
"a",
|
|
54
|
+
{
|
|
55
|
+
href: `#${heading.slug}`,
|
|
56
|
+
className: cn(
|
|
57
|
+
headingColorMap[heading.level]
|
|
58
|
+
),
|
|
59
|
+
children: [
|
|
60
|
+
heading.level === 3 && "-",
|
|
61
|
+
" ",
|
|
62
|
+
heading.text
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
},
|
|
67
|
+
heading.slug
|
|
68
|
+
)) })
|
|
42
69
|
] })
|
|
43
70
|
] });
|
|
44
71
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blog-post/_components/table-of-contents.tsx"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\nimport { BlogPostRes } from \"../_types/blog-post\";\nimport { cn } from \"../../../utils/merge\";\nimport Image from \"next/image\";\nimport { opinlyConfig } from \"../../../utils/sdk-config\";\nimport { extractHeadings } from \"../_helpers/extract-headings\";\nimport { Share } from \"./share\";\nimport Link from \"next/link\";\n\ntype TableOfContentsProps = {\n content: JSONContent;\n author: BlogPostRes[\"author\"] | null;\n post: BlogPostRes;\n};\n\nexport const TableOfContents = ({\n content,\n author,\n post,\n}: TableOfContentsProps) => {\n return (\n <
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blog-post/_components/table-of-contents.tsx"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\nimport { BlogPostRes } from \"../_types/blog-post\";\nimport { cn } from \"../../../utils/merge\";\nimport Image from \"next/image\";\nimport { opinlyConfig } from \"../../../utils/sdk-config\";\nimport { extractHeadings } from \"../_helpers/extract-headings\";\nimport { Share } from \"./share\";\nimport Link from \"next/link\";\n\ntype TableOfContentsProps = {\n content: JSONContent;\n author: BlogPostRes[\"author\"] | null;\n post: BlogPostRes;\n};\n\nconst headingColorMap = {\n 2: \"text-op-heading\",\n 3: \"text-op-body\",\n};\n\nexport const TableOfContents = ({\n content,\n author,\n post,\n}: TableOfContentsProps) => {\n return (\n <div className={cn(\"w-full flex flex-col space-y-4\")}>\n {author && (\n <div className=\"w-full flex flex-col space-y-2 mb-6 border p-4 rounded-md text-sm\">\n {author.fileKey && (\n <Image\n unoptimized={opinlyConfig.unoptimizedImages}\n src={`${opinlyConfig.imagesPrefix}/${author.fileKey}`}\n alt={author.name}\n width={48}\n height={48}\n className=\"rounded-full\"\n />\n )}\n <div className=\"w-full flex flex-col space-y-2\">\n <Link\n href={`${opinlyConfig.blogPrefix}/authors/${author.slug}`}\n className=\"text-lg text-op-heading font-bold\"\n >\n {author.name}\n </Link>\n <div className=\"w-48 \">\n {/* Mobile: show truncated bio */}\n <span className=\"text-op-muted text-sm w-56 break-words block md:hidden\">\n {author.bio && author.bio.length > 40\n ? author.bio.slice(0, 40) + \"...\"\n : author.bio}\n </span>\n {/* Desktop: show full bio */}\n <p className=\"text-op-muted text-sm w-48 hidden md:block\">\n {author.bio}\n </p>\n </div>\n </div>\n </div>\n )}\n <Share post={post} />\n <div className=\"border-l-4 border-op-accent pl-4 mb-4\">\n <h2 className=\"text-lg font-semibold mb-2\">Table of Contents</h2>\n <ul className=\"text-sm space-y-1\">\n {(extractHeadings(content) || []).map((heading) => (\n <li\n key={heading.slug}\n className={cn(heading.level === 3 && \"ml-2\")}\n >\n <a\n href={`#${heading.slug}`}\n className={cn(\n headingColorMap[heading.level as keyof typeof headingColorMap]\n )}\n >\n {heading.level === 3 && \"-\"} {heading.text}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n );\n};\n"],"mappings":"AA8BY,cAgBA,YAhBA;AA5BZ,SAAS,UAAU;AACnB,OAAO,WAAW;AAClB,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,aAAa;AACtB,OAAO,UAAU;AAQjB,MAAM,kBAAkB;AAAA,EACtB,GAAG;AAAA,EACH,GAAG;AACL;AAEO,MAAM,kBAAkB,CAAC;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF,MAA4B;AAC1B,SACE,qBAAC,SAAI,WAAW,GAAG,gCAAgC,GAChD;AAAA,cACC,qBAAC,SAAI,WAAU,qEACZ;AAAA,aAAO,WACN;AAAA,QAAC;AAAA;AAAA,UACC,aAAa,aAAa;AAAA,UAC1B,KAAK,GAAG,aAAa,YAAY,IAAI,OAAO,OAAO;AAAA,UACnD,KAAK,OAAO;AAAA,UACZ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,WAAU;AAAA;AAAA,MACZ;AAAA,MAEF,qBAAC,SAAI,WAAU,kCACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,GAAG,aAAa,UAAU,YAAY,OAAO,IAAI;AAAA,YACvD,WAAU;AAAA,YAET,iBAAO;AAAA;AAAA,QACV;AAAA,QACA,qBAAC,SAAI,WAAU,SAEb;AAAA,8BAAC,UAAK,WAAU,0DACb,iBAAO,OAAO,OAAO,IAAI,SAAS,KAC/B,OAAO,IAAI,MAAM,GAAG,EAAE,IAAI,QAC1B,OAAO,KACb;AAAA,UAEA,oBAAC,OAAE,WAAU,+CACV,iBAAO,KACV;AAAA,WACF;AAAA,SACF;AAAA,OACF;AAAA,IAEF,oBAAC,SAAM,MAAY;AAAA,IACnB,qBAAC,SAAI,WAAU,yCACb;AAAA,0BAAC,QAAG,WAAU,8BAA6B,+BAAiB;AAAA,MAC5D,oBAAC,QAAG,WAAU,qBACV,2BAAgB,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC,YACrC;AAAA,QAAC;AAAA;AAAA,UAEC,WAAW,GAAG,QAAQ,UAAU,KAAK,MAAM;AAAA,UAE3C;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,IAAI,QAAQ,IAAI;AAAA,cACtB,WAAW;AAAA,gBACT,gBAAgB,QAAQ,KAAqC;AAAA,cAC/D;AAAA,cAEC;AAAA,wBAAQ,UAAU,KAAK;AAAA,gBAAI;AAAA,gBAAE,QAAQ;AAAA;AAAA;AAAA,UACxC;AAAA;AAAA,QAVK,QAAQ;AAAA,MAWf,CACD,GACH;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -29,7 +29,8 @@ function extractHeadings(content) {
|
|
|
29
29
|
if (node.type === "heading" && node.content?.[0]?.text) {
|
|
30
30
|
const text = node.content[0].text;
|
|
31
31
|
const slug = text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
32
|
-
|
|
32
|
+
const level = node.attrs?.level;
|
|
33
|
+
headings.push({ text, slug, level });
|
|
33
34
|
}
|
|
34
35
|
if (node.content) walk(node.content);
|
|
35
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/extract-headings.ts"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\n\nexport function extractHeadings(\n content: JSONContent\n): { text: string; slug: string }[] {\n const headings: { text: string; slug: string }[] = [];\n if (!content?.content) return headings;\n\n const walk = (nodes:
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/extract-headings.ts"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\n\nexport function extractHeadings(\n content: JSONContent\n): { text: string; slug: string; level: number }[] {\n const headings: { text: string; slug: string; level: number }[] = [];\n if (!content?.content) return headings;\n\n const walk = (nodes: JSONContent[]) => {\n for (const node of nodes) {\n if (node.type === \"heading\" && node.content?.[0]?.text) {\n const text = node.content[0].text;\n const slug = text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n const level = node.attrs?.level;\n headings.push({ text, slug, level });\n }\n if (node.content) walk(node.content);\n }\n };\n\n walk(content.content);\n return headings;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,SAAS,gBACd,SACiD;AACjD,QAAM,WAA4D,CAAC;AACnE,MAAI,CAAC,SAAS,QAAS,QAAO;AAE9B,QAAM,OAAO,CAAC,UAAyB;AACrC,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,aAAa,KAAK,UAAU,CAAC,GAAG,MAAM;AACtD,cAAM,OAAO,KAAK,QAAQ,CAAC,EAAE;AAC7B,cAAM,OAAO,KACV,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAEzB,cAAM,QAAQ,KAAK,OAAO;AAC1B,iBAAS,KAAK,EAAE,MAAM,MAAM,MAAM,CAAC;AAAA,MACrC;AACA,UAAI,KAAK,QAAS,MAAK,KAAK,OAAO;AAAA,IACrC;AAAA,EACF;AAEA,OAAK,QAAQ,OAAO;AACpB,SAAO;AACT;","names":[]}
|
|
@@ -6,7 +6,8 @@ function extractHeadings(content) {
|
|
|
6
6
|
if (node.type === "heading" && node.content?.[0]?.text) {
|
|
7
7
|
const text = node.content[0].text;
|
|
8
8
|
const slug = text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
9
|
-
|
|
9
|
+
const level = node.attrs?.level;
|
|
10
|
+
headings.push({ text, slug, level });
|
|
10
11
|
}
|
|
11
12
|
if (node.content) walk(node.content);
|
|
12
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/extract-headings.ts"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\n\nexport function extractHeadings(\n content: JSONContent\n): { text: string; slug: string }[] {\n const headings: { text: string; slug: string }[] = [];\n if (!content?.content) return headings;\n\n const walk = (nodes:
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/extract-headings.ts"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\n\nexport function extractHeadings(\n content: JSONContent\n): { text: string; slug: string; level: number }[] {\n const headings: { text: string; slug: string; level: number }[] = [];\n if (!content?.content) return headings;\n\n const walk = (nodes: JSONContent[]) => {\n for (const node of nodes) {\n if (node.type === \"heading\" && node.content?.[0]?.text) {\n const text = node.content[0].text;\n const slug = text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n const level = node.attrs?.level;\n headings.push({ text, slug, level });\n }\n if (node.content) walk(node.content);\n }\n };\n\n walk(content.content);\n return headings;\n}\n"],"mappings":"AAEO,SAAS,gBACd,SACiD;AACjD,QAAM,WAA4D,CAAC;AACnE,MAAI,CAAC,SAAS,QAAS,QAAO;AAE9B,QAAM,OAAO,CAAC,UAAyB;AACrC,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,aAAa,KAAK,UAAU,CAAC,GAAG,MAAM;AACtD,cAAM,OAAO,KAAK,QAAQ,CAAC,EAAE;AAC7B,cAAM,OAAO,KACV,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAEzB,cAAM,QAAQ,KAAK,OAAO;AAC1B,iBAAS,KAAK,EAAE,MAAM,MAAM,MAAM,CAAC;AAAA,MACrC;AACA,UAAI,KAAK,QAAS,MAAK,KAAK,OAAO;AAAA,IACrC;AAAA,EACF;AAEA,OAAK,QAAQ,OAAO;AACpB,SAAO;AACT;","names":[]}
|
|
@@ -35,7 +35,9 @@ function generateArticleBodyHtml(content) {
|
|
|
35
35
|
break;
|
|
36
36
|
case "heading":
|
|
37
37
|
const headingLevel = node.attrs?.level || 1;
|
|
38
|
-
htmlString += `<h${headingLevel}>${generateChildrenHtml(
|
|
38
|
+
htmlString += `<h${headingLevel}>${generateChildrenHtml(
|
|
39
|
+
node.content
|
|
40
|
+
)}</h${headingLevel}>`;
|
|
39
41
|
break;
|
|
40
42
|
case "bulletList":
|
|
41
43
|
htmlString += `<ul>${generateChildrenHtml(node.content)}</ul>`;
|
|
@@ -120,13 +122,11 @@ const genBlogPostingJSONLD = (post) => {
|
|
|
120
122
|
const genBreadcrumbJSONLD = (post) => {
|
|
121
123
|
const itemListElement = [
|
|
122
124
|
{
|
|
123
|
-
"@type": "ListItem",
|
|
124
125
|
position: 1,
|
|
125
|
-
name:
|
|
126
|
+
name: import_sdk_config.opinlyConfig.siteName,
|
|
126
127
|
item: import_sdk_config.opinlyConfig.siteUrl
|
|
127
128
|
},
|
|
128
129
|
{
|
|
129
|
-
"@type": "ListItem",
|
|
130
130
|
position: 2,
|
|
131
131
|
name: post.folder?.name || "Blog",
|
|
132
132
|
item: `${import_sdk_config.opinlyConfig.blogUrl}/blog`
|
|
@@ -134,30 +134,23 @@ const genBreadcrumbJSONLD = (post) => {
|
|
|
134
134
|
];
|
|
135
135
|
if (post.folder) {
|
|
136
136
|
itemListElement.push({
|
|
137
|
-
"@type": "ListItem",
|
|
138
137
|
position: 3,
|
|
139
138
|
name: post.folder.name,
|
|
140
139
|
item: `${import_sdk_config.opinlyConfig.blogUrl}/blog/${post.folder.slug}`
|
|
141
140
|
});
|
|
142
141
|
itemListElement.push({
|
|
143
|
-
"@type": "ListItem",
|
|
144
142
|
position: 4,
|
|
145
143
|
name: post.title,
|
|
146
144
|
item: `${import_sdk_config.opinlyConfig.blogUrl}/blog/${post.folder.slug}/${post.slug}`
|
|
147
145
|
});
|
|
148
146
|
} else {
|
|
149
147
|
itemListElement.push({
|
|
150
|
-
"@type": "ListItem",
|
|
151
148
|
position: 3,
|
|
152
149
|
name: post.title,
|
|
153
150
|
item: `${import_sdk_config.opinlyConfig.blogUrl}/blog/${post.slug}`
|
|
154
151
|
});
|
|
155
152
|
}
|
|
156
|
-
return
|
|
157
|
-
"@context": "https://schema.org",
|
|
158
|
-
"@type": "BreadcrumbList",
|
|
159
|
-
itemListElement
|
|
160
|
-
};
|
|
153
|
+
return itemListElement;
|
|
161
154
|
};
|
|
162
155
|
// Annotate the CommonJS export names for ESM import in node:
|
|
163
156
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/json-ld.ts"],"sourcesContent":["import {\n BlogPosting,\n BreadcrumbList,\n FAQPage,\n WithContext,\n ListItem,\n} from \"schema-dts\";\nimport { BlogPostRes } from \"../_types/blog-post\";\nimport { opinlyConfig } from \"../../../utils/sdk-config\";\nimport { JSONContent } from \"@tiptap/core\";\n\n// Add this function somewhere in your BlogPost component file\nexport function generateArticleBodyHtml(content: JSONContent): string {\n if (!content?.content) return \"\";\n\n let htmlString = \"\";\n\n content.content.forEach((node) => {\n switch (node.type) {\n case \"paragraph\":\n htmlString += `<p>${generateChildrenHtml(node.content)}</p>`;\n break;\n case \"heading\":\n const headingLevel = node.attrs?.level || 1;\n htmlString += `<h${headingLevel}>${generateChildrenHtml(node.content)}</h${headingLevel}>`;\n break;\n case \"bulletList\":\n htmlString += `<ul>${generateChildrenHtml(node.content)}</ul>`;\n break;\n case \"orderedList\":\n htmlString += `<ol>${generateChildrenHtml(node.content)}</ol>`;\n break;\n case \"listItem\":\n htmlString += `<li>${generateChildrenHtml(node.content)}</li>`;\n break;\n // Add other node types if they contain text content relevant for articleBody\n // For images, you might just skip them or include an <img> tag if semantic\n // For example:\n // case \"image\":\n // if (node.attrs?.src) {\n // htmlString += `<img src=\"${replaceImageHostname(node.attrs.src, opinlyConfig.imagesPrefix)}\" alt=\"${node.attrs?.alt || ''}\" />`;\n // }\n // break;\n default:\n // Handle other block types or just ignore them for articleBody\n break;\n }\n });\n\n return htmlString;\n}\n\nfunction generateChildrenHtml(\n nodes: JSONContent[\"content\"] | undefined\n): string {\n if (!nodes) return \"\";\n\n let childrenHtml = \"\";\n nodes.forEach((child) => {\n if (child.type === \"text\") {\n let text = child.text || \"\";\n if (child.marks) {\n child.marks.forEach((mark) => {\n if (mark.type === \"bold\") text = `<strong>${text}</strong>`;\n if (mark.type === \"italic\") text = `<em>${text}</em>`;\n if (mark.type === \"link\" && mark.attrs?.href) {\n text = `<a href=\"${mark.attrs.href}\">${text}</a>`;\n }\n });\n }\n childrenHtml += text;\n }\n // If you have nested content within child nodes, you might need a recursive call here\n // For example, if a list item can contain paragraphs\n // if (child.content) {\n // childrenHtml += generateChildrenHtml(child.content);\n // }\n });\n return childrenHtml;\n}\n\nexport const genFaqJSONLD = (\n faqs: NonNullable<BlogPostRes[\"faqs\"]>\n): WithContext<FAQPage> => {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n mainEntity: faqs.map((faq) => ({\n \"@type\": \"Question\",\n name: faq.question,\n acceptedAnswer: {\n \"@type\": \"Answer\",\n text: faq.answer,\n },\n })),\n };\n};\n\nexport const genBlogPostingJSONLD = (\n post: BlogPostRes\n): WithContext<BlogPosting> => {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BlogPosting\",\n headline: post.title,\n description: post.description || undefined,\n url: `${opinlyConfig.blogUrl}/${post.folder ? `${post.folder.slug + \"/\"}${post.slug}` : post.slug}`,\n datePublished: post.firstPublishedAt || undefined,\n dateModified: post.modifiedAt || undefined,\n image: post.titleFile?.fileKey\n ? {\n \"@type\": \"ImageObject\",\n url: `${opinlyConfig.imagesUrl}/${post.titleFile.fileKey}`,\n }\n : undefined,\n author: post.author\n ? {\n \"@type\": \"Person\",\n name: post.author.name,\n url: `${opinlyConfig.blogUrl}/author/${post.author.slug}`,\n description: post.author.bio || undefined,\n }\n : undefined,\n isAccessibleForFree: true,\n articleBody: generateArticleBodyHtml(post.content as JSONContent),\n };\n};\n\nexport const genBreadcrumbJSONLD = (
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/json-ld.ts"],"sourcesContent":["import {\n BlogPosting,\n BreadcrumbList,\n FAQPage,\n WithContext,\n ListItem,\n} from \"schema-dts\";\nimport { BlogPostRes } from \"../_types/blog-post\";\nimport { opinlyConfig } from \"../../../utils/sdk-config\";\nimport { JSONContent } from \"@tiptap/core\";\n\n// Add this function somewhere in your BlogPost component file\nexport function generateArticleBodyHtml(content: JSONContent): string {\n if (!content?.content) return \"\";\n\n let htmlString = \"\";\n\n content.content.forEach((node) => {\n switch (node.type) {\n case \"paragraph\":\n htmlString += `<p>${generateChildrenHtml(node.content)}</p>`;\n break;\n case \"heading\":\n const headingLevel = node.attrs?.level || 1;\n htmlString += `<h${headingLevel}>${generateChildrenHtml(\n node.content\n )}</h${headingLevel}>`;\n break;\n case \"bulletList\":\n htmlString += `<ul>${generateChildrenHtml(node.content)}</ul>`;\n break;\n case \"orderedList\":\n htmlString += `<ol>${generateChildrenHtml(node.content)}</ol>`;\n break;\n case \"listItem\":\n htmlString += `<li>${generateChildrenHtml(node.content)}</li>`;\n break;\n // Add other node types if they contain text content relevant for articleBody\n // For images, you might just skip them or include an <img> tag if semantic\n // For example:\n // case \"image\":\n // if (node.attrs?.src) {\n // htmlString += `<img src=\"${replaceImageHostname(node.attrs.src, opinlyConfig.imagesPrefix)}\" alt=\"${node.attrs?.alt || ''}\" />`;\n // }\n // break;\n default:\n // Handle other block types or just ignore them for articleBody\n break;\n }\n });\n\n return htmlString;\n}\n\nfunction generateChildrenHtml(\n nodes: JSONContent[\"content\"] | undefined\n): string {\n if (!nodes) return \"\";\n\n let childrenHtml = \"\";\n nodes.forEach((child) => {\n if (child.type === \"text\") {\n let text = child.text || \"\";\n if (child.marks) {\n child.marks.forEach((mark) => {\n if (mark.type === \"bold\") text = `<strong>${text}</strong>`;\n if (mark.type === \"italic\") text = `<em>${text}</em>`;\n if (mark.type === \"link\" && mark.attrs?.href) {\n text = `<a href=\"${mark.attrs.href}\">${text}</a>`;\n }\n });\n }\n childrenHtml += text;\n }\n // If you have nested content within child nodes, you might need a recursive call here\n // For example, if a list item can contain paragraphs\n // if (child.content) {\n // childrenHtml += generateChildrenHtml(child.content);\n // }\n });\n return childrenHtml;\n}\n\nexport const genFaqJSONLD = (\n faqs: NonNullable<BlogPostRes[\"faqs\"]>\n): WithContext<FAQPage> => {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n mainEntity: faqs.map((faq) => ({\n \"@type\": \"Question\",\n name: faq.question,\n acceptedAnswer: {\n \"@type\": \"Answer\",\n text: faq.answer,\n },\n })),\n };\n};\n\nexport const genBlogPostingJSONLD = (\n post: BlogPostRes\n): WithContext<BlogPosting> => {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BlogPosting\",\n headline: post.title,\n description: post.description || undefined,\n url: `${opinlyConfig.blogUrl}/${\n post.folder ? `${post.folder.slug + \"/\"}${post.slug}` : post.slug\n }`,\n datePublished: post.firstPublishedAt || undefined,\n dateModified: post.modifiedAt || undefined,\n image: post.titleFile?.fileKey\n ? {\n \"@type\": \"ImageObject\",\n url: `${opinlyConfig.imagesUrl}/${post.titleFile.fileKey}`,\n }\n : undefined,\n author: post.author\n ? {\n \"@type\": \"Person\",\n name: post.author.name,\n url: `${opinlyConfig.blogUrl}/author/${post.author.slug}`,\n description: post.author.bio || undefined,\n }\n : undefined,\n isAccessibleForFree: true,\n articleBody: generateArticleBodyHtml(post.content as JSONContent),\n };\n};\n\nexport const genBreadcrumbJSONLD = (post: BlogPostRes) => {\n const itemListElement = [\n {\n position: 1,\n name: opinlyConfig.siteName,\n item: opinlyConfig.siteUrl,\n },\n {\n position: 2,\n name: post.folder?.name || \"Blog\",\n item: `${opinlyConfig.blogUrl}/blog`,\n },\n ];\n\n if (post.folder) {\n itemListElement.push({\n position: 3,\n name: post.folder.name,\n item: `${opinlyConfig.blogUrl}/blog/${post.folder.slug}`,\n });\n\n itemListElement.push({\n position: 4,\n name: post.title,\n item: `${opinlyConfig.blogUrl}/blog/${post.folder.slug}/${post.slug}`,\n });\n } else {\n itemListElement.push({\n position: 3,\n name: post.title,\n item: `${opinlyConfig.blogUrl}/blog/${post.slug}`,\n });\n }\n\n return itemListElement;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WithContext, FAQPage, BlogPosting
|
|
1
|
+
import { WithContext, FAQPage, BlogPosting } from 'schema-dts';
|
|
2
2
|
import { BlogPostRes } from '../_types/blog-post.cjs';
|
|
3
3
|
import { JSONContent } from '@tiptap/core';
|
|
4
4
|
import '@opinly/backend';
|
|
@@ -6,6 +6,10 @@ import '@opinly/backend';
|
|
|
6
6
|
declare function generateArticleBodyHtml(content: JSONContent): string;
|
|
7
7
|
declare const genFaqJSONLD: (faqs: NonNullable<BlogPostRes["faqs"]>) => WithContext<FAQPage>;
|
|
8
8
|
declare const genBlogPostingJSONLD: (post: BlogPostRes) => WithContext<BlogPosting>;
|
|
9
|
-
declare const genBreadcrumbJSONLD: (post: BlogPostRes) =>
|
|
9
|
+
declare const genBreadcrumbJSONLD: (post: BlogPostRes) => {
|
|
10
|
+
position: number;
|
|
11
|
+
name: string;
|
|
12
|
+
item: string;
|
|
13
|
+
}[];
|
|
10
14
|
|
|
11
15
|
export { genBlogPostingJSONLD, genBreadcrumbJSONLD, genFaqJSONLD, generateArticleBodyHtml };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WithContext, FAQPage, BlogPosting
|
|
1
|
+
import { WithContext, FAQPage, BlogPosting } from 'schema-dts';
|
|
2
2
|
import { BlogPostRes } from '../_types/blog-post.js';
|
|
3
3
|
import { JSONContent } from '@tiptap/core';
|
|
4
4
|
import '@opinly/backend';
|
|
@@ -6,6 +6,10 @@ import '@opinly/backend';
|
|
|
6
6
|
declare function generateArticleBodyHtml(content: JSONContent): string;
|
|
7
7
|
declare const genFaqJSONLD: (faqs: NonNullable<BlogPostRes["faqs"]>) => WithContext<FAQPage>;
|
|
8
8
|
declare const genBlogPostingJSONLD: (post: BlogPostRes) => WithContext<BlogPosting>;
|
|
9
|
-
declare const genBreadcrumbJSONLD: (post: BlogPostRes) =>
|
|
9
|
+
declare const genBreadcrumbJSONLD: (post: BlogPostRes) => {
|
|
10
|
+
position: number;
|
|
11
|
+
name: string;
|
|
12
|
+
item: string;
|
|
13
|
+
}[];
|
|
10
14
|
|
|
11
15
|
export { genBlogPostingJSONLD, genBreadcrumbJSONLD, genFaqJSONLD, generateArticleBodyHtml };
|
|
@@ -9,7 +9,9 @@ function generateArticleBodyHtml(content) {
|
|
|
9
9
|
break;
|
|
10
10
|
case "heading":
|
|
11
11
|
const headingLevel = node.attrs?.level || 1;
|
|
12
|
-
htmlString += `<h${headingLevel}>${generateChildrenHtml(
|
|
12
|
+
htmlString += `<h${headingLevel}>${generateChildrenHtml(
|
|
13
|
+
node.content
|
|
14
|
+
)}</h${headingLevel}>`;
|
|
13
15
|
break;
|
|
14
16
|
case "bulletList":
|
|
15
17
|
htmlString += `<ul>${generateChildrenHtml(node.content)}</ul>`;
|
|
@@ -94,13 +96,11 @@ const genBlogPostingJSONLD = (post) => {
|
|
|
94
96
|
const genBreadcrumbJSONLD = (post) => {
|
|
95
97
|
const itemListElement = [
|
|
96
98
|
{
|
|
97
|
-
"@type": "ListItem",
|
|
98
99
|
position: 1,
|
|
99
|
-
name:
|
|
100
|
+
name: opinlyConfig.siteName,
|
|
100
101
|
item: opinlyConfig.siteUrl
|
|
101
102
|
},
|
|
102
103
|
{
|
|
103
|
-
"@type": "ListItem",
|
|
104
104
|
position: 2,
|
|
105
105
|
name: post.folder?.name || "Blog",
|
|
106
106
|
item: `${opinlyConfig.blogUrl}/blog`
|
|
@@ -108,30 +108,23 @@ const genBreadcrumbJSONLD = (post) => {
|
|
|
108
108
|
];
|
|
109
109
|
if (post.folder) {
|
|
110
110
|
itemListElement.push({
|
|
111
|
-
"@type": "ListItem",
|
|
112
111
|
position: 3,
|
|
113
112
|
name: post.folder.name,
|
|
114
113
|
item: `${opinlyConfig.blogUrl}/blog/${post.folder.slug}`
|
|
115
114
|
});
|
|
116
115
|
itemListElement.push({
|
|
117
|
-
"@type": "ListItem",
|
|
118
116
|
position: 4,
|
|
119
117
|
name: post.title,
|
|
120
118
|
item: `${opinlyConfig.blogUrl}/blog/${post.folder.slug}/${post.slug}`
|
|
121
119
|
});
|
|
122
120
|
} else {
|
|
123
121
|
itemListElement.push({
|
|
124
|
-
"@type": "ListItem",
|
|
125
122
|
position: 3,
|
|
126
123
|
name: post.title,
|
|
127
124
|
item: `${opinlyConfig.blogUrl}/blog/${post.slug}`
|
|
128
125
|
});
|
|
129
126
|
}
|
|
130
|
-
return
|
|
131
|
-
"@context": "https://schema.org",
|
|
132
|
-
"@type": "BreadcrumbList",
|
|
133
|
-
itemListElement
|
|
134
|
-
};
|
|
127
|
+
return itemListElement;
|
|
135
128
|
};
|
|
136
129
|
export {
|
|
137
130
|
genBlogPostingJSONLD,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/json-ld.ts"],"sourcesContent":["import {\n BlogPosting,\n BreadcrumbList,\n FAQPage,\n WithContext,\n ListItem,\n} from \"schema-dts\";\nimport { BlogPostRes } from \"../_types/blog-post\";\nimport { opinlyConfig } from \"../../../utils/sdk-config\";\nimport { JSONContent } from \"@tiptap/core\";\n\n// Add this function somewhere in your BlogPost component file\nexport function generateArticleBodyHtml(content: JSONContent): string {\n if (!content?.content) return \"\";\n\n let htmlString = \"\";\n\n content.content.forEach((node) => {\n switch (node.type) {\n case \"paragraph\":\n htmlString += `<p>${generateChildrenHtml(node.content)}</p>`;\n break;\n case \"heading\":\n const headingLevel = node.attrs?.level || 1;\n htmlString += `<h${headingLevel}>${generateChildrenHtml(node.content)}</h${headingLevel}>`;\n break;\n case \"bulletList\":\n htmlString += `<ul>${generateChildrenHtml(node.content)}</ul>`;\n break;\n case \"orderedList\":\n htmlString += `<ol>${generateChildrenHtml(node.content)}</ol>`;\n break;\n case \"listItem\":\n htmlString += `<li>${generateChildrenHtml(node.content)}</li>`;\n break;\n // Add other node types if they contain text content relevant for articleBody\n // For images, you might just skip them or include an <img> tag if semantic\n // For example:\n // case \"image\":\n // if (node.attrs?.src) {\n // htmlString += `<img src=\"${replaceImageHostname(node.attrs.src, opinlyConfig.imagesPrefix)}\" alt=\"${node.attrs?.alt || ''}\" />`;\n // }\n // break;\n default:\n // Handle other block types or just ignore them for articleBody\n break;\n }\n });\n\n return htmlString;\n}\n\nfunction generateChildrenHtml(\n nodes: JSONContent[\"content\"] | undefined\n): string {\n if (!nodes) return \"\";\n\n let childrenHtml = \"\";\n nodes.forEach((child) => {\n if (child.type === \"text\") {\n let text = child.text || \"\";\n if (child.marks) {\n child.marks.forEach((mark) => {\n if (mark.type === \"bold\") text = `<strong>${text}</strong>`;\n if (mark.type === \"italic\") text = `<em>${text}</em>`;\n if (mark.type === \"link\" && mark.attrs?.href) {\n text = `<a href=\"${mark.attrs.href}\">${text}</a>`;\n }\n });\n }\n childrenHtml += text;\n }\n // If you have nested content within child nodes, you might need a recursive call here\n // For example, if a list item can contain paragraphs\n // if (child.content) {\n // childrenHtml += generateChildrenHtml(child.content);\n // }\n });\n return childrenHtml;\n}\n\nexport const genFaqJSONLD = (\n faqs: NonNullable<BlogPostRes[\"faqs\"]>\n): WithContext<FAQPage> => {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n mainEntity: faqs.map((faq) => ({\n \"@type\": \"Question\",\n name: faq.question,\n acceptedAnswer: {\n \"@type\": \"Answer\",\n text: faq.answer,\n },\n })),\n };\n};\n\nexport const genBlogPostingJSONLD = (\n post: BlogPostRes\n): WithContext<BlogPosting> => {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BlogPosting\",\n headline: post.title,\n description: post.description || undefined,\n url: `${opinlyConfig.blogUrl}/${post.folder ? `${post.folder.slug + \"/\"}${post.slug}` : post.slug}`,\n datePublished: post.firstPublishedAt || undefined,\n dateModified: post.modifiedAt || undefined,\n image: post.titleFile?.fileKey\n ? {\n \"@type\": \"ImageObject\",\n url: `${opinlyConfig.imagesUrl}/${post.titleFile.fileKey}`,\n }\n : undefined,\n author: post.author\n ? {\n \"@type\": \"Person\",\n name: post.author.name,\n url: `${opinlyConfig.blogUrl}/author/${post.author.slug}`,\n description: post.author.bio || undefined,\n }\n : undefined,\n isAccessibleForFree: true,\n articleBody: generateArticleBodyHtml(post.content as JSONContent),\n };\n};\n\nexport const genBreadcrumbJSONLD = (
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/json-ld.ts"],"sourcesContent":["import {\n BlogPosting,\n BreadcrumbList,\n FAQPage,\n WithContext,\n ListItem,\n} from \"schema-dts\";\nimport { BlogPostRes } from \"../_types/blog-post\";\nimport { opinlyConfig } from \"../../../utils/sdk-config\";\nimport { JSONContent } from \"@tiptap/core\";\n\n// Add this function somewhere in your BlogPost component file\nexport function generateArticleBodyHtml(content: JSONContent): string {\n if (!content?.content) return \"\";\n\n let htmlString = \"\";\n\n content.content.forEach((node) => {\n switch (node.type) {\n case \"paragraph\":\n htmlString += `<p>${generateChildrenHtml(node.content)}</p>`;\n break;\n case \"heading\":\n const headingLevel = node.attrs?.level || 1;\n htmlString += `<h${headingLevel}>${generateChildrenHtml(\n node.content\n )}</h${headingLevel}>`;\n break;\n case \"bulletList\":\n htmlString += `<ul>${generateChildrenHtml(node.content)}</ul>`;\n break;\n case \"orderedList\":\n htmlString += `<ol>${generateChildrenHtml(node.content)}</ol>`;\n break;\n case \"listItem\":\n htmlString += `<li>${generateChildrenHtml(node.content)}</li>`;\n break;\n // Add other node types if they contain text content relevant for articleBody\n // For images, you might just skip them or include an <img> tag if semantic\n // For example:\n // case \"image\":\n // if (node.attrs?.src) {\n // htmlString += `<img src=\"${replaceImageHostname(node.attrs.src, opinlyConfig.imagesPrefix)}\" alt=\"${node.attrs?.alt || ''}\" />`;\n // }\n // break;\n default:\n // Handle other block types or just ignore them for articleBody\n break;\n }\n });\n\n return htmlString;\n}\n\nfunction generateChildrenHtml(\n nodes: JSONContent[\"content\"] | undefined\n): string {\n if (!nodes) return \"\";\n\n let childrenHtml = \"\";\n nodes.forEach((child) => {\n if (child.type === \"text\") {\n let text = child.text || \"\";\n if (child.marks) {\n child.marks.forEach((mark) => {\n if (mark.type === \"bold\") text = `<strong>${text}</strong>`;\n if (mark.type === \"italic\") text = `<em>${text}</em>`;\n if (mark.type === \"link\" && mark.attrs?.href) {\n text = `<a href=\"${mark.attrs.href}\">${text}</a>`;\n }\n });\n }\n childrenHtml += text;\n }\n // If you have nested content within child nodes, you might need a recursive call here\n // For example, if a list item can contain paragraphs\n // if (child.content) {\n // childrenHtml += generateChildrenHtml(child.content);\n // }\n });\n return childrenHtml;\n}\n\nexport const genFaqJSONLD = (\n faqs: NonNullable<BlogPostRes[\"faqs\"]>\n): WithContext<FAQPage> => {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n mainEntity: faqs.map((faq) => ({\n \"@type\": \"Question\",\n name: faq.question,\n acceptedAnswer: {\n \"@type\": \"Answer\",\n text: faq.answer,\n },\n })),\n };\n};\n\nexport const genBlogPostingJSONLD = (\n post: BlogPostRes\n): WithContext<BlogPosting> => {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BlogPosting\",\n headline: post.title,\n description: post.description || undefined,\n url: `${opinlyConfig.blogUrl}/${\n post.folder ? `${post.folder.slug + \"/\"}${post.slug}` : post.slug\n }`,\n datePublished: post.firstPublishedAt || undefined,\n dateModified: post.modifiedAt || undefined,\n image: post.titleFile?.fileKey\n ? {\n \"@type\": \"ImageObject\",\n url: `${opinlyConfig.imagesUrl}/${post.titleFile.fileKey}`,\n }\n : undefined,\n author: post.author\n ? {\n \"@type\": \"Person\",\n name: post.author.name,\n url: `${opinlyConfig.blogUrl}/author/${post.author.slug}`,\n description: post.author.bio || undefined,\n }\n : undefined,\n isAccessibleForFree: true,\n articleBody: generateArticleBodyHtml(post.content as JSONContent),\n };\n};\n\nexport const genBreadcrumbJSONLD = (post: BlogPostRes) => {\n const itemListElement = [\n {\n position: 1,\n name: opinlyConfig.siteName,\n item: opinlyConfig.siteUrl,\n },\n {\n position: 2,\n name: post.folder?.name || \"Blog\",\n item: `${opinlyConfig.blogUrl}/blog`,\n },\n ];\n\n if (post.folder) {\n itemListElement.push({\n position: 3,\n name: post.folder.name,\n item: `${opinlyConfig.blogUrl}/blog/${post.folder.slug}`,\n });\n\n itemListElement.push({\n position: 4,\n name: post.title,\n item: `${opinlyConfig.blogUrl}/blog/${post.folder.slug}/${post.slug}`,\n });\n } else {\n itemListElement.push({\n position: 3,\n name: post.title,\n item: `${opinlyConfig.blogUrl}/blog/${post.slug}`,\n });\n }\n\n return itemListElement;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -38,7 +38,7 @@ const countWords = (content) => {
|
|
|
38
38
|
return wordCount;
|
|
39
39
|
};
|
|
40
40
|
function calculateReadingTime(content) {
|
|
41
|
-
const wordCount = countWords(content
|
|
41
|
+
const wordCount = countWords(content);
|
|
42
42
|
const readingTimeMinutes = Math.ceil(wordCount / 200);
|
|
43
43
|
return readingTimeMinutes;
|
|
44
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/reading-time.ts"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\n\nexport const countWords = (content: JSONContent | undefined): number => {\n if (!content?.content) return 0;\n\n let wordCount = 0;\n\n const countWords = (nodes: any[]) => {\n for (const node of nodes) {\n if (node.type === \"text\" && node.text) {\n const words = node.text.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n }\n if (node.content) countWords(node.content);\n }\n };\n\n countWords(content.content);\n\n return wordCount;\n};\n\nexport function calculateReadingTime(content: JSONContent): number {\n const wordCount = countWords(content
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/reading-time.ts"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\n\nexport const countWords = (content: JSONContent | undefined): number => {\n if (!content?.content) return 0;\n\n let wordCount = 0;\n\n const countWords = (nodes: any[]) => {\n for (const node of nodes) {\n if (node.type === \"text\" && node.text) {\n const words = node.text.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n }\n if (node.content) countWords(node.content);\n }\n };\n\n countWords(content.content);\n\n return wordCount;\n};\n\nexport function calculateReadingTime(content: JSONContent): number {\n const wordCount = countWords(content);\n\n const readingTimeMinutes = Math.ceil(wordCount / 200);\n return readingTimeMinutes;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,aAAa,CAAC,YAA6C;AACtE,MAAI,CAAC,SAAS,QAAS,QAAO;AAE9B,MAAI,YAAY;AAEhB,QAAMA,cAAa,CAAC,UAAiB;AACnC,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,UAAU,KAAK,MAAM;AACrC,cAAM,QAAQ,KAAK,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AAC1D,qBAAa,MAAM;AAAA,MACrB;AACA,UAAI,KAAK,QAAS,CAAAA,YAAW,KAAK,OAAO;AAAA,IAC3C;AAAA,EACF;AAEA,EAAAA,YAAW,QAAQ,OAAO;AAE1B,SAAO;AACT;AAEO,SAAS,qBAAqB,SAA8B;AACjE,QAAM,YAAY,WAAW,OAAO;AAEpC,QAAM,qBAAqB,KAAK,KAAK,YAAY,GAAG;AACpD,SAAO;AACT;","names":["countWords"]}
|
|
@@ -14,7 +14,7 @@ const countWords = (content) => {
|
|
|
14
14
|
return wordCount;
|
|
15
15
|
};
|
|
16
16
|
function calculateReadingTime(content) {
|
|
17
|
-
const wordCount = countWords(content
|
|
17
|
+
const wordCount = countWords(content);
|
|
18
18
|
const readingTimeMinutes = Math.ceil(wordCount / 200);
|
|
19
19
|
return readingTimeMinutes;
|
|
20
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/reading-time.ts"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\n\nexport const countWords = (content: JSONContent | undefined): number => {\n if (!content?.content) return 0;\n\n let wordCount = 0;\n\n const countWords = (nodes: any[]) => {\n for (const node of nodes) {\n if (node.type === \"text\" && node.text) {\n const words = node.text.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n }\n if (node.content) countWords(node.content);\n }\n };\n\n countWords(content.content);\n\n return wordCount;\n};\n\nexport function calculateReadingTime(content: JSONContent): number {\n const wordCount = countWords(content
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blog-post/_helpers/reading-time.ts"],"sourcesContent":["import { JSONContent } from \"@tiptap/core\";\n\nexport const countWords = (content: JSONContent | undefined): number => {\n if (!content?.content) return 0;\n\n let wordCount = 0;\n\n const countWords = (nodes: any[]) => {\n for (const node of nodes) {\n if (node.type === \"text\" && node.text) {\n const words = node.text.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n }\n if (node.content) countWords(node.content);\n }\n };\n\n countWords(content.content);\n\n return wordCount;\n};\n\nexport function calculateReadingTime(content: JSONContent): number {\n const wordCount = countWords(content);\n\n const readingTimeMinutes = Math.ceil(wordCount / 200);\n return readingTimeMinutes;\n}\n"],"mappings":"AAEO,MAAM,aAAa,CAAC,YAA6C;AACtE,MAAI,CAAC,SAAS,QAAS,QAAO;AAE9B,MAAI,YAAY;AAEhB,QAAMA,cAAa,CAAC,UAAiB;AACnC,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,UAAU,KAAK,MAAM;AACrC,cAAM,QAAQ,KAAK,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AAC1D,qBAAa,MAAM;AAAA,MACrB;AACA,UAAI,KAAK,QAAS,CAAAA,YAAW,KAAK,OAAO;AAAA,IAC3C;AAAA,EACF;AAEA,EAAAA,YAAW,QAAQ,OAAO;AAE1B,SAAO;AACT;AAEO,SAAS,qBAAqB,SAA8B;AACjE,QAAM,YAAY,WAAW,OAAO;AAEpC,QAAM,qBAAqB,KAAK,KAAK,YAAY,GAAG;AACpD,SAAO;AACT;","names":["countWords"]}
|
|
@@ -48,6 +48,7 @@ const BlogPost = ({
|
|
|
48
48
|
classNames = {}
|
|
49
49
|
}) => {
|
|
50
50
|
const content = post.content;
|
|
51
|
+
console.log("is app router", !import_sdk_config.opinlyConfig.pagesRouter);
|
|
51
52
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
52
53
|
post.faqs && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
53
54
|
import_script.default,
|
|
@@ -83,7 +84,7 @@ const BlogPost = ({
|
|
|
83
84
|
}
|
|
84
85
|
),
|
|
85
86
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "max-w-7xl mx-auto px-4 py-24 flex items-start space-x-8", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-12 w-full", children: [
|
|
86
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
87
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
87
88
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
88
89
|
import_bread_crumbs.BreadCrumbs,
|
|
89
90
|
{
|
|
@@ -95,39 +96,42 @@ const BlogPost = ({
|
|
|
95
96
|
]
|
|
96
97
|
}
|
|
97
98
|
),
|
|
98
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-4xl font-bold mb-2 leading-tight", children: post.title }),
|
|
99
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-sm mb-4", children: [
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
(0,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
99
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-op-heading text-4xl font-bold mb-2 leading-tight", children: post.title }),
|
|
100
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-sm mb-4 text-op-muted space-x-1", children: [
|
|
101
|
+
post.author && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
102
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
103
|
+
import_link.default,
|
|
104
|
+
{
|
|
105
|
+
href: `${import_sdk_config.opinlyConfig.blogPrefix}/authors/${post.author?.slug}`,
|
|
106
|
+
className: "font-medium",
|
|
107
|
+
children: post.author?.name
|
|
108
|
+
}
|
|
109
|
+
),
|
|
110
|
+
" ",
|
|
111
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-op-muted", children: "\xB7" })
|
|
112
|
+
] }),
|
|
113
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
114
|
+
(0, import_reading_time.calculateReadingTime)(content),
|
|
115
|
+
" min read ",
|
|
116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\xB7" })
|
|
117
|
+
] }),
|
|
118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: (0, import_dates.formatDate)(post.firstPublishedAt) || "Today" })
|
|
116
119
|
] })
|
|
117
120
|
] }),
|
|
118
121
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
119
122
|
"div",
|
|
120
123
|
{
|
|
121
124
|
className: (0, import_merge.cn)(
|
|
122
|
-
"flex
|
|
125
|
+
"flex md:space-x-12 flex-col mx-auto w-full",
|
|
126
|
+
"md:flex-row-reverse",
|
|
123
127
|
classNames.container
|
|
124
128
|
),
|
|
125
129
|
children: [
|
|
126
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("article", { className: "w-full
|
|
130
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("article", { className: "w-full md:w-3/4 order-2 md:order-1 flex items-start", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "prose w-full ", children: [
|
|
127
131
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_content.Content, { content, classNames }),
|
|
128
132
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_faq.FAQS, { faqs: post.faqs })
|
|
129
133
|
] }) }),
|
|
130
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "
|
|
134
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex md:w-1/4 md:sticky md:top-20", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
131
135
|
import_table_of_contents.TableOfContents,
|
|
132
136
|
{
|
|
133
137
|
content,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/blog-post/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { JSONContent } from \"@tiptap/core\";\nimport Link from \"next/link\";\nimport { cn } from \"../../utils/merge\";\nimport { opinlyConfig } from \"../../utils/sdk-config\";\nimport { BlogPostRes } from \"./_types/blog-post\";\nimport {\n genBlogPostingJSONLD,\n genBreadcrumbJSONLD,\n genFaqJSONLD,\n} from \"./_helpers/json-ld\";\nimport { BlogComponentClassNames } from \"./_types/class-names\";\nimport { FAQS } from \"./_components/faq\";\nimport { calculateReadingTime } from \"./_helpers/reading-time\";\nimport { Content } from \"./_components/content\";\nimport { TableOfContents } from \"./_components/table-of-contents\";\nimport { BreadCrumbs } from \"../bread-crumbs\";\nimport { formatDate } from \"../../utils/dates\";\nimport Script from \"next/script\";\n\nexport const BlogPost = ({\n post,\n classNames = {},\n}: {\n post: BlogPostRes;\n classNames?: BlogComponentClassNames;\n notFoundComponent?: React.ReactNode;\n}) => {\n const content = post.content as JSONContent;\n\n return (\n <>\n {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/blog-post/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { JSONContent } from \"@tiptap/core\";\nimport Link from \"next/link\";\nimport { cn } from \"../../utils/merge\";\nimport { opinlyConfig } from \"../../utils/sdk-config\";\nimport { BlogPostRes } from \"./_types/blog-post\";\nimport {\n genBlogPostingJSONLD,\n genBreadcrumbJSONLD,\n genFaqJSONLD,\n} from \"./_helpers/json-ld\";\nimport { BlogComponentClassNames } from \"./_types/class-names\";\nimport { FAQS } from \"./_components/faq\";\nimport { calculateReadingTime } from \"./_helpers/reading-time\";\nimport { Content } from \"./_components/content\";\nimport { TableOfContents } from \"./_components/table-of-contents\";\nimport { BreadCrumbs } from \"../bread-crumbs\";\nimport { formatDate } from \"../../utils/dates\";\nimport Script from \"next/script\";\n\nexport const BlogPost = ({\n post,\n classNames = {},\n}: {\n post: BlogPostRes;\n classNames?: BlogComponentClassNames;\n notFoundComponent?: React.ReactNode;\n}) => {\n const content = post.content as JSONContent;\n\n console.log(\"is app router\", !opinlyConfig.pagesRouter);\n\n return (\n <>\n {post.faqs && (\n <Script\n strategy=\"beforeInteractive\"\n type=\"application/ld+json\"\n dangerouslySetInnerHTML={{\n __html: JSON.stringify(genFaqJSONLD(post.faqs)).replace(\n /</g,\n \"\\\\u003c\"\n ),\n }}\n />\n )}\n <Script\n strategy=\"beforeInteractive\"\n type=\"application/ld+json\"\n dangerouslySetInnerHTML={{\n __html: JSON.stringify(genBlogPostingJSONLD(post)),\n }}\n />\n <Script\n strategy=\"beforeInteractive\"\n type=\"application/ld+json\"\n dangerouslySetInnerHTML={{\n __html: JSON.stringify(genBreadcrumbJSONLD(post)),\n }}\n />\n <div className=\"max-w-7xl mx-auto px-4 py-24 flex items-start space-x-8\">\n <div className=\"flex flex-col gap-12 w-full\">\n <div>\n <BreadCrumbs\n breadcrumbs={[\n post.folder && {\n url: `${opinlyConfig.blogPrefix}/${post.folder.slug}`,\n name: post.folder.name,\n },\n ]}\n />\n\n <h1 className=\"text-op-heading text-4xl font-bold mb-2 leading-tight\">\n {post.title}\n </h1>\n <div className=\"text-sm mb-4 text-op-muted space-x-1\">\n {post.author && (\n <>\n <Link\n href={`${opinlyConfig.blogPrefix}/authors/${post.author?.slug}`}\n className=\"font-medium\"\n >\n {post.author?.name}\n </Link>{\" \"}\n <span className=\"text-op-muted\">·</span>\n </>\n )}\n <span>\n {calculateReadingTime(content)} min read <span>·</span>\n </span>\n <span>\n {formatDate(post.firstPublishedAt as string) || \"Today\"}\n </span>\n </div>\n </div>\n\n <div\n className={cn(\n \"flex md:space-x-12 flex-col mx-auto w-full\",\n \"md:flex-row-reverse\",\n classNames.container\n )}\n >\n <article className=\"w-full md:w-3/4 order-2 md:order-1 flex items-start\">\n <div className=\"prose w-full \">\n <Content content={content} classNames={classNames} />\n <FAQS faqs={post.faqs} />\n </div>\n </article>\n <div className=\"flex md:w-1/4 md:sticky md:top-20\">\n <TableOfContents\n content={content}\n author={post.author}\n post={post}\n />\n </div>\n </div>\n </div>\n </div>\n </>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCQ;AAjCR,kBAAiB;AACjB,mBAAmB;AACnB,wBAA6B;AAE7B,qBAIO;AAEP,iBAAqB;AACrB,0BAAqC;AACrC,qBAAwB;AACxB,+BAAgC;AAChC,0BAA4B;AAC5B,mBAA2B;AAC3B,oBAAmB;AAEZ,MAAM,WAAW,CAAC;AAAA,EACvB;AAAA,EACA,aAAa,CAAC;AAChB,MAIM;AACJ,QAAM,UAAU,KAAK;AAErB,UAAQ,IAAI,iBAAiB,CAAC,+BAAa,WAAW;AAEtD,SACE,4EACG;AAAA,SAAK,QACJ;AAAA,MAAC,cAAAA;AAAA,MAAA;AAAA,QACC,UAAS;AAAA,QACT,MAAK;AAAA,QACL,yBAAyB;AAAA,UACvB,QAAQ,KAAK,cAAU,6BAAa,KAAK,IAAI,CAAC,EAAE;AAAA,YAC9C;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA;AAAA,IACF;AAAA,IAEF;AAAA,MAAC,cAAAA;AAAA,MAAA;AAAA,QACC,UAAS;AAAA,QACT,MAAK;AAAA,QACL,yBAAyB;AAAA,UACvB,QAAQ,KAAK,cAAU,qCAAqB,IAAI,CAAC;AAAA,QACnD;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC,cAAAA;AAAA,MAAA;AAAA,QACC,UAAS;AAAA,QACT,MAAK;AAAA,QACL,yBAAyB;AAAA,UACvB,QAAQ,KAAK,cAAU,oCAAoB,IAAI,CAAC;AAAA,QAClD;AAAA;AAAA,IACF;AAAA,IACA,4CAAC,SAAI,WAAU,2DACb,uDAAC,SAAI,WAAU,+BACb;AAAA,mDAAC,SACC;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,aAAa;AAAA,cACX,KAAK,UAAU;AAAA,gBACb,KAAK,GAAG,+BAAa,UAAU,IAAI,KAAK,OAAO,IAAI;AAAA,gBACnD,MAAM,KAAK,OAAO;AAAA,cACpB;AAAA,YACF;AAAA;AAAA,QACF;AAAA,QAEA,4CAAC,QAAG,WAAU,yDACX,eAAK,OACR;AAAA,QACA,6CAAC,SAAI,WAAU,wCACZ;AAAA,eAAK,UACJ,4EACE;AAAA;AAAA,cAAC,YAAAC;AAAA,cAAA;AAAA,gBACC,MAAM,GAAG,+BAAa,UAAU,YAAY,KAAK,QAAQ,IAAI;AAAA,gBAC7D,WAAU;AAAA,gBAET,eAAK,QAAQ;AAAA;AAAA,YAChB;AAAA,YAAQ;AAAA,YACR,4CAAC,UAAK,WAAU,iBAAgB,kBAAC;AAAA,aACnC;AAAA,UAEF,6CAAC,UACE;AAAA,0DAAqB,OAAO;AAAA,YAAE;AAAA,YAAU,4CAAC,UAAK,kBAAC;AAAA,aAClD;AAAA,UACA,4CAAC,UACE,uCAAW,KAAK,gBAA0B,KAAK,SAClD;AAAA,WACF;AAAA,SACF;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA,WAAW;AAAA,UACb;AAAA,UAEA;AAAA,wDAAC,aAAQ,WAAU,uDACjB,uDAAC,SAAI,WAAU,iBACb;AAAA,0DAAC,0BAAQ,SAAkB,YAAwB;AAAA,cACnD,4CAAC,mBAAK,MAAM,KAAK,MAAM;AAAA,eACzB,GACF;AAAA,YACA,4CAAC,SAAI,WAAU,qCACb;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA,QAAQ,KAAK;AAAA,gBACb;AAAA;AAAA,YACF,GACF;AAAA;AAAA;AAAA,MACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;","names":["Script","Link"]}
|