'use strict';

const node_path = require('node:path');
const fsExtra = require('fs-extra');
const index = require('./shared/vue-email.f3ecad87.cjs');
const compiler = require('vue/compiler-sfc');
const vue = require('vue');
const serverRenderer = require('vue/server-renderer');
const scule = require('scule');
const vm = require('node:vm');
const node_module = require('node:module');
const esbuild = require('esbuild');
const crypto = require('crypto');
const node_url = require('node:url');
require('@flowko/tw-to-css');

function _interopNamespaceCompat(e) {
  if (e && typeof e === 'object' && 'default' in e) return e;
  const n = Object.create(null);
  if (e) {
    for (const k in e) {
      n[k] = e[k];
    }
  }
  n.default = e;
  return n;
}

const compiler__namespace = /*#__PURE__*/_interopNamespaceCompat(compiler);

function createInitConfig(options) {
  const config = index.deepmerge(
    {
      verbose: true,
      options: options.options
    },
    options
  );
  return config;
}

let enabled = true;
// Support both browser and node environments
const globalVar = typeof self !== 'undefined'
    ? self
    : typeof window !== 'undefined'
        ? window
        : typeof global !== 'undefined'
            ? global
            : {};
/**
 * Detect how much colors the current terminal supports
 */
let supportLevel = 0 /* none */;
if (globalVar.process && globalVar.process.env && globalVar.process.stdout) {
    const { FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, COLORTERM } = globalVar.process.env;
    if (NODE_DISABLE_COLORS || NO_COLOR || FORCE_COLOR === '0') {
        enabled = false;
    }
    else if (FORCE_COLOR === '1' ||
        FORCE_COLOR === '2' ||
        FORCE_COLOR === '3') {
        enabled = true;
    }
    else if (TERM === 'dumb') {
        enabled = false;
    }
    else if ('CI' in globalVar.process.env &&
        [
            'TRAVIS',
            'CIRCLECI',
            'APPVEYOR',
            'GITLAB_CI',
            'GITHUB_ACTIONS',
            'BUILDKITE',
            'DRONE',
        ].some(vendor => vendor in globalVar.process.env)) {
        enabled = true;
    }
    else {
        enabled = process.stdout.isTTY;
    }
    if (enabled) {
        // Windows supports 24bit True Colors since Windows 10 revision #14931,
        // see https://devblogs.microsoft.com/commandline/24-bit-color-in-the-windows-console/
        if (process.platform === 'win32') {
            supportLevel = 3 /* trueColor */;
        }
        else {
            if (COLORTERM && (COLORTERM === 'truecolor' || COLORTERM === '24bit')) {
                supportLevel = 3 /* trueColor */;
            }
            else if (TERM && (TERM.endsWith('-256color') || TERM.endsWith('256'))) {
                supportLevel = 2 /* ansi256 */;
            }
            else {
                supportLevel = 1 /* ansi */;
            }
        }
    }
}
let options = {
    enabled,
    supportLevel,
};
function kolorist(start, end, level = 1 /* ansi */) {
    const open = `\x1b[${start}m`;
    const close = `\x1b[${end}m`;
    const regex = new RegExp(`\\x1b\\[${end}m`, 'g');
    return (str) => {
        return options.enabled && options.supportLevel >= level
            ? open + ('' + str).replace(regex, open) + close
            : '' + str;
    };
}
const bold = kolorist(1, 22);
const red = kolorist(31, 39);
const blue = kolorist(34, 39);
const white = kolorist(97, 39);
const lightGreen = kolorist(92, 39);

const urlAlphabet =
  'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';

let random = bytes =>
  new Promise((resolve, reject) => {
    crypto.randomFill(Buffer.allocUnsafe(bytes), (err, buf) => {
      if (err) {
        reject(err);
      } else {
        resolve(buf);
      }
    });
  });
let nanoid = (size = 21) =>
  random(size).then(bytes => {
    let id = '';
    while (size--) {
      id += urlAlphabet[bytes[size] & 63];
    }
    return id
  });

