diff --git a/.gitignore b/.gitignore index 0f1dbfd5..3f328349 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ node_modules *.db* test_space silverbullet -deploy.json \ No newline at end of file +deploy.json +*.generated \ No newline at end of file diff --git a/common/json.test.ts b/common/json.test.ts new file mode 100644 index 00000000..183e0f6c --- /dev/null +++ b/common/json.test.ts @@ -0,0 +1,37 @@ +import { assertEquals } from "../test_deps.ts"; +import { traverseAndRewriteJSON } from "./json.ts"; + +Deno.test("traverseAndRewrite should recursively traverse and rewrite object properties", () => { + const bufArray = new Uint8Array([1, 2, 3]); + const obj = { + foo: "bar", + list: ["hello", { sup: "world" }], + nested: { + baz: "qux", + }, + special: { + value: () => { + return bufArray; + }, + }, + }; + + const rewritten = traverseAndRewriteJSON(obj, (val) => { + if (typeof val?.value === "function") { + return val.value(); + } + if (typeof val === "string") { + return val.toUpperCase(); + } + return val; + }); + + assertEquals(rewritten, { + foo: "BAR", + list: ["HELLO", { sup: "WORLD" }], + nested: { + baz: "QUX", + }, + special: bufArray, + }); +}); diff --git a/common/json.ts b/common/json.ts new file mode 100644 index 00000000..05ad691c --- /dev/null +++ b/common/json.ts @@ -0,0 +1,26 @@ +/** + * Traverses and rewrites an object recursively. + * + * @param obj - The object to traverse and rewrite. + * @param rewrite - The function to apply for rewriting each value. + * @returns The rewritten object. + */ +export function traverseAndRewriteJSON( + obj: any, + rewrite: (val: any) => any, +): any { + // Apply rewrite to object as a whole + obj = rewrite(obj); + // Recurse down if this is an array or a "plain object" + if ( + obj && Array.isArray(obj) || + (typeof obj === "object" && obj.constructor === Object) + ) { + const keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + obj[key] = traverseAndRewriteJSON(obj[key], rewrite); + } + } + return obj; +} diff --git a/common/languages.ts b/common/languages.ts index e8af865b..0d45325f 100644 --- a/common/languages.ts +++ b/common/languages.ts @@ -25,7 +25,10 @@ import { xmlLanguage, yamlLanguage, } from "./deps.ts"; -import { highlightingQueryParser } from "./markdown_parser/parser.ts"; +import { + expressionParser, + highlightingQueryParser, +} from "./markdown_parser/parser.ts"; export const builtinLanguages: Record = { "meta": StreamLanguage.define(yamlLanguage), @@ -81,6 +84,10 @@ export const builtinLanguages: Record = { name: "query", parser: highlightingQueryParser, }), + "expression": LRLanguage.define({ + name: "expression", + parser: expressionParser, + }), }; export function languageFor(name: string): Language | null { diff --git a/common/markdown_parser/expression.grammar b/common/markdown_parser/expression.grammar deleted file mode 100644 index 75b7ab9b..00000000 --- a/common/markdown_parser/expression.grammar +++ /dev/null @@ -1,119 +0,0 @@ -@top Program { Expression } - -@precedence { - mulop @left - addop @left - binop @left - and @left - or @left -} - -@skip { - space -} - -commaSep { content ("," content)* } - -kw { @specialize[@name={term}] } - - -Query { - TagIdentifier ( WhereClause | LimitClause | OrderClause | SelectClause | RenderClause )* -} - -WhereClause { kw<"where"> Expression } -LimitClause { kw<"limit"> Expression } -OrderClause { Order commaSep } -OrderBy { Expression OrderDirection? } -SelectClause { kw<"select"> commaSep