embed-dlsurf-blogs 1.0.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.
package/README.md ADDED
@@ -0,0 +1,232 @@
1
+ # `embed-dlsurf-blogs`
2
+
3
+ Render dlsurf blog documents as a polished React component with TOC, sharing UI, and SSR-safe Tiptap JSON -> HTML rendering.
4
+
5
+ ## 1. Fetch Document Data First
6
+
7
+ Before rendering, fetch the blog document from:
8
+
9
+ `https://docapi.dl.surf/api/doc/{user}/{linkSlug}`
10
+
11
+ Example:
12
+
13
+ ```txt
14
+ https://docapi.dl.surf/api/doc/rishav/why-django-is-a-game-changer-in-modern-web-development
15
+ ```
16
+
17
+ Response format:
18
+
19
+ ```json
20
+ {
21
+ "status": "success",
22
+ "message": "Document retrieved successfully",
23
+ "data": {
24
+ "id": 1252,
25
+ "title": "Why Django is a Game-Changer in Modern Web Development",
26
+ "content_json": "{\"type\":\"doc\",\"content\":[...]}",
27
+ "thumbnail_path": "thumbnails/3e3ded2a-0.png",
28
+ "keywords": "[\"Django web framework\",\"Python Django framework\"]",
29
+ "followers_only": false,
30
+ "visibility": "public",
31
+ "created_at": "2025-12-23T05:59:12.432707Z",
32
+ "link_slug": "why-django-is-a-game-changer-in-modern-web-development",
33
+ "updated_at": "2025-12-23T06:17:28.878387Z",
34
+ "profile": {
35
+ "username": "rishav",
36
+ "display_name": "Rishav Dahal",
37
+ "account_level": "6",
38
+ "profile_picture": "/media/profile_picture/a609d8df22.JPG"
39
+ },
40
+ "ads_step": 1,
41
+ "banner_ads": false,
42
+ "video_ads": false
43
+ }
44
+ }
45
+ ```
46
+
47
+ Pass `response.data` directly to the component.
48
+
49
+ ## 2. Pre-requirements
50
+
51
+ - `node >= 18`
52
+ - React app (`react >= 18`)
53
+ - TypeScript recommended
54
+
55
+ Library peer dependencies:
56
+
57
+ - `react`
58
+ - `@tiptap/core`
59
+
60
+ ## 3. Install
61
+
62
+ ```bash
63
+ npm install embed-dlsurf-blogs @tiptap/core
64
+ ```
65
+
66
+ or
67
+
68
+ ```bash
69
+ yarn add embed-dlsurf-blogs @tiptap/core
70
+ ```
71
+
72
+ or
73
+
74
+ ```bash
75
+ pnpm add embed-dlsurf-blogs @tiptap/core
76
+ ```
77
+
78
+ ## 4. Component Usage Patterns
79
+
80
+ ### Basic Usage (Client Component)
81
+
82
+ ```tsx
83
+ "use client";
84
+
85
+ import { useEffect, useState } from "react";
86
+ import BlogRenderer from "embed-dlsurf-blogs";
87
+
88
+ type DocApiResponse = {
89
+ status: string;
90
+ message: string;
91
+ data: BlogPost;
92
+ };
93
+
94
+ type BlogPostProfile = {
95
+ username: string;
96
+ display_name: string;
97
+ account_level: string;
98
+ profile_picture: string;
99
+ };
100
+
101
+ type BlogPost = {
102
+ id: number;
103
+ title: string;
104
+ content_json: string;
105
+ thumbnail_path: string | null;
106
+ keywords: string;
107
+ followers_only: boolean;
108
+ visibility: string;
109
+ created_at: string;
110
+ link_slug: string;
111
+ updated_at: string;
112
+ profile: BlogPostProfile;
113
+ ads_step: number;
114
+ banner_ads: boolean;
115
+ video_ads: boolean;
116
+ };
117
+
118
+ export default function BlogPage() {
119
+ const [post, setPost] = useState<BlogPost | null>(null);
120
+ const [error, setError] = useState<string | null>(null);
121
+
122
+ useEffect(() => {
123
+ const run = async () => {
124
+ try {
125
+ const res = await fetch(
126
+ "https://docapi.dl.surf/api/doc/rishav/why-django-is-a-game-changer-in-modern-web-development",
127
+ );
128
+ if (!res.ok) throw new Error(`Request failed: ${res.status}`);
129
+
130
+ const json: DocApiResponse = await res.json();
131
+ setPost(json.data);
132
+ } catch (e) {
133
+ setError(e instanceof Error ? e.message : "Unknown error");
134
+ }
135
+ };
136
+
137
+ run();
138
+ }, []);
139
+
140
+ if (error) return <p>{error}</p>;
141
+ if (!post) return <p>Loading...</p>;
142
+
143
+ return <BlogRenderer post={post} />;
144
+ }
145
+ ```
146
+
147
+ ### Named Import Usage
148
+
149
+ ```tsx
150
+ import { BlogRenderer } from "embed-dlsurf-blogs";
151
+
152
+ export function MyBlogView({ post }: { post: BlogPost }) {
153
+ return <BlogRenderer post={post} />;
154
+ }
155
+ ```
156
+
157
+ ### Next.js Server Component Pattern
158
+
159
+ ```tsx
160
+ import BlogRenderer from "embed-dlsurf-blogs";
161
+
162
+ type Params = { user: string; slug: string };
163
+
164
+ export default async function Page({ params }: { params: Promise<Params> }) {
165
+ const { user, slug } = await params;
166
+ const res = await fetch(`https://docapi.dl.surf/api/doc/${user}/${slug}`, {
167
+ next: { revalidate: 60 },
168
+ });
169
+
170
+ if (!res.ok) return <div>Not found</div>;
171
+
172
+ const json = await res.json();
173
+ return <BlogRenderer post={json.data} />;
174
+ }
175
+ ```
176
+
177
+ ## 5. Types
178
+
179
+ The component expects this shape for the `post` prop:
180
+
181
+ ```ts
182
+ type BlogPostProfile = {
183
+ username: string;
184
+ display_name: string;
185
+ account_level: string;
186
+ profile_picture: string;
187
+ };
188
+
189
+ type BlogPost = {
190
+ id: number;
191
+ title: string;
192
+ content_json: string;
193
+ thumbnail_path: string | null;
194
+ keywords: string;
195
+ followers_only: boolean;
196
+ visibility: string;
197
+ created_at: string;
198
+ link_slug: string;
199
+ updated_at: string;
200
+ profile: BlogPostProfile;
201
+ ads_step: number;
202
+ banner_ads: boolean;
203
+ video_ads: boolean;
204
+ };
205
+ ```
206
+
207
+ ## 6. What The Component Does Internally
208
+
209
+ - Parses `post.content_json` using an SSR-safe renderer.
210
+ - Strips outer `prose` wrappers from generated HTML.
211
+ - Builds an auto Table of Contents from `h2`/`h3` headings.
212
+ - Handles image URL normalization for `thumbnail_path`.
213
+ - Injects scoped component styles during build (`injectStyle: true`).
214
+
215
+
216
+ ## 7. API Utilities Exported
217
+
218
+ From this package:
219
+
220
+ - `default` -> `BlogRenderer`
221
+ - `{ BlogRenderer }`
222
+ - `{ renderText }` (utility test export)
223
+
224
+ ## 8. Troubleshooting
225
+
226
+ - If content is empty, check that `data.content_json` is a valid Tiptap JSON string.
227
+ - If the API call fails, verify `user` and `linkSlug` values in the URL.
228
+ - If you use strict CSP, confirm style injection rules allow runtime-injected styles.
229
+
230
+ ## 9. License
231
+
232
+ ISC
package/dist/index.css ADDED
@@ -0,0 +1,342 @@
1
+ /* src/SingleBlogClient.css */
2
+ .edlsb-wrapper {
3
+ background-color: #f8fafc;
4
+ min-height: 100vh;
5
+ }
6
+ .edlsb-progressBar {
7
+ position: fixed;
8
+ top: 0;
9
+ left: 0;
10
+ right: 0;
11
+ height: 4px;
12
+ background-color: #4f46e5;
13
+ transform-origin: left center;
14
+ z-index: 100;
15
+ }
16
+ .edlsb-main {
17
+ position: relative;
18
+ }
19
+ .edlsb-headerSection {
20
+ padding-top: 8rem;
21
+ padding-bottom: 5rem;
22
+ position: relative;
23
+ overflow: hidden;
24
+ }
25
+ .edlsb-headerContainer {
26
+ width: 100%;
27
+ max-width: 56rem;
28
+ margin: 0 auto;
29
+ padding-left: 1.5rem;
30
+ padding-right: 1.5rem;
31
+ position: relative;
32
+ z-index: 10;
33
+ }
34
+ .edlsb-headerContent {
35
+ text-align: center;
36
+ }
37
+ .edlsb-headerContent > * + * {
38
+ margin-top: 2rem;
39
+ }
40
+ @media (min-width: 768px) {
41
+ .edlsb-headerContent {
42
+ text-align: left;
43
+ }
44
+ }
45
+ .edlsb-metaRow {
46
+ display: flex;
47
+ flex-wrap: wrap;
48
+ align-items: center;
49
+ gap: 1rem;
50
+ color: #94a3b8;
51
+ font-weight: 700;
52
+ font-size: 0.75rem;
53
+ line-height: 1rem;
54
+ text-transform: uppercase;
55
+ letter-spacing: 0.1em;
56
+ justify-content: center;
57
+ }
58
+ @media (min-width: 768px) {
59
+ .edlsb-metaRow {
60
+ justify-content: flex-start;
61
+ }
62
+ }
63
+ .edlsb-articleBadge {
64
+ padding: 0.25rem 0.75rem;
65
+ background-color: #ffffff;
66
+ border-radius: 0.5rem;
67
+ border: 1px solid #e2e8f0;
68
+ color: #4f46e5;
69
+ }
70
+ .edlsb-dot {
71
+ width: 0.25rem;
72
+ height: 0.25rem;
73
+ background-color: #cbd5e1;
74
+ border-radius: 9999px;
75
+ }
76
+ .edlsb-metaItem {
77
+ display: flex;
78
+ align-items: center;
79
+ gap: 0.5rem;
80
+ }
81
+ .edlsb-icon {
82
+ width: 1rem;
83
+ height: 1rem;
84
+ }
85
+ .edlsb-postTitle {
86
+ font-size: 2.25rem;
87
+ line-height: 0.95;
88
+ font-weight: 1000;
89
+ color: #0f172a;
90
+ letter-spacing: -0.04em;
91
+ }
92
+ @media (min-width: 768px) {
93
+ .edlsb-postTitle {
94
+ font-size: 3.75rem;
95
+ }
96
+ }
97
+ @media (min-width: 1024px) {
98
+ .edlsb-postTitle {
99
+ font-size: 4.5rem;
100
+ }
101
+ }
102
+ .edlsb-bodyContainer {
103
+ width: 100%;
104
+ max-width: 56rem;
105
+ margin: 0 auto;
106
+ padding-left: 1.5rem;
107
+ padding-right: 1.5rem;
108
+ padding-top: 5rem;
109
+ padding-bottom: 5rem;
110
+ }
111
+ .edlsb-thumbnailWrapper {
112
+ margin-bottom: 2rem;
113
+ border-radius: 1rem;
114
+ overflow: hidden;
115
+ box-shadow: 0 25px 50px -12px rgb(49 46 129 / 0.1);
116
+ margin-top: -8rem;
117
+ position: relative;
118
+ z-index: 20;
119
+ }
120
+ .edlsb-thumbnail {
121
+ width: 100%;
122
+ height: auto;
123
+ object-fit: cover;
124
+ max-height: 600px;
125
+ }
126
+ .edlsb-tocWrapper {
127
+ margin-bottom: 2.5rem;
128
+ }
129
+ .edlsb-tocToggle {
130
+ width: 100%;
131
+ display: flex;
132
+ align-items: center;
133
+ justify-content: space-between;
134
+ gap: 0.75rem;
135
+ padding: 1rem 1.25rem;
136
+ border-radius: 1rem;
137
+ background-color: rgba(241, 245, 249, 0.8);
138
+ border: none;
139
+ cursor: pointer;
140
+ transition-property: all;
141
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
142
+ transition-duration: 150ms;
143
+ }
144
+ .edlsb-tocToggle:hover {
145
+ background-color: #f1f5f9;
146
+ }
147
+ .edlsb-tocToggle:hover .tocIconWrap {
148
+ color: #334155;
149
+ }
150
+ .edlsb-tocToggleInner {
151
+ display: flex;
152
+ align-items: center;
153
+ gap: 0.75rem;
154
+ }
155
+ .edlsb-tocIconWrap {
156
+ display: flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ width: 1.75rem;
160
+ height: 1.75rem;
161
+ border-radius: 0.5rem;
162
+ background-color: rgba(226, 232, 240, 0.8);
163
+ color: #64748b;
164
+ transition-property: color;
165
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
166
+ transition-duration: 150ms;
167
+ }
168
+ .edlsb-tocLabel {
169
+ font-size: 13px;
170
+ font-weight: 600;
171
+ color: #475569;
172
+ }
173
+ .edlsb-tocCount {
174
+ color: #94a3b8;
175
+ font-weight: 400;
176
+ margin-left: 0.25rem;
177
+ }
178
+ .edlsb-chevronIcon {
179
+ width: 1rem;
180
+ height: 1rem;
181
+ color: #94a3b8;
182
+ transition-property: transform;
183
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
184
+ transition-duration: 200ms;
185
+ }
186
+ .edlsb-chevronIconOpen {
187
+ transform: rotate(180deg);
188
+ }
189
+ .edlsb-tocPanelInner {
190
+ margin-top: 0.375rem;
191
+ border-radius: 1rem;
192
+ background-color: rgba(241, 245, 249, 0.8);
193
+ padding: 0.5rem;
194
+ }
195
+ .edlsb-tocGrid {
196
+ display: grid;
197
+ grid-template-columns: 1fr;
198
+ gap: 0.125rem;
199
+ }
200
+ @media (min-width: 640px) {
201
+ .edlsb-tocGrid {
202
+ grid-template-columns: repeat(2, minmax(0, 1fr));
203
+ }
204
+ }
205
+ .edlsb-tocItem {
206
+ display: flex;
207
+ align-items: center;
208
+ gap: 0.625rem;
209
+ text-align: left;
210
+ border-radius: 0.75rem;
211
+ padding: 0.625rem 0.75rem;
212
+ font-size: 13px;
213
+ border: none;
214
+ cursor: pointer;
215
+ background-color: transparent;
216
+ color: #475569;
217
+ transition-property: all;
218
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
219
+ transition-duration: 150ms;
220
+ }
221
+ .edlsb-tocItem:hover {
222
+ background-color: #ffffff;
223
+ color: #0f172a;
224
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
225
+ }
226
+ .edlsb-tocItemActive {
227
+ background-color: #0f172a;
228
+ color: #ffffff;
229
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
230
+ }
231
+ .edlsb-tocItemActive:hover {
232
+ background-color: #0f172a;
233
+ color: #ffffff;
234
+ }
235
+ .edlsb-tocItemLevel3 {
236
+ padding-left: 2rem;
237
+ }
238
+ .edlsb-tocBadge {
239
+ flex-shrink: 0;
240
+ width: 1.25rem;
241
+ height: 1.25rem;
242
+ border-radius: 0.375rem;
243
+ font-size: 10px;
244
+ font-weight: 700;
245
+ display: flex;
246
+ align-items: center;
247
+ justify-content: center;
248
+ background-color: rgba(226, 232, 240, 0.8);
249
+ color: #94a3b8;
250
+ }
251
+ .edlsb-tocBadgeActive {
252
+ background-color: rgba(255, 255, 255, 0.15);
253
+ color: rgba(255, 255, 255, 0.8);
254
+ }
255
+ .edlsb-tocItemText {
256
+ overflow: hidden;
257
+ text-overflow: ellipsis;
258
+ white-space: nowrap;
259
+ }
260
+ .edlsb-shareSection {
261
+ margin-top: 3.5rem;
262
+ border-top: 1px solid #e2e8f0;
263
+ padding-top: 1.5rem;
264
+ }
265
+ .edlsb-shareInner {
266
+ display: flex;
267
+ flex-direction: column;
268
+ gap: 1rem;
269
+ }
270
+ @media (min-width: 640px) {
271
+ .edlsb-shareInner {
272
+ flex-direction: row;
273
+ align-items: center;
274
+ justify-content: space-between;
275
+ }
276
+ }
277
+ .edlsb-shareTitle {
278
+ font-size: 1rem;
279
+ line-height: 1.5rem;
280
+ font-weight: 600;
281
+ color: #0f172a;
282
+ }
283
+ .edlsb-shareSubtitle {
284
+ font-size: 0.875rem;
285
+ line-height: 1.25rem;
286
+ color: #64748b;
287
+ }
288
+ .edlsb-shareButtons {
289
+ display: flex;
290
+ align-items: center;
291
+ gap: 0.625rem;
292
+ }
293
+ .edlsb-shareBtn {
294
+ height: 2.5rem;
295
+ padding-left: 1rem;
296
+ padding-right: 1rem;
297
+ border-radius: 9999px;
298
+ border: 1px solid #e2e8f0;
299
+ background-color: #ffffff;
300
+ color: #334155;
301
+ font-size: 0.875rem;
302
+ font-weight: 600;
303
+ cursor: pointer;
304
+ transition-property:
305
+ color,
306
+ background-color,
307
+ border-color;
308
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
309
+ transition-duration: 150ms;
310
+ }
311
+ .edlsb-shareBtn:hover {
312
+ border-color: #cbd5e1;
313
+ color: #0f172a;
314
+ }
315
+ .edlsb-shareBtnInner {
316
+ display: inline-flex;
317
+ align-items: center;
318
+ gap: 0.5rem;
319
+ }
320
+ .edlsb-copyBtn {
321
+ height: 2.5rem;
322
+ width: 2.5rem;
323
+ border-radius: 9999px;
324
+ border: 1px solid #e2e8f0;
325
+ background-color: #ffffff;
326
+ color: #475569;
327
+ cursor: pointer;
328
+ display: inline-flex;
329
+ align-items: center;
330
+ justify-content: center;
331
+ transition-property:
332
+ color,
333
+ background-color,
334
+ border-color;
335
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
336
+ transition-duration: 150ms;
337
+ }
338
+ .edlsb-copyBtn:hover {
339
+ border-color: #cbd5e1;
340
+ color: #0f172a;
341
+ }
342
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/SingleBlogClient.css"],"sourcesContent":["/* SingleBlogClient.module.css */\n\n.edlsb-wrapper {\n background-color: #f8fafc;\n min-height: 100vh;\n}\n\n.edlsb-progressBar {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 4px;\n background-color: #4f46e5;\n transform-origin: left center;\n z-index: 100;\n}\n\n.edlsb-main {\n position: relative;\n}\n\n.edlsb-headerSection {\n padding-top: 8rem;\n padding-bottom: 5rem;\n position: relative;\n overflow: hidden;\n}\n\n.edlsb-headerContainer {\n width: 100%;\n max-width: 56rem;\n margin: 0 auto;\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n position: relative;\n z-index: 10;\n}\n\n.edlsb-headerContent {\n text-align: center;\n}\n\n.edlsb-headerContent > * + * {\n margin-top: 2rem;\n}\n\n@media (min-width: 768px) {\n .edlsb-headerContent {\n text-align: left;\n }\n}\n\n.edlsb-metaRow {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 1rem;\n color: #94a3b8;\n font-weight: 700;\n font-size: 0.75rem;\n line-height: 1rem;\n text-transform: uppercase;\n letter-spacing: 0.1em;\n justify-content: center;\n}\n\n@media (min-width: 768px) {\n .edlsb-metaRow {\n justify-content: flex-start;\n }\n}\n\n.edlsb-articleBadge {\n padding: 0.25rem 0.75rem;\n background-color: #ffffff;\n border-radius: 0.5rem;\n border: 1px solid #e2e8f0;\n color: #4f46e5;\n}\n\n.edlsb-dot {\n width: 0.25rem;\n height: 0.25rem;\n background-color: #cbd5e1;\n border-radius: 9999px;\n}\n\n.edlsb-metaItem {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.edlsb-icon {\n width: 1rem;\n height: 1rem;\n}\n\n.edlsb-postTitle {\n font-size: 2.25rem;\n line-height: 0.95;\n font-weight: 1000;\n color: #0f172a;\n letter-spacing: -0.04em;\n}\n\n@media (min-width: 768px) {\n .edlsb-postTitle {\n font-size: 3.75rem;\n }\n}\n\n@media (min-width: 1024px) {\n .edlsb-postTitle {\n font-size: 4.5rem;\n }\n}\n\n.edlsb-bodyContainer {\n width: 100%;\n max-width: 56rem;\n margin: 0 auto;\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n padding-top: 5rem;\n padding-bottom: 5rem;\n}\n\n.edlsb-thumbnailWrapper {\n margin-bottom: 2rem;\n border-radius: 1rem;\n overflow: hidden;\n box-shadow: 0 25px 50px -12px rgb(49 46 129 / 0.1);\n margin-top: -8rem;\n position: relative;\n z-index: 20;\n}\n\n.edlsb-thumbnail {\n width: 100%;\n height: auto;\n object-fit: cover;\n max-height: 600px;\n}\n\n.edlsb-tocWrapper {\n margin-bottom: 2.5rem;\n}\n\n.edlsb-tocToggle {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n padding: 1rem 1.25rem;\n border-radius: 1rem;\n background-color: rgba(241, 245, 249, 0.8);\n border: none;\n cursor: pointer;\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.edlsb-tocToggle:hover {\n background-color: #f1f5f9;\n}\n\n.edlsb-tocToggle:hover .tocIconWrap {\n color: #334155;\n}\n\n.edlsb-tocToggleInner {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.edlsb-tocIconWrap {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 0.5rem;\n background-color: rgba(226, 232, 240, 0.8);\n color: #64748b;\n transition-property: color;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.edlsb-tocLabel {\n font-size: 13px;\n font-weight: 600;\n color: #475569;\n}\n\n.edlsb-tocCount {\n color: #94a3b8;\n font-weight: 400;\n margin-left: 0.25rem;\n}\n\n.edlsb-chevronIcon {\n width: 1rem;\n height: 1rem;\n color: #94a3b8;\n transition-property: transform;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 200ms;\n}\n\n.edlsb-chevronIconOpen {\n transform: rotate(180deg);\n}\n\n.edlsb-tocPanelInner {\n margin-top: 0.375rem;\n border-radius: 1rem;\n background-color: rgba(241, 245, 249, 0.8);\n padding: 0.5rem;\n}\n\n.edlsb-tocGrid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 0.125rem;\n}\n\n@media (min-width: 640px) {\n .edlsb-tocGrid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n}\n\n.edlsb-tocItem {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n text-align: left;\n border-radius: 0.75rem;\n padding: 0.625rem 0.75rem;\n font-size: 13px;\n border: none;\n cursor: pointer;\n background-color: transparent;\n color: #475569;\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.edlsb-tocItem:hover {\n background-color: #ffffff;\n color: #0f172a;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.edlsb-tocItemActive {\n background-color: #0f172a;\n color: #ffffff;\n box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n}\n\n.edlsb-tocItemActive:hover {\n background-color: #0f172a;\n color: #ffffff;\n}\n\n.edlsb-tocItemLevel3 {\n padding-left: 2rem;\n}\n\n.edlsb-tocBadge {\n flex-shrink: 0;\n width: 1.25rem;\n height: 1.25rem;\n border-radius: 0.375rem;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: rgba(226, 232, 240, 0.8);\n color: #94a3b8;\n}\n\n.edlsb-tocBadgeActive {\n background-color: rgba(255, 255, 255, 0.15);\n color: rgba(255, 255, 255, 0.8);\n}\n\n.edlsb-tocItemText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.edlsb-shareSection {\n margin-top: 3.5rem;\n border-top: 1px solid #e2e8f0;\n padding-top: 1.5rem;\n}\n\n.edlsb-shareInner {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n@media (min-width: 640px) {\n .edlsb-shareInner {\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n }\n}\n\n.edlsb-shareTitle {\n font-size: 1rem;\n line-height: 1.5rem;\n font-weight: 600;\n color: #0f172a;\n}\n\n.edlsb-shareSubtitle {\n font-size: 0.875rem;\n line-height: 1.25rem;\n color: #64748b;\n}\n\n.edlsb-shareButtons {\n display: flex;\n align-items: center;\n gap: 0.625rem;\n}\n\n.edlsb-shareBtn {\n height: 2.5rem;\n padding-left: 1rem;\n padding-right: 1rem;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background-color: #ffffff;\n color: #334155;\n font-size: 0.875rem;\n font-weight: 600;\n cursor: pointer;\n transition-property: color, background-color, border-color;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.edlsb-shareBtn:hover {\n border-color: #cbd5e1;\n color: #0f172a;\n}\n\n.edlsb-shareBtnInner {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.edlsb-copyBtn {\n height: 2.5rem;\n width: 2.5rem;\n border-radius: 9999px;\n border: 1px solid #e2e8f0;\n background-color: #ffffff;\n color: #475569;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition-property: color, background-color, border-color;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n\n.edlsb-copyBtn:hover {\n border-color: #cbd5e1;\n color: #0f172a;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,33 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ export { JSONContent } from '@tiptap/core';
3
+
4
+ interface SingleBlogClientProps {
5
+ post: BlogPost;
6
+ }
7
+ interface BlogPostProfile {
8
+ username: string;
9
+ display_name: string;
10
+ account_level: string;
11
+ profile_picture: string;
12
+ }
13
+ interface BlogPost {
14
+ id: number;
15
+ title: string;
16
+ content_json: string;
17
+ thumbnail_path: string | null;
18
+ keywords: string;
19
+ followers_only: boolean;
20
+ visibility: string;
21
+ created_at: string;
22
+ link_slug: string;
23
+ updated_at: string;
24
+ profile: BlogPostProfile;
25
+ ads_step: number;
26
+ banner_ads: boolean;
27
+ video_ads: boolean;
28
+ }
29
+ declare function BlogRenderer({ post }: SingleBlogClientProps): react_jsx_runtime.JSX.Element;
30
+
31
+ declare function renderText(): string;
32
+
33
+ export { BlogRenderer, BlogRenderer as default, renderText };
@@ -0,0 +1,33 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ export { JSONContent } from '@tiptap/core';
3
+
4
+ interface SingleBlogClientProps {
5
+ post: BlogPost;
6
+ }
7
+ interface BlogPostProfile {
8
+ username: string;
9
+ display_name: string;
10
+ account_level: string;
11
+ profile_picture: string;
12
+ }
13
+ interface BlogPost {
14
+ id: number;
15
+ title: string;
16
+ content_json: string;
17
+ thumbnail_path: string | null;
18
+ keywords: string;
19
+ followers_only: boolean;
20
+ visibility: string;
21
+ created_at: string;
22
+ link_slug: string;
23
+ updated_at: string;
24
+ profile: BlogPostProfile;
25
+ ads_step: number;
26
+ banner_ads: boolean;
27
+ video_ads: boolean;
28
+ }
29
+ declare function BlogRenderer({ post }: SingleBlogClientProps): react_jsx_runtime.JSX.Element;
30
+
31
+ declare function renderText(): string;
32
+
33
+ export { BlogRenderer, BlogRenderer as default, renderText };