@budibase/string-templates 2.22.1 → 2.22.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.cjs +1 -0
- package/dist/bundle.mjs +1 -1
- package/dist/conversion/index.d.ts +2 -2
- package/dist/errors.d.ts +1 -2
- package/dist/helpers/Helper.d.ts +9 -8
- package/dist/helpers/constants.d.ts +8 -8
- package/dist/helpers/date.d.ts +2 -2
- package/dist/helpers/external.d.ts +8 -15
- package/dist/helpers/index.d.ts +5 -6
- package/dist/helpers/javascript.d.ts +7 -4
- package/dist/helpers/list.d.ts +2 -2
- package/dist/iife.d.ts +1 -1
- package/dist/index.d.ts +1078 -20
- package/dist/processors/index.d.ts +3 -2
- package/dist/processors/postprocessor.d.ts +7 -7
- package/dist/processors/preprocessor.d.ts +10 -10
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/utilities.d.ts +11 -11
- package/package.json +13 -13
- package/src/conversion/{index.js → index.ts} +13 -11
- package/src/errors.ts +3 -0
- package/src/helpers/Helper.ts +34 -0
- package/src/helpers/{constants.js → constants.ts} +3 -3
- package/src/helpers/{date.js → date.ts} +26 -16
- package/src/helpers/{external.js → external.ts} +13 -11
- package/src/helpers/index.ts +103 -0
- package/src/helpers/{javascript.js → javascript.ts} +20 -18
- package/src/helpers/{list.js → list.ts} +11 -11
- package/src/iife.ts +3 -0
- package/src/{index.js → index.ts} +100 -85
- package/src/processors/{index.js → index.ts} +7 -6
- package/src/processors/postprocessor.ts +56 -0
- package/src/processors/preprocessor.ts +82 -0
- package/src/types.ts +8 -0
- package/src/{utilities.js → utilities.ts} +22 -17
- package/dist/index.d.mts +0 -23
- package/src/errors.js +0 -11
- package/src/helpers/Helper.js +0 -29
- package/src/helpers/index.js +0 -100
- package/src/iife.js +0 -3
- package/src/index.mjs +0 -26
- package/src/processors/postprocessor.js +0 -49
- package/src/processors/preprocessor.js +0 -78
- /package/{manifest.json → src/manifest.json} +0 -0
@@ -1,22 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
import { atob, isJSAllowed } from "../utilities"
|
2
|
+
import cloneDeep from "lodash/fp/cloneDeep"
|
3
|
+
import { LITERAL_MARKER } from "../helpers/constants"
|
4
|
+
import { getJsHelperList } from "./list"
|
5
|
+
import { iifeWrapper } from "../iife"
|
6
6
|
|
7
7
|
// The method of executing JS scripts depends on the bundle being built.
|
8
8
|
// This setter is used in the entrypoint (either index.js or index.mjs).
|
9
|
-
let runJS
|
10
|
-
|
11
|
-
|
9
|
+
let runJS: ((js: string, context: any) => any) | undefined = undefined
|
10
|
+
export const setJSRunner = (runner: typeof runJS) => (runJS = runner)
|
11
|
+
|
12
|
+
export const removeJSRunner = () => {
|
12
13
|
runJS = undefined
|
13
14
|
}
|
14
15
|
|
15
|
-
let onErrorLog
|
16
|
-
|
16
|
+
let onErrorLog: (message: Error) => void
|
17
|
+
export const setOnErrorLog = (delegate: typeof onErrorLog) =>
|
18
|
+
(onErrorLog = delegate)
|
17
19
|
|
18
20
|
// Helper utility to strip square brackets from a value
|
19
|
-
const removeSquareBrackets = value => {
|
21
|
+
const removeSquareBrackets = (value: string) => {
|
20
22
|
if (!value || typeof value !== "string") {
|
21
23
|
return value
|
22
24
|
}
|
@@ -30,7 +32,7 @@ const removeSquareBrackets = value => {
|
|
30
32
|
|
31
33
|
// Our context getter function provided to JS code as $.
|
32
34
|
// Extracts a value from context.
|
33
|
-
const getContextValue = (path, context) => {
|
35
|
+
const getContextValue = (path: string, context: any) => {
|
34
36
|
let data = context
|
35
37
|
path.split(".").forEach(key => {
|
36
38
|
if (data == null || typeof data !== "object") {
|
@@ -42,8 +44,8 @@ const getContextValue = (path, context) => {
|
|
42
44
|
}
|
43
45
|
|
44
46
|
// Evaluates JS code against a certain context
|
45
|
-
|
46
|
-
if (!isJSAllowed() ||
|
47
|
+
export function processJS(handlebars: string, context: any) {
|
48
|
+
if (!isJSAllowed() || !runJS) {
|
47
49
|
throw new Error("JS disabled in environment.")
|
48
50
|
}
|
49
51
|
try {
|
@@ -53,8 +55,8 @@ module.exports.processJS = (handlebars, context) => {
|
|
53
55
|
|
54
56
|
// Transform snippets into an object for faster access, and cache previously
|
55
57
|
// evaluated snippets
|
56
|
-
let snippetMap = {}
|
57
|
-
let snippetCache = {}
|
58
|
+
let snippetMap: any = {}
|
59
|
+
let snippetCache: any = {}
|
58
60
|
for (let snippet of context.snippets || []) {
|
59
61
|
snippetMap[snippet.name] = snippet.code
|
60
62
|
}
|
@@ -64,7 +66,7 @@ module.exports.processJS = (handlebars, context) => {
|
|
64
66
|
// app context.
|
65
67
|
const clonedContext = cloneDeep({ ...context, snippets: null })
|
66
68
|
const sandboxContext = {
|
67
|
-
$: path => getContextValue(path, clonedContext),
|
69
|
+
$: (path: string) => getContextValue(path, clonedContext),
|
68
70
|
helpers: getJsHelperList(),
|
69
71
|
|
70
72
|
// Proxy to evaluate snippets when running in the browser
|
@@ -84,7 +86,7 @@ module.exports.processJS = (handlebars, context) => {
|
|
84
86
|
// Create a sandbox with our context and run the JS
|
85
87
|
const res = { data: runJS(js, sandboxContext) }
|
86
88
|
return `{{${LITERAL_MARKER} js_result-${JSON.stringify(res)}}}`
|
87
|
-
} catch (error) {
|
89
|
+
} catch (error: any) {
|
88
90
|
onErrorLog && onErrorLog(error)
|
89
91
|
|
90
92
|
if (error.code === "ERR_SCRIPT_EXECUTION_TIMEOUT") {
|
@@ -1,7 +1,7 @@
|
|
1
|
-
|
1
|
+
import { date, duration } from "./date"
|
2
2
|
|
3
3
|
// https://github.com/evanw/esbuild/issues/56
|
4
|
-
const
|
4
|
+
const getExternalCollections = (): Record<string, () => any> => ({
|
5
5
|
math: require("@budibase/handlebars-helpers/lib/math"),
|
6
6
|
array: require("@budibase/handlebars-helpers/lib/array"),
|
7
7
|
number: require("@budibase/handlebars-helpers/lib/number"),
|
@@ -11,32 +11,32 @@ const externalCollections = {
|
|
11
11
|
object: require("@budibase/handlebars-helpers/lib/object"),
|
12
12
|
regex: require("@budibase/handlebars-helpers/lib/regex"),
|
13
13
|
uuid: require("@budibase/handlebars-helpers/lib/uuid"),
|
14
|
-
}
|
14
|
+
})
|
15
15
|
|
16
|
-
const helpersToRemoveForJs = ["sortBy"]
|
17
|
-
module.exports.helpersToRemoveForJs = helpersToRemoveForJs
|
16
|
+
export const helpersToRemoveForJs = ["sortBy"]
|
18
17
|
|
19
18
|
const addedHelpers = {
|
20
19
|
date: date,
|
21
20
|
duration: duration,
|
22
21
|
}
|
23
22
|
|
24
|
-
let helpers
|
23
|
+
let helpers: Record<string, any>
|
25
24
|
|
26
|
-
|
25
|
+
export function getJsHelperList() {
|
27
26
|
if (helpers) {
|
28
27
|
return helpers
|
29
28
|
}
|
30
29
|
|
31
30
|
helpers = {}
|
32
|
-
for (let collection of Object.values(
|
31
|
+
for (let collection of Object.values(getExternalCollections())) {
|
33
32
|
for (let [key, func] of Object.entries(collection)) {
|
34
33
|
// Handlebars injects the hbs options to the helpers by default. We are adding an empty {} as a last parameter to simulate it
|
35
|
-
helpers[key] = (...props) => func(...props, {})
|
34
|
+
helpers[key] = (...props: any) => func(...props, {})
|
36
35
|
}
|
37
36
|
}
|
38
|
-
|
39
|
-
helpers
|
37
|
+
helpers = {
|
38
|
+
...helpers,
|
39
|
+
addedHelpers,
|
40
40
|
}
|
41
41
|
|
42
42
|
for (const toRemove of helpersToRemoveForJs) {
|
package/src/iife.ts
ADDED
@@ -1,24 +1,30 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
import { Context, createContext, runInNewContext } from "vm"
|
2
|
+
import { create } from "handlebars"
|
3
|
+
import { registerAll, registerMinimum } from "./helpers/index"
|
4
|
+
import { preprocess, postprocess } from "./processors"
|
5
|
+
import {
|
6
|
+
atob,
|
7
|
+
btoa,
|
8
|
+
isBackendService,
|
9
9
|
FIND_HBS_REGEX,
|
10
10
|
FIND_ANY_HBS_REGEX,
|
11
11
|
findDoubleHbsInstances,
|
12
|
-
}
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
} from "./utilities"
|
13
|
+
import { convertHBSBlock } from "./conversion"
|
14
|
+
import { setJSRunner, removeJSRunner } from "./helpers/javascript"
|
15
|
+
import { helpersToRemoveForJs } from "./helpers/list"
|
16
16
|
|
17
|
-
|
17
|
+
import manifest from "./manifest.json"
|
18
|
+
import { ProcessOptions } from "./types"
|
19
|
+
|
20
|
+
export { setJSRunner, setOnErrorLog } from "./helpers/javascript"
|
21
|
+
export { iifeWrapper } from "./iife"
|
22
|
+
|
23
|
+
const hbsInstance = create()
|
18
24
|
registerAll(hbsInstance)
|
19
|
-
const hbsInstanceNoHelpers =
|
25
|
+
const hbsInstanceNoHelpers = create()
|
20
26
|
registerMinimum(hbsInstanceNoHelpers)
|
21
|
-
const defaultOpts = {
|
27
|
+
const defaultOpts: ProcessOptions = {
|
22
28
|
noHelpers: false,
|
23
29
|
cacheTemplates: false,
|
24
30
|
noEscaping: false,
|
@@ -29,7 +35,7 @@ const defaultOpts = {
|
|
29
35
|
/**
|
30
36
|
* Utility function to check if the object is valid.
|
31
37
|
*/
|
32
|
-
function testObject(object) {
|
38
|
+
function testObject(object: any) {
|
33
39
|
// JSON stringify will fail if there are any cycles, stops infinite recursion
|
34
40
|
try {
|
35
41
|
JSON.stringify(object)
|
@@ -41,8 +47,8 @@ function testObject(object) {
|
|
41
47
|
/**
|
42
48
|
* Creates a HBS template function for a given string, and optionally caches it.
|
43
49
|
*/
|
44
|
-
|
45
|
-
function createTemplate(string, opts) {
|
50
|
+
const templateCache: Record<string, HandlebarsTemplateDelegate<any>> = {}
|
51
|
+
function createTemplate(string: string, opts?: ProcessOptions) {
|
46
52
|
opts = { ...defaultOpts, ...opts }
|
47
53
|
|
48
54
|
// Finalising adds a helper, can't do this with no helpers
|
@@ -53,11 +59,11 @@ function createTemplate(string, opts) {
|
|
53
59
|
return templateCache[key]
|
54
60
|
}
|
55
61
|
|
56
|
-
string =
|
62
|
+
string = preprocess(string, opts)
|
57
63
|
|
58
64
|
// Optionally disable built in HBS escaping
|
59
65
|
if (opts.noEscaping) {
|
60
|
-
string =
|
66
|
+
string = disableEscaping(string)
|
61
67
|
}
|
62
68
|
|
63
69
|
// This does not throw an error when template can't be fulfilled,
|
@@ -78,24 +84,25 @@ function createTemplate(string, opts) {
|
|
78
84
|
* @param {object|undefined} [opts] optional - specify some options for processing.
|
79
85
|
* @returns {Promise<object|array>} The structure input, as fully updated as possible.
|
80
86
|
*/
|
81
|
-
|
87
|
+
export async function processObject<T extends Record<string, any>>(
|
88
|
+
object: T,
|
89
|
+
context: object,
|
90
|
+
opts?: { noHelpers?: boolean; escapeNewlines?: boolean; onlyFound?: boolean }
|
91
|
+
): Promise<T> {
|
82
92
|
testObject(object)
|
83
|
-
|
93
|
+
|
94
|
+
for (const key of Object.keys(object || {})) {
|
84
95
|
if (object[key] != null) {
|
85
|
-
|
96
|
+
const val = object[key]
|
97
|
+
let parsedValue
|
86
98
|
if (typeof val === "string") {
|
87
|
-
|
88
|
-
object[key],
|
89
|
-
context,
|
90
|
-
opts
|
91
|
-
)
|
99
|
+
parsedValue = await processString(object[key], context, opts)
|
92
100
|
} else if (typeof val === "object") {
|
93
|
-
|
94
|
-
object[key],
|
95
|
-
context,
|
96
|
-
opts
|
97
|
-
)
|
101
|
+
parsedValue = await processObject(object[key], context, opts)
|
98
102
|
}
|
103
|
+
|
104
|
+
// @ts-ignore
|
105
|
+
object[key] = parsedValue
|
99
106
|
}
|
100
107
|
}
|
101
108
|
return object
|
@@ -109,9 +116,13 @@ module.exports.processObject = async (object, context, opts) => {
|
|
109
116
|
* @param {object|undefined} [opts] optional - specify some options for processing.
|
110
117
|
* @returns {Promise<string>} The enriched string, all templates should have been replaced if they can be.
|
111
118
|
*/
|
112
|
-
|
119
|
+
export async function processString(
|
120
|
+
string: string,
|
121
|
+
context: object,
|
122
|
+
opts?: ProcessOptions
|
123
|
+
): Promise<string> {
|
113
124
|
// TODO: carry out any async calls before carrying out async call
|
114
|
-
return
|
125
|
+
return processStringSync(string, context, opts)
|
115
126
|
}
|
116
127
|
|
117
128
|
/**
|
@@ -123,14 +134,18 @@ module.exports.processString = async (string, context, opts) => {
|
|
123
134
|
* @param {object|undefined} [opts] optional - specify some options for processing.
|
124
135
|
* @returns {object|array} The structure input, as fully updated as possible.
|
125
136
|
*/
|
126
|
-
|
137
|
+
export function processObjectSync(
|
138
|
+
object: { [x: string]: any },
|
139
|
+
context: any,
|
140
|
+
opts: any
|
141
|
+
): object | Array<any> {
|
127
142
|
testObject(object)
|
128
143
|
for (let key of Object.keys(object || {})) {
|
129
144
|
let val = object[key]
|
130
145
|
if (typeof val === "string") {
|
131
|
-
object[key] =
|
146
|
+
object[key] = processStringSync(object[key], context, opts)
|
132
147
|
} else if (typeof val === "object") {
|
133
|
-
object[key] =
|
148
|
+
object[key] = processObjectSync(object[key], context, opts)
|
134
149
|
}
|
135
150
|
}
|
136
151
|
return object
|
@@ -144,29 +159,32 @@ module.exports.processObjectSync = (object, context, opts) => {
|
|
144
159
|
* @param {object|undefined} [opts] optional - specify some options for processing.
|
145
160
|
* @returns {string} The enriched string, all templates should have been replaced if they can be.
|
146
161
|
*/
|
147
|
-
|
162
|
+
export function processStringSync(
|
163
|
+
string: string,
|
164
|
+
context?: object,
|
165
|
+
opts?: ProcessOptions
|
166
|
+
): string {
|
148
167
|
// Take a copy of input in case of error
|
149
168
|
const input = string
|
150
169
|
if (typeof string !== "string") {
|
151
170
|
throw "Cannot process non-string types."
|
152
171
|
}
|
153
|
-
function process(stringPart) {
|
172
|
+
function process(stringPart: string) {
|
154
173
|
const template = createTemplate(stringPart, opts)
|
155
174
|
const now = Math.floor(Date.now() / 1000) * 1000
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
)
|
175
|
+
const processedString = template({
|
176
|
+
now: new Date(now).toISOString(),
|
177
|
+
__opts: {
|
178
|
+
...opts,
|
179
|
+
input: stringPart,
|
180
|
+
},
|
181
|
+
...context,
|
182
|
+
})
|
183
|
+
return postprocess(processedString)
|
166
184
|
}
|
167
185
|
try {
|
168
186
|
if (opts && opts.onlyFound) {
|
169
|
-
const blocks =
|
187
|
+
const blocks = findHBSBlocks(string)
|
170
188
|
for (let block of blocks) {
|
171
189
|
const outcome = process(block)
|
172
190
|
string = string.replace(block, outcome)
|
@@ -186,7 +204,7 @@ module.exports.processStringSync = (string, context, opts) => {
|
|
186
204
|
* this function will find any double braces and switch to triple.
|
187
205
|
* @param string the string to have double HBS statements converted to triple.
|
188
206
|
*/
|
189
|
-
|
207
|
+
export function disableEscaping(string: string) {
|
190
208
|
const matches = findDoubleHbsInstances(string)
|
191
209
|
if (matches == null) {
|
192
210
|
return string
|
@@ -207,7 +225,7 @@ module.exports.disableEscaping = string => {
|
|
207
225
|
* @param {string} property The property which is to be wrapped.
|
208
226
|
* @returns {string} The wrapped property ready to be added to a templating string.
|
209
227
|
*/
|
210
|
-
|
228
|
+
export function makePropSafe(property: any): string {
|
211
229
|
return `[${property}]`.replace("[[", "[").replace("]]", "]")
|
212
230
|
}
|
213
231
|
|
@@ -217,7 +235,7 @@ module.exports.makePropSafe = property => {
|
|
217
235
|
* @param [opts] optional - specify some options for processing.
|
218
236
|
* @returns {boolean} Whether or not the input string is valid.
|
219
237
|
*/
|
220
|
-
|
238
|
+
export function isValid(string: any, opts?: any): boolean {
|
221
239
|
const validCases = [
|
222
240
|
"string",
|
223
241
|
"number",
|
@@ -238,7 +256,7 @@ module.exports.isValid = (string, opts) => {
|
|
238
256
|
})
|
239
257
|
template(context)
|
240
258
|
return true
|
241
|
-
} catch (err) {
|
259
|
+
} catch (err: any) {
|
242
260
|
const msg = err && err.message ? err.message : err
|
243
261
|
if (!msg) {
|
244
262
|
return false
|
@@ -259,7 +277,7 @@ module.exports.isValid = (string, opts) => {
|
|
259
277
|
* This manifest provides information about each of the helpers and how it can be used.
|
260
278
|
* @returns The manifest JSON which has been generated from the helpers.
|
261
279
|
*/
|
262
|
-
|
280
|
+
export function getManifest() {
|
263
281
|
return manifest
|
264
282
|
}
|
265
283
|
|
@@ -268,8 +286,8 @@ module.exports.getManifest = () => {
|
|
268
286
|
* @param handlebars the HBS expression to check
|
269
287
|
* @returns {boolean} whether the expression is JS or not
|
270
288
|
*/
|
271
|
-
|
272
|
-
return
|
289
|
+
export function isJSBinding(handlebars: any): boolean {
|
290
|
+
return decodeJSBinding(handlebars) != null
|
273
291
|
}
|
274
292
|
|
275
293
|
/**
|
@@ -277,7 +295,7 @@ module.exports.isJSBinding = handlebars => {
|
|
277
295
|
* @param javascript the JS code to encode
|
278
296
|
* @returns {string} the JS HBS expression
|
279
297
|
*/
|
280
|
-
|
298
|
+
export function encodeJSBinding(javascript: string): string {
|
281
299
|
return `{{ js "${btoa(javascript)}" }}`
|
282
300
|
}
|
283
301
|
|
@@ -286,7 +304,7 @@ module.exports.encodeJSBinding = javascript => {
|
|
286
304
|
* @param handlebars the JS HBS expression
|
287
305
|
* @returns {string|null} the raw JS code
|
288
306
|
*/
|
289
|
-
|
307
|
+
export function decodeJSBinding(handlebars: string): string | null {
|
290
308
|
if (!handlebars || typeof handlebars !== "string") {
|
291
309
|
return null
|
292
310
|
}
|
@@ -311,7 +329,7 @@ module.exports.decodeJSBinding = handlebars => {
|
|
311
329
|
* @param {string[]} strings The strings to look for.
|
312
330
|
* @returns {boolean} Will return true if all strings found in HBS statement.
|
313
331
|
*/
|
314
|
-
|
332
|
+
export function doesContainStrings(template: string, strings: any[]): boolean {
|
315
333
|
let regexp = new RegExp(FIND_HBS_REGEX)
|
316
334
|
let matches = template.match(regexp)
|
317
335
|
if (matches == null) {
|
@@ -319,8 +337,8 @@ module.exports.doesContainStrings = (template, strings) => {
|
|
319
337
|
}
|
320
338
|
for (let match of matches) {
|
321
339
|
let hbs = match
|
322
|
-
if (
|
323
|
-
hbs =
|
340
|
+
if (isJSBinding(match)) {
|
341
|
+
hbs = decodeJSBinding(match)!
|
324
342
|
}
|
325
343
|
let allFound = true
|
326
344
|
for (let string of strings) {
|
@@ -341,7 +359,7 @@ module.exports.doesContainStrings = (template, strings) => {
|
|
341
359
|
* @param {string} string The string to search within.
|
342
360
|
* @return {string[]} The found HBS blocks.
|
343
361
|
*/
|
344
|
-
|
362
|
+
export function findHBSBlocks(string: string): string[] {
|
345
363
|
if (!string || typeof string !== "string") {
|
346
364
|
return []
|
347
365
|
}
|
@@ -362,18 +380,15 @@ module.exports.findHBSBlocks = string => {
|
|
362
380
|
* @param {string} string The word or sentence to search for.
|
363
381
|
* @returns {boolean} The this return true if the string is found, false if not.
|
364
382
|
*/
|
365
|
-
|
366
|
-
return
|
383
|
+
export function doesContainString(template: any, string: any): boolean {
|
384
|
+
return doesContainStrings(template, [string])
|
367
385
|
}
|
368
386
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
module.exports.convertToJS = hbs => {
|
373
|
-
const blocks = exports.findHBSBlocks(hbs)
|
387
|
+
export function convertToJS(hbs: string) {
|
388
|
+
const blocks = findHBSBlocks(hbs)
|
374
389
|
let js = "return `",
|
375
|
-
prevBlock = null
|
376
|
-
const variables = {}
|
390
|
+
prevBlock: string | null = null
|
391
|
+
const variables: Record<string, any> = {}
|
377
392
|
if (blocks.length === 0) {
|
378
393
|
js += hbs
|
379
394
|
}
|
@@ -387,7 +402,7 @@ module.exports.convertToJS = hbs => {
|
|
387
402
|
prevBlock = block
|
388
403
|
const { variable, value } = convertHBSBlock(block, count++)
|
389
404
|
variables[variable] = value
|
390
|
-
js += `${stringPart
|
405
|
+
js += `${[stringPart]}\${${variable}}`
|
391
406
|
}
|
392
407
|
let varBlock = ""
|
393
408
|
for (let [variable, value] of Object.entries(variables)) {
|
@@ -397,34 +412,34 @@ module.exports.convertToJS = hbs => {
|
|
397
412
|
return `${varBlock}${js}`
|
398
413
|
}
|
399
414
|
|
400
|
-
|
415
|
+
const _FIND_ANY_HBS_REGEX = FIND_ANY_HBS_REGEX
|
416
|
+
export { _FIND_ANY_HBS_REGEX as FIND_ANY_HBS_REGEX }
|
401
417
|
|
402
|
-
|
403
|
-
// We cannot use dynamic exports, otherwise the typescript file will not be generating it
|
404
|
-
module.exports.JsErrorTimeout = errors.JsErrorTimeout
|
418
|
+
export { JsErrorTimeout } from "./errors"
|
405
419
|
|
406
|
-
|
420
|
+
const _helpersToRemoveForJs = helpersToRemoveForJs
|
421
|
+
export { _helpersToRemoveForJs as helpersToRemoveForJs }
|
407
422
|
|
408
423
|
function defaultJSSetup() {
|
409
424
|
if (!isBackendService()) {
|
410
425
|
/**
|
411
426
|
* Use polyfilled vm to run JS scripts in a browser Env
|
412
427
|
*/
|
413
|
-
|
428
|
+
setJSRunner((js: string, context: Context) => {
|
414
429
|
context = {
|
415
430
|
...context,
|
416
431
|
alert: undefined,
|
417
432
|
setInterval: undefined,
|
418
433
|
setTimeout: undefined,
|
419
434
|
}
|
420
|
-
|
421
|
-
return
|
435
|
+
createContext(context)
|
436
|
+
return runInNewContext(js, context, { timeout: 1000 })
|
422
437
|
})
|
423
438
|
} else {
|
424
|
-
|
439
|
+
removeJSRunner()
|
425
440
|
}
|
426
441
|
}
|
427
442
|
defaultJSSetup()
|
428
443
|
|
429
|
-
|
430
|
-
|
444
|
+
const _defaultJSSetup = defaultJSSetup
|
445
|
+
export { _defaultJSSetup as defaultJSSetup }
|
@@ -1,8 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
import { FIND_HBS_REGEX } from "../utilities"
|
2
|
+
import * as preprocessor from "./preprocessor"
|
3
|
+
import * as postprocessor from "./postprocessor"
|
4
|
+
import { ProcessOptions } from "../types"
|
4
5
|
|
5
|
-
function process(output, processors, opts) {
|
6
|
+
function process(output: string, processors: any[], opts?: ProcessOptions) {
|
6
7
|
for (let processor of processors) {
|
7
8
|
// if a literal statement has occurred stop
|
8
9
|
if (typeof output !== "string") {
|
@@ -21,7 +22,7 @@ function process(output, processors, opts) {
|
|
21
22
|
return output
|
22
23
|
}
|
23
24
|
|
24
|
-
|
25
|
+
export function preprocess(string: string, opts: ProcessOptions) {
|
25
26
|
let processors = preprocessor.processors
|
26
27
|
if (opts.noFinalise) {
|
27
28
|
processors = processors.filter(
|
@@ -30,7 +31,7 @@ module.exports.preprocess = (string, opts) => {
|
|
30
31
|
}
|
31
32
|
return process(string, processors, opts)
|
32
33
|
}
|
33
|
-
|
34
|
+
export function postprocess(string: string) {
|
34
35
|
let processors = postprocessor.processors
|
35
36
|
return process(string, processors)
|
36
37
|
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import { LITERAL_MARKER } from "../helpers/constants"
|
2
|
+
|
3
|
+
export const PostProcessorNames = {
|
4
|
+
CONVERT_LITERALS: "convert-literals",
|
5
|
+
}
|
6
|
+
|
7
|
+
/* eslint-disable no-unused-vars */
|
8
|
+
class Postprocessor {
|
9
|
+
name: string
|
10
|
+
private fn: any
|
11
|
+
|
12
|
+
constructor(name: string, fn: any) {
|
13
|
+
this.name = name
|
14
|
+
this.fn = fn
|
15
|
+
}
|
16
|
+
|
17
|
+
process(statement: any) {
|
18
|
+
return this.fn(statement)
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
export const processors = [
|
23
|
+
new Postprocessor(
|
24
|
+
PostProcessorNames.CONVERT_LITERALS,
|
25
|
+
(statement: string) => {
|
26
|
+
if (
|
27
|
+
typeof statement !== "string" ||
|
28
|
+
!statement.includes(LITERAL_MARKER)
|
29
|
+
) {
|
30
|
+
return statement
|
31
|
+
}
|
32
|
+
const splitMarkerIndex = statement.indexOf("-")
|
33
|
+
const type = statement.substring(12, splitMarkerIndex)
|
34
|
+
const value = statement.substring(
|
35
|
+
splitMarkerIndex + 1,
|
36
|
+
statement.length - 2
|
37
|
+
)
|
38
|
+
switch (type) {
|
39
|
+
case "string":
|
40
|
+
return value
|
41
|
+
case "number":
|
42
|
+
return parseFloat(value)
|
43
|
+
case "boolean":
|
44
|
+
return value === "true"
|
45
|
+
case "object":
|
46
|
+
return JSON.parse(value)
|
47
|
+
case "js_result":
|
48
|
+
// We use the literal helper to process the result of JS expressions
|
49
|
+
// as we want to be able to return any types.
|
50
|
+
// We wrap the value in an abject to be able to use undefined properly.
|
51
|
+
return JSON.parse(value).data
|
52
|
+
}
|
53
|
+
return value
|
54
|
+
}
|
55
|
+
),
|
56
|
+
]
|