Compare commits

..

1 Commits

Author SHA1 Message Date
8fe38af7b3 Update headings list to display plain text, and add option to insert at beginning
Some checks failed
Node.js build / build (20.x) (push) Failing after 5m48s
Node.js build / build (22.x) (push) Failing after 5m45s
2026-02-20 16:16:30 -08:00
4 changed files with 38 additions and 14 deletions

View File

@@ -10,6 +10,7 @@ import {
collectTodoBlockLines, collectTodoBlockLines,
removeTodoBlock, removeTodoBlock,
moveTodoBlock, moveTodoBlock,
insertTodoAtBeginning,
} from './todo-transformer'; } from './todo-transformer';
describe('toggleTodo', () => { describe('toggleTodo', () => {
@@ -414,3 +415,21 @@ describe('moveTodoBlock', () => {
expect(result).toBe('- [ ] B\n - B1\n - B2\n- [ ] A\n- [ ] C'); expect(result).toBe('- [ ] B\n - B1\n - B2\n- [ ] A\n- [ ] C');
}); });
}); });
describe('insertTodoAtBeginning', () => {
it('should insert at the beginning of file content', () => {
const content = 'Line 1\nLine 2';
const result = insertTodoAtBeginning(content, '- [ ] New todo');
expect(result).toBe('- [ ] New todo\nLine 1\nLine 2');
});
it('should handle empty file', () => {
const result = insertTodoAtBeginning('', '- [ ] New todo');
expect(result).toBe('- [ ] New todo');
});
it('should handle file with only whitespace', () => {
const result = insertTodoAtBeginning('\n\n', '- [ ] New todo');
expect(result).toBe('- [ ] New todo\n\n\n');
});
});

View File

@@ -49,6 +49,16 @@ export function removeTodoLine(content: string, lineNumber: number): string {
return lines.join('\n'); return lines.join('\n');
} }
/**
* Insert a todo line at the beginning of the content.
*/
export function insertTodoAtBeginning(content: string, todoLine: string): string {
if (!content) {
return todoLine;
}
return todoLine + '\n' + content;
}
/** /**
* Insert a todo line at the end of the content. * Insert a todo line at the end of the content.
* Handles files with/without trailing newlines. * Handles files with/without trailing newlines.

View File

@@ -2,7 +2,7 @@ import { App, FuzzySuggestModal, TFile, HeadingCache } from 'obsidian';
import type { TodoItem } from '../core/types'; import type { TodoItem } from '../core/types';
import { import {
removeTodoBlock, removeTodoBlock,
insertTodoAtEnd, insertTodoAtBeginning,
insertTodoUnderHeading, insertTodoUnderHeading,
collectTodoBlockLines, collectTodoBlockLines,
} from '../core/todo-transformer'; } from '../core/todo-transformer';
@@ -30,24 +30,21 @@ export class HeadingSelectModal extends FuzzySuggestModal<HeadingOption> {
this.sourceFile = sourceFile; this.sourceFile = sourceFile;
this.targetFile = targetFile; this.targetFile = targetFile;
this.headings = headings; this.headings = headings;
this.setPlaceholder('Select a heading (or end of file)...'); this.setPlaceholder('Select a heading...');
} }
getItems(): HeadingOption[] { getItems(): HeadingOption[] {
const items: HeadingOption[] = []; const items: HeadingOption[] = [];
// Add "End of file" option first
items.push({ items.push({
heading: null, heading: null,
displayText: 'End of file', displayText: 'Beginning of file',
}); });
// Add all headings
for (const heading of this.headings) { for (const heading of this.headings) {
const indent = ' '.repeat(heading.level - 1);
items.push({ items.push({
heading, heading,
displayText: `${indent}${'#'.repeat(heading.level)} ${heading.heading}`, displayText: heading.heading,
}); });
} }
@@ -92,11 +89,10 @@ export class HeadingSelectModal extends FuzzySuggestModal<HeadingOption> {
); );
}); });
} else { } else {
// End of file // Beginning of file
await this.app.vault.process(this.targetFile, (content) => { await this.app.vault.process(this.targetFile, (content) => {
// Reconstruct block as a single string
const blockContent = blockLines.join('\n'); const blockContent = blockLines.join('\n');
return insertTodoAtEnd(content, blockContent); return insertTodoAtBeginning(content, blockContent);
}); });
} }
} }

View File

@@ -1,7 +1,7 @@
import { App, FuzzySuggestModal, TFile } from 'obsidian'; import { App, FuzzySuggestModal, TFile } from 'obsidian';
import type { TodoItem } from '../core/types'; import type { TodoItem } from '../core/types';
import { HeadingSelectModal } from './heading-select-modal'; import { HeadingSelectModal } from './heading-select-modal';
import { removeTodoBlock, insertTodoAtEnd, collectTodoBlockLines } from '../core/todo-transformer'; import { removeTodoBlock, insertTodoAtBeginning, collectTodoBlockLines } from '../core/todo-transformer';
export class NoteSelectModal extends FuzzySuggestModal<TFile> { export class NoteSelectModal extends FuzzySuggestModal<TFile> {
private todo: TodoItem; private todo: TodoItem;
@@ -37,7 +37,7 @@ export class NoteSelectModal extends FuzzySuggestModal<TFile> {
headings headings
).open(); ).open();
} else { } else {
// No headings - move directly to end of file // No headings - move directly to beginning of file
await this.moveTodo(file); await this.moveTodo(file);
} }
} }
@@ -61,9 +61,8 @@ export class NoteSelectModal extends FuzzySuggestModal<TFile> {
}); });
} else { } else {
await this.app.vault.process(targetFile, (content) => { await this.app.vault.process(targetFile, (content) => {
// Reconstruct block as a single string
const blockContent = blockLines.join('\n'); const blockContent = blockLines.join('\n');
return insertTodoAtEnd(content, blockContent); return insertTodoAtBeginning(content, blockContent);
}); });
} }
} }