docula 0.90.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docula.d.ts +34 -1
- package/dist/docula.js +271 -184
- package/package.json +2 -2
- package/templates/classic/css/base.css +29 -0
- package/templates/modern/css/home.css +37 -0
- package/templates/modern/css/styles.css +45 -0
- package/templates/modern/home.hbs +11 -0
- package/templates/modern/includes/header-bar.hbs +20 -0
- package/templates/modern/includes/scripts.hbs +55 -0
package/dist/docula.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/docula.ts
|
|
2
|
-
import
|
|
2
|
+
import fs4 from "fs";
|
|
3
3
|
import http from "http";
|
|
4
|
-
import
|
|
4
|
+
import path6 from "path";
|
|
5
5
|
import process4 from "process";
|
|
6
6
|
import { pathToFileURL } from "url";
|
|
7
7
|
import { createJiti } from "jiti";
|
|
@@ -9,8 +9,8 @@ import handler from "serve-handler";
|
|
|
9
9
|
import updateNotifier from "update-notifier";
|
|
10
10
|
|
|
11
11
|
// src/builder.ts
|
|
12
|
-
import
|
|
13
|
-
import
|
|
12
|
+
import fs3 from "fs";
|
|
13
|
+
import path5 from "path";
|
|
14
14
|
import { Ecto } from "ecto";
|
|
15
15
|
import { Writr } from "writr";
|
|
16
16
|
|
|
@@ -691,6 +691,8 @@ var DoculaConsole = class {
|
|
|
691
691
|
};
|
|
692
692
|
|
|
693
693
|
// src/github.ts
|
|
694
|
+
import fs from "fs";
|
|
695
|
+
import path2 from "path";
|
|
694
696
|
import process2 from "process";
|
|
695
697
|
import { CacheableNet } from "@cacheable/net";
|
|
696
698
|
var Github = class {
|
|
@@ -700,18 +702,32 @@ var Github = class {
|
|
|
700
702
|
repo: ""
|
|
701
703
|
};
|
|
702
704
|
net;
|
|
703
|
-
|
|
705
|
+
cacheConfig;
|
|
706
|
+
constructor(options, cacheConfig) {
|
|
704
707
|
this.parseOptions(options);
|
|
705
708
|
this.net = new CacheableNet();
|
|
709
|
+
if (cacheConfig) {
|
|
710
|
+
this.cacheConfig = cacheConfig;
|
|
711
|
+
}
|
|
706
712
|
}
|
|
707
713
|
async getData() {
|
|
714
|
+
if (this.cacheConfig && this.cacheConfig.ttl > 0) {
|
|
715
|
+
const cached = this.loadCache();
|
|
716
|
+
if (cached) {
|
|
717
|
+
return cached;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
708
720
|
const data = {
|
|
709
721
|
releases: {},
|
|
710
722
|
contributors: {}
|
|
711
723
|
};
|
|
712
724
|
data.releases = await this.getReleases();
|
|
713
725
|
data.contributors = await this.getContributors();
|
|
714
|
-
|
|
726
|
+
const result = data;
|
|
727
|
+
if (this.cacheConfig && this.cacheConfig.ttl > 0) {
|
|
728
|
+
this.saveCache(result);
|
|
729
|
+
}
|
|
730
|
+
return result;
|
|
715
731
|
}
|
|
716
732
|
// biome-ignore lint/suspicious/noExplicitAny: need to fix
|
|
717
733
|
async getReleases() {
|
|
@@ -775,6 +791,41 @@ var Github = class {
|
|
|
775
791
|
this.options.author = options.author;
|
|
776
792
|
this.options.repo = options.repo;
|
|
777
793
|
}
|
|
794
|
+
getCacheFilePath() {
|
|
795
|
+
if (!this.cacheConfig) {
|
|
796
|
+
throw new Error("Cache config is not set");
|
|
797
|
+
}
|
|
798
|
+
const cacheDir = path2.join(this.cacheConfig.cachePath, "github");
|
|
799
|
+
return path2.join(cacheDir, "github-data.json");
|
|
800
|
+
}
|
|
801
|
+
loadCache() {
|
|
802
|
+
try {
|
|
803
|
+
const cacheFile = this.getCacheFilePath();
|
|
804
|
+
if (!fs.existsSync(cacheFile)) {
|
|
805
|
+
return void 0;
|
|
806
|
+
}
|
|
807
|
+
const stat = fs.statSync(cacheFile);
|
|
808
|
+
const ageInSeconds = (Date.now() - stat.mtimeMs) / 1e3;
|
|
809
|
+
if (ageInSeconds > (this.cacheConfig?.ttl ?? 0)) {
|
|
810
|
+
return void 0;
|
|
811
|
+
}
|
|
812
|
+
const raw = fs.readFileSync(cacheFile, "utf8");
|
|
813
|
+
return JSON.parse(raw);
|
|
814
|
+
} catch {
|
|
815
|
+
return void 0;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
saveCache(data) {
|
|
819
|
+
try {
|
|
820
|
+
const cacheFile = this.getCacheFilePath();
|
|
821
|
+
const cacheDir = path2.dirname(cacheFile);
|
|
822
|
+
if (!fs.existsSync(cacheDir)) {
|
|
823
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
824
|
+
}
|
|
825
|
+
fs.writeFileSync(cacheFile, JSON.stringify(data, null, 2));
|
|
826
|
+
} catch {
|
|
827
|
+
}
|
|
828
|
+
}
|
|
778
829
|
// biome-ignore lint/suspicious/noExplicitAny: need to fix
|
|
779
830
|
addAnchorLink(data) {
|
|
780
831
|
return data.map((release) => {
|
|
@@ -786,7 +837,7 @@ var Github = class {
|
|
|
786
837
|
};
|
|
787
838
|
|
|
788
839
|
// src/options.ts
|
|
789
|
-
import
|
|
840
|
+
import path3 from "path";
|
|
790
841
|
import process3 from "process";
|
|
791
842
|
var DoculaOptions = class {
|
|
792
843
|
/**
|
|
@@ -800,11 +851,11 @@ var DoculaOptions = class {
|
|
|
800
851
|
/**
|
|
801
852
|
* Path to the output directory
|
|
802
853
|
*/
|
|
803
|
-
output =
|
|
854
|
+
output = path3.join(process3.cwd(), "./dist");
|
|
804
855
|
/**
|
|
805
856
|
* Path to the site directory
|
|
806
857
|
*/
|
|
807
|
-
sitePath =
|
|
858
|
+
sitePath = path3.join(process3.cwd(), "./site");
|
|
808
859
|
/**
|
|
809
860
|
* Path to the github repository
|
|
810
861
|
*/
|
|
@@ -860,6 +911,28 @@ var DoculaOptions = class {
|
|
|
860
911
|
* site directory's .gitignore file if not already present.
|
|
861
912
|
*/
|
|
862
913
|
autoUpdateIgnores = true;
|
|
914
|
+
/**
|
|
915
|
+
* File extensions to copy as assets from docs/ and changelog/ directories.
|
|
916
|
+
* Override in docula.config to customize.
|
|
917
|
+
*/
|
|
918
|
+
/**
|
|
919
|
+
* Cookie-based authentication. When set, shows a Login/Logout button
|
|
920
|
+
* in the header based on whether a JWT cookie is present.
|
|
921
|
+
*/
|
|
922
|
+
cookieAuth;
|
|
923
|
+
/**
|
|
924
|
+
* File extensions to copy as assets from docs/ and changelog/ directories.
|
|
925
|
+
* Override in docula.config to customize.
|
|
926
|
+
*/
|
|
927
|
+
/**
|
|
928
|
+
* Cache settings. Controls caching of external data (e.g., GitHub API responses)
|
|
929
|
+
* in the .cache directory within the site path.
|
|
930
|
+
*/
|
|
931
|
+
cache = {
|
|
932
|
+
github: {
|
|
933
|
+
ttl: 3600
|
|
934
|
+
}
|
|
935
|
+
};
|
|
863
936
|
/**
|
|
864
937
|
* File extensions to copy as assets from docs/ and changelog/ directories.
|
|
865
938
|
* Override in docula.config to customize.
|
|
@@ -899,15 +972,15 @@ var DoculaOptions = class {
|
|
|
899
972
|
}
|
|
900
973
|
if (options.templatePath) {
|
|
901
974
|
this.templatePath = options.templatePath;
|
|
902
|
-
this.templatePath =
|
|
975
|
+
this.templatePath = path3.join(process3.cwd(), this.templatePath);
|
|
903
976
|
}
|
|
904
977
|
if (options.output) {
|
|
905
978
|
this.output = options.output;
|
|
906
|
-
this.output =
|
|
979
|
+
this.output = path3.join(process3.cwd(), this.output);
|
|
907
980
|
}
|
|
908
981
|
if (options.sitePath) {
|
|
909
982
|
this.sitePath = options.sitePath;
|
|
910
|
-
this.sitePath =
|
|
983
|
+
this.sitePath = path3.join(process3.cwd(), this.sitePath);
|
|
911
984
|
}
|
|
912
985
|
if (options.githubPath) {
|
|
913
986
|
this.githubPath = options.githubPath;
|
|
@@ -945,33 +1018,39 @@ var DoculaOptions = class {
|
|
|
945
1018
|
if (options.autoUpdateIgnores !== void 0 && typeof options.autoUpdateIgnores === "boolean") {
|
|
946
1019
|
this.autoUpdateIgnores = options.autoUpdateIgnores;
|
|
947
1020
|
}
|
|
1021
|
+
if (options.cache && typeof options.cache === "object" && options.cache.github !== null && typeof options.cache.github === "object" && typeof options.cache.github.ttl === "number") {
|
|
1022
|
+
this.cache = options.cache;
|
|
1023
|
+
}
|
|
948
1024
|
if (options.allowedAssets && Array.isArray(options.allowedAssets)) {
|
|
949
1025
|
this.allowedAssets = options.allowedAssets;
|
|
950
1026
|
}
|
|
1027
|
+
if (options.cookieAuth && typeof options.cookieAuth === "object" && typeof options.cookieAuth.loginUrl === "string") {
|
|
1028
|
+
this.cookieAuth = options.cookieAuth;
|
|
1029
|
+
}
|
|
951
1030
|
}
|
|
952
1031
|
};
|
|
953
1032
|
|
|
954
1033
|
// src/template-resolver.ts
|
|
955
|
-
import
|
|
956
|
-
import
|
|
1034
|
+
import fs2 from "fs";
|
|
1035
|
+
import path4 from "path";
|
|
957
1036
|
function getBuiltInTemplatesDir() {
|
|
958
|
-
return
|
|
1037
|
+
return path4.join(import.meta.url, "../../templates").replace("file:", "");
|
|
959
1038
|
}
|
|
960
1039
|
function listBuiltInTemplates() {
|
|
961
1040
|
const templatesDir = getBuiltInTemplatesDir();
|
|
962
|
-
if (!
|
|
1041
|
+
if (!fs2.existsSync(templatesDir)) {
|
|
963
1042
|
return [];
|
|
964
1043
|
}
|
|
965
|
-
return
|
|
966
|
-
(entry) =>
|
|
1044
|
+
return fs2.readdirSync(templatesDir).filter(
|
|
1045
|
+
(entry) => fs2.statSync(path4.join(templatesDir, entry)).isDirectory()
|
|
967
1046
|
);
|
|
968
1047
|
}
|
|
969
1048
|
function resolveTemplatePath(templatePath, templateName) {
|
|
970
1049
|
if (templatePath) {
|
|
971
1050
|
return templatePath;
|
|
972
1051
|
}
|
|
973
|
-
const resolvedPath =
|
|
974
|
-
if (!
|
|
1052
|
+
const resolvedPath = path4.join(getBuiltInTemplatesDir(), templateName);
|
|
1053
|
+
if (!fs2.existsSync(resolvedPath)) {
|
|
975
1054
|
const available = listBuiltInTemplates();
|
|
976
1055
|
throw new Error(
|
|
977
1056
|
`Built-in template "${templateName}" not found. Available templates: ${available.join(", ")}`
|
|
@@ -1014,9 +1093,10 @@ var DoculaBuilder = class {
|
|
|
1014
1093
|
sections: this.options.sections,
|
|
1015
1094
|
openApiUrl: this.options.openApiUrl,
|
|
1016
1095
|
homePage: this.options.homePage,
|
|
1017
|
-
themeMode: this.options.themeMode
|
|
1096
|
+
themeMode: this.options.themeMode,
|
|
1097
|
+
cookieAuth: this.options.cookieAuth
|
|
1018
1098
|
};
|
|
1019
|
-
if (!doculaData.openApiUrl &&
|
|
1099
|
+
if (!doculaData.openApiUrl && fs3.existsSync(`${doculaData.sitePath}/api/swagger.json`)) {
|
|
1020
1100
|
doculaData.openApiUrl = "/api/swagger.json";
|
|
1021
1101
|
}
|
|
1022
1102
|
if (this.options.githubPath) {
|
|
@@ -1105,43 +1185,43 @@ var DoculaBuilder = class {
|
|
|
1105
1185
|
}
|
|
1106
1186
|
const siteRelativePath = this.options.sitePath;
|
|
1107
1187
|
this._console.step("Copying assets...");
|
|
1108
|
-
if (
|
|
1109
|
-
await
|
|
1188
|
+
if (fs3.existsSync(`${siteRelativePath}/favicon.ico`)) {
|
|
1189
|
+
await fs3.promises.copyFile(
|
|
1110
1190
|
`${siteRelativePath}/favicon.ico`,
|
|
1111
1191
|
`${this.options.output}/favicon.ico`
|
|
1112
1192
|
);
|
|
1113
1193
|
this._console.fileCopied("favicon.ico");
|
|
1114
1194
|
}
|
|
1115
|
-
if (
|
|
1116
|
-
await
|
|
1195
|
+
if (fs3.existsSync(`${siteRelativePath}/logo.svg`)) {
|
|
1196
|
+
await fs3.promises.copyFile(
|
|
1117
1197
|
`${siteRelativePath}/logo.svg`,
|
|
1118
1198
|
`${this.options.output}/logo.svg`
|
|
1119
1199
|
);
|
|
1120
1200
|
this._console.fileCopied("logo.svg");
|
|
1121
1201
|
}
|
|
1122
|
-
if (
|
|
1123
|
-
await
|
|
1202
|
+
if (fs3.existsSync(`${siteRelativePath}/logo_horizontal.png`)) {
|
|
1203
|
+
await fs3.promises.copyFile(
|
|
1124
1204
|
`${siteRelativePath}/logo_horizontal.png`,
|
|
1125
1205
|
`${this.options.output}/logo_horizontal.png`
|
|
1126
1206
|
);
|
|
1127
1207
|
this._console.fileCopied("logo_horizontal.png");
|
|
1128
1208
|
}
|
|
1129
|
-
if (
|
|
1209
|
+
if (fs3.existsSync(`${resolvedTemplatePath}/css`)) {
|
|
1130
1210
|
this.copyDirectory(
|
|
1131
1211
|
`${resolvedTemplatePath}/css`,
|
|
1132
1212
|
`${this.options.output}/css`
|
|
1133
1213
|
);
|
|
1134
1214
|
this._console.fileCopied("css/");
|
|
1135
1215
|
}
|
|
1136
|
-
if (
|
|
1216
|
+
if (fs3.existsSync(`${resolvedTemplatePath}/js`)) {
|
|
1137
1217
|
this.copyDirectory(
|
|
1138
1218
|
`${resolvedTemplatePath}/js`,
|
|
1139
1219
|
`${this.options.output}/js`
|
|
1140
1220
|
);
|
|
1141
1221
|
this._console.fileCopied("js/");
|
|
1142
1222
|
}
|
|
1143
|
-
if (
|
|
1144
|
-
await
|
|
1223
|
+
if (fs3.existsSync(`${siteRelativePath}/variables.css`)) {
|
|
1224
|
+
await fs3.promises.copyFile(
|
|
1145
1225
|
`${siteRelativePath}/variables.css`,
|
|
1146
1226
|
`${this.options.output}/css/variables.css`
|
|
1147
1227
|
);
|
|
@@ -1183,14 +1263,21 @@ var DoculaBuilder = class {
|
|
|
1183
1263
|
author: paths[0],
|
|
1184
1264
|
repo: paths[1]
|
|
1185
1265
|
};
|
|
1186
|
-
|
|
1266
|
+
let cacheConfig;
|
|
1267
|
+
if (this._options.cache.github.ttl > 0) {
|
|
1268
|
+
cacheConfig = {
|
|
1269
|
+
cachePath: path5.join(this._options.sitePath, ".cache"),
|
|
1270
|
+
ttl: this._options.cache.github.ttl
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
const github = new Github(options, cacheConfig);
|
|
1187
1274
|
return github.getData();
|
|
1188
1275
|
}
|
|
1189
1276
|
async getTemplates(templatePath, hasDocuments, hasChangelog = false) {
|
|
1190
1277
|
const templates = {
|
|
1191
1278
|
home: ""
|
|
1192
1279
|
};
|
|
1193
|
-
if (
|
|
1280
|
+
if (fs3.existsSync(templatePath)) {
|
|
1194
1281
|
const home = await this.getTemplateFile(templatePath, "home");
|
|
1195
1282
|
if (home) {
|
|
1196
1283
|
templates.home = home;
|
|
@@ -1216,9 +1303,9 @@ var DoculaBuilder = class {
|
|
|
1216
1303
|
}
|
|
1217
1304
|
return templates;
|
|
1218
1305
|
}
|
|
1219
|
-
async getTemplateFile(
|
|
1306
|
+
async getTemplateFile(path7, name) {
|
|
1220
1307
|
let result;
|
|
1221
|
-
const files = await
|
|
1308
|
+
const files = await fs3.promises.readdir(path7);
|
|
1222
1309
|
for (const file of files) {
|
|
1223
1310
|
const fileName = file.split(".");
|
|
1224
1311
|
if (fileName[0].toString().toLowerCase() === name.toLowerCase()) {
|
|
@@ -1232,8 +1319,8 @@ var DoculaBuilder = class {
|
|
|
1232
1319
|
const { sitePath } = options;
|
|
1233
1320
|
const { output } = options;
|
|
1234
1321
|
const robotsPath = `${output}/robots.txt`;
|
|
1235
|
-
await
|
|
1236
|
-
await (
|
|
1322
|
+
await fs3.promises.mkdir(output, { recursive: true });
|
|
1323
|
+
await (fs3.existsSync(`${sitePath}/robots.txt`) ? fs3.promises.copyFile(`${sitePath}/robots.txt`, robotsPath) : fs3.promises.writeFile(robotsPath, "User-agent: *\nDisallow:"));
|
|
1237
1324
|
}
|
|
1238
1325
|
async buildSiteMapPage(data) {
|
|
1239
1326
|
const sitemapPath = `${data.output}/sitemap.xml`;
|
|
@@ -1264,14 +1351,14 @@ var DoculaBuilder = class {
|
|
|
1264
1351
|
xml += "</url>";
|
|
1265
1352
|
}
|
|
1266
1353
|
xml += "</urlset>";
|
|
1267
|
-
await
|
|
1268
|
-
await
|
|
1354
|
+
await fs3.promises.mkdir(data.output, { recursive: true });
|
|
1355
|
+
await fs3.promises.writeFile(sitemapPath, xml, "utf8");
|
|
1269
1356
|
}
|
|
1270
1357
|
async buildLlmsFiles(data) {
|
|
1271
1358
|
if (!this.options.enableLlmsTxt) {
|
|
1272
1359
|
return;
|
|
1273
1360
|
}
|
|
1274
|
-
await
|
|
1361
|
+
await fs3.promises.mkdir(data.output, { recursive: true });
|
|
1275
1362
|
const llmsOutputPath = `${data.output}/llms.txt`;
|
|
1276
1363
|
const llmsFullOutputPath = `${data.output}/llms-full.txt`;
|
|
1277
1364
|
const llmsOverrideContent = await this.getSafeSiteOverrideFileContent(
|
|
@@ -1283,21 +1370,21 @@ var DoculaBuilder = class {
|
|
|
1283
1370
|
"llms-full.txt"
|
|
1284
1371
|
);
|
|
1285
1372
|
if (llmsOverrideContent !== void 0) {
|
|
1286
|
-
await
|
|
1373
|
+
await fs3.promises.writeFile(llmsOutputPath, llmsOverrideContent, "utf8");
|
|
1287
1374
|
} else {
|
|
1288
1375
|
const llmsContent = this.generateLlmsIndexContent(data);
|
|
1289
|
-
await
|
|
1376
|
+
await fs3.promises.writeFile(llmsOutputPath, llmsContent, "utf8");
|
|
1290
1377
|
}
|
|
1291
1378
|
this._console.fileBuilt("llms.txt");
|
|
1292
1379
|
if (llmsFullOverrideContent !== void 0) {
|
|
1293
|
-
await
|
|
1380
|
+
await fs3.promises.writeFile(
|
|
1294
1381
|
llmsFullOutputPath,
|
|
1295
1382
|
llmsFullOverrideContent,
|
|
1296
1383
|
"utf8"
|
|
1297
1384
|
);
|
|
1298
1385
|
} else {
|
|
1299
1386
|
const llmsFullContent = await this.generateLlmsFullContent(data);
|
|
1300
|
-
await
|
|
1387
|
+
await fs3.promises.writeFile(llmsFullOutputPath, llmsFullContent, "utf8");
|
|
1301
1388
|
}
|
|
1302
1389
|
this._console.fileBuilt("llms-full.txt");
|
|
1303
1390
|
}
|
|
@@ -1466,17 +1553,17 @@ var DoculaBuilder = class {
|
|
|
1466
1553
|
return void 0;
|
|
1467
1554
|
}
|
|
1468
1555
|
const normalizedPath = openApiPathWithoutQuery.startsWith("/") ? openApiPathWithoutQuery.slice(1) : openApiPathWithoutQuery;
|
|
1469
|
-
return
|
|
1556
|
+
return path5.join(data.sitePath, normalizedPath);
|
|
1470
1557
|
}
|
|
1471
1558
|
async getSafeSiteOverrideFileContent(sitePath, fileName) {
|
|
1472
|
-
const resolvedSitePath =
|
|
1473
|
-
const candidatePath =
|
|
1559
|
+
const resolvedSitePath = path5.resolve(sitePath);
|
|
1560
|
+
const candidatePath = path5.resolve(sitePath, fileName);
|
|
1474
1561
|
if (!this.isPathWithinBasePath(candidatePath, resolvedSitePath)) {
|
|
1475
1562
|
return void 0;
|
|
1476
1563
|
}
|
|
1477
1564
|
let candidateStats;
|
|
1478
1565
|
try {
|
|
1479
|
-
candidateStats = await
|
|
1566
|
+
candidateStats = await fs3.promises.lstat(candidatePath);
|
|
1480
1567
|
} catch {
|
|
1481
1568
|
return void 0;
|
|
1482
1569
|
}
|
|
@@ -1486,29 +1573,29 @@ var DoculaBuilder = class {
|
|
|
1486
1573
|
let realSitePath;
|
|
1487
1574
|
let realCandidatePath;
|
|
1488
1575
|
try {
|
|
1489
|
-
realSitePath = await
|
|
1490
|
-
realCandidatePath = await
|
|
1576
|
+
realSitePath = await fs3.promises.realpath(resolvedSitePath);
|
|
1577
|
+
realCandidatePath = await fs3.promises.realpath(candidatePath);
|
|
1491
1578
|
} catch {
|
|
1492
1579
|
return void 0;
|
|
1493
1580
|
}
|
|
1494
1581
|
if (!this.isPathWithinBasePath(realCandidatePath, realSitePath)) {
|
|
1495
1582
|
return void 0;
|
|
1496
1583
|
}
|
|
1497
|
-
return
|
|
1584
|
+
return fs3.promises.readFile(realCandidatePath, "utf8");
|
|
1498
1585
|
}
|
|
1499
1586
|
async getSafeLocalOpenApiSpec(data) {
|
|
1500
1587
|
const localOpenApiPath = this.resolveLocalOpenApiPath(data);
|
|
1501
1588
|
if (!localOpenApiPath) {
|
|
1502
1589
|
return void 0;
|
|
1503
1590
|
}
|
|
1504
|
-
const resolvedSitePath =
|
|
1505
|
-
const resolvedLocalOpenApiPath =
|
|
1591
|
+
const resolvedSitePath = path5.resolve(data.sitePath);
|
|
1592
|
+
const resolvedLocalOpenApiPath = path5.resolve(localOpenApiPath);
|
|
1506
1593
|
if (!this.isPathWithinBasePath(resolvedLocalOpenApiPath, resolvedSitePath)) {
|
|
1507
1594
|
return void 0;
|
|
1508
1595
|
}
|
|
1509
1596
|
let localOpenApiStats;
|
|
1510
1597
|
try {
|
|
1511
|
-
localOpenApiStats = await
|
|
1598
|
+
localOpenApiStats = await fs3.promises.lstat(resolvedLocalOpenApiPath);
|
|
1512
1599
|
} catch {
|
|
1513
1600
|
return void 0;
|
|
1514
1601
|
}
|
|
@@ -1518,8 +1605,8 @@ var DoculaBuilder = class {
|
|
|
1518
1605
|
let realSitePath;
|
|
1519
1606
|
let realLocalOpenApiPath;
|
|
1520
1607
|
try {
|
|
1521
|
-
realSitePath = await
|
|
1522
|
-
realLocalOpenApiPath = await
|
|
1608
|
+
realSitePath = await fs3.promises.realpath(resolvedSitePath);
|
|
1609
|
+
realLocalOpenApiPath = await fs3.promises.realpath(
|
|
1523
1610
|
resolvedLocalOpenApiPath
|
|
1524
1611
|
);
|
|
1525
1612
|
} catch {
|
|
@@ -1528,26 +1615,26 @@ var DoculaBuilder = class {
|
|
|
1528
1615
|
if (!this.isPathWithinBasePath(realLocalOpenApiPath, realSitePath)) {
|
|
1529
1616
|
return void 0;
|
|
1530
1617
|
}
|
|
1531
|
-
const localOpenApiContent = (await
|
|
1618
|
+
const localOpenApiContent = (await fs3.promises.readFile(realLocalOpenApiPath, "utf8")).trim();
|
|
1532
1619
|
return {
|
|
1533
1620
|
sourcePath: realLocalOpenApiPath,
|
|
1534
1621
|
content: localOpenApiContent
|
|
1535
1622
|
};
|
|
1536
1623
|
}
|
|
1537
1624
|
isPathWithinBasePath(candidatePath, basePath) {
|
|
1538
|
-
const relativePath =
|
|
1539
|
-
|
|
1540
|
-
|
|
1625
|
+
const relativePath = path5.relative(
|
|
1626
|
+
path5.resolve(basePath),
|
|
1627
|
+
path5.resolve(candidatePath)
|
|
1541
1628
|
);
|
|
1542
|
-
return relativePath === "" || !relativePath.startsWith("..") && !
|
|
1629
|
+
return relativePath === "" || !relativePath.startsWith("..") && !path5.isAbsolute(relativePath);
|
|
1543
1630
|
}
|
|
1544
1631
|
toPosixPath(filePath) {
|
|
1545
|
-
return filePath.replaceAll(
|
|
1632
|
+
return filePath.replaceAll(path5.sep, path5.posix.sep);
|
|
1546
1633
|
}
|
|
1547
1634
|
async buildIndexPage(data) {
|
|
1548
1635
|
if (data.templates) {
|
|
1549
1636
|
const indexPath = `${data.output}/index.html`;
|
|
1550
|
-
await
|
|
1637
|
+
await fs3.promises.mkdir(data.output, { recursive: true });
|
|
1551
1638
|
const indexTemplate = `${data.templatePath}/${data.templates.home}`;
|
|
1552
1639
|
let content;
|
|
1553
1640
|
if (!data.hasDocuments) {
|
|
@@ -1559,7 +1646,7 @@ var DoculaBuilder = class {
|
|
|
1559
1646
|
{ ...data, content, announcement },
|
|
1560
1647
|
data.templatePath
|
|
1561
1648
|
);
|
|
1562
|
-
await
|
|
1649
|
+
await fs3.promises.writeFile(indexPath, indexContent, "utf8");
|
|
1563
1650
|
} else {
|
|
1564
1651
|
throw new Error("No templates found");
|
|
1565
1652
|
}
|
|
@@ -1572,7 +1659,7 @@ var DoculaBuilder = class {
|
|
|
1572
1659
|
throw new Error("No documents found for homePage");
|
|
1573
1660
|
}
|
|
1574
1661
|
const indexPath = `${data.output}/index.html`;
|
|
1575
|
-
await
|
|
1662
|
+
await fs3.promises.mkdir(data.output, { recursive: true });
|
|
1576
1663
|
const documentsTemplate = `${data.templatePath}/${data.templates.docPage}`;
|
|
1577
1664
|
const firstDocument = data.documents[0];
|
|
1578
1665
|
if (!data.sidebarItems) {
|
|
@@ -1583,12 +1670,12 @@ var DoculaBuilder = class {
|
|
|
1583
1670
|
{ ...data, ...firstDocument },
|
|
1584
1671
|
data.templatePath
|
|
1585
1672
|
);
|
|
1586
|
-
await
|
|
1673
|
+
await fs3.promises.writeFile(indexPath, documentContent, "utf8");
|
|
1587
1674
|
}
|
|
1588
1675
|
async buildReadmeSection(data) {
|
|
1589
1676
|
let htmlReadme = "";
|
|
1590
|
-
if (
|
|
1591
|
-
const readmeContent =
|
|
1677
|
+
if (fs3.existsSync(`${data.sitePath}/README.md`)) {
|
|
1678
|
+
const readmeContent = fs3.readFileSync(
|
|
1592
1679
|
`${data.sitePath}/README.md`,
|
|
1593
1680
|
"utf8"
|
|
1594
1681
|
);
|
|
@@ -1598,8 +1685,8 @@ var DoculaBuilder = class {
|
|
|
1598
1685
|
}
|
|
1599
1686
|
async buildAnnouncementSection(data) {
|
|
1600
1687
|
const announcementPath = `${data.sitePath}/announcement.md`;
|
|
1601
|
-
if (
|
|
1602
|
-
const announcementContent =
|
|
1688
|
+
if (fs3.existsSync(announcementPath)) {
|
|
1689
|
+
const announcementContent = fs3.readFileSync(announcementPath, "utf8");
|
|
1603
1690
|
return new Writr(announcementContent).render();
|
|
1604
1691
|
}
|
|
1605
1692
|
return void 0;
|
|
@@ -1607,11 +1694,11 @@ var DoculaBuilder = class {
|
|
|
1607
1694
|
async buildDocsPages(data) {
|
|
1608
1695
|
if (data.templates && data.documents?.length) {
|
|
1609
1696
|
const documentsTemplate = `${data.templatePath}/${data.templates.docPage}`;
|
|
1610
|
-
await
|
|
1697
|
+
await fs3.promises.mkdir(`${data.output}/docs`, { recursive: true });
|
|
1611
1698
|
data.sidebarItems = this.generateSidebarItems(data);
|
|
1612
1699
|
const promises = data.documents.map(async (document) => {
|
|
1613
1700
|
const folder = document.urlPath.split("/").slice(0, -1).join("/");
|
|
1614
|
-
await
|
|
1701
|
+
await fs3.promises.mkdir(`${data.output}/${folder}`, {
|
|
1615
1702
|
recursive: true
|
|
1616
1703
|
});
|
|
1617
1704
|
const slug = `${data.output}${document.urlPath}`;
|
|
@@ -1620,7 +1707,7 @@ var DoculaBuilder = class {
|
|
|
1620
1707
|
{ ...data, ...document },
|
|
1621
1708
|
data.templatePath
|
|
1622
1709
|
);
|
|
1623
|
-
return
|
|
1710
|
+
return fs3.promises.writeFile(slug, documentContent, "utf8");
|
|
1624
1711
|
});
|
|
1625
1712
|
await Promise.all(promises);
|
|
1626
1713
|
} else {
|
|
@@ -1633,10 +1720,10 @@ var DoculaBuilder = class {
|
|
|
1633
1720
|
}
|
|
1634
1721
|
const apiPath = `${data.output}/api/index.html`;
|
|
1635
1722
|
const apiOutputPath = `${data.output}/api`;
|
|
1636
|
-
await
|
|
1723
|
+
await fs3.promises.mkdir(apiOutputPath, { recursive: true });
|
|
1637
1724
|
const swaggerSource = `${data.sitePath}/api/swagger.json`;
|
|
1638
|
-
if (
|
|
1639
|
-
await
|
|
1725
|
+
if (fs3.existsSync(swaggerSource)) {
|
|
1726
|
+
await fs3.promises.copyFile(
|
|
1640
1727
|
swaggerSource,
|
|
1641
1728
|
`${apiOutputPath}/swagger.json`
|
|
1642
1729
|
);
|
|
@@ -1670,17 +1757,17 @@ var DoculaBuilder = class {
|
|
|
1670
1757
|
{ ...data, specUrl: data.openApiUrl, apiSpec },
|
|
1671
1758
|
data.templatePath
|
|
1672
1759
|
);
|
|
1673
|
-
await
|
|
1760
|
+
await fs3.promises.writeFile(apiPath, apiContent, "utf8");
|
|
1674
1761
|
}
|
|
1675
1762
|
getChangelogEntries(changelogPath) {
|
|
1676
1763
|
const entries = [];
|
|
1677
|
-
if (!
|
|
1764
|
+
if (!fs3.existsSync(changelogPath)) {
|
|
1678
1765
|
return entries;
|
|
1679
1766
|
}
|
|
1680
|
-
const files =
|
|
1767
|
+
const files = fs3.readdirSync(changelogPath);
|
|
1681
1768
|
for (const file of files) {
|
|
1682
1769
|
const filePath = `${changelogPath}/${file}`;
|
|
1683
|
-
const stats =
|
|
1770
|
+
const stats = fs3.statSync(filePath);
|
|
1684
1771
|
if (stats.isFile() && (file.endsWith(".md") || file.endsWith(".mdx"))) {
|
|
1685
1772
|
const entry = this.parseChangelogEntry(filePath);
|
|
1686
1773
|
entries.push(entry);
|
|
@@ -1703,11 +1790,11 @@ var DoculaBuilder = class {
|
|
|
1703
1790
|
return entries;
|
|
1704
1791
|
}
|
|
1705
1792
|
parseChangelogEntry(filePath) {
|
|
1706
|
-
const fileContent =
|
|
1793
|
+
const fileContent = fs3.readFileSync(filePath, "utf8");
|
|
1707
1794
|
const writr = new Writr(fileContent);
|
|
1708
1795
|
const matterData = writr.frontMatter;
|
|
1709
1796
|
const markdownContent = writr.body;
|
|
1710
|
-
const fileName =
|
|
1797
|
+
const fileName = path5.basename(filePath, path5.extname(filePath));
|
|
1711
1798
|
const slug = fileName.replace(/^\d{4}-\d{2}-\d{2}-/, "");
|
|
1712
1799
|
const isMdx = filePath.endsWith(".mdx");
|
|
1713
1800
|
const tag = matterData.tag;
|
|
@@ -1789,14 +1876,14 @@ var DoculaBuilder = class {
|
|
|
1789
1876
|
}
|
|
1790
1877
|
const changelogOutputPath = `${data.output}/changelog`;
|
|
1791
1878
|
const changelogIndexPath = `${changelogOutputPath}/index.html`;
|
|
1792
|
-
await
|
|
1879
|
+
await fs3.promises.mkdir(changelogOutputPath, { recursive: true });
|
|
1793
1880
|
const changelogTemplate = `${data.templatePath}/${data.templates.changelog}`;
|
|
1794
1881
|
const changelogContent = await this._ecto.renderFromFile(
|
|
1795
1882
|
changelogTemplate,
|
|
1796
1883
|
{ ...data, entries: data.changelogEntries },
|
|
1797
1884
|
data.templatePath
|
|
1798
1885
|
);
|
|
1799
|
-
await
|
|
1886
|
+
await fs3.promises.writeFile(changelogIndexPath, changelogContent, "utf8");
|
|
1800
1887
|
}
|
|
1801
1888
|
async buildChangelogEntryPages(data) {
|
|
1802
1889
|
if (!data.hasChangelog || !data.templates?.changelogEntry || !data.changelogEntries?.length) {
|
|
@@ -1805,14 +1892,14 @@ var DoculaBuilder = class {
|
|
|
1805
1892
|
const entryTemplate = `${data.templatePath}/${data.templates.changelogEntry}`;
|
|
1806
1893
|
const promises = data.changelogEntries.map(async (entry) => {
|
|
1807
1894
|
const entryOutputPath = `${data.output}/changelog/${entry.slug}`;
|
|
1808
|
-
await
|
|
1895
|
+
await fs3.promises.mkdir(entryOutputPath, { recursive: true });
|
|
1809
1896
|
const entryContent = await this._ecto.renderFromFile(
|
|
1810
1897
|
entryTemplate,
|
|
1811
1898
|
{ ...data, ...entry, entries: data.changelogEntries },
|
|
1812
1899
|
data.templatePath
|
|
1813
1900
|
);
|
|
1814
1901
|
const entryFilePath = `${entryOutputPath}/index.html`;
|
|
1815
|
-
return
|
|
1902
|
+
return fs3.promises.writeFile(entryFilePath, entryContent, "utf8");
|
|
1816
1903
|
});
|
|
1817
1904
|
await Promise.all(promises);
|
|
1818
1905
|
}
|
|
@@ -1868,7 +1955,7 @@ var DoculaBuilder = class {
|
|
|
1868
1955
|
}
|
|
1869
1956
|
getDocuments(sitePath, doculaData) {
|
|
1870
1957
|
let documents = [];
|
|
1871
|
-
if (
|
|
1958
|
+
if (fs3.existsSync(sitePath)) {
|
|
1872
1959
|
documents = this.getDocumentInDirectory(sitePath);
|
|
1873
1960
|
doculaData.sections = this.getSections(sitePath, this.options);
|
|
1874
1961
|
for (const section of doculaData.sections) {
|
|
@@ -1881,11 +1968,11 @@ var DoculaBuilder = class {
|
|
|
1881
1968
|
}
|
|
1882
1969
|
getDocumentInDirectory(sitePath) {
|
|
1883
1970
|
const documents = [];
|
|
1884
|
-
const documentList =
|
|
1971
|
+
const documentList = fs3.readdirSync(sitePath);
|
|
1885
1972
|
if (documentList.length > 0) {
|
|
1886
1973
|
for (const document of documentList) {
|
|
1887
1974
|
const documentPath = `${sitePath}/${document}`;
|
|
1888
|
-
const stats =
|
|
1975
|
+
const stats = fs3.statSync(documentPath);
|
|
1889
1976
|
if (stats.isFile() && (document.endsWith(".md") || document.endsWith(".mdx"))) {
|
|
1890
1977
|
const documentData = this.parseDocumentData(documentPath);
|
|
1891
1978
|
documents.push(documentData);
|
|
@@ -1899,12 +1986,12 @@ var DoculaBuilder = class {
|
|
|
1899
1986
|
}
|
|
1900
1987
|
getSections(sitePath, doculaOptions) {
|
|
1901
1988
|
const sections = [];
|
|
1902
|
-
if (
|
|
1903
|
-
const documentList =
|
|
1989
|
+
if (fs3.existsSync(sitePath)) {
|
|
1990
|
+
const documentList = fs3.readdirSync(sitePath);
|
|
1904
1991
|
if (documentList.length > 0) {
|
|
1905
1992
|
for (const document of documentList) {
|
|
1906
1993
|
const documentPath = `${sitePath}/${document}`;
|
|
1907
|
-
const stats =
|
|
1994
|
+
const stats = fs3.statSync(documentPath);
|
|
1908
1995
|
if (stats.isDirectory() && this.directoryContainsMarkdown(documentPath)) {
|
|
1909
1996
|
const section = {
|
|
1910
1997
|
name: document.replaceAll("-", " ").replaceAll(/\b\w/g, (l) => l.toUpperCase()),
|
|
@@ -1935,7 +2022,7 @@ var DoculaBuilder = class {
|
|
|
1935
2022
|
return section;
|
|
1936
2023
|
}
|
|
1937
2024
|
parseDocumentData(documentPath) {
|
|
1938
|
-
const documentContent =
|
|
2025
|
+
const documentContent = fs3.readFileSync(documentPath, "utf8");
|
|
1939
2026
|
const writr = new Writr(documentContent);
|
|
1940
2027
|
const matterData = writr.frontMatter;
|
|
1941
2028
|
let markdownContent = writr.body;
|
|
@@ -1987,10 +2074,10 @@ ${markdownContent.slice(firstH2)}`;
|
|
|
1987
2074
|
return atxHeading.test(normalized) || setextHeading.test(normalized) || htmlHeading.test(normalized);
|
|
1988
2075
|
}
|
|
1989
2076
|
directoryContainsMarkdown(dirPath) {
|
|
1990
|
-
const entries =
|
|
2077
|
+
const entries = fs3.readdirSync(dirPath);
|
|
1991
2078
|
for (const entry of entries) {
|
|
1992
2079
|
const fullPath = `${dirPath}/${entry}`;
|
|
1993
|
-
const stat =
|
|
2080
|
+
const stat = fs3.statSync(fullPath);
|
|
1994
2081
|
if (stat.isFile() && (entry.endsWith(".md") || entry.endsWith(".mdx"))) {
|
|
1995
2082
|
return true;
|
|
1996
2083
|
}
|
|
@@ -2001,16 +2088,16 @@ ${markdownContent.slice(firstH2)}`;
|
|
|
2001
2088
|
if (this.options.templatePath) {
|
|
2002
2089
|
return resolvedTemplatePath;
|
|
2003
2090
|
}
|
|
2004
|
-
const overrideDir =
|
|
2005
|
-
const cacheDir =
|
|
2091
|
+
const overrideDir = path5.join(sitePath, "templates", templateName);
|
|
2092
|
+
const cacheDir = path5.join(sitePath, ".cache", "templates", templateName);
|
|
2006
2093
|
if (!this.isPathWithinBasePath(overrideDir, sitePath) || !this.isPathWithinBasePath(cacheDir, sitePath)) {
|
|
2007
2094
|
return resolvedTemplatePath;
|
|
2008
2095
|
}
|
|
2009
|
-
if (!
|
|
2096
|
+
if (!fs3.existsSync(overrideDir)) {
|
|
2010
2097
|
return resolvedTemplatePath;
|
|
2011
2098
|
}
|
|
2012
2099
|
const overrideFiles = this.listFilesRecursive(overrideDir);
|
|
2013
|
-
if (
|
|
2100
|
+
if (fs3.existsSync(cacheDir) && this.isCacheFresh(overrideDir, cacheDir, overrideFiles)) {
|
|
2014
2101
|
this._console.step("Using cached template overrides...");
|
|
2015
2102
|
return cacheDir;
|
|
2016
2103
|
}
|
|
@@ -2021,48 +2108,48 @@ ${markdownContent.slice(firstH2)}`;
|
|
|
2021
2108
|
}
|
|
2022
2109
|
}
|
|
2023
2110
|
this.ensureCacheInGitignore(sitePath);
|
|
2024
|
-
if (
|
|
2025
|
-
|
|
2111
|
+
if (fs3.existsSync(cacheDir)) {
|
|
2112
|
+
fs3.rmSync(cacheDir, { recursive: true, force: true });
|
|
2026
2113
|
}
|
|
2027
|
-
|
|
2114
|
+
fs3.mkdirSync(cacheDir, { recursive: true });
|
|
2028
2115
|
this.copyDirectory(resolvedTemplatePath, cacheDir);
|
|
2029
2116
|
this.copyDirectory(overrideDir, cacheDir);
|
|
2030
|
-
const manifestPath =
|
|
2031
|
-
|
|
2117
|
+
const manifestPath = path5.join(cacheDir, ".manifest.json");
|
|
2118
|
+
fs3.writeFileSync(manifestPath, JSON.stringify(overrideFiles));
|
|
2032
2119
|
return cacheDir;
|
|
2033
2120
|
}
|
|
2034
2121
|
ensureCacheInGitignore(sitePath) {
|
|
2035
2122
|
if (!this.options.autoUpdateIgnores) {
|
|
2036
2123
|
return;
|
|
2037
2124
|
}
|
|
2038
|
-
const cacheDir =
|
|
2039
|
-
if (
|
|
2125
|
+
const cacheDir = path5.join(sitePath, ".cache");
|
|
2126
|
+
if (fs3.existsSync(cacheDir)) {
|
|
2040
2127
|
return;
|
|
2041
2128
|
}
|
|
2042
|
-
const gitignorePath =
|
|
2129
|
+
const gitignorePath = path5.join(sitePath, ".gitignore");
|
|
2043
2130
|
const entry = ".cache";
|
|
2044
|
-
if (
|
|
2045
|
-
const content =
|
|
2131
|
+
if (fs3.existsSync(gitignorePath)) {
|
|
2132
|
+
const content = fs3.readFileSync(gitignorePath, "utf8");
|
|
2046
2133
|
if (!content.split("\n").some((line) => line.trim() === entry)) {
|
|
2047
|
-
|
|
2134
|
+
fs3.appendFileSync(gitignorePath, `
|
|
2048
2135
|
${entry}
|
|
2049
2136
|
`);
|
|
2050
2137
|
this._console.info(`Added ${entry} to .gitignore`);
|
|
2051
2138
|
}
|
|
2052
2139
|
} else {
|
|
2053
|
-
|
|
2140
|
+
fs3.writeFileSync(gitignorePath, `${entry}
|
|
2054
2141
|
`);
|
|
2055
2142
|
this._console.info("Created .gitignore with .cache");
|
|
2056
2143
|
}
|
|
2057
2144
|
}
|
|
2058
2145
|
isCacheFresh(overrideDir, cacheDir, overrideFiles) {
|
|
2059
|
-
const manifestPath =
|
|
2060
|
-
if (!
|
|
2146
|
+
const manifestPath = path5.join(cacheDir, ".manifest.json");
|
|
2147
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
2061
2148
|
return false;
|
|
2062
2149
|
}
|
|
2063
2150
|
try {
|
|
2064
2151
|
const previousFiles = JSON.parse(
|
|
2065
|
-
|
|
2152
|
+
fs3.readFileSync(manifestPath, "utf8")
|
|
2066
2153
|
);
|
|
2067
2154
|
if (previousFiles.length !== overrideFiles.length || !previousFiles.every((f, i) => f === overrideFiles[i])) {
|
|
2068
2155
|
return false;
|
|
@@ -2071,13 +2158,13 @@ ${entry}
|
|
|
2071
2158
|
return false;
|
|
2072
2159
|
}
|
|
2073
2160
|
for (const file of overrideFiles) {
|
|
2074
|
-
const overridePath =
|
|
2075
|
-
const cachedPath =
|
|
2076
|
-
if (!
|
|
2161
|
+
const overridePath = path5.join(overrideDir, file);
|
|
2162
|
+
const cachedPath = path5.join(cacheDir, file);
|
|
2163
|
+
if (!fs3.existsSync(cachedPath)) {
|
|
2077
2164
|
return false;
|
|
2078
2165
|
}
|
|
2079
|
-
const overrideMtime =
|
|
2080
|
-
const cachedMtime =
|
|
2166
|
+
const overrideMtime = fs3.statSync(overridePath).mtimeMs;
|
|
2167
|
+
const cachedMtime = fs3.statSync(cachedPath).mtimeMs;
|
|
2081
2168
|
if (overrideMtime > cachedMtime) {
|
|
2082
2169
|
return false;
|
|
2083
2170
|
}
|
|
@@ -2086,14 +2173,14 @@ ${entry}
|
|
|
2086
2173
|
}
|
|
2087
2174
|
listFilesRecursive(dir, prefix = "") {
|
|
2088
2175
|
const results = [];
|
|
2089
|
-
const entries =
|
|
2176
|
+
const entries = fs3.readdirSync(dir);
|
|
2090
2177
|
for (const entry of entries) {
|
|
2091
2178
|
if (entry.startsWith(".")) {
|
|
2092
2179
|
continue;
|
|
2093
2180
|
}
|
|
2094
|
-
const fullPath =
|
|
2181
|
+
const fullPath = path5.join(dir, entry);
|
|
2095
2182
|
const relativePath = prefix ? `${prefix}/${entry}` : entry;
|
|
2096
|
-
const stat =
|
|
2183
|
+
const stat = fs3.lstatSync(fullPath);
|
|
2097
2184
|
if (stat.isSymbolicLink()) {
|
|
2098
2185
|
continue;
|
|
2099
2186
|
}
|
|
@@ -2106,55 +2193,55 @@ ${entry}
|
|
|
2106
2193
|
return results;
|
|
2107
2194
|
}
|
|
2108
2195
|
copyDirectory(source, target) {
|
|
2109
|
-
const files =
|
|
2196
|
+
const files = fs3.readdirSync(source);
|
|
2110
2197
|
for (const file of files) {
|
|
2111
2198
|
if (file.startsWith(".")) {
|
|
2112
2199
|
continue;
|
|
2113
2200
|
}
|
|
2114
2201
|
const sourcePath = `${source}/${file}`;
|
|
2115
2202
|
const targetPath = `${target}/${file}`;
|
|
2116
|
-
const stat =
|
|
2203
|
+
const stat = fs3.lstatSync(sourcePath);
|
|
2117
2204
|
if (stat.isSymbolicLink()) {
|
|
2118
2205
|
continue;
|
|
2119
2206
|
}
|
|
2120
2207
|
if (stat.isDirectory()) {
|
|
2121
|
-
|
|
2208
|
+
fs3.mkdirSync(targetPath, { recursive: true });
|
|
2122
2209
|
this.copyDirectory(sourcePath, targetPath);
|
|
2123
2210
|
} else {
|
|
2124
|
-
|
|
2125
|
-
|
|
2211
|
+
fs3.mkdirSync(target, { recursive: true });
|
|
2212
|
+
fs3.copyFileSync(sourcePath, targetPath);
|
|
2126
2213
|
}
|
|
2127
2214
|
}
|
|
2128
2215
|
}
|
|
2129
2216
|
copyPublicFolder(sitePath, output) {
|
|
2130
2217
|
const publicPath = `${sitePath}/public`;
|
|
2131
|
-
if (!
|
|
2218
|
+
if (!fs3.existsSync(publicPath)) {
|
|
2132
2219
|
return;
|
|
2133
2220
|
}
|
|
2134
2221
|
this._console.step("Copying public folder...");
|
|
2135
|
-
const resolvedOutput =
|
|
2222
|
+
const resolvedOutput = path5.resolve(output);
|
|
2136
2223
|
this.copyPublicDirectory(publicPath, output, publicPath, resolvedOutput);
|
|
2137
2224
|
}
|
|
2138
2225
|
copyPublicDirectory(source, target, basePath, output) {
|
|
2139
|
-
const files =
|
|
2226
|
+
const files = fs3.readdirSync(source);
|
|
2140
2227
|
for (const file of files) {
|
|
2141
2228
|
const sourcePath = `${source}/${file}`;
|
|
2142
2229
|
const targetPath = `${target}/${file}`;
|
|
2143
2230
|
const relativePath = sourcePath.replace(`${basePath}/`, "");
|
|
2144
|
-
const resolvedSourcePath =
|
|
2145
|
-
if (resolvedSourcePath === output || resolvedSourcePath.startsWith(`${output}${
|
|
2231
|
+
const resolvedSourcePath = path5.resolve(sourcePath);
|
|
2232
|
+
if (resolvedSourcePath === output || resolvedSourcePath.startsWith(`${output}${path5.sep}`)) {
|
|
2146
2233
|
continue;
|
|
2147
2234
|
}
|
|
2148
|
-
const stat =
|
|
2235
|
+
const stat = fs3.lstatSync(sourcePath);
|
|
2149
2236
|
if (stat.isSymbolicLink()) {
|
|
2150
2237
|
continue;
|
|
2151
2238
|
}
|
|
2152
2239
|
if (stat.isDirectory()) {
|
|
2153
|
-
|
|
2240
|
+
fs3.mkdirSync(targetPath, { recursive: true });
|
|
2154
2241
|
this.copyPublicDirectory(sourcePath, targetPath, basePath, output);
|
|
2155
2242
|
} else {
|
|
2156
|
-
|
|
2157
|
-
|
|
2243
|
+
fs3.mkdirSync(target, { recursive: true });
|
|
2244
|
+
fs3.copyFileSync(sourcePath, targetPath);
|
|
2158
2245
|
this._console.fileCopied(relativePath);
|
|
2159
2246
|
}
|
|
2160
2247
|
}
|
|
@@ -2164,18 +2251,18 @@ ${entry}
|
|
|
2164
2251
|
return;
|
|
2165
2252
|
}
|
|
2166
2253
|
for (const document of data.documents) {
|
|
2167
|
-
const sourceDir =
|
|
2168
|
-
const outputDir = `${data.output}${
|
|
2254
|
+
const sourceDir = path5.dirname(document.documentPath);
|
|
2255
|
+
const outputDir = `${data.output}${path5.dirname(document.urlPath)}`;
|
|
2169
2256
|
const availableAssets = this.listContentAssets(sourceDir);
|
|
2170
2257
|
for (const assetRelPath of availableAssets) {
|
|
2171
2258
|
if (document.markdown.includes(assetRelPath)) {
|
|
2172
|
-
const source =
|
|
2173
|
-
if (
|
|
2259
|
+
const source = path5.join(sourceDir, assetRelPath);
|
|
2260
|
+
if (fs3.lstatSync(source).isSymbolicLink()) {
|
|
2174
2261
|
continue;
|
|
2175
2262
|
}
|
|
2176
|
-
const target =
|
|
2177
|
-
|
|
2178
|
-
|
|
2263
|
+
const target = path5.join(outputDir, assetRelPath);
|
|
2264
|
+
fs3.mkdirSync(path5.dirname(target), { recursive: true });
|
|
2265
|
+
fs3.copyFileSync(source, target);
|
|
2179
2266
|
}
|
|
2180
2267
|
}
|
|
2181
2268
|
}
|
|
@@ -2183,52 +2270,52 @@ ${entry}
|
|
|
2183
2270
|
listContentAssets(sourcePath, basePath) {
|
|
2184
2271
|
const root = basePath ?? sourcePath;
|
|
2185
2272
|
const results = [];
|
|
2186
|
-
if (!
|
|
2273
|
+
if (!fs3.existsSync(sourcePath)) {
|
|
2187
2274
|
return results;
|
|
2188
2275
|
}
|
|
2189
|
-
const files =
|
|
2276
|
+
const files = fs3.readdirSync(sourcePath);
|
|
2190
2277
|
for (const file of files) {
|
|
2191
2278
|
if (file.startsWith(".")) {
|
|
2192
2279
|
continue;
|
|
2193
2280
|
}
|
|
2194
2281
|
const fullPath = `${sourcePath}/${file}`;
|
|
2195
|
-
const stat =
|
|
2282
|
+
const stat = fs3.lstatSync(fullPath);
|
|
2196
2283
|
if (stat.isSymbolicLink()) {
|
|
2197
2284
|
continue;
|
|
2198
2285
|
}
|
|
2199
2286
|
if (stat.isDirectory()) {
|
|
2200
2287
|
results.push(...this.listContentAssets(fullPath, root));
|
|
2201
2288
|
} else {
|
|
2202
|
-
const ext =
|
|
2289
|
+
const ext = path5.extname(file).toLowerCase();
|
|
2203
2290
|
if (this.options.allowedAssets.includes(ext)) {
|
|
2204
|
-
results.push(
|
|
2291
|
+
results.push(path5.relative(root, fullPath));
|
|
2205
2292
|
}
|
|
2206
2293
|
}
|
|
2207
2294
|
}
|
|
2208
2295
|
return results;
|
|
2209
2296
|
}
|
|
2210
2297
|
copyContentAssets(sourcePath, targetPath) {
|
|
2211
|
-
if (!
|
|
2298
|
+
if (!fs3.existsSync(sourcePath)) {
|
|
2212
2299
|
return;
|
|
2213
2300
|
}
|
|
2214
|
-
const files =
|
|
2301
|
+
const files = fs3.readdirSync(sourcePath);
|
|
2215
2302
|
for (const file of files) {
|
|
2216
2303
|
if (file.startsWith(".")) {
|
|
2217
2304
|
continue;
|
|
2218
2305
|
}
|
|
2219
2306
|
const source = `${sourcePath}/${file}`;
|
|
2220
2307
|
const target = `${targetPath}/${file}`;
|
|
2221
|
-
const stat =
|
|
2308
|
+
const stat = fs3.lstatSync(source);
|
|
2222
2309
|
if (stat.isSymbolicLink()) {
|
|
2223
2310
|
continue;
|
|
2224
2311
|
}
|
|
2225
2312
|
if (stat.isDirectory()) {
|
|
2226
2313
|
this.copyContentAssets(source, target);
|
|
2227
2314
|
} else {
|
|
2228
|
-
const ext =
|
|
2315
|
+
const ext = path5.extname(file).toLowerCase();
|
|
2229
2316
|
if (this.options.allowedAssets.includes(ext)) {
|
|
2230
|
-
|
|
2231
|
-
|
|
2317
|
+
fs3.mkdirSync(targetPath, { recursive: true });
|
|
2318
|
+
fs3.copyFileSync(source, target);
|
|
2232
2319
|
}
|
|
2233
2320
|
}
|
|
2234
2321
|
}
|
|
@@ -2304,13 +2391,13 @@ var Docula = class {
|
|
|
2304
2391
|
* @param {string} sitePath
|
|
2305
2392
|
*/
|
|
2306
2393
|
cleanCache(sitePath) {
|
|
2307
|
-
const resolvedSitePath =
|
|
2308
|
-
const cachePath =
|
|
2309
|
-
if (!cachePath.startsWith(resolvedSitePath +
|
|
2394
|
+
const resolvedSitePath = path6.resolve(sitePath);
|
|
2395
|
+
const cachePath = path6.resolve(resolvedSitePath, ".cache");
|
|
2396
|
+
if (!cachePath.startsWith(resolvedSitePath + path6.sep) && cachePath !== resolvedSitePath) {
|
|
2310
2397
|
return;
|
|
2311
2398
|
}
|
|
2312
|
-
if (
|
|
2313
|
-
|
|
2399
|
+
if (fs4.existsSync(cachePath)) {
|
|
2400
|
+
fs4.rmSync(cachePath, { recursive: true, force: true });
|
|
2314
2401
|
}
|
|
2315
2402
|
}
|
|
2316
2403
|
/**
|
|
@@ -2318,9 +2405,9 @@ var Docula = class {
|
|
|
2318
2405
|
* @returns {void}
|
|
2319
2406
|
*/
|
|
2320
2407
|
checkForUpdates() {
|
|
2321
|
-
const packageJsonPath =
|
|
2322
|
-
if (
|
|
2323
|
-
const packageJson = JSON.parse(
|
|
2408
|
+
const packageJsonPath = path6.join(process4.cwd(), "package.json");
|
|
2409
|
+
if (fs4.existsSync(packageJsonPath)) {
|
|
2410
|
+
const packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf8"));
|
|
2324
2411
|
updateNotifier({ pkg: packageJson }).notify();
|
|
2325
2412
|
}
|
|
2326
2413
|
}
|
|
@@ -2376,8 +2463,8 @@ var Docula = class {
|
|
|
2376
2463
|
}
|
|
2377
2464
|
case "serve": {
|
|
2378
2465
|
if (consoleProcess.args.build || consoleProcess.args.watch) {
|
|
2379
|
-
if (consoleProcess.args.clean &&
|
|
2380
|
-
|
|
2466
|
+
if (consoleProcess.args.clean && fs4.existsSync(this.options.output)) {
|
|
2467
|
+
fs4.rmSync(this.options.output, { recursive: true, force: true });
|
|
2381
2468
|
}
|
|
2382
2469
|
if (consoleProcess.args.clean) {
|
|
2383
2470
|
this.cleanCache(this.options.sitePath);
|
|
@@ -2392,8 +2479,8 @@ var Docula = class {
|
|
|
2392
2479
|
break;
|
|
2393
2480
|
}
|
|
2394
2481
|
default: {
|
|
2395
|
-
if (consoleProcess.args.clean &&
|
|
2396
|
-
|
|
2482
|
+
if (consoleProcess.args.clean && fs4.existsSync(this.options.output)) {
|
|
2483
|
+
fs4.rmSync(this.options.output, { recursive: true, force: true });
|
|
2397
2484
|
}
|
|
2398
2485
|
if (consoleProcess.args.clean) {
|
|
2399
2486
|
this.cleanCache(this.options.sitePath);
|
|
@@ -2411,8 +2498,8 @@ var Docula = class {
|
|
|
2411
2498
|
* @returns {void}
|
|
2412
2499
|
*/
|
|
2413
2500
|
generateInit(sitePath, typescript = false) {
|
|
2414
|
-
if (!
|
|
2415
|
-
|
|
2501
|
+
if (!fs4.existsSync(sitePath)) {
|
|
2502
|
+
fs4.mkdirSync(sitePath);
|
|
2416
2503
|
}
|
|
2417
2504
|
const configExtension = typescript ? "ts" : "mjs";
|
|
2418
2505
|
const doculaConfigFile = `${sitePath}/docula.config.${configExtension}`;
|
|
@@ -2420,11 +2507,11 @@ var Docula = class {
|
|
|
2420
2507
|
typescript ? doculaconfigts : doculaconfigmjs,
|
|
2421
2508
|
"base64"
|
|
2422
2509
|
);
|
|
2423
|
-
|
|
2510
|
+
fs4.writeFileSync(doculaConfigFile, doculaConfigFileBuffer);
|
|
2424
2511
|
const logoBuffer = Buffer.from(logopng, "base64");
|
|
2425
|
-
|
|
2512
|
+
fs4.writeFileSync(`${sitePath}/logo.png`, logoBuffer);
|
|
2426
2513
|
const faviconBuffer = Buffer.from(faviconico, "base64");
|
|
2427
|
-
|
|
2514
|
+
fs4.writeFileSync(`${sitePath}/favicon.ico`, faviconBuffer);
|
|
2428
2515
|
this._console.log(
|
|
2429
2516
|
`docula initialized. Please update the ${doculaConfigFile} file with your site information. In addition, you can replace the image and favicon.`
|
|
2430
2517
|
);
|
|
@@ -2434,7 +2521,7 @@ var Docula = class {
|
|
|
2434
2521
|
* @returns {string}
|
|
2435
2522
|
*/
|
|
2436
2523
|
getVersion() {
|
|
2437
|
-
const packageJson =
|
|
2524
|
+
const packageJson = fs4.readFileSync("./package.json", "utf8");
|
|
2438
2525
|
const packageObject = JSON.parse(packageJson);
|
|
2439
2526
|
return packageObject.version;
|
|
2440
2527
|
}
|
|
@@ -2445,21 +2532,21 @@ var Docula = class {
|
|
|
2445
2532
|
* @returns {Promise<void>}
|
|
2446
2533
|
*/
|
|
2447
2534
|
async loadConfigFile(sitePath) {
|
|
2448
|
-
if (!
|
|
2535
|
+
if (!fs4.existsSync(sitePath)) {
|
|
2449
2536
|
return;
|
|
2450
2537
|
}
|
|
2451
2538
|
const tsConfigFile = `${sitePath}/docula.config.ts`;
|
|
2452
2539
|
const mjsConfigFile = `${sitePath}/docula.config.mjs`;
|
|
2453
|
-
if (
|
|
2454
|
-
const absolutePath =
|
|
2540
|
+
if (fs4.existsSync(tsConfigFile)) {
|
|
2541
|
+
const absolutePath = path6.resolve(tsConfigFile);
|
|
2455
2542
|
const jiti = createJiti(import.meta.url, {
|
|
2456
2543
|
interopDefault: true
|
|
2457
2544
|
});
|
|
2458
2545
|
this._configFileModule = await jiti.import(absolutePath);
|
|
2459
2546
|
return;
|
|
2460
2547
|
}
|
|
2461
|
-
if (
|
|
2462
|
-
const absolutePath =
|
|
2548
|
+
if (fs4.existsSync(mjsConfigFile)) {
|
|
2549
|
+
const absolutePath = path6.resolve(mjsConfigFile);
|
|
2463
2550
|
this._configFileModule = await import(pathToFileURL(absolutePath).href);
|
|
2464
2551
|
}
|
|
2465
2552
|
}
|
|
@@ -2476,7 +2563,7 @@ var Docula = class {
|
|
|
2476
2563
|
let debounceTimer;
|
|
2477
2564
|
let isBuilding = false;
|
|
2478
2565
|
let pendingRebuild = false;
|
|
2479
|
-
const outputRelative =
|
|
2566
|
+
const outputRelative = path6.relative(options.sitePath, options.output);
|
|
2480
2567
|
const runBuild = async (filename) => {
|
|
2481
2568
|
isBuilding = true;
|
|
2482
2569
|
this._console.info(`File changed: ${filename}, rebuilding...`);
|
|
@@ -2493,11 +2580,11 @@ var Docula = class {
|
|
|
2493
2580
|
}
|
|
2494
2581
|
}
|
|
2495
2582
|
};
|
|
2496
|
-
this._watcher =
|
|
2583
|
+
this._watcher = fs4.watch(
|
|
2497
2584
|
options.sitePath,
|
|
2498
2585
|
{ recursive: true },
|
|
2499
2586
|
(_eventType, filename) => {
|
|
2500
|
-
if (filename && outputRelative && !outputRelative.startsWith("..") && (String(filename) === outputRelative || String(filename).startsWith(`${outputRelative}${
|
|
2587
|
+
if (filename && outputRelative && !outputRelative.startsWith("..") && (String(filename) === outputRelative || String(filename).startsWith(`${outputRelative}${path6.sep}`))) {
|
|
2501
2588
|
return;
|
|
2502
2589
|
}
|
|
2503
2590
|
if (isBuilding) {
|
|
@@ -2526,8 +2613,8 @@ var Docula = class {
|
|
|
2526
2613
|
}
|
|
2527
2614
|
const { port } = options;
|
|
2528
2615
|
const { output } = options;
|
|
2529
|
-
if (!
|
|
2530
|
-
|
|
2616
|
+
if (!fs4.existsSync(output)) {
|
|
2617
|
+
fs4.mkdirSync(output, { recursive: true });
|
|
2531
2618
|
}
|
|
2532
2619
|
const config = {
|
|
2533
2620
|
public: output
|
|
@@ -2561,9 +2648,9 @@ export {
|
|
|
2561
2648
|
Docula as default
|
|
2562
2649
|
};
|
|
2563
2650
|
/* v8 ignore next -- @preserve */
|
|
2651
|
+
/* v8 ignore next 3 -- @preserve */
|
|
2564
2652
|
/* v8 ignore next 2 -- @preserve */
|
|
2565
2653
|
/* v8 ignore next 9 -- @preserve */
|
|
2566
|
-
/* v8 ignore next 3 -- @preserve */
|
|
2567
2654
|
/* v8 ignore next 4 -- @preserve */
|
|
2568
2655
|
/* v8 ignore start -- @preserve */
|
|
2569
2656
|
/* v8 ignore stop -- @preserve */
|