@opinly/next 0.1.4 → 0.1.6

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/index.mjs DELETED
@@ -1,838 +0,0 @@
1
- // src/components/blog-post/index.tsx
2
- import Link5 from "next/link";
3
-
4
- // src/utils/merge.ts
5
- import { clsx } from "clsx";
6
- import { twMerge } from "tailwind-merge";
7
- var cn = (...inputs) => {
8
- return twMerge(clsx(inputs));
9
- };
10
-
11
- // src/sdk-config.ts
12
- var siteUrl = process.env.OPINLY_SITE_URL;
13
- var opinlyEnvVars = {
14
- OPINLY_IMAGES_PREFIX: process.env.OPINLY_IMAGES_PREFIX,
15
- OPINLY_SITE_URL: process.env.OPINLY_SITE_URL,
16
- OPINLY_BLOG_PREFIX: process.env.OPINLY_BLOG_PREFIX,
17
- OPINLY_CDN_URL: process.env.OPINLY_CDN_URL,
18
- OPINLY_SITE_NAME: process.env.OPINLY_SITE_NAME
19
- };
20
- Object.entries(opinlyEnvVars).forEach(([key, value]) => {
21
- if (!value) {
22
- throw new Error(`OPINLY ERROR: env var ${key} is not set`);
23
- }
24
- });
25
- var opinlyConfig = {
26
- cdnUrl: process.env.OPINLY_CDN_URL || "https://cdn.opinly.ai",
27
- siteUrl: process.env.OPINLY_SITE_URL,
28
- imagesPrefix: process.env.OPINLY_IMAGES_PREFIX,
29
- imagesUrl: `${process.env.OPINLY_SITE_URL}${process.env.OPINLY_IMAGES_PREFIX}`,
30
- blogPrefix: process.env.OPINLY_BLOG_PREFIX,
31
- blogUrl: `${process.env.OPINLY_SITE_URL}${process.env.OPINLY_BLOG_PREFIX}`,
32
- siteName: process.env.OPINLY_SITE_NAME
33
- };
34
-
35
- // src/utils/images.ts
36
- function replaceImageNameSpace(fileKey) {
37
- const pathParts = fileKey.split("/").filter(Boolean);
38
- if (pathParts.length > 1) {
39
- pathParts.shift();
40
- }
41
- return pathParts.join("/");
42
- }
43
-
44
- // src/components/blog-post/_helpers/json-ld.ts
45
- function generateArticleBodyHtml(content) {
46
- if (!content?.content)
47
- return "";
48
- let htmlString = "";
49
- content.content.forEach((node) => {
50
- switch (node.type) {
51
- case "paragraph":
52
- htmlString += `<p>${generateChildrenHtml(node.content)}</p>`;
53
- break;
54
- case "heading":
55
- const headingLevel = node.attrs?.level || 1;
56
- htmlString += `<h${headingLevel}>${generateChildrenHtml(node.content)}</h${headingLevel}>`;
57
- break;
58
- case "bulletList":
59
- htmlString += `<ul>${generateChildrenHtml(node.content)}</ul>`;
60
- break;
61
- case "orderedList":
62
- htmlString += `<ol>${generateChildrenHtml(node.content)}</ol>`;
63
- break;
64
- case "listItem":
65
- htmlString += `<li>${generateChildrenHtml(node.content)}</li>`;
66
- break;
67
- default:
68
- break;
69
- }
70
- });
71
- return htmlString;
72
- }
73
- function generateChildrenHtml(nodes) {
74
- if (!nodes)
75
- return "";
76
- let childrenHtml = "";
77
- nodes.forEach((child) => {
78
- if (child.type === "text") {
79
- let text = child.text || "";
80
- if (child.marks) {
81
- child.marks.forEach((mark) => {
82
- if (mark.type === "bold")
83
- text = `<strong>${text}</strong>`;
84
- if (mark.type === "italic")
85
- text = `<em>${text}</em>`;
86
- if (mark.type === "link" && mark.attrs?.href) {
87
- text = `<a href="${mark.attrs.href}">${text}</a>`;
88
- }
89
- });
90
- }
91
- childrenHtml += text;
92
- }
93
- });
94
- return childrenHtml;
95
- }
96
- var genFaqJSONLD = (faqs) => {
97
- return {
98
- "@context": "https://schema.org",
99
- "@type": "FAQPage",
100
- mainEntity: faqs.map((faq) => ({
101
- "@type": "Question",
102
- name: faq.question,
103
- acceptedAnswer: {
104
- "@type": "Answer",
105
- text: faq.answer
106
- }
107
- }))
108
- };
109
- };
110
- var genBlogPostingJSONLD = (post) => {
111
- return {
112
- "@context": "https://schema.org",
113
- "@type": "BlogPosting",
114
- headline: post.title,
115
- description: post.description || void 0,
116
- url: `${opinlyConfig.blogUrl}/${post.folder ? `${post.folder.slug + "/"}${post.slug}` : post.slug}`,
117
- datePublished: post.firstPublishedAt || void 0,
118
- dateModified: post.modifiedAt || void 0,
119
- image: post.titleFile?.fileKey ? {
120
- "@type": "ImageObject",
121
- url: `${opinlyConfig.imagesUrl}/${replaceImageNameSpace(post.titleFile.fileKey)}`
122
- } : void 0,
123
- author: post.author ? {
124
- "@type": "Person",
125
- name: post.author.name,
126
- url: `${opinlyConfig.blogUrl}/author/${post.author.slug}`,
127
- description: post.author.bio || void 0
128
- } : void 0,
129
- isAccessibleForFree: true,
130
- articleBody: generateArticleBodyHtml(post.content)
131
- };
132
- };
133
- var genBreadcrumbJSONLD = (post) => {
134
- const itemListElement = [
135
- {
136
- "@type": "ListItem",
137
- position: 1,
138
- name: "Company Name",
139
- item: opinlyConfig.siteUrl
140
- },
141
- {
142
- "@type": "ListItem",
143
- position: 2,
144
- name: post.folder?.name || "Blog",
145
- item: `${opinlyConfig.blogUrl}/blog`
146
- }
147
- ];
148
- if (post.folder) {
149
- itemListElement.push({
150
- "@type": "ListItem",
151
- position: 3,
152
- name: post.folder.name,
153
- item: `${opinlyConfig.blogUrl}/blog/${post.folder.slug}`
154
- });
155
- itemListElement.push({
156
- "@type": "ListItem",
157
- position: 4,
158
- name: post.title,
159
- item: `${opinlyConfig.blogUrl}/blog/${post.folder.slug}/${post.slug}`
160
- });
161
- } else {
162
- itemListElement.push({
163
- "@type": "ListItem",
164
- position: 3,
165
- name: post.title,
166
- item: `${opinlyConfig.blogUrl}/blog/${post.slug}`
167
- });
168
- }
169
- return {
170
- "@context": "https://schema.org",
171
- "@type": "BreadcrumbList",
172
- itemListElement
173
- };
174
- };
175
-
176
- // src/components/blog-post/_components/faq.tsx
177
- import { jsx, jsxs } from "react/jsx-runtime";
178
- var FAQS = ({ faqs }) => {
179
- if (!faqs)
180
- return null;
181
- return /* @__PURE__ */ jsxs("div", { children: [
182
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold mb-2", children: "FAQS" }),
183
- /* @__PURE__ */ jsx("ul", { children: faqs.map((faq) => /* @__PURE__ */ jsxs("li", { children: [
184
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: faq.question }),
185
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-700", children: faq.answer })
186
- ] }, faq.question)) })
187
- ] });
188
- };
189
-
190
- // src/components/blog-post/_helpers/reading-time.ts
191
- var countWords = (content) => {
192
- if (!content?.content)
193
- return 0;
194
- let wordCount = 0;
195
- const countWords2 = (nodes) => {
196
- for (const node of nodes) {
197
- if (node.type === "text" && node.text) {
198
- const words = node.text.trim().split(/\s+/).filter(Boolean);
199
- wordCount += words.length;
200
- }
201
- if (node.content)
202
- countWords2(node.content);
203
- }
204
- };
205
- countWords2(content.content);
206
- return wordCount;
207
- };
208
- function calculateReadingTime(content) {
209
- const wordCount = countWords(content.content);
210
- const readingTimeMinutes = Math.ceil(wordCount / 200);
211
- return readingTimeMinutes;
212
- }
213
-
214
- // src/components/blog-post/_components/content.tsx
215
- import Link from "next/link";
216
- import { jsx as jsx2 } from "react/jsx-runtime";
217
- function renderTiptapContent(content, classNames) {
218
- if (!content?.content)
219
- return [];
220
- return content.content.map((node, index) => {
221
- switch (node.type) {
222
- case "paragraph":
223
- return /* @__PURE__ */ jsx2("p", { className: classNames.paragraph || "mb-4", children: renderChildren(node.content, classNames) }, index);
224
- case "heading": {
225
- const text = node.content?.[0]?.text ?? "";
226
- const slug = text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
227
- const Tag = `h${node.attrs?.level || 1}`;
228
- return /* @__PURE__ */ jsx2(
229
- Tag,
230
- {
231
- id: slug,
232
- className: classNames.heading || "mt-8 mb-4 font-bold text-gray-800",
233
- children: renderChildren(node.content, classNames)
234
- },
235
- index
236
- );
237
- }
238
- case "image":
239
- return /* @__PURE__ */ jsx2(
240
- "div",
241
- {
242
- className: cn(
243
- "relative w-full max-w-[800px] my-6",
244
- classNames.image
245
- ),
246
- style: { aspectRatio: "2 / 1" }
247
- },
248
- index
249
- );
250
- case "bulletList":
251
- return /* @__PURE__ */ jsx2(
252
- "ul",
253
- {
254
- className: classNames.bulletList || "list-disc pl-6 my-4",
255
- children: renderChildren(node.content, classNames)
256
- },
257
- index
258
- );
259
- case "orderedList":
260
- return /* @__PURE__ */ jsx2(
261
- "ol",
262
- {
263
- className: classNames.orderedList || "list-decimal pl-6 my-4",
264
- children: renderChildren(node.content, classNames)
265
- },
266
- index
267
- );
268
- case "listItem":
269
- return /* @__PURE__ */ jsx2("li", { className: classNames.listItem || "my-1", children: renderChildren(node.content, classNames) }, index);
270
- default:
271
- return null;
272
- }
273
- }).filter(Boolean);
274
- }
275
- var Content = ({
276
- content,
277
- classNames
278
- }) => {
279
- return /* @__PURE__ */ jsx2("div", { className: "prose min-w-full", children: renderTiptapContent(content, classNames) });
280
- };
281
- function renderChildren(nodes, classNames) {
282
- if (!nodes)
283
- return [];
284
- return nodes.map((child, idx) => {
285
- if (child.type === "text") {
286
- let text = child.text;
287
- if (child.marks) {
288
- child.marks.forEach((mark) => {
289
- if (mark.type === "bold")
290
- text = /* @__PURE__ */ jsx2("strong", { children: text }, idx);
291
- if (mark.type === "italic")
292
- text = /* @__PURE__ */ jsx2("em", { children: text }, idx);
293
- if (mark.type === "link")
294
- text = /* @__PURE__ */ jsx2(
295
- Link,
296
- {
297
- href: mark.attrs?.href,
298
- className: classNames.link || "text-blue-600 underline",
299
- children: text
300
- },
301
- idx
302
- );
303
- });
304
- }
305
- return /* @__PURE__ */ jsx2("span", { children: text }, idx);
306
- }
307
- return null;
308
- }).filter(Boolean);
309
- }
310
-
311
- // src/components/blog-post/_components/table-of-contents.tsx
312
- import Image from "next/image";
313
-
314
- // src/components/blog-post/_helpers/extract-headings.ts
315
- function extractHeadings(content) {
316
- const headings = [];
317
- if (!content?.content)
318
- return headings;
319
- const walk = (nodes) => {
320
- for (const node of nodes) {
321
- if (node.type === "heading" && node.content?.[0]?.text) {
322
- const text = node.content[0].text;
323
- const slug = text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
324
- headings.push({ text, slug });
325
- }
326
- if (node.content)
327
- walk(node.content);
328
- }
329
- };
330
- walk(content.content);
331
- return headings;
332
- }
333
-
334
- // src/components/blog-post/_components/share.tsx
335
- import { Facebook, Linkedin, Mail, Twitter } from "lucide-react";
336
- import Link2 from "next/link";
337
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
338
- var Share = ({ post }) => {
339
- const postUrl = encodeURIComponent(`${opinlyConfig.blogUrl}/${post.slug}`);
340
- return /* @__PURE__ */ jsxs2("div", { className: "flex gap-2 mb-6", children: [
341
- /* @__PURE__ */ jsxs2(
342
- Link2,
343
- {
344
- href: `https://linkedin.com/sharing/share-offsite?url=${postUrl}`,
345
- target: "_blank",
346
- rel: "noopener noreferrer",
347
- className: "border p-1 rounded flex items-center justify-center w-8 h-8",
348
- children: [
349
- /* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Share on LinkedIn" }),
350
- /* @__PURE__ */ jsx3(Linkedin, { className: "w-4 h-4" })
351
- ]
352
- }
353
- ),
354
- /* @__PURE__ */ jsxs2(
355
- Link2,
356
- {
357
- href: `https://twitter.com/intent/tweet?url=${postUrl}&text=${encodeURIComponent(
358
- `Check out this article by ${post.author?.name}`
359
- )}`,
360
- target: "_blank",
361
- rel: "noopener noreferrer",
362
- className: "border p-1 rounded flex items-center justify-center w-8 h-8",
363
- children: [
364
- /* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Share on Twitter" }),
365
- /* @__PURE__ */ jsx3(Twitter, {})
366
- ]
367
- }
368
- ),
369
- /* @__PURE__ */ jsxs2(
370
- Link2,
371
- {
372
- href: `https://facebook.com/sharer/sharer.php?u=${postUrl}`,
373
- target: "_blank",
374
- rel: "noopener noreferrer",
375
- className: "border p-1 rounded flex items-center justify-center w-8 h-8",
376
- children: [
377
- /* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Share on Facebook" }),
378
- /* @__PURE__ */ jsx3(Facebook, {})
379
- ]
380
- }
381
- ),
382
- /* @__PURE__ */ jsxs2(
383
- Link2,
384
- {
385
- href: `mailto:?body=${encodeURIComponent(`${post.title}
386
- ${postUrl}`)}`,
387
- className: "border p-1 rounded flex items-center justify-center w-8 h-8",
388
- children: [
389
- /* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Share via Email" }),
390
- /* @__PURE__ */ jsx3(Mail, { className: "w-4 h-4" })
391
- ]
392
- }
393
- )
394
- ] });
395
- };
396
-
397
- // src/components/blog-post/_components/table-of-contents.tsx
398
- import Link3 from "next/link";
399
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
400
- var TableOfContents = ({
401
- content,
402
- author,
403
- post
404
- }) => {
405
- return /* @__PURE__ */ jsxs3("aside", { className: cn("w-full lg:w-1/3 lg:sticky lg:top-20 lg:self-start"), children: [
406
- author && /* @__PURE__ */ jsx4("div", { className: "w-full mb-6 border p-4 rounded-md text-sm", children: /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3 mb-3", children: [
407
- author.fileKey && /* @__PURE__ */ jsx4(
408
- Image,
409
- {
410
- src: `${opinlyConfig.imagesPrefix}/${replaceImageNameSpace(author.fileKey)}`,
411
- alt: author.name,
412
- width: 48,
413
- height: 48,
414
- className: "rounded-full"
415
- }
416
- ),
417
- /* @__PURE__ */ jsxs3("div", { children: [
418
- /* @__PURE__ */ jsx4(
419
- Link3,
420
- {
421
- href: `${opinlyConfig.blogPrefix}/authors/${author.slug}`,
422
- className: "text-xs uppercase text-muted-foreground font-medium",
423
- children: author.name
424
- }
425
- ),
426
- /* @__PURE__ */ jsx4("div", { className: "text-muted-foreground text-sm", children: author.bio })
427
- ] })
428
- ] }) }),
429
- /* @__PURE__ */ jsx4(Share, { post }),
430
- /* @__PURE__ */ jsxs3("div", { className: "border-l-4 border-opinlyAccent pl-4 mb-4", children: [
431
- /* @__PURE__ */ jsx4("h2", { className: "text-lg font-semibold mb-2", children: "TABLE OF CONTENTS" }),
432
- /* @__PURE__ */ jsx4("ul", { className: "text-sm text-gray-700 space-y-1", children: (extractHeadings(content) || []).map((heading) => /* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsx4("a", { href: `#${heading.slug}`, className: "hover:underline", children: heading.text }) }, heading.slug)) })
433
- ] })
434
- ] });
435
- };
436
-
437
- // src/components/bread-crumbs.tsx
438
- import Link4 from "next/link";
439
- import { Fragment } from "react";
440
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
441
- var BreadCrumbs = ({
442
- breadcrumbs
443
- }) => {
444
- return /* @__PURE__ */ jsx5("nav", { className: "text-sm text-orange-100 text-muted-foreground mb-4", children: /* @__PURE__ */ jsxs4("ol", { className: "list-reset flex space-x-2", children: [
445
- /* @__PURE__ */ jsx5(Link4, { href: "/", className: "font-bold", children: opinlyConfig.siteName }),
446
- /* @__PURE__ */ jsx5("span", { children: "/" }),
447
- /* @__PURE__ */ jsx5(Link4, { href: opinlyConfig.blogPrefix, className: "font-bold", children: "Blog" }),
448
- breadcrumbs?.map((breadcrumb, index) => {
449
- if (!breadcrumb) {
450
- return null;
451
- }
452
- return /* @__PURE__ */ jsxs4(Fragment, { children: [
453
- /* @__PURE__ */ jsx5("span", { children: "/" }),
454
- breadcrumb.url ? /* @__PURE__ */ jsx5(Link4, { href: breadcrumb.url, className: "font-bold", children: breadcrumb.name }) : /* @__PURE__ */ jsx5("span", { className: "font-bold", children: breadcrumb.name })
455
- ] }, index);
456
- })
457
- ] }) });
458
- };
459
-
460
- // src/utils/dates.ts
461
- var formatDate = (iso) => new Date(iso).toLocaleDateString("en-US", {
462
- month: "short",
463
- day: "2-digit",
464
- year: "numeric"
465
- });
466
-
467
- // src/components/blog-post/index.tsx
468
- import Script from "next/script";
469
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
470
- var BlogPost = ({
471
- post,
472
- classNames = {}
473
- }) => {
474
- const content = post.content;
475
- console.log("content", content);
476
- return /* @__PURE__ */ jsxs5(Fragment2, { children: [
477
- post.faqs && /* @__PURE__ */ jsx6(
478
- Script,
479
- {
480
- strategy: "beforeInteractive",
481
- type: "application/ld+json",
482
- dangerouslySetInnerHTML: {
483
- __html: JSON.stringify(genFaqJSONLD(post.faqs)).replace(
484
- /</g,
485
- "\\u003c"
486
- )
487
- }
488
- }
489
- ),
490
- /* @__PURE__ */ jsx6(
491
- Script,
492
- {
493
- strategy: "beforeInteractive",
494
- type: "application/ld+json",
495
- dangerouslySetInnerHTML: {
496
- __html: JSON.stringify(genBlogPostingJSONLD(post))
497
- }
498
- }
499
- ),
500
- /* @__PURE__ */ jsx6(
501
- Script,
502
- {
503
- strategy: "beforeInteractive",
504
- type: "application/ld+json",
505
- dangerouslySetInnerHTML: {
506
- __html: JSON.stringify(genBreadcrumbJSONLD(post))
507
- }
508
- }
509
- ),
510
- /* @__PURE__ */ jsx6("div", { className: "max-w-7xl mx-auto px-4 py-24 flex items-start space-x-8", children: /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-12 w-full", children: [
511
- /* @__PURE__ */ jsxs5("div", { className: "bg-orange-600", children: [
512
- /* @__PURE__ */ jsx6(
513
- BreadCrumbs,
514
- {
515
- breadcrumbs: [
516
- post.folder && {
517
- url: `${opinlyConfig.blogPrefix}/${post.folder.slug}`,
518
- name: post.folder.name
519
- }
520
- ]
521
- }
522
- ),
523
- /* @__PURE__ */ jsx6("h1", { className: "text-4xl font-bold mb-2 leading-tight", children: post.title }),
524
- /* @__PURE__ */ jsxs5("div", { className: "text-sm mb-4", children: [
525
- "Author:",
526
- " ",
527
- /* @__PURE__ */ jsx6(
528
- Link5,
529
- {
530
- href: `${opinlyConfig.blogPrefix}/authors/${post.author?.slug}`,
531
- className: "font-medium",
532
- children: post.author?.name
533
- }
534
- ),
535
- " ",
536
- "\xB7 ",
537
- calculateReadingTime(content),
538
- " min read \xB7",
539
- " ",
540
- formatDate(post.firstPublishedAt) || "Today"
541
- ] })
542
- ] }),
543
- /* @__PURE__ */ jsxs5(
544
- "div",
545
- {
546
- className: cn(
547
- "flex flex-col-reverse md:flex-row mx-auto mt-10 gap-12 relative w-full ",
548
- classNames.container
549
- ),
550
- children: [
551
- /* @__PURE__ */ jsx6("article", { className: "w-full lg:w-2/3 order-2 lg:order-1 flex items-start space-x-4", children: /* @__PURE__ */ jsxs5("div", { className: "prose w-full", children: [
552
- /* @__PURE__ */ jsx6(Content, { content, classNames }),
553
- /* @__PURE__ */ jsx6(FAQS, { faqs: post.faqs })
554
- ] }) }),
555
- /* @__PURE__ */ jsx6("div", { className: "block md:min-w-72 md:sticky md:top-20 md:self-start", children: /* @__PURE__ */ jsx6(
556
- TableOfContents,
557
- {
558
- content,
559
- author: post.author,
560
- post
561
- }
562
- ) })
563
- ]
564
- }
565
- )
566
- ] }) })
567
- ] });
568
- };
569
-
570
- // src/components/post-preview.tsx
571
- import Link6 from "next/link";
572
- import Image2 from "next/image";
573
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
574
- var PostPreview = ({
575
- post
576
- }) => {
577
- const postSlug = `${opinlyConfig.blogPrefix}/${post.folder?.slug ? `${post.folder.slug}/` : ""}${post.slug}`;
578
- return /* @__PURE__ */ jsxs6("div", { children: [
579
- post.image?.fileKey && /* @__PURE__ */ jsx7(Link6, { href: postSlug, className: "group", children: /* @__PURE__ */ jsx7("div", { className: "relative w-full h-48 mb-4", children: /* @__PURE__ */ jsx7(
580
- Image2,
581
- {
582
- src: `${opinlyConfig.imagesPrefix}/${replaceImageNameSpace(post.image.fileKey)}`,
583
- alt: post.title,
584
- fill: true,
585
- className: "object-cover rounded-lg"
586
- }
587
- ) }) }, post.slug),
588
- /* @__PURE__ */ jsxs6("div", { className: "text-sm text-muted-foreground mb-1", children: [
589
- post.folder?.name && /* @__PURE__ */ jsxs6(Fragment3, { children: [
590
- /* @__PURE__ */ jsx7(
591
- Link6,
592
- {
593
- href: `${opinlyConfig.blogPrefix}/${post.folder.slug}`,
594
- className: "hover:underline",
595
- children: post.folder.name
596
- }
597
- ),
598
- /* @__PURE__ */ jsx7("span", { className: "mx-1", children: "\xB7" })
599
- ] }),
600
- " ",
601
- formatDate(post.firstPublishedAt)
602
- ] }),
603
- /* @__PURE__ */ jsx7(Link6, { href: postSlug, className: "group", children: /* @__PURE__ */ jsx7("h2", { className: "text-lg font-semibold leading-snug group-hover:underline", children: post.title }) }, post.slug),
604
- post.description && /* @__PURE__ */ jsx7("p", { className: "text-sm text-gray-600 mt-1 line-clamp-2", children: post.description }),
605
- /* @__PURE__ */ jsxs6("div", { className: "text-xs text-gray-500 mt-2", children: [
606
- post.author && /* @__PURE__ */ jsxs6(Fragment3, { children: [
607
- /* @__PURE__ */ jsx7(
608
- Link6,
609
- {
610
- href: `${opinlyConfig.blogPrefix}/authors/${post.author.slug}`,
611
- className: "font-medium hover:underline",
612
- children: post.author?.name
613
- }
614
- ),
615
- " ",
616
- /* @__PURE__ */ jsx7("span", { className: "mx-1", children: "\xB7" })
617
- ] }),
618
- " ",
619
- formatDate(post.firstPublishedAt)
620
- ] })
621
- ] });
622
- };
623
-
624
- // src/components/folder-page/index.tsx
625
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
626
- var FolderPage = ({
627
- folder
628
- }) => {
629
- console.log("folder", JSON.stringify(folder, null, 2));
630
- return /* @__PURE__ */ jsxs7("div", { className: "max-w-6xl mx-auto px-4 py-10", children: [
631
- /* @__PURE__ */ jsx8(BreadCrumbs, {}),
632
- /* @__PURE__ */ jsx8("h1", { className: "text-4xl font-bold mb-2", children: folder.name }),
633
- /* @__PURE__ */ jsx8("p", { className: "text-muted-foreground max-w-2xl mb-8", children: folder.description || `Explore articles about ${folder.name}.` }),
634
- /* @__PURE__ */ jsxs7("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8", children: [
635
- folder.posts.length === 0 && /* @__PURE__ */ jsx8("div", { className: "text-muted-foreground", children: "No posts added yet" }),
636
- folder.posts.map((post) => {
637
- console.log("post.image", post.image);
638
- return /* @__PURE__ */ jsx8(PostPreview, { post }, post.slug);
639
- })
640
- ] })
641
- ] });
642
- };
643
-
644
- // src/components/home-page.tsx
645
- import Link7 from "next/link";
646
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
647
- var HomePage = ({
648
- homePage,
649
- page
650
- }) => {
651
- const { posts, folders, count } = homePage;
652
- console.log("posts", JSON.stringify(posts, null, 2));
653
- const currentPage = page;
654
- const totalPages = Math.ceil(count / 10);
655
- return /* @__PURE__ */ jsxs8("div", { className: "max-w-7xl mx-auto px-4 py-10", children: [
656
- /* @__PURE__ */ jsx9("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-10", children: posts.map((post) => /* @__PURE__ */ jsx9(PostPreview, { post }, post.slug)) }),
657
- /* @__PURE__ */ jsx9("div", { className: "flex justify-center items-center mt-10 gap-2", children: Array.from({ length: totalPages }, (_, i) => i + 1).map((p) => /* @__PURE__ */ jsx9(
658
- Link7,
659
- {
660
- href: `?page=${p}`,
661
- className: `px-3 py-1 border rounded ${p === currentPage ? "bg-black text-white" : "hover:bg-gray-100 text-gray-700"}`,
662
- children: p
663
- },
664
- p
665
- )) }),
666
- /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap gap-2 mb-10", children: folders.map((folder) => /* @__PURE__ */ jsx9(
667
- Link7,
668
- {
669
- href: `/blog/${folder.slug}`,
670
- className: "px-4 py-1 bg-gray-100 text-sm rounded-full hover:bg-gray-200",
671
- children: folder.title
672
- },
673
- folder.slug
674
- )) })
675
- ] });
676
- };
677
-
678
- // src/components/author-page/index.tsx
679
- import Image3 from "next/image";
680
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
681
- var AuthorPage = ({
682
- author
683
- }) => {
684
- return /* @__PURE__ */ jsxs9("div", { className: "max-w-5xl mx-auto px-4 py-10", children: [
685
- /* @__PURE__ */ jsx10(
686
- BreadCrumbs,
687
- {
688
- breadcrumbs: [
689
- {
690
- name: "Authors",
691
- url: `${opinlyConfig.blogPrefix}/authors`
692
- }
693
- ]
694
- }
695
- ),
696
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-6 mb-10", children: [
697
- author.image.fileKey && /* @__PURE__ */ jsx10(
698
- Image3,
699
- {
700
- src: `${opinlyConfig.imagesPrefix}/${replaceImageNameSpace(author.image.fileKey)}`,
701
- alt: author.image.alt || author.name,
702
- width: 150,
703
- height: 150,
704
- className: "rounded-full border"
705
- }
706
- ),
707
- /* @__PURE__ */ jsxs9("div", { children: [
708
- /* @__PURE__ */ jsx10("h1", { className: "text-3xl font-bold mb-1", children: author.name }),
709
- author.bio && /* @__PURE__ */ jsx10("p", { className: "text-muted-foreground text-base max-w-2xl", children: author.bio })
710
- ] })
711
- ] }),
712
- /* @__PURE__ */ jsxs9("h2", { className: "text-xl font-semibold mb-6", children: [
713
- "Posts by ",
714
- author.name
715
- ] }),
716
- /* @__PURE__ */ jsx10("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8", children: author.posts && author.posts.length > 0 ? author.posts.map(
717
- (post) => post && /* @__PURE__ */ jsx10(PostPreview, { post }, post.slug)
718
- ) : /* @__PURE__ */ jsx10("div", { className: "text-muted-foreground col-span-full", children: "No posts yet." }) })
719
- ] });
720
- };
721
-
722
- // src/components/not-found.tsx
723
- import Link8 from "next/link";
724
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
725
- var OpinlyNotFound = () => {
726
- return /* @__PURE__ */ jsxs10(Fragment4, { children: [
727
- /* @__PURE__ */ jsx11("div", { className: "bg-orange-600 py-10", children: /* @__PURE__ */ jsxs10("div", { className: "max-w-7xl mx-auto px-4", children: [
728
- /* @__PURE__ */ jsx11("h1", { className: "text-4xl font-bold mb-2 leading-tight text-white", children: "Post Not Found" }),
729
- /* @__PURE__ */ jsx11("div", { className: "text-sm mb-4 text-orange-100", children: "The post you're looking for doesn't exist or has been removed." })
730
- ] }) }),
731
- /* @__PURE__ */ jsx11("div", { className: "flex max-w-7xl mx-auto mt-10 gap-12", children: /* @__PURE__ */ jsx11("article", { className: "w-2/3", children: /* @__PURE__ */ jsxs10("div", { className: "prose max-w-none", children: [
732
- /* @__PURE__ */ jsx11("p", { className: "text-gray-600", children: "You can try:" }),
733
- /* @__PURE__ */ jsxs10("ul", { className: "list-disc pl-6 my-4", children: [
734
- /* @__PURE__ */ jsx11("li", { children: "Checking the URL for typos" }),
735
- /* @__PURE__ */ jsxs10("li", { children: [
736
- "Returning to the",
737
- " ",
738
- /* @__PURE__ */ jsx11(Link8, { href: "/blog", className: "text-blue-600 underline", children: "blog homepage" })
739
- ] }),
740
- /* @__PURE__ */ jsx11("li", { children: "Using the search function to find what you're looking for" })
741
- ] })
742
- ] }) }) })
743
- ] });
744
- };
745
-
746
- // src/components/authors-page/index.tsx
747
- import Image4 from "next/image";
748
- import Link9 from "next/link";
749
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
750
- var AuthorsPage = ({
751
- authors
752
- }) => {
753
- return /* @__PURE__ */ jsxs11("div", { className: "max-w-5xl mx-auto px-4 py-10", children: [
754
- /* @__PURE__ */ jsx12(
755
- BreadCrumbs,
756
- {
757
- breadcrumbs: [
758
- {
759
- name: "Authors"
760
- }
761
- ]
762
- }
763
- ),
764
- /* @__PURE__ */ jsx12("h1", { className: "text-3xl font-bold mb-10", children: "Authors" }),
765
- /* @__PURE__ */ jsx12("div", { className: "space-y-16", children: authors.map((author, idx) => {
766
- const authorSlug = `${opinlyConfig.blogPrefix}/authors/${author.slug}`;
767
- return /* @__PURE__ */ jsxs11(
768
- "div",
769
- {
770
- className: "rounded-lg p-6 flex flex-col gap-6",
771
- children: [
772
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-6 mb-4", children: [
773
- author.image?.fileKey && /* @__PURE__ */ jsx12(Link9, { href: authorSlug, children: /* @__PURE__ */ jsx12(
774
- Image4,
775
- {
776
- src: `${opinlyConfig.imagesPrefix}/${replaceImageNameSpace(author.image.fileKey)}`,
777
- alt: author.image.alt || author.name,
778
- width: 100,
779
- height: 100,
780
- className: "rounded-full border"
781
- }
782
- ) }),
783
- /* @__PURE__ */ jsxs11("div", { children: [
784
- /* @__PURE__ */ jsx12(Link9, { href: authorSlug, children: /* @__PURE__ */ jsx12("h2", { className: "text-2xl font-semibold mb-1", children: author.name }) }),
785
- author.bio && /* @__PURE__ */ jsx12("p", { className: "text-muted-foreground text-base max-w-2xl", children: author.bio })
786
- ] })
787
- ] }),
788
- /* @__PURE__ */ jsxs11("div", { children: [
789
- /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mb-4", children: author.posts && author.posts.length > 0 ? author.posts.map(
790
- (post) => post && /* @__PURE__ */ jsx12(PostPreview, { post }, post.slug)
791
- ) : /* @__PURE__ */ jsx12("div", { className: "text-muted-foreground col-span-full", children: "No posts yet." }) }),
792
- /* @__PURE__ */ jsx12("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs11(
793
- Link9,
794
- {
795
- href: `${opinlyConfig.blogPrefix}/authors/${author.slug}`,
796
- className: "text-bold",
797
- children: [
798
- "View more posts from ",
799
- author.name
800
- ]
801
- }
802
- ) })
803
- ] })
804
- ]
805
- },
806
- author.name + idx
807
- );
808
- }) })
809
- ] });
810
- };
811
-
812
- // src/components/opinly-blog.tsx
813
- import { jsx as jsx13 } from "react/jsx-runtime";
814
- var OpinlyBlog = ({
815
- blog,
816
- page
817
- }) => {
818
- if (blog.type === "not-found") {
819
- return /* @__PURE__ */ jsx13(OpinlyNotFound, {});
820
- }
821
- if (blog.type === "home") {
822
- return /* @__PURE__ */ jsx13(HomePage, { homePage: blog.data, page });
823
- }
824
- if (blog.type === "post") {
825
- return /* @__PURE__ */ jsx13(BlogPost, { post: blog.data });
826
- }
827
- if (blog.type === "author") {
828
- return /* @__PURE__ */ jsx13(AuthorPage, { author: blog.data });
829
- }
830
- if (blog.type === "authors") {
831
- return /* @__PURE__ */ jsx13(AuthorsPage, { authors: blog.data });
832
- }
833
- return /* @__PURE__ */ jsx13(FolderPage, { folder: blog.data });
834
- };
835
- export {
836
- HomePage,
837
- OpinlyBlog
838
- };