Skip to content
Draft
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
19 changes: 17 additions & 2 deletions src/Query/Query.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LayoutOptions } from '../TaskLayout';
import type { ExtendParserHook } from 'QueryRenderer';
import { LayoutOptions } from '../LayoutOptions';
import type { Task } from '../Task';
import type { IQuery } from '../IQuery';
import { getSettings } from '../Config/Settings';
Expand Down Expand Up @@ -50,7 +51,7 @@ export class Query implements IQuery {

private readonly commentRegexp = /^#.*/;

constructor({ source }: { source: string }) {
constructor({ source, extensions = [] }: { source: string; extensions?: ExtendParserHook[] }) {
this.source = source;
source
.split('\n')
Expand Down Expand Up @@ -81,6 +82,8 @@ export class Query implements IQuery {
break;
case this.parseFilter(line):
break;
case this.parseExtensions(extensions, line):
break;
default:
this._error = `do not understand query: ${line}`;
}
Expand Down Expand Up @@ -235,4 +238,16 @@ export class Query implements IQuery {
this._error = 'do not understand query grouping';
}
}

private parseExtensions(extensions: ExtendParserHook[], line: string): boolean {
let found = false;
// Let plugins that implement the "extendParse" hook parse the given
// line
extensions.forEach((extendParser: ExtendParserHook) => {
if (extendParser(line, this.layoutOptions)) {
found = true;
}
});
return found;
}
}
39 changes: 36 additions & 3 deletions src/QueryRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { replaceTaskWithTasks } from './File';
import { Query } from './Query/Query';
import type { GroupHeading } from './Query/GroupHeading';
import { TaskModal } from './TaskModal';
import { Task as TaskModel } from './Task';
import type { TasksEvents } from './TasksEvents';
import type { Task } from './Task';
import { DateFallback } from './DateFallback';
Expand Down Expand Up @@ -37,6 +38,9 @@ export class QueryRenderer {
}
}

export type ExtendTaskHook = (listItem: HTMLLIElement, task: Task, api: object) => void;
export type ExtendParserHook = (line: string, layoutOptions: object) => boolean;

class QueryRenderChild extends MarkdownRenderChild {
private readonly app: App;
private readonly events: TasksEvents;
Expand All @@ -48,6 +52,9 @@ class QueryRenderChild extends MarkdownRenderChild {
private renderEventRef: EventRef | undefined;
private queryReloadTimeout: NodeJS.Timeout | undefined;

private extendTask: ExtendTaskHook[];
private extendParser: ExtendParserHook[];

constructor({
app,
events,
Expand All @@ -67,18 +74,34 @@ class QueryRenderChild extends MarkdownRenderChild {
this.events = events;
this.source = source;
this.filePath = filePath;
this.extendTask = [];
this.extendParser = [];

// Cache which plugins implement our extension hooks
// @ts-ignore
Object.keys(this.app.plugins.plugins).forEach((name) => {
// @ts-ignore
const plugin = this.app.plugins.plugins[name];
if (plugin.extendTask) {
this.extendTask.push(plugin.extendTask);
}

if (plugin.extendParser) {
this.extendParser.push(plugin.extendParser);
}
});

// The engine is chosen on the basis of the code block language. Currently
// there is only the main engine for the plugin, this allows others to be
// added later.
switch (this.containerEl.className) {
case 'block-language-tasks':
this.query = new Query({ source });
this.query = new Query({ source, extensions: this.extendParser });
this.queryType = 'tasks';
break;

default:
this.query = new Query({ source });
this.query = new Query({ source, extensions: this.extendParser });
this.queryType = 'tasks';
break;
}
Expand Down Expand Up @@ -119,7 +142,7 @@ class QueryRenderChild extends MarkdownRenderChild {
const millisecondsToMidnight = midnight.getTime() - now.getTime();

this.queryReloadTimeout = setTimeout(() => {
this.query = new Query({ source: this.source });
this.query = new Query({ source: this.source, extensions: this.extendParser });
// Process the current cache state:
this.events.triggerRequestCacheUpdate(this.render.bind(this));
this.reloadQueryAtMidnight();
Expand Down Expand Up @@ -215,6 +238,16 @@ class QueryRenderChild extends MarkdownRenderChild {
this.addEditButton(listItem, task);
}

// Let plugins that implement the "extendTask" hook extend the
// current task
this.extendTask.forEach((extendTask: ExtendTaskHook) =>
extendTask(listItem, task, {
layoutOptions: this.query.layoutOptions,
Task: TaskModel,
replaceTaskWithTasks,
}),
);

taskList.appendChild(listItem);
}

Expand Down