Merge branch 'feature/handlebars-migration' of github.com:Budibase/budibase into component-binding-refactor

This commit is contained in:
Andrew Kingston 2021-01-21 18:14:47 +00:00
commit e5db9d6725
11 changed files with 114 additions and 60 deletions

View File

@ -14,10 +14,12 @@
"dependencies": { "dependencies": {
"handlebars": "^4.7.6", "handlebars": "^4.7.6",
"handlebars-helpers": "^0.10.0", "handlebars-helpers": "^0.10.0",
"handlebars-utils": "^1.0.6",
"helper-date": "^1.0.1", "helper-date": "^1.0.1",
"lodash": "^4.17.20" "lodash": "^4.17.20"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-json": "^4.1.0",
"jest": "^26.6.3", "jest": "^26.6.3",
"rollup": "^2.36.2", "rollup": "^2.36.2",
"rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-commonjs": "^10.1.0",

View File

@ -1,24 +1,28 @@
import commonjs from "rollup-plugin-commonjs" import commonjs from "rollup-plugin-commonjs"
import nodeResolve from "rollup-plugin-node-resolve" import resolve from "rollup-plugin-node-resolve"
import globals from "rollup-plugin-node-globals"
import builtins from "rollup-plugin-node-builtins" import builtins from "rollup-plugin-node-builtins"
import globals from "rollup-plugin-node-globals"
import json from "@rollup/plugin-json"
export default { export default {
input: "src/index.js", input: "src/index.js",
output: { output: [
file: "dist/bundle.js", {
sourcemap: true,
format: "umd", format: "umd",
file: "./dist/bundle.js",
name: "string-templates", name: "string-templates",
exports: "named", exports: "named",
globals: {
fs: "fs",
}, },
}, ],
external: ["fs"],
plugins: [ plugins: [
nodeResolve({ preferBuiltins: false }), resolve({
preferBuiltins: true,
browser: true,
}),
commonjs(), commonjs(),
globals(), globals(),
builtins(), builtins(),
json(),
], ],
} }

View File

@ -12,7 +12,7 @@ module.exports.HelperFunctionBuiltin = [
"unless", "unless",
"log", "log",
"lookup", "lookup",
"with" "with",
] ]
module.exports.HelperFunctionNames = { module.exports.HelperFunctionNames = {

View File

@ -13,7 +13,7 @@ const EXTERNAL_FUNCTION_COLLECTIONS = [
"number", "number",
"url", "url",
"string", "string",
"markdown" "markdown",
] ]
const DATE_NAME = "date" const DATE_NAME = "date"
@ -24,17 +24,20 @@ exports.registerAll = handlebars => {
for (let collection of EXTERNAL_FUNCTION_COLLECTIONS) { for (let collection of EXTERNAL_FUNCTION_COLLECTIONS) {
// collect information about helper // collect information about helper
let hbsHelperInfo = helpers[collection]() let hbsHelperInfo = helpers[collection]()
for (let [name, func] of Object.entries(hbsHelperInfo)) { for (let entry of Object.entries(hbsHelperInfo)) {
const name = entry[0]
// skip built in functions and ones seen already // skip built in functions and ones seen already
if (HelperFunctionBuiltin.indexOf(name) !== -1 || if (
externalNames.indexOf(name) !== -1) { HelperFunctionBuiltin.indexOf(name) !== -1 ||
externalNames.indexOf(name) !== -1
) {
continue continue
} }
externalNames.push(name) externalNames.push(name)
} }
// attach it to our handlebars instance // attach it to our handlebars instance
helpers[collection]({ helpers[collection]({
handlebars handlebars,
}) })
} }
// add date external functionality // add date external functionality

View File

@ -32,7 +32,7 @@ const HELPERS = [
module.exports.HelperNames = () => { module.exports.HelperNames = () => {
return Object.values(HelperFunctionNames).concat( return Object.values(HelperFunctionNames).concat(
HelperFunctionBuiltin, HelperFunctionBuiltin,
externalHandlebars.externalHelperNames, externalHandlebars.externalHelperNames
) )
} }

View File

@ -1,6 +1,6 @@
const handlebars = require("handlebars") const handlebars = require("handlebars")
const { registerAll } = require("./helpers/index") const { registerAll } = require("./helpers/index")
const { preprocess } = require("./custom/preprocessor") const processors = require("./processors")
const { cloneDeep } = require("lodash/fp") const { cloneDeep } = require("lodash/fp")
const { removeNull } = require("./utilities") const { removeNull } = require("./utilities")
@ -88,10 +88,10 @@ module.exports.processStringSync = (string, context) => {
throw "Cannot process non-string types." throw "Cannot process non-string types."
} }
let template let template
string = preprocess(string) string = processors.preprocess(string)
// this does not throw an error when template can't be fulfilled, have to try correct beforehand // this does not throw an error when template can't be fulfilled, have to try correct beforehand
template = hbsInstance.compile(string) template = hbsInstance.compile(string)
return template(clonedContext) return processors.postprocess(template(clonedContext))
} }
/** /**

View File

@ -0,0 +1,26 @@
const { FIND_HBS_REGEX } = require("../utilities")
const preprocessor = require("./preprocessor")
const postprocessor = require("./postprocessor")
function process(string, processors) {
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 = processor.process(string, match)
}
}
return string
}
module.exports.preprocess = string => {
return process(string, preprocessor.processors)
}
module.exports.postprocess = string => {
return process(string, postprocessor.processors)
}

View File

@ -1,6 +1,9 @@
/* eslint-disable no-unused-vars */
class Postprocessor { class Postprocessor {
constructor(name, fn) { constructor(name, fn) {
this.name = name this.name = name
this.fn = fn this.fn = fn
} }
} }
module.exports.processors = []

View File

@ -1,10 +1,5 @@
const { HelperNames } = require("../helpers") const { HelperNames } = require("../helpers")
const { const { swapStrings, isAlphaNumeric } = require("../utilities")
swapStrings,
isAlphaNumeric,
FIND_HBS_REGEX,
includesAny,
} = require("../utilities")
const PreprocessorNames = { const PreprocessorNames = {
SWAP_TO_DOT: "swap-to-dot-notation", SWAP_TO_DOT: "swap-to-dot-notation",
@ -12,6 +7,7 @@ const PreprocessorNames = {
FINALISE: "finalise", FINALISE: "finalise",
} }
/* eslint-disable no-unused-vars */
class Preprocessor { class Preprocessor {
constructor(name, fn) { constructor(name, fn) {
this.name = name this.name = name
@ -25,7 +21,7 @@ class Preprocessor {
} }
} }
const PROCESSORS = [ module.exports.processors = [
new Preprocessor(PreprocessorNames.SWAP_TO_DOT, statement => { new Preprocessor(PreprocessorNames.SWAP_TO_DOT, statement => {
let startBraceIdx = statement.indexOf("[") let startBraceIdx = statement.indexOf("[")
let lastIdx = 0 let lastIdx = 0
@ -44,10 +40,14 @@ const PROCESSORS = [
// exclude helpers and brackets, regex will only find double brackets // exclude helpers and brackets, regex will only find double brackets
const exclusions = HelperNames() const exclusions = HelperNames()
// find all the parts split by spaces // find all the parts split by spaces
const splitBySpaces = statement.split(" ").filter(el => el !== "{{" && el !== "}}") const splitBySpaces = statement
.split(" ")
.filter(el => el !== "{{" && el !== "}}")
// remove braces if they are found and weren't spaced out // remove braces if they are found and weren't spaced out
splitBySpaces[0] = splitBySpaces[0].replace("{", "") splitBySpaces[0] = splitBySpaces[0].replace("{", "")
splitBySpaces[splitBySpaces.length - 1] = splitBySpaces[splitBySpaces.length - 1].replace("}", "") splitBySpaces[splitBySpaces.length - 1] = splitBySpaces[
splitBySpaces.length - 1
].replace("}", "")
// remove the excluded elements // remove the excluded elements
const propertyParts = splitBySpaces.filter( const propertyParts = splitBySpaces.filter(
part => exclusions.indexOf(part) === -1 part => exclusions.indexOf(part) === -1
@ -86,29 +86,3 @@ const PROCESSORS = [
return `{{ all ${insideStatement} }}` return `{{ all ${insideStatement} }}`
}), }),
] ]
/**
* When running handlebars statements to execute on the context of the automation it possible user's may input handlebars
* in a few different forms, some of which are invalid but are logically valid. An example of this would be the handlebars
* statement "{{steps[0].revision}}" here it is obvious the user is attempting to access an array or object using array
* like operators. These are not supported by handlebars and therefore the statement will fail. This function pre-processes will
* the handlebars statement so it instead reads as "{{steps.0.revision}}" which is valid and will work. It may also be expanded
* to include any other handlebars statement pre-process that has been deemed necessary for the system.
*
* @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 => {
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 = processor.process(string, match)
}
}
return string
}

View File

@ -14,7 +14,7 @@ module.exports.swapStrings = (string, start, length, swap) => {
module.exports.removeNull = obj => { module.exports.removeNull = obj => {
return Object.fromEntries( return Object.fromEntries(
Object.entries(obj) Object.entries(obj)
.filter(([key, value]) => value != null) .filter(entry => entry[1] != null)
.map(([key, value]) => [ .map(([key, value]) => [
key, key,
value === Object(value) ? module.exports.removeNull(value) : value, value === Object(value) ? module.exports.removeNull(value) : value,

View File

@ -465,6 +465,22 @@
"@types/yargs" "^15.0.0" "@types/yargs" "^15.0.0"
chalk "^4.0.0" chalk "^4.0.0"
"@rollup/plugin-json@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3"
integrity sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==
dependencies:
"@rollup/pluginutils" "^3.0.8"
"@rollup/pluginutils@^3.0.8":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
dependencies:
"@types/estree" "0.0.39"
estree-walker "^1.0.1"
picomatch "^2.2.2"
"@sinonjs/commons@^1.7.0": "@sinonjs/commons@^1.7.0":
version "1.8.2" version "1.8.2"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b"
@ -517,6 +533,11 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe"
integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg== integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==
"@types/estree@0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
"@types/graceful-fs@^4.1.2": "@types/graceful-fs@^4.1.2":
version "4.1.4" version "4.1.4"
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.4.tgz#4ff9f641a7c6d1a3508ff88bc3141b152772e753" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.4.tgz#4ff9f641a7c6d1a3508ff88bc3141b152772e753"
@ -1755,6 +1776,11 @@ estree-walker@^0.6.1:
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
estree-walker@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
esutils@^2.0.2: esutils@^2.0.2:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@ -3345,7 +3371,7 @@ magic-string@^0.22.5:
dependencies: dependencies:
vlq "^0.2.2" vlq "^0.2.2"
magic-string@^0.25.2: magic-string@^0.25.2, magic-string@^0.25.3:
version "0.25.7" version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
@ -3758,7 +3784,7 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
picomatch@^2.0.4, picomatch@^2.0.5: picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.2:
version "2.2.2" version "2.2.2"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
@ -4087,6 +4113,15 @@ rollup-plugin-commonjs@^10.1.0:
resolve "^1.11.0" resolve "^1.11.0"
rollup-pluginutils "^2.8.1" rollup-pluginutils "^2.8.1"
rollup-plugin-inject@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz#e4233855bfba6c0c12a312fd6649dff9a13ee9f4"
integrity sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==
dependencies:
estree-walker "^0.6.1"
magic-string "^0.25.3"
rollup-pluginutils "^2.8.1"
rollup-plugin-node-builtins@^2.1.2: rollup-plugin-node-builtins@^2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/rollup-plugin-node-builtins/-/rollup-plugin-node-builtins-2.1.2.tgz#24a1fed4a43257b6b64371d8abc6ce1ab14597e9" resolved "https://registry.yarnpkg.com/rollup-plugin-node-builtins/-/rollup-plugin-node-builtins-2.1.2.tgz#24a1fed4a43257b6b64371d8abc6ce1ab14597e9"
@ -4109,6 +4144,13 @@ rollup-plugin-node-globals@^1.4.0:
process-es6 "^0.11.6" process-es6 "^0.11.6"
rollup-pluginutils "^2.3.1" rollup-pluginutils "^2.3.1"
rollup-plugin-node-polyfills@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz#53092a2744837164d5b8a28812ba5f3ff61109fd"
integrity sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==
dependencies:
rollup-plugin-inject "^3.0.0"
rollup-plugin-node-resolve@^5.2.0: rollup-plugin-node-resolve@^5.2.0:
version "5.2.0" version "5.2.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz#730f93d10ed202473b1fb54a5997a7db8c6d8523" resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz#730f93d10ed202473b1fb54a5997a7db8c6d8523"