{"version":3,"file":"guessit-js.cjs","sources":["../node_modules/rebulk-js/dist/rebulk-js.js","../src/rules/markers/path.ts","../src/rules/markers/groups.ts","../src/reutils.ts","../src/rules/common/numeral.ts","../src/rules/common/index.ts","../src/rules/common/validators.ts","../src/rules/common/diacritics.ts","../src/rules/common/formatters.ts","../src/rules/common/pattern.ts","../src/rules/properties/episodes.ts","../src/rules/properties/container.ts","../src/rules/properties/source.ts","../src/rules/properties/video_codec.ts","../src/config/index.ts","../src/rules/properties/audio_codec.ts","../src/rules/common/quantity.ts","../src/rules/properties/screen_size.ts","../src/data/tlds.ts","../src/rules/properties/website.ts","../src/rules/common/date.ts","../src/rules/properties/date.ts","../src/rules/common/comparators.ts","../src/rules/common/expected.ts","../src/rules/properties/title.ts","../src/rules/properties/episode_title.ts","../src/language/data.ts","../src/language/index.ts","../src/rules/common/words.ts","../src/rules/properties/language.ts","../src/rules/properties/country.ts","../src/rules/properties/release_group.ts","../src/rules/properties/streaming_service.ts","../src/rules/properties/other.ts","../src/rules/properties/size.ts","../src/rules/properties/bit_rate.ts","../src/rules/properties/edition.ts","../src/rules/properties/cd.ts","../src/rules/properties/bonus.ts","../src/rules/properties/film.ts","../src/rules/properties/part.ts","../src/rules/properties/crc.ts","../src/rules/properties/imdb.ts","../src/rules/properties/volume.ts","../src/rules/properties/mimetype.ts","../src/rules/properties/type.ts","../src/rules/processors.ts","../src/rules/index.ts","../src/options.ts","../src/schema.ts","../src/api.ts","../src/index.ts"],"sourcesContent":["function defaultFormatter(value) {\n  return value;\n}\nfunction formatters(...fns) {\n  return (value) => {\n    let result = value;\n    for (const fn of fns) {\n      result = fn(result);\n    }\n    return result;\n  };\n}\nfunction call(fn, ...args) {\n  if (fn.length > 0 && args.length > fn.length) {\n    return fn(...args.slice(0, fn.length));\n  }\n  return fn(...args);\n}\nfunction ensureList(param) {\n  if (!param) return [];\n  if (Array.isArray(param)) return param;\n  return [param];\n}\nfunction ensureDict(param, defaultValue, defaultKey = null) {\n  if (!param) {\n    param = defaultValue;\n  }\n  if (typeof param !== \"object\" || param === null || Array.isArray(param)) {\n    if (param) {\n      defaultValue = param;\n    }\n    const key = defaultKey ?? void 0;\n    return [{ [key]: param }, defaultValue];\n  }\n  const asObj = param;\n  return [asObj, defaultValue];\n}\nfunction filterIndex(collection, predicate, index) {\n  if (typeof predicate === \"number\") {\n    index = predicate;\n    predicate = null;\n  }\n  let result = predicate ? collection.filter(predicate) : [...collection];\n  if (index !== null && index !== void 0) {\n    if (index < 0) return result[result.length + index];\n    return result[index];\n  }\n  return result;\n}\nfunction setDefaults(defaults, kwargs, override = false) {\n  if (\"clear\" in defaults && defaults[\"clear\"]) {\n    for (const key of Object.keys(kwargs)) delete kwargs[key];\n    delete defaults[\"clear\"];\n  }\n  for (const [key, value] of Object.entries(defaults)) {\n    if (key in kwargs) {\n      if (Array.isArray(value) && Array.isArray(kwargs[key])) {\n        kwargs[key] = [...value, ...kwargs[key]];\n        continue;\n      }\n      if (value && typeof value === \"object\" && !Array.isArray(value) && kwargs[key] && typeof kwargs[key] === \"object\" && !Array.isArray(kwargs[key])) {\n        setDefaults(value, kwargs[key]);\n        continue;\n      }\n    }\n    if (!(key in kwargs) || override) {\n      kwargs[key] = value;\n    }\n  }\n}\nfunction isIterable(obj) {\n  if (obj === null || obj === void 0) return false;\n  if (typeof obj === \"string\") return false;\n  return typeof obj[Symbol.iterator] === \"function\";\n}\nfunction* findAll(string, sub, start = 0, end, ignoreCase = false) {\n  let haystack = string;\n  let needle = sub;\n  if (ignoreCase) {\n    haystack = haystack.toLowerCase();\n    needle = needle.toLowerCase();\n  }\n  const limit = end !== void 0 ? end : haystack.length;\n  let idx = start;\n  while (true) {\n    const found = haystack.indexOf(needle, idx);\n    if (found === -1 || found >= limit) return;\n    yield found;\n    idx = found + needle.length;\n  }\n}\nfunction getFirstDefined(data, keys, defaultValue = void 0) {\n  for (const key of keys) {\n    if (key !== null && key !== void 0 && key in data) {\n      return data[key];\n    }\n  }\n  return defaultValue;\n}\nfunction extendSafe(target, source) {\n  for (const elt of source) {\n    if (!target.includes(elt)) {\n      target.push(elt);\n    }\n  }\n}\nclass IdentitySet {\n  _map = /* @__PURE__ */ new Map();\n  constructor(items) {\n    if (items) {\n      for (const item of items) this.add(item);\n    }\n  }\n  add(value) {\n    this._map.set(value, true);\n    return this;\n  }\n  delete(value) {\n    return this._map.delete(value);\n  }\n  has(value) {\n    return this._map.has(value);\n  }\n  get size() {\n    return this._map.size;\n  }\n  [Symbol.iterator]() {\n    return this._map.keys();\n  }\n}\nfunction alwaysTrue(_match) {\n  return true;\n}\nfunction charsBefore(chars, match) {\n  if (!match.inputString) return true;\n  const idx = match.start - 1;\n  if (idx < 0) return true;\n  return chars.includes(match.inputString[idx]);\n}\nfunction charsAfter(chars, match) {\n  if (!match.inputString) return true;\n  const idx = match.end;\n  if (idx >= match.inputString.length) return true;\n  return chars.includes(match.inputString[idx]);\n}\nfunction charsSurround(chars, match) {\n  return charsBefore(chars, match) && charsAfter(chars, match);\n}\nfunction validators(...chainedValidators) {\n  return (match) => chainedValidators.every((v) => v(match));\n}\nlet DEBUG = false;\nlet LOG_LEVEL = 10;\nfunction frameRepr(frame) {\n  const basename = frame.filename.split(\"/\").pop() ?? frame.filename;\n  return `${basename}#L${frame.lineno}`;\n}\nfunction definedAt() {\n  if (!DEBUG) return void 0;\n  const err = new Error();\n  const stack = err.stack;\n  if (!stack) return void 0;\n  const lines = stack.split(\"\\n\").slice(1);\n  for (const line of lines) {\n    if (line.includes(\"/src/\") && (line.includes(\"/rebulk-js/src/\") || line.includes(\"/rebulk-js/dist/\"))) {\n      continue;\n    }\n    const match = line.match(/at\\s+(?:(.+?)\\s+)?\\(?(.+?):(\\d+):\\d+\\)?/);\n    if (match) {\n      return {\n        lineno: parseInt(match[3], 10),\n        package_: void 0,\n        name: match[1] || void 0,\n        filename: match[2]\n      };\n    }\n  }\n  return void 0;\n}\nfunction setDebug(value) {\n  DEBUG = value;\n}\nfunction setLogLevel(value) {\n  LOG_LEVEL = value;\n}\nclass Match {\n  start;\n  end;\n  name;\n  tags;\n  marker;\n  private;\n  inputString;\n  formatter;\n  pattern;\n  parent;\n  conflictSolver;\n  defined_at;\n  /** Index within the sequence of matches produced by the same pattern. */\n  matchIndex = 0;\n  _value;\n  _children;\n  _rawStart;\n  _rawEnd;\n  constructor(start, end, opts = {}) {\n    this.start = start;\n    this.end = end;\n    this.name = opts.name;\n    this.tags = ensureList(opts.tags);\n    this.marker = opts.marker ?? false;\n    this.private = opts.private ?? false;\n    this.inputString = opts.inputString;\n    this.formatter = opts.formatter;\n    this._value = opts.value;\n    this.conflictSolver = opts.conflictSolver;\n    this.pattern = opts.pattern;\n    this.parent = opts.parent;\n    this.defined_at = opts.pattern ? opts.pattern.defined_at : definedAt();\n  }\n  get span() {\n    return [this.start, this.end];\n  }\n  get rawStart() {\n    return this._rawStart !== void 0 ? this._rawStart : this.start;\n  }\n  set rawStart(v) {\n    this._rawStart = v;\n  }\n  get rawEnd() {\n    return this._rawEnd !== void 0 ? this._rawEnd : this.end;\n  }\n  set rawEnd(v) {\n    this._rawEnd = v;\n  }\n  get raw() {\n    if (this.inputString !== void 0) {\n      return this.inputString.slice(this.rawStart, this.rawEnd);\n    }\n    return void 0;\n  }\n  get value() {\n    if (this._value) return this._value;\n    if (this.formatter && typeof this.formatter === \"function\") return this.formatter(this.raw ?? \"\");\n    return this.raw;\n  }\n  set value(v) {\n    this._value = v;\n  }\n  get children() {\n    if (!this._children) {\n      this._children = new Matches(void 0, this.inputString);\n    }\n    return this._children;\n  }\n  set children(v) {\n    this._children = v;\n  }\n  /** All property names in this match (recursing into children). */\n  get names() {\n    if (!this._children || this._children.length === 0) {\n      return this.name ? /* @__PURE__ */ new Set([this.name]) : /* @__PURE__ */ new Set();\n    }\n    const ret = /* @__PURE__ */ new Set();\n    for (const child of this._children) {\n      for (const n of child.names) ret.add(n);\n    }\n    return ret;\n  }\n  /** Walk up to the root (top-most parent). */\n  get initiator() {\n    let m = this;\n    while (m.parent) m = m.parent;\n    return m;\n  }\n  get length() {\n    return this.end - this.start;\n  }\n  /** Check if this match has at least one of the given tags. */\n  tagged(...tags) {\n    return tags.some((t) => this.tags.includes(t));\n  }\n  /** Check if any child (recursive) has one of the given names. */\n  named(...names) {\n    return names.some((n) => this.names.has(n));\n  }\n  /**\n   * Crop this match with the given spans/matches.\n   * Returns a list of Match fragments after subtracting the crop regions.\n   */\n  crop(crops, predicate, index) {\n    const cropsArr = Array.isArray(crops) && crops.length === 2 && typeof crops[0] === \"number\" ? [crops] : Array.isArray(crops) ? crops : [crops];\n    const initial = this._clone();\n    let ret = [initial];\n    for (const crop of cropsArr) {\n      const [cStart, cEnd] = \"span\" in crop ? crop.span : crop;\n      for (const current of [...ret]) {\n        if (cStart <= current.start && cEnd >= current.end) {\n          ret.splice(ret.indexOf(current), 1);\n        } else if (cStart >= current.start && cEnd <= current.end) {\n          const right = current._clone();\n          current.end = cStart;\n          if (current.length === 0) ret.splice(ret.indexOf(current), 1);\n          right.start = cEnd;\n          if (right.length > 0) ret.push(right);\n        } else if (current.end >= cEnd && cEnd > current.start) {\n          current.start = cEnd;\n        } else if (current.start <= cStart && cStart < current.end) {\n          current.end = cStart;\n        }\n      }\n    }\n    return filterIndex(ret, predicate ?? null, index ?? null);\n  }\n  /**\n   * Split this match into multiple matches at each separator character.\n   */\n  split(seps, predicate, index) {\n    const ret = [];\n    let currentStart = null;\n    for (let i = 0; i < (this.raw?.length ?? 0); i++) {\n      const char = this.raw[i];\n      if (seps.includes(char)) {\n        if (currentStart !== null) {\n          const m = this._clone();\n          m.start = this.start + currentStart;\n          m.end = this.start + i;\n          ret.push(m);\n          currentStart = null;\n        }\n      } else {\n        if (currentStart === null) currentStart = i;\n      }\n    }\n    if (currentStart !== null) {\n      const m = this._clone();\n      m.start = this.start + currentStart;\n      ret.push(m);\n    }\n    return filterIndex(ret, predicate ?? null, index ?? null);\n  }\n  clone() {\n    return this._clone();\n  }\n  _clone() {\n    const m = new Match(this.start, this.end, {\n      name: this.name,\n      tags: [...this.tags],\n      marker: this.marker,\n      private: this.private,\n      inputString: this.inputString,\n      formatter: this.formatter,\n      value: this._value,\n      conflictSolver: this.conflictSolver,\n      pattern: this.pattern,\n      parent: this.parent\n    });\n    m.matchIndex = this.matchIndex;\n    m._rawStart = this._rawStart;\n    m._rawEnd = this._rawEnd;\n    return m;\n  }\n  /** Equality by span, value, name, parent identity. */\n  equals(other) {\n    return this.start === other.start && this.end === other.end && this.value === other.value && this.name === other.name && this.parent === other.parent;\n  }\n  toString() {\n    let flags = \"\";\n    const initiatorVal = this.initiator.value;\n    if (initiatorVal !== this.value) flags += `+initiator=${String(initiatorVal)}`;\n    if (this.private) flags += \"+private\";\n    const name = this.name ? `+name=${this.name}` : \"\";\n    const tags = this.tags.length ? `+tags=${JSON.stringify(this.tags)}` : \"\";\n    const defined = this.defined_at ? `@${this.defined_at.filename.split(\"/\").pop()}#L${this.defined_at.lineno}` : \"\";\n    return `<${String(this.value)}:(${this.start}, ${this.end})${flags}${name}${tags}${defined}>`;\n  }\n}\nclass MatchesDict extends Map {\n  /** Keyed by property name → all Match objects for that name. */\n  matches = /* @__PURE__ */ new Map();\n  /** Keyed by property name → unique values (de-duped). */\n  valuesList = /* @__PURE__ */ new Map();\n}\nclass _BaseMatches {\n  inputString;\n  _delegate = [];\n  _maxEnd = 0;\n  // Lazy lookup caches (null = not yet built)\n  _nameDict = null;\n  _tagDict = null;\n  _startDict = null;\n  _endDict = null;\n  _indexDict = null;\n  constructor(matches, inputString) {\n    this.inputString = inputString;\n    if (matches) this.extend(matches);\n  }\n  get length() {\n    return this._delegate.length;\n  }\n  [Symbol.iterator]() {\n    return this._delegate[Symbol.iterator]();\n  }\n  toArray() {\n    return [...this._delegate];\n  }\n  /** All matches as an array. Ported Python code reads `matches.matches` — without\n   *  this getter that silently evaluated to undefined and turned rules into no-ops. */\n  get matches() {\n    return [...this._delegate];\n  }\n  // ── Cache accessors ──────────────────────────────────────────────────────\n  get nameDict() {\n    if (!this._nameDict) {\n      this._nameDict = /* @__PURE__ */ new Map();\n      for (const m of this._delegate) {\n        if (m.name) {\n          const arr = this._nameDict.get(m.name) ?? [];\n          arr.push(m);\n          this._nameDict.set(m.name, arr);\n        }\n      }\n    }\n    return this._nameDict;\n  }\n  get startDict() {\n    if (!this._startDict) {\n      this._startDict = /* @__PURE__ */ new Map();\n      for (const m of this._delegate) {\n        const arr = this._startDict.get(m.start) ?? [];\n        arr.push(m);\n        this._startDict.set(m.start, arr);\n      }\n    }\n    return this._startDict;\n  }\n  get endDict() {\n    if (!this._endDict) {\n      this._endDict = /* @__PURE__ */ new Map();\n      for (const m of this._delegate) {\n        const arr = this._endDict.get(m.end) ?? [];\n        arr.push(m);\n        this._endDict.set(m.end, arr);\n      }\n    }\n    return this._endDict;\n  }\n  get tagDict() {\n    if (!this._tagDict) {\n      this._tagDict = /* @__PURE__ */ new Map();\n      for (const m of this._delegate) {\n        for (const tag of m.tags) {\n          const arr = this._tagDict.get(tag) ?? [];\n          arr.push(m);\n          this._tagDict.set(tag, arr);\n        }\n      }\n    }\n    return this._tagDict;\n  }\n  get indexDict() {\n    if (!this._indexDict) {\n      this._indexDict = /* @__PURE__ */ new Map();\n      for (const m of this._delegate) {\n        for (let i = m.start; i < m.end; i++) {\n          const arr = this._indexDict.get(i) ?? [];\n          arr.push(m);\n          this._indexDict.set(i, arr);\n        }\n      }\n    }\n    return this._indexDict;\n  }\n  get maxEnd() {\n    return this.inputString ? Math.max(this.inputString.length, this._maxEnd) : this._maxEnd;\n  }\n  // ── Mutations ─────────────────────────────────────────────────────────────\n  _addMatch(match) {\n    if (this._nameDict && match.name) {\n      const arr = this._nameDict.get(match.name) ?? [];\n      arr.push(match);\n      this._nameDict.set(match.name, arr);\n    }\n    if (this._tagDict) {\n      for (const tag of match.tags) {\n        const arr = this._tagDict.get(tag) ?? [];\n        arr.push(match);\n        this._tagDict.set(tag, arr);\n      }\n    }\n    if (this._startDict) {\n      const arr = this._startDict.get(match.start) ?? [];\n      arr.push(match);\n      this._startDict.set(match.start, arr);\n    }\n    if (this._endDict) {\n      const arr = this._endDict.get(match.end) ?? [];\n      arr.push(match);\n      this._endDict.set(match.end, arr);\n    }\n    if (this._indexDict) {\n      for (let i = match.start; i < match.end; i++) {\n        const arr = this._indexDict.get(i) ?? [];\n        arr.push(match);\n        this._indexDict.set(i, arr);\n      }\n    }\n    if (match.end > this._maxEnd) this._maxEnd = match.end;\n  }\n  _removeMatch(match) {\n    if (this._nameDict && match.name) {\n      const arr = this._nameDict.get(match.name);\n      if (arr) {\n        const idx = arr.findIndex((m) => m === match);\n        if (idx !== -1) arr.splice(idx, 1);\n      }\n    }\n    if (this._tagDict) {\n      for (const tag of match.tags) {\n        const arr = this._tagDict.get(tag);\n        if (arr) {\n          const idx = arr.findIndex((m) => m === match);\n          if (idx !== -1) arr.splice(idx, 1);\n        }\n      }\n    }\n    if (this._startDict) {\n      const arr = this._startDict.get(match.start);\n      if (arr) {\n        const idx = arr.findIndex((m) => m === match);\n        if (idx !== -1) arr.splice(idx, 1);\n      }\n    }\n    if (this._endDict) {\n      const arr = this._endDict.get(match.end);\n      if (arr) {\n        const idx = arr.findIndex((m) => m === match);\n        if (idx !== -1) arr.splice(idx, 1);\n      }\n    }\n    if (this._indexDict) {\n      for (let i = match.start; i < match.end; i++) {\n        const arr = this._indexDict.get(i);\n        if (arr) {\n          const idx = arr.findIndex((m) => m === match);\n          if (idx !== -1) arr.splice(idx, 1);\n        }\n      }\n    }\n    if (match.end >= this._maxEnd) {\n      this._maxEnd = 0;\n      for (const m of this._delegate) {\n        if (m.end > this._maxEnd) this._maxEnd = m.end;\n      }\n    }\n  }\n  append(match) {\n    this._delegate.push(match);\n    this._addMatch(match);\n  }\n  extend(matches) {\n    for (const m of matches) this.append(m);\n  }\n  remove(match) {\n    const idx = this._delegate.findIndex((m) => m === match);\n    if (idx !== -1) {\n      this._delegate.splice(idx, 1);\n      this._removeMatch(match);\n    }\n  }\n  includes(match) {\n    return this._delegate.some((m) => m === match || m.equals(match));\n  }\n  at(index) {\n    return this._delegate[index];\n  }\n  get(index) {\n    return this._delegate[index];\n  }\n  clear() {\n    this._delegate.length = 0;\n    this._nameDict = null;\n    this._tagDict = null;\n    this._startDict = null;\n    this._endDict = null;\n    this._indexDict = null;\n    this._maxEnd = 0;\n  }\n  slice(start, end) {\n    return new Matches(this._delegate.slice(start, end), this.inputString);\n  }\n  deleteSlice(start, end) {\n    const removed = this._delegate.splice(start, end - start);\n    for (const m of removed) this._removeMatch(m);\n  }\n  setSlice(start, end, ...items) {\n    const removed = this._delegate.splice(start, end - start, ...items);\n    for (const m of removed) this._removeMatch(m);\n    for (const m of items) this._addMatch(m);\n  }\n  setAt(index, match) {\n    const old = this._delegate[index];\n    if (old) this._removeMatch(old);\n    this._delegate[index] = match;\n    this._addMatch(match);\n  }\n  insert(index, match) {\n    this._delegate.splice(index, 0, match);\n    this._addMatch(match);\n  }\n  sort() {\n    return [...this._delegate].sort((a, b) => {\n      if (a.start !== b.start) return a.start - b.start;\n      return a.end - b.end;\n    });\n  }\n  named(name, predicate, index) {\n    const arr = this.nameDict.get(name) ?? [];\n    return filterIndex(arr, predicate, index);\n  }\n  tagged(tag, predicate, index) {\n    const arr = this.tagDict.get(tag) ?? [];\n    return filterIndex(arr, predicate, index);\n  }\n  starting(start, predicate, index) {\n    const arr = this.startDict.get(start) ?? [];\n    return filterIndex(arr, predicate, index);\n  }\n  ending(end, predicate, index) {\n    const arr = this.endDict.get(end) ?? [];\n    return filterIndex(arr, predicate, index);\n  }\n  atIndex(pos, predicate, index) {\n    const arr = this.indexDict.get(pos) ?? [];\n    return filterIndex(arr, predicate, index);\n  }\n  atSpan(span, predicate, index) {\n    const starting = this.indexDict.get(span[0]) ?? [];\n    const ending = this.indexDict.get(span[1] - 1) ?? [];\n    const merged = [...starting];\n    for (const m of ending) {\n      if (!merged.includes(m)) merged.push(m);\n    }\n    return filterIndex(merged, predicate, index);\n  }\n  atMatch(match, predicate, index) {\n    return this.atSpan(match.span, predicate, index);\n  }\n  range(start = 0, end, predicate, index) {\n    const limit = end !== void 0 ? Math.min(this.maxEnd, end) : this.maxEnd;\n    const ret = [];\n    for (const m of this.sort()) {\n      if (m.start < limit && m.end > start) {\n        if (!predicate || predicate(m)) ret.push(m);\n      }\n    }\n    return filterIndex(ret, null, index);\n  }\n  /** Nearest match ending just before (or at) `match.start`. */\n  previous(match, predicate, index) {\n    let current = match.start;\n    while (current > -1) {\n      const prev = this.ending(current);\n      if (prev.length > 0) return filterIndex(prev, predicate, index);\n      current--;\n    }\n    return filterIndex([], predicate, index);\n  }\n  /** Nearest match starting after `match.start`. */\n  next(match, predicate, index) {\n    let current = match.start + 1;\n    while (current <= this.maxEnd) {\n      const nxt = this.starting(current);\n      if (nxt.length > 0) return filterIndex(nxt, predicate, index);\n      current++;\n    }\n    return filterIndex([], predicate, index);\n  }\n  /** All matches that overlap with `match`. */\n  conflicting(match, predicate, index) {\n    const ret = [];\n    const seen = /* @__PURE__ */ new Set();\n    for (let i = match.start; i < match.end; i++) {\n      for (const m of this.indexDict.get(i) ?? []) {\n        if (m !== match && !seen.has(m)) {\n          seen.add(m);\n          ret.push(m);\n        }\n      }\n    }\n    return filterIndex(ret, predicate, index);\n  }\n  /** Matches chained before `position` separated only by chars in `seps`. */\n  chainBefore(position, seps, start = 0, predicate, index) {\n    const pos = typeof position === \"number\" ? position : position.start;\n    const chain = [];\n    for (let i = Math.min(this.maxEnd, pos) - 1; i >= start; i--) {\n      const atI = this.indexDict.get(i) ?? [];\n      const filtered = predicate ? atI.filter(predicate) : [...atI];\n      if (filtered.length > 0) {\n        for (const m of filtered) {\n          if (!chain.includes(m)) chain.push(m);\n        }\n      } else if (!this.inputString || !seps.includes(this.inputString[i])) {\n        break;\n      }\n    }\n    return filterIndex(chain, null, index);\n  }\n  /** Matches chained after `position` separated only by chars in `seps`. */\n  chainAfter(position, seps, end, predicate, index) {\n    const pos = typeof position === \"number\" ? position : position.end;\n    const limit = end !== void 0 ? Math.min(this.maxEnd, end) : this.maxEnd;\n    const chain = [];\n    for (let i = pos; i < limit; i++) {\n      const atI = this.indexDict.get(i) ?? [];\n      const filtered = predicate ? atI.filter(predicate) : [...atI];\n      if (filtered.length > 0) {\n        for (const m of filtered) {\n          if (!chain.includes(m)) chain.push(m);\n        }\n      } else if (!this.inputString || !seps.includes(this.inputString[i])) {\n        break;\n      }\n    }\n    return filterIndex(chain, null, index);\n  }\n  /** All \"hole\" matches (gaps not covered by any existing match). */\n  holes(start = 0, end, opts = {}) {\n    const { formatter, ignore, seps, predicate, index } = opts;\n    const limit = end !== void 0 ? Math.min(this.maxEnd, end) : this.maxEnd;\n    const ret = [];\n    let hole = false;\n    let loopStart = 0;\n    for (let i = start - 1; i >= 0; i--) {\n      const startingMatches = this.starting(i);\n      let found = false;\n      for (const m of startingMatches) {\n        if (!ignore || !ignore(m)) {\n          loopStart = i;\n          found = true;\n          break;\n        }\n      }\n      if (found) break;\n    }\n    for (let rindex = loopStart; rindex < limit; rindex++) {\n      const atI = this.indexDict.get(rindex) ?? [];\n      const current = ignore ? atI.filter((m) => !ignore(m)) : [...atI];\n      if (seps && hole && this.inputString && seps.includes(this.inputString[rindex])) {\n        hole = false;\n        ret[ret.length - 1].end = rindex;\n      } else {\n        if (current.length === 0 && !hole) {\n          hole = true;\n          ret.push(new Match(Math.max(rindex, start), 0, { inputString: this.inputString, formatter }));\n        } else if (current.length > 0 && hole) {\n          hole = false;\n          ret[ret.length - 1].end = rindex;\n        }\n      }\n    }\n    if (ret.length > 0 && hole) {\n      let holeEnd = this.maxEnd;\n      const lastRindex = limit > loopStart ? limit - 1 : loopStart;\n      for (let ri = lastRindex; ri < this.maxEnd; ri++) {\n        const startingMatches = this.starting(ri);\n        let found = false;\n        for (const m of startingMatches) {\n          if (!ignore || !ignore(m)) {\n            holeEnd = ri;\n            found = true;\n            break;\n          }\n        }\n        if (found) break;\n      }\n      ret[ret.length - 1].end = Math.min(holeEnd, limit);\n    }\n    const validHoles = ret.filter((h) => h.end > h.start);\n    return filterIndex(validHoles, predicate ?? null, index ?? null);\n  }\n  /** All property names present. */\n  get names() {\n    return new Set(this.nameDict.keys());\n  }\n  /** All tags present. */\n  get allTags() {\n    return new Set(this.tagDict.keys());\n  }\n  /**\n   * Convert to a plain dict (like Python Matches.to_dict).\n   */\n  toDict(details = false, firstValue = false, enforceList = false) {\n    const ret = new MatchesDict();\n    for (const match of this.sort()) {\n      const val = details ? match : match.value;\n      const matchArr = ret.matches.get(match.name ?? \"\") ?? [];\n      matchArr.push(match);\n      ret.matches.set(match.name ?? \"\", matchArr);\n      const valEquals = (a, b) => details && a instanceof Match && b instanceof Match ? a.equals(b) : a === b;\n      if (!enforceList) {\n        const valArr = ret.valuesList.get(match.name ?? \"\") ?? [];\n        if (!valArr.some((v) => valEquals(v, val))) valArr.push(val);\n        ret.valuesList.set(match.name ?? \"\", valArr);\n      }\n      const existing = ret.get(match.name ?? \"\");\n      if (existing !== void 0) {\n        if (!firstValue) {\n          if (Array.isArray(existing)) {\n            if (!existing.some((v) => valEquals(v, val))) existing.push(val);\n          } else {\n            if (!valEquals(existing, val)) ret.set(match.name, [existing, val]);\n          }\n        }\n      } else {\n        ret.set(match.name, enforceList && !Array.isArray(val) ? [val] : val);\n      }\n    }\n    return ret;\n  }\n  toString() {\n    return `[${this._delegate.map(String).join(\", \")}]`;\n  }\n}\nclass Matches extends _BaseMatches {\n  markers;\n  constructor(matches, inputString) {\n    super(void 0, inputString);\n    this.markers = new Markers(void 0, inputString);\n    if (matches) this.extend(matches);\n  }\n  _addMatch(match) {\n    if (match.marker) throw new Error(\"A marker match should not be added to Matches\");\n    super._addMatch(match);\n  }\n}\nclass Markers extends _BaseMatches {\n  constructor(matches, inputString) {\n    super(void 0, inputString);\n    if (matches) this.extend(matches);\n  }\n  _addMatch(match) {\n    if (!match.marker) throw new Error(\"A non-marker match should not be added to Markers\");\n    super._addMatch(match);\n  }\n}\nfunction filterMatchKwargs(opts, children = false) {\n  const result = { ...opts };\n  delete result[\"pattern\"];\n  delete result[\"start\"];\n  delete result[\"end\"];\n  delete result[\"parent\"];\n  delete result[\"formatter\"];\n  delete result[\"value\"];\n  if (children) {\n    delete result[\"name\"];\n  }\n  return result;\n}\nfunction convertPythonNamedGroups(pattern) {\n  return pattern.replace(/\\(\\?P</g, \"(?<\");\n}\nfunction applyAbbreviations(pattern, abbreviations) {\n  let result = pattern;\n  for (const [key, replacement] of abbreviations) {\n    result = result.split(key).join(replacement);\n  }\n  return result;\n}\nfunction compileRegex(source, opts) {\n  let src = convertPythonNamedGroups(source);\n  if (opts.abbreviations) {\n    src = applyAbbreviations(src, opts.abbreviations);\n  }\n  let flagStr = opts.flags ?? \"\";\n  if (opts.ignoreCase && !flagStr.includes(\"i\")) flagStr += \"i\";\n  if (!flagStr.includes(\"g\")) flagStr += \"g\";\n  if (!flagStr.includes(\"d\")) flagStr += \"d\";\n  return new RegExp(src, flagStr);\n}\nfunction buildGroupNames(source) {\n  const names = [];\n  let i = 0;\n  while (i < source.length) {\n    if (source[i] === \"\\\\\") {\n      i += 2;\n      continue;\n    }\n    if (source[i] === \"[\") {\n      i++;\n      while (i < source.length && source[i] !== \"]\") {\n        if (source[i] === \"\\\\\") i++;\n        i++;\n      }\n      i++;\n      continue;\n    }\n    if (source[i] === \"(\") {\n      const next = source[i + 1];\n      if (next !== \"?\") {\n        names.push(void 0);\n      } else {\n        const next2 = source[i + 2];\n        if (next2 === \"<\") {\n          const next3 = source[i + 3];\n          if (next3 !== \"=\" && next3 !== \"!\") {\n            const nameEnd = source.indexOf(\">\", i + 3);\n            names.push(nameEnd !== -1 ? source.slice(i + 3, nameEnd) : void 0);\n          }\n        }\n      }\n    }\n    i++;\n  }\n  return names;\n}\nclass BasePattern {\n}\nclass Pattern extends BasePattern {\n  name;\n  tags;\n  formatters;\n  defaultFormatterFn;\n  values;\n  defaultValue;\n  validators;\n  defaultValidator;\n  children;\n  every;\n  private_;\n  privateNames;\n  ignoreNames;\n  privateParent;\n  privateChildren;\n  marker;\n  formatAll;\n  validateAll;\n  disabled;\n  logLevel;\n  properties_;\n  postProcessor;\n  preMatchProcessor;\n  postMatchProcessor;\n  defined_at;\n  _opts;\n  constructor(opts = {}) {\n    super();\n    this._opts = opts;\n    this.name = opts.name;\n    this.tags = ensureList(opts.tags);\n    const [formattersMap, defaultFmt] = ensureDict(opts.formatter, defaultFormatter);\n    this.formatters = formattersMap;\n    this.defaultFormatterFn = defaultFmt ?? defaultFormatter;\n    const [valuesMap, defaultVal] = ensureDict(opts.value, void 0);\n    this.values = valuesMap;\n    this.defaultValue = defaultVal;\n    const [validatorsMap, defaultValid] = ensureDict(opts.validator, alwaysTrue);\n    this.validators = validatorsMap;\n    this.defaultValidator = defaultValid ?? alwaysTrue;\n    this.every = opts.every ?? false;\n    this.children = opts.children ?? false;\n    this.private_ = opts.private ?? false;\n    this.privateNames = opts.privateNames ?? [];\n    this.ignoreNames = opts.ignoreNames ?? [];\n    this.privateParent = opts.privateParent ?? false;\n    this.privateChildren = opts.privateChildren ?? false;\n    this.marker = opts.marker ?? false;\n    this.formatAll = opts.formatAll ?? false;\n    this.validateAll = opts.validateAll ?? false;\n    const d = opts.disabled;\n    if (typeof d === \"function\") {\n      this.disabled = d;\n    } else if (typeof d === \"boolean\") {\n      this.disabled = () => d;\n    } else {\n      this.disabled = () => false;\n    }\n    this.logLevel = opts.logLevel ?? 0;\n    this.properties_ = opts.properties;\n    this.postProcessor = typeof opts.postProcessor === \"function\" ? opts.postProcessor : void 0;\n    this.preMatchProcessor = typeof opts.preMatchProcessor === \"function\" ? opts.preMatchProcessor : void 0;\n    this.postMatchProcessor = typeof opts.postMatchProcessor === \"function\" ? opts.postMatchProcessor : void 0;\n    this.defined_at = definedAt();\n  }\n  get shouldIncludeChildren() {\n    return this.children || this.every;\n  }\n  get shouldIncludeParent() {\n    return !this.children || this.every;\n  }\n  _matchConfigPropertyKeys(match, child = false) {\n    const keys = [];\n    if (match.name) keys.push(match.name);\n    keys.push(child ? \"__children__\" : \"__parent__\");\n    keys.push(null);\n    return keys;\n  }\n  _processMatchPrivate(match, child = false) {\n    if (match.name && this.privateNames.includes(match.name) || !child && this.privateParent || child && this.privateChildren) {\n      match.private = true;\n    }\n  }\n  _processMatchValue(match, child = false) {\n    const keys = this._matchConfigPropertyKeys(match, child);\n    const patternValue = getFirstDefined(this.values, keys, this.defaultValue);\n    if (patternValue !== void 0 && patternValue !== null) {\n      match.value = patternValue;\n    }\n  }\n  _processMatchFormatter(match, child = false) {\n    const included = child ? this.shouldIncludeChildren : this.shouldIncludeParent;\n    if (included || this.formatAll) {\n      const keys = this._matchConfigPropertyKeys(match, child);\n      match.formatter = getFirstDefined(this.formatters, keys, this.defaultFormatterFn);\n    }\n  }\n  _processMatchValidator(match, child = false) {\n    const included = child ? this.shouldIncludeChildren : this.shouldIncludeParent;\n    if (included || this.validateAll) {\n      const keys = this._matchConfigPropertyKeys(match, child);\n      const validator = getFirstDefined(this.validators, keys, this.defaultValidator);\n      if (validator && !validator(match)) return false;\n    }\n    return true;\n  }\n  _processMatch(match, matchIndex, child = false) {\n    match.matchIndex = matchIndex;\n    this._processMatchPrivate(match, child);\n    this._processMatchValue(match, child);\n    this._processMatchFormatter(match, child);\n    return this._processMatchValidator(match, child);\n  }\n  static _applyProcessor(match, processor) {\n    if (!processor) return match;\n    if (!match) return match;\n    const ret = processor(match);\n    return ret !== void 0 ? ret : match;\n  }\n  *_processMatches(match, matchIndex) {\n    const processed = Pattern._applyProcessor(match, this.preMatchProcessor);\n    if (!processed) return;\n    if (!this._processMatch(processed, matchIndex)) return;\n    for (const child of processed.children) {\n      if (!this._processMatch(child, matchIndex, true)) return;\n    }\n    const postProcessed = Pattern._applyProcessor(processed, this.postMatchProcessor);\n    if (!postProcessed) return;\n    if ((this.shouldIncludeParent || this.privateParent) && !this.ignoreNames.includes(postProcessed.name ?? \"\")) {\n      yield postProcessed;\n    }\n    if (this.shouldIncludeChildren || this.privateChildren) {\n      for (const child of postProcessed.children) {\n        if (!this.ignoreNames.includes(child.name ?? \"\")) yield child;\n      }\n    }\n  }\n  _postProcessMatches(matches) {\n    if (this.postProcessor) return this.postProcessor(matches, this);\n    return matches;\n  }\n  matches(inputString, context, withRawMatches = false) {\n    const allMatches = [];\n    const rawMatches = [];\n    for (const pattern of this.patterns) {\n      let matchIndex = 0;\n      for (const rawMatch of this._match(pattern, inputString, context)) {\n        rawMatches.push(rawMatch);\n        for (const m of this._processMatches(rawMatch, matchIndex)) {\n          allMatches.push(m);\n        }\n        matchIndex++;\n      }\n    }\n    const finalMatches = this._postProcessMatches(allMatches);\n    if (withRawMatches) return [finalMatches, rawMatches];\n    return finalMatches;\n  }\n  get properties() {\n    return this.properties_ ?? {};\n  }\n}\nclass StringPattern extends Pattern {\n  _patterns;\n  _matchKwargs;\n  constructor(firstArg, ...rest) {\n    if (typeof firstArg === \"string\") {\n      super({});\n      this._patterns = [firstArg, ...rest];\n      this._matchKwargs = filterMatchKwargs({});\n    } else {\n      super(firstArg);\n      this._patterns = rest;\n      this._matchKwargs = filterMatchKwargs(firstArg);\n    }\n  }\n  get patterns() {\n    return this._patterns;\n  }\n  get matchOptions() {\n    return this._matchKwargs;\n  }\n  *_match(pattern, inputString, _context) {\n    const ignoreCase = (this._opts.ignoreCase ?? false) || (this._opts.flags?.includes(\"i\") ?? false);\n    const searchStart = this._opts.start ?? 0;\n    const searchEnd = this._opts.end ?? void 0;\n    for (const idx of findAll(inputString, pattern, searchStart, searchEnd, ignoreCase)) {\n      const match = new Match(idx, idx + pattern.length, {\n        ...this._matchKwargs,\n        pattern: this,\n        inputString\n      });\n      if (match.length > 0) yield match;\n    }\n  }\n  toString() {\n    return `<StringPattern:(${this._patterns.map((p) => `'${p}'`).join(\", \")})>`;\n  }\n}\nclass RePattern extends Pattern {\n  _regexes;\n  _matchKwargs;\n  _childrenMatchKwargs;\n  _groupNamesList;\n  constructor(opts, ...patterns) {\n    super(opts);\n    this._matchKwargs = filterMatchKwargs(opts);\n    this._childrenMatchKwargs = filterMatchKwargs(opts, true);\n    this._regexes = [];\n    this._groupNamesList = [];\n    for (const p of patterns) {\n      if (p instanceof RegExp) {\n        this._regexes.push(p);\n        this._groupNamesList.push(buildGroupNames(p.source));\n      } else {\n        const compiled = compileRegex(p, {\n          flags: opts.flags,\n          ignoreCase: opts.ignoreCase,\n          abbreviations: opts.abbreviations\n        });\n        this._regexes.push(compiled);\n        this._groupNamesList.push(buildGroupNames(compiled.source));\n      }\n    }\n  }\n  get patterns() {\n    return this._regexes;\n  }\n  get matchOptions() {\n    return this._matchKwargs;\n  }\n  *_match(pattern, inputString, _context) {\n    const groupNames = this._groupNamesList[this._regexes.indexOf(pattern)] ?? [];\n    pattern.lastIndex = 0;\n    let m;\n    while ((m = pattern.exec(inputString)) !== null) {\n      const start = m.index;\n      const end = m.index + m[0].length;\n      const mainMatch = new Match(start, end, {\n        ...this._matchKwargs,\n        pattern: this,\n        inputString\n      });\n      if (groupNames.length > 0) {\n        const indices = m.indices;\n        for (let i = 0; i < groupNames.length; i++) {\n          const groupIdx = i + 1;\n          const name = groupNames[i] ?? this.name;\n          const groupIndices = indices?.[groupIdx];\n          if (groupIndices && groupIndices[0] !== -1) {\n            const [gs, ge] = groupIndices;\n            const childMatch = new Match(gs, ge, {\n              ...this._childrenMatchKwargs,\n              name,\n              parent: mainMatch,\n              pattern: this,\n              inputString\n            });\n            if (childMatch.length > 0) mainMatch.children.append(childMatch);\n          }\n        }\n      }\n      if (mainMatch.length > 0 || m[0].length === 0) {\n        if (mainMatch.length > 0) yield mainMatch;\n      }\n      if (m[0].length === 0) pattern.lastIndex++;\n    }\n  }\n  toString() {\n    return `<RePattern:(${this._regexes.map((r) => r.source).join(\", \")})>`;\n  }\n}\nclass FunctionalPattern extends Pattern {\n  _fns;\n  _matchKwargs;\n  constructor(opts, ...fns) {\n    super(opts);\n    this._fns = fns;\n    this._matchKwargs = filterMatchKwargs(opts);\n  }\n  get patterns() {\n    return this._fns;\n  }\n  get matchOptions() {\n    return this._matchKwargs;\n  }\n  *_match(fn, inputString, context) {\n    const ret = fn(inputString, context);\n    if (!ret) return;\n    const isSingleResult = (v) => {\n      if (!Array.isArray(v)) return true;\n      if (v.length >= 2 && typeof v[0] === \"number\" && typeof v[1] === \"number\") return true;\n      return false;\n    };\n    const args_iterable = isSingleResult(ret) ? [ret] : ret;\n    for (const args of args_iterable) {\n      if (!args) continue;\n      if (typeof args === \"object\" && !Array.isArray(args)) {\n        const { start: s, end: e, ...rest } = args;\n        const opts = { ...this._matchKwargs, ...rest };\n        const m = new Match(s ?? 0, e ?? 0, {\n          ...opts,\n          pattern: this,\n          inputString\n        });\n        if (m.length > 0) yield m;\n      } else if (Array.isArray(args)) {\n        let matchOpts = this._matchKwargs;\n        let start, end;\n        if (args.length >= 3 && typeof args[2] === \"object\" && !Array.isArray(args[2])) {\n          matchOpts = { ...this._matchKwargs, ...args[2] };\n          [start, end] = args;\n        } else {\n          [start, end] = args;\n        }\n        const m = new Match(start, end, { ...matchOpts, pattern: this, inputString });\n        if (m.length > 0) yield m;\n      }\n    }\n  }\n  toString() {\n    return `<FunctionalPattern:(${this._fns.map((f) => f.name || \"anonymous\").join(\", \")})>`;\n  }\n}\nlet _ChainCtor = null;\nfunction registerChain(ctor) {\n  _ChainCtor = ctor;\n}\nfunction getChainClass() {\n  return _ChainCtor;\n}\nfunction splitPatternsOpts(args) {\n  if (args.length === 0) return [[], {}];\n  const first = args[0];\n  const last = args[args.length - 1];\n  if (typeof first === \"object\" && first !== null) {\n    return [args.slice(1), first];\n  }\n  if (args.length > 1 && typeof last === \"object\" && last !== null) {\n    return [args.slice(0, -1), last];\n  }\n  return [args, {}];\n}\nclass Builder {\n  _defaults = {};\n  _regexDefaults = {};\n  _stringDefaults = {};\n  _functionalDefaults = {};\n  _chainDefaults = {};\n  reset() {\n    this._defaults = {};\n    this._regexDefaults = {};\n    this._stringDefaults = {};\n    this._functionalDefaults = {};\n    this._chainDefaults = {};\n    return this;\n  }\n  defaults(kwargs) {\n    setDefaults(kwargs, this._defaults, true);\n    return this;\n  }\n  regexDefaults(kwargs) {\n    setDefaults(kwargs, this._regexDefaults, true);\n    return this;\n  }\n  stringDefaults(kwargs) {\n    setDefaults(kwargs, this._stringDefaults, true);\n    return this;\n  }\n  functionalDefaults(kwargs) {\n    setDefaults(kwargs, this._functionalDefaults, true);\n    return this;\n  }\n  chainDefaults(kwargs) {\n    setDefaults(kwargs, this._chainDefaults, true);\n    return this;\n  }\n  _applyOverrides(kwargs) {\n    const overrideKeys = kwargs[\"overrides\"] ?? [];\n    delete kwargs[\"overrides\"];\n    const backup = {};\n    for (const k of overrideKeys) backup[k] = kwargs[k];\n    return [kwargs, backup];\n  }\n  buildRe(opts, ...patterns) {\n    const kwargs = { ...opts };\n    const [, backup] = this._applyOverrides(kwargs);\n    setDefaults(this._regexDefaults, kwargs);\n    setDefaults(this._defaults, kwargs);\n    Object.assign(kwargs, backup);\n    return new RePattern(kwargs, ...patterns);\n  }\n  buildString(opts, ...patterns) {\n    const kwargs = { ...opts };\n    const [, backup] = this._applyOverrides(kwargs);\n    setDefaults(this._stringDefaults, kwargs);\n    setDefaults(this._defaults, kwargs);\n    Object.assign(kwargs, backup);\n    return new StringPattern(kwargs, ...patterns);\n  }\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  buildFunctional(opts, ...fns) {\n    const kwargs = { ...opts };\n    const [, backup] = this._applyOverrides(kwargs);\n    setDefaults(this._functionalDefaults, kwargs);\n    setDefaults(this._defaults, kwargs);\n    Object.assign(kwargs, backup);\n    return new FunctionalPattern(kwargs, ...fns);\n  }\n  /**\n   * Fluent API: add a regex pattern and return `this`.\n   * Supports both:\n   *   regex(opts, 'pat1', 'pat2')  — options-first\n   *   regex('pat1', 'pat2', opts)  — patterns-first, opts last\n   *   regex('pat1', 'pat2')        — patterns only\n   */\n  regex(...args) {\n    const [patterns, opts] = splitPatternsOpts(args);\n    const p = this.buildRe(opts, ...patterns);\n    return this.pattern(p);\n  }\n  /**\n   * Fluent API: add a string pattern and return `this`.\n   */\n  string(...args) {\n    const [patterns, opts] = splitPatternsOpts(args);\n    const p = this.buildString(opts, ...patterns);\n    return this.pattern(p);\n  }\n  /**\n   * Fluent API: add a functional pattern and return `this`.\n   * Supports:\n   *   functional(fn)                — function only\n   *   functional(fn, opts)          — fn-first, opts-last (Python style)\n   *   functional(opts, fn)          — opts-first, fn-last\n   *   functional(opts, fn1, fn2, …) — opts-first, multiple fns\n   */\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  functional(opts, ...fns) {\n    let p;\n    if (typeof opts === \"function\") {\n      const lastArg = fns[fns.length - 1];\n      if (fns.length > 0 && typeof lastArg === \"object\" && lastArg !== null && !Array.isArray(lastArg)) {\n        const o = lastArg;\n        const actualFns = fns.slice(0, -1);\n        p = this.buildFunctional(o, opts, ...actualFns);\n      } else {\n        p = this.buildFunctional({}, opts, ...fns);\n      }\n    } else {\n      p = this.buildFunctional(opts, ...fns);\n    }\n    return this.pattern(p);\n  }\n  /**\n   * Fluent API: start a chain and return it.\n   * The chain is also registered via pattern().\n   */\n  chain(opts = {}) {\n    const ChainCtor = getChainClass();\n    if (!ChainCtor) throw new Error(\"Chain class not registered. Import chain.ts before calling chain().\");\n    const kwargs = { ...opts };\n    setDefaults(this._chainDefaults, kwargs);\n    setDefaults(this._defaults, kwargs);\n    const c = new ChainCtor(this, kwargs);\n    c._defaults = { ...this._defaults };\n    c._regexDefaults = { ...this._regexDefaults };\n    c._stringDefaults = { ...this._stringDefaults };\n    c._functionalDefaults = { ...this._functionalDefaults };\n    c._chainDefaults = { ...this._chainDefaults };\n    this.pattern(c);\n    return c;\n  }\n}\nclass CyclicDependency extends Error {\n  cyclic;\n  constructor(cyclic) {\n    const parts = [...cyclic.entries()].map(([k, v]) => `${String(k)} -> ${[...v].map(String).join(\", \")}`);\n    super(`Cyclic dependencies exist among these items: ${parts.join(\"; \")}`);\n    this.cyclic = cyclic;\n    this.name = \"CyclicDependency\";\n  }\n}\nfunction toposortFlatten(data, sort = true) {\n  const result = [];\n  for (const group of toposort(data)) {\n    const items = [...group];\n    if (sort) items.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);\n    result.push(...items);\n  }\n  return result;\n}\nfunction* toposort(data) {\n  if (data.size === 0) return;\n  const workData = /* @__PURE__ */ new Map();\n  for (const [k, v] of data) {\n    const deps = new Set(v);\n    deps.delete(k);\n    workData.set(k, deps);\n  }\n  const allDeps = /* @__PURE__ */ new Set();\n  for (const deps of workData.values()) {\n    for (const d of deps) allDeps.add(d);\n  }\n  for (const dep of allDeps) {\n    if (!workData.has(dep)) workData.set(dep, /* @__PURE__ */ new Set());\n  }\n  while (workData.size > 0) {\n    const ordered = /* @__PURE__ */ new Set();\n    for (const [item, deps] of workData) {\n      if (deps.size === 0) ordered.add(item);\n    }\n    if (ordered.size === 0) {\n      throw new CyclicDependency(workData);\n    }\n    yield ordered;\n    for (const item of ordered) workData.delete(item);\n    for (const deps of workData.values()) {\n      for (const item of ordered) deps.delete(item);\n    }\n  }\n}\nclass Consequence {\n}\nclass Condition {\n}\nclass CustomRule extends Condition {\n  static priority = 0;\n  static ruleName = void 0;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  static dependency = null;\n  static properties = {};\n  priority = this.constructor.priority;\n  name_ = this.constructor.name;\n  dependency_ = this.constructor.dependency;\n  logLevel = 0;\n  defined_at;\n  constructor() {\n    super();\n    this.defined_at = definedAt();\n  }\n  enabled(_context) {\n    return true;\n  }\n  toString() {\n    const defined = this.defined_at ? `@${this.defined_at.filename.split(\"/\").pop()}#L${this.defined_at.lineno}` : \"\";\n    return `<${this.name_ ?? this.constructor.name}${defined}>`;\n  }\n  /** Equality: same class = same rule (for deduplication). */\n  equals(other) {\n    return this.constructor === other.constructor;\n  }\n}\nclass Rule extends CustomRule {\n  consequence = null;\n  then(matches, whenResponse, context) {\n    const cons = this.consequence ?? this.constructor.consequence;\n    if (Array.isArray(cons)) {\n      const responses = Array.isArray(whenResponse) ? whenResponse : [whenResponse];\n      const iter = responses[Symbol.iterator]();\n      for (const c of cons) {\n        const instance = typeof c === \"function\" ? new c() : c;\n        instance.then(matches, iter.next().value, context);\n      }\n    } else {\n      const instance = typeof cons === \"function\" ? new cons() : cons;\n      if (instance) instance.then(matches, whenResponse, context);\n    }\n  }\n}\nclass RemoveMatch extends Consequence {\n  then(matches, whenResponse, _context) {\n    if (!whenResponse) return void 0;\n    if (isIterable(whenResponse) && !(whenResponse instanceof String)) {\n      const ret = [];\n      for (const m2 of whenResponse) {\n        if (matches.includes(m2)) {\n          matches.remove(m2);\n          ret.push(m2);\n        }\n      }\n      return ret;\n    }\n    const m = whenResponse;\n    if (matches.includes(m)) {\n      matches.remove(m);\n      return m;\n    }\n    return void 0;\n  }\n}\nclass AppendMatch extends Consequence {\n  matchName;\n  constructor(matchName) {\n    super();\n    this.matchName = matchName;\n  }\n  then(matches, whenResponse, _context) {\n    if (!whenResponse) return void 0;\n    if (isIterable(whenResponse) && !(whenResponse instanceof String)) {\n      const ret = [];\n      for (const m2 of whenResponse) {\n        if (!matches.includes(m2)) {\n          if (this.matchName) m2.name = this.matchName;\n          matches.append(m2);\n          ret.push(m2);\n        }\n      }\n      return ret;\n    }\n    const m = whenResponse;\n    if (this.matchName) m.name = this.matchName;\n    if (!matches.includes(m)) {\n      matches.append(m);\n      return m;\n    }\n    return void 0;\n  }\n}\nclass RenameMatch extends Consequence {\n  matchName;\n  _remove = new RemoveMatch();\n  _append = new AppendMatch();\n  constructor(matchName) {\n    super();\n    this.matchName = matchName;\n  }\n  then(matches, whenResponse, context) {\n    const removed = this._remove.then(matches, whenResponse, context);\n    if (!removed) return;\n    if (Array.isArray(removed)) {\n      for (const m of removed) m.name = this.matchName;\n      this._append.then(matches, removed, context);\n    } else {\n      removed.name = this.matchName;\n      this._append.then(matches, removed, context);\n    }\n  }\n}\nclass AppendTags extends Consequence {\n  tags;\n  _remove = new RemoveMatch();\n  _append = new AppendMatch();\n  constructor(tags) {\n    super();\n    this.tags = tags;\n  }\n  then(matches, whenResponse, context) {\n    const removed = this._remove.then(matches, whenResponse, context);\n    if (!removed) return;\n    if (Array.isArray(removed)) {\n      for (const m of removed) m.tags.push(...this.tags);\n    } else {\n      removed.tags.push(...this.tags);\n    }\n    this._append.then(matches, removed, context);\n  }\n}\nclass RemoveTags extends Consequence {\n  tags;\n  _remove = new RemoveMatch();\n  _append = new AppendMatch();\n  constructor(tags) {\n    super();\n    this.tags = tags;\n  }\n  then(matches, whenResponse, context) {\n    const removed = this._remove.then(matches, whenResponse, context);\n    if (!removed) return;\n    const allRemoved = Array.isArray(removed) ? removed : [removed];\n    for (const m of allRemoved) {\n      for (const tag of this.tags) {\n        const idx = m.tags.indexOf(tag);\n        if (idx !== -1) m.tags.splice(idx, 1);\n      }\n    }\n    this._append.then(matches, removed, context);\n  }\n}\nclass Rules {\n  _list = [];\n  constructor(...rules) {\n    this.load(...rules);\n  }\n  load(...rules) {\n    for (const rule of rules) {\n      if (typeof rule === \"function\" && rule.prototype instanceof CustomRule) {\n        this._list.push(new rule());\n      } else if (typeof rule === \"object\" && rule !== null && !(rule instanceof CustomRule)) {\n        this.loadModule(rule);\n      } else if (rule instanceof CustomRule) {\n        this._list.push(rule);\n      } else if (typeof rule === \"function\") {\n        this._list.push(new rule());\n      }\n    }\n  }\n  /**\n   * Load rules from a module-like object by scanning its exported members.\n   * Port of Python Rules.load_module() which uses inspect.getmembers().\n   */\n  loadModule(module) {\n    for (const value of Object.values(module)) {\n      if (typeof value === \"function\" && value.prototype instanceof CustomRule) {\n        this._list.push(new value());\n      }\n    }\n  }\n  extend(other) {\n    for (const r of other._list) {\n      if (!this._list.some((existing) => existing.equals(r))) {\n        this._list.push(r);\n      }\n    }\n  }\n  indexOf(rule) {\n    return this._list.indexOf(rule);\n  }\n  [Symbol.iterator]() {\n    return this._list[Symbol.iterator]();\n  }\n  get length() {\n    return this._list.length;\n  }\n  executeAllRules(matches, context) {\n    const ret = [];\n    const byPriority = /* @__PURE__ */ new Map();\n    for (const rule of this._list) {\n      const p = rule.priority;\n      const arr = byPriority.get(p) ?? [];\n      arr.push(rule);\n      byPriority.set(p, arr);\n    }\n    const sortedPriorities = [...byPriority.keys()].sort((a, b) => b - a);\n    for (const _priority of sortedPriorities) {\n      const priorityRules = byPriority.get(_priority);\n      const sorted = toposortRules(priorityRules);\n      for (const ruleGroup of sorted) {\n        const groupArr = [...ruleGroup].sort((a, b) => this.indexOf(a) - this.indexOf(b));\n        for (const rule of groupArr) {\n          const whenResponse = executeRule(rule, matches, context);\n          if (whenResponse !== null && whenResponse !== void 0 && whenResponse !== false) {\n            ret.push([rule, whenResponse]);\n          }\n        }\n      }\n    }\n    return ret;\n  }\n}\nfunction executeRule(rule, matches, context) {\n  if (!rule.enabled(context)) return null;\n  const whenResponse = rule.when(matches, context);\n  if (whenResponse !== null && whenResponse !== void 0 && whenResponse !== false) {\n    rule.then(matches, whenResponse, context);\n    return whenResponse;\n  }\n  return null;\n}\nfunction toposortRules(rules) {\n  const graph = /* @__PURE__ */ new Map();\n  const classToDeps = /* @__PURE__ */ new Map();\n  for (const rule of rules) {\n    const cls = rule.constructor;\n    classToDeps.set(cls, [...classToDeps.get(cls) ?? [], rule]);\n  }\n  for (const rule of rules) {\n    const deps = /* @__PURE__ */ new Set();\n    const rawDeps = rule.dependency_;\n    if (rawDeps) {\n      const depArr = Array.isArray(rawDeps) ? rawDeps : [rawDeps];\n      for (const dep of depArr) {\n        let resolved = [];\n        if (typeof dep === \"string\") {\n          for (const [cls, insts] of classToDeps) {\n            if (cls.name === dep) {\n              resolved = insts;\n              break;\n            }\n          }\n        } else {\n          resolved = classToDeps.get(dep) ?? [];\n        }\n        for (const inst of resolved) {\n          if (inst !== rule) deps.add(inst);\n        }\n      }\n    }\n    graph.set(rule, deps);\n  }\n  return [...toposort(graph)];\n}\nconst DEFAULT_SYMBOL = \"__default__\";\nconst PRE_PROCESS = 2048;\nconst POST_PROCESS = -2048;\nfunction defaultConflictSolver(match, conflicting) {\n  if (conflicting.initiator.length < match.initiator.length) return conflicting;\n  if (match.initiator.length < conflicting.initiator.length) return match;\n  return null;\n}\nclass ConflictSolver extends Rule {\n  static priority = PRE_PROCESS;\n  priority = PRE_PROCESS;\n  consequence = RemoveMatch;\n  get defaultConflictSolverFn() {\n    return defaultConflictSolver;\n  }\n  when(matches, _context) {\n    const toRemove = new IdentitySet();\n    const publicMatches = matches.toArray().filter((m) => !m.private).sort((a, b) => a.length - b.length);\n    for (const match of publicMatches) {\n      const conflicting = matches.conflicting(match) ?? [];\n      if (!conflicting.length) continue;\n      const publicConflicting = conflicting.filter((c) => !c.private).sort((a, b) => a.length - b.length);\n      for (const conflictingMatch of publicConflicting) {\n        const solvers = [\n          [this.defaultConflictSolverFn, false]\n        ];\n        if (match.conflictSolver) solvers.push([match.conflictSolver, false]);\n        if (conflictingMatch.conflictSolver) solvers.push([conflictingMatch.conflictSolver, true]);\n        for (let si = solvers.length - 1; si >= 0; si--) {\n          const [solver, reverse] = solvers[si];\n          const toRem = reverse ? solver(conflictingMatch, match) : solver(match, conflictingMatch);\n          if (toRem === DEFAULT_SYMBOL) continue;\n          if (toRem && !toRemove.has(toRem)) {\n            const toKeep = toRem === match ? conflictingMatch : match;\n            if (!toRemove.has(toKeep)) {\n              toRemove.add(toRem);\n            }\n          }\n          break;\n        }\n      }\n    }\n    return toRemove;\n  }\n}\nclass PrivateRemover extends Rule {\n  static priority = POST_PROCESS;\n  priority = POST_PROCESS;\n  consequence = RemoveMatch;\n  when(matches, _context) {\n    return matches.toArray().filter((m) => m.private);\n  }\n}\nclass InvalidChainException extends Error {\n  constructor() {\n    super(\"Invalid chain\");\n  }\n}\nclass ChainPart extends BasePattern {\n  _chain;\n  pattern;\n  repeaterStart = 1;\n  repeaterEnd = 1;\n  _hidden = false;\n  constructor(chain, pattern) {\n    super();\n    this._chain = chain;\n    this.pattern = pattern;\n  }\n  get isChainStart() {\n    return this._chain.parts[0] === this;\n  }\n  get isHidden() {\n    return this._hidden;\n  }\n  hidden(hidden = true) {\n    this._hidden = hidden;\n    return this;\n  }\n  matches(inputString, context, withRawMatches = false) {\n    const result = this.pattern.matches(inputString, context, true);\n    let [allMatches, rawMatches] = result;\n    allMatches = this._truncateRepeater(allMatches, inputString);\n    rawMatches = this._truncateRepeater(rawMatches, inputString);\n    this._validateRepeater(rawMatches);\n    if (withRawMatches) return [allMatches, rawMatches];\n    return allMatches;\n  }\n  _truncateRepeater(matches, inputString) {\n    if (!matches.length) return matches;\n    if (!this.isChainStart) {\n      const separator = inputString.slice(0, matches[0].initiator.rawStart);\n      if (separator) return [];\n    }\n    let j = 1;\n    for (let i = 0; i < matches.length - 1; i++) {\n      const sep = inputString.slice(matches[i].initiator.rawEnd, matches[i + 1].initiator.rawStart);\n      if (sep) break;\n      j++;\n    }\n    let truncated = matches.slice(0, j);\n    if (this.repeaterEnd !== null) {\n      truncated = truncated.filter((m) => m.matchIndex < this.repeaterEnd);\n    }\n    return truncated;\n  }\n  _validateRepeater(matches) {\n    const maxMatchIndex = matches.length > 0 ? Math.max(...matches.map((m) => m.matchIndex)) : -1;\n    if (maxMatchIndex + 1 < this.repeaterStart) {\n      throw new InvalidChainException();\n    }\n  }\n  repeater(value) {\n    if (typeof value === \"number\") {\n      this.repeaterStart = value;\n      this.repeaterEnd = value;\n      return this;\n    }\n    const v = String(value);\n    if (v === \"+\") {\n      this.repeaterStart = 1;\n      this.repeaterEnd = null;\n    } else if (v === \"*\") {\n      this.repeaterStart = 0;\n      this.repeaterEnd = null;\n    } else if (v === \"?\") {\n      this.repeaterStart = 0;\n      this.repeaterEnd = 1;\n    } else {\n      const m = /\\{\\s*(\\d*)\\s*,?\\s*(\\d*)\\s*\\}/.exec(v);\n      if (m) {\n        this.repeaterStart = m[1] ? parseInt(m[1]) : 0;\n        this.repeaterEnd = m[2] ? parseInt(m[2]) : null;\n      }\n    }\n    return this;\n  }\n  // Proxy chain methods for fluent API\n  regex(opts, ...rest) {\n    return this._chain.regex(opts, ...rest);\n  }\n  string(opts, ...rest) {\n    return this._chain.string(opts, ...rest);\n  }\n  functional(opts, ...fns) {\n    return this._chain.functional(opts, ...fns);\n  }\n  chain(opts) {\n    return this._chain.chain(opts);\n  }\n  close() {\n    return this._chain.close();\n  }\n  toString() {\n    return `${this.pattern}({${this.repeaterStart},${this.repeaterEnd}})`;\n  }\n}\nclass Chain extends Pattern {\n  parts = [];\n  // Builder-compatible defaults (populated by Builder.chain())\n  _defaults = {};\n  _regexDefaults = {};\n  _stringDefaults = {};\n  _functionalDefaults = {};\n  _chainDefaults = {};\n  _parent;\n  _chainBreaker;\n  _matchKwargs;\n  constructor(parent, opts = {}) {\n    super(opts);\n    this._parent = parent;\n    this._matchKwargs = filterMatchKwargs(opts);\n    this._chainBreaker = opts.chainBreaker ?? null;\n  }\n  // Builder-like methods so chain().regex() etc. work\n  defaults(kwargs) {\n    setDefaults(kwargs, this._defaults, true);\n    if (\"children\" in kwargs) this.children = kwargs.children;\n    if (\"privateParent\" in kwargs) this.privateParent = kwargs.privateParent;\n    if (\"privateChildren\" in kwargs) this.privateChildren = kwargs.privateChildren;\n    if (\"conflictSolver\" in kwargs) this._matchKwargs.conflictSolver = kwargs.conflictSolver;\n    if (\"privateNames\" in kwargs) this.privateNames = kwargs.privateNames;\n    return this;\n  }\n  regexDefaults(kwargs) {\n    setDefaults(kwargs, this._regexDefaults, true);\n    return this;\n  }\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  regex(...args) {\n    const lastArg = args[args.length - 1];\n    const opts = typeof lastArg === \"object\" && lastArg !== null && !Array.isArray(lastArg) ? lastArg : {};\n    const patterns = typeof lastArg === \"object\" && lastArg !== null && !Array.isArray(lastArg) ? args.slice(0, -1) : args;\n    const kwargs = { ...this._regexDefaults, ...this._defaults, ...opts };\n    const pat = new RePattern(kwargs, ...patterns);\n    return this.pattern(pat);\n  }\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  string(...args) {\n    const lastArg = args[args.length - 1];\n    const opts = typeof lastArg === \"object\" && lastArg !== null && !Array.isArray(lastArg) ? lastArg : {};\n    const patterns = typeof lastArg === \"object\" && lastArg !== null && !Array.isArray(lastArg) ? args.slice(0, -1) : args;\n    const kwargs = { ...this._stringDefaults, ...this._defaults, ...opts };\n    const pat = new StringPattern(kwargs, ...patterns);\n    return this.pattern(pat);\n  }\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  functional(...args) {\n    const fn = args[0];\n    const opts = args.length > 1 && typeof args[1] === \"object\" ? args[1] : {};\n    const kwargs = { ...this._functionalDefaults, ...this._defaults, ...opts };\n    const pat = new FunctionalPattern(kwargs, fn);\n    return this.pattern(pat);\n  }\n  chain(opts = {}) {\n    const kwargs = { ...this._chainDefaults, ...this._defaults, ...opts };\n    const c = new Chain(this, kwargs);\n    c._defaults = { ...this._defaults };\n    c._regexDefaults = { ...this._regexDefaults };\n    c._stringDefaults = { ...this._stringDefaults };\n    c._functionalDefaults = { ...this._functionalDefaults };\n    c._chainDefaults = { ...this._chainDefaults };\n    this.pattern(c);\n    return c;\n  }\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  pattern(...patterns) {\n    if (!patterns.length) throw new Error(\"One pattern should be given to the chain\");\n    if (patterns.length > 1) throw new Error(\"Only one pattern can be given to the chain\");\n    const part = new ChainPart(this, patterns[0]);\n    this.parts.push(part);\n    return part;\n  }\n  close() {\n    let p = this._parent;\n    while (p instanceof Chain) p = p._parent;\n    return p;\n  }\n  get patterns() {\n    return [this];\n  }\n  get matchOptions() {\n    return {};\n  }\n  /**\n   * Override from Pattern — when the main chain match fails validation,\n   * try removing trailing groups from the last pattern and re-validate.\n   * Port of Python Chain._process_match fallback logic.\n   */\n  _processMatch(match, matchIndex, child = false) {\n    const ret = super._processMatch(match, matchIndex, child);\n    if (ret) return true;\n    if (match.children.length > 0) {\n      const lastPattern = match.children.get(match.children.length - 1).pattern;\n      const lastPatternChildren = match.children.toArray().filter((c) => c.pattern === lastPattern);\n      const lastPatternGroups = Chain._groupByMatchIndex(lastPatternChildren);\n      if (lastPatternGroups.size > 0) {\n        const originalChildren = new Matches(match.children.toArray());\n        const originalEnd = match.end;\n        const indices = [...lastPatternGroups.keys()].sort((a, b) => b - a);\n        for (const idx of indices) {\n          const lastMatches = lastPatternGroups.get(idx);\n          for (const lm of lastMatches) {\n            match.children.remove(lm);\n          }\n          match.end = match.children.length > 0 ? match.children.get(match.children.length - 1).end : match.start;\n          const retried = super._processMatch(match, matchIndex, child);\n          if (retried) return true;\n        }\n        match.children = originalChildren;\n        match.end = originalEnd;\n      }\n    }\n    return false;\n  }\n  *_match(_pattern, inputString, context) {\n    let offset = 0;\n    while (offset < inputString.length) {\n      let chainFound = false;\n      const currentChainMatches = [];\n      let valid = true;\n      let chainInputString = inputString.slice(offset);\n      for (const chainPart of this.parts) {\n        try {\n          const result = chainPart.matches(chainInputString, context, true);\n          const [partMatches, rawPartMatches] = result;\n          Chain._fixMatchesOffset(partMatches, inputString, offset);\n          Chain._fixMatchesOffset(rawPartMatches, inputString, offset);\n          if (rawPartMatches.length > 0) {\n            const groupedRaw = Chain._groupByMatchIndex(rawPartMatches);\n            const groupedAll = Chain._groupByMatchIndex(partMatches);\n            for (const [matchIndex, grouped] of groupedRaw) {\n              chainFound = true;\n              offset = grouped[grouped.length - 1].rawEnd;\n              chainInputString = inputString.slice(offset);\n              if (!chainPart.isHidden) {\n                const groupedMatches = groupedAll.get(matchIndex) ?? [];\n                if (this._chainBreakerEval([...currentChainMatches, ...groupedMatches])) {\n                  currentChainMatches.push(...groupedMatches);\n                }\n              }\n            }\n          }\n        } catch (e) {\n          if (e instanceof InvalidChainException) {\n            valid = false;\n            if (currentChainMatches.length > 0) {\n              offset = currentChainMatches[0].rawEnd;\n            } else {\n              offset++;\n            }\n            break;\n          }\n          throw e;\n        }\n      }\n      if (!chainFound) break;\n      if (currentChainMatches.length > 0 && valid) {\n        yield this._buildChainMatch(currentChainMatches, inputString);\n      }\n    }\n  }\n  _chainBreakerEval(matches) {\n    if (!this._chainBreaker) return true;\n    return !this._chainBreaker(new Matches(matches));\n  }\n  _buildChainMatch(currentChainMatches, inputString) {\n    let start = Infinity;\n    let end = -Infinity;\n    for (const m of currentChainMatches) {\n      if (m.start < start) start = m.start;\n      if (m.end > end) end = m.end;\n    }\n    const match = new Match(start, end, {\n      ...this._matchKwargs,\n      pattern: this,\n      inputString\n    });\n    for (const chainMatch of currentChainMatches) {\n      if (chainMatch.children.length > 0) {\n        for (const child of chainMatch.children) {\n          match.children.append(child);\n        }\n      }\n      if (!match.children.includes(chainMatch)) {\n        match.children.append(chainMatch);\n        chainMatch.parent = match;\n      }\n    }\n    return match;\n  }\n  static _fixMatchesOffset(matches, inputString, offset) {\n    for (const m of matches) {\n      if (m.inputString !== inputString) {\n        m.inputString = inputString;\n        const oldRawStart = m.rawStart;\n        const oldRawEnd = m.rawEnd;\n        m.start += offset;\n        m.end += offset;\n        m.rawStart = oldRawStart + offset;\n        m.rawEnd = oldRawEnd + offset;\n      }\n      if (m.children.length > 0) {\n        Chain._fixMatchesOffset(m.children.toArray(), inputString, offset);\n      }\n    }\n  }\n  static _groupByMatchIndex(matches) {\n    const map = /* @__PURE__ */ new Map();\n    for (const m of matches) {\n      const arr = map.get(m.matchIndex) ?? [];\n      arr.push(m);\n      map.set(m.matchIndex, arr);\n    }\n    return map;\n  }\n}\nregisterChain(Chain);\nclass Rebulk extends Builder {\n  _patterns = [];\n  _rules;\n  _rebulks = [];\n  _disabled;\n  /** Optional property customizer (guessit-specific). */\n  customizeProperties;\n  constructor(opts = {}) {\n    super();\n    const d = opts.disabled;\n    if (typeof d === \"function\") {\n      this._disabled = d;\n    } else if (typeof d === \"boolean\") {\n      this._disabled = () => d;\n    } else {\n      this._disabled = () => false;\n    }\n    this._rules = new Rules();\n    if (opts.defaultRules !== false) {\n      this._rules.load(ConflictSolver, PrivateRemover);\n    }\n  }\n  pattern(...patterns) {\n    this._patterns.push(...patterns);\n    return this;\n  }\n  rules(...rules) {\n    this._rules.load(...rules);\n    return this;\n  }\n  rebulk(...rebulks) {\n    this._rebulks.push(...rebulks);\n    return this;\n  }\n  /** Run all patterns and rules against `string`. */\n  matches(string, context = {}) {\n    const matches = new Matches(void 0, string);\n    this._matchesPatterns(matches, context);\n    this._executeRules(matches, context);\n    return matches;\n  }\n  effectiveRules(context) {\n    const rules = new Rules();\n    rules.extend(this._rules);\n    for (const child of this._rebulks) {\n      if (!child._disabled(context ?? {})) {\n        rules.extend(child._rules);\n      }\n    }\n    return rules;\n  }\n  effectivePatterns(context) {\n    const patterns = [...this._patterns];\n    for (const child of this._rebulks) {\n      if (!child._disabled(context ?? {})) {\n        extendSafe(patterns, child._patterns);\n      }\n    }\n    return patterns;\n  }\n  _executeRules(matches, context) {\n    if (!this._disabled(context)) {\n      const rules = this.effectiveRules(context);\n      rules.executeAllRules(matches, context);\n    }\n  }\n  _matchesPatterns(matches, context) {\n    if (this._disabled(context)) return;\n    const patterns = this.effectivePatterns(context);\n    for (const pat of patterns) {\n      if (pat.disabled && pat.disabled(context)) continue;\n      const patternMatches = pat.matches(matches.inputString, context);\n      for (const m of patternMatches) {\n        if (m.marker) {\n          matches.markers.append(m);\n        } else {\n          matches.append(m);\n        }\n      }\n    }\n  }\n}\nclass Description {\n}\nclass PatternDescription extends Description {\n  pattern;\n  _properties;\n  constructor(pattern) {\n    super();\n    this.pattern = pattern;\n    this._properties = {};\n    const pat = pattern;\n    if (pat.properties_ && Object.keys(pat.properties_).length > 0) {\n      for (const [key, values] of Object.entries(pat.properties_)) {\n        if (!this._properties[key]) this._properties[key] = [];\n        extendSafe(this._properties[key], values);\n      }\n    } else if (pat.defaultValue !== void 0 && pat.defaultValue !== null) {\n      const name = pat.name ?? \"\";\n      if (!this._properties[name]) this._properties[name] = [];\n      this._properties[name].push(pat.defaultValue);\n    } else if (pattern instanceof StringPattern) {\n      const name = pat.name ?? \"\";\n      if (!this._properties[name]) this._properties[name] = [];\n      extendSafe(this._properties[name], pat.patterns);\n    } else if (pattern instanceof RePattern) {\n      if (pat.name && !(pat.privateNames || []).includes(pat.name)) {\n        if (!this._properties[pat.name]) this._properties[pat.name] = [];\n        extendSafe(this._properties[pat.name], [null]);\n      }\n      if (!pat.privateChildren) {\n        for (const regex of pat.patterns) {\n          if (regex.source) {\n            const groupRegex = /\\(\\?<([^>]+)>/g;\n            let m;\n            while ((m = groupRegex.exec(regex.source)) !== null) {\n              const groupName = m[1];\n              if (!(pat.privateNames || []).includes(groupName)) {\n                if (!this._properties[groupName]) this._properties[groupName] = [];\n                extendSafe(this._properties[groupName], [null]);\n              }\n            }\n          }\n        }\n      }\n    } else if (pattern instanceof FunctionalPattern) {\n      if (pat.name && !(pat.privateNames || []).includes(pat.name)) {\n        if (!this._properties[pat.name]) this._properties[pat.name] = [];\n        extendSafe(this._properties[pat.name], [null]);\n      }\n    }\n  }\n  get properties() {\n    return this._properties;\n  }\n}\nclass RuleDescription extends Description {\n  rule;\n  _properties;\n  constructor(rule) {\n    super();\n    this.rule = rule;\n    this._properties = {};\n    const ruleProps = rule.constructor.properties;\n    if (ruleProps) {\n      for (const [key, values] of Object.entries(ruleProps)) {\n        if (!this._properties[key]) this._properties[key] = [];\n        extendSafe(this._properties[key], values);\n      }\n    }\n  }\n  get properties() {\n    return this._properties;\n  }\n}\nclass Introspection extends Description {\n  patterns;\n  rules;\n  constructor(rebulk, context) {\n    super();\n    const effectivePatterns = rebulk.effectivePatterns(context);\n    this.patterns = effectivePatterns.filter((p) => !p.private_ && !p.marker).map((p) => new PatternDescription(p));\n    const effectiveRules = rebulk.effectiveRules(context);\n    this.rules = [];\n    for (const rule of effectiveRules) {\n      this.rules.push(new RuleDescription(rule));\n    }\n  }\n  get properties() {\n    const props = {};\n    for (const pattern of this.patterns) {\n      for (const [key, values] of Object.entries(pattern.properties)) {\n        if (!props[key]) props[key] = [];\n        extendSafe(props[key], values);\n      }\n    }\n    for (const rule of this.rules) {\n      for (const [key, values] of Object.entries(rule.properties)) {\n        if (!props[key]) props[key] = [];\n        extendSafe(props[key], values);\n      }\n    }\n    return props;\n  }\n}\nfunction introspect(rebulk, context) {\n  return new Introspection(rebulk, context);\n}\nexport {\n  AppendMatch,\n  AppendTags,\n  BasePattern,\n  Builder,\n  Chain,\n  ChainPart,\n  Condition,\n  ConflictSolver,\n  Consequence,\n  CustomRule,\n  CyclicDependency,\n  DEBUG,\n  Description,\n  FunctionalPattern,\n  IdentitySet,\n  Introspection,\n  LOG_LEVEL,\n  Markers,\n  Match,\n  Matches,\n  MatchesDict,\n  POST_PROCESS,\n  PRE_PROCESS,\n  Pattern,\n  PatternDescription,\n  PrivateRemover,\n  RePattern,\n  Rebulk,\n  RemoveMatch,\n  RemoveTags,\n  RenameMatch,\n  Rule,\n  RuleDescription,\n  Rules,\n  StringPattern,\n  alwaysTrue,\n  call,\n  charsAfter,\n  charsBefore,\n  charsSurround,\n  defaultFormatter,\n  definedAt,\n  ensureDict,\n  ensureList,\n  executeRule,\n  extendSafe,\n  filterMatchKwargs,\n  findAll,\n  formatters,\n  frameRepr,\n  introspect,\n  isIterable,\n  setDebug,\n  setLogLevel,\n  toposort,\n  toposortFlatten,\n  toposortRules,\n  validators\n};\n//# sourceMappingURL=rebulk-js.js.map\n","/**\n * Path markers — port of guessit/rules/markers/path.py\n */\nimport { Rebulk } from 'rebulk-js';\nimport { findAll } from 'rebulk-js';\n\nexport function path(config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk();\n  rebulk.defaults({ name: 'path', marker: true });\n\n  function markPath(inputString: string, context?: Record<string, unknown>): Array<[number, number]> {\n    if (context?.['name_only']) {\n      return [[0, inputString.length]];\n    }\n\n    const indices: number[] = [\n      ...findAll(inputString, '/'),\n      ...findAll(inputString, '\\\\'),\n      -1,\n      inputString.length,\n    ];\n    indices.sort((a, b) => a - b);\n\n    const ret: Array<[number, number]> = [];\n    for (let i = 0; i < indices.length - 1; i++) {\n      ret.push([indices[i] + 1, indices[i + 1]]);\n    }\n    return ret;\n  }\n\n  rebulk.functional(markPath);\n  return rebulk;\n}\n","/**\n * Group markers (...), [...] and {...} — port of guessit/rules/markers/groups.py\n */\nimport { Rebulk } from 'rebulk-js';\n\nexport class ConfigurationException extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'ConfigurationException';\n  }\n}\n\nexport function groups(config: { starting: string; ending: string }): Rebulk {\n  const rebulk = new Rebulk();\n  rebulk.defaults({ name: 'group', marker: true });\n\n  const { starting, ending } = config;\n\n  if (starting.length !== ending.length) {\n    throw new ConfigurationException('Starting and ending groups must have the same length');\n  }\n\n  function markGroups(inputString: string): Array<[number, number]> {\n    // One stack per bracket type\n    const openings: number[][] = Array.from({ length: starting.length }, () => []);\n    const ret: Array<[number, number]> = [];\n\n    for (let i = 0; i < inputString.length; i++) {\n      const ch = inputString[i];\n\n      const startType = starting.indexOf(ch);\n      if (startType > -1) {\n        openings[startType].push(i);\n      }\n\n      const endType = ending.indexOf(ch);\n      if (endType > -1) {\n        const stack = openings[endType];\n        if (stack.length > 0) {\n          const startIndex = stack.pop()!;\n          ret.push([startIndex, i + 1]);\n        }\n      }\n    }\n    return ret;\n  }\n\n  rebulk.functional(markGroups);\n  return rebulk;\n}\n","/**\n * Regex utilities — port of guessit/reutils.py\n */\n\n/**\n * Build an alternation pattern from a list of patterns.\n * Mirrors Python's build_or_pattern(patterns, name=None, escape=False).\n */\nexport function buildOrPattern(patterns: string[], name?: string, escape = false): string {\n  if (!patterns || patterns.length === 0) return '(?:)';\n  const parts: string[] = [];\n  for (const pattern of patterns) {\n    if (parts.length === 0) {\n      parts.push('(?');\n      if (name) {\n        parts.push(`<${name}>`);\n      } else {\n        parts.push(':');\n      }\n    } else {\n      parts.push('|');\n    }\n    parts.push(escape ? `(?:${pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')})` : `(?:${pattern})`);\n  }\n  parts.push(')');\n  return parts.join('');\n}\n","/**\n * Numeral helpers — port of guessit/rules/common/numeral.py\n */\n\nconst ROMAN_VALUES: [string, number][] = [\n  ['M', 1000], ['CM', 900], ['D', 500], ['CD', 400],\n  ['C', 100], ['XC', 90], ['L', 50], ['XL', 40],\n  ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1],\n];\n\n// Word numerals — English and French\nconst WORD_NUMERALS: Record<string, number> = {\n  // English\n  'zero': 0, 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5,\n  'six': 6, 'seven': 7, 'eight': 8, 'nine': 9, 'ten': 10,\n  'eleven': 11, 'twelve': 12, 'thirteen': 13, 'fourteen': 14, 'fifteen': 15,\n  'sixteen': 16, 'seventeen': 17, 'eighteen': 18, 'nineteen': 19, 'twenty': 20,\n  // French\n  'zéro': 0, 'un': 1, 'deux': 2, 'trois': 3, 'quatre': 4, 'cinq': 5,\n  // 'six' is shared with the English list above (same spelling and value)\n  'sept': 7, 'huit': 8, 'neuf': 9, 'dix': 10,\n  'onze': 11, 'douze': 12, 'treize': 13, 'quatorze': 14, 'quinze': 15,\n  'seize': 16, 'dix-sept': 17, 'dix-huit': 18, 'dix-neuf': 19, 'vingt': 20,\n};\n\nexport function parseRoman(s: string): number | undefined {\n  const upper = s.toUpperCase();\n  let result = 0;\n  let i = 0;\n  for (const [sym, val] of ROMAN_VALUES) {\n    while (upper.startsWith(sym, i)) {\n      result += val;\n      i += sym.length;\n    }\n  }\n  return i === upper.length && result > 0 ? result : undefined;\n}\n\nexport function parseWord(s: string): number | undefined {\n  return WORD_NUMERALS[s.toLowerCase()];\n}\n\nexport function parseNumber(s: string): number | undefined {\n  const n = parseInt(s, 10);\n  if (!isNaN(n)) return n;\n  const roman = parseRoman(s);\n  if (roman !== undefined) return roman;\n  return parseWord(s);\n}\n\nexport function numericFunction(value: string): number {\n  return parseNumber(value) ?? parseInt(value, 10);\n}\n","/**\n * Common constants and helpers — port of guessit/rules/common/__init__.py\n */\n\n/** Characters that can act as separators between words/tokens. */\nexport const seps = ' [](){}+*|=-_~#/\\\\.,;:';\n\n/** Separators without group brackets */\nexport const sepsNoGroups = seps.replace(/[\\[\\](){}]/g, '');\n\n/** Separators without filesystem path characters */\nexport const sepsNoFs = seps.replace(/[/\\\\]/g, '');\n\n/** Separators for title splitting */\nexport const titleSeps = '-+/\\\\|';\n\n/** Escape a string for use in a regex character class. */\nexport function reEscape(s: string): string {\n  return s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n}\n\n/** Pre-escaped `seps` safe for use in a regex character class `[sepsPattern]`. */\nexport const sepsPattern = reEscape(seps);\n\n/** Pre-escaped `sepsNoGroups` safe for use in a regex character class. */\nexport const sepsNoGroupsPattern = reEscape(sepsNoGroups);\n\n/** Strip all separator characters from a string. */\nexport function stripSeps(s: string): string {\n  return s.replace(new RegExp(`[${sepsPattern}]`, 'g'), '');\n}\n\n/**\n * Abbreviation pair: literal `-` expands to a separator character class.\n * Used as: abbreviations=[dash] in regex_defaults.\n */\nexport const dash: [string, string] = ['-', '[' + reEscape(sepsNoFs) + ']'];\nexport const altDash: [string, string] = ['@', '[' + reEscape(sepsNoFs) + ']'];\n\n/** Make a regex pattern optional. */\nexport function optional(pattern: string): string {\n  return '(?:' + pattern + ')?';\n}\n","/**\n * Validators — port of guessit/rules/common/validators.py\n */\nimport { charsBefore, charsAfter, charsSurround } from 'rebulk-js';\nimport { seps } from './index.js';\nimport type { Match } from 'rebulk-js';\n\nexport const sepsBefore = (match: Match) => charsBefore(seps, match);\nexport const sepsAfter = (match: Match) => charsAfter(seps, match);\nexport const sepsSurround = (match: Match) => charsSurround(seps, match);\n\nexport function intCoercable(string: string): boolean {\n  // Matches Python's int() behaviour: the ENTIRE string must be a valid integer.\n  // parseInt('720p') returns 720 in JS but int('720p') raises ValueError in Python.\n  // Use Number() which returns NaN for '720p', matching Python semantics.\n  const n = Number(string.trim());\n  return Number.isInteger(n);\n}\n\nexport function and_(...validators: ((m: Match) => boolean)[]): (m: Match) => boolean {\n  return (m) => validators.every((v) => v(m));\n}\n\nexport function or_(...validators: ((m: Match) => boolean)[]): (m: Match) => boolean {\n  return (m) => validators.some((v) => v(m));\n}\n","// AUTO-GENERATED by scripts/gen-diacritics.mjs — do not edit by hand.\n// 844 precomposed accented characters → their base form, matching\n// V8's normalize('NFD') + combining-mark strip, for every script. Engine-\n// independent so the QuickJS/WASM build folds accents identically to the JS build.\n\nexport const DIACRITIC_FOLD: Record<string, string> = {\n  \"À\": \"A\",\n  \"Á\": \"A\",\n  \"Â\": \"A\",\n  \"Ã\": \"A\",\n  \"Ä\": \"A\",\n  \"Å\": \"A\",\n  \"Ç\": \"C\",\n  \"È\": \"E\",\n  \"É\": \"E\",\n  \"Ê\": \"E\",\n  \"Ë\": \"E\",\n  \"Ì\": \"I\",\n  \"Í\": \"I\",\n  \"Î\": \"I\",\n  \"Ï\": \"I\",\n  \"Ñ\": \"N\",\n  \"Ò\": \"O\",\n  \"Ó\": \"O\",\n  \"Ô\": \"O\",\n  \"Õ\": \"O\",\n  \"Ö\": \"O\",\n  \"Ù\": \"U\",\n  \"Ú\": \"U\",\n  \"Û\": \"U\",\n  \"Ü\": \"U\",\n  \"Ý\": \"Y\",\n  \"à\": \"a\",\n  \"á\": \"a\",\n  \"â\": \"a\",\n  \"ã\": \"a\",\n  \"ä\": \"a\",\n  \"å\": \"a\",\n  \"ç\": \"c\",\n  \"è\": \"e\",\n  \"é\": \"e\",\n  \"ê\": \"e\",\n  \"ë\": \"e\",\n  \"ì\": \"i\",\n  \"í\": \"i\",\n  \"î\": \"i\",\n  \"ï\": \"i\",\n  \"ñ\": \"n\",\n  \"ò\": \"o\",\n  \"ó\": \"o\",\n  \"ô\": \"o\",\n  \"õ\": \"o\",\n  \"ö\": \"o\",\n  \"ù\": \"u\",\n  \"ú\": \"u\",\n  \"û\": \"u\",\n  \"ü\": \"u\",\n  \"ý\": \"y\",\n  \"ÿ\": \"y\",\n  \"Ā\": \"A\",\n  \"ā\": \"a\",\n  \"Ă\": \"A\",\n  \"ă\": \"a\",\n  \"Ą\": \"A\",\n  \"ą\": \"a\",\n  \"Ć\": \"C\",\n  \"ć\": \"c\",\n  \"Ĉ\": \"C\",\n  \"ĉ\": \"c\",\n  \"Ċ\": \"C\",\n  \"ċ\": \"c\",\n  \"Č\": \"C\",\n  \"č\": \"c\",\n  \"Ď\": \"D\",\n  \"ď\": \"d\",\n  \"Ē\": \"E\",\n  \"ē\": \"e\",\n  \"Ĕ\": \"E\",\n  \"ĕ\": \"e\",\n  \"Ė\": \"E\",\n  \"ė\": \"e\",\n  \"Ę\": \"E\",\n  \"ę\": \"e\",\n  \"Ě\": \"E\",\n  \"ě\": \"e\",\n  \"Ĝ\": \"G\",\n  \"ĝ\": \"g\",\n  \"Ğ\": \"G\",\n  \"ğ\": \"g\",\n  \"Ġ\": \"G\",\n  \"ġ\": \"g\",\n  \"Ģ\": \"G\",\n  \"ģ\": \"g\",\n  \"Ĥ\": \"H\",\n  \"ĥ\": \"h\",\n  \"Ĩ\": \"I\",\n  \"ĩ\": \"i\",\n  \"Ī\": \"I\",\n  \"ī\": \"i\",\n  \"Ĭ\": \"I\",\n  \"ĭ\": \"i\",\n  \"Į\": \"I\",\n  \"į\": \"i\",\n  \"İ\": \"I\",\n  \"Ĵ\": \"J\",\n  \"ĵ\": \"j\",\n  \"Ķ\": \"K\",\n  \"ķ\": \"k\",\n  \"Ĺ\": \"L\",\n  \"ĺ\": \"l\",\n  \"Ļ\": \"L\",\n  \"ļ\": \"l\",\n  \"Ľ\": \"L\",\n  \"ľ\": \"l\",\n  \"Ń\": \"N\",\n  \"ń\": \"n\",\n  \"Ņ\": \"N\",\n  \"ņ\": \"n\",\n  \"Ň\": \"N\",\n  \"ň\": \"n\",\n  \"Ō\": \"O\",\n  \"ō\": \"o\",\n  \"Ŏ\": \"O\",\n  \"ŏ\": \"o\",\n  \"Ő\": \"O\",\n  \"ő\": \"o\",\n  \"Ŕ\": \"R\",\n  \"ŕ\": \"r\",\n  \"Ŗ\": \"R\",\n  \"ŗ\": \"r\",\n  \"Ř\": \"R\",\n  \"ř\": \"r\",\n  \"Ś\": \"S\",\n  \"ś\": \"s\",\n  \"Ŝ\": \"S\",\n  \"ŝ\": \"s\",\n  \"Ş\": \"S\",\n  \"ş\": \"s\",\n  \"Š\": \"S\",\n  \"š\": \"s\",\n  \"Ţ\": \"T\",\n  \"ţ\": \"t\",\n  \"Ť\": \"T\",\n  \"ť\": \"t\",\n  \"Ũ\": \"U\",\n  \"ũ\": \"u\",\n  \"Ū\": \"U\",\n  \"ū\": \"u\",\n  \"Ŭ\": \"U\",\n  \"ŭ\": \"u\",\n  \"Ů\": \"U\",\n  \"ů\": \"u\",\n  \"Ű\": \"U\",\n  \"ű\": \"u\",\n  \"Ų\": \"U\",\n  \"ų\": \"u\",\n  \"Ŵ\": \"W\",\n  \"ŵ\": \"w\",\n  \"Ŷ\": \"Y\",\n  \"ŷ\": \"y\",\n  \"Ÿ\": \"Y\",\n  \"Ź\": \"Z\",\n  \"ź\": \"z\",\n  \"Ż\": \"Z\",\n  \"ż\": \"z\",\n  \"Ž\": \"Z\",\n  \"ž\": \"z\",\n  \"Ơ\": \"O\",\n  \"ơ\": \"o\",\n  \"Ư\": \"U\",\n  \"ư\": \"u\",\n  \"Ǎ\": \"A\",\n  \"ǎ\": \"a\",\n  \"Ǐ\": \"I\",\n  \"ǐ\": \"i\",\n  \"Ǒ\": \"O\",\n  \"ǒ\": \"o\",\n  \"Ǔ\": \"U\",\n  \"ǔ\": \"u\",\n  \"Ǖ\": \"U\",\n  \"ǖ\": \"u\",\n  \"Ǘ\": \"U\",\n  \"ǘ\": \"u\",\n  \"Ǚ\": \"U\",\n  \"ǚ\": \"u\",\n  \"Ǜ\": \"U\",\n  \"ǜ\": \"u\",\n  \"Ǟ\": \"A\",\n  \"ǟ\": \"a\",\n  \"Ǡ\": \"A\",\n  \"ǡ\": \"a\",\n  \"Ǣ\": \"Æ\",\n  \"ǣ\": \"æ\",\n  \"Ǧ\": \"G\",\n  \"ǧ\": \"g\",\n  \"Ǩ\": \"K\",\n  \"ǩ\": \"k\",\n  \"Ǫ\": \"O\",\n  \"ǫ\": \"o\",\n  \"Ǭ\": \"O\",\n  \"ǭ\": \"o\",\n  \"Ǯ\": \"Ʒ\",\n  \"ǯ\": \"ʒ\",\n  \"ǰ\": \"j\",\n  \"Ǵ\": \"G\",\n  \"ǵ\": \"g\",\n  \"Ǹ\": \"N\",\n  \"ǹ\": \"n\",\n  \"Ǻ\": \"A\",\n  \"ǻ\": \"a\",\n  \"Ǽ\": \"Æ\",\n  \"ǽ\": \"æ\",\n  \"Ǿ\": \"Ø\",\n  \"ǿ\": \"ø\",\n  \"Ȁ\": \"A\",\n  \"ȁ\": \"a\",\n  \"Ȃ\": \"A\",\n  \"ȃ\": \"a\",\n  \"Ȅ\": \"E\",\n  \"ȅ\": \"e\",\n  \"Ȇ\": \"E\",\n  \"ȇ\": \"e\",\n  \"Ȉ\": \"I\",\n  \"ȉ\": \"i\",\n  \"Ȋ\": \"I\",\n  \"ȋ\": \"i\",\n  \"Ȍ\": \"O\",\n  \"ȍ\": \"o\",\n  \"Ȏ\": \"O\",\n  \"ȏ\": \"o\",\n  \"Ȑ\": \"R\",\n  \"ȑ\": \"r\",\n  \"Ȓ\": \"R\",\n  \"ȓ\": \"r\",\n  \"Ȕ\": \"U\",\n  \"ȕ\": \"u\",\n  \"Ȗ\": \"U\",\n  \"ȗ\": \"u\",\n  \"Ș\": \"S\",\n  \"ș\": \"s\",\n  \"Ț\": \"T\",\n  \"ț\": \"t\",\n  \"Ȟ\": \"H\",\n  \"ȟ\": \"h\",\n  \"Ȧ\": \"A\",\n  \"ȧ\": \"a\",\n  \"Ȩ\": \"E\",\n  \"ȩ\": \"e\",\n  \"Ȫ\": \"O\",\n  \"ȫ\": \"o\",\n  \"Ȭ\": \"O\",\n  \"ȭ\": \"o\",\n  \"Ȯ\": \"O\",\n  \"ȯ\": \"o\",\n  \"Ȱ\": \"O\",\n  \"ȱ\": \"o\",\n  \"Ȳ\": \"Y\",\n  \"ȳ\": \"y\",\n  \"΅\": \"¨\",\n  \"Ά\": \"Α\",\n  \"Έ\": \"Ε\",\n  \"Ή\": \"Η\",\n  \"Ί\": \"Ι\",\n  \"Ό\": \"Ο\",\n  \"Ύ\": \"Υ\",\n  \"Ώ\": \"Ω\",\n  \"ΐ\": \"ι\",\n  \"Ϊ\": \"Ι\",\n  \"Ϋ\": \"Υ\",\n  \"ά\": \"α\",\n  \"έ\": \"ε\",\n  \"ή\": \"η\",\n  \"ί\": \"ι\",\n  \"ΰ\": \"υ\",\n  \"ϊ\": \"ι\",\n  \"ϋ\": \"υ\",\n  \"ό\": \"ο\",\n  \"ύ\": \"υ\",\n  \"ώ\": \"ω\",\n  \"ϓ\": \"ϒ\",\n  \"ϔ\": \"ϒ\",\n  \"Ѐ\": \"Е\",\n  \"Ё\": \"Е\",\n  \"Ѓ\": \"Г\",\n  \"Ї\": \"І\",\n  \"Ќ\": \"К\",\n  \"Ѝ\": \"И\",\n  \"Ў\": \"У\",\n  \"Й\": \"И\",\n  \"й\": \"и\",\n  \"ѐ\": \"е\",\n  \"ё\": \"е\",\n  \"ѓ\": \"г\",\n  \"ї\": \"і\",\n  \"ќ\": \"к\",\n  \"ѝ\": \"и\",\n  \"ў\": \"у\",\n  \"Ѷ\": \"Ѵ\",\n  \"ѷ\": \"ѵ\",\n  \"Ӂ\": \"Ж\",\n  \"ӂ\": \"ж\",\n  \"Ӑ\": \"А\",\n  \"ӑ\": \"а\",\n  \"Ӓ\": \"А\",\n  \"ӓ\": \"а\",\n  \"Ӗ\": \"Е\",\n  \"ӗ\": \"е\",\n  \"Ӛ\": \"Ә\",\n  \"ӛ\": \"ә\",\n  \"Ӝ\": \"Ж\",\n  \"ӝ\": \"ж\",\n  \"Ӟ\": \"З\",\n  \"ӟ\": \"з\",\n  \"Ӣ\": \"И\",\n  \"ӣ\": \"и\",\n  \"Ӥ\": \"И\",\n  \"ӥ\": \"и\",\n  \"Ӧ\": \"О\",\n  \"ӧ\": \"о\",\n  \"Ӫ\": \"Ө\",\n  \"ӫ\": \"ө\",\n  \"Ӭ\": \"Э\",\n  \"ӭ\": \"э\",\n  \"Ӯ\": \"У\",\n  \"ӯ\": \"у\",\n  \"Ӱ\": \"У\",\n  \"ӱ\": \"у\",\n  \"Ӳ\": \"У\",\n  \"ӳ\": \"у\",\n  \"Ӵ\": \"Ч\",\n  \"ӵ\": \"ч\",\n  \"Ӹ\": \"Ы\",\n  \"ӹ\": \"ы\",\n  \"Ḁ\": \"A\",\n  \"ḁ\": \"a\",\n  \"Ḃ\": \"B\",\n  \"ḃ\": \"b\",\n  \"Ḅ\": \"B\",\n  \"ḅ\": \"b\",\n  \"Ḇ\": \"B\",\n  \"ḇ\": \"b\",\n  \"Ḉ\": \"C\",\n  \"ḉ\": \"c\",\n  \"Ḋ\": \"D\",\n  \"ḋ\": \"d\",\n  \"Ḍ\": \"D\",\n  \"ḍ\": \"d\",\n  \"Ḏ\": \"D\",\n  \"ḏ\": \"d\",\n  \"Ḑ\": \"D\",\n  \"ḑ\": \"d\",\n  \"Ḓ\": \"D\",\n  \"ḓ\": \"d\",\n  \"Ḕ\": \"E\",\n  \"ḕ\": \"e\",\n  \"Ḗ\": \"E\",\n  \"ḗ\": \"e\",\n  \"Ḙ\": \"E\",\n  \"ḙ\": \"e\",\n  \"Ḛ\": \"E\",\n  \"ḛ\": \"e\",\n  \"Ḝ\": \"E\",\n  \"ḝ\": \"e\",\n  \"Ḟ\": \"F\",\n  \"ḟ\": \"f\",\n  \"Ḡ\": \"G\",\n  \"ḡ\": \"g\",\n  \"Ḣ\": \"H\",\n  \"ḣ\": \"h\",\n  \"Ḥ\": \"H\",\n  \"ḥ\": \"h\",\n  \"Ḧ\": \"H\",\n  \"ḧ\": \"h\",\n  \"Ḩ\": \"H\",\n  \"ḩ\": \"h\",\n  \"Ḫ\": \"H\",\n  \"ḫ\": \"h\",\n  \"Ḭ\": \"I\",\n  \"ḭ\": \"i\",\n  \"Ḯ\": \"I\",\n  \"ḯ\": \"i\",\n  \"Ḱ\": \"K\",\n  \"ḱ\": \"k\",\n  \"Ḳ\": \"K\",\n  \"ḳ\": \"k\",\n  \"Ḵ\": \"K\",\n  \"ḵ\": \"k\",\n  \"Ḷ\": \"L\",\n  \"ḷ\": \"l\",\n  \"Ḹ\": \"L\",\n  \"ḹ\": \"l\",\n  \"Ḻ\": \"L\",\n  \"ḻ\": \"l\",\n  \"Ḽ\": \"L\",\n  \"ḽ\": \"l\",\n  \"Ḿ\": \"M\",\n  \"ḿ\": \"m\",\n  \"Ṁ\": \"M\",\n  \"ṁ\": \"m\",\n  \"Ṃ\": \"M\",\n  \"ṃ\": \"m\",\n  \"Ṅ\": \"N\",\n  \"ṅ\": \"n\",\n  \"Ṇ\": \"N\",\n  \"ṇ\": \"n\",\n  \"Ṉ\": \"N\",\n  \"ṉ\": \"n\",\n  \"Ṋ\": \"N\",\n  \"ṋ\": \"n\",\n  \"Ṍ\": \"O\",\n  \"ṍ\": \"o\",\n  \"Ṏ\": \"O\",\n  \"ṏ\": \"o\",\n  \"Ṑ\": \"O\",\n  \"ṑ\": \"o\",\n  \"Ṓ\": \"O\",\n  \"ṓ\": \"o\",\n  \"Ṕ\": \"P\",\n  \"ṕ\": \"p\",\n  \"Ṗ\": \"P\",\n  \"ṗ\": \"p\",\n  \"Ṙ\": \"R\",\n  \"ṙ\": \"r\",\n  \"Ṛ\": \"R\",\n  \"ṛ\": \"r\",\n  \"Ṝ\": \"R\",\n  \"ṝ\": \"r\",\n  \"Ṟ\": \"R\",\n  \"ṟ\": \"r\",\n  \"Ṡ\": \"S\",\n  \"ṡ\": \"s\",\n  \"Ṣ\": \"S\",\n  \"ṣ\": \"s\",\n  \"Ṥ\": \"S\",\n  \"ṥ\": \"s\",\n  \"Ṧ\": \"S\",\n  \"ṧ\": \"s\",\n  \"Ṩ\": \"S\",\n  \"ṩ\": \"s\",\n  \"Ṫ\": \"T\",\n  \"ṫ\": \"t\",\n  \"Ṭ\": \"T\",\n  \"ṭ\": \"t\",\n  \"Ṯ\": \"T\",\n  \"ṯ\": \"t\",\n  \"Ṱ\": \"T\",\n  \"ṱ\": \"t\",\n  \"Ṳ\": \"U\",\n  \"ṳ\": \"u\",\n  \"Ṵ\": \"U\",\n  \"ṵ\": \"u\",\n  \"Ṷ\": \"U\",\n  \"ṷ\": \"u\",\n  \"Ṹ\": \"U\",\n  \"ṹ\": \"u\",\n  \"Ṻ\": \"U\",\n  \"ṻ\": \"u\",\n  \"Ṽ\": \"V\",\n  \"ṽ\": \"v\",\n  \"Ṿ\": \"V\",\n  \"ṿ\": \"v\",\n  \"Ẁ\": \"W\",\n  \"ẁ\": \"w\",\n  \"Ẃ\": \"W\",\n  \"ẃ\": \"w\",\n  \"Ẅ\": \"W\",\n  \"ẅ\": \"w\",\n  \"Ẇ\": \"W\",\n  \"ẇ\": \"w\",\n  \"Ẉ\": \"W\",\n  \"ẉ\": \"w\",\n  \"Ẋ\": \"X\",\n  \"ẋ\": \"x\",\n  \"Ẍ\": \"X\",\n  \"ẍ\": \"x\",\n  \"Ẏ\": \"Y\",\n  \"ẏ\": \"y\",\n  \"Ẑ\": \"Z\",\n  \"ẑ\": \"z\",\n  \"Ẓ\": \"Z\",\n  \"ẓ\": \"z\",\n  \"Ẕ\": \"Z\",\n  \"ẕ\": \"z\",\n  \"ẖ\": \"h\",\n  \"ẗ\": \"t\",\n  \"ẘ\": \"w\",\n  \"ẙ\": \"y\",\n  \"ẛ\": \"ſ\",\n  \"Ạ\": \"A\",\n  \"ạ\": \"a\",\n  \"Ả\": \"A\",\n  \"ả\": \"a\",\n  \"Ấ\": \"A\",\n  \"ấ\": \"a\",\n  \"Ầ\": \"A\",\n  \"ầ\": \"a\",\n  \"Ẩ\": \"A\",\n  \"ẩ\": \"a\",\n  \"Ẫ\": \"A\",\n  \"ẫ\": \"a\",\n  \"Ậ\": \"A\",\n  \"ậ\": \"a\",\n  \"Ắ\": \"A\",\n  \"ắ\": \"a\",\n  \"Ằ\": \"A\",\n  \"ằ\": \"a\",\n  \"Ẳ\": \"A\",\n  \"ẳ\": \"a\",\n  \"Ẵ\": \"A\",\n  \"ẵ\": \"a\",\n  \"Ặ\": \"A\",\n  \"ặ\": \"a\",\n  \"Ẹ\": \"E\",\n  \"ẹ\": \"e\",\n  \"Ẻ\": \"E\",\n  \"ẻ\": \"e\",\n  \"Ẽ\": \"E\",\n  \"ẽ\": \"e\",\n  \"Ế\": \"E\",\n  \"ế\": \"e\",\n  \"Ề\": \"E\",\n  \"ề\": \"e\",\n  \"Ể\": \"E\",\n  \"ể\": \"e\",\n  \"Ễ\": \"E\",\n  \"ễ\": \"e\",\n  \"Ệ\": \"E\",\n  \"ệ\": \"e\",\n  \"Ỉ\": \"I\",\n  \"ỉ\": \"i\",\n  \"Ị\": \"I\",\n  \"ị\": \"i\",\n  \"Ọ\": \"O\",\n  \"ọ\": \"o\",\n  \"Ỏ\": \"O\",\n  \"ỏ\": \"o\",\n  \"Ố\": \"O\",\n  \"ố\": \"o\",\n  \"Ồ\": \"O\",\n  \"ồ\": \"o\",\n  \"Ổ\": \"O\",\n  \"ổ\": \"o\",\n  \"Ỗ\": \"O\",\n  \"ỗ\": \"o\",\n  \"Ộ\": \"O\",\n  \"ộ\": \"o\",\n  \"Ớ\": \"O\",\n  \"ớ\": \"o\",\n  \"Ờ\": \"O\",\n  \"ờ\": \"o\",\n  \"Ở\": \"O\",\n  \"ở\": \"o\",\n  \"Ỡ\": \"O\",\n  \"ỡ\": \"o\",\n  \"Ợ\": \"O\",\n  \"ợ\": \"o\",\n  \"Ụ\": \"U\",\n  \"ụ\": \"u\",\n  \"Ủ\": \"U\",\n  \"ủ\": \"u\",\n  \"Ứ\": \"U\",\n  \"ứ\": \"u\",\n  \"Ừ\": \"U\",\n  \"ừ\": \"u\",\n  \"Ử\": \"U\",\n  \"ử\": \"u\",\n  \"Ữ\": \"U\",\n  \"ữ\": \"u\",\n  \"Ự\": \"U\",\n  \"ự\": \"u\",\n  \"Ỳ\": \"Y\",\n  \"ỳ\": \"y\",\n  \"Ỵ\": \"Y\",\n  \"ỵ\": \"y\",\n  \"Ỷ\": \"Y\",\n  \"ỷ\": \"y\",\n  \"Ỹ\": \"Y\",\n  \"ỹ\": \"y\",\n  \"ἀ\": \"α\",\n  \"ἁ\": \"α\",\n  \"ἂ\": \"α\",\n  \"ἃ\": \"α\",\n  \"ἄ\": \"α\",\n  \"ἅ\": \"α\",\n  \"ἆ\": \"α\",\n  \"ἇ\": \"α\",\n  \"Ἀ\": \"Α\",\n  \"Ἁ\": \"Α\",\n  \"Ἂ\": \"Α\",\n  \"Ἃ\": \"Α\",\n  \"Ἄ\": \"Α\",\n  \"Ἅ\": \"Α\",\n  \"Ἆ\": \"Α\",\n  \"Ἇ\": \"Α\",\n  \"ἐ\": \"ε\",\n  \"ἑ\": \"ε\",\n  \"ἒ\": \"ε\",\n  \"ἓ\": \"ε\",\n  \"ἔ\": \"ε\",\n  \"ἕ\": \"ε\",\n  \"Ἐ\": \"Ε\",\n  \"Ἑ\": \"Ε\",\n  \"Ἒ\": \"Ε\",\n  \"Ἓ\": \"Ε\",\n  \"Ἔ\": \"Ε\",\n  \"Ἕ\": \"Ε\",\n  \"ἠ\": \"η\",\n  \"ἡ\": \"η\",\n  \"ἢ\": \"η\",\n  \"ἣ\": \"η\",\n  \"ἤ\": \"η\",\n  \"ἥ\": \"η\",\n  \"ἦ\": \"η\",\n  \"ἧ\": \"η\",\n  \"Ἠ\": \"Η\",\n  \"Ἡ\": \"Η\",\n  \"Ἢ\": \"Η\",\n  \"Ἣ\": \"Η\",\n  \"Ἤ\": \"Η\",\n  \"Ἥ\": \"Η\",\n  \"Ἦ\": \"Η\",\n  \"Ἧ\": \"Η\",\n  \"ἰ\": \"ι\",\n  \"ἱ\": \"ι\",\n  \"ἲ\": \"ι\",\n  \"ἳ\": \"ι\",\n  \"ἴ\": \"ι\",\n  \"ἵ\": \"ι\",\n  \"ἶ\": \"ι\",\n  \"ἷ\": \"ι\",\n  \"Ἰ\": \"Ι\",\n  \"Ἱ\": \"Ι\",\n  \"Ἲ\": \"Ι\",\n  \"Ἳ\": \"Ι\",\n  \"Ἴ\": \"Ι\",\n  \"Ἵ\": \"Ι\",\n  \"Ἶ\": \"Ι\",\n  \"Ἷ\": \"Ι\",\n  \"ὀ\": \"ο\",\n  \"ὁ\": \"ο\",\n  \"ὂ\": \"ο\",\n  \"ὃ\": \"ο\",\n  \"ὄ\": \"ο\",\n  \"ὅ\": \"ο\",\n  \"Ὀ\": \"Ο\",\n  \"Ὁ\": \"Ο\",\n  \"Ὂ\": \"Ο\",\n  \"Ὃ\": \"Ο\",\n  \"Ὄ\": \"Ο\",\n  \"Ὅ\": \"Ο\",\n  \"ὐ\": \"υ\",\n  \"ὑ\": \"υ\",\n  \"ὒ\": \"υ\",\n  \"ὓ\": \"υ\",\n  \"ὔ\": \"υ\",\n  \"ὕ\": \"υ\",\n  \"ὖ\": \"υ\",\n  \"ὗ\": \"υ\",\n  \"Ὑ\": \"Υ\",\n  \"Ὓ\": \"Υ\",\n  \"Ὕ\": \"Υ\",\n  \"Ὗ\": \"Υ\",\n  \"ὠ\": \"ω\",\n  \"ὡ\": \"ω\",\n  \"ὢ\": \"ω\",\n  \"ὣ\": \"ω\",\n  \"ὤ\": \"ω\",\n  \"ὥ\": \"ω\",\n  \"ὦ\": \"ω\",\n  \"ὧ\": \"ω\",\n  \"Ὠ\": \"Ω\",\n  \"Ὡ\": \"Ω\",\n  \"Ὢ\": \"Ω\",\n  \"Ὣ\": \"Ω\",\n  \"Ὤ\": \"Ω\",\n  \"Ὥ\": \"Ω\",\n  \"Ὦ\": \"Ω\",\n  \"Ὧ\": \"Ω\",\n  \"ὰ\": \"α\",\n  \"ά\": \"α\",\n  \"ὲ\": \"ε\",\n  \"έ\": \"ε\",\n  \"ὴ\": \"η\",\n  \"ή\": \"η\",\n  \"ὶ\": \"ι\",\n  \"ί\": \"ι\",\n  \"ὸ\": \"ο\",\n  \"ό\": \"ο\",\n  \"ὺ\": \"υ\",\n  \"ύ\": \"υ\",\n  \"ὼ\": \"ω\",\n  \"ώ\": \"ω\",\n  \"ᾀ\": \"α\",\n  \"ᾁ\": \"α\",\n  \"ᾂ\": \"α\",\n  \"ᾃ\": \"α\",\n  \"ᾄ\": \"α\",\n  \"ᾅ\": \"α\",\n  \"ᾆ\": \"α\",\n  \"ᾇ\": \"α\",\n  \"ᾈ\": \"Α\",\n  \"ᾉ\": \"Α\",\n  \"ᾊ\": \"Α\",\n  \"ᾋ\": \"Α\",\n  \"ᾌ\": \"Α\",\n  \"ᾍ\": \"Α\",\n  \"ᾎ\": \"Α\",\n  \"ᾏ\": \"Α\",\n  \"ᾐ\": \"η\",\n  \"ᾑ\": \"η\",\n  \"ᾒ\": \"η\",\n  \"ᾓ\": \"η\",\n  \"ᾔ\": \"η\",\n  \"ᾕ\": \"η\",\n  \"ᾖ\": \"η\",\n  \"ᾗ\": \"η\",\n  \"ᾘ\": \"Η\",\n  \"ᾙ\": \"Η\",\n  \"ᾚ\": \"Η\",\n  \"ᾛ\": \"Η\",\n  \"ᾜ\": \"Η\",\n  \"ᾝ\": \"Η\",\n  \"ᾞ\": \"Η\",\n  \"ᾟ\": \"Η\",\n  \"ᾠ\": \"ω\",\n  \"ᾡ\": \"ω\",\n  \"ᾢ\": \"ω\",\n  \"ᾣ\": \"ω\",\n  \"ᾤ\": \"ω\",\n  \"ᾥ\": \"ω\",\n  \"ᾦ\": \"ω\",\n  \"ᾧ\": \"ω\",\n  \"ᾨ\": \"Ω\",\n  \"ᾩ\": \"Ω\",\n  \"ᾪ\": \"Ω\",\n  \"ᾫ\": \"Ω\",\n  \"ᾬ\": \"Ω\",\n  \"ᾭ\": \"Ω\",\n  \"ᾮ\": \"Ω\",\n  \"ᾯ\": \"Ω\",\n  \"ᾰ\": \"α\",\n  \"ᾱ\": \"α\",\n  \"ᾲ\": \"α\",\n  \"ᾳ\": \"α\",\n  \"ᾴ\": \"α\",\n  \"ᾶ\": \"α\",\n  \"ᾷ\": \"α\",\n  \"Ᾰ\": \"Α\",\n  \"Ᾱ\": \"Α\",\n  \"Ὰ\": \"Α\",\n  \"Ά\": \"Α\",\n  \"ᾼ\": \"Α\",\n  \"῁\": \"¨\",\n  \"ῂ\": \"η\",\n  \"ῃ\": \"η\",\n  \"ῄ\": \"η\",\n  \"ῆ\": \"η\",\n  \"ῇ\": \"η\",\n  \"Ὲ\": \"Ε\",\n  \"Έ\": \"Ε\",\n  \"Ὴ\": \"Η\",\n  \"Ή\": \"Η\",\n  \"ῌ\": \"Η\",\n  \"῍\": \"᾿\",\n  \"῎\": \"᾿\",\n  \"῏\": \"᾿\",\n  \"ῐ\": \"ι\",\n  \"ῑ\": \"ι\",\n  \"ῒ\": \"ι\",\n  \"ΐ\": \"ι\",\n  \"ῖ\": \"ι\",\n  \"ῗ\": \"ι\",\n  \"Ῐ\": \"Ι\",\n  \"Ῑ\": \"Ι\",\n  \"Ὶ\": \"Ι\",\n  \"Ί\": \"Ι\",\n  \"῝\": \"῾\",\n  \"῞\": \"῾\",\n  \"῟\": \"῾\",\n  \"ῠ\": \"υ\",\n  \"ῡ\": \"υ\",\n  \"ῢ\": \"υ\",\n  \"ΰ\": \"υ\",\n  \"ῤ\": \"ρ\",\n  \"ῥ\": \"ρ\",\n  \"ῦ\": \"υ\",\n  \"ῧ\": \"υ\",\n  \"Ῠ\": \"Υ\",\n  \"Ῡ\": \"Υ\",\n  \"Ὺ\": \"Υ\",\n  \"Ύ\": \"Υ\",\n  \"Ῥ\": \"Ρ\",\n  \"῭\": \"¨\",\n  \"΅\": \"¨\",\n  \"ῲ\": \"ω\",\n  \"ῳ\": \"ω\",\n  \"ῴ\": \"ω\",\n  \"ῶ\": \"ω\",\n  \"ῷ\": \"ω\",\n  \"Ὸ\": \"Ο\",\n  \"Ό\": \"Ο\",\n  \"Ὼ\": \"Ω\",\n  \"Ώ\": \"Ω\",\n  \"ῼ\": \"Ω\",\n  \"Å\": \"A\",\n  \"↚\": \"←\",\n  \"↛\": \"→\",\n  \"↮\": \"↔\",\n  \"⇍\": \"⇐\",\n  \"⇎\": \"⇔\",\n  \"⇏\": \"⇒\",\n  \"∄\": \"∃\",\n  \"∉\": \"∈\",\n  \"∌\": \"∋\",\n  \"∤\": \"∣\",\n  \"∦\": \"∥\",\n  \"≁\": \"∼\",\n  \"≄\": \"≃\",\n  \"≇\": \"≅\",\n  \"≉\": \"≈\",\n  \"≠\": \"=\",\n  \"≢\": \"≡\",\n  \"≭\": \"≍\",\n  \"≮\": \"<\",\n  \"≯\": \">\",\n  \"≰\": \"≤\",\n  \"≱\": \"≥\",\n  \"≴\": \"≲\",\n  \"≵\": \"≳\",\n  \"≸\": \"≶\",\n  \"≹\": \"≷\",\n  \"⊀\": \"≺\",\n  \"⊁\": \"≻\",\n  \"⊄\": \"⊂\",\n  \"⊅\": \"⊃\",\n  \"⊈\": \"⊆\",\n  \"⊉\": \"⊇\",\n  \"⊬\": \"⊢\",\n  \"⊭\": \"⊨\",\n  \"⊮\": \"⊩\",\n  \"⊯\": \"⊫\",\n  \"⋠\": \"≼\",\n  \"⋡\": \"≽\",\n  \"⋢\": \"⊑\",\n  \"⋣\": \"⊒\",\n  \"⋪\": \"⊲\",\n  \"⋫\": \"⊳\",\n  \"⋬\": \"⊴\",\n  \"⋭\": \"⊵\",\n  \"⫝̸\": \"⫝\",\n};\n","/**\n * Common formatters — port of guessit/rules/common/formatters.py\n */\nimport { seps } from './index.js';\nimport { formatters as composeFormatters } from 'rebulk-js';\nimport { DIACRITIC_FOLD } from './diacritics.js';\n\n/**\n * Strip diacritics from a string, reproducing V8's\n *   s.normalize('NFD').replace(/[̀-ͯ]/g, '')\n * for every accented letter in every script (Latin, Greek, Cyrillic, Vietnamese,\n * …) WITHOUT calling `String.prototype.normalize` — QuickJS (the runtime Javy\n * compiles to WASM) doesn't implement `normalize` at all, so relying on it would\n * make the WASM build diverge from the JS build on any accented title (e.g.\n * \"Hôtel\", \"Rêves\", \"Ολυμπιάδα\"). The folding table in `./diacritics.ts` is\n * generated from V8's NFD (scripts/gen-diacritics.mjs), so both engines fold\n * identically. The trailing regex also removes any already-decomposed standalone\n * combining marks (U+0300–U+036F), which works in both engines.\n */\nexport function foldDiacritics(input: string): string {\n  let out = '';\n  for (const ch of input) out += DIACRITIC_FOLD[ch] ?? ch;\n  return out.replace(/[̀-ͯ]/g, '');\n}\n\n// Characters excluded from cleanup stripping (we keep them inside)\nconst EXCLUDED_CLEAN_CHARS = new Set([',', ':', ';', '-', '/', '\\\\']);\nconst cleanChars = seps.split('').filter(c => !EXCLUDED_CLEAN_CHARS.has(c)).join('');\n\nfunction potentialBefore(i: number, inputString: string): boolean {\n  return (\n    i - 1 >= 0 &&\n    seps.includes(inputString[i]) &&\n    (i - 2 < 0 || seps.includes(inputString[i - 2])) &&\n    !seps.includes(inputString[i - 1])\n  );\n}\n\nfunction potentialAfter(i: number, inputString: string): boolean {\n  return (\n    i + 2 >= inputString.length ||\n    (inputString[i + 2] === inputString[i] && !seps.includes(inputString[i + 1]))\n  );\n}\n\n/**\n * Remove and strip separators from inputString (but keep ',;' characters).\n * Also keeps separators for single characters (e.g., S.H.I.E.L.D.).\n */\nexport function cleanup(inputString: string): string {\n  if (!inputString) return inputString;\n\n  // Replace clean chars with spaces\n  let cleanString = inputString;\n  for (const char of cleanChars) {\n    cleanString = cleanString.split(char).join(' ');\n  }\n\n  // Find indices where separators remain\n  const indices: number[] = [];\n  for (let i = 0; i < cleanString.length; i++) {\n    if (seps.includes(cleanString[i])) indices.push(i);\n  }\n\n  const dots = new Set<string>();\n  if (indices.length > 0) {\n    const cleanList = cleanString.split('');\n\n    const potentialIndices: number[] = [];\n    for (const i of indices) {\n      if (potentialBefore(i, inputString) && potentialAfter(i, inputString)) {\n        potentialIndices.push(i);\n      }\n    }\n\n    const replaceIndices: number[] = [];\n    for (const pi of potentialIndices) {\n      if (potentialIndices.includes(pi - 2) || potentialIndices.includes(pi + 2)) {\n        replaceIndices.push(pi);\n      }\n    }\n\n    if (replaceIndices.length > 0) {\n      for (const ri of replaceIndices) {\n        dots.add(inputString[ri]);\n        cleanList[ri] = inputString[ri];\n      }\n      cleanString = cleanList.join('');\n    }\n  }\n\n  // A dotted version run trailing a title is one token (\"Evangelion.3.0.1.11\").\n  // The acronym rule above only keeps a separator between single characters, so\n  // the \".11\" tail would be split off; restore every dot inside the run\n  // (upstream #963). A run that opens the value is the title itself and keeps\n  // Python's spelling — the show \"11.22.63\" is titled \"11 22 63\".\n  const versionDots: number[] = [];\n  const versionPattern = /\\d+(?:\\.\\d+){2,}/g;\n  let versionMatch: RegExpExecArray | null;\n  while ((versionMatch = versionPattern.exec(inputString)) !== null) {\n    if (!/[^\\s._-]/.test(inputString.slice(0, versionMatch.index))) continue;\n    for (let i = versionMatch.index; i < versionMatch.index + versionMatch[0].length; i++) {\n      if (inputString[i] === '.') versionDots.push(i);\n    }\n  }\n  if (versionDots.length > 0) {\n    const cleanList = cleanString.split('');\n    for (const i of versionDots) cleanList[i] = '.';\n    dots.add('.');\n    cleanString = cleanList.join('');\n  }\n\n  // Strip surrounding separators (except preserved dots)\n  const stripChars = seps.split('').filter(c => !dots.has(c)).join('');\n  cleanString = strip(cleanString, stripChars);\n\n  // A decimal version at the end of a title (\"Jackass.2.5.\", \"M3GAN.2.0.\")\n  // keeps its inner dot through the acronym rule above, but the trailing\n  // separator is just the gap to the next property — drop it. Real acronyms\n  // (\"S.H.I.E.L.D.\") end in a letter, so they are untouched (upstream #963).\n  if (/(?:^|[ ])\\d+\\.\\d+\\.$/.test(cleanString)) {\n    cleanString = cleanString.slice(0, -1);\n  }\n\n  // Collapse multiple spaces\n  cleanString = cleanString.replace(/ +/g, ' ');\n  return cleanString;\n}\n\n/**\n * Strip separator characters from both ends of the string.\n */\nexport function strip(inputString: string, chars: string = seps): string {\n  let start = 0;\n  let end = inputString.length;\n  while (start < end && chars.includes(inputString[start])) start++;\n  while (end > start && chars.includes(inputString[end - 1])) end--;\n  return inputString.slice(start, end);\n}\n\n/**\n * Cleanup a raw value to perform raw comparison.\n */\nexport function rawCleanup(raw: string): string {\n  return composeFormatters(cleanup, strip)(raw.toLowerCase()) as string;\n}\n\n/**\n * Reorder the title by moving a trailing article to the front.\n * \"The Dark Knight, The\" → \"The Dark Knight\"\n * Also handles moving leading article to end: not the primary direction in Python.\n * Python's reorder_title moves \"title, the\" patterns to canonical form.\n */\nexport function reorderTitle(\n  title: string,\n  articles: string[] = ['the'],\n  separators: string[] = [', ', ','],\n): string {\n  const ltitle = title.toLowerCase();\n  for (const article of articles) {\n    for (const separator of separators) {\n      const suffix = separator + article;\n      if (ltitle.endsWith(suffix)) {\n        return title.slice(title.length - suffix.length + separator.length) + ' ' + title.slice(0, title.length - suffix.length);\n      }\n    }\n  }\n  return title;\n}\n","/**\n * Pattern helpers — port of guessit/rules/common/pattern.py\n */\nimport type { Context } from 'rebulk-js';\n\n/**\n * Check if a property is disabled in the current context.\n * Used by property builders: disabled=lambda context: is_disabled(context, 'video_codec')\n */\nexport function isDisabled(context: Context | undefined, name: string): boolean {\n  if (!context) return false;\n  const excludes = context['excludes'] as string[] | undefined;\n  const includes = context['includes'] as string[] | undefined;\n  if (excludes && excludes.includes(name)) return true;\n  if (includes && includes.length > 0 && !includes.includes(name)) return true;\n  return false;\n}\n","/**\n * Episodes property — port of guessit/rules/properties/episodes.py\n * Detects season/episode patterns, absolute episodes, and episode details\n */\nimport { Rebulk, Rule, RemoveMatch, AppendMatch, RenameMatch } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport { buildOrPattern } from '../../reutils.js';\nimport { parseNumber, numericFunction } from '../common/numeral.js';\nimport { intCoercable, and_, sepsSurround } from '../common/validators.js';\nimport { cleanup } from '../common/formatters.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { seps, altDash } from '../common/index.js';\n\ninterface EpisodesConfig {\n  season_max_range: number;\n  episode_max_range: number;\n  max_range_gap: number;\n  season_markers: string[];\n  season_ep_markers: string[];\n  disc_markers: string[];\n  episode_markers: string[];\n  range_separators: string[];\n  discrete_separators: string[];\n  season_words: (string | { value: string; numfirst?: boolean })[];\n  episode_words: (string | { value: string; numfirst?: boolean })[];\n  ordinal_suffix: string;\n  of_words: string[];\n  all_words: string[];\n}\n\nconst CJK_DIGITS: Record<string, number> = {\n  '零': 0, '一': 1, '二': 2, '两': 2, '三': 3, '四': 4,\n  '五': 5, '六': 6, '七': 7, '八': 8, '九': 9,\n};\n\n// ASCII digits or Han numerals up to 99 (十一 → 11, 二十三 → 23, single digit otherwise).\nconst CJK_NUMBER = '(?:\\\\d{1,4}|[一二两三四五六七八九]?十[一二两三四五六七八九]?|[零一二两三四五六七八九])';\n\nfunction parseCjkNumber(value: string): number {\n  if (/^\\d+$/.test(value)) return parseInt(value, 10);\n  if (value.includes('十')) {\n    const [tens, ones] = value.split('十');\n    const tensValue = tens ? CJK_DIGITS[tens] : 1;\n    const onesValue = ones ? CJK_DIGITS[ones] : 0;\n    return tensValue * 10 + onesValue;\n  }\n  return CJK_DIGITS[value];\n}\n\n/**\n * Split a season/episode word config into (all values, number-first values).\n * Each entry is a plain string (word-first only) or {value, numfirst}.\n * Mirrors Python's _split_words (upstream 4.x).\n */\nfunction splitWords(entries: (string | { value: string; numfirst?: boolean })[]): { words: string[]; numfirst: string[] } {\n  const words: string[] = [];\n  const numfirst: string[] = [];\n  for (const entry of entries) {\n    if (typeof entry === 'object') {\n      if (entry.numfirst) numfirst.push(entry.value);\n      words.push(entry.value);\n    } else {\n      words.push(entry);\n    }\n  }\n  return { words, numfirst };\n}\n\n/**\n * Chain breaker for episode/season chains\n */\nfunction episodesSeasonChainBreaker(\n  matches: any,\n  config: EpisodesConfig,\n): boolean {\n  const episodes = matches.named('episode') || [];\n  if (\n    episodes.length > 1 &&\n    Math.abs(episodes[episodes.length - 1].value - episodes[episodes.length - 2].value) >\n      config.episode_max_range\n  ) {\n    return true;\n  }\n\n  const seasons = matches.named('season') || [];\n  if (seasons.length > 1) {\n    const last = seasons[seasons.length - 1].value;\n    const prev = seasons[seasons.length - 2].value;\n    if (Math.abs(last - prev) > config.season_max_range) {\n      return true;\n    }\n    if (last < prev) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n/**\n * Conflict solver for season/episode patterns\n */\nfunction seasonEpisodeConflictSolver(match: any, other: any): any {\n  // Any two weak-family matches (weak_episode vs weak_duplicate, parents or\n  // children) keep BOTH: the default solver would annihilate same-span pairs\n  // (264 vs 2|64) before WeakConflictSolverRule can pick the right reading.\n  const weakFamily = (m: any) => !!(m?.tags?.includes('weak-episode') ||\n    ['weak_episode', 'weak_duplicate'].includes(m?.initiator?.name) ||\n    ['weak_episode', 'weak_duplicate'].includes(m?.name));\n  if (weakFamily(match) && weakFamily(other)) return null;\n  // A number-first private parent (\"60 Сезон\") colliding with a word-first private\n  // parent (\"Сезон 5\") on the marker word alone: keep BOTH and let\n  // RemoveNumfirstMarkerCollision decide with full context (it can see whether the\n  // word-first number is really a resolution, as in \"Temporada 720p\").\n  const famChild = (p: any) => {\n    if (p?.name) return null;\n    const ch = [...(p?.children ?? [])];\n    return ch.find((c: any) => c.name === 'season' || c.name === 'episode') ?? null;\n  };\n  const mChild = famChild(match);\n  const oChild = famChild(other);\n  if (mChild && oChild) {\n    const mNumfirst = !!mChild.tags?.includes('numfirst');\n    const oNumfirst = !!oChild.tags?.includes('numfirst');\n    if (mNumfirst !== oNumfirst) return null;\n  }\n  if (match.name !== other.name) {\n    if (match.name === 'episode' && other.name === 'year') {\n      return match;\n    }\n    if (['season', 'episode'].includes(match.name)) {\n      if (\n        [\n          'video_codec',\n          'audio_codec',\n          'container',\n          'date',\n        ].includes(other.name)\n      ) {\n        // A codec like \"h_264\" whose letter is glued to the preceding word is a\n        // phantom (\"Bleach_264\" is title + episode 264, upstream #877): the codec\n        // loses instead. Real \"h.264\"/\".x264\"/\"HDTVx264\" forms are untouched.\n        if (other.name === 'video_codec' && /^[hx][\\W_]\\d/i.test(String(other.raw ?? ''))) {\n          const before = (other.inputString ?? '')[other.start - 1] ?? '';\n          if (/[a-z]/i.test(before)) return other;\n        }\n        return match;\n      }\n      if (\n        (other.name === 'audio_channels' &&\n          !other.tags?.includes('weak-audio_channels') &&\n          !match.initiator?.children?.named(match.name + 'Marker')?.length) ||\n        (other.name === 'screen_size' && !intCoercable(other.raw))\n      ) {\n        return match;\n      }\n    }\n  }\n  // Handle cross-chain conflicts between season/episode matches (same or different names).\n  // This covers episode vs episode and season vs season where one is from a strong\n  // SxxExx chain and the other is from a weak-episode/weak-duplicate chain.\n  if (\n    ['season', 'episode'].includes(match.name) &&\n    ['season', 'episode'].includes(other.name) &&\n    match.initiator !== other.initiator\n  ) {\n    // A number-first form (\"1 Серия\") and a word-first form (\"Сезон 1\") claiming the\n    // same digits: pick the pairing that leaves no dangling number. \"Сезон 1 Серия 5\"\n    // reads word-first (numfirst \"1 Серия\" would orphan the 5); \"2 Sezon 7 Bolum\"\n    // reads number-first (word-first \"Sezon 7\" would orphan the leading 2). Marker-only\n    // overlaps (\"04ª Temporada\" vs \"Temporada 720\") are not number collisions.\n    const isWeak = (m: any) => !!(m.tags?.includes('weak-episode') ||\n      ['weak_episode', 'weak_duplicate'].includes(m.initiator?.name));\n    const matchNumfirst = !!match.tags?.includes('numfirst');\n    const otherNumfirst = !!other.tags?.includes('numfirst');\n    if (\n      matchNumfirst !== otherNumfirst &&\n      !isWeak(match) && !isWeak(other) &&\n      match.start < other.end && other.start < match.end\n    ) {\n      const nf = matchNumfirst ? match : other;\n      const wf = matchNumfirst ? other : match;\n      const input: string = match.inputString ?? '';\n      const digitToken = (from: number, dir: 1 | -1): string => {\n        let i = from;\n        while (i >= 0 && i < input.length && seps.includes(input[i])) i += dir;\n        let tok = '';\n        while (i >= 0 && i < input.length && /\\d/.test(input[i])) { tok = dir === 1 ? tok + input[i] : input[i] + tok; i += dir; }\n        return tok;\n      };\n      const isYearLike = (t: string) => t.length === 4 && +t >= 1900 && +t <= 2100;\n      const nfInit = nf.initiator ?? nf;\n      const wfInit = wf.initiator ?? wf;\n      const nfDangling = (() => { const t = digitToken(nfInit.end, 1); return t.length >= 1 && t.length <= 4 && !isYearLike(t); })();\n      // The dangling number before a word-first marker may carry an ordinal suffix\n      // (\"5-го сезон\", \"04ª Temporada\") — match it as one token.\n      const wfDangling = (() => {\n        const before = input.slice(Math.max(0, wfInit.start - 12), wfInit.start);\n        const m = /(\\d{1,3})(?:ª|º|°|a|o|-?(?:й|я|е|го|ая|ый|ое))?[\\s.,_\\-–]*$/iu.exec(before);\n        return !!(m && !isYearLike(m[1]));\n      })();\n      if (wfDangling && !nfDangling) return wf;\n      return nf;\n    }\n    const matchIsWeak = !!(match.tags?.includes('weak-episode') ||\n      ['weak_episode', 'weak_duplicate'].includes(match.initiator?.name));\n    const otherIsWeak = !!(other.tags?.includes('weak-episode') ||\n      ['weak_episode', 'weak_duplicate'].includes(other.initiator?.name));\n\n    // Both weak: keep BOTH here — the default solver would annihilate the pair\n    // (264 vs 2|64 on the same span) before WeakConflictSolverRule can pick the\n    // anime (weak_episode) or non-anime (weak_duplicate) reading.\n    if (matchIsWeak && otherIsWeak) {\n      return null;\n    }\n    // Only one is weak: remove it\n    if (matchIsWeak) return match;\n    if (otherIsWeak) return other;\n    // Prefer SxxExx-tagged matches over non-SxxExx when they conflict\n    // (e.g. \"Ep 2x03\": episode-word \"Ep 2\" vs SxxExx \"2x03\" → keep SxxExx)\n    const matchIsSxxExx = !!match.tags?.includes('SxxExx');\n    const otherIsSxxExx = !!other.tags?.includes('SxxExx');\n    if (matchIsSxxExx && !otherIsSxxExx) return other;\n    if (otherIsSxxExx && !matchIsSxxExx) return match;\n    // Neither weak but initiator raw contains 'x' (e.g. spurious season from \"x264\")\n    // Don't remove SxxExx-tagged matches even if they contain 'x' (e.g. \"2x03\" is valid)\n    const matchHasX = match.initiator?.raw?.toLowerCase().includes('x') && !matchIsSxxExx;\n    const otherHasX = other.initiator?.raw?.toLowerCase().includes('x') && !otherIsSxxExx;\n    if (matchHasX && !otherHasX) return match;\n    if (otherHasX && !matchHasX) return other;\n  }\n  return '__default__';\n}\n\n/**\n * Validate ordering of season/episode lists\n */\nfunction orderingValidator(match: any): boolean {\n  // rebulk-js names it toDict (to_dict was the Python spelling and always\n  // returned undefined here, silently skipping ordering validation)\n  const dict = match.children?.toDict?.() ?? match.children?.to_dict?.();\n  const values: any = dict instanceof Map ? Object.fromEntries(dict) : (dict || {});\n\n  if (values.season && Array.isArray(values.season)) {\n    const sorted = [...values.season].sort((a, b) => a - b);\n    if (JSON.stringify(sorted) !== JSON.stringify(values.season)) {\n      return false;\n    }\n  }\n\n  if (values.episode && Array.isArray(values.episode)) {\n    const sorted = [...values.episode].sort((a, b) => a - b);\n    if (JSON.stringify(sorted) !== JSON.stringify(values.episode)) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n/**\n * Validate roman numerals and integer-coercable strings with separators\n */\nfunction validateRoman(match: any): boolean {\n  if (intCoercable(match.raw)) {\n    return true;\n  }\n  return sepsSurround(match);\n}\n\n/**\n * Season validator for the \"Season N\" WORD pattern: reject a 4-digit year as the\n * season number, so \"The Four Seasons 2025\" is not parsed as \"Season 2025\"\n * (leaving \"Seasons\" to stay in the title). Does not affect SxxExx (a different\n * chain), so \"S2013E14\" → season 2013 is unaffected.\n */\nfunction seasonWordNotYear(match: any): boolean {\n  const raw = String(match.raw ?? '');\n  if (/^\\d{4}$/.test(raw)) {\n    const n = parseInt(raw, 10);\n    if (n >= 1900 && n <= 2100) return false;\n  }\n  return validateRoman(match);\n}\n\n/**\n * Build the episodes rebulk\n */\nexport function episodes(config: EpisodesConfig): Rebulk {\n  const subtitleBoth = config.range_separators;\n  const discreteSeparators = config.discrete_separators;\n  const weakDiscreteSeparators = seps\n    .split('')\n    .filter(s => !config.range_separators.includes(s) && s !== '/' && s !== '\\\\');\n  // Python merges weak separators in too: \"S03E21.22\" chains over the '.' (FASTSUB case).\n  const allSeparators = [\n    ...config.range_separators,\n    ...discreteSeparators,\n    ...weakDiscreteSeparators,\n  ];\n\n  // Values chained across a WEAK separator must be consecutive (\"S03E21.22\" ok,\n  // \"S01E10.24\" is the show \"24\"); a strong discrete separator (\"&\") lifts the\n  // requirement. Mirrors Python's ordering_validator is_consecutive.\n  const moduleOrderingValidator = orderingValidator;\n  const localOrderingValidator = (match: any): boolean => {\n    if (!moduleOrderingValidator(match)) return false;\n    const isConsecutive = (prop: string): boolean => {\n      let previous: any = null;\n      let valid = true;\n      const children = match.children;\n      const named = (children?.named?.(prop) ?? []) as any[];\n      for (const current of Array.isArray(named) ? named : [named]) {\n        if (previous) {\n          const separator = children.previous?.(current, (m: any) => m.name === prop + 'Separator', 0);\n          if (separator) {\n            const sraw = String(separator.raw ?? '');\n            if (!config.range_separators.includes(sraw) && weakDiscreteSeparators.includes(sraw)) {\n              const gap = Number(current.value) - Number(previous.value);\n              if (!(gap > 0 && gap <= config.max_range_gap + 1)) valid = false;\n            }\n            if (discreteSeparators.includes(sraw)) { valid = true; break; }\n          }\n        }\n        previous = current;\n      }\n      return valid;\n    };\n    return isConsecutive('episode') && isConsecutive('season');\n  };\n\n  // Word numerals for season word patterns (e.g. \"Saison sept\")\n  const wordNumerals = [\n    'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten',\n    'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty',\n    'un', 'deux', 'trois', 'quatre', 'cinq', 'sept', 'huit', 'neuf', 'dix',\n    'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize', 'vingt',\n  ];\n  const wordNumeralsPat = wordNumerals.join('|');\n  const numeralWithWords = `(?:\\\\d+|[ivxlcdm]+|${wordNumeralsPat})`;\n  const numeral = `(?:\\\\d+|[ivxlcdm]+)`;\n\n  function isSeasonEpisodeDisabled(context: any): boolean {\n    return isDisabled(context, 'episode') || isDisabled(context, 'season');\n  }\n\n  const rebulk = new Rebulk()\n    .regexDefaults({ flags: 'i' })\n    .stringDefaults({ ignoreCase: true })\n    .defaults({\n      privateNames: ['episodeSeparator', 'seasonSeparator', 'episodeMarker', 'seasonMarker'],\n      formatter: { season: (v: any) => parseInt(v, 10), episode: (v: any) => parseInt(v, 10), version: (v: any) => parseInt(v, 10), count: (v: any) => parseInt(v, 10) },\n      children: true,\n      privateParent: true,\n      conflictSolver: seasonEpisodeConflictSolver,\n      abbreviations: [altDash],\n    });\n\n  // CJK episode/season markers (Japanese: upstream #671, #763; Chinese: #779):\n  // 第195話 → episode 195, 第3集 → episode 3, 第二季 → season 2, シーズン2 → season 2, 2期 → season 2.\n  // Numbers may be ASCII digits or Han numerals up to 99 (二 → 2, 十一 → 11, 二十三 → 23).\n  rebulk.regex(`第(?<episode>${CJK_NUMBER})[話话集]`, { tags: ['SxxExx'], formatter: { episode: parseCjkNumber } });\n  rebulk.regex(`第(?<season>${CJK_NUMBER})季`, { tags: ['SxxExx'], formatter: { season: parseCjkNumber } });\n  rebulk.regex('(?:シーズン|シリーズ)(?<season>\\\\d{1,2})(?!\\\\d)', { tags: ['SxxExx'] });\n  rebulk.regex('(?<!\\\\d)(?<season>\\\\d{1,2})期', {});\n\n  // Main SxxExx patterns\n  const seasonMarkerPattern = buildOrPattern(config.season_markers, 'seasonMarker');\n  const episodeMarkerPattern = buildOrPattern(\n    [...config.episode_markers, ...config.disc_markers],\n    'episodeMarker',\n  );\n  const allSeparatorsPattern = buildOrPattern(\n    [...config.episode_markers, ...config.disc_markers, ...allSeparators],\n    'episodeSeparator',\n    true,\n  );\n\n  // S01E02, S01E02E03, S01E02-E03, etc\n  rebulk.chain({\n    tags: ['SxxExx'],\n    validateAll: true,\n    validator: {\n      __parent__: and_(sepsSurround, localOrderingValidator),\n    },\n    chainBreaker: (matches: any) => episodesSeasonChainBreaker(matches, config),\n    disabled: isSeasonEpisodeDisabled,\n  })\n    .defaults({ tags: ['SxxExx'] })\n    .regex(\n      seasonMarkerPattern +\n        `(?<season>\\\\d+)@?` +\n        episodeMarkerPattern +\n        `@?(?<episode>\\\\d+)(?:[a-d](?![a-z0-9]))?(?:v(?<version>\\\\d+))?`,\n    )\n    .repeater('+')\n    .regex(\n      allSeparatorsPattern + `@?(?<episode>\\\\d+)`,\n    )\n    .repeater('*');\n\n  // 1x02, 1x02x03 patterns\n  const seasonEpMarkerPattern = buildOrPattern(config.season_ep_markers, 'episodeMarker');\n  // A separator before the marker requires one after it too: \"1x03\" and \"1 x 03\" are\n  // episodes, while \"1080.x264\" is a number followed by a codec token (#933).\n  const asymmetricSeasonEpMarker = `(?!@` + buildOrPattern(config.season_ep_markers) + `\\\\d)`;\n  rebulk.chain({\n    tags: ['SxxExx'],\n    validateAll: true,\n    validator: {\n      __parent__: and_(sepsSurround, orderingValidator),\n    },\n    disabled: isSeasonEpisodeDisabled,\n  })\n    .defaults({ tags: ['SxxExx'] })\n    .regex(\n      `(?!0x[0-9a-fA-F])(?<season>\\\\d+)` + asymmetricSeasonEpMarker + `@?` + seasonEpMarkerPattern + `@?(?<episode>\\\\d+)`,\n    )\n    .repeater('+');\n\n  // 1x02 with additional episodes (1x02x03, 1x02-03)\n  rebulk.chain({\n    tags: ['SxxExx'],\n    validateAll: true,\n    validator: {\n      __parent__: and_(sepsSurround, orderingValidator),\n    },\n    disabled: isSeasonEpisodeDisabled,\n  })\n    .defaults({ tags: ['SxxExx'] })\n    .regex(`(?!0x[0-9a-fA-F])(?<season>\\\\d+)` + asymmetricSeasonEpMarker + `@?` + seasonEpMarkerPattern + `@?(?<episode>\\\\d+)`)\n    .regex(\n      buildOrPattern(\n        [...config.season_ep_markers, ...discreteSeparators, ...config.range_separators],\n        'episodeSeparator',\n        true,\n      ) + `(?<episode>\\\\d+)`,\n    )\n    .repeater('*');\n\n  // Compact non-English season/episode marker: \"T02E22\", \"T01XE08\" (Spanish/Portuguese).\n  // Restricted to a \"t\" prefix immediately followed by an episode marker so a lone\n  // \"T1\" stays a title token. (upstream 4.x)\n  rebulk.regex(\n    `t(?<season>\\\\d{1,2})@?` + buildOrPattern(config.episode_markers, 'episodeMarker') + `@?(?<episode>\\\\d{1,4})`,\n    { tags: ['SxxExx'], disabled: isSeasonEpisodeDisabled },\n  );\n\n  // Anime special-episode markers: SP01/EX01/OVA2 → episode (upstream #877 B1).\n  // ED/OP stay credit sequences (see other.ts) — only the special/extra forms\n  // carry a real episode number.\n  rebulk.regex(\n    `(?<![^\\\\W_])(?:SP|EX|OVA|OAV)-?(?<episode>\\\\d{1,3})(?![^\\\\W_])`,\n    { tags: ['SxxExx', 'special-episode'], disabled: (context: any) => isDisabled(context, 'episode') },\n  );\n\n  // English ordinal season: \"2nd Season 24\" → season 2 (upstream #877 B2f).\n  rebulk.regex(\n    `(?<season>\\\\d{1,2})(?:st|nd|rd|th)@?(?:season)(?![^\\\\W_])`,\n    { tags: ['SxxExx', 'numfirst'], disabled: isSeasonEpisodeDisabled },\n  );\n\n  // Glued NxNN forms without separators (cross-parser corpus): \"Castle1x01\",\n  // \"clny.3x11m720p\". Both numbers are bounded so resolutions (1280x720) and\n  // hex ids never match.\n  rebulk.regex(\n    `(?<!\\\\d)(?<season>\\\\d{1,2})(?<episodeMarker>x)(?<episode>\\\\d{2})(?!\\\\d)`,\n    { tags: ['SxxExx'], disabled: isSeasonEpisodeDisabled },\n  );\n\n  // Season-only: S01, S01S02S03\n  const seasonOnlySepPattern = buildOrPattern(\n    [...config.season_markers, ...discreteSeparators, ...config.range_separators],\n    'seasonSeparator',\n    true,\n  );\n  rebulk.chain({\n    tags: ['SxxExx'],\n    validateAll: true,\n    validator: {\n      __parent__: and_(sepsSurround, orderingValidator),\n    },\n    disabled: isSeasonEpisodeDisabled,\n  })\n    .defaults({ tags: ['SxxExx'] })\n    .regex(seasonMarkerPattern + `(?<season>\\\\d+)`)\n    .regex(`(?<other>Extras)`, { name: 'other', value: 'Extras', tags: ['no-release-group-prefix'] } as any)\n    .repeater('?')\n    .regex(seasonOnlySepPattern + `(?<season>\\\\d+)`)\n    .repeater('*');\n\n  // Episode details\n  for (const detail of ['Special', 'Pilot', 'Unaired', 'Final']) {\n    rebulk.string(detail, {\n      name: 'episode_details',\n      value: detail,\n      children: false,\n      privateParent: false,\n      disabled: (context: any) => isDisabled(context, 'episode_details'),\n    });\n  }\n\n  // Season-of patterns\n  const { words: seasonWords, numfirst: seasonWordsNumfirst } = splitWords(config.season_words);\n  const { words: episodeWords, numfirst: episodeWordsNumfirst } = splitWords(config.episode_words);\n  const seasonWordPattern = buildOrPattern(seasonWords, 'seasonMarker');\n  const ofWordPattern = buildOrPattern(config.of_words);\n\n  rebulk.chain({\n    validateAll: true,\n    conflictSolver: seasonEpisodeConflictSolver,\n    formatter: { season: parseNumber, season_count: parseNumber },\n    validator: {\n      __parent__: and_(sepsSurround, orderingValidator),\n      season: seasonWordNotYear,\n      season_count: validateRoman,\n    },\n    chainBreaker: (matches: any) => episodesSeasonChainBreaker(matches, config),\n    disabled: (context: any) =>\n      context?.type === 'movie' || isDisabled(context, 'season'),\n  })\n    .defaults({\n      formatter: { season: parseNumber, season_count: parseNumber },\n      validator: { season: seasonWordNotYear, season_count: validateRoman },\n      conflictSolver: seasonEpisodeConflictSolver,\n    })\n    .regex(seasonWordPattern + `@?(?P<season>${numeralWithWords})`)\n    .regex(ofWordPattern + `@?(?P<season_count>${numeral})`)\n    .repeater('?')\n    .regex(\n      // an optional comma before the separator covers list forms like \", & 6\"\n      `(?:,@?)?@?` +\n        buildOrPattern(\n          [...config.range_separators, ...discreteSeparators, '@'],\n          'seasonSeparator',\n          true,\n        ) +\n        `@?(?P<season>\\\\d+)`,\n    )\n    .repeater('*');\n\n  // Non-English convention where the number precedes the keyword:\n  //   \"1ª Temporada\", \"3 сезон\", \"2.Sezon\" (season); \"24 серия\", \"7.Bölüm\" (episode).\n  // An optional ordinal suffix may sit between the two, and the total may follow\n  // the keyword (\"5 серия из 12\"). Mirrors upstream 4.x numfirst patterns.\n  const ofCountPattern = `(?:@?` + ofWordPattern + `@?(?<count>\\\\d+))?`;\n  if (seasonWordsNumfirst.length > 0) {\n    rebulk.regex(\n      `(?<season>\\\\d{1,2})` + config.ordinal_suffix + `@?@?` +\n        buildOrPattern(seasonWordsNumfirst, 'seasonMarker') + `(?![^\\\\W\\\\d_])` + ofCountPattern,\n      {\n        tags: ['SxxExx', 'numfirst'],\n        formatter: { season: parseNumber, count: (v: any) => parseInt(v, 10) },\n        disabled: isSeasonEpisodeDisabled,\n      },\n    );\n  }\n  if (episodeWordsNumfirst.length > 0) {\n    rebulk.regex(\n      `(?<episode>\\\\d{1,3})` + config.ordinal_suffix + `@?@?` +\n        buildOrPattern(episodeWordsNumfirst, 'episodeMarker') + `(?![^\\\\W\\\\d_])` + ofCountPattern,\n      {\n        tags: ['SxxExx', 'numfirst'],\n        formatter: { episode: parseNumber, count: (v: any) => parseInt(v, 10) },\n        disabled: (context: any) => isDisabled(context, 'episode'),\n      },\n    );\n  }\n\n  // Episode patterns\n  const episodeWordPattern = buildOrPattern(episodeWords, 'episodeMarker');\n\n  // Decimal season.episode notations (cross-parser corpus):\n  //   \"Episode 1.22\"        → s1 e22 (episode word + decimal)\n  //   \" - 6.01 - \" / \"[5.134]\" → s6 e1 / s5 e134 (delimited decimal)\n  // The episode needs two+ digits (or a leading zero) so audio \"5.1\"/\"7.1\" and\n  // version \"2.0\" never match.\n  rebulk.regex(\n    buildOrPattern(episodeWords, 'episodeMarker') + `@?(?<season>\\\\d{1,2})\\\\.(?<episode>\\\\d{2,3})(?!\\\\d)`,\n    { tags: ['SxxExx'], disabled: isSeasonEpisodeDisabled },\n  );\n  rebulk.regex(\n    // The season half may not be the tail of an episode range: \"s16e03-04.313\"\n    // must leave \"04\" to the SxxExx chain and \"313\" to the absolute-episode\n    // range behind it, instead of reading \"04.313\" as season 4 (upstream #944).\n    `(?<=[\\\\s([_-][\\\\s._-]?)(?<!\\\\d[-x])(?<season>\\\\d{1,2})\\\\.(?<episode>\\\\d{2,3})(?=[\\\\s)\\\\]._-]|$)(?!\\\\.\\\\d)`,\n    {\n      tags: ['SxxExx', 'decimal-episode'],\n      validator: {\n        __parent__: (m: any) => {\n          // require a real delimiter context: dash/space before, or brackets\n          const inp = m.inputString ?? '';\n          const before = inp.slice(Math.max(0, m.start - 3), m.start);\n          return /[-([]\\s?$|^\\s*$|\\s-\\s$/.test(before) || /[([]/.test(before);\n        },\n      },\n      disabled: isSeasonEpisodeDisabled,\n    },\n  );\n\n  rebulk.regex(\n    `(?<![a-zA-Z\\\\d])` + episodeWordPattern + `@?(?<episode>\\\\d+)` +\n      `(?:v(?<version>\\\\d+))?` +\n      `(?:@?` + ofWordPattern + `@?(?<count>\\\\d+))?`,\n    {\n      disabled: (context: any) =>\n        context?.type === 'episode' || isDisabled(context, 'episode'),\n    },\n  );\n\n  rebulk.regex(\n    `(?<![a-zA-Z\\\\d])` + episodeWordPattern + `@?(?<episode>${numeral})` +\n      `(?:v(?<version>\\\\d+))?` +\n      `(?:@?` + ofWordPattern + `@?(?<count>\\\\d+))?`,\n    {\n      validator: { episode: validateRoman },\n      formatter: { episode: parseNumber },\n      disabled: (context: any) =>\n        context?.type !== 'episode' || isDisabled(context, 'episode'),\n    },\n  );\n\n  // S?01-xE/Ex/E/x-All patterns\n  rebulk.regex(\n    `S?(?<season>\\\\d+)-?(?:xE|Ex|E|x)-?(?<other>` +\n      buildOrPattern(config.all_words) + ')',\n    {\n      tags: ['SxxExx'],\n      formatter: { other: () => 'Complete' },\n      disabled: (context: any) => isDisabled(context, 'season'),\n    },\n  );\n\n  // Weak episode patterns: 12, 13\n  rebulk.chain({\n    tags: ['weak-episode'],\n    disabled: (context: any) =>\n      context?.type === 'movie' || isDisabled(context, 'episode'),\n  })\n    .defaults({ validator: null, tags: ['weak-episode'] })\n    .regex(`(?<![^\\\\W_])(?<episode>\\\\d{2})(?!(?:st|nd|rd|th)\\\\b)(?!%)(?:[a-d](?![a-z0-9]))?(?!(?![vV]\\\\d)[^\\\\W_])`)\n    .regex(`v(?<version>\\\\d+)`)\n    .repeater('?')\n    .regex(`(?<episodeSeparator>[x-])(?<episode>\\\\d{2})`, {\n      abbreviations: null,\n    } as any)\n    .repeater('*');\n\n  // Weak episode patterns: 012, 013\n  rebulk.chain({\n    tags: ['weak-episode'],\n    disabled: (context: any) =>\n      context?.type === 'movie' || isDisabled(context, 'episode'),\n  })\n    .defaults({ validator: null, tags: ['weak-episode'] })\n    .regex(`(?<![^\\\\W_])0(?<episode>\\\\d{1,2})(?!%)(?:[a-d](?![a-z0-9]))?(?!(?![vV]\\\\d)[^\\\\W_])`)\n    .regex(`v(?<version>\\\\d+)`)\n    .repeater('?')\n    .regex(`(?<episodeSeparator>[x-])0(?<episode>\\\\d{1,2})`, {\n      abbreviations: null,\n    } as any)\n    .repeater('*');\n\n  // Weak episode patterns: 112, 113\n  rebulk.chain({\n    tags: ['weak-episode'],\n    name: 'weak_episode',\n    disabled: (context: any) =>\n      context?.type === 'movie' || isDisabled(context, 'episode'),\n  })\n    .defaults({\n      validator: null,\n      tags: ['weak-episode'],\n      name: 'weak_episode',\n    })\n    .regex(`(?<![^\\\\W_])(?<episode>\\\\d{3,4})(?!%)(?:[a-d](?![a-z0-9]))?(?!(?![vV]\\\\d)[^\\\\W_])`)\n    .regex(`v(?<version>\\\\d+)`)\n    .repeater('?')\n    .regex(`(?<episodeSeparator>[x-])(?<episode>\\\\d{3,4})`, {\n      abbreviations: null,\n    } as any)\n    .repeater('*');\n\n  // Single digit episodes\n  rebulk.chain({\n    tags: ['weak-episode'],\n    disabled: (context: any) =>\n      context?.type !== 'episode' || isDisabled(context, 'episode'),\n  })\n    .defaults({ validator: null, tags: ['weak-episode'] })\n    .regex(`(?<![^\\\\W_])(?<episode>\\\\d)(?!-[a-z])(?!%)(?!(?![vV]\\\\d)[^\\\\W_])`)\n    .regex(`v(?<version>\\\\d+)`)\n    .repeater('?')\n    .regex(`(?<episodeSeparator>[x-])(?<episode>\\\\d{1,2})`, {\n      abbreviations: null,\n    } as any)\n    .repeater('*');\n\n  // e112, e113, 1e18, 3e19\n  rebulk.chain({\n    validateAll: true,\n    validator: { __parent__: sepsSurround },\n    disabled: (context: any) => isDisabled(context, 'episode'),\n  })\n    .defaults({ validator: null })\n    .regex(`(?<season>\\\\d{1,2})?(?<episodeMarker>e)(?<episode>\\\\d{1,4})`)\n    .regex(`v(?<version>\\\\d+)`)\n    .repeater('?')\n    .regex(`(?<episodeSeparator>e|x|-)(?<episode>\\\\d{1,4})`, {\n      abbreviations: null,\n    } as any)\n    .repeater('*');\n\n  // ep112, ep113\n  rebulk.chain({\n    disabled: (context: any) => isDisabled(context, 'episode'),\n  })\n    .defaults({ validator: null })\n    .regex(`(?<![a-zA-Z\\\\d])ep-?(?<episode>\\\\d{1,4})`)\n    .regex(`v(?<version>\\\\d+)`)\n    .repeater('?')\n    .regex(`(?<episodeSeparator>ep|e|x|-)(?<episode>\\\\d{1,4})`, {\n     abbreviations: null,\n   } as any)\n    .repeater('*');\n\n  // cap patterns\n  rebulk.chain({\n    tags: ['see-pattern'],\n    disabled: isSeasonEpisodeDisabled,\n  })\n    .defaults({ validator: null, tags: ['see-pattern'] })\n    .regex(`(?<seasonMarker>cap)@?(?<season>\\\\d{1,2})(?<episode>\\\\d{2})(?!\\\\d)`)\n    .regex(`(?<episodeSeparator>[_-])(?<season>\\\\d{1,2})(?<episode>\\\\d{2})(?!\\\\d)`)\n    .repeater('?');\n\n  // 102, 0102 (weak duplicate)\n  rebulk.chain({\n    tags: ['weak-episode', 'weak-duplicate'],\n    name: 'weak_duplicate',\n    conflictSolver: seasonEpisodeConflictSolver,\n    disabled: (context: any) =>\n      context?.episode_prefer_number === true ||\n      context?.type === 'movie' ||\n      isSeasonEpisodeDisabled(context),\n  })\n    .defaults({\n      tags: ['weak-episode', 'weak-duplicate'],\n      name: 'weak_duplicate',\n      validator: null,\n      conflictSolver: seasonEpisodeConflictSolver,\n    })\n    .regex(`(?<![^\\\\W_])(?<season>\\\\d{1,2})(?<episode>\\\\d{2})(?!%)(?!(?![vV]\\\\d)[^\\\\W_])`)\n    .regex(`v(?<version>\\\\d+)`)\n    .repeater('?')\n    .regex(`(?<episodeSeparator>x|-)(?<episode>\\\\d{2})`, {\n      abbreviations: null,\n    } as any)\n    .repeater('*');\n\n  // Version pattern\n  rebulk.regex(`v(?<version>\\\\d+)`, {\n    formatter: { version: (v: string) => parseInt(v, 10) },\n    disabled: (context: any) => isDisabled(context, 'version'),\n  });\n\n  // Detached of X count (e.g. \"14 of 21\", \"14.of.21\", \"1-of-6\")\n  // Use @? (altDash abbreviation) so separators like '.' and ' ' are also matched.\n  rebulk.regex(\n    // The lookbehind keeps this off token tails: \"AC3-de[42]\" is not \"episode 3 of 42\"\n    // ('de' is also a Spanish of-word — codec suffixes must stay intact).\n    `(?<![^\\\\W_])(?<episode>\\\\d+)@?` +\n      ofWordPattern +\n      `@?(?<count>\\\\d+)@?` +\n      episodeWordPattern + '?',\n    {\n      formatter: { episode: (v: string) => parseInt(v, 10), count: (v: string) => parseInt(v, 10) },\n      preMatchProcessor: (match: any) => {\n        match.value = cleanup(match.value);\n        return match;\n      },\n      disabled: (context: any) => isDisabled(context, 'episode'),\n    },\n  );\n\n  // Minisodes\n  rebulk.regex(`Minisodes?`, {\n    children: false,\n    privateParent: false,\n    name: 'episode_format',\n    value: 'Minisode',\n    disabled: (context: any) => isDisabled(context, 'episode_format'),\n  });\n\n  // Add rules for validation and cleanup\n  rebulk.rules(\n    EventNumberAsTitleRule,\n    EpisodeWordBeforeYearAsTitle,\n    RemoveGroupSuffixSeason,\n    AnimeTrailingEpisodeRule,\n    PreferAnchoredWeakEpisodeRule,\n    SeasonWordDashedEpisodeRule,\n    RemoveNumfirstMarkerCollision,\n    CountValidator,\n    new DiscMarkerRule(config),\n    FixCorruptedGroupBoundaryValues,\n    new RangeExpansionRule(config),\n    WeakConflictSolverRule,\n    RemoveWeakDuplicateRule,\n    RemoveWeakIfSxxExxRule,\n    AbsoluteEpisodeInGroupRule,\n    RemoveInvalidSeasonRule,\n    RemoveInvalidEpisodeRule,\n    RemoveUndeterminedLanguagesRule,\n  );\n\n  return rebulk;\n}\n\n/**\n * A dash-glued \"S<n>\" hanging off a release token is a group name, not a season:\n * \"DD5.1-S56\", \"[E-AC3-S78]\" (cross-parser corpus). Season-only S-chains whose\n * initiator directly follows a dash after an audio/codec/channels token (or that\n * sit inside a bracket group with such a token) are dropped so the release-group\n * logic can claim them.\n */\nclass RemoveGroupSuffixSeason extends Rule {\n  static override priority = 72;\n  override priority = 72;\n  override consequence = RemoveMatch;\n\n  when(matches: any, _context: any): any {\n    const input: string = matches.inputString ?? '';\n    const toRemove: any[] = [];\n    const TOKENS = new Set(['audio_codec', 'audio_channels', 'video_codec', 'audio_profile', 'other']);\n    for (const season of (matches.named('season') as any[]) ?? []) {\n      const init = season.initiator ?? season;\n      if (!/^s\\d{1,3}$/i.test(String(init.raw ?? ''))) continue;\n      const hasEpisode = [...(init.children ?? [])].some((c: any) => c.name === 'episode');\n      if (hasEpisode) continue;\n      if (input[init.start - 1] !== '-') continue;\n      const prev = matches.range(Math.max(0, init.start - 12), init.start - 1,\n        (m: any) => !m.private && TOKENS.has(m.name ?? ''), -1) ??\n        matches.range(Math.max(0, init.start - 12), init.start - 1,\n          (m: any) => !m.private && TOKENS.has(m.name ?? ''), 0);\n      const inGroup = matches.markers.atMatch(init, (m: any) => m.name === 'group', 0);\n      if (!prev && !inGroup) continue;\n      toRemove.push(season);\n      for (const c of (init.children ?? [])) if (!toRemove.includes(c)) toRemove.push(c);\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\n/**\n * Event/title numbers that are not episodes (cross-parser corpus):\n * - \"UFC.247.PPV…\" — a number directly followed by PPV numbers the event\n * - \"22.Jump.Street.GERMAN…\" — a leading 2-digit before a multi-word title with\n *   no year/season/SxxExx anywhere is part of a movie title\n * The weak match is dropped so the number rejoins the title.\n */\nclass EventNumberAsTitleRule extends Rule {\n  static override priority = 60;\n  override priority = 60;\n  override consequence = RemoveMatch;\n\n  when(matches: any, _context: any): any {\n    const input: string = matches.inputString ?? '';\n    const toRemove: any[] = [];\n    const isWeak = (m: any) => !!(m.tags?.includes('weak-episode') ||\n      ['weak_episode', 'weak_duplicate'].includes(m.initiator?.name));\n    for (const filepart of (matches.markers.named('path') as any[]) ?? []) {\n      const weaks = ((matches.range(filepart.start, filepart.end,\n        (m: any) => m.name === 'episode' && !m.private && isWeak(m)) as any[]) ?? []);\n      if (!weaks.length) continue;\n      const strong = matches.range(filepart.start, filepart.end, (m: any) =>\n        !m.private && (m.name === 'season' || m.name === 'year' || m.name === 'date' ||\n          (m.name === 'episode' && m.tags?.includes('SxxExx'))), 0);\n      for (const w of weaks) {\n        const init = w.initiator ?? w;\n        const after = input.slice(init.end, init.end + 5);\n        // \"UFC 247 PPV\": number glued to a PPV marker is the event number\n        if (/^[\\s._-]?PPV/i.test(after)) {\n          for (const c of [init, ...(init.children ?? [])]) if (!toRemove.includes(c)) toRemove.push(c);\n          continue;\n        }\n        // Leading 2-digit + multi-word title, no year/season/SxxExx anywhere\n        // zero-padded leading numbers (\"01 - Ep Name\") are deliberate episode numbering\n        if (!strong && init.start === filepart.start && /^[1-9]\\d$/.test(String(init.raw ?? ''))) {\n          const rest = input.slice(init.end, filepart.end);\n          const words = (rest.match(/[A-Za-z][a-z]+/g) ?? []);\n          if (words.length >= 2) {\n            for (const c of [init, ...(init.children ?? [])]) if (!toRemove.includes(c)) toRemove.push(c);\n          }\n        }\n      }\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\n/**\n * \"Episode N\" spelled out before the movie year is part of the title:\n * \"Star Wars Episode 1 La Menace fantome 1999\" (cross-parser corpus). Only when\n * a year follows and the filepart has no season/SxxExx — a real episode marker\n * never precedes the year in movie naming.\n */\nclass EpisodeWordBeforeYearAsTitle extends Rule {\n  static override priority = 60;\n  override priority = 60;\n  override consequence = RemoveMatch;\n\n  when(matches: any, _context: any): any {\n    const toRemove: any[] = [];\n    for (const episode of (matches.named('episode') as any[]) ?? []) {\n      const init = episode.initiator ?? episode;\n      const marker = [...(init.children ?? [])].find((c: any) => c.name === 'episodeMarker');\n      if (!marker || String(marker.raw ?? '').length < 3) continue; // word marker only (Episode/Ep.)\n      const filepart = matches.markers.atMatch(episode, (m: any) => m.name === 'path', 0);\n      if (!filepart) continue;\n      const year = matches.range(episode.end, filepart.end, (m: any) => !m.private && m.name === 'year', 0);\n      if (!year) continue;\n      const seasonish = matches.range(filepart.start, filepart.end,\n        (m: any) => !m.private && (m.name === 'season' || (m.name === 'episode' && m.tags?.includes('SxxExx'))), 0);\n      if (seasonish) continue;\n      // title text must continue between the number and the year (the episode name)\n      const between = String(matches.inputString ?? '').slice(episode.end, year.start);\n      if (!/[a-zA-Z]{2,}/.test(between)) continue;\n      toRemove.push(episode);\n      if (!toRemove.includes(init)) toRemove.push(init);\n      for (const c of (init.children ?? [])) if (!toRemove.includes(c)) toRemove.push(c);\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\n/**\n * Anime episode from a trailing bare number (upstream #877 B1): with an anime\n * signal in the filepart — a CRC32 checksum or a leading bracket release group —\n * a trailing number is the episode, whether bare (\"Eve no Jikan 2 [88F4F7F0]\")\n * or parenthesized (\"[N LogN Fansubs] Angel Beats (9)\"). The episode match then\n * types the release as an episode. Without such a signal nothing happens, so\n * movie sequels (\"Deadpool 2\") are untouched.\n */\nclass AnimeTrailingEpisodeRule extends Rule {\n  static override priority = -64;\n  override priority = -64;\n  override consequence = [RemoveMatch, AppendMatch];\n\n  when(matches: any, _context: any): any {\n    const input: string = matches.inputString ?? '';\n    const toRemove: any[] = [];\n    const toAppend: any[] = [];\n    const episodes = (matches.named('episode') as any[]) ?? [];\n    if (episodes.length) return false;\n    for (const filepart of (matches.markers.named('path') as any[]) ?? []) {\n      const crc = matches.range(filepart.start, filepart.end, (m: any) => m.name === 'crc32', 0);\n      const animeRg = matches.range(filepart.start, filepart.end,\n        (m: any) => m.name === 'release_group' && m.tags?.includes('anime'), 0);\n      const groupCount = ((matches.markers.range(filepart.start, filepart.end,\n        (m: any) => m.name === 'group') as any[]) ?? []).length;\n      if (!crc && !animeRg && groupCount < 3) continue;\n      // Parenthesized bare number: \"(9)\"\n      let done = false;\n      for (const group of (matches.markers.range(filepart.start, filepart.end, (m: any) => m.name === 'group') as any[]) ?? []) {\n        const core = input.slice(group.start + 1, group.end - 1).trim();\n        if (!/^\\d{1,3}$/.test(core)) continue;\n        const inner = (matches.range(group.start, group.end, (m: any) => !m.private) as any[]) ?? [];\n        // a numeric bracket often gets misread as alternative_title / weak junk — reclaim it\n        if (inner.some((m: any) => !['alternative_title', 'episode_title'].includes(m.name ?? '') && !m.tags?.includes('weak-episode'))) continue;\n        toRemove.push(...inner);\n        toAppend.push(new Match(group.start + 1, group.end - 1, {\n          name: 'episode', value: parseInt(core, 10), inputString: input, tags: ['anime'],\n        }));\n        done = true;\n        break;\n      }\n      if (done) continue;\n      // Trailing bare number at the end of the title: \"Eve no Jikan 2\"\n      const title = matches.range(filepart.start, filepart.end, (m: any) => m.name === 'title', 0);\n      if (!title) continue;\n      const m = /^(.*[^\\W\\d_])[\\s._-]+(\\d{1,3})$/.exec(input.slice(title.start, title.end));\n      if (!m) continue;\n      const numStart = title.start + m[1].length + (m[0].length - m[1].length - m[2].length);\n      toRemove.push(title);\n      const newTitle = new Match(title.start, title.start + m[1].length, {\n        name: 'title', value: cleanup(m[1]), inputString: input,\n      });\n      toAppend.push(newTitle);\n      toAppend.push(new Match(numStart, title.end, {\n        name: 'episode', value: parseInt(m[2], 10), inputString: input, tags: ['anime'],\n      }));\n    }\n    return (toRemove.length || toAppend.length) ? [toRemove, toAppend] : false;\n  }\n}\n\n/**\n * Competing weak episode numbers in one filepart (upstream #875): a number that is\n * plainly the anime episode — dash-delimited (\" - 09\"), zero-padded (\"002\") — wins\n * over a digit that belongs to the title (\"Mob Psycho 100\") or an absolute number\n * quoted in parentheses (\"52 (227)\"). An explicit episode-word match (\"episode 18\")\n * outranks every weak reading. Scoring: leading zero +4, dash-delimited +1,\n * inside brackets -2; the top-scoring initiator group survives, and lower-scoring\n * groups are dropped. Nothing happens when all candidates tie.\n */\nclass PreferAnchoredWeakEpisodeRule extends Rule {\n  static override priority = 40;\n  override priority = 40;\n  override consequence = RemoveMatch;\n\n  when(matches: any, _context: any): any {\n    const input: string = matches.inputString ?? '';\n    const toRemove: any[] = [];\n    const isWeakEp = (m: any) => m.name === 'episode' && !m.private &&\n      (m.tags?.includes('weak-episode') || ['weak_episode', 'weak_duplicate'].includes(m.initiator?.name));\n    const removeGroup = (init: any) => {\n      for (const c of [...(init.children ?? []), init]) {\n        if (!toRemove.includes(c)) toRemove.push(c);\n      }\n      if (!init.children?.length && !toRemove.includes(init)) toRemove.push(init);\n    };\n    for (const filepart of (matches.markers.named('path') as any[]) ?? []) {\n      const weaks = ((matches.range(filepart.start, filepart.end, isWeakEp) as any[]) ?? []);\n      if (!weaks.length) continue;\n      const strong = matches.range(filepart.start, filepart.end, (m: any) =>\n        m.name === 'episode' && !m.private && !isWeakEp(m) &&\n        !!(m.initiator?.children?.named?.('episodeMarker')?.length), 0);\n      const byInit = new Map<any, any[]>();\n      for (const w of weaks) {\n        const init = w.initiator ?? w;\n        byInit.set(init, [...(byInit.get(init) ?? []), w]);\n      }\n      if (strong) {\n        for (const init of byInit.keys()) removeGroup(init);\n        continue;\n      }\n      if (byInit.size < 2) continue;\n      const score = (init: any): number => {\n        let sc = 0;\n        const raw = String(init.raw ?? '');\n        if (/^0\\d/.test(raw)) sc += 4;\n        // dash-delimited: the token right before the number is a dash\n        let i = init.start - 1;\n        while (i >= 0 && (input[i] === ' ' || input[i] === '.' || input[i] === '_')) i--;\n        if (input[i] === '-') sc += 1;\n        if (matches.markers.atMatch(init, (m: any) => m.name === 'group', 0)) sc -= 2;\n        return sc;\n      };\n      const scored = [...byInit.keys()].map((init) => [init, score(init)] as const);\n      const top = Math.max(...scored.map(([, sc]) => sc));\n      const winners = scored.filter(([, sc]) => sc === top);\n      if (winners.length === scored.length) continue; // all tie — leave untouched\n      const winnerValues = new Set(winners.flatMap(([init]) => (byInit.get(init) ?? []).map((w) => Number(w.value))));\n      for (const [init, sc] of scored) {\n        if (sc >= top) continue;\n        const eps = byInit.get(init) ?? [];\n        // A multi-value group is a range/list (absolute numbering \"(191-195)\") and a\n        // group agreeing with the winner (\"101 (01)\" both read episode 1) both stay.\n        if (eps.length > 1) continue;\n        if (eps.some((w) => winnerValues.has(Number(w.value)))) continue;\n        removeGroup(init);\n      }\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\n/**\n * \"Season N - EE\": an anime convention where the space-padded dash joins the season\n * word to the EPISODE number, not a season range (upstream #875): \"Attack on Titan\n * Season 3 - 11\" → season 3, episode 11. A glued dash (\"Season 1-3\") or an explicit\n * completeness marker (\"Season 1 - 4 Complete\") keeps range semantics, and a plural\n * marker (\"Seasons 1 - 5\") is always a range.\n */\nclass SeasonWordDashedEpisodeRule extends Rule {\n  static override priority = 32;\n  override priority = 32;\n  override consequence = [RemoveMatch, AppendMatch];\n\n  when(matches: any, _context: any): any {\n    const input: string = matches.inputString ?? '';\n    const toRemove: any[] = [];\n    const toAppend: any[] = [];\n    const seasons = (matches.named('season') as any[]) ?? [];\n    const seen = new Set<any>();\n    for (const season of seasons) {\n      const init = season.initiator ?? season;\n      if (seen.has(init)) continue;\n      seen.add(init);\n      const children = [...(init.children ?? [])];\n      const marker = children.find((c: any) => c.name === 'seasonMarker');\n      if (!marker) continue;\n      const markerRaw = String(marker.raw ?? '');\n      const isWordMarker = /^[a-zà-ÿа-я]{3,}$/i.test(markerRaw);\n      // A compact \"S4-24\" confined to a bracket group is season 4 + episode 24\n      // (upstream #875): brackets quote metadata, and a season RANGE would use\n      // the S-prefix on both sides (\"S01-S05\").\n      const inBracket = !!matches.markers.atMatch(season, (m: any) => m.name === 'group', 0);\n      if (!isWordMarker && !(markerRaw.toLowerCase() === 's' && inBracket)) continue;\n      if (isWordMarker && /s$/i.test(markerRaw)) continue; // \"Seasons\" — plural means a real range\n      const nums = children.filter((c: any) => c.name === 'season');\n      if (nums.length !== 2) continue;\n      const sep = children.find((c: any) => c.name === 'seasonSeparator');\n      if (!sep || String(sep.raw ?? '').trim() !== '-') continue;\n      // word markers need the space-padded dash (\"Season 3 - 11\"); a glued\n      // \"Season 1-3\" is a range. Bracketed \"S4-24\" is glued by convention.\n      if (isWordMarker && (input[sep.start - 1] !== ' ' || input[sep.end] !== ' ')) continue;\n      const filepart = matches.markers.atMatch(season, (m: any) => m.name === 'path', 0);\n      if (filepart) {\n        const complete = matches.range(filepart.start, filepart.end,\n          (m: any) => m.name === 'other' && m.value === 'Complete', 0);\n        if (complete) continue;\n      }\n      const episodeMatch = new Match(nums[1].start, nums[1].end, {\n        name: 'episode',\n        value: nums[1].value,\n        inputString: input,\n      });\n      toRemove.push(nums[1]);\n      toAppend.push(episodeMatch);\n    }\n    return (toRemove.length || toAppend.length) ? [toRemove, toAppend] : false;\n  }\n}\n\n/**\n * RemoveNumfirstMarkerCollision — a number-first match (\"60 Сезон\") whose marker\n * word is also claimed by a surviving word-first match (\"Сезон 5\") yields to it:\n * the explicit word-then-number form is the intended reading. Runs after\n * match-level conflicts, so a word-first match whose number was consumed by a\n * stronger property (e.g. \"Temporada 720\" where 720 is the resolution) is\n * already gone and leaves the number-first reading in place.\n */\nclass RemoveNumfirstMarkerCollision extends Rule {\n  static override priority = 70;\n  override priority = 70;\n  override consequence = [RemoveMatch, AppendMatch];\n\n  when(matches: any, _context: any): any {\n    const toRemove: any[] = [];\n    const toAppend: any[] = [];\n    const isWeak = (m: any) => !!(m.tags?.includes('weak-episode') ||\n      ['weak_episode', 'weak_duplicate'].includes(m.initiator?.name));\n    const removeWithParent = (m: any) => {\n      const init = m.initiator ?? m;\n      if (!toRemove.includes(m)) toRemove.push(m);\n      for (const child of init.children ?? []) {\n        if (!toRemove.includes(child)) toRemove.push(child);\n      }\n    };\n    const all: any[] = [...matches];\n    const numfirsts = all.filter((m: any) =>\n      (m.name === 'season' || m.name === 'episode') && m.tags?.includes('numfirst'));\n    for (const nf of numfirsts) {\n      const nfInit = nf.initiator ?? nf;\n      const wordFirst = all.find((w: any) => {\n        if (w.name !== 'season' && w.name !== 'episode') return false;\n        if (w.tags?.includes('numfirst') || isWeak(w)) return false;\n        const wInit = w.initiator ?? w;\n        if (wInit === nfInit) return false;\n        return wInit.start < nfInit.end && nfInit.start < wInit.end;\n      });\n      if (!wordFirst) continue;\n      // The word-first reading loses only when its number is really another property\n      // (the resolution in \"04ª Temporada 720p\"); otherwise the explicit\n      // word-then-number form wins (\"Studio 60 Сезон 5\" → season 5, weak 60 → episode).\n      const claimed = all.some((m: any) =>\n        !m.private && (m.name === 'screen_size' || m.name === 'year') &&\n        m.start < wordFirst.end && wordFirst.start < m.end);\n      // A glued ordinal (\"2nd Season\") binds the number to the marker — that\n      // number-first reading wins and the trailing number stays an absolute\n      // episode (\"Hayate no Gotoku 2nd Season 24\" → season 2).\n      const gluedOrdinal = /^(?:st|nd|rd|th|ª|º|°)/i.test(String(matches.inputString ?? '').slice(nf.end, nf.end + 2));\n      if (claimed || gluedOrdinal) {\n        removeWithParent(wordFirst);\n        // The word-first number was real text — resurface it as the (absolute)\n        // episode unless another property claimed it (\"Studio 60 Сезон 5\" → e60,\n        // \"Hayate no Gotoku 2nd Season 24\" → e24; matches Python).\n        if (!claimed) {\n          toAppend.push(new Match(wordFirst.start, wordFirst.end, {\n            name: 'episode',\n            value: wordFirst.value,\n            inputString: matches.inputString,\n          }));\n        }\n      }\n      else removeWithParent(nf);\n    }\n    return (toRemove.length || toAppend.length) ? [toRemove, toAppend] : false;\n  }\n}\n\n/**\n * CountValidator — validate a `count` match and rename it to episode_count or\n * season_count depending on the last episode/season inside its own match; drop\n * counts with no owner. Scoped to the count's initiator rather than the nearest\n * neighbour because another property can sit on the linking word itself (\"de\"\n * is the German language code as much as the Spanish \"of\"). Mirrors upstream 4.x.\n */\nclass CountValidator extends Rule {\n  static override priority = 64;\n  override priority = 64;\n  static consequence = [RemoveMatch, new RenameMatch('episode_count'), new RenameMatch('season_count')];\n  override consequence = [RemoveMatch, new RenameMatch('episode_count'), new RenameMatch('season_count')];\n\n  when(matches: any, _context: any): any {\n    const toRemove: any[] = [];\n    const episodeCount: any[] = [];\n    const seasonCount: any[] = [];\n\n    for (const count of matches.named('count') ?? []) {\n      const numbers = matches.range(\n        count.initiator.start,\n        count.start,\n        (m: Match) => m.name === 'episode' || m.name === 'season',\n      ) as Match[];\n      const numbered = numbers.length ? numbers[numbers.length - 1] : undefined;\n      if (!numbered) toRemove.push(count);\n      else if (numbered.name === 'episode') episodeCount.push(count);\n      else seasonCount.push(count);\n    }\n    if (toRemove.length || episodeCount.length || seasonCount.length) {\n      return [toRemove, episodeCount, seasonCount];\n    }\n    return false;\n  }\n}\n\n/**\n * DiscMarkerRule — when the episode marker is a disc marker (e.g. \"D\"),\n * rename the episode matches to disc.\n */\nclass DiscMarkerRule extends Rule {\n  static override priority = 128;\n  override priority = 128;\n  private config: EpisodesConfig;\n\n  constructor(config: EpisodesConfig) {\n    super();\n    this.config = config;\n  }\n\n  when(matches: any, _context: any): any {\n    const discMarkers = new Set((this.config.disc_markers || []).map((s: string) => s.toLowerCase()));\n    if (discMarkers.size === 0) return false;\n\n    const toRename: any[] = [];\n    const episodes: any[] = matches.named('episode', (m: any) => !m.private) || [];\n    for (const ep of episodes) {\n      const initiator = ep.initiator;\n      if (!initiator) continue;\n      const children = initiator.children;\n      if (!children) continue;\n      const markers: any[] = (typeof children.named === 'function'\n        ? children.named('episodeMarker')\n        : []) || [];\n      for (const marker of markers) {\n        const markerText = (marker.rawString || marker.raw || marker.value || '').toString().toLowerCase();\n        if (discMarkers.has(markerText)) {\n          toRename.push(ep);\n          break;\n        }\n      }\n    }\n    return toRename.length > 0 ? toRename : false;\n  }\n\n  then(matches: any, toRename: any, context: any): void {\n    const discExcluded = isDisabled(context, 'disc');\n    for (const ep of toRename) {\n      if (discExcluded) {\n        // Disc is excluded — remove the episode AND its associated season from the same chain\n        const initiator = ep.initiator;\n        matches.remove(ep);\n        if (initiator) {\n          // Remove all children of this initiator (season, episode, markers)\n          const siblings = initiator.children\n            ? (typeof initiator.children[Symbol.iterator] === 'function'\n                ? [...initiator.children]\n                : [])\n            : [];\n          for (const sib of siblings) {\n            if (matches.includes(sib)) matches.remove(sib);\n          }\n          if (matches.includes(initiator)) matches.remove(initiator);\n        }\n      } else {\n        matches.remove(ep);\n        ep.name = 'disc';\n        matches.append(ep);\n      }\n    }\n  }\n}\n\n/**\n * Fix numeric episode/season values that were corrupted by EnlargeGroupMatches.\n * When a match ends at a group bracket boundary, EnlargeGroupMatches extends the\n * span to include the bracket and shrinks rawEnd by 1. For regex chain children,\n * this can truncate the captured value (e.g. \"04\" → \"0\"). This rule detects\n * such cases and re-parses the value from the original input text.\n */\nclass FixCorruptedGroupBoundaryValues extends Rule {\n  when(matches: any, _context: any): any {\n    const toFix: Array<{ match: any; correctValue: number }> = [];\n    const groups = matches.markers?.named('group') || [];\n    const groupArr: any[] = Array.isArray(groups) ? groups : groups ? [groups] : [];\n\n    for (const match of matches) {\n      if (match.name !== 'episode' && match.name !== 'season') continue;\n      if (typeof match.value !== 'number') continue;\n\n      // Check if this match ends at a group boundary\n      const atGroupEnd = groupArr.some((g: any) => match.end === g.end);\n      if (!atGroupEnd) continue;\n\n      // Re-read the digits from the original input before the bracket\n      const inputStr = matches.inputString || '';\n      // Find the digits just before the group boundary (match.end - 1 is the bracket)\n      let digitEnd = match.end - 1; // position of the bracket\n      let digitStart = digitEnd;\n      while (digitStart > match.start && /\\d/.test(inputStr[digitStart - 1])) {\n        digitStart--;\n      }\n      if (digitStart >= digitEnd) continue;\n\n      const correctStr = inputStr.slice(digitStart, digitEnd);\n      const correctValue = parseInt(correctStr, 10);\n      if (isNaN(correctValue) || correctValue === match.value) continue;\n\n      toFix.push({ match, correctValue });\n    }\n\n    return toFix.length > 0 ? toFix : false;\n  }\n\n  then(matches: any, whenResponse: any, _context: any): void {\n    for (const { match, correctValue } of whenResponse) {\n      (match as any).value = correctValue;\n      // Also fix rawEnd to include the full digit sequence\n      const inputStr = matches.inputString || '';\n      let digitEnd = match.end - 1;\n      if (match.rawEnd < digitEnd) {\n        (match as any).rawEnd = digitEnd;\n      }\n    }\n  }\n}\n\n/**\n * Expand ranges: when two season/episode values are connected by a range separator,\n * fill in the intermediate values (e.g., S01-S03 -> [1,2,3], E01-04 -> [1,2,3,4]).\n */\nclass RangeExpansionRule extends Rule {\n  consequence = AppendMatch;\n  private config: EpisodesConfig;\n\n  constructor(config: EpisodesConfig) {\n    super();\n    this.config = config;\n  }\n\n  when(matches: any, _context: any): any {\n    const toAppend: any[] = [];\n    const rangeSeps = new Set(this.config.range_separators || ['-', '~', 'to', 'a']);\n\n    // Get filepart markers to restrict range expansion to within the same filepart\n    const fileparts = matches.markers?.named('path') || [];\n    const filepartArr: any[] = Array.isArray(fileparts) ? fileparts : fileparts ? [fileparts] : [];\n\n    // Helper: find which filepart a match belongs to\n    const getFilepart = (m: any): any => {\n      for (const fp of filepartArr) {\n        if (m.start >= fp.start && m.end <= fp.end) return fp;\n      }\n      return null;\n    };\n\n    for (const name of ['season', 'episode', 'absolute_episode', 'disc']) {\n      const maxRange = name === 'season' ? this.config.season_max_range : this.config.episode_max_range;\n      const all: any[] = matches.named(name, (m: any) => !m.private) || [];\n      if (all.length < 2) continue;\n\n      // Sort by position\n      const sorted = [...all].sort((a: any, b: any) => a.start - b.start);\n\n      for (let i = 0; i < sorted.length - 1; i++) {\n        const current = sorted[i];\n        const next = sorted[i + 1];\n\n        // Only expand ranges within the same filepart\n        const currentFp = getFilepart(current);\n        const nextFp = getFilepart(next);\n        if (currentFp !== nextFp || !currentFp) continue;\n\n        const curVal = typeof current.value === 'number' ? current.value : parseInt(current.value, 10);\n        const nextVal = typeof next.value === 'number' ? next.value : parseInt(next.value, 10);\n\n        if (isNaN(curVal) || isNaN(nextVal)) continue;\n        if (nextVal <= curVal) continue;\n        const gap = nextVal - curVal;\n        if (gap <= 1 || gap > maxRange) continue;\n\n        // Check if connected by a range separator (look at text between them).\n        // Only strip whitespace and dots: a dot is a discrete separator\n        // (\"Season.1.3.4\" -> [1,3,4]) while \"_\" is a range separator within a\n        // chain (\"Cap.102_104\" -> [2,3,4]), so the two must not be conflated.\n        const between = matches.inputString?.slice(current.end, next.start) || '';\n        const betweenClean = between.replace(/[\\s.]/g, '').toLowerCase();\n        // Also check after stripping marker letters (s/e/x/p) so the \"-\" in\n        // \"E01-E07\" is still recognised as the range separator.\n        const betweenStripMarkers = betweenClean.replace(/[sexp]/gi, '');\n        // A single-char range separator (-, ~, _) anywhere between the two\n        // numbers marks a range, even when adjacent digits/markers cling to it\n        // (e.g. \"Cap.102_104\" leaves \"_1\" between the \"02\" and \"04\" matches).\n        // \"_\" counts here although it is not in the configured range_separators.\n        const hasRangeChar = /[-~_]/.test(between);\n        // \"Complete Seasons 1: 11\" — a colon between two season numbers is a range\n        const seasonColon = name === 'season' && betweenClean === ':';\n        const isRange = hasRangeChar || seasonColon || rangeSeps.has(betweenClean) || rangeSeps.has(betweenStripMarkers);\n\n        // Expand only on an explicit range separator. A bare episode/season\n        // marker between the numbers means a new explicit value, not a range\n        // (\"S01E01E07\" -> [1,7], not [1..7]); a dot is likewise discrete.\n        if (isRange) {\n          // Fill intermediate values\n          for (let v = curVal + 1; v < nextVal; v++) {\n            const m = new Match(current.start, next.end, {\n              name,\n              value: v,\n              inputString: matches.inputString,\n              tags: current.tags ? [...current.tags] : [],\n            });\n            toAppend.push(m);\n          }\n        }\n      }\n    }\n\n    return toAppend.length > 0 ? toAppend : false;\n  }\n}\n\n/**\n * Remove invalid season matches\n */\nclass RemoveInvalidSeasonRule extends Rule {\n  consequence = RemoveMatch;\n  static override priority = 64;\n  override priority = 64;\n\n  when(matches: any, context: any): any {\n    const toRemove: any[] = [];\n\n    for (const filepart of matches.markers?.named('path') || []) {\n      const strongSeason = matches.range?.(filepart.start, filepart.end, (m: any) =>\n        m.name === 'season' && !m.private && m.tags?.includes('SxxExx'),\n      )?.[0];\n\n      if (strongSeason?.initiator?.children?.named('episode')) {\n        for (const season of matches.range?.(strongSeason.end, filepart.end, (m: any) =>\n          m.name === 'season' && !m.private,\n        ) || []) {\n          if (\n            !season.tags?.includes('SxxExx') ||\n            !season.initiator?.children?.named('episode')\n          ) {\n            if (season.initiator) {\n              toRemove.push(season.initiator);\n              toRemove.push(...(season.initiator.children || []));\n            } else {\n              toRemove.push(season);\n            }\n          }\n        }\n      }\n    }\n\n    return toRemove.length > 0 ? toRemove : false;\n  }\n}\n\n/**\n * Remove invalid episode matches\n */\nclass RemoveInvalidEpisodeRule extends Rule {\n  consequence = RemoveMatch;\n  static override priority = 64;\n  override priority = 64;\n\n  when(matches: any, context: any): any {\n    const toRemove: any[] = [];\n\n    for (const filepart of matches.markers?.named('path') || []) {\n      const strongEpisode = matches.range?.(filepart.start, filepart.end, (m: any) =>\n        m.name === 'episode' && !m.private && m.tags?.includes('SxxExx'),\n      )?.[0];\n\n      if (strongEpisode) {\n        const strongMarker = this.getEpisodePrefix(matches, strongEpisode);\n\n        for (const episode of matches.range?.(strongEpisode.end, filepart.end, (m: any) =>\n          m.name === 'episode' && !m.private,\n        ) || []) {\n          if (episode.tags?.includes('SxxExx')) continue;\n\n          const marker = this.getEpisodePrefix(matches, episode);\n\n          const epMarkers = episode.initiator?.children?.named?.('episodeMarker') || [];\n          const epMarkerArr: any[] = Array.isArray(epMarkers) ? epMarkers : [epMarkers];\n          const hasShortEMarker = epMarkerArr.some((m: any) => {\n            const raw = (m.rawString || m.raw || m.value || '').toString().toLowerCase();\n            return raw === 'e' || raw === 'ep';\n          });\n\n          const shouldRemove = (strongMarker && marker)\n            ? strongMarker.value?.toLowerCase?.() !== marker.value?.toLowerCase?.()\n            : (!episode.tags?.includes('SxxExx') && !hasShortEMarker);\n\n          if (shouldRemove) {\n            if (episode.initiator) {\n              toRemove.push(episode.initiator);\n              toRemove.push(...(episode.initiator.children || []));\n            } else {\n              if (marker) toRemove.push(marker);\n              toRemove.push(episode);\n            }\n          }\n        }\n      }\n    }\n\n    return toRemove.length > 0 ? toRemove : false;\n  }\n\n  private getEpisodePrefix(matches: any, episode: any): any {\n    // Only look for non-private markers — in Python, private names are invisible\n    // to lookup methods, so private episodeMarker/episodeSeparator are not found.\n    return matches.previous?.(episode, (m: any) =>\n      !m.private && ['episodeMarker', 'episodeSeparator'].includes(m.name),\n    )?.[0];\n  }\n}\n\n/**\n * RemoveWeakDuplicate — mirrors Python's RemoveWeakDuplicate.\n *\n * Remove weak-duplicate tagged matches if duplicate patterns exist.\n * For example: \"The 100.109\" produces two weak_duplicate matches (100 and 109).\n * Keep the LAST one (109 → season=1, episode=9) and remove the earlier (100).\n */\nclass RemoveWeakDuplicateRule extends Rule {\n  consequence = RemoveMatch;\n  static override priority = 64;\n  override priority = 64;\n\n  when(matches: any, _context: any): any {\n    const toRemove: any[] = [];\n    const fileparts = matches.markers?.named('path') || [];\n    const filepartArr: any[] = Array.isArray(fileparts) ? fileparts : fileparts ? [fileparts] : [];\n\n    for (const filepart of filepartArr) {\n      const weakDups: any[] = (matches.range?.(filepart.start, filepart.end,\n        (m: any) => m.tags?.includes('weak-duplicate'),\n      ) || []).slice().reverse(); // iterate in reverse (keep last)\n\n      const seen: Record<string, Set<any>> = {};\n      for (const match of weakDups) {\n        const name = match.name ?? '';\n        const pattern = match.initiator?.pattern ?? match.pattern ?? null;\n        if (!pattern) continue;\n        if (!seen[name]) seen[name] = new Set();\n        if (seen[name].has(pattern)) {\n          toRemove.push(match);\n        } else {\n          seen[name].add(pattern);\n        }\n      }\n    }\n\n    return toRemove.length > 0 ? toRemove : false;\n  }\n}\n\n/**\n * Remove undetermined languages (placeholder)\n */\nclass RemoveUndeterminedLanguagesRule extends Rule {\n  consequence = RemoveMatch;\n  static override priority = 32;\n  override priority = 32;\n\n  when(matches: any, context: any): any {\n    // Placeholder implementation\n    return false;\n  }\n}\n\n/**\n * WeakConflictSolverRule — mirrors Python's WeakConflictSolver.\n *\n * Decides between weak_episode (plain number like 679) and weak_duplicate (season+episode like 6+79):\n * - If anime detected (has version/crc32/screen_size-in-brackets): remove weak_duplicate\n * - Otherwise, if weak_duplicate present with no SxxExx and no range episodes: remove weak_episode\n */\nclass WeakConflictSolverRule extends Rule {\n  consequence = RemoveMatch;\n  static override priority = 128;\n  override priority = 128;\n\n  enabled(context: any): boolean {\n    return context?.type !== 'movie';\n  }\n\n  private isAnime(matches: any): boolean {\n    if ((matches.named('version') as any[])?.length > 0) return true;\n    if ((matches.named('crc32') as any[])?.length > 0) return true;\n    const groups = matches.markers?.named('group') || [];\n    const groupArr: any[] = Array.isArray(groups) ? groups : groups ? [groups] : [];\n    for (const group of groupArr) {\n      // screen_size inside a group marker\n      const screenSizeInGroup = matches.range?.(group.start, group.end, (m: any) =>\n        m.name === 'screen_size',\n      );\n      const hasScreenSize = Array.isArray(screenSizeInGroup)\n        ? screenSizeInGroup.length > 0\n        : !!screenSizeInGroup;\n      if (hasScreenSize) return true;\n      // Empty bracket group with non-numeric text (likely anime release group)\n      const innerMatches = matches.range?.(group.start, group.end,\n        (m: any) => !m.private && !m.tags?.includes('weak-language')) || [];\n      const innerArr: any[] = Array.isArray(innerMatches) ? innerMatches : innerMatches ? [innerMatches] : [];\n      const nonRG = innerArr.filter((m: any) => m.name !== 'release_group');\n      if (nonRG.length === 0) {\n        const groupText = (matches.inputString ?? '').slice(group.start + 1, group.end - 1).trim();\n        if (groupText && !/^\\d+$/.test(groupText)) return true;\n      }\n    }\n    return false;\n  }\n\n  when(matches: any, _context: any): any {\n    const toRemove: any[] = [];\n\n    const animeDetected = this.isAnime(matches);\n\n    const fileparts = matches.markers?.named('path') || [];\n    const filepartArr: any[] = Array.isArray(fileparts) ? fileparts : fileparts ? [fileparts] : [];\n\n    for (const filepart of filepartArr) {\n      const weakMatches: any[] = matches.range?.(filepart.start, filepart.end, (m: any) =>\n        m.initiator?.name === 'weak_episode',\n      ) || [];\n\n      const weakDupMatches: any[] = matches.range?.(filepart.start, filepart.end, (m: any) =>\n        m.initiator?.name === 'weak_duplicate',\n      ) || [];\n\n      if (animeDetected) {\n        // Anime: remove weak_duplicate, keep weak_episode\n        if (weakMatches.length > 0) {\n          toRemove.push(...weakDupMatches);\n        }\n      } else if (weakDupMatches.length > 0) {\n        // Check for episodes in range (weak_episode with episodeSeparator child)\n        const episodesInRange: any[] = matches.range?.(filepart.start, filepart.end, (m: any) => {\n          if (m.name !== 'episode' || m.initiator?.name !== 'weak_episode') return false;\n          const children = m.initiator?.children;\n          if (!children) return false;\n          if (Array.isArray(children)) return children.some((c: any) => c.name === 'episodeSeparator');\n          if (typeof children.named === 'function') return (children.named('episodeSeparator') || []).length > 0;\n          return false;\n        }) || [];\n\n        const hasSxxExx = (matches.range?.(filepart.start, filepart.end, (m: any) =>\n          m.tags?.includes('SxxExx') && !m.private,\n        ) || []).length > 0;\n\n        if (episodesInRange.length === 0 && !hasSxxExx) {\n          // Remove weak_episode matches, keep weak_duplicate\n          toRemove.push(...weakMatches);\n        } else if (episodesInRange.length > 0) {\n          // Remove weak_duplicate, keep weak_episode range\n          toRemove.push(...weakDupMatches);\n        }\n      }\n    }\n\n    return toRemove.length > 0 ? toRemove : false;\n  }\n}\n\n/**\n * RemoveWeakIfSxxExxRule — mirrors Python's RemoveWeakIfSxxExx.\n *\n * When an SxxExx match exists in a filepart:\n * - Remove weak-duplicate matches (season+episode combos like 102 → S01E02)\n * - Rename weak_episode matches (3-4 digit absolute numbers like 313) to absolute_episode\n * - Remove 2-digit weak-episode matches (they're just noise when SxxExx is present)\n */\n/**\n * AbsoluteEpisodeInGroupRule — when episodes exist both inside and outside a group marker\n * (parentheses), rename the group-interior episodes to absolute_episode.\n * E.g. \"Fairy_Tail_2_-_16-20_(191-195)_[720p]\" → episodes 16-20, absolute_episode 191-195.\n */\nclass AbsoluteEpisodeInGroupRule extends Rule {\n  static override priority = -1;\n  override priority = -1;\n\n  when(matches: any, _context: any): any {\n    const toRename: any[] = [];\n\n    const fileparts = matches.markers?.named('path') || [];\n    const filepartArr: any[] = Array.isArray(fileparts) ? fileparts : [fileparts];\n\n    for (const filepart of filepartArr) {\n      const episodes: any[] = (matches.range?.(filepart.start, filepart.end, (m: any) =>\n        m.name === 'episode' && !m.private,\n      ) || []);\n      if (episodes.length < 2) continue;\n\n      const groups = matches.markers?.named?.('group') || [];\n      const groupArr: any[] = Array.isArray(groups) ? groups : groups ? [groups] : [];\n      const relevantGroups = groupArr.filter((g: any) => g.start >= filepart.start && g.end <= filepart.end);\n\n      const isInGroup = (m: any) =>\n        relevantGroups.some((g: any) => m.start >= g.start && m.end <= g.end);\n\n      const insideGroup = episodes.filter(isInGroup);\n      const outsideGroup = episodes.filter((m: any) => !isInGroup(m));\n\n      if (insideGroup.length > 0 && outsideGroup.length > 0) {\n        toRename.push(...insideGroup);\n      }\n    }\n\n    if (toRename.length === 0) return false;\n    (this as any)._toRename = toRename;\n    return true;\n  }\n\n  then(matches: any, _whenResponse: any, _context: any): void {\n    const toRename = (this as any)._toRename || [];\n    for (const match of toRename) {\n      matches.remove(match);\n      match.name = 'absolute_episode';\n      matches.append(match);\n    }\n  }\n}\n\nclass RemoveWeakIfSxxExxRule extends Rule {\n  consequence = RemoveMatch;\n  static override priority = 64;\n  override priority = 64;\n\n  when(matches: any, _context: any): any {\n    const toRemove: any[] = [];\n    const toRename: any[] = [];\n\n    const fileparts = matches.markers?.named('path') || [];\n    const filepartArr = Array.isArray(fileparts) ? fileparts : [fileparts];\n\n    for (const filepart of filepartArr) {\n      const sxxexxMatches = matches.range?.(filepart.start, filepart.end, (m: any) =>\n        !m.private && m.tags?.includes('SxxExx'),\n      ) || [];\n      const hasSxxExx = Array.isArray(sxxexxMatches) ? sxxexxMatches.length > 0 : !!sxxexxMatches;\n\n      if (hasSxxExx) {\n        const weakEpisodes: any[] = (matches.range?.(filepart.start, filepart.end, (m: any) =>\n          m.tags?.includes('weak-episode'),\n        ) || []);\n\n        // Collect weak_episode matches and check if any form a range\n        const weakEpByInitiator = new Map<any, any[]>();\n        for (const match of weakEpisodes) {\n          const init = match.initiator;\n          if (!weakEpByInitiator.has(init)) weakEpByInitiator.set(init, []);\n          weakEpByInitiator.get(init)!.push(match);\n        }\n\n        for (const match of weakEpisodes) {\n          const initiator = match.initiator;\n          const isWeakEpisode = match.name === 'episode' && initiator?.name === 'weak_episode';\n          // Check if this weak_episode is part of a range (has episodeSeparator child\n          // or multiple episode siblings from the same initiator)\n          const siblings = weakEpByInitiator.get(initiator) || [];\n          const isRange = siblings.filter((s: any) => s.name === 'episode').length > 1;\n          // Check if surrounded by separators (standalone number)\n          const inp = matches.inputString || '';\n          const mStart = initiator?.start ?? match.start;\n          const mEnd = initiator?.end ?? match.end;\n          const prevChar = mStart > 0 ? inp[mStart - 1] : '';\n          const nextChar = mEnd < inp.length ? inp[mEnd] : '';\n          const isSurrounded = (!prevChar || seps.includes(prevChar)) &&\n                              (!nextChar || seps.includes(nextChar));\n          if (isWeakEpisode && isSurrounded && isRange) {\n            toRename.push(match);\n          } else {\n            toRemove.push(match);\n          }\n        }\n      }\n    }\n\n    // Store renames on the rule instance for then() to process\n    (this as any)._toRename = toRename;\n    return toRemove.length > 0 || toRename.length > 0 ? toRemove : false;\n  }\n\n  then(matches: any, toRemove: any, _context: any): void {\n    // Remove matches\n    if (toRemove && Array.isArray(toRemove)) {\n      for (const match of toRemove) {\n        matches.remove(match);\n      }\n    }\n    // Rename weak_episode to absolute_episode\n    const toRename = (this as any)._toRename || [];\n    for (const match of toRename) {\n      matches.remove(match);\n      match.name = 'absolute_episode';\n      matches.append(match);\n    }\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport { seps, reEscape, sepsPattern } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { buildOrPattern } from '../../reutils.js';\n\nexport function container(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'container') });\n  rebulk.regexDefaults({ flags: 'i' }).stringDefaults({ ignoreCase: true });\n  rebulk.defaults({\n    name: 'container',\n    formatter: (value: string) => value.replace(new RegExp(`[${reEscape(seps)}]`, 'g'), ''),\n    tags: ['extension'],\n    conflictSolver: (match: Match, other: Match) =>\n      other.name === 'source' || other.name === 'video_codec' || (other.name === 'container' && !other.tags.includes('extension'))\n        ? other\n        : '__default__',\n  });\n\n  const subtitles = (config['subtitles'] as string[]) || [];\n  const info = (config['info'] as string[]) || [];\n  const videos = (config['videos'] as string[]) || [];\n  const torrent = (config['torrent'] as string[]) || [];\n  const nzb = (config['nzb'] as string[]) || [];\n  const archives = (config['archives'] as string[]) || [];\n  const images = (config['images'] as string[]) || [];\n\n  if (archives.length) rebulk.regex('\\\\.' + buildOrPattern(archives, undefined, true) + '$', {\n    exts: archives,\n    tags: ['extension', 'archive'],\n  });\n  // Split RAR volumes: \".r00\", \".r01\", … and \".partNN.rar\" (the .rar is caught above).\n  rebulk.regex('\\\\.r\\\\d{2}$', { tags: ['extension', 'archive'] });\n  if (images.length) rebulk.regex('\\\\.' + buildOrPattern(images, undefined, true) + '$', {\n    exts: images,\n    tags: ['extension', 'image'],\n  });\n  if (subtitles.length) rebulk.regex('\\\\.' + buildOrPattern(subtitles, undefined, true) + '$', {\n    exts: subtitles,\n    tags: ['extension', 'subtitle'],\n  });\n  if (info.length) rebulk.regex('\\\\.' + buildOrPattern(info, undefined, true) + '$', {\n    exts: info,\n    tags: ['extension', 'info'],\n  });\n  if (videos.length) rebulk.regex('\\\\.' + buildOrPattern(videos, undefined, true) + '$', {\n    exts: videos,\n    tags: ['extension', 'video'],\n  });\n  if (torrent.length) rebulk.regex('\\\\.' + buildOrPattern(torrent, undefined, true) + '$', {\n    exts: torrent,\n    tags: ['extension', 'torrent'],\n  });\n  if (nzb.length) rebulk.regex('\\\\.' + buildOrPattern(nzb, undefined, true) + '$', {\n    exts: nzb,\n    tags: ['extension', 'nzb'],\n  });\n\n  rebulk.defaults({\n    clear: true,\n    name: 'container',\n    validator: sepsSurround,\n    formatter: (s: string) => s.toLowerCase(),\n    conflictSolver: (match: Match, other: Match) =>\n      other.name === 'source' || other.name === 'video_codec' || (other.name === 'container' && other.tags.includes('extension'))\n        ? match\n        : '__default__',\n  });\n\n  const nonStdSubtitles = subtitles.filter((s) => !['sub', 'ass'].includes(s));\n  rebulk.string(...nonStdSubtitles, { tags: ['subtitle'] });\n  rebulk.string(...videos, { tags: ['video'] });\n  rebulk.string(...torrent, { tags: ['torrent'] });\n  rebulk.string(...nzb, { tags: ['nzb'] });\n\n  return rebulk;\n}\n","/**\n * Source property patterns and rules — port of guessit/rules/properties/source.py\n */\nimport { Rebulk, Rule, RemoveMatch, AppendMatch } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport type { Matches } from 'rebulk-js';\nimport type { Context } from 'rebulk-js';\nimport { dash, seps, sepsPattern, optional } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsBefore, sepsAfter, or_ } from '../common/validators.js';\n\nexport function source(config: Record<string, unknown>): Rebulk {\n  const ripPrefix = (config['rip_prefix'] as string) ?? '(?P<other>Rip)-?';\n  const ripSuffix = (config['rip_suffix'] as string) ?? '-?(?P<other>Rip)';\n\n  function buildSourcePattern(patterns: string[], prefix = '', suffix = ''): string[] {\n    return patterns.map((p) => `${prefix}(${p})${suffix}`);\n  }\n\n  function demoteOther(match: Match, other: Match): Match | '__default__' {\n    return ['other', 'release_group'].includes(other.name ?? '') ? other : '__default__';\n  }\n\n  const rebulk = new Rebulk({ disabled: (context: Context) => isDisabled(context, 'source') });\n\n  rebulk.regexDefaults({\n    flags: 'i',\n    abbreviations: [dash],\n    privateParent: true,\n    children: true,\n  });\n\n  rebulk.defaults({\n    name: 'source',\n    tags: ['video-codec-prefix', 'streaming_service.suffix'],\n    validateAll: true,\n    validator: { __parent__: or_(sepsBefore, sepsAfter) },\n  });\n\n  // VHS\n  rebulk.regex(...buildSourcePattern(['VHS'], '', optional(ripSuffix)),\n    { value: { source: 'VHS', other: 'Rip' } });\n\n  // Camera\n  rebulk.regex(...buildSourcePattern(['CAM'], '', optional(ripSuffix)),\n    { value: { source: 'Camera', other: 'Rip' } });\n\n  // HD Camera\n  rebulk.regex(...buildSourcePattern(['HD-?CAM'], '', optional(ripSuffix)),\n    { value: { source: 'HD Camera', other: 'Rip' } });\n\n  // HQCAM and S-Print/SPrint (Indian cam-release conventions) are cameras too\n  // (cross-parser corpus).\n  rebulk.regex(...buildSourcePattern(['HQ-?CAM'], '', optional(ripSuffix)),\n    { value: { source: 'Camera', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['S-?Print'], '', optional(ripSuffix)),\n    { value: { source: 'Camera' } });\n\n  // Telesync (TS is too common, avoid 'streaming_service.suffix' tag)\n  rebulk.regex(...buildSourcePattern(['TELESYNC', 'TS'], '', optional(ripSuffix)),\n    { value: { source: 'Telesync', other: 'Rip' }, tags: ['video-codec-prefix'], overrides: ['tags'] });\n\n  // HD Telesync\n  rebulk.regex(...buildSourcePattern(['HD-?TELESYNC', 'HD-?TS'], '', optional(ripSuffix)),\n    { value: { source: 'HD Telesync', other: 'Rip' } });\n\n  // Workprint\n  rebulk.regex(...buildSourcePattern(['WORKPRINT', 'WP']),\n    { value: 'Workprint' });\n\n  // Telecine\n  rebulk.regex(...buildSourcePattern(['TELECINE', 'TC'], '', optional(ripSuffix)),\n    { value: { source: 'Telecine', other: 'Rip' } });\n\n  // HD Telecine\n  rebulk.regex(...buildSourcePattern(['HD-?TELECINE', 'HD-?TC'], '', optional(ripSuffix)),\n    { value: { source: 'HD Telecine', other: 'Rip' } });\n\n  // Pay-per-view\n  rebulk.regex(...buildSourcePattern(['PPV'], '', optional(ripSuffix)),\n    { value: { source: 'Pay-per-view', other: 'Rip' } });\n\n  // TV\n  rebulk.regex(...buildSourcePattern(['SD-?TV'], '', optional(ripSuffix)),\n    { value: { source: 'TV', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['TV'], '', ripSuffix),\n    { value: { source: 'TV', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['TV', 'SD-?TV'], ripPrefix),\n    { value: { source: 'TV', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['TV-?(?=Dub)']),\n    { value: 'TV' });\n\n  // Digital TV\n  rebulk.regex(...buildSourcePattern(['DVB', 'PD-?TV'], '', optional(ripSuffix)),\n    { value: { source: 'Digital TV', other: 'Rip' } });\n\n  // DVD\n  rebulk.regex(...buildSourcePattern(['DVD'], '', optional(ripSuffix)),\n    { value: { source: 'DVD', other: 'Rip' } });\n  // DVD-R9 / DVD-R5 disc formats (\"DvdR9\") are DVDs (cross-parser corpus).\n  rebulk.regex(...buildSourcePattern(['DVD-?R[59]'], '', ''),\n    { value: { source: 'DVD' } });\n  // \"LD\" alone also means \"Line Dubbed\", so a bare \"LD\" is only Laserdisc with a Rip\n  // suffix; the full \"Laserdisc\" word matches with or without it. (upstream 4.x)\n  rebulk.regex(...buildSourcePattern(['LD'], '', ripSuffix),\n    { value: { source: 'Laserdisc', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['LASERDISC'], '', optional(ripSuffix)),\n    { value: { source: 'Laserdisc', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['DM'], '', optional(ripSuffix)),\n    { value: { source: 'Digital Master', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['VIDEO-?TS', 'DVD-?R(?:$|(?!E))', 'DVD-?9', 'DVD-?5']),\n    { value: 'DVD' });\n\n  // HDTV\n  rebulk.regex(...buildSourcePattern(['HD-?TV'], '', optional(ripSuffix)),\n    { conflictSolver: demoteOther, value: { source: 'HDTV', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['TV-?HD'], '', ripSuffix),\n    { conflictSolver: demoteOther, value: { source: 'HDTV', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['TV'], '', '-?(?P<other>Rip-?HD)'),\n    { conflictSolver: demoteOther, value: { source: 'HDTV', other: 'Rip' } });\n\n  // Video on Demand\n  rebulk.regex(...buildSourcePattern(['VOD'], '', optional(ripSuffix)),\n    { value: { source: 'Video on Demand', other: 'Rip' } });\n\n  // Web\n  rebulk.regex(...buildSourcePattern(['WEB', 'WEB-?DL'], '', ripSuffix),\n    { value: { source: 'Web', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['WEB-?(?P<another>Cap)'], '', optional(ripSuffix)),\n    { value: { source: 'Web', other: 'Rip', another: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['WEB-?DL', 'WEB-?U?HD', 'DL-?WEB', 'DL(?=-?Mux)']),\n    { value: { source: 'Web' } });\n  rebulk.regex('(WEB)', { value: 'Web', tags: 'weak.source' });\n\n  // HD-DVD\n  rebulk.regex(...buildSourcePattern(['HD-?DVD'], '', optional(ripSuffix)),\n    { value: { source: 'HD-DVD', other: 'Rip' } });\n\n  // Blu-ray\n  rebulk.regex(...buildSourcePattern(['Blu-?ray', 'BD', 'BD[59]', 'BD25', 'BD50'], '', optional(ripSuffix)),\n    { value: { source: 'Blu-ray', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['(?P<another>BR)-?(?=Scr(?:eener)?)', '(?P<another>BR)-?(?=Mux)']),\n    { value: { source: 'Blu-ray', another: 'Reencoded' } });\n  rebulk.regex(...buildSourcePattern(['(?P<another>BR)'], '', ripSuffix),\n    { value: { source: 'Blu-ray', other: 'Rip', another: 'Reencoded' } });\n\n  // Ultra HD Blu-ray\n  rebulk.regex(...buildSourcePattern(['Ultra-?Blu-?ray', 'Blu-?ray-?Ultra']),\n    { value: 'Ultra HD Blu-ray' });\n\n  // Analog HDTV\n  rebulk.regex(...buildSourcePattern(['AHDTV']),\n    { value: 'Analog HDTV' });\n\n  // Ultra HDTV\n  rebulk.regex(...buildSourcePattern(['UHD-?TV'], '', optional(ripSuffix)),\n    { conflictSolver: demoteOther, value: { source: 'Ultra HDTV', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['UHD'], '', ripSuffix),\n    { conflictSolver: demoteOther, value: { source: 'Ultra HDTV', other: 'Rip' } });\n\n  // Satellite\n  rebulk.regex(...buildSourcePattern(['DSR', 'DTH'], '', optional(ripSuffix)),\n    { value: { source: 'Satellite', other: 'Rip' } });\n  rebulk.regex(...buildSourcePattern(['DSR?', 'SAT'], '', ripSuffix),\n    { value: { source: 'Satellite', other: 'Rip' } });\n\n  rebulk.rules(ValidateSourcePrefixSuffix, ValidateWeakSource, UltraHdBlurayRule);\n\n  return rebulk;\n}\n\nclass ValidateSourcePrefixSuffix extends Rule {\n  static override priority = 64;\n  override consequence = RemoveMatch;\n\n  override enabled(context: Context): boolean {\n    return !isDisabled(context, 'source');\n  }\n\n  override when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n\n    for (const filepart of (matches.markers.named('path') as Match[] | Match | undefined ? [matches.markers.named('path')].flat() : [])) {\n      const fp = filepart as Match;\n      const sources = matches.range(fp.start, fp.end, (m) => m.name === 'source') as Match[];\n      for (const match of (Array.isArray(sources) ? sources : sources ? [sources] : [])) {\n        const initiator = (match as any).initiator ?? match;\n        const hasPrefixSep = sepsBefore(initiator);\n        const hasPrefixTag = matches.range(initiator.start - 1, initiator.start,\n          (m) => m.tags?.includes('source-prefix')) as Match[];\n        if (!hasPrefixSep && !(Array.isArray(hasPrefixTag) ? hasPrefixTag.length > 0 : !!hasPrefixTag)) {\n          if (initiator.children?.length > 0) ret.push(...initiator.children.toArray());\n          ret.push(initiator);\n          continue;\n        }\n        const hasSuffixSep = sepsAfter(initiator);\n        const hasSuffixTag = matches.range(initiator.end, initiator.end + 1,\n          (m) => m.tags?.includes('source-suffix')) as Match[];\n        if (!hasSuffixSep && !(Array.isArray(hasSuffixTag) ? hasSuffixTag.length > 0 : !!hasSuffixTag)) {\n          if (initiator.children?.length > 0) ret.push(...initiator.children.toArray());\n          ret.push(initiator);\n        }\n      }\n    }\n\n    return ret;\n  }\n}\n\nclass ValidateWeakSource extends Rule {\n  static override priority = 64;\n  override consequence = RemoveMatch;\n\n  override enabled(context: Context): boolean {\n    return !isDisabled(context, 'source');\n  }\n\n  override when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n\n    const toArray = (result: unknown): Match[] =>\n      (Array.isArray(result) ? result : result ? [result] : []) as Match[];\n\n    for (const filepart of [matches.markers.named('path')].flat().filter(Boolean) as Match[]) {\n      const sources = matches.range(filepart.start, filepart.end, (m) => m.name === 'source');\n      const hasText = (holes: unknown) =>\n        Array.isArray(holes) ? holes.length > 0 : !!holes;\n      const textHoles = (start: number, end: number) => matches.holes(start, end, {\n        predicate: (m: Match) => !!(m.value && String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')),\n      });\n\n      const containerMatches = toArray(\n        matches.range(filepart.start, filepart.end, (m) => m.name === 'container'),\n      );\n      // \".ts\" is the file extension — a container that also spells a source\n      // abbreviation. It must never outrank a real source earlier in the name.\n      const isExtension = (m: Match) =>\n        containerMatches.some((c) => c.start <= m.start && c.end >= m.end);\n\n      for (const match of toArray(sources)) {\n        const weak = !!match.tags?.includes('weak.source');\n\n        // If another source exists after this match\n        const nextSources = toArray(matches.range(match.end, filepart.end, (m) => m.name === 'source'));\n        if (nextSources.length === 0) continue;\n\n        // And there's a title-like hole before this match\n        if (!hasText(textHoles(filepart.start, match.start))) continue;\n\n        if (!weak) {\n          // A non-weak source only loses to a later one that is a genuine rival:\n          // the extension does not count (\"…MPEG2-TrollHD.ts\" keeps its HDTV).\n          const rivals = nextSources.filter((m) => !isExtension(m));\n          if (rivals.length === 0) continue;\n\n          // Title text between the two is necessary but not sufficient — two\n          // real sources compose across it (\"UFC.247.PPV.Jones.vs.Reyes.HDTV\").\n          // What marks the earlier one as episode-title text is a tag block\n          // opening before the rival: \"…Vhs.Mix.Tape.1080p.WEBRip…\" puts a\n          // screen_size between the two, so \"Vhs\" is title text (upstream #964).\n          if (!hasText(textHoles(match.end, rivals[0].start))) continue;\n          const tagsBetween = toArray(\n            matches.range(match.end, rivals[0].start, (m) => !!m.name && m.name !== 'source'),\n          );\n          if (tagsBetween.length === 0) continue;\n        }\n\n        if ((match as any).children?.length > 0) ret.push(...(match as any).children.toArray());\n        ret.push(match);\n      }\n    }\n\n    return ret;\n  }\n}\n\nclass UltraHdBlurayRule extends Rule {\n  override consequence = [RemoveMatch, AppendMatch];\n\n  override enabled(context: Context): boolean {\n    return !isDisabled(context, 'source');\n  }\n\n  override when(matches: Matches, _context: Context): [Match[], Match[]] | false {\n    const toRemove: Match[] = [];\n    const toAppend: Match[] = [];\n\n    for (const filepart of [matches.markers.named('path')].flat().filter(Boolean) as Match[]) {\n      const bluRaySources = matches.range(filepart.start, filepart.end,\n        (m) => !m.private && m.name === 'source' && m.value === 'Blu-ray') as Match[];\n\n      for (const match of (Array.isArray(bluRaySources) ? bluRaySources : bluRaySources ? [bluRaySources] : [])) {\n        // Look for Ultra HD match before or after\n        const findUltraHd = (start: number, end: number) =>\n          (matches.range(start, end, (m) => !m.private && m.name === 'other' && m.value === 'Ultra HD') as Match[])?.[0];\n\n        let other = findUltraHd(filepart.start, match.start);\n        if (other) {\n          const hasHoles = matches.holes(other.end, match.start,\n            { predicate: (m: Match) => !!(m.value && String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')) });\n          const hasInvalidMatches = matches.range(other.end, match.start,\n            (m) => !m.private && !['screen_size', 'color_depth'].includes(m.name ?? '') &&\n              !(m.name === 'other' && m.tags?.includes('uhdbluray-neighbor')));\n          if ((Array.isArray(hasHoles) ? hasHoles.length : hasHoles ? 1 : 0) > 0 ||\n              (Array.isArray(hasInvalidMatches) ? hasInvalidMatches.length : hasInvalidMatches ? 1 : 0) > 0) {\n            other = undefined as any;\n          }\n        }\n\n        if (!other) {\n          other = findUltraHd(match.end, filepart.end);\n          if (other) {\n            const hasHoles = matches.holes(match.end, other.start,\n              { predicate: (m: Match) => !!(m.value && String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')) });\n            const hasInvalidMatches = matches.range(match.end, other.start,\n              (m) => !m.private && !['screen_size', 'color_depth'].includes(m.name ?? '') &&\n                !(m.name === 'other' && m.tags?.includes('uhdbluray-neighbor')));\n            if ((Array.isArray(hasHoles) ? hasHoles.length : hasHoles ? 1 : 0) > 0 ||\n                (Array.isArray(hasInvalidMatches) ? hasInvalidMatches.length : hasInvalidMatches ? 1 : 0) > 0) {\n              other = undefined as any;\n            }\n          }\n        }\n\n        if (!other) {\n          // Also accept 2160p screen_size as indicator of Ultra HD\n          const has2160 = matches.range(filepart.start, filepart.end,\n            (m) => m.name === 'screen_size' && m.value === '2160p');\n          if (!(Array.isArray(has2160) ? has2160.length : has2160 ? 1 : 0)) continue;\n        }\n\n        if (other) other.private = true;\n\n        // Create a new proper Match instance with Ultra HD Blu-ray value\n        const newSource = new Match(match.start, match.end, {\n          name: match.name,\n          inputString: matches.inputString,\n          tags: [...(match.tags ?? [])],\n          private: match.private,\n          value: 'Ultra HD Blu-ray',\n        });\n        toRemove.push(match);\n        toAppend.push(newSource);\n      }\n    }\n\n    if (toRemove.length || toAppend.length) return [toRemove, toAppend];\n    return false;\n  }\n}\n","/**\n * Video codec property patterns and rules — port of guessit/rules/properties/video_codec.py\n */\nimport { Rebulk, Rule, RemoveMatch } from 'rebulk-js';\nimport type { Match, Matches } from 'rebulk-js';\nimport type { Context } from 'rebulk-js';\nimport { dash } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsBefore, sepsAfter, sepsSurround } from '../common/validators.js';\n\nexport function videoCodec(config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk();\n\n  rebulk.regexDefaults({\n    flags: 'i',\n    abbreviations: [dash],\n  });\n  rebulk.stringDefaults({ ignoreCase: true });\n  rebulk.defaults({\n    name: 'video_codec',\n    tags: ['source-suffix', 'streaming_service.suffix'],\n    disabled: (context: Context) => isDisabled(context, 'video_codec'),\n  });\n\n  rebulk.regex('Rv\\\\d{2}', { value: 'RealVideo' });\n  rebulk.regex('Mpe?g-?2', '[hx]-?262', { value: 'MPEG-2' });\n  rebulk.string('DVDivX', 'DivX', { value: 'DivX' });\n  rebulk.string('XviD', { value: 'Xvid' });\n  rebulk.regex('VC-?1', { value: 'VC-1' });\n  rebulk.string('VP7', { value: 'VP7' });\n  rebulk.string('VP8', 'VP80', { value: 'VP8' });\n  rebulk.string('VP9', { value: 'VP9' });\n  rebulk.regex('[hx]-?263', { value: 'H.263' });\n  rebulk.regex('[hx]-?264', '(?:MPEG-?4)?AVC(?:HD)?', { value: 'H.264' });\n  rebulk.regex('[hx]-?265', 'HEVC', { value: 'H.265' });\n  rebulk.regex('(?<video_codec>hevc)(?<color_depth>10)', {\n    value: { video_codec: 'H.265', color_depth: '10-bit' },\n    tags: ['video-codec-suffix'],\n    children: true,\n  });\n\n  rebulk.defaults({\n    clear: true,\n    name: 'video_profile',\n    validator: sepsSurround,\n    disabled: (context: Context) => isDisabled(context, 'video_profile'),\n  });\n  rebulk.string('BP', { value: 'Baseline', tags: 'video_profile.rule' });\n  rebulk.string('XP', 'EP', { value: 'Extended', tags: 'video_profile.rule' });\n  rebulk.string('MP', { value: 'Main', tags: 'video_profile.rule' });\n  rebulk.string('HP', 'HiP', { value: 'High', tags: 'video_profile.rule' });\n  rebulk.string('SC', 'SVC', { value: 'Scalable Video Coding', tags: 'video_profile.rule' });\n  rebulk.regex('AVC(?:HD)?', { value: 'Advanced Video Codec High Definition', tags: 'video_profile.rule' });\n  rebulk.string('HEVC', { value: 'High Efficiency Video Coding', tags: 'video_profile.rule' });\n  rebulk.regex('Hi422P', { value: 'High 4:2:2' });\n  rebulk.regex('Hi444PP', { value: 'High 4:4:4 Predictive' });\n  rebulk.regex('Hi10P?', { value: 'High 10' });\n  rebulk.string('DXVA', {\n    value: 'DXVA',\n    name: 'video_api',\n    disabled: (context: Context) => isDisabled(context, 'video_api'),\n  });\n\n  rebulk.defaults({\n    clear: true,\n    name: 'color_depth',\n    validator: sepsSurround,\n    disabled: (context: Context) => isDisabled(context, 'color_depth'),\n  });\n  rebulk.regex('12.?bits?', { value: '12-bit' });\n  rebulk.regex('10.?bits?', 'YUV420P10', 'Hi10P?', { value: '10-bit' });\n  rebulk.regex('8.?bits?', { value: '8-bit' });\n\n  rebulk.rules(ValidateVideoCodec, VideoProfileRule);\n\n  return rebulk;\n}\n\nclass ValidateVideoCodec extends Rule {\n  static priority = 64;\n  static consequence = RemoveMatch;\n\n  enabled(context: Context): boolean {\n    return !isDisabled(context, 'video_codec');\n  }\n\n  when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n    const codecs = matches.named('video_codec');\n\n    const hasAny = (v: any) => Array.isArray(v) ? v.length > 0 : !!v;\n    const inp: string = (matches as any).inputString ?? '';\n    for (const codec of codecs) {\n      // A codec enlarged over a bracket edge (\"[h264…\") is separator-bounded by\n      // the bracket itself (Python loses these — see ponyo[h264.dts]).\n      const bracketBefore = inp[codec.start] === '[' || inp[codec.start - 1] === '[';\n      const bracketAfter = inp[codec.end - 1] === ']' || inp[codec.end] === ']';\n      if (!bracketBefore && !sepsBefore(codec) && !hasAny(matches.atIndex(codec.start - 1, (m) => m.tags?.includes('video-codec-prefix')))) {\n        ret.push(codec);\n        continue;\n      }\n      if (!bracketAfter && !sepsAfter(codec) && !hasAny(matches.atIndex(codec.end + 1, (m) => m.tags?.includes('video-codec-suffix')))) {\n        ret.push(codec);\n        continue;\n      }\n    }\n\n    return ret;\n  }\n}\n\nclass VideoProfileRule extends Rule {\n  static consequence = RemoveMatch;\n\n  enabled(context: Context): boolean {\n    return !isDisabled(context, 'video_profile');\n  }\n\n  when(matches: Matches, _context: Context): Match[] {\n    const profileList = (matches.named('video_profile', (m) => m.tags?.includes('video_profile.rule')) as Match[]) ?? [];\n    const ret: Match[] = [];\n\n    for (const profile of profileList) {\n      let codec = matches.atSpan(profile.span, (m) => m.name === 'video_codec', 0);\n      if (!codec) {\n        codec = matches.previous(profile, (m) => m.name === 'video_codec', 0);\n      }\n      if (!codec) {\n        codec = matches.next(profile, (m) => m.name === 'video_codec', 0);\n      }\n      if (!codec) {\n        ret.push(profile);\n      }\n    }\n\n    return ret;\n  }\n}\n","/**\n * Config module — port of guessit/config/__init__.py\n * Handles loading patterns from the config JSON into a Rebulk builder.\n */\nimport type { Rebulk } from 'rebulk-js';\nimport { sepsBefore, sepsAfter, sepsSurround } from '../rules/common/validators.js';\n\nconst REGEX_PREFIX = 're:';\nconst IMPORT_PREFIX = 'import:';\nconst EVAL_PREFIX = 'eval:';\nconst PATTERN_TYPES = ['regex', 'string'] as const;\n\nconst DEFAULT_MODULE_NAMES: Record<string, string> = {\n  validator: 'validators',\n  formatter: 'formatters',\n};\n\n// Dynamic import cache for validator/formatter functions\nconst importCache: Map<string, unknown> = new Map();\n\n/**\n * Registry of named validators and formatters that can be imported by name.\n */\nconst registry: Map<string, unknown> = new Map();\n\nexport function registerFunction(name: string, fn: unknown): void {\n  registry.set(name, fn);\n}\n\n// Pre-register common validators so `import:seps_after` etc. resolve correctly.\nregistry.set('seps_after', sepsAfter);\nregistry.set('seps_before', sepsBefore);\nregistry.set('seps_surround', sepsSurround);\n\n// ─── Known Python lambda implementations ─────────────────────────────────────\n// In Python rebulk, conflict_solver(match, other) returns the match to REMOVE,\n// or '__default__' to fall back to the default solver.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ConflictSolverFn = (match: any, other: any) => any;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ValidatorFn = (match: any) => boolean;\n\nconst KNOWN_CONFLICT_SOLVERS: Record<string, ConflictSolverFn> = {\n  // DTS-HD: remove the other audio_codec in favor of DTS-HD\n  \"lambda match, other: other if other.name == 'audio_codec' else '__default__'\":\n    (match, other) => other.name === 'audio_codec' ? other : '__default__',\n\n  // bit_rate: remove bit_rate if other is a strong audio_channels; else remove audio_channels\n  \"lambda match, other: match if other.name == 'audio_channels' and 'weak-audio_channels' not in other.tags else other\":\n    (match, other) => {\n      if (other.name === 'audio_channels' && !(other.tags ?? []).includes('weak-audio_channels')) {\n        return match; // remove bit_rate\n      }\n      return other; // remove audio_channels\n    },\n\n  // bonus: yield to video_codec or strong episode; win against weak episodes\n  \"lambda match, conflicting: match if conflicting.name in ('video_codec', 'episode') and 'weak-episode' not in conflicting.tags else '__default__'\":\n    (match, conflicting) => {\n      if (\n        ['video_codec', 'episode'].includes(conflicting.name) &&\n        !(conflicting.tags ?? []).includes('weak-episode')\n      ) {\n        return match; // remove bonus, keep strong episode/video_codec\n      }\n      // When conflicting is a weak episode, keep the bonus (remove the episode)\n      if (conflicting.name === 'episode' && (conflicting.tags ?? []).includes('weak-episode')) {\n        return conflicting; // remove weak episode, keep bonus\n      }\n      return '__default__';\n    },\n\n  // special edition: remove episode_details 'Special' in favor of this match\n  \"lambda match, other: other if other.name == 'episode_details' and other.value == 'Special' else '__default__'\":\n    (match, other) => (other.name === 'episode_details' && other.value === 'Special') ? other : '__default__',\n};\n\nconst KNOWN_VALIDATORS: Record<string, ValidatorFn> = {\n  'lambda match: 0 < match.value < 100':\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    (match: any) => typeof match.value === 'number' && match.value > 0 && match.value < 100,\n};\n\nfunction processExecutable(value: string, _defaultModule?: string): unknown {\n  if (value.startsWith(IMPORT_PREFIX)) {\n    const target = value.slice(IMPORT_PREFIX.length);\n    if (importCache.has(target)) return importCache.get(target);\n    const fn = registry.get(target);\n    if (fn !== undefined) {\n      importCache.set(target, fn);\n      return fn;\n    }\n    // Return as-is if not found — pattern definitions may reference functions\n    // that need to be resolved at runtime\n    return undefined;\n  }\n  if (value.startsWith(EVAL_PREFIX)) {\n    // Map common Python eval: formatter expressions to JS functions\n    const expr = value.slice(EVAL_PREFIX.length).trim();\n    if (expr === 'int') return (s: unknown) => parseInt(String(s), 10);\n    if (expr === 'float') return (s: unknown) => parseFloat(String(s));\n    if (expr === 'bool') return (s: unknown) => Boolean(s);\n    // Unknown eval: expression — return raw string (best effort)\n    return expr;\n  }\n  if (value.startsWith('lambda ') || value.startsWith('lambda:')) {\n    // Try to resolve known Python lambdas to native JS implementations\n    const knownConflict = KNOWN_CONFLICT_SOLVERS[value];\n    if (knownConflict) return knownConflict;\n    const knownValidator = KNOWN_VALIDATORS[value];\n    if (knownValidator) return knownValidator;\n    // Unknown lambda — not executable in JS, return undefined\n    return undefined;\n  }\n  return value;\n}\n\n/** Map from Python snake_case option names to TypeScript camelCase counterparts. */\nconst SNAKE_TO_CAMEL: Record<string, string> = {\n  conflict_solver: 'conflictSolver',\n  private_parent: 'privateParent',\n  private_children: 'privateChildren',\n  private_names: 'privateNames',\n  ignore_names: 'ignoreNames',\n  format_all: 'formatAll',\n  validate_all: 'validateAll',\n  pre_match_processor: 'preMatchProcessor',\n  post_match_processor: 'postMatchProcessor',\n  post_processor: 'postProcessor',\n  log_level: 'logLevel',\n  ignore_case: 'ignoreCase',\n};\n\n/** Rename snake_case keys to camelCase in an options object (shallow, in-place). */\nfunction normalizeCamelCase(obj: Record<string, unknown>): Record<string, unknown> {\n  for (const [snake, camel] of Object.entries(SNAKE_TO_CAMEL)) {\n    if (snake in obj && !(camel in obj)) {\n      obj[camel] = obj[snake];\n      delete obj[snake];\n    }\n  }\n  return obj;\n}\n\nfunction processOption(name: string, value: unknown): unknown {\n  if (name === 'validator' || name === 'conflict_solver' || name === 'formatter') {\n    if (value && typeof value === 'object' && !Array.isArray(value)) {\n      const result: Record<string, unknown> = {};\n      for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n        result[k] = processOption(name, v);\n      }\n      return result;\n    }\n    if (value !== null && value !== undefined && typeof value === 'string') {\n      return processExecutable(value, DEFAULT_MODULE_NAMES[name]);\n    }\n  }\n  return value;\n}\n\nfunction buildEntryDecl(entry: unknown, options: Record<string | symbol, unknown>, value: string): Record<string, unknown> {\n  const defaultOpts = (options[Symbol.for('default')] || options['__default__'] || {}) as Record<string, unknown>;\n  const entryDecl: Record<string, unknown> = { ...defaultOpts };\n  if (!value.startsWith('_')) {\n    entryDecl['value'] = value;\n  }\n  if (typeof entry === 'string') {\n    if (entry.startsWith(REGEX_PREFIX)) {\n      entryDecl['regex'] = [entry.slice(REGEX_PREFIX.length)];\n    } else {\n      entryDecl['string'] = [entry];\n    }\n  } else if (entry && typeof entry === 'object') {\n    Object.assign(entryDecl, entry as Record<string, unknown>);\n  }\n  // Handle legacy 'pattern' key\n  if ('pattern' in entryDecl) {\n    const legacyPattern = entryDecl['pattern'] as string;\n    delete entryDecl['pattern'];\n    if (legacyPattern.startsWith(REGEX_PREFIX)) {\n      entryDecl['regex'] = [legacyPattern.slice(REGEX_PREFIX.length)];\n    } else {\n      entryDecl['string'] = [legacyPattern];\n    }\n  }\n  return entryDecl;\n}\n\nexport function loadPatterns(\n  rebulk: Rebulk,\n  patternType: 'regex' | 'string',\n  patterns: string[],\n  options: Record<string | symbol, unknown> = {},\n): void {\n  const defaultOpts = (options[Symbol.for('default')] || options['__default__'] || {}) as Record<string, unknown>;\n  const itemOptions: Record<string, unknown> = { ...defaultOpts };\n  const patternTypeOption = options[patternType] as Record<string, unknown> | undefined;\n  if (patternTypeOption) Object.assign(itemOptions, patternTypeOption);\n\n  // Process option values (handle import: / eval: / lambda strings)\n  const processedOptions: Record<string, unknown> = {};\n  for (const [name, val] of Object.entries(itemOptions)) {\n    processedOptions[name] = processOption(name, val);\n  }\n\n  // Remove undefined processed options (e.g. unresolvable lambda/eval strings)\n  for (const key of Object.keys(processedOptions)) {\n    if (processedOptions[key] === undefined) {\n      delete processedOptions[key];\n    }\n  }\n\n  // Convert snake_case keys to camelCase for TypeScript pattern/match options\n  normalizeCamelCase(processedOptions);\n\n  if (patternType === 'regex') {\n    (rebulk as Rebulk).regex(...patterns, processedOptions as Parameters<Rebulk['regex']>[0]);\n  } else {\n    (rebulk as Rebulk).string(...patterns, processedOptions as Parameters<Rebulk['string']>[0]);\n  }\n}\n\n/**\n * Load patterns defined in the given config dict into the rebulk builder.\n * Mirrors Python's load_config_patterns().\n */\nexport function loadConfigPatterns(\n  rebulk: Rebulk,\n  config: Record<string, unknown> | undefined,\n  options: Record<string | symbol, unknown> = {},\n): void {\n  if (!config) return;\n\n  for (const [value, rawEntries] of Object.entries(config)) {\n    const entries: unknown[] = Array.isArray(rawEntries) ? rawEntries : [rawEntries];\n    for (const entry of entries) {\n      // Process entry\n      const entryDecl = buildEntryDecl(entry, options, value);\n\n      for (const patternType of PATTERN_TYPES) {\n        let patterns = entryDecl[patternType];\n        if (!patterns) continue;\n        if (!Array.isArray(patterns)) patterns = [patterns];\n\n        const patternsEntryDecl = { ...entryDecl };\n        for (const pt of PATTERN_TYPES) delete patternsEntryDecl[pt];\n\n        const currentPatternOptions: Record<string | symbol, unknown> = { ...options };\n        currentPatternOptions[Symbol.for('default')] = patternsEntryDecl;\n        currentPatternOptions['__default__'] = patternsEntryDecl;\n\n        loadPatterns(rebulk, patternType as 'regex' | 'string', patterns as string[], currentPatternOptions);\n      }\n    }\n  }\n}\n","/**\n * Audio codec property patterns and rules — port of guessit/rules/properties/audio_codec.py\n */\nimport { Rebulk, Rule, RemoveMatch, AppendMatch } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport type { Matches } from 'rebulk-js';\nimport type { Context } from 'rebulk-js';\nimport { dash } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsBefore, sepsAfter, sepsSurround } from '../common/validators.js';\nimport { loadConfigPatterns } from '../../config/index.js';\n\nexport function audioCodec(config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk();\n\n  rebulk.regexDefaults({\n    flags: 'i',\n    abbreviations: [dash],\n  });\n  rebulk.stringDefaults({ ignoreCase: true });\n\n  // Load audio_codec patterns from config\n  rebulk.defaults({\n    name: 'audio_codec',\n    tags: ['source-suffix', 'streaming_service.suffix'],\n    disabled: (context: Context) => isDisabled(context, 'audio_codec'),\n  });\n  loadConfigPatterns(rebulk, config['audio_codec'] as Record<string, unknown>);\n\n  // Load audio_profile patterns from config\n  rebulk.defaults({\n    clear: true,\n    name: 'audio_profile',\n    validator: sepsSurround,\n    disabled: (context: Context) => isDisabled(context, 'audio_profile'),\n  });\n  loadConfigPatterns(rebulk, config['audio_profile'] as Record<string, unknown>);\n\n  // Load audio_channels patterns from config\n  rebulk.defaults({\n    clear: true,\n    name: 'audio_channels',\n    disabled: (context: Context) => isDisabled(context, 'audio_channels'),\n  });\n  loadConfigPatterns(rebulk, config['audio_channels'] as Record<string, unknown>);\n\n  // Compound codec+profile functional patterns (e.g. DTSES, HE-AAC)\n  function findCompoundAudio(input: string): Array<[number, number, Record<string, unknown>]> {\n    const results: Array<[number, number, Record<string, unknown>]> = [];\n    const patterns: Array<{ regex: RegExp; codec: string; profile: string }> = [\n      { regex: /DTS-?ES/gi, codec: 'DTS', profile: 'Extended Surround' },\n      { regex: /DTS-?MA/gi, codec: 'DTS-HD', profile: 'Master Audio' },\n      { regex: /HE-?AAC/gi, codec: 'AAC', profile: 'High Efficiency' },\n      { regex: /DD-?EX/gi, codec: 'Dolby Digital', profile: 'EX' },\n    ];\n    for (const p of patterns) {\n      let m: RegExpExecArray | null;\n      while ((m = p.regex.exec(input)) !== null) {\n        results.push([m.index, m.index + m[0].length, { value: p.codec, tags: ['compound-audio'] }]);\n      }\n    }\n    return results;\n  }\n\n  rebulk.functional(findCompoundAudio, {\n    name: 'audio_codec',\n    disabled: (context: Context) => isDisabled(context, 'audio_codec'),\n  });\n\n  rebulk.rules(\n    CompoundAudioProfileRule,\n    DtsHDRule,\n    DtsRule,\n    AacRule,\n    DolbyDigitalRule,\n    HqConflictRule,\n    AudioValidatorRule,\n    AudioChannelsValidatorRule,\n    RemoveDecimalTitleChannels,\n  );\n\n  return rebulk;\n}\n\nconst COMPOUND_PROFILES: Record<string, string> = {\n  'DTS': 'Extended Surround',\n  'DTS-HD': 'Master Audio',\n  'AAC': 'High Efficiency',\n  'Dolby Digital': 'EX',\n};\n\nclass CompoundAudioProfileRule extends Rule {\n  // Must run before AudioValidatorRule (priority 64): the appended Master Audio\n  // profile is the neighbor that keeps a glued 'MA5.1' channels match alive.\n  static priority = 128;\n  priority = 128;\n  static consequence = AppendMatch;\n\n  enabled(context: Context): boolean {\n    return !isDisabled(context, 'audio_profile');\n  }\n\n  when(matches: Matches): Match | undefined {\n    const codecs = matches.named('audio_codec') as Match[];\n    for (const codec of codecs) {\n      // Check compound-audio tagged matches first\n      if (codec.tags?.includes('compound-audio')) {\n        const profileValue = COMPOUND_PROFILES[String(codec.value)];\n        if (profileValue) {\n          const profile = new Match(codec.start, codec.end, {\n            name: 'audio_profile',\n            value: profileValue,\n            inputString: codec.inputString,\n          });\n          return profile;\n        }\n      }\n      // Also check DTS-HD matches whose raw text contains \"MA\" (e.g. \"DTSMA\", \"DTS-MA\")\n      // or if \"MA\" immediately follows the DTS-HD match (e.g. \"DTS-HD.MA5.1\")\n      if (String(codec.value) === 'DTS-HD') {\n        const raw = (codec.raw ?? codec.inputString?.slice(codec.start, codec.end) ?? '').toUpperCase();\n        if (/MA/.test(raw)) {\n          const profile = new Match(codec.start, codec.end, {\n            name: 'audio_profile',\n            value: 'Master Audio',\n            inputString: codec.inputString,\n          });\n          return profile;\n        }\n        // Check if \"MA\" follows right after (with optional separator)\n        const inputStr = codec.inputString ?? '';\n        const afterCodec = inputStr.slice(codec.end, codec.end + 4).toUpperCase();\n        if (/^[.\\-_\\s]?MA(?!\\w*[b-ln-z])/i.test(afterCodec)) {\n          const maStart = codec.end + (afterCodec.match(/^[.\\-_\\s]/) ? 1 : 0);\n          const profile = new Match(maStart, maStart + 2, {\n            name: 'audio_profile',\n            value: 'Master Audio',\n            inputString: codec.inputString,\n          });\n          return profile;\n        }\n      }\n    }\n  }\n}\n\nabstract class AudioProfileRule extends Rule {\n  static consequence = RemoveMatch;\n  abstract codecName: string;\n\n  enabled(context: Context): boolean {\n    return !isDisabled(context, 'audio_profile');\n  }\n\n  when(matches: Matches, _context: Context): Match[] | false {\n    const ret: Match[] = [];\n    const profiles = matches.named('audio_profile') as Match[];\n    const hasResult = (v: any) => v && (!Array.isArray(v) || v.length > 0);\n\n    for (const profile of profiles) {\n      // Only check profiles that belong to this codec (via tags)\n      if (!profile.tags.includes(this.codecName)) continue;\n\n      let codec: any = matches.atSpan(profile.span, (m: Match) => m.name === `audio_codec` && m.value === this.codecName);\n      if (!hasResult(codec)) {\n        // Check IMMEDIATELY previous and next matches only (not scanning far away).\n        // In Python rebulk, previous/next return the nearest match; the JS version\n        // should do the same but currently scans further. So we check the immediate\n        // neighbor and verify it's the right codec.\n        const prevMatch = matches.previous(profile, (m: Match) => !m.private, 0) as Match | undefined;\n        if (prevMatch && prevMatch.name === 'audio_codec' && prevMatch.value === this.codecName) {\n          codec = prevMatch;\n        }\n      }\n      if (!hasResult(codec)) {\n        const nextMatch = matches.next(profile, (m: Match) => !m.private, 0) as Match | undefined;\n        if (nextMatch && nextMatch.name === 'audio_codec' && nextMatch.value === this.codecName) {\n          codec = nextMatch;\n        }\n      }\n      if (!hasResult(codec)) {\n        ret.push(profile);\n      }\n    }\n\n    return ret.length > 0 ? ret : false;\n  }\n}\n\nclass DtsHDRule extends AudioProfileRule {\n  codecName = 'DTS-HD';\n}\n\nclass DtsRule extends AudioProfileRule {\n  codecName = 'DTS';\n}\n\nclass AacRule extends AudioProfileRule {\n  codecName = 'AAC';\n}\n\nclass DolbyDigitalRule extends AudioProfileRule {\n  codecName = 'Dolby Digital';\n}\n\nclass HqConflictRule extends Rule {\n  static consequence = RemoveMatch;\n\n  enabled(context: Context): boolean {\n    return !isDisabled(context, 'audio_profile');\n  }\n\n  when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n    const others = matches.named('other');\n    const hqProfiles = (matches.named('audio_profile', (m) => m.value === 'High Quality') as Match[]) ?? [];\n\n    for (const hq of hqProfiles) {\n      for (const other of others) {\n        if (other.span[0] === hq.span[0] && other.span[1] === hq.span[1]) {\n          ret.push(other);\n        }\n      }\n    }\n\n    return ret;\n  }\n}\n\nclass AudioValidatorRule extends Rule {\n  static priority = 64;\n  static consequence = RemoveMatch;\n\n  enabled(context: Context): boolean {\n    return !isDisabled(context, 'audio_codec') && !isDisabled(context, 'audio_profile');\n  }\n\n  when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n    const AUDIO_PROPS = ['audio_codec', 'audio_profile', 'audio_channels'];\n    const audioProps = AUDIO_PROPS.flatMap((n) => [...matches.named(n)]);\n\n    for (const prop of audioProps) {\n      if (!sepsBefore(prop)) {\n        const validBefore = matches.range(prop.start - 1, prop.start,\n          (m: Match) => AUDIO_PROPS.includes(m.name ?? '')) as Match[];\n        if (!(Array.isArray(validBefore) ? validBefore.length : validBefore)) {\n          ret.push(prop);\n          continue;\n        }\n      }\n      if (!sepsAfter(prop)) {\n        const validAfter = matches.range(prop.end, prop.end + 1,\n          (m: Match) => AUDIO_PROPS.includes(m.name ?? '')) as Match[];\n        if (!(Array.isArray(validAfter) ? validAfter.length : validAfter)) {\n          ret.push(prop);\n          continue;\n        }\n      }\n    }\n\n    return ret;\n  }\n}\n\n/**\n * \"Ghost.In.The.Shell.2.0.2008\" and \"M3GAN.2.0.2025\" carry a decimal version in\n * the title, not a stereo track (upstream #963). A channel layout that sits in\n * title text and is immediately followed by the release year — with no audio\n * codec glued in front of it, which is how real layouts appear (\"DD5.1\") — is\n * that version number.\n */\nclass RemoveDecimalTitleChannels extends Rule {\n  static priority = 128;\n  static consequence = RemoveMatch;\n\n  enabled(context: Context): boolean {\n    return !isDisabled(context, 'audio_channels');\n  }\n\n  when(matches: Matches, _context: Context): Match[] {\n    const input: string = matches.inputString ?? '';\n    const ret: Match[] = [];\n\n    for (const channels of (matches.named('audio_channels') as Match[])) {\n      const initiator = (channels as any).initiator ?? channels;\n      if (!/^\\d[\\W_]\\d$/.test(input.slice(initiator.start, initiator.end))) continue;\n\n      // An audio codec or profile glued in front makes it a genuine layout.\n      const prefixed = matches.range(initiator.start - 1, initiator.start,\n        (m: Match) => !m.private) as Match[];\n      if ((Array.isArray(prefixed) ? prefixed.length : prefixed ? 1 : 0)) continue;\n\n      // The year has to follow across a single separator.\n      const yearAfter = matches.range(initiator.end, initiator.end + 2,\n        (m: Match) => m.name === 'year') as Match[];\n      if (!(Array.isArray(yearAfter) ? yearAfter.length : yearAfter ? 1 : 0)) continue;\n\n      if ((channels as any).children?.length > 0) ret.push(...(channels as any).children.toArray());\n      ret.push(channels);\n      if (initiator !== channels) ret.push(initiator);\n    }\n\n    return ret;\n  }\n}\n\nclass AudioChannelsValidatorRule extends Rule {\n  static priority = 128;\n  static consequence = RemoveMatch;\n\n  enabled(context: Context): boolean {\n    return !isDisabled(context, 'audio_channels');\n  }\n\n  when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n    const weakChannels = (matches.named('audio_channels', (m) => m.tags.includes('weak-audio_channels')) as Match[]) ?? [];\n\n    for (const channels of weakChannels) {\n      const prevCodec = matches.previous(channels, (m) => m.name === `audio_codec`);\n      if (!prevCodec) {\n        ret.push(channels);\n      }\n    }\n\n    return ret;\n  }\n}\n","/**\n * Quantity helpers — port of guessit/rules/common/quantity.py\n */\nimport { seps } from './index.js';\n\nconst PARSER_RE = /^(?<magnitude>\\d+(?:[.]\\d+)?)(?<units>[^\\d]+)?/;\n\nexport abstract class Quantity {\n  magnitude: number;\n  units: string;\n\n  constructor(magnitude: number, units: string) {\n    this.magnitude = magnitude;\n    this.units = units;\n  }\n\n  static parseUnits(_value: string): string {\n    throw new Error('parseUnits must be implemented by subclass');\n  }\n\n  static fromstring(this: any, string: string): any {\n    const m = PARSER_RE.exec(string);\n    if (!m?.groups) throw new Error(`Cannot parse quantity: ${string}`);\n    const magStr = m.groups['magnitude'];\n    const magnitude = magStr.includes('.') ? parseFloat(magStr) : parseInt(magStr, 10);\n    const unitsStr = m.groups['units'] ?? '';\n    const units: string = (this as unknown as typeof Quantity).parseUnits(unitsStr);\n    return new this(magnitude, units);\n  }\n\n  toString(): string {\n    return `${this.magnitude}${this.units}`;\n  }\n\n  equals(other: unknown): boolean {\n    if (typeof other === 'string') return this.toString() === other;\n    if (!(other instanceof Quantity)) return false;\n    return this.magnitude === other.magnitude && this.units === other.units;\n  }\n}\n\nexport class Size extends Quantity {\n  static parseUnits(value: string): string {\n    let s = value;\n    for (const sep of seps) s = s.split(sep).join('');\n    return s.toUpperCase();\n  }\n\n  static fromstring(string: string): Size {\n    return Quantity.fromstring.call(Size, string) as Size;\n  }\n}\n\nexport class BitRate extends Quantity {\n  static parseUnits(value: string): string {\n    let s = value;\n    for (const sep of seps) s = s.split(sep).join('');\n    s = s.charAt(0).toUpperCase() + s.slice(1);\n    for (const token of ['bits', 'bit']) {\n      s = s.replace(token, 'bps');\n    }\n    return s;\n  }\n\n  static fromstring(string: string): BitRate {\n    return Quantity.fromstring.call(BitRate, string) as BitRate;\n  }\n}\n\nexport class FrameRate extends Quantity {\n  static parseUnits(_value: string): string {\n    return 'fps';\n  }\n\n  static fromstring(string: string): FrameRate {\n    return Quantity.fromstring.call(FrameRate, string) as FrameRate;\n  }\n}\n","/**\n * screen_size property — port of guessit/rules/properties/screen_size.py\n */\nimport { Rebulk } from 'rebulk-js';\nimport { Rule, RemoveMatch, AppendMatch } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport type { Matches } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { dash, seps , sepsPattern } from '../common/index.js';\nimport { buildOrPattern } from '../../reutils.js';\nimport { FrameRate } from '../common/quantity.js';\n\nexport interface ScreenSizeConfig {\n  frame_rates: string[];\n  interlaced: string[];\n  progressive: string[];\n  min_ar: number;\n  max_ar: number;\n}\n\nexport function screenSize(config: ScreenSizeConfig): Rebulk {\n  const interlaced = new Set(config.interlaced);\n  const progressive = new Set(config.progressive);\n  const standardHeights = progressive;\n  const frameRates = config.frame_rates;\n  const minAr = config.min_ar;\n  const maxAr = config.max_ar;\n\n  const rebulk = new Rebulk();\n  rebulk.stringDefaults({ ignoreCase: true });\n  rebulk.regexDefaults({ flags: 'i' });\n\n  rebulk.defaults({\n    name: 'screen_size',\n    validator: sepsSurround,\n    abbreviations: [dash],\n    disabled: (context: Record<string, unknown>) => isDisabled(context, 'screen_size'),\n  });\n\n  const frameRatePattern = buildOrPattern(frameRates, 'frame_rate');\n  const interlacedPattern = buildOrPattern([...interlaced], 'height');\n  const progressivePattern = buildOrPattern([...progressive], 'height');\n  const resSeparator = `(?:x|\\\\*|×)`;\n  const resPattern = `(?:(?<width>\\\\d{3,4})${resSeparator})?`;\n\n  rebulk.regex(resPattern + interlacedPattern + `(?<scan_type>i)` + frameRatePattern + `?`);\n  rebulk.regex(resPattern + progressivePattern + `(?<scan_type>p)` + frameRatePattern + `?`);\n  rebulk.regex(resPattern + progressivePattern + `(?<scan_type>p)?(?:hd)`);\n  rebulk.regex(resPattern + progressivePattern + `(?<scan_type>p)?x?`);\n  rebulk.string('4k', {\n    value: '2160p',\n    conflictSolver: (match: Match, other: Match) =>\n      other.name === 'screen_size' ? '__default__' : match,\n  });\n  // Trailing \"up\" (upscaled) marker may glue to the resolution (#741); × is the U+00D7 separator.\n  // Separators around the \"x\" must be symmetric: \"1920x1080\" or \"1920 x 1080\", never \"1080 x265\".\n  rebulk.regex(`(?<width>\\\\d{3,4})(?:${resSeparator}|-${resSeparator}-)(?<height>\\\\d{3,4})(?:up)?`, {\n    conflictSolver: (match: Match, other: Match) =>\n      other.name === 'screen_size' ? '__default__' : other,\n  });\n\n  rebulk.regex(frameRatePattern + `-?(?:p|fps)`, {\n    name: 'frame_rate',\n    formatter: (s: string) => FrameRate.fromstring(s).toString(),\n    disabled: (context: Record<string, unknown>) => isDisabled(context, 'frame_rate'),\n  });\n\n  rebulk.rules(\n    new PostProcessScreenSize(standardHeights, minAr, maxAr),\n    ScreenSizeOnlyOne,\n    ResolveScreenSizeConflicts,\n  );\n\n  return rebulk;\n}\n\nclass PostProcessScreenSize extends Rule {\n  static consequence = AppendMatch;\n\n  private standardHeights: Set<string>;\n  private minAr: number;\n  private maxAr: number;\n\n  constructor(standardHeights: Set<string>, minAr: number, maxAr: number) {\n    super();\n    this.standardHeights = standardHeights;\n    this.minAr = minAr;\n    this.maxAr = maxAr;\n  }\n\n  when(matches: Matches, context: Record<string, unknown>): Match[] {\n    const toAppend: Match[] = [];\n\n    for (const match of matches.named('screen_size')) {\n      if (!isDisabled(context, 'frame_rate')) {\n        for (const frameRate of match.children.named('frame_rate')) {\n          (frameRate as unknown as { formatter: (s: string) => string }).formatter = (s: string) => FrameRate.fromstring(s).toString();\n          toAppend.push(frameRate);\n        }\n      }\n\n      // Try to get height/width/scan_type from children (when children:true is set)\n      // or fall back to parsing the raw string directly.\n      let values = match.children.toDict() as unknown as Record<string, unknown>;\n      if (!('height' in values)) {\n        // Parse raw string. Handle these formats:\n        //   \"WxH\"  / \"WXH\"  → width W, height H (no scan type)\n        //   \"Hx\"   (pattern consumed trailing x but no second number) → height H only\n        //   \"Hp\"   / \"Hi\"   → height H, scan type p/i\n        //   \"H\"              → height H only (defaults to 'p')\n        const raw = String(match.raw ?? '');\n        // Full WxH form (both dimensions present), allow optional separators around x/*\n        const rxWxH = /^(\\d{3,4})\\s*[xX*×]\\s*(\\d{3,4})(?:up)?$/i;\n        const mWxH = rxWxH.exec(raw);\n        if (mWxH) {\n          values = { width: mWxH[1], height: mWxH[2], scan_type: undefined };\n        } else {\n          // Height-only or height+scan_type form (strip any trailing separator chars)\n          const rxH = /^(\\d{3,4})([ip])?/i;\n          const mH = rxH.exec(raw);\n          if (mH && mH[1]) {\n            values = { height: mH[1], scan_type: mH[2] };\n          } else {\n            continue;\n          }\n        }\n      }\n\n      const scanType = ((values['scan_type'] as string) || 'p').toLowerCase();\n      const height = String(values['height'] ?? '');\n\n      if (!('width' in values) || values['width'] === undefined) {\n        (match as unknown as { value: unknown }).value = `${height}${scanType}`;\n        continue;\n      }\n\n      const width = String(values['width'] ?? '');\n      const calculatedAr = parseFloat(width) / parseFloat(height);\n\n      if (this.standardHeights.has(height) && this.minAr < calculatedAr && calculatedAr < this.maxAr) {\n        (match as unknown as { value: unknown }).value = `${height}${scanType}`;\n      } else {\n        (match as unknown as { value: unknown }).value = `${width}x${height}`;\n      }\n\n      // Add aspect_ratio when width is present and within valid range\n      if (!isDisabled(context, 'aspect_ratio') && width && this.minAr < calculatedAr && calculatedAr < this.maxAr) {\n        const arMatch = new Match(match.start, match.end, {\n          name: 'aspect_ratio',\n          value: Math.round(calculatedAr * 1000) / 1000,\n          inputString: match.inputString,\n        });\n        toAppend.push(arMatch);\n      }\n    }\n\n    return toAppend;\n  }\n}\n\nclass ScreenSizeOnlyOne extends Rule {\n  static consequence = RemoveMatch;\n\n  when(matches: Matches, _context: Record<string, unknown>): Match[] {\n    const toRemove: Match[] = [];\n    for (const filepart of matches.markers.named('path')) {\n      const screenSizes = (matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'screen_size') as Match[]).reverse();\n      const uniqueValues = new Set(screenSizes.map((m: Match) => m.value));\n      if (screenSizes.length > 1 && uniqueValues.size > 1) {\n        toRemove.push(...screenSizes.slice(1));\n      }\n    }\n    return toRemove;\n  }\n}\n\nclass ResolveScreenSizeConflicts extends Rule {\n  static consequence = RemoveMatch;\n\n  when(matches: Matches, _context: Record<string, unknown>): Match[] {\n    const toRemove: Match[] = [];\n    for (const filepart of matches.markers.named('path')) {\n      const screenSizeMatch = matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'screen_size', 0) as Match | undefined;\n      if (!screenSizeMatch) continue;\n\n      const conflicts = (matches.conflicting(screenSizeMatch, (m: Match) => ['season', 'episode'].includes(m.name ?? '')) as Match[]) ?? [];\n      if (conflicts.length === 0) continue;\n\n      let hasNeighbor = false;\n\n      const allScreensizes = (matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'screen_size') as Match[]) ?? [];\n      const groupOf = (m: Match) =>\n        matches.markers.atMatch(m, (marker: Match) => marker.name === 'group', 0);\n      const following = matches.range(screenSizeMatch.end, filepart.end,\n        (m: Match) => m.name === 'video_profile' || m.name === 'video_codec', 0) as Match | undefined;\n      if (following && (matches.holes(screenSizeMatch.end, following.start, { predicate: (h: Match) => !!(h.value && String(h.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')) }) as Match[]).length === 0) {\n        // A video_codec marks the number as a resolution (\"1080.x264\" → 1080p) only when both\n        // sit in the same tag block and the part spells no other resolution (#933).\n        if (following.name === 'video_profile' ||\n            (allScreensizes.length === 1 && groupOf(screenSizeMatch) === groupOf(following))) {\n          toRemove.push(...conflicts);\n          hasNeighbor = true;\n        }\n      }\n\n      const previous = matches.previous(screenSizeMatch, (m: Match) =>\n        ['date', 'source', 'other', 'streaming_service'].includes(m.name ?? ''), 0) as Match | undefined;\n      if (previous && (matches.holes(previous.end, screenSizeMatch.start, { predicate: (h: Match) => !!(h.value && String(h.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')) }) as Match[]).length === 0) {\n        toRemove.push(...conflicts);\n        hasNeighbor = true;\n      }\n\n      if (!hasNeighbor) {\n        toRemove.push(screenSizeMatch);\n      }\n    }\n    return toRemove;\n  }\n}\n","// IANA TLD list (tlds-alpha-by-domain.txt), same data file Python guessit ships.\n// xn-- internationalized TLDs excluded, matching upstream parsing.\nexport const TLDS: string[] = [\"aarp\",\"abb\",\"abbott\",\"abbvie\",\"abc\",\"able\",\"abogado\",\"abudhabi\",\"ac\",\"academy\",\"accenture\",\"accountant\",\"accountants\",\"aco\",\"actor\",\"ad\",\"ads\",\"adult\",\"ae\",\"aeg\",\"aero\",\"aetna\",\"af\",\"afl\",\"africa\",\"ag\",\"agakhan\",\"agency\",\"ai\",\"aig\",\"airbus\",\"airforce\",\"airtel\",\"akdn\",\"al\",\"alibaba\",\"alipay\",\"allfinanz\",\"allstate\",\"ally\",\"alsace\",\"alstom\",\"am\",\"amazon\",\"americanexpress\",\"americanfamily\",\"amex\",\"amfam\",\"amica\",\"amsterdam\",\"analytics\",\"android\",\"anquan\",\"anz\",\"ao\",\"aol\",\"apartments\",\"app\",\"apple\",\"aq\",\"aquarelle\",\"ar\",\"arab\",\"aramco\",\"archi\",\"army\",\"arpa\",\"art\",\"arte\",\"as\",\"asda\",\"asia\",\"associates\",\"at\",\"athleta\",\"attorney\",\"au\",\"auction\",\"audi\",\"audible\",\"audio\",\"auspost\",\"author\",\"auto\",\"autos\",\"aw\",\"aws\",\"ax\",\"axa\",\"az\",\"azure\",\"ba\",\"baby\",\"baidu\",\"banamex\",\"band\",\"bank\",\"bar\",\"barcelona\",\"barclaycard\",\"barclays\",\"barefoot\",\"bargains\",\"baseball\",\"basketball\",\"bauhaus\",\"bayern\",\"bb\",\"bbc\",\"bbt\",\"bbva\",\"bcg\",\"bcn\",\"bd\",\"be\",\"beats\",\"beauty\",\"beer\",\"berlin\",\"best\",\"bestbuy\",\"bet\",\"bf\",\"bg\",\"bh\",\"bharti\",\"bi\",\"bible\",\"bid\",\"bike\",\"bing\",\"bingo\",\"bio\",\"biz\",\"bj\",\"black\",\"blackfriday\",\"blockbuster\",\"blog\",\"bloomberg\",\"blue\",\"bm\",\"bms\",\"bmw\",\"bn\",\"bnpparibas\",\"bo\",\"boats\",\"boehringer\",\"bofa\",\"bom\",\"bond\",\"boo\",\"book\",\"booking\",\"bosch\",\"bostik\",\"boston\",\"bot\",\"boutique\",\"box\",\"br\",\"bradesco\",\"bridgestone\",\"broadway\",\"broker\",\"brother\",\"brussels\",\"bs\",\"bt\",\"build\",\"builders\",\"business\",\"buy\",\"buzz\",\"bv\",\"bw\",\"by\",\"bz\",\"bzh\",\"ca\",\"cab\",\"cafe\",\"cal\",\"call\",\"calvinklein\",\"cam\",\"camera\",\"camp\",\"canon\",\"capetown\",\"capital\",\"capitalone\",\"car\",\"caravan\",\"cards\",\"care\",\"career\",\"careers\",\"cars\",\"casa\",\"case\",\"cash\",\"casino\",\"cat\",\"catering\",\"catholic\",\"cba\",\"cbn\",\"cbre\",\"cc\",\"cd\",\"center\",\"ceo\",\"cern\",\"cf\",\"cfa\",\"cfd\",\"cg\",\"ch\",\"chanel\",\"channel\",\"charity\",\"chase\",\"chat\",\"cheap\",\"chintai\",\"christmas\",\"chrome\",\"church\",\"ci\",\"cipriani\",\"circle\",\"cisco\",\"citadel\",\"citi\",\"citic\",\"city\",\"ck\",\"cl\",\"claims\",\"cleaning\",\"click\",\"clinic\",\"clinique\",\"clothing\",\"cloud\",\"club\",\"clubmed\",\"cm\",\"cn\",\"co\",\"coach\",\"codes\",\"coffee\",\"college\",\"cologne\",\"com\",\"commbank\",\"community\",\"company\",\"compare\",\"computer\",\"comsec\",\"condos\",\"construction\",\"consulting\",\"contact\",\"contractors\",\"cooking\",\"cool\",\"coop\",\"corsica\",\"country\",\"coupon\",\"coupons\",\"courses\",\"cpa\",\"cr\",\"credit\",\"creditcard\",\"creditunion\",\"cricket\",\"crown\",\"crs\",\"cruise\",\"cruises\",\"cu\",\"cuisinella\",\"cv\",\"cw\",\"cx\",\"cy\",\"cymru\",\"cyou\",\"cz\",\"dad\",\"dance\",\"data\",\"date\",\"dating\",\"datsun\",\"day\",\"dclk\",\"dds\",\"de\",\"deal\",\"dealer\",\"deals\",\"degree\",\"delivery\",\"dell\",\"deloitte\",\"delta\",\"democrat\",\"dental\",\"dentist\",\"desi\",\"design\",\"dev\",\"dhl\",\"diamonds\",\"diet\",\"digital\",\"direct\",\"directory\",\"discount\",\"discover\",\"dish\",\"diy\",\"dj\",\"dk\",\"dm\",\"dnp\",\"do\",\"docs\",\"doctor\",\"dog\",\"domains\",\"dot\",\"download\",\"drive\",\"dtv\",\"dubai\",\"dupont\",\"durban\",\"dvag\",\"dvr\",\"dz\",\"earth\",\"eat\",\"ec\",\"eco\",\"edeka\",\"edu\",\"education\",\"ee\",\"eg\",\"email\",\"emerck\",\"energy\",\"engineer\",\"engineering\",\"enterprises\",\"epson\",\"equipment\",\"er\",\"ericsson\",\"erni\",\"es\",\"esq\",\"estate\",\"et\",\"eu\",\"eurovision\",\"eus\",\"events\",\"exchange\",\"expert\",\"exposed\",\"express\",\"extraspace\",\"fage\",\"fail\",\"fairwinds\",\"faith\",\"family\",\"fan\",\"fans\",\"farm\",\"farmers\",\"fashion\",\"fast\",\"fedex\",\"feedback\",\"ferrari\",\"ferrero\",\"fi\",\"fidelity\",\"fido\",\"film\",\"final\",\"finance\",\"financial\",\"fire\",\"firestone\",\"firmdale\",\"fish\",\"fishing\",\"fit\",\"fitness\",\"fj\",\"fk\",\"flickr\",\"flights\",\"flir\",\"florist\",\"flowers\",\"fly\",\"fm\",\"fo\",\"foo\",\"food\",\"football\",\"ford\",\"forex\",\"forsale\",\"forum\",\"foundation\",\"fox\",\"fr\",\"free\",\"fresenius\",\"frl\",\"frogans\",\"frontier\",\"ftr\",\"fujitsu\",\"fun\",\"fund\",\"furniture\",\"futbol\",\"fyi\",\"ga\",\"gal\",\"gallery\",\"gallo\",\"gallup\",\"game\",\"games\",\"gap\",\"garden\",\"gay\",\"gb\",\"gbiz\",\"gd\",\"gdn\",\"ge\",\"gea\",\"gent\",\"genting\",\"george\",\"gf\",\"gg\",\"ggee\",\"gh\",\"gi\",\"gift\",\"gifts\",\"gives\",\"giving\",\"gl\",\"glass\",\"gle\",\"global\",\"globo\",\"gm\",\"gmail\",\"gmbh\",\"gmo\",\"gmx\",\"gn\",\"godaddy\",\"gold\",\"goldpoint\",\"golf\",\"goodyear\",\"goog\",\"google\",\"gop\",\"got\",\"gov\",\"gp\",\"gq\",\"gr\",\"grainger\",\"graphics\",\"gratis\",\"green\",\"gripe\",\"grocery\",\"group\",\"gs\",\"gt\",\"gu\",\"gucci\",\"guge\",\"guide\",\"guitars\",\"guru\",\"gw\",\"gy\",\"hair\",\"hamburg\",\"hangout\",\"haus\",\"hbo\",\"hdfc\",\"hdfcbank\",\"health\",\"healthcare\",\"help\",\"helsinki\",\"here\",\"hermes\",\"hiphop\",\"hisamitsu\",\"hitachi\",\"hiv\",\"hk\",\"hkt\",\"hm\",\"hn\",\"hockey\",\"holdings\",\"holiday\",\"homedepot\",\"homegoods\",\"homes\",\"homesense\",\"honda\",\"horse\",\"hospital\",\"host\",\"hosting\",\"hot\",\"hotels\",\"hotmail\",\"house\",\"how\",\"hr\",\"hsbc\",\"ht\",\"hu\",\"hughes\",\"hyatt\",\"hyundai\",\"ibm\",\"icbc\",\"ice\",\"icu\",\"id\",\"ie\",\"ieee\",\"ifm\",\"ikano\",\"il\",\"im\",\"imamat\",\"imdb\",\"immo\",\"immobilien\",\"in\",\"inc\",\"industries\",\"infiniti\",\"info\",\"ing\",\"ink\",\"institute\",\"insurance\",\"insure\",\"int\",\"international\",\"intuit\",\"investments\",\"io\",\"ipiranga\",\"iq\",\"ir\",\"irish\",\"is\",\"ismaili\",\"ist\",\"istanbul\",\"it\",\"itau\",\"itv\",\"jaguar\",\"java\",\"jcb\",\"je\",\"jeep\",\"jetzt\",\"jewelry\",\"jio\",\"jll\",\"jm\",\"jmp\",\"jnj\",\"jo\",\"jobs\",\"joburg\",\"jot\",\"joy\",\"jp\",\"jpmorgan\",\"jprs\",\"juegos\",\"juniper\",\"kaufen\",\"kddi\",\"ke\",\"kerryhotels\",\"kerryproperties\",\"kfh\",\"kg\",\"kh\",\"ki\",\"kia\",\"kids\",\"kim\",\"kindle\",\"kitchen\",\"kiwi\",\"km\",\"kn\",\"koeln\",\"komatsu\",\"kosher\",\"kp\",\"kpmg\",\"kpn\",\"kr\",\"krd\",\"kred\",\"kuokgroup\",\"kw\",\"ky\",\"kyoto\",\"kz\",\"la\",\"lacaixa\",\"lamborghini\",\"lamer\",\"land\",\"landrover\",\"lanxess\",\"lasalle\",\"lat\",\"latino\",\"latrobe\",\"law\",\"lawyer\",\"lb\",\"lc\",\"lds\",\"lease\",\"leclerc\",\"lefrak\",\"legal\",\"lego\",\"lexus\",\"lgbt\",\"li\",\"lidl\",\"life\",\"lifeinsurance\",\"lifestyle\",\"lighting\",\"like\",\"lilly\",\"limited\",\"limo\",\"lincoln\",\"link\",\"live\",\"living\",\"lk\",\"llc\",\"llp\",\"loan\",\"loans\",\"locker\",\"locus\",\"lol\",\"london\",\"lotte\",\"lotto\",\"love\",\"lpl\",\"lplfinancial\",\"lr\",\"ls\",\"lt\",\"ltd\",\"ltda\",\"lu\",\"lundbeck\",\"luxe\",\"luxury\",\"lv\",\"ly\",\"ma\",\"madrid\",\"maif\",\"maison\",\"makeup\",\"man\",\"management\",\"mango\",\"map\",\"market\",\"marketing\",\"markets\",\"marriott\",\"marshalls\",\"mattel\",\"mba\",\"mc\",\"mckinsey\",\"md\",\"me\",\"med\",\"media\",\"meet\",\"melbourne\",\"meme\",\"memorial\",\"men\",\"menu\",\"merck\",\"merckmsd\",\"mg\",\"mh\",\"miami\",\"microsoft\",\"mil\",\"mini\",\"mint\",\"mit\",\"mitsubishi\",\"mk\",\"ml\",\"mlb\",\"mls\",\"mm\",\"mma\",\"mn\",\"mo\",\"mobi\",\"mobile\",\"moda\",\"moe\",\"moi\",\"mom\",\"monash\",\"money\",\"monster\",\"mormon\",\"mortgage\",\"moscow\",\"moto\",\"motorcycles\",\"mov\",\"movie\",\"mp\",\"mq\",\"mr\",\"ms\",\"msd\",\"mt\",\"mtn\",\"mtr\",\"mu\",\"museum\",\"music\",\"mv\",\"mw\",\"mx\",\"my\",\"mz\",\"na\",\"nab\",\"nagoya\",\"name\",\"navy\",\"nba\",\"nc\",\"ne\",\"nec\",\"net\",\"netbank\",\"netflix\",\"network\",\"neustar\",\"new\",\"news\",\"next\",\"nextdirect\",\"nexus\",\"nf\",\"nfl\",\"ng\",\"ngo\",\"nhk\",\"ni\",\"nico\",\"nike\",\"nikon\",\"ninja\",\"nissan\",\"nissay\",\"nl\",\"no\",\"nokia\",\"norton\",\"now\",\"nowruz\",\"nowtv\",\"np\",\"nr\",\"nra\",\"nrw\",\"ntt\",\"nu\",\"nyc\",\"nz\",\"obi\",\"observer\",\"office\",\"okinawa\",\"olayan\",\"olayangroup\",\"ollo\",\"om\",\"omega\",\"one\",\"ong\",\"onl\",\"online\",\"ooo\",\"open\",\"oracle\",\"orange\",\"org\",\"organic\",\"origins\",\"osaka\",\"otsuka\",\"ott\",\"ovh\",\"pa\",\"page\",\"panasonic\",\"paris\",\"pars\",\"partners\",\"parts\",\"party\",\"pay\",\"pccw\",\"pe\",\"pet\",\"pf\",\"pfizer\",\"pg\",\"ph\",\"pharmacy\",\"phd\",\"philips\",\"phone\",\"photo\",\"photography\",\"photos\",\"physio\",\"pics\",\"pictet\",\"pictures\",\"pid\",\"pin\",\"ping\",\"pink\",\"pioneer\",\"pizza\",\"pk\",\"pl\",\"place\",\"play\",\"playstation\",\"plumbing\",\"plus\",\"pm\",\"pn\",\"pnc\",\"pohl\",\"poker\",\"politie\",\"porn\",\"post\",\"pr\",\"praxi\",\"press\",\"prime\",\"pro\",\"prod\",\"productions\",\"prof\",\"progressive\",\"promo\",\"properties\",\"property\",\"protection\",\"pru\",\"prudential\",\"ps\",\"pt\",\"pub\",\"pw\",\"pwc\",\"py\",\"qa\",\"qpon\",\"quebec\",\"quest\",\"racing\",\"radio\",\"re\",\"read\",\"realestate\",\"realtor\",\"realty\",\"recipes\",\"red\",\"redumbrella\",\"rehab\",\"reise\",\"reisen\",\"reit\",\"reliance\",\"ren\",\"rent\",\"rentals\",\"repair\",\"report\",\"republican\",\"rest\",\"restaurant\",\"review\",\"reviews\",\"rexroth\",\"rich\",\"richardli\",\"ricoh\",\"ril\",\"rio\",\"rip\",\"ro\",\"rocks\",\"rodeo\",\"rogers\",\"room\",\"rs\",\"rsvp\",\"ru\",\"rugby\",\"ruhr\",\"run\",\"rw\",\"rwe\",\"ryukyu\",\"sa\",\"saarland\",\"safe\",\"safety\",\"sakura\",\"sale\",\"salon\",\"samsclub\",\"samsung\",\"sandvik\",\"sandvikcoromant\",\"sanofi\",\"sap\",\"sarl\",\"sas\",\"save\",\"saxo\",\"sb\",\"sbi\",\"sbs\",\"sc\",\"scb\",\"schaeffler\",\"schmidt\",\"scholarships\",\"school\",\"schule\",\"schwarz\",\"science\",\"scot\",\"sd\",\"se\",\"search\",\"seat\",\"secure\",\"security\",\"seek\",\"select\",\"sener\",\"services\",\"seven\",\"sew\",\"sex\",\"sexy\",\"sfr\",\"sg\",\"sh\",\"shangrila\",\"sharp\",\"shell\",\"shia\",\"shiksha\",\"shoes\",\"shop\",\"shopping\",\"shouji\",\"show\",\"si\",\"silk\",\"sina\",\"singles\",\"site\",\"sj\",\"sk\",\"ski\",\"skin\",\"sky\",\"skype\",\"sl\",\"sling\",\"sm\",\"smart\",\"smile\",\"sn\",\"sncf\",\"so\",\"soccer\",\"social\",\"softbank\",\"software\",\"sohu\",\"solar\",\"solutions\",\"song\",\"sony\",\"soy\",\"spa\",\"space\",\"sport\",\"spot\",\"sr\",\"srl\",\"ss\",\"st\",\"stada\",\"staples\",\"star\",\"statebank\",\"statefarm\",\"stc\",\"stcgroup\",\"stockholm\",\"storage\",\"store\",\"stream\",\"studio\",\"study\",\"style\",\"su\",\"sucks\",\"supplies\",\"supply\",\"support\",\"surf\",\"surgery\",\"suzuki\",\"sv\",\"swatch\",\"swiss\",\"sx\",\"sy\",\"sydney\",\"systems\",\"sz\",\"tab\",\"taipei\",\"talk\",\"taobao\",\"target\",\"tatamotors\",\"tatar\",\"tattoo\",\"tax\",\"taxi\",\"tc\",\"tci\",\"td\",\"tdk\",\"team\",\"tech\",\"technology\",\"tel\",\"temasek\",\"tennis\",\"teva\",\"tf\",\"tg\",\"th\",\"thd\",\"theater\",\"theatre\",\"tiaa\",\"tickets\",\"tienda\",\"tips\",\"tires\",\"tirol\",\"tj\",\"tjmaxx\",\"tjx\",\"tk\",\"tkmaxx\",\"tl\",\"tm\",\"tmall\",\"tn\",\"to\",\"today\",\"tokyo\",\"tools\",\"top\",\"toray\",\"toshiba\",\"total\",\"tours\",\"town\",\"toyota\",\"toys\",\"tr\",\"trade\",\"trading\",\"training\",\"travel\",\"travelers\",\"travelersinsurance\",\"trust\",\"trv\",\"tt\",\"tube\",\"tui\",\"tunes\",\"tushu\",\"tv\",\"tvs\",\"tw\",\"tz\",\"ua\",\"ubank\",\"ubs\",\"ug\",\"uk\",\"unicom\",\"university\",\"uno\",\"uol\",\"ups\",\"us\",\"uy\",\"uz\",\"va\",\"vacations\",\"vana\",\"vanguard\",\"vc\",\"ve\",\"vegas\",\"ventures\",\"verisign\",\"versicherung\",\"vet\",\"vg\",\"vi\",\"viajes\",\"video\",\"vig\",\"viking\",\"villas\",\"vin\",\"vip\",\"virgin\",\"visa\",\"vision\",\"viva\",\"vivo\",\"vlaanderen\",\"vn\",\"vodka\",\"volvo\",\"vote\",\"voting\",\"voto\",\"voyage\",\"vu\",\"wales\",\"walmart\",\"walter\",\"wang\",\"wanggou\",\"watch\",\"watches\",\"weather\",\"weatherchannel\",\"webcam\",\"weber\",\"website\",\"wed\",\"wedding\",\"weibo\",\"weir\",\"wf\",\"whoswho\",\"wien\",\"wiki\",\"williamhill\",\"win\",\"windows\",\"wine\",\"winners\",\"wme\",\"woodside\",\"work\",\"works\",\"world\",\"wow\",\"ws\",\"wtc\",\"wtf\",\"xbox\",\"xerox\",\"xihuan\",\"xin\",\"xxx\",\"xyz\",\"yachts\",\"yahoo\",\"yamaxun\",\"yandex\",\"ye\",\"yodobashi\",\"yoga\",\"yokohama\",\"you\",\"youtube\",\"yt\",\"yun\",\"za\",\"zappos\",\"zara\",\"zero\",\"zip\",\"zm\",\"zone\",\"zuerich\",\"zw\"];\n","import { Rebulk } from 'rebulk-js';\nimport { Rule, RemoveMatch } from 'rebulk-js';\nimport type { Match } from 'rebulk-js';\nimport { seps } from '../common/index.js';\nimport { cleanup } from '../common/formatters.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { buildOrPattern } from '../../reutils.js';\n\nimport { TLDS as DEFAULT_TLDS } from '../../data/tlds.js';\n\nexport function website(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'website') });\n  rebulk.regexDefaults({ flags: 'i' }).stringDefaults({ ignoreCase: true });\n  rebulk.defaults({ name: 'website' });\n\n  const tlds = (config['tlds'] as string[]) || DEFAULT_TLDS;\n  const safeTlds = (config['safe_tlds'] as string[]) || ['com', 'org', 'net'];\n  const safeSubdomains = (config['safe_subdomains'] as string[]) || ['www'];\n  const safePrefix = (config['safe_prefixes'] as string[]) || [];\n  const websitePrefixes = (config['prefixes'] as string[]) || [];\n\n  rebulk.regex(\n    `(?:[^a-z0-9]|^)((?:${buildOrPattern(safeSubdomains)}\\\\.)+(?:[a-z-0-9-]+\\\\.)+(?:${buildOrPattern(tlds)}))(?:[^a-z0-9]|$)`,\n    { children: true }\n  );\n  rebulk.regex(\n    `(?:[^a-z0-9]|^)((?:${buildOrPattern(safeSubdomains)}\\\\.)*[a-z0-9-]+\\\\.(?:${buildOrPattern(safeTlds)}))(?:[^a-z0-9]|$)`,\n    { children: true }\n  );\n  rebulk.regex(\n    `(?:[^a-z0-9]|^)((?:${buildOrPattern(safeSubdomains)}\\\\.)*[a-z0-9-]+\\\\.(?:${buildOrPattern(safePrefix)}\\\\.)+(?:${buildOrPattern(tlds)}))(?:[^a-z0-9]|$)`,\n    { children: true }\n  );\n\n  rebulk.string(...websitePrefixes, {\n    validator: sepsSurround,\n    private: true,\n    tags: ['website.prefix'],\n  });\n\n  // Pass safeSubdomains and safePrefix from config to the rule via closure\n  class PreferTitleOverWebsiteWithConfig extends Rule {\n    override consequence = RemoveMatch;\n    private safeSubdomains: string[];\n    private safePrefix: string[];\n\n    constructor(safeSubdomainsArg: string[], safePrefixArg: string[]) {\n      super();\n      this.safeSubdomains = safeSubdomainsArg;\n      this.safePrefix = safePrefixArg;\n    }\n\n    validFollowers(match: Match): boolean {\n      return ['season', 'episode', 'year'].includes(match.name ?? '');\n    }\n\n    override when(matches: any) {\n      const toRemove = [];\n      for (const websiteMatch of matches.named('website')) {\n        let safe = false;\n        for (const safeStart of [...this.safeSubdomains, ...this.safePrefix]) {\n          if (String(websiteMatch.value ?? '').toLowerCase().startsWith(safeStart)) {\n            safe = true;\n            break;\n          }\n        }\n        if (!safe) {\n          // Work around rebulk-js next() bug: use range() to find followers\n          const filepart = matches.markers.atMatch(websiteMatch, (m: Match) => m.name === 'path', 0);\n          const searchEnd = filepart?.end ?? (matches.inputString?.length ?? websiteMatch.end + 50);\n          const followers = matches.range(websiteMatch.end, searchEnd,\n            (m: Match) => !m.private && this.validFollowers(m)) as Match[];\n          const followerArr = Array.isArray(followers) ? followers : followers ? [followers] : [];\n          const suffix = followerArr.length > 0 ? followerArr[0] : undefined;\n          if (suffix) {\n            const group = matches.markers.atMatch(\n              websiteMatch,\n              (m: Match) => m.name === 'group',\n              0\n            );\n            if (!group) {\n              toRemove.push(websiteMatch);\n            }\n          }\n        }\n      }\n      return toRemove;\n    }\n  }\n\n  rebulk.rules(new PreferTitleOverWebsiteWithConfig(safeSubdomains, safePrefix), ValidateWebsitePrefix);\n\n  return rebulk;\n}\n\nclass ValidateWebsitePrefix extends Rule {\n  static priority = 64;\n  static consequence = RemoveMatch;\n\n  when(matches: any) {\n    const toRemove = [];\n    for (const prefix of matches.tagged('website.prefix')) {\n      // Work around rebulk-js next() bug: use range() instead\n      const websites = matches.range(prefix.end, prefix.end + 100,\n        (m: Match) => !m.private && m.name === 'website') as Match[];\n      const webArr = Array.isArray(websites) ? websites : websites ? [websites] : [];\n      const websiteMatch = webArr.length > 0 ? webArr[0] : undefined;\n      if (\n        !websiteMatch ||\n        matches.holes(prefix.end, websiteMatch.start, cleanup, seps, (m: Match) => m.value)\n      ) {\n        toRemove.push(prefix);\n      }\n    }\n    return toRemove;\n  }\n}\n","/**\n * Date utilities — port of guessit/rules/common/date.py\n */\n\nconst DSEP = '[-/ .]';\nconst DSEP_BIS = '[-/ .x]';\n\nconst DATE_REGEXPS: RegExp[] = [\n  new RegExp(`${DSEP}((\\\\d{8}))${DSEP}`, 'i'),\n  new RegExp(`${DSEP}((\\\\d{6}))${DSEP}`, 'i'),\n  new RegExp(`(?:^|[^\\\\d])((\\\\d{2})${DSEP}(\\\\d{1,2})${DSEP}(\\\\d{1,2}))(?:$|[^\\\\d])`, 'i'),\n  new RegExp(`(?:^|[^\\\\d])((\\\\d{1,2})${DSEP}(\\\\d{1,2})${DSEP}(\\\\d{2}))(?:$|[^\\\\d])`, 'i'),\n  new RegExp(`(?:^|[^\\\\d])((\\\\d{4})${DSEP_BIS}(\\\\d{1,2})${DSEP}(\\\\d{1,2}))(?:$|[^\\\\d])`, 'i'),\n  new RegExp(`(?:^|[^\\\\d])((\\\\d{1,2})${DSEP}(\\\\d{1,2})${DSEP_BIS}(\\\\d{4}))(?:$|[^\\\\d])`, 'i'),\n  new RegExp(`(?:^|[^\\\\d])((\\\\d{1,2}(?:st|nd|rd|th)?${DSEP}(?:[a-z]{3,10})${DSEP}\\\\d{4}))(?:$|[^\\\\d])`, 'i'),\n  // Month-name first: \"July 30 2021\", \"Jul.30.2021\"\n  new RegExp(`(?:^|[^a-z\\\\d])(([a-z]{3,10})${DSEP}\\\\d{1,2}(?:st|nd|rd|th)?${DSEP}\\\\d{4})(?:$|[^\\\\d])`, 'i'),\n];\n\nconst MONTHS: Record<string, number> = {\n  jan: 1, january: 1, feb: 2, february: 2, mar: 3, march: 3, apr: 4, april: 4,\n  may: 5, jun: 6, june: 6, jul: 7, july: 7, aug: 8, august: 8, sep: 9, sept: 9,\n  september: 9, oct: 10, october: 10, nov: 11, november: 11, dec: 12, december: 12,\n};\n\nexport function validYear(year: number): boolean {\n  return year >= 1900 && year < 2035;\n}\n\nexport function validWeek(week: number): boolean {\n  return week >= 1 && week < 53;\n}\n\nfunction isInt(s: string): boolean {\n  return !isNaN(parseInt(s, 10)) && String(parseInt(s, 10)) === s.replace(/^0+/, '') || s === '0';\n}\n\nfunction guessDayFirst(groups: string[]): boolean | undefined {\n  const first = groups[0];\n  const last = groups[groups.length - 1];\n  if (isInt(first) && validYear(parseInt(first.slice(0, 4), 10))) return false;\n  if (isInt(last) && validYear(parseInt(last.slice(-4), 10))) return true;\n  if (isInt(first) && parseInt(first.slice(0, 2), 10) > 31) return false;\n  if (isInt(last) && parseInt(last.slice(-2), 10) > 31) return true;\n  return undefined;\n}\n\nfunction tryParseDate(\n  match: string,\n  groups: string[],\n  yearFirst?: boolean,\n  dayFirst?: boolean,\n): Date | undefined {\n  // Normalize the match string: replace separators with '-'\n  const normalized = match.replace(/[-/ .x]/g, '-');\n  const parts = normalized.split('-').filter(Boolean);\n\n  const yearFirstOpts = yearFirst !== undefined ? [yearFirst] : [false, true];\n  const dayFirstOpts = dayFirst !== undefined ? [dayFirst] : [true, false];\n\n  for (const yf of yearFirstOpts) {\n    for (const df of dayFirstOpts) {\n      let year: number, month: number, day: number;\n\n      // Month-name dates: one part is a month name (e.g. \"July\"/\"Jul\"), the\n      // 4-digit part is the year, the remaining part is the day. Handles both\n      // \"30 July 2021\" and \"July 30 2021\".\n      const monthNameIdx = parts.findIndex((x) => MONTHS[x.toLowerCase()] !== undefined);\n      if (parts.length === 3 && monthNameIdx >= 0) {\n        month = MONTHS[parts[monthNameIdx].toLowerCase()];\n        const rest = parts\n          .filter((_, i) => i !== monthNameIdx)\n          .map((x) => parseInt(x.replace(/(st|nd|rd|th)$/i, ''), 10));\n        const yearPos = rest.findIndex((n) => n >= 1000);\n        if (yearPos >= 0) { year = rest[yearPos]; day = rest[1 - yearPos]; }\n        else { year = rest[1]; day = rest[0]; }\n        if (month >= 1 && month <= 12 && day >= 1 && day <= 31 && validYear(year)) {\n          const ts = Date.UTC(year, month - 1, day);\n          const d = new Date(ts);\n          if (d.getUTCFullYear() === year && d.getUTCMonth() === month - 1 && d.getUTCDate() === day) {\n            return d;\n          }\n        }\n        continue;\n      }\n\n      if (parts.length === 1) {\n        // yyyymmdd or yymmdd\n        const s = parts[0];\n        if (s.length === 8) {\n          year = parseInt(s.slice(0, 4), 10);\n          month = parseInt(s.slice(4, 6), 10);\n          day = parseInt(s.slice(6, 8), 10);\n        } else if (s.length === 6) {\n          // yymmdd\n          const yy = parseInt(s.slice(0, 2), 10);\n          year = yy > 50 ? 1900 + yy : 2000 + yy;\n          month = parseInt(s.slice(2, 4), 10);\n          day = parseInt(s.slice(4, 6), 10);\n        } else {\n          continue;\n        }\n      } else if (parts.length === 3) {\n        const p = parts.map(Number);\n        if (yf) {\n          [year, month, day] = df ? [p[0], p[2], p[1]] : [p[0], p[1], p[2]];\n          // Convert 2-digit year\n          if (!validYear(year) && year < 100) {\n            year = year > 50 ? 1900 + year : 2000 + year;\n          }\n        } else {\n          // year is the 4-digit one, or the last part\n          const longIdx = p.findIndex((n, i) => parts[i].length === 4 && validYear(n));\n          if (longIdx === 0) {\n            [year, month, day] = df ? [p[0], p[2], p[1]] : [p[0], p[1], p[2]];\n          } else if (longIdx === 2) {\n            [year, month, day] = df ? [p[2], p[1], p[0]] : [p[2], p[0], p[1]];\n          } else {\n            // 2-digit year\n            if (df) {\n              [day, month, year] = yf ? [p[2], p[1], p[0]] : [p[0], p[1], p[2]];\n            } else {\n              [month, day, year] = yf ? [p[2], p[0], p[1]] : [p[0], p[1], p[2]];\n            }\n            const yy = year > 100 ? year : (year > 50 ? 1900 + year : 2000 + year);\n            year = yy;\n          }\n        }\n      } else {\n        continue;\n      }\n\n      if (month < 1 || month > 12) continue;\n      if (day < 1 || day > 31) continue;\n      if (!validYear(year)) continue;\n\n      try {\n        // Use UTC to avoid local-timezone offsets shifting the date when serialized to ISO string.\n        const ts = Date.UTC(year, month - 1, day);\n        const date = new Date(ts);\n        if (date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day) {\n          return date;\n        }\n      } catch {\n        // invalid date\n      }\n    }\n  }\n  return undefined;\n}\n\nexport function searchDate(\n  string: string,\n  yearFirst?: boolean,\n  dayFirst?: boolean,\n): [number, number, Date] | undefined {\n  for (const dateRe of DATE_REGEXPS) {\n    const globalRe = new RegExp(dateRe.source, dateRe.flags.includes('g') ? dateRe.flags : dateRe.flags + 'g');\n    let m: RegExpExecArray | null;\n    globalRe.lastIndex = 0;\n    while ((m = globalRe.exec(string)) !== null) {\n      if (!m[1]) continue;\n      const start = m.index + m[0].indexOf(m[1]);\n      const end = start + m[1].length;\n      const groups = m.slice(2).filter(Boolean);\n      const matchStr = m[1];\n\n      // \"Jackass.2.5.2007\" is sequel 2.5 released in 2007, not 2 May 2007\n      // (upstream #963). Release names zero-pad genuine broadcast dates\n      // (\"10.11.2008\"), so two unpadded single digits in front of a full year\n      // means decimal versioning — skip this candidate and keep scanning.\n      if (/^\\d\\.\\d\\.\\d{4}$/.test(matchStr)) continue;\n\n      let dfGuess = dayFirst;\n      if (yearFirst && dfGuess === undefined) dfGuess = false;\n      const dfGuessWasExplicit = dfGuess !== undefined;\n      if (!dfGuessWasExplicit && groups.length > 0) {\n        dfGuess = guessDayFirst(groups);\n      }\n\n      // Try guessed day-first setting first. If it fails (e.g., month > 12),\n      // fall back to the opposite setting so ambiguous dates like \"03-29-2012\"\n      // are correctly resolved even when the heuristic guesses wrong.\n      const dfOptions: Array<boolean | undefined> = dfGuess !== undefined\n        ? (dfGuessWasExplicit ? [dfGuess] : [dfGuess, !dfGuess])\n        : [undefined];\n\n      let date: Date | undefined;\n      for (const df of dfOptions) {\n        date = tryParseDate(matchStr, groups, yearFirst, df);\n        if (date && validYear(date.getUTCFullYear())) break;\n      }\n      if (date && validYear(date.getUTCFullYear())) {\n        return [start, end, date];\n      }\n    }\n  }\n  return undefined;\n}\n","/**\n * Date property — port of guessit/rules/properties/date.py\n */\nimport { Rebulk } from 'rebulk-js';\nimport { Rule, RemoveMatch } from 'rebulk-js';\nimport type { Match, Matches } from 'rebulk-js';\nimport type { Context } from 'rebulk-js';\nimport { dash, seps } from '../common/index.js';\nimport { searchDate, validYear, validWeek } from '../common/date.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { buildOrPattern } from '../../reutils.js';\n\n/**\n * Rule to keep only the marked year in the filepart (remove others).\n * Prioritizes grouped years over ungrouped.\n */\nclass KeepMarkedYearInFilepart extends Rule {\n  static override priority = 64;\n  override consequence = RemoveMatch;\n\n  override enabled(context: Context): boolean {\n    return !isDisabled(context, 'year');\n  }\n\n  override when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n    const yearMatches = matches.named('year') as Match[] | Match | undefined;\n    const yearArray = Array.isArray(yearMatches) ? yearMatches : yearMatches ? [yearMatches] : [];\n\n    if (yearArray.length <= 1) return ret;\n\n    // Get path markers\n    const pathMarkers = matches.markers.named('path') as Match[] | Match | undefined;\n    const pathArray = Array.isArray(pathMarkers) ? pathMarkers : pathMarkers ? [pathMarkers] : [];\n\n    for (const filepart of pathArray) {\n      const yearsInPart = matches.range(\n        filepart.start,\n        filepart.end,\n        (m) => m.name === 'year',\n      ) as Match[] | Match | undefined;\n      const yearsInPartArray = Array.isArray(yearsInPart) ? yearsInPart : yearsInPart ? [yearsInPart] : [];\n\n      if (yearsInPartArray.length <= 1) continue;\n\n      const groupYears: Match[] = [];\n      const ungroupYears: Match[] = [];\n\n      for (const year of yearsInPartArray) {\n        const groupMarker = matches.markers.atMatch(year, (m: Match) => m.name === 'group', 0) as Match | undefined;\n        if (groupMarker) {\n          groupYears.push(year);\n        } else {\n          ungroupYears.push(year);\n        }\n      }\n\n      if (groupYears.length > 0 && ungroupYears.length > 0) {\n        // Only remove ungrouped years that appear BEFORE the first grouped year\n        // (they are likely part of the title). Ungrouped years after the grouped year\n        // may be part of bonus_title or episode content.\n        const firstGroupStart = groupYears[0].start;\n        ret.push(...ungroupYears.filter((y: Match) => y.start < firstGroupStart));\n        ret.push(...groupYears.slice(1));\n      } else if (groupYears.length === 0) {\n        ret.push(ungroupYears[0]);\n        if (ungroupYears.length > 2) {\n          ret.push(...ungroupYears.slice(2));\n        }\n      }\n    }\n\n    return ret;\n  }\n}\n\n/**\n * Remove years inside group markers when a strong SxxExx episode pattern exists.\n * e.g. \"feud.s01e05.and.the.winner.is.(the.oscars.of.1963)\" — 1963 is episode content, not year.\n */\nclass RemoveGroupedYearWithSxxExx extends Rule {\n  static override priority = 64;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n    const hasSxxExx = (matches.named('episode') as Match[]).some(\n      (m: Match) => m.tags?.includes('SxxExx')\n    );\n    if (!hasSxxExx) return ret;\n\n    for (const year of (matches.named('year') as Match[])) {\n      const group = matches.markers.atMatch(year, (m: Match) => m.name === 'group', 0) as Match | undefined;\n      if (!group) continue;\n      // Only remove if the group contains significant non-year content\n      // e.g. \"(the.oscars.of.1963)\" has lots of text, but \"(2005)\" is just a year\n      const groupLen = group.end - group.start;\n      const yearLen = year.end - year.start;\n      if (groupLen - yearLen > 4) {\n        // Group has significant content beyond the year - it's episode title content\n        ret.push(year);\n      }\n    }\n    return ret;\n  }\n}\n\n/**\n * Drop a date that is really a fragment of a longer dotted numeric run in the\n * title (upstream #963): \"Evangelion.3.0.1.11\" matches \"0.1.11\" as 2000-11-01\n * while the \"3.\" in front of it belongs to the title. A digit claimed by another\n * property (the \"1\" of \"S01\" before a real \"2015.10.13\" stamp) does not count.\n *\n * The sibling shape — an unpadded \"D.M.YYYY\" like \"Jackass.2.5.2007\" — is\n * rejected earlier, inside searchDate, so the trailing \"2007\" still surfaces as\n * a year instead of being swallowed by the discarded date span.\n */\nclass RemoveDecimalVersionDate extends Rule {\n  static override priority = 128;\n  override consequence = RemoveMatch;\n\n  override enabled(context: Context): boolean {\n    return !isDisabled(context, 'date');\n  }\n\n  override when(matches: Matches, _context: Context): Match[] {\n    const input: string = matches.inputString ?? '';\n    const ret: Match[] = [];\n\n    for (const dateMatch of (matches.named('date') as Match[])) {\n      const prevChar = input[dateMatch.start - 1];\n      const prevDigit = input[dateMatch.start - 2];\n      if (prevChar && prevDigit && /[.\\-_/ ]/.test(prevChar) && /\\d/.test(prevDigit)) {\n        const claimed = matches.range(dateMatch.start - 2, dateMatch.start - 1,\n          (m: Match) => !m.private) as Match[];\n        if (!(Array.isArray(claimed) ? claimed.length : claimed ? 1 : 0)) {\n          ret.push(dateMatch);\n        }\n      }\n    }\n\n    return ret;\n  }\n}\n\n/**\n * Create a rebulk pattern for date detection.\n */\nexport function date(config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk().defaults({ validator: sepsSurround });\n\n  // Year regex\n  rebulk.regex('\\\\d{4}', {\n    name: 'year',\n    formatter: (s: string) => parseInt(s, 10),\n    disabled: (context: Context) => isDisabled(context, 'year'),\n    conflictSolver: (match, other) =>\n      other.name === 'episode' || other.name === 'season'\n        ? other.raw && match.raw && other.raw.length < match.raw.length\n          ? other\n          : '__default__'\n        : '__default__',\n    validator: (m: Match) => sepsSurround(m) && validYear(m.value as number),\n  });\n\n  // Week regex\n  const weekWords = config['week_words'] as string[] | undefined;\n  if (weekWords && weekWords.length > 0) {\n    const weekPattern = buildOrPattern(weekWords) + '-?(\\\\d{1,2})';\n    rebulk.regex(weekPattern, {\n      name: 'week',\n      formatter: (s: string) => parseInt(s.replace(/\\D/g, ''), 10),\n      children: true,\n      flags: 'i',\n      abbreviations: [dash],\n      conflictSolver: (match, other) =>\n        other.name === 'episode' || other.name === 'season'\n          ? other.raw && match.raw && other.raw.length < match.raw.length\n            ? other\n            : '__default__'\n          : '__default__',\n      validator: (m: Match) => sepsSurround(m) && validWeek(m.value as number),\n    });\n  }\n\n  // Date functional pattern\n  const dateFunctional = (inputString: string, context?: Context) => {\n    const result = searchDate(\n      inputString,\n      context?.['date_year_first'] as boolean | undefined,\n      context?.['date_day_first'] as boolean | undefined,\n    );\n    if (result) {\n      return [[result[0], result[1], { value: result[2] }]];\n    }\n    return [];\n  };\n\n  rebulk.functional(dateFunctional, {\n    name: 'date',\n    properties: { date: [null] },\n    disabled: (context: Context) => isDisabled(context, 'date'),\n    conflictSolver: (match, other) =>\n      other.name === 'episode' || other.name === 'season' || other.name === 'crc32'\n        ? other\n        : '__default__',\n  });\n\n  rebulk.rules(RemoveDecimalVersionDate, KeepMarkedYearInFilepart, RemoveGroupedYearWithSxxExx, new AbsorbWeekdayPrefix((config['weekday_words'] as string[]) ?? []));\n  return rebulk;\n}\n\n/**\n * Absorb a weekday word glued to a date into the date match (upstream #794).\n * \"…S2025E01.Thu.2.Jan.2025.Mar.Menor.Spain…\": \"Thu\" is the broadcast weekday, not\n * the title — growing the date span over it removes the bogus first title hole so\n * the real episode title after the date is reclaimed.\n */\nclass AbsorbWeekdayPrefix extends Rule {\n  override consequence = RemoveMatch;\n  private weekdayRe: RegExp;\n\n  constructor(weekdayWords: string[]) {\n    super();\n    const sepsClass = '[' + seps.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + ']';\n    this.weekdayRe = new RegExp(\n      '(?:^|' + sepsClass + ')(' + buildOrPattern(weekdayWords.length ? weekdayWords : ['\\\\bnever\\\\b']) + ')' + sepsClass + '*$',\n      'i',\n    );\n  }\n\n  enabled(context: any): boolean {\n    return !isDisabled(context, 'date');\n  }\n\n  when(matches: any, _context: any): any {\n    const input: string = matches.inputString ?? '';\n    const ret: Array<[any, number]> = [];\n    for (const dateMatch of matches.named('date') ?? []) {\n      const filepart = matches.markers.atMatch(dateMatch, (m: any) => m.name === 'path', 0);\n      const lower = filepart ? filepart.start : 0;\n      const segment = input.slice(lower, dateMatch.start);\n      const weekday = this.weekdayRe.exec(segment);\n      if (!weekday) continue;\n      const groupStart = lower + weekday.index + weekday[0].indexOf(weekday[1]);\n      const claimed = matches.range(groupStart, dateMatch.start, (m: any) => !m.private) as any[];\n      if ((Array.isArray(claimed) ? claimed.length : claimed ? 1 : 0) > 0) continue;\n      ret.push([dateMatch, groupStart]);\n    }\n    return ret.length ? ret : false;\n  }\n\n  override then(matches: any, whenResponse: any, _context: any): void {\n    for (const [dateMatch, newStart] of whenResponse as Array<[any, number]>) {\n      matches.remove(dateMatch);\n      dateMatch.start = newStart;\n      matches.append(dateMatch);\n    }\n  }\n}\n","/**\n * Comparators — port of guessit/rules/common/comparators.py\n */\nimport type { Match, Matches, _BaseMatches } from 'rebulk-js';\n\n/**\n * Predicate for marker comparator — excludes private, proper_count, title, extension containers, and Rip other.\n */\nexport function markerComparatorPredicate(m: Match): boolean {\n  return (\n    !m.private &&\n    m.name !== 'proper_count' &&\n    m.name !== 'title' &&\n    !(m.name === 'container' && m.tags?.includes('extension')) &&\n    !(m.name === 'other' && m.value === 'Rip')\n  );\n}\n\n/**\n * Compute weight of a marker: number of distinct match names inside it.\n */\nfunction markerWeight(matches: _BaseMatches, marker: Match, predicate: (m: Match) => boolean): number {\n  const rangeResult = (matches as Matches).range(marker.start, marker.end, predicate);\n  const arr: Match[] = Array.isArray(rangeResult) ? rangeResult : rangeResult ? [rangeResult as Match] : [];\n  const names = new Set(arr.map((m) => m.name));\n  return names.size;\n}\n\n/**\n * Sort markers from most valuable (most distinct match types) to least.\n * Ties broken by rightmost position (later in path = preferred).\n * Mirrors Python guessit's marker_sorted / marker_comparator.\n */\nexport function markerSorted(\n  markers: Iterable<Match>,\n  matches: _BaseMatches,\n  predicate: (m: Match) => boolean = markerComparatorPredicate,\n): Match[] {\n  const markersArr = [...markers];\n  // Snapshot input order — Python's comparator indexes the ORIGINAL list; calling\n  // indexOf on the array being sorted in place gives unstable garbage mid-sort.\n  const originalIndex = new Map<Match, number>(markersArr.map((m, i) => [m, i]));\n  return markersArr.sort((a, b) => {\n    const weightDiff = markerWeight(matches, b, predicate) - markerWeight(matches, a, predicate);\n    if (weightDiff !== 0) return weightDiff;\n    // Give preference to rightmost (higher index in the input array = later in path)\n    return (originalIndex.get(b) ?? 0) - (originalIndex.get(a) ?? 0);\n  });\n}\n","/**\n * Expected titles/groups — port of guessit/rules/common/expected.py\n */\nimport type { Context } from 'rebulk-js';\nimport type { MatchOptions } from 'rebulk-js';\n\n/**\n * Build a functional pattern function that finds expected titles/groups in the string.\n * Mirrors Python's build_expected_function('expected_title').\n */\nexport function buildExpectedFunction(optionName: string) {\n  return function findExpected(inputString: string, context?: Context): Array<[number, number, Partial<MatchOptions>]> {\n    let expected = context?.[optionName] as string | string[] | undefined;\n    if (!expected || (Array.isArray(expected) && expected.length === 0)) return [];\n    // Normalise to array — a single string from CLI options (-T \"title\") must be wrapped\n    if (typeof expected === 'string') expected = [expected];\n\n    // Separator characters that can appear between words in a filename\n    const SEP_CLASS = '[\\\\s._-]';\n\n    const results: Array<[number, number, Partial<MatchOptions>]> = [];\n    for (const title of expected) {\n      let pattern: RegExp;\n\n      // Support \"re:\" prefix for raw regex patterns (e.g. \"re:my \\\\d+p show\")\n      if (title.startsWith('re:')) {\n        // Python rewrites the space to a dash and compiles with the `dash`\n        // abbreviation, which expands every literal \"-\" to [\\W_]? — so a space\n        // in a re: pattern matches any filename separator, and \"re:Foo 2\" finds\n        // \"Foo.2\" (guessit/rules/common/expected.py, upstream #966).\n        const rawPattern = title.slice(3).replace(/ /g, '-').replace(/-/g, '[\\\\W_]?');\n        try {\n          pattern = new RegExp(rawPattern, 'gi');\n        } catch {\n          continue;\n        }\n      } else {\n        // Build a flexible pattern: spaces and separators in expected titles can match\n        // any separator character in the input (handles \"OSS 117\" matching \"OSS_117\").\n        // Escape each word individually, then join with separator class.\n        const parts = title.split(/[\\s._-]+/).map(p => p.replace(/[-[\\]{}()*+?.,\\\\^$|#]/g, '\\\\$&'));\n        if (parts.length === 0) continue;\n        // Require at least one separator character (or none) between words;\n        // use word boundaries to prevent partial matches inside longer words.\n        const patternStr = '(?<![a-zA-Z0-9])' + parts.join(`${SEP_CLASS}?`) + '(?![a-zA-Z0-9])';\n        try {\n          pattern = new RegExp(patternStr, 'gi');\n        } catch {\n          // Fallback to literal matching if regex construction fails\n          const literalPat = title.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n          try {\n            pattern = new RegExp(literalPat, 'gi');\n          } catch {\n            continue;\n          }\n        }\n      }\n      let m: RegExpExecArray | null;\n      while ((m = pattern.exec(inputString)) !== null) {\n        results.push([m.index, m.index + m[0].length, {}]);\n        // Prevent infinite loop on zero-length matches\n        if (m[0].length === 0) break;\n      }\n    }\n    return results;\n  };\n}\n","/**\n * Title property — port of guessit/rules/properties/title.py\n */\nimport { Rebulk } from 'rebulk-js';\nimport { Rule, AppendMatch, RemoveMatch, AppendTags } from 'rebulk-js';\nimport { Match, type Matches } from 'rebulk-js';\nimport type { Context } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { cleanup, reorderTitle, foldDiacritics } from '../common/formatters.js';\nimport { markerSorted } from '../common/comparators.js';\nimport { buildExpectedFunction } from '../common/expected.js';\nimport { formatters, POST_PROCESS } from 'rebulk-js';\nimport { titleSeps, seps, sepsPattern } from '../common/index.js';\n\n// Function words that a title cannot meaningfully END on. If cropping a trailing\n// language/country would leave the title dangling on one of these, the token is\n// actually part of the title (e.g. \"It Ends With Us\", \"Oshi no Ko\").\nconst TITLE_STOP_WORDS = new Set([\n  'the', 'a', 'an', 'and', 'or', 'of', 'to', 'in', 'on', 'at', 'for', 'from',\n  'by', 'with', 'into', 'onto', 'no', 'le', 'la', 'les', 'de', 'du', 'des', 'el',\n]);\n\n/** Helper: truthy check for match result (handles empty arrays correctly) */\nfunction hasmatch(result: Match[] | Match | undefined): boolean {\n  if (result === null || result === undefined) return false;\n  if (Array.isArray(result)) return result.length > 0;\n  return true;\n}\n\n/**\n * Base class for title rules.\n */\nabstract class TitleBaseRule extends Rule {\n  static override priority = 0;\n  // dependency is inherited from Rule (not overridden here to allow subclasses to set string arrays)\n  static override properties: Record<string, unknown[]> = {};\n\n  override consequence = [AppendMatch, RemoveMatch];\n  matchName: string;\n  propertyName: string;\n  alternativePropertyName: string;\n\n  constructor(\n    matchName: string,\n    propertyNames: string[],\n    alternativePropertyName: string,\n  ) {\n    super();\n    this.matchName = matchName;\n    this.propertyName = propertyNames[0] ?? 'title';\n    this.alternativePropertyName = alternativePropertyName;\n  }\n\n  /**\n   * Filter predicate for holes.\n   */\n  protected holeFilter(_hole: Match): boolean {\n    return true;\n  }\n\n  /**\n   * Filter predicate for fileparts.\n   */\n  protected filepartFilter(_filepart: Match): boolean {\n    return true;\n  }\n\n  /**\n   * Process holes: crop by group markers, skip markers spanning entire path.\n   */\n  protected holesProcess(holes: Match[], matches: Matches, filepart: Match): Match[] {\n    const groupMarkers = matches.markers.named('group') as Match[] | Match | undefined;\n    const groupArray = Array.isArray(groupMarkers)\n      ? groupMarkers\n      : groupMarkers\n        ? [groupMarkers]\n        : [];\n\n    // Filter to groups within filepart\n    const relevantGroups = groupArray.filter((g) => g.start >= filepart.start && g.end <= filepart.end);\n\n    // Skip groups that span the entire filepart\n    const filteredGroups = relevantGroups.filter((g) => !(g.start === filepart.start && g.end === filepart.end));\n\n    const ret: Match[] = [];\n    for (const hole of holes) {\n      // Crop hole by filtered group markers\n      const cropped = hole.crop(filteredGroups);\n      if (!cropped) continue;\n      if (Array.isArray(cropped)) {\n        ret.push(...cropped);\n      } else {\n        ret.push(cropped);\n      }\n    }\n    return ret;\n  }\n\n  /**\n   * Determine if a match should be ignored (e.g., language, country).\n   *\n   * Python parity: a full-word (len > 3) UPPERCASE language/country is a real\n   * token, not title filler, so it is NOT ignored — e.g. the trailing \"FRENCH\"\n   * in \"...XViD-NTK.FRENCH...\" must not be pulled into an alternative_title.\n   * Lowercase or short (<= 3 char) language/country codes remain ignored.\n   */\n  protected isIgnored(match: Match): boolean {\n    if (!(match.name === 'language' || match.name === 'country' || match.name === 'episode_details')) {\n      return false;\n    }\n    const raw = match.raw ?? '';\n    if (match.end - match.start > 3 && raw !== '' && raw === raw.toUpperCase() && raw !== raw.toLowerCase()) {\n      return false;\n    }\n    return true;\n  }\n\n  /**\n   * Determine if we should keep a hole boundary (don't trim this side).\n   * Returns false (allow trimming) only when the ignored match spans the entire hole edge\n   * with no remaining title content — i.e., it's a pure language/country/episode_details hole.\n   * Mirrors Python TitleBaseRule.should_keep().\n   */\n  protected shouldKeep(hole: Match, ignored: Match[], before: boolean): boolean {\n    if (before) {\n      // Keep if there's still content in the hole after this leading ignored match\n      return ignored[0].end < hole.end || ignored.length > 1;\n    } else {\n      // Python: `to_keep_match.start > hole.start and len(to_keep) > 1`\n      return ignored[ignored.length - 1].start > hole.start && ignored.length > 1;\n    }\n  }\n\n  /**\n   * Check if a trailing ignored match (language/country) appears again in the same filepart\n   * after the given position. If so, the occurrence in the title hole is part of the movie/show\n   * title (e.g. \"Immersion French\" where \"FRENCH\" also appears later as a separate tag).\n   */\n  protected languageDuplicatedAfterHole(lastIgnored: Match, afterPos: number, matches: Matches): boolean {\n    if (lastIgnored.name !== 'language' && lastIgnored.name !== 'country') return false;\n    const filepart = matches.markers.atMatch(lastIgnored, (m: Match) => m.name === 'path') as Match | undefined;\n    if (!filepart) return false;\n    // Compare using string representation of the value (works for Language objects)\n    const ignoredValueStr = String(lastIgnored.value ?? '').toLowerCase();\n    const duplicates = matches.range(afterPos, filepart.end, (m: Match) =>\n      m.name === lastIgnored.name &&\n      String(m.value ?? '').toLowerCase() === ignoredValueStr\n    ) as Match[] | Match | undefined;\n    return Array.isArray(duplicates) ? duplicates.length > 0 : !!duplicates;\n  }\n\n  /**\n   * Determine if we should remove a hole.\n   */\n  protected shouldRemove(_hole: Match): boolean {\n    return false;\n  }\n\n  /**\n   * Split a title hole at titleSeps characters (- / | + \\) into title + alternative_titles.\n   * Returns null if no split is possible.\n   * Mirrors Python's TitleBaseRule._split_title_alternative().\n   */\n  protected splitTitleAlternative(\n    hole: Match,\n    inputString: string,\n  ): { title: Match; alternatives: Match[] } | null {\n    const text = inputString.slice(hole.start, hole.end);\n\n    // Find ALL titleSep positions in the text\n    const splitPositions: number[] = [];\n    for (let i = 0; i < text.length; i++) {\n      const ch = text[i];\n      if (!titleSeps.includes(ch)) continue;\n\n      // Check the character is a standalone separator (surrounded by seps or start/end)\n      const prevIsSep = i === 0 || seps.includes(text[i - 1]);\n      const nextIsSep = i === text.length - 1 || seps.includes(text[i + 1]);\n\n      // Also allow \"/\" without surrounding seps (e.g., \"Timsit/Lindon\")\n      if ((prevIsSep && nextIsSep) || ch === '/') {\n        splitPositions.push(i);\n      }\n    }\n\n    if (splitPositions.length === 0) return null;\n\n    // Helper to create a trimmed Match from a range\n    const createMatch = (start: number, end: number): Match | null => {\n      let s = start;\n      let e = end;\n      while (s < e && seps.includes(inputString[s])) s++;\n      while (e > s && seps.includes(inputString[e - 1])) e--;\n      if (s >= e) return null;\n      const raw = inputString.slice(s, e);\n      const value = hole.formatter ? (hole.formatter as Function)(raw) : raw;\n      return new Match(s, e, { inputString, formatter: hole.formatter, value });\n    };\n\n    // Split into segments\n    const segments: Match[] = [];\n    let prevEnd = hole.start;\n    for (const pos of splitPositions) {\n      const absPos = hole.start + pos;\n      const seg = createMatch(prevEnd, absPos);\n      if (seg) segments.push(seg);\n      prevEnd = absPos + 1;\n    }\n    // Last segment\n    const lastSeg = createMatch(prevEnd, hole.end);\n    if (lastSeg) segments.push(lastSeg);\n\n    if (segments.length < 2) return null;\n\n    // A bare number is no title on its own — \"2047 - Sights of Death\" is one\n    // title, not title 2047 + alternative (cross-parser corpus, go-ptn/ptn).\n    if (/^\\d+$/.test(String(segments[0].value ?? '').trim())) return null;\n\n    return { title: segments[0], alternatives: segments.slice(1) };\n  }\n\n  /**\n   * Check and extract titles from a filepart.\n   * Mirrors Python's TitleBaseRule.check_titles_in_filepart().\n   */\n  protected checkTitlesInFilepart(\n    filepart: Match,\n    matches: Matches,\n    context?: any,\n  ): { toAppend: Match[]; toRemove: Match[] } {\n    const toAppend: Match[] = [];\n    const toRemove: Match[] = [];\n\n    // Get holes (gaps) in the entire filepart\n    // If a year exists in this filepart and a weak-episode match starts AT the very\n    // beginning of the filepart, treat it as transparent so the title can include it\n    // (e.g. \"12.Angry.Men.1957.mkv\" → title=\"12 Angry Men\", not \"Angry Men\").\n    // Also do this when a strong SxxExx pattern or date is present (e.g. \"4400.S01E01...\" → title=\"4400\").\n    const firstYearInFilepart = matches.range(filepart.start, filepart.end,\n      (m: Match) => m.name === 'year', 0) as Match | undefined;\n    const hasYearInFilepart = !!firstYearInFilepart;\n    const hasDateInFilepart = !!(matches.range(filepart.start, filepart.end,\n      (m: Match) => m.name === 'date', 0) as Match | undefined);\n    const hasSxxExxInFilepart = !!(matches.range(filepart.start, filepart.end,\n      (m: Match) => m.tags?.includes('SxxExx') && !m.private, 0) as Match | undefined);\n    const holesResult = matches.holes(filepart.start, filepart.end, {\n      formatter: formatters(cleanup, reorderTitle),\n      ignore: (m: Match) => {\n        if (this.isIgnored(m)) return true;\n        // Ignore private weak-episode remnants (children of removed weak_duplicate chains)\n        if (m.private && m.tags?.includes('weak-episode')) return true;\n        if (\n          (m.tags?.includes('weak-episode') || m.tags?.includes('weak-duplicate'))\n        ) {\n          // Check if this match OR its chain initiator starts at the filepart boundary.\n          // Chain children (e.g. season=1 at [0,1) and episode=23 at [1,3) from \"123\")\n          // share the same initiator — ignore ALL of them when the chain starts at filepart.start.\n          const initiator = m.initiator;\n          const startsAtFilepart = m.start === filepart.start || initiator.start === filepart.start;\n          if (startsAtFilepart) {\n            if (hasYearInFilepart || hasDateInFilepart || hasSxxExxInFilepart) return true;\n          }\n          // Also ignore weak-episode fragments within the first 4 characters of the filepart\n          // when a year exists (handles \"2001...\" where \"001\" at [1,4) is a fragment).\n          if (hasYearInFilepart && m.start >= filepart.start && m.start < filepart.start + 4 && m.end <= filepart.start + 4) {\n            return true;\n          }\n          // Ignore weak-episode/weak-duplicate matches that appear BEFORE the first year\n          // in the filepart. These numbers are typically part of the title, not episode numbers.\n          // (e.g. \"Paris 2054, Renaissance (2005)\" → \"2054\" is part of the title).\n          if (firstYearInFilepart && m.end <= firstYearInFilepart.start) {\n            return true;\n          }\n          // Ignore weak_duplicate matches when another weak_duplicate exists LATER\n          // in the filepart (the earlier number is part of the title).\n          // (e.g. \"the.100.109\" → \"100\" is title, \"109\" is season=1/episode=9)\n          if (m.tags?.includes('weak-duplicate')) {\n            const init = m.initiator || m;\n            // Find any weak_duplicate that starts AFTER this one ends\n            const laterWds = (matches.range(init.end, filepart.end,\n              (other: Match) => other.tags?.includes('weak-duplicate') && !other.private\n            ) as Match[]) || [];\n            // Check it's a DIFFERENT initiator (not same chain)\n            const hasLaterDifferent = laterWds.some((other: Match) => {\n              const otherInit = other.initiator || other;\n              return otherInit !== init;\n            });\n            if (hasLaterDifferent) return true;\n          }\n        }\n        return false;\n      },\n      predicate: (m) => m.value ? true : false,\n    });\n\n    const holeArray = Array.isArray(holesResult) ? holesResult : holesResult ? [holesResult] : [];\n\n    // Process holes through holesProcess\n    let processedHoles = this.holesProcess(holeArray, matches, filepart);\n\n    // For each hole, find ignored matches inside and trim boundaries\n    for (const hole of processedHoles) {\n      if (!this.holeFilter(hole)) continue;\n      if (process.env.DEBUG_TITLE_TRIM) {\n        const inp = (matches as any).inputString ?? '';\n        console.log(`[trim] hole=\"${inp.slice(hole.start, hole.end)}\" [${hole.start},${hole.end})`);\n      }\n\n      // Find ignored matches inside this hole\n      const ignoredInHole = matches.range(hole.start, hole.end, (m) =>\n        this.isIgnored(m),\n      ) as Match[] | Match | undefined;\n      const ignoredArray = Array.isArray(ignoredInHole)\n        ? ignoredInHole\n        : ignoredInHole\n          ? [ignoredInHole]\n          : [];\n\n      // A hole made up entirely of languages/countries is not a real title\n      // (\"Ita Eng\" between codecs, upstream #751): keep the languages rather than\n      // fabricating a title out of them and deleting them.\n      if (ignoredArray.length > 0 &&\n          ignoredArray.every((m) => m.name === 'language' || m.name === 'country')) {\n        const inpFull: string = (matches as any).inputString ?? '';\n        let rest = inpFull.slice(hole.start, hole.end);\n        for (const m of ignoredArray) {\n          const rel = m.start - hole.start;\n          rest = rest.slice(0, rel) + ' '.repeat(m.end - m.start) + rest.slice(m.end - hole.start);\n        }\n        const hasTitleText = [...rest].some((c) => !seps.includes(c) && c !== ' ');\n        if (!hasTitleText) continue;\n      }\n\n      let trimmedHole = hole;\n      // Pre-strip leading/trailing seps from the hole boundaries so that language-match\n      // positions (which don't include surrounding seps) align with the trimmed boundaries.\n      const inp: string = (matches as any).inputString ?? '';\n      while (trimmedHole.start < trimmedHole.end && seps.includes(inp[trimmedHole.start])) {\n        trimmedHole.start++;\n      }\n      while (trimmedHole.end > trimmedHole.start && seps.includes(inp[trimmedHole.end - 1])) {\n        const pos = trimmedHole.end - 1;\n        // Don't strip '.' if it's part of an abbreviation pattern (e.g. S.H.I.E.L.D., 0.8.4.)\n        // Check: inp[pos]='.' AND inp[pos-1] is a letter/digit AND inp[pos-2] is '.'\n        if (inp[pos] === '.' && pos >= 2 && /[a-zA-Z0-9]/.test(inp[pos - 1]) && inp[pos - 2] === '.') {\n          break;\n        }\n        trimmedHole.end--;\n      }\n      if (process.env.DEBUG_TITLE_TRIM) {\n        const ignoredNames = ignoredArray.map((m: Match) => `${m.name}=\"${inp.slice(m.start, m.end)}\"@[${m.start},${m.end})`).join(', ');\n        console.log(`  after pre-strip hole=[${trimmedHole.start},${trimmedHole.end}) ignoredArray=[${ignoredNames}]`);\n      }\n\n      // Trim leading ignored matches\n      while (ignoredArray.length > 0) {\n        const firstIgnored = ignoredArray[0];\n        if (firstIgnored.start === trimmedHole.start) {\n          // Country codes at the leading edge should always be stripped (e.g. \"US Presidential Debates\").\n          // Languages at the leading edge are kept when there's more content (e.g. \"French Maid Services\").\n          const keep = firstIgnored.name === 'country'\n            ? false\n            : this.shouldKeep(trimmedHole, ignoredArray, true);\n          if (process.env.DEBUG_TITLE_TRIM) {\n            console.log(`  leading trim: shouldKeep=${keep} for \"${inp.slice(firstIgnored.start, firstIgnored.end)}\"`);\n          }\n          if (keep) {\n            // Even when shouldKeep says true, strip the ignored match if what follows\n            // is a title separator (e.g. \"Fr - Paris 2054\" → strip \"Fr\" because it's\n            // a language/country before a title separator, not part of the actual title).\n            let hasTitleSep = false;\n            for (let pp = firstIgnored.end; pp < trimmedHole.end; pp++) {\n              const ch = inp[pp];\n              if (titleSeps.includes(ch)) { hasTitleSep = true; break; }\n              if (!seps.includes(ch)) break; // hit non-sep content → stop\n            }\n            if (hasTitleSep) {\n              // Fall through to strip\n            } else {\n              break;\n            }\n          }\n          trimmedHole.start = firstIgnored.end;\n          // Also skip any seps after the leading ignored match\n          while (trimmedHole.start < trimmedHole.end && seps.includes(inp[trimmedHole.start])) {\n            trimmedHole.start++;\n          }\n          ignoredArray.shift();\n        } else {\n          break;\n        }\n      }\n\n      // Trim trailing ignored matches\n      while (ignoredArray.length > 0) {\n        const lastIgnored = ignoredArray[ignoredArray.length - 1];\n        if (lastIgnored.end === trimmedHole.end) {\n          // Don't crop a trailing language/country if it would leave the title\n          // ending on a stop-word (preposition/article/particle) — the token is\n          // part of the title: \"It Ends With Us\" (else \"It Ends With\"), \"Oshi no\n          // Ko\" (else \"Oshi no\"). Keep the text, drop the language/country match.\n          if (lastIgnored.name === 'language' || lastIgnored.name === 'country') {\n            const beforeWords = inp.slice(trimmedHole.start, lastIgnored.start)\n              .toLowerCase().split(/[^a-z0-9]+/i).filter(Boolean);\n            const lastWord = beforeWords[beforeWords.length - 1];\n            if (lastWord && TITLE_STOP_WORDS.has(lastWord)) {\n              toRemove.push(lastIgnored);\n              ignoredArray.pop();\n              break;\n            }\n          }\n          // Don't trim episode_details \"Special\" when followed directly by a year\n          // (e.g. \"A.Common.Title.Special.2014\" → \"Special\" is part of the title)\n          if (lastIgnored.name === 'episode_details' && lastIgnored.value === 'Special') {\n            const nextMatch = matches.range(lastIgnored.end, lastIgnored.end + 10,\n              (m: Match) => m.name === 'year' && !m.private, 0) as Match | undefined;\n            if (nextMatch) {\n              const between = inp.slice(lastIgnored.end, nextMatch.start);\n              if ([...between].every(c => seps.includes(c))) {\n                // \"Special\" is right before a year — keep it in the title\n                break;\n              }\n            }\n          }\n          // If the same language value appears again after this hole, it's part of the title name\n          // (e.g. \"Immersion French ... FRENCH ENGLISH\" → keep \"French\" in title).\n          // We also remove the language match so it doesn't appear as both language AND title.\n          if (this.languageDuplicatedAfterHole(lastIgnored, trimmedHole.end, matches)) {\n            toRemove.push(lastIgnored);\n            ignoredArray.pop();\n            break;\n          }\n          if (this.shouldKeep(trimmedHole, ignoredArray, false)) {\n            // Check if ALL remaining ignored matches form a contiguous block at the\n            // trailing edge (only seps between them). If so, they are ALL language/country\n            // tags and should be trimmed despite shouldKeep returning true.\n            // e.g. \"Die.Schluempfe.2.German.DL\" → \"German\" and \"DL\" are contiguous languages.\n            let allContiguousAtEnd = true;\n            let checkEnd = trimmedHole.end;\n            for (let k = ignoredArray.length - 1; k >= 0; k--) {\n              const ig = ignoredArray[k];\n              const between = inp.slice(ig.end, checkEnd);\n              if (![...between].every(c => seps.includes(c))) {\n                allContiguousAtEnd = false;\n                break;\n              }\n              checkEnd = ig.start;\n            }\n            // Only skip the trim if the languages are NOT all contiguous at the end\n            if (!allContiguousAtEnd) break;\n          }\n          trimmedHole.end = lastIgnored.start;\n          // Also strip any trailing seps before the ignored match\n          while (trimmedHole.end > trimmedHole.start && seps.includes(inp[trimmedHole.end - 1])) {\n            trimmedHole.end--;\n          }\n          ignoredArray.pop();\n        } else {\n          break;\n        }\n      }\n\n      if (process.env.DEBUG_TITLE_TRIM) {\n        console.log(`  result: hole=[${trimmedHole.start},${trimmedHole.end}) length=${trimmedHole.length} value=\"${trimmedHole.value}\"`);\n      }\n      if (trimmedHole.length > 0 && !this.shouldRemove(trimmedHole) && trimmedHole.value) {\n        // Split title at titleSeps (- / | + \\) to create title + alternative_title\n        // Anime releases use \" - \" inside titles (\"Tower of Druaga - Sword of Uruk\")\n        // and a leading bracket group or CRC32 marks the naming style — keep the\n        // compound title whole instead of splitting off an alternative_title.\n        const inp0: string = (matches as any).inputString ?? '';\n        const animeStyle =\n          (matches.markers.range(filepart.start, filepart.end,\n            (m: Match) => m.name === 'group' && m.start === filepart.start, 0) as Match | undefined) !== undefined ||\n          (matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'crc32', 0) as Match | undefined) !== undefined;\n        // Skip the split when the alternative property is excluded (--exclude alternative_title).\n        let splitResult = (this.alternativePropertyName && !isDisabled(context, this.alternativePropertyName))\n          ? this.splitTitleAlternative(trimmedHole, inp)\n          : null;\n        // Under an anime signal, wordy dash segments are one compound title\n        // (\"Garo - Vanishing Line\"); short coded segments (\"T1\", \"IS\") still split.\n        if (splitResult && animeStyle &&\n            splitResult.alternatives.every((a) => {\n              const v = String(a.value ?? '').trim();\n              return v.length >= 4 || /\\s/.test(v);\n            })) {\n          splitResult = null;\n        }\n        if (splitResult) {\n          splitResult.title.name = this.matchName;\n          toAppend.push(splitResult.title);\n          for (const alt of splitResult.alternatives) {\n            alt.name = this.alternativePropertyName;\n            toAppend.push(alt);\n          }\n        } else {\n          trimmedHole.name = this.matchName;\n          toAppend.push(trimmedHole);\n        }\n      }\n    }\n\n    // Python's TitleBaseRule.should_remove: an episode_details or country match\n    // absorbed INTO the main title hole (it's \"ignored\" for hole purposes) is\n    // removed. So \"Special.Correspondents\" keeps title \"Special Correspondents\"\n    // without a phantom episode_details \"Special\", and \"Bienvenue.Au.Gondwana\"\n    // keeps the title without a phantom country \"Au\" (French \"au\"). A country at\n    // the title's *edge* was already cropped out of the hole, so it survives\n    // (e.g. \"Show.Name.Au.S01E01\" → title \"Show Name\" + country AU). Only the\n    // first/main title is considered — a later hole that becomes an episode_title\n    // (e.g. \"Christmas Special …\") keeps its episode_details so the type holds.\n    const mainTitle = toAppend.find((t) => t.name === this.matchName);\n    if (mainTitle) {\n      const absorbedRaw = matches.range(mainTitle.start, mainTitle.end,\n        (m: Match) => m.name === 'episode_details' || m.name === 'country' || m.name === 'language') as Match[] | Match | undefined;\n      const absorbed = Array.isArray(absorbedRaw) ? absorbedRaw : absorbedRaw ? [absorbedRaw] : [];\n      for (const m of absorbed) if (!toRemove.includes(m)) toRemove.push(m);\n    }\n\n    return { toAppend, toRemove };\n  }\n\n  /**\n   * Find the \"series name\" filepart: the directory immediately preceding a season-only directory.\n   * e.g. in Series/Californication/Season 2/..., returns the Californication filepart.\n   * Mirrors Python's TitleBaseRule._serie_name_filepart().\n   */\n  protected _serieNameFilepart(matches: Matches, fileparts: Match[]): Match | null {\n    for (let index = 0; index < fileparts.length - 1; index++) {\n      if (index === 0) continue; // Skip most-informative filepart (the filename)\n      const filepart = fileparts[index];\n      const fpMatches = (matches.range(filepart.start, filepart.end) as Match[]).filter((m) => !m.private);\n      if (process.env.DEBUG_TITLE) {\n        const inp = (matches as any).inputString ?? '';\n        console.log(`[_serieNameFilepart] index=${index} fp=\"${inp.slice(filepart.start, filepart.end)}\" fpMatches=${fpMatches.map((m: Match) => `${m.name}=\"${m.value}\"@[${m.start},${m.end})`).join(',')}`);\n        if (fpMatches[0]) {\n          const parent = (fpMatches[0] as any).parent;\n          console.log(`  season span=[${fpMatches[0].start},${fpMatches[0].end}), filepart=[${filepart.start},${filepart.end}), parent span=${parent ? `[${parent.start},${parent.end})` : 'null'}`);\n        }\n      }\n      if (\n        fpMatches.length === 1 &&\n        fpMatches[0].name === 'season' &&\n        (\n          (fpMatches[0].start === filepart.start && fpMatches[0].end === filepart.end) ||\n          ((fpMatches[0] as any).parent &&\n            (fpMatches[0] as any).parent.start === filepart.start &&\n            (fpMatches[0] as any).parent.end === filepart.end)\n        )\n      ) {\n        // This filepart contains only a season match — the NEXT one (less informative) is the series name\n        return fileparts[index + 1] ?? null;\n      }\n    }\n    return null;\n  }\n\n  /**\n   * Get the title match from the series name filepart.\n   * Mirrors Python's TitleBaseRule._serie_name_filepart_match().\n   *\n   * First looks for an existing title match in the filepart (added by Filepart3EpisodeTitle\n   * or Filepart2EpisodeTitle which run before TitleFromPosition). If not found, attempts\n   * to create one from holes in the filepart.\n   */\n  protected _serieNameFilepartMatch(\n    matches: Matches,\n    serieNameFilepart: Match,\n    toAppend: Match[],\n    toRemove: Match[],\n  ): Match | null {\n    // First check for an existing title match in the filepart (from Filepart3/2EpisodeTitle)\n    const existingTitle = matches.range(\n      serieNameFilepart.start, serieNameFilepart.end,\n      (m: Match) => m.name === 'title', 0,\n    ) as Match | undefined;\n\n    if (existingTitle) {\n      if (process.env.DEBUG_TITLE) {\n        const inp = (matches as any).inputString ?? '';\n        console.log(`[_serieNameFilepartMatch] fp=\"${inp.slice(serieNameFilepart.start, serieNameFilepart.end)}\" found existing title=\"${existingTitle.value}\"`);\n      }\n      return existingTitle;\n    }\n\n    // No existing title: try to create one from holes\n    const weakIgnored = (m: Match) =>\n      m.tags ? m.tags.some((t: string) => t === 'weak' || t.startsWith('weak-')) : false;\n\n    const savedIsIgnored = this.isIgnored.bind(this);\n    const combinedIgnore = (m: Match) => savedIsIgnored(m) || weakIgnored(m);\n\n    const holesResult = matches.holes(serieNameFilepart.start, serieNameFilepart.end, {\n      formatter: formatters(cleanup, reorderTitle),\n      ignore: combinedIgnore,\n      predicate: (m: Match) => m.value ? true : false,\n    });\n    const holeArray = Array.isArray(holesResult) ? holesResult : holesResult ? [holesResult] : [];\n    const processedHoles = this.holesProcess(holeArray, matches, serieNameFilepart);\n    if (process.env.DEBUG_TITLE) {\n      const inp = (matches as any).inputString ?? '';\n      console.log(`[_serieNameFilepartMatch] fp=\"${inp.slice(serieNameFilepart.start, serieNameFilepart.end)}\" holeArray=${holeArray.length} processedHoles=${processedHoles.length}`);\n      processedHoles.forEach((h, i) => console.log(`  hole[${i}]=\"${inp.slice(h.start, h.end)}\" value=\"${h.value}\"`));\n    }\n\n    if (processedHoles.length === 1 && processedHoles[0].value) {\n      const serieTitle = processedHoles[0];\n      serieTitle.name = this.matchName;\n      toAppend.push(serieTitle);\n      return serieTitle;\n    }\n    return null;\n  }\n\n  override when(matches: Matches, context: Context): { toAppend: Match[]; toRemove: Match[] } | null {\n    // If an expected title already created title match(es), skip position-based title extraction.\n    // This mirrors Python guessit behavior where expected_title takes precedence.\n    const existingExpected = (matches.tagged('expected') as Match[] | undefined)?.filter(\n      (m: Match) => m.name === 'title'\n    ) ?? [];\n    if (existingExpected.length > 0) {\n      return null;\n    }\n\n    const toAppend: Match[] = [];\n    const toRemove: Match[] = [];\n\n    // Get path markers\n    const pathMarkers = matches.markers.named('path') as Match[] | Match | undefined;\n    const pathArray = Array.isArray(pathMarkers) ? pathMarkers : pathMarkers ? [pathMarkers] : [];\n\n    // Sort fileparts by value (number of distinct matches inside), rightmost first on tie.\n    // This mirrors Python's marker_sorted behavior: process most-info filepart first.\n    const sortedFileparts = markerSorted(pathArray, matches);\n\n    // Find the \"series name\" filepart (the directory before a season-only directory)\n    const serieNameFilepart = this._serieNameFilepart(matches, sortedFileparts);\n    let serieNameMatch: Match | null = null;\n    if (serieNameFilepart) {\n      serieNameMatch = this._serieNameFilepartMatch(matches, serieNameFilepart, toAppend, toRemove);\n    }\n    if (process.env.DEBUG_TITLE) {\n      const inp = (matches as any).inputString ?? '';\n      console.log(`[when] sortedFileparts: ${sortedFileparts.map((fp: Match) => `\"${inp.slice(fp.start, fp.end)}\"`).join(', ')}`);\n      console.log(`[when] serieNameFilepart: ${serieNameFilepart ? `\"${inp.slice(serieNameFilepart.start, serieNameFilepart.end)}\"` : 'null'}`);\n      console.log(`[when] serieNameMatch: ${serieNameMatch ? `\"${serieNameMatch.value}\"` : 'null'}`);\n    }\n\n    // Identify fileparts that contain a year (process these separately at the end)\n    const yearFileparts = new Set<Match>(\n      sortedFileparts.filter((fp) =>\n        hasmatch(matches.range(fp.start, fp.end, (m: Match) => m.name === 'year', 0)),\n      ),\n    );\n\n    // Process sorted fileparts — stop at first filepart that yields titles\n    for (const filepart of sortedFileparts) {\n      yearFileparts.delete(filepart); // Track which year fileparts are processed\n      if (!this.filepartFilter(filepart)) continue;\n\n      const result = this.checkTitlesInFilepart(filepart, matches, context);\n      if (result.toAppend.length > 0 || result.toRemove.length > 0) {\n        // If we found the series name, rename titles with different values to episode_title\n        if (serieNameMatch) {\n          // Normalize for comparison: strip apostrophes, trailing dots, and accents\n          const normTitle = (s: string) =>\n            foldDiacritics(s).replace(/[''`]/g, '').replace(/\\.+$/, '').toLowerCase().trim();\n          for (const titleMatch of result.toAppend) {\n            if (normTitle(String(titleMatch.value)) !== normTitle(String(serieNameMatch.value))) {\n              titleMatch.name = 'episode_title';\n            }\n          }\n        }\n        toAppend.push(...result.toAppend);\n        toRemove.push(...result.toRemove);\n        break; // Only process first successful filepart (matches Python behavior)\n      }\n    }\n\n    // Also process remaining fileparts that contain years (for extra title candidates).\n    // When a year-filepart title is an accented/richer version of the filename title,\n    // prefer the year-filepart title (e.g., \"La Science des Rêves\" over \"La Science Des Reves\").\n    for (const filepart of yearFileparts) {\n      if (!this.filepartFilter(filepart)) continue;\n      const result = this.checkTitlesInFilepart(filepart, matches, context);\n      const filteredAppend: Match[] = [];\n      for (const newTitle of result.toAppend) {\n        if (newTitle.name !== this.matchName) {\n          filteredAppend.push(newTitle);\n          continue;\n        }\n        const newVal = String(newTitle.value ?? '');\n        // Check if an existing title in toAppend is an equivalent of the new one\n        // (stripping accents, apostrophes, and other punctuation for comparison)\n        const norm = (s: string) => foldDiacritics(s).replace(/[''`]/g, '').toLowerCase();\n        const existingIdx = toAppend.findIndex((m) => {\n          const existingVal = String(m.value ?? '');\n          return norm(existingVal) === norm(newVal) && existingVal !== newVal;\n        });\n        if (existingIdx !== -1) {\n          const existing = toAppend[existingIdx];\n          if (existing.name === this.matchName) {\n            // Update the existing title's value to the richer version\n            existing.value = newVal;\n          } else if (existing.name === this.alternativePropertyName) {\n            // The year-filepart title matches an alternative_title — promote:\n            // the directory title (with year) should be the main title,\n            // and the current main title becomes alternative or stays as-is.\n            existing.value = newVal;\n            const mainTitle = toAppend.find(m => m.name === this.matchName);\n            if (mainTitle) {\n              mainTitle.name = this.alternativePropertyName || 'alternative_title';\n              existing.name = this.matchName;\n            }\n          }\n          continue;\n        }\n        // Skip year-filepart titles that are just the existing title + country/language\n        // (e.g. \"The Office US\" when existing is \"The Office\")\n        const isSuperset = toAppend.some((m) => {\n          if (m.name !== this.matchName) return false;\n          const existingNorm = norm(String(m.value ?? ''));\n          const newNorm = norm(newVal);\n          return newNorm.startsWith(existingNorm + ' ') || newNorm.endsWith(' ' + existingNorm);\n        });\n        if (isSuperset) continue;\n        filteredAppend.push(newTitle);\n      }\n      toAppend.push(...filteredAppend);\n      toRemove.push(...result.toRemove);\n    }\n\n    if (toAppend.length === 0 && toRemove.length === 0) {\n      return null;\n    }\n\n    return { toAppend, toRemove };\n  }\n\n  override then(matches: Matches, whenResponse: unknown, context: Context): void {\n    if (!whenResponse || typeof whenResponse !== 'object') return;\n    const response = whenResponse as { toAppend: Match[]; toRemove: Match[] };\n\n    // Apply removes first\n    const removeConsequence = new RemoveMatch();\n    removeConsequence.then(matches, response.toRemove, context);\n\n    // Then appends\n    const appendConsequence = new AppendMatch();\n    appendConsequence.then(matches, response.toAppend, context);\n  }\n}\n\n/**\n * Extract title from filepart positions.\n */\nclass TitleFromPosition extends TitleBaseRule {\n  static override priority = 0;\n  // Run after DashSeparatedReleaseGroup so it doesn't create title holes\n  // where the release group has already been claimed (matches Python behavior)\n  static override dependency = ['DashSeparatedReleaseGroup', 'SubtitlePrefixLanguageRule', 'SubtitleSuffixLanguageRule', 'SubtitleExtensionRule'];\n  static override properties: Record<string, unknown[]> = { title: [null], alternative_title: [null] };\n\n  constructor() {\n    super('title', ['title'], 'alternative_title');\n  }\n}\n\n/**\n * Prefer title with year: mark titles without year as equivalent-ignore.\n */\nclass PreferTitleWithYear extends Rule {\n  static override priority = 32;\n  static override dependency: typeof Rule | typeof Rule[] = [TitleFromPosition];\n\n  override consequence = [RemoveMatch, AppendTags];\n\n  override when(matches: Matches, _context: Context): Match[] {\n    const ret: Match[] = [];\n\n    const titleMatches = matches.named('title') as Match[] | Match | undefined;\n    const titleArray = Array.isArray(titleMatches) ? titleMatches : titleMatches ? [titleMatches] : [];\n\n    const yearMatches = matches.named('year') as Match[] | Match | undefined;\n    const yearArray = Array.isArray(yearMatches) ? yearMatches : yearMatches ? [yearMatches] : [];\n\n    for (const title of titleArray) {\n      // Never remove expected titles (from -T / expected_title option)\n      if (title.tags?.includes('expected')) continue;\n\n      // Check if there's a year in the same filepart\n      const filepart = matches.markers.atMatch(title, (m) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n\n      const yearsInPart = matches.range(filepart.start, filepart.end, (m) =>\n        m.name === 'year',\n      ) as Match[] | Match | undefined;\n      const yearsInPartArray = Array.isArray(yearsInPart)\n        ? yearsInPart\n        : yearsInPart\n          ? [yearsInPart]\n          : [];\n\n      if (yearsInPartArray.length === 0) {\n        ret.push(title);\n      }\n    }\n\n    return ret;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, context: Context): void {\n    if (!whenResponse || !Array.isArray(whenResponse)) return;\n\n    // Remove titles without year\n    const removeConsequence = new RemoveMatch();\n    removeConsequence.then(matches, whenResponse, context);\n\n    // Mark removed ones as equivalent-ignore\n    const appendConsequence = new AppendTags(['equivalent-ignore']);\n    appendConsequence.then(matches, whenResponse, context);\n  }\n}\n\n/**\n * Create a rebulk pattern for title detection.\n */\nconst ARTICLES = new Set([\n  'the', 'a', 'an', 'le', 'la', 'les', \"l'\", 'el', 'los', 'las', 'il', 'lo',\n  'un', 'una', 'der', 'die', 'das', 'de', 'het', 'o', 'os',\n]);\n\n/**\n * A title that is a lone article (\"The\", \"La\", …) is almost always truncated:\n * the following word was claimed as an edition/language/country/other (e.g.\n * \"The.Collector\" → title \"The\" + edition Collector; \"The.English\" → title \"The\"\n * + language English). When that property is the LAST title-region token (a\n * year/season/episode or end follows), absorb it back into the title.\n * (Issues #652, #737.)\n */\nclass ExtendLoneArticleTitle extends Rule {\n  static override priority = -32;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: Context): Array<{ title: Match; prop: Match }> | false {\n    const inp = (matches as any).inputString || '';\n    const out: Array<{ title: Match; prop: Match }> = [];\n    const titles = (matches.named('title') as Match[] | Match | undefined);\n    const epTitles = (matches.named('episode_title') as Match[] | Match | undefined);\n    const titleArr = [\n      ...(Array.isArray(titles) ? titles : titles ? [titles] : []),\n      ...(Array.isArray(epTitles) ? epTitles : epTitles ? [epTitles] : []),\n    ];\n    for (const title of titleArr) {\n      if (!ARTICLES.has(String(title.value ?? '').trim().toLowerCase())) continue;\n      const filepart = matches.markers.atMatch(title, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      const prop = matches.range(title.end, filepart.end,\n        (m: Match) => !m.private && ['edition', 'language', 'country', 'other', 'source'].includes(m.name ?? ''), 0) as Match | undefined;\n      if (!prop) continue;\n      if (![...inp.slice(title.end, prop.start)].every((c: string) => seps.includes(c))) continue;\n      // Only absorb when the property is the last title-region token: a\n      // year/season/episode/date follows with nothing but seps in between\n      // (so \"The.French.Connection.1971\" — \"Connection\" after \"French\" — is left).\n      const next = matches.range(prop.end, filepart.end,\n        (m: Match) => !m.private && ['year', 'season', 'episode', 'date'].includes(m.name ?? ''), 0) as Match | undefined;\n      // The gap may contain season/episode marker letters (the \"S\" of \"S01E01\")\n      // plus separators, but no real title text.\n      if (next && inp.slice(prop.end, next.start).replace(/[sexd]/gi, '').split('').some((c: string) => !seps.includes(c))) continue;\n      out.push({ title, prop });\n    }\n    return out.length ? out : false;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: Context): void {\n    for (const { title, prop } of whenResponse as Array<{ title: Match; prop: Match }>) {\n      const inp = (matches as any).inputString || '';\n      matches.remove(title);\n      matches.remove(prop);\n      title.end = prop.end;\n      title.value = cleanup(inp.slice(title.start, title.end));\n      matches.append(title);\n    }\n  }\n}\n\n/**\n * A Title-Case country code that sits alone at the title position followed by a\n * year (\"Us.2019\" → country US, no title) is really the film title. Remove the\n * country before title detection so the word becomes the title. Guards: raw must\n * be Title-Case (\"Us\", not \"US\"/\"us\"), it must start the filepart, a YEAR (not a\n * season/episode — those are real country tags like \"US.S01E01\") must follow with\n * only separators between, and nothing else precedes the year. (Issue #638.)\n */\nclass CountryAtTitlePosition extends Rule {\n  static override priority = 64;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: Context): Match[] | false {\n    const inp = (matches as any).inputString || '';\n    const out: Match[] = [];\n    const cand = matches.range(0, inp.length,\n      (m: Match) => !m.private && ['country', 'other', 'edition'].includes(m.name ?? '')) as Match[] | Match | undefined;\n    const arr = Array.isArray(cand) ? cand : cand ? [cand] : [];\n    for (const c of arr) {\n      // Title-Case raw only (\"Us\"/\"Extras\", not \"US\"/\"PROPER\"/lowercase tags).\n      if (!/^[A-Z][a-z]+$/.test(c.raw ?? '')) continue;\n      const filepart = matches.markers.atMatch(c, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      if (![...inp.slice(filepart.start, c.start)].every((ch: string) => seps.includes(ch))) continue;\n      // A release tag (streaming/group prefix) or bracketed token is a deliberate tag.\n      if (['release-group-prefix', 'streaming_service.prefix', 'streaming_service.suffix']\n        .some((t) => c.tags?.includes(t))) continue;\n      if (matches.markers.atMatch(c, (m: Match) => m.name === 'group', 0)) continue;\n      // Anchor on the first year/season/episode/date after the candidate (upstream widened\n      // this beyond years so \"Uk.Top.Gear.S01E01\" and \"Au bout ... - 8x01\" qualify).\n      const anchor = matches.range(c.end, filepart.end,\n        (m: Match) => !m.private && ['year', 'season', 'episode', 'date'].includes(m.name ?? ''), 0) as Match | undefined;\n      if (!anchor) continue;\n      if (![...inp.slice(c.end, anchor.start)].every((ch: string) => seps.includes(ch))) {\n        // Plain title text between the word and the anchor means the word opens the title\n        // (\"Au bout c'est la mer - 8x01\"); another property in the gap means a real tag.\n        if (matches.range(c.end, anchor.start, (m: Match) => !m.private && m.value != null, 0)) continue;\n      }\n      out.push(c);\n    }\n    return out.length ? out : false;\n  }\n}\n\n/**\n * When a filepart ends up with NO title but a recognised property\n * (other/country/edition) sits at the very start where the title belongs, that\n * token is really the title — e.g. \"xXx.2002\" → other XXX but no title;\n * \"Extras.(2005).S01E01\" → other Extras but no title. Convert the leading\n * property to the title. Only fires when there is genuinely no title and the\n * filepart looks like media (has a year/season/episode/date). (Issues #773, #722.)\n */\n/**\n * A property value whose spelling is also a plain title word (tagged `title-word`\n * in the vocabulary, e.g. audio_codec \"Opus\") is really part of the title when it\n * sits before the first year/season/episode/date anchor of the filepart. Removing\n * the property match reopens the title hole: \"Opus.2025…\" → title \"Opus\",\n * \"Foo.Opus.2025…\" → \"Foo Opus\". A spelling after the anchor stays the property.\n * (upstream #885)\n */\nclass TitleWordAtTitlePosition extends Rule {\n  static override priority = 64;\n  override priority = 64;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: Context): Match[] | false {\n    const toRemove: Match[] = [];\n    const tagged = (matches as any).tagged('title-word') as Match[] ?? [];\n    for (const candidate of Array.isArray(tagged) ? tagged : [tagged]) {\n      if (!candidate || candidate.private) continue;\n      const filepart = matches.markers.atMatch(candidate, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      const anchor = matches.range(filepart.start, filepart.end,\n        (m: Match) => !m.private && ['year', 'season', 'episode', 'date'].includes(m.name ?? ''), 0) as Match | undefined;\n      if (!anchor || candidate.start >= anchor.start) continue;\n      toRemove.push(candidate);\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\n\n// Non-Latin script ranges: Greek, Cyrillic, Hebrew, Arabic, Thai, CJK punctuation,\n// kana, CJK ideographs, Hangul, fullwidth forms. (upstream #890)\nconst NON_LATIN_SCRIPT_RE = /[\\u0370-\\u03FF\\u0400-\\u04FF\\u0590-\\u05FF\\u0600-\\u06FF\\u0E00-\\u0E7F\\u3000-\\u303F\\u3040-\\u30FF\\u3400-\\u4DBF\\u4E00-\\u9FFF\\uAC00-\\uD7AF\\uFF00-\\uFFEF]/;\n\n/**\n * A title glued as \"<original-language title> <romanized title>\" — a leading\n * non-Latin script run in front of a Latin run — yields the Latin part as the\n * title and the original run as alternative_title (#890):\n * \"超能警探 Memorist\" → title \"Memorist\", alternative_title \"超能警探\".\n * Only a LEADING non-Latin run is split; an all-non-Latin title stays whole.\n */\nclass SplitOriginalScriptTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override priority = POST_PROCESS;\n  override consequence = [RemoveMatch, AppendMatch];\n\n  override when(matches: Matches, context: Context): any {\n    if (isDisabled(context, 'alternative_title')) return false;\n    const input: string = (matches as any).inputString ?? '';\n    const toRemove: Match[] = [];\n    const toAppend: Match[] = [];\n    for (const titleMatch of matches.named('title') as Match[]) {\n      if (titleMatch.tags?.includes('expected')) continue;\n      const raw = input.slice(titleMatch.start, titleMatch.end);\n      // The Latin part must start a word so a stray Latin homoglyph inside a\n      // Cyrillic word is not a split point.\n      const latin = new RegExp('(?:^|[' + sepsPattern + '])([A-Za-z])').exec(raw);\n      if (!latin) continue;\n      const latinOffset = latin.index + latin[0].indexOf(latin[1]);\n      const prefix = raw.slice(0, latinOffset);\n      if (!NON_LATIN_SCRIPT_RE.test(prefix)) continue;\n      let prefixTrim = prefix;\n      while (prefixTrim.length && seps.includes(prefixTrim[prefixTrim.length - 1])) prefixTrim = prefixTrim.slice(0, -1);\n      const prefixEnd = titleMatch.start + prefixTrim.length;\n      const latinStart = titleMatch.start + latinOffset;\n      if (prefixEnd <= titleMatch.start) continue;\n      toRemove.push(titleMatch);\n      toAppend.push(new Match(titleMatch.start, prefixEnd, {\n        name: 'alternative_title',\n        value: cleanup(input.slice(titleMatch.start, prefixEnd)),\n        inputString: input,\n      }));\n      toAppend.push(new Match(latinStart, titleMatch.end, {\n        name: 'title',\n        tags: ['title'],\n        value: cleanup(input.slice(latinStart, titleMatch.end)),\n        inputString: input,\n      }));\n    }\n    return (toRemove.length || toAppend.length) ? [toRemove, toAppend] : false;\n  }\n}\n\n/**\n * A title ending in a bare season word right before a season match (\"Skins\n * Season S01-S07\") carries the marker word into the title — crop it (cross-parser\n * corpus; mirrors the episode-marker-word cleanup on episode_title).\n */\nclass TrimSeasonWordFromTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override priority = POST_PROCESS;\n  override consequence = [RemoveMatch, AppendMatch];\n\n  override when(matches: Matches, context: Context): any {\n    if (isDisabled(context, 'title')) return false;\n    const input: string = (matches as any).inputString ?? '';\n    const toRemove: Match[] = [];\n    const toAppend: Match[] = [];\n    for (const title of (matches.named('title') as Match[]) ?? []) {\n      const m = /^(.*\\S)[\\s._-]+(seasons?|saison)$/i.exec(String(title.value ?? ''));\n      if (!m) continue;\n      const next = matches.range(title.end, (input.length), (mm: Match) => !mm.private && !!mm.value, 0) as Match | undefined;\n      if (!next || next.name !== 'season') continue;\n      toRemove.push(title);\n      const rawHead = input.slice(title.start, title.end).slice(0, m[1].length + (String(title.value).length === (title.end - title.start) ? 0 : 0));\n      // recompute end by scanning: shrink until cleaned value equals m[1]\n      let newEnd = title.end;\n      while (newEnd > title.start && cleanup(input.slice(title.start, newEnd)).toLowerCase() !== m[1].toLowerCase()) newEnd--;\n      if (newEnd <= title.start) continue;\n      toAppend.push(new Match(title.start, newEnd, {\n        name: 'title', value: cleanup(input.slice(title.start, newEnd)), inputString: input,\n      }));\n    }\n    return (toRemove.length || toAppend.length) ? [toRemove, toAppend] : false;\n  }\n}\n\n/**\n * A short junk word before a leading anime bracket (\"EvoBot.[Watakushi]_Akuma…\",\n * upstream #877 B2) steals the title position. When a single-word title opens the\n * filepart, an anime release-group bracket follows it, and ANOTHER title sits\n * after the bracket, the pre-bracket word is junk — keep the post-bracket title.\n */\nclass PreBracketJunkTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, context: Context): any {\n    if (isDisabled(context, 'title')) return false;\n    const input: string = (matches as any).inputString ?? '';\n    const toRemove: Match[] = [];\n    for (const filepart of matches.markers.named('path') as Match[]) {\n      const titles = ((matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'title') as Match[]) ?? [])\n        .sort((a, b) => a.start - b.start);\n      if (titles.length < 2) continue;\n      const first = titles[0];\n      if (first.start !== filepart.start) continue;\n      if (/[\\s._-]/.test(String(first.value ?? '').trim())) continue; // single word only\n      const group = matches.markers.range(first.end, filepart.end, (m: Match) => m.name === 'group', 0) as Match | undefined;\n      if (!group || group.start >= titles[1].start) continue;\n      if (![...input.slice(first.end, group.start)].every((c) => seps.includes(c))) continue;\n      const rg = matches.range(group.start, group.end,\n        (m: Match) => m.name === 'release_group' && !!m.tags?.includes('anime'), 0);\n      if (!rg) continue;\n      toRemove.push(first);\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\n/**\n * Fully-bracketed fansub names have no unbracketed run to use as a title\n * (\"[FuktLogik][Sayonara_Zetsubou_Sensei][01][DVDRip]\", upstream #877 B2): the\n * first bracket whose content is plain words (not a claimed release group, not a\n * matched property, not a number) becomes the title. When no such bracket exists\n * and the leading bracket was claimed as the release group with nothing wordy\n * left outside (\"[Keroro].148.\"), the group name itself is the title.\n */\nclass BracketedTitleFallback extends Rule {\n  static override priority = POST_PROCESS;\n  override priority = POST_PROCESS;\n  override consequence = [RemoveMatch, AppendMatch];\n\n  override when(matches: Matches, context: Context): any {\n    if (isDisabled(context, 'title')) return false;\n    const input: string = (matches as any).inputString ?? '';\n    const toRemove: Match[] = [];\n    const toAppend: Match[] = [];\n    for (const filepart of matches.markers.named('path') as Match[]) {\n      // A symbol-only \"title\" (★ between fullwidth brackets) does not count.\n      const titlesHere = (matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'title') as Match[]) ?? [];\n      const realTitle = titlesHere.find((t) => /[\\p{L}\\p{N}]/u.test(String(t.value ?? '')));\n      if (realTitle) continue;\n      toRemove.push(...titlesHere);\n      const groups = (matches.markers.range(filepart.start, filepart.end, (m: Match) => m.name === 'group') as Match[]) ?? [];\n      if (!groups.length) continue;\n      const rg = matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'release_group', 0) as Match | undefined;\n      let candidate: Match | undefined;\n      for (const g of groups) {\n        if (rg && g.start <= rg.start && g.end >= rg.end) continue;\n        const core = input.slice(g.start + 1, g.end - 1);\n        if (!/[a-zA-Z]{2,}/.test(core)) continue;\n        // A bracket fully claimed as an episode_title/alternative_title is really\n        // the missing series title (\"【Golden Time】[24…]\") — reclaim it.\n        const softInner = (matches.range(g.start, g.end,\n          (m: Match) => !m.private && ['episode_title', 'alternative_title'].includes(m.name ?? '')) as Match[]) ?? [];\n        const hardInner = (matches.range(g.start, g.end,\n          (m: Match) => !m.private && !['episode_title', 'alternative_title'].includes(m.name ?? '')) as Match[]) ?? [];\n        if (softInner.length && !hardInner.length) {\n          toRemove.push(...softInner);\n          candidate = new Match(g.start + 1, g.end - 1, {\n            name: 'title',\n            value: cleanup(input.slice(g.start + 1, g.end - 1)),\n            inputString: input,\n          });\n          break;\n        }\n        // The bracket may carry property matches (\"[… HD REMASTER]\") — the\n        // unmatched hole inside it is the title candidate.\n        const hole = matches.holes(g.start + 1, g.end - 1, {\n          formatter: cleanup, predicate: (h: Match) => !!h.value, index: 0,\n        }) as Match | undefined;\n        if (!hole || !/[a-zA-Z]{3,}/.test(String(hole.value ?? ''))) continue;\n        candidate = hole;\n        break;\n      }\n      if (candidate) {\n        candidate.name = 'title';\n        toAppend.push(candidate);\n        continue;\n      }\n      // No wordy bracket left: a lone claimed group with only numbers/properties\n      // outside means the \"group\" is really the title.\n      if (rg && rg.tags?.includes('anime')) {\n        const outside = input.slice(filepart.start, filepart.end)\n          .replace(input.slice(rg.start - 1 >= filepart.start ? rg.start - 1 : rg.start, Math.min(rg.end + 1, filepart.end)), '');\n        const outsideMatches = (matches.range(filepart.start, filepart.end,\n          (m: Match) => !m.private && m.name !== 'release_group' && m.start >= filepart.start) as Match[]) ?? [];\n        const wordyOutside = /[a-zA-Z]{2,}/.test(outside.replace(/\\b(mkv|avi|mp4)\\b/gi, '')) &&\n          outsideMatches.some((m) => ['title', 'episode_title', 'alternative_title'].includes(m.name ?? ''));\n        if (!wordyOutside) {\n          toRemove.push(rg);\n          toAppend.push(new Match(rg.start, rg.end, {\n            name: 'title',\n            value: cleanup(input.slice(rg.start, rg.end)),\n            inputString: input,\n          }));\n        }\n      }\n    }\n    return (toRemove.length || toAppend.length) ? [toRemove, toAppend] : false;\n  }\n}\n\n/**\n * A part written as a WORD numeral before the year/episode anchor is title text:\n * \"Dune.Part.Two.2024\" → title \"Dune Part Two\" (cross-parser corpus). A digit\n * part (\"Part 2\") and any part after the anchor stay the property.\n */\nclass WordNumeralPartAtTitlePosition extends Rule {\n  static override priority = 64;\n  override priority = 64;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, context: Context): Match[] | false {\n    if (isDisabled(context, 'part')) return false;\n    const toRemove: Match[] = [];\n    for (const part of (matches.named('part') as Match[]) ?? []) {\n      const target = part.initiator ?? part;\n      if (/\\d/.test(String(target.raw ?? ''))) continue; // digit parts stay\n      const filepart = matches.markers.atMatch(part, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      const anchor = matches.range(part.end, filepart.end,\n        (m: Match) => !m.private && ['year', 'season', 'episode', 'date'].includes(m.name ?? ''), 0) as Match | undefined;\n      if (!anchor) continue;\n      toRemove.push(part);\n      for (const c of [...(target.children ?? [])] as Match[]) if (!toRemove.includes(c)) toRemove.push(c);\n      if (target !== part && !toRemove.includes(target)) toRemove.push(target);\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\n/**\n * A bonus marker (\"x365\") glued into an anime title before the episode anchor is\n * title text: \"[SpoonSubs] Hidamari Sketch x365 - 04 …\" (cross-parser corpus).\n * Only under an anime signal (bracket release group / CRC32) and only before the\n * anchor — a real bonus (\"Movie x02 …\") after the anchor stays.\n */\nclass BonusAtTitlePositionRule extends Rule {\n  static override priority = 64;\n  override priority = 64;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, context: Context): Match[] | false {\n    if (isDisabled(context, 'bonus')) return false;\n    const toRemove: Match[] = [];\n    for (const bonus of (matches.named('bonus') as Match[]) ?? []) {\n      const filepart = matches.markers.atMatch(bonus, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      const anime =\n        matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'crc32', 0) ||\n        (matches.markers.range(filepart.start, filepart.end,\n          (m: Match) => m.name === 'group' && m.start === filepart.start, 0));\n      if (!anime) continue;\n      const anchor = matches.range(bonus.end, filepart.end,\n        (m: Match) => !m.private && ['episode', 'season', 'year', 'date'].includes(m.name ?? ''), 0) as Match | undefined;\n      const bonusTitles = (matches.named('bonus_title') as Match[]) ?? [];\n      if (!anchor && !bonusTitles.length) continue;\n      toRemove.push(bonus);\n      toRemove.push(...bonusTitles.filter((bt) => bt.start >= filepart.start && bt.end <= filepart.end));\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\n/**\n * A short Titlecase language code inside an anime title zone is a title word:\n * \"Bokura Ga Ita\" (Ita ≠ Italian), \"Ro-Kyu-Bu!\" (Ro ≠ Romanian). Scoped to a\n * leading bracket-group filepart and the pre-anchor zone.\n */\nclass LanguageWordInAnimeTitle extends Rule {\n  static override priority = 64;\n  override priority = 64;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, context: Context): Match[] | false {\n    if (isDisabled(context, 'language')) return false;\n    const toRemove: Match[] = [];\n    for (const lang of (matches.named('language') as Match[]) ?? []) {\n      const raw = String(lang.raw ?? '');\n      if (raw.length > 3 || !/^[A-Z][a-z]{0,2}$/.test(raw)) continue;\n      const filepart = matches.markers.atMatch(lang, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      const leadingBracket = matches.markers.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'group' && m.start === filepart.start, 0);\n      if (!leadingBracket) continue;\n      const anchor = matches.range(lang.end, filepart.end,\n        (m: Match) => !m.private && ['episode', 'season', 'year', 'date'].includes(m.name ?? ''), 0);\n      if (!anchor) continue;\n      toRemove.push(lang);\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\nclass PropertyAtTitlePositionAsTitle extends Rule {\n  static override priority = -48;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: Context): Match[] | false {\n    const inp = (matches as any).inputString || '';\n    const out: Match[] = [];\n    for (const filepart of matches.markers.named('path') as Match[]) {\n      const lead = matches.range(filepart.start, filepart.end, (m: Match) => !m.private && !!m.value, 0) as Match | undefined;\n      if (!lead) continue;\n      // The anchor is the first year/season/episode/date AFTER the lead (a leading\n      // year must not anchor itself: \"1923 S02E01\" anchors on the season).\n      const anchor = matches.range(lead.end, filepart.end,\n        (m: Match) => !m.private && ['year', 'season', 'episode', 'date'].includes(m.name ?? ''), 0) as Match | undefined;\n      // A lone leading year with nothing else title-like is itself the title\n      // (\"2012.AC3.720p.BluRay\", cross-parser corpus).\n      if (!anchor) {\n        const anyTitle = matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'title', 0);\n        if (lead.name === 'year' && lead.start === filepart.start && !anyTitle) {\n          lead.name = 'title';\n          (lead as any).value = String((matches as any).inputString ?? '').slice(lead.start, lead.end);\n          out.push(lead);\n          continue;\n        }\n        continue;\n      }\n      // A leading year with a season/episode anchor after it is a year-titled show\n      // (\"1923 S02E01\" → title 1923, cross-parser corpus).\n      const yearTitled = lead.name === 'year' && ['season', 'episode'].includes(anchor.name ?? '') &&\n        !anchor.tags?.includes('weak-episode') && !anchor.tags?.includes('weak-duplicate');\n      if (!yearTitled && !['other', 'country', 'edition'].includes(lead.name ?? '')) continue;\n      // Existing titles block the conversion unless they sit in the release zone\n      // after the anchor (a dash-group name mistaken for the title).\n      const titles = (matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'title') as Match[]) ?? [];\n      if (titles.some((t) => t.start < anchor.end)) continue;\n      if (titles.length && !yearTitled) continue;\n      out.push(...titles);\n      // A canonical spelling (\"Extended\", \"Proper\", \"US\") is a deliberate tag and stays the\n      // property; only a case-divergent spelling (\"xXx\" vs XXX, \"Us\" vs US) reads as a title.\n      if (lead.name !== 'year' && (lead.raw ?? '') === String(lead.value ?? '')) continue;\n      if (![...inp.slice(filepart.start, lead.start)].every((c: string) => seps.includes(c))) continue;\n      out.push(lead);\n    }\n    return out.length ? out : false;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: Context): void {\n    const inp = (matches as any).inputString || '';\n    for (const lead of whenResponse as Match[]) {\n      matches.remove(lead);\n      const t = new Match(lead.start, lead.end, {\n        name: 'title',\n        value: cleanup(inp.slice(lead.start, lead.end)),\n        inputString: inp,\n      });\n      matches.append(t);\n    }\n  }\n}\n\n/**\n * An `alternative_title` whose raw text is purely numeric (digits plus range\n * separators / spaces) next to a detected episode is never a real alt-title —\n * it is the episode number that leaked across a `-` separator (e.g.\n * \"Show.Name.-.07.(2016)\" → episode 7 + alt \"07\"; \"...-.476-479...\" → alt\n * \"476-479\"). Drop it so only the genuine title survives. (Python keeps just the\n * episode here.) Note: numeric *episode_title*s are NOT dropped — \"24\",\n * \"18-5-4\", \"0.8.4.\" are genuine episode titles that Python also keeps.\n */\nclass RemoveNumericAlternativeTitle extends Rule {\n  static override priority = -64;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: Context): Match[] | false {\n    const alts = matches.named('alternative_title') as Match[] | Match | undefined;\n    const altArr = Array.isArray(alts) ? alts : alts ? [alts] : [];\n    if (!altArr.length) return false;\n    const out: Match[] = [];\n    for (const alt of altArr) {\n      const raw = String(alt.raw ?? alt.value ?? '');\n      if (!/^[\\d\\s.~_-]+$/.test(raw) || !/\\d/.test(raw)) continue;\n      const filepart = matches.markers.atMatch(alt, (m) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      const hasEpisode = matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'episode' || m.name === 'absolute_episode', 0);\n      if (hasEpisode) out.push(alt);\n    }\n    return out.length ? out : false;\n  }\n}\n\n/**\n * An `alternative_title` that begins after the year AND has a recognised release\n * property (resolution, source, codec, edition, country, …) sitting *between* the\n * year and the alt-title is a stray fragment from the release tail — a label,\n * region or edition word that fell into a later hole (e.g.\n * \"Heathers.1988.1080p.BluRay.ARROW…\" → alt \"ARROW\" after 1080p/BluRay;\n * \"…1975.Criterion.Collection…\" → alt \"Collection\" after edition Criterion;\n * \"…1946.US.(Kino.Classics)…\" → alt \"Kino Classics\" after country US). Drop it.\n *\n * A genuine alt-title is *contiguous* with the year (nothing but separators\n * between them, e.g. \"Show.Name.2015.Nice.Title.1080p\" → alt \"Nice Title\";\n * \"London.2012.Olympics.CTV.Preview.Show.HDTV\" → alt \"Olympics CTV Preview\n * Show\") — Python keeps those, so we leave them alone.\n */\nclass RemoveTailAlternativeTitle extends Rule {\n  // Tail episode_titles become alternative_title in RenameEpisodeTitleWhenMovieType\n  // (POST_PROCESS); run after it so we see the renamed matches.\n  static override priority = POST_PROCESS;\n  static override dependency = ['RenameEpisodeTitleWhenMovieType'];\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: Context): Match[] | false {\n    const alts = matches.named('alternative_title') as Match[] | Match | undefined;\n    const altArr = Array.isArray(alts) ? alts : alts ? [alts] : [];\n    if (!altArr.length) return false;\n    const titleish = new Set(['year', 'title', 'alternative_title', 'episode_title', 'type']);\n    const out: Match[] = [];\n    for (const alt of altArr) {\n      const filepart = matches.markers.atMatch(alt, (m) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      const years = matches.range(filepart.start, filepart.end, (m: Match) => m.name === 'year') as Match[] | Match | undefined;\n      const yearArr = Array.isArray(years) ? years : years ? [years] : [];\n      if (!yearArr.length) continue;\n      const yMax = Math.max(...yearArr.map((y) => y.end));\n      if (alt.start < yMax) continue;\n      // Keep alt-titles that are contiguous with the year; drop only those that\n      // sit behind another recognised property in the release tail.\n      const between = matches.range(yMax, alt.start,\n        (m: Match) => !m.private && !!m.value && !titleish.has(m.name ?? ''), 0);\n      if (between) out.push(alt);\n    }\n    return out.length ? out : false;\n  }\n}\n\n/**\n * guessit-js can produce several `title` matches in one filepart (one per hole),\n * leaving `title` as a list ([\"The Arrival\",\"MadVR\"], [\"Show-A\",\"Episode Title\"],\n * [\"Show Name\",\"and\",\"Blah-Group\"]). Python returns a single title. When the\n * primary (first) title is a real title — not a lone stop-word — drop the later\n * title fragments that sit *behind* a recognised property in the release tail,\n * exactly as RemoveTailAlternativeTitle does for alt-titles. The first title is\n * kept. Filepart whose first title is itself a stop-word (e.g. \"From [tracker] -\n * Real.Title\") is left alone — there the real title is the *later* one.\n */\nclass RemoveTailTitle extends Rule {\n  static override priority = POST_PROCESS;\n  static override dependency = ['RenameEpisodeTitleWhenMovieType'];\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: Context): Match[] | false {\n    const titleish = new Set(['year', 'title', 'alternative_title', 'episode_title', 'type']);\n    const out: Match[] = [];\n    for (const filepart of matches.markers.named('path') as Match[]) {\n      const titles = (matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'title') as Match[] | Match | undefined);\n      const titleArr = (Array.isArray(titles) ? titles : titles ? [titles] : [])\n        .slice().sort((a, b) => a.start - b.start);\n      if (titleArr.length < 2) continue;\n      const primary = titleArr[0];\n      const head = String(primary.value ?? '').trim().toLowerCase();\n      if (!head) continue;\n      if (TITLE_STOP_WORDS.has(head)) {\n        // Stop-word-first (\"From [tracker] - Real.Title\"): the real title is the\n        // later one — drop the leading stop-word title instead.\n        if (titleArr.slice(1).some((t) => !TITLE_STOP_WORDS.has(String(t.value ?? '').trim().toLowerCase()))) {\n          out.push(primary);\n        }\n        continue;\n      }\n      for (const t of titleArr.slice(1)) {\n        const between = matches.range(primary.end, t.start,\n          (m: Match) => !m.private && !!m.value && !titleish.has(m.name ?? ''), 0);\n        if (between) out.push(t);\n      }\n    }\n    return out.length ? out : false;\n  }\n}\n\nexport function title(config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk({\n    disabled: (context: Context) => isDisabled(context, 'title'),\n  });\n\n  rebulk.rules(CountryAtTitlePosition, TitleWordAtTitlePosition, WordNumeralPartAtTitlePosition, BonusAtTitlePositionRule, LanguageWordInAnimeTitle, SplitOriginalScriptTitle, TitleFromPosition, PreferTitleWithYear, ExtendLoneArticleTitle, PropertyAtTitlePositionAsTitle, RemoveNumericAlternativeTitle, RemoveTailAlternativeTitle, RemoveTailTitle, BracketedTitleFallback, PreBracketJunkTitle, TrimSeasonWordFromTitle);\n\n  // Expected title functional pattern\n  const expectedTitle = buildExpectedFunction('expected_title');\n  rebulk.functional(expectedTitle, {\n    name: 'title',\n    tags: ['expected', 'title'],\n    validator: sepsSurround,\n    formatter: formatters(cleanup, reorderTitle),\n    conflictSolver: (match, other) => other,\n    disabled: (context: Context) => !(context?.['expected_title'] as boolean | undefined),\n  });\n\n  return rebulk;\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Rule, AppendMatch, RemoveMatch } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport type { Matches } from 'rebulk-js';\nimport { POST_PROCESS } from 'rebulk-js';\nimport { seps, titleSeps, sepsPattern } from '../common/index.js';\nimport { cleanup, reorderTitle } from '../common/formatters.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { or_ } from '../common/validators.js';\nimport { formatters } from 'rebulk-js';\n\n/** Helper: truthy check for match result (handles empty arrays correctly) */\nfunction hasmatch(result: Match[] | Match | undefined): boolean {\n  if (result === null || result === undefined) return false;\n  if (Array.isArray(result)) return result.length > 0;\n  return true;\n}\n\n/** Strip leading articles for title comparison */\nconst LEADING_ARTICLES_RE = /^(the|a|an|le|la|les|l'|el|los|las|der|die|das)\\s+/i;\nfunction normalizeTitle(s: string): string {\n  return s.toLowerCase().replace(LEADING_ARTICLES_RE, '').trim();\n}\n\n/**\n * A dash-joined digit run after an SxxExx chain that spills into a numeric\n * episode_title (\"S03E03.4-5-1\" → episodes [3,4,5] + episode_title \"1\") is a\n * formation/score, not an episode range (upstream #744): drop the continuation\n * episodes and keep the whole run as the episode title (\"4-5-1\").\n */\nclass FormationRunEpisodeTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override priority = POST_PROCESS;\n  override consequence = [RemoveMatch, AppendMatch];\n\n  override when(matches: any, _context: any): any {\n    const input: string = matches.inputString ?? '';\n    const toRemove: any[] = [];\n    const toAppend: any[] = [];\n    const ets = (matches.named('episode_title') as any[]) ?? [];\n    for (const et of ets) {\n      if (!/^\\d{1,2}$/.test(String(et.value ?? ''))) continue;\n      const eps = ((matches.named('episode') as any[]) ?? [])\n        .filter((e: any) => e.end <= et.start && !e.private)\n        .sort((a: any, b: any) => a.start - b.start);\n      if (eps.length < 3) continue;\n      // continuation episodes = those after the first, glued to the et by dashes\n      const run = eps.slice(1);\n      const runStart = run[0].start;\n      const span = input.slice(runStart, et.end);\n      if (!/^\\d{1,3}(-\\d{1,3})+$/.test(span)) continue;\n      // the run must hang off the strong chain via a weak separator ('.', ' ')\n      const between = input.slice(eps[0].end, runStart);\n      if (!/^[\\s._]+$/.test(between)) continue;\n      toRemove.push(...run, et);\n      toAppend.push(new Match(runStart, et.end, {\n        name: 'episode_title',\n        value: span,\n        inputString: input,\n      }));\n    }\n    return (toRemove.length || toAppend.length) ? [toRemove, toAppend] : false;\n  }\n}\n\nexport function episodeTitle(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'episode_title') });\n  rebulk.rules(\n    RemoveConflictsWithEpisodeTitle,\n    TitleToEpisodeTitle,\n    ExtendEpisodeTitleWithDetails,\n    EpisodeTitleFromPosition,\n    AlternativeTitleReplace,\n    TrimLanguageFromEpisodeTitle,\n    Filepart3EpisodeTitle,\n    Filepart2EpisodeTitle,\n    NumericEpisodeTitleToEpisode,\n    RemoveEpisodeTitleInReleaseGroup,\n    RemoveEpisodeMarkerWordTitle,\n    RemoveEpisodeTitleCoveredByDetailsInGroup,\n    RemoveFansubCreditEpisodeTitle,\n    RemoveSubtitleDescriptorEpisodeTitle,\n    RemoveHashFilepartJunk,\n    RemoveTailEpisodeTitle,\n    FormationRunEpisodeTitle,\n    RenameEpisodeTitleWhenMovieType\n  );\n\n  return rebulk;\n}\n\n/**\n * An `episode_title` that is a bare episode-marker word (\"Ep\", \"Episode\", \"Cap\",\n * …) sitting immediately before the episode number is the marker that leaked, not\n * a title — e.g. \".../Ep. 02 - Soul Hunter\" → episode_title [\"Ep\",\"Soul Hunter\"].\n * Python keeps only the real title; drop the marker word.\n */\nconst EPISODE_MARKER_WORDS = new Set([\n  'ep', 'eps', 'episode', 'episodes', 'episodio', 'episodios', 'cap', 'capitulo',\n  'capitulos', 'folge', 'e',\n]);\nclass RemoveEpisodeMarkerWordTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: any): Match[] | false {\n    const ets = matches.named('episode_title') as Match[] | Match | undefined;\n    const etArr = Array.isArray(ets) ? ets : ets ? [ets] : [];\n    if (!etArr.length) return false;\n    const out: Match[] = [];\n    for (const et of etArr) {\n      if (!EPISODE_MARKER_WORDS.has(String(et.value ?? '').trim().toLowerCase())) continue;\n      const next = matches.range(et.end, (matches as any).inputString?.length ?? et.end + 100,\n        (m: Match) => !m.private && !!m.value, 0) as Match | undefined;\n      if (next && next.name === 'episode') out.push(et);\n    }\n    return out.length ? out : false;\n  }\n}\n\n/**\n * An \"-Obfuscated\" / scene rename leaves the file in a directory whose last part\n * is a bare hash — \"…-MeGusta-Obfuscated/afaae96ae7a140e0981ced2a79221751.mkv\",\n * \"…-TVSmash/mxNMuJWeO7PUWCMEwqKSsS6D8Vs9S6V3PHD.mkv\". guessit-js mines the hash\n * for junk (hex chunks → episode_title; \"V3\" → version). Python extracts nothing\n * from it (the real data lives in the parent part). When a filepart's content is\n * a single high-entropy hash token, strip episode_title / version / episode_details\n * / alternative_title matches found inside it.\n */\nclass RemoveHashFilepartJunk extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  private static isHash(token: string): boolean {\n    if (/[\\s._\\-]/.test(token)) return false;          // a hash is one unbroken token\n    if (/^[0-9a-f]{16,}$/i.test(token)) return true;   // pure hex (CRC/md5-like)\n    return token.length >= 24 && /[a-z]/.test(token) && /[A-Z]/.test(token) && /\\d/.test(token);\n  }\n\n  override when(matches: Matches, _context: any): Match[] | false {\n    const inp: string = (matches as any).inputString ?? '';\n    const strip = new Set(['episode_title', 'version', 'episode_details', 'alternative_title']);\n    const out: Match[] = [];\n    for (const fp of matches.markers.named('path') as Match[]) {\n      let text = inp.slice(fp.start, fp.end);\n      const cont = matches.range(fp.start, fp.end, (m: Match) => m.name === 'container', 0) as Match | undefined;\n      if (cont) text = inp.slice(fp.start, cont.start);\n      if (!RemoveHashFilepartJunk.isHash(text.replace(/[.\\s]+$/, ''))) continue;\n      for (const m of matches.range(fp.start, fp.end, (m: Match) => strip.has(m.name ?? '')) as Match[]) {\n        out.push(m);\n      }\n    }\n    return out.length ? out : false;\n  }\n}\n\n/**\n * An `episode_title` fully covered by an `episode_details` *inside a bracket\n * group* is a duplicate of that detail, not a title — e.g. \"[Cap.112_114.Final]\"\n * yields both episode_details \"Final\" and episode_title \"Final\". Python keeps only\n * the detail. The bracket-group guard is what separates this from bare\n * \"S01E01.Pilot\" / \"…2014.Special\" where the detail word IS the episode title and\n * Python keeps the episode_title (those are never inside a metadata bracket).\n */\nclass RemoveEpisodeTitleCoveredByDetailsInGroup extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: any): Match[] | false {\n    const ets = matches.named('episode_title') as Match[] | Match | undefined;\n    const etArr = Array.isArray(ets) ? ets : ets ? [ets] : [];\n    const out: Match[] = [];\n    for (const et of etArr) {\n      if (!matches.markers.atMatch(et, (m: Match) => m.name === 'group', 0)) continue;\n      const covered = matches.range(et.start, et.end,\n        (m: Match) => m.name === 'episode_details' && m.start <= et.start && m.end >= et.end, 0);\n      if (covered) out.push(et);\n    }\n    return out.length ? out : false;\n  }\n}\n\n/**\n * An `episode_title` containing the word \"fansub\" is a fan-subbing group credit,\n * not a title — e.g. \"Show Name 445 VOSTFR par Fansub-Resistance …\" →\n * episode_title \"par Fansub-Resistance\" (\"by Fansub-Resistance\"). Drop it.\n */\nclass RemoveFansubCreditEpisodeTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: any): Match[] | false {\n    const ets = matches.named('episode_title') as Match[] | Match | undefined;\n    const etArr = Array.isArray(ets) ? ets : ets ? [ets] : [];\n    const out = etArr.filter((et) => /\\bfansub/i.test(String(et.value ?? '')));\n    return out.length ? out : false;\n  }\n}\n\n/**\n * A single-word `episode_title` immediately followed by a subtitle keyword\n * (\"Subtitles\"/\"Subs\") is a subtitle-type descriptor, not a title — e.g.\n * \"…Eng.Soft.Subtitles.720p…\" → episode_title \"Soft\" (\"soft subtitles\"). Python\n * forms no episode_title there; drop it.\n */\nclass RemoveSubtitleDescriptorEpisodeTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: any): Match[] | false {\n    const inp: string = (matches as any).inputString ?? '';\n    const ets = matches.named('episode_title') as Match[] | Match | undefined;\n    const etArr = Array.isArray(ets) ? ets : ets ? [ets] : [];\n    const out: Match[] = [];\n    for (const et of etArr) {\n      if (/[\\s.]/.test(String(et.value ?? '').trim())) continue; // single word only\n      const after = inp.slice(et.end).replace(/^[\\s._-]+/, '');\n      if (/^subtitl(e|es)\\b|^subs?\\b/i.test(after)) out.push(et);\n    }\n    return out.length ? out : false;\n  }\n}\n\nconst ET_STOP_WORDS = new Set([\n  'the', 'a', 'an', 'and', 'or', 'of', 'to', 'in', 'on', 'at', 'for', 'from',\n  'by', 'with', 'le', 'la', 'les', 'de', 'du', 'des', 'el',\n]);\n\n/**\n * guessit-js can leave `episode_title` as a list when a stray fragment from the\n * release tail forms a second episode_title — e.g.\n * \"NHL…Condensed.Game.720p.Away.Feed.GC…\" → [\"Leafs vs Red Wings Condensed\n * Game\",\"Away Feed\"]; \"Tales S01E08 All I Need…Mary J Blige 720p BET…\" → [...,\n * \"BET\"]. Python keeps a single episode_title. Keep the primary (first) one and\n * drop later fragments that sit *behind* a recognised property in the tail.\n */\nclass RemoveTailEpisodeTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  private static readonly TITLEISH = new Set([\n    'year', 'title', 'alternative_title', 'episode_title', 'type', 'episode', 'season',\n  ]);\n\n  override when(matches: Matches, _context: any): Match[] | false {\n    const out: Match[] = [];\n    for (const fp of matches.markers.named('path') as Match[]) {\n      const ets = matches.range(fp.start, fp.end, (m: Match) => m.name === 'episode_title') as Match[] | Match | undefined;\n      const etArr = (Array.isArray(ets) ? ets : ets ? [ets] : []).slice().sort((a, b) => a.start - b.start);\n      if (etArr.length < 2) continue;\n      const primary = etArr[0];\n      const head = String(primary.value ?? '').trim().toLowerCase();\n      if (!head || ET_STOP_WORDS.has(head)) continue;\n      for (const et of etArr.slice(1)) {\n        const between = matches.range(primary.end, et.start,\n          (m: Match) => !m.private && !!m.value && !RemoveTailEpisodeTitle.TITLEISH.has(m.name ?? ''), 0);\n        if (between) out.push(et);\n      }\n    }\n    return out.length ? out : false;\n  }\n}\n\n/**\n * An `episode_title` that sits inside a bracket group which also holds release\n * metadata (resolution, codec, audio, source, …) is a stray tag, not a title —\n * e.g. \"Show Name S01e10[Mux - 1080p - H264 - Ita Eng Ac3 …]\" → episode_title\n * \"Mux\". Python forms no episode_title inside such release-info groups; drop it.\n */\nclass RemoveEpisodeTitleInReleaseGroup extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  private static readonly RELEASE_PROPS = new Set([\n    'screen_size', 'video_codec', 'audio_codec', 'audio_channels', 'source',\n    'color_depth', 'video_profile', 'audio_profile', 'streaming_service',\n    'video_bit_rate', 'audio_bit_rate', 'container',\n  ]);\n\n  override when(matches: Matches, _context: any): Match[] | false {\n    const ets = matches.named('episode_title') as Match[] | Match | undefined;\n    const etArr = Array.isArray(ets) ? ets : ets ? [ets] : [];\n    if (!etArr.length) return false;\n    const out: Match[] = [];\n    const inp: string = (matches as any).inputString ?? '';\n    const hasReleaseIn = (s: number, e: number) =>\n      !!matches.range(s, e, (m: Match) => RemoveEpisodeTitleInReleaseGroup.RELEASE_PROPS.has(m.name ?? ''), 0);\n    const onlySeps = (s: number, e: number) => e <= s || [...inp.slice(s, e)].every((c) => '[](){} .-_'.includes(c));\n    for (const et of etArr) {\n      const group = matches.markers.atMatch(et, (m: Match) => m.name === 'group', 0) as Match | undefined;\n      if (!group) continue;\n      // Release props inside the episode_title's own bracket, OR in an\n      // immediately-adjacent bracket (a run of metadata brackets like\n      // \"[LQ][h264][720p]\") — in either case the token is a tag, not a title.\n      let tag = hasReleaseIn(group.start, group.end);\n      if (!tag) {\n        for (const other of matches.markers.named('group') as Match[]) {\n          if (other.span?.[0] === group.span?.[0]) continue;\n          const adjacent = (other.start >= group.end && onlySeps(group.end, other.start)) ||\n            (other.end <= group.start && onlySeps(other.end, group.start));\n          if (adjacent && hasReleaseIn(other.start, other.end)) { tag = true; break; }\n        }\n      }\n      if (tag) out.push(et);\n    }\n    return out.length ? out : false;\n  }\n}\n\n/**\n * A purely-numeric episode_title in a filepart that has a season but NO episode\n * is really the episode number — the anime \"S2 - 01\" convention, where \"01\"\n * after the dash is the episode, not an episode_title. (Issue #667.)\n */\nclass NumericEpisodeTitleToEpisode extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  override when(matches: Matches, _context: any): Match[] | false {\n    const out: Match[] = [];\n    for (const fp of matches.markers.named('path') as Match[]) {\n      if (matches.range(fp.start, fp.end, (m: Match) => m.name === 'episode' && !m.private, 0)) continue;\n      if (!matches.range(fp.start, fp.end, (m: Match) => m.name === 'season' && !m.private, 0)) continue;\n      const ets = matches.range(fp.start, fp.end, (m: Match) => m.name === 'episode_title') as Match[] | Match | undefined;\n      for (const et of (Array.isArray(ets) ? ets : ets ? [ets] : [])) {\n        if (/^\\d{1,3}$/.test(String(et.value ?? '').trim())) out.push(et);\n      }\n    }\n    return out.length ? out : false;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: any): void {\n    for (const et of whenResponse as Match[]) {\n      matches.remove(et);\n      et.name = 'episode';\n      et.value = parseInt(String(et.value).trim(), 10);\n      matches.append(et);\n    }\n  }\n}\n\nclass RemoveConflictsWithEpisodeTitle extends Rule {\n  static override priority = 64;\n  override consequence = RemoveMatch;\n\n  previousNames = ['episode', 'episode_count', 'season', 'season_count', 'date', 'title', 'year'];\n  nextNames = ['streaming_service', 'screen_size', 'source', 'video_codec', 'audio_codec', 'other', 'container'];\n  affectedIfHolesAfter = ['part'];\n  affectedNames = ['part', 'year'];\n\n  override when(matches: Matches, _context: any): Match[] {\n    const toRemove: Match[] = [];\n    const fileparts = matches.markers.named('path') as Match[];\n    for (const filepart of fileparts) {\n      const affectedMatches = matches.range(filepart.start, filepart.end,\n        (m: Match) => this.affectedNames.includes(m.name ?? '')) as Match[];\n      for (const match of affectedMatches) {\n        const before = matches.range(filepart.start, match.start,\n          (m: Match) => !m.private, -1) as Match | undefined;\n        if (!before || !this.previousNames.includes(before.name ?? '')) {\n          continue;\n        }\n        // Don't remove year when the preceding match is only a weak episode\n        // (e.g. \"12.Angry.Men.1957.mkv\" — the \"12\" is a weak episode, 1957 is a real year).\n        if ((before as any).tags?.includes('weak-episode') || (before as any).tags?.includes('weak-duplicate')) {\n          continue;\n        }\n\n        // Don't remove year when it's inside a group (parentheses/brackets)\n        // e.g. \"(the.oscars.of.1963)\" — the year is significant, not part of episode title\n        if (match.name === 'year') {\n          const yearGroup = matches.markers.atMatch(match,\n            (m: Match) => m.name === 'group', 0) as Match | undefined;\n          if (yearGroup) continue;\n        }\n\n        const after = matches.range(match.end, filepart.end,\n          (m: Match) => !m.private, 0) as Match | undefined;\n        if (!after || !this.nextNames.includes(after.name ?? '')) {\n          continue;\n        }\n\n        const group = matches.markers.atMatch(match,\n          (m: Match) => m.name === 'group', 0) as Match | undefined;\n\n        const hasValueInSameGroup = (m: Match) =>\n          !!(m.value && String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')) &&\n          group === matches.markers.atMatch(m, (mm: Match) => mm.name === 'group', 0);\n\n        const holesBefore = matches.holes(before.end, match.start, { predicate: hasValueInSameGroup });\n        const holesAfter = matches.holes(match.end, after.start, { predicate: hasValueInSameGroup });\n\n        const hasHolesBefore = hasmatch(holesBefore);\n        const hasHolesAfter = hasmatch(holesAfter);\n\n        if (!hasHolesBefore && !hasHolesAfter) {\n          continue;\n        }\n\n        if (this.affectedIfHolesAfter.includes(match.name ?? '') && !hasHolesAfter) {\n          continue;\n        }\n\n        toRemove.push(match);\n        if ((match as any).parent) {\n          toRemove.push((match as any).parent);\n        }\n      }\n    }\n\n    return toRemove;\n  }\n}\n\nclass TitleToEpisodeTitle extends Rule {\n  static override dependency = ['TitleFromPosition'];\n\n  override when(matches: Matches, _context: any): Match[] {\n    const titles = matches.named('title') as Match[];\n    const titleGroups: Record<string, Match[]> = {};\n    for (const title of titles) {\n      const key = String(title.value);\n      titleGroups[key] = titleGroups[key] || [];\n      titleGroups[key].push(title);\n    }\n\n    const episodeTitles: Match[] = [];\n    if (Object.keys(titleGroups).length < 2) {\n      return episodeTitles;\n    }\n\n    // Work around rebulk-js previous() bug: use range() to find\n    // preceding episode/season/date/year matches within the same filepart.\n    const epNames = new Set(['episode', 'season', 'date', 'year']);\n    const findPrevEpisode = (title: Match): Match | undefined => {\n      const filepart = matches.markers.atMatch(title, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) return undefined;\n      const prevMatches = matches.range(filepart.start, title.start,\n        (m: Match) => !m.private && epNames.has(m.name ?? '')) as Match[];\n      const arr = Array.isArray(prevMatches) ? prevMatches : prevMatches ? [prevMatches] : [];\n      return arr.length > 0 ? arr[arr.length - 1] : undefined;\n    };\n\n    // Determine which titles are \"series titles\" (no previous episode match)\n    // so we can avoid converting article variants of them to episode_title.\n    const seriesTitleKeys = new Set<string>();\n    for (const title of titles) {\n      const prevEpisode = findPrevEpisode(title);\n      if (!prevEpisode) {\n        seriesTitleKeys.add(normalizeTitle(String(title.value)));\n      }\n    }\n\n    for (const title of titles) {\n      const prevEpisode = findPrevEpisode(title);\n      if (prevEpisode) {\n        // Only convert to episode_title if this title's normalized value\n        // differs from all series titles (handles \"The Simpsons\" vs \"Simpsons\")\n        const norm = normalizeTitle(String(title.value));\n        if (!seriesTitleKeys.has(norm)) {\n          episodeTitles.push(title);\n        }\n      }\n    }\n\n    return episodeTitles;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: any): void {\n    const episodeTitles = whenResponse as Match[];\n    for (const title of episodeTitles) {\n      matches.remove(title);\n      title.name = 'episode_title';\n      matches.append(title);\n    }\n  }\n}\n\n/**\n * Extend episode_title to include adjacent episode_details matches (e.g., \"Special\").\n * When \"Special\" appears right after an episode_title like \"Head To Tail\",\n * the title trimming logic strips it. This rule re-attaches it.\n */\nclass ExtendEpisodeTitleWithDetails extends Rule {\n  static override dependency = ['TitleToEpisodeTitle'];\n\n  override when(matches: Matches, _context: any): Array<{ et: Match; detail: Match }> | undefined {\n    const episodeTitles = matches.named('episode_title') as Match[];\n    if (!episodeTitles || episodeTitles.length === 0) return undefined;\n\n    const updates: Array<{ et: Match; detail: Match }> = [];\n\n    for (const et of episodeTitles) {\n      const inp: string = (matches as any).inputString ?? '';\n      // Look for episode_details immediately after the episode_title (with only seps between)\n      const detailMatches = matches.range(et.end, et.end + 20,\n        (m: Match) => m.name === 'episode_details') as Match[];\n      if (!detailMatches || detailMatches.length === 0) continue;\n\n      for (const detail of detailMatches) {\n        const between = inp.slice(et.end, detail.start);\n        if ([...between].every(c => seps.includes(c))) {\n          updates.push({ et, detail });\n          break;\n        }\n      }\n    }\n\n    return updates.length > 0 ? updates : undefined;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: any): void {\n    const updates = whenResponse as Array<{ et: Match; detail: Match }>;\n    if (!updates) return;\n\n    for (const { et, detail } of updates) {\n      matches.remove(et);\n      et.end = detail.end;\n      // Reset cached value so it recomputes\n      et.value = undefined as any;\n      const _ = et.value; // trigger recompute\n      matches.append(et);\n    }\n  }\n}\n\nclass EpisodeTitleFromPosition extends Rule {\n  static override dependency = ['ExtendEpisodeTitleWithDetails'];\n\n  previousNames = ['episode', 'episode_count', 'season', 'season_count', 'date', 'title', 'year'];\n\n  protected isIgnored(match: Match): boolean {\n    if (!(match.name === 'language' || match.name === 'country' || match.name === 'episode_details')) {\n      return false;\n    }\n    // Python parity: a full-word (len > 3) UPPERCASE language/country is a real\n    // token, not title filler — e.g. \"...S01E12.FRENCH.BDRip...\" must NOT pull\n    // \"FRENCH\" into the episode_title. Lowercase/short ones stay ignored.\n    const raw = match.raw ?? '';\n    if (match.end - match.start > 3 && raw !== '' && raw === raw.toUpperCase() && raw !== raw.toLowerCase()) {\n      return false;\n    }\n    return true;\n  }\n\n  override when(matches: Matches, _context: any): Match[] {\n    const toAppend: Match[] = [];\n    const fileparts = matches.markers.named('path') as Match[];\n\n    for (const filepart of fileparts) {\n      // Skip fileparts that already have an episode_title\n      const hasEpTitleInPart = hasmatch(matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'episode_title', 0));\n      if (hasEpTitleInPart) continue;\n\n      // Only look at fileparts that have a title or episode (for multi-part paths\n      // where the title may have been de-duped into a parent directory)\n      const hasTitleInPart = hasmatch(matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'title', 0));\n      const hasEpisodeInPart = hasmatch(matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'episode' && !m.private, 0));\n      if (!hasTitleInPart && !hasEpisodeInPart) continue;\n\n      // Find holes (gaps) in filepart\n      const holesResult = matches.holes(filepart.start, filepart.end, {\n        formatter: formatters(cleanup, reorderTitle),\n        ignore: (m: Match) => this.isIgnored(m),\n        predicate: (m: Match) => !!(m.value),\n      });\n      const holeArray = Array.isArray(holesResult) ? holesResult : holesResult ? [holesResult] : [];\n\n      const inp: string = (matches as any).inputString || '';\n      for (const hole of holeArray) {\n        // A parenthetical/bracket group that ALSO contains a year is metadata,\n        // typically \"(Director - YYYY)\" (e.g. \"(Michel Deville - 1983)\") — not a\n        // title. Skip it so it doesn't become an episode_title (which for movies\n        // is then renamed to alternative_title). Legit alt-title parens like\n        // \"(The Killers)\" carry no year, so they're unaffected.\n        const groupMarker = (matches.markers as any)?.atMatch?.(hole, (m: Match) => m.name === 'group', 0) as Match | undefined;\n        if (groupMarker) {\n          const yearInGroup = matches.range(groupMarker.start, groupMarker.end,\n            (m: Match) => (m.name === 'year' || m.name === 'date') && !m.private, 0) as Match | undefined;\n          if (yearInGroup) continue;\n        }\n        // Crop leading/trailing ignored (language/country/episode_details) matches\n        // out of the hole — Python's TitleBaseRule does this via should_keep, but\n        // this standalone port did not. Without it a hole that is wholly or partly\n        // a lowercase language (\"...French...\", \"...multi...\") survives as an\n        // episode_title (and is later renamed to alternative_title for movies).\n        // Only crop language/country — episode_details (\"Pilot\", \"Special\") are\n        // legitimate episode_title content and must be kept.\n        const cropName = (m: Match) => m.name === 'language' || m.name === 'country';\n        const fpLangsRaw = matches.range(filepart.start, filepart.end, (m: Match) => cropName(m)) as Match[] | Match | undefined;\n        const langArr = (Array.isArray(fpLangsRaw) ? fpLangsRaw : fpLangsRaw ? [fpLangsRaw] : []);\n        // Trim, from each edge, any region covered by a language/country match —\n        // including a match that *encloses* the edge (e.g. \"[Espanol Castellano]\"\n        // where the language spans the whole bracket around the hole).\n        let guard = 0;\n        while (guard++ < 64) {\n          let e = hole.end;\n          while (e > hole.start && seps.includes(inp[e - 1])) e--;\n          if (e <= hole.start) break;\n          const cover = langArr.find((m: Match) => m.start <= e - 1 && m.end >= e);\n          if (cover && cover.start < hole.end) { hole.end = Math.min(hole.end, cover.start); } else break;\n        }\n        guard = 0;\n        while (guard++ < 64) {\n          let s = hole.start;\n          while (s < hole.end && seps.includes(inp[s])) s++;\n          if (s >= hole.end) break;\n          const cover = langArr.find((m: Match) => m.start <= s && m.end >= s + 1);\n          if (cover && cover.end > hole.start) { hole.start = Math.max(hole.start, cover.end); } else break;\n        }\n        while (hole.start < hole.end && seps.includes(inp[hole.start])) hole.start++;\n        while (hole.end > hole.start && seps.includes(inp[hole.end - 1])) hole.end--;\n        if (hole.end <= hole.start || !hole.value) continue;\n\n        // Check there's an episode/crc32/etc. BEFORE this hole in the same filepart\n        // Work around rebulk-js previous() bug by using range()\n        const prevPred = (m: Match) => !m.private && this.previousNames.includes(m.name ?? '');\n        const prevMatches = matches.range(filepart.start, hole.start, prevPred) as Match[];\n        const prevArr = Array.isArray(prevMatches) ? prevMatches : prevMatches ? [prevMatches] : [];\n        const prevEpisode = prevArr.length > 0 ? prevArr[prevArr.length - 1] : undefined;\n\n        let prevCrc32: Match | undefined;\n        if (!prevEpisode) {\n          const crc32Matches = matches.range(filepart.start, hole.start,\n            (m: Match) => !m.private && m.name === 'crc32') as Match[];\n          const crc32Arr = Array.isArray(crc32Matches) ? crc32Matches : crc32Matches ? [crc32Matches] : [];\n          prevCrc32 = crc32Arr.length > 0 ? crc32Arr[crc32Arr.length - 1] : undefined;\n        }\n        if (!prevEpisode && !prevCrc32) continue;\n\n        hole.name = 'episode_title';\n        toAppend.push(hole);\n      }\n    }\n\n    return toAppend;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: any): void {\n    const holes = whenResponse as Match[];\n    for (const hole of holes) {\n      if (!matches.includes(hole)) {\n        matches.append(hole);\n      }\n    }\n  }\n}\n\nclass AlternativeTitleReplace extends Rule {\n  static override dependency = ['EpisodeTitleFromPosition'];\n\n  previousNames = ['episode', 'episode_count', 'season', 'season_count', 'date', 'title', 'year'];\n\n  override when(matches: Matches, _context: any): Match | undefined {\n    // Skip if episode_title already found\n    if (hasmatch(matches.named('episode_title', null, 0))) {\n      return undefined;\n    }\n\n    // range with proper args: start=0, end=undefined, predicate, index\n    const alternativeTitle = matches.range(0, undefined,\n      (m: Match) => m.name === 'alternative_title', 0) as Match | undefined;\n    if (alternativeTitle) {\n      const mainTitle = (matches as any).chainBefore(\n        alternativeTitle.start,\n        seps,\n        0,\n        (m: Match) => m.name === 'title',\n        0\n      ) as Match | undefined;\n      if (mainTitle) {\n        // Work around rebulk-js previous() bug: use range() to search\n        // within the same filepart for a preceding episode/season/date/year/title\n        const filepart = matches.markers.atMatch(mainTitle, (m: Match) => m.name === 'path', 0) as Match | undefined;\n        const searchStart = filepart?.start ?? 0;\n        const prevPred = (m: Match) => !m.private && this.previousNames.includes(m.name ?? '');\n        const prevMatches = matches.range(searchStart, mainTitle.start, prevPred) as Match[];\n        const prevArr = Array.isArray(prevMatches) ? prevMatches : prevMatches ? [prevMatches] : [];\n        const episode = prevArr.length > 0 ? prevArr[prevArr.length - 1] : undefined;\n\n        // Check crc32 anywhere in the same filepart (not just before the title)\n        const searchEnd = filepart?.end ?? (matches.inputString?.length ?? mainTitle.end + 100);\n        const crc32Matches = !episode ? (matches.range(searchStart, searchEnd,\n          (m: Match) => !m.private && m.name === 'crc32') as Match[]) : undefined;\n        const crc32Arr = Array.isArray(crc32Matches) ? crc32Matches : crc32Matches ? [crc32Matches] : [];\n        const crc32 = crc32Arr.length > 0 ? crc32Arr[0] : undefined;\n\n        if (episode || crc32) {\n          return alternativeTitle;\n        }\n      }\n    }\n    return undefined;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: any): void {\n    const match = whenResponse as Match | undefined;\n    if (!match) return;\n    matches.remove(match);\n    match.name = 'episode_title';\n    match.tags = match.tags || [];\n    match.tags.push('alternative-replaced');\n    matches.append(match);\n  }\n}\n\n/**\n * Trim language/country/subtitle_language matches that overlap with the\n * trailing (or leading) edge of an episode_title.  When title extraction\n * ignores language matches the resulting hole text includes the language\n * word — this rule shrinks the episode_title span so it no longer covers\n * the language match, then recomputes the cleaned value.\n */\nclass TrimLanguageFromEpisodeTitle extends Rule {\n  static override dependency = ['EpisodeTitleFromPosition', 'AlternativeTitleReplace'];\n\n  private readonly langNames = new Set(['language', 'country', 'subtitle_language']);\n\n  override when(matches: Matches, _context: any): Array<{ match: Match; newStart: number; newEnd: number }> | undefined {\n    const episodeTitles = matches.named('episode_title') as Match[];\n    if (!episodeTitles || episodeTitles.length === 0) return undefined;\n\n    const updates: Array<{ match: Match; newStart: number; newEnd: number }> = [];\n\n    for (const et of episodeTitles) {\n      let newStart = et.start;\n      let newEnd = et.end;\n\n      // Find language/country matches overlapping with the episode_title\n      const overlapping = matches.range(et.start, et.end,\n        (m: Match) => this.langNames.has(m.name ?? '')) as Match[];\n\n      if (!overlapping || overlapping.length === 0) continue;\n\n      // Trim from the end: remove language matches that touch or extend past the trailing edge\n      // Sort by start descending to peel from the end\n      const sorted = [...overlapping].sort((a, b) => b.start - a.start);\n      for (const lang of sorted) {\n        // Language match starts within the episode title and reaches (or extends past) the end\n        if (lang.start >= newStart && lang.start < newEnd) {\n          const inputStr = et.inputString ?? '';\n          // Check that between the language match end and the episode title end is only seps (or language extends beyond)\n          const between = lang.end >= newEnd ? '' : inputStr.slice(lang.end, newEnd);\n          if (between === '' || [...between].every(c => seps.includes(c))) {\n            let trimEnd = lang.start;\n            while (trimEnd > newStart && seps.includes(inputStr[trimEnd - 1])) {\n              trimEnd--;\n            }\n            if (trimEnd < newEnd) {\n              newEnd = trimEnd;\n            }\n          }\n        }\n      }\n\n      // Note: we intentionally do NOT trim language matches from the leading\n      // edge because short language codes (e.g. \"En\") frequently appear as\n      // legitimate title words.\n\n      if (newStart !== et.start || newEnd !== et.end) {\n        if (newEnd > newStart) {\n          updates.push({ match: et, newStart, newEnd });\n        }\n      }\n    }\n\n    return updates.length > 0 ? updates : undefined;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: any): void {\n    const updates = whenResponse as Array<{ match: Match; newStart: number; newEnd: number }>;\n    if (!updates) return;\n\n    for (const { match, newStart, newEnd } of updates) {\n      matches.remove(match);\n      match.start = newStart;\n      match.end = newEnd;\n      // Reset cached value so it recomputes from formatter + new span\n      match.value = undefined as any;\n      const val = match.value;\n      if (val && String(val).trim()) {\n        matches.append(match);\n      }\n    }\n  }\n}\n\n/**\n * Title hole in a parent filepart, keeping a dash-joined name (e.g. \"Adam-12\",\n * \"The X-Files\") whole. matches.holes() splits holes on titleSeps (dash included),\n * so without this such names truncate to their first hole (\"The X\"). Merge the\n * consecutive leading holes joined by a single \"-\" with non-separator characters\n * on both sides. Mirrors Python's _parent_title_hole (upstream guessit #796).\n */\nfunction parentTitleHole(matches: Matches, start: number, end: number): Match | undefined {\n  const holesResult = matches.holes(start, end, {\n    ignore: or_(\n      (m: Match) => !!(m.tags?.includes('weak-episode')),\n      (m: Match) => m.name === 'language' || m.name === 'country' || m.name === 'episode_details',\n    ),\n    formatter: cleanup,\n    seps: titleSeps,\n    predicate: (m: Match) => !!(m.value),\n  }) as Match[] | Match | undefined;\n  const holes = Array.isArray(holesResult) ? holesResult : holesResult ? [holesResult] : [];\n  if (holes.length === 0) return undefined;\n\n  const hole = holes[0];\n  const inputString = hole.inputString ?? '';\n  for (const nextHole of holes.slice(1)) {\n    const separator = inputString.slice(hole.end, nextHole.start);\n    const holeRaw = hole.raw;\n    const nextRaw = nextHole.raw;\n    if (\n      separator === '-' &&\n      holeRaw && !seps.includes(holeRaw[holeRaw.length - 1]) &&\n      nextRaw && !seps.includes(nextRaw[0])\n    ) {\n      hole.end = nextHole.end;\n    } else {\n      break;\n    }\n  }\n  return hole;\n}\n\nclass Filepart3EpisodeTitle extends Rule {\n  // consequence produces a hole; we rename it to 'title' via matchName\n  override consequence = new AppendMatch('title');\n\n  override when(matches: Matches, _context: any): Match | undefined {\n    if (hasmatch(matches.tagged('filepart-title', null, 0))) {\n      return undefined;\n    }\n\n    const fileparts = matches.markers.named('path') as Match[];\n    if (fileparts.length < 3) {\n      return undefined;\n    }\n\n    const filename = fileparts[fileparts.length - 1];\n    const directory = fileparts[fileparts.length - 2];\n    const subdirectory = fileparts[fileparts.length - 3];\n\n    const episodeNumber = matches.range(filename.start, filename.end,\n      (m: Match) => m.name === 'episode', 0) as Match | undefined;\n    if (episodeNumber) {\n      const season = matches.range(directory.start, directory.end,\n        (m: Match) => m.name === 'season', 0) as Match | undefined;\n\n      if (season) {\n        const hole = parentTitleHole(matches, subdirectory.start, subdirectory.end);\n        if (hole) {\n          return hole;\n        }\n      }\n    }\n    return undefined;\n  }\n}\n\nclass Filepart2EpisodeTitle extends Rule {\n  // consequence produces a hole; we rename it to 'title' via matchName\n  override consequence = new AppendMatch('title');\n\n  override when(matches: Matches, _context: any): Match | undefined {\n    if (hasmatch(matches.tagged('filepart-title', null, 0))) {\n      return undefined;\n    }\n\n    const fileparts = matches.markers.named('path') as Match[];\n    if (fileparts.length < 2) {\n      return undefined;\n    }\n\n    const filename = fileparts[fileparts.length - 1];\n    const directory = fileparts[fileparts.length - 2];\n\n    const episodeNumber = matches.range(filename.start, filename.end,\n      (m: Match) => m.name === 'episode', 0) as Match | undefined;\n    if (episodeNumber) {\n      const season =\n        (matches.range(directory.start, directory.end, (m: Match) => m.name === 'season', 0) as Match | undefined) ||\n        (matches.range(filename.start, filename.end, (m: Match) => m.name === 'season', 0) as Match | undefined);\n\n      // Absolute numbering (no season anywhere) still puts the title in the parent\n      // directory: \"zettai karen children/01 - Episode Title.mkv\". (upstream 4.x)\n      const anySeason = (matches.named('season') as Match[] | Match | undefined);\n      const hasAnySeason = Array.isArray(anySeason) ? anySeason.length > 0 : !!anySeason;\n      if (season || !hasAnySeason) {\n        const hole = parentTitleHole(matches, directory.start, directory.end);\n        if (hole) {\n          // Crop the hole at group marker boundaries so that content inside\n          // parentheses (e.g., \"(US)\") that was ignored (country) doesn't\n          // bleed into the title text.\n          const groupMarkers = matches.markers.named('group') as Match[] | Match | undefined;\n          const groupArray = Array.isArray(groupMarkers) ? groupMarkers : groupMarkers ? [groupMarkers] : [];\n          const relevantGroups = groupArray.filter(\n            (g) => g.start >= directory.start && g.end <= directory.end &&\n                   !(g.start === directory.start && g.end === directory.end),\n          );\n          if (relevantGroups.length > 0) {\n            const cropped = hole.crop(relevantGroups);\n            const croppedArr = Array.isArray(cropped) ? cropped : cropped ? [cropped] : [];\n            const first = croppedArr.find((c) => c.value);\n            if (first) {\n              first.tags = first.tags || [];\n              first.tags.push('filepart-title');\n              return first;\n            }\n            // If cropping removed all content, fall through\n          } else {\n            hole.tags = hole.tags || [];\n            hole.tags.push('filepart-title');\n            return hole;\n          }\n        }\n      }\n    }\n    return undefined;\n  }\n}\n\nclass RenameEpisodeTitleWhenMovieType extends Rule {\n  static override priority = POST_PROCESS;\n  static override dependency = ['TypeProcessor'];\n\n  override when(matches: Matches, _context: any): Match[] | undefined {\n    // Get episode_title matches (excluding alternative-replaced ones)\n    const episodeTitles = (matches.named('episode_title',\n      (m: Match) => !m.tags?.includes('alternative-replaced')) as Match[]) || [];\n\n    // Check if type is episode (using index=0 to get single match → undefined if none)\n    const episodeType = matches.named('type', (m: Match) => m.value === 'episode', 0) as Match | undefined;\n\n    if (episodeTitles.length > 0 && !episodeType) {\n      return episodeTitles;\n    }\n    return undefined;\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: any): void {\n    const episodeTitles = whenResponse as Match[] | undefined;\n    if (!episodeTitles) return;\n    for (const match of episodeTitles) {\n      matches.remove(match);\n      match.name = 'alternative_title';\n      matches.append(match);\n    }\n  }\n}\n","/**\n * Language data lookup table — port of babelfish with custom additions\n */\n\nexport interface LanguageData {\n  alpha3: string;\n  alpha2?: string;\n  name: string;\n  opensubtitles?: string;\n  country?: string;\n  script?: string;\n}\n\nexport const LANGUAGES: LanguageData[] = [\n  // Major languages\n  { alpha3: 'eng', alpha2: 'en', name: 'English', opensubtitles: 'eng' },\n  { alpha3: 'fra', alpha2: 'fr', name: 'French', opensubtitles: 'fre' },\n  { alpha3: 'deu', alpha2: 'de', name: 'German', opensubtitles: 'ger' },\n  { alpha3: 'spa', alpha2: 'es', name: 'Spanish', opensubtitles: 'spa' },\n  { alpha3: 'ita', alpha2: 'it', name: 'Italian', opensubtitles: 'ita' },\n  { alpha3: 'por', alpha2: 'pt', name: 'Portuguese', opensubtitles: 'por' },\n  { alpha3: 'rus', alpha2: 'ru', name: 'Russian', opensubtitles: 'rus' },\n  { alpha3: 'jpn', alpha2: 'ja', name: 'Japanese', opensubtitles: 'jpn' },\n  { alpha3: 'zho', alpha2: 'zh', name: 'Chinese', opensubtitles: 'chi' },\n  { alpha3: 'kor', alpha2: 'ko', name: 'Korean', opensubtitles: 'kor' },\n  { alpha3: 'ara', alpha2: 'ar', name: 'Arabic', opensubtitles: 'ara' },\n  { alpha3: 'hin', alpha2: 'hi', name: 'Hindi', opensubtitles: 'hin' },\n  { alpha3: 'tur', alpha2: 'tr', name: 'Turkish', opensubtitles: 'tur' },\n  { alpha3: 'pol', alpha2: 'pl', name: 'Polish', opensubtitles: 'pol' },\n  { alpha3: 'nld', alpha2: 'nl', name: 'Dutch', opensubtitles: 'dut' },\n  { alpha3: 'swe', alpha2: 'sv', name: 'Swedish', opensubtitles: 'swe' },\n  { alpha3: 'dan', alpha2: 'da', name: 'Danish', opensubtitles: 'dan' },\n  { alpha3: 'nor', alpha2: 'no', name: 'Norwegian', opensubtitles: 'nor' },\n  { alpha3: 'fin', alpha2: 'fi', name: 'Finnish', opensubtitles: 'fin' },\n  { alpha3: 'hun', alpha2: 'hu', name: 'Hungarian', opensubtitles: 'hun' },\n  { alpha3: 'ces', alpha2: 'cs', name: 'Czech', opensubtitles: 'cze' },\n  { alpha3: 'ron', alpha2: 'ro', name: 'Romanian', opensubtitles: 'rum' },\n  { alpha3: 'ukr', alpha2: 'uk', name: 'Ukrainian', opensubtitles: 'ukr' },\n  { alpha3: 'heb', alpha2: 'he', name: 'Hebrew', opensubtitles: 'heb' },\n  { alpha3: 'cat', alpha2: 'ca', name: 'Catalan', opensubtitles: 'cat' },\n  { alpha3: 'vie', alpha2: 'vi', name: 'Vietnamese', opensubtitles: 'vie' },\n  { alpha3: 'tha', alpha2: 'th', name: 'Thai', opensubtitles: 'tha' },\n  { alpha3: 'ind', alpha2: 'id', name: 'Indonesian', opensubtitles: 'ind' },\n  { alpha3: 'mal', alpha2: 'ml', name: 'Malayalam', opensubtitles: 'mal' },\n  { alpha3: 'tel', alpha2: 'te', name: 'Telugu', opensubtitles: 'tel' },\n  { alpha3: 'tam', alpha2: 'ta', name: 'Tamil', opensubtitles: 'tam' },\n  { alpha3: 'bul', alpha2: 'bg', name: 'Bulgarian', opensubtitles: 'bul' },\n  { alpha3: 'hrv', alpha2: 'hr', name: 'Croatian', opensubtitles: 'hrv' },\n  { alpha3: 'srp', alpha2: 'sr', name: 'Serbian', opensubtitles: 'srp' },\n  { alpha3: 'slk', alpha2: 'sk', name: 'Slovak', opensubtitles: 'slo' },\n  { alpha3: 'slv', alpha2: 'sl', name: 'Slovenian', opensubtitles: 'slv' },\n  { alpha3: 'ell', alpha2: 'el', name: 'Greek', opensubtitles: 'ell' },\n  { alpha3: 'lit', alpha2: 'lt', name: 'Lithuanian', opensubtitles: 'lit' },\n  { alpha3: 'lav', alpha2: 'lv', name: 'Latvian', opensubtitles: 'lav' },\n  { alpha3: 'est', alpha2: 'et', name: 'Estonian', opensubtitles: 'est' },\n  { alpha3: 'glg', alpha2: 'gl', name: 'Galician', opensubtitles: 'glg' },\n  { alpha3: 'eus', alpha2: 'eu', name: 'Basque', opensubtitles: 'baq' },\n  { alpha3: 'ben', alpha2: 'bn', name: 'Bengali', opensubtitles: 'ben' },\n  { alpha3: 'isl', alpha2: 'is', name: 'Icelandic', opensubtitles: 'ice' },\n  { alpha3: 'mkd', alpha2: 'mk', name: 'Macedonian', opensubtitles: 'mac' },\n  { alpha3: 'bos', alpha2: 'bs', name: 'Bosnian', opensubtitles: 'bos' },\n  { alpha3: 'alb', alpha2: 'sq', name: 'Albanian', opensubtitles: 'alb' },\n  { alpha3: 'per', alpha2: 'fa', name: 'Persian', opensubtitles: 'per' },\n  { alpha3: 'msa', alpha2: 'ms', name: 'Malay', opensubtitles: 'may' },\n  { alpha3: 'mon', alpha2: 'mn', name: 'Mongolian', opensubtitles: 'mon' },\n  { alpha3: 'tha', alpha2: 'th', name: 'Thai', opensubtitles: 'tha' },\n  { alpha3: 'urd', alpha2: 'ur', name: 'Urdu', opensubtitles: 'urd' },\n  { alpha3: 'pan', alpha2: 'pa', name: 'Punjabi', opensubtitles: 'pun' },\n  { alpha3: 'guj', alpha2: 'gu', name: 'Gujarati', opensubtitles: 'guj' },\n  { alpha3: 'kan', alpha2: 'kn', name: 'Kannada', opensubtitles: 'kan' },\n  { alpha3: 'mar', alpha2: 'mr', name: 'Marathi', opensubtitles: 'mar' },\n  { alpha3: 'asm', alpha2: 'as', name: 'Assamese', opensubtitles: 'asm' },\n  { alpha3: 'mya', alpha2: 'my', name: 'Burmese', opensubtitles: 'mya' },\n  { alpha3: 'khm', alpha2: 'km', name: 'Khmer', opensubtitles: 'khm' },\n  { alpha3: 'lao', alpha2: 'lo', name: 'Lao', opensubtitles: 'lao' },\n\n  // Regional variants\n  { alpha3: 'por', alpha2: 'pt', name: 'Brazilian Portuguese', country: 'BR', opensubtitles: 'pob' },\n  { alpha3: 'zho', alpha2: 'zh', name: 'Simplified Chinese', country: 'CN', opensubtitles: 'chi' },\n  { alpha3: 'zho', alpha2: 'zh', name: 'Traditional Chinese', country: 'TW', opensubtitles: 'zht' },\n  { alpha3: 'zho', alpha2: 'zh', name: 'Hong Kong Chinese', country: 'HK', opensubtitles: 'zht' },\n  { alpha3: 'deu', alpha2: 'de', name: 'Swiss German', country: 'CH', opensubtitles: 'ger' },\n  { alpha3: 'fra', alpha2: 'fr', name: 'Swiss French', country: 'CH', opensubtitles: 'fre' },\n  { alpha3: 'ita', alpha2: 'it', name: 'Swiss Italian', country: 'CH', opensubtitles: 'ita' },\n  { alpha3: 'nld', alpha2: 'nl', name: 'Flemish', country: 'BE', opensubtitles: 'dut' },\n\n  // Special languages\n  { alpha3: 'und', name: 'Undetermined', opensubtitles: 'und' },\n  { alpha3: 'mul', name: 'Multiple Languages', opensubtitles: 'mul' },\n];\n\n/**\n * Build lookup maps from language data\n */\nfunction buildLookupMap<K extends keyof LanguageData>(key: K): Map<string, LanguageData> {\n  const map = new Map<string, LanguageData>();\n  for (const lang of LANGUAGES) {\n    const value = lang[key];\n    if (value) {\n      const k = String(value).toLowerCase();\n      // Prefer entries without country/region (generic language) over\n      // country-specific variants so that e.g. \"fr\" maps to French,\n      // not Swiss French.\n      if (!map.has(k) || (!lang.country && map.get(k)!.country)) {\n        map.set(k, lang);\n      }\n    }\n  }\n  return map;\n}\n\nexport const ALPHA3_MAP = buildLookupMap('alpha3');\nexport const ALPHA2_MAP = buildLookupMap('alpha2');\nexport const NAME_MAP = buildLookupMap('name');\nexport const OPENSUBTITLES_MAP = buildLookupMap('opensubtitles');\n\n/**\n * Guessit synonym mappings from config\n */\nexport const GUESSIT_SYNONYMS: Record<string, string[]> = {\n  'ell': ['gr', 'greek'],\n  'spa': ['esp', 'español', 'espanol'],\n  'fra': ['français', 'vf', 'vff', 'vfi', 'vfq'],\n  'swe': ['se'],\n  'por_BR': ['po', 'pb', 'pob', 'ptbr', 'br', 'brazilian'],\n  'deu_CH': ['swissgerman', 'swiss german'],\n  'nld_BE': ['flemish'],\n  'cat': ['català', 'castellano', 'espanol castellano', 'español castellano'],\n  'ces': ['cz'],\n  'ukr': ['ua'],\n  'zho': ['cn'],\n  'jpn': ['jp'],\n  'hrv': ['scr'],\n  'mul': ['multi', 'multiple', 'dl'],\n};\n\n/**\n * Countries data\n */\nexport const COUNTRIES: Record<string, string> = {\n  'US': 'United States',\n  'GB': 'United Kingdom',\n  'FR': 'France',\n  'DE': 'Germany',\n  'ES': 'Spain',\n  'IT': 'Italy',\n  'PT': 'Portugal',\n  'BR': 'Brazil',\n  'CA': 'Canada',\n  'AU': 'Australia',\n  'JP': 'Japan',\n  'CN': 'China',\n  'IN': 'India',\n  'RU': 'Russia',\n  'MX': 'Mexico',\n  'CH': 'Switzerland',\n  'BE': 'Belgium',\n  'NL': 'Netherlands',\n  'SE': 'Sweden',\n  'NO': 'Norway',\n  'DK': 'Denmark',\n  'FI': 'Finland',\n  'PL': 'Poland',\n  'CZ': 'Czech Republic',\n  'SK': 'Slovakia',\n  'HU': 'Hungary',\n  'RO': 'Romania',\n  'BG': 'Bulgaria',\n  'HR': 'Croatia',\n  'RS': 'Serbia',\n  'GR': 'Greece',\n  'TR': 'Turkey',\n  'KR': 'South Korea',\n  'TW': 'Taiwan',\n  'HK': 'Hong Kong',\n  'TH': 'Thailand',\n  'VN': 'Vietnam',\n  'ID': 'Indonesia',\n  'MY': 'Malaysia',\n  'SG': 'Singapore',\n  'PH': 'Philippines',\n  'AE': 'United Arab Emirates',\n  'SA': 'Saudi Arabia',\n  'IL': 'Israel',\n  'EG': 'Egypt',\n  'ZA': 'South Africa',\n  'NG': 'Nigeria',\n};\n","/**\n * Language class and lookup functions — port of babelfish\n */\nimport {\n  LANGUAGES,\n  ALPHA3_MAP,\n  ALPHA2_MAP,\n  NAME_MAP,\n  OPENSUBTITLES_MAP,\n  GUESSIT_SYNONYMS,\n  type LanguageData,\n} from './data.js';\n\nexport class Language {\n  alpha3: string;\n  country?: string;\n  script?: string;\n\n  constructor(alpha3: string, country?: string, script?: string) {\n    this.alpha3 = alpha3;\n    this.country = country;\n    this.script = script;\n  }\n\n  /**\n   * Convert to string representation: \"eng\" or \"eng-US\"\n   */\n  toString(): string {\n    if (this.country) {\n      return `${this.alpha3}-${this.country}`;\n    }\n    return this.alpha3;\n  }\n\n  /**\n   * Get the language name\n   */\n  getName(): string {\n    const key = this.country\n      ? `${this.alpha3}-${this.country}`\n      : this.alpha3;\n\n    for (const lang of LANGUAGES) {\n      if (lang.alpha3 === this.alpha3 && lang.country === this.country) {\n        return lang.name;\n      }\n    }\n\n    // Fallback to alpha3-only match\n    for (const lang of LANGUAGES) {\n      if (lang.alpha3 === this.alpha3 && !lang.country) {\n        return lang.name;\n      }\n    }\n\n    return this.alpha3;\n  }\n\n  /**\n   * Get the alpha2 code if available\n   */\n  getAlpha2(): string | undefined {\n    for (const lang of LANGUAGES) {\n      if (lang.alpha3 === this.alpha3 && lang.country === this.country) {\n        return lang.alpha2;\n      }\n    }\n\n    // Fallback to alpha3-only match\n    for (const lang of LANGUAGES) {\n      if (lang.alpha3 === this.alpha3 && !lang.country) {\n        return lang.alpha2;\n      }\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Get the OpenSubtitles code if available\n   */\n  getOpenSubtitles(): string | undefined {\n    for (const lang of LANGUAGES) {\n      if (lang.alpha3 === this.alpha3 && lang.country === this.country) {\n        return lang.opensubtitles;\n      }\n    }\n\n    // Fallback to alpha3-only match\n    for (const lang of LANGUAGES) {\n      if (lang.alpha3 === this.alpha3 && !lang.country) {\n        return lang.opensubtitles;\n      }\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Create a Language from a string (main lookup method)\n   * Tries multiple formats: alpha3, alpha2, name, IETF, OpenSubtitles, synonyms\n   */\n  static fromString(value: string): Language | undefined {\n    if (!value) return undefined;\n\n    const lower = value.toLowerCase().trim();\n\n    // Try as synonym first\n    const lang = this.fromSynonym(lower);\n    if (lang) return lang;\n\n    // Try as direct codes\n    if (lower.length === 3) {\n      return this.fromAlpha3(lower);\n    }\n\n    if (lower.length === 2) {\n      return this.fromAlpha2(lower);\n    }\n\n    // Try as name\n    const byName = this.fromName(lower);\n    if (byName) return byName;\n\n    // Try as OpenSubtitles code\n    const byOpenSubs = this.fromOpenSubtitles(lower);\n    if (byOpenSubs) return byOpenSubs;\n\n    // Try as IETF tag\n    const byIETF = this.fromIetf(lower);\n    if (byIETF) return byIETF;\n\n    return undefined;\n  }\n\n  /**\n   * Create a Language from alpha3 code\n   */\n  static fromAlpha3(code: string): Language | undefined {\n    if (!code) return undefined;\n    const lower = code.toLowerCase().trim();\n    const lang = ALPHA3_MAP.get(lower);\n    if (lang) {\n      return new Language(lang.alpha3, lang.country, lang.script);\n    }\n    return undefined;\n  }\n\n  /**\n   * Create a Language from alpha2 code\n   */\n  static fromAlpha2(code: string): Language | undefined {\n    if (!code) return undefined;\n    const lower = code.toLowerCase().trim();\n    const lang = ALPHA2_MAP.get(lower);\n    if (lang) {\n      return new Language(lang.alpha3, lang.country, lang.script);\n    }\n    return undefined;\n  }\n\n  /**\n   * Create a Language from language name\n   */\n  static fromName(name: string): Language | undefined {\n    if (!name) return undefined;\n    const lower = name.toLowerCase().trim();\n    const lang = NAME_MAP.get(lower);\n    if (lang) {\n      return new Language(lang.alpha3, lang.country, lang.script);\n    }\n    return undefined;\n  }\n\n  /**\n   * Create a Language from OpenSubtitles code\n   */\n  static fromOpenSubtitles(code: string): Language | undefined {\n    if (!code) return undefined;\n    const lower = code.toLowerCase().trim();\n    const lang = OPENSUBTITLES_MAP.get(lower);\n    if (lang) {\n      return new Language(lang.alpha3, lang.country, lang.script);\n    }\n    return undefined;\n  }\n\n  /**\n   * Create a Language from IETF language tag (e.g., \"en-US\", \"pt-BR\")\n   */\n  static fromIetf(tag: string): Language | undefined {\n    if (!tag) return undefined;\n\n    const parts = tag.toLowerCase().trim().split('-');\n    if (parts.length === 0) return undefined;\n\n    // Try as alpha2-country\n    if (parts.length >= 1) {\n      const byAlpha2 = this.fromAlpha2(parts[0]);\n      if (byAlpha2 && parts.length >= 2) {\n        // IETF country/region subtags are 2 letters (ISO 3166-1 alpha-2).\n        // If the second part is 3+ letters it's likely a language code, not a country.\n        if (parts[1].length === 2) {\n          byAlpha2.country = parts[1].toUpperCase();\n        } else {\n          // Not a valid IETF tag - return undefined so each part is parsed separately\n          return undefined;\n        }\n      }\n      return byAlpha2;\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Create a Language from a guessit synonym\n   */\n  static fromSynonym(value: string): Language | undefined {\n    if (!value) return undefined;\n    const lower = value.toLowerCase().trim();\n\n    for (const [key, synonyms] of Object.entries(GUESSIT_SYNONYMS)) {\n      for (const syn of synonyms) {\n        if (syn.toLowerCase() === lower) {\n          const [alpha3, country] = key.split('_');\n          return new Language(alpha3, country);\n        }\n      }\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Check equality\n   */\n  equals(other: Language): boolean {\n    return (\n      this.alpha3 === other.alpha3 &&\n      this.country === other.country &&\n      this.script === other.script\n    );\n  }\n}\n\n/**\n * Special language instances\n */\nexport const UNDETERMINED = new Language('und');\nexport const MULTIPLE = new Language('mul');\n\n/**\n * Non-specific languages set\n */\nexport const NON_SPECIFIC_LANGUAGES = new Set([UNDETERMINED, MULTIPLE]);\n\n/**\n * Check if a language is non-specific\n */\nexport function isNonSpecific(lang: Language): boolean {\n  return lang.alpha3 === 'und' || lang.alpha3 === 'mul';\n}\n","/**\n * Word iteration — port of guessit/rules/common/words.py\n */\nimport { seps } from './index.js';\n\nexport interface Word {\n  span: [number, number];\n  value: string;\n}\n\n/** Yield individual words from a string, separated by `seps` characters. */\nexport function* iterWords(string: string): Generator<Word> {\n  let start: number | null = null;\n  for (let i = 0; i <= string.length; i++) {\n    const ch = i < string.length ? string[i] : null;\n    if (ch !== null && !seps.includes(ch)) {\n      if (start === null) start = i;\n    } else {\n      if (start !== null) {\n        yield { span: [start, i], value: string.slice(start, i) };\n        start = null;\n      }\n    }\n  }\n}\n","/**\n * Language and subtitle_language properties — port of guessit/rules/properties/language.py\n */\nimport { Rebulk, Rule, RemoveMatch, RenameMatch, POST_PROCESS } from 'rebulk-js';\nimport { Language, UNDETERMINED, MULTIPLE, NON_SPECIFIC_LANGUAGES, isNonSpecific } from '../../language/index.js';\nimport { buildOrPattern } from '../../reutils.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { iterWords } from '../common/words.js';\nimport { seps } from '../common/index.js';\nimport type { Match } from 'rebulk-js';\n\ninterface LanguageConfig {\n  subtitle_affixes: string[];\n  subtitle_prefixes: string[];\n  subtitle_suffixes: string[];\n  language_affixes: string[];\n  language_prefixes: string[];\n  language_suffixes: string[];\n  weak_affixes: string[];\n  synonyms: Record<string, string[]>;\n}\n\n/**\n * LanguageWord - Extension for compound words like \"pt-BR\", \"soft subtitles\"\n */\nclass LanguageWord {\n  start: number;\n  end: number;\n  value: string;\n  inputString: string;\n  nextWord?: LanguageWord;\n\n  constructor(\n    start: number,\n    end: number,\n    value: string,\n    inputString: string,\n    nextWord?: LanguageWord,\n  ) {\n    this.start = start;\n    this.end = end;\n    this.value = value;\n    this.inputString = inputString;\n    this.nextWord = nextWord;\n  }\n\n  /**\n   * Get extended word by combining with next word if separators match\n   */\n  get extendedWord(): LanguageWord | undefined {\n    if (!this.nextWord) return undefined;\n\n    const separator = this.inputString.slice(this.end, this.nextWord.start);\n    const nextSeparator = this.inputString.slice(\n      this.nextWord.end,\n      this.nextWord.end + 1,\n    );\n\n    if (\n      (separator === '-' && separator !== nextSeparator) ||\n      separator === ' ' ||\n      separator === '.'\n    ) {\n      const value = this.inputString\n        .slice(this.start, this.nextWord.end)\n        .replace(/\\./g, ' ');\n      return new LanguageWord(\n        this.start,\n        this.nextWord.end,\n        value,\n        this.inputString,\n        this.nextWord.nextWord,\n      );\n    }\n\n    return undefined;\n  }\n}\n\ninterface LanguageMatch {\n  propertyName: 'language' | 'subtitle_language';\n  word: LanguageWord;\n  lang: Language;\n}\n\n/**\n * LanguageFinder - Helper to search for language matches\n */\nclass LanguageFinder {\n  allowedLanguages: Set<string>;\n  weakAffixes: Set<string>;\n  commonWords: Set<string>;\n  prefixesMap: Map<string, string[]>;\n  suffixesMap: Map<string, string[]>;\n\n  constructor(\n    context: any,\n    subtitlePrefixes: string[],\n    subtitleSuffixes: string[],\n    langPrefixes: string[],\n    langSuffixes: string[],\n    weakAffixes: string[],\n    commonWords?: Set<string>,\n  ) {\n    const allowedLanguagesArray = context?.allowed_languages || [];\n    this.allowedLanguages = new Set(\n      allowedLanguagesArray.map((l: string) => l.toLowerCase()),\n    );\n    this.weakAffixes = new Set(weakAffixes);\n    this.commonWords = commonWords ?? new Set();\n    this.prefixesMap = new Map();\n    this.suffixesMap = new Map();\n\n    if (!isDisabled(context, 'subtitle_language')) {\n      this.prefixesMap.set('subtitle_language', subtitlePrefixes);\n      this.suffixesMap.set('subtitle_language', subtitleSuffixes);\n    }\n\n    this.prefixesMap.set('language', langPrefixes);\n    this.suffixesMap.set('language', langSuffixes);\n  }\n\n  /**\n   * Find all language matches in the string\n   */\n  *find(inputString: string): Generator<[number, number, Record<string, any>]> {\n    const regularLangMap = new Map<string, Set<LanguageMatch>>();\n    const undeterminedMap = new Map<string, Set<LanguageMatch>>();\n    const multiMap = new Map<string, Set<LanguageMatch>>();\n\n    for (const match of this.iterLanguageMatches(inputString)) {\n      const key = match.propertyName;\n\n      if (match.lang.equals(UNDETERMINED)) {\n        if (!undeterminedMap.has(key)) undeterminedMap.set(key, new Set());\n        undeterminedMap.get(key)!.add(match);\n      } else if (match.lang.equals(MULTIPLE)) {\n        if (!multiMap.has(key)) multiMap.set(key, new Set());\n        multiMap.get(key)!.add(match);\n      } else {\n        if (!regularLangMap.has(key)) regularLangMap.set(key, new Set());\n        regularLangMap.get(key)!.add(match);\n      }\n    }\n\n    // Dedup yielded matches by (name, span, language). Python stores\n    // LanguageMatch in a set keyed by value equality, so two identical matches\n    // (same word, same language) collapse to one; the JS Set above keys by\n    // object identity, so without this an exact-duplicate match would be emitted\n    // twice (e.g. \"German.Sub\" -> subtitle_language [\"deu\",\"deu\"]).\n    const emitted = new Set<string>();\n    const emit = (m: LanguageMatch): [number, number, Record<string, any>] | undefined => {\n      const key = `${m.propertyName}:${m.word.start}-${m.word.end}:${m.lang.alpha3}`;\n      if (emitted.has(key)) return undefined;\n      emitted.add(key);\n      return this.toRebulkMatch(m);\n    };\n\n    // Yield multi matches if there are regular or no undetermined\n    for (const [key, values] of multiMap) {\n      if (regularLangMap.has(key) || !undeterminedMap.has(key)) {\n        for (const value of values) {\n          const r = emit(value);\n          if (r) yield r;\n        }\n      }\n    }\n\n    // Yield undetermined if there are no regular\n    for (const [key, values] of undeterminedMap) {\n      if (!regularLangMap.has(key)) {\n        for (const value of values) {\n          const r = emit(value);\n          if (r) yield r;\n        }\n      }\n    }\n\n    // Yield regular\n    for (const values of regularLangMap.values()) {\n      for (const value of values) {\n        const r = emit(value);\n        if (r) yield r;\n      }\n    }\n  }\n\n  /**\n   * Convert LanguageMatch to rebulk match tuple\n   */\n  private toRebulkMatch(\n    match: LanguageMatch,\n  ): [number, number, Record<string, any>] {\n    const word = match.word;\n    const start = word.start;\n    const end = word.end;\n    const name = match.propertyName;\n\n    if (match.lang.equals(UNDETERMINED)) {\n      return [\n        start,\n        end,\n        {\n          name,\n          value: word.value.toLowerCase(),\n          formatter: (s: string) => new Language('und'),\n          tags: ['weak-language'],\n        },\n      ];\n    }\n\n    const tags: string[] = [];\n    if (this.commonWords.has(word.value.toLowerCase())) {\n      tags.push('common');\n    }\n\n    return [\n      start,\n      end,\n      {\n        name,\n        value: match.lang,\n        ...(tags.length > 0 ? { tags } : {}),\n      },\n    ];\n  }\n\n  /**\n   * Iterate over language matches in the string\n   */\n  private *iterLanguageMatches(\n    inputString: string,\n  ): Generator<LanguageMatch> {\n    const candidates: LanguageWord[] = [];\n    let previous: LanguageWord | null = null;\n\n    for (const word of iterWords(inputString)) {\n      const languageWord = new LanguageWord(\n        word.span[0],\n        word.span[1],\n        word.value,\n        inputString,\n      );\n\n      if (previous) {\n        previous.nextWord = languageWord;\n        candidates.push(previous);\n      }\n\n      previous = languageWord;\n    }\n\n    if (previous) {\n      candidates.push(previous);\n    }\n\n    for (const candidate of candidates) {\n      yield* this.iterMatchesForCandidate(candidate);\n    }\n  }\n\n  /**\n   * Iterate over matches for a candidate word\n   */\n  private *iterMatchesForCandidate(\n    languageWord: LanguageWord,\n  ): Generator<LanguageMatch> {\n    // Check prefixes with next word\n    if (languageWord.nextWord) {\n      const match = this.findMatchForWord(\n        languageWord.nextWord,\n        languageWord,\n        this.prefixesMap,\n        (w, p) => w.startsWith(p),\n        (w, p) => w.slice(p.length),\n      );\n      if (match) yield match;\n    }\n\n    // Check suffixes with language word\n    const match = this.findMatchForWord(\n      languageWord,\n      languageWord.nextWord ?? undefined,\n      this.suffixesMap,\n      (w, s) => w.endsWith(s),\n      (w, s) => w.slice(0, -s.length),\n    );\n    if (match) yield match;\n\n    // Try direct language match\n    const directMatch = this.findLanguageMatchForWord(languageWord);\n    if (directMatch) yield directMatch;\n  }\n\n  /**\n   * Find match for word with affixes\n   */\n  private findMatchForWord(\n    word: LanguageWord | undefined,\n    fallbackWord: LanguageWord | undefined,\n    affixes: Map<string, string[]>,\n    isAffix: (w: string, a: string) => boolean,\n    stripAffix: (w: string, a: string) => string,\n  ): LanguageMatch | undefined {\n    if (!word) return undefined;\n\n    for (const currentWord of [word.extendedWord, word]) {\n      if (!currentWord) continue;\n\n      const wordLang = currentWord.value.toLowerCase();\n\n      for (const [key, parts] of affixes) {\n        for (const part of parts) {\n          if (!isAffix(wordLang, part)) continue;\n\n          let match: LanguageMatch | undefined = undefined;\n          const value = stripAffix(wordLang, part);\n\n          if (!value) {\n            if (\n              fallbackWord &&\n              (Math.abs(fallbackWord.start - currentWord.end) <= 1 ||\n                Math.abs(currentWord.start - fallbackWord.end) <= 1)\n            ) {\n              match = this.findLanguageMatchForWord(fallbackWord, key as any);\n            }\n\n            if (!match && !this.weakAffixes.has(part)) {\n              match = this.createLanguageMatch(\n                key as any,\n                new LanguageWord(\n                  currentWord.start,\n                  currentWord.end,\n                  'und',\n                  currentWord.inputString,\n                ),\n              );\n            }\n          } else {\n            // When the affix is stripped from an extendedWord, narrow the match position\n            // to only cover the remaining (non-affix) portion. This prevents creating\n            // wide matches that conflict with direct matches at the non-affix position.\n            // For example, \"Dubbed.DL\" with suffix \"dubbed\" → value \"dl\" should create\n            // a match at DL's position, not at the full \"Dubbed.DL\" span.\n            let matchStart = currentWord.start;\n            let matchEnd = currentWord.end;\n            if (currentWord !== word) {\n              // This is an extendedWord match — narrow to the sub-word that\n              // actually holds the stripped (non-affix) value. The value can be\n              // the leading word (\"German.Sub\", suffix \"sub\" -> value \"german\"\n              // lives in \"German\") or the trailing word (\"Dubbed.DL\", value \"dl\"\n              // lives in \"DL\"). Narrowing blindly to fallbackWord put the value on\n              // the affix word (e.g. \"Sub\" -> deu).\n              const trimmedValue = value.trim();\n              if (trimmedValue && word && word.value.toLowerCase() === trimmedValue) {\n                // Value lives in the leading word (\"German.Sub\" -> \"german\").\n                matchStart = word.start;\n                matchEnd = word.end;\n              } else if (trimmedValue && word && word.nextWord && word.nextWord.value.toLowerCase() === trimmedValue) {\n                // Value lives in the word after the affix (\"Subtitulado.Esp\",\n                // prefix \"subtitulado\" -> value \"esp\" lives in \"Esp\"). Without\n                // this it narrowed to fallbackWord (the word *before* the affix,\n                // e.g. \"HDTV\" -> spa).\n                matchStart = word.nextWord.start;\n                matchEnd = word.nextWord.end;\n              } else if (trimmedValue && fallbackWord) {\n                // Default: value lives in the trailing word (\"Dubbed.DL\" -> \"dl\"),\n                // or a compound the affix applies to (\"Sub.Fr-Eng\").\n                matchStart = fallbackWord.start;\n                matchEnd = fallbackWord.end;\n              }\n            }\n            match = this.createLanguageMatch(\n              key as any,\n              new LanguageWord(\n                matchStart,\n                matchEnd,\n                value,\n                currentWord.inputString,\n              ),\n            );\n          }\n\n          if (match) return match;\n        }\n      }\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Find language match for word\n   */\n  private findLanguageMatchForWord(\n    word: LanguageWord | undefined,\n    key: 'language' | 'subtitle_language' = 'language',\n  ): LanguageMatch | undefined {\n    if (!word) return undefined;\n\n    for (const currentWord of [word.extendedWord, word]) {\n      if (currentWord) {\n        const match = this.createLanguageMatch(key, currentWord);\n        if (match) return match;\n      }\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Create a LanguageMatch for a word\n   */\n  private createLanguageMatch(\n    key: 'language' | 'subtitle_language',\n    word: LanguageWord,\n  ): LanguageMatch | undefined {\n    const lang = this.parseLanguage(word.value.toLowerCase());\n\n    if (lang) {\n      return {\n        propertyName: key,\n        word,\n        lang,\n      };\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Parse a language word into a Language object\n   */\n  private parseLanguage(langWord: string): Language | undefined {\n    const lang = Language.fromString(langWord);\n\n    if (!lang) return undefined;\n\n    if (this.allowedLanguages.size === 0) {\n      return lang;\n    }\n\n    const name = lang.getName().toLowerCase();\n    const alpha2 = lang.getAlpha2();\n    const alpha3 = lang.alpha3.toLowerCase();\n\n    if (\n      this.allowedLanguages.has(name) ||\n      (alpha2 && this.allowedLanguages.has(alpha2.toLowerCase())) ||\n      this.allowedLanguages.has(alpha3)\n    ) {\n      return lang;\n    }\n\n    return undefined;\n  }\n}\n\n/**\n * Rules for language detection\n */\nclass SubtitlePrefixLanguageRule extends Rule {\n  consequence = RemoveMatch;\n  properties = { subtitle_language: [null] };\n\n  enabled(context: any): boolean {\n    return !isDisabled(context, 'subtitle_language');\n  }\n\n  when(matches: any, context: any): any {\n    const toRename: Array<[any, any]> = [];\n    const toRemove: any[] = matches.named('subtitle_language.prefix') || [];\n\n    for (const lang of matches.named('language') || []) {\n      let prefix = matches.previous(\n        lang,\n        (m: any) => m.name === 'subtitle_language.prefix',\n        0,\n      );\n\n      if (!prefix) {\n        const groupMarker = matches.markers?.at(lang, (m: any) => m.name === 'group', 0);\n        if (groupMarker) {\n          prefix = matches.previous(\n            groupMarker,\n            (m: any) => m.name === 'subtitle_language.prefix',\n            0,\n          );\n          if (!prefix) {\n            prefix = matches.range?.(\n              groupMarker.start,\n              lang.start,\n              (m: any) => m.name === 'subtitle_language.prefix',\n              0,\n            );\n          }\n        }\n      }\n\n      if (!prefix) {\n        // If another language in the same group is already being renamed to\n        // subtitle_language (in toRename), this language should also be renamed.\n        // This handles cases like St{Fr-Eng} or {Sub.Fr-Eng} where the prefix\n        // applies to the first language but subsequent languages in the same\n        // group should also become subtitle_language.\n        const groupMarker = matches.markers?.atMatch?.(lang, (m: any) => m.name === 'group', 0);\n        if (groupMarker) {\n          const siblingRename = toRename.find(([_pfx, renamedLang]: [any, any]) =>\n            renamedLang.start >= groupMarker.start && renamedLang.end <= groupMarker.end\n          );\n          if (siblingRename) {\n            prefix = siblingRename[0];\n          }\n        }\n      }\n\n      if (prefix) {\n        toRename.push([prefix, lang]);\n        const conflicting = matches.conflicting?.(lang) || [];\n        toRemove.push(...conflicting);\n        if (toRemove.includes(prefix)) {\n          toRemove.splice(toRemove.indexOf(prefix), 1);\n        }\n      }\n    }\n\n    if (toRename.length > 0 || toRemove.length > 0) {\n      return { toRename, toRemove };\n    }\n\n    return false;\n  }\n\n  then(matches: any, whenResponse: any, context: any): void {\n    const { toRename, toRemove } = whenResponse;\n\n    for (const m of toRemove) {\n      matches.remove(m);\n    }\n\n    for (const [prefix, match] of toRename) {\n      const suffix = { ...prefix, name: 'subtitle_language.suffix' };\n      if (matches.includes?.(suffix)) {\n        matches.remove(suffix);\n      }\n      matches.remove(match);\n      match.name = 'subtitle_language';\n      matches.append(match);\n    }\n  }\n}\n\nclass SubtitleSuffixLanguageRule extends Rule {\n  dependency = SubtitlePrefixLanguageRule;\n  consequence = RemoveMatch;\n  properties = { subtitle_language: [null] };\n\n  enabled(context: any): boolean {\n    return !isDisabled(context, 'subtitle_language');\n  }\n\n  when(matches: any, context: any): any {\n    const toAppend: any[] = [];\n    const toRemove: any[] = matches.named('subtitle_language.suffix') || [];\n\n    for (const lang of matches.named('language') || []) {\n      const suffix = matches.next(\n        lang,\n        (m: any) => m.name === 'subtitle_language.suffix',\n        0,\n      );\n\n      if (suffix) {\n        // Don't treat a suffix as belonging to this language if there is another\n        // language/subtitle_language match right after the suffix (e.g. \"ENG.sub.FR\" →\n        // \"sub\" is a prefix for FR, not a suffix for ENG).\n        const nextLang = matches.next(\n          suffix,\n          (m: any) => m.name === 'language' || m.name === 'subtitle_language',\n          0,\n        );\n        if (nextLang) {\n          continue;\n        }\n        // Also check if a subtitle_language match overlaps/contains the suffix position.\n        // This happens when the LanguageFinder detects \"sub.FR\" as a single subtitle_language\n        // match spanning the prefix+language (e.g. [32,38) for \"sub.FR\"). In that case,\n        // matches.next() won't find it because the match starts before suffix.end.\n        const overlapping = matches.range?.(\n          suffix.start,\n          suffix.end + 10,\n          (m: any) => (m.name === 'language' || m.name === 'subtitle_language') && m.start >= suffix.start && m.end > suffix.end,\n          0,\n        );\n        if (overlapping) {\n          continue;\n        }\n        toAppend.push(lang);\n        if (toRemove.includes(suffix)) {\n          toRemove.splice(toRemove.indexOf(suffix), 1);\n        }\n      }\n    }\n\n    if (toAppend.length > 0 || toRemove.length > 0) {\n      return { toAppend, toRemove };\n    }\n\n    return false;\n  }\n\n  then(matches: any, whenResponse: any, context: any): void {\n    const { toAppend, toRemove } = whenResponse;\n\n    for (const m of toRemove) {\n      matches.remove(m);\n    }\n\n    for (const match of toAppend) {\n      matches.remove(match);\n      match.name = 'subtitle_language';\n      matches.append(match);\n    }\n  }\n}\n\nclass SubtitleExtensionRule extends Rule {\n  dependency = SubtitleSuffixLanguageRule;\n  static SUBTITLE_EXTENSIONS = new Set(['srt', 'sub', 'smi', 'ssa', 'ass', 'vtt', 'idx', 'sup']);\n\n  when(matches: any, context: any): any {\n    const containers = matches.named('container') || [];\n    const containerArr: any[] = Array.isArray(containers) ? containers : containers ? [containers] : [];\n    const subtitleContainer = containerArr.find((c: any) =>\n      SubtitleExtensionRule.SUBTITLE_EXTENSIONS.has(String(c.value).toLowerCase()),\n    );\n    if (!subtitleContainer) return false;\n\n    // Find the filepart containing the subtitle extension\n    const fileparts = matches.markers?.named('path') || [];\n    const filepartArr: any[] = Array.isArray(fileparts) ? fileparts : fileparts ? [fileparts] : [];\n    const subtitleFilepart = filepartArr.find((fp: any) =>\n      subtitleContainer.start >= fp.start && subtitleContainer.end <= fp.end\n    );\n\n    const languages = matches.named('language') || [];\n    const langArr: any[] = Array.isArray(languages) ? languages : languages ? [languages] : [];\n\n    // Only convert languages that are in the same filepart as the subtitle extension.\n    // In name_only mode (single filepart), all languages in the filepart are converted.\n    let toConvert: any[];\n    if (subtitleFilepart) {\n      toConvert = langArr.filter((l: any) =>\n        l.start >= subtitleFilepart.start && l.end <= subtitleFilepart.end\n      );\n    } else {\n      toConvert = langArr;\n    }\n\n    return toConvert.length > 0 ? toConvert : false;\n  }\n\n  then(matches: any, whenResponse: any, _context: any): void {\n    if (!whenResponse || !Array.isArray(whenResponse)) return;\n    for (const match of whenResponse) {\n      matches.remove(match);\n      match.name = 'subtitle_language';\n      matches.append(match);\n    }\n  }\n}\n\nclass RemoveCommonWordsLanguageRule extends Rule {\n  consequence = RemoveMatch;\n  static override priority = 32;\n  override priority = 32;\n\n  when(matches: any, _context: any): any {\n    // Faithful port of Python's RemoveInvalidLanguages: remove every\n    // language/subtitle_language match whose raw text is a blacklisted common\n    // word (e.g. \"De\", \"no\", \"it\") — UNLESS it sits in a group marker that\n    // contains nothing but language matches (e.g. \"[Multiple Subtitles]\"), in\n    // which case it is a real tag. The finder tags such matches 'common', which\n    // is equivalent to `raw.toLowerCase() in common_words`.\n    const toRemove: any[] = [];\n    const all = matches.range?.(0, matches.inputString?.length ?? 0, (m: any) =>\n      m.name === 'language' || m.name === 'subtitle_language') || [];\n    const allArr: any[] = Array.isArray(all) ? all : all ? [all] : [];\n\n    for (const match of allArr) {\n      if (!match.tags?.includes('common')) continue;\n\n      const group = matches.markers?.atMatch?.(match, (m: any) => m.name === 'group', 0);\n      if (group) {\n        const nonLang = matches.range?.(group.start, group.end,\n          (m: any) => m.name !== 'language' && m.name !== 'subtitle_language');\n        const hasNonLang = Array.isArray(nonLang) ? nonLang.length > 0 : !!nonLang;\n        const holesRes = matches.holes?.(group.start, group.end,\n          { predicate: (m: any) => m.value && [...String(m.value)].some((c: string) => !seps.includes(c)) });\n        const hasContentHoles = Array.isArray(holesRes) ? holesRes.length > 0 : !!holesRes;\n        if (!hasNonLang && !hasContentHoles) continue; // group is all-languages → keep\n      }\n\n      toRemove.push(match);\n    }\n    return toRemove.length > 0 ? toRemove : false;\n  }\n}\n\nclass RemoveLanguageRule extends Rule {\n  consequence = RemoveMatch;\n\n  enabled(context: any): boolean {\n    return isDisabled(context, 'language');\n  }\n\n  when(matches: any, context: any): any {\n    return matches.named('language') || false;\n  }\n}\n\nclass RemoveUndeterminedLanguagesRule extends Rule {\n  consequence = RemoveMatch;\n  static override priority = 32;\n  override priority = 32;\n\n  when(matches: any, context: any): any {\n    const toRemove: any[] = [];\n\n    for (const match of matches.range?.(0, matches.inputString?.length) || []) {\n      if (!['language', 'subtitle_language'].includes(match.name)) continue;\n\n      if (match.value === 'und' || (match.value instanceof Language && match.value.alpha3 === 'und')) {\n        const previous = matches.previous?.(match, undefined, 0);\n        const next = matches.next?.(match, undefined, 0);\n        const langNames = new Set(['language', 'subtitle_language']);\n\n        if (\n          (previous && langNames.has(previous.name)) ||\n          (next && langNames.has(next.name))\n        ) {\n          toRemove.push(match);\n        }\n      }\n    }\n\n    return toRemove.length > 0 ? toRemove : false;\n  }\n}\n\n/**\n * Remove exact-duplicate language / subtitle_language matches — same span AND\n * same language. The subtitle rename rules can append a copy of a match that the\n * finder already produced (e.g. \"German.Sub\" -> two subtitle_language matches at\n * the same span). Python never reports the same language twice. Only same-span +\n * same-value copies are removed; distinct positions and genuine multi-language\n * releases are untouched. Runs after the subtitle rename rules.\n */\nclass DedupLanguageRule extends Rule {\n  consequence = RemoveMatch;\n  dependency = [SubtitlePrefixLanguageRule, SubtitleSuffixLanguageRule, SubtitleExtensionRule];\n\n  private identity(match: any): string {\n    const v = match.value;\n    if (v instanceof Language) {\n      const country = (v as any).country;\n      return `${v.alpha3}:${country ? String(country) : ''}`;\n    }\n    return String(v);\n  }\n\n  when(matches: any): any {\n    const toRemove: any[] = [];\n    for (const name of ['language', 'subtitle_language']) {\n      const list = [...(matches.named(name) || [])].sort((a: any, b: any) => a.start - b.start || a.end - b.end);\n      const seen = new Set<string>();\n      for (const m of list) {\n        const key = `${m.start}-${m.end}:${this.identity(m)}`;\n        if (seen.has(key)) toRemove.push(m);\n        else seen.add(key);\n      }\n    }\n    return toRemove.length > 0 ? toRemove : false;\n  }\n}\n\n/**\n * Main language property builder\n */\nexport function language(config: LanguageConfig, commonWords: Set<string>): Rebulk {\n  const subtitleBoth = config.subtitle_affixes;\n  const subtitlePrefixes = [\n    ...subtitleBoth,\n    ...config.subtitle_prefixes,\n  ].sort((a, b) => b.length - a.length);\n  const subtitleSuffixes = [\n    ...subtitleBoth,\n    ...config.subtitle_suffixes,\n  ].sort((a, b) => b.length - a.length);\n\n  const langBoth = config.language_affixes;\n  const langPrefixes = [...langBoth, ...config.language_prefixes].sort(\n    (a, b) => b.length - a.length,\n  );\n  const langSuffixes = [...langBoth, ...config.language_suffixes].sort(\n    (a, b) => b.length - a.length,\n  );\n\n  const weakAffixes = new Set(config.weak_affixes);\n\n  const rebulk = new Rebulk()\n    .stringDefaults({ ignoreCase: true })\n    .defaults({\n      validator: sepsSurround,\n    });\n\n  // Register subtitle language prefixes\n  for (const prefix of subtitlePrefixes) {\n    rebulk.string(prefix, {\n      name: 'subtitle_language.prefix',\n      ignoreCase: true,\n      private: true,\n      validator: sepsSurround,\n      tags: ['release-group-prefix'],\n      disabled: (context: any) => isDisabled(context, 'subtitle_language'),\n    });\n  }\n\n  // Register subtitle language suffixes\n  for (const suffix of subtitleSuffixes) {\n    rebulk.string(suffix, {\n      name: 'subtitle_language.suffix',\n      ignoreCase: true,\n      private: true,\n      validator: sepsSurround,\n      disabled: (context: any) => isDisabled(context, 'subtitle_language'),\n    });\n  }\n\n  // Register language suffixes\n  for (const suffix of langSuffixes) {\n    rebulk.string(suffix, {\n      name: 'language.suffix',\n      ignoreCase: true,\n      private: true,\n      validator: sepsSurround,\n      tags: ['source-suffix'],\n      disabled: (context: any) => isDisabled(context, 'language'),\n    });\n  }\n\n  // Functional pattern for finding languages\n  rebulk.functional(\n    (input: string, context: any) => {\n      const finder = new LanguageFinder(\n        context,\n        subtitlePrefixes,\n        subtitleSuffixes,\n        langPrefixes,\n        langSuffixes,\n        Array.from(weakAffixes),\n        commonWords,\n      );\n      return Array.from(finder.find(input));\n    },\n    {\n      properties: { language: [null] },\n      disabled: (context: any) => isDisabled(context, 'language') && isDisabled(context, 'subtitle_language'),\n    },\n  );\n\n  // Add rules\n  rebulk.rules(\n    SubtitlePrefixLanguageRule,\n    SubtitleSuffixLanguageRule,\n    SubtitleExtensionRule,\n    RemoveCommonWordsLanguageRule,\n    RemoveLanguageRule,\n    RemoveUndeterminedLanguagesRule,\n    DedupLanguageRule,\n    RemoveLanguageInsideTitle,\n  );\n\n  return rebulk;\n}\n\n/**\n * A short language *abbreviation* (≤3 chars, e.g. \"En\", \"It\") whose span falls\n * entirely inside a finalised title / episode_title is part of that title's text,\n * not real metadata — e.g. \"…- En Close, Yet En Far.…French.…\" matches \"En\" →\n * English twice inside the episode_title \"En Close, Yet En Far\". Python keeps only\n * the trailing French. Full language *names* buried in a title (e.g. \"Masala …\n * Telugu Movie\", \"…Spanish…\") are left alone — those are genuine languages that\n * Python misses and we keep.\n */\nclass RemoveLanguageInsideTitle extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  override when(matches: any): Match[] | false {\n    const titleNames = new Set(['title', 'episode_title', 'alternative_title']);\n    const titles = matches.range(0, (matches.inputString ?? '').length,\n      (m: Match) => titleNames.has(m.name ?? '')) as Match[];\n    if (!titles.length) return false;\n    const out: Match[] = [];\n    for (const name of ['language', 'subtitle_language']) {\n      for (const lang of (matches.named(name) as Match[])) {\n        const rawLen = String(lang.raw ?? '').trim().length;\n        if (rawLen > 3) continue;\n        if (titles.some((t) => t.start <= lang.start && t.end >= lang.end)) out.push(lang);\n      }\n    }\n    return out.length ? out : false;\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport { iterWords } from '../common/words.js';\n\n// Simple country lookup map\nconst COUNTRY_MAP: Record<string, string> = {\n  'us': 'US',\n  'usa': 'US',\n  'united states': 'US',\n  'gb': 'GB',\n  'uk': 'GB',\n  'united kingdom': 'GB',\n  'ca': 'CA',\n  'canada': 'CA',\n  'de': 'DE',\n  'germany': 'DE',\n  'fr': 'FR',\n  'france': 'FR',\n  'it': 'IT',\n  'italy': 'IT',\n  'es': 'ES',\n  'spain': 'ES',\n  'nl': 'NL',\n  'netherlands': 'NL',\n  'be': 'BE',\n  'belgium': 'BE',\n  'ch': 'CH',\n  'switzerland': 'CH',\n  'se': 'SE',\n  'sweden': 'SE',\n  'no': 'NO',\n  'norway': 'NO',\n  'dk': 'DK',\n  'denmark': 'DK',\n  'fi': 'FI',\n  'finland': 'FI',\n  'pl': 'PL',\n  'poland': 'PL',\n  'ru': 'RU',\n  'russia': 'RU',\n  'cn': 'CN',\n  'china': 'CN',\n  'jp': 'JP',\n  'japan': 'JP',\n  'au': 'AU',\n  'australia': 'AU',\n  'nz': 'NZ',\n  'new zealand': 'NZ',\n  'in': 'IN',\n  'india': 'IN',\n  'br': 'BR',\n  'brazil': 'BR',\n  'mx': 'MX',\n  'mexico': 'MX',\n  'za': 'ZA',\n  'south africa': 'ZA',\n  'kr': 'KR',\n  'south korea': 'KR',\n  'tw': 'TW',\n  'taiwan': 'TW',\n  'hk': 'HK',\n  'hong kong': 'HK',\n};\n\nexport function country(config: Record<string, unknown>, commonWords: Set<string>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'country') });\n  rebulk.defaults({ name: 'country' });\n\n  function findCountries(str: string, context?: Record<string, unknown>) {\n    const allowedCountries = context?.['allowed_countries'] as string[] | undefined;\n    return new CountryFinder(allowedCountries, commonWords).find(str);\n  }\n\n  rebulk.functional(findCountries, {\n    conflictSolver: (match, other) =>\n      other.name !== 'language' || !['US', 'GB'].includes(String(match.value)) ? match : other,\n    properties: { country: [null] },\n    disabled: (context) => !context?.['allowed_countries'],\n  });\n\n  return rebulk;\n}\n\nclass CountryFinder {\n  allowedCountries: Set<string>;\n  commonWords: Set<string>;\n\n  constructor(allowedCountries: string[] | undefined, commonWords: Set<string>) {\n    this.allowedCountries = new Set(\n      allowedCountries?.map((c) => c.toLowerCase()) || []\n    );\n    this.commonWords = commonWords;\n  }\n\n  find(str: string) {\n    const results: Array<[number, number, { value: string }]> = [];\n\n    for (const wordMatch of iterWords(str.trim().toLowerCase())) {\n      const word = wordMatch.value;\n      if (this.commonWords.has(word.toLowerCase())) {\n        continue;\n      }\n\n      const countryCode = COUNTRY_MAP[word.toLowerCase()];\n      if (countryCode) {\n        if (\n          this.allowedCountries.has(countryCode.toLowerCase()) ||\n          this.allowedCountries.has(word.toLowerCase())\n        ) {\n          results.push([\n            wordMatch.span[0],\n            wordMatch.span[1],\n            { value: countryCode },\n          ]);\n        }\n      }\n    }\n\n    return results;\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Rule, AppendMatch, RemoveMatch, POST_PROCESS } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport { seps , sepsPattern } from '../common/index.js';\nimport { buildExpectedFunction } from '../common/expected.js';\nimport { cleanup, strip } from '../common/formatters.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { intCoercable, sepsSurround } from '../common/validators.js';\nimport { markerSorted } from '../common/comparators.js';\n\nexport function releaseGroup(config: Record<string, unknown>) {\n  const forbiddenGroupnames = config['forbidden_names'] as string[];\n  const groupnameIgnoreSeps = config['ignored_seps'] as string;\n  const groupnameSeps = seps\n    .split('')\n    .filter((c) => !groupnameIgnoreSeps.includes(c))\n    .join('');\n\n  function cleanGroupname(str: string): string {\n    // Step 1: Strip groupname seps (seps minus ignored bracket-like chars) from both ends.\n    // We use groupnameSeps (not full seps) so brackets/parens are preserved inside.\n    let result = strip(str, groupnameSeps);\n\n    // Step 2: Only strip ignored_seps from ends if the string doesn't have them\n    // as surrounding brackets AND doesn't contain them internally.\n    const containsIgnored = groupnameIgnoreSeps.split('').some((c) => result.includes(c));\n    const startsWithIgnored = groupnameIgnoreSeps.split('').some((c) => result.startsWith(c));\n    const endsWithIgnored = groupnameIgnoreSeps.split('').some((c) => result.endsWith(c));\n    if (!(startsWithIgnored && endsWithIgnored) && !containsIgnored) {\n      result = strip(result, groupnameIgnoreSeps);\n    }\n\n    // Step 3: Strip forbidden names from start/end.\n    for (const forbidden of forbiddenGroupnames) {\n      if (\n        result.toLowerCase().startsWith(forbidden) &&\n        result.length > forbidden.length &&\n        seps.includes(result[forbidden.length])\n      ) {\n        result = strip(result.slice(forbidden.length), groupnameSeps);\n      }\n      if (\n        result.toLowerCase().endsWith(forbidden) &&\n        result.length > forbidden.length &&\n        seps.includes(result[result.length - forbidden.length - 1])\n      ) {\n        result = strip(result.slice(0, result.length - forbidden.length), groupnameSeps);\n      }\n    }\n\n    // Step 4: Remove unmatched closing bracket/paren characters at the end.\n    // e.g. \"tigole)\" → \"tigole\", \"TrollHD ]\" → \"TrollHD\"\n    result = result.replace(/\\s*[)\\]]\\s*$/, (m) => {\n      const closing = m.trim();\n      const opening = closing === ')' ? '(' : '[';\n      return result.includes(opening) ? m : '';\n    }).trim();\n\n    // Step 5: Normalize 'foo) [bar]' patterns → 'foo [bar]'.\n    return result.replace(/(.+)\\)\\s*\\[(.+)\\]/, '$1 $2').trim();\n  }\n\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'release_group') });\n\n  const expectedGroup = buildExpectedFunction('expected_group');\n\n  rebulk.functional(expectedGroup, {\n    name: 'release_group',\n    tags: ['expected'],\n    validator: sepsSurround,\n    conflictSolver: () => null as any,\n    disabled: (context) => !context?.['expected_group'],\n  });\n\n  return rebulk.rules(\n    new DashSeparatedReleaseGroup(cleanGroupname),\n    new SceneReleaseGroup(cleanGroupname),\n    AnimeReleaseGroup,\n    new TrailingTokenAfterEpisodeAsReleaseGroup(cleanGroupname),\n    NumericPrefixedGroupRule,\n    RemoveSeasonPackReleaseGroup\n  );\n}\n\n/**\n * A bracket like \"[Season.2.Full]\" in a directory part has no parseable content\n * (the written-out \"Season 2\" isn't matched as a season), so the empty-group\n * release-group rule claims the whole bracket as release_group \"[Season.2.Full]\".\n * A release group named after a season pack is never real — drop a release_group\n * whose text is a \"Season N\" expression. (Python emits no release_group here.)\n */\nclass RemoveSeasonPackReleaseGroup extends Rule {\n  static override priority = POST_PROCESS;\n  override consequence = RemoveMatch;\n\n  override when(matches: any): Match[] | false {\n    const rgs = matches.named('release_group') as Match[];\n    const out = (Array.isArray(rgs) ? rgs : rgs ? [rgs] : []).filter((m: Match) =>\n      /(^|[\\s._\\-\\[(])seasons?[\\s._-]*\\d/i.test(String(m.value ?? '')));\n    return out.length ? out : false;\n  }\n}\n\nclass DashSeparatedReleaseGroup extends Rule {\n  consequence = [RemoveMatch, AppendMatch];\n  valueFormatter: (s: string) => string;\n\n  constructor(valueFormatter: (s: string) => string) {\n    super();\n    this.valueFormatter = valueFormatter;\n  }\n\n  isValid(\n    matches: any,\n    candidate: Match,\n    start: number,\n    end: number,\n    atEnd: boolean\n  ): boolean {\n    if (!atEnd) {\n      if (String(candidate.value).length <= 1) {\n        return false;\n      }\n\n      if (matches.markers.atMatch(candidate, (m: Match) => m.name === 'group', 0)) {\n        return false;\n      }\n\n      // A leading token that is already an episode number (e.g. \"03\" in\n      // \"03-Criminal.Minds\") is the episode, not a release group.\n      if (matches.range(candidate.start, candidate.end, (m: Match) => m.name === 'episode', 0)) {\n        return false;\n      }\n\n      const firstHole = matches.holes(\n        candidate.end,\n        end,\n        { predicate: (m: Match) => m.start === candidate.end, index: 0 }\n      );\n      if (!firstHole) {\n        return false;\n      }\n\n      // A candidate at the filepart start, joined by a dash to a SINGLE word (no\n      // internal separator) and followed by a season/episode/date anchor, is the\n      // first half of a hyphenated title (\"grown-ish.s03e01\" → \"grown-ish\"), not a\n      // release group (#634/#640). A multi-word remainder (\"FoV-Show.Name.S01E01\")\n      // keeps the leading scene group. (upstream 4.4 refinement)\n      const holeRaw = String((firstHole as any).raw ?? '');\n      const holeCore = holeRaw.replace(new RegExp('^[' + sepsPattern + ']+|[' + sepsPattern + ']+$', 'g'), '');\n      if (candidate.start === start &&\n          !holeCore.includes('.') && !holeCore.includes(' ') &&\n          matches.range(candidate.end, end,\n            (m: Match) => ['season', 'episode', 'date'].includes(m.name ?? '') && !m.private, 0)) {\n        return false;\n      }\n\n      const rawValue = firstHole.raw;\n      return (\n        rawValue[0] === '-' &&\n        !rawValue.slice(1).includes('-') &&\n        rawValue.includes('.') &&\n        !rawValue.includes(' ')\n      );\n    }\n\n    const group = matches.markers.atMatch(\n      candidate,\n      (m: Match) => m.name === 'group',\n      0\n    );\n    if (group && matches.atMatch(group, (m: Match) => !m.private && m.span !== candidate.span)) {\n      return false;\n    }\n\n    let count = 0;\n    let match: Match | null = candidate;\n    while (match) {\n      // Fix: correct arg order - predicate is 3rd, index is 4th\n      const current = matches.range(\n        start,\n        match.start,\n        (m: Match) => !m.private && !m.tags.includes('expected'),\n        -1\n      ) as Match | undefined;\n      if (!current) {\n        break;\n      }\n\n      // Fix: use inputString (camelCase)\n      const inputStr: string = matches.inputString ?? '';\n      let separator = inputStr.slice(current.end, match.start);\n      if (!separator && (match.raw ?? '')[0] === '-') {\n        separator = '-';\n      }\n\n      match = current;\n\n      if (count === 0) {\n        if (separator !== '-') {\n          break;\n        }\n        count++;\n        continue;\n      }\n\n      if (separator === '.') {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  detect(matches: any, start: number, end: number, atEnd: boolean): Match | null {\n    let candidate: Match | null = null;\n    if (atEnd) {\n      const container = matches.ending(end, (m: Match) => m.name === 'container', 0);\n      if (container) {\n        end = container.start;\n      }\n\n      // Fix: correct arg order - predicate is 2nd, index is 3rd\n      candidate = matches.ending(\n        end,\n        (m: Match) =>\n          !m.private &&\n          !(m.name === 'other' && m.tags.includes('not-a-release-group')) &&\n          !(m.raw ?? '').includes('-') &&\n          (m.raw ?? '').trim() === m.raw,\n        0\n      );\n    }\n\n    if (!candidate) {\n      // Ignore weak-episode matches when computing holes for release groups,\n      // so that trailing numbers like \"45\" in \"Scarface45\" aren't consumed.\n      const ignoreWeak = (m: Match) =>\n        !!(m.tags?.includes('weak-episode') || m.tags?.includes('weak-duplicate'));\n      if (atEnd) {\n        // Fix: pass options as object with seps, index, predicate\n        candidate = matches.holes(\n          start,\n          end,\n          {\n            seps,\n            index: -1,\n            ignore: ignoreWeak,\n            predicate: (m: Match) => m.end === end && !!(m.raw ?? '').trim() && (m.raw ?? '')[0] === '-',\n          }\n        );\n      } else {\n        candidate = matches.holes(\n          start,\n          end,\n          {\n            seps,\n            index: 0,\n            ignore: ignoreWeak,\n            predicate: (m: Match) => m.start === start && !!(m.raw ?? '').trim(),\n          }\n        );\n      }\n    }\n\n    if (candidate && this.isValid(matches, candidate, start, end, atEnd)) {\n      return candidate;\n    }\n\n    return null;\n  }\n\n  when(matches: any) {\n    // Fix: JS truthiness - named() returns [] (truthy), use .length check\n    if ((matches.named('release_group') as Match[]).length > 0) {\n      return;\n    }\n\n    const toRemove = [];\n    const toAppend = [];\n    for (const filepart of matches.markers.named('path')) {\n      let candidate = this.detect(matches, filepart.start, filepart.end, true);\n      if (candidate) {\n        toRemove.push(...matches.atMatch(candidate));\n      } else {\n        candidate = this.detect(matches, filepart.start, filepart.end, false);\n      }\n\n      if (candidate) {\n        const releasegroup = new Match(candidate.start, candidate.end, {\n          name: 'release_group',\n          inputString: matches.inputString,\n        });\n        releasegroup.formatter = this.valueFormatter;\n\n        if (releasegroup.value) {\n          toAppend.push(releasegroup);\n        }\n        if (toRemove.length || toAppend.length) {\n          return [toRemove, toAppend];\n        }\n      }\n    }\n  }\n}\n\nclass SceneReleaseGroup extends Rule {\n  static dependency = ['TitleFromPosition'];\n  static consequence = AppendMatch;\n  static properties = { release_group: [null] };\n\n  valueFormatter: (s: string) => string;\n\n  constructor(valueFormatter: (s: string) => string) {\n    super();\n    this.valueFormatter = valueFormatter;\n  }\n\n  isPreviousMatch(match: Match): boolean {\n    const sceneNames = [\n      'video_codec',\n      'source',\n      'video_api',\n      'audio_codec',\n      'audio_profile',\n      'video_profile',\n      'audio_channels',\n      'screen_size',\n      'other',\n      'container',\n      'language',\n      'subtitle_language',\n      'subtitle_language.suffix',\n      'subtitle_language.prefix',\n      'language.suffix',\n    ];\n    const scenePrefixTags = ['release-group-prefix'];\n    const sceneNoPrefixTags = ['no-release-group-prefix'];\n\n    return sceneNames.includes(match.name ?? '')\n      ? !match.tags.some((t) => sceneNoPrefixTags.includes(t))\n      : match.tags.some((t) => scenePrefixTags.includes(t));\n  }\n\n  when(matches: any) {\n    const ret = [];\n\n    for (const filepart of markerSorted(matches.markers.named('path'), matches)) {\n      const { start, end } = filepart;\n      // Fix: JS truthiness - check .length\n      if (\n        ((matches.named(\n          'release_group',\n          (m: Match) => m.start >= start && m.end <= end\n        )) as Match[]).length > 0\n      ) {\n        continue;\n      }\n\n      const titles = matches.named(\n        'title',\n        (m: Match) => m.start >= start && m.end <= end\n      ) as Match[];\n\n      // Ignore extra titles AND episode_title matches when computing holes,\n      // so these don't prevent release_group detection.\n      // Also ignore weak-episode matches so trailing numbers (e.g. \"Scarface45\")\n      // aren't consumed by weak episode patterns.\n      const keepOnlyFirstTitle = (match: Match) =>\n        titles.slice(1).includes(match) || match.name === 'episode_title' ||\n        !!(match.tags?.includes('weak-episode') || match.tags?.includes('weak-duplicate'));\n\n      // Python: ignore=keepOnlyFirstTitle (treat extra titles as unmatched),\n      // predicate=lambda hole: cleanup(hole.value) (filter holes with non-empty value)\n      const lastHole = matches.holes(\n        start,\n        end + 1,\n        {\n          formatter: (s: string) => cleanup(s),\n          ignore: keepOnlyFirstTitle,\n          predicate: (hole: Match) => Boolean(cleanup(String(hole.value ?? ''))),\n          index: -1,\n        }\n      );\n\n      if (lastHole) {\n        // Anime episode releases carry the group in the leading [bracket]; a trailing\n        // (English title) parenthetical must not be claimed instead — leave it for\n        // AnimeReleaseGroup (#696/#757). Gated on an episode/season match so a movie's\n        // trailing (group) (YTS/YIFY) is untouched.\n        const holeGroup = matches.markers.atMatch(lastHole, (m: Match) => m.name === 'group', 0);\n        if (holeGroup && String((holeGroup as any).raw ?? '').startsWith('(')) {\n          const hasEpisodeish = ((matches.range(start, end,\n            (m: Match) => m.name === 'episode' || m.name === 'season') as Match[]) ?? []).length > 0;\n          if (hasEpisodeish) {\n            const firstGroup = matches.markers.range(start, end,\n              (m: Match) => m.name === 'group' && m.start === start, 0) as Match | undefined;\n            if (firstGroup) {\n              const inner = (matches.range(firstGroup.start, firstGroup.end,\n                (mm: Match) => !mm.tags.includes('weak-language')) as Match[]) ?? [];\n              const core = String((firstGroup as any).value ?? '').replace(new RegExp(`[${sepsPattern}]`, 'g'), '');\n              const emptyish = inner.length === 0 ||\n                inner.every((mm: Match) => mm.name === 'container' && mm.tags?.includes('subtitle'));\n              if (emptyish && core && !intCoercable(core)) continue;\n            }\n          }\n        }\n        const previousMatchFilter = (match: Match) => {\n          if (match.start < filepart.start) {\n            return false;\n          }\n          return !match.private || this.isPreviousMatch(match);\n        };\n\n        const previousMatch = matches.previous(lastHole, previousMatchFilter, 0);\n        // Fix: use inputString (camelCase)\n        const inputStr: string = matches.inputString ?? '';\n        const holeValue = String(lastHole.value ?? '');\n        if (\n          previousMatch &&\n          this.isPreviousMatch(previousMatch) &&\n          !inputStr\n            .slice(previousMatch.end, lastHole.start)\n            .replace(new RegExp(`[${sepsPattern}]`, 'g'), '') &&\n          !intCoercable(holeValue.replace(new RegExp(`[${sepsPattern}]`, 'g'), ''))\n        ) {\n          lastHole.name = 'release_group';\n          lastHole.tags = ['scene'];\n          // Use the cleanGroupname formatter so release_group value is properly cleaned.\n          lastHole.formatter = this.valueFormatter;\n\n          const group = matches.markers.atMatch(\n            lastHole,\n            (m: Match) => m.name === 'group',\n            0\n          );\n          if (group) {\n            group.formatter = this.valueFormatter;\n            if (group.value === lastHole.value) {\n              lastHole.start = group.start + 1;\n              lastHole.end = group.end - 1;\n              lastHole.tags = ['anime'];\n            }\n          }\n\n          // Remove episode_title and extra-title matches that overlap with the release_group span.\n          const ignoredMatches = matches.range(\n            lastHole.start,\n            lastHole.end,\n            keepOnlyFirstTitle\n          );\n\n          for (const ignoredMatch of ignoredMatches) {\n            matches.remove(ignoredMatch);\n          }\n\n          ret.push(lastHole);\n        }\n      }\n    }\n    return ret;\n  }\n}\n\nclass AnimeReleaseGroup extends Rule {\n  static dependency = ['SceneReleaseGroup', 'TitleFromPosition'];\n  static consequence = [RemoveMatch, AppendMatch];\n  static properties = { release_group: [null] };\n\n  when(matches: any) {\n    const toRemove = [];\n    const toAppend = [];\n\n    // Fix: JS truthiness - named() returns [] (truthy), use .length check\n    if ((matches.named('release_group') as Match[]).length > 0) {\n      return false;\n    }\n\n    if (\n      !(matches.named('episode') as Match[]).length &&\n      !(matches.named('season') as Match[]).length &&\n      (matches.named('release_group') as Match[]).length > 0\n    ) {\n      return false;\n    }\n\n    for (const filepart of markerSorted(matches.markers.named('path'), matches)) {\n      // A group is a candidate for anime release group if it contains\n      // no matches (excluding weak-language), OR if it only contains\n      // 'other' matches (like \"Fan Subtitled\" from \"Fansub\") which are\n      // commonly embedded in release group names.\n      const isGroupEmpty = (m: Match): boolean => {\n        const innerMatches = (matches.range(\n          m.start,\n          m.end,\n          (mm: Match) => !mm.tags.includes('weak-language')\n        ) as Match[]);\n        if (innerMatches.length === 0) return true;\n        // A LEADING bracket whose only content is a subtitle-format container\n        // name (e.g. \"[SSA]\", \"[ASS]\") is an anime release group, not a\n        // container — the name happens to collide with a subtitle extension.\n        if (m.start === filepart.start &&\n            innerMatches.every((mm: Match) => mm.name === 'container' && mm.tags?.includes('subtitle'))) {\n          return true;\n        }\n        return false;\n      };\n\n      const emptyGroup = matches.markers.range(\n        filepart.start,\n        filepart.end,\n        (m: Match) =>\n          m.name === 'group' &&\n          isGroupEmpty(m) &&\n          String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '') &&\n          !intCoercable(String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')),\n        0\n      );\n\n      if (emptyGroup) {\n        // Create a proper Match instance (not a plain spread) so prototype getters like .span work\n        const group = new Match(emptyGroup.start + 1, emptyGroup.end - 1, {\n          name: 'release_group',\n          inputString: matches.inputString,\n          tags: ['anime'],\n        });\n        toAppend.push(group);\n        // Remove weak-language, other, and subtitle-container matches that were\n        // inside the group (the bracket content is the release group name).\n        toRemove.push(\n          ...matches.range(\n            emptyGroup.start,\n            emptyGroup.end,\n            (m: Match) => m.tags.includes('weak-language') || m.name === 'other' ||\n              (m.name === 'container' && m.tags?.includes('subtitle'))\n          )\n        );\n      }\n    }\n\n    if (toRemove.length || toAppend.length) {\n      return [toRemove, toAppend];\n    }\n    return false;\n  }\n}\n\n/**\n * A single dash-separated token at the very end of a filepart, immediately\n * following the episode / absolute-episode numbers, is a release group — not an\n * episode title (e.g. \"Bleach.s16e03-04.313-314-GROUP\" → release_group \"GROUP\").\n * When the dash-separated walk in DashSeparatedReleaseGroup is disrupted by a\n * weak-episode range, the trailing token gets mislabelled as episode_title;\n * reclaim it here. Only fires when no release_group was found. (Python emits\n * release_group.)\n */\n/**\n * A scene group claimed as \"NN [name]\" swallowed a leading episode number:\n * \"Mary Bell (DVD) - 02 [h-b]\" (cross-parser corpus). Split it: the number is\n * the episode, the bracket content the release group.\n */\nclass NumericPrefixedGroupRule extends Rule {\n  static override priority = -32;\n  override priority = -32;\n  override consequence = [RemoveMatch, AppendMatch];\n\n  when(matches: any, _context: any): any {\n    const input: string = matches.inputString ?? '';\n    const toRemove: any[] = [];\n    const toAppend: any[] = [];\n    for (const rg of (matches.named('release_group') as any[]) ?? []) {\n      const m = /^(\\d{1,3})\\s*\\[([^\\]]+)\\]$/.exec(String(rg.value ?? ''));\n      if (!m) continue;\n      const raw = input.slice(rg.start, rg.end);\n      const numLen = m[1].length;\n      toRemove.push(rg);\n      toAppend.push(new Match(rg.start, rg.start + numLen, {\n        name: 'episode', value: parseInt(m[1], 10), inputString: input,\n      }));\n      const inner = raw.indexOf('[');\n      toAppend.push(new Match(rg.start + inner + 1, rg.end - 1, {\n        name: 'release_group', value: m[2], inputString: input,\n      }));\n    }\n    return (toRemove.length || toAppend.length) ? [toRemove, toAppend] : false;\n  }\n}\n\nclass TrailingTokenAfterEpisodeAsReleaseGroup extends Rule {\n  static dependency = ['AnimeReleaseGroup'];\n  consequence = [RemoveMatch, AppendMatch];\n  valueFormatter: (s: string) => string;\n\n  constructor(valueFormatter: (s: string) => string) {\n    super();\n    this.valueFormatter = valueFormatter;\n  }\n\n  when(matches: any) {\n    if ((matches.named('release_group') as Match[]).length > 0) return false;\n    const inp: string = matches.inputString ?? '';\n    const toRemove: Match[] = [];\n    const toAppend: Match[] = [];\n\n    for (const filepart of matches.markers.named('path')) {\n      // Trailing episode_title, ignoring a zero-width type/container marker.\n      const last = matches.range(filepart.start, filepart.end,\n        (m: Match) => !m.private && m.name === 'episode_title' && m.value, -1) as Match | undefined;\n      if (!last) continue;\n      // Must be the last real content of the filepart.\n      const after = matches.range(last.end, filepart.end,\n        (m: Match) => !m.private && m.span[0] !== m.span[1], 0);\n      if (after) continue;\n      // Single token, dash-separated from what precedes it.\n      const raw = String(last.raw ?? last.value);\n      if (/[\\s.]/.test(raw.trim())) continue;\n      if (inp[last.start - 1] !== '-') continue;\n      const prev = matches.range(filepart.start, last.start,\n        (m: Match) => !m.private, -1) as Match | undefined;\n      if (!prev || !['episode', 'absolute_episode'].includes(prev.name ?? '')) continue;\n\n      const rg = new Match(last.start, last.end, {\n        name: 'release_group',\n        inputString: inp,\n      });\n      rg.formatter = this.valueFormatter;\n      if (rg.value) {\n        toRemove.push(last);\n        toAppend.push(rg);\n      }\n    }\n    return toRemove.length || toAppend.length ? [toRemove, toAppend] : false;\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Rule, RemoveMatch } from 'rebulk-js';\nimport type { Match } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport { loadConfigPatterns } from '../../config/index.js';\nimport { seps, dash , sepsPattern } from '../common/index.js';\nimport { sepsBefore, sepsAfter } from '../common/validators.js';\n\nexport function streamingService(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'streaming_service') });\n  rebulk.stringDefaults({ ignoreCase: true }).regexDefaults({ flags: 'i', abbreviations: [dash] });\n  rebulk.defaults({ name: 'streaming_service', tags: ['source-prefix'] });\n\n  loadConfigPatterns(rebulk, config);\n\n  rebulk.rules(ValidateStreamingService);\n\n  return rebulk;\n}\n\nclass ValidateStreamingService extends Rule {\n  static priority = 128;\n  static consequence = RemoveMatch;\n\n  when(matches: any) {\n    const toRemove = [];\n    const allServices = matches.named('streaming_service');\n    if (process.env.DEBUG_SS) console.log(`[VS.when] allServices count=${allServices.length}`);\n    const inp: string = matches.inputString || '';\n    for (const service of allServices) {\n      // Reject a SHORT service abbreviation glued to surrounding word chars —\n      // it's really a substring of a longer token (e.g. \"CN\" inside the release\n      // group \"CNHD\" → bogus Cartoon Network). Long distinctive names glued to a\n      // recognised suffix (e.g. \"NetflixUHD\", \"iTunesHD\") are left alone.\n      const rawLen = (service.raw ?? '').length;\n      if (rawLen <= 3) {\n        const charAfter = inp[service.end];\n        const charBefore = inp[service.start - 1];\n        if ((charAfter && /[a-z0-9]/i.test(charAfter)) || (charBefore && /[a-z0-9]/i.test(charBefore))) {\n          toRemove.push(service);\n          continue;\n        }\n      }\n      // Work around rebulk-js next()/previous() bug: they stop at the first position\n      // with ANY match and filter by predicate, instead of continuing to find matches\n      // that satisfy the predicate. Use range() to find suffix/prefix matches instead.\n      const suffixPred = (m: Match) => !m.private && m.tags?.includes('streaming_service.suffix');\n      const prefixPred = (m: Match) => !m.private && m.tags?.includes('streaming_service.prefix');\n\n      // Find the nearest suffix match after the service\n      const suffixMatches = matches.range(service.end, service.end + 30, suffixPred) as Match[];\n      const suffixArray = Array.isArray(suffixMatches) ? suffixMatches : suffixMatches ? [suffixMatches] : [];\n      const nextMatch = suffixArray.length > 0 ? suffixArray.reduce((a: Match, b: Match) => a.start < b.start ? a : b) : undefined;\n\n      // Find the nearest prefix match before the service\n      const prefixMatches = matches.range(Math.max(0, service.start - 30), service.start, prefixPred) as Match[];\n      const prefixArray = Array.isArray(prefixMatches) ? prefixMatches : prefixMatches ? [prefixMatches] : [];\n      const previousMatch = prefixArray.length > 0 ? prefixArray.reduce((a: Match, b: Match) => a.end > b.end ? a : b) : undefined;\n      const hasOther = service.initiator && (service.initiator.children.named('other') as Match[]).length > 0;\n\n      if (process.env.DEBUG_SS) {\n        console.log(`[SS] service=${service.value} [${service.start},${service.end}) nextMatch=${nextMatch?.name}@${nextMatch?.start} prevMatch=${previousMatch?.name} sepsBefore=${sepsBefore(service)} sepsAfter=${sepsAfter(service)}`);\n      }\n\n      if (!hasOther) {\n        const holesToNext = nextMatch\n          ? (matches.holes(service.end, nextMatch.start, { predicate: (m: Match) => Boolean(String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')) }) as Match[])\n          : null;\n        const holesToPrev = previousMatch\n          ? (matches.holes(previousMatch.end, service.start, { predicate: (m: Match) => Boolean(String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')) }) as Match[])\n          : null;\n\n        // Additional check: ensure suffix/prefix is close to the service (within ~20 chars)\n        // and no other named matches (non-streaming-service) exist between them.\n        const maxDistance = 20;\n        const nextTooFar = nextMatch && (nextMatch.start - service.end) > maxDistance;\n        const prevTooFar = previousMatch && (service.start - previousMatch.end) > maxDistance;\n\n        // Check if there are non-streaming-service matches between service and its suffix/prefix\n        const matchesBetweenNext = nextMatch\n          ? (matches.range(service.end, nextMatch.start, (m: Match) =>\n              m.name !== 'streaming_service' && !m.private && m.name !== 'other'\n            ) as Match[])\n          : null;\n        const matchesBetweenPrev = previousMatch\n          ? (matches.range(previousMatch.end, service.start, (m: Match) =>\n              m.name !== 'streaming_service' && !m.private && m.name !== 'other'\n            ) as Match[])\n          : null;\n\n        const nextHasIntervening = matchesBetweenNext && matchesBetweenNext.length > 0;\n        const prevHasIntervening = matchesBetweenPrev && matchesBetweenPrev.length > 0;\n\n        if (\n          !nextMatch || nextTooFar || nextHasIntervening ||\n          (holesToNext !== null && holesToNext.length > 0) ||\n          !sepsBefore(service)\n        ) {\n          if (\n            !previousMatch || prevTooFar || prevHasIntervening ||\n            (holesToPrev !== null && holesToPrev.length > 0) ||\n            !sepsAfter(service)\n          ) {\n            if (process.env.DEBUG_SS) console.log(`  [VS.when] pushing to toRemove: ${service.value}`);\n            toRemove.push(service);\n            continue;\n          }\n        }\n      }\n\n      if (service.value === 'Comedy Central') {\n        toRemove.push(\n          ...matches.named('edition', (m: Match) => m.value === 'Criterion')\n        );\n      }\n    }\n\n    if (process.env.DEBUG_SS) console.log(`[VS.when] returning toRemove.length=${toRemove.length}`);\n    return toRemove;\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Rule, RemoveMatch, AppendMatch, RenameMatch } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport { POST_PROCESS } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround, sepsAfter, sepsBefore } from '../common/validators.js';\nimport { dash, seps , sepsPattern } from '../common/index.js';\nimport { loadConfigPatterns } from '../../config/index.js';\nimport { buildOrPattern } from '../../reutils.js';\nimport { rawCleanup } from '../common/formatters.js';\n\nexport function other(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'other') });\n  rebulk.regexDefaults({ flags: 'i', abbreviations: [dash] }).stringDefaults({ ignoreCase: true });\n  rebulk.defaults({ name: 'other', validator: sepsSurround });\n\n  loadConfigPatterns(rebulk, config['other'] as Record<string, unknown>);\n\n  openingEndingCredits(rebulk);\n\n  rebulk.rules(\n    AppendCreditless,\n    AppendOpedEndingCredits,\n    ValidateStereoVRContext,\n    RenameAnotherToOther,\n    ValidateHasNeighbor,\n    ValidateHasNeighborAfter,\n    ValidateHasNeighborBefore,\n    ValidateScreenerRule,\n    ValidateMuxRule,\n    ValidateHardcodedSubs,\n    ValidateStreamingServiceNeighbor,\n    ValidateAtEnd,\n    ValidateReal,\n    RemoveTitleCaseAmbiguous,\n    ImageArtKeywordToOther,\n    ProperCountRule,\n    FixCountRule\n  );\n\n  return rebulk;\n}\n\n/**\n * In an image file (a filepart with an image container — .jpg/.png/…), a\n * title/alternative_title/episode_title that is exactly an artwork keyword is the\n * artwork kind, not a title — e.g. \"poster.jpg\" → other \"Poster\";\n * \"Movie.2020-fanart.jpg\" → other \"Fanart\". Scoped to image fileparts so it can\n * never clobber a real video title that happens to contain such a word. (#273)\n */\nconst ART_KEYWORDS: Record<string, string> = {\n  poster: 'Poster', fanart: 'Fanart', banner: 'Banner', thumb: 'Thumbnail',\n  thumbnail: 'Thumbnail', landscape: 'Landscape', cover: 'Cover',\n  clearart: 'Clear Art', clearlogo: 'Clear Logo', logo: 'Logo', discart: 'Disc Art',\n};\nclass ImageArtKeywordToOther extends Rule {\n  static priority = POST_PROCESS;\n  consequence = [RemoveMatch, AppendMatch];\n\n  when(matches: any): [Match[], Match[]] | false {\n    const toRemove: Match[] = [];\n    const toAppend: Match[] = [];\n    for (const fp of matches.markers.named('path') as Match[]) {\n      const hasImage = matches.range(fp.start, fp.end,\n        (m: Match) => m.name === 'container' && m.tags?.includes('image'), 0);\n      if (!hasImage) continue;\n      const cands = matches.range(fp.start, fp.end,\n        (m: Match) => ['title', 'alternative_title', 'episode_title'].includes(m.name ?? '')) as Match[];\n      for (const c of cands) {\n        const key = String(c.value ?? '').trim().toLowerCase().replace(/[\\s._-]+/g, '');\n        const canon = ART_KEYWORDS[key];\n        if (!canon) continue;\n        toRemove.push(c);\n        toAppend.push(new Match(c.start, c.end, { name: 'other', value: canon, inputString: matches.inputString }));\n      }\n    }\n    return toRemove.length ? [toRemove, toAppend] : false;\n  }\n}\n\n// Ordinal of an opening/ending sequence, e.g. \"2\" in \"OP02\" or \"4a\" in \"OP4a\".\n// Kept as a string because of variant-letter forms. The leading version \"v\" is\n// excluded so \"ED2v2\" yields number \"2\", version 2. `[^\\W\\d_]` (a letter) avoids\n// a literal '-' which the dash abbreviation would corrupt. (upstream 4.x)\nconst CREDITS_NUMBER = `(?P<credits_number>\\\\d+(?:(?![vV]\\\\d)[^\\\\W\\\\d_])?)?`;\nconst CREDITS_VERSION = `(?:-?[vV](?P<version>\\\\d+))?`;\nconst CREDITS_SUFFIX = CREDITS_NUMBER + CREDITS_VERSION;\n\nfunction formatCreditsNumber(value: string): string {\n  const m = /^(\\d+)(\\w?)$/.exec(value);\n  if (!m) return value;\n  return String(parseInt(m[1], 10)) + m[2].toLowerCase();\n}\n\n/**\n * Match anime opening/ending credit sequences (OP/ED, NCOP/NCED, creditless…).\n * Emits other: \"Opening Credits\"/\"Ending Credits\" plus credits_number (\"4a\") and\n * version. Bare OP/ED tokens are uppercase-only so the name \"Ed\" is never captured.\n */\nfunction openingEndingCredits(rebulk: Rebulk) {\n  const add = (pattern: string, value: string, ignoreCase: boolean) => {\n    rebulk.regex(\n      `(?P<other>` + pattern + `)` + CREDITS_SUFFIX,\n      {\n        flags: ignoreCase ? 'i' : '',\n        name: 'other',\n        children: true,\n        privateParent: true,\n        validateAll: true,\n        validator: { __parent__: sepsSurround },\n        formatter: {\n          other: () => value,\n          credits_number: formatCreditsNumber,\n          version: (v: string) => parseInt(v, 10),\n        },\n        disabled: (context: any) => isDisabled(context, 'other'),\n      } as any,\n    );\n  };\n  // NC*/creditless forms are unambiguous — case-insensitive.\n  add(`NC-?OP|creditless-?op(?:ening)?`, 'Opening Credits', true);\n  add(`NC-?ED|creditless-?(?:ed|ending)`, 'Ending Credits', true);\n  // Bare uppercase tokens. OPED is the combined opening+ending sequence.\n  add(`OPED|OP`, 'Opening Credits', false);\n  add(`ED`, 'Ending Credits', false);\n}\n\n/**\n * Surface a `Creditless` other value for creditless opening/ending tokens\n * (the NC-/creditless- forms). OPED is opening+ending, not creditless. (upstream 4.x)\n */\nclass AppendCreditless extends Rule {\n  static override priority = POST_PROCESS;\n  override priority = POST_PROCESS;\n  override consequence = AppendMatch;\n  static properties = { other: ['Creditless'] };\n\n  when(matches: any, _context: any): any {\n    const toAppend: any[] = [];\n    for (const match of matches.named('other', (m: Match) =>\n      m.value === 'Opening Credits' || m.value === 'Ending Credits') ?? []) {\n      const raw = (match.raw ?? '').toLowerCase().replace(/[\\s._-]+/g, '');\n      if (raw.startsWith('nc') || raw.includes('creditless')) {\n        toAppend.push(new Match(match.start, match.end, {\n          name: 'other', value: 'Creditless', inputString: matches.inputString,\n        }));\n      }\n    }\n    return toAppend.length ? toAppend : false;\n  }\n}\n\n/**\n * OPED is the combined opening AND ending sequence — add the missing\n * `Ending Credits` value over the same span. (upstream 4.x)\n */\nclass AppendOpedEndingCredits extends Rule {\n  static override priority = POST_PROCESS;\n  override priority = POST_PROCESS;\n  override consequence = AppendMatch;\n  static properties = { other: ['Ending Credits'] };\n\n  when(matches: any, _context: any): any {\n    const toAppend: any[] = [];\n    for (const match of matches.named('other', (m: Match) => m.value === 'Opening Credits') ?? []) {\n      if ((match.raw ?? '').toLowerCase().replace(/[\\s._-]+/g, '') === 'oped') {\n        toAppend.push(new Match(match.start, match.end, {\n          name: 'other', value: 'Ending Credits', inputString: matches.inputString,\n        }));\n      }\n    }\n    return toAppend.length ? toAppend : false;\n  }\n}\n\nconst STEREO_VR_CONTEXT_TAG = 'stereo-vr-context';\nconst VR_CONTEXT_VALUES = new Set(['Virtual Reality', '3D']);\n\n/**\n * A stereoscopic abbreviation (SBS/LR/TB/OU) is ambiguous on its own (SBS is\n * also a broadcaster). Keep it only when its filepart carries a VR/3D signal —\n * and then let it win its span over a colliding streaming_service. (upstream 4.x)\n */\nclass ValidateStereoVRContext extends Rule {\n  static override priority = 64;\n  override priority = 64;\n  override consequence = RemoveMatch;\n\n  when(matches: any, _context: any): any {\n    const toRemove: any[] = [];\n    const fileparts = matches.markers.named('path') as Match[];\n    for (const filepart of Array.isArray(fileparts) ? fileparts : fileparts ? [fileparts] : []) {\n      const gated = matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'other' && m.tags.includes(STEREO_VR_CONTEXT_TAG)) as Match[];\n      if (!gated?.length) continue;\n      const hasVrContext = (matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'other' && VR_CONTEXT_VALUES.has(String(m.value))) as Match[])?.length > 0;\n      if (hasVrContext) {\n        for (const stereo of gated) {\n          toRemove.push(...(matches.range(stereo.start, stereo.end,\n            (m: Match) => m.name === 'streaming_service') as Match[] ?? []));\n        }\n      } else {\n        toRemove.push(...gated);\n      }\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\nconst TOKEN_START = `(?<![^\\\\W_])`;\n\nexport function completeWords(\n  rebulk: Rebulk,\n  opts: {\n    completeMarkerWords: string[];\n    seasonWords: string[];\n    completeArticleWords: string[];\n    completePrefixWords: string[];\n    seasonNumberSeparators: string[];\n  },\n) {\n  const completeMarkerPattern = buildOrPattern(opts.completeMarkerWords);\n  const seasonWordsPattern = buildOrPattern(opts.seasonWords);\n  const completeArticleWordsPattern = buildOrPattern(opts.completeArticleWords);\n  // The season numbers listed between the season word and the marker: \"1\", \"1 & 2\", \"1 and 2\".\n  const seasonNumbersPattern =\n    `(?:-+(?:\\\\d+|` + buildOrPattern(opts.seasonNumberSeparators, undefined, true) + `))+-+`;\n\n  function validateComplete(match: Match) {\n    const children = match.children;\n    if (!children.named('completeWordsBefore') && !children.named('completeWordsAfter')) {\n      return false;\n    }\n    return true;\n  }\n\n  rebulk.regex(\n    TOKEN_START +\n    `(?P<completeArticle>${completeArticleWordsPattern}-)?` +\n    `(?P<completeWordsBefore>${seasonWordsPattern}-)?` +\n    completeMarkerPattern +\n    `(?P<completeWordsAfter>-${seasonWordsPattern})?`,\n    {\n      privateNames: ['completeArticle', 'completeWordsBefore', 'completeWordsAfter'],\n      value: { other: 'Complete' },\n      tags: ['release-group-prefix'],\n      validator: {\n        __parent__: (m: Match) => sepsSurround(m) && validateComplete(m),\n      },\n    }\n  );\n\n  // \"Season 1 Complete\", \"Seasons 1 & 2 - Complete\": the season numbers sit between the\n  // season word and the marker, so the adjacency pattern above cannot see the word.\n  rebulk.regex(\n    seasonWordsPattern + seasonNumbersPattern + `(?P<other>` + completeMarkerPattern + `)`,\n    {\n      children: true,\n      privateParent: true,\n      validateAll: true,\n      value: { other: 'Complete' },\n      tags: ['release-group-prefix'],\n      validator: { __parent__: sepsSurround },\n    }\n  );\n\n  // \"L'Intégrale\", \"Coffret Intégrale\": the prefix carries the completeness with no season\n  // word to anchor on. The separator is optional because the French elided article glues to\n  // the marker (\"L'Intégrale\" is a single token).\n  rebulk.regex(\n    TOKEN_START +\n    `(?P<completePrefix>` + buildOrPattern(opts.completePrefixWords) + `-?)` +\n    completeMarkerPattern,\n    {\n      privateNames: ['completePrefix'],\n      value: { other: 'Complete' },\n      tags: ['release-group-prefix'],\n      validator: { __parent__: sepsSurround },\n    }\n  );\n}\n\nclass ProperCountRule extends Rule {\n  static priority = POST_PROCESS;\n  static consequence = AppendMatch;\n  static properties = { proper_count: [null] };\n\n  when(matches: any, context: Record<string, unknown>) {\n    const propers = matches.named('other', (m: Match) => m.value === 'Proper');\n    if (!propers || propers.length === 0) {\n      return;\n    }\n\n    const raws: Record<string, Match> = {};\n    for (const proper of propers) {\n      raws[rawCleanup(proper.raw)] = proper;\n    }\n\n    let value = 0;\n    let start: number | null = null;\n    let end: number | null = null;\n\n    for (const proper of Object.values(raws)) {\n      if (!start || start > proper.start) {\n        start = proper.start;\n      }\n      if (!end || end < proper.end) {\n        end = proper.end;\n      }\n      const properCount = proper.children.named('proper_count', null, 0) as Match | undefined;\n      if (properCount) {\n        value += parseInt(String((properCount as Match).value), 10);\n      } else if (proper.tags.includes('real')) {\n        value += 2;\n      } else {\n        value += 1;\n      }\n    }\n\n    const properCountMatch = new Match(start!, end!, {\n      name: 'proper_count',\n    });\n    properCountMatch.value = value;\n\n    return [properCountMatch];\n  }\n}\n\nclass FixCountRule extends Rule {\n  static priority = POST_PROCESS;\n  static consequence = AppendMatch;\n  static properties = { proper_count: [null] };\n\n  when(matches: any) {\n    const fixes = (matches.named('other', (m: Match) => m.value === 'Fix') as Match[])\n      .filter((m: Match) => {\n        // Only standalone Fix/Fixed should generate proper_count.\n        // Compound fixes like Dirfix, Nfofix, Prooffix should not.\n        const raw = rawCleanup(m.raw ?? '').toLowerCase();\n        return raw === 'fix' || raw === 'fixed';\n      });\n    if (!fixes || fixes.length === 0) return;\n\n    // Check if proper_count already set\n    const existing = matches.named('proper_count');\n    if (existing && (Array.isArray(existing) ? existing.length > 0 : true)) return;\n\n    let start: number | null = null;\n    let end: number | null = null;\n    for (const fix of fixes) {\n      if (start === null || fix.start < start) start = fix.start;\n      if (end === null || fix.end > end) end = fix.end;\n    }\n\n    const m = new Match(start!, end!, { name: 'proper_count' });\n    m.value = -1;\n    return [m];\n  }\n}\n\nclass RenameAnotherToOther extends Rule {\n  static priority = 32;\n  static consequence = new RenameMatch('other');\n\n  when(matches: any) {\n    return matches.named('another');\n  }\n}\n\nclass ValidateHasNeighbor extends Rule {\n  static consequence = RemoveMatch;\n  static priority = 64;\n\n  when(matches: any) {\n    const ret = [];\n    for (const toCheck of matches.range(0, undefined, (m: Match) => m.tags.includes('has-neighbor'))) {\n      let previousMatch = matches.previous(toCheck, (m: Match) => true, 0);\n      let previousGroup = matches.markers.previous(\n        toCheck,\n        (m: Match) => m.name === 'group',\n        0\n      );\n      if (previousGroup && (!previousMatch || previousGroup.end > previousMatch.end)) {\n        previousMatch = previousGroup;\n      }\n      if (\n        previousMatch &&\n        !matches.inputString\n          .slice(previousMatch.end, toCheck.start)\n          .replace(new RegExp(`[${sepsPattern}]`, 'g'), '')\n      ) {\n        continue;\n      }\n      let nextMatch = matches.next(toCheck, (m: Match) => true, 0);\n      let nextGroup = matches.markers.next(toCheck, (m: Match) => m.name === 'group', 0);\n      if (nextGroup && (!nextMatch || nextGroup.start < nextMatch.start)) {\n        nextMatch = nextGroup;\n      }\n      if (\n        nextMatch &&\n        !matches.inputString\n          .slice(toCheck.end, nextMatch.start)\n          .replace(new RegExp(`[${sepsPattern}]`, 'g'), '')\n      ) {\n        continue;\n      }\n      ret.push(toCheck);\n    }\n    return ret;\n  }\n}\n\nclass ValidateHasNeighborBefore extends Rule {\n  static consequence = RemoveMatch;\n  static priority = 64;\n\n  when(matches: any) {\n    const ret = [];\n    for (const toCheck of matches.range(0, undefined, (m: Match) => m.tags.includes('has-neighbor-before'))) {\n      let previousMatch = matches.previous(toCheck, (m: Match) => true, 0);\n      let previousGroup = matches.markers.previous(\n        toCheck,\n        (m: Match) => m.name === 'group',\n        0\n      );\n      if (previousGroup && (!previousMatch || previousGroup.end > previousMatch.end)) {\n        previousMatch = previousGroup;\n      }\n      if (\n        previousMatch &&\n        !matches.inputString\n          .slice(previousMatch.end, toCheck.start)\n          .replace(new RegExp(`[${sepsPattern}]`, 'g'), '')\n      ) {\n        continue;\n      }\n      ret.push(toCheck);\n    }\n    return ret;\n  }\n}\n\nclass ValidateHasNeighborAfter extends Rule {\n  static consequence = RemoveMatch;\n  static priority = 64;\n\n  when(matches: any) {\n    const ret = [];\n    for (const toCheck of matches.range(0, undefined, (m: Match) =>\n      m.tags.includes('has-neighbor-after')\n    )) {\n      let nextMatch = matches.next(toCheck, (m: Match) => true, 0);\n      let nextGroup = matches.markers.next(toCheck, (m: Match) => m.name === 'group', 0);\n      if (nextGroup && (!nextMatch || nextGroup.start < nextMatch.start)) {\n        nextMatch = nextGroup;\n      }\n      if (\n        nextMatch &&\n        !matches.inputString\n          .slice(toCheck.end, nextMatch.start)\n          .replace(new RegExp(`[${sepsPattern}]`, 'g'), '')\n      ) {\n        continue;\n      }\n      ret.push(toCheck);\n    }\n    return ret;\n  }\n}\n\nclass ValidateScreenerRule extends Rule {\n  static consequence = RemoveMatch;\n  static priority = 64;\n\n  when(matches: any) {\n    const ret = [];\n    for (const screener of matches.named(\n      'other',\n      (m: Match) => m.tags.includes('other.validate.screener')\n    )) {\n      const sourceMatch = matches.previous(\n        screener,\n        (m: Match) => m.initiator?.name === 'source',\n        0\n      );\n      if (!sourceMatch || matches.inputString\n        .slice(sourceMatch.end, screener.start)\n        .replace(new RegExp(`[${sepsPattern}]`, 'g'), '')) {\n        ret.push(screener);\n      }\n    }\n    return ret;\n  }\n}\n\nclass ValidateMuxRule extends Rule {\n  static consequence = RemoveMatch;\n  static priority = 64;\n\n  when(matches: any) {\n    const ret = [];\n    for (const mux of matches.named(\n      'other',\n      (m: Match) => m.tags.includes('other.validate.mux')\n    )) {\n      const sourceMatch = matches.previous(\n        mux,\n        (m: Match) => m.initiator?.name === 'source',\n        0\n      );\n      if (!sourceMatch) {\n        ret.push(mux);\n      }\n    }\n    return ret;\n  }\n}\n\nclass ValidateHardcodedSubs extends Rule {\n  static priority = 32;\n  static consequence = RemoveMatch;\n\n  when(matches: any) {\n    // In Python guessit, standalone HC (no adjacent subtitle_language) is kept in other.\n    // Only remove HC when a subtitle_language is present elsewhere in the filepart but\n    // is NOT directly adjacent (with no holes between) — this prevents false HC tagging.\n    // For practical purposes: keep all HC matches (never remove standalone HC).\n    // HC adjacent to subtitle_language is also kept (it strengthens the subtitle info).\n    return [];\n  }\n}\n\nclass ValidateStreamingServiceNeighbor extends Rule {\n  static priority = 32;\n  static consequence = RemoveMatch;\n\n  when(matches: any) {\n    const toRemove = [];\n    for (const match of matches.named(\n      'other',\n      (m: Match) =>\n        m.initiator?.name !== 'source' &&\n        (m.tags.includes('streaming_service.prefix') ||\n          m.tags.includes('streaming_service.suffix'))\n    )) {\n      let initiatorMatch = match.initiator;\n      if (!sepsAfter(initiatorMatch)) {\n        if (initiatorMatch.tags.includes('streaming_service.prefix')) {\n          const nextMatch = matches.next(\n            initiatorMatch,\n            (m: Match) => m.name === 'streaming_service',\n            0\n          );\n          if (\n            nextMatch &&\n            !(matches.holes(initiatorMatch.end, nextMatch.start, (m: Match) =>\n              String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')\n            ) as Match[]).length\n          ) {\n            continue;\n          }\n        }\n        if (initiatorMatch.children) {\n          toRemove.push(...initiatorMatch.children);\n        }\n        toRemove.push(initiatorMatch);\n      } else if (!sepsBefore(initiatorMatch)) {\n        if (initiatorMatch.tags.includes('streaming_service.suffix')) {\n          const previousMatch = matches.previous(\n            initiatorMatch,\n            (m: Match) => m.name === 'streaming_service',\n            0\n          );\n          if (\n            previousMatch &&\n            !(matches.holes(previousMatch.end, initiatorMatch.start, (m: Match) =>\n              String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')\n            ) as Match[]).length\n          ) {\n            continue;\n          }\n        }\n\n        if (initiatorMatch.children) {\n          toRemove.push(...initiatorMatch.children);\n        }\n        toRemove.push(initiatorMatch);\n      }\n    }\n\n    return toRemove;\n  }\n}\n\nclass ValidateAtEnd extends Rule {\n  static priority = 32;\n  static consequence = RemoveMatch;\n\n  when(matches: any) {\n    const toRemove = [];\n    for (const filepart of matches.markers.named('path')) {\n      for (const match of matches.range(\n        filepart.start,\n        filepart.end,\n        (m: Match) => m.name === 'other' && m.tags.includes('at-end')\n      )) {\n        if (\n          (matches.holes(match.end, filepart.end, (m: Match) =>\n            String(m.value).replace(new RegExp(`[${sepsPattern}]`, 'g'), '')\n          ) as Match[]).length ||\n          (matches.range(match.end, filepart.end, (m: Match) =>\n            !['other', 'container'].includes(m.name ?? '')\n          ) as Match[]).length\n        ) {\n          toRemove.push(match);\n        }\n      }\n    }\n\n    return toRemove;\n  }\n}\n\n/**\n * Remove ambiguous word-values (Proper←\"real\", Converted←\"convert\",\n * Camera←\"cam\") when their raw text is Title-Case (initial capital, rest\n * lowercase). Scene tags are ALL-CAPS (\"REAL\", \"CAM\", \"CONVERT\") or all-lower;\n * a Title-Case spelling means it's a title word, e.g. \"The Cam\", \"Something\n * Real\", \"The Convert\". Runs before TitleFromPosition so the freed word rejoins\n * the title/episode_title. (Issues #732, #743, #746, #784.)\n */\nclass RemoveTitleCaseAmbiguous extends Rule {\n  static consequence = RemoveMatch;\n  static priority = 64;\n\n  // Exact Title-Case spellings of words that double as common title words. The\n  // canonical tag spellings (\"PROPER\", \"REAL.PROPER\", \"CAM\", \"CONVERT\") and\n  // lowercase scene spellings are unaffected; only the Title-Case word is removed.\n  when(matches: any) {\n    const TITLE_WORDS = new Set(['Real', 'Cam', 'Convert']);\n    const RELEASE_META = new Set(['screen_size', 'video_codec', 'audio_codec', 'video_profile', 'release_group']);\n    const ret: Match[] = [];\n    for (const m of matches.range(0, matches.inputString?.length ?? 0) as Match[]) {\n      if (m.name !== 'other' && m.name !== 'source') continue;\n      if (!TITLE_WORDS.has(m.raw ?? '')) continue;\n      // A word surrounded by release metadata is a real scene tag regardless of its\n      // case: \"Show.S01E01.Cam.720p.x264\" is a CAM release. (upstream #732 refinement)\n      const filepart = matches.markers.atMatch(m, (marker: Match) => marker.name === 'path', 0) as Match | undefined;\n      const searchEnd = filepart?.end ?? (matches.inputString?.length ?? m.end);\n      const metaAfter = (matches.range(m.end, searchEnd,\n        (o: Match) => !o.private && RELEASE_META.has(o.name ?? '')) as Match[]) ?? [];\n      if (metaAfter.length > 0) continue;\n      ret.push(m);\n    }\n    return ret.length ? ret : false;\n  }\n}\n\nclass ValidateReal extends Rule {\n  static consequence = RemoveMatch;\n  static priority = 64;\n\n  when(matches: any) {\n    const ret = [];\n    for (const filepart of matches.markers.named('path')) {\n      for (const match of matches.range(\n        filepart.start,\n        filepart.end,\n        (m: Match) => m.name === 'other' && m.tags.includes('real')\n      )) {\n        // Python: `if not matches.range(...)` — empty list is falsy in Python but truthy in JS.\n        // Must check .length explicitly.\n        const before = matches.range(filepart.start, match.start) as Match[];\n        if (!before || before.length === 0) {\n          ret.push(match);\n        }\n      }\n    }\n\n    return ret;\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { dash } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { Size } from '../common/quantity.js';\n\nexport function size(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'size') });\n  rebulk.regexDefaults({ flags: 'i', abbreviations: [dash] });\n  rebulk.defaults({ name: 'size', validator: sepsSurround });\n  rebulk.regex('\\\\d+-?[mgt]b', '\\\\d+\\\\.\\\\d+-?[mgt]b', {\n    formatter: (s: string) => Size.fromstring(s).toString(),\n    tags: ['release-group-prefix'],\n  });\n\n  return rebulk;\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Rule, RemoveMatch, RenameMatch } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport { dash, seps , sepsPattern } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { loadConfigPatterns, registerFunction } from '../../config/index.js';\nimport { BitRate } from '../common/quantity.js';\n\n// Register the BitRate formatter so config's import:guessit.rules.common.quantity:BitRate.fromstring resolves.\n// We return a string directly so the final result is serialized correctly.\nregisterFunction(\n  'guessit.rules.common.quantity:BitRate.fromstring',\n  (s: string) => BitRate.fromstring(s).toString(),\n);\n\nexport function bitRate(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({\n    disabled: (context) =>\n      isDisabled(context, 'audio_bit_rate') && isDisabled(context, 'video_bit_rate'),\n  });\n  rebulk.regexDefaults({ flags: 'i', abbreviations: [dash] });\n  rebulk.defaults({ name: 'audio_bit_rate', validator: sepsSurround });\n\n  loadConfigPatterns(rebulk, config['bit_rate'] as Record<string, unknown>);\n\n  rebulk.rules(BitRateTypeRule);\n\n  return rebulk;\n}\n\nclass BitRateTypeRule extends Rule {\n  static consequence = [new RenameMatch('video_bit_rate'), RemoveMatch];\n\n  when(matches: any, context: Record<string, unknown>) {\n    const toRename = [];\n    const toRemove = [];\n\n    if (isDisabled(context, 'audio_bit_rate')) {\n      toRemove.push(...matches.named('audio_bit_rate'));\n    } else {\n      const videoBitRateDisabled = isDisabled(context, 'video_bit_rate');\n      for (const match of matches.named('audio_bit_rate')) {\n        const previous = matches.previous(\n          match,\n          (m: Match) => ['source', 'screen_size', 'video_codec'].includes(m.name ?? ''),\n          0\n        );\n        // Check for only-separator text between previous and current match\n        const inputStr = matches.inputString ?? '';\n        const onlySepsBetween = (a: number, b: number) =>\n          inputStr.slice(a, b).replace(new RegExp(`[${sepsPattern}]`, 'g'), '') === '';\n\n        const noHolesBefore = previous ? onlySepsBetween(previous.end, match.start) : false;\n\n        if (previous && noHolesBefore) {\n          const bitrate = String(match.value);\n          const lc = bitrate.toLowerCase();\n          const isKbps = /kbps$|kbits?$/.test(lc);\n\n          // Path A: audio_codec follows immediately (only seps between) → rename if not audio rate\n          const after = matches.next(\n            match,\n            (m: Match) => m.name === 'audio_codec',\n            0\n          );\n          if (after && onlySepsBetween(match.end, after.start)) {\n            if (!isKbps) {\n              if (videoBitRateDisabled) {\n                toRemove.push(match);\n              } else {\n                toRename.push(match);\n              }\n            }\n            continue;\n          }\n\n          // Path B: no audio_codec after, but Mbps bit_rate after video-related match → video\n          if (!isKbps) {\n            if (videoBitRateDisabled) {\n              toRemove.push(match);\n            } else {\n              toRename.push(match);\n            }\n          }\n        }\n      }\n    }\n\n    if (toRename.length || toRemove.length) {\n      return [toRename, toRemove];\n    }\n    return false;\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { dash } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { loadConfigPatterns } from '../../config/index.js';\n\nexport function edition(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'edition') });\n  rebulk.regexDefaults({ flags: 'i', abbreviations: [dash] }).stringDefaults({ ignoreCase: true });\n  rebulk.defaults({ name: 'edition', validator: sepsSurround });\n\n  loadConfigPatterns(rebulk, config['edition'] as Record<string, unknown>);\n\n  return rebulk;\n}\n","import { Rebulk } from 'rebulk-js';\nimport { dash } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { loadConfigPatterns } from '../../config/index.js';\n\nexport function cd(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'cd') });\n  rebulk.regexDefaults({ flags: 'i', abbreviations: [dash] });\n\n  loadConfigPatterns(rebulk, config);\n\n  return rebulk;\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Rule, AppendMatch } from 'rebulk-js';\nimport { Match, Matches } from 'rebulk-js';\nimport { cleanup } from '../common/formatters.js';\nimport { seps } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { loadConfigPatterns } from '../../config/index.js';\n\nexport function bonus(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'bonus') });\n  rebulk.regexDefaults({ name: 'bonus', flags: 'i' });\n\n  loadConfigPatterns(rebulk, config['bonus'] as Record<string, unknown>);\n\n  rebulk.rules(BonusAtFilepartStartRule, BonusToEpisodeRule, BonusTitleRule);\n\n  return rebulk;\n}\n\n/**\n * The `x\\d+` bonus pattern is a feature *appended after a title* (e.g.\n * \"Band_of_Brothers-x02-...\", \"Moon_(2009)-x02-Making_Of\"). When it instead sits\n * at the very start of its filepart with no title content before it, it isn't a\n * bonus at all — it's the title itself (e.g. \"X2.2003.720p...\" -> title \"X2\",\n * the film https://en.wikipedia.org/wiki/X2_(film)).\n *\n * Remove such matches before title detection runs so the text becomes a hole and\n * is picked up as the title (and a following year stays a year, not a bonus_title).\n * Runs at priority 128 — ahead of BonusToEpisodeRule (64), BonusTitleRule and\n * TitleFromPosition (0).\n */\nclass BonusAtFilepartStartRule extends Rule {\n  static override priority = 128;\n\n  override when(matches: Matches): Match[] {\n    const inputString = matches.inputString || '';\n    const bonuses = (matches.named('bonus') as Match[])?.filter((m: Match) => !m.private) ?? [];\n    const toRemove: Match[] = [];\n    for (const bonus of bonuses) {\n      const filepart = matches.markers.atMatch(bonus, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      // The bonus child captures only the digits; the private parent spans the\n      // leading \"x\" too. Fall back to the char before the digits if no parent.\n      const parent = (bonus as any).parent as Match | undefined;\n      const xStart = parent ? parent.start : bonus.start - 1;\n      // Title-position only when nothing but separators precede the \"x\" in the filepart.\n      const before = inputString.slice(filepart.start, xStart);\n      if ([...before].every((c) => seps.includes(c))) {\n        toRemove.push(bonus);\n        if (parent) toRemove.push(parent);\n      }\n    }\n    return toRemove;\n  }\n\n  override then(matches: Matches, whenResponse: unknown): void {\n    for (const m of whenResponse as Match[]) {\n      matches.remove(m);\n    }\n  }\n}\n\n/**\n * When a bonus match follows a season-only match (no episode in the same filepart),\n * convert the bonus to an episode. E.g. \"Parks_and_Recreation-s03-x01\" -> episode=1 not bonus=1.\n */\nclass BonusToEpisodeRule extends Rule {\n  static override priority = 64;\n\n  override when(matches: Matches): Match[] {\n    const bonuses = (matches.named('bonus') as Match[])?.filter((m: Match) => !m.private) ?? [];\n    const toConvert: Match[] = [];\n    for (const bonus of bonuses) {\n      const filepart = matches.markers.atMatch(bonus, (m: Match) => m.name === 'path', 0) as Match | undefined;\n      if (!filepart) continue;\n      const hasSeason = !!(matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'season' && !m.private, 0) as Match | undefined);\n      const hasEpisode = !!(matches.range(filepart.start, filepart.end,\n        (m: Match) => m.name === 'episode' && !m.private, 0) as Match | undefined);\n      if (hasSeason && !hasEpisode) {\n        toConvert.push(bonus);\n      }\n    }\n    return toConvert;\n  }\n\n  override then(matches: Matches, whenResponse: unknown): void {\n    const toConvert = whenResponse as Match[];\n    for (const bonus of toConvert) {\n      matches.remove(bonus);\n      bonus.name = 'episode';\n      matches.append(bonus);\n    }\n  }\n}\n\n/**\n * Names that indicate \"real\" property boundaries that should stop the bonus title.\n * Year is NOT included because it can be part of the bonus title.\n */\nconst BOUNDARY_NAMES = new Set([\n  'source', 'video_codec', 'audio_codec', 'screen_size',\n  'container', 'release_group', 'language', 'country', 'other',\n  'streaming_service', 'edition', 'audio_channels',\n  'season', 'date',\n]);\n\nclass BonusTitleRule extends Rule {\n  static dependency = ['TitleFromPosition'];\n  static properties = { bonus_title: [null] };\n\n  when(matches: any) {\n    const bonusNumber = matches.named(\n      'bonus',\n      (m: Match) => !m.private,\n      0\n    );\n    if (!bonusNumber) return;\n\n    const filepath = matches.markers.atMatch(\n      bonusNumber,\n      (m: Match) => m.name === 'path',\n      0\n    );\n    if (!filepath) return;\n\n    // First, check if there's a title/alternative_title/episode_title match after the bonus number\n    const titleAfterBonus = matches.range(\n      bonusNumber.end,\n      filepath.end + 1,\n      (m: Match) => (m.name === 'title' || m.name === 'alternative_title' || m.name === 'episode_title') && !m.private,\n      0,\n    );\n    if (titleAfterBonus && titleAfterBonus.value) {\n      const inputString = matches.inputString || '';\n      const containerMatch = matches.range(\n        bonusNumber.end,\n        filepath.end + 1,\n        (m: Match) => m.name === 'container' && !m.private,\n        0,\n      ) as Match | undefined;\n      const maxEnd = containerMatch ? containerMatch.start : filepath.end;\n\n      // Extend the bonus title span backward to include any text between bonus and the title\n      let btStart = bonusNumber.end;\n      while (btStart < titleAfterBonus.start && /[\\s._\\-]/.test(inputString[btStart])) btStart++;\n\n      // Extend forward: include year matches right after the title ONLY if there's\n      // no other text between the year and the container/end\n      let btEnd = titleAfterBonus.end;\n      // Check for year match immediately after the title (with just seps between)\n      const yearAfterTitle = matches.range(\n        titleAfterBonus.end,\n        maxEnd,\n        (m: Match) => !m.private && m.name === 'year',\n        0,\n      ) as Match | undefined;\n      if (yearAfterTitle) {\n        // Check if there's only seps between title end and year, and only seps between year and end\n        const gapBefore = inputString.slice(titleAfterBonus.end, yearAfterTitle.start);\n        const gapAfter = inputString.slice(yearAfterTitle.end, maxEnd);\n        const onlySesBefore = [...gapBefore].every(c => /[\\s._\\-]/.test(c));\n        const onlySepsAfter = [...gapAfter].every(c => /[\\s._\\-]/.test(c));\n        if (onlySesBefore && onlySepsAfter) {\n          // Year is the last thing before container - include it in bonus title\n          btEnd = yearAfterTitle.end;\n        }\n      }\n\n      const rawText = inputString.slice(btStart, btEnd);\n      const bonusTitleValue = cleanup(rawText);\n\n      // Remove the title match and any matches in the extended range\n      const toRemove: Match[] = [titleAfterBonus];\n      const allMatchesInRange = (matches.range(\n        btStart,\n        btEnd,\n        (m: Match) => !m.private && m.name !== 'bonus' && m.name !== 'container',\n      ) as Match[]) || [];\n      for (const m of allMatchesInRange) {\n        if (!toRemove.includes(m)) toRemove.push(m);\n      }\n\n      const bonusTitle = new Match(btStart, btEnd, {\n        name: 'bonus_title',\n        value: bonusTitleValue || cleanup(String(titleAfterBonus.value)),\n        inputString,\n      });\n      return { toRemove, toAppend: [bonusTitle] };\n    }\n\n    // Fallback: construct bonus title from raw text between bonus and first boundary match\n    const inputString = matches.inputString || '';\n\n    // Find the container position\n    const containerMatch = matches.range(\n      bonusNumber.end,\n      filepath.end + 1,\n      (m: Match) => m.name === 'container' && !m.private,\n      0,\n    ) as Match | undefined;\n    const maxEnd = containerMatch ? containerMatch.start : filepath.end;\n\n    // Find boundary matches after bonus (these stop the bonus title)\n    const boundaryMatches = (matches.range(\n      bonusNumber.end,\n      maxEnd,\n      (m: Match) => !m.private && BOUNDARY_NAMES.has(m.name ?? ''),\n    ) as Match[]) || [];\n    boundaryMatches.sort((a: Match, b: Match) => a.start - b.start);\n\n    // End at first boundary match or container/filepart end\n    let endPos = maxEnd;\n    if (boundaryMatches.length > 0) {\n      endPos = boundaryMatches[0].start;\n    }\n\n    // Get raw text\n    let start = bonusNumber.end;\n    while (start < endPos && /[\\s._\\-]/.test(inputString[start])) start++;\n    let end = endPos;\n    while (end > start && /[\\s._\\-]/.test(inputString[end - 1])) end--;\n\n    if (start >= end) return;\n\n    const rawText = inputString.slice(start, end);\n    const bonusTitleValue = cleanup(rawText);\n    if (!bonusTitleValue) return;\n\n    // Remove any matches that fall entirely within the bonus title range\n    const toRemove: Match[] = [];\n    const matchesInRange = (matches.range(\n      start,\n      end,\n      (m: Match) => !m.private && m.name !== 'bonus' && m.name !== 'container',\n    ) as Match[]) || [];\n    for (const m of matchesInRange) {\n      toRemove.push(m);\n    }\n\n    const bonusTitle = new Match(start, end, {\n      name: 'bonus_title',\n      value: bonusTitleValue,\n      inputString,\n    });\n\n    return { toRemove, toAppend: [bonusTitle] };\n  }\n\n  then(matches: any, whenResponse: any): void {\n    if (!whenResponse) return;\n    if (whenResponse instanceof Match) {\n      matches.append(whenResponse);\n      return;\n    }\n    const { toRemove, toAppend } = whenResponse;\n    for (const m of toRemove) {\n      matches.remove(m);\n    }\n    for (const m of toAppend) {\n      matches.append(m);\n    }\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Rule, AppendMatch, RemoveMatch } from 'rebulk-js';\nimport type { Match } from 'rebulk-js';\nimport { dash } from '../common/index.js';\nimport { cleanup } from '../common/formatters.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport { loadConfigPatterns } from '../../config/index.js';\n\nexport function film(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'film') });\n  rebulk.regexDefaults({ flags: 'i', abbreviations: [dash] }).stringDefaults({ ignoreCase: true });\n  rebulk.defaults({ name: 'film', validator: sepsSurround });\n\n  loadConfigPatterns(rebulk, config['film'] as Record<string, unknown>);\n\n  rebulk.rules(LeadingFilmNumberRule, FilmTitleRule);\n\n  return rebulk;\n}\n\n/**\n * Discard a film number that leads the filepart with nothing before it. A collection\n * number only makes sense after a collection title (\"James Bond f17\"); when f\\d opens\n * the name with no title ahead, it belongs to the title itself (\"F1 The Movie\").\n * (upstream #751)\n */\nclass LeadingFilmNumberRule extends Rule {\n  static consequence = RemoveMatch;\n  override consequence = RemoveMatch;\n\n  when(matches: any, _context: any) {\n    const toRemove: any[] = [];\n    const films = matches.named('film', (m: Match) => !m.private) ?? [];\n    for (const filmMatch of Array.isArray(films) ? films : [films]) {\n      const filepath = matches.markers.atMatch(filmMatch, (m: Match) => m.name === 'path', 0);\n      if (!filepath) continue;\n      const hole = matches.holes(filepath.start, filmMatch.start + 1,\n        { formatter: cleanup, index: 0 });\n      if (!(hole && hole.value)) {\n        toRemove.push(filmMatch);\n        if (filmMatch.parent) toRemove.push(filmMatch.parent);\n      }\n    }\n    return toRemove.length ? toRemove : false;\n  }\n}\n\nclass FilmTitleRule extends Rule {\n  static consequence = AppendMatch;\n  static properties = { film_title: [null] };\n\n  enabled(context: Record<string, unknown>) {\n    return !isDisabled(context, 'film_title');\n  }\n\n  when(matches: any) {\n    const bonusNumber = matches.named(\n      'film',\n      (m: Match) => !m.private,\n      0\n    );\n    if (bonusNumber) {\n      const filepath = matches.markers.atMatch(\n        bonusNumber,\n        (m: Match) => m.name === 'path',\n        0\n      );\n      if (!filepath) return;\n      const hole = matches.holes(\n        filepath.start,\n        bonusNumber.start + 1,\n        {\n          formatter: cleanup,\n          predicate: (h: Match) => !!h.value,\n          index: 0,\n        }\n      );\n      if (hole && hole.value) {\n        hole.name = 'film_title';\n        return hole;\n      }\n    }\n  }\n}\n","import { Rebulk } from 'rebulk-js';\nimport { dash } from '../common/index.js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround, intCoercable, and_ } from '../common/validators.js';\nimport { parseNumber } from '../common/numeral.js';\nimport { buildOrPattern } from '../../reutils.js';\n\nexport function part(config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'part') });\n  rebulk.regexDefaults({\n    flags: 'i',\n    abbreviations: [dash],\n    validator: { __parent__: sepsSurround },\n  });\n\n  const prefixes = config['prefixes'] as string[];\n  const wordNumerals = [\n    'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten',\n    'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty',\n  ];\n  const numeral = `(?:\\\\d+|[ivxlcdm]+|${wordNumerals.join('|')})`;\n\n  function validateRoman(match: any) {\n    if (intCoercable(match.raw)) {\n      return true;\n    }\n    return sepsSurround(match);\n  }\n\n  rebulk.regex(\n    `${buildOrPattern(prefixes)}-?(?P<part>${numeral})`,\n    {\n      prefixes,\n      validateAll: true,\n      privateParent: true,\n      children: true,\n      formatter: parseNumber,\n      validator: {\n        part: and_(\n          validateRoman,\n          (m: any) => 0 < (m.value as number) && (m.value as number) < 100\n        ),\n      },\n    }\n  );\n\n  return rebulk;\n}\n","/**\n * crc32 and uuid property — port of guessit/rules/properties/crc.py\n */\nimport { Rebulk } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\nimport type { Match } from 'rebulk-js';\n\nconst DIGIT = 0;\nconst LETTER = 1;\nconst OTHER = 2;\n\nconst IDNUM_SOURCE = '[a-zA-Z0-9-]{20,}';\n\nfunction guessIdnumber(str: string): Array<[number, number]> {\n  const ret: Array<[number, number]> = [];\n  const regex = new RegExp(IDNUM_SOURCE, 'g');\n  let match: RegExpExecArray | null;\n\n  while ((match = regex.exec(str)) !== null) {\n    const uuid = match[0];\n    let switchCount = 0;\n    let switchLetterCount = 0;\n    let letterCount = 0;\n    let lastLetter: string | null = null;\n    let last = LETTER;\n\n    for (const c of uuid) {\n      let ci: number;\n      if ('0123456789'.includes(c)) {\n        ci = DIGIT;\n      } else if (/[a-zA-Z]/.test(c)) {\n        ci = LETTER;\n        if (c !== lastLetter) switchLetterCount++;\n        lastLetter = c;\n        letterCount++;\n      } else {\n        ci = OTHER;\n      }\n      if (ci !== last) switchCount++;\n      last = ci;\n    }\n\n    const switchRatio = switchCount / uuid.length;\n    const lettersRatio = letterCount > 0 ? switchLetterCount / letterCount : 1;\n\n    if (switchRatio > 0.4 && lettersRatio > 0.4) {\n      // Skip matches that look like SxxExx episode patterns (e.g. \"S01E01E07-FooBar-Group\")\n      if (/^[sS]\\d+[eE]\\d+/i.test(uuid)) continue;\n      ret.push([match.index, match.index + uuid.length]);\n    }\n  }\n\n  return ret;\n}\n\nexport function crc(_config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk({ disabled: (context: Record<string, unknown>) => isDisabled(context, 'crc32') });\n  rebulk.regexDefaults({ flags: 'i' });\n  rebulk.defaults({ validator: sepsSurround });\n\n  rebulk.regex('(?:[a-fA-F]|[0-9]){8}', {\n    name: 'crc32',\n    conflictSolver: (_match: Match, other: Match) =>\n      ['episode', 'season'].includes(other.name ?? '') ? other : '__default__',\n  });\n\n  rebulk.regex('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', {\n    name: 'uuid',\n    validator: undefined,\n    conflictSolver: (_match: Match, other: Match) =>\n      ['episode', 'season', 'crc32'].includes(other.name ?? '') ? other : '__default__',\n  });\n\n  rebulk.functional(guessIdnumber, {\n    name: 'uuid',\n    conflictSolver: (_match: Match, other: Match) =>\n      ['episode', 'season', 'crc32'].includes(other.name ?? '') ? other : '__default__',\n  });\n\n  return rebulk;\n}\n","/**\n * imdb_id property — extracts an IMDb id (e.g. tt1234567) from the filename.\n *\n * Not present in Python guessit; this is a guessit-js enhancement (upstream\n * feature request guessit-io/guessit#622). IMDb ids are `tt` followed by 7–8\n * digits and appear in release names like \"Movie.2020.tt1234567.1080p…\" or\n * \"[tt12345678]\".\n */\nimport { Rebulk } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\n\nexport function imdb(_config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk({ disabled: (context: Record<string, unknown>) => isDisabled(context, 'imdb_id') });\n  rebulk.regexDefaults({ flags: 'i' });\n  rebulk.defaults({ validator: sepsSurround });\n\n  rebulk.regex('tt\\\\d{7,8}', {\n    name: 'imdb_id',\n    formatter: (value: string) => value.toLowerCase(),\n  } as any);\n\n  // TMDb / TVDb ids in Plex/Jellyfin-style naming: {tmdb-12345}, [tvdbid-12345],\n  // tmdb=12345, etc. Capture the numeric id.\n  rebulk.regex('tmdb(?:id)?[-=]?(?<tmdb_id>\\\\d{1,9})', {\n    name: 'tmdb_id', private_parent: true, children: true,\n    formatter: (value: string) => parseInt(value, 10),\n  } as any);\n  rebulk.regex('tvdb(?:id)?[-=]?(?<tvdb_id>\\\\d{1,9})', {\n    name: 'tvdb_id', private_parent: true, children: true,\n    formatter: (value: string) => parseInt(value, 10),\n  } as any);\n\n  return rebulk;\n}\n","/**\n * volume property — detects \"vol. N\" / \"volume N\" (common for manga/anime/music\n * box sets). guessit-js enhancement (upstream feature request\n * guessit-io/guessit#301); not present in Python guessit.\n */\nimport { Rebulk } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport { sepsSurround } from '../common/validators.js';\n\nexport function volume(_config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk({ disabled: (context: Record<string, unknown>) => isDisabled(context, 'volume') });\n  rebulk.regexDefaults({ flags: 'i' });\n\n  // Match the whole \"vol…N\" token (so it's excluded from the title) and extract\n  // the number. Either the short marker glued to digits (\"vol127\") or any marker\n  // followed by a separator (\"vol.3\", \"vol 3\", \"volume 12\"). \"volume1\" (full word\n  // glued, as in the NAS path \"/volume1/\") is intentionally NOT matched.\n  // Fansub variants: \"Vol. 1v2\" (version), \"Vol.1&2\" (pair) — consume the whole\n  // token so nothing leaks into the weak-episode chains or the title.\n  rebulk.regex('vol(?:\\\\d{1,3}|(?:ume)?[-. ]{1,2}\\\\d{1,3})(?:v\\\\d)?(?:[&+]\\\\d{1,3})?', {\n    name: 'volume',\n    validator: sepsSurround,\n    formatter: (value: string) => parseInt(String(value).replace(/^vol(?:ume)?[-. ]*/i, '').replace(/[v&+].*$/i, ''), 10),\n    conflictSolver: (match: any, other: any) =>\n      (other.name === 'episode' || other.name === 'season') ? other : '__default__',\n  } as any);\n\n  return rebulk;\n}\n","import { Rebulk } from 'rebulk-js';\nimport { Rule } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport { POST_PROCESS } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\nimport type { Matches } from 'rebulk-js';\nimport type { Context } from 'rebulk-js';\n\n// Simple mimetype mapping\nconst MIMETYPE_MAP: Record<string, string> = {\n  'mkv': 'video/x-matroska',\n  'mp4': 'video/mp4',\n  'avi': 'video/x-msvideo',\n  'mov': 'video/quicktime',\n  'flv': 'video/x-flv',\n  'wmv': 'video/x-ms-wmv',\n  'webm': 'video/webm',\n  'mp3': 'audio/mpeg',\n  'flac': 'audio/flac',\n  'aac': 'audio/aac',\n  'ogg': 'audio/ogg',\n  'wma': 'audio/x-ms-wma',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'png': 'image/png',\n  'gif': 'image/gif',\n  'svg': 'image/svg+xml',\n  'zip': 'application/zip',\n  'rar': 'application/x-rar-compressed',\n  'pdf': 'application/pdf',\n  // .srt subtitles are plain text (matches Python's text/plain).\n  'srt': 'text/plain',\n  // MPEG transport stream (Blu-ray/DVD/broadcast). video/mp2t is the correct\n  // IANA type — Python's mimetypes returns a bogus \"text/vnd.trolltech.linguist\"\n  // for .ts, so here we intentionally diverge to the *correct* value.\n  'ts': 'video/mp2t',\n  // Disc image and torrent — both correct and match Python.\n  'iso': 'application/x-iso9660-image',\n  'torrent': 'application/x-bittorrent',\n};\n\nexport function mimetype(_config: Record<string, unknown>) {\n  const rebulk = new Rebulk({ disabled: (context) => isDisabled(context, 'mimetype') });\n  rebulk.rules(Mimetype);\n  return rebulk;\n}\n\nclass Mimetype extends Rule {\n  static override priority = POST_PROCESS;\n  // No dependency, so this sorts by registration order and lands ahead of\n  // TypeProcessor — Python emits mimetype before type, and the rule only reads\n  // the extension off the input string, never other matches.\n  static override dependency = undefined;\n  static override properties = { mimetype: [null] };\n\n  when(matches: Matches, _context: Context): string | null {\n    const input = matches.inputString ?? '';\n    const ext = input.split('.').pop()?.toLowerCase() || '';\n    return MIMETYPE_MAP[ext] || null;\n  }\n\n  then(matches: Matches, whenResponse: unknown, _context: Context): void {\n    if (whenResponse && typeof whenResponse === 'string') {\n      const len = matches.inputString?.length ?? 0;\n      const match = new Match(len, len, {\n        name: 'mimetype',\n        value: whenResponse,\n        inputString: matches.inputString,\n      });\n      matches.append(match);\n    }\n  }\n}\n","/**\n * Type property — port of guessit/rules/properties/type.py\n */\nimport { Rebulk } from 'rebulk-js';\nimport { Rule, AppendMatch } from 'rebulk-js';\nimport { POST_PROCESS } from 'rebulk-js';\nimport { Match } from 'rebulk-js';\nimport type { Matches } from 'rebulk-js';\nimport type { Context } from 'rebulk-js';\nimport { isDisabled } from '../common/pattern.js';\n\n/**\n * Append a type match to the matches collection.\n */\nfunction addType(matches: Matches, value: string): void {\n  matches.append(\n    new Match(matches.inputString?.length ?? 0, matches.inputString?.length ?? 0, {\n      name: 'type',\n      value,\n    }),\n  );\n}\n\n/**\n * TypeProcessor — determines file type as 'episode' or 'movie'.\n */\nclass TypeProcessor extends Rule {\n  static override priority = POST_PROCESS;\n  static override dependency = undefined;\n  static override properties = { type: ['episode', 'movie'] };\n\n  override priority = POST_PROCESS;\n  override consequence = AppendMatch;\n\n  override when(matches: Matches, context: Context): { type: string; removeWeak?: boolean } | string | null {\n    // If context provides an explicit type, use it\n    const optionType = context?.['type'] as string | undefined;\n    if (optionType) return optionType;\n\n    // Check for episode indicators\n    const episode = matches.named('episode') as Match[] | Match | undefined;\n    const season = matches.named('season') as Match[] | Match | undefined;\n    const absoluteEpisode = matches.named('absolute_episode') as Match[] | Match | undefined;\n    const episodeDetails = matches.named('episode_details') as Match[] | Match | undefined;\n    const year = matches.named('year') as Match[] | Match | undefined;\n\n    const episodeArr = Array.isArray(episode) ? episode : episode ? [episode as Match] : [];\n    const seasonArr = Array.isArray(season) ? season : season ? [season as Match] : [];\n    const hasYear = !!(year && (Array.isArray(year) ? (year as Match[]).length > 0 : true));\n\n    const hasAbsoluteEpisode = !!(absoluteEpisode &&\n      (Array.isArray(absoluteEpisode) ? absoluteEpisode.length > 0 : true));\n    const hasEpisodeDetails = !!(episodeDetails &&\n      (Array.isArray(episodeDetails) ? episodeDetails.length > 0 : true));\n\n    if (\n      episodeArr.length > 0 ||\n      seasonArr.length > 0 ||\n      hasEpisodeDetails ||\n      hasAbsoluteEpisode\n    ) {\n      // If ALL episode matches are weak (no explicit marker) AND a year is present AND\n      // no season/absoluteEpisode/episodeDetails exist, the number is likely a movie title\n      // component (e.g. \"12 Angry Men (1957)\", \"21 (2008)\") rather than an episode number.\n      const allEpisodesWeak =\n        episodeArr.length > 0 &&\n        episodeArr.every((m) => m.tags.includes('weak-episode') || m.tags.includes('weak-duplicate'));\n      // Seasons from weak_duplicate are also \"weak\" only if they appear BEFORE the year.\n      // A season from weak_duplicate that appears AFTER a year is a real episode indicator\n      // (e.g. \"Flash.2014.208\" — season=2, ep=8 after year=2014 is real).\n      // But \"123.Angry.Men.1957\" — season=1 from \"123\" appears BEFORE year=1957 → weak.\n      const yearArr2 = Array.isArray(year) ? (year as Match[]) : year ? [year as Match] : [];\n      const firstYearStart = yearArr2.length > 0 ? yearArr2[0].start : Infinity;\n      const allSeasonsWeak =\n        seasonArr.every((m) =>\n          (m.tags.includes('weak-duplicate') || m.tags.includes('weak-episode')) &&\n          m.start < firstYearStart\n        );\n      const noStrongEpisodeIndicators =\n        (seasonArr.length === 0 || allSeasonsWeak) &&\n        !hasAbsoluteEpisode &&\n        !hasEpisodeDetails;\n\n      // Check if weak episodes form a range (e.g. \"476-479\" or \"2.-.10\") which is a\n      // strong indicator of real episode numbers even without SxxExx markers.\n      let hasEpisodeRange = false;\n      const weakEpisodes = episodeArr.filter((m) =>\n        m.tags.includes('weak-episode') || m.tags.includes('weak-duplicate'));\n      if (weakEpisodes.length >= 3) {\n        hasEpisodeRange = true;\n      } else if (weakEpisodes.length === 2) {\n        const sorted = [...weakEpisodes].sort((a, b) => a.start - b.start);\n        const between = (matches.inputString ?? '').slice(sorted[0].end, sorted[1].start);\n        const betweenClean = between.replace(/[\\s._]/g, '');\n        if (betweenClean === '-' || betweenClean === '~' || betweenClean.toLowerCase() === 'to') {\n          hasEpisodeRange = true;\n        }\n      }\n\n      const allEpisodesWeakNoRange =\n        episodeArr.length > 0 &&\n        !hasEpisodeRange &&\n        episodeArr.every((m) => m.tags.includes('weak-episode') || m.tags.includes('weak-duplicate'));\n\n      // Also check if weak seasons have embedded digits (e.g. \"BT709\")\n      const allSeasonsWeakExtended =\n        seasonArr.every((m) => {\n          if (!(m.tags.includes('weak-duplicate') || m.tags.includes('weak-episode'))) return false;\n          if (m.start < firstYearStart) return true;\n          const inputStr = matches.inputString ?? '';\n          const initiator = m.initiator;\n          if (initiator) {\n            const iStart = initiator.start ?? m.start;\n            const iEnd = initiator.end ?? m.end;\n            const charBefore = iStart > 0 ? inputStr[iStart - 1] : '';\n            const charAfter = iEnd < inputStr.length ? inputStr[iEnd] : '';\n            if (charBefore && /[a-zA-Z]/.test(charBefore)) return true;\n            if (charAfter && /[a-zA-Z]/.test(charAfter)) return true;\n          }\n          return false;\n        });\n\n      const noStrongIndicatorsExtended =\n        (seasonArr.length === 0 || allSeasonsWeakExtended) &&\n        !hasAbsoluteEpisode &&\n        !hasEpisodeDetails;\n\n      // Exception: anime-style bracket release group (e.g. [HorribleSubs]) with weak episodes\n      // indicates a real episode even when year is present\n      const releaseGroup = matches.named('release_group') as Match[] | Match | undefined;\n      const rgArr = Array.isArray(releaseGroup) ? releaseGroup : releaseGroup ? [releaseGroup] : [];\n      const inputStr2 = matches.inputString ?? '';\n      const hasAnimeStyleRG = rgArr.some((rg) => {\n        const charBefore = rg.start > 0 ? inputStr2[rg.start - 1] : '';\n        return charBefore === '[';\n      });\n\n      // Case 1: all episodes weak + year + no strong indicators → movie\n      // e.g. \"12 Angry Men (1957)\", \"21 (2008)\" — the number is part of the movie title.\n      // But not if there's an anime-style bracket release group.\n      if (allEpisodesWeakNoRange && noStrongIndicatorsExtended && hasYear && !hasAnimeStyleRG) {\n        return { type: 'movie', removeWeak: true };\n      }\n      // Case 2: episodeDetails only (no episode/season/absolute) + year → movie\n      // e.g. \"Special.Correspondents.2016\" (ep_details=\"Special\"), \"Final.Fantasy.XV.2016\" (ep_details=\"Final\")\n      // But only if episodeDetails appears BEFORE the year (it's part of the title, not a post-year episode\n      // marker). If episodeDetails comes AFTER the year (e.g. \"Downton.Abbey.2013.Christmas.Special\"),\n      // it's a genuine special episode indicator → return 'episode'.\n      else if (\n        episodeArr.length === 0 &&\n        seasonArr.length === 0 &&\n        !hasAbsoluteEpisode &&\n        hasEpisodeDetails &&\n        hasYear\n      ) {\n        // Get positions to determine if episodeDetails comes before the year\n        const epDetailsArr = Array.isArray(episodeDetails)\n          ? (episodeDetails as Match[])\n          : episodeDetails\n            ? [episodeDetails as Match]\n            : [];\n        const yearArr = Array.isArray(year) ? (year as Match[]) : year ? [year as Match] : [];\n        const yearStart = yearArr.length > 0 ? yearArr[0].start : Infinity;\n        // If any episodeDetails match starts AFTER the year → real episode marker\n        const epDetailsAfterYear = epDetailsArr.some((m) => m.start > yearStart);\n        if (epDetailsAfterYear) {\n          return 'episode';\n        }\n        // episodeDetails precedes the year → likely a title word → fall through to movie\n      } else {\n        return 'episode';\n      }\n    }\n\n    // \"COMPLETE SERIES\", \"COMPLETE MINISERIES\": the season word next to the marker is\n    // consumed into it, so it reaches no property of its own — but a film is never a\n    // *series*. This holds even against a year, unlike a bare `Complete`. (upstream 4.x)\n    const completeSeries = matches.named('other', (m: Match) =>\n      m.value === 'Complete' &&\n      !!(m.children?.named?.('completeWordsBefore')?.length || m.children?.named?.('completeWordsAfter')?.length),\n    ) as Match[] | Match | undefined;\n    if (completeSeries && (Array.isArray(completeSeries) ? completeSeries.length > 0 : true)) {\n      return 'episode';\n    }\n\n    // Check for film indicator\n    const film = matches.named('film') as Match[] | Match | undefined;\n    if (film && (Array.isArray(film) ? film.length > 0 : true)) {\n      return 'movie';\n    }\n\n    // Check for date/year patterns\n    const date = matches.named('date') as Match[] | Match | undefined;\n\n    if (date && (Array.isArray(date) ? date.length > 0 : true)) {\n      if (!year || (Array.isArray(year) ? year.length === 0 : false)) {\n        return 'episode';\n      }\n    }\n\n    // Check for bonus indicator\n    const bonus = matches.named('bonus') as Match[] | Match | undefined;\n    if (bonus && (Array.isArray(bonus) ? bonus.length > 0 : true)) {\n      if (!year || (Array.isArray(year) ? year.length === 0 : false)) {\n        return 'episode';\n      }\n    }\n\n    // Check for CRC32 + anime release group\n    const crc32 = matches.named('crc32') as Match[] | Match | undefined;\n    const animeReleaseGroup = matches.named(\n      'release_group',\n      (m) => m.tags.includes('anime'),\n    ) as Match[] | Match | undefined;\n\n    if (\n      crc32 &&\n      (Array.isArray(crc32) ? crc32.length > 0 : true) &&\n      animeReleaseGroup &&\n      (Array.isArray(animeReleaseGroup) ? animeReleaseGroup.length > 0 : true)\n    ) {\n      return 'episode';\n    }\n\n\n    // A complete run of a series spans several years and carries none of its own,\n    // whereas a film on a complete disc carries its release year. (upstream #953)\n    const complete = matches.named('other', (m: Match) => m.value === 'Complete') as Match[] | Match | undefined;\n    if (\n      complete && (Array.isArray(complete) ? complete.length > 0 : true) &&\n      (!year || (Array.isArray(year) ? (year as Match[]).length === 0 : false))\n    ) {\n      return 'episode';\n    }\n\n    // Default to movie\n    return 'movie';\n  }\n\n  override then(matches: Matches, whenResponse: unknown, _context: Context): void {\n    if (!whenResponse) return;\n\n    let typeValue: string;\n    let removeWeak = false;\n\n    if (typeof whenResponse === 'string') {\n      typeValue = whenResponse;\n    } else if (typeof whenResponse === 'object' && whenResponse !== null && 'type' in whenResponse) {\n      const resp = whenResponse as { type: string; removeWeak?: boolean };\n      typeValue = resp.type;\n      removeWeak = !!resp.removeWeak;\n    } else {\n      return;\n    }\n\n    if (removeWeak) {\n      // Remove weak episode/season matches so they don't consume text that should\n      // belong to the title or release_group.\n      const toRemove: Match[] = [];\n      for (const name of ['episode', 'season']) {\n        const arr = matches.named(name) as Match[] | Match | undefined;\n        const items = Array.isArray(arr) ? arr : arr ? [arr] : [];\n        for (const m of items) {\n          if (m.tags.includes('weak-episode') || m.tags.includes('weak-duplicate')) {\n            toRemove.push(m);\n          }\n        }\n      }\n      for (const m of toRemove) {\n        matches.remove(m);\n      }\n    }\n\n    addType(matches, typeValue);\n  }\n}\n\n/**\n * Create a rebulk pattern for type detection.\n */\nexport function type_(config: Record<string, unknown>): Rebulk {\n  const rebulk = new Rebulk({\n    disabled: (context: Context) => isDisabled(context, 'type'),\n  });\n  rebulk.rules(TypeProcessor);\n  return rebulk;\n}\n","/**\n * Post/pre processors — port of guessit/rules/processors.py\n */\nimport { Rebulk } from 'rebulk-js';\nimport { Rule, CustomRule, AppendMatch, RemoveMatch, AppendTags } from 'rebulk-js';\nimport type { Match, Matches } from 'rebulk-js';\nimport type { Context } from 'rebulk-js';\nimport { PRE_PROCESS, POST_PROCESS } from 'rebulk-js';\nimport { sepsNoGroups } from './common/index.js';\nimport { cleanup } from './common/formatters.js';\nimport { markerSorted } from './common/comparators.js';\nimport { validYear } from './common/date.js';\nimport { iterWords } from './common/words.js';\nimport { Language } from '../language/index.js';\n\nconst LANG_KEYS = new Set(['language', 'subtitle_language']);\n\n/** Check whether a match value represents the \"undetermined\" language placeholder. */\nfunction isUndeterminedLang(match: Match): boolean {\n  if (!LANG_KEYS.has(match.name ?? '')) return false;\n  const v = match.value;\n  if (v === 'und') return true;\n  if (v && typeof v === 'object' && 'alpha3' in (v as Record<string, unknown>)) {\n    return (v as { alpha3: string }).alpha3 === 'und';\n  }\n  return false;\n}\n\n/** Enlarge matches that start/end a group to include bracket characters. */\nexport class EnlargeGroupMatches extends CustomRule {\n  static override priority = PRE_PROCESS;\n\n  when(matches: Matches, _context: Context): [Match[], Match[]] | false {\n    const starting: Match[] = [];\n    const ending: Match[] = [];\n\n    for (const group of matches.markers.named('group')) {\n      for (const match of matches.starting(group.start + 1)) {\n        starting.push(match);\n      }\n      for (const match of matches.ending(group.end - 1)) {\n        ending.push(match);\n      }\n    }\n\n    if (starting.length > 0 || ending.length > 0) return [starting, ending];\n    return false;\n  }\n\n  then(matches: Matches, whenResponse: unknown, _context: Context): void {\n    const [starting, ending] = whenResponse as [Match[], Match[]];\n    for (const match of starting) {\n      matches.remove(match);\n      (match as unknown as { start: number }).start -= 1;\n      (match as unknown as { rawStart: number }).rawStart += 1;\n      matches.append(match);\n    }\n    for (const match of ending) {\n      matches.remove(match);\n      (match as unknown as { end: number }).end += 1;\n      (match as unknown as { rawEnd: number }).rawEnd -= 1;\n      matches.append(match);\n    }\n  }\n}\n\nfunction preferredString(value1: string, value2: string): string {\n  if (value1 === value2) return value1;\n  if (isTitleCase(value1) && !isTitleCase(value2)) return value1;\n  if (!value1.toUpperCase().startsWith(value1) && value2 === value2.toUpperCase()) return value1;\n  if (!value1.toUpperCase().startsWith(value1) && value1[0] === value1[0].toUpperCase() && value2[0] !== value2[0].toUpperCase()) return value1;\n  if (countTitleWords(value1) > countTitleWords(value2)) return value1;\n  return value2;\n}\n\nfunction isTitleCase(s: string): boolean {\n  return s.split(' ').every(w => w.length === 0 || w[0] === w[0].toUpperCase());\n}\n\nfunction countTitleWords(value: string): number {\n  let ret = 0;\n  for (const word of iterWords(value)) {\n    if (word.value[0] === word.value[0].toUpperCase() && word.value[0] !== word.value[0].toLowerCase()) ret++;\n  }\n  return ret;\n}\n\n/** Creates equivalent matches for holes that have the same value as an existing match. */\nexport class EquivalentHoles extends Rule {\n  static priority = POST_PROCESS;\n  static consequence = AppendMatch;\n\n  when(matches: Matches, _context: Record<string, unknown>): Match[] {\n    const newMatches: Match[] = [];\n\n    for (const filepath of markerSorted(matches.markers.named('path'), matches)) {\n      const holes = matches.holes(filepath.start, filepath.end, { formatter: cleanup }) as Match[];\n      for (const name of matches.names) {\n        const holesLeft = [...holes];\n        for (const hole of [...holesLeft]) {\n          for (const currentMatch of matches.named(name)) {\n            if (typeof currentMatch.value === 'string' &&\n                hole.value && typeof hole.value === 'string' &&\n                hole.value.toLowerCase() === (currentMatch.value as string).toLowerCase()) {\n              if (currentMatch.tags.includes('equivalent-ignore')) continue;\n              const newValue = preferredString(hole.value as string, currentMatch.value as string);\n              if (hole.value !== newValue) (hole as unknown as { value: unknown }).value = newValue;\n              if (currentMatch.value !== newValue) (currentMatch as unknown as { value: unknown }).value = newValue;\n              (hole as unknown as { name: string; tags: string[] }).name = name;\n              (hole as unknown as { tags: string[] }).tags = ['equivalent'];\n              newMatches.push(hole);\n              const idx = holesLeft.indexOf(hole);\n              if (idx > -1) holesLeft.splice(idx, 1);\n            }\n          }\n        }\n      }\n    }\n    return newMatches;\n  }\n}\n\n/**\n * If multiple matches with same name and different values exist, keep the one\n * in the most valuable filepart and mark others for removal.\n */\nexport class RemoveAmbiguous extends Rule {\n  static priority = POST_PROCESS;\n  static consequence = RemoveMatch;\n\n  protected sortFunction: (markers: Match[], matches: Matches) => Match[];\n  protected predicate: ((m: Match) => boolean) | null;\n\n  constructor(\n    sortFn?: (markers: Match[], matches: Matches) => Match[],\n    predicate?: (m: Match) => boolean,\n  ) {\n    super();\n    this.sortFunction = sortFn ?? markerSorted;\n    this.predicate = predicate ?? null;\n  }\n\n  when(matches: Matches, _context: Record<string, unknown>): Match[] {\n    const fileparts = this.sortFunction(matches.markers.named('path'), matches);\n    const previousFilepartsNames = new Set<string>();\n    const values = new Map<string, unknown[]>();\n    const toRemove: Match[] = [];\n\n    for (const filepart of fileparts) {\n      const filepartMatches = (this.predicate\n        ? matches.range(filepart.start, filepart.end, this.predicate)\n        : matches.range(filepart.start, filepart.end)) as Match[];\n\n      const filepartNames = new Set<string>();\n      for (const match of filepartMatches) {\n        const matchName = match.name ?? '';\n        filepartNames.add(matchName);\n        if (previousFilepartsNames.has(matchName)) {\n          const vals = values.get(matchName) ?? [];\n          if (!vals.includes(match.value)) {\n            // For episode_title, prefer the match from the filepart that\n            // contains the SxxExx episode match (typically the filename).\n            if (matchName === 'episode_title') {\n              const hasSxxExx = (matches.range(filepart.start, filepart.end,\n                (m: Match) => !m.private && (m.tags?.includes('SxxExx') ?? false), 0) as Match | undefined);\n              if (hasSxxExx) {\n                // This filepart has the episode match — prefer its episode_title.\n                // Remove the previously registered episode_titles and keep this one.\n                const oldEpTitles = (matches.named(matchName) as Match[]).filter(\n                  (m: Match) => m.start < filepart.start || m.end > filepart.end\n                );\n                toRemove.push(...oldEpTitles);\n                vals.length = 0;\n                vals.push(match.value);\n                values.set(matchName, vals);\n                continue;\n              }\n            }\n            // When a real language value appears in a secondary filepart,\n            // and the primary filepart only registered \"und\" (undetermined),\n            // keep the real value and remove the \"und\" matches instead.\n            if (!isUndeterminedLang(match) && LANG_KEYS.has(matchName)) {\n              const allUnd = vals.every(v =>\n                v === 'und' || (v && typeof v === 'object' && 'alpha3' in (v as Record<string, unknown>) && (v as { alpha3: string }).alpha3 === 'und')\n              );\n              if (allUnd) {\n                // Replace und values: remove existing und matches for this name and keep the new one\n                const undMatches = toRemove.length > 0 ? [] :\n                  (matches.named(matchName) as Match[]).filter((m: Match) => isUndeterminedLang(m));\n                toRemove.push(...undMatches);\n                vals.length = 0;\n                vals.push(match.value);\n                values.set(matchName, vals);\n                continue;\n              }\n            }\n            toRemove.push(match);\n          }\n        } else {\n          const vals = values.get(matchName) ?? [];\n          if (!vals.includes(match.value)) {\n            vals.push(match.value);\n            values.set(matchName, vals);\n          }\n        }\n      }\n      for (const n of filepartNames) previousFilepartsNames.add(n);\n    }\n    return toRemove;\n  }\n}\n\nconst sxxExxWeightPredicate = (m: Match) =>\n  (m.name === 'season' || m.name === 'episode') && m.tags.includes('SxxExx');\n\nexport class RemoveLessSpecificSeasonEpisode extends RemoveAmbiguous {\n  constructor(name: string) {\n    super(\n      // Sort fileparts most-valuable-first: a SxxExx-tagged season/episode outweighs a\n      // weaker one, so the filename's S44E03 beats a season-only or weak-number parent\n      // directory (upstream #797/#772).\n      (markers, matches) => markerSorted(markers, matches, sxxExxWeightPredicate),\n      (m: Match) => m.name === name,\n    );\n  }\n\n  override when(matches: Matches, context: Record<string, unknown>): Match[] {\n    // Only decide when the SxxExx weights strictly differ. Equally-specific fileparts\n    // (\"S06E01.E10\" pack dir vs \"S06E09\" file, or a real dir vs a sample file) are\n    // left to the generic RemoveAmbiguous, whose full-property weight and rightmost\n    // preference pick the correct side for both directions.\n    const markers = matches.markers.named('path') as Match[];\n    const markerArr = Array.isArray(markers) ? markers : markers ? [markers] : [];\n    if (markerArr.length > 1) {\n      const weights = markerArr.map((marker) => {\n        const inRange = matches.range(marker.start, marker.end, sxxExxWeightPredicate) as Match[];\n        return new Set((Array.isArray(inRange) ? inRange : []).map((m) => m.name)).size;\n      });\n      const top = Math.max(...weights);\n      if (weights.filter((w) => w === top).length > 1) return [];\n    }\n    return super.when(matches, context);\n  }\n}\n\n// rebulk-js (unlike Python rebulk) rejects two rule instances of the same class in one\n// priority group, so the season/episode passes need distinct classes.\nexport class RemoveLessSpecificSeason extends RemoveLessSpecificSeasonEpisode {\n  constructor() { super('season'); }\n}\nexport class RemoveLessSpecificEpisode extends RemoveLessSpecificSeasonEpisode {\n  constructor() { super('episode'); }\n}\n\n/** If a season is a valid year and no year found, create a year match. */\nexport class SeasonYear extends Rule {\n  static priority = POST_PROCESS;\n  static consequence = AppendMatch;\n\n  when(matches: Matches, _context: Record<string, unknown>): Match[] {\n    const ret: Match[] = [];\n    if (matches.named('year').length === 0) {\n      for (const season of matches.named('season')) {\n        if (typeof season.value === 'number' && validYear(season.value)) {\n          const year = season.clone();\n          (year as unknown as { name: string }).name = 'year';\n          ret.push(year);\n        }\n      }\n    }\n    return ret;\n  }\n}\n\n/** If year found, no season found, and episode found, create a season match. */\nexport class YearSeason extends Rule {\n  static priority = POST_PROCESS;\n  static consequence = AppendMatch;\n\n  when(matches: Matches, _context: Record<string, unknown>): Match[] {\n    const ret: Match[] = [];\n    // Only trigger when there are strong (non-weak) episodes. Weak-episode matches\n    // (bare 2-digit numbers) often coincide with title numbers like \"21\" or \"12\".\n    const strongEpisodes = matches.named('episode').filter(\n      (m: Match) => !m.tags.includes('weak-episode') && !m.tags.includes('weak-duplicate'),\n    );\n    if (matches.named('season').length === 0 && strongEpisodes.length > 0) {\n      for (const year of matches.named('year')) {\n        const season = year.clone();\n        (season as unknown as { name: string }).name = 'season';\n        ret.push(season);\n      }\n    }\n    return ret;\n  }\n}\n\n/** Empty rule for ordering post-processing. */\nexport class Processors extends Rule {\n  static priority = POST_PROCESS;\n\n  when(_matches: Matches, _context: Record<string, unknown>): false {\n    return false;\n  }\n}\n\n/** Strip separator characters from match boundaries. */\nexport class StripSeparators extends CustomRule {\n  static override priority = POST_PROCESS;\n\n  when(matches: Matches, _context: Context): Matches {\n    return matches;\n  }\n\n  then(matches: Matches, _whenResponse: unknown, _context: Context): void {\n    for (const match of matches) {\n      const span = match.span;\n      for (let i = 0; i < span[1] - span[0]; i++) {\n        const raw = match.raw;\n        if (raw && sepsNoGroups.includes(raw[0]) && (raw.length < 3 || !sepsNoGroups.includes(raw[2]))) {\n          match.rawStart = match.rawStart + 1;\n        } else break;\n      }\n      for (let i = span[1] - span[0] - 1; i >= 0; i--) {\n        const raw = match.raw;\n        if (raw && sepsNoGroups.includes(raw[raw.length - 1]) && (raw.length < 3 || !sepsNoGroups.includes(raw[raw.length - 3]))) {\n          match.rawEnd = match.rawEnd - 1;\n        } else break;\n      }\n    }\n  }\n}\n\n/** Remove matches with invalid values (NaN, null, undefined, empty) after processing. */\nclass RemoveInvalidMatches extends CustomRule {\n  static override priority = POST_PROCESS;\n\n  when(matches: Matches): Match[] {\n    const toRemove: Match[] = [];\n    for (const match of matches) {\n      if (match.value === null || match.value === undefined ||\n          (typeof match.value === 'number' && isNaN(match.value)) ||\n          match.value === '') {\n        toRemove.push(match);\n      }\n    }\n    return toRemove;\n  }\n\n  then(matches: Matches, whenResponse: unknown): void {\n    const toRemove = whenResponse as Match[];\n    for (const m of toRemove) {\n      matches.remove(m);\n    }\n  }\n}\n\nexport function processors(_config: Record<string, unknown>): Rebulk {\n  return new Rebulk().rules(\n    EnlargeGroupMatches,\n    EquivalentHoles,\n    RemoveLessSpecificSeason,\n    RemoveLessSpecificEpisode,\n    RemoveAmbiguous,\n    SeasonYear,\n    YearSeason,\n    Processors,\n    StripSeparators,\n    RemoveInvalidMatches,\n  );\n}\n","/**\n * Main rebulk builder — port of guessit/rules/__init__.py\n */\nimport { Rebulk } from 'rebulk-js';\nimport { path } from './markers/path.js';\nimport { groups } from './markers/groups.js';\nimport { episodes } from './properties/episodes.js';\nimport { container } from './properties/container.js';\nimport { source } from './properties/source.js';\nimport { videoCodec } from './properties/video_codec.js';\nimport { audioCodec } from './properties/audio_codec.js';\nimport { screenSize } from './properties/screen_size.js';\nimport { website } from './properties/website.js';\nimport { date } from './properties/date.js';\nimport { title } from './properties/title.js';\nimport { episodeTitle } from './properties/episode_title.js';\nimport { language } from './properties/language.js';\nimport { country } from './properties/country.js';\nimport { releaseGroup } from './properties/release_group.js';\nimport { streamingService } from './properties/streaming_service.js';\nimport { other, completeWords } from './properties/other.js';\nimport { size } from './properties/size.js';\nimport { bitRate } from './properties/bit_rate.js';\nimport { edition } from './properties/edition.js';\nimport { cd } from './properties/cd.js';\nimport { bonus } from './properties/bonus.js';\nimport { film } from './properties/film.js';\nimport { part } from './properties/part.js';\nimport { crc } from './properties/crc.js';\nimport { imdb } from './properties/imdb.js';\nimport { volume } from './properties/volume.js';\nimport { mimetype } from './properties/mimetype.js';\nimport { type_ } from './properties/type.js';\nimport { processors } from './processors.js';\n\nexport interface AdvancedConfig {\n  common_words?: string[];\n  groups?: { starting: string; ending: string };\n  audio_codec?: Record<string, unknown>;\n  screen_size?: {\n    frame_rates: string[];\n    interlaced: string[];\n    progressive: string[];\n    min_ar: number;\n    max_ar: number;\n  };\n  source?: Record<string, unknown>;\n  episodes?: Record<string, unknown>;\n  language?: Record<string, unknown>;\n  country?: Record<string, unknown>;\n  [key: string]: unknown;\n}\n\nexport function rebulkBuilder(config: AdvancedConfig): Rebulk {\n  function cfg(name: string): Record<string, unknown> {\n    return (config[name] as Record<string, unknown>) ?? {};\n  }\n\n  const rebulk = new Rebulk();\n  const commonWords = new Set<string>((config['common_words'] as string[]) ?? []);\n\n  rebulk.rebulk(path(cfg('path')));\n  rebulk.rebulk(groups((cfg('groups') as { starting: string; ending: string }) ?? { starting: '([{', ending: ')]}' }));\n\n  rebulk.rebulk(episodes(cfg('episodes') as unknown as any));\n  rebulk.rebulk(container(cfg('container')));\n  rebulk.rebulk(source(cfg('source')));\n  rebulk.rebulk(videoCodec(cfg('video_codec')));\n  rebulk.rebulk(audioCodec(cfg('audio_codec')));\n  rebulk.rebulk(screenSize(cfg('screen_size') as unknown as any));\n  rebulk.rebulk(website(cfg('website')));\n  rebulk.rebulk(date(cfg('date')));\n  rebulk.rebulk(title(cfg('title')));\n  rebulk.rebulk(episodeTitle(cfg('episode_title')));\n  rebulk.rebulk(language(cfg('language') as unknown as any, commonWords));\n  rebulk.rebulk(country(cfg('country') as unknown as any, commonWords));\n  rebulk.rebulk(releaseGroup(cfg('release_group')));\n  rebulk.rebulk(streamingService(cfg('streaming_service')));\n  const otherRebulk = other(cfg('other'));\n  const episodesConfig = cfg('episodes') as any;\n  // Complete words use regex patterns for season words (from options.json _complete_words config)\n  completeWords(otherRebulk, {\n    completeMarkerWords: ['Complete', 'Int[ée]grale'],\n    seasonWords: ['seasons?', 'mini-?series?', 'series?'],\n    completeArticleWords: ['The'],\n    completePrefixWords: [\"L['’]?\", 'Coffret'],\n    seasonNumberSeparators: ['&', 'and'],\n  });\n  rebulk.rebulk(otherRebulk);\n  rebulk.rebulk(size(cfg('size')));\n  rebulk.rebulk(bitRate(cfg('bit_rate')));\n  rebulk.rebulk(edition(cfg('edition')));\n  rebulk.rebulk(cd(cfg('cd')));\n  rebulk.rebulk(bonus(cfg('bonus')));\n  rebulk.rebulk(film(cfg('film')));\n  rebulk.rebulk(part(cfg('part')));\n  rebulk.rebulk(crc(cfg('crc')));\n  rebulk.rebulk(imdb(cfg('imdb')));\n  rebulk.rebulk(volume(cfg('volume')));\n  rebulk.rebulk(processors(cfg('processors')));\n  rebulk.rebulk(mimetype(cfg('mimetype')));\n  rebulk.rebulk(type_(cfg('type')));\n\n  // Customize properties: rename 'count' to both 'season_count' and 'episode_count'\n  (rebulk as unknown as { customizeProperties: (props: Record<string, unknown>) => Record<string, unknown> }).customizeProperties =\n    function customizeProperties(properties: Record<string, unknown>) {\n      const count = properties['count'];\n      delete properties['count'];\n      properties['season_count'] = count;\n      properties['episode_count'] = count;\n      return properties;\n    };\n\n  return rebulk;\n}\n","/**\n * Options handling — port of guessit/options.py\n */\nimport defaultOptions from './config/options.json' assert { type: 'json' };\n\nexport interface GuessItOptions {\n  type?: 'movie' | 'episode';\n  nameOnly?: boolean;\n  dateYearFirst?: boolean;\n  dateDayFirst?: boolean;\n  allowedLanguages?: string[];\n  allowedCountries?: string[];\n  episodePreferNumber?: boolean;\n  expectedTitle?: string[];\n  expectedGroup?: string[];\n  includes?: string[];\n  excludes?: string[];\n  advanced?: boolean;\n  singleValue?: boolean;\n  enforceList?: boolean;\n  outputInputString?: boolean;\n  noUserConfig?: boolean;\n  noDefaultConfig?: boolean;\n  advancedConfig?: Record<string, unknown>;\n  [key: string]: unknown;\n}\n\nexport type RawOptions = string | string[] | GuessItOptions | null | undefined;\n\n/**\n * Parse raw options into a normalized options dict.\n * In the JS version we don't support CLI args, only dict/null.\n */\nexport function parseOptions(options?: RawOptions, _api = false): GuessItOptions {\n  if (!options) return {};\n  if (typeof options === 'object' && !Array.isArray(options)) return options as GuessItOptions;\n  // String or array: return empty (CLI not supported in JS)\n  return {};\n}\n\n/**\n * Load and merge configuration from the default options JSON.\n */\nexport function loadConfig(options: GuessItOptions = {}): Record<string, unknown> {\n  const configurations: Record<string, unknown>[] = [];\n\n  if (!options.noDefaultConfig) {\n    configurations.push(defaultOptions as Record<string, unknown>);\n  }\n\n  const config: Record<string, unknown> = configurations.length > 0\n    ? mergeOptions(...configurations)\n    : {};\n\n  // Always ensure advanced_config is present\n  if (!('advanced_config' in config)) {\n    config['advanced_config'] = (defaultOptions as Record<string, unknown>)['advanced_config'];\n  }\n\n  return config;\n}\n\n/**\n * Deep merge multiple options objects into one.\n */\nexport function mergeOptions(...optionsList: Record<string, unknown>[]): Record<string, unknown> {\n  let merged: Record<string, unknown> = {};\n\n  if (optionsList.length === 0) return merged;\n\n  if (optionsList[0]) {\n    merged = deepCopy(optionsList[0]);\n  }\n\n  for (const opts of optionsList.slice(1)) {\n    if (!opts) continue;\n    const pristine = opts['pristine'];\n    if (pristine === true) {\n      merged = {};\n    } else if (Array.isArray(pristine)) {\n      for (const key of pristine) {\n        delete merged[key];\n      }\n    }\n\n    for (const [option, value] of Object.entries(opts)) {\n      mergeOptionValue(option, value, merged);\n    }\n  }\n\n  return merged;\n}\n\nfunction mergeOptionValue(\n  option: string,\n  value: unknown,\n  merged: Record<string, unknown>,\n): void {\n  if (value !== null && value !== undefined && option !== 'pristine') {\n    const existing = merged[option];\n    if (Array.isArray(existing) && Array.isArray(value)) {\n      for (const val of value) {\n        if (!existing.includes(val) && val !== null) {\n          existing.push(val);\n        }\n      }\n    } else if (existing !== null && typeof existing === 'object' && !Array.isArray(existing) &&\n               value !== null && typeof value === 'object' && !Array.isArray(value)) {\n      merged[option] = mergeOptions(existing as Record<string, unknown>, value as Record<string, unknown>);\n    } else if (Array.isArray(value)) {\n      merged[option] = [...value];\n    } else {\n      merged[option] = value;\n    }\n  }\n}\n\nfunction deepCopy<T>(obj: T): T {\n  return JSON.parse(JSON.stringify(obj));\n}\n","// AUTO-GENERATED by scripts/gen-schema.mjs — do not edit by hand.\n// Regenerate: node --import tsx scripts/gen-schema.mjs\n// Source of truth: test/fixtures/corpus-schema-data.json + python-properties.json.\n\n/** A detected language or country, as guessit renders it. */\nexport interface GuessitLanguage {\n  name?: string;\n  alpha3?: string;\n  alpha2?: string;\n  country?: string | null;\n  script?: string | null;\n}\n\n/** Machine-readable description of every property guessit-js can emit. */\nexport interface PropertySchema {\n  /** JSON-ish base type(s) of the value. */\n  type: Array<'string' | 'number' | 'boolean' | 'Language' | 'object'>;\n  /** True if this property can be emitted as an array (multiple values). */\n  array: boolean;\n  /** True if this property can be emitted as a single scalar. */\n  scalar: boolean;\n  /** Closed vocabulary of allowed values, when the property is value-constrained. */\n  enum?: Array<string | number>;\n}\n\nexport const GUESSIT_SCHEMA: Record<string, PropertySchema> = {\n  \"absolute_episode\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"alternative_title\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"another\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": false\n  },\n  \"aspect_ratio\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"audio_bit_rate\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"audio_channels\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true,\n    \"enum\": [\n      \"1.0\",\n      \"1ch\",\n      \"2.0\",\n      \"20\",\n      \"2ch\",\n      \"5.1\",\n      \"5ch\",\n      \"6ch\",\n      \"7.1\",\n      \"7ch\",\n      \"8ch\",\n      \"mono\",\n      \"stereo\"\n    ]\n  },\n  \"audio_codec\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true,\n    \"enum\": [\n      \"AAC\",\n      \"Atmos\",\n      \"DD+\",\n      \"DDP\",\n      \"Dolby\",\n      \"Dolby Atmos\",\n      \"Dolby Digital\",\n      \"Dolby Digital Plus\",\n      \"Dolby TrueHD\",\n      \"DolbyDigital\",\n      \"DTS\",\n      \"DTS-HD\",\n      \"DTS-X\",\n      \"DTS:X\",\n      \"DTSX\",\n      \"Flac\",\n      \"FLAC\",\n      \"LAME\",\n      \"LPCM\",\n      \"MP2\",\n      \"MP3\",\n      \"Opus\",\n      \"PCM\",\n      \"Vorbis\"\n    ]\n  },\n  \"audio_profile\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true,\n    \"enum\": [\n      \"ES\",\n      \"EX\",\n      \"Extended Surround\",\n      \"HE\",\n      \"High Efficiency\",\n      \"High Quality\",\n      \"High Resolution Audio\",\n      \"HQ\",\n      \"HR\",\n      \"HRA\",\n      \"LC\",\n      \"Low Complexity\",\n      \"MA\",\n      \"Master Audio\"\n    ]\n  },\n  \"bonus\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"bonus_title\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"cd\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"cd_count\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"color_depth\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"10-bit\",\n      \"12-bit\",\n      \"8-bit\"\n    ]\n  },\n  \"container\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true,\n    \"enum\": [\n      \"3g2\",\n      \"3gp\",\n      \"3gp2\",\n      \"7z\",\n      \"ace\",\n      \"arj\",\n      \"asf\",\n      \"avi\",\n      \"bmp\",\n      \"bz2\",\n      \"cb7\",\n      \"cbr\",\n      \"cbz\",\n      \"divx\",\n      \"flv\",\n      \"gif\",\n      \"gz\",\n      \"idx\",\n      \"iso\",\n      \"jpeg\",\n      \"jpg\",\n      \"m2ts\",\n      \"m4v\",\n      \"mk2\",\n      \"mk3d\",\n      \"mka\",\n      \"mkv\",\n      \"MKV\",\n      \"mov\",\n      \"mp4\",\n      \"mp4a\",\n      \"mpeg\",\n      \"mpg\",\n      \"nfo\",\n      \"nzb\",\n      \"ogg\",\n      \"ogm\",\n      \"ogv\",\n      \"png\",\n      \"qt\",\n      \"r00\",\n      \"ra\",\n      \"ram\",\n      \"rar\",\n      \"rm\",\n      \"srt\",\n      \"ssa\",\n      \"tar\",\n      \"tbn\",\n      \"tgz\",\n      \"torrent\",\n      \"ts\",\n      \"vob\",\n      \"wav\",\n      \"webm\",\n      \"webp\",\n      \"wma\",\n      \"wmv\",\n      \"zip\"\n    ]\n  },\n  \"country\": {\n    \"type\": [\n      \"Language\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"crc32\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"date\": {\n    \"type\": [\n      \"object\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"disc\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"edition\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true,\n    \"enum\": [\n      \"Alternative Cut\",\n      \"CC\",\n      \"collector\",\n      \"Collector\",\n      \"Criterion\",\n      \"DC\",\n      \"ddc\",\n      \"deluxe\",\n      \"Deluxe\",\n      \"Director's Cut\",\n      \"Director's Definitive Cut\",\n      \"extended\",\n      \"Extended\",\n      \"Fan\",\n      \"Festival\",\n      \"imax\",\n      \"IMAX\",\n      \"limited\",\n      \"Limited\",\n      \"Remastered\",\n      \"Restored\",\n      \"se\",\n      \"Special\",\n      \"theatrical\",\n      \"Theatrical\",\n      \"Ultimate\",\n      \"Uncensored\",\n      \"Uncut\",\n      \"Unrated\"\n    ]\n  },\n  \"episode\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"episode_count\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"episode_details\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"episode_format\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"Minisode\"\n    ]\n  },\n  \"episode_title\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"film\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"film_title\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"frame_rate\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"language\": {\n    \"type\": [\n      \"Language\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"mimetype\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"application/x-bittorrent\",\n      \"application/x-iso9660-image\",\n      \"application/x-rar-compressed\",\n      \"application/zip\",\n      \"image/gif\",\n      \"image/jpeg\",\n      \"image/png\",\n      \"text/plain\",\n      \"video/mp2t\",\n      \"video/mp4\",\n      \"video/webm\",\n      \"video/x-matroska\",\n      \"video/x-msvideo\"\n    ]\n  },\n  \"other\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true,\n    \"enum\": [\n      \"2in1\",\n      \"3D\",\n      \"asrequested\",\n      \"Audio Fixed\",\n      \"Banner\",\n      \"Bonus\",\n      \"BT.2020\",\n      \"Classic\",\n      \"Clear Art\",\n      \"Clear Logo\",\n      \"Colorized\",\n      \"Complet\",\n      \"Complete\",\n      \"CONVERT\",\n      \"Converted\",\n      \"Cover\",\n      \"Dirfix\",\n      \"Disc Art\",\n      \"DOCU\",\n      \"Documentary\",\n      \"DOKU\",\n      \"Dolby Vision\",\n      \"Dual\",\n      \"Dual Audio\",\n      \"East Coast Feed\",\n      \"Extras\",\n      \"Fan Subtitled\",\n      \"Fanart\",\n      \"Fansub\",\n      \"Fast Subtitled\",\n      \"Fastsub\",\n      \"FHD\",\n      \"Fix\",\n      \"Fixed\",\n      \"Full HD\",\n      \"Half Over Under\",\n      \"Half Side By Side\",\n      \"Hardcoded Subtitles\",\n      \"HC\",\n      \"HD\",\n      \"HDLight\",\n      \"HDR10\",\n      \"HFR\",\n      \"High Frame Rate\",\n      \"High Quality\",\n      \"High Resolution\",\n      \"HQ\",\n      \"HR\",\n      \"Hybrid\",\n      \"Internal\",\n      \"Landscape\",\n      \"LD\",\n      \"LDTV\",\n      \"LiNE\",\n      \"Line Audio\",\n      \"Line Dubbed\",\n      \"Logo\",\n      \"Low Definition\",\n      \"MD\",\n      \"mHD\",\n      \"Mic Dubbed\",\n      \"Micro HD\",\n      \"Mux\",\n      \"Nfofix\",\n      \"NTSC\",\n      \"Oad\",\n      \"OAR\",\n      \"Oav\",\n      \"Obfuscated\",\n      \"Ona\",\n      \"Open Matte\",\n      \"Original Animated Video\",\n      \"Original Animation DVD\",\n      \"Original Aspect Ratio\",\n      \"Original Net Animation\",\n      \"Original Video\",\n      \"OV\",\n      \"Ova\",\n      \"Over Under\",\n      \"PAL\",\n      \"postbot\",\n      \"Poster\",\n      \"Preair\",\n      \"Proof\",\n      \"Prooffix\",\n      \"Proper\",\n      \"PS Vita\",\n      \"R5\",\n      \"RC\",\n      \"Read NFO\",\n      \"Real\",\n      \"Reencoded\",\n      \"Region 5\",\n      \"Region C\",\n      \"Remux\",\n      \"Repost\",\n      \"Retail\",\n      \"Rip\",\n      \"Sample\",\n      \"Scrambled\",\n      \"Screener\",\n      \"SDR\",\n      \"SECAM\",\n      \"Side By Side\",\n      \"Standard Dynamic Range\",\n      \"Straight to Video\",\n      \"STV\",\n      \"Sync Fixed\",\n      \"Thumbnail\",\n      \"Trailer\",\n      \"UHD\",\n      \"Ultra HD\",\n      \"Upscaled\",\n      \"Variable Frame Rate\",\n      \"VFR\",\n      \"Virtual Reality\",\n      \"Vita\",\n      \"VO\",\n      \"vost\",\n      \"West Coast Feed\",\n      \"Widescreen\",\n      \"ws\",\n      \"xpost\",\n      \"XXX\"\n    ]\n  },\n  \"part\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"proper_count\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"release_group\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"screen_size\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"1080i\",\n      \"1080p\",\n      \"1440p\",\n      \"1444x866\",\n      \"2160p\",\n      \"360p\",\n      \"368p\",\n      \"480p\",\n      \"4k\",\n      \"540p\",\n      \"576p\",\n      \"720p\",\n      \"720x432\",\n      \"960x544\"\n    ]\n  },\n  \"season\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"season_count\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"size\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"source\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"Analog HDTV\",\n      \"Blu-ray\",\n      \"Camera\",\n      \"Digital Master\",\n      \"Digital TV\",\n      \"DVD\",\n      \"HD Camera\",\n      \"HD Telecine\",\n      \"HD Telesync\",\n      \"HD-DVD\",\n      \"HDTV\",\n      \"Laserdisc\",\n      \"Pay-per-view\",\n      \"Satellite\",\n      \"Telecine\",\n      \"Telesync\",\n      \"TV\",\n      \"Ultra HD Blu-ray\",\n      \"Ultra HDTV\",\n      \"VHS\",\n      \"Video on Demand\",\n      \"Web\",\n      \"Workprint\"\n    ]\n  },\n  \"streaming_service\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"4OD\",\n      \"9Now\",\n      \"9NOW\",\n      \"A&E\",\n      \"ABC\",\n      \"ABC Australia\",\n      \"Adult Swim\",\n      \"AE\",\n      \"AJAZ\",\n      \"Al Jazeera English\",\n      \"ALL4\",\n      \"Amazon\",\n      \"Amazon Prime\",\n      \"AMBC\",\n      \"AMC\",\n      \"America's Test Kitchen\",\n      \"AMZN\",\n      \"AMZN-CBR\",\n      \"Animal Planet\",\n      \"AnimeLab\",\n      \"ANLB\",\n      \"ANPL\",\n      \"AOL\",\n      \"AppleTV\",\n      \"APTV\",\n      \"ARD\",\n      \"AS\",\n      \"ATK\",\n      \"ATV+\",\n      \"ATVP\",\n      \"AUBC\",\n      \"BBC iPlayer\",\n      \"Binge\",\n      \"BKPL\",\n      \"Blackpills\",\n      \"BLU\",\n      \"BluTV\",\n      \"BNGE\",\n      \"BOOM\",\n      \"Boomerang\",\n      \"BRAV\",\n      \"BravoTV\",\n      \"Canal+\",\n      \"Cartoon Network\",\n      \"CBC\",\n      \"CBS\",\n      \"CC\",\n      \"CCGC\",\n      \"Channel 4\",\n      \"CHGD\",\n      \"CHRGD\",\n      \"Cinemax\",\n      \"CMAX\",\n      \"CMT\",\n      \"CN\",\n      \"CNBC\",\n      \"CNLP\",\n      \"Comedians in Cars Getting Coffee\",\n      \"Comedy Central\",\n      \"Country Music Television\",\n      \"CR\",\n      \"Crackle\",\n      \"CRAV\",\n      \"Crave\",\n      \"CRKL\",\n      \"Crunchy Roll\",\n      \"CSpan\",\n      \"CSPN\",\n      \"CTV\",\n      \"CUR\",\n      \"CuriosityStream\",\n      \"CW\",\n      \"CWS\",\n      \"CWSeed\",\n      \"Daisuki\",\n      \"DC Universe\",\n      \"DCU\",\n      \"DDY\",\n      \"Deadhouse Films\",\n      \"DF\",\n      \"DHF\",\n      \"Digiturk Diledigin Yerde\",\n      \"DISC\",\n      \"Discovery\",\n      \"Discovery Plus\",\n      \"Disney\",\n      \"Disney+\",\n      \"DIY\",\n      \"DIY Network\",\n      \"Doc Club\",\n      \"DOCC\",\n      \"DPlay\",\n      \"DPLY\",\n      \"DramaFever\",\n      \"DSCP\",\n      \"DSKI\",\n      \"DSNP\",\n      \"DSNY\",\n      \"E!\",\n      \"El Trece\",\n      \"ePix\",\n      \"EPIX\",\n      \"ESPN\",\n      \"ESQ\",\n      \"Esquire\",\n      \"ETTV\",\n      \"ETV\",\n      \"Facebook Watch\",\n      \"FAM\",\n      \"Family\",\n      \"Family Jr\",\n      \"Fandor\",\n      \"FANDOR\",\n      \"FBWatch\",\n      \"FJR\",\n      \"FOOD\",\n      \"Food Network\",\n      \"Fox\",\n      \"FOX\",\n      \"Fox Premium\",\n      \"FOXP\",\n      \"Foxtel\",\n      \"FP\",\n      \"FREE\",\n      \"Freeform\",\n      \"FXTL\",\n      \"FYI\",\n      \"FYI Network\",\n      \"Gaga\",\n      \"GagaOOLala\",\n      \"GC\",\n      \"GLBL\",\n      \"GLOB\",\n      \"Global\",\n      \"GloboSat Play\",\n      \"Hallmark\",\n      \"HBO\",\n      \"HBO Go\",\n      \"HBO Max\",\n      \"HGTV\",\n      \"HIST\",\n      \"History\",\n      \"HLMK\",\n      \"HMAX\",\n      \"hoichoi\",\n      \"HoiChoi\",\n      \"Hulu\",\n      \"HULU\",\n      \"ID\",\n      \"IFC\",\n      \"iflix\",\n      \"IFX\",\n      \"INA\",\n      \"Investigation Discovery\",\n      \"iP\",\n      \"iQIYI\",\n      \"iT\",\n      \"iTunes\",\n      \"ITV\",\n      \"KNOW\",\n      \"Knowledge Network\",\n      \"LIFE\",\n      \"Lifetime\",\n      \"MBC\",\n      \"MBCVOD\",\n      \"MNBC\",\n      \"Motor Trend OnDemand\",\n      \"MSNBC\",\n      \"MTOD\",\n      \"MTV\",\n      \"MUBI\",\n      \"NATG\",\n      \"National Audiovisual Institute\",\n      \"National Film Board\",\n      \"National Geographic\",\n      \"NBA\",\n      \"NBA TV\",\n      \"NBC\",\n      \"Netflix\",\n      \"NF\",\n      \"NFB\",\n      \"NFL\",\n      \"NFL Now\",\n      \"NFLN\",\n      \"NHL GameCenter\",\n      \"NICK\",\n      \"NICKAPP\",\n      \"Nickelodeon\",\n      \"Norsk Rikskringkasting\",\n      \"NRK\",\n      \"ODK\",\n      \"OnDemandKorea\",\n      \"Oprah Winfrey Network\",\n      \"Opto\",\n      \"OPTO\",\n      \"OWN\",\n      \"Paramount+\",\n      \"ParamountPlus\",\n      \"PBS\",\n      \"PBS Kids\",\n      \"PBSK\",\n      \"PCOK\",\n      \"Peacock\",\n      \"Playstation Network\",\n      \"PLUZ\",\n      \"Pluzz\",\n      \"PMNP\",\n      \"PMT+\",\n      \"PMTP\",\n      \"POGO\",\n      \"PokerGO\",\n      \"PSN\",\n      \"Rakuten TV\",\n      \"RED\",\n      \"RKTN\",\n      \"ROKU\",\n      \"RTE\",\n      \"RTE One\",\n      \"RUUTU\",\n      \"SBS\",\n      \"SCI\",\n      \"Science Channel\",\n      \"SeeSo\",\n      \"SESO\",\n      \"SHMI\",\n      \"SHO\",\n      \"Shomi\",\n      \"Showtime\",\n      \"SNET\",\n      \"Sony\",\n      \"SONY\",\n      \"SPIK\",\n      \"Spike\",\n      \"Spike TV\",\n      \"SPKE\",\n      \"Sportsnet\",\n      \"Sprout\",\n      \"SPRT\",\n      \"Stan\",\n      \"STAN\",\n      \"Starz\",\n      \"STZ\",\n      \"Sveriges Television\",\n      \"SVT\",\n      \"SwearNet\",\n      \"SWER\",\n      \"Syfy\",\n      \"SYFY\",\n      \"TBS\",\n      \"TFou\",\n      \"TFOU\",\n      \"The CW\",\n      \"The Roku Channel\",\n      \"TLC\",\n      \"TUBI\",\n      \"TubiTV\",\n      \"TV Land\",\n      \"TV3\",\n      \"TV3 Ireland\",\n      \"TV4\",\n      \"TV4 Sweeden\",\n      \"TVING\",\n      \"TVL\",\n      \"TVNZ\",\n      \"UFC\",\n      \"UFC Fight Pass\",\n      \"UKTV\",\n      \"UNIV\",\n      \"Univision\",\n      \"USA Network\",\n      \"USAN\",\n      \"Velocity\",\n      \"VH1\",\n      \"VICE\",\n      \"Viceland\",\n      \"Viki\",\n      \"VIKI\",\n      \"Vimeo\",\n      \"VLCT\",\n      \"VMEO\",\n      \"VRV\",\n      \"W Network\",\n      \"WatchMe\",\n      \"WME\",\n      \"WNET\",\n      \"WWE Network\",\n      \"WWEN\",\n      \"XBOX\",\n      \"Xbox Video\",\n      \"Yahoo\",\n      \"YHOO\",\n      \"YouTube Red\",\n      \"ZDF\"\n    ]\n  },\n  \"subtitle_language\": {\n    \"type\": [\n      \"Language\"\n    ],\n    \"array\": true,\n    \"scalar\": true\n  },\n  \"title\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"type\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"episode\",\n      \"movie\"\n    ]\n  },\n  \"uuid\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"version\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"video_api\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"DXVA\"\n    ]\n  },\n  \"video_bit_rate\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"video_codec\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true,\n    \"enum\": [\n      \"DivX\",\n      \"DVDivX\",\n      \"H.263\",\n      \"H.264\",\n      \"H.265\",\n      \"MPEG-2\",\n      \"RealVideo\",\n      \"VC-1\",\n      \"VP7\",\n      \"VP8\",\n      \"VP80\",\n      \"VP9\",\n      \"Xvid\",\n      \"XviD\"\n    ]\n  },\n  \"video_profile\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": true,\n    \"scalar\": true,\n    \"enum\": [\n      \"Advanced Video Codec High Definition\",\n      \"Baseline\",\n      \"BP\",\n      \"EP\",\n      \"Extended\",\n      \"HEVC\",\n      \"High\",\n      \"High 10\",\n      \"High 4:2:2\",\n      \"High 4:4:4 Predictive\",\n      \"High Efficiency Video Coding\",\n      \"HiP\",\n      \"HP\",\n      \"Main\",\n      \"MP\",\n      \"SC\",\n      \"Scalable Video Coding\",\n      \"SVC\",\n      \"XP\"\n    ]\n  },\n  \"website\": {\n    \"type\": [\n      \"string\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  },\n  \"year\": {\n    \"type\": [\n      \"number\"\n    ],\n    \"array\": false,\n    \"scalar\": true\n  }\n};\n\n/** Fully-typed guessit-js result. Every key is optional (presence depends on the input). */\nexport interface GuessItResult {\n  absolute_episode?: number | (number)[];\n  alternative_title?: string | (string)[];\n  another?: string;\n  aspect_ratio?: number;\n  audio_bit_rate?: string;\n  audio_channels?: \"1.0\" | \"1ch\" | \"2.0\" | \"20\" | \"2ch\" | \"5.1\" | \"5ch\" | \"6ch\" | \"7.1\" | \"7ch\" | \"8ch\" | \"mono\" | \"stereo\" | (\"1.0\" | \"1ch\" | \"2.0\" | \"20\" | \"2ch\" | \"5.1\" | \"5ch\" | \"6ch\" | \"7.1\" | \"7ch\" | \"8ch\" | \"mono\" | \"stereo\")[];\n  audio_codec?: \"AAC\" | \"Atmos\" | \"DD+\" | \"DDP\" | \"Dolby\" | \"Dolby Atmos\" | \"Dolby Digital\" | \"Dolby Digital Plus\" | \"Dolby TrueHD\" | \"DolbyDigital\" | \"DTS\" | \"DTS-HD\" | \"DTS-X\" | \"DTS:X\" | \"DTSX\" | \"Flac\" | \"FLAC\" | \"LAME\" | \"LPCM\" | \"MP2\" | \"MP3\" | \"Opus\" | \"PCM\" | \"Vorbis\" | (\"AAC\" | \"Atmos\" | \"DD+\" | \"DDP\" | \"Dolby\" | \"Dolby Atmos\" | \"Dolby Digital\" | \"Dolby Digital Plus\" | \"Dolby TrueHD\" | \"DolbyDigital\" | \"DTS\" | \"DTS-HD\" | \"DTS-X\" | \"DTS:X\" | \"DTSX\" | \"Flac\" | \"FLAC\" | \"LAME\" | \"LPCM\" | \"MP2\" | \"MP3\" | \"Opus\" | \"PCM\" | \"Vorbis\")[];\n  audio_profile?: \"ES\" | \"EX\" | \"Extended Surround\" | \"HE\" | \"High Efficiency\" | \"High Quality\" | \"High Resolution Audio\" | \"HQ\" | \"HR\" | \"HRA\" | \"LC\" | \"Low Complexity\" | \"MA\" | \"Master Audio\" | (\"ES\" | \"EX\" | \"Extended Surround\" | \"HE\" | \"High Efficiency\" | \"High Quality\" | \"High Resolution Audio\" | \"HQ\" | \"HR\" | \"HRA\" | \"LC\" | \"Low Complexity\" | \"MA\" | \"Master Audio\")[];\n  bonus?: number;\n  bonus_title?: string;\n  cd?: number;\n  cd_count?: number;\n  color_depth?: \"10-bit\" | \"12-bit\" | \"8-bit\";\n  container?: \"3g2\" | \"3gp\" | \"3gp2\" | \"7z\" | \"ace\" | \"arj\" | \"asf\" | \"avi\" | \"bmp\" | \"bz2\" | \"cb7\" | \"cbr\" | \"cbz\" | \"divx\" | \"flv\" | \"gif\" | \"gz\" | \"idx\" | \"iso\" | \"jpeg\" | \"jpg\" | \"m2ts\" | \"m4v\" | \"mk2\" | \"mk3d\" | \"mka\" | \"mkv\" | \"MKV\" | \"mov\" | \"mp4\" | \"mp4a\" | \"mpeg\" | \"mpg\" | \"nfo\" | \"nzb\" | \"ogg\" | \"ogm\" | \"ogv\" | \"png\" | \"qt\" | \"r00\" | \"ra\" | \"ram\" | \"rar\" | \"rm\" | \"srt\" | \"ssa\" | \"tar\" | \"tbn\" | \"tgz\" | \"torrent\" | \"ts\" | \"vob\" | \"wav\" | \"webm\" | \"webp\" | \"wma\" | \"wmv\" | \"zip\" | (\"3g2\" | \"3gp\" | \"3gp2\" | \"7z\" | \"ace\" | \"arj\" | \"asf\" | \"avi\" | \"bmp\" | \"bz2\" | \"cb7\" | \"cbr\" | \"cbz\" | \"divx\" | \"flv\" | \"gif\" | \"gz\" | \"idx\" | \"iso\" | \"jpeg\" | \"jpg\" | \"m2ts\" | \"m4v\" | \"mk2\" | \"mk3d\" | \"mka\" | \"mkv\" | \"MKV\" | \"mov\" | \"mp4\" | \"mp4a\" | \"mpeg\" | \"mpg\" | \"nfo\" | \"nzb\" | \"ogg\" | \"ogm\" | \"ogv\" | \"png\" | \"qt\" | \"r00\" | \"ra\" | \"ram\" | \"rar\" | \"rm\" | \"srt\" | \"ssa\" | \"tar\" | \"tbn\" | \"tgz\" | \"torrent\" | \"ts\" | \"vob\" | \"wav\" | \"webm\" | \"webp\" | \"wma\" | \"wmv\" | \"zip\")[];\n  country?: string | GuessitLanguage;\n  crc32?: string;\n  date?: string | Date;\n  disc?: number | (number)[];\n  edition?: \"Alternative Cut\" | \"CC\" | \"collector\" | \"Collector\" | \"Criterion\" | \"DC\" | \"ddc\" | \"deluxe\" | \"Deluxe\" | \"Director's Cut\" | \"Director's Definitive Cut\" | \"extended\" | \"Extended\" | \"Fan\" | \"Festival\" | \"imax\" | \"IMAX\" | \"limited\" | \"Limited\" | \"Remastered\" | \"Restored\" | \"se\" | \"Special\" | \"theatrical\" | \"Theatrical\" | \"Ultimate\" | \"Uncensored\" | \"Uncut\" | \"Unrated\" | (\"Alternative Cut\" | \"CC\" | \"collector\" | \"Collector\" | \"Criterion\" | \"DC\" | \"ddc\" | \"deluxe\" | \"Deluxe\" | \"Director's Cut\" | \"Director's Definitive Cut\" | \"extended\" | \"Extended\" | \"Fan\" | \"Festival\" | \"imax\" | \"IMAX\" | \"limited\" | \"Limited\" | \"Remastered\" | \"Restored\" | \"se\" | \"Special\" | \"theatrical\" | \"Theatrical\" | \"Ultimate\" | \"Uncensored\" | \"Uncut\" | \"Unrated\")[];\n  episode?: number | (number)[];\n  episode_count?: number;\n  episode_details?: string | (string)[];\n  episode_format?: \"Minisode\";\n  episode_title?: string;\n  film?: number;\n  film_title?: string;\n  frame_rate?: string;\n  language?: string | GuessitLanguage | (string | GuessitLanguage)[];\n  mimetype?: \"application/x-bittorrent\" | \"application/x-iso9660-image\" | \"application/x-rar-compressed\" | \"application/zip\" | \"image/gif\" | \"image/jpeg\" | \"image/png\" | \"text/plain\" | \"video/mp2t\" | \"video/mp4\" | \"video/webm\" | \"video/x-matroska\" | \"video/x-msvideo\";\n  other?: \"2in1\" | \"3D\" | \"asrequested\" | \"Audio Fixed\" | \"Banner\" | \"Bonus\" | \"BT.2020\" | \"Classic\" | \"Clear Art\" | \"Clear Logo\" | \"Colorized\" | \"Complet\" | \"Complete\" | \"CONVERT\" | \"Converted\" | \"Cover\" | \"Dirfix\" | \"Disc Art\" | \"DOCU\" | \"Documentary\" | \"DOKU\" | \"Dolby Vision\" | \"Dual\" | \"Dual Audio\" | \"East Coast Feed\" | \"Extras\" | \"Fan Subtitled\" | \"Fanart\" | \"Fansub\" | \"Fast Subtitled\" | \"Fastsub\" | \"FHD\" | \"Fix\" | \"Fixed\" | \"Full HD\" | \"Half Over Under\" | \"Half Side By Side\" | \"Hardcoded Subtitles\" | \"HC\" | \"HD\" | \"HDLight\" | \"HDR10\" | \"HFR\" | \"High Frame Rate\" | \"High Quality\" | \"High Resolution\" | \"HQ\" | \"HR\" | \"Hybrid\" | \"Internal\" | \"Landscape\" | \"LD\" | \"LDTV\" | \"LiNE\" | \"Line Audio\" | \"Line Dubbed\" | \"Logo\" | \"Low Definition\" | \"MD\" | \"mHD\" | \"Mic Dubbed\" | \"Micro HD\" | \"Mux\" | \"Nfofix\" | \"NTSC\" | \"Oad\" | \"OAR\" | \"Oav\" | \"Obfuscated\" | \"Ona\" | \"Open Matte\" | \"Original Animated Video\" | \"Original Animation DVD\" | \"Original Aspect Ratio\" | \"Original Net Animation\" | \"Original Video\" | \"OV\" | \"Ova\" | \"Over Under\" | \"PAL\" | \"postbot\" | \"Poster\" | \"Preair\" | \"Proof\" | \"Prooffix\" | \"Proper\" | \"PS Vita\" | \"R5\" | \"RC\" | \"Read NFO\" | \"Real\" | \"Reencoded\" | \"Region 5\" | \"Region C\" | \"Remux\" | \"Repost\" | \"Retail\" | \"Rip\" | \"Sample\" | \"Scrambled\" | \"Screener\" | \"SDR\" | \"SECAM\" | \"Side By Side\" | \"Standard Dynamic Range\" | \"Straight to Video\" | \"STV\" | \"Sync Fixed\" | \"Thumbnail\" | \"Trailer\" | \"UHD\" | \"Ultra HD\" | \"Upscaled\" | \"Variable Frame Rate\" | \"VFR\" | \"Virtual Reality\" | \"Vita\" | \"VO\" | \"vost\" | \"West Coast Feed\" | \"Widescreen\" | \"ws\" | \"xpost\" | \"XXX\" | (\"2in1\" | \"3D\" | \"asrequested\" | \"Audio Fixed\" | \"Banner\" | \"Bonus\" | \"BT.2020\" | \"Classic\" | \"Clear Art\" | \"Clear Logo\" | \"Colorized\" | \"Complet\" | \"Complete\" | \"CONVERT\" | \"Converted\" | \"Cover\" | \"Dirfix\" | \"Disc Art\" | \"DOCU\" | \"Documentary\" | \"DOKU\" | \"Dolby Vision\" | \"Dual\" | \"Dual Audio\" | \"East Coast Feed\" | \"Extras\" | \"Fan Subtitled\" | \"Fanart\" | \"Fansub\" | \"Fast Subtitled\" | \"Fastsub\" | \"FHD\" | \"Fix\" | \"Fixed\" | \"Full HD\" | \"Half Over Under\" | \"Half Side By Side\" | \"Hardcoded Subtitles\" | \"HC\" | \"HD\" | \"HDLight\" | \"HDR10\" | \"HFR\" | \"High Frame Rate\" | \"High Quality\" | \"High Resolution\" | \"HQ\" | \"HR\" | \"Hybrid\" | \"Internal\" | \"Landscape\" | \"LD\" | \"LDTV\" | \"LiNE\" | \"Line Audio\" | \"Line Dubbed\" | \"Logo\" | \"Low Definition\" | \"MD\" | \"mHD\" | \"Mic Dubbed\" | \"Micro HD\" | \"Mux\" | \"Nfofix\" | \"NTSC\" | \"Oad\" | \"OAR\" | \"Oav\" | \"Obfuscated\" | \"Ona\" | \"Open Matte\" | \"Original Animated Video\" | \"Original Animation DVD\" | \"Original Aspect Ratio\" | \"Original Net Animation\" | \"Original Video\" | \"OV\" | \"Ova\" | \"Over Under\" | \"PAL\" | \"postbot\" | \"Poster\" | \"Preair\" | \"Proof\" | \"Prooffix\" | \"Proper\" | \"PS Vita\" | \"R5\" | \"RC\" | \"Read NFO\" | \"Real\" | \"Reencoded\" | \"Region 5\" | \"Region C\" | \"Remux\" | \"Repost\" | \"Retail\" | \"Rip\" | \"Sample\" | \"Scrambled\" | \"Screener\" | \"SDR\" | \"SECAM\" | \"Side By Side\" | \"Standard Dynamic Range\" | \"Straight to Video\" | \"STV\" | \"Sync Fixed\" | \"Thumbnail\" | \"Trailer\" | \"UHD\" | \"Ultra HD\" | \"Upscaled\" | \"Variable Frame Rate\" | \"VFR\" | \"Virtual Reality\" | \"Vita\" | \"VO\" | \"vost\" | \"West Coast Feed\" | \"Widescreen\" | \"ws\" | \"xpost\" | \"XXX\")[];\n  part?: number | (number)[];\n  proper_count?: number;\n  release_group?: string;\n  screen_size?: \"1080i\" | \"1080p\" | \"1440p\" | \"1444x866\" | \"2160p\" | \"360p\" | \"368p\" | \"480p\" | \"4k\" | \"540p\" | \"576p\" | \"720p\" | \"720x432\" | \"960x544\";\n  season?: number | (number)[];\n  season_count?: number;\n  size?: string;\n  source?: \"Analog HDTV\" | \"Blu-ray\" | \"Camera\" | \"Digital Master\" | \"Digital TV\" | \"DVD\" | \"HD Camera\" | \"HD Telecine\" | \"HD Telesync\" | \"HD-DVD\" | \"HDTV\" | \"Laserdisc\" | \"Pay-per-view\" | \"Satellite\" | \"Telecine\" | \"Telesync\" | \"TV\" | \"Ultra HD Blu-ray\" | \"Ultra HDTV\" | \"VHS\" | \"Video on Demand\" | \"Web\" | \"Workprint\";\n  streaming_service?: \"4OD\" | \"9Now\" | \"9NOW\" | \"A&E\" | \"ABC\" | \"ABC Australia\" | \"Adult Swim\" | \"AE\" | \"AJAZ\" | \"Al Jazeera English\" | \"ALL4\" | \"Amazon\" | \"Amazon Prime\" | \"AMBC\" | \"AMC\" | \"America's Test Kitchen\" | \"AMZN\" | \"AMZN-CBR\" | \"Animal Planet\" | \"AnimeLab\" | \"ANLB\" | \"ANPL\" | \"AOL\" | \"AppleTV\" | \"APTV\" | \"ARD\" | \"AS\" | \"ATK\" | \"ATV+\" | \"ATVP\" | \"AUBC\" | \"BBC iPlayer\" | \"Binge\" | \"BKPL\" | \"Blackpills\" | \"BLU\" | \"BluTV\" | \"BNGE\" | \"BOOM\" | \"Boomerang\" | \"BRAV\" | \"BravoTV\" | \"Canal+\" | \"Cartoon Network\" | \"CBC\" | \"CBS\" | \"CC\" | \"CCGC\" | \"Channel 4\" | \"CHGD\" | \"CHRGD\" | \"Cinemax\" | \"CMAX\" | \"CMT\" | \"CN\" | \"CNBC\" | \"CNLP\" | \"Comedians in Cars Getting Coffee\" | \"Comedy Central\" | \"Country Music Television\" | \"CR\" | \"Crackle\" | \"CRAV\" | \"Crave\" | \"CRKL\" | \"Crunchy Roll\" | \"CSpan\" | \"CSPN\" | \"CTV\" | \"CUR\" | \"CuriosityStream\" | \"CW\" | \"CWS\" | \"CWSeed\" | \"Daisuki\" | \"DC Universe\" | \"DCU\" | \"DDY\" | \"Deadhouse Films\" | \"DF\" | \"DHF\" | \"Digiturk Diledigin Yerde\" | \"DISC\" | \"Discovery\" | \"Discovery Plus\" | \"Disney\" | \"Disney+\" | \"DIY\" | \"DIY Network\" | \"Doc Club\" | \"DOCC\" | \"DPlay\" | \"DPLY\" | \"DramaFever\" | \"DSCP\" | \"DSKI\" | \"DSNP\" | \"DSNY\" | \"E!\" | \"El Trece\" | \"ePix\" | \"EPIX\" | \"ESPN\" | \"ESQ\" | \"Esquire\" | \"ETTV\" | \"ETV\" | \"Facebook Watch\" | \"FAM\" | \"Family\" | \"Family Jr\" | \"Fandor\" | \"FANDOR\" | \"FBWatch\" | \"FJR\" | \"FOOD\" | \"Food Network\" | \"Fox\" | \"FOX\" | \"Fox Premium\" | \"FOXP\" | \"Foxtel\" | \"FP\" | \"FREE\" | \"Freeform\" | \"FXTL\" | \"FYI\" | \"FYI Network\" | \"Gaga\" | \"GagaOOLala\" | \"GC\" | \"GLBL\" | \"GLOB\" | \"Global\" | \"GloboSat Play\" | \"Hallmark\" | \"HBO\" | \"HBO Go\" | \"HBO Max\" | \"HGTV\" | \"HIST\" | \"History\" | \"HLMK\" | \"HMAX\" | \"hoichoi\" | \"HoiChoi\" | \"Hulu\" | \"HULU\" | \"ID\" | \"IFC\" | \"iflix\" | \"IFX\" | \"INA\" | \"Investigation Discovery\" | \"iP\" | \"iQIYI\" | \"iT\" | \"iTunes\" | \"ITV\" | \"KNOW\" | \"Knowledge Network\" | \"LIFE\" | \"Lifetime\" | \"MBC\" | \"MBCVOD\" | \"MNBC\" | \"Motor Trend OnDemand\" | \"MSNBC\" | \"MTOD\" | \"MTV\" | \"MUBI\" | \"NATG\" | \"National Audiovisual Institute\" | \"National Film Board\" | \"National Geographic\" | \"NBA\" | \"NBA TV\" | \"NBC\" | \"Netflix\" | \"NF\" | \"NFB\" | \"NFL\" | \"NFL Now\" | \"NFLN\" | \"NHL GameCenter\" | \"NICK\" | \"NICKAPP\" | \"Nickelodeon\" | \"Norsk Rikskringkasting\" | \"NRK\" | \"ODK\" | \"OnDemandKorea\" | \"Oprah Winfrey Network\" | \"Opto\" | \"OPTO\" | \"OWN\" | \"Paramount+\" | \"ParamountPlus\" | \"PBS\" | \"PBS Kids\" | \"PBSK\" | \"PCOK\" | \"Peacock\" | \"Playstation Network\" | \"PLUZ\" | \"Pluzz\" | \"PMNP\" | \"PMT+\" | \"PMTP\" | \"POGO\" | \"PokerGO\" | \"PSN\" | \"Rakuten TV\" | \"RED\" | \"RKTN\" | \"ROKU\" | \"RTE\" | \"RTE One\" | \"RUUTU\" | \"SBS\" | \"SCI\" | \"Science Channel\" | \"SeeSo\" | \"SESO\" | \"SHMI\" | \"SHO\" | \"Shomi\" | \"Showtime\" | \"SNET\" | \"Sony\" | \"SONY\" | \"SPIK\" | \"Spike\" | \"Spike TV\" | \"SPKE\" | \"Sportsnet\" | \"Sprout\" | \"SPRT\" | \"Stan\" | \"STAN\" | \"Starz\" | \"STZ\" | \"Sveriges Television\" | \"SVT\" | \"SwearNet\" | \"SWER\" | \"Syfy\" | \"SYFY\" | \"TBS\" | \"TFou\" | \"TFOU\" | \"The CW\" | \"The Roku Channel\" | \"TLC\" | \"TUBI\" | \"TubiTV\" | \"TV Land\" | \"TV3\" | \"TV3 Ireland\" | \"TV4\" | \"TV4 Sweeden\" | \"TVING\" | \"TVL\" | \"TVNZ\" | \"UFC\" | \"UFC Fight Pass\" | \"UKTV\" | \"UNIV\" | \"Univision\" | \"USA Network\" | \"USAN\" | \"Velocity\" | \"VH1\" | \"VICE\" | \"Viceland\" | \"Viki\" | \"VIKI\" | \"Vimeo\" | \"VLCT\" | \"VMEO\" | \"VRV\" | \"W Network\" | \"WatchMe\" | \"WME\" | \"WNET\" | \"WWE Network\" | \"WWEN\" | \"XBOX\" | \"Xbox Video\" | \"Yahoo\" | \"YHOO\" | \"YouTube Red\" | \"ZDF\";\n  subtitle_language?: string | GuessitLanguage | (string | GuessitLanguage)[];\n  title?: string;\n  type?: \"episode\" | \"movie\";\n  uuid?: string;\n  version?: number;\n  video_api?: \"DXVA\";\n  video_bit_rate?: string;\n  video_codec?: \"DivX\" | \"DVDivX\" | \"H.263\" | \"H.264\" | \"H.265\" | \"MPEG-2\" | \"RealVideo\" | \"VC-1\" | \"VP7\" | \"VP8\" | \"VP80\" | \"VP9\" | \"Xvid\" | \"XviD\";\n  video_profile?: \"Advanced Video Codec High Definition\" | \"Baseline\" | \"BP\" | \"EP\" | \"Extended\" | \"HEVC\" | \"High\" | \"High 10\" | \"High 4:2:2\" | \"High 4:4:4 Predictive\" | \"High Efficiency Video Coding\" | \"HiP\" | \"HP\" | \"Main\" | \"MP\" | \"SC\" | \"Scalable Video Coding\" | \"SVC\" | \"XP\" | (\"Advanced Video Codec High Definition\" | \"Baseline\" | \"BP\" | \"EP\" | \"Extended\" | \"HEVC\" | \"High\" | \"High 10\" | \"High 4:2:2\" | \"High 4:4:4 Predictive\" | \"High Efficiency Video Coding\" | \"HiP\" | \"HP\" | \"Main\" | \"MP\" | \"SC\" | \"Scalable Video Coding\" | \"SVC\" | \"XP\")[];\n  website?: string;\n  year?: number;\n  /** Any future / custom property. */\n  [key: string]: unknown;\n}\n","/**\n * Main API — port of guessit/api.py\n */\nimport type { Rebulk } from 'rebulk-js';\nimport { rebulkBuilder, type AdvancedConfig } from './rules/index.js';\nimport { parseOptions, loadConfig, mergeOptions, type GuessItOptions, type RawOptions } from './options.js';\nimport { GUESSIT_SCHEMA } from './schema.js';\nexport type { GuessItResult, GuessitLanguage, PropertySchema } from './schema.js';\nexport { GUESSIT_SCHEMA } from './schema.js';\nimport type { GuessItResult } from './schema.js';\n\nexport class GuessItException extends Error {\n  string: string;\n  options: Record<string, unknown>;\n\n  constructor(string: string, options: Record<string, unknown>, cause?: unknown) {\n    const causeMsg = cause instanceof Error ? cause.message : String(cause);\n    super(\n      `An internal error has occurred in guessit.\\n` +\n      `string=${string}\\n` +\n      `options=${JSON.stringify(options)}\\n` +\n      causeMsg,\n    );\n    this.name = 'GuessItException';\n    this.string = string;\n    this.options = options;\n    if (cause instanceof Error) (this as unknown as { cause: unknown }).cause = cause;\n  }\n}\n\n\nexport class GuessItApi {\n  private _rebulk: Rebulk | null = null;\n  private _config: Record<string, unknown> | null = null;\n  private _loadConfigOptions: GuessItOptions | null = null;\n  private _advancedConfig: unknown = null;\n\n  reset(): void {\n    this._rebulk = null;\n    this._config = null;\n    this._loadConfigOptions = null;\n    this._advancedConfig = null;\n  }\n\n  configure(\n    options?: RawOptions,\n    rulesBuilder?: (config: AdvancedConfig) => Rebulk,\n    force = false,\n    sanitizeOptions = true,\n  ): Record<string, unknown> {\n    const builder = rulesBuilder ?? rebulkBuilder;\n\n    let parsedOptions = sanitizeOptions ? parseOptions(options, true) : (options as GuessItOptions ?? {});\n\n    const hasSameConfigProps = (a: GuessItOptions, b: GuessItOptions) =>\n      a['config'] === b['config'] &&\n      a.noUserConfig === b.noUserConfig &&\n      a.noDefaultConfig === b.noDefaultConfig;\n\n    let config: Record<string, unknown>;\n    if (this._config === null || this._loadConfigOptions === null || force ||\n        !hasSameConfigProps(this._loadConfigOptions, parsedOptions)) {\n      config = loadConfig(parsedOptions);\n      this._loadConfigOptions = parsedOptions;\n    } else {\n      config = this._config;\n    }\n\n    const advancedConfig = mergeOptions(\n      (config['advanced_config'] as Record<string, unknown>) ?? {},\n      (parsedOptions['advancedConfig'] as Record<string, unknown>) ?? {},\n    );\n\n    const shouldBuild = force || !this._rebulk || !this._advancedConfig ||\n      JSON.stringify(this._advancedConfig) !== JSON.stringify(advancedConfig);\n\n    if (shouldBuild) {\n      this._advancedConfig = JSON.parse(JSON.stringify(advancedConfig));\n      this._rebulk = builder(advancedConfig as AdvancedConfig);\n    }\n\n    this._config = config;\n    return config;\n  }\n\n  guessit(string: string, options?: RawOptions): GuessItResult {\n    try {\n      const parsedOptions = parseOptions(options, true);\n      const config = this.configure(parsedOptions, undefined, false, false);\n      const mergedOptions = mergeOptions(config, parsedOptions);\n\n      if (!this._rebulk) {\n        throw new Error('Rebulk not initialized');\n      }\n\n      const matches = this._rebulk.matches(string, mergedOptions);\n      const matchesDict = matches.toDict(\n        !!(mergedOptions['advanced'] as boolean),\n        !!(mergedOptions['singleValue'] as boolean) || !!(mergedOptions['single_value'] as boolean),\n        !!(mergedOptions['enforceList'] as boolean) || !!(mergedOptions['enforce_list'] as boolean),\n      );\n\n      // Convert Map → plain object so callers can do result[key]\n      const result: GuessItResult = Object.fromEntries(matchesDict);\n\n      // Dedup language / subtitle_language VALUES at render time. Python never\n      // lists the same language twice (e.g. \"VFF+VFQ\" -> a single fra, two \"eng\"\n      // tags -> one). We dedup here rather than removing matches, because those\n      // duplicate matches are load-bearing — they suppress their text from\n      // adjacent title/episode_title holes. Distinct languages are preserved.\n      for (const key of ['language', 'subtitle_language']) {\n        const v = result[key];\n        if (!Array.isArray(v)) continue;\n        const seen = new Set<string>();\n        const deduped = v.filter((lang) => {\n          const id = lang && typeof lang === 'object' && 'alpha3' in lang\n            ? `${(lang as any).alpha3}:${(lang as any).country ?? ''}`\n            : String(lang);\n          if (seen.has(id)) return false;\n          seen.add(id);\n          return true;\n        });\n        result[key] = deduped.length === 1 ? deduped[0] : deduped;\n      }\n      if (mergedOptions['outputInputString'] || mergedOptions['output_input_string']) {\n        result['input_string'] = matches.inputString;\n      }\n\n      return result;\n    } catch (err) {\n      if (err instanceof GuessItException) throw err;\n      throw new GuessItException(\n        string,\n        typeof options === 'object' && options !== null ? options as Record<string, unknown> : {},\n        err,\n      );\n    }\n  }\n\n  properties(options?: RawOptions): Record<string, unknown[]> {\n    const parsedOptions = parseOptions(options, true);\n    const config = this.configure(parsedOptions, undefined, false, false);\n    const mergedOptions = mergeOptions(config, parsedOptions);\n\n    if (!this._rebulk) return {};\n\n    // Collect properties from all patterns\n    const props: Record<string, Set<unknown>> = {};\n    for (const pattern of (this._rebulk as unknown as { effectivePatterns(): Array<{ name?: string; properties?: Record<string, unknown[]> }> }).effectivePatterns()) {\n      if (pattern.properties) {\n        for (const [k, vals] of Object.entries(pattern.properties)) {\n          if (!props[k]) props[k] = new Set();\n          for (const v of vals) props[k].add(v);\n        }\n      }\n    }\n\n    let ordered: Record<string, unknown[]> = {};\n    for (const k of Object.keys(props).sort()) {\n      ordered[k] = [...props[k]].sort((a, b) => String(a).localeCompare(String(b)));\n    }\n\n    const rb = this._rebulk as unknown as { customizeProperties?: (p: Record<string, unknown>) => Record<string, unknown> };\n    if (rb.customizeProperties) {\n      ordered = rb.customizeProperties(ordered) as Record<string, unknown[]>;\n    }\n\n    // Final step: complete the (incomplete) pattern-derived map with the\n    // declarative GUESSIT_SCHEMA so every emittable property is advertised with\n    // its possible values — like Python's guessit.api.properties(). Done AFTER\n    // customizeProperties (which otherwise blanks count properties). Value-\n    // constrained properties get their enum; free/computed ones (title, episode,\n    // year, …) get [null], matching Python's convention.\n    for (const [name, def] of Object.entries(GUESSIT_SCHEMA)) {\n      const cur = Array.isArray(ordered[name]) ? ordered[name] : [];\n      if (def.enum) {\n        const merged = new Set([...cur, ...def.enum]);\n        ordered[name] = [...merged].sort((a, b) => String(a).localeCompare(String(b)));\n      } else if (cur.length === 0) {\n        ordered[name] = [null];\n      }\n    }\n    return ordered;\n  }\n\n  suggestedExpected(titles: string[], options?: RawOptions): string[] {\n    const suggested: string[] = [];\n    for (const title of titles) {\n      const guess = this.guessit(title, options);\n      if (Object.keys(guess).length !== 2 || !('title' in guess)) {\n        suggested.push(title);\n      }\n    }\n    return suggested;\n  }\n}\n\n/** Default singleton API instance */\nexport const defaultApi = new GuessItApi();\n\n/**\n * Guess metadata from a filename or release name.\n */\nexport function guessit(string: string, options?: RawOptions): GuessItResult {\n  return defaultApi.guessit(string, options);\n}\n\n/**\n * Get all properties that can be detected.\n */\nexport function properties(options?: RawOptions): Record<string, unknown[]> {\n  return defaultApi.properties(options);\n}\n\n/**\n * Configure the default API instance.\n */\nexport function configure(\n  options?: RawOptions,\n  rulesBuilder?: (config: AdvancedConfig) => Rebulk,\n  force = false,\n): void {\n  defaultApi.configure(options, rulesBuilder, force);\n}\n\n/**\n * Reset the default API instance.\n */\nexport function reset(): void {\n  defaultApi.reset();\n}\n","/**\n * guessit-js — TypeScript port of the Python guessit library.\n * Extracts metadata from media filenames.\n *\n * @example\n * import { guessit } from 'guessit-js';\n * guessit('The.Dark.Knight.2008.1080p.BluRay.x264-GROUP.mkv');\n * // => { title: 'The Dark Knight', year: 2008, screen_size: '1080p', source: 'Blu-ray', video_codec: 'H.264', release_group: 'GROUP', container: 'mkv', mimetype: 'video/x-matroska', type: 'movie' }\n */\n\nexport { guessit, properties, configure, reset, defaultApi, GuessItApi, GuessItException } from './api.js';\nexport { GUESSIT_SCHEMA } from './schema.js';\nexport type { GuessItResult, GuessitLanguage, PropertySchema } from './schema.js';\nexport { parseOptions, loadConfig, mergeOptions } from './options.js';\nexport type { GuessItOptions, RawOptions } from './options.js';\nexport { rebulkBuilder } from './rules/index.js';\nexport type { AdvancedConfig } from './rules/index.js';\n\n// Named import so bundlers inline only the version string, not the whole manifest.\nimport { version as pkgVersion } from '../package.json';\n/** The guessit-js package version. */\nexport const version: string = pkgVersion;\n"],"names":["defaultFormatter","value","__name","formatters","fns","result","fn","ensureList","param","ensureDict","defaultValue","defaultKey","filterIndex","collection","predicate","index","setDefaults","defaults","kwargs","override","key","isIterable","obj","findAll","string","sub","start","end","ignoreCase","haystack","needle","limit","idx","found","getFirstDefined","data","keys","extendSafe","target","source","elt","_IdentitySet","items","__publicField","item","IdentitySet","alwaysTrue","_match","charsBefore","chars","match","charsAfter","charsSurround","_Match","opts","v","Matches","ret","child","m","tags","names","n","crops","cropsArr","crop","cStart","cEnd","current","right","seps","currentStart","i","char","other","flags","initiatorVal","name","defined","Match","_MatchesDict","MatchesDict","__BaseMatches","matches","inputString","arr","tag","removed","old","a","b","pos","span","starting","ending","merged","prev","nxt","seen","position","chain","atI","filtered","formatter","ignore","hole","loopStart","startingMatches","rindex","holeEnd","lastRindex","ri","validHoles","h","details","firstValue","enforceList","val","matchArr","valEquals","valArr","existing","_BaseMatches","_Matches","Markers","_Markers","filterMatchKwargs","children","convertPythonNamedGroups","pattern","applyAbbreviations","abbreviations","replacement","compileRegex","src","flagStr","buildGroupNames","next3","nameEnd","_BasePattern","BasePattern","_Pattern","formattersMap","defaultFmt","valuesMap","defaultVal","validatorsMap","defaultValid","d","patternValue","validator","matchIndex","processor","processed","postProcessed","context","withRawMatches","allMatches","rawMatches","rawMatch","finalMatches","Pattern","_StringPattern","firstArg","rest","__super","args","_context","searchStart","searchEnd","p","StringPattern","_RePattern","patterns","compiled","groupNames","mainMatch","indices","groupIdx","groupIndices","gs","ge","childMatch","r","RePattern","_FunctionalPattern","args_iterable","s","e","matchOpts","f","FunctionalPattern","_ChainCtor","registerChain","ctor","getChainClass","splitPatternsOpts","first","last","_Builder","overrideKeys","backup","k","lastArg","o","actualFns","ChainCtor","c","Builder","_CyclicDependency","cyclic","parts","CyclicDependency","toposort","workData","deps","allDeps","dep","ordered","_Consequence","Consequence","_Condition","Condition","_CustomRule","CustomRule","_Rule","whenResponse","cons","iter","instance","Rule","_RemoveMatch","m2","RemoveMatch","_AppendMatch","matchName","AppendMatch","_RenameMatch","RenameMatch","_AppendTags","AppendTags","_Rules","rules","rule","module","byPriority","sortedPriorities","_priority","priorityRules","sorted","toposortRules","ruleGroup","groupArr","executeRule","Rules","graph","classToDeps","cls","rawDeps","depArr","resolved","insts","inst","DEFAULT_SYMBOL","PRE_PROCESS","POST_PROCESS","defaultConflictSolver","conflicting","_ConflictSolver","toRemove","publicMatches","publicConflicting","conflictingMatch","solvers","si","solver","reverse","toRem","toKeep","ConflictSolver","_PrivateRemover","PrivateRemover","_InvalidChainException","InvalidChainException","_ChainPart","hidden","j","truncated","ChainPart","_Chain","parent","pat","part","lastPattern","lastPatternChildren","lastPatternGroups","originalChildren","originalEnd","lastMatches","lm","_pattern","offset","chainFound","currentChainMatches","valid","chainInputString","chainPart","partMatches","rawPartMatches","groupedRaw","groupedAll","grouped","groupedMatches","chainMatch","oldRawStart","oldRawEnd","map","Chain","_Rebulk","rebulks","patternMatches","Rebulk","path","config","rebulk","markPath","_ConfigurationException","message","ConfigurationException","groups","markGroups","openings","ch","startType","endType","stack","startIndex","buildOrPattern","escape","ROMAN_VALUES","WORD_NUMERALS","parseRoman","upper","sym","parseWord","parseNumber","roman","sepsNoGroups","sepsNoFs","titleSeps","reEscape","sepsPattern","dash","altDash","optional","sepsBefore","sepsAfter","sepsSurround","intCoercable","and_","validators","or_","DIACRITIC_FOLD","foldDiacritics","input","out","EXCLUDED_CLEAN_CHARS","cleanChars","potentialBefore","potentialAfter","cleanup","cleanString","dots","cleanList","potentialIndices","replaceIndices","pi","versionDots","versionPattern","versionMatch","stripChars","strip","rawCleanup","raw","composeFormatters","reorderTitle","title","articles","separators","ltitle","article","separator","suffix","isDisabled","excludes","includes","CJK_DIGITS","CJK_NUMBER","parseCjkNumber","tens","ones","tensValue","onesValue","splitWords","entries","words","numfirst","entry","episodesSeasonChainBreaker","episodes","seasons","seasonEpisodeConflictSolver","weakFamily","famChild","mChild","oChild","mNumfirst","oNumfirst","before","isWeak","matchNumfirst","otherNumfirst","nf","wf","digitToken","from","dir","tok","isYearLike","t","nfInit","wfInit","nfDangling","matchIsWeak","otherIsWeak","matchIsSxxExx","otherIsSxxExx","matchHasX","otherHasX","orderingValidator","dict","values","validateRoman","seasonWordNotYear","discreteSeparators","weakDiscreteSeparators","allSeparators","moduleOrderingValidator","localOrderingValidator","isConsecutive","prop","previous","named","sraw","gap","numeralWithWords","numeral","isSeasonEpisodeDisabled","seasonMarkerPattern","episodeMarkerPattern","allSeparatorsPattern","seasonEpMarkerPattern","asymmetricSeasonEpMarker","seasonOnlySepPattern","detail","seasonWords","seasonWordsNumfirst","episodeWords","episodeWordsNumfirst","seasonWordPattern","ofWordPattern","ofCountPattern","episodeWordPattern","EventNumberAsTitleRule","EpisodeWordBeforeYearAsTitle","RemoveGroupSuffixSeason","AnimeTrailingEpisodeRule","PreferAnchoredWeakEpisodeRule","SeasonWordDashedEpisodeRule","RemoveNumfirstMarkerCollision","CountValidator","DiscMarkerRule","FixCorruptedGroupBoundaryValues","RangeExpansionRule","WeakConflictSolverRule","RemoveWeakDuplicateRule","RemoveWeakIfSxxExxRule","AbsoluteEpisodeInGroupRule","RemoveInvalidSeasonRule","RemoveInvalidEpisodeRule","RemoveUndeterminedLanguagesRule","_RemoveGroupSuffixSeason","TOKENS","season","init","inGroup","_EventNumberAsTitleRule","filepart","weaks","strong","w","after","_EpisodeWordBeforeYearAsTitle","episode","marker","year","between","_AnimeTrailingEpisodeRule","toAppend","crc","animeRg","groupCount","done","group","core","inner","numStart","newTitle","_PreferAnchoredWeakEpisodeRule","isWeakEp","removeGroup","byInit","score","sc","scored","top","winners","winnerValues","eps","_SeasonWordDashedEpisodeRule","markerRaw","isWordMarker","inBracket","nums","sep","episodeMatch","_RemoveNumfirstMarkerCollision","removeWithParent","all","numfirsts","wordFirst","wInit","claimed","gluedOrdinal","_CountValidator","episodeCount","seasonCount","count","numbers","numbered","_DiscMarkerRule","discMarkers","toRename","ep","initiator","markers","markerText","discExcluded","siblings","sib","_FixCorruptedGroupBoundaryValues","toFix","g","inputStr","digitEnd","digitStart","correctStr","correctValue","_RangeExpansionRule","rangeSeps","fileparts","filepartArr","getFilepart","fp","maxRange","next","currentFp","nextFp","curVal","nextVal","betweenClean","betweenStripMarkers","_RemoveInvalidSeasonRule","strongSeason","_RemoveInvalidEpisodeRule","strongEpisode","strongMarker","epMarkers","hasShortEMarker","_RemoveWeakDuplicateRule","weakDups","_a","_WeakConflictSolverRule","screenSizeInGroup","innerMatches","groupText","animeDetected","weakMatches","weakDupMatches","episodesInRange","hasSxxExx","_AbsoluteEpisodeInGroupRule","relevantGroups","isInGroup","insideGroup","outsideGroup","_whenResponse","_RemoveWeakIfSxxExxRule","sxxexxMatches","weakEpisodes","weakEpByInitiator","isWeakEpisode","isRange","inp","mStart","mEnd","prevChar","nextChar","isSurrounded","container","subtitles","info","videos","torrent","nzb","archives","images","nonStdSubtitles","ripPrefix","ripSuffix","buildSourcePattern","prefix","demoteOther","ValidateSourcePrefixSuffix","ValidateWeakSource","UltraHdBlurayRule","_ValidateSourcePrefixSuffix","sources","hasPrefixSep","hasPrefixTag","hasSuffixSep","hasSuffixTag","_ValidateWeakSource","toArray","hasText","holes","textHoles","containerMatches","isExtension","weak","nextSources","rivals","_UltraHdBlurayRule","bluRaySources","findUltraHd","hasHoles","hasInvalidMatches","has2160","newSource","videoCodec","ValidateVideoCodec","VideoProfileRule","_ValidateVideoCodec","codecs","hasAny","codec","bracketBefore","bracketAfter","_VideoProfileRule","profileList","profile","REGEX_PREFIX","IMPORT_PREFIX","EVAL_PREFIX","PATTERN_TYPES","importCache","registry","registerFunction","KNOWN_CONFLICT_SOLVERS","KNOWN_VALIDATORS","processExecutable","_defaultModule","expr","knownConflict","knownValidator","SNAKE_TO_CAMEL","normalizeCamelCase","snake","camel","processOption","buildEntryDecl","options","entryDecl","legacyPattern","loadPatterns","patternType","itemOptions","patternTypeOption","processedOptions","loadConfigPatterns","rawEntries","patternsEntryDecl","pt","currentPatternOptions","audioCodec","findCompoundAudio","results","CompoundAudioProfileRule","DtsHDRule","DtsRule","AacRule","DolbyDigitalRule","HqConflictRule","AudioValidatorRule","AudioChannelsValidatorRule","RemoveDecimalTitleChannels","COMPOUND_PROFILES","_CompoundAudioProfileRule","profileValue","afterCodec","maStart","_AudioProfileRule","profiles","hasResult","prevMatch","nextMatch","AudioProfileRule","_DtsHDRule","_DtsRule","_AacRule","_DolbyDigitalRule","_HqConflictRule","others","hqProfiles","hq","_AudioValidatorRule","AUDIO_PROPS","audioProps","validBefore","validAfter","_RemoveDecimalTitleChannels","channels","prefixed","yearAfter","_AudioChannelsValidatorRule","weakChannels","PARSER_RE","_Quantity","magnitude","units","_value","magStr","unitsStr","Quantity","_Size","Size","_BitRate","token","BitRate","_FrameRate","FrameRate","screenSize","interlaced","progressive","standardHeights","frameRates","minAr","maxAr","frameRatePattern","interlacedPattern","progressivePattern","resSeparator","resPattern","PostProcessScreenSize","ScreenSizeOnlyOne","ResolveScreenSizeConflicts","_PostProcessScreenSize","frameRate","mWxH","mH","scanType","height","width","calculatedAr","arMatch","_ScreenSizeOnlyOne","screenSizes","uniqueValues","_ResolveScreenSizeConflicts","screenSizeMatch","conflicts","hasNeighbor","allScreensizes","groupOf","following","TLDS","website","tlds","DEFAULT_TLDS","safeTlds","safeSubdomains","safePrefix","websitePrefixes","_PreferTitleOverWebsiteWithConfig","safeSubdomainsArg","safePrefixArg","websiteMatch","safe","safeStart","followers","followerArr","PreferTitleOverWebsiteWithConfig","ValidateWebsitePrefix","_ValidateWebsitePrefix","websites","webArr","DSEP","DSEP_BIS","DATE_REGEXPS","MONTHS","validYear","validWeek","week","isInt","guessDayFirst","tryParseDate","yearFirst","dayFirst","yearFirstOpts","dayFirstOpts","yf","df","month","day","monthNameIdx","x","_","yearPos","ts","yy","longIdx","date","searchDate","dateRe","globalRe","matchStr","dfGuess","dfGuessWasExplicit","dfOptions","_KeepMarkedYearInFilepart","yearMatches","pathMarkers","pathArray","yearsInPart","yearsInPartArray","groupYears","ungroupYears","firstGroupStart","y","KeepMarkedYearInFilepart","_RemoveGroupedYearWithSxxExx","groupLen","yearLen","RemoveGroupedYearWithSxxExx","_RemoveDecimalVersionDate","dateMatch","prevDigit","RemoveDecimalVersionDate","weekWords","weekPattern","dateFunctional","AbsorbWeekdayPrefix","_AbsorbWeekdayPrefix","weekdayWords","sepsClass","lower","segment","weekday","groupStart","newStart","markerComparatorPredicate","markerWeight","rangeResult","markerSorted","markersArr","originalIndex","weightDiff","buildExpectedFunction","optionName","expected","SEP_CLASS","rawPattern","patternStr","literalPat","TITLE_STOP_WORDS","hasmatch","_TitleBaseRule","propertyNames","alternativePropertyName","_hole","_filepart","groupMarkers","filteredGroups","cropped","ignored","lastIgnored","afterPos","ignoredValueStr","duplicates","text","splitPositions","prevIsSep","nextIsSep","createMatch","segments","prevEnd","absPos","seg","lastSeg","firstYearInFilepart","hasYearInFilepart","hasDateInFilepart","hasSxxExxInFilepart","holesResult","holeArray","processedHoles","ignoredInHole","ignoredArray","rel","trimmedHole","ignoredNames","firstIgnored","keep","hasTitleSep","pp","beforeWords","lastWord","allContiguousAtEnd","checkEnd","ig","animeStyle","splitResult","alt","mainTitle","absorbedRaw","absorbed","fpMatches","serieNameFilepart","existingTitle","weakIgnored","savedIsIgnored","combinedIgnore","serieTitle","sortedFileparts","serieNameMatch","yearFileparts","normTitle","titleMatch","filteredAppend","newVal","norm","existingIdx","existingVal","existingNorm","newNorm","response","TitleBaseRule","_TitleFromPosition","TitleFromPosition","_PreferTitleWithYear","titleMatches","titleArray","PreferTitleWithYear","ARTICLES","_ExtendLoneArticleTitle","titles","epTitles","titleArr","ExtendLoneArticleTitle","_CountryAtTitlePosition","cand","anchor","CountryAtTitlePosition","_TitleWordAtTitlePosition","tagged","candidate","TitleWordAtTitlePosition","NON_LATIN_SCRIPT_RE","_SplitOriginalScriptTitle","latin","latinOffset","prefixTrim","prefixEnd","latinStart","SplitOriginalScriptTitle","_TrimSeasonWordFromTitle","mm","newEnd","TrimSeasonWordFromTitle","_PreBracketJunkTitle","PreBracketJunkTitle","_BracketedTitleFallback","titlesHere","rg","softInner","hardInner","outside","outsideMatches","BracketedTitleFallback","_WordNumeralPartAtTitlePosition","WordNumeralPartAtTitlePosition","_BonusAtTitlePositionRule","bonus","bonusTitles","bt","BonusAtTitlePositionRule","_LanguageWordInAnimeTitle","lang","LanguageWordInAnimeTitle","_PropertyAtTitlePositionAsTitle","lead","anyTitle","yearTitled","PropertyAtTitlePositionAsTitle","_RemoveNumericAlternativeTitle","alts","altArr","RemoveNumericAlternativeTitle","_RemoveTailAlternativeTitle","titleish","years","yearArr","yMax","RemoveTailAlternativeTitle","_RemoveTailTitle","primary","head","RemoveTailTitle","expectedTitle","LEADING_ARTICLES_RE","normalizeTitle","_FormationRunEpisodeTitle","ets","et","run","runStart","FormationRunEpisodeTitle","episodeTitle","RemoveConflictsWithEpisodeTitle","TitleToEpisodeTitle","ExtendEpisodeTitleWithDetails","EpisodeTitleFromPosition","AlternativeTitleReplace","TrimLanguageFromEpisodeTitle","Filepart3EpisodeTitle","Filepart2EpisodeTitle","NumericEpisodeTitleToEpisode","RemoveEpisodeTitleInReleaseGroup","RemoveEpisodeMarkerWordTitle","RemoveEpisodeTitleCoveredByDetailsInGroup","RemoveFansubCreditEpisodeTitle","RemoveSubtitleDescriptorEpisodeTitle","RemoveHashFilepartJunk","RemoveTailEpisodeTitle","RenameEpisodeTitleWhenMovieType","EPISODE_MARKER_WORDS","_RemoveEpisodeMarkerWordTitle","etArr","_RemoveHashFilepartJunk","cont","_RemoveEpisodeTitleCoveredByDetailsInGroup","_RemoveFansubCreditEpisodeTitle","_RemoveSubtitleDescriptorEpisodeTitle","ET_STOP_WORDS","_RemoveTailEpisodeTitle","_RemoveEpisodeTitleInReleaseGroup","hasReleaseIn","onlySeps","_NumericEpisodeTitleToEpisode","_RemoveConflictsWithEpisodeTitle","affectedMatches","hasValueInSameGroup","holesBefore","holesAfter","hasHolesBefore","hasHolesAfter","_TitleToEpisodeTitle","titleGroups","episodeTitles","epNames","findPrevEpisode","prevMatches","seriesTitleKeys","_ExtendEpisodeTitleWithDetails","updates","detailMatches","_EpisodeTitleFromPosition","hasTitleInPart","hasEpisodeInPart","groupMarker","cropName","fpLangsRaw","langArr","guard","cover","prevPred","prevArr","prevEpisode","prevCrc32","crc32Matches","crc32Arr","_AlternativeTitleReplace","alternativeTitle","crc32","_TrimLanguageFromEpisodeTitle","overlapping","trimEnd","parentTitleHole","nextHole","holeRaw","nextRaw","_Filepart3EpisodeTitle","filename","directory","subdirectory","_Filepart2EpisodeTitle","anySeason","hasAnySeason","_RenameEpisodeTitleWhenMovieType","episodeType","LANGUAGES","buildLookupMap","ALPHA3_MAP","ALPHA2_MAP","NAME_MAP","OPENSUBTITLES_MAP","GUESSIT_SYNONYMS","_Language","alpha3","country","script","byName","byOpenSubs","byIETF","code","byAlpha2","synonyms","syn","Language","UNDETERMINED","MULTIPLE","iterWords","_LanguageWord","nextWord","nextSeparator","LanguageWord","_LanguageFinder","subtitlePrefixes","subtitleSuffixes","langPrefixes","langSuffixes","weakAffixes","commonWords","allowedLanguagesArray","regularLangMap","undeterminedMap","multiMap","emitted","emit","word","candidates","languageWord","directMatch","fallbackWord","affixes","isAffix","stripAffix","currentWord","wordLang","matchStart","matchEnd","trimmedValue","langWord","alpha2","LanguageFinder","_SubtitlePrefixLanguageRule","siblingRename","_pfx","renamedLang","SubtitlePrefixLanguageRule","_SubtitleSuffixLanguageRule","SubtitleSuffixLanguageRule","_SubtitleExtensionRule","containers","subtitleContainer","subtitleFilepart","languages","toConvert","l","SubtitleExtensionRule","_RemoveCommonWordsLanguageRule","allArr","nonLang","hasNonLang","holesRes","hasContentHoles","RemoveCommonWordsLanguageRule","_RemoveLanguageRule","RemoveLanguageRule","_RemoveUndeterminedLanguagesRule","langNames","_DedupLanguageRule","list","DedupLanguageRule","language","subtitleBoth","langBoth","finder","RemoveLanguageInsideTitle","_RemoveLanguageInsideTitle","titleNames","COUNTRY_MAP","findCountries","str","allowedCountries","CountryFinder","_CountryFinder","wordMatch","countryCode","releaseGroup","forbiddenGroupnames","groupnameIgnoreSeps","groupnameSeps","cleanGroupname","containsIgnored","startsWithIgnored","endsWithIgnored","forbidden","opening","expectedGroup","DashSeparatedReleaseGroup","SceneReleaseGroup","AnimeReleaseGroup","TrailingTokenAfterEpisodeAsReleaseGroup","NumericPrefixedGroupRule","RemoveSeasonPackReleaseGroup","_RemoveSeasonPackReleaseGroup","rgs","_DashSeparatedReleaseGroup","valueFormatter","atEnd","firstHole","holeCore","rawValue","ignoreWeak","releasegroup","_SceneReleaseGroup","sceneNames","scenePrefixTags","sceneNoPrefixTags","keepOnlyFirstTitle","lastHole","holeGroup","firstGroup","previousMatchFilter","previousMatch","holeValue","ignoredMatches","ignoredMatch","_AnimeReleaseGroup","isGroupEmpty","emptyGroup","_NumericPrefixedGroupRule","numLen","_TrailingTokenAfterEpisodeAsReleaseGroup","streamingService","ValidateStreamingService","_ValidateStreamingService","allServices","service","charAfter","charBefore","suffixPred","prefixPred","suffixMatches","suffixArray","prefixMatches","prefixArray","hasOther","holesToNext","holesToPrev","maxDistance","nextTooFar","prevTooFar","matchesBetweenNext","matchesBetweenPrev","nextHasIntervening","prevHasIntervening","openingEndingCredits","AppendCreditless","AppendOpedEndingCredits","ValidateStereoVRContext","RenameAnotherToOther","ValidateHasNeighbor","ValidateHasNeighborAfter","ValidateHasNeighborBefore","ValidateScreenerRule","ValidateMuxRule","ValidateHardcodedSubs","ValidateStreamingServiceNeighbor","ValidateAtEnd","ValidateReal","RemoveTitleCaseAmbiguous","ImageArtKeywordToOther","ProperCountRule","FixCountRule","ART_KEYWORDS","_ImageArtKeywordToOther","cands","canon","CREDITS_NUMBER","CREDITS_VERSION","CREDITS_SUFFIX","formatCreditsNumber","add","_AppendCreditless","_AppendOpedEndingCredits","STEREO_VR_CONTEXT_TAG","VR_CONTEXT_VALUES","_ValidateStereoVRContext","gated","stereo","TOKEN_START","completeWords","completeMarkerPattern","seasonWordsPattern","completeArticleWordsPattern","seasonNumbersPattern","validateComplete","_ProperCountRule","propers","raws","proper","properCount","properCountMatch","_FixCountRule","fixes","fix","_RenameAnotherToOther","_ValidateHasNeighbor","toCheck","previousGroup","nextGroup","_ValidateHasNeighborBefore","_ValidateHasNeighborAfter","_ValidateScreenerRule","screener","sourceMatch","_ValidateMuxRule","mux","_ValidateHardcodedSubs","_ValidateStreamingServiceNeighbor","initiatorMatch","_ValidateAtEnd","_RemoveTitleCaseAmbiguous","TITLE_WORDS","RELEASE_META","_ValidateReal","size","bitRate","BitRateTypeRule","_BitRateTypeRule","videoBitRateDisabled","onlySepsBetween","noHolesBefore","lc","isKbps","edition","cd","BonusAtFilepartStartRule","BonusToEpisodeRule","BonusTitleRule","_BonusAtFilepartStartRule","bonuses","xStart","_BonusToEpisodeRule","hasSeason","hasEpisode","BOUNDARY_NAMES","_BonusTitleRule","bonusNumber","filepath","titleAfterBonus","containerMatch","maxEnd","btStart","btEnd","yearAfterTitle","gapBefore","gapAfter","onlySesBefore","onlySepsAfter","rawText","bonusTitleValue","allMatchesInRange","bonusTitle","boundaryMatches","endPos","matchesInRange","film","LeadingFilmNumberRule","FilmTitleRule","_LeadingFilmNumberRule","films","filmMatch","_FilmTitleRule","prefixes","DIGIT","LETTER","OTHER","IDNUM_SOURCE","guessIdnumber","regex","uuid","switchCount","switchLetterCount","letterCount","lastLetter","ci","switchRatio","lettersRatio","_config","imdb","volume","MIMETYPE_MAP","mimetype","Mimetype","_Mimetype","ext","len","addType","_TypeProcessor","optionType","absoluteEpisode","episodeDetails","episodeArr","seasonArr","hasYear","hasAbsoluteEpisode","hasEpisodeDetails","yearArr2","firstYearStart","allSeasonsWeak","hasEpisodeRange","allEpisodesWeakNoRange","allSeasonsWeakExtended","iStart","iEnd","noStrongIndicatorsExtended","rgArr","inputStr2","hasAnimeStyleRG","epDetailsArr","yearStart","completeSeries","animeReleaseGroup","complete","typeValue","removeWeak","resp","TypeProcessor","type_","LANG_KEYS","isUndeterminedLang","_EnlargeGroupMatches","EnlargeGroupMatches","preferredString","value1","value2","isTitleCase","countTitleWords","_EquivalentHoles","newMatches","holesLeft","currentMatch","newValue","EquivalentHoles","_RemoveAmbiguous","sortFn","previousFilepartsNames","filepartMatches","filepartNames","vals","oldEpTitles","undMatches","RemoveAmbiguous","sxxExxWeightPredicate","_RemoveLessSpecificSeasonEpisode","markerArr","weights","inRange","RemoveLessSpecificSeasonEpisode","_RemoveLessSpecificSeason","RemoveLessSpecificSeason","_RemoveLessSpecificEpisode","RemoveLessSpecificEpisode","_SeasonYear","SeasonYear","_YearSeason","strongEpisodes","YearSeason","_Processors","_matches","Processors","_StripSeparators","StripSeparators","_RemoveInvalidMatches","RemoveInvalidMatches","processors","rebulkBuilder","cfg","otherRebulk","properties","parseOptions","_api","loadConfig","configurations","defaultOptions","mergeOptions","optionsList","deepCopy","pristine","option","mergeOptionValue","GUESSIT_SCHEMA","_GuessItException","cause","causeMsg","GuessItException","_GuessItApi","rulesBuilder","force","sanitizeOptions","builder","parsedOptions","hasSameConfigProps","advancedConfig","mergedOptions","matchesDict","deduped","id","err","props","rb","def","cur","suggested","guess","GuessItApi","defaultApi","guessit","configure","reset","version","pkgVersion"],"mappings":"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CL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,IAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,IAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,IAAK,IACL,IAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,EAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IA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BACA,eACA,eACA,MACA,SACA,QACA,QACA,OACA,OACA,OACA,OACA,OACA,MACA,MACA,OACA,MACA,QAAA,CACF,EAEF,cAAiB,CACf,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,KACA,KACA,oBACA,KACA,kBACA,eACA,wBACA,KACA,KACA,MACA,KACA,iBACA,KACA,cAAA,CACF,EAEF,MAAS,CACP,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,YAAe,CACb,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,GAAM,CACJ,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,SAAY,CACV,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,YAAe,CACb,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,SACA,SACA,OAAA,CACF,EAEF,UAAa,CACX,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,MACA,MACA,OACA,KACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,OACA,MACA,MACA,KACA,MACA,MACA,OACA,MACA,OACA,MACA,MACA,OACA,MACA,MACA,MACA,MACA,MACA,OACA,OACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,KACA,MACA,KACA,MACA,MACA,KACA,MACA,MACA,MACA,MACA,MACA,UACA,KACA,MACA,MACA,OACA,OACA,MACA,MACA,KAAA,CACF,EAEF,QAAW,CACT,KAAQ,CACN,UAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,MAAS,CACP,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,KAAQ,CACN,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,KAAQ,CACN,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,QAAW,CACT,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,kBACA,KACA,YACA,YACA,YACA,KACA,MACA,SACA,SACA,iBACA,4BACA,WACA,WACA,MACA,WACA,OACA,OACA,UACA,UACA,aACA,WACA,KACA,UACA,aACA,aACA,WACA,aACA,QACA,SAAA,CACF,EAEF,QAAW,CACT,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,cAAiB,CACf,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,gBAAmB,CACjB,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,eAAkB,CAChB,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,UAAA,CACF,EAEF,cAAiB,CACf,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,KAAQ,CACN,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,WAAc,CACZ,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,WAAc,CACZ,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,SAAY,CACV,KAAQ,CACN,UAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,SAAY,CACV,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,2BACA,8BACA,+BACA,kBACA,YACA,aACA,YACA,aACA,aACA,YACA,aACA,mBACA,iBAAA,CACF,EAEF,MAAS,CACP,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,OACA,KACA,cACA,cACA,SACA,QACA,UACA,UACA,YACA,aACA,YACA,UACA,WACA,UACA,YACA,QACA,SACA,WACA,OACA,cACA,OACA,eACA,OACA,aACA,kBACA,SACA,gBACA,SACA,SACA,iBACA,UACA,MACA,MACA,QACA,UACA,kBACA,oBACA,sBACA,KACA,KACA,UACA,QACA,MACA,kBACA,eACA,kBACA,KACA,KACA,SACA,WACA,YACA,KACA,OACA,OACA,aACA,cACA,OACA,iBACA,KACA,MACA,aACA,WACA,MACA,SACA,OACA,MACA,MACA,MACA,aACA,MACA,aACA,0BACA,yBACA,wBACA,yBACA,iBACA,KACA,MACA,aACA,MACA,UACA,SACA,SACA,QACA,WACA,SACA,UACA,KACA,KACA,WACA,OACA,YACA,WACA,WACA,QACA,SACA,SACA,MACA,SACA,YACA,WACA,MACA,QACA,eACA,yBACA,oBACA,MACA,aACA,YACA,UACA,MACA,WACA,WACA,sBACA,MACA,kBACA,OACA,KACA,OACA,kBACA,aACA,KACA,QACA,KAAA,CACF,EAEF,KAAQ,CACN,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,aAAgB,CACd,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,cAAiB,CACf,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,YAAe,CACb,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,QACA,QACA,QACA,WACA,QACA,OACA,OACA,OACA,KACA,OACA,OACA,OACA,UACA,SAAA,CACF,EAEF,OAAU,CACR,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,aAAgB,CACd,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,KAAQ,CACN,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,EAAA,EAEZ,OAAU,CACR,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,cACA,UACA,SACA,iBACA,aACA,MACA,YACA,cACA,cACA,SACA,OACA,YACA,eACA,YACA,WACA,WACA,KACA,mBACA,aACA,MACA,kBACA,MACA,WAAA,CACF,EAEF,kBAAqB,CACnB,KAAQ,CACN,QAAA,EAEF,MAAS,GACT,OAAU,GACV,KAAQ,CACN,MACA,OACA,OACA,MACA,MACA,gBACA,aACA,KACA,OACA,qBACA,OACA,SACA,eACA,OACA,MACA,yBACA,OACA,WACA,gBACA,WACA,OACA,OACA,MACA,UACA,OACA,MACA,KACA,MACA,OACA,OACA,OACA,cACA,QACA,OACA,aACA,MACA,QACA,OACA,OACA,YACA,OACA,UACA,SACA,kBACA,MACA,MACA,KACA,OACA,YACA,OACA,QACA,UACA,OACA,MACA,KACA,OACA,OACA,mCACA,iBACA,2BACA,KACA,UACA,OACA,QACA,OACA,eACA,QACA,OACA,MACA,MACA,kBACA,KACA,MACA,SACA,UACA,cACA,MACA,MACA,kBACA,KACA,MACA,2BACA,OACA,YACA,iBACA,SACA,UACA,MACA,cACA,WACA,OACA,QACA,OACA,aACA,OACA,OACA,OACA,OACA,KACA,WACA,OACA,OACA,OACA,MACA,UACA,OACA,MACA,iBACA,MACA,SACA,YACA,SACA,SACA,UACA,MACA,OACA,eACA,MACA,MACA,cACA,OACA,SACA,KACA,OACA,WACA,OACA,MACA,cACA,OACA,aACA,KACA,OACA,OACA,SACA,gBACA,WACA,MACA,SACA,UACA,OACA,OACA,UACA,OACA,OACA,UACA,UACA,OACA,OACA,KACA,MACA,QACA,MACA,MACA,0BACA,KACA,QACA,KACA,SACA,MACA,OACA,oBACA,OACA,WACA,MACA,SACA,OACA,uBACA,QACA,OACA,MACA,OACA,OACA,iCACA,sBACA,sBACA,MACA,SACA,MACA,UACA,KACA,MACA,MACA,UACA,OACA,iBACA,OACA,UACA,cACA,yBACA,MACA,MACA,gBACA,wBACA,OACA,OACA,MACA,aACA,gBACA,MACA,WACA,OACA,OACA,UACA,sBACA,OACA,QACA,OACA,OACA,OACA,OACA,UACA,MACA,aACA,MACA,OACA,OACA,MACA,UACA,QACA,MACA,MACA,kBACA,QACA,OACA,OACA,MACA,QACA,WACA,OACA,OACA,OACA,OACA,QACA,WACA,OACA,YACA,SACA,OACA,OACA,OACA,QACA,MACA,sBACA,MACA,WACA,OACA,OACA,OACA,MACA,OACA,OACA,SACA,mBACA,MACA,OACA,SACA,UACA,MACA,cACA,MACA,cACA,QACA,MACA,OACA,MACA,iB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","x_google_ignoreList":[0]}