Skip to content

Commit 819b4b3

Browse files
authored
Merge pull request #40 from joeriddles/support-comments
feat: support both comment styles for exclude
2 parents 0793f78 + a9ba903 commit 819b4b3

3 files changed

Lines changed: 94 additions & 15 deletions

File tree

src/settings.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ const DEFAULT_SETTINGS: ExtendedTaskListsSettings = {
2424
excludeNestedFromParent: true,
2525
excludeFilePattern: "<!-- exclude TODO -->",
2626
excludeFolderFilename: ".exclude_todos",
27-
excludeRegionBegin: "%% exclude: start %%",
28-
excludeRegionEnd: "%% exclude: end %%",
27+
excludeRegionBegin: "<!-- exclude: start -->",
28+
excludeRegionEnd: "<!-- exclude: end -->",
2929
includeNotStarted: true,
3030
includeInProgress: true,
3131
includeWontDo: false,
@@ -120,29 +120,29 @@ class ExtendedTaskListsSettingTab extends PluginSettingTab {
120120
new Setting(containerEl).setName("Excludes").setHeading();
121121

122122
new Setting(containerEl)
123-
.setName("Exclude file pattern")
123+
.setName("Exclude folder filename")
124124
.setDesc(
125-
"A pattern that should be inserted anywhere in a Markdown file to exclude it from the generated TODO file.",
125+
'The filename to add to a folder to exclude all task lists in it from the generated TODO file. You may prefer to change the default value since dot files (files that start with a ".") do not show up within Obsidian.',
126126
)
127127
.addText((text) =>
128128
text
129-
.setValue(this.plugin.settings.excludeFilePattern)
129+
.setValue(this.plugin.settings.excludeFolderFilename)
130130
.onChange(async (value) => {
131-
this.plugin.settings.excludeFilePattern = value;
131+
this.plugin.settings.excludeFolderFilename = value;
132132
await this.plugin.saveSettings();
133133
}),
134134
);
135135

136136
new Setting(containerEl)
137-
.setName("Exclude folder filename")
137+
.setName("Exclude file pattern")
138138
.setDesc(
139-
'The filename to add to a folder to exclude all task lists in it from the generated TODO file. You may prefer to change the default value since dot files (files that start with a ".") do not show up within Obsidian.',
139+
"A pattern that should be inserted anywhere in a Markdown file to exclude it from the generated TODO file.",
140140
)
141141
.addText((text) =>
142142
text
143-
.setValue(this.plugin.settings.excludeFolderFilename)
143+
.setValue(this.plugin.settings.excludeFilePattern)
144144
.onChange(async (value) => {
145-
this.plugin.settings.excludeFolderFilename = value;
145+
this.plugin.settings.excludeFilePattern = value;
146146
await this.plugin.saveSettings();
147147
}),
148148
);

src/todoService.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,27 @@ class MockFileService implements IFileService {
101101
}
102102

103103
describe("TodoService", () => {
104+
test("findTodosFiles excludes files with alternate comment style", async () => {
105+
// Arrange
106+
const taskFile = createMockFile("test.md", "- [ ] task item");
107+
const fileWithObsidianExclude = createMockFile(
108+
"Exclude.md",
109+
"%% exclude TODO %%",
110+
);
111+
112+
const files = [taskFile, fileWithObsidianExclude];
113+
const mockFileService = new MockFileService(files);
114+
115+
// Act
116+
const todoService = new TodoService(mockFileService, MOCK_SETTINGS);
117+
const actual = await todoService.findTodosFiles();
118+
119+
// Assert
120+
expect(actual).toEqual([
121+
{ file: taskFile, contents: "- [ ] task item" } as TodoFile,
122+
]);
123+
});
124+
104125
test("findTodosFiles excludes files", async () => {
105126
// Arrange
106127
const taskFile = createMockFile("test.md", "- [ ] task item");
@@ -385,6 +406,38 @@ describe("TodoService", () => {
385406
expect(actual).toEqual(expected);
386407
});
387408

409+
test("parseTodos excludes task items inside HTML-style exclude regions", () => {
410+
// Arrange
411+
const content = `- [ ] Included
412+
<!-- exclude: start -->
413+
- [ ] Excluded
414+
- [.] Also excluded
415+
<!-- exclude: end -->
416+
- [ ] Also included`;
417+
418+
const mockFileService = new MockFileService([]);
419+
420+
// Act
421+
const todoService = new TodoService(mockFileService, MOCK_SETTINGS);
422+
const actual = todoService.parseTodos(content);
423+
424+
// Assert
425+
expect(actual).toEqual([
426+
{
427+
task: TaskType.NotStarted,
428+
text: "Included",
429+
indentation: "",
430+
lineno: 0,
431+
} as Todo,
432+
{
433+
task: TaskType.NotStarted,
434+
text: "Also included",
435+
indentation: "",
436+
lineno: 5,
437+
} as Todo,
438+
]);
439+
});
440+
388441
test("parseTodos excludes task items inside exclude regions", () => {
389442
// Arrange
390443
const content = `- [ ] Included

src/todoService.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ interface IndexMatch {
3333
const TODO_PATTERN = /^(?<indentation>\s*)-\s?\[(?<task>.)\]\s+(?<text>.*)$/;
3434
const LINK_PATTERN = /^- \[.*\]\((?<path>.*)\)$/;
3535

36+
function alternateCommentStyle(pattern: string): string | null {
37+
const obsidianMatch = pattern.match(/^%%\s*(.*?)\s*%%$/);
38+
if (obsidianMatch) {
39+
return `<!-- ${obsidianMatch[1]} -->`;
40+
}
41+
const htmlMatch = pattern.match(/^<!--\s*(.*?)\s*-->$/);
42+
if (htmlMatch) {
43+
return `%% ${htmlMatch[1]} %%`;
44+
}
45+
return null;
46+
}
47+
48+
function matchesEitherCommentStyle(line: string, pattern: string): boolean {
49+
if (line === pattern) return true;
50+
const alt = alternateCommentStyle(pattern);
51+
return alt != null && line === alt;
52+
}
53+
3654
class TodoService {
3755
private fileService: IFileService;
3856
private settings: ExtendedTaskListsSettings;
@@ -72,9 +90,11 @@ class TodoService {
7290
(todoFile) =>
7391
!todoFile.contents
7492
.split(/[\r\n]+/)
75-
.some(
76-
(line) =>
77-
line.trim() === this.settings.excludeFilePattern,
93+
.some((line) =>
94+
matchesEitherCommentStyle(
95+
line.trim(),
96+
this.settings.excludeFilePattern,
97+
),
7898
),
7999
);
80100
return todoFiles;
@@ -142,11 +162,17 @@ class TodoService {
142162
let inExcludedRegion = false;
143163
const matchesAndIndices = lines
144164
.map((line, index) => {
145-
if (beginPattern && line.trim() === beginPattern) {
165+
if (
166+
beginPattern &&
167+
matchesEitherCommentStyle(line.trim(), beginPattern)
168+
) {
146169
inExcludedRegion = true;
147170
}
148171
if (inExcludedRegion) {
149-
if (endPattern && line.trim() === endPattern) {
172+
if (
173+
endPattern &&
174+
matchesEitherCommentStyle(line.trim(), endPattern)
175+
) {
150176
inExcludedRegion = false;
151177
}
152178
return {

0 commit comments

Comments
 (0)