@budibase/string-templates 3.2.5 → 3.2.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,37 +0,0 @@
1
- import { FIND_HBS_REGEX } from "../utilities"
2
- import * as preprocessor from "./preprocessor"
3
- import * as postprocessor from "./postprocessor"
4
- import { ProcessOptions } from "../types"
5
-
6
- function process(output: string, processors: any[], opts?: ProcessOptions) {
7
- for (let processor of processors) {
8
- // if a literal statement has occurred stop
9
- if (typeof output !== "string") {
10
- break
11
- }
12
- // re-run search each time incase previous processor updated/removed a match
13
- let regexp = new RegExp(FIND_HBS_REGEX)
14
- let matches = output.match(regexp)
15
- if (matches == null) {
16
- continue
17
- }
18
- for (let match of matches) {
19
- output = processor.process(output, match, opts)
20
- }
21
- }
22
- return output
23
- }
24
-
25
- export function preprocess(string: string, opts: ProcessOptions) {
26
- let processors = preprocessor.processors
27
- if (opts.noFinalise) {
28
- processors = processors.filter(
29
- processor => processor.name !== preprocessor.PreprocessorNames.FINALISE
30
- )
31
- }
32
-
33
- return process(string, processors, opts)
34
- }
35
- export function postprocess(string: string) {
36
- return process(string, postprocessor.processors)
37
- }
@@ -1,57 +0,0 @@
1
- import { LITERAL_MARKER } from "../helpers/constants"
2
-
3
- export enum PostProcessorNames {
4
- CONVERT_LITERALS = "convert-literals",
5
- }
6
-
7
- type PostprocessorFn = (statement: string) => string
8
-
9
- class Postprocessor {
10
- name: PostProcessorNames
11
- private readonly fn: PostprocessorFn
12
-
13
- constructor(name: PostProcessorNames, fn: PostprocessorFn) {
14
- this.name = name
15
- this.fn = fn
16
- }
17
-
18
- process(statement: string) {
19
- return this.fn(statement)
20
- }
21
- }
22
-
23
- export const processors = [
24
- new Postprocessor(
25
- PostProcessorNames.CONVERT_LITERALS,
26
- (statement: string) => {
27
- if (
28
- typeof statement !== "string" ||
29
- !statement.includes(LITERAL_MARKER)
30
- ) {
31
- return statement
32
- }
33
- const splitMarkerIndex = statement.indexOf("-")
34
- const type = statement.substring(12, splitMarkerIndex)
35
- const value = statement.substring(
36
- splitMarkerIndex + 1,
37
- statement.length - 2
38
- )
39
- switch (type) {
40
- case "string":
41
- return value
42
- case "number":
43
- return parseFloat(value)
44
- case "boolean":
45
- return value === "true"
46
- case "object":
47
- return JSON.parse(value)
48
- case "js_result":
49
- // We use the literal helper to process the result of JS expressions
50
- // as we want to be able to return any types.
51
- // We wrap the value in an abject to be able to use undefined properly.
52
- return JSON.parse(value).data
53
- }
54
- return value
55
- }
56
- ),
57
- ]
@@ -1,90 +0,0 @@
1
- import { HelperNames } from "../helpers"
2
- import { swapStrings, isAlphaNumeric } from "../utilities"
3
- import { ProcessOptions } from "../types"
4
-
5
- const FUNCTION_CASES = ["#", "else", "/"]
6
-
7
- export enum PreprocessorNames {
8
- SWAP_TO_DOT = "swap-to-dot-notation",
9
- FIX_FUNCTIONS = "fix-functions",
10
- FINALISE = "finalise",
11
- NORMALIZE_SPACES = "normalize-spaces",
12
- }
13
-
14
- type PreprocessorFn = (statement: string, opts?: ProcessOptions) => string
15
-
16
- class Preprocessor {
17
- name: string
18
- private readonly fn: PreprocessorFn
19
-
20
- constructor(name: PreprocessorNames, fn: PreprocessorFn) {
21
- this.name = name
22
- this.fn = fn
23
- }
24
-
25
- process(fullString: string, statement: string, opts: ProcessOptions) {
26
- const output = this.fn(statement, opts)
27
- const idx = fullString.indexOf(statement)
28
- return swapStrings(fullString, idx, statement.length, output)
29
- }
30
- }
31
-
32
- export const processors = [
33
- new Preprocessor(PreprocessorNames.SWAP_TO_DOT, (statement: string) => {
34
- let startBraceIdx = statement.indexOf("[")
35
- let lastIdx = 0
36
- while (startBraceIdx !== -1) {
37
- // if the character previous to the literal specifier is alphanumeric this should happen
38
- if (isAlphaNumeric(statement.charAt(startBraceIdx - 1))) {
39
- statement = swapStrings(statement, startBraceIdx + lastIdx, 1, ".[")
40
- }
41
- lastIdx = startBraceIdx + 1
42
- const nextBraceIdx = statement.substring(lastIdx + 1).indexOf("[")
43
- startBraceIdx = nextBraceIdx > 0 ? lastIdx + 1 + nextBraceIdx : -1
44
- }
45
- return statement
46
- }),
47
-
48
- new Preprocessor(PreprocessorNames.FIX_FUNCTIONS, (statement: string) => {
49
- for (let specialCase of FUNCTION_CASES) {
50
- const toFind = `{ ${specialCase}`,
51
- replacement = `{${specialCase}`
52
- statement = statement.replace(new RegExp(toFind, "g"), replacement)
53
- }
54
- return statement
55
- }),
56
-
57
- new Preprocessor(PreprocessorNames.NORMALIZE_SPACES, (statement: string) => {
58
- return statement.replace(/{{(\s{2,})/g, "{{ ")
59
- }),
60
- new Preprocessor(
61
- PreprocessorNames.FINALISE,
62
- (statement: string, opts?: ProcessOptions) => {
63
- const noHelpers = opts?.noHelpers
64
- const helpersEnabled = !noHelpers
65
- let insideStatement = statement.slice(2, statement.length - 2)
66
- if (insideStatement.charAt(0) === " ") {
67
- insideStatement = insideStatement.slice(1)
68
- }
69
- if (insideStatement.charAt(insideStatement.length - 1) === " ") {
70
- insideStatement = insideStatement.slice(0, insideStatement.length - 1)
71
- }
72
- const possibleHelper = insideStatement.split(" ")[0]
73
- // function helpers can't be wrapped
74
- for (let specialCase of FUNCTION_CASES) {
75
- if (possibleHelper.includes(specialCase)) {
76
- return statement
77
- }
78
- }
79
- const testHelper = possibleHelper.trim().toLowerCase()
80
- if (
81
- helpersEnabled &&
82
- !opts?.disabledHelpers?.includes(testHelper) &&
83
- HelperNames().some(option => testHelper === option.toLowerCase())
84
- ) {
85
- insideStatement = `(${insideStatement})`
86
- }
87
- return `{{ all ${insideStatement} }}`
88
- }
89
- ),
90
- ]
package/src/types.ts DELETED
@@ -1,10 +0,0 @@
1
- export interface ProcessOptions {
2
- cacheTemplates?: boolean
3
- noEscaping?: boolean
4
- noHelpers?: boolean
5
- noFinalise?: boolean
6
- noThrow?: boolean
7
- escapeNewlines?: boolean
8
- onlyFound?: boolean
9
- disabledHelpers?: string[]
10
- }
package/src/utilities.ts DELETED
@@ -1,88 +0,0 @@
1
- const ALPHA_NUMERIC_REGEX = /^[A-Za-z0-9]+$/g
2
-
3
- export const FIND_HBS_REGEX = /{{([^{].*?)}}/g
4
- export const FIND_ANY_HBS_REGEX = /{?{{([^{].*?)}}}?/g
5
- export const FIND_TRIPLE_HBS_REGEX = /{{{([^{].*?)}}}/g
6
-
7
- const isJest = () => typeof jest !== "undefined"
8
-
9
- export const isBackendService = () => {
10
- // We consider the tests for string-templates to be frontend, so that they
11
- // test the frontend JS functionality.
12
- if (isJest()) {
13
- return false
14
- }
15
- return typeof window === "undefined"
16
- }
17
-
18
- export const isJSAllowed = () => {
19
- return process && !process.env.NO_JS
20
- }
21
-
22
- // originally this could be done with a single regex using look behinds
23
- // but safari does not support this feature
24
- // original regex: /(?<!{){{[^{}]+}}(?!})/g
25
- export const findDoubleHbsInstances = (string: string): string[] => {
26
- let copied = string
27
- const doubleRegex = new RegExp(FIND_HBS_REGEX)
28
- const regex = new RegExp(FIND_TRIPLE_HBS_REGEX)
29
- const tripleMatches = copied.match(regex)
30
- // remove triple braces
31
- if (tripleMatches) {
32
- tripleMatches.forEach((match: string) => {
33
- copied = copied.replace(match, "")
34
- })
35
- }
36
- const doubleMatches = copied.match(doubleRegex)
37
- return doubleMatches ? doubleMatches : []
38
- }
39
-
40
- export const isAlphaNumeric = (char: string) => {
41
- return char.match(ALPHA_NUMERIC_REGEX)
42
- }
43
-
44
- export const swapStrings = (
45
- string: string,
46
- start: number,
47
- length: number,
48
- swap: string
49
- ) => {
50
- return string.slice(0, start) + swap + string.slice(start + length)
51
- }
52
-
53
- export const removeHandlebarsStatements = (
54
- string: string,
55
- replacement = "Invalid binding"
56
- ) => {
57
- let regexp = new RegExp(FIND_HBS_REGEX)
58
- let matches = string.match(regexp)
59
- if (matches == null) {
60
- return string
61
- }
62
- for (let match of matches) {
63
- const idx = string.indexOf(match)
64
- string = swapStrings(string, idx, match.length, replacement)
65
- }
66
- return string
67
- }
68
-
69
- export const btoa = (plainText: string) => {
70
- return Buffer.from(plainText, "utf-8").toString("base64")
71
- }
72
-
73
- export const atob = (base64: string) => {
74
- return Buffer.from(base64, "base64").toString("utf-8")
75
- }
76
-
77
- export const prefixStrings = (
78
- baseString: string,
79
- strings: string[],
80
- prefix: string
81
- ) => {
82
- // Escape any special characters in the strings to avoid regex errors
83
- const escapedStrings = strings.map(str =>
84
- str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
85
- )
86
- const regexPattern = new RegExp(`\\b(${escapedStrings.join("|")})\\b`, "g")
87
- return baseString.replace(regexPattern, `${prefix}$1`)
88
- }