Added new "tasks" built-in plug
This commit is contained in:
parent
66c21c4c6b
commit
d0431bbd99
@ -1,17 +1,5 @@
|
|||||||
name: core
|
name: core
|
||||||
syntax:
|
syntax:
|
||||||
HashTag:
|
|
||||||
firstCharacters:
|
|
||||||
- "#"
|
|
||||||
regex: "#[A-Za-z\\.]+"
|
|
||||||
styles:
|
|
||||||
color: blue
|
|
||||||
AtMention:
|
|
||||||
firstCharacters:
|
|
||||||
- "@"
|
|
||||||
regex: "@[A-Za-z\\.]+"
|
|
||||||
styles:
|
|
||||||
color: blue
|
|
||||||
NakedURL:
|
NakedURL:
|
||||||
firstCharacters:
|
firstCharacters:
|
||||||
- "h"
|
- "h"
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
queryPrefix,
|
queryPrefix,
|
||||||
} from "@silverbulletmd/plugos-silverbullet-syscall";
|
} from "@silverbulletmd/plugos-silverbullet-syscall";
|
||||||
import {
|
import {
|
||||||
|
addParentPointers,
|
||||||
collectNodesOfType,
|
collectNodesOfType,
|
||||||
findNodeOfType,
|
findNodeOfType,
|
||||||
ParseTree,
|
ParseTree,
|
||||||
@ -67,7 +68,22 @@ export function extractMeta(
|
|||||||
removeKeys: string[] = []
|
removeKeys: string[] = []
|
||||||
): any {
|
): any {
|
||||||
let data: any = {};
|
let data: any = {};
|
||||||
|
addParentPointers(parseTree);
|
||||||
replaceNodesMatching(parseTree, (t) => {
|
replaceNodesMatching(parseTree, (t) => {
|
||||||
|
if (t.type === "Hashtag") {
|
||||||
|
// Check if if nested directly into a Paragraph
|
||||||
|
if (t.parent && t.parent.type === "Paragraph") {
|
||||||
|
let tagname = t.children![0].text;
|
||||||
|
if (!data.tags) {
|
||||||
|
data.tags = [];
|
||||||
|
}
|
||||||
|
if (!data.tags.includes(tagname)) {
|
||||||
|
data.tags.push(tagname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Find a fenced code block
|
||||||
if (t.type !== "FencedCode") {
|
if (t.type !== "FencedCode") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
17
packages/plugs/tags/tags.plug.yaml
Normal file
17
packages/plugs/tags/tags.plug.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: tags
|
||||||
|
syntax:
|
||||||
|
Hashtag:
|
||||||
|
firstCharacters:
|
||||||
|
- "#"
|
||||||
|
regex: "#[^#\\s]+"
|
||||||
|
styles:
|
||||||
|
color: blue
|
||||||
|
functions:
|
||||||
|
indexTags:
|
||||||
|
path: "./tags.ts:indexTags"
|
||||||
|
events:
|
||||||
|
- page:index
|
||||||
|
tagComplete:
|
||||||
|
path: "./tags.ts:tagComplete"
|
||||||
|
events:
|
||||||
|
- page:complete
|
39
packages/plugs/tags/tags.ts
Normal file
39
packages/plugs/tags/tags.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { collectNodesOfType } from "@silverbulletmd/common/tree";
|
||||||
|
import {
|
||||||
|
batchSet,
|
||||||
|
queryPrefix,
|
||||||
|
} from "@silverbulletmd/plugos-silverbullet-syscall";
|
||||||
|
import { matchBefore } from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||||
|
import type { IndexTreeEvent } from "@silverbulletmd/web/app_event";
|
||||||
|
import { removeQueries } from "../query/util";
|
||||||
|
|
||||||
|
// Key space
|
||||||
|
// ht:TAG => true (for completion)
|
||||||
|
|
||||||
|
export async function indexTags({ name, tree }: IndexTreeEvent) {
|
||||||
|
removeQueries(tree);
|
||||||
|
let allTags = new Set<string>();
|
||||||
|
collectNodesOfType(tree, "Hashtag").forEach((n) => {
|
||||||
|
allTags.add(n.children![0].text!);
|
||||||
|
});
|
||||||
|
batchSet(
|
||||||
|
name,
|
||||||
|
[...allTags].map((t) => ({ key: `ht:${t}`, value: t }))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function tagComplete() {
|
||||||
|
let prefix = await matchBefore("#[^#\\s]+");
|
||||||
|
// console.log("Running tag complete", prefix);
|
||||||
|
if (!prefix) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let allTags = await queryPrefix(`ht:${prefix.text}`);
|
||||||
|
return {
|
||||||
|
from: prefix.from,
|
||||||
|
options: allTags.map((tag) => ({
|
||||||
|
label: tag.value,
|
||||||
|
type: "tag",
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
@ -23,6 +23,7 @@ import {
|
|||||||
nodeAtPos,
|
nodeAtPos,
|
||||||
ParseTree,
|
ParseTree,
|
||||||
renderToText,
|
renderToText,
|
||||||
|
replaceNodesMatching,
|
||||||
} from "@silverbulletmd/common/tree";
|
} from "@silverbulletmd/common/tree";
|
||||||
import { removeQueries } from "../query/util";
|
import { removeQueries } from "../query/util";
|
||||||
import { applyQuery, QueryProviderEvent, renderQuery } from "../query/engine";
|
import { applyQuery, QueryProviderEvent, renderQuery } from "../query/engine";
|
||||||
@ -32,6 +33,7 @@ export type Task = {
|
|||||||
name: string;
|
name: string;
|
||||||
done: boolean;
|
done: boolean;
|
||||||
deadline?: string;
|
deadline?: string;
|
||||||
|
tags?: string[];
|
||||||
nested?: string;
|
nested?: string;
|
||||||
// Not saved in DB, just added when pulled out (from key)
|
// Not saved in DB, just added when pulled out (from key)
|
||||||
pos?: number;
|
pos?: number;
|
||||||
@ -47,28 +49,40 @@ export async function indexTasks({ name, tree }: IndexTreeEvent) {
|
|||||||
let tasks: { key: string; value: Task }[] = [];
|
let tasks: { key: string; value: Task }[] = [];
|
||||||
removeQueries(tree);
|
removeQueries(tree);
|
||||||
collectNodesOfType(tree, "Task").forEach((n) => {
|
collectNodesOfType(tree, "Task").forEach((n) => {
|
||||||
let task = n.children!.slice(1).map(renderToText).join("").trim();
|
|
||||||
let complete = n.children![0].children![0].text! !== "[ ]";
|
let complete = n.children![0].children![0].text! !== "[ ]";
|
||||||
let value: Task = {
|
let task: Task = {
|
||||||
name: task,
|
name: "",
|
||||||
done: complete,
|
done: complete,
|
||||||
};
|
};
|
||||||
|
|
||||||
let deadlineNode = findNodeOfType(n, "DeadlineDate");
|
replaceNodesMatching(n, (tree) => {
|
||||||
if (deadlineNode) {
|
if (tree.type === "DeadlineDate") {
|
||||||
value.deadline = getDeadline(deadlineNode);
|
task.deadline = getDeadline(tree);
|
||||||
}
|
// Remove this node from the tree
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (tree.type === "Hashtag") {
|
||||||
|
if (!task.tags) {
|
||||||
|
task.tags = [];
|
||||||
|
}
|
||||||
|
task.tags.push(tree.children![0].text!);
|
||||||
|
// Remove this node from the tree
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
task.name = n.children!.slice(1).map(renderToText).join("").trim();
|
||||||
|
|
||||||
let taskIndex = n.parent!.children!.indexOf(n);
|
let taskIndex = n.parent!.children!.indexOf(n);
|
||||||
let nestedItems = n.parent!.children!.slice(taskIndex + 1);
|
let nestedItems = n.parent!.children!.slice(taskIndex + 1);
|
||||||
if (nestedItems.length > 0) {
|
if (nestedItems.length > 0) {
|
||||||
value.nested = nestedItems.map(renderToText).join("").trim();
|
task.nested = nestedItems.map(renderToText).join("").trim();
|
||||||
}
|
}
|
||||||
tasks.push({
|
tasks.push({
|
||||||
key: `task:${n.from}`,
|
key: `task:${n.from}`,
|
||||||
value,
|
value: task,
|
||||||
});
|
});
|
||||||
// console.log("Task", value);
|
console.log("Task", task);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Found", tasks.length, "task(s)");
|
console.log("Found", tasks.length, "task(s)");
|
||||||
|
Loading…
Reference in New Issue
Block a user