Update headings list to display plain text, and add option to insert at beginning
This commit is contained in:
@@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user