bunki 0.16.2 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -15
- package/dist/cli/commands/templates/archive-njk.d.ts +4 -0
- package/dist/cli/commands/templates/base-njk.d.ts +4 -0
- package/dist/cli/commands/templates/default-css.d.ts +4 -0
- package/dist/cli/commands/templates/index-njk.d.ts +4 -0
- package/dist/cli/commands/templates/index.d.ts +14 -0
- package/dist/cli/commands/templates/post-njk.d.ts +4 -0
- package/dist/cli/commands/templates/sample-post.d.ts +4 -0
- package/dist/cli/commands/templates/tag-njk.d.ts +4 -0
- package/dist/cli/commands/templates/tags-njk.d.ts +4 -0
- package/dist/cli/commands/validate.d.ts +0 -3
- package/dist/cli.js +1636 -1530
- package/dist/generators/assets.d.ts +16 -0
- package/dist/generators/feeds.d.ts +32 -0
- package/dist/generators/pages.d.ts +48 -0
- package/dist/index.js +913 -830
- package/dist/site-generator.d.ts +22 -22
- package/dist/utils/build-metrics.d.ts +52 -0
- package/dist/utils/css-processor.d.ts +10 -1
- package/dist/utils/markdown/constants.d.ts +16 -0
- package/dist/utils/markdown/parser.d.ts +32 -0
- package/dist/utils/markdown/validators.d.ts +31 -0
- package/dist/utils/markdown-utils.d.ts +16 -11
- package/dist/utils/pagination.d.ts +38 -0
- package/dist/utils/xml-builder.d.ts +42 -0
- package/package.json +1 -1
package/dist/site-generator.d.ts
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Site generator orchestrator
|
|
3
|
+
* Coordinates all generation tasks using modular generators
|
|
4
|
+
*/
|
|
5
|
+
import type { GeneratorOptions } from "./types";
|
|
2
6
|
export declare class SiteGenerator {
|
|
3
7
|
private options;
|
|
4
8
|
private site;
|
|
5
|
-
private
|
|
6
|
-
private groupPostsByYear;
|
|
7
|
-
private getSortedTags;
|
|
8
|
-
private createPagination;
|
|
9
|
+
private metrics;
|
|
9
10
|
constructor(options: GeneratorOptions);
|
|
11
|
+
/**
|
|
12
|
+
* Initialize site data - parse markdown and prepare site structure
|
|
13
|
+
*/
|
|
10
14
|
initialize(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Generate all static site content
|
|
17
|
+
*/
|
|
11
18
|
generate(): Promise<void>;
|
|
12
|
-
private generate404Page;
|
|
13
|
-
private generateYearArchives;
|
|
14
|
-
private generateIndexPage;
|
|
15
|
-
private generatePostPages;
|
|
16
|
-
private generateTagPages;
|
|
17
|
-
private generateMapPage;
|
|
18
|
-
private generateStylesheet;
|
|
19
|
-
private fallbackCSSGeneration;
|
|
20
|
-
private copyStaticAssets;
|
|
21
19
|
/**
|
|
22
|
-
*
|
|
20
|
+
* Generate all feed files (RSS, sitemap, robots.txt)
|
|
21
|
+
*/
|
|
22
|
+
private generateFeeds;
|
|
23
|
+
/**
|
|
24
|
+
* Group posts by year (Pacific timezone)
|
|
25
|
+
* @param posts - Array of posts
|
|
26
|
+
* @returns Posts grouped by year
|
|
23
27
|
*/
|
|
24
|
-
private
|
|
28
|
+
private groupPostsByYear;
|
|
25
29
|
/**
|
|
26
|
-
*
|
|
30
|
+
* Calculate output statistics (file count and total size)
|
|
27
31
|
*/
|
|
28
|
-
private
|
|
29
|
-
private generateRSSFeed;
|
|
30
|
-
private generateSitemap;
|
|
31
|
-
private generateSitemapIndex;
|
|
32
|
-
private generateRobotsTxt;
|
|
32
|
+
private calculateOutputStats;
|
|
33
33
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build performance metrics and tracking
|
|
3
|
+
*/
|
|
4
|
+
export interface BuildMetrics {
|
|
5
|
+
totalTime: number;
|
|
6
|
+
stages: {
|
|
7
|
+
initialization: number;
|
|
8
|
+
cssProcessing: number;
|
|
9
|
+
pageGeneration: number;
|
|
10
|
+
feedGeneration: number;
|
|
11
|
+
assetCopying: number;
|
|
12
|
+
};
|
|
13
|
+
outputs: {
|
|
14
|
+
posts: number;
|
|
15
|
+
pages: number;
|
|
16
|
+
totalSize: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface BuildStage {
|
|
20
|
+
name: keyof BuildMetrics["stages"];
|
|
21
|
+
startTime: number;
|
|
22
|
+
}
|
|
23
|
+
export declare class MetricsCollector {
|
|
24
|
+
private startTime;
|
|
25
|
+
private stageTimings;
|
|
26
|
+
private currentStage;
|
|
27
|
+
constructor();
|
|
28
|
+
/**
|
|
29
|
+
* Start tracking a build stage
|
|
30
|
+
*/
|
|
31
|
+
startStage(name: keyof BuildMetrics["stages"]): void;
|
|
32
|
+
/**
|
|
33
|
+
* End the current build stage
|
|
34
|
+
*/
|
|
35
|
+
endStage(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get final build metrics
|
|
38
|
+
*/
|
|
39
|
+
getMetrics(outputs: {
|
|
40
|
+
posts: number;
|
|
41
|
+
pages: number;
|
|
42
|
+
totalSize: number;
|
|
43
|
+
}): BuildMetrics;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Format bytes to human-readable string
|
|
47
|
+
*/
|
|
48
|
+
export declare function formatBytes(bytes: number): string;
|
|
49
|
+
/**
|
|
50
|
+
* Display build metrics in the console
|
|
51
|
+
*/
|
|
52
|
+
export declare function displayMetrics(metrics: BuildMetrics): void;
|
|
@@ -8,12 +8,21 @@ export interface CSSProcessorOptions {
|
|
|
8
8
|
outputDir: string;
|
|
9
9
|
/** Whether to run in verbose mode */
|
|
10
10
|
verbose?: boolean;
|
|
11
|
+
/** Enable content-based cache busting with hash */
|
|
12
|
+
enableHashing?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface CSSProcessResult {
|
|
15
|
+
/** Output file path (may include hash if hashing enabled) */
|
|
16
|
+
outputPath: string;
|
|
17
|
+
/** Content hash (8-char base36) if hashing enabled */
|
|
18
|
+
hash?: string;
|
|
11
19
|
}
|
|
12
20
|
/**
|
|
13
21
|
* Process CSS using PostCSS directly
|
|
14
22
|
* Throws on error - no fallback
|
|
23
|
+
* Returns output path (with hash if hashing enabled)
|
|
15
24
|
*/
|
|
16
|
-
export declare function processCSS(options: CSSProcessorOptions): Promise<
|
|
25
|
+
export declare function processCSS(options: CSSProcessorOptions): Promise<CSSProcessResult>;
|
|
17
26
|
/**
|
|
18
27
|
* Watch CSS files for changes and reprocess
|
|
19
28
|
*/
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for markdown processing
|
|
3
|
+
* Extracted for better code organization and performance
|
|
4
|
+
*/
|
|
5
|
+
export declare const RELATIVE_LINK_REGEX: RegExp;
|
|
6
|
+
export declare const IMAGE_PATH_REGEX: RegExp;
|
|
7
|
+
export declare const YOUTUBE_EMBED_REGEX: RegExp;
|
|
8
|
+
export declare const EXTERNAL_LINK_REGEX: RegExp;
|
|
9
|
+
export declare const SCHEMA_ORG_PLACE_TYPES: Set<string>;
|
|
10
|
+
export declare const ALERT_ICONS: {
|
|
11
|
+
readonly note: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\"><path fill-rule=\"evenodd\" d=\"M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-7-4a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM9 9a.75.75 0 0 0 0 1.5h.253a.25.25 0 0 1 .244.304l-.459 2.066A1.75 1.75 0 0 0 10.747 15H11a.75.75 0 0 0 0-1.5h-.253a.25.25 0 0 1-.244-.304l.459-2.066A1.75 1.75 0 0 0 9.253 9H9Z\" clip-rule=\"evenodd\" /></svg>";
|
|
12
|
+
readonly tip: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M10 1a6 6 0 0 0-3.815 10.631C7.237 12.5 8 13.443 8 14.456v.644a.75.75 0 0 0 .75.75h2.5a.75.75 0 0 0 .75-.75v-.644c0-1.013.762-1.957 1.815-2.825A6 6 0 0 0 10 1ZM8.863 17.414a.75.75 0 0 0-.226 1.483 9.066 9.066 0 0 0 2.726 0 .75.75 0 0 0-.226-1.483 7.553 7.553 0 0 1-2.274 0Z\" /></svg>";
|
|
13
|
+
readonly important: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\"><path fill-rule=\"evenodd\" d=\"M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-8-5a.75.75 0 0 1 .75.75v4.5a.75.75 0 0 1-1.5 0v-4.5A.75.75 0 0 1 10 5Zm0 10a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z\" clip-rule=\"evenodd\" /></svg>";
|
|
14
|
+
readonly warning: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\"><path fill-rule=\"evenodd\" d=\"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495ZM10 5a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 10 5Zm0 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z\" clip-rule=\"evenodd\" /></svg>";
|
|
15
|
+
readonly caution: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\"><path fill-rule=\"evenodd\" d=\"M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM8.28 7.22a.75.75 0 0 0-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 1 0 1.06 1.06L10 11.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L11.06 10l1.72-1.72a.75.75 0 0 0-1.06-1.06L10 8.94 8.28 7.22Z\" clip-rule=\"evenodd\" /></svg>";
|
|
16
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core markdown parsing and transformation logic
|
|
3
|
+
*/
|
|
4
|
+
import { Marked } from "marked";
|
|
5
|
+
import type { CDNConfig } from "../../types";
|
|
6
|
+
/**
|
|
7
|
+
* Set domains that should not have nofollow attribute
|
|
8
|
+
* @param exceptions - Array of domain names (e.g., ["example.com", "trusted-site.org"])
|
|
9
|
+
*/
|
|
10
|
+
export declare function setNoFollowExceptions(exceptions: string[]): void;
|
|
11
|
+
/**
|
|
12
|
+
* Creates an isolated Marked instance with custom configuration.
|
|
13
|
+
* V17 best practice: Use instance-scoped configuration to avoid global mutations.
|
|
14
|
+
* @param cdnConfig - Optional CDN configuration for image URL transformation
|
|
15
|
+
* @returns Configured Marked instance
|
|
16
|
+
*/
|
|
17
|
+
export declare function createMarked(cdnConfig?: CDNConfig): Marked;
|
|
18
|
+
/**
|
|
19
|
+
* Convert markdown to sanitized HTML
|
|
20
|
+
* @param markdownContent - Raw markdown string
|
|
21
|
+
* @param cdnConfig - Optional CDN configuration
|
|
22
|
+
* @returns Sanitized HTML string
|
|
23
|
+
*/
|
|
24
|
+
export declare function convertMarkdownToHtml(markdownContent: string, cdnConfig?: CDNConfig): string;
|
|
25
|
+
/**
|
|
26
|
+
* Extract excerpt from markdown content
|
|
27
|
+
* Removes headings, code blocks, and formatting to create plain text excerpt
|
|
28
|
+
* @param content - Raw markdown content
|
|
29
|
+
* @param maxLength - Maximum length of excerpt (default: 200)
|
|
30
|
+
* @returns Plain text excerpt
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractExcerpt(content: string, maxLength?: number): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontmatter and business location validators
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationError {
|
|
5
|
+
file: string;
|
|
6
|
+
type: "yaml" | "missing_field" | "file_not_found" | "unknown" | "validation";
|
|
7
|
+
message: string;
|
|
8
|
+
suggestion?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Validate business location format
|
|
12
|
+
* Required fields: type, name, address, lat/lng (NOT latitude/longitude)
|
|
13
|
+
* @param business - Business location data (can be array or single object)
|
|
14
|
+
* @param filePath - File path for error reporting
|
|
15
|
+
* @returns ValidationError if invalid, null if valid
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateBusinessLocation(business: any, filePath: string): ValidationError | null;
|
|
18
|
+
/**
|
|
19
|
+
* Validate that tags don't contain spaces (must use hyphens)
|
|
20
|
+
* @param tags - Array of tag strings
|
|
21
|
+
* @param filePath - File path for error reporting
|
|
22
|
+
* @returns ValidationError if invalid, null if valid
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateTags(tags: string[], filePath: string): ValidationError | null;
|
|
25
|
+
/**
|
|
26
|
+
* Check for deprecated 'location' field (should use 'business' instead)
|
|
27
|
+
* @param data - Frontmatter data
|
|
28
|
+
* @param filePath - File path for error reporting
|
|
29
|
+
* @returns ValidationError if found, null otherwise
|
|
30
|
+
*/
|
|
31
|
+
export declare function checkDeprecatedLocationField(data: any, filePath: string): ValidationError | null;
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Markdown utilities - Main export file
|
|
3
|
+
* Re-exports from modular components for backward compatibility
|
|
4
|
+
*/
|
|
5
|
+
import type { Post, CDNConfig } from "../types";
|
|
6
|
+
import { convertMarkdownToHtml, extractExcerpt, setNoFollowExceptions } from "./markdown/parser";
|
|
7
|
+
import type { ValidationError } from "./markdown/validators";
|
|
8
|
+
export { setNoFollowExceptions, extractExcerpt, convertMarkdownToHtml };
|
|
9
|
+
export type { ValidationError as ParseError };
|
|
11
10
|
export interface ParseMarkdownResult {
|
|
12
11
|
post: Post | null;
|
|
13
|
-
error:
|
|
12
|
+
error: ValidationError | null;
|
|
14
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse a markdown file with frontmatter validation
|
|
16
|
+
* @param filePath - Path to markdown file
|
|
17
|
+
* @param cdnConfig - Optional CDN configuration
|
|
18
|
+
* @returns ParseMarkdownResult with post data or error
|
|
19
|
+
*/
|
|
15
20
|
export declare function parseMarkdownFile(filePath: string, cdnConfig?: CDNConfig): Promise<ParseMarkdownResult>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination utilities
|
|
3
|
+
*/
|
|
4
|
+
export interface PaginationData {
|
|
5
|
+
currentPage: number;
|
|
6
|
+
totalPages: number;
|
|
7
|
+
hasNextPage: boolean;
|
|
8
|
+
hasPrevPage: boolean;
|
|
9
|
+
nextPage: number | null;
|
|
10
|
+
prevPage: number | null;
|
|
11
|
+
pageSize: number;
|
|
12
|
+
totalItems: number;
|
|
13
|
+
pagePath: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create pagination data for a list of items
|
|
17
|
+
* @param items - Array of items to paginate
|
|
18
|
+
* @param currentPage - Current page number (1-indexed)
|
|
19
|
+
* @param pageSize - Number of items per page
|
|
20
|
+
* @param pagePath - Base path for pagination (e.g., "/", "/tags/tech/")
|
|
21
|
+
* @returns Pagination data object
|
|
22
|
+
*/
|
|
23
|
+
export declare function createPagination<T>(items: T[], currentPage: number, pageSize: number, pagePath: string): PaginationData;
|
|
24
|
+
/**
|
|
25
|
+
* Get paginated slice of items for a specific page
|
|
26
|
+
* @param items - Array of items to paginate
|
|
27
|
+
* @param page - Page number (1-indexed)
|
|
28
|
+
* @param pageSize - Number of items per page
|
|
29
|
+
* @returns Slice of items for the requested page
|
|
30
|
+
*/
|
|
31
|
+
export declare function getPaginatedItems<T>(items: T[], page: number, pageSize: number): T[];
|
|
32
|
+
/**
|
|
33
|
+
* Calculate total number of pages needed for items
|
|
34
|
+
* @param totalItems - Total number of items
|
|
35
|
+
* @param pageSize - Number of items per page
|
|
36
|
+
* @returns Total number of pages
|
|
37
|
+
*/
|
|
38
|
+
export declare function getTotalPages(totalItems: number, pageSize: number): number;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XML building utilities for RSS and Sitemap generation
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Escape special characters in XML text to prevent CDATA issues
|
|
6
|
+
* @param text - Text to escape
|
|
7
|
+
* @returns Escaped XML text
|
|
8
|
+
*/
|
|
9
|
+
export declare function escapeXml(text: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Build XML sitemap URL entry
|
|
12
|
+
* @param loc - URL location
|
|
13
|
+
* @param lastmod - Last modification date (ISO string)
|
|
14
|
+
* @param changefreq - Change frequency
|
|
15
|
+
* @param priority - Priority (0.0 to 1.0)
|
|
16
|
+
* @returns XML string for sitemap URL entry
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildSitemapUrl(loc: string, lastmod: string, changefreq: string, priority: number): string;
|
|
19
|
+
/**
|
|
20
|
+
* Calculate priority based on content freshness
|
|
21
|
+
* @param date - Content date (ISO string)
|
|
22
|
+
* @param basePriority - Base priority value
|
|
23
|
+
* @param now - Current time (default: Date.now())
|
|
24
|
+
* @returns Adjusted priority value (0.0 to 1.0)
|
|
25
|
+
*/
|
|
26
|
+
export declare function calculateFreshnessPriority(date: string, basePriority: number, now?: number): number;
|
|
27
|
+
/**
|
|
28
|
+
* Build RSS item with all metadata
|
|
29
|
+
* @param params - RSS item parameters
|
|
30
|
+
* @returns RSS item XML string
|
|
31
|
+
*/
|
|
32
|
+
export interface RSSItemParams {
|
|
33
|
+
title: string;
|
|
34
|
+
link: string;
|
|
35
|
+
pubDate: string;
|
|
36
|
+
description: string;
|
|
37
|
+
content: string;
|
|
38
|
+
tags?: string[];
|
|
39
|
+
author?: string;
|
|
40
|
+
image?: string | null;
|
|
41
|
+
}
|
|
42
|
+
export declare function buildRSSItem(params: RSSItemParams): string;
|
package/package.json
CHANGED