Moving everything over to use the string template library, now just need to escape spaces properly and handle HTML escaping.
This commit is contained in:
parent
5a7c0de397
commit
d7a3e6210d
|
@ -76,7 +76,6 @@
|
|||
"deepmerge": "^4.2.2",
|
||||
"fast-sort": "^2.2.0",
|
||||
"lodash": "^4.17.13",
|
||||
"mustache": "^4.0.1",
|
||||
"posthog-js": "1.4.5",
|
||||
"remixicon": "^2.5.0",
|
||||
"shortid": "^2.2.15",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
export const CAPTURE_VAR_INSIDE_MUSTACHE = /{{([^}]+)}}/g
|
||||
export const CAPTURE_VAR_INSIDE_TEMPLATE = /{{([^}]+)}}/g
|
||||
|
||||
export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
|
||||
// Find all instances of mustasche
|
||||
const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_MUSTACHE)
|
||||
// Find all instances of template strings
|
||||
const boundValues = textWithBindings.match(CAPTURE_VAR_INSIDE_TEMPLATE)
|
||||
|
||||
let result = textWithBindings
|
||||
// Replace readableBindings with runtimeBindings
|
||||
|
@ -22,7 +22,7 @@ export function runtimeToReadableBinding(bindableProperties, textWithBindings) {
|
|||
let temp = textWithBindings
|
||||
const boundValues =
|
||||
(typeof textWithBindings === "string" &&
|
||||
textWithBindings.match(CAPTURE_VAR_INSIDE_MUSTACHE)) ||
|
||||
textWithBindings.match(CAPTURE_VAR_INSIDE_TEMPLATE)) ||
|
||||
[]
|
||||
|
||||
// Replace runtimeBindings with readableBindings:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export function uuid() {
|
||||
// always want to make this start with a letter, as this makes it
|
||||
// easier to use with mustache bindings in the client
|
||||
// easier to use with template string bindings in the client
|
||||
return "cxxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, c => {
|
||||
const r = (Math.random() * 16) | 0,
|
||||
v = c == "x" ? r : (r & 0x3) | 0x8
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import mustache from "mustache"
|
||||
import { processString } from "@budibase/string-templates"
|
||||
import { get } from "lodash/fp"
|
||||
import { backendUiStore } from "builderStore"
|
||||
|
||||
|
@ -54,8 +54,8 @@
|
|||
}
|
||||
})
|
||||
|
||||
// Fill in bindings with handlebars
|
||||
return mustache.render(formattedTagline, { inputs })
|
||||
// Fill in bindings with templating library
|
||||
return processString(formattedTagline, { inputs })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -5324,11 +5324,6 @@ ms@2.1.2, ms@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
mustache@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.1.tgz#d99beb031701ad433338e7ea65e0489416c854a2"
|
||||
integrity sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA==
|
||||
|
||||
nan@^2.12.1:
|
||||
version "2.14.2"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
"dependencies": {
|
||||
"@budibase/string-templates": "^0.5.3",
|
||||
"deep-equal": "^2.0.1",
|
||||
"mustache": "^4.0.1",
|
||||
"regexparam": "^1.3.0",
|
||||
"svelte-spa-router": "^3.0.5"
|
||||
},
|
||||
|
|
|
@ -1,23 +1,7 @@
|
|||
import mustache from "mustache"
|
||||
import { processString } from "@budibase/string-templates"
|
||||
|
||||
// this is a much more liberal version of mustache's escape function
|
||||
// ...just ignoring < and > to prevent tags from user input
|
||||
// original version here https://github.com/janl/mustache.js/blob/4b7908f5c9fec469a11cfaed2f2bed23c84e1c5c/mustache.js#L78
|
||||
const entityMap = {
|
||||
"<": "<",
|
||||
">": ">",
|
||||
}
|
||||
mustache.escape = text => {
|
||||
if (text == null || typeof text !== "string") {
|
||||
return text
|
||||
}
|
||||
return text.replace(/[<>]/g, function fromEntityMap(s) {
|
||||
return entityMap[s] || s
|
||||
})
|
||||
}
|
||||
|
||||
// Regex to test inputs with to see if they are likely candidates for mustache
|
||||
const looksLikeMustache = /{{.*}}/
|
||||
// Regex to test inputs with to see if they are likely candidates for template strings
|
||||
const looksLikeTemplate = /{{.*}}/
|
||||
|
||||
/**
|
||||
* Enriches a given input with a row from the database.
|
||||
|
@ -27,11 +11,11 @@ export const enrichDataBinding = (input, context) => {
|
|||
if (!input || typeof input !== "string") {
|
||||
return input
|
||||
}
|
||||
// Do a fast regex check if this looks like a mustache string
|
||||
if (!looksLikeMustache.test(input)) {
|
||||
// Do a fast regex check if this looks like a template string
|
||||
if (!looksLikeTemplate.test(input)) {
|
||||
return input
|
||||
}
|
||||
return mustache.render(input, context)
|
||||
return processString(input, context)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1362,11 +1362,6 @@ minimatch@^3.0.4:
|
|||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
mustache@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.1.tgz#d99beb031701ad433338e7ea65e0489416c854a2"
|
||||
integrity sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA==
|
||||
|
||||
nwsapi@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
"main": "dist/bundle.js",
|
||||
"module": "dist/bundle.js",
|
||||
"license": "AGPL-3.0",
|
||||
"private": true,
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
|
|
|
@ -1,10 +1,26 @@
|
|||
const Helper = require("./Helper")
|
||||
const { SafeString } = require("handlebars")
|
||||
|
||||
const HTML_SWAPS = {
|
||||
"<": "<",
|
||||
">": ">",
|
||||
}
|
||||
|
||||
const HELPERS = [
|
||||
// external helpers
|
||||
new Helper("object", value => {
|
||||
return new SafeString(JSON.stringify(value))
|
||||
}),
|
||||
// this help is applied to all statements
|
||||
new Helper("all", value => {
|
||||
let text = unescape(value).replace(/&/g, '&');
|
||||
if (text == null || typeof text !== "string") {
|
||||
return text
|
||||
}
|
||||
return text.replace(/[<>]/g, tag => {
|
||||
return HTML_SWAPS[tag] || tag
|
||||
})
|
||||
})
|
||||
]
|
||||
|
||||
module.exports.registerAll = handlebars => {
|
||||
|
|
|
@ -2,6 +2,7 @@ const handlebars = require("handlebars")
|
|||
const { registerAll } = require("./helpers/index")
|
||||
|
||||
const HBS_CLEANING_REGEX = /{{[^}}]*}}/g
|
||||
const FIND_HBS_REGEX = /{{.*}}/
|
||||
|
||||
const hbsInstance = handlebars.create()
|
||||
registerAll(hbsInstance)
|
||||
|
@ -22,6 +23,12 @@ function attemptToCorrectError(string) {
|
|||
* @returns {string} The string that was input with cleaned up handlebars statements as required.
|
||||
*/
|
||||
function cleanHandlebars(string) {
|
||||
// TODO: handle these types of statement
|
||||
// every statement must have the "all" helper added e.g.
|
||||
// {{ person }} => {{ html person }}
|
||||
// escaping strings must be handled as such:
|
||||
// {{ person name }} => {{ [person name] }}
|
||||
// {{ obj.person name }} => {{ obj.[person name] }}
|
||||
let charToReplace = {
|
||||
"[": ".",
|
||||
"]": "",
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
const {
|
||||
processString,
|
||||
} = require("../src/index")
|
||||
|
||||
describe("Handling context properties with spaces in their name", () => {
|
||||
it("should be able to handle a property with a space in its name", () => {
|
||||
const output = processString("hello my name is {{ person name }}", {
|
||||
"person name": "Mike",
|
||||
})
|
||||
expect(output).toBe("hello my name is Mike")
|
||||
})
|
||||
|
||||
it("should be able to handle an object with layers that requires escaping", () => {
|
||||
const output = processString("testcase {{ testing.test case }}", {
|
||||
testing: {
|
||||
"test case": 1
|
||||
}
|
||||
})
|
||||
expect(output).toBe("testcase 1")
|
||||
})
|
||||
})
|
|
@ -0,0 +1,12 @@
|
|||
const {
|
||||
processString,
|
||||
} = require("../src/index")
|
||||
|
||||
describe("test the custom helpers we have applied", () => {
|
||||
it("should be able to use the object helper", () => {
|
||||
const output = processString("object is {{ object obj }}", {
|
||||
obj: { a: 1 },
|
||||
})
|
||||
expect(output).toBe("object is {\"a\":1}")
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue