{"version":3,"file":"ipuz-C1G2Yf15.mjs","names":[],"sources":["../src/ipuz.ts"],"sourcesContent":["/**\n * Parser for ipuz crossword format.\n * Based on specification at https://www.puzzazz.com/ipuz\n */\n\nimport { UnsupportedPuzzleTypeError, IpuzParseError } from \"./errors\";\nimport type {\n  Puzzle,\n  Grid,\n  Cell as UnifiedCell,\n  Clues,\n  ParseOptions,\n} from \"./types\";\nimport { ErrorCode } from \"./types\";\nimport { MAX_GRID_WIDTH, MAX_GRID_HEIGHT } from \"./constants\";\n\nfunction parseString(value: unknown): string | undefined {\n  return typeof value === \"string\" ? value : undefined;\n}\n\nfunction parseBoolean(value: unknown): boolean | undefined {\n  return typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction parseRecord(value: unknown): Record<string, unknown> | undefined {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value)\n    ? (value as Record<string, unknown>)\n    : undefined;\n}\n\nfunction parseArray(value: unknown): unknown[] | undefined {\n  return Array.isArray(value) ? value : undefined;\n}\n\nexport enum CellType {\n  NORMAL = \"normal\",\n  BLOCK = \"block\",\n  NULL = \"null\",\n}\n\nexport interface CellStyle {\n  shapebg?: string;\n  highlight?: boolean;\n  named?: boolean;\n  border?: number;\n  divided?: string;\n  label?: string;\n  mark?: Record<string, unknown>;\n  imagebg?: string;\n  color?: string;\n  colortext?: string;\n  colorborder?: string;\n  colorbar?: string;\n  barred?: string;\n  dotted?: string;\n  dashed?: string;\n  lessthan?: string;\n  greaterthan?: string;\n  equal?: string;\n  handler?: string;\n  handlerdata?: unknown;\n}\n\nexport interface IpuzCell {\n  type: CellType;\n  number?: number | string;\n  value?: string;\n  solution?: string;\n  style?: CellStyle;\n  continued?: Record<string, unknown>;\n  directions?: string[];\n  given?: boolean;\n}\n\nexport interface IpuzClue {\n  number: number | string;\n  text: string;\n  cells?: Array<[number, number]>;\n  references?: Array<number | string>;\n  continued?: Record<string, unknown>;\n  highlight?: boolean;\n  image?: string;\n}\n\nexport interface IpuzPuzzle {\n  version: string;\n  kind: string[];\n\n  dimensions: {\n    width: number;\n    height: number;\n  };\n\n  puzzle: IpuzCell[][];\n\n  title?: string;\n  author?: string;\n  copyright?: string;\n  publisher?: string;\n  publication?: string;\n  url?: string;\n  uniqueId?: string;\n  intro?: string;\n  explanation?: string;\n  annotation?: string;\n  notes?: string;\n  difficulty?: string;\n  origin?: string;\n  date?: string;\n\n  empty?: string;\n  charset?: string;\n\n  clues: Record<string, IpuzClue[]>;\n\n  solution?: Array<Array<string | null>>;\n\n  zones?: Array<Record<string, unknown>>;\n\n  styles?: Record<string, unknown>;\n\n  extensions: Record<string, unknown>;\n\n  volatile?: Record<string, boolean>;\n\n  checksum?: string[];\n\n  saved?: Array<Array<string | null>>;\n\n  enumeration?: boolean;\n  enumerations?: string[];\n\n  misses?: Record<string, unknown>;\n\n  block?: string;\n\n  showEnumerations?: boolean;\n  cluePlacement?: string;\n\n  answer?: string;\n  answers?: string[];\n}\n\ninterface IpuzCellData {\n  cell?: unknown;\n  style?: Record<string, unknown>;\n  value?: string;\n  continued?: Record<string, unknown>;\n  directions?: string[];\n  given?: boolean;\n}\n\ninterface IpuzClueData {\n  number?: number | string;\n  clue?: string;\n  cells?: Array<[number, number]>;\n  references?: Array<number | string>;\n  continued?: Record<string, unknown>;\n  highlight?: boolean;\n  image?: string;\n}\n\ninterface IpuzData {\n  version?: string;\n  kind?: string[];\n  dimensions?: {\n    width: number;\n    height: number;\n  };\n  puzzle?: unknown[][];\n  solution?: Array<Array<string | null>>;\n  clues?: Record<string, unknown[]>;\n  saved?: Array<Array<string | null>>;\n  title?: string;\n  author?: string;\n  copyright?: string;\n  publisher?: string;\n  publication?: string;\n  url?: string;\n  uniqueid?: string;\n  intro?: string;\n  explanation?: string;\n  annotation?: string;\n  notes?: string;\n  difficulty?: string;\n  origin?: string;\n  date?: string;\n  empty?: string;\n  charset?: string;\n  block?: string;\n  showenumerations?: boolean;\n  clueplacement?: string;\n  answer?: string;\n  answers?: string[];\n  enumeration?: boolean;\n  enumerations?: string[];\n  volatile?: Record<string, boolean>;\n  checksum?: string[];\n  zones?: Array<Record<string, unknown>>;\n  styles?: Record<string, unknown>;\n  misses?: Record<string, unknown>;\n  [key: string]: unknown;\n}\n\nfunction parseCellFromIpuz(\n  cellData: unknown,\n  solutionData?: unknown,\n): IpuzCell {\n  const cell: IpuzCell = {\n    type: CellType.NORMAL,\n  };\n\n  if (cellData === null || cellData === \"null\") {\n    cell.type = CellType.NULL;\n    return cell;\n  }\n\n  if (cellData === \"#\") {\n    cell.type = CellType.BLOCK;\n    return cell;\n  }\n\n  if (typeof cellData === \"object\" && cellData !== null) {\n    const cellObj = cellData as IpuzCellData;\n\n    if (\"cell\" in cellObj && cellObj.cell !== undefined) {\n      const baseValue = cellObj.cell;\n      if (baseValue === \"#\") {\n        cell.type = CellType.BLOCK;\n      } else if (baseValue === \"null\" || baseValue === null) {\n        cell.type = CellType.NULL;\n      } else if (\n        typeof baseValue === \"number\" ||\n        typeof baseValue === \"string\"\n      ) {\n        if (baseValue !== 0 && baseValue !== \"0\") {\n          cell.number = baseValue;\n        }\n      }\n    }\n\n    if (\n      \"style\" in cellObj &&\n      cellObj.style &&\n      typeof cellObj.style === \"object\"\n    ) {\n      cell.style = {};\n      const styleFields: (keyof CellStyle)[] = [\n        \"shapebg\",\n        \"highlight\",\n        \"named\",\n        \"border\",\n        \"divided\",\n        \"label\",\n        \"mark\",\n        \"imagebg\",\n        \"color\",\n        \"colortext\",\n        \"colorborder\",\n        \"colorbar\",\n        \"barred\",\n        \"dotted\",\n        \"dashed\",\n        \"lessthan\",\n        \"greaterthan\",\n        \"equal\",\n        \"handler\",\n        \"handlerdata\",\n      ];\n\n      for (const field of styleFields) {\n        if (field in cellObj.style) {\n          const value = cellObj.style[field];\n          if (value !== undefined) {\n            (cell.style as Record<string, unknown>)[field] = value;\n          }\n        }\n      }\n    }\n\n    if (\"value\" in cellObj && cellObj.value !== undefined) {\n      cell.value = cellObj.value;\n    }\n\n    if (\"continued\" in cellObj && cellObj.continued !== undefined) {\n      cell.continued = cellObj.continued;\n    }\n\n    if (\"directions\" in cellObj && cellObj.directions !== undefined) {\n      cell.directions = cellObj.directions;\n    }\n\n    if (\"given\" in cellObj && cellObj.given !== undefined) {\n      cell.given = cellObj.given;\n    }\n  } else if (typeof cellData === \"number\" || typeof cellData === \"string\") {\n    if (typeof cellData === \"number\" && cellData > 0) {\n      cell.number = cellData;\n    } else if (typeof cellData === \"string\") {\n      if (cellData === \"0\" || cellData === \"#\" || cellData === \"null\") {\n        // Handle special cases\n        if (cellData === \"#\") {\n          cell.type = CellType.BLOCK;\n        }\n      } else {\n        // Try to parse as number for cell numbering\n        const numVal = Number.parseInt(cellData, 10);\n        if (!Number.isNaN(numVal) && numVal > 0) {\n          cell.number = cellData;\n        } else {\n          // It's a letter/value\n          cell.value = cellData;\n        }\n      }\n    }\n  }\n\n  if (solutionData) {\n    if (\n      typeof solutionData === \"string\" &&\n      solutionData !== \"#\" &&\n      solutionData !== \"null\" &&\n      solutionData !== null\n    ) {\n      cell.solution = solutionData;\n    }\n  }\n\n  return cell;\n}\n\nfunction parseCluesFromIpuz(\n  cluesData: Record<string, unknown[]>,\n): Record<string, IpuzClue[]> {\n  const clues: Record<string, IpuzClue[]> = {};\n\n  for (const [direction, clueList] of Object.entries(cluesData)) {\n    if (!Array.isArray(clueList)) {\n      continue;\n    }\n    clues[direction] = [];\n\n    for (const clueItem of clueList) {\n      let clue: IpuzClue | null = null;\n\n      if (Array.isArray(clueItem) && clueItem.length >= 2) {\n        clue = {\n          number: clueItem[0] as number | string,\n          text: clueItem[1] as string,\n        };\n\n        if (clueItem.length > 2) {\n          for (let i = 2; i < clueItem.length; i++) {\n            const extra = clueItem[i] as unknown;\n            if (typeof extra === \"object\" && extra !== null) {\n              const extraObj = extra as IpuzClueData;\n              if (\"references\" in extraObj && extraObj.references) {\n                clue.references = extraObj.references;\n              }\n              if (\"continued\" in extraObj && extraObj.continued) {\n                clue.continued = extraObj.continued;\n              }\n              if (\"highlight\" in extraObj && extraObj.highlight) {\n                clue.highlight = extraObj.highlight;\n              }\n              if (\"image\" in extraObj && extraObj.image) {\n                clue.image = extraObj.image;\n              }\n            }\n          }\n        }\n      } else if (typeof clueItem === \"object\" && clueItem !== null) {\n        const clueObj = clueItem as IpuzClueData;\n        clue = {\n          number: clueObj.number || \"\",\n          text: clueObj.clue || \"\",\n        };\n\n        if (clueObj.cells) {\n          clue.cells = clueObj.cells;\n        }\n        if (clueObj.references) {\n          clue.references = clueObj.references;\n        }\n        if (clueObj.continued) {\n          clue.continued = clueObj.continued;\n        }\n        if (clueObj.highlight !== undefined) {\n          clue.highlight = clueObj.highlight;\n        }\n        if (clueObj.image) {\n          clue.image = clueObj.image;\n        }\n      }\n\n      if (clue) {\n        clues[direction].push(clue);\n      }\n    }\n  }\n\n  return clues;\n}\n\n/**\n * Parse an iPUZ format crossword puzzle.\n *\n * @param content - The iPUZ data as JSON string or Buffer\n * @param options - Optional parsing options\n * @param options.maxGridSize - Maximum allowed grid dimensions\n * @returns An IpuzPuzzle object containing all puzzle data\n * @throws {IpuzParseError} When the content is not valid iPUZ format\n * @throws {UnsupportedPuzzleTypeError} When the puzzle is not a crossword\n *\n * @example\n * ```typescript\n * import { parseIpuz } from 'xword-parser';\n * const ipuzData = '{\"version\":\"http://ipuz.org/v2\",\"kind\":[\"http://ipuz.org/crossword#1\"]...}';\n * const puzzle = parseIpuz(ipuzData);\n * ```\n */\nexport function parseIpuz(\n  content: string | Buffer,\n  options?: ParseOptions,\n): IpuzPuzzle {\n  const stringContent =\n    typeof content === \"string\" ? content : content.toString(\"utf-8\");\n  let jsonContent = stringContent.trim();\n\n  if (jsonContent.startsWith(\"ipuz(\") && jsonContent.endsWith(\")\")) {\n    jsonContent = jsonContent.slice(5, -1);\n  }\n\n  let data: IpuzData;\n  try {\n    data = JSON.parse(jsonContent) as IpuzData;\n  } catch (e) {\n    throw new IpuzParseError(\n      `Invalid JSON: ${e instanceof Error ? e.message : \"Unknown error\"}`,\n      ErrorCode.IPUZ_INVALID_JSON,\n      undefined,\n      e,\n    );\n  }\n\n  if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n    throw new IpuzParseError(\n      \"Invalid iPUZ data: expected a JSON object\",\n      ErrorCode.IPUZ_INVALID_JSON,\n    );\n  }\n\n  if (\n    !data.kind ||\n    !Array.isArray(data.kind) ||\n    !data.kind.some(\n      (k: unknown) => typeof k === \"string\" && k.includes(\"crossword\"),\n    )\n  ) {\n    throw new UnsupportedPuzzleTypeError(\"Non-crossword\");\n  }\n\n  // Validate required fields for crossword puzzles\n  if (!data.dimensions || typeof data.dimensions !== \"object\") {\n    throw new IpuzParseError(\n      \"Missing or invalid dimensions field\",\n      ErrorCode.IPUZ_MISSING_REQUIRED_FIELD,\n    );\n  }\n\n  if (!data.dimensions.width || !data.dimensions.height) {\n    throw new IpuzParseError(\n      \"Missing width or height in dimensions\",\n      ErrorCode.IPUZ_MISSING_REQUIRED_FIELD,\n    );\n  }\n\n  if (\n    typeof data.dimensions.width !== \"number\" ||\n    typeof data.dimensions.height !== \"number\"\n  ) {\n    throw new IpuzParseError(\n      \"Width and height must be numbers\",\n      ErrorCode.IPUZ_INVALID_DATA_TYPE,\n    );\n  }\n\n  if (\n    !Number.isInteger(data.dimensions.width) ||\n    !Number.isInteger(data.dimensions.height)\n  ) {\n    throw new IpuzParseError(\n      \"Width and height must be integers\",\n      ErrorCode.IPUZ_INVALID_DATA_TYPE,\n    );\n  }\n\n  if (data.dimensions.width <= 0 || data.dimensions.height <= 0) {\n    throw new IpuzParseError(\n      \"Width and height must be positive numbers\",\n      ErrorCode.IPUZ_INVALID_GRID_SIZE,\n    );\n  }\n  const maxWidth = options?.maxGridSize?.width ?? MAX_GRID_WIDTH;\n  const maxHeight = options?.maxGridSize?.height ?? MAX_GRID_HEIGHT;\n\n  if (data.dimensions.width > maxWidth || data.dimensions.height > maxHeight) {\n    throw new IpuzParseError(\n      `Grid dimensions too large: ${data.dimensions.width}x${data.dimensions.height}. Maximum supported size is ${maxWidth}x${maxHeight}`,\n      ErrorCode.IPUZ_INVALID_GRID_SIZE,\n    );\n  }\n\n  if (!data.puzzle || !Array.isArray(data.puzzle)) {\n    throw new IpuzParseError(\n      \"Missing or invalid puzzle grid\",\n      ErrorCode.IPUZ_MISSING_REQUIRED_FIELD,\n    );\n  }\n\n  const puzzle: IpuzPuzzle = {\n    version: parseString(data.version) ?? \"\",\n    kind: data.kind || [],\n    dimensions: data.dimensions,\n    puzzle: [],\n    clues: {},\n    extensions: {},\n  };\n\n  // String metadata fields\n  puzzle.title = parseString(data.title);\n  puzzle.author = parseString(data.author);\n  puzzle.copyright = parseString(data.copyright);\n  puzzle.publisher = parseString(data.publisher);\n  puzzle.publication = parseString(data.publication);\n  puzzle.url = parseString(data.url);\n  puzzle.intro = parseString(data.intro);\n  puzzle.explanation = parseString(data.explanation);\n  puzzle.annotation = parseString(data.annotation);\n  puzzle.notes = parseString(data.notes);\n  puzzle.difficulty = parseString(data.difficulty);\n  puzzle.origin = parseString(data.origin);\n  puzzle.date = parseString(data.date);\n  puzzle.empty = parseString(data.empty);\n  puzzle.charset = parseString(data.charset);\n  puzzle.block = parseString(data.block);\n  puzzle.answer = parseString(data.answer);\n\n  // Fields that need renaming from spec format to camelCase\n  puzzle.uniqueId = parseString(data.uniqueid);\n  puzzle.showEnumerations = parseBoolean(data.showenumerations);\n  puzzle.cluePlacement = parseString(data.clueplacement);\n\n  // Structured fields\n  puzzle.answers = parseRecord(data.answers) as string[] | undefined;\n  puzzle.enumeration = parseBoolean(data.enumeration);\n  puzzle.enumerations = parseRecord(data.enumerations) as string[] | undefined;\n  puzzle.volatile = parseRecord(data.volatile) as\n    | Record<string, boolean>\n    | undefined;\n  puzzle.checksum = parseArray(data.checksum) as string[] | undefined;\n  puzzle.zones = parseArray(data.zones) as\n    | Array<Record<string, unknown>>\n    | undefined;\n  puzzle.styles = parseRecord(data.styles);\n  puzzle.misses = parseRecord(data.misses);\n\n  const solutionGrid = data.solution || [];\n  if (solutionGrid.length > 0) {\n    puzzle.solution = solutionGrid;\n  }\n\n  if (\"saved\" in data && data.saved) {\n    puzzle.saved = data.saved;\n  }\n\n  const puzzleGrid = data.puzzle || [];\n  for (let rowIdx = 0; rowIdx < puzzleGrid.length; rowIdx++) {\n    const row = puzzleGrid[rowIdx];\n    if (!row) continue;\n\n    const cellRow: IpuzCell[] = [];\n\n    for (let colIdx = 0; colIdx < row.length; colIdx++) {\n      const cellData = row[colIdx];\n      let solutionVal = undefined;\n\n      if (\n        solutionGrid.length > rowIdx &&\n        solutionGrid[rowIdx] &&\n        solutionGrid[rowIdx]!.length > colIdx\n      ) {\n        solutionVal = solutionGrid[rowIdx]![colIdx];\n      }\n\n      const cell = parseCellFromIpuz(cellData, solutionVal);\n      cellRow.push(cell);\n    }\n\n    puzzle.puzzle.push(cellRow);\n  }\n\n  if (\"clues\" in data && data.clues) {\n    puzzle.clues = parseCluesFromIpuz(data.clues);\n  }\n\n  for (const [key, value] of Object.entries(data)) {\n    if (\n      key.startsWith(\"http://\") ||\n      key.startsWith(\"https://\") ||\n      key.includes(\":\")\n    ) {\n      puzzle.extensions[key] = value;\n    }\n  }\n\n  return puzzle;\n}\n\n/**\n * Convert an iPUZ puzzle to the unified Puzzle format.\n *\n * @param puzzle - The IpuzPuzzle object to convert\n * @returns A unified Puzzle object\n *\n * @example\n * ```typescript\n * import { parseIpuz, convertIpuzToUnified } from 'xword-parser';\n * const ipuzPuzzle = parseIpuz(ipuzData);\n * const unifiedPuzzle = convertIpuzToUnified(ipuzPuzzle);\n * ```\n */\nexport function convertIpuzToUnified(puzzle: IpuzPuzzle): Puzzle {\n  const grid: Grid = {\n    width: puzzle.dimensions.width,\n    height: puzzle.dimensions.height,\n    cells: [],\n  };\n\n  // Convert grid\n  for (let y = 0; y < puzzle.dimensions.height; y++) {\n    const row: UnifiedCell[] = [];\n    for (let x = 0; x < puzzle.dimensions.width; x++) {\n      const ipuzCell = puzzle.puzzle[y]?.[x];\n      const solutionCell = puzzle.solution?.[y]?.[x];\n\n      // iPUZ cells are already Cell objects from our parser\n      const cellNumber = ipuzCell?.number\n        ? typeof ipuzCell.number === \"string\"\n          ? parseInt(ipuzCell.number)\n          : ipuzCell.number\n        : undefined;\n\n      const isBlack = ipuzCell?.type === CellType.BLOCK;\n\n      const solution =\n        typeof solutionCell === \"string\"\n          ? solutionCell\n          : ipuzCell?.value || undefined;\n\n      const cell: UnifiedCell = {\n        solution,\n        number: cellNumber,\n        isBlack,\n      };\n\n      // Check for circle style (common in iPUZ)\n      if (\n        ipuzCell?.style &&\n        typeof ipuzCell.style === \"object\" &&\n        ipuzCell.style.shapebg === \"circle\"\n      ) {\n        cell.isCircled = true;\n      }\n\n      // Add remaining cell-specific metadata if present\n      if (\n        ipuzCell?.style ||\n        ipuzCell?.continued ||\n        ipuzCell?.directions ||\n        ipuzCell?.given\n      ) {\n        cell.additionalProperties = {};\n        // Only add style if it has more than just shapebg='circle'\n        if (\n          ipuzCell.style &&\n          typeof ipuzCell.style === \"object\" &&\n          (Object.keys(ipuzCell.style).length > 1 ||\n            ipuzCell.style.shapebg !== \"circle\")\n        ) {\n          cell.additionalProperties.style = ipuzCell.style;\n        }\n        if (ipuzCell.continued) {\n          cell.additionalProperties.continued = ipuzCell.continued;\n        }\n        if (ipuzCell.directions) {\n          cell.additionalProperties.directions = ipuzCell.directions;\n        }\n        if (ipuzCell.given !== undefined) {\n          cell.additionalProperties.given = ipuzCell.given;\n        }\n        // Remove additionalProperties if it's empty\n        if (Object.keys(cell.additionalProperties).length === 0) {\n          delete cell.additionalProperties;\n        }\n      }\n\n      row.push(cell);\n    }\n    grid.cells.push(row);\n  }\n\n  // Convert clues\n  const clues: Clues = {\n    across: [],\n    down: [],\n  };\n\n  if (puzzle.clues?.Across) {\n    for (const clue of puzzle.clues.Across) {\n      const clueNumber =\n        typeof clue.number === \"string\" ? parseInt(clue.number) : clue.number;\n      // Skip invalid clue numbers (NaN, 0, negative)\n      if (!Number.isNaN(clueNumber) && clueNumber > 0) {\n        clues.across.push({\n          number: clueNumber,\n          text: clue.text || \"\",\n        });\n      }\n    }\n  }\n\n  if (puzzle.clues?.Down) {\n    for (const clue of puzzle.clues.Down) {\n      const clueNumber =\n        typeof clue.number === \"string\" ? parseInt(clue.number) : clue.number;\n      // Skip invalid clue numbers (NaN, 0, negative)\n      if (!Number.isNaN(clueNumber) && clueNumber > 0) {\n        clues.down.push({\n          number: clueNumber,\n          text: clue.text || \"\",\n        });\n      }\n    }\n  }\n\n  const result: Puzzle = {\n    title: puzzle.title,\n    author: puzzle.author,\n    copyright: puzzle.copyright,\n    notes: puzzle.notes,\n    date: puzzle.date,\n    grid,\n    clues,\n  };\n\n  // Add puzzle-level metadata if present\n  const additionalProps: Record<string, unknown> = {};\n  if (puzzle.difficulty) additionalProps.difficulty = puzzle.difficulty;\n  if (puzzle.publisher) additionalProps.publisher = puzzle.publisher;\n  if (puzzle.publication) additionalProps.publication = puzzle.publication;\n  if (puzzle.url) additionalProps.url = puzzle.url;\n  if (puzzle.uniqueId) additionalProps.uniqueId = puzzle.uniqueId;\n  if (puzzle.intro) additionalProps.intro = puzzle.intro;\n  if (puzzle.explanation) additionalProps.explanation = puzzle.explanation;\n  if (puzzle.annotation) additionalProps.annotation = puzzle.annotation;\n\n  // Add styles if present\n  if (puzzle.styles && Object.keys(puzzle.styles).length > 0) {\n    additionalProps.styles = puzzle.styles;\n  }\n\n  // Add zones if present\n  if (puzzle.zones && puzzle.zones.length > 0) {\n    additionalProps.zones = puzzle.zones;\n  }\n\n  // Add extensions if present\n  if (Object.keys(puzzle.extensions).length > 0) {\n    additionalProps.extensions = puzzle.extensions;\n  }\n\n  if (Object.keys(additionalProps).length > 0) {\n    result.additionalProperties = additionalProps;\n  }\n\n  return result;\n}\n"],"mappings":"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"}