/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const INDENT = "  ";
import { describeList } from "./String.js";
function FormattedText(text, width = 120) {
  const structure = detectStructure(text);
  return formatBlock(structure, width);
}
var BlockKind = /* @__PURE__ */ ((BlockKind2) => {
  BlockKind2["Simple"] = "simple";
  BlockKind2["Bullet1"] = "-";
  BlockKind2["Bullet2"] = "\u2022";
  BlockKind2["Bullet3"] = "\u25E6";
  BlockKind2["Bullet4"] = "\u25AA";
  BlockKind2["Bullet5"] = "\u25CB";
  BlockKind2["Bullet6"] = "\u25CF";
  BlockKind2["Bullet7"] = "\u2023";
  BlockKind2["Bullet8"] = "\u2043";
  BlockKind2["Quote"] = ">";
  BlockKind2["Number"] = "number";
  BlockKind2["LowerAlpha"] = "alpha";
  BlockKind2["UpperAlpha"] = "ALPHA";
  BlockKind2["LowerRoman"] = "roman";
  BlockKind2["UpperRoman"] = "ROMAN";
  return BlockKind2;
})(BlockKind || {});
const Bullets = Object.entries(BlockKind).filter(([key]) => key.startsWith("Bullet")).map(([, value]) => value);
const enumTest = "(?:\\d+|[ivx]+|[a-z])\\.";
const listItemTest = new RegExp(`^(?:[${Bullets.join("")}]|${enumTest})\\s`, "i");
function looksLikeListItem(text) {
  return !!listItemTest.exec(text);
}
const Empty = {
  kind: "simple" /* Simple */,
  indentWidth: 0,
  entries: []
};
function detectBlock(text, breadcrumb) {
  const match = text.match(/^(\s*)(\S+)/);
  if (!match) {
    return;
  }
  const [, leadingSpace, marker] = match;
  const indent = leadingSpace.length;
  if (Bullets.includes(marker) || marker === ">" /* Quote */) {
    enterBlock(marker, indent);
    return;
  }
  if (detectEnumeration(/^\d+\.$/, "1", "number" /* Number */)) return;
  if (detectEnumeration(/^[ivx]+\.$/, "i", "roman" /* LowerRoman */)) return;
  if (detectEnumeration(/^[IVX]+\.$/, "I", "ROMAN" /* UpperRoman */)) return;
  if (detectEnumeration(/^[a-z]+\.$/, "a", "alpha" /* LowerAlpha */)) return;
  if (detectEnumeration(/^[A-Z]+\.$/, "A", "ALPHA" /* UpperAlpha */)) return;
  breadcrumb.length = 1;
  function enterBlock(kind, sourceIndent) {
    if (sourceIndent !== void 0 && kind === "-" /* Bullet1 */) {
      let matchLevel = -1;
      for (let i = breadcrumb.length - 1; i >= 0; i--) {
        if (breadcrumb[i].kind === kind) {
          if (breadcrumb[i].sourceIndent !== void 0 && breadcrumb[i].sourceIndent <= sourceIndent) {
            matchLevel = i;
            if (breadcrumb[i].sourceIndent === sourceIndent) {
              breadcrumb.length = matchLevel + 1;
              return;
            }
            break;
          }
        }
      }
      if (matchLevel === -1) {
        for (let i = 0; i < breadcrumb.length; i++) {
          if (breadcrumb[i].kind === kind) {
            breadcrumb.length = i + 1;
            return;
          }
        }
      }
    } else {
      const level = breadcrumb.findIndex((entry) => entry.kind === kind);
      if (level !== -1) {
        breadcrumb.length = level + 1;
        return;
      }
    }
    const block = {
      kind,
      indentWidth: (breadcrumb[breadcrumb.length - 1]?.indentWidth ?? 0) + kind === ">" /* Quote */ ? 0 : 2,
      sourceIndent,
      entries: []
    };
    breadcrumb[breadcrumb.length - 1].entries.push(block);
    breadcrumb.push(block);
  }
  function detectEnumeration(test, startsWith, kind) {
    if (!marker.match(test)) {
      return false;
    }
    if (!breadcrumb.find((block) => block.kind === kind)) {
      if (marker !== `${startsWith}.`) {
        return false;
      }
    }
    enterBlock(kind);
    return true;
  }
}
function detectStructure(text) {
  const lines = text.split(/\n+/).map((line) => line.trimEnd());
  if (!lines.some((p) => p)) {
    return Empty;
  }
  const breadcrumb = [{ ...Empty, entries: [] }];
  for (const line of lines) {
    detectBlock(line, breadcrumb);
    breadcrumb[breadcrumb.length - 1].entries.push(line.trim().replace(/\s+/g, " "));
  }
  return breadcrumb[0];
}
function wrapParagraph(input, into, wrapWidth, initialPrefix, wrapPrefix) {
  const prefixWidth = visibleWidthOf(initialPrefix);
  const segments = input.split(/\s+/);
  if (!segments) {
    return;
  }
  for (let i = 0; i < segments?.length; i++) {
    if (!segments[i].includes("{@")) {
      continue;
    }
    for (let j = i; j < segments.length; j++) {
      if (segments[j].includes("}")) {
        segments.splice(i, j - i + 1, segments.slice(i, j + 1).join(" "));
        break;
      }
    }
  }
  const line = [initialPrefix];
  let width = prefixWidth;
  let pushedOne = false;
  for (const s of segments) {
    const segmentWidth = visibleWidthOf(s);
    if (width && width + segmentWidth > wrapWidth) {
      addLine();
      line.length = 0;
      width = prefixWidth;
    }
    if (!line.length) {
      line.push(wrapPrefix);
      width = prefixWidth;
    }
    line.push(s);
    line.push(" ");
    width += segmentWidth + 1;
  }
  line.length = line.length - 1;
  if (line.length) {
    addLine();
  }
  function addLine() {
    if (!pushedOne) {
      if (into.length) {
        into.push("");
      }
      pushedOne = true;
    }
    into.push(line.join(""));
  }
}
function separatePrefixFromContent(text) {
  const match = text.match(/^(\S+\s)\s*(\S.*$)/);
  if (match) {
    return { prefix: match[1], text: match[2] };
  }
  return { prefix: "", text };
}
function formatBlock(block, width) {
  const lines = Array();
  function formatLevel(block2, parentPrefix) {
    for (const entry of block2.entries) {
      if (typeof entry === "string") {
        let prefix, text;
        if (block2.kind === "simple" /* Simple */) {
          prefix = "";
          text = entry;
        } else {
          ({ prefix, text } = separatePrefixFromContent(entry));
        }
        wrapParagraph(
          text,
          lines,
          width,
          parentPrefix + prefix,
          parentPrefix + " ".repeat(visibleWidthOf(prefix))
        );
      } else {
        let childPrefix = parentPrefix;
        if (entry.kind !== ">" /* Quote */ || parentPrefix !== "") {
          childPrefix += INDENT;
        }
        formatLevel(entry, childPrefix);
      }
    }
  }
  formatLevel(block, "");
  return lines;
}
function visibleWidthOf(text) {
  let length = 0;
  for (let i = 0; i < text.length; ) {
    switch (text[i]) {
      case `\x1B`:
        i++;
        const code = text[i];
        if (code >= "@" && code <= "Z" || code === "-" || code === "_") {
          i++;
          break;
        }
        if (code === "[") {
          i++;
          while (text[i] >= "0" && text[i] <= "?") {
            i++;
          }
          while (text[i] >= " " && text[i] <= "/") {
            i++;
          }
          if (text[i] >= "@" && text[i] <= "~") {
            i++;
            break;
          }
        }
        break;
      case `\u200B`:
        i++;
        break;
      default:
        i++;
        length++;
        break;
    }
  }
  return length;
}
export {
  BlockKind,
  Bullets,
  FormattedText,
  describeList,
  looksLikeListItem
};
//# sourceMappingURL=FormattedText.js.map
