From 8e47f333294730554d5a6c95b4a033d497937e6e Mon Sep 17 00:00:00 2001 From: Wael Nasreddine Date: Sat, 10 Jan 2026 11:44:54 -0800 Subject: [PATCH 1/4] Refactor edit-docs to use edit-docs-config.yaml This removes hardcoded configuration from edit-docs.ts and replaces it with dynamic loading from edit-docs-config.yaml. Changes: - Removed BASE_URL and NOTE_MAPPINGS constants - Removed DOCS_ROOT and USER_GUIDE_ROOT environment variable dependencies - Added js-yaml for YAML parsing - Config paths are resolved relative to repository root The tool now reads configuration from edit-docs-config.yaml, making it easier to customize without code changes. The pnpm script is simplified since it no longer needs to pass complex environment variables. --- apps/edit-docs/package.json | 2 +- apps/edit-docs/src/edit-docs.ts | 64 ++++++++++++++++----------------- edit-docs-config.yaml | 24 +++++++++++++ package.json | 2 ++ pnpm-lock.yaml | 43 ++++++++++------------ 5 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 edit-docs-config.yaml diff --git a/apps/edit-docs/package.json b/apps/edit-docs/package.json index 30df95734..d62727532 100644 --- a/apps/edit-docs/package.json +++ b/apps/edit-docs/package.json @@ -16,7 +16,7 @@ "fs-extra": "11.3.3" }, "scripts": { - "edit-docs": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-docs.ts", + "edit-docs": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store tsx ../../scripts/electron-start.mts src/edit-docs.ts", "edit-demo": "cross-env TRILIUM_PORT=37744 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-demo.ts" } } \ No newline at end of file diff --git a/apps/edit-docs/src/edit-docs.ts b/apps/edit-docs/src/edit-docs.ts index 762dacc5b..86c56ed27 100644 --- a/apps/edit-docs/src/edit-docs.ts +++ b/apps/edit-docs/src/edit-docs.ts @@ -1,14 +1,16 @@ -import fs from "fs/promises"; -import fsExtra from "fs-extra"; -import path from "path"; -import type { NoteMetaFile } from "@triliumnext/server/src/services/meta/note_meta.js"; -import { initializeTranslations } from "@triliumnext/server/src/services/i18n.js"; import debounce from "@triliumnext/client/src/services/debounce.js"; -import { extractZip, importData, initializeDatabase, startElectron } from "./utils.js"; import cls from "@triliumnext/server/src/services/cls.js"; import type { AdvancedExportOptions, ExportFormat } from "@triliumnext/server/src/services/export/zip/abstract_provider.js"; +import { initializeTranslations } from "@triliumnext/server/src/services/i18n.js"; import { parseNoteMetaFile } from "@triliumnext/server/src/services/in_app_help.js"; +import type { NoteMetaFile } from "@triliumnext/server/src/services/meta/note_meta.js"; import type NoteMeta from "@triliumnext/server/src/services/meta/note_meta.js"; +import fs from "fs/promises"; +import fsExtra from "fs-extra"; +import yaml from "js-yaml"; +import path from "path"; + +import { extractZip, importData, initializeDatabase, startElectron } from "./utils.js"; interface NoteMapping { rootNoteId: string; @@ -18,39 +20,33 @@ interface NoteMapping { exportOnly?: boolean; } -const { DOCS_ROOT, USER_GUIDE_ROOT } = process.env; -if (!DOCS_ROOT || !USER_GUIDE_ROOT) { - throw new Error("Missing DOCS_ROOT or USER_GUIDE_ROOT environment variable."); +interface Config { + baseUrl: string; + noteMappings: NoteMapping[]; } -const BASE_URL = "https://docs.triliumnotes.org"; +// Configuration variables +let BASE_URL: string; +let NOTE_MAPPINGS: NoteMapping[]; + +// Load configuration from edit-docs-config.yaml +async function loadConfig() { + const CONFIG_PATH = path.join(__dirname, "../../../edit-docs-config.yaml"); + const configContent = await fs.readFile(CONFIG_PATH, "utf-8"); + const config = yaml.load(configContent) as Config; + + BASE_URL = config.baseUrl; + // Resolve all paths relative to the repository root + const REPO_ROOT = path.join(__dirname, "../../.."); + NOTE_MAPPINGS = config.noteMappings.map((mapping) => ({ + ...mapping, + path: path.join(REPO_ROOT, mapping.path) + })); +} -const NOTE_MAPPINGS: NoteMapping[] = [ - { - rootNoteId: "pOsGYCXsbNQG", - path: path.join(__dirname, DOCS_ROOT, "User Guide"), - format: "markdown" - }, - { - rootNoteId: "pOsGYCXsbNQG", - path: path.join(__dirname, USER_GUIDE_ROOT), - format: "html", - ignoredFiles: ["index.html", "navigation.html", "style.css", "User Guide.html"], - exportOnly: true - }, - { - rootNoteId: "jdjRLhLV3TtI", - path: path.join(__dirname, DOCS_ROOT, "Developer Guide"), - format: "markdown" - }, - { - rootNoteId: "hD3V4hiu2VW4", - path: path.join(__dirname, DOCS_ROOT, "Release Notes"), - format: "markdown" - } -]; async function main() { + await loadConfig(); const initializedPromise = startElectron(() => { // Wait for the import to be finished and the application to be loaded before we listen to changes. setTimeout(() => registerHandlers(), 10_000); diff --git a/edit-docs-config.yaml b/edit-docs-config.yaml new file mode 100644 index 000000000..728523c5c --- /dev/null +++ b/edit-docs-config.yaml @@ -0,0 +1,24 @@ +baseUrl: "https://docs.triliumnotes.org" + +noteMappings: + - rootNoteId: "pOsGYCXsbNQG" + path: "docs/User Guide" + format: "markdown" + + - rootNoteId: "pOsGYCXsbNQG" + path: "apps/server/src/assets/doc_notes/en/User Guide" + format: "html" + ignoredFiles: + - "index.html" + - "navigation.html" + - "style.css" + - "User Guide.html" + exportOnly: true + + - rootNoteId: "jdjRLhLV3TtI" + path: "docs/Developer Guide" + format: "markdown" + + - rootNoteId: "hD3V4hiu2VW4" + path: "docs/Release Notes" + format: "markdown" diff --git a/package.json b/package.json index 251595a85..95b5c1345 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@playwright/test": "1.57.0", "@triliumnext/server": "workspace:*", "@types/express": "5.0.6", + "@types/js-yaml": "4.0.9", "@types/node": "24.10.7", "@vitest/browser-webdriverio": "4.0.16", "@vitest/coverage-v8": "4.0.16", @@ -64,6 +65,7 @@ "happy-dom": "~20.1.0", "http-server": "14.1.1", "jiti": "2.6.1", + "js-yaml": "4.1.1", "jsonc-eslint-parser": "2.4.2", "react-refresh": "0.18.0", "rollup-plugin-webpack-stats": "2.1.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 30b925c5b..7ca1bdb55 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,6 +49,9 @@ importers: '@types/express': specifier: 5.0.6 version: 5.0.6 + '@types/js-yaml': + specifier: 4.0.9 + version: 4.0.9 '@types/node': specifier: 24.10.7 version: 24.10.7 @@ -97,6 +100,9 @@ importers: jiti: specifier: 2.6.1 version: 2.6.1 + js-yaml: + specifier: 4.1.1 + version: 4.1.1 jsonc-eslint-parser: specifier: 2.4.2 version: 2.4.2 @@ -5376,6 +5382,9 @@ packages: '@types/jquery@3.5.33': resolution: {integrity: sha512-SeyVJXlCZpEki5F0ghuYe+L+PprQta6nRZqhONt9F13dWBtR/ftoaIbdRQ7cis7womE+X2LKhsDdDtkkDhJS6g==} + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -15022,6 +15031,8 @@ snapshots: '@ckeditor/ckeditor5-core': 47.3.0 '@ckeditor/ckeditor5-upload': 47.3.0 ckeditor5: 47.3.0 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-ai@47.3.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)': dependencies: @@ -15160,6 +15171,8 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.3.0 '@ckeditor/ckeditor5-widget': 47.3.0 es-toolkit: 1.39.5 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-cloud-services@47.3.0': dependencies: @@ -15360,6 +15373,8 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 es-toolkit: 1.39.5 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-editor-classic@47.3.0': dependencies: @@ -15369,6 +15384,8 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 es-toolkit: 1.39.5 + transitivePeerDependencies: + - supports-color '@ckeditor/ckeditor5-editor-decoupled@47.3.0': dependencies: @@ -15612,8 +15629,6 @@ snapshots: '@ckeditor/ckeditor5-widget': 47.3.0 ckeditor5: 47.3.0 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-import-word@47.3.0': dependencies: @@ -15639,8 +15654,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.3.0 '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-inspector@5.0.0': {} @@ -15650,8 +15663,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.3.0 '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-line-height@47.3.0': dependencies: @@ -15676,8 +15687,6 @@ snapshots: '@ckeditor/ckeditor5-widget': 47.3.0 ckeditor5: 47.3.0 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-list-multi-level@47.3.0': dependencies: @@ -15701,8 +15710,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.3.0 '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-markdown-gfm@47.3.0': dependencies: @@ -15831,8 +15838,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.3.0 '@ckeditor/ckeditor5-widget': 47.3.0 ckeditor5: 47.3.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-pagination@47.3.0': dependencies: @@ -15940,8 +15945,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.3.0 '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-slash-command@47.3.0': dependencies: @@ -15954,8 +15957,6 @@ snapshots: '@ckeditor/ckeditor5-ui': 47.3.0 '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-source-editing-enhanced@47.3.0': dependencies: @@ -16003,8 +16004,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-table@47.3.0': dependencies: @@ -16129,8 +16128,6 @@ snapshots: '@ckeditor/ckeditor5-engine': 47.3.0 '@ckeditor/ckeditor5-utils': 47.3.0 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@ckeditor/ckeditor5-widget@47.3.0': dependencies: @@ -16150,8 +16147,6 @@ snapshots: '@ckeditor/ckeditor5-utils': 47.3.0 ckeditor5: 47.3.0 es-toolkit: 1.39.5 - transitivePeerDependencies: - - supports-color '@codemirror/autocomplete@6.18.6': dependencies: @@ -20005,6 +20000,8 @@ snapshots: dependencies: '@types/sizzle': 2.3.9 + '@types/js-yaml@4.0.9': {} + '@types/json-schema@7.0.15': {} '@types/jsonfile@6.1.4': @@ -21675,8 +21672,6 @@ snapshots: ckeditor5-collaboration@47.3.0: dependencies: '@ckeditor/ckeditor5-collaboration-core': 47.3.0 - transitivePeerDependencies: - - supports-color ckeditor5-premium-features@47.3.0(bufferutil@4.0.9)(ckeditor5@47.3.0)(utf-8-validate@6.0.5): dependencies: From 015e41e79235b5db1ae817d6ce675555320ac5cd Mon Sep 17 00:00:00 2001 From: Wael Nasreddine Date: Sun, 11 Jan 2026 14:10:19 -0800 Subject: [PATCH 2/4] fix(edit-docs): Minify meta for format==share --- apps/edit-docs/src/edit-docs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/edit-docs/src/edit-docs.ts b/apps/edit-docs/src/edit-docs.ts index 86c56ed27..baf56c6f6 100644 --- a/apps/edit-docs/src/edit-docs.ts +++ b/apps/edit-docs/src/edit-docs.ts @@ -138,7 +138,7 @@ async function exportData(noteId: string, format: ExportFormat, outputPath: stri } } - const minifyMeta = (format === "html"); + const minifyMeta = (format === "html" || format === "share"); await cleanUpMeta(outputPath, minifyMeta); } From fb4d63b049216784dfefec64430e4f577fd04ebe Mon Sep 17 00:00:00 2001 From: Wael Nasreddine Date: Sat, 10 Jan 2026 12:09:18 -0800 Subject: [PATCH 3/4] Add --config, --help, and --version flags to edit-docs - Implement --config (-c) flag to allow custom configuration file paths. - Add --help (-h) flag to display tool usage and available options. - Add --version (-v) flag to display the current Trilium version. - Update electron-start.mts to correctly pass command-line arguments to Electron. - Synchronize edit-docs version with the root package.json via update-version.ts. - Resolve config paths relative to the configuration file's directory. This makes edit-docs more robust and easier to use from external projects and immutable environments like Nix. --- apps/edit-docs/package.json | 2 +- apps/edit-docs/src/edit-docs.ts | 69 ++++++++++++++++++++++++++++++--- scripts/electron-start.mts | 3 +- scripts/update-version.ts | 2 +- 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/apps/edit-docs/package.json b/apps/edit-docs/package.json index d62727532..31d7e51ec 100644 --- a/apps/edit-docs/package.json +++ b/apps/edit-docs/package.json @@ -1,6 +1,6 @@ { "name": "@triliumnext/edit-docs", - "version": "0.0.1", + "version": "0.101.3", "private": true, "description": "Desktop version of Trilium which imports the demo database (presented to new users at start-up) or the user guide and other documentation and saves the modifications for committing.", "dependencies": { diff --git a/apps/edit-docs/src/edit-docs.ts b/apps/edit-docs/src/edit-docs.ts index baf56c6f6..c15a2f086 100644 --- a/apps/edit-docs/src/edit-docs.ts +++ b/apps/edit-docs/src/edit-docs.ts @@ -10,6 +10,7 @@ import fsExtra from "fs-extra"; import yaml from "js-yaml"; import path from "path"; +import packageJson from "../package.json" with { type: "json" }; import { extractZip, importData, initializeDatabase, startElectron } from "./utils.js"; interface NoteMapping { @@ -25,26 +26,82 @@ interface Config { noteMappings: NoteMapping[]; } -// Configuration variables +// 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]; + 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-edit-docs [options] + +Options: + -c, --config Path to the configuration file (default: edit-docs-config.yaml in the root) + -h, --help Display this help message + -v, --version Display version information + +Version: ${version} +`); +} + +function printVersion() { + const version = getVersion(); + console.log(version); +} + +const { configPath, showHelp, showVersion } = parseArgs(); + +if (showHelp) { + printHelp(); + process.exit(0); +} else if (showVersion) { + printVersion(); + process.exit(0); +} + +// Configuration variables to be initialized let BASE_URL: string; let NOTE_MAPPINGS: NoteMapping[]; // Load configuration from edit-docs-config.yaml async function loadConfig() { - const CONFIG_PATH = path.join(__dirname, "../../../edit-docs-config.yaml"); + const CONFIG_PATH = configPath + ? path.resolve(configPath) + : path.join(__dirname, "../../../edit-docs-config.yaml"); + const configContent = await fs.readFile(CONFIG_PATH, "utf-8"); const config = yaml.load(configContent) as Config; BASE_URL = config.baseUrl; - // Resolve all paths relative to the repository root - const REPO_ROOT = path.join(__dirname, "../../.."); + // Resolve all paths relative to the config file's directory (for flexibility with external configs) + const CONFIG_DIR = path.dirname(CONFIG_PATH); NOTE_MAPPINGS = config.noteMappings.map((mapping) => ({ ...mapping, - path: path.join(REPO_ROOT, mapping.path) + path: path.resolve(CONFIG_DIR, mapping.path) })); } - async function main() { await loadConfig(); const initializedPromise = startElectron(() => { diff --git a/scripts/electron-start.mts b/scripts/electron-start.mts index e1ed9df7e..05277820a 100644 --- a/scripts/electron-start.mts +++ b/scripts/electron-start.mts @@ -3,7 +3,8 @@ import { getElectronPath, isNixOS } from "./utils.mjs"; const LD_LIBRARY_PATH = isNixOS() && execSync("nix eval --raw nixpkgs#gcc.cc.lib").toString("utf-8") + "/lib"; -execSync(`${getElectronPath()} ${process.argv[2]} --no-sandbox`, { +const args = process.argv.slice(2); +execSync(`${getElectronPath()} ${args.join(" ")} --no-sandbox`, { stdio: "inherit", env: { ...process.env, diff --git a/scripts/update-version.ts b/scripts/update-version.ts index fd00ff35d..d9e52abe4 100644 --- a/scripts/update-version.ts +++ b/scripts/update-version.ts @@ -26,7 +26,7 @@ function getVersion(packageJsonPath: string) { function main() { const version = getVersion(join(__dirname, "..", "package.json")); - for (const appName of ["server", "client", "desktop"]) { + for (const appName of ["server", "client", "desktop", "edit-docs"]) { patchPackageJson(join(__dirname, "..", "apps", appName, "package.json"), version); } From 0273c64bbfd2dd1d0f72732d79a2546d2f156031 Mon Sep 17 00:00:00 2001 From: Wael Nasreddine Date: Sat, 10 Jan 2026 12:04:22 -0800 Subject: [PATCH 4/4] Build edit-docs as standalone package using makeApp Changed edit-docs from a simple wrapper script to a properly built Nix package using makeApp, similar to how desktop and server are built. Changes: - Added build script to apps/edit-docs/package.json - Created apps/edit-docs/scripts/build.ts based on desktop's build script - Added edit-docs:build task to root package.json - Changed flake.nix to use makeApp which: - Builds edit-docs with all dependencies bundled - Creates a standalone trilium-edit-docs executable - Can be installed with 'nix profile install' and run from any directory This makes edit-docs truly reusable - it can now be installed and run from any project without requiring the Trilium source tree. --- README.md | 11 +++++ apps/edit-docs/package.json | 2 + apps/edit-docs/scripts/build.ts | 40 ++++++++++++++++ .../spec/build-checks/artifacts.spec.ts | 48 +++++++++++++++++++ apps/edit-docs/src/edit-docs.ts | 23 +++++++-- apps/edit-docs/src/utils.ts | 32 +++++++------ apps/edit-docs/vitest.build.config.mts | 17 +++++++ flake.nix | 25 +++++++++- package.json | 3 +- 9 files changed, 181 insertions(+), 20 deletions(-) create mode 100644 apps/edit-docs/scripts/build.ts create mode 100644 apps/edit-docs/spec/build-checks/artifacts.spec.ts create mode 100644 apps/edit-docs/vitest.build.config.mts diff --git a/README.md b/README.md index 34664689b..0fc8e562b 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,17 @@ pnpm install pnpm edit-docs:edit-docs ``` +Alternatively, if you have Nix installed: +```shell +# Run directly +nix run .#edit-docs + +# Or install to your profile +nix profile install .#edit-docs +trilium-edit-docs +``` + + ### Building the Executable Download the repository, install dependencies using `pnpm` and then build the desktop app for Windows: ```shell diff --git a/apps/edit-docs/package.json b/apps/edit-docs/package.json index 31d7e51ec..2282522f7 100644 --- a/apps/edit-docs/package.json +++ b/apps/edit-docs/package.json @@ -16,6 +16,8 @@ "fs-extra": "11.3.3" }, "scripts": { + "build": "tsx scripts/build.ts", + "test-build": "vitest --config vitest.build.config.mts", "edit-docs": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store tsx ../../scripts/electron-start.mts src/edit-docs.ts", "edit-demo": "cross-env TRILIUM_PORT=37744 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-demo.ts" } diff --git a/apps/edit-docs/scripts/build.ts b/apps/edit-docs/scripts/build.ts new file mode 100644 index 000000000..251d96f7b --- /dev/null +++ b/apps/edit-docs/scripts/build.ts @@ -0,0 +1,40 @@ +import { writeFileSync } from "fs"; +import { join } from "path"; + +import BuildHelper from "../../../scripts/build-utils"; +import originalPackageJson from "../package.json" with { type: "json" }; + +const build = new BuildHelper("apps/edit-docs"); + +async function main() { + await build.buildBackend(["src/edit-docs.ts", "src/utils.ts"]); + + // Copy assets from server (needed for DB initialization) + build.copy("/apps/server/src/assets", "assets/"); + build.triggerBuildAndCopyTo("packages/share-theme", "share-theme/assets/"); + build.copy("/packages/share-theme/src/templates", "share-theme/templates/"); + build.copy("/node_modules/ckeditor5/dist/ckeditor5-content.css", "ckeditor5-content.css"); + build.buildFrontend(); + + // Copy node modules dependencies + build.copyNodeModules(["better-sqlite3", "bindings", "file-uri-to-path", "@electron/remote"]); + + generatePackageJson(); +} + +function generatePackageJson() { + const { version, author, license, description, dependencies, devDependencies } = originalPackageJson; + const packageJson = { + name: "trilium-edit-docs", + main: "edit-docs.cjs", + version, + author, + license, + description, + dependencies: {"better-sqlite3": dependencies["better-sqlite3"]}, + devDependencies: {electron: devDependencies.electron}, + }; + writeFileSync(join(build.outDir, "package.json"), JSON.stringify(packageJson, null, "\t"), "utf-8"); +} + +main(); diff --git a/apps/edit-docs/spec/build-checks/artifacts.spec.ts b/apps/edit-docs/spec/build-checks/artifacts.spec.ts new file mode 100644 index 000000000..ae2e17196 --- /dev/null +++ b/apps/edit-docs/spec/build-checks/artifacts.spec.ts @@ -0,0 +1,48 @@ +import { globSync } from "fs"; +import { join } from "path"; +import { it, describe, expect } from "vitest"; + +describe("Check artifacts are present", () => { + const distPath = join(__dirname, "../../dist"); + + it("has the necessary node modules", async () => { + const paths = [ + "node_modules/better-sqlite3", + "node_modules/bindings", + "node_modules/file-uri-to-path", + "node_modules/@electron/remote" + ]; + + ensurePathsExist(paths); + }); + + it("includes the client", async () => { + const paths = [ + "public/assets", + "public/fonts", + "public/node_modules", + "public/src", + "public/stylesheets", + "public/translations" + ]; + + ensurePathsExist(paths); + }); + + it("includes necessary assets", async () => { + const paths = [ + "assets", + "share-theme", + "ckeditor5-content.css" + ]; + + ensurePathsExist(paths); + }); + + function ensurePathsExist(paths: string[]) { + for (const path of paths) { + const result = globSync(join(distPath, path, "**")); + expect(result, path).not.toHaveLength(0); + } + } +}); diff --git a/apps/edit-docs/src/edit-docs.ts b/apps/edit-docs/src/edit-docs.ts index c15a2f086..8cb6b898d 100644 --- a/apps/edit-docs/src/edit-docs.ts +++ b/apps/edit-docs/src/edit-docs.ts @@ -36,6 +36,10 @@ function parseArgs() { 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; @@ -86,9 +90,15 @@ let NOTE_MAPPINGS: NoteMapping[]; // Load configuration from edit-docs-config.yaml async function loadConfig() { - const CONFIG_PATH = configPath + let CONFIG_PATH = configPath ? path.resolve(configPath) - : path.join(__dirname, "../../../edit-docs-config.yaml"); + : path.join(process.cwd(), "edit-docs-config.yaml"); + + const exists = await fs.access(CONFIG_PATH).then(() => true).catch(() => false); + if (!exists && !configPath) { + // Fallback to project root if running from within a subproject + CONFIG_PATH = path.join(__dirname, "../../../edit-docs-config.yaml"); + } const configContent = await fs.readFile(CONFIG_PATH, "utf-8"); const config = yaml.load(configContent) as Config; @@ -106,12 +116,18 @@ async function main() { await loadConfig(); const initializedPromise = startElectron(() => { // Wait for the import to be finished and the application to be loaded before we listen to changes. - setTimeout(() => registerHandlers(), 10_000); + setTimeout(() => { + registerHandlers(); + }, 10_000); }); await initializeTranslations(); await initializeDatabase(true); + // Wait for becca to be loaded before importing data + const beccaLoader = await import("@triliumnext/server/src/becca/becca_loader.js"); + await beccaLoader.beccaLoaded; + cls.init(async () => { for (const mapping of NOTE_MAPPINGS) { if (!mapping.exportOnly) { @@ -248,7 +264,6 @@ async function registerHandlers() { return; } - console.log("Got entity changed", e.entityName, e.entity.title); debouncer(); }); } diff --git a/apps/edit-docs/src/utils.ts b/apps/edit-docs/src/utils.ts index 84e62ba39..3b41a70fd 100644 --- a/apps/edit-docs/src/utils.ts +++ b/apps/edit-docs/src/utils.ts @@ -7,18 +7,21 @@ import type { WriteStream } from "fs"; import fs from "fs/promises"; import fsExtra from "fs-extra"; import path from "path"; -import { resolve } from "path"; -import { deferred, DeferredPromise } from "../../../packages/commons/src"; +import { deferred, type DeferredPromise } from "../../../packages/commons/src/index.js"; -export function initializeDatabase(skipDemoDb: boolean) { - return new Promise(async (resolve) => { - const sqlInit = (await import("@triliumnext/server/src/services/sql_init.js")).default; - cls.init(async () => { - if (!sqlInit.isDbInitialized()) { - await sqlInit.createInitialDatabase(skipDemoDb); - } - resolve(); +export function initializeDatabase(skipDemoDb: boolean): Promise { + return new Promise((resolve) => { + import("@triliumnext/server/src/services/sql_init.js").then((m) => { + const sqlInit = m.default; + cls.init(async () => { + if (!sqlInit.isDbInitialized()) { + sqlInit.createInitialDatabase(skipDemoDb).then(() => resolve()); + } else { + sqlInit.dbReady.resolve(); + resolve(); + } + }); }); }); } @@ -78,7 +81,6 @@ async function createImportZip(path: string) { zlib: { level: 0 } }); - console.log("Archive path is ", resolve(path)); archive.directory(path, "/"); const outputStream = fsExtra.createWriteStream(inputFile); @@ -93,9 +95,11 @@ async function createImportZip(path: string) { } function waitForEnd(archive: Archiver, stream: WriteStream) { - return new Promise(async (res, rej) => { - stream.on("finish", () => res()); - await archive.finalize(); + return new Promise((res, rej) => { + stream.on("finish", res); + stream.on("error", rej); + archive.on("error", rej); + archive.finalize().catch(rej); }); } diff --git a/apps/edit-docs/vitest.build.config.mts b/apps/edit-docs/vitest.build.config.mts new file mode 100644 index 000000000..9dff36fc0 --- /dev/null +++ b/apps/edit-docs/vitest.build.config.mts @@ -0,0 +1,17 @@ +/// +import { defineConfig } from 'vite'; + +export default defineConfig(() => ({ + root: __dirname, + cacheDir: '../../node_modules/.vite/apps/edit-docs', + plugins: [], + test: { + watch: false, + globals: true, + environment: "node", + include: ['spec/build-checks/**'], + reporters: [ + "verbose" + ] + }, +})); diff --git a/flake.nix b/flake.nix index 72cc8946b..ed1548b9e 100644 --- a/flake.nix +++ b/flake.nix @@ -112,7 +112,7 @@ nodejs.python removeReferencesTo ] - ++ lib.optionals (app == "desktop") [ + ++ lib.optionals (app == "desktop" || app == "edit-docs") [ copyDesktopItems # required for NIXOS_OZONE_WL expansion # https://github.com/NixOS/nixpkgs/issues/172583 @@ -252,10 +252,33 @@ --add-flags $out/opt/trilium-server/main.cjs ''; }; + + edit-docs = makeApp { + app = "edit-docs"; + preBuildCommands = '' + export npm_config_nodedir=${electron.headers} + pnpm postinstall + ''; + buildTask = "edit-docs:build"; + mainProgram = "trilium-edit-docs"; + installCommands = '' + #remove-references-to -t ${electron.headers} apps/edit-docs/dist/node_modules/better-sqlite3/build/config.gypi + #remove-references-to -t ${nodejs.python} apps/edit-docs/dist/node_modules/better-sqlite3/build/config.gypi + + mkdir -p $out/{bin,opt/trilium-edit-docs} + cp --archive apps/edit-docs/dist/* $out/opt/trilium-edit-docs + makeShellWrapper ${lib.getExe electron} $out/bin/trilium-edit-docs \ + --set-default ELECTRON_IS_DEV 0 \ + --set TRILIUM_RESOURCE_DIR $out/opt/trilium-edit-docs \ + --add-flags $out/opt/trilium-edit-docs/edit-docs.cjs + ''; + }; + in { packages.desktop = desktop; packages.server = server; + packages.edit-docs = edit-docs; packages.default = desktop; diff --git a/package.json b/package.json index 95b5c1345..a6cc47c5f 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ "desktop:start": "pnpm run --filter desktop dev", "desktop:build": "pnpm run --filter desktop build", "desktop:start-prod": "pnpm run --filter desktop start-prod", + "edit-docs:edit-docs": "pnpm run --filter edit-docs edit-docs", + "edit-docs:build": "pnpm run --filter edit-docs build", "website:start": "pnpm run --filter website dev", "website:build": "pnpm run --filter website build", "electron:build": "pnpm desktop:build", @@ -28,7 +30,6 @@ "chore:update-version": "tsx ./scripts/update-version.ts", "docs:build": "pnpm run --filter build-docs start", "docs:preview": "pnpm http-server site -p 9000", - "edit-docs:edit-docs": "pnpm run --filter edit-docs edit-docs", "edit-docs:edit-demo": "pnpm run --filter edit-docs edit-demo", "test:all": "pnpm test:parallel && pnpm test:sequential", "test:parallel": "pnpm --filter=!server --filter=!ckeditor5-mermaid --filter=!ckeditor5-math --parallel test",