diff --git a/src/constants/paths.ts b/src/constants/paths.ts index 8636355c..27894c2e 100644 --- a/src/constants/paths.ts +++ b/src/constants/paths.ts @@ -52,6 +52,11 @@ export const PACKAGE_PATH_BASE = isPackaged // Package-specific paths export const ZX_FOLDER = path.resolve(PACKAGE_PATH_BASE, 'zx', 'build', 'cli.js'); export const TIDDLYWIKI_PACKAGE_FOLDER = path.resolve(PACKAGE_PATH_BASE, 'tiddlywiki', 'boot'); +/** + * Path to TidGi's built-in TiddlyWiki plugins (compiled by scripts/compilePlugins.mjs). + * When wiki uses a local TiddlyWiki installation, we still need to load TidGi's custom plugins from here. + */ +export const TIDDLYWIKI_BUILT_IN_PLUGINS_PATH = path.resolve(PACKAGE_PATH_BASE, 'tiddlywiki', 'plugins'); export const SQLITE_BINARY_PATH = path.resolve(PACKAGE_PATH_BASE, 'better-sqlite3', 'build', 'Release', 'better_sqlite3.node'); /** diff --git a/src/services/wiki/index.ts b/src/services/wiki/index.ts index 1572276b..d54b0bc2 100644 --- a/src/services/wiki/index.ts +++ b/src/services/wiki/index.ts @@ -13,7 +13,7 @@ import WikiWorkerFactory from './wikiWorker/index?nodeWorker'; import { container } from '@services/container'; import { WikiChannel } from '@/constants/channels'; -import { getTiddlyWikiBootPath, TIDDLERS_PATH, TIDDLYWIKI_TEMPLATE_FOLDER_PATH } from '@/constants/paths'; +import { getTiddlyWikiBootPath, TIDDLERS_PATH, TIDDLYWIKI_BUILT_IN_PLUGINS_PATH, TIDDLYWIKI_TEMPLATE_FOLDER_PATH } from '@/constants/paths'; import type { IAuthenticationService } from '@services/auth/interface'; import type { IGitService, IGitUserInfos } from '@services/git/interface'; import { i18n } from '@services/libs/i18n'; @@ -140,7 +140,7 @@ export class Wiki implements IWikiService { const workerData: IStartNodeJSWikiConfigs = { authToken, - constants: { TIDDLYWIKI_PACKAGE_FOLDER: getTiddlyWikiBootPath(wikiFolderLocation) }, + constants: { TIDDLY_WIKI_BOOT_PATH: getTiddlyWikiBootPath(wikiFolderLocation), TIDDLYWIKI_BUILT_IN_PLUGINS_PATH }, enableHTTPAPI, excludedPlugins, homePath: wikiFolderLocation, @@ -368,7 +368,7 @@ export class Wiki implements IWikiService { if (await exists(saveWikiFolderPath)) { throw new AlreadyExistError(saveWikiFolderPath); } - await worker.extractWikiHTML(htmlWikiPath, saveWikiFolderPath, { TIDDLYWIKI_PACKAGE_FOLDER: getTiddlyWikiBootPath(saveWikiFolderPath) }); + await worker.extractWikiHTML(htmlWikiPath, saveWikiFolderPath, { TIDDLY_WIKI_BOOT_PATH: getTiddlyWikiBootPath(saveWikiFolderPath) }); } catch (error) { const result = `${(error as Error).name} ${(error as Error).message}`; logger.error(result, { worker: 'NodeJSWiki', method: 'extractWikiHTML', htmlWikiPath, saveWikiFolderPath }); @@ -385,7 +385,7 @@ export class Wiki implements IWikiService { const worker = createWorkerProxy(nativeWorker); try { - await worker.packetHTMLFromWikiFolder(wikiFolderLocation, pathOfNewHTML, { TIDDLYWIKI_PACKAGE_FOLDER: getTiddlyWikiBootPath(wikiFolderLocation) }); + await worker.packetHTMLFromWikiFolder(wikiFolderLocation, pathOfNewHTML, { TIDDLY_WIKI_BOOT_PATH: getTiddlyWikiBootPath(wikiFolderLocation) }); } finally { // this worker is only for one time use. we will spawn a new one for starting wiki later. await terminateWorker(nativeWorker); diff --git a/src/services/wiki/wikiWorker/htmlWiki.ts b/src/services/wiki/wikiWorker/htmlWiki.ts index 75533692..ea28b203 100644 --- a/src/services/wiki/wikiWorker/htmlWiki.ts +++ b/src/services/wiki/wikiWorker/htmlWiki.ts @@ -2,11 +2,11 @@ import { isHtmlWiki } from '@/constants/fileNames'; import { remove } from 'fs-extra'; import { TiddlyWiki } from 'tiddlywiki'; -export async function extractWikiHTML(htmlWikiPath: string, saveWikiFolderPath: string, constants: { TIDDLYWIKI_PACKAGE_FOLDER: string }): Promise { +export async function extractWikiHTML(htmlWikiPath: string, saveWikiFolderPath: string, constants: { TIDDLY_WIKI_BOOT_PATH: string }): Promise { // tiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder // --savewikifolder [] // . /mywikifolder is the path where the tiddlder and plugins folders are stored - const { TIDDLYWIKI_PACKAGE_FOLDER } = constants; + const { TIDDLY_WIKI_BOOT_PATH } = constants; try { const wikiInstance = TiddlyWiki(); wikiInstance.boot.argv = ['--load', htmlWikiPath, '--savewikifolder', saveWikiFolderPath, 'explodePlugins=no']; @@ -14,7 +14,7 @@ export async function extractWikiHTML(htmlWikiPath: string, saveWikiFolderPath: try { wikiInstance.boot.startup({ // passing bootPath inside TidGi app. fix The "path" argument must be of type string. Received undefined - bootPath: TIDDLYWIKI_PACKAGE_FOLDER, + bootPath: TIDDLY_WIKI_BOOT_PATH, callback: () => { resolve(); }, @@ -32,10 +32,10 @@ export async function extractWikiHTML(htmlWikiPath: string, saveWikiFolderPath: } } -export async function packetHTMLFromWikiFolder(folderWikiPath: string, pathOfNewHTML: string, constants: { TIDDLYWIKI_PACKAGE_FOLDER: string }): Promise { +export async function packetHTMLFromWikiFolder(folderWikiPath: string, pathOfNewHTML: string, constants: { TIDDLY_WIKI_BOOT_PATH: string }): Promise { // tiddlywiki ./mywikifolder --rendertiddler '$:/core/save/all' mywiki.html text/plain // . /mywikifolder is the path to the wiki folder, which generally contains the tiddlder and plugins directories - const { TIDDLYWIKI_PACKAGE_FOLDER } = constants; + const { TIDDLY_WIKI_BOOT_PATH } = constants; const wikiInstance = TiddlyWiki(); // a .html file path should be provided, but if provided a folder path, we can add /index.html to fix it. wikiInstance.boot.argv = [folderWikiPath, '--rendertiddler', '$:/core/save/all', isHtmlWiki(pathOfNewHTML) ? pathOfNewHTML : `${pathOfNewHTML}/index.html`, 'text/plain']; @@ -43,7 +43,7 @@ export async function packetHTMLFromWikiFolder(folderWikiPath: string, pathOfNew try { wikiInstance.boot.startup({ // passing bootPath inside TidGi app. fix The "path" argument must be of type string. Received undefined - bootPath: TIDDLYWIKI_PACKAGE_FOLDER, + bootPath: TIDDLY_WIKI_BOOT_PATH, callback: () => { resolve(); }, diff --git a/src/services/wiki/wikiWorker/index.ts b/src/services/wiki/wikiWorker/index.ts index e0b5af7c..43e274b9 100644 --- a/src/services/wiki/wikiWorker/index.ts +++ b/src/services/wiki/wikiWorker/index.ts @@ -25,7 +25,7 @@ import { startNodeJSWiki } from './startNodeJSWiki'; export interface IStartNodeJSWikiConfigs { authToken?: string; - constants: { TIDDLYWIKI_PACKAGE_FOLDER: string }; + constants: { TIDDLY_WIKI_BOOT_PATH: string; TIDDLYWIKI_BUILT_IN_PLUGINS_PATH: string }; enableHTTPAPI: boolean; excludedPlugins: string[]; homePath: string; diff --git a/src/services/wiki/wikiWorker/startNodeJSWiki.ts b/src/services/wiki/wikiWorker/startNodeJSWiki.ts index 5889b243..1f5aa7ec 100644 --- a/src/services/wiki/wikiWorker/startNodeJSWiki.ts +++ b/src/services/wiki/wikiWorker/startNodeJSWiki.ts @@ -21,25 +21,26 @@ import { ipcServerRoutes } from './ipcServerRoutes'; import { createLoadWikiTiddlersWithSubWikis } from './loadWikiTiddlersWithSubWikis'; import { authTokenIsProvided } from './wikiWorkerUtilities'; -export function startNodeJSWiki({ - enableHTTPAPI, - authToken, - constants: { TIDDLYWIKI_PACKAGE_FOLDER }, - excludedPlugins = [], - homePath, - https, - isDev, - openDebugger, - readOnlyMode, - rootTiddler = '$:/core/save/all', - shouldUseDarkColors, - subWikis = [], - tiddlyWikiHost = defaultServerIP, - tiddlyWikiPort = 5112, - tokenAuth, - userName, - workspace, -}: IStartNodeJSWikiConfigs): Observable { +export function startNodeJSWiki(configs: IStartNodeJSWikiConfigs): Observable { + const { + enableHTTPAPI, + authToken, + constants: { TIDDLYWIKI_BUILT_IN_PLUGINS_PATH, TIDDLY_WIKI_BOOT_PATH }, + excludedPlugins = [], + homePath, + https, + isDev, + openDebugger, + readOnlyMode, + rootTiddler = '$:/core/save/all', + shouldUseDarkColors, + subWikis = [], + tiddlyWikiHost = defaultServerIP, + tiddlyWikiPort = 5112, + tokenAuth, + userName, + workspace, + } = configs; return new Observable((observer) => { if (openDebugger === true) { inspector.open(); @@ -49,7 +50,7 @@ export function startNodeJSWiki({ } // Wait for services to be ready before using intercept with logFor onWorkerServicesReady(() => { - void native.logFor(workspace.name, 'info', 'test-id-WorkerServicesReady'); + void native.logFor(workspace.name, 'debug', 'test-id-WorkerServicesReady', configs as unknown as Record); const textDecoder = new TextDecoder(); intercept( (newStdOut: string | Uint8Array) => { @@ -93,16 +94,26 @@ export function startNodeJSWiki({ try { // Log which TiddlyWiki version is being used (local vs built-in) - const isUsingLocalTiddlyWiki = TIDDLYWIKI_PACKAGE_FOLDER.includes(path.join(homePath, 'node_modules')); + const isUsingLocalTiddlyWiki = TIDDLY_WIKI_BOOT_PATH.includes(path.join(homePath, 'node_modules')); void native.logFor( workspace.name, 'info', - `Starting TiddlyWiki from ${isUsingLocalTiddlyWiki ? 'wiki-local installation' : 'built-in installation'}: ${TIDDLYWIKI_PACKAGE_FOLDER}`, + `Starting TiddlyWiki from ${isUsingLocalTiddlyWiki ? 'wiki-local installation' : 'built-in installation'}: ${TIDDLY_WIKI_BOOT_PATH}`, ); const wikiInstance = TiddlyWiki(); setWikiInstance(wikiInstance); - process.env.TIDDLYWIKI_PLUGIN_PATH = path.resolve(homePath, 'plugins'); + /** + * Set plugin search paths. When wiki uses local TiddlyWiki installation, + * we still need to include TidGi's built-in plugins path so our custom plugins can be found. + * Path separator is ':' on Unix and ';' on Windows. + */ + const pathSeparator = process.platform === 'win32' ? ';' : ':'; + const pluginPaths = [ + path.resolve(homePath, 'plugins'), + TIDDLYWIKI_BUILT_IN_PLUGINS_PATH, + ]; + process.env.TIDDLYWIKI_PLUGIN_PATH = pluginPaths.join(pathSeparator); process.env.TIDDLYWIKI_THEME_PATH = path.resolve(homePath, 'themes'); /** @@ -233,7 +244,7 @@ export function startNodeJSWiki({ }); }); }); - wikiInstance.boot.startup({ bootPath: TIDDLYWIKI_PACKAGE_FOLDER }); + wikiInstance.boot.startup({ bootPath: TIDDLY_WIKI_BOOT_PATH }); // after setWikiInstance, ipc server routes will start serving content ipcServerRoutes.setConfig({ readOnlyMode }); ipcServerRoutes.setWikiInstance(wikiInstance);