folderblog 0.0.2 → 0.0.3

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 (61) hide show
  1. package/dist/{chunk-24MKFHML.cjs → chunk-2TZSVPNP.cjs} +5 -0
  2. package/dist/{chunk-HMQIQUPB.cjs → chunk-6TFXNIO6.cjs} +108 -0
  3. package/dist/{chunk-ZRUBI3GH.js → chunk-B43UAOPC.js} +106 -1
  4. package/dist/{chunk-XP5J4LFJ.js → chunk-D26H5722.js} +5 -0
  5. package/dist/chunk-E7PYGJA7.cjs +39 -0
  6. package/dist/{chunk-QA4KPPTA.cjs → chunk-J3Y3HEBF.cjs} +84 -13
  7. package/dist/{chunk-PARGDJNY.js → chunk-K76XLEC7.js} +1 -1
  8. package/dist/{chunk-IXP35S24.js → chunk-LPPBVXJ7.js} +83 -12
  9. package/dist/chunk-Q6EXKX6K.js +17 -0
  10. package/dist/{chunk-4ZJGUMHS.cjs → chunk-Q6EYTOTM.cjs} +2 -2
  11. package/dist/chunk-UCXXH2MP.cjs +20 -0
  12. package/dist/chunk-XQD3UUL5.js +34 -0
  13. package/dist/cli/bin.cjs +5 -5
  14. package/dist/cli/bin.js +4 -4
  15. package/dist/cli/index.cjs +5 -5
  16. package/dist/cli/index.js +4 -4
  17. package/dist/config-ADPY6IQS.d.cts +473 -0
  18. package/dist/config-Dctsdeo6.d.ts +473 -0
  19. package/dist/index.cjs +157 -187
  20. package/dist/index.d.cts +4 -3
  21. package/dist/index.d.ts +4 -3
  22. package/dist/index.js +16 -69
  23. package/dist/local/index.cjs +785 -0
  24. package/dist/local/index.d.cts +268 -0
  25. package/dist/local/index.d.ts +268 -0
  26. package/dist/local/index.js +772 -0
  27. package/dist/output-0P0br3Jc.d.cts +452 -0
  28. package/dist/output-0P0br3Jc.d.ts +452 -0
  29. package/dist/plugins/embed-cloudflare-ai.cjs +166 -0
  30. package/dist/plugins/embed-cloudflare-ai.d.cts +73 -0
  31. package/dist/plugins/embed-cloudflare-ai.d.ts +73 -0
  32. package/dist/plugins/embed-cloudflare-ai.js +156 -0
  33. package/dist/plugins/embed-transformers.cjs +121 -0
  34. package/dist/plugins/embed-transformers.d.cts +55 -0
  35. package/dist/plugins/embed-transformers.d.ts +55 -0
  36. package/dist/plugins/embed-transformers.js +113 -0
  37. package/dist/plugins/similarity.cjs +19 -0
  38. package/dist/plugins/similarity.d.cts +41 -0
  39. package/dist/plugins/similarity.d.ts +41 -0
  40. package/dist/plugins/similarity.js +2 -0
  41. package/dist/processor/index.cjs +123 -111
  42. package/dist/processor/index.d.cts +6 -2
  43. package/dist/processor/index.d.ts +6 -2
  44. package/dist/processor/index.js +3 -3
  45. package/dist/processor/plugins.cjs +24 -12
  46. package/dist/processor/plugins.d.cts +4 -2
  47. package/dist/processor/plugins.d.ts +4 -2
  48. package/dist/processor/plugins.js +1 -1
  49. package/dist/processor/types.cjs +16 -16
  50. package/dist/processor/types.d.cts +3 -2
  51. package/dist/processor/types.d.ts +3 -2
  52. package/dist/processor/types.js +1 -1
  53. package/dist/seo/index.cjs +289 -0
  54. package/dist/seo/index.d.cts +95 -0
  55. package/dist/seo/index.d.ts +95 -0
  56. package/dist/seo/index.js +274 -0
  57. package/dist/server/index.cjs +2 -5
  58. package/dist/server/index.js +2 -5
  59. package/package.json +36 -1
  60. package/dist/config-DFr-htlO.d.cts +0 -887
  61. package/dist/config-DFr-htlO.d.ts +0 -887
@@ -1,2 +1,2 @@
1
- export { CopyOnlyImageProcessor, NoOpDatabase, NoOpImageEmbedder, NoOpSimilarity, NoOpTextEmbedder, PassthroughMermaidRenderer, PluginManager, createAllNoOpPlugins, createDefaultPlugins, createPluginManager, topologicalSort } from '../chunk-ZRUBI3GH.js';
1
+ export { CopyOnlyImageProcessor, CosineSimilarityPlugin, NoOpDatabase, NoOpImageEmbedder, NoOpSimilarity, NoOpTextEmbedder, PassthroughMermaidRenderer, PluginManager, cosineSimilarity, createAllNoOpPlugins, createDefaultPlugins, createPluginManager, createSimilarityPlugin, topologicalSort } from '../chunk-B43UAOPC.js';
2
2
  import '../chunk-3RG5ZIWI.js';
