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.
- package/dist/{chunk-24MKFHML.cjs → chunk-2TZSVPNP.cjs} +5 -0
- package/dist/{chunk-HMQIQUPB.cjs → chunk-6TFXNIO6.cjs} +108 -0
- package/dist/{chunk-ZRUBI3GH.js → chunk-B43UAOPC.js} +106 -1
- package/dist/{chunk-XP5J4LFJ.js → chunk-D26H5722.js} +5 -0
- package/dist/chunk-E7PYGJA7.cjs +39 -0
- package/dist/{chunk-QA4KPPTA.cjs → chunk-J3Y3HEBF.cjs} +84 -13
- package/dist/{chunk-PARGDJNY.js → chunk-K76XLEC7.js} +1 -1
- package/dist/{chunk-IXP35S24.js → chunk-LPPBVXJ7.js} +83 -12
- package/dist/chunk-Q6EXKX6K.js +17 -0
- package/dist/{chunk-4ZJGUMHS.cjs → chunk-Q6EYTOTM.cjs} +2 -2
- package/dist/chunk-UCXXH2MP.cjs +20 -0
- package/dist/chunk-XQD3UUL5.js +34 -0
- package/dist/cli/bin.cjs +5 -5
- package/dist/cli/bin.js +4 -4
- package/dist/cli/index.cjs +5 -5
- package/dist/cli/index.js +4 -4
- package/dist/config-ADPY6IQS.d.cts +473 -0
- package/dist/config-Dctsdeo6.d.ts +473 -0
- package/dist/index.cjs +157 -187
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +16 -69
- package/dist/local/index.cjs +785 -0
- package/dist/local/index.d.cts +268 -0
- package/dist/local/index.d.ts +268 -0
- package/dist/local/index.js +772 -0
- package/dist/output-0P0br3Jc.d.cts +452 -0
- package/dist/output-0P0br3Jc.d.ts +452 -0
- package/dist/plugins/embed-cloudflare-ai.cjs +166 -0
- package/dist/plugins/embed-cloudflare-ai.d.cts +73 -0
- package/dist/plugins/embed-cloudflare-ai.d.ts +73 -0
- package/dist/plugins/embed-cloudflare-ai.js +156 -0
- package/dist/plugins/embed-transformers.cjs +121 -0
- package/dist/plugins/embed-transformers.d.cts +55 -0
- package/dist/plugins/embed-transformers.d.ts +55 -0
- package/dist/plugins/embed-transformers.js +113 -0
- package/dist/plugins/similarity.cjs +19 -0
- package/dist/plugins/similarity.d.cts +41 -0
- package/dist/plugins/similarity.d.ts +41 -0
- package/dist/plugins/similarity.js +2 -0
- package/dist/processor/index.cjs +123 -111
- package/dist/processor/index.d.cts +6 -2
- package/dist/processor/index.d.ts +6 -2
- package/dist/processor/index.js +3 -3
- package/dist/processor/plugins.cjs +24 -12
- package/dist/processor/plugins.d.cts +4 -2
- package/dist/processor/plugins.d.ts +4 -2
- package/dist/processor/plugins.js +1 -1
- package/dist/processor/types.cjs +16 -16
- package/dist/processor/types.d.cts +3 -2
- package/dist/processor/types.d.ts +3 -2
- package/dist/processor/types.js +1 -1
- package/dist/seo/index.cjs +289 -0
- package/dist/seo/index.d.cts +95 -0
- package/dist/seo/index.d.ts +95 -0
- package/dist/seo/index.js +274 -0
- package/dist/server/index.cjs +2 -5
- package/dist/server/index.js +2 -5
- package/package.json +36 -1
- package/dist/config-DFr-htlO.d.cts +0 -887
- package/dist/config-DFr-htlO.d.ts +0 -887
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { b as IssueReport, P as ProcessingIssue, c as IssueSummary, B as BrokenLinkIssue, S as SlugConflictIssue, s as MissingMediaIssue, m as IssueCategory, n as IssueModule, I as IssueFilterOptions, d as ProcessedPost, e as ProcessedMedia } from '../output-0P0br3Jc.cjs';
|
|
2
|
+
|
|
3
|
+
declare class IssueIndex {
|
|
4
|
+
private readonly report;
|
|
5
|
+
constructor(report: IssueReport);
|
|
6
|
+
/** All issues */
|
|
7
|
+
all(): readonly ProcessingIssue[];
|
|
8
|
+
/** The summary (counts, affected files, etc.) */
|
|
9
|
+
get summary(): IssueSummary;
|
|
10
|
+
/** Build metadata (start/end time, version) */
|
|
11
|
+
get metadata(): {
|
|
12
|
+
readonly processStartTime: string;
|
|
13
|
+
readonly processEndTime: string;
|
|
14
|
+
readonly processorVersion?: string;
|
|
15
|
+
};
|
|
16
|
+
/** Total issue count */
|
|
17
|
+
get count(): number;
|
|
18
|
+
/** Whether there are any errors */
|
|
19
|
+
get hasErrors(): boolean;
|
|
20
|
+
/** Whether there are any warnings */
|
|
21
|
+
get hasWarnings(): boolean;
|
|
22
|
+
errors(): readonly ProcessingIssue[];
|
|
23
|
+
warnings(): readonly ProcessingIssue[];
|
|
24
|
+
info(): readonly ProcessingIssue[];
|
|
25
|
+
brokenLinks(): readonly BrokenLinkIssue[];
|
|
26
|
+
slugConflicts(): readonly SlugConflictIssue[];
|
|
27
|
+
missingMedia(): readonly MissingMediaIssue[];
|
|
28
|
+
/** Filter by category name */
|
|
29
|
+
byCategory(category: IssueCategory): readonly ProcessingIssue[];
|
|
30
|
+
/** Filter by module name */
|
|
31
|
+
byModule(module: IssueModule): readonly ProcessingIssue[];
|
|
32
|
+
/** Filter by file path */
|
|
33
|
+
byFile(filePath: string): readonly ProcessingIssue[];
|
|
34
|
+
/** Generic filter with multiple criteria (AND) */
|
|
35
|
+
filter(options: IssueFilterOptions): readonly ProcessingIssue[];
|
|
36
|
+
/** Get affected file paths */
|
|
37
|
+
affectedFiles(): string[];
|
|
38
|
+
/** Human-readable summary string */
|
|
39
|
+
summaryString(): string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Types for the FolderBlogLocal client
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
interface FolderBlogLocalOptions<TPost = ProcessedPost> {
|
|
47
|
+
/** Build output directory path (absolute or relative to cwd) */
|
|
48
|
+
dir: string;
|
|
49
|
+
/** Transform ProcessedPost into a custom type */
|
|
50
|
+
mapPost?: (post: ProcessedPost) => TPost;
|
|
51
|
+
/** Full-text search configuration */
|
|
52
|
+
search?: {
|
|
53
|
+
/** Enable search indexing (default: true) */
|
|
54
|
+
enabled?: boolean;
|
|
55
|
+
/** Field boost weights */
|
|
56
|
+
boost?: Record<string, number>;
|
|
57
|
+
/** Fuzzy matching tolerance (default: 0.2) */
|
|
58
|
+
fuzzy?: number;
|
|
59
|
+
/** Enable prefix matching (default: true) */
|
|
60
|
+
prefix?: boolean;
|
|
61
|
+
};
|
|
62
|
+
/** Similarity configuration */
|
|
63
|
+
similarity?: {
|
|
64
|
+
/** Enable similarity (default: auto — true if similarity.json exists) */
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
/** Number of similar posts to return (default: 5) */
|
|
67
|
+
topN?: number;
|
|
68
|
+
};
|
|
69
|
+
/** LRU cache configuration */
|
|
70
|
+
cache?: {
|
|
71
|
+
/** Enable caching (default: true) */
|
|
72
|
+
enabled?: boolean;
|
|
73
|
+
/** Max cache entries (default: 500) */
|
|
74
|
+
maxSize?: number;
|
|
75
|
+
};
|
|
76
|
+
/** Enable debug logging (default: false) */
|
|
77
|
+
debug?: boolean;
|
|
78
|
+
}
|
|
79
|
+
interface SearchOptions {
|
|
80
|
+
/** Max results (default: 10) */
|
|
81
|
+
limit?: number;
|
|
82
|
+
/** Fuzzy tolerance override */
|
|
83
|
+
fuzzy?: number;
|
|
84
|
+
/** Enable prefix matching override */
|
|
85
|
+
prefix?: boolean;
|
|
86
|
+
/** Field boost overrides */
|
|
87
|
+
boost?: Record<string, number>;
|
|
88
|
+
}
|
|
89
|
+
interface SearchResult {
|
|
90
|
+
slug: string;
|
|
91
|
+
title: string;
|
|
92
|
+
excerpt: string;
|
|
93
|
+
score: number;
|
|
94
|
+
}
|
|
95
|
+
interface AutocompleteResult {
|
|
96
|
+
slug: string;
|
|
97
|
+
title: string;
|
|
98
|
+
}
|
|
99
|
+
interface SimilarResult {
|
|
100
|
+
post: ProcessedPost;
|
|
101
|
+
score: number;
|
|
102
|
+
}
|
|
103
|
+
interface RelatedResult {
|
|
104
|
+
post: ProcessedPost;
|
|
105
|
+
score: number;
|
|
106
|
+
reasons: string[];
|
|
107
|
+
}
|
|
108
|
+
/** Frontmatter key-value query. All conditions must match (AND). */
|
|
109
|
+
type WhereQuery = Record<string, unknown>;
|
|
110
|
+
interface TagCount {
|
|
111
|
+
tag: string;
|
|
112
|
+
count: number;
|
|
113
|
+
}
|
|
114
|
+
interface CategoryCount {
|
|
115
|
+
category: string;
|
|
116
|
+
count: number;
|
|
117
|
+
}
|
|
118
|
+
interface BlogStats {
|
|
119
|
+
posts: number;
|
|
120
|
+
media: number;
|
|
121
|
+
tags: number;
|
|
122
|
+
categories: number;
|
|
123
|
+
hasSearch: boolean;
|
|
124
|
+
hasSimilarity: boolean;
|
|
125
|
+
}
|
|
126
|
+
interface FolderBlogLocalClient<TPost = ProcessedPost> {
|
|
127
|
+
posts: {
|
|
128
|
+
list(): TPost[];
|
|
129
|
+
get(slug: string): TPost;
|
|
130
|
+
getByHash(hash: string): TPost;
|
|
131
|
+
getByPath(path: string): TPost;
|
|
132
|
+
recent(count?: number): TPost[];
|
|
133
|
+
filter(predicate: (post: TPost) => boolean): TPost[];
|
|
134
|
+
where(query: WhereQuery): TPost[];
|
|
135
|
+
featured(): TPost[];
|
|
136
|
+
published(): TPost[];
|
|
137
|
+
sorted(posts?: TPost[]): TPost[];
|
|
138
|
+
slugs(): string[];
|
|
139
|
+
readonly count: number;
|
|
140
|
+
readonly slugMap: Record<string, string>;
|
|
141
|
+
};
|
|
142
|
+
search(query: string, options?: SearchOptions): SearchResult[];
|
|
143
|
+
searchAutocomplete(term: string, limit?: number): AutocompleteResult[];
|
|
144
|
+
similar(slugOrHash: string, count?: number): SimilarResult[];
|
|
145
|
+
related(slugOrHash: string, count?: number): RelatedResult[];
|
|
146
|
+
tags: {
|
|
147
|
+
list(): TagCount[];
|
|
148
|
+
posts(tag: string): TPost[];
|
|
149
|
+
};
|
|
150
|
+
categories: {
|
|
151
|
+
list(): CategoryCount[];
|
|
152
|
+
posts(category: string): TPost[];
|
|
153
|
+
};
|
|
154
|
+
media: {
|
|
155
|
+
list(): ProcessedMedia[];
|
|
156
|
+
get(path: string): ProcessedMedia;
|
|
157
|
+
};
|
|
158
|
+
readonly stats: BlogStats;
|
|
159
|
+
/** Raw issue report (from processor-issues.json) */
|
|
160
|
+
readonly issues: IssueReport;
|
|
161
|
+
/** Queryable issue index with filtering by category, severity, file */
|
|
162
|
+
readonly report: IssueIndex;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* PostStore — loads posts.json and provides indexed access by slug, hash, and path.
|
|
167
|
+
*/
|
|
168
|
+
|
|
169
|
+
/** Extract section/folder from a post's originalPath, stripping number prefixes */
|
|
170
|
+
declare function extractSection(post: ProcessedPost): string;
|
|
171
|
+
/** Check if a post is scheduled (date is in the future) */
|
|
172
|
+
declare function isScheduled(post: ProcessedPost): boolean;
|
|
173
|
+
/** Check if a post is a draft */
|
|
174
|
+
declare function isDraft(post: ProcessedPost): boolean;
|
|
175
|
+
/** Check if a post is hidden (excluded from public listings but still accessible) */
|
|
176
|
+
declare function isHidden(post: ProcessedPost): boolean;
|
|
177
|
+
/** Check if a post is published (not draft, not hidden, not future-dated) */
|
|
178
|
+
declare function isPublished(post: ProcessedPost): boolean;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Standard Post view type and mapper.
|
|
182
|
+
*
|
|
183
|
+
* Every consumer project maps ProcessedPost to a near-identical "Post" type.
|
|
184
|
+
* This module provides that standard mapping so consumers don't have to.
|
|
185
|
+
*
|
|
186
|
+
* Field renames:
|
|
187
|
+
* - content → html
|
|
188
|
+
* - plainText → plain
|
|
189
|
+
* - excerpt → firstParagraphText
|
|
190
|
+
* - originalPath → originalFilePath
|
|
191
|
+
* - toc[].slug → toc[].id
|
|
192
|
+
* - toc[].text → toc[].title
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
interface PostTocItem {
|
|
196
|
+
id: string;
|
|
197
|
+
title: string;
|
|
198
|
+
depth: number;
|
|
199
|
+
}
|
|
200
|
+
interface PostFrontmatter {
|
|
201
|
+
title: string;
|
|
202
|
+
date?: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
tags?: string[];
|
|
205
|
+
category?: string;
|
|
206
|
+
featured?: boolean;
|
|
207
|
+
draft?: boolean;
|
|
208
|
+
[key: string]: unknown;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Standard consumer-friendly Post type.
|
|
212
|
+
* Matches the shape every consumer independently creates.
|
|
213
|
+
*/
|
|
214
|
+
interface Post {
|
|
215
|
+
fileName: string;
|
|
216
|
+
slug: string;
|
|
217
|
+
hash: string;
|
|
218
|
+
frontmatter: PostFrontmatter;
|
|
219
|
+
firstParagraphText: string;
|
|
220
|
+
plain: string;
|
|
221
|
+
html: string;
|
|
222
|
+
toc: PostTocItem[];
|
|
223
|
+
originalFilePath: string;
|
|
224
|
+
wordCount: number;
|
|
225
|
+
firstImage?: string;
|
|
226
|
+
cover?: string;
|
|
227
|
+
links?: readonly string[];
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Convert a ProcessedPost to the standard Post view type.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* import { createLocalClient, toPost } from 'folderblog/local';
|
|
235
|
+
* const blog = createLocalClient({ dir: './dist', mapPost: toPost });
|
|
236
|
+
* blog.posts.list() // Post[]
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
declare function toPost(p: ProcessedPost): Post;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* FolderBlogLocal — local client that reads build output with search, similarity, and caching.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* import { createLocalClient } from 'folderblog/local';
|
|
247
|
+
*
|
|
248
|
+
* const blog = createLocalClient({ dir: './dist' });
|
|
249
|
+
* const posts = blog.posts.list();
|
|
250
|
+
* const results = blog.search('typescript');
|
|
251
|
+
* const similar = blog.similar('my-post-slug', 5);
|
|
252
|
+
* const related = blog.related('my-post-slug', 5);
|
|
253
|
+
* const autocomplete = blog.searchAutocomplete('type');
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Create a local client that reads from build output.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* const blog = createLocalClient({ dir: './dist' });
|
|
263
|
+
* const posts = blog.posts.list();
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
declare function createLocalClient<TPost = ProcessedPost>(options: FolderBlogLocalOptions<TPost>): FolderBlogLocalClient<TPost>;
|
|
267
|
+
|
|
268
|
+
export { type AutocompleteResult, type BlogStats, type CategoryCount, type FolderBlogLocalClient, type FolderBlogLocalOptions, IssueIndex, type Post, type PostFrontmatter, type PostTocItem, type RelatedResult, type SearchOptions, type SearchResult, type SimilarResult, type TagCount, type WhereQuery, createLocalClient, extractSection, isDraft, isHidden, isPublished, isScheduled, toPost };
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { b as IssueReport, P as ProcessingIssue, c as IssueSummary, B as BrokenLinkIssue, S as SlugConflictIssue, s as MissingMediaIssue, m as IssueCategory, n as IssueModule, I as IssueFilterOptions, d as ProcessedPost, e as ProcessedMedia } from '../output-0P0br3Jc.js';
|
|
2
|
+
|
|
3
|
+
declare class IssueIndex {
|
|
4
|
+
private readonly report;
|
|
5
|
+
constructor(report: IssueReport);
|
|
6
|
+
/** All issues */
|
|
7
|
+
all(): readonly ProcessingIssue[];
|
|
8
|
+
/** The summary (counts, affected files, etc.) */
|
|
9
|
+
get summary(): IssueSummary;
|
|
10
|
+
/** Build metadata (start/end time, version) */
|
|
11
|
+
get metadata(): {
|
|
12
|
+
readonly processStartTime: string;
|
|
13
|
+
readonly processEndTime: string;
|
|
14
|
+
readonly processorVersion?: string;
|
|
15
|
+
};
|
|
16
|
+
/** Total issue count */
|
|
17
|
+
get count(): number;
|
|
18
|
+
/** Whether there are any errors */
|
|
19
|
+
get hasErrors(): boolean;
|
|
20
|
+
/** Whether there are any warnings */
|
|
21
|
+
get hasWarnings(): boolean;
|
|
22
|
+
errors(): readonly ProcessingIssue[];
|
|
23
|
+
warnings(): readonly ProcessingIssue[];
|
|
24
|
+
info(): readonly ProcessingIssue[];
|
|
25
|
+
brokenLinks(): readonly BrokenLinkIssue[];
|
|
26
|
+
slugConflicts(): readonly SlugConflictIssue[];
|
|
27
|
+
missingMedia(): readonly MissingMediaIssue[];
|
|
28
|
+
/** Filter by category name */
|
|
29
|
+
byCategory(category: IssueCategory): readonly ProcessingIssue[];
|
|
30
|
+
/** Filter by module name */
|
|
31
|
+
byModule(module: IssueModule): readonly ProcessingIssue[];
|
|
32
|
+
/** Filter by file path */
|
|
33
|
+
byFile(filePath: string): readonly ProcessingIssue[];
|
|
34
|
+
/** Generic filter with multiple criteria (AND) */
|
|
35
|
+
filter(options: IssueFilterOptions): readonly ProcessingIssue[];
|
|
36
|
+
/** Get affected file paths */
|
|
37
|
+
affectedFiles(): string[];
|
|
38
|
+
/** Human-readable summary string */
|
|
39
|
+
summaryString(): string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Types for the FolderBlogLocal client
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
interface FolderBlogLocalOptions<TPost = ProcessedPost> {
|
|
47
|
+
/** Build output directory path (absolute or relative to cwd) */
|
|
48
|
+
dir: string;
|
|
49
|
+
/** Transform ProcessedPost into a custom type */
|
|
50
|
+
mapPost?: (post: ProcessedPost) => TPost;
|
|
51
|
+
/** Full-text search configuration */
|
|
52
|
+
search?: {
|
|
53
|
+
/** Enable search indexing (default: true) */
|
|
54
|
+
enabled?: boolean;
|
|
55
|
+
/** Field boost weights */
|
|
56
|
+
boost?: Record<string, number>;
|
|
57
|
+
/** Fuzzy matching tolerance (default: 0.2) */
|
|
58
|
+
fuzzy?: number;
|
|
59
|
+
/** Enable prefix matching (default: true) */
|
|
60
|
+
prefix?: boolean;
|
|
61
|
+
};
|
|
62
|
+
/** Similarity configuration */
|
|
63
|
+
similarity?: {
|
|
64
|
+
/** Enable similarity (default: auto — true if similarity.json exists) */
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
/** Number of similar posts to return (default: 5) */
|
|
67
|
+
topN?: number;
|
|
68
|
+
};
|
|
69
|
+
/** LRU cache configuration */
|
|
70
|
+
cache?: {
|
|
71
|
+
/** Enable caching (default: true) */
|
|
72
|
+
enabled?: boolean;
|
|
73
|
+
/** Max cache entries (default: 500) */
|
|
74
|
+
maxSize?: number;
|
|
75
|
+
};
|
|
76
|
+
/** Enable debug logging (default: false) */
|
|
77
|
+
debug?: boolean;
|
|
78
|
+
}
|
|
79
|
+
interface SearchOptions {
|
|
80
|
+
/** Max results (default: 10) */
|
|
81
|
+
limit?: number;
|
|
82
|
+
/** Fuzzy tolerance override */
|
|
83
|
+
fuzzy?: number;
|
|
84
|
+
/** Enable prefix matching override */
|
|
85
|
+
prefix?: boolean;
|
|
86
|
+
/** Field boost overrides */
|
|
87
|
+
boost?: Record<string, number>;
|
|
88
|
+
}
|
|
89
|
+
interface SearchResult {
|
|
90
|
+
slug: string;
|
|
91
|
+
title: string;
|
|
92
|
+
excerpt: string;
|
|
93
|
+
score: number;
|
|
94
|
+
}
|
|
95
|
+
interface AutocompleteResult {
|
|
96
|
+
slug: string;
|
|
97
|
+
title: string;
|
|
98
|
+
}
|
|
99
|
+
interface SimilarResult {
|
|
100
|
+
post: ProcessedPost;
|
|
101
|
+
score: number;
|
|
102
|
+
}
|
|
103
|
+
interface RelatedResult {
|
|
104
|
+
post: ProcessedPost;
|
|
105
|
+
score: number;
|
|
106
|
+
reasons: string[];
|
|
107
|
+
}
|
|
108
|
+
/** Frontmatter key-value query. All conditions must match (AND). */
|
|
109
|
+
type WhereQuery = Record<string, unknown>;
|
|
110
|
+
interface TagCount {
|
|
111
|
+
tag: string;
|
|
112
|
+
count: number;
|
|
113
|
+
}
|
|
114
|
+
interface CategoryCount {
|
|
115
|
+
category: string;
|
|
116
|
+
count: number;
|
|
117
|
+
}
|
|
118
|
+
interface BlogStats {
|
|
119
|
+
posts: number;
|
|
120
|
+
media: number;
|
|
121
|
+
tags: number;
|
|
122
|
+
categories: number;
|
|
123
|
+
hasSearch: boolean;
|
|
124
|
+
hasSimilarity: boolean;
|
|
125
|
+
}
|
|
126
|
+
interface FolderBlogLocalClient<TPost = ProcessedPost> {
|
|
127
|
+
posts: {
|
|
128
|
+
list(): TPost[];
|
|
129
|
+
get(slug: string): TPost;
|
|
130
|
+
getByHash(hash: string): TPost;
|
|
131
|
+
getByPath(path: string): TPost;
|
|
132
|
+
recent(count?: number): TPost[];
|
|
133
|
+
filter(predicate: (post: TPost) => boolean): TPost[];
|
|
134
|
+
where(query: WhereQuery): TPost[];
|
|
135
|
+
featured(): TPost[];
|
|
136
|
+
published(): TPost[];
|
|
137
|
+
sorted(posts?: TPost[]): TPost[];
|
|
138
|
+
slugs(): string[];
|
|
139
|
+
readonly count: number;
|
|
140
|
+
readonly slugMap: Record<string, string>;
|
|
141
|
+
};
|
|
142
|
+
search(query: string, options?: SearchOptions): SearchResult[];
|
|
143
|
+
searchAutocomplete(term: string, limit?: number): AutocompleteResult[];
|
|
144
|
+
similar(slugOrHash: string, count?: number): SimilarResult[];
|
|
145
|
+
related(slugOrHash: string, count?: number): RelatedResult[];
|
|
146
|
+
tags: {
|
|
147
|
+
list(): TagCount[];
|
|
148
|
+
posts(tag: string): TPost[];
|
|
149
|
+
};
|
|
150
|
+
categories: {
|
|
151
|
+
list(): CategoryCount[];
|
|
152
|
+
posts(category: string): TPost[];
|
|
153
|
+
};
|
|
154
|
+
media: {
|
|
155
|
+
list(): ProcessedMedia[];
|
|
156
|
+
get(path: string): ProcessedMedia;
|
|
157
|
+
};
|
|
158
|
+
readonly stats: BlogStats;
|
|
159
|
+
/** Raw issue report (from processor-issues.json) */
|
|
160
|
+
readonly issues: IssueReport;
|
|
161
|
+
/** Queryable issue index with filtering by category, severity, file */
|
|
162
|
+
readonly report: IssueIndex;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* PostStore — loads posts.json and provides indexed access by slug, hash, and path.
|
|
167
|
+
*/
|
|
168
|
+
|
|
169
|
+
/** Extract section/folder from a post's originalPath, stripping number prefixes */
|
|
170
|
+
declare function extractSection(post: ProcessedPost): string;
|
|
171
|
+
/** Check if a post is scheduled (date is in the future) */
|
|
172
|
+
declare function isScheduled(post: ProcessedPost): boolean;
|
|
173
|
+
/** Check if a post is a draft */
|
|
174
|
+
declare function isDraft(post: ProcessedPost): boolean;
|
|
175
|
+
/** Check if a post is hidden (excluded from public listings but still accessible) */
|
|
176
|
+
declare function isHidden(post: ProcessedPost): boolean;
|
|
177
|
+
/** Check if a post is published (not draft, not hidden, not future-dated) */
|
|
178
|
+
declare function isPublished(post: ProcessedPost): boolean;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Standard Post view type and mapper.
|
|
182
|
+
*
|
|
183
|
+
* Every consumer project maps ProcessedPost to a near-identical "Post" type.
|
|
184
|
+
* This module provides that standard mapping so consumers don't have to.
|
|
185
|
+
*
|
|
186
|
+
* Field renames:
|
|
187
|
+
* - content → html
|
|
188
|
+
* - plainText → plain
|
|
189
|
+
* - excerpt → firstParagraphText
|
|
190
|
+
* - originalPath → originalFilePath
|
|
191
|
+
* - toc[].slug → toc[].id
|
|
192
|
+
* - toc[].text → toc[].title
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
interface PostTocItem {
|
|
196
|
+
id: string;
|
|
197
|
+
title: string;
|
|
198
|
+
depth: number;
|
|
199
|
+
}
|
|
200
|
+
interface PostFrontmatter {
|
|
201
|
+
title: string;
|
|
202
|
+
date?: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
tags?: string[];
|
|
205
|
+
category?: string;
|
|
206
|
+
featured?: boolean;
|
|
207
|
+
draft?: boolean;
|
|
208
|
+
[key: string]: unknown;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Standard consumer-friendly Post type.
|
|
212
|
+
* Matches the shape every consumer independently creates.
|
|
213
|
+
*/
|
|
214
|
+
interface Post {
|
|
215
|
+
fileName: string;
|
|
216
|
+
slug: string;
|
|
217
|
+
hash: string;
|
|
218
|
+
frontmatter: PostFrontmatter;
|
|
219
|
+
firstParagraphText: string;
|
|
220
|
+
plain: string;
|
|
221
|
+
html: string;
|
|
222
|
+
toc: PostTocItem[];
|
|
223
|
+
originalFilePath: string;
|
|
224
|
+
wordCount: number;
|
|
225
|
+
firstImage?: string;
|
|
226
|
+
cover?: string;
|
|
227
|
+
links?: readonly string[];
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Convert a ProcessedPost to the standard Post view type.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* import { createLocalClient, toPost } from 'folderblog/local';
|
|
235
|
+
* const blog = createLocalClient({ dir: './dist', mapPost: toPost });
|
|
236
|
+
* blog.posts.list() // Post[]
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
declare function toPost(p: ProcessedPost): Post;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* FolderBlogLocal — local client that reads build output with search, similarity, and caching.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* import { createLocalClient } from 'folderblog/local';
|
|
247
|
+
*
|
|
248
|
+
* const blog = createLocalClient({ dir: './dist' });
|
|
249
|
+
* const posts = blog.posts.list();
|
|
250
|
+
* const results = blog.search('typescript');
|
|
251
|
+
* const similar = blog.similar('my-post-slug', 5);
|
|
252
|
+
* const related = blog.related('my-post-slug', 5);
|
|
253
|
+
* const autocomplete = blog.searchAutocomplete('type');
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Create a local client that reads from build output.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* const blog = createLocalClient({ dir: './dist' });
|
|
263
|
+
* const posts = blog.posts.list();
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
declare function createLocalClient<TPost = ProcessedPost>(options: FolderBlogLocalOptions<TPost>): FolderBlogLocalClient<TPost>;
|
|
267
|
+
|
|
268
|
+
export { type AutocompleteResult, type BlogStats, type CategoryCount, type FolderBlogLocalClient, type FolderBlogLocalOptions, IssueIndex, type Post, type PostFrontmatter, type PostTocItem, type RelatedResult, type SearchOptions, type SearchResult, type SimilarResult, type TagCount, type WhereQuery, createLocalClient, extractSection, isDraft, isHidden, isPublished, isScheduled, toPost };
|