function isInESModuleScope() {
  try {
    return module === void 0;
  } catch {
    return true;
  }
}
const FILE_URL_PROTOCOL = "file:";
const isFileURL = (value) => value.startsWith(FILE_URL_PROTOCOL);
function ensureFileURL(value) {
  return isFileURL(value) ? value : node_url.pathToFileURL(value).toString();
}
function ensurePath(value) {
  return isFileURL(value) ? node_url.fileURLToPath(value) : value;
}
const internalFunctionNames = ["getCallerDirname", "requireFromString", "importFromStringSync", "importFromString", "processTicksAndRejections"];
function getCallerDirname() {
  const __prepareStackTrace = Error.prepareStackTrace;
  Error.prepareStackTrace = (_err, stackTraces) => stackTraces;
  const callSites = new Error("error").stack.filter((callSite) => {
    const functionName = callSite.getFunctionName();
    return functionName === null || !internalFunctionNames.includes(functionName);
  });
  Error.prepareStackTrace = __prepareStackTrace;
  const caller = callSites[0];
  const callerFilename = caller.getFileName() ?? process.argv[1];
  return node_path.dirname(ensurePath(callerFilename));
}
function ensureTrailingSeparator(dirname2) {
  const separator = isFileURL(dirname2) ? "/" : node_path.sep;
  return dirname2.endsWith(separator) ? dirname2 : `${dirname2}${separator}`;
}
function getModuleFilename(dirname2, filename) {
  if (isInESModuleScope()) {
    if (isFileURL(filename)) {
      return filename;
    } else {
      const validatedDirname = ensureTrailingSeparator(dirname2);
      return new node_url.URL(filename, ensureFileURL(validatedDirname)).toString();
    }
  } else {
    return node_path.resolve(ensurePath(dirname2), ensurePath(filename));
  }
}
function forEachPropertyKey(context, callbackfn) {
  Object.getOwnPropertyNames(context).forEach(callbackfn);
  Object.getOwnPropertySymbols(context).forEach(callbackfn);
}
function shallowMergeContext(target, source) {
  forEachPropertyKey(source, (propertyKey) => {
    Object.defineProperty(target, propertyKey, {
      ...Object.getOwnPropertyDescriptor(source, propertyKey)
    });
  });
  return target;
}
const __GLOBAL__ = global;
function getCurrentGlobal() {
  const currentGlobal = shallowMergeContext({}, __GLOBAL__);
  delete currentGlobal.global;
  delete currentGlobal.globalThis;
  return currentGlobal;
}
function createGlobalObject(globals, useCurrentGlobal) {
  const globalObject = useCurrentGlobal ? getCurrentGlobal() : Object.defineProperty({}, Symbol.toStringTag, {
    ...Object.getOwnPropertyDescriptor(__GLOBAL__, Symbol.toStringTag)
  });
  forEachPropertyKey(globals, (propertyKey) => {
    if (propertyKey in __GLOBAL__) {
      Object.defineProperty(globalObject, propertyKey, {
        ...Object.getOwnPropertyDescriptor(__GLOBAL__, propertyKey),
        value: globals[propertyKey]
      });
    } else {
      Object.defineProperty(globalObject, propertyKey, {
        ...Object.getOwnPropertyDescriptor(globals, propertyKey)
      });
    }
  });
  return globalObject;
}
function createContextObject(moduleContext, globalObject) {
  const contextObject = shallowMergeContext(moduleContext, globalObject);
  if (!("global" in contextObject)) {
    contextObject.global = contextObject;
  }
  return contextObject;
}
function resolveModuleSpecifier(specifier, dirname2) {
  if (isFileURL(specifier)) {
    return specifier;
  }
  return specifier.startsWith(".") || node_path.isAbsolute(specifier) ? node_path.resolve(ensurePath(dirname2), specifier) : specifier;
}

