@budibase/string-templates 3.2.4 → 3.2.6

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.
@@ -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
- }