{"version":3,"file":"browser.module.mjs","sources":["../src/storage.ts","../src/err.ts","../src/compile.ts","../src/compile-string.ts","../src/utils.ts","../src/config.ts","../src/parse.ts","../src/render.ts","../src/core.ts","../src/browser.ts"],"sourcesContent":["/**\n * Handles storage and accessing of values\n *\n * In this case, we use it to store compiled template functions\n * Indexed by their `name` or `filename`\n */\n\nexport class Cacher<T> {\n  constructor(private cache: Record<string, T>) {}\n  define(key: string, val: T): void {\n    this.cache[key] = val;\n  }\n  get(key: string): T {\n    return this.cache[key];\n  }\n  remove(key: string): void {\n    delete this.cache[key];\n  }\n  reset(): void {\n    this.cache = {};\n  }\n  load(cacheObj: Record<string, T>): void {\n    this.cache = { ...this.cache, ...cacheObj };\n  }\n}\n","export class EtaError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"Eta Error\";\n  }\n}\n\nexport class EtaParseError extends EtaError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"EtaParser Error\";\n  }\n}\n\nexport class EtaRuntimeError extends EtaError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"EtaRuntime Error\";\n  }\n}\n\nexport class EtaFileResolutionError extends EtaError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"EtaFileResolution Error\";\n  }\n}\n\nexport class EtaNameResolutionError extends EtaError {\n  constructor(message: string) {\n    super(message);\n    this.name = \"EtaNameResolution Error\";\n  }\n}\n\n/**\n * Throws an EtaError with a nicely formatted error and message showing where in the template the error occurred.\n */\n\nexport function ParseErr(message: string, str: string, indx: number): never {\n  const whitespace = str.slice(0, indx).split(/\\n/);\n\n  const lineNo = whitespace.length;\n  const colNo = whitespace[lineNo - 1].length + 1;\n  message += \" at line \" +\n    lineNo +\n    \" col \" +\n    colNo +\n    \":\\n\\n\" +\n    \"  \" +\n    str.split(/\\n/)[lineNo - 1] +\n    \"\\n\" +\n    \"  \" +\n    Array(colNo).join(\" \") +\n    \"^\";\n  throw new EtaParseError(message);\n}\n\nexport function RuntimeErr(\n  originalError: Error,\n  str: string,\n  lineNo: number,\n  path: string,\n): never {\n  // code gratefully taken from https://github.com/mde/ejs and adapted\n\n  const lines = str.split(\"\\n\");\n  const start = Math.max(lineNo - 3, 0);\n  const end = Math.min(lines.length, lineNo + 3);\n  const filename = path;\n  // Error context\n  const context = lines\n    .slice(start, end)\n    .map(function (line, i) {\n      const curr = i + start + 1;\n      return (curr == lineNo ? \" >> \" : \"    \") + curr + \"| \" + line;\n    })\n    .join(\"\\n\");\n\n  const header = filename\n    ? filename + \":\" + lineNo + \"\\n\"\n    : \"line \" + lineNo + \"\\n\";\n\n  const err = new EtaRuntimeError(\n    header + context + \"\\n\\n\" + originalError.message,\n  );\n\n  err.name = originalError.name; // the original name (e.g. ReferenceError) may be useful\n\n  throw err;\n}\n","import { EtaParseError } from \"./err.ts\";\n\n/* TYPES */\nimport type { Eta } from \"./core.ts\";\nimport type { EtaConfig, Options } from \"./config.ts\";\n\nexport type TemplateFunction = (\n  this: Eta,\n  data?: object,\n  options?: Partial<Options>,\n) => string;\n/* END TYPES */\n\n/* istanbul ignore next */\nconst AsyncFunction = async function () {}.constructor; // eslint-disable-line @typescript-eslint/no-empty-function\n\n/**\n * Takes a template string and returns a template function that can be called with (data, config)\n *\n * @param str - The template string\n * @param config - A custom configuration object (optional)\n */\n\nexport function compile(\n  this: Eta,\n  str: string,\n  options?: Partial<Options>,\n): TemplateFunction {\n  const config: EtaConfig = this.config;\n\n  /* ASYNC HANDLING */\n  // code gratefully taken from https://github.com/mde/ejs and adapted\n  const ctor = options && options.async\n    ? (AsyncFunction as FunctionConstructor)\n    : Function;\n  /* END ASYNC HANDLING */\n\n  try {\n    return new ctor(\n      config.varName,\n      \"options\",\n      this.compileToString.call(this, str, options),\n    ) as TemplateFunction; // eslint-disable-line no-new-func\n  } catch (e) {\n    if (e instanceof SyntaxError) {\n      throw new EtaParseError(\n        \"Bad template syntax\\n\\n\" +\n          e.message +\n          \"\\n\" +\n          Array(e.message.length + 1).join(\"=\") +\n          \"\\n\" +\n          this.compileToString.call(this, str, options) +\n          \"\\n\", // This will put an extra newline before the callstack for extra readability\n      );\n    } else {\n      throw e;\n    }\n  }\n}\n","/* TYPES */\n\nimport type { Options } from \"./config.ts\";\nimport type { AstObject } from \"./parse.ts\";\nimport type { Eta } from \"./core.ts\";\n\n/* END TYPES */\n\n/**\n * Compiles a template string to a function string. Most often users just use `compile()`, which calls `compileToString` and creates a new function using the result\n */\n\nexport function compileToString(\n  this: Eta,\n  str: string,\n  options?: Partial<Options>,\n): string {\n  const config = this.config;\n  const isAsync = options && options.async;\n\n  const compileBody = this.compileBody;\n\n  const buffer: Array<AstObject> = this.parse.call(this, str);\n\n  // note: when the include function passes through options, the only parameter that matters is the filepath parameter\n  let res = `${config.functionHeader}\nlet include = (template, data) => this.render(template, data, options);\nlet includeAsync = (template, data) => this.renderAsync(template, data, options);\n\nlet __eta = {res: \"\", e: this.config.escapeFunction, f: this.config.filterFunction${\n    config.debug\n      ? ', line: 1, templateStr: \"' +\n        str.replace(/\\\\|\"/g, \"\\\\$&\").replace(/\\r\\n|\\n|\\r/g, \"\\\\n\") +\n        '\"'\n      : \"\"\n  }};\n\nfunction layout(path, data) {\n  __eta.layout = path;\n  __eta.layoutData = data;\n}${config.debug ? \"try {\" : \"\"}${\n    config.useWith ? \"with(\" + config.varName + \"||{}){\" : \"\"\n  }\n\n${compileBody.call(this, buffer)}\nif (__eta.layout) {\n  __eta.res = ${\n    isAsync ? \"await includeAsync\" : \"include\"\n  } (__eta.layout, {...${config.varName}, body: __eta.res, ...__eta.layoutData});\n}\n${config.useWith ? \"}\" : \"\"}${\n    config.debug\n      ? \"} catch (e) { this.RuntimeErr(e, __eta.templateStr, __eta.line, options.filepath) }\"\n      : \"\"\n  }\nreturn __eta.res;\n`;\n\n  if (config.plugins) {\n    for (let i = 0; i < config.plugins.length; i++) {\n      const plugin = config.plugins[i];\n      if (plugin.processFnString) {\n        res = plugin.processFnString(res, config);\n      }\n    }\n  }\n\n  return res;\n}\n\n/**\n * Loops through the AST generated by `parse` and transform each item into JS calls\n *\n * **Example**\n *\n * ```js\n * let templateAST = ['Hi ', { val: 'it.name', t: 'i' }]\n * compileBody.call(Eta, templateAST)\n * // => \"__eta.res+='Hi '\\n__eta.res+=__eta.e(it.name)\\n\"\n * ```\n */\n\nexport function compileBody(this: Eta, buff: Array<AstObject>): string {\n  const config = this.config;\n\n  let i = 0;\n  const buffLength = buff.length;\n  let returnStr = \"\";\n\n  for (i; i < buffLength; i++) {\n    const currentBlock = buff[i];\n    if (typeof currentBlock === \"string\") {\n      const str = currentBlock;\n\n      // we know string exists\n      returnStr += \"__eta.res+='\" + str + \"'\\n\";\n    } else {\n      const type = currentBlock.t; // \"r\", \"e\", or \"i\"\n      let content = currentBlock.val || \"\";\n\n      if (config.debug) returnStr += \"__eta.line=\" + currentBlock.lineNo + \"\\n\";\n\n      if (type === \"r\") {\n        // raw\n\n        if (config.autoFilter) {\n          content = \"__eta.f(\" + content + \")\";\n        }\n\n        returnStr += \"__eta.res+=\" + content + \"\\n\";\n      } else if (type === \"i\") {\n        // interpolate\n\n        if (config.autoFilter) {\n          content = \"__eta.f(\" + content + \")\";\n        }\n\n        if (config.autoEscape) {\n          content = \"__eta.e(\" + content + \")\";\n        }\n\n        returnStr += \"__eta.res+=\" + content + \"\\n\";\n      } else if (type === \"e\") {\n        // execute\n        returnStr += content + \"\\n\";\n      }\n    }\n  }\n\n  return returnStr;\n}\n","import type { EtaConfig } from \"./config.ts\";\n\n/**\n * Takes a string within a template and trims it, based on the preceding tag's whitespace control and `config.autoTrim`\n */\n\nexport function trimWS(\n  str: string,\n  config: EtaConfig,\n  wsLeft: string | false,\n  wsRight?: string | false,\n): string {\n  let leftTrim;\n  let rightTrim;\n\n  if (Array.isArray(config.autoTrim)) {\n    // Slightly confusing,\n    // but _}} will trim the left side of the following string\n    leftTrim = config.autoTrim[1];\n    rightTrim = config.autoTrim[0];\n  } else {\n    leftTrim = rightTrim = config.autoTrim;\n  }\n\n  if (wsLeft || wsLeft === false) {\n    leftTrim = wsLeft;\n  }\n\n  if (wsRight || wsRight === false) {\n    rightTrim = wsRight;\n  }\n\n  if (!rightTrim && !leftTrim) {\n    return str;\n  }\n\n  if (leftTrim === \"slurp\" && rightTrim === \"slurp\") {\n    return str.trim();\n  }\n\n  if (leftTrim === \"_\" || leftTrim === \"slurp\") {\n    // full slurp\n    str = str.trimStart();\n  } else if (leftTrim === \"-\" || leftTrim === \"nl\") {\n    // nl trim\n    str = str.replace(/^(?:\\r\\n|\\n|\\r)/, \"\");\n  }\n\n  if (rightTrim === \"_\" || rightTrim === \"slurp\") {\n    // full slurp\n    str = str.trimEnd();\n  } else if (rightTrim === \"-\" || rightTrim === \"nl\") {\n    // nl trim\n    str = str.replace(/(?:\\r\\n|\\n|\\r)$/, \"\");\n  }\n\n  return str;\n}\n\n/**\n * A map of special HTML characters to their XML-escaped equivalents\n */\n\nconst escMap: { [key: string]: string } = {\n  \"&\": \"&amp;\",\n  \"<\": \"&lt;\",\n  \">\": \"&gt;\",\n  '\"': \"&quot;\",\n  \"'\": \"&#39;\",\n};\n\nfunction replaceChar(s: string): string {\n  return escMap[s];\n}\n\n/**\n * XML-escapes an input value after converting it to a string\n *\n * @param str - Input value (usually a string)\n * @returns XML-escaped string\n */\n\nexport function XMLEscape(str: unknown): string {\n  // To deal with XSS. Based on Escape implementations of Mustache.JS and Marko, then customized.\n  const newStr = String(str);\n  if (/[&<>\"']/.test(newStr)) {\n    return newStr.replace(/[&<>\"']/g, replaceChar);\n  } else {\n    return newStr;\n  }\n}\n","import { XMLEscape } from \"./utils.ts\";\n\n/* TYPES */\n\ntype trimConfig = \"nl\" | \"slurp\" | false;\n\nexport interface Options {\n  /** Compile to async function */\n  async?: boolean;\n\n  /** Absolute path to template file */\n  filepath?: string;\n}\n\nexport interface EtaConfig {\n  /** Whether or not to automatically XML-escape interpolations. Default true */\n  autoEscape: boolean;\n\n  /** Apply a filter function defined on the class to every interpolation or raw interpolation */\n  autoFilter: boolean;\n\n  /** Configure automatic whitespace trimming. Default `[false, 'nl']` */\n  autoTrim: trimConfig | [trimConfig, trimConfig];\n\n  /** Whether or not to cache templates if `name` or `filename` is passed */\n  cache: boolean;\n\n  /** Holds cache of resolved filepaths. Set to `false` to disable. */\n  cacheFilepaths: boolean;\n\n  /** Whether to pretty-format error messages (introduces runtime penalties) */\n  debug: boolean;\n\n  /** Function to XML-sanitize interpolations */\n  escapeFunction: (str: unknown) => string;\n\n  /** Function applied to all interpolations when autoFilter is true */\n  filterFunction: (val: unknown) => string;\n\n  /** Raw JS code inserted in the template function. Useful for declaring global variables for user templates */\n  functionHeader: string;\n\n  /** Parsing options */\n  parse: {\n    /** Which prefix to use for evaluation. Default `\"\"`, does not support `\"-\"` or `\"_\"` */\n    exec: string;\n\n    /** Which prefix to use for interpolation. Default `\"=\"`, does not support `\"-\"` or `\"_\"` */\n    interpolate: string;\n\n    /** Which prefix to use for raw interpolation. Default `\"~\"`, does not support `\"-\"` or `\"_\"` */\n    raw: string;\n  };\n\n  /** Array of plugins */\n  plugins: Array<\n    {\n      processFnString?: Function;\n      processAST?: Function;\n      processTemplate?: Function;\n    }\n  >;\n\n  /** Remove all safe-to-remove whitespace */\n  rmWhitespace: boolean;\n\n  /** Delimiters: by default `['<%', '%>']` */\n  tags: [string, string];\n\n  /** Make data available on the global object instead of varName */\n  useWith: boolean;\n\n  /** Name of the data object. Default `it` */\n  varName: string;\n\n  /** Directory that contains templates */\n  views?: string;\n\n  /** Control template file extension defaults. Default `.eta` */\n  defaultExtension?: string;\n}\n\n/* END TYPES */\n\n/** Eta's base (global) configuration */\nconst defaultConfig: EtaConfig = {\n  autoEscape: true,\n  autoFilter: false,\n  autoTrim: [false, \"nl\"],\n  cache: false,\n  cacheFilepaths: true,\n  debug: false,\n  escapeFunction: XMLEscape,\n  // default filter function (not used unless enables) just stringifies the input\n  filterFunction: (val) => String(val),\n  functionHeader: \"\",\n  parse: {\n    exec: \"\",\n    interpolate: \"=\",\n    raw: \"~\",\n  },\n  plugins: [],\n  rmWhitespace: false,\n  tags: [\"<%\", \"%>\"],\n  useWith: false,\n  varName: \"it\",\n  defaultExtension: \".eta\",\n};\n\nexport { defaultConfig };\n","import { ParseErr } from \"./err.ts\";\nimport { trimWS } from \"./utils.ts\";\n\n/* TYPES */\n\nimport type { Eta } from \"./core.ts\";\n\nexport type TagType = \"r\" | \"e\" | \"i\" | \"\";\n\nexport interface TemplateObject {\n  t: TagType;\n  val: string;\n  lineNo?: number;\n}\n\nexport type AstObject = string | TemplateObject;\n\n/* END TYPES */\n\nconst templateLitReg =\n  /`(?:\\\\[\\s\\S]|\\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})*}|(?!\\${)[^\\\\`])*`/g;\n\nconst singleQuoteReg = /'(?:\\\\[\\s\\w\"'\\\\`]|[^\\n\\r'\\\\])*?'/g;\n\nconst doubleQuoteReg = /\"(?:\\\\[\\s\\w\"'\\\\`]|[^\\n\\r\"\\\\])*?\"/g;\n\n/** Escape special regular expression characters inside a string */\n\nfunction escapeRegExp(string: string) {\n  // From MDN\n  return string.replace(/[.*+\\-?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\nfunction getLineNo(str: string, index: number) {\n  return str.slice(0, index).split(\"\\n\").length;\n}\n\nexport function parse(this: Eta, str: string): Array<AstObject> {\n  const config = this.config;\n\n  let buffer: Array<AstObject> = [];\n  let trimLeftOfNextStr: string | false = false;\n  let lastIndex = 0;\n  const parseOptions = config.parse;\n\n  if (config.plugins) {\n    for (let i = 0; i < config.plugins.length; i++) {\n      const plugin = config.plugins[i];\n      if (plugin.processTemplate) {\n        str = plugin.processTemplate(str, config);\n      }\n    }\n  }\n\n  /* Adding for EJS compatibility */\n  if (config.rmWhitespace) {\n    // Code taken directly from EJS\n    // Have to use two separate replaces here as `^` and `$` operators don't\n    // work well with `\\r` and empty lines don't work well with the `m` flag.\n    // Essentially, this replaces the whitespace at the beginning and end of\n    // each line and removes multiple newlines.\n    str = str.replace(/[\\r\\n]+/g, \"\\n\").replace(/^\\s+|\\s+$/gm, \"\");\n  }\n  /* End rmWhitespace option */\n\n  templateLitReg.lastIndex = 0;\n  singleQuoteReg.lastIndex = 0;\n  doubleQuoteReg.lastIndex = 0;\n\n  function pushString(strng: string, shouldTrimRightOfString?: string | false) {\n    if (strng) {\n      // if string is truthy it must be of type 'string'\n\n      strng = trimWS(\n        strng,\n        config,\n        trimLeftOfNextStr, // this will only be false on the first str, the next ones will be null or undefined\n        shouldTrimRightOfString,\n      );\n\n      if (strng) {\n        // replace \\ with \\\\, ' with \\'\n        // we're going to convert all CRLF to LF so it doesn't take more than one replace\n\n        strng = strng.replace(/\\\\|'/g, \"\\\\$&\").replace(/\\r\\n|\\n|\\r/g, \"\\\\n\");\n\n        buffer.push(strng);\n      }\n    }\n  }\n\n  const prefixes = [\n    parseOptions.exec,\n    parseOptions.interpolate,\n    parseOptions.raw,\n  ].reduce(function (\n    accumulator,\n    prefix,\n  ) {\n    if (accumulator && prefix) {\n      return accumulator + \"|\" + escapeRegExp(prefix);\n    } else if (prefix) {\n      // accumulator is falsy\n      return escapeRegExp(prefix);\n    } else {\n      // prefix and accumulator are both falsy\n      return accumulator;\n    }\n  }, \"\");\n\n  const parseOpenReg = new RegExp(\n    escapeRegExp(config.tags[0]) + \"(-|_)?\\\\s*(\" + prefixes + \")?\\\\s*\",\n    \"g\",\n  );\n\n  const parseCloseReg = new RegExp(\n    \"'|\\\"|`|\\\\/\\\\*|(\\\\s*(-|_)?\" + escapeRegExp(config.tags[1]) + \")\",\n    \"g\",\n  );\n\n  let m;\n\n  while ((m = parseOpenReg.exec(str))) {\n    const precedingString = str.slice(lastIndex, m.index);\n\n    lastIndex = m[0].length + m.index;\n\n    const wsLeft = m[1];\n    const prefix = m[2] || \"\"; // by default either ~, =, or empty\n\n    pushString(precedingString, wsLeft);\n\n    parseCloseReg.lastIndex = lastIndex;\n    let closeTag;\n    let currentObj: AstObject | false = false;\n\n    while ((closeTag = parseCloseReg.exec(str))) {\n      if (closeTag[1]) {\n        const content = str.slice(lastIndex, closeTag.index);\n\n        parseOpenReg.lastIndex = lastIndex = parseCloseReg.lastIndex;\n\n        trimLeftOfNextStr = closeTag[2];\n\n        const currentType: TagType = prefix === parseOptions.exec\n          ? \"e\"\n          : prefix === parseOptions.raw\n          ? \"r\"\n          : prefix === parseOptions.interpolate\n          ? \"i\"\n          : \"\";\n\n        currentObj = { t: currentType, val: content };\n        break;\n      } else {\n        const char = closeTag[0];\n        if (char === \"/*\") {\n          const commentCloseInd = str.indexOf(\"*/\", parseCloseReg.lastIndex);\n\n          if (commentCloseInd === -1) {\n            ParseErr(\"unclosed comment\", str, closeTag.index);\n          }\n          parseCloseReg.lastIndex = commentCloseInd;\n        } else if (char === \"'\") {\n          singleQuoteReg.lastIndex = closeTag.index;\n\n          const singleQuoteMatch = singleQuoteReg.exec(str);\n          if (singleQuoteMatch) {\n            parseCloseReg.lastIndex = singleQuoteReg.lastIndex;\n          } else {\n            ParseErr(\"unclosed string\", str, closeTag.index);\n          }\n        } else if (char === '\"') {\n          doubleQuoteReg.lastIndex = closeTag.index;\n          const doubleQuoteMatch = doubleQuoteReg.exec(str);\n\n          if (doubleQuoteMatch) {\n            parseCloseReg.lastIndex = doubleQuoteReg.lastIndex;\n          } else {\n            ParseErr(\"unclosed string\", str, closeTag.index);\n          }\n        } else if (char === \"`\") {\n          templateLitReg.lastIndex = closeTag.index;\n          const templateLitMatch = templateLitReg.exec(str);\n          if (templateLitMatch) {\n            parseCloseReg.lastIndex = templateLitReg.lastIndex;\n          } else {\n            ParseErr(\"unclosed string\", str, closeTag.index);\n          }\n        }\n      }\n    }\n    if (currentObj) {\n      if (config.debug) {\n        currentObj.lineNo = getLineNo(str, m.index);\n      }\n      buffer.push(currentObj);\n    } else {\n      ParseErr(\"unclosed tag\", str, m.index);\n    }\n  }\n\n  pushString(str.slice(lastIndex, str.length), false);\n\n  if (config.plugins) {\n    for (let i = 0; i < config.plugins.length; i++) {\n      const plugin = config.plugins[i];\n      if (plugin.processAST) {\n        buffer = plugin.processAST(buffer, config);\n      }\n    }\n  }\n\n  return buffer;\n}\n","import { EtaNameResolutionError } from \"./err.ts\";\n\n/* TYPES */\nimport type { Options } from \"./config.ts\";\nimport type { TemplateFunction } from \"./compile.ts\";\nimport type { Eta } from \"./core.ts\";\n/* END TYPES */\n\nfunction handleCache(\n  this: Eta,\n  template: string,\n  options: Partial<Options>,\n): TemplateFunction {\n  const templateStore = options && options.async\n    ? this.templatesAsync\n    : this.templatesSync;\n\n  if (this.resolvePath && this.readFile && !template.startsWith(\"@\")) {\n    const templatePath = options.filepath as string;\n\n    const cachedTemplate = templateStore.get(templatePath);\n\n    if (this.config.cache && cachedTemplate) {\n      return cachedTemplate;\n    } else {\n      const templateString = this.readFile(templatePath);\n\n      const templateFn = this.compile(templateString, options);\n\n      if (this.config.cache) templateStore.define(templatePath, templateFn);\n\n      return templateFn;\n    }\n  } else {\n    const cachedTemplate = templateStore.get(template);\n\n    if (cachedTemplate) {\n      return cachedTemplate;\n    } else {\n      throw new EtaNameResolutionError(\n        \"Failed to get template '\" + template + \"'\",\n      );\n    }\n  }\n}\n\nexport function render<T extends object>(\n  this: Eta,\n  template: string | TemplateFunction, // template name or template function\n  data: T,\n  meta?: { filepath: string },\n): string {\n  let templateFn: TemplateFunction;\n  const options = { ...meta, async: false };\n\n  if (typeof template === \"string\") {\n    if (this.resolvePath && this.readFile && !template.startsWith(\"@\")) {\n      options.filepath = this.resolvePath(template, options);\n    }\n\n    templateFn = handleCache.call(this, template, options);\n  } else {\n    templateFn = template;\n  }\n\n  const res = templateFn.call(this, data, options);\n\n  return res;\n}\n\nexport function renderAsync<T extends object>(\n  this: Eta,\n  template: string | TemplateFunction, // template name or template function\n  data: T,\n  meta?: { filepath: string },\n): Promise<string> {\n  let templateFn: TemplateFunction;\n  const options = { ...meta, async: true };\n\n  if (typeof template === \"string\") {\n    if (this.resolvePath && this.readFile && !template.startsWith(\"@\")) {\n      options.filepath = this.resolvePath(template, options);\n    }\n\n    templateFn = handleCache.call(this, template, options);\n  } else {\n    templateFn = template;\n  }\n\n  const res = templateFn.call(this, data, options);\n\n  // Return a promise\n  return Promise.resolve(res);\n}\n\nexport function renderString<T extends object>(\n  this: Eta,\n  template: string,\n  data: T,\n): string {\n  const templateFn = this.compile(template, { async: false });\n\n  return render.call(this, templateFn, data);\n}\n\nexport function renderStringAsync<T extends object>(\n  this: Eta,\n  template: string,\n  data: T,\n): Promise<string> {\n  const templateFn = this.compile(template, { async: true });\n\n  return renderAsync.call(this, templateFn, data);\n}\n","import { Cacher } from \"./storage.ts\";\nimport { compile } from \"./compile.ts\";\nimport { compileBody, compileToString } from \"./compile-string.ts\";\nimport { defaultConfig } from \"./config.ts\";\nimport { parse } from \"./parse.ts\";\nimport {\n  render,\n  renderAsync,\n  renderString,\n  renderStringAsync,\n} from \"./render.ts\";\nimport { EtaError, RuntimeErr } from \"./err.ts\";\nimport { TemplateFunction } from \"./compile.ts\";\n\n/* TYPES */\nimport type { EtaConfig, Options } from \"./config.ts\";\n/* END TYPES */\n\nexport class Eta {\n  constructor(customConfig?: Partial<EtaConfig>) {\n    if (customConfig) {\n      this.config = { ...defaultConfig, ...customConfig };\n    } else {\n      this.config = { ...defaultConfig };\n    }\n  }\n\n  config: EtaConfig;\n\n  RuntimeErr = RuntimeErr;\n\n  compile = compile;\n  compileToString = compileToString;\n  compileBody = compileBody;\n  parse = parse;\n  render = render;\n  renderAsync = renderAsync;\n  renderString = renderString;\n  renderStringAsync = renderStringAsync;\n\n  filepathCache: Record<string, string> = {};\n  templatesSync: Cacher<TemplateFunction> = new Cacher<TemplateFunction>({});\n  templatesAsync: Cacher<TemplateFunction> = new Cacher<TemplateFunction>({});\n\n  // resolvePath takes a relative path from the \"views\" directory\n  resolvePath:\n    | null\n    | ((this: Eta, template: string, options?: Partial<Options>) => string) =\n      null;\n  readFile: null | ((this: Eta, path: string) => string) = null;\n\n  // METHODS\n\n  configure(customConfig: Partial<EtaConfig>) {\n    this.config = { ...this.config, ...customConfig };\n  }\n\n  withConfig(customConfig: Partial<EtaConfig>): this & { config: EtaConfig } {\n    return { ...this, config: { ...this.config, ...customConfig } };\n  }\n\n  loadTemplate(\n    name: string,\n    template: string | TemplateFunction, // template string or template function\n    options?: { async: boolean },\n  ): void {\n    if (typeof template === \"string\") {\n      const templates = options && options.async\n        ? this.templatesAsync\n        : this.templatesSync;\n\n      templates.define(name, this.compile(template, options));\n    } else {\n      let templates = this.templatesSync;\n\n      if (\n        template.constructor.name === \"AsyncFunction\" ||\n        (options && options.async)\n      ) {\n        templates = this.templatesAsync;\n      }\n\n      templates.define(name, template);\n    }\n  }\n}\n\n// for instance checking against thrown errors\nexport { EtaError };\n","import { Eta as EtaCore } from \"./core.ts\";\n\nexport class Eta extends EtaCore {}\n"],"names":["Cacher","constructor","cache","this","define","key","val","get","remove","reset","load","cacheObj","_extends","EtaError","Error","message","super","name","EtaParseError","EtaRuntimeError","EtaNameResolutionError","ParseErr","str","indx","whitespace","slice","split","lineNo","length","colNo","Array","join","RuntimeErr","originalError","path","lines","start","Math","max","end","min","filename","context","map","line","i","curr","err","AsyncFunction","async","compile","options","config","ctor","Function","varName","compileToString","call","e","SyntaxError","isAsync","compileBody","buffer","parse","res","functionHeader","debug","replace","useWith","plugins","plugin","processFnString","buff","buffLength","returnStr","currentBlock","type","t","content","autoFilter","autoEscape","escMap","replaceChar","s","defaultConfig","autoTrim","cacheFilepaths","escapeFunction","newStr","String","test","filterFunction","exec","interpolate","raw","rmWhitespace","tags","defaultExtension","templateLitReg","singleQuoteReg","doubleQuoteReg","escapeRegExp","string","getLineNo","index","trimLeftOfNextStr","lastIndex","parseOptions","processTemplate","pushString","strng","shouldTrimRightOfString","wsLeft","wsRight","leftTrim","rightTrim","isArray","trim","trimStart","trimEnd","trimWS","push","prefixes","reduce","accumulator","prefix","parseOpenReg","RegExp","parseCloseReg","m","precedingString","closeTag","currentObj","char","commentCloseInd","indexOf","processAST","handleCache","template","templateStore","templatesAsync","templatesSync","resolvePath","readFile","startsWith","templatePath","filepath","cachedTemplate","templateString","templateFn","render","data","meta","renderAsync","Promise","resolve","renderString","renderStringAsync","Eta","customConfig","filepathCache","configure","withConfig","loadTemplate","templates","EtaCore"],"mappings":"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"}