1
0

Materialized query parser redo

This commit is contained in:
Zef Hemel 2022-04-11 20:34:09 +02:00
parent d649009dd2
commit b3c3302970
31 changed files with 1182 additions and 667 deletions

View File

@ -13,4 +13,14 @@ export type SilverBulletHooks = CommandHookT &
CronHookT & CronHookT &
EventHookT; EventHookT;
export type Manifest = plugos.Manifest<SilverBulletHooks>; export type SyntaxExtensions = {
syntax?: { [key: string]: NodeDef };
};
export type NodeDef = {
firstCharacters: string[];
regex: string;
styles: { [key: string]: string };
};
export type Manifest = plugos.Manifest<SilverBulletHooks> & SyntaxExtensions;

84
common/parse_tree.ts Normal file
View File

@ -0,0 +1,84 @@
import type { SyntaxNode } from "@lezer/common";
import type { Language } from "@codemirror/language";
import { ParseTree } from "./tree";
export function lezerToParseTree(
text: string,
n: SyntaxNode,
offset = 0
): ParseTree {
let children: ParseTree[] = [];
let nodeText: string | undefined;
let child = n.firstChild;
while (child) {
children.push(lezerToParseTree(text, child));
child = child.nextSibling;
}
if (children.length === 0) {
children = [
{
from: n.from + offset,
to: n.to + offset,
text: text.substring(n.from, n.to),
},
];
} else {
let newChildren: ParseTree[] = [];
let index = n.from;
for (let child of children) {
let s = text.substring(index, child.from);
if (s) {
newChildren.push({
from: index + offset,
to: child.from! + offset,
text: s,
});
}
newChildren.push(child);
index = child.to!;
}
let s = text.substring(index, n.to);
if (s) {
newChildren.push({ from: index + offset, to: n.to + offset, text: s });
}
children = newChildren;
}
let result: ParseTree = {
type: n.name,
from: n.from + offset,
to: n.to + offset,
};
if (children.length > 0) {
result.children = children;
}
if (nodeText) {
result.text = nodeText;
}
return result;
}
export function parse(language: Language, text: string): ParseTree {
let tree = lezerToParseTree(text, language.parser.parse(text).topNode);
// replaceNodesMatching(tree, (n): MarkdownTree | undefined | null => {
// if (n.type === "FencedCode") {
// let infoN = findNodeMatching(n, (n) => n.type === "CodeInfo");
// let language = infoN!.children![0].text;
// let textN = findNodeMatching(n, (n) => n.type === "CodeText");
// let text = textN!.children![0].text!;
//
// console.log(language, text);
// switch (language) {
// case "yaml":
// let parsed = StreamLanguage.define(yaml).parser.parse(text);
// let subTree = treeToAST(text, parsed.topNode, n.from);
// // console.log(JSON.stringify(subTree, null, 2));
// subTree.type = "yaml";
// return subTree;
// }
// }
// return;
// });
return tree;
}

View File

@ -1,10 +1,12 @@
import { SysCallMapping } from "../../plugos/system"; import { SysCallMapping } from "../../plugos/system";
import { MarkdownTree, parse } from "../tree"; import { parse } from "../parse_tree";
import { Language } from "@codemirror/language";
import type { ParseTree } from "../tree";
export function markdownSyscalls(): SysCallMapping { export function markdownSyscalls(lang: Language): SysCallMapping {
return { return {
"markdown.parseMarkdown": (ctx, text: string): MarkdownTree => { "markdown.parseMarkdown": (ctx, text: string): ParseTree => {
return parse(text); return parse(lang, text);
}, },
}; };
} }

View File

