docula 1.2.0 → 1.5.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 +33 -716
- package/dist/docula.d.ts +82 -11
- package/dist/docula.js +736 -122
- package/package.json +6 -2
- package/templates/classic/changelog.hbs +23 -2
- package/templates/classic/css/base.css +75 -0
- package/templates/classic/css/variables.css +30 -0
- package/templates/classic/home.hbs +7 -0
- package/templates/modern/api.hbs +37 -0
- package/templates/modern/changelog.hbs +23 -2
- package/templates/modern/css/styles.css +124 -36
- package/templates/modern/css/variables.css +32 -0
- package/templates/modern/home.hbs +8 -1
- package/templates/modern/includes/footer.hbs +3 -0
- package/templates/modern/includes/header-bar.hbs +32 -14
- package/templates/modern/includes/header.hbs +15 -0
- package/templates/modern/includes/scripts.hbs +42 -33
- package/templates/modern/js/api.js +17 -6
package/dist/docula.js
CHANGED
|
@@ -12,6 +12,7 @@ import updateNotifier from "update-notifier";
|
|
|
12
12
|
import fs3 from "fs";
|
|
13
13
|
import path5 from "path";
|
|
14
14
|
import { Ecto } from "ecto";
|
|
15
|
+
import { Hashery } from "hashery";
|
|
15
16
|
import { Writr } from "writr";
|
|
16
17
|
|
|
17
18
|
// src/api-parser.ts
|
|
@@ -571,55 +572,52 @@ var DoculaConsole = class {
|
|
|
571
572
|
console.log(
|
|
572
573
|
` ${green("build")} Build the project. By default just npx docula will build the project if it finds a ./site folder`
|
|
573
574
|
);
|
|
575
|
+
console.log(
|
|
576
|
+
` ${green("dev")} Build, watch, and serve the project`
|
|
577
|
+
);
|
|
578
|
+
console.log(` ${green("start")} Build and serve the project`);
|
|
574
579
|
console.log(
|
|
575
580
|
` ${green("serve")} Serve the project as a local website`
|
|
576
581
|
);
|
|
577
582
|
console.log(` ${green("help")} Print this help`);
|
|
578
583
|
console.log(` ${green("version")} Print the version`);
|
|
579
584
|
console.log();
|
|
580
|
-
console.log(bold(cyan("
|
|
581
|
-
console.log(
|
|
582
|
-
` ${yellow("--typescript")} Generate TypeScript config file (docula.config.ts)`
|
|
583
|
-
);
|
|
584
|
-
console.log(
|
|
585
|
-
` ${yellow("-s, --site")} Set the path where site files are located`
|
|
586
|
-
);
|
|
587
|
-
console.log();
|
|
588
|
-
console.log(bold(cyan(" Arguments build:")));
|
|
585
|
+
console.log(bold(cyan(" Common Options:")));
|
|
589
586
|
console.log(
|
|
590
|
-
` ${yellow("-
|
|
587
|
+
` ${yellow("-s, --site")} Set the path where site files are located`
|
|
591
588
|
);
|
|
592
589
|
console.log(
|
|
593
590
|
` ${yellow("-c, --clean")} Clean the output directory before building`
|
|
594
591
|
);
|
|
595
|
-
console.log(
|
|
596
|
-
` ${yellow("-s, --site")} Set the path where site files are located`
|
|
597
|
-
);
|
|
598
592
|
console.log(
|
|
599
593
|
` ${yellow("-o, --output")} Set the output directory. Default is ./site/dist`
|
|
600
594
|
);
|
|
601
595
|
console.log(
|
|
602
|
-
` ${yellow("-
|
|
596
|
+
` ${yellow("-p, --port")} Set the port number. Default is 3000`
|
|
603
597
|
);
|
|
604
598
|
console.log(
|
|
605
|
-
` ${yellow("-
|
|
599
|
+
` ${yellow("-w, --watch")} Watch for changes and rebuild`
|
|
606
600
|
);
|
|
607
601
|
console.log();
|
|
608
|
-
console.log(bold(cyan("
|
|
602
|
+
console.log(bold(cyan(" Init Options:")));
|
|
609
603
|
console.log(
|
|
610
|
-
` ${yellow("
|
|
604
|
+
` ${yellow("--typescript")} Generate TypeScript config file (docula.config.ts)`
|
|
611
605
|
);
|
|
612
606
|
console.log(
|
|
613
|
-
` ${yellow("
|
|
607
|
+
` ${yellow("--javascript")} Generate JavaScript config file (docula.config.mjs)`
|
|
614
608
|
);
|
|
609
|
+
console.log();
|
|
610
|
+
console.log(bold(cyan(" Build / Dev Options:")));
|
|
615
611
|
console.log(
|
|
616
|
-
` ${yellow("-
|
|
612
|
+
` ${yellow("-t, --templatePath")} Set the custom template to use`
|
|
617
613
|
);
|
|
618
614
|
console.log(
|
|
619
|
-
` ${yellow("-
|
|
615
|
+
` ${yellow("-T, --template")} Set the built-in template name (e.g., modern, classic)`
|
|
620
616
|
);
|
|
617
|
+
console.log();
|
|
618
|
+
console.log(bold(cyan(" Serve Options:")));
|
|
621
619
|
console.log(
|
|
622
|
-
` ${yellow("-
|
|
620
|
+
` ${yellow("-b, --build")} Build the site before serving`
|
|
623
621
|
);
|
|
624
622
|
}
|
|
625
623
|
parseProcessArgv(argv) {
|
|
@@ -632,7 +630,28 @@ var DoculaConsole = class {
|
|
|
632
630
|
};
|
|
633
631
|
}
|
|
634
632
|
getCommand(argv) {
|
|
633
|
+
const flagsWithValues = /* @__PURE__ */ new Set([
|
|
634
|
+
"-s",
|
|
635
|
+
"--site",
|
|
636
|
+
"-o",
|
|
637
|
+
"--output",
|
|
638
|
+
"-p",
|
|
639
|
+
"--port",
|
|
640
|
+
"-t",
|
|
641
|
+
"--templatePath",
|
|
642
|
+
"-T",
|
|
643
|
+
"--template"
|
|
644
|
+
]);
|
|
645
|
+
let skipNext = false;
|
|
635
646
|
for (const argument of argv) {
|
|
647
|
+
if (skipNext) {
|
|
648
|
+
skipNext = false;
|
|
649
|
+
continue;
|
|
650
|
+
}
|
|
651
|
+
if (flagsWithValues.has(argument)) {
|
|
652
|
+
skipNext = true;
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
636
655
|
switch (argument) {
|
|
637
656
|
case "init": {
|
|
638
657
|
return "init";
|
|
@@ -643,7 +662,15 @@ var DoculaConsole = class {
|
|
|
643
662
|
case "serve": {
|
|
644
663
|
return "serve";
|
|
645
664
|
}
|
|
646
|
-
case "
|
|
665
|
+
case "dev": {
|
|
666
|
+
return "dev";
|
|
667
|
+
}
|
|
668
|
+
case "start": {
|
|
669
|
+
return "start";
|
|
670
|
+
}
|
|
671
|
+
case "help":
|
|
672
|
+
case "-h":
|
|
673
|
+
case "--help": {
|
|
647
674
|
return "help";
|
|
648
675
|
}
|
|
649
676
|
case "version": {
|
|
@@ -662,7 +689,8 @@ var DoculaConsole = class {
|
|
|
662
689
|
clean: false,
|
|
663
690
|
build: false,
|
|
664
691
|
port: void 0,
|
|
665
|
-
typescript: false
|
|
692
|
+
typescript: false,
|
|
693
|
+
javascript: false
|
|
666
694
|
};
|
|
667
695
|
for (let i = 0; i < argv.length; i++) {
|
|
668
696
|
const argument = argv[i];
|
|
@@ -720,6 +748,10 @@ var DoculaConsole = class {
|
|
|
720
748
|
arguments_.typescript = true;
|
|
721
749
|
break;
|
|
722
750
|
}
|
|
751
|
+
case "--javascript": {
|
|
752
|
+
arguments_.javascript = true;
|
|
753
|
+
break;
|
|
754
|
+
}
|
|
723
755
|
}
|
|
724
756
|
}
|
|
725
757
|
return arguments_;
|
|
@@ -887,7 +919,7 @@ var DoculaOptions = class {
|
|
|
887
919
|
/**
|
|
888
920
|
* Path to the output directory
|
|
889
921
|
*/
|
|
890
|
-
output =
|
|
922
|
+
output = "";
|
|
891
923
|
/**
|
|
892
924
|
* Path to the site directory
|
|
893
925
|
*/
|
|
@@ -928,10 +960,9 @@ var DoculaOptions = class {
|
|
|
928
960
|
*/
|
|
929
961
|
enableReleaseChangelog = true;
|
|
930
962
|
/**
|
|
931
|
-
*
|
|
932
|
-
* and the home.hbs template is not rendered.
|
|
963
|
+
* Number of changelog entries to display per page on the changelog index.
|
|
933
964
|
*/
|
|
934
|
-
|
|
965
|
+
changelogPerPage = 20;
|
|
935
966
|
/**
|
|
936
967
|
* When true, generates llms.txt and llms-full.txt files for the built site.
|
|
937
968
|
*/
|
|
@@ -1005,6 +1036,9 @@ var DoculaOptions = class {
|
|
|
1005
1036
|
if (options) {
|
|
1006
1037
|
this.parseOptions(options);
|
|
1007
1038
|
}
|
|
1039
|
+
if (!this.output) {
|
|
1040
|
+
this.output = path3.join(this.sitePath, "dist");
|
|
1041
|
+
}
|
|
1008
1042
|
}
|
|
1009
1043
|
// biome-ignore lint/suspicious/noExplicitAny: need to fix
|
|
1010
1044
|
parseOptions(options) {
|
|
@@ -1047,8 +1081,8 @@ var DoculaOptions = class {
|
|
|
1047
1081
|
if (options.enableReleaseChangelog !== void 0 && typeof options.enableReleaseChangelog === "boolean") {
|
|
1048
1082
|
this.enableReleaseChangelog = options.enableReleaseChangelog;
|
|
1049
1083
|
}
|
|
1050
|
-
if (options.
|
|
1051
|
-
this.
|
|
1084
|
+
if (options.changelogPerPage !== void 0 && typeof options.changelogPerPage === "number" && options.changelogPerPage > 0) {
|
|
1085
|
+
this.changelogPerPage = options.changelogPerPage;
|
|
1052
1086
|
}
|
|
1053
1087
|
if (options.enableLlmsTxt !== void 0 && typeof options.enableLlmsTxt === "boolean") {
|
|
1054
1088
|
this.enableLlmsTxt = options.enableLlmsTxt;
|
|
@@ -1076,6 +1110,9 @@ var DoculaOptions = class {
|
|
|
1076
1110
|
this.headerLinks = validLinks;
|
|
1077
1111
|
}
|
|
1078
1112
|
}
|
|
1113
|
+
if (!options.output && !this.output) {
|
|
1114
|
+
this.output = path3.join(this.sitePath, "dist");
|
|
1115
|
+
}
|
|
1079
1116
|
}
|
|
1080
1117
|
};
|
|
1081
1118
|
|
|
@@ -1113,6 +1150,8 @@ var DoculaBuilder = class {
|
|
|
1113
1150
|
_options = new DoculaOptions();
|
|
1114
1151
|
_ecto;
|
|
1115
1152
|
_console = new DoculaConsole();
|
|
1153
|
+
_hash = new Hashery();
|
|
1154
|
+
onReleaseChangelog;
|
|
1116
1155
|
// biome-ignore lint/suspicious/noExplicitAny: need to fix
|
|
1117
1156
|
constructor(options, engineOptions) {
|
|
1118
1157
|
if (options) {
|
|
@@ -1131,6 +1170,29 @@ var DoculaBuilder = class {
|
|
|
1131
1170
|
this.options.sitePath,
|
|
1132
1171
|
this.options.template
|
|
1133
1172
|
);
|
|
1173
|
+
const previousManifest = this.loadBuildManifest(this.options.sitePath);
|
|
1174
|
+
const currentConfigHash = this.hashOptions();
|
|
1175
|
+
const currentTemplateHash = this.hashTemplateDirectory(resolvedTemplatePath);
|
|
1176
|
+
const validManifest = previousManifest?.configHash === currentConfigHash ? previousManifest : void 0;
|
|
1177
|
+
const currentDocHashes = this.hashSourceFiles(
|
|
1178
|
+
`${this.options.sitePath}/docs`
|
|
1179
|
+
);
|
|
1180
|
+
const currentChangelogHashes = this.hashSourceFiles(
|
|
1181
|
+
`${this.options.sitePath}/changelog`
|
|
1182
|
+
);
|
|
1183
|
+
const currentAssetHashes = {};
|
|
1184
|
+
if (validManifest && fs3.existsSync(this.options.output) && validManifest.templateHash === currentTemplateHash && this.recordsEqual(validManifest.docs, currentDocHashes) && this.recordsEqual(validManifest.changelog, currentChangelogHashes)) {
|
|
1185
|
+
const assetsChanged = this.hasAssetsChanged(
|
|
1186
|
+
this.options.sitePath,
|
|
1187
|
+
validManifest.assets
|
|
1188
|
+
);
|
|
1189
|
+
if (!assetsChanged) {
|
|
1190
|
+
this._console.success("No changes detected, skipping build");
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
const cachedDocs = validManifest ? this.loadCachedDocuments(this.options.sitePath) : /* @__PURE__ */ new Map();
|
|
1195
|
+
const cachedChangelog = validManifest ? this.loadCachedChangelog(this.options.sitePath) : /* @__PURE__ */ new Map();
|
|
1134
1196
|
const doculaData = {
|
|
1135
1197
|
siteUrl: this.options.siteUrl,
|
|
1136
1198
|
siteTitle: this.options.siteTitle,
|
|
@@ -1141,12 +1203,16 @@ var DoculaBuilder = class {
|
|
|
1141
1203
|
githubPath: this.options.githubPath,
|
|
1142
1204
|
sections: this.options.sections,
|
|
1143
1205
|
openApiUrl: this.options.openApiUrl,
|
|
1144
|
-
|
|
1206
|
+
hasReadme: fs3.existsSync(`${this.options.sitePath}/README.md`),
|
|
1145
1207
|
themeMode: this.options.themeMode,
|
|
1146
1208
|
cookieAuth: this.options.cookieAuth,
|
|
1147
1209
|
headerLinks: this.options.headerLinks,
|
|
1148
1210
|
enableLlmsTxt: this.options.enableLlmsTxt
|
|
1149
1211
|
};
|
|
1212
|
+
const readmePath = `${this.options.sitePath}/README.md`;
|
|
1213
|
+
if (doculaData.hasReadme) {
|
|
1214
|
+
currentAssetHashes["README.md"] = this.hashFile(readmePath);
|
|
1215
|
+
}
|
|
1150
1216
|
if (!doculaData.openApiUrl && fs3.existsSync(`${doculaData.sitePath}/api/swagger.json`)) {
|
|
1151
1217
|
doculaData.openApiUrl = "/api/swagger.json";
|
|
1152
1218
|
}
|
|
@@ -1155,7 +1221,10 @@ var DoculaBuilder = class {
|
|
|
1155
1221
|
}
|
|
1156
1222
|
doculaData.documents = this.getDocuments(
|
|
1157
1223
|
`${doculaData.sitePath}/docs`,
|
|
1158
|
-
doculaData
|
|
1224
|
+
doculaData,
|
|
1225
|
+
cachedDocs,
|
|
1226
|
+
validManifest?.docs ?? {},
|
|
1227
|
+
currentDocHashes
|
|
1159
1228
|
);
|
|
1160
1229
|
doculaData.sections = this.getSections(
|
|
1161
1230
|
`${doculaData.sitePath}/docs`,
|
|
@@ -1164,14 +1233,31 @@ var DoculaBuilder = class {
|
|
|
1164
1233
|
doculaData.hasDocuments = doculaData.documents?.length > 0;
|
|
1165
1234
|
doculaData.hasFeed = doculaData.hasDocuments;
|
|
1166
1235
|
const changelogPath = `${doculaData.sitePath}/changelog`;
|
|
1167
|
-
const fileChangelogEntries = this.getChangelogEntries(
|
|
1236
|
+
const fileChangelogEntries = this.getChangelogEntries(
|
|
1237
|
+
changelogPath,
|
|
1238
|
+
cachedChangelog,
|
|
1239
|
+
validManifest?.changelog ?? {},
|
|
1240
|
+
currentChangelogHashes
|
|
1241
|
+
);
|
|
1168
1242
|
const hasChangelogTemplate = await this.getTemplateFile(resolvedTemplatePath, "changelog") !== void 0;
|
|
1169
1243
|
let allChangelogEntries = [...fileChangelogEntries];
|
|
1170
1244
|
if (this._options.enableReleaseChangelog && hasChangelogTemplate && doculaData.github?.releases && Array.isArray(doculaData.github.releases) && doculaData.github.releases.length > 0) {
|
|
1171
|
-
|
|
1245
|
+
let releaseEntries = this.getReleasesAsChangelogEntries(
|
|
1172
1246
|
// biome-ignore lint/suspicious/noExplicitAny: GitHub release objects
|
|
1173
1247
|
doculaData.github.releases
|
|
1174
1248
|
);
|
|
1249
|
+
if (this.onReleaseChangelog) {
|
|
1250
|
+
try {
|
|
1251
|
+
releaseEntries = await this.onReleaseChangelog(
|
|
1252
|
+
releaseEntries,
|
|
1253
|
+
this._console
|
|
1254
|
+
);
|
|
1255
|
+
} catch (error) {
|
|
1256
|
+
this._console.error(
|
|
1257
|
+
`onReleaseChangelog error: ${error.message}`
|
|
1258
|
+
);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1175
1261
|
allChangelogEntries = [...allChangelogEntries, ...releaseEntries];
|
|
1176
1262
|
}
|
|
1177
1263
|
allChangelogEntries.sort((a, b) => {
|
|
@@ -1198,17 +1284,21 @@ var DoculaBuilder = class {
|
|
|
1198
1284
|
doculaData.hasApi = Boolean(
|
|
1199
1285
|
doculaData.openApiUrl && doculaData.templates?.api
|
|
1200
1286
|
);
|
|
1287
|
+
doculaData.lastModified = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1201
1288
|
this._console.step("Building pages...");
|
|
1202
|
-
if (
|
|
1289
|
+
if (doculaData.hasReadme) {
|
|
1290
|
+
await this.buildIndexPage(doculaData);
|
|
1291
|
+
this._console.fileBuilt("index.html");
|
|
1292
|
+
} else if (doculaData.hasDocuments) {
|
|
1203
1293
|
await this.buildDocsHomePage(doculaData);
|
|
1204
1294
|
this._console.fileBuilt("index.html");
|
|
1205
|
-
} else if (
|
|
1295
|
+
} else if (doculaData.hasApi) {
|
|
1296
|
+
await this.buildApiHomePage(doculaData);
|
|
1297
|
+
this._console.fileBuilt("index.html");
|
|
1298
|
+
} else {
|
|
1206
1299
|
this._console.error(
|
|
1207
|
-
"
|
|
1300
|
+
"No content found for the home page. Add a README.md, docs/ folder, or api/swagger.json to your site directory."
|
|
1208
1301
|
);
|
|
1209
|
-
} else {
|
|
1210
|
-
await this.buildIndexPage(doculaData);
|
|
1211
|
-
this._console.fileBuilt("index.html");
|
|
1212
1302
|
}
|
|
1213
1303
|
await this.buildSiteMapPage(doculaData);
|
|
1214
1304
|
this._console.fileBuilt("sitemap.xml");
|
|
@@ -1240,22 +1330,41 @@ var DoculaBuilder = class {
|
|
|
1240
1330
|
}
|
|
1241
1331
|
}
|
|
1242
1332
|
const siteRelativePath = this.options.sitePath;
|
|
1333
|
+
const previousAssets = validManifest?.assets ?? {};
|
|
1243
1334
|
this._console.step("Copying assets...");
|
|
1244
|
-
if (
|
|
1335
|
+
if (!this.hashAssetAndCheckSkip(
|
|
1336
|
+
`${siteRelativePath}/favicon.ico`,
|
|
1337
|
+
`${this.options.output}/favicon.ico`,
|
|
1338
|
+
"favicon.ico",
|
|
1339
|
+
previousAssets,
|
|
1340
|
+
currentAssetHashes
|
|
1341
|
+
)) {
|
|
1245
1342
|
await fs3.promises.copyFile(
|
|
1246
1343
|
`${siteRelativePath}/favicon.ico`,
|
|
1247
1344
|
`${this.options.output}/favicon.ico`
|
|
1248
1345
|
);
|
|
1249
1346
|
this._console.fileCopied("favicon.ico");
|
|
1250
1347
|
}
|
|
1251
|
-
if (
|
|
1348
|
+
if (!this.hashAssetAndCheckSkip(
|
|
1349
|
+
`${siteRelativePath}/logo.svg`,
|
|
1350
|
+
`${this.options.output}/logo.svg`,
|
|
1351
|
+
"logo.svg",
|
|
1352
|
+
previousAssets,
|
|
1353
|
+
currentAssetHashes
|
|
1354
|
+
)) {
|
|
1252
1355
|
await fs3.promises.copyFile(
|
|
1253
1356
|
`${siteRelativePath}/logo.svg`,
|
|
1254
1357
|
`${this.options.output}/logo.svg`
|
|
1255
1358
|
);
|
|
1256
1359
|
this._console.fileCopied("logo.svg");
|
|
1257
1360
|
}
|
|
1258
|
-
if (
|
|
1361
|
+
if (!this.hashAssetAndCheckSkip(
|
|
1362
|
+
`${siteRelativePath}/logo_horizontal.png`,
|
|
1363
|
+
`${this.options.output}/logo_horizontal.png`,
|
|
1364
|
+
"logo_horizontal.png",
|
|
1365
|
+
previousAssets,
|
|
1366
|
+
currentAssetHashes
|
|
1367
|
+
)) {
|
|
1259
1368
|
await fs3.promises.copyFile(
|
|
1260
1369
|
`${siteRelativePath}/logo_horizontal.png`,
|
|
1261
1370
|
`${this.options.output}/logo_horizontal.png`
|
|
@@ -1263,27 +1372,48 @@ var DoculaBuilder = class {
|
|
|
1263
1372
|
this._console.fileCopied("logo_horizontal.png");
|
|
1264
1373
|
}
|
|
1265
1374
|
if (fs3.existsSync(`${resolvedTemplatePath}/css`)) {
|
|
1266
|
-
this.
|
|
1375
|
+
this.copyDirectoryWithHashing(
|
|
1267
1376
|
`${resolvedTemplatePath}/css`,
|
|
1268
|
-
`${this.options.output}/css
|
|
1377
|
+
`${this.options.output}/css`,
|
|
1378
|
+
"css",
|
|
1379
|
+
previousAssets,
|
|
1380
|
+
currentAssetHashes
|
|
1269
1381
|
);
|
|
1270
1382
|
this._console.fileCopied("css/");
|
|
1271
1383
|
}
|
|
1272
1384
|
if (fs3.existsSync(`${resolvedTemplatePath}/js`)) {
|
|
1273
|
-
this.
|
|
1385
|
+
this.copyDirectoryWithHashing(
|
|
1274
1386
|
`${resolvedTemplatePath}/js`,
|
|
1275
|
-
`${this.options.output}/js
|
|
1387
|
+
`${this.options.output}/js`,
|
|
1388
|
+
"js",
|
|
1389
|
+
previousAssets,
|
|
1390
|
+
currentAssetHashes
|
|
1276
1391
|
);
|
|
1277
1392
|
this._console.fileCopied("js/");
|
|
1278
1393
|
}
|
|
1279
|
-
if (
|
|
1394
|
+
if (!this.hashAssetAndCheckSkip(
|
|
1395
|
+
`${siteRelativePath}/variables.css`,
|
|
1396
|
+
`${this.options.output}/css/variables.css`,
|
|
1397
|
+
"variables.css",
|
|
1398
|
+
previousAssets,
|
|
1399
|
+
currentAssetHashes
|
|
1400
|
+
)) {
|
|
1280
1401
|
await fs3.promises.copyFile(
|
|
1281
1402
|
`${siteRelativePath}/variables.css`,
|
|
1282
1403
|
`${this.options.output}/css/variables.css`
|
|
1283
1404
|
);
|
|
1284
1405
|
this._console.fileCopied("css/variables.css");
|
|
1285
1406
|
}
|
|
1286
|
-
|
|
1407
|
+
const swaggerPath = `${siteRelativePath}/api/swagger.json`;
|
|
1408
|
+
if (fs3.existsSync(swaggerPath)) {
|
|
1409
|
+
currentAssetHashes["api/swagger.json"] = this.hashFile(swaggerPath);
|
|
1410
|
+
}
|
|
1411
|
+
this.copyPublicFolder(
|
|
1412
|
+
siteRelativePath,
|
|
1413
|
+
this.options.output,
|
|
1414
|
+
validManifest?.assets ?? {},
|
|
1415
|
+
currentAssetHashes
|
|
1416
|
+
);
|
|
1287
1417
|
this.copyContentAssets(
|
|
1288
1418
|
`${doculaData.sitePath}/changelog`,
|
|
1289
1419
|
`${this.options.output}/changelog`
|
|
@@ -1295,6 +1425,18 @@ var DoculaBuilder = class {
|
|
|
1295
1425
|
this._console.step("Building LLM files...");
|
|
1296
1426
|
}
|
|
1297
1427
|
await this.buildLlmsFiles(doculaData);
|
|
1428
|
+
this.ensureCacheInGitignore(this.options.sitePath);
|
|
1429
|
+
const newManifest = {
|
|
1430
|
+
version: 1,
|
|
1431
|
+
configHash: currentConfigHash,
|
|
1432
|
+
templateHash: currentTemplateHash,
|
|
1433
|
+
docs: currentDocHashes,
|
|
1434
|
+
changelog: currentChangelogHashes,
|
|
1435
|
+
assets: currentAssetHashes
|
|
1436
|
+
};
|
|
1437
|
+
this.saveBuildManifest(this.options.sitePath, newManifest);
|
|
1438
|
+
this.saveCachedDocuments(this.options.sitePath, doculaData.documents ?? []);
|
|
1439
|
+
this.saveCachedChangelog(this.options.sitePath, fileChangelogEntries);
|
|
1298
1440
|
const endTime = Date.now();
|
|
1299
1441
|
const executionTime = endTime - startTime;
|
|
1300
1442
|
this._console.success(`Build completed in ${executionTime}ms`);
|
|
@@ -1389,6 +1531,16 @@ var DoculaBuilder = class {
|
|
|
1389
1531
|
}
|
|
1390
1532
|
if (data.hasChangelog && data.templates?.changelog) {
|
|
1391
1533
|
urls.push({ url: `${data.siteUrl}/changelog` });
|
|
1534
|
+
const perPage = this.options.changelogPerPage;
|
|
1535
|
+
const totalPages = Math.max(
|
|
1536
|
+
1,
|
|
1537
|
+
Math.ceil((data.changelogEntries ?? []).length / perPage)
|
|
1538
|
+
);
|
|
1539
|
+
for (let page = 2; page <= totalPages; page++) {
|
|
1540
|
+
urls.push({
|
|
1541
|
+
url: `${data.siteUrl}/changelog/page/${page}`
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1392
1544
|
for (const entry of data.changelogEntries ?? []) {
|
|
1393
1545
|
urls.push({
|
|
1394
1546
|
url: `${data.siteUrl}/changelog/${entry.slug}`
|
|
@@ -1756,10 +1908,10 @@ var DoculaBuilder = class {
|
|
|
1756
1908
|
}
|
|
1757
1909
|
async buildDocsHomePage(data) {
|
|
1758
1910
|
if (!data.templates?.docPage) {
|
|
1759
|
-
throw new Error("No docPage template found for
|
|
1911
|
+
throw new Error("No docPage template found for docs home page");
|
|
1760
1912
|
}
|
|
1761
1913
|
if (!data.documents?.length) {
|
|
1762
|
-
throw new Error("No documents found for
|
|
1914
|
+
throw new Error("No documents found for docs home page");
|
|
1763
1915
|
}
|
|
1764
1916
|
const indexPath = `${data.output}/index.html`;
|
|
1765
1917
|
await fs3.promises.mkdir(data.output, { recursive: true });
|
|
@@ -1817,14 +1969,13 @@ var DoculaBuilder = class {
|
|
|
1817
1969
|
throw new Error("No templates found");
|
|
1818
1970
|
}
|
|
1819
1971
|
}
|
|
1820
|
-
async
|
|
1972
|
+
async renderApiContent(data) {
|
|
1821
1973
|
if (!data.openApiUrl || !data.templates?.api) {
|
|
1822
|
-
|
|
1974
|
+
throw new Error("No API template or openApiUrl found");
|
|
1823
1975
|
}
|
|
1824
|
-
const
|
|
1976
|
+
const swaggerSource = `${data.sitePath}/api/swagger.json`;
|
|
1825
1977
|
const apiOutputPath = `${data.output}/api`;
|
|
1826
1978
|
await fs3.promises.mkdir(apiOutputPath, { recursive: true });
|
|
1827
|
-
const swaggerSource = `${data.sitePath}/api/swagger.json`;
|
|
1828
1979
|
if (fs3.existsSync(swaggerSource)) {
|
|
1829
1980
|
await fs3.promises.copyFile(
|
|
1830
1981
|
swaggerSource,
|
|
@@ -1855,14 +2006,27 @@ var DoculaBuilder = class {
|
|
|
1855
2006
|
}
|
|
1856
2007
|
}
|
|
1857
2008
|
const apiTemplate = `${data.templatePath}/${data.templates.api}`;
|
|
1858
|
-
|
|
2009
|
+
return this._ecto.renderFromFile(
|
|
1859
2010
|
apiTemplate,
|
|
1860
2011
|
{ ...data, specUrl: data.openApiUrl, apiSpec },
|
|
1861
2012
|
data.templatePath
|
|
1862
2013
|
);
|
|
2014
|
+
}
|
|
2015
|
+
async buildApiPage(data) {
|
|
2016
|
+
if (!data.openApiUrl || !data.templates?.api) {
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
const apiPath = `${data.output}/api/index.html`;
|
|
2020
|
+
const apiContent = await this.renderApiContent(data);
|
|
1863
2021
|
await fs3.promises.writeFile(apiPath, apiContent, "utf8");
|
|
1864
2022
|
}
|
|
1865
|
-
|
|
2023
|
+
async buildApiHomePage(data) {
|
|
2024
|
+
const indexPath = `${data.output}/index.html`;
|
|
2025
|
+
await fs3.promises.mkdir(data.output, { recursive: true });
|
|
2026
|
+
const apiContent = await this.renderApiContent(data);
|
|
2027
|
+
await fs3.promises.writeFile(indexPath, apiContent, "utf8");
|
|
2028
|
+
}
|
|
2029
|
+
getChangelogEntries(changelogPath, cachedEntries, previousHashes, currentHashes) {
|
|
1866
2030
|
const entries = [];
|
|
1867
2031
|
if (!fs3.existsSync(changelogPath)) {
|
|
1868
2032
|
return entries;
|
|
@@ -1872,6 +2036,16 @@ var DoculaBuilder = class {
|
|
|
1872
2036
|
const filePath = `${changelogPath}/${file}`;
|
|
1873
2037
|
const stats = fs3.statSync(filePath);
|
|
1874
2038
|
if (stats.isFile() && (file.endsWith(".md") || file.endsWith(".mdx"))) {
|
|
2039
|
+
if (cachedEntries && previousHashes && currentHashes) {
|
|
2040
|
+
const slug = path5.basename(file, path5.extname(file));
|
|
2041
|
+
const hash = currentHashes[file] ?? this.hashFile(filePath);
|
|
2042
|
+
const prevHash = previousHashes[file];
|
|
2043
|
+
const cached = cachedEntries.get(slug);
|
|
2044
|
+
if (cached && prevHash === hash) {
|
|
2045
|
+
entries.push(cached);
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
1875
2049
|
const entry = this.parseChangelogEntry(filePath);
|
|
1876
2050
|
entries.push(entry);
|
|
1877
2051
|
}
|
|
@@ -1898,7 +2072,7 @@ var DoculaBuilder = class {
|
|
|
1898
2072
|
const matterData = writr.frontMatter;
|
|
1899
2073
|
const markdownContent = writr.body;
|
|
1900
2074
|
const fileName = path5.basename(filePath, path5.extname(filePath));
|
|
1901
|
-
const slug = fileName
|
|
2075
|
+
const slug = fileName;
|
|
1902
2076
|
const isMdx = filePath.endsWith(".mdx");
|
|
1903
2077
|
const tag = matterData.tag;
|
|
1904
2078
|
const tagClass = tag ? tag.toLowerCase().replace(/\s+/g, "-") : void 0;
|
|
@@ -1917,6 +2091,7 @@ var DoculaBuilder = class {
|
|
|
1917
2091
|
day: "numeric"
|
|
1918
2092
|
});
|
|
1919
2093
|
}
|
|
2094
|
+
const previewImage = matterData.previewImage;
|
|
1920
2095
|
return {
|
|
1921
2096
|
title: matterData.title ?? fileName,
|
|
1922
2097
|
date: dateString,
|
|
@@ -1926,9 +2101,73 @@ var DoculaBuilder = class {
|
|
|
1926
2101
|
slug,
|
|
1927
2102
|
content: markdownContent,
|
|
1928
2103
|
generatedHtml: new Writr(markdownContent).renderSync({ mdx: isMdx }),
|
|
1929
|
-
|
|
2104
|
+
preview: this.generateChangelogPreview(markdownContent, 500, isMdx),
|
|
2105
|
+
previewImage,
|
|
2106
|
+
urlPath: `/changelog/${slug}/index.html`,
|
|
2107
|
+
lastModified: fs3.statSync(filePath).mtime.toISOString().split("T")[0]
|
|
1930
2108
|
};
|
|
1931
2109
|
}
|
|
2110
|
+
generateChangelogPreview(markdown, maxLength = 500, mdx = false) {
|
|
2111
|
+
const minLength = 300;
|
|
2112
|
+
let cleaned = markdown.split("\n").filter((line) => !/^#{1,6}\s/.test(line)).join("\n");
|
|
2113
|
+
cleaned = cleaned.replace(/^\n+/, "");
|
|
2114
|
+
cleaned = cleaned.replace(/!\[[^\]]*\]\([^)]*\)/g, "");
|
|
2115
|
+
cleaned = cleaned.replace(/\[([^\]]*)\]\([^)]*\)/g, "$1");
|
|
2116
|
+
cleaned = cleaned.replace(/^\n+/, "").trim();
|
|
2117
|
+
if (cleaned.length <= minLength) {
|
|
2118
|
+
return new Writr(cleaned).renderSync({ mdx });
|
|
2119
|
+
}
|
|
2120
|
+
const searchArea = cleaned.slice(0, maxLength);
|
|
2121
|
+
let splitIndex = -1;
|
|
2122
|
+
let pos = searchArea.lastIndexOf("\n\n");
|
|
2123
|
+
while (pos >= 0) {
|
|
2124
|
+
if (pos >= minLength) {
|
|
2125
|
+
splitIndex = pos;
|
|
2126
|
+
break;
|
|
2127
|
+
}
|
|
2128
|
+
if (splitIndex === -1) {
|
|
2129
|
+
splitIndex = pos;
|
|
2130
|
+
}
|
|
2131
|
+
pos = searchArea.lastIndexOf("\n\n", pos - 1);
|
|
2132
|
+
}
|
|
2133
|
+
if (splitIndex === -1) {
|
|
2134
|
+
const lastNewline = searchArea.lastIndexOf("\n");
|
|
2135
|
+
if (lastNewline >= minLength) {
|
|
2136
|
+
const nextLine = cleaned.slice(lastNewline + 1);
|
|
2137
|
+
if (/^[-*]\s/.test(nextLine) || /^\d+\.\s/.test(nextLine)) {
|
|
2138
|
+
splitIndex = lastNewline;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
if (splitIndex === -1) {
|
|
2142
|
+
const lines = searchArea.split("\n");
|
|
2143
|
+
let charCount = 0;
|
|
2144
|
+
let lastItemEnd = -1;
|
|
2145
|
+
for (const line of lines) {
|
|
2146
|
+
const lineEnd = charCount + line.length;
|
|
2147
|
+
if (lineEnd <= maxLength && (/^[-*]\s/.test(line) || /^\d+\.\s/.test(line))) {
|
|
2148
|
+
if (charCount > 0 && charCount >= minLength) {
|
|
2149
|
+
lastItemEnd = charCount - 1;
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
charCount = lineEnd + 1;
|
|
2153
|
+
}
|
|
2154
|
+
if (lastItemEnd > 0) {
|
|
2155
|
+
splitIndex = lastItemEnd;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
if (splitIndex > 0) {
|
|
2160
|
+
const truncated2 = cleaned.slice(0, splitIndex).trim();
|
|
2161
|
+
return new Writr(truncated2).renderSync({ mdx });
|
|
2162
|
+
}
|
|
2163
|
+
let truncated = cleaned.slice(0, maxLength);
|
|
2164
|
+
const lastSpace = truncated.lastIndexOf(" ");
|
|
2165
|
+
if (lastSpace > 0) {
|
|
2166
|
+
truncated = truncated.slice(0, lastSpace);
|
|
2167
|
+
}
|
|
2168
|
+
truncated += "...";
|
|
2169
|
+
return new Writr(truncated).renderSync({ mdx });
|
|
2170
|
+
}
|
|
1932
2171
|
convertReleaseToChangelogEntry(release) {
|
|
1933
2172
|
const tagName = release.tag_name ?? "";
|
|
1934
2173
|
const slug = tagName.replace(/\./g, "-");
|
|
@@ -1960,7 +2199,9 @@ var DoculaBuilder = class {
|
|
|
1960
2199
|
slug,
|
|
1961
2200
|
content: body,
|
|
1962
2201
|
generatedHtml: new Writr(body).renderSync(),
|
|
1963
|
-
|
|
2202
|
+
preview: this.generateChangelogPreview(body),
|
|
2203
|
+
urlPath: `/changelog/${slug}/index.html`,
|
|
2204
|
+
lastModified: dateString
|
|
1964
2205
|
};
|
|
1965
2206
|
}
|
|
1966
2207
|
getReleasesAsChangelogEntries(releases) {
|
|
@@ -1977,16 +2218,40 @@ var DoculaBuilder = class {
|
|
|
1977
2218
|
if (!data.hasChangelog || !data.templates?.changelog) {
|
|
1978
2219
|
return;
|
|
1979
2220
|
}
|
|
1980
|
-
const
|
|
1981
|
-
const
|
|
1982
|
-
|
|
2221
|
+
const allEntries = data.changelogEntries ?? [];
|
|
2222
|
+
const perPage = this.options.changelogPerPage;
|
|
2223
|
+
const totalPages = Math.max(1, Math.ceil(allEntries.length / perPage));
|
|
1983
2224
|
const changelogTemplate = `${data.templatePath}/${data.templates.changelog}`;
|
|
1984
|
-
const
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
2225
|
+
const promises = [];
|
|
2226
|
+
for (let page = 1; page <= totalPages; page++) {
|
|
2227
|
+
const startIndex = (page - 1) * perPage;
|
|
2228
|
+
const pageEntries = allEntries.slice(startIndex, startIndex + perPage);
|
|
2229
|
+
const outputPath = page === 1 ? `${data.output}/changelog` : `${data.output}/changelog/page/${page}`;
|
|
2230
|
+
const indexPath = `${outputPath}/index.html`;
|
|
2231
|
+
const paginationData = {
|
|
2232
|
+
...data,
|
|
2233
|
+
entries: pageEntries,
|
|
2234
|
+
currentPage: page,
|
|
2235
|
+
totalPages,
|
|
2236
|
+
hasPagination: totalPages > 1,
|
|
2237
|
+
hasNextPage: page < totalPages,
|
|
2238
|
+
hasPrevPage: page > 1,
|
|
2239
|
+
nextPageUrl: page < totalPages ? `/changelog/page/${page + 1}/` : "",
|
|
2240
|
+
prevPageUrl: page > 1 ? page === 2 ? "/changelog/" : `/changelog/page/${page - 1}/` : ""
|
|
2241
|
+
};
|
|
2242
|
+
promises.push(
|
|
2243
|
+
(async () => {
|
|
2244
|
+
await fs3.promises.mkdir(outputPath, { recursive: true });
|
|
2245
|
+
const content = await this._ecto.renderFromFile(
|
|
2246
|
+
changelogTemplate,
|
|
2247
|
+
paginationData,
|
|
2248
|
+
data.templatePath
|
|
2249
|
+
);
|
|
2250
|
+
await fs3.promises.writeFile(indexPath, content, "utf8");
|
|
2251
|
+
})()
|
|
2252
|
+
);
|
|
2253
|
+
}
|
|
2254
|
+
await Promise.all(promises);
|
|
1990
2255
|
}
|
|
1991
2256
|
async buildChangelogEntryPages(data) {
|
|
1992
2257
|
if (!data.hasChangelog || !data.templates?.changelogEntry || !data.changelogEntries?.length) {
|
|
@@ -2007,7 +2272,12 @@ var DoculaBuilder = class {
|
|
|
2007
2272
|
await Promise.all(promises);
|
|
2008
2273
|
}
|
|
2009
2274
|
generateSidebarItems(data) {
|
|
2010
|
-
let sidebarItems =
|
|
2275
|
+
let sidebarItems = (data.sections ?? []).map(
|
|
2276
|
+
(section) => ({
|
|
2277
|
+
...section,
|
|
2278
|
+
children: section.children ? [...section.children] : void 0
|
|
2279
|
+
})
|
|
2280
|
+
);
|
|
2011
2281
|
for (const document of data.documents ?? []) {
|
|
2012
2282
|
if (document.isRoot) {
|
|
2013
2283
|
sidebarItems.unshift({
|
|
@@ -2056,27 +2326,49 @@ var DoculaBuilder = class {
|
|
|
2056
2326
|
);
|
|
2057
2327
|
return sidebarItems;
|
|
2058
2328
|
}
|
|
2059
|
-
getDocuments(sitePath, doculaData) {
|
|
2329
|
+
getDocuments(sitePath, doculaData, cachedDocs, previousDocHashes, currentDocHashes) {
|
|
2060
2330
|
let documents = [];
|
|
2061
2331
|
if (fs3.existsSync(sitePath)) {
|
|
2062
|
-
documents = this.getDocumentInDirectory(
|
|
2332
|
+
documents = this.getDocumentInDirectory(
|
|
2333
|
+
sitePath,
|
|
2334
|
+
sitePath,
|
|
2335
|
+
cachedDocs,
|
|
2336
|
+
previousDocHashes,
|
|
2337
|
+
currentDocHashes
|
|
2338
|
+
);
|
|
2063
2339
|
doculaData.sections = this.getSections(sitePath, this.options);
|
|
2064
2340
|
for (const section of doculaData.sections) {
|
|
2065
2341
|
const sectionPath = `${sitePath}/${section.path}`;
|
|
2066
|
-
const sectionDocuments = this.getDocumentInDirectory(
|
|
2342
|
+
const sectionDocuments = this.getDocumentInDirectory(
|
|
2343
|
+
sectionPath,
|
|
2344
|
+
sitePath,
|
|
2345
|
+
cachedDocs,
|
|
2346
|
+
previousDocHashes,
|
|
2347
|
+
currentDocHashes
|
|
2348
|
+
);
|
|
2067
2349
|
documents = [...documents, ...sectionDocuments];
|
|
2068
2350
|
}
|
|
2069
2351
|
}
|
|
2070
2352
|
return documents;
|
|
2071
2353
|
}
|
|
2072
|
-
getDocumentInDirectory(sitePath) {
|
|
2354
|
+
getDocumentInDirectory(sitePath, docsRootPath, cachedDocs, previousDocHashes, currentDocHashes) {
|
|
2073
2355
|
const documents = [];
|
|
2074
2356
|
const documentList = fs3.readdirSync(sitePath);
|
|
2075
2357
|
if (documentList.length > 0) {
|
|
2076
2358
|
for (const document of documentList) {
|
|
2077
2359
|
const documentPath = `${sitePath}/${document}`;
|
|
2360
|
+
const relativeKey = path5.relative(docsRootPath, documentPath);
|
|
2078
2361
|
const stats = fs3.statSync(documentPath);
|
|
2079
2362
|
if (stats.isFile() && (document.endsWith(".md") || document.endsWith(".mdx"))) {
|
|
2363
|
+
if (cachedDocs && previousDocHashes && currentDocHashes) {
|
|
2364
|
+
const hash = currentDocHashes[relativeKey] ?? this.hashFile(documentPath);
|
|
2365
|
+
const prevHash = previousDocHashes[relativeKey];
|
|
2366
|
+
const cached = cachedDocs.get(relativeKey);
|
|
2367
|
+
if (cached && prevHash === hash) {
|
|
2368
|
+
documents.push(cached);
|
|
2369
|
+
continue;
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2080
2372
|
const documentData = this.parseDocumentData(documentPath);
|
|
2081
2373
|
documents.push(documentData);
|
|
2082
2374
|
}
|
|
@@ -2166,7 +2458,8 @@ ${markdownContent.slice(firstH2)}`;
|
|
|
2166
2458
|
}),
|
|
2167
2459
|
documentPath,
|
|
2168
2460
|
urlPath,
|
|
2169
|
-
isRoot
|
|
2461
|
+
isRoot,
|
|
2462
|
+
lastModified: fs3.statSync(documentPath).mtime.toISOString().split("T")[0]
|
|
2170
2463
|
};
|
|
2171
2464
|
}
|
|
2172
2465
|
hasTableOfContents(markdown) {
|
|
@@ -2200,9 +2493,45 @@ ${markdownContent.slice(firstH2)}`;
|
|
|
2200
2493
|
return resolvedTemplatePath;
|
|
2201
2494
|
}
|
|
2202
2495
|
const overrideFiles = this.listFilesRecursive(overrideDir);
|
|
2203
|
-
if (fs3.existsSync(cacheDir)
|
|
2204
|
-
this.
|
|
2205
|
-
|
|
2496
|
+
if (fs3.existsSync(cacheDir)) {
|
|
2497
|
+
const diff = this.getChangedOverrides(
|
|
2498
|
+
overrideDir,
|
|
2499
|
+
cacheDir,
|
|
2500
|
+
overrideFiles
|
|
2501
|
+
);
|
|
2502
|
+
if (diff) {
|
|
2503
|
+
const hasChanges = diff.added.length > 0 || diff.changed.length > 0 || diff.removed.length > 0;
|
|
2504
|
+
if (!hasChanges) {
|
|
2505
|
+
this._console.step("Using cached template overrides...");
|
|
2506
|
+
return cacheDir;
|
|
2507
|
+
}
|
|
2508
|
+
this._console.step("Updating template overrides...");
|
|
2509
|
+
for (const file of diff.added) {
|
|
2510
|
+
this._console.info(`Template override added: ${file}`);
|
|
2511
|
+
const targetPath = path5.join(cacheDir, file);
|
|
2512
|
+
fs3.mkdirSync(path5.dirname(targetPath), { recursive: true });
|
|
2513
|
+
fs3.copyFileSync(path5.join(overrideDir, file), targetPath);
|
|
2514
|
+
}
|
|
2515
|
+
for (const file of diff.changed) {
|
|
2516
|
+
this._console.info(`Template override changed: ${file}`);
|
|
2517
|
+
const targetPath = path5.join(cacheDir, file);
|
|
2518
|
+
fs3.mkdirSync(path5.dirname(targetPath), { recursive: true });
|
|
2519
|
+
fs3.copyFileSync(path5.join(overrideDir, file), targetPath);
|
|
2520
|
+
}
|
|
2521
|
+
for (const file of diff.removed) {
|
|
2522
|
+
this._console.info(`Template override removed: ${file}`);
|
|
2523
|
+
const cachedPath = path5.join(cacheDir, file);
|
|
2524
|
+
const originalPath = path5.join(resolvedTemplatePath, file);
|
|
2525
|
+
if (fs3.existsSync(originalPath)) {
|
|
2526
|
+
fs3.copyFileSync(originalPath, cachedPath);
|
|
2527
|
+
} else if (fs3.existsSync(cachedPath)) {
|
|
2528
|
+
fs3.unlinkSync(cachedPath);
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
const manifestPath2 = path5.join(cacheDir, ".manifest.json");
|
|
2532
|
+
fs3.writeFileSync(manifestPath2, JSON.stringify(diff.currentHashes));
|
|
2533
|
+
return cacheDir;
|
|
2534
|
+
}
|
|
2206
2535
|
}
|
|
2207
2536
|
if (overrideFiles.length > 0) {
|
|
2208
2537
|
this._console.step("Applying template overrides...");
|
|
@@ -2217,8 +2546,12 @@ ${markdownContent.slice(firstH2)}`;
|
|
|
2217
2546
|
fs3.mkdirSync(cacheDir, { recursive: true });
|
|
2218
2547
|
this.copyDirectory(resolvedTemplatePath, cacheDir);
|
|
2219
2548
|
this.copyDirectory(overrideDir, cacheDir);
|
|
2549
|
+
const currentHashes = {};
|
|
2550
|
+
for (const file of overrideFiles) {
|
|
2551
|
+
currentHashes[file] = this.hashFile(path5.join(overrideDir, file));
|
|
2552
|
+
}
|
|
2220
2553
|
const manifestPath = path5.join(cacheDir, ".manifest.json");
|
|
2221
|
-
fs3.writeFileSync(manifestPath, JSON.stringify(
|
|
2554
|
+
fs3.writeFileSync(manifestPath, JSON.stringify(currentHashes));
|
|
2222
2555
|
return cacheDir;
|
|
2223
2556
|
}
|
|
2224
2557
|
ensureCacheInGitignore(sitePath) {
|
|
@@ -2245,34 +2578,43 @@ ${entry}
|
|
|
2245
2578
|
this._console.info("Created .gitignore with .cache");
|
|
2246
2579
|
}
|
|
2247
2580
|
}
|
|
2248
|
-
|
|
2581
|
+
getChangedOverrides(overrideDir, cacheDir, overrideFiles) {
|
|
2249
2582
|
const manifestPath = path5.join(cacheDir, ".manifest.json");
|
|
2250
2583
|
if (!fs3.existsSync(manifestPath)) {
|
|
2251
|
-
return
|
|
2584
|
+
return void 0;
|
|
2252
2585
|
}
|
|
2586
|
+
let previousHashes;
|
|
2253
2587
|
try {
|
|
2254
|
-
|
|
2588
|
+
previousHashes = JSON.parse(
|
|
2255
2589
|
fs3.readFileSync(manifestPath, "utf8")
|
|
2256
2590
|
);
|
|
2257
|
-
if (previousFiles.length !== overrideFiles.length || !previousFiles.every((f, i) => f === overrideFiles[i])) {
|
|
2258
|
-
return false;
|
|
2259
|
-
}
|
|
2260
2591
|
} catch {
|
|
2261
|
-
return
|
|
2592
|
+
return void 0;
|
|
2262
2593
|
}
|
|
2594
|
+
const currentHashes = {};
|
|
2263
2595
|
for (const file of overrideFiles) {
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2596
|
+
currentHashes[file] = this.hashFile(path5.join(overrideDir, file));
|
|
2597
|
+
}
|
|
2598
|
+
const added = [];
|
|
2599
|
+
const changed = [];
|
|
2600
|
+
const removed = [];
|
|
2601
|
+
for (const file of overrideFiles) {
|
|
2602
|
+
if (!(file in previousHashes)) {
|
|
2603
|
+
added.push(file);
|
|
2604
|
+
} else if (currentHashes[file] !== previousHashes[file]) {
|
|
2605
|
+
changed.push(file);
|
|
2268
2606
|
}
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
if (
|
|
2272
|
-
|
|
2607
|
+
}
|
|
2608
|
+
for (const file of Object.keys(previousHashes)) {
|
|
2609
|
+
if (!overrideFiles.includes(file)) {
|
|
2610
|
+
removed.push(file);
|
|
2273
2611
|
}
|
|
2274
2612
|
}
|
|
2275
|
-
return
|
|
2613
|
+
return { added, changed, removed, currentHashes };
|
|
2614
|
+
}
|
|
2615
|
+
hashFile(filePath) {
|
|
2616
|
+
const content = fs3.readFileSync(filePath);
|
|
2617
|
+
return this._hash.toHashSync(content);
|
|
2276
2618
|
}
|
|
2277
2619
|
listFilesRecursive(dir, prefix = "") {
|
|
2278
2620
|
const results = [];
|
|
@@ -2316,16 +2658,23 @@ ${entry}
|
|
|
2316
2658
|
}
|
|
2317
2659
|
}
|
|
2318
2660
|
}
|
|
2319
|
-
copyPublicFolder(sitePath, output) {
|
|
2661
|
+
copyPublicFolder(sitePath, output, previousAssets, currentAssets) {
|
|
2320
2662
|
const publicPath = `${sitePath}/public`;
|
|
2321
2663
|
if (!fs3.existsSync(publicPath)) {
|
|
2322
2664
|
return;
|
|
2323
2665
|
}
|
|
2324
2666
|
this._console.step("Copying public folder...");
|
|
2325
2667
|
const resolvedOutput = path5.resolve(output);
|
|
2326
|
-
this.copyPublicDirectory(
|
|
2668
|
+
this.copyPublicDirectory(
|
|
2669
|
+
publicPath,
|
|
2670
|
+
output,
|
|
2671
|
+
publicPath,
|
|
2672
|
+
resolvedOutput,
|
|
2673
|
+
previousAssets,
|
|
2674
|
+
currentAssets
|
|
2675
|
+
);
|
|
2327
2676
|
}
|
|
2328
|
-
copyPublicDirectory(source, target, basePath, output) {
|
|
2677
|
+
copyPublicDirectory(source, target, basePath, output, previousAssets, currentAssets) {
|
|
2329
2678
|
const files = fs3.readdirSync(source);
|
|
2330
2679
|
for (const file of files) {
|
|
2331
2680
|
const sourcePath = `${source}/${file}`;
|
|
@@ -2341,8 +2690,21 @@ ${entry}
|
|
|
2341
2690
|
}
|
|
2342
2691
|
if (stat.isDirectory()) {
|
|
2343
2692
|
fs3.mkdirSync(targetPath, { recursive: true });
|
|
2344
|
-
this.copyPublicDirectory(
|
|
2693
|
+
this.copyPublicDirectory(
|
|
2694
|
+
sourcePath,
|
|
2695
|
+
targetPath,
|
|
2696
|
+
basePath,
|
|
2697
|
+
output,
|
|
2698
|
+
previousAssets,
|
|
2699
|
+
currentAssets
|
|
2700
|
+
);
|
|
2345
2701
|
} else {
|
|
2702
|
+
const assetKey = `public/${relativePath}`;
|
|
2703
|
+
const hash = this.hashFile(sourcePath);
|
|
2704
|
+
currentAssets[assetKey] = hash;
|
|
2705
|
+
if (previousAssets[assetKey] === hash && fs3.existsSync(targetPath)) {
|
|
2706
|
+
continue;
|
|
2707
|
+
}
|
|
2346
2708
|
fs3.mkdirSync(target, { recursive: true });
|
|
2347
2709
|
fs3.copyFileSync(sourcePath, targetPath);
|
|
2348
2710
|
this._console.fileCopied(relativePath);
|
|
@@ -2397,6 +2759,210 @@ ${entry}
|
|
|
2397
2759
|
}
|
|
2398
2760
|
return results;
|
|
2399
2761
|
}
|
|
2762
|
+
loadBuildManifest(sitePath) {
|
|
2763
|
+
const manifestPath = path5.join(
|
|
2764
|
+
sitePath,
|
|
2765
|
+
".cache",
|
|
2766
|
+
"build",
|
|
2767
|
+
"manifest.json"
|
|
2768
|
+
);
|
|
2769
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
2770
|
+
return void 0;
|
|
2771
|
+
}
|
|
2772
|
+
try {
|
|
2773
|
+
const data = JSON.parse(
|
|
2774
|
+
fs3.readFileSync(manifestPath, "utf8")
|
|
2775
|
+
);
|
|
2776
|
+
if (data.version !== 1) {
|
|
2777
|
+
return void 0;
|
|
2778
|
+
}
|
|
2779
|
+
return data;
|
|
2780
|
+
} catch {
|
|
2781
|
+
return void 0;
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
saveBuildManifest(sitePath, manifest) {
|
|
2785
|
+
const dir = path5.join(sitePath, ".cache", "build");
|
|
2786
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
2787
|
+
fs3.writeFileSync(path5.join(dir, "manifest.json"), JSON.stringify(manifest));
|
|
2788
|
+
}
|
|
2789
|
+
hashOptions() {
|
|
2790
|
+
const relevant = {
|
|
2791
|
+
siteUrl: this.options.siteUrl,
|
|
2792
|
+
siteTitle: this.options.siteTitle,
|
|
2793
|
+
siteDescription: this.options.siteDescription,
|
|
2794
|
+
githubPath: this.options.githubPath,
|
|
2795
|
+
template: this.options.template,
|
|
2796
|
+
templatePath: this.options.templatePath,
|
|
2797
|
+
enableLlmsTxt: this.options.enableLlmsTxt,
|
|
2798
|
+
changelogPerPage: this.options.changelogPerPage,
|
|
2799
|
+
enableReleaseChangelog: this.options.enableReleaseChangelog,
|
|
2800
|
+
sections: this.options.sections,
|
|
2801
|
+
openApiUrl: this.options.openApiUrl,
|
|
2802
|
+
themeMode: this.options.themeMode,
|
|
2803
|
+
cookieAuth: this.options.cookieAuth,
|
|
2804
|
+
headerLinks: this.options.headerLinks
|
|
2805
|
+
};
|
|
2806
|
+
return this._hash.toHashSync(JSON.stringify(relevant));
|
|
2807
|
+
}
|
|
2808
|
+
hashTemplateDirectory(templatePath) {
|
|
2809
|
+
if (!fs3.existsSync(templatePath)) {
|
|
2810
|
+
return "";
|
|
2811
|
+
}
|
|
2812
|
+
const files = this.listFilesRecursive(templatePath);
|
|
2813
|
+
const hashes = files.map((f) => this.hashFile(path5.join(templatePath, f)));
|
|
2814
|
+
return this._hash.toHashSync(hashes.join(""));
|
|
2815
|
+
}
|
|
2816
|
+
loadCachedDocuments(sitePath) {
|
|
2817
|
+
const cachePath = path5.join(sitePath, ".cache", "build", "documents.json");
|
|
2818
|
+
if (!fs3.existsSync(cachePath)) {
|
|
2819
|
+
return /* @__PURE__ */ new Map();
|
|
2820
|
+
}
|
|
2821
|
+
try {
|
|
2822
|
+
const data = JSON.parse(fs3.readFileSync(cachePath, "utf8"));
|
|
2823
|
+
return new Map(Object.entries(data));
|
|
2824
|
+
} catch {
|
|
2825
|
+
return /* @__PURE__ */ new Map();
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
saveCachedDocuments(sitePath, documents) {
|
|
2829
|
+
const dir = path5.join(sitePath, ".cache", "build");
|
|
2830
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
2831
|
+
const docsRoot = path5.join(sitePath, "docs");
|
|
2832
|
+
const map = {};
|
|
2833
|
+
for (const doc of documents) {
|
|
2834
|
+
const relativeKey = path5.relative(docsRoot, doc.documentPath);
|
|
2835
|
+
map[relativeKey] = doc;
|
|
2836
|
+
}
|
|
2837
|
+
fs3.writeFileSync(path5.join(dir, "documents.json"), JSON.stringify(map));
|
|
2838
|
+
}
|
|
2839
|
+
loadCachedChangelog(sitePath) {
|
|
2840
|
+
const cachePath = path5.join(sitePath, ".cache", "build", "changelog.json");
|
|
2841
|
+
if (!fs3.existsSync(cachePath)) {
|
|
2842
|
+
return /* @__PURE__ */ new Map();
|
|
2843
|
+
}
|
|
2844
|
+
try {
|
|
2845
|
+
const data = JSON.parse(fs3.readFileSync(cachePath, "utf8"));
|
|
2846
|
+
return new Map(Object.entries(data));
|
|
2847
|
+
} catch {
|
|
2848
|
+
return /* @__PURE__ */ new Map();
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
saveCachedChangelog(sitePath, entries) {
|
|
2852
|
+
const dir = path5.join(sitePath, ".cache", "build");
|
|
2853
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
2854
|
+
const map = {};
|
|
2855
|
+
for (const entry of entries) {
|
|
2856
|
+
map[entry.slug] = entry;
|
|
2857
|
+
}
|
|
2858
|
+
fs3.writeFileSync(path5.join(dir, "changelog.json"), JSON.stringify(map));
|
|
2859
|
+
}
|
|
2860
|
+
hashSourceFiles(dir) {
|
|
2861
|
+
const hashes = {};
|
|
2862
|
+
if (!fs3.existsSync(dir)) {
|
|
2863
|
+
return hashes;
|
|
2864
|
+
}
|
|
2865
|
+
const files = this.listFilesRecursive(dir);
|
|
2866
|
+
for (const file of files) {
|
|
2867
|
+
const fullPath = path5.join(dir, file);
|
|
2868
|
+
hashes[file] = this.hashFile(fullPath);
|
|
2869
|
+
}
|
|
2870
|
+
return hashes;
|
|
2871
|
+
}
|
|
2872
|
+
recordsEqual(a, b) {
|
|
2873
|
+
const keysA = Object.keys(a);
|
|
2874
|
+
const keysB = Object.keys(b);
|
|
2875
|
+
if (keysA.length !== keysB.length) {
|
|
2876
|
+
return false;
|
|
2877
|
+
}
|
|
2878
|
+
for (const key of keysA) {
|
|
2879
|
+
if (a[key] !== b[key]) {
|
|
2880
|
+
return false;
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
return true;
|
|
2884
|
+
}
|
|
2885
|
+
hasAssetsChanged(sitePath, previousAssets) {
|
|
2886
|
+
const assetFiles = [
|
|
2887
|
+
"favicon.ico",
|
|
2888
|
+
"logo.svg",
|
|
2889
|
+
"logo_horizontal.png",
|
|
2890
|
+
"variables.css",
|
|
2891
|
+
"api/swagger.json",
|
|
2892
|
+
"README.md"
|
|
2893
|
+
];
|
|
2894
|
+
for (const file of assetFiles) {
|
|
2895
|
+
const filePath = path5.join(sitePath, file);
|
|
2896
|
+
if (fs3.existsSync(filePath)) {
|
|
2897
|
+
const hash = this.hashFile(filePath);
|
|
2898
|
+
if (previousAssets[file] !== hash) {
|
|
2899
|
+
return true;
|
|
2900
|
+
}
|
|
2901
|
+
} else if (previousAssets[file]) {
|
|
2902
|
+
return true;
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
const publicPath = path5.join(sitePath, "public");
|
|
2906
|
+
if (fs3.existsSync(publicPath)) {
|
|
2907
|
+
const publicHashes = this.hashSourceFiles(publicPath);
|
|
2908
|
+
for (const [file, hash] of Object.entries(publicHashes)) {
|
|
2909
|
+
if (previousAssets[`public/${file}`] !== hash) {
|
|
2910
|
+
return true;
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
return false;
|
|
2915
|
+
}
|
|
2916
|
+
/**
|
|
2917
|
+
* Hashes the source file, records it in currentAssets, and returns
|
|
2918
|
+
* whether the copy can be skipped (unchanged from previous build).
|
|
2919
|
+
*/
|
|
2920
|
+
hashAssetAndCheckSkip(sourcePath, targetPath, assetKey, previousAssets, currentAssets) {
|
|
2921
|
+
if (!fs3.existsSync(sourcePath)) {
|
|
2922
|
+
return true;
|
|
2923
|
+
}
|
|
2924
|
+
const hash = this.hashFile(sourcePath);
|
|
2925
|
+
currentAssets[assetKey] = hash;
|
|
2926
|
+
if (previousAssets[assetKey] === hash && fs3.existsSync(targetPath)) {
|
|
2927
|
+
return true;
|
|
2928
|
+
}
|
|
2929
|
+
return false;
|
|
2930
|
+
}
|
|
2931
|
+
copyDirectoryWithHashing(source, target, prefix, previousAssets, currentAssets) {
|
|
2932
|
+
if (!fs3.existsSync(source)) {
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
const files = fs3.readdirSync(source);
|
|
2936
|
+
for (const file of files) {
|
|
2937
|
+
if (file.startsWith(".")) {
|
|
2938
|
+
continue;
|
|
2939
|
+
}
|
|
2940
|
+
const sourcePath = `${source}/${file}`;
|
|
2941
|
+
const targetPath = `${target}/${file}`;
|
|
2942
|
+
const assetKey = prefix ? `${prefix}/${file}` : file;
|
|
2943
|
+
const stat = fs3.lstatSync(sourcePath);
|
|
2944
|
+
if (stat.isSymbolicLink()) {
|
|
2945
|
+
continue;
|
|
2946
|
+
}
|
|
2947
|
+
if (stat.isDirectory()) {
|
|
2948
|
+
this.copyDirectoryWithHashing(
|
|
2949
|
+
sourcePath,
|
|
2950
|
+
targetPath,
|
|
2951
|
+
assetKey,
|
|
2952
|
+
previousAssets,
|
|
2953
|
+
currentAssets
|
|
2954
|
+
);
|
|
2955
|
+
} else {
|
|
2956
|
+
const hash = this.hashFile(sourcePath);
|
|
2957
|
+
currentAssets[assetKey] = hash;
|
|
2958
|
+
if (previousAssets[assetKey] === hash && fs3.existsSync(targetPath)) {
|
|
2959
|
+
continue;
|
|
2960
|
+
}
|
|
2961
|
+
fs3.mkdirSync(target, { recursive: true });
|
|
2962
|
+
fs3.copyFileSync(sourcePath, targetPath);
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2400
2966
|
copyContentAssets(sourcePath, targetPath) {
|
|
2401
2967
|
if (!fs3.existsSync(sourcePath)) {
|
|
2402
2968
|
return;
|
|
@@ -2426,8 +2992,8 @@ ${entry}
|
|
|
2426
2992
|
};
|
|
2427
2993
|
|
|
2428
2994
|
// src/init.ts
|
|
2429
|
-
var doculaconfigmjs = "
|
|
2430
|
-
var doculaconfigts = "aW1wb3J0IHR5cGUgeyBEb2N1bGFPcHRpb25zIH0gZnJvbSAnZG9jdWxhJzsKCmV4cG9ydCBjb25zdCBvcHRpb25zOiBQYXJ0aWFsPERvY3VsYU9wdGlvbnM+
|
|
2995
|
+
var doculaconfigmjs = "ZXhwb3J0IGNvbnN0IG9wdGlvbnMgPSB7CglvdXRwdXQ6ICcuL2Rpc3QnLAoJc2l0ZVBhdGg6ICcuL3NpdGUnLAoJZ2l0aHViUGF0aDogJ2phcmVkd3JheS9kb2N1bGEnLAoJc2l0ZVRpdGxlOiAnRG9jdWxhJywKCXNpdGVEZXNjcmlwdGlvbjogJ0JlYXV0aWZ1bCBXZWJzaXRlIGZvciBZb3VyIFByb2plY3RzJywKCXNpdGVVcmw6ICdodHRwczovL2RvY3VsYS5vcmcnLAoJLy8gb3BlbkFwaVVybDogJy9hcGkvc3dhZ2dlci5qc29uJywKCS8vIGVuYWJsZVJlbGVhc2VDaGFuZ2Vsb2c6IHRydWUsCgkvLyBlbmFibGVMbG1zVHh0OiB0cnVlLAoJLy8gdGhlbWVNb2RlOiAnbGlnaHQnLAp9Owo=";
|
|
2996
|
+
var doculaconfigts = "aW1wb3J0IHR5cGUgeyBEb2N1bGFPcHRpb25zIH0gZnJvbSAnZG9jdWxhJzsKCmV4cG9ydCBjb25zdCBvcHRpb25zOiBQYXJ0aWFsPERvY3VsYU9wdGlvbnM+ID0gewoJb3V0cHV0OiAnLi9kaXN0JywKCXNpdGVQYXRoOiAnLi9zaXRlJywKCWdpdGh1YlBhdGg6ICdqYXJlZHdyYXkvZG9jdWxhJywKCXNpdGVUaXRsZTogJ0RvY3VsYScsCglzaXRlRGVzY3JpcHRpb246ICdCZWF1dGlmdWwgV2Vic2l0ZSBmb3IgWW91ciBQcm9qZWN0cycsCglzaXRlVXJsOiAnaHR0cHM6Ly9kb2N1bGEub3JnJywKCS8vIG9wZW5BcGlVcmw6ICcvYXBpL3N3YWdnZXIuanNvbicsCgkvLyBlbmFibGVSZWxlYXNlQ2hhbmdlbG9nOiB0cnVlLAoJLy8gZW5hYmxlTGxtc1R4dDogdHJ1ZSwKCS8vIHRoZW1lTW9kZTogJ2xpZ2h0JywKfTsK";
|
|
2431
2997
|
var faviconico = "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";
|
|
2432
2998
|
var logopng = "iVBORw0KGgoAAAANSUhEUgAAAxEAAAHXCAYAAADDSdfmAAAACXBIWXMAACxLAAAsSwGlPZapAAAFw2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgOS4xLWMwMDMgNzkuOTY5MGE4N2ZjLCAyMDI1LzAzLzA2LTIwOjUwOjE2ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjYuNiAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjUtMDUtMThUMTM6MzM6NTgtMDc6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI1LTA1LTE4VDEzOjM2OjE5LTA3OjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI1LTA1LTE4VDEzOjM2OjE5LTA3OjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5YTc4ZDY2Ny02NjAzLTQwNmUtYTViZC02MjYzMTNjY2VmY2QiIHhtcE1NOkRvY3VtZW50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";
|
|
2433
2999
|
|
|
@@ -2534,7 +3100,7 @@ var Docula = class {
|
|
|
2534
3100
|
}
|
|
2535
3101
|
if (this._configFileModule.onPrepare) {
|
|
2536
3102
|
try {
|
|
2537
|
-
await this._configFileModule.onPrepare(this.options);
|
|
3103
|
+
await this._configFileModule.onPrepare(this.options, this._console);
|
|
2538
3104
|
} catch (error) {
|
|
2539
3105
|
this._console.error(error.message);
|
|
2540
3106
|
}
|
|
@@ -2542,18 +3108,37 @@ var Docula = class {
|
|
|
2542
3108
|
if (consoleProcess.args.template) {
|
|
2543
3109
|
this.options.template = consoleProcess.args.template;
|
|
2544
3110
|
}
|
|
3111
|
+
if (consoleProcess.args.templatePath) {
|
|
3112
|
+
this.options.templatePath = consoleProcess.args.templatePath;
|
|
3113
|
+
}
|
|
2545
3114
|
if (consoleProcess.args.output) {
|
|
2546
3115
|
this.options.output = consoleProcess.args.output;
|
|
3116
|
+
} else {
|
|
3117
|
+
const configOptions = this._configFileModule.options;
|
|
3118
|
+
if (!configOptions?.output) {
|
|
3119
|
+
this.options.output = path6.join(this.options.sitePath, "dist");
|
|
3120
|
+
}
|
|
2547
3121
|
}
|
|
2548
3122
|
if (consoleProcess.args.port !== void 0 && !Number.isNaN(consoleProcess.args.port)) {
|
|
2549
3123
|
this.options.port = consoleProcess.args.port;
|
|
2550
3124
|
}
|
|
2551
3125
|
switch (consoleProcess.command) {
|
|
2552
3126
|
case "init": {
|
|
2553
|
-
|
|
2554
|
-
this.
|
|
2555
|
-
|
|
2556
|
-
|
|
3127
|
+
if (consoleProcess.args.typescript && consoleProcess.args.javascript) {
|
|
3128
|
+
this._console.error(
|
|
3129
|
+
"Cannot use both --typescript and --javascript flags. Please choose one."
|
|
3130
|
+
);
|
|
3131
|
+
break;
|
|
3132
|
+
}
|
|
3133
|
+
let useTypeScript;
|
|
3134
|
+
if (consoleProcess.args.typescript) {
|
|
3135
|
+
useTypeScript = true;
|
|
3136
|
+
} else if (consoleProcess.args.javascript) {
|
|
3137
|
+
useTypeScript = false;
|
|
3138
|
+
} else {
|
|
3139
|
+
useTypeScript = this.detectTypeScript();
|
|
3140
|
+
}
|
|
3141
|
+
this.generateInit(this.options.sitePath, useTypeScript);
|
|
2557
3142
|
break;
|
|
2558
3143
|
}
|
|
2559
3144
|
case "help": {
|
|
@@ -2564,16 +3149,23 @@ var Docula = class {
|
|
|
2564
3149
|
this._console.log(this.getVersion());
|
|
2565
3150
|
break;
|
|
2566
3151
|
}
|
|
3152
|
+
case "dev": {
|
|
3153
|
+
const devBuilder = await this.runBuild(consoleProcess.args.clean);
|
|
3154
|
+
this.watch(this.options, devBuilder);
|
|
3155
|
+
await this.serve(this.options);
|
|
3156
|
+
break;
|
|
3157
|
+
}
|
|
3158
|
+
case "start": {
|
|
3159
|
+
const startBuilder = await this.runBuild(consoleProcess.args.clean);
|
|
3160
|
+
if (consoleProcess.args.watch) {
|
|
3161
|
+
this.watch(this.options, startBuilder);
|
|
3162
|
+
}
|
|
3163
|
+
await this.serve(this.options);
|
|
3164
|
+
break;
|
|
3165
|
+
}
|
|
2567
3166
|
case "serve": {
|
|
2568
3167
|
if (consoleProcess.args.build || consoleProcess.args.watch) {
|
|
2569
|
-
|
|
2570
|
-
fs4.rmSync(this.options.output, { recursive: true, force: true });
|
|
2571
|
-
}
|
|
2572
|
-
if (consoleProcess.args.clean) {
|
|
2573
|
-
this.cleanCache(this.options.sitePath);
|
|
2574
|
-
}
|
|
2575
|
-
const builder = new DoculaBuilder(this.options);
|
|
2576
|
-
await builder.build();
|
|
3168
|
+
const builder = await this.runBuild(consoleProcess.args.clean);
|
|
2577
3169
|
if (consoleProcess.args.watch) {
|
|
2578
3170
|
this.watch(this.options, builder);
|
|
2579
3171
|
}
|
|
@@ -2582,18 +3174,32 @@ var Docula = class {
|
|
|
2582
3174
|
break;
|
|
2583
3175
|
}
|
|
2584
3176
|
default: {
|
|
2585
|
-
|
|
2586
|
-
fs4.rmSync(this.options.output, { recursive: true, force: true });
|
|
2587
|
-
}
|
|
2588
|
-
if (consoleProcess.args.clean) {
|
|
2589
|
-
this.cleanCache(this.options.sitePath);
|
|
2590
|
-
}
|
|
2591
|
-
const builder = new DoculaBuilder(this.options);
|
|
2592
|
-
await builder.build();
|
|
3177
|
+
await this.runBuild(consoleProcess.args.clean);
|
|
2593
3178
|
break;
|
|
2594
3179
|
}
|
|
2595
3180
|
}
|
|
2596
3181
|
}
|
|
3182
|
+
async runBuild(clean) {
|
|
3183
|
+
if (clean && fs4.existsSync(this.options.output)) {
|
|
3184
|
+
fs4.rmSync(this.options.output, { recursive: true, force: true });
|
|
3185
|
+
}
|
|
3186
|
+
if (clean) {
|
|
3187
|
+
this.cleanCache(this.options.sitePath);
|
|
3188
|
+
}
|
|
3189
|
+
const builder = new DoculaBuilder(this.options);
|
|
3190
|
+
if (this._configFileModule.onReleaseChangelog) {
|
|
3191
|
+
builder.onReleaseChangelog = this._configFileModule.onReleaseChangelog;
|
|
3192
|
+
}
|
|
3193
|
+
await builder.build();
|
|
3194
|
+
return builder;
|
|
3195
|
+
}
|
|
3196
|
+
/**
|
|
3197
|
+
* Detect if the current project uses TypeScript by checking for tsconfig.json
|
|
3198
|
+
* @returns {boolean}
|
|
3199
|
+
*/
|
|
3200
|
+
detectTypeScript() {
|
|
3201
|
+
return fs4.existsSync(path6.join(process4.cwd(), "tsconfig.json"));
|
|
3202
|
+
}
|
|
2597
3203
|
/**
|
|
2598
3204
|
* Generate the init files
|
|
2599
3205
|
* @param {string} sitePath
|
|
@@ -2672,7 +3278,10 @@ var Docula = class {
|
|
|
2672
3278
|
this._console.info(`File changed: ${filename}, rebuilding...`);
|
|
2673
3279
|
try {
|
|
2674
3280
|
await builder.build();
|
|
2675
|
-
this._console.success(
|
|
3281
|
+
this._console.success(`Rebuild complete`);
|
|
3282
|
+
this._console.banner(
|
|
3283
|
+
`\u{1F987} at http://localhost:${options.port}`
|
|
3284
|
+
);
|
|
2676
3285
|
} catch (error) {
|
|
2677
3286
|
this._console.error(`Rebuild failed: ${error.message}`);
|
|
2678
3287
|
} finally {
|
|
@@ -2690,6 +3299,9 @@ var Docula = class {
|
|
|
2690
3299
|
if (filename && outputRelative && !outputRelative.startsWith("..") && (String(filename) === outputRelative || String(filename).startsWith(`${outputRelative}${path6.sep}`))) {
|
|
2691
3300
|
return;
|
|
2692
3301
|
}
|
|
3302
|
+
if (filename && (String(filename) === ".cache" || String(filename).startsWith(`.cache${path6.sep}`))) {
|
|
3303
|
+
return;
|
|
3304
|
+
}
|
|
2693
3305
|
if (isBuilding) {
|
|
2694
3306
|
pendingRebuild = true;
|
|
2695
3307
|
return;
|
|
@@ -2746,6 +3358,7 @@ var Docula = class {
|
|
|
2746
3358
|
}
|
|
2747
3359
|
};
|
|
2748
3360
|
export {
|
|
3361
|
+
DoculaConsole,
|
|
2749
3362
|
DoculaOptions,
|
|
2750
3363
|
Writr2 as Writr,
|
|
2751
3364
|
Docula as default
|
|
@@ -2757,4 +3370,5 @@ export {
|
|
|
2757
3370
|
/* v8 ignore next 9 -- @preserve */
|
|
2758
3371
|
/* v8 ignore next 4 -- @preserve */
|
|
2759
3372
|
/* v8 ignore start -- @preserve */
|
|
3373
|
+
/* v8 ignore next 8 -- @preserve */
|
|
2760
3374
|
/* v8 ignore stop -- @preserve */
|