Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/Queries/Layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ The `show tree` instruction enables us to see the parent/child relationships in

- For now, **all child tasks and list items are displayed**, regardless of whether they match the query.
- In the screenshot above, `Decide who to invite` did not match the `not done` query, but it is still shown.
- If you are using the Global Filter, any child tasks without the Global Filter are rendered without their checkbox. We are tracking this in [issue #3170](https://github.com/obsidian-tasks-group/obsidian-tasks/issues/3170).
- Any **sorting instructions only affect the sorting of the left-most tasks** in the results list.
- Child tasks and list items are displayed in the order that they appear in the file. They are not affected by any `sort by` instructions.
- For now, the **tree layout is turned off by default**, whilst we explore how it should interact with the filtering instructions.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- [ ] #task task parent
- [ ] #task task child
- [ ] non-task child
- list item child

```tasks
filename includes {{query.file.filename}}
show tree
```
11 changes: 9 additions & 2 deletions src/Obsidian/FileParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ export class FileParser {
sectionIndex: number,
) {
if (listItem.task === undefined) {
const parentListItem: ListItem | null = this.line2ListItem.get(listItem.parent) ?? null;
this.line2ListItem.set(lineNumber, new ListItem(line, parentListItem));
this.createListItem(listItem, line, lineNumber);
return sectionIndex;
}
let task;
Expand Down Expand Up @@ -148,10 +147,18 @@ export class FileParser {
sectionIndex++;
this.tasks.push(task);
}
} else {
// Treat tasks without the global filter as list items
this.createListItem(listItem, line, lineNumber);
}
} catch (e) {
this.errorReporter(e, this.filePath, listItem, line);
}
return sectionIndex;
}

