code:
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });

// src/constants/ansi-escape-codes.constants.ts
var ANSI_ESCAPE = "\x1B[";
var ANSI_ESCAPE_CODES = {
  CURSOR_HIDE: ANSI_ESCAPE + "?25l",
  CURSOR_SHOW: ANSI_ESCAPE + "?25h"
};

// src/constants/environment-variables.constants.ts
var ListrEnvironmentVariables = /* @__PURE__ */ ((ListrEnvironmentVariables2) => {
  ListrEnvironmentVariables2["FORCE_UNICODE"] = "LISTR_FORCE_UNICODE";
  ListrEnvironmentVariables2["FORCE_TTY"] = "LISTR_FORCE_TTY";
  ListrEnvironmentVariables2["DISABLE_COLOR"] = "NO_COLOR";
  ListrEnvironmentVariables2["FORCE_COLOR"] = "FORCE_COLOR";
  return ListrEnvironmentVariables2;
})(ListrEnvironmentVariables || {});

// src/constants/listr-error.constants.ts
var ListrErrorTypes = /* @__PURE__ */ ((ListrErrorTypes2) => {
  ListrErrorTypes2["WILL_RETRY"] = "WILL_RETRY";
  ListrErrorTypes2["WILL_ROLLBACK"] = "WILL_ROLLBACK";
  ListrErrorTypes2["HAS_FAILED_TO_ROLLBACK"] = "HAS_FAILED_TO_ROLLBACK";
  ListrErrorTypes2["HAS_FAILED"] = "HAS_FAILED";
  ListrErrorTypes2["HAS_FAILED_WITHOUT_ERROR"] = "HAS_FAILED_WITHOUT_ERROR";
  return ListrErrorTypes2;
})(ListrErrorTypes || {});

// src/constants/listr-events.constants.ts
var ListrEventType = /* @__PURE__ */ ((ListrEventType2) => {
  ListrEventType2["SHOULD_REFRESH_RENDER"] = "SHOUD_REFRESH_RENDER";
  return ListrEventType2;
})(ListrEventType || {});

// src/constants/listr-renderer.constants.ts
var ListrRendererSelection = /* @__PURE__ */ ((ListrRendererSelection2) => {
  ListrRendererSelection2["PRIMARY"] = "PRIMARY";
  ListrRendererSelection2["SECONDARY"] = "SECONDARY";
  ListrRendererSelection2["SILENT"] = "SILENT";
  return ListrRendererSelection2;
})(ListrRendererSelection || {});

// src/constants/listr-task-events.constants.ts
var ListrTaskEventType = /* @__PURE__ */ ((ListrTaskEventType2) => {
  ListrTaskEventType2["TITLE"] = "TITLE";
  ListrTaskEventType2["STATE"] = "STATE";
  ListrTaskEventType2["ENABLED"] = "ENABLED";
  ListrTaskEventType2["SUBTASK"] = "SUBTASK";
  ListrTaskEventType2["PROMPT"] = "PROMPT";
  ListrTaskEventType2["OUTPUT"] = "OUTPUT";
  ListrTaskEventType2["MESSAGE"] = "MESSAGE";
  ListrTaskEventType2["CLOSED"] = "CLOSED";
  return ListrTaskEventType2;
})(ListrTaskEventType || {});

// src/constants/listr-task-state.constants.ts
var ListrTaskState = /* @__PURE__ */ ((ListrTaskState2) => {
  ListrTaskState2["WAITING"] = "WAITING";
  ListrTaskState2["STARTED"] = "STARTED";
  ListrTaskState2["COMPLETED"] = "COMPLETED";
  ListrTaskState2["FAILED"] = "FAILED";
  ListrTaskState2["SKIPPED"] = "SKIPPED";
  ListrTaskState2["ROLLING_BACK"] = "ROLLING_BACK";
  ListrTaskState2["ROLLED_BACK"] = "ROLLED_BACK";
  ListrTaskState2["RETRY"] = "RETRY";
  ListrTaskState2["PAUSED"] = "PAUSED";
  ListrTaskState2["PROMPT"] = "PROMPT";
  ListrTaskState2["PROMPT_COMPLETED"] = "PROMPT_COMPLETED";
  ListrTaskState2["PROMPT_FAILED"] = "PROMPT_FAILED";
  return ListrTaskState2;
})(ListrTaskState || {});

// src/lib/event-manager.ts
import EventEmitter from "eventemitter3";
var EventManager = class {
  static {
    __name(this, "EventManager");
  }
  emitter = new EventEmitter();
  emit(dispatch, args) {
    this.emitter.emit(dispatch, args);
  }
  on(dispatch, handler) {
    this.emitter.addListener(dispatch, handler);
  }
  once(dispatch, handler) {
    this.emitter.once(dispatch, handler);
  }
  off(dispatch, handler) {
    this.emitter.off(dispatch, handler);
  }
  complete() {
    this.emitter.removeAllListeners();
  }
};

// src/interfaces/event.interface.ts
var BaseEventMap = class {
  static {
    __name(this, "BaseEventMap");
  }
};

// src/utils/environment/is-observable.ts
function isObservable(obj) {
  return !!obj && typeof obj === "object" && typeof obj.subscribe === "function";
}
__name(isObservable, "isObservable");

// src/utils/environment/is-readable.ts
function isReadable(obj) {
  return !!obj && typeof obj === "object" && obj.readable === true && typeof obj.read === "function" && typeof obj.on === "function";
}
__name(isReadable, "isReadable");

// src/utils/environment/is-unicode-supported.ts
function isUnicodeSupported() {
  return !!process.env["LISTR_FORCE_UNICODE" /* FORCE_UNICODE */] || process.platform !== "win32" || !!process.env.CI || !!process.env.WT_SESSION || process.env.TERM_PROGRAM === "vscode" || process.env.TERM === "xterm-256color" || process.env.TERM === "alacritty";
}
__name(isUnicodeSupported, "isUnicodeSupported");

// src/utils/format/cleanse-ansi.constants.ts
var CLEAR_LINE_REGEX = "(?:\\u001b|\\u009b)\\[[\\=><~/#&.:=?%@~_-]*[0-9]*[\\a-ln-tqyz=><~/#&.:=?%@~_-]+";
var BELL_REGEX = /\u0007/;

// src/utils/format/cleanse-ansi.ts
function cleanseAnsi(chunk) {
  return String(chunk).replace(new RegExp(CLEAR_LINE_REGEX, "gmi"), "").replace(new RegExp(BELL_REGEX, "gmi"), "").trim();
}
__name(cleanseAnsi, "cleanseAnsi");

// src/utils/format/color.ts
import { createColors } from "colorette";
var color = createColors();

// src/utils/format/indent.ts
function indent(string, count) {
  return string.replace(/^(?!\s*$)/gm, " ".repeat(count));
}
__name(indent, "indent");

// src/utils/format/figures.ts
var FIGURES_MAIN = {
  warning: "\u26A0",
  cross: "\u2716",
  arrowDown: "\u2193",
  tick: "\u2714",
  arrowRight: "\u2192",
  pointer: "\u276F",
  checkboxOn: "\u2612",
  arrowLeft: "\u2190",
  squareSmallFilled: "\u25FC",
  pointerSmall: "\u203A"
};
var FIGURES_FALLBACK = {
  ...FIGURES_MAIN,
  warning: "\u203C",
  cross: "\xD7",
  tick: "\u221A",
  pointer: ">",
  checkboxOn: "[\xD7]",
  squareSmallFilled: "\u25A0"
};
var figures = isUnicodeSupported() ? FIGURES_MAIN : FIGURES_FALLBACK;

// src/utils/format/splat.ts
import { format } from "util";
function splat(message, ...splat2) {
  return format(String(message), ...splat2);
}
__name(splat, "splat");

// src/utils/logger/logger.constants.ts
var ListrLogLevels = /* @__PURE__ */ ((ListrLogLevels2) => {
  ListrLogLevels2["STARTED"] = "STARTED";
  ListrLogLevels2["COMPLETED"] = "COMPLETED";
  ListrLogLevels2["FAILED"] = "FAILED";
  ListrLogLevels2["SKIPPED"] = "SKIPPED";
  ListrLogLevels2["OUTPUT"] = "OUTPUT";
  ListrLogLevels2["TITLE"] = "TITLE";
  ListrLogLevels2["ROLLBACK"] = "ROLLBACK";
  ListrLogLevels2["RETRY"] = "RETRY";
  ListrLogLevels2["PROMPT"] = "PROMPT";
  ListrLogLevels2["PAUSED"] = "PAUSED";
  return ListrLogLevels2;
})(ListrLogLevels || {});
var LISTR_LOGGER_STYLE = {
  icon: {
    ["STARTED" /* STARTED */]: figures.pointer,
    ["FAILED" /* FAILED */]: figures.cross,
    ["SKIPPED" /* SKIPPED */]: figures.arrowDown,
    ["COMPLETED" /* COMPLETED */]: figures.tick,
    ["OUTPUT" /* OUTPUT */]: figures.pointerSmall,
    ["TITLE" /* TITLE */]: figures.arrowRight,
    ["RETRY" /* RETRY */]: figures.warning,
    ["ROLLBACK" /* ROLLBACK */]: figures.arrowLeft,
    ["PAUSED" /* PAUSED */]: figures.squareSmallFilled
  },
  color: {
    ["STARTED" /* STARTED */]: color.yellow,
    ["FAILED" /* FAILED */]: color.red,
    ["SKIPPED" /* SKIPPED */]: color.yellow,
    ["COMPLETED" /* COMPLETED */]: color.green,
    ["RETRY" /* RETRY */]: color.yellowBright,
    ["ROLLBACK" /* ROLLBACK */]: color.redBright,
    ["PAUSED" /* PAUSED */]: color.yellowBright
  }
};
var LISTR_LOGGER_STDERR_LEVELS = ["RETRY" /* RETRY */, "ROLLBACK" /* ROLLBACK */, "FAILED" /* FAILED */];

// src/utils/logger/logger.ts
import { EOL } from "os";
var ListrLogger = class {
  constructor(options) {
    this.options = options;
    this.options = {
      useIcons: true,
      toStderr: [],
      ...options ?? {}
    };
    this.options.fields ??= {};
    this.options.fields.prefix ??= [];
    this.options.fields.suffix ??= [];
    this.process = this.options.processOutput ?? new ProcessOutput();
  }
  static {
    __name(this, "ListrLogger");
  }
  process;
  log(level, message, options) {
    const output = this.format(level, message, options);
    if (this.options.toStderr.includes(level)) {
      this.process.toStderr(output);
      return;
    }
    this.process.toStdout(output);
  }
  toStdout(message, options, eol = true) {
    this.process.toStdout(this.format(null, message, options), eol);
  }
  toStderr(message, options, eol = true) {
    this.process.toStderr(this.format(null, message, options), eol);
  }
  wrap(message, options) {
    if (!message) {
      return message;
    }
    return this.applyFormat(`[${message}]`, options);
  }
  splat(...args) {
    const message = args.shift() ?? "";
    return args.length === 0 ? message : splat(message, args);
  }
  suffix(message, ...suffixes) {
    suffixes.filter(Boolean).forEach((suffix) => {
      message += this.spacing(message);
      if (typeof suffix === "string") {
        message += this.wrap(suffix);
      } else if (typeof suffix === "object") {
        suffix.args ??= [];
        if (typeof suffix.condition === "function" ? !suffix.condition(...suffix.args) : !(suffix.condition ?? true)) {
          return message;
        }
        message += this.wrap(typeof suffix.field === "function" ? suffix.field(...suffix.args) : suffix.field, {
          format: suffix?.format(...suffix.args)
        });
      }
    });
    return message;
  }
  prefix(message, ...prefixes) {
    prefixes.filter(Boolean).forEach((prefix) => {
      message = this.spacing(message) + message;
      if (typeof prefix === "string") {
        message = this.wrap(prefix) + message;
      } else if (typeof prefix === "object") {
        prefix.args ??= [];
        if (typeof prefix.condition === "function" ? !prefix.condition(...prefix.args) : !(prefix.condition ?? true)) {
          return message;
        }
        message = this.wrap(typeof prefix.field === "function" ? prefix.field(...prefix.args) : prefix.field, {
          format: prefix?.format()
        }) + message;
      }
    });
    return message;
  }
  fields(message, options) {
    if (this.options?.fields?.prefix) {
      message = this.prefix(message, ...this.options.fields.prefix);
    }
    if (options?.prefix) {
      message = this.prefix(message, ...options.prefix);
    }
    if (options?.suffix) {
      message = this.suffix(message, ...options.suffix);
    }
    if (this.options?.fields?.suffix) {
      message = this.suffix(message, ...this.options.fields.suffix);
    }
    return message;
  }
  icon(level, icon) {
    if (!level) {
      return null;
    }
    icon ||= this.options.icon?.[level];
    const coloring = this.options.color?.[level];
    if (icon && coloring) {
      icon = coloring(icon);
    }
    return icon;
  }
  format(level, message, options) {
    if (!Array.isArray(message)) {
      message = [message];
    }
    message = this.splat(message.shift(), ...message).toString().split(EOL).filter((m) => !m || m.trim() !== "").map((m) => {
      return this.style(
        level,
        this.fields(m, {
          prefix: Array.isArray(options?.prefix) ? options.prefix : [options?.prefix],
          suffix: Array.isArray(options?.suffix) ? options.suffix : [options?.suffix]
        })
      );
    }).join(EOL);
    return message;
  }
  style(level, message) {
    if (!level || !message) {
      return message;
    }
    const icon = this.icon(level, !this.options.useIcons && this.wrap(level));
    if (icon) {
      message = icon + " " + message;
    }
    return message;
  }
  applyFormat(message, options) {
    if (options?.format) {
      return options.format(message);
    }
    return message;
  }
  spacing(message) {
    return typeof message === "undefined" || message.trim() === "" ? "" : " ";
  }
};

