docula 1.7.0 → 1.8.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/docula.d.ts CHANGED
@@ -119,6 +119,8 @@ type DoculaConsoleArguments = {
119
119
  port: number | undefined;
120
120
  typescript: boolean;
121
121
  javascript: boolean;
122
+ overwrite: boolean;
123
+ downloadTarget: string;
122
124
  };
123
125
 
124
126
  type GithubData = {
@@ -503,6 +505,26 @@ declare class Docula {
503
505
  * @returns {void}
504
506
  */
505
507
  generateInit(sitePath: string, typescript?: boolean): void;
508
+ /**
509
+ * Copy the template's variables.css to the site directory.
510
+ * If the file already exists and overwrite is false, prints an error.
511
+ * @param {string} sitePath
512
+ * @param {string} templatePath
513
+ * @param {string} templateName
514
+ * @param {boolean} overwrite
515
+ * @returns {void}
516
+ */
517
+ downloadVariables(sitePath: string, templatePath: string, templateName: string, overwrite?: boolean): void;
518
+ /**
519
+ * Copy the full template directory to {sitePath}/templates/{outputName}/.
520
+ * If the directory already exists and overwrite is false, prints an error.
521
+ * @param {string} sitePath
522
+ * @param {string} templatePath
523
+ * @param {string} templateName
524
+ * @param {boolean} overwrite
525
+ * @returns {void}
526
+ */
527
+ downloadTemplate(sitePath: string, templatePath: string, templateName: string, overwrite?: boolean): void;
506
528
  /**
507
529
  * Get the version of the package
508
530
  * @returns {string}
package/dist/docula.js CHANGED
@@ -581,6 +581,9 @@ var DoculaConsole = class {
581
581
  );
582
582
  console.log(` ${green("help")} Print this help`);
583
583
  console.log(` ${green("version")} Print the version`);
584
+ console.log(
585
+ ` ${green("download")} Download template files to your site directory`
586
+ );
584
587
  console.log();
585
588
  console.log(bold(cyan(" Common Options:")));
586
589
  console.log(
@@ -619,6 +622,17 @@ var DoculaConsole = class {
619
622
  console.log(
620
623
  ` ${yellow("-b, --build")} Build the site before serving`
621
624
  );
625
+ console.log();
626
+ console.log(bold(cyan(" Download Options:")));
627
+ console.log(
628
+ ` ${yellow("variables")} Copy variables.css to your site directory`
629
+ );
630
+ console.log(
631
+ ` ${yellow("template")} Copy the full template to site/templates/<name>/`
632
+ );
633
+ console.log(
634
+ ` ${yellow("--overwrite")} Overwrite existing files if they already exist`
635
+ );
622
636
  }
623
637
  parseProcessArgv(argv) {
624
638
  const command = this.getCommand(argv);
@@ -676,6 +690,9 @@ var DoculaConsole = class {
676
690
  case "version": {
677
691
  return "version";
678
692
  }
693
+ case "download": {
694
+ return "download";
695
+ }
679
696
  }
680
697
  }
681
698
  }
@@ -690,7 +707,9 @@ var DoculaConsole = class {
690
707
  build: false,
691
708
  port: void 0,
692
709
  typescript: false,
693
- javascript: false
710
+ javascript: false,
711
+ overwrite: false,
712
+ downloadTarget: ""
694
713
  };
695
714
  for (let i = 0; i < argv.length; i++) {
696
715
  const argument = argv[i];
@@ -752,6 +771,36 @@ var DoculaConsole = class {
752
771
  arguments_.javascript = true;
753
772
  break;
754
773
  }
774
+ case "--overwrite": {
775
+ arguments_.overwrite = true;
776
+ break;
777
+ }
778
+ }
779
+ }
780
+ const downloadFlagsWithValues = /* @__PURE__ */ new Set([
781
+ "-s",
782
+ "--site",
783
+ "-o",
784
+ "--output",
785
+ "-p",
786
+ "--port",
787
+ "-t",
788
+ "--templatePath",
789
+ "-T",
790
+ "--template"
791
+ ]);
792
+ const downloadIndex = argv.indexOf("download");
793
+ if (downloadIndex !== -1) {
794
+ for (let i = downloadIndex + 1; i < argv.length; i++) {
795
+ const token = argv[i];
796
+ if (downloadFlagsWithValues.has(token)) {
797
+ i++;
798
+ continue;
799
+ }
800
+ if (!token.startsWith("-")) {
801
+ arguments_.downloadTarget = token;
802
+ break;
803
+ }
755
804
  }
756
805
  }
757
806
  return arguments_;
@@ -1184,6 +1233,10 @@ function resolveTemplatePath(templatePath, templateName) {
1184
1233
  }
1185
1234
 
1186
1235
  // src/builder.ts
1236
+ var writrOptions = {
1237
+ throwOnEmitError: false,
1238
+ throwOnEmptyListeners: false
1239
+ };
1187
1240
  var DoculaBuilder = class {
1188
1241
  _options = new DoculaOptions();
1189
1242
  _ecto;
@@ -1662,7 +1715,7 @@ var DoculaBuilder = class {
1662
1715
  data.siteUrl,
1663
1716
  `${data.baseUrl}${this.normalizePathForUrl(document.urlPath)}`
1664
1717
  );
1665
- const summary = document.description || this.summarizeMarkdown(new Writr(document.content).body);
1718
+ const summary = document.description || this.summarizeMarkdown(new Writr(document.content, writrOptions).body);
1666
1719
  xml += "<item>";
1667
1720
  xml += `<title>${this.escapeXml(itemTitle)}</title>`;
1668
1721
  xml += `<link>${this.escapeXml(itemLink)}</link>`;
@@ -1847,7 +1900,10 @@ var DoculaBuilder = class {
1847
1900
  data.siteUrl,
1848
1901
  `${data.baseUrl}${this.normalizePathForUrl(document.urlPath)}`
1849
1902
  );
1850
- const markdownBody = new Writr(document.content).body.trim();
1903
+ const markdownBody = new Writr(
1904
+ document.content,
1905
+ writrOptions
1906
+ ).body.trim();
1851
1907
  lines.push("");
1852
1908
  lines.push(`### ${document.navTitle}`);
1853
1909
  lines.push(`URL: ${documentUrl}`);
@@ -2089,7 +2145,7 @@ var DoculaBuilder = class {
2089
2145
  `${data.sitePath}/README.md`,
2090
2146
  "utf8"
2091
2147
  );
2092
- htmlReadme = await new Writr(readmeContent).render();
2148
+ htmlReadme = await new Writr(readmeContent, writrOptions).render();
2093
2149
  }
2094
2150
  return htmlReadme;
2095
2151
  }
@@ -2097,7 +2153,7 @@ var DoculaBuilder = class {
2097
2153
  const announcementPath = `${data.sitePath}/announcement.md`;
2098
2154
  if (fs3.existsSync(announcementPath)) {
2099
2155
  const announcementContent = fs3.readFileSync(announcementPath, "utf8");
2100
- return new Writr(announcementContent).render();
2156
+ return new Writr(announcementContent, writrOptions).render();
2101
2157
  }
2102
2158
  return void 0;
2103
2159
  }
@@ -2153,12 +2209,16 @@ var DoculaBuilder = class {
2153
2209
  }
2154
2210
  if (apiSpec) {
2155
2211
  apiSpec.info.description = new Writr(
2156
- apiSpec.info.description
2212
+ apiSpec.info.description,
2213
+ writrOptions
2157
2214
  ).renderSync();
2158
2215
  for (const group of apiSpec.groups) {
2159
- group.description = new Writr(group.description).renderSync();
2216
+ group.description = new Writr(
2217
+ group.description,
2218
+ writrOptions
2219
+ ).renderSync();
2160
2220
  for (const op of group.operations) {
2161
- op.description = new Writr(op.description).renderSync();
2221
+ op.description = new Writr(op.description, writrOptions).renderSync();
2162
2222
  }
2163
2223
  }
2164
2224
  }
@@ -2225,7 +2285,7 @@ var DoculaBuilder = class {
2225
2285
  }
2226
2286
  parseChangelogEntry(filePath) {
2227
2287
  const fileContent = fs3.readFileSync(filePath, "utf8");
2228
- const writr = new Writr(fileContent);
2288
+ const writr = new Writr(fileContent, writrOptions);
2229
2289
  const matterData = writr.frontMatter;
2230
2290
  const markdownContent = writr.body;
2231
2291
  const fileName = path5.basename(filePath, path5.extname(filePath));
@@ -2257,7 +2317,9 @@ var DoculaBuilder = class {
2257
2317
  tagClass,
2258
2318
  slug,
2259
2319
  content: markdownContent,
2260
- generatedHtml: new Writr(markdownContent).renderSync({ mdx: isMdx }),
2320
+ generatedHtml: new Writr(markdownContent, writrOptions).renderSync({
2321
+ mdx: isMdx
2322
+ }),
2261
2323
  preview: this.generateChangelogPreview(markdownContent, 500, isMdx),
2262
2324
  previewImage,
2263
2325
  urlPath: `/${this.options.changelogPath}/${slug}/index.html`,
@@ -2272,7 +2334,7 @@ var DoculaBuilder = class {
2272
2334
  cleaned = cleaned.replace(/\[([^\]]*)\]\([^)]*\)/g, "$1");
2273
2335
  cleaned = cleaned.replace(/^\n+/, "").trim();
2274
2336
  if (cleaned.length <= minLength) {
2275
- return new Writr(cleaned).renderSync({ mdx });
2337
+ return new Writr(cleaned, writrOptions).renderSync({ mdx });
2276
2338
  }
2277
2339
  const searchArea = cleaned.slice(0, maxLength);
2278
2340
  let splitIndex = -1;
@@ -2315,7 +2377,7 @@ var DoculaBuilder = class {
2315
2377
  }
2316
2378
  if (splitIndex > 0) {
2317
2379
  const truncated2 = cleaned.slice(0, splitIndex).trim();
2318
- return new Writr(truncated2).renderSync({ mdx });
2380
+ return new Writr(truncated2, writrOptions).renderSync({ mdx });
2319
2381
  }
2320
2382
  let truncated = cleaned.slice(0, maxLength);
2321
2383
  const lastSpace = truncated.lastIndexOf(" ");
@@ -2323,7 +2385,7 @@ var DoculaBuilder = class {
2323
2385
  truncated = truncated.slice(0, lastSpace);
2324
2386
  }
2325
2387
  truncated += "...";
2326
- return new Writr(truncated).renderSync({ mdx });
2388
+ return new Writr(truncated, writrOptions).renderSync({ mdx });
2327
2389
  }
2328
2390
  convertReleaseToChangelogEntry(release) {
2329
2391
  const tagName = release.tag_name ?? "";
@@ -2355,7 +2417,7 @@ var DoculaBuilder = class {
2355
2417
  tagClass,
2356
2418
  slug,
2357
2419
  content: body,
2358
- generatedHtml: new Writr(body).renderSync(),
2420
+ generatedHtml: new Writr(body, writrOptions).renderSync(),
2359
2421
  preview: this.generateChangelogPreview(body),
2360
2422
  urlPath: `/${this.options.changelogPath}/${slug}/index.html`,
2361
2423
  lastModified: dateString
@@ -2576,7 +2638,7 @@ var DoculaBuilder = class {
2576
2638
  }
2577
2639
  parseDocumentData(documentPath) {
2578
2640
  const documentContent = fs3.readFileSync(documentPath, "utf8");
2579
- const writr = new Writr(documentContent);
2641
+ const writr = new Writr(documentContent, writrOptions);
2580
2642
  const matterData = writr.frontMatter;
2581
2643
  let markdownContent = writr.body;
2582
2644
  markdownContent = markdownContent.replace(/^# .*\n/, "");
@@ -2616,7 +2678,7 @@ ${markdownContent.slice(firstH2)}`;
2616
2678
  keywords: matterData.keywords ?? [],
2617
2679
  content: documentContent,
2618
2680
  markdown: markdownContent,
2619
- generatedHtml: new Writr(markdownContent).renderSync({
2681
+ generatedHtml: new Writr(markdownContent, writrOptions).renderSync({
2620
2682
  toc: true,
2621
2683
  mdx: isMdx
2622
2684
  }),
@@ -3341,6 +3403,34 @@ var Docula = class {
3341
3403
  await this.serve(this.options);
3342
3404
  break;
3343
3405
  }
3406
+ case "download": {
3407
+ switch (consoleProcess.args.downloadTarget) {
3408
+ case "variables": {
3409
+ this.downloadVariables(
3410
+ this.options.sitePath,
3411
+ this.options.templatePath,
3412
+ this.options.template,
3413
+ consoleProcess.args.overwrite
3414
+ );
3415
+ break;
3416
+ }
3417
+ case "template": {
3418
+ this.downloadTemplate(
3419
+ this.options.sitePath,
3420
+ this.options.templatePath,
3421
+ this.options.template,
3422
+ consoleProcess.args.overwrite
3423
+ );
3424
+ break;
3425
+ }
3426
+ default: {
3427
+ this._console.error(
3428
+ "Please specify a download target: 'variables' or 'template'"
3429
+ );
3430
+ }
3431
+ }
3432
+ break;
3433
+ }
3344
3434
  default: {
3345
3435
  await this.runBuild(consoleProcess.args.clean);
3346
3436
  break;
@@ -3393,6 +3483,56 @@ var Docula = class {
3393
3483
  `docula initialized. Please update the ${doculaConfigFile} file with your site information. In addition, you can replace the image and favicon.`
3394
3484
  );
3395
3485
  }
3486
+ /**
3487
+ * Copy the template's variables.css to the site directory.
3488
+ * If the file already exists and overwrite is false, prints an error.
3489
+ * @param {string} sitePath
3490
+ * @param {string} templatePath
3491
+ * @param {string} templateName
3492
+ * @param {boolean} overwrite
3493
+ * @returns {void}
3494
+ */
3495
+ downloadVariables(sitePath, templatePath, templateName, overwrite = false) {
3496
+ const resolvedTemplatePath = resolveTemplatePath(
3497
+ templatePath,
3498
+ templateName
3499
+ );
3500
+ const source = path6.join(resolvedTemplatePath, "css", "variables.css");
3501
+ const dest = path6.join(sitePath, "variables.css");
3502
+ if (fs4.existsSync(dest) && !overwrite) {
3503
+ this._console.error(
3504
+ `variables.css already exists at ${dest}. Use --overwrite to replace it.`
3505
+ );
3506
+ return;
3507
+ }
3508
+ fs4.copyFileSync(source, dest);
3509
+ this._console.success(`variables.css copied to ${dest}`);
3510
+ }
3511
+ /**
3512
+ * Copy the full template directory to {sitePath}/templates/{outputName}/.
3513
+ * If the directory already exists and overwrite is false, prints an error.
3514
+ * @param {string} sitePath
3515
+ * @param {string} templatePath
3516
+ * @param {string} templateName
3517
+ * @param {boolean} overwrite
3518
+ * @returns {void}
3519
+ */
3520
+ downloadTemplate(sitePath, templatePath, templateName, overwrite = false) {
3521
+ const resolvedTemplatePath = resolveTemplatePath(
3522
+ templatePath,
3523
+ templateName
3524
+ );
3525
+ const outputName = templatePath ? path6.basename(resolvedTemplatePath) : templateName;
3526
+ const dest = path6.join(sitePath, "templates", outputName);
3527
+ if (fs4.existsSync(dest) && !overwrite) {
3528
+ this._console.error(
3529
+ `Template already exists at ${dest}. Use --overwrite to replace it.`
3530
+ );
3531
+ return;
3532
+ }
3533
+ fs4.cpSync(resolvedTemplatePath, dest, { recursive: true, force: true });
3534
+ this._console.success(`Template copied to ${dest}`);
3535
+ }
3396
3536
  /**
3397
3537
  * Get the version of the package
3398
3538
  * @returns {string}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docula",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Beautiful Website for Your Projects",
5
5
  "type": "module",
6
6
  "main": "./dist/docula.js",
@@ -40,31 +40,31 @@
40
40
  "docula": "./bin/docula.js"
41
41
  },
42
42
  "dependencies": {
43
- "@cacheable/net": "^2.0.5",
43
+ "@cacheable/net": "^2.0.6",
44
44
  "colorette": "^2.0.20",
45
- "ecto": "^4.8.2",
45
+ "ecto": "^4.8.3",
46
46
  "feed": "^5.2.0",
47
47
  "hashery": "^1.5.0",
48
48
  "jiti": "^2.6.1",
49
- "serve-handler": "^6.1.6",
49
+ "serve-handler": "^6.1.7",
50
50
  "update-notifier": "^7.3.1",
51
- "writr": "^5.0.3"
51
+ "writr": "^6.0.1"
52
52
  },
53
53
  "devDependencies": {
54
- "@biomejs/biome": "^2.4.2",
54
+ "@biomejs/biome": "^2.4.7",
55
55
  "@playwright/test": "^1.58.2",
56
56
  "@types/express": "^5.0.6",
57
57
  "@types/js-yaml": "^4.0.9",
58
- "@types/node": "^25.2.3",
58
+ "@types/node": "^25.5.0",
59
59
  "@types/serve-handler": "^6.1.4",
60
60
  "@types/update-notifier": "^6.0.8",
61
- "@vitest/coverage-v8": "^4.0.18",
61
+ "@vitest/coverage-v8": "^4.1.0",
62
62
  "dotenv": "^17.3.1",
63
63
  "rimraf": "^6.1.3",
64
64
  "tsup": "^8.5.1",
65
65
  "tsx": "^4.21.0",
66
66
  "typescript": "^5.9.3",
67
- "vitest": "^4.0.18"
67
+ "vitest": "^4.1.0"
68
68
  },
69
69
  "files": [
70
70
  "dist",