Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hooks to let other plugins extend the Tasks plugin. #1249

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
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