mirror of https://github.com/Budibase/budibase.git
6 changed files with 84 additions and 2 deletions
@ -0,0 +1,66 @@ |
|||
const CAPTURE_JS = new RegExp(/{{ js "(.*)" }}/) |
|||
const vm = require("vm") |
|||
|
|||
// Helper utility to strip square brackets from a value
|
|||
const removeSquareBrackets = value => { |
|||
if (!value || typeof value !== "string") { |
|||
return value |
|||
} |
|||
const regex = /\[+(.+)]+/ |
|||
const matches = value.match(regex) |
|||
if (matches && matches[1]) { |
|||
return matches[1] |
|||
} |
|||
return value |
|||
} |
|||
|
|||
// Our context getter function provided to JS code as $.
|
|||
// Extracts a value from context.
|
|||
const getContextValue = (path, context) => { |
|||
let data = context |
|||
path.split(".").forEach(key => { |
|||
data = data[removeSquareBrackets(key)] || {} |
|||
}) |
|||
return data |
|||
} |
|||
|
|||
// Evaluates JS code against a certain context
|
|||
module.exports.processJS = (handlebars, context) => { |
|||
try { |
|||
// Wrap JS in a function and immediately invoke it.
|
|||
// This is required to allow the final `return` statement to be valid.
|
|||
const js = `function run(){${atob(handlebars)}};run();` |
|||
|
|||
// Our $ context function gets a value from context
|
|||
const sandboxContext = { $: path => getContextValue(path, context) } |
|||
|
|||
// Create a sandbox with out context and run the JS
|
|||
vm.createContext(sandboxContext) |
|||
return vm.runInNewContext(js, sandboxContext) |
|||
} catch (error) { |
|||
console.warn(error) |
|||
return "Error while executing JS" |
|||
} |
|||
} |
|||
|
|||
// Checks if a HBS expression is a valid JS HBS expression
|
|||
module.exports.isJSBinding = handlebars => { |
|||
return module.exports.decodeJSBinding(handlebars) != null |
|||
} |
|||
|
|||
// Encodes a raw JS string as a JS HBS expression
|
|||
module.exports.encodeJSBinding = javascript => { |
|||
return `{{ js "${btoa(javascript)}" }}` |
|||
} |
|||
|
|||
// Decodes a JS HBS expression to the raw JS string
|
|||
module.exports.decodeJSBinding = handlebars => { |
|||
if (!handlebars || typeof handlebars !== "string") { |
|||
return null |
|||
} |
|||
const match = handlebars.match(CAPTURE_JS) |
|||
if (!match || match.length < 2) { |
|||
return null |
|||
} |
|||
return atob(match[1]) |
|||
} |
|||
Loading…
Reference in new issue