@@ -1,67 +1,67 @@
1
1
  'use strict';
2
2
 
3
- var chunk24MKFHML_cjs = require('../chunk-24MKFHML.cjs');
3
+ var chunk2TZSVPNP_cjs = require('../chunk-2TZSVPNP.cjs');
4
4
  require('../chunk-OBGZSXTJ.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "DEFAULT_IMAGE_SIZES", {
9
9
  enumerable: true,
10
- get: function () { return chunk24MKFHML_cjs.DEFAULT_IMAGE_SIZES; }
10
+ get: function () { return chunk2TZSVPNP_cjs.DEFAULT_IMAGE_SIZES; }
11
11
  });
12
12
  Object.defineProperty(exports, "OUTPUT_FILES", {
13
13
  enumerable: true,
14
- get: function () { return chunk24MKFHML_cjs.OUTPUT_FILES; }
14
+ get: function () { return chunk2TZSVPNP_cjs.OUTPUT_FILES; }
15
15
  });
16
16
  Object.defineProperty(exports, "buildEmbeddingCacheFromManifest", {
17
17
  enumerable: true,
18
- get: function () { return chunk24MKFHML_cjs.buildEmbeddingCacheFromManifest; }
18
+ get: function () { return chunk2TZSVPNP_cjs.buildEmbeddingCacheFromManifest; }
19
19
  });
20
20
  Object.defineProperty(exports, "buildMediaCacheFromManifest", {
21
21
  enumerable: true,
22
- get: function () { return chunk24MKFHML_cjs.buildMediaCacheFromManifest; }
22
+ get: function () { return chunk2TZSVPNP_cjs.buildMediaCacheFromManifest; }
23
23
  });
24
24
  Object.defineProperty(exports, "createEmptyCacheStats", {
25
25
  enumerable: true,
26
- get: function () { return chunk24MKFHML_cjs.createEmptyCacheStats; }
26
+ get: function () { return chunk2TZSVPNP_cjs.createEmptyCacheStats; }
27
27
  });
28
28
  Object.defineProperty(exports, "getMediaOutputDir", {
29
29
  enumerable: true,
30
- get: function () { return chunk24MKFHML_cjs.getMediaOutputDir; }
30
+ get: function () { return chunk2TZSVPNP_cjs.getMediaOutputDir; }
31
31
  });
32
32
  Object.defineProperty(exports, "getOutputDir", {
33
33
  enumerable: true,
34
- get: function () { return chunk24MKFHML_cjs.getOutputDir; }
34
+ get: function () { return chunk2TZSVPNP_cjs.getOutputDir; }
35
35
  });
36
36
  Object.defineProperty(exports, "isBrokenLinkIssue", {
37
37
  enumerable: true,
38
- get: function () { return chunk24MKFHML_cjs.isBrokenLinkIssue; }
38
+ get: function () { return chunk2TZSVPNP_cjs.isBrokenLinkIssue; }
39
39
  });
40
40
  Object.defineProperty(exports, "isEmbeddingErrorIssue", {
41
41
  enumerable: true,
42
- get: function () { return chunk24MKFHML_cjs.isEmbeddingErrorIssue; }
42
+ get: function () { return chunk2TZSVPNP_cjs.isEmbeddingErrorIssue; }
43
43
  });
44
44
  Object.defineProperty(exports, "isMediaProcessingIssue", {
45
45
  enumerable: true,
46
- get: function () { return chunk24MKFHML_cjs.isMediaProcessingIssue; }
46
+ get: function () { return chunk2TZSVPNP_cjs.isMediaProcessingIssue; }
47
47
  });
48
48
  Object.defineProperty(exports, "isMermaidErrorIssue", {
49
49
  enumerable: true,
50
- get: function () { return chunk24MKFHML_cjs.isMermaidErrorIssue; }
50
+ get: function () { return chunk2TZSVPNP_cjs.isMermaidErrorIssue; }
51
51
  });
52
52
  Object.defineProperty(exports, "isMissingMediaIssue", {
53
53
  enumerable: true,
54
- get: function () { return chunk24MKFHML_cjs.isMissingMediaIssue; }
54
+ get: function () { return chunk2TZSVPNP_cjs.isMissingMediaIssue; }
55
55
  });
56
56
  Object.defineProperty(exports, "isPluginErrorIssue", {
57
57
  enumerable: true,
58
- get: function () { return chunk24MKFHML_cjs.isPluginErrorIssue; }
58
+ get: function () { return chunk2TZSVPNP_cjs.isPluginErrorIssue; }
59
59
  });
60
60
  Object.defineProperty(exports, "isSlugConflictIssue", {
61
61
  enumerable: true,
62
- get: function () { return chunk24MKFHML_cjs.isSlugConflictIssue; }
62
+ get: function () { return chunk2TZSVPNP_cjs.isSlugConflictIssue; }
63
63
  });
