From bb85078300e8c9056f7f9c9c17648d340dcfe495 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 25 Jan 2021 18:14:45 +0000 Subject: [PATCH] Adding a literal helper which can make sure the output of an operation is a literal value. --- .../string-templates/src/helpers/constants.js | 3 ++ .../string-templates/src/helpers/index.js | 8 ++++- .../string-templates/src/processors/index.js | 14 +++++--- .../src/processors/postprocessor.js | 36 ++++++++++++++++++- packages/string-templates/src/utilities.js | 2 +- .../string-templates/test/helpers.spec.js | 16 +++++++++ 6 files changed, 71 insertions(+), 8 deletions(-) diff --git a/packages/string-templates/src/helpers/constants.js b/packages/string-templates/src/helpers/constants.js index 124ba6f277..f0d004060a 100644 --- a/packages/string-templates/src/helpers/constants.js +++ b/packages/string-templates/src/helpers/constants.js @@ -18,4 +18,7 @@ module.exports.HelperFunctionBuiltin = [ module.exports.HelperFunctionNames = { OBJECT: "object", ALL: "all", + LITERAL: "literal", } + +module.exports.LITERAL_MARKER = "%LITERAL%" diff --git a/packages/string-templates/src/helpers/index.js b/packages/string-templates/src/helpers/index.js index e5cf3c7a01..330f4761c8 100644 --- a/packages/string-templates/src/helpers/index.js +++ b/packages/string-templates/src/helpers/index.js @@ -1,7 +1,7 @@ const Helper = require("./Helper") const { SafeString } = require("handlebars") const externalHandlebars = require("./external") -const { HelperFunctionNames, HelperFunctionBuiltin } = require("./constants") +const { HelperFunctionNames, HelperFunctionBuiltin, LITERAL_MARKER } = require("./constants") const HTML_SWAPS = { "<": "<", @@ -27,6 +27,12 @@ const HELPERS = [ return HTML_SWAPS[tag] || tag }) }), + // adds a note for post-processor + new Helper(HelperFunctionNames.LITERAL, value => { + const type = typeof(value) + const outputVal = type === "object" ? JSON.stringify(value) : value + return `{{-${LITERAL_MARKER}-${type}-${outputVal}-}}` + }) ] module.exports.HelperNames = () => { diff --git a/packages/string-templates/src/processors/index.js b/packages/string-templates/src/processors/index.js index db02aee8e7..174041133a 100644 --- a/packages/string-templates/src/processors/index.js +++ b/packages/string-templates/src/processors/index.js @@ -2,19 +2,23 @@ const { FIND_HBS_REGEX } = require("../utilities") const preprocessor = require("./preprocessor") const postprocessor = require("./postprocessor") -function process(string, processors) { +function process(output, processors) { for (let processor of processors) { + // if a literal statement has occurred stop + if (typeof output !== "string") { + break + } // re-run search each time incase previous processor updated/removed a match - let regex = new RegExp(FIND_HBS_REGEX) - let matches = string.match(regex) + let regexp = new RegExp(FIND_HBS_REGEX) + let matches = output.match(regexp) if (matches == null) { continue } for (let match of matches) { - string = processor.process(string, match) + output = processor.process(output, match) } } - return string + return output } module.exports.preprocess = (string, finalise = true) => { diff --git a/packages/string-templates/src/processors/postprocessor.js b/packages/string-templates/src/processors/postprocessor.js index 9f2491cb17..66f8a3696c 100644 --- a/packages/string-templates/src/processors/postprocessor.js +++ b/packages/string-templates/src/processors/postprocessor.js @@ -1,9 +1,43 @@ +const { LITERAL_MARKER } = require("../helpers/constants") + +const PostProcessorNames = { + CONVERT_LITERALS: "convert-literals", +} + /* eslint-disable no-unused-vars */ class Postprocessor { constructor(name, fn) { this.name = name this.fn = fn } + + process(statement) { + return this.fn(statement) + } } -module.exports.processors = [] +module.exports.processors = [ + new Postprocessor(PostProcessorNames.CONVERT_LITERALS, statement => { + if (!statement.includes(LITERAL_MARKER)) { + return statement + } + + const components = statement.split("-") + // pop and shift remove the empty array elements from the first and last dash + components.pop() + components.shift() + const type = components[1] + const value = components[2] + switch (type) { + case "string": + return value + case "number": + return parseFloat(value) + case "boolean": + return value === "true" + case "object": + return JSON.parse(value) + } + return value + }) +] diff --git a/packages/string-templates/src/utilities.js b/packages/string-templates/src/utilities.js index 1f88db9d41..bebbc62557 100644 --- a/packages/string-templates/src/utilities.js +++ b/packages/string-templates/src/utilities.js @@ -1,7 +1,7 @@ const _ = require("lodash") const ALPHA_NUMERIC_REGEX = /^[A-Za-z0-9]+$/g -module.exports.FIND_HBS_REGEX = /{{([^{}])+}}/g +module.exports.FIND_HBS_REGEX = /{{([^{].*?)}}/g module.exports.isAlphaNumeric = char => { return char.match(ALPHA_NUMERIC_REGEX) diff --git a/packages/string-templates/test/helpers.spec.js b/packages/string-templates/test/helpers.spec.js index c85cd63f58..cf6828e641 100644 --- a/packages/string-templates/test/helpers.spec.js +++ b/packages/string-templates/test/helpers.spec.js @@ -258,4 +258,20 @@ describe("test the comparison helpers", () => { }) expect(output).toBe("s") }) +}) + +describe("Test the literal helper", () => { + it("should allow use of the literal specifier for a number", async () => { + const output = await processString(`{{literal a}}`, { + a: 51, + }) + expect(output).toBe(51) + }) + + it("should allow use of the literal specifier for an object", async () => { + const output = await processString(`{{literal a}}`, { + a: {b: 1}, + }) + expect(output.b).toBe(1) + }) }) \ No newline at end of file