// src/utils/process-output/process-output-buffer.ts
import { StringDecoder } from "string_decoder";
var ProcessOutputBuffer = class {
  constructor(options) {
    this.options = options;
  }
  static {
    __name(this, "ProcessOutputBuffer");
  }
  buffer = [];
  decoder = new StringDecoder();
  get all() {
    return this.buffer;
  }
  get last() {
    return this.buffer.at(-1);
  }
  get length() {
    return this.buffer.length;
  }
  write(data, ...args) {
    const callback = args[args.length - 1];
    this.buffer.push({
      time: Date.now(),
      stream: this.options?.stream,
      entry: this.decoder.write(typeof data === "string" ? Buffer.from(data, typeof args[0] === "string" ? args[0] : void 0) : Buffer.from(data))
    });
    if (this.options?.limit) {
      this.buffer = this.buffer.slice(-this.options.limit);
    }
    if (typeof callback === "function") {
      callback();
    }
    return true;
  }
  reset() {
    this.buffer = [];
  }
};

// src/utils/process-output/process-output-stream.ts
var ProcessOutputStream = class {
  constructor(stream) {
    this.stream = stream;
    this.method = stream.write;
    this.buffer = new ProcessOutputBuffer({ stream });
  }
  static {
    __name(this, "ProcessOutputStream");
  }
  method;
  buffer;
  get out() {
    return Object.assign({}, this.stream, {
      write: this.write.bind(this)
    });
  }
  hijack() {
    this.stream.write = this.buffer.write.bind(this.buffer);
  }
  release() {
    this.stream.write = this.method;
    const buffer = [...this.buffer.all];
    this.buffer.reset();
    return buffer;
  }
  write(...args) {
    return this.method.apply(this.stream, args);
  }
};

// src/utils/process-output/process-output.ts
import { EOL as EOL2 } from "os";
var ProcessOutput = class {
  constructor(stdout, stderr, options) {
    this.options = options;
    this.stream = {
      stdout: new ProcessOutputStream(stdout ?? process.stdout),
      stderr: new ProcessOutputStream(stderr ?? process.stderr)
    };
    this.options = {
      dump: ["stdout", "stderr"],
      leaveEmptyLine: true,
      ...options
    };
  }
  static {
    __name(this, "ProcessOutput");
  }
  stream;
  active;
  get stdout() {
    return this.stream.stdout.out;
  }
  get stderr() {
    return this.stream.stderr.out;
  }
  hijack() {
    if (this.active) {
      throw new Error("ProcessOutput has been already hijacked!");
    }
    this.stream.stdout.write(ANSI_ESCAPE_CODES.CURSOR_HIDE);
    Object.values(this.stream).forEach((stream) => stream.hijack());
    this.active = true;
  }
  release() {
    const output = Object.entries(this.stream).map(([name, stream]) => ({ name, buffer: stream.release() })).filter((output2) => this.options.dump.includes(output2.name)).flatMap((output2) => output2.buffer).sort((a, b) => a.time - b.time).map((message) => {
      return {
        ...message,
        entry: cleanseAnsi(message.entry)
      };
    }).filter((message) => message.entry);
    if (output.length > 0) {
      if (this.options.leaveEmptyLine) {
        this.stdout.write(EOL2);
      }
      output.forEach((message) => {
        const stream = message.stream ?? this.stdout;
        stream.write(message.entry + EOL2);
      });
    }
    this.stream.stdout.write(ANSI_ESCAPE_CODES.CURSOR_SHOW);
    this.active = false;
  }
  toStdout(buffer, eol = true) {
    if (eol) {
      buffer = buffer + EOL2;
    }
    return this.stream.stdout.write(buffer);
  }
  toStderr(buffer, eol = true) {
    if (eol) {
      buffer = buffer + EOL2;
    }
    return this.stream.stderr.write(buffer);
  }
};

// src/utils/process-output/writable.ts
import { Writable } from "stream";
function createWritable(cb) {
  const writable = new Writable();
  writable.rows = Infinity;
  writable.columns = Infinity;
  writable.write = (chunk) => {
    cb(chunk.toString());
    return true;
  };
  return writable;
}
__name(createWritable, "createWritable");

// src/utils/prompts/adapter.ts
var ListrPromptAdapter = class {
  constructor(task, wrapper) {
    this.task = task;
    this.wrapper = wrapper;
  }
  static {
    __name(this, "ListrPromptAdapter");
  }
  state;
  reportStarted() {
    this.state = this.task.state;
    if (this.task.prompt) {
      throw new PromptError("There is already an active prompt attached to this task which may not be cleaned up properly.");
    }
    this.task.prompt = this;
    this.task.state$ = "PROMPT" /* PROMPT */;
  }
  reportFailed() {
    this.task.state$ = "PROMPT_FAILED" /* PROMPT_FAILED */;
    this.restoreState();
  }
  reportCompleted() {
    this.task.state$ = "PROMPT_COMPLETED" /* PROMPT_COMPLETED */;
    this.restoreState();
  }
  restoreState() {
    this.task.prompt = void 0;
    if (this.state) {
      this.task.state = this.state;
    }
  }
};

// src/utils/ui/spinner.ts
var Spinner = class {
  static {
    __name(this, "Spinner");
  }
  spinner = !isUnicodeSupported() ? ["-", "\\", "|", "/"] : ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
  id;
  spinnerPosition = 0;
  spin() {
    this.spinnerPosition = ++this.spinnerPosition % this.spinner.length;
  }
  fetch() {
    return this.spinner[this.spinnerPosition];
  }
  isRunning() {
    return !!this.id;
  }
  start(cb, interval = 100) {
    this.id = setInterval(() => {
      this.spin();
      if (cb) {
        cb();
      }
    }, interval);
  }
  stop() {
    clearInterval(this.id);
  }
};

// src/renderer/default/renderer.constants.ts
var ListrDefaultRendererLogLevels = /* @__PURE__ */ ((ListrDefaultRendererLogLevels2) => {
  ListrDefaultRendererLogLevels2["SKIPPED_WITH_COLLAPSE"] = "SKIPPED_WITH_COLLAPSE";
  ListrDefaultRendererLogLevels2["SKIPPED_WITHOUT_COLLAPSE"] = "SKIPPED_WITHOUT_COLLAPSE";
  ListrDefaultRendererLogLevels2["OUTPUT"] = "OUTPUT";
  ListrDefaultRendererLogLevels2["OUTPUT_WITH_BOTTOMBAR"] = "OUTPUT_WITH_BOTTOMBAR";
  ListrDefaultRendererLogLevels2["PENDING"] = "PENDING";
  ListrDefaultRendererLogLevels2["COMPLETED"] = "COMPLETED";
  ListrDefaultRendererLogLevels2["COMPLETED_WITH_FAILED_SUBTASKS"] = "COMPLETED_WITH_FAILED_SUBTASKS";
  ListrDefaultRendererLogLevels2["COMPLETED_WITH_FAILED_SISTER_TASKS"] = "COMPLETED_WITH_SISTER_TASKS_FAILED";
  ListrDefaultRendererLogLevels2["RETRY"] = "RETRY";
  ListrDefaultRendererLogLevels2["ROLLING_BACK"] = "ROLLING_BACK";
  ListrDefaultRendererLogLevels2["ROLLED_BACK"] = "ROLLED_BACK";
  ListrDefaultRendererLogLevels2["FAILED"] = "FAILED";
  ListrDefaultRendererLogLevels2["FAILED_WITH_FAILED_SUBTASKS"] = "FAILED_WITH_SUBTASKS";
  ListrDefaultRendererLogLevels2["WAITING"] = "WAITING";
  ListrDefaultRendererLogLevels2["PAUSED"] = "PAUSED";
  return ListrDefaultRendererLogLevels2;
})(ListrDefaultRendererLogLevels || {});
var LISTR_DEFAULT_RENDERER_STYLE = {
  icon: {
    ["SKIPPED_WITH_COLLAPSE" /* SKIPPED_WITH_COLLAPSE */]: figures.arrowDown,
    ["SKIPPED_WITHOUT_COLLAPSE" /* SKIPPED_WITHOUT_COLLAPSE */]: figures.warning,
    ["OUTPUT" /* OUTPUT */]: figures.pointerSmall,
    ["OUTPUT_WITH_BOTTOMBAR" /* OUTPUT_WITH_BOTTOMBAR */]: figures.pointerSmall,
    ["PENDING" /* PENDING */]: figures.pointer,
    ["COMPLETED" /* COMPLETED */]: figures.tick,
    ["COMPLETED_WITH_FAILED_SUBTASKS" /* COMPLETED_WITH_FAILED_SUBTASKS */]: figures.warning,
    ["COMPLETED_WITH_SISTER_TASKS_FAILED" /* COMPLETED_WITH_FAILED_SISTER_TASKS */]: figures.squareSmallFilled,
    ["RETRY" /* RETRY */]: figures.warning,
    ["ROLLING_BACK" /* ROLLING_BACK */]: figures.warning,
    ["ROLLED_BACK" /* ROLLED_BACK */]: figures.arrowLeft,
    ["FAILED" /* FAILED */]: figures.cross,
    ["FAILED_WITH_SUBTASKS" /* FAILED_WITH_FAILED_SUBTASKS */]: figures.pointer,
    ["WAITING" /* WAITING */]: figures.squareSmallFilled,
    ["PAUSED" /* PAUSED */]: figures.squareSmallFilled
  },
  color: {
    ["SKIPPED_WITH_COLLAPSE" /* SKIPPED_WITH_COLLAPSE */]: color.yellow,
    ["SKIPPED_WITHOUT_COLLAPSE" /* SKIPPED_WITHOUT_COLLAPSE */]: color.yellow,
    ["PENDING" /* PENDING */]: color.yellow,
    ["COMPLETED" /* COMPLETED */]: color.green,
    ["COMPLETED_WITH_FAILED_SUBTASKS" /* COMPLETED_WITH_FAILED_SUBTASKS */]: color.yellow,
    ["COMPLETED_WITH_SISTER_TASKS_FAILED" /* COMPLETED_WITH_FAILED_SISTER_TASKS */]: color.red,
    ["RETRY" /* RETRY */]: color.yellowBright,
    ["ROLLING_BACK" /* ROLLING_BACK */]: color.redBright,
    ["ROLLED_BACK" /* ROLLED_BACK */]: color.redBright,
    ["FAILED" /* FAILED */]: color.red,
    ["FAILED_WITH_SUBTASKS" /* FAILED_WITH_FAILED_SUBTASKS */]: color.red,
    ["WAITING" /* WAITING */]: color.dim,
    ["PAUSED" /* PAUSED */]: color.yellowBright
  }
};

// src/renderer/default/renderer.ts
import { EOL as EOL3 } from "os";

// src/presets/timer/parser.ts
function parseTimer(duration) {
  const seconds = Math.floor(duration / 1e3);
  const minutes = Math.floor(seconds / 60);
  let parsedTime;
  if (seconds === 0 && minutes === 0) {
    parsedTime = `0.${Math.floor(duration / 100)}s`;
  }
  if (seconds > 0) {
    parsedTime = `${seconds % 60}s`;
  }
  if (minutes > 0) {
    parsedTime = `${minutes}m${parsedTime}`;
  }
  return parsedTime;
}
__name(parseTimer, "parseTimer");

// src/presets/timer/preset.ts
var PRESET_TIMER = {
  condition: true,
  field: parseTimer,
  format: /* @__PURE__ */ __name(() => color.dim, "format")
};

