Skip to content

Commit e893c2f

Browse files
authored
Integrate Developer Guide into documentation build process (#7601)
2 parents ed146f7 + aa526d9 commit e893c2f

File tree

6 files changed

+66
-18
lines changed

6 files changed

+66
-18
lines changed

.github/workflows/deploy-docs.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
paths:
1111
- 'docs/**'
1212
- 'apps/edit-docs/**'
13+
- 'apps/build-docs/**'
1314
- 'packages/share-theme/**'
1415

1516
# Allow manual triggering from Actions tab
@@ -23,6 +24,7 @@ on:
2324
paths:
2425
- 'docs/**'
2526
- 'apps/edit-docs/**'
27+
- 'apps/build-docs/**'
2628
- 'packages/share-theme/**'
2729

2830
jobs:
@@ -60,6 +62,8 @@ jobs:
6062
- name: Validate Built Site
6163
run: |
6264
test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1)
65+
test -f site/developer-guide/index.html || (echo "ERROR: site/developer-guide/index.html not found" && exit 1)
66+
echo "✓ User Guide and Developer Guide built successfully"
6367
6468
- name: Deploy
6569
uses: ./.github/actions/deploy-to-cloudflare-pages

apps/build-docs/src/build-docs.ts

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,12 @@ import BuildContext from "./context.js";
1414
const DOCS_ROOT = "../../../docs";
1515
const OUTPUT_DIR = "../../site";
1616

17-
async function buildDocsInner() {
18-
const i18n = await import("@triliumnext/server/src/services/i18n.js");
19-
await i18n.initializeTranslations();
20-
21-
const sqlInit = (await import("../../server/src/services/sql_init.js")).default;
22-
await sqlInit.createInitialDatabase(true);
23-
24-
const note = await importData(join(__dirname, DOCS_ROOT, "User Guide"));
17+
async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
18+
const note = await importData(sourcePath);
2519

26-
// Export
27-
const zipFilePath = "output.zip";
20+
// Use a meaningful name for the temporary zip file
21+
const zipName = outputSubDir || "user-guide";
22+
const zipFilePath = `output-${zipName}.zip`;
2823
try {
2924
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default;
3025
const branch = note.getParentBranches()[0];
@@ -36,25 +31,50 @@ async function buildDocsInner() {
3631
const fileOutputStream = fsExtra.createWriteStream(zipFilePath);
3732
await exportToZip(taskContext, branch, "share", fileOutputStream);
3833
await waitForStreamToFinish(fileOutputStream);
39-
await extractZip(zipFilePath, OUTPUT_DIR);
34+
35+
// Output to root directory if outputSubDir is empty, otherwise to subdirectory
36+
const outputPath = outputSubDir ? join(OUTPUT_DIR, outputSubDir) : OUTPUT_DIR;
37+
await extractZip(zipFilePath, outputPath);
4038
} finally {
4139
if (await fsExtra.exists(zipFilePath)) {
4240
await fsExtra.rm(zipFilePath);
4341
}
4442
}
43+
}
44+
45+
async function buildDocsInner() {
46+
const i18n = await import("@triliumnext/server/src/services/i18n.js");
47+
await i18n.initializeTranslations();
48+
49+
const sqlInit = (await import("../../server/src/services/sql_init.js")).default;
50+
await sqlInit.createInitialDatabase(true);
51+
52+
// Wait for becca to be loaded before importing data
53+
const beccaLoader = await import("../../server/src/becca/becca_loader.js");
54+
await beccaLoader.beccaLoaded;
55+
56+
// Build User Guide
57+
console.log("Building User Guide...");
58+
await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide");
59+
60+
// Build Developer Guide
61+
console.log("Building Developer Guide...");
62+
await importAndExportDocs(join(__dirname, DOCS_ROOT, "Developer Guide"), "developer-guide");
4563

4664
// Copy favicon.
4765
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico"));
66+
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "user-guide", "favicon.ico"));
67+
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "developer-guide", "favicon.ico"));
4868

4969
console.log("Documentation built successfully!");
5070
}
5171

