Types
This commit is contained in:
parent
9e0e9297f5
commit
c3531ac8ba
|
@ -1,11 +1,11 @@
|
|||
import { getJsHelperList } from "../helpers"
|
||||
|
||||
function getLayers(fullBlock) {
|
||||
function getLayers(fullBlock: string): string[] {
|
||||
let layers = []
|
||||
while (fullBlock.length) {
|
||||
const start = fullBlock.lastIndexOf("("),
|
||||
end = fullBlock.indexOf(")")
|
||||
let layer
|
||||
let layer: string
|
||||
if (start === -1 || end === -1) {
|
||||
layer = fullBlock.trim()
|
||||
fullBlock = ""
|
||||
|
@ -21,7 +21,7 @@ function getLayers(fullBlock) {
|
|||
return layers
|
||||
}
|
||||
|
||||
function getVariable(variableName) {
|
||||
function getVariable(variableName: string) {
|
||||
if (!variableName || typeof variableName !== "string") {
|
||||
return variableName
|
||||
}
|
||||
|
@ -47,10 +47,12 @@ function getVariable(variableName) {
|
|||
return `$("${variableName}")`
|
||||
}
|
||||
|
||||
function buildList(parts, value) {
|
||||
function buildList(parts: any[], value: any) {
|
||||
function build() {
|
||||
return parts
|
||||
.map(part => (part.startsWith("helper") ? part : getVariable(part)))
|
||||
.map((part: string) =>
|
||||
part.startsWith("helper") ? part : getVariable(part)
|
||||
)
|
||||
.join(", ")
|
||||
}
|
||||
if (!value) {
|
||||
|
@ -60,12 +62,12 @@ function buildList(parts, value) {
|
|||
}
|
||||
}
|
||||
|
||||
function splitBySpace(layer) {
|
||||
function splitBySpace(layer: string) {
|
||||
const parts = []
|
||||
let started = null,
|
||||
endChar = null,
|
||||
last = 0
|
||||
function add(str) {
|
||||
function add(str: string) {
|
||||
const startsWith = ["]"]
|
||||
while (startsWith.indexOf(str.substring(0, 1)) !== -1) {
|
||||
str = str.substring(1, str.length)
|
||||
|
@ -103,7 +105,7 @@ function splitBySpace(layer) {
|
|||
return parts
|
||||
}
|
||||
|
||||
export function convertHBSBlock(block, blockNumber) {
|
||||
export function convertHBSBlock(block: string, blockNumber: number) {
|
||||
const braceLength = block[2] === "{" ? 3 : 2
|
||||
block = block.substring(braceLength, block.length - braceLength).trim()
|
||||
const layers = getLayers(block)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createContext, runInNewContext } from "vm"
|
||||
import { Context, createContext, runInNewContext } from "vm"
|
||||
import { create } from "handlebars"
|
||||
import { registerAll, registerMinimum } from "./helpers/index"
|
||||
import { preprocess, postprocess } from "./processors"
|
||||
|
@ -15,6 +15,7 @@ import { setJSRunner, removeJSRunner } from "./helpers/javascript"
|
|||
import { helpersToRemoveForJs } from "./helpers/list"
|
||||
|
||||
import manifest from "../manifest.json"
|
||||
import { ProcessOptions } from "./types"
|
||||
|
||||
export { setJSRunner, setOnErrorLog } from "./helpers/javascript"
|
||||
|
||||
|
@ -22,7 +23,7 @@ const hbsInstance = create()
|
|||
registerAll(hbsInstance)
|
||||
const hbsInstanceNoHelpers = create()
|
||||
registerMinimum(hbsInstanceNoHelpers)
|
||||
const defaultOpts = {
|
||||
const defaultOpts: ProcessOptions = {
|
||||
noHelpers: false,
|
||||
cacheTemplates: false,
|
||||
noEscaping: false,
|
||||
|
@ -33,7 +34,7 @@ const defaultOpts = {
|
|||
/**
|
||||
* Utility function to check if the object is valid.
|
||||
*/
|
||||
function testObject(object) {
|
||||
function testObject(object: any) {
|
||||
// JSON stringify will fail if there are any cycles, stops infinite recursion
|
||||
try {
|
||||
JSON.stringify(object)
|
||||
|
@ -46,7 +47,7 @@ function testObject(object) {
|
|||
* Creates a HBS template function for a given string, and optionally caches it.
|
||||
*/
|
||||
let templateCache = {}
|
||||
function createTemplate(string, opts) {
|
||||
function createTemplate(string: string, opts: ProcessOptions) {
|
||||
opts = { ...defaultOpts, ...opts }
|
||||
|
||||
// Finalising adds a helper, can't do this with no helpers
|
||||
|
@ -82,7 +83,11 @@ function createTemplate(string, opts) {
|
|||
* @param {object|undefined} [opts] optional - specify some options for processing.
|
||||
* @returns {Promise<object|array>} The structure input, as fully updated as possible.
|
||||
*/
|
||||
export async function processObject(object, context, opts?) {
|
||||
export async function processObject(
|
||||
object: { [x: string]: any },
|
||||
context: object,
|
||||
opts?: { noHelpers?: boolean; escapeNewlines?: boolean; onlyFound?: boolean }
|
||||
) {
|
||||
testObject(object)
|
||||
for (let key of Object.keys(object || {})) {
|
||||
if (object[key] != null) {
|
||||
|
@ -123,7 +128,11 @@ export async function processString(
|
|||
* @param {object|undefined} [opts] optional - specify some options for processing.
|
||||
* @returns {object|array} The structure input, as fully updated as possible.
|
||||
*/
|
||||
export function processObjectSync(object, context, opts) {
|
||||
export function processObjectSync(
|
||||
object: { [x: string]: any },
|
||||
context: any,
|
||||
opts: any
|
||||
) {
|
||||
testObject(object)
|
||||
for (let key of Object.keys(object || {})) {
|
||||
let val = object[key]
|
||||
|
@ -144,13 +153,17 @@ export function processObjectSync(object, context, opts) {
|
|||
* @param {object|undefined} [opts] optional - specify some options for processing.
|
||||
* @returns {string} The enriched string, all templates should have been replaced if they can be.
|
||||
*/
|
||||
export function processStringSync(string, context, opts?) {
|
||||
export function processStringSync(
|
||||
string: string,
|
||||
context: object,
|
||||
opts?: { noHelpers?: boolean; escapeNewlines?: boolean; onlyFound: any }
|
||||
) {
|
||||
// Take a copy of input in case of error
|
||||
const input = string
|
||||
if (typeof string !== "string") {
|
||||
throw "Cannot process non-string types."
|
||||
}
|
||||
function process(stringPart) {
|
||||
function process(stringPart: string) {
|
||||
const template = createTemplate(stringPart, opts)
|
||||
const now = Math.floor(Date.now() / 1000) * 1000
|
||||
return postprocess(
|
||||
|
@ -186,7 +199,7 @@ export function processStringSync(string, context, opts?) {
|
|||
* this function will find any double braces and switch to triple.
|
||||
* @param string the string to have double HBS statements converted to triple.
|
||||
*/
|
||||
export function disableEscaping(string) {
|
||||
export function disableEscaping(string: string) {
|
||||
const matches = findDoubleHbsInstances(string)
|
||||
if (matches == null) {
|
||||
return string
|
||||
|
@ -207,7 +220,7 @@ export function disableEscaping(string) {
|
|||
* @param {string} property The property which is to be wrapped.
|
||||
* @returns {string} The wrapped property ready to be added to a templating string.
|
||||
*/
|
||||
export function makePropSafe(property) {
|
||||
export function makePropSafe(property: any) {
|
||||
return `[${property}]`.replace("[[", "[").replace("]]", "]")
|
||||
}
|
||||
|
||||
|
@ -217,7 +230,7 @@ export function makePropSafe(property) {
|
|||
* @param [opts] optional - specify some options for processing.
|
||||
* @returns {boolean} Whether or not the input string is valid.
|
||||
*/
|
||||
export function isValid(string, opts?) {
|
||||
export function isValid(string: any, opts?: any) {
|
||||
const validCases = [
|
||||
"string",
|
||||
"number",
|
||||
|
@ -268,7 +281,7 @@ export function getManifest() {
|
|||
* @param handlebars the HBS expression to check
|
||||
* @returns {boolean} whether the expression is JS or not
|
||||
*/
|
||||
export function isJSBinding(handlebars) {
|
||||
export function isJSBinding(handlebars: any) {
|
||||
return decodeJSBinding(handlebars) != null
|
||||
}
|
||||
|
||||
|
@ -277,7 +290,7 @@ export function isJSBinding(handlebars) {
|
|||
* @param javascript the JS code to encode
|
||||
* @returns {string} the JS HBS expression
|
||||
*/
|
||||
export function encodeJSBinding(javascript) {
|
||||
export function encodeJSBinding(javascript: string) {
|
||||
return `{{ js "${btoa(javascript)}" }}`
|
||||
}
|
||||
|
||||
|
@ -286,7 +299,7 @@ export function encodeJSBinding(javascript) {
|
|||
* @param handlebars the JS HBS expression
|
||||
* @returns {string|null} the raw JS code
|
||||
*/
|
||||
export function decodeJSBinding(handlebars) {
|
||||
export function decodeJSBinding(handlebars: string) {
|
||||
if (!handlebars || typeof handlebars !== "string") {
|
||||
return null
|
||||
}
|
||||
|
@ -311,7 +324,7 @@ export function decodeJSBinding(handlebars) {
|
|||
* @param {string[]} strings The strings to look for.
|
||||
* @returns {boolean} Will return true if all strings found in HBS statement.
|
||||
*/
|
||||
export function doesContainStrings(template, strings) {
|
||||
export function doesContainStrings(template: string, strings: any[]) {
|
||||
let regexp = new RegExp(FIND_HBS_REGEX)
|
||||
let matches = template.match(regexp)
|
||||
if (matches == null) {
|
||||
|
@ -341,7 +354,7 @@ export function doesContainStrings(template, strings) {
|
|||
* @param {string} string The string to search within.
|
||||
* @return {string[]} The found HBS blocks.
|
||||
*/
|
||||
export function findHBSBlocks(string) {
|
||||
export function findHBSBlocks(string: string) {
|
||||
if (!string || typeof string !== "string") {
|
||||
return []
|
||||
}
|
||||
|
@ -362,11 +375,11 @@ export function findHBSBlocks(string) {
|
|||
* @param {string} string The word or sentence to search for.
|
||||
* @returns {boolean} The this return true if the string is found, false if not.
|
||||
*/
|
||||
export function doesContainString(template, string) {
|
||||
export function doesContainString(template: any, string: any) {
|
||||
return doesContainStrings(template, [string])
|
||||
}
|
||||
|
||||
export function convertToJS(hbs) {
|
||||
export function convertToJS(hbs: string) {
|
||||
const blocks = findHBSBlocks(hbs)
|
||||
let js = "return `",
|
||||
prevBlock: string | null = null
|
||||
|
@ -407,7 +420,7 @@ function defaultJSSetup() {
|
|||
/**
|
||||
* Use polyfilled vm to run JS scripts in a browser Env
|
||||
*/
|
||||
setJSRunner((js, context) => {
|
||||
setJSRunner((js: string, context: Context) => {
|
||||
context = {
|
||||
...context,
|
||||
alert: undefined,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { FIND_HBS_REGEX } from "../utilities"
|
||||
import * as preprocessor from "./preprocessor"
|
||||
import * as postprocessor from "./postprocessor"
|
||||
import { ProcessOptions } from "../types"
|
||||
|
||||
function process(output, processors, opts?) {
|
||||
function process(output: string, processors: any[], opts?: ProcessOptions) {
|
||||
for (let processor of processors) {
|
||||
// if a literal statement has occurred stop
|
||||
if (typeof output !== "string") {
|
||||
|
@ -21,7 +22,7 @@ function process(output, processors, opts?) {
|
|||
return output
|
||||
}
|
||||
|
||||
export function preprocess(string, opts) {
|
||||
export function preprocess(string: string, opts: ProcessOptions) {
|
||||
let processors = preprocessor.processors
|
||||
if (opts.noFinalise) {
|
||||
processors = processors.filter(
|
||||
|
@ -30,7 +31,7 @@ export function preprocess(string, opts) {
|
|||
}
|
||||
return process(string, processors, opts)
|
||||
}
|
||||
export function postprocess(string) {
|
||||
export function postprocess(string: string) {
|
||||
let processors = postprocessor.processors
|
||||
return process(string, processors)
|
||||
}
|
||||
|
|
|
@ -6,45 +6,51 @@ export const PostProcessorNames = {
|
|||
|
||||
/* eslint-disable no-unused-vars */
|
||||
class Postprocessor {
|
||||
name
|
||||
private fn
|
||||
name: string
|
||||
private fn: any
|
||||
|
||||
constructor(name, fn) {
|
||||
constructor(name: string, fn: any) {
|
||||
this.name = name
|
||||
this.fn = fn
|
||||
}
|
||||
|
||||
process(statement) {
|
||||
process(statement: any) {
|
||||
return this.fn(statement)
|
||||
}
|
||||
}
|
||||
|
||||
export const processors = [
|
||||
new Postprocessor(PostProcessorNames.CONVERT_LITERALS, statement => {
|
||||
if (typeof statement !== "string" || !statement.includes(LITERAL_MARKER)) {
|
||||
return statement
|
||||
new Postprocessor(
|
||||
PostProcessorNames.CONVERT_LITERALS,
|
||||
(statement: string) => {
|
||||
if (
|
||||
typeof statement !== "string" ||
|
||||
!statement.includes(LITERAL_MARKER)
|
||||
) {
|
||||
return statement
|
||||
}
|
||||
const splitMarkerIndex = statement.indexOf("-")
|
||||
const type = statement.substring(12, splitMarkerIndex)
|
||||
const value = statement.substring(
|
||||
splitMarkerIndex + 1,
|
||||
statement.length - 2
|
||||
)
|
||||
switch (type) {
|
||||
case "string":
|
||||
return value
|
||||
case "number":
|
||||
return parseFloat(value)
|
||||
case "boolean":
|
||||
return value === "true"
|
||||
case "object":
|
||||
return JSON.parse(value)
|
||||
case "js_result":
|
||||
// We use the literal helper to process the result of JS expressions
|
||||
// as we want to be able to return any types.
|
||||
// We wrap the value in an abject to be able to use undefined properly.
|
||||
return JSON.parse(value).data
|
||||
}
|
||||
return value
|
||||
}
|
||||
const splitMarkerIndex = statement.indexOf("-")
|
||||
const type = statement.substring(12, splitMarkerIndex)
|
||||
const value = statement.substring(
|
||||
splitMarkerIndex + 1,
|
||||
statement.length - 2
|
||||
)
|
||||
switch (type) {
|
||||
case "string":
|
||||
return value
|
||||
case "number":
|
||||
return parseFloat(value)
|
||||
case "boolean":
|
||||
return value === "true"
|
||||
case "object":
|
||||
return JSON.parse(value)
|
||||
case "js_result":
|
||||
// We use the literal helper to process the result of JS expressions
|
||||
// as we want to be able to return any types.
|
||||
// We wrap the value in an abject to be able to use undefined properly.
|
||||
return JSON.parse(value).data
|
||||
}
|
||||
return value
|
||||
}),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -14,7 +14,7 @@ class Preprocessor {
|
|||
name: string
|
||||
private fn: any
|
||||
|
||||
constructor(name, fn) {
|
||||
constructor(name: string, fn: any) {
|
||||
this.name = name
|
||||
this.fn = fn
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class Preprocessor {
|
|||
}
|
||||
|
||||
export const processors = [
|
||||
new Preprocessor(PreprocessorNames.SWAP_TO_DOT, statement => {
|
||||
new Preprocessor(PreprocessorNames.SWAP_TO_DOT, (statement: string) => {
|
||||
let startBraceIdx = statement.indexOf("[")
|
||||
let lastIdx = 0
|
||||
while (startBraceIdx !== -1) {
|
||||
|
@ -42,7 +42,7 @@ export const processors = [
|
|||
return statement
|
||||
}),
|
||||
|
||||
new Preprocessor(PreprocessorNames.FIX_FUNCTIONS, statement => {
|
||||
new Preprocessor(PreprocessorNames.FIX_FUNCTIONS, (statement: string) => {
|
||||
for (let specialCase of FUNCTION_CASES) {
|
||||
const toFind = `{ ${specialCase}`,
|
||||
replacement = `{${specialCase}`
|
||||
|
@ -51,29 +51,32 @@ export const processors = [
|
|||
return statement
|
||||
}),
|
||||
|
||||
new Preprocessor(PreprocessorNames.FINALISE, (statement, opts) => {
|
||||
const noHelpers = opts && opts.noHelpers
|
||||
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
|
||||
new Preprocessor(
|
||||
PreprocessorNames.FINALISE,
|
||||
(statement: string, opts: { noHelpers: any }) => {
|
||||
const noHelpers = opts && opts.noHelpers
|
||||
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
|
||||
}
|
||||
}
|
||||
const testHelper = possibleHelper.trim().toLowerCase()
|
||||
if (
|
||||
!noHelpers &&
|
||||
HelperNames().some(option => testHelper === option.toLowerCase())
|
||||
) {
|
||||
insideStatement = `(${insideStatement})`
|
||||
}
|
||||
return `{{ all ${insideStatement} }}`
|
||||
}
|
||||
const testHelper = possibleHelper.trim().toLowerCase()
|
||||
if (
|
||||
!noHelpers &&
|
||||
HelperNames().some(option => testHelper === option.toLowerCase())
|
||||
) {
|
||||
insideStatement = `(${insideStatement})`
|
||||
}
|
||||
return `{{ all ${insideStatement} }}`
|
||||
}),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export interface ProcessOptions {
|
||||
cacheTemplates?: boolean
|
||||
noEscaping?: boolean
|
||||
noHelpers?: boolean
|
||||
noFinalise?: boolean
|
||||
escapeNewlines?: boolean
|
||||
}
|
Loading…
Reference in New Issue