utilities.ts
1 import { isTest, isTestingBackendJS } from "./environment" 2 3 const ALPHA_NUMERIC_REGEX = /^[A-Za-z0-9]+$/g 4 5 export const FIND_HBS_REGEX = /{{([^{].*?)}}/g 6 export const FIND_ANY_HBS_REGEX = /{?{{([^{].*?)}}}?/g 7 export const FIND_TRIPLE_HBS_REGEX = /{{{([^{].*?)}}}/g 8 9 export const isBackendService = () => { 10 // allow configuring backend JS mode when testing - we default to assuming 11 // frontend, but need a method to control this 12 if (isTest() && isTestingBackendJS()) { 13 return true 14 } 15 // We consider the tests for string-templates to be frontend, so that they 16 // test the frontend JS functionality. 17 if (isTest()) { 18 return false 19 } 20 return typeof window === "undefined" 21 } 22 23 export const isJSAllowed = () => { 24 return process && !process.env.NO_JS 25 } 26 27 // originally this could be done with a single regex using look behinds 28 // but safari does not support this feature 29 // original regex: /(?<!{){{[^{}]+}}(?!})/g 30 export const findDoubleHbsInstances = (string: string): string[] => { 31 let copied = string 32 const doubleRegex = new RegExp(FIND_HBS_REGEX) 33 const regex = new RegExp(FIND_TRIPLE_HBS_REGEX) 34 const tripleMatches = copied.match(regex) 35 // remove triple braces 36 if (tripleMatches) { 37 tripleMatches.forEach((match: string) => { 38 copied = copied.replace(match, "") 39 }) 40 } 41 const doubleMatches = copied.match(doubleRegex) 42 return doubleMatches ? doubleMatches : [] 43 } 44 45 export const isAlphaNumeric = (char: string) => { 46 return char.match(ALPHA_NUMERIC_REGEX) 47 } 48 49 export const swapStrings = ( 50 string: string, 51 start: number, 52 length: number, 53 swap: string 54 ) => { 55 return string.slice(0, start) + swap + string.slice(start + length) 56 } 57 58 export const removeHandlebarsStatements = ( 59 string: string, 60 replacement = "Invalid binding" 61 ) => { 62 let regexp = new RegExp(FIND_HBS_REGEX) 63 let matches = string.match(regexp) 64 if (matches == null) { 65 return string 66 } 67 for (let match of matches) { 68 const idx = string.indexOf(match) 69 string = swapStrings(string, idx, match.length, replacement) 70 } 71 return string 72 } 73 74 export const btoa = (plainText: string) => { 75 return Buffer.from(plainText, "utf-8").toString("base64") 76 } 77 78 export const atob = (base64: string) => { 79 return Buffer.from(base64, "base64").toString("utf-8") 80 } 81 82 export const prefixStrings = ( 83 baseString: string, 84 strings: string[], 85 prefix: string 86 ) => { 87 // Escape any special characters in the strings to avoid regex errors 88 const escapedStrings = strings.map(str => 89 str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") 90 ) 91 const regexPattern = new RegExp(`\\b(${escapedStrings.join("|")})\\b`, "g") 92 return baseString.replace(regexPattern, `${prefix}$1`) 93 } 94 95 export function frontendWrapJS(js: string) { 96 return ` 97 result = { 98 result: null, 99 error: null, 100 }; 101 102 try { 103 result.result = ${js}; 104 } catch (e) { 105 result.error = e; 106 } 107 108 result; 109 ` 110 }