2022-04-05 15:02:17 +00:00
|
|
|
import { flashNotification, getCurrentPage, reloadPage, save } from "plugos-silverbullet-syscall/editor";
|
2022-04-01 15:07:08 +00:00
|
|
|
|
2022-04-05 15:02:17 +00:00
|
|
|
import { listPages, readPage, writePage } from "plugos-silverbullet-syscall/space";
|
|
|
|
import { invokeFunction } from "plugos-silverbullet-syscall/system";
|
|
|
|
import { scanPrefixGlobal } from "plugos-silverbullet-syscall";
|
2022-04-11 18:34:09 +00:00
|
|
|
import { niceDate } from "../core/dates";
|
2022-04-12 11:33:07 +00:00
|
|
|
import { applyQuery, parseQuery } from "./engine";
|
|
|
|
import { PageMeta } from "../../common/types";
|
|
|
|
import type { Task } from "../tasks/task";
|
|
|
|
import { Item } from "../core/item";
|
|
|
|
import YAML from "yaml";
|
2022-03-29 15:02:28 +00:00
|
|
|
|
|
|
|
export const queryRegex =
|
2022-04-12 11:33:07 +00:00
|
|
|
/(<!--\s*#query\s+(.+?)-->)(.+?)(<!--\s*#end\s*-->)/gs;
|
2022-04-11 18:34:09 +00:00
|
|
|
|
2022-03-29 15:02:28 +00:00
|
|
|
export function whiteOutQueries(text: string): string {
|
2022-04-12 11:33:07 +00:00
|
|
|
return text.replaceAll(queryRegex, (match) =>
|
2022-03-29 15:02:28 +00:00
|
|
|
new Array(match.length + 1).join(" ")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function replaceAsync(
|
|
|
|
str: string,
|
|
|
|
regex: RegExp,
|
|
|
|
asyncFn: (match: string, ...args: any[]) => Promise<string>
|
|
|
|
) {
|
|
|
|
const promises: Promise<string>[] = [];
|
|
|
|
str.replace(regex, (match: string, ...args: any[]): string => {
|
|
|
|
const promise = asyncFn(match, ...args);
|
|
|
|
promises.push(promise);
|
|
|
|
return "";
|
|
|
|
});
|
|
|
|
const data = await Promise.all(promises);
|
|
|
|
return str.replace(regex, () => data.shift()!);
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function updateMaterializedQueriesCommand() {
|
2022-04-01 15:07:08 +00:00
|
|
|
const currentPage = await getCurrentPage();
|
|
|
|
await save();
|
2022-04-05 15:02:17 +00:00
|
|
|
await invokeFunction(
|
|
|
|
"server",
|
|
|
|
"updateMaterializedQueriesOnPage",
|
|
|
|
currentPage
|
|
|
|
);
|
2022-04-01 15:07:08 +00:00
|
|
|
await reloadPage();
|
|
|
|
await flashNotification("Updated materialized queries");
|
2022-03-29 15:02:28 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 18:34:09 +00:00
|
|
|
function replaceTemplateVars(s: string): string {
|
|
|
|
return s.replaceAll(/\{\{(\w+)\}\}/g, (match, v) => {
|
|
|
|
switch (v) {
|
|
|
|
case "today":
|
|
|
|
return niceDate(new Date());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return match;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-03-29 15:02:28 +00:00
|
|
|
// Called from client, running on server
|
|
|
|
export async function updateMaterializedQueriesOnPage(pageName: string) {
|
2022-04-01 15:07:08 +00:00
|
|
|
let { text } = await readPage(pageName);
|
2022-04-08 15:46:09 +00:00
|
|
|
|
2022-04-12 11:33:07 +00:00
|
|
|
text = await replaceAsync(
|
|
|
|
text,
|
|
|
|
queryRegex,
|
|
|
|
async (fullMatch, startQuery, query, body, endQuery) => {
|
|
|
|
let parsedQuery = parseQuery(replaceTemplateVars(query));
|
2022-04-06 13:39:20 +00:00
|
|
|
|
2022-04-12 11:33:07 +00:00
|
|
|
console.log("Parsed query", parsedQuery);
|
|
|
|
|
|
|
|
switch (parsedQuery.table) {
|
|
|
|
case "page":
|
|
|
|
let allPages = await listPages();
|
|
|
|
let markdownPages = applyQuery(parsedQuery, allPages).map(
|
|
|
|
(pageMeta: PageMeta) => `* [[${pageMeta.name}]]`
|
|
|
|
);
|
|
|
|
return `${startQuery}\n${markdownPages.join("\n")}\n${endQuery}`;
|
|
|
|
case "task":
|
|
|
|
let allTasks: Task[] = [];
|
|
|
|
for (let { key, page, value } of await scanPrefixGlobal("task:")) {
|
|
|
|
let [, pos] = key.split(":");
|
|
|
|
allTasks.push({
|
|
|
|
...value,
|
|
|
|
page: page,
|
|
|
|
pos: pos,
|
|
|
|
});
|
2022-03-29 15:02:28 +00:00
|
|
|
}
|
2022-04-12 11:33:07 +00:00
|
|
|
let markdownTasks = applyQuery(parsedQuery, allTasks).map(
|
|
|
|
(t) =>
|
|
|
|
`* [${t.done ? "x" : " "}] [[${t.page}@${t.pos}]] ${t.name}` +
|
|
|
|
(t.nested ? "\n " + t.nested : "")
|
|
|
|
);
|
|
|
|
return `${startQuery}\n${markdownTasks.join("\n")}\n${endQuery}`;
|
|
|
|
case "link":
|
|
|
|
let uniqueLinks = new Set<string>();
|
|
|
|
for (let { value: name } of await scanPrefixGlobal(
|
|
|
|
`pl:${pageName}:`
|
|
|
|
)) {
|
2022-03-31 15:25:34 +00:00
|
|
|
uniqueLinks.add(name);
|
|
|
|
}
|
2022-04-12 11:33:07 +00:00
|
|
|
let markdownLinks = applyQuery(
|
|
|
|
parsedQuery,
|
|
|
|
[...uniqueLinks].map((l) => ({ name: l }))
|
|
|
|
).map((pageMeta) => `* [[${pageMeta.name}]]`);
|
|
|
|
return `${startQuery}\n${markdownLinks.join("\n")}\n${endQuery}`;
|
|
|
|
case "item":
|
|
|
|
let allItems: Item[] = [];
|
|
|
|
for (let { key, page, value } of await scanPrefixGlobal("it:")) {
|
|
|
|
let [, pos] = key.split("@");
|
|
|
|
allItems.push({
|
|
|
|
...value,
|
|
|
|
page: page,
|
|
|
|
pos: +pos,
|
|
|
|
});
|
2022-03-29 15:02:28 +00:00
|
|
|
}
|
2022-04-12 11:33:07 +00:00
|
|
|
let markdownItems = applyQuery(parsedQuery, allItems).map(
|
|
|
|
(item) =>
|
|
|
|
`* [[${item.page}@${item.pos}]] ${item.name}` +
|
|
|
|
(item.nested ? "\n " + item.nested : "")
|
|
|
|
);
|
|
|
|
return `${startQuery}\n${markdownItems.join("\n")}\n${endQuery}`;
|
|
|
|
case "data":
|
|
|
|
let allData: Object[] = [];
|
|
|
|
for (let { key, page, value } of await scanPrefixGlobal("data:")) {
|
|
|
|
let [, pos] = key.split("@");
|
|
|
|
allData.push({
|
|
|
|
...value,
|
|
|
|
page: page,
|
|
|
|
pos: +pos,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
let markdownData = applyQuery(parsedQuery, allData).map((item) =>
|
|
|
|
YAML.stringify(item)
|
|
|
|
);
|
|
|
|
return `${startQuery}\n\`\`\`data\n${markdownData.join(
|
|
|
|
"---\n"
|
|
|
|
)}\`\`\`\n${endQuery}`;
|
|
|
|
default:
|
|
|
|
return fullMatch;
|
|
|
|
}
|
2022-03-29 15:02:28 +00:00
|
|
|
}
|
2022-04-12 11:33:07 +00:00
|
|
|
);
|
2022-03-29 15:02:28 +00:00
|
|
|
// console.log("New text", text);
|
2022-04-01 15:07:08 +00:00
|
|
|
await writePage(pageName, text);
|
2022-03-29 15:02:28 +00:00
|
|
|
}
|