{title}
{#if subtitle != null}
diff --git a/packages/builder/src/components/design/PropertiesPanel/BindingPanel.svelte b/packages/builder/src/components/design/PropertiesPanel/BindingPanel.svelte
index 1e40e8e001..6ab2504077 100644
--- a/packages/builder/src/components/design/PropertiesPanel/BindingPanel.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/BindingPanel.svelte
@@ -1,12 +1,6 @@
-
+
diff --git a/packages/string-templates/jest.config.js b/packages/string-templates/jest.config.js
index 3c3d264fa5..c6391cdb92 100644
--- a/packages/string-templates/jest.config.js
+++ b/packages/string-templates/jest.config.js
@@ -191,4 +191,4 @@ module.exports = {
// Whether to use watchman for file crawling
// watchman: true,
-};
+}
diff --git a/packages/string-templates/rollup.config.js b/packages/string-templates/rollup.config.js
index fa215261dc..f4cf851f92 100644
--- a/packages/string-templates/rollup.config.js
+++ b/packages/string-templates/rollup.config.js
@@ -11,7 +11,7 @@ export default {
name: "string-templates",
exports: "named",
globals: {
- "fs": "fs",
+ fs: "fs",
},
},
external: ["fs"],
diff --git a/packages/string-templates/src/custom/preprocessor.js b/packages/string-templates/src/custom/preprocessor.js
index f562c67c6a..ffd81f1693 100644
--- a/packages/string-templates/src/custom/preprocessor.js
+++ b/packages/string-templates/src/custom/preprocessor.js
@@ -1,60 +1,81 @@
const { HelperFunctions } = require("../helpers")
-const { swapStrings, isAlphaNumeric, FIND_HBS_REGEX, includesAny } = require("../utilities")
+const {
+ swapStrings,
+ isAlphaNumeric,
+ FIND_HBS_REGEX,
+ includesAny,
+} = require("../utilities")
-function handleProcessor(string, match, fn) {
- const output = fn(match)
- const idx = string.indexOf(match)
- return swapStrings(string, idx, match.length, output)
+class Preprocessor {
+ constructor(name, fn) {
+ this.name = name
+ this.fn = fn
+ }
+
+ process(fullString, statement) {
+ const output = this.fn(statement)
+ const idx = fullString.indexOf(statement)
+ return swapStrings(fullString, idx, statement.length, output)
+ }
}
-function swapToDotNotation(statement) {
- let startBraceIdx = statement.indexOf("[")
- let lastIdx = 0
- while (startBraceIdx !== -1) {
- // if the character previous to the literal specifier is alpha-numeric this should happen
- if (isAlphaNumeric(statement.charAt(startBraceIdx - 1))) {
- statement = swapStrings(statement, startBraceIdx + lastIdx, 1, ".[")
+const PROCESSORS = [
+ new Preprocessor("swap-to-dot-notation", statement => {
+ let startBraceIdx = statement.indexOf("[")
+ let lastIdx = 0
+ while (startBraceIdx !== -1) {
+ // if the character previous to the literal specifier is alpha-numeric this should happen
+ if (isAlphaNumeric(statement.charAt(startBraceIdx - 1))) {
+ statement = swapStrings(statement, startBraceIdx + lastIdx, 1, ".[")
+ }
+ lastIdx = startBraceIdx + 1
+ startBraceIdx = statement.substring(lastIdx + 1).indexOf("[")
}
- lastIdx = startBraceIdx + 1
- startBraceIdx = statement.substring(lastIdx + 1).indexOf("[")
- }
- return statement
-}
+ return statement
+ }),
-function handleSpacesInProperties(statement) {
- // exclude helpers and brackets, regex will only find double brackets
- const exclusions = HelperFunctions.concat(["{{", "}}"])
- // find all the parts split by spaces
- const splitBySpaces = statement.split(" ")
- // remove the excluded elements
- const propertyParts = splitBySpaces.filter(part => exclusions.indexOf(part) === -1)
- // rebuild to get the full property
- const fullProperty = propertyParts.join(" ")
- // now work out the dot notation layers and split them up
- const propertyLayers = fullProperty.split(".")
- // find the layers which need to be wrapped and wrap them
- for (let layer of propertyLayers) {
- if (layer.indexOf(" ") !== -1) {
- statement = swapStrings(statement, statement.indexOf(layer), layer.length, `[${layer}]`)
+ new Preprocessor("handle-spaces-in-properties", statement => {
+ // exclude helpers and brackets, regex will only find double brackets
+ const exclusions = HelperFunctions.concat(["{{", "}}"])
+ // find all the parts split by spaces
+ const splitBySpaces = statement.split(" ")
+ // remove the excluded elements
+ const propertyParts = splitBySpaces.filter(
+ part => exclusions.indexOf(part) === -1
+ )
+ // rebuild to get the full property
+ const fullProperty = propertyParts.join(" ")
+ // now work out the dot notation layers and split them up
+ const propertyLayers = fullProperty.split(".")
+ // find the layers which need to be wrapped and wrap them
+ for (let layer of propertyLayers) {
+ if (layer.indexOf(" ") !== -1) {
+ statement = swapStrings(
+ statement,
+ statement.indexOf(layer),
+ layer.length,
+ `[${layer}]`
+ )
+ }
}
- }
- // remove the edge case of double brackets being entered (in-case user already has specified)
- return statement.replace(/\[\[/g, "[").replace(/]]/g, "]")
-}
+ // remove the edge case of double brackets being entered (in-case user already has specified)
+ return statement.replace(/\[\[/g, "[").replace(/]]/g, "]")
+ }),
-function finalise(statement) {
- let insideStatement = statement.slice(2, statement.length - 2)
- if (insideStatement.charAt(0) === " ") {
- insideStatement = insideStatement.slice(1)
- }
- if (insideStatement.charAt(insideStatement.length - 1) === " ") {
- insideStatement = insideStatement.slice(0, insideStatement.length - 1)
- }
- if (includesAny(insideStatement, HelperFunctions)) {
- insideStatement = `(${insideStatement})`
- }
- return `{{ all ${insideStatement} }}`
-}
+ new Preprocessor("finalise", statement => {
+ let insideStatement = statement.slice(2, statement.length - 2)
+ if (insideStatement.charAt(0) === " ") {
+ insideStatement = insideStatement.slice(1)
+ }
+ if (insideStatement.charAt(insideStatement.length - 1) === " ") {
+ insideStatement = insideStatement.slice(0, insideStatement.length - 1)
+ }
+ if (includesAny(insideStatement, HelperFunctions)) {
+ insideStatement = `(${insideStatement})`
+ }
+ return `{{ all ${insideStatement} }}`
+ })
+]
/**
* When running handlebars statements to execute on the context of the automation it possible user's may input handlebars
@@ -67,18 +88,17 @@ function finalise(statement) {
* @param {string} string The string which *may* contain handlebars statements, it is OK if it does not contain any.
* @returns {string} The string that was input with processed up handlebars statements as required.
*/
-module.exports.preprocess = (string) => {
- let preprocessors = [swapToDotNotation, handleSpacesInProperties, finalise]
- for (let processor of preprocessors) {
- // re-run search each time incase previous cleaner update/removed a match
+module.exports.preprocess = string => {
+ for (let processor of PROCESSORS) {
+ // re-run search each time incase previous processor updated/removed a match
let regex = new RegExp(FIND_HBS_REGEX)
let matches = string.match(regex)
if (matches == null) {
continue
}
for (let match of matches) {
- string = handleProcessor(string, match, processor)
+ string = processor.process(string, match)
}
}
return string
-}
\ No newline at end of file
+}
diff --git a/packages/string-templates/src/helpers/index.js b/packages/string-templates/src/helpers/index.js
index 498ac40dce..768fe297af 100644
--- a/packages/string-templates/src/helpers/index.js
+++ b/packages/string-templates/src/helpers/index.js
@@ -12,7 +12,7 @@ const HelperFunctionBuiltin = [
"#each",
"#with",
"lookup",
- "log"
+ "log",
]
const HelperFunctionNames = {
@@ -27,17 +27,19 @@ const HELPERS = [
}),
// this help is applied to all statements
new Helper(HelperFunctionNames.ALL, value => {
- let text = new SafeString(unescape(value).replace(/&/g, '&'))
+ let text = new SafeString(unescape(value).replace(/&/g, "&"))
if (text == null || typeof text !== "string") {
return text
}
return text.replace(/[<>]/g, tag => {
return HTML_SWAPS[tag] || tag
})
- })
+ }),
]
-module.exports.HelperFunctions = Object.values(HelperFunctionNames).concat(HelperFunctionBuiltin)
+module.exports.HelperFunctions = Object.values(HelperFunctionNames).concat(
+ HelperFunctionBuiltin
+)
module.exports.registerAll = handlebars => {
for (let helper of HELPERS) {
diff --git a/packages/string-templates/src/utilities.js b/packages/string-templates/src/utilities.js
index c7179aac75..bb35e94567 100644
--- a/packages/string-templates/src/utilities.js
+++ b/packages/string-templates/src/utilities.js
@@ -1,8 +1,8 @@
const ALPHA_NUMERIC_REGEX = /^[A-Za-z0-9]+$/g
-module.exports.FIND_HBS_REGEX = /{{[^}}]*}}/g
+module.exports.FIND_HBS_REGEX = /{{([^{}])+}}/g
-module.exports.isAlphaNumeric = (char) => {
+module.exports.isAlphaNumeric = char => {
return char.match(ALPHA_NUMERIC_REGEX)
}
diff --git a/packages/string-templates/test/basic.spec.js b/packages/string-templates/test/basic.spec.js
index 172c94ca21..6babce8f8c 100644
--- a/packages/string-templates/test/basic.spec.js
+++ b/packages/string-templates/test/basic.spec.js
@@ -11,6 +11,13 @@ describe("Test that the string processing works correctly", () => {
expect(output).toBe("templating is easy")
})
+ it("should process a literal template", async () => {
+ const output = await processString("derp is {{{ adjective }}}", {
+ adjective: "derp"
+ })
+ expect(output).toBe("derp is derp")
+ })
+
it("should fail gracefully when wrong type passed in", async () => {
let error = null
try {
diff --git a/packages/string-templates/test/escapes.spec.js b/packages/string-templates/test/escapes.spec.js
index eb94b1ce2e..39df8719d6 100644
--- a/packages/string-templates/test/escapes.spec.js
+++ b/packages/string-templates/test/escapes.spec.js
@@ -32,4 +32,20 @@ describe("Handling context properties with spaces in their name", () => {
})
expect(output).toBe("testcase 1")
})
+})
+
+describe("attempt some complex problems", () => {
+ it("should be able to handle a very complex handlebars statement", async () => {
+ const context = {
+ "New Repeater": {
+ "Get Actors": {
+ "first_name": "Bob",
+ "last_name": "Bobert"
+ },
+ },
+ }
+ const hbs = "{{ New Repeater.Get Actors.first_name }} {{ New Repeater.Get Actors.last_name }}"
+ const output = await processString(hbs, context)
+ expect(output).toBe("Bob Bobert")
+ })
})
\ No newline at end of file
diff --git a/packages/string-templates/test/renderApp.spec.js b/packages/string-templates/test/renderApp.spec.js
new file mode 100644
index 0000000000..1ae08ee113
--- /dev/null
+++ b/packages/string-templates/test/renderApp.spec.js
@@ -0,0 +1,33 @@
+const { processString } = require("../src/index")
+
+describe("specific test case for whether or not full app template can still be rendered", () => {
+ it("should be able to render the app template", async () => {
+ const template =
+ `
+
+
+ {{{head}}}
+
+
+ {{{body}}}
+ `
+ const context = {
+ appId: "App1",
+ head: "App things
" + } + const output = await processString(template, context) + expect(output).toBe(` + + +App things
+ `) + }) +}) \ No newline at end of file