mirror of
https://github.com/poanse/obsidian-taskmap.git
synced 2026-07-22 06:05:58 +00:00
fixed incorrect link behaviour
This commit is contained in:
parent
c4036d0ae2
commit
f1ad3fe0cd
8 changed files with 72 additions and 44 deletions
|
|
@ -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",
|
||||
|
|
|
|||
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "obsidian-taskmap",
|
||||
"version": "0.1.4",
|
||||
"version": "0.1.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -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": {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
</script>
|
||||
|
|
@ -193,7 +206,7 @@
|
|||
onblur={handleBlur}
|
||||
onkeydown={handleKeydown}
|
||||
oninput={handleInput}
|
||||
>{taskData.name}</textarea>
|
||||
>{taskData.path ? linkFromFilePath(taskData.path) : taskData.name}</textarea>
|
||||
{:else}
|
||||
<div
|
||||
class="text-preview tasktext"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { AbstractInputSuggest, App, prepareFuzzySearch, TFile } from "obsidian";
|
||||
import { linkFromFilePath } from "../LinkManager";
|
||||
|
||||
export class LinkSuggest extends AbstractInputSuggest<TFile> {
|
||||
textInputEl: HTMLTextAreaElement;
|
||||
|
|
@ -58,21 +59,11 @@ export class LinkSuggest extends AbstractInputSuggest<TFile> {
|
|||
|
||||
if (!match) return;
|
||||
|
||||
const linkStart = lineStart + match.index!;
|
||||
const beforeLink = text.substring(0, linkStart);
|
||||
const afterCursor = text.substring(cursor);
|
||||
|
||||
const newLinkText = `[[${file.basename}]]`;
|
||||
|
||||
this.textInputEl.value = beforeLink + newLinkText + afterCursor;
|
||||
this.textInputEl.value = linkFromFilePath(file.path);
|
||||
|
||||
// Trigger Svelte update
|
||||
this.textInputEl.dispatchEvent(new Event("input"));
|
||||
|
||||
// Reset cursor
|
||||
const newCursor = beforeLink.length + newLinkText.length;
|
||||
this.textInputEl.setSelectionRange(newCursor, newCursor);
|
||||
|
||||
this.textInputEl.focus();
|
||||
this.textInputEl.blur();
|
||||
this.close();
|
||||
|
|
|
|||
Loading…
Reference in a new issue