bunki 0.3.7 → 0.4.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 CHANGED
@@ -319,6 +319,18 @@ Your post content goes here with **markdown** support!
319
319
  ```javascript
320
320
  console.log("Code highlighting works too!");
321
321
  ```
322
+
323
+ You can also embed videos using HTML5 video tags:
324
+
325
+ <video src="https://example.com/video.mp4" controls width="640" height="360"></video>
326
+
327
+ Or with multiple formats for better browser compatibility:
328
+
329
+ <video controls width="640" height="360" poster="thumbnail.jpg">
330
+ <source src="video.mp4" type="video/mp4">
331
+ <source src="video.webm" type="video/webm">
332
+ Your browser does not support the video tag.
333
+ </video>
322
334
  ````
323
335
 
324
336
  ````
package/dist/cli.js CHANGED
@@ -32721,6 +32721,7 @@ marked.use({
32721
32721
  },
32722
32722
  postprocess(html) {
32723
32723
  html = html.replace(/<a href="(https?:\/\/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)[^"]*)"[^>]*>(.*?)<\/a>/g, '<div class="video-container"><iframe src="https://www.youtube.com/embed/$4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen loading="lazy"></iframe></div>');
32724
+ html = html.replace(/<img /g, '<img loading="lazy" ');
32724
32725
  return html.replace(/<a href="(https?:\/\/|\/\/)([^"]+)"/g, '<a href="$1$2" target="_blank" rel="noopener noreferrer"');
32725
32726
  }
32726
32727
  }
@@ -32743,17 +32744,31 @@ function convertMarkdownToHtml(markdownContent) {
32743
32744
  "h2",
32744
32745
  "span",
32745
32746
  "iframe",
32746
- "div"
32747
+ "div",
32748
+ "video",
32749
+ "source"
32747
32750
  ]),
32748
32751
  allowedAttributes: {
32749
32752
  ...import_sanitize_html.default.defaults.allowedAttributes,
32750
32753
  a: ["href", "name", "target", "rel", "title"],
32751
- img: ["src", "alt", "title"],
32754
+ img: ["src", "alt", "title", "loading"],
32752
32755
  code: ["class"],
32753
32756
  pre: ["class"],
32754
32757
  span: ["class", "style"],
32755
32758
  iframe: ["src", "frameborder", "allow", "allowfullscreen", "loading"],
32756
- div: ["class"]
32759
+ div: ["class"],
32760
+ video: [
32761
+ "src",
32762
+ "controls",
32763
+ "width",
32764
+ "height",
32765
+ "autoplay",
32766
+ "loop",
32767
+ "muted",
32768
+ "preload",
32769
+ "poster"
32770
+ ],
32771
+ source: ["src", "type"]
32757
32772
  },
