/ packages / string-templates / src / utilities.ts
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  }