64
64
  Object.defineProperty(exports, "withDefaults", {
65
65
  enumerable: true,
66
- get: function () { return chunk24MKFHML_cjs.withDefaults; }
66
+ get: function () { return chunk2TZSVPNP_cjs.withDefaults; }
67
67
  });
@@ -1,5 +1,6 @@
1
- import { a8 as ProcessedPost } from '../config-DFr-htlO.cjs';
2
- export { B as BrokenLinkIssue, C as CacheContext, a as CacheStats, b as CachedMediaMetadata, c as CachedMediaSizeVariant, d as ContentConfig, D as DEFAULT_IMAGE_SIZES, h as DebugConfig, i as DirectoryConfig, E as EmbeddingErrorIssue, j as EmbeddingMap, G as GraphData, k as GraphEdge, l as GraphNode, q as ImageSizeConfig, r as IssueCategory, u as IssueFilterOptions, v as IssueModule, w as IssueReport, x as IssueSeverity, y as IssueSummary, M as MediaConfig, z as MediaMetadata, A as MediaPathMap, F as MediaProcessingIssue, H as MediaSizeVariant, J as MermaidConfig, K as MermaidErrorIssue, R as MissingMediaIssue, S as OUTPUT_FILES, T as OutputFiles, U as PathHashMap, V as PipelineConfig, _ as PluginErrorIssue, a0 as PostCover, a1 as PostCoverError, a2 as PostCoverSize, a3 as PostMetadata, a4 as ProcessConfig, a5 as ProcessConfigWithDefaults, a6 as ProcessResult, a7 as ProcessedMedia, a9 as ProcessingIssue, aa as RelationshipType, ad as SlugConflictIssue, ae as SlugHashMap, ag as TocItem, ah as buildEmbeddingCacheFromManifest, ai as buildMediaCacheFromManifest, ak as createEmptyCacheStats, an as getMediaOutputDir, ao as getOutputDir, ap as isBrokenLinkIssue, aq as isEmbeddingErrorIssue, ar as isMediaProcessingIssue, as as isMermaidErrorIssue, at as isMissingMediaIssue, au as isPluginErrorIssue, av as isSlugConflictIssue, aw as withDefaults } from '../config-DFr-htlO.cjs';
1
+ export { C as ContentConfig, D as DEFAULT_IMAGE_SIZES, d as DebugConfig, e as DirectoryConfig, j as ImageSizeConfig, M as MediaConfig, m as MermaidConfig, r as PipelineConfig, w as ProcessConfig, x as ProcessConfigWithDefaults, S as SimilarityConfig, F as getMediaOutputDir, G as getOutputDir, H as withDefaults } from '../config-ADPY6IQS.cjs';
2
+ import { d as ProcessedPost } from '../output-0P0br3Jc.cjs';
3
+ export { B as BrokenLinkIssue, f as BuildReport, C as CacheContext, g as CacheStats, h as CachedMediaMetadata, i as CachedMediaSizeVariant, E as EmbeddingErrorIssue, j as EmbeddingMap, G as GraphData, k as GraphEdge, l as GraphNode, m as IssueCategory, I as IssueFilterOptions, n as IssueModule, b as IssueReport, a as IssueSeverity, c as IssueSummary, M as MediaMetadata, o as MediaPathMap, p as MediaProcessingIssue, q as MediaSizeVariant, r as MermaidErrorIssue, s as MissingMediaIssue, O as OUTPUT_FILES, t as OutputFiles, u as PathHashMap, v as PluginErrorIssue, w as PostCover, x as PostCoverError, y as PostCoverSize, z as PostMetadata, A as ProcessResult, e as ProcessedMedia, P as ProcessingIssue, R as RelationshipType, S as SlugConflictIssue, D as SlugHashMap, T as TocItem, F as buildEmbeddingCacheFromManifest, H as buildMediaCacheFromManifest, J as createEmptyCacheStats, K as isBrokenLinkIssue, L as isEmbeddingErrorIssue, N as isMediaProcessingIssue, Q as isMermaidErrorIssue, U as isMissingMediaIssue, V as isPluginErrorIssue, W as isSlugConflictIssue } from '../output-0P0br3Jc.cjs';
3
4
 