const USE_STRICT = '"use strict";';
const IMPORT_META_URL_SHIM = 'var import_meta_url = require("url").pathToFileURL(__filename).toString();';
const IMPORT_META_RESOLVE_SHIM = `function import_meta_resolve() {
  throw new Error(
    \`'import.meta.resolve' is not supported
Use asynchronous function 'importFromString' and enable '--experimental-vm-modules' CLI option.
Or use 'transformOptions' to include a polyfill. See https://github.com/evanw/esbuild/issues/1492#issuecomment-893144483 as an example.\`
  );
}`;
function requireFromString(code, { filename = `${nanoid()}.js`, dirname = getCallerDirname(), globals = {}, useCurrentGlobal = false } = {}) {
  const moduleFilename = ensurePath(getModuleFilename(dirname, filename));
  const mainModule = isInESModuleScope() ? void 0 : require.main;
  const contextModule = new node_module.Module(moduleFilename, mainModule);
  contextModule.require = node_module.createRequire(moduleFilename);
  contextModule.filename = moduleFilename;
  contextModule.paths = mainModule?.paths ?? [];
  const globalObject = createGlobalObject(globals, useCurrentGlobal);
  const contextObject = createContextObject(
    {
      exports: contextModule.exports,
      require: contextModule.require,
      module: contextModule,
      __filename: contextModule.filename,
      __dirname: contextModule.path
    },
    globalObject
  );
  vm.runInNewContext(code, contextObject, {
    filename: moduleFilename,
    // @ts-expect-error: experimental
    async importModuleDynamically(specifier) {
      return await import(resolveModuleSpecifier(specifier, contextModule.path));
    }
  });
  contextModule.loaded = true;
  return contextModule.exports;
}
function getCommonJS(transformOptions) {
  return {
    ...transformOptions,
    banner: `${USE_STRICT}
${IMPORT_META_URL_SHIM}
${IMPORT_META_RESOLVE_SHIM}
${transformOptions?.banner ?? ""}`,
    define: {
      "import.meta.url": "import_meta_url",
      "import.meta.resolve": "import_meta_resolve",
      ...transformOptions?.define
    },
    format: "cjs"
  };
}
const ERR_REQUIRE_ESM = "ERR_REQUIRE_ESM";
function importFromStringSync(code, { transformOptions, ...options } = {}) {
  const { code: transformedCode } = esbuild.transformSync(code, getCommonJS(transformOptions));
  try {
    return requireFromString(transformedCode, options);
  } catch (error) {
    if (error != null && error.code === ERR_REQUIRE_ESM) {
      throw new Error(
        `'import' statement of ES modules is not supported
  Use asynchronous function 'importFromString' instead or replace it with dynamic 'import()' expression.`
      );
    }
    throw error;
  }
}