// src/presets/timestamp/parser.ts
function parseTimestamp() {
  const now = /* @__PURE__ */ new Date();
  return String(now.getHours()).padStart(2, "0") + ":" + String(now.getMinutes()).padStart(2, "0") + ":" + String(now.getSeconds()).padStart(2, "0");
}
__name(parseTimestamp, "parseTimestamp");

// src/presets/timestamp/preset.ts
var PRESET_TIMESTAMP = {
  condition: true,
  field: parseTimestamp,
  format: /* @__PURE__ */ __name(() => color.dim, "format")
};

// src/renderer/default/renderer.ts
var DefaultRenderer = class _DefaultRenderer {
  constructor(tasks, options, events) {
    this.tasks = tasks;
    this.options = options;
    this.events = events;
    this.options = {
      ..._DefaultRenderer.rendererOptions,
      ...this.options,
      icon: {
        ...LISTR_DEFAULT_RENDERER_STYLE.icon,
        ...options?.icon ?? {}
      },
      color: {
        ...LISTR_DEFAULT_RENDERER_STYLE.color,
        ...options?.color ?? {}
      }
    };
    this.spinner = this.options.spinner ?? new Spinner();
    this.logger = this.options.logger ?? new ListrLogger({ useIcons: true, toStderr: [] });
    this.logger.options.icon = this.options.icon;
    this.logger.options.color = this.options.color;
  }
  static {
    __name(this, "DefaultRenderer");
  }
  static nonTTY = false;
  static rendererOptions = {
    indentation: 2,
    clearOutput: false,
    showSubtasks: true,
    collapseSubtasks: true,
    collapseSkips: true,
    showSkipMessage: true,
    suffixSkips: false,
    collapseErrors: true,
    showErrorMessage: true,
    suffixRetries: true,
    lazy: false,
    removeEmptyLines: true,
    formatOutput: "wrap",
    pausedTimer: {
      ...PRESET_TIMER,
      format: /* @__PURE__ */ __name(() => color.yellowBright, "format")
    }
  };
  static rendererTaskOptions = {
    outputBar: true
  };
  prompt;
  activePrompt;
  spinner;
  logger;
  updater;
  truncate;
  wrap;
  buffer = {
    output: /* @__PURE__ */ new Map(),
    bottom: /* @__PURE__ */ new Map()
  };
  cache = {
    render: /* @__PURE__ */ new Map(),
    rendererOptions: /* @__PURE__ */ new Map(),
    rendererTaskOptions: /* @__PURE__ */ new Map()
  };
  async render() {
    const { createLogUpdate } = await import("log-update");
    const { default: truncate } = await import("cli-truncate");
    const { default: wrap } = await import("wrap-ansi");
    this.updater = createLogUpdate(this.logger.process.stdout);
    this.truncate = truncate;
    this.wrap = wrap;
    this.logger.process.hijack();
    if (!this.options?.lazy) {
      this.spinner.start(() => {
        this.update();
      });
    }
    this.events.on("SHOUD_REFRESH_RENDER" /* SHOULD_REFRESH_RENDER */, () => {
      this.update();
    });
  }
  update() {
    this.updater(this.create());
  }
  end() {
    this.spinner.stop();
    this.updater.clear();
    this.updater.done();
    if (!this.options.clearOutput) {
      this.logger.process.toStdout(this.create({ prompt: false }));
    }
    this.logger.process.release();
  }
  create(options) {
    options = {
      tasks: true,
      bottomBar: true,
      prompt: true,
      ...options
    };
    const render = [];
    const renderTasks = this.renderer(this.tasks);
    const renderBottomBar = this.renderBottomBar();
    const renderPrompt = this.renderPrompt();
    if (options.tasks && renderTasks.length > 0) {
      render.push(...renderTasks);
    }
    if (options.bottomBar && renderBottomBar.length > 0) {
      if (render.length > 0) {
        render.push("");
      }
      render.push(...renderBottomBar);
    }
    if (options.prompt && renderPrompt.length > 0) {
      if (render.length > 0) {
        render.push("");
      }
      render.push(...renderPrompt);
    }
    return render.join(EOL3);
  }
  // eslint-disable-next-line complexity
  style(task, output = false) {
    const rendererOptions = this.cache.rendererOptions.get(task.id);
    if (task.isSkipped()) {
      if (output || rendererOptions.collapseSkips) {
        return this.logger.icon("SKIPPED_WITH_COLLAPSE" /* SKIPPED_WITH_COLLAPSE */);
      } else if (rendererOptions.collapseSkips === false) {
        return this.logger.icon("SKIPPED_WITHOUT_COLLAPSE" /* SKIPPED_WITHOUT_COLLAPSE */);
      }
    }
    if (output) {
      if (this.shouldOutputToBottomBar(task)) {
        return this.logger.icon("OUTPUT_WITH_BOTTOMBAR" /* OUTPUT_WITH_BOTTOMBAR */);
      }
      return this.logger.icon("OUTPUT" /* OUTPUT */);
    }
    if (task.hasSubtasks()) {
      if (task.isStarted() || task.isPrompt() && rendererOptions.showSubtasks !== false && !task.subtasks.every((subtask) => !subtask.hasTitle())) {
        return this.logger.icon("PENDING" /* PENDING */);
      } else if (task.isCompleted() && task.subtasks.some((subtask) => subtask.hasFailed())) {
        return this.logger.icon("COMPLETED_WITH_FAILED_SUBTASKS" /* COMPLETED_WITH_FAILED_SUBTASKS */);
      } else if (task.hasFailed()) {
        return this.logger.icon("FAILED_WITH_SUBTASKS" /* FAILED_WITH_FAILED_SUBTASKS */);
      }
    }
    if (task.isStarted() || task.isPrompt()) {
      return this.logger.icon("PENDING" /* PENDING */, !this.options?.lazy && this.spinner.fetch());
    } else if (task.isCompleted()) {
      return this.logger.icon("COMPLETED" /* COMPLETED */);
    } else if (task.isRetrying()) {
      return this.logger.icon("RETRY" /* RETRY */, !this.options?.lazy && this.spinner.fetch());
    } else if (task.isRollingBack()) {
      return this.logger.icon("ROLLING_BACK" /* ROLLING_BACK */, !this.options?.lazy && this.spinner.fetch());
    } else if (task.hasRolledBack()) {
      return this.logger.icon("ROLLED_BACK" /* ROLLED_BACK */);
    } else if (task.hasFailed()) {
      return this.logger.icon("FAILED" /* FAILED */);
    } else if (task.isPaused()) {
      return this.logger.icon("PAUSED" /* PAUSED */);
    }
    return this.logger.icon("WAITING" /* WAITING */);
  }
  format(message, icon, level) {
    if (message.trim() === "") {
      return [];
    }
    if (icon) {
      message = icon + " " + message;
    }
    let parsed;
    const columns = (process.stdout.columns ?? 80) - level * this.options.indentation - 2;
    switch (this.options.formatOutput) {
      case "truncate":
        parsed = message.split(EOL3).map((s, i) => {
          return this.truncate(this.indent(s, i), columns);
        });
        break;
      case "wrap":
        parsed = this.wrap(message, columns, { hard: true }).split(EOL3).map((s, i) => this.indent(s, i));
        break;
      default:
        throw new ListrRendererError("Format option for the renderer is wrong.");
    }
    if (this.options.removeEmptyLines) {
      parsed = parsed.filter(Boolean);
    }
    return parsed.map((str) => indent(str, level * this.options.indentation));
  }
  shouldOutputToOutputBar(task) {
    const outputBar = this.cache.rendererTaskOptions.get(task.id).outputBar;
    return typeof outputBar === "number" && outputBar !== 0 || typeof outputBar === "boolean" && outputBar !== false;
  }
  shouldOutputToBottomBar(task) {
    const bottomBar = this.cache.rendererTaskOptions.get(task.id).bottomBar;
    return typeof bottomBar === "number" && bottomBar !== 0 || typeof bottomBar === "boolean" && bottomBar !== false || !task.hasTitle();
  }
  renderer(tasks, level = 0) {
    return tasks.flatMap((task) => {
      if (!task.isEnabled()) {
        return [];
      }
      if (this.cache.render.has(task.id)) {
        return this.cache.render.get(task.id);
      }
      this.calculate(task);
      this.setupBuffer(task);
      const rendererOptions = this.cache.rendererOptions.get(task.id);
      const rendererTaskOptions = this.cache.rendererTaskOptions.get(task.id);
      const output = [];
      if (task.isPrompt()) {
        if (this.activePrompt && this.activePrompt !== task.id) {
          throw new ListrRendererError("Only one prompt can be active at the given time, please re-evaluate your task design.");
        } else if (!this.activePrompt) {
          task.on("PROMPT" /* PROMPT */, (prompt) => {
            const cleansed = cleanseAnsi(prompt);
            if (cleansed) {
              this.prompt = cleansed;
            }
          });
          task.on("STATE" /* STATE */, (state) => {
            if (state === "PROMPT_COMPLETED" /* PROMPT_COMPLETED */ || task.hasFinalized() || task.hasReset()) {
              this.prompt = null;
              this.activePrompt = null;
              task.off("PROMPT" /* PROMPT */);
            }
          });
          this.activePrompt = task.id;
        }
      }
      if (task.hasTitle()) {
        if (!(tasks.some((task2) => task2.hasFailed()) && !task.hasFailed() && task.options.exitOnError !== false && !(task.isCompleted() || task.isSkipped()))) {
          if (task.hasFailed() && rendererOptions.collapseErrors) {
            output.push(...this.format(!task.hasSubtasks() && task.message.error && rendererOptions.showErrorMessage ? task.message.error : task.title, this.style(task), level));
          } else if (task.isSkipped() && rendererOptions.collapseSkips) {
            output.push(
              ...this.format(
                this.logger.suffix(task.message.skip && rendererOptions.showSkipMessage ? task.message.skip : task.title, {
                  field: "SKIPPED" /* SKIPPED */,
                  condition: rendererOptions.suffixSkips,
                  format: /* @__PURE__ */ __name(() => color.dim, "format")
                }),
                this.style(task),
                level
              )
            );
          } else if (task.isRetrying()) {
            output.push(
              ...this.format(
                this.logger.suffix(task.title, {
                  field: `${"RETRY" /* RETRY */}:${task.message.retry.count}`,
                  format: /* @__PURE__ */ __name(() => color.yellow, "format"),
                  condition: rendererOptions.suffixRetries
                }),
                this.style(task),
                level
              )
            );
          } else if (task.isCompleted() && task.hasTitle() && assertFunctionOrSelf(rendererTaskOptions.timer?.condition, task.message.duration)) {
            output.push(
              ...this.format(
                this.logger.suffix(task?.title, {
                  ...rendererTaskOptions.timer,
                  args: [task.message.duration]
                }),
                this.style(task),
                level
              )
            );
          } else if (task.isPaused()) {
            output.push(
              ...this.format(
                this.logger.suffix(task.title, {
                  ...rendererOptions.pausedTimer,
                  args: [task.message.paused - Date.now()]
                }),
                this.style(task),
                level
              )
            );
          } else {
            output.push(...this.format(task.title, this.style(task), level));
          }
        } else {
          output.push(...this.format(task.title, this.logger.icon("COMPLETED_WITH_SISTER_TASKS_FAILED" /* COMPLETED_WITH_FAILED_SISTER_TASKS */), level));
        }
      }
      if (!task.hasSubtasks() || !rendererOptions.showSubtasks) {
        if (task.hasFailed() && rendererOptions.collapseErrors === false && (rendererOptions.showErrorMessage || !rendererOptions.showSubtasks)) {
          output.push(...this.dump(task, level, "FAILED" /* FAILED */));
        } else if (task.isSkipped() && rendererOptions.collapseSkips === false && (rendererOptions.showSkipMessage || !rendererOptions.showSubtasks)) {
          output.push(...this.dump(task, level, "SKIPPED" /* SKIPPED */));
        }
      }
      if (task.isPending() || rendererTaskOptions.persistentOutput) {
        output.push(...this.renderOutputBar(task, level));
      }
      if (
        // check if renderer option is on first
        rendererOptions.showSubtasks !== false && // if it doesnt have subtasks no need to check
        task.hasSubtasks() && (task.isPending() || task.hasFinalized() && !task.hasTitle() || // have to be completed and have subtasks
        task.isCompleted() && rendererOptions.collapseSubtasks === false && !task.subtasks.some((subtask) => this.cache.rendererOptions.get(subtask.id)?.collapseSubtasks === true) || // if any of the subtasks have the collapse option of
        task.subtasks.some((subtask) => this.cache.rendererOptions.get(subtask.id)?.collapseSubtasks === false) || // if any of the subtasks has failed
        task.subtasks.some((subtask) => subtask.hasFailed()) || // if any of the subtasks rolled back
        task.subtasks.some((subtask) => subtask.hasRolledBack()))
      ) {
        const subtaskLevel = !task.hasTitle() ? level : level + 1;
        const subtaskRender = this.renderer(task.subtasks, subtaskLevel);
        output.push(...subtaskRender);
      }
      if (task.hasFinalized()) {
        if (!rendererTaskOptions.persistentOutput) {
          this.buffer.bottom.delete(task.id);
          this.buffer.output.delete(task.id);
        }
      }
      if (task.isClosed()) {
        this.cache.render.set(task.id, output);
        this.reset(task);
      }
      return output;
    });
  }
  renderOutputBar(task, level) {
    const output = this.buffer.output.get(task.id);
    if (!output) {
      return [];
    }
    return output.all.flatMap((o) => this.dump(task, level, "OUTPUT" /* OUTPUT */, o.entry));
  }
  renderBottomBar() {
    if (this.buffer.bottom.size === 0) {
      return [];
    }
    return Array.from(this.buffer.bottom.values()).flatMap((output) => output.all).sort((a, b) => a.time - b.time).map((output) => output.entry);
  }
  renderPrompt() {
    if (!this.prompt) {
      return [];
    }
    return [this.prompt];
  }
  calculate(task) {
    if (this.cache.rendererOptions.has(task.id) && this.cache.rendererTaskOptions.has(task.id)) {
      return;
    }
    const rendererOptions = {
      ...this.options,
      ...task.rendererOptions
    };
    this.cache.rendererOptions.set(task.id, rendererOptions);
    this.cache.rendererTaskOptions.set(task.id, {
      ..._DefaultRenderer.rendererTaskOptions,
      timer: rendererOptions.timer,
      ...task.rendererTaskOptions
    });
  }
  setupBuffer(task) {
    if (this.buffer.bottom.has(task.id) || this.buffer.output.has(task.id)) {
      return;
    }
    const rendererTaskOptions = this.cache.rendererTaskOptions.get(task.id);
    if (this.shouldOutputToBottomBar(task) && !this.buffer.bottom.has(task.id)) {
      this.buffer.bottom.set(task.id, new ProcessOutputBuffer({ limit: typeof rendererTaskOptions.bottomBar === "number" ? rendererTaskOptions.bottomBar : 1 }));
      task.on("OUTPUT" /* OUTPUT */, (output) => {
        const data = this.dump(task, -1, "OUTPUT" /* OUTPUT */, output);
        this.buffer.bottom.get(task.id).write(data.join(EOL3));
      });
      task.on("STATE" /* STATE */, (state) => {
        switch (state) {
          case ("RETRY" /* RETRY */ || "ROLLING_BACK" /* ROLLING_BACK */):
            this.buffer.bottom.delete(task.id);
            break;
        }
      });
    } else if (this.shouldOutputToOutputBar(task) && !this.buffer.output.has(task.id)) {
      this.buffer.output.set(task.id, new ProcessOutputBuffer({ limit: typeof rendererTaskOptions.outputBar === "number" ? rendererTaskOptions.outputBar : 1 }));
      task.on("OUTPUT" /* OUTPUT */, (output) => {
        this.buffer.output.get(task.id).write(output);
      });
      task.on("STATE" /* STATE */, (state) => {
        switch (state) {
          case ("RETRY" /* RETRY */ || "ROLLING_BACK" /* ROLLING_BACK */):
            this.buffer.output.delete(task.id);
            break;
        }
      });
    }
  }
  reset(task) {
    this.cache.rendererOptions.delete(task.id);
    this.cache.rendererTaskOptions.delete(task.id);
    this.buffer.output.delete(task.id);
  }
  dump(task, level, source = "OUTPUT" /* OUTPUT */, data) {
    if (!data) {
      switch (source) {
        case "OUTPUT" /* OUTPUT */:
          data = task.output;
          break;
        case "SKIPPED" /* SKIPPED */:
          data = task.message.skip;
          break;
        case "FAILED" /* FAILED */:
          data = task.message.error;
          break;
      }
    }
    if (task.hasTitle() && source === "FAILED" /* FAILED */ && data === task.title || typeof data !== "string") {
      return [];
    }
    if (source === "OUTPUT" /* OUTPUT */) {
      data = cleanseAnsi(data);
    }
    return this.format(data, this.style(task, true), level + 1);
  }
  indent(str, i) {
    return i > 0 ? indent(str.trim(), this.options.indentation) : str.trim();
  }
};