private createListItem(listItem: ListItemCache, line: string, lineNumber: number) {
const parentListItem: ListItem | null = this.line2ListItem.get(listItem.parent) ?? null;
this.line2ListItem.set(lineNumber, new ListItem(line, parentListItem));
}
}
8 changes: 8 additions & 0 deletions src/Task/ListItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ export class ListItem {
public readonly parent: ListItem | null = null;
public readonly children: ListItem[] = [];
public readonly description: string;
public readonly statusCharacter: string | null = null;

constructor(originalMarkdown: string, parent: ListItem | null) {
this.description = originalMarkdown.replace(TaskRegularExpressions.listItemRegex, '').trim();
const nonTaskMatch = RegExp(TaskRegularExpressions.nonTaskRegex).exec(originalMarkdown);
if (nonTaskMatch) {
this.description = nonTaskMatch[5].trim();
this.statusCharacter = nonTaskMatch[4] ?? null;
}
this.originalMarkdown = originalMarkdown;
this.parent = parent;

Expand Down Expand Up @@ -87,6 +93,8 @@ export class ListItem {
return false;
}

// Not testing status character as it is implied from the original markdown

return ListItem.listsAreIdentical(this.children, other.children);
}

Expand Down
6 changes: 6 additions & 0 deletions src/Task/TaskRegularExpressions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ export class TaskRegularExpressions {
);

// Used with the "Create or Edit Task" command to parse indentation and status if present
// It matches the following:
// - Indentation
// - List marker
// - Checkbox with status character
// - Status character
// - Rest of task after checkbox markdown
public static readonly nonTaskRegex = new RegExp(
TaskRegularExpressions.indentationRegex.source +
TaskRegularExpressions.listMarkerRegex.source +
Expand Down
2 changes: 2 additions & 0 deletions tests/Obsidian/AllCacheSampleData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import inheritance_2siblings from './__test_data__/inheritance_2siblings.json';
import inheritance_listitem_listitem_task from './__test_data__/inheritance_listitem_listitem_task.json';
import inheritance_listitem_task from './__test_data__/inheritance_listitem_task.json';
import inheritance_listitem_task_siblings from './__test_data__/inheritance_listitem_task_siblings.json';
import inheritance_non_task_child from './__test_data__/inheritance_non_task_child.json';
import inheritance_rendering_sample from './__test_data__/inheritance_rendering_sample.json';
import inheritance_task_2listitem_3task from './__test_data__/inheritance_task_2listitem_3task.json';
import inheritance_task_listitem from './__test_data__/inheritance_task_listitem.json';
Expand Down Expand Up @@ -96,6 +97,7 @@ export function allCacheSampleData() {
inheritance_listitem_listitem_task,
inheritance_listitem_task,
inheritance_listitem_task_siblings,
inheritance_non_task_child,
inheritance_rendering_sample,
inheritance_task_2listitem_3task,
inheritance_task_listitem,
Expand Down
35 changes: 35 additions & 0 deletions tests/Obsidian/Cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import moment from 'moment/moment';
import type { CachedMetadata } from 'obsidian';
import { GlobalFilter } from '../../src/Config/GlobalFilter';
import type { ListItem } from '../../src/Task/ListItem';
import { getTasksFileFromMockData, listPathAndData } from '../TestingTools/MockDataHelpers';
import inheritance_1parent1child from './__test_data__/inheritance_1parent1child.json';
Expand All @@ -19,6 +20,7 @@ import inheritance_2siblings from './__test_data__/inheritance_2siblings.json';
import inheritance_listitem_listitem_task from './__test_data__/inheritance_listitem_listitem_task.json';
import inheritance_listitem_task from './__test_data__/inheritance_listitem_task.json';
import inheritance_listitem_task_siblings from './__test_data__/inheritance_listitem_task_siblings.json';
import inheritance_non_task_child from './__test_data__/inheritance_non_task_child.json';
import inheritance_task_2listitem_3task from './__test_data__/inheritance_task_2listitem_3task.json';
import inheritance_task_listitem from './__test_data__/inheritance_task_listitem.json';
import inheritance_task_listitem_mixed_grandchildren from './__test_data__/inheritance_task_listitem_mixed_grandchildren.json';
Expand Down Expand Up @@ -95,6 +97,10 @@ function printRoots(listItems: ListItem[]) {
return rootHierarchies;
}

afterEach(() => {
GlobalFilter.getInstance().reset();
});

describe('cache', () => {
it('should read one task', () => {
const tasks = readTasksFromSimulatedFile(one_task);
Expand Down Expand Up @@ -480,6 +486,35 @@ describe('cache', () => {
`);
});

it('should read non task check box when global filter is enabled', () => {
GlobalFilter.getInstance().set('#task');

const data = inheritance_non_task_child;
const tasks = readTasksFromSimulatedFile(data);
expect(data.fileContents).toMatchInlineSnapshot(`
"- [ ] #task task parent
- [ ] #task task child
- [ ] non-task child
- list item child

\`\`\`tasks
filename includes {{query.file.filename}}
show tree
\`\`\`
"
`);

expect(tasks.length).toEqual(2);

expect(printRoots(tasks)).toMatchInlineSnapshot(`
"- [ ] #task task parent : Task
- [ ] #task task child : Task
- [ ] non-task child : ListItem
- list item child : ListItem
"
`);
});

it('callout', () => {
const tasks = readTasksFromSimulatedFile(callout);
expect(callout.fileContents).toMatchInlineSnapshot(`
Expand Down
141 changes: 141 additions & 0 deletions tests/Obsidian/__test_data__/inheritance_non_task_child.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"cachedMetadata": {
"listItems": [
{
"parent": -1,
"position": {
"end": {
"col": 24,
"line": 0,
"offset": 24
},
"start": {
"col": 0,
"line": 0,
"offset": 0
}
},
"task": " "
},
{
"parent": 0,
"position": {
"end": {
"col": 26,
"line": 1,
"offset": 51
},
"start": {
"col": 3,
"line": 1,
"offset": 28
}
},
"task": " "
},
{
"parent": 0,
"position": {
"end": {
"col": 24,
"line": 2,
"offset": 76
},
"start": {
"col": 3,
"line": 2,
"offset": 55
}
},
"task": " "
},
{
"parent": 0,
"position": {
"end": {
"col": 21,
"line": 3,
"offset": 98
},
"start": {
"col": 3,
"line": 3,
"offset": 80
}
}
}
],
"sections": [
{
"position": {
"end": {
"col": 21,
"line": 3,
"offset": 98
},
"start": {
"col": 0,
"line": 0,
"offset": 0
}
},
"type": "list"
},
{
"position": {
"end": {
"col": 3,
"line": 8,
"offset": 164
},
"start": {
"col": 0,
"line": 5,
"offset": 100
}
},
"type": "code"
}
],
"tags": [
{
"position": {
"end": {
"col": 12,
"line": 0,
"offset": 12
},
"start": {
"col": 7,
"line": 0,
"offset": 7
}
},
"tag": "#task"
},
{
"position": {
"end": {
"col": 15,
"line": 1,
"offset": 40
},
"start": {
"col": 10,
"line": 1,
"offset": 35
}
},
"tag": "#task"
}
]
},
"fileContents": "- [ ] #task task parent\n - [ ] #task task child\n - [ ] non-task child\n - list item child\n\n```tasks\nfilename includes {{query.file.filename}}\nshow tree\n```\n",
"filePath": "Test Data/inheritance_non_task_child.md",
"getAllTags": [
"#task",
"#task"
],
"obsidianApiVersion": "1.8.0",
"parseFrontMatterTags": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!--
- [ ] #task task parent
- [ ] #task task child
-->

<div>
<ul class="contains-task-list plugin-tasks-query-result tasks-layout-hide-urgency">
<li
class="task-list-item plugin-tasks-list-item"
data-task-priority="normal"
data-task=""
data-line="0"
data-task-status-name="Todo"
data-task-status-type="TODO">
<input class="task-list-item-checkbox" type="checkbox" title="Right-click for options" data-line="0" />
<span class="tasks-list-text">
<span class="task-description"><span>#task task parent</span></span>
</span>
<span class="task-extras">
<span class="tasks-backlink">
(
<a rel="noopener" target="_blank" class="internal-link">inheritance_non_task_child</a>
)
</span>
<a class="tasks-edit" title="Edit task" href="#"></a>
</span>
<ul class="contains-task-list plugin-tasks-query-result tasks-layout-hide-urgency">
<li
class="task-list-item plugin-tasks-list-item"
data-task-priority="normal"
data-task=""
data-line="0"
data-task-status-name="Todo"
data-task-status-type="TODO">
<input class="task-list-item-checkbox" type="checkbox" title="Right-click for options" data-line="0" />
<span class="tasks-list-text">
<span class="task-description"><span>#task task child</span></span>
</span>
<span class="task-extras">
<span class="tasks-backlink">
(
<a rel="noopener" target="_blank" class="internal-link">inheritance_non_task_child</a>
)
</span>
<a class="tasks-edit" title="Edit task" href="#"></a>
</span>
</li>
<li><span>non-task child</span></li>
<li><span>list item child</span></li>
</ul>
</li>
</ul>
<div class="task-count">2 tasks</div>
</div>
9 changes: 9 additions & 0 deletions tests/Renderer/QueryResultsRenderer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
*/
import moment from 'moment';
import type { Task } from 'Task/Task';
import { GlobalFilter } from '../../src/Config/GlobalFilter';
import { State } from '../../src/Obsidian/Cache';
import { QueryResultsRenderer } from '../../src/Renderer/QueryResultsRenderer';
import { TasksFile } from '../../src/Scripting/TasksFile';
import inheritance_non_task_child from '../Obsidian/__test_data__/inheritance_non_task_child.json';
import inheritance_rendering_sample from '../Obsidian/__test_data__/inheritance_rendering_sample.json';
import inheritance_task_2listitem_3task from '../Obsidian/__test_data__/inheritance_task_2listitem_3task.json';
import { readTasksFromSimulatedFile } from '../Obsidian/SimulatedFile';
Expand All @@ -24,6 +26,7 @@ beforeEach(() => {

afterEach(() => {
jest.useRealTimers();
GlobalFilter.getInstance().reset();
});

function makeQueryResultsRenderer(source: string, tasksFile: TasksFile) {
Expand Down Expand Up @@ -92,6 +95,12 @@ ${toMarkdown(allTasks)}
const allTasks = readTasksFromSimulatedFile(inheritance_task_2listitem_3task);
await verifyRenderedTasksHTML(allTasks, showTree + 'description includes grandchild');
});

it('should render non task check box when global filter is enabled', async () => {
GlobalFilter.getInstance().set('#task');
const allTasks = readTasksFromSimulatedFile(inheritance_non_task_child);
await verifyRenderedTasksHTML(allTasks, showTree);
});
});

describe('QueryResultsRenderer - responding to file edits', () => {
Expand Down
Loading
Loading