diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ExecuteQuery.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ExecuteQuery.svelte
index 8c438e4b22..462ee71cbe 100644
--- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ExecuteQuery.svelte
+++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/actions/ExecuteQuery.svelte
@@ -52,7 +52,7 @@
{/if}
{#if query?.parameters?.length > 0}
-
+
+
+
diff --git a/packages/server/src/api/routes/tests/query.spec.js b/packages/server/src/api/routes/tests/query.spec.js
index 9357d53cde..dac576836e 100644
--- a/packages/server/src/api/routes/tests/query.spec.js
+++ b/packages/server/src/api/routes/tests/query.spec.js
@@ -230,7 +230,6 @@ describe("/queries", () => {
})
describe("variables", () => {
-
async function preview(datasource, fields) {
return config.previewQuery(request, config, datasource, fields)
}
diff --git a/packages/server/src/threads/query.js b/packages/server/src/threads/query.js
index 23b4dc1ef8..5b1a30b57d 100644
--- a/packages/server/src/threads/query.js
+++ b/packages/server/src/threads/query.js
@@ -161,10 +161,16 @@ class QueryRunner {
const responses = await Promise.all(dynamics)
for (let i = 0; i < foundVars.length; i++) {
const variable = foundVars[i]
- parameters[variable.name] = processStringSync(variable.value, {
- data: responses[i].rows,
- info: responses[i].extra,
- })
+ parameters[variable.name] = processStringSync(
+ variable.value,
+ {
+ data: responses[i].rows,
+ info: responses[i].extra,
+ },
+ {
+ escapeNewlines: true,
+ }
+ )
// make sure its known that this uses dynamic variables in case it fails
this.hasDynamicVariables = true
}
@@ -188,6 +194,7 @@ class QueryRunner {
enrichedQuery[key] = processStringSync(fields[key], parameters, {
noEscaping: true,
noHelpers: true,
+ escapeNewlines: true,
})
} else {
enrichedQuery[key] = fields[key]
diff --git a/packages/string-templates/src/helpers/index.js b/packages/string-templates/src/helpers/index.js
index 6b9195047e..ad4082e3a4 100644
--- a/packages/string-templates/src/helpers/index.js
+++ b/packages/string-templates/src/helpers/index.js
@@ -21,7 +21,7 @@ const HELPERS = [
// javascript helper
new Helper(HelperFunctionNames.JS, processJS, false),
// this help is applied to all statements
- new Helper(HelperFunctionNames.ALL, value => {
+ new Helper(HelperFunctionNames.ALL, (value, { __opts }) => {
if (
value != null &&
typeof value === "object" &&
@@ -36,7 +36,11 @@ const HELPERS = [
if (value && value.string) {
value = value.string
}
- let text = new SafeString(value.replace(/&/g, "&"))
+ let text = value
+ if (__opts && __opts.escapeNewlines) {
+ text = value.replace(/\n/g, "\\n")
+ }
+ text = new SafeString(text.replace(/&/g, "&"))
if (text == null || typeof text !== "string") {
return text
}
@@ -62,10 +66,14 @@ module.exports.HelperNames = () => {
)
}
-module.exports.registerAll = handlebars => {
+module.exports.registerMinimum = handlebars => {
for (let helper of HELPERS) {
helper.register(handlebars)
}
+}
+
+module.exports.registerAll = handlebars => {
+ module.exports.registerMinimum(handlebars)
// register imported helpers
externalHandlebars.registerAll(handlebars)
}
diff --git a/packages/string-templates/src/index.js b/packages/string-templates/src/index.js
index 5ffd1bf1cc..093da977ea 100644
--- a/packages/string-templates/src/index.js
+++ b/packages/string-templates/src/index.js
@@ -1,5 +1,5 @@
const handlebars = require("handlebars")
-const { registerAll } = require("./helpers/index")
+const { registerAll, registerMinimum } = require("./helpers/index")
const processors = require("./processors")
const { atob, btoa } = require("./utilities")
const manifest = require("../manifest.json")
@@ -8,6 +8,7 @@ const { FIND_HBS_REGEX, FIND_DOUBLE_HBS_REGEX } = require("./utilities")
const hbsInstance = handlebars.create()
registerAll(hbsInstance)
const hbsInstanceNoHelpers = handlebars.create()
+registerMinimum(hbsInstanceNoHelpers)
const defaultOpts = { noHelpers: false, noEscaping: false }
/**
@@ -105,9 +106,7 @@ module.exports.processStringSync = (string, context, opts) => {
throw "Cannot process non-string types."
}
try {
- // finalising adds a helper, can't do this with no helpers
- const shouldFinalise = !opts.noHelpers
- string = processors.preprocess(string, shouldFinalise)
+ string = processors.preprocess(string, opts)
// this does not throw an error when template can't be fulfilled, have to try correct beforehand
const instance = opts.noHelpers ? hbsInstanceNoHelpers : hbsInstance
const templateString =
@@ -119,8 +118,10 @@ module.exports.processStringSync = (string, context, opts) => {
return processors.postprocess(
template({
now: new Date(now).toISOString(),
+ __opts: opts,
...context,
- })
+ }),
+ { escapeNewlines: opts ? opts.escapeNewlines : false }
)
} catch (err) {
return input
diff --git a/packages/string-templates/src/processors/index.js b/packages/string-templates/src/processors/index.js
index 174041133a..257dca7aec 100644
--- a/packages/string-templates/src/processors/index.js
+++ b/packages/string-templates/src/processors/index.js
@@ -2,7 +2,7 @@ const { FIND_HBS_REGEX } = require("../utilities")
const preprocessor = require("./preprocessor")
const postprocessor = require("./postprocessor")
-function process(output, processors) {
+function process(output, processors, opts) {
for (let processor of processors) {
// if a literal statement has occurred stop
if (typeof output !== "string") {
@@ -15,24 +15,18 @@ function process(output, processors) {
continue
}
for (let match of matches) {
- output = processor.process(output, match)
+ output = processor.process(output, match, opts)
}
}
return output
}
-module.exports.preprocess = (string, finalise = true) => {
+module.exports.preprocess = (string, opts) => {
let processors = preprocessor.processors
- // the pre-processor finalisation stops handlebars from ever throwing an error
- // might want to pre-process for other benefits but still want to see errors
- if (!finalise) {
- processors = processors.filter(
- processor => processor.name !== preprocessor.PreprocessorNames.FINALISE
- )
- }
- return process(string, processors)
+ return process(string, processors, opts)
}
module.exports.postprocess = string => {
- return process(string, postprocessor.processors)
+ let processors = postprocessor.processors
+ return process(string, processors)
}
diff --git a/packages/string-templates/src/processors/postprocessor.js b/packages/string-templates/src/processors/postprocessor.js
index 7fc3f663fe..f78a572d07 100644
--- a/packages/string-templates/src/processors/postprocessor.js
+++ b/packages/string-templates/src/processors/postprocessor.js
@@ -16,6 +16,8 @@ class Postprocessor {
}
}
+module.exports.PostProcessorNames = PostProcessorNames
+
module.exports.processors = [
new Postprocessor(PostProcessorNames.CONVERT_LITERALS, statement => {
if (typeof statement !== "string" || !statement.includes(LITERAL_MARKER)) {
diff --git a/packages/string-templates/src/processors/preprocessor.js b/packages/string-templates/src/processors/preprocessor.js
index 6f6537674a..4b296d0fc7 100644
--- a/packages/string-templates/src/processors/preprocessor.js
+++ b/packages/string-templates/src/processors/preprocessor.js
@@ -16,8 +16,8 @@ class Preprocessor {
this.fn = fn
}
- process(fullString, statement) {
- const output = this.fn(statement)
+ process(fullString, statement, opts) {
+ const output = this.fn(statement, opts)
const idx = fullString.indexOf(statement)
return swapStrings(fullString, idx, statement.length, output)
}
@@ -48,7 +48,8 @@ module.exports.processors = [
return statement
}),
- new Preprocessor(PreprocessorNames.FINALISE, statement => {
+ new Preprocessor(PreprocessorNames.FINALISE, (statement, opts) => {
+ const noHelpers = opts && opts.noHelpers
let insideStatement = statement.slice(2, statement.length - 2)
if (insideStatement.charAt(0) === " ") {
insideStatement = insideStatement.slice(1)
@@ -63,7 +64,10 @@ module.exports.processors = [
return statement
}
}
- if (HelperNames().some(option => option.includes(possibleHelper))) {
+ if (
+ !noHelpers &&
+ HelperNames().some(option => option.includes(possibleHelper))
+ ) {
insideStatement = `(${insideStatement})`
}
return `{{ all ${insideStatement} }}`
diff --git a/packages/string-templates/test/escapes.spec.js b/packages/string-templates/test/escapes.spec.js
index 7e55b66b88..b845fddec9 100644
--- a/packages/string-templates/test/escapes.spec.js
+++ b/packages/string-templates/test/escapes.spec.js
@@ -59,3 +59,33 @@ describe("attempt some complex problems", () => {
expect(output).toBe("nulltest")
})
})
+
+describe("check behaviour with newlines", () => {
+ const context = {
+ binding: `Hello
+ there`
+ }
+ it("should escape new line to \\n with double brace", async () => {
+ const hbs = JSON.stringify({
+ body: "{{ binding }}"
+ })
+ const output = await processString(hbs, context, { escapeNewlines: true })
+ expect(JSON.parse(output).body).toBe(context.binding)
+ })
+
+ it("should work the same with triple brace", async () => {
+ const hbs = JSON.stringify({
+ body: "{{{ binding }}}"
+ })
+ const output = await processString(hbs, context, { escapeNewlines: true })
+ expect(JSON.parse(output).body).toBe(context.binding)
+ })
+
+ it("should still work with helpers disabled", async () => {
+ const hbs = JSON.stringify({
+ body: "{{ binding }}"
+ })
+ const output = await processString(hbs, context, { escapeNewlines: true, noHelpers: true })
+ expect(JSON.parse(output).body).toBe(context.binding)
+ })
+})