@ -1,14 +1,15 @@
import { expect, test } from "@jest/globals"; import { expect, test } from "@jest/globals";
import { parse } from "../../common/tree"; import { parse } from "./parse_tree";
import { import {
addParentPointers, addParentPointers,
collectNodesMatching, collectNodesMatching,
findParentMatching, findParentMatching,
nodeAtPos, nodeAtPos,
removeParentPointers, removeParentPointers,
renderMarkdown, renderToText,
replaceNodesMatching replaceNodesMatching
} from "./tree"; } from "./tree";
import wikiMarkdownLang from "../webapp/parser";
const mdTest1 = ` const mdTest1 = `
# Heading # Heading
@ -46,7 +47,8 @@ name: something
`; `;
test("Run a Node sandbox", async () => { test("Run a Node sandbox", async () => {
let mdTree = parse(mdTest1); const lang = wikiMarkdownLang([]);
let mdTree = parse(lang, mdTest1);
addParentPointers(mdTree); addParentPointers(mdTree);
// console.log(JSON.stringify(mdTree, null, 2)); // console.log(JSON.stringify(mdTree, null, 2));
let wikiLink = nodeAtPos(mdTree, mdTest1.indexOf("Wiki Page"))!; let wikiLink = nodeAtPos(mdTree, mdTest1.indexOf("Wiki Page"))!;
@ -59,7 +61,7 @@ test("Run a Node sandbox", async () => {
expect(allTodos.length).toBe(2); expect(allTodos.length).toBe(2);
// Render back into markdown should be equivalent // Render back into markdown should be equivalent
expect(renderMarkdown(mdTree)).toBe(mdTest1); expect(renderToText(mdTree)).toBe(mdTest1);
removeParentPointers(mdTree); removeParentPointers(mdTree);
replaceNodesMatching(mdTree, (n) => { replaceNodesMatching(mdTree, (n) => {
@ -70,6 +72,6 @@ test("Run a Node sandbox", async () => {
} }
}); });
console.log(JSON.stringify(mdTree, null, 2)); console.log(JSON.stringify(mdTree, null, 2));
let mdTree3 = parse(mdTest3); let mdTree3 = parse(lang, mdTest3);
console.log(JSON.stringify(mdTree3, null, 2)); console.log(JSON.stringify(mdTree3, null, 2));
}); });

View File

@ -1,87 +1,137 @@
import { SyntaxNode } from "@lezer/common"; export type ParseTree = {
import wikiMarkdownLang from "../webapp/parser";
export type MarkdownTree = {
type?: string; // undefined === text node type?: string; // undefined === text node
from?: number; from?: number;
to?: number; to?: number;
text?: string; text?: string;
children?: MarkdownTree[]; children?: ParseTree[];
// Only present after running addParentPointers
parent?: ParseTree;
}; };
function treeToAST(text: string, n: SyntaxNode, offset = 0): MarkdownTree { export function addParentPointers(tree: ParseTree) {
let children: MarkdownTree[] = []; if (!tree.children) {
let nodeText: string | undefined; return;
let child = n.firstChild;
while (child) {
children.push(treeToAST(text, child));
child = child.nextSibling;
} }
for (let child of tree.children) {
child.parent = tree;
addParentPointers(child);
}
}
if (children.length === 0) { export function removeParentPointers(tree: ParseTree) {
children = [ delete tree.parent;
{ if (!tree.children) {
from: n.from + offset, return;
to: n.to + offset, }
text: text.substring(n.from, n.to), for (let child of tree.children) {
}, removeParentPointers(child);
]; }
} else { }
let newChildren: MarkdownTree[] | string = [];
let index = n.from; export function findParentMatching(
tree: ParseTree,
matchFn: (tree: ParseTree) => boolean
): ParseTree | null {
let node = tree.parent;
while (node) {
if (matchFn(node)) {
return node;
}
node = node.parent;
}
return null;
}
export function collectNodesOfType(
tree: ParseTree,
nodeType: string
): ParseTree[] {
return collectNodesMatching(tree, (n) => n.type === nodeType);
}
export function collectNodesMatching(
tree: ParseTree,
matchFn: (tree: ParseTree) => boolean
): ParseTree[] {
if (matchFn(tree)) {
return [tree];
}
let results: ParseTree[] = [];
if (tree.children) {
for (let child of tree.children) {
results = [...results, ...collectNodesMatching(child, matchFn)];
}
}
return results;
}
// return value: returning undefined = not matched, continue, null = delete, new node = replace
export function replaceNodesMatching(
tree: ParseTree,
substituteFn: (tree: ParseTree) => ParseTree | null | undefined
) {
if (tree.children) {
let children = tree.children.slice();
for (let child of children) { for (let child of children) {
let s = text.substring(index, child.from); let subst = substituteFn(child);
if (s) { if (subst !== undefined) {
newChildren.push({ let pos = tree.children.indexOf(child);
from: index + offset, if (subst) {
to: child.from! + offset, tree.children.splice(pos, 1, subst);
text: s, } else {
}); // null = delete
tree.children.splice(pos, 1);
}
} else {
replaceNodesMatching(child, substituteFn);
} }
newChildren.push(child);
index = child.to!;
} }
let s = text.substring(index, n.to);
if (s) {
newChildren.push({ from: index + offset, to: n.to + offset, text: s });
}
children = newChildren;
} }
let result: MarkdownTree = {
type: n.name,
from: n.from + offset,
to: n.to + offset,
};
if (children.length > 0) {
result.children = children;
}
if (nodeText) {
result.text = nodeText;
}
return result;
} }
export function parse(text: string): MarkdownTree { export function findNodeMatching(
let tree = treeToAST(text, wikiMarkdownLang.parser.parse(text).topNode); tree: ParseTree,
// replaceNodesMatching(tree, (n): MarkdownTree | undefined | null => { matchFn: (tree: ParseTree) => boolean
// if (n.type === "FencedCode") { ): ParseTree | null {
// let infoN = findNodeMatching(n, (n) => n.type === "CodeInfo"); return collectNodesMatching(tree, matchFn)[0];
// let language = infoN!.children![0].text; }
// let textN = findNodeMatching(n, (n) => n.type === "CodeText");
// let text = textN!.children![0].text!; export function findNodeOfType(
// tree: ParseTree,
// console.log(language, text); nodeType: string
// switch (language) { ): ParseTree | null {
// case "yaml": return collectNodesMatching(tree, (n) => n.type === nodeType)[0];
// let parsed = StreamLanguage.define(yaml).parser.parse(text); }
// let subTree = treeToAST(text, parsed.topNode, n.from);
// // console.log(JSON.stringify(subTree, null, 2)); // Finds non-text node at position
// subTree.type = "yaml"; export function nodeAtPos(tree: ParseTree, pos: number): ParseTree | null {
// return subTree; if (pos < tree.from! || pos > tree.to!) {
// } return null;
// } }
// return; if (!tree.children) {
// }); return tree;
return tree; }
for (let child of tree.children) {
let n = nodeAtPos(child, pos);
if (n && n.text !== undefined) {
// Got a text node, let's return its parent
return tree;
} else if (n) {
// Got it
return n;
}
}
return null;
}
// Turn ParseTree back into text
export function renderToText(tree: ParseTree): string {
let pieces: string[] = [];
if (tree.text !== undefined) {
return tree.text;
}
for (let child of tree.children!) {
pieces.push(renderToText(child));
}
return pieces.join("");
} }

View File

@ -36,7 +36,8 @@
}, },
"test": { "test": {
"source": [ "source": [
"plugs/lib/tree.test.ts", "common/tree.test.ts",
"plugs/query/engine.test.ts",
"common/spaces/sync.test.ts" "common/spaces/sync.test.ts"
], ],
"includeNodeModules": ["@codemirror/legacy-modes"], "includeNodeModules": ["@codemirror/legacy-modes"],

View File

@ -1,6 +1,7 @@
import { syscall } from "./syscall"; import { syscall } from "./syscall";
import type { MarkdownTree } from "../common/tree";
export async function parseMarkdown(text: string): Promise<MarkdownTree> { import type { ParseTree } from "../common/tree";
export async function parseMarkdown(text: string): Promise<ParseTree> {
return syscall("markdown.parseMarkdown", text); return syscall("markdown.parseMarkdown", text);
} }

View File

@ -1,3 +1,23 @@
syntax:
HashTag:
firstCharacters:
- "#"
regex: "#[A-Za-z\\.]+"
styles:
color: blue
AtMention:
firstCharacters:
- "@"
regex: "@[A-Za-z\\.]+"
styles:
color: blue
URL:
firstCharacters:
- "h"
regex: "https?:\\/\\/[-a-zA-Z0-9@:%._\\+~#=]{1,256}([-a-zA-Z0-9()@:%_\\+.~#?&=\\/]*)"
styles:
color: "#0330cb"
textDecoration: underline
functions: functions:
clearPageIndex: clearPageIndex:
path: "./page.ts:clearPageIndex" path: "./page.ts:clearPageIndex"
@ -55,13 +75,13 @@ functions:
path: "./dates.ts:indexDates" path: "./dates.ts:indexDates"
events: events:
- page:index - page:index
updateMaterializedQueriesOnPage: parseServerCommand:
path: ./materialized_queries.ts:updateMaterializedQueriesOnPage path: ./page.ts:parseServerPageCommand
updateMaterializedQueriesCommand:
path: ./materialized_queries.ts:updateMaterializedQueriesCommand
command: command:
name: "Materialized Queries: Update" name: "Debug: Parse Document on Server"
parseCommand: parsePage:
path: ./page.ts:parsePage path: ./page.ts:parsePage
parseCommand:
path: ./page.ts:parsePageCommand
command: command:
name: Parse Document name: "Debug: Parse Document"

View File

@ -1,7 +1,7 @@
import { insertAtCursor } from "plugos-silverbullet-syscall/editor"; import { insertAtCursor } from "plugos-silverbullet-syscall/editor";
import { IndexEvent } from "../../webapp/app_event"; import { IndexEvent } from "../../webapp/app_event";
import { batchSet } from "plugos-silverbullet-syscall"; import { batchSet } from "plugos-silverbullet-syscall";
import { whiteOutQueries } from "./materialized_queries"; import { whiteOutQueries } from "../query/materialized_queries";
const dateMatchRegex = /(\d{4}\-\d{2}\-\d{2})/g; const dateMatchRegex = /(\d{4}\-\d{2}\-\d{2})/g;
@ -23,12 +23,16 @@ export async function indexDates({ name, text }: IndexEvent) {
await batchSet(name, dates); await batchSet(name, dates);
} }
export function niceDate(d: Date): string {
return new Date().toISOString().split("T")[0];
}
export async function insertToday() { export async function insertToday() {
await insertAtCursor(new Date().toISOString().split("T")[0]); await insertAtCursor(niceDate(new Date()));
} }
export async function insertTomorrow() { export async function insertTomorrow() {
let d = new Date(); let d = new Date();
d.setDate(d.getDate() + 1); d.setDate(d.getDate() + 1);
await insertAtCursor(d.toISOString().split("T")[0]); await insertAtCursor(niceDate(d));
} }

View File

@ -1,9 +1,9 @@
import { IndexEvent } from "../../webapp/app_event"; import { IndexEvent } from "../../webapp/app_event";
import { whiteOutQueries } from "./materialized_queries"; import { whiteOutQueries } from "../query/materialized_queries";
import { batchSet } from "plugos-silverbullet-syscall/index"; import { batchSet } from "plugos-silverbullet-syscall/index";
import { parseMarkdown } from "plugos-silverbullet-syscall/markdown"; import { parseMarkdown } from "plugos-silverbullet-syscall/markdown";
import { collectNodesMatching, MarkdownTree, renderMarkdown } from "../lib/tree"; import { collectNodesMatching, ParseTree, renderToText } from "../../common/tree";
type Item = { type Item = {
item: string; item: string;
@ -23,16 +23,16 @@ export async function indexItems({ name, text }: IndexEvent) {
if (!n.children) { if (!n.children) {
return; return;
} }
let textNodes: MarkdownTree[] = []; let textNodes: ParseTree[] = [];
let nested: string | undefined; let nested: string | undefined;
for (let child of n.children!.slice(1)) { for (let child of n.children!.slice(1)) {
if (child.type === "OrderedList" || child.type === "BulletList") { if (child.type === "OrderedList" || child.type === "BulletList") {
nested = renderMarkdown(child); nested = renderToText(child);
break; break;
} }
textNodes.push(child); textNodes.push(child);
} }
let item = textNodes.map(renderMarkdown).join("").trim(); let item = textNodes.map(renderToText).join("").trim();
let value: Item = { let value: Item = {
item, item,
}; };

View File

@ -1,13 +1,11 @@
import { ClickEvent } from "../../webapp/app_event"; import { ClickEvent } from "../../webapp/app_event";
import { updateMaterializedQueriesCommand } from "./materialized_queries";
import { getCursor, getText, navigate as navigateTo, openUrl } from "plugos-silverbullet-syscall/editor"; import { getCursor, getText, navigate as navigateTo, openUrl } from "plugos-silverbullet-syscall/editor";
import { taskToggleAtPos } from "../tasks/task";
import { parseMarkdown } from "plugos-silverbullet-syscall/markdown"; import { parseMarkdown } from "plugos-silverbullet-syscall/markdown";
import { MarkdownTree, nodeAtPos } from "../lib/tree"; import { nodeAtPos, ParseTree } from "../../common/tree";
const materializedQueryPrefix = /<!--\s*#query\s+/; const materializedQueryPrefix = /<!--\s*#query\s+/;
async function actionClickOrActionEnter(mdTree: MarkdownTree | null) { async function actionClickOrActionEnter(mdTree: ParseTree | null) {
if (!mdTree) { if (!mdTree) {
return; return;
} }
@ -24,17 +22,9 @@ async function actionClickOrActionEnter(mdTree: MarkdownTree | null) {
case "URL": case "URL":
await openUrl(mdTree.children![0].text!); await openUrl(mdTree.children![0].text!);
break; break;
case "CommentBlock":
if (mdTree.children![0].text!.match(materializedQueryPrefix)) {
await updateMaterializedQueriesCommand();
}
break;
case "Link": case "Link":
await openUrl(mdTree.children![4].children![0].text!); await openUrl(mdTree.children![4].children![0].text!);
break; break;
case "TaskMarker":
await taskToggleAtPos(mdTree.from! + 1);
break;
} }
} }
@ -45,9 +35,11 @@ export async function linkNavigate() {
} }
export async function clickNavigate(event: ClickEvent) { export async function clickNavigate(event: ClickEvent) {
// Navigate by default, don't navigate when Ctrl or Cmd is held
if (event.ctrlKey || event.metaKey) { if (event.ctrlKey || event.metaKey) {
let mdTree = await parseMarkdown(await getText()); return;
let newNode = nodeAtPos(mdTree, event.pos);
await actionClickOrActionEnter(newNode);
} }
let mdTree = await parseMarkdown(await getText());
let newNode = nodeAtPos(mdTree, event.pos);
await actionClickOrActionEnter(newNode);
} }

View File

@ -21,10 +21,10 @@ import { parseMarkdown } from "plugos-silverbullet-syscall/markdown";
import { import {
addParentPointers, addParentPointers,
collectNodesMatching, collectNodesMatching,
MarkdownTree, ParseTree,
renderMarkdown, renderToText,
replaceNodesMatching replaceNodesMatching
} from "../lib/tree"; } from "../../common/tree";
export async function indexLinks({ name, text }: IndexEvent) { export async function indexLinks({ name, text }: IndexEvent) {
let backLinks: { key: string; value: string }[] = []; let backLinks: { key: string; value: string }[] = [];
@ -93,7 +93,7 @@ export async function renamePage() {
} }
let mdTree = await parseMarkdown(text); let mdTree = await parseMarkdown(text);
addParentPointers(mdTree); addParentPointers(mdTree);
replaceNodesMatching(mdTree, (n): MarkdownTree | undefined | null => { replaceNodesMatching(mdTree, (n): ParseTree | undefined | null => {
if (n.type === "WikiLinkPage") { if (n.type === "WikiLinkPage") {
let pageName = n.children![0].text!; let pageName = n.children![0].text!;
if (pageName === oldName) { if (pageName === oldName) {
@ -110,7 +110,7 @@ export async function renamePage() {
return; return;
}); });
// let newText = text.replaceAll(`[[${oldName}]]`, `[[${newName}]]`); // let newText = text.replaceAll(`[[${oldName}]]`, `[[${newName}]]`);
let newText = renderMarkdown(mdTree); let newText = renderToText(mdTree);
if (text !== newText) { if (text !== newText) {
console.log("Changes made, saving..."); console.log("Changes made, saving...");
await writePage(pageToUpdate, newText); await writePage(pageToUpdate, newText);
@ -179,6 +179,14 @@ export async function clearPageIndex(page: string) {
await clearPageIndexForPage(page); await clearPageIndexForPage(page);
} }
export async function parsePage() { export async function parseServerPageCommand() {
console.log(await parseMarkdown(await getText())); console.log(await invokeFunction("server", "parsePage", await getText()));
}
export async function parsePageCommand() {
parsePage(await getText());
}
export async function parsePage(text: string) {
console.log("AST", JSON.stringify(await parseMarkdown(text), null, 2));
} }

View File

@ -1,124 +0,0 @@
export type MarkdownTree = {
type?: string; // undefined === text node
from?: number;
to?: number;
text?: string;
children?: MarkdownTree[];
parent?: MarkdownTree;
};
export function addParentPointers(mdTree: MarkdownTree) {
if (!mdTree.children) {
return;
}
for (let child of mdTree.children) {
child.parent = mdTree;
addParentPointers(child);
}
}
export function removeParentPointers(mdTree: MarkdownTree) {
delete mdTree.parent;
if (!mdTree.children) {
return;
}
for (let child of mdTree.children) {
removeParentPointers(child);
}
}
export function findParentMatching(
mdTree: MarkdownTree,
matchFn: (mdTree: MarkdownTree) => boolean
): MarkdownTree | null {
let node = mdTree.parent;
while (node) {
if (matchFn(node)) {
return node;
}
node = node.parent;
}
return null;
}
export function collectNodesMatching(
mdTree: MarkdownTree,
matchFn: (mdTree: MarkdownTree) => boolean
): MarkdownTree[] {
if (matchFn(mdTree)) {
return [mdTree];
}
let results: MarkdownTree[] = [];
if (mdTree.children) {
for (let child of mdTree.children) {
results = [...results, ...collectNodesMatching(child, matchFn)];
}
}
return results;
}
// return value: returning undefined = not matched, continue, null = delete, new node = replace
export function replaceNodesMatching(
mdTree: MarkdownTree,
substituteFn: (mdTree: MarkdownTree) => MarkdownTree | null | undefined
) {
if (mdTree.children) {
for (let child of mdTree.children) {
let subst = substituteFn(child);
if (subst !== undefined) {
let pos = mdTree.children.indexOf(child);
if (subst) {
mdTree.children.splice(pos, 1, subst);
} else {
// null = delete
mdTree.children.splice(pos, 1);
}
} else {
replaceNodesMatching(child, substituteFn);
}
}
}
}
export function findNodeMatching(
mdTree: MarkdownTree,
matchFn: (mdTree: MarkdownTree) => boolean
): MarkdownTree | null {
return collectNodesMatching(mdTree, matchFn)[0];
}
// Finds non-text node at position
export function nodeAtPos(
mdTree: MarkdownTree,
pos: number
): MarkdownTree | null {
if (pos < mdTree.from! || pos > mdTree.to!) {
return null;
}
if (!mdTree.children) {
return mdTree;
}
for (let child of mdTree.children) {
let n = nodeAtPos(child, pos);
if (n && n.text !== undefined) {
// Got a text node, let's return its parent
return mdTree;
} else if (n) {
// Got it
return n;
}
}
return null;
}
// Turn MarkdownTree back into regular markdown text
export function renderMarkdown(mdTree: MarkdownTree): string {
let pieces: string[] = [];
if (mdTree.text !== undefined) {
return mdTree.text;
}
for (let child of mdTree.children!) {
pieces.push(renderMarkdown(child));
}
return pieces.join("");
}

View File

@ -2,7 +2,7 @@ import MarkdownIt from "markdown-it";
import { getText, hideRhs, showRhs } from "plugos-silverbullet-syscall/editor"; import { getText, hideRhs, showRhs } from "plugos-silverbullet-syscall/editor";
import * as clientStore from "plugos-silverbullet-syscall/clientStore"; import * as clientStore from "plugos-silverbullet-syscall/clientStore";
import { parseMarkdown } from "plugos-silverbullet-syscall/markdown"; import { parseMarkdown } from "plugos-silverbullet-syscall/markdown";
import { renderMarkdown, replaceNodesMatching } from "../lib/tree"; import { renderToText, replaceNodesMatching } from "../../common/tree";
const css = ` const css = `
<style> <style>
@ -79,7 +79,7 @@ export async function cleanMarkdown(text: string) {
return null; return null;
} }
}); });
let html = md.render(renderMarkdown(mdTree)); let html = md.render(renderToText(mdTree));
return html; return html;
} }

View File

@ -9,8 +9,12 @@
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@jest/globals": "^27.5.1", "@jest/globals": "^27.5.1",
"@lezer/generator": "^0.15.4",
"@lezer/lr": "^0.15.8",
"@types/yaml": "^1.9.7",
"plugos-silverbullet-syscall": "file:../plugos-silverbullet-syscall", "plugos-silverbullet-syscall": "file:../plugos-silverbullet-syscall",
"plugos-syscall": "file:../plugos-syscall" "plugos-syscall": "file:../plugos-syscall",
"yaml": "^2.0.0"
} }
}, },
"../plugos-silverbullet-syscall": { "../plugos-silverbullet-syscall": {
@ -173,6 +177,31 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
} }
}, },
"node_modules/@lezer/common": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz",
"integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig=="
},
"node_modules/@lezer/generator": {
"version": "0.15.4",
"resolved": "https://registry.npmjs.org/@lezer/generator/-/generator-0.15.4.tgz",
"integrity": "sha512-9bBwU2TzKMBQ6OCEDevuMNWGOBKlkq5YIGEhjrz9pb3MLb+oYYR4dVFZ7ehwLcDoSecsSA7PdlAy0thJO5pt2w==",
"dependencies": {
"@lezer/common": "^0.15.0",
"@lezer/lr": "^0.15.0"
},
"bin": {
"lezer-generator": "dist/lezer-generator.cjs"
}
},
"node_modules/@lezer/lr": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz",
"integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==",
"dependencies": {
"@lezer/common": "^0.15.0"
}
},
"node_modules/@sinonjs/commons": { "node_modules/@sinonjs/commons": {
"version": "1.8.3", "version": "1.8.3",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
@ -220,6 +249,15 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
}, },
"node_modules/@types/yaml": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
"integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==",
"deprecated": "This is a stub types definition. yaml provides its own type definitions, so you do not need this installed.",
"dependencies": {
"yaml": "*"
}
},
"node_modules/@types/yargs": { "node_modules/@types/yargs": {
"version": "16.0.4", "version": "16.0.4",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz",
@ -560,6 +598,14 @@
"engines": { "engines": {
"node": ">=4" "node": ">=4"
} }
},
"node_modules/yaml": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0.tgz",
"integrity": "sha512-JbfdlHKGP2Ik9IHylzWlGd4pPK++EU46/IxMykphS2ZKw7a7h+dHNmcXObLgpRDriBY+rpWslldikckX8oruWQ==",
"engines": {
"node": ">= 14"
}
} }
}, },
"dependencies": { "dependencies": {
@ -683,6 +729,28 @@
"chalk": "^4.0.0" "chalk": "^4.0.0"
} }
}, },
"@lezer/common": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz",
"integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig=="
},
"@lezer/generator": {
"version": "0.15.4",
"resolved": "https://registry.npmjs.org/@lezer/generator/-/generator-0.15.4.tgz",
"integrity": "sha512-9bBwU2TzKMBQ6OCEDevuMNWGOBKlkq5YIGEhjrz9pb3MLb+oYYR4dVFZ7ehwLcDoSecsSA7PdlAy0thJO5pt2w==",
"requires": {
"@lezer/common": "^0.15.0",
"@lezer/lr": "^0.15.0"
}
},
"@lezer/lr": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz",
"integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==",
"requires": {
"@lezer/common": "^0.15.0"
}
},
"@sinonjs/commons": { "@sinonjs/commons": {
"version": "1.8.3", "version": "1.8.3",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
@ -730,6 +798,14 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
}, },
"@types/yaml": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
"integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==",
"requires": {
"yaml": "*"
}
},
"@types/yargs": { "@types/yargs": {
"version": "16.0.4", "version": "16.0.4",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz",
@ -980,6 +1056,11 @@
"version": "4.0.8", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
},
"yaml": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0.tgz",
"integrity": "sha512-JbfdlHKGP2Ik9IHylzWlGd4pPK++EU46/IxMykphS2ZKw7a7h+dHNmcXObLgpRDriBY+rpWslldikckX8oruWQ=="
} }
} }
} }

