mirror of
https://github.com/rioskit/obsidian-todo-txt-mode.git
synced 2026-07-22 05:49:24 +00:00
Reorganize project structure and update configuration files
• Move source files to src/ directory: - main.ts → src/main.ts (main plugin class) - settings.ts → src/settings.ts (settings interface and UI) - sort.ts → src/sort.ts (task sorting and moving functionality) - syntax.ts → src/syntax.ts (syntax highlighting with CodeMirror) • Update build configuration: - esbuild.config.mjs: Change entry point from "main.ts" to "src/main.ts" • Update plugin manifest: - manifest.json: Remove unnecessary "main" field • Enhance UI styling: - styles.css: Add .todo-txt-mode-files-container styling for better settings layout
This commit is contained in:
parent
42a69ef75f
commit
116449cdc2
7 changed files with 91 additions and 79 deletions
|
|
@ -15,7 +15,7 @@ const context = await esbuild.context({
|
|||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ["main.ts"],
|
||||
entryPoints: ["src/main.ts"],
|
||||
bundle: true,
|
||||
external: [
|
||||
"obsidian",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,5 @@
|
|||
"description": "Support for todo.txt file format with syntax highlighting and task management",
|
||||
"author": "Riosk It",
|
||||
"authorUrl": "https://github.com/rioskit",
|
||||
"isDesktopOnly": false,
|
||||
"main": "main.js"
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
import {
|
||||
Editor,
|
||||
MarkdownView,
|
||||
Plugin,
|
||||
TFile,
|
||||
debounce,
|
||||
} from 'obsidian';
|
||||
|
||||
import { TodoTxtSettings, DEFAULT_SETTINGS, TodoTxtSettingTab } from './settings';
|
||||
|
|
@ -20,10 +17,19 @@ export default class TodoTxtPlugin extends Plugin {
|
|||
this.sorter = new TodoTxtSorter(this.app, this.settings, this.isTodoTxtFile.bind(this));
|
||||
|
||||
this.addCommand({
|
||||
id: 'todo-txt-done',
|
||||
id: 'done',
|
||||
name: 'Move completed tasks to done file',
|
||||
callback: async () => {
|
||||
await this.sorter.moveCompletedTasks();
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (!activeView || !activeView.file) return false;
|
||||
|
||||
const isTodoFile = this.isTodoTxtFile(activeView.file.path);
|
||||
if (checking) return isTodoFile;
|
||||
|
||||
if (isTodoFile) {
|
||||
this.sorter.moveCompletedTasks();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
this.sorter.registerSortCommands(this);
|
||||
|
|
@ -34,36 +40,12 @@ export default class TodoTxtPlugin extends Plugin {
|
|||
]);
|
||||
|
||||
|
||||
const debouncedEditorChangeHandler = debounce((editor: Editor, markdownView: MarkdownView) => {
|
||||
const file = markdownView?.file;
|
||||
if (!file || !this.isTodoTxtFile(file.path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
}, 100, true);
|
||||
|
||||
this.registerEvent(
|
||||
this.app.workspace.on('editor-change', debouncedEditorChangeHandler)
|
||||
);
|
||||
|
||||
this.registerEvent(
|
||||
this.app.workspace.on('file-open', (file: TFile | null) => {
|
||||
if (file && this.isTodoTxtFile(file.path)) {
|
||||
this.refreshView();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.refreshView();
|
||||
});
|
||||
}
|
||||
|
||||
onunload() {
|
||||
if (this.sorter) {
|
||||
this.sorter = null as unknown as TodoTxtSorter;
|
||||
}
|
||||
console.log('Todo.txt Mode plugin unloaded');
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
|
|
@ -72,26 +54,9 @@ export default class TodoTxtPlugin extends Plugin {
|
|||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
this.refreshView();
|
||||
}
|
||||
|
||||
public isTodoTxtFile(path: string): boolean {
|
||||
return this.settings.todoFilePaths.includes(path) || path === this.settings.doneFilePath;
|
||||
}
|
||||
|
||||
private refreshView() {
|
||||
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (!activeView || !activeView.editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = activeView.editor;
|
||||
const content = editor.getValue();
|
||||
const cursor = editor.getCursor();
|
||||
|
||||
if (content && content.length > 0) {
|
||||
editor.setValue(content);
|
||||
editor.setCursor(cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { App, PluginSettingTab, Setting } from 'obsidian';
|
||||
import { App, PluginSettingTab, Setting, normalizePath } from 'obsidian';
|
||||
import TodoTxtPlugin from './main';
|
||||
|
||||
export enum SortType {
|
||||
|
|
@ -109,7 +109,9 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
.setPlaceholder(placeholder)
|
||||
.setValue(this.plugin.settings[key] as string)
|
||||
.onChange(async (value) => {
|
||||
(this.plugin.settings[key] as string) = value;
|
||||
// Normalize path for file path settings
|
||||
const normalizedValue = (key === 'doneFilePath') ? normalizePath(value) : value;
|
||||
(this.plugin.settings[key] as string) = normalizedValue;
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
);
|
||||
|
|
@ -119,10 +121,9 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
const {containerEl}: {containerEl: HTMLElement} = this;
|
||||
containerEl.empty();
|
||||
|
||||
containerEl.createEl('h2', {text: 'Todo.txt Mode Settings'});
|
||||
|
||||
const todoFilesSetting = new Setting(containerEl)
|
||||
.setName('Todo Files')
|
||||
.setName('Todo files')
|
||||
.setDesc('Paths to your todo files (relative to vault root)');
|
||||
|
||||
todoFilesSetting.addButton(button => button
|
||||
|
|
@ -143,7 +144,7 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
.setPlaceholder('e.g. /path/to/todo.md')
|
||||
.setValue(path)
|
||||
.onChange(async (value: string) => {
|
||||
this.plugin.settings.todoFilePaths[index] = value;
|
||||
this.plugin.settings.todoFilePaths[index] = normalizePath(value);
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
)
|
||||
|
|
@ -161,13 +162,13 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
|
||||
this.createTextSetting(
|
||||
containerEl,
|
||||
'Done File Path',
|
||||
'Done file path',
|
||||
'File to store completed tasks (relative to vault root)',
|
||||
'e.g. /done.md',
|
||||
'doneFilePath'
|
||||
);
|
||||
|
||||
containerEl.createEl('h3', {text: 'Highlighting'});
|
||||
new Setting(containerEl).setHeading().setName('Highlighting');
|
||||
|
||||
const styleSettingsInfo = containerEl.createEl('div', {
|
||||
cls: 'todo-txt-style-settings-info',
|
||||
|
|
@ -186,7 +187,7 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
|
||||
this.createHighlightSetting(
|
||||
containerEl,
|
||||
'Highlight Completed Tasks',
|
||||
'Highlight completed tasks',
|
||||
'Apply strikethrough to completed tasks (starting with "x ")',
|
||||
'highlightCompletedTask',
|
||||
'completedTaskColor'
|
||||
|
|
@ -194,7 +195,7 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
|
||||
this.createHighlightSetting(
|
||||
containerEl,
|
||||
'Highlight Projects',
|
||||
'Highlight projects',
|
||||
'Apply color to projects ("+project")',
|
||||
'highlightProject',
|
||||
'projectColor'
|
||||
|
|
@ -202,7 +203,7 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
|
||||
this.createHighlightSetting(
|
||||
containerEl,
|
||||
'Highlight Contexts',
|
||||
'Highlight contexts',
|
||||
'Apply color to contexts ("@context")',
|
||||
'highlightContext',
|
||||
'contextColor'
|
||||
|
|
@ -210,7 +211,7 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
|
||||
this.createHighlightSetting(
|
||||
containerEl,
|
||||
'Highlight Priorities',
|
||||
'Highlight priorities',
|
||||
'Apply color to priorities ("(A)", "(1)")',
|
||||
'highlightPriority',
|
||||
'priorityColor'
|
||||
|
|
@ -218,17 +219,17 @@ export class TodoTxtSettingTab extends PluginSettingTab {
|
|||
|
||||
this.createHighlightSetting(
|
||||
containerEl,
|
||||
'Highlight Due Dates',
|
||||
'Highlight due dates',
|
||||
'Apply color to due dates ("due:yyyy-mm-dd")',
|
||||
'highlightDueDate',
|
||||
'dueDateColor'
|
||||
);
|
||||
|
||||
containerEl.createEl('h3', {text: 'Sort Settings'});
|
||||
new Setting(containerEl).setHeading().setName('Sort settings');
|
||||
|
||||
this.createTextSetting(
|
||||
containerEl,
|
||||
'Boundary Marker',
|
||||
'Boundary marker',
|
||||
'Lines after this marker will not be sorted. Default: "--"',
|
||||
'--',
|
||||
'boundaryMarker'
|
||||
|
|
@ -58,34 +58,70 @@ export class TodoTxtSorter {
|
|||
|
||||
registerSortCommands(plugin: Plugin) {
|
||||
plugin.addCommand({
|
||||
id: 'todo-txt-sort-priority',
|
||||
id: 'sort-priority',
|
||||
name: 'Sort by priority',
|
||||
callback: async () => {
|
||||
await this.sortTasks(SortType.Priority);
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (!activeView || !activeView.file) return false;
|
||||
|
||||
const isTodoFile = this.isTodoTxtFile(activeView.file.path);
|
||||
if (checking) return isTodoFile;
|
||||
|
||||
if (isTodoFile) {
|
||||
this.sortTasks(SortType.Priority);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
plugin.addCommand({
|
||||
id: 'todo-txt-sort-project',
|
||||
id: 'sort-project',
|
||||
name: 'Sort by project',
|
||||
callback: async () => {
|
||||
await this.sortTasks(SortType.Project);
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (!activeView || !activeView.file) return false;
|
||||
|
||||
const isTodoFile = this.isTodoTxtFile(activeView.file.path);
|
||||
if (checking) return isTodoFile;
|
||||
|
||||
if (isTodoFile) {
|
||||
this.sortTasks(SortType.Project);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
plugin.addCommand({
|
||||
id: 'todo-txt-sort-context',
|
||||
id: 'sort-context',
|
||||
name: 'Sort by context',
|
||||
callback: async () => {
|
||||
await this.sortTasks(SortType.Context);
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (!activeView || !activeView.file) return false;
|
||||
|
||||
const isTodoFile = this.isTodoTxtFile(activeView.file.path);
|
||||
if (checking) return isTodoFile;
|
||||
|
||||
if (isTodoFile) {
|
||||
this.sortTasks(SortType.Context);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
plugin.addCommand({
|
||||
id: 'todo-txt-sort-due-date',
|
||||
id: 'sort-due-date',
|
||||
name: 'Sort by due date',
|
||||
callback: async () => {
|
||||
await this.sortTasks(SortType.DueDate);
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (!activeView || !activeView.file) return false;
|
||||
|
||||
const isTodoFile = this.isTodoTxtFile(activeView.file.path);
|
||||
if (checking) return isTodoFile;
|
||||
|
||||
if (isTodoFile) {
|
||||
this.sortTasks(SortType.DueDate);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -178,7 +214,9 @@ export class TodoTxtSorter {
|
|||
const sortedLines = linesAfterBoundary.length > 0
|
||||
? [...sortedTasks, '', ...linesAfterBoundary]
|
||||
: sortedTasks;
|
||||
await this.app.vault.modify(file, sortedLines.join('\n'));
|
||||
await this.app.vault.process(file, (data) => {
|
||||
return sortedLines.join('\n');
|
||||
});
|
||||
|
||||
new Notice(`Tasks sorted by ${sortType}`);
|
||||
}
|
||||
|
|
@ -218,7 +256,9 @@ export class TodoTxtSorter {
|
|||
|
||||
if (completedLines.length > 0) {
|
||||
completedTasks = [...completedTasks, ...completedLines];
|
||||
await this.app.vault.modify(file, remainingLines.join('\n'));
|
||||
await this.app.vault.process(file, (data) => {
|
||||
return remainingLines.join('\n');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +281,9 @@ export class TodoTxtSorter {
|
|||
const existingContent = await this.app.vault.cachedRead(doneFile);
|
||||
const newContent = completedTasks.join('\n') +
|
||||
(existingContent ? '\n' + existingContent : '');
|
||||
await this.app.vault.modify(doneFile, newContent);
|
||||
await this.app.vault.process(doneFile, (data) => {
|
||||
return newContent;
|
||||
});
|
||||
}
|
||||
|
||||
new Notice(`Moved ${completedTasks.length} completed task(s) to ${doneFilePath}`);
|
||||
|
|
@ -83,6 +83,11 @@ settings:
|
|||
display: none;
|
||||
}
|
||||
|
||||
/* Todo files container styling */
|
||||
.todo-txt-mode-files-container {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* スタイル設定案内メッセージのスタイル */
|
||||
.todo-txt-style-settings-info {
|
||||
margin-bottom: 12px;
|
||||
|
|
|
|||
Loading…
Reference in a new issue