budibase/packages/string-templates/src/processors/preprocessor.js

74 lines
2.3 KiB
JavaScript

const { HelperNames } = require("../helpers")
const { swapStrings, isAlphaNumeric } = require("../utilities")
const FUNCTION_CASES = ["#", "else", "/"]
const PreprocessorNames = {
SWAP_TO_DOT: "swap-to-dot-notation",
FIX_FUNCTIONS: "fix-functions",
FINALISE: "finalise",
}
/* eslint-disable no-unused-vars */
class Preprocessor {
constructor(name, fn) {
this.name = name
this.fn = fn
}
process(fullString, statement) {
const output = this.fn(statement)
const idx = fullString.indexOf(statement)
return swapStrings(fullString, idx, statement.length, output)
}
}
module.exports.processors = [
new Preprocessor(PreprocessorNames.SWAP_TO_DOT, statement => {
let startBraceIdx = statement.indexOf("[")
let lastIdx = 0
while (startBraceIdx !== -1) {
// if the character previous to the literal specifier is alpha-numeric this should happen
if (isAlphaNumeric(statement.charAt(startBraceIdx - 1))) {
statement = swapStrings(statement, startBraceIdx + lastIdx, 1, ".[")
}
lastIdx = startBraceIdx + 1
const nextBraceIdx = statement.substring(lastIdx + 1).indexOf("[")
startBraceIdx = nextBraceIdx > 0 ? lastIdx + 1 + nextBraceIdx : -1
}
return statement
}),
new Preprocessor(PreprocessorNames.FIX_FUNCTIONS, statement => {
for (let specialCase of FUNCTION_CASES) {
const toFind = `{ ${specialCase}`,
replacement = `{${specialCase}`
statement = statement.replace(new RegExp(toFind, "g"), replacement)
}
return statement
}),
new Preprocessor(PreprocessorNames.FINALISE, statement => {
let insideStatement = statement.slice(2, statement.length - 2)
if (insideStatement.charAt(0) === " ") {
insideStatement = insideStatement.slice(1)
}
if (insideStatement.charAt(insideStatement.length - 1) === " ") {
insideStatement = insideStatement.slice(0, insideStatement.length - 1)
}
const possibleHelper = insideStatement.split(" ")[0]
// function helpers can't be wrapped
for (let specialCase of FUNCTION_CASES) {
if (possibleHelper.includes(specialCase)) {
return statement
}
}
if (HelperNames().some(option => option.includes(possibleHelper))) {
insideStatement = `(${insideStatement})`
}
return `{{ all ${insideStatement} }}`
}),
]
module.exports.PreprocessorNames = PreprocessorNames