From 07f273fda40b138c0262d8c1aea172948af62855 Mon Sep 17 00:00:00 2001 From: Wael Nasreddine Date: Sat, 31 Jan 2026 01:00:57 -0800 Subject: [PATCH] feat: enhance build-docs utility with pnpm and Nix support This enhances the `build-docs` utility to allow running it via pnpm and packaging it as a Nix application. Changes include: - Added `build` and `cli` scripts to `apps/build-docs/package.json`. - Implemented a standalone CLI wrapper for documentation generation. - Added a `trilium-build-docs` package to the Nix flake for use in other projects. - Integrated `apps/build-docs` into the Nix workspace and build pipeline. These changes make the documentation build process more portable and easier to integrate into CI/CD pipelines outside of the main repository. --- apps/build-docs/package.json | 10 +- apps/build-docs/scripts/build.ts | 23 +++ .../src/backend_script_entrypoint.ts | 11 +- apps/build-docs/src/build-docs.ts | 189 +++++++++++++++--- apps/build-docs/src/cli.ts | 89 +++++++++ .../src/frontend_script_entrypoint.ts | 9 +- apps/build-docs/src/main.ts | 7 +- apps/build-docs/src/script-api.ts | 3 +- apps/build-docs/src/swagger.ts | 10 +- apps/build-docs/tsconfig.json | 4 +- apps/build-docs/typedoc.backend.json | 1 + apps/build-docs/typedoc.frontend.json | 1 + apps/server/src/services/export/zip.ts | 4 +- apps/server/src/services/utils.ts | 11 +- flake.nix | 42 +++- pnpm-lock.yaml | 6 +- 16 files changed, 365 insertions(+), 55 deletions(-) create mode 100644 apps/build-docs/scripts/build.ts create mode 100644 apps/build-docs/src/cli.ts diff --git a/apps/build-docs/package.json b/apps/build-docs/package.json index ac5be7e9be..e8934b71ec 100644 --- a/apps/build-docs/package.json +++ b/apps/build-docs/package.json @@ -1,10 +1,15 @@ { "name": "build-docs", "version": "1.0.0", - "description": "", + "description": "Build documentation from Trilium notes", "main": "src/main.ts", + "bin": { + "trilium-build-docs": "dist/cli.js" + }, "scripts": { - "start": "tsx ." + "start": "tsx .", + "cli": "tsx src/cli.ts", + "build": "tsx scripts/build.ts" }, "keywords": [], "author": "Elian Doran ", @@ -14,6 +19,7 @@ "@redocly/cli": "2.15.0", "archiver": "7.0.1", "fs-extra": "11.3.3", + "js-yaml": "4.1.1", "react": "19.2.4", "react-dom": "19.2.4", "typedoc": "0.28.16", diff --git a/apps/build-docs/scripts/build.ts b/apps/build-docs/scripts/build.ts new file mode 100644 index 0000000000..79fa01f3f6 --- /dev/null +++ b/apps/build-docs/scripts/build.ts @@ -0,0 +1,23 @@ +import BuildHelper from "../../../scripts/build-utils"; + +const build = new BuildHelper("apps/build-docs"); + +async function main() { + // Build the CLI and other TypeScript files + await build.buildBackend([ + "src/cli.ts", + "src/main.ts", + "src/build-docs.ts", + "src/swagger.ts", + "src/script-api.ts", + "src/context.ts" + ]); + + // Copy HTML template + build.copy("src/index.html", "index.html"); + + // Copy node modules dependencies if needed + build.copyNodeModules([ "better-sqlite3", "bindings", "file-uri-to-path" ]); +} + +main(); diff --git a/apps/build-docs/src/backend_script_entrypoint.ts b/apps/build-docs/src/backend_script_entrypoint.ts index bc9087c0c1..0447900b6b 100644 --- a/apps/build-docs/src/backend_script_entrypoint.ts +++ b/apps/build-docs/src/backend_script_entrypoint.ts @@ -13,8 +13,12 @@ * Make sure to keep in line with backend's `script_context.ts`. */ -export type { default as AbstractBeccaEntity } from "../../server/src/becca/entities/abstract_becca_entity.js"; -export type { default as BAttachment } from "../../server/src/becca/entities/battachment.js"; +export type { + default as AbstractBeccaEntity +} from "../../server/src/becca/entities/abstract_becca_entity.js"; +export type { + default as BAttachment +} from "../../server/src/becca/entities/battachment.js"; export type { default as BAttribute } from "../../server/src/becca/entities/battribute.js"; export type { default as BBranch } from "../../server/src/becca/entities/bbranch.js"; export type { default as BEtapiToken } from "../../server/src/becca/entities/betapi_token.js"; @@ -31,6 +35,7 @@ export type { Api }; const fakeNote = new BNote(); /** - * The `api` global variable allows access to the backend script API, which is documented in {@link Api}. + * The `api` global variable allows access to the backend script API, + * which is documented in {@link Api}. */ export const api: Api = new BackendScriptApi(fakeNote, {}); diff --git a/apps/build-docs/src/build-docs.ts b/apps/build-docs/src/build-docs.ts index 5d1a0cdd6f..357ecb1d41 100644 --- a/apps/build-docs/src/build-docs.ts +++ b/apps/build-docs/src/build-docs.ts @@ -1,19 +1,90 @@ process.env.TRILIUM_INTEGRATION_TEST = "memory-no-store"; -process.env.TRILIUM_RESOURCE_DIR = "../server/src"; +// Only set TRILIUM_RESOURCE_DIR if not already set (e.g., by Nix wrapper) +if (!process.env.TRILIUM_RESOURCE_DIR) { + process.env.TRILIUM_RESOURCE_DIR = "../server/src"; +} process.env.NODE_ENV = "development"; import cls from "@triliumnext/server/src/services/cls.js"; -import { dirname, join, resolve } from "path"; +import archiver from "archiver"; +import { execSync } from "child_process"; +import { WriteStream } from "fs"; import * as fs from "fs/promises"; import * as fsExtra from "fs-extra"; -import archiver from "archiver"; -import { WriteStream } from "fs"; -import { execSync } from "child_process"; +import yaml from "js-yaml"; +import { dirname, join, resolve } from "path"; + import BuildContext from "./context.js"; +interface NoteMapping { + rootNoteId: string; + path: string; + format: "markdown" | "html" | "share"; + ignoredFiles?: string[]; + exportOnly?: boolean; +} + +interface Config { + baseUrl: string; + noteMappings: NoteMapping[]; +} + const DOCS_ROOT = "../../../docs"; const OUTPUT_DIR = "../../site"; +// Load configuration from edit-docs-config.yaml +async function loadConfig(configPath?: string): Promise { + const pathsToTry = configPath + ? [resolve(configPath)] + : [ + join(process.cwd(), "edit-docs-config.yaml"), + join(__dirname, "../../../edit-docs-config.yaml") + ]; + + for (const path of pathsToTry) { + try { + const configContent = await fs.readFile(path, "utf-8"); + const config = yaml.load(configContent) as Config; + + // Resolve all paths relative to the config file's directory + const CONFIG_DIR = dirname(path); + config.noteMappings = config.noteMappings.map((mapping) => ({ + ...mapping, + path: resolve(CONFIG_DIR, mapping.path) + })); + + return config; + } catch (error) { + if (error.code !== "ENOENT") { + throw error; // rethrow unexpected errors + } + } + } + + return null; // No config file found +} + +async function exportDocs( + noteId: string, + format: "markdown" | "html" | "share", + outputPath: string, + ignoredFiles?: string[] +) { + const zipFilePath = `output-${noteId}.zip`; + try { + const { exportToZipFile } = (await import("@triliumnext/server/src/services/export/zip.js")) + .default; + await exportToZipFile(noteId, format, zipFilePath, {}); + + const ignoredSet = ignoredFiles ? new Set(ignoredFiles) : undefined; + await extractZip(zipFilePath, outputPath, ignoredSet); + } finally { + if (await fsExtra.exists(zipFilePath)) { + await fsExtra.rm(zipFilePath); + } + } +} + async function importAndExportDocs(sourcePath: string, outputSubDir: string) { const note = await importData(sourcePath); @@ -21,15 +92,18 @@ async function importAndExportDocs(sourcePath: string, outputSubDir: string) { const zipName = outputSubDir || "user-guide"; const zipFilePath = `output-${zipName}.zip`; try { - const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default; + const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")) + .default; const branch = note.getParentBranches()[0]; - const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")).default( - "no-progress-reporting", - "export", - null - ); + const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")) + .default( + "no-progress-reporting", + "export", + null + ); const fileOutputStream = fsExtra.createWriteStream(zipFilePath); await exportToZip(taskContext, branch, "share", fileOutputStream); + const { waitForStreamToFinish } = await import("@triliumnext/server/src/services/utils.js"); await waitForStreamToFinish(fileOutputStream); // Output to root directory if outputSubDir is empty, otherwise to subdirectory @@ -42,7 +116,7 @@ async function importAndExportDocs(sourcePath: string, outputSubDir: string) { } } -async function buildDocsInner() { +async function buildDocsInner(config?: Config) { const i18n = await import("@triliumnext/server/src/services/i18n.js"); await i18n.initializeTranslations(); @@ -53,18 +127,49 @@ async function buildDocsInner() { const beccaLoader = await import("../../server/src/becca/becca_loader.js"); await beccaLoader.beccaLoaded; - // Build User Guide - console.log("Building User Guide..."); - await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide"); + if (config) { + // Config-based build (reads from edit-docs-config.yaml) + console.log("Building documentation from config file..."); - // Build Developer Guide - console.log("Building Developer Guide..."); - await importAndExportDocs(join(__dirname, DOCS_ROOT, "Developer Guide"), "developer-guide"); + // Import all non-export-only mappings + for (const mapping of config.noteMappings) { + if (!mapping.exportOnly) { + console.log(`Importing from ${mapping.path}...`); + await importData(mapping.path); + } + } - // Copy favicon. - await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico")); - await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "user-guide", "favicon.ico")); - await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "developer-guide", "favicon.ico")); + // Export all mappings + for (const mapping of config.noteMappings) { + if (mapping.exportOnly) { + console.log(`Exporting ${mapping.format} to ${mapping.path}...`); + await exportDocs( + mapping.rootNoteId, + mapping.format, + mapping.path, + mapping.ignoredFiles + ); + } + } + } else { + // Legacy hardcoded build (for backward compatibility) + console.log("Building User Guide..."); + await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide"); + + console.log("Building Developer Guide..."); + await importAndExportDocs( + join(__dirname, DOCS_ROOT, "Developer Guide"), + "developer-guide" + ); + + // Copy favicon. + await fs.copyFile("../../apps/website/src/assets/favicon.ico", + join(OUTPUT_DIR, "favicon.ico")); + await fs.copyFile("../../apps/website/src/assets/favicon.ico", + join(OUTPUT_DIR, "user-guide", "favicon.ico")); + await fs.copyFile("../../apps/website/src/assets/favicon.ico", + join(OUTPUT_DIR, "developer-guide", "favicon.ico")); + } console.log("Documentation built successfully!"); } @@ -91,12 +196,13 @@ async function createImportZip(path: string) { zlib: { level: 0 } }); - console.log("Archive path is ", resolve(path)) + console.log("Archive path is ", resolve(path)); archive.directory(path, "/"); const outputStream = fsExtra.createWriteStream(inputFile); archive.pipe(outputStream); archive.finalize(); + const { waitForStreamToFinish } = await import("@triliumnext/server/src/services/utils.js"); await waitForStreamToFinish(outputStream); try { @@ -106,15 +212,15 @@ async function createImportZip(path: string) { } } -function waitForStreamToFinish(stream: WriteStream) { - return new Promise((res, rej) => { - stream.on("finish", () => res()); - stream.on("error", (err) => rej(err)); - }); -} -export async function extractZip(zipFilePath: string, outputPath: string, ignoredFiles?: Set) { - const { readZipFile, readContent } = (await import("@triliumnext/server/src/services/import/zip.js")); +export async function extractZip( + zipFilePath: string, + outputPath: string, + ignoredFiles?: Set +) { + const { readZipFile, readContent } = (await import( + "@triliumnext/server/src/services/import/zip.js" + )); await readZipFile(await fs.readFile(zipFilePath), async (zip, entry) => { // We ignore directories since they can appear out of order anyway. if (!entry.fileName.endsWith("/") && !ignoredFiles?.has(entry.fileName)) { @@ -129,6 +235,27 @@ export async function extractZip(zipFilePath: string, outputPath: string, ignore }); } +export async function buildDocsFromConfig(configPath?: string, gitRootDir?: string) { + const config = await loadConfig(configPath); + + if (gitRootDir) { + // Build the share theme if we have a gitRootDir (for Trilium project) + execSync(`pnpm run --filter share-theme build`, { + stdio: "inherit", + cwd: gitRootDir + }); + } + + // Trigger the actual build. + await new Promise((res, rej) => { + cls.init(() => { + buildDocsInner(config ?? undefined) + .catch(rej) + .then(res); + }); + }); +} + export default async function buildDocs({ gitRootDir }: BuildContext) { // Build the share theme. execSync(`pnpm run --filter share-theme build`, { diff --git a/apps/build-docs/src/cli.ts b/apps/build-docs/src/cli.ts new file mode 100644 index 0000000000..8aee089701 --- /dev/null +++ b/apps/build-docs/src/cli.ts @@ -0,0 +1,89 @@ +#!/usr/bin/env node + +import packageJson from "../package.json" with { type: "json" }; +import { buildDocsFromConfig } from "./build-docs.js"; + +// Parse command-line arguments +function parseArgs() { + const args = process.argv.slice(2); + let configPath: string | undefined; + let showHelp = false; + let showVersion = false; + + for (let i = 0; i < args.length; i++) { + if (args[i] === "--config" || args[i] === "-c") { + configPath = args[i + 1]; + if (!configPath) { + console.error("Error: --config/-c requires a path argument"); + process.exit(1); + } + i++; // Skip the next argument as it's the value + } else if (args[i] === "--help" || args[i] === "-h") { + showHelp = true; + } else if (args[i] === "--version" || args[i] === "-v") { + showVersion = true; + } + } + + return { configPath, showHelp, showVersion }; +} + +function getVersion(): string { + return packageJson.version; +} + +function printHelp() { + const version = getVersion(); + console.log(` +Usage: trilium-build-docs [options] + +Options: + -c, --config Path to the configuration file + (default: edit-docs-config.yaml in current directory) + -h, --help Display this help message + -v, --version Display version information + +Description: + Builds documentation from Trilium note structure and exports to various formats. + Configuration file should be in YAML format with the following structure: + + baseUrl: "https://example.com" + noteMappings: + - rootNoteId: "noteId123" + path: "docs" + format: "markdown" + - rootNoteId: "noteId456" + path: "public/docs" + format: "share" + exportOnly: true + +Version: ${version} +`); +} + +function printVersion() { + const version = getVersion(); + console.log(version); +} + +async function main() { + const { configPath, showHelp, showVersion } = parseArgs(); + + if (showHelp) { + printHelp(); + process.exit(0); + } else if (showVersion) { + printVersion(); + process.exit(0); + } + + try { + await buildDocsFromConfig(configPath); + process.exit(0); + } catch (error) { + console.error("Error building documentation:", error); + process.exit(1); + } +} + +main(); diff --git a/apps/build-docs/src/frontend_script_entrypoint.ts b/apps/build-docs/src/frontend_script_entrypoint.ts index 768774eca6..7aba11b2a4 100644 --- a/apps/build-docs/src/frontend_script_entrypoint.ts +++ b/apps/build-docs/src/frontend_script_entrypoint.ts @@ -13,16 +13,19 @@ * Make sure to keep in line with frontend's `script_context.ts`. */ -export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js"; export type { default as FAttachment } from "../../client/src/entities/fattachment.js"; export type { default as FAttribute } from "../../client/src/entities/fattribute.js"; export type { default as FBranch } from "../../client/src/entities/fbranch.js"; export type { default as FNote } from "../../client/src/entities/fnote.js"; export type { Api } from "../../client/src/services/frontend_script_api.js"; -export type { default as NoteContextAwareWidget } from "../../client/src/widgets/note_context_aware_widget.js"; +export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js"; +export type { + default as NoteContextAwareWidget +} from "../../client/src/widgets/note_context_aware_widget.js"; export type { default as RightPanelWidget } from "../../client/src/widgets/right_panel_widget.js"; import FrontendScriptApi, { type Api } from "../../client/src/services/frontend_script_api.js"; -//@ts-expect-error + +// @ts-expect-error - FrontendScriptApi is not directly exportable as Api without this simulation. export const api: Api = new FrontendScriptApi(); diff --git a/apps/build-docs/src/main.ts b/apps/build-docs/src/main.ts index d94ada167b..cca17125d8 100644 --- a/apps/build-docs/src/main.ts +++ b/apps/build-docs/src/main.ts @@ -1,9 +1,10 @@ -import { join } from "path"; -import BuildContext from "./context"; -import buildSwagger from "./swagger"; import { cpSync, existsSync, mkdirSync, rmSync } from "fs"; +import { join } from "path"; + import buildDocs from "./build-docs"; +import BuildContext from "./context"; import buildScriptApi from "./script-api"; +import buildSwagger from "./swagger"; const context: BuildContext = { gitRootDir: join(__dirname, "../../../"), diff --git a/apps/build-docs/src/script-api.ts b/apps/build-docs/src/script-api.ts index 8473ae3a02..2c62477474 100644 --- a/apps/build-docs/src/script-api.ts +++ b/apps/build-docs/src/script-api.ts @@ -1,7 +1,8 @@ import { execSync } from "child_process"; -import BuildContext from "./context"; import { join } from "path"; +import BuildContext from "./context"; + export default function buildScriptApi({ baseDir, gitRootDir }: BuildContext) { // Generate types execSync(`pnpm typecheck`, { stdio: "inherit", cwd: gitRootDir }); diff --git a/apps/build-docs/src/swagger.ts b/apps/build-docs/src/swagger.ts index b3677aeebe..2af458ec47 100644 --- a/apps/build-docs/src/swagger.ts +++ b/apps/build-docs/src/swagger.ts @@ -1,7 +1,8 @@ -import BuildContext from "./context"; -import { join } from "path"; import { execSync } from "child_process"; import { mkdirSync } from "fs"; +import { join } from "path"; + +import BuildContext from "./context"; interface BuildInfo { specPath: string; @@ -27,6 +28,9 @@ export default function buildSwagger({ baseDir, gitRootDir }: BuildContext) { const absSpecPath = join(gitRootDir, specPath); const targetDir = join(baseDir, outDir); mkdirSync(targetDir, { recursive: true }); - execSync(`pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`, { stdio: "inherit" }); + execSync( + `pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`, + { stdio: "inherit" } + ); } } diff --git a/apps/build-docs/tsconfig.json b/apps/build-docs/tsconfig.json index 858921cfb6..99c9b71b37 100644 --- a/apps/build-docs/tsconfig.json +++ b/apps/build-docs/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.base.json", - "include": [], + "include": [ + "scripts/**/*.ts" + ], "references": [ { "path": "../server" diff --git a/apps/build-docs/typedoc.backend.json b/apps/build-docs/typedoc.backend.json index 1781774c6f..a7f91c42e4 100644 --- a/apps/build-docs/typedoc.backend.json +++ b/apps/build-docs/typedoc.backend.json @@ -4,6 +4,7 @@ "entryPoints": [ "src/backend_script_entrypoint.ts" ], + "tsconfig": "tsconfig.app.json", "plugin": [ "typedoc-plugin-missing-exports" ] diff --git a/apps/build-docs/typedoc.frontend.json b/apps/build-docs/typedoc.frontend.json index f07d20dc71..c462004712 100644 --- a/apps/build-docs/typedoc.frontend.json +++ b/apps/build-docs/typedoc.frontend.json @@ -4,6 +4,7 @@ "entryPoints": [ "src/frontend_script_entrypoint.ts" ], + "tsconfig": "tsconfig.app.json", "plugin": [ "typedoc-plugin-missing-exports" ] diff --git a/apps/server/src/services/export/zip.ts b/apps/server/src/services/export/zip.ts index 4a9f140411..a6cd5b59c3 100644 --- a/apps/server/src/services/export/zip.ts +++ b/apps/server/src/services/export/zip.ts @@ -3,7 +3,7 @@ import dateUtils from "../date_utils.js"; import path from "path"; import packageInfo from "../../../package.json" with { type: "json" }; -import { getContentDisposition } from "../utils.js"; +import { getContentDisposition, waitForStreamToFinish } from "../utils.js"; import protectedSessionService from "../protected_session.js"; import sanitize from "sanitize-filename"; import fs from "fs"; @@ -468,6 +468,7 @@ async function exportToZip(taskContext: TaskContext<"export">, branch: BBranch, taskContext.taskSucceeded(null); } + async function exportToZipFile(noteId: string, format: ExportFormat, zipFilePath: string, zipExportOptions?: AdvancedExportOptions) { const fileOutputStream = fs.createWriteStream(zipFilePath); const taskContext = new TaskContext("no-progress-reporting", "export", null); @@ -479,6 +480,7 @@ async function exportToZipFile(noteId: string, format: ExportFormat, zipFilePath } await exportToZip(taskContext, note.getParentBranches()[0], format, fileOutputStream, false, zipExportOptions); + await waitForStreamToFinish(fileOutputStream); log.info(`Exported '${noteId}' with format '${format}' to '${zipFilePath}'`); } diff --git a/apps/server/src/services/utils.ts b/apps/server/src/services/utils.ts index a97b84a6c7..a2b707edf9 100644 --- a/apps/server/src/services/utils.ts +++ b/apps/server/src/services/utils.ts @@ -1,5 +1,4 @@ - import chardet from "chardet"; import crypto from "crypto"; import escape from "escape-html"; @@ -516,6 +515,13 @@ function slugify(text: string) { .replace(/(^-|-$)+/g, ""); // trim dashes } +export function waitForStreamToFinish(stream: any): Promise { + return new Promise((resolve, reject) => { + stream.on("finish", () => resolve()); + stream.on("error", (err) => reject(err)); + }); +} + export default { compareVersions, constantTimeCompare, @@ -556,5 +562,6 @@ export default { toBase64, toMap, toObject, - unescapeHtml + unescapeHtml, + waitForStreamToFinish }; diff --git a/flake.nix b/flake.nix index 23a7a38cf4..69a0482b8c 100644 --- a/flake.nix +++ b/flake.nix @@ -113,7 +113,7 @@ [ moreutils # sponge nodejs.python - removeReferencesTo + removeReferencesTo ] ++ lib.optionals (app == "desktop" || app == "edit-docs") [ copyDesktopItems @@ -126,7 +126,7 @@ which electron ] - ++ lib.optionals (app == "server") [ + ++ lib.optionals (app == "server" || app == "build-docs") [ makeBinaryWrapper ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ @@ -153,7 +153,7 @@ # This file is a symlink into /build which is not allowed. postFixup = '' - rm $out/opt/trilium*/node_modules/better-sqlite3/node_modules/.bin/prebuild-install || true + find $out/opt -name prebuild-install -path "*/better-sqlite3/node_modules/.bin/*" -delete || true ''; components = [ @@ -169,6 +169,7 @@ "packages/highlightjs" "packages/turndown-plugin-gfm" + "apps/build-docs" "apps/client" "apps/db-compare" "apps/desktop" @@ -277,11 +278,46 @@ ''; }; + build-docs = makeApp { + app = "build-docs"; + preBuildCommands = '' + pushd apps/server + pnpm rebuild || true + popd + ''; + buildTask = "client:build && pnpm run server:build && pnpm run --filter build-docs build"; + mainProgram = "trilium-build-docs"; + installCommands = '' + mkdir -p $out/{bin,opt/trilium-build-docs} + + # Copy build-docs dist + cp --archive apps/build-docs/dist/* $out/opt/trilium-build-docs + + # Copy server dist (needed for runtime) + mkdir -p $out/opt/trilium-build-docs/server + cp --archive apps/server/dist/* $out/opt/trilium-build-docs/server/ + + # Copy client dist (needed for runtime) + mkdir -p $out/opt/trilium-build-docs/client + cp --archive apps/client/dist/* $out/opt/trilium-build-docs/client/ + + # Copy share-theme (needed for exports) + mkdir -p $out/opt/trilium-build-docs/packages/share-theme + cp --archive packages/share-theme/dist/* $out/opt/trilium-build-docs/packages/share-theme/ + + # Create wrapper script + makeWrapper ${lib.getExe nodejs} $out/bin/trilium-build-docs \ + --add-flags $out/opt/trilium-build-docs/cli.cjs \ + --set TRILIUM_RESOURCE_DIR $out/opt/trilium-build-docs/server + ''; + }; + in { packages.desktop = desktop; packages.server = server; packages.edit-docs = edit-docs; + packages.build-docs = build-docs; packages.default = desktop; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3e48992b05..f584515033 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -164,6 +164,9 @@ importers: fs-extra: specifier: 11.3.3 version: 11.3.3 + js-yaml: + specifier: 4.1.1 + version: 4.1.1 react: specifier: 19.2.4 version: 19.2.4 @@ -16544,8 +16547,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.4.0 '@ckeditor/ckeditor5-utils': 47.4.0 ckeditor5: 47.4.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-markdown-gfm@47.4.0': dependencies: @@ -16954,6 +16955,7 @@ snapshots: ckeditor5: 47.4.0 transitivePeerDependencies: - bufferutil + - supports-color - utf-8-validate '@ckeditor/ckeditor5-utils@47.4.0':