32758
32773
  allowedClasses: {
32759
32774
  code: ["*"],
@@ -33267,7 +33282,9 @@ class SiteGenerator {
33267
33282
  }
33268
33283
  if (await dirExists(publicDir)) {
33269
33284
  const copyRecursive = async (srcDir) => {
33270
- const entries = await fs3.promises.readdir(srcDir, { withFileTypes: true });
33285
+ const entries = await fs3.promises.readdir(srcDir, {
33286
+ withFileTypes: true
33287
+ });
33271
33288
  for (const entry of entries) {
33272
33289
  const srcPath = path5.join(srcDir, entry.name);
33273
33290
  const relativePath = path5.relative(publicDir, srcPath);
@@ -33323,6 +33340,20 @@ ${rssItems}
33323
33340
  const currentDate = this.getPacificDate(new Date).toISOString();
33324
33341
  const pageSize = 10;
33325
33342
  const config = this.options.config;
33343
+ const now = this.getPacificDate(new Date).getTime();
33344
+ const ONE_DAY = 24 * 60 * 60 * 1000;
33345
+ const ONE_WEEK = 7 * ONE_DAY;
33346
+ const ONE_MONTH = 30 * ONE_DAY;
33347
+ const calculatePriority = (date, basePriority) => {
33348
+ const postTime = new Date(date).getTime();
33349
+ const age = now - postTime;
33350
+ if (age < ONE_WEEK) {
33351
+ return Math.min(1, basePriority + 0.2);
33352
+ } else if (age < ONE_MONTH) {
33353
+ return Math.min(1, basePriority + 0.1);
33354
+ }
33355
+ return basePriority;
33356
+ };
33326
33357
  let sitemapContent = `<?xml version="1.0" encoding="UTF-8"?>
33327
33358
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
33328
33359
  `;
@@ -33340,7 +33371,7 @@ ${rssItems}
33340
33371
  <loc>${config.baseUrl}/page/${page}/</loc>
33341
33372
  <lastmod>${currentDate}</lastmod>
33342
33373
  <changefreq>daily</changefreq>
33343
- <priority>0.9</priority>
33374
+ <priority>0.8</priority>
33344
33375
  </url>
33345
33376
  `;
33346
33377
  }
@@ -33348,11 +33379,14 @@ ${rssItems}
33348
33379
  for (const post of this.site.posts) {
33349
33380
  const postUrl = `${config.baseUrl}${post.url}`;
33350
33381
  const postDate = new Date(post.date).toISOString();
33382
+ const priority = calculatePriority(post.date, 0.7);
33383
+ const age = now - new Date(post.date).getTime();
33384
+ const changefreq = age < ONE_MONTH ? "weekly" : "monthly";
33351
33385
  sitemapContent += ` <url>
33352
33386
  <loc>${postUrl}</loc>
33353
33387
  <lastmod>${postDate}</lastmod>
33354
- <changefreq>monthly</changefreq>
33355
- <priority>0.8</priority>
33388
+ <changefreq>${changefreq}</changefreq>
33389
+ <priority>${priority.toFixed(1)}</priority>
33356
33390
  </url>
33357
33391
  `;
33358
33392
  }
@@ -33360,16 +33394,18 @@ ${rssItems}
33360
33394
  <loc>${config.baseUrl}/tags/</loc>
33361
33395
  <lastmod>${currentDate}</lastmod>
33362
33396
  <changefreq>weekly</changefreq>
33363
- <priority>0.6</priority>
33397
+ <priority>0.5</priority>
33364
33398
  </url>
33365
33399
  `;
33366
33400
  for (const [, tagData] of Object.entries(this.site.tags)) {
33367
33401
  const tagUrl = `${config.baseUrl}/tags/${tagData.slug}/`;
33402
+ const mostRecentPost = tagData.posts[0];
33403
+ const tagPriority = mostRecentPost ? calculatePriority(mostRecentPost.date, 0.4) : 0.4;
33368
33404
  sitemapContent += ` <url>
33369
33405
  <loc>${tagUrl}</loc>
33370
33406
  <lastmod>${currentDate}</lastmod>
33371
33407
  <changefreq>weekly</changefreq>
33372
- <priority>0.5</priority>
33408
+ <priority>${tagPriority.toFixed(1)}</priority>
33373
33409
  </url>
33374
33410
  `;
33375
33411
  const totalTagPages = Math.ceil(tagData.posts.length / pageSize);
@@ -33379,7 +33415,7 @@ ${rssItems}
33379
33415
  <loc>${config.baseUrl}/tags/${tagData.slug}/page/${page}/</loc>
33380
33416
  <lastmod>${currentDate}</lastmod>
33381
33417
  <changefreq>weekly</changefreq>
33382
- <priority>0.5</priority>
33418
+ <priority>${Math.max(0.3, tagPriority - 0.1).toFixed(1)}</priority>
33383
33419
  </url>
33384
33420
  `;
33385
33421
  }
@@ -33395,11 +33431,14 @@ ${rssItems}
33395
33431
  postsByYear[year].push(post);
33396
33432
  }
33397
33433
  for (const [year, yearPosts] of Object.entries(postsByYear)) {
33434
+ const currentYear = new Date().getFullYear();
33435
+ const isCurrentYear = parseInt(year) === currentYear;
33436
+ const yearPriority = isCurrentYear ? 0.7 : 0.5;
33398
33437
  sitemapContent += ` <url>
33399
33438
  <loc>${config.baseUrl}/${year}/</loc>
33400
33439
  <lastmod>${currentDate}</lastmod>
33401
- <changefreq>monthly</changefreq>
33402
- <priority>0.6</priority>
33440
+ <changefreq>${isCurrentYear ? "weekly" : "monthly"}</changefreq>
33441
+ <priority>${yearPriority.toFixed(1)}</priority>
33403
33442
  </url>
33404
33443
  `;
33405
33444
  const totalYearPages = Math.ceil(yearPosts.length / pageSize);
@@ -33408,8 +33447,8 @@ ${rssItems}
33408
33447
  sitemapContent += ` <url>
33409
33448
  <loc>${config.baseUrl}/${year}/page/${page}/</loc>
33410
33449
  <lastmod>${currentDate}</lastmod>
33411
- <changefreq>monthly</changefreq>
33412
- <priority>0.6</priority>
33450
+ <changefreq>${isCurrentYear ? "weekly" : "monthly"}</changefreq>
33451
+ <priority>${(yearPriority - 0.1).toFixed(1)}</priority>
33413
33452
  </url>
33414
33453
  `;
33415
33454
  }
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ export * from "./types";
2
2
  export { parseMarkdownDirectory } from "./parser";
3
3
  export { startServer } from "./server";
4
4
  export { SiteGenerator } from "./site-generator";
5
- export { configExists, createDefaultConfig, DEFAULT_CONFIG_FILE, DEFAULT_CONTENT_DIR, DEFAULT_OUTPUT_DIR, DEFAULT_TEMPLATES_DIR, loadConfig, saveConfig } from "./config";
6
- export { copyFile, ensureDir, fileExists, findFilesByPattern, getBaseFilename, readFileAsText } from "./utils/file-utils";
7
- export { convertMarkdownToHtml, extractExcerpt, parseMarkdownFile } from "./utils/markdown-utils";
5
+ export { configExists, createDefaultConfig, DEFAULT_CONFIG_FILE, DEFAULT_CONTENT_DIR, DEFAULT_OUTPUT_DIR, DEFAULT_TEMPLATES_DIR, loadConfig, saveConfig, } from "./config";
6
+ export { copyFile, ensureDir, fileExists, findFilesByPattern, getBaseFilename, readFileAsText, } from "./utils/file-utils";
7
+ export { convertMarkdownToHtml, extractExcerpt, parseMarkdownFile, } from "./utils/markdown-utils";
8
8
  export { DEFAULT_IMAGES_DIR, uploadImages } from "./utils/image-uploader";
9
9
  export { createUploader } from "./utils/s3-uploader";
package/dist/index.js CHANGED
@@ -30366,6 +30366,7 @@ marked.use({
30366
30366
  },
30367
30367
  postprocess(html) {
30368
30368
  html = html.replace(/<a href="(https?:\/\/(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)[^"]*)"[^>]*>(.*?)<\/a>/g, '<div class="video-container"><iframe src="https://www.youtube.com/embed/$4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen loading="lazy"></iframe></div>');
30369
+ html = html.replace(/<img /g, '<img loading="lazy" ');
30369
30370
  return html.replace(/<a href="(https?:\/\/|\/\/)([^"]+)"/g, '<a href="$1$2" target="_blank" rel="noopener noreferrer"');
30370
30371
  }
30371
30372
  }
@@ -30388,17 +30389,31 @@ function convertMarkdownToHtml(markdownContent) {
30388
30389
  "h2",
30389
30390
  "span",
30390
30391
  "iframe",
30391
- "div"
30392
+ "div",
30393
+ "video",
30394
+ "source"
30392
30395
  ]),
30393
30396
  allowedAttributes: {
30394
30397
  ...import_sanitize_html.default.defaults.allowedAttributes,
30395
30398
  a: ["href", "name", "target", "rel", "title"],
30396
- img: ["src", "alt", "title"],
30399
+ img: ["src", "alt", "title", "loading"],
30397
30400
  code: ["class"],
30398
30401
  pre: ["class"],
30399
30402
  span: ["class", "style"],
30400
30403
  iframe: ["src", "frameborder", "allow", "allowfullscreen", "loading"],
30401
- div: ["class"]
30404
+ div: ["class"],
30405
+ video: [
30406
+ "src",
30407
+ "controls",
30408
+ "width",
30409
+ "height",
30410
+ "autoplay",
30411
+ "loop",
30412
+ "muted",
30413
+ "preload",
30414
+ "poster"
30415
+ ],
30416
+ source: ["src", "type"]
30402
30417
  },
30403
30418
  allowedClasses: {
30404
30419
  code: ["*"],
@@ -31139,7 +31154,9 @@ class SiteGenerator {
31139
31154
  }
31140
31155
  if (await dirExists(publicDir)) {
31141
31156
  const copyRecursive = async (srcDir) => {
31142
- const entries = await fs3.promises.readdir(srcDir, { withFileTypes: true });
31157
+ const entries = await fs3.promises.readdir(srcDir, {
31158
+ withFileTypes: true
31159
+ });
31143
31160
  for (const entry of entries) {
31144
31161
  const srcPath = path5.join(srcDir, entry.name);
31145
31162
  const relativePath = path5.relative(publicDir, srcPath);
@@ -31195,6 +31212,20 @@ ${rssItems}
31195
31212
  const currentDate = this.getPacificDate(new Date).toISOString();
31196
31213
  const pageSize = 10;
31197
31214
  const config = this.options.config;
31215
+ const now = this.getPacificDate(new Date).getTime();
31216
+ const ONE_DAY = 24 * 60 * 60 * 1000;
31217
+ const ONE_WEEK = 7 * ONE_DAY;
31218
+ const ONE_MONTH = 30 * ONE_DAY;
31219
+ const calculatePriority = (date, basePriority) => {
31220
+ const postTime = new Date(date).getTime();
31221
+ const age = now - postTime;
31222
+ if (age < ONE_WEEK) {
31223
+ return Math.min(1, basePriority + 0.2);
31224
+ } else if (age < ONE_MONTH) {
31225
+ return Math.min(1, basePriority + 0.1);
31226
+ }
31227
+ return basePriority;
31228
+ };
31198
31229
  let sitemapContent = `<?xml version="1.0" encoding="UTF-8"?>
31199
31230
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
31200
31231
  `;
@@ -31212,7 +31243,7 @@ ${rssItems}
31212
31243
  <loc>${config.baseUrl}/page/${page}/</loc>
31213
31244
  <lastmod>${currentDate}</lastmod>
31214
31245
  <changefreq>daily</changefreq>
31215
- <priority>0.9</priority>
31246
+ <priority>0.8</priority>
31216
31247
  </url>
31217
31248
  `;
31218
31249
  }
@@ -31220,11 +31251,14 @@ ${rssItems}
31220
31251
  for (const post of this.site.posts) {
31221
31252
  const postUrl = `${config.baseUrl}${post.url}`;
31222
31253
  const postDate = new Date(post.date).toISOString();
31254
+ const priority = calculatePriority(post.date, 0.7);
31255
+ const age = now - new Date(post.date).getTime();
31256
+ const changefreq = age < ONE_MONTH ? "weekly" : "monthly";
31223
31257
  sitemapContent += ` <url>
31224
31258
  <loc>${postUrl}</loc>
31225
31259
  <lastmod>${postDate}</lastmod>
31226
- <changefreq>monthly</changefreq>
31227
- <priority>0.8</priority>
31260
+ <changefreq>${changefreq}</changefreq>
31261
+ <priority>${priority.toFixed(1)}</priority>
31228
31262
  </url>
31229
31263
  `;
31230
31264
  }
@@ -31232,16 +31266,18 @@ ${rssItems}
31232
31266
  <loc>${config.baseUrl}/tags/</loc>
31233
31267
  <lastmod>${currentDate}</lastmod>
31234
31268
  <changefreq>weekly</changefreq>
31235
- <priority>0.6</priority>
31269
+ <priority>0.5</priority>
31236
31270
  </url>
31237
31271
  `;
31238
31272
  for (const [, tagData] of Object.entries(this.site.tags)) {
31239
31273
  const tagUrl = `${config.baseUrl}/tags/${tagData.slug}/`;
31274
+ const mostRecentPost = tagData.posts[0];
31275
+ const tagPriority = mostRecentPost ? calculatePriority(mostRecentPost.date, 0.4) : 0.4;
31240
31276
  sitemapContent += ` <url>
31241
31277
  <loc>${tagUrl}</loc>
31242
31278
  <lastmod>${currentDate}</lastmod>
31243
31279
  <changefreq>weekly</changefreq>
31244
- <priority>0.5</priority>
31280
+ <priority>${tagPriority.toFixed(1)}</priority>
31245
31281
  </url>
31246
31282
  `;
31247
31283
  const totalTagPages = Math.ceil(tagData.posts.length / pageSize);
@@ -31251,7 +31287,7 @@ ${rssItems}
31251
31287
  <loc>${config.baseUrl}/tags/${tagData.slug}/page/${page}/</loc>
31252
31288
  <lastmod>${currentDate}</lastmod>
31253
31289
  <changefreq>weekly</changefreq>
31254
- <priority>0.5</priority>
31290
+ <priority>${Math.max(0.3, tagPriority - 0.1).toFixed(1)}</priority>
31255
31291
  </url>
31256
31292
  `;
31257
31293
  }
@@ -31267,11 +31303,14 @@ ${rssItems}
31267
31303
  postsByYear[year].push(post);
31268
31304
  }
31269
31305
  for (const [year, yearPosts] of Object.entries(postsByYear)) {
31306
+ const currentYear = new Date().getFullYear();
31307
+ const isCurrentYear = parseInt(year) === currentYear;
31308
+ const yearPriority = isCurrentYear ? 0.7 : 0.5;
31270
31309
  sitemapContent += ` <url>
31271
31310
  <loc>${config.baseUrl}/${year}/</loc>
31272
31311
  <lastmod>${currentDate}</lastmod>
31273
- <changefreq>monthly</changefreq>
31274
- <priority>0.6</priority>
31312
+ <changefreq>${isCurrentYear ? "weekly" : "monthly"}</changefreq>
31313
+ <priority>${yearPriority.toFixed(1)}</priority>
31275
31314
  </url>
31276
31315
  `;
31277
31316
  const totalYearPages = Math.ceil(yearPosts.length / pageSize);
@@ -31280,8 +31319,8 @@ ${rssItems}
31280
31319
  sitemapContent += ` <url>
31281
31320
  <loc>${config.baseUrl}/${year}/page/${page}/</loc>
31282
31321
  <lastmod>${currentDate}</lastmod>
31283
- <changefreq>monthly</changefreq>
31284
- <priority>0.6</priority>
31322
+ <changefreq>${isCurrentYear ? "weekly" : "monthly"}</changefreq>
31323
+ <priority>${(yearPriority - 0.1).toFixed(1)}</priority>
31285
31324
  </url>
31286
31325
  `;
31287
31326
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunki",
3
- "version": "0.3.7",
3
+ "version": "0.4.0",
4
4
  "description": "An opinionated static site generator built with Bun featuring PostCSS integration and modern web development workflows",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",