docula 0.41.0 → 0.41.1

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.js ADDED
@@ -0,0 +1,1195 @@
1
+ // src/docula.ts
2
+ import fs2 from "fs";
3
+ import http from "http";
4
+ import path4 from "path";
5
+ import process4 from "process";
6
+ import { pathToFileURL } from "url";
7
+ import { createJiti } from "jiti";
8
+ import handler from "serve-handler";
9
+ import updateNotifier from "update-notifier";
10
+
11
+ // src/builder.ts
12
+ import fs from "fs";
13
+ import path3 from "path";
14
+ import { Ecto } from "ecto";
15
+ import { Writr } from "writr";
16
+
17
+ // src/console.ts
18
+ import path from "path";
19
+ import process from "process";
20
+ var DoculaConsole = class {
21
+ log(message) {
22
+ console.log(message);
23
+ }
24
+ error(message) {
25
+ console.error(message);
26
+ }
27
+ warn(message) {
28
+ console.warn(message);
29
+ }
30
+ printHelp() {
31
+ console.log(" Usage: docula [command] [arguments]");
32
+ console.log();
33
+ console.log(" Commands:");
34
+ console.log(" init Initialize a new project");
35
+ console.log(
36
+ " build Build the project. By default just npx docula will build the project if it finds a ./site folder"
37
+ );
38
+ console.log(" serve Serve the project as a local website");
39
+ console.log(" help Print this help");
40
+ console.log(" version Print the version");
41
+ console.log();
42
+ console.log(" Arguments init:");
43
+ console.log(
44
+ " --typescript Generate TypeScript config file (docula.config.ts)"
45
+ );
46
+ console.log(
47
+ " -s, --site Set the path where site files are located"
48
+ );
49
+ console.log();
50
+ console.log(" Arguments build:");
51
+ console.log(" -w, --watch watch for changes and rebuild");
52
+ console.log(
53
+ " -s, --site Set the path where site files are located"
54
+ );
55
+ console.log(
56
+ " -o, --outputPath Set the output directory. Default is ./site/dist"
57
+ );
58
+ console.log(" -t, --templatePath Set the custom template to use");
59
+ console.log();
60
+ console.log(" Arguments serve:");
61
+ console.log(" -p, --port Set the port number used with serve");
62
+ console.log(" -w, --watch watch for changes and rebuild");
63
+ console.log(
64
+ " -s, --site Set the path where site files are located"
65
+ );
66
+ }
67
+ parseProcessArgv(argv) {
68
+ const command = this.getCommand(argv);
69
+ const arguments_ = this.getArguments(argv);
70
+ return {
71
+ argv,
72
+ command,
73
+ args: arguments_
74
+ };
75
+ }
76
+ getCommand(argv) {
77
+ for (const argument of argv) {
78
+ switch (argument) {
79
+ case "init": {
80
+ return "init";
81
+ }
82
+ case "build": {
83
+ return "build";
84
+ }
85
+ case "serve": {
86
+ return "serve";
87
+ }
88
+ case "help": {
89
+ return "help";
90
+ }
91
+ case "version": {
92
+ return "version";
93
+ }
94
+ }
95
+ }
96
+ }
97
+ getArguments(argv) {
98
+ const arguments_ = {
99
+ sitePath: "",
100
+ templatePath: "",
101
+ output: "",
102
+ watch: false,
103
+ port: 3e3,
104
+ typescript: false
105
+ };
106
+ for (let i = 0; i < argv.length; i++) {
107
+ const argument = argv[i];
108
+ switch (argument) {
109
+ case "-p":
110
+ case "--port": {
111
+ const portString = argv[i + 1];
112
+ if (portString !== void 0) {
113
+ arguments_.port = Number.parseInt(portString, 10);
114
+ }
115
+ break;
116
+ }
117
+ case "-o":
118
+ case "--output": {
119
+ arguments_.output = argv[i + 1];
120
+ arguments_.output = path.join(process.cwd(), arguments_.output);
121
+ break;
122
+ }
123
+ case "-w":
124
+ case "--watch": {
125
+ arguments_.watch = true;
126
+ break;
127
+ }
128
+ case "-s":
129
+ case "--site": {
130
+ arguments_.sitePath = argv[i + 1];
131
+ arguments_.sitePath = path.join(process.cwd(), arguments_.sitePath);
132
+ break;
133
+ }
134
+ case "-t":
135
+ case "--templatePath": {
136
+ arguments_.templatePath = argv[i + 1];
137
+ arguments_.templatePath = path.join(
138
+ process.cwd(),
139
+ arguments_.templatePath
140
+ );
141
+ break;
142
+ }
143
+ case "--typescript": {
144
+ arguments_.typescript = true;
145
+ break;
146
+ }
147
+ }
148
+ }
149
+ return arguments_;
150
+ }
151
+ };
152
+
153
+ // src/github.ts
154
+ import process2 from "process";
155
+ import { CacheableNet } from "@cacheable/net";
156
+ var Github = class {
157
+ options = {
158
+ api: "https://api.github.com",
159
+ author: "",
160
+ repo: ""
161
+ };
162
+ net;
163
+ constructor(options) {
164
+ this.parseOptions(options);
165
+ this.net = new CacheableNet();
166
+ }
167
+ async getData() {
168
+ const data = {
169
+ releases: {},
170
+ contributors: {}
171
+ };
172
+ data.releases = await this.getReleases();
173
+ data.contributors = await this.getContributors();
174
+ return data;
175
+ }
176
+ // biome-ignore lint/suspicious/noExplicitAny: need to fix
177
+ async getReleases() {
178
+ const url = `${this.options.api}/repos/${this.options.author}/${this.options.repo}/releases`;
179
+ let options = {};
180
+ if (process2.env.GITHUB_TOKEN) {
181
+ options = {
182
+ headers: {
183
+ Authorization: `Bearer ${process2.env.GITHUB_TOKEN}`,
184
+ Accept: "application/vnd.github.v3+json"
185
+ }
186
+ };
187
+ }
188
+ try {
189
+ const result = await this.net.get(url, options);
190
+ if (result && result.data.length > 0) {
191
+ return this.addAnchorLink(result.data);
192
+ }
193
+ return [];
194
+ } catch (error) {
195
+ const typedError = error;
196
+ if (typedError.response?.status === 404) {
197
+ throw new Error(
198
+ `Repository ${this.options.author}/${this.options.repo} not found.`
199
+ );
200
+ }
201
+ throw error;
202
+ }
203
+ }
204
+ // biome-ignore lint/suspicious/noExplicitAny: need to fix
205
+ async getContributors() {
206
+ const url = `${this.options.api}/repos/${this.options.author}/${this.options.repo}/contributors`;
207
+ let options = {};
208
+ if (process2.env.GITHUB_TOKEN) {
209
+ options = {
210
+ headers: {
211
+ Authorization: `Bearer ${process2.env.GITHUB_TOKEN}`,
212
+ Accept: "application/vnd.github.v3+json"
213
+ }
214
+ };
215
+ }
216
+ try {
217
+ const result = await this.net.get(url, options);
218
+ if (result && result.data.length > 0) {
219
+ return result.data;
220
+ }
221
+ } catch (error) {
222
+ const typedError = error;
223
+ if (typedError.response?.status === 404) {
224
+ throw new Error(
225
+ `Repository ${this.options.author}/${this.options.repo} not found.`
226
+ );
227
+ }
228
+ throw error;
229
+ }
230
+ }
231
+ parseOptions(options) {
232
+ if (options.api) {
233
+ this.options.api = options.api;
234
+ }
235
+ this.options.author = options.author;
236
+ this.options.repo = options.repo;
237
+ }
238
+ // biome-ignore lint/suspicious/noExplicitAny: need to fix
239
+ addAnchorLink(data) {
240
+ return data.map((release) => {
241
+ const regex = /(?<!]\()(https:\/\/[\w./]+)(?!\))/g;
242
+ release.body = release.body.replaceAll(regex, "[$1]($1)");
243
+ return release;
244
+ });
245
+ }
246
+ };
247
+
248
+ // src/options.ts
249
+ import path2 from "path";
250
+ import process3 from "process";
251
+ var DoculaOptions = class {
252
+ /**
253
+ * Path to the template directory
254
+ */
255
+ templatePath = path2.join(import.meta.url, "../../template").replace("file:", "");
256
+ /**
257
+ * Path to the output directory
258
+ */
259
+ outputPath = path2.join(process3.cwd(), "./dist");
260
+ /**
261
+ * Path to the site directory
262
+ */
263
+ sitePath = path2.join(process3.cwd(), "./site");
264
+ /**
265
+ * Path to the github repository
266
+ */
267
+ githubPath = "jaredwray/docula";
268
+ /**
269
+ * Site title
270
+ */
271
+ siteTitle = "docula";
272
+ /**
273
+ * Site description
274
+ */
275
+ siteDescription = "Beautiful Website for Your Projects";
276
+ /**
277
+ * Site URL
278
+ */
279
+ siteUrl = "https://docula.org";
280
+ /**
281
+ * Port to run the server
282
+ */
283
+ port = 3e3;
284
+ /**
285
+ * Single page website
286
+ */
287
+ singlePage = true;
288
+ /**
289
+ * Sections
290
+ */
291
+ sections;
292
+ /**
293
+ * OpenAPI specification URL for API documentation.
294
+ * When provided, creates a dedicated /api page
295
+ * Supports both external URLs (https://...) and relative paths (/openapi.json)
296
+ */
297
+ openApiUrl;
298
+ constructor(options) {
299
+ if (options) {
300
+ this.parseOptions(options);
301
+ }
302
+ }
303
+ // biome-ignore lint/suspicious/noExplicitAny: need to fix
304
+ parseOptions(options) {
305
+ if (options.templatePath) {
306
+ this.templatePath = options.templatePath;
307
+ this.templatePath = path2.join(process3.cwd(), this.templatePath);
308
+ }
309
+ if (options.outputPath) {
310
+ this.outputPath = options.outputPath;
311
+ this.githubPath = path2.join(process3.cwd(), this.outputPath);
312
+ }
313
+ if (options.sitePath) {
314
+ this.sitePath = options.sitePath;
315
+ this.sitePath = path2.join(process3.cwd(), this.sitePath);
316
+ }
317
+ if (options.githubPath) {
318
+ this.githubPath = options.githubPath;
319
+ }
320
+ if (options.siteTitle) {
321
+ this.siteTitle = options.siteTitle;
322
+ }
323
+ if (options.siteDescription) {
324
+ this.siteDescription = options.siteDescription;
325
+ }
326
+ if (options.siteUrl) {
327
+ this.siteUrl = options.siteUrl;
328
+ }
329
+ if (options.sections) {
330
+ this.sections = options.sections;
331
+ }
332
+ if (options.port) {
333
+ this.port = options.port;
334
+ }
335
+ if (options.singlePage !== void 0 && typeof options.singlePage === "boolean") {
336
+ this.singlePage = options.singlePage;
337
+ }
338
+ if (options.openApiUrl) {
339
+ this.openApiUrl = options.openApiUrl;
340
+ }
341
+ }
342
+ };
343
+
344
+ // src/builder.ts
345
+ var DoculaBuilder = class {
346
+ _options = new DoculaOptions();
347
+ _ecto;
348
+ _console = new DoculaConsole();
349
+ // biome-ignore lint/suspicious/noExplicitAny: need to fix
350
+ constructor(options, engineOptions) {
351
+ if (options) {
352
+ this._options = options;
353
+ }
354
+ this._ecto = new Ecto(engineOptions);
355
+ }
356
+ get options() {
357
+ return this._options;
358
+ }
359
+ async build() {
360
+ const startTime = Date.now();
361
+ this.validateOptions(this.options);
362
+ const doculaData = {
363
+ siteUrl: this.options.siteUrl,
364
+ siteTitle: this.options.siteTitle,
365
+ siteDescription: this.options.siteDescription,
366
+ sitePath: this.options.sitePath,
367
+ templatePath: this.options.templatePath,
368
+ outputPath: this.options.outputPath,
369
+ githubPath: this.options.githubPath,
370
+ sections: this.options.sections,
371
+ openApiUrl: this.options.openApiUrl
372
+ };
373
+ doculaData.github = await this.getGithubData(this.options.githubPath);
374
+ doculaData.documents = this.getDocuments(
375
+ `${doculaData.sitePath}/docs`,
376
+ doculaData
377
+ );
378
+ doculaData.sections = this.getSections(
379
+ `${doculaData.sitePath}/docs`,
380
+ this.options
381
+ );
382
+ doculaData.hasDocuments = doculaData.documents?.length > 0;
383
+ const changelogPath = `${doculaData.sitePath}/changelog`;
384
+ doculaData.changelogEntries = this.getChangelogEntries(changelogPath);
385
+ doculaData.hasChangelog = doculaData.changelogEntries.length > 0;
386
+ doculaData.templates = await this.getTemplates(
387
+ this.options,
388
+ doculaData.hasDocuments,
389
+ doculaData.hasChangelog
390
+ );
391
+ await this.buildIndexPage(doculaData);
392
+ await this.buildReleasePage(doculaData);
393
+ await this.buildSiteMapPage(doculaData);
394
+ await this.buildRobotsPage(this.options);
395
+ if (doculaData.hasDocuments) {
396
+ await this.buildDocsPages(doculaData);
397
+ }
398
+ if (doculaData.openApiUrl) {
399
+ await this.buildApiPage(doculaData);
400
+ }
401
+ if (doculaData.hasChangelog) {
402
+ await this.buildChangelogPage(doculaData);
403
+ await this.buildChangelogEntryPages(doculaData);
404
+ }
405
+ const siteRelativePath = this.options.sitePath;
406
+ if (fs.existsSync(`${siteRelativePath}/favicon.ico`)) {
407
+ await fs.promises.copyFile(
408
+ `${siteRelativePath}/favicon.ico`,
409
+ `${this.options.outputPath}/favicon.ico`
410
+ );
411
+ }
412
+ if (fs.existsSync(`${siteRelativePath}/logo.svg`)) {
413
+ await fs.promises.copyFile(
414
+ `${siteRelativePath}/logo.svg`,
415
+ `${this.options.outputPath}/logo.svg`
416
+ );
417
+ }
418
+ if (fs.existsSync(`${siteRelativePath}/logo_horizontal.png`)) {
419
+ await fs.promises.copyFile(
420
+ `${siteRelativePath}/logo_horizontal.png`,
421
+ `${this.options.outputPath}/logo_horizontal.png`
422
+ );
423
+ }
424
+ if (fs.existsSync(`${this.options.templatePath}/css`)) {
425
+ this.copyDirectory(
426
+ `${this.options.templatePath}/css`,
427
+ `${this.options.outputPath}/css`
428
+ );
429
+ }
430
+ if (fs.existsSync(`${siteRelativePath}/variables.css`)) {
431
+ await fs.promises.copyFile(
432
+ `${siteRelativePath}/variables.css`,
433
+ `${this.options.outputPath}/css/variables.css`
434
+ );
435
+ }
436
+ this.copyPublicFolder(siteRelativePath, this.options.outputPath);
437
+ const endTime = Date.now();
438
+ const executionTime = endTime - startTime;
439
+ this._console.log(`Build completed in ${executionTime}ms`);
440
+ }
441
+ validateOptions(options) {
442
+ if (options.githubPath.length < 3) {
443
+ throw new Error("No github options provided");
444
+ }
445
+ if (options.siteDescription.length < 3) {
446
+ throw new Error("No site description options provided");
447
+ }
448
+ if (!options.siteTitle) {
449
+ throw new Error("No site title options provided");
450
+ }
451
+ if (!options.siteUrl) {
452
+ throw new Error("No site url options provided");
453
+ }
454
+ }
455
+ async getGithubData(githubPath) {
456
+ const paths = githubPath.split("/");
457
+ const options = {
458
+ author: paths[0],
459
+ repo: paths[1]
460
+ };
461
+ const github = new Github(options);
462
+ return github.getData();
463
+ }
464
+ async getTemplates(options, hasDocuments, hasChangelog = false) {
465
+ const templates = {
466
+ index: "",
467
+ releases: ""
468
+ };
469
+ if (fs.existsSync(options.templatePath)) {
470
+ const index = await this.getTemplateFile(options.templatePath, "index");
471
+ if (index) {
472
+ templates.index = index;
473
+ }
474
+ const releases = await this.getTemplateFile(
475
+ options.templatePath,
476
+ "releases"
477
+ );
478
+ if (releases) {
479
+ templates.releases = releases;
480
+ }
481
+ const documentPage = hasDocuments ? await this.getTemplateFile(options.templatePath, "docs") : void 0;
482
+ if (documentPage) {
483
+ templates.docPage = documentPage;
484
+ }
485
+ const apiPage = options.openApiUrl ? await this.getTemplateFile(options.templatePath, "api") : void 0;
486
+ if (apiPage) {
487
+ templates.api = apiPage;
488
+ }
489
+ const changelogPage = hasChangelog ? await this.getTemplateFile(options.templatePath, "changelog") : void 0;
490
+ if (changelogPage) {
491
+ templates.changelog = changelogPage;
492
+ }
493
+ const changelogEntryPage = hasChangelog ? await this.getTemplateFile(options.templatePath, "changelog-entry") : void 0;
494
+ if (changelogEntryPage) {
495
+ templates.changelogEntry = changelogEntryPage;
496
+ }
497
+ } else {
498
+ throw new Error(`No template path found at ${options.templatePath}`);
499
+ }
500
+ return templates;
501
+ }
502
+ async getTemplateFile(path5, name) {
503
+ let result;
504
+ const files = await fs.promises.readdir(path5);
505
+ for (const file of files) {
506
+ const fileName = file.split(".");
507
+ if (fileName[0].toString().toLowerCase() === name.toLowerCase()) {
508
+ result = file.toString();
509
+ break;
510
+ }
511
+ }
512
+ return result;
513
+ }
514
+ async buildRobotsPage(options) {
515
+ const { sitePath } = options;
516
+ const { outputPath } = options;
517
+ const robotsPath = `${outputPath}/robots.txt`;
518
+ await fs.promises.mkdir(outputPath, { recursive: true });
519
+ await (fs.existsSync(`${sitePath}/robots.txt`) ? fs.promises.copyFile(`${sitePath}/robots.txt`, robotsPath) : fs.promises.writeFile(robotsPath, "User-agent: *\nDisallow:"));
520
+ }
521
+ async buildSiteMapPage(data) {
522
+ const sitemapPath = `${data.outputPath}/sitemap.xml`;
523
+ const urls = [{ url: data.siteUrl }, { url: `${data.siteUrl}/releases` }];
524
+ if (data.openApiUrl && data.templates?.api) {
525
+ urls.push({ url: `${data.siteUrl}/api` });
526
+ }
527
+ if (data.hasChangelog && data.templates?.changelog) {
528
+ urls.push({ url: `${data.siteUrl}/changelog` });
529
+ for (const entry of data.changelogEntries ?? []) {
530
+ urls.push({
531
+ url: `${data.siteUrl}/changelog/${entry.slug}`
532
+ });
533
+ }
534
+ }
535
+ for (const document of data.documents ?? []) {
536
+ let { urlPath } = document;
537
+ if (urlPath.endsWith("index.html")) {
538
+ urlPath = urlPath.slice(0, -10);
539
+ }
540
+ urls.push({ url: `${data.siteUrl}${urlPath}` });
541
+ }
542
+ let xml = '<?xml version="1.0" encoding="UTF-8"?>';
543
+ xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
544
+ for (const { url } of urls) {
545
+ xml += "<url>";
546
+ xml += `<loc>${url}</loc>`;
547
+ xml += "</url>";
548
+ }
549
+ xml += "</urlset>";
550
+ await fs.promises.mkdir(data.outputPath, { recursive: true });
551
+ await fs.promises.writeFile(sitemapPath, xml, "utf8");
552
+ }
553
+ async buildIndexPage(data) {
554
+ if (data.templates) {
555
+ const indexPath = `${data.outputPath}/index.html`;
556
+ await fs.promises.mkdir(data.outputPath, { recursive: true });
557
+ const indexTemplate = `${data.templatePath}/${data.templates.index}`;
558
+ let content;
559
+ if (!data.hasDocuments) {
560
+ content = await this.buildReadmeSection(data);
561
+ }
562
+ const announcement = await this.buildAnnouncementSection(data);
563
+ const indexContent = await this._ecto.renderFromFile(
564
+ indexTemplate,
565
+ { ...data, content, announcement },
566
+ data.templatePath
567
+ );
568
+ await fs.promises.writeFile(indexPath, indexContent, "utf8");
569
+ } else {
570
+ throw new Error("No templates found");
571
+ }
572
+ }
573
+ async buildReleasePage(data) {
574
+ if (data.github && data.templates) {
575
+ const releasesPath = `${data.outputPath}/releases/index.html`;
576
+ const releaseOutputPath = `${data.outputPath}/releases`;
577
+ await fs.promises.mkdir(releaseOutputPath, { recursive: true });
578
+ const releasesTemplate = `${data.templatePath}/${data.templates.releases}`;
579
+ const releasesContent = await this._ecto.renderFromFile(
580
+ releasesTemplate,
581
+ data,
582
+ data.templatePath
583
+ );
584
+ await fs.promises.writeFile(releasesPath, releasesContent, "utf8");
585
+ } else {
586
+ throw new Error("No github data found");
587
+ }
588
+ }
589
+ async buildReadmeSection(data) {
590
+ let htmlReadme = "";
591
+ if (fs.existsSync(`${data.sitePath}/README.md`)) {
592
+ const readmeContent = fs.readFileSync(
593
+ `${data.sitePath}/README.md`,
594
+ "utf8"
595
+ );
596
+ htmlReadme = await new Writr(readmeContent).render();
597
+ }
598
+ return htmlReadme;
599
+ }
600
+ async buildAnnouncementSection(data) {
601
+ const announcementPath = `${data.sitePath}/announcement.md`;
602
+ if (fs.existsSync(announcementPath)) {
603
+ const announcementContent = fs.readFileSync(announcementPath, "utf8");
604
+ return new Writr(announcementContent).render();
605
+ }
606
+ return void 0;
607
+ }
608
+ async buildDocsPages(data) {
609
+ if (data.templates && data.documents?.length) {
610
+ const documentsTemplate = `${data.templatePath}/${data.templates.docPage}`;
611
+ await fs.promises.mkdir(`${data.outputPath}/docs`, { recursive: true });
612
+ data.sidebarItems = this.generateSidebarItems(data);
613
+ const promises = data.documents.map(async (document) => {
614
+ const folder = document.urlPath.split("/").slice(0, -1).join("/");
615
+ await fs.promises.mkdir(`${data.outputPath}/${folder}`, {
616
+ recursive: true
617
+ });
618
+ const slug = `${data.outputPath}${document.urlPath}`;
619
+ const documentContent = await this._ecto.renderFromFile(
620
+ documentsTemplate,
621
+ { ...data, ...document },
622
+ data.templatePath
623
+ );
624
+ return fs.promises.writeFile(slug, documentContent, "utf8");
625
+ });
626
+ await Promise.all(promises);
627
+ } else {
628
+ throw new Error("No templates found");
629
+ }
630
+ }
631
+ async buildApiPage(data) {
632
+ if (!data.openApiUrl || !data.templates?.api) {
633
+ return;
634
+ }
635
+ const apiPath = `${data.outputPath}/api/index.html`;
636
+ const apiOutputPath = `${data.outputPath}/api`;
637
+ await fs.promises.mkdir(apiOutputPath, { recursive: true });
638
+ const apiTemplate = `${data.templatePath}/${data.templates.api}`;
639
+ const apiContent = await this._ecto.renderFromFile(
640
+ apiTemplate,
641
+ { ...data, specUrl: data.openApiUrl },
642
+ data.templatePath
643
+ );
644
+ await fs.promises.writeFile(apiPath, apiContent, "utf8");
645
+ }
646
+ getChangelogEntries(changelogPath) {
647
+ const entries = [];
648
+ if (!fs.existsSync(changelogPath)) {
649
+ return entries;
650
+ }
651
+ const files = fs.readdirSync(changelogPath);
652
+ for (const file of files) {
653
+ const filePath = `${changelogPath}/${file}`;
654
+ const stats = fs.statSync(filePath);
655
+ if (stats.isFile() && (file.endsWith(".md") || file.endsWith(".mdx"))) {
656
+ const entry = this.parseChangelogEntry(filePath);
657
+ entries.push(entry);
658
+ }
659
+ }
660
+ entries.sort((a, b) => {
661
+ const dateA = new Date(a.date).getTime();
662
+ const dateB = new Date(b.date).getTime();
663
+ if (Number.isNaN(dateA) && Number.isNaN(dateB)) {
664
+ return 0;
665
+ }
666
+ if (Number.isNaN(dateA)) {
667
+ return 1;
668
+ }
669
+ if (Number.isNaN(dateB)) {
670
+ return -1;
671
+ }
672
+ return dateB - dateA;
673
+ });
674
+ return entries;
675
+ }
676
+ parseChangelogEntry(filePath) {
677
+ const fileContent = fs.readFileSync(filePath, "utf8");
678
+ const writr = new Writr(fileContent);
679
+ const matterData = writr.frontMatter;
680
+ const markdownContent = writr.body;
681
+ const fileName = path3.basename(filePath, path3.extname(filePath));
682
+ const slug = fileName.replace(/^\d{4}-\d{2}-\d{2}-/, "");
683
+ const isMdx = filePath.endsWith(".mdx");
684
+ const tag = matterData.tag;
685
+ const tagClass = tag ? tag.toLowerCase().replace(/\s+/g, "-") : void 0;
686
+ let dateString = "";
687
+ if (matterData.date instanceof Date) {
688
+ dateString = matterData.date.toISOString().split("T")[0];
689
+ } else if (matterData.date) {
690
+ dateString = String(matterData.date);
691
+ }
692
+ let formattedDate = dateString;
693
+ const parsedDate = new Date(dateString);
694
+ if (!Number.isNaN(parsedDate.getTime())) {
695
+ formattedDate = parsedDate.toLocaleDateString("en-US", {
696
+ year: "numeric",
697
+ month: "long",
698
+ day: "numeric"
699
+ });
700
+ }
701
+ return {
702
+ title: matterData.title ?? fileName,
703
+ date: dateString,
704
+ formattedDate,
705
+ tag,
706
+ tagClass,
707
+ slug,
708
+ content: markdownContent,
709
+ generatedHtml: new Writr(markdownContent).renderSync({ mdx: isMdx }),
710
+ urlPath: `/changelog/${slug}/index.html`
711
+ };
712
+ }
713
+ async buildChangelogPage(data) {
714
+ if (!data.hasChangelog || !data.templates?.changelog) {
715
+ return;
716
+ }
717
+ const changelogOutputPath = `${data.outputPath}/changelog`;
718
+ const changelogIndexPath = `${changelogOutputPath}/index.html`;
719
+ await fs.promises.mkdir(changelogOutputPath, { recursive: true });
720
+ const changelogTemplate = `${data.templatePath}/${data.templates.changelog}`;
721
+ const changelogContent = await this._ecto.renderFromFile(
722
+ changelogTemplate,
723
+ { ...data, entries: data.changelogEntries },
724
+ data.templatePath
725
+ );
726
+ await fs.promises.writeFile(changelogIndexPath, changelogContent, "utf8");
727
+ }
728
+ async buildChangelogEntryPages(data) {
729
+ if (!data.hasChangelog || !data.templates?.changelogEntry || !data.changelogEntries?.length) {
730
+ return;
731
+ }
732
+ const entryTemplate = `${data.templatePath}/${data.templates.changelogEntry}`;
733
+ const promises = data.changelogEntries.map(async (entry) => {
734
+ const entryOutputPath = `${data.outputPath}/changelog/${entry.slug}`;
735
+ await fs.promises.mkdir(entryOutputPath, { recursive: true });
736
+ const entryContent = await this._ecto.renderFromFile(
737
+ entryTemplate,
738
+ { ...data, ...entry, entries: data.changelogEntries },
739
+ data.templatePath
740
+ );
741
+ const entryFilePath = `${entryOutputPath}/index.html`;
742
+ return fs.promises.writeFile(entryFilePath, entryContent, "utf8");
743
+ });
744
+ await Promise.all(promises);
745
+ }
746
+ generateSidebarItems(data) {
747
+ let sidebarItems = [...data.sections ?? []];
748
+ for (const document of data.documents ?? []) {
749
+ if (document.isRoot) {
750
+ sidebarItems.unshift({
751
+ path: document.urlPath.replace("index.html", ""),
752
+ name: document.navTitle,
753
+ order: document.order
754
+ });
755
+ } else {
756
+ const relativeFilePath = document.documentPath.replace(
757
+ `${data.sitePath}/docs/`,
758
+ ""
759
+ );
760
+ const sectionPath = relativeFilePath.slice(
761
+ 0,
762
+ Math.max(0, relativeFilePath.lastIndexOf("/"))
763
+ );
764
+ const documentSection = document.section ?? sectionPath;
765
+ const sectionIndex = sidebarItems.findIndex(
766
+ (section) => section.path === documentSection
767
+ );
768
+ if (sectionIndex === -1) {
769
+ continue;
770
+ }
771
+ sidebarItems[sectionIndex].children ??= [];
772
+ sidebarItems[sectionIndex].children.push({
773
+ path: document.urlPath.replace("index.html", ""),
774
+ name: document.navTitle,
775
+ order: document.order
776
+ });
777
+ }
778
+ }
779
+ sidebarItems = sidebarItems.map((section) => {
780
+ if (section.children) {
781
+ section.children.sort(
782
+ (a, b) => (
783
+ // biome-ignore lint/style/noNonNullAssertion: need to fix
784
+ (a.order ?? section.children.length) - // biome-ignore lint/style/noNonNullAssertion: need to fix
785
+ (b.order ?? section.children.length)
786
+ )
787
+ );
788
+ }
789
+ return section;
790
+ });
791
+ sidebarItems.sort(
792
+ (a, b) => (a.order ?? sidebarItems.length) - (b.order ?? sidebarItems.length)
793
+ );
794
+ return sidebarItems;
795
+ }
796
+ getDocuments(sitePath, doculaData) {
797
+ let documents = [];
798
+ if (fs.existsSync(sitePath)) {
799
+ documents = this.getDocumentInDirectory(sitePath);
800
+ doculaData.sections = this.getSections(sitePath, this.options);
801
+ for (const section of doculaData.sections) {
802
+ const sectionPath = `${sitePath}/${section.path}`;
803
+ const sectionDocuments = this.getDocumentInDirectory(sectionPath);
804
+ documents = [...documents, ...sectionDocuments];
805
+ }
806
+ }
807
+ return documents;
808
+ }
809
+ getDocumentInDirectory(sitePath) {
810
+ const documents = [];
811
+ const documentList = fs.readdirSync(sitePath);
812
+ if (documentList.length > 0) {
813
+ for (const document of documentList) {
814
+ const documentPath = `${sitePath}/${document}`;
815
+ const stats = fs.statSync(documentPath);
816
+ if (stats.isFile()) {
817
+ const documentData = this.parseDocumentData(documentPath);
818
+ documents.push(documentData);
819
+ }
820
+ }
821
+ }
822
+ documents.sort(
823
+ (a, b) => (a.order ?? documents.length) - (b.order ?? documents.length)
824
+ );
825
+ return documents;
826
+ }
827
+ getSections(sitePath, doculaOptions) {
828
+ const sections = [];
829
+ if (fs.existsSync(sitePath)) {
830
+ const documentList = fs.readdirSync(sitePath);
831
+ if (documentList.length > 0) {
832
+ for (const document of documentList) {
833
+ const documentPath = `${sitePath}/${document}`;
834
+ const stats = fs.statSync(documentPath);
835
+ if (stats.isDirectory()) {
836
+ const section = {
837
+ name: document.replaceAll("-", " ").replaceAll(/\b\w/g, (l) => l.toUpperCase()),
838
+ path: document
839
+ };
840
+ this.mergeSectionWithOptions(section, doculaOptions);
841
+ sections.push(section);
842
+ }
843
+ }
844
+ }
845
+ sections.sort(
846
+ (a, b) => (a.order ?? sections.length) - (b.order ?? sections.length)
847
+ );
848
+ }
849
+ return sections;
850
+ }
851
+ mergeSectionWithOptions(section, options) {
852
+ if (options.sections) {
853
+ const sectionOptions = options.sections.find(
854
+ (sectionOption) => sectionOption.path === section.path
855
+ );
856
+ if (sectionOptions) {
857
+ section.name = sectionOptions.name;
858
+ section.order = sectionOptions.order;
859
+ section.path = sectionOptions.path;
860
+ }
861
+ }
862
+ return section;
863
+ }
864
+ parseDocumentData(documentPath) {
865
+ const documentContent = fs.readFileSync(documentPath, "utf8");
866
+ const writr = new Writr(documentContent);
867
+ const matterData = writr.frontMatter;
868
+ let markdownContent = writr.body;
869
+ markdownContent = markdownContent.replace(/^# .*\n/, "");
870
+ const isMdx = documentPath.endsWith(".mdx");
871
+ const fileExtension = isMdx ? ".mdx" : ".md";
872
+ const documentsFolderIndex = documentPath.lastIndexOf("/docs/");
873
+ let urlPath = documentPath.slice(documentsFolderIndex).replace(fileExtension, "/index.html");
874
+ let isRoot = urlPath.split("/").length === 3;
875
+ if (!documentPath.slice(documentsFolderIndex + 6).includes("/")) {
876
+ isRoot = true;
877
+ const filePath = documentPath.slice(documentsFolderIndex + 6);
878
+ if (filePath === "index.md" || filePath === "index.mdx") {
879
+ urlPath = documentPath.slice(documentsFolderIndex).replace(fileExtension, ".html");
880
+ }
881
+ }
882
+ if (!this.hasTableOfContents(markdownContent)) {
883
+ markdownContent = `## Table of Contents
884
+
885
+ ${markdownContent}`;
886
+ }
887
+ return {
888
+ title: matterData.title,
889
+ navTitle: matterData.navTitle ?? matterData.title,
890
+ description: matterData.description ?? "",
891
+ order: matterData.order ?? void 0,
892
+ section: matterData.section ?? void 0,
893
+ keywords: matterData.keywords ?? [],
894
+ content: documentContent,
895
+ markdown: markdownContent,
896
+ generatedHtml: new Writr(markdownContent).renderSync({
897
+ toc: true,
898
+ mdx: isMdx
899
+ }),
900
+ documentPath,
901
+ urlPath,
902
+ isRoot
903
+ };
904
+ }
905
+ hasTableOfContents(markdown) {
906
+ const normalized = markdown.replace(/\r\n/g, "\n");
907
+ const atxHeading = /^#{1,6}\s*(table of contents|toc)\s*$/im;
908
+ const setextHeading = /^(table of contents|toc)\s*\n[-=]{2,}\s*$/im;
909
+ const htmlHeading = /<h[1-6][^>]*>\s*(table of contents|toc)\s*<\/h[1-6]>/i;
910
+ return atxHeading.test(normalized) || setextHeading.test(normalized) || htmlHeading.test(normalized);
911
+ }
912
+ copyDirectory(source, target) {
913
+ const files = fs.readdirSync(source);
914
+ for (const file of files) {
915
+ if (file.startsWith(".")) {
916
+ continue;
917
+ }
918
+ const sourcePath = `${source}/${file}`;
919
+ const targetPath = `${target}/${file}`;
920
+ const stat = fs.lstatSync(sourcePath);
921
+ if (stat.isDirectory()) {
922
+ fs.mkdirSync(targetPath, { recursive: true });
923
+ this.copyDirectory(sourcePath, targetPath);
924
+ } else {
925
+ fs.mkdirSync(target, { recursive: true });
926
+ fs.copyFileSync(sourcePath, targetPath);
927
+ }
928
+ }
929
+ }
930
+ copyPublicFolder(sitePath, outputPath) {
931
+ const publicPath = `${sitePath}/public`;
932
+ if (!fs.existsSync(publicPath)) {
933
+ return;
934
+ }
935
+ this._console.log("Public folder found, copying contents to dist...");
936
+ const resolvedOutputPath = path3.resolve(outputPath);
937
+ this.copyPublicDirectory(
938
+ publicPath,
939
+ outputPath,
940
+ publicPath,
941
+ resolvedOutputPath
942
+ );
943
+ }
944
+ copyPublicDirectory(source, target, basePath, outputPath) {
945
+ const files = fs.readdirSync(source);
946
+ for (const file of files) {
947
+ const sourcePath = `${source}/${file}`;
948
+ const targetPath = `${target}/${file}`;
949
+ const relativePath = sourcePath.replace(`${basePath}/`, "");
950
+ const resolvedSourcePath = path3.resolve(sourcePath);
951
+ if (resolvedSourcePath === outputPath || resolvedSourcePath.startsWith(`${outputPath}${path3.sep}`)) {
952
+ continue;
953
+ }
954
+ const stat = fs.lstatSync(sourcePath);
955
+ if (stat.isDirectory()) {
956
+ fs.mkdirSync(targetPath, { recursive: true });
957
+ this.copyPublicDirectory(sourcePath, targetPath, basePath, outputPath);
958
+ } else {
959
+ fs.mkdirSync(target, { recursive: true });
960
+ fs.copyFileSync(sourcePath, targetPath);
961
+ this._console.log(` Copied: ${relativePath}`);
962
+ }
963
+ }
964
+ }
965
+ };
966
+
967
+ // src/init.ts
968
+ var doculaconfigmjs = "ZXhwb3J0IGNvbnN0IG9wdGlvbnMgPSB7Cgl0ZW1wbGF0ZVBhdGg6ICcuL3RlbXBsYXRlJywKCW91dHB1dFBhdGg6ICcuL2Rpc3QnLAoJc2l0ZVBhdGg6ICcuL3NpdGUnLAoJZ2l0aHViUGF0aDogJ2phcmVkd3JheS9kb2N1bGEnLAoJc2l0ZVRpdGxlOiAnRG9jdWxhJywKCXNpdGVEZXNjcmlwdGlvbjogJ0JlYXV0aWZ1bCBXZWJzaXRlIGZvciBZb3VyIFByb2plY3RzJywKCXNpdGVVcmw6ICdodHRwczovL2RvY3VsYS5vcmcnLAp9OwoK";
969
+ var doculaconfigts = "aW1wb3J0IHR5cGUgeyBEb2N1bGFPcHRpb25zIH0gZnJvbSAnZG9jdWxhJzsKCmV4cG9ydCBjb25zdCBvcHRpb25zOiBQYXJ0aWFsPERvY3VsYU9wdGlvbnM+ID0gewoJdGVtcGxhdGVQYXRoOiAnLi90ZW1wbGF0ZScsCglvdXRwdXRQYXRoOiAnLi9kaXN0JywKCXNpdGVQYXRoOiAnLi9zaXRlJywKCWdpdGh1YlBhdGg6ICdqYXJlZHdyYXkvZG9jdWxhJywKCXNpdGVUaXRsZTogJ0RvY3VsYScsCglzaXRlRGVzY3JpcHRpb246ICdCZWF1dGlmdWwgV2Vic2l0ZSBmb3IgWW91ciBQcm9qZWN0cycsCglzaXRlVXJsOiAnaHR0cHM6Ly9kb2N1bGEub3JnJywKfTsK";
970
+ var faviconico = "AAABAAEAAAAAAAEAIAA6FAAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAEAAAABAAgEAAAA9ntg7QAAAAFvck5UAc+id5oAABP0SURBVHja7V17cFTXfb7iYcnCQmA3tiNDIabYBheHl2OSeKYttsNMKLYcnHFASaAxiYydGfUxiFcdRJOBOsaQPzJITmzcmRpS17ZaFBtIUhOeqjCFoRiQOklw8ASJICIkXooeq6/f7r27Wq12pV3tfZx77u87Mx7Pot17z+/7zjm/8zvn/I5haIISA4llGAowHtMxD0uwElvwBvagDmdwDhdxBe3oQghhhPh/7fzkIj5GPY7wr7bjB1iFpfzmDP5CAYYn/vaLhkAR9CO9EJMxF89gA3ZgPxpwAVfRiR5kih5+6yq/3YAD+Ak2YhkewT0Ywyf0eaJADeILcB8exxqS/gHO4wacQDsacZRiWIsnMAWjRQgqUD8Gs9jaq1CLJrZYt9DJp9Xyqcv49LEiAy+oz8O9WIytbJEt8BItfINKlLD/yRMZuEP9aMxBOXaxow9BFYQ4OOymozknfmAQ2E19AR7GehxCK1RFKw7jn/iWIgObqc/ldGw1vfE2+AFXcJDu6Ey+tcjABvLHcRa/E83wG5r51kv59iKCIZOfyzF1E+oVGusz9w0aWIM5vX2BIF3yx2Ihqj328O2bKVTjqd7poiApZveSX4TldKY6oBM6WKPlrJlVx1IhPEXLn8Ap3skhBG79gB58yNpNlJ4gNflrOGbqjgasFRH0J78IK+juBQX17AmKAi+COIevFCcQNJxgrYPrGMZN9YqxD90IIrpZ8+JAThFj9M/GDlxHkHGdFpgdKAnEyL8T69AIAWiFClojGCKwqjmCXd8RYT4OR/AkRmougVjbn4QqXBPOE3CNVpmkcT9gVW0kFuGUsJ0Cp2gdHfuBuFBPlUP79XTBDbxCK+nVD1jVycF8HBeG08BxWipHGwnENm9W4LJwmyYu01pjtJCARf/9qNF0gce5haMaWs3fEoh1/cUBivLbu2xU7OOhwKI/H6uk689iKFhNC/pRArE1vm0BjfPbt17wenTd0H/0P4D3hUEbsJeW9JMELPofxWnhziacpjX9IYGY41eC88KbrQtGJT5wCGNLPWUKn97xK1pp1RFKSyB2bLMC7cKXA2inZfOUlYBF/y3YjC7hyiF00bq3KCkBi/5CVPr4HI8fEKKFC5WTQCze/5ow5AJei24mVY3+bcKNS3hdoaWiWOcvrd/dXkCNgSDm+lUKJy6jUgl30Jr4bRbXzwN3cLM5KfSa/hGcncrEz5tJYYUZGvKS/hyUSdjHw9BQmRkg9m70L5Ggr8cB4hJPPIHYip+c7fEajR6sFMbW+2XBVwWcdn2/gLXbZ6/YXhHsNXcNuUl/vsT9lMI2c++ge77/atnrpxS6yYgb8wFr9C+Wnb7K4TJZcdoTiB3zaBB7K4h6x4+SWKt+NWJrRVFjrhI6O/pXyCEvZdFDdpzyBKzuf76M/op7AvMdGgas8/1ywFt1HDfzCzhB/0hUiX19gCozy4j93f8iye7hC9wgU/YOA1ZqJ8nt4xecMtNNSfcvw4CNsT9J7OYnXLMtLmhl9ZS0jn5DnZl91J72XyH29CHW2dAHWCmdZd+PH9FopqHOlv5c7BBb+hQ7zGT02QmgOOAJ3f2M66YrmA39Y7FP7Ohj7DMPkg5dAKWy88fX6CaDQxOAtfHzhNjQ5zgxpA2jC0wBrBD7aYAVYS5nD2nxV1K86oD6ISwQRwSwRmynCdZkKACr/cvWT13QkGEfEBFAudhNI5RnIADL/z8pVtMIJzOYC0QEsFz2/mqFHjKangCs+N9hsZlmOJxmTDAigIXoEItphg6yOrgArPW/arGXhqhOY20wIoA5aBFraYgWMpuWADbpWf8DaZ5qOYpDukpg0yACiNA/Ts8A0HsYj2moG/TvDmEqJuBnegqggewOJIGIAJbqmPTxPbPmmIR/GyCpYSe2Y6IVBtVSAiEsGUwAudipX71/jj+NXV88CqX4MOlE+X+xLHpHG8tEPW+82hl2BAdq/zPQrN/YfzeMPmUcvo1f4AJbvDk/amJ7fw53JfzVn+noCzST4VR9QKTWq3Wr8TGO6UaSks/P57NHXML/TsHNSf9mmo77YVYPJIDROKhXbX+Fh5JSm275HH6jmwAOkuWU7f9htOlU19/ji1nRHy4LcFEvAbSR5WR9QKS263Wq6Q18M2v6w+VZ3bJhr08lgNE6eT092Bi9Zi/LMgIv6SWAQ0kGASsE3OongrtjJZRk7fo/o9fq2FBuxbtJnh/ik7tYzDfwEVqThIQj9VypIs3tuISzOI69eBuvYhO+g79np7wUi/BlfAlPsjyFr+Dr+Bb+FmvxIl7Bv3MGvzuF7x8uU/EF3Nbv09v4aervPMCJ4n/hTVThn/mUMg4uX8PTWIhiPBF7g1L8HV5gb/EjvMW/PUb3sZnDkJLbKlYmE0AeraYEOkn5GfychlxLMz9C44/HWE7UhqfZXoezKvkp//UznBl04V8T/iKfn3TxXz6T8nuj+KvDMniDMRiHP8dfoQSrKJs9OEU5dKoigF3hy2YS2/+93l733EWf/QPSsJJt6tO4I3pHqu3l+cjTfmeFfHvjfr+LfP68Q0/Nxe2YxhnFCvwL6nDB6zt2zpPt+D7Auvsj5E17P8f2sYHd6VQURi/IdrBMx0lc50DRV2B5bKXX+S/THX9+Dj2wKRw2vstm+Fuv9t2EzHtG+grA9Yvf/kB39PscRe92rLUnLxPxWRT0+7SAn0509T1y8Sn2CRuxn0Oe69iaKICxOOre0xtRQ0dqVhIaglhuYb/zbfyHuyPw0fAOwfj2P8udXUCXOKF6jp39TUJ8QrkJ93EeUeNW3LGFjEf7gMjzn3H6iR34H07hZrrc3fut5LI3WEtn2AXf4Jm+AnA0C+BlvMO58p8IwWmW2+gkvuV0l1wVL4DRqHXqORfocX/e3I4qJaMh4bP0y5ucE0Bt2AUjvht+2hRnntRMZ3Nm2uETKYllGGbgh055BU10Osi++aQn7A9S3cBPqGEhP3sRPITtTuTp6iTr4UEg8pS19s8ynpJu30bX8Et0DG3H2qgAhtmbCfAqNvfbXycl21KEl2lZW7Ej3EGHf7vQziDQb/CVtJdtpGRShuNpezeofUDmIwKYbF8Qqg4PClUOlgfTONqSwZLQZFMAj9h1E8hJod/xMtu+zB03MNcUwDL7pn21eBsv4Zv4S0xMsdVaSublZkzAX5Cm7+MtHLbz4MYyUwAb7Xcwr+O3eJ9uy9OcbIoQhlrycA++zAb1C3zkzH0dG8ICGM4Ju2PoRiN+hjX4nKz8ZVQKMAersJvDtKOZejkPCD/rgPMrD204iNX4tHmRjZQB9yBPw0rsd2d/7gEUGBjv3nHw3+NNFIfnHlKSltF4nI3ygnu7AhowLrxHysUnAn+k7P4mya7coJdbsQS/dPsIygVMNzDP7gBTOp5BLb4mXkHcnqDFOOTFRtGrmGdQeJ7sVu7ELk5DZbEoh1Pmd73aHNqJJQadTc/OLrRwihPsVYMivIg/wDP0YJWBLfAUdfhCYOl/FP8Nj7HFwHav3+ESVgQwWHQz/kGFZCzbDezx/i268GPcHij6P4FXvD4dZGKPocqlsO/iU4GhfyJqoAjqDJxR5V324Z5A0D+Z831lcMbAx+q8zf5++bz0K3erdRHjOUOttHC7zCuvtS134D0ohYsGrqj1RtswSlv68/EaFMMVQ7UMSN1m+gotS7l617C2G2rMRvrGBR7Tkv7HvDgGPugM3FAxv1Gthp7AHWrewhMyoCQqtBNAhZqG7lFUAOfNnMbalBneJmAaUACKprh7RaPjJcNZG0URUtAJtCaomK3RXn5l8w13Geomwt2sjQA2Q1m0KxcI6sWvzBuPfV8msCbKos1Q94aQEJZqIQClL2G6qNRiUCLetCnft7f7/N+Ewjin0HJwf5x1OXWjM2v/Z1UWwBnDzvPGdqMDC3wvgAVqX8Ncp8SWMJ0jghVQGnsU2BQ6EN72uRcwgjVQGm94vi18YBwzL733bRnLGiiNLZ4eDBkcH/t8k9jdKk+ywgdDVnp2NCw9XDZzGvu2zGINFEbkaJgHh0MziFSG09j4uMxV+8q5yOFQl4+HZyrR+b4WwF+r3L1ax8NdTBCRObpRiiLchdvpTo3ySX6RkXzTsXzju/jmpertAoxHfThBhCspYrIIVuMj/JpvehwH8VO8jo14jr3CA/iEQhPEEXybaXyr57CBb/hTvulxvvGv+eaKXzsbSRHjaJIopyKEzfgQ1fgOjT7Bw35hBJ/+Rb5FNd+mWe2IX3JEkkQ5kibOPSmcxTtsefe7fAnNTXzicrzNp/8RPsYGmxNFeocmyuCr+KQr5N+JEj6tCRpgmc2pYr12GE/iBYcPmE7GP/Ip3dACsVSxk1XdsjoUfITvYZIj5E/iL5+FRogliy50885AN/B/KMOtNsf0y/irmiGWLt7mCyNUQAjv2xhDnMtfC0E7xC6McODKGBVwiRO0MVmTP4a/cglaInZljCOXRqmAHtRgalb0T+Uv9OhJfycejwjghXA9p+gxq0mGU1mcNX6M39YWkWvjVjl/caQKNf3qEK6lz+G3mqAxohdHunF1rNdoxbMZJqUdhuXuJGz3Dn2ujnXh8mhvcRXPZ9AL5PCvr0JzJFwe7dL18d7hCr6RtgC+oe55ObsQf328YUY6jupe50soTov+J3Wd9sXjaHi3rREnAAOV+tf6LB4alP45eoV7U2FrXPu3BFCiY7ArEYcxfkD6x+s8HepFiGz3E8C9Oi0JpcY25KWkP4//GgicJ9vxAjDM2u8OQt07OSVMJYDlegZE+2NXuBUYCQIwsDIYtT+XIgHVTP5LQFCe0P6NqP/TGoz6v5MkHe0oVAeF/lYynSgAKyB8KBgW6DSjIH3KsqB0/yDLo/vRb/UB64Nig9MJqScm8pPAYH2S9m8J4GG0BcUKG/oIYGNw6G8jy8kEYA0CB4Nih/OYHqN/OhqDI4ADsVXApH3A6uBYotJaIRwWhCBoL1anaP9GNKltc1AscREPRqr8oOoHuOxEszkHNlJKIBc7g2ONrchh2Rqk9r+TDBvGAAJQPK+hvWjEVNwfpPE/hCUDtH9LAONUPi5uN77HEiA0kN2BBGBJYFNwLNKk976/RGwahP5YSLgFAv3QkjQEnEQAucEJiwcK1WEHcBABWBJY6MdsB4IB0UFWB6ffiJ6FPCwW0wyHzZybRpoSWK7riaiAooeMpke/JYAinBSraYSTZDRdARjRe04F+qA8A/qN6FU3DWI3TdBgXr9kZCiBNWI5TbAmQ/pjfUC92E4D1Gfc/g1jgSmBFWI9DbAizOVswxhCH1CEE2I/n+NERv5/PwmU6pIUL6AIZ9seGv2xmOA+saKPsS/t+F9KCRTjutjRp7hunog3shJArn5ZBAOD7Wmt/w0qgdlB2jWlERrJXHb0G9GN8+vEmj7EOpM9wwYJ3IkjYk+foY6sZU9/rA8oxjWxqY9wLZoQybBJAiP1ziSoHarMK5VsgpUu/5TY1Sc4ZV6ZYNgqAAOL9LhZRHvcIFOGrQKQYcBn3f9Im+mPWyA+LvZVHMeGsPibwTAwX+3bkAOPy9G7dg2HJJCDCtkvrCx6yE6OQ/THJDAGNWJpRVFj3pFjOCoAA/fLVjElUU9mDEcFEBcXFE9AvdG/2HH64zyBVbJTSCl0k5EcF+iPSSA/KHmVfYJtZMQd+uM2jL4vdlcEe4e88TMrT+CBIKXXVBinyYThqgBiEng0GHcMKI1GsuA2/XESWByUDOOKotW8+8N1+uPmA2VoFx48Qjutn+MR/TEJjEAFuoQLD9BFy4/wkP6YBPLwcnCSSyqDEDab1x8ZngvAwC2olCUil1FJqxueCyAmgUK8Kpy4iNdocRXoj5PAGIkNuobXzVU/JejvI4FXZSBwpfWrRX+fgaBS3EGHXb9KhTr/pO7gyzIpdHDi97Iirt8AEsjj7FRCQ86EfSqi994qCkRDQ2USIHYg6Ftmhn2UpT9OAjlYLMtEtqIRJWbQV2n6E1YKZbHYLpz2aMUv6/0CsmXEDuz1YL3fJgl8Ettk72BW6KYFi3xHf5wE8rFKdhAPGZdpvXxf0t/HISyWcwRDQj0tl+Nb+hOOkuyUIHFG6EGNC8c8XF0nqJChIIOuv0LBeH/WQ8F8HBNu08BxWipHG/rjJBDOL1AlWUYGxA1aaELUXloB0SwjiyTXUEqconVGakh+Qj8wiSq/Kmwn4BqtMknLtp90uagYdcJ5HI7QIiM1Jz+hH7gT6yQHsbXQs87M6hkA+hNEMAvbA56M/jp2mCmdA0N+ggRy2fXtC+h6QTdrXmwmdA8Y/QkiGItvBfBuohMoNW/zCCT5/URQhBUBWjGoZ22LAk9+kjDRmgDcVtrAWk4Q8lOLoBwnNV046mHNyoX8FJgdPxw8i8Po0Ir8DtZoeW+3v0AIH9QxXIhqtGhBfgtr8pQ4fEOZIs7BS3SY/HvWKMQRfxNrkSvkD1UEBsZhCXai2XfkN/Otl/LtDSE/exHkYgZW4wDafEF9Gw7S05/R2+6FfHtkUIDPYz0OKXzqqJVvtx4PY7RQ75wMRnNMLccunFfINwjxbXZjJd9MqHdJBnm4F4uxFR94PFNowVFUooRvkyfUuy+D8GbTmXiGFNSiCZ2u0d7Jp9Wiik+e1Tu9E+q9k0HYP7gPj9P12sE+4bxD+w5v8JeP8glr8QSmxHf2Qr06QhiGQkzGXLbNDaRqP+pxAVfZYjMPLvfwW1f57QbOPnZgI5bhEf5yIZ8gxKuIkkQphMVQwHn4dMzDEjpoW/AG9qAOp3EOF3EF7eii89bDEuL/tfOTi/gYZ/gXe7Cdf72K35rHb4/nrwxP/O0XtbHb/wPBh64vbaYDKgAAAABJRU5ErkJggg==";
971
+ var logopng = "iVBORw0KGgoAAAANSUhEUgAAAxEAAAHXCAYAAADDSdfmAAAACXBIWXMAACxLAAAsSwGlPZapAAAFw2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgOS4xLWMwMDMgNzkuOTY5MGE4N2ZjLCAyMDI1LzAzLzA2LTIwOjUwOjE2ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjYuNiAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjUtMDUtMThUMTM6MzM6NTgtMDc6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI1LTA1LTE4VDEzOjM2OjE5LTA3OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI1LTA1LTE4VDEzOjM2OjE5LTA3OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5YTc4ZDY2Ny02NjAzLTQwNmUtYTViZC02MjYzMTNjY2VmY2QiIHhtcE1NOkRvY3VtZW50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";
972
+ var variablescss = "OnJvb3QgewogICAgLS1mb250LWZhbWlseTogJ09wZW4gU2FucycsIHNhbnMtc2VyaWY7CiAgCiAgICAtLWNvbG9yLXByaW1hcnk6ICAjMzIyZDNjOwogICAgLS1jb2xvci1zZWNvbmRhcnk6ICM4Y2RjMDA7CiAgICAtLWNvbG9yLXNlY29uZGFyeS1kYXJrOiAjOGNkYzAwOwogICAgLS1jb2xvci10ZXh0OiAjMzIyZDNjOwogIAogICAgLS1iYWNrZ3JvdW5kOiAjZmZmZmZmOwogICAgLS1ob21lLWJhY2tncm91bmQ6ICNmZmZmZmY7CiAgICAtLWhlYWRlci1iYWNrZ3JvdW5kOiAjZmZmZmZmOwogIAogICAgLS1zaWRlYmFyLWJhY2tncm91bmQ6ICNmZmZmZmY7CiAgICAtLXNpZGViYXItdGV4dDogIzMyMmQzYzsKICAgIC0tc2lkZWJhci10ZXh0LWFjdGl2ZTogIzdkNzg4NzsKICAKICAgIC0tYm9yZGVyOiByZ2JhKDIzOCwyMzgsMjQ1LDEpOwogIAogICAgLS1iYWNrZ3JvdW5kLXNlYXJjaC1oaWdobGlnaHQ6IHZhcigtLWNvbG9yLXNlY29uZGFyeS1kYXJrKTsKICAgIC0tY29sb3Itc2VhcmNoLWhpZ2hsaWdodDogI2ZmZmZmZjsKICAgIC0tc2VhcmNoLWlucHV0LWJhY2tncm91bmQ6IHZhcigtLWhlYWRlci1iYWNrZ3JvdW5kKTsKICAKICAgIC0tY29kZTogcmdiYSgyMzgsMjM4LDI0NSwxKTsKICAKICAgIC0tcGFnZWZpbmQtdWktdGV4dDogdmFyKC0tY29sb3ItdGV4dCkgIWltcG9ydGFudDsKICAgIC0tcGFnZWZpbmQtdWktZm9udDogdmFyKC0tZm9udC1mYW1pbHkpICFpbXBvcnRhbnQ7CiAgICAtLXBhZ2VmaW5kLXVpLWJhY2tncm91bmQ6IHZhcigtLWJhY2tncm91bmQpICFpbXBvcnRhbnQ7CiAgICAtLXBhZ2VmaW5kLXVpLWJvcmRlcjogdmFyKC0tYm9yZGVyKSAhaW1wb3J0YW50OwogICAgLS1wYWdlZmluZC11aS1zY2FsZTogLjkgIWltcG9ydGFudDsKICB9";
973
+
974
+ // src/docula.ts
975
+ import { Writr as Writr2 } from "writr";
976
+ var Docula = class {
977
+ _options = new DoculaOptions();
978
+ _console = new DoculaConsole();
979
+ // biome-ignore lint/suspicious/noExplicitAny: need to fix
980
+ _configFileModule = {};
981
+ _server;
982
+ /**
983
+ * Initialize the Docula class
984
+ * @param {DoculaOptions} options
985
+ * @returns {void}
986
+ * @constructor
987
+ */
988
+ constructor(options) {
989
+ if (options) {
990
+ this._options = options;
991
+ }
992
+ }
993
+ /**
994
+ * Get the options
995
+ * @returns {DoculaOptions}
996
+ */
997
+ get options() {
998
+ return this._options;
999
+ }
1000
+ /**
1001
+ * Set the options
1002
+ * @param {DoculaOptions} value
1003
+ */
1004
+ set options(value) {
1005
+ this._options = value;
1006
+ }
1007
+ /**
1008
+ * The http server used to serve the site
1009
+ * @returns {http.Server | undefined}
1010
+ */
1011
+ get server() {
1012
+ return this._server;
1013
+ }
1014
+ /**
1015
+ * The config file module. This is the module that is loaded from the docula.config.ts or docula.config.mjs file
1016
+ * @returns {any}
1017
+ */
1018
+ // biome-ignore lint/suspicious/noExplicitAny: need to fix
1019
+ get configFileModule() {
1020
+ return this._configFileModule;
1021
+ }
1022
+ /**
1023
+ * Check for updates
1024
+ * @returns {void}
1025
+ */
1026
+ checkForUpdates() {
1027
+ const packageJsonPath = path4.join(process4.cwd(), "package.json");
1028
+ if (fs2.existsSync(packageJsonPath)) {
1029
+ const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
1030
+ updateNotifier({ pkg: packageJson }).notify();
1031
+ }
1032
+ }
1033
+ /**
1034
+ * Is the execution process that runs the docula command
1035
+ * @param {NodeJS.Process} process
1036
+ * @returns {Promise<void>}
1037
+ */
1038
+ async execute(process5) {
1039
+ this.checkForUpdates();
1040
+ const consoleProcess = this._console.parseProcessArgv(process5.argv);
1041
+ this.options.singlePage = this.isSinglePageWebsite(this.options.sitePath);
1042
+ if (consoleProcess.args.sitePath) {
1043
+ this.options.sitePath = consoleProcess.args.sitePath;
1044
+ }
1045
+ await this.loadConfigFile(this.options.sitePath);
1046
+ if (this._configFileModule.options) {
1047
+ this.options.parseOptions(
1048
+ // biome-ignore lint/suspicious/noExplicitAny: need to fix
1049
+ this._configFileModule.options
1050
+ );
1051
+ }
1052
+ if (this._configFileModule.onPrepare) {
1053
+ try {
1054
+ await this._configFileModule.onPrepare(this.options);
1055
+ } catch (error) {
1056
+ this._console.error(error.message);
1057
+ }
1058
+ }
1059
+ if (consoleProcess.args.output) {
1060
+ this.options.outputPath = consoleProcess.args.output;
1061
+ }
1062
+ switch (consoleProcess.command) {
1063
+ case "init": {
1064
+ this.generateInit(
1065
+ this.options.sitePath,
1066
+ consoleProcess.args.typescript
1067
+ );
1068
+ break;
1069
+ }
1070
+ case "help": {
1071
+ this._console.printHelp();
1072
+ break;
1073
+ }
1074
+ case "version": {
1075
+ this._console.log(this.getVersion());
1076
+ break;
1077
+ }
1078
+ case "serve": {
1079
+ const builder = new DoculaBuilder(this.options);
1080
+ await builder.build();
1081
+ await this.serve(this.options);
1082
+ break;
1083
+ }
1084
+ default: {
1085
+ const builder = new DoculaBuilder(this.options);
1086
+ await builder.build();
1087
+ break;
1088
+ }
1089
+ }
1090
+ }
1091
+ /**
1092
+ * Checks if the site is a single page website
1093
+ * @param {string} sitePath
1094
+ * @returns {boolean}
1095
+ */
1096
+ isSinglePageWebsite(sitePath) {
1097
+ const documentationPath = `${sitePath}/docs`;
1098
+ if (!fs2.existsSync(documentationPath)) {
1099
+ return true;
1100
+ }
1101
+ const files = fs2.readdirSync(documentationPath);
1102
+ return files.length === 0;
1103
+ }
1104
+ /**
1105
+ * Generate the init files
1106
+ * @param {string} sitePath
1107
+ * @param {boolean} typescript - If true, generates docula.config.ts instead of docula.config.mjs
1108
+ * @returns {void}
1109
+ */
1110
+ generateInit(sitePath, typescript = false) {
1111
+ if (!fs2.existsSync(sitePath)) {
1112
+ fs2.mkdirSync(sitePath);
1113
+ }
1114
+ const configExtension = typescript ? "ts" : "mjs";
1115
+ const doculaConfigFile = `${sitePath}/docula.config.${configExtension}`;
1116
+ const doculaConfigFileBuffer = Buffer.from(
1117
+ typescript ? doculaconfigts : doculaconfigmjs,
1118
+ "base64"
1119
+ );
1120
+ fs2.writeFileSync(doculaConfigFile, doculaConfigFileBuffer);
1121
+ const logoBuffer = Buffer.from(logopng, "base64");
1122
+ fs2.writeFileSync(`${sitePath}/logo.png`, logoBuffer);
1123
+ const faviconBuffer = Buffer.from(faviconico, "base64");
1124
+ fs2.writeFileSync(`${sitePath}/favicon.ico`, faviconBuffer);
1125
+ const variablesBuffer = Buffer.from(variablescss, "base64");
1126
+ fs2.writeFileSync(`${sitePath}/variables.css`, variablesBuffer);
1127
+ this._console.log(
1128
+ `docula initialized. Please update the ${doculaConfigFile} file with your site information. In addition, you can replace the image, favicon, and style the site with site.css file.`
1129
+ );
1130
+ }
1131
+ /**
1132
+ * Get the version of the package
1133
+ * @returns {string}
1134
+ */
1135
+ getVersion() {
1136
+ const packageJson = fs2.readFileSync("./package.json", "utf8");
1137
+ const packageObject = JSON.parse(packageJson);
1138
+ return packageObject.version;
1139
+ }
1140
+ /**
1141
+ * Load the config file. Supports both .mjs and .ts config files.
1142
+ * Priority: docula.config.ts > docula.config.mjs
1143
+ * @param {string} sitePath
1144
+ * @returns {Promise<void>}
1145
+ */
1146
+ async loadConfigFile(sitePath) {
1147
+ if (!fs2.existsSync(sitePath)) {
1148
+ return;
1149
+ }
1150
+ const tsConfigFile = `${sitePath}/docula.config.ts`;
1151
+ const mjsConfigFile = `${sitePath}/docula.config.mjs`;
1152
+ if (fs2.existsSync(tsConfigFile)) {
1153
+ const absolutePath = path4.resolve(tsConfigFile);
1154
+ const jiti = createJiti(import.meta.url, {
1155
+ interopDefault: true
1156
+ });
1157
+ this._configFileModule = await jiti.import(absolutePath);
1158
+ return;
1159
+ }
1160
+ if (fs2.existsSync(mjsConfigFile)) {
1161
+ const absolutePath = path4.resolve(mjsConfigFile);
1162
+ this._configFileModule = await import(pathToFileURL(absolutePath).href);
1163
+ }
1164
+ }
1165
+ /**
1166
+ * Serve the site based on the options (port and output path)
1167
+ * @param {DoculaOptions} options
1168
+ * @returns {Promise<void>}
1169
+ */
1170
+ async serve(options) {
1171
+ if (this._server) {
1172
+ this._server.close();
1173
+ }
1174
+ const { port } = options;
1175
+ const { outputPath } = options;
1176
+ const config = {
1177
+ public: outputPath
1178
+ };
1179
+ this._server = http.createServer(
1180
+ async (request, response) => (
1181
+ /* v8 ignore next -- @preserve */
1182
+ handler(request, response, config)
1183
+ )
1184
+ );
1185
+ this._server.listen(port, () => {
1186
+ this._console.log(`Docula \u{1F987} at http://localhost:${port}`);
1187
+ });
1188
+ return this._server;
1189
+ }
1190
+ };
1191
+ export {
1192
+ Writr2 as Writr,
1193
+ Docula as default
1194
+ };
1195
+ /* v8 ignore next -- @preserve */