async function templateRender(name, code, options, config) {
  let vueI18n;
  const verbose = config?.verbose || false;
  const i18nOptions = {
    defaultLocale: options?.i18n?.defaultLocale || config?.options?.i18n?.defaultLocale || "en",
    translations: options?.i18n?.translations || config?.options?.i18n?.translations
  };
  const props = options?.props || config?.options?.props;
  const component = loadComponent(name, code.source, verbose);
  if (verbose) {
    console.warn(`${lightGreen("\u{1F48C}")} ${bold(blue("Generating output"))}`);
  }
  if (!component)
    throw new Error(`Component ${name} not found`);
  const app = vue.createApp(component, props);
  app.use(index.VueEmailPlugin, config?.options);
  app.config.performance = true;
  if (code.components && code.components.length) {
    for (const emailComponent of code.components) {
      const name2 = correctName(emailComponent.name);
      const componentCode = loadComponent(name2, emailComponent.source, verbose);
      if (componentCode)
        app.component(name2, {
          ...componentCode,
          components: index.components
        });
    }
  }
  if (i18nOptions) {
    try {
      vueI18n = await import('./chunks/vue-i18n.cjs');
    } catch (error) {
      throw new Error(`${lightGreen("\u274C")} ${bold(red(`Missing vue-i18n dependency`))} ${white("please install it using: ")} ${bold(white("npm i vue-i18n@9"))}`);
    }
    const locale = i18nOptions.defaultLocale;
    if (locale && vueI18n) {
      if (verbose) {
        console.warn(`${lightGreen("\u{1F30E}")} ${bold(blue("Injecting translations"))}`);
      }
      const i18n = vueI18n.createI18n({
        locale,
        fallbackLocale: i18nOptions.defaultLocale,
        messages: i18nOptions.translations,
        silentFallbackWarn: !verbose,
        silentTranslationWarn: !verbose,
        warnHtmlInMessage: "off"
      });
      app.use(i18n);
    }
  }
  if (verbose) {
    console.warn(`${lightGreen("\u{1F389}")} ${bold(blue("Rendering template"))} ${bold(lightGreen(name))}`);
  }
  const markup = await serverRenderer.renderToString(app);
  const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
  const doc = `${doctype}${index.cleanup(markup)}`;
  return doc;
}
function correctName(name) {
  return scule.pascalCase(name.replace(":", "-").replace(".vue", ""));
}
function loadComponent(name, source, verbose = false) {
  try {
    name = correctName(name);
    const compiledCompoennt = compile(name, source, verbose);
    const componentCode = importFromStringSync(compiledCompoennt, {
      transformOptions: { loader: "ts" }
    }).default;
    return componentCode;
  } catch (error) {
    console.error("Error loading component", error);
  }
  return null;
}
function compile(filename, source, verbose = false) {
  let styles = null;
  let script = null;
  const scriptIdentifier = "_sfc_main";
  if (verbose) {
    console.warn(`${lightGreen("\u{1F6A7}")} ${bold(blue("Compiling"))} ${bold(lightGreen(filename))} ${bold(blue("file"))}`);
  }
  const { descriptor, errors } = compiler__namespace.parse(source, {
    filename
  });
  if (errors.length) {
    throw new Error(errors.join("\n"));
  }
  if (descriptor.script || descriptor.scriptSetup)
    script = compiler__namespace.compileScript(descriptor, {
      id: descriptor.filename,
      genDefaultAs: scriptIdentifier
    });
  if (descriptor.styles && descriptor.styles.length)
    styles = compiler__namespace.compileStyle({
      id: descriptor.filename,
      filename,
      source: descriptor.styles[0].content,
      scoped: descriptor.styles.some((s) => s.scoped)
    });
  const template = compiler__namespace.compileTemplate({
    filename,
    id: descriptor.filename,
    source: descriptor.template.content,
    compilerOptions: script ? {
      bindingMetadata: script.bindings
    } : {}
  });
  const output = `
  ${template.code}

  ${script ? script.content : ""}
  ${styles ? `const styles = \`${styles.code}\`` : ""}
  ${script ? `${scriptIdentifier}.render = render` : `const ${scriptIdentifier} = { render }`}
  ${styles ? `${scriptIdentifier}.style = styles` : ""}
  ${scriptIdentifier}.__file = ${JSON.stringify(descriptor.filename)}
  ${script ? `export default ${scriptIdentifier}` : `export default { render }`}
  `;
  return output;
}

const config = (dir, config2 = {}) => {
  const defaultConfig = createInitConfig(config2);
  const components = getAllComponents(dir);
  return {
    render: (name, options) => {
      const path = dir ? node_path.resolve(dir, name) : name;
      const source = readFile(path);
      return templateRender(name, { source, components }, options, defaultConfig);
    }
  };
};
function readFile(path) {
  return fsExtra.readFileSync(path, "utf-8").toString();
}
function getAllComponents(emailsPath, basePath = "") {
  const result = [];
  const files = fsExtra.readdirSync(emailsPath);
  files.forEach((file) => {
    const filePath = node_path.join(emailsPath, file);
    const relativePath = node_path.join(basePath, file);
    if (fsExtra.statSync(filePath).isDirectory()) {
      result.push(...getAllComponents(filePath, relativePath));
    } else {
      result.push({
        name: relativePath.replace(/\\/g, ":"),
        source: readFile(filePath)
      });
    }
  });
  return result;
}

exports.config = config;
exports.templateRender = templateRender;
