2021-01-21 11:42:14 +01:00
|
|
|
import { cloneDeep } from "lodash/fp"
|
2020-12-02 14:49:24 +01:00
|
|
|
import mustache from "mustache"
|
|
|
|
|
|
|
|
// 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
|
|
|
|
})
|
|
|
|
}
|
2020-11-19 10:24:58 +01:00
|
|
|
|
|
|
|
// Regex to test inputs with to see if they are likely candidates for mustache
|
|
|
|
const looksLikeMustache = /{{.*}}/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enriches a given input with a row from the database.
|
|
|
|
*/
|
2020-11-20 10:50:10 +01:00
|
|
|
export const enrichDataBinding = (input, context) => {
|
2020-11-19 10:24:58 +01:00
|
|
|
// Only accept string inputs
|
|
|
|
if (!input || typeof input !== "string") {
|
|
|
|
return input
|
|
|
|
}
|
|
|
|
// Do a fast regex check if this looks like a mustache string
|
|
|
|
if (!looksLikeMustache.test(input)) {
|
|
|
|
return input
|
|
|
|
}
|
2020-12-02 14:49:24 +01:00
|
|
|
return mustache.render(input, context)
|
2020-11-19 10:24:58 +01:00
|
|
|
}
|
2020-11-25 10:50:51 +01:00
|
|
|
|
|
|
|
/**
|
2021-01-21 11:42:14 +01:00
|
|
|
* Recursively enriches all props in a props object and returns the new props.
|
|
|
|
* Props are deeply cloned so that no mutation is done to the source object.
|
2020-11-25 10:50:51 +01:00
|
|
|
*/
|
|
|
|
export const enrichDataBindings = (props, context) => {
|
2021-01-21 11:42:14 +01:00
|
|
|
let clonedProps = cloneDeep(props)
|
|
|
|
recursiveEnrich(clonedProps, context)
|
|
|
|
return clonedProps
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Recurses through an object and enriches all string props found.
|
|
|
|
*/
|
|
|
|
const recursiveEnrich = (props, context) => {
|
|
|
|
if (typeof props !== "object") {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let keys = []
|
|
|
|
if (Array.isArray(props)) {
|
|
|
|
keys = Array.from(props.keys())
|
|
|
|
} else if (typeof props === "object") {
|
|
|
|
keys = Object.keys(props || {})
|
|
|
|
}
|
|
|
|
keys.forEach(key => {
|
|
|
|
if (typeof props[key] === "string") {
|
|
|
|
props[key] = enrichDataBinding(props[key], context)
|
|
|
|
} else {
|
|
|
|
recursiveEnrich(props[key], context)
|
|
|
|
}
|
2020-11-25 10:50:51 +01:00
|
|
|
})
|
|
|
|
}
|