4
5
  /**
5
6
  * Link resolution types for wiki-link and markdown link processing.
@@ -1,5 +1,6 @@
1
- import { a8 as ProcessedPost } from '../config-DFr-htlO.js';
2
- export { B as BrokenLinkIssue, C as CacheContext, a as CacheStats, b as CachedMediaMetadata, c as CachedMediaSizeVariant, d as ContentConfig, D as DEFAULT_IMAGE_SIZES, h as DebugConfig, i as DirectoryConfig, E as EmbeddingErrorIssue, j as EmbeddingMap, G as GraphData, k as GraphEdge, l as GraphNode, q as ImageSizeConfig, r as IssueCategory, u as IssueFilterOptions, v as IssueModule, w as IssueReport, x as IssueSeverity, y as IssueSummary, M as MediaConfig, z as MediaMetadata, A as MediaPathMap, F as MediaProcessingIssue, H as MediaSizeVariant, J as MermaidConfig, K as MermaidErrorIssue, R as MissingMediaIssue, S as OUTPUT_FILES, T as OutputFiles, U as PathHashMap, V as PipelineConfig, _ as PluginErrorIssue, a0 as PostCover, a1 as PostCoverError, a2 as PostCoverSize, a3 as PostMetadata, a4 as ProcessConfig, a5 as ProcessConfigWithDefaults, a6 as ProcessResult, a7 as ProcessedMedia, a9 as ProcessingIssue, aa as RelationshipType, ad as SlugConflictIssue, ae as SlugHashMap, ag as TocItem, ah as buildEmbeddingCacheFromManifest, ai as buildMediaCacheFromManifest, ak as createEmptyCacheStats, an as getMediaOutputDir, ao as getOutputDir, ap as isBrokenLinkIssue, aq as isEmbeddingErrorIssue, ar as isMediaProcessingIssue, as as isMermaidErrorIssue, at as isMissingMediaIssue, au as isPluginErrorIssue, av as isSlugConflictIssue, aw as withDefaults } from '../config-DFr-htlO.js';
1
+ export { C as ContentConfig, D as DEFAULT_IMAGE_SIZES, d as DebugConfig, e as DirectoryConfig, j as ImageSizeConfig, M as MediaConfig, m as MermaidConfig, r as PipelineConfig, w as ProcessConfig, x as ProcessConfigWithDefaults, S as SimilarityConfig, F as getMediaOutputDir, G as getOutputDir, H as withDefaults } from '../config-Dctsdeo6.js';
2
+ import { d as ProcessedPost } from '../output-0P0br3Jc.js';
3
+ export { B as BrokenLinkIssue, f as BuildReport, C as CacheContext, g as CacheStats, h as CachedMediaMetadata, i as CachedMediaSizeVariant, E as EmbeddingErrorIssue, j as EmbeddingMap, G as GraphData, k as GraphEdge, l as GraphNode, m as IssueCategory, I as IssueFilterOptions, n as IssueModule, b as IssueReport, a as IssueSeverity, c as IssueSummary, M as MediaMetadata, o as MediaPathMap, p as MediaProcessingIssue, q as MediaSizeVariant, r as MermaidErrorIssue, s as MissingMediaIssue, O as OUTPUT_FILES, t as OutputFiles, u as PathHashMap, v as PluginErrorIssue, w as PostCover, x as PostCoverError, y as PostCoverSize, z as PostMetadata, A as ProcessResult, e as ProcessedMedia, P as ProcessingIssue, R as RelationshipType, S as SlugConflictIssue, D as SlugHashMap, T as TocItem, F as buildEmbeddingCacheFromManifest, H as buildMediaCacheFromManifest, J as createEmptyCacheStats, K as isBrokenLinkIssue, L as isEmbeddingErrorIssue, N as isMediaProcessingIssue, Q as isMermaidErrorIssue, U as isMissingMediaIssue, V as isPluginErrorIssue, W as isSlugConflictIssue } from '../output-0P0br3Jc.js';
3
4
 
4
5
  /**
5
6
  * Link resolution types for wiki-link and markdown link processing.
@@ -1,2 +1,2 @@
1
- export { DEFAULT_IMAGE_SIZES, OUTPUT_FILES, buildEmbeddingCacheFromManifest, buildMediaCacheFromManifest, createEmptyCacheStats, getMediaOutputDir, getOutputDir, isBrokenLinkIssue, isEmbeddingErrorIssue, isMediaProcessingIssue, isMermaidErrorIssue, isMissingMediaIssue, isPluginErrorIssue, isSlugConflictIssue, withDefaults } from '../chunk-XP5J4LFJ.js';
1
+ export { DEFAULT_IMAGE_SIZES, OUTPUT_FILES, buildEmbeddingCacheFromManifest, buildMediaCacheFromManifest, createEmptyCacheStats, getMediaOutputDir, getOutputDir, isBrokenLinkIssue, isEmbeddingErrorIssue, isMediaProcessingIssue, isMermaidErrorIssue, isMissingMediaIssue, isPluginErrorIssue, isSlugConflictIssue, withDefaults } from '../chunk-D26H5722.js';
2
2
  import '../chunk-3RG5ZIWI.js';
@@ -0,0 +1,289 @@
1
+ 'use strict';
2
+
3
+ require('../chunk-OBGZSXTJ.cjs');
4
+
5
+ // src/seo/index.ts
6
+ function escapeMarkup(str, aposEntity = "'") {
7
+ if (!str) return "";
8
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, aposEntity);
9
+ }
10
+ function escapeXml(str) {
11
+ return escapeMarkup(str, "&apos;");
12
+ }
13
+ function escapeHtml(str) {
14
+ return escapeMarkup(str, "&#039;");
15
+ }
16
+ function makeAbsoluteUrl(path, siteUrl) {
17
+ if (path.startsWith("http://") || path.startsWith("https://")) return path;
18
+ if (path.startsWith("//")) return `https:${path}`;
19
+ if (path.startsWith("/")) return `${siteUrl}${path}`;
20
+ return `${siteUrl}/${path}`;
21
+ }
22
+ function generateMetaTags(site, options) {
23
+ const title = options.title ?? site.siteName;
24
+ const description = options.description ?? site.siteDescription ?? "";
25
+ const image = options.image ?? site.ogImage ?? "";
26
+ const url = options.url ?? site.siteUrl;
27
+ const type = options.type ?? "website";
28
+ const absoluteImage = image ? makeAbsoluteUrl(image, site.siteUrl) : "";
29
+ const tags = [
30
+ { title },
31
+ { name: "description", content: description },
32
+ { tagName: "link", rel: "canonical", href: url },
33
+ { property: "og:title", content: title },
34
+ { property: "og:description", content: description },
35
+ { property: "og:url", content: url },
36
+ { property: "og:type", content: type },
37
+ { property: "og:site_name", content: site.siteName },
38
+ { name: "twitter:card", content: "summary_large_image" },
39
+ { name: "twitter:title", content: title },
40
+ { name: "twitter:description", content: description }
41
+ ];
42
+ if (absoluteImage) {
43
+ tags.push(
44
+ { property: "og:image", content: absoluteImage },
45
+ { name: "twitter:image", content: absoluteImage }
46
+ );
47
+ }
48
+ if (type === "article" && options.article) {
49
+ const { article } = options;
50
+ if (article.publishedTime) {
51
+ tags.push({ property: "article:published_time", content: article.publishedTime });
52
+ }
53
+ if (article.modifiedTime) {
54
+ tags.push({ property: "article:modified_time", content: article.modifiedTime });
55
+ }
56
+ if (article.tags) {
57
+ for (const tag of article.tags) {
58
+ tags.push({ property: "article:tag", content: tag });
59
+ }
60
+ }
61
+ }
62
+ return tags;
63
+ }
64
+ function generatePostMetaTags(site, post, url) {
65
+ return generateMetaTags(site, {
66
+ title: `${post.title} | ${site.siteName}`,
67
+ description: post.description || post.excerpt,
68
+ image: post.coverImage,
69
+ url,
70
+ type: "article",
71
+ article: {
72
+ publishedTime: post.date,
73
+ author: post.authorName ?? site.author?.name,
74
+ tags: post.tags
75
+ }
76
+ });
77
+ }
78
+ function generateListMetaTags(site, title, description, url, pageNumber) {
79
+ const pageTitle = pageNumber && pageNumber > 1 ? `${title} - Page ${pageNumber} | ${site.siteName}` : `${title} | ${site.siteName}`;
80
+ const tags = generateMetaTags(site, {
81
+ title: pageTitle,
82
+ description,
83
+ url,
84
+ type: "website"
85
+ });
86
+ if (pageNumber && pageNumber > 1) {
87
+ tags.push({ name: "robots", content: "noindex, follow" });
88
+ }
89
+ return tags;
90
+ }
91
+ function postToArticleJsonLd(site, post, url) {
92
+ return {
93
+ "@context": "https://schema.org",
94
+ "@type": "BlogPosting",
95
+ headline: post.title,
96
+ description: post.description || post.excerpt,
97
+ author: {
98
+ "@type": post.authorName ? "Person" : "Organization",
99
+ name: post.authorName ?? site.author?.name ?? site.siteName
100
+ },
101
+ publisher: {
102
+ "@type": "Organization",
103
+ name: site.siteName
104
+ },
105
+ datePublished: post.date,
106
+ mainEntityOfPage: { "@type": "WebPage", "@id": url },
107
+ keywords: post.tags?.join(", "),
108
+ ...post.coverImage ? { image: [makeAbsoluteUrl(post.coverImage, site.siteUrl)] } : {}
109
+ };
110
+ }
111
+ function createItemListJsonLd(posts, listName, listDescription, baseUrl) {
112
+ return {
113
+ "@context": "https://schema.org",
114
+ "@type": "ItemList",
115
+ name: listName,
116
+ description: listDescription,
117
+ numberOfItems: posts.length,
118
+ itemListElement: posts.map((post, index) => ({
119
+ "@type": "ListItem",
120
+ position: index + 1,
121
+ url: baseUrl ? `${baseUrl}/${post.slug}` : `/${post.slug}`,
122
+ name: post.title
123
+ }))
124
+ };
125
+ }
126
+ function createBreadcrumbJsonLd(items) {
127
+ return {
128
+ "@context": "https://schema.org",
129
+ "@type": "BreadcrumbList",
130
+ itemListElement: items.map((item, index) => ({
131
+ "@type": "ListItem",
132
+ position: index + 1,
133
+ name: item.name,
134
+ item: item.url
135
+ }))
136
+ };
137
+ }
138
+ function createOrganizationJsonLd(site) {
139
+ const sameAs = [];
140
+ if (site.social?.twitter) sameAs.push(site.social.twitter);
141
+ if (site.social?.github) sameAs.push(site.social.github);
142
+ return {
143
+ "@context": "https://schema.org",
144
+ "@type": "Organization",
145
+ name: site.siteName,
146
+ url: site.siteUrl,
147
+ description: site.siteDescription,
148
+ ...sameAs.length > 0 ? { sameAs } : {}
149
+ };
150
+ }
151
+ function createWebsiteJsonLd(site, searchUrl) {
152
+ const jsonLd = {
153
+ "@context": "https://schema.org",
154
+ "@type": "WebSite",
155
+ name: site.siteName,
156
+ url: site.siteUrl,
157
+ description: site.siteDescription
158
+ };
159
+ if (searchUrl) {
160
+ jsonLd.potentialAction = {
161
+ "@type": "SearchAction",
162
+ target: {
163
+ "@type": "EntryPoint",
164
+ urlTemplate: searchUrl
165
+ },
166
+ "query-input": "required name=search_term_string"
167
+ };
168
+ }
169
+ return jsonLd;
170
+ }
171
+ function serializeJsonLd(jsonLd) {
172
+ return JSON.stringify(jsonLd, null, 2);
173
+ }
174
+ function generateRssFeed(options) {
175
+ const feedUrl = `${options.baseUrl}/api/feed.xml`;
176
+ const postPath = options.postPath ?? "/posts";
177
+ return `<?xml version="1.0" encoding="UTF-8"?>
178
+ <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
179
+ <channel>
180
+ <title>${escapeXml(options.title)}</title>
181
+ <description>${escapeXml(options.description)}</description>
182
+ <link>${escapeXml(options.baseUrl)}</link>
183
+ <atom:link href="${escapeXml(feedUrl)}" rel="self" type="application/rss+xml"/>
184
+ <lastBuildDate>${(/* @__PURE__ */ new Date()).toUTCString()}</lastBuildDate>
185
+ ${options.posts.map((post) => {
186
+ const postUrl = `${options.baseUrl}${postPath}/${encodeURIComponent(post.slug)}`;
187
+ return `
188
+ <item>
189
+ <title>${escapeXml(post.title)}</title>
190
+ <link>${escapeXml(postUrl)}</link>
191
+ <guid isPermaLink="true">${escapeXml(postUrl)}</guid>
192
+ <description>${escapeXml(post.description || post.excerpt)}</description>
193
+ ${post.date ? `<pubDate>${new Date(post.date).toUTCString()}</pubDate>` : ""}
194
+ ${(post.tags ?? []).map((tag) => `<category>${escapeXml(tag)}</category>`).join("\n ")}
195
+ </item>`;
196
+ }).join("")}
197
+ </channel>
198
+ </rss>`;
199
+ }
200
+ function generateJsonFeed(options) {
201
+ const postPath = options.postPath ?? "/posts";
202
+ return {
203
+ version: "https://jsonfeed.org/version/1.1",
204
+ title: options.title,
205
+ description: options.description,
206
+ home_page_url: options.baseUrl,
207
+ feed_url: `${options.baseUrl}/api/feed.json`,
208
+ icon: options.logo,
209
+ items: options.posts.map((post) => {
210
+ const postUrl = `${options.baseUrl}${postPath}/${encodeURIComponent(post.slug)}`;
211
+ return {
212
+ id: postUrl,
213
+ url: postUrl,
214
+ title: post.title,
215
+ summary: post.description || post.excerpt,
216
+ image: post.coverImage,
217
+ date_published: post.date,
218
+ authors: post.authorName ? [{ name: post.authorName }] : [],
219
+ tags: post.tags
220
+ };
221
+ })
222
+ };
223
+ }
224
+ function generateSitemap(baseUrl, posts, options) {
225
+ const postPath = options?.postPath ?? "/posts";
226
+ return `<?xml version="1.0" encoding="UTF-8"?>
227
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
228
+ <url>
229
+ <loc>${escapeXml(baseUrl)}</loc>
230
+ <changefreq>daily</changefreq>
231
+ <priority>1.0</priority>
232
+ </url>
233
+ ${posts.map((post) => {
234
+ const postUrl = `${baseUrl}${postPath}/${encodeURIComponent(post.slug)}`;
235
+ return `
236
+ <url>
237
+ <loc>${escapeXml(postUrl)}</loc>
238
+ ${post.date ? `<lastmod>${new Date(post.date).toISOString().split("T")[0]}</lastmod>` : ""}
239
+ <changefreq>weekly</changefreq>
240
+ <priority>0.8</priority>
241
+ </url>`;
242
+ }).join("")}
243
+ </urlset>`;
244
+ }
245
+ function generateRobotsTxt(sitemapUrl, options) {
246
+ const lines = ["User-agent: *"];
247
+ if (options?.allowPaths) {
248
+ for (const path of options.allowPaths) {
249
+ lines.push(`Allow: ${path}`);
250
+ }
251
+ }
252
+ if (options?.disallowPaths) {
253
+ for (const path of options.disallowPaths) {
254
+ lines.push(`Disallow: ${path}`);
255
+ }
256
+ }
257
+ lines.push("", `Sitemap: ${sitemapUrl}`);
258
+ return lines.join("\n");
259
+ }
260
+ function metaTagsToHtml(tags) {
261
+ return tags.map((tag) => {
262
+ if (tag.title) return `<title>${escapeHtml(tag.title)}</title>`;
263
+ if (tag.tagName === "link") {
264
+ return `<link rel="${escapeHtml(tag.rel)}" href="${escapeHtml(tag.href)}">`;
265
+ }
266
+ if (tag.property) {
267
+ return `<meta property="${escapeHtml(tag.property)}" content="${escapeHtml(tag.content)}">`;
268
+ }
269
+ if (tag.name) {
270
+ return `<meta name="${escapeHtml(tag.name)}" content="${escapeHtml(tag.content)}">`;
271
+ }
272
+ return "";
273
+ }).filter(Boolean).join("\n");
274
+ }
275
+
276
+ exports.createBreadcrumbJsonLd = createBreadcrumbJsonLd;
277
+ exports.createItemListJsonLd = createItemListJsonLd;
278
+ exports.createOrganizationJsonLd = createOrganizationJsonLd;
279
+ exports.createWebsiteJsonLd = createWebsiteJsonLd;
280
+ exports.generateJsonFeed = generateJsonFeed;
281
+ exports.generateListMetaTags = generateListMetaTags;
282
+ exports.generateMetaTags = generateMetaTags;
283
+ exports.generatePostMetaTags = generatePostMetaTags;
284
+ exports.generateRobotsTxt = generateRobotsTxt;
285
+ exports.generateRssFeed = generateRssFeed;
286
+ exports.generateSitemap = generateSitemap;
287
+ exports.metaTagsToHtml = metaTagsToHtml;
288
+ exports.postToArticleJsonLd = postToArticleJsonLd;
289
+ exports.serializeJsonLd = serializeJsonLd;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * SEO utilities for folderblog — meta tags, JSON-LD, sitemap, RSS, JSON Feed, robots.txt.
3
+ *
4
+ * Framework-agnostic pure functions. No dependencies on folderblog/local or processor.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { generateMetaTags, postToArticleJsonLd, generateSitemap } from 'folderblog/seo';
9
+ * ```
10
+ */
11
+ interface SeoSiteConfig {
12
+ siteName: string;
13
+ siteUrl: string;
14
+ siteDescription?: string;
15
+ ogImage?: string;
16
+ author?: {
17
+ name: string;
18
+ };
19
+ social?: {
20
+ twitter?: string;
21
+ github?: string;
22
+ };
23
+ }
24
+ interface SeoPost {
25
+ slug: string;
26
+ title: string;
27
+ description?: string;
28
+ excerpt?: string;
29
+ date?: string;
30
+ tags?: string[];
31
+ categories?: string[];
32
+ coverImage?: string;
33
+ authorName?: string;
34
+ }
35
+ interface MetaTag {
36
+ title?: string;
37
+ name?: string;
38
+ property?: string;
39
+ content?: string;
40
+ tagName?: string;
41
+ rel?: string;
42
+ href?: string;
43
+ }
44
+ interface MetaTagOptions {
45
+ title?: string;
46
+ description?: string;
47
+ image?: string;
48
+ url?: string;
49
+ type?: "website" | "article";
50
+ article?: {
51
+ publishedTime?: string;
52
+ modifiedTime?: string;
53
+ author?: string;
54
+ section?: string;
55
+ tags?: string[];
56
+ };
57
+ }
58
+ declare function generateMetaTags(site: SeoSiteConfig, options: MetaTagOptions): MetaTag[];
59
+ declare function generatePostMetaTags(site: SeoSiteConfig, post: SeoPost, url: string): MetaTag[];
60
+ declare function generateListMetaTags(site: SeoSiteConfig, title: string, description: string, url: string, pageNumber?: number): MetaTag[];
61
+ interface JsonLd {
62
+ "@context": string;
63
+ "@type": string;
64
+ [key: string]: unknown;
65
+ }
66
+ declare function postToArticleJsonLd(site: SeoSiteConfig, post: SeoPost, url: string): JsonLd;
67
+ declare function createItemListJsonLd(posts: SeoPost[], listName: string, listDescription?: string, baseUrl?: string): JsonLd;
68
+ declare function createBreadcrumbJsonLd(items: Array<{
69
+ name: string;
70
+ url?: string;
71
+ }>): JsonLd;
72
+ declare function createOrganizationJsonLd(site: SeoSiteConfig): JsonLd;
73
+ declare function createWebsiteJsonLd(site: SeoSiteConfig, searchUrl?: string): JsonLd;
74
+ declare function serializeJsonLd(jsonLd: JsonLd): string;
75
+ interface FeedOptions {
76
+ title: string;
77
+ description?: string;
78
+ baseUrl: string;
79
+ /** URL path prefix for posts (default: "/posts") */
80
+ postPath?: string;
81
+ logo?: string;
82
+ posts: SeoPost[];
83
+ }
84
+ declare function generateRssFeed(options: FeedOptions): string;
85
+ declare function generateJsonFeed(options: FeedOptions): object;
86
+ declare function generateSitemap(baseUrl: string, posts: SeoPost[], options?: {
87
+ postPath?: string;
88
+ }): string;
89
+ declare function generateRobotsTxt(sitemapUrl: string, options?: {
90
+ disallowPaths?: string[];
91
+ allowPaths?: string[];
92
+ }): string;
93
+ declare function metaTagsToHtml(tags: MetaTag[]): string;
94
+
95
+ export { type FeedOptions, type JsonLd, type MetaTag, type MetaTagOptions, type SeoPost, type SeoSiteConfig, createBreadcrumbJsonLd, createItemListJsonLd, createOrganizationJsonLd, createWebsiteJsonLd, generateJsonFeed, generateListMetaTags, generateMetaTags, generatePostMetaTags, generateRobotsTxt, generateRssFeed, generateSitemap, metaTagsToHtml, postToArticleJsonLd, serializeJsonLd };
@@ -0,0 +1,95 @@
1
+ /**
2
+ * SEO utilities for folderblog — meta tags, JSON-LD, sitemap, RSS, JSON Feed, robots.txt.
3
+ *
4
+ * Framework-agnostic pure functions. No dependencies on folderblog/local or processor.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { generateMetaTags, postToArticleJsonLd, generateSitemap } from 'folderblog/seo';
9
+ * ```
10
+ */
11
+ interface SeoSiteConfig {
12
+ siteName: string;
13
+ siteUrl: string;
14
+ siteDescription?: string;
15
+ ogImage?: string;
16
+ author?: {
17
+ name: string;
18
+ };
19
+ social?: {
20
+ twitter?: string;
21
+ github?: string;
22
+ };
23
+ }
24
+ interface SeoPost {
25
+ slug: string;
26
+ title: string;
27
+ description?: string;
28
+ excerpt?: string;
29
+ date?: string;
30
+ tags?: string[];
31
+ categories?: string[];
32
+ coverImage?: string;
33
+ authorName?: string;
34
+ }
35
+ interface MetaTag {
36
+ title?: string;
37
+ name?: string;
38
+ property?: string;
39
+ content?: string;
40
+ tagName?: string;
41
+ rel?: string;
42
+ href?: string;
43
+ }
44
+ interface MetaTagOptions {
45
+ title?: string;
46
+ description?: string;
47
+ image?: string;
48
+ url?: string;
49
+ type?: "website" | "article";
50
+ article?: {
51
+ publishedTime?: string;
52
+ modifiedTime?: string;
53
+ author?: string;
54
+ section?: string;
55
+ tags?: string[];
56
+ };
57
+ }
58
+ declare function generateMetaTags(site: SeoSiteConfig, options: MetaTagOptions): MetaTag[];
59
+ declare function generatePostMetaTags(site: SeoSiteConfig, post: SeoPost, url: string): MetaTag[];
60
+ declare function generateListMetaTags(site: SeoSiteConfig, title: string, description: string, url: string, pageNumber?: number): MetaTag[];
61
+ interface JsonLd {
62
+ "@context": string;
63
+ "@type": string;
64
+ [key: string]: unknown;
65
+ }
66
+ declare function postToArticleJsonLd(site: SeoSiteConfig, post: SeoPost, url: string): JsonLd;
67
+ declare function createItemListJsonLd(posts: SeoPost[], listName: string, listDescription?: string, baseUrl?: string): JsonLd;
68
+ declare function createBreadcrumbJsonLd(items: Array<{
69
+ name: string;
70
+ url?: string;
71
+ }>): JsonLd;
72
+ declare function createOrganizationJsonLd(site: SeoSiteConfig): JsonLd;
73
+ declare function createWebsiteJsonLd(site: SeoSiteConfig, searchUrl?: string): JsonLd;
74
+ declare function serializeJsonLd(jsonLd: JsonLd): string;
75
+ interface FeedOptions {
76
+ title: string;
77
+ description?: string;
78
+ baseUrl: string;
79
+ /** URL path prefix for posts (default: "/posts") */
80
+ postPath?: string;
81
+ logo?: string;
82
+ posts: SeoPost[];
83
+ }
84
+ declare function generateRssFeed(options: FeedOptions): string;
85
+ declare function generateJsonFeed(options: FeedOptions): object;
86
+ declare function generateSitemap(baseUrl: string, posts: SeoPost[], options?: {
87
+ postPath?: string;
88
+ }): string;
89
+ declare function generateRobotsTxt(sitemapUrl: string, options?: {
90
+ disallowPaths?: string[];
91
+ allowPaths?: string[];
92
+ }): string;
93
+ declare function metaTagsToHtml(tags: MetaTag[]): string;
94
+
95
+ export { type FeedOptions, type JsonLd, type MetaTag, type MetaTagOptions, type SeoPost, type SeoSiteConfig, createBreadcrumbJsonLd, createItemListJsonLd, createOrganizationJsonLd, createWebsiteJsonLd, generateJsonFeed, generateListMetaTags, generateMetaTags, generatePostMetaTags, generateRobotsTxt, generateRssFeed, generateSitemap, metaTagsToHtml, postToArticleJsonLd, serializeJsonLd };