UNPKG

@xwordly/xword-parser

Version:

Fast, type-safe TypeScript library for parsing crossword puzzles (PUZ, iPUZ, JPZ, XD)

1 lines 10.9 kB
{"version":3,"sources":["../src/types.ts","../src/errors.ts"],"names":["ErrorCode"],"mappings":"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","file":"chunk-O732NFC7.mjs","sourcesContent":["// Branded types for improved type safety\nexport type ClueNumber = number & { __brand: 'ClueNumber' };\nexport type GridCoordinate = number & { __brand: 'GridCoordinate' };\nexport type RebusId = number & { __brand: 'RebusId' };\n\n// Helper functions to create branded types\nexport const asClueNumber = (n: number): ClueNumber => n as ClueNumber;\nexport const asGridCoordinate = (n: number): GridCoordinate => n as GridCoordinate;\nexport const asRebusId = (n: number): RebusId => n as RebusId;\n\n// Stricter type for direction\nexport type Direction = 'across' | 'down';\n\nexport interface Puzzle {\n title?: string;\n author?: string;\n copyright?: string;\n notes?: string;\n date?: string;\n grid: Grid;\n clues: Clues;\n rebusTable?: Map<number, string>;\n additionalProperties?: Record<string, unknown>;\n}\n\nexport interface Grid {\n width: number;\n height: number;\n cells: Cell[][];\n additionalProperties?: Record<string, unknown>;\n}\n\nexport interface Cell {\n solution?: string;\n number?: number;\n isBlack: boolean;\n isCircled?: boolean;\n hasRebus?: boolean;\n rebusKey?: number;\n additionalProperties?: Record<string, unknown>;\n}\n\nexport interface Clues {\n across: Clue[];\n down: Clue[];\n additionalProperties?: Record<string, unknown>;\n}\n\nexport interface Clue {\n number: number;\n text: string;\n additionalProperties?: Record<string, unknown>;\n}\n\nexport interface ParseOptions {\n filename?: string;\n encoding?: BufferEncoding;\n maxGridSize?: { width: number; height: number };\n}\n\nexport enum ErrorCode {\n FORMAT_DETECTION_FAILED = 'FORMAT_DETECTION_FAILED',\n INVALID_FILE = 'INVALID_FILE',\n UNSUPPORTED_PUZZLE_TYPE = 'UNSUPPORTED_PUZZLE_TYPE',\n BINARY_PARSE_ERROR = 'BINARY_PARSE_ERROR',\n\n IPUZ_PARSE_ERROR = 'IPUZ_PARSE_ERROR',\n IPUZ_INVALID_JSON = 'IPUZ_INVALID_JSON',\n IPUZ_MISSING_VERSION = 'IPUZ_MISSING_VERSION',\n IPUZ_MISSING_KIND = 'IPUZ_MISSING_KIND',\n IPUZ_MISSING_REQUIRED_FIELD = 'IPUZ_MISSING_REQUIRED_FIELD',\n IPUZ_INVALID_DATA_TYPE = 'IPUZ_INVALID_DATA_TYPE',\n IPUZ_INVALID_GRID_SIZE = 'IPUZ_INVALID_GRID_SIZE',\n\n PUZ_PARSE_ERROR = 'PUZ_PARSE_ERROR',\n PUZ_INVALID_HEADER = 'PUZ_INVALID_HEADER',\n PUZ_INVALID_GRID = 'PUZ_INVALID_GRID',\n PUZ_CHECKSUM_MISMATCH = 'PUZ_CHECKSUM_MISMATCH',\n\n JPZ_PARSE_ERROR = 'JPZ_PARSE_ERROR',\n JPZ_INVALID_XML = 'JPZ_INVALID_XML',\n JPZ_MISSING_GRID = 'JPZ_MISSING_GRID',\n JPZ_INVALID_GRID = 'JPZ_INVALID_GRID',\n\n XD_PARSE_ERROR = 'XD_PARSE_ERROR',\n XD_FORMAT_ERROR = 'XD_FORMAT_ERROR',\n XD_INVALID_GRID = 'XD_INVALID_GRID',\n XD_MISSING_CLUES = 'XD_MISSING_CLUES',\n}\n\nexport interface ErrorContext {\n line?: number;\n column?: number;\n field?: string;\n offset?: number;\n details?: Record<string, unknown>;\n}\n","/**\n * Custom error classes for xword-parser\n */\n\nimport { ErrorCode, ErrorContext } from './types';\n\n/**\n * Base error class for all parsing errors\n */\nexport class ParseError extends Error {\n public readonly code: ErrorCode;\n public readonly context?: ErrorContext;\n\n constructor(\n message: string,\n code: ErrorCode = ErrorCode.FORMAT_DETECTION_FAILED,\n context?: ErrorContext,\n cause?: unknown,\n ) {\n super(message, { cause });\n this.code = code;\n this.context = context;\n }\n\n /**\n * Determines if this error indicates a format mismatch (file is valid but wrong format)\n * vs a real parsing error (file is corrupted or has other issues)\n */\n isFormatMismatch(): boolean {\n return (\n this.code === ErrorCode.UNSUPPORTED_PUZZLE_TYPE ||\n this.code === ErrorCode.FORMAT_DETECTION_FAILED\n );\n }\n}\n\n/**\n * Error thrown when the input format cannot be detected\n */\nexport class FormatDetectionError extends ParseError {\n constructor(\n message: string = 'Unable to detect puzzle format',\n context?: ErrorContext,\n cause?: unknown,\n ) {\n super(message, ErrorCode.FORMAT_DETECTION_FAILED, context, cause);\n }\n}\n\n/**\n * Error thrown when a file is corrupted or invalid\n */\nexport class InvalidFileError extends ParseError {\n constructor(format: string, message: string, context?: ErrorContext, cause?: unknown) {\n super(`Invalid ${format} file: ${message}`, ErrorCode.INVALID_FILE, context, cause);\n }\n}\n\n/**\n * Error thrown when a puzzle type is not supported\n */\nexport class UnsupportedPuzzleTypeError extends ParseError {\n constructor(puzzleType: string, context?: ErrorContext, cause?: unknown) {\n super(\n `${puzzleType} puzzles are not supported`,\n ErrorCode.UNSUPPORTED_PUZZLE_TYPE,\n context,\n cause,\n );\n }\n}\n\n/**\n * Format-specific error classes\n */\nexport class IpuzParseError extends ParseError {\n constructor(\n message: string,\n code: ErrorCode = ErrorCode.IPUZ_PARSE_ERROR,\n context?: ErrorContext,\n cause?: unknown,\n ) {\n super(message, code, context, cause);\n }\n\n override isFormatMismatch(): boolean {\n // IPUZ_INVALID_JSON means it's not valid JSON, so likely not an iPUZ file\n // IPUZ_MISSING_VERSION and IPUZ_MISSING_KIND mean it's JSON but not iPUZ format\n return (\n super.isFormatMismatch() ||\n this.code === ErrorCode.IPUZ_INVALID_JSON ||\n this.code === ErrorCode.IPUZ_MISSING_VERSION ||\n this.code === ErrorCode.IPUZ_MISSING_KIND\n );\n }\n}\n\nexport class PuzParseError extends ParseError {\n constructor(\n message: string,\n code: ErrorCode = ErrorCode.PUZ_PARSE_ERROR,\n context?: ErrorContext,\n cause?: unknown,\n ) {\n super(message, code, context, cause);\n }\n\n override isFormatMismatch(): boolean {\n // PUZ_INVALID_HEADER means the file doesn't appear to be a PUZ file at all\n // PUZ_CHECKSUM_MISMATCH is a real error - the file is corrupted\n return super.isFormatMismatch() || this.code === ErrorCode.PUZ_INVALID_HEADER;\n }\n}\n\nexport class JpzParseError extends ParseError {\n constructor(\n message: string,\n code: ErrorCode = ErrorCode.JPZ_PARSE_ERROR,\n context?: ErrorContext,\n cause?: unknown,\n ) {\n super(message, code, context, cause);\n }\n\n override isFormatMismatch(): boolean {\n // JPZ_INVALID_XML means it's not valid XML, so likely not a JPZ file\n // JPZ_MISSING_GRID could be a corrupted JPZ file, not a format mismatch\n return super.isFormatMismatch() || this.code === ErrorCode.JPZ_INVALID_XML;\n }\n}\n\nexport class XdParseError extends ParseError {\n constructor(\n message: string,\n code: ErrorCode = ErrorCode.XD_PARSE_ERROR,\n context?: ErrorContext,\n cause?: unknown,\n ) {\n super(message, code, context, cause);\n }\n\n override isFormatMismatch(): boolean {\n // XD_FORMAT_ERROR indicates the content doesn't look like XD format\n return super.isFormatMismatch() || this.code === ErrorCode.XD_FORMAT_ERROR;\n }\n}\n\n/**\n * Error thrown when binary data cannot be read or parsed correctly.\n * This is used by the BinaryReader class for low-level binary parsing errors.\n */\nexport class BinaryParseError extends ParseError {\n constructor(message: string, context?: ErrorContext) {\n super(message, ErrorCode.BINARY_PARSE_ERROR, context);\n this.name = 'BinaryParseError';\n }\n}\n"]}