From 8f4d6e5d23f8b33e230826f9f65c1c430e86a268 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Mon, 30 Oct 2023 14:15:12 +0100 Subject: [PATCH] Fixes #542: render each and render all --- common/markdown_parser/expression.grammar | 2 +- common/markdown_parser/parse-query.js | 16 +++++++------- common/markdown_parser/parse-query.terms.js | 2 +- common/markdown_parser/parser.ts | 3 ++- common/markdown_parser/query.grammar | 2 +- plug-api/lib/parse-query.ts | 5 ++++- plug-api/lib/parser-query.test.ts | 23 +++++++++++++++++++++ plug-api/types.ts | 1 + plugs/directive/util.ts | 6 +++++- plugs/query/query.ts | 2 ++ website/CHANGELOG.md | 7 +++++++ website/Live Queries.md | 17 ++++++++++++--- website/template/people.md | 5 +++++ 13 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 website/template/people.md diff --git a/common/markdown_parser/expression.grammar b/common/markdown_parser/expression.grammar index 049d38e..75b7ab9 100644 --- a/common/markdown_parser/expression.grammar +++ b/common/markdown_parser/expression.grammar @@ -26,7 +26,7 @@ LimitClause { kw<"limit"> Expression } OrderClause { Order commaSep } OrderBy { Expression OrderDirection? } SelectClause { kw<"select"> commaSep } -RenderClause { kw<"render"> PageRef } +RenderClause { kw<"render"> ( kw<"each"> | kw<"all"> )? PageRef } Select { Identifier | Expression kw<"as"> Identifier } diff --git a/plug-api/lib/parse-query.ts b/plug-api/lib/parse-query.ts index 080b171..76d70ee 100644 --- a/plug-api/lib/parse-query.ts +++ b/plug-api/lib/parse-query.ts @@ -74,7 +74,10 @@ export function astToKvQuery( break; } case "RenderClause": { - query.render = (clause[2][1] as string).slice(2, -2); + // console.log("Render clause", clause); + const pageRef = (clause as any[]).find((c) => c[0] === "PageRef"); + query.render = pageRef[1].slice(2, -2); + query.renderAll = !!(clause as any[]).find((c) => c[0] === "all"); break; } default: diff --git a/plug-api/lib/parser-query.test.ts b/plug-api/lib/parser-query.test.ts index 3c609e7..d8185d9 100644 --- a/plug-api/lib/parser-query.test.ts +++ b/plug-api/lib/parser-query.test.ts @@ -149,6 +149,29 @@ Deno.test("Test directive parser", () => { { querySource: "task", render: "my/page", + renderAll: false, + }, + ); + + assertEquals( + astToKvQuery( + wrapQueryParse(`task render each [[my/page]]`)!, + ), + { + querySource: "task", + render: "my/page", + renderAll: false, + }, + ); + + assertEquals( + astToKvQuery( + wrapQueryParse(`task render all [[my/page]]`)!, + ), + { + querySource: "task", + render: "my/page", + renderAll: true, }, ); diff --git a/plug-api/types.ts b/plug-api/types.ts index 36ab0d7..5822d3a 100644 --- a/plug-api/types.ts +++ b/plug-api/types.ts @@ -66,6 +66,7 @@ export type Query = { select?: Select[]; limit?: QueryExpression; render?: string; + renderAll?: boolean; distinct?: boolean; }; diff --git a/plugs/directive/util.ts b/plugs/directive/util.ts index b854025..9256a70 100644 --- a/plugs/directive/util.ts +++ b/plugs/directive/util.ts @@ -1,6 +1,7 @@ import { handlebars, space } from "$sb/syscalls.ts"; import { handlebarHelpers } from "../../common/syscalls/handlebar_helpers.ts"; import { PageMeta } from "$sb/types.ts"; +import { render } from "preact"; export function defaultJsonTransformer(_k: string, v: any) { if (v === undefined) { @@ -57,9 +58,12 @@ export async function renderTemplate( pageMeta: PageMeta, renderTemplate: string, data: any[], + renderAll: boolean, ): Promise { let templateText = await space.readPage(renderTemplate); - templateText = `{{#each .}}\n${templateText}\n{{/each}}`; + if (!renderAll) { + templateText = `{{#each .}}\n${templateText}\n{{/each}}`; + } return handlebars.renderTemplate(templateText, data, { page: pageMeta }); } diff --git a/plugs/query/query.ts b/plugs/query/query.ts index 1a1935e..1691660 100644 --- a/plugs/query/query.ts +++ b/plugs/query/query.ts @@ -4,6 +4,7 @@ import { parseTreeToAST } from "$sb/lib/tree.ts"; import { astToKvQuery } from "$sb/lib/parse-query.ts"; import { jsonToMDTable, renderTemplate } from "../directive/util.ts"; import { replaceTemplateVars } from "../template/template.ts"; +import { parse } from "../../common/markdown_parser/parse_tree.ts"; export async function widget(bodyText: string): Promise { const pageMeta = await space.getPageMeta(await editor.getCurrentPage()); @@ -45,6 +46,7 @@ export async function widget(bodyText: string): Promise { pageMeta, parsedQuery.render, allResults, + parsedQuery.renderAll!, ); resultMarkdown = rendered.trim(); } else { diff --git a/website/CHANGELOG.md b/website/CHANGELOG.md index 6fffbb2..560d1d2 100644 --- a/website/CHANGELOG.md +++ b/website/CHANGELOG.md @@ -1,6 +1,13 @@ An attempt at documenting the changes/new features introduced in each release. +--- +## 0.5.4 +* Many styling fixes and improvements to [[Live Queries]] and [[Live Templates]] +* Added a “source” button to [[Live Queries]] and [[Live Templates]] for better debugging (showing you the markdown code rendered by the template so you can more easily detect issues) +* [[Live Queries]]: + * Support for `render all` where the entire result set is passed to a single template allowing you to e.g. dynamically build up tables, see [[Live Queries@render]] for an example. + --- ## 0.5.3 * Changes to [[Objects]]: diff --git a/website/Live Queries.md b/website/Live Queries.md index 86552d4..4f60fd2 100644 --- a/website/Live Queries.md +++ b/website/Live Queries.md @@ -55,14 +55,25 @@ person where page = "{{@page.name}}" select name, age, age + 1 as nextYear ``` -### `render [[template]]` -By default results are rendered as a table, to instead render each result item using [[Templates|a template]], use the `render` clause: +### `render each [[template]]` and `render all [[template]]` +$render +By default results are rendered as a table, to instead render results using [[Templates|a template]], use the `render` clause, which comes in two shapes `render each` where the template is instantiated for _each_ result (the `each` keyword is optional): ```query person where page = "{{@page.name}}" -render [[template/person]] +render each [[template/person]] ``` + +And `render all` where the entire result set is passed to the template as a list so the template can do its own iteration using `#each`, which you could then use to e.g. build a table (using this [[template/people]] template for instance): + +```query +person +where page = "{{@page.name}}" +render all [[template/people]] +``` + + ## Expressions $expression diff --git a/website/template/people.md b/website/template/people.md new file mode 100644 index 0000000..046643c --- /dev/null +++ b/website/template/people.md @@ -0,0 +1,5 @@ +| Name | Age | +|----------|----------| +{{#each .}} +| **{{name}}** | {{age}} | +{{/each}}