nextblogkit 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +951 -0
  3. package/dist/admin/index.cjs +2465 -0
  4. package/dist/admin/index.cjs.map +1 -0
  5. package/dist/admin/index.d.cts +44 -0
  6. package/dist/admin/index.d.ts +44 -0
  7. package/dist/admin/index.js +2438 -0
  8. package/dist/admin/index.js.map +1 -0
  9. package/dist/api/categories.cjs +82 -0
  10. package/dist/api/categories.cjs.map +1 -0
  11. package/dist/api/categories.d.cts +27 -0
  12. package/dist/api/categories.d.ts +27 -0
  13. package/dist/api/categories.js +77 -0
  14. package/dist/api/categories.js.map +1 -0
  15. package/dist/api/media.cjs +113 -0
  16. package/dist/api/media.cjs.map +1 -0
  17. package/dist/api/media.d.cts +22 -0
  18. package/dist/api/media.d.ts +22 -0
  19. package/dist/api/media.js +109 -0
  20. package/dist/api/media.js.map +1 -0
  21. package/dist/api/posts.cjs +103 -0
  22. package/dist/api/posts.cjs.map +1 -0
  23. package/dist/api/posts.d.cts +27 -0
  24. package/dist/api/posts.d.ts +27 -0
  25. package/dist/api/posts.js +98 -0
  26. package/dist/api/posts.js.map +1 -0
  27. package/dist/api/rss.cjs +25 -0
  28. package/dist/api/rss.cjs.map +1 -0
  29. package/dist/api/rss.d.cts +5 -0
  30. package/dist/api/rss.d.ts +5 -0
  31. package/dist/api/rss.js +23 -0
  32. package/dist/api/rss.js.map +1 -0
  33. package/dist/api/settings.cjs +40 -0
  34. package/dist/api/settings.cjs.map +1 -0
  35. package/dist/api/settings.d.cts +17 -0
  36. package/dist/api/settings.d.ts +17 -0
  37. package/dist/api/settings.js +37 -0
  38. package/dist/api/settings.js.map +1 -0
  39. package/dist/api/sitemap.cjs +25 -0
  40. package/dist/api/sitemap.cjs.map +1 -0
  41. package/dist/api/sitemap.d.cts +5 -0
  42. package/dist/api/sitemap.d.ts +5 -0
  43. package/dist/api/sitemap.js +23 -0
  44. package/dist/api/sitemap.js.map +1 -0
  45. package/dist/chunk-4NKOJYWJ.js +68 -0
  46. package/dist/chunk-4NKOJYWJ.js.map +1 -0
  47. package/dist/chunk-4PY224XM.js +103 -0
  48. package/dist/chunk-4PY224XM.js.map +1 -0
  49. package/dist/chunk-64HUVJOZ.js +446 -0
  50. package/dist/chunk-64HUVJOZ.js.map +1 -0
  51. package/dist/chunk-6HKMZOI4.cjs +48 -0
  52. package/dist/chunk-6HKMZOI4.cjs.map +1 -0
  53. package/dist/chunk-A2S32RZN.js +138 -0
  54. package/dist/chunk-A2S32RZN.js.map +1 -0
  55. package/dist/chunk-E2QLTHKN.cjs +70 -0
  56. package/dist/chunk-E2QLTHKN.cjs.map +1 -0
  57. package/dist/chunk-JLPJKNRZ.js +37 -0
  58. package/dist/chunk-JLPJKNRZ.js.map +1 -0
  59. package/dist/chunk-JM7QRXXK.js +330 -0
  60. package/dist/chunk-JM7QRXXK.js.map +1 -0
  61. package/dist/chunk-KDZER3PU.cjs +43 -0
  62. package/dist/chunk-KDZER3PU.cjs.map +1 -0
  63. package/dist/chunk-N5MKAD7J.cjs +109 -0
  64. package/dist/chunk-N5MKAD7J.cjs.map +1 -0
  65. package/dist/chunk-QE4VLQYN.cjs +337 -0
  66. package/dist/chunk-QE4VLQYN.cjs.map +1 -0
  67. package/dist/chunk-R6MO3QIP.js +46 -0
  68. package/dist/chunk-R6MO3QIP.js.map +1 -0
  69. package/dist/chunk-U2ROR6AY.cjs +476 -0
  70. package/dist/chunk-U2ROR6AY.cjs.map +1 -0
  71. package/dist/chunk-ZP5XRVVH.cjs +141 -0
  72. package/dist/chunk-ZP5XRVVH.cjs.map +1 -0
  73. package/dist/cli/index.cjs +1308 -0
  74. package/dist/components/index.cjs +541 -0
  75. package/dist/components/index.cjs.map +1 -0
  76. package/dist/components/index.d.cts +165 -0
  77. package/dist/components/index.d.ts +165 -0
  78. package/dist/components/index.js +527 -0
  79. package/dist/components/index.js.map +1 -0
  80. package/dist/editor/index.cjs +1083 -0
  81. package/dist/editor/index.cjs.map +1 -0
  82. package/dist/editor/index.d.cts +133 -0
  83. package/dist/editor/index.d.ts +133 -0
  84. package/dist/editor/index.js +1051 -0
  85. package/dist/editor/index.js.map +1 -0
  86. package/dist/index-Cgzphklp.d.ts +266 -0
  87. package/dist/index-vjlZDWNr.d.cts +266 -0
  88. package/dist/index.cjs +368 -0
  89. package/dist/index.cjs.map +1 -0
  90. package/dist/index.d.cts +27 -0
  91. package/dist/index.d.ts +27 -0
  92. package/dist/index.js +208 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/lib/index.cjs +120 -0
  95. package/dist/lib/index.cjs.map +1 -0
  96. package/dist/lib/index.d.cts +4 -0
  97. package/dist/lib/index.d.ts +4 -0
  98. package/dist/lib/index.js +7 -0
  99. package/dist/lib/index.js.map +1 -0
  100. package/dist/styles/admin.css +657 -0
  101. package/dist/styles/blog.css +851 -0
  102. package/dist/styles/editor.css +452 -0
  103. package/dist/styles/globals.css +270 -0
  104. package/dist/styles/prose.css +299 -0
  105. package/dist/types-CBEEBR4A.d.cts +732 -0
  106. package/dist/types-CBEEBR4A.d.ts +732 -0
  107. package/package.json +134 -0
