bunki 0.18.1 → 0.18.5

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 CHANGED
@@ -541,6 +541,54 @@ This is useful for:
541
541
  - Testing uploads for specific years
542
542
  - Managing large image collections across multiple uploads
543
543
 
544
+ #### `--content-assets`
545
+
546
+ Upload images that are co-located with markdown files instead of the top-level `assets/` directory.
547
+
548
+ When content is organized with images living alongside the markdown:
549
+
550
+ ```
551
+ content/
552
+ ├── 2024/
553
+ │ └── _assets/
554
+ │ ├── paris-cafe.webp
555
+ │ └── eiffel-tower.webp
556
+ └── 2025/
557
+ └── _assets/
558
+ └── tokyo-ramen.webp
559
+ ```
560
+
561
+ Run:
562
+
563
+ ```bash
564
+ bunki images:push --content-assets
565
+ ```
566
+
567
+ This uploads each file with the S3 key `{year}/{filename}` — the `_assets/` segment is stripped. For example, `content/2024/_assets/paris-cafe.webp` becomes key `2024/paris-cafe.webp`, accessible at `https://cdn.example.com/2024/paris-cafe.webp`.
568
+
569
+ > [!IMPORTANT]
570
+ > Always use CDN URLs in your markdown, not relative `_assets/` paths. Relative paths cause the image files to be bundled into your Cloudflare Workers deployment instead of served from R2.
571
+
572
+ ```markdown
573
+ <!-- ❌ Causes image to be bundled into Workers -->
574
+ ![Paris](../2024/_assets/paris-cafe.webp)
575
+
576
+ <!-- ✅ Served from R2 CDN -->
577
+ ![Paris](https://cdn.example.com/2024/paris-cafe.webp)
578
+ ```
579
+
580
+ #### `--content-assets-dir <dir>`
581
+
582
+ Override the assets subdirectory name. Defaults to `_assets` (or `contentAssets.assetsDir` in `bunki.config.ts`).
583
+
584
+ ```bash
585
+ # Use _images instead of _assets
586
+ bunki images:push --content-assets --content-assets-dir _images
587
+
588
+ # Use any custom name
589
+ bunki images:push --content-assets --content-assets-dir media
590
+ ```
591
+
544
592
  ### Complete Examples
545
593
 
546
594
  #### Cloudflare R2 Setup
@@ -746,6 +794,56 @@ Ensure all required environment variables are set. Check `bunki.config.ts` and y
746
794
 
747
795
  ### Advanced Configuration
748
796
 
797
+ #### Content Assets Configuration
798
+
799
+ Configure co-located content assets in `bunki.config.ts`:
800
+
801
+ ```typescript
802
+ import { SiteConfig } from "bunki";
803
+
804
+ export default (): SiteConfig => ({
805
+ title: "My Blog",
806
+ baseUrl: "https://example.com",
807
+ domain: "example.com",
808
+
809
+ // Default S3 config (used by bunki images:push)
810
+ s3: {
811
+ accessKeyId: process.env.S3_ACCESS_KEY_ID || "",
812
+ secretAccessKey: process.env.S3_SECRET_ACCESS_KEY || "",
813
+ bucket: "my-site-assets",
814
+ endpoint: process.env.S3_ENDPOINT,
815
+ region: "auto",
816
+ publicUrl: "https://assets.example.com",
817
+ },
818
+
819
+ // Content assets: images stored alongside markdown in content/{year}/_images/
820
+ contentAssets: {
821
+ // Directory name within content/{year}/ (default: "_assets")
822
+ assetsDir: "_images",
823
+
824
+ // Optional: use a separate R2 bucket for content assets
825
+ s3: {
826
+ accessKeyId: process.env.IMG_ACCESS_KEY_ID || "",
827
+ secretAccessKey: process.env.IMG_SECRET_ACCESS_KEY || "",
828
+ bucket: "my-blog-images",
829
+ endpoint: process.env.S3_ENDPOINT,
830
+ region: "auto",
831
+ publicUrl: "https://img.example.com",
832
+ },
833
+ },
834
+ });
835
+ ```
836
+
837
+ Then upload content assets:
838
+
839
+ ```bash
840
+ # Uses contentAssets.assetsDir and contentAssets.s3 from config
841
+ bunki images:push --content-assets
842
+
843
+ # Override the directory name at the CLI level
844
+ bunki images:push --content-assets --content-assets-dir _media
845
+ ```
846
+
749
847
  #### Custom Domain per Bucket
750
848
 
751
849
  If you have multiple S3 buckets with different custom domains:
@@ -7,9 +7,11 @@ interface ImagesPushDeps {
7
7
  }
8
8
  export declare function handleImagesPushCommand(options: {
9
9
  domain?: string;
10
- images: string;
10
+ images?: string;
11
11
  outputJson?: string;
12
12
  minYear?: string;
13
+ contentAssets?: boolean;
14
+ contentAssetsDir?: string;
13
15
  }, deps?: ImagesPushDeps): Promise<void>;
14
16
  export declare function registerImagesPushCommand(program: Command): Command;
15
17
  export {};
@@ -0,0 +1,9 @@
1
+ import { Command } from "commander";
2
+ export declare function handleValidateMediaCommand(options: {
3
+ contentDir?: string;
4
+ fix?: boolean;
5
+ }, deps?: {
6
+ logger: Console;
7
+ exit: (code: number) => never;
8
+ }): Promise<void>;
9
+ export declare function registerValidateMediaCommand(program: Command): Command;