diff --git a/packages/bbui/src/Typography/Detail.svelte b/packages/bbui/src/Typography/Detail.svelte
index 80e5e1cbe9..dfec234e10 100644
--- a/packages/bbui/src/Typography/Detail.svelte
+++ b/packages/bbui/src/Typography/Detail.svelte
@@ -1,9 +1,9 @@
-
{
- if (isMustacheStatement(node) && isPathExpression(node.path)) {
+ if (
+ (isMustacheStatement(node) || isBlockStatement(node)) &&
+ isPathExpression(node.path)
+ ) {
const helperName = node.path.original
const from =
@@ -75,21 +78,64 @@ export function validateHbsTemplate(
message: `Helper "${helperName}" requires a body:\n{{#${helperName} ...}} [body] {{/${helperName}}}`,
})
return
+ } else if (!requiresBlock && isBlockStatement(node)) {
+ diagnostics.push({
+ from,
+ to,
+ severity: "error",
+ message: `Helper "${helperName}" should not contain a body.`,
+ })
+ return
}
- const providedParams = node.params
+ let providedParamsCount = node.params.length
+ if (isBlockStatement(node)) {
+ // Block body counts as a parameter
+ providedParamsCount++
+ }
- if (providedParams.length !== expectedArguments.length) {
+ const optionalArgMatcher = new RegExp(/^\[(.+)\]$/)
+ const optionalArgs = expectedArguments.filter(a =>
+ optionalArgMatcher.test(a)
+ )
+
+ if (
+ !optionalArgs.length &&
+ providedParamsCount !== expectedArguments.length
+ ) {
diagnostics.push({
from,
to,
severity: "error",
message: `Helper "${helperName}" expects ${
expectedArguments.length
- } parameters (${expectedArguments.join(", ")}), but got ${
- providedParams.length
- }.`,
+ } parameters (${expectedArguments.join(
+ ", "
+ )}), but got ${providedParamsCount}.`,
})
+ } else if (optionalArgs.length) {
+ const maxArgs = expectedArguments.length
+ const minArgs = maxArgs - optionalArgs.length
+ if (
+ minArgs > providedParamsCount ||
+ maxArgs < providedParamsCount
+ ) {
+ const parameters = expectedArguments
+ .map(a => {
+ const test = optionalArgMatcher.exec(a)
+ if (!test?.[1]) {
+ return a
+ }
+ return `${test[1]} (optional)`
+ })
+ .join(", ")
+ diagnostics.push({
+ from,
+ to,
+ severity: "error",
+ message: `Helper "${helperName}" expects between ${minArgs} to ${expectedArguments.length} parameters (${parameters}), but got ${providedParamsCount}.`,
+ })
+ }
}
}
diff --git a/packages/builder/src/components/common/CodeEditor/validator/tests/hbs.spec.ts b/packages/builder/src/components/common/CodeEditor/validator/tests/hbs.spec.ts
index 9484c7a4a5..5d2cfa06c2 100644
--- a/packages/builder/src/components/common/CodeEditor/validator/tests/hbs.spec.ts
+++ b/packages/builder/src/components/common/CodeEditor/validator/tests/hbs.spec.ts
@@ -2,7 +2,7 @@ import { validateHbsTemplate } from "../hbs"
import { CodeValidator } from "@/types"
describe("hbs validator", () => {
- it("validate empty strings", () => {
+ it("validates empty strings", () => {
const text = ""
const validators = {}
@@ -10,7 +10,7 @@ describe("hbs validator", () => {
expect(result).toHaveLength(0)
})
- it("validate strings without hbs expressions", () => {
+ it("validates strings without hbs expressions", () => {
const text = "first line\nand another one"
const validators = {}
@@ -23,7 +23,7 @@ describe("hbs validator", () => {
fieldName: {},
}
- it("validate valid expressions", () => {
+ it("validates valid expressions", () => {
const text = "{{ fieldName }}"
const result = validateHbsTemplate(text, validators)
@@ -98,45 +98,193 @@ describe("hbs validator", () => {
})
describe("expressions with parameters", () => {
- const validators: CodeValidator = {
- helperFunction: {
- arguments: ["a", "b", "c"],
- },
- }
+ describe("basic expression", () => {
+ const validators: CodeValidator = {
+ helperFunction: {
+ arguments: ["a", "b", "c"],
+ },
+ }
- it("validate valid params", () => {
- const text = "{{ helperFunction 1 99 'a' }}"
+ it("validates valid params", () => {
+ const text = "{{ helperFunction 1 99 'a' }}"
- const result = validateHbsTemplate(text, validators)
- expect(result).toHaveLength(0)
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toHaveLength(0)
+ })
+
+ it("throws on too few params", () => {
+ const text = "{{ helperFunction 100 }}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toEqual([
+ {
+ from: 0,
+ message: `Helper "helperFunction" expects 3 parameters (a, b, c), but got 1.`,
+ severity: "error",
+ to: 24,
+ },
+ ])
+ })
+
+ it("throws on too many params", () => {
+ const text = "{{ helperFunction 1 99 'a' 100 }}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toEqual([
+ {
+ from: 0,
+ message: `Helper "helperFunction" expects 3 parameters (a, b, c), but got 4.`,
+ severity: "error",
+ to: 34,
+ },
+ ])
+ })
})
- it("throws on too few params", () => {
- const text = "{{ helperFunction 100 }}"
-
- const result = validateHbsTemplate(text, validators)
- expect(result).toEqual([
- {
- from: 0,
- message: `Helper "helperFunction" expects 3 parameters (a, b, c), but got 1.`,
- severity: "error",
- to: 24,
+ describe("body expressions", () => {
+ const validators: CodeValidator = {
+ bodyFunction: {
+ arguments: ["a", "b", "c"],
+ requiresBlock: true,
},
- ])
+ nonBodyFunction: {
+ arguments: ["a", "b"],
+ },
+ }
+
+ it("validates valid params", () => {
+ const text = "{{#bodyFunction 1 99 }}body{{/bodyFunction}}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toHaveLength(0)
+ })
+
+ it("validates empty bodies", () => {
+ const text = "{{#bodyFunction 1 99 }}{{/bodyFunction}}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toHaveLength(0)
+ })
+
+ it("validates too little parameters", () => {
+ const text = "{{#bodyFunction 1 }}{{/bodyFunction}}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toEqual([
+ {
+ from: 0,
+ message: `Helper "bodyFunction" expects 3 parameters (a, b, c), but got 2.`,
+ severity: "error",
+ to: 37,
+ },
+ ])
+ })
+
+ it("validates too many parameters", () => {
+ const text = "{{#bodyFunction 1 99 'a' 0 }}{{/bodyFunction}}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toEqual([
+ {
+ from: 0,
+ message: `Helper "bodyFunction" expects 3 parameters (a, b, c), but got 5.`,
+ severity: "error",
+ to: 46,
+ },
+ ])
+ })
+
+ it("validates non-supported body usages", () => {
+ const text = "{{#nonBodyFunction 1 99}}{{/nonBodyFunction}}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toEqual([
+ {
+ from: 0,
+ message: `Helper "nonBodyFunction" should not contain a body.`,
+ severity: "error",
+ to: 45,
+ },
+ ])
+ })
})
- it("throws on too many params", () => {
- const text = "{{ helperFunction 1 99 'a' 100 }}"
+ describe("optional parameters", () => {
+ it("supports empty parameters", () => {
+ const validators: CodeValidator = {
+ helperFunction: {
+ arguments: ["a", "b", "[c]"],
+ },
+ }
+ const text = "{{ helperFunction 1 99 }}"
- const result = validateHbsTemplate(text, validators)
- expect(result).toEqual([
- {
- from: 0,
- message: `Helper "helperFunction" expects 3 parameters (a, b, c), but got 4.`,
- severity: "error",
- to: 34,
- },
- ])
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toHaveLength(0)
+ })
+
+ it("supports valid parameters", () => {
+ const validators: CodeValidator = {
+ helperFunction: {
+ arguments: ["a", "b", "[c]"],
+ },
+ }
+ const text = "{{ helperFunction 1 99 'a' }}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toHaveLength(0)
+ })
+
+ it("returns a valid message on missing parameters", () => {
+ const validators: CodeValidator = {
+ helperFunction: {
+ arguments: ["a", "b", "[c]"],
+ },
+ }
+ const text = "{{ helperFunction 1 }}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toEqual([
+ {
+ from: 0,
+ message: `Helper "helperFunction" expects between 2 to 3 parameters (a, b, c (optional)), but got 1.`,
+ severity: "error",
+ to: 22,
+ },
+ ])
+ })
+
+ it("returns a valid message on too many parameters", () => {
+ const validators: CodeValidator = {
+ helperFunction: {
+ arguments: ["a", "b", "[c]"],
+ },
+ }
+ const text = "{{ helperFunction 1 2 3 4 }}"
+
+ const result = validateHbsTemplate(text, validators)
+ expect(result).toEqual([
+ {
+ from: 0,
+ message: `Helper "helperFunction" expects between 2 to 3 parameters (a, b, c (optional)), but got 4.`,
+ severity: "error",
+ to: 28,
+ },
+ ])
+ })
})
})
+
+ it("validates wrong hbs code", () => {
+ const text = "{{#fieldName}}{{/wrong}}"
+
+ const result = validateHbsTemplate(text, {})
+ expect(result).toEqual([
+ {
+ from: 0,
+ message: `The handlebars code is not valid:\nfieldName doesn't match wrong - 1:3`,
+ severity: "error",
+ to: text.length,
+ },
+ ])
+ })
})
diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte
index 3715719565..a760599fb1 100644
--- a/packages/builder/src/components/common/bindings/BindingPanel.svelte
+++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte
@@ -422,7 +422,7 @@
{context}
addHelper={onSelectHelper}
addBinding={onSelectBinding}
- mode={editorMode}
+ {mode}
/>
{:else if sidePanel === SidePanel.Evaluation}
+
-
-
- {#if hoverTarget.description}
-
+{#if popoverAnchor && hoverTarget}
+
+
+ {#if hoverTarget.description}
+
+
+ {@html hoverTarget.description}
+
+ {/if}
+ {#if hoverTarget.code}
- {@html hoverTarget.description}
-
- {/if}
- {#if hoverTarget.code}
-
- {@html hoverTarget.code}
- {/if}
-
-
+
{@html hoverTarget.code}
+ {/if}
+
+
+{/if}
@@ -173,7 +187,7 @@