@@ -0,0 +1,266 @@
1
+ import { N as NextBlogKitConfig, d as BlockType, e as BlogPost, M as Media, g as CreateCategoryInput, C as Category, h as CreatePostInput, f as BlogSettings, i as MediaListQuery, P as PostListQuery, U as UpdateCategoryInput, p as UpdatePostInput, o as SEOScore } from './types-CBEEBR4A.cjs';
2
+ import { z } from 'zod';
3
+ import { Document, Collection, Db } from 'mongodb';
4
+
5
+ declare const envSchema: z.ZodObject<{
6
+ NEXTBLOGKIT_MONGODB_URI: z.ZodString;
7
+ NEXTBLOGKIT_R2_ACCOUNT_ID: z.ZodString;
8
+ NEXTBLOGKIT_R2_ACCESS_KEY: z.ZodString;
9
+ NEXTBLOGKIT_R2_SECRET_KEY: z.ZodString;
10
+ NEXTBLOGKIT_R2_BUCKET: z.ZodString;
11
+ NEXTBLOGKIT_R2_PUBLIC_URL: z.ZodString;
12
+ NEXTBLOGKIT_API_KEY: z.ZodString;
13
+ NEXTBLOGKIT_SITE_URL: z.ZodString;
14
+ NEXTBLOGKIT_SITE_NAME: z.ZodString;
15
+ }, "strip", z.ZodTypeAny, {
16
+ NEXTBLOGKIT_MONGODB_URI: string;
17
+ NEXTBLOGKIT_R2_ACCOUNT_ID: string;
18
+ NEXTBLOGKIT_R2_ACCESS_KEY: string;
19
+ NEXTBLOGKIT_R2_SECRET_KEY: string;
20
+ NEXTBLOGKIT_R2_BUCKET: string;
21
+ NEXTBLOGKIT_R2_PUBLIC_URL: string;
22
+ NEXTBLOGKIT_API_KEY: string;
23
+ NEXTBLOGKIT_SITE_URL: string;
24
+ NEXTBLOGKIT_SITE_NAME: string;
25
+ }, {
26
+ NEXTBLOGKIT_MONGODB_URI: string;
27
+ NEXTBLOGKIT_R2_ACCOUNT_ID: string;
28
+ NEXTBLOGKIT_R2_ACCESS_KEY: string;
29
+ NEXTBLOGKIT_R2_SECRET_KEY: string;
30
+ NEXTBLOGKIT_R2_BUCKET: string;
31
+ NEXTBLOGKIT_R2_PUBLIC_URL: string;
32
+ NEXTBLOGKIT_API_KEY: string;
33
+ NEXTBLOGKIT_SITE_URL: string;
34
+ NEXTBLOGKIT_SITE_NAME: string;
35
+ }>;
36
+ type EnvConfig = z.infer<typeof envSchema>;
37
+ declare function getEnvConfig(): EnvConfig;
38
+ declare function defineConfig(config: Partial<NextBlogKitConfig>): Partial<NextBlogKitConfig>;
39
+ declare function getConfig(userConfig?: Partial<NextBlogKitConfig>): NextBlogKitConfig;
40
+ declare function getBlogConfig(): {
41
+ siteUrl: string;
42
+ siteName: string;
43
+ metadata: {
44
+ title: string;
45
+ description: string;
46
+ openGraph: {
47
+ title: string;
48
+ description: string;
49
+ url: string;
50
+ siteName: string;
51
+ type: string;
52
+ };
53
+ };
54
+ basePath: string;
55
+ adminPath: string;
56
+ apiPath: string;
57
+ postsPerPage: number;
58
+ excerptLength: number;
59
+ codeHighlighter: "shiki" | "prism";
60
+ editor: {
61
+ blocks: BlockType[];
62
+ maxImageSize: number;
63
+ imageFormats: string[];
64
+ autosaveInterval: number;
65
+ };
66
+ seo: {
67
+ titleTemplate: string;
68
+ defaultOgImage?: string;
69
+ generateRSS: boolean;
70
+ generateSitemap: boolean;
71
+ structuredData: boolean;
72
+ minContentLength: number;
73
+ };
74
+ auth: {
75
+ strategy: "api-key" | "custom" | "credentials";
76
+ verify?: (request: Request) => Promise<boolean>;
77
+ admins?: string[];
78
+ };
79
+ features: {
80
+ search: boolean;
81
+ relatedPosts: boolean;
82
+ readingProgress: boolean;
83
+ tableOfContents: boolean;
84
+ shareButtons: boolean;
85
+ darkMode: boolean;
86
+ scheduling: boolean;
87
+ revisionHistory: boolean;
88
+ imageOptimization: boolean;
89
+ };
90
+ theme: {
91
+ variables?: Record<string, string>;
92
+ darkMode?: boolean;
93
+ components?: Record<string, React.ComponentType<unknown>>;
94
+ };
95
+ hooks: {
96
+ beforePublish?: (post: BlogPost) => Promise<void>;
97
+ afterPublish?: (post: BlogPost) => Promise<void>;
98
+ beforeDelete?: (post: BlogPost) => Promise<void>;
99
+ onMediaUpload?: (media: Media) => Promise<void>;
100
+ };
101
+ };
102
+
103
+ declare function getDb(): Promise<Db>;
104
+ declare function getCollection<T extends Document = Document>(name: string): Promise<Collection<T>>;
105
+ declare function ensureIndexes(): Promise<void>;
106
+ declare function createPost(input: CreatePostInput, defaultAuthor?: BlogPost['author']): Promise<BlogPost>;
107
+ declare function updatePost(id: string, input: UpdatePostInput): Promise<BlogPost | null>;
108
+ declare function deletePost(id: string): Promise<boolean>;
109
+ declare function getPostBySlug(slug: string): Promise<BlogPost | null>;
110
+ declare function getPostById(id: string): Promise<BlogPost | null>;
111
+ declare function listPosts(query?: PostListQuery): Promise<{
112
+ posts: BlogPost[];
113
+ total: number;
114
+ }>;
115
+ declare function createCategory(input: CreateCategoryInput): Promise<Category>;
116
+ declare function updateCategory(id: string, input: UpdateCategoryInput): Promise<Category | null>;
117
+ declare function deleteCategory(id: string): Promise<boolean>;
118
+ declare function listCategories(): Promise<Category[]>;
119
+ declare function getCategoryBySlug(slug: string): Promise<Category | null>;
120
+ declare function createMedia(data: Omit<Media, '_id'>): Promise<Media>;
121
+ declare function deleteMedia(id: string): Promise<Media | null>;
122
+ declare function listMedia(query?: MediaListQuery): Promise<{
123
+ media: Media[];
124
+ total: number;
125
+ }>;
126
+ declare function getSettings(): Promise<BlogSettings>;
127
+ declare function updateSettings(data: Partial<BlogSettings>): Promise<BlogSettings>;
128
+
129
+ interface MediaUploadResult {
130
+ key: string;
131
+ url: string;
132
+ size: number;
133
+ contentType: string;
134
+ }
135
+ interface StorageObject {
136
+ key: string;
137
+ size: number;
138
+ lastModified: Date;
139
+ }
140
+ interface StorageProvider {
141
+ upload(file: Buffer, filename: string, contentType: string): Promise<MediaUploadResult>;
142
+ delete(key: string): Promise<void>;
143
+ list(prefix?: string): Promise<StorageObject[]>;
144
+ }
145
+ declare class R2StorageProvider implements StorageProvider {
146
+ upload(file: Buffer, filename: string, contentType: string): Promise<MediaUploadResult>;
147
+ delete(key: string): Promise<void>;
148
+ list(prefix?: string): Promise<StorageObject[]>;
149
+ }
150
+
151
+ declare function generateSlug(text: string): string;
152
+ declare function ensureUniqueSlug(slug: string, collection: Collection, excludeId?: string): Promise<string>;
153
+
154
+ declare function calculateReadingTime(text: string): number;
155
+ declare function countWords(text: string): number;
156
+ declare function extractTextFromHTML(html: string): string;
157
+ declare function extractTextFromBlocks(blocks: unknown[]): string;
158
+
159
+ interface SearchResult {
160
+ slug: string;
161
+ title: string;
162
+ excerpt: string;
163
+ score: number;
164
+ }
165
+ declare function searchPosts(collection: Collection, query: string, limit?: number): Promise<SearchResult[]>;
166
+
167
+ interface MetaTags {
168
+ title: string;
169
+ description: string;
170
+ canonical: string;
171
+ openGraph: {
172
+ title: string;
173
+ description: string;
174
+ url: string;
175
+ siteName: string;
176
+ type: string;
177
+ images: {
178
+ url: string;
179
+ width?: number;
180
+ height?: number;
181
+ alt?: string;
182
+ }[];
183
+ article?: {
184
+ publishedTime: string;
185
+ modifiedTime: string;
186
+ section?: string;
187
+ tags?: string[];
188
+ };
189
+ };
190
+ twitter: {
191
+ card: string;
192
+ title: string;
193
+ description: string;
194
+ images: string[];
195
+ };
196
+ robots?: string;
197
+ }
198
+ declare function generateMetaTags(post: BlogPost): MetaTags;
199
+ interface ArticleStructuredData {
200
+ '@context': string;
201
+ '@type': string;
202
+ headline: string;
203
+ description: string;
204
+ image?: string;
205
+ datePublished?: string;
206
+ dateModified: string;
207
+ author: {
208
+ '@type': string;
209
+ name: string;
210
+ url?: string;
211
+ };
212
+ publisher: {
213
+ '@type': string;
214
+ name: string;
215
+ };
216
+ mainEntityOfPage: {
217
+ '@type': string;
218
+ '@id': string;
219
+ };
220
+ wordCount: number;
221
+ articleSection?: string;
222
+ }
223
+ declare function generateStructuredData(post: BlogPost): ArticleStructuredData;
224
+ interface FAQStructuredData {
225
+ '@context': string;
226
+ '@type': string;
227
+ mainEntity: {
228
+ '@type': string;
229
+ name: string;
230
+ acceptedAnswer: {
231
+ '@type': string;
232
+ text: string;
233
+ };
234
+ }[];
235
+ }
236
+ declare function generateFAQStructuredData(faqItems: {
237
+ question: string;
238
+ answer: string;
239
+ }[]): FAQStructuredData | null;
240
+ interface BreadcrumbStructuredData {
241
+ '@context': string;
242
+ '@type': string;
243
+ itemListElement: {
244
+ '@type': string;
245
+ position: number;
246
+ name: string;
247
+ item?: string;
248
+ }[];
249
+ }
250
+ declare function generateBreadcrumbs(post: BlogPost, categoryName?: string): BreadcrumbStructuredData;
251
+
252
+ declare function calculateSEOScore(post: BlogPost): SEOScore;
253
+
254
+ declare function generateSitemap(): Promise<string>;
255
+
256
+ declare function generateRSSFeed(fullContent?: boolean): Promise<string>;
257
+
258
+ interface ProcessedImage {
259
+ original: MediaUploadResult;
260
+ width: number;
261
+ height: number;
262
+ format: string;
263
+ }
264
+ declare function processImage(file: Buffer, filename: string, storage: R2StorageProvider): Promise<ProcessedImage>;
265
+
266
+ export { getEnvConfig as A, getPostById as B, getPostBySlug as C, getSettings as D, listCategories as E, listMedia as F, listPosts as G, processImage as H, searchPosts as I, updateCategory as J, updatePost as K, updateSettings as L, R2StorageProvider as R, calculateSEOScore as a, countWords as b, calculateReadingTime as c, createCategory as d, createMedia as e, createPost as f, defineConfig as g, deleteCategory as h, deleteMedia as i, deletePost as j, ensureIndexes as k, ensureUniqueSlug as l, extractTextFromBlocks as m, extractTextFromHTML as n, generateBreadcrumbs as o, generateFAQStructuredData as p, generateMetaTags as q, generateRSSFeed as r, generateSitemap as s, generateSlug as t, generateStructuredData as u, getBlogConfig as v, getCategoryBySlug as w, getCollection as x, getConfig as y, getDb as z };
package/dist/index.cjs ADDED
@@ -0,0 +1,368 @@
1
+ 'use strict';
2
+
3
+ var chunkQE4VLQYN_cjs = require('./chunk-QE4VLQYN.cjs');
4
+ var chunkZP5XRVVH_cjs = require('./chunk-ZP5XRVVH.cjs');
5
+ var chunkE2QLTHKN_cjs = require('./chunk-E2QLTHKN.cjs');
6
+ var chunk6HKMZOI4_cjs = require('./chunk-6HKMZOI4.cjs');
7
+ var chunkU2ROR6AY_cjs = require('./chunk-U2ROR6AY.cjs');
8
+
9
+ // src/editor/renderer.ts
10
+ function renderBlocksToHTML(doc) {
11
+ if (!doc.content) return "";
12
+ return doc.content.map(renderNode).join("");
13
+ }
14
+ function renderNode(node) {
15
+ switch (node.type) {
16
+ case "paragraph":
17
+ return `<p>${renderInline(node)}</p>`;
18
+ case "heading": {
19
+ const level = node.attrs?.level || 2;
20
+ const text = renderInline(node);
21
+ const id = slugify(stripTags(text));
22
+ return `<h${level} id="${id}">${text}</h${level}>`;
23
+ }
24
+ case "bulletList":
25
+ return `<ul>${renderChildren(node)}</ul>`;
26
+ case "orderedList":
27
+ return `<ol>${renderChildren(node)}</ol>`;
28
+ case "listItem":
29
+ return `<li>${renderChildren(node)}</li>`;
30
+ case "taskList":
31
+ return `<ul class="nbk-task-list">${renderChildren(node)}</ul>`;
32
+ case "taskItem": {
33
+ const checked = node.attrs?.checked ? "checked" : "";
34
+ return `<li class="nbk-task-item" data-checked="${checked}"><input type="checkbox" ${checked} disabled />${renderChildren(node)}</li>`;
35
+ }
36
+ case "blockquote":
37
+ return `<blockquote>${renderChildren(node)}</blockquote>`;
38
+ case "codeBlock": {
39
+ const lang = node.attrs?.language || "plaintext";
40
+ const filename = node.attrs?.filename;
41
+ const code = escapeHtml(getTextContent(node));
42
+ const header = filename ? `<div class="nbk-code-header">${escapeHtml(filename)}</div>` : "";
43
+ return `${header}<pre><code class="language-${lang}">${code}</code></pre>`;
44
+ }
45
+ case "image": {
46
+ const src = node.attrs?.src || "";
47
+ const alt = node.attrs?.alt || "";
48
+ const caption = node.attrs?.caption;
49
+ const width = node.attrs?.width;
50
+ const height = node.attrs?.height;
51
+ let img = `<img src="${escapeAttr(src)}" alt="${escapeAttr(alt)}"`;
52
+ if (width) img += ` width="${width}"`;
53
+ if (height) img += ` height="${height}"`;
54
+ img += ' loading="lazy" />';
55
+ if (caption) {
56
+ return `<figure>${img}<figcaption>${escapeHtml(caption)}</figcaption></figure>`;
57
+ }
58
+ return img;
59
+ }
60
+ case "horizontalRule":
61
+ return "<hr />";
62
+ case "table":
63
+ return `<table>${renderChildren(node)}</table>`;
64
+ case "tableRow":
65
+ return `<tr>${renderChildren(node)}</tr>`;
66
+ case "tableHeader":
67
+ return `<th>${renderInline(node)}</th>`;
68
+ case "tableCell":
69
+ return `<td>${renderInline(node)}</td>`;
70
+ case "callout": {
71
+ const calloutType = node.attrs?.type || "info";
72
+ const icons = {
73
+ info: "\u2139\uFE0F",
74
+ warning: "\u26A0\uFE0F",
75
+ tip: "\u{1F4A1}",
76
+ danger: "\u{1F6A8}"
77
+ };
78
+ return `<div class="nbk-callout nbk-callout-${calloutType}"><span class="nbk-callout-icon">${icons[calloutType] || ""}</span><div class="nbk-callout-content">${renderChildren(node)}</div></div>`;
79
+ }
80
+ case "faq":
81
+ return `<div class="nbk-faq" itemscope itemtype="https://schema.org/FAQPage">${renderChildren(node)}</div>`;
82
+ case "faqItem":
83
+ return `<div class="nbk-faq-item" itemscope itemprop="mainEntity" itemtype="https://schema.org/Question">${renderChildren(node)}</div>`;
84
+ case "faqQuestion":
85
+ return `<h3 itemprop="name">${renderInline(node)}</h3>`;
86
+ case "faqAnswer":
87
+ return `<div itemprop="acceptedAnswer" itemscope itemtype="https://schema.org/Answer"><div itemprop="text">${renderChildren(node)}</div></div>`;
88
+ case "tableOfContents":
89
+ return '<div data-toc="true" class="nbk-toc"></div>';
90
+ case "html":
91
+ return getTextContent(node);
92
+ case "embed": {
93
+ const embedUrl = node.attrs?.src || "";
94
+ return `<div class="nbk-embed"><iframe src="${escapeAttr(embedUrl)}" frameborder="0" allowfullscreen loading="lazy"></iframe></div>`;
95
+ }
96
+ case "text":
97
+ return renderTextNode(node);
98
+ case "hardBreak":
99
+ return "<br />";
100
+ default:
101
+ if (node.content) return renderChildren(node);
102
+ if (node.text) return escapeHtml(node.text);
103
+ return "";
104
+ }
105
+ }
106
+ function renderChildren(node) {
107
+ if (!node.content) return "";
108
+ return node.content.map(renderNode).join("");
109
+ }
110
+ function renderInline(node) {
111
+ if (!node.content) return "";
112
+ return node.content.map(renderNode).join("");
113
+ }
114
+ function renderTextNode(node) {
115
+ let text = escapeHtml(node.text || "");
116
+ if (node.marks) {
117
+ for (const mark of node.marks) {
118
+ switch (mark.type) {
119
+ case "bold":
120
+ text = `<strong>${text}</strong>`;
121
+ break;
122
+ case "italic":
123
+ text = `<em>${text}</em>`;
124
+ break;
125
+ case "strike":
126
+ text = `<s>${text}</s>`;
127
+ break;
128
+ case "code":
129
+ text = `<code>${text}</code>`;
130
+ break;
131
+ case "underline":
132
+ text = `<u>${text}</u>`;
133
+ break;
134
+ case "highlight":
135
+ text = `<mark>${text}</mark>`;
136
+ break;
137
+ case "link": {
138
+ const href = mark.attrs?.href || "";
139
+ const target = href.startsWith("http") ? ' target="_blank" rel="noopener noreferrer"' : "";
140
+ text = `<a href="${escapeAttr(href)}"${target}>${text}</a>`;
141
+ break;
142
+ }
143
+ }
144
+ }
145
+ }
146
+ return text;
147
+ }
148
+ function getTextContent(node) {
149
+ if (node.text) return node.text;
150
+ if (!node.content) return "";
151
+ return node.content.map(getTextContent).join("");
152
+ }
153
+ function escapeHtml(str) {
154
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
155
+ }
156
+ function escapeAttr(str) {
157
+ return str.replace(/"/g, "&quot;").replace(/&/g, "&amp;");
158
+ }
159
+ function stripTags(html) {
160
+ return html.replace(/<[^>]+>/g, "");
161
+ }
162
+ function slugify(text) {
163
+ return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/-+/g, "-");
164
+ }
165
+ function extractHeadings(doc) {
166
+ const headings = [];
167
+ function walk(node) {
168
+ if (node.type === "heading") {
169
+ const text = getTextContent(node);
170
+ headings.push({
171
+ id: slugify(text),
172
+ text,
173
+ level: node.attrs?.level || 2
174
+ });
175
+ }
176
+ if (node.content) {
177
+ node.content.forEach(walk);
178
+ }
179
+ }
180
+ if (doc.content) {
181
+ doc.content.forEach(walk);
182
+ }
183
+ return headings;
184
+ }
185
+ function extractFAQItems(doc) {
186
+ const items = [];
187
+ function walk(node) {
188
+ if (node.type === "faqItem" && node.content) {
189
+ const question = node.content.find((c) => c.type === "faqQuestion");
190
+ const answer = node.content.find((c) => c.type === "faqAnswer");
191
+ if (question && answer) {
192
+ items.push({
193
+ question: getTextContent(question),
194
+ answer: renderChildren(answer)
195
+ });
196
+ }
197
+ }
198
+ if (node.content) {
199
+ node.content.forEach(walk);
200
+ }
201
+ }
202
+ if (doc.content) {
203
+ doc.content.forEach(walk);
204
+ }
205
+ return items;
206
+ }
207
+
208
+ Object.defineProperty(exports, "calculateSEOScore", {
209
+ enumerable: true,
210
+ get: function () { return chunkQE4VLQYN_cjs.calculateSEOScore; }
211
+ });
212
+ Object.defineProperty(exports, "generateBreadcrumbs", {
213
+ enumerable: true,
214
+ get: function () { return chunkQE4VLQYN_cjs.generateBreadcrumbs; }
215
+ });
216
+ Object.defineProperty(exports, "generateFAQStructuredData", {
217
+ enumerable: true,
218
+ get: function () { return chunkQE4VLQYN_cjs.generateFAQStructuredData; }
219
+ });
220
+ Object.defineProperty(exports, "generateMetaTags", {
221
+ enumerable: true,
222
+ get: function () { return chunkQE4VLQYN_cjs.generateMetaTags; }
223
+ });
224
+ Object.defineProperty(exports, "generateStructuredData", {
225
+ enumerable: true,
226
+ get: function () { return chunkQE4VLQYN_cjs.generateStructuredData; }
227
+ });
228
+ Object.defineProperty(exports, "searchPosts", {
229
+ enumerable: true,
230
+ get: function () { return chunkQE4VLQYN_cjs.searchPosts; }
231
+ });
232
+ Object.defineProperty(exports, "R2StorageProvider", {
233
+ enumerable: true,
234
+ get: function () { return chunkZP5XRVVH_cjs.R2StorageProvider; }
235
+ });
236
+ Object.defineProperty(exports, "processImage", {
237
+ enumerable: true,
238
+ get: function () { return chunkZP5XRVVH_cjs.processImage; }
239
+ });
240
+ Object.defineProperty(exports, "generateSitemap", {
241
+ enumerable: true,
242
+ get: function () { return chunkE2QLTHKN_cjs.generateSitemap; }
243
+ });
244
+ Object.defineProperty(exports, "generateRSSFeed", {
245
+ enumerable: true,
246
+ get: function () { return chunk6HKMZOI4_cjs.generateRSSFeed; }
247
+ });
248
+ Object.defineProperty(exports, "calculateReadingTime", {
249
+ enumerable: true,
250
+ get: function () { return chunkU2ROR6AY_cjs.calculateReadingTime; }
251
+ });
252
+ Object.defineProperty(exports, "countWords", {
253
+ enumerable: true,
254
+ get: function () { return chunkU2ROR6AY_cjs.countWords; }
255
+ });
256
+ Object.defineProperty(exports, "createCategory", {
257
+ enumerable: true,
258
+ get: function () { return chunkU2ROR6AY_cjs.createCategory; }
259
+ });
260
+ Object.defineProperty(exports, "createMedia", {
261
+ enumerable: true,
262
+ get: function () { return chunkU2ROR6AY_cjs.createMedia; }
263
+ });
264
+ Object.defineProperty(exports, "createPost", {
265
+ enumerable: true,
266
+ get: function () { return chunkU2ROR6AY_cjs.createPost; }
267
+ });
268
+ Object.defineProperty(exports, "defineConfig", {
269
+ enumerable: true,
270
+ get: function () { return chunkU2ROR6AY_cjs.defineConfig; }
271
+ });
272
+ Object.defineProperty(exports, "deleteCategory", {
273
+ enumerable: true,
274
+ get: function () { return chunkU2ROR6AY_cjs.deleteCategory; }
275
+ });
276
+ Object.defineProperty(exports, "deleteMedia", {
277
+ enumerable: true,
278
+ get: function () { return chunkU2ROR6AY_cjs.deleteMedia; }
279
+ });
280
+ Object.defineProperty(exports, "deletePost", {
281
+ enumerable: true,
282
+ get: function () { return chunkU2ROR6AY_cjs.deletePost; }
283
+ });
284
+ Object.defineProperty(exports, "ensureIndexes", {
285
+ enumerable: true,
286
+ get: function () { return chunkU2ROR6AY_cjs.ensureIndexes; }
287
+ });
288
+ Object.defineProperty(exports, "ensureUniqueSlug", {
289
+ enumerable: true,
290
+ get: function () { return chunkU2ROR6AY_cjs.ensureUniqueSlug; }
291
+ });
292
+ Object.defineProperty(exports, "extractTextFromBlocks", {
293
+ enumerable: true,
294
+ get: function () { return chunkU2ROR6AY_cjs.extractTextFromBlocks; }
295
+ });
296
+ Object.defineProperty(exports, "extractTextFromHTML", {
297
+ enumerable: true,
298
+ get: function () { return chunkU2ROR6AY_cjs.extractTextFromHTML; }
299
+ });
300
+ Object.defineProperty(exports, "generateSlug", {
301
+ enumerable: true,
302
+ get: function () { return chunkU2ROR6AY_cjs.generateSlug; }
303
+ });
304
+ Object.defineProperty(exports, "getBlogConfig", {
305
+ enumerable: true,
306
+ get: function () { return chunkU2ROR6AY_cjs.getBlogConfig; }
307
+ });
308
+ Object.defineProperty(exports, "getCategoryBySlug", {
309
+ enumerable: true,
310
+ get: function () { return chunkU2ROR6AY_cjs.getCategoryBySlug; }
311
+ });
312
+ Object.defineProperty(exports, "getCollection", {
313
+ enumerable: true,
314
+ get: function () { return chunkU2ROR6AY_cjs.getCollection; }
315
+ });
316
+ Object.defineProperty(exports, "getConfig", {
317
+ enumerable: true,
318
+ get: function () { return chunkU2ROR6AY_cjs.getConfig; }
319
+ });
320
+ Object.defineProperty(exports, "getDb", {
321
+ enumerable: true,
322
+ get: function () { return chunkU2ROR6AY_cjs.getDb; }
323
+ });
324
+ Object.defineProperty(exports, "getEnvConfig", {
325
+ enumerable: true,
326
+ get: function () { return chunkU2ROR6AY_cjs.getEnvConfig; }
327
+ });
328
+ Object.defineProperty(exports, "getPostById", {
329
+ enumerable: true,
330
+ get: function () { return chunkU2ROR6AY_cjs.getPostById; }
331
+ });
332
+ Object.defineProperty(exports, "getPostBySlug", {
333
+ enumerable: true,
334
+ get: function () { return chunkU2ROR6AY_cjs.getPostBySlug; }
335
+ });
336
+ Object.defineProperty(exports, "getSettings", {
337
+ enumerable: true,
338
+ get: function () { return chunkU2ROR6AY_cjs.getSettings; }
339
+ });
340
+ Object.defineProperty(exports, "listCategories", {
341
+ enumerable: true,
342
+ get: function () { return chunkU2ROR6AY_cjs.listCategories; }
343
+ });
344
+ Object.defineProperty(exports, "listMedia", {
345
+ enumerable: true,
346
+ get: function () { return chunkU2ROR6AY_cjs.listMedia; }
347
+ });
348
+ Object.defineProperty(exports, "listPosts", {
349
+ enumerable: true,
350
+ get: function () { return chunkU2ROR6AY_cjs.listPosts; }
351
+ });
352
+ Object.defineProperty(exports, "updateCategory", {
353
+ enumerable: true,
354
+ get: function () { return chunkU2ROR6AY_cjs.updateCategory; }
355
+ });
356
+ Object.defineProperty(exports, "updatePost", {
357
+ enumerable: true,
358
+ get: function () { return chunkU2ROR6AY_cjs.updatePost; }
359
+ });
360
+ Object.defineProperty(exports, "updateSettings", {
361
+ enumerable: true,
362
+ get: function () { return chunkU2ROR6AY_cjs.updateSettings; }
363
+ });
364
+ exports.extractFAQItems = extractFAQItems;
365
+ exports.extractHeadings = extractHeadings;
366
+ exports.renderBlocksToHTML = renderBlocksToHTML;
367
+ //# sourceMappingURL=index.cjs.map
368
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/editor/renderer.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { BlockContent } from '../lib/types';\n\nexport function renderBlocksToHTML(doc: { type: string; content?: BlockContent[] }): string {\n if (!doc.content) return '';\n return doc.content.map(renderNode).join('');\n}\n\nfunction renderNode(node: BlockContent): string {\n switch (node.type) {\n case 'paragraph':\n return `<p>${renderInline(node)}</p>`;\n\n case 'heading': {\n const level = (node.attrs?.level as number) || 2;\n const text = renderInline(node);\n const id = slugify(stripTags(text));\n return `<h${level} id=\"${id}\">${text}</h${level}>`;\n }\n\n case 'bulletList':\n return `<ul>${renderChildren(node)}</ul>`;\n\n case 'orderedList':\n return `<ol>${renderChildren(node)}</ol>`;\n\n case 'listItem':\n return `<li>${renderChildren(node)}</li>`;\n\n case 'taskList':\n return `<ul class=\"nbk-task-list\">${renderChildren(node)}</ul>`;\n\n case 'taskItem': {\n const checked = node.attrs?.checked ? 'checked' : '';\n return `<li class=\"nbk-task-item\" data-checked=\"${checked}\"><input type=\"checkbox\" ${checked} disabled />${renderChildren(node)}</li>`;\n }\n\n case 'blockquote':\n return `<blockquote>${renderChildren(node)}</blockquote>`;\n\n case 'codeBlock': {\n const lang = (node.attrs?.language as string) || 'plaintext';\n const filename = node.attrs?.filename as string;\n const code = escapeHtml(getTextContent(node));\n const header = filename ? `<div class=\"nbk-code-header\">${escapeHtml(filename)}</div>` : '';\n return `${header}<pre><code class=\"language-${lang}\">${code}</code></pre>`;\n }\n\n case 'image': {\n const src = node.attrs?.src as string || '';\n const alt = node.attrs?.alt as string || '';\n const caption = node.attrs?.caption as string;\n const width = node.attrs?.width;\n const height = node.attrs?.height;\n let img = `<img src=\"${escapeAttr(src)}\" alt=\"${escapeAttr(alt)}\"`;\n if (width) img += ` width=\"${width}\"`;\n if (height) img += ` height=\"${height}\"`;\n img += ' loading=\"lazy\" />';\n if (caption) {\n return `<figure>${img}<figcaption>${escapeHtml(caption)}</figcaption></figure>`;\n }\n return img;\n }\n\n case 'horizontalRule':\n return '<hr />';\n\n case 'table':\n return `<table>${renderChildren(node)}</table>`;\n\n case 'tableRow':\n return `<tr>${renderChildren(node)}</tr>`;\n\n case 'tableHeader':\n return `<th>${renderInline(node)}</th>`;\n\n case 'tableCell':\n return `<td>${renderInline(node)}</td>`;\n\n case 'callout': {\n const calloutType = (node.attrs?.type as string) || 'info';\n const icons: Record<string, string> = {\n info: 'ℹ️',\n warning: '⚠️',\n tip: '💡',\n danger: '🚨',\n };\n return `<div class=\"nbk-callout nbk-callout-${calloutType}\"><span class=\"nbk-callout-icon\">${icons[calloutType] || ''}</span><div class=\"nbk-callout-content\">${renderChildren(node)}</div></div>`;\n }\n\n case 'faq':\n return `<div class=\"nbk-faq\" itemscope itemtype=\"https://schema.org/FAQPage\">${renderChildren(node)}</div>`;\n\n case 'faqItem':\n return `<div class=\"nbk-faq-item\" itemscope itemprop=\"mainEntity\" itemtype=\"https://schema.org/Question\">${renderChildren(node)}</div>`;\n\n case 'faqQuestion':\n return `<h3 itemprop=\"name\">${renderInline(node)}</h3>`;\n\n case 'faqAnswer':\n return `<div itemprop=\"acceptedAnswer\" itemscope itemtype=\"https://schema.org/Answer\"><div itemprop=\"text\">${renderChildren(node)}</div></div>`;\n\n case 'tableOfContents':\n return '<div data-toc=\"true\" class=\"nbk-toc\"></div>';\n\n case 'html':\n return getTextContent(node);\n\n case 'embed': {\n const embedUrl = node.attrs?.src as string || '';\n return `<div class=\"nbk-embed\"><iframe src=\"${escapeAttr(embedUrl)}\" frameborder=\"0\" allowfullscreen loading=\"lazy\"></iframe></div>`;\n }\n\n case 'text':\n return renderTextNode(node);\n\n case 'hardBreak':\n return '<br />';\n\n default:\n if (node.content) return renderChildren(node);\n if (node.text) return escapeHtml(node.text);\n return '';\n }\n}\n\nfunction renderChildren(node: BlockContent): string {\n if (!node.content) return '';\n return node.content.map(renderNode).join('');\n}\n\nfunction renderInline(node: BlockContent): string {\n if (!node.content) return '';\n return node.content.map(renderNode).join('');\n}\n\nfunction renderTextNode(node: BlockContent): string {\n let text = escapeHtml(node.text || '');\n\n if (node.marks) {\n for (const mark of node.marks) {\n switch (mark.type) {\n case 'bold':\n text = `<strong>${text}</strong>`;\n break;\n case 'italic':\n text = `<em>${text}</em>`;\n break;\n case 'strike':\n text = `<s>${text}</s>`;\n break;\n case 'code':\n text = `<code>${text}</code>`;\n break;\n case 'underline':\n text = `<u>${text}</u>`;\n break;\n case 'highlight':\n text = `<mark>${text}</mark>`;\n break;\n case 'link': {\n const href = mark.attrs?.href as string || '';\n const target = href.startsWith('http') ? ' target=\"_blank\" rel=\"noopener noreferrer\"' : '';\n text = `<a href=\"${escapeAttr(href)}\"${target}>${text}</a>`;\n break;\n }\n }\n }\n }\n\n return text;\n}\n\nfunction getTextContent(node: BlockContent): string {\n if (node.text) return node.text;\n if (!node.content) return '';\n return node.content.map(getTextContent).join('');\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\nfunction escapeAttr(str: string): string {\n return str.replace(/\"/g, '&quot;').replace(/&/g, '&amp;');\n}\n\nfunction stripTags(html: string): string {\n return html.replace(/<[^>]+>/g, '');\n}\n\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_]+/g, '-')\n .replace(/-+/g, '-');\n}\n\nexport function extractHeadings(\n doc: { type: string; content?: BlockContent[] }\n): { id: string; text: string; level: number }[] {\n const headings: { id: string; text: string; level: number }[] = [];\n\n function walk(node: BlockContent) {\n if (node.type === 'heading') {\n const text = getTextContent(node);\n headings.push({\n id: slugify(text),\n text,\n level: (node.attrs?.level as number) || 2,\n });\n }\n if (node.content) {\n node.content.forEach(walk);\n }\n }\n\n if (doc.content) {\n doc.content.forEach(walk);\n }\n\n return headings;\n}\n\nexport function extractFAQItems(\n doc: { type: string; content?: BlockContent[] }\n): { question: string; answer: string }[] {\n const items: { question: string; answer: string }[] = [];\n\n function walk(node: BlockContent) {\n if (node.type === 'faqItem' && node.content) {\n const question = node.content.find((c) => c.type === 'faqQuestion');\n const answer = node.content.find((c) => c.type === 'faqAnswer');\n if (question && answer) {\n items.push({\n question: getTextContent(question),\n answer: renderChildren(answer),\n });\n }\n }\n if (node.content) {\n node.content.forEach(walk);\n }\n }\n\n if (doc.content) {\n doc.content.forEach(walk);\n }\n\n return items;\n}\n"]}