bunki 0.21.1 → 0.22.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/dist/parser.d.ts CHANGED
@@ -14,4 +14,6 @@ export interface ParseResult {
14
14
  */
15
15
  export declare function parseMarkdownFiles(filePaths: string[], cdnConfig?: CDNConfig): Promise<ParsedMarkdownFile[]>;
16
16
  export declare function parseMarkdownDirectory(contentDir: string, strictMode?: boolean, cdnConfig?: CDNConfig): Promise<Post[]>;
17
+ /** Validate the whole collection while parsing only files without reusable posts. */
18
+ export declare function parseMarkdownCollection(markdownFiles: string[], strictMode?: boolean, cdnConfig?: CDNConfig, cachedPosts?: ReadonlyMap<string, Post>): Promise<ParsedMarkdownFile[]>;
17
19
  export {};
@@ -9,6 +9,8 @@ export declare class SiteGenerator {
9
9
  private metrics;
10
10
  private cache;
11
11
  private incrementalMode;
12
+ private stylesheetInvalidated;
13
+ private readonly templateEngine;
12
14
  constructor(options: GeneratorOptions);
13
15
  /**
14
16
  * Enable incremental builds
@@ -30,12 +32,6 @@ export declare class SiteGenerator {
30
32
  * Parse content (full or incremental)
31
33
  */
32
34
  private parseContent;
33
- /**
34
- * Group posts by year (Pacific timezone)
35
- * @param posts - Array of posts
36
- * @returns Posts grouped by year
37
- */
38
- private groupPostsByYear;
39
35
  /**
40
36
  * Calculate output statistics (file count and total size)
41
37
  */
@@ -0,0 +1,3 @@
1
+ import type { Post, Site, SiteConfig } from "./types";
2
+ export declare function createSiteModel(posts: readonly Post[], config: SiteConfig, tagDescriptions?: Readonly<Record<string, string>>): Site;
3
+ export declare function groupPostsByYear(posts: readonly Post[]): Record<string, Post[]>;
package/dist/types.d.ts CHANGED
@@ -121,7 +121,9 @@ export interface CSSConfig {
121
121
  input: string;
122
122
  /** Output CSS file path (relative to output directory) */
123
123
  output: string;
124
- /** PostCSS config file path (relative to project root) */
124
+ /** CSS engine; defaults to Bun unless a PostCSS config is supplied or detected. */
125
+ processor?: "bun" | "postcss";
126
+ /** PostCSS config file path (relative to project root); selects PostCSS in auto mode. */
125
127
  postcssConfig?: string;
126
128
  /** Whether to enable CSS processing */
127
129
  enabled: boolean;
@@ -155,7 +157,7 @@ export interface SiteConfig {
155
157
  domain: string;
156
158
  /** Optional author name used by config templates and feeds */
157
159
  author?: string;
158
- /** Optional content directory override */
160
+ /** Content directory used by validate; generate uses its --content option */
159
161
  contentDir?: string;
160
162
  /** Optional templates directory override */
161
163
  templatesDir?: string;
@@ -169,7 +171,7 @@ export interface SiteConfig {
169
171
  cdn?: CDNConfig;
170
172
  /** Optional number of tags to display on homepage (sorted by count). If not set, all tags are shown */
171
173
  maxTagsOnHomepage?: number;
172
- /** Optional list of domains to exclude from nofollow attribute. Links to these domains will have follow attribute. */
174
+ /** Domains whose links should omit nofollow; no explicit follow attribute is added */
173
175
  noFollowExceptions?: string[];
174
176
  /** RSS feed language code (default: en-US) */
175
177
  rssLanguage?: string;
@@ -202,6 +204,10 @@ export interface SiteConfig {
202
204
  * Options for initializing the site generator
203
205
  */
204
206
  export interface GeneratorOptions {
207
+ /** Config file used by the caller, for incremental cache invalidation */
208
+ configFile?: string;
209
+ /** Project root used for config, cache, and project-relative assets */
210
+ rootDir?: string;
205
211
  /** Directory containing markdown content */
206
212
  contentDir: string;
207
213
  /** Directory where generated files will be output */
@@ -279,7 +285,7 @@ export interface ImageUploader {
279
285
  * @param keyTransform Optional function to transform relative file path into S3 key
280
286
  * @returns Record of S3 keys to their public URLs
281
287
  */
282
- uploadImages(imagesDir: string, minYear?: number, keyTransform?: (relativePath: string) => string, maxYear?: number): Promise<Record<string, string>>;
288
+ uploadImages(imagesDir: string, minYear?: number, keyTransform?: (relativePath: string) => string, maxYear?: number, includeFile?: (relativePath: string) => boolean): Promise<Record<string, string>>;
283
289
  }
284
290
  /**
285
291
  * S3 configuration type
@@ -20,6 +20,8 @@ export interface BuildCache {
20
20
  files: Record<string, CacheEntry>;
21
21
  /** Config file hash */
22
22
  configHash?: string;
23
+ /** Resolved configuration, including environment-derived and programmatic values */
24
+ optionsHash?: string;
23
25
  /** Last full build timestamp */
24
26
  lastFullBuild?: number;
25
27
  }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Map async work with bounded concurrency, preserving input order.
3
+ * On failure, stop scheduling and drain active work before rejecting.
4
+ */
5
+ export declare function mapConcurrent<T, R>(items: readonly T[], transform: (item: T, index: number) => Promise<R>, concurrency?: number): Promise<R[]>;
@@ -1,4 +1,7 @@
1
1
  import type { CSSConfig } from "../types";
2
+ export declare class PostCSSProcessingError extends Error {
3
+ constructor(cause: unknown);
4
+ }
2
5
  export interface CSSProcessorOptions {
3
6
  /** CSS configuration */
4
7
  css: CSSConfig;
@@ -18,7 +21,7 @@ export interface CSSProcessResult {
18
21
  hash?: string;
19
22
  }
20
23
  /**
21
- * Process CSS using PostCSS directly
24
+ * Process CSS with Bun, or PostCSS for projects with a plugin configuration
22
25
  * Throws on error - no fallback
23
26
  * Returns output path (with hash if hashing enabled)
24
27
  */
@@ -6,7 +6,7 @@
6
6
  * This is used consistently across the codebase for date handling
7
7
  *
8
8
  * @param date - Date string or Date object to convert
9
- * @returns Date object in Pacific timezone
9
+ * @returns Date whose local fields represent Pacific wall-clock time, not the original instant
10
10
  */
11
11
  export declare function toPacificTime(date: string | Date): Date;
12
12
  /**
@@ -74,10 +74,8 @@ export declare function createDir(dirPath: string): Promise<void>;
74
74
  */
75
75
  export declare function ensureDir(dirPath: string): Promise<void>;
76
76
  /**
77
- * Copy a file from source to target using Bun's zero-copy file-to-file operation
78
- *
79
- * This uses Bun.write(target, BunFile) which performs a zero-copy operation at the kernel level.
80
- * Similar to `cat source > target` but much faster than reading into memory and writing back.
77
+ * Copy a file with Bun.write without reading its contents into a JavaScript string.
78
+ * Bun selects the underlying copy mechanism for the platform and file types.
81
79
  *
82
80
  * @param sourcePath - Source file path
83
81
  * @param targetPath - Target file path
@@ -113,7 +111,7 @@ export declare function listDir(dirPath: string, recursive?: boolean): Promise<s
113
111
  * Useful for streaming writes or building large files incrementally without loading
114
112
  * everything into memory. Uses a buffered sink with configurable watermark.
115
113
  *
116
- * Zero-copy streaming to disk with backpressure handling.
114
+ * Call flush() or end() to finish writing buffered data.
117
115
  *
118
116
  * @param filePath - Path to file
119
117
  * @param highWaterMark - Buffer size in bytes (default: 1MB)
@@ -131,10 +129,7 @@ export declare function listDir(dirPath: string, recursive?: boolean): Promise<s
131
129
  */
132
130
  export declare function createFileWriter(filePath: string, highWaterMark?: number): Bun.FileSink;
133
131
  /**
134
- * Write a file to stdout using zero-copy streaming
135
- *
136
- * Similar to `cat file.txt` command. Uses Bun's zero-copy mechanism to stream
137
- * the file content directly to stdout without loading into memory.
132
+ * Write a BunFile directly to stdout without creating a JavaScript string.
138
133
  *
139
134
  * @param filePath - Path to file to output
140
135
  * @returns Promise that resolves when file is written to stdout
@@ -13,13 +13,7 @@ export declare class S3Uploader implements Uploader, ImageUploader {
13
13
  * @returns The public URL for the file
14
14
  */
15
15
  private getPublicUrl;
16
- /**
17
- * Execute async tasks with concurrency limit
18
- * @param tasks Array of task functions that return promises
19
- * @param concurrency Maximum number of concurrent tasks
20
- */
21
- private executeWithConcurrency;
22
- uploadImages(imagesDir: string, minYear?: number, keyTransform?: (relativePath: string) => string, maxYear?: number): Promise<Record<string, string>>;
16
+ uploadImages(imagesDir: string, minYear?: number, keyTransform?: (relativePath: string) => string, maxYear?: number, includeFile?: (relativePath: string) => boolean): Promise<Record<string, string>>;
23
17
  }
24
18
  /**
25
19
  * Create an S3 uploader
@@ -13,7 +13,7 @@ import nunjucks from "nunjucks";
13
13
  * @example
14
14
  * ```typescript
15
15
  * const env = createTemplateEngine("./templates");
16
- * const html = nunjucks.render("index.njk", { site, posts });
16
+ * const html = env.render("index.njk", { site, posts });
17
17
  * ```
18
18
  */
19
19
  export declare function createTemplateEngine(templatesDir: string, watch?: boolean): nunjucks.Environment;
@@ -7,6 +7,7 @@
7
7
  * @returns Escaped XML text
8
8
  */
9
9
  export declare function escapeXml(text: string): string;
10
+ export declare function cdata(text: string): string;
10
11
  /**
11
12
  * Build XML sitemap URL entry
12
13
  * @param loc - URL location
@@ -0,0 +1,17 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1200" height="320" viewBox="0 0 1200 320" role="img" aria-labelledby="title description">
2
+ <title id="title">Bunki</title>
3
+ <desc id="description">An open book beside the Bunki wordmark on warm cream. Your words, on your own site.</desc>
4
+ <rect width="1200" height="320" rx="24" fill="#F6F1E7"/>
5
+ <path d="M68 250H1132" stroke="#D8CFC0"/>
6
+ <g transform="translate(72 66)">
7
+ <rect width="144" height="144" rx="32" fill="#293E36"/>
8
+ <path d="M30 40Q51 35 72 48Q93 35 114 40V104Q93 99 72 112Q51 99 30 104Z" fill="#F6F1E7"/>
9
+ <path d="M72 49V111" stroke="#293E36" stroke-width="4"/>
10
+ <path d="M42 58L59 62M42 72L59 76M85 62L102 58M85 76L102 72" stroke="#A9B9A7" stroke-width="4" stroke-linecap="round"/>
11
+ <circle cx="116" cy="28" r="12" fill="#D7794E"/>
12
+ </g>
13
+ <text x="252" y="153" fill="#293E36" font-family="Georgia, 'Times New Roman', serif" font-size="100" font-weight="bold" letter-spacing="-5">bunki</text>
14
+ <text x="258" y="200" fill="#42574C" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="27">Your words, on your own site.</text>
15
+ <text x="74" y="286" fill="#526357" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="16" letter-spacing="2">MARKDOWN · BUN · STATIC HTML</text>
16
+ <path d="M956 80H1108M996 108H1108M1036 136H1108" fill="none" stroke="#D8CFC0" stroke-width="3" stroke-linecap="round"/>
17
+ </svg>
@@ -0,0 +1,9 @@
1
+ # Migrating to 0.22.0 (release candidate)
2
+
3
+ Compared with npm 0.21.1, Bunki now requires Bun 1.4.4 or newer (previously 1.3.14). Upgrade Bun before installing.
4
+
5
+ Plain CSS now defaults to Bun’s native bundler. Review generated CSS and asset URLs after upgrading: local imports are bundled and assets may be embedded. To retain the PostCSS engine, set `css.processor: "postcss"` in your configuration. Existing PostCSS plugin configurations remain supported and are detected automatically; see the [CSS reference](https://github.com/kahwee/bunki/blob/main/docs/reference.md#css-configuration).
6
+
7
+ The root import now maps to the shipped `dist/index.js`. The 0.21.1 npm manifest mapped imports to `dist/index.mjs`, but that file was absent from its archive. Public API additions are additive.
8
+
9
+ This is a candidate, not a published release.
package/package.json CHANGED
@@ -1,26 +1,28 @@
1
1
  {
2
2
  "name": "bunki",
3
- "version": "0.21.1",
4
- "description": "An opinionated static site generator built with Bun featuring PostCSS integration and modern web development workflows",
3
+ "version": "0.22.0",
4
+ "packageManager": "bun@1.4.4",
5
+ "description": "Your words, on your own site. A Bun-powered static site generator for Markdown blogs, notes, and documentation.",
5
6
  "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "type": "module",
9
9
  "scripts": {
10
- "build": "bun build.js",
10
+ "build": "bun run typecheck && bun run build:artifacts",
11
11
  "dev": "bun run --watch src/index.ts",
12
12
  "test": "bun test",
13
13
  "test:coverage": "bun test --coverage --coverage-reporter=lcov",
14
14
  "test:watch": "bun test --watch",
15
- "format": "biome format --write .",
16
- "format:check": "biome format .",
17
- "lint": "biome check .",
18
- "lint:fix": "biome check --write .",
15
+ "benchmark": "bun scripts/benchmark-build.ts",
16
+ "format": "bun fmt .",
17
+ "format:check": "bun fmt --check .",
19
18
  "prepare": "husky",
20
- "typecheck": "bun tsc --noEmit",
19
+ "typecheck": "bun --check --tsconfig-override=tsconfig.json",
21
20
  "clean": "rm -rf dist coverage",
22
21
  "prepack": "bun run clean && bun run build",
23
- "prepublishOnly": "bun run clean && bun run build && bun run test && bun run typecheck"
22
+ "prepublishOnly": "bun run clean && bun run check",
23
+ "check:source": "bun run --parallel format:check typecheck test",
24
+ "build:artifacts": "bun --bun build.ts",
25
+ "check": "bun run check:source && bun run build:artifacts"
24
26
  },
25
27
  "bin": {
26
28
  "bunki": "dist/cli.js"
@@ -50,42 +52,34 @@
50
52
  "dependencies": {
51
53
  "commander": "^15.0.0",
52
54
  "gray-matter": "^4.0.3",
53
- "highlight.js": "^11.11.1",
54
- "marked": "^18.0.7",
55
+ "highlight.js": "^11.12.0",
56
+ "marked": "^18.1.3",
55
57
  "marked-alert": "^2.1.2",
56
58
  "marked-highlight": "^2.2.4",
57
59
  "nunjucks": "^3.2.4",
58
- "postcss": "^8.5.22",
59
- "postcss-cli": "^11.0.1",
60
- "sanitize-html": "^2.17.6",
60
+ "postcss": "^8.5.32",
61
+ "postcss-cli": "^12.0.0",
62
+ "sanitize-html": "^2.18.1",
63
+ "serialize-javascript": "7.1.4",
61
64
  "slugify": "^1.6.9"
62
65
  },
63
66
  "devDependencies": {
64
- "@biomejs/biome": "^2.5.5",
65
- "@tailwindcss/postcss": "^4.3.3",
66
67
  "@types/nunjucks": "^3.2.6",
67
- "@types/sanitize-html": "^2.16.1",
68
- "autoprefixer": "^10.5.4",
69
- "bun-types": "^1.3.14",
68
+ "@types/sanitize-html": "^2.16.2",
69
+ "@types/serialize-javascript": "5.0.4",
70
+ "bun-types": "^1.4.4",
70
71
  "husky": "^9.1.7",
71
- "tailwindcss": "^4.3.3",
72
- "typescript": "^7.0.2"
73
- },
74
- "peerDependencies": {
75
- "postcss": "^8.0.0"
76
- },
77
- "peerDependenciesMeta": {
78
- "postcss": {
79
- "optional": true
80
- }
72
+ "typescript": "7.0.2"
81
73
  },
82
74
  "files": [
83
75
  "dist",
76
+ "docs/assets",
77
+ "docs/migration.md",
84
78
  "LICENSE",
85
79
  "README.md"
86
80
  ],
87
81
  "engines": {
88
- "bun": ">=1.3.14"
82
+ "bun": ">=1.4.4"
89
83
  },
90
84
  "engineStrict": true,
91
85
  "publishConfig": {
@@ -98,10 +92,15 @@
98
92
  "exports": {
99
93
  ".": {
100
94
  "types": "./dist/index.d.ts",
101
- "import": "./dist/index.mjs",
95
+ "import": "./dist/index.js",
102
96
  "default": "./dist/index.js"
103
97
  },
104
98
  "./cli": "./dist/cli.js"
105
99
  },
106
- "sideEffects": false
100
+ "sideEffects": false,
101
+ "overrides": {
102
+ "yaml": "^2.8.3",
103
+ "picomatch": "^2.3.2",
104
+ "js-yaml": "^3.14.2"
105
+ }
107
106
  }
Binary file