// src/renderer/silent/renderer.ts
var SilentRenderer = class {
  constructor(tasks, options) {
    this.tasks = tasks;
    this.options = options;
  }
  static {
    __name(this, "SilentRenderer");
  }
  static nonTTY = true;
  static rendererOptions;
  static rendererTaskOptions;
  render() {
    return;
  }
  end() {
    return;
  }
};

// src/renderer/simple/renderer.ts
var SimpleRenderer = class _SimpleRenderer {
  constructor(tasks, options) {
    this.tasks = tasks;
    this.options = options;
    this.options = {
      ..._SimpleRenderer.rendererOptions,
      ...options,
      icon: {
        ...LISTR_LOGGER_STYLE.icon,
        ...options?.icon ?? {}
      },
      color: {
        ...LISTR_LOGGER_STYLE.color,
        ...options?.color ?? {}
      }
    };
    this.logger = this.options.logger ?? new ListrLogger({ useIcons: true, toStderr: LISTR_LOGGER_STDERR_LEVELS });
    this.logger.options.icon = this.options.icon;
    this.logger.options.color = this.options.color;
    if (this.options.timestamp) {
      this.logger.options.fields.prefix.unshift(this.options.timestamp);
    }
  }
  static {
    __name(this, "SimpleRenderer");
  }
  static nonTTY = true;
  static rendererOptions = {
    pausedTimer: {
      ...PRESET_TIMER,
      field: /* @__PURE__ */ __name((time) => `${"PAUSED" /* PAUSED */}:${time}`, "field"),
      format: /* @__PURE__ */ __name(() => color.yellowBright, "format")
    }
  };
  static rendererTaskOptions = {};
  logger;
  cache = {
    rendererOptions: /* @__PURE__ */ new Map(),
    rendererTaskOptions: /* @__PURE__ */ new Map()
  };
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  end() {
  }
  render() {
    this.renderer(this.tasks);
  }
  renderer(tasks) {
    tasks.forEach((task) => {
      this.calculate(task);
      task.once("CLOSED" /* CLOSED */, () => {
        this.reset(task);
      });
      const rendererOptions = this.cache.rendererOptions.get(task.id);
      const rendererTaskOptions = this.cache.rendererTaskOptions.get(task.id);
      task.on("SUBTASK" /* SUBTASK */, (subtasks) => {
        this.renderer(subtasks);
      });
      task.on("STATE" /* STATE */, (state) => {
        if (!task.hasTitle()) {
          return;
        }
        if (state === "STARTED" /* STARTED */) {
          this.logger.log("STARTED" /* STARTED */, task.title);
        } else if (state === "COMPLETED" /* COMPLETED */) {
          const timer = rendererTaskOptions?.timer;
          this.logger.log(
            "COMPLETED" /* COMPLETED */,
            task.title,
            timer && {
              suffix: {
                ...timer,
                condition: !!task.message?.duration && timer.condition,
                args: [task.message.duration]
              }
            }
          );
        } else if (state === "PROMPT" /* PROMPT */) {
          this.logger.process.hijack();
          task.on("PROMPT" /* PROMPT */, (prompt) => {
            this.logger.process.toStderr(prompt, false);
          });
        } else if (state === "PROMPT_COMPLETED" /* PROMPT_COMPLETED */) {
          task.off("PROMPT" /* PROMPT */);
          this.logger.process.release();
        }
      });
      task.on("OUTPUT" /* OUTPUT */, (output) => {
        this.logger.log("OUTPUT" /* OUTPUT */, output);
      });
      task.on("MESSAGE" /* MESSAGE */, (message) => {
        if (message.error) {
          this.logger.log("FAILED" /* FAILED */, task.title, {
            suffix: {
              field: `${"FAILED" /* FAILED */}: ${message.error}`,
              format: /* @__PURE__ */ __name(() => color.red, "format")
            }
          });
        } else if (message.skip) {
          this.logger.log("SKIPPED" /* SKIPPED */, task.title, {
            suffix: {
              field: `${"SKIPPED" /* SKIPPED */}: ${message.skip}`,
              format: /* @__PURE__ */ __name(() => color.yellow, "format")
            }
          });
        } else if (message.rollback) {
          this.logger.log("ROLLBACK" /* ROLLBACK */, task.title, {
            suffix: {
              field: `${"ROLLBACK" /* ROLLBACK */}: ${message.rollback}`,
              format: /* @__PURE__ */ __name(() => color.red, "format")
            }
          });
        } else if (message.retry) {
          this.logger.log("RETRY" /* RETRY */, task.title, {
            suffix: {
              field: `${"RETRY" /* RETRY */}:${message.retry.count}`,
              format: /* @__PURE__ */ __name(() => color.red, "format")
            }
          });
        } else if (message.paused) {
          const timer = rendererOptions?.pausedTimer;
          this.logger.log(
            "PAUSED" /* PAUSED */,
            task.title,
            timer && {
              suffix: {
                ...timer,
                condition: !!message?.paused && timer.condition,
                args: [message.paused - Date.now()]
              }
            }
          );
        }
      });
    });
  }
  calculate(task) {
    if (this.cache.rendererOptions.has(task.id) && this.cache.rendererTaskOptions.has(task.id)) {
      return;
    }
    const rendererOptions = {
      ...this.options,
      ...task.rendererOptions
    };
    this.cache.rendererOptions.set(task.id, rendererOptions);
    this.cache.rendererTaskOptions.set(task.id, {
      ..._SimpleRenderer.rendererTaskOptions,
      timer: rendererOptions.timer,
      ...task.rendererTaskOptions
    });
  }
  reset(task) {
    this.cache.rendererOptions.delete(task.id);
    this.cache.rendererTaskOptions.delete(task.id);
  }
};

// src/renderer/test/serializer.ts
var TestRendererSerializer = class {
  constructor(options) {
    this.options = options;
  }
  static {
    __name(this, "TestRendererSerializer");
  }
  serialize(event, data, task) {
    return JSON.stringify(this.generate(event, data, task));
  }
  generate(event, data, task) {
    const output = {
      event,
      data
    };
    if (typeof this.options?.task !== "boolean") {
      const t = Object.fromEntries(
        this.options.task.map((entity) => {
          const property = task[entity];
          if (typeof property === "function") {
            return [entity, property.call(task)];
          }
          return [entity, property];
        })
      );
      if (Object.keys(task).length > 0) {
        output.task = t;
      }
    }
    return output;
  }
};

// src/renderer/test/renderer.ts
var TestRenderer = class _TestRenderer {
  constructor(tasks, options) {
    this.tasks = tasks;
    this.options = options;
    this.options = { ..._TestRenderer.rendererOptions, ...this.options };
    this.logger = this.options.logger ?? new ListrLogger({ useIcons: false });
    this.serializer = new TestRendererSerializer(this.options);
  }
  static {
    __name(this, "TestRenderer");
  }
  static nonTTY = true;
  static rendererOptions = {
    subtasks: true,
    state: Object.values(ListrTaskState),
    output: true,
    prompt: true,
    title: true,
    messages: ["skip", "error", "retry", "rollback", "paused"],
    messagesToStderr: ["error", "rollback", "retry"],
    task: [
      "hasRolledBack",
      "isRollingBack",
      "isCompleted",
      "isSkipped",
      "hasFinalized",
      "hasSubtasks",
      "title",
      "hasReset",
      "hasTitle",
      "isPrompt",
      "isPaused",
      "isPending",
      "isSkipped",
      "isStarted",
      "hasFailed",
      "isEnabled",
      "isRetrying",
      "path"
    ]
  };
  static rendererTaskOptions;
  logger;
  serializer;
  render() {
    this.renderer(this.tasks);
  }
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  end() {
  }
  // verbose renderer multi-level
  renderer(tasks) {
    tasks.forEach((task) => {
      if (this.options.subtasks) {
        task.on("SUBTASK" /* SUBTASK */, (subtasks) => {
          this.renderer(subtasks);
        });
      }
      if (this.options.state) {
        task.on("STATE" /* STATE */, (state) => {
          this.logger.toStdout(this.serializer.serialize("STATE" /* STATE */, state, task));
        });
      }
      if (this.options.output) {
        task.on("OUTPUT" /* OUTPUT */, (data) => {
          this.logger.toStdout(this.serializer.serialize("OUTPUT" /* OUTPUT */, data, task));
        });
      }
      if (this.options.prompt) {
        task.on("PROMPT" /* PROMPT */, (prompt) => {
          this.logger.toStdout(this.serializer.serialize("PROMPT" /* PROMPT */, prompt, task));
        });
      }
      if (this.options.title) {
        task.on("TITLE" /* TITLE */, (title) => {
          this.logger.toStdout(this.serializer.serialize("TITLE" /* TITLE */, title, task));
        });
      }
      task.on("MESSAGE" /* MESSAGE */, (message) => {
        const parsed = Object.fromEntries(
          Object.entries(message).map(([key, value]) => {
            if (this.options.messages.includes(key)) {
              return [key, value];
            }
          }).filter(Boolean)
        );
        if (Object.keys(parsed).length > 0) {
          const output = this.serializer.serialize("MESSAGE" /* MESSAGE */, parsed, task);
          if (this.options.messagesToStderr.some((state) => Object.keys(parsed).includes(state))) {
            this.logger.toStderr(output);
          } else {
            this.logger.toStdout(output);
          }
        }
      });
    });
  }
};

// src/renderer/verbose/renderer.ts
var VerboseRenderer = class _VerboseRenderer {
  constructor(tasks, options) {
    this.tasks = tasks;
    this.options = options;
    this.options = {
      ..._VerboseRenderer.rendererOptions,
      ...this.options,
      icon: {
        ...LISTR_LOGGER_STYLE.icon,
        ...options?.icon ?? {}
      },
      color: {
        ...LISTR_LOGGER_STYLE.color,
        ...options?.color ?? {}
      }
    };
    this.logger = this.options.logger ?? new ListrLogger({ useIcons: false, toStderr: LISTR_LOGGER_STDERR_LEVELS });
    this.logger.options.icon = this.options.icon;
    this.logger.options.color = this.options.color;
    if (this.options.timestamp) {
      this.logger.options.fields.prefix.unshift(this.options.timestamp);
    }
  }
  static {
    __name(this, "VerboseRenderer");
  }
  static nonTTY = true;
  static rendererOptions = {
    logTitleChange: false,
    pausedTimer: {
      ...PRESET_TIMER,
      format: /* @__PURE__ */ __name(() => color.yellowBright, "format")
    }
  };
  static rendererTaskOptions;
  logger;
  cache = {
    rendererOptions: /* @__PURE__ */ new Map(),
    rendererTaskOptions: /* @__PURE__ */ new Map()
  };
  render() {
    this.renderer(this.tasks);
  }
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  end() {
  }
  renderer(tasks) {
    tasks.forEach((task) => {
      this.calculate(task);
      task.once("CLOSED" /* CLOSED */, () => {
        this.reset(task);
      });
      const rendererOptions = this.cache.rendererOptions.get(task.id);
      const rendererTaskOptions = this.cache.rendererTaskOptions.get(task.id);
      task.on("SUBTASK" /* SUBTASK */, (subtasks) => {
        this.renderer(subtasks);
      });
      task.on("STATE" /* STATE */, (state) => {
        if (!task.hasTitle()) {
          return;
        }
        if (state === "STARTED" /* STARTED */) {
          this.logger.log("STARTED" /* STARTED */, task.title);
        } else if (state === "COMPLETED" /* COMPLETED */) {
          const timer = rendererTaskOptions.timer;
          this.logger.log(
            "COMPLETED" /* COMPLETED */,
            task.title,
            timer && {
              suffix: {
                ...timer,
                condition: !!task.message?.duration && timer.condition,
                args: [task.message.duration]
              }
            }
          );
        }
      });
      task.on("OUTPUT" /* OUTPUT */, (data) => {
        this.logger.log("OUTPUT" /* OUTPUT */, data);
      });
      task.on("PROMPT" /* PROMPT */, (prompt) => {
        const cleansed = cleanseAnsi(prompt);
        if (cleansed) {
          this.logger.log("PROMPT" /* PROMPT */, cleansed);
        }
      });
      if (this.options?.logTitleChange !== false) {
        task.on("TITLE" /* TITLE */, (title) => {
          this.logger.log("TITLE" /* TITLE */, title);
        });
      }
      task.on("MESSAGE" /* MESSAGE */, (message) => {
        if (message?.error) {
          this.logger.log("FAILED" /* FAILED */, message.error);
        } else if (message?.skip) {
          this.logger.log("SKIPPED" /* SKIPPED */, message.skip);
        } else if (message?.rollback) {
          this.logger.log("ROLLBACK" /* ROLLBACK */, message.rollback);
        } else if (message?.retry) {
          this.logger.log("RETRY" /* RETRY */, task.title, { suffix: message.retry.count.toString() });
        } else if (message?.paused) {
          const timer = rendererOptions?.pausedTimer;
          this.logger.log(
            "PAUSED" /* PAUSED */,
            task.title,
            timer && {
              suffix: {
                ...timer,
                condition: !!message?.paused && timer.condition,
                args: [message.paused - Date.now()]
              }
            }
          );
        }
      });
    });
  }
  calculate(task) {
    if (this.cache.rendererOptions.has(task.id) && this.cache.rendererTaskOptions.has(task.id)) {
      return;
    }
    const rendererOptions = {
      ...this.options,
      ...task.rendererOptions
    };
    this.cache.rendererOptions.set(task.id, rendererOptions);
    this.cache.rendererTaskOptions.set(task.id, {
      ..._VerboseRenderer.rendererTaskOptions,
      timer: rendererOptions.timer,
      ...task.rendererTaskOptions
    });
  }
  reset(task) {
    this.cache.rendererOptions.delete(task.id);
    this.cache.rendererTaskOptions.delete(task.id);
  }
};

// src/utils/ui/renderer.ts
var RENDERERS = {
  default: DefaultRenderer,
  simple: SimpleRenderer,
  verbose: VerboseRenderer,
  test: TestRenderer,
  silent: SilentRenderer
};
function isRendererSupported(renderer) {
  return process.stdout.isTTY === true || renderer.nonTTY === true;
}
__name(isRendererSupported, "isRendererSupported");
function getRendererClass(renderer) {
  if (typeof renderer === "string") {
    return RENDERERS[renderer] ?? RENDERERS.default;
  }
  return typeof renderer === "function" ? renderer : RENDERERS.default;
}
__name(getRendererClass, "getRendererClass");
function getRenderer(options) {
  if (assertFunctionOrSelf(options?.silentRendererCondition)) {
    return { renderer: getRendererClass("silent"), selection: "SILENT" /* SILENT */ };
  }
  const r = {
    renderer: getRendererClass(options.renderer),
    options: options.rendererOptions,
    selection: "PRIMARY" /* PRIMARY */
  };
  if (!isRendererSupported(r.renderer) || assertFunctionOrSelf(options?.fallbackRendererCondition)) {
    return {
      renderer: getRendererClass(options.fallbackRenderer),
      options: options.fallbackRendererOptions,
      selection: "SECONDARY" /* SECONDARY */
    };
  }
  return r;
}
__name(getRenderer, "getRenderer");

// src/utils/assert.ts
function assertFunctionOrSelf(functionOrSelf, ...args) {
  if (typeof functionOrSelf === "function") {
    return functionOrSelf(...args);
  } else {
    return functionOrSelf;
  }
}
__name(assertFunctionOrSelf, "assertFunctionOrSelf");

// src/utils/clone.ts
import rfdc from "rfdc";
var clone = rfdc({ circles: true });
function cloneObject(obj) {
  return clone(obj);
}
__name(cloneObject, "cloneObject");

// src/utils/concurrency.ts
var Concurrency = class {
  static {
    __name(this, "Concurrency");
  }
  concurrency;
  count;
  queue;
  constructor(options) {
    this.concurrency = options.concurrency;
    this.count = 0;
    this.queue = /* @__PURE__ */ new Set();
  }
  add(fn) {
    if (this.count < this.concurrency) {
      return this.run(fn);
    }
    return new Promise((resolve) => {
      const callback = /* @__PURE__ */ __name(() => resolve(this.run(fn)), "callback");
      this.queue.add(callback);
    });
  }
  flush() {
    for (const callback of this.queue) {
      if (this.count >= this.concurrency) {
        break;
      }
      this.queue.delete(callback);
      callback();
    }
  }
  run(fn) {
    this.count++;
    const promise = fn();
    const cleanup = /* @__PURE__ */ __name(() => {
      this.count--;
      this.flush();
    }, "cleanup");
    promise.then(cleanup, () => {
      this.queue.clear();
    });
    return promise;
  }
};

// src/utils/delay.ts
function delay(time) {
  return new Promise((resolve) => {
    setTimeout(resolve, time);
  });
}
__name(delay, "delay");

// src/interfaces/listr-error.interface.ts
var ListrError = class extends Error {
  constructor(error, type, task) {
    super(error.message);
    this.error = error;
    this.type = type;
    this.task = task;
    this.name = "ListrError";
    this.path = task.path;
    if (task?.options.collectErrors === "full") {
      this.task = cloneObject(task);
      this.ctx = cloneObject(task.listr.ctx);
    }
    this.stack = error?.stack;
  }
  static {
    __name(this, "ListrError");
  }
  path;
  ctx;
};

// src/interfaces/listr-renderer-error.interface.ts
var ListrRendererError = class extends Error {
  static {
    __name(this, "ListrRendererError");
  }
};

// src/interfaces/prompt-error.interface.ts
var PromptError = class extends Error {
  static {
    __name(this, "PromptError");
  }
};

// src/lib/task-wrapper.ts
var TaskWrapper = class {
  constructor(task) {
    this.task = task;
  }
  static {
    __name(this, "TaskWrapper");
  }
  /* istanbul ignore next */
  get title() {
    return this.task.title;
  }
  /**
   * Title of the current task.
   *
   * @see {@link https://listr2.kilic.dev/task/title.html}
   */
  set title(title) {
    title = Array.isArray(title) ? title : [title];
    this.task.title$ = splat(title.shift(), ...title);
  }
  /* istanbul ignore next */
  get output() {
    return this.task.output;
  }
  /* istanbul ignore next */
  /**
   * Send output from the current task to the renderer.
   *
   * @see {@link https://listr2.kilic.dev/task/output.html}
   */
  set output(output) {
    output = Array.isArray(output) ? output : [output];
    this.task.output$ = splat(output.shift(), ...output);
  }
  /* istanbul ignore next */
  /** Send an output to the output channel as prompt. */
  set promptOutput(output) {
    this.task.promptOutput$ = output;
  }
  /**
   * Creates a new set of Listr subtasks.
   *
   * @see {@link https://listr2.kilic.dev/task/subtasks.html}
   */
  newListr(task, options) {
    let tasks;
    if (typeof task === "function") {
      tasks = task(this);
    } else {
      tasks = task;
    }
    return new Listr(tasks, options, this.task);
  }
  /**
   * Report an error that has to be collected and handled.
   *
   * @see {@link https://listr2.kilic.dev/task/error-handling.html}
   */
  report(error, type) {
    if (this.task.options.collectErrors !== false) {
      this.task.listr.errors.push(new ListrError(error, type, this.task));
    }
    this.task.message$ = { error: error.message ?? this.task?.title };
  }
  /**
   * Skip the current task.
   *
   * @see {@link https://listr2.kilic.dev/task/skip.html}
   */
  skip(message, ...metadata) {
    this.task.state$ = "SKIPPED" /* SKIPPED */;
    if (message) {
      this.task.message$ = { skip: message ? splat(message, ...metadata) : this.task?.title };
    }
  }
  /**
   * Check whether this task is currently in a retry state.
   *
   * @see {@link https://listr2.kilic.dev/task/retry.html}
   */
  isRetrying() {
    return this.task.isRetrying() ? this.task.retry : { count: 0 };
  }
  /* istanbul ignore next */
  /**
   * Create a new prompt for getting user input through the prompt adapter.
   * This will create a new prompt through the adapter if the task is not currently rendering a prompt or will return the active instance.
   *
   * This part of the application requires optional peer dependencies, please refer to documentation.
   *
   * @see {@link https://listr2.kilic.dev/task/prompt.html}
   */
  prompt(adapter) {
    if (this.task.prompt) {
      return this.task.prompt;
    }
    return new adapter(this.task, this);
  }
  /* istanbul ignore next */
  /**
   * Generates a fake stdout for your use case, where it will be tunnelled through Listr to handle the rendering process.
   *
   * @see {@link https://listr2.kilic.dev/renderer/process-output.html}
   */
  stdout(type) {
    return createWritable((chunk) => {
      switch (type) {
        case "PROMPT" /* PROMPT */:
          this.promptOutput = chunk;
          break;
        default:
          this.output = chunk;
      }
    });
  }
  /** Run this task. */
  run(ctx) {
    return this.task.run(ctx, this);
  }
};

// src/lib/task.ts
import { randomUUID } from "crypto";

// src/lib/listr-task-event-manager.ts
var ListrTaskEventManager = class extends EventManager {
  static {
    __name(this, "ListrTaskEventManager");
  }
};

// src/lib/task.ts
var Task = class extends ListrTaskEventManager {
  constructor(listr, task, options, rendererOptions, rendererTaskOptions) {
    super();
    this.listr = listr;
    this.task = task;
    this.options = options;
    this.rendererOptions = rendererOptions;
    this.rendererTaskOptions = rendererTaskOptions;
    if (task.title) {
      const title = Array.isArray(task?.title) ? task.title : [task.title];
      this.title = splat(title.shift(), ...title);
      this.initialTitle = this.title;
    }
    this.taskFn = task.task;
    this.parent = listr.parentTask;
  }
  static {
    __name(this, "Task");
  }
  /** Unique id per task, can be used for identifying a Task. */
  id = randomUUID();
  /** The current state of the task. */
  state = "WAITING" /* WAITING */;
  /** Subtasks of the current task. */
  subtasks;
  /** Title of the task. */
  title;
  /** Initial/Untouched version of the title for using whenever task has a reset. */
  initialTitle;
  /** Output channel for the task. */
  output;
  /** Current state of the retry process whenever the task is retrying. */
  retry;
  /**
   * A channel for messages.
   *
   * This requires a separate channel for messages like error, skip or runtime messages to further utilize in the renderers.
   */
  message = {};
  /** Current prompt instance or prompt error whenever the task is prompting. */
  prompt;
  /** Parent task of the current task. */
  parent;
  /** Enable flag of this task. */
  enabled;
  /** User provided Task callback function to run. */
  taskFn;
  /** Marks the task as closed. This is different from finalized since this is not really related to task itself. */
  closed;
  /**
   * Update the current state of the Task and emit the neccassary events.
   */
  set state$(state) {
    this.state = state;
    this.emit("STATE" /* STATE */, state);
    if (this.hasSubtasks() && this.hasFailed()) {
      for (const subtask of this.subtasks) {
        if (subtask.state === "STARTED" /* STARTED */) {
          subtask.state$ = "FAILED" /* FAILED */;
        }
      }
    }
    this.listr.events.emit("SHOUD_REFRESH_RENDER" /* SHOULD_REFRESH_RENDER */);
  }
  /**
   * Update the current output of the Task and emit the neccassary events.
   */
  set output$(data) {
    this.output = data;
    this.emit("OUTPUT" /* OUTPUT */, data);
    this.listr.events.emit("SHOUD_REFRESH_RENDER" /* SHOULD_REFRESH_RENDER */);
  }
  /**
   * Update the current prompt output of the Task and emit the neccassary events.
   */
  set promptOutput$(data) {
    this.emit("PROMPT" /* PROMPT */, data);
    if (cleanseAnsi(data)) {
      this.listr.events.emit("SHOUD_REFRESH_RENDER" /* SHOULD_REFRESH_RENDER */);
    }
  }
  /**
   * Update or extend the current message of the Task and emit the neccassary events.
   */
  set message$(data) {
    this.message = { ...this.message, ...data };
    this.emit("MESSAGE" /* MESSAGE */, data);
    this.listr.events.emit("SHOUD_REFRESH_RENDER" /* SHOULD_REFRESH_RENDER */);
  }
  /**
   * Update the current title of the Task and emit the neccassary events.
   */
  set title$(title) {
    this.title = title;
    this.emit("TITLE" /* TITLE */, title);
    this.listr.events.emit("SHOUD_REFRESH_RENDER" /* SHOULD_REFRESH_RENDER */);
  }
  /**
   * Current task path in the hierarchy.
   */
  get path() {
    return [...this.listr.path, this.initialTitle];
  }
  /**
   * Checks whether the current task with the given context should be set as enabled.
   */
  async check(ctx) {
    if (this.state === "WAITING" /* WAITING */) {
      this.enabled = await assertFunctionOrSelf(this.task?.enabled ?? true, ctx);
      this.emit("ENABLED" /* ENABLED */, this.enabled);
      this.listr.events.emit("SHOUD_REFRESH_RENDER" /* SHOULD_REFRESH_RENDER */);
    }
    return this.enabled;
  }
  /** Returns whether this task has subtasks. */
  hasSubtasks() {
    return this.subtasks?.length > 0;
  }
  /** Returns whether this task is finalized in someform. */
  hasFinalized() {
    return this.isCompleted() || this.hasFailed() || this.isSkipped() || this.hasRolledBack();
  }
  /** Returns whether this task is in progress. */
  isPending() {
    return this.isStarted() || this.isPrompt() || this.hasReset();
  }
  /** Returns whether this task has started. */
  isStarted() {
    return this.state === "STARTED" /* STARTED */;
  }
  /** Returns whether this task is skipped. */
  isSkipped() {
    return this.state === "SKIPPED" /* SKIPPED */;
  }
  /** Returns whether this task has been completed. */
  isCompleted() {
    return this.state === "COMPLETED" /* COMPLETED */;
  }
  /** Returns whether this task has been failed. */
  hasFailed() {
    return this.state === "FAILED" /* FAILED */;
  }
  /** Returns whether this task has an active rollback task going on. */
  isRollingBack() {
    return this.state === "ROLLING_BACK" /* ROLLING_BACK */;
  }
  /** Returns whether the rollback action was successful. */
  hasRolledBack() {
    return this.state === "ROLLED_BACK" /* ROLLED_BACK */;
  }
  /** Returns whether this task has an actively retrying task going on. */
  isRetrying() {
    return this.state === "RETRY" /* RETRY */;
  }
  /** Returns whether this task has some kind of reset like retry and rollback going on. */
  hasReset() {
    return this.state === "RETRY" /* RETRY */ || this.state === "ROLLING_BACK" /* ROLLING_BACK */;
  }
  /** Returns whether enabled function resolves to true. */
  isEnabled() {
    return this.enabled;
  }
  /** Returns whether this task actually has a title. */
  hasTitle() {
    return typeof this?.title === "string";
  }
  /** Returns whether this task has a prompt inside. */
  isPrompt() {
    return this.state === "PROMPT" /* PROMPT */ || this.state === "PROMPT_COMPLETED" /* PROMPT_COMPLETED */;
  }
  /** Returns whether this task is currently paused. */
  isPaused() {
    return this.state === "PAUSED" /* PAUSED */;
  }
  /** Returns whether this task is closed. */
  isClosed() {
    return this.closed;
  }
  /** Pause the given task for certain time. */
  async pause(time) {
    const state = this.state;
    this.state$ = "PAUSED" /* PAUSED */;
    this.message$ = {
      paused: Date.now() + time
    };
    await delay(time);
    this.state$ = state;
    this.message$ = {
      paused: null
    };
  }
  /** Run the current task. */
  async run(context, wrapper) {
    const handleResult = /* @__PURE__ */ __name((result) => {
      if (result instanceof Listr) {
        result.options = { ...this.options, ...result.options };
        result.rendererClass = getRendererClass("silent");
        this.subtasks = result.tasks;
        result.errors = this.listr.errors;
        this.emit("SUBTASK" /* SUBTASK */, this.subtasks);
        result = result.run(context);
      } else if (result instanceof Promise) {
        result = result.then(handleResult);
      } else if (isReadable(result)) {
        result = new Promise((resolve, reject) => {
          result.on("data", (data) => {
            this.output$ = data.toString();
          });
          result.on("error", (error) => reject(error));
          result.on("end", () => resolve(null));
        });
      } else if (isObservable(result)) {
        result = new Promise((resolve, reject) => {
          result.subscribe({
            next: /* @__PURE__ */ __name((data) => {
              this.output$ = data;
            }, "next"),
            error: reject,
            complete: resolve
          });
        });
      }
      return result;
    }, "handleResult");
    const startTime = Date.now();
    this.state$ = "STARTED" /* STARTED */;
    const skipped = await assertFunctionOrSelf(this.task?.skip ?? false, context);
    if (skipped) {
      if (typeof skipped === "string") {
        this.message$ = { skip: skipped };
      } else if (this.hasTitle()) {
        this.message$ = { skip: this.title };
      } else {
        this.message$ = { skip: "Skipped task without a title." };
      }
      this.state$ = "SKIPPED" /* SKIPPED */;
      return;
    }
    try {
      const retryCount = typeof this.task?.retry === "number" && this.task.retry > 0 ? this.task.retry + 1 : typeof this.task?.retry === "object" && this.task.retry.tries > 0 ? this.task.retry.tries + 1 : 1;
      const retryDelay = typeof this.task.retry === "object" && this.task.retry.delay;
      for (let retries = 1; retries <= retryCount; retries++) {
        try {
          await handleResult(this.taskFn(context, wrapper));
          break;
        } catch (err) {
          if (retries !== retryCount) {
            this.retry = { count: retries, error: err };
            this.message$ = { retry: this.retry };
            this.title$ = this.initialTitle;
            this.output = void 0;
            wrapper.report(err, "WILL_RETRY" /* WILL_RETRY */);
            this.state$ = "RETRY" /* RETRY */;
            if (retryDelay) {
              await this.pause(retryDelay);
            }
          } else {
            throw err;
          }
        }
      }
      if (this.isStarted() || this.isRetrying()) {
        this.message$ = { duration: Date.now() - startTime };
        this.state$ = "COMPLETED" /* COMPLETED */;
      }
    } catch (error) {
      if (this.prompt instanceof PromptError) {
        error = this.prompt;
      }
      if (this.task?.rollback) {
        wrapper.report(error, "WILL_ROLLBACK" /* WILL_ROLLBACK */);
        try {
          this.state$ = "ROLLING_BACK" /* ROLLING_BACK */;
          await this.task.rollback(context, wrapper);
          this.message$ = { rollback: this.title };
          this.state$ = "ROLLED_BACK" /* ROLLED_BACK */;
        } catch (err) {
          this.state$ = "FAILED" /* FAILED */;
          wrapper.report(err, "HAS_FAILED_TO_ROLLBACK" /* HAS_FAILED_TO_ROLLBACK */);
          this.close();
          throw err;
        }
        if (this.listr.options?.exitAfterRollback !== false) {
          this.close();
          throw error;
        }
      } else {
        this.state$ = "FAILED" /* FAILED */;
        if (this.listr.options.exitOnError !== false && await assertFunctionOrSelf(this.task?.exitOnError, context) !== false) {
          wrapper.report(error, "HAS_FAILED" /* HAS_FAILED */);
          this.close();
          throw error;
        } else if (!this.hasSubtasks()) {
          wrapper.report(error, "HAS_FAILED_WITHOUT_ERROR" /* HAS_FAILED_WITHOUT_ERROR */);
        }
      }
    } finally {
      this.close();
    }
  }
  close() {
    this.emit("CLOSED" /* CLOSED */);
    this.listr.events.emit("SHOUD_REFRESH_RENDER" /* SHOULD_REFRESH_RENDER */);
    this.complete();
  }
};

// src/lib/listr-event-manager.ts
var ListrEventManager = class extends EventManager {
  static {
    __name(this, "ListrEventManager");
  }
};

// src/listr.ts
var Listr = class {
  constructor(task, options, parentTask) {
    this.task = task;
    this.options = options;
    this.parentTask = parentTask;
    this.options = {
      concurrent: false,
      renderer: "default",
      fallbackRenderer: "simple",
      exitOnError: true,
      exitAfterRollback: true,
      collectErrors: false,
      registerSignalListeners: true,
      ...this.parentTask?.options ?? {},
      ...options
    };
    if (this.options.concurrent === true) {
      this.options.concurrent = Infinity;
    } else if (typeof this.options.concurrent !== "number") {
      this.options.concurrent = 1;
    }
    this.concurrency = new Concurrency({ concurrency: this.options.concurrent });
    if (parentTask) {
      this.path = [...parentTask.listr.path, parentTask.title];
      this.errors = parentTask.listr.errors;
    }
    if (this.parentTask?.listr.events instanceof ListrEventManager) {
      this.events = this.parentTask.listr.events;
    } else {
      this.events = new ListrEventManager();
    }
    const renderer = getRenderer({
      renderer: this.options.renderer,
      rendererOptions: this.options.rendererOptions,
      fallbackRenderer: this.options.fallbackRenderer,
      fallbackRendererOptions: this.options.fallbackRendererOptions,
      fallbackRendererCondition: this.options?.fallbackRendererCondition,
      silentRendererCondition: this.options?.silentRendererCondition
    });
    this.rendererClass = renderer.renderer;
    this.rendererClassOptions = renderer.options;
    this.rendererSelection = renderer.selection;
    this.add(task ?? []);
    if (this.options.registerSignalListeners) {
      this.boundSignalHandler = this.signalHandler.bind(this);
      process.once("SIGINT", this.boundSignalHandler).setMaxListeners(0);
    }
    if (this.options?.forceTTY || process.env["LISTR_FORCE_TTY" /* FORCE_TTY */]) {
      process.stdout.isTTY = true;
      process.stderr.isTTY = true;
    }
    if (this.options?.forceUnicode) {
      process.env["LISTR_FORCE_UNICODE" /* FORCE_UNICODE */] = "1";
    }
  }
  static {
    __name(this, "Listr");
  }
  tasks = [];
  errors = [];
  ctx;
  events;
  path = [];
  rendererClass;
  rendererClassOptions;
  rendererSelection;
  boundSignalHandler;
  concurrency;
  renderer;
  /**
   * Whether this is the root task.
   */
  isRoot() {
    return !this.parentTask;
  }
  /**
   * Whether this is a subtask of another task list.
   */
  isSubtask() {
    return !!this.parentTask;
  }
  /**
   * Add tasks to current task list.
   *
   * @see {@link https://listr2.kilic.dev/task/task.html}
   */
  add(tasks) {
    this.tasks.push(...this.generate(tasks));
  }
  /**
   * Run the task list.
   *
   * @see {@link https://listr2.kilic.dev/listr/listr.html#run-the-generated-task-list}
   */
  async run(context) {
    if (!this.renderer) {
      this.renderer = new this.rendererClass(this.tasks, this.rendererClassOptions, this.events);
    }
    await this.renderer.render();
    this.ctx = this.options?.ctx ?? context ?? {};
    await Promise.all(this.tasks.map((task) => task.check(this.ctx)));
    try {
      await Promise.all(this.tasks.map((task) => this.concurrency.add(() => this.runTask(task))));
      this.renderer.end();
      this.removeSignalHandler();
    } catch (err) {
      if (this.options.exitOnError !== false) {
        this.renderer.end(err);
        this.removeSignalHandler();
        throw err;
      }
    }
    return this.ctx;
  }
  generate(tasks) {
    tasks = Array.isArray(tasks) ? tasks : [tasks];
    return tasks.map((task) => {
      let rendererTaskOptions;
      if (this.rendererSelection === "PRIMARY" /* PRIMARY */) {
        rendererTaskOptions = task.rendererOptions;
      } else if (this.rendererSelection === "SECONDARY" /* SECONDARY */) {
        rendererTaskOptions = task.fallbackRendererOptions;
      }
      return new Task(
        this,
        task,
        this.options,
        this.rendererClassOptions,
        rendererTaskOptions
      );
    });
  }
  async runTask(task) {
    if (!await task.check(this.ctx)) {
      return;
    }
    return new TaskWrapper(task).run(this.ctx);
  }
  signalHandler() {
    this.tasks?.forEach(async (task) => {
      if (task.isPending()) {
        task.state$ = "FAILED" /* FAILED */;
      }
    });
    if (this.isRoot()) {
      this.renderer.end(new Error("Interrupted."));
      process.exit(127);
    }
  }
  removeSignalHandler() {
    if (this.boundSignalHandler) {
      process.removeListener("SIGINT", this.boundSignalHandler);
    }
  }
};
export {
  ANSI_ESCAPE,
  ANSI_ESCAPE_CODES,
  BaseEventMap,
  Concurrency,
  DefaultRenderer,
  EventManager,
  LISTR_DEFAULT_RENDERER_STYLE,
  LISTR_LOGGER_STDERR_LEVELS,
  LISTR_LOGGER_STYLE,
  Listr,
  ListrDefaultRendererLogLevels,
  ListrEnvironmentVariables,
  ListrError,
  ListrErrorTypes,
  ListrEventManager,
  ListrEventType,
  ListrLogLevels,
  ListrLogger,
  ListrPromptAdapter,
  ListrRendererError,
  ListrRendererSelection,
  ListrTaskEventManager,
  ListrTaskEventType,
  ListrTaskState,
  PRESET_TIMER,
  PRESET_TIMESTAMP,
  ProcessOutput,
  ProcessOutputBuffer,
  ProcessOutputStream,
  PromptError,
  SilentRenderer,
  SimpleRenderer,
  Spinner,
  TestRenderer,
  TestRendererSerializer,
  VerboseRenderer,
  assertFunctionOrSelf,
  cleanseAnsi,
  cloneObject,
  color,
  createWritable,
  delay,
  figures,
  getRenderer,
  getRendererClass,
  indent,
  isObservable,
  isReadable,
  isUnicodeSupported,
  parseTimer,
  parseTimestamp,
  splat
};

license: mit


code:
export type Options = {
	/**
	Match only the first ANSI escape.

	@default false
	*/
	readonly onlyFirst: boolean;
};

/**
Regular expression for matching ANSI escape codes.

@example
```
import ansiRegex from 'ansi-regex';

ansiRegex().test('\u001B[4mcake\u001B[0m');
//=> true

ansiRegex().test('cake');
//=> false

'\u001B[4mcake\u001B[0m'.match(ansiRegex());
//=> ['\u001B[4m', '\u001B[0m']

'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
//=> ['\u001B[4m']

'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
```
*/
export default function ansiRegex(options?: Options): RegExp;


ansi-regex

description: Regular expression for matching ANSI escape codes

license: MIT

repository: chalk/ansi-regex

type: module

test: xo && ava && tsd

view-supported: node fixtures/view-codes.js

keywords: ansi styles color colour colors terminal console cli string tty escape formatting rgb 256 shell xterm command-line text regex regexp re match test find pattern


code:
# ansi-regex

> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)

## Install

```sh
npm install ansi-regex
```

## Usage

```js
import ansiRegex from 'ansi-regex';

ansiRegex().test('\u001B[4mcake\u001B[0m');
//=> true

ansiRegex().test('cake');
//=> false

'\u001B[4mcake\u001B[0m'.match(ansiRegex());
//=> ['\u001B[4m', '\u001B[0m']

'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
//=> ['\u001B[4m']

'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
```

## API

### ansiRegex(options?)

Returns a regex for matching ANSI escape codes.

#### options

Type: `object`

##### onlyFirst

Type: `boolean`\
Default: `false` *(Matches any ANSI escape codes in a string)*

Match only the first ANSI escape.

## FAQ

### Why do you test for codes not in the ECMA 48 standard?

Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.

On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.

## Maintainers

- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)


code:
export interface CSPair { // eslint-disable-line @typescript-eslint/naming-convention
	/**
	The ANSI terminal control sequence for starting this style.
	*/
	readonly open: string;

	/**
	The ANSI terminal control sequence for ending this style.
	*/
	readonly close: string;
}

export interface ColorBase {
	/**
	The ANSI terminal control sequence for ending this color.
	*/
	readonly close: string;

	ansi(code: number): string;

	ansi256(code: number): string;

	ansi16m(red: number, green: number, blue: number): string;
}

export interface Modifier {
	/**
	Resets the current color chain.
	*/
	readonly reset: CSPair;

	/**
	Make text bold.
	*/
	readonly bold: CSPair;

	/**
	Emitting only a small amount of light.
	*/
	readonly dim: CSPair;

	/**
	Make text italic. (Not widely supported)
	*/
	readonly italic: CSPair;

	/**
	Make text underline. (Not widely supported)
	*/
	readonly underline: CSPair;

	/**
	Make text overline.

	Supported on VTE-based terminals, the GNOME terminal, mintty, and Git Bash.
	*/
	readonly overline: CSPair;

	/**
	Inverse background and foreground colors.
	*/
	readonly inverse: CSPair;

	/**
	Prints the text, but makes it invisible.
	*/
	readonly hidden: CSPair;

	/**
	Puts a horizontal line through the center of the text. (Not widely supported)
	*/
	readonly strikethrough: CSPair;
}

export interface ForegroundColor {
	readonly black: CSPair;
	readonly red: CSPair;
	readonly green: CSPair;
	readonly yellow: CSPair;
	readonly blue: CSPair;
	readonly cyan: CSPair;
	readonly magenta: CSPair;
	readonly white: CSPair;

	/**
	Alias for `blackBright`.
	*/
	readonly gray: CSPair;

	/**
	Alias for `blackBright`.
	*/
	readonly grey: CSPair;

	readonly blackBright: CSPair;
	readonly redBright: CSPair;
	readonly greenBright: CSPair;
	readonly yellowBright: CSPair;
	readonly blueBright: CSPair;
	readonly cyanBright: CSPair;
	readonly magentaBright: CSPair;
	readonly whiteBright: CSPair;
}

export interface BackgroundColor {
	readonly bgBlack: CSPair;
	readonly bgRed: CSPair;
	readonly bgGreen: CSPair;
	readonly bgYellow: CSPair;
	readonly bgBlue: CSPair;
	readonly bgCyan: CSPair;
	readonly bgMagenta: CSPair;
	readonly bgWhite: CSPair;

	/**
	Alias for `bgBlackBright`.
	*/
	readonly bgGray: CSPair;

	/**
	Alias for `bgBlackBright`.
	*/
	readonly bgGrey: CSPair;

	readonly bgBlackBright: CSPair;
	readonly bgRedBright: CSPair;
	readonly bgGreenBright: CSPair;
	readonly bgYellowBright: CSPair;
	readonly bgBlueBright: CSPair;
	readonly bgCyanBright: CSPair;
	readonly bgMagentaBright: CSPair;
	readonly bgWhiteBright: CSPair;
}

export interface ConvertColor {
	/**
	Convert from the RGB color space to the ANSI 256 color space.

	@param red - (`0...255`)
	@param green - (`0...255`)
	@param blue - (`0...255`)
	*/
	rgbToAnsi256(red: number, green: number, blue: number): number;

	/**
	Convert from the RGB HEX color space to the RGB color space.

	@param hex - A hexadecimal string containing RGB data.
	*/
	hexToRgb(hex: string): [red: number, green: number, blue: number];

	/**
	Convert from the RGB HEX color space to the ANSI 256 color space.

	@param hex - A hexadecimal string containing RGB data.
	*/
	hexToAnsi256(hex: string): number;

	/**
	Convert from the ANSI 256 color space to the ANSI 16 color space.

	@param code - A number representing the ANSI 256 color.
	*/
	ansi256ToAnsi(code: number): number;

	/**
	Convert from the RGB color space to the ANSI 16 color space.

	@param red - (`0...255`)
	@param green - (`0...255`)
	@param blue - (`0...255`)
	*/
	rgbToAnsi(red: number, green: number, blue: number): number;

	/**
	Convert from the RGB HEX color space to the ANSI 16 color space.

	@param hex - A hexadecimal string containing RGB data.
	*/
	hexToAnsi(hex: string): number;
}

/**
Basic modifier names.
*/
export type ModifierName = keyof Modifier;

/**
Basic foreground color names.

[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type ForegroundColorName = keyof ForegroundColor;

/**
Basic background color names.

[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type BackgroundColorName = keyof BackgroundColor;

/**
Basic color names. The combination of foreground and background color names.

[More colors here.](https://github.com/chalk/chalk/blob/main/readme.md#256-and-truecolor-color-support)
*/
export type ColorName = ForegroundColorName | BackgroundColorName;

/**
Basic modifier names.
*/
export const modifierNames: readonly ModifierName[];

/**
Basic foreground color names.
*/
export const foregroundColorNames: readonly ForegroundColorName[];

/**
Basic background color names.
*/
export const backgroundColorNames: readonly BackgroundColorName[];

/*
Basic color names. The combination of foreground and background color names.
*/
export const colorNames: readonly ColorName[];

declare const ansiStyles: {
	readonly modifier: Modifier;
	readonly color: ColorBase & ForegroundColor;
	readonly bgColor: ColorBase & BackgroundColor;
	readonly codes: ReadonlyMap<number, number>;
} & ForegroundColor & BackgroundColor & Modifier & ConvertColor;

export default ansiStyles;


code:
const ANSI_BACKGROUND_OFFSET = 10;

const wrapAnsi16 = (offset = 0) => code => `\u001B[${code + offset}m`;

const wrapAnsi256 = (offset = 0) => code => `\u001B[${38 + offset};5;${code}m`;

const wrapAnsi16m = (offset = 0) => (red, green, blue) => `\u001B[${38 + offset};2;${red};${green};${blue}m`;

const styles = {
	modifier: {
		reset: [0, 0],
		// 21 isn't widely supported and 22 does the same thing
		bold: [1, 22],
		dim: [2, 22],
		italic: [3, 23],
		underline: [4, 24],
		overline: [53, 55],
		inverse: [7, 27],
		hidden: [8, 28],
		strikethrough: [9, 29],
	},
	color: {
		black: [30, 39],
		red: [31, 39],
		green: [32, 39],
		yellow: [33, 39],
		blue: [34, 39],
		magenta: [35, 39],
		cyan: [36, 39],
		white: [37, 39],

		// Bright color
		blackBright: [90, 39],
		gray: [90, 39], // Alias of `blackBright`
		grey: [90, 39], // Alias of `blackBright`
		redBright: [91, 39],
		greenBright: [92, 39],
		yellowBright: [93, 39],
		blueBright: [94, 39],
		magentaBright: [95, 39],
		cyanBright: [96, 39],
		whiteBright: [97, 39],
	},
	bgColor: {
		bgBlack: [40, 49],
		bgRed: [41, 49],
		bgGreen: [42, 49],
		bgYellow: [43, 49],
		bgBlue: [44, 49],
		bgMagenta: [45, 49],
		bgCyan: [46, 49],
		bgWhite: [47, 49],

		// Bright color
		bgBlackBright: [100, 49],
		bgGray: [100, 49], // Alias of `bgBlackBright`
		bgGrey: [100, 49], // Alias of `bgBlackBright`
		bgRedBright: [101, 49],
		bgGreenBright: [102, 49],
		bgYellowBright: [103, 49],
		bgBlueBright: [104, 49],
		bgMagentaBright: [105, 49],
		bgCyanBright: [106, 49],
		bgWhiteBright: [107, 49],
	},
};

export const modifierNames = Object.keys(styles.modifier);
export const foregroundColorNames = Object.keys(styles.color);
export const backgroundColorNames = Object.keys(styles.bgColor);
export const colorNames = [...foregroundColorNames, ...backgroundColorNames];

function assembleStyles() {
	const codes = new Map();

	for (const [groupName, group] of Object.entries(styles)) {
		for (const [styleName, style] of Object.entries(group)) {
			styles[styleName] = {
				open: `\u001B[${style[0]}m`,
				close: `\u001B[${style[1]}m`,
			};

			group[styleName] = styles[styleName];

			codes.set(style[0], style[1]);
		}

		Object.defineProperty(styles, groupName, {
			value: group,
			enumerable: false,
		});
	}

	Object.defineProperty(styles, 'codes', {
		value: codes,
		enumerable: false,
	});

	styles.color.close = '\u001B[39m';
	styles.bgColor.close = '\u001B[49m';

	styles.color.ansi = wrapAnsi16();
	styles.color.ansi256 = wrapAnsi256();
	styles.color.ansi16m = wrapAnsi16m();
	styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
	styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
	styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);

	// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js
	Object.defineProperties(styles, {
		rgbToAnsi256: {
			value: (red, green, blue) => {
				// We use the extended greyscale palette here, with the exception of
				// black and white. normal palette only has 4 greyscale shades.
				if (red === green && green === blue) {
					if (red < 8) {
						return 16;
					}

					if (red > 248) {
						return 231;
					}

					return Math.round(((red - 8) / 247) * 24) + 232;
				}

				return 16
					+ (36 * Math.round(red / 255 * 5))
					+ (6 * Math.round(green / 255 * 5))
					+ Math.round(blue / 255 * 5);
			},
			enumerable: false,
		},
		hexToRgb: {
			value: hex => {
				const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
				if (!matches) {
					return [0, 0, 0];
				}

				let [colorString] = matches;

				if (colorString.length === 3) {
					colorString = [...colorString].map(character => character + character).join('');
				}

				const integer = Number.parseInt(colorString, 16);

				return [
					/* eslint-disable no-bitwise */
					(integer >> 16) & 0xFF,
					(integer >> 8) & 0xFF,
					integer & 0xFF,
					/* eslint-enable no-bitwise */
				];
			},
			enumerable: false,
		},
		hexToAnsi256: {
			value: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
			enumerable: false,
		},
		ansi256ToAnsi: {
			value: code => {
				if (code < 8) {
					return 30 + code;
				}

				if (code < 16) {
					return 90 + (code - 8);
				}

				let red;
				let green;
				let blue;

				if (code >= 232) {
					red = (((code - 232) * 10) + 8) / 255;
					green = red;
					blue = red;
				} else {
					code -= 16;

					const remainder = code % 36;

					red = Math.floor(code / 36) / 5;
					green = Math.floor(remainder / 6) / 5;
					blue = (remainder % 6) / 5;
				}

				const value = Math.max(red, green, blue) * 2;

				if (value === 0) {
					return 30;
				}

				// eslint-disable-next-line no-bitwise
				let result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red));

				if (value === 2) {
					result += 60;
				}

				return result;
			},
			enumerable: false,
		},
		rgbToAnsi: {
			value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
			enumerable: false,
		},
		hexToAnsi: {
			value: hex => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
			enumerable: false,
		},
	});

	return styles;
}

const ansiStyles = assembleStyles();

export default ansiStyles;


ansi-styles

description: ANSI escape codes for styling strings in the terminal

repository: chalk/ansi-styles

screenshot: svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor

keywords: ansi styles color colour colors terminal console cli string tty escape formatting rgb 256 shell xterm log logging command-line text


code:
# ansi-styles

> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal

You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.

![](screenshot.png)

## Install

```sh
npm install ansi-styles
```

## Usage

```js
import styles from 'ansi-styles';

console.log(`${styles.green.open}Hello world!${styles.green.close}`);

// Color conversion between 256/truecolor
// NOTE: When converting from truecolor to 256 colors, the original color
//       may be degraded to fit the new color palette. This means terminals
//       that do not support 16 million colors will best-match the
//       original color.
console.log(`${styles.color.ansi(styles.rgbToAnsi(199, 20, 250))}Hello World${styles.color.close}`)
console.log(`${styles.color.ansi256(styles.rgbToAnsi256(199, 20, 250))}Hello World${styles.color.close}`)
console.log(`${styles.color.ansi16m(...styles.hexToRgb('#abcdef'))}Hello World${styles.color.close}`)
```

## API

### `open` and `close`

Each style has an `open` and `close` property.

### `modifierNames`, `foregroundColorNames`, `backgroundColorNames`, and `colorNames`

All supported style strings are exposed as an array of strings for convenience. `colorNames` is the combination of `foregroundColorNames` and `backgroundColorNames`.

This can be useful if you need to validate input:

```js
import {modifierNames, foregroundColorNames} from 'ansi-styles';

console.log(modifierNames.includes('bold'));
//=> true

console.log(foregroundColorNames.includes('pink'));
//=> false
```

## Styles

### Modifiers

- `reset`
- `bold`
- `dim`
- `italic` *(Not widely supported)*
- `underline`
- `overline` *Supported on VTE-based terminals, the GNOME terminal, mintty, and Git Bash.*
- `inverse`
- `hidden`
- `strikethrough` *(Not widely supported)*

### Colors

- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `blackBright` (alias: `gray`, `grey`)
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`

### Background colors

- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`

## Advanced usage

By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.

- `styles.modifier`
- `styles.color`
- `styles.bgColor`

###### Example

```js
import styles from 'ansi-styles';

console.log(styles.color.green.open);
```

Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `styles.codes`, which returns a `Map` with the open codes as keys and close codes as values.

###### Example

```js
import styles from 'ansi-styles';

console.log(styles.codes.get(36));
//=> 39
```

## 16 / 256 / 16 million (TrueColor) support

`ansi-styles` allows converting between various color formats and ANSI escapes, with support for 16, 256 and [16 million colors](https://gist.github.com/XVilka/8346728).

The following color spaces are supported:

- `rgb`
- `hex`
- `ansi256`
- `ansi`

To use these, call the associated conversion function with the intended output, for example:

```js
import styles from 'ansi-styles';

styles.color.ansi(styles.rgbToAnsi(100, 200, 15)); // RGB to 16 color ansi foreground code
styles.bgColor.ansi(styles.hexToAnsi('#C0FFEE')); // HEX to 16 color ansi foreground code

styles.color.ansi256(styles.rgbToAnsi256(100, 200, 15)); // RGB to 256 color ansi foreground code
styles.bgColor.ansi256(styles.hexToAnsi256('#C0FFEE')); // HEX to 256 color ansi foreground code

styles.color.ansi16m(100, 200, 15); // RGB to 16 million color foreground code
styles.bgColor.ansi16m(...styles.hexToRgb('#C0FFEE')); // Hex (RGB) to 16 million color foreground code
```

## Related

- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal

## Maintainers

- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)

## For enterprise

Available as part of the Tidelift Subscription.

The maintainers of `ansi-styles` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-ansi-styles?utm_source=npm-ansi-styles&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)


code:
Copyright Mathias Bynens <https://mathiasbynens.be/>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


code:
# emoji-regex [![Build status](https://github.com/mathiasbynens/emoji-regex/actions/workflows/main.yml/badge.svg)](https://github.com/mathiasbynens/emoji-regex/actions/workflows/main.yml) [![emoji-regex on npm](https://img.shields.io/npm/v/emoji-regex)](https://www.npmjs.com/package/emoji-regex)

_emoji-regex_ offers a regular expression to match all emoji symbols and sequences (including textual representations of emoji) as per the Unicode Standard. It’s based on [_emoji-test-regex-pattern_](https://github.com/mathiasbynens/emoji-test-regex-pattern), which generates (at build time) the regular expression pattern based on the Unicode Standard. As a result, _emoji-regex_ can easily be updated whenever new emoji are added to Unicode.

Since each version of _emoji-regex_ is tied to the latest Unicode version at the time of release, results are deterministic. This is important for use cases like image replacement, where you want to guarantee that an image asset is available for every possibly matched emoji. If you don’t need a deterministic regex, a lighter-weight, general emoji pattern is available via the [_emoji-regex-xs_](https://github.com/slevithan/emoji-regex-xs) package that follows the same API.

## Installation

Via [npm](https://www.npmjs.com/):

```bash
npm install emoji-regex
```

In [Node.js](https://nodejs.org/):

```js
const emojiRegex = require('emoji-regex');
// Note: because the regular expression has the global flag set, this module
// exports a function that returns the regex rather than exporting the regular
// expression itself, to make it impossible to (accidentally) mutate the
// original regular expression.

const text = `
\u{231A}: ⌚ default emoji presentation character (Emoji_Presentation)
\u{2194}\u{FE0F}: ↔ default text presentation character rendered as emoji
\u{1F469}: 👩 emoji modifier base (Emoji_Modifier_Base)
\u{1F469}\u{1F3FF}: 👩🏿 emoji modifier base followed by a modifier
`;

const regex = emojiRegex();
for (const match of text.matchAll(regex)) {
  const emoji = match[0];
  console.log(`Matched sequence ${ emoji } — code points: ${ [...emoji].length }`);
}
```

Console output:

```
Matched sequence ⌚ — code points: 1
Matched sequence ⌚ — code points: 1
Matched sequence ↔ — code points: 2
Matched sequence ↔ — code points: 2
Matched sequence 👩 — code points: 1
Matched sequence 👩 — code points: 1
Matched sequence 👩🏿 — code points: 2
Matched sequence 👩🏿 — code points: 2
```

## For maintainers

### How to update emoji-regex after new Unicode Standard releases

1. [Update _emoji-test-regex-pattern_ as described in its repository](https://github.com/mathiasbynens/emoji-test-regex-pattern#how-to-update-emoji-test-regex-pattern-after-new-uts51-releases).

1. Bump the _emoji-test-regex-pattern_ dependency to the latest version.

1. Update the Unicode data dependency in `package.json` by running the following commands:

     ```sh
     # Example: updating from Unicode v13 to Unicode v14.
     npm uninstall @unicode/unicode-13.0.0
     npm install @unicode/unicode-14.0.0 --save-dev
     ````

 1. Generate the new output:

     ```sh
     npm run build
     ```

 1. Verify that tests still pass:

     ```sh
     npm test
     ```

### How to publish a new release

1. On the `main` branch, bump the emoji-regex version number in `package.json`:

    ```sh
    npm version patch -m 'Release v%s'
    ```

    Instead of `patch`, use `minor` or `major` [as needed](https://semver.org/).

    Note that this produces a Git commit + tag.

1. Push the release commit and tag:

    ```sh
    git push && git push --tags
    ```

    Our CI then automatically publishes the new release to npm.

## Author

| [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") |
|---|
| [Mathias Bynens](https://mathiasbynens.be/) |

## License

_emoji-regex_ is available under the [MIT](https://mths.be/mit) license.


code:
declare module 'emoji-regex' {
  export default function emojiRegex(): RegExp;
}


emoji-regex

description: A regular expression to match all Emoji-only symbols as per the Unicode Standard.

keywords:
unicode
regex
regexp
regular expressions
code points
symbols
characters
emoji

type: git

build: node script/build.js

test: mocha

test:watch: npm run test -- --watch