bunki 0.6.0 → 0.7.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.
@@ -9,6 +9,7 @@ export declare function handleImagesPushCommand(options: {
9
9
  domain?: string;
10
10
  images: string;
11
11
  outputJson?: string;
12
+ minYear?: string;
12
13
  }, deps?: ImagesPushDeps): Promise<void>;
13
14
  export declare function registerImagesPushCommand(program: Command): Command;
14
15
  export {};
package/dist/cli.js CHANGED
@@ -28185,7 +28185,7 @@ function getDefaultConfig() {
28185
28185
  return base;
28186
28186
  }
28187
28187
  async function createDefaultConfig(configPath = DEFAULT_CONFIG_FILE) {
28188
- if (await configExists()) {
28188
+ if (await configExists(configPath)) {
28189
28189
  console.log(`Config file already exists`);
28190
28190
  return false;
28191
28191
  }
@@ -28243,15 +28243,6 @@ async function processCSS(options2) {
28243
28243
  } catch (error) {
28244
28244
  throw new Error(`CSS input file not found: ${inputPath}`);
28245
28245
  }
28246
- let postcssConfigExists = false;
28247
- try {
28248
- await fs.promises.access(postcssConfigPath);
28249
- postcssConfigExists = true;
28250
- } catch (error) {
28251
- if (verbose) {
28252
- console.log(`PostCSS config not found at ${postcssConfigPath}, will fallback to simple copy`);
28253
- }
28254
- }
28255
28246
  const outputDirPath = path2.dirname(outputPath);
28256
28247
  await fs.promises.mkdir(outputDirPath, { recursive: true });
28257
28248
  if (verbose) {
@@ -28260,71 +28251,40 @@ async function processCSS(options2) {
28260
28251
  console.log(`Output: ${outputPath}`);
28261
28252
  console.log(`Config: ${postcssConfigPath}`);
28262
28253
  }
28263
- if (!postcssConfigExists) {
28264
- await fs.promises.copyFile(inputPath, outputPath);
28265
- if (verbose)
28266
- console.log("Copied CSS without PostCSS config");
28267
- return;
28268
- }
28269
- const runPostCSS = (configPathToUse) => {
28270
- return new Promise((resolve, reject) => {
28271
- const args = ["postcss", inputPath, "-o", outputPath];
28272
- if (configPathToUse && fs.existsSync(configPathToUse)) {
28273
- args.push("--config", configPathToUse);
28274
- }
28275
- const postcss = spawn("bunx", args, {
28276
- stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
28277
- cwd: projectRoot
28254
+ await runPostCSS(inputPath, outputPath, postcssConfigPath, projectRoot, verbose);
28255
+ }
28256
+ function runPostCSS(inputPath, outputPath, configPath, projectRoot, verbose) {
28257
+ return new Promise((resolve, reject) => {
28258
+ const args = [
28259
+ "postcss",
28260
+ inputPath,
28261
+ "-o",
28262
+ outputPath,
28263
+ "--config",
28264
+ configPath
28265
+ ];
28266
+ const postcss = spawn("bunx", args, {
28267
+ stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
28268
+ cwd: projectRoot
28269
+ });
28270
+ let errorOutput = "";
28271
+ if (!verbose) {
28272
+ postcss.stderr?.on("data", (data) => {
28273
+ errorOutput += data.toString();
28278
28274
  });
28279
- let errorOutput = "";
28280
- if (!verbose) {
28281
- postcss.stderr?.on("data", (data) => {
28282
- errorOutput += data.toString();
28283
- });
28275
+ }
28276
+ postcss.on("close", (code) => {
28277
+ if (code === 0) {
28278
+ if (verbose)
28279
+ console.log("\u2705 CSS build completed successfully!");
28280
+ return resolve();
28284
28281
  }
28285
- postcss.on("close", async (code) => {
28286
- if (code === 0) {
28287
- if (verbose)
28288
- console.log("\u2705 CSS build completed successfully!");
28289
- return resolve();
28290
- }
28291
- if (/module is not defined in ES module scope/i.test(errorOutput) && configPathToUse.endsWith(".js")) {
28292
- const cjsPath = configPathToUse.replace(/\.js$/, ".cjs");
28293
- try {
28294
- if (!fs.existsSync(cjsPath)) {
28295
- const original = await fs.promises.readFile(configPathToUse, "utf-8");
28296
- await fs.promises.writeFile(cjsPath, original, "utf-8");
28297
- if (verbose) {
28298
- console.log(`Retrying PostCSS with converted CommonJS config at ${cjsPath}`);
28299
- }
28300
- }
28301
- return resolve(runPostCSS(cjsPath));
28302
- } catch (e) {
28303
- if (verbose)
28304
- console.warn("CJS fallback failed, copying CSS.");
28305
- await fs.promises.copyFile(inputPath, outputPath);
28306
- return resolve();
28307
- }
28308
- }
28309
- if (verbose) {
28310
- console.warn(`PostCSS failed (code ${code}). Falling back to simple copy. Error: ${errorOutput.trim()}`);
28311
- }
28312
- try {
28313
- await fs.promises.copyFile(inputPath, outputPath);
28314
- resolve();
28315
- } catch (copyErr) {
28316
- reject(new Error(`CSS build failed with code ${code} and fallback copy also failed: ${copyErr.message}`));
28317
- }
28318
- });
28319
- postcss.on("error", (err) => {
28320
- if (verbose) {
28321
- console.warn(`Failed to start PostCSS process (${err.message}). Falling back to copy.`);
28322
- }
28323
- fs.promises.copyFile(inputPath, outputPath).then(() => resolve()).catch((copyErr) => reject(new Error(`Failed to start PostCSS and fallback copy failed: ${copyErr.message}`)));
28324
- });
28282
+ reject(new Error(`PostCSS failed with exit code ${code}: ${errorOutput.trim()}`));
28325
28283
  });
28326
- };
28327
- await runPostCSS(postcssConfigPath);
28284
+ postcss.on("error", (err) => {
28285
+ reject(new Error(`Failed to start PostCSS: ${err.message}`));
28286
+ });
28287
+ });
28328
28288
  }
28329
28289
  async function watchCSS(options2) {
28330
28290
  const { css, projectRoot, verbose = false } = options2;
@@ -28422,6 +28382,7 @@ import path5 from "path";
28422
28382
  // src/utils/file-utils.ts
28423
28383
  var {Glob } = globalThis.Bun;
28424
28384
  import path4 from "path";
28385
+ import { mkdir } from "fs/promises";
28425
28386
  async function findFilesByPattern(pattern, directory, absolute = true) {
28426
28387
  const glob = new Glob(pattern);
28427
28388
  const files = [];
@@ -28434,8 +28395,20 @@ async function findFilesByPattern(pattern, directory, absolute = true) {
28434
28395
  return files;
28435
28396
  }
28436
28397
  async function fileExists(filePath) {
28437
- const file = Bun.file(filePath);
28438
- return await file.exists();
28398
+ try {
28399
+ const file = Bun.file(filePath);
28400
+ return await file.exists();
28401
+ } catch {
28402
+ return false;
28403
+ }
28404
+ }
28405
+ async function isDirectory(dirPath) {
28406
+ try {
28407
+ const stat = await Bun.file(dirPath).stat();
28408
+ return stat?.isDirectory() ?? false;
28409
+ } catch {
28410
+ return false;
28411
+ }
28439
28412
  }
28440
28413
  async function readFileAsText(filePath) {
28441
28414
  try {
@@ -28452,18 +28425,33 @@ async function readFileAsText(filePath) {
28452
28425
  function getBaseFilename(filePath, extension = ".md") {
28453
28426
  return path4.basename(filePath, extension);
28454
28427
  }
28455
- async function ensureDir(dirPath) {
28428
+ async function createDir(dirPath) {
28456
28429
  try {
28457
- await Bun.write(`${dirPath}/.gitkeep`, "");
28458
- } catch (error) {}
28430
+ await mkdir(dirPath, { recursive: true });
28431
+ } catch (error) {
28432
+ if (await isDirectory(dirPath)) {
28433
+ return;
28434
+ }
28435
+ if (await fileExists(dirPath)) {
28436
+ throw new Error(`Path exists but is not a directory: ${dirPath}`);
28437
+ }
28438
+ console.error(`Error creating directory ${dirPath}:`, error);
28439
+ throw error;
28440
+ }
28441
+ }
28442
+ async function ensureDir(dirPath) {
28443
+ return createDir(dirPath);
28459
28444
  }
28460
28445
  async function copyFile(sourcePath, targetPath) {
28461
28446
  try {
28462
28447
  const sourceFile = Bun.file(sourcePath);
28463
- const content = await sourceFile.arrayBuffer();
28464
- await Bun.write(targetPath, content);
28448
+ if (!await sourceFile.exists()) {
28449
+ throw new Error(`Source file does not exist: ${sourcePath}`);
28450
+ }
28451
+ await Bun.write(targetPath, sourceFile);
28465
28452
  } catch (error) {
28466
28453
  console.error(`Error copying file from ${sourcePath} to ${targetPath}:`, error);
28454
+ throw error;
28467
28455
  }
28468
28456
  }
28469
28457
 
@@ -33614,8 +33602,11 @@ class S3Uploader {
33614
33602
  }
33615
33603
  }
33616
33604
  }
33617
- async uploadImages(imagesDir) {
33605
+ async uploadImages(imagesDir, minYear) {
33618
33606
  console.log(`[S3] Uploading all images from ${imagesDir} to bucket ${this.s3Config.bucket}...`);
33607
+ if (minYear) {
33608
+ console.log(`[S3] Filtering images from year ${minYear} onwards`);
33609
+ }
33619
33610
  const imageUrls = {};
33620
33611
  try {
33621
33612
  console.log(`[S3] Checking if directory exists: ${imagesDir}`);
@@ -33658,8 +33649,19 @@ class S3Uploader {
33658
33649
  cwd: imagesDir,
33659
33650
  absolute: false
33660
33651
  })) {
33661
- console.log(`[S3] Found image file: ${file}`);
33662
- files.push(file);
33652
+ if (minYear) {
33653
+ const yearMatch = file.match(/^(\d{4})\//);
33654
+ if (yearMatch) {
33655
+ const fileYear = parseInt(yearMatch[1], 10);
33656
+ if (fileYear >= minYear) {
33657
+ console.log(`[S3] Found image file: ${file}`);
33658
+ files.push(file);
33659
+ }
33660
+ }
33661
+ } else {
33662
+ console.log(`[S3] Found image file: ${file}`);
33663
+ files.push(file);
33664
+ }
33663
33665
  }
33664
33666
  const imageFiles = files;
33665
33667
  if (imageFiles.length === 0) {
@@ -33734,8 +33736,11 @@ async function uploadImages(options2 = {}) {
33734
33736
  };
33735
33737
  }
33736
33738
  console.log(`Uploading images from ${imagesDir} to bucket ${s3Config.bucket}`);
33739
+ if (options2.minYear) {
33740
+ console.log(`Filtering images from year ${options2.minYear} onwards`);
33741
+ }
33737
33742
  const uploader = createUploader(s3Config);
33738
- const imageUrlMap = await uploader.uploadImages(imagesDir);
33743
+ const imageUrlMap = await uploader.uploadImages(imagesDir, options2.minYear);
33739
33744
  if (options2.outputJson) {
33740
33745
  const outputFile = path8.resolve(options2.outputJson);
33741
33746
  await Bun.write(outputFile, JSON.stringify(imageUrlMap, null, 2));
@@ -33753,7 +33758,7 @@ Image upload completed successfully!`);
33753
33758
  return imageUrlMap;
33754
33759
  } catch (error) {
33755
33760
  console.error("Error uploading images:", error);
33756
- process.exit(1);
33761
+ throw error;
33757
33762
  }
33758
33763
  }
33759
33764
 
@@ -33768,7 +33773,8 @@ async function handleImagesPushCommand(options2, deps = defaultDeps3) {
33768
33773
  await deps.uploadImages({
33769
33774
  domain: options2.domain,
33770
33775
  images: options2.images,
33771
- outputJson: options2.outputJson
33776
+ outputJson: options2.outputJson,
33777
+ minYear: options2.minYear ? parseInt(options2.minYear, 10) : undefined
33772
33778
  });
33773
33779
  } catch (error) {
33774
33780
  deps.logger.error("Error uploading images:", error);
@@ -33776,7 +33782,7 @@ async function handleImagesPushCommand(options2, deps = defaultDeps3) {
33776
33782
  }
33777
33783
  }
33778
33784
  function registerImagesPushCommand(program2) {
33779
- return program2.command("images:push").description("Upload images to S3-compatible storage").option("-d, --domain <domain>", "Domain name for bucket identification (defaults to domain in bunki.config.ts)").option("-i, --images <dir>", "Images directory path", DEFAULT_IMAGES_DIR).option("--output-json <file>", "Output URL mapping to JSON file").action(async (options2) => {
33785
+ return program2.command("images:push").description("Upload images to S3-compatible storage").option("-d, --domain <domain>", "Domain name for bucket identification (defaults to domain in bunki.config.ts)").option("-i, --images <dir>", "Images directory path", DEFAULT_IMAGES_DIR).option("--output-json <file>", "Output URL mapping to JSON file").option("--min-year <year>", "Only upload images from the specified year onwards (e.g., 2023 uploads 2023, 2024, etc.)").action(async (options2) => {
33780
33786
  await handleImagesPushCommand(options2);
33781
33787
  });
33782
33788
  }
@@ -34252,56 +34258,56 @@ function getDefaultCss() {
34252
34258
  }
34253
34259
  function getSamplePost() {
34254
34260
  return `---
34255
- title: Welcome to Bunki
34256
- date: ${new Date().toISOString()}
34257
- tags: [getting-started, bunki]
34258
- ---
34261
+ title: Welcome to Bunki
34262
+ date: 2025-01-15T12:00:00Z
34263
+ tags: [getting-started, bunki]
34264
+ ---
34259
34265
 
34260
- # Welcome to Your New Bunki Site
34266
+ # Welcome to Your New Bunki Site
34261
34267
 
34262
- This is a sample blog post to help you get started with Bunki. You can edit this file or create new markdown files in the \`content\` directory.
34268
+ This is a sample blog post to help you get started with Bunki. You can edit this file or create new markdown files in the \`content\` directory.
34263
34269
 
34264
- ## Features
34270
+ ## Features
34265
34271
 
34266
- - Markdown support with frontmatter
34267
- - Syntax highlighting for code blocks
34268
- - Tag-based organization
34269
- - Pagination for post listings
34270
- - RSS feed generation
34271
- - Sitemap generation
34272
+ - Markdown support with frontmatter
34273
+ - Syntax highlighting for code blocks
34274
+ - Tag-based organization
34275
+ - Pagination for post listings
34276
+ - RSS feed generation
34277
+ - Sitemap generation
34272
34278
 
34273
- ## Adding Content
34279
+ ## Adding Content
34274
34280
 
34275
- Create new markdown files in the \`content\` directory with frontmatter like this:
34281
+ Create new markdown files in the \`content\` directory with frontmatter like this:
34276
34282
 
34277
- \`\`\`markdown
34278
- ---
34279
- title: Your Post Title
34280
- date: 2025-01-01T12:00:00Z
34281
- tags: [tag1, tag2]
34282
- ---
34283
+ \`\`\`markdown
34284
+ ---
34285
+ title: Your Post Title
34286
+ date: 2025-01-01T12:00:00Z
34287
+ tags: [tag1, tag2]
34288
+ ---
34283
34289
 
34284
- Your post content goes here...
34285
- \`\`\`
34290
+ Your post content goes here...
34291
+ \`\`\`
34286
34292
 
34287
- ## Code Highlighting
34293
+ ## Code Highlighting
34288
34294
 
34289
- Bunki supports syntax highlighting for code blocks:
34295
+ Bunki supports syntax highlighting for code blocks:
34290
34296
 
34291
- \`\`\`javascript
34292
- function hello() {
34293
- console.log('Hello, world!');
34294
- }
34295
- \`\`\`
34297
+ \`\`\`javascript
34298
+ function hello() {
34299
+ console.log('Hello, world!');
34300
+ }
34301
+ \`\`\`
34296
34302
 
34297
- ## Next Steps
34303
+ ## Next Steps
34298
34304
 
34299
- 1. Edit the site configuration in \`bunki.config.ts\`
34300
- 2. Create your own templates in the \`templates\` directory
34301
- 3. Add more blog posts in the \`content\` directory
34302
- 4. Run \`bunki generate\` to build your site
34303
- 5. Run \`bunki serve\` to preview your site locally
34304
- `;
34305
+ 1. Edit the site configuration in \`bunki.config.ts\`
34306
+ 2. Create your own templates in the \`templates\` directory
34307
+ 3. Add more blog posts in the \`content\` directory
34308
+ 4. Run \`bunki generate\` to build your site
34309
+ 5. Run \`bunki serve\` to preview your site locally
34310
+ `;
34305
34311
  }
34306
34312
 
34307
34313
  // src/cli/commands/new-post.ts
@@ -34501,6 +34507,8 @@ registerServeCommand(program2);
34501
34507
  registerCssCommand(program2);
34502
34508
  registerImagesPushCommand(program2);
34503
34509
  program2.name("bunki").description("An opinionated static site generator built with Bun").version("0.5.3");
34504
- if (import.meta.url === Bun.main) {
34510
+ var currentFile = import.meta.url.replace("file://", "");
34511
+ var mainFile = Bun.main;
34512
+ if (currentFile === mainFile || currentFile.endsWith(mainFile)) {
34505
34513
  program2.parse(Bun.argv);
34506
34514
  }
package/dist/index.js CHANGED
@@ -23766,9 +23766,9 @@ var require_fsevents_handler = __commonJS((exports, module) => {
23766
23766
  if (this.fsw.closed || this.checkIgnored(path4))
23767
23767
  return;
23768
23768
  if (event === EV_UNLINK) {
23769
- const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY;
23770
- if (isDirectory || watchedDir.has(item)) {
23771
- this.fsw._remove(parent, item, isDirectory);
23769
+ const isDirectory2 = info.type === FSEVENT_TYPE_DIRECTORY;
23770
+ if (isDirectory2 || watchedDir.has(item)) {
23771
+ this.fsw._remove(parent, item, isDirectory2);
23772
23772
  }
23773
23773
  } else {
23774
23774
  if (event === EV_ADD) {
@@ -24550,13 +24550,13 @@ var require_chokidar = __commonJS((exports) => {
24550
24550
  const it = Number.parseInt(st.toString(8)[0], 10);
24551
24551
  return Boolean(4 & it);
24552
24552
  }
24553
- _remove(directory, item, isDirectory) {
24553
+ _remove(directory, item, isDirectory2) {
24554
24554
  const path4 = sysPath.join(directory, item);
24555
24555
  const fullPath = sysPath.resolve(path4);
24556
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path4) || this._watched.has(fullPath);
24556
+ isDirectory2 = isDirectory2 != null ? isDirectory2 : this._watched.has(path4) || this._watched.has(fullPath);
24557
24557
  if (!this._throttle("remove", path4, 100))
24558
24558
  return;
24559
- if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) {
24559
+ if (!isDirectory2 && !this.options.useFsEvents && this._watched.size === 1) {
24560
24560
  this.add(directory, item, true);
24561
24561
  }
24562
24562
  const wp = this._getWatchedDir(path4);
@@ -24578,7 +24578,7 @@ var require_chokidar = __commonJS((exports) => {
24578
24578
  }
24579
24579
  this._watched.delete(path4);
24580
24580
  this._watched.delete(fullPath);
24581
- const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK;
24581
+ const eventName = isDirectory2 ? EV_UNLINK_DIR : EV_UNLINK;
24582
24582
  if (wasTracked && !this._isIgnored(path4))
24583
24583
  this._emit(eventName, path4);
24584
24584
  if (!this.options.useFsEvents) {
@@ -26000,6 +26000,7 @@ var require_slugify = __commonJS((exports, module) => {
26000
26000
  // src/utils/file-utils.ts
26001
26001
  var {Glob } = globalThis.Bun;
26002
26002
  import path from "path";
26003
+ import { mkdir } from "fs/promises";
26003
26004
  async function findFilesByPattern(pattern, directory, absolute = true) {
26004
26005
  const glob = new Glob(pattern);
26005
26006
  const files = [];
@@ -26012,8 +26013,20 @@ async function findFilesByPattern(pattern, directory, absolute = true) {
26012
26013
  return files;
26013
26014
  }
26014
26015
  async function fileExists(filePath) {
26015
- const file = Bun.file(filePath);
26016
- return await file.exists();
26016
+ try {
26017
+ const file = Bun.file(filePath);
26018
+ return await file.exists();
26019
+ } catch {
26020
+ return false;
26021
+ }
26022
+ }
26023
+ async function isDirectory(dirPath) {
26024
+ try {
26025
+ const stat = await Bun.file(dirPath).stat();
26026
+ return stat?.isDirectory() ?? false;
26027
+ } catch {
26028
+ return false;
26029
+ }
26017
26030
  }
26018
26031
  async function readFileAsText(filePath) {
26019
26032
  try {
@@ -26030,18 +26043,33 @@ async function readFileAsText(filePath) {
26030
26043
  function getBaseFilename(filePath, extension = ".md") {
26031
26044
  return path.basename(filePath, extension);
26032
26045
  }
26033
- async function ensureDir(dirPath) {
26046
+ async function createDir(dirPath) {
26034
26047
  try {
26035
- await Bun.write(`${dirPath}/.gitkeep`, "");
26036
- } catch (error) {}
26048
+ await mkdir(dirPath, { recursive: true });
26049
+ } catch (error) {
26050
+ if (await isDirectory(dirPath)) {
26051
+ return;
26052
+ }
26053
+ if (await fileExists(dirPath)) {
26054
+ throw new Error(`Path exists but is not a directory: ${dirPath}`);
26055
+ }
26056
+ console.error(`Error creating directory ${dirPath}:`, error);
26057
+ throw error;
26058
+ }
26059
+ }
26060
+ async function ensureDir(dirPath) {
26061
+ return createDir(dirPath);
26037
26062
  }
26038
26063
  async function copyFile(sourcePath, targetPath) {
26039
26064
  try {
26040
26065
  const sourceFile = Bun.file(sourcePath);
26041
- const content = await sourceFile.arrayBuffer();
26042
- await Bun.write(targetPath, content);
26066
+ if (!await sourceFile.exists()) {
26067
+ throw new Error(`Source file does not exist: ${sourcePath}`);
26068
+ }
26069
+ await Bun.write(targetPath, sourceFile);
26043
26070
  } catch (error) {
26044
26071
  console.error(`Error copying file from ${sourcePath} to ${targetPath}:`, error);
26072
+ throw error;
26045
26073
  }
26046
26074
  }
26047
26075
 
@@ -30576,7 +30604,7 @@ function getDefaultConfig() {
30576
30604
  return base;
30577
30605
  }
30578
30606
  async function createDefaultConfig(configPath = DEFAULT_CONFIG_FILE) {
30579
- if (await configExists()) {
30607
+ if (await configExists(configPath)) {
30580
30608
  console.log(`Config file already exists`);
30581
30609
  return false;
30582
30610
  }
@@ -30775,15 +30803,6 @@ async function processCSS(options2) {
30775
30803
  } catch (error) {
30776
30804
  throw new Error(`CSS input file not found: ${inputPath}`);
30777
30805
  }
30778
- let postcssConfigExists = false;
30779
- try {
30780
- await fs2.promises.access(postcssConfigPath);
30781
- postcssConfigExists = true;
30782
- } catch (error) {
30783
- if (verbose) {
30784
- console.log(`PostCSS config not found at ${postcssConfigPath}, will fallback to simple copy`);
30785
- }
30786
- }
30787
30806
  const outputDirPath = path4.dirname(outputPath);
30788
30807
  await fs2.promises.mkdir(outputDirPath, { recursive: true });
30789
30808
  if (verbose) {
@@ -30792,71 +30811,40 @@ async function processCSS(options2) {
30792
30811
  console.log(`Output: ${outputPath}`);
30793
30812
  console.log(`Config: ${postcssConfigPath}`);
30794
30813
  }
30795
- if (!postcssConfigExists) {
30796
- await fs2.promises.copyFile(inputPath, outputPath);
30797
- if (verbose)
30798
- console.log("Copied CSS without PostCSS config");
30799
- return;
30800
- }
30801
- const runPostCSS = (configPathToUse) => {
30802
- return new Promise((resolve, reject) => {
30803
- const args = ["postcss", inputPath, "-o", outputPath];
30804
- if (configPathToUse && fs2.existsSync(configPathToUse)) {
30805
- args.push("--config", configPathToUse);
30806
- }
30807
- const postcss = spawn("bunx", args, {
30808
- stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
30809
- cwd: projectRoot
30814
+ await runPostCSS(inputPath, outputPath, postcssConfigPath, projectRoot, verbose);
30815
+ }
30816
+ function runPostCSS(inputPath, outputPath, configPath, projectRoot, verbose) {
30817
+ return new Promise((resolve, reject) => {
30818
+ const args = [
30819
+ "postcss",
30820
+ inputPath,
30821
+ "-o",
30822
+ outputPath,
30823
+ "--config",
30824
+ configPath
30825
+ ];
30826
+ const postcss = spawn("bunx", args, {
30827
+ stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
30828
+ cwd: projectRoot
30829
+ });
30830
+ let errorOutput = "";
30831
+ if (!verbose) {
30832
+ postcss.stderr?.on("data", (data) => {
30833
+ errorOutput += data.toString();
30810
30834
  });
30811
- let errorOutput = "";
30812
- if (!verbose) {
30813
- postcss.stderr?.on("data", (data) => {
30814
- errorOutput += data.toString();
30815
- });
30835
+ }
30836
+ postcss.on("close", (code) => {
30837
+ if (code === 0) {
30838
+ if (verbose)
30839
+ console.log("\u2705 CSS build completed successfully!");
30840
+ return resolve();
30816
30841
  }
30817
- postcss.on("close", async (code) => {
30818
- if (code === 0) {
30819
- if (verbose)
30820
- console.log("\u2705 CSS build completed successfully!");
30821
- return resolve();
30822
- }
30823
- if (/module is not defined in ES module scope/i.test(errorOutput) && configPathToUse.endsWith(".js")) {
30824
- const cjsPath = configPathToUse.replace(/\.js$/, ".cjs");
30825
- try {
30826
- if (!fs2.existsSync(cjsPath)) {
30827
- const original = await fs2.promises.readFile(configPathToUse, "utf-8");
30828
- await fs2.promises.writeFile(cjsPath, original, "utf-8");
30829
- if (verbose) {
30830
- console.log(`Retrying PostCSS with converted CommonJS config at ${cjsPath}`);
30831
- }
30832
- }
30833
- return resolve(runPostCSS(cjsPath));
30834
- } catch (e) {
30835
- if (verbose)
30836
- console.warn("CJS fallback failed, copying CSS.");
30837
- await fs2.promises.copyFile(inputPath, outputPath);
30838
- return resolve();
30839
- }
30840
- }
30841
- if (verbose) {
30842
- console.warn(`PostCSS failed (code ${code}). Falling back to simple copy. Error: ${errorOutput.trim()}`);
30843
- }
30844
- try {
30845
- await fs2.promises.copyFile(inputPath, outputPath);
30846
- resolve();
30847
- } catch (copyErr) {
30848
- reject(new Error(`CSS build failed with code ${code} and fallback copy also failed: ${copyErr.message}`));
30849
- }
30850
- });
30851
- postcss.on("error", (err) => {
30852
- if (verbose) {
30853
- console.warn(`Failed to start PostCSS process (${err.message}). Falling back to copy.`);
30854
- }
30855
- fs2.promises.copyFile(inputPath, outputPath).then(() => resolve()).catch((copyErr) => reject(new Error(`Failed to start PostCSS and fallback copy failed: ${copyErr.message}`)));
30856
- });
30842
+ reject(new Error(`PostCSS failed with exit code ${code}: ${errorOutput.trim()}`));
30857
30843
  });
30858
- };
30859
- await runPostCSS(postcssConfigPath);
30844
+ postcss.on("error", (err) => {
30845
+ reject(new Error(`Failed to start PostCSS: ${err.message}`));
30846
+ });
30847
+ });
30860
30848
  }
30861
30849
  function getDefaultCSSConfig() {
30862
30850
  return {
@@ -31521,8 +31509,11 @@ class S3Uploader {
31521
31509
  }
31522
31510
  }
31523
31511
  }
31524
- async uploadImages(imagesDir) {
31512
+ async uploadImages(imagesDir, minYear) {
31525
31513
  console.log(`[S3] Uploading all images from ${imagesDir} to bucket ${this.s3Config.bucket}...`);
31514
+ if (minYear) {
31515
+ console.log(`[S3] Filtering images from year ${minYear} onwards`);
31516
+ }
31526
31517
  const imageUrls = {};
31527
31518
  try {
31528
31519
  console.log(`[S3] Checking if directory exists: ${imagesDir}`);
@@ -31565,8 +31556,19 @@ class S3Uploader {
31565
31556
  cwd: imagesDir,
31566
31557
  absolute: false
31567
31558
  })) {
31568
- console.log(`[S3] Found image file: ${file}`);
31569
- files.push(file);
31559
+ if (minYear) {
31560
+ const yearMatch = file.match(/^(\d{4})\//);
31561
+ if (yearMatch) {
31562
+ const fileYear = parseInt(yearMatch[1], 10);
31563
+ if (fileYear >= minYear) {
31564
+ console.log(`[S3] Found image file: ${file}`);
31565
+ files.push(file);
31566
+ }
31567
+ }
31568
+ } else {
31569
+ console.log(`[S3] Found image file: ${file}`);
31570
+ files.push(file);
31571
+ }
31570
31572
  }
31571
31573
  const imageFiles = files;
31572
31574
  if (imageFiles.length === 0) {
@@ -31641,8 +31643,11 @@ async function uploadImages(options2 = {}) {
31641
31643
  };
31642
31644
  }
31643
31645
  console.log(`Uploading images from ${imagesDir} to bucket ${s3Config.bucket}`);
31646
+ if (options2.minYear) {
31647
+ console.log(`Filtering images from year ${options2.minYear} onwards`);
31648
+ }
31644
31649
  const uploader = createUploader(s3Config);
31645
- const imageUrlMap = await uploader.uploadImages(imagesDir);
31650
+ const imageUrlMap = await uploader.uploadImages(imagesDir, options2.minYear);
31646
31651
  if (options2.outputJson) {
31647
31652
  const outputFile = path7.resolve(options2.outputJson);
31648
31653
  await Bun.write(outputFile, JSON.stringify(imageUrlMap, null, 2));
@@ -31660,7 +31665,7 @@ Image upload completed successfully!`);
31660
31665
  return imageUrlMap;
31661
31666
  } catch (error) {
31662
31667
  console.error("Error uploading images:", error);
31663
- process.exit(1);
31668
+ throw error;
31664
31669
  }
31665
31670
  }
31666
31671
  export {