mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-05 18:20:39 -08:00
refactor: remove outdated method signature
This commit is contained in:
parent
a1f99632a6
commit
a90ccdf44e
8 changed files with 188 additions and 145 deletions
|
|
@ -482,7 +482,7 @@ export class Wiki implements IWikiService {
|
||||||
this.logProgress(i18n.t('AddWorkspace.WikiTemplateCopyCompleted') + newWikiPath);
|
this.logProgress(i18n.t('AddWorkspace.WikiTemplateCopyCompleted') + newWikiPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createSubWiki(parentFolderLocation: string, folderName: string, _subWikiFolderName: string, _mainWikiPath: string, _tagName = '', onlyLink = false): Promise<void> {
|
public async createSubWiki(parentFolderLocation: string, folderName: string, onlyLink = false): Promise<void> {
|
||||||
this.logProgress(i18n.t('AddWorkspace.StartCreatingSubWiki'));
|
this.logProgress(i18n.t('AddWorkspace.StartCreatingSubWiki'));
|
||||||
const newWikiPath = path.join(parentFolderLocation, folderName);
|
const newWikiPath = path.join(parentFolderLocation, folderName);
|
||||||
if (!(await pathExists(parentFolderLocation))) {
|
if (!(await pathExists(parentFolderLocation))) {
|
||||||
|
|
@ -625,14 +625,7 @@ export class Wiki implements IWikiService {
|
||||||
await gitService.clone(gitRepoUrl, path.join(parentFolderLocation, wikiFolderName), gitUserInfo);
|
await gitService.clone(gitRepoUrl, path.join(parentFolderLocation, wikiFolderName), gitUserInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async cloneSubWiki(
|
public async cloneSubWiki(parentFolderLocation: string, wikiFolderName: string, gitRepoUrl: string, gitUserInfo: IGitUserInfos): Promise<void> {
|
||||||
parentFolderLocation: string,
|
|
||||||
wikiFolderName: string,
|
|
||||||
_mainWikiPath: string,
|
|
||||||
gitRepoUrl: string,
|
|
||||||
gitUserInfo: IGitUserInfos,
|
|
||||||
_tagName = '',
|
|
||||||
): Promise<void> {
|
|
||||||
this.logProgress(i18n.t('AddWorkspace.StartCloningSubWiki'));
|
this.logProgress(i18n.t('AddWorkspace.StartCloningSubWiki'));
|
||||||
const newWikiPath = path.join(parentFolderLocation, wikiFolderName);
|
const newWikiPath = path.join(parentFolderLocation, wikiFolderName);
|
||||||
if (!(await pathExists(parentFolderLocation))) {
|
if (!(await pathExists(parentFolderLocation))) {
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,7 @@ export interface IWikiService {
|
||||||
/** return true if wiki does existed and folder is a valid tiddlywiki folder, return error message (a string) if there is an error checking wiki existence */
|
/** return true if wiki does existed and folder is a valid tiddlywiki folder, return error message (a string) if there is an error checking wiki existence */
|
||||||
checkWikiExist(workspace: IWorkspace, options?: { shouldBeMainWiki?: boolean; showDialog?: boolean }): Promise<string | true>;
|
checkWikiExist(workspace: IWorkspace, options?: { shouldBeMainWiki?: boolean; showDialog?: boolean }): Promise<string | true>;
|
||||||
checkWikiStartLock(wikiFolderLocation: string): boolean;
|
checkWikiStartLock(wikiFolderLocation: string): boolean;
|
||||||
cloneSubWiki(
|
cloneSubWiki(parentFolderLocation: string, wikiFolderName: string, gitRepoUrl: string, gitUserInfo: IGitUserInfos): Promise<void>;
|
||||||
parentFolderLocation: string,
|
|
||||||
wikiFolderName: string,
|
|
||||||
mainWikiPath: string,
|
|
||||||
gitRepoUrl: string,
|
|
||||||
gitUserInfo: IGitUserInfos,
|
|
||||||
tagName?: string,
|
|
||||||
): Promise<void>;
|
|
||||||
cloneWiki(parentFolderLocation: string, wikiFolderName: string, gitRepoUrl: string, gitUserInfo: IGitUserInfos): Promise<void>;
|
cloneWiki(parentFolderLocation: string, wikiFolderName: string, gitRepoUrl: string, gitUserInfo: IGitUserInfos): Promise<void>;
|
||||||
copyWikiTemplate(newFolderPath: string, folderName: string): Promise<void>;
|
copyWikiTemplate(newFolderPath: string, folderName: string): Promise<void>;
|
||||||
/**
|
/**
|
||||||
|
|
@ -43,7 +36,7 @@ export interface IWikiService {
|
||||||
* @param mainWikiToLink
|
* @param mainWikiToLink
|
||||||
* @param onlyLink not creating new subwiki folder, just link existed subwiki folder to main wiki folder
|
* @param onlyLink not creating new subwiki folder, just link existed subwiki folder to main wiki folder
|
||||||
*/
|
*/
|
||||||
createSubWiki(parentFolderLocation: string, folderName: string, subWikiFolderName: string, mainWikiPath: string, tagName?: string, onlyLink?: boolean): Promise<void>;
|
createSubWiki(parentFolderLocation: string, folderName: string, onlyLink?: boolean): Promise<void>;
|
||||||
ensureWikiExist(wikiPath: string, shouldBeMainWiki: boolean): Promise<void>;
|
ensureWikiExist(wikiPath: string, shouldBeMainWiki: boolean): Promise<void>;
|
||||||
extractWikiHTML(htmlWikiPath: string, saveWikiFolderPath: string): Promise<string | undefined>;
|
extractWikiHTML(htmlWikiPath: string, saveWikiFolderPath: string): Promise<string | undefined>;
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { IFileInfo } from 'tiddlywiki';
|
import type { IFileInfo } from 'tiddlywiki';
|
||||||
import type { Tiddler, Wiki } from 'tiddlywiki';
|
import type { Tiddler, Wiki } from 'tiddlywiki';
|
||||||
|
import { isWikiWorkspaceWithRouting, matchTiddlerToWorkspace } from './routingUtilities';
|
||||||
import { isFileLockError } from './utilities';
|
import { isFileLockError } from './utilities';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -83,32 +84,10 @@ export class FileSystemAdaptor {
|
||||||
|
|
||||||
const allWorkspaces = await workspace.getWorkspacesAsList();
|
const allWorkspaces = await workspace.getWorkspacesAsList();
|
||||||
|
|
||||||
// Include both main workspace and sub-wikis for tag-based routing or filter-based routing
|
// Filter to wiki workspaces with routing config (main or sub-wikis)
|
||||||
const isWikiWorkspaceWithRouting = (workspaceItem: IWorkspace): workspaceItem is IWikiWorkspace => {
|
const workspacesWithRouting = allWorkspaces
|
||||||
if (!('wikiFolderLocation' in workspaceItem) || !workspaceItem.wikiFolderLocation) {
|
.filter((w: IWorkspace): w is IWikiWorkspace => isWikiWorkspaceWithRouting(w, currentWorkspace.id))
|
||||||
return false;
|
.sort(workspaceSorter);
|
||||||
}
|
|
||||||
|
|
||||||
// Check if workspace has routing config (either tagNames or fileSystemPathFilter)
|
|
||||||
const hasRoutingConfig = ('tagNames' in workspaceItem && workspaceItem.tagNames.length > 0) ||
|
|
||||||
('fileSystemPathFilterEnable' in workspaceItem && workspaceItem.fileSystemPathFilterEnable && 'fileSystemPathFilter' in workspaceItem &&
|
|
||||||
workspaceItem.fileSystemPathFilter);
|
|
||||||
|
|
||||||
if (!hasRoutingConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Include if it's the main workspace
|
|
||||||
const isMain = workspaceItem.id === currentWorkspace.id;
|
|
||||||
|
|
||||||
// Include if it's a sub-wiki of the current main workspace
|
|
||||||
const isSubWiki = 'isSubWiki' in workspaceItem &&
|
|
||||||
workspaceItem.isSubWiki &&
|
|
||||||
workspaceItem.mainWikiID === currentWorkspace.id;
|
|
||||||
|
|
||||||
return isMain || isSubWiki;
|
|
||||||
};
|
|
||||||
const workspacesWithRouting = allWorkspaces.filter(isWikiWorkspaceWithRouting).sort(workspaceSorter);
|
|
||||||
|
|
||||||
this.wikisWithRouting = workspacesWithRouting;
|
this.wikisWithRouting = workspacesWithRouting;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -163,7 +142,7 @@ export class FileSystemAdaptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find matching workspace using the routing logic
|
// Find matching workspace using the routing logic
|
||||||
const matchingWiki = this.matchTitleToWiki(title, tags);
|
const matchingWiki = matchTiddlerToWorkspace(title, tags, this.wikisWithRouting, $tw.wiki, $tw.rootWidget);
|
||||||
|
|
||||||
// Determine the target directory based on routing
|
// Determine the target directory based on routing
|
||||||
// Sub-wikis store tiddlers directly in their root folder (not in /tiddlers subfolder)
|
// Sub-wikis store tiddlers directly in their root folder (not in /tiddlers subfolder)
|
||||||
|
|
@ -209,56 +188,6 @@ export class FileSystemAdaptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Match a tiddler to a workspace based on routing rules.
|
|
||||||
* Checks workspaces in order (priority) and returns the first match.
|
|
||||||
*
|
|
||||||
* For each workspace, checks in order (any match wins):
|
|
||||||
* 1. Direct tag match (including if tiddler's title IS one of the tagNames - it's a "tag tiddler")
|
|
||||||
* 2. If includeTagTree is enabled, use in-tagtree-of filter for recursive tag matching
|
|
||||||
* 3. If fileSystemPathFilterEnable is enabled, use custom filter expressions (one per line, any match wins)
|
|
||||||
*/
|
|
||||||
protected matchTitleToWiki(title: string, tags: string[]): IWikiWorkspace | undefined {
|
|
||||||
for (const wiki of this.wikisWithRouting) {
|
|
||||||
// Direct tag match - check if any of the tiddler's tags match any of the wiki's tagNames
|
|
||||||
// Also check if the tiddler's title IS one of the tagNames (it's a "tag tiddler" that defines that tag)
|
|
||||||
if (wiki.tagNames.length > 0) {
|
|
||||||
const hasMatchingTag = wiki.tagNames.some(tagName => tags.includes(tagName));
|
|
||||||
const isTitleATagName = wiki.tagNames.includes(title);
|
|
||||||
if (hasMatchingTag || isTitleATagName) {
|
|
||||||
return wiki;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tag tree match if enabled - check all tagNames
|
|
||||||
if (wiki.includeTagTree && wiki.tagNames.length > 0) {
|
|
||||||
for (const tagName of wiki.tagNames) {
|
|
||||||
const result = $tw.wiki.filterTiddlers(
|
|
||||||
`[in-tagtree-of:inclusive<tagName>]`,
|
|
||||||
$tw.rootWidget.makeFakeWidgetWithVariables({ tagName }),
|
|
||||||
$tw.wiki.makeTiddlerIterator([title]),
|
|
||||||
);
|
|
||||||
if (result.length > 0) {
|
|
||||||
return wiki;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom filter match if enabled
|
|
||||||
if (wiki.fileSystemPathFilterEnable && wiki.fileSystemPathFilter) {
|
|
||||||
// Split by newlines and try each filter
|
|
||||||
const filters = wiki.fileSystemPathFilter.split('\n').map(f => f.trim()).filter(f => f.length > 0);
|
|
||||||
for (const filter of filters) {
|
|
||||||
const result = $tw.wiki.filterTiddlers(filter, undefined, $tw.wiki.makeTiddlerIterator([title]));
|
|
||||||
if (result.length > 0) {
|
|
||||||
return wiki;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate file info for sub-wiki directory
|
* Generate file info for sub-wiki directory
|
||||||
* Handles symlinks correctly across platforms (Windows junctions and Linux symlinks)
|
* Handles symlinks correctly across platforms (Windows junctions and Linux symlinks)
|
||||||
|
|
|
||||||
|
|
@ -12,20 +12,19 @@ Version: TiddlyWiki v5.3.x (as of 2025-10-24)
|
||||||
|
|
||||||
!!! Key Modifications
|
!!! Key Modifications
|
||||||
|
|
||||||
!!!! 1. Dynamic Workspace Information via IPC
|
!!!! 1. Dynamic Workspace Information via Worker Services
|
||||||
|
|
||||||
* ''Original'': Uses static `$:/config/FileSystemPaths` tiddler for routing
|
* ''Original'': Uses static `$:/config/FileSystemPaths` tiddler for routing
|
||||||
* ''Modified'': Queries workspace information from main process via worker threads IPC
|
* ''Modified'': Queries workspace information from main process via worker thread services
|
||||||
* ''Reason'': Eliminates need for complex string manipulation of `FileSystemPaths` configuration
|
* ''Reason'': Eliminates need for complex string manipulation of `FileSystemPaths` configuration
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Added: Worker service caller integration
|
// Added: Worker service integration
|
||||||
import { callMainProcessService } from '@services/wiki/wikiWorker/workerServiceCaller';
|
import { workspace } from '@services/wiki/wikiWorker/services';
|
||||||
import type { IWorkspace } from '@services/workspaces/interface';
|
|
||||||
|
|
||||||
// Added: Methods to query workspace dynamically
|
// Queries workspace data dynamically
|
||||||
private async getCurrentWorkspace(): Promise<IWorkspace | undefined>
|
const currentWorkspace = await workspace.get(this.workspaceID);
|
||||||
private async getSubWikis(currentWorkspace: IWorkspace): Promise<IWorkspace[]>
|
const allWorkspaces = await workspace.getWorkspacesAsList();
|
||||||
```
|
```
|
||||||
|
|
||||||
!!!! 2. Tag-Based and Filter-Based Sub-Wiki Routing
|
!!!! 2. Tag-Based and Filter-Based Sub-Wiki Routing
|
||||||
|
|
@ -40,52 +39,42 @@ private async getSubWikis(currentWorkspace: IWorkspace): Promise<IWorkspace[]>
|
||||||
* ''Important'': Always recalculates path on save to handle tag changes - old `fileInfo` only used for cleanup
|
* ''Important'': Always recalculates path on save to handle tag changes - old `fileInfo` only used for cleanup
|
||||||
* ''Implementation'':
|
* ''Implementation'':
|
||||||
** Checks tiddler tags/filters against sub-workspace routing rules (in priority order)
|
** Checks tiddler tags/filters against sub-workspace routing rules (in priority order)
|
||||||
** Routes matching tiddlers to sub-wiki's `tiddlers` folder
|
** Routes matching tiddlers directly to sub-wiki's root folder (not `/tiddlers` subfolder)
|
||||||
** Falls back to TiddlyWiki's `$:/config/FileSystemPaths` logic for non-matching tiddlers
|
** Falls back to TiddlyWiki's `$:/config/FileSystemPaths` logic for non-matching tiddlers
|
||||||
** Loads sub-wikis cache on initialization
|
** Loads sub-wikis cache on initialization
|
||||||
** Currently loads sub-wikis once, future enhancements can watch for workspace changes
|
** Currently loads sub-wikis once, future enhancements can watch for workspace changes
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Modified: getTiddlerFileInfo is now async (safe since callers only use callback)
|
// Uses pure functions from routingUtils.ts for matching logic
|
||||||
async getTiddlerFileInfo(tiddler: Tiddler, callback: IFileSystemAdaptorCallback): Promise<void> {
|
import { matchTiddlerToWorkspace, isWikiWorkspaceWithRouting } from './routingUtils';
|
||||||
// Direct async/await instead of nested void IIFE
|
|
||||||
const currentWorkspace = await this.getCurrentWorkspace();
|
|
||||||
const subWikis = this.getSubWikis(); // Uses cache instead of IPC
|
|
||||||
const matchingSubWiki = subWikis.find(...);
|
|
||||||
|
|
||||||
if (matchingSubWiki) {
|
|
||||||
this.routeToSubWorkspace(...);
|
|
||||||
} else {
|
|
||||||
this.useDefaultFileSystemLogic(...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Added: Caching mechanism
|
// Match tiddler to workspace
|
||||||
private subWikis: IWorkspace[] = [];
|
const matchingWiki = matchTiddlerToWorkspace(title, tags, this.wikisWithRouting, $tw.wiki, $tw.rootWidget);
|
||||||
|
|
||||||
private async initializeSubWikisCache(): Promise<void> {
|
// Generate file info based on routing result
|
||||||
await this.updateSubWikisCache();
|
if (matchingWiki) {
|
||||||
}
|
return this.generateSubWikiFileInfo(tiddler, matchingWiki);
|
||||||
|
} else {
|
||||||
private async updateSubWikisCache(): Promise<void> {
|
return this.generateDefaultFileInfo(tiddler);
|
||||||
// Load sub-wikis once and cache them
|
|
||||||
const allWorkspaces = await callMainProcessService(...);
|
|
||||||
this.subWikis = allWorkspaces.filter(...);
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
!!!! 3. Separated Routing Logic
|
!!!! 3. Separated Routing Logic into Pure Functions
|
||||||
|
|
||||||
* ''Added'': `routeToSubWorkspace()` method for sub-wiki routing
|
* ''Added'': `routingUtils.ts` with pure functions for routing logic:
|
||||||
* ''Added'': `useDefaultFileSystemLogic()` method for standard routing
|
** `isWikiWorkspaceWithRouting()` - checks if workspace has routing config
|
||||||
* ''Reason'': Better code organization and maintainability
|
** `matchTiddlerToWorkspace()` - matches tiddler to workspace based on routing rules
|
||||||
|
** `matchesDirectTag()` - checks direct tag match
|
||||||
|
** `matchesTagTree()` - checks tag tree match using in-tagtree-of filter
|
||||||
|
** `matchesCustomFilter()` - checks custom filter match
|
||||||
|
* ''Reason'': Better code organization, testability, and maintainability
|
||||||
|
|
||||||
!!! Future Compatibility Notes
|
!!! Future Compatibility Notes
|
||||||
|
|
||||||
When updating from upstream TiddlyWiki filesystem adaptor:
|
When updating from upstream TiddlyWiki filesystem adaptor:
|
||||||
|
|
||||||
# Review changes to core methods: `saveTiddler`, `deleteTiddler`, `getTiddlerInfo`
|
# Review changes to core methods: `saveTiddler`, `deleteTiddler`, `getTiddlerInfo`
|
||||||
# Preserve our IPC-based workspace querying logic
|
# Preserve our worker-service-based workspace querying logic
|
||||||
# Preserve tag-based routing in `getTiddlerFileInfo`
|
# Preserve tag-based routing in `getTiddlerFileInfo`
|
||||||
# Update type definitions if TiddlyWiki's FileInfo interface changes
|
# Update type definitions if TiddlyWiki's FileInfo interface changes
|
||||||
# Test sub-wiki routing functionality after merge
|
# Test sub-wiki routing functionality after merge
|
||||||
|
|
@ -96,7 +85,7 @@ When validating this adaptor:
|
||||||
|
|
||||||
* [ ] Tiddlers with matching tags route to correct sub-wiki
|
* [ ] Tiddlers with matching tags route to correct sub-wiki
|
||||||
* [ ] Tiddlers without matching tags use default FileSystemPaths
|
* [ ] Tiddlers without matching tags use default FileSystemPaths
|
||||||
* [ ] IPC communication works correctly in worker thread
|
* [ ] Worker service communication works correctly
|
||||||
* [ ] Error handling falls back gracefully
|
* [ ] Error handling falls back gracefully
|
||||||
* [ ] File operations (save/delete) work in both main and sub-wikis
|
* [ ] File operations (save/delete) work in both main and sub-wikis
|
||||||
* [ ] Workspace ID caching reduces IPC overhead
|
* [ ] Workspace caching reduces service call overhead
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
import type { IWikiWorkspace, IWorkspace } from '@services/workspaces/interface';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a workspace has routing configuration (tagNames or fileSystemPathFilter).
|
||||||
|
*/
|
||||||
|
export function hasRoutingConfig(workspaceItem: IWorkspace): boolean {
|
||||||
|
const hasTagNames = 'tagNames' in workspaceItem && Array.isArray(workspaceItem.tagNames) && workspaceItem.tagNames.length > 0;
|
||||||
|
const hasFilter = 'fileSystemPathFilterEnable' in workspaceItem &&
|
||||||
|
workspaceItem.fileSystemPathFilterEnable &&
|
||||||
|
'fileSystemPathFilter' in workspaceItem &&
|
||||||
|
Boolean(workspaceItem.fileSystemPathFilter);
|
||||||
|
return hasTagNames || hasFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a workspace is a wiki workspace with routing configuration.
|
||||||
|
* This filters to wiki workspaces that are either the main workspace or sub-wikis of it.
|
||||||
|
*/
|
||||||
|
export function isWikiWorkspaceWithRouting(
|
||||||
|
workspaceItem: IWorkspace,
|
||||||
|
mainWorkspaceId: string,
|
||||||
|
): workspaceItem is IWikiWorkspace {
|
||||||
|
// Must have wiki folder location
|
||||||
|
if (!('wikiFolderLocation' in workspaceItem) || !workspaceItem.wikiFolderLocation) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must have routing config
|
||||||
|
if (!hasRoutingConfig(workspaceItem)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include if it's the main workspace
|
||||||
|
const isMain = workspaceItem.id === mainWorkspaceId;
|
||||||
|
|
||||||
|
// Include if it's a sub-wiki of the current main workspace
|
||||||
|
const isSubWiki = 'isSubWiki' in workspaceItem &&
|
||||||
|
workspaceItem.isSubWiki &&
|
||||||
|
'mainWikiID' in workspaceItem &&
|
||||||
|
workspaceItem.mainWikiID === mainWorkspaceId;
|
||||||
|
|
||||||
|
return isMain || isSubWiki;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a tiddler matches a workspace's direct tag routing.
|
||||||
|
* Returns true if:
|
||||||
|
* - Any of the tiddler's tags match any of the workspace's tagNames
|
||||||
|
* - The tiddler's title IS one of the tagNames (it's a "tag tiddler")
|
||||||
|
*/
|
||||||
|
export function matchesDirectTag(
|
||||||
|
tiddlerTitle: string,
|
||||||
|
tiddlerTags: string[],
|
||||||
|
workspaceTagNames: string[],
|
||||||
|
): boolean {
|
||||||
|
if (workspaceTagNames.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasMatchingTag = workspaceTagNames.some(tagName => tiddlerTags.includes(tagName));
|
||||||
|
const isTitleATagName = workspaceTagNames.includes(tiddlerTitle);
|
||||||
|
|
||||||
|
return hasMatchingTag || isTitleATagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a tiddler matches a workspace's tag tree routing.
|
||||||
|
* Uses TiddlyWiki's in-tagtree-of filter for recursive tag hierarchy matching.
|
||||||
|
*/
|
||||||
|
export function matchesTagTree(
|
||||||
|
tiddlerTitle: string,
|
||||||
|
workspaceTagNames: string[],
|
||||||
|
wiki: typeof $tw.wiki,
|
||||||
|
rootWidget: typeof $tw.rootWidget,
|
||||||
|
): boolean {
|
||||||
|
for (const tagName of workspaceTagNames) {
|
||||||
|
const result = wiki.filterTiddlers(
|
||||||
|
`[in-tagtree-of:inclusive<tagName>]`,
|
||||||
|
rootWidget.makeFakeWidgetWithVariables({ tagName }),
|
||||||
|
wiki.makeTiddlerIterator([tiddlerTitle]),
|
||||||
|
);
|
||||||
|
if (result.length > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a tiddler matches a workspace's custom filter routing.
|
||||||
|
* Filters are separated by newlines; any match wins.
|
||||||
|
*/
|
||||||
|
export function matchesCustomFilter(
|
||||||
|
tiddlerTitle: string,
|
||||||
|
filterExpression: string,
|
||||||
|
wiki: typeof $tw.wiki,
|
||||||
|
): boolean {
|
||||||
|
const filters = filterExpression.split('\n').map(f => f.trim()).filter(f => f.length > 0);
|
||||||
|
|
||||||
|
for (const filter of filters) {
|
||||||
|
const result = wiki.filterTiddlers(filter, undefined, wiki.makeTiddlerIterator([tiddlerTitle]));
|
||||||
|
if (result.length > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match a tiddler to a workspace based on routing rules.
|
||||||
|
* Checks workspaces in order (priority) and returns the first match.
|
||||||
|
*
|
||||||
|
* For each workspace, checks in order (any match wins):
|
||||||
|
* 1. Direct tag match (including if tiddler's title IS one of the tagNames)
|
||||||
|
* 2. If includeTagTree is enabled, use in-tagtree-of filter for recursive tag matching
|
||||||
|
* 3. If fileSystemPathFilterEnable is enabled, use custom filter expressions
|
||||||
|
*/
|
||||||
|
export function matchTiddlerToWorkspace(
|
||||||
|
tiddlerTitle: string,
|
||||||
|
tiddlerTags: string[],
|
||||||
|
workspacesWithRouting: IWikiWorkspace[],
|
||||||
|
wiki: typeof $tw.wiki,
|
||||||
|
rootWidget: typeof $tw.rootWidget,
|
||||||
|
): IWikiWorkspace | undefined {
|
||||||
|
for (const workspace of workspacesWithRouting) {
|
||||||
|
// 1. Direct tag match
|
||||||
|
if (matchesDirectTag(tiddlerTitle, tiddlerTags, workspace.tagNames)) {
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Tag tree match (if enabled)
|
||||||
|
if (workspace.includeTagTree && workspace.tagNames.length > 0) {
|
||||||
|
if (matchesTagTree(tiddlerTitle, workspace.tagNames, wiki, rootWidget)) {
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Custom filter match (if enabled)
|
||||||
|
if (workspace.fileSystemPathFilterEnable && workspace.fileSystemPathFilter) {
|
||||||
|
if (matchesCustomFilter(tiddlerTitle, workspace.fileSystemPathFilter, wiki)) {
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
@ -73,10 +73,8 @@ export function useCloneWiki(
|
||||||
await window.service.wiki.cloneSubWiki(
|
await window.service.wiki.cloneSubWiki(
|
||||||
form.parentFolderLocation,
|
form.parentFolderLocation,
|
||||||
form.wikiFolderName,
|
form.wikiFolderName,
|
||||||
form.mainWikiToLink.wikiFolderLocation,
|
|
||||||
form.gitRepoUrl,
|
form.gitRepoUrl,
|
||||||
form.gitUserInfo!,
|
form.gitUserInfo!,
|
||||||
form.tagNames[0] ?? '',
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await callWikiInitialization(newWorkspaceConfig, wikiCreationMessageSetter, t, form.gitUserInfo, { from: WikiCreationMethod.Clone });
|
await callWikiInitialization(newWorkspaceConfig, wikiCreationMessageSetter, t, form.gitUserInfo, { from: WikiCreationMethod.Clone });
|
||||||
|
|
|
||||||
|
|
@ -81,14 +81,7 @@ export function useExistedWiki(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await window.service.wiki.ensureWikiExist(form.wikiFolderLocation, false);
|
await window.service.wiki.ensureWikiExist(form.wikiFolderLocation, false);
|
||||||
await window.service.wiki.createSubWiki(
|
await window.service.wiki.createSubWiki(parentFolderLocationForExistedFolder, wikiFolderNameForExistedFolder, true);
|
||||||
parentFolderLocationForExistedFolder,
|
|
||||||
wikiFolderNameForExistedFolder,
|
|
||||||
'subwiki',
|
|
||||||
form.mainWikiToLink.wikiFolderLocation,
|
|
||||||
form.tagNames[0] ?? '',
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
await callWikiInitialization(newWorkspaceConfig, wikiCreationMessageSetter, t, form.gitUserInfo, { from: WikiCreationMethod.LoadExisting });
|
await callWikiInitialization(newWorkspaceConfig, wikiCreationMessageSetter, t, form.gitUserInfo, { from: WikiCreationMethod.LoadExisting });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ export function useNewWiki(
|
||||||
await window.service.wiki.copyWikiTemplate(form.parentFolderLocation, form.wikiFolderName);
|
await window.service.wiki.copyWikiTemplate(form.parentFolderLocation, form.wikiFolderName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await window.service.wiki.createSubWiki(form.parentFolderLocation, form.wikiFolderName, 'subwiki', form.mainWikiToLink.wikiFolderLocation, form.tagNames[0] ?? '');
|
await window.service.wiki.createSubWiki(form.parentFolderLocation, form.wikiFolderName);
|
||||||
}
|
}
|
||||||
await callWikiInitialization(newWorkspaceConfig, wikiCreationMessageSetter, t, form.gitUserInfo, { notClose: options?.notClose, from: WikiCreationMethod.Create });
|
await callWikiInitialization(newWorkspaceConfig, wikiCreationMessageSetter, t, form.gitUserInfo, { notClose: options?.notClose, from: WikiCreationMethod.Create });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue