From b3c3302970e890b6c9bb18010a35a16c84abd515 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Mon, 11 Apr 2022 20:34:09 +0200 Subject: [PATCH] Materialized query parser redo --- common/manifest.ts | 12 +- common/parse_tree.ts | 84 +++ common/syscalls/markdown.ts | 10 +- {plugs/lib => common}/tree.test.ts | 12 +- common/tree.ts | 194 ++++--- package.json | 3 +- plugos-silverbullet-syscall/markdown.ts | 5 +- plugs/core/core.plug.yaml | 34 +- plugs/core/dates.ts | 10 +- plugs/core/item.ts | 10 +- plugs/core/navigate.ts | 22 +- plugs/core/page.ts | 22 +- plugs/lib/tree.ts | 124 ---- plugs/markdown/markdown.ts | 4 +- plugs/package-lock.json | 83 ++- plugs/package.json | 5 + plugs/query/engine.test.ts | 70 +++ plugs/query/engine.ts | 154 +++++ plugs/{core => query}/materialized_queries.ts | 22 +- plugs/query/query.grammar | 44 ++ plugs/query/query.plug.yaml | 7 + plugs/tasks/task.ts | 29 +- plugs/tasks/tasks.plug.yaml | 19 + plugs/yarn.lock | 542 +++++++++--------- server/api_server.ts | 19 +- webapp/editor.tsx | 20 +- webapp/editor_paste.ts | 4 +- webapp/markdown_ext.ts | 66 +++ webapp/parser.ts | 142 ++--- webapp/service_worker.ts | 1 - webapp/style.ts | 76 +-- 31 files changed, 1182 insertions(+), 667 deletions(-) create mode 100644 common/parse_tree.ts rename {plugs/lib => common}/tree.test.ts (84%) delete mode 100644 plugs/lib/tree.ts create mode 100644 plugs/query/engine.test.ts create mode 100644 plugs/query/engine.ts rename plugs/{core => query}/materialized_queries.ts (90%) create mode 100644 plugs/query/query.grammar create mode 100644 plugs/query/query.plug.yaml create mode 100644 webapp/markdown_ext.ts diff --git a/common/manifest.ts b/common/manifest.ts index a9716d87..acecdcde 100644 --- a/common/manifest.ts +++ b/common/manifest.ts @@ -13,4 +13,14 @@ export type SilverBulletHooks = CommandHookT & CronHookT & EventHookT; -export type Manifest = plugos.Manifest; +export type SyntaxExtensions = { + syntax?: { [key: string]: NodeDef }; +}; + +export type NodeDef = { + firstCharacters: string[]; + regex: string; + styles: { [key: string]: string }; +}; + +export type Manifest = plugos.Manifest & SyntaxExtensions; diff --git a/common/parse_tree.ts b/common/parse_tree.ts new file mode 100644 index 00000000..91f44429 --- /dev/null +++ b/common/parse_tree.ts @@ -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; +} diff --git a/common/syscalls/markdown.ts b/common/syscalls/markdown.ts index 53d0c07a..4d0a5ff7 100644 --- a/common/syscalls/markdown.ts +++ b/common/syscalls/markdown.ts @@ -1,10 +1,12 @@ 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 { - "markdown.parseMarkdown": (ctx, text: string): MarkdownTree => { - return parse(text); + "markdown.parseMarkdown": (ctx, text: string): ParseTree => { + return parse(lang, text); }, }; } diff --git a/plugs/lib/tree.test.ts b/common/tree.test.ts similarity index 84% rename from plugs/lib/tree.test.ts rename to common/tree.test.ts index d9998c5c..be6c766e 100644 --- a/plugs/lib/tree.test.ts +++ b/common/tree.test.ts @@ -1,14 +1,15 @@ import { expect, test } from "@jest/globals"; -import { parse } from "../../common/tree"; +import { parse } from "./parse_tree"; import { addParentPointers, collectNodesMatching, findParentMatching, nodeAtPos, removeParentPointers, - renderMarkdown, + renderToText, replaceNodesMatching } from "./tree"; +import wikiMarkdownLang from "../webapp/parser"; const mdTest1 = ` # Heading @@ -46,7 +47,8 @@ name: something `; test("Run a Node sandbox", async () => { - let mdTree = parse(mdTest1); + const lang = wikiMarkdownLang([]); + let mdTree = parse(lang, mdTest1); addParentPointers(mdTree); // console.log(JSON.stringify(mdTree, null, 2)); let wikiLink = nodeAtPos(mdTree, mdTest1.indexOf("Wiki Page"))!; @@ -59,7 +61,7 @@ test("Run a Node sandbox", async () => { expect(allTodos.length).toBe(2); // Render back into markdown should be equivalent - expect(renderMarkdown(mdTree)).toBe(mdTest1); + expect(renderToText(mdTree)).toBe(mdTest1); removeParentPointers(mdTree); replaceNodesMatching(mdTree, (n) => { @@ -70,6 +72,6 @@ test("Run a Node sandbox", async () => { } }); console.log(JSON.stringify(mdTree, null, 2)); - let mdTree3 = parse(mdTest3); + let mdTree3 = parse(lang, mdTest3); console.log(JSON.stringify(mdTree3, null, 2)); }); diff --git a/common/tree.ts b/common/tree.ts index 9fd00dd3..ea4b1e85 100644 --- a/common/tree.ts +++ b/common/tree.ts @@ -1,87 +1,137 @@ -import { SyntaxNode } from "@lezer/common"; -import wikiMarkdownLang from "../webapp/parser"; - -export type MarkdownTree = { +export type ParseTree = { type?: string; // undefined === text node from?: number; to?: number; text?: string; - children?: MarkdownTree[]; + children?: ParseTree[]; + // Only present after running addParentPointers + parent?: ParseTree; }; -function treeToAST(text: string, n: SyntaxNode, offset = 0): MarkdownTree { - let children: MarkdownTree[] = []; - let nodeText: string | undefined; - let child = n.firstChild; - while (child) { - children.push(treeToAST(text, child)); - child = child.nextSibling; +export function addParentPointers(tree: ParseTree) { + if (!tree.children) { + return; } + for (let child of tree.children) { + child.parent = tree; + addParentPointers(child); + } +} - if (children.length === 0) { - children = [ - { - from: n.from + offset, - to: n.to + offset, - text: text.substring(n.from, n.to), - }, - ]; - } else { - let newChildren: MarkdownTree[] | string = []; - let index = n.from; +export function removeParentPointers(tree: ParseTree) { + delete tree.parent; + if (!tree.children) { + return; + } + for (let child of tree.children) { + removeParentPointers(child); + } +} + +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) { - let s = text.substring(index, child.from); - if (s) { - newChildren.push({ - from: index + offset, - to: child.from! + offset, - text: s, - }); + let subst = substituteFn(child); + if (subst !== undefined) { + let pos = tree.children.indexOf(child); + if (subst) { + tree.children.splice(pos, 1, subst); + } 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 { - let tree = treeToAST(text, wikiMarkdownLang.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; +export function findNodeMatching( + tree: ParseTree, + matchFn: (tree: ParseTree) => boolean +): ParseTree | null { + return collectNodesMatching(tree, matchFn)[0]; +} + +export function findNodeOfType( + tree: ParseTree, + nodeType: string +): ParseTree | null { + return collectNodesMatching(tree, (n) => n.type === nodeType)[0]; +} + +// Finds non-text node at position +export function nodeAtPos(tree: ParseTree, pos: number): ParseTree | null { + if (pos < tree.from! || pos > tree.to!) { + return null; + } + if (!tree.children) { + 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(""); } diff --git a/package.json b/package.json index f4c9c375..314083f1 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ }, "test": { "source": [ - "plugs/lib/tree.test.ts", + "common/tree.test.ts", + "plugs/query/engine.test.ts", "common/spaces/sync.test.ts" ], "includeNodeModules": ["@codemirror/legacy-modes"], diff --git a/plugos-silverbullet-syscall/markdown.ts b/plugos-silverbullet-syscall/markdown.ts index de11461d..62ac5f47 100644 --- a/plugos-silverbullet-syscall/markdown.ts +++ b/plugos-silverbullet-syscall/markdown.ts @@ -1,6 +1,7 @@ import { syscall } from "./syscall"; -import type { MarkdownTree } from "../common/tree"; -export async function parseMarkdown(text: string): Promise { +import type { ParseTree } from "../common/tree"; + +export async function parseMarkdown(text: string): Promise { return syscall("markdown.parseMarkdown", text); } diff --git a/plugs/core/core.plug.yaml b/plugs/core/core.plug.yaml index c0a72760..bae1823d 100644 --- a/plugs/core/core.plug.yaml +++ b/plugs/core/core.plug.yaml @@ -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: clearPageIndex: path: "./page.ts:clearPageIndex" @@ -55,13 +75,13 @@ functions: path: "./dates.ts:indexDates" events: - page:index - updateMaterializedQueriesOnPage: - path: ./materialized_queries.ts:updateMaterializedQueriesOnPage - updateMaterializedQueriesCommand: - path: ./materialized_queries.ts:updateMaterializedQueriesCommand + parseServerCommand: + path: ./page.ts:parseServerPageCommand command: - name: "Materialized Queries: Update" - parseCommand: + name: "Debug: Parse Document on Server" + parsePage: path: ./page.ts:parsePage + parseCommand: + path: ./page.ts:parsePageCommand command: - name: Parse Document + name: "Debug: Parse Document" diff --git a/plugs/core/dates.ts b/plugs/core/dates.ts index dff88fe0..2474c77b 100644 --- a/plugs/core/dates.ts +++ b/plugs/core/dates.ts @@ -1,7 +1,7 @@ import { insertAtCursor } from "plugos-silverbullet-syscall/editor"; import { IndexEvent } from "../../webapp/app_event"; 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; @@ -23,12 +23,16 @@ export async function indexDates({ name, text }: IndexEvent) { await batchSet(name, dates); } +export function niceDate(d: Date): string { + return new Date().toISOString().split("T")[0]; +} + export async function insertToday() { - await insertAtCursor(new Date().toISOString().split("T")[0]); + await insertAtCursor(niceDate(new Date())); } export async function insertTomorrow() { let d = new Date(); d.setDate(d.getDate() + 1); - await insertAtCursor(d.toISOString().split("T")[0]); + await insertAtCursor(niceDate(d)); } diff --git a/plugs/core/item.ts b/plugs/core/item.ts index 4965af50..68bbdb23 100644 --- a/plugs/core/item.ts +++ b/plugs/core/item.ts @@ -1,9 +1,9 @@ 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 { parseMarkdown } from "plugos-silverbullet-syscall/markdown"; -import { collectNodesMatching, MarkdownTree, renderMarkdown } from "../lib/tree"; +import { collectNodesMatching, ParseTree, renderToText } from "../../common/tree"; type Item = { item: string; @@ -23,16 +23,16 @@ export async function indexItems({ name, text }: IndexEvent) { if (!n.children) { return; } - let textNodes: MarkdownTree[] = []; + let textNodes: ParseTree[] = []; let nested: string | undefined; for (let child of n.children!.slice(1)) { if (child.type === "OrderedList" || child.type === "BulletList") { - nested = renderMarkdown(child); + nested = renderToText(child); break; } textNodes.push(child); } - let item = textNodes.map(renderMarkdown).join("").trim(); + let item = textNodes.map(renderToText).join("").trim(); let value: Item = { item, }; diff --git a/plugs/core/navigate.ts b/plugs/core/navigate.ts index e0a492a3..a3ad2ca6 100644 --- a/plugs/core/navigate.ts +++ b/plugs/core/navigate.ts @@ -1,13 +1,11 @@ import { ClickEvent } from "../../webapp/app_event"; -import { updateMaterializedQueriesCommand } from "./materialized_queries"; 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 { MarkdownTree, nodeAtPos } from "../lib/tree"; +import { nodeAtPos, ParseTree } from "../../common/tree"; const materializedQueryPrefix = /)(.+?)()/gs; +export const newQueryRegex = + /)-->(.+?)/gs; + export function whiteOutQueries(text: string): string { - return text.replaceAll(queryRegex, (match) => + return text.replaceAll(newQueryRegex, (match) => new Array(match.length + 1).join(" ") ); } @@ -40,6 +44,17 @@ export async function updateMaterializedQueriesCommand() { 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 export async function updateMaterializedQueriesOnPage(pageName: string) { let { text } = await readPage(pageName); @@ -50,6 +65,7 @@ export async function updateMaterializedQueriesOnPage(pageName: string) { const startQuery = args[0]; const endQuery = args[args.length - 4]; let results = []; + filter = filter && replaceTemplateVars(filter); switch (table) { case "page": let pages = await listPages(); @@ -94,21 +110,17 @@ export async function updateMaterializedQueriesOnPage(pageName: string) { return `${startQuery}\n${results.sort().join("\n")}\n${endQuery}`; case "link": let uniqueLinks = new Set(); - console.log("Here!!"); for (let { key, page, value: name } of await scanPrefixGlobal( `pl:${pageName}:` )) { - console.log("Here!!"); let [, pos] = key.split(":"); if (!filter || (filter && name.includes(filter))) { uniqueLinks.add(name); } } - console.log("Here!!"); for (const uniqueResult of uniqueLinks) { results.push(`* [[${uniqueResult}]]`); } - console.log("Here!!"); return `${startQuery}\n${results.sort().join("\n")}\n${endQuery}`; case "item": for (let { diff --git a/plugs/query/query.grammar b/plugs/query/query.grammar new file mode 100644 index 00000000..e2aa90b1 --- /dev/null +++ b/plugs/query/query.grammar @@ -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+ } +} diff --git a/plugs/query/query.plug.yaml b/plugs/query/query.plug.yaml new file mode 100644 index 00000000..ae6c373a --- /dev/null +++ b/plugs/query/query.plug.yaml @@ -0,0 +1,7 @@ +functions: + updateMaterializedQueriesOnPage: + path: ./materialized_queries.ts:updateMaterializedQueriesOnPage + updateMaterializedQueriesCommand: + path: ./materialized_queries.ts:updateMaterializedQueriesCommand + command: + name: "Materialized Queries: Update" diff --git a/plugs/tasks/task.ts b/plugs/tasks/task.ts index 6cdc8bef..eb547014 100644 --- a/plugs/tasks/task.ts +++ b/plugs/tasks/task.ts @@ -1,16 +1,23 @@ import type { ClickEvent } 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 { readPage, writePage } from "plugos-silverbullet-syscall/space"; import { parseMarkdown } from "plugos-silverbullet-syscall/markdown"; 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 = { task: string; complete: boolean; + deadline?: string; pos?: number; nested?: string; }; @@ -21,23 +28,29 @@ export async function indexTasks({ name, text }: IndexEvent) { text = whiteOutQueries(text); let mdTree = await parseMarkdown(text); addParentPointers(mdTree); - collectNodesMatching(mdTree, (n) => n.type === "Task").forEach((n) => { - let task = n.children!.slice(1).map(renderMarkdown).join("").trim(); + collectNodesOfType(mdTree, "Task").forEach((n) => { + let task = n.children!.slice(1).map(renderToText).join("").trim(); let complete = n.children![0].children![0].text! !== "[ ]"; - let value: Task = { task, 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 nestedItems = n.parent!.children!.slice(taskIndex + 1); if (nestedItems.length > 0) { - value.nested = nestedItems.map(renderMarkdown).join("").trim(); + value.nested = nestedItems.map(renderToText).join("").trim(); } tasks.push({ key: `task:${n.from}`, value, }); + // console.log("Task", value); }); console.log("Found", tasks.length, "task(s)"); @@ -95,9 +108,9 @@ export async function taskToggleAtPos(pos: number) { taskMarkerNode.children![0].text = changeTo; console.log( "This will be the new marker", - renderMarkdown(taskMarkerNode) + renderToText(taskMarkerNode) ); - text = renderMarkdown(referenceMdTree); + text = renderToText(referenceMdTree); console.log("Updated reference paged text", text); await writePage(page, text); } diff --git a/plugs/tasks/tasks.plug.yaml b/plugs/tasks/tasks.plug.yaml index 4f33dd42..06c58610 100644 --- a/plugs/tasks/tasks.plug.yaml +++ b/plugs/tasks/tasks.plug.yaml @@ -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: indexTasks: path: "./task.ts:indexTasks" diff --git a/plugs/yarn.lock b/plugs/yarn.lock index 7322688e..3868630c 100644 --- a/plugs/yarn.lock +++ b/plugs/yarn.lock @@ -3,396 +3,418 @@ "@babel/code-frame@^7.12.13": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + "integrity" "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" + "version" "7.16.7" dependencies: "@babel/highlight" "^7.16.7" "@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + "integrity" "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" + "version" "7.16.7" "@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + "integrity" "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==" + "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz" + "version" "7.16.10" dependencies: "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" + "chalk" "^2.0.0" + "js-tokens" "^4.0.0" "@jest/environment@^27.5.1": - version "27.5.1" - resolved "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz" - integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA== + "integrity" "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==" + "resolved" "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz" + "version" "27.5.1" dependencies: "@jest/fake-timers" "^27.5.1" "@jest/types" "^27.5.1" "@types/node" "*" - jest-mock "^27.5.1" + "jest-mock" "^27.5.1" "@jest/fake-timers@^27.5.1": - version "27.5.1" - resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz" - integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ== + "integrity" "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==" + "resolved" "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz" + "version" "27.5.1" dependencies: "@jest/types" "^27.5.1" "@sinonjs/fake-timers" "^8.0.1" "@types/node" "*" - jest-message-util "^27.5.1" - jest-mock "^27.5.1" - jest-util "^27.5.1" + "jest-message-util" "^27.5.1" + "jest-mock" "^27.5.1" + "jest-util" "^27.5.1" "@jest/globals@^27.5.1": - version "27.5.1" - resolved "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz" - integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q== + "integrity" "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==" + "resolved" "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz" + "version" "27.5.1" dependencies: "@jest/environment" "^27.5.1" "@jest/types" "^27.5.1" - expect "^27.5.1" + "expect" "^27.5.1" "@jest/types@^27.5.1": - version "27.5.1" - resolved "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz" - integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + "integrity" "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==" + "resolved" "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz" + "version" "27.5.1" dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" "@types/node" "*" "@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": - version "1.8.3" - resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + "integrity" "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==" + "resolved" "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz" + "version" "1.8.3" dependencies: - type-detect "4.0.8" + "type-detect" "4.0.8" "@sinonjs/fake-timers@^8.0.1": - version "8.1.0" - resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz" - integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg== + "integrity" "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==" + "resolved" "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz" + "version" "8.1.0" dependencies: "@sinonjs/commons" "^1.7.0" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.4" - resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + "integrity" "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + "resolved" "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz" + "version" "2.0.4" "@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + "integrity" "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==" + "resolved" "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" + "version" "3.0.0" dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + "integrity" "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==" + "resolved" "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz" + "version" "3.0.1" dependencies: "@types/istanbul-lib-report" "*" "@types/node@*": - version "17.0.23" - resolved "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz" - integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== + "integrity" "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz" + "version" "17.0.23" "@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + "integrity" "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + "resolved" "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz" + "version" "2.0.1" "@types/yaml@^1.9.7": - version "1.9.7" - resolved "https://registry.yarnpkg.com/@types/yaml/-/yaml-1.9.7.tgz#2331f36e0aac91311a63d33eb026c21687729679" - integrity sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA== + "integrity" "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==" + "resolved" "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz" + "version" "1.9.7" dependencies: - yaml "*" + "yaml" "*" "@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + "integrity" "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + "resolved" "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz" + "version" "21.0.0" "@types/yargs@^16.0.0": - version "16.0.4" - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz" - integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + "integrity" "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==" + "resolved" "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz" + "version" "16.0.4" dependencies: "@types/yargs-parser" "*" -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +"ansi-regex@^5.0.1": + "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + "version" "5.0.1" -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== +"ansi-styles@^3.2.1": + "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + "version" "3.2.1" dependencies: - color-convert "^1.9.0" + "color-convert" "^1.9.0" -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== +"ansi-styles@^4.1.0": + "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + "version" "4.3.0" dependencies: - color-convert "^2.0.1" + "color-convert" "^2.0.1" -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +"ansi-styles@^5.0.0": + "integrity" "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" + "version" "5.2.0" -braces@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +"braces@^3.0.2": + "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" + "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + "version" "3.0.2" dependencies: - fill-range "^7.0.1" + "fill-range" "^7.0.1" -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== +"chalk@^2.0.0": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== +"chalk@^4.0.0": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" -ci-info@^3.2.0: - version "3.3.0" - resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz" - integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== +"ci-info@^3.2.0": + "integrity" "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==" + "resolved" "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz" + "version" "3.3.0" -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== +"color-convert@^1.9.0": + "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + "version" "1.9.3" dependencies: - color-name "1.1.3" + "color-name" "1.1.3" -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== +"color-convert@^2.0.1": + "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + "version" "2.0.1" dependencies: - color-name "~1.1.4" + "color-name" "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +"color-name@~1.1.4": + "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + "version" "1.1.4" -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +"color-name@1.1.3": + "integrity" "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + "version" "1.1.3" -diff-sequences@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz" - integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== +"diff-sequences@^27.5.1": + "integrity" "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + "resolved" "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz" + "version" "27.5.1" -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +"escape-string-regexp@^1.0.5": + "integrity" "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== +"escape-string-regexp@^2.0.0": + "integrity" "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" + "version" "2.0.0" -expect@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz" - integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw== +"expect@^27.5.1": + "integrity" "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==" + "resolved" "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz" + "version" "27.5.1" dependencies: "@jest/types" "^27.5.1" - jest-get-type "^27.5.1" - jest-matcher-utils "^27.5.1" - jest-message-util "^27.5.1" + "jest-get-type" "^27.5.1" + "jest-matcher-utils" "^27.5.1" + "jest-message-util" "^27.5.1" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +"fill-range@^7.0.1": + "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" + "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + "version" "7.0.1" dependencies: - to-regex-range "^5.0.1" + "to-regex-range" "^5.0.1" -graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +"graceful-fs@^4.2.9": + "integrity" "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" + "version" "4.2.9" -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +"has-flag@^3.0.0": + "integrity" "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + "version" "3.0.0" -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +"has-flag@^4.0.0": + "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + "version" "4.0.0" -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +"is-number@^7.0.0": + "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + "version" "7.0.0" -jest-diff@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz" - integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== +"jest-diff@^27.5.1": + "integrity" "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==" + "resolved" "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz" + "version" "27.5.1" dependencies: - chalk "^4.0.0" - diff-sequences "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" + "chalk" "^4.0.0" + "diff-sequences" "^27.5.1" + "jest-get-type" "^27.5.1" + "pretty-format" "^27.5.1" -jest-get-type@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz" - integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== +"jest-get-type@^27.5.1": + "integrity" "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + "resolved" "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz" + "version" "27.5.1" -jest-matcher-utils@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz" - integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== +"jest-matcher-utils@^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" + "version" "27.5.1" dependencies: - chalk "^4.0.0" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" + "chalk" "^4.0.0" + "jest-diff" "^27.5.1" + "jest-get-type" "^27.5.1" + "pretty-format" "^27.5.1" -jest-message-util@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz" - integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g== +"jest-message-util@^27.5.1": + "integrity" "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==" + "resolved" "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz" + "version" "27.5.1" dependencies: "@babel/code-frame" "^7.12.13" "@jest/types" "^27.5.1" "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^27.5.1" - slash "^3.0.0" - stack-utils "^2.0.3" + "chalk" "^4.0.0" + "graceful-fs" "^4.2.9" + "micromatch" "^4.0.4" + "pretty-format" "^27.5.1" + "slash" "^3.0.0" + "stack-utils" "^2.0.3" -jest-mock@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz" - integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== +"jest-mock@^27.5.1": + "integrity" "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==" + "resolved" "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz" + "version" "27.5.1" dependencies: "@jest/types" "^27.5.1" "@types/node" "*" -jest-util@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz" - integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw== +"jest-util@^27.5.1": + "integrity" "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==" + "resolved" "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz" + "version" "27.5.1" dependencies: "@jest/types" "^27.5.1" "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" + "chalk" "^4.0.0" + "ci-info" "^3.2.0" + "graceful-fs" "^4.2.9" + "picomatch" "^2.2.3" -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +"js-tokens@^4.0.0": + "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + "version" "4.0.0" -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== +"micromatch@^4.0.4": + "integrity" "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==" + "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" + "version" "4.0.5" dependencies: - braces "^3.0.2" - picomatch "^2.3.1" + "braces" "^3.0.2" + "picomatch" "^2.3.1" -picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +"picomatch@^2.2.3", "picomatch@^2.3.1": + "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + "version" "2.3.1" "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": - version "1.0.0" + "resolved" "file:../plugos-syscall" + "version" "1.0.0" -pretty-format@^27.5.1: - version "27.5.1" - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz" - integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== +"pretty-format@^27.5.1": + "integrity" "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==" + "resolved" "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz" + "version" "27.5.1" dependencies: - ansi-regex "^5.0.1" - ansi-styles "^5.0.0" - react-is "^17.0.1" + "ansi-regex" "^5.0.1" + "ansi-styles" "^5.0.0" + "react-is" "^17.0.1" -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +"react-is@^17.0.1": + "integrity" "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "resolved" "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" + "version" "17.0.2" -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +"slash@^3.0.0": + "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + "version" "3.0.0" -stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== +"stack-utils@^2.0.3": + "integrity" "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==" + "resolved" "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz" + "version" "2.0.5" dependencies: - escape-string-regexp "^2.0.0" + "escape-string-regexp" "^2.0.0" -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== +"supports-color@^5.3.0": + "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + "version" "5.5.0" dependencies: - has-flag "^3.0.0" + "has-flag" "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== +"supports-color@^7.1.0": + "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + "version" "7.2.0" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== +"to-regex-range@^5.0.1": + "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" + "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + "version" "5.0.1" dependencies: - is-number "^7.0.0" + "is-number" "^7.0.0" -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +"type-detect@4.0.8": + "integrity" "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "resolved" "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + "version" "4.0.8" -yaml@*, yaml@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0.tgz#cbc588ad58e0cd924cd3f5f2b1a9485103048e25" - integrity sha512-JbfdlHKGP2Ik9IHylzWlGd4pPK++EU46/IxMykphS2ZKw7a7h+dHNmcXObLgpRDriBY+rpWslldikckX8oruWQ== +"yaml@*", "yaml@^2.0.0": + "integrity" "sha512-JbfdlHKGP2Ik9IHylzWlGd4pPK++EU46/IxMykphS2ZKw7a7h+dHNmcXObLgpRDriBY+rpWslldikckX8oruWQ==" + "resolved" "https://registry.npmjs.org/yaml/-/yaml-2.0.0.tgz" + "version" "2.0.0" diff --git a/server/api_server.ts b/server/api_server.ts index 217d59b4..e74fe375 100644 --- a/server/api_server.ts +++ b/server/api_server.ts @@ -17,10 +17,12 @@ import { NodeCronHook } from "../plugos/hooks/node_cron"; import { markdownSyscalls } from "../common/syscalls/markdown"; import { EventedSpacePrimitives } from "../common/spaces/evented_space_primitives"; 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 { jwtSyscalls } from "../plugos/syscalls/jwt"; import { fetchSyscalls } from "../plugos/syscalls/fetch.node"; +import buildMarkdown from "../webapp/parser"; +import { loadMarkdownExtensions } from "../webapp/markdown_ext"; export class ExpressServer { app: Express; @@ -66,23 +68,29 @@ export class ExpressServer { system.registerSyscalls([], pageIndexSyscalls(this.db)); system.registerSyscalls([], spaceSyscalls(this.space)); system.registerSyscalls([], eventSyscalls(this.eventHook)); - system.registerSyscalls([], markdownSyscalls()); + system.registerSyscalls([], markdownSyscalls(buildMarkdown([]))); system.registerSyscalls([], fetchSyscalls()); system.registerSyscalls([], jwtSyscalls()); system.addHook(new EndpointHook(app, "/_/")); + let throttledRebuildMdExtensions = throttle(() => { + this.rebuildMdExtensions(); + }, 100); + this.space.on({ plugLoaded: (plugName, plug) => { safeRun(async () => { console.log("Plug load", plugName); await system.load(plugName, plug, createSandbox); }); + throttledRebuildMdExtensions(); }, plugUnloaded: (plugName) => { safeRun(async () => { console.log("Plug unload", plugName); await system.unload(plugName); }); + throttledRebuildMdExtensions(); }, }); @@ -92,6 +100,13 @@ export class ExpressServer { this.space.updatePageListAsync(); } + rebuildMdExtensions() { + this.system.registerSyscalls( + [], + markdownSyscalls(buildMarkdown(loadMarkdownExtensions(this.system))) + ); + } + async init() { console.log("Setting up router"); diff --git a/webapp/editor.tsx b/webapp/editor.tsx index a745da42..05923250 100644 --- a/webapp/editor.tsx +++ b/webapp/editor.tsx @@ -27,6 +27,7 @@ import { lineWrapper } from "./line_wrapper"; import { markdown } from "./markdown"; import { PathPageNavigator } from "./navigator"; import customMarkDown from "./parser"; +import buildMarkdown from "./parser"; import reducer from "./reducer"; import { smartQuoteKeymap } from "./smart_quotes"; import { Space } from "../common/spaces/space"; @@ -48,6 +49,7 @@ import { pasteLinkExtension } from "./editor_paste"; import { markdownSyscalls } from "../common/syscalls/markdown"; import { clientStoreSyscalls } from "./syscalls/clientStore"; import { StatusBar } from "./components/status_bar"; +import { loadMarkdownExtensions, MDExt } from "./markdown_ext"; class PageState { scrollTop: number; @@ -77,6 +79,7 @@ export class Editor implements AppEventDispatcher { this.eventHook.dispatchEvent("editor:updated"); }, 1000); private system = new System("client"); + private mdExtensions: MDExt[] = []; constructor(space: Space, parent: Element) { this.space = space; @@ -118,7 +121,10 @@ export class Editor implements AppEventDispatcher { this.system.registerSyscalls([], spaceSyscalls(this)); this.system.registerSyscalls([], indexerSyscalls(this.space)); this.system.registerSyscalls([], systemSyscalls(this.space)); - this.system.registerSyscalls([], markdownSyscalls()); + this.system.registerSyscalls( + [], + markdownSyscalls(buildMarkdown(this.mdExtensions)) + ); this.system.registerSyscalls([], clientStoreSyscalls()); } @@ -270,7 +276,7 @@ export class Editor implements AppEventDispatcher { history(), drawSelection(), dropCursor(), - customMarkdownStyle, + customMarkdownStyle(this.mdExtensions), bracketMatching(), closeBrackets(), autocompletion({ @@ -387,7 +393,7 @@ export class Editor implements AppEventDispatcher { ), pasteLinkExtension, markdown({ - base: customMarkDown, + base: customMarkDown(this.mdExtensions), }), ], }); @@ -396,6 +402,14 @@ export class Editor implements AppEventDispatcher { rebuildEditorState() { const editorView = this.editorView; 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( this.createEditorState(this.currentPage, editorView.state.sliceDoc()) ); diff --git a/webapp/editor_paste.ts b/webapp/editor_paste.ts index 422cc0e3..fbab3004 100644 --- a/webapp/editor_paste.ts +++ b/webapp/editor_paste.ts @@ -1,5 +1,7 @@ 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( class { diff --git a/webapp/markdown_ext.ts b/webapp/markdown_ext.ts new file mode 100644 index 00000000..612e0b47 --- /dev/null +++ b/webapp/markdown_ext.ts @@ -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): 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; +} diff --git a/webapp/parser.ts b/webapp/parser.ts index cdb31b62..47e3e02a 100644 --- a/webapp/parser.ts +++ b/webapp/parser.ts @@ -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 { commonmark, getCodeParser, mkLang } from "./markdown/markdown"; 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 { yaml } from "@codemirror/legacy-modes/mode/yaml"; import { javascriptLanguage } from "@codemirror/lang-javascript"; +import { MDExt, mdExtensionStyleTags, mdExtensionSyntaxConfig } from "./markdown_ext"; 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 { nextLine() { return false; @@ -111,60 +67,40 @@ export const Comment: MarkdownConfig = { ], }; -const TagLink: MarkdownConfig = { - defineNodes: ["TagLink"], - parseInline: [ - { - name: "TagLink", - parse(cx, next, pos) { - let match: RegExpMatchArray | null; - if ( - next != 35 /* '#' */ || - !(match = /^[A-Za-z\.]+/.exec(cx.slice(pos + 1, cx.end))) - ) { - return -1; - } - return cx.addElement(cx.elt("TagLink", pos, pos + 1 + match[0].length)); +export default function buildMarkdown(mdExtensions: MDExt[]): Language { + return mkLang( + commonmark.configure([ + WikiLink, + TaskList, + Comment, + ...mdExtensions.map(mdExtensionSyntaxConfig), + 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, + 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); + ]) + ); +} diff --git a/webapp/service_worker.ts b/webapp/service_worker.ts index 1b56baf2..b5387dab 100644 --- a/webapp/service_worker.ts +++ b/webapp/service_worker.ts @@ -19,7 +19,6 @@ async function activate() { self.addEventListener("activate", (e) => e.waitUntil(activate())); self.addEventListener("fetch", (event: any) => { - return; event.respondWith( caches.open(version).then(async (cache) => { let parsedUrl = new URL(event.request.url); diff --git a/webapp/style.ts b/webapp/style.ts index f1a86ce7..56f003c0 100644 --- a/webapp/style.ts +++ b/webapp/style.ts @@ -1,38 +1,44 @@ import { HighlightStyle, tags as t } from "@codemirror/highlight"; import * as ct from "./customtags"; +import { MDExt } from "./markdown_ext"; -export default HighlightStyle.define([ - { tag: t.heading1, class: "h1" }, - { tag: t.heading2, class: "h2" }, - { tag: t.heading3, class: "h3" }, - { tag: t.link, class: "link" }, - { tag: t.meta, class: "meta" }, - { tag: t.quote, class: "quote" }, - { tag: t.monospace, class: "code" }, - { tag: t.url, class: "url" }, - { tag: ct.WikiLinkTag, class: "wiki-link" }, - { tag: ct.WikiLinkPageTag, class: "wiki-link-page" }, - { tag: ct.TagTag, class: "tag" }, - { tag: ct.MentionTag, class: "mention" }, - { tag: ct.TaskTag, class: "task" }, - { tag: ct.TaskMarkerTag, class: "task-marker" }, - { tag: ct.CommentTag, class: "comment" }, - { tag: ct.CommentMarkerTag, class: "comment-marker" }, - { tag: t.emphasis, class: "emphasis" }, - { tag: t.strong, class: "strong" }, - { tag: t.atom, class: "atom" }, - { tag: t.bool, class: "bool" }, - { tag: t.url, class: "url" }, - { tag: t.inserted, class: "inserted" }, - { tag: t.deleted, class: "deleted" }, - { tag: t.literal, class: "literal" }, - { tag: t.list, class: "list" }, - { tag: t.definition, class: "li" }, - { tag: t.string, class: "string" }, - { tag: t.number, class: "number" }, - { tag: [t.regexp, t.escape, t.special(t.string)], class: "string2" }, - { tag: t.variableName, class: "variableName" }, - { tag: t.comment, class: "comment" }, - { tag: t.invalid, class: "invalid" }, - { tag: t.punctuation, class: "punctuation" }, -]); +export default function highlightStyles(mdExtension: MDExt[]) { + return HighlightStyle.define([ + { tag: t.heading1, class: "h1" }, + { tag: t.heading2, class: "h2" }, + { tag: t.heading3, class: "h3" }, + { tag: t.link, class: "link" }, + { tag: t.meta, class: "meta" }, + { tag: t.quote, class: "quote" }, + { tag: t.monospace, class: "code" }, + { tag: t.url, class: "url" }, + { tag: ct.WikiLinkTag, class: "wiki-link" }, + { tag: ct.WikiLinkPageTag, class: "wiki-link-page" }, + { tag: ct.TagTag, class: "tag" }, + { tag: ct.MentionTag, class: "mention" }, + { tag: ct.TaskTag, class: "task" }, + { tag: ct.TaskMarkerTag, class: "task-marker" }, + { tag: ct.CommentTag, class: "comment" }, + { tag: ct.CommentMarkerTag, class: "comment-marker" }, + { tag: t.emphasis, class: "emphasis" }, + { tag: t.strong, class: "strong" }, + { tag: t.atom, class: "atom" }, + { tag: t.bool, class: "bool" }, + { tag: t.url, class: "url" }, + { tag: t.inserted, class: "inserted" }, + { tag: t.deleted, class: "deleted" }, + { tag: t.literal, class: "literal" }, + { tag: t.list, class: "list" }, + { tag: t.definition, class: "li" }, + { tag: t.string, class: "string" }, + { tag: t.number, class: "number" }, + { tag: [t.regexp, t.escape, t.special(t.string)], class: "string2" }, + { tag: t.variableName, class: "variableName" }, + { tag: t.comment, class: "comment" }, + { tag: t.invalid, class: "invalid" }, + { tag: t.punctuation, class: "punctuation" }, + ...mdExtension.map((mdExt) => { + return { tag: mdExt.tag, ...mdExt.styles }; + }), + ]); +}