Initial commit
This commit is contained in:
98
src/core/todo-transformer.ts
Normal file
98
src/core/todo-transformer.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Regex pattern for markdown todo checkboxes (for toggling).
|
||||
*/
|
||||
const TODO_PATTERN = /^(\s*[-*+]\s+\[)([xX ]?)(\].*)$/;
|
||||
|
||||
/**
|
||||
* Toggle the checkbox state at the specified line number.
|
||||
* Returns the modified content.
|
||||
*/
|
||||
export function toggleTodo(content: string, lineNumber: number): string {
|
||||
const lines = content.split('\n');
|
||||
|
||||
if (lineNumber < 0 || lineNumber >= lines.length) {
|
||||
return content;
|
||||
}
|
||||
|
||||
const line = lines[lineNumber];
|
||||
if (line === undefined) {
|
||||
return content;
|
||||
}
|
||||
|
||||
const match = line.match(TODO_PATTERN);
|
||||
if (!match) {
|
||||
return content;
|
||||
}
|
||||
|
||||
const checkboxContent = match[2];
|
||||
const isChecked = checkboxContent === 'x' || checkboxContent === 'X';
|
||||
const newCheckbox = isChecked ? ' ' : 'x';
|
||||
|
||||
lines[lineNumber] = `${match[1]}${newCheckbox}${match[3]}`;
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the line at the specified line number.
|
||||
* Returns the modified content.
|
||||
*/
|
||||
export function removeTodoLine(content: string, lineNumber: number): string {
|
||||
const lines = content.split('\n');
|
||||
|
||||
if (lineNumber < 0 || lineNumber >= lines.length) {
|
||||
return content;
|
||||
}
|
||||
|
||||
lines.splice(lineNumber, 1);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a todo line at the end of the content.
|
||||
* Handles files with/without trailing newlines.
|
||||
*/
|
||||
export function insertTodoAtEnd(content: string, todoLine: string): string {
|
||||
if (!content) {
|
||||
return todoLine;
|
||||
}
|
||||
|
||||
// If content ends with newline(s), append directly
|
||||
if (content.endsWith('\n')) {
|
||||
return content + todoLine;
|
||||
}
|
||||
|
||||
// Otherwise add a newline before the todo
|
||||
return content + '\n' + todoLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a todo line under a specific heading.
|
||||
* @param content - The file content
|
||||
* @param headingLineNumber - The line number of the heading (0-based)
|
||||
* @param todoLine - The todo line to insert
|
||||
* @param nextHeadingLineNumber - Optional line number of the next heading (for section boundary)
|
||||
*/
|
||||
export function insertTodoUnderHeading(
|
||||
content: string,
|
||||
headingLineNumber: number,
|
||||
todoLine: string,
|
||||
nextHeadingLineNumber?: number
|
||||
): string {
|
||||
const lines = content.split('\n');
|
||||
|
||||
// Determine where to insert
|
||||
let insertPosition: number;
|
||||
|
||||
if (nextHeadingLineNumber !== undefined) {
|
||||
// Insert just before the next heading (at the end of this section)
|
||||
insertPosition = nextHeadingLineNumber;
|
||||
} else {
|
||||
// No next heading - insert right after the heading line
|
||||
insertPosition = headingLineNumber + 1;
|
||||
}
|
||||
|
||||
// Insert the todo line
|
||||
lines.splice(insertPosition, 0, todoLine);
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
Reference in New Issue
Block a user