5272
export async function importData(path: string) {
5373
const buffer = await createImportZip(path);
54-
const importService = (await import("@triliumnext/server/src/services/import/zip.js")).default;
55-
const TaskContext = (await import("@triliumnext/server/src/services/task_context.js")).default;
74+
const importService = (await import("../../server/src/services/import/zip.js")).default;
75+
const TaskContext = (await import("../../server/src/services/task_context.js")).default;
5676
const context = new TaskContext("no-progress-reporting", "importNotes", null);
57-
const becca = (await import("@triliumnext/server/src/becca/becca.js")).default;
77+
const becca = (await import("../../server/src/becca/becca.js")).default;
5878

5979
const rootNote = becca.getRoot();
6080
if (!rootNote) {

apps/build-docs/src/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta http-equiv="refresh" content="0; url=/user-guide">
5+
<title>Redirecting...</title>
6+
</head>
7+
<body>
8+
<p>If you are not redirected automatically, <a href="/user-guide">click here</a>.</p>
9+
</body>
10+
</html>

apps/build-docs/src/main.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { join } from "path";
22
import BuildContext from "./context";
33
import buildSwagger from "./swagger";
4-
import { existsSync, mkdirSync, rmSync } from "fs";
4+
import { cpSync, existsSync, mkdirSync, rmSync } from "fs";
55
import buildDocs from "./build-docs";
66
import buildScriptApi from "./script-api";
77

@@ -21,6 +21,9 @@ async function main() {
2121
await buildDocs(context);
2222
buildSwagger(context);
2323
buildScriptApi(context);
24+
25+
// Copy index file.
26+
cpSync(join(__dirname, "index.html"), join(context.baseDir, "index.html"));
2427
}
2528

2629
main();

apps/server/src/services/export/zip.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
253253

254254
for (let i = 0; i < targetPath.length - 1; i++) {
255255
const meta = noteIdToMeta[targetPath[i]];
256+
if (meta === rootMeta && format === "share") {
257+
continue;
258+
}
259+
256260
if (meta.dirFileName) {
257261
url += `${encodeURIComponent(meta.dirFileName)}/`;
258262
}
@@ -371,10 +375,12 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch,
371375
}
372376

373377
if (noteMeta.children?.length || 0 > 0) {
374-
const directoryPath = filePathPrefix + noteMeta.dirFileName;
378+
const directoryPath = filePathPrefix !== "" || format !== "share" ? filePathPrefix + noteMeta.dirFileName : "";
375379

376380
// create directory
377-
archive.append("", { name: `${directoryPath}/`, date: dateUtils.parseDateTime(note.utcDateModified) });
381+
if (directoryPath) {
382+
archive.append("", { name: `${directoryPath}/`, date: dateUtils.parseDateTime(note.utcDateModified) });
383+
}
378384

379385
for (const childMeta of noteMeta.children || []) {
380386
saveNote(childMeta, `${directoryPath}/`);

apps/server/src/services/export/zip/share_theme.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
2727
private assetsMeta: NoteMeta[] = [];
2828
private indexMeta: NoteMeta | null = null;
2929
private searchIndex: Map<string, SearchIndexEntry> = new Map();
30+
private rootMeta: NoteMeta | null = null;
3031

3132
prepareMeta(metaFile: NoteMetaFile): void {
3233
const assets = [
@@ -50,6 +51,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
5051
noImport: true,
5152
dataFileName: "index.html"
5253
};
54+
this.rootMeta = metaFile.files[0];
5355

5456
metaFile.files.push(this.indexMeta);
5557
}
@@ -58,7 +60,7 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
5860
if (!noteMeta?.notePath?.length) {
5961
throw new Error("Missing note path.");
6062
}
61-
const basePath = "../".repeat(noteMeta.notePath.length - 1);
63+
const basePath = "../".repeat(Math.max(0, noteMeta.notePath.length - 2));
6264
let searchContent = "";
6365

6466
if (note) {
@@ -71,6 +73,9 @@ export default class ShareThemeExportProvider extends ZipExportProvider {
7173
if (typeof content === "string") {
7274
content = content.replace(/href="[^"]*\.\/([a-zA-Z0-9_\/]{12})[^"]*"/g, (match, id) => {
7375
if (match.includes("/assets/")) return match;
76+
if (id === this.rootMeta?.noteId) {
77+
return `href="${basePath}"`;
78+
}
7479
return `href="#root/${id}"`;
7580
});
7681
content = this.rewriteFn(content, noteMeta);

0 commit comments

Comments
 (0)