Materialized query parser redo
This commit is contained in:
parent
d649009dd2
commit
b3c3302970
@ -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
84
common/parse_tree.ts
Normal 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;
|
||||||
|
}
|
@ -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);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
});
|
});
|
194
common/tree.ts
194
common/tree.ts
@ -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("");
|
||||||
}
|
}
|
||||||
|
@ -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"],
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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("");
|
|
||||||
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
83
plugs/package-lock.json
generated
83
plugs/package-lock.json
generated
@ -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=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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",
|
||||||
|
70
plugs/query/engine.test.ts
Normal file
70
plugs/query/engine.test.ts
Normal 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
154
plugs/query/engine.ts
Normal 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;
|
||||||
|
}
|
@ -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
44
plugs/query/query.grammar
Normal 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+ }
|
||||||
|
}
|
7
plugs/query/query.plug.yaml
Normal file
7
plugs/query/query.plug.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
functions:
|
||||||
|
updateMaterializedQueriesOnPage:
|
||||||
|
path: ./materialized_queries.ts:updateMaterializedQueriesOnPage
|
||||||
|
updateMaterializedQueriesCommand:
|
||||||
|
path: ./materialized_queries.ts:updateMaterializedQueriesCommand
|
||||||
|
command:
|
||||||
|
name: "Materialized Queries: Update"
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
542
plugs/yarn.lock
542
plugs/yarn.lock
@ -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"
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
@ -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())
|
||||||
);
|
);
|
||||||
|
@ -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
66
webapp/markdown_ext.ts
Normal 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;
|
||||||
|
}
|
142
webapp/parser.ts
142
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 { 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);
|
|
||||||
|
@ -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);
|
||||||
|
@ -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 };
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user