From f1ad3fe0cd075ebabf606eb4dd3e8eeaa9fe0a72 Mon Sep 17 00:00:00 2001 From: poanse <50020771+poanse@users.noreply.github.com> Date: Sun, 3 May 2026 22:46:32 +0300 Subject: [PATCH] fixed incorrect link behaviour --- manifest.json | 2 +- package-lock.json | 2 +- package.json | 2 +- src/Context.svelte.ts | 11 ++++++++--- src/FileWatcherWithCache.ts | 23 +++++++++++++--------- src/LinkManager.ts | 28 ++++++++++++++++++++------- src/components/TaskText.svelte | 35 +++++++++++++++++++++++----------- src/helpers/LinkSuggest.ts | 13 ++----------- 8 files changed, 72 insertions(+), 44 deletions(-) diff --git a/manifest.json b/manifest.json index ef4c86e..7d0a8f2 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "taskmap", "name": "Taskmap", - "version": "0.1.4", + "version": "0.1.5", "minAppVersion": "1.12.4", "description": "Plan projects via interactive GUI task trees with automatic layout.", "author": "poanse", diff --git a/package-lock.json b/package-lock.json index 58873b0..c0b9220 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "obsidian-taskmap", - "version": "0.1.4", + "version": "0.1.5", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index da4ed04..3e08de5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-taskmap", - "version": "0.1.4", + "version": "0.1.5", "description": "Taskmap plugin for Obsidian (https://obsidian.md)", "main": "main.js", "scripts": { diff --git a/src/Context.svelte.ts b/src/Context.svelte.ts index df4177e..55c579e 100644 --- a/src/Context.svelte.ts +++ b/src/Context.svelte.ts @@ -22,7 +22,12 @@ import { V2, } from "./NodePositionsCalculator"; import { DraggingManager } from "./DraggingManager.svelte"; -import { delink, LinkManager, tasknameFromFilePath } from "./LinkManager"; +import { + delink, + LinkManager, + taskNameFromFile, + taskPathFromFile, +} from "./LinkManager"; import { HistoryManager } from "./data/HistoryManager.svelte"; import type { ProjectData } from "./data/ProjectData.svelte.js"; import { VersionedData } from "./data/VersionedData"; @@ -508,8 +513,8 @@ export class Context { ); this.versionedData.setName( taskId, - tasknameFromFilePath(this.versionedData.getTask(taskId).name), - filepath, + taskNameFromFile(tfile), + taskPathFromFile(tfile), ); this.save(); await this.app.workspace diff --git a/src/FileWatcherWithCache.ts b/src/FileWatcherWithCache.ts index c1d2e1a..2f66f19 100644 --- a/src/FileWatcherWithCache.ts +++ b/src/FileWatcherWithCache.ts @@ -1,7 +1,12 @@ import { type App, type Plugin, TAbstractFile, TFile, TFolder } from "obsidian"; import { TASKMAP_VIEW_TYPE, TaskmapView } from "./TaskmapView"; import { loadProjectData, updateFile } from "./SaveManager"; -import { delink, generateMarkdownLink, pathIsUnderFolder } from "./LinkManager"; +import { + delink, + pathIsUnderFolder, + taskNameFromFile, + taskPathFromFile, +} from "./LinkManager"; import type { ProjectData } from "./data/ProjectData.svelte"; /** In-memory index of `.taskmap` files; `TFile.path` stays in sync with vault renames. */ @@ -113,9 +118,9 @@ export class FileWatcherWithCache { if (!projectData) { continue; } - const affectedTasks = projectData.getTasks().filter( - (t) => t.path && deletedFile.path === t.path, - ); + const affectedTasks = projectData + .getTasks() + .filter((t) => t.path && deletedFile.path === t.path); for (const t of affectedTasks) { t.name = delink(t.name); t.path = undefined; @@ -153,12 +158,12 @@ export class FileWatcherWithCache { if (!projectData) { continue; } - const affectedTasks = projectData.getTasks().filter( - (t) => t.path && t.path === oldPath, - ); + const affectedTasks = projectData + .getTasks() + .filter((t) => t.path && t.path === oldPath); for (const t of affectedTasks) { - t.path = changedMdFile.path; - t.name = generateMarkdownLink(app, changedMdFile); + t.path = taskPathFromFile(changedMdFile); + t.name = taskNameFromFile(changedMdFile); } if (affectedTasks) { console.debug(`${taskmapFile.path} changed`); diff --git a/src/LinkManager.ts b/src/LinkManager.ts index 9354638..264154a 100644 --- a/src/LinkManager.ts +++ b/src/LinkManager.ts @@ -1,6 +1,7 @@ import type { App, TFile } from "obsidian"; +import type { TaskData } from "./types"; -export function tasknameFromFilePath(path: string) { +export function linkFromFilePath(path: string) { if (path.endsWith(".md")) { path = path.slice(0, path.length - 3); } @@ -15,14 +16,20 @@ export function delink(s: string) { return isLink(s) ? s.slice(2, s.length - 2) : s; } -/** relativePath to TFile */ -export function getFromRelativePath(app: App, path: string) { - return app.vault.getFileByPath(path); +export function nameFromLink(app: App, s: string) { + if (!isLink(s)) { + return s; + } + const delinked = delink(s); + const file = app.vault.getFileByPath(delinked); + if (!file) { + return delinked; + } + return file.basename; } -/** TFile to wikilink */ -export function generateMarkdownLink(app: App, file: TFile) { - return app.fileManager.generateMarkdownLink(file, ""); +export function generateMarkdownLinkFromTask(task: TaskData) { + return `[${task.name}](${task.path})`; } /** True if `path` is a file inside `folderPath` (not a false `startsWith` on the folder segment). */ @@ -30,6 +37,13 @@ export function pathIsUnderFolder(path: string, folderPath: string): boolean { return path.startsWith(folderPath + "/"); } +export function taskPathFromFile(tfile: TFile) { + return tfile.path; +} +export function taskNameFromFile(tfile: TFile) { + return tfile.basename; +} + export class LinkManager { private app: App; diff --git a/src/components/TaskText.svelte b/src/components/TaskText.svelte index 651b014..e146a5e 100644 --- a/src/components/TaskText.svelte +++ b/src/components/TaskText.svelte @@ -3,7 +3,13 @@ import {Component, MarkdownRenderer, Notice} from "obsidian"; import {LinkSuggest} from "../helpers/LinkSuggest"; import type {Context} from "../Context.svelte.js"; - import {delink, getFromRelativePath, isLink} from "../LinkManager"; + import { + generateMarkdownLinkFromTask, + isLink, + linkFromFilePath, + nameFromLink, taskNameFromFile, + taskPathFromFile + } from "../LinkManager"; import {NoTaskId} from "../NodePositionsCalculator"; let { @@ -62,7 +68,7 @@ const target = e.target as HTMLElement; const link = target.closest(".internal-link"); if (link && taskData.path) { - const file = getFromRelativePath(context.app, taskData.path); + const file = context.app.vault.getFileByPath(taskData.path); if (file) { e.preventDefault(); // TODO: is this line needed? e.stopPropagation(); @@ -96,7 +102,7 @@ return; } textPreviewEl.empty(); // Clear previous render - const content = taskData.name; + const content = taskData.path ? generateMarkdownLinkFromTask(taskData) : taskData.name; await MarkdownRenderer.render( context.app, content, @@ -159,20 +165,27 @@ return; } let path; - let newName = textEditEl.value; - if (isLink(newName)) { - const file = context.linkManager.getFromLink(newName); + let name; + let maybeLink = textEditEl.value; + if (textEditEl.value == taskData.name) { + // no changes + return; + } + if (isLink(maybeLink)) { + const file = context.linkManager.getFromLink(maybeLink); if (file !== null) { - path = file.path; + path = taskPathFromFile(file); + name = taskNameFromFile(file); } else { - new Notice(`Link ${newName} points to a nonexistent file`); + new Notice(`Link ${maybeLink} points to a nonexistent file`); path = undefined; - newName = delink(newName); + name = nameFromLink(context.app, maybeLink); } } else { path = undefined; + name = maybeLink; } - context.versionedData.setName(taskId, newName, path); + context.versionedData.setName(taskId, name, path); context.save(); } @@ -193,7 +206,7 @@ onblur={handleBlur} onkeydown={handleKeydown} oninput={handleInput} - >{taskData.name} + >{taskData.path ? linkFromFilePath(taskData.path) : taskData.name} {:else}