Handling undefined/null values in context object for string templates, replacing with empty string.
This commit is contained in:
parent
4deccae711
commit
38144f84a3
|
@ -12,15 +12,16 @@
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"handlebars": "^4.7.6"
|
"handlebars": "^4.7.6",
|
||||||
|
"lodash": "^4.17.20"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"jest": "^26.6.3",
|
||||||
"rollup": "^2.36.2",
|
"rollup": "^2.36.2",
|
||||||
"rollup-plugin-commonjs": "^10.1.0",
|
"rollup-plugin-commonjs": "^10.1.0",
|
||||||
"rollup-plugin-node-builtins": "^2.1.2",
|
"rollup-plugin-node-builtins": "^2.1.2",
|
||||||
"rollup-plugin-node-globals": "^1.4.0",
|
"rollup-plugin-node-globals": "^1.4.0",
|
||||||
"rollup-plugin-node-resolve": "^5.2.0",
|
"rollup-plugin-node-resolve": "^5.2.0",
|
||||||
"typescript": "^4.1.3",
|
"typescript": "^4.1.3"
|
||||||
"jest": "^26.6.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
class Postprocessor {
|
||||||
|
constructor(name, fn) {
|
||||||
|
this.name = name
|
||||||
|
this.fn = fn
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,12 @@ const {
|
||||||
includesAny,
|
includesAny,
|
||||||
} = require("../utilities")
|
} = require("../utilities")
|
||||||
|
|
||||||
|
const PreprocessorNames = {
|
||||||
|
SWAP_TO_DOT: "swap-to-dot-notation",
|
||||||
|
HANDLE_SPACES: "handle-spaces-in-properties",
|
||||||
|
FINALISE: "finalise",
|
||||||
|
}
|
||||||
|
|
||||||
class Preprocessor {
|
class Preprocessor {
|
||||||
constructor(name, fn) {
|
constructor(name, fn) {
|
||||||
this.name = name
|
this.name = name
|
||||||
|
@ -20,7 +26,7 @@ class Preprocessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
const PROCESSORS = [
|
const PROCESSORS = [
|
||||||
new Preprocessor("swap-to-dot-notation", statement => {
|
new Preprocessor(PreprocessorNames.SWAP_TO_DOT, statement => {
|
||||||
let startBraceIdx = statement.indexOf("[")
|
let startBraceIdx = statement.indexOf("[")
|
||||||
let lastIdx = 0
|
let lastIdx = 0
|
||||||
while (startBraceIdx !== -1) {
|
while (startBraceIdx !== -1) {
|
||||||
|
@ -34,7 +40,7 @@ const PROCESSORS = [
|
||||||
return statement
|
return statement
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new Preprocessor("handle-spaces-in-properties", statement => {
|
new Preprocessor(PreprocessorNames.HANDLE_SPACES, statement => {
|
||||||
// exclude helpers and brackets, regex will only find double brackets
|
// exclude helpers and brackets, regex will only find double brackets
|
||||||
const exclusions = HelperFunctions.concat(["{{", "}}"])
|
const exclusions = HelperFunctions.concat(["{{", "}}"])
|
||||||
// find all the parts split by spaces
|
// find all the parts split by spaces
|
||||||
|
@ -62,7 +68,7 @@ const PROCESSORS = [
|
||||||
return statement.replace(/\[\[/g, "[").replace(/]]/g, "]")
|
return statement.replace(/\[\[/g, "[").replace(/]]/g, "]")
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new Preprocessor("finalise", statement => {
|
new Preprocessor(Preprocessor.FINALISE, statement => {
|
||||||
let insideStatement = statement.slice(2, statement.length - 2)
|
let insideStatement = statement.slice(2, statement.length - 2)
|
||||||
if (insideStatement.charAt(0) === " ") {
|
if (insideStatement.charAt(0) === " ") {
|
||||||
insideStatement = insideStatement.slice(1)
|
insideStatement = insideStatement.slice(1)
|
||||||
|
@ -74,7 +80,7 @@ const PROCESSORS = [
|
||||||
insideStatement = `(${insideStatement})`
|
insideStatement = `(${insideStatement})`
|
||||||
}
|
}
|
||||||
return `{{ all ${insideStatement} }}`
|
return `{{ all ${insideStatement} }}`
|
||||||
})
|
}),
|
||||||
]
|
]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,6 +27,10 @@ const HELPERS = [
|
||||||
}),
|
}),
|
||||||
// this help is applied to all statements
|
// this help is applied to all statements
|
||||||
new Helper(HelperFunctionNames.ALL, value => {
|
new Helper(HelperFunctionNames.ALL, value => {
|
||||||
|
// null/undefined values produce bad results
|
||||||
|
if (value == null) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
let text = new SafeString(unescape(value).replace(/&/g, "&"))
|
let text = new SafeString(unescape(value).replace(/&/g, "&"))
|
||||||
if (text == null || typeof text !== "string") {
|
if (text == null || typeof text !== "string") {
|
||||||
return text
|
return text
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
const handlebars = require("handlebars")
|
const handlebars = require("handlebars")
|
||||||
const { registerAll } = require("./helpers/index")
|
const { registerAll } = require("./helpers/index")
|
||||||
const { preprocess } = require("./custom/preprocessor")
|
const { preprocess } = require("./custom/preprocessor")
|
||||||
|
const { cloneDeep } = require("lodash/fp")
|
||||||
|
const { removeNull } = require("./utilities")
|
||||||
|
|
||||||
const hbsInstance = handlebars.create()
|
const hbsInstance = handlebars.create()
|
||||||
registerAll(hbsInstance)
|
registerAll(hbsInstance)
|
||||||
|
@ -78,6 +80,8 @@ module.exports.processObjectSync = (object, context) => {
|
||||||
* @returns {string} The enriched string, all templates should have been replaced if they can be.
|
* @returns {string} The enriched string, all templates should have been replaced if they can be.
|
||||||
*/
|
*/
|
||||||
module.exports.processStringSync = (string, context) => {
|
module.exports.processStringSync = (string, context) => {
|
||||||
|
const clonedContext = removeNull(cloneDeep(context))
|
||||||
|
// remove any null/undefined properties
|
||||||
if (typeof string !== "string") {
|
if (typeof string !== "string") {
|
||||||
throw "Cannot process non-string types."
|
throw "Cannot process non-string types."
|
||||||
}
|
}
|
||||||
|
@ -85,7 +89,7 @@ module.exports.processStringSync = (string, context) => {
|
||||||
string = preprocess(string)
|
string = 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(context)
|
return template(clonedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,3 +13,15 @@ module.exports.swapStrings = (string, start, length, swap) => {
|
||||||
module.exports.includesAny = (string, options) => {
|
module.exports.includesAny = (string, options) => {
|
||||||
return options.some(option => string.includes(option))
|
return options.some(option => string.includes(option))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removes null and undefined
|
||||||
|
module.exports.removeNull = obj => {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(obj)
|
||||||
|
.filter(([key, value]) => value != null)
|
||||||
|
.map(([key, value]) => [
|
||||||
|
key,
|
||||||
|
value === Object(value) ? module.exports.removeNull(value) : value,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,14 @@ describe("Test that the string processing works correctly", () => {
|
||||||
}
|
}
|
||||||
expect(error).not.toBeNull()
|
expect(error).not.toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("confirm that null properties are handled correctly", async () => {
|
||||||
|
const output = await processString("hello {{ name }} I am {{ name2 }}", {
|
||||||
|
name: undefined,
|
||||||
|
name2: null,
|
||||||
|
})
|
||||||
|
expect(output).toBe("hello I am ")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Test that the object processing works correctly", () => {
|
describe("Test that the object processing works correctly", () => {
|
||||||
|
|
|
@ -2799,7 +2799,7 @@ lodash.sortby@^4.7.0:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||||
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
|
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
|
||||||
|
|
||||||
lodash@^4.17.19:
|
lodash@^4.17.19, lodash@^4.17.20:
|
||||||
version "4.17.20"
|
version "4.17.20"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||||
|
|
Loading…
Reference in New Issue