View File

@ -1,8 +1,13 @@
{ {
"name": "plugs", "name": "plugs",
"version": "1.0.0", "version": "1.0.0",
"scripts": {
"generate": "lezer-generator query/query.grammar -o query/parse-query.js"
},
"dependencies": { "dependencies": {
"@jest/globals": "^27.5.1", "@jest/globals": "^27.5.1",
"@lezer/generator": "^0.15.4",
"@lezer/lr": "^0.15.8",
"@types/yaml": "^1.9.7", "@types/yaml": "^1.9.7",
"plugos-silverbullet-syscall": "file:../plugos-silverbullet-syscall", "plugos-silverbullet-syscall": "file:../plugos-silverbullet-syscall",
"plugos-syscall": "file:../plugos-syscall", "plugos-syscall": "file:../plugos-syscall",

View File

@ -0,0 +1,70 @@
import { expect, test } from "@jest/globals";
import { applyQuery, parseQuery } from "./engine";
test("Test parser", () => {
let parsedBasicQuery = parseQuery(`page`);
expect(parsedBasicQuery.table).toBe("page");
let parsedQuery1 = parseQuery(
`task where completed = false and dueDate <= "{{today}}" order by dueDate desc limit 5`
);
expect(parsedQuery1.table).toBe("task");
expect(parsedQuery1.orderBy).toBe("dueDate");
expect(parsedQuery1.orderDesc).toBe(true);
expect(parsedQuery1.limit).toBe(5);
expect(parsedQuery1.filter.length).toBe(2);
expect(parsedQuery1.filter[0]).toStrictEqual({
op: "=",
prop: "completed",
value: false,
});
expect(parsedQuery1.filter[1]).toStrictEqual({
op: "<=",
prop: "dueDate",
value: "{{today}}",
});
let parsedQuery2 = parseQuery(`page where name like "interview/%"`);
expect(parsedQuery2.table).toBe("page");
expect(parsedQuery2.filter.length).toBe(1);
expect(parsedQuery2.filter[0]).toStrictEqual({
op: "like",
prop: "name",
value: "interview/%",
});
});
test("Test performing the queries", () => {
let data: any[] = [
{ name: "interview/My Interview", lastModified: 1 },
{ name: "interview/My Interview 2", lastModified: 2 },
{ name: "Pete", age: 38 },
{ name: "Angie", age: 28 },
];
expect(applyQuery(`page where name like "interview/%"`, data)).toStrictEqual([
{ name: "interview/My Interview", lastModified: 1 },
{ name: "interview/My Interview 2", lastModified: 2 },
]);
expect(
applyQuery(`page where name like "interview/%" order by lastModified`, data)
).toStrictEqual([
{ name: "interview/My Interview", lastModified: 1 },
{ name: "interview/My Interview 2", lastModified: 2 },
]);
expect(
applyQuery(
`page where name like "interview/%" order by lastModified desc`,
data
)
).toStrictEqual([
{ name: "interview/My Interview 2", lastModified: 2 },
{ name: "interview/My Interview", lastModified: 1 },
]);
expect(applyQuery(`page where age > 30`, data)).toStrictEqual([
{ name: "Pete", age: 38 },
]);
expect(applyQuery(`page where age > 28 and age < 38`, data)).toStrictEqual(
[]
);
});

154
plugs/query/engine.ts Normal file
View File

@ -0,0 +1,154 @@
import { collectNodesOfType, findNodeOfType, replaceNodesMatching } from "../../common/tree";
import { lezerToParseTree } from "../../common/parse_tree";
// @ts-ignore
import { parser } from "./parse-query";
type Filter = {
op: string;
prop: string;
value: any;
};
type ParsedQuery = {
table: string;
orderBy?: string;
orderDesc?: boolean;
limit?: number;
filter: Filter[];
};
export function parseQuery(query: string): ParsedQuery {
let n = lezerToParseTree(query, parser.parse(query).topNode);
// Clean the tree a bit
replaceNodesMatching(n, (n) => {
if (!n.type) {
let trimmed = n.text!.trim();
if (!trimmed) {
return null;
}
n.text = trimmed;
}
});
let queryNode = n.children![0];
let parsedQuery: ParsedQuery = {
table: queryNode.children![0].children![0].text!,
filter: [],
};
let orderByNode = findNodeOfType(queryNode, "OrderClause");
if (orderByNode) {
let nameNode = findNodeOfType(orderByNode, "Name");
parsedQuery.orderBy = nameNode!.children![0].text!;
let orderNode = findNodeOfType(orderByNode, "Order");
parsedQuery.orderDesc = orderNode
? orderNode.children![0].text! === "desc"
: false;
}
let limitNode = findNodeOfType(queryNode, "LimitClause");
if (limitNode) {
let nameNode = findNodeOfType(limitNode, "Number");
parsedQuery.limit = +nameNode!.children![0].text!;
}
let filterNodes = collectNodesOfType(queryNode, "FilterExpr");
for (let filterNode of filterNodes) {
let val: any = undefined;
let valNode = filterNode.children![2].children![0];
switch (valNode.type) {
case "Number":
val = valNode.children![0].text!;
break;
case "Bool":
val = valNode.children![0].text! === "true";
break;
case "Name":
val = valNode.children![0].text!;
break;
case "String":
val = valNode.children![0].text!;
val = val.substring(1, val.length - 1);
break;
}
let f: Filter = {
prop: filterNode.children![0].children![0].text!,
op: filterNode.children![1].text!,
value: val,
};
parsedQuery.filter.push(f);
}
// console.log(JSON.stringify(queryNode, null, 2));
return parsedQuery;
}
export function applyQuery(query: string, records: any[]): any {
const parsedQuery = parseQuery(query);
let resultRecords: any[] = [];
if (parsedQuery.filter.length === 0) {
resultRecords = records.slice();
} else {
recordLoop: for (let record of records) {
for (let { op, prop, value } of parsedQuery.filter) {
switch (op) {
case "=":
if (!(record[prop] === value)) {
continue recordLoop;
}
break;
case "!=":
if (!(record[prop] !== value)) {
continue recordLoop;
}
break;
case "<":
if (!(record[prop] < value)) {
continue recordLoop;
}
break;
case "<=":
if (!(record[prop] <= value)) {
continue recordLoop;
}
break;
case ">":
if (!(record[prop] > value)) {
continue recordLoop;
}
break;
case ">=":
if (!(record[prop] >= value)) {
continue recordLoop;
}
break;
case "like":
let re = new RegExp(value.replaceAll("%", ".*"));
if (!re.exec(record[prop])) {
continue recordLoop;
}
break;
}
}
resultRecords.push(record);
}
}
// Now the sorting
if (parsedQuery.orderBy) {
resultRecords = resultRecords.sort((a: any, b: any) => {
const orderBy = parsedQuery.orderBy!;
const orderDesc = parsedQuery.orderDesc!;
if (a[orderBy] === b[orderBy]) {
return 0;
}
if (a[orderBy] < b[orderBy]) {
return orderDesc ? 1 : -1;
} else {
return orderDesc ? -1 : 1;
}
});
}
if (parsedQuery.limit) {
resultRecords = resultRecords.slice(0, parsedQuery.limit);
}
return resultRecords;
}

View File

@ -3,12 +3,16 @@ import { flashNotification, getCurrentPage, reloadPage, save } from "plugos-silv
import { listPages, readPage, writePage } from "plugos-silverbullet-syscall/space"; import { listPages, readPage, writePage } from "plugos-silverbullet-syscall/space";
import { invokeFunction } from "plugos-silverbullet-syscall/system"; import { invokeFunction } from "plugos-silverbullet-syscall/system";
import { scanPrefixGlobal } from "plugos-silverbullet-syscall"; import { scanPrefixGlobal } from "plugos-silverbullet-syscall";
import { niceDate } from "../core/dates";
export const queryRegex = export const queryRegex =
/(<!--\s*#query\s+(?<table>\w+)\s*(filter\s+["'](?<filter>[^"']+)["'])?\s*\s*(order by\s+(?<orderBy>\w+)(?<orderDesc>\s+desc)?)?(group by\s+(?<groupBy>\w+))?\s*(limit\s+(?<limit>\d+))?\s*-->)(.+?)(<!--\s*#end\s*-->)/gs; /(<!--\s*#query\s+(?<table>\w+)\s*(filter\s+["'](?<filter>[^"']+)["'])?\s*\s*(order by\s+(?<orderBy>\w+)(?<orderDesc>\s+desc)?)?(group by\s+(?<groupBy>\w+))?\s*(limit\s+(?<limit>\d+))?\s*-->)(.+?)(<!--\s*#end\s*-->)/gs;
export const newQueryRegex =
/<!--\s*#query\s+(.+?)(?=\s*-->)-->(.+?)<!--\s*#end\s*-->/gs;
export function whiteOutQueries(text: string): string { export function whiteOutQueries(text: string): string {
return text.replaceAll(queryRegex, (match) => return text.replaceAll(newQueryRegex, (match) =>
new Array(match.length + 1).join(" ") new Array(match.length + 1).join(" ")
); );
} }
@ -40,6 +44,17 @@ export async function updateMaterializedQueriesCommand() {
await flashNotification("Updated materialized queries"); await flashNotification("Updated materialized queries");
} }
function replaceTemplateVars(s: string): string {
return s.replaceAll(/\{\{(\w+)\}\}/g, (match, v) => {
switch (v) {
case "today":
return niceDate(new Date());
break;
}
return match;
});
}
// Called from client, running on server // Called from client, running on server
export async function updateMaterializedQueriesOnPage(pageName: string) { export async function updateMaterializedQueriesOnPage(pageName: string) {
let { text } = await readPage(pageName); let { text } = await readPage(pageName);
@ -50,6 +65,7 @@ export async function updateMaterializedQueriesOnPage(pageName: string) {
const startQuery = args[0]; const startQuery = args[0];
const endQuery = args[args.length - 4]; const endQuery = args[args.length - 4];
let results = []; let results = [];
filter = filter && replaceTemplateVars(filter);
switch (table) { switch (table) {
case "page": case "page":
let pages = await listPages(); let pages = await listPages();
@ -94,21 +110,17 @@ export async function updateMaterializedQueriesOnPage(pageName: string) {
return `${startQuery}\n${results.sort().join("\n")}\n${endQuery}`; return `${startQuery}\n${results.sort().join("\n")}\n${endQuery}`;
case "link": case "link":
let uniqueLinks = new Set<string>(); let uniqueLinks = new Set<string>();
console.log("Here!!");
for (let { key, page, value: name } of await scanPrefixGlobal( for (let { key, page, value: name } of await scanPrefixGlobal(
`pl:${pageName}:` `pl:${pageName}:`
)) { )) {
console.log("Here!!");
let [, pos] = key.split(":"); let [, pos] = key.split(":");
if (!filter || (filter && name.includes(filter))) { if (!filter || (filter && name.includes(filter))) {
uniqueLinks.add(name); uniqueLinks.add(name);
} }
} }
console.log("Here!!");
for (const uniqueResult of uniqueLinks) { for (const uniqueResult of uniqueLinks) {
results.push(`* [[${uniqueResult}]]`); results.push(`* [[${uniqueResult}]]`);
} }
console.log("Here!!");
return `${startQuery}\n${results.sort().join("\n")}\n${endQuery}`; return `${startQuery}\n${results.sort().join("\n")}\n${endQuery}`;
case "item": case "item":
for (let { for (let {

44
plugs/query/query.grammar Normal file
View File

@ -0,0 +1,44 @@
@precedence { logic @left }
@top Program { Query }
Query {
Name (WhereClause | OrderClause | LimitClause)*
}
WhereClause { "where" LogicalExpr }
OrderClause { "order" "by" Name Order? }
LimitClause { "limit" Number }
Order {
"desc" | "asc"
}
Value { Number | String | Bool }
LogicalExpr { AndExpr | FilterExpr }
AndExpr { FilterExpr !logic "and" FilterExpr }
FilterExpr {
Name "<" Value
| Name "<=" Value
| Name "=" Value
| Name "!=" Value
| Name ">=" Value
| Name ">" Value
| Name "like" Value
}
@skip { space }
Bool {
"true" | "false"
}
@tokens {
space { std.whitespace+ }
Name { std.asciiLetter+ }
String { "\"" ![\"]* "\"" }
Number { std.digit+ }
}

View File

@ -0,0 +1,7 @@
functions:
updateMaterializedQueriesOnPage:
path: ./materialized_queries.ts:updateMaterializedQueriesOnPage
updateMaterializedQueriesCommand:
path: ./materialized_queries.ts:updateMaterializedQueriesCommand
command:
name: "Materialized Queries: Update"

View File

@ -1,16 +1,23 @@
import type { ClickEvent } from "../../webapp/app_event"; import type { ClickEvent } from "../../webapp/app_event";
import { IndexEvent } from "../../webapp/app_event"; import { IndexEvent } from "../../webapp/app_event";
import { whiteOutQueries } from "../core/materialized_queries"; import { whiteOutQueries } from "../query/materialized_queries";
import { batchSet } from "plugos-silverbullet-syscall/index"; import { batchSet } from "plugos-silverbullet-syscall/index";
import { readPage, writePage } from "plugos-silverbullet-syscall/space"; import { readPage, writePage } from "plugos-silverbullet-syscall/space";
import { parseMarkdown } from "plugos-silverbullet-syscall/markdown"; import { parseMarkdown } from "plugos-silverbullet-syscall/markdown";
import { dispatch, getText } from "plugos-silverbullet-syscall/editor"; import { dispatch, getText } from "plugos-silverbullet-syscall/editor";
import { addParentPointers, collectNodesMatching, nodeAtPos, renderMarkdown } from "../lib/tree"; import {
addParentPointers,
collectNodesMatching,
collectNodesOfType,
nodeAtPos,
renderToText
} from "../../common/tree";
type Task = { type Task = {
task: string; task: string;
complete: boolean; complete: boolean;
deadline?: string;
pos?: number; pos?: number;
nested?: string; nested?: string;
}; };
@ -21,23 +28,29 @@ export async function indexTasks({ name, text }: IndexEvent) {
text = whiteOutQueries(text); text = whiteOutQueries(text);
let mdTree = await parseMarkdown(text); let mdTree = await parseMarkdown(text);
addParentPointers(mdTree); addParentPointers(mdTree);
collectNodesMatching(mdTree, (n) => n.type === "Task").forEach((n) => { collectNodesOfType(mdTree, "Task").forEach((n) => {
let task = n.children!.slice(1).map(renderMarkdown).join("").trim(); 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 value: Task = {
task, task,
complete, complete,
}; };
let deadlineNodes = collectNodesOfType(n, "DeadlineDate");
if (deadlineNodes.length > 0) {
value.deadline = deadlineNodes[0].children![0].text!.replace(/📅\s*/, "");
}
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(renderMarkdown).join("").trim(); value.nested = nestedItems.map(renderToText).join("").trim();
} }
tasks.push({ tasks.push({
key: `task:${n.from}`, key: `task:${n.from}`,
value, value,
}); });
// console.log("Task", value);
}); });
console.log("Found", tasks.length, "task(s)"); console.log("Found", tasks.length, "task(s)");
@ -95,9 +108,9 @@ export async function taskToggleAtPos(pos: number) {
taskMarkerNode.children![0].text = changeTo; taskMarkerNode.children![0].text = changeTo;
console.log( console.log(
"This will be the new marker", "This will be the new marker",
renderMarkdown(taskMarkerNode) renderToText(taskMarkerNode)
); );
text = renderMarkdown(referenceMdTree); text = renderToText(referenceMdTree);
console.log("Updated reference paged text", text); console.log("Updated reference paged text", text);
await writePage(page, text); await writePage(page, text);
} }

View File

@ -1,3 +1,22 @@
syntax:
DeadlineDate:
firstCharacters:
- "📅"
regex: "📅\\s*\\d{4}\\-\\d{2}\\-\\d{2}"
styles:
backgroundColor: "rgba(22,22,22,0.07)"
CompletedDate:
firstCharacters:
- "✅"
regex: "✅\\s*\\d{4}\\-\\d{2}\\-\\d{2}"
styles:
backgroundColor: "rgba(22,22,22,0.07)"
RepeatInterval:
firstCharacters:
- "🔁"
regex: "🔁\\s*every\\s+\\w+"
styles:
backgroundColor: "rgba(22,22,22,0.07)"
functions: functions:
indexTasks: indexTasks:
path: "./task.ts:indexTasks" path: "./task.ts:indexTasks"

View File

@ -3,396 +3,418 @@
"@babel/code-frame@^7.12.13": "@babel/code-frame@^7.12.13":
version "7.16.7" "integrity" "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg=="
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz"
integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== "version" "7.16.7"
dependencies: dependencies:
"@babel/highlight" "^7.16.7" "@babel/highlight" "^7.16.7"
"@babel/helper-validator-identifier@^7.16.7": "@babel/helper-validator-identifier@^7.16.7":
version "7.16.7" "integrity" "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw=="
resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz"
integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== "version" "7.16.7"
"@babel/highlight@^7.16.7": "@babel/highlight@^7.16.7":
version "7.16.10" "integrity" "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw=="
resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz" "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz"
integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== "version" "7.16.10"
dependencies: dependencies:
"@babel/helper-validator-identifier" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7"
chalk "^2.0.0" "chalk" "^2.0.0"
js-tokens "^4.0.0" "js-tokens" "^4.0.0"
"@jest/environment@^27.5.1": "@jest/environment@^27.5.1":
version "27.5.1" "integrity" "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA=="
resolved "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz" "resolved" "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz"
integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== "version" "27.5.1"
dependencies: dependencies:
"@jest/fake-timers" "^27.5.1" "@jest/fake-timers" "^27.5.1"
"@jest/types" "^27.5.1" "@jest/types" "^27.5.1"
"@types/node" "*" "@types/node" "*"
jest-mock "^27.5.1" "jest-mock" "^27.5.1"
"@jest/fake-timers@^27.5.1": "@jest/fake-timers@^27.5.1":
version "27.5.1" "integrity" "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ=="
resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz" "resolved" "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz"
integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== "version" "27.5.1"
dependencies: dependencies:
"@jest/types" "^27.5.1" "@jest/types" "^27.5.1"
"@sinonjs/fake-timers" "^8.0.1" "@sinonjs/fake-timers" "^8.0.1"
"@types/node" "*" "@types/node" "*"
jest-message-util "^27.5.1" "jest-message-util" "^27.5.1"
jest-mock "^27.5.1" "jest-mock" "^27.5.1"
jest-util "^27.5.1" "jest-util" "^27.5.1"
"@jest/globals@^27.5.1": "@jest/globals@^27.5.1":
version "27.5.1" "integrity" "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q=="
resolved "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz" "resolved" "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz"
integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== "version" "27.5.1"
dependencies: dependencies:
"@jest/environment" "^27.5.1" "@jest/environment" "^27.5.1"
"@jest/types" "^27.5.1" "@jest/types" "^27.5.1"
expect "^27.5.1" "expect" "^27.5.1"
"@jest/types@^27.5.1": "@jest/types@^27.5.1":
version "27.5.1" "integrity" "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw=="
resolved "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz" "resolved" "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz"
integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== "version" "27.5.1"
dependencies: dependencies:
"@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-lib-coverage" "^2.0.0"
"@types/istanbul-reports" "^3.0.0" "@types/istanbul-reports" "^3.0.0"
"@types/node" "*" "@types/node" "*"
"@types/yargs" "^16.0.0" "@types/yargs" "^16.0.0"
chalk "^4.0.0" "chalk" "^4.0.0"
"@lezer/common@^0.15.0":
"integrity" "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig=="
"resolved" "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz"
"version" "0.15.12"
"@lezer/generator@^0.15.4":
"integrity" "sha512-9bBwU2TzKMBQ6OCEDevuMNWGOBKlkq5YIGEhjrz9pb3MLb+oYYR4dVFZ7ehwLcDoSecsSA7PdlAy0thJO5pt2w=="
"resolved" "https://registry.npmjs.org/@lezer/generator/-/generator-0.15.4.tgz"
"version" "0.15.4"
dependencies:
"@lezer/common" "^0.15.0"
"@lezer/lr" "^0.15.0"
"@lezer/lr@^0.15.0", "@lezer/lr@^0.15.8":
"integrity" "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg=="
"resolved" "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz"
"version" "0.15.8"
dependencies:
"@lezer/common" "^0.15.0"
"@sinonjs/commons@^1.7.0": "@sinonjs/commons@^1.7.0":
version "1.8.3" "integrity" "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ=="
resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz" "resolved" "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz"
integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== "version" "1.8.3"
dependencies: dependencies:
type-detect "4.0.8" "type-detect" "4.0.8"
"@sinonjs/fake-timers@^8.0.1": "@sinonjs/fake-timers@^8.0.1":
version "8.1.0" "integrity" "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg=="
resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz" "resolved" "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz"
integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== "version" "8.1.0"
dependencies: dependencies:
"@sinonjs/commons" "^1.7.0" "@sinonjs/commons" "^1.7.0"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.4" "integrity" "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g=="
resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz" "resolved" "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz"
integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== "version" "2.0.4"
"@types/istanbul-lib-report@*": "@types/istanbul-lib-report@*":
version "3.0.0" "integrity" "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg=="
resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" "resolved" "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz"
integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== "version" "3.0.0"
dependencies: dependencies:
"@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-coverage" "*"
"@types/istanbul-reports@^3.0.0": "@types/istanbul-reports@^3.0.0":
version "3.0.1" "integrity" "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw=="
resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz" "resolved" "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz"
integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== "version" "3.0.1"
dependencies: dependencies:
"@types/istanbul-lib-report" "*" "@types/istanbul-lib-report" "*"
"@types/node@*": "@types/node@*":
version "17.0.23" "integrity" "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
resolved "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz" "resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz"
integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== "version" "17.0.23"
"@types/stack-utils@^2.0.0": "@types/stack-utils@^2.0.0":
version "2.0.1" "integrity" "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz" "resolved" "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz"
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "version" "2.0.1"
"@types/yaml@^1.9.7": "@types/yaml@^1.9.7":
version "1.9.7" "integrity" "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA=="
resolved "https://registry.yarnpkg.com/@types/yaml/-/yaml-1.9.7.tgz#2331f36e0aac91311a63d33eb026c21687729679" "resolved" "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz"
integrity sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA== "version" "1.9.7"
dependencies: dependencies:
yaml "*" "yaml" "*"
"@types/yargs-parser@*": "@types/yargs-parser@*":
version "21.0.0" "integrity" "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz" "resolved" "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz"
integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== "version" "21.0.0"
"@types/yargs@^16.0.0": "@types/yargs@^16.0.0":
version "16.0.4" "integrity" "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw=="
resolved "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz" "resolved" "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz"
integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== "version" "16.0.4"
dependencies: dependencies:
"@types/yargs-parser" "*" "@types/yargs-parser" "*"
ansi-regex@^5.0.1: "ansi-regex@^5.0.1":
version "5.0.1" "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== "version" "5.0.1"
ansi-styles@^3.2.1: "ansi-styles@^3.2.1":
version "3.2.1" "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== "version" "3.2.1"
dependencies: dependencies:
color-convert "^1.9.0" "color-convert" "^1.9.0"
ansi-styles@^4.1.0: "ansi-styles@^4.1.0":
version "4.3.0" "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== "version" "4.3.0"
dependencies: dependencies:
color-convert "^2.0.1" "color-convert" "^2.0.1"
ansi-styles@^5.0.0: "ansi-styles@^5.0.0":
version "5.2.0" "integrity" "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz"
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== "version" "5.2.0"
braces@^3.0.2: "braces@^3.0.2":
version "3.0.2" "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A=="
resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== "version" "3.0.2"
dependencies: dependencies:
fill-range "^7.0.1" "fill-range" "^7.0.1"
chalk@^2.0.0: "chalk@^2.0.0":
version "2.4.2" "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== "version" "2.4.2"
dependencies: dependencies:
ansi-styles "^3.2.1" "ansi-styles" "^3.2.1"
escape-string-regexp "^1.0.5" "escape-string-regexp" "^1.0.5"
supports-color "^5.3.0" "supports-color" "^5.3.0"
chalk@^4.0.0: "chalk@^4.0.0":
version "4.1.2" "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== "version" "4.1.2"
dependencies: dependencies:
ansi-styles "^4.1.0" "ansi-styles" "^4.1.0"
supports-color "^7.1.0" "supports-color" "^7.1.0"
ci-info@^3.2.0: "ci-info@^3.2.0":
version "3.3.0" "integrity" "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw=="
resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz" "resolved" "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz"
integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== "version" "3.3.0"
color-convert@^1.9.0: "color-convert@^1.9.0":
version "1.9.3" "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="
resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== "version" "1.9.3"
dependencies: dependencies:
color-name "1.1.3" "color-name" "1.1.3"
color-convert@^2.0.1: "color-convert@^2.0.1":
version "2.0.1" "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== "version" "2.0.1"
dependencies: dependencies:
color-name "~1.1.4" "color-name" "~1.1.4"
color-name@1.1.3: "color-name@~1.1.4":
version "1.1.3" "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= "version" "1.1.4"
color-name@~1.1.4: "color-name@1.1.3":
version "1.1.4" "integrity" "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== "version" "1.1.3"
diff-sequences@^27.5.1: "diff-sequences@^27.5.1":
version "27.5.1" "integrity" "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ=="
resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz" "resolved" "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz"
integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== "version" "27.5.1"
escape-string-regexp@^1.0.5: "escape-string-regexp@^1.0.5":
version "1.0.5" "integrity" "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= "version" "1.0.5"
escape-string-regexp@^2.0.0: "escape-string-regexp@^2.0.0":
version "2.0.0" "integrity" "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz"
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== "version" "2.0.0"
expect@^27.5.1: "expect@^27.5.1":
version "27.5.1" "integrity" "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw=="
resolved "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz" "resolved" "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz"
integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== "version" "27.5.1"
dependencies: dependencies:
"@jest/types" "^27.5.1" "@jest/types" "^27.5.1"
jest-get-type "^27.5.1" "jest-get-type" "^27.5.1"
jest-matcher-utils "^27.5.1" "jest-matcher-utils" "^27.5.1"
jest-message-util "^27.5.1" "jest-message-util" "^27.5.1"
fill-range@^7.0.1: "fill-range@^7.0.1":
version "7.0.1" "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ=="
resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== "version" "7.0.1"
dependencies: dependencies:
to-regex-range "^5.0.1" "to-regex-range" "^5.0.1"
graceful-fs@^4.2.9: "graceful-fs@^4.2.9":
version "4.2.9" "integrity" "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz"
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== "version" "4.2.9"
has-flag@^3.0.0: "has-flag@^3.0.0":
version "3.0.0" "integrity" "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= "version" "3.0.0"
has-flag@^4.0.0: "has-flag@^4.0.0":
version "4.0.0" "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== "version" "4.0.0"
is-number@^7.0.0: "is-number@^7.0.0":
version "7.0.0" "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== "version" "7.0.0"
jest-diff@^27.5.1: "jest-diff@^27.5.1":
version "27.5.1" "integrity" "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw=="
resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz" "resolved" "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz"
integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== "version" "27.5.1"
dependencies: dependencies:
chalk "^4.0.0" "chalk" "^4.0.0"
diff-sequences "^27.5.1" "diff-sequences" "^27.5.1"
jest-get-type "^27.5.1" "jest-get-type" "^27.5.1"
pretty-format "^27.5.1" "pretty-format" "^27.5.1"
jest-get-type@^27.5.1: "jest-get-type@^27.5.1":
version "27.5.1" "integrity" "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw=="
resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz" "resolved" "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz"
integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== "version" "27.5.1"
jest-matcher-utils@^27.5.1: "jest-matcher-utils@^27.5.1":
version "27.5.1" "integrity" "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw=="
resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz" "resolved" "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz"
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== "version" "27.5.1"
dependencies: dependencies:
chalk "^4.0.0" "chalk" "^4.0.0"
jest-diff "^27.5.1" "jest-diff" "^27.5.1"
jest-get-type "^27.5.1" "jest-get-type" "^27.5.1"
pretty-format "^27.5.1" "pretty-format" "^27.5.1"
jest-message-util@^27.5.1: "jest-message-util@^27.5.1":
version "27.5.1" "integrity" "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g=="
resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz" "resolved" "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz"
integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== "version" "27.5.1"
dependencies: dependencies:
"@babel/code-frame" "^7.12.13" "@babel/code-frame" "^7.12.13"
"@jest/types" "^27.5.1" "@jest/types" "^27.5.1"
"@types/stack-utils" "^2.0.0" "@types/stack-utils" "^2.0.0"
chalk "^4.0.0" "chalk" "^4.0.0"
graceful-fs "^4.2.9" "graceful-fs" "^4.2.9"
micromatch "^4.0.4" "micromatch" "^4.0.4"
pretty-format "^27.5.1" "pretty-format" "^27.5.1"
slash "^3.0.0" "slash" "^3.0.0"
stack-utils "^2.0.3" "stack-utils" "^2.0.3"
jest-mock@^27.5.1: "jest-mock@^27.5.1":
version "27.5.1" "integrity" "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og=="
resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz" "resolved" "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz"
integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== "version" "27.5.1"
dependencies: dependencies:
"@jest/types" "^27.5.1" "@jest/types" "^27.5.1"
"@types/node" "*" "@types/node" "*"
jest-util@^27.5.1: "jest-util@^27.5.1":
version "27.5.1" "integrity" "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw=="
resolved "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz" "resolved" "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz"
integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== "version" "27.5.1"
dependencies: dependencies:
"@jest/types" "^27.5.1" "@jest/types" "^27.5.1"
"@types/node" "*" "@types/node" "*"
chalk "^4.0.0" "chalk" "^4.0.0"
ci-info "^3.2.0" "ci-info" "^3.2.0"
graceful-fs "^4.2.9" "graceful-fs" "^4.2.9"
picomatch "^2.2.3" "picomatch" "^2.2.3"
js-tokens@^4.0.0: "js-tokens@^4.0.0":
version "4.0.0" "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== "version" "4.0.0"
micromatch@^4.0.4: "micromatch@^4.0.4":
version "4.0.5" "integrity" "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA=="
resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz"
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== "version" "4.0.5"
dependencies: dependencies:
braces "^3.0.2" "braces" "^3.0.2"
picomatch "^2.3.1" "picomatch" "^2.3.1"
picomatch@^2.2.3, picomatch@^2.3.1: "picomatch@^2.2.3", "picomatch@^2.3.1":
version "2.3.1" "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== "version" "2.3.1"
"plugos-silverbullet-syscall@file:../plugos-silverbullet-syscall": "plugos-silverbullet-syscall@file:../plugos-silverbullet-syscall":
version "1.0.0" "resolved" "file:../plugos-silverbullet-syscall"
"version" "1.0.0"
"plugos-syscall@file:../plugos-syscall": "plugos-syscall@file:../plugos-syscall":
version "1.0.0" "resolved" "file:../plugos-syscall"
"version" "1.0.0"
pretty-format@^27.5.1: "pretty-format@^27.5.1":
version "27.5.1" "integrity" "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="
resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz" "resolved" "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz"
integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== "version" "27.5.1"
dependencies: dependencies:
ansi-regex "^5.0.1" "ansi-regex" "^5.0.1"
ansi-styles "^5.0.0" "ansi-styles" "^5.0.0"
react-is "^17.0.1" "react-is" "^17.0.1"
react-is@^17.0.1: "react-is@^17.0.1":
version "17.0.2" "integrity" "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" "resolved" "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== "version" "17.0.2"
slash@^3.0.0: "slash@^3.0.0":
version "3.0.0" "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== "version" "3.0.0"
stack-utils@^2.0.3: "stack-utils@^2.0.3":
version "2.0.5" "integrity" "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA=="
resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz" "resolved" "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz"
integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== "version" "2.0.5"
dependencies: dependencies:
escape-string-regexp "^2.0.0" "escape-string-regexp" "^2.0.0"
supports-color@^5.3.0: "supports-color@^5.3.0":
version "5.5.0" "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== "version" "5.5.0"
dependencies: dependencies:
has-flag "^3.0.0" "has-flag" "^3.0.0"
supports-color@^7.1.0: "supports-color@^7.1.0":
version "7.2.0" "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== "version" "7.2.0"
dependencies: dependencies:
has-flag "^4.0.0" "has-flag" "^4.0.0"
to-regex-range@^5.0.1: "to-regex-range@^5.0.1":
version "5.0.1" "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== "version" "5.0.1"
dependencies: dependencies:
is-number "^7.0.0" "is-number" "^7.0.0"
type-detect@4.0.8: "type-detect@4.0.8":
version "4.0.8" "integrity" "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" "resolved" "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== "version" "4.0.8"
yaml@*, yaml@^2.0.0: "yaml@*", "yaml@^2.0.0":
version "2.0.0" "integrity" "sha512-JbfdlHKGP2Ik9IHylzWlGd4pPK++EU46/IxMykphS2ZKw7a7h+dHNmcXObLgpRDriBY+rpWslldikckX8oruWQ=="
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0.tgz#cbc588ad58e0cd924cd3f5f2b1a9485103048e25" "resolved" "https://registry.npmjs.org/yaml/-/yaml-2.0.0.tgz"
integrity sha512-JbfdlHKGP2Ik9IHylzWlGd4pPK++EU46/IxMykphS2ZKw7a7h+dHNmcXObLgpRDriBY+rpWslldikckX8oruWQ== "version" "2.0.0"

View File

@ -17,10 +17,12 @@ import { NodeCronHook } from "../plugos/hooks/node_cron";
import { markdownSyscalls } from "../common/syscalls/markdown"; import { markdownSyscalls } from "../common/syscalls/markdown";
import { EventedSpacePrimitives } from "../common/spaces/evented_space_primitives"; import { EventedSpacePrimitives } from "../common/spaces/evented_space_primitives";
import { Space } from "../common/spaces/space"; import { Space } from "../common/spaces/space";
import { safeRun } from "../webapp/util"; import { safeRun, throttle } from "../webapp/util";
import { createSandbox } from "../plugos/environments/node_sandbox"; import { createSandbox } from "../plugos/environments/node_sandbox";
import { jwtSyscalls } from "../plugos/syscalls/jwt"; import { jwtSyscalls } from "../plugos/syscalls/jwt";
import { fetchSyscalls } from "../plugos/syscalls/fetch.node"; import { fetchSyscalls } from "../plugos/syscalls/fetch.node";
import buildMarkdown from "../webapp/parser";
import { loadMarkdownExtensions } from "../webapp/markdown_ext";
export class ExpressServer { export class ExpressServer {
app: Express; app: Express;
@ -66,23 +68,29 @@ export class ExpressServer {
system.registerSyscalls([], pageIndexSyscalls(this.db)); system.registerSyscalls([], pageIndexSyscalls(this.db));
system.registerSyscalls([], spaceSyscalls(this.space)); system.registerSyscalls([], spaceSyscalls(this.space));
system.registerSyscalls([], eventSyscalls(this.eventHook)); system.registerSyscalls([], eventSyscalls(this.eventHook));
system.registerSyscalls([], markdownSyscalls()); system.registerSyscalls([], markdownSyscalls(buildMarkdown([])));
system.registerSyscalls([], fetchSyscalls()); system.registerSyscalls([], fetchSyscalls());
system.registerSyscalls([], jwtSyscalls()); system.registerSyscalls([], jwtSyscalls());
system.addHook(new EndpointHook(app, "/_/")); system.addHook(new EndpointHook(app, "/_/"));
let throttledRebuildMdExtensions = throttle(() => {
this.rebuildMdExtensions();
}, 100);
this.space.on({ this.space.on({
plugLoaded: (plugName, plug) => { plugLoaded: (plugName, plug) => {
safeRun(async () => { safeRun(async () => {
console.log("Plug load", plugName); console.log("Plug load", plugName);
await system.load(plugName, plug, createSandbox); await system.load(plugName, plug, createSandbox);
}); });
throttledRebuildMdExtensions();
}, },
plugUnloaded: (plugName) => { plugUnloaded: (plugName) => {
safeRun(async () => { safeRun(async () => {
console.log("Plug unload", plugName); console.log("Plug unload", plugName);
await system.unload(plugName); await system.unload(plugName);
}); });
throttledRebuildMdExtensions();
}, },
}); });
@ -92,6 +100,13 @@ export class ExpressServer {
this.space.updatePageListAsync(); this.space.updatePageListAsync();
} }
rebuildMdExtensions() {
this.system.registerSyscalls(
[],
markdownSyscalls(buildMarkdown(loadMarkdownExtensions(this.system)))
);
}
async init() { async init() {
console.log("Setting up router"); console.log("Setting up router");

View File

@ -27,6 +27,7 @@ import { lineWrapper } from "./line_wrapper";
import { markdown } from "./markdown"; import { markdown } from "./markdown";
import { PathPageNavigator } from "./navigator"; import { PathPageNavigator } from "./navigator";
import customMarkDown from "./parser"; import customMarkDown from "./parser";
import buildMarkdown from "./parser";
import reducer from "./reducer"; import reducer from "./reducer";
import { smartQuoteKeymap } from "./smart_quotes"; import { smartQuoteKeymap } from "./smart_quotes";
import { Space } from "../common/spaces/space"; import { Space } from "../common/spaces/space";
@ -48,6 +49,7 @@ import { pasteLinkExtension } from "./editor_paste";
import { markdownSyscalls } from "../common/syscalls/markdown"; import { markdownSyscalls } from "../common/syscalls/markdown";
import { clientStoreSyscalls } from "./syscalls/clientStore"; import { clientStoreSyscalls } from "./syscalls/clientStore";
import { StatusBar } from "./components/status_bar"; import { StatusBar } from "./components/status_bar";
import { loadMarkdownExtensions, MDExt } from "./markdown_ext";
class PageState { class PageState {
scrollTop: number; scrollTop: number;
@ -77,6 +79,7 @@ export class Editor implements AppEventDispatcher {
this.eventHook.dispatchEvent("editor:updated"); this.eventHook.dispatchEvent("editor:updated");
}, 1000); }, 1000);
private system = new System<SilverBulletHooks>("client"); private system = new System<SilverBulletHooks>("client");
private mdExtensions: MDExt[] = [];
constructor(space: Space, parent: Element) { constructor(space: Space, parent: Element) {
this.space = space; this.space = space;
@ -118,7 +121,10 @@ export class Editor implements AppEventDispatcher {
this.system.registerSyscalls([], spaceSyscalls(this)); this.system.registerSyscalls([], spaceSyscalls(this));
this.system.registerSyscalls([], indexerSyscalls(this.space)); this.system.registerSyscalls([], indexerSyscalls(this.space));
this.system.registerSyscalls([], systemSyscalls(this.space)); this.system.registerSyscalls([], systemSyscalls(this.space));
this.system.registerSyscalls([], markdownSyscalls()); this.system.registerSyscalls(
[],
markdownSyscalls(buildMarkdown(this.mdExtensions))
);
this.system.registerSyscalls([], clientStoreSyscalls()); this.system.registerSyscalls([], clientStoreSyscalls());
} }
@ -270,7 +276,7 @@ export class Editor implements AppEventDispatcher {
history(), history(),
drawSelection(), drawSelection(),
dropCursor(), dropCursor(),
customMarkdownStyle, customMarkdownStyle(this.mdExtensions),
bracketMatching(), bracketMatching(),
closeBrackets(), closeBrackets(),
autocompletion({ autocompletion({
@ -387,7 +393,7 @@ export class Editor implements AppEventDispatcher {
), ),
pasteLinkExtension, pasteLinkExtension,
markdown({ markdown({
base: customMarkDown, base: customMarkDown(this.mdExtensions),
}), }),
], ],
}); });
@ -396,6 +402,14 @@ export class Editor implements AppEventDispatcher {
rebuildEditorState() { rebuildEditorState() {
const editorView = this.editorView; const editorView = this.editorView;
if (editorView && this.currentPage) { if (editorView && this.currentPage) {
this.mdExtensions = loadMarkdownExtensions(this.system);
// And reload the syscalls to use the new syntax extensions
this.system.registerSyscalls(
[],
markdownSyscalls(buildMarkdown(this.mdExtensions))
);
editorView.setState( editorView.setState(
this.createEditorState(this.currentPage, editorView.state.sliceDoc()) this.createEditorState(this.currentPage, editorView.state.sliceDoc())
); );

View File

@ -1,5 +1,7 @@
import { ViewPlugin, ViewUpdate } from "@codemirror/view"; import { ViewPlugin, ViewUpdate } from "@codemirror/view";
import { urlRegexp } from "./parser";
const urlRegexp =
/^https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{1,256}([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
export const pasteLinkExtension = ViewPlugin.fromClass( export const pasteLinkExtension = ViewPlugin.fromClass(
class { class {

66
webapp/markdown_ext.ts Normal file
View File

@ -0,0 +1,66 @@
import { Tag } from "@codemirror/highlight";
import type { MarkdownConfig } from "@lezer/markdown";
import { System } from "../plugos/system";
import { Manifest } from "../common/manifest";
export type MDExt = {
// unicode char code for efficiency .charCodeAt(0)
firstCharCodes: number[];
regex: RegExp;
nodeType: string;
tag: Tag;
styles: { [key: string]: string };
};
export function mdExtensionSyntaxConfig({
regex,
firstCharCodes,
nodeType,
}: MDExt): MarkdownConfig {
return {
defineNodes: [nodeType],
parseInline: [
{
name: nodeType,
parse(cx, next, pos) {
if (!firstCharCodes.includes(next)) {
return -1;
}
let match = regex.exec(cx.slice(pos, cx.end));
if (!match) {
return -1;
}
return cx.addElement(cx.elt(nodeType, pos, pos + match[0].length));
},
after: "Emphasis",
},
],
};
}
export function mdExtensionStyleTags({ nodeType, tag }: MDExt): {
[selector: string]: Tag | readonly Tag[];
} {
return {
[nodeType]: tag,
};
}
export function loadMarkdownExtensions(system: System<any>): MDExt[] {
let mdExtensions: MDExt[] = [];
for (let plug of system.loadedPlugs.values()) {
let manifest = plug.manifest as Manifest;
if (manifest.syntax) {
for (let [nodeType, def] of Object.entries(manifest.syntax)) {
mdExtensions.push({
nodeType,
tag: Tag.define(),
firstCharCodes: def.firstCharacters.map((ch) => ch.charCodeAt(0)),
regex: new RegExp("^" + def.regex),
styles: def.styles,
});
}
}
}
return mdExtensions;
}

View File

@ -1,11 +1,12 @@
import { styleTags, tags as t } from "@codemirror/highlight"; import { styleTags } from "@codemirror/highlight";
import { BlockContext, LeafBlock, LeafBlockParser, MarkdownConfig, parseCode, TaskList } from "@lezer/markdown"; import { BlockContext, LeafBlock, LeafBlockParser, MarkdownConfig, parseCode, TaskList } from "@lezer/markdown";
import { commonmark, getCodeParser, mkLang } from "./markdown/markdown"; import { commonmark, getCodeParser, mkLang } from "./markdown/markdown";
import * as ct from "./customtags"; import * as ct from "./customtags";
import { LanguageDescription, LanguageSupport } from "@codemirror/language"; import { Language, LanguageDescription, LanguageSupport } from "@codemirror/language";
import { StreamLanguage } from "@codemirror/stream-parser"; import { StreamLanguage } from "@codemirror/stream-parser";
import { yaml } from "@codemirror/legacy-modes/mode/yaml"; import { yaml } from "@codemirror/legacy-modes/mode/yaml";
import { javascriptLanguage } from "@codemirror/lang-javascript"; import { javascriptLanguage } from "@codemirror/lang-javascript";
import { MDExt, mdExtensionStyleTags, mdExtensionSyntaxConfig } from "./markdown_ext";
export const pageLinkRegex = /^\[\[([^\]]+)\]\]/; export const pageLinkRegex = /^\[\[([^\]]+)\]\]/;
@ -37,51 +38,6 @@ const WikiLink: MarkdownConfig = {
], ],
}; };
const AtMention: MarkdownConfig = {
defineNodes: ["AtMention"],
parseInline: [
{
name: "AtMention",
parse(cx, next, pos) {
let match: RegExpMatchArray | null;
if (
next != 64 /* '@' */ ||
!(match = /^[A-Za-z\.]+/.exec(cx.slice(pos + 1, cx.end)))
) {
return -1;
}
return cx.addElement(
cx.elt("AtMention", pos, pos + 1 + match[0].length)
);
},
after: "Emphasis",
},
],
};
export const urlRegexp =
/^https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{1,256}([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
const UnmarkedUrl: MarkdownConfig = {
defineNodes: ["URL"],
parseInline: [
{
name: "URL",
parse(cx, next, pos) {
let match: RegExpMatchArray | null;
if (
next != 104 /* 'h' */ ||
!(match = urlRegexp.exec(cx.slice(pos, cx.end)))
) {
return -1;
}
return cx.addElement(cx.elt("URL", pos, pos + match[0].length));
},
after: "Emphasis",
},
],
};
class CommentParser implements LeafBlockParser { class CommentParser implements LeafBlockParser {
nextLine() { nextLine() {
return false; return false;
@ -111,60 +67,40 @@ export const Comment: MarkdownConfig = {
], ],
}; };
const TagLink: MarkdownConfig = { export default function buildMarkdown(mdExtensions: MDExt[]): Language {
defineNodes: ["TagLink"], return mkLang(
parseInline: [ commonmark.configure([
{ WikiLink,
name: "TagLink", TaskList,
parse(cx, next, pos) { Comment,
let match: RegExpMatchArray | null; ...mdExtensions.map(mdExtensionSyntaxConfig),
if ( parseCode({
next != 35 /* '#' */ || codeParser: getCodeParser([
!(match = /^[A-Za-z\.]+/.exec(cx.slice(pos + 1, cx.end))) LanguageDescription.of({
) { name: "yaml",
return -1; support: new LanguageSupport(StreamLanguage.define(yaml)),
} }),
return cx.addElement(cx.elt("TagLink", pos, pos + 1 + match[0].length)); LanguageDescription.of({
name: "javascript",
alias: ["js"],
support: new LanguageSupport(javascriptLanguage),
}),
]),
}),
{
props: [
styleTags({
WikiLink: ct.WikiLinkTag,
WikiLinkPage: ct.WikiLinkPageTag,
Task: ct.TaskTag,
TaskMarker: ct.TaskMarkerTag,
Comment: ct.CommentTag,
}),
...mdExtensions.map((mdExt) =>
styleTags(mdExtensionStyleTags(mdExt))
),
],
}, },
after: "Emphasis", ])
}, );
], }
};
const WikiMarkdown = commonmark.configure([
WikiLink,
AtMention,
// TagLink,
TaskList,
UnmarkedUrl,
Comment,
parseCode({
codeParser: getCodeParser([
LanguageDescription.of({
name: "yaml",
support: new LanguageSupport(StreamLanguage.define(yaml)),
}),
LanguageDescription.of({
name: "javascript",
alias: ["js"],
support: new LanguageSupport(javascriptLanguage),
}),
]),
}),
{
props: [
styleTags({
WikiLink: ct.WikiLinkTag,
WikiLinkPage: ct.WikiLinkPageTag,
AtMention: ct.MentionTag,
TagLink: ct.TagTag,
Task: ct.TaskTag,
TaskMarker: ct.TaskMarkerTag,
Url: t.url,
Comment: ct.CommentTag,
}),
],
},
]);
export default mkLang(WikiMarkdown);

View File

@ -19,7 +19,6 @@ async function activate() {
self.addEventListener("activate", (e) => e.waitUntil(activate())); self.addEventListener("activate", (e) => e.waitUntil(activate()));
self.addEventListener("fetch", (event: any) => { self.addEventListener("fetch", (event: any) => {
return;
event.respondWith( event.respondWith(
caches.open(version).then(async (cache) => { caches.open(version).then(async (cache) => {
let parsedUrl = new URL(event.request.url); let parsedUrl = new URL(event.request.url);

View File

@ -1,38 +1,44 @@
import { HighlightStyle, tags as t } from "@codemirror/highlight"; import { HighlightStyle, tags as t } from "@codemirror/highlight";
import * as ct from "./customtags"; import * as ct from "./customtags";
import { MDExt } from "./markdown_ext";
export default HighlightStyle.define([ export default function highlightStyles(mdExtension: MDExt[]) {
{ tag: t.heading1, class: "h1" }, return HighlightStyle.define([
{ tag: t.heading2, class: "h2" }, { tag: t.heading1, class: "h1" },
{ tag: t.heading3, class: "h3" }, { tag: t.heading2, class: "h2" },
{ tag: t.link, class: "link" }, { tag: t.heading3, class: "h3" },
{ tag: t.meta, class: "meta" }, { tag: t.link, class: "link" },
{ tag: t.quote, class: "quote" }, { tag: t.meta, class: "meta" },
{ tag: t.monospace, class: "code" }, { tag: t.quote, class: "quote" },
{ tag: t.url, class: "url" }, { tag: t.monospace, class: "code" },
{ tag: ct.WikiLinkTag, class: "wiki-link" }, { tag: t.url, class: "url" },
{ tag: ct.WikiLinkPageTag, class: "wiki-link-page" }, { tag: ct.WikiLinkTag, class: "wiki-link" },
{ tag: ct.TagTag, class: "tag" }, { tag: ct.WikiLinkPageTag, class: "wiki-link-page" },
{ tag: ct.MentionTag, class: "mention" }, { tag: ct.TagTag, class: "tag" },
{ tag: ct.TaskTag, class: "task" }, { tag: ct.MentionTag, class: "mention" },
{ tag: ct.TaskMarkerTag, class: "task-marker" }, { tag: ct.TaskTag, class: "task" },
{ tag: ct.CommentTag, class: "comment" }, { tag: ct.TaskMarkerTag, class: "task-marker" },
{ tag: ct.CommentMarkerTag, class: "comment-marker" }, { tag: ct.CommentTag, class: "comment" },
{ tag: t.emphasis, class: "emphasis" }, { tag: ct.CommentMarkerTag, class: "comment-marker" },
{ tag: t.strong, class: "strong" }, { tag: t.emphasis, class: "emphasis" },
{ tag: t.atom, class: "atom" }, { tag: t.strong, class: "strong" },
{ tag: t.bool, class: "bool" }, { tag: t.atom, class: "atom" },
{ tag: t.url, class: "url" }, { tag: t.bool, class: "bool" },
{ tag: t.inserted, class: "inserted" }, { tag: t.url, class: "url" },
{ tag: t.deleted, class: "deleted" }, { tag: t.inserted, class: "inserted" },
{ tag: t.literal, class: "literal" }, { tag: t.deleted, class: "deleted" },
{ tag: t.list, class: "list" }, { tag: t.literal, class: "literal" },
{ tag: t.definition, class: "li" }, { tag: t.list, class: "list" },
{ tag: t.string, class: "string" }, { tag: t.definition, class: "li" },
{ tag: t.number, class: "number" }, { tag: t.string, class: "string" },
{ tag: [t.regexp, t.escape, t.special(t.string)], class: "string2" }, { tag: t.number, class: "number" },
{ tag: t.variableName, class: "variableName" }, { tag: [t.regexp, t.escape, t.special(t.string)], class: "string2" },
{ tag: t.comment, class: "comment" }, { tag: t.variableName, class: "variableName" },
{ tag: t.invalid, class: "invalid" }, { tag: t.comment, class: "comment" },
{ tag: t.punctuation, class: "punctuation" }, { tag: t.invalid, class: "invalid" },
]); { tag: t.punctuation, class: "punctuation" },
...mdExtension.map((mdExt) => {
return { tag: mdExt.tag, ...mdExt.styles };
}),
]);
}