hwp2md 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["data: Uint8Array | ArrayBuffer","CFB","streams: string[][]","records: Record[]","cells: Cell[]","row: number","col: number","colspan: number","rowspan: number","textParts: string[]","cellText: string","cell: Cell","matrix: string[][]","lines: string[]","result: string[]","reader: RecordReader","options: ConvertOptions","tables: string[]","paragraphs: Paragraph[]","XMLParser","idToHref: Record<string, string>","parts: string[]","textParts: string[]","cells: Cell[]","paragraphs: Paragraph[]","tableMds: string[]","lines: string[]","allParagraphs: Paragraph[]","hwp: HWPFile"],"sources":["../src/utils/compression.ts","../src/parser.ts","../src/record.ts","../src/table.ts","../src/paragraph.ts","../src/hwpx_parser.ts","../src/converter.ts","../src/utils/binary.ts"],"sourcesContent":["import { inflateRaw } from \"pako\";\n\n/**\n * Decompress raw deflate data (no zlib header)\n * Equivalent to Python: zlib.decompress(data, -15)\n *\n * HWP files use raw deflate compression without zlib wrapper headers.\n * The windowBits=-15 in Python indicates raw deflate mode.\n *\n * @param data - Compressed data\n * @returns Decompressed data\n */\nexport function decompressRaw(data: Uint8Array): Uint8Array {\n try {\n return inflateRaw(data);\n } catch (error) {\n throw new Error(`Failed to decompress data: ${(error as Error).message}`);\n }\n}\n\n/**\n * Check if data appears to be compressed\n * This is a heuristic check, not foolproof\n */\nexport function looksCompressed(data: Uint8Array): boolean {\n if (data.length < 2) return false;\n\n // Check for common compression headers\n // zlib: 0x78 0x9C, 0x78 0x01, 0x78 0xDA, etc.\n if (data[0] === 0x78) return true;\n\n // Raw deflate doesn't have a header, so this is just a guess\n // Check for low entropy (lots of zeros or repeated patterns)\n let zeros = 0;\n for (let i = 0; i < Math.min(100, data.length); i++) {\n if (data[i] === 0) zeros++;\n }\n\n // If less than 10% zeros in first 100 bytes, might be compressed\n return zeros < 10;\n}\n","/**\n * HWP 5.0 File Parser\n * Parses OLE Compound File format HWP files\n */\n\nimport * as CFB from \"cfb\";\nimport { decompressRaw } from \"./utils/compression\";\nimport type { FileHeader } from \"./types\";\n\n/**\n * HWP File Parser\n * Reads and parses HWP 5.0 files using OLE Compound File format\n */\nexport class HWPFile {\n private cfb: CFB.CFB$Container | null = null;\n private _fileHeader: FileHeader | null = null;\n private _isCompressed: boolean = false;\n\n /**\n * Create HWPFile from raw data\n * @param data - Raw HWP file data\n */\n constructor(private data: Uint8Array | ArrayBuffer) {}\n\n /**\n * Create HWPFile from file path (Node.js only)\n * @param path - Path to HWP file\n */\n static async fromFile(path: string): Promise<HWPFile> {\n const fs = await import(\"node:fs/promises\");\n const data = await fs.readFile(path);\n return new HWPFile(new Uint8Array(data));\n }\n\n /**\n * Create HWPFile from ArrayBuffer\n * @param data - ArrayBuffer data\n */\n static fromArrayBuffer(data: ArrayBuffer): HWPFile {\n return new HWPFile(new Uint8Array(data));\n }\n\n /**\n * Create HWPFile from Uint8Array\n * @param data - Uint8Array data\n */\n static fromUint8Array(data: Uint8Array): HWPFile {\n return new HWPFile(data);\n }\n\n /**\n * Open and parse HWP file\n */\n open(): void {\n const uint8Array =\n this.data instanceof Uint8Array ? this.data : new Uint8Array(this.data);\n\n // Check for HWP 3.0 format (HWP 97, 2002, etc.)\n // HWP 3.0 files start with \"HWP Document File V3.00\"\n if (uint8Array.length >= 30) {\n const signature = new TextDecoder(\"utf-8\")\n .decode(uint8Array.slice(0, 30))\n .replace(/\\0+$/, \"\");\n\n if (signature.startsWith(\"HWP Document File V3\")) {\n throw new Error(\n \"HWP 3.0 format (HWP 97, 2002, etc.) is not supported. \" +\n \"Please use HWP 5.0 or later format. \" +\n \"You can convert HWP 3.0 files to HWP 5.0 format using Hancom Office.\",\n );\n }\n }\n\n try {\n // cfb library works best with Buffer in Node.js\n // Check if Buffer is available (Node.js environment)\n if (typeof Buffer !== \"undefined\") {\n const buffer = Buffer.from(uint8Array);\n this.cfb = CFB.read(buffer, { type: \"buffer\" });\n } else {\n // Browser environment - convert to regular array\n const buffer = Array.from(uint8Array);\n this.cfb = CFB.read(buffer, { type: \"array\" });\n }\n } catch (error) {\n throw new Error(`Failed to parse HWP file: ${(error as Error).message}`);\n }\n\n this._fileHeader = this.parseFileHeader();\n this._isCompressed = this._fileHeader.isCompressed;\n }\n\n /**\n * Close HWP file and release resources\n */\n close(): void {\n this.cfb = null;\n this._fileHeader = null;\n }\n\n /**\n * Get file header information\n */\n get fileHeader(): FileHeader | null {\n return this._fileHeader;\n }\n\n /**\n * Check if file is compressed\n */\n get isCompressed(): boolean {\n return this._isCompressed;\n }\n\n /**\n * Parse FileHeader stream (256 bytes fixed)\n */\n private parseFileHeader(): FileHeader {\n if (!this.cfb) {\n throw new Error(\"HWP file not opened\");\n }\n\n const entry = CFB.find(this.cfb, \"FileHeader\");\n if (!entry) {\n throw new Error(\"FileHeader not found in HWP file\");\n }\n\n const data = entry.content as Uint8Array;\n if (data.length !== 256) {\n throw new Error(`Invalid FileHeader size: ${data.length} (expected 256)`);\n }\n\n // Signature (32 bytes)\n const signatureBytes = data.slice(0, 32);\n const signature = new TextDecoder(\"utf-8\")\n .decode(signatureBytes)\n .replace(/\\0+$/, \"\");\n\n if (!signature.startsWith(\"HWP Document File\")) {\n throw new Error(`Invalid HWP signature: ${signature}`);\n }\n\n // Version (4 bytes at offset 32, little-endian)\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const versionRaw = view.getUint32(32, true);\n const major = (versionRaw >> 24) & 0xff;\n const minor = (versionRaw >> 16) & 0xff;\n const patch = (versionRaw >> 8) & 0xff;\n const rev = versionRaw & 0xff;\n\n // Properties (4 bytes at offset 36)\n const properties = view.getUint32(36, true);\n const isCompressed = Boolean(properties & 0x01);\n const isEncrypted = Boolean(properties & 0x02);\n\n return {\n signature,\n version: `${major}.${minor}.${patch}.${rev}`,\n isCompressed,\n isEncrypted,\n rawProperties: properties,\n };\n }\n\n /**\n * Read and decompress stream\n * @param streamPath - Stream path (e.g., 'DocInfo', 'BodyText/Section0')\n * @returns Decompressed data or null if stream doesn't exist\n */\n readStream(streamPath: string): Uint8Array | null {\n if (!this.cfb) {\n return null;\n }\n\n const entry = CFB.find(this.cfb, streamPath);\n if (!entry) {\n return null;\n }\n\n let data = entry.content as Uint8Array;\n\n // Decompress if needed\n if (this._isCompressed) {\n try {\n data = decompressRaw(data);\n } catch (error) {\n throw new Error(\n `Failed to decompress ${streamPath}: ${(error as Error).message}`,\n );\n }\n }\n\n return data;\n }\n\n /**\n * List all streams in HWP file\n * @returns Array of stream paths\n */\n listStreams(): string[][] {\n if (!this.cfb) {\n return [];\n }\n\n const streams: string[][] = [];\n for (const entry of this.cfb.FileIndex) {\n if (entry.type === 2) {\n // Stream type\n const path = entry.name.split(\"/\").filter((p) => p);\n if (path.length > 0) {\n streams.push(path);\n }\n }\n }\n return streams;\n }\n\n /**\n * Get file information\n */\n getFileInfo(): Record<string, unknown> {\n if (!this._fileHeader) {\n return {};\n }\n\n return {\n signature: this._fileHeader.signature,\n version: this._fileHeader.version,\n compressed: this._isCompressed,\n encrypted: this._fileHeader.isEncrypted,\n streams: this.listStreams(),\n };\n }\n\n /**\n * Get number of sections in BodyText\n */\n getSectionCount(): number {\n if (!this.cfb) {\n return 0;\n }\n\n let count = 0;\n // Try both BodyText/SectionN and SectionN paths\n while (\n CFB.find(this.cfb, `BodyText/Section${count}`) ||\n CFB.find(this.cfb, `Section${count}`)\n ) {\n count++;\n }\n\n return count;\n }\n\n /**\n * Read section data\n * @param sectionIndex - Section index (0-based)\n * @returns Decompressed section data\n */\n readSection(sectionIndex: number): Uint8Array | null {\n // Try BodyText/SectionN first, then SectionN\n let data = this.readStream(`BodyText/Section${sectionIndex}`);\n if (!data) {\n data = this.readStream(`Section${sectionIndex}`);\n }\n return data;\n }\n}\n","/**\n * HWP Record Reader\n * Parses HWP's record-based binary format\n */\n\nimport type { Record } from \"./types\";\n\n// Tag IDs (Document Info)\nexport const HWPTAG_BEGIN = 0x010;\nexport const HWPTAG_DOCUMENT_PROPERTIES = 0x010;\nexport const HWPTAG_ID_MAPPINGS = 0x011;\nexport const HWPTAG_BIN_DATA = 0x012;\nexport const HWPTAG_FACE_NAME = 0x013;\nexport const HWPTAG_BORDER_FILL = 0x014;\nexport const HWPTAG_CHAR_SHAPE = 0x015;\nexport const HWPTAG_TAB_DEF = 0x016;\nexport const HWPTAG_NUMBERING = 0x017;\nexport const HWPTAG_BULLET = 0x018;\nexport const HWPTAG_PARA_SHAPE = 0x019;\nexport const HWPTAG_STYLE = 0x01a;\n\n// Body text tags (HWPTAG_BEGIN + decimal offset)\nexport const HWPTAG_PARA_HEADER = HWPTAG_BEGIN + 50; // 0x042\nexport const HWPTAG_PARA_TEXT = HWPTAG_BEGIN + 51; // 0x043\nexport const HWPTAG_PARA_CHAR_SHAPE = HWPTAG_BEGIN + 52; // 0x044\nexport const HWPTAG_PARA_LINE_SEG = HWPTAG_BEGIN + 53; // 0x045\nexport const HWPTAG_PARA_RANGE_TAG = HWPTAG_BEGIN + 54; // 0x046\nexport const HWPTAG_CTRL_HEADER = HWPTAG_BEGIN + 55; // 0x047\nexport const HWPTAG_LIST_HEADER = HWPTAG_BEGIN + 56; // 0x048\nexport const HWPTAG_PAGE_DEF = HWPTAG_BEGIN + 57; // 0x049\nexport const HWPTAG_FOOTNOTE_SHAPE = HWPTAG_BEGIN + 58; // 0x04a\nexport const HWPTAG_PAGE_BORDER_FILL = HWPTAG_BEGIN + 59; // 0x04b\nexport const HWPTAG_SHAPE_COMPONENT = HWPTAG_BEGIN + 60; // 0x04c\nexport const HWPTAG_TABLE = HWPTAG_BEGIN + 61; // 0x04d\nexport const HWPTAG_SHAPE_COMPONENT_LINE = HWPTAG_BEGIN + 62; // 0x04e\nexport const HWPTAG_CTRL_DATA = HWPTAG_BEGIN + 71; // 0x057\n\n/**\n * HWP Record Reader\n * Reads binary records from HWP stream data\n */\nexport class RecordReader {\n private data: Uint8Array;\n private offset: number = 0;\n\n constructor(data: Uint8Array) {\n this.data = data;\n }\n\n /**\n * Check if there are more records to read\n */\n hasMore(): boolean {\n return this.offset < this.data.length;\n }\n\n /**\n * Read next record\n * @returns Next record, or null if no more records\n */\n readRecord(): Record | null {\n // Check if we have at least 4 bytes for the record header\n if (this.offset + 4 > this.data.length) {\n return null;\n }\n\n // Parse record header (4 bytes)\n const view = new DataView(\n this.data.buffer,\n this.data.byteOffset + this.offset,\n 4,\n );\n const header = view.getUint32(0, true);\n\n const tagId = header & 0x3ff; // Lower 10 bits\n const level = (header >> 10) & 0x3ff; // Middle 10 bits\n let size = (header >> 20) & 0xfff; // Upper 12 bits\n\n // Move past header\n let dataOffset = this.offset + 4;\n\n // Extended size if size == 0xFFF\n if (size === 0xfff) {\n // Check if we have 4 bytes for extended size\n if (dataOffset + 4 > this.data.length) {\n return null;\n }\n const extView = new DataView(\n this.data.buffer,\n this.data.byteOffset + dataOffset,\n 4,\n );\n size = extView.getUint32(0, true);\n dataOffset += 4;\n }\n\n // Check if we have enough data for the record body\n if (dataOffset + size > this.data.length) {\n return null;\n }\n\n // Extract record data\n const recordData = this.data.slice(dataOffset, dataOffset + size);\n\n // Move offset to next record\n this.offset = dataOffset + size;\n\n return { tagId, level, data: recordData, size };\n }\n\n /**\n * Peek at next record header without consuming it\n * @returns Header info with tagId, level, size\n */\n peekRecordHeader(): { tagId: number; level: number; size: number } | null {\n // Check if we have at least 4 bytes for the record header\n if (this.offset + 4 > this.data.length) {\n return null;\n }\n\n // Parse header\n const view = new DataView(\n this.data.buffer,\n this.data.byteOffset + this.offset,\n 4,\n );\n const header = view.getUint32(0, true);\n\n const tagId = header & 0x3ff;\n const level = (header >> 10) & 0x3ff;\n let size = (header >> 20) & 0xfff;\n\n let dataOffset = this.offset + 4;\n\n if (size === 0xfff) {\n // Check if we have 4 bytes for extended size\n if (dataOffset + 4 > this.data.length) {\n return null;\n }\n const extView = new DataView(\n this.data.buffer,\n this.data.byteOffset + dataOffset,\n 4,\n );\n size = extView.getUint32(0, true);\n }\n\n return { tagId, level, size };\n }\n\n /**\n * Read all records (considering hierarchy)\n * @param parentLevel - Stop when reaching this level or below\n * @returns All records at current level\n */\n readAllRecords(parentLevel?: number): Record[] {\n const records: Record[] = [];\n\n while (this.hasMore()) {\n // Peek at next record\n const header = this.peekRecordHeader();\n if (!header) {\n break;\n }\n\n // Check if we should stop (returned to parent level)\n if (parentLevel !== undefined && header.level <= parentLevel) {\n break;\n }\n\n // Read record\n const record = this.readRecord();\n if (record) {\n records.push(record);\n }\n }\n\n return records;\n }\n\n /**\n * Get current position\n */\n get position(): number {\n return this.offset;\n }\n\n /**\n * Get remaining bytes\n */\n get remaining(): number {\n return this.data.length - this.offset;\n }\n}\n","/**\n * HWP Table Parser\n * Parses table records and converts to Markdown\n */\n\nimport {\n RecordReader,\n HWPTAG_LIST_HEADER,\n HWPTAG_PARA_HEADER,\n HWPTAG_PARA_TEXT,\n} from \"./record\";\nimport { parseParaText, processControlChars } from \"./paragraph\";\nimport type { Table, Cell, MergeStrategy } from \"./types\";\n\n/**\n * Parse table properties from TABLE record data\n * @param data - TABLE record data\n * @returns Table properties with rows, cols\n */\nexport function parseTableProperties(data: Uint8Array): {\n properties: number;\n rows: number;\n cols: number;\n} {\n if (data.length < 8) {\n throw new Error(`Invalid TABLE record size: ${data.length}`);\n }\n\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n // Properties flag (4 bytes)\n const properties = view.getUint32(0, true);\n\n // Row count (2 bytes)\n const rows = view.getUint16(4, true);\n\n // Column count (2 bytes)\n const cols = view.getUint16(6, true);\n\n return { properties, rows, cols };\n}\n\n/**\n * Parse cell properties\n * @param data - Cell property data\n * @returns Cell properties\n */\nexport function parseCellProperties(data: Uint8Array): {\n col: number;\n row: number;\n colspan: number;\n rowspan: number;\n} {\n if (data.length < 8) {\n return {\n col: 0,\n row: 0,\n colspan: 1,\n rowspan: 1,\n };\n }\n\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n // Column address (2 bytes)\n const col = view.getUint16(0, true);\n\n // Row address (2 bytes)\n const row = view.getUint16(2, true);\n\n // Column span (2 bytes)\n const colspan = view.getUint16(4, true);\n\n // Row span (2 bytes)\n const rowspan = view.getUint16(6, true);\n\n return { col, row, colspan, rowspan };\n}\n\n/**\n * Parse table from TABLE record and subsequent records\n * @param tableRecordData - TABLE record data\n * @param reader - Record reader for reading cell data\n * @param lineBreakStyle - How to handle line breaks in cells\n * @returns Parsed table\n */\nexport function parseTable(\n tableRecordData: Uint8Array,\n reader: RecordReader,\n lineBreakStyle: \"space\" | \"br\" = \"space\",\n): Table {\n // Parse table properties\n const props = parseTableProperties(tableRecordData);\n const rows = props.rows;\n const cols = props.cols;\n\n const cells: Cell[] = [];\n let cellIndex = 0;\n\n // Read cells from LIST_HEADER records\n while (reader.hasMore() && cellIndex < rows * cols) {\n const header = reader.peekRecordHeader();\n if (!header) {\n break;\n }\n\n // Stop if we're back to level 0 or 1 (end of table)\n if (header.level < 2) {\n break;\n }\n\n // Read LIST_HEADER (cell start)\n if (header.tagId === HWPTAG_LIST_HEADER) {\n const listRecord = reader.readRecord();\n if (!listRecord) {\n break;\n }\n\n // Parse cell properties from LIST_HEADER (offset 8)\n let row: number, col: number, colspan: number, rowspan: number;\n\n if (listRecord.data.length >= 16) {\n const view = new DataView(\n listRecord.data.buffer,\n listRecord.data.byteOffset,\n listRecord.data.byteLength,\n );\n col = view.getUint16(8, true);\n row = view.getUint16(10, true);\n colspan = view.getUint16(12, true);\n rowspan = view.getUint16(14, true);\n\n // Fix colspan/rowspan (0 means 1)\n if (colspan === 0) colspan = 1;\n if (rowspan === 0) rowspan = 1;\n } else {\n // Fallback: use index\n row = Math.floor(cellIndex / cols);\n col = cellIndex % cols;\n colspan = 1;\n rowspan = 1;\n }\n\n // Read cell text from paragraphs\n const textParts: string[] = [];\n\n while (reader.hasMore()) {\n const paraHeader = reader.peekRecordHeader();\n if (!paraHeader) {\n break;\n }\n\n // Stop at next cell or end of table\n if (paraHeader.tagId === HWPTAG_LIST_HEADER) {\n break;\n }\n if (paraHeader.level < 2) {\n break;\n }\n\n // Read paragraph\n if (paraHeader.tagId === HWPTAG_PARA_HEADER) {\n const paraRec = reader.readRecord();\n if (!paraRec) {\n break;\n }\n\n // Parse paragraph header\n if (paraRec.data.length >= 4) {\n const view = new DataView(\n paraRec.data.buffer,\n paraRec.data.byteOffset,\n paraRec.data.byteLength,\n );\n const nchars = view.getUint32(0, true) & 0x7fffffff;\n\n // Read text if present\n if (nchars > 0 && reader.hasMore()) {\n const nextH = reader.peekRecordHeader();\n if (nextH && nextH.tagId === HWPTAG_PARA_TEXT) {\n const textRec = reader.readRecord();\n if (textRec) {\n // Use parseParaText to handle control chars properly\n const rawText = parseParaText(textRec.data, nchars);\n const processed = processControlChars(rawText);\n const text = processed.text;\n\n if (text.trim()) {\n textParts.push(text.trim());\n }\n }\n }\n }\n }\n } else {\n // Skip other records in cell\n reader.readRecord();\n }\n }\n\n // Create cell: handle line breaks based on style\n let cellText: string;\n if (lineBreakStyle === \"br\") {\n // Human-readable: use <br> for visual line breaks\n cellText = textParts.join(\"<br>\");\n cellText = cellText.replace(/\\n/g, \"<br>\");\n } else {\n // LLM-optimized (default): use space for clean text\n cellText = textParts.join(\" \");\n cellText = cellText.replace(/\\n/g, \" \");\n }\n\n const cell: Cell = { row, col, rowspan, colspan, text: cellText };\n cells.push(cell);\n cellIndex++;\n } else {\n // Skip non-LIST_HEADER records\n reader.readRecord();\n }\n }\n\n return { rows, cols, cells };\n}\n\n/**\n * Convert table to Markdown\n * @param table - Table object\n * @param mergeStrategy - 'repeat' (default) or 'blank'\n * @returns Markdown table\n */\nexport function tableToMarkdown(\n table: Table,\n mergeStrategy: MergeStrategy = \"repeat\",\n): string {\n const { rows, cols, cells } = table;\n\n // Create matrix\n const matrix: string[][] = Array.from({ length: rows }, () =>\n Array(cols).fill(\"\"),\n );\n\n // Fill matrix with cell data\n for (const cell of cells) {\n if (mergeStrategy === \"repeat\") {\n // Repeat content in all merged cells\n for (let r = cell.row; r < cell.row + cell.rowspan; r++) {\n for (let c = cell.col; c < cell.col + cell.colspan; c++) {\n if (r < rows && c < cols) {\n matrix[r][c] = cell.text;\n }\n }\n }\n } else {\n // Only fill first cell\n if (cell.row < rows && cell.col < cols) {\n matrix[cell.row][cell.col] = cell.text;\n }\n }\n }\n\n // Generate Markdown table\n const lines: string[] = [];\n\n if (rows === 0 || cols === 0) {\n return \"[Empty Table]\";\n }\n\n // Empty header row (Korean docs often use tables for layout, not data)\n lines.push(\"| \" + Array(cols).fill(\"\").join(\" | \") + \" |\");\n lines.push(\"| \" + Array(cols).fill(\"---\").join(\" | \") + \" |\");\n\n // All rows as body (including original first row)\n for (const row of matrix) {\n lines.push(\"| \" + row.join(\" | \") + \" |\");\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * HWP Paragraph Parser\n * Parses paragraph records and extracts text\n */\n\nimport {\n RecordReader,\n HWPTAG_PARA_HEADER,\n HWPTAG_PARA_TEXT,\n HWPTAG_CTRL_HEADER,\n HWPTAG_TABLE,\n} from \"./record\";\nimport type { Paragraph, ParagraphHeader, ConvertOptions } from \"./types\";\nimport { parseTable, tableToMarkdown } from \"./table\";\n\n/**\n * Parse paragraph header\n * @param data - PARA_HEADER record data\n * @returns Paragraph header information\n */\nexport function parseParaHeader(data: Uint8Array): ParagraphHeader {\n if (data.length < 22) {\n throw new Error(`Invalid PARA_HEADER size: ${data.length}`);\n }\n\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\n // Number of characters (nchars)\n const ncharsRaw = view.getUint32(0, true);\n const textCount = ncharsRaw & 0x7fffffff; // Remove sign bit if present\n\n // Control mask\n const controlMask = view.getUint32(4, true);\n\n // Para shape ID\n const paraShapeId = view.getUint16(8, true);\n\n // Style ID\n const styleId = view.getUint8(10);\n\n // Column type\n const columnType = view.getUint8(11);\n\n // Char shape count\n const charShapeCount = view.getUint16(12, true);\n\n return {\n textCount,\n controlMask,\n paraShapeId,\n styleId,\n columnType,\n charShapeCount,\n };\n}\n\n/**\n * Parse paragraph text with control info table\n *\n * PARA_TEXT structure:\n * [Control info table: 16 bytes per control] + [Actual text]\n *\n * Each control info block (16 bytes):\n * - 2 bytes: control code\n * - 4 bytes: control ID\n * - 8 bytes: control data\n * - 2 bytes: control code (repeated)\n *\n * @param data - PARA_TEXT record data\n * @param nchars - Number of WCHAR characters (control table + text)\n * @returns Decoded text\n */\nexport function parseParaText(data: Uint8Array, _nchars: number): string {\n // Control character types WITHOUT additional data in control table\n const CHAR_CONTROLS = new Set([0x00, 0x0a, 0x0d, 0x1e, 0x1f]);\n\n let offset = 0;\n\n // Phase 1: Skip control info table\n // Control info blocks always start with control code (< 32)\n // Actual text starts with regular character (>= 32)\n while (offset + 2 <= data.length) {\n const view = new DataView(data.buffer, data.byteOffset + offset, 2);\n const charCode = view.getUint16(0, true);\n\n if (charCode < 32 && !CHAR_CONTROLS.has(charCode)) {\n // This is a control info block (16 bytes)\n offset += 16;\n if (offset > data.length) {\n break;\n }\n } else {\n // Found start of actual text\n break;\n }\n }\n\n // Phase 2: Parse actual text\n const textData = data.slice(offset);\n\n if (textData.length === 0) {\n return \"\";\n }\n\n // Decode UTF-16LE (handles surrogate pairs correctly)\n try {\n const decoder = new TextDecoder(\"utf-16le\");\n return decoder.decode(textData);\n } catch (error) {\n // Fallback: return empty string\n return \"\";\n }\n}\n\n/**\n * Process control characters in text\n * @param text - Raw text with control characters\n * @returns Processed text and has_table flag\n */\nexport function processControlChars(text: string): {\n text: string;\n hasTable: boolean;\n} {\n const result: string[] = [];\n let hasTable = false;\n\n for (const char of text) {\n const code = char.codePointAt(0) ?? 0;\n\n if (code < 32) {\n // Control character\n if (code === 10) {\n // 0x0A: line break\n result.push(\"\\n\");\n } else if (code === 11) {\n // 0x0B: table/object marker\n // Tables are handled by CTRL_HEADER records, not text markers\n // Just skip this control character\n hasTable = true;\n } else if (code === 13) {\n // 0x0D: para break\n result.push(\"\\n\");\n }\n // Ignore other control chars\n } else {\n result.push(char);\n }\n }\n\n return { text: result.join(\"\"), hasTable };\n}\n\n/**\n * Paragraph Parser\n * Parses paragraphs from HWP record stream\n */\nexport class ParagraphParser {\n constructor(\n private reader: RecordReader,\n private options: ConvertOptions = {},\n ) {\n // Default table line break style\n if (!this.options.tableLineBreakStyle) {\n this.options.tableLineBreakStyle = \"space\";\n }\n }\n\n /**\n * Parse next paragraph\n * @returns Parsed paragraph, or null if no more paragraphs\n */\n parseParagraph(): Paragraph | null {\n if (!this.reader.hasMore()) {\n return null;\n }\n\n // Find PARA_HEADER\n let record = null;\n while (this.reader.hasMore()) {\n record = this.reader.readRecord();\n if (record && record.tagId === HWPTAG_PARA_HEADER) {\n break;\n }\n record = null;\n }\n\n if (!record) {\n return null;\n }\n\n const header = parseParaHeader(record.data);\n\n // Read PARA_TEXT if present\n let text = \"\";\n\n if (header.textCount > 0) {\n // Peek to see if next is PARA_TEXT\n const nextHeader = this.reader.peekRecordHeader();\n if (nextHeader && nextHeader.tagId === HWPTAG_PARA_TEXT) {\n record = this.reader.readRecord();\n if (record) {\n const rawText = parseParaText(record.data, header.textCount);\n const processed = processControlChars(rawText);\n text = processed.text;\n // hasTable flag from processed.hasTable is not used currently\n }\n }\n }\n\n // Process control records (tables, etc.)\n const tables: string[] = [];\n while (this.reader.hasMore()) {\n const nextHeader = this.reader.peekRecordHeader();\n if (!nextHeader) {\n break;\n }\n\n // Stop if we hit next paragraph or lower level\n if (nextHeader.tagId === HWPTAG_PARA_HEADER) {\n break;\n }\n if (nextHeader.level === 0) {\n break;\n }\n\n // Check for table (CTRL_HEADER followed by TABLE)\n if (nextHeader.tagId === HWPTAG_CTRL_HEADER) {\n this.reader.readRecord(); // Skip CTRL_HEADER\n\n // Check for TABLE\n const tableHeader = this.reader.peekRecordHeader();\n if (tableHeader && tableHeader.tagId === HWPTAG_TABLE) {\n const tableRecord = this.reader.readRecord();\n if (tableRecord) {\n try {\n const table = parseTable(\n tableRecord.data,\n this.reader,\n this.options.tableLineBreakStyle,\n );\n const tableMd = tableToMarkdown(table);\n tables.push(tableMd);\n } catch (error) {\n console.warn(\"Warning: Failed to parse table:\", error);\n tables.push(\"[TABLE - Parse Error]\");\n }\n }\n } else {\n // Other control types, skip for now\n }\n } else {\n // Skip other records (char shapes, line segments, etc.)\n this.reader.readRecord();\n }\n }\n\n // Append tables after paragraph text\n if (tables.length > 0) {\n // Add tables as separate blocks after the text\n text = text.trimEnd();\n\n // Check if text is just garbled control characters (short, all non-ASCII)\n // If so, skip the text and just use the table\n const isGarbled =\n text.length > 0 &&\n text.length < 5 &&\n [...text].every((c) => {\n const code = c.codePointAt(0) ?? 0;\n return code > 127 || /\\s/.test(c);\n });\n\n if (isGarbled) {\n // Skip garbled text, just use tables\n text = tables.join(\"\\n\\n\");\n } else {\n // Include both text and tables\n if (text) {\n text += \"\\n\\n\";\n }\n text += tables.join(\"\\n\\n\");\n }\n }\n\n return { text, header };\n }\n\n /**\n * Parse all paragraphs in section\n * @returns All paragraphs\n */\n parseAllParagraphs(): Paragraph[] {\n const paragraphs: Paragraph[] = [];\n\n while (this.reader.hasMore()) {\n const para = this.parseParagraph();\n if (para) {\n paragraphs.push(para);\n } else {\n break;\n }\n }\n\n return paragraphs;\n }\n}\n","/**\n * HWPX (ZIP+XML) File Parser\n * Parses HWPX files (ZIP archives containing XML) into Paragraphs and Tables\n */\n\nimport { unzipSync } from \"fflate\";\nimport { XMLParser } from \"fast-xml-parser\";\nimport { tableToMarkdown } from \"./table\";\nimport type { Paragraph, Table, Cell, ConvertOptions } from \"./types\";\n\nconst HWPX_MIMETYPE = \"application/hwp+zip\";\n\n/** Options for the XML parser */\nconst xmlParserOptions = {\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n // Preserve namespace prefixes in tag names\n removeNSPrefix: false,\n isArray: (name: string) => {\n // These elements should always be arrays for consistent handling\n return [\n \"hp:p\",\n \"hp:run\",\n \"hp:t\",\n \"hp:tr\",\n \"hp:tc\",\n \"hp:tbl\",\n \"opf:item\",\n \"opf:itemref\",\n ].includes(name);\n },\n textNodeName: \"#text\",\n};\n\ninterface ZipEntries {\n [path: string]: Uint8Array;\n}\n\n/**\n * HWPX file parser\n */\nexport class HWPXFile {\n private data: Uint8Array;\n private entries: ZipEntries | null = null;\n private sectionPaths: string[] = [];\n private version = \"\";\n private xmlParser: XMLParser;\n\n constructor(data: Uint8Array) {\n this.data = data;\n this.xmlParser = new XMLParser(xmlParserOptions);\n }\n\n static async fromFile(path: string): Promise<HWPXFile> {\n const { readFileSync } = await import(\"node:fs\");\n const data = readFileSync(path);\n return new HWPXFile(new Uint8Array(data));\n }\n\n static fromArrayBuffer(data: ArrayBuffer): HWPXFile {\n return new HWPXFile(new Uint8Array(data));\n }\n\n static fromUint8Array(data: Uint8Array): HWPXFile {\n return new HWPXFile(data);\n }\n\n open(): void {\n // Check ZIP magic bytes\n if (\n this.data.length < 4 ||\n this.data[0] !== 0x50 ||\n this.data[1] !== 0x4b ||\n this.data[2] !== 0x03 ||\n this.data[3] !== 0x04\n ) {\n throw new Error(\"Not a valid HWPX file (not a ZIP archive)\");\n }\n\n // Extract ZIP\n try {\n this.entries = unzipSync(this.data) as ZipEntries;\n } catch (e) {\n throw new Error(\n `Failed to parse HWPX file: ${e instanceof Error ? e.message : e}`,\n );\n }\n\n // Validate mimetype\n const mimetypeEntry = this.entries[\"mimetype\"];\n if (!mimetypeEntry) {\n throw new Error(\"Not a valid HWPX file: missing 'mimetype' entry\");\n }\n const mimetype = new TextDecoder().decode(mimetypeEntry).trim();\n if (mimetype !== HWPX_MIMETYPE) {\n throw new Error(\n `Invalid HWPX mimetype: '${mimetype}' (expected '${HWPX_MIMETYPE}')`,\n );\n }\n\n // Parse version\n this.parseVersion();\n\n // Discover sections\n this.discoverSections();\n }\n\n close(): void {\n this.entries = null;\n this.sectionPaths = [];\n }\n\n private parseVersion(): void {\n const versionEntry = this.entries?.[\"version.xml\"];\n if (!versionEntry) {\n this.version = \"unknown\";\n return;\n }\n\n try {\n const xml = new TextDecoder().decode(versionEntry);\n const parsed = this.xmlParser.parse(xml);\n // Navigate to the version element (may be nested)\n const root =\n parsed[\"hv:HCFVersion\"] ?? parsed[\"HCFVersion\"] ?? parsed;\n const major = root[\"@_major\"] ?? \"\";\n const minor = root[\"@_minor\"] ?? \"\";\n const micro = root[\"@_micro\"] ?? \"\";\n if (major) {\n this.version = `${major}.${minor}.${micro}`;\n } else {\n this.version = root[\"@_Version\"] ?? \"unknown\";\n }\n } catch {\n this.version = \"unknown\";\n }\n }\n\n private discoverSections(): void {\n this.sectionPaths = [];\n\n const hpfEntry = this.entries?.[\"Contents/content.hpf\"];\n if (!hpfEntry) {\n // Fallback: scan for section files\n for (const name of Object.keys(this.entries ?? {})) {\n if (name.startsWith(\"Contents/section\") && name.endsWith(\".xml\")) {\n this.sectionPaths.push(name);\n }\n }\n this.sectionPaths.sort();\n return;\n }\n\n try {\n const xml = new TextDecoder().decode(hpfEntry);\n const parsed = this.xmlParser.parse(xml);\n\n const pkg =\n parsed[\"opf:package\"] ?? parsed[\"package\"] ?? {};\n const manifest = pkg[\"opf:manifest\"] ?? pkg[\"manifest\"] ?? {};\n const spine = pkg[\"opf:spine\"] ?? pkg[\"spine\"] ?? {};\n\n // Build id→href map\n const idToHref: Record<string, string> = {};\n const items = manifest[\"opf:item\"] ?? manifest[\"item\"] ?? [];\n const itemList = Array.isArray(items) ? items : [items];\n for (const item of itemList) {\n const id = item[\"@_id\"] ?? \"\";\n const href = item[\"@_href\"] ?? \"\";\n if (href) {\n idToHref[id] = href;\n }\n }\n\n // Get sections from spine\n const itemrefs = spine[\"opf:itemref\"] ?? spine[\"itemref\"] ?? [];\n const refList = Array.isArray(itemrefs) ? itemrefs : [itemrefs];\n for (const ref of refList) {\n const idref = ref[\"@_idref\"] ?? \"\";\n if (idref in idToHref && idref.toLowerCase().includes(\"section\")) {\n let href = idToHref[idref];\n if (!href.startsWith(\"Contents/\")) {\n href = \"Contents/\" + href;\n }\n this.sectionPaths.push(href);\n }\n }\n\n // Fallback if spine yielded nothing\n if (this.sectionPaths.length === 0) {\n for (const [, href] of Object.entries(idToHref).sort()) {\n if (href.toLowerCase().includes(\"section\")) {\n const fullHref = href.startsWith(\"Contents/\")\n ? href\n : \"Contents/\" + href;\n this.sectionPaths.push(fullHref);\n }\n }\n }\n } catch {\n // Parse error: fallback\n for (const name of Object.keys(this.entries ?? {})) {\n if (name.startsWith(\"Contents/section\") && name.endsWith(\".xml\")) {\n this.sectionPaths.push(name);\n }\n }\n this.sectionPaths.sort();\n }\n }\n\n get fileInfo(): Record<string, unknown> {\n this.ensureOpen();\n return {\n format: \"HWPX\",\n version: this.version,\n sectionCount: this.sectionPaths.length,\n contents: Object.keys(this.entries ?? {}),\n };\n }\n\n getSectionCount(): number {\n this.ensureOpen();\n return this.sectionPaths.length;\n }\n\n getSectionXml(index: number): unknown {\n this.ensureOpen();\n if (index < 0 || index >= this.sectionPaths.length) {\n throw new RangeError(\n `Section index ${index} out of range (0-${this.sectionPaths.length - 1})`,\n );\n }\n const path = this.sectionPaths[index];\n const entry = this.entries?.[path];\n if (!entry) {\n throw new Error(`Section file not found: ${path}`);\n }\n const xml = new TextDecoder().decode(entry);\n return this.xmlParser.parse(xml);\n }\n\n listContents(): string[] {\n this.ensureOpen();\n return Object.keys(this.entries ?? {});\n }\n\n private ensureOpen(): void {\n if (!this.entries) {\n throw new Error(\"HWPX file is not open. Call open() first.\");\n }\n }\n}\n\n// ── XML traversal helpers ────────────────────────────────────\n\nfunction ensureArray<T>(val: T | T[] | undefined): T[] {\n if (val === undefined || val === null) return [];\n return Array.isArray(val) ? val : [val];\n}\n\n/**\n * Extract text from a paragraph object (hp:p)\n */\nfunction extractParagraphText(pObj: Record<string, unknown>): string {\n const parts: string[] = [];\n\n for (const run of ensureArray(pObj[\"hp:run\"] as Record<string, unknown>[])) {\n // Iterate over keys to find text and special elements\n for (const [key, value] of Object.entries(run)) {\n if (key === \"hp:t\") {\n for (const t of ensureArray(value as (string | Record<string, unknown>)[])) {\n const text = typeof t === \"string\" ? t : (t as Record<string, unknown>)?.[\"#text\"];\n if (text !== undefined && text !== null) {\n parts.push(String(text));\n }\n }\n } else if (key === \"hp:lineBreak\") {\n parts.push(\"\\n\");\n } else if (key === \"hp:tab\") {\n parts.push(\"\\t\");\n }\n }\n }\n\n return parts.join(\"\");\n}\n\n/**\n * Extract text from a table cell (hp:tc)\n */\nfunction extractCellText(\n tcObj: Record<string, unknown>,\n lineBreakStyle: string = \"space\",\n): string {\n const textParts: string[] = [];\n\n const subList = tcObj[\"hp:subList\"] as Record<string, unknown> | undefined;\n if (subList) {\n for (const p of ensureArray(subList[\"hp:p\"] as Record<string, unknown>[])) {\n const paraText = extractParagraphText(p);\n if (paraText.trim()) {\n textParts.push(paraText.trim());\n }\n }\n }\n\n if (lineBreakStyle === \"br\") {\n return textParts.join(\"<br>\").replace(/\\n/g, \"<br>\");\n }\n return textParts.join(\" \").replace(/\\n/g, \" \");\n}\n\n/**\n * Parse a table XML object (hp:tbl) into a Table\n */\nexport function parseHwpxTable(\n tblObj: Record<string, unknown>,\n lineBreakStyle: string = \"space\",\n): Table {\n const rows = Number(tblObj[\"@_rowCnt\"] ?? 0);\n const cols = Number(tblObj[\"@_colCnt\"] ?? 0);\n\n const cells: Cell[] = [];\n\n for (const tr of ensureArray(tblObj[\"hp:tr\"] as Record<string, unknown>[])) {\n for (const tc of ensureArray(tr[\"hp:tc\"] as Record<string, unknown>[])) {\n // Cell address\n const addr = tc[\"hp:cellAddr\"] as Record<string, unknown> | undefined;\n const col = Number(addr?.[\"@_colAddr\"] ?? 0);\n const row = Number(addr?.[\"@_rowAddr\"] ?? 0);\n\n // Cell span\n const span = tc[\"hp:cellSpan\"] as Record<string, unknown> | undefined;\n let colspan = Number(span?.[\"@_colSpan\"] ?? 1);\n let rowspan = Number(span?.[\"@_rowSpan\"] ?? 1);\n if (colspan < 1) colspan = 1;\n if (rowspan < 1) rowspan = 1;\n\n // Cell text\n const text = extractCellText(tc, lineBreakStyle);\n\n cells.push({ row, col, rowspan, colspan, text });\n }\n }\n\n return { rows, cols, cells };\n}\n\n/**\n * Parse a section XML object into paragraphs\n */\nexport function parseHwpxSection(\n sectionObj: Record<string, unknown>,\n options: ConvertOptions = {},\n): Paragraph[] {\n const lineBreakStyle = options.tableLineBreakStyle ?? \"space\";\n const paragraphs: Paragraph[] = [];\n\n // Find the sec element\n let sec = sectionObj as Record<string, unknown>;\n if (sec[\"hs:sec\"]) {\n sec = sec[\"hs:sec\"] as Record<string, unknown>;\n }\n\n // Process paragraphs\n for (const p of ensureArray(sec[\"hp:p\"] as Record<string, unknown>[])) {\n let text = extractParagraphText(p);\n\n // Check for tables within runs\n const tableMds: string[] = [];\n for (const run of ensureArray(p[\"hp:run\"] as Record<string, unknown>[])) {\n for (const tbl of ensureArray(run[\"hp:tbl\"] as Record<string, unknown>[])) {\n try {\n const table = parseHwpxTable(tbl, lineBreakStyle);\n tableMds.push(tableToMarkdown(table));\n } catch {\n tableMds.push(\"[TABLE - Parse Error]\");\n }\n }\n }\n\n // Check for direct table children\n for (const tbl of ensureArray(p[\"hp:tbl\"] as Record<string, unknown>[])) {\n try {\n const table = parseHwpxTable(tbl, lineBreakStyle);\n tableMds.push(tableToMarkdown(table));\n } catch {\n tableMds.push(\"[TABLE - Parse Error]\");\n }\n }\n\n if (tableMds.length > 0) {\n text = text.trimEnd();\n if (text) text += \"\\n\\n\";\n text += tableMds.join(\"\\n\\n\");\n }\n\n if (text.trim()) {\n paragraphs.push({\n text,\n header: {\n textCount: 0,\n controlMask: 0,\n paraShapeId: 0,\n styleId: 0,\n columnType: 0,\n charShapeCount: 0,\n },\n });\n }\n }\n\n // Check for standalone tables (direct children of sec)\n for (const tbl of ensureArray(sec[\"hp:tbl\"] as Record<string, unknown>[])) {\n try {\n const table = parseHwpxTable(tbl, lineBreakStyle);\n const md = tableToMarkdown(table);\n if (md.trim()) {\n paragraphs.push({\n text: md,\n header: {\n textCount: 0,\n controlMask: 0,\n paraShapeId: 0,\n styleId: 0,\n columnType: 0,\n charShapeCount: 0,\n },\n });\n }\n } catch {\n // Skip malformed tables\n }\n }\n\n return paragraphs;\n}\n\n/**\n * Check if binary data is a HWPX file (ZIP magic bytes)\n */\nexport function isHwpxData(data: Uint8Array | ArrayBuffer): boolean {\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n return (\n bytes.length >= 4 &&\n bytes[0] === 0x50 &&\n bytes[1] === 0x4b &&\n bytes[2] === 0x03 &&\n bytes[3] === 0x04\n );\n}\n\n/**\n * Check if a file path has HWPX extension\n */\nexport function isHwpxPath(path: string): boolean {\n return path.toLowerCase().endsWith(\".hwpx\");\n}\n","/**\n * HWP/HWPX to Markdown Converter\n * Orchestrates conversion from HWP/HWPX to Markdown\n */\n\nimport { HWPFile } from \"./parser\";\nimport { RecordReader } from \"./record\";\nimport { ParagraphParser } from \"./paragraph\";\nimport {\n HWPXFile,\n parseHwpxSection,\n isHwpxData,\n isHwpxPath,\n} from \"./hwpx_parser\";\nimport type { Paragraph, ConvertOptions } from \"./types\";\n\n/**\n * Convert paragraphs to Markdown\n * @param paragraphs - List of paragraphs\n * @returns Markdown text\n */\nexport function paragraphsToMarkdown(paragraphs: Paragraph[]): string {\n const lines: string[] = [];\n\n for (const para of paragraphs) {\n const text = para.text.trim();\n if (!text) {\n continue;\n }\n\n // Skip paragraphs that are likely garbled control characters\n // These appear as short mysterious character sequences before tables\n if (\n text.length < 5 &&\n !text.startsWith(\"|\") &&\n [...text].every((c) => (c.codePointAt(0) ?? 0) > 127)\n ) {\n continue;\n }\n\n lines.push(text);\n }\n\n return lines.join(\"\\n\\n\");\n}\n\n/**\n * Convert HWP file to Markdown\n * @param hwp - Opened HWP file\n * @param options - Conversion options\n * @returns Markdown content\n */\nexport function convertHwpToMarkdown(\n hwp: HWPFile,\n options: ConvertOptions = {},\n): string {\n const allParagraphs: Paragraph[] = [];\n\n // Default options\n if (!options.tableLineBreakStyle) {\n options.tableLineBreakStyle = \"space\";\n }\n\n // Process each section\n const sectionCount = hwp.getSectionCount();\n\n for (let i = 0; i < sectionCount; i++) {\n // Read section data\n const sectionData = hwp.readSection(i);\n if (!sectionData) {\n continue;\n }\n\n // Parse records\n const reader = new RecordReader(sectionData);\n const parser = new ParagraphParser(reader, options);\n\n // Parse paragraphs\n const paragraphs = parser.parseAllParagraphs();\n allParagraphs.push(...paragraphs);\n }\n\n // Convert to Markdown\n const markdown = paragraphsToMarkdown(allParagraphs);\n\n return markdown;\n}\n\n/**\n * Convert HWPX file to Markdown\n * @param hwpx - Opened HWPX file\n * @param options - Conversion options\n * @returns Markdown content\n */\nexport function convertHwpxToMarkdown(\n hwpx: HWPXFile,\n options: ConvertOptions = {},\n): string {\n const allParagraphs: Paragraph[] = [];\n\n const sectionCount = hwpx.getSectionCount();\n for (let i = 0; i < sectionCount; i++) {\n const sectionObj = hwpx.getSectionXml(i) as Record<string, unknown>;\n const paragraphs = parseHwpxSection(sectionObj, options);\n allParagraphs.push(...paragraphs);\n }\n\n return paragraphsToMarkdown(allParagraphs);\n}\n\n/**\n * High-level API: Convert HWP/HWPX file to Markdown\n * Auto-detects format based on file extension or magic bytes.\n * @param input - File path (Node.js), ArrayBuffer, or Uint8Array\n * @param options - Conversion options\n * @returns Markdown content\n */\nexport async function convert(\n input: string | ArrayBuffer | Uint8Array,\n options?: ConvertOptions,\n): Promise<string> {\n // Detect HWPX format\n if (typeof input === \"string\" && isHwpxPath(input)) {\n const hwpx = await HWPXFile.fromFile(input);\n try {\n hwpx.open();\n return convertHwpxToMarkdown(hwpx, options);\n } finally {\n hwpx.close();\n }\n }\n\n if (\n (input instanceof Uint8Array || input instanceof ArrayBuffer) &&\n isHwpxData(input instanceof ArrayBuffer ? new Uint8Array(input) : input)\n ) {\n const hwpx =\n input instanceof Uint8Array\n ? HWPXFile.fromUint8Array(input)\n : HWPXFile.fromArrayBuffer(input);\n try {\n hwpx.open();\n return convertHwpxToMarkdown(hwpx, options);\n } finally {\n hwpx.close();\n }\n }\n\n // Default: HWP format\n let hwp: HWPFile;\n if (typeof input === \"string\") {\n hwp = await HWPFile.fromFile(input);\n } else if (input instanceof Uint8Array) {\n hwp = HWPFile.fromUint8Array(input);\n } else {\n hwp = HWPFile.fromArrayBuffer(input);\n }\n\n try {\n hwp.open();\n return convertHwpToMarkdown(hwp, options);\n } finally {\n hwp.close();\n }\n}\n","/**\n * Binary Reader Utility\n * Replaces Python's struct.unpack functionality\n * All multi-byte values are little-endian\n */\nexport class BinaryReader {\n private view: DataView;\n private offset: number = 0;\n\n constructor(data: Uint8Array | ArrayBuffer) {\n const buffer = data instanceof Uint8Array ? data.buffer : data;\n const byteOffset = data instanceof Uint8Array ? data.byteOffset : 0;\n const byteLength =\n data instanceof Uint8Array\n ? data.byteLength\n : (data as ArrayBuffer).byteLength;\n this.view = new DataView(buffer, byteOffset, byteLength);\n }\n\n /**\n * Read unsigned 8-bit integer (BYTE)\n */\n readUint8(): number {\n const value = this.view.getUint8(this.offset);\n this.offset += 1;\n return value;\n }\n\n /**\n * Read unsigned 16-bit integer (WORD) - little-endian\n */\n readUint16LE(): number {\n const value = this.view.getUint16(this.offset, true);\n this.offset += 2;\n return value;\n }\n\n /**\n * Read unsigned 32-bit integer (DWORD) - little-endian\n */\n readUint32LE(): number {\n const value = this.view.getUint32(this.offset, true);\n this.offset += 4;\n return value;\n }\n\n /**\n * Read signed 32-bit integer - little-endian\n */\n readInt32LE(): number {\n const value = this.view.getInt32(this.offset, true);\n this.offset += 4;\n return value;\n }\n\n /**\n * Read bytes without advancing offset (peek)\n */\n peekBytes(length: number): Uint8Array {\n return new Uint8Array(\n this.view.buffer,\n this.view.byteOffset + this.offset,\n length,\n );\n }\n\n /**\n * Read bytes and advance offset\n */\n readBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(\n this.view.buffer,\n this.view.byteOffset + this.offset,\n length,\n );\n this.offset += length;\n return bytes;\n }\n\n /**\n * Skip bytes\n */\n skip(length: number): void {\n this.offset += length;\n }\n\n /**\n * Set absolute position\n */\n seek(offset: number): void {\n this.offset = offset;\n }\n\n /**\n * Get current position\n */\n get position(): number {\n return this.offset;\n }\n\n /**\n * Get remaining bytes\n */\n get remaining(): number {\n return this.view.byteLength - this.offset;\n }\n\n /**\n * Check if more data is available\n */\n hasMore(minBytes: number = 1): boolean {\n return this.remaining >= minBytes;\n }\n\n /**\n * Get total length\n */\n get length(): number {\n return this.view.byteLength;\n }\n\n /**\n * Create a new BinaryReader for a subset of data\n */\n slice(start: number, end?: number): BinaryReader {\n const actualEnd = end ?? this.view.byteLength;\n const slicedData = new Uint8Array(\n this.view.buffer,\n this.view.byteOffset + start,\n actualEnd - start,\n );\n return new BinaryReader(slicedData);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,454 @@
1
+ //#region src/types.d.ts
2
+ /**
3
+ * HWP File Header Information
4
+ */
5
+ interface FileHeader {
6
+ signature: string;
7
+ version: string;
8
+ isCompressed: boolean;
9
+ isEncrypted: boolean;
10
+ rawProperties: number;
11
+ }
12
+ /**
13
+ * Binary Record Structure
14
+ */
15
+ interface Record$1 {
16
+ tagId: number;
17
+ level: number;
18
+ data: Uint8Array;
19
+ size: number;
20
+ }
21
+ /**
22
+ * Paragraph Header Information
23
+ */
24
+ interface ParagraphHeader {
25
+ textCount: number;
26
+ controlMask: number;
27
+ paraShapeId: number;
28
+ styleId: number;
29
+ columnType: number;
30
+ charShapeCount: number;
31
+ }
32
+ /**
33
+ * Parsed Paragraph
34
+ */
35
+ interface Paragraph {
36
+ text: string;
37
+ header: ParagraphHeader;
38
+ }
39
+ /**
40
+ * Table Cell
41
+ */
42
+ interface Cell {
43
+ row: number;
44
+ col: number;
45
+ rowspan: number;
46
+ colspan: number;
47
+ text: string;
48
+ }
49
+ /**
50
+ * Parsed Table
51
+ */
52
+ interface Table {
53
+ rows: number;
54
+ cols: number;
55
+ cells: Cell[];
56
+ }
57
+ /**
58
+ * Conversion Options
59
+ */
60
+ interface ConvertOptions {
61
+ tableLineBreakStyle?: "space" | "br";
62
+ }
63
+ /**
64
+ * Merge Strategy for Table Cells
65
+ */
66
+ type MergeStrategy = "repeat" | "blank";
67
+ //#endregion
68
+ //#region src/parser.d.ts
69
+ /**
70
+ * HWP File Parser
71
+ * Reads and parses HWP 5.0 files using OLE Compound File format
72
+ */
73
+ declare class HWPFile {
74
+ private data;
75
+ private cfb;
76
+ private _fileHeader;
77
+ private _isCompressed;
78
+ /**
79
+ * Create HWPFile from raw data
80
+ * @param data - Raw HWP file data
81
+ */
82
+ constructor(data: Uint8Array | ArrayBuffer);
83
+ /**
84
+ * Create HWPFile from file path (Node.js only)
85
+ * @param path - Path to HWP file
86
+ */
87
+ static fromFile(path: string): Promise<HWPFile>;
88
+ /**
89
+ * Create HWPFile from ArrayBuffer
90
+ * @param data - ArrayBuffer data
91
+ */
92
+ static fromArrayBuffer(data: ArrayBuffer): HWPFile;
93
+ /**
94
+ * Create HWPFile from Uint8Array
95
+ * @param data - Uint8Array data
96
+ */
97
+ static fromUint8Array(data: Uint8Array): HWPFile;
98
+ /**
99
+ * Open and parse HWP file
100
+ */
101
+ open(): void;
102
+ /**
103
+ * Close HWP file and release resources
104
+ */
105
+ close(): void;
106
+ /**
107
+ * Get file header information
108
+ */
109
+ get fileHeader(): FileHeader | null;
110
+ /**
111
+ * Check if file is compressed
112
+ */
113
+ get isCompressed(): boolean;
114
+ /**
115
+ * Parse FileHeader stream (256 bytes fixed)
116
+ */
117
+ private parseFileHeader;
118
+ /**
119
+ * Read and decompress stream
120
+ * @param streamPath - Stream path (e.g., 'DocInfo', 'BodyText/Section0')
121
+ * @returns Decompressed data or null if stream doesn't exist
122
+ */
123
+ readStream(streamPath: string): Uint8Array | null;
124
+ /**
125
+ * List all streams in HWP file
126
+ * @returns Array of stream paths
127
+ */
128
+ listStreams(): string[][];
129
+ /**
130
+ * Get file information
131
+ */
132
+ getFileInfo(): Record<string, unknown>;
133
+ /**
134
+ * Get number of sections in BodyText
135
+ */
136
+ getSectionCount(): number;
137
+ /**
138
+ * Read section data
139
+ * @param sectionIndex - Section index (0-based)
140
+ * @returns Decompressed section data
141
+ */
142
+ readSection(sectionIndex: number): Uint8Array | null;
143
+ }
144
+ //#endregion
145
+ //#region src/record.d.ts
146
+ declare const HWPTAG_BEGIN = 16;
147
+ declare const HWPTAG_DOCUMENT_PROPERTIES = 16;
148
+ declare const HWPTAG_ID_MAPPINGS = 17;
149
+ declare const HWPTAG_BIN_DATA = 18;
150
+ declare const HWPTAG_FACE_NAME = 19;
151
+ declare const HWPTAG_BORDER_FILL = 20;
152
+ declare const HWPTAG_CHAR_SHAPE = 21;
153
+ declare const HWPTAG_TAB_DEF = 22;
154
+ declare const HWPTAG_NUMBERING = 23;
155
+ declare const HWPTAG_BULLET = 24;
156
+ declare const HWPTAG_PARA_SHAPE = 25;
157
+ declare const HWPTAG_STYLE = 26;
158
+ declare const HWPTAG_PARA_HEADER: number;
159
+ declare const HWPTAG_PARA_TEXT: number;
160
+ declare const HWPTAG_PARA_CHAR_SHAPE: number;
161
+ declare const HWPTAG_PARA_LINE_SEG: number;
162
+ declare const HWPTAG_PARA_RANGE_TAG: number;
163
+ declare const HWPTAG_CTRL_HEADER: number;
164
+ declare const HWPTAG_LIST_HEADER: number;
165
+ declare const HWPTAG_PAGE_DEF: number;
166
+ declare const HWPTAG_FOOTNOTE_SHAPE: number;
167
+ declare const HWPTAG_PAGE_BORDER_FILL: number;
168
+ declare const HWPTAG_SHAPE_COMPONENT: number;
169
+ declare const HWPTAG_TABLE: number;
170
+ declare const HWPTAG_SHAPE_COMPONENT_LINE: number;
171
+ declare const HWPTAG_CTRL_DATA: number;
172
+ /**
173
+ * HWP Record Reader
174
+ * Reads binary records from HWP stream data
175
+ */
176
+ declare class RecordReader {
177
+ private data;
178
+ private offset;
179
+ constructor(data: Uint8Array);
180
+ /**
181
+ * Check if there are more records to read
182
+ */
183
+ hasMore(): boolean;
184
+ /**
185
+ * Read next record
186
+ * @returns Next record, or null if no more records
187
+ */
188
+ readRecord(): Record$1 | null;
189
+ /**
190
+ * Peek at next record header without consuming it
191
+ * @returns Header info with tagId, level, size
192
+ */
193
+ peekRecordHeader(): {
194
+ tagId: number;
195
+ level: number;
196
+ size: number;
197
+ } | null;
198
+ /**
199
+ * Read all records (considering hierarchy)
200
+ * @param parentLevel - Stop when reaching this level or below
201
+ * @returns All records at current level
202
+ */
203
+ readAllRecords(parentLevel?: number): Record$1[];
204
+ /**
205
+ * Get current position
206
+ */
207
+ get position(): number;
208
+ /**
209
+ * Get remaining bytes
210
+ */
211
+ get remaining(): number;
212
+ }
213
+ //#endregion
214
+ //#region src/paragraph.d.ts
215
+ /**
216
+ * Parse paragraph header
217
+ * @param data - PARA_HEADER record data
218
+ * @returns Paragraph header information
219
+ */
220
+ declare function parseParaHeader(data: Uint8Array): ParagraphHeader;
221
+ /**
222
+ * Parse paragraph text with control info table
223
+ *
224
+ * PARA_TEXT structure:
225
+ * [Control info table: 16 bytes per control] + [Actual text]
226
+ *
227
+ * Each control info block (16 bytes):
228
+ * - 2 bytes: control code
229
+ * - 4 bytes: control ID
230
+ * - 8 bytes: control data
231
+ * - 2 bytes: control code (repeated)
232
+ *
233
+ * @param data - PARA_TEXT record data
234
+ * @param nchars - Number of WCHAR characters (control table + text)
235
+ * @returns Decoded text
236
+ */
237
+ declare function parseParaText(data: Uint8Array, _nchars: number): string;
238
+ /**
239
+ * Process control characters in text
240
+ * @param text - Raw text with control characters
241
+ * @returns Processed text and has_table flag
242
+ */
243
+ declare function processControlChars(text: string): {
244
+ text: string;
245
+ hasTable: boolean;
246
+ };
247
+ /**
248
+ * Paragraph Parser
249
+ * Parses paragraphs from HWP record stream
250
+ */
251
+ declare class ParagraphParser {
252
+ private reader;
253
+ private options;
254
+ constructor(reader: RecordReader, options?: ConvertOptions);
255
+ /**
256
+ * Parse next paragraph
257
+ * @returns Parsed paragraph, or null if no more paragraphs
258
+ */
259
+ parseParagraph(): Paragraph | null;
260
+ /**
261
+ * Parse all paragraphs in section
262
+ * @returns All paragraphs
263
+ */
264
+ parseAllParagraphs(): Paragraph[];
265
+ }
266
+ //#endregion
267
+ //#region src/table.d.ts
268
+ /**
269
+ * Parse table properties from TABLE record data
270
+ * @param data - TABLE record data
271
+ * @returns Table properties with rows, cols
272
+ */
273
+ declare function parseTableProperties(data: Uint8Array): {
274
+ properties: number;
275
+ rows: number;
276
+ cols: number;
277
+ };
278
+ /**
279
+ * Parse cell properties
280
+ * @param data - Cell property data
281
+ * @returns Cell properties
282
+ */
283
+ declare function parseCellProperties(data: Uint8Array): {
284
+ col: number;
285
+ row: number;
286
+ colspan: number;
287
+ rowspan: number;
288
+ };
289
+ /**
290
+ * Parse table from TABLE record and subsequent records
291
+ * @param tableRecordData - TABLE record data
292
+ * @param reader - Record reader for reading cell data
293
+ * @param lineBreakStyle - How to handle line breaks in cells
294
+ * @returns Parsed table
295
+ */
296
+ declare function parseTable(tableRecordData: Uint8Array, reader: RecordReader, lineBreakStyle?: "space" | "br"): Table;
297
+ /**
298
+ * Convert table to Markdown
299
+ * @param table - Table object
300
+ * @param mergeStrategy - 'repeat' (default) or 'blank'
301
+ * @returns Markdown table
302
+ */
303
+ declare function tableToMarkdown(table: Table, mergeStrategy?: MergeStrategy): string;
304
+ //#endregion
305
+ //#region src/hwpx_parser.d.ts
306
+ /**
307
+ * HWPX file parser
308
+ */
309
+ declare class HWPXFile {
310
+ private data;
311
+ private entries;
312
+ private sectionPaths;
313
+ private version;
314
+ private xmlParser;
315
+ constructor(data: Uint8Array);
316
+ static fromFile(path: string): Promise<HWPXFile>;
317
+ static fromArrayBuffer(data: ArrayBuffer): HWPXFile;
318
+ static fromUint8Array(data: Uint8Array): HWPXFile;
319
+ open(): void;
320
+ close(): void;
321
+ private parseVersion;
322
+ private discoverSections;
323
+ get fileInfo(): Record<string, unknown>;
324
+ getSectionCount(): number;
325
+ getSectionXml(index: number): unknown;
326
+ listContents(): string[];
327
+ private ensureOpen;
328
+ }
329
+ /**
330
+ * Parse a table XML object (hp:tbl) into a Table
331
+ */
332
+ declare function parseHwpxTable(tblObj: Record<string, unknown>, lineBreakStyle?: string): Table;
333
+ /**
334
+ * Parse a section XML object into paragraphs
335
+ */
336
+ declare function parseHwpxSection(sectionObj: Record<string, unknown>, options?: ConvertOptions): Paragraph[];
337
+ /**
338
+ * Check if binary data is a HWPX file (ZIP magic bytes)
339
+ */
340
+ declare function isHwpxData(data: Uint8Array | ArrayBuffer): boolean;
341
+ /**
342
+ * Check if a file path has HWPX extension
343
+ */
344
+ declare function isHwpxPath(path: string): boolean;
345
+ //#endregion
346
+ //#region src/converter.d.ts
347
+ /**
348
+ * Convert paragraphs to Markdown
349
+ * @param paragraphs - List of paragraphs
350
+ * @returns Markdown text
351
+ */
352
+ declare function paragraphsToMarkdown(paragraphs: Paragraph[]): string;
353
+ /**
354
+ * Convert HWP file to Markdown
355
+ * @param hwp - Opened HWP file
356
+ * @param options - Conversion options
357
+ * @returns Markdown content
358
+ */
359
+ declare function convertHwpToMarkdown(hwp: HWPFile, options?: ConvertOptions): string;
360
+ /**
361
+ * Convert HWPX file to Markdown
362
+ * @param hwpx - Opened HWPX file
363
+ * @param options - Conversion options
364
+ * @returns Markdown content
365
+ */
366
+ declare function convertHwpxToMarkdown(hwpx: HWPXFile, options?: ConvertOptions): string;
367
+ /**
368
+ * High-level API: Convert HWP/HWPX file to Markdown
369
+ * Auto-detects format based on file extension or magic bytes.
370
+ * @param input - File path (Node.js), ArrayBuffer, or Uint8Array
371
+ * @param options - Conversion options
372
+ * @returns Markdown content
373
+ */
374
+ declare function convert(input: string | ArrayBuffer | Uint8Array, options?: ConvertOptions): Promise<string>;
375
+ //#endregion
376
+ //#region src/utils/binary.d.ts
377
+ /**
378
+ * Binary Reader Utility
379
+ * Replaces Python's struct.unpack functionality
380
+ * All multi-byte values are little-endian
381
+ */
382
+ declare class BinaryReader {
383
+ private view;
384
+ private offset;
385
+ constructor(data: Uint8Array | ArrayBuffer);
386
+ /**
387
+ * Read unsigned 8-bit integer (BYTE)
388
+ */
389
+ readUint8(): number;
390
+ /**
391
+ * Read unsigned 16-bit integer (WORD) - little-endian
392
+ */
393
+ readUint16LE(): number;
394
+ /**
395
+ * Read unsigned 32-bit integer (DWORD) - little-endian
396
+ */
397
+ readUint32LE(): number;
398
+ /**
399
+ * Read signed 32-bit integer - little-endian
400
+ */
401
+ readInt32LE(): number;
402
+ /**
403
+ * Read bytes without advancing offset (peek)
404
+ */
405
+ peekBytes(length: number): Uint8Array;
406
+ /**
407
+ * Read bytes and advance offset
408
+ */
409
+ readBytes(length: number): Uint8Array;
410
+ /**
411
+ * Skip bytes
412
+ */
413
+ skip(length: number): void;
414
+ /**
415
+ * Set absolute position
416
+ */
417
+ seek(offset: number): void;
418
+ /**
419
+ * Get current position
420
+ */
421
+ get position(): number;
422
+ /**
423
+ * Get remaining bytes
424
+ */
425
+ get remaining(): number;
426
+ /**
427
+ * Check if more data is available
428
+ */
429
+ hasMore(minBytes?: number): boolean;
430
+ /**
431
+ * Get total length
432
+ */
433
+ get length(): number;
434
+ /**
435
+ * Create a new BinaryReader for a subset of data
436
+ */
437
+ slice(start: number, end?: number): BinaryReader;
438
+ }
439
+ //#endregion
440
+ //#region src/utils/compression.d.ts
441
+ /**
442
+ * Decompress raw deflate data (no zlib header)
443
+ * Equivalent to Python: zlib.decompress(data, -15)
444
+ *
445
+ * HWP files use raw deflate compression without zlib wrapper headers.
446
+ * The windowBits=-15 in Python indicates raw deflate mode.
447
+ *
448
+ * @param data - Compressed data
449
+ * @returns Decompressed data
450
+ */
451
+ declare function decompressRaw(data: Uint8Array): Uint8Array;
452
+ //#endregion
453
+ export { BinaryReader, Cell, ConvertOptions, FileHeader, HWPFile, HWPTAG_BEGIN, HWPTAG_BIN_DATA, HWPTAG_BORDER_FILL, HWPTAG_BULLET, HWPTAG_CHAR_SHAPE, HWPTAG_CTRL_DATA, HWPTAG_CTRL_HEADER, HWPTAG_DOCUMENT_PROPERTIES, HWPTAG_FACE_NAME, HWPTAG_FOOTNOTE_SHAPE, HWPTAG_ID_MAPPINGS, HWPTAG_LIST_HEADER, HWPTAG_NUMBERING, HWPTAG_PAGE_BORDER_FILL, HWPTAG_PAGE_DEF, HWPTAG_PARA_CHAR_SHAPE, HWPTAG_PARA_HEADER, HWPTAG_PARA_LINE_SEG, HWPTAG_PARA_RANGE_TAG, HWPTAG_PARA_SHAPE, HWPTAG_PARA_TEXT, HWPTAG_SHAPE_COMPONENT, HWPTAG_SHAPE_COMPONENT_LINE, HWPTAG_STYLE, HWPTAG_TABLE, HWPTAG_TAB_DEF, HWPXFile, MergeStrategy, Paragraph, ParagraphHeader, ParagraphParser, Record$1 as Record, RecordReader, Table, convert, convertHwpToMarkdown, convertHwpxToMarkdown, decompressRaw, isHwpxData, isHwpxPath, paragraphsToMarkdown, parseCellProperties, parseHwpxSection, parseHwpxTable, parseParaHeader, parseParaText, parseTable, parseTableProperties, processControlChars, tableToMarkdown };
454
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/parser.ts","../src/record.ts","../src/paragraph.ts","../src/table.ts","../src/hwpx_parser.ts","../src/converter.ts","../src/utils/binary.ts","../src/utils/compression.ts"],"sourcesContent":[],"mappings":"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"}