hwpkit-dev 0.0.3 → 0.0.5

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/contract/result.ts","../src/pipeline/registry.ts","../src/model/doc-props.ts","../src/model/builders.ts","../src/safety/ShieldedParser.ts","../src/safety/StyleBridge.ts","../src/toolkit/ArchiveKit.ts","../src/toolkit/XmlKit.ts","../src/toolkit/TextKit.ts","../src/core/BaseDecoder.ts","../src/encoders/hwpx/constants.ts","../src/decoders/hwpx/HwpxDecoder.ts","../src/toolkit/BinaryKit.ts","../src/decoders/hwp/HwpScanner.ts","../src/decoders/docx/DocxDecoder.ts","../src/decoders/md/MdDecoder.ts","../src/decoders/html/HtmlDecoder.ts","../src/core/BaseEncoder.ts","../src/encoders/hwpx/HwpxEncoder.ts","../src/encoders/docx/DocxEncoder.ts","../src/encoders/md/MdEncoder.ts","../src/encoders/html/HtmlEncoder.ts","../src/encoders/hwp/HwpEncoder.ts","../src/pipeline/Pipeline.ts","../src/walk/TreeWalker.ts","../src/walk/tree-ops.ts"],"sourcesContent":["// ─── 공개 API ───────────────────────────────────────────────\n\n// Pipeline\nexport { Pipeline } from './pipeline/Pipeline';\nexport { registry } from './pipeline/registry';\n\n// Side-effect imports: register all decoders/encoders\nimport './decoders/md/MdDecoder';\nimport './decoders/hwpx/HwpxDecoder';\nimport './decoders/docx/DocxDecoder';\nimport './decoders/hwp/HwpScanner';\nimport './encoders/md/MdEncoder';\nimport './encoders/html/HtmlEncoder';\nimport './encoders/hwpx/HwpxEncoder';\nimport './encoders/docx/DocxEncoder';\nimport './encoders/hwp/HwpEncoder';\n\n// Model\nexport type {\n DocRoot, SheetNode, ParaNode, SpanNode, GridNode, RowNode, CellNode,\n ImgNode, LinkNode, TxtNode, BrNode, PbNode, PageNumNode, ContentNode, AnyNode, BlockTag,\n} from './model/doc-tree';\nexport type {\n TextProps, ParaProps, CellProps, GridProps, TableLook, PageDims, DocMeta,\n Align, VAlign, Heading, StrokeKind, Stroke,\n} from './model/doc-props';\nexport { A4, A4_LANDSCAPE, DEFAULT_STROKE, normalizeDims } from './model/doc-props';\nexport { buildRoot, buildSheet, buildPara, buildSpan, buildImg, buildGrid, buildRow, buildCell, buildPageNum, buildBr, buildPb } from './model/builders';\n\n// Contract\nexport type { Decoder } from './contract/decoder';\nexport type { Encoder } from './contract/encoder';\nexport type { Outcome, Ok, Fail } from './contract/result';\nexport { succeed, fail } from './contract/result';\n\n// Safety\nexport { ShieldedParser } from './safety/ShieldedParser';\nexport { Metric, safeHex, safeAlign, safeFont, safeFontToKr, safeStrokeHwpx, safeStrokeDocx } from './safety/StyleBridge';\n\n// Walk\nexport { TreeWalker, walkNode } from './walk/TreeWalker';\nexport { countNodes, validateRoot } from './walk/tree-ops';\n\n// Toolkit\nexport { XmlKit } from './toolkit/XmlKit';\nexport { ArchiveKit } from './toolkit/ArchiveKit';\nexport { BinaryKit } from './toolkit/BinaryKit';\nexport { TextKit } from './toolkit/TextKit';\n","export type Outcome<T> = Ok<T> | Fail;\n\nexport interface Ok<T> {\n ok: true;\n data: T;\n warns: string[];\n}\n\nexport interface Fail {\n ok: false;\n error: string;\n warns: string[];\n}\n\nexport function succeed<T>(data: T, warns: string[] = []): Ok<T> {\n return { ok: true, data, warns };\n}\n\nexport function fail(error: string, warns: string[] = []): Fail {\n return { ok: false, error, warns };\n}\n","import type { Decoder } from '../contract/decoder';\nimport type { Encoder } from '../contract/encoder';\n\nclass FormatRegistry {\n private decoders = new Map<string, Decoder>();\n private encoders = new Map<string, Encoder>();\n\n registerDecoder(d: Decoder): void {\n this.decoders.set(d.format, d);\n if (d.aliases) {\n for (const alias of d.aliases) this.decoders.set(alias, d);\n }\n }\n\n registerEncoder(e: Encoder): void {\n this.encoders.set(e.format, e);\n if (e.aliases) {\n for (const alias of e.aliases) this.encoders.set(alias, e);\n }\n }\n\n getDecoder(fmt: string): Decoder | undefined { return this.decoders.get(fmt); }\n getEncoder(fmt: string): Encoder | undefined { return this.encoders.get(fmt); }\n\n supportedInputs(): string[] { return [...this.decoders.keys()]; }\n supportedOutputs(): string[] { return [...this.encoders.keys()]; }\n}\n\nexport const registry = new FormatRegistry();\n","export type Align = 'left' | 'center' | 'right' | 'justify';\n\n// ─── 이미지 배치 ────────────────────────────────────────────\nexport type ImgWrap = 'inline' | 'square' | 'tight' | 'through' | 'none' | 'behind' | 'front' | 'topAndBottom';\nexport type ImgHorzAlign = 'left' | 'center' | 'right';\nexport type ImgVertAlign = 'top' | 'center' | 'bottom';\nexport type ImgHorzRelTo = 'margin' | 'column' | 'page' | 'para';\nexport type ImgVertRelTo = 'margin' | 'line' | 'page' | 'para';\n\nexport interface ImgLayout {\n wrap: ImgWrap;\n horzAlign?: ImgHorzAlign; // 정렬 기준 (xPt 없을 때)\n vertAlign?: ImgVertAlign; // 정렬 기준 (yPt 없을 때)\n horzRelTo?: ImgHorzRelTo; // 가로 기준점\n vertRelTo?: ImgVertRelTo; // 세로 기준점\n xPt?: number; // 명시적 가로 오프셋 (pt)\n yPt?: number; // 명시적 세로 오프셋 (pt)\n distT?: number; // 텍스트와의 거리 top (pt)\n distB?: number;\n distL?: number;\n distR?: number;\n behindDoc?: boolean; // 텍스트 뒤에 배치\n zOrder?: number;\n}\nexport type VAlign = 'top' | 'mid' | 'bot';\nexport type Heading = 1 | 2 | 3 | 4 | 5 | 6;\nexport type StrokeKind = 'solid' | 'dash' | 'dot' | 'double' | 'none' | 'dashDot' | 'dashDotDot' | 'wave';\n\nexport interface TextProps {\n b?: boolean;\n i?: boolean;\n u?: boolean;\n s?: boolean;\n sup?: boolean;\n sub?: boolean;\n font?: string;\n pt?: number;\n color?: string;\n bg?: string;\n}\n\nexport interface ParaProps {\n align?: Align;\n heading?: Heading;\n styleId?: string; // DOCX pStyle styleId (e.g. \"Heading1\", \"TOC1\")\n indentPt?: number; // 문단 왼쪽 전체 들여쓰기 (pt) — OWPML hc:left\n indentRightPt?: number; // 문단 오른쪽 전체 들여쓰기 (pt) — OWPML hc:right\n firstLineIndentPt?: number; // 첫 줄 들여쓰기 (pt, 음수=내어쓰기) — OWPML hc:indent\n leftMargin?: number; // 문단 왼쪽 여백 (HWP leftMargin, pt)\n spaceBefore?: number;\n spaceAfter?: number;\n lineHeight?: number; // 줄 간격 배율 (예: 1.5 = 150%)\n lineHeightFixed?: number; // 고정 줄 높이 (pt) — OWPML lineSpacing type=\"FIXED\"\n listLv?: number;\n listOrd?: boolean;\n listMark?: string;\n}\n\nexport interface Stroke {\n kind: StrokeKind;\n pt: number;\n color: string;\n}\n\nexport interface CellProps {\n top?: Stroke;\n bot?: Stroke;\n left?: Stroke;\n right?: Stroke;\n bg?: string;\n padPt?: number; // 모든 방향 균일 패딩 (하위 호환)\n padT?: number; // 상단 패딩 (pt)\n padB?: number; // 하단 패딩\n padL?: number; // 좌측 패딩\n padR?: number; // 우측 패딩\n align?: Align;\n va?: VAlign;\n isHeader?: boolean;\n}\n\nexport interface TableLook {\n firstRow?: boolean;\n lastRow?: boolean;\n firstCol?: boolean;\n lastCol?: boolean;\n bandedRows?: boolean;\n bandedCols?: boolean;\n}\n\nexport interface GridProps {\n widthPct?: number;\n colWidths?: number[]; // column widths in points\n defaultStroke?: Stroke;\n look?: TableLook;\n headerRow?: boolean;\n align?: Align; // 표 정렬: 'left' | 'center' | 'right' | 'justify'\n}\n\nexport interface PageDims {\n wPt: number;\n hPt: number;\n mt: number;\n mb: number;\n ml: number;\n mr: number;\n orient?: 'portrait' | 'landscape';\n headerPt?: number; // distance from paper top to header top (DOCX w:header)\n footerPt?: number; // distance from paper bottom to footer bottom (DOCX w:footer)\n}\n\nexport interface DocMeta {\n title?: string;\n author?: string;\n subject?: string;\n desc?: string;\n keywords?: string;\n created?: string;\n modified?: string;\n zoom?: number;\n viewMode?: string;\n}\n\nexport const A4: PageDims = {\n wPt: 595.28, hPt: 841.89,\n mt: 56.69, mb: 56.69, ml: 70.87, mr: 70.87,\n orient: 'portrait',\n};\n\nexport const A4_LANDSCAPE: PageDims = {\n wPt: 841.89, hPt: 595.28,\n mt: 56.69, mb: 56.69, ml: 70.87, mr: 70.87,\n orient: 'landscape',\n};\n\n/**\n * orient === 'landscape'일 때 wPt < hPt이면 swap,\n * orient === 'portrait'일 때 wPt > hPt이면 swap하여\n * 방향과 치수가 항상 일치하도록 정규화합니다.\n */\n\nexport function normalizeDims(dims: PageDims): PageDims {\n const orient = dims.orient ?? 'portrait';\n if (orient === 'landscape' && dims.wPt < dims.hPt) {\n return { ...dims, wPt: dims.hPt, hPt: dims.wPt };\n }\n if (orient === 'portrait' && dims.wPt > dims.hPt) {\n return { ...dims, wPt: dims.hPt, hPt: dims.wPt };\n }\n return dims;\n}\n\nexport const DEFAULT_STROKE: Stroke = { kind: 'solid', pt: 0.5, color: '000000' };\n","import type {\n DocRoot, SheetNode, ParaNode, SpanNode, ImgNode,\n GridNode, RowNode, CellNode, ContentNode, TxtNode, PageNumNode, BrNode, PbNode,\n} from './doc-tree';\nimport type { TextProps, ParaProps, CellProps, GridProps, DocMeta, PageDims, ImgLayout } from './doc-props';\nimport { A4 } from './doc-props';\n\nexport function buildRoot(meta: DocMeta = {}, kids: SheetNode[] = []): DocRoot {\n return { tag: 'root', meta, kids };\n}\n\nexport function buildSheet(\n kids: ContentNode[] = [],\n dims: PageDims = A4,\n opts?: { headers?: SheetNode[\"headers\"]; footers?: SheetNode[\"footers\"] },\n): SheetNode {\n const node: SheetNode = { tag: 'sheet', dims, kids };\n if (opts?.headers) node.headers = opts.headers;\n if (opts?.footers) node.footers = opts.footers;\n return node;\n}\n\nexport function buildPageNum(format?: PageNumNode['format']): PageNumNode {\n return { tag: 'pagenum', format };\n}\n\nexport function buildBr(): BrNode { return { tag: 'br' }; }\nexport function buildPb(): PbNode { return { tag: 'pb' }; }\n\nexport function buildPara(kids: ParaNode['kids'] = [], props: ParaProps = {}): ParaNode {\n return { tag: 'para', props, kids };\n}\n\nexport function buildSpan(content: string, props: TextProps = {}): SpanNode {\n const txt: TxtNode = { tag: 'txt', content };\n return { tag: 'span', props, kids: [txt] };\n}\n\nexport function buildImg(\n b64: string,\n mime: ImgNode['mime'],\n w: number,\n h: number,\n alt?: string,\n layout?: ImgLayout,\n): ImgNode {\n const node: ImgNode = { tag: 'img', b64, mime, w, h };\n if (alt) node.alt = alt;\n if (layout) node.layout = layout;\n return node;\n}\n\nexport function buildGrid(kids: RowNode[], props: GridProps = {}): GridNode {\n return { tag: 'grid', props, kids };\n}\n\nexport function buildRow(kids: CellNode[], heightPt?: number): RowNode {\n const node: RowNode = { tag: 'row', kids };\n if (heightPt != null) node.heightPt = heightPt;\n return node;\n}\n\nexport function buildCell(\n kids: (ParaNode | GridNode)[],\n opts: { cs?: number; rs?: number; props?: CellProps } = {},\n): CellNode {\n return { tag: 'cell', cs: opts.cs ?? 1, rs: opts.rs ?? 1, props: opts.props ?? {}, kids };\n}\n","export class ShieldedParser {\n private log: string[] = [];\n\n /** 단일 요소 안전 파싱 */\n guard<T>(fn: () => T, fallback: T, label: string): T {\n try {\n const v = fn();\n if (v == null) {\n this.warn(label, 'returned null/undefined');\n return fallback;\n }\n return v;\n } catch (e: any) {\n this.warn(label, e?.message ?? String(e));\n return fallback;\n }\n }\n\n /** 배열 각 요소 독립 파싱 (하나 실패해도 나머지 계속) */\n guardAll<I, O>(\n items: I[],\n fn: (x: I, i: number) => O,\n fb: (x: I, i: number) => O,\n label: string,\n ): O[] {\n return items.map((x, i) =>\n this.guard(() => fn(x, i), fb(x, i), `${label}[${i}]`),\n );\n }\n\n /**\n * 표 전용 4단계 폴백\n * Lv1: Full → Lv2: Grid → Lv3: Flat → Lv4: Text\n */\n guardGrid<T>(\n node: unknown,\n lv1Full: (n: unknown) => T,\n lv2Grid: (n: unknown) => T,\n lv3Flat: (n: unknown) => T,\n lv4Text: (n: unknown) => T,\n label: string,\n ): { value: T; level: 1 | 2 | 3 | 4 } {\n const levels: [(n: unknown) => T, 1 | 2 | 3 | 4][] = [\n [lv1Full, 1], [lv2Grid, 2], [lv3Flat, 3], [lv4Text, 4],\n ];\n\n for (const [fn, lv] of levels) {\n try {\n const v = fn(node);\n if (v != null) {\n if (lv > 1) this.warn(label, `degraded to level ${lv}`);\n return { value: v, level: lv };\n }\n } catch (e: any) {\n this.warn(label, `Lv${lv} failed: ${e?.message ?? String(e)}`);\n }\n }\n\n this.warn(label, 'ALL LEVELS FAILED — returning lv4Text forced');\n return { value: lv4Text(null), level: 4 };\n }\n\n /** 이미지 안전 파싱 */\n guardImg<T>(\n node: unknown,\n fn: (n: unknown) => T,\n placeholder: (alt: string) => T,\n label: string,\n ): T {\n try {\n const v = fn(node);\n if (v != null) return v;\n } catch (e: any) {\n this.warn(label, e?.message ?? String(e));\n }\n this.warn(label, 'using placeholder image');\n return placeholder(`[이미지 로드 실패: ${label}]`);\n }\n\n private warn(label: string, msg: string): void {\n const w = `[SHIELD] ${label}: ${msg}`;\n console.warn(w);\n this.log.push(w);\n }\n\n flush(): string[] {\n const r = [...this.log];\n this.log = [];\n return r;\n }\n}\n","import type { Align, StrokeKind, Stroke } from '../model/doc-props';\n\n// ─── 단위 변환 ─────────────────────────────────────────────\nexport const Metric = {\n // HWP 세계 (1 inch = 7200 HWPUNIT)\n hwpToPt: (v: number) => v / 100,\n ptToHwp: (v: number) => Math.round(v * 100),\n hwpToDxa: (v: number) => Math.round(v / 5),\n dxaToHwp: (v: number) => Math.round(v * 5),\n hwpToEmu: (v: number) => Math.round(v * 127),\n emuToHwp: (v: number) => Math.round(v / 127),\n\n // DOCX 세계 (1 inch = 1440 dxa, 1 pt = 20 dxa)\n dxaToPt: (v: number) => v / 20,\n ptToDxa: (v: number) => Math.round(v * 20),\n dxaToEmu: (v: number) => Math.round(v * 635),\n emuToDxa: (v: number) => Math.round(v / 635),\n emuToPt: (v: number) => v / 12700,\n ptToEmu: (v: number) => Math.round(v * 12700),\n\n // HWPX charPr height: 1000 = 10pt\n hHeightToPt: (v: number) => v / 100,\n ptToHHeight: (v: number) => Math.round(v * 100),\n\n // DOCX half-point: 24 = 12pt\n halfPtToPt: (v: number) => v / 2,\n ptToHalfPt: (v: number) => Math.round(v * 2),\n} as const;\n\n// ─── 색상 정규화 ───────────────────────────────────────────\nexport function safeHex(raw: string | number | null | undefined): string | undefined {\n if (raw == null) return undefined;\n if (typeof raw === 'number') {\n if (raw <= 0) return '000000';\n if (raw >= 0xFFFFFF) return undefined;\n return raw.toString(16).padStart(6, '0').toUpperCase();\n }\n let s = String(raw).replace(/^#/, '').toUpperCase();\n if (/^[0-9A-F]{3}$/.test(s)) s = s[0] + s[0] + s[1] + s[1] + s[2] + s[2];\n if (/^[0-9A-F]{6}$/.test(s)) return s;\n if (s === 'AUTO' || s === 'NONE' || s === 'TRANSPARENT') return undefined;\n return undefined;\n}\n\n// ─── 정렬 정규화 ───────────────────────────────────────────\nconst ALIGN_MAP: Record<string, Align> = {\n LEFT: 'left', CENTER: 'center', RIGHT: 'right', JUSTIFY: 'justify',\n BOTH: 'justify', DISTRIBUTE: 'justify',\n left: 'left', center: 'center', right: 'right', both: 'justify',\n start: 'left', end: 'right',\n};\nexport function safeAlign(raw?: string): Align {\n return ALIGN_MAP[raw ?? ''] ?? 'left';\n}\n\n// ─── 테두리 정규화 ─────────────────────────────────────────\nconst HWPX_STROKE: Record<string, StrokeKind> = {\n SOLID: \"solid\",\n NONE: \"none\",\n DASH: \"dash\",\n DOT: \"dot\",\n DOUBLE: \"double\",\n LONG_DASH: \"dash\",\n DASH_DOT: \"dashDot\",\n DASH_DOT_DOT: \"dashDotDot\",\n THICK_THIN: \"double\",\n THIN_THICK: \"double\",\n TRIPLE: \"double\",\n};\nconst DOCX_STROKE: Record<string, StrokeKind> = {\n single: \"solid\",\n none: \"none\",\n nil: \"none\",\n dashed: \"dash\",\n dotted: \"dot\",\n double: \"double\",\n dotDash: \"dashDot\",\n dotDotDash: \"dashDotDot\",\n thickThin: \"double\",\n thinThick: \"double\",\n triple: \"double\",\n wave: \"wave\",\n dashDotStroked: \"dashDot\",\n threeDEmboss: \"solid\",\n threeDEngrave: \"solid\",\n};\n\nexport function safeStrokeHwpx(type?: string, w?: number, c?: string): Stroke {\n return {\n kind: HWPX_STROKE[type ?? ''] ?? 'solid',\n pt: w != null ? Metric.hwpToPt(w) : 0.5,\n color: safeHex(c) ?? '000000',\n };\n}\n\nexport function safeStrokeDocx(val?: string, sz?: number, c?: string): Stroke {\n return {\n kind: DOCX_STROKE[val ?? ''] ?? 'solid',\n pt: sz != null ? sz / 8 : 0.5,\n color: safeHex(c) ?? '000000',\n };\n}\n\n// ─── 폰트 정규화 ───────────────────────────────────────────\nconst FONT_MAP: Record<string, string> = {\n // 맑은 고딕 계열\n '맑은 고딕': 'Malgun Gothic',\n '맑은고딕': 'Malgun Gothic',\n // 바탕 계열 (serif)\n '바탕': 'Batang',\n '바탕체': 'BatangChe',\n '한컴바탕': 'Batang',\n '함초롬바탕': 'Batang',\n 'HY신명조': 'Batang',\n 'HY견명조': 'Batang',\n 'HY그래픽': 'Batang',\n '궁서': 'Gungsuh',\n '궁서체': 'GungsuhChe',\n // 고딕 계열 (sans-serif)\n '돋움': 'Dotum',\n '돋움체': 'DotumChe',\n '굴림': 'Gulim',\n '굴림체': 'GulimChe',\n '한컴돋움': 'Malgun Gothic',\n '함초롬돋움': 'Malgun Gothic',\n 'HY견고딕': 'Malgun Gothic',\n 'HY중고딕': 'Malgun Gothic',\n 'HY헤드라인M': 'Malgun Gothic',\n 'HY강B': 'Malgun Gothic',\n 'HY나무M': 'Malgun Gothic',\n 'HY목각파임B': 'Malgun Gothic',\n 'HY엽서M': 'Malgun Gothic',\n 'HY엽서L': 'Malgun Gothic',\n // 나눔 계열\n '나눔고딕': 'Malgun Gothic',\n '나눔명조': 'Batang',\n};\nexport function safeFont(raw?: string): string {\n return FONT_MAP[raw ?? ''] ?? raw ?? 'Malgun Gothic';\n}\n\n// Reverse mapping: English → Korean (for HWPX encoding)\nconst FONT_MAP_KR: Record<string, string> = {\n 'Malgun Gothic': '맑은 고딕',\n 'Batang': '바탕',\n 'Dotum': '돋움',\n 'Gulim': '굴림',\n};\nexport function safeFontToKr(raw?: string): string {\n return FONT_MAP_KR[raw ?? ''] ?? raw ?? '맑은 고딕';\n}\n","import pako from 'pako';\n\ninterface ZipEntry {\n name: string;\n data: Uint8Array;\n}\n\nexport const ArchiveKit = {\n async inflate(compressed: Uint8Array): Promise<Uint8Array> {\n return pako.inflate(compressed);\n },\n\n async deflate(data: Uint8Array): Promise<Uint8Array> {\n return pako.deflate(data, { level: 6 });\n },\n\n async unzip(zipData: Uint8Array): Promise<Map<string, Uint8Array>> {\n const files = new Map<string, Uint8Array>();\n const view = new DataView(zipData.buffer, zipData.byteOffset, zipData.byteLength);\n\n // Find EOCD by scanning backward from end (supports ZIP comment up to 64KB)\n let eocdOffset = -1;\n const searchStart = Math.max(0, zipData.length - 65558);\n for (let i = zipData.length - 22; i >= searchStart; i--) {\n if (view.getUint32(i, true) === 0x06054b50) {\n eocdOffset = i;\n break;\n }\n }\n\n if (eocdOffset !== -1) {\n // Parse central directory — always has correct sizes even with data descriptors\n const entryCount = view.getUint16(eocdOffset + 10, true);\n const centralDirOffset = view.getUint32(eocdOffset + 16, true);\n\n let cdOffset = centralDirOffset;\n for (let i = 0; i < entryCount; i++) {\n if (cdOffset + 46 > zipData.length) break;\n if (view.getUint32(cdOffset, true) !== 0x02014b50) break;\n\n const compressionMethod = view.getUint16(cdOffset + 10, true);\n const compressedSize = view.getUint32(cdOffset + 20, true);\n const uncompressedSize = view.getUint32(cdOffset + 24, true);\n const fileNameLength = view.getUint16(cdOffset + 28, true);\n const extraLength = view.getUint16(cdOffset + 30, true);\n const commentLength = view.getUint16(cdOffset + 32, true);\n const localHeaderOffset = view.getUint32(cdOffset + 42, true);\n\n const nameBytes = zipData.subarray(cdOffset + 46, cdOffset + 46 + fileNameLength);\n const name = new TextDecoder('utf-8').decode(nameBytes);\n cdOffset += 46 + fileNameLength + extraLength + commentLength;\n\n if (name.endsWith('/')) continue; // directory entry\n\n // Read actual data using the local header offset from central directory\n const localFnLen = view.getUint16(localHeaderOffset + 26, true);\n const localExtraLen = view.getUint16(localHeaderOffset + 28, true);\n const dataOffset = localHeaderOffset + 30 + localFnLen + localExtraLen;\n\n let fileData: Uint8Array;\n if (compressionMethod === 0) {\n fileData = zipData.subarray(dataOffset, dataOffset + uncompressedSize);\n } else if (compressionMethod === 8) {\n const compressed = zipData.subarray(dataOffset, dataOffset + compressedSize);\n fileData = pako.inflateRaw(compressed);\n } else {\n throw new Error(`Unsupported ZIP compression method: ${compressionMethod}`);\n }\n\n files.set(name, new Uint8Array(fileData));\n }\n\n return files;\n }\n\n // Fallback: scan local headers sequentially (no EOCD found — truncated ZIP)\n let offset = 0;\n while (offset < zipData.length - 4) {\n const sig = view.getUint32(offset, true);\n\n if (sig === 0x04034b50) {\n const compressionMethod = view.getUint16(offset + 8, true);\n const compressedSize = view.getUint32(offset + 18, true);\n const uncompressedSize = view.getUint32(offset + 22, true);\n const fileNameLength = view.getUint16(offset + 26, true);\n const extraLength = view.getUint16(offset + 28, true);\n\n const nameBytes = zipData.subarray(offset + 30, offset + 30 + fileNameLength);\n const name = new TextDecoder('utf-8').decode(nameBytes);\n\n const dataOffset = offset + 30 + fileNameLength + extraLength;\n let fileData: Uint8Array;\n\n if (compressionMethod === 0) {\n fileData = zipData.subarray(dataOffset, dataOffset + uncompressedSize);\n } else if (compressionMethod === 8) {\n const compressed = zipData.subarray(dataOffset, dataOffset + compressedSize);\n fileData = pako.inflateRaw(compressed);\n } else {\n throw new Error(`Unsupported ZIP compression method: ${compressionMethod}`);\n }\n\n files.set(name, new Uint8Array(fileData));\n offset = dataOffset + compressedSize;\n } else if (sig === 0x02014b50 || sig === 0x06054b50) {\n break;\n } else {\n offset++;\n }\n }\n\n return files;\n },\n\n async zip(entries: ZipEntry[]): Promise<Uint8Array> {\n const localHeaders: Uint8Array[] = [];\n const centralHeaders: Uint8Array[] = [];\n let localOffset = 0;\n\n for (const entry of entries) {\n const nameBytes = new TextEncoder().encode(entry.name);\n const crc = crc32(entry.data);\n\n // 'mimetype' and 'version.xml' must be stored uncompressed per HWPX spec\n const store = entry.name === 'mimetype' || entry.name === 'version.xml';\n const method = store ? 0 : 8;\n const payload = store ? entry.data : pako.deflateRaw(entry.data, { level: 6 });\n\n // Local file header (30 bytes + name + data)\n const local = new Uint8Array(30 + nameBytes.length + payload.length);\n const lv = new DataView(local.buffer);\n lv.setUint32(0, 0x04034b50, true);\n lv.setUint16(4, 20, true);\n lv.setUint16(6, 0, true);\n lv.setUint16(8, method, true);\n lv.setUint16(10, 0, true);\n lv.setUint16(12, 0x0021, true); // date (1980-01-01)\n lv.setUint32(14, crc, true);\n lv.setUint32(18, payload.length, true);\n lv.setUint32(22, entry.data.length, true);\n lv.setUint16(26, nameBytes.length, true);\n lv.setUint16(28, 0, true);\n local.set(nameBytes, 30);\n local.set(payload, 30 + nameBytes.length);\n\n // Central directory header (46 bytes + name)\n const central = new Uint8Array(46 + nameBytes.length);\n const cv = new DataView(central.buffer);\n cv.setUint32(0, 0x02014b50, true);\n cv.setUint16(4, 20, true);\n cv.setUint16(6, 20, true);\n cv.setUint16(8, 0, true);\n cv.setUint16(10, method, true);\n cv.setUint16(12, 0, true); // mod time\n cv.setUint16(14, 0x0021, true); // mod date (1980-01-01)\n cv.setUint32(16, crc, true);\n cv.setUint32(20, payload.length, true);\n cv.setUint32(24, entry.data.length, true);\n cv.setUint16(28, nameBytes.length, true);\n cv.setUint16(30, 0, true);\n cv.setUint16(32, 0, true);\n cv.setUint16(34, 0, true);\n cv.setUint16(36, 0, true);\n cv.setUint32(38, 0, true);\n cv.setUint32(42, localOffset, true);\n central.set(nameBytes, 46);\n\n localHeaders.push(local);\n centralHeaders.push(central);\n localOffset += local.length;\n }\n\n const centralDir = concat(centralHeaders);\n const eocd = new Uint8Array(22);\n const ev = new DataView(eocd.buffer);\n ev.setUint32(0, 0x06054b50, true);\n ev.setUint16(4, 0, true);\n ev.setUint16(6, 0, true);\n ev.setUint16(8, entries.length, true);\n ev.setUint16(10, entries.length, true);\n ev.setUint32(12, centralDir.length, true);\n ev.setUint32(16, localOffset, true);\n ev.setUint16(20, 0, true);\n\n return concat([...localHeaders, centralDir, eocd]);\n },\n};\n\nfunction concat(arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((s, a) => s + a.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const a of arrays) { out.set(a, offset); offset += a.length; }\n return out;\n}\n\nfunction crc32(data: Uint8Array): number {\n let crc = 0xFFFFFFFF;\n for (const byte of data) {\n crc ^= byte;\n for (let i = 0; i < 8; i++) {\n crc = (crc & 1) ? (crc >>> 1) ^ 0xEDB88320 : crc >>> 1;\n }\n }\n return (crc ^ 0xFFFFFFFF) >>> 0;\n}\n","import { SaxesParser } from 'saxes';\n\n// Parses XML into an xml2js-compatible object structure:\n// { tagName: [{ _attr: { k: v }, _text: '...', childTag: [...] }] }\nfunction parseXmlStrict(xml: string): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const parser = new SaxesParser({ xmlns: false });\n\n interface Frame { tag: string; obj: Record<string, unknown> }\n const stack: Frame[] = [];\n let result: unknown = null;\n\n parser.on('error', (err: Error) => reject(err));\n\n parser.on('opentag', (node: any) => {\n const obj: Record<string, unknown> = {};\n const attrs = node.attributes as Record<string, string>;\n if (attrs && Object.keys(attrs).length > 0) {\n obj['_attr'] = { ...attrs };\n }\n stack.push({ tag: node.name as string, obj });\n });\n\n const appendText = (text: string) => {\n if (stack.length > 0 && text) {\n const frame = stack[stack.length - 1];\n const cur = frame.obj['_text'];\n frame.obj['_text'] = typeof cur === 'string' ? cur + text : text;\n }\n };\n\n parser.on('text', (text: string) => appendText(text));\n parser.on('cdata', (cdata: string) => appendText(cdata));\n\n parser.on('closetag', () => {\n const frame = stack.pop();\n if (!frame) return;\n const { tag, obj } = frame;\n\n if (stack.length === 0) {\n result = { [tag]: [obj] };\n } else {\n const parent = stack[stack.length - 1].obj;\n const existing = parent[tag];\n if (Array.isArray(existing)) {\n (existing as unknown[]).push(obj);\n } else {\n parent[tag] = [obj];\n }\n // Track child order for document-order iteration\n if (!parent['_childOrder']) parent['_childOrder'] = [];\n (parent['_childOrder'] as string[]).push(tag);\n }\n });\n\n try {\n parser.write(xml).close();\n resolve(result);\n } catch (e) {\n reject(e);\n }\n });\n}\n\nexport const XmlKit = {\n /** @deprecated Use parseStrict instead */\n async parse(xml: string): Promise<unknown> {\n return parseXmlStrict(xml);\n },\n\n async parseStrict(xml: string): Promise<unknown> {\n return parseXmlStrict(xml);\n },\n\n attr(node: Record<string, unknown>, key: string): string | undefined {\n const a = node['_attr'] as Record<string, string> | undefined;\n return a?.[key];\n },\n\n text(node: Record<string, unknown> | string | undefined): string {\n if (node == null) return '';\n if (typeof node === 'string') return node;\n const t = node['_text'];\n return typeof t === 'string' ? t : '';\n },\n};\n","export const TextKit = {\n decode(data: Uint8Array, encoding = 'utf-8'): string {\n try {\n return new TextDecoder(encoding, { fatal: true }).decode(data);\n } catch {\n return new TextDecoder('utf-8', { fatal: false }).decode(data);\n }\n },\n\n encode(text: string): Uint8Array {\n return new TextEncoder().encode(text);\n },\n\n escapeXml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n },\n\n unescapeXml(s: string): string {\n return s\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&apos;/g, \"'\");\n },\n\n normalizeWhitespace(s: string): string {\n return s.replace(/\\s+/g, ' ').trim();\n },\n\n stripControl(s: string): string {\n // eslint-disable-next-line no-control-regex\n return s.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '');\n },\n\n base64Encode(data: Uint8Array): string {\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n return btoa(binary);\n },\n\n base64Decode(b64: string): Uint8Array {\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n },\n};\n","/**\n * BaseDecoder - 모든 디코더의 기본 클래스\n *\n * 공통 로직을 제공하여 각 포맷별 디코더가 포맷 특유의 로직만 구현하도록 합니다.\n */\n\nimport type { Decoder } from '../contract/decoder';\nimport type { Outcome } from '../contract/result';\nimport type { DocRoot } from '../model/doc-tree';\nimport { TextKit } from '../toolkit/TextKit';\nimport { ArchiveKit } from '../toolkit/ArchiveKit';\n\n// ─── BaseDecoder ───────────────────────────────────\n\nexport abstract class BaseDecoder implements Decoder {\n readonly format: string = this.getFormat();\n readonly aliases: string[] = this.getAliases();\n\n /** 포맷 이름 반환 (하위 클래스에서 오버라이드) */\n protected abstract getFormat(): string;\n\n /** 별칭 목록 반환 (하위 클래스에서 필요 시 오버라이드) */\n protected getAliases(): string[] { return []; }\n\n /** 데이터 디코딩 (하위 클래스에서 오버라이드) */\n abstract decode(data: Uint8Array): Promise<Outcome<DocRoot>>;\n\n // ─── 공통 유틸리티 메서드 ──────────────────────────\n\n /** 바이트를 UTF-8 문자열로 변환 */\n protected bytesToString(data: Uint8Array): string {\n return TextKit.decode(data);\n }\n\n /** 문자열을 UTF-8 바이트로 변환 */\n protected stringToBytes(s: string): Uint8Array {\n return TextKit.encode(s);\n }\n\n /** XML 이스케이프 */\n protected escapeXml(s: string): string {\n return TextKit.escapeXml(s);\n }\n\n /** XML 언이스케이프 */\n protected unescapeXml(s: string): string {\n return TextKit.unescapeXml(s);\n }\n\n /** base64 문자열을 Uint8Array 로 변환 */\n protected base64ToBytes(b64: string): Uint8Array {\n return TextKit.base64Decode(b64);\n }\n\n /** Uint8Array 를 base64 문자열로 변환 */\n protected bytesToBase64(data: Uint8Array): string {\n return TextKit.base64Encode(data);\n }\n\n /** ZIP 해제 */\n protected async unzip(data: Uint8Array): Promise<Map<string, Uint8Array>> {\n return ArchiveKit.unzip(data);\n }\n\n /** ZIP 압축 */\n protected async zip(entries: { name: string; data: Uint8Array }[]): Promise<Uint8Array> {\n return ArchiveKit.zip(entries);\n }\n\n /** inflate 해제 */\n protected async inflate(data: Uint8Array): Promise<Uint8Array> {\n return ArchiveKit.inflate(data);\n }\n\n /** deflate 압축 */\n protected async deflate(data: Uint8Array): Promise<Uint8Array> {\n return ArchiveKit.deflate(data);\n }\n\n /** 제어 문자 제거 */\n protected stripControl(s: string): string {\n return TextKit.stripControl(s);\n }\n\n /** 공백 정규화 */\n protected normalizeWhitespace(s: string): string {\n return TextKit.normalizeWhitespace(s);\n }\n\n /** XML 파싱 (DOMParser 사용) */\n protected parseXml(xmlString: string): Document {\n const parser = new DOMParser();\n return parser.parseFromString(xmlString, 'text/xml');\n }\n\n /** XML 요소에서 텍스트 내용 추출 */\n protected getTextContent(element: Element | null | undefined): string {\n if (!element) return '';\n return element.textContent ?? '';\n }\n\n /** XML 요소의 속성 값 추출 */\n protected getAttr(element: Element | null | undefined, name: string): string | null {\n return element?.getAttribute(name) ?? null;\n }\n\n /** XML 요소의 자식 요소 찾기 */\n protected getChild(element: Element | null | undefined, tagName: string): Element | null {\n if (!element) return null;\n return element.querySelector(`>${tagName}`) ?? null;\n }\n\n /** XML 요소의 모든 자식 요소 찾기 */\n protected getChildren(element: Element | null | undefined, tagName: string): Element[] {\n if (!element) return [];\n return Array.from(element.querySelectorAll(`>${tagName}`));\n }\n}\n","/**\n * HWPX 인코더 관련 상수\n *\n * HWPX 파일 생성에 필요한 모든 설정값을 한곳에 모아 관리합니다.\n * 초중급 개발자도 쉽게 수정할 수 있도록 명확한 주석을 포함했습니다.\n */\n\n// ==================== 파일 형식 관련 ====================\n\n/** HWPX 파일의 MIME 타입 (ZIP 파일 내 mimetype 파일에 저장됨) */\nexport const HWPX_MIME_TYPE = \"application/hwp+zip\";\n\n/** HWPX 파일의 버전 */\nexport const HWPX_VERSION = \"1.2\";\n\n// ==================== XML 네임스페이스 ====================\n\n/** HWPX XML 문서에서 사용되는 네임스페이스 */\nexport const NAMESPACES = {\n /** Hancom 문서 네임스페이스 */\n HANCOM: \"http://www.hancom.co.kr/hwp/xml\",\n /** Hancom 공통 네임스페이스 */\n HANCOM_COMMON: \"http://www.hancom.co.kr/hwp/xml/common\",\n /** Hancom 버전 네임스페이스 */\n HANCOM_VERSION: \"http://www.hancom.co.kr/hwp/xml/version\",\n /** Hancom 속성 네임스페이스 */\n HANCOM_PROP: \"http://www.hancom.co.kr/hwp/xml/property\",\n} as const;\n\n/** XML 헤더에 포함될 네임스페이스 선언 문자열 */\nexport const NAMESPACE_DECLARATIONS = {\n HEAD: `xmlns:hh=\"${NAMESPACES.HANCOM}\" xmlns:hc=\"${NAMESPACES.HANCOM_COMMON}\" xmlns:hv=\"${NAMESPACES.HANCOM_VERSION}\" xmlns:hp=\"${NAMESPACES.HANCOM_PROP}\"`,\n SECTION: `xmlns:hs=\"${NAMESPACES.HANCOM}\" xmlns:hp=\"${NAMESPACES.HANCOM_PROP}\"`,\n} as const;\n\n// ==================== 단위 변환 ====================\n\n/** 1 포인트 (pt) 를 HWPUNIT 으로 변환한 값 (HWPX 내부 단위) */\nexport const HWPUNIT_PER_PT = 1000;\n\n/** 1 인치 (inch) 를 포인트 (pt) 로 변환한 값 */\nexport const PT_PER_INCH = 72;\n\n/** 1 인치 (inch) 를 픽셀로 변환한 값 (표준 96 DPI 기준) */\nexport const PIXELS_PER_INCH = 96;\n\n/** 픽셀을 포인트로 변환하는 계수 */\nexport const PT_PER_PIXEL = PT_PER_INCH / PIXELS_PER_INCH; // 0.75\n\n// ==================== 페이지 크기 (A4 기준) ====================\n\n/** A4 용지 너비 (포인트) */\nexport const A4_WIDTH_PT = 794;\n\n/** A4 용지 높이 (포인트) */\nexport const A4_HEIGHT_PT = 1123;\n\n/** A4 용지 상단 여백 (포인트) */\nexport const A4_TOP_MARGIN_PT = 72;\n\n/** A4 용지 하단 여백 (포인트) */\nexport const A4_BOTTOM_MARGIN_PT = 72;\n\n/** A4 용지 왼쪽 여백 (포인트) */\nexport const A4_LEFT_MARGIN_PT = 83;\n\n/** A4 용지 오른쪽 여백 (포인트) */\nexport const A4_RIGHT_MARGIN_PT = 83;\n\n/** A4 용지 상단 머리글 영역 (포인트) */\nexport const A4_HEADER_MARGIN_PT = 40;\n\n/** A4 용지 하단 바닥글 영역 (포인트) */\nexport const A4_FOOTER_MARGIN_PT = 40;\n\n// ==================== 폰트 관련 ====================\n\n/** 기본 한글 폰트 */\nexport const DEFAULT_KOREAN_FONT = \"Batang\";\n\n/** 기본 영문 폰트 */\nexport const DEFAULT_LATIN_FONT = \"Arial\";\n\n/** 기본 폰트 크기 (포인트) */\nexport const DEFAULT_FONT_SIZE_PT = 10;\n\n// ==================== 줄 간격 ====================\n\n/** 기본 줄 간격 (폰트 크기의 %) */\nexport const DEFAULT_LINE_SPACING_PERCENT = 160;\n\n/** 최소 줄 간격 (HWPUNIT) */\nexport const MIN_LINE_SPACING_HWPUNIT = 1000;\n\n// ==================== 스타일 ID ====================\n\n/** 바탕글 스타일 ID */\nexport const STYLE_ID_BATANGGUL = \"0\";\n\n/** 개요 1 스타일 ID */\nexport const STYLE_ID_GYEYOE1 = \"1\";\n\n/** 개요 2 스타일 ID */\nexport const STYLE_ID_GYEYOE2 = \"2\";\n\n// ==================== 이미지 관련 ====================\n\n/** 이미지 파일이 저장될 디렉토리 경로 (ZIP 내) */\nexport const IMAGE_DIR_PATH = \"image/\";\n\n/** 이미지 파일명 접미사 */\nexport const IMAGE_FILE_EXTENSION = \".png\";\n\n// ==================== 테이블 관련 ====================\n\n/** 테이블 테두리 기본 두께 (HWPUNIT) */\nexport const TABLE_BORDER_WIDTH_HWPUNIT = 500; // 0.5pt\n\n/** 테이블 셀 기본 패딩 (HWPUNIT) */\nexport const TABLE_CELL_PADDING_HWPUNIT = 200; // 0.2pt\n\n// ==================== 색상 코드 ====================\n\n/** 검정색 (hex) */\nexport const COLOR_BLACK = \"#000000\";\n\n/** 흰색 (hex) */\nexport const COLOR_WHITE = \"#FFFFFF\";\n\n/** 회색 (워터마크용) */\nexport const COLOR_GRAY = \"#CCCCCC\";\n\n/** 코드 블록 배경색 */\nexport const COLOR_CODE_BLOCK_BG = \"#f4f4f4\";\n\n// ==================== ZIP 파일 구조 ====================\n\n/** HWPX 파일 내 파일 목록 */\nexport const HWPX_FILE_STRUCTURE = [\n { name: \"mimetype\", mimeType: \"\" },\n { name: \".hwpversions/version.xml\", mimeType: \"application/xml\" },\n { name: \"header.xml\", mimeType: \"application/xml\" },\n { name: \"section0.xml\", mimeType: \"application/xml\" },\n { name: \"content.hpf\", mimeType: \"application/octet-stream\" },\n] as const;\n\n/** ZIP 파일 생성 시 사용할 압축 레벨 (0=압축안함, 9=최대압축) */\nexport const ZIP_COMPRESSION_LEVEL = 9;\n","import type {\n DocRoot,\n ContentNode,\n ParaNode,\n SpanNode,\n GridNode,\n ImgNode,\n PageNumNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport type {\n DocMeta,\n PageDims,\n TextProps,\n ParaProps,\n CellProps,\n GridProps,\n Stroke,\n ImgLayout,\n ImgWrap,\n ImgHorzAlign,\n ImgVertAlign,\n ImgHorzRelTo,\n ImgVertRelTo,\n} from \"../../model/doc-props\";\nimport { A4 } from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport {\n buildRoot,\n buildSheet,\n buildPara,\n buildSpan,\n buildImg,\n buildGrid,\n buildRow,\n buildCell,\n buildPb,\n} from \"../../model/builders\";\nimport { ShieldedParser } from \"../../safety/ShieldedParser\";\nimport {\n Metric,\n safeAlign,\n safeFont,\n safeHex,\n safeStrokeHwpx,\n} from \"../../safety/StyleBridge\";\nimport { ArchiveKit } from \"../../toolkit/ArchiveKit\";\nimport { XmlKit } from \"../../toolkit/XmlKit\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { registry } from \"../../pipeline/registry\";\nimport { BaseDecoder } from \"../../core/BaseDecoder\";\nimport { HWPX_MIME_TYPE } from \"../../encoders/hwpx/constants\";\n\ninterface BorderFillInfo {\n stroke?: Stroke; // uniform fallback (used when all sides are the same)\n top?: Stroke;\n right?: Stroke;\n bottom?: Stroke;\n left?: Stroke;\n bgColor?: string;\n}\n\ninterface CharPrInfo {\n b?: boolean;\n i?: boolean;\n u?: boolean;\n s?: boolean;\n pt?: number;\n color?: string;\n font?: string;\n bg?: string;\n}\n\ninterface ParaPrInfo {\n align?: string;\n indentPt?: number; // hc:left → 문단 전체 왼쪽 여백\n indentRightPt?: number; // hc:right → 문단 전체 오른쪽 여백\n firstLineIndentPt?: number; // hc:indent → 첫 줄 들여쓰기 (양수=들여쓰기, 음수=내어쓰기)\n spaceBefore?: number;\n spaceAfter?: number;\n lineHeight?: number;\n lineHeightFixed?: number; // FIXED 행 높이 (pt)\n}\n\ninterface DecCtx {\n files: Map<string, Uint8Array>;\n shield: ShieldedParser;\n borderFills: Map<number, BorderFillInfo>;\n charPrs: Map<number, CharPrInfo>;\n paraPrs: Map<number, ParaPrInfo>;\n warns: string[];\n}\n\nexport class HwpxDecoder extends BaseDecoder {\n protected getFormat(): string {\n return \"hwpx\";\n }\n protected getAliases(): string[] {\n return [HWPX_MIME_TYPE, \"application/hwp+zip\"];\n }\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n const files = await ArchiveKit.unzip(data);\n\n const sectionFiles: Uint8Array[] = [];\n for (let i = 0; ; i++) {\n const sec =\n files.get(`Contents/section${i}.xml`) ?? files.get(`section${i}.xml`);\n if (!sec) break;\n sectionFiles.push(sec);\n }\n if (sectionFiles.length === 0) {\n const fallback = findSectionFile(files);\n if (fallback) sectionFiles.push(fallback);\n }\n\n if (sectionFiles.length === 0)\n return fail(\"HWPX: No section files found\");\n\n const headXml =\n files.get(\"Contents/header.xml\") ?? files.get(\"header.xml\");\n\n let meta: DocMeta = {};\n let dims: PageDims = { ...A4 };\n let borderFills = new Map<number, BorderFillInfo>();\n let charPrs = new Map<number, CharPrInfo>();\n let paraPrs = new Map<number, ParaPrInfo>();\n\n if (headXml) {\n try {\n const headStr = TextKit.decode(headXml);\n const headObj: any = await XmlKit.parseStrict(headStr);\n if (headObj) {\n meta = extractMeta(headObj);\n dims = extractDims(headObj) ?? dims;\n borderFills = extractBorderFills(headObj);\n charPrs = extractCharPrs(headObj);\n paraPrs = extractParaPrs(headObj);\n }\n } catch {\n // header parse failure is non-fatal\n }\n }\n\n const ctx: DecCtx = {\n files,\n shield,\n borderFills,\n charPrs,\n paraPrs,\n warns,\n };\n\n const allSections: any[] = [];\n for (const secFile of sectionFiles) {\n const bodyStr = TextKit.decode(secFile);\n const bodyObj: any = await XmlKit.parseStrict(bodyStr);\n allSections.push(...normalizeSections(bodyObj));\n }\n\n const kids = shield.guardAll(\n allSections,\n (sec: any) => decodeSection(sec, dims, ctx),\n () => buildSheet([buildPara([buildSpan(\"[섹션 파싱 실패]\")])], dims),\n \"hwpx:section\",\n );\n\n warns.push(...shield.flush());\n return succeed(buildRoot(meta, kids), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`HWPX decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\n// ─── helpers ────────────────────────────────────────────────\n\nfunction findSectionFile(\n files: Map<string, Uint8Array>,\n): Uint8Array | undefined {\n for (const [key, val] of files) {\n if (key.toLowerCase().includes(\"section\") && key.endsWith(\".xml\"))\n return val;\n }\n return undefined;\n}\n\nfunction normalizeSections(bodyObj: any): any[] {\n // <hs:sec> (real HWPX), <hp:SEC> (legacy)\n if (bodyObj?.[\"hs:sec\"]) return toArr(bodyObj[\"hs:sec\"]);\n if (bodyObj?.[\"hp:SEC\"]) return toArr(bodyObj[\"hp:SEC\"]);\n\n const root = bodyObj?.[\"hp:HWPML\"] ?? bodyObj?.HWPML ?? bodyObj;\n const body =\n root?.[\"hp:BODY\"]?.[0] ??\n root?.BODY?.[0] ??\n root?.[\"hp:BODY\"] ??\n root?.BODY;\n if (!body) return [bodyObj];\n const sections = body?.[\"hp:SECTION\"] ?? body?.SECTION ?? [];\n return Array.isArray(sections) ? sections : [sections];\n}\n\n// Get a tag regardless of namespace/case variations\nfunction getTag(obj: any, ...names: string[]): any[] {\n for (const n of names) {\n const v = obj?.[n];\n if (v != null) return toArr(v);\n }\n return [];\n}\n\nfunction extractMeta(headObj: any): DocMeta {\n try {\n // Support both <hh:HEAD> and <hh:head>\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const info = root?.[\"hh:DOCSUMMARY\"]?.[0] ?? root?.DOCSUMMARY?.[0];\n if (!info) return {};\n const a = (k: string) =>\n info?.[`hh:${k}`]?.[0]?._text ?? info?.[k]?.[0]?._text ?? \"\";\n return {\n title: a(\"TITLE\") || undefined,\n author: a(\"AUTHOR\") || undefined,\n subject: a(\"SUBJECT\") || undefined,\n };\n } catch {\n return {};\n }\n}\n\nfunction extractDims(headObj: any): PageDims | null {\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return null;\n\n const secPrList =\n refList?.[\"hh:SECPRLST\"]?.[0]?.[\"hh:SECPR\"] ??\n refList?.SECPRLST?.[0]?.SECPR;\n const sec = Array.isArray(secPrList) ? secPrList[0] : secPrList;\n if (!sec) return null;\n\n const pa =\n sec?.[\"hh:PAGEPROPERTY\"]?.[0]?._attr ?? sec?.PAGEPROPERTY?.[0]?._attr;\n if (!pa) return null;\n\n const ew = Number(pa.Width ?? 59528);\n const eh = Number(pa.Height ?? 84188);\n return {\n wPt: Metric.hwpToPt(ew),\n hPt: Metric.hwpToPt(eh),\n mt: Metric.hwpToPt(Number(pa.TopMargin ?? 5670)),\n mb: Metric.hwpToPt(Number(pa.BottomMargin ?? 4252)),\n ml: Metric.hwpToPt(Number(pa.LeftMargin ?? 8504)),\n mr: Metric.hwpToPt(Number(pa.RightMargin ?? 8504)),\n orient: ew > eh ? \"landscape\" : \"portrait\",\n };\n } catch {\n return null;\n }\n}\n\nfunction extractBorderFills(headObj: any): Map<number, BorderFillInfo> {\n const map = new Map<number, BorderFillInfo>();\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return map;\n\n const bfList =\n refList?.[\"hh:borderFills\"]?.[0] ??\n refList?.[\"hh:BORDERFILLLIST\"]?.[0] ??\n refList?.BORDERFILLLIST?.[0];\n if (!bfList) return map;\n\n const bfs = getTag(bfList, \"hh:borderFill\", \"hh:BORDERFILL\");\n for (const bf of bfs) {\n const attr = bf?._attr ?? {};\n const id = Number(attr.id ?? 0);\n if (id === 0) continue;\n\n const info: BorderFillInfo = {};\n\n // Helper: parse a border element into a Stroke\n const parseBorderEl = (el: any): Stroke | undefined => {\n if (!el) return undefined;\n const a = el?._attr ?? {};\n const mmVal = parseFloat(a.width) || undefined;\n const hwpVal = mmVal != null ? mmVal * 2.835 * 100 : undefined;\n return safeStrokeHwpx(a.type, hwpVal, a.color);\n };\n\n // Parse all four sides\n const topEl =\n bf?.[\"hh:topBorder\"]?.[0] ?? bf?.[\"hh:top\"]?.[0] ?? bf?.top?.[0];\n const rightEl =\n bf?.[\"hh:rightBorder\"]?.[0] ?? bf?.[\"hh:right\"]?.[0] ?? bf?.right?.[0];\n const bottomEl =\n bf?.[\"hh:bottomBorder\"]?.[0] ??\n bf?.[\"hh:bottom\"]?.[0] ??\n bf?.bottom?.[0];\n const leftEl =\n bf?.[\"hh:leftBorder\"]?.[0] ?? bf?.[\"hh:left\"]?.[0] ?? bf?.left?.[0];\n\n info.top = parseBorderEl(topEl);\n info.right = parseBorderEl(rightEl);\n info.bottom = parseBorderEl(bottomEl);\n info.left = parseBorderEl(leftEl);\n\n // Set uniform stroke fallback = top border (for defaultStroke etc.)\n info.stroke = info.top ?? info.left ?? info.right ?? info.bottom;\n\n // Parse fill (real HWPX uses hc:fillBrush, not hh:fillBrush)\n const fillBrush =\n bf?.[\"hc:fillBrush\"]?.[0] ??\n bf?.[\"hh:fillBrush\"]?.[0] ??\n bf?.[\"hh:fill\"]?.[0] ??\n bf?.fill?.[0] ??\n bf?.fillBrush?.[0];\n if (fillBrush) {\n const winBrush =\n fillBrush?.[\"hc:winBrush\"]?.[0]?._attr ??\n fillBrush?.[\"hh:winBrush\"]?.[0]?._attr ??\n fillBrush?.winBrush?.[0]?._attr;\n if (winBrush?.faceColor && winBrush.faceColor !== \"none\") {\n info.bgColor = safeHex(winBrush.faceColor);\n }\n }\n\n map.set(id, info);\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\nfunction buildFontIdMap(headObj: any): Map<number, string> {\n const fontMap = new Map<number, string>();\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return fontMap;\n\n const fontfaces =\n refList?.[\"hh:fontfaces\"]?.[0] ?? refList?.[\"hh:FONTFACES\"]?.[0];\n if (!fontfaces) return fontMap;\n\n // Try each fontface group (HANGUL, LATIN, etc.) — use the first group that has entries\n const ffGroups = getTag(fontfaces, \"hh:fontface\", \"hh:FONTFACE\");\n for (const ff of ffGroups) {\n const fonts = getTag(ff, \"hh:font\", \"hh:FONT\");\n for (const font of fonts) {\n const fa = font?._attr ?? {};\n const fid = Number(fa.id ?? -1);\n const name = fa.face ?? fa.name ?? fa.Face ?? \"\";\n if (fid >= 0 && name && !fontMap.has(fid)) fontMap.set(fid, name);\n }\n if (fontMap.size > 0) break; // use first group (usually HANGUL)\n }\n } catch {\n /* non-fatal */\n }\n return fontMap;\n}\n\nfunction extractCharPrs(headObj: any): Map<number, CharPrInfo> {\n const map = new Map<number, CharPrInfo>();\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return map;\n\n // Build font id → name map from fontfaces\n const fontIdMap = buildFontIdMap(headObj);\n\n const cpList =\n refList?.[\"hh:charProperties\"]?.[0] ??\n refList?.[\"hh:CHARPROPERTIES\"]?.[0];\n if (!cpList) return map;\n\n const cps = getTag(cpList, \"hh:charPr\", \"hh:CHARPR\");\n for (const cp of cps) {\n const attr = cp?._attr ?? {};\n const id = Number(attr.id ?? -1);\n if (id < 0) continue;\n\n const info: CharPrInfo = {};\n\n // height → pt\n if (attr.height) info.pt = Metric.hHeightToPt(Number(attr.height));\n\n // textColor\n if (attr.textColor) info.color = safeHex(attr.textColor);\n\n // bold\n if (cp?.[\"hh:bold\"]?.[0] != null) info.b = true;\n\n // italic\n if (cp?.[\"hh:italic\"]?.[0] != null) info.i = true;\n\n // underline\n const ulAttr = cp?.[\"hh:underline\"]?.[0]?._attr;\n if (ulAttr?.type && ulAttr.type !== \"NONE\") info.u = true;\n\n // strikeout — shape=\"3D\" is default \"no strikeout\" in real HWPX; only SOLID/etc means active\n const stAttr = cp?.[\"hh:strikeout\"]?.[0]?._attr;\n if (stAttr?.shape && stAttr.shape !== \"NONE\" && stAttr.shape !== \"3D\")\n info.s = true;\n\n // font name — resolve from fontRef.hangul → fontfaces\n const fontRefAttr =\n cp?.[\"hh:fontRef\"]?.[0]?._attr ?? cp?.[\"hh:FONTREF\"]?.[0]?._attr;\n if (fontRefAttr) {\n const fid = Number(\n fontRefAttr.hangul ?? fontRefAttr.latin ?? fontRefAttr.Hangul ?? 0,\n );\n const name = fontIdMap.get(fid);\n if (name) info.font = safeFont(name);\n }\n\n map.set(id, info);\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\nfunction extractParaPrs(headObj: any): Map<number, ParaPrInfo> {\n const map = new Map<number, ParaPrInfo>();\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return map;\n\n const ppList =\n refList?.[\"hh:paraProperties\"]?.[0] ??\n refList?.[\"hh:PARAPROPERTIES\"]?.[0];\n if (!ppList) return map;\n\n const pps = getTag(ppList, \"hh:paraPr\", \"hh:PARAPR\");\n for (const pp of pps) {\n const attr = pp?._attr ?? {};\n const id = Number(attr.id ?? -1);\n if (id < 0) continue;\n\n const alignNode =\n pp?.[\"hh:align\"]?.[0]?._attr ?? pp?.[\"hh:ALIGN\"]?.[0]?._attr;\n const align = alignNode?.horizontal ?? alignNode?.Horizontal;\n\n // Read margin and lineSpacing from direct child OR hp:switch > hp:default/hp:case\n let marginEl = pp?.[\"hh:margin\"]?.[0] ?? null;\n let lineSpEl = pp?.[\"hh:lineSpacing\"]?.[0] ?? null;\n if (!marginEl) {\n const sw = pp?.[\"hp:switch\"]?.[0];\n const container = sw?.[\"hp:default\"]?.[0] ?? sw?.[\"hp:case\"]?.[0];\n marginEl = container?.[\"hh:margin\"]?.[0] ?? null;\n lineSpEl = lineSpEl ?? container?.[\"hh:lineSpacing\"]?.[0] ?? null;\n }\n\n let indentPt: number | undefined;\n let indentRightPt: number | undefined;\n let firstLineIndentPt: number | undefined;\n let spaceBefore: number | undefined;\n let spaceAfter: number | undefined;\n let lineHeight: number | undefined;\n let lineHeightFixed: number | undefined;\n\n if (marginEl) {\n // OWPML §7.5.4.4: hc:left=전체왼쪽여백, hc:right=전체오른쪽여백,\n // hc:indent=첫줄들여쓰기(양수)/내어쓰기(음수)\n // hc:intent는 자사 인코더가 생성하는 오기 표기로, hc:indent와 동일하게 처리\n const leftEl = marginEl?.[\"hc:left\"]?.[0];\n const rightEl = marginEl?.[\"hc:right\"]?.[0];\n const indentEl =\n marginEl?.[\"hc:intent\"]?.[0] ?? marginEl?.[\"hc:indent\"]?.[0];\n const prevEl = marginEl?.[\"hc:prev\"]?.[0];\n const nextEl = marginEl?.[\"hc:next\"]?.[0];\n\n const leftVal = Number(leftEl?._attr?.value ?? 0);\n const rightVal = Number(rightEl?._attr?.value ?? 0);\n const indentVal = Number(indentEl?._attr?.value ?? 0);\n const prevVal = Number(prevEl?._attr?.value ?? 0);\n const nextVal = Number(nextEl?._attr?.value ?? 0);\n\n if (leftVal !== 0) indentPt = Metric.hwpToPt(leftVal);\n if (rightVal !== 0) indentRightPt = Metric.hwpToPt(rightVal);\n if (indentVal !== 0) firstLineIndentPt = Metric.hwpToPt(indentVal);\n if (prevVal > 0) spaceBefore = Metric.hwpToPt(prevVal);\n if (nextVal > 0) spaceAfter = Metric.hwpToPt(nextVal);\n }\n\n if (lineSpEl) {\n const lsAttr = lineSpEl._attr ?? {};\n const lsType = lsAttr.type ?? \"PERCENT\";\n const lsVal = Number(lsAttr.value ?? 160);\n // OWPML §7.5.4.6: PERCENT(비율), FIXED(고정), BETWEEN_LINE(줄간격), AT_LEAST(최소)\n if (lsType === \"PERCENT\" && lsVal > 0 && lsVal !== 160) {\n lineHeight = lsVal / 100;\n } else if (lsType === \"FIXED\" && lsVal > 0) {\n // FIXED: 값이 HWPUNIT 단위의 고정 줄 높이\n lineHeightFixed = Metric.hwpToPt(lsVal);\n }\n }\n\n map.set(id, {\n align,\n indentPt,\n indentRightPt,\n firstLineIndentPt,\n spaceBefore,\n spaceAfter,\n lineHeight,\n lineHeightFixed,\n });\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\n// ─── Section decoding ──────────────────────────────────────\n\nfunction addParaItems(p: any, items: { type: string; node: any }[]): void {\n // Check if this paragraph contains a table in its runs\n const runs = getTag(p, \"hp:run\", \"hp:RUN\");\n let hasTable = false;\n for (const run of runs) {\n const tbls = getTag(run, \"hp:tbl\", \"hp:TABLE\");\n if (tbls.length > 0) {\n for (const tbl of tbls) {\n items.push({ type: \"table\", node: tbl });\n }\n hasTable = true;\n }\n }\n // 테이블을 포함한 단락은 일반 단락으로 다시 추가하지 않음 (중복 방지)\n if (!hasTable) {\n items.push({ type: \"para\", node: p });\n }\n}\n\nfunction decodeSection(sec: any, dims: PageDims, ctx: DecCtx) {\n // Try to extract dims from first paragraph's secPr\n const firstParas = getTag(sec, \"hp:p\", \"hp:P\");\n const pageDims = extractSecPrDims(firstParas[0]) ?? dims;\n\n // Build items list preserving document order via _childOrder\n const items: { type: string; node: any }[] = [];\n const paras = getTag(sec, \"hp:p\", \"hp:P\");\n const tbls = getTag(sec, \"hp:tbl\", \"hp:TABLE\");\n\n const childOrder = sec?.[\"_childOrder\"] as string[] | undefined;\n\n if (Array.isArray(childOrder)) {\n let pi = 0;\n let ti = 0;\n for (const tag of childOrder) {\n if ((tag === \"hp:p\" || tag === \"hp:P\") && pi < paras.length) {\n addParaItems(paras[pi++], items);\n } else if ((tag === \"hp:tbl\" || tag === \"hp:TABLE\") && ti < tbls.length) {\n items.push({ type: \"table\", node: tbls[ti++] });\n }\n }\n // Append any remaining (fallback)\n while (pi < paras.length) addParaItems(paras[pi++], items);\n while (ti < tbls.length) items.push({ type: \"table\", node: tbls[ti++] });\n } else {\n // No order info — process paragraphs sequentially (fallback to previous logic)\n for (const p of paras) addParaItems(p, items);\n // Note: direct tables are appended after paras in this fallback\n for (const t of tbls) items.push({ type: \"table\", node: t });\n }\n\n const kids: ContentNode[] = ctx.shield.guardAll(\n items,\n (item: any) => {\n if (item.type === \"table\") {\n try {\n const { value } = ctx.shield.guardGrid(\n item.node,\n (n) => decodeGrid(n, ctx),\n (n) => decodeGridSimple(n, ctx),\n (n) => decodeGridFlat(n),\n (n) => decodeGridText(n) as unknown as GridNode,\n \"hwpx:table\",\n );\n return value;\n } catch {\n return buildPara([buildSpan(\"[표 파싱 실패]\")]);\n }\n }\n return decodePara(item.node, ctx);\n },\n () => buildPara([buildSpan(\"[파싱 실패]\")]),\n \"hwpx:content\",\n );\n\n // Decode header/footer\n const headerParas = decodeHeaderFooter(sec, \"header\", ctx);\n const footerParas = decodeHeaderFooter(sec, \"footer\", ctx);\n\n return buildSheet(kids.filter(Boolean) as ContentNode[], pageDims, {\n headers: { default: headerParas },\n footers: { default: footerParas },\n });\n}\n\nfunction parseSecPrDims(secPr: any): PageDims | null {\n const pagePr =\n secPr?.[\"hp:pagePr\"]?.[0]?._attr ?? secPr?.[\"hp:PAGEPR\"]?.[0]?._attr;\n if (!pagePr) return null;\n const margin =\n secPr?.[\"hp:pagePr\"]?.[0]?.[\"hp:margin\"]?.[0]?._attr ??\n secPr?.[\"hp:PAGEPR\"]?.[0]?.[\"hp:MARGIN\"]?.[0]?._attr ??\n {};\n const pw = Number(pagePr.width ?? 59528);\n const ph = Number(pagePr.height ?? 84188);\n return {\n wPt: Metric.hwpToPt(pw),\n hPt: Metric.hwpToPt(ph),\n mt: Metric.hwpToPt(Number(margin.top ?? 5670)),\n mb: Metric.hwpToPt(Number(margin.bottom ?? 4252)),\n ml: Metric.hwpToPt(Number(margin.left ?? 8504)),\n mr: Metric.hwpToPt(Number(margin.right ?? 8504)),\n orient: pw > ph ? \"landscape\" : \"portrait\",\n };\n}\n\nfunction extractSecPrDims(p: any): PageDims | null {\n if (!p) return null;\n try {\n // Primary: hp:secPr is a DIRECT child of hp:p (as generated by HwpxEncoder)\n const secPrDirect = p?.[\"hp:secPr\"]?.[0] ?? p?.[\"hp:SECPR\"]?.[0];\n if (secPrDirect) {\n const dims = parseSecPrDims(secPrDirect);\n if (dims) return dims;\n }\n // Fallback: legacy format may nest hp:secPr inside hp:run\n const runs = getTag(p, \"hp:run\", \"hp:RUN\");\n for (const run of runs) {\n const secPr = run?.[\"hp:secPr\"]?.[0] ?? run?.[\"hp:SECPR\"]?.[0];\n if (!secPr) continue;\n const dims = parseSecPrDims(secPr);\n if (dims) return dims;\n }\n } catch {\n /* ignore */\n }\n return null;\n}\n\nfunction decodeHeaderFooter(\n sec: any,\n kind: \"header\" | \"footer\",\n ctx: DecCtx,\n): ParaNode[] | undefined {\n try {\n const hf =\n sec?.[\"hp:headerFooter\"]?.[0] ??\n sec?.[\"hp:HEADERFOOTER\"]?.[0] ??\n sec?.headerFooter?.[0] ??\n sec?.HEADERFOOTER?.[0];\n if (!hf) return undefined;\n\n const part =\n hf?.[\"hp:\" + kind]?.[0] ??\n hf?.[\"hp:\" + kind.toUpperCase()]?.[0] ??\n hf?.[kind]?.[0] ??\n hf?.[kind.toUpperCase()]?.[0];\n if (!part) return undefined;\n\n const paras = getTag(part, \"hp:p\", \"hp:P\");\n if (paras.length === 0) return undefined;\n\n return paras.map((p: any) => decodePara(p, ctx));\n } catch {\n return undefined;\n }\n}\n\n// ─── Paragraph & run decoding ──────────────────────────────\n\nfunction decodePara(p: any, ctx: DecCtx): ParaNode {\n const pAttr = p?._attr ?? {};\n const paraPrIdRef = Number(pAttr.paraPrIDRef ?? -1);\n\n // Resolve paraPr from IDRef or inline\n let align: string | undefined;\n const paraPrDef = ctx.paraPrs.get(paraPrIdRef);\n if (paraPrDef?.align) align = paraPrDef.align;\n\n // Check inline PARAPR too\n const inlineParaPr =\n p?.[\"hp:PARAPR\"]?.[0] ?? p?.[\"hp:paraPr\"]?.[0] ?? p?.PARAPR?.[0];\n if (inlineParaPr) {\n const alignNode =\n inlineParaPr?.[\"hp:ALIGN\"]?.[0]?._attr ??\n inlineParaPr?.[\"hp:align\"]?.[0]?._attr ??\n inlineParaPr?.ALIGN?.[0]?._attr;\n if (alignNode?.Type) align = alignNode.Type;\n if (alignNode?.horizontal) align = alignNode.horizontal;\n }\n\n const inlineAttr = inlineParaPr?._attr ?? {};\n const props: ParaProps = { align: safeAlign(align) };\n\n // Apply spacing/indent/lineHeight from paraPr definition\n if (paraPrDef) {\n if (paraPrDef.indentPt !== undefined) props.indentPt = paraPrDef.indentPt;\n if (paraPrDef.indentRightPt !== undefined)\n props.indentRightPt = paraPrDef.indentRightPt;\n if (paraPrDef.firstLineIndentPt !== undefined)\n props.firstLineIndentPt = paraPrDef.firstLineIndentPt;\n if (paraPrDef.spaceBefore !== undefined)\n props.spaceBefore = paraPrDef.spaceBefore;\n if (paraPrDef.spaceAfter !== undefined)\n props.spaceAfter = paraPrDef.spaceAfter;\n if (paraPrDef.lineHeight !== undefined)\n props.lineHeight = paraPrDef.lineHeight;\n if (paraPrDef.lineHeightFixed !== undefined)\n props.lineHeightFixed = paraPrDef.lineHeightFixed;\n }\n\n // List support (from inline attr)\n if (inlineAttr.listType) {\n props.listOrd =\n inlineAttr.listType === \"DIGIT\" || inlineAttr.listType === \"DECIMAL\";\n props.listLv = Number(inlineAttr.listLevel ?? 0);\n }\n\n const runs = getTag(p, \"hp:run\", \"hp:RUN\");\n const kids: (SpanNode | ImgNode)[] = [];\n\n // Helper: collect hp:pic elements from a container (direct child OR inside hp:ctrl)\n const collectPics = (container: any): any[] => {\n const direct = getTag(container, \"hp:pic\", \"hp:PIC\");\n const ctrls = getTag(container, \"hp:ctrl\", \"hp:CTRL\");\n const nested = ctrls.flatMap((c: any) => getTag(c, \"hp:pic\", \"hp:PIC\"));\n return [...direct, ...nested];\n };\n\n // Images that are direct children of <hp:p> (common in table cells and floats)\n for (const pic of collectPics(p)) {\n const img = decodePic(pic, ctx);\n if (img) kids.push(img);\n }\n\n for (const run of runs) {\n // Images: directly in run OR in run→ctrl (both patterns appear in practice)\n for (const pic of collectPics(run)) {\n const img = decodePic(pic, ctx);\n if (img) kids.push(img);\n }\n\n // Page number\n const pageNums = getTag(run, \"hp:pageNum\", \"hp:PAGENUM\");\n if (pageNums.length > 0) {\n const pn = pageNums[0]?._attr ?? {};\n const fmt =\n pn.formatType === \"ROMAN_LOWER\"\n ? (\"roman\" as const)\n : pn.formatType === \"ROMAN_UPPER\"\n ? (\"romanCaps\" as const)\n : (\"decimal\" as const);\n const pageNumNode: PageNumNode = { tag: \"pagenum\", format: fmt };\n const spanProps = resolveCharPr(run, ctx);\n kids.push({ tag: \"span\", props: spanProps, kids: [pageNumNode] });\n continue;\n }\n\n // Text\n const runPics = collectPics(run);\n const textNodes = getTag(run, \"hp:t\", \"hp:T\", \"hp:CHAR\");\n const content = textNodes\n .map((t: any) => {\n const val =\n typeof t === \"string\" ? t : (t?._text ?? t?._ ?? t?.[\"#text\"] ?? \"\");\n return val.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n })\n .join(\"\");\n\n // Skip empty secPr-only runs that produced no images\n if (\n content === \"\" &&\n (run?.[\"hp:secPr\"]?.[0] || run?.[\"hp:SECPR\"]?.[0]) &&\n runPics.length === 0 &&\n pageNums.length === 0\n )\n continue;\n\n // Only push text span when there's actual content and no image already pushed for this run\n if (content !== \"\" || (runPics.length === 0 && pageNums.length === 0)) {\n const spanProps = resolveCharPr(run, ctx);\n kids.push(buildSpan(content, spanProps));\n }\n }\n\n // pageBreak=\"1\" → prepend a pb node in its own span\n if (pAttr.pageBreak === \"1\") {\n kids.unshift({ tag: \"span\", props: {}, kids: [buildPb()] });\n }\n\n return buildPara(kids.filter(Boolean) as ParaNode[\"kids\"], props);\n}\n\nfunction resolveCharPr(run: any, ctx: DecCtx): TextProps {\n const runAttr = run?._attr ?? {};\n const charPrIdRef = Number(runAttr.charPrIDRef ?? runAttr.CharPrIDRef ?? -1);\n\n // IDRef로 먼저 조회\n const def = ctx.charPrs.get(charPrIdRef);\n if (def) {\n return {\n b: def.b,\n i: def.i,\n u: def.u,\n s: def.s,\n pt: def.pt,\n color: def.color,\n font: def.font,\n bg: def.bg,\n };\n }\n\n // 인라인 CHARPR fallback — 대소문자 모두 시도\n const inlinePr =\n run?.[\"hp:CHARPR\"]?.[0] ??\n run?.[\"hp:charPr\"]?.[0] ??\n run?.CHARPR?.[0] ??\n run?.charPr?.[0];\n const ca = inlinePr?._attr ?? {};\n\n const bVal = ca.Bold ?? ca.bold ?? ca.B ?? \"\";\n const iVal = ca.Italic ?? ca.italic ?? ca.I ?? \"\";\n const uVal = ca.Underline ?? ca.underline ?? \"\";\n const sVal = ca.Strikeout ?? ca.strikeout ?? \"\";\n const fontName =\n ca.FontName ?? ca.fontName ?? ca.FaceNameHangul ?? ca.faceNameHangul ?? \"\";\n const heightVal = ca.Height ?? ca.height ?? \"\";\n\n return {\n b: bVal === \"1\" || bVal === \"true\" || bVal === \"True\" || undefined,\n i: iVal === \"1\" || iVal === \"true\" || iVal === \"True\" || undefined,\n u: uVal && uVal !== \"NONE\" ? true : undefined,\n s: sVal && sVal !== \"NONE\" && sVal !== \"3D\" ? true : undefined,\n font: fontName ? safeFont(fontName) : undefined,\n pt: heightVal ? Metric.hHeightToPt(Number(heightVal)) : undefined,\n color: safeHex(ca.TextColor ?? ca.textColor),\n bg: safeHex(ca.BgColor ?? ca.bgColor),\n };\n}\n\n// ─── Image decoding ────────────────────────────────────────\n\nfunction decodePic(pic: any, ctx: DecCtx): ImgNode | null {\n try {\n const szAttr = pic?.[\"hp:sz\"]?.[0]?._attr ?? pic?.sz?.[0]?._attr ?? {};\n const w = Metric.hwpToPt(Number(szAttr.width ?? 0));\n const h = Metric.hwpToPt(Number(szAttr.height ?? 0));\n\n // Try multiple tag patterns for image reference\n const imgNode =\n pic?.[\"hp:img\"]?.[0]?._attr ??\n pic?.[\"hc:img\"]?.[0]?._attr ??\n pic?.img?.[0]?._attr ??\n {};\n const binRef = imgNode.binaryItemIDRef ?? imgNode.BinaryItemIDRef;\n if (!binRef) return null;\n\n // Find binary data\n let imgData: Uint8Array | undefined;\n for (const [key, val] of ctx.files) {\n if (\n key.includes(binRef) ||\n key.toLowerCase().includes(binRef.toLowerCase())\n ) {\n imgData = val;\n break;\n }\n }\n if (!imgData) return null;\n\n const ext = binRef.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const mimeMap: Record<string, ImgNode[\"mime\"]> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n bmp: \"image/bmp\",\n };\n\n // ── hp:pos에서 layout 추출 ───────────────────────────────\n const posAttr = pic?.[\"hp:pos\"]?.[0]?._attr ?? pic?.pos?.[0]?._attr ?? {};\n const layout = extractHwpxLayout(posAttr, pic);\n\n return buildImg(\n TextKit.base64Encode(imgData),\n mimeMap[ext] ?? \"image/png\",\n w,\n h,\n undefined,\n layout,\n );\n } catch {\n return null;\n }\n}\n\nfunction extractHwpxLayout(posAttr: any, pic: any): ImgLayout {\n const treatAsChar =\n posAttr.treatAsChar === \"1\" || posAttr.treatAsChar === \"true\";\n if (treatAsChar) return { wrap: \"inline\" };\n\n // textWrap → wrap (direct attribute of hp:pic element)\n const textWrap: string =\n pic?._attr?.textWrap ?? pic?.pic?.[0]?._attr?.textWrap ?? \"TOP_AND_BOTTOM\";\n // OWPML §7.5.8.1 textWrap → ImgWrap 매핑\n // TOP_AND_BOTTOM: 텍스트가 이미지 위아래로만 흐름 → DOCX wrapTopAndBottom (float anchor)\n const wrapMap: Record<string, ImgWrap> = {\n TOP_AND_BOTTOM: \"topAndBottom\", // float, 위아래 텍스트 흐름\n SQUARE: \"square\",\n BOTH_SIDES: \"tight\",\n LEFT: \"tight\",\n RIGHT: \"tight\",\n LARGER_ONLY: \"tight\",\n SMALLER_ONLY: \"tight\",\n LARGEST_ONLY: \"tight\",\n BEHIND_TEXT: \"behind\",\n FRONT_TEXT: \"front\",\n };\n const wrap: ImgWrap = wrapMap[textWrap] ?? \"square\";\n\n // 기준점\n const horzRelToMap: Record<string, ImgHorzRelTo> = {\n PARA: \"para\",\n MARGIN: \"margin\",\n PAGE: \"page\",\n COLUMN: \"column\",\n };\n const vertRelToMap: Record<string, ImgVertRelTo> = {\n PARA: \"para\",\n MARGIN: \"margin\",\n PAGE: \"page\",\n PAPER: \"page\",\n LINE: \"line\",\n };\n const horzRelTo = horzRelToMap[posAttr.horzRelTo ?? \"\"] ?? \"para\";\n const vertRelTo = vertRelToMap[posAttr.vertRelTo ?? \"\"] ?? \"para\";\n\n // 정렬\n const horzAlignMap: Record<string, ImgHorzAlign> = {\n LEFT: \"left\",\n CENTER: \"center\",\n RIGHT: \"right\",\n };\n const vertAlignMap: Record<string, ImgVertAlign> = {\n TOP: \"top\",\n CENTER: \"center\",\n BOTTOM: \"bottom\",\n };\n const horzAlign = horzAlignMap[posAttr.horzAlign ?? \"\"];\n const vertAlign = vertAlignMap[posAttr.vertAlign ?? \"\"];\n\n // 오프셋\n const horzOffset = Number(posAttr.horzOffset ?? 0);\n const vertOffset = Number(posAttr.vertOffset ?? 0);\n const xPt = horzOffset !== 0 ? Metric.hwpToPt(horzOffset) : undefined;\n const yPt = vertOffset !== 0 ? Metric.hwpToPt(vertOffset) : undefined;\n\n return { wrap, horzAlign, vertAlign, horzRelTo, vertRelTo, xPt, yPt };\n}\n\n// ─── Table decoding ────────────────────────────────────────\n\nfunction decodeGrid(tbl: any, ctx: DecCtx): GridNode {\n const tblAttr = tbl?._attr ?? {};\n const borderFillId = Number(tblAttr.borderFillIDRef ?? 0);\n const borderFill = ctx.borderFills.get(borderFillId);\n const headerRow = tblAttr.repeatHeader === \"1\";\n\n const gridProps: GridProps = { headerRow: headerRow || undefined };\n if (borderFill?.stroke) gridProps.defaultStroke = borderFill.stroke;\n\n const rowArr = getTag(tbl, \"hp:tr\", \"hp:ROW\");\n\n // Read column widths: first try a row where ALL cells have cs=1\n for (const row of rowArr) {\n const cells = getTag(row, \"hp:tc\", \"hp:CELL\");\n const rowWidths: number[] = [];\n let allSingle = true;\n for (const cell of cells) {\n const cellSpanAttr = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n const cs = Number(cellSpanAttr.colSpan ?? cell?._attr?.ColSpan ?? 1);\n if (cs > 1) {\n allSingle = false;\n break;\n }\n const szAttr = cell?.[\"hp:cellSz\"]?.[0]?._attr ?? {};\n const w = Number(szAttr.width ?? 0);\n rowWidths.push(Metric.hwpToPt(w));\n }\n if (allSingle && rowWidths.length > 0 && rowWidths.some((w) => w > 0)) {\n gridProps.colWidths = rowWidths;\n break;\n }\n }\n\n // Fallback: proportional distribution when no all-single row exists\n if (!gridProps.colWidths) {\n // Determine colCount first: max column index reached across all rows\n let detectedCols = 0;\n for (const row of rowArr) {\n let ci = 0;\n for (const cell of getTag(row, \"hp:tc\", \"hp:CELL\")) {\n const csEl = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n ci += Number(csEl.colSpan ?? cell?._attr?.ColSpan ?? 1);\n }\n if (ci > detectedCols) detectedCols = ci;\n }\n if (detectedCols > 0) {\n const sums = new Float64Array(detectedCols);\n const counts = new Int32Array(detectedCols);\n for (const row of rowArr) {\n let ci = 0;\n for (const cell of getTag(row, \"hp:tc\", \"hp:CELL\")) {\n const csEl = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n const cs = Number(csEl.colSpan ?? cell?._attr?.ColSpan ?? 1);\n const szAttr = cell?.[\"hp:cellSz\"]?.[0]?._attr ?? {};\n const w = Number(szAttr.width ?? 0);\n if (w > 0 && cs > 0) {\n const perCol = w / cs;\n for (let k = 0; k < cs && ci + k < detectedCols; k++) {\n sums[ci + k] += perCol;\n counts[ci + k]++;\n }\n }\n ci += cs;\n }\n }\n const estimated = Array.from(sums).map((s, i) =>\n counts[i] > 0 ? Metric.hwpToPt(s / counts[i]) : 0,\n );\n if (estimated.some((w) => w > 0)) gridProps.colWidths = estimated;\n }\n }\n const rowNodes = rowArr.map((row: any) => {\n const cellArr = getTag(row, \"hp:tc\", \"hp:CELL\");\n const cellNodes = cellArr.map((cell: any) => {\n const ca = cell?._attr ?? {};\n\n // Cell borderFill\n const cellBfId = Number(ca.borderFillIDRef ?? 0);\n const cellBf = ctx.borderFills.get(cellBfId);\n\n const cellProps: CellProps = {\n bg: cellBf?.bgColor ?? safeHex(ca.BgColor),\n };\n\n if (cellBf) {\n // Preserve explicit NONE so it overrides table-level defaultStroke in DOCX tcBorders.\n // Only skip when the side is truly undefined (not specified in borderFill).\n cellProps.top = cellBf.top ?? cellBf.stroke;\n cellProps.bot = cellBf.bottom ?? cellBf.stroke;\n cellProps.left = cellBf.left ?? cellBf.stroke;\n cellProps.right = cellBf.right ?? cellBf.stroke;\n }\n\n // Vertical alignment and cell padding from subList\n const subList = cell?.[\"hp:subList\"]?.[0] ?? cell?.subList?.[0];\n const subAttr = subList?._attr ?? {};\n if (subAttr.vertAlign) {\n const vaMap: Record<string, \"top\" | \"mid\" | \"bot\"> = {\n TOP: \"top\",\n CENTER: \"mid\",\n BOTTOM: \"bot\",\n };\n cellProps.va = vaMap[subAttr.vertAlign];\n }\n // Cell margins (stored in HWPUNIT on subList attributes)\n const HWPX_DEFAULT_MARGIN_LR = 360; // typical default: 3.6pt\n const HWPX_DEFAULT_MARGIN_TB = 141; // typical default: ~1.4pt\n const mL = Number(subAttr.marginLeft ?? HWPX_DEFAULT_MARGIN_LR);\n const mR = Number(subAttr.marginRight ?? HWPX_DEFAULT_MARGIN_LR);\n const mT = Number(subAttr.marginTop ?? HWPX_DEFAULT_MARGIN_TB);\n const mB = Number(subAttr.marginBottom ?? HWPX_DEFAULT_MARGIN_TB);\n if (mL !== HWPX_DEFAULT_MARGIN_LR) cellProps.padL = Metric.hwpToPt(mL);\n if (mR !== HWPX_DEFAULT_MARGIN_LR) cellProps.padR = Metric.hwpToPt(mR);\n if (mT !== HWPX_DEFAULT_MARGIN_TB) cellProps.padT = Metric.hwpToPt(mT);\n if (mB !== HWPX_DEFAULT_MARGIN_TB) cellProps.padB = Metric.hwpToPt(mB);\n\n // Colspan/rowspan from cellSpan element or attributes\n const cellSpan = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n const cs = Number(cellSpan.colSpan ?? ca.ColSpan ?? 1);\n const rs = Number(cellSpan.rowSpan ?? ca.RowSpan ?? 1);\n\n // Parse cell content — paragraphs and nested tables (중첩 표)\n const cellKids: (ParaNode | GridNode)[] = [];\n const source = subList ?? cell;\n const sourcePSource = getTag(source, \"hp:p\", \"hp:P\");\n for (const sp of sourcePSource) {\n try {\n // Check if this paragraph contains a nested table in its runs\n const runs = getTag(sp, \"hp:run\", \"hp:RUN\");\n let hasNestedTable = false;\n for (const run of runs) {\n const nestedTbls = getTag(run, \"hp:tbl\", \"hp:TABLE\");\n for (const nestedTbl of nestedTbls) {\n try {\n cellKids.push(decodeGrid(nestedTbl, ctx));\n } catch {\n /* skip malformed nested table */\n }\n hasNestedTable = true;\n }\n }\n if (!hasNestedTable) {\n cellKids.push(decodePara(sp, ctx));\n }\n } catch {\n /* skip corrupted para in cell */\n }\n }\n\n return buildCell(\n cellKids.length > 0 ? cellKids : [buildPara([buildSpan(\"\")])],\n { cs, rs, props: cellProps },\n );\n });\n // Row height: prefer a non-merged cell (rs=1) for accuracy.\n // For merged cells, divide total height by rowSpan to get per-row height.\n let rowHeightPt: number | undefined;\n for (const cell of cellArr) {\n const ca = cell?._attr ?? {};\n const cellSpan = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n const cellRs = Math.max(1, Number(cellSpan.rowSpan ?? ca.RowSpan ?? 1));\n const hSz = cell?.[\"hp:cellSz\"]?.[0]?._attr ?? {};\n const hVal = Number(hSz.height ?? 0);\n if (hVal > 0) {\n rowHeightPt = Metric.hwpToPt(hVal) / cellRs;\n if (cellRs === 1) break; // exact match — stop searching\n }\n }\n return buildRow(cellNodes, rowHeightPt);\n });\n return buildGrid(rowNodes, gridProps);\n}\n\nfunction decodeGridSimple(tbl: any, ctx: DecCtx): GridNode {\n const rowArr = getTag(tbl, \"hp:tr\", \"hp:ROW\");\n const rowNodes = rowArr.map((row: any) => {\n const cellArr = getTag(row, \"hp:tc\", \"hp:CELL\");\n return buildRow(\n cellArr.map((cell: any) =>\n buildCell([buildPara([buildSpan(cellText(cell))])]),\n ),\n );\n });\n return buildGrid(rowNodes);\n}\n\nfunction decodeGridFlat(tbl: any): GridNode {\n return buildGrid([\n buildRow([buildCell([buildPara([buildSpan(tableText(tbl))])])]),\n ]);\n}\n\nfunction decodeGridText(tbl: any): ParaNode {\n return buildPara([buildSpan(tableText(tbl))]);\n}\n\nfunction cellText(cell: any): string {\n const subList = cell?.[\"hp:subList\"]?.[0] ?? cell?.subList?.[0];\n const source = subList ?? cell;\n return getTag(source, \"hp:p\", \"hp:P\")\n .map((p: any) =>\n getTag(p, \"hp:run\", \"hp:RUN\")\n .map((r: any) =>\n getTag(r, \"hp:t\", \"hp:T\")\n .map((t: any) => {\n const val =\n typeof t === \"string\"\n ? t\n : (t?._text ?? t?._ ?? t?.[\"#text\"] ?? \"\");\n return val.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n })\n .join(\"\"),\n )\n .join(\"\"),\n )\n .join(\" \");\n}\n\nfunction tableText(tbl: any): string {\n return getTag(tbl, \"hp:tr\", \"hp:ROW\")\n .map((row: any) =>\n getTag(row, \"hp:tc\", \"hp:CELL\")\n .map((c: any) => cellText(c))\n .join(\"\\t\"),\n )\n .join(\"\\n\");\n}\n\nfunction toArr(v: any): any[] {\n return v == null ? [] : Array.isArray(v) ? v : [v];\n}\n\n// Auto-register\nregistry.registerDecoder(new HwpxDecoder());\n","/**\n * OLE2 Compound File Binary Format (CFB) parser.\n * Used for legacy HWP 5.0 files.\n */\n\nexport const BinaryKit = {\n readU16LE(buf: Uint8Array, offset: number): number {\n return buf[offset] | (buf[offset + 1] << 8);\n },\n\n readU32LE(buf: Uint8Array, offset: number): number {\n return (\n (buf[offset] | (buf[offset + 1] << 8) | (buf[offset + 2] << 16)) >>> 0\n ) + buf[offset + 3] * 0x1000000;\n },\n\n isOle2(data: Uint8Array): boolean {\n return (\n data.length >= 8 &&\n data[0] === 0xD0 && data[1] === 0xCF &&\n data[2] === 0x11 && data[3] === 0xE0 &&\n data[4] === 0xA1 && data[5] === 0xB1 &&\n data[6] === 0x1A && data[7] === 0xE1\n );\n },\n\n parseCfb(data: Uint8Array): Map<string, Uint8Array> {\n const streams = new Map<string, Uint8Array>();\n\n if (!this.isOle2(data)) {\n throw new Error('Not a valid OLE2 file');\n }\n\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const sectorSize = 1 << view.getUint16(30, true);\n const miniSectorSz = 1 << view.getUint16(32, true);\n const dirFirstSec = view.getUint32(48, true);\n const miniStreamCutoff = view.getUint32(56, true);\n const miniFatFirst = view.getUint32(60, true);\n const miniFatCnt = view.getUint32(64, true);\n const difatFirst = view.getUint32(68, true);\n\n const ENDOFCHAIN = 0xFFFFFFFE;\n const FREESECT = 0xFFFFFFFF;\n\n const sectorAt = (sec: number): Uint8Array =>\n data.subarray(512 + sec * sectorSize, 512 + (sec + 1) * sectorSize);\n\n // Build FAT from DIFAT\n const fatSecNums: number[] = [];\n for (let i = 0; i < 109; i++) {\n const s = view.getUint32(76 + i * 4, true);\n if (s === FREESECT || s === ENDOFCHAIN) break;\n fatSecNums.push(s);\n }\n if (difatFirst !== ENDOFCHAIN && difatFirst !== FREESECT) {\n let difSec = difatFirst;\n while (difSec !== ENDOFCHAIN && difSec !== FREESECT) {\n const sec = sectorAt(difSec);\n const sv = new DataView(sec.buffer, sec.byteOffset, sec.byteLength);\n for (let i = 0; i < (sectorSize / 4) - 1; i++) {\n const s = sv.getUint32(i * 4, true);\n if (s === FREESECT || s === ENDOFCHAIN) break;\n fatSecNums.push(s);\n }\n difSec = sv.getUint32(sectorSize - 4, true);\n }\n }\n\n const fat: number[] = [];\n for (const sec of fatSecNums) {\n const s = sectorAt(sec);\n const sv = new DataView(s.buffer, s.byteOffset, s.byteLength);\n for (let i = 0; i < sectorSize / 4; i++) {\n fat.push(sv.getUint32(i * 4, true));\n }\n }\n\n const readChain = (startSec: number): Uint8Array => {\n const chunks: Uint8Array[] = [];\n let sec = startSec;\n while (sec !== ENDOFCHAIN && sec !== FREESECT && sec < fat.length) {\n chunks.push(sectorAt(sec));\n sec = fat[sec];\n }\n return concatUint8(chunks);\n };\n\n // Directory entries\n const dirData = readChain(dirFirstSec);\n const dirView = new DataView(dirData.buffer, dirData.byteOffset, dirData.byteLength);\n const dirCount = dirData.length / 128;\n\n interface DirEntry {\n name: string;\n type: number;\n startSec: number;\n size: number;\n childId: number;\n siblingLeftId: number;\n siblingRightId: number;\n }\n\n const dirEntries: DirEntry[] = [];\n for (let i = 0; i < dirCount; i++) {\n const base = i * 128;\n const nameLen = dirView.getUint16(base + 64, true);\n const nameBytes = dirData.subarray(base, base + Math.max(0, nameLen - 2));\n const name = new TextDecoder('utf-16le').decode(nameBytes);\n const type = dirData[base + 66];\n const childId = dirView.getInt32(base + 76, true);\n const sibLeft = dirView.getInt32(base + 68, true);\n const sibRight = dirView.getInt32(base + 72, true);\n const startSec = dirView.getUint32(base + 116, true);\n const size = dirView.getUint32(base + 120, true);\n dirEntries.push({ name, type, startSec, size, childId, siblingLeftId: sibLeft, siblingRightId: sibRight });\n }\n\n // Mini stream\n const rootEntry = dirEntries[0];\n let miniStreamData: Uint8Array | null = null;\n let miniFat: number[] = [];\n\n if (rootEntry && rootEntry.startSec !== ENDOFCHAIN && rootEntry.startSec !== FREESECT) {\n miniStreamData = readChain(rootEntry.startSec);\n }\n\n if (miniFatCnt > 0 && miniFatFirst !== ENDOFCHAIN && miniFatFirst !== FREESECT) {\n const mfData = readChain(miniFatFirst);\n const mfv = new DataView(mfData.buffer, mfData.byteOffset, mfData.byteLength);\n for (let i = 0; i < mfData.length / 4; i++) {\n miniFat.push(mfv.getUint32(i * 4, true));\n }\n }\n\n const readMiniChain = (startSec: number, size: number): Uint8Array => {\n if (!miniStreamData) return new Uint8Array(0);\n const chunks: Uint8Array[] = [];\n let sec = startSec;\n let remaining = size;\n while (sec !== ENDOFCHAIN && sec !== FREESECT && sec < miniFat.length && remaining > 0) {\n const off = sec * miniSectorSz;\n const chunk = miniStreamData.subarray(off, off + Math.min(miniSectorSz, remaining));\n chunks.push(chunk);\n remaining -= chunk.length;\n sec = miniFat[sec];\n }\n return concatUint8(chunks).subarray(0, size);\n };\n\n // DFS traversal\n const visit = (id: number, path: string): void => {\n if (id < 0 || id >= dirEntries.length) return;\n const entry = dirEntries[id];\n const fullPath = path ? `${path}/${entry.name}` : entry.name;\n\n if (entry.type === 2) {\n let streamData: Uint8Array;\n if (entry.size < miniStreamCutoff && miniStreamData) {\n streamData = readMiniChain(entry.startSec, entry.size);\n } else {\n streamData = readChain(entry.startSec).subarray(0, entry.size);\n }\n streams.set(fullPath, streamData);\n streams.set(entry.name, streamData);\n }\n\n if (entry.childId >= 0) visit(entry.childId, fullPath);\n if (entry.siblingLeftId >= 0) visit(entry.siblingLeftId, path);\n if (entry.siblingRightId >= 0) visit(entry.siblingRightId, path);\n };\n\n if (dirEntries.length > 0 && dirEntries[0].childId >= 0) {\n visit(dirEntries[0].childId, '');\n }\n\n return streams;\n },\n};\n\nfunction concatUint8(arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((s, a) => s + a.length, 0);\n const out = new Uint8Array(total);\n let off = 0;\n for (const a of arrays) { out.set(a, off); off += a.length; }\n return out;\n}\n","import type { Decoder } from '../../contract/decoder';\nimport type { DocRoot, ContentNode, ParaNode, SpanNode, ImgNode, GridNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport type { Align, Stroke, StrokeKind, PageDims, TextProps, ParaProps, CellProps, GridProps } from '../../model/doc-props';\nimport { succeed, fail } from '../../contract/result';\nimport { buildRoot, buildSheet, buildPara, buildSpan, buildGrid, buildRow, buildCell, buildImg } from '../../model/builders';\nimport { ShieldedParser } from '../../safety/ShieldedParser';\nimport { BinaryKit } from '../../toolkit/BinaryKit';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { Metric, safeHex, safeFont } from '../../safety/StyleBridge';\nimport { registry } from '../../pipeline/registry';\nimport { A4 } from '../../model/doc-props';\nimport pako from 'pako';\n\n/* ═══════════════════════════════════════════════════════════════\n HWP 5.0 Tag Constants\n ═══════════════════════════════════════════════════════════════ */\n\nconst HWPTAG_BEGIN = 16;\n\nconst TAG_FACE_NAME = HWPTAG_BEGIN + 3; // 19\nconst TAG_BORDER_FILL = HWPTAG_BEGIN + 4; // 20\nconst TAG_CHAR_SHAPE = HWPTAG_BEGIN + 5; // 21\nconst TAG_PARA_SHAPE = HWPTAG_BEGIN + 9; // 25\nconst TAG_PARA_HEADER = HWPTAG_BEGIN + 50; // 66\nconst TAG_PARA_TEXT = HWPTAG_BEGIN + 51; // 67\nconst TAG_PARA_CHAR_SHAPE = HWPTAG_BEGIN + 52; // 68\nconst TAG_CTRL_HEADER = HWPTAG_BEGIN + 55; // 71\nconst TAG_PAGE_DEF = HWPTAG_BEGIN + 57; // 73\n\n// TABLE / CELL tags vary by HWP version\nconst TAG_LIST_HEADER = HWPTAG_BEGIN + 56; // 72\nconst TAG_TABLE_A = HWPTAG_BEGIN + 61; // 77\nconst TAG_CELL_A = HWPTAG_BEGIN + 62; // 78\nconst TAG_TABLE_B = HWPTAG_BEGIN + 64; // 80\nconst TAG_CELL_B = HWPTAG_BEGIN + 65; // 81\n\nfunction isTableTag(t: number) { return t === TAG_TABLE_A || t === TAG_TABLE_B; }\nfunction isCellTag(t: number) { return t === TAG_CELL_A || t === TAG_CELL_B || t === TAG_LIST_HEADER; }\n\n// CTRL_HEADER ctrlId values (UINT32-LE as ASCII)\nconst CTRL_TABLE = 0x74626C20; // ' lbt' = 표(table)\nconst CTRL_IMAGE = 0x696D6720; // 'img '\nconst CTRL_OBJ = 0x6F626A20; // 'obj '\nconst CTRL_FIG = 0x66696720; // 'fig '\nconst CTRL_GSO = 0x67736F20; // 'gso ' = 그리기 객체 (drawing object, contains embedded images)\n\n/* ═══════════════════════════════════════════════════════════════\n Types\n ═══════════════════════════════════════════════════════════════ */\n\ninterface HwpRecord {\n tag: number;\n level: number;\n data: Uint8Array;\n}\n\ninterface HwpCharShape {\n faceIds: number[];\n height: number;\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikeout: boolean;\n superscript: boolean;\n subscript: boolean;\n textColor: string;\n}\n\ninterface HwpParaShape {\n align: Align;\n spaceBefore: number;\n spaceAfter: number;\n lineSpacing: number;\n leftMargin: number;\n indent: number;\n}\n\ninterface HwpBorderFill {\n borders: { type: number; widthPt: number; color: string }[];\n bgColor?: string;\n}\n\ninterface DocInfo {\n faceNames: string[];\n charShapes: HwpCharShape[];\n paraShapes: HwpParaShape[];\n borderFills: HwpBorderFill[];\n}\n\ninterface ParsedChar { pos: number; ch: string }\ninterface ParsedCtrl { pos: number; ctrlId: number; objId: number; matched: boolean }\ninterface ParaTextResult { chars: ParsedChar[]; controls: ParsedCtrl[] }\n\ninterface OleObject {\n id: number;\n data: Uint8Array;\n mimeType: string;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Low-level record parsing\n ═══════════════════════════════════════════════════════════════ */\n\nfunction parseRecords(data: Uint8Array): HwpRecord[] {\n const out: HwpRecord[] = [];\n let off = 0;\n while (off + 4 <= data.length) {\n const hdr = BinaryKit.readU32LE(data, off);\n const tag = hdr & 0x3FF;\n const level = (hdr >> 10) & 0x3FF;\n let size = (hdr >> 20) & 0xFFF;\n off += 4;\n if (size === 0xFFF) {\n if (off + 4 > data.length) break;\n size = BinaryKit.readU32LE(data, off);\n off += 4;\n }\n if (off + size > data.length) break;\n out.push({ tag, level, data: data.subarray(off, off + size) });\n off += size;\n }\n return out;\n}\n\nfunction tryInflate(data: Uint8Array): Uint8Array {\n try { return pako.inflate(data); } catch {\n try { return pako.inflateRaw(data); } catch { return data; }\n }\n}\n\n/* ═══════════════════════════════════════════════════════════════\n FileHeader\n ═══════════════════════════════════════════════════════════════ */\n\nfunction parseFileHeader(buf: Uint8Array) {\n if (buf.length < 40) return { compressed: true, encrypted: false };\n const props = BinaryKit.readU32LE(buf, 36);\n return { compressed: (props & 1) !== 0, encrypted: (props & 2) !== 0 };\n}\n\n/* ═══════════════════════════════════════════════════════════════\n DocInfo parsing\n ═══════════════════════════════════════════════════════════════ */\n\nfunction parseDocInfo(data: Uint8Array, compressed: boolean): DocInfo {\n const raw = compressed ? tryInflate(data) : data;\n const recs = parseRecords(raw);\n const info: DocInfo = { faceNames: [], charShapes: [], paraShapes: [], borderFills: [] };\n\n for (const r of recs) {\n try {\n if (r.tag === TAG_FACE_NAME) info.faceNames.push(parseFaceName(r.data));\n if (r.tag === TAG_CHAR_SHAPE) info.charShapes.push(parseCharShape(r.data));\n if (r.tag === TAG_PARA_SHAPE) info.paraShapes.push(parseParaShape(r.data));\n if (r.tag === TAG_BORDER_FILL) info.borderFills.push(parseBorderFill(r.data));\n } catch { /* skip malformed record */ }\n }\n return info;\n}\n\n/* ── FACE_NAME ──────────────────────────────────────────────── */\n\nfunction parseFaceName(d: Uint8Array): string {\n if (d.length < 3) return '';\n const len = BinaryKit.readU16LE(d, 1); // UTF-16 char count\n if (d.length < 3 + len * 2) return '';\n return new TextDecoder('utf-16le').decode(d.subarray(3, 3 + len * 2));\n}\n\n/* ── CHAR_SHAPE ─────────────────────────────────────────────── */\n/* offset size field\n 0 14 faceId[7] (UINT16 × 7)\n 14 7 ratio[7]\n 21 7 spacing[7]\n 28 7 relSize[7]\n 35 7 offset[7]\n 42 4 height (UINT32, HWP-units 100 = 1pt)\n 46 4 attr (UINT32, bit flags)\n 50 1 shadowX\n 51 1 shadowY\n 52 4 textColor (COLORREF R,G,B,0) */\n\nfunction parseCharShape(d: Uint8Array): HwpCharShape {\n const faceIds: number[] = [];\n for (let i = 0; i < 7; i++) faceIds.push(d.length >= (i + 1) * 2 ? BinaryKit.readU16LE(d, i * 2) : 0);\n\n const height = d.length >= 46 ? BinaryKit.readU32LE(d, 42) : 1000;\n const attr = d.length >= 50 ? BinaryKit.readU32LE(d, 46) : 0;\n\n // attr bit layout (HWP 5.0 spec Table 35):\n // 0: italic, 1: bold, 2-4: underline type(3), 5-8: underline shape(4),\n // 9-11: outline(3), 12-13: shadow(2), 14: emboss, 15: engrave,\n // 16-17: super/sub(2, 0=none,1=super,2=sub), 18-20: strikeout type(3),\n // 21-24: strikeout shape(4), 25: annotLine, 26-28: annotLine type,\n // 29: useFontSpace, 30: kerning\n const ulType = (attr >> 2) & 0x7; // 3 bits at 2-4\n const skType = (attr >> 18) & 0x7; // 3 bits at 18-20\n const suType = (attr >> 16) & 0x3; // 2 bits at 16-17 (0=none,1=super,2=sub)\n\n return {\n faceIds,\n height: (height > 0 && height < 100000) ? height : 1000,\n italic: (attr & 1) !== 0,\n bold: ((attr >> 1) & 1) !== 0,\n underline: ulType !== 0,\n strikeout: skType !== 0,\n superscript: suType === 1,\n subscript: suType === 2,\n textColor: d.length >= 56 ? colorRef(d, 52) : '000000',\n };\n}\n\n/* ── PARA_SHAPE ─────────────────────────────────────────────── */\n/* offset size field\n 0 4 attr1 (bits 0-1 = alignment: 0=justify,1=left,2=right,3=center)\n 4 4 leftMargin (HWPUNIT)\n 8 4 rightMargin\n 12 4 indent\n 16 4 spaceBefore\n 20 4 spaceAfter\n 24 4 lineSpacing */\n\nconst ALIGN_TBL: Record<number, Align> = { 0: 'justify', 1: 'left', 2: 'right', 3: 'center', 4: 'justify' };\n\nfunction parseParaShape(d: Uint8Array): HwpParaShape {\n if (d.length < 4) return { align: 'left', spaceBefore: 0, spaceAfter: 0, lineSpacing: 160, leftMargin: 0, indent: 0 };\n const attr = BinaryKit.readU32LE(d, 0);\n return {\n align: ALIGN_TBL[(attr >> 2) & 0x7] ?? 'left',\n leftMargin: d.length >= 8 ? i32(d, 4) : 0, // offset 4: leftMargin (들여쓰기)\n indent: d.length >= 16 ? i32(d, 12) : 0, // offset 12: first-line indent\n spaceBefore: d.length >= 20 ? i32(d, 16) : 0,\n spaceAfter: d.length >= 24 ? i32(d, 20) : 0,\n lineSpacing: d.length >= 28 ? i32(d, 24) : 160,\n };\n}\n\n/* ── BORDER_FILL ────────────────────────────────────────────── */\n/* [0:2] attr\n For each of 5 borders (left,right,top,bottom,diagonal): 6 bytes\n +0 type(BYTE) +1 widthIdx(BYTE) +2 color(COLORREF)\n [32:4] fillType\n [36:4] faceColor (bgColor for solid fill) */\n\nconst BORDER_W_PT = [0.28, 0.34, 0.43, 0.57, 0.71, 0.85, 1.13, 1.42, 1.70, 1.98, 2.84, 4.25, 5.67, 8.50, 11.34, 14.17];\nconst BORDER_KIND: Record<number, StrokeKind> = { 0:'solid',1:'dash',2:'dash',3:'dot',4:'dash',5:'dash',6:'dash',7:'double',8:'double',9:'double',10:'none' };\n\nfunction parseBorderFill(d: Uint8Array): HwpBorderFill {\n // Spec grouped format (표 23):\n // [0:2] attr\n // [2:4] 4 border types (left, right, top, bottom) — 1 byte each\n // [6:4] 4 border widths (left, right, top, bottom) — 1 byte each (index into BORDER_W_PT)\n // [10:16] 4 border colors (left, right, top, bottom) — 4 bytes each (COLORREF)\n // [26:3] diagonal: type(1) + width(1) + color(4) = 6 bytes actually [26:6]\n // [32:4] fillType\n // [36:4] faceColor (bgColor for solid fill)\n const borders: HwpBorderFill['borders'] = [];\n const BASE_TYPE = 2; // 4 type bytes\n const BASE_WIDTH = 6; // 4 width bytes\n const BASE_COLOR = 10; // 4 × 4-byte colors\n for (let i = 0; i < 4; i++) {\n const type = BASE_TYPE + i < d.length ? d[BASE_TYPE + i] : 0;\n const widthPt = BASE_WIDTH + i < d.length ? (BORDER_W_PT[d[BASE_WIDTH + i]] ?? 0.5) : 0.5;\n const color = BASE_COLOR + i * 4 + 4 <= d.length ? colorRef(d, BASE_COLOR + i * 4) : '000000';\n borders.push({ type, widthPt, color });\n }\n let bgColor: string | undefined;\n // after attr(2) + 4 types(4) + 4 widths(4) + 4 colors(16) + diagonal(6) = offset 32\n const fOff = 32;\n if (d.length >= fOff + 8) {\n const ft = BinaryKit.readU32LE(d, fOff);\n if (ft & 1) bgColor = colorRef(d, fOff + 4);\n }\n return { borders, bgColor };\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Body section parsing\n ═══════════════════════════════════════════════════════════════ */\n\n// gsoCtx: shared mutable counter for 'gso ' drawing objects.\n// Each 'gso ' CTRL_HEADER encountered increments this counter.\n// objectMap is keyed by 0-based gso order = sequential BinData insertion order.\ninterface GsoCtx { count: number }\n\nfunction parseBody(\n raw: Uint8Array, compressed: boolean, di: DocInfo, shield: ShieldedParser, gsoCtx: GsoCtx,\n): { content: ContentNode[]; pageDims?: PageDims } {\n const recs = parseRecords(compressed ? tryInflate(raw) : raw);\n const content: ContentNode[] = [];\n let pageDims: PageDims | undefined;\n\n // Pre-scan for PAGE_DEF at any nesting level (real HWP stores it at level 2 inside section ctrl)\n for (const r of recs) {\n if (r.tag === TAG_PAGE_DEF) {\n pageDims = shield.guard(() => parsePageDef(r.data), A4, 'hwp:pageDef');\n break;\n }\n }\n\n let i = 0;\n while (i < recs.length) {\n if (recs[i].tag === TAG_PAGE_DEF) {\n i++; // already handled above; skip at top level\n } else if (recs[i].tag === TAG_PARA_HEADER) {\n const r = shield.guard(\n () => parseParagraphGroup(recs, i, di, shield, gsoCtx),\n { nodes: [] as ContentNode[], next: i + 1 },\n `hwp:para@${i}`,\n );\n content.push(...r.nodes);\n i = r.next;\n } else {\n i++;\n }\n }\n return { content, pageDims };\n}\n\n/* ── Paragraph group ────────────────────────────────────────── */\n\nfunction parseParagraphGroup(\n recs: HwpRecord[], start: number, di: DocInfo, shield: ShieldedParser, gsoCtx: GsoCtx,\n): { nodes: ContentNode[]; next: number } {\n const hdr = recs[start];\n const lv = hdr.level;\n\n // paraShapeId at offset 8 (UINT16)\n const psId = hdr.data.length >= 10 ? BinaryKit.readU16LE(hdr.data, 8) : 0;\n const ps = di.paraShapes[psId];\n\n let text: ParaTextResult | null = null;\n let csPairs: [number, number][] = [];\n const grids: ContentNode[] = [];\n // imgId: for 'gso' uses sequential gsoCtx.count; for others uses flags-based objId\n const ctrlHeaders: { ctrlId: number; imgId: number; wPt: number; hPt: number }[] = [];\n let i = start + 1;\n\n while (i < recs.length && recs[i].level > lv) {\n const r = recs[i];\n\n if (r.tag === TAG_PARA_TEXT && r.level === lv + 1) {\n text = decodeParaText(r.data);\n i++;\n } else if (r.tag === TAG_PARA_CHAR_SHAPE && r.level === lv + 1) {\n csPairs = parseCharShapePairs(r.data);\n i++;\n } else if (r.tag === TAG_CTRL_HEADER && r.level === lv + 1) {\n if (r.data.length >= 4) {\n const ctrlId = BinaryKit.readU32LE(r.data, 0);\n\n // HWP 5.0 general-object layout:\n // [0:4] ctrlId [4:4] flags [8:4] xOff [12:4] yOff\n // [16:4] width(HWPUNIT) [20:4] height(HWPUNIT)\n const MAX_HWP = 1_000_000;\n const rawW = r.data.length >= 24 ? BinaryKit.readU32LE(r.data, 16) : 0;\n const rawH = r.data.length >= 28 ? BinaryKit.readU32LE(r.data, 20) : 0;\n const wPt = rawW > 0 && rawW < MAX_HWP ? Metric.hwpToPt(rawW) : 0;\n const hPt = rawH > 0 && rawH < MAX_HWP ? Metric.hwpToPt(rawH) : 0;\n\n // 'gso ' (그리기 객체) uses sequential counter; others use flags-based id\n const imgId = ctrlId === CTRL_GSO ? gsoCtx.count++ : (r.data.length >= 6 ? BinaryKit.readU16LE(r.data, 4) : 0);\n ctrlHeaders.push({ ctrlId, imgId, wPt, hPt });\n\n if (ctrlId === CTRL_TABLE) {\n const tr = shield.guard(\n () => parseTableCtrl(recs, i, di, shield, gsoCtx),\n { grid: null, next: skipKids(recs, i) },\n `hwp:tbl@${i}`,\n );\n if (tr.grid) grids.push(tr.grid);\n i = tr.next;\n } else {\n i = skipKids(recs, i);\n }\n } else {\n i = skipKids(recs, i);\n }\n } else {\n i++;\n }\n }\n\n const nodes: ContentNode[] = [];\n\n // Build paragraph from text and inline controls (images)\n if (text && (text.chars.length > 0 || text.controls.length > 0)) {\n const paraContent: (SpanNode | ContentNode)[] = [];\n\n if (text.chars.length > 0) {\n const spans = resolveCharShapes(text.chars, csPairs, di);\n paraContent.push(...spans);\n }\n\n // Image placeholder spans: only for actual image controls.\n // Non-image controls (footnotes, TOC entries, etc.) are silently skipped.\n if (text.controls.length > 0) {\n for (let ci = 0; ci < text.controls.length; ci++) {\n const ch = ctrlHeaders[ci];\n if (!ch) continue; // anchor-only ctrl (gso is sibling, not inline)\n const isImg = ch.ctrlId === CTRL_IMAGE || ch.ctrlId === CTRL_FIG || ch.ctrlId === CTRL_OBJ || ch.ctrlId === CTRL_GSO;\n if (!isImg) continue; // skip footnotes, TOC, page num, etc.\n const dimStr = (ch.wPt > 0 && ch.hPt > 0)\n ? `_W${Math.round(ch.wPt)}_H${Math.round(ch.hPt)}`\n : '';\n paraContent.push(buildSpan(`__EXT_${ch.imgId}${dimStr}__`));\n }\n }\n\n if (paraContent.length > 0) {\n nodes.push(buildPara(paraContent as any, buildParaProps(ps)));\n }\n }\n\n nodes.push(...grids);\n return { nodes, next: i };\n}\n\nfunction skipKids(recs: HwpRecord[], idx: number): number {\n const lv = recs[idx].level;\n let i = idx + 1;\n while (i < recs.length && recs[i].level > lv) i++;\n return i;\n}\n\n/* ── PARA_TEXT ───────────────────────────────────────────────── */\n\n// Extended controls: 8 WORDs, associated CTRL_HEADER\nconst EXT_CTRL = new Set([2, 3, 11, 12, 14, 15]);\n// Inline controls: 8 WORDs, no CTRL_HEADER\nconst INL_CTRL = new Set([4, 5, 6, 7, 8]);\n\nfunction decodeParaText(d: Uint8Array): ParaTextResult {\n const chars: ParsedChar[] = [];\n const controls: ParsedCtrl[] = [];\n let i = 0, pos = 0;\n\n while (i + 1 < d.length) {\n const c = d[i] | (d[i + 1] << 8);\n if (c === 0) { i += 2; pos++; continue; }\n if (c === 13) { break; } // paragraph end\n if (c === 10) { chars.push({ pos, ch: '\\n' }); i += 2; pos++; continue; }\n\n if (EXT_CTRL.has(c)) {\n // Extended control: 8 WORDs (16 bytes)\n // WORD 4 contains objId (for images, charts, etc.)\n let objId = 0;\n if (i + 16 <= d.length) {\n objId = BinaryKit.readU16LE(d, i + 8); // 4th WORD (offset 8) contains objId\n }\n controls.push({ pos, ctrlId: 0, objId, matched: false });\n i += 16; pos += 8; continue;\n }\n if (INL_CTRL.has(c)) {\n i += 16; pos += 8; continue;\n }\n if (c === 9) { // tab (inline 8 WORDs)\n chars.push({ pos, ch: '\\t' });\n i += 16; pos += 8; continue;\n }\n if (c >= 1 && c <= 31) { i += 2; pos++; continue; } // other control\n\n chars.push({ pos, ch: String.fromCharCode(c) });\n i += 2; pos++;\n }\n return { chars, controls };\n}\n\n/* ── PARA_CHAR_SHAPE ────────────────────────────────────────── */\n\nfunction parseCharShapePairs(d: Uint8Array): [number, number][] {\n const out: [number, number][] = [];\n for (let i = 0; i + 7 < d.length; i += 8)\n out.push([BinaryKit.readU32LE(d, i), BinaryKit.readU32LE(d, i + 4)]);\n return out;\n}\n\n/* ── Char-shape → SpanNode resolution ───────────────────────── */\n\nfunction resolveCharShapes(chars: ParsedChar[], pairs: [number, number][], di: DocInfo): SpanNode[] {\n if (chars.length === 0) return [buildSpan('')];\n\n const defaultId = pairs.length > 0 ? pairs[0][1] : 0;\n\n function idFor(pos: number): number {\n let id = defaultId;\n for (const [p, sid] of pairs) { if (p <= pos) id = sid; else break; }\n return id;\n }\n\n const spans: SpanNode[] = [];\n let curId = idFor(chars[0].pos);\n let buf = chars[0].ch;\n\n for (let k = 1; k < chars.length; k++) {\n const sid = idFor(chars[k].pos);\n if (sid !== curId) { spans.push(styledSpan(buf, curId, di)); buf = ''; curId = sid; }\n buf += chars[k].ch;\n }\n if (buf) spans.push(styledSpan(buf, curId, di));\n return spans;\n}\n\nfunction styledSpan(text: string, shapeId: number, di: DocInfo): SpanNode {\n const cs = di.charShapes[shapeId];\n if (!cs) return buildSpan(text);\n\n const props: TextProps = {};\n const fid = cs.faceIds[0] ?? 0;\n if (fid < di.faceNames.length && di.faceNames[fid]) props.font = safeFont(di.faceNames[fid]);\n if (cs.height > 0) props.pt = Metric.hwpToPt(cs.height);\n if (cs.bold) props.b = true;\n if (cs.italic) props.i = true;\n if (cs.underline) props.u = true;\n if (cs.strikeout) props.s = true;\n if (cs.superscript) props.sup = true;\n if (cs.subscript) props.sub = true;\n\n const hex = safeHex(cs.textColor);\n if (hex && hex !== '000000') props.color = hex;\n\n return buildSpan(text, props);\n}\n\n/* ── Table control parsing ──────────────────────────────────── */\n\nfunction parseTableCtrl(\n recs: HwpRecord[], ctrlIdx: number, di: DocInfo, shield: ShieldedParser, gsoCtx: GsoCtx,\n): { grid: ContentNode | null; next: number } {\n const ctrlLv = recs[ctrlIdx].level;\n let i = ctrlIdx + 1;\n\n let tblData: Uint8Array | null = null;\n const cells: { data: Uint8Array; tag: number; cStart: number; cEnd: number }[] = [];\n\n // Collect TABLE and cell records within this control's scope\n const tblLevel = ctrlLv + 1;\n\n while (i < recs.length && recs[i].level > ctrlLv) {\n const r = recs[i];\n\n if (isTableTag(r.tag) && r.level === tblLevel) {\n tblData = r.data;\n i++;\n } else if (r.tag === TAG_LIST_HEADER && r.level === tblLevel) {\n // LIST_HEADER as cell: paraCount tells how many paragraphs follow\n const cellData = r.data;\n const paraCount = cellData.length >= 2 ? BinaryKit.readU16LE(cellData, 0) : 0;\n i++;\n const cStart = i;\n // Consume exactly paraCount paragraphs (each with its child records)\n let consumed = 0;\n while (i < recs.length && consumed < paraCount) {\n if (recs[i].tag === TAG_PARA_HEADER && recs[i].level === tblLevel) {\n consumed++;\n i++;\n // Skip child records of this paragraph\n while (i < recs.length && recs[i].level > tblLevel) i++;\n } else if (recs[i].level > tblLevel) {\n i++;\n } else {\n break; // hit next sibling at same level\n }\n }\n cells.push({ data: cellData, tag: TAG_LIST_HEADER, cStart, cEnd: i });\n } else if (isCellTag(r.tag) && r.level === tblLevel) {\n // Full CELL record (with cell-specific fields)\n const cellData = r.data;\n const cellTag = r.tag;\n i++;\n const cStart = i;\n while (i < recs.length && recs[i].level > tblLevel) i++;\n cells.push({ data: cellData, tag: cellTag, cStart, cEnd: i });\n } else {\n i++;\n }\n }\n\n if (!tblData || cells.length === 0) return { grid: null, next: i };\n\n const rowCnt = tblData.length >= 6 ? BinaryKit.readU16LE(tblData, 4) : 1;\n const colCnt = tblData.length >= 8 ? BinaryKit.readU16LE(tblData, 6) : 1;\n\n interface PC { row: number; col: number; cs: number; rs: number; widthHwp: number; heightHwp?: number; props: CellProps; cellChildren: (ParaNode | GridNode)[] }\n const parsed: PC[] = [];\n\n for (let ci = 0; ci < cells.length; ci++) {\n const c = cells[ci];\n const seqIdx = ci;\n const pc = shield.guard(\n () => parseCellRec(c.data, c.tag, recs, c.cStart, c.cEnd, di, shield, seqIdx, colCnt, gsoCtx),\n { row: Math.floor(ci / (colCnt || 1)), col: ci % (colCnt || 1), cs: 1, rs: 1, widthHwp: 0, heightHwp: undefined, props: {}, cellChildren: [buildPara([buildSpan('')])] },\n `hwp:cell@${c.cStart}`,\n );\n parsed.push(pc);\n }\n\n // Determine actual row count from cell data (may exceed rowCnt for merged cells)\n const maxRow = parsed.reduce((m, c) => Math.max(m, c.row + c.rs), 0);\n const actualRowCnt = Math.max(rowCnt, maxRow);\n\n // Validate cell positions; fallback to sequential layout if invalid\n const posValid = parsed.every(c => c.row >= 0 && c.col >= 0 && c.col < colCnt);\n if (!posValid) {\n let idx = 0;\n for (const c of parsed) { c.row = Math.floor(idx / colCnt); c.col = idx % colCnt; idx++; }\n }\n\n // Compute column widths in points from cell widths\n const colWidthsPt: number[] = new Array(colCnt).fill(0);\n // Pass 1: use cells with cs=1 for exact column widths\n for (const c of parsed) {\n if (c.cs === 1 && c.widthHwp > 0) {\n const wPt = Metric.hwpToPt(c.widthHwp);\n if (wPt > colWidthsPt[c.col]) colWidthsPt[c.col] = wPt;\n }\n }\n // Pass 2: for columns still 0, try to derive from multi-span cells\n // Sort by span size ascending so smaller, more precise spans fill widths before larger spans\n const zeroColumns = colWidthsPt.filter(w => w === 0).length;\n if (zeroColumns > 0) {\n const spanCells = parsed.filter(c => c.cs > 1 && c.widthHwp > 0).sort((a, b) => a.cs - b.cs);\n for (const c of spanCells) {\n if (c.cs > 1 && c.widthHwp > 0) {\n // Subtract known column widths from the span\n let known = 0;\n let unknownCols = 0;\n for (let ci = c.col; ci < c.col + c.cs && ci < colCnt; ci++) {\n if (colWidthsPt[ci] > 0) known += colWidthsPt[ci];\n else unknownCols++;\n }\n if (unknownCols > 0) {\n const remaining = Metric.hwpToPt(c.widthHwp) - known;\n const each = remaining > 0 ? remaining / unknownCols : 0;\n for (let ci = c.col; ci < c.col + c.cs && ci < colCnt; ci++) {\n if (colWidthsPt[ci] === 0 && each > 0) colWidthsPt[ci] = each;\n }\n }\n }\n }\n }\n\n // Post-process: clamp near-zero column widths (< 1pt = floating-point artifact) to minimum 1pt\n for (let i = 0; i < colWidthsPt.length; i++) {\n if (colWidthsPt[i] > 0 && colWidthsPt[i] < 1) colWidthsPt[i] = 1;\n }\n\n const rows = [];\n for (let r = 0; r < actualRowCnt; r++) {\n const rc = parsed.filter(c => c.row === r).sort((a, b) => a.col - b.col);\n if (rc.length === 0) continue;\n\n // Calculate row height — prefer rs=1 cells (exact per-row height)\n let rowHeightPt: number | undefined = undefined;\n for (const c of rc) {\n if (c.heightHwp && c.heightHwp > 0 && c.rs === 1) {\n const hPt = Metric.hwpToPt(c.heightHwp);\n if (rowHeightPt == null || hPt > rowHeightPt) rowHeightPt = hPt;\n }\n }\n // Fallback: all cells span multiple rows → approximate height per row\n if (rowHeightPt == null) {\n for (const c of rc) {\n if (c.heightHwp && c.heightHwp > 0) {\n const hPt = Metric.hwpToPt(c.heightHwp) / c.rs;\n if (rowHeightPt == null || hPt > rowHeightPt) rowHeightPt = hPt;\n }\n }\n }\n\n rows.push(buildRow(rc.map(c => {\n return buildCell(c.cellChildren, { cs: c.cs, rs: c.rs, props: c.props });\n }), rowHeightPt));\n }\n if (rows.length === 0) return { grid: null, next: i };\n\n // Table-level default stroke\n let defStroke: Stroke | undefined;\n const bfOff = 18 + rowCnt * 2;\n if (tblData.length >= bfOff + 2) {\n const bfId = BinaryKit.readU16LE(tblData, bfOff);\n defStroke = strokeFromBF(bfId, di);\n }\n\n const gp: GridProps = {};\n if (defStroke) gp.defaultStroke = defStroke;\n const hasWidths = colWidthsPt.some(w => w > 0);\n if (hasWidths) gp.colWidths = colWidthsPt;\n return { grid: buildGrid(rows, gp), next: i };\n}\n\n/* ── Cell record ────────────────────────────────────────────── */\n/* LIST_HEADER for cells (HWP 5.0/5.1):\n [0:2] paraCount [2:4] attr (bits 6-7 = vertAlign)\n [6:2] unknown [8:2] rowAddr [10:2] colAddr\n [12:2] rowSpan [14:2] colSpan\n [16:4] width(HWPUNIT) [20:4] height(HWPUNIT)\n [24:8] padding[4] [32:2] borderFillId */\n\nfunction parseCellRec(\n d: Uint8Array, tag: number, recs: HwpRecord[], cStart: number, cEnd: number,\n di: DocInfo, shield: ShieldedParser, seqIdx: number, colCnt: number, gsoCtx: GsoCtx,\n) {\n let col: number, row: number, cs = 1, rs = 1;\n let widthHwp = 0;\n let heightHwp = 0;\n const props: CellProps = {};\n\n const attr = d.length >= 6 ? BinaryKit.readU32LE(d, 2) : 0;\n const va = (attr >> 6) & 0x3;\n if (va === 1) props.va = 'mid';\n else if (va === 2) props.va = 'bot';\n\n const HWP_PAD_LR_DEFAULT = 360;\n const HWP_PAD_TB_DEFAULT = 141;\n\n if (tag === TAG_LIST_HEADER && d.length >= 22) {\n col = BinaryKit.readU16LE(d, 8);\n row = BinaryKit.readU16LE(d, 10);\n cs = Math.max(1, BinaryKit.readU16LE(d, 12));\n rs = Math.max(1, BinaryKit.readU16LE(d, 14));\n widthHwp = BinaryKit.readU32LE(d, 16);\n heightHwp = d.length >= 24 ? BinaryKit.readU32LE(d, 20) : 0;\n if (d.length >= 32) {\n const pL = BinaryKit.readU16LE(d, 24); const pR = BinaryKit.readU16LE(d, 26);\n const pT = BinaryKit.readU16LE(d, 28); const pB = BinaryKit.readU16LE(d, 30);\n if (pL !== HWP_PAD_LR_DEFAULT) props.padL = Metric.hwpToPt(pL);\n if (pR !== HWP_PAD_LR_DEFAULT) props.padR = Metric.hwpToPt(pR);\n if (pT !== HWP_PAD_TB_DEFAULT) props.padT = Metric.hwpToPt(pT);\n if (pB !== HWP_PAD_TB_DEFAULT) props.padB = Metric.hwpToPt(pB);\n }\n const bfId = d.length >= 34 ? BinaryKit.readU16LE(d, 32) : 0;\n if (bfId > 0 && bfId <= di.borderFills.length) applyCellBorderFill(di.borderFills[bfId - 1], props);\n } else if (tag !== TAG_LIST_HEADER) {\n col = d.length >= 8 ? BinaryKit.readU16LE(d, 6) : seqIdx % (colCnt || 1);\n row = d.length >= 10 ? BinaryKit.readU16LE(d, 8) : Math.floor(seqIdx / (colCnt || 1));\n cs = d.length >= 12 ? Math.max(1, BinaryKit.readU16LE(d, 10)) : 1;\n rs = d.length >= 14 ? Math.max(1, BinaryKit.readU16LE(d, 12)) : 1;\n widthHwp = d.length >= 18 ? BinaryKit.readU32LE(d, 14) : 0;\n heightHwp = d.length >= 22 ? BinaryKit.readU32LE(d, 18) : 0;\n if (d.length >= 30) {\n const pL = BinaryKit.readU16LE(d, 22); const pR = BinaryKit.readU16LE(d, 24);\n const pT = BinaryKit.readU16LE(d, 26); const pB = BinaryKit.readU16LE(d, 28);\n if (pL !== HWP_PAD_LR_DEFAULT) props.padL = Metric.hwpToPt(pL);\n if (pR !== HWP_PAD_LR_DEFAULT) props.padR = Metric.hwpToPt(pR);\n if (pT !== HWP_PAD_TB_DEFAULT) props.padT = Metric.hwpToPt(pT);\n if (pB !== HWP_PAD_TB_DEFAULT) props.padB = Metric.hwpToPt(pB);\n }\n const bfId = d.length >= 32 ? BinaryKit.readU16LE(d, 30) : 0;\n if (bfId > 0 && bfId <= di.borderFills.length) applyCellBorderFill(di.borderFills[bfId - 1], props);\n } else {\n row = Math.floor(seqIdx / (colCnt || 1));\n col = seqIdx % (colCnt || 1);\n }\n\n const cellChildren: (ParaNode | GridNode)[] = [];\n const MAX_HWP = 1_000_000;\n let k = cStart;\n\n while (k < cEnd) {\n if (recs[k].tag === TAG_PARA_HEADER) {\n // Parse paragraph inside cell — also extracts nested tables within the paragraph\n const r = shield.guard(\n () => {\n const hdr = recs[k];\n const lv = hdr.level;\n const psId = hdr.data.length >= 10 ? BinaryKit.readU16LE(hdr.data, 8) : 0;\n const ps = di.paraShapes[psId];\n let txt: ParaTextResult | null = null;\n let csp: [number, number][] = [];\n const ctrlHdrs: { ctrlId: number; imgId: number; wPt: number; hPt: number }[] = [];\n const innerGrids: GridNode[] = [];\n let j = k + 1;\n while (j < cEnd && recs[j].level > lv) {\n if (recs[j].tag === TAG_PARA_TEXT) { txt = decodeParaText(recs[j].data); j++; }\n else if (recs[j].tag === TAG_PARA_CHAR_SHAPE) { csp = parseCharShapePairs(recs[j].data); j++; }\n else if (recs[j].tag === TAG_CTRL_HEADER && recs[j].level === lv + 1) {\n if (recs[j].data.length >= 4) {\n const ctrlId = BinaryKit.readU32LE(recs[j].data, 0);\n if (ctrlId === CTRL_TABLE) {\n // Nested table inside a cell paragraph — recurse into parseTableCtrl\n const nestedTr = shield.guard(\n () => parseTableCtrl(recs, j, di, shield, gsoCtx),\n { grid: null, next: skipKids(recs, j) },\n `hwp:innerNestedTbl@${j}`,\n );\n if (nestedTr.grid) innerGrids.push(nestedTr.grid as GridNode);\n j = nestedTr.next;\n } else {\n const rawW = recs[j].data.length >= 24 ? BinaryKit.readU32LE(recs[j].data, 16) : 0;\n const rawH = recs[j].data.length >= 28 ? BinaryKit.readU32LE(recs[j].data, 20) : 0;\n const wPt = rawW > 0 && rawW < MAX_HWP ? Metric.hwpToPt(rawW) : 0;\n const hPt = rawH > 0 && rawH < MAX_HWP ? Metric.hwpToPt(rawH) : 0;\n const imgId = ctrlId === CTRL_GSO ? gsoCtx.count++ : (recs[j].data.length >= 6 ? BinaryKit.readU16LE(recs[j].data, 4) : 0);\n ctrlHdrs.push({ ctrlId, imgId, wPt, hPt });\n j = skipKids(recs, j);\n }\n } else {\n j = skipKids(recs, j);\n }\n }\n else j++;\n }\n const paraContent: (SpanNode | ContentNode)[] = [];\n if (txt && txt.chars.length > 0) paraContent.push(...resolveCharShapes(txt.chars, csp, di));\n if (txt && txt.controls.length > 0) {\n for (let ci = 0; ci < txt.controls.length; ci++) {\n const ch = ctrlHdrs[ci];\n if (!ch) continue;\n const isImg = ch.ctrlId === CTRL_IMAGE || ch.ctrlId === CTRL_FIG || ch.ctrlId === CTRL_OBJ || ch.ctrlId === CTRL_GSO;\n if (!isImg) continue;\n const dimStr = (ch.wPt > 0 && ch.hPt > 0) ? `_W${Math.round(ch.wPt)}_H${Math.round(ch.hPt)}` : '';\n paraContent.push(buildSpan(`__EXT_${ch.imgId}${dimStr}__`));\n }\n }\n const kids = paraContent.length > 0 ? paraContent as any : [buildSpan('')];\n const items: (ParaNode | GridNode)[] = [buildPara(kids, buildParaProps(ps)), ...innerGrids];\n return { items, next: j };\n },\n { items: [buildPara([buildSpan('')])] as (ParaNode | GridNode)[], next: k + 1 },\n `hwp:cellP@${k}`,\n );\n cellChildren.push(...r.items);\n k = r.next;\n } else if (recs[k].tag === TAG_CTRL_HEADER && recs[k].data.length >= 4) {\n // CTRL_HEADER at cell level (sibling of PARA_HEADER) — anchored 'gso' images and outer-level nested tables\n const cellCtrlId = BinaryKit.readU32LE(recs[k].data, 0);\n if (cellCtrlId === CTRL_GSO) {\n const gsoId = gsoCtx.count++;\n const rawW = recs[k].data.length >= 24 ? BinaryKit.readU32LE(recs[k].data, 16) : 0;\n const rawH = recs[k].data.length >= 28 ? BinaryKit.readU32LE(recs[k].data, 20) : 0;\n const wPt = rawW > 0 && rawW < MAX_HWP ? Metric.hwpToPt(rawW) : 0;\n const hPt = rawH > 0 && rawH < MAX_HWP ? Metric.hwpToPt(rawH) : 0;\n const dimStr = (wPt > 0 && hPt > 0) ? `_W${Math.round(wPt)}_H${Math.round(hPt)}` : '';\n cellChildren.push(buildPara([buildSpan(`__EXT_${gsoId}${dimStr}__`)]));\n k = skipKids(recs, k);\n } else if (cellCtrlId === CTRL_TABLE) {\n const tr = shield.guard(\n () => parseTableCtrl(recs, k, di, shield, gsoCtx),\n { grid: null, next: skipKids(recs, k) },\n `hwp:nestedTbl@${k}`,\n );\n if (tr.grid) cellChildren.push(tr.grid as GridNode);\n k = tr.next;\n } else {\n k = skipKids(recs, k);\n }\n } else { k++; }\n }\n\n return {\n row, col, cs, rs, props, widthHwp,\n heightHwp: heightHwp || undefined,\n cellChildren: cellChildren.length ? cellChildren : [buildPara([buildSpan('')])],\n };\n}\n\n/* ── PAGE_DEF ───────────────────────────────────────────────── */\n/* [0:4] width [4:4] height [8:4] ml [12:4] mr\n [16:4] mt [20:4] mb [36:4] attr (bit0=landscape) */\n\nfunction parsePageDef(d: Uint8Array): PageDims {\n if (d.length < 24) return A4;\n const w = BinaryKit.readU32LE(d, 0);\n const h = BinaryKit.readU32LE(d, 4);\n const ml = BinaryKit.readU32LE(d, 8);\n const mr = BinaryKit.readU32LE(d, 12);\n const mt = BinaryKit.readU32LE(d, 16);\n const mb = BinaryKit.readU32LE(d, 20);\n const at = d.length >= 40 ? BinaryKit.readU32LE(d, 36) : 0;\n return {\n wPt: Metric.hwpToPt(w), hPt: Metric.hwpToPt(h),\n ml: Metric.hwpToPt(ml), mr: Metric.hwpToPt(mr),\n mt: Metric.hwpToPt(mt), mb: Metric.hwpToPt(mb),\n orient: (at & 1) ? 'landscape' : 'portrait',\n };\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Helpers\n ═══════════════════════════════════════════════════════════════ */\n\nfunction i32(d: Uint8Array, o: number): number {\n const u = BinaryKit.readU32LE(d, o);\n return u > 0x7FFFFFFF ? u - 0x100000000 : u;\n}\n\nfunction colorRef(d: Uint8Array, o: number): string {\n if (o + 3 > d.length) return '000000';\n return ((d[o] << 16) | (d[o + 1] << 8) | d[o + 2]).toString(16).padStart(6, '0').toUpperCase();\n}\n\nfunction toStroke(b: { type: number; widthPt: number; color: string }): Stroke {\n return { kind: BORDER_KIND[b.type] ?? 'solid', pt: b.widthPt, color: b.color };\n}\n\n// Apply borderFill to CellProps. Preserve explicit NONE so DOCX tcBorders can\n// override the table-level tblBorders. Filtering NONE would let tblBorders bleed through.\nfunction applyCellBorderFill(bf: HwpBorderFill, props: CellProps): void {\n if (bf.borders.length >= 4) {\n props.left = toStroke(bf.borders[0]);\n props.right = toStroke(bf.borders[1]);\n props.top = toStroke(bf.borders[2]);\n props.bot = toStroke(bf.borders[3]);\n }\n if (bf.bgColor && bf.bgColor !== 'FFFFFF') props.bg = bf.bgColor;\n}\n\nfunction strokeFromBF(bfId: number, di: DocInfo): Stroke | undefined {\n if (bfId <= 0 || bfId > di.borderFills.length) return undefined;\n const bf = di.borderFills[bfId - 1];\n if (!bf.borders.length) return undefined;\n const b = bf.borders[0];\n return { kind: BORDER_KIND[b.type] ?? 'solid', pt: b.widthPt, color: b.color };\n}\n\nfunction buildParaProps(ps?: HwpParaShape): ParaProps {\n if (!ps) return {};\n const p: ParaProps = {};\n if (ps.align && ps.align !== 'left') p.align = ps.align;\n if (ps.spaceBefore > 0) p.spaceBefore = Metric.hwpToPt(ps.spaceBefore);\n if (ps.spaceAfter > 0) p.spaceAfter = Metric.hwpToPt(ps.spaceAfter);\n if (ps.lineSpacing > 0 && ps.lineSpacing !== 160) p.lineHeight = ps.lineSpacing / 100;\n // leftMargin (offset 4) = 문단 몸체 왼쪽 여백 → leftMargin (pt), ensure non-negative\n const leftMarginPt = Math.max(0, Metric.hwpToPt(ps.leftMargin));\n if (leftMarginPt > 0) p.leftMargin = leftMarginPt;\n // indent (offset 12) = 첫 줄 들여쓰기(양수) / 내어쓰기(음수) → firstLineIndentPt\n if (ps.indent !== 0) p.firstLineIndentPt = Metric.hwpToPt(ps.indent);\n return p;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Decoder class\n ═══════════════════════════════════════════════════════════════ */\n\nexport class HwpScanner implements Decoder {\n readonly format = 'hwp';\n readonly aliases = ['application/vnd.hancom.hwp'];\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n if (!BinaryKit.isOle2(data)) return fail('HWP: Invalid OLE2 signature');\n const streams = BinaryKit.parseCfb(data);\n\n // FileHeader\n const fh = streams.get('FileHeader');\n const { compressed, encrypted } = fh ? parseFileHeader(fh) : { compressed: true, encrypted: false };\n if (encrypted) return fail('HWP: 암호화된 파일은 지원하지 않습니다');\n\n // DocInfo\n const diRaw = streams.get('DocInfo');\n let di: DocInfo = { faceNames: [], charShapes: [], paraShapes: [], borderFills: [] };\n if (diRaw) {\n di = shield.guard(() => parseDocInfo(diRaw, compressed), di, 'hwp:docInfo');\n }\n\n // Extract images from BinData streams.\n // HWP duplicates each BinData entry: once as \"BinData/BIN0001.jpg\" and once as \"BIN0001.jpg\".\n // We keep only the \"BinData/\" prefixed versions, sort by BIN number, then assign 0-based keys\n // matching the order 'gso' CTRL_HEADER records are encountered during body parsing.\n const binEntries: { binNum: number; data: Uint8Array }[] = [];\n for (const [path, streamData] of streams) {\n // Match \"BinData/BIN0001.jpg\" style — the canonical form\n const m = path.match(/^BinData[/\\\\]BIN(\\d+)\\.\\w+$/i);\n if (m) binEntries.push({ binNum: parseInt(m[1], 10), data: streamData });\n }\n // Sort by BIN number (ascending) so BIN0001→idx0, BIN0002→idx1, …\n binEntries.sort((a, b) => a.binNum - b.binNum);\n\n const objectMap = new Map<number, ImgNode>();\n for (let idx = 0; idx < binEntries.length; idx++) {\n const { data: imgData } = binEntries[idx];\n\n // Determine MIME type from binary signature first, then fall back to extension\n let mimeType: ImgNode['mime'] = 'image/jpeg';\n if (imgData[0] === 0x89 && imgData[1] === 0x50) mimeType = 'image/png';\n else if (imgData[0] === 0x47 && imgData[1] === 0x49) mimeType = 'image/gif';\n else if (imgData[0] === 0x42 && imgData[1] === 0x4D) mimeType = 'image/bmp';\n\n const base64 = TextKit.base64Encode(imgData);\n const { wPt, hPt } = getImageDimsPt(imgData, mimeType);\n objectMap.set(idx, buildImg(base64, mimeType, wPt, hPt));\n }\n\n // gsoCtx tracks sequential 'gso' encounter order — must be shared across all sections\n const gsoCtx: GsoCtx = { count: 0 };\n\n // Body sections\n const allContent: ContentNode[] = [];\n let pageDims: PageDims = A4;\n\n for (let s = 0; s < 100; s++) {\n const sec = streams.get(`BodyText/Section${s}`) ?? streams.get(`Section${s}`);\n if (!sec) {\n if (s === 0) {\n const fb = findBodySection(streams);\n if (fb) {\n const r = parseBody(fb, compressed, di, shield, gsoCtx);\n allContent.push(...r.content);\n if (r.pageDims) pageDims = r.pageDims;\n }\n }\n break;\n }\n const r = shield.guard(\n () => parseBody(sec, compressed, di, shield, gsoCtx),\n { content: [], pageDims: undefined },\n `hwp:sec${s}`,\n );\n allContent.push(...r.content);\n if (r.pageDims) pageDims = r.pageDims;\n }\n\n if (objectMap.size > 0) {\n injectImagesIntoContent(allContent, objectMap);\n }\n\n warns.push(...shield.flush());\n const content = allContent.length > 0 ? allContent : [buildPara([buildSpan('')])];\n return succeed(buildRoot({}, [buildSheet(content, pageDims)]), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`HWP decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\nfunction findBodySection(streams: Map<string, Uint8Array>): Uint8Array | undefined {\n for (const [k, v] of streams)\n if (k.includes('Section') && !k.includes('Header') && !k.includes('Info')) return v;\n return undefined;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Image dimension extraction from binary headers\n ════════════════════════════════════════════════════════════ */\n\n// Returns { wPt, hPt } by parsing image headers; falls back to { wPt: 72, hPt: 72 } (1-inch)\nfunction getImageDimsPt(data: Uint8Array, mime: string): { wPt: number; hPt: number } {\n const fallback = { wPt: 72, hPt: 72 };\n try {\n if (mime === 'image/png' && data.length >= 24) {\n // PNG IHDR: sig(8) + length(4) + type(4) + width(4) + height(4) — all big-endian\n const w = (data[16] << 24 | data[17] << 16 | data[18] << 8 | data[19]) >>> 0;\n const h = (data[20] << 24 | data[21] << 16 | data[22] << 8 | data[23]) >>> 0;\n if (w > 0 && h > 0) return { wPt: w * 0.75, hPt: h * 0.75 }; // 96 DPI → pt\n }\n if (mime === 'image/jpeg') {\n // Scan for SOF markers: FF C0 / C1 / C2 / C3\n let i = 2;\n while (i + 8 < data.length) {\n if (data[i] !== 0xFF) { i++; continue; }\n const marker = data[i + 1];\n if (marker >= 0xC0 && marker <= 0xC3) {\n // SOF: 2-byte marker + 2-byte length + 1-byte precision + 2-byte height + 2-byte width\n const h = (data[i + 5] << 8 | data[i + 6]) >>> 0;\n const w = (data[i + 7] << 8 | data[i + 8]) >>> 0;\n if (w > 0 && h > 0) return { wPt: w * 0.75, hPt: h * 0.75 };\n }\n const segLen = data[i + 2] << 8 | data[i + 3];\n i += 2 + (segLen > 0 ? segLen : 2);\n }\n }\n if (mime === 'image/bmp' && data.length >= 26) {\n // BMP DIB header: width at 18, height at 22 (signed int32 LE; negative = top-down)\n const w = BinaryKit.readU32LE(data, 18);\n const h = Math.abs(BinaryKit.readU32LE(data, 22) | 0);\n if (w > 0 && h > 0) return { wPt: w * 0.75, hPt: h * 0.75 };\n }\n if (mime === 'image/gif' && data.length >= 10) {\n // GIF: width at 6, height at 8 (uint16 LE)\n const w = data[6] | data[7] << 8;\n const h = data[8] | data[9] << 8;\n if (w > 0 && h > 0) return { wPt: w * 0.75, hPt: h * 0.75 };\n }\n } catch { /* ignore */ }\n return fallback;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n OLE Object extraction (images)\n ════════════════════════════════════════════════════════════ */\n\nfunction extractImagesFromOleObjectLink(data: Uint8Array): OleObject[] {\n const objects: OleObject[] = [];\n let off = 0;\n\n while (off + 8 <= data.length) {\n const objId = BinaryKit.readU32LE(data, off);\n const dataSize = BinaryKit.readU32LE(data, off + 4);\n const reserved = BinaryKit.readU32LE(data, off + 8);\n\n if (objId === 0 || dataSize === 0) break;\n\n const objOff = off + 16;\n if (objOff + dataSize > data.length) break;\n\n const objData = data.subarray(objOff, objOff + dataSize);\n\n // Detect MIME type from signature\n let mimeType = 'application/octet-stream';\n if (objData[0] === 0xFF && objData[1] === 0xD8 && objData[2] === 0xFF) {\n mimeType = 'image/jpeg';\n } else if (objData[0] === 0x89 && objData[1] === 0x50 && objData[2] === 0x4E && objData[3] === 0x47) {\n mimeType = 'image/png';\n } else if (objData[0] === 0x47 && objData[1] === 0x49 && objData[2] === 0x46 && objData[3] === 0x3538) {\n mimeType = 'image/gif';\n } else if (objData[0] === 0x42 && objData[1] === 0x4D) {\n mimeType = 'image/bmp';\n }\n\n objects.push({ id: objId, data: objData, mimeType });\n off = objOff + dataSize;\n }\n\n return objects;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Helper to inject images into paragraph content\n ════════════════════════════════════════════════════════════ */\n\nfunction injectImagesIntoContent(\n content: ContentNode[],\n objectMap: Map<number, ImgNode>\n): void {\n if (objectMap.size === 0) return;\n\n // Helper function to process a list of kids (spans, images, etc.)\n const processKids = (kids: any[]) => {\n for (let i = 0; i < kids.length; i++) {\n const kid = kids[i];\n // Span node structure: { tag: 'span', props, kids: [{ tag: 'txt', content }] }\n if (kid.tag === 'span' && kid.kids && kid.kids[0]?.tag === 'txt') {\n const text = kid.kids[0].content;\n // __EXT_N__ or __EXT_N_W<wPt>_H<hPt>__ (with encoded display size)\n // N is the objId that matches the index in objectMap\n const match = text.match?.(/^__(?:IMG|EXT)_(\\d+)(?:_W(\\d+)_H(\\d+))?__$/);\n if (match) {\n const objId = parseInt(match[1], 10);\n const base = objectMap.get(objId);\n if (base) {\n const wPt = match[2] ? parseInt(match[2], 10) : 0;\n const hPt = match[3] ? parseInt(match[3], 10) : 0;\n // Use encoded display size when valid; otherwise keep pixel-based dims\n kids[i] = (wPt > 0 && hPt > 0) ? { ...base, w: wPt, h: hPt } : base;\n }\n }\n }\n }\n };\n\n // Recursively process a grid (table): resolves image placeholders in all cells,\n // including nested grids inside cells.\n const processGridKids = (grid: any) => {\n if (!grid.kids || !Array.isArray(grid.kids)) return;\n\n for (const row of grid.kids) {\n if (!row.kids || !Array.isArray(row.kids)) continue;\n\n for (const cell of row.kids) {\n if (!cell.kids || !Array.isArray(cell.kids)) continue;\n\n for (const cellKid of cell.kids) {\n if (cellKid.tag === 'grid') {\n // Nested table inside cell — recurse\n processGridKids(cellKid);\n } else if (cellKid.tag === 'para' && cellKid.kids) {\n processKids(cellKid.kids);\n }\n }\n }\n }\n };\n\n for (const node of content) {\n if (node.tag === 'para' && node.kids) {\n // Process paragraph kids (spans, images, links, grids)\n processKids(node.kids);\n\n // Also process any nested grids inside the paragraph\n for (const kid of node.kids) {\n if (kid.tag === 'grid') {\n processGridKids(kid);\n }\n }\n } else if (node.tag === 'grid') {\n // Process grid nodes (tables)\n processGridKids(node);\n }\n }\n}\n\nregistry.registerDecoder(new HwpScanner());\n","import type {\n DocRoot,\n ContentNode,\n ParaNode,\n SpanNode,\n GridNode,\n ImgNode,\n LinkNode,\n PageNumNode,\n CellNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport type {\n DocMeta,\n PageDims,\n TextProps,\n ParaProps,\n CellProps,\n GridProps,\n TableLook,\n Stroke,\n ImgLayout,\n ImgHorzAlign,\n ImgVertAlign,\n ImgHorzRelTo,\n ImgVertRelTo,\n ImgWrap,\n} from \"../../model/doc-props\";\nimport { A4 } from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport {\n buildRoot,\n buildSheet,\n buildPara,\n buildSpan,\n buildImg,\n buildGrid,\n buildRow,\n buildCell,\n buildPb,\n} from \"../../model/builders\";\nimport { ShieldedParser } from \"../../safety/ShieldedParser\";\nimport {\n Metric,\n safeAlign,\n safeFont,\n safeHex,\n safeStrokeDocx,\n} from \"../../safety/StyleBridge\";\nimport { BaseDecoder } from \"../../core/BaseDecoder\";\nimport { ArchiveKit } from \"../../toolkit/ArchiveKit\";\nimport { XmlKit } from \"../../toolkit/XmlKit\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { registry } from \"../../pipeline/registry\";\n\nexport class DocxDecoder extends BaseDecoder {\n protected getFormat(): string {\n return \"docx\";\n }\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n const files = await ArchiveKit.unzip(data);\n\n const getFile = (path: string) => {\n const lower = path.toLowerCase();\n for (const [name, data] of files.entries()) {\n if (name.toLowerCase() === lower) return data;\n }\n return undefined;\n };\n\n const docXml = getFile(\"word/document.xml\");\n if (!docXml) return fail(\"DOCX: word/document.xml not found\");\n\n const relsXml = getFile(\"word/_rels/document.xml.rels\");\n const relsMap = relsXml\n ? await parseRels(TextKit.decode(relsXml))\n : new Map<string, string>();\n\n const coreXml = getFile(\"docProps/core.xml\");\n let meta: DocMeta = {};\n if (coreXml) {\n try {\n meta = await parseCoreProps(TextKit.decode(coreXml));\n } catch {\n // ignore — meta is optional\n }\n }\n\n // Parse numbering.xml for list support\n const numXml = getFile(\"word/numbering.xml\");\n let numMap: NumMap = new Map();\n if (numXml) {\n try {\n numMap = await parseNumbering(TextKit.decode(numXml));\n } catch {\n /* non-fatal */\n }\n }\n\n // Parse styles.xml for table and paragraph/character style defaults\n let stylesMap: StylesMap = new Map();\n let paraStyleMap: ParaStyleMap = new Map();\n const stylesXml = getFile(\"word/styles.xml\");\n if (stylesXml) {\n try {\n const stylesStr = TextKit.decode(stylesXml);\n stylesMap = await parseStylesMap(stylesStr);\n paraStyleMap = await parseParaStyleMap(stylesStr);\n } catch {\n /* non-fatal */\n }\n }\n\n let docStr = TextKit.decode(docXml).trim();\n if (!docStr) {\n warns.push(\n \"DOCX: word/document.xml is empty, using fallback empty document\",\n );\n docStr =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:document xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:body/></w:document>';\n }\n const docObj: any = await XmlKit.parseStrict(docStr);\n\n const body = getBody(docObj);\n const dims = extractDims(body) ?? { ...A4 };\n const elements = getBodyElements(body);\n console.log(\n `[DocxDecoder] 파싱된 전체 본문 요소 개수: ${elements.length}`,\n );\n\n const decCtx: DecCtx = {\n relsMap,\n files,\n shield,\n numMap,\n warns,\n stylesMap,\n paraStyleMap,\n };\n\n const kids: ContentNode[] = [];\n for (const el of elements) {\n const nodes = shield.guard(\n () => decodeElement(el, decCtx),\n [buildPara([buildSpan(\"[요소 파싱 실패]\")])],\n \"docx:bodyElement\",\n );\n if (Array.isArray(nodes)) {\n kids.push(...nodes);\n } else {\n kids.push(nodes);\n }\n\n // Inline sectPr in pPr = section break → insert page-break paragraph after\n if (el.type === \"para\") {\n const pPr = el.node?.[\"w:pPr\"]?.[0] ?? el.node?.pPr?.[0] ?? {};\n const inlineSectPr = pPr?.[\"w:sectPr\"]?.[0] ?? pPr?.sectPr?.[0];\n if (inlineSectPr) {\n const typeAttr = inlineSectPr?.[\"w:type\"]?.[0]?._attr;\n const sectType = typeAttr?.[\"w:val\"] ?? typeAttr?.val ?? \"nextPage\";\n if (sectType !== \"continuous\") {\n kids.push(\n buildPara([{ tag: \"span\", props: {}, kids: [buildPb()] }]),\n );\n }\n }\n }\n }\n\n // Decode header/footer\n const headersMap = await decodeHeaderFooter(\n \"header\",\n body,\n relsMap,\n files,\n decCtx,\n );\n const footersMap = await decodeHeaderFooter(\n \"footer\",\n body,\n relsMap,\n files,\n decCtx,\n );\n\n warns.push(...shield.flush());\n const sheet = buildSheet(kids.filter(Boolean) as ContentNode[], dims, {\n headers: headersMap,\n footers: footersMap,\n });\n return succeed(buildRoot(meta, [sheet]), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`DOCX decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\n// ─── types ─────────────────────────────────────────────────\n\ninterface TblBorderDef {\n top?: Stroke;\n bottom?: Stroke;\n left?: Stroke;\n right?: Stroke;\n insideH?: Stroke;\n insideV?: Stroke;\n}\n\n/** Parsed tblStyle defaults from styles.xml */\ninterface TblStyleDef {\n tblBorders?: TblBorderDef;\n cellBg?: string; // default cell background\n}\n\n/** Parsed paragraph/character style defaults */\ninterface ParaStyleDef {\n rPr?: {\n b?: boolean;\n i?: boolean;\n u?: boolean;\n s?: boolean;\n pt?: number;\n color?: string;\n font?: string;\n };\n pPr?: {\n align?: string;\n spaceBefore?: number;\n spaceAfter?: number;\n lineHeight?: number;\n indentPt?: number;\n indentRightPt?: number;\n firstLineIndentPt?: number;\n };\n basedOn?: string; // parent style id\n}\n\ntype StylesMap = Map<string, TblStyleDef>; // styleId → table style defaults\ntype ParaStyleMap = Map<string, ParaStyleDef>; // styleId → para/char style defaults\n\ninterface DecCtx {\n relsMap: Map<string, string>;\n files: Map<string, Uint8Array>;\n shield: ShieldedParser;\n numMap: NumMap;\n warns: string[];\n stylesMap: StylesMap;\n paraStyleMap: ParaStyleMap;\n}\n\n// numId → { abstractNumId, levels: Map<ilvl, { fmt, isOrdered }> }\ntype NumMap = Map<\n number,\n { levels: Map<number, { fmt: string; isOrdered: boolean }> }\n>;\n\n// ─── helpers ────────────────────────────────────────────────\n\nfunction toArr(v: any): any[] {\n return v == null ? [] : Array.isArray(v) ? v : [v];\n}\n\n/** Resolve DOCX relative paths. e.g. (\"word\", \"../media/image1.png\") → \"word/media/image1.png\" */\nfunction resolveDocxPath(baseDir: string, target: string): string {\n if (target.startsWith(\"/\")) return target.slice(1);\n const parts = (baseDir + \"/\" + target).split(\"/\");\n const stack: string[] = [];\n for (const p of parts) {\n if (p === \"..\") {\n stack.pop();\n } else if (p !== \".\") {\n stack.push(p);\n }\n }\n return stack.join(\"/\");\n}\n\nasync function parseRels(xml: string): Promise<Map<string, string>> {\n const map = new Map<string, string>();\n const trimmed = xml.trim();\n if (!trimmed) return map;\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n for (const rel of toArr(obj?.Relationships?.[0]?.Relationship)) {\n const a = rel?._attr ?? {};\n if (a.Id && a.Target) map.set(a.Id, a.Target);\n }\n } catch {\n /* ignore */\n }\n return map;\n}\n\nasync function parseCoreProps(xml: string): Promise<DocMeta> {\n const trimmed = xml.trim();\n if (!trimmed) return {};\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n const c = obj?.[\"cp:coreProperties\"]?.[0] ?? obj?.coreProperties?.[0] ?? {};\n return {\n title: c?.[\"dc:title\"]?.[0]?._text ?? undefined,\n author: c?.[\"dc:creator\"]?.[0]?._text ?? undefined,\n subject: c?.[\"dc:subject\"]?.[0]?._text ?? undefined,\n created: c?.[\"dcterms:created\"]?.[0]?._text ?? undefined,\n modified: c?.[\"dcterms:modified\"]?.[0]?._text ?? undefined,\n };\n } catch {\n return {};\n }\n}\n\nasync function parseNumbering(xml: string): Promise<NumMap> {\n const map: NumMap = new Map();\n const trimmed = xml.trim();\n if (!trimmed) return map;\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n const root = obj?.[\"w:numbering\"]?.[0] ?? obj?.numbering?.[0] ?? obj;\n\n // Parse abstractNums\n const absMap = new Map<\n number,\n Map<number, { fmt: string; isOrdered: boolean }>\n >();\n for (const abs of toArr(root?.[\"w:abstractNum\"] ?? root?.abstractNum)) {\n const absId = Number(\n abs?._attr?.[\"w:abstractNumId\"] ?? abs?._attr?.abstractNumId ?? 0,\n );\n const levels = new Map<number, { fmt: string; isOrdered: boolean }>();\n for (const lvl of toArr(abs?.[\"w:lvl\"] ?? abs?.lvl)) {\n const ilvl = Number(lvl?._attr?.[\"w:ilvl\"] ?? lvl?._attr?.ilvl ?? 0);\n const fmtNode =\n lvl?.[\"w:numFmt\"]?.[0]?._attr ?? lvl?.numFmt?.[0]?._attr ?? {};\n const fmt = fmtNode?.[\"w:val\"] ?? fmtNode?.val ?? \"decimal\";\n levels.set(ilvl, { fmt, isOrdered: fmt !== \"bullet\" });\n }\n absMap.set(absId, levels);\n }\n\n // Parse nums\n for (const num of toArr(root?.[\"w:num\"] ?? root?.num)) {\n const numId = Number(num?._attr?.[\"w:numId\"] ?? num?._attr?.numId ?? 0);\n const absRef =\n num?.[\"w:abstractNumId\"]?.[0]?._attr ??\n num?.abstractNumId?.[0]?._attr ??\n {};\n const absId = Number(absRef?.[\"w:val\"] ?? absRef?.val ?? 0);\n const levels = absMap.get(absId) ?? new Map();\n map.set(numId, { levels });\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\nfunction getBody(obj: any): any {\n // XML 파서에 따라 w:document 또는 document 형태일 수 있음\n const doc = obj?.[\"w:document\"]?.[0] ?? obj?.document?.[0] ?? obj;\n const body = doc?.[\"w:body\"]?.[0] ?? doc?.body?.[0] ?? doc;\n\n if (!body) {\n console.error(\"[DocxDecoder] 본문(body)을 찾을 수 없습니다.\");\n }\n return body;\n}\n\nfunction extractDims(body: any): PageDims | null {\n try {\n const sp = body?.[\"w:sectPr\"]?.[0] ?? body?.sectPr?.[0];\n if (!sp) return null;\n const sz = sp?.[\"w:pgSz\"]?.[0]?._attr ?? sp?.pgSz?.[0]?._attr;\n const mar = sp?.[\"w:pgMar\"]?.[0]?._attr ?? sp?.pgMar?.[0]?._attr;\n if (!sz) return null;\n const headerDxa = Number(mar?.[\"w:header\"] ?? mar?.header ?? 0);\n const footerDxa = Number(mar?.[\"w:footer\"] ?? mar?.footer ?? 0);\n return {\n wPt: Metric.dxaToPt(Number(sz[\"w:w\"] ?? sz.w ?? 11906)),\n hPt: Metric.dxaToPt(Number(sz[\"w:h\"] ?? sz.h ?? 16838)),\n mt: Metric.dxaToPt(Number(mar?.[\"w:top\"] ?? mar?.top ?? 1440)),\n mb: Metric.dxaToPt(Number(mar?.[\"w:bottom\"] ?? mar?.bottom ?? 1440)),\n ml: Metric.dxaToPt(Number(mar?.[\"w:left\"] ?? mar?.left ?? 1800)),\n mr: Metric.dxaToPt(Number(mar?.[\"w:right\"] ?? mar?.right ?? 1800)),\n orient:\n (sz[\"w:orient\"] ?? sz.orient) === \"landscape\"\n ? \"landscape\"\n : \"portrait\",\n headerPt: headerDxa > 0 ? Metric.dxaToPt(headerDxa) : undefined,\n footerPt: footerDxa > 0 ? Metric.dxaToPt(footerDxa) : undefined,\n };\n } catch {\n return null;\n }\n}\n\nfunction getBodyElements(body: any): { type: string; node: any }[] {\n const paras = toArr(body?.[\"w:p\"] ?? body?.p);\n const tables = toArr(body?.[\"w:tbl\"] ?? body?.tbl);\n const sdts = toArr(body?.[\"w:sdt\"] ?? body?.sdt);\n\n const childOrder = body?.[\"_childOrder\"] as string[] | undefined;\n if (Array.isArray(childOrder)) {\n const items: { type: string; node: any }[] = [];\n let pi = 0,\n ti = 0,\n si = 0;\n for (const tag of childOrder) {\n if ((tag === \"w:p\" || tag === \"p\") && pi < paras.length) {\n items.push({ type: \"para\", node: paras[pi++] });\n } else if ((tag === \"w:tbl\" || tag === \"tbl\") && ti < tables.length) {\n items.push({ type: \"table\", node: tables[ti++] });\n } else if ((tag === \"w:sdt\" || tag === \"sdt\") && si < sdts.length) {\n items.push({ type: \"sdt\", node: sdts[si++] });\n }\n }\n // Append any remainders\n while (pi < paras.length) items.push({ type: \"para\", node: paras[pi++] });\n while (ti < tables.length)\n items.push({ type: \"table\", node: tables[ti++] });\n while (si < sdts.length) items.push({ type: \"sdt\", node: sdts[si++] });\n return items;\n }\n\n // Fallback: paragraphs, then tables, then sdts\n return [\n ...paras.map((n: any) => ({ type: \"para\", node: n })),\n ...tables.map((n: any) => ({ type: \"table\", node: n })),\n ...sdts.map((n: any) => ({ type: \"sdt\", node: n })),\n ];\n}\n\n// ─── Header/Footer decoding ────────────────────────────────\n\nasync function decodeHeaderFooter(\n kind: \"header\" | \"footer\",\n body: any,\n relsMap: Map<string, string>, // document.xml.rels (기존)\n files: Map<string, Uint8Array>,\n ctx: DecCtx,\n): Promise<Record<string, ParaNode[]> | undefined> {\n try {\n const sp = body?.[\"w:sectPr\"]?.[0] ?? body?.sectPr?.[0];\n if (!sp) return undefined;\n\n const refTag =\n kind === \"header\" ? \"w:headerReference\" : \"w:footerReference\";\n const refs = toArr(sp?.[refTag] ?? sp?.[refTag.replace(\"w:\", \"\")]);\n if (refs.length === 0) return undefined;\n\n const result: Record<string, ParaNode[]> = {};\n\n for (const ref of refs) {\n const type = ref._attr?.[\"w:type\"] ?? ref._attr?.type ?? \"default\";\n const rId = ref._attr?.[\"r:id\"] ?? ref._attr?.[\"r:Id\"] ?? ref._attr?.id;\n if (!rId) continue;\n\n const target = relsMap.get(rId);\n if (!target) continue;\n\n const filePath = resolveDocxPath(\"word\", target);\n const fileData = files.get(filePath);\n if (!fileData) continue;\n\n // ★ 핵심 수정: 헤더/풋터 전용 rels 파일 로드\n const hfFileName = filePath.split(\"/\").pop() ?? \"\";\n const hfRelsPath = `word/_rels/${hfFileName}.rels`;\n const hfRelsData = files.get(hfRelsPath);\n // 헤더/풋터 rels를 document rels와 병합\n let hfRelsMap = relsMap;\n if (hfRelsData) {\n const hfRelsStr = TextKit.decode(hfRelsData).trim();\n const parsed = hfRelsStr\n ? await parseRels(hfRelsStr)\n : new Map<string, string>();\n // 병합 (헤더/풋터 rels 우선)\n hfRelsMap = new Map([...relsMap, ...parsed]);\n }\n\n const xmlStr = TextKit.decode(fileData).trim();\n if (!xmlStr) continue;\n\n const watermark = extractWatermark(xmlStr);\n if (watermark) {\n result[type] = [\n buildPara([\n buildSpan(watermark, { pt: 80, color: \"CCCCCC\", b: true }),\n ]),\n ];\n continue;\n }\n\n try {\n const obj: any = await XmlKit.parseStrict(xmlStr);\n const rootTag = kind === \"header\" ? \"w:hdr\" : \"w:ftr\";\n const root =\n obj?.[rootTag]?.[0] ?? obj?.[rootTag.replace(\"w:\", \"\")]?.[0] ?? obj;\n\n // ctx에 hfRelsMap 임시 적용\n const origRelsMap = ctx.relsMap;\n (ctx as any).relsMap = hfRelsMap;\n const paras = toArr(root?.[\"w:p\"] ?? root?.p);\n result[type] = paras.map((p: any) => decodePara(p, ctx));\n (ctx as any).relsMap = origRelsMap;\n } catch (err) {\n console.warn(`[DocxDecoder] ${kind} (${type}) XML 파싱 실패:`, err);\n continue;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** 워터마크 텍스트 추출 (VML v:textpath 기반) */\nfunction extractWatermark(xml: string): string | null {\n if (!xml.includes(\"v:textpath\")) return null;\n const m = xml.match(/string=\"([^\"]+)\"/);\n return m ? m[1] : null;\n}\n\n// ─── Element decoding ──────────────────────────────────────\n\n//만약에 drawing 태그가 안에 있으면 true 반환\nfunction hasDrawingDeep(node: any): boolean {\n if (!node || typeof node !== \"object\") return false;\n\n if (node[\"w:drawing\"] || node[\"w:pict\"]) return true;\n\n return Object.values(node).some((v) => {\n if (Array.isArray(v)) return v.some(hasDrawingDeep);\n return hasDrawingDeep(v);\n });\n}\n\nfunction decodeElement(\n el: { type: string; node: any },\n ctx: DecCtx,\n): ContentNode | ContentNode[] {\n if (el.type === \"table\") {\n const { value } = ctx.shield.guardGrid(\n el.node,\n (n) => decodeGrid(n as any, ctx),\n (n) => decodeGridSimple(n as any),\n (n) => decodeGridFlat(n as any),\n (n) => decodeGridText(n as any) as unknown as GridNode,\n \"docx:table\",\n );\n return value;\n } else if (el.type === \"sdt\") {\n return decodeSdt(el.node, ctx);\n }\n return decodePara(el.node, ctx);\n}\n\nfunction decodeSdt(sdt: any, ctx: DecCtx): ContentNode[] {\n const content = sdt?.[\"w:sdtContent\"]?.[0] ?? sdt?.sdtContent?.[0];\n if (!content) return [];\n const elements = getBodyElements(content);\n const kids: ContentNode[] = [];\n for (const el of elements) {\n const res = decodeElement(el, ctx);\n if (Array.isArray(res)) kids.push(...res);\n else kids.push(res);\n }\n return kids;\n}\n\nfunction decodePara(p: any, ctx: DecCtx): ParaNode {\n const pPr = p?.[\"w:pPr\"]?.[0] ?? {};\n const alignVal =\n pPr?.[\"w:jc\"]?.[0]?._attr?.[\"w:val\"] ?? pPr?.[\"w:jc\"]?.[0]?._attr?.val;\n const headStyle =\n pPr?.[\"w:pStyle\"]?.[0]?._attr?.[\"w:val\"] ??\n pPr?.[\"w:pStyle\"]?.[0]?._attr?.val ??\n \"\";\n\n // Resolve paragraph style inheritance chain\n const styleInherited = resolveParaStyle(\n headStyle || undefined,\n ctx.paraStyleMap,\n );\n\n const props: ParaProps = {\n align: safeAlign(alignVal),\n heading: parseHeading(headStyle),\n styleId: headStyle || undefined,\n };\n\n // Spacing (before/after/line height) — inline pPr wins over style\n const spacingAttr =\n pPr?.[\"w:spacing\"]?.[0]?._attr ?? pPr?.spacing?.[0]?._attr ?? {};\n const beforeVal = Number(\n spacingAttr?.[\"w:before\"] ?? spacingAttr?.before ?? 0,\n );\n const afterVal = Number(spacingAttr?.[\"w:after\"] ?? spacingAttr?.after ?? 0);\n const lineVal = Number(spacingAttr?.[\"w:line\"] ?? spacingAttr?.line ?? 0);\n const lineRule =\n spacingAttr?.[\"w:lineRule\"] ?? spacingAttr?.lineRule ?? \"auto\";\n if (beforeVal > 0) props.spaceBefore = Metric.dxaToPt(beforeVal);\n else if (styleInherited.pPr?.spaceBefore)\n props.spaceBefore = styleInherited.pPr.spaceBefore;\n if (afterVal > 0) props.spaceAfter = Metric.dxaToPt(afterVal);\n else if (styleInherited.pPr?.spaceAfter)\n props.spaceAfter = styleInherited.pPr.spaceAfter;\n if (lineVal > 0 && lineRule === \"auto\") props.lineHeight = lineVal / 240;\n else if (styleInherited.pPr?.lineHeight)\n props.lineHeight = styleInherited.pPr.lineHeight;\n\n // Indentation\n const indAttr = pPr?.[\"w:ind\"]?.[0]?._attr ?? pPr?.ind?.[0]?._attr ?? {};\n const leftVal = Number(indAttr?.[\"w:left\"] ?? indAttr?.left ?? 0);\n const rightVal = Number(indAttr?.[\"w:right\"] ?? indAttr?.right ?? 0);\n const firstLineVal = Number(\n indAttr?.[\"w:firstLine\"] ?? indAttr?.firstLine ?? 0,\n );\n const hangingVal = Number(indAttr?.[\"w:hanging\"] ?? indAttr?.hanging ?? 0);\n if (leftVal > 0) props.indentPt = Metric.dxaToPt(leftVal);\n else if (styleInherited.pPr?.indentPt)\n props.indentPt = styleInherited.pPr.indentPt;\n if (rightVal > 0) props.indentRightPt = Metric.dxaToPt(rightVal);\n else if (styleInherited.pPr?.indentRightPt)\n props.indentRightPt = styleInherited.pPr.indentRightPt;\n if (firstLineVal > 0) props.firstLineIndentPt = Metric.dxaToPt(firstLineVal);\n else if (hangingVal > 0)\n props.firstLineIndentPt = -Metric.dxaToPt(hangingVal);\n else if (styleInherited.pPr?.firstLineIndentPt)\n props.firstLineIndentPt = styleInherited.pPr.firstLineIndentPt;\n\n // Alignment from style if not set inline\n if (!alignVal && styleInherited.pPr?.align)\n props.align = safeAlign(styleInherited.pPr.align);\n\n // List/numbering\n const numPr = pPr?.[\"w:numPr\"]?.[0] ?? pPr?.numPr?.[0];\n if (numPr) {\n const ilvlNode =\n numPr?.[\"w:ilvl\"]?.[0]?._attr ?? numPr?.ilvl?.[0]?._attr ?? {};\n const numIdNode =\n numPr?.[\"w:numId\"]?.[0]?._attr ?? numPr?.numId?.[0]?._attr ?? {};\n const ilvl = Number(ilvlNode?.[\"w:val\"] ?? ilvlNode?.val ?? 0);\n const numId = Number(numIdNode?.[\"w:val\"] ?? numIdNode?.val ?? 0);\n\n props.listLv = ilvl;\n const numEntry = ctx.numMap.get(numId);\n if (numEntry) {\n const lvlInfo = numEntry.levels.get(ilvl) ?? numEntry.levels.get(0);\n props.listOrd = lvlInfo?.isOrdered ?? false;\n } else {\n // Fallback: numId=1 is typically bullet, numId=2 is numbered\n props.listOrd = numId >= 2;\n }\n }\n\n // pageBreakBefore: paragraph always starts on a new page\n const pbBeforeNode =\n pPr?.[\"w:pageBreakBefore\"]?.[0] ?? pPr?.pageBreakBefore?.[0];\n const hasPageBreakBefore =\n pbBeforeNode != null &&\n (pbBeforeNode?._attr?.[\"w:val\"] ?? pbBeforeNode?._attr?.val ?? \"1\") !== \"0\";\n\n // Resolve all children (runs AND hyperlinks) in document order\n const children = p?.[\"_childOrder\"] as string[] | undefined;\n const kids: (SpanNode | ImgNode | LinkNode)[] = [];\n\n if (Array.isArray(children)) {\n const runsArr = toArr(p?.[\"w:r\"] ?? p?.r);\n const hlArr = toArr(p?.[\"w:hyperlink\"] ?? p?.hyperlink);\n const sdtArr = toArr(p?.[\"w:sdt\"] ?? p?.sdt);\n let ri = 0;\n let hi = 0;\n let si = 0;\n\n for (const tag of children) {\n if (tag === \"w:r\" || tag === \"r\") {\n const run = runsArr[ri++];\n if (run) {\n kids.push(\n ctx.shield.guard(\n () =>\n hasDrawingDeep(run)\n ? decodeRunOrImage(run, ctx)\n : decodeRun(run, ctx, styleInherited.rPr),\n buildSpan(\"\"),\n \"docx:run\",\n ),\n );\n }\n } else if (tag === \"w:hyperlink\" || tag === \"hyperlink\") {\n const hl = hlArr[hi++];\n if (hl) {\n const rId = hl?._attr?.[\"r:id\"] ?? hl?._attr?.id;\n const url = rId ? ctx.relsMap.get(rId) : \"\";\n const hlRuns = toArr(hl?.[\"w:r\"] ?? hl?.r);\n const hlKids = hlRuns.map((r: any) =>\n decodeRun(r, ctx, {\n ...styleInherited.rPr,\n u: true,\n color: \"0000FF\",\n }),\n );\n kids.push({\n tag: \"link\",\n href: url || \"\",\n kids: hlKids,\n });\n }\n } else if (tag === \"w:sdt\" || tag === \"sdt\") {\n const sdt = sdtArr[si++];\n if (sdt) {\n const sdtContent = sdt?.[\"w:sdtContent\"]?.[0] ?? sdt?.sdtContent?.[0];\n if (sdtContent) {\n const innerRuns = toArr(sdtContent?.[\"w:r\"] ?? sdtContent?.r);\n for (const ir of innerRuns) {\n kids.push(\n ctx.shield.guard(\n () =>\n hasDrawingDeep(ir)\n ? decodeRunOrImage(ir, ctx)\n : decodeRun(ir, ctx, styleInherited.rPr),\n buildSpan(\"\"),\n \"docx:run\",\n ),\n );\n }\n }\n }\n }\n }\n } else {\n // Fallback if _childOrder is missing\n const runs = toArr(p?.[\"w:r\"] ?? p?.r);\n const legacyKids: (SpanNode | ImgNode)[] = ctx.shield.guardAll(\n runs,\n (run: any) =>\n hasDrawingDeep(run)\n ? decodeRunOrImage(run, ctx)\n : decodeRun(run, ctx, styleInherited.rPr),\n () => buildSpan(\"\"),\n \"docx:run\",\n );\n kids.push(...legacyKids);\n }\n\n const filteredKids = kids.filter(Boolean) as ParaNode[\"kids\"];\n\n // Prepend pb span when pageBreakBefore is set\n if (hasPageBreakBefore) {\n filteredKids.unshift({ tag: \"span\", props: {}, kids: [buildPb()] });\n }\n\n return buildPara(filteredKids, props);\n}\n\n// 3/28 코드 수정\nfunction decodeRunOrImage(run: any, ctx: DecCtx): SpanNode | ImgNode {\n function findFirstDrawing(node: any): any | null {\n if (!node || typeof node !== \"object\") return null;\n\n if (node[\"w:drawing\"]) return node[\"w:drawing\"][0];\n if (node[\"w:pict\"]) return node[\"w:pict\"][0];\n\n for (const value of Object.values(node)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n const found = findFirstDrawing(v);\n if (found) return found;\n }\n } else {\n const found = findFirstDrawing(value);\n if (found) return found;\n }\n }\n\n return null;\n }\n\n const drawing = findFirstDrawing(run);\n\n if (drawing) {\n const img = decodeDrawing(drawing, ctx);\n if (img) return img;\n }\n\n return decodeRun(run, ctx);\n}\n/** Decode image layout from anchor element */\nfunction decodeImageLayout(anchor: any): ImgLayout {\n const wrap = anchor?.[\"wp:wrapTop\"]?.[0] ?? anchor?.wrapTop?.[0];\n const anchorPos =\n anchor?.[\"wp:anchorPos\"]?.[0]?._attr ?? anchor?.anchorPos?.[0]?._attr ?? {};\n\n const layout: ImgLayout = {\n wrap: \"square\",\n horzAlign: \"left\",\n vertAlign: \"top\",\n horzRelTo: \"page\",\n vertRelTo: \"page\",\n xPt: Number(anchorPos?.x ?? 0) / 12700, // emu to pt\n yPt: Number(anchorPos?.y ?? 0) / 12700, // emu to pt\n };\n\n // Parse wrap type\n if (wrap?.[\"wp:none\"]) layout.wrap = \"none\";\n else if (wrap?.[\"wp:square\"]) layout.wrap = \"square\";\n else if (wrap?.[\"wp:tight\"]) layout.wrap = \"tight\";\n else if (wrap?.[\"wp:through\"]) layout.wrap = \"through\";\n else if (wrap?.[\"wp:behind\"]) layout.wrap = \"behind\";\n else if (wrap?.[\"wp:inFront\"]) layout.wrap = \"front\";\n\n return layout;\n}\n\nfunction decodeDrawing(drawing: any, ctx: DecCtx): ImgNode | null {\n try {\n const inline = drawing?.[\"wp:inline\"]?.[0] ?? drawing?.inline?.[0];\n const anchor = drawing?.[\"wp:anchor\"]?.[0] ?? drawing?.anchor?.[0];\n const container = inline ?? anchor;\n if (!container) return null;\n\n // Get dimensions\n const extent =\n container?.[\"wp:extent\"]?.[0]?._attr ??\n container?.extent?.[0]?._attr ??\n {};\n const cx = Number(extent?.cx ?? 0);\n const cy = Number(extent?.cy ?? 0);\n const wPt = Metric.emuToPt(cx);\n const hPt = Metric.emuToPt(cy);\n\n // Get alt text\n const docPr =\n container?.[\"wp:docPr\"]?.[0]?._attr ?? container?.docPr?.[0]?._attr ?? {};\n const alt = docPr?.descr ?? docPr?.name ?? \"\";\n\n // Navigate to blip\n const graphic = container?.[\"a:graphic\"]?.[0] ?? container?.graphic?.[0];\n const graphicData =\n graphic?.[\"a:graphicData\"]?.[0] ?? graphic?.graphicData?.[0];\n\n // 1. 차트 감지\n if (graphicData?.[\"c:chart\"] || graphicData?.chart) {\n return {\n tag: \"img\",\n b64: \"\", // 플레이스홀더\n mime: \"image/png\",\n w: wPt,\n h: hPt,\n alt: `[차트: ${alt || \"차트\"}]`,\n layout: decodeImageLayout(anchor),\n };\n }\n\n const pic = graphicData?.[\"pic:pic\"]?.[0] ?? graphicData?.pic?.[0];\n const blipFill = pic?.[\"pic:blipFill\"]?.[0] ?? pic?.blipFill?.[0];\n const blip =\n blipFill?.[\"a:blip\"]?.[0]?._attr ?? blipFill?.blip?.[0]?._attr ?? {};\n const rId = blip?.[\"r:embed\"] ?? blip?.embed;\n\n if (!rId) return null;\n\n const target = ctx.relsMap.get(rId);\n if (!target) return null;\n\n let filePath = resolveDocxPath(\"word\", target);\n let fileData = ctx.files.get(filePath);\n\n if (!fileData) {\n filePath = resolveDocxPath(\"word/_rels\", target);\n fileData = ctx.files.get(filePath);\n }\n\n if (!fileData) {\n const fileName = target.split(\"/\").pop() ?? \"\";\n for (const [k, v] of ctx.files) {\n if (fileName && (k.endsWith(\"/\" + fileName) || k === fileName)) {\n fileData = v;\n filePath = k;\n break;\n }\n }\n }\n\n if (!fileData) {\n console.warn(`[DocxDecoder] image not found: \"${target}\"`);\n return null;\n }\n\n const ext = target.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const mimeMap: Record<string, ImgNode[\"mime\"]> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n bmp: \"image/bmp\",\n };\n const mime = mimeMap[ext] ?? \"image/png\";\n console.log(\n `[DocxDecoder] image loaded: ${filePath} (${mime}, ${fileData.length} bytes)`,\n );\n\n // ── layout 추출 ──────────────────────────────────────────\n const layout: ImgLayout = inline\n ? { wrap: \"inline\" }\n : extractAnchorLayout(anchor);\n\n return buildImg(\n TextKit.base64Encode(fileData),\n mime,\n wPt,\n hPt,\n alt || undefined,\n layout,\n );\n } catch {\n return null;\n }\n}\n\n/** w:highlight val → hex 색상 매핑 (OOXML 명세) */\nconst HIGHLIGHT_COLOR_MAP: Record<string, string> = {\n yellow: \"FFFF00\",\n green: \"00FF00\",\n cyan: \"00FFFF\",\n magenta: \"FF00FF\",\n blue: \"0000FF\",\n red: \"FF0000\",\n darkBlue: \"00008B\",\n darkCyan: \"008B8B\",\n darkGreen: \"006400\",\n darkMagenta: \"8B008B\",\n darkRed: \"8B0000\",\n darkYellow: \"808000\",\n darkGray: \"A9A9A9\",\n lightGray: \"D3D3D3\",\n black: \"000000\",\n white: \"FFFFFF\",\n};\n\nfunction decodeRun(\n run: any,\n ctx: DecCtx,\n styleRpr?: ParaStyleDef[\"rPr\"],\n): SpanNode {\n const rPr = run?.[\"w:rPr\"]?.[0] ?? run?.rPr?.[0] ?? {};\n\n // w:vanish — 숨긴 텍스트: run 전체 건너뜀 (빈 span 반환)\n const vanishNode = rPr?.[\"w:vanish\"]?.[0] ?? rPr?.vanish?.[0];\n if (vanishNode != null) {\n const vanishVal =\n vanishNode?._attr?.[\"w:val\"] ?? vanishNode?._attr?.val ?? \"1\";\n if (vanishVal !== \"0\") return buildSpan(\"\");\n }\n\n // w:sz → 없으면 w:szCs 로 fallback (한글 글꼴 크기)\n const szAttr = rPr?.[\"w:sz\"]?.[0]?._attr ?? rPr?.sz?.[0]?._attr ?? {};\n const szVal = szAttr?.[\"w:val\"] ?? szAttr?.val;\n const szCsAttr = rPr?.[\"w:szCs\"]?.[0]?._attr ?? rPr?.szCs?.[0]?._attr ?? {};\n const szCsVal = szCsAttr?.[\"w:val\"] ?? szCsAttr?.val;\n const effectiveSzVal = szVal ?? szCsVal;\n\n const colorAttr =\n rPr?.[\"w:color\"]?.[0]?._attr ?? rPr?.color?.[0]?._attr ?? {};\n const colorVal = colorAttr?.[\"w:val\"] ?? colorAttr?.val;\n\n const fontAttr =\n rPr?.[\"w:rFonts\"]?.[0]?._attr ?? rPr?.rFonts?.[0]?._attr ?? {};\n const fontName =\n fontAttr?.[\"w:ascii\"] ??\n fontAttr?.ascii ??\n fontAttr?.[\"w:hAnsi\"] ??\n fontAttr?.hAnsi ??\n fontAttr?.[\"w:eastAsia\"] ??\n fontAttr?.eastAsia;\n\n const underVal =\n rPr?.[\"w:u\"]?.[0]?._attr?.[\"w:val\"] ?? rPr?.[\"w:u\"]?.[0]?._attr?.val;\n\n // w:shd — 배경색 (낮은 우선순위)\n const shdAttr = rPr?.[\"w:shd\"]?.[0]?._attr ?? rPr?.shd?.[0]?._attr ?? {};\n const shdBg = safeHex(shdAttr?.[\"w:fill\"] ?? shdAttr?.fill);\n\n // w:highlight — 형광펜 색상 (w:shd보다 우선)\n const hlAttr =\n rPr?.[\"w:highlight\"]?.[0]?._attr ?? rPr?.highlight?.[0]?._attr ?? {};\n const hlVal = hlAttr?.[\"w:val\"] ?? hlAttr?.val;\n const bgVal = (hlVal ? HIGHLIGHT_COLOR_MAP[hlVal] : undefined) ?? shdBg;\n\n // w:vertAlign — superscript / subscript\n const vertAlignVal =\n rPr?.[\"w:vertAlign\"]?.[0]?._attr?.[\"w:val\"] ??\n rPr?.[\"w:vertAlign\"]?.[0]?._attr?.val;\n\n // w:position — 글자 상하 이동 (half-point, 양수=위, 음수=아래)\n // vertAlign이 없을 때 보조 판단: ±4 half-pt(≈2pt) 이상이면 sup/sub\n const posAttr =\n rPr?.[\"w:position\"]?.[0]?._attr ?? rPr?.position?.[0]?._attr ?? {};\n const posVal = Number(posAttr?.[\"w:val\"] ?? posAttr?.val ?? 0);\n let isSup = vertAlignVal === \"superscript\";\n let isSub = vertAlignVal === \"subscript\";\n if (!isSup && !isSub && posVal !== 0) {\n if (posVal >= 4) isSup = true;\n else if (posVal <= -4) isSub = true;\n }\n\n // Check bold/italic/strike — val=\"0\" means explicitly OFF\n const bNode = rPr?.[\"w:b\"]?.[0] ?? rPr?.b?.[0];\n const isBold =\n bNode != null &&\n (bNode?._attr?.[\"w:val\"] ?? bNode?._attr?.val ?? \"1\") !== \"0\";\n const iNode = rPr?.[\"w:i\"]?.[0] ?? rPr?.i?.[0];\n const isItalic =\n iNode != null &&\n (iNode?._attr?.[\"w:val\"] ?? iNode?._attr?.val ?? \"1\") !== \"0\";\n const sNode = rPr?.[\"w:strike\"]?.[0] ?? rPr?.strike?.[0];\n const isStrike =\n sNode != null &&\n (sNode?._attr?.[\"w:val\"] ?? sNode?._attr?.val ?? \"1\") !== \"0\";\n\n // Run-level properties: run wins, then fall back to paragraph style inheritance\n const props: TextProps = {\n b: (bNode != null ? isBold : styleRpr?.b) || undefined,\n i: (iNode != null ? isItalic : styleRpr?.i) || undefined,\n u: (underVal ? underVal !== \"none\" : styleRpr?.u) || undefined,\n s: (sNode != null ? isStrike : styleRpr?.s) || undefined,\n sup: isSup || undefined,\n sub: isSub || undefined,\n pt: effectiveSzVal\n ? Metric.halfPtToPt(Number(effectiveSzVal))\n : styleRpr?.pt,\n color: safeHex(colorVal) ?? styleRpr?.color,\n font: fontName ? safeFont(fontName) : styleRpr?.font,\n bg: bgVal,\n };\n\n // Check for field codes (PAGE number)\n const fldChar = run?.[\"w:fldChar\"]?.[0]?._attr ?? run?.fldChar?.[0]?._attr;\n const instrText = run?.[\"w:instrText\"]?.[0];\n\n // Page break: <w:br w:type=\"page\"/>\n const brNodes = toArr(run?.[\"w:br\"] ?? run?.br ?? []);\n for (const br of brNodes) {\n const brType = br?._attr?.[\"w:type\"] ?? br?._attr?.type;\n if (brType === \"page\") {\n return { tag: \"span\", props, kids: [buildPb()] };\n }\n }\n\n const textNodes = toArr(run?.[\"w:t\"] ?? run?.t);\n const content = textNodes\n .map((t: any) => (typeof t === \"string\" ? t : (t?._ ?? t?._text ?? \"\")))\n .join(\"\");\n\n // Handle page number field in instrText\n if (instrText) {\n const instrStr =\n typeof instrText === \"string\" ? instrText : (instrText?._text ?? \"\");\n if (instrStr.trim().toUpperCase() === \"PAGE\") {\n const pageNum: PageNumNode = { tag: \"pagenum\", format: \"decimal\" };\n return { tag: \"span\", props, kids: [pageNum] };\n }\n }\n\n return buildSpan(content, props);\n}\n\n/** Parse all 6 border sides from a w:tblBorders or w:tcBorders node */\nfunction parseBorderDef(bdrNode: any): TblBorderDef {\n const sides: [string, keyof TblBorderDef][] = [\n [\"top\", \"top\"],\n [\"bottom\", \"bottom\"],\n [\"left\", \"left\"],\n [\"right\", \"right\"],\n [\"insideH\", \"insideH\"],\n [\"insideV\", \"insideV\"],\n ];\n const result: TblBorderDef = {};\n for (const [xml, prop] of sides) {\n const bdr = bdrNode?.[\"w:\" + xml]?.[0]?._attr ?? bdrNode?.[xml]?.[0]?._attr;\n if (!bdr) continue;\n const val = bdr?.[\"w:val\"] ?? bdr?.val;\n if (val === \"none\" || val === \"nil\") continue; // explicit none → skip (no border)\n result[prop] = safeStrokeDocx(\n val,\n Number(bdr?.[\"w:sz\"] ?? bdr?.sz ?? 4),\n bdr?.[\"w:color\"] ?? bdr?.color,\n );\n }\n return result;\n}\n\n/** Parse styles.xml and build a map of tblStyle defaults */\nasync function parseStylesMap(xml: string): Promise<StylesMap> {\n const map: StylesMap = new Map();\n const trimmed = xml.trim();\n if (!trimmed) return map;\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n const stylesRoot = obj?.[\"w:styles\"]?.[0] ?? obj?.styles?.[0] ?? obj;\n const styleArr = toArr(stylesRoot?.[\"w:style\"] ?? stylesRoot?.style);\n for (const style of styleArr) {\n const attr = style?._attr ?? {};\n const type = attr?.[\"w:type\"] ?? attr?.type;\n if (type !== \"table\") continue;\n const id = attr?.[\"w:styleId\"] ?? attr?.styleId;\n if (!id) continue;\n const tblPr = style?.[\"w:tblPr\"]?.[0] ?? style?.tblPr?.[0];\n const tblBdrNode = tblPr?.[\"w:tblBorders\"]?.[0] ?? tblPr?.tblBorders?.[0];\n const tblBorders = tblBdrNode ? parseBorderDef(tblBdrNode) : undefined;\n // tcStyle > tcBdr for default cell borders\n const tcStyle = style?.[\"w:tcStyle\"]?.[0] ?? style?.tcStyle?.[0];\n const tcBdrNode = tcStyle?.[\"w:tcBdr\"]?.[0] ?? tcStyle?.tcBdr?.[0];\n if (tcBdrNode) {\n const cellDef = parseBorderDef(tcBdrNode);\n // merge into tblBorders as inner/outer defaults\n if (!tblBorders) {\n map.set(id, { tblBorders: cellDef });\n } else {\n map.set(id, { tblBorders: { ...cellDef, ...tblBorders } });\n }\n } else if (tblBorders) {\n map.set(id, { tblBorders });\n }\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\n/** Parse styles.xml and build a map of paragraph/character style defaults */\nasync function parseParaStyleMap(xml: string): Promise<ParaStyleMap> {\n const map: ParaStyleMap = new Map();\n const trimmed = xml.trim();\n if (!trimmed) return map;\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n const stylesRoot = obj?.[\"w:styles\"]?.[0] ?? obj?.styles?.[0] ?? obj;\n const styleArr = toArr(stylesRoot?.[\"w:style\"] ?? stylesRoot?.style);\n for (const style of styleArr) {\n const attr = style?._attr ?? {};\n const type = attr?.[\"w:type\"] ?? attr?.type;\n if (type !== \"paragraph\" && type !== \"character\") continue;\n const id = attr?.[\"w:styleId\"] ?? attr?.styleId;\n if (!id) continue;\n const basedOn = (style?.[\"w:basedOn\"]?.[0]?._attr ??\n style?.basedOn?.[0]?._attr)?.[\"w:val\"];\n\n const def: ParaStyleDef = { basedOn };\n\n // rPr from run properties\n const rPr = style?.[\"w:rPr\"]?.[0] ?? style?.rPr?.[0];\n if (rPr) {\n const szAttr = rPr?.[\"w:sz\"]?.[0]?._attr ?? rPr?.sz?.[0]?._attr ?? {};\n const szVal = szAttr?.[\"w:val\"] ?? szAttr?.val;\n const colorAttr =\n rPr?.[\"w:color\"]?.[0]?._attr ?? rPr?.color?.[0]?._attr ?? {};\n const colorVal = colorAttr?.[\"w:val\"] ?? colorAttr?.val;\n const fontAttr =\n rPr?.[\"w:rFonts\"]?.[0]?._attr ?? rPr?.rFonts?.[0]?._attr ?? {};\n const fontName =\n fontAttr?.[\"w:ascii\"] ??\n fontAttr?.ascii ??\n fontAttr?.[\"w:eastAsia\"] ??\n fontAttr?.eastAsia;\n const bNode = rPr?.[\"w:b\"]?.[0] ?? rPr?.b?.[0];\n const isBold =\n bNode != null &&\n (bNode?._attr?.[\"w:val\"] ?? bNode?._attr?.val ?? \"1\") !== \"0\";\n const iNode = rPr?.[\"w:i\"]?.[0] ?? rPr?.i?.[0];\n const isItalic =\n iNode != null &&\n (iNode?._attr?.[\"w:val\"] ?? iNode?._attr?.val ?? \"1\") !== \"0\";\n const underVal =\n rPr?.[\"w:u\"]?.[0]?._attr?.[\"w:val\"] ?? rPr?.[\"w:u\"]?.[0]?._attr?.val;\n const sNode = rPr?.[\"w:strike\"]?.[0] ?? rPr?.strike?.[0];\n const isStrike =\n sNode != null &&\n (sNode?._attr?.[\"w:val\"] ?? sNode?._attr?.val ?? \"1\") !== \"0\";\n def.rPr = {\n b: isBold || undefined,\n i: isItalic || undefined,\n u: underVal && underVal !== \"none\" ? true : undefined,\n s: isStrike || undefined,\n pt: szVal ? Metric.halfPtToPt(Number(szVal)) : undefined,\n color: safeHex(colorVal),\n font: fontName ? safeFont(fontName) : undefined,\n };\n }\n\n // pPr from paragraph properties\n const pPr = style?.[\"w:pPr\"]?.[0] ?? style?.pPr?.[0];\n if (pPr) {\n const spacingAttr =\n pPr?.[\"w:spacing\"]?.[0]?._attr ?? pPr?.spacing?.[0]?._attr ?? {};\n const beforeVal = Number(\n spacingAttr?.[\"w:before\"] ?? spacingAttr?.before ?? 0,\n );\n const afterVal = Number(\n spacingAttr?.[\"w:after\"] ?? spacingAttr?.after ?? 0,\n );\n const lineVal = Number(\n spacingAttr?.[\"w:line\"] ?? spacingAttr?.line ?? 0,\n );\n const lineRule =\n spacingAttr?.[\"w:lineRule\"] ?? spacingAttr?.lineRule ?? \"auto\";\n const indAttr =\n pPr?.[\"w:ind\"]?.[0]?._attr ?? pPr?.ind?.[0]?._attr ?? {};\n const leftVal = Number(indAttr?.[\"w:left\"] ?? indAttr?.left ?? 0);\n const rightVal = Number(indAttr?.[\"w:right\"] ?? indAttr?.right ?? 0);\n const firstLineVal = Number(\n indAttr?.[\"w:firstLine\"] ?? indAttr?.firstLine ?? 0,\n );\n const hangingVal = Number(\n indAttr?.[\"w:hanging\"] ?? indAttr?.hanging ?? 0,\n );\n const alignVal =\n pPr?.[\"w:jc\"]?.[0]?._attr?.[\"w:val\"] ??\n pPr?.[\"w:jc\"]?.[0]?._attr?.val;\n def.pPr = {\n align: alignVal,\n spaceBefore: beforeVal > 0 ? Metric.dxaToPt(beforeVal) : undefined,\n spaceAfter: afterVal > 0 ? Metric.dxaToPt(afterVal) : undefined,\n lineHeight:\n lineVal > 0 && lineRule === \"auto\" ? lineVal / 240 : undefined,\n indentPt: leftVal > 0 ? Metric.dxaToPt(leftVal) : undefined,\n indentRightPt: rightVal > 0 ? Metric.dxaToPt(rightVal) : undefined,\n firstLineIndentPt:\n firstLineVal > 0\n ? Metric.dxaToPt(firstLineVal)\n : hangingVal > 0\n ? -Metric.dxaToPt(hangingVal)\n : undefined,\n };\n }\n\n map.set(id, def);\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\n/** Resolve paragraph style inheritance chain (max depth 8) */\nfunction resolveParaStyle(\n styleId: string | undefined,\n map: ParaStyleMap,\n): ParaStyleDef {\n let merged: ParaStyleDef = {};\n const visited = new Set<string>();\n let cur = styleId;\n while (cur && !visited.has(cur)) {\n visited.add(cur);\n const def = map.get(cur);\n if (!def) break;\n // Merge: child values win over parent\n if (def.rPr) {\n merged.rPr = { ...def.rPr, ...merged.rPr };\n }\n if (def.pPr) {\n merged.pPr = { ...def.pPr, ...merged.pPr };\n }\n cur = def.basedOn;\n }\n return merged;\n}\n\n/** Resolve final CellProps borders using 3-level priority chain */\nfunction resolveCellBorders(\n cp: CellProps,\n ri: number,\n ci: number,\n rs: number,\n cs: number,\n rowCount: number,\n colCount: number,\n tblBdr: TblBorderDef,\n): CellProps {\n const isTopEdge = ri === 0;\n const isBottomEdge = ri + rs >= rowCount;\n const isLeftEdge = ci === 0;\n const isRightEdge = ci + cs >= colCount;\n\n // Apply tblBorders only where no explicit tcBorder was set\n const resolved: CellProps = { ...cp };\n if (!resolved.top) resolved.top = isTopEdge ? tblBdr.top : tblBdr.insideH;\n if (!resolved.bot)\n resolved.bot = isBottomEdge ? tblBdr.bottom : tblBdr.insideH;\n if (!resolved.left) resolved.left = isLeftEdge ? tblBdr.left : tblBdr.insideV;\n if (!resolved.right)\n resolved.right = isRightEdge ? tblBdr.right : tblBdr.insideV;\n return resolved;\n}\n\nfunction decodeGrid(tbl: any, ctx: DecCtx): GridNode {\n // Parse tblPr for table styles\n const tblPr = tbl?.[\"w:tblPr\"]?.[0] ?? tbl?.tblPr?.[0] ?? {};\n const tblLookAttr =\n tblPr?.[\"w:tblLook\"]?.[0]?._attr ?? tblPr?.tblLook?.[0]?._attr ?? {};\n\n const look: TableLook = {\n firstRow: tblLookAttr?.[\"w:firstRow\"] === \"1\" || undefined,\n lastRow: tblLookAttr?.[\"w:lastRow\"] === \"1\" || undefined,\n firstCol:\n tblLookAttr?.[\"w:firstColumn\"] === \"1\" ||\n tblLookAttr?.[\"w:firstCol\"] === \"1\" ||\n undefined,\n lastCol:\n tblLookAttr?.[\"w:lastColumn\"] === \"1\" ||\n tblLookAttr?.[\"w:lastCol\"] === \"1\" ||\n undefined,\n bandedRows: tblLookAttr?.[\"w:noHBand\"] === \"0\" || undefined,\n bandedCols: tblLookAttr?.[\"w:noVBand\"] === \"0\" || undefined,\n };\n\n // ① tblStyle 기본값 로드\n const tblStyleId = (tblPr?.[\"w:tblStyle\"]?.[0]?._attr ??\n tblPr?.tblStyle?.[0]?._attr)?.[\"w:val\"];\n const styleDef = tblStyleId ? ctx.stylesMap.get(tblStyleId) : undefined;\n let tblBdr: TblBorderDef = styleDef?.tblBorders ?? {};\n\n // ② tblBorders 재정의 (tblStyle보다 우선)\n const tblBordersNode = tblPr?.[\"w:tblBorders\"]?.[0] ?? tblPr?.tblBorders?.[0];\n if (tblBordersNode) {\n const parsed = parseBorderDef(tblBordersNode);\n tblBdr = { ...tblBdr, ...parsed };\n }\n\n // defaultStroke for HWPX/HWP encoders: use insideH (inner horizontal border)\n const defaultStroke = tblBdr.insideH ?? tblBdr.top;\n const gridProps: GridProps = { look, defaultStroke };\n\n // Read column widths from w:tblGrid\n const tblGrid = tbl?.[\"w:tblGrid\"]?.[0] ?? tbl?.tblGrid?.[0];\n if (tblGrid) {\n const gridCols = toArr(tblGrid?.[\"w:gridCol\"] ?? tblGrid?.gridCol ?? []);\n const colWidthsPt = gridCols\n .map((gc: any) =>\n Metric.dxaToPt(Number(gc?._attr?.[\"w:w\"] ?? gc?._attr?.w ?? 0)),\n )\n .filter((w: number) => w > 0);\n if (colWidthsPt.length > 0) gridProps.colWidths = colWidthsPt;\n }\n\n const rowArr = toArr(tbl?.[\"w:tr\"] ?? tbl?.tr);\n\n // ── Pass 1: parse raw cells with vMerge info ──\n interface RawCell {\n cell: any;\n gridSpan: number;\n vMergeRestart: boolean;\n vMergeContinue: boolean;\n }\n const rawGrid: RawCell[][] = rowArr.map((row: any) => {\n const cellArr = toArr(row?.[\"w:tc\"] ?? row?.tc);\n return cellArr.map((cell: any): RawCell => {\n const tcPr = cell?.[\"w:tcPr\"]?.[0] ?? {};\n const gridSpan = Number(tcPr?.[\"w:gridSpan\"]?.[0]?._attr?.[\"w:val\"] ?? 1);\n const vMergeNode = tcPr?.[\"w:vMerge\"]?.[0];\n const vMergeVal = vMergeNode?._attr?.[\"w:val\"] ?? vMergeNode?._attr?.val;\n const vMergeRestart = vMergeVal === \"restart\";\n // vMerge present but val is not \"restart\" → continuation cell\n const vMergeContinue = vMergeNode != null && !vMergeRestart;\n return { cell, gridSpan, vMergeRestart, vMergeContinue };\n });\n });\n\n // ── Pass 2: compute rowSpan for restart cells ──\n // rsMap[ri][ci] = computed rowSpan (only set for restart cells)\n const rsMap: Map<string, number> = new Map();\n for (let ri = 0; ri < rawGrid.length; ri++) {\n let gridCol = 0;\n for (let ci = 0; ci < rawGrid[ri].length; ci++) {\n const rc = rawGrid[ri][ci];\n if (rc.vMergeRestart) {\n let span = 1;\n for (let nr = ri + 1; nr < rawGrid.length; nr++) {\n // Find the cell at the same grid column in the next row\n let col = 0;\n let found = false;\n for (const nc of rawGrid[nr]) {\n if (col === gridCol && nc.vMergeContinue) {\n span++;\n found = true;\n break;\n }\n col += nc.gridSpan;\n }\n if (!found) break;\n }\n rsMap.set(`${ri},${ci}`, span);\n }\n gridCol += rc.gridSpan;\n }\n }\n\n // ── Pass 3: build CellNodes, skip continuation cells ──\n const rowNodes = rawGrid.map((rawRow, ri) => {\n // Check for header row\n const row = rowArr[ri];\n const trPr = row?.[\"w:trPr\"]?.[0] ?? row?.trPr?.[0] ?? {};\n const isHeaderRow =\n trPr?.[\"w:tblHeader\"]?.[0] != null || trPr?.tblHeader?.[0] != null;\n if (ri === 0 && isHeaderRow) gridProps.headerRow = true;\n\n // Row height from w:trHeight\n let rowHeightPt: number | undefined;\n const trHAttr =\n trPr?.[\"w:trHeight\"]?.[0]?._attr ?? trPr?.trHeight?.[0]?._attr;\n if (trHAttr) {\n const hDxa = Number(trHAttr?.[\"w:val\"] ?? trHAttr?.val ?? 0);\n if (hDxa > 0) rowHeightPt = Metric.dxaToPt(hDxa);\n }\n\n const cellNodes: CellNode[] = [];\n for (let ci = 0; ci < rawRow.length; ci++) {\n const rc = rawRow[ci];\n // Skip continuation cells — they are part of a vertical merge\n if (rc.vMergeContinue) continue;\n\n const cell = rc.cell;\n const tcPr = cell?.[\"w:tcPr\"]?.[0] ?? {};\n\n // Cell background\n const bgAttr = tcPr?.[\"w:shd\"]?.[0]?._attr ?? {};\n const bg = safeHex(bgAttr?.[\"w:fill\"] ?? bgAttr?.fill);\n\n // ③ tcBorders 셀 수준 재정의 (우선순위 가장 높음)\n const tcBordersNode = tcPr?.[\"w:tcBorders\"]?.[0] ?? tcPr?.tcBorders?.[0];\n const cp: CellProps = { bg, isHeader: isHeaderRow || undefined };\n\n if (tcBordersNode) {\n const dirs: Array<[string, \"top\" | \"bot\" | \"left\" | \"right\"]> = [\n [\"top\", \"top\"],\n [\"bottom\", \"bot\"],\n [\"left\", \"left\"],\n [\"right\", \"right\"],\n ];\n for (const [xmlTag, propKey] of dirs) {\n const bdr =\n tcBordersNode?.[\"w:\" + xmlTag]?.[0]?._attr ??\n tcBordersNode?.[xmlTag]?.[0]?._attr;\n if (!bdr) continue;\n const val = bdr?.[\"w:val\"] ?? bdr?.val;\n if (val === \"none\" || val === \"nil\") {\n // explicit none: keep as undefined (no border)\n } else {\n cp[propKey] = safeStrokeDocx(\n val,\n Number(bdr?.[\"w:sz\"] ?? bdr?.sz ?? 4),\n bdr?.[\"w:color\"] ?? bdr?.color,\n );\n }\n }\n }\n\n // Vertical alignment\n const vaAttr =\n tcPr?.[\"w:vAlign\"]?.[0]?._attr ?? tcPr?.vAlign?.[0]?._attr ?? {};\n const vaVal = vaAttr?.[\"w:val\"] ?? vaAttr?.val;\n if (vaVal) {\n const vaMap: Record<string, \"top\" | \"mid\" | \"bot\"> = {\n top: \"top\",\n center: \"mid\",\n bottom: \"bot\",\n };\n cp.va = vaMap[vaVal];\n }\n\n // Cell margins (padding)\n const tcMar = tcPr?.[\"w:tcMar\"]?.[0] ?? tcPr?.tcMar?.[0];\n if (tcMar) {\n const top = tcMar?.[\"w:top\"]?.[0]?._attr ?? tcMar?.top?.[0]?._attr;\n const bot =\n tcMar?.[\"w:bottom\"]?.[0]?._attr ?? tcMar?.bottom?.[0]?._attr;\n const left = tcMar?.[\"w:left\"]?.[0]?._attr ?? tcMar?.left?.[0]?._attr;\n const right =\n tcMar?.[\"w:right\"]?.[0]?._attr ?? tcMar?.right?.[0]?._attr;\n\n if (top) cp.padT = Metric.dxaToPt(Number(top?.[\"w:w\"] ?? top?.w ?? 0));\n if (bot) cp.padB = Metric.dxaToPt(Number(bot?.[\"w:w\"] ?? bot?.w ?? 0));\n if (left)\n cp.padL = Metric.dxaToPt(Number(left?.[\"w:w\"] ?? left?.w ?? 0));\n if (right)\n cp.padR = Metric.dxaToPt(Number(right?.[\"w:w\"] ?? right?.w ?? 0));\n }\n\n const rs = rsMap.get(`${ri},${ci}`) ?? 1;\n\n // Compute logical column index for this cell\n let gridColIdx = 0;\n for (let prevCi = 0; prevCi < ci; prevCi++) {\n if (!rawRow[prevCi].vMergeContinue)\n gridColIdx += rawRow[prevCi].gridSpan;\n }\n\n // Apply 3-level border resolution (tblStyle → tblBorders → tcBorders already in cp)\n const colCount =\n gridProps.colWidths?.length ??\n rawGrid[0]?.reduce((s, c) => s + c.gridSpan, 0) ??\n 1;\n const resolvedCp = resolveCellBorders(\n cp,\n ri,\n gridColIdx,\n rs,\n rc.gridSpan,\n rawGrid.length,\n colCount,\n tblBdr,\n );\n\n const paras = toArr(cell?.[\"w:p\"] ?? cell?.p).map((p: any) =>\n decodePara(p, ctx),\n );\n cellNodes.push(\n buildCell(paras.length > 0 ? paras : [buildPara([buildSpan(\"\")])], {\n cs: rc.gridSpan,\n rs,\n props: resolvedCp,\n }),\n );\n }\n return buildRow(cellNodes, rowHeightPt);\n });\n return buildGrid(rowNodes, gridProps);\n}\n\nfunction decodeGridSimple(tbl: any): GridNode {\n const rowArr = toArr(tbl?.[\"w:tr\"] ?? tbl?.tr);\n const rowNodes = rowArr.map((row: any) => {\n const cellArr = toArr(row?.[\"w:tc\"] ?? row?.tc);\n return buildRow(\n cellArr.map((c: any) => buildCell([buildPara([buildSpan(cellText(c))])])),\n );\n });\n return buildGrid(rowNodes);\n}\n\nfunction decodeGridFlat(tbl: any): GridNode {\n return buildGrid([\n buildRow([buildCell([buildPara([buildSpan(tableText(tbl))])])]),\n ]);\n}\n\nfunction decodeGridText(tbl: any): ParaNode {\n return buildPara([buildSpan(tableText(tbl))]);\n}\n\nfunction cellText(cell: any): string {\n return toArr(cell?.[\"w:p\"] ?? cell?.p)\n .map((p: any) =>\n toArr(p?.[\"w:r\"] ?? p?.r)\n .map((r: any) =>\n toArr(r?.[\"w:t\"] ?? r?.t)\n .map((t: any) => (typeof t === \"string\" ? t : (t?._ ?? \"\")))\n .join(\"\"),\n )\n .join(\"\"),\n )\n .join(\" \");\n}\n\nfunction tableText(tbl: any): string {\n return toArr(tbl?.[\"w:tr\"] ?? tbl?.tr)\n .map((row: any) =>\n toArr(row?.[\"w:tc\"] ?? row?.tc)\n .map((c: any) => cellText(c))\n .join(\"\\t\"),\n )\n .join(\"\\n\");\n}\n\nfunction parseHeading(style?: string): 1 | 2 | 3 | 4 | 5 | 6 | undefined {\n if (!style) return undefined;\n const m = style.match(/[Hh]eading(\\d)/);\n if (m) {\n const n = Number(m[1]);\n if (n >= 1 && n <= 6) return n as any;\n }\n return undefined;\n}\n\nregistry.registerDecoder(new DocxDecoder());\n\n// ─── Anchor layout 추출 ─────────────────────────────────────\n\nfunction extractAnchorLayout(anchor: any): ImgLayout {\n const attr = anchor?._attr ?? {};\n const behindDoc = attr.behindDoc === \"1\";\n\n // 텍스트 감싸기 타입\n let wrap: ImgWrap = \"square\";\n if (anchor?.[\"wp:wrapNone\"]?.[0] != null)\n wrap = behindDoc ? \"behind\" : \"none\";\n else if (anchor?.[\"wp:wrapTight\"]?.[0] != null) wrap = \"tight\";\n else if (anchor?.[\"wp:wrapThrough\"]?.[0] != null) wrap = \"through\";\n else if (anchor?.[\"wp:wrapSquare\"]?.[0] != null) wrap = \"square\";\n else if (anchor?.[\"wp:wrapTopAndBottom\"]?.[0] != null) wrap = \"square\";\n else if (anchor?.[\"wp:wrapBehind\"]?.[0] != null || behindDoc) wrap = \"behind\";\n\n // 가로 위치\n const posH = anchor?.[\"wp:positionH\"]?.[0];\n const horzRelTo = parseHorzRelTo(posH?._attr?.relativeFrom);\n const horzAlignTxt = posH?.[\"wp:align\"]?.[0]?._text;\n const horzOffsetTxt = posH?.[\"wp:posOffset\"]?.[0]?._text;\n const horzAlign = horzAlignTxt ? parseHorzAlign(horzAlignTxt) : undefined;\n const xPt =\n horzOffsetTxt && !horzAlignTxt\n ? Metric.emuToPt(Number(horzOffsetTxt))\n : undefined;\n\n // 세로 위치\n const posV = anchor?.[\"wp:positionV\"]?.[0];\n const vertRelTo = parseVertRelTo(posV?._attr?.relativeFrom);\n const vertAlignTxt = posV?.[\"wp:align\"]?.[0]?._text;\n const vertOffsetTxt = posV?.[\"wp:posOffset\"]?.[0]?._text;\n const vertAlign = vertAlignTxt ? parseVertAlign(vertAlignTxt) : undefined;\n const yPt =\n vertOffsetTxt && !vertAlignTxt\n ? Metric.emuToPt(Number(vertOffsetTxt))\n : undefined;\n\n // 텍스트와의 거리\n const distT = attr.distT ? Metric.emuToPt(Number(attr.distT)) : undefined;\n const distB = attr.distB ? Metric.emuToPt(Number(attr.distB)) : undefined;\n const distL = attr.distL ? Metric.emuToPt(Number(attr.distL)) : undefined;\n const distR = attr.distR ? Metric.emuToPt(Number(attr.distR)) : undefined;\n const zOrder = attr.relativeHeight ? Number(attr.relativeHeight) : undefined;\n\n return {\n wrap,\n horzAlign,\n vertAlign,\n horzRelTo,\n vertRelTo,\n xPt,\n yPt,\n distT,\n distB,\n distL,\n distR,\n behindDoc,\n zOrder,\n };\n}\n\nconst HORZ_RELTO_MAP: Record<string, ImgHorzRelTo> = {\n margin: \"margin\",\n leftMargin: \"margin\",\n rightMargin: \"margin\",\n insideMargin: \"margin\",\n outsideMargin: \"margin\",\n column: \"column\",\n page: \"page\",\n character: \"para\",\n paragraph: \"para\",\n};\nconst VERT_RELTO_MAP: Record<string, ImgVertRelTo> = {\n margin: \"margin\",\n topMargin: \"margin\",\n bottomMargin: \"margin\",\n insideMargin: \"margin\",\n outsideMargin: \"margin\",\n line: \"line\",\n page: \"page\",\n paragraph: \"para\",\n};\nconst HORZ_ALIGN_MAP: Record<string, ImgHorzAlign> = {\n left: \"left\",\n center: \"center\",\n right: \"right\",\n inside: \"left\",\n outside: \"right\",\n};\nconst VERT_ALIGN_MAP: Record<string, ImgVertAlign> = {\n top: \"top\",\n center: \"center\",\n bottom: \"bottom\",\n inside: \"top\",\n outside: \"bottom\",\n};\n\nfunction parseHorzRelTo(v?: string): ImgHorzRelTo {\n return HORZ_RELTO_MAP[v ?? \"\"] ?? \"column\";\n}\nfunction parseVertRelTo(v?: string): ImgVertRelTo {\n return VERT_RELTO_MAP[v ?? \"\"] ?? \"para\";\n}\nfunction parseHorzAlign(v?: string): ImgHorzAlign | undefined {\n return HORZ_ALIGN_MAP[v ?? \"\"];\n}\nfunction parseVertAlign(v?: string): ImgVertAlign | undefined {\n return VERT_ALIGN_MAP[v ?? \"\"];\n}\n","import type { DocRoot, ContentNode, ParaNode, SpanNode, ImgNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport type { ParaProps, TextProps } from '../../model/doc-props';\nimport { A4 } from '../../model/doc-props';\nimport { succeed, fail } from '../../contract/result';\nimport { buildRoot, buildSheet, buildPara, buildSpan, buildImg, buildGrid, buildRow, buildCell } from '../../model/builders';\nimport { ShieldedParser } from '../../safety/ShieldedParser';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { registry } from '../../pipeline/registry';\nimport { BaseDecoder } from '../../core/BaseDecoder';\n\nexport class MdDecoder extends BaseDecoder {\n protected getFormat(): string { return 'md'; }\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n const text = this.bytesToString(data);\n const lines = text.split(/\\r?\\n/);\n const kids: ContentNode[] = [];\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n\n // Heading\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n const level = headingMatch[1].length as 1 | 2 | 3 | 4 | 5 | 6;\n kids.push(buildPara([buildSpan(headingMatch[2], { b: level <= 2 })], { heading: level }));\n i++; continue;\n }\n\n // Table (pipe + separator line)\n if (line.includes('|') && i + 1 < lines.length && lines[i + 1].match(/^\\s*\\|?\\s*[-:]+\\s*\\|/)) {\n const tableResult = shield.guard(() => parseMdTable(lines, i), null, `md:table@${i}`);\n if (tableResult) { kids.push(tableResult.node); i = tableResult.nextLine; continue; }\n }\n\n // HR\n if (line.match(/^[-*_]{3,}$/)) { kids.push(buildPara([buildSpan('')], {})); i++; continue; }\n\n // List item\n const listMatch = line.match(/^(\\s*)([-*+]|\\d+\\.)\\s+(.+)$/);\n if (listMatch) {\n kids.push(buildPara(parseInline(listMatch[3]), {\n listLv: Math.floor(listMatch[1].length / 2),\n listOrd: /\\d+\\./.test(listMatch[2]),\n }));\n i++; continue;\n }\n\n // Blockquote\n const bqMatch = line.match(/^>\\s*(.*)$/);\n if (bqMatch) { kids.push(buildPara([buildSpan(bqMatch[1])], { indentPt: 28 })); i++; continue; }\n\n // Code block\n if (line.startsWith('```')) {\n const codeLines: string[] = [];\n i++;\n while (i < lines.length && !lines[i].startsWith('```')) { codeLines.push(lines[i]); i++; }\n i++;\n kids.push(buildPara([buildSpan(codeLines.join('\\n'), { font: 'Courier New' })], {}));\n continue;\n }\n\n // Empty line\n if (line.trim() === '') { i++; continue; }\n\n // Regular paragraph — check for alignment div\n const alignMatch = line.match(/^<div\\s+align=\"(center|right|left)\">(.*?)<\\/div>$/i);\n if (alignMatch) {\n const align = alignMatch[1].toLowerCase() as 'left' | 'center' | 'right';\n kids.push(buildPara(parseInline(alignMatch[2]), { align }));\n i++; continue;\n }\n\n // Regular paragraph\n kids.push(buildPara(parseInline(line), {}));\n i++;\n }\n\n warns.push(...shield.flush());\n const sheet = buildSheet(kids.length > 0 ? kids : [buildPara([buildSpan('')])], A4);\n return succeed(buildRoot({}, [sheet]), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`MD decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\nfunction parseInline(text: string): (SpanNode | ImgNode)[] {\n const result: (SpanNode | ImgNode)[] = [];\n let rem = text;\n\n while (rem.length > 0) {\n // Image: ![alt](data:mime;base64,...)\n let m = rem.match(/^(.*?)!\\[([^\\]]*)\\]\\((data:([^;]+);base64,([^)]+))\\)(.*)/s);\n if (m) {\n if (m[1]) result.push(buildSpan(m[1]));\n const mime = m[4] as ImgNode['mime'];\n const validMimes = ['image/png', 'image/jpeg', 'image/gif', 'image/bmp'];\n result.push(buildImg(m[5], validMimes.includes(mime) ? mime : 'image/png', 100, 100, m[2] || undefined));\n rem = m[6]; continue;\n }\n\n // Image: ![alt](url) — non-base64\n m = rem.match(/^(.*?)!\\[([^\\]]*)\\]\\(([^)]+)\\)(.*)/s);\n if (m) {\n if (m[1]) result.push(buildSpan(m[1]));\n // Can't convert URL to base64, just preserve alt text\n result.push(buildSpan(`[이미지: ${m[2] || m[3]}]`));\n rem = m[4]; continue;\n }\n\n // Bold+italic\n m = rem.match(/^(.*?)\\*\\*\\*(.+?)\\*\\*\\*(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { b: true, i: true })); rem = m[3]; continue; }\n\n // Bold\n m = rem.match(/^(.*?)\\*\\*(.+?)\\*\\*(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { b: true })); rem = m[3]; continue; }\n\n // Italic\n m = rem.match(/^(.*?)\\*(.+?)\\*(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { i: true })); rem = m[3]; continue; }\n\n // Strikethrough ~~text~~\n m = rem.match(/^(.*?)~~(.+?)~~(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { s: true })); rem = m[3]; continue; }\n\n // Underline <u>text</u>\n m = rem.match(/^(.*?)<u>(.+?)<\\/u>(.*)/si);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { u: true })); rem = m[3]; continue; }\n\n // Superscript <sup>text</sup>\n m = rem.match(/^(.*?)<sup>(.+?)<\\/sup>(.*)/si);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { sup: true })); rem = m[3]; continue; }\n\n // Subscript <sub>text</sub>\n m = rem.match(/^(.*?)<sub>(.+?)<\\/sub>(.*)/si);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { sub: true })); rem = m[3]; continue; }\n\n // Inline code\n m = rem.match(/^(.*?)`(.+?)`(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { font: 'Courier New' })); rem = m[3]; continue; }\n\n result.push(buildSpan(rem));\n break;\n }\n\n return result.length > 0 ? result : [buildSpan(text)];\n}\n\nfunction parseMdTable(lines: string[], startLine: number): { node: any; nextLine: number } | null {\n const parse = (line: string) => line.split('|').map(c => c.trim()).filter((c, i, arr) => i > 0 || c !== '');\n const headers = parse(lines[startLine]);\n\n let cur = startLine + 2;\n const rows: string[][] = [];\n while (cur < lines.length) {\n if (!lines[cur].includes('|')) break;\n const cells = parse(lines[cur]);\n if (cells.length === 0) break;\n rows.push(cells);\n cur++;\n }\n\n const allRows = [headers, ...rows];\n const gridRows = allRows.map((row, ri) =>\n buildRow(row.map(cell => buildCell([buildPara([buildSpan(cell, ri === 0 ? { b: true } : {})])]))),\n );\n\n return { node: buildGrid(gridRows), nextLine: cur };\n}\n\nregistry.registerDecoder(new MdDecoder());\n","/**\n * HtmlDecoder — HTML → DocRoot\n * 간단한 HTML 파서 (표, 이미지, 스타일 지원)\n */\n\nimport type { DocRoot, ContentNode, ParaNode, SpanNode, ImgNode, GridNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport type { TextProps, ParaProps } from '../../model/doc-props';\nimport { A4 } from '../../model/doc-props';\nimport { succeed, fail } from '../../contract/result';\nimport { buildRoot, buildSheet, buildPara, buildSpan, buildImg, buildGrid, buildRow, buildCell } from '../../model/builders';\nimport { ShieldedParser } from '../../safety/ShieldedParser';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { registry } from '../../pipeline/registry';\nimport { BaseDecoder } from '../../core/BaseDecoder';\n\ninterface Token {\n type: 'tag' | 'text' | 'comment';\n name?: string;\n attrs?: Record<string, string>;\n selfClose?: boolean;\n close?: boolean;\n content?: string;\n}\n\nexport class HtmlDecoder extends BaseDecoder {\n protected getFormat(): string { return 'html'; }\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n const html = this.bytesToString(data);\n const tokens = shield.guard(() => tokenize(html), [], 'html:tokenize');\n const kids = shield.guard(() => parseTokens(tokens), [], 'html:parse');\n\n warns.push(...shield.flush());\n const sheet = buildSheet(kids.length > 0 ? kids : [buildPara([buildSpan('')])], A4);\n return succeed(buildRoot({}, [sheet]), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`HTML decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\nfunction tokenize(html: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < html.length) {\n if (html[i] === '<') {\n if (html[i + 1] === '!') {\n const end = html.indexOf('>', i);\n i = end + 1;\n continue;\n }\n\n const isClose = html[i + 1] === '/';\n const start = isClose ? i + 2 : i + 1;\n const end = html.indexOf('>', i);\n if (end === -1) break;\n\n const tagContent = html.slice(start, end).trim();\n const spaceIdx = tagContent.search(/\\s/);\n const name = spaceIdx > 0 ? tagContent.slice(0, spaceIdx) : tagContent;\n const attrsStr = spaceIdx > 0 ? tagContent.slice(spaceIdx + 1).trim() : '';\n\n const attrs: Record<string, string> = {};\n if (attrsStr) {\n const attrRegex = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))?/g;\n let m;\n while ((m = attrRegex.exec(attrsStr)) !== null) {\n attrs[m[1].toLowerCase()] = m[2] ?? m[3] ?? m[4] ?? '';\n }\n }\n\n tokens.push({\n type: 'tag',\n name: name.toLowerCase(),\n attrs,\n selfClose: html[end - 1] === '/',\n close: isClose,\n });\n\n i = end + 1;\n } else {\n const end = html.indexOf('<', i);\n const text = end === -1 ? html.slice(i) : html.slice(i, end);\n if (text.trim()) {\n tokens.push({ type: 'text', content: text });\n }\n i = end === -1 ? html.length : end;\n }\n }\n\n return tokens;\n}\n\nfunction parseTokens(tokens: Token[]): ContentNode[] {\n const kids: ContentNode[] = [];\n let i = 0;\n\n while (i < tokens.length) {\n const t = tokens[i];\n\n if (t.type === 'tag' && !t.close) {\n switch (t.name) {\n case 'html':\n // Extract body content\n i++;\n let bodyStart = -1;\n let depth = 1;\n while (i < tokens.length && depth > 0) {\n if (tokens[i].type === 'tag' && !tokens[i].close && tokens[i].name === 'html') depth++;\n else if (tokens[i].type === 'tag' && tokens[i].close && tokens[i].name === 'html') depth--;\n else if (tokens[i].type === 'tag' && !tokens[i].close && tokens[i].name === 'body') {\n bodyStart = i + 1;\n }\n i++;\n }\n if (bodyStart > 0) {\n // Find body end\n let bodyEnd = bodyStart;\n let bodyDepth = 1;\n while (bodyEnd < tokens.length && bodyDepth > 0) {\n if (tokens[bodyEnd].type === 'tag' && !tokens[bodyEnd].close && tokens[bodyEnd].name === 'body') bodyDepth++;\n else if (tokens[bodyEnd].type === 'tag' && tokens[bodyEnd].close && tokens[bodyEnd].name === 'body') bodyDepth--;\n bodyEnd++;\n }\n bodyEnd--;\n const bodyTokens = tokens.slice(bodyStart, bodyEnd);\n const bodyKids = parseTokens(bodyTokens);\n kids.push(...bodyKids);\n }\n continue;\n\n case 'head':\n case 'style':\n case 'script':\n i = skipBlock(tokens, i, t.name);\n continue;\n\n case 'body':\n case 'div':\n case 'section':\n case 'article':\n case 'main':\n // Find closing tag and process contents\n const start = i + 1;\n let end = start;\n let divDepth = 1;\n while (end < tokens.length && divDepth > 0) {\n const t = tokens[end];\n if (t.type === 'tag' && !t.close) {\n if (['html', 'head', 'body', 'div', 'section', 'article', 'main'].includes(t.name ?? '')) divDepth++;\n } else if (t.type === 'tag' && t.close) {\n if (['html', 'head', 'body', 'div', 'section', 'article', 'main'].includes(t.name ?? '')) divDepth--;\n }\n end++;\n }\n end--;\n\n // Process tokens between start and end\n const subTokens = tokens.slice(start, end);\n const subKids = parseTokens(subTokens);\n kids.push(...subKids);\n\n i = end + 1;\n continue;\n\n case 'p':\n i++;\n const paraKids = collectInline(tokens, i, ['p', 'div', 'br']);\n i = paraKids.nextI;\n const align = t.attrs?.style?.includes('text-align: center') ? 'center'\n : t.attrs?.style?.includes('text-align: right') ? 'right'\n : t.attrs?.style?.includes('text-align: left') ? 'left'\n : undefined;\n kids.push(buildPara(paraKids.nodes, { align }));\n continue;\n\n case 'br':\n kids.push(buildPara([buildSpan('')], {}));\n i++;\n continue;\n\n case 'img':\n i++;\n const src = t.attrs?.src;\n const alt = t.attrs?.alt || '';\n if (src?.startsWith('data:')) {\n const match = src.match(/^data:([^;]+);base64,(.+)$/);\n if (match) {\n kids.push(buildPara([buildImg(match[2], match[1] as any, 100, 100, alt)], {}));\n }\n }\n continue;\n\n case 'table':\n i++;\n const rows: any[] = [];\n while (i < tokens.length) {\n if (tokens[i].type === 'tag' && tokens[i].close && tokens[i].name === 'table') {\n i++;\n break;\n }\n if (tokens[i].type === 'tag' && tokens[i].name === 'tr' && !tokens[i].close) {\n i++;\n const cells: any[] = [];\n while (i < tokens.length) {\n if (tokens[i].type === 'tag' && tokens[i].close && tokens[i].name === 'tr') {\n i++;\n break;\n }\n if (tokens[i].type === 'tag' && (tokens[i].name === 'td' || tokens[i].name === 'th') && !tokens[i].close) {\n i++;\n const cellKids = collectInline(tokens, i, ['td', 'th', 'tr']);\n i = cellKids.nextI;\n const isHeader = tokens[i - 2]?.name === 'th';\n const paraKids = cellKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, b: isHeader } } : n);\n cells.push(buildCell([buildPara(paraKids, {})]));\n } else if (tokens[i].type === 'text' && tokens[i].content?.trim()) {\n cells.push(buildCell([buildPara([buildSpan(tokens[i].content!.trim())])]));\n i++;\n } else {\n i++;\n }\n }\n if (cells.length > 0) rows.push(buildRow(cells));\n } else {\n i++;\n }\n }\n if (rows.length > 0) kids.push(buildGrid(rows));\n continue;\n\n case 'ul':\n case 'ol':\n i++;\n const isOrdered = t.name === 'ol';\n while (i < tokens.length) {\n if (tokens[i].type === 'tag' && tokens[i].close && tokens[i].name === t.name) {\n i++;\n break;\n }\n if (tokens[i].type === 'tag' && tokens[i].name === 'li' && !tokens[i].close) {\n i++;\n const liKids = collectInline(tokens, i, ['li', 'ul', 'ol']);\n i = liKids.nextI;\n kids.push(buildPara(liKids.nodes, { listOrd: isOrdered }));\n } else {\n i++;\n }\n }\n continue;\n\n default:\n i++;\n }\n } else if (t.type === 'text' && t.content?.trim()) {\n kids.push(buildPara([buildSpan(t.content!.trim())], {}));\n i++;\n } else {\n i++;\n }\n }\n\n return kids;\n}\n\nfunction collectInline(tokens: Token[], start: number, stopTags: string[]): { nodes: (SpanNode | ImgNode)[]; nextI: number } {\n const nodes: (SpanNode | ImgNode)[] = [];\n let i = start;\n\n while (i < tokens.length) {\n const t = tokens[i];\n\n if (t.type === 'tag' && !t.close) {\n if (t.name && stopTags.includes(t.name)) {\n break;\n }\n\n switch (t.name) {\n case 'b':\n case 'strong':\n i++;\n const boldKids = collectInline(tokens, i, ['b', 'strong', ...stopTags]);\n i = boldKids.nextI;\n nodes.push(...boldKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, b: true } } : n));\n continue;\n\n case 'i':\n case 'em':\n i++;\n const italicKids = collectInline(tokens, i, ['i', 'em', ...stopTags]);\n i = italicKids.nextI;\n nodes.push(...italicKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, i: true } } : n));\n continue;\n\n case 'u':\n i++;\n const underlineKids = collectInline(tokens, i, ['u', ...stopTags]);\n i = underlineKids.nextI;\n nodes.push(...underlineKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, u: true } } : n));\n continue;\n\n case 's':\n case 'strike':\n i++;\n const strikeKids = collectInline(tokens, i, ['s', 'strike', ...stopTags]);\n i = strikeKids.nextI;\n nodes.push(...strikeKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, s: true } } : n));\n continue;\n\n case 'span':\n i++;\n const spanKids = collectInline(tokens, i, ['span', ...stopTags]);\n i = spanKids.nextI;\n const color = t.attrs?.style?.match(/color:\\s*([^;]+)/)?.[1];\n nodes.push(...spanKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, color: color || n.props.color } } : n));\n continue;\n\n case 'img':\n const src = t.attrs?.src;\n const alt = t.attrs?.alt || '';\n if (src?.startsWith('data:')) {\n const match = src.match(/^data:([^;]+);base64,(.+)$/);\n if (match) {\n nodes.push(buildImg(match[2], match[1] as any, 100, 100, alt));\n }\n }\n i++;\n continue;\n\n default:\n i++;\n }\n } else if (t.type === 'text') {\n if (t.content?.trim()) {\n nodes.push(buildSpan(t.content!.trim()));\n }\n i++;\n } else {\n i++;\n }\n }\n\n return { nodes: nodes.length > 0 ? nodes : [buildSpan('')], nextI: i };\n}\n\nfunction skipBlock(tokens: Token[], start: number, name: string): number {\n let i = start + 1;\n let depth = 1;\n while (i < tokens.length && depth > 0) {\n if (tokens[i].type === 'tag') {\n if (!tokens[i].close && tokens[i].name === name) depth++;\n if (tokens[i].close && tokens[i].name === name) depth--;\n }\n i++;\n }\n return i;\n}\n\nregistry.registerDecoder(new HtmlDecoder());\n","/**\n * BaseEncoder - 모든 인코더의 기본 클래스\n *\n * 공통 로직을 제공하여 각 포맷별 인코더가 포맷 특유의 로직만 구현하도록 합니다.\n */\n\nimport type { Encoder } from '../contract/encoder';\nimport type { Outcome } from '../contract/result';\nimport type { DocRoot, AnyNode, ImgNode } from '../model/doc-tree';\nimport { TextKit } from '../toolkit/TextKit';\nimport { ArchiveKit } from '../toolkit/ArchiveKit';\n\n// ─── 타입 정의 ───────────────────────────────────\n\nexport interface ImageData {\n node: ImgNode;\n path: string;\n data: Uint8Array;\n}\n\nexport interface ZipEntry {\n name: string;\n data: Uint8Array;\n}\n\n// ─── BaseEncoder ───────────────────────────────\n\nexport abstract class BaseEncoder implements Encoder {\n readonly format: string = this.getFormat();\n readonly aliases: string[] = this.getAliases();\n\n /** 포맷 이름 반환 (하위 클래스에서 오버라이드) */\n protected abstract getFormat(): string;\n\n /** 별칭 목록 반환 (하위 클래스에서 필요 시 오버라이드) */\n protected getAliases(): string[] { return []; }\n\n /** 문서 인코딩 (하위 클래스에서 오버라이드) */\n abstract encode(doc: DocRoot): Promise<Outcome<Uint8Array>>;\n\n // ─── 공통 유틸리티 메서드 ───────────────────────────\n\n /** 문서 내 모든 이미지 노드 수집 */\n protected collectImages(doc: DocRoot): ImgNode[] {\n const images: ImgNode[] = [];\n this.collectImagesRecursive(doc, images);\n return images;\n }\n\n /** 재귀적으로 이미지 수집 */\n private collectImagesRecursive(node: AnyNode, images: ImgNode[]): void {\n if (node.tag === 'img') {\n images.push(node);\n return;\n }\n\n const children = this.getChildren(node);\n for (const child of children) {\n this.collectImagesRecursive(child, images);\n }\n }\n\n /** 노드의 자식 노드 반환 */\n private getChildren(node: AnyNode): AnyNode[] {\n switch (node.tag) {\n case 'root':\n return node.kids;\n case 'sheet':\n return [...node.kids, ...(node.headers?.default ?? []), ...(node.footers?.default ?? [])];\n case 'para':\n return node.kids;\n case 'span':\n return node.kids;\n case 'link':\n return node.kids;\n case 'row':\n return node.kids;\n case 'cell':\n return node.kids;\n case 'grid':\n return node.kids;\n default:\n return [];\n }\n }\n\n /** base64 문자열을 Uint8Array 로 변환 */\n protected base64ToBytes(b64: string): Uint8Array {\n return TextKit.base64Decode(b64);\n }\n\n /** Uint8Array 를 base64 문자열로 변환 */\n protected bytesToBase64(data: Uint8Array): string {\n return TextKit.base64Encode(data);\n }\n\n /** XML 이스케이프 */\n protected escapeXml(s: string): string {\n return TextKit.escapeXml(s);\n }\n\n /** XML 언이스케이프 */\n protected unescapeXml(s: string): string {\n return TextKit.unescapeXml(s);\n }\n\n /** 문자열을 UTF-8 바이트로 변환 */\n protected stringToBytes(s: string): Uint8Array {\n return TextKit.encode(s);\n }\n\n /** 바이트를 UTF-8 문자열로 변환 */\n protected bytesToString(data: Uint8Array): string {\n return TextKit.decode(data);\n }\n\n /** ZIP 압축 */\n protected async zip(entries: ZipEntry[]): Promise<Uint8Array> {\n return ArchiveKit.zip(entries);\n }\n\n /** ZIP 해제 */\n protected async unzip(data: Uint8Array): Promise<Map<string, Uint8Array>> {\n return ArchiveKit.unzip(data);\n }\n\n /** deflate 압축 */\n protected async deflate(data: Uint8Array): Promise<Uint8Array> {\n return ArchiveKit.deflate(data);\n }\n\n /** inflate 해제 */\n protected async inflate(data: Uint8Array): Promise<Uint8Array> {\n return ArchiveKit.inflate(data);\n }\n\n /** 제어 문자 제거 */\n protected stripControl(s: string): string {\n return TextKit.stripControl(s);\n }\n\n /** 공백 정규화 */\n protected normalizeWhitespace(s: string): string {\n return TextKit.normalizeWhitespace(s);\n }\n}\n","/**\n * HwpxEncoder — DocRoot → HWPX (ZIP + XML)\n *\n * ANYTOHWP에서 영감받은 개선 사항:\n * 1. LangFontBank — 7개 언어 그룹 독립 폰트 레지스트리 (HANGUL/LATIN/HANJA/…)\n * 2. BorderFillBank — 정확한 ID 관리 (하드코딩 \"1\" 제거)\n * 3. readPixelDims — PNG/JPEG 바이너리 헤더에서 실제 픽셀 치수 추출\n * 4. 두 패스 구조 — Pre-scan(등록) → Encode(생성)\n */\n\nimport type {\n DocRoot,\n ParaNode,\n SpanNode,\n GridNode,\n ContentNode,\n ImgNode,\n SheetNode,\n CellNode,\n LinkNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport { BaseEncoder } from \"../../core/BaseEncoder\";\nimport type {\n DocMeta,\n PageDims,\n TextProps,\n ParaProps,\n CellProps,\n Stroke,\n} from \"../../model/doc-props\";\nimport { A4, DEFAULT_STROKE, normalizeDims } from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport { Metric, safeFontToKr } from \"../../safety/StyleBridge\";\nimport { ArchiveKit } from \"../../toolkit/ArchiveKit\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { registry } from \"../../pipeline/registry\";\nimport { HWPX_MIME_TYPE } from \"./constants\";\n\n// ─── HWPX 네임스페이스 ──────────────────────────────────────\nconst NS = [\n 'xmlns:ha=\"http://www.hancom.co.kr/hwpml/2011/app\"',\n 'xmlns:hp=\"http://www.hancom.co.kr/hwpml/2011/paragraph\"',\n 'xmlns:hp10=\"http://www.hancom.co.kr/hwpml/2016/paragraph\"',\n 'xmlns:hs=\"http://www.hancom.co.kr/hwpml/2011/section\"',\n 'xmlns:hc=\"http://www.hancom.co.kr/hwpml/2011/core\"',\n 'xmlns:hh=\"http://www.hancom.co.kr/hwpml/2011/head\"',\n 'xmlns:hhs=\"http://www.hancom.co.kr/hwpml/2011/history\"',\n 'xmlns:hm=\"http://www.hancom.co.kr/hwpml/2011/master-page\"',\n 'xmlns:hpf=\"http://www.hancom.co.kr/schema/2011/hpf\"',\n 'xmlns:dc=\"http://purl.org/dc/elements/1.1/\"',\n 'xmlns:opf=\"http://www.idpf.org/2007/opf\"',\n 'xmlns:ooxmlchart=\"http://www.hancom.co.kr/hwpml/2016/ooxmlchart\"',\n 'xmlns:epub=\"http://www.idpf.org/2007/ops\"',\n 'xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\"',\n].join(\" \");\n\n// ─── LinesegArray Flags 상수 (HWPX 스펙) ─────────────────\n// 첫 번째 lineseg: 0x160000 = 1441792 (시작 줄, 고정 위치)\n// 이후 lineseg: 0x60000 = 393216 (일반 줄)\nconst LINESEG_FLAGS_FIRST = 0x160000; // 1441792 - 첫 줄 (시작, 고정)\nconst LINESEG_FLAGS_OTHER = 0x60000; // 393216 - 이후 줄\n\n// ─── ANYTOHWP 영감: 언어별 폰트 레지스트리 ─────────────────\n// 7개 언어 그룹을 독립적으로 관리 — charPr fontRef의 정확한 ID 생성\nconst LANG_GROUPS = [\n \"HANGUL\",\n \"LATIN\",\n \"HANJA\",\n \"JAPANESE\",\n \"OTHER\",\n \"SYMBOL\",\n \"USER\",\n] as const;\ntype LangGroup = (typeof LANG_GROUPS)[number];\n\nclass LangFontBank {\n // 언어 그룹별 독립 폰트 맵: face → localId (0-based)\n private maps = new Map<LangGroup, Map<string, number>>(\n LANG_GROUPS.map((g) => [g, new Map<string, number>()]),\n );\n\n constructor() {\n // ANYTOHWP 기본값: 모든 그룹에 한컴 기본 폰트 등록 (id=0)\n this.registerAll(\"함초롬바탕\");\n }\n\n /** 모든 언어 그룹에 동일 폰트 등록 */\n registerAll(face: string): void {\n for (const g of LANG_GROUPS) {\n const m = this.maps.get(g)!;\n if (!m.has(face)) m.set(face, m.size);\n }\n }\n\n /** 특정 언어 그룹에 폰트 등록, 이미 있으면 기존 ID 반환 */\n register(lang: LangGroup, face: string): number {\n const m = this.maps.get(lang)!;\n if (m.has(face)) return m.get(face)!;\n const id = m.size;\n m.set(face, id);\n return id;\n }\n\n /** 폰트 이름 → 한글 폰트 여부 판별 (ANYTOHWP 방식) */\n private isKorean(face: string): boolean {\n return (\n /[\\uAC00-\\uD7A3\\u3131-\\u318E]/.test(face) ||\n [\"맑은\", \"나눔\", \"굴림\", \"돋움\", \"바탕\", \"함초롬\", \"한컴\", \"HY\"].some(\n (k) => face.includes(k),\n )\n );\n }\n\n /** TextProps.font 문자열에서 적절한 HANGUL/LATIN 그룹에 등록 */\n registerFont(rawFace: string): { hangulId: number; latinId: number } {\n const face = safeFontToKr(rawFace) || \"함초롬바탕\";\n const isKor = this.isKorean(face);\n // 한글 폰트: HANGUL/HANJA/JAPANESE/OTHER/SYMBOL/USER에 등록\n // 라틴 폰트: LATIN에 등록, 나머지는 기본값(0) 유지\n const hangulId = this.register(\"HANGUL\", isKor ? face : \"함초롬바탕\");\n const latinId = this.register(\"LATIN\", isKor ? \"함초롬바탕\" : face);\n for (const g of [\n \"HANJA\",\n \"JAPANESE\",\n \"OTHER\",\n \"SYMBOL\",\n \"USER\",\n ] as LangGroup[]) {\n this.register(g, isKor ? face : \"함초롬바탕\");\n }\n return { hangulId, latinId };\n }\n\n /** 언어 그룹별 폰트 목록 반환 */\n getFaces(lang: LangGroup): string[] {\n return [...this.maps.get(lang)!.keys()];\n }\n\n getId(lang: LangGroup, face: string): number {\n return this.maps.get(lang)!.get(face) ?? 0;\n }\n\n /** hh:fontfaces XML 생성 */\n toXml(): string {\n let xml = `<hh:fontfaces itemCnt=\"${LANG_GROUPS.length}\">`;\n for (const lang of LANG_GROUPS) {\n const faces = this.getFaces(lang);\n xml += `<hh:fontface lang=\"${lang}\" fontCnt=\"${faces.length}\">`;\n faces.forEach((face, i) => {\n xml +=\n `<hh:font id=\"${i}\" face=\"${esc(face)}\" type=\"TTF\" isEmbedded=\"0\">` +\n `<hh:typeInfo familyType=\"FCAT_UNKNOWN\" weight=\"0\" proportion=\"0\" contrast=\"0\" strokeVariation=\"0\" armStyle=\"0\" letterform=\"0\" midline=\"252\" xHeight=\"255\"/>` +\n `</hh:font>`;\n });\n xml += `</hh:fontface>`;\n }\n return xml + `</hh:fontfaces>`;\n }\n}\n\n// ─── ANYTOHWP 영감: BorderFill 레지스트리 ───────────────────\n// 하드코딩 \"1\" 제거 — 모든 셀/표의 실제 테두리를 추적\n\nconst KIND_MAP: Record<string, string> = {\n solid: \"SOLID\",\n dash: \"DASH\",\n dot: \"DOT\",\n double: \"DOUBLE\",\n none: \"NONE\",\n dash_dot: \"DASH_DOT\",\n dash_dot_dot: \"DASH_DOT_DOT\",\n};\n\nclass BorderFillBank {\n private fills: { id: number; xml: string }[] = [];\n private keyMap = new Map<string, number>();\n\n constructor() {\n // id=1: 기본 (테두리 없음) — ANYTOHWP의 기본 초기화 방식\n this._addXml(\n this._buildXml(undefined, undefined, undefined, undefined, undefined),\n );\n // id=2: 표 기본 테두리 (solid 0.5pt black)\n const defS: Stroke = { kind: \"solid\", pt: 0.5, color: \"000000\" };\n this._addXml(this._buildXml(defS, defS, defS, defS, undefined));\n }\n\n private _strokeXml(tag: string, s?: Stroke): string {\n const type =\n s && s.kind !== \"none\" ? (KIND_MAP[s.kind] ?? \"SOLID\") : \"NONE\";\n const w =\n s && s.kind !== \"none\" ? `${(s.pt * 0.3528).toFixed(2)} mm` : \"0.12 mm\";\n const c = s\n ? s.color.startsWith(\"#\")\n ? s.color\n : `#${s.color}`\n : \"#000000\";\n return `<hh:${tag} type=\"${type}\" width=\"${w}\" color=\"${c}\"/>`;\n }\n\n private _buildXml(\n top?: Stroke,\n right?: Stroke,\n bottom?: Stroke,\n left?: Stroke,\n bg?: string,\n ): string {\n const fill = bg\n ? `<hc:fillBrush><hc:winBrush faceColor=\"${bg.startsWith(\"#\") ? bg : \"#\" + bg}\" hatchColor=\"none\" alpha=\"0\"/></hc:fillBrush>`\n : \"\";\n return (\n `<hh:borderFill id=\"__ID__\" threeD=\"0\" shadow=\"0\" centerLine=\"NONE\" breakCellSeparateLine=\"0\">` +\n `<hh:slash type=\"NONE\" Crooked=\"0\" isCounter=\"0\"/>` +\n `<hh:backSlash type=\"NONE\" Crooked=\"0\" isCounter=\"0\"/>` +\n this._strokeXml(\"leftBorder\", left) +\n this._strokeXml(\"rightBorder\", right) +\n this._strokeXml(\"topBorder\", top) +\n this._strokeXml(\"bottomBorder\", bottom) +\n `<hh:diagonal type=\"NONE\" width=\"0.12 mm\" color=\"#000000\"/>` +\n fill +\n `</hh:borderFill>`\n );\n }\n\n private _addXml(xml: string): number {\n const id = this.fills.length + 1;\n this.fills.push({ id, xml: xml.replace(\"__ID__\", String(id)) });\n return id;\n }\n\n private _key(\n top?: Stroke,\n right?: Stroke,\n bottom?: Stroke,\n left?: Stroke,\n bg?: string,\n ): string {\n const sk = (s?: Stroke) =>\n s ? `${s.kind}:${s.pt.toFixed(2)}:${s.color}` : \"none\";\n return `${sk(top)}|${sk(right)}|${sk(bottom)}|${sk(left)}|${bg ?? \"\"}`;\n }\n\n /** 균일 테두리 등록 */\n addUniform(s?: Stroke, bg?: string): number {\n const key = this._key(s, s, s, s, bg);\n if (this.keyMap.has(key)) return this.keyMap.get(key)!;\n const id = this._addXml(this._buildXml(s, s, s, s, bg));\n this.keyMap.set(key, id);\n return id;\n }\n\n /** 방향별 테두리 등록 */\n addPerSide(\n top?: Stroke,\n right?: Stroke,\n bottom?: Stroke,\n left?: Stroke,\n bg?: string,\n ): number {\n const key = this._key(top, right, bottom, left, bg);\n if (this.keyMap.has(key)) return this.keyMap.get(key)!;\n const id = this._addXml(this._buildXml(top, right, bottom, left, bg));\n this.keyMap.set(key, id);\n return id;\n }\n\n /** CellProps에서 적절한 borderFill ID 계산 (하드코딩 \"1\" 완전 제거) */\n addFromCellProps(cp: CellProps, defStroke?: Stroke): number {\n const d = defStroke ?? DEFAULT_STROKE;\n const top = cp.top ?? d;\n const right = cp.right ?? d;\n const bottom = cp.bot ?? d;\n const left = cp.left ?? d;\n const bg = cp.bg;\n const uniform =\n top.kind === right.kind &&\n top.kind === bottom.kind &&\n top.kind === left.kind &&\n top.pt === right.pt &&\n top.pt === bottom.pt &&\n top.pt === left.pt &&\n top.color === right.color &&\n top.color === bottom.color &&\n top.color === left.color;\n return uniform\n ? this.addUniform(top, bg)\n : this.addPerSide(top, right, bottom, left, bg);\n }\n\n toXml(): string {\n return `<hh:borderFills itemCnt=\"${this.fills.length}\">${this.fills.map((f) => f.xml).join(\"\")}</hh:borderFills>`;\n }\n}\n\n// ─── ANYTOHWP 영감: PNG/JPEG 바이너리 헤더에서 픽셀 치수 추출\nfunction readPixelDims(\n b64: string,\n mime: string,\n): { w: number; h: number } | null {\n try {\n const raw = TextKit.base64Decode(b64);\n const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n\n if (mime.includes(\"png\")) {\n // PNG: 시그니처 8바이트 + IHDR 청크 길이(4) + 타입(4) + 너비(4) + 높이(4)\n if (\n raw.length >= 24 &&\n view.getUint32(0) === 0x89504e47 &&\n view.getUint32(4) === 0x0d0a1a0a\n ) {\n return { w: view.getUint32(16), h: view.getUint32(20) };\n }\n } else if (mime.includes(\"jpeg\") || mime.includes(\"jpg\")) {\n // JPEG: SOI(FF D8) 후 SOF0(FF C0) 또는 SOF2(FF C2) 마커 탐색\n let off = 2;\n while (off < raw.length - 4) {\n const marker = view.getUint16(off);\n off += 2;\n if (marker === 0xffc0 || marker === 0xffc2) {\n // SOF: length(2) + precision(1) + height(2) + width(2)\n return { w: view.getUint16(off + 5), h: view.getUint16(off + 3) };\n }\n if ((marker & 0xff00) !== 0xff00) break;\n const segLen = view.getUint16(off);\n off += segLen;\n }\n }\n } catch {\n /* 무시 */\n }\n return null;\n}\n\n// ─── charPr / paraPr 레지스트리 ─────────────────────────────\n\ninterface CharPrDef {\n id: number;\n height: number; // HWPX height 단위 (1000 = 10pt)\n bold: boolean;\n italic: boolean;\n underline: string; // \"NONE\" | \"BOTTOM\"\n strikeout: string; // \"NONE\" | \"SOLID\"\n textColor: string; // \"#RRGGBB\"\n hangulId: number; // HANGUL 그룹 폰트 ID\n latinId: number; // LATIN 그룹 폰트 ID\n bg?: string;\n}\n\ninterface ParaPrDef {\n id: number;\n align: string;\n leftHwp: number;\n rightHwp: number;\n intentHwp: number;\n prevHwp: number;\n nextHwp: number;\n lineSpacing: number;\n listType?: string;\n listLevel?: number;\n}\n\ninterface StyleEntry {\n id: number;\n name: string;\n engName: string;\n paraPrIDRef: number;\n charPrIDRef: number;\n}\n\ninterface BinEntry {\n id: string; // \"BIN0001\"\n name: string; // \"BIN0001.png\"\n data: Uint8Array;\n}\n\nfunction charPrKey(p: TextProps): string {\n return `${p.b ? 1 : 0}|${p.i ? 1 : 0}|${p.u ? 1 : 0}|${p.s ? 1 : 0}|${p.pt ?? 10}|${p.color ?? \"000000\"}|${p.font ?? \"\"}|${p.bg ?? \"\"}`;\n}\n\n/**\n * ParaProps 를 해시 키로 변환 (동일 포맷팅 감지용)\n * null/undefined는 0 으로 처리하여 일관성 유지\n */\nfunction paraPrKey(p: ParaProps): string {\n return `${p.align ?? \"left\"}|${p.listOrd ?? \"\"}|${p.listLv ?? 0}|${p.indentPt ?? 0}|${p.firstLineIndentPt ?? 0}|${p.spaceBefore ?? 0}|${p.spaceAfter ?? 0}|${p.lineHeight ?? 0}|${p.styleId ?? \"\"}`;\n}\n\n// ─── 인코딩 컨텍스트 ─────────────────────────────────────────\n\ninterface HwpxCtx {\n fontBank: LangFontBank;\n borderFillBank: BorderFillBank;\n charPrs: CharPrDef[];\n charPrMap: Map<string, number>;\n paraPrs: ParaPrDef[];\n paraPrMap: Map<string, number>;\n bins: BinEntry[];\n nextBinNum: number;\n nextElementId: number;\n availableWidth: number; // HWPUNIT\n imgMap: WeakMap<ImgNode, string>;\n nextZOrder: number;\n styleIdToHwpxId: Map<string, number>;\n hwpxStyles: StyleEntry[];\n}\n\nfunction registerCharPr(props: TextProps, ctx: HwpxCtx): number {\n const key = charPrKey(props);\n const existing = ctx.charPrMap.get(key);\n if (existing !== undefined) return existing;\n\n const rawFont = props.font ?? \"함초롬바탕\";\n const { hangulId, latinId } = ctx.fontBank.registerFont(rawFont);\n const id = ctx.charPrs.length;\n\n ctx.charPrs.push({\n id,\n height: Metric.ptToHHeight(props.pt ?? 10),\n bold: !!props.b,\n italic: !!props.i,\n underline: props.u ? \"BOTTOM\" : \"NONE\",\n strikeout: props.s ? \"SOLID\" : \"NONE\",\n textColor: props.color ? `#${props.color}` : \"#000000\",\n hangulId,\n latinId,\n bg: props.bg,\n });\n ctx.charPrMap.set(key, id);\n return id;\n}\n\nfunction registerParaPr(props: ParaProps, ctx: HwpxCtx): number {\n const key = paraPrKey(props);\n const existing = ctx.paraPrMap.get(key);\n if (existing !== undefined) return existing;\n\n const id = ctx.paraPrs.length;\n const def: ParaPrDef = {\n id,\n align: (props.align ?? \"left\").toUpperCase(),\n leftHwp: Metric.ptToHwp(props.indentPt ?? 0),\n rightHwp: Metric.ptToHwp(props.indentRightPt ?? 0),\n intentHwp: Metric.ptToHwp(props.firstLineIndentPt ?? 0),\n prevHwp: Metric.ptToHwp(props.spaceBefore ?? 0),\n nextHwp: Metric.ptToHwp(props.spaceAfter ?? 0),\n lineSpacing: props.lineHeight ? Math.round(props.lineHeight * 100) : 160,\n };\n if (props.listOrd !== undefined) {\n def.listType = props.listOrd ? \"DIGIT\" : \"BULLET\";\n def.listLevel = props.listLv ?? 0;\n }\n ctx.paraPrs.push(def);\n ctx.paraPrMap.set(key, id);\n return id;\n}\n\n// ─── 이미지 등록 ─────────────────────────────────────────────\n\nfunction mimeToExt(mime: string): string {\n if (mime.includes(\"jpeg\")) return \"jpg\";\n if (mime.includes(\"gif\")) return \"gif\";\n if (mime.includes(\"bmp\")) return \"bmp\";\n return \"png\";\n}\n\nfunction registerImage(img: ImgNode, ctx: HwpxCtx): void {\n if (ctx.imgMap.has(img)) return;\n const ext = mimeToExt(img.mime);\n const id = `BIN${String(ctx.nextBinNum).padStart(4, \"0\")}`;\n const name = `${id}.${ext}`;\n ctx.nextBinNum++;\n const data = TextKit.base64Decode(img.b64);\n ctx.bins.push({ id, name, data });\n ctx.imgMap.set(img, id);\n}\n\n// ─── 스타일 등록 ─────────────────────────────────────────────\n\nconst STYLE_NAME_MAP: Record<string, string> = {\n Normal: \"바탕글\",\n \"Heading 1\": \"개요 1\",\n \"Heading 2\": \"개요 2\",\n \"Heading 3\": \"개요 3\",\n \"Heading 4\": \"개요 4\",\n \"Heading 5\": \"개요 5\",\n \"Heading 6\": \"개요 6\",\n \"Body Text\": \"본문\",\n};\n\nfunction registerStyle(\n styleId: string,\n paraPrId: number,\n charPrId: number,\n ctx: HwpxCtx,\n): void {\n if (!styleId || ctx.styleIdToHwpxId.has(styleId)) return;\n if (styleId === \"Normal\") {\n ctx.styleIdToHwpxId.set(styleId, 0);\n return;\n }\n const hwpxId = ctx.hwpxStyles.length;\n ctx.styleIdToHwpxId.set(styleId, hwpxId);\n ctx.hwpxStyles.push({\n id: hwpxId,\n name: STYLE_NAME_MAP[styleId] ?? styleId,\n engName: \"\",\n paraPrIDRef: paraPrId,\n charPrIDRef: charPrId,\n });\n}\n\n// ─── Pre-scan: 콘텐츠 순회하며 모든 ID 사전 등록 ─────────────\n\nfunction scanPara(para: ParaNode, ctx: HwpxCtx): void {\n const paraPrId = registerParaPr(para.props, ctx);\n let firstCharPrId = 0;\n let hasFirstSpan = false;\n\n function scanKids(kids: ParaNode[\"kids\"]): void {\n for (const kid of kids) {\n if (kid.tag === \"span\") {\n const cId = registerCharPr(kid.props, ctx);\n if (!hasFirstSpan) {\n firstCharPrId = cId;\n hasFirstSpan = true;\n }\n } else if (kid.tag === \"img\") {\n registerImage(kid, ctx);\n } else if (kid.tag === \"link\") {\n scanKids((kid as LinkNode).kids as ParaNode[\"kids\"]);\n }\n }\n }\n scanKids(para.kids);\n if (para.props.styleId)\n registerStyle(para.props.styleId, paraPrId, firstCharPrId, ctx);\n}\n\nfunction scanGrid(grid: GridNode, ctx: HwpxCtx): void {\n const defStroke = grid.props.defaultStroke ?? DEFAULT_STROKE;\n // 표 기본 테두리 사전 등록\n ctx.borderFillBank.addUniform(defStroke);\n for (const row of grid.kids) {\n for (const cell of row.kids) {\n ctx.borderFillBank.addFromCellProps(cell.props, defStroke);\n for (const p of cell.kids) {\n if (p.tag === 'grid') scanGrid(p, ctx);\n else scanPara(p, ctx);\n }\n }\n }\n}\n\nfunction scanContent(kids: ContentNode[], ctx: HwpxCtx): void {\n for (const kid of kids) {\n if (kid.tag === \"para\") scanPara(kid, ctx);\n else if (kid.tag === \"grid\") scanGrid(kid, ctx);\n }\n}\n\n// ─── Encoder 클래스 ──────────────────────────────────────────\n\nexport class HwpxEncoder extends BaseEncoder {\n protected getFormat(): string { return \"hwpx\"; }\n protected getAliases(): string[] { return [HWPX_MIME_TYPE, \"application/hwp+zip\"]; }\n\n async encode(doc: DocRoot): Promise<Outcome<Uint8Array>> {\n try {\n const sheet = doc.kids[0];\n const dims = normalizeDims(sheet?.dims ?? A4);\n\n const safeML = dims.ml > 0 ? dims.ml : 70.87;\n const safeMR = dims.mr > 0 ? dims.mr : 70.87;\n const availableWidth = Math.round(\n Metric.ptToHwp(dims.wPt) -\n Metric.ptToHwp(safeML) -\n Metric.ptToHwp(safeMR),\n );\n\n // 컨텍스트 초기화\n const ctx: HwpxCtx = {\n fontBank: new LangFontBank(), // ANYTOHWP 방식 언어별 폰트\n borderFillBank: new BorderFillBank(), // 하드코딩 없는 테두리 관리\n charPrs: [],\n charPrMap: new Map(),\n paraPrs: [],\n paraPrMap: new Map(),\n bins: [],\n nextBinNum: 1,\n nextElementId: 10000,\n availableWidth,\n imgMap: new WeakMap(),\n nextZOrder: 0,\n styleIdToHwpxId: new Map(),\n hwpxStyles: [],\n };\n\n // id=0 기본 charPr/paraPr 등록\n registerCharPr({}, ctx);\n registerParaPr({}, ctx);\n\n // 바탕글(Normal) 스타일 id=0으로 고정\n ctx.hwpxStyles.push({\n id: 0,\n name: \"바탕글\",\n engName: \"Normal\",\n paraPrIDRef: 0,\n charPrIDRef: 0,\n });\n ctx.styleIdToHwpxId.set(\"Normal\", 0);\n\n // 패스 1: Pre-scan — 모든 charPr/paraPr/이미지/테두리 사전 등록\n scanContent(sheet?.kids ?? [], ctx);\n if (sheet?.headers?.default) for (const p of sheet.headers.default) scanPara(p, ctx);\n if (sheet?.footers?.default) for (const p of sheet.footers.default) scanPara(p, ctx);\n\n // 패스 2: Encode — section 먼저 (borderFill 동적 등록 완료 후 header 생성)\n const sectionData = this.stringToBytes(buildSectionXml(sheet, dims, ctx));\n const headerData = this.stringToBytes(buildHeaderXml(dims, doc.meta, ctx));\n const previewText = extractPreviewText(sheet);\n\n const entries: { name: string; data: Uint8Array; mime: string; compression?: 'STORE' | 'DEFLATE' }[] = [\n {\n name: \"mimetype\",\n data: new TextEncoder().encode(HWPX_MIME_TYPE),\n compression: \"STORE\",\n mime: \"\",\n },\n {\n name: \"version.xml\",\n data: this.stringToBytes(VERSION_XML),\n mime: \"application/xml\",\n },\n {\n name: \"META-INF/container.xml\",\n data: this.stringToBytes(CONTAINER_XML),\n mime: \"application/xml\",\n },\n {\n name: \"META-INF/container.rdf\",\n data: this.stringToBytes(CONTAINER_RDF),\n mime: \"application/rdf+xml\",\n },\n {\n name: \"Contents/content.hpf\",\n data: this.stringToBytes(buildContentHpf(ctx, doc.meta)),\n mime: \"application/hwpml-package+xml\",\n },\n {\n name: \"Contents/header.xml\",\n data: headerData,\n mime: \"application/xml\",\n },\n {\n name: \"Contents/section0.xml\",\n data: sectionData,\n mime: \"application/xml\",\n },\n {\n name: \"Preview/PrvText.txt\",\n data: this.stringToBytes(previewText),\n mime: \"text/plain\",\n },\n {\n name: \"settings.xml\",\n data: this.stringToBytes(buildSettingsXml()),\n mime: \"application/xml\",\n },\n ];\n\n for (const bin of ctx.bins) {\n const ext = bin.name.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const ct =\n ext === \"png\"\n ? \"image/png\"\n : ext === \"jpg\" || ext === \"jpeg\"\n ? \"image/jpeg\"\n : ext === \"gif\"\n ? \"image/gif\"\n : \"image/bmp\";\n entries.push({ name: `BinData/${bin.name}`, data: bin.data, mime: ct });\n }\n\n return succeed(await this.zip(entries));\n } catch (e: any) {\n return fail(`HWPX 인코딩 오류: ${e?.message ?? String(e)}`);\n }\n }\n}\n\n// ─── 상수 XML ────────────────────────────────────────────────\n\nconst VERSION_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<hv:HCFVersion xmlns:hv=\"http://www.owpml.org/owpml/2024/version\" ` +\n `targetApplication=\"WORDPROCESSING\" major=\"5\" minor=\"1\" micro=\"0\" buildNumber=\"1\" ` +\n `os=\"1\" xmlVersion=\"1.4\" application=\"Hancom Office Hangul\" appVersion=\"11, 0, 0, 0\"/>`;\n\nconst CONTAINER_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<ocf:container xmlns:ocf=\"urn:oasis:names:tc:opendocument:xmlns:container\" ` +\n `xmlns:hpf=\"http://www.hancom.co.kr/schema/2011/hpf\">` +\n `<ocf:rootfiles>` +\n `<ocf:rootfile full-path=\"Contents/content.hpf\" media-type=\"application/hwpml-package+xml\"/>` +\n `<ocf:rootfile full-path=\"Preview/PrvText.txt\" media-type=\"text/plain\"/>` +\n `<ocf:rootfile full-path=\"META-INF/container.rdf\" media-type=\"application/rdf+xml\"/>` +\n `</ocf:rootfiles></ocf:container>`;\n\nconst CONTAINER_RDF =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">` +\n `<rdf:Description rdf:about=\"\"><ns0:hasPart xmlns:ns0=\"http://www.hancom.co.kr/hwpml/2016/meta/pkg#\" rdf:resource=\"Contents/header.xml\"/></rdf:Description>` +\n `<rdf:Description rdf:about=\"Contents/header.xml\"><rdf:type rdf:resource=\"http://www.hancom.co.kr/hwpml/2016/meta/pkg#HeaderFile\"/></rdf:Description>` +\n `<rdf:Description rdf:about=\"\"><ns0:hasPart xmlns:ns0=\"http://www.hancom.co.kr/hwpml/2016/meta/pkg#\" rdf:resource=\"Contents/section0.xml\"/></rdf:Description>` +\n `<rdf:Description rdf:about=\"Contents/section0.xml\"><rdf:type rdf:resource=\"http://www.hancom.co.kr/hwpml/2016/meta/pkg#SectionFile\"/></rdf:Description>` +\n `<rdf:Description rdf:about=\"\"><rdf:type rdf:resource=\"http://www.hancom.co.kr/hwpml/2016/meta/pkg#Document\"/></rdf:Description>` +\n `</rdf:RDF>`;\n\nconst MANIFEST_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<odf:manifest xmlns:odf=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\"/>`;\n\n// ─── content.hpf ─────────────────────────────────────────────\n\nfunction buildContentHpf(ctx: HwpxCtx, meta?: DocMeta): string {\n const title = esc(meta?.title ?? \"\");\n const creator = esc(meta?.author ?? \"text\");\n const subject = esc(meta?.subject ?? \"text\");\n const desc = esc(meta?.desc ?? \"text\");\n const keyword = esc(meta?.keywords ?? \"text\");\n const created =\n meta?.created ?? new Date().toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n const modified = meta?.modified ?? created;\n\n let items =\n `<opf:item id=\"header\" href=\"Contents/header.xml\" media-type=\"application/xml\"/>` +\n `<opf:item id=\"section0\" href=\"Contents/section0.xml\" media-type=\"application/xml\"/>` +\n `<opf:item id=\"settings\" href=\"settings.xml\" media-type=\"application/xml\"/>`;\n\n for (const bin of ctx.bins) {\n const ext = bin.name.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const ct =\n ext === \"png\"\n ? \"image/png\"\n : ext === \"jpg\" || ext === \"jpeg\"\n ? \"image/jpeg\"\n : ext === \"gif\"\n ? \"image/gif\"\n : \"image/bmp\";\n items += `<opf:item id=\"${bin.id}\" href=\"BinData/${bin.name}\" media-type=\"${ct}\" isEmbeded=\"1\"/>`;\n }\n\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<opf:package ${NS} version=\"\" unique-identifier=\"\" id=\"\">` +\n `<opf:metadata>` +\n `<opf:title>${title}</opf:title><opf:language>ko</opf:language>` +\n `<opf:meta name=\"creator\" content=\"text\">${creator}</opf:meta>` +\n `<opf:meta name=\"subject\" content=\"text\">${subject}</opf:meta>` +\n `<opf:meta name=\"description\" content=\"text\">${desc}</opf:meta>` +\n `<opf:meta name=\"CreatedDate\" content=\"text\">${created}</opf:meta>` +\n `<opf:meta name=\"ModifiedDate\" content=\"text\">${modified}</opf:meta>` +\n `<opf:meta name=\"keyword\" content=\"text\">${keyword}</opf:meta>` +\n `<opf:meta name=\"trackchageConfig\" content=\"text\">0</opf:meta>` +\n `</opf:metadata>` +\n `<opf:manifest>${items}</opf:manifest>` +\n `<opf:spine><opf:itemref idref=\"header\"/><opf:itemref idref=\"section0\"/></opf:spine>` +\n `</opf:package>`\n );\n}\n\n// ─── settings.xml ────────────────────────────────────────────\n\nfunction buildSettingsXml(): string {\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<ha:HWPApplicationSetting xmlns:ha=\"http://www.hancom.co.kr/hwpml/2011/app\" ` +\n `xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\">` +\n `<ha:CaretPosition listIDRef=\"0\" paraIDRef=\"0\" pos=\"0\"/>` +\n `<config:config-item-set name=\"PrintInfo\">` +\n `<config:config-item name=\"PrintAutoFootNote\" type=\"boolean\">false</config:config-item>` +\n `<config:config-item name=\"PrintAutoHeadNote\" type=\"boolean\">false</config:config-item>` +\n `<config:config-item name=\"PrintMethod\" type=\"short\">4</config:config-item>` +\n `<config:config-item name=\"OverlapSize\" type=\"short\">0</config:config-item>` +\n `<config:config-item name=\"PrintCropMark\" type=\"short\">0</config:config-item>` +\n `<config:config-item name=\"BinderHoleType\" type=\"short\">0</config:config-item>` +\n `<config:config-item name=\"ZoomX\" type=\"short\">100</config:config-item>` +\n `<config:config-item name=\"ZoomY\" type=\"short\">100</config:config-item>` +\n `</config:config-item-set>` +\n `</ha:HWPApplicationSetting>`\n );\n}\n\nfunction buildNumberingsXml(): string {\n return (\n `<hh:numberings itemCnt=\"1\">` +\n `<hh:numbering id=\"1\" start=\"1\">` +\n `<hh:paraHead start=\"1\" level=\"1\" align=\"LEFT\" ` +\n `useInstWidth=\"1\" autoIndent=\"0\" widthAdjust=\"0\" ` +\n `textOffsetType=\"PERCENT\" textOffset=\"50\" ` +\n `numFormat=\"BULLET\" charPrIDRef=\"0\" checkable=\"0\"/>` +\n `</hh:numbering></hh:numberings>`\n );\n}\n\nfunction buildBulletsXml(): string {\n return (\n `<hh:bullets itemCnt=\"1\">` +\n `<hh:bullet id=\"1\" charPrIDRef=\"0\" start=\"1\" numFormat=\"BULLET\">` +\n `<hh:paraHead level=\"1\" numChar=\"&#x2022;\"/>` +\n `<hh:paraHead level=\"2\" numChar=\"&#x2022;\"/>` +\n `<hh:paraHead level=\"3\" numChar=\"&#x2022;\"/>` +\n `</hh:bullet></hh:bullets>`\n );\n}\n\n// ─── header.xml ──────────────────────────────────────────────\n\nfunction buildHeaderXml(dims: PageDims, meta: DocMeta, ctx: HwpxCtx): string {\n // 언어별 폰트 (LangFontBank → XML)\n const fontFacesXml = ctx.fontBank.toXml();\n\n // charPr 목록 — 언어별 폰트 ID를 fontRef에 반영 (ANYTOHWP 핵심 개선)\n let charPrXml = \"\";\n for (const cp of ctx.charPrs) {\n const bold = cp.bold ? \"<hh:bold/>\" : \"\";\n const italic = cp.italic ? \"<hh:italic/>\" : \"\";\n const hid = cp.hangulId;\n const lid = cp.latinId;\n const shadeColor = cp.bg ? (cp.bg.startsWith(\"#\") ? cp.bg : `#${cp.bg}`) : \"none\";\n charPrXml +=\n `<hh:charPr id=\"${cp.id}\" height=\"${cp.height}\" textColor=\"${cp.textColor}\" ` +\n `shadeColor=\"${shadeColor}\" useFontSpace=\"0\" useKerning=\"0\" symMark=\"NONE\" borderFillIDRef=\"1\">` +\n `<hh:fontRef hangul=\"${hid}\" latin=\"${lid}\" hanja=\"${hid}\" japanese=\"${hid}\" other=\"${lid}\" symbol=\"${lid}\" user=\"${lid}\"/>` +\n `<hh:ratio hangul=\"100\" latin=\"100\" hanja=\"100\" japanese=\"100\" other=\"100\" symbol=\"100\" user=\"100\"/>` +\n `<hh:spacing hangul=\"0\" latin=\"0\" hanja=\"0\" japanese=\"0\" other=\"0\" symbol=\"0\" user=\"0\"/>` +\n `<hh:relSz hangul=\"100\" latin=\"100\" hanja=\"100\" japanese=\"100\" other=\"100\" symbol=\"100\" user=\"100\"/>` +\n `<hh:offset hangul=\"0\" latin=\"0\" hanja=\"0\" japanese=\"0\" other=\"0\" symbol=\"0\" user=\"0\"/>` +\n bold +\n italic +\n `<hh:underline type=\"${cp.underline}\" shape=\"SOLID\" color=\"#000000\"/>` +\n `<hh:strikeout shape=\"${cp.strikeout}\" color=\"#000000\"/>` +\n `<hh:outline type=\"NONE\"/>` +\n `<hh:shadow type=\"NONE\" color=\"#C0C0C0\" offsetX=\"10\" offsetY=\"10\"/>` +\n `</hh:charPr>`;\n }\n\n // paraPr 목록\n let paraPrXml = \"\";\n for (const pp of ctx.paraPrs) {\n paraPrXml +=\n `<hh:paraPr id=\"${pp.id}\" tabPrIDRef=\"0\" condense=\"0\" fontLineHeight=\"0\" snapToGrid=\"0\" suppressLineNumbers=\"0\" checked=\"0\">` +\n `<hh:align horizontal=\"${pp.align}\" vertical=\"BASELINE\"/>` +\n `<hh:heading type=\"NONE\" idRef=\"0\" level=\"0\"/>` +\n `<hh:breakSetting breakLatinWord=\"KEEP_WORD\" breakNonLatinWord=\"BREAK_WORD\" widowOrphan=\"0\" keepWithNext=\"0\" keepLines=\"0\" pageBreakBefore=\"0\" lineWrap=\"BREAK\"/>` +\n `<hh:autoSpacing eAsianEng=\"0\" eAsianNum=\"0\"/>` +\n `<hh:margin>` +\n `<hc:intent value=\"${pp.intentHwp}\" unit=\"HWPUNIT\"/>` +\n `<hc:left value=\"${pp.leftHwp}\" unit=\"HWPUNIT\"/>` +\n `<hc:right value=\"${pp.rightHwp}\" unit=\"HWPUNIT\"/>` +\n `<hc:prev value=\"${pp.prevHwp}\" unit=\"HWPUNIT\"/>` +\n `<hc:next value=\"${pp.nextHwp}\" unit=\"HWPUNIT\"/>` +\n `</hh:margin>` +\n `<hh:lineSpacing type=\"PERCENT\" value=\"${pp.lineSpacing}\" unit=\"HWPUNIT\"/>` +\n `<hh:border borderFillIDRef=\"1\" offsetLeft=\"0\" offsetRight=\"0\" offsetTop=\"0\" offsetBottom=\"0\" connect=\"0\" ignoreMargin=\"0\"/>` +\n `</hh:paraPr>`;\n }\n\n // borderFill 목록 (BorderFillBank → XML)\n const borderFillXml = ctx.borderFillBank.toXml();\n\n // 스타일 목록\n const stylesXml =\n `<hh:styles itemCnt=\"${ctx.hwpxStyles.length}\">` +\n ctx.hwpxStyles\n .map(\n (s) =>\n `<hh:style id=\"${s.id}\" type=\"PARA\" name=\"${esc(s.name)}\" engName=\"${esc(s.engName)}\" ` +\n `paraPrIDRef=\"${s.paraPrIDRef}\" charPrIDRef=\"${s.charPrIDRef}\" nextStyleIDRef=\"0\" langID=\"1042\" lockForm=\"0\"/>`,\n )\n .join(\"\") +\n `</hh:styles>`;\n\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<hh:head ${NS} version=\"1.2\" secCnt=\"1\">` +\n `<hh:beginNum page=\"1\" footnote=\"1\" endnote=\"1\" pic=\"1\" tbl=\"1\" equation=\"1\"/>` +\n `<hh:refList>` +\n fontFacesXml +\n borderFillXml +\n `<hh:charProperties itemCnt=\"${ctx.charPrs.length}\">${charPrXml}</hh:charProperties>` +\n `<hh:tabProperties itemCnt=\"1\"><hh:tabPr id=\"0\" autoTabLeft=\"0\" autoTabRight=\"0\"/></hh:tabProperties>` +\n buildNumberingsXml() +\n buildBulletsXml() +\n `<hh:paraProperties itemCnt=\"${ctx.paraPrs.length}\">${paraPrXml}</hh:paraProperties>` +\n stylesXml +\n `</hh:refList>` +\n `<hh:compatibleDocument targetProgram=\"MS_WORD\"> \n <hh:layoutCompatibility>\n <hh:applyFontWeightToBold />\n <hh:useInnerUnderline />\n <hh:useLowercaseStrikeout />\n <hh:extendLineheightToOffset />\n <hh:treatQuotationAsLatin />\n <hh:doNotAlignWhitespaceOnRight />\n <hh:doNotAdjustWordInJustify />\n <hh:baseCharUnitOnEAsian />\n <hh:baseCharUnitOfIndentOnFirstChar />\n <hh:adjustLineheightToFont />\n <hh:adjustBaselineInFixedLinespacing />\n <hh:applyPrevspacingBeneathObject />\n <hh:applyNextspacingOfLastPara />\n <hh:adjustParaBorderfillToSpacing />\n <hh:connectParaBorderfillOfEqualBorder />\n <hh:adjustParaBorderOffsetWithBorder />\n <hh:extendLineheightToParaBorderOffset />\n <hh:applyParaBorderToOutside />\n <hh:applyMinColumnWidthTo1mm />\n <hh:applyTabPosBasedOnSegment />\n <hh:breakTabOverLine />\n <hh:adjustVertPosOfLine />\n <hh:doNotAlignLastForbidden />\n <hh:adjustMarginFromAdjustLineheight />\n <hh:baseLineSpacingOnLineGrid />\n <hh:applyCharSpacingToCharGrid />\n <hh:doNotApplyGridInHeaderFooter />\n <hh:applyExtendHeaderFooterEachSection />\n <hh:doNotApplyLinegridAtNoLinespacing />\n <hh:doNotAdjustEmptyAnchorLine />\n <hh:overlapBothAllowOverlap />\n <hh:extendVertLimitToPageMargins />\n <hh:doNotHoldAnchorOfTable />\n <hh:doNotFormattingAtBeneathAnchor />\n <hh:adjustBaselineOfObjectToBottom />\n </hh:layoutCompatibility>\n </hh:compatibleDocument>` +\n `<hh:docOption><hh:linkinfo path=\"\" pageInherit=\"0\" footnoteInherit=\"0\"/></hh:docOption>` +\n `<hh:trackchageConfig flags=\"56\"/>` +\n `</hh:head>`\n );\n}\n\n// ─── section0.xml ────────────────────────────────────────────\n\nfunction buildHeaderFooterRunXml(\n sheet: SheetNode,\n dims: PageDims,\n ctx: HwpxCtx,\n): string {\n const headers = sheet.headers || {};\n const footers = sheet.footers || {};\n const hasAny = Object.keys(headers).length > 0 || Object.keys(footers).length > 0;\n if (!hasAny) return \"\";\n\n const availW = ctx.availableWidth;\n const mtHwp = Metric.ptToHwp(dims.mt);\n const mbHwp = Metric.ptToHwp(dims.mb);\n const headerZoneH = dims.headerPt ? Math.max(100, mtHwp - Metric.ptToHwp(dims.headerPt)) : 3600;\n const footerZoneH = dims.footerPt ? Math.max(100, mbHwp - Metric.ptToHwp(dims.footerPt)) : 3600;\n\n let inner = \"\";\n\n // 1. 첫 페이지 숨김 설정 (first 헤더/푸터가 있으면 활성화)\n const hideFirst = !!(headers.first || footers.first);\n inner += `<hp:ctrl><hp:pageHiding hideHeader=\"${hideFirst ? 1 : 0}\" hideFooter=\"${hideFirst ? 1 : 0}\" hideMasterPage=\"0\" hideBorder=\"0\" hideFill=\"0\" hidePageNum=\"0\"/></hp:ctrl>`;\n\n // 2. 헤더들 생성\n for (const [type, paras] of Object.entries(headers)) {\n const applyPageType = type === \"even\" ? \"EVEN\" : (type === \"default\" || type === \"first\" ? \"BOTH\" : \"ODD\");\n const savedId = ctx.nextElementId;\n ctx.nextElementId = 0;\n const parasXml = paras.map((p) => encodeParaPositioned(p, ctx, 0, \"\", availW).xml).join(\"\");\n ctx.nextElementId = savedId;\n inner +=\n `<hp:ctrl>` +\n `<hp:header id=\"1\" applyPageType=\"${applyPageType}\">` +\n `<hp:subList id=\"\" textDirection=\"HORIZONTAL\" lineWrap=\"BREAK\" vertAlign=\"TOP\" ` +\n `linkListIDRef=\"0\" linkListNextIDRef=\"0\" textWidth=\"${availW}\" textHeight=\"${headerZoneH}\" ` +\n `hasTextRef=\"0\" hasNumRef=\"0\">` +\n parasXml +\n `</hp:subList>` +\n `</hp:header>` +\n `</hp:ctrl>`;\n }\n\n // 3. 푸터들 생성\n for (const [type, paras] of Object.entries(footers)) {\n const applyPageType = type === \"even\" ? \"EVEN\" : (type === \"default\" || type === \"first\" ? \"BOTH\" : \"ODD\");\n const savedId = ctx.nextElementId;\n ctx.nextElementId = 0;\n const parasXml = paras.map((p) => encodeParaPositioned(p, ctx, 0, \"\", availW).xml).join(\"\");\n ctx.nextElementId = savedId;\n inner +=\n `<hp:ctrl>` +\n `<hp:footer id=\"2\" applyPageType=\"${applyPageType}\">` +\n `<hp:subList id=\"\" textDirection=\"HORIZONTAL\" lineWrap=\"BREAK\" vertAlign=\"BOTTOM\" ` +\n `linkListIDRef=\"0\" linkListNextIDRef=\"0\" textWidth=\"${availW}\" textHeight=\"${footerZoneH}\" ` +\n `hasTextRef=\"0\" hasNumRef=\"0\">` +\n parasXml +\n `</hp:subList>` +\n `</hp:footer>` +\n `</hp:ctrl>`;\n }\n\n return `<hp:run charPrIDRef=\"0\" charTcId=\"0\">${inner}</hp:run>`;\n}\n\nfunction buildSectionXml(\n sheet: SheetNode | undefined,\n dims: PageDims,\n ctx: HwpxCtx,\n): string {\n const secPrXml = buildSecPrXml(dims);\n const kids = sheet?.kids ?? [];\n const hfRunXml = sheet ? buildHeaderFooterRunXml(sheet, dims, ctx) : \"\";\n\n // 가용 너비 계산 (HWPUNIT)\n const availWidth = Math.max(\n 1000,\n Metric.ptToHwp(dims.wPt) - Metric.ptToHwp(dims.ml) - Metric.ptToHwp(dims.mr),\n );\n ctx.availableWidth = availWidth;\n\n let contentXml = \"\";\n let vertPos = 0;\n\n for (let i = 0; i < kids.length; i++) {\n const kid = kids[i];\n const isFirst = i === 0;\n const curSecPr = isFirst ? secPrXml : \"\";\n const curHfRun = isFirst ? hfRunXml : \"\";\n\n if (kid.tag === \"para\") {\n const { xml, nextVertPos } = encodeParaPositioned(\n kid,\n ctx,\n vertPos,\n curSecPr,\n availWidth,\n curHfRun,\n );\n contentXml += xml;\n vertPos = nextVertPos;\n } else if (kid.tag === \"grid\") {\n const { xml, nextVertPos } = encodeGridPositioned(\n kid,\n ctx,\n vertPos,\n curSecPr,\n curHfRun,\n );\n contentXml += xml;\n vertPos = nextVertPos;\n }\n }\n\n if (kids.length === 0) {\n // 빈 문서 — 최소 단락 1개 필수\n const fs = 1000;\n const vs = 1600;\n const { xml: linesegXml } = buildLinesegarray(\" \", 0, fs, vs / (fs / 100), availWidth);\n contentXml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"0\" styleIDRef=\"0\" pageBreak=\"0\" columnBreak=\"0\" merged=\"0\" paraTcId=\"0\">` +\n secPrXml +\n hfRunXml +\n `<hp:run charPrIDRef=\"0\" charTcId=\"0\"><hp:t xml:space=\"preserve\"> </hp:t></hp:run>` +\n linesegXml +\n `</hp:p>`;\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><hs:sec ${NS} xmlns:hwpunitchar=\"http://www.hancom.co.kr/hwpml/2016/HwpUnitChar\">${contentXml}</hs:sec>`;\n}\n\nfunction buildSecPrXml(dims: PageDims): string {\n const wHwp = Metric.ptToHwp(dims.wPt);\n const hHwp = Metric.ptToHwp(dims.hPt);\n const ml = Metric.ptToHwp(dims.ml);\n const mr = Metric.ptToHwp(dims.mr);\n const mt = Metric.ptToHwp(dims.mt);\n const mb = Metric.ptToHwp(dims.mb);\n // HWPX margin header/footer = header/footer ZONE HEIGHT (not distance from paper edge)\n // = top_hwp - header_from_top_hwp (and bottom_hwp - footer_from_bottom_hwp)\n const headerZone = dims.headerPt\n ? Math.max(0, mt - Metric.ptToHwp(dims.headerPt))\n : 0;\n const footerZone = dims.footerPt\n ? Math.max(0, mb - Metric.ptToHwp(dims.footerPt))\n : 0;\n\n const pageBorderFill =\n `<hp:pageBorderFill type=\"BOTH\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hp:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hp:pageBorderFill>` +\n `<hp:pageBorderFill type=\"EVEN\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hp:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hp:pageBorderFill>` +\n `<hp:pageBorderFill type=\"ODD\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hp:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hp:pageBorderFill>`;\n\n return (\n `<hp:secPr id=\"0\" textDirection=\"HORIZONTAL\" spaceColumns=\"1134\" tabStop=\"8000\" outlineShapeIDRef=\"0\" memoShapeIDRef=\"0\" textVerticalWidthHead=\"0\" masterPageCnt=\"0\">` +\n `<hp:grid lineGrid=\"0\" charGrid=\"0\" wonggojiFormat=\"0\"/>` +\n `<hp:startNum pageStartsOn=\"BOTH\" page=\"0\" pic=\"0\" tbl=\"0\" equation=\"0\"/>` +\n `<hp:visibility hideFirstHeader=\"0\" hideFirstFooter=\"0\" hideFirstMasterPage=\"0\" border=\"SHOW_ALL\" fill=\"SHOW_ALL\" hideFirstPageNum=\"0\" hideFirstEmptyLine=\"0\" showLineNumber=\"0\"/>` +\n `<hp:lineNumberShape restartType=\"0\" countBy=\"0\" distance=\"0\" startNumber=\"0\"/>` +\n `<hp:pagePr landscape=\"${dims.wPt >= dims.hPt ? 'WIDELY' : 'NARROWLY'}\" width=\"${wHwp}\" height=\"${hHwp}\" gutterType=\"LEFT_ONLY\">` +\n `<hp:margin header=\"${headerZone}\" footer=\"${footerZone}\" gutter=\"0\" left=\"${ml}\" right=\"${mr}\" top=\"${mt}\" bottom=\"${mb}\"/>` +\n `</hp:pagePr>` +\n `<hp:colPr id=\"\" type=\"NEWSPAPER\" layout=\"LEFT\" colCount=\"1\" sameSz=\"1\" sameGap=\"0\"/>` +\n `<hp:footNotePr><hp:autoNumFormat type=\"DIGIT\" userChar=\"\" prefixChar=\"\" suffixChar=\"\" supscript=\"1\"/>` +\n `<hp:noteLine length=\"-1\" type=\"SOLID\" width=\"0.25 mm\" color=\"#000000\"/>` +\n `<hp:noteSpacing betweenNotes=\"283\" belowLine=\"0\" aboveLine=\"1000\"/>` +\n `<hp:numbering type=\"CONTINUOUS\" newNum=\"1\"/>` +\n `<hp:placement place=\"EACH_COLUMN\" beneathText=\"0\"/>` +\n `</hp:footNotePr>` +\n `<hp:endNotePr><hp:autoNumFormat type=\"DIGIT\" userChar=\"\" prefixChar=\"\" suffixChar=\"\" supscript=\"1\"/>` +\n `<hp:noteLine length=\"-1\" type=\"SOLID\" width=\"0.25 mm\" color=\"#000000\"/>` +\n `<hp:noteSpacing betweenNotes=\"0\" belowLine=\"0\" aboveLine=\"1000\"/>` +\n `<hp:numbering type=\"CONTINUOUS\" newNum=\"1\"/>` +\n `<hp:placement place=\"END_OF_DOCUMENT\" beneathText=\"0\"/>` +\n `</hp:endNotePr>` +\n pageBorderFill +\n `</hp:secPr>`\n );\n}\n\n// ─── 줄 정보 XML (linesegarray) ──────────────────────────────\n// 가이드 준수: 실제 시각적 줄 단위로 lineseg 생성\n\nfunction buildLinesegarray(\n text: string,\n vertPosStart: number,\n fontSize: number,\n lineSpacingPct: number,\n horzSize: number,\n): { xml: string; totalHeight: number } {\n const vertsizeLine = Math.round((fontSize * lineSpacingPct) / 100);\n const spacing = vertsizeLine - fontSize;\n const baseline = Math.round(fontSize * 0.83);\n\n // 글자 너비 추정 (영문 0.47, 한글 1.0)\n const isKorean = /[\\uAC00-\\uD7A3\\u3131-\\u318E]/.test(text);\n const charW = isKorean ? fontSize : Math.round(fontSize * 0.47);\n const charsPerLine = Math.max(1, Math.floor(horzSize / charW));\n const lineCount = text.length === 0 ? 1 : Math.ceil(text.length / charsPerLine);\n\n // 성능 최적화: 문자열 병합 대신 배열 수집 후 join 사용 (O(n²) → O(n))\n const linesegParts: string[] = [];\n for (let i = 0; i < lineCount; i++) {\n const flags = i === 0 ? LINESEG_FLAGS_FIRST : LINESEG_FLAGS_OTHER;\n linesegParts.push(\n `<hp:lineseg textpos=\"${i * charsPerLine}\" ` +\n `vertpos=\"${vertPosStart + i * vertsizeLine}\" ` +\n `vertsize=\"${vertsizeLine}\" textheight=\"${fontSize}\" ` +\n `baseline=\"${baseline}\" spacing=\"${spacing}\" ` +\n `horzpos=\"0\" horzsize=\"${horzSize}\" ` +\n `flags=\"${flags}\"/>`,\n );\n }\n\n return {\n xml: `<hp:linesegarray>${linesegParts.join(\"\")}</hp:linesegarray>`,\n totalHeight: lineCount * vertsizeLine,\n };\n}\n\n/** 단락에서 순수 텍스트 추출 (줄바꿈 계산용) */\nfunction extractParaText(para: ParaNode): string {\n let text = \"\";\n const walk = (kids: any[]) => {\n for (const k of kids) {\n if (k.tag === \"span\") {\n for (const c of k.kids) if (c.tag === \"txt\") text += c.content;\n } else if (k.tag === \"link\") {\n walk(k.kids);\n }\n }\n };\n walk(para.kids);\n return text;\n}\n\nfunction fontSizeForPara(para: ParaNode, ctx: HwpxCtx): number {\n for (const kid of para.kids) {\n if (kid.tag === \"span\") {\n const id = ctx.charPrMap.get(charPrKey(kid.props));\n if (id !== undefined && ctx.charPrs[id]) return ctx.charPrs[id].height;\n }\n }\n return 1000; // 기본 10pt\n}\n\n// ─── 단락 인코딩 ─────────────────────────────────────────────\n\nfunction encodeParaPositioned(\n para: ParaNode,\n ctx: HwpxCtx,\n vertPos: number,\n secPr = \"\",\n availWidth?: number,\n hfRun = \"\",\n): { xml: string; nextVertPos: number } {\n // ✅ 표(Grid)를 포함하는 단락인지 확인\n const gridKid = para.kids.find((k): k is GridNode => k.tag === \"grid\");\n if (gridKid) {\n return encodeTablePara(para, gridKid, ctx, vertPos, secPr, hfRun);\n }\n\n const paraPrId = ctx.paraPrMap.get(paraPrKey(para.props)) ?? 0;\n const styleIDRef = para.props.styleId\n ? (ctx.styleIdToHwpxId.get(para.props.styleId) ?? 0)\n : 0;\n const fontSize = fontSizeForPara(para, ctx);\n const paraPr = ctx.paraPrs[paraPrId];\n const lineSpacing = paraPr?.lineSpacing ?? 160;\n const spacing = Math.max(0, Math.round(fontSize * (lineSpacing / 100 - 1)));\n let vertSize = fontSize + spacing;\n const horzSize = availWidth ?? ctx.availableWidth;\n\n // 코드 블록 감지 (Courier 폰트 또는 styleId \"code\")\n const isCourierFont = (kids: ParaNode[\"kids\"]): boolean =>\n kids.some(\n (k) =>\n (k.tag === \"span\" && k.props.font?.toLowerCase().includes(\"courier\")) ||\n (k.tag === \"link\" &&\n isCourierFont((k as LinkNode).kids as ParaNode[\"kids\"])),\n );\n const isCode =\n availWidth === undefined &&\n (para.props.styleId?.toLowerCase().includes(\"code\") ||\n isCourierFont(para.kids));\n\n if (isCode)\n return encodeCodeBlockPositioned(\n para,\n ctx,\n vertPos,\n secPr,\n fontSize,\n spacing,\n vertSize,\n );\n\n let runsXml = encodeParaKids(para.kids, ctx);\n if (!runsXml) runsXml = `<hp:run charPrIDRef=\"0\" charTcId=\"0\"><hp:t xml:space=\"preserve\"> </hp:t></hp:run>`;\n\n const paraText = extractParaText(para);\n const { xml: linesegXml, totalHeight } = buildLinesegarray(\n paraText,\n vertPos,\n fontSize,\n lineSpacing,\n horzSize,\n );\n\n const hasPageBreak = para.kids.some(\n (k) => k.tag === \"span\" && k.kids.some((c) => c.tag === \"pb\"),\n );\n\n const xml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"${paraPrId}\" styleIDRef=\"${styleIDRef}\" ` +\n `pageBreak=\"${hasPageBreak ? 1 : 0}\" columnBreak=\"0\" merged=\"0\" paraTcId=\"0\">` +\n secPr +\n hfRun +\n runsXml +\n linesegXml +\n `</hp:p>`;\n\n return { xml, nextVertPos: vertPos + totalHeight };\n}\n\n/** ✅ 가이드 준수: 표를 포함하는 단락 인코딩 */\nfunction encodeTablePara(\n para: ParaNode,\n grid: GridNode,\n ctx: HwpxCtx,\n vertPos: number,\n secPr: string,\n hfRun: string,\n): { xml: string; nextVertPos: number } {\n const paraPrId = ctx.paraPrMap.get(paraPrKey(para.props)) ?? 0;\n \n // 표 알맹이 생성 (기존 로직 재사용)\n const { xml: gridXml, height: tblHeight } = buildGridXml(grid, ctx);\n \n // 가이드: 표 단락의 lineseg는 1개여야 하고, vertsize는 표 전체 높이여야 함\n const fontSize = 1000; \n const totalHeight = Math.max(1600, tblHeight);\n const baseline = 850;\n const spacing = Math.max(0, totalHeight - fontSize);\n\n const linesegXml =\n `<hp:linesegarray>` +\n `<hp:lineseg textpos=\"0\" vertpos=\"${vertPos}\" vertsize=\"${totalHeight}\" ` +\n `textheight=\"${fontSize}\" baseline=\"${baseline}\" spacing=\"${spacing}\" ` +\n `horzpos=\"0\" horzsize=\"${ctx.availableWidth}\" flags=\"1441792\"/>` +\n `</hp:linesegarray>`;\n\n const xml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"${paraPrId}\" styleIDRef=\"0\" ` +\n `pageBreak=\"0\" columnBreak=\"0\" merged=\"0\" paraTcId=\"0\">` +\n secPr +\n gridXml +\n hfRun +\n linesegXml +\n `</hp:p>`;\n\n return { xml, nextVertPos: vertPos + totalHeight };\n}\n\nfunction encodeCodeBlockPositioned(\n para: ParaNode,\n ctx: HwpxCtx,\n vertPos: number,\n secPr: string,\n fontSize: number,\n spacing: number,\n vertSize: number,\n): { xml: string; nextVertPos: number } {\n const codeBfId = ctx.borderFillBank.addUniform(\n { kind: \"solid\", pt: 0.5, color: \"aaaaaa\" },\n \"f4f4f4\",\n );\n const cellW = ctx.availableWidth;\n const innerW = Math.max(cellW - 510, 100);\n const subListId = ctx.nextElementId++;\n const { xml: innerXml } = encodeParaPositioned(para, ctx, 0, \"\", innerW);\n\n const paraText = extractParaText(para);\n const { xml: linesegXml, totalHeight } = buildLinesegarray(\n paraText,\n vertPos,\n fontSize,\n 160, // 코드 블록 기본 줄간격 160%\n ctx.availableWidth,\n );\n\n const xml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"0\" styleIDRef=\"0\" paraTcId=\"0\">` +\n secPr +\n `<hp:run charPrIDRef=\"0\" charTcId=\"0\">` +\n `<hp:tbl id=\"${ctx.nextElementId++}\" zOrder=\"0\" numberingType=\"TABLE\" textWrap=\"TOP_AND_BOTTOM\" textFlow=\"BOTH_SIDES\" lock=\"0\" dropcapstyle=\"None\" pageBreak=\"NONE\" rowCnt=\"1\" colCnt=\"1\" cellSpacing=\"0\" borderFillIDRef=\"${codeBfId}\" noAdjust=\"0\">` +\n `<hp:sz width=\"${cellW}\" widthRelTo=\"ABSOLUTE\" height=\"0\" heightRelTo=\"ABSOLUTE\" protect=\"0\"/>` +\n `<hp:pos treatAsChar=\"1\" affectLSpacing=\"0\" flowWithText=\"1\" allowOverlap=\"0\" holdAnchorAndSO=\"0\" vertRelTo=\"PARA\" horzRelTo=\"PARA\" vertAlign=\"TOP\" horzAlign=\"LEFT\" vertOffset=\"0\" horzOffset=\"0\"/>` +\n `<hp:outMargin left=\"138\" right=\"138\" top=\"138\" bottom=\"138\"/>` +\n `<hp:inMargin left=\"138\" right=\"138\" top=\"138\" bottom=\"138\"/>` +\n `<hp:tr><hp:tc name=\"\" header=\"0\" hasMargin=\"1\" protect=\"0\" editable=\"0\" dirty=\"0\" borderFillIDRef=\"${codeBfId}\">` +\n `<hp:subList id=\"${subListId}\" textDirection=\"HORIZONTAL\" lineWrap=\"BREAK\" vertAlign=\"CENTER\" linkListIDRef=\"0\" linkListNextIDRef=\"0\" textWidth=\"0\" textHeight=\"0\" hasTextRef=\"0\" hasNumRef=\"0\">` +\n innerXml +\n `</hp:subList>` +\n `<hp:cellAddr colAddr=\"0\" rowAddr=\"0\"/>` +\n `<hp:cellSpan colSpan=\"1\" rowSpan=\"1\"/>` +\n `<hp:cellSz width=\"${cellW}\" height=\"0\"/>` +\n `<hp:cellMargin left=\"283\" right=\"283\" top=\"141\" bottom=\"141\"/>` +\n `</hp:tc></hp:tr></hp:tbl><hp:t xml:space=\"preserve\"> </hp:t></hp:run>` +\n linesegXml +\n `</hp:p>`;\n\n return { xml, nextVertPos: vertPos + totalHeight };\n}\n\nfunction encodeParaKids(kids: ParaNode[\"kids\"], ctx: HwpxCtx): string {\n let xml = \"\";\n let currentRunCharPrId: number | null = null;\n let currentRunContent = \"\";\n\n const flushRun = () => {\n if (currentRunCharPrId !== null) {\n // 내용이 없더라도 빈 hp:t를 생성하여 '텍스트 없음' 오류 방지\n const content = currentRunContent || `<hp:t xml:space=\"preserve\"> </hp:t>`;\n xml += `<hp:run charPrIDRef=\"${currentRunCharPrId}\" charTcId=\"0\">${content}</hp:run>`;\n }\n currentRunCharPrId = null;\n currentRunContent = \"\";\n };\n\n for (const kid of kids) {\n if (kid.tag === \"span\") {\n const span = kid as SpanNode;\n const charPrId = ctx.charPrMap.get(charPrKey(span.props)) ?? 0;\n \n if (currentRunCharPrId !== null && currentRunCharPrId !== charPrId) {\n flushRun();\n }\n \n currentRunCharPrId = charPrId;\n currentRunContent += encodeRunInner(span);\n } \n else if (kid.tag === \"link\") {\n const link = kid as LinkNode;\n // 링크의 첫 번째 span 스타일을 기준으로 함\n let charPrId = 0;\n if (link.kids.length > 0 && link.kids[0].tag === \"span\") {\n charPrId = ctx.charPrMap.get(charPrKey((link.kids[0] as SpanNode).props)) ?? 0;\n }\n\n if (currentRunCharPrId !== null && currentRunCharPrId !== charPrId) {\n flushRun();\n }\n\n currentRunCharPrId = charPrId;\n currentRunContent += encodeLinkInner(link, ctx);\n }\n else if (kid.tag === \"img\") {\n flushRun();\n xml += encodeImgWrapped(kid, ctx);\n }\n }\n\n flushRun();\n return xml;\n}\n\n/** hp:run 내부의 태그들만 생성 (span용) */\nfunction encodeRunInner(span: SpanNode): string {\n let xml = \"\";\n for (const kid of span.kids) {\n if (kid.tag === \"txt\") {\n const content = esc(kid.content);\n if (content) xml += `<hp:t xml:space=\"preserve\">${content}</hp:t>`;\n } else if (kid.tag === \"br\") {\n xml += `<hp:t xml:space=\"preserve\">\\n</hp:t>`;\n } else if (kid.tag === \"pagenum\") {\n const fmt = (kid as any).format === \"roman\" ? \"ROMAN_LOWER\" \n : (kid as any).format === \"romanCaps\" ? \"ROMAN_UPPER\" : \"DIGIT\";\n xml += `<hp:pageNum pageStartsOn=\"BOTH\" formatType=\"${fmt}\"/>`;\n }\n }\n return xml;\n}\n\n/** hp:run 내부의 태그들만 생성 (link용) */\nfunction encodeLinkInner(link: LinkNode, ctx: HwpxCtx): string {\n const fieldId = 600000000 + (ctx.nextElementId++ % 100000000);\n const instanceId = 2100000000 + (ctx.nextElementId++ % 100000000);\n const url = link.href;\n\n let xml = `<hp:ctrl>` +\n `<hp:fieldBegin id=\"${instanceId}\" type=\"HYPERLINK\" name=\"\" editable=\"0\" dirty=\"1\" zorder=\"-1\" fieldid=\"${fieldId}\">` +\n `<hp:parameters cnt=\"6\" name=\"\">` +\n `<hp:integerParam name=\"Prop\">0</hp:integerParam>` +\n `<hp:stringParam name=\"Command\">${esc(url.replace(/:/g, \"\\\\:\"))};1;5;-1;</hp:stringParam>` +\n `<hp:stringParam name=\"Path\">${esc(url)}</hp:stringParam>` +\n `<hp:stringParam name=\"Category\">HWPHYPERLINK_TYPE_URL</hp:stringParam>` +\n `<hp:stringParam name=\"TargetType\">HWPHYPERLINK_TARGET_HYPERLINK</hp:stringParam>` +\n `<hp:stringParam name=\"DocOpenType\">HWPHYPERLINK_JUMP_DONTCARE</hp:stringParam>` +\n `</hp:parameters>` +\n `</hp:fieldBegin>` +\n `</hp:ctrl>`;\n\n for (const kid of link.kids) {\n if (kid.tag === \"span\") {\n xml += encodeRunInner(kid as SpanNode);\n }\n }\n\n xml += `<hp:ctrl><hp:fieldEnd beginIDRef=\"${instanceId}\"/></hp:ctrl>`;\n return xml;\n}\n\n// ─── 이미지 인코딩 (ANYTOHWP 영감: 픽셀 치수 추출) ──────────\n\nconst WRAP_MAP: Record<string, string> = {\n inline: \"TOP_AND_BOTTOM\",\n square: \"SQUARE\",\n tight: \"BOTH_SIDES\",\n through: \"BOTH_SIDES\",\n none: \"FRONT_TEXT\",\n behind: \"BEHIND_TEXT\",\n front: \"FRONT_TEXT\",\n};\nconst FLOW_MAP: Record<string, string> = {\n inline: \"BOTH_SIDES\",\n square: \"LARGEST_ONLY\",\n tight: \"BOTH_SIDES\",\n through: \"BOTH_SIDES\",\n none: \"BOTH_SIDES\",\n behind: \"BOTH_SIDES\",\n front: \"BOTH_SIDES\",\n};\n\nfunction encodeImage(img: ImgNode, ctx: HwpxCtx): string {\n // 0. 플레이스홀더 처리 (차트 등 b64가 없는 경우)\n if (!img.b64) {\n return `<hp:t xml:space=\"preserve\">${esc(img.alt || \"[개체]\")}</hp:t>`;\n }\n\n const binId = ctx.imgMap.get(img);\n if (!binId) return \"\";\n\n // ANYTOHWP 영감: PNG/JPEG 바이너리 헤더에서 실제 픽셀 치수 추출\n // img.w / img.h는 pt 단위이지만, 이미지 실제 픽셀을 HWPUNIT으로 변환하면 더 정확\n const pixelDims = readPixelDims(img.b64, img.mime);\n let wHwp: number, hHwp: number;\n\n if (pixelDims && pixelDims.w > 0 && pixelDims.h > 0) {\n // 픽셀 → pt (96dpi 기준) → HWPUNIT\n wHwp = Metric.ptToHwp((pixelDims.w * 72) / 96);\n hHwp = Metric.ptToHwp((pixelDims.h * 72) / 96);\n } else {\n wHwp = Metric.ptToHwp(img.w);\n hHwp = Metric.ptToHwp(img.h);\n }\n\n // 가용 너비 초과 방지 (비율 유지)\n if (wHwp > ctx.availableWidth) {\n hHwp = Math.round((hHwp * ctx.availableWidth) / wHwp);\n wHwp = ctx.availableWidth;\n }\n\n // 회전 중심점 (rotation center) 계산: 이미지 중앙을 기준으로 회전\n const rotationCenterX = Math.round(wHwp / 2);\n const rotationCenterY = Math.round(hHwp / 2);\n\n const layout = img.layout;\n const isInline = !layout || layout.wrap === \"inline\";\n const textWrap = layout ? (WRAP_MAP[layout.wrap] ?? \"SQUARE\") : \"SQUARE\";\n const textFlow = layout\n ? (FLOW_MAP[layout.wrap] ?? \"BOTH_SIDES\")\n : \"BOTH_SIDES\";\n const zOrder = ctx.nextZOrder++;\n\n return (\n `<hp:pic id=\"${ctx.nextElementId++}\" zOrder=\"${zOrder}\" numberingType=\"PICTURE\" ` +\n `textWrap=\"${textWrap}\" textFlow=\"${textFlow}\" lock=\"0\" dropcapstyle=\"None\" href=\"\" groupLevel=\"0\" instid=\"0\" reverse=\"0\">` +\n `<hp:offset x=\"0\" y=\"0\"/>` +\n `<hp:orgSz width=\"${wHwp}\" height=\"${hHwp}\"/>` +\n `<hp:curSz width=\"${wHwp}\" height=\"${hHwp}\"/>` +\n `<hp:flip horizontal=\"0\" vertical=\"0\"/>` +\n `<hp:rotationInfo angle=\"0\" centerX=\"${rotationCenterX}\" centerY=\"${rotationCenterY}\" rotateimage=\"1\"/>` +\n `<hp:renderingInfo>` +\n `<hc:transMatrix e1=\"1\" e2=\"0\" e3=\"0\" e4=\"0\" e5=\"1\" e6=\"0\"/>` +\n `<hc:scaMatrix e1=\"1\" e2=\"0\" e3=\"0\" e4=\"0\" e5=\"1\" e6=\"0\"/>` +\n `<hc:rotMatrix e1=\"1\" e2=\"0\" e3=\"0\" e4=\"0\" e5=\"1\" e6=\"0\"/>` +\n `</hp:renderingInfo>` +\n `<hp:imgRect>` +\n `<hc:pt0 x=\"0\" y=\"0\"/><hc:pt1 x=\"${wHwp}\" y=\"0\"/>` +\n `<hc:pt2 x=\"${wHwp}\" y=\"${hHwp}\"/><hc:pt3 x=\"0\" y=\"${hHwp}\"/>` +\n `</hp:imgRect>` +\n `<hp:imgClip left=\"0\" right=\"0\" top=\"0\" bottom=\"0\"/>` +\n `<hp:inMargin left=\"0\" right=\"0\" top=\"0\" bottom=\"0\"/>` +\n `<hp:imgDim dimwidth=\"${wHwp}\" dimheight=\"${hHwp}\"/>` +\n `<hc:img binaryItemIDRef=\"${binId}\" bright=\"0\" contrast=\"0\" effect=\"REAL_PIC\" alpha=\"0\"/>` +\n `<hp:effects/>` +\n `<hp:sz width=\"${wHwp}\" widthRelTo=\"ABSOLUTE\" height=\"${hHwp}\" heightRelTo=\"ABSOLUTE\" protect=\"0\"/>` +\n `<hp:pos treatAsChar=\"${isInline ? 1 : 0}\" affectLSpacing=\"0\" flowWithText=\"1\" ` +\n `allowOverlap=\"0\" holdAnchorAndSO=\"0\" vertRelTo=\"PARA\" horzRelTo=\"PARA\" ` +\n `vertAlign=\"TOP\" horzAlign=\"LEFT\" vertOffset=\"0\" horzOffset=\"0\"/>` +\n `<hp:outMargin left=\"0\" right=\"0\" top=\"0\" bottom=\"0\"/>` +\n `</hp:pic>`\n );\n}\n\nfunction encodeImgWrapped(img: ImgNode, ctx: HwpxCtx): string {\n const content = encodeImage(img, ctx);\n if (!img.b64) {\n return `<hp:run charPrIDRef=\"0\" charTcId=\"0\">${content}</hp:run>`;\n }\n return `<hp:run charPrIDRef=\"0\" charTcId=\"0\">${content}<hp:t xml:space=\"preserve\"> </hp:t></hp:run>`;\n}\n\n// ─── 표(Grid) 인코딩 ─────────────────────────────────────────\n\nfunction encodeGridPositioned(\n grid: GridNode,\n ctx: HwpxCtx,\n vertPos: number,\n secPr = \"\",\n hfRun = \"\",\n): { xml: string; nextVertPos: number } {\n const { xml: gridXml, height: tblHeight } = buildGridXml(grid, ctx);\n const totalHeight = Math.max(1600, tblHeight);\n const fontSize = 1000;\n const baseline = Math.round(fontSize * 0.83);\n const spacing = Math.max(0, totalHeight - fontSize);\n\n const linesegXml =\n `<hp:linesegarray>` +\n `<hp:lineseg textpos=\"0\" vertpos=\"${vertPos}\" vertsize=\"${totalHeight}\" ` +\n `textheight=\"${fontSize}\" baseline=\"${baseline}\" spacing=\"${spacing}\" ` +\n `horzpos=\"0\" horzsize=\"${ctx.availableWidth}\" flags=\"${LINESEG_FLAGS_FIRST}\"/>` +\n `</hp:linesegarray>`;\n\n const xml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"0\" styleIDRef=\"0\" pageBreak=\"0\" columnBreak=\"0\" merged=\"0\" paraTcId=\"0\">` +\n secPr +\n hfRun +\n gridXml +\n linesegXml +\n `</hp:p>`;\n\n return { xml, nextVertPos: vertPos + totalHeight };\n}\nfunction buildGridXml(\n grid: GridNode,\n ctx: HwpxCtx,\n): { xml: string; height: number } {\n const rowCount = grid.kids.length;\n // ... (기존 tableMap 생성 로직 동일)\n\n // 가상 2D 맵 — 병합 셀 처리\n interface CellEntry {\n type: \"real\" | \"absorbed\";\n cell?: CellNode;\n }\n const tableMap: CellEntry[][] = Array.from({ length: rowCount }, () => []);\n\n for (let ri = 0; ri < rowCount; ri++) {\n let ci = 0;\n for (const cell of grid.kids[ri].kids) {\n while (tableMap[ri][ci]) ci++;\n tableMap[ri][ci] = { type: \"real\", cell };\n for (let rr = 0; rr < cell.rs; rr++) {\n const tri = ri + rr;\n if (tri >= rowCount) break;\n for (let cc = 0; cc < cell.cs; cc++) {\n if (rr === 0 && cc === 0) continue;\n tableMap[tri][ci + cc] = { type: \"absorbed\" };\n }\n }\n ci += cell.cs;\n }\n }\n\n let colCount = 0;\n for (let ri = 0; ri < rowCount; ri++)\n colCount = Math.max(colCount, tableMap[ri].length);\n if (colCount === 0) colCount = 1;\n\n // 컬럼 너비 계산 (Bug 6: 균등 배분 금지, 원본 보존)\n const totalW = ctx.availableWidth;\n const colWidths: number[] = [];\n\n if (grid.props.colWidths && grid.props.colWidths.length === colCount) {\n // pt -> HWPUNIT 변환하여 원본 값 보존\n for (const wPt of grid.props.colWidths) {\n colWidths.push(Metric.ptToHwp(wPt));\n }\n } else {\n // 너비 정보가 없을 때만 균등 배분\n const defW = Math.round(totalW / colCount);\n for (let c = 0; c < colCount; c++) colWidths.push(defW);\n }\n\n // 본문 너비 초과 시에만 비율 축소 보정\n const rawTotal = colWidths.reduce((s, w) => s + w, 0);\n if (rawTotal > totalW && rawTotal > 0) {\n const scale = totalW / rawTotal;\n for (let i = 0; i < colWidths.length; i++) {\n colWidths[i] = Math.max(100, Math.round(colWidths[i] * scale));\n }\n }\n const actualTotal = colWidths.reduce((s, w) => s + w, 0);\n\n // 행 높이 계산\n const rowHeights: number[] = [];\n for (let ri = 0; ri < rowCount; ri++) {\n if (\n grid.kids[ri].heightPt != null &&\n (grid.kids[ri].heightPt as number) > 0\n ) {\n rowHeights.push(Metric.ptToHwp(grid.kids[ri].heightPt as number));\n } else {\n let maxH = 0;\n for (let ci = 0; ci < colCount; ci++) {\n const entry = tableMap[ri][ci];\n if (entry?.type === \"real\") {\n const h = estimateCellHeight(entry.cell!, ctx);\n if (h > maxH) maxH = h;\n }\n }\n rowHeights.push(maxH || Math.round(1000 * 1.6));\n }\n }\n const totalH = rowHeights.reduce((s, h) => s + h, 0);\n\n const defStroke = grid.props.defaultStroke ?? DEFAULT_STROKE;\n // 표 기본 테두리 — BorderFillBank에서 실제 ID 조회\n const tblBfId = ctx.borderFillBank.addUniform(defStroke);\n\n let rowsXml = \"\";\n for (let ri = 0; ri < rowCount; ri++) {\n let cellsXml = \"\";\n for (let ci = 0; ci < colCount; ci++) {\n const entry = tableMap[ri][ci];\n if (!entry || entry.type === \"absorbed\") continue;\n const cell = entry.cell!;\n const cp = cell.props;\n\n // 셀 테두리 — BorderFillBank에서 실제 ID 조회 (하드코딩 제거)\n const cellBfId = ctx.borderFillBank.addFromCellProps(cp, defStroke);\n\n let cellW = 0;\n for (let sc = ci; sc < ci + cell.cs && sc < colWidths.length; sc++)\n cellW += colWidths[sc];\n if (!cellW) cellW = Math.round(totalW / colCount) * cell.cs;\n\n const subListId = ctx.nextElementId++;\n\n // 셀 여백 (기본 141)\n const padL = cp.padL !== undefined ? Metric.ptToHwp(cp.padL) : 141;\n const padR = cp.padR !== undefined ? Metric.ptToHwp(cp.padR) : 141;\n const padT = cp.padT !== undefined ? Metric.ptToHwp(cp.padT) : 141;\n const padB = cp.padB !== undefined ? Metric.ptToHwp(cp.padB) : 141;\n\n const innerW = Math.max(cellW - padL - padR, 100);\n let parasXml = '';\n if (cell.kids.length > 0) {\n for (const kid of cell.kids) {\n if (kid.tag === 'grid') {\n // 중첩 표: <hp:p><hp:run><hp:tbl>...</hp:tbl></hp:run></hp:p> 형식으로 감싸기\n const { xml: tblXml } = buildGridXml(kid, ctx);\n const pid = ctx.nextElementId++;\n const rid = ctx.nextElementId++;\n parasXml += `<hp:p id=\"${pid}\" paraPrIDRef=\"0\" styleIDRef=\"0\" paraTcId=\"0\"><hp:run id=\"${rid}\" charPrIDRef=\"0\" charTcId=\"0\">${tblXml}</hp:run></hp:p>`;\n } else {\n parasXml += encodeParaPositioned(kid, ctx, 0, '', innerW).xml;\n }\n }\n } else {\n parasXml = `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"0\" styleIDRef=\"0\" paraTcId=\"0\"><hp:run charPrIDRef=\"0\" charTcId=\"0\"><hp:t xml:space=\"preserve\"> </hp:t></hp:run></hp:p>`;\n }\n\n const vAlign =\n cp.va === \"mid\" ? \"CENTER\" : cp.va === \"bot\" ? \"BOTTOM\" : \"TOP\";\n\n cellsXml +=\n `<hp:tc name=\"\" header=\"0\" hasMargin=\"1\" protect=\"0\" editable=\"0\" dirty=\"0\" borderFillIDRef=\"${cellBfId}\">` +\n `<hp:cellAddr colAddr=\"${ci}\" rowAddr=\"${ri}\"/>` +\n `<hp:cellSpan colSpan=\"${cell.cs}\" rowSpan=\"${cell.rs}\"/>` +\n `<hp:cellSz width=\"${cellW}\" height=\"${rowHeights[ri]}\"/>` +\n `<hp:cellMargin left=\"${padL}\" right=\"${padR}\" top=\"${padT}\" bottom=\"${padB}\"/>` +\n `<hp:subList id=\"${subListId}\" textDirection=\"HORIZONTAL\" lineWrap=\"BREAK\" vertAlign=\"${vAlign}\" ` +\n `linkListIDRef=\"0\" linkListNextIDRef=\"0\" textWidth=\"${innerW}\" textHeight=\"${Math.max(100, rowHeights[ri] - padT - padB)}\" hasTextRef=\"0\" hasNumRef=\"0\">` +\n parasXml +\n `</hp:subList>` +\n `</hp:tc>`;\n }\n rowsXml += `<hp:tr>${cellsXml}</hp:tr>`;\n }\n\n // 표 정렬 처리\n const alignMap: Record<string, string> = {\n left: 'LEFT', right: 'RIGHT', center: 'CENTER', justify: 'JUSTIFY',\n };\n const horzAlign = alignMap[grid.props.align ?? 'left'] ?? 'LEFT';\n\n const headerRow = grid.props.headerRow ? ' repeatHeader=\"1\"' : \"\";\n const xml =\n `<hp:tbl id=\"${ctx.nextElementId++}\" zOrder=\"0\" numberingType=\"TABLE\" textWrap=\"TOP_AND_BOTTOM\" textFlow=\"BOTH_SIDES\" lock=\"0\" dropcapstyle=\"None\" pageBreak=\"NONE\"${headerRow} rowCnt=\"${rowCount}\" colCnt=\"${colCount}\" cellSpacing=\"0\" borderFillIDRef=\"${tblBfId}\" noAdjust=\"0\">` +\n `<hp:sz width=\"${actualTotal}\" widthRelTo=\"ABSOLUTE\" height=\"${totalH}\" heightRelTo=\"ABSOLUTE\" protect=\"0\"/>` +\n `<hp:pos treatAsChar=\"1\" affectLSpacing=\"0\" flowWithText=\"1\" allowOverlap=\"0\" holdAnchorAndSO=\"0\" vertRelTo=\"PARA\" horzRelTo=\"PARA\" vertAlign=\"TOP\" horzAlign=\"${horzAlign}\" vertOffset=\"0\" horzOffset=\"0\"/>` +\n `<hp:outMargin left=\"138\" right=\"138\" top=\"138\" bottom=\"138\"/>` +\n `<hp:inMargin left=\"0\" right=\"0\" top=\"0\" bottom=\"0\"/>` +\n rowsXml +\n `</hp:tbl>`;\n\n return { xml, height: totalH };\n}\n\nfunction estimateCellHeight(cell: CellNode, ctx: HwpxCtx): number {\n const topPad = 141;\n const botPad = 141;\n let h = 0;\n for (const kid of cell.kids) {\n if (kid.tag === 'grid') {\n // 중첩 표 높이는 최소값으로 처리\n h += 1600;\n continue;\n }\n const para = kid;\n const fs = fontSizeForPara(para, ctx);\n const ppId = ctx.paraPrMap.get(paraPrKey(para.props));\n const pp = ppId !== undefined ? ctx.paraPrs[ppId] : null;\n const ls = pp?.lineSpacing ?? 160;\n const before = pp?.prevHwp ?? 0;\n const after = pp?.nextHwp ?? 0;\n h += Math.round((fs * ls) / 100) + before + after;\n }\n if (!h) h = Math.round(1000 * 1.6);\n return h + topPad + botPad;\n}\n\n// ─── 미리보기 텍스트 추출 ────────────────────────────────────\n\nfunction extractPreviewText(sheet?: SheetNode): string {\n if (!sheet) return \"\";\n const lines: string[] = [];\n for (const kid of sheet.kids) {\n if (kid.tag === \"para\") {\n const text = kid.kids\n .flatMap((k) =>\n k.tag === \"span\"\n ? k.kids.flatMap((c) => (c.tag === \"txt\" ? [c.content] : []))\n : [],\n )\n .join(\"\");\n if (text) lines.push(text);\n } else if (kid.tag === \"grid\") {\n for (const row of kid.kids) {\n const cells = row.kids.map((cell) =>\n cell.kids\n .flatMap((p) =>\n p.tag === 'para'\n ? p.kids.flatMap((k) =>\n k.tag === \"span\"\n ? k.kids.flatMap((c) => (c.tag === \"txt\" ? [c.content] : []))\n : [],\n )\n : [],\n )\n .join(\"\"),\n );\n lines.push(cells.join(\"\\t\"));\n }\n }\n }\n return lines.join(\"\\r\\n\");\n}\n\n// ─── XML 이스케이프 ──────────────────────────────────────────\n\nfunction esc(s: string): string {\n if (!s) return \"\";\n s = s.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n s = s.replace(/湰灧/g, \"\").replace(/\\uFEFF/g, \"\");\n // XML 1.0 비허용 제어문자 제거\n // eslint-disable-next-line no-control-regex\n s = s.replace(\n /[^\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]/gu,\n \"\",\n );\n return TextKit.escapeXml(s);\n}\n\nregistry.registerEncoder(new HwpxEncoder());\n","import type {\n DocRoot,\n ParaNode,\n SpanNode,\n GridNode,\n ContentNode,\n ImgNode,\n SheetNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport type { PageDims, GridProps, CellProps } from \"../../model/doc-props\";\nimport { A4, normalizeDims } from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport { Metric } from \"../../safety/StyleBridge\";\nimport { ArchiveKit } from \"../../toolkit/ArchiveKit\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { registry } from \"../../pipeline/registry\";\nimport { BaseEncoder } from \"../../core/BaseEncoder\";\n\ninterface ImageEntry {\n rId: string;\n name: string;\n data: Uint8Array;\n ext: string;\n}\n\nexport class DocxEncoder extends BaseEncoder {\n protected getFormat(): string {\n return \"docx\";\n }\n\n async encode(doc: DocRoot): Promise<Outcome<Uint8Array>> {\n try {\n // 모든 섹션(SheetNode)을 처리 — 첫 번째 섹션에서 헤더/푸터/페이지 설정을 가져오고\n // 이후 섹션들의 콘텐츠는 sectPr로 구분하여 단일 body에 병합한다.\n const sheets = doc.kids.length > 0 ? doc.kids : [];\n const firstSheet = sheets[0];\n const dims = normalizeDims(firstSheet?.dims ?? A4);\n\n // 모든 섹션의 콘텐츠를 합산\n const allKids: ContentNode[] = sheets.flatMap((s) => s?.kids ?? []);\n\n const images: ImageEntry[] = [];\n const ctx: EncCtx = {\n images,\n nextId: 10,\n nextImgNum: 1,\n warns: [],\n imgMap: new WeakMap(),\n };\n\n // Collect images from all content\n collectImages(allKids, ctx);\n\n // Header / footer (첫 번째 섹션 기준)\n let headerParas = firstSheet?.headers?.default;\n let footerParas = firstSheet?.footers?.default;\n const hasHeader = headerParas && headerParas.length > 0;\n const hasFooter = footerParas && footerParas.length > 0;\n\n // Collect images from header/footer\n if (hasHeader) collectImagesFromParas(headerParas!, ctx);\n if (hasFooter) collectImagesFromParas(footerParas!, ctx);\n\n const headerRId = hasHeader ? `rId${ctx.nextId++}` : \"\";\n const footerRId = hasFooter ? `rId${ctx.nextId++}` : \"\";\n\n // Numbering: collect list info from all sections\n const numInfo = collectNumbering(allKids);\n\n // kids 참조를 allKids로 통일 (후속 코드 호환)\n const kids = allKids;\n\n const entries: { name: string; data: Uint8Array }[] = [\n {\n name: \"[Content_Types].xml\",\n data: this.stringToBytes(contentTypes(images, hasHeader, hasFooter)),\n },\n { name: \"_rels/.rels\", data: this.stringToBytes(pkgRels()) },\n {\n name: \"word/document.xml\",\n data: this.stringToBytes(\n documentXml(kids, dims, ctx, headerRId, footerRId),\n ),\n },\n { name: \"word/styles.xml\", data: this.stringToBytes(stylesXml()) },\n { name: \"word/settings.xml\", data: this.stringToBytes(settingsXml()) },\n {\n name: \"word/_rels/document.xml.rels\",\n data: this.stringToBytes(\n docRels(images, headerRId, footerRId, numInfo.hasLists),\n ),\n },\n { name: \"docProps/app.xml\", data: this.stringToBytes(appXml()) },\n {\n name: \"docProps/core.xml\",\n data: this.stringToBytes(coreXml(doc.meta)),\n },\n ];\n\n // Add numbering.xml if needed\n if (numInfo.hasLists) {\n entries.push({\n name: \"word/numbering.xml\",\n data: this.stringToBytes(numberingXml(numInfo)),\n });\n }\n\n // Add header/footer files\n if (hasHeader) {\n entries.push({\n name: \"word/header1.xml\",\n data: this.stringToBytes(headerFooterXml(\"hdr\", headerParas!, ctx)),\n });\n }\n if (hasFooter) {\n entries.push({\n name: \"word/footer1.xml\",\n data: this.stringToBytes(headerFooterXml(\"ftr\", footerParas!, ctx)),\n });\n }\n\n // Add image media files\n for (const img of images) {\n entries.push({ name: `word/media/${img.name}`, data: img.data });\n }\n\n return succeed(await this.zip(entries));\n } catch (e: any) {\n return fail(`DOCX encode error: ${e?.message ?? String(e)}`);\n }\n }\n}\n\n// ─── Context ────────────────────────────────────────────────\n\ninterface EncCtx {\n images: ImageEntry[];\n nextId: number;\n nextImgNum: number;\n warns: string[];\n imgMap: WeakMap<ImgNode, string>; // ImgNode → rId (no mutation)\n}\n\n// ─── Image collection ───────────────────────────────────────\n\nfunction mimeToExt(mime: string): string {\n if (mime.includes(\"jpeg\")) return \"jpeg\";\n if (mime.includes(\"gif\")) return \"gif\";\n if (mime.includes(\"bmp\")) return \"bmp\";\n return \"png\";\n}\n\nfunction collectImages(kids: ContentNode[], ctx: EncCtx): void {\n for (const kid of kids) {\n if (kid.tag === \"para\") collectImagesFromPara(kid, ctx);\n else if (kid.tag === \"grid\") {\n for (const row of kid.kids)\n for (const cell of row.kids)\n for (const p of cell.kids)\n if (p.tag === \"para\") collectImagesFromPara(p, ctx);\n else collectImages([p], ctx);\n }\n }\n}\n\nfunction collectImagesFromParas(paras: ParaNode[], ctx: EncCtx): void {\n for (const p of paras) collectImagesFromPara(p, ctx);\n}\n\nfunction collectImagesFromPara(para: ParaNode, ctx: EncCtx): void {\n for (const kid of para.kids) {\n if (kid.tag === \"img\") registerImage(kid, ctx);\n }\n}\n\nfunction registerImage(img: ImgNode, ctx: EncCtx): void {\n if (ctx.imgMap.has(img)) return;\n const ext = mimeToExt(img.mime);\n const name = `image${ctx.nextImgNum++}.${ext}`;\n const rId = `rId${ctx.nextId++}`;\n const data = TextKit.base64Decode(img.b64);\n ctx.images.push({ rId, name, data, ext });\n ctx.imgMap.set(img, rId);\n}\n\n// ─── List/numbering collection ──────────────────────────────\n\ninterface NumInfo {\n hasLists: boolean;\n hasBullet: boolean;\n hasNumbered: boolean;\n}\n\nfunction collectNumbering(kids: ContentNode[]): NumInfo {\n let hasBullet = false;\n let hasNumbered = false;\n for (const kid of kids) {\n if (kid.tag === \"para\") {\n if (kid.props.listOrd === true) hasNumbered = true;\n else if (kid.props.listOrd === false) hasBullet = true;\n }\n }\n return { hasLists: hasBullet || hasNumbered, hasBullet, hasNumbered };\n}\n\n// ─── OOXML boilerplate ──────────────────────────────────────\n\nfunction contentTypes(\n images: ImageEntry[],\n hasHeader?: boolean,\n hasFooter?: boolean,\n): string {\n const imgDefaults = new Set<string>();\n for (const img of images) imgDefaults.add(img.ext);\n\n let defaults = `<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>`;\n\n for (const ext of imgDefaults) {\n const ct =\n ext === \"png\"\n ? \"image/png\"\n : ext === \"jpeg\"\n ? \"image/jpeg\"\n : ext === \"gif\"\n ? \"image/gif\"\n : \"image/bmp\";\n defaults += `\\n <Default Extension=\"${ext}\" ContentType=\"${ct}\"/>`;\n }\n\n let overrides = `<Override PartName=\"/word/document.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml\"/>\n <Override PartName=\"/word/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml\"/>\n <Override PartName=\"/word/settings.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml\"/>\n <Override PartName=\"/docProps/core.xml\" ContentType=\"application/vnd.openxmlformats-package.core-properties+xml\"/>\n <Override PartName=\"/docProps/app.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.extended-properties+xml\"/>`;\n\n if (hasHeader)\n overrides += `\\n <Override PartName=\"/word/header1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml\"/>`;\n if (hasFooter)\n overrides += `\\n <Override PartName=\"/word/footer1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml\"/>`;\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n ${defaults}\n ${overrides}\n</Types>`;\n}\n\nfunction pkgRels(): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"word/document.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties\" Target=\"docProps/core.xml\"/>\n <Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties\" Target=\"docProps/app.xml\"/>\n</Relationships>`;\n}\n\nfunction docRels(\n images: ImageEntry[],\n headerRId?: string,\n footerRId?: string,\n hasLists?: boolean,\n): string {\n let rels = `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings\" Target=\"settings.xml\"/>`;\n\n // Numbering relationship — only when lists exist\n if (hasLists) {\n rels += `\\n <Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering\" Target=\"numbering.xml\"/>`;\n }\n\n for (const img of images) {\n rels += `\\n <Relationship Id=\"${img.rId}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image\" Target=\"media/${img.name}\"/>`;\n }\n\n if (headerRId) {\n rels += `\\n <Relationship Id=\"${headerRId}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header\" Target=\"header1.xml\"/>`;\n }\n if (footerRId) {\n rels += `\\n <Relationship Id=\"${footerRId}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer\" Target=\"footer1.xml\"/>`;\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n ${rels}\n</Relationships>`;\n}\n\nfunction appXml(): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\">\n <Application>hwpkit</Application>\n</Properties>`;\n}\n\nfunction coreXml(meta: any): string {\n const now = new Date().toISOString();\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <dc:title>${esc(meta.title ?? \"\")}</dc:title>\n <dc:creator>${esc(meta.author ?? \"\")}</dc:creator>\n <dcterms:created xsi:type=\"dcterms:W3CDTF\">${meta.created ?? now}</dcterms:created>\n <dcterms:modified xsi:type=\"dcterms:W3CDTF\">${now}</dcterms:modified>\n</cp:coreProperties>`;\n}\n\nfunction stylesXml(): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:styles xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">\n <w:docDefaults>\n <w:rPrDefault><w:rPr>\n <w:rFonts w:ascii=\"맑은 고딕\" w:eastAsia=\"맑은 고딕\" w:hAnsi=\"맑은 고딕\"/>\n <w:sz w:val=\"20\"/>\n <w:szCs w:val=\"20\"/>\n </w:rPr></w:rPrDefault>\n <w:pPrDefault><w:pPr>\n <w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/>\n <w:jc w:val=\"both\"/>\n </w:pPr></w:pPrDefault>\n </w:docDefaults>\n <w:style w:type=\"paragraph\" w:default=\"1\" w:styleId=\"Normal\"><w:name w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Heading1\"><w:name w:val=\"heading 1\"/><w:basedOn w:val=\"Normal\"/><w:pPr><w:keepNext/><w:outlineLvl w:val=\"0\"/></w:pPr><w:rPr><w:b/><w:sz w:val=\"44\"/><w:szCs w:val=\"44\"/></w:rPr></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Heading2\"><w:name w:val=\"heading 2\"/><w:basedOn w:val=\"Normal\"/><w:pPr><w:keepNext/><w:outlineLvl w:val=\"1\"/></w:pPr><w:rPr><w:b/><w:sz w:val=\"36\"/><w:szCs w:val=\"36\"/></w:rPr></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Heading3\"><w:name w:val=\"heading 3\"/><w:basedOn w:val=\"Normal\"/><w:pPr><w:keepNext/><w:outlineLvl w:val=\"2\"/></w:pPr><w:rPr><w:b/><w:sz w:val=\"28\"/><w:szCs w:val=\"28\"/></w:rPr></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Header\"><w:name w:val=\"header\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Footer\"><w:name w:val=\"footer\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"ListParagraph\"><w:name w:val=\"List Paragraph\"/><w:basedOn w:val=\"Normal\"/><w:pPr><w:ind w:left=\"720\"/></w:pPr></w:style>\n <w:style w:type=\"table\" w:styleId=\"TableGrid\"><w:name w:val=\"Table Grid\"/><w:tblPr><w:tblBorders><w:top w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:left w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:bottom w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:right w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:insideH w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:insideV w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/></w:tblBorders></w:tblPr></w:style>\n</w:styles>`;\n}\n\nfunction settingsXml(): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:settings xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">\n <w:zoom w:percent=\"100\"/>\n <w:bordersDoNotSurroundHeader/>\n <w:bordersDoNotSurroundFooter/>\n <w:defaultTabStop w:val=\"800\"/>\n <w:compat>\n <w:spaceForUL/>\n <w:balanceSingleByteDoubleByteWidth/>\n <w:doNotLeaveBackslashAlone/>\n <w:ulTrailSpace/>\n <w:doNotExpandShiftReturn/>\n <w:adjustLineHeightInTable/>\n <w:useFELayout/>\n </w:compat>\n</w:settings>`;\n}\n\n// ─── numbering.xml ──────────────────────────────────────────\n\nfunction numberingXml(info: NumInfo): string {\n let abstractNums = \"\";\n let nums = \"\";\n\n // Bullet list: abstractNumId=0, numId=1\n if (info.hasBullet) {\n abstractNums += `<w:abstractNum w:abstractNumId=\"0\">`;\n for (let lvl = 0; lvl < 9; lvl++) {\n const marker = lvl === 0 ? \"●\" : lvl === 1 ? \"○\" : \"■\";\n const indent = (lvl + 1) * 720;\n abstractNums += `<w:lvl w:ilvl=\"${lvl}\"><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"${marker}\"/><w:pPr><w:ind w:left=\"${indent}\" w:hanging=\"360\"/></w:pPr></w:lvl>`;\n }\n abstractNums += `</w:abstractNum>`;\n nums += `<w:num w:numId=\"1\"><w:abstractNumId w:val=\"0\"/></w:num>`;\n }\n\n // Numbered list: abstractNumId=1, numId=2\n if (info.hasNumbered) {\n abstractNums += `<w:abstractNum w:abstractNumId=\"1\">`;\n for (let lvl = 0; lvl < 9; lvl++) {\n const fmt =\n lvl % 3 === 0\n ? \"decimal\"\n : lvl % 3 === 1\n ? \"lowerLetter\"\n : \"lowerRoman\";\n const indent = (lvl + 1) * 720;\n abstractNums += `<w:lvl w:ilvl=\"${lvl}\"><w:start w:val=\"1\"/><w:numFmt w:val=\"${fmt}\"/><w:lvlText w:val=\"%${lvl + 1}.\"/><w:pPr><w:ind w:left=\"${indent}\" w:hanging=\"360\"/></w:pPr></w:lvl>`;\n }\n abstractNums += `</w:abstractNum>`;\n nums += `<w:num w:numId=\"2\"><w:abstractNumId w:val=\"1\"/></w:num>`;\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:numbering xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">\n ${abstractNums}\n ${nums}\n</w:numbering>`;\n}\n\n// ─── header / footer xml ────────────────────────────────────\n\nfunction headerFooterXml(\n type: \"hdr\" | \"ftr\",\n paras: ParaNode[],\n ctx: EncCtx,\n): string {\n const tag = type === \"hdr\" ? \"w:hdr\" : \"w:ftr\";\n const body = paras.map((p) => encodeParaInner(p, ctx)).join(\"\\n\");\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<${tag} xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">\n${body}\n</${tag}>`;\n}\n\n// ─── document.xml ───────────────────────────────────────────\n\nfunction documentXml(\n kids: ContentNode[],\n dims: PageDims,\n ctx: EncCtx,\n headerRId?: string,\n footerRId?: string,\n): string {\n const body = kids.map((k) => encodeContent(k, ctx, dims)).join(\"\\n\");\n\n let sectRefs = \"\";\n if (headerRId)\n sectRefs += `\\n <w:headerReference w:type=\"default\" r:id=\"${headerRId}\"/>`;\n if (footerRId)\n sectRefs += `\\n <w:footerReference w:type=\"default\" r:id=\"${footerRId}\"/>`;\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:document xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">\n <w:body>\n${body}\n <w:sectPr>${sectRefs}\n <w:pgSz w:w=\"${Metric.ptToDxa(dims.wPt)}\" w:h=\"${Metric.ptToDxa(dims.hPt)}\" w:orient=\"${dims.orient ?? \"portrait\"}\"/>\n <w:pgMar w:top=\"${Metric.ptToDxa(dims.mt)}\" w:right=\"${Metric.ptToDxa(dims.mr)}\" w:bottom=\"${Metric.ptToDxa(dims.mb)}\" w:left=\"${Metric.ptToDxa(dims.ml)}\" w:header=\"709\" w:footer=\"709\" w:gutter=\"0\"/>\n </w:sectPr>\n </w:body>\n</w:document>`;\n}\n\nfunction encodeContent(\n node: ContentNode,\n ctx: EncCtx,\n dims?: PageDims,\n): string {\n return node.tag === \"grid\"\n ? encodeGrid(node, ctx, dims)\n : encodeParaInner(node, ctx);\n}\n\nfunction encodeParaInner(para: ParaNode, ctx: EncCtx): string {\n const align = para.props.align ?? \"left\";\n const headStyle = para.props.heading\n ? `<w:pStyle w:val=\"Heading${para.props.heading}\"/>`\n : \"\";\n\n // List numbering\n let numPr = \"\";\n if (para.props.listOrd !== undefined) {\n const numId = para.props.listOrd ? 2 : 1;\n const ilvl = para.props.listLv ?? 0;\n numPr = `<w:pStyle w:val=\"ListParagraph\"/><w:numPr><w:ilvl w:val=\"${ilvl}\"/><w:numId w:val=\"${numId}\"/></w:numPr>`;\n }\n\n // Spacing (before / after / line height) - ensure all values are non-negative\n // ECMA-376 §17.3.1.33 spacing: line은 1/240th of a line(auto) 또는 dxa(exact/atLeast)\n let spacingXml = \"\";\n const { spaceBefore, spaceAfter, lineHeight, lineHeightFixed } = para.props;\n if (\n spaceBefore !== undefined ||\n spaceAfter !== undefined ||\n lineHeight !== undefined ||\n lineHeightFixed !== undefined\n ) {\n const parts: string[] = [];\n if (spaceBefore !== undefined)\n parts.push(`w:before=\"${Math.max(0, Metric.ptToDxa(spaceBefore))}\"`);\n if (spaceAfter !== undefined)\n parts.push(`w:after=\"${Math.max(0, Metric.ptToDxa(spaceAfter))}\"`);\n if (lineHeightFixed !== undefined) {\n // FIXED: lineRule=\"exact\", line값은 dxa (1pt = 20dxa)\n parts.push(\n `w:line=\"${Math.max(1, Metric.ptToDxa(lineHeightFixed))}\" w:lineRule=\"exact\"`,\n );\n } else if (lineHeight !== undefined) {\n parts.push(`w:line=\"${Math.round(lineHeight * 240)}\" w:lineRule=\"auto\"`);\n }\n spacingXml = `<w:spacing ${parts.join(\" \")}/>`;\n }\n\n // Indentation — ECMA-376 §17.3.1.12 ind\n // w:left = 전체 왼쪽 여백(dxa), w:right = 전체 오른쪽 여백(dxa)\n // w:firstLine = 첫 줄 추가 들여쓰기(dxa, 양수), w:hanging = 내어쓰기(dxa, 양수값으로 표현)\n let indentXml = \"\";\n const leftDxa = Math.round(Metric.ptToDxa(para.props.indentPt ?? 0));\n const rightDxa = Math.round(Metric.ptToDxa(para.props.indentRightPt ?? 0));\n const firstPt = para.props.firstLineIndentPt ?? 0;\n\n const indParts: string[] = [];\n if (leftDxa > 0) indParts.push(`w:left=\"${leftDxa}\"`);\n if (rightDxa > 0) indParts.push(`w:right=\"${rightDxa}\"`);\n if (firstPt > 0)\n indParts.push(`w:firstLine=\"${Math.round(Metric.ptToDxa(firstPt))}\"`);\n if (firstPt < 0)\n indParts.push(`w:hanging=\"${Math.round(Metric.ptToDxa(-firstPt))}\"`);\n if (indParts.length > 0) indentXml = `<w:ind ${indParts.join(\" \")}/>`;\n\n const runs = para.kids\n .map((k) => {\n if (k.tag === \"span\") return encodeRun(k, ctx);\n if (k.tag === \"img\") return encodeImage(k, ctx);\n return \"\";\n })\n .join(\"\");\n\n return ` <w:p>\n <w:pPr>${headStyle}${numPr}${spacingXml}${indentXml}<w:jc w:val=\"${align === \"justify\" ? \"both\" : align}\"/></w:pPr>\n ${runs}\n </w:p>`;\n}\n\nfunction encodeRun(span: SpanNode, _ctx: EncCtx): string {\n const p = span.props;\n const rPr: string[] = [];\n if (p.b) rPr.push(\"<w:b/>\");\n if (p.i) rPr.push(\"<w:i/>\");\n if (p.u) rPr.push('<w:u w:val=\"single\"/>');\n if (p.s) rPr.push(\"<w:strike/>\");\n if (p.sup) rPr.push('<w:vertAlign w:val=\"superscript\"/>');\n if (p.sub) rPr.push('<w:vertAlign w:val=\"subscript\"/>');\n if (p.pt)\n rPr.push(\n `<w:sz w:val=\"${Metric.ptToHalfPt(p.pt)}\"/><w:szCs w:val=\"${Metric.ptToHalfPt(p.pt)}\"/>`,\n );\n if (p.color) rPr.push(`<w:color w:val=\"${p.color}\"/>`);\n if (p.font)\n rPr.push(\n `<w:rFonts w:ascii=\"${esc(p.font)}\" w:hAnsi=\"${esc(p.font)}\" w:eastAsia=\"${esc(p.font)}\"/>`,\n );\n if (p.bg) rPr.push(`<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${p.bg}\"/>`);\n\n // Process kids — text and pagenum\n const parts: string[] = [];\n for (const kid of span.kids) {\n if (kid.tag === \"txt\") {\n // __EXT_N__ or __EXT_N_W<w>_H<h>__ 자리표시자 제거\n const content = kid.content.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n if (content) {\n parts.push(\n `<w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:t xml:space=\"preserve\">${esc(content)}</w:t></w:r>`,\n );\n }\n } else if (kid.tag === \"pagenum\") {\n parts.push(\n `<w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:fldChar w:fldCharType=\"begin\"/></w:r><w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:instrText> PAGE </w:instrText></w:r><w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:fldChar w:fldCharType=\"separate\"/></w:r><w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:t>1</w:t></w:r><w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:fldChar w:fldCharType=\"end\"/></w:r>`,\n );\n } else if (kid.tag === \"br\") {\n parts.push(`<w:r><w:br/></w:r>`);\n } else if (kid.tag === \"pb\") {\n parts.push(`<w:r><w:br w:type=\"page\"/></w:r>`);\n }\n }\n\n return parts.join(\"\");\n}\n\nfunction encodeImage(img: ImgNode, ctx: EncCtx): string {\n const rId = ctx.imgMap.get(img);\n if (!rId) return \"\";\n\n // Fallback to 72pt (1 inch) when w/h are 0 to prevent invisible images\n const cx = Metric.ptToEmu(img.w > 0 ? img.w : 72);\n const cy = Metric.ptToEmu(img.h > 0 ? img.h : 72);\n const alt = esc(img.alt ?? \"\");\n const docPrId = ctx.nextId++;\n\n const graphic = `<a:graphic><a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\"><pic:pic><pic:nvPicPr><pic:cNvPr id=\"0\" name=\"Image\"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed=\"${rId}\"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x=\"0\" y=\"0\"/><a:ext cx=\"${cx}\" cy=\"${cy}\"/></a:xfrm><a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic>`;\n\n const layout = img.layout;\n\n const isInline = !layout || layout.wrap === \"inline\";\n // topAndBottom은 반드시 anchor (float)로 처리\n const forceAnchor =\n layout?.wrap === \"topAndBottom\" ||\n layout?.wrap === \"square\" ||\n layout?.wrap === \"tight\" ||\n layout?.wrap === \"behind\" ||\n layout?.wrap === \"front\";\n if (isInline && !forceAnchor) {\n return `<w:r><w:drawing><wp:inline distT=\"0\" distB=\"0\" distL=\"0\" distR=\"0\"><wp:extent cx=\"${cx}\" cy=\"${cy}\"/><wp:docPr id=\"${docPrId}\" name=\"Image\" descr=\"${alt}\"/>${graphic}</wp:inline></w:drawing></w:r>`;\n }\n return `<w:r><w:drawing>${encodeAnchor(img, cx, cy, alt, docPrId, graphic, layout!)}</w:drawing></w:r>`;\n}\n\nfunction encodeAnchor(\n _img: ImgNode,\n cx: number,\n cy: number,\n alt: string,\n docPrId: number,\n graphic: string,\n layout: NonNullable<ImgNode[\"layout\"]>,\n): string {\n const distT = Metric.ptToEmu(layout.distT ?? 0);\n const distB = Metric.ptToEmu(layout.distB ?? 0);\n const distL = Metric.ptToEmu(layout.distL ?? 9144); // DOCX 기본 0.18pt\n const distR = Metric.ptToEmu(layout.distR ?? 9144);\n const behindDoc = layout.behindDoc || layout.wrap === \"behind\" ? \"1\" : \"0\";\n const relH = layout.zOrder ?? 251658240;\n\n // 가로 위치\n const horzRelFrom = HORZ_RELTO_DOCX[layout.horzRelTo ?? \"column\"] ?? \"column\";\n let posH: string;\n if (layout.xPt != null) {\n posH = `<wp:positionH relativeFrom=\"${horzRelFrom}\"><wp:posOffset>${Metric.ptToEmu(layout.xPt)}</wp:posOffset></wp:positionH>`;\n } else {\n const ha = HORZ_ALIGN_DOCX[layout.horzAlign ?? \"left\"] ?? \"left\";\n posH = `<wp:positionH relativeFrom=\"${horzRelFrom}\"><wp:align>${ha}</wp:align></wp:positionH>`;\n }\n\n // 세로 위치\n const vertRelFrom =\n VERT_RELTO_DOCX[layout.vertRelTo ?? \"para\"] ?? \"paragraph\";\n let posV: string;\n if (layout.yPt != null) {\n posV = `<wp:positionV relativeFrom=\"${vertRelFrom}\"><wp:posOffset>${Metric.ptToEmu(layout.yPt)}</wp:posOffset></wp:positionV>`;\n } else {\n const va = VERT_ALIGN_DOCX[layout.vertAlign ?? \"top\"] ?? \"top\";\n posV = `<wp:positionV relativeFrom=\"${vertRelFrom}\"><wp:align>${va}</wp:align></wp:positionV>`;\n }\n\n // 텍스트 감싸기\n const wrapXml =\n WRAP_DOCX[layout.wrap] ?? '<wp:wrapSquare wrapText=\"bothSides\"/>';\n\n return `<wp:anchor distT=\"${distT}\" distB=\"${distB}\" distL=\"${distL}\" distR=\"${distR}\" simplePos=\"0\" relativeHeight=\"${relH}\" behindDoc=\"${behindDoc}\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\"><wp:simplePos x=\"0\" y=\"0\"/>${posH}${posV}<wp:extent cx=\"${cx}\" cy=\"${cy}\"/><wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>${wrapXml}<wp:docPr id=\"${docPrId}\" name=\"Image\" descr=\"${alt}\"/>${graphic}</wp:anchor>`;\n}\n\nconst HORZ_RELTO_DOCX: Record<string, string> = {\n margin: \"margin\",\n column: \"column\",\n page: \"page\",\n para: \"paragraph\",\n};\nconst VERT_RELTO_DOCX: Record<string, string> = {\n margin: \"margin\",\n line: \"line\",\n page: \"page\",\n para: \"paragraph\",\n};\nconst HORZ_ALIGN_DOCX: Record<string, string> = {\n left: \"left\",\n center: \"center\",\n right: \"right\",\n};\nconst VERT_ALIGN_DOCX: Record<string, string> = {\n top: \"top\",\n center: \"center\",\n bottom: \"bottom\",\n};\n// ECMA-376 §20.4.2 wordprocessingDrawing wrapping elements\nconst WRAP_DOCX: Record<string, string> = {\n square: '<wp:wrapSquare wrapText=\"bothSides\"/>',\n tight:\n '<wp:wrapTight><wp:wrapPolygon edited=\"0\"><wp:start x=\"0\" y=\"0\"/><wp:lineTo x=\"0\" y=\"21600\"/><wp:lineTo x=\"21600\" y=\"21600\"/><wp:lineTo x=\"21600\" y=\"0\"/><wp:lineTo x=\"0\" y=\"0\"/></wp:wrapPolygon></wp:wrapTight>',\n through:\n '<wp:wrapThrough wrapText=\"bothSides\"><wp:wrapPolygon edited=\"0\"><wp:start x=\"0\" y=\"0\"/><wp:lineTo x=\"0\" y=\"21600\"/><wp:lineTo x=\"21600\" y=\"21600\"/><wp:lineTo x=\"21600\" y=\"0\"/><wp:lineTo x=\"0\" y=\"0\"/></wp:wrapPolygon></wp:wrapThrough>',\n // ECMA-376 §20.4.2.15: wrapTopAndBottom — 텍스트가 이미지 위아래로만 흐름\n topAndBottom: \"<wp:wrapTopAndBottom/>\",\n none: \"<wp:wrapNone/>\",\n behind: \"<wp:wrapNone/>\",\n front: \"<wp:wrapNone/>\",\n};\n\nfunction encodeGrid(grid: GridNode, ctx: EncCtx, dims: PageDims = A4): string {\n const gp = grid.props;\n const look = gp.look;\n\n // tblLook attributes\n const firstRow = look?.firstRow ? \"1\" : \"0\";\n const lastRow = look?.lastRow ? \"1\" : \"0\";\n const firstCol = look?.firstCol ? \"1\" : \"0\";\n const lastCol = look?.lastCol ? \"1\" : \"0\";\n const noHBand = look?.bandedRows ? \"0\" : \"1\";\n const noVBand = look?.bandedCols ? \"0\" : \"1\";\n\n const d = dims ?? A4;\n const availDxa = Metric.ptToDxa(d.wPt - d.ml - d.mr);\n\n // 1단계: 표의 가상 2D 맵핑 (Virtual Table Map) 생성\n // 'real': 데이터 셀, 'continue': 세로 병합 지속 셀, 'absorbed': 가로/세로 병합으로 흡수된 자리, 'void': 빈 공간\n interface CellMap {\n type: \"real\" | \"continue\" | \"absorbed\" | \"void\";\n cell?: any;\n width?: number;\n }\n const tableMap: CellMap[][] = Array.from(\n { length: grid.kids.length },\n () => [],\n );\n\n for (let ri = 0; ri < grid.kids.length; ri++) {\n let c = 0;\n for (const cell of grid.kids[ri].kids) {\n // 이미 이전 행의 rowspan이나 현재 행의 colspan으로 차지된 자리 건너뜀\n while (tableMap[ri][c]) c++;\n\n // 실제 데이터 셀 배치\n tableMap[ri][c] = { type: \"real\", cell, width: cell.cs };\n\n // 병합 영역(colspan, rowspan) 예약 처리\n for (let rr = 0; rr < cell.rs; rr++) {\n const targetRi = ri + rr;\n if (targetRi >= grid.kids.length) break;\n if (!tableMap[targetRi]) tableMap[targetRi] = [];\n\n for (let cc = 0; cc < cell.cs; cc++) {\n if (rr === 0 && cc === 0) continue; // 시작 셀은 이미 'real'로 처리됨\n\n if (rr > 0 && cc === 0) {\n // 세로 병합이 시작된 이후 행의 첫 번째 칸\n tableMap[targetRi][c + cc] = { type: \"continue\", width: cell.cs };\n } else {\n // 가로 병합으로 흡수된 칸 또는 세로 병합 중 가로 병합된 칸\n tableMap[targetRi][c + cc] = { type: \"absorbed\" };\n }\n }\n }\n c += cell.cs;\n }\n }\n\n // 정확한 전체 열 개수(colCount) 계산 (모든 행 중 최대 길이)\n let colCount = 0;\n for (let ri = 0; ri < grid.kids.length; ri++) {\n colCount = Math.max(colCount, tableMap[ri].length);\n }\n if (colCount === 0) colCount = 1;\n\n // 빈 공간(void) 채우기 및 colCount에 맞춰 배열 길이 정규화\n for (let ri = 0; ri < grid.kids.length; ri++) {\n for (let c = 0; c < colCount; c++) {\n if (!tableMap[ri][c]) tableMap[ri][c] = { type: \"void\" };\n }\n }\n\n // 2단계: 컬럼 너비(dxa) 계산\n const defaultColDxa = Math.round(availDxa / colCount);\n let colWidthsDxa: number[] = [];\n\n if (grid.props.colWidths && grid.props.colWidths.length > 0) {\n const srcPt = [...grid.props.colWidths];\n while (srcPt.length < colCount) srcPt.push(0);\n srcPt.length = colCount;\n\n const knownTotalPt = srcPt.filter((w) => w > 0).reduce((s, w) => s + w, 0);\n const zeroCount = srcPt.filter((w) => w <= 0).length;\n const availPt = Metric.dxaToPt(availDxa);\n\n const remainingPt = Math.max(0, availPt - knownTotalPt);\n const zeroFillPt = zeroCount > 0 ? remainingPt / zeroCount : 0;\n\n for (let i = 0; i < srcPt.length; i++) {\n if (srcPt[i] <= 0) {\n srcPt[i] = zeroFillPt > 0 ? zeroFillPt : availPt / colCount;\n }\n }\n\n colWidthsDxa = srcPt.map((w) => Math.round(Metric.ptToDxa(w)));\n const computedTotalDxa = colWidthsDxa.reduce((s, w) => s + w, 0);\n if (computedTotalDxa > availDxa) {\n const scale = availDxa / computedTotalDxa;\n colWidthsDxa = colWidthsDxa.map((w) => Math.round(w * scale));\n }\n } else {\n for (let c = 0; c < colCount; c++) colWidthsDxa.push(defaultColDxa);\n }\n\n const totalDxa = colWidthsDxa.reduce((s, w) => s + w, 0);\n const gridCols = colWidthsDxa.map((w) => `<w:gridCol w:w=\"${w}\"/>`).join(\"\");\n\n // 3단계: XML 렌더링\n const rows = tableMap\n .map((rowMap, ri) => {\n const cellXmls: string[] = [];\n\n for (let c = 0; c < colCount; c++) {\n const mapEntry = rowMap[c];\n\n // 가로 병합으로 흡수된 칸은 렌더링하지 않음 (앞선 칸의 gridSpan이 차지)\n if (mapEntry.type === \"absorbed\") continue;\n\n // 세로 병합 지속(continue), 실제 셀(real), 또는 빈 공간(void) 처리\n const isContinue = mapEntry.type === \"continue\";\n const isReal = mapEntry.type === \"real\";\n const isVoid = mapEntry.type === \"void\";\n\n if (isContinue || isReal || isVoid) {\n let cw = 0;\n const cellWidth = mapEntry.width || 1;\n\n // 너비 계산: 현재 칸부터 colspan(width) 만큼의 컬럼 너비 합산\n // colWidthsDxa 가 colCount 보다 작은 경우를 대비하여 safe 하게 처리\n const safeColWidths =\n colWidthsDxa.length >= colCount\n ? colWidthsDxa\n : [\n ...colWidthsDxa,\n ...Array(colCount - colWidthsDxa.length).fill(defaultColDxa),\n ];\n for (\n let sc = c;\n sc < c + cellWidth && sc < safeColWidths.length;\n sc++\n ) {\n cw += safeColWidths[sc];\n }\n if (cw <= 0) cw = defaultColDxa * cellWidth;\n\n const tcPrParts: string[] = [];\n tcPrParts.push(`<w:tcW w:w=\"${Math.round(cw)}\" w:type=\"dxa\"/>`);\n\n if (cellWidth > 1) {\n tcPrParts.push(`<w:gridSpan w:val=\"${cellWidth}\"/>`);\n }\n\n if (isContinue) {\n tcPrParts.push(`<w:vMerge/>`);\n }\n\n let cellContent = \"\";\n if (isReal) {\n const cell = mapEntry.cell!;\n const cp = cell.props;\n if (cell.rs > 1) tcPrParts.push(`<w:vMerge w:val=\"restart\"/>`);\n\n const borders = encodeCellBorders(cp);\n if (borders) tcPrParts.push(borders);\n if (cp.bg)\n tcPrParts.push(\n `<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${cp.bg}\"/>`,\n );\n if (cp.va) {\n const vaMap: Record<string, string> = {\n top: \"top\",\n mid: \"center\",\n bot: \"bottom\",\n };\n tcPrParts.push(`<w:vAlign w:val=\"${vaMap[cp.va] ?? \"top\"}\"/>`);\n }\n // Per-cell margin override (only when explicitly set)\n const cPadT =\n cp.padT != null ? Math.round(Metric.ptToDxa(cp.padT)) : null;\n const cPadB =\n cp.padB != null ? Math.round(Metric.ptToDxa(cp.padB)) : null;\n const cPadL =\n cp.padL != null ? Math.round(Metric.ptToDxa(cp.padL)) : null;\n const cPadR =\n cp.padR != null ? Math.round(Metric.ptToDxa(cp.padR)) : null;\n if (\n cPadT != null ||\n cPadB != null ||\n cPadL != null ||\n cPadR != null\n ) {\n const t = cPadT ?? 28;\n const b = cPadB ?? 28;\n const l = cPadL ?? 72;\n const r = cPadR ?? 72;\n tcPrParts.push(\n `<w:tcMar><w:top w:w=\"${t}\" w:type=\"dxa\"/><w:left w:w=\"${l}\" w:type=\"dxa\"/><w:bottom w:w=\"${b}\" w:type=\"dxa\"/><w:right w:w=\"${r}\" w:type=\"dxa\"/></w:tcMar>`,\n );\n }\n // Encode cell content: paragraphs and nested grids (중첩 표)\n // DOCX cells must end with <w:p>; nested <w:tbl> goes between paras\n const parts: string[] = [];\n for (const kid of cell.kids) {\n if (kid.tag === \"grid\") {\n parts.push(encodeGrid(kid, ctx)); // dims 제거 — 중첩 표는 부모 dims 불필요\n } else if (kid.tag === \"para\") {\n parts.push(encodeParaInner(kid, ctx));\n }\n }\n // DOCX 셀은 반드시 <w:p>로 끝나야 함\n const lastKid = cell.kids[cell.kids.length - 1];\n if (cell.kids.length === 0 || lastKid?.tag === \"grid\") {\n parts.push('<w:p><w:pPr><w:spacing w:after=\"0\"/></w:pPr></w:p>');\n }\n cellContent = parts.join(\"\");\n } else {\n // continue 거나 void 인 경우 빈 단락 추가\n cellContent = `<w:p><w:pPr/></w:p>`;\n }\n\n const tcPr = `<w:tcPr>${tcPrParts.join(\"\")}</w:tcPr>`;\n cellXmls.push(` <w:tc>${tcPr}${cellContent}</w:tc>`);\n }\n }\n\n const trPrParts: string[] = [];\n if (ri === 0 && (gp.headerRow || look?.firstRow)) {\n trPrParts.push(\"<w:tblHeader/>\");\n }\n // 원본 행 정보에서 높이 가져오기 (tableMap 과 grid.kids 는 같은 인덱스)\n const originalRow = grid.kids[ri];\n if (originalRow?.heightPt != null && originalRow.heightPt > 0) {\n const hDxa = Math.round(Metric.ptToDxa(originalRow.heightPt));\n trPrParts.push(`<w:trHeight w:val=\"${hDxa}\" w:hRule=\"atLeast\"/>`);\n }\n const trPr =\n trPrParts.length > 0 ? `<w:trPr>${trPrParts.join(\"\")}</w:trPr>` : \"\";\n\n return ` <w:tr>${trPr}\\n${cellXmls.join(\"\\n\")}\\n </w:tr>`;\n })\n .join(\"\\n\");\n\n // 4단계: 테두리 및 최종 테이블 XML 조립\n let tblBorders = \"\";\n const strokeKindMap: Record<string, string> = {\n solid: \"single\",\n dash: \"dash\",\n dot: \"dot\",\n double: \"double\",\n none: \"none\",\n dotDash: \"dotDash\",\n dotDotDash: \"dotDotDash\",\n triple: \"triple\",\n thinThickSmallGap: \"thinThickSmallGap\",\n thickThinSmallGap: \"thickThinSmallGap\",\n thinThickThinSmallGap: \"thinThickThinSmallGap\",\n };\n\n if (gp.defaultStroke) {\n const s = gp.defaultStroke;\n const val = strokeKindMap[s.kind] ?? \"single\";\n\n if (val === \"none\" || s.pt <= 0) {\n tblBorders =\n '<w:tblBorders><w:top w:val=\"none\"/><w:left w:val=\"none\"/><w:bottom w:val=\"none\"/><w:right w:val=\"none\"/><w:insideH w:val=\"none\"/><w:insideV w:val=\"none\"/></w:tblBorders>';\n } else {\n // DOCX sz는 1/8pt 단위. 최소 굵기 2(0.25pt) 보장\n const sz = Math.max(2, Math.round(s.pt * 8));\n // 색상 '#' 제거 및 빈 값일 경우 auto 처리\n const clr = s.color ? s.color.replace(\"#\", \"\") : \"auto\";\n const bdr = `w:val=\"${val}\" w:sz=\"${sz}\" w:space=\"0\" w:color=\"${clr}\"`;\n tblBorders = `<w:tblBorders><w:top ${bdr}/><w:left ${bdr}/><w:bottom ${bdr}/><w:right ${bdr}/><w:insideH ${bdr}/><w:insideV ${bdr}/></w:tblBorders>`;\n }\n }\n\n // ECMA-376 §17.4.58: tblJc — 표 가로 정렬 (start/center/end)\n const tblAlignMap: Record<string, string> = {\n left: \"start\",\n center: \"center\",\n right: \"end\",\n justify: \"start\",\n };\n const tblJc = gp.align\n ? `<w:jc w:val=\"${tblAlignMap[gp.align] ?? \"start\"}\"/>`\n : \"\";\n\n return ` <w:tbl>\n <w:tblPr><w:tblStyle w:val=\"TableGrid\"/><w:tblW w:w=\"${Math.round(totalDxa)}\" w:type=\"dxa\"/><w:tblLayout w:type=\"fixed\"/><w:tblLook w:val=\"04A0\" w:firstRow=\"${firstRow}\" w:lastRow=\"${lastRow}\" w:firstColumn=\"${firstCol}\" w:lastColumn=\"${lastCol}\" w:noHBand=\"${noHBand}\" w:noVBand=\"${noVBand}\"/>${tblBorders}${tblJc}<w:tblCellMar><w:top w:w=\"28\" w:type=\"dxa\"/><w:left w:w=\"72\" w:type=\"dxa\"/><w:bottom w:w=\"28\" w:type=\"dxa\"/><w:right w:w=\"72\" w:type=\"dxa\"/></w:tblCellMar></w:tblPr>\n <w:tblGrid>${gridCols}</w:tblGrid>\n${rows}\n </w:tbl>`;\n}\nfunction encodeCellBorders(cp: CellProps): string {\n if (!cp.top && !cp.bot && !cp.left && !cp.right) return \"\";\n const strokeKindMap: Record<string, string> = {\n solid: \"single\",\n dash: \"dash\",\n dot: \"dot\",\n double: \"double\",\n none: \"none\",\n dotDash: \"dotDash\",\n dotDotDash: \"dotDotDash\",\n triple: \"triple\",\n };\n\n const encode = (\n s?: { kind: string; pt: number; color: string },\n tag?: string,\n ) => {\n if (!s || !tag) return \"\";\n const val = strokeKindMap[s.kind] ?? \"single\";\n\n // 선이 없거나 굵기가 0 이하인 경우 확실하게 제거 처리\n if (val === \"none\" || s.pt <= 0) {\n return `<w:${tag} w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>`;\n }\n\n // 최소 굵기 sz=2 (0.25pt) 보장\n const sz = Math.max(2, Math.round(s.pt * 8));\n // 색상 '#' 제거 및 빈 값일 경우 auto 처리\n const clr = s.color ? s.color.replace(\"#\", \"\") : \"auto\";\n\n return `<w:${tag} w:val=\"${val}\" w:sz=\"${sz}\" w:space=\"0\" w:color=\"${clr}\"/>`;\n };\n\n return `<w:tcBorders>${encode(cp.top, \"top\")}${encode(cp.bot, \"bottom\")}${encode(cp.left, \"left\")}${encode(cp.right, \"right\")}</w:tcBorders>`;\n}\n\nfunction esc(s: string): string {\n if (!s) return \"\";\n // 1. 내부 처리용 플레이스홀더(__EXT_0__ 또는 __EXT_0_W144_H108__ 등) 제거\n s = s.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n\n // 2. 글자 깨짐을 유발하는 쓰레기값 및 BOM 기호 명시적 제거 (이 부분 추가!)\n s = s.replace(/湰灧/g, \"\");\n s = s.replace(/\\uFEFF/g, \"\");\n\n // 3. DOCX(XML 1.0)에서 허용하지 않는 보이지 않는 제어문자 모두 제거\n s = s.replace(/[^\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD]/g, \"\");\n\n return TextKit.escapeXml(s);\n}\n\nregistry.registerEncoder(new DocxEncoder());\n","import type { DocRoot, ParaNode, SpanNode, GridNode, ContentNode, ImgNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport type { Stroke } from '../../model/doc-props';\nimport type { EncoderOptions } from '../../contract/encoder';\nimport { succeed, fail } from '../../contract/result';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { registry } from '../../pipeline/registry';\nimport { BaseEncoder } from '../../core/BaseEncoder';\n\nexport class MdEncoder extends BaseEncoder {\n protected getFormat(): string { return 'md'; }\n\n async encode(doc: DocRoot, options?: EncoderOptions): Promise<Outcome<Uint8Array>> {\n const includeImages = options?.includeImages !== false; // default: true\n try {\n const warns: string[] = [];\n const parts: string[] = [];\n for (const sheet of doc.kids) {\n // Warn about header/footer loss\n if (sheet.headers && sheet.headers.default && sheet.headers.default.length > 0) warns.push('[SHIELD] MD: 머리글(header) 표현 불가 — 손실됨');\n if (sheet.footers && sheet.footers.default && sheet.footers.default.length > 0) warns.push('[SHIELD] MD: 바닥글(footer) 표현 불가 — 손실됨');\n\n for (const kid of sheet.kids) parts.push(encodeContent(kid, warns, includeImages));\n }\n return succeed(this.stringToBytes(parts.join('\\n\\n')), warns);\n } catch (e: any) {\n return fail(`MD encode error: ${e?.message ?? String(e)}`);\n }\n }\n}\n\nfunction encodeContent(node: ContentNode, warns: string[], includeImages: boolean): string {\n return node.tag === 'grid' ? encodeGrid(node, warns, includeImages) : encodePara(node, warns, includeImages);\n}\n\nfunction encodePara(para: ParaNode, warns: string[], includeImages: boolean): string {\n const text = para.kids.map(k => {\n if (k.tag === 'span') return encodeSpan(k, warns);\n if (k.tag === 'img') return encodeImage(k, includeImages);\n return '';\n }).join('');\n\n if (para.props.heading) return `${'#'.repeat(para.props.heading)} ${text}`;\n\n if (para.props.listOrd !== undefined) {\n const indent = ' '.repeat(para.props.listLv ?? 0);\n return `${indent}${para.props.listOrd ? '1.' : '-'} ${text}`;\n }\n\n // Alignment: use HTML fallback for non-left\n if (para.props.align && para.props.align !== 'left' && para.props.align !== 'justify') {\n return `<div align=\"${para.props.align}\">${text}</div>`;\n }\n\n return text;\n}\n\nfunction encodeSpan(span: SpanNode, warns: string[]): string {\n let hasPageNum = false;\n const textParts: string[] = [];\n for (const kid of span.kids) {\n if (kid.tag === 'txt') textParts.push(kid.content);\n else if (kid.tag === 'pagenum') {\n hasPageNum = true;\n warns.push('[SHIELD] MD: 페이지 번호 표현 불가 — 손실됨');\n }\n }\n\n let r = textParts.join('');\n if (hasPageNum && r === '') r = '[페이지 번호]';\n\n // Collect CSS styles for font/color/size/bg — use HTML span so fonts can be\n // loaded externally via the page's stylesheet or @font-face rules.\n const cssStyles: string[] = [];\n if (span.props.font) cssStyles.push(`font-family: ${span.props.font}`);\n if (span.props.pt) cssStyles.push(`font-size: ${span.props.pt}pt`);\n if (span.props.color) cssStyles.push(`color: #${span.props.color}`);\n if (span.props.bg) cssStyles.push(`background-color: #${span.props.bg}`);\n\n const hasHtmlStyle = cssStyles.length > 0;\n\n if (hasHtmlStyle) {\n // When style properties are present, use HTML for all formatting so that\n // markdown markers inside an HTML element don't break parsers.\n if (span.props.b) cssStyles.push('font-weight: bold');\n if (span.props.i) cssStyles.push('font-style: italic');\n if (span.props.s) cssStyles.push('text-decoration: line-through');\n if (span.props.u) {\n // combine underline with possible line-through\n const existing = cssStyles.find(s => s.startsWith('text-decoration:'));\n if (existing) {\n const idx = cssStyles.indexOf(existing);\n cssStyles[idx] = existing.replace('line-through', 'underline line-through');\n if (!existing.includes('line-through')) cssStyles[idx] = existing + ' underline';\n } else {\n cssStyles.push('text-decoration: underline');\n }\n }\n const styleAttr = cssStyles.join('; ');\n if (span.props.sup) return `<sup style=\"${styleAttr}\">${r}</sup>`;\n if (span.props.sub) return `<sub style=\"${styleAttr}\">${r}</sub>`;\n return `<span style=\"${styleAttr}\">${r}</span>`;\n }\n\n // No CSS styles needed — use plain Markdown formatting\n if (span.props.b && span.props.i) r = `***${r}***`;\n else if (span.props.b) r = `**${r}**`;\n else if (span.props.i) r = `*${r}*`;\n if (span.props.s) r = `~~${r}~~`;\n if (span.props.u) r = `<u>${r}</u>`;\n if (span.props.sup) r = `<sup>${r}</sup>`;\n if (span.props.sub) r = `<sub>${r}</sub>`;\n\n return r;\n}\n\nfunction encodeImage(img: ImgNode, includeImages: boolean): string {\n if (!includeImages) {\n return `![${img.alt ?? ''}]`; // alt text only, no data URI\n }\n return `![${img.alt ?? ''}](data:${img.mime};base64,${img.b64})`;\n}\n\n/** pt → CSS border shorthand (only if stroke is visible) */\nfunction strokeToCss(s?: Stroke): string | undefined {\n if (!s || s.kind === 'none' || s.pt <= 0) return undefined;\n const kindMap: Record<string, string> = { solid: 'solid', dash: 'dashed', dot: 'dotted', double: 'double', none: 'none' };\n const style = kindMap[s.kind] ?? 'solid';\n const px = Math.max(1, Math.round(s.pt * 96 / 72));\n const color = s.color.startsWith('#') ? s.color : `#${s.color}`;\n return `${px}px ${style} ${color}`;\n}\n\nfunction encodeGrid(grid: GridNode, warns: string[], includeImages: boolean): string {\n if (grid.kids.length === 0) return '';\n\n // HTML 테이블로 출력 — 테두리/배경색을 인라인 스타일로 유지\n const rowCount = grid.kids.length;\n\n // Build occupancy map for rowspan\n const occupancy: Set<number>[] = Array.from({ length: rowCount }, () => new Set());\n let colCount = 0;\n for (let ri = 0; ri < rowCount; ri++) {\n const row = grid.kids[ri];\n let ci = 0;\n for (const cell of row.kids) {\n while (occupancy[ri].has(ci)) ci++;\n if (cell.rs > 1) {\n for (let r = ri + 1; r < ri + cell.rs && r < rowCount; r++) {\n for (let c = ci; c < ci + cell.cs; c++) occupancy[r].add(c);\n }\n }\n ci += cell.cs;\n }\n while (occupancy[ri].has(ci)) ci++;\n if (ci > colCount) colCount = ci;\n }\n\n let rows = '';\n for (let ri = 0; ri < rowCount; ri++) {\n const row = grid.kids[ri];\n let cells = '';\n let colIdx = 0;\n\n for (const cell of row.kids) {\n while (occupancy[ri].has(colIdx)) colIdx++;\n\n const cs = cell.cs > 1 ? ` colspan=\"${cell.cs}\"` : '';\n const rs = cell.rs > 1 ? ` rowspan=\"${cell.rs}\"` : '';\n\n const styles: string[] = ['padding:4px 6px', 'vertical-align:top'];\n const top = strokeToCss(cell.props.top);\n const bot = strokeToCss(cell.props.bot);\n const left = strokeToCss(cell.props.left);\n const right = strokeToCss(cell.props.right);\n if (top) styles.push(`border-top:${top}`);\n if (bot) styles.push(`border-bottom:${bot}`);\n if (left) styles.push(`border-left:${left}`);\n if (right) styles.push(`border-right:${right}`);\n if (cell.props.bg) styles.push(`background-color:#${cell.props.bg}`);\n if (cell.props.va === 'mid') styles[1] = 'vertical-align:middle';\n else if (cell.props.va === 'bot') styles[1] = 'vertical-align:bottom';\n\n const tag = (grid.props.headerRow && ri === 0) || cell.props.isHeader ? 'th' : 'td';\n const content = cell.kids.map(p => p.tag === 'para' ? encodePara(p, warns, includeImages) : encodeGrid(p, warns, includeImages)).join('\\n');\n cells += `<${tag}${cs}${rs} style=\"${styles.join(';')}\">${content}</${tag}>`;\n colIdx += cell.cs;\n }\n rows += `<tr>${cells}</tr>\\n`;\n }\n\n return `<table style=\"border-collapse:collapse;width:100%\">\\n<tbody>\\n${rows}</tbody>\\n</table>\\n`;\n}\n\nregistry.registerEncoder(new MdEncoder());\n","import type { DocRoot, ParaNode, SpanNode, GridNode, ContentNode, ImgNode, LinkNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport { succeed, fail } from '../../contract/result';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { registry } from '../../pipeline/registry';\nimport { BaseEncoder } from '../../core/BaseEncoder';\n\nexport class HtmlEncoder extends BaseEncoder {\n protected getFormat(): string { return 'html'; }\n\n async encode(doc: DocRoot): Promise<Outcome<Uint8Array>> {\n try {\n const warns: string[] = [];\n const bodyParts: string[] = [];\n\n for (const sheet of doc.kids) {\n // Header/footer as comments\n if (sheet.headers?.default && sheet.headers.default.length > 0) {\n const hText = sheet.headers.default.map((p: ParaNode) => encodePara(p, warns)).join('');\n bodyParts.push(`<div class=\"hwp-header\">${hText}</div>`);\n }\n\n for (const kid of sheet.kids) {\n bodyParts.push(encodeContent(kid, warns));\n }\n\n if (sheet.footers?.default && sheet.footers.default.length > 0) {\n const fText = sheet.footers.default.map((p: ParaNode) => encodePara(p, warns)).join('');\n bodyParts.push(`<div class=\"hwp-footer\">${fText}</div>`);\n }\n }\n\n const title = this.escapeXml(doc.meta?.title ?? '');\n const html = `<!DOCTYPE html>\\n<html lang=\"ko\">\\n<head>\\n<meta charset=\"UTF-8\">\\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\\n<title>${title}</title>\\n<style>\\n${BASE_CSS}\\n</style>\\n</head>\\n<body>\\n<div class=\"hwp-doc\">\\n${bodyParts.join('\\n')}\\n</div>\\n</body>\\n</html>`;\n\n return succeed(this.stringToBytes(html), warns);\n } catch (e: any) {\n return fail(`HTML encode error: ${e?.message ?? String(e)}`);\n }\n }\n}\n\nconst BASE_CSS = `\nbody { margin: 0; padding: 0; background: #f0f0f0; }\n.hwp-doc { max-width: 800px; margin: 0 auto; background: #fff; padding: 40px 60px; box-shadow: 0 0 8px rgba(0,0,0,0.15); }\n.hwp-header, .hwp-footer { color: #666; font-size: 0.9em; border-bottom: 1px solid #ddd; margin-bottom: 8px; padding-bottom: 4px; }\n.hwp-footer { border-top: 1px solid #ddd; border-bottom: none; margin-top: 8px; padding-top: 4px; }\np { margin: 0; padding: 0; line-height: 1; }\ntable { border-collapse: collapse; width: 100%; margin: 8px 0; }\ntd, th { border: 1px solid #ccc; padding: 4px 8px; vertical-align: top; }\nimg { max-width: 100%; height: auto; }\n`.trim();\n\nfunction encodeContent(node: ContentNode, warns: string[]): string {\n return node.tag === 'grid' ? encodeGrid(node, warns) : encodePara(node, warns);\n}\n\nfunction encodePara(para: ParaNode, warns: string[]): string {\n const kids = para.kids.map((k): string => {\n if (k.tag === 'span') return encodeSpan(k, warns);\n if (k.tag === 'img') return encodeImage(k);\n if (k.tag === 'link') {\n const link = k as LinkNode;\n const inner = link.kids.map(s => encodeSpan(s, warns)).join('');\n return `<a href=\"${TextKit.escapeXml(link.href)}\">${inner}</a>`;\n }\n return '';\n }).join('');\n\n // Heading\n if (para.props.heading) {\n const tag = `h${para.props.heading}`;\n return `<${tag}>${kids}</${tag}>\\n`;\n }\n\n // List\n if (para.props.listOrd !== undefined) {\n const indent = (para.props.listLv ?? 0) * 20;\n const style = indent > 0 ? ` style=\"margin-left:${indent}px\"` : '';\n const marker = para.props.listOrd ? `<span class=\"list-marker\">1. </span>` : `<span class=\"list-marker\">• </span>`;\n return `<p${style}>${marker}${kids}</p>\\n`;\n }\n\n // Alignment\n const align = para.props.align;\n const styleAttrs: string[] = [];\n if (align && align !== 'left') styleAttrs.push(`text-align:${align}`);\n if (para.props.indentPt) styleAttrs.push(`margin-left:${para.props.indentPt.toFixed(1)}pt`);\n if (para.props.spaceBefore) styleAttrs.push(`margin-top:${para.props.spaceBefore.toFixed(1)}pt`);\n if (para.props.spaceAfter) styleAttrs.push(`margin-bottom:${para.props.spaceAfter.toFixed(1)}pt`);\n if (para.props.lineHeight) styleAttrs.push(`line-height:${para.props.lineHeight}`);\n\n const styleAttr = styleAttrs.length > 0 ? ` style=\"${styleAttrs.join(';')}\"` : '';\n return `<p${styleAttr}>${kids || '&nbsp;'}</p>\\n`;\n}\n\nfunction encodeSpan(span: SpanNode, warns: string[]): string {\n const parts: string[] = [];\n let hasPageNum = false;\n\n for (const kid of span.kids) {\n if (kid.tag === 'txt') {\n // __EXT_N__ 또는 __EXT_N_W<w>_H<h>__ 자리표시자 제거\n const content = kid.content.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, '');\n if (content) parts.push(TextKit.escapeXml(content));\n } else if (kid.tag === 'br') {\n parts.push('<br>');\n } else if (kid.tag === 'pb') {\n parts.push('<div style=\"page-break-after:always\"></div>');\n } else if (kid.tag === 'pagenum') {\n hasPageNum = true;\n warns.push('[SHIELD] HTML: 페이지 번호 — 정적 값으로 대체됨');\n parts.push('<span class=\"page-num\">[페이지]</span>');\n }\n }\n\n let text = parts.join('');\n if (hasPageNum && text.trim() === '<span class=\"page-num\">[페이지]</span>') {\n // keep as-is\n }\n\n const p = span.props;\n const css: string[] = [];\n if (p.font) css.push(`font-family:${TextKit.escapeXml(p.font)}`);\n if (p.pt) css.push(`font-size:${p.pt}pt`);\n if (p.color) css.push(`color:#${p.color}`);\n if (p.bg) css.push(`background-color:#${p.bg}`);\n if (p.b) css.push('font-weight:bold');\n if (p.i) css.push('font-style:italic');\n\n const decorations: string[] = [];\n if (p.u) decorations.push('underline');\n if (p.s) decorations.push('line-through');\n if (decorations.length > 0) css.push(`text-decoration:${decorations.join(' ')}`);\n\n if (p.sup) return `<sup${css.length ? ` style=\"${css.join(';')}\"` : ''}>${text}</sup>`;\n if (p.sub) return `<sub${css.length ? ` style=\"${css.join(';')}\"` : ''}>${text}</sub>`;\n if (css.length > 0) return `<span style=\"${css.join(';')}\">${text}</span>`;\n return text;\n}\n\nfunction encodeImage(img: ImgNode): string {\n const wStyle = img.w ? ` width=\"${Math.round(img.w / 72 * 96)}px\"` : '';\n const hStyle = img.h ? ` height=\"${Math.round(img.h / 72 * 96)}px\"` : '';\n const alt = TextKit.escapeXml(img.alt ?? '');\n return `<img src=\"data:${img.mime};base64,${img.b64}\" alt=\"${alt}\"${wStyle}${hStyle}>`;\n}\n\nfunction encodeGrid(grid: GridNode, warns: string[]): string {\n if (grid.kids.length === 0) return '';\n\n // Build occupancy map for rowspan\n const rowCount = grid.kids.length;\n const occupancy: Set<number>[] = Array.from({ length: rowCount }, () => new Set());\n let colCount = 0;\n for (let ri = 0; ri < rowCount; ri++) {\n const row = grid.kids[ri];\n let ci = 0;\n for (const cell of row.kids) {\n while (occupancy[ri].has(ci)) ci++;\n if (cell.rs > 1) {\n for (let r = ri + 1; r < ri + cell.rs && r < rowCount; r++) {\n for (let c = ci; c < ci + cell.cs; c++) occupancy[r].add(c);\n }\n }\n ci += cell.cs;\n }\n while (occupancy[ri].has(ci)) ci++;\n if (ci > colCount) colCount = ci;\n }\n\n let rows = '';\n for (let ri = 0; ri < rowCount; ri++) {\n const row = grid.kids[ri];\n let cells = '';\n let ci = 0;\n for (const cell of row.kids) {\n while (occupancy[ri].has(ci)) ci++;\n\n const isHeader = cell.props.isHeader || (grid.props.headerRow && ri === 0);\n const tag = isHeader ? 'th' : 'td';\n\n const cs = cell.cs > 1 ? ` colspan=\"${cell.cs}\"` : '';\n const rs = cell.rs > 1 ? ` rowspan=\"${cell.rs}\"` : '';\n\n const styleAttrs: string[] = [];\n if (cell.props.bg) styleAttrs.push(`background-color:#${cell.props.bg}`);\n const va = cell.props.va;\n if (va === 'mid') styleAttrs.push('vertical-align:middle');\n else if (va === 'bot') styleAttrs.push('vertical-align:bottom');\n const styleAttr = styleAttrs.length > 0 ? ` style=\"${styleAttrs.join(';')}\"` : '';\n\n const content = cell.kids.map(p => p.tag === 'para' ? encodePara(p, warns) : encodeGrid(p, warns)).join('');\n cells += `<${tag}${cs}${rs}${styleAttr}>${content}</${tag}>`;\n ci += cell.cs;\n }\n rows += `<tr>${cells}</tr>\\n`;\n }\n\n return `<table>\\n<tbody>\\n${rows}</tbody>\\n</table>\\n`;\n}\n\nregistry.registerEncoder(new HtmlEncoder());\n","/**\n * HwpEncoder — DocRoot → HWP 5.0 바이너리 (OLE2/CFB 컨테이너)\n *\n * ANYTOHWP에서 영감받은 개선 사항:\n * 1. HwpStyleBank — 7개 언어 그룹 독립 폰트 레지스트리 (HANGUL/LATIN/HANJA/…)\n * 2. readPixelDims — PNG/JPEG 바이너리 헤더에서 픽셀 치수 추출 → 정확한 HWPUNIT 변환\n * 3. mkIdMappings — 언어별 폰트 카운트를 개별 기록\n * 4. mkCharShape — 언어별 faceId[7] 사용\n *\n * OLE2 레이아웃:\n * FileHeader (stream) — 256-byte HWP 시그니처 + 플래그\n * DocInfo (stream) — zlib 압축된 FACE_NAME / CHAR_SHAPE / PARA_SHAPE 레코드\n * BodyText (storage)\n * Section0 (stream) — zlib 압축된 PAGE_DEF + 문단/표 레코드\n */\n\nimport type {\n DocRoot,\n ContentNode,\n ParaNode,\n SpanNode,\n GridNode,\n ImgNode,\n LinkNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport type {\n TextProps,\n ParaProps,\n Stroke,\n PageDims,\n Align,\n} from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport { Metric, safeFontToKr } from \"../../safety/StyleBridge\";\nimport { registry } from \"../../pipeline/registry\";\nimport { A4 } from \"../../model/doc-props\";\nimport pako from \"pako\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { BaseEncoder } from \"../../core/BaseEncoder\";\n\n// ─── HWP 5.0 태그 ID ────────────────────────────────────────\nconst T = 16; // HWPTAG_BEGIN\n\n// DocInfo 태그\nconst TAG_DOCUMENT_PROPERTIES = T + 0; // 16\nconst TAG_ID_MAPPINGS = T + 1; // 17\nconst TAG_BIN_DATA = T + 2; // 18\nconst TAG_FACE_NAME = T + 3; // 19\nconst TAG_BORDER_FILL = T + 4; // 20\nconst TAG_CHAR_SHAPE = T + 5; // 21\nconst TAG_PARA_SHAPE = T + 9; // 25\nconst TAG_STYLE = T + 10; // 26\n\n// BodyText 태그\nconst TAG_PARA_HEADER = T + 50; // 66\nconst TAG_PARA_TEXT = T + 51; // 67\nconst TAG_PARA_CHAR_SHAPE = T + 52; // 68\nconst TAG_PARA_LINE_SEG = T + 53; // 69\nconst TAG_CTRL_HEADER = T + 55; // 71\nconst TAG_LIST_HEADER = T + 56; // 72\nconst TAG_PAGE_DEF = T + 57; // 73\nconst TAG_FOOTNOTE_SHAPE = T + 58; // 74\nconst TAG_TABLE = T + 61; // 77\nconst TAG_SHAPE_COMPONENT_PICTURE = T + 69; // 85\n\n// Control ID (LE UINT32)\nconst CTRL_TABLE = 0x74626c20; // 'tbl '\nconst CTRL_SECD = 0x73656364; // 'secd'\nconst CTRL_PIC = 0x24706963; // '$pic'\nconst CTRL_FIELD_BEGIN = 0x646c6625; // '%fld'\nconst CTRL_FIELD_END = 0x646c665c; // '\\fld'\n\n/** 테두리선 굵기 인덱스 테이블 (pt) */\nconst BORDER_W_PT = [\n 0.28, 0.34, 0.43, 0.57, 0.71, 0.85, 1.13, 1.42, 1.7, 1.98, 2.84, 4.25, 5.67,\n 8.5, 11.34, 14.17,\n];\n\nconst BORDER_KIND_IDX: Record<string, number> = {\n solid: 0,\n dot: 1,\n dash: 2,\n double: 7,\n triple: 8,\n none: 0,\n};\n\nconst ALIGN_CODE: Record<string, number> = {\n justify: 0,\n left: 1,\n right: 2,\n center: 3,\n distribute: 4,\n};\n\n// ─── 바이너리 버퍼 라이터 ────────────────────────────────────\n\nclass BufWriter {\n private chunks: Uint8Array[] = [];\n private _sz = 0;\n get size() {\n return this._sz;\n }\n\n u8(v: number): this {\n this.chunks.push(new Uint8Array([v & 0xff]));\n this._sz++;\n return this;\n }\n u16(v: number): this {\n this.chunks.push(new Uint8Array([v & 0xff, (v >> 8) & 0xff]));\n this._sz += 2;\n return this;\n }\n u32(v: number): this {\n const b = new Uint8Array(4);\n b[0] = v & 0xff;\n b[1] = (v >>> 8) & 0xff;\n b[2] = (v >>> 16) & 0xff;\n b[3] = (v >>> 24) & 0xff;\n this.chunks.push(b);\n this._sz += 4;\n return this;\n }\n i32(v: number): this {\n return this.u32(v < 0 ? v + 0x100000000 : v);\n }\n i16(v: number): this {\n return this.u16(v < 0 ? v + 0x10000 : v);\n }\n bytes(d: Uint8Array): this {\n this.chunks.push(d);\n this._sz += d.length;\n return this;\n }\n zeros(n: number): this {\n this.chunks.push(new Uint8Array(n));\n this._sz += n;\n return this;\n }\n utf16(s: string): this {\n for (let i = 0; i < s.length; i++) this.u16(s.charCodeAt(i));\n return this;\n }\n colorRef(hex: string): this {\n const h = (hex || \"000000\").replace(\"#\", \"\").padStart(6, \"0\");\n return this.u8(parseInt(h.slice(0, 2), 16))\n .u8(parseInt(h.slice(2, 4), 16))\n .u8(parseInt(h.slice(4, 6), 16))\n .u8(0);\n }\n build(): Uint8Array {\n const out = new Uint8Array(this._sz);\n let off = 0;\n for (const c of this.chunks) {\n out.set(c, off);\n off += c.length;\n }\n return out;\n }\n}\n\n// ─── HWP 레코드 빌더 ─────────────────────────────────────────\n\nfunction mkRec(tag: number, level: number, data: Uint8Array): Uint8Array {\n const sz = data.length;\n const enc = Math.min(sz, 0xfff);\n const hdr = (enc << 20) | ((level & 0x3ff) << 10) | (tag & 0x3ff);\n const w = new BufWriter().u32(hdr);\n if (enc >= 0xfff) w.u32(sz);\n w.bytes(data);\n return w.build();\n}\n\n// ─── ANYTOHWP 영감: PNG/JPEG 바이너리 헤더에서 픽셀 치수 추출\nfunction readPixelDims(\n data: Uint8Array,\n mime: string,\n): { w: number; h: number } | null {\n try {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n if (mime.includes(\"png\")) {\n if (\n data.length >= 24 &&\n view.getUint32(0) === 0x89504e47 &&\n view.getUint32(4) === 0x0d0a1a0a\n ) {\n return { w: view.getUint32(16), h: view.getUint32(20) };\n }\n } else if (mime.includes(\"jpeg\") || mime.includes(\"jpg\")) {\n let off = 2;\n while (off < data.length - 4) {\n const marker = view.getUint16(off);\n off += 2;\n if (marker === 0xffc0 || marker === 0xffc2) {\n return { w: view.getUint16(off + 5), h: view.getUint16(off + 3) };\n }\n if ((marker & 0xff00) !== 0xff00) break;\n off += view.getUint16(off);\n }\n }\n } catch {\n /* 무시 */\n }\n return null;\n}\n\n// ─── ANYTOHWP 영감: HwpStyleBank — 7개 언어 그룹 독립 폰트 레지스트리\n// StyleCollector를 대체하는 새로운 스타일 수집기\n\nconst LANG_GROUPS = [\n \"HANGUL\",\n \"LATIN\",\n \"HANJA\",\n \"JAPANESE\",\n \"OTHER\",\n \"SYMBOL\",\n \"USER\",\n] as const;\ntype LangGroup = (typeof LANG_GROUPS)[number];\n\n/** 한글 폰트 여부 판별 */\nfunction isKoreanFont(face: string): boolean {\n return (\n /[\\uAC00-\\uD7A3\\u3131-\\u318E]/.test(face) ||\n [\"맑은\", \"나눔\", \"굴림\", \"돋움\", \"바탕\", \"함초롬\", \"한컴\", \"HY\"].some((k) =>\n face.includes(k),\n )\n );\n}\n\nclass HwpStyleBank {\n readonly DEF_STROKE: Stroke = { kind: \"solid\", pt: 0.5, color: \"000000\" };\n\n // 언어별 독립 폰트 목록 (ANYTOHWP langFontFaces)\n private langFonts = new Map<LangGroup, string[]>(\n LANG_GROUPS.map((g) => [g, []]),\n );\n private langFontIdx = new Map<LangGroup, Map<string, number>>(\n LANG_GROUPS.map((g) => [g, new Map()]),\n );\n\n // charShape, parShape, borderFill 레지스트리\n readonly csProps: TextProps[] = [{}];\n private csIdx = new Map<string, number>([[csKey({}), 0]]);\n\n readonly psProps: ParaProps[] = [{}];\n private psIdx = new Map<string, number>([[psKey({}), 0]]);\n\n readonly bfData: BfEntry[] = [];\n private bfIdx = new Map<string, number>();\n\n // charShape마다 언어별 fontId를 기록\n readonly csFontIds: number[][] = [[0, 0, 0, 0, 0, 0, 0]]; // id=0 → 모두 0\n\n constructor() {\n // 기본 폰트 등록 (ANYTOHWP: 함초롬바탕)\n for (const g of LANG_GROUPS) this._registerLangFont(g, \"함초롬바탕\");\n this.addBorderFill(this.DEF_STROKE); // bfId=1\n }\n\n private _registerLangFont(lang: LangGroup, face: string): number {\n const idx = this.langFontIdx.get(lang)!;\n if (idx.has(face)) return idx.get(face)!;\n const id = this.langFonts.get(lang)!.length;\n this.langFonts.get(lang)!.push(face);\n idx.set(face, id);\n return id;\n }\n\n /** 폰트 이름 → 언어별 7개 ID 반환 (ANYTOHWP 방식) */\n registerFontForLangs(rawFace: string): number[] {\n const face = safeFontToKr(rawFace) || \"함초롬바탕\";\n const isKor = isKoreanFont(face);\n const hangulFace = isKor ? face : \"함초롬바탕\";\n const latinFace = isKor ? \"함초롬바탕\" : face;\n\n const ids: number[] = [];\n for (const lang of LANG_GROUPS) {\n const f = lang === \"LATIN\" ? latinFace : hangulFace;\n ids.push(this._registerLangFont(lang, f));\n }\n return ids; // [hangulId, latinId, hanjaId, japaneseId, otherId, symbolId, userId]\n }\n\n /** 언어별 폰트 목록 반환 */\n getFontsForLang(lang: LangGroup): string[] {\n return [...(this.langFonts.get(lang) ?? [])];\n }\n\n /** 폰트 수 반환 (mkIdMappings용) */\n getFontCount(lang: LangGroup): number {\n return this.langFonts.get(lang)?.length ?? 0;\n }\n\n addCharShape(p: TextProps): number {\n const k = csKey(p);\n if (this.csIdx.has(k)) return this.csIdx.get(k)!;\n const id = this.csProps.length;\n const fIds = p.font\n ? this.registerFontForLangs(p.font)\n : [0, 0, 0, 0, 0, 0, 0];\n this.csProps.push(p);\n this.csFontIds.push(fIds);\n this.csIdx.set(k, id);\n return id;\n }\n\n addParaShape(p: ParaProps): number {\n const k = psKey(p);\n if (this.psIdx.has(k)) return this.psIdx.get(k)!;\n const id = this.psProps.length;\n this.psProps.push(p);\n this.psIdx.set(k, id);\n return id;\n }\n\n addBorderFill(s: Stroke, bg?: string): number {\n const k = bfKey(s, bg);\n if (this.bfIdx.has(k)) return this.bfIdx.get(k)!;\n const id = this.bfData.length + 1;\n this.bfData.push({ uniform: true, s, bg });\n this.bfIdx.set(k, id);\n return id;\n }\n\n addBorderFillPerSide(\n l: Stroke,\n r: Stroke,\n t: Stroke,\n b: Stroke,\n bg?: string,\n ): number {\n const k = bfPerSideKey(l, r, t, b, bg);\n if (this.bfIdx.has(k)) return this.bfIdx.get(k)!;\n const id = this.bfData.length + 1;\n this.bfData.push({ uniform: false, l, r, t, b, bg });\n this.bfIdx.set(k, id);\n return id;\n }\n}\n\n// ─── 키 함수 ────────────────────────────────────────────────\n\nfunction csKey(p: TextProps): string {\n return [\n p.font ?? \"\",\n p.pt ?? 10,\n p.b ? 1 : 0,\n p.i ? 1 : 0,\n p.u ? 1 : 0,\n p.s ? 1 : 0,\n p.sup ? 1 : 0,\n p.sub ? 1 : 0,\n p.color ?? \"000000\",\n ].join(\"|\");\n}\n\nfunction psKey(p: ParaProps): string {\n return [\n p.align ?? \"left\",\n p.indentPt ?? 0,\n p.firstLineIndentPt ?? 0,\n p.spaceBefore ?? 0,\n p.spaceAfter ?? 0,\n p.lineHeight ?? 1,\n ].join(\"|\");\n}\n\nfunction bfKey(s: Stroke, bg?: string): string {\n return `${s.kind}|${s.pt}|${s.color}|${bg ?? \"\"}`;\n}\n\nfunction bfPerSideKey(\n l: Stroke,\n r: Stroke,\n t: Stroke,\n b: Stroke,\n bg?: string,\n): string {\n return `${bfKey(l)}/${bfKey(r)}/${bfKey(t)}/${bfKey(b)}/${bg ?? \"\"}`;\n}\n\ntype BfEntry =\n | { uniform: true; s: Stroke; bg?: string }\n | { uniform: false; l: Stroke; r: Stroke; t: Stroke; b: Stroke; bg?: string };\n\n// ─── Pre-scan: 스타일 수집 ──────────────────────────────────\n\nfunction collectNode(node: ContentNode, bank: HwpStyleBank): void {\n if (node.tag === \"para\") {\n bank.addParaShape(node.props);\n for (const kid of node.kids) {\n if (kid.tag === \"span\") bank.addCharShape((kid as SpanNode).props);\n }\n } else if (node.tag === \"grid\") {\n if (node.props.defaultStroke) bank.addBorderFill(node.props.defaultStroke);\n for (const row of node.kids) {\n for (const cell of row.kids) {\n const defStroke = node.props.defaultStroke ?? bank.DEF_STROKE;\n const cp = cell.props;\n if (cp.top || cp.bot || cp.left || cp.right) {\n bank.addBorderFillPerSide(\n cp.left ?? defStroke,\n cp.right ?? defStroke,\n cp.top ?? defStroke,\n cp.bot ?? defStroke,\n cp.bg,\n );\n } else {\n bank.addBorderFill(defStroke, cp.bg);\n }\n for (const para of cell.kids) collectNode(para, bank);\n }\n }\n }\n}\n\n// ─── DocInfo 레코드 빌더 ─────────────────────────────────────\n\nfunction mkDocumentProperties(): Uint8Array {\n return new BufWriter()\n .u16(1)\n .u16(1)\n .u16(1)\n .u16(1)\n .u16(1)\n .u16(1)\n .u16(1) // 7× UINT16 카운터\n .u32(0)\n .u32(0)\n .u32(0) // 캐럿 위치\n .build(); // 26 bytes\n}\n\n/**\n * HWPTAG_ID_MAPPINGS (72 bytes = 18 × INT32)\n * [0]=binData, [1-7]=7개 언어별 글꼴 수 (ANYTOHWP 방식으로 언어별 독립),\n * [8]=테두리/배경, [9]=글자모양, [10]=탭, [11]=번호, [12]=글머리,\n * [13]=문단모양, [14]=스타일, [15-17]=메모/변경추적\n */\nfunction mkIdMappings(bank: HwpStyleBank, nBinData = 0): Uint8Array {\n const w = new BufWriter();\n w.u32(nBinData);\n // [1-7]: 언어별 폰트 수 (ANYTOHWP: langFontFaces별 크기)\n for (const lang of LANG_GROUPS) w.u32(bank.getFontCount(lang));\n w.u32(bank.bfData.length); // [8]\n w.u32(bank.csProps.length); // [9]\n w.u32(0); // [10] tabDef\n w.u32(0); // [11] numbering\n w.u32(0); // [12] bullet\n w.u32(bank.psProps.length); // [13]\n w.u32(1); // [14] style (바탕글 1개)\n w.u32(0); // [15]\n w.u32(0); // [16]\n w.u32(0); // [17]\n return w.build(); // 18 × 4 = 72 bytes\n}\n\nfunction mkStyle(\n name: string,\n engName: string,\n paraPrId: number,\n charPrId: number,\n): Uint8Array {\n return new BufWriter()\n .u16(name.length)\n .utf16(name)\n .u16(engName.length)\n .utf16(engName)\n .u16(paraPrId)\n .u16(charPrId)\n .u16(0)\n .u16(1042)\n .u16(0)\n .build();\n}\n\nfunction mkFaceName(name: string): Uint8Array {\n return new BufWriter()\n .u8(0)\n .u16(name.length)\n .utf16(name)\n .u8(0)\n .u16(0)\n .zeros(10)\n .u16(0)\n .build();\n}\n\nfunction borderWidthIdx(pt: number): number {\n let best = 0;\n for (let i = 0; i < BORDER_W_PT.length; i++) {\n if (Math.abs(BORDER_W_PT[i] - pt) < Math.abs(BORDER_W_PT[best] - pt))\n best = i;\n }\n return best;\n}\n\nfunction mkBorderFill(s: Stroke, bg?: string): Uint8Array {\n const w = new BufWriter();\n const t = BORDER_KIND_IDX[s.kind] ?? 0;\n const wi = borderWidthIdx(s.pt);\n const col = s.color || \"000000\";\n w.u16(0);\n for (let i = 0; i < 4; i++) w.u8(t);\n for (let i = 0; i < 4; i++) w.u8(wi);\n for (let i = 0; i < 4; i++) w.colorRef(col);\n w.u8(0).u8(0).colorRef(\"000000\");\n if (bg) {\n w.u32(1).colorRef(bg).colorRef(\"FFFFFF\").u32(0);\n } else {\n w.u32(0);\n }\n return w.build();\n}\n\nfunction mkBorderFillPerSide(\n l: Stroke,\n r: Stroke,\n t: Stroke,\n b: Stroke,\n bg?: string,\n): Uint8Array {\n const w = new BufWriter();\n w.u16(0);\n w.u8(BORDER_KIND_IDX[l.kind] ?? 0)\n .u8(BORDER_KIND_IDX[r.kind] ?? 0)\n .u8(BORDER_KIND_IDX[t.kind] ?? 0)\n .u8(BORDER_KIND_IDX[b.kind] ?? 0);\n w.u8(borderWidthIdx(l.pt))\n .u8(borderWidthIdx(r.pt))\n .u8(borderWidthIdx(t.pt))\n .u8(borderWidthIdx(b.pt));\n w.colorRef(l.color || \"000000\")\n .colorRef(r.color || \"000000\")\n .colorRef(t.color || \"000000\")\n .colorRef(b.color || \"000000\");\n w.u8(0).u8(0).colorRef(\"000000\");\n if (bg) {\n w.u32(1).colorRef(bg).colorRef(\"FFFFFF\").u32(0);\n } else {\n w.u32(0);\n }\n return w.build();\n}\n\n/**\n * HWPTAG_CHAR_SHAPE (74 bytes)\n * ANYTOHWP 개선: faceId[7]에 언어별 ID를 개별 기록\n */\nfunction mkCharShape(fontIds: number[], p: TextProps): Uint8Array {\n const height = Math.round((p.pt ?? 10) * 100);\n let attr = 0;\n if (p.i) attr |= 1 << 0;\n if (p.b) attr |= 1 << 1;\n if (p.u) attr |= 1 << 2;\n if (p.s) attr |= 1 << 18;\n if (p.sup) attr |= 1 << 16;\n if (p.sub) attr |= 2 << 16;\n\n const w = new BufWriter();\n // faceId[7]: 언어별 독립 ID (ANYTOHWP 핵심 개선)\n for (const id of fontIds) w.u16(id);\n for (let i = 0; i < 7; i++) w.u8(100); // ratio\n for (let i = 0; i < 7; i++) w.u8(0); // spacing\n for (let i = 0; i < 7; i++) w.u8(100); // relSize\n for (let i = 0; i < 7; i++) w.u8(0); // offset\n w.i32(height).u32(attr).u8(0).u8(0);\n w.colorRef(p.color ?? \"000000\");\n w.colorRef(\"000000\"); // underlineColor\n w.colorRef(p.bg ?? \"FFFFFF\"); // shadeColor\n w.colorRef(\"000000\"); // shadowColor\n w.u16(0); // borderFillId\n w.colorRef(\"000000\"); // strikeColor\n return w.build(); // 74 bytes\n}\n\nfunction mkParaShape(p: ParaProps): Uint8Array {\n const alignVal = ALIGN_CODE[p.align ?? \"left\"] ?? 1;\n const attr1 = (alignVal & 0x7) << 2;\n const lineSpacePct = p.lineHeight ? Math.round(p.lineHeight * 100) : 160;\n return new BufWriter()\n .u32(attr1)\n .i32(Metric.ptToHwp(p.indentPt ?? 0))\n .i32(Metric.ptToHwp(p.indentRightPt ?? 0))\n .i32(Metric.ptToHwp(p.firstLineIndentPt ?? 0))\n .i32(Metric.ptToHwp(p.spaceBefore ?? 0))\n .i32(Metric.ptToHwp(p.spaceAfter ?? 0))\n .i32(lineSpacePct)\n .u16(0)\n .u16(0)\n .u16(0)\n .i16(0)\n .i16(0)\n .i16(0)\n .i16(0)\n .u32(0)\n .u32(4)\n .u32(lineSpacePct)\n .build(); // 54 bytes\n}\n\nfunction mkBinData(id: number, ext: string): Uint8Array {\n return new BufWriter().u16(0x0002).u16(id).u16(ext.length).utf16(ext).build();\n}\n\ninterface BinImage {\n id: number;\n ext: string;\n data: Uint8Array;\n}\n\n/**\n * DocInfo 스트림 빌더\n * ANYTOHWP 개선: 언어별 폰트 목록을 순서대로 독립 기록\n */\nfunction buildDocInfoStream(\n bank: HwpStyleBank,\n images: BinImage[] = [],\n): Uint8Array {\n const chunks: Uint8Array[] = [];\n\n chunks.push(mkRec(TAG_DOCUMENT_PROPERTIES, 0, mkDocumentProperties()));\n chunks.push(mkRec(TAG_ID_MAPPINGS, 1, mkIdMappings(bank, images.length)));\n\n for (const img of images) {\n chunks.push(mkRec(TAG_BIN_DATA, 1, mkBinData(img.id, img.ext)));\n }\n\n // ANYTOHWP 방식: 언어 그룹별로 독립된 FACE_NAME 레코드 직렬화\n for (const lang of LANG_GROUPS) {\n for (const face of bank.getFontsForLang(lang)) {\n chunks.push(mkRec(TAG_FACE_NAME, 1, mkFaceName(face)));\n }\n }\n\n for (const entry of bank.bfData) {\n chunks.push(\n mkRec(\n TAG_BORDER_FILL,\n 1,\n entry.uniform\n ? mkBorderFill(entry.s, entry.bg)\n : mkBorderFillPerSide(entry.l, entry.r, entry.t, entry.b, entry.bg),\n ),\n );\n }\n\n // charShape — 언어별 fontId 배열 사용\n for (let i = 0; i < bank.csProps.length; i++) {\n chunks.push(\n mkRec(TAG_CHAR_SHAPE, 1, mkCharShape(bank.csFontIds[i], bank.csProps[i])),\n );\n }\n\n for (const p of bank.psProps) {\n chunks.push(mkRec(TAG_PARA_SHAPE, 1, mkParaShape(p)));\n }\n\n chunks.push(mkRec(TAG_STYLE, 1, mkStyle(\"바탕글\", \"Normal\", 0, 0)));\n\n return concatU8(chunks);\n}\n\n// ─── BodyText 레코드 빌더 ────────────────────────────────────\n\nfunction mkPageDef(dims: PageDims): Uint8Array {\n return new BufWriter()\n .u32(Metric.ptToHwp(dims.wPt))\n .u32(Metric.ptToHwp(dims.hPt))\n .u32(Metric.ptToHwp(dims.ml))\n .u32(Metric.ptToHwp(dims.mr))\n .u32(Metric.ptToHwp(dims.mt))\n .u32(Metric.ptToHwp(dims.mb))\n .zeros(12)\n .u32(dims.orient === \"landscape\" ? 1 : 0)\n .build(); // 40 bytes\n}\n\nfunction mkParaHeader(\n nchars: number,\n ctrlMask: number,\n psId: number,\n csCount: number,\n lineAlignCount = 0,\n instanceId = 0,\n): Uint8Array {\n return new BufWriter()\n .u32(nchars)\n .u32(ctrlMask)\n .u16(psId)\n .u8(0)\n .u8(0)\n .u16(csCount)\n .u16(0)\n .u16(lineAlignCount)\n .u32(instanceId)\n .u16(0)\n .build(); // 24 bytes\n}\n\nfunction mkParaText(text: string): Uint8Array {\n const w = new BufWriter();\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i);\n // 0x09(탭), 0x0A(줄바꿈), 0x03(필드시작), 0x04(필드종료) 등 허용\n w.u16(c);\n }\n w.u16(13); // 문단 종결자\n return w.build();\n}\n\nfunction mkParaCharShape(pairs: [pos: number, id: number][]): Uint8Array {\n const w = new BufWriter();\n for (const [pos, id] of pairs) w.u32(pos).u32(id);\n return w.build();\n}\n\n/**\n * 5가지 LineSpacing(줄 간격) 타입에 따른 height 계산 로직\n */\nfunction calcLineHeight(\n type: number,\n value: number,\n textHeight: number,\n): number {\n switch (type) {\n case 0:\n return Math.floor((textHeight * value) / 100);\n case 1:\n return value;\n case 2:\n return Math.max(textHeight, value);\n case 3:\n return textHeight + value;\n case 4:\n return Math.floor(textHeight * value);\n default:\n return Math.floor((textHeight * value) / 100);\n }\n}\n\n/**\n * LineSeg 36바이트 구조체 (HWP 5.0 공식 규격)\n */\nfunction mkLineSeg(\n textStartPos: number,\n vertPos: number,\n vertSize: number,\n textHeight: number,\n baseline: number,\n spacing: number,\n horzPos: number,\n horzSize: number,\n flags: number,\n): Uint8Array {\n return new BufWriter()\n .u32(textStartPos)\n .i32(vertPos)\n .i32(vertSize)\n .i32(textHeight)\n .i32(baseline)\n .i32(spacing)\n .i32(horzPos)\n .i32(horzSize)\n .u32(flags)\n .build(); // 36 bytes\n}\n\nfunction buildDefaultLineSeg(\n availWidthHwp: number,\n fontHwp: number,\n nchars: number,\n paraProps?: ParaProps,\n vertPos = 0,\n): Uint8Array {\n const ratio = paraProps?.lineHeight\n ? Math.round(paraProps.lineHeight * 100)\n : 160;\n const vertSize = calcLineHeight(0, ratio, fontHwp);\n const baseline = Math.round(fontHwp * 0.85);\n const spacing = vertSize - fontHwp;\n // flags: bit 0 (페이지 첫 줄), bit 1 (컬럼 첫 줄)\n const flags = 3;\n\n return mkLineSeg(\n 0,\n vertPos,\n vertSize,\n fontHwp,\n baseline,\n spacing,\n 0,\n availWidthHwp,\n flags,\n );\n}\n\nfunction mkSecdParaText(): Uint8Array {\n const lo = CTRL_SECD & 0xffff;\n const hi = (CTRL_SECD >>> 16) & 0xffff;\n return new BufWriter()\n .u16(0x0002)\n .u16(lo)\n .u16(hi)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0x0002)\n .u16(0x000d)\n .build();\n}\n\nfunction mkTableParaText(): Uint8Array {\n const lo = CTRL_TABLE & 0xffff;\n const hi = (CTRL_TABLE >>> 16) & 0xffff;\n return new BufWriter()\n .u16(0x000b)\n .u16(lo)\n .u16(hi)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0x000b)\n .u16(0x000d)\n .build();\n}\n\nfunction mkPicParaText(): Uint8Array {\n const lo = CTRL_PIC & 0xffff;\n const hi = (CTRL_PIC >>> 16) & 0xffff;\n return new BufWriter()\n .u16(0x000b)\n .u16(lo)\n .u16(hi)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0x000b)\n .u16(0x000d)\n .build();\n}\n\n// ─── 이미지 관련 레코드 (ANYTOHWP 영감: 픽셀 치수 우선 사용)\n\ninterface ImgLayout {\n wrap?: string;\n xPt?: number;\n yPt?: number;\n zOrder?: number;\n distL?: number;\n distR?: number;\n distT?: number;\n distB?: number;\n}\n\nfunction mkShapeComponentPicture(\n binDataId: number,\n wHwp: number,\n hHwp: number,\n): Uint8Array {\n const w = new BufWriter();\n w.u32(CTRL_PIC).zeros(15);\n w.u32(0).u32(0).u32(wHwp).u32(hHwp);\n w.u32(0).u32(0).u32(wHwp).u32(hHwp);\n w.zeros(36);\n w.u16(binDataId).u8(0).u8(0).u8(0).zeros(5);\n return w.build();\n}\n\nfunction mkObjectCtrl(\n ctrlId: number,\n wHwp: number,\n hHwp: number,\n instanceId: number,\n layout?: ImgLayout,\n): Uint8Array {\n let attr = 0x082a2210;\n if (layout?.wrap === \"inline\") attr |= 1 << 3;\n return new BufWriter()\n .u32(ctrlId)\n .u32(attr)\n .i32(layout?.yPt ? Metric.ptToHwp(layout.yPt) : 0)\n .i32(layout?.xPt ? Metric.ptToHwp(layout.xPt) : 0)\n .u32(wHwp)\n .u32(hHwp)\n .i32(layout?.zOrder ?? 0)\n .u16(layout?.distL ? Metric.ptToHwp(layout.distL) : 0)\n .u16(layout?.distR ? Metric.ptToHwp(layout.distR) : 0)\n .u16(layout?.distT ? Metric.ptToHwp(layout.distT) : 0)\n .u16(layout?.distB ? Metric.ptToHwp(layout.distB) : 0)\n .u32(instanceId)\n .i32(0)\n .u16(0)\n .build(); // 46 bytes\n}\n\nfunction mkFieldBeginCtrl(instanceId: number): Uint8Array {\n // 46-byte Object Control Header for Field\n return new BufWriter()\n .u32(CTRL_FIELD_BEGIN)\n .u32(0x00000002) // 필드 플래그\n .zeros(28) // xy/size 등 불필요 (필드는 비가시)\n .u32(instanceId)\n .zeros(6)\n .build();\n}\n\nfunction mkFieldEndCtrl(beginId: number): Uint8Array {\n return new BufWriter()\n .u32(CTRL_FIELD_END)\n .u32(0)\n .zeros(28)\n .u32(beginId)\n .zeros(6)\n .build();\n}\n\n/**\n * 이미지 단락 인코딩\n * ANYTOHWP 개선: PNG/JPEG 픽셀 치수에서 HWPUNIT 계산\n */\nfunction encodePicPara(\n imgNode: ImgNode,\n binDataId: number,\n bank: HwpStyleBank,\n lv: number,\n idGen: () => number,\n availWidthHwp: number,\n): Uint8Array[] {\n // ANYTOHWP 방식: 픽셀 치수 추출 시도 → 실패 시 pt 기반으로 폴백\n const rawData = TextKit.base64Decode(imgNode.b64);\n const pixDims = readPixelDims(rawData, imgNode.mime);\n\n let wHwp: number, hHwp: number;\n if (pixDims && pixDims.w > 0 && pixDims.h > 0) {\n wHwp = Metric.ptToHwp((pixDims.w * 72) / 96); // px → pt(96dpi) → hwpunit\n hHwp = Metric.ptToHwp((pixDims.h * 72) / 96);\n } else {\n wHwp = Metric.ptToHwp(imgNode.w);\n hHwp = Metric.ptToHwp(imgNode.h);\n }\n\n // 가용 너비 초과 방지\n if (wHwp > availWidthHwp) {\n hHwp = Math.round((hHwp * availWidthHwp) / wHwp);\n wHwp = availWidthHwp;\n }\n\n const CTRL_MASK = 1 << 11;\n const instanceId = idGen();\n const psId = bank.addParaShape({});\n\n return [\n mkRec(\n TAG_PARA_HEADER,\n lv,\n mkParaHeader(9, CTRL_MASK, psId, 1, 1, instanceId),\n ),\n mkRec(TAG_PARA_TEXT, lv + 1, mkPicParaText()),\n mkRec(TAG_PARA_CHAR_SHAPE, lv + 1, mkParaCharShape([[0, 0]])),\n mkRec(\n TAG_PARA_LINE_SEG,\n lv + 1,\n buildDefaultLineSeg(availWidthHwp, hHwp, 9),\n ),\n mkRec(\n TAG_CTRL_HEADER,\n lv + 1,\n mkObjectCtrl(CTRL_PIC, wHwp, hHwp, idGen(), imgNode.layout),\n ),\n mkRec(\n TAG_SHAPE_COMPONENT_PICTURE,\n lv + 2,\n mkShapeComponentPicture(binDataId, wHwp, hHwp),\n ),\n ];\n}\n\n// ─── 문단 인코딩 ─────────────────────────────────────────────\n\nfunction encodePara(\n para: ParaNode,\n bank: HwpStyleBank,\n lv: number,\n instanceId: number,\n availWidthHwp: number,\n mask = 0,\n vertPos = 0,\n): Uint8Array[] {\n let text = \"\";\n const csPairs: [number, number][] = [];\n let pos = 0;\n let fontHwp = 1000;\n const ctrlRecords: Uint8Array[] = [];\n\n for (const kid of para.kids) {\n if (\n kid.tag === \"span\" &&\n (kid as SpanNode).props.pt &&\n ((kid as SpanNode).props.pt as number) > 0\n ) {\n fontHwp = Metric.ptToHwp((kid as SpanNode).props.pt as number);\n break;\n }\n }\n\n // 내부적으로 사용되는 ID 생성기 (단락 내에서 로컬하게 사용)\n let localIdCounter = 10000;\n const localIdGen = () => localIdCounter++;\n\n function processKids(kids: any[]): void {\n for (const kid of kids) {\n if (kid.tag === \"span\") {\n const span = kid as SpanNode;\n const csId = bank.addCharShape(span.props);\n if (!csPairs.length || csPairs[csPairs.length - 1][1] !== csId) {\n csPairs.push([pos, csId]);\n }\n for (const t of span.kids) {\n if (t.tag === \"txt\") {\n text += t.content;\n pos += t.content.length;\n }\n }\n } else if (kid.tag === \"link\") {\n const link = kid as LinkNode;\n mask |= 1 << 11; // 하이퍼링크 마스크\n\n const fieldBeginId = localIdGen();\n // 1. 시작 제어 문자 (0x03)\n text += String.fromCharCode(3);\n pos += 1;\n ctrlRecords.push(\n mkRec(TAG_CTRL_HEADER, lv + 1, mkFieldBeginCtrl(fieldBeginId)),\n );\n\n // 2. 내용 처리\n processKids(link.kids);\n\n // 3. 종료 제어 문자 (0x04)\n text += String.fromCharCode(4);\n pos += 1;\n ctrlRecords.push(\n mkRec(TAG_CTRL_HEADER, lv + 1, mkFieldEndCtrl(fieldBeginId)),\n );\n }\n }\n }\n processKids(para.kids);\n if (!csPairs.length) csPairs.push([0, 0]);\n\n const psId = bank.addParaShape(para.props);\n const nchars = text.length + 1;\n\n return [\n mkRec(\n TAG_PARA_HEADER,\n lv,\n mkParaHeader(nchars, mask, psId, csPairs.length, 1, instanceId),\n ),\n mkRec(TAG_PARA_TEXT, lv + 1, mkParaText(text)),\n mkRec(TAG_PARA_CHAR_SHAPE, lv + 1, mkParaCharShape(csPairs)),\n mkRec(\n TAG_PARA_LINE_SEG,\n lv + 1,\n buildDefaultLineSeg(availWidthHwp, fontHwp, nchars, para.props, vertPos),\n ),\n ...ctrlRecords,\n ];\n}\n\n// ─── 표 인코딩 ───────────────────────────────────────────────\n\nfunction mkTableCtrl(\n wHwp: number,\n hHwp: number,\n instanceId: number,\n align: Align = \"left\",\n): Uint8Array {\n // 표 정렬 속성 플래그 (HWP 표 제어 문자)\n // offset 20-21: 속성 플래그 (align: left=0, center=1, right=2, justify=3)\n const alignFlags = { left: 0, center: 1, right: 2, justify: 3 }[align] ?? 0;\n return new BufWriter()\n .u32(CTRL_TABLE)\n .u32(0x082a2211)\n .i32(0)\n .i32(0)\n .u32(wHwp)\n .u32(hHwp)\n .i32(7)\n .u16(140)\n .u16(140)\n .u16(140)\n .u16(140)\n .u32(instanceId)\n .i32(alignFlags)\n .u16(0)\n .build(); // 46 bytes\n}\n\nfunction mkTableRecord(\n rowCnt: number,\n colCnt: number,\n rowHwp: number[],\n bfId: number,\n): Uint8Array {\n const w = new BufWriter();\n w.u32(0x04000006).u16(rowCnt).u16(colCnt).u16(0);\n w.u16(510).u16(510).u16(141).u16(141);\n for (const h of rowHwp) w.u16(Math.max(1, h & 0xffff));\n w.u16(bfId).u16(0);\n return w.build();\n}\n\nfunction mkCellListHeader(\n paraCount: number,\n row: number,\n col: number,\n rs: number,\n cs: number,\n wHwp: number,\n hHwp: number,\n bfId: number,\n padL = 141,\n padR = 141,\n padT = 141,\n padB = 141,\n): Uint8Array {\n return new BufWriter()\n .u16(paraCount)\n .u32(0)\n .u16(0)\n .u16(col)\n .u16(row)\n .u16(rs)\n .u16(cs)\n .u32(wHwp)\n .u32(hHwp)\n .u16(padL)\n .u16(padR)\n .u16(padT)\n .u16(padB)\n .u16(bfId)\n .zeros(13)\n .build(); // 47 bytes\n}\n\nconst DEFAULT_ROW_HEIGHT_PT = 14;\n\nfunction encodeGrid(\n grid: GridNode,\n bank: HwpStyleBank,\n lv: number,\n idGen: () => number,\n availWidthHwp: number,\n): Uint8Array[] {\n const records: Uint8Array[] = [];\n const rowCnt = grid.kids.length;\n const colCnt = Math.max(1, grid.kids[0]?.kids.length ?? 1);\n\n const cwPt = (grid.props as any).colWidths ?? [];\n const totalPt = cwPt.reduce((s: number, w: number) => s + w, 0) || 453;\n const defColPt = totalPt / colCnt;\n const defStroke = grid.props.defaultStroke ?? bank.DEF_STROKE;\n const defBfId = bank.addBorderFill(defStroke);\n\n const rowHwp = grid.kids.map((row: any) =>\n row.heightPt != null && row.heightPt > 0\n ? Metric.ptToHwp(row.heightPt)\n : Metric.ptToHwp(DEFAULT_ROW_HEIGHT_PT),\n );\n\n const tblWPt =\n cwPt.length > 0 ? cwPt.reduce((s: number, w: number) => s + w, 0) : totalPt;\n const tblHPt = grid.kids.reduce(\n (s: number, row: any) =>\n s +\n (row.heightPt != null && row.heightPt > 0\n ? row.heightPt\n : DEFAULT_ROW_HEIGHT_PT),\n 0,\n );\n const tblInstanceId = idGen();\n const tblAlign = grid.props.align ?? \"left\";\n\n records.push(\n mkRec(\n TAG_CTRL_HEADER,\n lv,\n mkTableCtrl(\n Metric.ptToHwp(tblWPt),\n Metric.ptToHwp(tblHPt),\n tblInstanceId,\n tblAlign,\n ),\n ),\n );\n records.push(\n mkRec(TAG_TABLE, lv + 1, mkTableRecord(rowCnt, colCnt, rowHwp, defBfId)),\n );\n\n for (let r = 0; r < grid.kids.length; r++) {\n for (let c = 0; c < grid.kids[r].kids.length; c++) {\n const cell = grid.kids[r].kids[c];\n const wHwp = Metric.ptToHwp(cwPt[c] ?? defColPt);\n const hHwp = rowHwp[r];\n const cp = cell.props;\n const hasPerSide = cp.top || cp.bot || cp.left || cp.right;\n const bfId = hasPerSide\n ? bank.addBorderFillPerSide(\n cp.left ?? defStroke,\n cp.right ?? defStroke,\n cp.top ?? defStroke,\n cp.bot ?? defStroke,\n cp.bg,\n )\n : bank.addBorderFill(defStroke, cp.bg);\n\n const paras =\n cell.kids.length > 0\n ? cell.kids\n : [{ tag: \"para\" as const, props: {}, kids: [] }];\n\n const padL = cp.padL !== undefined ? Metric.ptToHwp(cp.padL) : 510;\n const padR = cp.padR !== undefined ? Metric.ptToHwp(cp.padR) : 510;\n const padT = cp.padT !== undefined ? Metric.ptToHwp(cp.padT) : 141;\n const padB = cp.padB !== undefined ? Metric.ptToHwp(cp.padB) : 141;\n\n records.push(\n mkRec(\n TAG_LIST_HEADER,\n lv + 1,\n mkCellListHeader(\n paras.length,\n r,\n c,\n cell.rs,\n cell.cs,\n wHwp,\n hHwp,\n bfId,\n padL,\n padR,\n padT,\n padB,\n ),\n ),\n );\n\n const cellWidthHwp = Metric.ptToHwp(cwPt[c] ?? defColPt);\n for (const para of paras) {\n records.push(\n ...encodePara(para as ParaNode, bank, lv + 2, idGen(), cellWidthHwp),\n );\n }\n }\n }\n return records;\n}\n\nfunction mkSectionCtrl(): Uint8Array {\n return new BufWriter()\n .u32(CTRL_SECD)\n .u32(0)\n .u32(1134)\n .u16(0x4000)\n .u16(0x001f)\n .zeros(31)\n .build(); // 47 bytes\n}\n\nfunction buildSectionParagraph(\n dims: PageDims,\n instanceId: number,\n): Uint8Array[] {\n const SECD_CTRL_MASK = 1 << 2;\n const nchars = 9;\n const availWidthHwp = Math.max(\n 1000,\n Metric.ptToHwp(dims.wPt) -\n Metric.ptToHwp(dims.ml) -\n Metric.ptToHwp(dims.mr),\n );\n return [\n mkRec(\n TAG_PARA_HEADER,\n 0,\n mkParaHeader(nchars, SECD_CTRL_MASK, 0, 1, 1, instanceId),\n ),\n mkRec(TAG_PARA_TEXT, 1, mkSecdParaText()),\n mkRec(TAG_PARA_CHAR_SHAPE, 1, mkParaCharShape([[0, 0]])),\n mkRec(\n TAG_PARA_LINE_SEG,\n 1,\n buildDefaultLineSeg(availWidthHwp, 1000, nchars),\n ),\n mkRec(TAG_CTRL_HEADER, 1, mkSectionCtrl()),\n mkRec(TAG_PAGE_DEF, 2, mkPageDef(dims)),\n mkRec(TAG_FOOTNOTE_SHAPE, 2, new Uint8Array(28)),\n mkRec(TAG_FOOTNOTE_SHAPE, 2, new Uint8Array(28)),\n ];\n}\n\n// ─── BodyText 스트림 빌더 ─────────────────────────────────────\n\nfunction flatImgNodes(kids: any[]): any[] {\n const result: any[] = [];\n for (const kid of kids) {\n if (kid.tag === \"img\") result.push(kid);\n else if (kid.tag === \"link\" && Array.isArray(kid.kids))\n result.push(...flatImgNodes(kid.kids));\n }\n return result;\n}\n\nfunction b64Matches(binImg: BinImage, b64: string): boolean {\n const a = TextKit.base64Encode(binImg.data).replace(/\\s/g, \"\");\n const b = b64.replace(/\\s/g, \"\");\n return a === b;\n}\n\nfunction buildBodyTextStream(\n doc: DocRoot,\n bank: HwpStyleBank,\n images: BinImage[],\n): Uint8Array {\n const chunks: Uint8Array[] = [];\n const dims = doc.kids[0]?.dims ?? A4;\n let instanceIdCounter = 1;\n const idGen = () => instanceIdCounter++;\n const availWidthHwp = Math.max(\n 1000,\n Metric.ptToHwp(dims.wPt) -\n Metric.ptToHwp(dims.ml) -\n Metric.ptToHwp(dims.mr),\n );\n\n for (const r of buildSectionParagraph(dims, idGen())) chunks.push(r);\n\n const TABLE_CTRL_MASK = 1 << 11;\n let vertPos = 0; // 단락 간격 추적\n\n for (const sheet of doc.kids) {\n for (const node of sheet.kids) {\n if (node.tag === \"para\") {\n const para = node as ParaNode;\n\n const hasPageBreak = para.kids.some(\n (k) => k.tag === \"span\" && k.kids.some((c) => c.tag === \"pb\"),\n );\n let paraMask = hasPageBreak ? 1 << 2 : 0;\n\n // 코드 블록 감지 → 1×1 표로 감싸기\n const hasCourier = (kids: any[]): boolean =>\n kids.some(\n (k) =>\n (k.tag === \"span\" &&\n k.props.font?.toLowerCase().includes(\"courier\")) ||\n (k.tag === \"link\" && hasCourier(k.kids)),\n );\n const isCode =\n para.props.styleId?.toLowerCase().includes(\"code\") ||\n hasCourier(para.kids);\n\n if (isCode) {\n const gridNode: GridNode = {\n tag: \"grid\",\n props: {\n colWidths: [Metric.hwpToPt(availWidthHwp)],\n defaultStroke: { kind: \"solid\", pt: 0.5, color: \"aaaaaa\" },\n },\n kids: [\n {\n tag: \"row\",\n kids: [\n {\n tag: \"cell\",\n rs: 1,\n cs: 1,\n props: { bg: \"f4f4f4\" },\n kids: [para],\n },\n ],\n },\n ],\n };\n chunks.push(\n mkRec(\n TAG_PARA_HEADER,\n 0,\n mkParaHeader(9, TABLE_CTRL_MASK | paraMask, 0, 1, 1, idGen()),\n ),\n );\n chunks.push(mkRec(TAG_PARA_TEXT, 1, mkTableParaText()));\n chunks.push(mkRec(TAG_PARA_CHAR_SHAPE, 1, mkParaCharShape([[0, 0]])));\n chunks.push(\n mkRec(\n TAG_PARA_LINE_SEG,\n 1,\n buildDefaultLineSeg(availWidthHwp, 1000, 9, undefined, vertPos),\n ),\n );\n vertPos += Metric.ptToHwp(20); // 코드 블록 후 간격\n for (const r of encodeGrid(gridNode, bank, 1, idGen, availWidthHwp))\n chunks.push(r);\n continue;\n }\n\n const imgNodes = flatImgNodes(para.kids);\n if (imgNodes.length > 0) {\n for (const img of imgNodes) {\n const binImg = images.find((b) => b64Matches(b, img.b64));\n if (binImg) {\n for (const r of encodePicPara(\n img,\n binImg.id,\n bank,\n 0,\n idGen,\n availWidthHwp,\n )) {\n // 첫 레코드가 PARA_HEADER인 경우 페이지 브레이크 마스크 적용\n chunks.push(r);\n }\n vertPos += Metric.ptToHwp(img.h ?? 100); // 이미지 높이 추가\n }\n }\n const textKids = para.kids.filter(\n (k: any) => k.tag !== \"img\" && k.tag !== \"link\",\n );\n if (textKids.length > 0) {\n const textPara: ParaNode = {\n tag: \"para\",\n props: para.props,\n kids: textKids as any,\n };\n for (const r of encodePara(\n textPara,\n bank,\n 0,\n idGen(),\n availWidthHwp,\n paraMask,\n vertPos,\n )) {\n // PARA_HEADER 레코드(목록의 첫 번째)에 마스크 적용\n if (r[0] === (TAG_PARA_HEADER & 0xff)) {\n // 레코드 헤더 수정은 복잡하므로 encodePara 내부에서 처리하는 것이 안전하지만\n // 여기서는 간단히 구현하기 위해 encodePara의 인자로 mask를 넘기도록 구조를 변경하는 것이 좋습니다.\n }\n chunks.push(r);\n }\n // 단락 높이 계산 및 vertPos 업데이트 (이미지/텍스트 혼합)\n const fontHwp_img = (\n textKids.find(\n (k: any) => k.tag === \"span\" && k.props?.pt,\n ) as SpanNode\n )?.props.pt\n ? Metric.ptToHwp(\n (\n textKids.find(\n (k: any) => k.tag === \"span\" && k.props?.pt,\n ) as SpanNode\n ).props.pt as number,\n )\n : 1000;\n const lineSpacePct_img = Math.round((para.props.lineHeight ?? 1.6) * 100);\n vertPos += Math.round((fontHwp_img * lineSpacePct_img) / 100);\n }\n } else {\n for (const r of encodePara(\n para,\n bank,\n 0,\n idGen(),\n availWidthHwp,\n paraMask,\n vertPos,\n ))\n chunks.push(r);\n // 단락 높이 계산 및 vertPos 업데이트 (일반 단락)\n const fontHwp_para = (\n para.kids.find(\n (k: any) => k.tag === \"span\" && k.props?.pt,\n ) as SpanNode\n )?.props.pt\n ? Metric.ptToHwp(\n (\n para.kids.find(\n (k: any) => k.tag === \"span\" && k.props?.pt,\n ) as SpanNode\n ).props.pt as number,\n )\n : 1000;\n const lineSpacePct_para = para.props.lineHeight\n ? Math.round(para.props.lineHeight * 100)\n : 160;\n vertPos += Math.round((fontHwp_para * lineSpacePct_para) / 100);\n }\n } else if (node.tag === \"grid\") {\n chunks.push(\n mkRec(\n TAG_PARA_HEADER,\n 0,\n mkParaHeader(9, TABLE_CTRL_MASK, 0, 1, 1, idGen()),\n ),\n );\n chunks.push(mkRec(TAG_PARA_TEXT, 1, mkTableParaText()));\n chunks.push(mkRec(TAG_PARA_CHAR_SHAPE, 1, mkParaCharShape([[0, 0]])));\n chunks.push(\n mkRec(\n TAG_PARA_LINE_SEG,\n 1,\n buildDefaultLineSeg(availWidthHwp, 1000, 9, undefined, vertPos),\n ),\n );\n vertPos += Metric.ptToHwp(20); // 표 후 간격\n for (const r of encodeGrid(\n node as GridNode,\n bank,\n 1,\n idGen,\n availWidthHwp,\n ))\n chunks.push(r);\n }\n }\n }\n\n return concatU8(chunks);\n}\n\n// ─── HWP FileHeader ─────────────────────────────────────────\n/**\n * HWP 5.0 FileHeader 를 생성합니다.\n *\n * 구조:\n * 0-15: 시그니처 \"HWP Document File\" (16 바이트)\n * 16-31: reserved (16 바이트)\n * 32-35: version (4 바이트, Little-Endian) - 0x05000300 = 5.0.3.0\n * 36-39: flags (4 바이트, Little-Endian) - bit 0 = compressed, bit 1 = encrypted\n * 40-255: reserved (216 바이트)\n *\n * 총 256 바이트\n */\nfunction buildHwpFileHeader(): Uint8Array {\n const SIZE = 256;\n const buf = new Uint8Array(SIZE);\n const dv = new DataView(buf.buffer);\n\n // 0-15: 시그니처 \"HWP Document File\" (16 바이트)\n const sig = \"HWP Document File\";\n for (let i = 0; i < sig.length; i++) {\n buf[i] = sig.charCodeAt(i);\n }\n\n // 16-31: reserved (0 으로 초기화됨)\n\n // 32-35: version (4 바이트, Little-Endian) - 0x05000300 = 5.0.3.0\n dv.setUint32(32, 0x05000300, true);\n\n // 36-39: flags (4 바이트, Little-Endian)\n // bit 0 = 1: compressed (압축됨)\n // bit 1 = 0: not encrypted (암호화 안됨)\n dv.setUint32(36, 0x00000001, true);\n\n // 40-255: reserved (0 으로 초기화됨)\n\n // 검증\n if (buf.length !== SIZE) {\n throw new Error(`FileHeader 크기 오류: ${buf.length} (기대: ${SIZE})`);\n }\n if (new TextDecoder().decode(buf.subarray(0, sig.length)) !== sig) {\n throw new Error(\"FileHeader 시그니처 오류\");\n }\n if (dv.getUint32(32, true) !== 0x05000300) {\n throw new Error(\"FileHeader 버전 오류\");\n }\n\n return buf;\n}\n\n// ─── OLE2/CFB 컨테이너 빌더 ─────────────────────────────────\n\nfunction buildHwpOle2(\n fileHeaderData: Uint8Array,\n docInfoData: Uint8Array,\n section0Data: Uint8Array,\n binImages: BinImage[] = [],\n): Uint8Array {\n const SS = 512;\n const ENDOFCHAIN = 0xfffffffe;\n const FREESECT = 0xffffffff;\n const FATSECT = 0xfffffffd;\n\n // FileHeader 크기 검증\n if (fileHeaderData.length < 256) {\n throw new Error(\n `FileHeader 크기 부족: ${fileHeaderData.length} (최소 256)`,\n );\n }\n\n function padSector(d: Uint8Array): Uint8Array {\n const n = Math.ceil(Math.max(d.length, 1) / SS) * SS;\n if (d.length === n) return d;\n const out = new Uint8Array(n);\n out.set(d);\n return out;\n }\n\n const fhPad = padSector(fileHeaderData);\n const diPad = padSector(docInfoData);\n const s0Pad = padSector(section0Data);\n const imgPads = binImages.map((img) => padSector(img.data));\n\n const fhN = fhPad.length / SS;\n const diN = diPad.length / SS;\n const s0N = s0Pad.length / SS;\n const imgNs = imgPads.map((p) => p.length / SS);\n const totalImgN = imgNs.reduce((s, n) => s + n, 0);\n\n const numDirEntries = 5 + (binImages.length > 0 ? 1 + binImages.length : 0);\n const dirN = Math.max(2, Math.ceil(numDirEntries / 4));\n\n let fatN = 1;\n for (let iter = 0; iter < 10; iter++) {\n const total = fatN + dirN + fhN + diN + s0N + totalImgN;\n const needed = Math.ceil(total / 128);\n if (needed <= fatN) break;\n fatN = needed;\n }\n\n const dir1Sec = fatN;\n const fhSec = dir1Sec + dirN;\n const diSec = fhSec + fhN;\n const s0Sec = diSec + diN;\n\n const imgSecs: number[] = [];\n let curSec = s0Sec + s0N;\n for (const n of imgNs) {\n imgSecs.push(curSec);\n curSec += n;\n }\n const totalSec = curSec;\n\n const fatBuf = new Uint8Array(fatN * SS).fill(0xff);\n const setFat = (i: number, v: number) => {\n fatBuf[i * 4] = v & 0xff;\n fatBuf[i * 4 + 1] = (v >>> 8) & 0xff;\n fatBuf[i * 4 + 2] = (v >>> 16) & 0xff;\n fatBuf[i * 4 + 3] = (v >>> 24) & 0xff;\n };\n\n for (let i = 0; i < fatN; i++) setFat(i, FATSECT);\n for (let i = 0; i < dirN; i++)\n setFat(dir1Sec + i, i + 1 < dirN ? dir1Sec + i + 1 : ENDOFCHAIN);\n for (let i = 0; i < fhN; i++)\n setFat(fhSec + i, i + 1 < fhN ? fhSec + i + 1 : ENDOFCHAIN);\n for (let i = 0; i < diN; i++)\n setFat(diSec + i, i + 1 < diN ? diSec + i + 1 : ENDOFCHAIN);\n for (let i = 0; i < s0N; i++)\n setFat(s0Sec + i, i + 1 < s0N ? s0Sec + i + 1 : ENDOFCHAIN);\n for (let ii = 0; ii < imgNs.length; ii++) {\n const start = imgSecs[ii];\n const n = imgNs[ii];\n for (let i = 0; i < n; i++)\n setFat(start + i, i + 1 < n ? start + i + 1 : ENDOFCHAIN);\n }\n\n const dirBuf = new Uint8Array(dirN * SS);\n const dv = new DataView(dirBuf.buffer);\n\n function writeDirEntry(\n idx: number,\n name: string,\n type: number,\n left: number,\n right: number,\n child: number,\n startSec: number,\n size: number,\n ): void {\n const base = idx * 128;\n const nl = name.length;\n // OLE2: 이름은 UTF-16LE, (글자수+1)*2 바이트가 길이 필드에 기록됨\n for (let i = 0; i < nl; i++)\n dv.setUint16(base + i * 2, name.charCodeAt(i), true);\n dv.setUint16(base + 64, (nl + 1) * 2, true);\n dirBuf[base + 66] = type;\n dirBuf[base + 67] = 1; // DE_NODE\n dv.setInt32(base + 68, left, true);\n dv.setInt32(base + 72, right, true);\n dv.setInt32(base + 76, child, true);\n dv.setUint32(base + 116, startSec >>> 0, true);\n dv.setUint32(base + 120, size >>> 0, true);\n }\n\n // 초기값 -1 (NOSTREAM)\n for (let i = 0; i < dirN * 4; i++) {\n const base = i * 128;\n dv.setInt32(base + 68, -1, true);\n dv.setInt32(base + 72, -1, true);\n dv.setInt32(base + 76, -1, true);\n }\n\n /**\n * 트리 구조 설계:\n * 0: Root Entry (child -> 1)\n * 1: FileHeader (left -> -1, right -> 2)\n * 2: DocInfo (left -> -1, right -> 3)\n * 3: BodyText (left -> -1, right -> 5, child -> 4)\n * 4: Section0 (left -> -1, right -> -1)\n * 5: BinData (left -> -1, right -> -1, child -> 6...)\n */\n\n if (binImages.length > 0) {\n writeDirEntry(0, \"Root Entry\", 5, -1, -1, 1, ENDOFCHAIN, 0);\n writeDirEntry(1, \"FileHeader\", 2, -1, 2, -1, fhSec, fileHeaderData.length);\n writeDirEntry(2, \"DocInfo\", 2, -1, 3, -1, diSec, docInfoData.length);\n writeDirEntry(3, \"BodyText\", 1, -1, 5, 4, ENDOFCHAIN, 0);\n writeDirEntry(4, \"Section0\", 2, -1, -1, -1, s0Sec, section0Data.length);\n writeDirEntry(5, \"BinData\", 1, -1, -1, 6, ENDOFCHAIN, 0);\n for (let ii = 0; ii < binImages.length; ii++) {\n const img = binImages[ii];\n const streamName = `BIN${String(img.id).padStart(4, \"0\")}.${img.ext}`;\n const sibling = ii + 1 < binImages.length ? 7 + ii : -1;\n writeDirEntry(\n 6 + ii,\n streamName,\n 2,\n -1,\n sibling,\n -1,\n imgSecs[ii],\n img.data.length,\n );\n }\n } else {\n writeDirEntry(0, \"Root Entry\", 5, -1, -1, 1, ENDOFCHAIN, 0);\n writeDirEntry(1, \"FileHeader\", 2, -1, 2, -1, fhSec, fileHeaderData.length);\n writeDirEntry(2, \"DocInfo\", 2, -1, 3, -1, diSec, docInfoData.length);\n writeDirEntry(3, \"BodyText\", 1, -1, -1, 4, ENDOFCHAIN, 0);\n writeDirEntry(4, \"Section0\", 2, -1, -1, -1, s0Sec, section0Data.length);\n }\n\n // HWP Root Entry CLSID\n const HWP_CLSID = [\n 0x20, 0xe9, 0xe3, 0xc0, 0x46, 0x35, 0xcf, 0x11, 0x8d, 0x81, 0x00, 0xaa,\n 0x00, 0x38, 0x9b, 0x71,\n ];\n for (let i = 0; i < 16; i++) dirBuf[80 + i] = HWP_CLSID[i];\n\n const hdr = new Uint8Array(SS);\n const hdv = new DataView(hdr.buffer);\n\n // OLE2/CFB 헤더 구조:\n // 0-7: Magic number (D0 CF 11 E0 A1 B1 1A E1)\n // 8-23: CLSID (16 bytes)\n // 24-25: Minor version (0x003E = 62)\n // 26-27: Major version (0x0003 = 3)\n // 28-29: Byte order (0x00FE = Little-Endian)\n // 30-31: Sector size exponent (0x0009 = 2^9 = 512)\n // 32-33: Mini sector size exponent (0x0006 = 2^6 = 64)\n // 34-39: Reserved (6 bytes)\n // 40-43: Number of FAT sectors\n // 44-47: Directory start sector location\n // 48-51: Transaction signature number\n // 52-55: Mini stream cutoff size (0x1000 = 4096)\n // 56-59: Mini FAT start sector location\n // 60-63: Number of mini FAT sectors\n // 64-67: FAT start sector location\n // 68-71: Number of backup FAT sectors\n // 72-75: Backup FAT start sector location\n // 76-511: Sector bitmap (109 sectors worth)\n\n // Magic number\n const MAGIC = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];\n MAGIC.forEach((b, i) => {\n hdr[i] = b;\n });\n\n // CLSID is already set in dirBuf[0][80:96] for Root Entry\n\n // Version\n hdv.setUint16(24, 0x003e, true); // Minor version\n hdv.setUint16(26, 0x0003, true); // Major version\n\n // Byte order\n hdv.setUint16(28, 0x00fe, true); // Little-Endian\n\n // Sector size exponent (2^9 = 512)\n hdv.setUint16(30, 0x0009, true);\n\n // Mini sector size exponent (2^6 = 64)\n hdv.setUint16(32, 0x0006, true);\n\n // Reserved (34-39, 6 bytes) - already zero\n\n // Number of FAT sectors\n hdv.setUint32(40, fatN, true);\n\n // Directory start sector location\n hdv.setUint32(44, dir1Sec, true);\n\n // Transaction signature number\n hdv.setUint32(48, 0, true);\n\n // Mini stream cutoff size\n hdv.setUint32(52, 0x1000, true);\n\n // Mini FAT start sector location\n hdv.setUint32(56, ENDOFCHAIN, true);\n\n // Number of mini FAT sectors\n hdv.setUint32(60, 0, true);\n\n // FAT start sector location\n hdv.setUint32(64, ENDOFCHAIN, true);\n\n // Number of backup FAT sectors\n hdv.setUint32(68, 0, true);\n\n // Backup FAT start sector location\n hdv.setUint32(72, 0, true);\n\n // Sector bitmap (76-511)\n for (let i = 0; i < 109; i++) {\n hdv.setUint32(76 + i * 4, i < fatN ? i : FREESECT, true);\n }\n\n const out = new Uint8Array(SS + totalSec * SS);\n out.set(hdr, 0);\n for (let i = 0; i < fatN; i++)\n out.set(fatBuf.subarray(i * SS, (i + 1) * SS), SS + i * SS);\n for (let i = 0; i < dirN; i++)\n out.set(dirBuf.subarray(i * SS, (i + 1) * SS), SS + (dir1Sec + i) * SS);\n out.set(fhPad, SS + fhSec * SS);\n out.set(diPad, SS + diSec * SS);\n out.set(s0Pad, SS + s0Sec * SS);\n for (let ii = 0; ii < imgPads.length; ii++)\n out.set(imgPads[ii], SS + imgSecs[ii] * SS);\n return out;\n}\n\n// ─── 유틸리티 ────────────────────────────────────────────────\n\nfunction concatU8(arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((s, a) => s + a.length, 0);\n const out = new Uint8Array(total);\n let off = 0;\n for (const a of arrays) {\n out.set(a, off);\n off += a.length;\n }\n return out;\n}\n\n// ─── OLE2 검증 ──────────────────────────────────────────────\n\nfunction validateOle2Magic(hwp: Uint8Array): boolean {\n const OLE_MAGIC = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];\n return OLE_MAGIC.every((b, i) => hwp[i] === b);\n}\n\n// ─── Encoder 진입점 ──────────────────────────────────────────\n\nexport class HwpEncoder extends BaseEncoder {\n protected getFormat(): string {\n return \"hwp\";\n }\n protected getAliases(): string[] {\n return [\"application/vnd.hancom.hwp\"];\n }\n\n async encode(doc: DocRoot): Promise<Outcome<Uint8Array>> {\n try {\n // 패스 1: 스타일 수집 (HwpStyleBank — ANYTOHWP 방식 언어별 폰트)\n const bank = new HwpStyleBank();\n for (const sheet of doc.kids) {\n for (const node of sheet.kids) collectNode(node, bank);\n }\n\n // 이미지 수집 (ANYTOHWP 개선: 픽셀 치수는 encodePicPara에서 추출)\n const images: BinImage[] = [];\n const seenB64 = new Set<string>();\n let binIdCounter = 1;\n\n function registerImg(img: any): void {\n const key = img.b64.substring(0, 50);\n if (seenB64.has(key)) return;\n seenB64.add(key);\n const raw = TextKit.base64Decode(img.b64);\n const ext =\n img.mime === \"image/png\"\n ? \"png\"\n : img.mime === \"image/gif\"\n ? \"gif\"\n : img.mime === \"image/bmp\"\n ? \"bmp\"\n : \"jpg\";\n images.push({ id: binIdCounter++, ext, data: new Uint8Array(raw) });\n }\n\n function collectImages(node: any): void {\n if (node.tag === \"para\") {\n for (const img of flatImgNodes(node.kids)) registerImg(img);\n } else if (node.tag === \"grid\") {\n for (const row of node.kids)\n for (const cell of row.kids)\n for (const para of cell.kids) collectImages(para);\n }\n }\n for (const sheet of doc.kids) {\n for (const node of sheet.kids) collectImages(node);\n }\n\n // 패스 2: 스트림 빌드\n const docInfoRaw = buildDocInfoStream(bank, images);\n const bodyRaw = buildBodyTextStream(doc, bank, images);\n\n // HWP 5.0: Zlib 헤더 없는 Raw Deflate\n const docInfoCmp = pako.deflateRaw(docInfoRaw);\n const bodyCmp = pako.deflateRaw(bodyRaw);\n\n const fileHdr = buildHwpFileHeader();\n\n // FileHeader 검증\n if (fileHdr.length !== 256) {\n return fail(\n `HwpEncoder: FileHeader 크기 오류 - ${fileHdr.length} bytes (기대: 256 bytes)`,\n );\n }\n\n const hwp = buildHwpOle2(fileHdr, docInfoCmp, bodyCmp, images);\n\n if (!validateOle2Magic(hwp)) {\n return fail(\"HwpEncoder: OLE2 매직 바이트 오류\");\n }\n\n // HWP 파일 크기 검증 (최소 512 바이트 - OLE2 헤더 1 섹터)\n if (hwp.length < 512) {\n return fail(\n `HwpEncoder: HWP 파일 크기 부족 - ${hwp.length} bytes (최소 512 bytes)`,\n );\n }\n\n return succeed(hwp);\n } catch (e: any) {\n return fail(`HwpEncoder: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n}\n\nregistry.registerEncoder(new HwpEncoder());\n","import type { DocRoot } from '../model/doc-tree';\nimport type { Outcome } from '../contract/result';\nimport type { EncoderOptions } from '../contract/encoder';\nimport { succeed, fail } from '../contract/result';\nimport { registry } from './registry';\n\n// Side-effect imports: auto-register all decoders and encoders\nimport '../decoders/hwpx/HwpxDecoder';\nimport '../decoders/hwp/HwpScanner';\nimport '../decoders/docx/DocxDecoder';\nimport '../decoders/md/MdDecoder';\nimport '../decoders/html/HtmlDecoder';\nimport '../encoders/hwpx/HwpxEncoder';\nimport '../encoders/docx/DocxEncoder';\nimport '../encoders/md/MdEncoder';\nimport '../encoders/html/HtmlEncoder';\nimport '../encoders/hwp/HwpEncoder';\n\nexport class Pipeline {\n private constructor(private raw: Uint8Array, private srcFmt: string) {}\n\n /** 파일을 열고 포맷을 자동 감지하거나 명시 */\n static open(input: Uint8Array | string, fmt?: string): Pipeline {\n if (typeof input === 'string') {\n return new Pipeline(new TextEncoder().encode(input), fmt ?? 'md');\n }\n return new Pipeline(input, fmt ?? detectFormat(input));\n }\n\n /** File/Blob 비동기 입력 */\n static async openAsync(input: File | Blob | Uint8Array | string, fmt?: string): Promise<Pipeline> {\n if (input instanceof Uint8Array || typeof input === 'string') {\n return Pipeline.open(input, fmt);\n }\n const buf = await input.arrayBuffer();\n const data = new Uint8Array(buf);\n const detectedFmt = fmt ?? (input instanceof File ? getExt(input.name) : undefined) ?? detectFormat(data);\n return new Pipeline(data, detectedFmt);\n }\n\n /** 목표 포맷으로 변환 */\n async to(targetFmt: string, options?: EncoderOptions): Promise<Outcome<Uint8Array>> {\n const decoder = registry.getDecoder(this.srcFmt);\n const encoder = registry.getEncoder(targetFmt);\n\n if (!decoder) return fail(`지원하지 않는 입력 포맷: ${this.srcFmt}`);\n if (!encoder) return fail(`지원하지 않는 출력 포맷: ${targetFmt}`);\n\n const docResult = await decoder.decode(this.raw);\n if (!docResult.ok) return docResult;\n\n const encResult = await encoder.encode(docResult.data, options);\n if (!encResult.ok) return { ...encResult, warns: [...docResult.warns, ...encResult.warns] };\n\n return { ...encResult, warns: [...docResult.warns, ...encResult.warns] };\n }\n\n /** DocRoot만 추출 (인코딩 없이) */\n async inspect(): Promise<Outcome<DocRoot>> {\n const decoder = registry.getDecoder(this.srcFmt);\n if (!decoder) return fail(`디코더 없음: ${this.srcFmt}`);\n return decoder.decode(this.raw);\n }\n}\n\nfunction detectFormat(data: Uint8Array): string {\n // HWP 파일 (OLE Compound Document)\n if (data[0] === 0xD0 && data[1] === 0xCF && data[2] === 0x11 && data[3] === 0xE0) return 'hwp';\n\n // ZIP 기반 파일 (DOCX, HWPX)\n if (data[0] === 0x50 && data[1] === 0x4B) {\n // DOCX 는 [Content_Types].xml 에 application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml 이 있음\n // HWPX 는 application/ha-xml-core-document\n const str = new TextDecoder('utf-8', { fatal: false }).decode(data.slice(0, 4096));\n if (str.includes('wordprocessingml')) return 'docx';\n if (str.includes('ha-xml')) return 'hwpx';\n if (str.includes('hwpml/')) return 'hwpx';\n if (str.includes('word/')) return 'docx';\n return 'hwpx'; // 기본값\n }\n\n return 'md';\n}\n\nfunction getExt(name: string): string | undefined {\n const parts = name.split('.');\n return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : undefined;\n}\n","import type { AnyNode, DocRoot } from '../model/doc-tree';\n\nexport type WalkCallback = (node: AnyNode, parent: AnyNode | null, depth: number) => void | 'stop';\n\nexport function walkNode(\n node: AnyNode,\n cb: WalkCallback,\n parent: AnyNode | null = null,\n depth = 0,\n): boolean {\n const result = cb(node, parent, depth);\n if (result === 'stop') return false;\n\n if ('kids' in node && Array.isArray((node as any).kids)) {\n for (const kid of (node as any).kids) {\n if (!walkNode(kid as AnyNode, cb, node, depth + 1)) return false;\n }\n }\n return true;\n}\n\nexport class TreeWalker {\n walk(root: DocRoot, cb: WalkCallback): void {\n walkNode(root, cb);\n }\n\n findAll<T extends AnyNode>(root: DocRoot, predicate: (n: AnyNode) => n is T): T[] {\n const results: T[] = [];\n walkNode(root, (n) => { if (predicate(n)) results.push(n); });\n return results;\n }\n\n extractText(root: DocRoot): string {\n const parts: string[] = [];\n walkNode(root, (n) => {\n if (n.tag === 'txt') parts.push(n.content);\n if (n.tag === 'br') parts.push('\\n');\n if (n.tag === 'pb') parts.push('\\n\\n');\n });\n return parts.join('');\n }\n}\n","import type { DocRoot, GridNode } from '../model/doc-tree';\nimport { walkNode } from './TreeWalker';\n\nexport function countNodes(root: DocRoot): Record<string, number> {\n const counts: Record<string, number> = {};\n walkNode(root, (n) => { counts[n.tag] = (counts[n.tag] ?? 0) + 1; });\n return counts;\n}\n\nexport function validateRoot(root: DocRoot): string[] {\n const errors: string[] = [];\n if (root.tag !== 'root') errors.push('Root node must have tag \"root\"');\n if (!Array.isArray(root.kids)) errors.push('Root.kids must be an array');\n if (root.kids.length === 0) errors.push('Document has no sheets');\n\n walkNode(root, (n) => {\n if (n.tag === 'cell' && n.kids.length === 0) {\n errors.push('CellNode must have at least one ParaNode child');\n }\n if (n.tag === 'grid' && (n as GridNode).kids.length === 0) {\n errors.push('GridNode must have at least one RowNode');\n }\n });\n\n return errors;\n}\n"],"mappings":"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","names":["pako","import_pako","pako","i","r","data","coreXml","stylesXml","extractDims","decodeHeaderFooter","toArr","decodePara","decodeGrid","decodeGridSimple","decodeGridFlat","decodeGridText","cellText","tableText","end","t","paraKids","stylesXml","mimeToExt","registerImage","esc","encodeImage","encodeContent","encodeGrid","encodeImage","encodePara","encodeContent","encodeGrid","encodeSpan","encodeImage","import_pako","TAG_FACE_NAME","TAG_BORDER_FILL","TAG_CHAR_SHAPE","TAG_PARA_SHAPE","TAG_PARA_HEADER","TAG_PARA_TEXT","TAG_PARA_CHAR_SHAPE","TAG_CTRL_HEADER","TAG_LIST_HEADER","TAG_PAGE_DEF","CTRL_TABLE","BORDER_W_PT","readPixelDims","LANG_GROUPS","encodePara","encodeGrid","out","registerImg","collectImages","pako"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/contract/result.ts","../src/pipeline/registry.ts","../src/model/doc-props.ts","../src/model/builders.ts","../src/safety/ShieldedParser.ts","../src/safety/StyleBridge.ts","../src/toolkit/ArchiveKit.ts","../src/toolkit/XmlKit.ts","../src/toolkit/TextKit.ts","../src/core/BaseDecoder.ts","../src/encoders/hwpx/constants.ts","../src/decoders/hwpx/HwpxDecoder.ts","../src/toolkit/BinaryKit.ts","../src/decoders/hwp/HwpScanner.ts","../src/decoders/docx/DocxDecoder.ts","../src/decoders/md/MdDecoder.ts","../src/decoders/html/HtmlDecoder.ts","../src/core/BaseEncoder.ts","../src/encoders/hwpx/HwpxEncoder.ts","../src/encoders/docx/DocxEncoder.ts","../src/encoders/md/MdEncoder.ts","../src/encoders/html/HtmlEncoder.ts","../src/encoders/hwp/HwpEncoder.ts","../src/pipeline/Pipeline.ts","../src/walk/TreeWalker.ts","../src/walk/tree-ops.ts"],"sourcesContent":["// ─── 공개 API ───────────────────────────────────────────────\n\n// Pipeline\nexport { Pipeline } from './pipeline/Pipeline';\nexport { registry } from './pipeline/registry';\n\n// Side-effect imports: register all decoders/encoders\nimport './decoders/md/MdDecoder';\nimport './decoders/hwpx/HwpxDecoder';\nimport './decoders/docx/DocxDecoder';\nimport './decoders/hwp/HwpScanner';\nimport './encoders/md/MdEncoder';\nimport './encoders/html/HtmlEncoder';\nimport './encoders/hwpx/HwpxEncoder';\nimport './encoders/docx/DocxEncoder';\nimport './encoders/hwp/HwpEncoder';\n\n// Model\nexport type {\n DocRoot, SheetNode, ParaNode, SpanNode, GridNode, RowNode, CellNode,\n ImgNode, LinkNode, TxtNode, BrNode, PbNode, PageNumNode, ContentNode, AnyNode, BlockTag,\n} from './model/doc-tree';\nexport type {\n TextProps, ParaProps, CellProps, GridProps, TableLook, PageDims, DocMeta,\n Align, VAlign, Heading, StrokeKind, Stroke,\n} from './model/doc-props';\nexport { A4, A4_LANDSCAPE, DEFAULT_STROKE, normalizeDims } from './model/doc-props';\nexport { buildRoot, buildSheet, buildPara, buildSpan, buildImg, buildGrid, buildRow, buildCell, buildPageNum, buildBr, buildPb } from './model/builders';\n\n// Contract\nexport type { Decoder } from './contract/decoder';\nexport type { Encoder } from './contract/encoder';\nexport type { Outcome, Ok, Fail } from './contract/result';\nexport { succeed, fail } from './contract/result';\n\n// Safety\nexport { ShieldedParser } from './safety/ShieldedParser';\nexport { Metric, safeHex, safeAlign, safeFont, safeFontToKr, safeStrokeHwpx, safeStrokeDocx } from './safety/StyleBridge';\n\n// Walk\nexport { TreeWalker, walkNode } from './walk/TreeWalker';\nexport { countNodes, validateRoot } from './walk/tree-ops';\n\n// Toolkit\nexport { XmlKit } from './toolkit/XmlKit';\nexport { ArchiveKit } from './toolkit/ArchiveKit';\nexport { BinaryKit } from './toolkit/BinaryKit';\nexport { TextKit } from './toolkit/TextKit';\n","export type Outcome<T> = Ok<T> | Fail;\n\nexport interface Ok<T> {\n ok: true;\n data: T;\n warns: string[];\n}\n\nexport interface Fail {\n ok: false;\n error: string;\n warns: string[];\n}\n\nexport function succeed<T>(data: T, warns: string[] = []): Ok<T> {\n return { ok: true, data, warns };\n}\n\nexport function fail(error: string, warns: string[] = []): Fail {\n return { ok: false, error, warns };\n}\n","import type { Decoder } from '../contract/decoder';\nimport type { Encoder } from '../contract/encoder';\n\nclass FormatRegistry {\n private decoders = new Map<string, Decoder>();\n private encoders = new Map<string, Encoder>();\n\n registerDecoder(d: Decoder): void {\n this.decoders.set(d.format, d);\n if (d.aliases) {\n for (const alias of d.aliases) this.decoders.set(alias, d);\n }\n }\n\n registerEncoder(e: Encoder): void {\n this.encoders.set(e.format, e);\n if (e.aliases) {\n for (const alias of e.aliases) this.encoders.set(alias, e);\n }\n }\n\n getDecoder(fmt: string): Decoder | undefined { return this.decoders.get(fmt); }\n getEncoder(fmt: string): Encoder | undefined { return this.encoders.get(fmt); }\n\n supportedInputs(): string[] { return [...this.decoders.keys()]; }\n supportedOutputs(): string[] { return [...this.encoders.keys()]; }\n}\n\nexport const registry = new FormatRegistry();\n","export type Align = 'left' | 'center' | 'right' | 'justify' | 'distribute' | 'distribute_space';\n\n// ─── 이미지 배치 ────────────────────────────────────────────\nexport type ImgWrap = 'inline' | 'square' | 'tight' | 'through' | 'none' | 'behind' | 'front' | 'topAndBottom';\nexport type ImgHorzAlign = 'left' | 'center' | 'right';\nexport type ImgVertAlign = 'top' | 'center' | 'bottom';\nexport type ImgHorzRelTo = 'margin' | 'column' | 'page' | 'para';\nexport type ImgVertRelTo = 'margin' | 'line' | 'page' | 'para';\n\nexport interface ImgLayout {\n wrap: ImgWrap;\n horzAlign?: ImgHorzAlign; // 정렬 기준 (xPt 없을 때)\n vertAlign?: ImgVertAlign; // 정렬 기준 (yPt 없을 때)\n horzRelTo?: ImgHorzRelTo; // 가로 기준점\n vertRelTo?: ImgVertRelTo; // 세로 기준점\n xPt?: number; // 명시적 가로 오프셋 (pt)\n yPt?: number; // 명시적 세로 오프셋 (pt)\n distT?: number; // 텍스트와의 거리 top (pt)\n distB?: number;\n distL?: number;\n distR?: number;\n behindDoc?: boolean; // 텍스트 뒤에 배치\n zOrder?: number;\n}\nexport type VAlign = 'top' | 'mid' | 'bot';\nexport type Heading = 1 | 2 | 3 | 4 | 5 | 6;\nexport type StrokeKind = 'solid' | 'dash' | 'dot' | 'double' | 'none' | 'dashDot' | 'dashDotDot' | 'wave';\n\nexport interface TextProps {\n b?: boolean;\n i?: boolean;\n u?: boolean;\n s?: boolean;\n sup?: boolean;\n sub?: boolean;\n font?: string;\n pt?: number;\n color?: string;\n bg?: string;\n}export interface ParaProps {\n align?: Align;\n heading?: Heading;\n styleId?: string; // DOCX pStyle styleId (e.g. \"Heading1\", \"TOC1\")\n hwpStyleId?: number; // HWP native style index (0=바탕글, 1=본문, ...)\n indentPt?: number; // 문단 왼쪽 전체 들여쓰기 (pt) — OWPML hc:left\n indentRightPt?: number; // 문단 오른쪽 전체 들여쓰기 (pt) — OWPML hc:right\n firstLineIndentPt?: number; // 첫 줄 들여쓰기 (pt, 음수=내어쓰기) — OWPML hc:indent\n leftMargin?: number; // 문단 왼쪽 여백 (HWP leftMargin, pt)\n spaceBefore?: number;\n spaceAfter?: number;\n lineHeight?: number; // 줄 간격 배율 (예: 1.5 = 150%)\n lineHeightFixed?: number; // 고정 줄 높이 (pt) — OWPML lineSpacing type=\"FIXED\"\n listLv?: number;\n listOrd?: boolean;\n listMark?: string;\n verAlign?: 'baseline' | 'top' | 'center' | 'bottom';\n lineWrap?: 'break' | 'squeeze' | 'keep';\n}\nexport interface Stroke {\n kind: StrokeKind;\n pt: number;\n color: string;\n}\n\nexport interface CellProps {\n top?: Stroke;\n bot?: Stroke;\n left?: Stroke;\n right?: Stroke;\n bg?: string;\n padPt?: number; // 모든 방향 균일 패딩 (하위 호환)\n padT?: number; // 상단 패딩 (pt)\n padB?: number; // 하단 패딩\n padL?: number; // 좌측 패딩\n padR?: number; // 우측 패딩\n align?: Align;\n va?: VAlign;\n isHeader?: boolean;\n}\n\nexport interface TableLook {\n firstRow?: boolean;\n lastRow?: boolean;\n firstCol?: boolean;\n lastCol?: boolean;\n bandedRows?: boolean;\n bandedCols?: boolean;\n}\n\nexport interface GridProps {\n widthPct?: number;\n colWidths?: number[]; // column widths in points\n defaultStroke?: Stroke;\n look?: TableLook;\n headerRow?: boolean;\n align?: Align; // 표 정렬: 'left' | 'center' | 'right' | 'justify'\n}\n\nexport interface PageDims {\n wPt: number;\n hPt: number;\n mt: number;\n mb: number;\n ml: number;\n mr: number;\n orient?: 'portrait' | 'landscape';\n headerPt?: number; // distance from paper top to header top (DOCX w:header)\n footerPt?: number; // distance from paper bottom to footer bottom (DOCX w:footer)\n}\n\nexport interface DocMeta {\n title?: string;\n author?: string;\n subject?: string;\n desc?: string;\n keywords?: string;\n created?: string;\n modified?: string;\n zoom?: number;\n viewMode?: string;\n}\n\nexport const A4: PageDims = {\n wPt: 595.28, hPt: 841.89,\n mt: 56.69, mb: 56.69, ml: 70.87, mr: 70.87,\n orient: 'portrait',\n};\n\nexport const A4_LANDSCAPE: PageDims = {\n wPt: 841.89, hPt: 595.28,\n mt: 56.69, mb: 56.69, ml: 70.87, mr: 70.87,\n orient: 'landscape',\n};\n\n/**\n * orient === 'landscape'일 때 wPt < hPt이면 swap,\n * orient === 'portrait'일 때 wPt > hPt이면 swap하여\n * 방향과 치수가 항상 일치하도록 정규화합니다.\n */\n\nexport function normalizeDims(dims: PageDims): PageDims {\n const orient = dims.orient ?? 'portrait';\n if (orient === 'landscape' && dims.wPt < dims.hPt) {\n return { ...dims, wPt: dims.hPt, hPt: dims.wPt };\n }\n if (orient === 'portrait' && dims.wPt > dims.hPt) {\n return { ...dims, wPt: dims.hPt, hPt: dims.wPt };\n }\n return dims;\n}\n\nexport const DEFAULT_STROKE: Stroke = { kind: 'solid', pt: 0.5, color: '000000' };\n","import type {\n DocRoot, SheetNode, ParaNode, SpanNode, ImgNode,\n GridNode, RowNode, CellNode, ContentNode, TxtNode, PageNumNode, BrNode, PbNode,\n} from './doc-tree';\nimport type { TextProps, ParaProps, CellProps, GridProps, DocMeta, PageDims, ImgLayout } from './doc-props';\nimport { A4 } from './doc-props';\n\nexport function buildRoot(meta: DocMeta = {}, kids: SheetNode[] = []): DocRoot {\n return { tag: 'root', meta, kids };\n}\n\nexport function buildSheet(\n kids: ContentNode[] = [],\n dims: PageDims = A4,\n opts?: { headers?: SheetNode[\"headers\"]; footers?: SheetNode[\"footers\"] },\n): SheetNode {\n const node: SheetNode = { tag: 'sheet', dims, kids };\n if (opts?.headers) node.headers = opts.headers;\n if (opts?.footers) node.footers = opts.footers;\n return node;\n}\n\nexport function buildPageNum(format?: PageNumNode['format']): PageNumNode {\n return { tag: 'pagenum', format };\n}\n\nexport function buildBr(): BrNode { return { tag: 'br' }; }\nexport function buildPb(): PbNode { return { tag: 'pb' }; }\n\nexport function buildPara(kids: ParaNode['kids'] = [], props: ParaProps = {}): ParaNode {\n return { tag: 'para', props, kids };\n}\n\nexport function buildSpan(content: string, props: TextProps = {}): SpanNode {\n const txt: TxtNode = { tag: 'txt', content };\n return { tag: 'span', props, kids: [txt] };\n}\n\nexport function buildImg(\n b64: string,\n mime: ImgNode['mime'],\n w: number,\n h: number,\n alt?: string,\n layout?: ImgLayout,\n): ImgNode {\n const node: ImgNode = { tag: 'img', b64, mime, w, h };\n if (alt) node.alt = alt;\n if (layout) node.layout = layout;\n return node;\n}\n\nexport function buildGrid(kids: RowNode[], props: GridProps = {}): GridNode {\n return { tag: 'grid', props, kids };\n}\n\nexport function buildRow(kids: CellNode[], heightPt?: number): RowNode {\n const node: RowNode = { tag: 'row', kids };\n if (heightPt != null) node.heightPt = heightPt;\n return node;\n}\n\nexport function buildCell(\n kids: (ParaNode | GridNode)[],\n opts: { cs?: number; rs?: number; props?: CellProps } = {},\n): CellNode {\n return { tag: 'cell', cs: opts.cs ?? 1, rs: opts.rs ?? 1, props: opts.props ?? {}, kids };\n}\n","export class ShieldedParser {\n private log: string[] = [];\n\n /** 단일 요소 안전 파싱 */\n guard<T>(fn: () => T, fallback: T, label: string): T {\n try {\n const v = fn();\n if (v == null) {\n this.warn(label, 'returned null/undefined');\n return fallback;\n }\n return v;\n } catch (e: any) {\n this.warn(label, e?.message ?? String(e));\n return fallback;\n }\n }\n\n /** 배열 각 요소 독립 파싱 (하나 실패해도 나머지 계속) */\n guardAll<I, O>(\n items: I[],\n fn: (x: I, i: number) => O,\n fb: (x: I, i: number) => O,\n label: string,\n ): O[] {\n return items.map((x, i) =>\n this.guard(() => fn(x, i), fb(x, i), `${label}[${i}]`),\n );\n }\n\n /**\n * 표 전용 4단계 폴백\n * Lv1: Full → Lv2: Grid → Lv3: Flat → Lv4: Text\n */\n guardGrid<T>(\n node: unknown,\n lv1Full: (n: unknown) => T,\n lv2Grid: (n: unknown) => T,\n lv3Flat: (n: unknown) => T,\n lv4Text: (n: unknown) => T,\n label: string,\n ): { value: T; level: 1 | 2 | 3 | 4 } {\n const levels: [(n: unknown) => T, 1 | 2 | 3 | 4][] = [\n [lv1Full, 1], [lv2Grid, 2], [lv3Flat, 3], [lv4Text, 4],\n ];\n\n for (const [fn, lv] of levels) {\n try {\n const v = fn(node);\n if (v != null) {\n if (lv > 1) this.warn(label, `degraded to level ${lv}`);\n return { value: v, level: lv };\n }\n } catch (e: any) {\n this.warn(label, `Lv${lv} failed: ${e?.message ?? String(e)}`);\n }\n }\n\n this.warn(label, 'ALL LEVELS FAILED — returning lv4Text forced');\n return { value: lv4Text(null), level: 4 };\n }\n\n /** 이미지 안전 파싱 */\n guardImg<T>(\n node: unknown,\n fn: (n: unknown) => T,\n placeholder: (alt: string) => T,\n label: string,\n ): T {\n try {\n const v = fn(node);\n if (v != null) return v;\n } catch (e: any) {\n this.warn(label, e?.message ?? String(e));\n }\n this.warn(label, 'using placeholder image');\n return placeholder(`[이미지 로드 실패: ${label}]`);\n }\n\n private warn(label: string, msg: string): void {\n const w = `[SHIELD] ${label}: ${msg}`;\n console.warn(w);\n this.log.push(w);\n }\n\n flush(): string[] {\n const r = [...this.log];\n this.log = [];\n return r;\n }\n}\n","import type { Align, StrokeKind, Stroke } from '../model/doc-props';\n\n// ─── 단위 변환 ─────────────────────────────────────────────\nexport const Metric = {\n // HWP 세계 (1 inch = 7200 HWPUNIT)\n hwpToPt: (v: number) => v / 100,\n ptToHwp: (v: number) => Math.round(v * 100),\n hwpToDxa: (v: number) => Math.round(v / 5),\n dxaToHwp: (v: number) => Math.round(v * 5),\n hwpToEmu: (v: number) => Math.round(v * 127),\n emuToHwp: (v: number) => Math.round(v / 127),\n\n // DOCX 세계 (1 inch = 1440 dxa, 1 pt = 20 dxa)\n dxaToPt: (v: number) => v / 20,\n ptToDxa: (v: number) => Math.round(v * 20),\n dxaToEmu: (v: number) => Math.round(v * 635),\n emuToDxa: (v: number) => Math.round(v / 635),\n emuToPt: (v: number) => v / 12700,\n ptToEmu: (v: number) => Math.round(v * 12700),\n\n // HWPX charPr height: 1000 = 10pt\n hHeightToPt: (v: number) => v / 100,\n ptToHHeight: (v: number) => Math.round(v * 100),\n\n // DOCX half-point: 24 = 12pt\n halfPtToPt: (v: number) => v / 2,\n ptToHalfPt: (v: number) => Math.round(v * 2),\n} as const;\n\n// ─── 색상 정규화 ───────────────────────────────────────────\nexport function safeHex(raw: string | number | null | undefined): string | undefined {\n if (raw == null) return undefined;\n if (typeof raw === 'number') {\n if (raw <= 0) return '000000';\n if (raw >= 0xFFFFFF) return undefined;\n return raw.toString(16).padStart(6, '0').toUpperCase();\n }\n let s = String(raw).replace(/^#/, '').toUpperCase();\n if (/^[0-9A-F]{3}$/.test(s)) s = s[0] + s[0] + s[1] + s[1] + s[2] + s[2];\n if (/^[0-9A-F]{6}$/.test(s)) return s;\n if (s === 'AUTO' || s === 'NONE' || s === 'TRANSPARENT') return undefined;\n return undefined;\n}\n\n// ─── 정렬 정규화 ───────────────────────────────────────────\nconst ALIGN_MAP: Record<string, Align> = {\n LEFT: 'left', CENTER: 'center', RIGHT: 'right', JUSTIFY: 'justify',\n BOTH: 'justify', DISTRIBUTE: 'justify',\n left: 'left', center: 'center', right: 'right', both: 'justify',\n start: 'left', end: 'right',\n};\nexport function safeAlign(raw?: string): Align {\n return ALIGN_MAP[raw ?? ''] ?? 'left';\n}\n\n// ─── 테두리 정규화 ─────────────────────────────────────────\nconst HWPX_STROKE: Record<string, StrokeKind> = {\n SOLID: \"solid\",\n NONE: \"none\",\n DASH: \"dash\",\n DOT: \"dot\",\n DOUBLE: \"double\",\n LONG_DASH: \"dash\",\n DASH_DOT: \"dashDot\",\n DASH_DOT_DOT: \"dashDotDot\",\n THICK_THIN: \"double\",\n THIN_THICK: \"double\",\n TRIPLE: \"double\",\n};\nconst DOCX_STROKE: Record<string, StrokeKind> = {\n single: \"solid\",\n none: \"none\",\n nil: \"none\",\n dashed: \"dash\",\n dotted: \"dot\",\n double: \"double\",\n dotDash: \"dashDot\",\n dotDotDash: \"dashDotDot\",\n thickThin: \"double\",\n thinThick: \"double\",\n triple: \"double\",\n wave: \"wave\",\n dashDotStroked: \"dashDot\",\n threeDEmboss: \"solid\",\n threeDEngrave: \"solid\",\n};\n\nexport function safeStrokeHwpx(type?: string, w?: number, c?: string): Stroke {\n return {\n kind: HWPX_STROKE[type ?? ''] ?? 'solid',\n pt: w != null ? Metric.hwpToPt(w) : 0.5,\n color: safeHex(c) ?? '000000',\n };\n}\n\nexport function safeStrokeDocx(val?: string, sz?: number, c?: string): Stroke {\n return {\n kind: DOCX_STROKE[val ?? ''] ?? 'solid',\n pt: sz != null ? sz / 8 : 0.5,\n color: safeHex(c) ?? '000000',\n };\n}\n\n// ─── 폰트 정규화 ───────────────────────────────────────────\nconst FONT_MAP: Record<string, string> = {\n // 맑은 고딕 계열\n '맑은 고딕': 'Malgun Gothic',\n '맑은고딕': 'Malgun Gothic',\n // 바탕 계열 (serif)\n '바탕': 'Batang',\n '바탕체': 'BatangChe',\n '한컴바탕': 'Batang',\n '함초롬바탕': 'Batang',\n 'HY신명조': 'Batang',\n 'HY견명조': 'Batang',\n 'HY그래픽': 'Batang',\n '궁서': 'Gungsuh',\n '궁서체': 'GungsuhChe',\n // 고딕 계열 (sans-serif)\n '돋움': 'Dotum',\n '돋움체': 'DotumChe',\n '굴림': 'Gulim',\n '굴림체': 'GulimChe',\n '한컴돋움': 'Malgun Gothic',\n '함초롬돋움': 'Malgun Gothic',\n 'HY견고딕': 'Malgun Gothic',\n 'HY중고딕': 'Malgun Gothic',\n 'HY헤드라인M': 'Malgun Gothic',\n 'HY강B': 'Malgun Gothic',\n 'HY나무M': 'Malgun Gothic',\n 'HY목각파임B': 'Malgun Gothic',\n 'HY엽서M': 'Malgun Gothic',\n 'HY엽서L': 'Malgun Gothic',\n // 나눔 계열\n '나눔고딕': 'Malgun Gothic',\n '나눔명조': 'Batang',\n};\nexport function safeFont(raw?: string): string {\n return FONT_MAP[raw ?? ''] ?? raw ?? 'Malgun Gothic';\n}\n\n// Reverse mapping: English → Korean (for HWPX encoding)\nconst FONT_MAP_KR: Record<string, string> = {\n 'Malgun Gothic': '맑은 고딕',\n 'Batang': '바탕',\n 'Dotum': '돋움',\n 'Gulim': '굴림',\n};\nexport function safeFontToKr(raw?: string): string {\n return FONT_MAP_KR[raw ?? ''] ?? raw ?? '맑은 고딕';\n}\n","import pako from 'pako';\n\ninterface ZipEntry {\n name: string;\n data: Uint8Array;\n}\n\nexport const ArchiveKit = {\n async inflate(compressed: Uint8Array): Promise<Uint8Array> {\n return pako.inflate(compressed);\n },\n\n async deflate(data: Uint8Array): Promise<Uint8Array> {\n return pako.deflate(data, { level: 6 });\n },\n\n async unzip(zipData: Uint8Array): Promise<Map<string, Uint8Array>> {\n const files = new Map<string, Uint8Array>();\n const view = new DataView(zipData.buffer, zipData.byteOffset, zipData.byteLength);\n\n // Find EOCD by scanning backward from end (supports ZIP comment up to 64KB)\n let eocdOffset = -1;\n const searchStart = Math.max(0, zipData.length - 65558);\n for (let i = zipData.length - 22; i >= searchStart; i--) {\n if (view.getUint32(i, true) === 0x06054b50) {\n eocdOffset = i;\n break;\n }\n }\n\n if (eocdOffset !== -1) {\n // Parse central directory — always has correct sizes even with data descriptors\n const entryCount = view.getUint16(eocdOffset + 10, true);\n const centralDirOffset = view.getUint32(eocdOffset + 16, true);\n\n let cdOffset = centralDirOffset;\n for (let i = 0; i < entryCount; i++) {\n if (cdOffset + 46 > zipData.length) break;\n if (view.getUint32(cdOffset, true) !== 0x02014b50) break;\n\n const compressionMethod = view.getUint16(cdOffset + 10, true);\n const compressedSize = view.getUint32(cdOffset + 20, true);\n const uncompressedSize = view.getUint32(cdOffset + 24, true);\n const fileNameLength = view.getUint16(cdOffset + 28, true);\n const extraLength = view.getUint16(cdOffset + 30, true);\n const commentLength = view.getUint16(cdOffset + 32, true);\n const localHeaderOffset = view.getUint32(cdOffset + 42, true);\n\n const nameBytes = zipData.subarray(cdOffset + 46, cdOffset + 46 + fileNameLength);\n const name = new TextDecoder('utf-8').decode(nameBytes);\n cdOffset += 46 + fileNameLength + extraLength + commentLength;\n\n if (name.endsWith('/')) continue; // directory entry\n\n // Read actual data using the local header offset from central directory\n const localFnLen = view.getUint16(localHeaderOffset + 26, true);\n const localExtraLen = view.getUint16(localHeaderOffset + 28, true);\n const dataOffset = localHeaderOffset + 30 + localFnLen + localExtraLen;\n\n let fileData: Uint8Array;\n if (compressionMethod === 0) {\n fileData = zipData.subarray(dataOffset, dataOffset + uncompressedSize);\n } else if (compressionMethod === 8) {\n const compressed = zipData.subarray(dataOffset, dataOffset + compressedSize);\n fileData = pako.inflateRaw(compressed);\n } else {\n throw new Error(`Unsupported ZIP compression method: ${compressionMethod}`);\n }\n\n files.set(name, new Uint8Array(fileData));\n }\n\n return files;\n }\n\n // Fallback: scan local headers sequentially (no EOCD found — truncated ZIP)\n let offset = 0;\n while (offset < zipData.length - 4) {\n const sig = view.getUint32(offset, true);\n\n if (sig === 0x04034b50) {\n const compressionMethod = view.getUint16(offset + 8, true);\n const compressedSize = view.getUint32(offset + 18, true);\n const uncompressedSize = view.getUint32(offset + 22, true);\n const fileNameLength = view.getUint16(offset + 26, true);\n const extraLength = view.getUint16(offset + 28, true);\n\n const nameBytes = zipData.subarray(offset + 30, offset + 30 + fileNameLength);\n const name = new TextDecoder('utf-8').decode(nameBytes);\n\n const dataOffset = offset + 30 + fileNameLength + extraLength;\n let fileData: Uint8Array;\n\n if (compressionMethod === 0) {\n fileData = zipData.subarray(dataOffset, dataOffset + uncompressedSize);\n } else if (compressionMethod === 8) {\n const compressed = zipData.subarray(dataOffset, dataOffset + compressedSize);\n fileData = pako.inflateRaw(compressed);\n } else {\n throw new Error(`Unsupported ZIP compression method: ${compressionMethod}`);\n }\n\n files.set(name, new Uint8Array(fileData));\n offset = dataOffset + compressedSize;\n } else if (sig === 0x02014b50 || sig === 0x06054b50) {\n break;\n } else {\n offset++;\n }\n }\n\n return files;\n },\n\n async zip(entries: ZipEntry[]): Promise<Uint8Array> {\n const localHeaders: Uint8Array[] = [];\n const centralHeaders: Uint8Array[] = [];\n let localOffset = 0;\n\n for (const entry of entries) {\n const nameBytes = new TextEncoder().encode(entry.name);\n const crc = crc32(entry.data);\n\n // 'mimetype' and 'version.xml' must be stored uncompressed per HWPX spec\n const store = entry.name === 'mimetype' || entry.name === 'version.xml';\n const method = store ? 0 : 8;\n const payload = store ? entry.data : pako.deflateRaw(entry.data, { level: 6 });\n\n // Local file header (30 bytes + name + data)\n const local = new Uint8Array(30 + nameBytes.length + payload.length);\n const lv = new DataView(local.buffer);\n lv.setUint32(0, 0x04034b50, true);\n lv.setUint16(4, 20, true);\n lv.setUint16(6, 0, true);\n lv.setUint16(8, method, true);\n lv.setUint16(10, 0, true);\n lv.setUint16(12, 0x0021, true); // date (1980-01-01)\n lv.setUint32(14, crc, true);\n lv.setUint32(18, payload.length, true);\n lv.setUint32(22, entry.data.length, true);\n lv.setUint16(26, nameBytes.length, true);\n lv.setUint16(28, 0, true);\n local.set(nameBytes, 30);\n local.set(payload, 30 + nameBytes.length);\n\n // Central directory header (46 bytes + name)\n const central = new Uint8Array(46 + nameBytes.length);\n const cv = new DataView(central.buffer);\n cv.setUint32(0, 0x02014b50, true);\n cv.setUint16(4, 20, true);\n cv.setUint16(6, 20, true);\n cv.setUint16(8, 0, true);\n cv.setUint16(10, method, true);\n cv.setUint16(12, 0, true); // mod time\n cv.setUint16(14, 0x0021, true); // mod date (1980-01-01)\n cv.setUint32(16, crc, true);\n cv.setUint32(20, payload.length, true);\n cv.setUint32(24, entry.data.length, true);\n cv.setUint16(28, nameBytes.length, true);\n cv.setUint16(30, 0, true);\n cv.setUint16(32, 0, true);\n cv.setUint16(34, 0, true);\n cv.setUint16(36, 0, true);\n cv.setUint32(38, 0, true);\n cv.setUint32(42, localOffset, true);\n central.set(nameBytes, 46);\n\n localHeaders.push(local);\n centralHeaders.push(central);\n localOffset += local.length;\n }\n\n const centralDir = concat(centralHeaders);\n const eocd = new Uint8Array(22);\n const ev = new DataView(eocd.buffer);\n ev.setUint32(0, 0x06054b50, true);\n ev.setUint16(4, 0, true);\n ev.setUint16(6, 0, true);\n ev.setUint16(8, entries.length, true);\n ev.setUint16(10, entries.length, true);\n ev.setUint32(12, centralDir.length, true);\n ev.setUint32(16, localOffset, true);\n ev.setUint16(20, 0, true);\n\n return concat([...localHeaders, centralDir, eocd]);\n },\n};\n\nfunction concat(arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((s, a) => s + a.length, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const a of arrays) { out.set(a, offset); offset += a.length; }\n return out;\n}\n\nfunction crc32(data: Uint8Array): number {\n let crc = 0xFFFFFFFF;\n for (const byte of data) {\n crc ^= byte;\n for (let i = 0; i < 8; i++) {\n crc = (crc & 1) ? (crc >>> 1) ^ 0xEDB88320 : crc >>> 1;\n }\n }\n return (crc ^ 0xFFFFFFFF) >>> 0;\n}\n","import { SaxesParser } from 'saxes';\n\n// Parses XML into an xml2js-compatible object structure:\n// { tagName: [{ _attr: { k: v }, _text: '...', childTag: [...] }] }\nfunction parseXmlStrict(xml: string): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const parser = new SaxesParser({ xmlns: false });\n\n interface Frame { tag: string; obj: Record<string, unknown> }\n const stack: Frame[] = [];\n let result: unknown = null;\n\n parser.on('error', (err: Error) => reject(err));\n\n parser.on('opentag', (node: any) => {\n const obj: Record<string, unknown> = {};\n const attrs = node.attributes as Record<string, string>;\n if (attrs && Object.keys(attrs).length > 0) {\n obj['_attr'] = { ...attrs };\n }\n stack.push({ tag: node.name as string, obj });\n });\n\n const appendText = (text: string) => {\n if (stack.length > 0 && text) {\n const frame = stack[stack.length - 1];\n const cur = frame.obj['_text'];\n frame.obj['_text'] = typeof cur === 'string' ? cur + text : text;\n }\n };\n\n parser.on('text', (text: string) => appendText(text));\n parser.on('cdata', (cdata: string) => appendText(cdata));\n\n parser.on('closetag', () => {\n const frame = stack.pop();\n if (!frame) return;\n const { tag, obj } = frame;\n\n if (stack.length === 0) {\n result = { [tag]: [obj] };\n } else {\n const parent = stack[stack.length - 1].obj;\n const existing = parent[tag];\n if (Array.isArray(existing)) {\n (existing as unknown[]).push(obj);\n } else {\n parent[tag] = [obj];\n }\n // Track child order for document-order iteration\n if (!parent['_childOrder']) parent['_childOrder'] = [];\n (parent['_childOrder'] as string[]).push(tag);\n }\n });\n\n try {\n parser.write(xml).close();\n resolve(result);\n } catch (e) {\n reject(e);\n }\n });\n}\n\nexport const XmlKit = {\n /** @deprecated Use parseStrict instead */\n async parse(xml: string): Promise<unknown> {\n return parseXmlStrict(xml);\n },\n\n async parseStrict(xml: string): Promise<unknown> {\n return parseXmlStrict(xml);\n },\n\n attr(node: Record<string, unknown>, key: string): string | undefined {\n const a = node['_attr'] as Record<string, string> | undefined;\n return a?.[key];\n },\n\n text(node: Record<string, unknown> | string | undefined): string {\n if (node == null) return '';\n if (typeof node === 'string') return node;\n const t = node['_text'];\n return typeof t === 'string' ? t : '';\n },\n};\n","export const TextKit = {\n decode(data: Uint8Array, encoding = 'utf-8'): string {\n try {\n return new TextDecoder(encoding, { fatal: true }).decode(data);\n } catch {\n return new TextDecoder('utf-8', { fatal: false }).decode(data);\n }\n },\n\n encode(text: string): Uint8Array {\n return new TextEncoder().encode(text);\n },\n\n escapeXml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n },\n\n unescapeXml(s: string): string {\n return s\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&apos;/g, \"'\");\n },\n\n normalizeWhitespace(s: string): string {\n return s.replace(/\\s+/g, ' ').trim();\n },\n\n stripControl(s: string): string {\n // eslint-disable-next-line no-control-regex\n return s.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '');\n },\n\n base64Encode(data: Uint8Array): string {\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n return btoa(binary);\n },\n\n base64Decode(b64: string): Uint8Array {\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n },\n};\n","/**\n * BaseDecoder - 모든 디코더의 기본 클래스\n *\n * 공통 로직을 제공하여 각 포맷별 디코더가 포맷 특유의 로직만 구현하도록 합니다.\n */\n\nimport type { Decoder } from '../contract/decoder';\nimport type { Outcome } from '../contract/result';\nimport type { DocRoot } from '../model/doc-tree';\nimport { TextKit } from '../toolkit/TextKit';\nimport { ArchiveKit } from '../toolkit/ArchiveKit';\n\n// ─── BaseDecoder ───────────────────────────────────\n\nexport abstract class BaseDecoder implements Decoder {\n readonly format: string = this.getFormat();\n readonly aliases: string[] = this.getAliases();\n\n /** 포맷 이름 반환 (하위 클래스에서 오버라이드) */\n protected abstract getFormat(): string;\n\n /** 별칭 목록 반환 (하위 클래스에서 필요 시 오버라이드) */\n protected getAliases(): string[] { return []; }\n\n /** 데이터 디코딩 (하위 클래스에서 오버라이드) */\n abstract decode(data: Uint8Array): Promise<Outcome<DocRoot>>;\n\n // ─── 공통 유틸리티 메서드 ──────────────────────────\n\n /** 바이트를 UTF-8 문자열로 변환 */\n protected bytesToString(data: Uint8Array): string {\n return TextKit.decode(data);\n }\n\n /** 문자열을 UTF-8 바이트로 변환 */\n protected stringToBytes(s: string): Uint8Array {\n return TextKit.encode(s);\n }\n\n /** XML 이스케이프 */\n protected escapeXml(s: string): string {\n return TextKit.escapeXml(s);\n }\n\n /** XML 언이스케이프 */\n protected unescapeXml(s: string): string {\n return TextKit.unescapeXml(s);\n }\n\n /** base64 문자열을 Uint8Array 로 변환 */\n protected base64ToBytes(b64: string): Uint8Array {\n return TextKit.base64Decode(b64);\n }\n\n /** Uint8Array 를 base64 문자열로 변환 */\n protected bytesToBase64(data: Uint8Array): string {\n return TextKit.base64Encode(data);\n }\n\n /** ZIP 해제 */\n protected async unzip(data: Uint8Array): Promise<Map<string, Uint8Array>> {\n return ArchiveKit.unzip(data);\n }\n\n /** ZIP 압축 */\n protected async zip(entries: { name: string; data: Uint8Array }[]): Promise<Uint8Array> {\n return ArchiveKit.zip(entries);\n }\n\n /** inflate 해제 */\n protected async inflate(data: Uint8Array): Promise<Uint8Array> {\n return ArchiveKit.inflate(data);\n }\n\n /** deflate 압축 */\n protected async deflate(data: Uint8Array): Promise<Uint8Array> {\n return ArchiveKit.deflate(data);\n }\n\n /** 제어 문자 제거 */\n protected stripControl(s: string): string {\n return TextKit.stripControl(s);\n }\n\n /** 공백 정규화 */\n protected normalizeWhitespace(s: string): string {\n return TextKit.normalizeWhitespace(s);\n }\n\n /** XML 파싱 (DOMParser 사용) */\n protected parseXml(xmlString: string): Document {\n const parser = new DOMParser();\n return parser.parseFromString(xmlString, 'text/xml');\n }\n\n /** XML 요소에서 텍스트 내용 추출 */\n protected getTextContent(element: Element | null | undefined): string {\n if (!element) return '';\n return element.textContent ?? '';\n }\n\n /** XML 요소의 속성 값 추출 */\n protected getAttr(element: Element | null | undefined, name: string): string | null {\n return element?.getAttribute(name) ?? null;\n }\n\n /** XML 요소의 자식 요소 찾기 */\n protected getChild(element: Element | null | undefined, tagName: string): Element | null {\n if (!element) return null;\n return element.querySelector(`>${tagName}`) ?? null;\n }\n\n /** XML 요소의 모든 자식 요소 찾기 */\n protected getChildren(element: Element | null | undefined, tagName: string): Element[] {\n if (!element) return [];\n return Array.from(element.querySelectorAll(`>${tagName}`));\n }\n}\n","/**\n * HWPX 인코더 관련 상수\n *\n * HWPX 파일 생성에 필요한 모든 설정값을 한곳에 모아 관리합니다.\n * 초중급 개발자도 쉽게 수정할 수 있도록 명확한 주석을 포함했습니다.\n */\n\n// ==================== 파일 형식 관련 ====================\n\n/** HWPX 파일의 MIME 타입 (ZIP 파일 내 mimetype 파일에 저장됨) */\nexport const HWPX_MIME_TYPE = \"application/hwp+zip\";\n\n/** HWPX 파일의 버전 */\nexport const HWPX_VERSION = \"1.2\";\n\n// ==================== XML 네임스페이스 ====================\n\n/** HWPX XML 문서에서 사용되는 네임스페이스 */\nexport const NAMESPACES = {\n /** Hancom 문서 네임스페이스 */\n HANCOM: \"http://www.hancom.co.kr/hwp/xml\",\n /** Hancom 공통 네임스페이스 */\n HANCOM_COMMON: \"http://www.hancom.co.kr/hwp/xml/common\",\n /** Hancom 버전 네임스페이스 */\n HANCOM_VERSION: \"http://www.hancom.co.kr/hwp/xml/version\",\n /** Hancom 속성 네임스페이스 */\n HANCOM_PROP: \"http://www.hancom.co.kr/hwp/xml/property\",\n} as const;\n\n/** XML 헤더에 포함될 네임스페이스 선언 문자열 */\nexport const NAMESPACE_DECLARATIONS = {\n HEAD: `xmlns:hh=\"${NAMESPACES.HANCOM}\" xmlns:hc=\"${NAMESPACES.HANCOM_COMMON}\" xmlns:hv=\"${NAMESPACES.HANCOM_VERSION}\" xmlns:hp=\"${NAMESPACES.HANCOM_PROP}\"`,\n SECTION: `xmlns:hs=\"${NAMESPACES.HANCOM}\" xmlns:hp=\"${NAMESPACES.HANCOM_PROP}\"`,\n} as const;\n\n// ==================== 단위 변환 ====================\n\n/** 1 포인트 (pt) 를 HWPUNIT 으로 변환한 값 (HWPX 내부 단위) */\nexport const HWPUNIT_PER_PT = 1000;\n\n/** 1 인치 (inch) 를 포인트 (pt) 로 변환한 값 */\nexport const PT_PER_INCH = 72;\n\n/** 1 인치 (inch) 를 픽셀로 변환한 값 (표준 96 DPI 기준) */\nexport const PIXELS_PER_INCH = 96;\n\n/** 픽셀을 포인트로 변환하는 계수 */\nexport const PT_PER_PIXEL = PT_PER_INCH / PIXELS_PER_INCH; // 0.75\n\n// ==================== 페이지 크기 (A4 기준) ====================\n\n/** A4 용지 너비 (포인트) */\nexport const A4_WIDTH_PT = 794;\n\n/** A4 용지 높이 (포인트) */\nexport const A4_HEIGHT_PT = 1123;\n\n/** A4 용지 상단 여백 (포인트) */\nexport const A4_TOP_MARGIN_PT = 72;\n\n/** A4 용지 하단 여백 (포인트) */\nexport const A4_BOTTOM_MARGIN_PT = 72;\n\n/** A4 용지 왼쪽 여백 (포인트) */\nexport const A4_LEFT_MARGIN_PT = 83;\n\n/** A4 용지 오른쪽 여백 (포인트) */\nexport const A4_RIGHT_MARGIN_PT = 83;\n\n/** A4 용지 상단 머리글 영역 (포인트) */\nexport const A4_HEADER_MARGIN_PT = 40;\n\n/** A4 용지 하단 바닥글 영역 (포인트) */\nexport const A4_FOOTER_MARGIN_PT = 40;\n\n// ==================== 폰트 관련 ====================\n\n/** 기본 한글 폰트 */\nexport const DEFAULT_KOREAN_FONT = \"Batang\";\n\n/** 기본 영문 폰트 */\nexport const DEFAULT_LATIN_FONT = \"Arial\";\n\n/** 기본 폰트 크기 (포인트) */\nexport const DEFAULT_FONT_SIZE_PT = 10;\n\n// ==================== 줄 간격 ====================\n\n/** 기본 줄 간격 (폰트 크기의 %) */\nexport const DEFAULT_LINE_SPACING_PERCENT = 160;\n\n/** 최소 줄 간격 (HWPUNIT) */\nexport const MIN_LINE_SPACING_HWPUNIT = 1000;\n\n// ==================== 스타일 ID ====================\n\n/** 바탕글 스타일 ID */\nexport const STYLE_ID_BATANGGUL = \"0\";\n\n/** 개요 1 스타일 ID */\nexport const STYLE_ID_GYEYOE1 = \"1\";\n\n/** 개요 2 스타일 ID */\nexport const STYLE_ID_GYEYOE2 = \"2\";\n\n// ==================== 이미지 관련 ====================\n\n/** 이미지 파일이 저장될 디렉토리 경로 (ZIP 내) */\nexport const IMAGE_DIR_PATH = \"image/\";\n\n/** 이미지 파일명 접미사 */\nexport const IMAGE_FILE_EXTENSION = \".png\";\n\n// ==================== 테이블 관련 ====================\n\n/** 테이블 테두리 기본 두께 (HWPUNIT) */\nexport const TABLE_BORDER_WIDTH_HWPUNIT = 500; // 0.5pt\n\n/** 테이블 셀 기본 패딩 (HWPUNIT) */\nexport const TABLE_CELL_PADDING_HWPUNIT = 200; // 0.2pt\n\n// ==================== 색상 코드 ====================\n\n/** 검정색 (hex) */\nexport const COLOR_BLACK = \"#000000\";\n\n/** 흰색 (hex) */\nexport const COLOR_WHITE = \"#FFFFFF\";\n\n/** 회색 (워터마크용) */\nexport const COLOR_GRAY = \"#CCCCCC\";\n\n/** 코드 블록 배경색 */\nexport const COLOR_CODE_BLOCK_BG = \"#f4f4f4\";\n\n// ==================== ZIP 파일 구조 ====================\n\n/** HWPX 파일 내 파일 목록 */\nexport const HWPX_FILE_STRUCTURE = [\n { name: \"mimetype\", mimeType: \"\" },\n { name: \".hwpversions/version.xml\", mimeType: \"application/xml\" },\n { name: \"header.xml\", mimeType: \"application/xml\" },\n { name: \"section0.xml\", mimeType: \"application/xml\" },\n { name: \"content.hpf\", mimeType: \"application/octet-stream\" },\n] as const;\n\n/** ZIP 파일 생성 시 사용할 압축 레벨 (0=압축안함, 9=최대압축) */\nexport const ZIP_COMPRESSION_LEVEL = 9;\n","import type {\n DocRoot,\n ContentNode,\n ParaNode,\n SpanNode,\n GridNode,\n ImgNode,\n PageNumNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport type {\n DocMeta,\n PageDims,\n TextProps,\n ParaProps,\n CellProps,\n GridProps,\n Stroke,\n ImgLayout,\n ImgWrap,\n ImgHorzAlign,\n ImgVertAlign,\n ImgHorzRelTo,\n ImgVertRelTo,\n} from \"../../model/doc-props\";\nimport { A4 } from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport {\n buildRoot,\n buildSheet,\n buildPara,\n buildSpan,\n buildImg,\n buildGrid,\n buildRow,\n buildCell,\n buildPb,\n} from \"../../model/builders\";\nimport { ShieldedParser } from \"../../safety/ShieldedParser\";\nimport {\n Metric,\n safeAlign,\n safeFont,\n safeHex,\n safeStrokeHwpx,\n} from \"../../safety/StyleBridge\";\nimport { ArchiveKit } from \"../../toolkit/ArchiveKit\";\nimport { XmlKit } from \"../../toolkit/XmlKit\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { registry } from \"../../pipeline/registry\";\nimport { BaseDecoder } from \"../../core/BaseDecoder\";\nimport { HWPX_MIME_TYPE } from \"../../encoders/hwpx/constants\";\n\ninterface BorderFillInfo {\n stroke?: Stroke; // uniform fallback (used when all sides are the same)\n top?: Stroke;\n right?: Stroke;\n bottom?: Stroke;\n left?: Stroke;\n bgColor?: string;\n}\n\ninterface CharPrInfo {\n b?: boolean;\n i?: boolean;\n u?: boolean;\n s?: boolean;\n pt?: number;\n color?: string;\n font?: string;\n bg?: string;\n}\n\ninterface ParaPrInfo {\n align?: string;\n indentPt?: number; // hc:left → 문단 전체 왼쪽 여백\n indentRightPt?: number; // hc:right → 문단 전체 오른쪽 여백\n firstLineIndentPt?: number; // hc:indent → 첫 줄 들여쓰기 (양수=들여쓰기, 음수=내어쓰기)\n spaceBefore?: number;\n spaceAfter?: number;\n lineHeight?: number;\n lineHeightFixed?: number; // FIXED 행 높이 (pt)\n}\n\ninterface DecCtx {\n files: Map<string, Uint8Array>;\n shield: ShieldedParser;\n borderFills: Map<number, BorderFillInfo>;\n charPrs: Map<number, CharPrInfo>;\n paraPrs: Map<number, ParaPrInfo>;\n warns: string[];\n}\n\nexport class HwpxDecoder extends BaseDecoder {\n protected getFormat(): string {\n return \"hwpx\";\n }\n protected getAliases(): string[] {\n return [HWPX_MIME_TYPE, \"application/hwp+zip\"];\n }\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n const files = await ArchiveKit.unzip(data);\n\n const sectionFiles: Uint8Array[] = [];\n for (let i = 0; ; i++) {\n const sec =\n files.get(`Contents/section${i}.xml`) ?? files.get(`section${i}.xml`);\n if (!sec) break;\n sectionFiles.push(sec);\n }\n if (sectionFiles.length === 0) {\n const fallback = findSectionFile(files);\n if (fallback) sectionFiles.push(fallback);\n }\n\n if (sectionFiles.length === 0)\n return fail(\"HWPX: No section files found\");\n\n const headXml =\n files.get(\"Contents/header.xml\") ?? files.get(\"header.xml\");\n\n let meta: DocMeta = {};\n let dims: PageDims = { ...A4 };\n let borderFills = new Map<number, BorderFillInfo>();\n let charPrs = new Map<number, CharPrInfo>();\n let paraPrs = new Map<number, ParaPrInfo>();\n\n if (headXml) {\n try {\n const headStr = TextKit.decode(headXml);\n const headObj: any = await XmlKit.parseStrict(headStr);\n if (headObj) {\n meta = extractMeta(headObj);\n dims = extractDims(headObj) ?? dims;\n borderFills = extractBorderFills(headObj);\n charPrs = extractCharPrs(headObj);\n paraPrs = extractParaPrs(headObj);\n }\n } catch {\n // header parse failure is non-fatal\n }\n }\n\n const ctx: DecCtx = {\n files,\n shield,\n borderFills,\n charPrs,\n paraPrs,\n warns,\n };\n\n const allSections: any[] = [];\n for (const secFile of sectionFiles) {\n const bodyStr = TextKit.decode(secFile);\n const bodyObj: any = await XmlKit.parseStrict(bodyStr);\n allSections.push(...normalizeSections(bodyObj));\n }\n\n const kids = shield.guardAll(\n allSections,\n (sec: any) => decodeSection(sec, dims, ctx),\n () => buildSheet([buildPara([buildSpan(\"[섹션 파싱 실패]\")])], dims),\n \"hwpx:section\",\n );\n\n warns.push(...shield.flush());\n return succeed(buildRoot(meta, kids), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`HWPX decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\n// ─── helpers ────────────────────────────────────────────────\n\nfunction findSectionFile(\n files: Map<string, Uint8Array>,\n): Uint8Array | undefined {\n for (const [key, val] of files) {\n if (key.toLowerCase().includes(\"section\") && key.endsWith(\".xml\"))\n return val;\n }\n return undefined;\n}\n\nfunction normalizeSections(bodyObj: any): any[] {\n // <hs:sec> (real HWPX), <hp:SEC> (legacy)\n if (bodyObj?.[\"hs:sec\"]) return toArr(bodyObj[\"hs:sec\"]);\n if (bodyObj?.[\"hp:SEC\"]) return toArr(bodyObj[\"hp:SEC\"]);\n\n const root = bodyObj?.[\"hp:HWPML\"] ?? bodyObj?.HWPML ?? bodyObj;\n const body =\n root?.[\"hp:BODY\"]?.[0] ??\n root?.BODY?.[0] ??\n root?.[\"hp:BODY\"] ??\n root?.BODY;\n if (!body) return [bodyObj];\n const sections = body?.[\"hp:SECTION\"] ?? body?.SECTION ?? [];\n return Array.isArray(sections) ? sections : [sections];\n}\n\n// Get a tag regardless of namespace/case variations\nfunction getTag(obj: any, ...names: string[]): any[] {\n for (const n of names) {\n const v = obj?.[n];\n if (v != null) return toArr(v);\n }\n return [];\n}\n\nfunction extractMeta(headObj: any): DocMeta {\n try {\n // Support both <hh:HEAD> and <hh:head>\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const info = root?.[\"hh:DOCSUMMARY\"]?.[0] ?? root?.DOCSUMMARY?.[0];\n if (!info) return {};\n const a = (k: string) =>\n info?.[`hh:${k}`]?.[0]?._text ?? info?.[k]?.[0]?._text ?? \"\";\n return {\n title: a(\"TITLE\") || undefined,\n author: a(\"AUTHOR\") || undefined,\n subject: a(\"SUBJECT\") || undefined,\n };\n } catch {\n return {};\n }\n}\n\nfunction extractDims(headObj: any): PageDims | null {\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return null;\n\n const secPrList =\n refList?.[\"hh:SECPRLST\"]?.[0]?.[\"hh:SECPR\"] ??\n refList?.SECPRLST?.[0]?.SECPR;\n const sec = Array.isArray(secPrList) ? secPrList[0] : secPrList;\n if (!sec) return null;\n\n const pa =\n sec?.[\"hh:PAGEPROPERTY\"]?.[0]?._attr ?? sec?.PAGEPROPERTY?.[0]?._attr;\n if (!pa) return null;\n\n const ew = Number(pa.Width ?? 59528);\n const eh = Number(pa.Height ?? 84188);\n return {\n wPt: Metric.hwpToPt(ew),\n hPt: Metric.hwpToPt(eh),\n mt: Metric.hwpToPt(Number(pa.TopMargin ?? 5670)),\n mb: Metric.hwpToPt(Number(pa.BottomMargin ?? 4252)),\n ml: Metric.hwpToPt(Number(pa.LeftMargin ?? 8504)),\n mr: Metric.hwpToPt(Number(pa.RightMargin ?? 8504)),\n orient: ew > eh ? \"landscape\" : \"portrait\",\n };\n } catch {\n return null;\n }\n}\n\nfunction extractBorderFills(headObj: any): Map<number, BorderFillInfo> {\n const map = new Map<number, BorderFillInfo>();\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return map;\n\n const bfList =\n refList?.[\"hh:borderFills\"]?.[0] ??\n refList?.[\"hh:BORDERFILLLIST\"]?.[0] ??\n refList?.BORDERFILLLIST?.[0];\n if (!bfList) return map;\n\n const bfs = getTag(bfList, \"hh:borderFill\", \"hh:BORDERFILL\");\n for (const bf of bfs) {\n const attr = bf?._attr ?? {};\n const id = Number(attr.id ?? 0);\n if (id === 0) continue;\n\n const info: BorderFillInfo = {};\n\n // Helper: parse a border element into a Stroke\n const parseBorderEl = (el: any): Stroke | undefined => {\n if (!el) return undefined;\n const a = el?._attr ?? {};\n const mmVal = parseFloat(a.width) || undefined;\n const hwpVal = mmVal != null ? mmVal * 2.835 * 100 : undefined;\n return safeStrokeHwpx(a.type, hwpVal, a.color);\n };\n\n // Parse all four sides\n const topEl =\n bf?.[\"hh:topBorder\"]?.[0] ?? bf?.[\"hh:top\"]?.[0] ?? bf?.top?.[0];\n const rightEl =\n bf?.[\"hh:rightBorder\"]?.[0] ?? bf?.[\"hh:right\"]?.[0] ?? bf?.right?.[0];\n const bottomEl =\n bf?.[\"hh:bottomBorder\"]?.[0] ??\n bf?.[\"hh:bottom\"]?.[0] ??\n bf?.bottom?.[0];\n const leftEl =\n bf?.[\"hh:leftBorder\"]?.[0] ?? bf?.[\"hh:left\"]?.[0] ?? bf?.left?.[0];\n\n info.top = parseBorderEl(topEl);\n info.right = parseBorderEl(rightEl);\n info.bottom = parseBorderEl(bottomEl);\n info.left = parseBorderEl(leftEl);\n\n // Set uniform stroke fallback = top border (for defaultStroke etc.)\n info.stroke = info.top ?? info.left ?? info.right ?? info.bottom;\n\n // Parse fill (real HWPX uses hc:fillBrush, not hh:fillBrush)\n const fillBrush =\n bf?.[\"hc:fillBrush\"]?.[0] ??\n bf?.[\"hh:fillBrush\"]?.[0] ??\n bf?.[\"hh:fill\"]?.[0] ??\n bf?.fill?.[0] ??\n bf?.fillBrush?.[0];\n if (fillBrush) {\n const winBrush =\n fillBrush?.[\"hc:winBrush\"]?.[0]?._attr ??\n fillBrush?.[\"hh:winBrush\"]?.[0]?._attr ??\n fillBrush?.winBrush?.[0]?._attr;\n if (winBrush?.faceColor && winBrush.faceColor !== \"none\") {\n info.bgColor = safeHex(winBrush.faceColor);\n }\n }\n\n map.set(id, info);\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\nfunction buildFontIdMap(headObj: any): Map<number, string> {\n const fontMap = new Map<number, string>();\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return fontMap;\n\n const fontfaces =\n refList?.[\"hh:fontfaces\"]?.[0] ?? refList?.[\"hh:FONTFACES\"]?.[0];\n if (!fontfaces) return fontMap;\n\n // Try each fontface group (HANGUL, LATIN, etc.) — use the first group that has entries\n const ffGroups = getTag(fontfaces, \"hh:fontface\", \"hh:FONTFACE\");\n for (const ff of ffGroups) {\n const fonts = getTag(ff, \"hh:font\", \"hh:FONT\");\n for (const font of fonts) {\n const fa = font?._attr ?? {};\n const fid = Number(fa.id ?? -1);\n const name = fa.face ?? fa.name ?? fa.Face ?? \"\";\n if (fid >= 0 && name && !fontMap.has(fid)) fontMap.set(fid, name);\n }\n if (fontMap.size > 0) break; // use first group (usually HANGUL)\n }\n } catch {\n /* non-fatal */\n }\n return fontMap;\n}\n\nfunction extractCharPrs(headObj: any): Map<number, CharPrInfo> {\n const map = new Map<number, CharPrInfo>();\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return map;\n\n // Build font id → name map from fontfaces\n const fontIdMap = buildFontIdMap(headObj);\n\n const cpList =\n refList?.[\"hh:charProperties\"]?.[0] ??\n refList?.[\"hh:CHARPROPERTIES\"]?.[0];\n if (!cpList) return map;\n\n const cps = getTag(cpList, \"hh:charPr\", \"hh:CHARPR\");\n for (const cp of cps) {\n const attr = cp?._attr ?? {};\n const id = Number(attr.id ?? -1);\n if (id < 0) continue;\n\n const info: CharPrInfo = {};\n\n // height → pt\n if (attr.height) info.pt = Metric.hHeightToPt(Number(attr.height));\n\n // textColor\n if (attr.textColor) info.color = safeHex(attr.textColor);\n\n // bold\n if (cp?.[\"hh:bold\"]?.[0] != null) info.b = true;\n\n // italic\n if (cp?.[\"hh:italic\"]?.[0] != null) info.i = true;\n\n // underline\n const ulAttr = cp?.[\"hh:underline\"]?.[0]?._attr;\n if (ulAttr?.type && ulAttr.type !== \"NONE\") info.u = true;\n\n // strikeout — shape=\"3D\" is default \"no strikeout\" in real HWPX; only SOLID/etc means active\n const stAttr = cp?.[\"hh:strikeout\"]?.[0]?._attr;\n if (stAttr?.shape && stAttr.shape !== \"NONE\" && stAttr.shape !== \"3D\")\n info.s = true;\n\n // font name — resolve from fontRef.hangul → fontfaces\n const fontRefAttr =\n cp?.[\"hh:fontRef\"]?.[0]?._attr ?? cp?.[\"hh:FONTREF\"]?.[0]?._attr;\n if (fontRefAttr) {\n const fid = Number(\n fontRefAttr.hangul ?? fontRefAttr.latin ?? fontRefAttr.Hangul ?? 0,\n );\n const name = fontIdMap.get(fid);\n if (name) info.font = safeFont(name);\n }\n\n map.set(id, info);\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\nfunction extractParaPrs(headObj: any): Map<number, ParaPrInfo> {\n const map = new Map<number, ParaPrInfo>();\n try {\n const root =\n headObj?.[\"hh:head\"]?.[0] ??\n headObj?.[\"hh:HEAD\"]?.[0] ??\n headObj?.HEAD?.[0] ??\n headObj;\n const refList =\n root?.[\"hh:refList\"]?.[0] ??\n root?.[\"hh:REFLIST\"]?.[0] ??\n root?.REFLIST?.[0];\n if (!refList) return map;\n\n const ppList =\n refList?.[\"hh:paraProperties\"]?.[0] ??\n refList?.[\"hh:PARAPROPERTIES\"]?.[0];\n if (!ppList) return map;\n\n const pps = getTag(ppList, \"hh:paraPr\", \"hh:PARAPR\");\n for (const pp of pps) {\n const attr = pp?._attr ?? {};\n const id = Number(attr.id ?? -1);\n if (id < 0) continue;\n\n const alignNode =\n pp?.[\"hh:align\"]?.[0]?._attr ?? pp?.[\"hh:ALIGN\"]?.[0]?._attr;\n const align = alignNode?.horizontal ?? alignNode?.Horizontal;\n\n // Read margin and lineSpacing from direct child OR hp:switch > hp:default/hp:case\n let marginEl = pp?.[\"hh:margin\"]?.[0] ?? null;\n let lineSpEl = pp?.[\"hh:lineSpacing\"]?.[0] ?? null;\n if (!marginEl) {\n const sw = pp?.[\"hp:switch\"]?.[0];\n const container = sw?.[\"hp:default\"]?.[0] ?? sw?.[\"hp:case\"]?.[0];\n marginEl = container?.[\"hh:margin\"]?.[0] ?? null;\n lineSpEl = lineSpEl ?? container?.[\"hh:lineSpacing\"]?.[0] ?? null;\n }\n\n let indentPt: number | undefined;\n let indentRightPt: number | undefined;\n let firstLineIndentPt: number | undefined;\n let spaceBefore: number | undefined;\n let spaceAfter: number | undefined;\n let lineHeight: number | undefined;\n let lineHeightFixed: number | undefined;\n\n if (marginEl) {\n // OWPML §7.5.4.4: hc:left=전체왼쪽여백, hc:right=전체오른쪽여백,\n // hc:indent=첫줄들여쓰기(양수)/내어쓰기(음수)\n // hc:intent는 자사 인코더가 생성하는 오기 표기로, hc:indent와 동일하게 처리\n const leftEl = marginEl?.[\"hc:left\"]?.[0];\n const rightEl = marginEl?.[\"hc:right\"]?.[0];\n const indentEl =\n marginEl?.[\"hc:intent\"]?.[0] ?? marginEl?.[\"hc:indent\"]?.[0];\n const prevEl = marginEl?.[\"hc:prev\"]?.[0];\n const nextEl = marginEl?.[\"hc:next\"]?.[0];\n\n const leftVal = Number(leftEl?._attr?.value ?? 0);\n const rightVal = Number(rightEl?._attr?.value ?? 0);\n const indentVal = Number(indentEl?._attr?.value ?? 0);\n const prevVal = Number(prevEl?._attr?.value ?? 0);\n const nextVal = Number(nextEl?._attr?.value ?? 0);\n\n if (leftVal !== 0) indentPt = Metric.hwpToPt(leftVal);\n if (rightVal !== 0) indentRightPt = Metric.hwpToPt(rightVal);\n if (indentVal !== 0) firstLineIndentPt = Metric.hwpToPt(indentVal);\n if (prevVal > 0) spaceBefore = Metric.hwpToPt(prevVal);\n if (nextVal > 0) spaceAfter = Metric.hwpToPt(nextVal);\n }\n\n if (lineSpEl) {\n const lsAttr = lineSpEl._attr ?? {};\n const lsType = lsAttr.type ?? \"PERCENT\";\n const lsVal = Number(lsAttr.value ?? 160);\n // OWPML §7.5.4.6: PERCENT(비율), FIXED(고정), BETWEEN_LINE(줄간격), AT_LEAST(최소)\n if (lsType === \"PERCENT\" && lsVal > 0 && lsVal !== 160) {\n lineHeight = lsVal / 100;\n } else if (lsType === \"FIXED\" && lsVal > 0) {\n // FIXED: 값이 HWPUNIT 단위의 고정 줄 높이\n lineHeightFixed = Metric.hwpToPt(lsVal);\n }\n }\n\n map.set(id, {\n align,\n indentPt,\n indentRightPt,\n firstLineIndentPt,\n spaceBefore,\n spaceAfter,\n lineHeight,\n lineHeightFixed,\n });\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\n// ─── Section decoding ──────────────────────────────────────\n\nfunction addParaItems(p: any, items: { type: string; node: any }[]): void {\n // Check if this paragraph contains a table in its runs\n const runs = getTag(p, \"hp:run\", \"hp:RUN\");\n let hasTable = false;\n for (const run of runs) {\n const tbls = getTag(run, \"hp:tbl\", \"hp:TABLE\");\n if (tbls.length > 0) {\n for (const tbl of tbls) {\n items.push({ type: \"table\", node: tbl });\n }\n hasTable = true;\n }\n }\n // 테이블을 포함한 단락은 일반 단락으로 다시 추가하지 않음 (중복 방지)\n if (!hasTable) {\n items.push({ type: \"para\", node: p });\n }\n}\n\nfunction decodeSection(sec: any, dims: PageDims, ctx: DecCtx) {\n // Try to extract dims from first paragraph's secPr\n const firstParas = getTag(sec, \"hp:p\", \"hp:P\");\n const pageDims = extractSecPrDims(firstParas[0]) ?? dims;\n\n // Build items list preserving document order via _childOrder\n const items: { type: string; node: any }[] = [];\n const paras = getTag(sec, \"hp:p\", \"hp:P\");\n const tbls = getTag(sec, \"hp:tbl\", \"hp:TABLE\");\n\n const childOrder = sec?.[\"_childOrder\"] as string[] | undefined;\n\n if (Array.isArray(childOrder)) {\n let pi = 0;\n let ti = 0;\n for (const tag of childOrder) {\n if ((tag === \"hp:p\" || tag === \"hp:P\") && pi < paras.length) {\n addParaItems(paras[pi++], items);\n } else if ((tag === \"hp:tbl\" || tag === \"hp:TABLE\") && ti < tbls.length) {\n items.push({ type: \"table\", node: tbls[ti++] });\n }\n }\n // Append any remaining (fallback)\n while (pi < paras.length) addParaItems(paras[pi++], items);\n while (ti < tbls.length) items.push({ type: \"table\", node: tbls[ti++] });\n } else {\n // No order info — process paragraphs sequentially (fallback to previous logic)\n for (const p of paras) addParaItems(p, items);\n // Note: direct tables are appended after paras in this fallback\n for (const t of tbls) items.push({ type: \"table\", node: t });\n }\n\n const kids: ContentNode[] = ctx.shield.guardAll(\n items,\n (item: any) => {\n if (item.type === \"table\") {\n try {\n const { value } = ctx.shield.guardGrid(\n item.node,\n (n) => decodeGrid(n, ctx),\n (n) => decodeGridSimple(n, ctx),\n (n) => decodeGridFlat(n),\n (n) => decodeGridText(n) as unknown as GridNode,\n \"hwpx:table\",\n );\n return value;\n } catch {\n return buildPara([buildSpan(\"[표 파싱 실패]\")]);\n }\n }\n return decodePara(item.node, ctx);\n },\n () => buildPara([buildSpan(\"[파싱 실패]\")]),\n \"hwpx:content\",\n );\n\n // Decode header/footer\n const headerParas = decodeHeaderFooter(sec, \"header\", ctx);\n const footerParas = decodeHeaderFooter(sec, \"footer\", ctx);\n\n return buildSheet(kids.filter(Boolean) as ContentNode[], pageDims, {\n headers: { default: headerParas },\n footers: { default: footerParas },\n });\n}\n\nfunction parseSecPrDims(secPr: any): PageDims | null {\n const pagePr =\n secPr?.[\"hp:pagePr\"]?.[0]?._attr ?? secPr?.[\"hp:PAGEPR\"]?.[0]?._attr;\n if (!pagePr) return null;\n const margin =\n secPr?.[\"hp:pagePr\"]?.[0]?.[\"hp:margin\"]?.[0]?._attr ??\n secPr?.[\"hp:PAGEPR\"]?.[0]?.[\"hp:MARGIN\"]?.[0]?._attr ??\n {};\n const pw = Number(pagePr.width ?? 59528);\n const ph = Number(pagePr.height ?? 84188);\n return {\n wPt: Metric.hwpToPt(pw),\n hPt: Metric.hwpToPt(ph),\n mt: Metric.hwpToPt(Number(margin.top ?? 5670)),\n mb: Metric.hwpToPt(Number(margin.bottom ?? 4252)),\n ml: Metric.hwpToPt(Number(margin.left ?? 8504)),\n mr: Metric.hwpToPt(Number(margin.right ?? 8504)),\n orient: pw > ph ? \"landscape\" : \"portrait\",\n };\n}\n\nfunction extractSecPrDims(p: any): PageDims | null {\n if (!p) return null;\n try {\n // Primary: hp:secPr is a DIRECT child of hp:p (as generated by HwpxEncoder)\n const secPrDirect = p?.[\"hp:secPr\"]?.[0] ?? p?.[\"hp:SECPR\"]?.[0];\n if (secPrDirect) {\n const dims = parseSecPrDims(secPrDirect);\n if (dims) return dims;\n }\n // Fallback: legacy format may nest hp:secPr inside hp:run\n const runs = getTag(p, \"hp:run\", \"hp:RUN\");\n for (const run of runs) {\n const secPr = run?.[\"hp:secPr\"]?.[0] ?? run?.[\"hp:SECPR\"]?.[0];\n if (!secPr) continue;\n const dims = parseSecPrDims(secPr);\n if (dims) return dims;\n }\n } catch {\n /* ignore */\n }\n return null;\n}\n\nfunction decodeHeaderFooter(\n sec: any,\n kind: \"header\" | \"footer\",\n ctx: DecCtx,\n): ParaNode[] | undefined {\n try {\n const hf =\n sec?.[\"hp:headerFooter\"]?.[0] ??\n sec?.[\"hp:HEADERFOOTER\"]?.[0] ??\n sec?.headerFooter?.[0] ??\n sec?.HEADERFOOTER?.[0];\n if (!hf) return undefined;\n\n const part =\n hf?.[\"hp:\" + kind]?.[0] ??\n hf?.[\"hp:\" + kind.toUpperCase()]?.[0] ??\n hf?.[kind]?.[0] ??\n hf?.[kind.toUpperCase()]?.[0];\n if (!part) return undefined;\n\n const paras = getTag(part, \"hp:p\", \"hp:P\");\n if (paras.length === 0) return undefined;\n\n return paras.map((p: any) => decodePara(p, ctx));\n } catch {\n return undefined;\n }\n}\n\n// ─── Paragraph & run decoding ──────────────────────────────\n\nfunction decodePara(p: any, ctx: DecCtx): ParaNode {\n const pAttr = p?._attr ?? {};\n const paraPrIdRef = Number(pAttr.paraPrIDRef ?? -1);\n\n // Resolve paraPr from IDRef or inline\n let align: string | undefined;\n const paraPrDef = ctx.paraPrs.get(paraPrIdRef);\n if (paraPrDef?.align) align = paraPrDef.align;\n\n // Check inline PARAPR too\n const inlineParaPr =\n p?.[\"hp:PARAPR\"]?.[0] ?? p?.[\"hp:paraPr\"]?.[0] ?? p?.PARAPR?.[0];\n if (inlineParaPr) {\n const alignNode =\n inlineParaPr?.[\"hp:ALIGN\"]?.[0]?._attr ??\n inlineParaPr?.[\"hp:align\"]?.[0]?._attr ??\n inlineParaPr?.ALIGN?.[0]?._attr;\n if (alignNode?.Type) align = alignNode.Type;\n if (alignNode?.horizontal) align = alignNode.horizontal;\n }\n\n const inlineAttr = inlineParaPr?._attr ?? {};\n const props: ParaProps = { align: safeAlign(align) };\n\n // Apply spacing/indent/lineHeight from paraPr definition\n if (paraPrDef) {\n if (paraPrDef.indentPt !== undefined) props.indentPt = paraPrDef.indentPt;\n if (paraPrDef.indentRightPt !== undefined)\n props.indentRightPt = paraPrDef.indentRightPt;\n if (paraPrDef.firstLineIndentPt !== undefined)\n props.firstLineIndentPt = paraPrDef.firstLineIndentPt;\n if (paraPrDef.spaceBefore !== undefined)\n props.spaceBefore = paraPrDef.spaceBefore;\n if (paraPrDef.spaceAfter !== undefined)\n props.spaceAfter = paraPrDef.spaceAfter;\n if (paraPrDef.lineHeight !== undefined)\n props.lineHeight = paraPrDef.lineHeight;\n if (paraPrDef.lineHeightFixed !== undefined)\n props.lineHeightFixed = paraPrDef.lineHeightFixed;\n }\n\n // List support (from inline attr)\n if (inlineAttr.listType) {\n props.listOrd =\n inlineAttr.listType === \"DIGIT\" || inlineAttr.listType === \"DECIMAL\";\n props.listLv = Number(inlineAttr.listLevel ?? 0);\n }\n\n const runs = getTag(p, \"hp:run\", \"hp:RUN\");\n const kids: (SpanNode | ImgNode)[] = [];\n\n // Helper: collect hp:pic elements from a container (direct child OR inside hp:ctrl)\n const collectPics = (container: any): any[] => {\n const direct = getTag(container, \"hp:pic\", \"hp:PIC\");\n const ctrls = getTag(container, \"hp:ctrl\", \"hp:CTRL\");\n const nested = ctrls.flatMap((c: any) => getTag(c, \"hp:pic\", \"hp:PIC\"));\n return [...direct, ...nested];\n };\n\n // Images that are direct children of <hp:p> (common in table cells and floats)\n for (const pic of collectPics(p)) {\n const img = decodePic(pic, ctx);\n if (img) kids.push(img);\n }\n\n for (const run of runs) {\n // Images: directly in run OR in run→ctrl (both patterns appear in practice)\n for (const pic of collectPics(run)) {\n const img = decodePic(pic, ctx);\n if (img) kids.push(img);\n }\n\n // Page number\n const pageNums = getTag(run, \"hp:pageNum\", \"hp:PAGENUM\");\n if (pageNums.length > 0) {\n const pn = pageNums[0]?._attr ?? {};\n const fmt =\n pn.formatType === \"ROMAN_LOWER\"\n ? (\"roman\" as const)\n : pn.formatType === \"ROMAN_UPPER\"\n ? (\"romanCaps\" as const)\n : (\"decimal\" as const);\n const pageNumNode: PageNumNode = { tag: \"pagenum\", format: fmt };\n const spanProps = resolveCharPr(run, ctx);\n kids.push({ tag: \"span\", props: spanProps, kids: [pageNumNode] });\n continue;\n }\n\n // Text\n const runPics = collectPics(run);\n const textNodes = getTag(run, \"hp:t\", \"hp:T\", \"hp:CHAR\");\n const content = textNodes\n .map((t: any) => {\n const val =\n typeof t === \"string\" ? t : (t?._text ?? t?._ ?? t?.[\"#text\"] ?? \"\");\n return val.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n })\n .join(\"\");\n\n // Skip empty secPr-only runs that produced no images\n if (\n content === \"\" &&\n (run?.[\"hp:secPr\"]?.[0] || run?.[\"hp:SECPR\"]?.[0]) &&\n runPics.length === 0 &&\n pageNums.length === 0\n )\n continue;\n\n // Only push text span when there's actual content and no image already pushed for this run\n if (content !== \"\" || (runPics.length === 0 && pageNums.length === 0)) {\n const spanProps = resolveCharPr(run, ctx);\n kids.push(buildSpan(content, spanProps));\n }\n }\n\n // pageBreak=\"1\" → prepend a pb node in its own span\n if (pAttr.pageBreak === \"1\") {\n kids.unshift({ tag: \"span\", props: {}, kids: [buildPb()] });\n }\n\n return buildPara(kids.filter(Boolean) as ParaNode[\"kids\"], props);\n}\n\nfunction resolveCharPr(run: any, ctx: DecCtx): TextProps {\n const runAttr = run?._attr ?? {};\n const charPrIdRef = Number(runAttr.charPrIDRef ?? runAttr.CharPrIDRef ?? -1);\n\n // IDRef로 먼저 조회\n const def = ctx.charPrs.get(charPrIdRef);\n if (def) {\n return {\n b: def.b,\n i: def.i,\n u: def.u,\n s: def.s,\n pt: def.pt,\n color: def.color,\n font: def.font,\n bg: def.bg,\n };\n }\n\n // 인라인 CHARPR fallback — 대소문자 모두 시도\n const inlinePr =\n run?.[\"hp:CHARPR\"]?.[0] ??\n run?.[\"hp:charPr\"]?.[0] ??\n run?.CHARPR?.[0] ??\n run?.charPr?.[0];\n const ca = inlinePr?._attr ?? {};\n\n const bVal = ca.Bold ?? ca.bold ?? ca.B ?? \"\";\n const iVal = ca.Italic ?? ca.italic ?? ca.I ?? \"\";\n const uVal = ca.Underline ?? ca.underline ?? \"\";\n const sVal = ca.Strikeout ?? ca.strikeout ?? \"\";\n const fontName =\n ca.FontName ?? ca.fontName ?? ca.FaceNameHangul ?? ca.faceNameHangul ?? \"\";\n const heightVal = ca.Height ?? ca.height ?? \"\";\n\n return {\n b: bVal === \"1\" || bVal === \"true\" || bVal === \"True\" || undefined,\n i: iVal === \"1\" || iVal === \"true\" || iVal === \"True\" || undefined,\n u: uVal && uVal !== \"NONE\" ? true : undefined,\n s: sVal && sVal !== \"NONE\" && sVal !== \"3D\" ? true : undefined,\n font: fontName ? safeFont(fontName) : undefined,\n pt: heightVal ? Metric.hHeightToPt(Number(heightVal)) : undefined,\n color: safeHex(ca.TextColor ?? ca.textColor),\n bg: safeHex(ca.BgColor ?? ca.bgColor),\n };\n}\n\n// ─── Image decoding ────────────────────────────────────────\n\nfunction decodePic(pic: any, ctx: DecCtx): ImgNode | null {\n try {\n const szAttr = pic?.[\"hp:sz\"]?.[0]?._attr ?? pic?.sz?.[0]?._attr ?? {};\n const w = Metric.hwpToPt(Number(szAttr.width ?? 0));\n const h = Metric.hwpToPt(Number(szAttr.height ?? 0));\n\n // Try multiple tag patterns for image reference\n const imgNode =\n pic?.[\"hp:img\"]?.[0]?._attr ??\n pic?.[\"hc:img\"]?.[0]?._attr ??\n pic?.img?.[0]?._attr ??\n {};\n const binRef = imgNode.binaryItemIDRef ?? imgNode.BinaryItemIDRef;\n if (!binRef) return null;\n\n // Find binary data\n let imgData: Uint8Array | undefined;\n for (const [key, val] of ctx.files) {\n if (\n key.includes(binRef) ||\n key.toLowerCase().includes(binRef.toLowerCase())\n ) {\n imgData = val;\n break;\n }\n }\n if (!imgData) return null;\n\n const ext = binRef.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const mimeMap: Record<string, ImgNode[\"mime\"]> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n bmp: \"image/bmp\",\n };\n\n // ── hp:pos에서 layout 추출 ───────────────────────────────\n const posAttr = pic?.[\"hp:pos\"]?.[0]?._attr ?? pic?.pos?.[0]?._attr ?? {};\n const layout = extractHwpxLayout(posAttr, pic);\n\n return buildImg(\n TextKit.base64Encode(imgData),\n mimeMap[ext] ?? \"image/png\",\n w,\n h,\n undefined,\n layout,\n );\n } catch {\n return null;\n }\n}\n\nfunction extractHwpxLayout(posAttr: any, pic: any): ImgLayout {\n const treatAsChar =\n posAttr.treatAsChar === \"1\" || posAttr.treatAsChar === \"true\";\n if (treatAsChar) return { wrap: \"inline\" };\n\n // textWrap → wrap (direct attribute of hp:pic element)\n const textWrap: string =\n pic?._attr?.textWrap ?? pic?.pic?.[0]?._attr?.textWrap ?? \"TOP_AND_BOTTOM\";\n // OWPML §7.5.8.1 textWrap → ImgWrap 매핑\n // TOP_AND_BOTTOM: 텍스트가 이미지 위아래로만 흐름 → DOCX wrapTopAndBottom (float anchor)\n const wrapMap: Record<string, ImgWrap> = {\n TOP_AND_BOTTOM: \"topAndBottom\", // float, 위아래 텍스트 흐름\n SQUARE: \"square\",\n BOTH_SIDES: \"tight\",\n LEFT: \"tight\",\n RIGHT: \"tight\",\n LARGER_ONLY: \"tight\",\n SMALLER_ONLY: \"tight\",\n LARGEST_ONLY: \"tight\",\n BEHIND_TEXT: \"behind\",\n FRONT_TEXT: \"front\",\n };\n const wrap: ImgWrap = wrapMap[textWrap] ?? \"square\";\n\n // 기준점\n const horzRelToMap: Record<string, ImgHorzRelTo> = {\n PARA: \"para\",\n MARGIN: \"margin\",\n PAGE: \"page\",\n COLUMN: \"column\",\n };\n const vertRelToMap: Record<string, ImgVertRelTo> = {\n PARA: \"para\",\n MARGIN: \"margin\",\n PAGE: \"page\",\n PAPER: \"page\",\n LINE: \"line\",\n };\n const horzRelTo = horzRelToMap[posAttr.horzRelTo ?? \"\"] ?? \"para\";\n const vertRelTo = vertRelToMap[posAttr.vertRelTo ?? \"\"] ?? \"para\";\n\n // 정렬\n const horzAlignMap: Record<string, ImgHorzAlign> = {\n LEFT: \"left\",\n CENTER: \"center\",\n RIGHT: \"right\",\n };\n const vertAlignMap: Record<string, ImgVertAlign> = {\n TOP: \"top\",\n CENTER: \"center\",\n BOTTOM: \"bottom\",\n };\n const horzAlign = horzAlignMap[posAttr.horzAlign ?? \"\"];\n const vertAlign = vertAlignMap[posAttr.vertAlign ?? \"\"];\n\n // 오프셋\n const horzOffset = Number(posAttr.horzOffset ?? 0);\n const vertOffset = Number(posAttr.vertOffset ?? 0);\n const xPt = horzOffset !== 0 ? Metric.hwpToPt(horzOffset) : undefined;\n const yPt = vertOffset !== 0 ? Metric.hwpToPt(vertOffset) : undefined;\n\n return { wrap, horzAlign, vertAlign, horzRelTo, vertRelTo, xPt, yPt };\n}\n\n// ─── Table decoding ────────────────────────────────────────\n\nfunction decodeGrid(tbl: any, ctx: DecCtx): GridNode {\n const tblAttr = tbl?._attr ?? {};\n const borderFillId = Number(tblAttr.borderFillIDRef ?? 0);\n const borderFill = ctx.borderFills.get(borderFillId);\n const headerRow = tblAttr.repeatHeader === \"1\";\n\n const gridProps: GridProps = { headerRow: headerRow || undefined };\n if (borderFill?.stroke) gridProps.defaultStroke = borderFill.stroke;\n\n // 표 정렬 — <hp:pos horzAlign=\"...\"> 에서 읽음 (OWPML CAbstractShapeObjectType)\n const posAttr = tbl?.[\"hp:pos\"]?.[0]?._attr ?? {};\n if (posAttr.horzAlign) {\n const alignMap: Record<string, \"left\" | \"right\" | \"center\" | \"justify\"> = {\n LEFT: \"left\", RIGHT: \"right\", CENTER: \"center\", JUSTIFY: \"justify\",\n };\n const a = alignMap[posAttr.horzAlign];\n if (a) gridProps.align = a;\n }\n\n const rowArr = getTag(tbl, \"hp:tr\", \"hp:ROW\");\n\n // Read column widths: first try a row where ALL cells have cs=1\n for (const row of rowArr) {\n const cells = getTag(row, \"hp:tc\", \"hp:CELL\");\n const rowWidths: number[] = [];\n let allSingle = true;\n for (const cell of cells) {\n const cellSpanAttr = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n const cs = Number(cellSpanAttr.colSpan ?? cell?._attr?.ColSpan ?? 1);\n if (cs > 1) {\n allSingle = false;\n break;\n }\n const szAttr = cell?.[\"hp:cellSz\"]?.[0]?._attr ?? {};\n const w = Number(szAttr.width ?? 0);\n rowWidths.push(Metric.hwpToPt(w));\n }\n if (allSingle && rowWidths.length > 0 && rowWidths.some((w) => w > 0)) {\n gridProps.colWidths = rowWidths;\n break;\n }\n }\n\n // Fallback: proportional distribution when no all-single row exists\n if (!gridProps.colWidths) {\n // Determine colCount first: max column index reached across all rows\n let detectedCols = 0;\n for (const row of rowArr) {\n let ci = 0;\n for (const cell of getTag(row, \"hp:tc\", \"hp:CELL\")) {\n const csEl = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n ci += Number(csEl.colSpan ?? cell?._attr?.ColSpan ?? 1);\n }\n if (ci > detectedCols) detectedCols = ci;\n }\n if (detectedCols > 0) {\n const sums = new Float64Array(detectedCols);\n const counts = new Int32Array(detectedCols);\n for (const row of rowArr) {\n let ci = 0;\n for (const cell of getTag(row, \"hp:tc\", \"hp:CELL\")) {\n const csEl = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n const cs = Number(csEl.colSpan ?? cell?._attr?.ColSpan ?? 1);\n const szAttr = cell?.[\"hp:cellSz\"]?.[0]?._attr ?? {};\n const w = Number(szAttr.width ?? 0);\n if (w > 0 && cs > 0) {\n const perCol = w / cs;\n for (let k = 0; k < cs && ci + k < detectedCols; k++) {\n sums[ci + k] += perCol;\n counts[ci + k]++;\n }\n }\n ci += cs;\n }\n }\n const estimated = Array.from(sums).map((s, i) =>\n counts[i] > 0 ? Metric.hwpToPt(s / counts[i]) : 0,\n );\n if (estimated.some((w) => w > 0)) gridProps.colWidths = estimated;\n }\n }\n const rowNodes = rowArr.map((row: any) => {\n const cellArr = getTag(row, \"hp:tc\", \"hp:CELL\");\n const cellNodes = cellArr.map((cell: any) => {\n const ca = cell?._attr ?? {};\n\n // Cell borderFill\n const cellBfId = Number(ca.borderFillIDRef ?? 0);\n const cellBf = ctx.borderFills.get(cellBfId);\n\n const cellProps: CellProps = {\n bg: cellBf?.bgColor ?? safeHex(ca.BgColor),\n };\n\n if (cellBf) {\n // Preserve explicit NONE so it overrides table-level defaultStroke in DOCX tcBorders.\n // Only skip when the side is truly undefined (not specified in borderFill).\n cellProps.top = cellBf.top ?? cellBf.stroke;\n cellProps.bot = cellBf.bottom ?? cellBf.stroke;\n cellProps.left = cellBf.left ?? cellBf.stroke;\n cellProps.right = cellBf.right ?? cellBf.stroke;\n }\n\n // 수직 정렬 — <hp:subList vertAlign=\"...\"> (OWPML CParaListType::GetVertAlign)\n const subList = cell?.[\"hp:subList\"]?.[0] ?? cell?.subList?.[0];\n const subAttr = subList?._attr ?? {};\n if (subAttr.vertAlign) {\n const vaMap: Record<string, \"top\" | \"mid\" | \"bot\"> = {\n TOP: \"top\",\n CENTER: \"mid\",\n BOTTOM: \"bot\",\n };\n cellProps.va = vaMap[subAttr.vertAlign];\n }\n // 셀 여백 — <hp:cellMargin left/right/top/bottom> (OWPML CTc::SetcellMargin)\n // subList 속성이 아닌 <hp:cellMargin> 자식 요소에서 읽어야 함\n const cellMarginAttr =\n cell?.[\"hp:cellMargin\"]?.[0]?._attr ?? {};\n const mL = cellMarginAttr.left !== undefined ? Number(cellMarginAttr.left) : -1;\n const mR = cellMarginAttr.right !== undefined ? Number(cellMarginAttr.right) : -1;\n const mT = cellMarginAttr.top !== undefined ? Number(cellMarginAttr.top) : -1;\n const mB = cellMarginAttr.bottom !== undefined ? Number(cellMarginAttr.bottom) : -1;\n if (mL >= 0) cellProps.padL = Metric.hwpToPt(mL);\n if (mR >= 0) cellProps.padR = Metric.hwpToPt(mR);\n if (mT >= 0) cellProps.padT = Metric.hwpToPt(mT);\n if (mB >= 0) cellProps.padB = Metric.hwpToPt(mB);\n\n // Colspan/rowspan from cellSpan element or attributes\n const cellSpan = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n const cs = Number(cellSpan.colSpan ?? ca.ColSpan ?? 1);\n const rs = Number(cellSpan.rowSpan ?? ca.RowSpan ?? 1);\n\n // Parse cell content — paragraphs and nested tables (중첩 표)\n const cellKids: (ParaNode | GridNode)[] = [];\n const source = subList ?? cell;\n const sourcePSource = getTag(source, \"hp:p\", \"hp:P\");\n for (const sp of sourcePSource) {\n try {\n // Check if this paragraph contains a nested table in its runs\n const runs = getTag(sp, \"hp:run\", \"hp:RUN\");\n let hasNestedTable = false;\n for (const run of runs) {\n const nestedTbls = getTag(run, \"hp:tbl\", \"hp:TABLE\");\n for (const nestedTbl of nestedTbls) {\n try {\n cellKids.push(decodeGrid(nestedTbl, ctx));\n } catch {\n /* skip malformed nested table */\n }\n hasNestedTable = true;\n }\n }\n if (!hasNestedTable) {\n cellKids.push(decodePara(sp, ctx));\n }\n } catch {\n /* skip corrupted para in cell */\n }\n }\n\n return buildCell(\n cellKids.length > 0 ? cellKids : [buildPara([buildSpan(\"\")])],\n { cs, rs, props: cellProps },\n );\n });\n // Row height: prefer a non-merged cell (rs=1) for accuracy.\n // For merged cells, divide total height by rowSpan to get per-row height.\n let rowHeightPt: number | undefined;\n for (const cell of cellArr) {\n const ca = cell?._attr ?? {};\n const cellSpan = cell?.[\"hp:cellSpan\"]?.[0]?._attr ?? {};\n const cellRs = Math.max(1, Number(cellSpan.rowSpan ?? ca.RowSpan ?? 1));\n const hSz = cell?.[\"hp:cellSz\"]?.[0]?._attr ?? {};\n const hVal = Number(hSz.height ?? 0);\n if (hVal > 0) {\n rowHeightPt = Metric.hwpToPt(hVal) / cellRs;\n if (cellRs === 1) break; // exact match — stop searching\n }\n }\n return buildRow(cellNodes, rowHeightPt);\n });\n return buildGrid(rowNodes, gridProps);\n}\n\nfunction decodeGridSimple(tbl: any, ctx: DecCtx): GridNode {\n const rowArr = getTag(tbl, \"hp:tr\", \"hp:ROW\");\n const rowNodes = rowArr.map((row: any) => {\n const cellArr = getTag(row, \"hp:tc\", \"hp:CELL\");\n return buildRow(\n cellArr.map((cell: any) =>\n buildCell([buildPara([buildSpan(cellText(cell))])]),\n ),\n );\n });\n return buildGrid(rowNodes);\n}\n\nfunction decodeGridFlat(tbl: any): GridNode {\n return buildGrid([\n buildRow([buildCell([buildPara([buildSpan(tableText(tbl))])])]),\n ]);\n}\n\nfunction decodeGridText(tbl: any): ParaNode {\n return buildPara([buildSpan(tableText(tbl))]);\n}\n\nfunction cellText(cell: any): string {\n const subList = cell?.[\"hp:subList\"]?.[0] ?? cell?.subList?.[0];\n const source = subList ?? cell;\n return getTag(source, \"hp:p\", \"hp:P\")\n .map((p: any) =>\n getTag(p, \"hp:run\", \"hp:RUN\")\n .map((r: any) =>\n getTag(r, \"hp:t\", \"hp:T\")\n .map((t: any) => {\n const val =\n typeof t === \"string\"\n ? t\n : (t?._text ?? t?._ ?? t?.[\"#text\"] ?? \"\");\n return val.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n })\n .join(\"\"),\n )\n .join(\"\"),\n )\n .join(\" \");\n}\n\nfunction tableText(tbl: any): string {\n return getTag(tbl, \"hp:tr\", \"hp:ROW\")\n .map((row: any) =>\n getTag(row, \"hp:tc\", \"hp:CELL\")\n .map((c: any) => cellText(c))\n .join(\"\\t\"),\n )\n .join(\"\\n\");\n}\n\nfunction toArr(v: any): any[] {\n return v == null ? [] : Array.isArray(v) ? v : [v];\n}\n\n// Auto-register\nregistry.registerDecoder(new HwpxDecoder());\n","/**\n * OLE2 Compound File Binary Format (CFB) parser.\n * Used for legacy HWP 5.0 files.\n */\n\nexport const BinaryKit = {\n readU16LE(buf: Uint8Array, offset: number): number {\n return buf[offset] | (buf[offset + 1] << 8);\n },\n\n readU32LE(buf: Uint8Array, offset: number): number {\n return (\n (buf[offset] | (buf[offset + 1] << 8) | (buf[offset + 2] << 16)) >>> 0\n ) + buf[offset + 3] * 0x1000000;\n },\n\n isOle2(data: Uint8Array): boolean {\n return (\n data.length >= 8 &&\n data[0] === 0xD0 && data[1] === 0xCF &&\n data[2] === 0x11 && data[3] === 0xE0 &&\n data[4] === 0xA1 && data[5] === 0xB1 &&\n data[6] === 0x1A && data[7] === 0xE1\n );\n },\n\n parseCfb(data: Uint8Array): Map<string, Uint8Array> {\n const streams = new Map<string, Uint8Array>();\n\n if (!this.isOle2(data)) {\n throw new Error('Not a valid OLE2 file');\n }\n\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const sectorSize = 1 << view.getUint16(30, true);\n const miniSectorSz = 1 << view.getUint16(32, true);\n const dirFirstSec = view.getUint32(48, true);\n const miniStreamCutoff = view.getUint32(56, true);\n const miniFatFirst = view.getUint32(60, true);\n const miniFatCnt = view.getUint32(64, true);\n const difatFirst = view.getUint32(68, true);\n\n const ENDOFCHAIN = 0xFFFFFFFE;\n const FREESECT = 0xFFFFFFFF;\n\n const sectorAt = (sec: number): Uint8Array =>\n data.subarray(512 + sec * sectorSize, 512 + (sec + 1) * sectorSize);\n\n // Build FAT from DIFAT\n const fatSecNums: number[] = [];\n for (let i = 0; i < 109; i++) {\n const s = view.getUint32(76 + i * 4, true);\n if (s === FREESECT || s === ENDOFCHAIN) break;\n fatSecNums.push(s);\n }\n if (difatFirst !== ENDOFCHAIN && difatFirst !== FREESECT) {\n let difSec = difatFirst;\n while (difSec !== ENDOFCHAIN && difSec !== FREESECT) {\n const sec = sectorAt(difSec);\n const sv = new DataView(sec.buffer, sec.byteOffset, sec.byteLength);\n for (let i = 0; i < (sectorSize / 4) - 1; i++) {\n const s = sv.getUint32(i * 4, true);\n if (s === FREESECT || s === ENDOFCHAIN) break;\n fatSecNums.push(s);\n }\n difSec = sv.getUint32(sectorSize - 4, true);\n }\n }\n\n const fat: number[] = [];\n for (const sec of fatSecNums) {\n const s = sectorAt(sec);\n const sv = new DataView(s.buffer, s.byteOffset, s.byteLength);\n for (let i = 0; i < sectorSize / 4; i++) {\n fat.push(sv.getUint32(i * 4, true));\n }\n }\n\n const readChain = (startSec: number): Uint8Array => {\n const chunks: Uint8Array[] = [];\n let sec = startSec;\n while (sec !== ENDOFCHAIN && sec !== FREESECT && sec < fat.length) {\n chunks.push(sectorAt(sec));\n sec = fat[sec];\n }\n return concatUint8(chunks);\n };\n\n // Directory entries\n const dirData = readChain(dirFirstSec);\n const dirView = new DataView(dirData.buffer, dirData.byteOffset, dirData.byteLength);\n const dirCount = dirData.length / 128;\n\n interface DirEntry {\n name: string;\n type: number;\n startSec: number;\n size: number;\n childId: number;\n siblingLeftId: number;\n siblingRightId: number;\n }\n\n const dirEntries: DirEntry[] = [];\n for (let i = 0; i < dirCount; i++) {\n const base = i * 128;\n const nameLen = dirView.getUint16(base + 64, true);\n const nameBytes = dirData.subarray(base, base + Math.max(0, nameLen - 2));\n const name = new TextDecoder('utf-16le').decode(nameBytes);\n const type = dirData[base + 66];\n const childId = dirView.getInt32(base + 76, true);\n const sibLeft = dirView.getInt32(base + 68, true);\n const sibRight = dirView.getInt32(base + 72, true);\n const startSec = dirView.getUint32(base + 116, true);\n const size = dirView.getUint32(base + 120, true);\n dirEntries.push({ name, type, startSec, size, childId, siblingLeftId: sibLeft, siblingRightId: sibRight });\n }\n\n // Mini stream\n const rootEntry = dirEntries[0];\n let miniStreamData: Uint8Array | null = null;\n let miniFat: number[] = [];\n\n if (rootEntry && rootEntry.startSec !== ENDOFCHAIN && rootEntry.startSec !== FREESECT) {\n miniStreamData = readChain(rootEntry.startSec);\n }\n\n if (miniFatCnt > 0 && miniFatFirst !== ENDOFCHAIN && miniFatFirst !== FREESECT) {\n const mfData = readChain(miniFatFirst);\n const mfv = new DataView(mfData.buffer, mfData.byteOffset, mfData.byteLength);\n for (let i = 0; i < mfData.length / 4; i++) {\n miniFat.push(mfv.getUint32(i * 4, true));\n }\n }\n\n const readMiniChain = (startSec: number, size: number): Uint8Array => {\n if (!miniStreamData) return new Uint8Array(0);\n const chunks: Uint8Array[] = [];\n let sec = startSec;\n let remaining = size;\n while (sec !== ENDOFCHAIN && sec !== FREESECT && sec < miniFat.length && remaining > 0) {\n const off = sec * miniSectorSz;\n const chunk = miniStreamData.subarray(off, off + Math.min(miniSectorSz, remaining));\n chunks.push(chunk);\n remaining -= chunk.length;\n sec = miniFat[sec];\n }\n return concatUint8(chunks).subarray(0, size);\n };\n\n // DFS traversal\n const visit = (id: number, path: string): void => {\n if (id < 0 || id >= dirEntries.length) return;\n const entry = dirEntries[id];\n const fullPath = path ? `${path}/${entry.name}` : entry.name;\n\n if (entry.type === 2) {\n let streamData: Uint8Array;\n if (entry.size < miniStreamCutoff && miniStreamData) {\n streamData = readMiniChain(entry.startSec, entry.size);\n } else {\n streamData = readChain(entry.startSec).subarray(0, entry.size);\n }\n streams.set(fullPath, streamData);\n streams.set(entry.name, streamData);\n }\n\n if (entry.childId >= 0) visit(entry.childId, fullPath);\n if (entry.siblingLeftId >= 0) visit(entry.siblingLeftId, path);\n if (entry.siblingRightId >= 0) visit(entry.siblingRightId, path);\n };\n\n if (dirEntries.length > 0 && dirEntries[0].childId >= 0) {\n visit(dirEntries[0].childId, '');\n }\n\n return streams;\n },\n};\n\nfunction concatUint8(arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((s, a) => s + a.length, 0);\n const out = new Uint8Array(total);\n let off = 0;\n for (const a of arrays) { out.set(a, off); off += a.length; }\n return out;\n}\n","import type { Decoder } from '../../contract/decoder';\nimport type { DocRoot, ContentNode, ParaNode, SpanNode, ImgNode, GridNode, PageNumNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport type { Align, Stroke, StrokeKind, PageDims, TextProps, ParaProps, CellProps, GridProps } from '../../model/doc-props';\nimport { succeed, fail } from '../../contract/result';\nimport { buildRoot, buildSheet, buildPara, buildSpan, buildGrid, buildRow, buildCell, buildImg, buildPb, buildPageNum } from '../../model/builders';\nimport { ShieldedParser } from '../../safety/ShieldedParser';\nimport { BinaryKit } from '../../toolkit/BinaryKit';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { Metric, safeHex, safeFont } from '../../safety/StyleBridge';\nimport { registry } from '../../pipeline/registry';\nimport { A4 } from '../../model/doc-props';\nimport pako from 'pako';\n\n/* ═══════════════════════════════════════════════════════════════\n HWP 5.0 Tag Constants\n ═══════════════════════════════════════════════════════════════ */\n\nconst HWPTAG_BEGIN = 16;\n\nconst TAG_FACE_NAME = HWPTAG_BEGIN + 3; // 19\nconst TAG_BORDER_FILL = HWPTAG_BEGIN + 4; // 20\nconst TAG_CHAR_SHAPE = HWPTAG_BEGIN + 5; // 21\nconst TAG_PARA_SHAPE = HWPTAG_BEGIN + 9; // 25\nconst TAG_PARA_HEADER = HWPTAG_BEGIN + 50; // 66\nconst TAG_PARA_TEXT = HWPTAG_BEGIN + 51; // 67\nconst TAG_PARA_CHAR_SHAPE = HWPTAG_BEGIN + 52; // 68\nconst TAG_CTRL_HEADER = HWPTAG_BEGIN + 55; // 71\nconst TAG_PAGE_DEF = HWPTAG_BEGIN + 57; // 73\n\n// TABLE / CELL tags vary by HWP version\nconst TAG_LIST_HEADER = HWPTAG_BEGIN + 56; // 72\nconst TAG_TABLE_A = HWPTAG_BEGIN + 61; // 77\nconst TAG_CELL_A = HWPTAG_BEGIN + 62; // 78\nconst TAG_TABLE_B = HWPTAG_BEGIN + 64; // 80\nconst TAG_CELL_B = HWPTAG_BEGIN + 65; // 81\n\nfunction isTableTag(t: number) { return t === TAG_TABLE_A || t === TAG_TABLE_B; }\nfunction isCellTag(t: number) { return t === TAG_CELL_A || t === TAG_CELL_B || t === TAG_LIST_HEADER; }\n\n// CTRL_HEADER ctrlId values (UINT32-LE as ASCII)\nconst CTRL_TABLE = 0x74626C20; // 'tbl ' = 표(table)\nconst CTRL_IMAGE = 0x696D6720; // 'img '\nconst CTRL_OBJ = 0x6F626A20; // 'obj '\nconst CTRL_FIG = 0x66696720; // 'fig '\nconst CTRL_GSO = 0x67736F20; // 'gso ' = 그리기 객체 (drawing object, contains embedded images)\nconst CTRL_HEAD = 0x68656164; // 'head' = 머리말\nconst CTRL_FOOT = 0x666F6F74; // 'foot' = 꼬리말\nconst CTRL_ATNO = 0x61746E6F; // 'atno' = 자동 번호 (쪽번호 등)\n\n/* ═══════════════════════════════════════════════════════════════\n Types\n ═══════════════════════════════════════════════════════════════ */\n\ninterface HwpRecord {\n tag: number;\n level: number;\n data: Uint8Array;\n}\n\ninterface HwpCharShape {\n faceIds: number[];\n height: number;\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikeout: boolean;\n superscript: boolean;\n subscript: boolean;\n textColor: string;\n}\ninterface HwpParaShape {\n align: Align;\n spaceBefore: number;\n spaceAfter: number;\n lineSpacing: number;\n lineSpacingType: 0 | 1 | 2 | 3; // 0=PERCENT, 1=FIXED, 2=BETWEEN_LINES, 3=AT_LEAST\n leftMargin: number;\n rightMargin: number;\n indent: number;\n verAlign?: 'baseline' | 'top' | 'center' | 'bottom';\n lineWrap?: 'break' | 'squeeze' | 'keep';\n}\ninterface HwpBorderFill {\n borders: { type: number; widthPt: number; color: string }[];\n bgColor?: string;\n}\n\ninterface DocInfo {\n faceNames: string[];\n charShapes: HwpCharShape[];\n paraShapes: HwpParaShape[];\n borderFills: HwpBorderFill[];\n}\n\ninterface ParsedChar { pos: number; ch: string }\ninterface ParsedCtrl { pos: number; ctrlId: number; objId: number; matched: boolean }\ninterface ParaTextResult { chars: ParsedChar[]; controls: ParsedCtrl[] }\n\ninterface OleObject {\n id: number;\n data: Uint8Array;\n mimeType: string;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Low-level record parsing\n ═══════════════════════════════════════════════════════════════ */\n\nfunction parseRecords(data: Uint8Array): HwpRecord[] {\n const out: HwpRecord[] = [];\n let off = 0;\n while (off + 4 <= data.length) {\n const hdr = BinaryKit.readU32LE(data, off);\n const tag = hdr & 0x3FF;\n const level = (hdr >> 10) & 0x3FF;\n let size = (hdr >> 20) & 0xFFF;\n off += 4;\n if (size === 0xFFF) {\n if (off + 4 > data.length) break;\n size = BinaryKit.readU32LE(data, off);\n off += 4;\n }\n if (off + size > data.length) break;\n out.push({ tag, level, data: data.subarray(off, off + size) });\n off += size;\n }\n return out;\n}\n\nfunction tryInflate(data: Uint8Array): Uint8Array {\n try { return pako.inflate(data); } catch {\n try { return pako.inflateRaw(data); } catch { return data; }\n }\n}\n\n/* ═══════════════════════════════════════════════════════════════\n FileHeader\n ═══════════════════════════════════════════════════════════════ */\n\nfunction parseFileHeader(buf: Uint8Array) {\n if (buf.length < 40) return { compressed: true, encrypted: false };\n const props = BinaryKit.readU32LE(buf, 36);\n return { compressed: (props & 1) !== 0, encrypted: (props & 2) !== 0 };\n}\n\n/* ═══════════════════════════════════════════════════════════════\n DocInfo parsing\n ═══════════════════════════════════════════════════════════════ */\n\nfunction parseDocInfo(data: Uint8Array, compressed: boolean): DocInfo {\n const raw = compressed ? tryInflate(data) : data;\n const recs = parseRecords(raw);\n const info: DocInfo = { faceNames: [], charShapes: [], paraShapes: [], borderFills: [] };\n\n for (const r of recs) {\n try {\n if (r.tag === TAG_FACE_NAME) info.faceNames.push(parseFaceName(r.data));\n if (r.tag === TAG_CHAR_SHAPE) info.charShapes.push(parseCharShape(r.data));\n if (r.tag === TAG_PARA_SHAPE) info.paraShapes.push(parseParaShape(r.data));\n if (r.tag === TAG_BORDER_FILL) info.borderFills.push(parseBorderFill(r.data));\n } catch { /* skip malformed record */ }\n }\n return info;\n}\n\n/* ── FACE_NAME ──────────────────────────────────────────────── */\n\nfunction parseFaceName(d: Uint8Array): string {\n if (d.length < 3) return '';\n const len = BinaryKit.readU16LE(d, 1); // UTF-16 char count\n if (d.length < 3 + len * 2) return '';\n return new TextDecoder('utf-16le').decode(d.subarray(3, 3 + len * 2));\n}\n\n/* ── CHAR_SHAPE ─────────────────────────────────────────────── */\n/* offset size field\n 0 14 faceId[7] (UINT16 × 7)\n 14 7 ratio[7]\n 21 7 spacing[7]\n 28 7 relSize[7]\n 35 7 offset[7]\n 42 4 height (UINT32, HWP-units 100 = 1pt)\n 46 4 attr (UINT32, bit flags)\n 50 1 shadowX\n 51 1 shadowY\n 52 4 textColor (COLORREF R,G,B,0) */\n\nfunction parseCharShape(d: Uint8Array): HwpCharShape {\n const faceIds: number[] = [];\n for (let i = 0; i < 7; i++) faceIds.push(d.length >= (i + 1) * 2 ? BinaryKit.readU16LE(d, i * 2) : 0);\n\n const height = d.length >= 46 ? BinaryKit.readU32LE(d, 42) : 1000;\n const attr = d.length >= 50 ? BinaryKit.readU32LE(d, 46) : 0;\n\n // attr bit layout (HWP 5.0 spec Table 35):\n // 0: italic, 1: bold, 2-4: underline type(3), 5-8: underline shape(4),\n // 9-11: outline(3), 12-13: shadow(2), 14: emboss, 15: engrave,\n // 16-17: super/sub(2, 0=none,1=super,2=sub), 18-20: strikeout type(3),\n // 21-24: strikeout shape(4), 25: annotLine, 26-28: annotLine type,\n // 29: useFontSpace, 30: kerning\n const ulType = (attr >> 2) & 0x7; // 3 bits at 2-4\n const skType = (attr >> 18) & 0x7; // 3 bits at 18-20\n const suType = (attr >> 16) & 0x3; // 2 bits at 16-17 (0=none,1=super,2=sub)\n\n return {\n faceIds,\n height: (height > 0 && height < 100000) ? height : 1000,\n italic: (attr & 1) !== 0,\n bold: ((attr >> 1) & 1) !== 0,\n underline: ulType !== 0,\n strikeout: skType !== 0,\n superscript: suType === 1,\n subscript: suType === 2,\n textColor: d.length >= 56 ? colorRef(d, 52) : '000000',\n };\n}\n\n/* ── PARA_SHAPE ─────────────────────────────────────────────── */\n/* offset size field\n 0 4 attr1 (bits 0-1 = line spacing type, bits 2-4 = alignment)\n 4 4 leftMargin (HWPUNIT)\n 8 4 rightMargin\n 12 4 indent\n 16 4 spaceBefore\n 20 4 spaceAfter\n 24 4 lineSpacing */\n\nconst ALIGN_TBL: Record<number, Align> = { 0: 'justify', 1: 'left', 2: 'right', 3: 'center', 4: 'distribute', 5: 'distribute_space' };\n\nfunction parseParaShape(d: Uint8Array): HwpParaShape {\n if (d.length < 4) return { align: 'left', spaceBefore: 0, spaceAfter: 0, lineSpacing: 160, lineSpacingType: 0, leftMargin: 0, rightMargin: 0, indent: 0 };\n const attr = BinaryKit.readU32LE(d, 0);\n\n // bits 0-1: 줄 간격 종류 (0=PERCENT, 1=FIXED, 2=BETWEEN_LINES, 3=AT_LEAST)\n const lineSpacingType = (attr & 0x3) as 0 | 1 | 2 | 3;\n\n // bits 2-4: 정렬 방식 (0=justify,1=left,2=right,3=center,4=distribute,5=split)\n const align = ALIGN_TBL[(attr >> 2) & 0x7] ?? 'left';\n\n // 세로 정렬 (Bit 18 ~ Bit 19)\n const vVal = (attr >> 18) & 0x3;\n const verAlign = vVal === 1 ? 'top' : vVal === 2 ? 'center' : vVal === 3 ? 'bottom' : 'baseline';\n\n // 줄 바꿈 기준: attr1 에는 별도 비트 없음, 기본값 'break'\n const lineWrap: 'break' = 'break';\n\n return {\n align,\n lineSpacingType,\n leftMargin: d.length >= 8 ? i32(d, 4) : 0, // offset 4: 문단 몸체 왼쪽 여백 (HWPUNIT)\n rightMargin: d.length >= 12 ? i32(d, 8) : 0, // offset 8: 문단 몸체 오른쪽 여백 (HWPUNIT)\n indent: d.length >= 16 ? i32(d, 12) : 0, // offset 12: 첫 줄 들여쓰기 (HWPUNIT)\n spaceBefore: d.length >= 20 ? i32(d, 16) : 0,\n spaceAfter: d.length >= 24 ? i32(d, 20) : 0,\n lineSpacing: d.length >= 28 ? i32(d, 24) : 160,\n verAlign,\n lineWrap,\n };\n}\n\n/* ── BORDER_FILL ────────────────────────────────────────────── */\n/* [0:2] attr\n For each of 5 borders (left,right,top,bottom,diagonal): 6 bytes\n +0 type(BYTE) +1 widthIdx(BYTE) +2 color(COLORREF)\n [32:4] fillType\n [36:4] faceColor (bgColor for solid fill) */\n\nconst BORDER_W_PT = [0.28, 0.34, 0.43, 0.57, 0.71, 0.85, 1.13, 1.42, 1.70, 1.98, 2.84, 4.25, 5.67, 8.50, 11.34, 14.17];\nconst BORDER_KIND: Record<number, StrokeKind> = { 0:'solid',1:'dash',2:'dash',3:'dot',4:'dash',5:'dash',6:'dash',7:'double',8:'double',9:'double',10:'none' };\n\nfunction parseBorderFill(d: Uint8Array): HwpBorderFill {\n // Spec grouped format (표 23):\n // [0:2] attr\n // [2:4] 4 border types (left, right, top, bottom) — 1 byte each\n // [6:4] 4 border widths (left, right, top, bottom) — 1 byte each (index into BORDER_W_PT)\n // [10:16] 4 border colors (left, right, top, bottom) — 4 bytes each (COLORREF)\n // [26:3] diagonal: type(1) + width(1) + color(4) = 6 bytes actually [26:6]\n // [32:4] fillType\n // [36:4] faceColor (bgColor for solid fill)\n const borders: HwpBorderFill['borders'] = [];\n const BASE_TYPE = 2; // 4 type bytes\n const BASE_WIDTH = 6; // 4 width bytes\n const BASE_COLOR = 10; // 4 × 4-byte colors\n for (let i = 0; i < 4; i++) {\n const type = BASE_TYPE + i < d.length ? d[BASE_TYPE + i] : 0;\n const widthPt = BASE_WIDTH + i < d.length ? (BORDER_W_PT[d[BASE_WIDTH + i]] ?? 0.5) : 0.5;\n const color = BASE_COLOR + i * 4 + 4 <= d.length ? colorRef(d, BASE_COLOR + i * 4) : '000000';\n borders.push({ type, widthPt, color });\n }\n let bgColor: string | undefined;\n // after attr(2) + 4 types(4) + 4 widths(4) + 4 colors(16) + diagonal(6) = offset 32\n const fOff = 32;\n if (d.length >= fOff + 8) {\n const ft = BinaryKit.readU32LE(d, fOff);\n if (ft & 1) bgColor = colorRef(d, fOff + 4);\n }\n return { borders, bgColor };\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Body section parsing\n ═══════════════════════════════════════════════════════════════ */\n\n// gsoCtx: shared mutable counter for 'gso ' drawing objects.\n// Each 'gso ' CTRL_HEADER encountered increments this counter.\n// objectMap is keyed by 0-based gso order = sequential BinData insertion order.\ninterface GsoCtx {\n count: number;\n headers?: ParaNode[];\n footers?: ParaNode[];\n}\n\nfunction parseBody(\n raw: Uint8Array, compressed: boolean, di: DocInfo, shield: ShieldedParser, gsoCtx: GsoCtx,\n): { content: ContentNode[]; pageDims?: PageDims } {\n const recs = parseRecords(compressed ? tryInflate(raw) : raw);\n const content: ContentNode[] = [];\n let pageDims: PageDims | undefined;\n\n // Pre-scan for PAGE_DEF at any nesting level (real HWP stores it at level 2 inside section ctrl)\n for (const r of recs) {\n if (r.tag === TAG_PAGE_DEF) {\n pageDims = shield.guard(() => parsePageDef(r.data), A4, 'hwp:pageDef');\n break;\n }\n }\n\n let i = 0;\n while (i < recs.length) {\n if (recs[i].tag === TAG_PAGE_DEF) {\n i++; // already handled above; skip at top level\n } else if (recs[i].tag === TAG_PARA_HEADER) {\n const r = shield.guard(\n () => parseParagraphGroup(recs, i, di, shield, gsoCtx),\n { nodes: [] as ContentNode[], next: i + 1 },\n `hwp:para@${i}`,\n );\n content.push(...r.nodes);\n i = r.next;\n } else {\n i++;\n }\n }\n return { content, pageDims };\n}\n\n/* ── Paragraph group ────────────────────────────────────────── */\n\nfunction parseParagraphGroup(\n recs: HwpRecord[], start: number, di: DocInfo, shield: ShieldedParser, gsoCtx: GsoCtx,\n): { nodes: ContentNode[]; next: number } {\n const hdr = recs[start];\n const lv = hdr.level;\n\n // P1: PARA_HEADER 레이아웃\n // offset 8-9: paraShapeId (UINT16)\n // offset 10: styleId (UINT8)\n // offset 11: divideSort (UINT8) — 0x04=쪽나누기\n const psId = hdr.data.length >= 10 ? BinaryKit.readU16LE(hdr.data, 8) : 0;\n const hwpStyleId = hdr.data.length >= 11 ? hdr.data[10] : 0;\n const divideSort = hdr.data.length >= 12 ? hdr.data[11] : 0;\n const ps = di.paraShapes[psId];\n\n let text: ParaTextResult | null = null;\n let csPairs: [number, number][] = [];\n const grids: ContentNode[] = [];\n // imgId: for 'gso' uses sequential gsoCtx.count; for others uses flags-based objId\n const ctrlHeaders: { ctrlId: number; imgId: number; wPt: number; hPt: number; atnoType?: number }[] = [];\n let i = start + 1;\n\n while (i < recs.length && recs[i].level > lv) {\n const r = recs[i];\n\n if (r.tag === TAG_PARA_TEXT && r.level === lv + 1) {\n text = decodeParaText(r.data);\n i++;\n } else if (r.tag === TAG_PARA_CHAR_SHAPE && r.level === lv + 1) {\n csPairs = parseCharShapePairs(r.data);\n i++;\n } else if (r.tag === TAG_CTRL_HEADER && r.level === lv + 1) {\n if (r.data.length >= 4) {\n const ctrlId = BinaryKit.readU32LE(r.data, 0);\n\n if (ctrlId === CTRL_HEAD || ctrlId === CTRL_FOOT) {\n // P8: 머리말/꼬리말 컨트롤 — 자식 문단을 파싱해 gsoCtx에 저장\n const ctrlLv = r.level;\n const hfParas: ParaNode[] = [];\n let j = i + 1;\n while (j < recs.length && recs[j].level > ctrlLv) {\n if (recs[j].tag === TAG_PARA_HEADER) {\n const pr = shield.guard(\n () => parseParagraphGroup(recs, j, di, shield, gsoCtx),\n { nodes: [] as ContentNode[], next: j + 1 },\n `hwp:hf@${j}`,\n );\n hfParas.push(...pr.nodes.filter((n): n is ParaNode => n.tag === 'para'));\n j = pr.next;\n } else {\n j++;\n }\n }\n if (hfParas.length > 0) {\n const key = ctrlId === CTRL_HEAD ? 'headers' : 'footers';\n if (!gsoCtx[key]) gsoCtx[key] = hfParas;\n }\n i = j;\n } else {\n // HWP 5.0 general-object layout:\n // [0:4] ctrlId [4:4] flags [8:4] xOff [12:4] yOff\n // [16:4] width(HWPUNIT) [20:4] height(HWPUNIT)\n const MAX_HWP = 1_000_000;\n const rawW = r.data.length >= 24 ? BinaryKit.readU32LE(r.data, 16) : 0;\n const rawH = r.data.length >= 28 ? BinaryKit.readU32LE(r.data, 20) : 0;\n const wPt = rawW > 0 && rawW < MAX_HWP ? Metric.hwpToPt(rawW) : 0;\n const hPt = rawH > 0 && rawH < MAX_HWP ? Metric.hwpToPt(rawH) : 0;\n\n // P9: atno — offset 4 u32 하위 4bit = 번호 종류 (0=쪽번호, 6=전체쪽수)\n const atnoType = ctrlId === CTRL_ATNO && r.data.length >= 8\n ? BinaryKit.readU32LE(r.data, 4) & 15\n : undefined;\n\n // 'gso ' (그리기 객체) uses sequential counter; others use flags-based id\n const imgId = ctrlId === CTRL_GSO ? gsoCtx.count++ : (r.data.length >= 6 ? BinaryKit.readU16LE(r.data, 4) : 0);\n ctrlHeaders.push({ ctrlId, imgId, wPt, hPt, atnoType });\n\n if (ctrlId === CTRL_TABLE) {\n const tr = shield.guard(\n () => parseTableCtrl(recs, i, di, shield, gsoCtx),\n { grid: null, next: skipKids(recs, i) },\n `hwp:tbl@${i}`,\n );\n if (tr.grid) grids.push(tr.grid);\n i = tr.next;\n } else {\n i = skipKids(recs, i);\n }\n }\n } else {\n i = skipKids(recs, i);\n }\n } else {\n i++;\n }\n }\n\n const nodes: ContentNode[] = [];\n\n {\n const paraContent: Array<SpanNode | GridNode | PageNumNode> = [];\n\n // P9: atno 컨트롤 위치 수집 (pos 기준 정렬)\n const atnoCtrls: { pos: number; type: number }[] = [];\n if (text && text.controls.length > 0) {\n for (let ci = 0; ci < text.controls.length; ci++) {\n const ch = ctrlHeaders[ci];\n if (ch && ch.ctrlId === CTRL_ATNO)\n atnoCtrls.push({ pos: text.controls[ci].pos, type: ch.atnoType ?? 0 });\n }\n atnoCtrls.sort((a, b) => a.pos - b.pos);\n }\n\n // P9: 텍스트 chars를 atno 위치 기준으로 분할하여 PageNumNode 삽입\n if (text && text.chars.length > 0) {\n if (atnoCtrls.length > 0) {\n let k = 0;\n for (const ac of atnoCtrls) {\n const seg: ParsedChar[] = [];\n while (k < text.chars.length && text.chars[k].pos < ac.pos) seg.push(text.chars[k++]);\n if (seg.length > 0) paraContent.push(...resolveCharShapes(seg, csPairs, di));\n paraContent.push(buildPageNum(ac.type === 0 ? 'decimal' : 'total'));\n }\n const rest = text.chars.slice(k);\n if (rest.length > 0) paraContent.push(...resolveCharShapes(rest, csPairs, di));\n } else {\n paraContent.push(...resolveCharShapes(text.chars, csPairs, di));\n }\n } else if (atnoCtrls.length > 0) {\n for (const ac of atnoCtrls) paraContent.push(buildPageNum(ac.type === 0 ? 'decimal' : 'total'));\n }\n\n // Image placeholder spans: only for actual image controls.\n // Non-image controls (footnotes, TOC entries, etc.) are silently skipped.\n if (text && text.controls.length > 0) {\n for (let ci = 0; ci < text.controls.length; ci++) {\n const ch = ctrlHeaders[ci];\n if (!ch) continue; // anchor-only ctrl (gso is sibling, not inline)\n const isImg = ch.ctrlId === CTRL_IMAGE || ch.ctrlId === CTRL_FIG || ch.ctrlId === CTRL_OBJ || ch.ctrlId === CTRL_GSO;\n if (!isImg) continue; // skip footnotes, TOC, page num, etc.\n const dimStr = (ch.wPt > 0 && ch.hPt > 0)\n ? `_W${Math.round(ch.wPt)}_H${Math.round(ch.hPt)}`\n : '';\n paraContent.push(buildSpan(`__EXT_${ch.imgId}${dimStr}__`));\n }\n }\n\n // P5: 쪽나누기(divideSort & 4) → page-break 문단 먼저 출력\n if (divideSort & 4) {\n nodes.push(buildPara([{ tag: 'span', props: {}, kids: [buildPb()] } as SpanNode]));\n }\n // P5: 표 → 앵커 문단 순서 (앵커 문단 드롭 금지)\n nodes.push(...grids);\n nodes.push(buildPara(\n paraContent.length > 0 ? paraContent as any : [buildSpan('')],\n buildParaProps(ps, hwpStyleId),\n ));\n }\n\n return { nodes, next: i };\n}\n\nfunction skipKids(recs: HwpRecord[], idx: number): number {\n const lv = recs[idx].level;\n let i = idx + 1;\n while (i < recs.length && recs[i].level > lv) i++;\n return i;\n}\n\n/* ── PARA_TEXT ───────────────────────────────────────────────── */\n\n// Extended controls: 8 WORDs, associated CTRL_HEADER (16-25 also skip 16 bytes)\nconst EXT_CTRL = new Set([2, 3, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]);\n// Inline controls: 8 WORDs, no CTRL_HEADER\nconst INL_CTRL = new Set([4, 5, 6, 7, 8]);\n\nfunction decodeParaText(d: Uint8Array): ParaTextResult {\n const chars: ParsedChar[] = [];\n const controls: ParsedCtrl[] = [];\n let i = 0, pos = 0;\n\n while (i + 1 < d.length) {\n const c = d[i] | (d[i + 1] << 8);\n if (c === 0) { i += 2; pos++; continue; }\n if (c === 13) { break; } // paragraph end\n if (c === 10) { chars.push({ pos, ch: '\\n' }); i += 2; pos++; continue; }\n\n if (EXT_CTRL.has(c)) {\n // Extended control: 8 WORDs (16 bytes)\n // WORD 4 contains objId (for images, charts, etc.)\n let objId = 0;\n if (i + 16 <= d.length) {\n objId = BinaryKit.readU16LE(d, i + 8); // 4th WORD (offset 8) contains objId\n }\n controls.push({ pos, ctrlId: 0, objId, matched: false });\n i += 16; pos += 8; continue;\n }\n if (INL_CTRL.has(c)) {\n i += 16; pos += 8; continue;\n }\n if (c === 9) { // tab (inline 8 WORDs)\n chars.push({ pos, ch: '\\t' });\n i += 16; pos += 8; continue;\n }\n if (c >= 1 && c <= 31) { i += 2; pos++; continue; } // other control\n\n chars.push({ pos, ch: String.fromCharCode(c) });\n i += 2; pos++;\n }\n return { chars, controls };\n}\n\n/* ── PARA_CHAR_SHAPE ────────────────────────────────────────── */\n\nfunction parseCharShapePairs(d: Uint8Array): [number, number][] {\n const out: [number, number][] = [];\n for (let i = 0; i + 7 < d.length; i += 8)\n out.push([BinaryKit.readU32LE(d, i), BinaryKit.readU32LE(d, i + 4)]);\n return out;\n}\n\n/* ── Char-shape → SpanNode resolution ───────────────────────── */\n\nfunction resolveCharShapes(chars: ParsedChar[], pairs: [number, number][], di: DocInfo): SpanNode[] {\n if (chars.length === 0) return [buildSpan('')];\n\n const defaultId = pairs.length > 0 ? pairs[0][1] : 0;\n\n function idFor(pos: number): number {\n let id = defaultId;\n for (const [p, sid] of pairs) { if (p <= pos) id = sid; else break; }\n return id;\n }\n\n const spans: SpanNode[] = [];\n let curId = idFor(chars[0].pos);\n let buf = chars[0].ch;\n\n for (let k = 1; k < chars.length; k++) {\n const sid = idFor(chars[k].pos);\n if (sid !== curId) { spans.push(styledSpan(buf, curId, di)); buf = ''; curId = sid; }\n buf += chars[k].ch;\n }\n if (buf) spans.push(styledSpan(buf, curId, di));\n return spans;\n}\n\nfunction styledSpan(text: string, shapeId: number, di: DocInfo): SpanNode {\n const cs = di.charShapes[shapeId];\n if (!cs) return buildSpan(text);\n\n const props: TextProps = {};\n const fid = cs.faceIds[0] ?? 0;\n if (fid < di.faceNames.length && di.faceNames[fid]) props.font = safeFont(di.faceNames[fid]);\n if (cs.height > 0) props.pt = Metric.hwpToPt(cs.height);\n if (cs.bold) props.b = true;\n if (cs.italic) props.i = true;\n if (cs.underline) props.u = true;\n if (cs.strikeout) props.s = true;\n if (cs.superscript) props.sup = true;\n if (cs.subscript) props.sub = true;\n\n const hex = safeHex(cs.textColor);\n if (hex && hex !== '000000') props.color = hex;\n\n return buildSpan(text, props);\n}\n\n/* ── Table control parsing ──────────────────────────────────── */\n\nfunction parseTableCtrl(\n recs: HwpRecord[], ctrlIdx: number, di: DocInfo, shield: ShieldedParser, gsoCtx: GsoCtx,\n): { grid: ContentNode | null; next: number } {\n const ctrlLv = recs[ctrlIdx].level;\n let i = ctrlIdx + 1;\n\n let tblData: Uint8Array | null = null;\n const cells: { data: Uint8Array; tag: number; cStart: number; cEnd: number }[] = [];\n\n // Collect TABLE and cell records within this control's scope\n const tblLevel = ctrlLv + 1;\n\n while (i < recs.length && recs[i].level > ctrlLv) {\n const r = recs[i];\n\n if (isTableTag(r.tag) && r.level === tblLevel) {\n tblData = r.data;\n i++;\n } else if (r.tag === TAG_LIST_HEADER && r.level === tblLevel) {\n // LIST_HEADER as cell: paraCount tells how many paragraphs follow\n const cellData = r.data;\n const paraCount = cellData.length >= 2 ? BinaryKit.readU16LE(cellData, 0) : 0;\n i++;\n const cStart = i;\n // Consume exactly paraCount paragraphs (each with its child records)\n let consumed = 0;\n while (i < recs.length && consumed < paraCount) {\n if (recs[i].tag === TAG_PARA_HEADER && recs[i].level === tblLevel) {\n consumed++;\n i++;\n // Skip child records of this paragraph\n while (i < recs.length && recs[i].level > tblLevel) i++;\n } else if (recs[i].level > tblLevel) {\n i++;\n } else {\n break; // hit next sibling at same level\n }\n }\n cells.push({ data: cellData, tag: TAG_LIST_HEADER, cStart, cEnd: i });\n } else if (isCellTag(r.tag) && r.level === tblLevel) {\n // Full CELL record (with cell-specific fields)\n const cellData = r.data;\n const cellTag = r.tag;\n i++;\n const cStart = i;\n while (i < recs.length && recs[i].level > tblLevel) i++;\n cells.push({ data: cellData, tag: cellTag, cStart, cEnd: i });\n } else {\n i++;\n }\n }\n\n if (!tblData || cells.length === 0) return { grid: null, next: i };\n\n const rowCnt = tblData.length >= 6 ? BinaryKit.readU16LE(tblData, 4) : 1;\n const colCnt = tblData.length >= 8 ? BinaryKit.readU16LE(tblData, 6) : 1;\n\n interface PC { row: number; col: number; cs: number; rs: number; widthHwp: number; heightHwp?: number; props: CellProps; cellChildren: (ParaNode | GridNode)[] }\n const parsed: PC[] = [];\n\n for (let ci = 0; ci < cells.length; ci++) {\n const c = cells[ci];\n const seqIdx = ci;\n const pc = shield.guard(\n () => parseCellRec(c.data, c.tag, recs, c.cStart, c.cEnd, di, shield, seqIdx, colCnt, gsoCtx),\n { row: Math.floor(ci / (colCnt || 1)), col: ci % (colCnt || 1), cs: 1, rs: 1, widthHwp: 0, heightHwp: undefined, props: {}, cellChildren: [buildPara([buildSpan('')])] },\n `hwp:cell@${c.cStart}`,\n );\n parsed.push(pc);\n }\n\n // Determine actual row count from cell data (may exceed rowCnt for merged cells)\n const maxRow = parsed.reduce((m, c) => Math.max(m, c.row + c.rs), 0);\n const actualRowCnt = Math.max(rowCnt, maxRow);\n\n // Validate cell positions; fallback to sequential layout if invalid\n const posValid = parsed.every(c => c.row >= 0 && c.col >= 0 && c.col < colCnt);\n if (!posValid) {\n let idx = 0;\n for (const c of parsed) { c.row = Math.floor(idx / colCnt); c.col = idx % colCnt; idx++; }\n }\n\n // Compute column widths in points from cell widths\n const colWidthsPt: number[] = new Array(colCnt).fill(0);\n // Pass 1: use cells with cs=1 for exact column widths\n for (const c of parsed) {\n if (c.cs === 1 && c.widthHwp > 0) {\n const wPt = Metric.hwpToPt(c.widthHwp);\n if (wPt > colWidthsPt[c.col]) colWidthsPt[c.col] = wPt;\n }\n }\n // Pass 2: for columns still 0, try to derive from multi-span cells\n // Sort by span size ascending so smaller, more precise spans fill widths before larger spans\n const zeroColumns = colWidthsPt.filter(w => w === 0).length;\n if (zeroColumns > 0) {\n const spanCells = parsed.filter(c => c.cs > 1 && c.widthHwp > 0).sort((a, b) => a.cs - b.cs);\n for (const c of spanCells) {\n if (c.cs > 1 && c.widthHwp > 0) {\n // Subtract known column widths from the span\n let known = 0;\n let unknownCols = 0;\n for (let ci = c.col; ci < c.col + c.cs && ci < colCnt; ci++) {\n if (colWidthsPt[ci] > 0) known += colWidthsPt[ci];\n else unknownCols++;\n }\n if (unknownCols > 0) {\n const remaining = Metric.hwpToPt(c.widthHwp) - known;\n const each = remaining > 0 ? remaining / unknownCols : 0;\n for (let ci = c.col; ci < c.col + c.cs && ci < colCnt; ci++) {\n if (colWidthsPt[ci] === 0 && each > 0) colWidthsPt[ci] = each;\n }\n }\n }\n }\n }\n\n // Post-process: clamp near-zero column widths (< 1pt = floating-point artifact) to minimum 1pt\n for (let i = 0; i < colWidthsPt.length; i++) {\n if (colWidthsPt[i] > 0 && colWidthsPt[i] < 1) colWidthsPt[i] = 1;\n }\n\n const rows = [];\n for (let r = 0; r < actualRowCnt; r++) {\n const rc = parsed.filter(c => c.row === r).sort((a, b) => a.col - b.col);\n if (rc.length === 0) continue;\n\n // Calculate row height — prefer rs=1 cells (exact per-row height)\n let rowHeightPt: number | undefined = undefined;\n for (const c of rc) {\n if (c.heightHwp && c.heightHwp > 0 && c.rs === 1) {\n const hPt = Metric.hwpToPt(c.heightHwp);\n if (rowHeightPt == null || hPt > rowHeightPt) rowHeightPt = hPt;\n }\n }\n // Fallback: all cells span multiple rows → approximate height per row\n if (rowHeightPt == null) {\n for (const c of rc) {\n if (c.heightHwp && c.heightHwp > 0) {\n const hPt = Metric.hwpToPt(c.heightHwp) / c.rs;\n if (rowHeightPt == null || hPt > rowHeightPt) rowHeightPt = hPt;\n }\n }\n }\n\n rows.push(buildRow(rc.map(c => {\n return buildCell(c.cellChildren, { cs: c.cs, rs: c.rs, props: c.props });\n }), rowHeightPt));\n }\n if (rows.length === 0) return { grid: null, next: i };\n\n // Table-level default stroke\n let defStroke: Stroke | undefined;\n const bfOff = 18 + rowCnt * 2;\n if (tblData.length >= bfOff + 2) {\n const bfId = BinaryKit.readU16LE(tblData, bfOff);\n defStroke = strokeFromBF(bfId, di);\n }\n\n const gp: GridProps = {};\n if (defStroke) gp.defaultStroke = defStroke;\n const hasWidths = colWidthsPt.some(w => w > 0);\n if (hasWidths) gp.colWidths = colWidthsPt;\n return { grid: buildGrid(rows, gp), next: i };\n}\n\n/* ── Cell record ────────────────────────────────────────────── */\n/* LIST_HEADER for cells (HWP 5.0/5.1):\n [0:2] paraCount [2:4] attr (bits 6-7 = vertAlign)\n [6:2] unknown [8:2] rowAddr [10:2] colAddr\n [12:2] rowSpan [14:2] colSpan\n [16:4] width(HWPUNIT) [20:4] height(HWPUNIT)\n [24:8] padding[4] [32:2] borderFillId */\n\nfunction parseCellRec(\n d: Uint8Array, tag: number, recs: HwpRecord[], cStart: number, cEnd: number,\n di: DocInfo, shield: ShieldedParser, seqIdx: number, colCnt: number, gsoCtx: GsoCtx,\n) {\n let col: number, row: number, cs = 1, rs = 1;\n let widthHwp = 0;\n let heightHwp = 0;\n const props: CellProps = {};\n\n const attr = d.length >= 6 ? BinaryKit.readU32LE(d, 2) : 0;\n const va = (attr >> 6) & 0x3;\n if (va === 1) props.va = 'mid';\n else if (va === 2) props.va = 'bot';\n\n const HWP_PAD_LR_DEFAULT = 360;\n const HWP_PAD_TB_DEFAULT = 141;\n\n if (tag === TAG_LIST_HEADER && d.length >= 22) {\n col = BinaryKit.readU16LE(d, 8);\n row = BinaryKit.readU16LE(d, 10);\n cs = Math.max(1, BinaryKit.readU16LE(d, 12));\n rs = Math.max(1, BinaryKit.readU16LE(d, 14));\n widthHwp = BinaryKit.readU32LE(d, 16);\n heightHwp = d.length >= 24 ? BinaryKit.readU32LE(d, 20) : 0;\n if (d.length >= 32) {\n const pL = BinaryKit.readU16LE(d, 24); const pR = BinaryKit.readU16LE(d, 26);\n const pT = BinaryKit.readU16LE(d, 28); const pB = BinaryKit.readU16LE(d, 30);\n if (pL !== HWP_PAD_LR_DEFAULT) props.padL = Metric.hwpToPt(pL);\n if (pR !== HWP_PAD_LR_DEFAULT) props.padR = Metric.hwpToPt(pR);\n if (pT !== HWP_PAD_TB_DEFAULT) props.padT = Metric.hwpToPt(pT);\n if (pB !== HWP_PAD_TB_DEFAULT) props.padB = Metric.hwpToPt(pB);\n }\n const bfId = d.length >= 34 ? BinaryKit.readU16LE(d, 32) : 0;\n if (bfId > 0 && bfId <= di.borderFills.length) applyCellBorderFill(di.borderFills[bfId - 1], props);\n } else if (tag !== TAG_LIST_HEADER) {\n col = d.length >= 8 ? BinaryKit.readU16LE(d, 6) : seqIdx % (colCnt || 1);\n row = d.length >= 10 ? BinaryKit.readU16LE(d, 8) : Math.floor(seqIdx / (colCnt || 1));\n cs = d.length >= 12 ? Math.max(1, BinaryKit.readU16LE(d, 10)) : 1;\n rs = d.length >= 14 ? Math.max(1, BinaryKit.readU16LE(d, 12)) : 1;\n widthHwp = d.length >= 18 ? BinaryKit.readU32LE(d, 14) : 0;\n heightHwp = d.length >= 22 ? BinaryKit.readU32LE(d, 18) : 0;\n if (d.length >= 30) {\n const pL = BinaryKit.readU16LE(d, 22); const pR = BinaryKit.readU16LE(d, 24);\n const pT = BinaryKit.readU16LE(d, 26); const pB = BinaryKit.readU16LE(d, 28);\n if (pL !== HWP_PAD_LR_DEFAULT) props.padL = Metric.hwpToPt(pL);\n if (pR !== HWP_PAD_LR_DEFAULT) props.padR = Metric.hwpToPt(pR);\n if (pT !== HWP_PAD_TB_DEFAULT) props.padT = Metric.hwpToPt(pT);\n if (pB !== HWP_PAD_TB_DEFAULT) props.padB = Metric.hwpToPt(pB);\n }\n const bfId = d.length >= 32 ? BinaryKit.readU16LE(d, 30) : 0;\n if (bfId > 0 && bfId <= di.borderFills.length) applyCellBorderFill(di.borderFills[bfId - 1], props);\n } else {\n row = Math.floor(seqIdx / (colCnt || 1));\n col = seqIdx % (colCnt || 1);\n }\n\n const cellChildren: (ParaNode | GridNode)[] = [];\n const MAX_HWP = 1_000_000;\n let k = cStart;\n\n while (k < cEnd) {\n if (recs[k].tag === TAG_PARA_HEADER) {\n // Parse paragraph inside cell — also extracts nested tables within the paragraph\n const r = shield.guard(\n () => {\n const hdr = recs[k];\n const lv = hdr.level;\n const psId = hdr.data.length >= 10 ? BinaryKit.readU16LE(hdr.data, 8) : 0;\n // P6: 셀 내부 문단의 styleId / divideSort 읽기\n const cellStyleId = hdr.data.length >= 11 ? hdr.data[10] : 0;\n const cellDivide = hdr.data.length >= 12 ? hdr.data[11] : 0;\n const ps = di.paraShapes[psId];\n let txt: ParaTextResult | null = null;\n let csp: [number, number][] = [];\n const ctrlHdrs: { ctrlId: number; imgId: number; wPt: number; hPt: number }[] = [];\n const innerGrids: GridNode[] = [];\n let j = k + 1;\n while (j < cEnd && recs[j].level > lv) {\n if (recs[j].tag === TAG_PARA_TEXT) { txt = decodeParaText(recs[j].data); j++; }\n else if (recs[j].tag === TAG_PARA_CHAR_SHAPE) { csp = parseCharShapePairs(recs[j].data); j++; }\n else if (recs[j].tag === TAG_CTRL_HEADER && recs[j].level === lv + 1) {\n if (recs[j].data.length >= 4) {\n const ctrlId = BinaryKit.readU32LE(recs[j].data, 0);\n if (ctrlId === CTRL_TABLE) {\n // Nested table inside a cell paragraph — recurse into parseTableCtrl\n const nestedTr = shield.guard(\n () => parseTableCtrl(recs, j, di, shield, gsoCtx),\n { grid: null, next: skipKids(recs, j) },\n `hwp:innerNestedTbl@${j}`,\n );\n if (nestedTr.grid) innerGrids.push(nestedTr.grid as GridNode);\n j = nestedTr.next;\n } else {\n const rawW = recs[j].data.length >= 24 ? BinaryKit.readU32LE(recs[j].data, 16) : 0;\n const rawH = recs[j].data.length >= 28 ? BinaryKit.readU32LE(recs[j].data, 20) : 0;\n const wPt = rawW > 0 && rawW < MAX_HWP ? Metric.hwpToPt(rawW) : 0;\n const hPt = rawH > 0 && rawH < MAX_HWP ? Metric.hwpToPt(rawH) : 0;\n const imgId = ctrlId === CTRL_GSO ? gsoCtx.count++ : (recs[j].data.length >= 6 ? BinaryKit.readU16LE(recs[j].data, 4) : 0);\n ctrlHdrs.push({ ctrlId, imgId, wPt, hPt });\n j = skipKids(recs, j);\n }\n } else {\n j = skipKids(recs, j);\n }\n }\n else j++;\n }\n const paraContent: (SpanNode | ContentNode)[] = [];\n if (txt && txt.chars.length > 0) paraContent.push(...resolveCharShapes(txt.chars, csp, di));\n if (txt && txt.controls.length > 0) {\n for (let ci = 0; ci < txt.controls.length; ci++) {\n const ch = ctrlHdrs[ci];\n if (!ch) continue;\n const isImg = ch.ctrlId === CTRL_IMAGE || ch.ctrlId === CTRL_FIG || ch.ctrlId === CTRL_OBJ || ch.ctrlId === CTRL_GSO;\n if (!isImg) continue;\n const dimStr = (ch.wPt > 0 && ch.hPt > 0) ? `_W${Math.round(ch.wPt)}_H${Math.round(ch.hPt)}` : '';\n paraContent.push(buildSpan(`__EXT_${ch.imgId}${dimStr}__`));\n }\n }\n const kids = paraContent.length > 0 ? paraContent as any : [buildSpan('')];\n // P6: innerGrids 먼저, 앵커 문단 나중 (P5와 동일한 순서)\n const items: (ParaNode | GridNode)[] = [...innerGrids, buildPara(kids, buildParaProps(ps, cellStyleId))];\n if (cellDivide & 4) items.unshift(buildPara([{ tag: 'span', props: {}, kids: [buildPb()] } as SpanNode]));\n return { items, next: j };\n },\n { items: [buildPara([buildSpan('')])] as (ParaNode | GridNode)[], next: k + 1 },\n `hwp:cellP@${k}`,\n );\n cellChildren.push(...r.items);\n k = r.next;\n } else if (recs[k].tag === TAG_CTRL_HEADER && recs[k].data.length >= 4) {\n // CTRL_HEADER at cell level (sibling of PARA_HEADER) — anchored 'gso' images and outer-level nested tables\n const cellCtrlId = BinaryKit.readU32LE(recs[k].data, 0);\n if (cellCtrlId === CTRL_GSO) {\n const gsoId = gsoCtx.count++;\n const rawW = recs[k].data.length >= 24 ? BinaryKit.readU32LE(recs[k].data, 16) : 0;\n const rawH = recs[k].data.length >= 28 ? BinaryKit.readU32LE(recs[k].data, 20) : 0;\n const wPt = rawW > 0 && rawW < MAX_HWP ? Metric.hwpToPt(rawW) : 0;\n const hPt = rawH > 0 && rawH < MAX_HWP ? Metric.hwpToPt(rawH) : 0;\n const dimStr = (wPt > 0 && hPt > 0) ? `_W${Math.round(wPt)}_H${Math.round(hPt)}` : '';\n cellChildren.push(buildPara([buildSpan(`__EXT_${gsoId}${dimStr}__`)]));\n k = skipKids(recs, k);\n } else if (cellCtrlId === CTRL_TABLE) {\n const tr = shield.guard(\n () => parseTableCtrl(recs, k, di, shield, gsoCtx),\n { grid: null, next: skipKids(recs, k) },\n `hwp:nestedTbl@${k}`,\n );\n if (tr.grid) cellChildren.push(tr.grid as GridNode);\n k = tr.next;\n } else {\n k = skipKids(recs, k);\n }\n } else { k++; }\n }\n\n return {\n row, col, cs, rs, props, widthHwp,\n heightHwp: heightHwp || undefined,\n cellChildren: cellChildren.length ? cellChildren : [buildPara([buildSpan('')])],\n };\n}\n\n/* ── PAGE_DEF ───────────────────────────────────────────────── */\n/* [0:4] width [4:4] height [8:4] ml [12:4] mr\n [16:4] mt [20:4] mb [24:4] header [28:4] footer [36:4] attr (bit0=landscape) */\n\nfunction parsePageDef(d: Uint8Array): PageDims {\n if (d.length < 24) return A4;\n const w = BinaryKit.readU32LE(d, 0);\n const h = BinaryKit.readU32LE(d, 4);\n const ml = BinaryKit.readU32LE(d, 8);\n const mr = BinaryKit.readU32LE(d, 12);\n const mt = BinaryKit.readU32LE(d, 16);\n const mb = BinaryKit.readU32LE(d, 20);\n const header = d.length >= 28 ? BinaryKit.readU32LE(d, 24) : 0;\n const footer = d.length >= 32 ? BinaryKit.readU32LE(d, 28) : 0;\n const at = d.length >= 40 ? BinaryKit.readU32LE(d, 36) : 0;\n return {\n wPt: Metric.hwpToPt(w), hPt: Metric.hwpToPt(h),\n ml: Metric.hwpToPt(ml), mr: Metric.hwpToPt(mr),\n mt: Metric.hwpToPt(mt), mb: Metric.hwpToPt(mb),\n headerPt: header > 0 ? Metric.hwpToPt(header) : undefined,\n footerPt: footer > 0 ? Metric.hwpToPt(footer) : undefined,\n orient: (at & 1) ? 'landscape' : 'portrait',\n };\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Helpers\n ═══════════════════════════════════════════════════════════════ */\n\nfunction i32(d: Uint8Array, o: number): number {\n const u = BinaryKit.readU32LE(d, o);\n return u > 0x7FFFFFFF ? u - 0x100000000 : u;\n}\n\nfunction colorRef(d: Uint8Array, o: number): string {\n if (o + 3 > d.length) return '000000';\n return ((d[o] << 16) | (d[o + 1] << 8) | d[o + 2]).toString(16).padStart(6, '0').toUpperCase();\n}\n\nfunction toStroke(b: { type: number; widthPt: number; color: string }): Stroke {\n return { kind: BORDER_KIND[b.type] ?? 'solid', pt: b.widthPt, color: b.color };\n}\n\n// Apply borderFill to CellProps. Preserve explicit NONE so DOCX tcBorders can\n// override the table-level tblBorders. Filtering NONE would let tblBorders bleed through.\nfunction applyCellBorderFill(bf: HwpBorderFill, props: CellProps): void {\n if (bf.borders.length >= 4) {\n props.left = toStroke(bf.borders[0]);\n props.right = toStroke(bf.borders[1]);\n props.top = toStroke(bf.borders[2]);\n props.bot = toStroke(bf.borders[3]);\n }\n if (bf.bgColor && bf.bgColor !== 'FFFFFF') props.bg = bf.bgColor;\n}\n\nfunction strokeFromBF(bfId: number, di: DocInfo): Stroke | undefined {\n if (bfId <= 0 || bfId > di.borderFills.length) return undefined;\n const bf = di.borderFills[bfId - 1];\n if (!bf.borders.length) return undefined;\n const b = bf.borders[0];\n return { kind: BORDER_KIND[b.type] ?? 'solid', pt: b.widthPt, color: b.color };\n}\n\nfunction buildParaProps(ps?: HwpParaShape, hwpStyleId?: number): ParaProps {\n // P2: hwpStyleId를 초기값으로 포함 (undefined이면 빈 객체)\n const p: ParaProps = hwpStyleId !== undefined ? { hwpStyleId } : {};\n if (!ps) return p;\n if (ps.align && ps.align !== 'left') p.align = ps.align;\n if (ps.spaceBefore > 0) p.spaceBefore = Metric.hwpToPt(ps.spaceBefore);\n if (ps.spaceAfter > 0) p.spaceAfter = Metric.hwpToPt(ps.spaceAfter);\n // 줄 간격: type=0(PERCENT) → lineHeight, type=1(FIXED) → lineHeightFixed\n if (ps.lineSpacingType === 1) {\n if (ps.lineSpacing > 0) p.lineHeightFixed = Metric.hwpToPt(ps.lineSpacing);\n } else {\n // P10: 160%(HWP 기본값) 생략 버그 수정 — 항상 lineHeight 설정\n if (ps.lineSpacing > 0) p.lineHeight = ps.lineSpacing / 100;\n }\n // leftMargin (offset 4) = 문단 몸체 왼쪽 여백 → leftMargin (pt), ensure non-negative\n const leftMarginPt = Math.max(0, Metric.hwpToPt(ps.leftMargin));\n if (leftMarginPt > 0) p.leftMargin = leftMarginPt;\n // rightMargin (offset 8) = 문단 몸체 오른쪽 여백 → indentRightPt (pt)\n const rightMarginPt = Math.max(0, Metric.hwpToPt(ps.rightMargin));\n if (rightMarginPt > 0) p.indentRightPt = rightMarginPt;\n // indent (offset 12) = 첫 줄 들여쓰기(양수) / 내어쓰기(음수) → firstLineIndentPt\n if (ps.indent !== 0) p.firstLineIndentPt = Metric.hwpToPt(ps.indent);\n if (ps.verAlign && ps.verAlign !== 'baseline') p.verAlign = ps.verAlign;\n if (ps.lineWrap && ps.lineWrap !== 'break') p.lineWrap = ps.lineWrap;\n return p;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Decoder class\n ═══════════════════════════════════════════════════════════════ */\n\nexport class HwpScanner implements Decoder {\n readonly format = 'hwp';\n readonly aliases = ['application/vnd.hancom.hwp'];\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n if (!BinaryKit.isOle2(data)) return fail('HWP: Invalid OLE2 signature');\n const streams = BinaryKit.parseCfb(data);\n\n // FileHeader\n const fh = streams.get('FileHeader');\n const { compressed, encrypted } = fh ? parseFileHeader(fh) : { compressed: true, encrypted: false };\n if (encrypted) return fail('HWP: 암호화된 파일은 지원하지 않습니다');\n\n // DocInfo\n const diRaw = streams.get('DocInfo');\n let di: DocInfo = { faceNames: [], charShapes: [], paraShapes: [], borderFills: [] };\n if (diRaw) {\n di = shield.guard(() => parseDocInfo(diRaw, compressed), di, 'hwp:docInfo');\n }\n\n // Extract images from BinData streams.\n // HWP duplicates each BinData entry: once as \"BinData/BIN0001.jpg\" and once as \"BIN0001.jpg\".\n // We keep only the \"BinData/\" prefixed versions, sort by BIN number, then assign 0-based keys\n // matching the order 'gso' CTRL_HEADER records are encountered during body parsing.\n const binEntries: { binNum: number; data: Uint8Array }[] = [];\n for (const [path, streamData] of streams) {\n // Match \"BinData/BIN0001.jpg\" style — the canonical form\n const m = path.match(/^BinData[/\\\\]BIN(\\d+)\\.\\w+$/i);\n if (m) binEntries.push({ binNum: parseInt(m[1], 10), data: streamData });\n }\n // Sort by BIN number (ascending) so BIN0001→idx0, BIN0002→idx1, …\n binEntries.sort((a, b) => a.binNum - b.binNum);\n\n const objectMap = new Map<number, ImgNode>();\n for (let idx = 0; idx < binEntries.length; idx++) {\n const { data: imgData } = binEntries[idx];\n\n // Determine MIME type from binary signature first, then fall back to extension\n let mimeType: ImgNode['mime'] = 'image/jpeg';\n if (imgData[0] === 0x89 && imgData[1] === 0x50) mimeType = 'image/png';\n else if (imgData[0] === 0x47 && imgData[1] === 0x49) mimeType = 'image/gif';\n else if (imgData[0] === 0x42 && imgData[1] === 0x4D) mimeType = 'image/bmp';\n\n const base64 = TextKit.base64Encode(imgData);\n const { wPt, hPt } = getImageDimsPt(imgData, mimeType);\n objectMap.set(idx, buildImg(base64, mimeType, wPt, hPt));\n }\n\n // gsoCtx tracks sequential 'gso' encounter order — must be shared across all sections\n const gsoCtx: GsoCtx = { count: 0 };\n\n // Body sections\n const allContent: ContentNode[] = [];\n let pageDims: PageDims = A4;\n\n for (let s = 0; s < 100; s++) {\n const sec = streams.get(`BodyText/Section${s}`) ?? streams.get(`Section${s}`);\n if (!sec) {\n if (s === 0) {\n const fb = findBodySection(streams);\n if (fb) {\n const r = parseBody(fb, compressed, di, shield, gsoCtx);\n allContent.push(...r.content);\n if (r.pageDims) pageDims = r.pageDims;\n }\n }\n break;\n }\n const r = shield.guard(\n () => parseBody(sec, compressed, di, shield, gsoCtx),\n { content: [], pageDims: undefined },\n `hwp:sec${s}`,\n );\n allContent.push(...r.content);\n if (r.pageDims) pageDims = r.pageDims;\n }\n\n if (objectMap.size > 0) {\n injectImagesIntoContent(allContent, objectMap);\n }\n\n warns.push(...shield.flush());\n const content = allContent.length > 0 ? allContent : [buildPara([buildSpan('')])];\n // P8: 머리말/꼬리말을 gsoCtx에서 가져와 buildSheet에 전달\n return succeed(buildRoot({}, [buildSheet(content, pageDims, {\n headers: gsoCtx.headers ? { default: gsoCtx.headers } : undefined,\n footers: gsoCtx.footers ? { default: gsoCtx.footers } : undefined,\n })]), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`HWP decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\nfunction findBodySection(streams: Map<string, Uint8Array>): Uint8Array | undefined {\n for (const [k, v] of streams)\n if (k.includes('Section') && !k.includes('Header') && !k.includes('Info')) return v;\n return undefined;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Image dimension extraction from binary headers\n ════════════════════════════════════════════════════════════ */\n\n// Returns { wPt, hPt } by parsing image headers; falls back to { wPt: 72, hPt: 72 } (1-inch)\nfunction getImageDimsPt(data: Uint8Array, mime: string): { wPt: number; hPt: number } {\n const fallback = { wPt: 72, hPt: 72 };\n try {\n if (mime === 'image/png' && data.length >= 24) {\n // PNG IHDR: sig(8) + length(4) + type(4) + width(4) + height(4) — all big-endian\n const w = (data[16] << 24 | data[17] << 16 | data[18] << 8 | data[19]) >>> 0;\n const h = (data[20] << 24 | data[21] << 16 | data[22] << 8 | data[23]) >>> 0;\n if (w > 0 && h > 0) return { wPt: w * 0.75, hPt: h * 0.75 }; // 96 DPI → pt\n }\n if (mime === 'image/jpeg') {\n // Scan for SOF markers: FF C0 / C1 / C2 / C3\n let i = 2;\n while (i + 8 < data.length) {\n if (data[i] !== 0xFF) { i++; continue; }\n const marker = data[i + 1];\n if (marker >= 0xC0 && marker <= 0xC3) {\n // SOF: 2-byte marker + 2-byte length + 1-byte precision + 2-byte height + 2-byte width\n const h = (data[i + 5] << 8 | data[i + 6]) >>> 0;\n const w = (data[i + 7] << 8 | data[i + 8]) >>> 0;\n if (w > 0 && h > 0) return { wPt: w * 0.75, hPt: h * 0.75 };\n }\n const segLen = data[i + 2] << 8 | data[i + 3];\n i += 2 + (segLen > 0 ? segLen : 2);\n }\n }\n if (mime === 'image/bmp' && data.length >= 26) {\n // BMP DIB header: width at 18, height at 22 (signed int32 LE; negative = top-down)\n const w = BinaryKit.readU32LE(data, 18);\n const h = Math.abs(BinaryKit.readU32LE(data, 22) | 0);\n if (w > 0 && h > 0) return { wPt: w * 0.75, hPt: h * 0.75 };\n }\n if (mime === 'image/gif' && data.length >= 10) {\n // GIF: width at 6, height at 8 (uint16 LE)\n const w = data[6] | data[7] << 8;\n const h = data[8] | data[9] << 8;\n if (w > 0 && h > 0) return { wPt: w * 0.75, hPt: h * 0.75 };\n }\n } catch { /* ignore */ }\n return fallback;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n OLE Object extraction (images)\n ════════════════════════════════════════════════════════════ */\n\nfunction extractImagesFromOleObjectLink(data: Uint8Array): OleObject[] {\n const objects: OleObject[] = [];\n let off = 0;\n\n while (off + 8 <= data.length) {\n const objId = BinaryKit.readU32LE(data, off);\n const dataSize = BinaryKit.readU32LE(data, off + 4);\n const reserved = BinaryKit.readU32LE(data, off + 8);\n\n if (objId === 0 || dataSize === 0) break;\n\n const objOff = off + 16;\n if (objOff + dataSize > data.length) break;\n\n const objData = data.subarray(objOff, objOff + dataSize);\n\n // Detect MIME type from signature\n let mimeType = 'application/octet-stream';\n if (objData[0] === 0xFF && objData[1] === 0xD8 && objData[2] === 0xFF) {\n mimeType = 'image/jpeg';\n } else if (objData[0] === 0x89 && objData[1] === 0x50 && objData[2] === 0x4E && objData[3] === 0x47) {\n mimeType = 'image/png';\n } else if (objData[0] === 0x47 && objData[1] === 0x49 && objData[2] === 0x46 && objData[3] === 0x3538) {\n mimeType = 'image/gif';\n } else if (objData[0] === 0x42 && objData[1] === 0x4D) {\n mimeType = 'image/bmp';\n }\n\n objects.push({ id: objId, data: objData, mimeType });\n off = objOff + dataSize;\n }\n\n return objects;\n}\n\n/* ═══════════════════════════════════════════════════════════════\n Helper to inject images into paragraph content\n ════════════════════════════════════════════════════════════ */\n\nfunction injectImagesIntoContent(\n content: ContentNode[],\n objectMap: Map<number, ImgNode>\n): void {\n if (objectMap.size === 0) return;\n\n // Helper function to process a list of kids (spans, images, etc.)\n const processKids = (kids: any[]) => {\n for (let i = 0; i < kids.length; i++) {\n const kid = kids[i];\n // Span node structure: { tag: 'span', props, kids: [{ tag: 'txt', content }] }\n if (kid.tag === 'span' && kid.kids && kid.kids[0]?.tag === 'txt') {\n const text = kid.kids[0].content;\n // __EXT_N__ or __EXT_N_W<wPt>_H<hPt>__ (with encoded display size)\n // N is the objId that matches the index in objectMap\n const match = text.match?.(/^__(?:IMG|EXT)_(\\d+)(?:_W(\\d+)_H(\\d+))?__$/);\n if (match) {\n const objId = parseInt(match[1], 10);\n const base = objectMap.get(objId);\n if (base) {\n const wPt = match[2] ? parseInt(match[2], 10) : 0;\n const hPt = match[3] ? parseInt(match[3], 10) : 0;\n // Use encoded display size when valid; otherwise keep pixel-based dims\n kids[i] = (wPt > 0 && hPt > 0) ? { ...base, w: wPt, h: hPt } : base;\n }\n }\n }\n }\n };\n\n // Recursively process a grid (table): resolves image placeholders in all cells,\n // including nested grids inside cells.\n const processGridKids = (grid: any) => {\n if (!grid.kids || !Array.isArray(grid.kids)) return;\n\n for (const row of grid.kids) {\n if (!row.kids || !Array.isArray(row.kids)) continue;\n\n for (const cell of row.kids) {\n if (!cell.kids || !Array.isArray(cell.kids)) continue;\n\n for (const cellKid of cell.kids) {\n if (cellKid.tag === 'grid') {\n // Nested table inside cell — recurse\n processGridKids(cellKid);\n } else if (cellKid.tag === 'para' && cellKid.kids) {\n processKids(cellKid.kids);\n }\n }\n }\n }\n };\n\n for (const node of content) {\n if (node.tag === 'para' && node.kids) {\n // Process paragraph kids (spans, images, links, grids)\n processKids(node.kids);\n\n // Also process any nested grids inside the paragraph\n for (const kid of node.kids) {\n if (kid.tag === 'grid') {\n processGridKids(kid);\n }\n }\n } else if (node.tag === 'grid') {\n // Process grid nodes (tables)\n processGridKids(node);\n }\n }\n}\n\nregistry.registerDecoder(new HwpScanner());\n","import type {\n DocRoot,\n ContentNode,\n ParaNode,\n SpanNode,\n GridNode,\n ImgNode,\n LinkNode,\n PageNumNode,\n CellNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport type {\n DocMeta,\n PageDims,\n TextProps,\n ParaProps,\n CellProps,\n GridProps,\n TableLook,\n Stroke,\n ImgLayout,\n ImgHorzAlign,\n ImgVertAlign,\n ImgHorzRelTo,\n ImgVertRelTo,\n ImgWrap,\n} from \"../../model/doc-props\";\nimport { A4 } from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport {\n buildRoot,\n buildSheet,\n buildPara,\n buildSpan,\n buildImg,\n buildGrid,\n buildRow,\n buildCell,\n buildPb,\n} from \"../../model/builders\";\nimport { ShieldedParser } from \"../../safety/ShieldedParser\";\nimport {\n Metric,\n safeAlign,\n safeFont,\n safeHex,\n safeStrokeDocx,\n} from \"../../safety/StyleBridge\";\nimport { BaseDecoder } from \"../../core/BaseDecoder\";\nimport { ArchiveKit } from \"../../toolkit/ArchiveKit\";\nimport { XmlKit } from \"../../toolkit/XmlKit\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { registry } from \"../../pipeline/registry\";\n\nexport class DocxDecoder extends BaseDecoder {\n protected getFormat(): string {\n return \"docx\";\n }\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n const files = await ArchiveKit.unzip(data);\n\n const getFile = (path: string) => {\n const lower = path.toLowerCase();\n for (const [name, data] of files.entries()) {\n if (name.toLowerCase() === lower) return data;\n }\n return undefined;\n };\n\n const docXml = getFile(\"word/document.xml\");\n if (!docXml) return fail(\"DOCX: word/document.xml not found\");\n\n const relsXml = getFile(\"word/_rels/document.xml.rels\");\n const relsMap = relsXml\n ? await parseRels(TextKit.decode(relsXml))\n : new Map<string, string>();\n\n const coreXml = getFile(\"docProps/core.xml\");\n let meta: DocMeta = {};\n if (coreXml) {\n try {\n meta = await parseCoreProps(TextKit.decode(coreXml));\n } catch {\n // ignore — meta is optional\n }\n }\n\n // Parse numbering.xml for list support\n const numXml = getFile(\"word/numbering.xml\");\n let numMap: NumMap = new Map();\n if (numXml) {\n try {\n numMap = await parseNumbering(TextKit.decode(numXml));\n } catch {\n /* non-fatal */\n }\n }\n\n // Parse styles.xml for table and paragraph/character style defaults\n let stylesMap: StylesMap = new Map();\n let paraStyleMap: ParaStyleMap = new Map();\n const stylesXml = getFile(\"word/styles.xml\");\n if (stylesXml) {\n try {\n const stylesStr = TextKit.decode(stylesXml);\n stylesMap = await parseStylesMap(stylesStr);\n paraStyleMap = await parseParaStyleMap(stylesStr);\n } catch {\n /* non-fatal */\n }\n }\n\n let docStr = TextKit.decode(docXml).trim();\n if (!docStr) {\n warns.push(\n \"DOCX: word/document.xml is empty, using fallback empty document\",\n );\n docStr =\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:document xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:body/></w:document>';\n }\n const docObj: any = await XmlKit.parseStrict(docStr);\n\n const body = getBody(docObj);\n const dims = extractDims(body) ?? { ...A4 };\n const elements = getBodyElements(body);\n console.log(\n `[DocxDecoder] 파싱된 전체 본문 요소 개수: ${elements.length}`,\n );\n\n const decCtx: DecCtx = {\n relsMap,\n files,\n shield,\n numMap,\n warns,\n stylesMap,\n paraStyleMap,\n };\n\n const kids: ContentNode[] = [];\n for (const el of elements) {\n const nodes = shield.guard(\n () => decodeElement(el, decCtx),\n [buildPara([buildSpan(\"[요소 파싱 실패]\")])],\n \"docx:bodyElement\",\n );\n if (Array.isArray(nodes)) {\n kids.push(...nodes);\n } else {\n kids.push(nodes);\n }\n\n // Inline sectPr in pPr = section break → insert page-break paragraph after\n if (el.type === \"para\") {\n const pPr = el.node?.[\"w:pPr\"]?.[0] ?? el.node?.pPr?.[0] ?? {};\n const inlineSectPr = pPr?.[\"w:sectPr\"]?.[0] ?? pPr?.sectPr?.[0];\n if (inlineSectPr) {\n const typeAttr = inlineSectPr?.[\"w:type\"]?.[0]?._attr;\n const sectType = typeAttr?.[\"w:val\"] ?? typeAttr?.val ?? \"nextPage\";\n if (sectType !== \"continuous\") {\n kids.push(\n buildPara([{ tag: \"span\", props: {}, kids: [buildPb()] }]),\n );\n }\n }\n }\n }\n\n // Decode header/footer\n const headersMap = await decodeHeaderFooter(\n \"header\",\n body,\n relsMap,\n files,\n decCtx,\n );\n const footersMap = await decodeHeaderFooter(\n \"footer\",\n body,\n relsMap,\n files,\n decCtx,\n );\n\n warns.push(...shield.flush());\n const sheet = buildSheet(kids.filter(Boolean) as ContentNode[], dims, {\n headers: headersMap,\n footers: footersMap,\n });\n return succeed(buildRoot(meta, [sheet]), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`DOCX decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\n// ─── types ─────────────────────────────────────────────────\n\ninterface TblBorderDef {\n top?: Stroke;\n bottom?: Stroke;\n left?: Stroke;\n right?: Stroke;\n insideH?: Stroke;\n insideV?: Stroke;\n}\n\n/** Parsed tblStyle defaults from styles.xml */\ninterface TblStyleDef {\n tblBorders?: TblBorderDef;\n cellBg?: string; // default cell background\n}\n\n/** Parsed paragraph/character style defaults */\ninterface ParaStyleDef {\n rPr?: {\n b?: boolean;\n i?: boolean;\n u?: boolean;\n s?: boolean;\n pt?: number;\n color?: string;\n font?: string;\n };\n pPr?: {\n align?: string;\n spaceBefore?: number;\n spaceAfter?: number;\n lineHeight?: number;\n indentPt?: number;\n indentRightPt?: number;\n firstLineIndentPt?: number;\n };\n basedOn?: string; // parent style id\n}\n\ntype StylesMap = Map<string, TblStyleDef>; // styleId → table style defaults\ntype ParaStyleMap = Map<string, ParaStyleDef>; // styleId → para/char style defaults\n\ninterface DecCtx {\n relsMap: Map<string, string>;\n files: Map<string, Uint8Array>;\n shield: ShieldedParser;\n numMap: NumMap;\n warns: string[];\n stylesMap: StylesMap;\n paraStyleMap: ParaStyleMap;\n}\n\n// numId → { abstractNumId, levels: Map<ilvl, { fmt, isOrdered }> }\ntype NumMap = Map<\n number,\n { levels: Map<number, { fmt: string; isOrdered: boolean }> }\n>;\n\n// ─── helpers ────────────────────────────────────────────────\n\nfunction toArr(v: any): any[] {\n return v == null ? [] : Array.isArray(v) ? v : [v];\n}\n\n/** Resolve DOCX relative paths. e.g. (\"word\", \"../media/image1.png\") → \"word/media/image1.png\" */\nfunction resolveDocxPath(baseDir: string, target: string): string {\n if (target.startsWith(\"/\")) return target.slice(1);\n const parts = (baseDir + \"/\" + target).split(\"/\");\n const stack: string[] = [];\n for (const p of parts) {\n if (p === \"..\") {\n stack.pop();\n } else if (p !== \".\") {\n stack.push(p);\n }\n }\n return stack.join(\"/\");\n}\n\nasync function parseRels(xml: string): Promise<Map<string, string>> {\n const map = new Map<string, string>();\n const trimmed = xml.trim();\n if (!trimmed) return map;\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n for (const rel of toArr(obj?.Relationships?.[0]?.Relationship)) {\n const a = rel?._attr ?? {};\n if (a.Id && a.Target) map.set(a.Id, a.Target);\n }\n } catch {\n /* ignore */\n }\n return map;\n}\n\nasync function parseCoreProps(xml: string): Promise<DocMeta> {\n const trimmed = xml.trim();\n if (!trimmed) return {};\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n const c = obj?.[\"cp:coreProperties\"]?.[0] ?? obj?.coreProperties?.[0] ?? {};\n return {\n title: c?.[\"dc:title\"]?.[0]?._text ?? undefined,\n author: c?.[\"dc:creator\"]?.[0]?._text ?? undefined,\n subject: c?.[\"dc:subject\"]?.[0]?._text ?? undefined,\n created: c?.[\"dcterms:created\"]?.[0]?._text ?? undefined,\n modified: c?.[\"dcterms:modified\"]?.[0]?._text ?? undefined,\n };\n } catch {\n return {};\n }\n}\n\nasync function parseNumbering(xml: string): Promise<NumMap> {\n const map: NumMap = new Map();\n const trimmed = xml.trim();\n if (!trimmed) return map;\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n const root = obj?.[\"w:numbering\"]?.[0] ?? obj?.numbering?.[0] ?? obj;\n\n // Parse abstractNums\n const absMap = new Map<\n number,\n Map<number, { fmt: string; isOrdered: boolean }>\n >();\n for (const abs of toArr(root?.[\"w:abstractNum\"] ?? root?.abstractNum)) {\n const absId = Number(\n abs?._attr?.[\"w:abstractNumId\"] ?? abs?._attr?.abstractNumId ?? 0,\n );\n const levels = new Map<number, { fmt: string; isOrdered: boolean }>();\n for (const lvl of toArr(abs?.[\"w:lvl\"] ?? abs?.lvl)) {\n const ilvl = Number(lvl?._attr?.[\"w:ilvl\"] ?? lvl?._attr?.ilvl ?? 0);\n const fmtNode =\n lvl?.[\"w:numFmt\"]?.[0]?._attr ?? lvl?.numFmt?.[0]?._attr ?? {};\n const fmt = fmtNode?.[\"w:val\"] ?? fmtNode?.val ?? \"decimal\";\n levels.set(ilvl, { fmt, isOrdered: fmt !== \"bullet\" });\n }\n absMap.set(absId, levels);\n }\n\n // Parse nums\n for (const num of toArr(root?.[\"w:num\"] ?? root?.num)) {\n const numId = Number(num?._attr?.[\"w:numId\"] ?? num?._attr?.numId ?? 0);\n const absRef =\n num?.[\"w:abstractNumId\"]?.[0]?._attr ??\n num?.abstractNumId?.[0]?._attr ??\n {};\n const absId = Number(absRef?.[\"w:val\"] ?? absRef?.val ?? 0);\n const levels = absMap.get(absId) ?? new Map();\n map.set(numId, { levels });\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\nfunction getBody(obj: any): any {\n // XML 파서에 따라 w:document 또는 document 형태일 수 있음\n const doc = obj?.[\"w:document\"]?.[0] ?? obj?.document?.[0] ?? obj;\n const body = doc?.[\"w:body\"]?.[0] ?? doc?.body?.[0] ?? doc;\n\n if (!body) {\n console.error(\"[DocxDecoder] 본문(body)을 찾을 수 없습니다.\");\n }\n return body;\n}\n\nfunction extractDims(body: any): PageDims | null {\n try {\n const sp = body?.[\"w:sectPr\"]?.[0] ?? body?.sectPr?.[0];\n if (!sp) return null;\n const sz = sp?.[\"w:pgSz\"]?.[0]?._attr ?? sp?.pgSz?.[0]?._attr;\n const mar = sp?.[\"w:pgMar\"]?.[0]?._attr ?? sp?.pgMar?.[0]?._attr;\n if (!sz) return null;\n const headerDxa = Number(mar?.[\"w:header\"] ?? mar?.header ?? 0);\n const footerDxa = Number(mar?.[\"w:footer\"] ?? mar?.footer ?? 0);\n return {\n wPt: Metric.dxaToPt(Number(sz[\"w:w\"] ?? sz.w ?? 11906)),\n hPt: Metric.dxaToPt(Number(sz[\"w:h\"] ?? sz.h ?? 16838)),\n mt: Metric.dxaToPt(Number(mar?.[\"w:top\"] ?? mar?.top ?? 1440)),\n mb: Metric.dxaToPt(Number(mar?.[\"w:bottom\"] ?? mar?.bottom ?? 1440)),\n ml: Metric.dxaToPt(Number(mar?.[\"w:left\"] ?? mar?.left ?? 1800)),\n mr: Metric.dxaToPt(Number(mar?.[\"w:right\"] ?? mar?.right ?? 1800)),\n orient:\n (sz[\"w:orient\"] ?? sz.orient) === \"landscape\"\n ? \"landscape\"\n : \"portrait\",\n headerPt: headerDxa > 0 ? Metric.dxaToPt(headerDxa) : undefined,\n footerPt: footerDxa > 0 ? Metric.dxaToPt(footerDxa) : undefined,\n };\n } catch {\n return null;\n }\n}\n\nfunction getBodyElements(body: any): { type: string; node: any }[] {\n const paras = toArr(body?.[\"w:p\"] ?? body?.p);\n const tables = toArr(body?.[\"w:tbl\"] ?? body?.tbl);\n const sdts = toArr(body?.[\"w:sdt\"] ?? body?.sdt);\n\n const childOrder = body?.[\"_childOrder\"] as string[] | undefined;\n if (Array.isArray(childOrder)) {\n const items: { type: string; node: any }[] = [];\n let pi = 0,\n ti = 0,\n si = 0;\n for (const tag of childOrder) {\n if ((tag === \"w:p\" || tag === \"p\") && pi < paras.length) {\n items.push({ type: \"para\", node: paras[pi++] });\n } else if ((tag === \"w:tbl\" || tag === \"tbl\") && ti < tables.length) {\n items.push({ type: \"table\", node: tables[ti++] });\n } else if ((tag === \"w:sdt\" || tag === \"sdt\") && si < sdts.length) {\n items.push({ type: \"sdt\", node: sdts[si++] });\n }\n }\n // Append any remainders\n while (pi < paras.length) items.push({ type: \"para\", node: paras[pi++] });\n while (ti < tables.length)\n items.push({ type: \"table\", node: tables[ti++] });\n while (si < sdts.length) items.push({ type: \"sdt\", node: sdts[si++] });\n return items;\n }\n\n // Fallback: paragraphs, then tables, then sdts\n return [\n ...paras.map((n: any) => ({ type: \"para\", node: n })),\n ...tables.map((n: any) => ({ type: \"table\", node: n })),\n ...sdts.map((n: any) => ({ type: \"sdt\", node: n })),\n ];\n}\n\n// ─── Header/Footer decoding ────────────────────────────────\n\nasync function decodeHeaderFooter(\n kind: \"header\" | \"footer\",\n body: any,\n relsMap: Map<string, string>, // document.xml.rels (기존)\n files: Map<string, Uint8Array>,\n ctx: DecCtx,\n): Promise<Record<string, ParaNode[]> | undefined> {\n try {\n const sp = body?.[\"w:sectPr\"]?.[0] ?? body?.sectPr?.[0];\n if (!sp) return undefined;\n\n const refTag =\n kind === \"header\" ? \"w:headerReference\" : \"w:footerReference\";\n const refs = toArr(sp?.[refTag] ?? sp?.[refTag.replace(\"w:\", \"\")]);\n if (refs.length === 0) return undefined;\n\n const result: Record<string, ParaNode[]> = {};\n\n for (const ref of refs) {\n const type = ref._attr?.[\"w:type\"] ?? ref._attr?.type ?? \"default\";\n const rId = ref._attr?.[\"r:id\"] ?? ref._attr?.[\"r:Id\"] ?? ref._attr?.id;\n if (!rId) continue;\n\n const target = relsMap.get(rId);\n if (!target) continue;\n\n const filePath = resolveDocxPath(\"word\", target);\n const fileData = files.get(filePath);\n if (!fileData) continue;\n\n // ★ 핵심 수정: 헤더/풋터 전용 rels 파일 로드\n const hfFileName = filePath.split(\"/\").pop() ?? \"\";\n const hfRelsPath = `word/_rels/${hfFileName}.rels`;\n const hfRelsData = files.get(hfRelsPath);\n // 헤더/풋터 rels를 document rels와 병합\n let hfRelsMap = relsMap;\n if (hfRelsData) {\n const hfRelsStr = TextKit.decode(hfRelsData).trim();\n const parsed = hfRelsStr\n ? await parseRels(hfRelsStr)\n : new Map<string, string>();\n // 병합 (헤더/풋터 rels 우선)\n hfRelsMap = new Map([...relsMap, ...parsed]);\n }\n\n const xmlStr = TextKit.decode(fileData).trim();\n if (!xmlStr) continue;\n\n const watermark = extractWatermark(xmlStr);\n if (watermark) {\n result[type] = [\n buildPara([\n buildSpan(watermark, { pt: 80, color: \"CCCCCC\", b: true }),\n ]),\n ];\n continue;\n }\n\n try {\n const obj: any = await XmlKit.parseStrict(xmlStr);\n const rootTag = kind === \"header\" ? \"w:hdr\" : \"w:ftr\";\n const root =\n obj?.[rootTag]?.[0] ?? obj?.[rootTag.replace(\"w:\", \"\")]?.[0] ?? obj;\n\n // ctx에 hfRelsMap 임시 적용\n const origRelsMap = ctx.relsMap;\n (ctx as any).relsMap = hfRelsMap;\n const paras = toArr(root?.[\"w:p\"] ?? root?.p);\n result[type] = paras.map((p: any) => decodePara(p, ctx));\n (ctx as any).relsMap = origRelsMap;\n } catch (err) {\n console.warn(`[DocxDecoder] ${kind} (${type}) XML 파싱 실패:`, err);\n continue;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** 워터마크 텍스트 추출 (VML v:textpath 기반) */\nfunction extractWatermark(xml: string): string | null {\n if (!xml.includes(\"v:textpath\")) return null;\n const m = xml.match(/string=\"([^\"]+)\"/);\n return m ? m[1] : null;\n}\n\n// ─── Element decoding ──────────────────────────────────────\n\n//만약에 drawing 태그가 안에 있으면 true 반환\nfunction hasDrawingDeep(node: any): boolean {\n if (!node || typeof node !== \"object\") return false;\n\n if (node[\"w:drawing\"] || node[\"w:pict\"]) return true;\n\n return Object.values(node).some((v) => {\n if (Array.isArray(v)) return v.some(hasDrawingDeep);\n return hasDrawingDeep(v);\n });\n}\n\nfunction decodeElement(\n el: { type: string; node: any },\n ctx: DecCtx,\n): ContentNode | ContentNode[] {\n if (el.type === \"table\") {\n const { value } = ctx.shield.guardGrid(\n el.node,\n (n) => decodeGrid(n as any, ctx),\n (n) => decodeGridSimple(n as any),\n (n) => decodeGridFlat(n as any),\n (n) => decodeGridText(n as any) as unknown as GridNode,\n \"docx:table\",\n );\n return value;\n } else if (el.type === \"sdt\") {\n return decodeSdt(el.node, ctx);\n }\n return decodePara(el.node, ctx);\n}\n\nfunction decodeSdt(sdt: any, ctx: DecCtx): ContentNode[] {\n const content = sdt?.[\"w:sdtContent\"]?.[0] ?? sdt?.sdtContent?.[0];\n if (!content) return [];\n const elements = getBodyElements(content);\n const kids: ContentNode[] = [];\n for (const el of elements) {\n const res = decodeElement(el, ctx);\n if (Array.isArray(res)) kids.push(...res);\n else kids.push(res);\n }\n return kids;\n}\n\nfunction decodePara(p: any, ctx: DecCtx): ParaNode {\n const pPr = p?.[\"w:pPr\"]?.[0] ?? {};\n const alignVal =\n pPr?.[\"w:jc\"]?.[0]?._attr?.[\"w:val\"] ?? pPr?.[\"w:jc\"]?.[0]?._attr?.val;\n const headStyle =\n pPr?.[\"w:pStyle\"]?.[0]?._attr?.[\"w:val\"] ??\n pPr?.[\"w:pStyle\"]?.[0]?._attr?.val ??\n \"\";\n\n // Resolve paragraph style inheritance chain\n const styleInherited = resolveParaStyle(\n headStyle || undefined,\n ctx.paraStyleMap,\n );\n\n const props: ParaProps = {\n align: safeAlign(alignVal),\n heading: parseHeading(headStyle),\n styleId: headStyle || undefined,\n };\n\n // Spacing (before/after/line height) — inline pPr wins over style\n const spacingAttr =\n pPr?.[\"w:spacing\"]?.[0]?._attr ?? pPr?.spacing?.[0]?._attr ?? {};\n const beforeVal = Number(\n spacingAttr?.[\"w:before\"] ?? spacingAttr?.before ?? 0,\n );\n const afterVal = Number(spacingAttr?.[\"w:after\"] ?? spacingAttr?.after ?? 0);\n const lineVal = Number(spacingAttr?.[\"w:line\"] ?? spacingAttr?.line ?? 0);\n const lineRule =\n spacingAttr?.[\"w:lineRule\"] ?? spacingAttr?.lineRule ?? \"auto\";\n if (beforeVal > 0) props.spaceBefore = Metric.dxaToPt(beforeVal);\n else if (styleInherited.pPr?.spaceBefore)\n props.spaceBefore = styleInherited.pPr.spaceBefore;\n if (afterVal > 0) props.spaceAfter = Metric.dxaToPt(afterVal);\n else if (styleInherited.pPr?.spaceAfter)\n props.spaceAfter = styleInherited.pPr.spaceAfter;\n if (lineVal > 0 && lineRule === \"auto\") props.lineHeight = lineVal / 240;\n else if (styleInherited.pPr?.lineHeight)\n props.lineHeight = styleInherited.pPr.lineHeight;\n\n // Indentation\n const indAttr = pPr?.[\"w:ind\"]?.[0]?._attr ?? pPr?.ind?.[0]?._attr ?? {};\n const leftVal = Number(indAttr?.[\"w:left\"] ?? indAttr?.left ?? 0);\n const rightVal = Number(indAttr?.[\"w:right\"] ?? indAttr?.right ?? 0);\n const firstLineVal = Number(\n indAttr?.[\"w:firstLine\"] ?? indAttr?.firstLine ?? 0,\n );\n const hangingVal = Number(indAttr?.[\"w:hanging\"] ?? indAttr?.hanging ?? 0);\n if (leftVal > 0) props.indentPt = Metric.dxaToPt(leftVal);\n else if (styleInherited.pPr?.indentPt)\n props.indentPt = styleInherited.pPr.indentPt;\n if (rightVal > 0) props.indentRightPt = Metric.dxaToPt(rightVal);\n else if (styleInherited.pPr?.indentRightPt)\n props.indentRightPt = styleInherited.pPr.indentRightPt;\n if (firstLineVal > 0) props.firstLineIndentPt = Metric.dxaToPt(firstLineVal);\n else if (hangingVal > 0)\n props.firstLineIndentPt = -Metric.dxaToPt(hangingVal);\n else if (styleInherited.pPr?.firstLineIndentPt)\n props.firstLineIndentPt = styleInherited.pPr.firstLineIndentPt;\n\n // Alignment from style if not set inline\n if (!alignVal && styleInherited.pPr?.align)\n props.align = safeAlign(styleInherited.pPr.align);\n\n // List/numbering\n const numPr = pPr?.[\"w:numPr\"]?.[0] ?? pPr?.numPr?.[0];\n if (numPr) {\n const ilvlNode =\n numPr?.[\"w:ilvl\"]?.[0]?._attr ?? numPr?.ilvl?.[0]?._attr ?? {};\n const numIdNode =\n numPr?.[\"w:numId\"]?.[0]?._attr ?? numPr?.numId?.[0]?._attr ?? {};\n const ilvl = Number(ilvlNode?.[\"w:val\"] ?? ilvlNode?.val ?? 0);\n const numId = Number(numIdNode?.[\"w:val\"] ?? numIdNode?.val ?? 0);\n\n props.listLv = ilvl;\n const numEntry = ctx.numMap.get(numId);\n if (numEntry) {\n const lvlInfo = numEntry.levels.get(ilvl) ?? numEntry.levels.get(0);\n props.listOrd = lvlInfo?.isOrdered ?? false;\n } else {\n // Fallback: numId=1 is typically bullet, numId=2 is numbered\n props.listOrd = numId >= 2;\n }\n }\n\n // pageBreakBefore: paragraph always starts on a new page\n const pbBeforeNode =\n pPr?.[\"w:pageBreakBefore\"]?.[0] ?? pPr?.pageBreakBefore?.[0];\n const hasPageBreakBefore =\n pbBeforeNode != null &&\n (pbBeforeNode?._attr?.[\"w:val\"] ?? pbBeforeNode?._attr?.val ?? \"1\") !== \"0\";\n\n // Resolve all children (runs AND hyperlinks) in document order\n const children = p?.[\"_childOrder\"] as string[] | undefined;\n const kids: (SpanNode | ImgNode | LinkNode)[] = [];\n\n if (Array.isArray(children)) {\n const runsArr = toArr(p?.[\"w:r\"] ?? p?.r);\n const hlArr = toArr(p?.[\"w:hyperlink\"] ?? p?.hyperlink);\n const sdtArr = toArr(p?.[\"w:sdt\"] ?? p?.sdt);\n let ri = 0;\n let hi = 0;\n let si = 0;\n\n for (const tag of children) {\n if (tag === \"w:r\" || tag === \"r\") {\n const run = runsArr[ri++];\n if (run) {\n kids.push(\n ctx.shield.guard(\n () =>\n hasDrawingDeep(run)\n ? decodeRunOrImage(run, ctx)\n : decodeRun(run, ctx, styleInherited.rPr),\n buildSpan(\"\"),\n \"docx:run\",\n ),\n );\n }\n } else if (tag === \"w:hyperlink\" || tag === \"hyperlink\") {\n const hl = hlArr[hi++];\n if (hl) {\n const rId = hl?._attr?.[\"r:id\"] ?? hl?._attr?.id;\n const url = rId ? ctx.relsMap.get(rId) : \"\";\n const hlRuns = toArr(hl?.[\"w:r\"] ?? hl?.r);\n const hlKids = hlRuns.map((r: any) =>\n decodeRun(r, ctx, {\n ...styleInherited.rPr,\n u: true,\n color: \"0000FF\",\n }),\n );\n kids.push({\n tag: \"link\",\n href: url || \"\",\n kids: hlKids,\n });\n }\n } else if (tag === \"w:sdt\" || tag === \"sdt\") {\n const sdt = sdtArr[si++];\n if (sdt) {\n const sdtContent = sdt?.[\"w:sdtContent\"]?.[0] ?? sdt?.sdtContent?.[0];\n if (sdtContent) {\n const innerRuns = toArr(sdtContent?.[\"w:r\"] ?? sdtContent?.r);\n for (const ir of innerRuns) {\n kids.push(\n ctx.shield.guard(\n () =>\n hasDrawingDeep(ir)\n ? decodeRunOrImage(ir, ctx)\n : decodeRun(ir, ctx, styleInherited.rPr),\n buildSpan(\"\"),\n \"docx:run\",\n ),\n );\n }\n }\n }\n }\n }\n } else {\n // Fallback if _childOrder is missing\n const runs = toArr(p?.[\"w:r\"] ?? p?.r);\n const legacyKids: (SpanNode | ImgNode)[] = ctx.shield.guardAll(\n runs,\n (run: any) =>\n hasDrawingDeep(run)\n ? decodeRunOrImage(run, ctx)\n : decodeRun(run, ctx, styleInherited.rPr),\n () => buildSpan(\"\"),\n \"docx:run\",\n );\n kids.push(...legacyKids);\n }\n\n const filteredKids = kids.filter(Boolean) as ParaNode[\"kids\"];\n\n // Prepend pb span when pageBreakBefore is set\n if (hasPageBreakBefore) {\n filteredKids.unshift({ tag: \"span\", props: {}, kids: [buildPb()] });\n }\n\n return buildPara(filteredKids, props);\n}\n\n// 3/28 코드 수정\nfunction decodeRunOrImage(run: any, ctx: DecCtx): SpanNode | ImgNode {\n function findFirstDrawing(node: any): any | null {\n if (!node || typeof node !== \"object\") return null;\n\n if (node[\"w:drawing\"]) return node[\"w:drawing\"][0];\n if (node[\"w:pict\"]) return node[\"w:pict\"][0];\n\n for (const value of Object.values(node)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n const found = findFirstDrawing(v);\n if (found) return found;\n }\n } else {\n const found = findFirstDrawing(value);\n if (found) return found;\n }\n }\n\n return null;\n }\n\n const drawing = findFirstDrawing(run);\n\n if (drawing) {\n const img = decodeDrawing(drawing, ctx);\n if (img) return img;\n }\n\n return decodeRun(run, ctx);\n}\n/** Decode image layout from anchor element */\nfunction decodeImageLayout(anchor: any): ImgLayout {\n const wrap = anchor?.[\"wp:wrapTop\"]?.[0] ?? anchor?.wrapTop?.[0];\n const anchorPos =\n anchor?.[\"wp:anchorPos\"]?.[0]?._attr ?? anchor?.anchorPos?.[0]?._attr ?? {};\n\n const layout: ImgLayout = {\n wrap: \"square\",\n horzAlign: \"left\",\n vertAlign: \"top\",\n horzRelTo: \"page\",\n vertRelTo: \"page\",\n xPt: Number(anchorPos?.x ?? 0) / 12700, // emu to pt\n yPt: Number(anchorPos?.y ?? 0) / 12700, // emu to pt\n };\n\n // Parse wrap type\n if (wrap?.[\"wp:none\"]) layout.wrap = \"none\";\n else if (wrap?.[\"wp:square\"]) layout.wrap = \"square\";\n else if (wrap?.[\"wp:tight\"]) layout.wrap = \"tight\";\n else if (wrap?.[\"wp:through\"]) layout.wrap = \"through\";\n else if (wrap?.[\"wp:behind\"]) layout.wrap = \"behind\";\n else if (wrap?.[\"wp:inFront\"]) layout.wrap = \"front\";\n\n return layout;\n}\n\nfunction decodeDrawing(drawing: any, ctx: DecCtx): ImgNode | null {\n try {\n const inline = drawing?.[\"wp:inline\"]?.[0] ?? drawing?.inline?.[0];\n const anchor = drawing?.[\"wp:anchor\"]?.[0] ?? drawing?.anchor?.[0];\n const container = inline ?? anchor;\n if (!container) return null;\n\n // Get dimensions\n const extent =\n container?.[\"wp:extent\"]?.[0]?._attr ??\n container?.extent?.[0]?._attr ??\n {};\n const cx = Number(extent?.cx ?? 0);\n const cy = Number(extent?.cy ?? 0);\n const wPt = Metric.emuToPt(cx);\n const hPt = Metric.emuToPt(cy);\n\n // Get alt text\n const docPr =\n container?.[\"wp:docPr\"]?.[0]?._attr ?? container?.docPr?.[0]?._attr ?? {};\n const alt = docPr?.descr ?? docPr?.name ?? \"\";\n\n // Navigate to blip\n const graphic = container?.[\"a:graphic\"]?.[0] ?? container?.graphic?.[0];\n const graphicData =\n graphic?.[\"a:graphicData\"]?.[0] ?? graphic?.graphicData?.[0];\n\n // 1. 차트 감지\n if (graphicData?.[\"c:chart\"] || graphicData?.chart) {\n return {\n tag: \"img\",\n b64: \"\", // 플레이스홀더\n mime: \"image/png\",\n w: wPt,\n h: hPt,\n alt: `[차트: ${alt || \"차트\"}]`,\n layout: decodeImageLayout(anchor),\n };\n }\n\n const pic = graphicData?.[\"pic:pic\"]?.[0] ?? graphicData?.pic?.[0];\n const blipFill = pic?.[\"pic:blipFill\"]?.[0] ?? pic?.blipFill?.[0];\n const blip =\n blipFill?.[\"a:blip\"]?.[0]?._attr ?? blipFill?.blip?.[0]?._attr ?? {};\n const rId = blip?.[\"r:embed\"] ?? blip?.embed;\n\n if (!rId) return null;\n\n const target = ctx.relsMap.get(rId);\n if (!target) return null;\n\n let filePath = resolveDocxPath(\"word\", target);\n let fileData = ctx.files.get(filePath);\n\n if (!fileData) {\n filePath = resolveDocxPath(\"word/_rels\", target);\n fileData = ctx.files.get(filePath);\n }\n\n if (!fileData) {\n const fileName = target.split(\"/\").pop() ?? \"\";\n for (const [k, v] of ctx.files) {\n if (fileName && (k.endsWith(\"/\" + fileName) || k === fileName)) {\n fileData = v;\n filePath = k;\n break;\n }\n }\n }\n\n if (!fileData) {\n console.warn(`[DocxDecoder] image not found: \"${target}\"`);\n return null;\n }\n\n const ext = target.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const mimeMap: Record<string, ImgNode[\"mime\"]> = {\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n bmp: \"image/bmp\",\n };\n const mime = mimeMap[ext] ?? \"image/png\";\n console.log(\n `[DocxDecoder] image loaded: ${filePath} (${mime}, ${fileData.length} bytes)`,\n );\n\n // ── layout 추출 ──────────────────────────────────────────\n const layout: ImgLayout = inline\n ? { wrap: \"inline\" }\n : extractAnchorLayout(anchor);\n\n return buildImg(\n TextKit.base64Encode(fileData),\n mime,\n wPt,\n hPt,\n alt || undefined,\n layout,\n );\n } catch {\n return null;\n }\n}\n\n/** w:highlight val → hex 색상 매핑 (OOXML 명세) */\nconst HIGHLIGHT_COLOR_MAP: Record<string, string> = {\n yellow: \"FFFF00\",\n green: \"00FF00\",\n cyan: \"00FFFF\",\n magenta: \"FF00FF\",\n blue: \"0000FF\",\n red: \"FF0000\",\n darkBlue: \"00008B\",\n darkCyan: \"008B8B\",\n darkGreen: \"006400\",\n darkMagenta: \"8B008B\",\n darkRed: \"8B0000\",\n darkYellow: \"808000\",\n darkGray: \"A9A9A9\",\n lightGray: \"D3D3D3\",\n black: \"000000\",\n white: \"FFFFFF\",\n};\n\nfunction decodeRun(\n run: any,\n ctx: DecCtx,\n styleRpr?: ParaStyleDef[\"rPr\"],\n): SpanNode {\n const rPr = run?.[\"w:rPr\"]?.[0] ?? run?.rPr?.[0] ?? {};\n\n // w:vanish — 숨긴 텍스트: run 전체 건너뜀 (빈 span 반환)\n const vanishNode = rPr?.[\"w:vanish\"]?.[0] ?? rPr?.vanish?.[0];\n if (vanishNode != null) {\n const vanishVal =\n vanishNode?._attr?.[\"w:val\"] ?? vanishNode?._attr?.val ?? \"1\";\n if (vanishVal !== \"0\") return buildSpan(\"\");\n }\n\n // w:sz → 없으면 w:szCs 로 fallback (한글 글꼴 크기)\n const szAttr = rPr?.[\"w:sz\"]?.[0]?._attr ?? rPr?.sz?.[0]?._attr ?? {};\n const szVal = szAttr?.[\"w:val\"] ?? szAttr?.val;\n const szCsAttr = rPr?.[\"w:szCs\"]?.[0]?._attr ?? rPr?.szCs?.[0]?._attr ?? {};\n const szCsVal = szCsAttr?.[\"w:val\"] ?? szCsAttr?.val;\n const effectiveSzVal = szVal ?? szCsVal;\n\n const colorAttr =\n rPr?.[\"w:color\"]?.[0]?._attr ?? rPr?.color?.[0]?._attr ?? {};\n const colorVal = colorAttr?.[\"w:val\"] ?? colorAttr?.val;\n\n const fontAttr =\n rPr?.[\"w:rFonts\"]?.[0]?._attr ?? rPr?.rFonts?.[0]?._attr ?? {};\n const fontName =\n fontAttr?.[\"w:ascii\"] ??\n fontAttr?.ascii ??\n fontAttr?.[\"w:hAnsi\"] ??\n fontAttr?.hAnsi ??\n fontAttr?.[\"w:eastAsia\"] ??\n fontAttr?.eastAsia;\n\n const underVal =\n rPr?.[\"w:u\"]?.[0]?._attr?.[\"w:val\"] ?? rPr?.[\"w:u\"]?.[0]?._attr?.val;\n\n // w:shd — 배경색 (낮은 우선순위)\n const shdAttr = rPr?.[\"w:shd\"]?.[0]?._attr ?? rPr?.shd?.[0]?._attr ?? {};\n const shdBg = safeHex(shdAttr?.[\"w:fill\"] ?? shdAttr?.fill);\n\n // w:highlight — 형광펜 색상 (w:shd보다 우선)\n const hlAttr =\n rPr?.[\"w:highlight\"]?.[0]?._attr ?? rPr?.highlight?.[0]?._attr ?? {};\n const hlVal = hlAttr?.[\"w:val\"] ?? hlAttr?.val;\n const bgVal = (hlVal ? HIGHLIGHT_COLOR_MAP[hlVal] : undefined) ?? shdBg;\n\n // w:vertAlign — superscript / subscript\n const vertAlignVal =\n rPr?.[\"w:vertAlign\"]?.[0]?._attr?.[\"w:val\"] ??\n rPr?.[\"w:vertAlign\"]?.[0]?._attr?.val;\n\n // w:position — 글자 상하 이동 (half-point, 양수=위, 음수=아래)\n // vertAlign이 없을 때 보조 판단: ±4 half-pt(≈2pt) 이상이면 sup/sub\n const posAttr =\n rPr?.[\"w:position\"]?.[0]?._attr ?? rPr?.position?.[0]?._attr ?? {};\n const posVal = Number(posAttr?.[\"w:val\"] ?? posAttr?.val ?? 0);\n let isSup = vertAlignVal === \"superscript\";\n let isSub = vertAlignVal === \"subscript\";\n if (!isSup && !isSub && posVal !== 0) {\n if (posVal >= 4) isSup = true;\n else if (posVal <= -4) isSub = true;\n }\n\n // Check bold/italic/strike — val=\"0\" means explicitly OFF\n const bNode = rPr?.[\"w:b\"]?.[0] ?? rPr?.b?.[0];\n const isBold =\n bNode != null &&\n (bNode?._attr?.[\"w:val\"] ?? bNode?._attr?.val ?? \"1\") !== \"0\";\n const iNode = rPr?.[\"w:i\"]?.[0] ?? rPr?.i?.[0];\n const isItalic =\n iNode != null &&\n (iNode?._attr?.[\"w:val\"] ?? iNode?._attr?.val ?? \"1\") !== \"0\";\n const sNode = rPr?.[\"w:strike\"]?.[0] ?? rPr?.strike?.[0];\n const isStrike =\n sNode != null &&\n (sNode?._attr?.[\"w:val\"] ?? sNode?._attr?.val ?? \"1\") !== \"0\";\n\n // Run-level properties: run wins, then fall back to paragraph style inheritance\n const props: TextProps = {\n b: (bNode != null ? isBold : styleRpr?.b) || undefined,\n i: (iNode != null ? isItalic : styleRpr?.i) || undefined,\n u: (underVal ? underVal !== \"none\" : styleRpr?.u) || undefined,\n s: (sNode != null ? isStrike : styleRpr?.s) || undefined,\n sup: isSup || undefined,\n sub: isSub || undefined,\n pt: effectiveSzVal\n ? Metric.halfPtToPt(Number(effectiveSzVal))\n : styleRpr?.pt,\n color: safeHex(colorVal) ?? styleRpr?.color,\n font: fontName ? safeFont(fontName) : styleRpr?.font,\n bg: bgVal,\n };\n\n // Check for field codes (PAGE number)\n const fldChar = run?.[\"w:fldChar\"]?.[0]?._attr ?? run?.fldChar?.[0]?._attr;\n const instrText = run?.[\"w:instrText\"]?.[0];\n\n // Page break: <w:br w:type=\"page\"/>\n const brNodes = toArr(run?.[\"w:br\"] ?? run?.br ?? []);\n for (const br of brNodes) {\n const brType = br?._attr?.[\"w:type\"] ?? br?._attr?.type;\n if (brType === \"page\") {\n return { tag: \"span\", props, kids: [buildPb()] };\n }\n }\n\n const textNodes = toArr(run?.[\"w:t\"] ?? run?.t);\n const content = textNodes\n .map((t: any) => (typeof t === \"string\" ? t : (t?._ ?? t?._text ?? \"\")))\n .join(\"\");\n\n // Handle page number field in instrText\n if (instrText) {\n const instrStr =\n typeof instrText === \"string\" ? instrText : (instrText?._text ?? \"\");\n if (instrStr.trim().toUpperCase() === \"PAGE\") {\n const pageNum: PageNumNode = { tag: \"pagenum\", format: \"decimal\" };\n return { tag: \"span\", props, kids: [pageNum] };\n }\n }\n\n return buildSpan(content, props);\n}\n\n/** Parse all 6 border sides from a w:tblBorders or w:tcBorders node */\nfunction parseBorderDef(bdrNode: any): TblBorderDef {\n const sides: [string, keyof TblBorderDef][] = [\n [\"top\", \"top\"],\n [\"bottom\", \"bottom\"],\n [\"left\", \"left\"],\n [\"right\", \"right\"],\n [\"insideH\", \"insideH\"],\n [\"insideV\", \"insideV\"],\n ];\n const result: TblBorderDef = {};\n for (const [xml, prop] of sides) {\n const bdr = bdrNode?.[\"w:\" + xml]?.[0]?._attr ?? bdrNode?.[xml]?.[0]?._attr;\n if (!bdr) continue;\n const val = bdr?.[\"w:val\"] ?? bdr?.val;\n if (val === \"none\" || val === \"nil\") continue; // explicit none → skip (no border)\n result[prop] = safeStrokeDocx(\n val,\n Number(bdr?.[\"w:sz\"] ?? bdr?.sz ?? 4),\n bdr?.[\"w:color\"] ?? bdr?.color,\n );\n }\n return result;\n}\n\n/** Parse styles.xml and build a map of tblStyle defaults */\nasync function parseStylesMap(xml: string): Promise<StylesMap> {\n const map: StylesMap = new Map();\n const trimmed = xml.trim();\n if (!trimmed) return map;\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n const stylesRoot = obj?.[\"w:styles\"]?.[0] ?? obj?.styles?.[0] ?? obj;\n const styleArr = toArr(stylesRoot?.[\"w:style\"] ?? stylesRoot?.style);\n for (const style of styleArr) {\n const attr = style?._attr ?? {};\n const type = attr?.[\"w:type\"] ?? attr?.type;\n if (type !== \"table\") continue;\n const id = attr?.[\"w:styleId\"] ?? attr?.styleId;\n if (!id) continue;\n const tblPr = style?.[\"w:tblPr\"]?.[0] ?? style?.tblPr?.[0];\n const tblBdrNode = tblPr?.[\"w:tblBorders\"]?.[0] ?? tblPr?.tblBorders?.[0];\n const tblBorders = tblBdrNode ? parseBorderDef(tblBdrNode) : undefined;\n // tcStyle > tcBdr for default cell borders\n const tcStyle = style?.[\"w:tcStyle\"]?.[0] ?? style?.tcStyle?.[0];\n const tcBdrNode = tcStyle?.[\"w:tcBdr\"]?.[0] ?? tcStyle?.tcBdr?.[0];\n if (tcBdrNode) {\n const cellDef = parseBorderDef(tcBdrNode);\n // merge into tblBorders as inner/outer defaults\n if (!tblBorders) {\n map.set(id, { tblBorders: cellDef });\n } else {\n map.set(id, { tblBorders: { ...cellDef, ...tblBorders } });\n }\n } else if (tblBorders) {\n map.set(id, { tblBorders });\n }\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\n/** Parse styles.xml and build a map of paragraph/character style defaults */\nasync function parseParaStyleMap(xml: string): Promise<ParaStyleMap> {\n const map: ParaStyleMap = new Map();\n const trimmed = xml.trim();\n if (!trimmed) return map;\n try {\n const obj: any = await XmlKit.parseStrict(trimmed);\n const stylesRoot = obj?.[\"w:styles\"]?.[0] ?? obj?.styles?.[0] ?? obj;\n const styleArr = toArr(stylesRoot?.[\"w:style\"] ?? stylesRoot?.style);\n for (const style of styleArr) {\n const attr = style?._attr ?? {};\n const type = attr?.[\"w:type\"] ?? attr?.type;\n if (type !== \"paragraph\" && type !== \"character\") continue;\n const id = attr?.[\"w:styleId\"] ?? attr?.styleId;\n if (!id) continue;\n const basedOn = (style?.[\"w:basedOn\"]?.[0]?._attr ??\n style?.basedOn?.[0]?._attr)?.[\"w:val\"];\n\n const def: ParaStyleDef = { basedOn };\n\n // rPr from run properties\n const rPr = style?.[\"w:rPr\"]?.[0] ?? style?.rPr?.[0];\n if (rPr) {\n const szAttr = rPr?.[\"w:sz\"]?.[0]?._attr ?? rPr?.sz?.[0]?._attr ?? {};\n const szVal = szAttr?.[\"w:val\"] ?? szAttr?.val;\n const colorAttr =\n rPr?.[\"w:color\"]?.[0]?._attr ?? rPr?.color?.[0]?._attr ?? {};\n const colorVal = colorAttr?.[\"w:val\"] ?? colorAttr?.val;\n const fontAttr =\n rPr?.[\"w:rFonts\"]?.[0]?._attr ?? rPr?.rFonts?.[0]?._attr ?? {};\n const fontName =\n fontAttr?.[\"w:ascii\"] ??\n fontAttr?.ascii ??\n fontAttr?.[\"w:eastAsia\"] ??\n fontAttr?.eastAsia;\n const bNode = rPr?.[\"w:b\"]?.[0] ?? rPr?.b?.[0];\n const isBold =\n bNode != null &&\n (bNode?._attr?.[\"w:val\"] ?? bNode?._attr?.val ?? \"1\") !== \"0\";\n const iNode = rPr?.[\"w:i\"]?.[0] ?? rPr?.i?.[0];\n const isItalic =\n iNode != null &&\n (iNode?._attr?.[\"w:val\"] ?? iNode?._attr?.val ?? \"1\") !== \"0\";\n const underVal =\n rPr?.[\"w:u\"]?.[0]?._attr?.[\"w:val\"] ?? rPr?.[\"w:u\"]?.[0]?._attr?.val;\n const sNode = rPr?.[\"w:strike\"]?.[0] ?? rPr?.strike?.[0];\n const isStrike =\n sNode != null &&\n (sNode?._attr?.[\"w:val\"] ?? sNode?._attr?.val ?? \"1\") !== \"0\";\n def.rPr = {\n b: isBold || undefined,\n i: isItalic || undefined,\n u: underVal && underVal !== \"none\" ? true : undefined,\n s: isStrike || undefined,\n pt: szVal ? Metric.halfPtToPt(Number(szVal)) : undefined,\n color: safeHex(colorVal),\n font: fontName ? safeFont(fontName) : undefined,\n };\n }\n\n // pPr from paragraph properties\n const pPr = style?.[\"w:pPr\"]?.[0] ?? style?.pPr?.[0];\n if (pPr) {\n const spacingAttr =\n pPr?.[\"w:spacing\"]?.[0]?._attr ?? pPr?.spacing?.[0]?._attr ?? {};\n const beforeVal = Number(\n spacingAttr?.[\"w:before\"] ?? spacingAttr?.before ?? 0,\n );\n const afterVal = Number(\n spacingAttr?.[\"w:after\"] ?? spacingAttr?.after ?? 0,\n );\n const lineVal = Number(\n spacingAttr?.[\"w:line\"] ?? spacingAttr?.line ?? 0,\n );\n const lineRule =\n spacingAttr?.[\"w:lineRule\"] ?? spacingAttr?.lineRule ?? \"auto\";\n const indAttr =\n pPr?.[\"w:ind\"]?.[0]?._attr ?? pPr?.ind?.[0]?._attr ?? {};\n const leftVal = Number(indAttr?.[\"w:left\"] ?? indAttr?.left ?? 0);\n const rightVal = Number(indAttr?.[\"w:right\"] ?? indAttr?.right ?? 0);\n const firstLineVal = Number(\n indAttr?.[\"w:firstLine\"] ?? indAttr?.firstLine ?? 0,\n );\n const hangingVal = Number(\n indAttr?.[\"w:hanging\"] ?? indAttr?.hanging ?? 0,\n );\n const alignVal =\n pPr?.[\"w:jc\"]?.[0]?._attr?.[\"w:val\"] ??\n pPr?.[\"w:jc\"]?.[0]?._attr?.val;\n def.pPr = {\n align: alignVal,\n spaceBefore: beforeVal > 0 ? Metric.dxaToPt(beforeVal) : undefined,\n spaceAfter: afterVal > 0 ? Metric.dxaToPt(afterVal) : undefined,\n lineHeight:\n lineVal > 0 && lineRule === \"auto\" ? lineVal / 240 : undefined,\n indentPt: leftVal > 0 ? Metric.dxaToPt(leftVal) : undefined,\n indentRightPt: rightVal > 0 ? Metric.dxaToPt(rightVal) : undefined,\n firstLineIndentPt:\n firstLineVal > 0\n ? Metric.dxaToPt(firstLineVal)\n : hangingVal > 0\n ? -Metric.dxaToPt(hangingVal)\n : undefined,\n };\n }\n\n map.set(id, def);\n }\n } catch {\n /* non-fatal */\n }\n return map;\n}\n\n/** Resolve paragraph style inheritance chain (max depth 8) */\nfunction resolveParaStyle(\n styleId: string | undefined,\n map: ParaStyleMap,\n): ParaStyleDef {\n let merged: ParaStyleDef = {};\n const visited = new Set<string>();\n let cur = styleId;\n while (cur && !visited.has(cur)) {\n visited.add(cur);\n const def = map.get(cur);\n if (!def) break;\n // Merge: child values win over parent\n if (def.rPr) {\n merged.rPr = { ...def.rPr, ...merged.rPr };\n }\n if (def.pPr) {\n merged.pPr = { ...def.pPr, ...merged.pPr };\n }\n cur = def.basedOn;\n }\n return merged;\n}\n\n/** Resolve final CellProps borders using 3-level priority chain */\nfunction resolveCellBorders(\n cp: CellProps,\n ri: number,\n ci: number,\n rs: number,\n cs: number,\n rowCount: number,\n colCount: number,\n tblBdr: TblBorderDef,\n): CellProps {\n const isTopEdge = ri === 0;\n const isBottomEdge = ri + rs >= rowCount;\n const isLeftEdge = ci === 0;\n const isRightEdge = ci + cs >= colCount;\n\n // Apply tblBorders only where no explicit tcBorder was set\n const resolved: CellProps = { ...cp };\n if (!resolved.top) resolved.top = isTopEdge ? tblBdr.top : tblBdr.insideH;\n if (!resolved.bot)\n resolved.bot = isBottomEdge ? tblBdr.bottom : tblBdr.insideH;\n if (!resolved.left) resolved.left = isLeftEdge ? tblBdr.left : tblBdr.insideV;\n if (!resolved.right)\n resolved.right = isRightEdge ? tblBdr.right : tblBdr.insideV;\n return resolved;\n}\n\nfunction decodeGrid(tbl: any, ctx: DecCtx): GridNode {\n // Parse tblPr for table styles\n const tblPr = tbl?.[\"w:tblPr\"]?.[0] ?? tbl?.tblPr?.[0] ?? {};\n const tblLookAttr =\n tblPr?.[\"w:tblLook\"]?.[0]?._attr ?? tblPr?.tblLook?.[0]?._attr ?? {};\n\n const look: TableLook = {\n firstRow: tblLookAttr?.[\"w:firstRow\"] === \"1\" || undefined,\n lastRow: tblLookAttr?.[\"w:lastRow\"] === \"1\" || undefined,\n firstCol:\n tblLookAttr?.[\"w:firstColumn\"] === \"1\" ||\n tblLookAttr?.[\"w:firstCol\"] === \"1\" ||\n undefined,\n lastCol:\n tblLookAttr?.[\"w:lastColumn\"] === \"1\" ||\n tblLookAttr?.[\"w:lastCol\"] === \"1\" ||\n undefined,\n bandedRows: tblLookAttr?.[\"w:noHBand\"] === \"0\" || undefined,\n bandedCols: tblLookAttr?.[\"w:noVBand\"] === \"0\" || undefined,\n };\n\n // ① tblStyle 기본값 로드\n const tblStyleId = (tblPr?.[\"w:tblStyle\"]?.[0]?._attr ??\n tblPr?.tblStyle?.[0]?._attr)?.[\"w:val\"];\n const styleDef = tblStyleId ? ctx.stylesMap.get(tblStyleId) : undefined;\n let tblBdr: TblBorderDef = styleDef?.tblBorders ?? {};\n\n // ② tblBorders 재정의 (tblStyle보다 우선)\n const tblBordersNode = tblPr?.[\"w:tblBorders\"]?.[0] ?? tblPr?.tblBorders?.[0];\n if (tblBordersNode) {\n const parsed = parseBorderDef(tblBordersNode);\n tblBdr = { ...tblBdr, ...parsed };\n }\n\n // defaultStroke for HWPX/HWP encoders: use insideH (inner horizontal border)\n const defaultStroke = tblBdr.insideH ?? tblBdr.top;\n const gridProps: GridProps = { look, defaultStroke };\n\n // Read column widths from w:tblGrid\n const tblGrid = tbl?.[\"w:tblGrid\"]?.[0] ?? tbl?.tblGrid?.[0];\n if (tblGrid) {\n const gridCols = toArr(tblGrid?.[\"w:gridCol\"] ?? tblGrid?.gridCol ?? []);\n const colWidthsPt = gridCols\n .map((gc: any) =>\n Metric.dxaToPt(Number(gc?._attr?.[\"w:w\"] ?? gc?._attr?.w ?? 0)),\n )\n .filter((w: number) => w > 0);\n if (colWidthsPt.length > 0) gridProps.colWidths = colWidthsPt;\n }\n\n const rowArr = toArr(tbl?.[\"w:tr\"] ?? tbl?.tr);\n\n // ── Pass 1: parse raw cells with vMerge info ──\n interface RawCell {\n cell: any;\n gridSpan: number;\n vMergeRestart: boolean;\n vMergeContinue: boolean;\n }\n const rawGrid: RawCell[][] = rowArr.map((row: any) => {\n const cellArr = toArr(row?.[\"w:tc\"] ?? row?.tc);\n return cellArr.map((cell: any): RawCell => {\n const tcPr = cell?.[\"w:tcPr\"]?.[0] ?? {};\n const gridSpan = Number(tcPr?.[\"w:gridSpan\"]?.[0]?._attr?.[\"w:val\"] ?? 1);\n const vMergeNode = tcPr?.[\"w:vMerge\"]?.[0];\n const vMergeVal = vMergeNode?._attr?.[\"w:val\"] ?? vMergeNode?._attr?.val;\n const vMergeRestart = vMergeVal === \"restart\";\n // vMerge present but val is not \"restart\" → continuation cell\n const vMergeContinue = vMergeNode != null && !vMergeRestart;\n return { cell, gridSpan, vMergeRestart, vMergeContinue };\n });\n });\n\n // ── Pass 2: compute rowSpan for restart cells ──\n // rsMap[ri][ci] = computed rowSpan (only set for restart cells)\n const rsMap: Map<string, number> = new Map();\n for (let ri = 0; ri < rawGrid.length; ri++) {\n let gridCol = 0;\n for (let ci = 0; ci < rawGrid[ri].length; ci++) {\n const rc = rawGrid[ri][ci];\n if (rc.vMergeRestart) {\n let span = 1;\n for (let nr = ri + 1; nr < rawGrid.length; nr++) {\n // Find the cell at the same grid column in the next row\n let col = 0;\n let found = false;\n for (const nc of rawGrid[nr]) {\n if (col === gridCol && nc.vMergeContinue) {\n span++;\n found = true;\n break;\n }\n col += nc.gridSpan;\n }\n if (!found) break;\n }\n rsMap.set(`${ri},${ci}`, span);\n }\n gridCol += rc.gridSpan;\n }\n }\n\n // ── Pass 3: build CellNodes, skip continuation cells ──\n const rowNodes = rawGrid.map((rawRow, ri) => {\n // Check for header row\n const row = rowArr[ri];\n const trPr = row?.[\"w:trPr\"]?.[0] ?? row?.trPr?.[0] ?? {};\n const isHeaderRow =\n trPr?.[\"w:tblHeader\"]?.[0] != null || trPr?.tblHeader?.[0] != null;\n if (ri === 0 && isHeaderRow) gridProps.headerRow = true;\n\n // Row height from w:trHeight\n let rowHeightPt: number | undefined;\n const trHAttr =\n trPr?.[\"w:trHeight\"]?.[0]?._attr ?? trPr?.trHeight?.[0]?._attr;\n if (trHAttr) {\n const hDxa = Number(trHAttr?.[\"w:val\"] ?? trHAttr?.val ?? 0);\n if (hDxa > 0) rowHeightPt = Metric.dxaToPt(hDxa);\n }\n\n const cellNodes: CellNode[] = [];\n for (let ci = 0; ci < rawRow.length; ci++) {\n const rc = rawRow[ci];\n // Skip continuation cells — they are part of a vertical merge\n if (rc.vMergeContinue) continue;\n\n const cell = rc.cell;\n const tcPr = cell?.[\"w:tcPr\"]?.[0] ?? {};\n\n // Cell background\n const bgAttr = tcPr?.[\"w:shd\"]?.[0]?._attr ?? {};\n const bg = safeHex(bgAttr?.[\"w:fill\"] ?? bgAttr?.fill);\n\n // ③ tcBorders 셀 수준 재정의 (우선순위 가장 높음)\n const tcBordersNode = tcPr?.[\"w:tcBorders\"]?.[0] ?? tcPr?.tcBorders?.[0];\n const cp: CellProps = { bg, isHeader: isHeaderRow || undefined };\n\n if (tcBordersNode) {\n const dirs: Array<[string, \"top\" | \"bot\" | \"left\" | \"right\"]> = [\n [\"top\", \"top\"],\n [\"bottom\", \"bot\"],\n [\"left\", \"left\"],\n [\"right\", \"right\"],\n ];\n for (const [xmlTag, propKey] of dirs) {\n const bdr =\n tcBordersNode?.[\"w:\" + xmlTag]?.[0]?._attr ??\n tcBordersNode?.[xmlTag]?.[0]?._attr;\n if (!bdr) continue;\n const val = bdr?.[\"w:val\"] ?? bdr?.val;\n if (val === \"none\" || val === \"nil\") {\n // explicit none: keep as undefined (no border)\n } else {\n cp[propKey] = safeStrokeDocx(\n val,\n Number(bdr?.[\"w:sz\"] ?? bdr?.sz ?? 4),\n bdr?.[\"w:color\"] ?? bdr?.color,\n );\n }\n }\n }\n\n // Vertical alignment\n const vaAttr =\n tcPr?.[\"w:vAlign\"]?.[0]?._attr ?? tcPr?.vAlign?.[0]?._attr ?? {};\n const vaVal = vaAttr?.[\"w:val\"] ?? vaAttr?.val;\n if (vaVal) {\n const vaMap: Record<string, \"top\" | \"mid\" | \"bot\"> = {\n top: \"top\",\n center: \"mid\",\n bottom: \"bot\",\n };\n cp.va = vaMap[vaVal];\n }\n\n // Cell margins (padding)\n const tcMar = tcPr?.[\"w:tcMar\"]?.[0] ?? tcPr?.tcMar?.[0];\n if (tcMar) {\n const top = tcMar?.[\"w:top\"]?.[0]?._attr ?? tcMar?.top?.[0]?._attr;\n const bot =\n tcMar?.[\"w:bottom\"]?.[0]?._attr ?? tcMar?.bottom?.[0]?._attr;\n const left = tcMar?.[\"w:left\"]?.[0]?._attr ?? tcMar?.left?.[0]?._attr;\n const right =\n tcMar?.[\"w:right\"]?.[0]?._attr ?? tcMar?.right?.[0]?._attr;\n\n if (top) cp.padT = Metric.dxaToPt(Number(top?.[\"w:w\"] ?? top?.w ?? 0));\n if (bot) cp.padB = Metric.dxaToPt(Number(bot?.[\"w:w\"] ?? bot?.w ?? 0));\n if (left)\n cp.padL = Metric.dxaToPt(Number(left?.[\"w:w\"] ?? left?.w ?? 0));\n if (right)\n cp.padR = Metric.dxaToPt(Number(right?.[\"w:w\"] ?? right?.w ?? 0));\n }\n\n const rs = rsMap.get(`${ri},${ci}`) ?? 1;\n\n // Compute logical column index for this cell\n let gridColIdx = 0;\n for (let prevCi = 0; prevCi < ci; prevCi++) {\n if (!rawRow[prevCi].vMergeContinue)\n gridColIdx += rawRow[prevCi].gridSpan;\n }\n\n // Apply 3-level border resolution (tblStyle → tblBorders → tcBorders already in cp)\n const colCount =\n gridProps.colWidths?.length ??\n rawGrid[0]?.reduce((s, c) => s + c.gridSpan, 0) ??\n 1;\n const resolvedCp = resolveCellBorders(\n cp,\n ri,\n gridColIdx,\n rs,\n rc.gridSpan,\n rawGrid.length,\n colCount,\n tblBdr,\n );\n\n const paras = toArr(cell?.[\"w:p\"] ?? cell?.p).map((p: any) =>\n decodePara(p, ctx),\n );\n cellNodes.push(\n buildCell(paras.length > 0 ? paras : [buildPara([buildSpan(\"\")])], {\n cs: rc.gridSpan,\n rs,\n props: resolvedCp,\n }),\n );\n }\n return buildRow(cellNodes, rowHeightPt);\n });\n return buildGrid(rowNodes, gridProps);\n}\n\nfunction decodeGridSimple(tbl: any): GridNode {\n const rowArr = toArr(tbl?.[\"w:tr\"] ?? tbl?.tr);\n const rowNodes = rowArr.map((row: any) => {\n const cellArr = toArr(row?.[\"w:tc\"] ?? row?.tc);\n return buildRow(\n cellArr.map((c: any) => buildCell([buildPara([buildSpan(cellText(c))])])),\n );\n });\n return buildGrid(rowNodes);\n}\n\nfunction decodeGridFlat(tbl: any): GridNode {\n return buildGrid([\n buildRow([buildCell([buildPara([buildSpan(tableText(tbl))])])]),\n ]);\n}\n\nfunction decodeGridText(tbl: any): ParaNode {\n return buildPara([buildSpan(tableText(tbl))]);\n}\n\nfunction cellText(cell: any): string {\n return toArr(cell?.[\"w:p\"] ?? cell?.p)\n .map((p: any) =>\n toArr(p?.[\"w:r\"] ?? p?.r)\n .map((r: any) =>\n toArr(r?.[\"w:t\"] ?? r?.t)\n .map((t: any) => (typeof t === \"string\" ? t : (t?._ ?? \"\")))\n .join(\"\"),\n )\n .join(\"\"),\n )\n .join(\" \");\n}\n\nfunction tableText(tbl: any): string {\n return toArr(tbl?.[\"w:tr\"] ?? tbl?.tr)\n .map((row: any) =>\n toArr(row?.[\"w:tc\"] ?? row?.tc)\n .map((c: any) => cellText(c))\n .join(\"\\t\"),\n )\n .join(\"\\n\");\n}\n\nfunction parseHeading(style?: string): 1 | 2 | 3 | 4 | 5 | 6 | undefined {\n if (!style) return undefined;\n const m = style.match(/[Hh]eading(\\d)/);\n if (m) {\n const n = Number(m[1]);\n if (n >= 1 && n <= 6) return n as any;\n }\n return undefined;\n}\n\nregistry.registerDecoder(new DocxDecoder());\n\n// ─── Anchor layout 추출 ─────────────────────────────────────\n\nfunction extractAnchorLayout(anchor: any): ImgLayout {\n const attr = anchor?._attr ?? {};\n const behindDoc = attr.behindDoc === \"1\";\n\n // 텍스트 감싸기 타입\n let wrap: ImgWrap = \"square\";\n if (anchor?.[\"wp:wrapNone\"]?.[0] != null)\n wrap = behindDoc ? \"behind\" : \"none\";\n else if (anchor?.[\"wp:wrapTight\"]?.[0] != null) wrap = \"tight\";\n else if (anchor?.[\"wp:wrapThrough\"]?.[0] != null) wrap = \"through\";\n else if (anchor?.[\"wp:wrapSquare\"]?.[0] != null) wrap = \"square\";\n else if (anchor?.[\"wp:wrapTopAndBottom\"]?.[0] != null) wrap = \"square\";\n else if (anchor?.[\"wp:wrapBehind\"]?.[0] != null || behindDoc) wrap = \"behind\";\n\n // 가로 위치\n const posH = anchor?.[\"wp:positionH\"]?.[0];\n const horzRelTo = parseHorzRelTo(posH?._attr?.relativeFrom);\n const horzAlignTxt = posH?.[\"wp:align\"]?.[0]?._text;\n const horzOffsetTxt = posH?.[\"wp:posOffset\"]?.[0]?._text;\n const horzAlign = horzAlignTxt ? parseHorzAlign(horzAlignTxt) : undefined;\n const xPt =\n horzOffsetTxt && !horzAlignTxt\n ? Metric.emuToPt(Number(horzOffsetTxt))\n : undefined;\n\n // 세로 위치\n const posV = anchor?.[\"wp:positionV\"]?.[0];\n const vertRelTo = parseVertRelTo(posV?._attr?.relativeFrom);\n const vertAlignTxt = posV?.[\"wp:align\"]?.[0]?._text;\n const vertOffsetTxt = posV?.[\"wp:posOffset\"]?.[0]?._text;\n const vertAlign = vertAlignTxt ? parseVertAlign(vertAlignTxt) : undefined;\n const yPt =\n vertOffsetTxt && !vertAlignTxt\n ? Metric.emuToPt(Number(vertOffsetTxt))\n : undefined;\n\n // 텍스트와의 거리\n const distT = attr.distT ? Metric.emuToPt(Number(attr.distT)) : undefined;\n const distB = attr.distB ? Metric.emuToPt(Number(attr.distB)) : undefined;\n const distL = attr.distL ? Metric.emuToPt(Number(attr.distL)) : undefined;\n const distR = attr.distR ? Metric.emuToPt(Number(attr.distR)) : undefined;\n const zOrder = attr.relativeHeight ? Number(attr.relativeHeight) : undefined;\n\n return {\n wrap,\n horzAlign,\n vertAlign,\n horzRelTo,\n vertRelTo,\n xPt,\n yPt,\n distT,\n distB,\n distL,\n distR,\n behindDoc,\n zOrder,\n };\n}\n\nconst HORZ_RELTO_MAP: Record<string, ImgHorzRelTo> = {\n margin: \"margin\",\n leftMargin: \"margin\",\n rightMargin: \"margin\",\n insideMargin: \"margin\",\n outsideMargin: \"margin\",\n column: \"column\",\n page: \"page\",\n character: \"para\",\n paragraph: \"para\",\n};\nconst VERT_RELTO_MAP: Record<string, ImgVertRelTo> = {\n margin: \"margin\",\n topMargin: \"margin\",\n bottomMargin: \"margin\",\n insideMargin: \"margin\",\n outsideMargin: \"margin\",\n line: \"line\",\n page: \"page\",\n paragraph: \"para\",\n};\nconst HORZ_ALIGN_MAP: Record<string, ImgHorzAlign> = {\n left: \"left\",\n center: \"center\",\n right: \"right\",\n inside: \"left\",\n outside: \"right\",\n};\nconst VERT_ALIGN_MAP: Record<string, ImgVertAlign> = {\n top: \"top\",\n center: \"center\",\n bottom: \"bottom\",\n inside: \"top\",\n outside: \"bottom\",\n};\n\nfunction parseHorzRelTo(v?: string): ImgHorzRelTo {\n return HORZ_RELTO_MAP[v ?? \"\"] ?? \"column\";\n}\nfunction parseVertRelTo(v?: string): ImgVertRelTo {\n return VERT_RELTO_MAP[v ?? \"\"] ?? \"para\";\n}\nfunction parseHorzAlign(v?: string): ImgHorzAlign | undefined {\n return HORZ_ALIGN_MAP[v ?? \"\"];\n}\nfunction parseVertAlign(v?: string): ImgVertAlign | undefined {\n return VERT_ALIGN_MAP[v ?? \"\"];\n}\n","import type { DocRoot, ContentNode, ParaNode, SpanNode, ImgNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport type { ParaProps, TextProps } from '../../model/doc-props';\nimport { A4 } from '../../model/doc-props';\nimport { succeed, fail } from '../../contract/result';\nimport { buildRoot, buildSheet, buildPara, buildSpan, buildImg, buildGrid, buildRow, buildCell } from '../../model/builders';\nimport { ShieldedParser } from '../../safety/ShieldedParser';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { registry } from '../../pipeline/registry';\nimport { BaseDecoder } from '../../core/BaseDecoder';\n\nexport class MdDecoder extends BaseDecoder {\n protected getFormat(): string { return 'md'; }\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n const text = this.bytesToString(data);\n const lines = text.split(/\\r?\\n/);\n const kids: ContentNode[] = [];\n\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n\n // Heading\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n const level = headingMatch[1].length as 1 | 2 | 3 | 4 | 5 | 6;\n kids.push(buildPara([buildSpan(headingMatch[2], { b: level <= 2 })], { heading: level }));\n i++; continue;\n }\n\n // Table (pipe + separator line)\n if (line.includes('|') && i + 1 < lines.length && lines[i + 1].match(/^\\s*\\|?\\s*[-:]+\\s*\\|/)) {\n const tableResult = shield.guard(() => parseMdTable(lines, i), null, `md:table@${i}`);\n if (tableResult) { kids.push(tableResult.node); i = tableResult.nextLine; continue; }\n }\n\n // HR\n if (line.match(/^[-*_]{3,}$/)) { kids.push(buildPara([buildSpan('')], {})); i++; continue; }\n\n // List item\n const listMatch = line.match(/^(\\s*)([-*+]|\\d+\\.)\\s+(.+)$/);\n if (listMatch) {\n kids.push(buildPara(parseInline(listMatch[3]), {\n listLv: Math.floor(listMatch[1].length / 2),\n listOrd: /\\d+\\./.test(listMatch[2]),\n }));\n i++; continue;\n }\n\n // Blockquote\n const bqMatch = line.match(/^>\\s*(.*)$/);\n if (bqMatch) { kids.push(buildPara([buildSpan(bqMatch[1])], { indentPt: 28 })); i++; continue; }\n\n // Code block\n if (line.startsWith('```')) {\n const codeLines: string[] = [];\n i++;\n while (i < lines.length && !lines[i].startsWith('```')) { codeLines.push(lines[i]); i++; }\n i++;\n kids.push(buildPara([buildSpan(codeLines.join('\\n'), { font: 'Courier New' })], {}));\n continue;\n }\n\n // Empty line\n if (line.trim() === '') { i++; continue; }\n\n // Regular paragraph — check for alignment div\n const alignMatch = line.match(/^<div\\s+align=\"(center|right|left)\">(.*?)<\\/div>$/i);\n if (alignMatch) {\n const align = alignMatch[1].toLowerCase() as 'left' | 'center' | 'right';\n kids.push(buildPara(parseInline(alignMatch[2]), { align }));\n i++; continue;\n }\n\n // Regular paragraph\n kids.push(buildPara(parseInline(line), {}));\n i++;\n }\n\n warns.push(...shield.flush());\n const sheet = buildSheet(kids.length > 0 ? kids : [buildPara([buildSpan('')])], A4);\n return succeed(buildRoot({}, [sheet]), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`MD decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\nfunction parseInline(text: string): (SpanNode | ImgNode)[] {\n const result: (SpanNode | ImgNode)[] = [];\n let rem = text;\n\n while (rem.length > 0) {\n // Image: ![alt](data:mime;base64,...)\n let m = rem.match(/^(.*?)!\\[([^\\]]*)\\]\\((data:([^;]+);base64,([^)]+))\\)(.*)/s);\n if (m) {\n if (m[1]) result.push(buildSpan(m[1]));\n const mime = m[4] as ImgNode['mime'];\n const validMimes = ['image/png', 'image/jpeg', 'image/gif', 'image/bmp'];\n result.push(buildImg(m[5], validMimes.includes(mime) ? mime : 'image/png', 100, 100, m[2] || undefined));\n rem = m[6]; continue;\n }\n\n // Image: ![alt](url) — non-base64\n m = rem.match(/^(.*?)!\\[([^\\]]*)\\]\\(([^)]+)\\)(.*)/s);\n if (m) {\n if (m[1]) result.push(buildSpan(m[1]));\n // Can't convert URL to base64, just preserve alt text\n result.push(buildSpan(`[이미지: ${m[2] || m[3]}]`));\n rem = m[4]; continue;\n }\n\n // Bold+italic\n m = rem.match(/^(.*?)\\*\\*\\*(.+?)\\*\\*\\*(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { b: true, i: true })); rem = m[3]; continue; }\n\n // Bold\n m = rem.match(/^(.*?)\\*\\*(.+?)\\*\\*(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { b: true })); rem = m[3]; continue; }\n\n // Italic\n m = rem.match(/^(.*?)\\*(.+?)\\*(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { i: true })); rem = m[3]; continue; }\n\n // Strikethrough ~~text~~\n m = rem.match(/^(.*?)~~(.+?)~~(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { s: true })); rem = m[3]; continue; }\n\n // Underline <u>text</u>\n m = rem.match(/^(.*?)<u>(.+?)<\\/u>(.*)/si);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { u: true })); rem = m[3]; continue; }\n\n // Superscript <sup>text</sup>\n m = rem.match(/^(.*?)<sup>(.+?)<\\/sup>(.*)/si);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { sup: true })); rem = m[3]; continue; }\n\n // Subscript <sub>text</sub>\n m = rem.match(/^(.*?)<sub>(.+?)<\\/sub>(.*)/si);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { sub: true })); rem = m[3]; continue; }\n\n // Inline code\n m = rem.match(/^(.*?)`(.+?)`(.*)/s);\n if (m) { if (m[1]) result.push(buildSpan(m[1])); result.push(buildSpan(m[2], { font: 'Courier New' })); rem = m[3]; continue; }\n\n result.push(buildSpan(rem));\n break;\n }\n\n return result.length > 0 ? result : [buildSpan(text)];\n}\n\nfunction parseMdTable(lines: string[], startLine: number): { node: any; nextLine: number } | null {\n const parse = (line: string) => line.split('|').map(c => c.trim()).filter((c, i, arr) => i > 0 || c !== '');\n const headers = parse(lines[startLine]);\n\n let cur = startLine + 2;\n const rows: string[][] = [];\n while (cur < lines.length) {\n if (!lines[cur].includes('|')) break;\n const cells = parse(lines[cur]);\n if (cells.length === 0) break;\n rows.push(cells);\n cur++;\n }\n\n const allRows = [headers, ...rows];\n const gridRows = allRows.map((row, ri) =>\n buildRow(row.map(cell => buildCell([buildPara([buildSpan(cell, ri === 0 ? { b: true } : {})])]))),\n );\n\n return { node: buildGrid(gridRows), nextLine: cur };\n}\n\nregistry.registerDecoder(new MdDecoder());\n","/**\n * HtmlDecoder — HTML → DocRoot\n * 간단한 HTML 파서 (표, 이미지, 스타일 지원)\n */\n\nimport type { DocRoot, ContentNode, ParaNode, SpanNode, ImgNode, GridNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport type { TextProps, ParaProps } from '../../model/doc-props';\nimport { A4 } from '../../model/doc-props';\nimport { succeed, fail } from '../../contract/result';\nimport { buildRoot, buildSheet, buildPara, buildSpan, buildImg, buildGrid, buildRow, buildCell } from '../../model/builders';\nimport { ShieldedParser } from '../../safety/ShieldedParser';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { registry } from '../../pipeline/registry';\nimport { BaseDecoder } from '../../core/BaseDecoder';\n\ninterface Token {\n type: 'tag' | 'text' | 'comment';\n name?: string;\n attrs?: Record<string, string>;\n selfClose?: boolean;\n close?: boolean;\n content?: string;\n}\n\nexport class HtmlDecoder extends BaseDecoder {\n protected getFormat(): string { return 'html'; }\n\n async decode(data: Uint8Array): Promise<Outcome<DocRoot>> {\n const shield = new ShieldedParser();\n const warns: string[] = [];\n\n try {\n const html = this.bytesToString(data);\n const tokens = shield.guard(() => tokenize(html), [], 'html:tokenize');\n const kids = shield.guard(() => parseTokens(tokens), [], 'html:parse');\n\n warns.push(...shield.flush());\n const sheet = buildSheet(kids.length > 0 ? kids : [buildPara([buildSpan('')])], A4);\n return succeed(buildRoot({}, [sheet]), warns);\n } catch (e: any) {\n warns.push(...shield.flush());\n return fail(`HTML decode error: ${e?.message ?? String(e)}`, warns);\n }\n }\n}\n\nfunction tokenize(html: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n\n while (i < html.length) {\n if (html[i] === '<') {\n if (html[i + 1] === '!') {\n const end = html.indexOf('>', i);\n i = end + 1;\n continue;\n }\n\n const isClose = html[i + 1] === '/';\n const start = isClose ? i + 2 : i + 1;\n const end = html.indexOf('>', i);\n if (end === -1) break;\n\n const tagContent = html.slice(start, end).trim();\n const spaceIdx = tagContent.search(/\\s/);\n const name = spaceIdx > 0 ? tagContent.slice(0, spaceIdx) : tagContent;\n const attrsStr = spaceIdx > 0 ? tagContent.slice(spaceIdx + 1).trim() : '';\n\n const attrs: Record<string, string> = {};\n if (attrsStr) {\n const attrRegex = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+)))?/g;\n let m;\n while ((m = attrRegex.exec(attrsStr)) !== null) {\n attrs[m[1].toLowerCase()] = m[2] ?? m[3] ?? m[4] ?? '';\n }\n }\n\n tokens.push({\n type: 'tag',\n name: name.toLowerCase(),\n attrs,\n selfClose: html[end - 1] === '/',\n close: isClose,\n });\n\n i = end + 1;\n } else {\n const end = html.indexOf('<', i);\n const text = end === -1 ? html.slice(i) : html.slice(i, end);\n if (text.trim()) {\n tokens.push({ type: 'text', content: text });\n }\n i = end === -1 ? html.length : end;\n }\n }\n\n return tokens;\n}\n\nfunction parseTokens(tokens: Token[]): ContentNode[] {\n const kids: ContentNode[] = [];\n let i = 0;\n\n while (i < tokens.length) {\n const t = tokens[i];\n\n if (t.type === 'tag' && !t.close) {\n switch (t.name) {\n case 'html':\n // Extract body content\n i++;\n let bodyStart = -1;\n let depth = 1;\n while (i < tokens.length && depth > 0) {\n if (tokens[i].type === 'tag' && !tokens[i].close && tokens[i].name === 'html') depth++;\n else if (tokens[i].type === 'tag' && tokens[i].close && tokens[i].name === 'html') depth--;\n else if (tokens[i].type === 'tag' && !tokens[i].close && tokens[i].name === 'body') {\n bodyStart = i + 1;\n }\n i++;\n }\n if (bodyStart > 0) {\n // Find body end\n let bodyEnd = bodyStart;\n let bodyDepth = 1;\n while (bodyEnd < tokens.length && bodyDepth > 0) {\n if (tokens[bodyEnd].type === 'tag' && !tokens[bodyEnd].close && tokens[bodyEnd].name === 'body') bodyDepth++;\n else if (tokens[bodyEnd].type === 'tag' && tokens[bodyEnd].close && tokens[bodyEnd].name === 'body') bodyDepth--;\n bodyEnd++;\n }\n bodyEnd--;\n const bodyTokens = tokens.slice(bodyStart, bodyEnd);\n const bodyKids = parseTokens(bodyTokens);\n kids.push(...bodyKids);\n }\n continue;\n\n case 'head':\n case 'style':\n case 'script':\n i = skipBlock(tokens, i, t.name);\n continue;\n\n case 'body':\n case 'div':\n case 'section':\n case 'article':\n case 'main':\n // Find closing tag and process contents\n const start = i + 1;\n let end = start;\n let divDepth = 1;\n while (end < tokens.length && divDepth > 0) {\n const t = tokens[end];\n if (t.type === 'tag' && !t.close) {\n if (['html', 'head', 'body', 'div', 'section', 'article', 'main'].includes(t.name ?? '')) divDepth++;\n } else if (t.type === 'tag' && t.close) {\n if (['html', 'head', 'body', 'div', 'section', 'article', 'main'].includes(t.name ?? '')) divDepth--;\n }\n end++;\n }\n end--;\n\n // Process tokens between start and end\n const subTokens = tokens.slice(start, end);\n const subKids = parseTokens(subTokens);\n kids.push(...subKids);\n\n i = end + 1;\n continue;\n\n case 'p':\n i++;\n const paraKids = collectInline(tokens, i, ['p', 'div', 'br']);\n i = paraKids.nextI;\n const align = t.attrs?.style?.includes('text-align: center') ? 'center'\n : t.attrs?.style?.includes('text-align: right') ? 'right'\n : t.attrs?.style?.includes('text-align: left') ? 'left'\n : undefined;\n kids.push(buildPara(paraKids.nodes, { align }));\n continue;\n\n case 'br':\n kids.push(buildPara([buildSpan('')], {}));\n i++;\n continue;\n\n case 'img':\n i++;\n const src = t.attrs?.src;\n const alt = t.attrs?.alt || '';\n if (src?.startsWith('data:')) {\n const match = src.match(/^data:([^;]+);base64,(.+)$/);\n if (match) {\n kids.push(buildPara([buildImg(match[2], match[1] as any, 100, 100, alt)], {}));\n }\n }\n continue;\n\n case 'table':\n i++;\n const rows: any[] = [];\n while (i < tokens.length) {\n if (tokens[i].type === 'tag' && tokens[i].close && tokens[i].name === 'table') {\n i++;\n break;\n }\n if (tokens[i].type === 'tag' && tokens[i].name === 'tr' && !tokens[i].close) {\n i++;\n const cells: any[] = [];\n while (i < tokens.length) {\n if (tokens[i].type === 'tag' && tokens[i].close && tokens[i].name === 'tr') {\n i++;\n break;\n }\n if (tokens[i].type === 'tag' && (tokens[i].name === 'td' || tokens[i].name === 'th') && !tokens[i].close) {\n i++;\n const cellKids = collectInline(tokens, i, ['td', 'th', 'tr']);\n i = cellKids.nextI;\n const isHeader = tokens[i - 2]?.name === 'th';\n const paraKids = cellKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, b: isHeader } } : n);\n cells.push(buildCell([buildPara(paraKids, {})]));\n } else if (tokens[i].type === 'text' && tokens[i].content?.trim()) {\n cells.push(buildCell([buildPara([buildSpan(tokens[i].content!.trim())])]));\n i++;\n } else {\n i++;\n }\n }\n if (cells.length > 0) rows.push(buildRow(cells));\n } else {\n i++;\n }\n }\n if (rows.length > 0) kids.push(buildGrid(rows));\n continue;\n\n case 'ul':\n case 'ol':\n i++;\n const isOrdered = t.name === 'ol';\n while (i < tokens.length) {\n if (tokens[i].type === 'tag' && tokens[i].close && tokens[i].name === t.name) {\n i++;\n break;\n }\n if (tokens[i].type === 'tag' && tokens[i].name === 'li' && !tokens[i].close) {\n i++;\n const liKids = collectInline(tokens, i, ['li', 'ul', 'ol']);\n i = liKids.nextI;\n kids.push(buildPara(liKids.nodes, { listOrd: isOrdered }));\n } else {\n i++;\n }\n }\n continue;\n\n default:\n i++;\n }\n } else if (t.type === 'text' && t.content?.trim()) {\n kids.push(buildPara([buildSpan(t.content!.trim())], {}));\n i++;\n } else {\n i++;\n }\n }\n\n return kids;\n}\n\nfunction collectInline(tokens: Token[], start: number, stopTags: string[]): { nodes: (SpanNode | ImgNode)[]; nextI: number } {\n const nodes: (SpanNode | ImgNode)[] = [];\n let i = start;\n\n while (i < tokens.length) {\n const t = tokens[i];\n\n if (t.type === 'tag' && !t.close) {\n if (t.name && stopTags.includes(t.name)) {\n break;\n }\n\n switch (t.name) {\n case 'b':\n case 'strong':\n i++;\n const boldKids = collectInline(tokens, i, ['b', 'strong', ...stopTags]);\n i = boldKids.nextI;\n nodes.push(...boldKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, b: true } } : n));\n continue;\n\n case 'i':\n case 'em':\n i++;\n const italicKids = collectInline(tokens, i, ['i', 'em', ...stopTags]);\n i = italicKids.nextI;\n nodes.push(...italicKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, i: true } } : n));\n continue;\n\n case 'u':\n i++;\n const underlineKids = collectInline(tokens, i, ['u', ...stopTags]);\n i = underlineKids.nextI;\n nodes.push(...underlineKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, u: true } } : n));\n continue;\n\n case 's':\n case 'strike':\n i++;\n const strikeKids = collectInline(tokens, i, ['s', 'strike', ...stopTags]);\n i = strikeKids.nextI;\n nodes.push(...strikeKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, s: true } } : n));\n continue;\n\n case 'span':\n i++;\n const spanKids = collectInline(tokens, i, ['span', ...stopTags]);\n i = spanKids.nextI;\n const color = t.attrs?.style?.match(/color:\\s*([^;]+)/)?.[1];\n nodes.push(...spanKids.nodes.map(n => n.tag === 'span' ? { ...n, props: { ...n.props, color: color || n.props.color } } : n));\n continue;\n\n case 'img':\n const src = t.attrs?.src;\n const alt = t.attrs?.alt || '';\n if (src?.startsWith('data:')) {\n const match = src.match(/^data:([^;]+);base64,(.+)$/);\n if (match) {\n nodes.push(buildImg(match[2], match[1] as any, 100, 100, alt));\n }\n }\n i++;\n continue;\n\n default:\n i++;\n }\n } else if (t.type === 'text') {\n if (t.content?.trim()) {\n nodes.push(buildSpan(t.content!.trim()));\n }\n i++;\n } else {\n i++;\n }\n }\n\n return { nodes: nodes.length > 0 ? nodes : [buildSpan('')], nextI: i };\n}\n\nfunction skipBlock(tokens: Token[], start: number, name: string): number {\n let i = start + 1;\n let depth = 1;\n while (i < tokens.length && depth > 0) {\n if (tokens[i].type === 'tag') {\n if (!tokens[i].close && tokens[i].name === name) depth++;\n if (tokens[i].close && tokens[i].name === name) depth--;\n }\n i++;\n }\n return i;\n}\n\nregistry.registerDecoder(new HtmlDecoder());\n","/**\n * BaseEncoder - 모든 인코더의 기본 클래스\n *\n * 공통 로직을 제공하여 각 포맷별 인코더가 포맷 특유의 로직만 구현하도록 합니다.\n */\n\nimport type { Encoder } from '../contract/encoder';\nimport type { Outcome } from '../contract/result';\nimport type { DocRoot, AnyNode, ImgNode } from '../model/doc-tree';\nimport { TextKit } from '../toolkit/TextKit';\nimport { ArchiveKit } from '../toolkit/ArchiveKit';\n\n// ─── 타입 정의 ───────────────────────────────────\n\nexport interface ImageData {\n node: ImgNode;\n path: string;\n data: Uint8Array;\n}\n\nexport interface ZipEntry {\n name: string;\n data: Uint8Array;\n}\n\n// ─── BaseEncoder ───────────────────────────────\n\nexport abstract class BaseEncoder implements Encoder {\n readonly format: string = this.getFormat();\n readonly aliases: string[] = this.getAliases();\n\n /** 포맷 이름 반환 (하위 클래스에서 오버라이드) */\n protected abstract getFormat(): string;\n\n /** 별칭 목록 반환 (하위 클래스에서 필요 시 오버라이드) */\n protected getAliases(): string[] { return []; }\n\n /** 문서 인코딩 (하위 클래스에서 오버라이드) */\n abstract encode(doc: DocRoot): Promise<Outcome<Uint8Array>>;\n\n // ─── 공통 유틸리티 메서드 ───────────────────────────\n\n /** 문서 내 모든 이미지 노드 수집 */\n protected collectImages(doc: DocRoot): ImgNode[] {\n const images: ImgNode[] = [];\n this.collectImagesRecursive(doc, images);\n return images;\n }\n\n /** 재귀적으로 이미지 수집 */\n private collectImagesRecursive(node: AnyNode, images: ImgNode[]): void {\n if (node.tag === 'img') {\n images.push(node);\n return;\n }\n\n const children = this.getChildren(node);\n for (const child of children) {\n this.collectImagesRecursive(child, images);\n }\n }\n\n /** 노드의 자식 노드 반환 */\n private getChildren(node: AnyNode): AnyNode[] {\n switch (node.tag) {\n case 'root':\n return node.kids;\n case 'sheet':\n return [...node.kids, ...(node.headers?.default ?? []), ...(node.footers?.default ?? [])];\n case 'para':\n return node.kids;\n case 'span':\n return node.kids;\n case 'link':\n return node.kids;\n case 'row':\n return node.kids;\n case 'cell':\n return node.kids;\n case 'grid':\n return node.kids;\n default:\n return [];\n }\n }\n\n /** base64 문자열을 Uint8Array 로 변환 */\n protected base64ToBytes(b64: string): Uint8Array {\n return TextKit.base64Decode(b64);\n }\n\n /** Uint8Array 를 base64 문자열로 변환 */\n protected bytesToBase64(data: Uint8Array): string {\n return TextKit.base64Encode(data);\n }\n\n /** XML 이스케이프 */\n protected escapeXml(s: string): string {\n return TextKit.escapeXml(s);\n }\n\n /** XML 언이스케이프 */\n protected unescapeXml(s: string): string {\n return TextKit.unescapeXml(s);\n }\n\n /** 문자열을 UTF-8 바이트로 변환 */\n protected stringToBytes(s: string): Uint8Array {\n return TextKit.encode(s);\n }\n\n /** 바이트를 UTF-8 문자열로 변환 */\n protected bytesToString(data: Uint8Array): string {\n return TextKit.decode(data);\n }\n\n /** ZIP 압축 */\n protected async zip(entries: ZipEntry[]): Promise<Uint8Array> {\n return ArchiveKit.zip(entries);\n }\n\n /** ZIP 해제 */\n protected async unzip(data: Uint8Array): Promise<Map<string, Uint8Array>> {\n return ArchiveKit.unzip(data);\n }\n\n /** deflate 압축 */\n protected async deflate(data: Uint8Array): Promise<Uint8Array> {\n return ArchiveKit.deflate(data);\n }\n\n /** inflate 해제 */\n protected async inflate(data: Uint8Array): Promise<Uint8Array> {\n return ArchiveKit.inflate(data);\n }\n\n /** 제어 문자 제거 */\n protected stripControl(s: string): string {\n return TextKit.stripControl(s);\n }\n\n /** 공백 정규화 */\n protected normalizeWhitespace(s: string): string {\n return TextKit.normalizeWhitespace(s);\n }\n}\n","/**\n * HwpxEncoder — DocRoot → HWPX (ZIP + XML)\n *\n * ANYTOHWP에서 영감받은 개선 사항:\n * 1. LangFontBank — 7개 언어 그룹 독립 폰트 레지스트리 (HANGUL/LATIN/HANJA/…)\n * 2. BorderFillBank — 정확한 ID 관리 (하드코딩 \"1\" 제거)\n * 3. readPixelDims — PNG/JPEG 바이너리 헤더에서 실제 픽셀 치수 추출\n * 4. 두 패스 구조 — Pre-scan(등록) → Encode(생성)\n */\n\nimport type {\n DocRoot,\n ParaNode,\n SpanNode,\n GridNode,\n ContentNode,\n ImgNode,\n SheetNode,\n CellNode,\n LinkNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport { BaseEncoder } from \"../../core/BaseEncoder\";\nimport type {\n DocMeta,\n PageDims,\n TextProps,\n ParaProps,\n CellProps,\n Stroke,\n} from \"../../model/doc-props\";\nimport { A4, DEFAULT_STROKE, normalizeDims } from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport { Metric, safeFontToKr } from \"../../safety/StyleBridge\";\nimport { ArchiveKit } from \"../../toolkit/ArchiveKit\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { registry } from \"../../pipeline/registry\";\nimport { HWPX_MIME_TYPE } from \"./constants\";\n\n// ─── HWPX 네임스페이스 ──────────────────────────────────────\nconst NS = [\n 'xmlns:ha=\"http://www.hancom.co.kr/hwpml/2011/app\"',\n 'xmlns:hp=\"http://www.hancom.co.kr/hwpml/2011/paragraph\"',\n 'xmlns:hp10=\"http://www.hancom.co.kr/hwpml/2016/paragraph\"',\n 'xmlns:hs=\"http://www.hancom.co.kr/hwpml/2011/section\"',\n 'xmlns:hc=\"http://www.hancom.co.kr/hwpml/2011/core\"',\n 'xmlns:hh=\"http://www.hancom.co.kr/hwpml/2011/head\"',\n 'xmlns:hhs=\"http://www.hancom.co.kr/hwpml/2011/history\"',\n 'xmlns:hm=\"http://www.hancom.co.kr/hwpml/2011/master-page\"',\n 'xmlns:hpf=\"http://www.hancom.co.kr/schema/2011/hpf\"',\n 'xmlns:dc=\"http://purl.org/dc/elements/1.1/\"',\n 'xmlns:opf=\"http://www.idpf.org/2007/opf\"',\n 'xmlns:ooxmlchart=\"http://www.hancom.co.kr/hwpml/2016/ooxmlchart\"',\n 'xmlns:epub=\"http://www.idpf.org/2007/ops\"',\n 'xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\"',\n].join(\" \");\n\n// ─── LinesegArray Flags 상수 (HWPX 스펙) ─────────────────\n// 첫 번째 lineseg: 0x160000 = 1441792 (시작 줄, 고정 위치)\n// 이후 lineseg: 0x60000 = 393216 (일반 줄)\nconst LINESEG_FLAGS_FIRST = 0x160000; // 1441792 - 첫 줄 (시작, 고정)\nconst LINESEG_FLAGS_OTHER = 0x60000; // 393216 - 이후 줄\n\n// ─── ANYTOHWP 영감: 언어별 폰트 레지스트리 ─────────────────\n// 7개 언어 그룹을 독립적으로 관리 — charPr fontRef의 정확한 ID 생성\nconst LANG_GROUPS = [\n \"HANGUL\",\n \"LATIN\",\n \"HANJA\",\n \"JAPANESE\",\n \"OTHER\",\n \"SYMBOL\",\n \"USER\",\n] as const;\ntype LangGroup = (typeof LANG_GROUPS)[number];\n\nclass LangFontBank {\n // 언어 그룹별 독립 폰트 맵: face → localId (0-based)\n private maps = new Map<LangGroup, Map<string, number>>(\n LANG_GROUPS.map((g) => [g, new Map<string, number>()]),\n );\n\n constructor() {\n // ANYTOHWP 기본값: 모든 그룹에 한컴 기본 폰트 등록 (id=0)\n this.registerAll(\"함초롬바탕\");\n }\n\n /** 모든 언어 그룹에 동일 폰트 등록 */\n registerAll(face: string): void {\n for (const g of LANG_GROUPS) {\n const m = this.maps.get(g)!;\n if (!m.has(face)) m.set(face, m.size);\n }\n }\n\n /** 특정 언어 그룹에 폰트 등록, 이미 있으면 기존 ID 반환 */\n register(lang: LangGroup, face: string): number {\n const m = this.maps.get(lang)!;\n if (m.has(face)) return m.get(face)!;\n const id = m.size;\n m.set(face, id);\n return id;\n }\n\n /** 폰트 이름 → 한글 폰트 여부 판별 (ANYTOHWP 방식) */\n private isKorean(face: string): boolean {\n return (\n /[\\uAC00-\\uD7A3\\u3131-\\u318E]/.test(face) ||\n [\"맑은\", \"나눔\", \"굴림\", \"돋움\", \"바탕\", \"함초롬\", \"한컴\", \"HY\"].some(\n (k) => face.includes(k),\n )\n );\n }\n\n /** TextProps.font 문자열에서 적절한 HANGUL/LATIN 그룹에 등록 */\n registerFont(rawFace: string): { hangulId: number; latinId: number } {\n const face = safeFontToKr(rawFace) || \"함초롬바탕\";\n const isKor = this.isKorean(face);\n // 한글 폰트: HANGUL/HANJA/JAPANESE/OTHER/SYMBOL/USER에 등록\n // 라틴 폰트: LATIN에 등록, 나머지는 기본값(0) 유지\n const hangulId = this.register(\"HANGUL\", isKor ? face : \"함초롬바탕\");\n const latinId = this.register(\"LATIN\", isKor ? \"함초롬바탕\" : face);\n for (const g of [\n \"HANJA\",\n \"JAPANESE\",\n \"OTHER\",\n \"SYMBOL\",\n \"USER\",\n ] as LangGroup[]) {\n this.register(g, isKor ? face : \"함초롬바탕\");\n }\n return { hangulId, latinId };\n }\n\n /** 언어 그룹별 폰트 목록 반환 */\n getFaces(lang: LangGroup): string[] {\n return [...this.maps.get(lang)!.keys()];\n }\n\n getId(lang: LangGroup, face: string): number {\n return this.maps.get(lang)!.get(face) ?? 0;\n }\n\n /** hh:fontfaces XML 생성 */\n toXml(): string {\n let xml = `<hh:fontfaces itemCnt=\"${LANG_GROUPS.length}\">`;\n for (const lang of LANG_GROUPS) {\n const faces = this.getFaces(lang);\n xml += `<hh:fontface lang=\"${lang}\" fontCnt=\"${faces.length}\">`;\n faces.forEach((face, i) => {\n xml +=\n `<hh:font id=\"${i}\" face=\"${esc(face)}\" type=\"TTF\" isEmbedded=\"0\">` +\n `<hh:typeInfo familyType=\"FCAT_UNKNOWN\" weight=\"0\" proportion=\"0\" contrast=\"0\" strokeVariation=\"0\" armStyle=\"0\" letterform=\"0\" midline=\"252\" xHeight=\"255\"/>` +\n `</hh:font>`;\n });\n xml += `</hh:fontface>`;\n }\n return xml + `</hh:fontfaces>`;\n }\n}\n\n// ─── ANYTOHWP 영감: BorderFill 레지스트리 ───────────────────\n// 하드코딩 \"1\" 제거 — 모든 셀/표의 실제 테두리를 추적\n\nconst KIND_MAP: Record<string, string> = {\n solid: \"SOLID\",\n dash: \"DASH\",\n dot: \"DOT\",\n double: \"DOUBLE\",\n none: \"NONE\",\n dash_dot: \"DASH_DOT\",\n dash_dot_dot: \"DASH_DOT_DOT\",\n};\n\n/**\n * 테두리 선 굵기 mm 값을 한글 표준 규격 리스트 중 가장 가까운 값으로 매핑(양자화)합니다.\n */\nfunction quantizeBorderWidth(pt: number): string {\n const mm = pt * 0.3528;\n const standardWidths = [0.1, 0.12, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0];\n let closest = standardWidths[0];\n let minDiff = Math.abs(mm - closest);\n for (let i = 1; i < standardWidths.length; i++) {\n const diff = Math.abs(mm - standardWidths[i]);\n if (diff < minDiff) {\n minDiff = diff;\n closest = standardWidths[i];\n }\n }\n let str = closest.toFixed(2);\n if (str.endsWith(\"0\")) {\n str = str.slice(0, -1);\n }\n if (str.endsWith(\".0\")) {\n str = str.slice(0, -2);\n }\n return `${str} mm`;\n}\n\nclass BorderFillBank {\n private fills: { id: number; xml: string }[] = [];\n private keyMap = new Map<string, number>();\n\n constructor() {\n // id=1: 기본 (테두리 없음) — ANYTOHWP의 기본 초기화 방식\n this._addXml(\n this._buildXml(undefined, undefined, undefined, undefined, undefined),\n );\n // id=2: 표 기본 테두리 (solid 0.5pt black)\n const defS: Stroke = { kind: \"solid\", pt: 0.5, color: \"000000\" };\n this._addXml(this._buildXml(defS, defS, defS, defS, undefined));\n }\n\n private _strokeXml(tag: string, s?: Stroke): string {\n const type =\n s && s.kind !== \"none\" ? (KIND_MAP[s.kind] ?? \"SOLID\") : \"NONE\";\n const w =\n s && s.kind !== \"none\" ? quantizeBorderWidth(s.pt) : \"0.12 mm\";\n const c = s\n ? s.color.startsWith(\"#\")\n ? s.color\n : `#${s.color}`\n : \"#000000\";\n return `<hh:${tag} type=\"${type}\" width=\"${w}\" color=\"${c}\"/>`;\n }\n\n private _buildXml(\n top?: Stroke,\n right?: Stroke,\n bottom?: Stroke,\n left?: Stroke,\n bg?: string,\n ): string {\n const fill = bg\n ? `<hc:fillBrush><hc:winBrush faceColor=\"${bg.startsWith(\"#\") ? bg : \"#\" + bg}\" hatchColor=\"none\" alpha=\"0\"/></hc:fillBrush>`\n : \"\";\n return (\n `<hh:borderFill id=\"__ID__\" threeD=\"0\" shadow=\"0\" centerLine=\"NONE\" breakCellSeparateLine=\"0\">` +\n `<hh:slash type=\"NONE\" Crooked=\"0\" isCounter=\"0\"/>` +\n `<hh:backSlash type=\"NONE\" Crooked=\"0\" isCounter=\"0\"/>` +\n this._strokeXml(\"leftBorder\", left) +\n this._strokeXml(\"rightBorder\", right) +\n this._strokeXml(\"topBorder\", top) +\n this._strokeXml(\"bottomBorder\", bottom) +\n `<hh:diagonal type=\"NONE\" width=\"0.12 mm\" color=\"#000000\"/>` +\n fill +\n `</hh:borderFill>`\n );\n }\n\n private _addXml(xml: string): number {\n const id = this.fills.length + 1;\n this.fills.push({ id, xml: xml.replace(\"__ID__\", String(id)) });\n return id;\n }\n\n private _key(\n top?: Stroke,\n right?: Stroke,\n bottom?: Stroke,\n left?: Stroke,\n bg?: string,\n ): string {\n const sk = (s?: Stroke) =>\n s ? `${s.kind}:${s.pt.toFixed(2)}:${s.color}` : \"none\";\n return `${sk(top)}|${sk(right)}|${sk(bottom)}|${sk(left)}|${bg ?? \"\"}`;\n }\n\n /** 균일 테두리 등록 */\n addUniform(s?: Stroke, bg?: string): number {\n const key = this._key(s, s, s, s, bg);\n if (this.keyMap.has(key)) return this.keyMap.get(key)!;\n const id = this._addXml(this._buildXml(s, s, s, s, bg));\n this.keyMap.set(key, id);\n return id;\n }\n\n /** 방향별 테두리 등록 */\n addPerSide(\n top?: Stroke,\n right?: Stroke,\n bottom?: Stroke,\n left?: Stroke,\n bg?: string,\n ): number {\n const key = this._key(top, right, bottom, left, bg);\n if (this.keyMap.has(key)) return this.keyMap.get(key)!;\n const id = this._addXml(this._buildXml(top, right, bottom, left, bg));\n this.keyMap.set(key, id);\n return id;\n }\n\n /** CellProps에서 적절한 borderFill ID 계산 (하드코딩 \"1\" 완전 제거) */\n addFromCellProps(cp: CellProps, defStroke?: Stroke): number {\n const d = defStroke ?? DEFAULT_STROKE;\n const top = cp.top ?? d;\n const right = cp.right ?? d;\n const bottom = cp.bot ?? d;\n const left = cp.left ?? d;\n const bg = cp.bg;\n const uniform =\n top.kind === right.kind &&\n top.kind === bottom.kind &&\n top.kind === left.kind &&\n top.pt === right.pt &&\n top.pt === bottom.pt &&\n top.pt === left.pt &&\n top.color === right.color &&\n top.color === bottom.color &&\n top.color === left.color;\n return uniform\n ? this.addUniform(top, bg)\n : this.addPerSide(top, right, bottom, left, bg);\n }\n\n toXml(): string {\n return `<hh:borderFills itemCnt=\"${this.fills.length}\">${this.fills.map((f) => f.xml).join(\"\")}</hh:borderFills>`;\n }\n}\n\n// ─── ANYTOHWP 영감: PNG/JPEG 바이너리 헤더에서 픽셀 치수 추출\nfunction readPixelDims(\n b64: string,\n mime: string,\n): { w: number; h: number } | null {\n try {\n const raw = TextKit.base64Decode(b64);\n const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n\n if (mime.includes(\"png\")) {\n // PNG: 시그니처 8바이트 + IHDR 청크 길이(4) + 타입(4) + 너비(4) + 높이(4)\n if (\n raw.length >= 24 &&\n view.getUint32(0) === 0x89504e47 &&\n view.getUint32(4) === 0x0d0a1a0a\n ) {\n return { w: view.getUint32(16), h: view.getUint32(20) };\n }\n } else if (mime.includes(\"jpeg\") || mime.includes(\"jpg\")) {\n // JPEG: SOI(FF D8) 후 SOF0(FF C0) 또는 SOF2(FF C2) 마커 탐색\n let off = 2;\n while (off < raw.length - 4) {\n const marker = view.getUint16(off);\n off += 2;\n if (marker === 0xffc0 || marker === 0xffc2) {\n // SOF: length(2) + precision(1) + height(2) + width(2)\n return { w: view.getUint16(off + 5), h: view.getUint16(off + 3) };\n }\n if ((marker & 0xff00) !== 0xff00) break;\n const segLen = view.getUint16(off);\n off += segLen;\n }\n }\n } catch {\n /* 무시 */\n }\n return null;\n}\n\n// ─── charPr / paraPr 레지스트리 ─────────────────────────────\n\ninterface CharPrDef {\n id: number;\n height: number; // HWPX height 단위 (1000 = 10pt)\n bold: boolean;\n italic: boolean;\n underline: string; // \"NONE\" | \"BOTTOM\"\n strikeout: string; // \"NONE\" | \"SOLID\"\n textColor: string; // \"#RRGGBB\"\n hangulId: number; // HANGUL 그룹 폰트 ID\n latinId: number; // LATIN 그룹 폰트 ID\n bg?: string;\n}\ninterface ParaPrDef {\n id: number;\n align: string;\n leftHwp: number;\n rightHwp: number;\n intentHwp: number;\n prevHwp: number;\n nextHwp: number;\n lineSpacing: number;\n lineSpacingFixed?: number; // HWPUNIT, type=FIXED\n listType?: string;\n listLevel?: number;\n verAlign?: string;\n lineWrap?: string;\n}\ninterface StyleEntry {\n id: number;\n name: string;\n engName: string;\n paraPrIDRef: number;\n charPrIDRef: number;\n}\n\ninterface BinEntry {\n id: string; // \"BIN0001\"\n name: string; // \"BIN0001.png\"\n data: Uint8Array;\n}\n\nfunction charPrKey(p: TextProps): string {\n return `${p.b ? 1 : 0}|${p.i ? 1 : 0}|${p.u ? 1 : 0}|${p.s ? 1 : 0}|${p.pt ?? 10}|${p.color ?? \"000000\"}|${p.font ?? \"\"}|${p.bg ?? \"\"}`;\n}\n\n/**\n * ParaProps 를 해시 키로 변환 (동일 포맷팅 감지용)\n * null/undefined는 0 으로 처리하여 일관성 유지\n */\nfunction paraPrKey(p: ParaProps): string {\n return `${p.align ?? \"left\"}|${p.verAlign ?? \"baseline\"}|${p.lineWrap ?? \"break\"}|${p.listOrd ?? \"\"}|${p.listLv ?? 0}|${p.indentPt ?? 0}|${p.leftMargin ?? 0}|${p.indentRightPt ?? 0}|${p.firstLineIndentPt ?? 0}|${p.spaceBefore ?? 0}|${p.spaceAfter ?? 0}|${p.lineHeight ?? 0}|${p.lineHeightFixed ?? 0}|${p.styleId ?? \"\"}`;\n}\n\n// ─── 인코딩 컨텍스트 ─────────────────────────────────────────\n\ninterface HwpxCtx {\n fontBank: LangFontBank;\n borderFillBank: BorderFillBank;\n charPrs: CharPrDef[];\n charPrMap: Map<string, number>;\n paraPrs: ParaPrDef[];\n paraPrMap: Map<string, number>;\n bins: BinEntry[];\n nextBinNum: number;\n nextElementId: number;\n availableWidth: number; // HWPUNIT\n imgMap: WeakMap<ImgNode, string>;\n nextZOrder: number;\n styleIdToHwpxId: Map<string, number>;\n hwpxStyles: StyleEntry[];\n}\n\nfunction registerCharPr(props: TextProps, ctx: HwpxCtx): number {\n const key = charPrKey(props);\n const existing = ctx.charPrMap.get(key);\n if (existing !== undefined) return existing;\n\n const rawFont = props.font ?? \"함초롬바탕\";\n const { hangulId, latinId } = ctx.fontBank.registerFont(rawFont);\n const id = ctx.charPrs.length;\n\n ctx.charPrs.push({\n id,\n height: Metric.ptToHHeight(props.pt ?? 10),\n bold: !!props.b,\n italic: !!props.i,\n underline: props.u ? \"BOTTOM\" : \"NONE\",\n strikeout: props.s ? \"SOLID\" : \"NONE\",\n textColor: props.color ? `#${props.color}` : \"#000000\",\n hangulId,\n latinId,\n bg: props.bg,\n });\n ctx.charPrMap.set(key, id);\n return id;\n}\n\nconst ALIGN_MAP: Record<string, string> = {\n left: \"LEFT\",\n center: \"CENTER\",\n right: \"RIGHT\",\n justify: \"JUSTIFY\",\n distribute: \"DISTRIBUTE\",\n distribute_space: \"DISTRIBUTE_SPACE\",\n};\n\nconst V_ALIGN_MAP: Record<string, string> = {\n baseline: \"BASELINE\",\n top: \"TOP\",\n center: \"CENTER\",\n bottom: \"BOTTOM\",\n};\n\nconst LINE_WRAP_MAP: Record<string, string> = {\n break: \"BREAK\",\n squeeze: \"SQUEEZE\",\n keep: \"KEEP\",\n};\n\nfunction registerParaPr(props: ParaProps, ctx: HwpxCtx): number {\n const key = paraPrKey(props);\n const existing = ctx.paraPrMap.get(key);\n if (existing !== undefined) return existing;\n\n const id = ctx.paraPrs.length;\n\n const alignStr = props.align ? (ALIGN_MAP[props.align] ?? \"LEFT\") : \"LEFT\";\n const verAlignStr = props.verAlign ? (V_ALIGN_MAP[props.verAlign] ?? \"BASELINE\") : \"BASELINE\";\n const lineWrapStr = props.lineWrap ? (LINE_WRAP_MAP[props.lineWrap] ?? \"BREAK\") : \"BREAK\";\n\n const def: ParaPrDef = {\n id,\n align: alignStr,\n verAlign: verAlignStr,\n lineWrap: lineWrapStr,\n leftHwp: Metric.ptToHwp(props.leftMargin ?? 0),\n rightHwp: Metric.ptToHwp(props.indentRightPt ?? 0),\n intentHwp: Metric.ptToHwp(props.firstLineIndentPt ?? 0),\n prevHwp: Metric.ptToHwp(props.spaceBefore ?? 0),\n nextHwp: Metric.ptToHwp(props.spaceAfter ?? 0),\n lineSpacing: props.lineHeightFixed ? 0 : (props.lineHeight ? Math.round(props.lineHeight * 100) : 160),\n lineSpacingFixed: props.lineHeightFixed ? Metric.ptToHwp(props.lineHeightFixed) : undefined,\n };\n if (props.listOrd !== undefined) {\n def.listType = props.listOrd ? \"DIGIT\" : \"BULLET\";\n def.listLevel = props.listLv ?? 0;\n }\n ctx.paraPrs.push(def);\n ctx.paraPrMap.set(key, id);\n return id;\n}\n\n// ─── 이미지 등록 ─────────────────────────────────────────────\n\nfunction mimeToExt(mime: string): string {\n if (mime.includes(\"jpeg\")) return \"jpg\";\n if (mime.includes(\"gif\")) return \"gif\";\n if (mime.includes(\"bmp\")) return \"bmp\";\n return \"png\";\n}\n\nfunction registerImage(img: ImgNode, ctx: HwpxCtx): void {\n if (ctx.imgMap.has(img)) return;\n const ext = mimeToExt(img.mime);\n const id = `BIN${String(ctx.nextBinNum).padStart(4, \"0\")}`;\n const name = `${id}.${ext}`;\n ctx.nextBinNum++;\n const data = TextKit.base64Decode(img.b64);\n ctx.bins.push({ id, name, data });\n ctx.imgMap.set(img, id);\n}\n\n// ─── 스타일 등록 ─────────────────────────────────────────────\n\nconst STYLE_NAME_MAP: Record<string, string> = {\n Normal: \"바탕글\",\n \"Heading 1\": \"개요 1\",\n \"Heading 2\": \"개요 2\",\n \"Heading 3\": \"개요 3\",\n \"Heading 4\": \"개요 4\",\n \"Heading 5\": \"개요 5\",\n \"Heading 6\": \"개요 6\",\n \"Body Text\": \"본문\",\n};\n\nfunction registerStyle(\n styleId: string,\n paraPrId: number,\n charPrId: number,\n ctx: HwpxCtx,\n): void {\n if (!styleId || ctx.styleIdToHwpxId.has(styleId)) return;\n if (styleId === \"Normal\") {\n ctx.styleIdToHwpxId.set(styleId, 0);\n return;\n }\n const hwpxId = ctx.hwpxStyles.length;\n ctx.styleIdToHwpxId.set(styleId, hwpxId);\n ctx.hwpxStyles.push({\n id: hwpxId,\n name: STYLE_NAME_MAP[styleId] ?? styleId,\n engName: \"\",\n paraPrIDRef: paraPrId,\n charPrIDRef: charPrId,\n });\n}\n\n// ─── Pre-scan: 콘텐츠 순회하며 모든 ID 사전 등록 ─────────────\n\nfunction scanPara(para: ParaNode, ctx: HwpxCtx): void {\n const paraPrId = registerParaPr(para.props, ctx);\n let firstCharPrId = 0;\n let hasFirstSpan = false;\n\n function scanKids(kids: ParaNode[\"kids\"]): void {\n for (const kid of kids) {\n if (kid.tag === \"span\") {\n const cId = registerCharPr(kid.props, ctx);\n if (!hasFirstSpan) {\n firstCharPrId = cId;\n hasFirstSpan = true;\n }\n } else if (kid.tag === \"img\") {\n registerImage(kid, ctx);\n } else if (kid.tag === \"link\") {\n scanKids((kid as LinkNode).kids as ParaNode[\"kids\"]);\n }\n }\n }\n scanKids(para.kids);\n if (para.props.styleId)\n registerStyle(para.props.styleId, paraPrId, firstCharPrId, ctx);\n}\n\nfunction scanGrid(grid: GridNode, ctx: HwpxCtx): void {\n const defStroke = grid.props.defaultStroke ?? DEFAULT_STROKE;\n // 표 기본 테두리 사전 등록\n ctx.borderFillBank.addUniform(defStroke);\n for (const row of grid.kids) {\n for (const cell of row.kids) {\n ctx.borderFillBank.addFromCellProps(cell.props, defStroke);\n for (const p of cell.kids) {\n if (p.tag === 'grid') scanGrid(p, ctx);\n else scanPara(p, ctx);\n }\n }\n }\n}\n\nfunction scanContent(kids: ContentNode[], ctx: HwpxCtx): void {\n for (const kid of kids) {\n if (kid.tag === \"para\") scanPara(kid, ctx);\n else if (kid.tag === \"grid\") scanGrid(kid, ctx);\n }\n}\n\n// ─── Encoder 클래스 ──────────────────────────────────────────\n\nexport class HwpxEncoder extends BaseEncoder {\n protected getFormat(): string { return \"hwpx\"; }\n protected getAliases(): string[] { return [HWPX_MIME_TYPE, \"application/hwp+zip\"]; }\n\n async encode(doc: DocRoot): Promise<Outcome<Uint8Array>> {\n try {\n const sheet = doc.kids[0];\n const dims = normalizeDims(sheet?.dims ?? A4);\n\n const safeML = (dims.ml !== undefined && dims.ml >= 0) ? dims.ml : 70.87;\n const safeMR = (dims.mr !== undefined && dims.mr >= 0) ? dims.mr : 70.87;\n const availableWidth = Math.round(\n Metric.ptToHwp(dims.wPt) -\n Metric.ptToHwp(safeML) -\n Metric.ptToHwp(safeMR),\n );\n\n // 컨텍스트 초기화\n const ctx: HwpxCtx = {\n fontBank: new LangFontBank(), // ANYTOHWP 방식 언어별 폰트\n borderFillBank: new BorderFillBank(), // 하드코딩 없는 테두리 관리\n charPrs: [],\n charPrMap: new Map(),\n paraPrs: [],\n paraPrMap: new Map(),\n bins: [],\n nextBinNum: 1,\n nextElementId: 10000,\n availableWidth,\n imgMap: new WeakMap(),\n nextZOrder: 0,\n styleIdToHwpxId: new Map(),\n hwpxStyles: [],\n };\n\n // id=0 기본 charPr/paraPr 등록\n registerCharPr({}, ctx);\n registerParaPr({}, ctx);\n\n // 바탕글(Normal) 스타일 id=0으로 고정\n ctx.hwpxStyles.push({\n id: 0,\n name: \"바탕글\",\n engName: \"Normal\",\n paraPrIDRef: 0,\n charPrIDRef: 0,\n });\n ctx.styleIdToHwpxId.set(\"Normal\", 0);\n\n // 패스 1: Pre-scan — 모든 charPr/paraPr/이미지/테두리 사전 등록\n scanContent(sheet?.kids ?? [], ctx);\n if (sheet?.headers?.default) for (const p of sheet.headers.default) scanPara(p, ctx);\n if (sheet?.footers?.default) for (const p of sheet.footers.default) scanPara(p, ctx);\n\n // 패스 2: Encode — section 먼저 (borderFill 동적 등록 완료 후 header 생성)\n const sectionData = this.stringToBytes(buildSectionXml(sheet, dims, ctx));\n const headerData = this.stringToBytes(buildHeaderXml(dims, doc.meta, ctx));\n const previewText = extractPreviewText(sheet);\n\n const entries: { name: string; data: Uint8Array; mime: string; compression?: 'STORE' | 'DEFLATE' }[] = [\n {\n name: \"mimetype\",\n data: new TextEncoder().encode(HWPX_MIME_TYPE),\n compression: \"STORE\",\n mime: \"\",\n },\n {\n name: \"version.xml\",\n data: this.stringToBytes(VERSION_XML),\n mime: \"application/xml\",\n },\n {\n name: \"META-INF/container.xml\",\n data: this.stringToBytes(CONTAINER_XML),\n mime: \"application/xml\",\n },\n {\n name: \"META-INF/manifest.xml\",\n data: this.stringToBytes(MANIFEST_XML),\n mime: \"application/xml\",\n },\n {\n name: \"Contents/content.hpf\",\n data: this.stringToBytes(buildContentHpf(ctx, doc.meta)),\n mime: \"application/hwpml-package+xml\",\n },\n {\n name: \"Contents/header.xml\",\n data: headerData,\n mime: \"application/xml\",\n },\n {\n name: \"Contents/section0.xml\",\n data: sectionData,\n mime: \"application/xml\",\n },\n {\n name: \"Preview/PrvText.txt\",\n data: this.stringToBytes(previewText),\n mime: \"text/plain\",\n },\n {\n name: \"settings.xml\",\n data: this.stringToBytes(buildSettingsXml()),\n mime: \"application/xml\",\n },\n ];\n\n for (const bin of ctx.bins) {\n const ext = bin.name.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const ct =\n ext === \"png\"\n ? \"image/png\"\n : ext === \"jpg\" || ext === \"jpeg\"\n ? \"image/jpeg\"\n : ext === \"gif\"\n ? \"image/gif\"\n : \"image/bmp\";\n entries.push({ name: `BinData/${bin.name}`, data: bin.data, mime: ct });\n }\n\n return succeed(await this.zip(entries));\n } catch (e: any) {\n return fail(`HWPX 인코딩 오류: ${e?.message ?? String(e)}`);\n }\n }\n}\n\n// ─── 상수 XML ────────────────────────────────────────────────\n\n// namespace: 실제 HWP가 기대하는 2011 버전 네임스페이스 사용 (owpml.org/2024는 열리지 않음)\nconst VERSION_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<hv:HCFVersion xmlns:hv=\"http://www.hancom.co.kr/hwpml/2011/version\" ` +\n `tagetApplication=\"WORDPROCESSOR\" major=\"5\" minor=\"0\" micro=\"5\" buildNumber=\"0\" ` +\n `os=\"1\" xmlVersion=\"1.4\" application=\"Hancom Office Hangul\" appVersion=\"9, 6, 1, 10097\"/>`;\n\n// container.rdf rootfile 항목 제거 — 실제 HWPX 파일 구조와 일치\nconst CONTAINER_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<ocf:container xmlns:ocf=\"urn:oasis:names:tc:opendocument:xmlns:container\" ` +\n `xmlns:hpf=\"http://www.hancom.co.kr/schema/2011/hpf\">` +\n `<ocf:rootfiles>` +\n `<ocf:rootfile full-path=\"Contents/content.hpf\" media-type=\"application/hwpml-package+xml\"/>` +\n `<ocf:rootfile full-path=\"Preview/PrvText.txt\" media-type=\"text/plain\"/>` +\n `</ocf:rootfiles></ocf:container>`;\n\n// HWPX 파일은 container.rdf 대신 manifest.xml(빈 ODF 매니페스트) 사용\nconst MANIFEST_XML =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<odf:manifest xmlns:odf=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\"/>`;\n\n// ─── content.hpf ─────────────────────────────────────────────\n\nfunction buildContentHpf(ctx: HwpxCtx, meta?: DocMeta): string {\n const title = esc(meta?.title ?? \"\");\n const creator = esc(meta?.author ?? \"text\");\n const subject = esc(meta?.subject ?? \"text\");\n const desc = esc(meta?.desc ?? \"text\");\n const keyword = esc(meta?.keywords ?? \"text\");\n const created =\n meta?.created ?? new Date().toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n const modified = meta?.modified ?? created;\n\n let items =\n `<opf:item id=\"header\" href=\"Contents/header.xml\" media-type=\"application/xml\"/>` +\n `<opf:item id=\"section0\" href=\"Contents/section0.xml\" media-type=\"application/xml\"/>` +\n `<opf:item id=\"settings\" href=\"settings.xml\" media-type=\"application/xml\"/>`;\n\n for (const bin of ctx.bins) {\n const ext = bin.name.split(\".\").pop()?.toLowerCase() ?? \"png\";\n const ct =\n ext === \"png\"\n ? \"image/png\"\n : ext === \"jpg\" || ext === \"jpeg\"\n ? \"image/jpeg\"\n : ext === \"gif\"\n ? \"image/gif\"\n : \"image/bmp\";\n items += `<opf:item id=\"${bin.id}\" href=\"BinData/${bin.name}\" media-type=\"${ct}\" isEmbeded=\"1\"/>`;\n }\n\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<opf:package ${NS} version=\"\" unique-identifier=\"\" id=\"\">` +\n `<opf:metadata>` +\n `<opf:title>${title}</opf:title><opf:language>ko</opf:language>` +\n `<opf:meta name=\"creator\" content=\"text\">${creator}</opf:meta>` +\n `<opf:meta name=\"subject\" content=\"text\">${subject}</opf:meta>` +\n `<opf:meta name=\"description\" content=\"text\">${desc}</opf:meta>` +\n `<opf:meta name=\"CreatedDate\" content=\"text\">${created}</opf:meta>` +\n `<opf:meta name=\"ModifiedDate\" content=\"text\">${modified}</opf:meta>` +\n `<opf:meta name=\"keyword\" content=\"text\">${keyword}</opf:meta>` +\n `<opf:meta name=\"trackchageConfig\" content=\"text\">0</opf:meta>` +\n `</opf:metadata>` +\n `<opf:manifest>${items}</opf:manifest>` +\n `<opf:spine><opf:itemref idref=\"header\"/><opf:itemref idref=\"section0\"/></opf:spine>` +\n `</opf:package>`\n );\n}\n\n// ─── settings.xml ────────────────────────────────────────────\n\nfunction buildSettingsXml(): string {\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<ha:HWPApplicationSetting xmlns:ha=\"http://www.hancom.co.kr/hwpml/2011/app\" ` +\n `xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\">` +\n `<ha:CaretPosition listIDRef=\"0\" paraIDRef=\"0\" pos=\"0\"/>` +\n `<config:config-item-set name=\"PrintInfo\">` +\n `<config:config-item name=\"PrintAutoFootNote\" type=\"boolean\">false</config:config-item>` +\n `<config:config-item name=\"PrintAutoHeadNote\" type=\"boolean\">false</config:config-item>` +\n `<config:config-item name=\"PrintMethod\" type=\"short\">4</config:config-item>` +\n `<config:config-item name=\"OverlapSize\" type=\"short\">0</config:config-item>` +\n `<config:config-item name=\"PrintCropMark\" type=\"short\">0</config:config-item>` +\n `<config:config-item name=\"BinderHoleType\" type=\"short\">0</config:config-item>` +\n `<config:config-item name=\"ZoomX\" type=\"short\">100</config:config-item>` +\n `<config:config-item name=\"ZoomY\" type=\"short\">100</config:config-item>` +\n `</config:config-item-set>` +\n `</ha:HWPApplicationSetting>`\n );\n}\n\nfunction buildNumberingsXml(): string {\n return (\n `<hh:numberings itemCnt=\"1\">` +\n `<hh:numbering id=\"1\" start=\"1\">` +\n `<hh:paraHead start=\"1\" level=\"1\" align=\"LEFT\" ` +\n `useInstWidth=\"1\" autoIndent=\"0\" widthAdjust=\"0\" ` +\n `textOffsetType=\"PERCENT\" textOffset=\"50\" ` +\n `numFormat=\"BULLET\" charPrIDRef=\"0\" checkable=\"0\"/>` +\n `</hh:numbering></hh:numberings>`\n );\n}\n\nfunction buildBulletsXml(): string {\n return (\n `<hh:bullets itemCnt=\"1\">` +\n `<hh:bullet id=\"1\" charPrIDRef=\"0\" start=\"1\" numFormat=\"BULLET\">` +\n `<hh:paraHead level=\"1\" numChar=\"&#x2022;\"/>` +\n `<hh:paraHead level=\"2\" numChar=\"&#x2022;\"/>` +\n `<hh:paraHead level=\"3\" numChar=\"&#x2022;\"/>` +\n `</hh:bullet></hh:bullets>`\n );\n}\n\n// ─── header.xml ──────────────────────────────────────────────\n\n/**\n * Contents/header.xml 용 전역 구역 설정 리스트(secPrList)를 생성합니다.\n */\n/**\n * 페이지 여백 (margin) 과 헤더/푸터 영역 (zone) 을 계산합니다.\n * HWPX spec 에서는 pagePr > margin 의 header/footer 가 헤더/푸터 영역의 높이 (zone height) 입니다.\n * - headerZone: 용지 상단에서 헤더 영역 상단까지의 거리 (headerPt 가 없으면 0)\n * - footerZone: 용지 하단에서 푸터 영역 하단까지의 거리 (footerPt 가 없으면 0)\n * - mt/mb: 용지 상단/하단에서 본문 영역 상단/하단까지의 거리\n */\nfunction buildHeaderSecPrListXml(dims: PageDims): string {\n const wHwp = Metric.ptToHwp(dims.wPt);\n const hHwp = Metric.ptToHwp(dims.hPt);\n const ml = Metric.ptToHwp(dims.ml);\n const mr = Metric.ptToHwp(dims.mr);\n const mt = Metric.ptToHwp(dims.mt);\n const mb = Metric.ptToHwp(dims.mb);\n\n // 헤더/푸터 영역 높이 계산 (HWPX 는 zone height 를 직접 지정)\n // headerPt 가 설정되어 있으면 그 값을 zone height 로 사용, 없으면 0 으로 설정\n const headerZone = dims.headerPt !== undefined && dims.headerPt > 0\n ? Metric.ptToHwp(dims.headerPt)\n : 0;\n const footerZone = dims.footerPt !== undefined && dims.footerPt > 0\n ? Metric.ptToHwp(dims.footerPt)\n : 0;\n\n const pageBorderFill =\n `<hh:pageBorderFill type=\"BOTH\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hh:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hh:pageBorderFill>` +\n `<hh:pageBorderFill type=\"EVEN\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hh:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hh:pageBorderFill>` +\n `<hh:pageBorderFill type=\"ODD\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hh:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hh:pageBorderFill>`;\n\n return (\n `<hh:secPrList itemCnt=\"1\">` +\n `<hh:secPr id=\"0\" textDirection=\"HORIZONTAL\" spaceColumns=\"1134\" tabStop=\"8000\" outlineShapeIDRef=\"0\" memoShapeIDRef=\"0\" textVerticalWidthHead=\"0\" masterPageCnt=\"0\">` +\n `<hh:grid lineGrid=\"0\" charGrid=\"0\" wonggojiFormat=\"0\"/>` +\n `<hh:startNum pageStartsOn=\"BOTH\" page=\"0\" pic=\"0\" tbl=\"0\" equation=\"0\"/>` +\n `<hh:visibility hideFirstHeader=\"0\" hideFirstFooter=\"0\" hideFirstMasterPage=\"0\" border=\"SHOW_ALL\" fill=\"SHOW_ALL\" hideFirstPageNum=\"0\" hideFirstEmptyLine=\"0\" showLineNumber=\"0\"/>` +\n `<hh:lineNumberShape restartType=\"0\" countBy=\"0\" distance=\"0\" startNumber=\"0\"/>` +\n `<hh:pagePr landscape=\"WIDELY\" width=\"${wHwp}\" height=\"${hHwp}\" gutterType=\"LEFT_ONLY\">` +\n `<hh:margin header=\"${headerZone}\" footer=\"${footerZone}\" gutter=\"0\" left=\"${ml}\" right=\"${mr}\" top=\"${mt}\" bottom=\"${mb}\"/>` +\n `</hh:pagePr>` +\n `<hh:colPr id=\"\" type=\"NEWSPAPER\" layout=\"LEFT\" colCount=\"1\" sameSz=\"1\" sameGap=\"0\"/>` +\n `<hh:footNotePr><hh:autoNumFormat type=\"DIGIT\" userChar=\"\" prefixChar=\"\" suffixChar=\"\" supscript=\"1\"/>` +\n `<hh:noteLine length=\"-1\" type=\"SOLID\" width=\"0.25 mm\" color=\"#000000\"/>` +\n `<hh:noteSpacing betweenNotes=\"283\" belowLine=\"0\" aboveLine=\"1000\"/>` +\n `<hh:numbering type=\"CONTINUOUS\" newNum=\"1\"/>` +\n `<hh:placement place=\"EACH_COLUMN\" beneathText=\"0\"/>` +\n `</hh:footNotePr>` +\n `<hh:endNotePr><hh:autoNumFormat type=\"DIGIT\" userChar=\"\" prefixChar=\"\" suffixChar=\"\" supscript=\"1\"/>` +\n `<hh:noteLine length=\"-1\" type=\"SOLID\" width=\"0.25 mm\" color=\"#000000\"/>` +\n `<hh:noteSpacing betweenNotes=\"0\" belowLine=\"0\" aboveLine=\"1000\"/>` +\n `<hh:numbering type=\"CONTINUOUS\" newNum=\"1\"/>` +\n `<hh:placement place=\"END_OF_DOCUMENT\" beneathText=\"0\"/>` +\n `</hh:endNotePr>` +\n pageBorderFill +\n `</hh:secPr>` +\n `</hh:secPrList>`\n );\n}\n\nfunction buildHeaderXml(dims: PageDims, meta: DocMeta, ctx: HwpxCtx): string {\n // 언어별 폰트 (LangFontBank → XML)\n const fontFacesXml = ctx.fontBank.toXml();\n\n // charPr 목록 — 언어별 폰트 ID를 fontRef에 반영 (ANYTOHWP 핵심 개선)\n let charPrXml = \"\";\n for (const cp of ctx.charPrs) {\n const bold = cp.bold ? \"<hh:bold/>\" : \"\";\n const italic = cp.italic ? \"<hh:italic/>\" : \"\";\n const hid = cp.hangulId;\n const lid = cp.latinId;\n const shadeColor = cp.bg ? (cp.bg.startsWith(\"#\") ? cp.bg : `#${cp.bg}`) : \"none\";\n charPrXml +=\n `<hh:charPr id=\"${cp.id}\" height=\"${cp.height}\" textColor=\"${cp.textColor}\" ` +\n `shadeColor=\"${shadeColor}\" useFontSpace=\"0\" useKerning=\"0\" symMark=\"NONE\" borderFillIDRef=\"1\">` +\n `<hh:fontRef hangul=\"${hid}\" latin=\"${lid}\" hanja=\"${hid}\" japanese=\"${hid}\" other=\"${lid}\" symbol=\"${lid}\" user=\"${lid}\"/>` +\n `<hh:ratio hangul=\"100\" latin=\"100\" hanja=\"100\" japanese=\"100\" other=\"100\" symbol=\"100\" user=\"100\"/>` +\n `<hh:spacing hangul=\"0\" latin=\"0\" hanja=\"0\" japanese=\"0\" other=\"0\" symbol=\"0\" user=\"0\"/>` +\n `<hh:relSz hangul=\"100\" latin=\"100\" hanja=\"100\" japanese=\"100\" other=\"100\" symbol=\"100\" user=\"100\"/>` +\n `<hh:offset hangul=\"0\" latin=\"0\" hanja=\"0\" japanese=\"0\" other=\"0\" symbol=\"0\" user=\"0\"/>` +\n bold +\n italic +\n `<hh:underline type=\"${cp.underline}\" shape=\"SOLID\" color=\"#000000\"/>` +\n `<hh:strikeout shape=\"${cp.strikeout}\" color=\"#000000\"/>` +\n `<hh:outline type=\"NONE\"/>` +\n `<hh:shadow type=\"NONE\" color=\"#C0C0C0\" offsetX=\"10\" offsetY=\"10\"/>` +\n `</hh:charPr>`;\n }\n\n // paraPr 목록 (동적 정렬 및 줄바꿈 적용)\n let paraPrXml = \"\";\n for (const pp of ctx.paraPrs) {\n const ver = pp.verAlign ?? \"BASELINE\";\n const wrap = pp.lineWrap ?? \"BREAK\";\n const lsType = pp.lineSpacingFixed !== undefined ? \"FIXED\" : \"PERCENT\";\n const lsValue = pp.lineSpacingFixed !== undefined ? pp.lineSpacingFixed : pp.lineSpacing;\n paraPrXml +=\n `<hh:paraPr id=\"${pp.id}\" tabPrIDRef=\"0\" condense=\"0\" fontLineHeight=\"0\" snapToGrid=\"0\" suppressLineNumbers=\"0\" checked=\"0\">` +\n `<hh:align horizontal=\"${pp.align}\" vertical=\"${ver}\"/>` +\n `<hh:heading type=\"NONE\" idRef=\"0\" level=\"0\"/>` +\n `<hh:breakSetting breakLatinWord=\"KEEP_WORD\" breakNonLatinWord=\"KEEP_WORD\" widowOrphan=\"0\" keepWithNext=\"0\" keepLines=\"0\" pageBreakBefore=\"0\" lineWrap=\"${wrap}\"/>` +\n `<hh:autoSpacing eAsianEng=\"0\" eAsianNum=\"0\"/>` +\n `<hh:margin>` +\n `<hc:intent value=\"${pp.intentHwp}\" unit=\"HWPUNIT\"/>` +\n `<hc:left value=\"${pp.leftHwp}\" unit=\"HWPUNIT\"/>` +\n `<hc:right value=\"${pp.rightHwp}\" unit=\"HWPUNIT\"/>` +\n `<hc:prev value=\"${pp.prevHwp}\" unit=\"HWPUNIT\"/>` +\n `<hc:next value=\"${pp.nextHwp}\" unit=\"HWPUNIT\"/>` +\n `</hh:margin>` +\n `<hh:lineSpacing type=\"${lsType}\" value=\"${lsValue}\" unit=\"HWPUNIT\"/>` +\n `<hh:border borderFillIDRef=\"1\" offsetLeft=\"0\" offsetRight=\"0\" offsetTop=\"0\" offsetBottom=\"0\" connect=\"0\" ignoreMargin=\"0\"/>` +\n `</hh:paraPr>`;\n }\n\n // borderFill 목록 (BorderFillBank → XML)\n const borderFillXml = ctx.borderFillBank.toXml();\n\n // 스타일 목록\n const stylesXml =\n `<hh:styles itemCnt=\"${ctx.hwpxStyles.length}\">` +\n ctx.hwpxStyles\n .map(\n (s) =>\n `<hh:style id=\"${s.id}\" type=\"PARA\" name=\"${esc(s.name)}\" engName=\"${esc(s.engName)}\" ` +\n `paraPrIDRef=\"${s.paraPrIDRef}\" charPrIDRef=\"${s.charPrIDRef}\" nextStyleIDRef=\"0\" langID=\"1042\" lockForm=\"0\"/>`,\n )\n .join(\"\") +\n `</hh:styles>`;\n\n return (\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>` +\n `<hh:head ${NS} version=\"1.2\" secCnt=\"1\">` +\n `<hh:beginNum page=\"1\" footnote=\"1\" endnote=\"1\" pic=\"1\" tbl=\"1\" equation=\"1\"/>` +\n `<hh:refList>` +\n fontFacesXml +\n borderFillXml +\n `<hh:charProperties itemCnt=\"${ctx.charPrs.length}\">${charPrXml}</hh:charProperties>` +\n `<hh:tabProperties itemCnt=\"1\"><hh:tabPr id=\"0\" autoTabLeft=\"0\" autoTabRight=\"0\"/></hh:tabProperties>` +\n buildNumberingsXml() +\n buildBulletsXml() +\n `<hh:paraProperties itemCnt=\"${ctx.paraPrs.length}\">${paraPrXml}</hh:paraProperties>` +\n stylesXml +\n `</hh:refList>` +\n buildHeaderSecPrListXml(dims) +\n `<hh:compatibleDocument targetProgram=\"HWP201X\"><hh:layoutCompatibility/></hh:compatibleDocument>` +\n `<hh:docOption><hh:linkinfo path=\"\" pageInherit=\"0\" footnoteInherit=\"0\"/></hh:docOption>` +\n `<hh:trackchageConfig flags=\"56\"/>` +\n `</hh:head>`\n );\n}\n\n// ─── section0.xml ────────────────────────────────────────────\n\nfunction buildHeaderFooterRunXml(\n sheet: SheetNode,\n dims: PageDims,\n ctx: HwpxCtx,\n): string {\n const headers = sheet.headers || {};\n const footers = sheet.footers || {};\n const hasAny = Object.keys(headers).length > 0 || Object.keys(footers).length > 0;\n if (!hasAny) return \"\";\n\n const availW = ctx.availableWidth;\n const mtHwp = Metric.ptToHwp(dims.mt);\n const mbHwp = Metric.ptToHwp(dims.mb);\n const headerZoneH = dims.headerPt ? Metric.ptToHwp(dims.headerPt) : 4252; // 기본값 15mm\n const footerZoneH = dims.footerPt ? Metric.ptToHwp(dims.footerPt) : 4252; // 기본값 15mm\n\n let inner = \"\";\n\n // 1. 첫 페이지 숨김 설정 (first 헤더/푸터가 있으면 활성화)\n const hideFirst = !!(headers.first || footers.first);\n inner += `<hp:ctrl><hp:pageHiding hideHeader=\"${hideFirst ? 1 : 0}\" hideFooter=\"${hideFirst ? 1 : 0}\" hideMasterPage=\"0\" hideBorder=\"0\" hideFill=\"0\" hidePageNum=\"0\"/></hp:ctrl>`;\n\n // 2. 헤더들 생성\n for (const [type, paras] of Object.entries(headers)) {\n if (!Array.isArray(paras) || paras.length === 0) continue;\n const applyPageType = type === \"even\" ? \"EVEN\" : (type === \"default\" || type === \"first\" ? \"BOTH\" : \"ODD\");\n const savedId = ctx.nextElementId;\n ctx.nextElementId = 0;\n const parasXml = paras.map((p) => encodeParaPositioned(p, ctx, 0, \"\", availW).xml).join(\"\");\n ctx.nextElementId = savedId;\n inner +=\n `<hp:ctrl>` +\n `<hp:header id=\"1\" applyPageType=\"${applyPageType}\">` +\n `<hp:subList id=\"\" textDirection=\"HORIZONTAL\" lineWrap=\"BREAK\" vertAlign=\"TOP\" ` +\n `linkListIDRef=\"0\" linkListNextIDRef=\"0\" textWidth=\"${availW}\" textHeight=\"${headerZoneH}\" ` +\n `hasTextRef=\"0\" hasNumRef=\"0\">` +\n parasXml +\n `</hp:subList>` +\n `</hp:header>` +\n `</hp:ctrl>`;\n }\n\n // 3. 푸터들 생성\n for (const [type, paras] of Object.entries(footers)) {\n if (!Array.isArray(paras) || paras.length === 0) continue;\n const applyPageType = type === \"even\" ? \"EVEN\" : (type === \"default\" || type === \"first\" ? \"BOTH\" : \"ODD\");\n const savedId = ctx.nextElementId;\n ctx.nextElementId = 0;\n const parasXml = paras.map((p) => encodeParaPositioned(p, ctx, 0, \"\", availW).xml).join(\"\");\n ctx.nextElementId = savedId;\n inner +=\n `<hp:ctrl>` +\n `<hp:footer id=\"2\" applyPageType=\"${applyPageType}\">` +\n `<hp:subList id=\"\" textDirection=\"HORIZONTAL\" lineWrap=\"BREAK\" vertAlign=\"BOTTOM\" ` +\n `linkListIDRef=\"0\" linkListNextIDRef=\"0\" textWidth=\"${availW}\" textHeight=\"${footerZoneH}\" ` +\n `hasTextRef=\"0\" hasNumRef=\"0\">` +\n parasXml +\n `</hp:subList>` +\n `</hp:footer>` +\n `</hp:ctrl>`;\n }\n\n return `<hp:run charPrIDRef=\"0\" charTcId=\"0\">${inner}</hp:run>`;\n}\n\nfunction buildSectionXml(\n sheet: SheetNode | undefined,\n dims: PageDims,\n ctx: HwpxCtx,\n): string {\n const secPrXml = buildSecPrXml(dims);\n const kids = sheet?.kids ?? [];\n const hfRunXml = sheet ? buildHeaderFooterRunXml(sheet, dims, ctx) : \"\";\n\n // 가용 너비 계산 (HWPUNIT)\n const availWidth = Math.max(\n 1000,\n Metric.ptToHwp(dims.wPt) - Metric.ptToHwp(dims.ml) - Metric.ptToHwp(dims.mr),\n );\n ctx.availableWidth = availWidth;\n\n let contentXml = \"\";\n let vertPos = 0;\n\n for (let i = 0; i < kids.length; i++) {\n const kid = kids[i];\n const isFirst = i === 0;\n // secPr은 hs:sec 하위에 직접 기입하므로 문단 내에는 기입하지 않습니다.\n const curSecPr = \"\";\n const curHfRun = isFirst ? hfRunXml : \"\";\n\n if (kid.tag === \"para\") {\n const { xml, nextVertPos, hasPageBreak } = encodeParaPositioned(\n kid,\n ctx,\n vertPos,\n curSecPr,\n availWidth,\n curHfRun,\n );\n contentXml += xml;\n vertPos = nextVertPos; // 페이지 브레이크 발생 시에도 누적 절대 좌표 유지\n } else if (kid.tag === \"grid\") {\n const { xml, nextVertPos, hasPageBreak } = encodeGridPositioned(\n kid,\n ctx,\n vertPos,\n curSecPr,\n curHfRun,\n );\n contentXml += xml;\n vertPos = nextVertPos; // 페이지 브레이크 발생 시에도 누적 절대 좌표 유지\n }\n }\n\n if (kids.length === 0) {\n // 빈 문서 — 최소 단락 1개 필수\n const fs = 1000;\n const vs = 1600;\n const { xml: linesegXml } = buildLinesegarray(\" \", 0, fs, vs / (fs / 100), availWidth);\n contentXml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"0\" styleIDRef=\"0\" pageBreak=\"0\" columnBreak=\"0\" merged=\"0\" paraTcId=\"0\">` +\n hfRunXml +\n `<hp:run charPrIDRef=\"0\" charTcId=\"0\"><hp:t xml:space=\"preserve\"> </hp:t></hp:run>` +\n linesegXml +\n `</hp:p>`;\n }\n\n // hs:sec 바로 아래 직계 첫 자식으로 secPrXml 기입!\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><hs:sec ${NS} xmlns:hwpunitchar=\"http://www.hancom.co.kr/hwpml/2016/HwpUnitChar\">${secPrXml}${contentXml}</hs:sec>`;\n}\n\nfunction buildSecPrXml(dims: PageDims): string {\n const wHwp = Metric.ptToHwp(dims.wPt);\n const hHwp = Metric.ptToHwp(dims.hPt);\n const ml = Metric.ptToHwp(dims.ml);\n const mr = Metric.ptToHwp(dims.mr);\n const mt = Metric.ptToHwp(dims.mt);\n const mb = Metric.ptToHwp(dims.mb);\n // HWPX margin header/footer = header/footer ZONE HEIGHT (not distance from paper edge)\n // = top_hwp - header_from_top_hwp (and bottom_hwp - footer_from_bottom_hwp)\n const headerZone = dims.headerPt ? Metric.ptToHwp(dims.headerPt) : 0;\n const footerZone = dims.footerPt ? Metric.ptToHwp(dims.footerPt) : 0;\n\n const pageBorderFill =\n `<hp:pageBorderFill type=\"BOTH\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hp:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hp:pageBorderFill>` +\n `<hp:pageBorderFill type=\"EVEN\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hp:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hp:pageBorderFill>` +\n `<hp:pageBorderFill type=\"ODD\" borderFillIDRef=\"1\" textBorder=\"PAPER\" headerInside=\"0\" footerInside=\"0\" fillArea=\"PAPER\">` +\n `<hp:offset left=\"1417\" right=\"1417\" top=\"1417\" bottom=\"1417\"/>` +\n `</hp:pageBorderFill>`;\n\n return (\n `<hp:secPr id=\"0\" textDirection=\"HORIZONTAL\" spaceColumns=\"1134\" tabStop=\"8000\" outlineShapeIDRef=\"0\" memoShapeIDRef=\"0\" textVerticalWidthHead=\"0\" masterPageCnt=\"0\">` +\n `<hp:grid lineGrid=\"0\" charGrid=\"0\" wonggojiFormat=\"0\"/>` +\n `<hp:startNum pageStartsOn=\"BOTH\" page=\"0\" pic=\"0\" tbl=\"0\" equation=\"0\"/>` +\n `<hp:visibility hideFirstHeader=\"0\" hideFirstFooter=\"0\" hideFirstMasterPage=\"0\" border=\"SHOW_ALL\" fill=\"SHOW_ALL\" hideFirstPageNum=\"0\" hideFirstEmptyLine=\"0\" showLineNumber=\"0\"/>` +\n `<hp:lineNumberShape restartType=\"0\" countBy=\"0\" distance=\"0\" startNumber=\"0\"/>` +\n `<hp:pagePr landscape=\"WIDELY\" width=\"${wHwp}\" height=\"${hHwp}\" gutterType=\"LEFT_ONLY\">` +\n `<hp:margin header=\"${headerZone}\" footer=\"${footerZone}\" gutter=\"0\" left=\"${ml}\" right=\"${mr}\" top=\"${mt}\" bottom=\"${mb}\"/>` +\n `</hp:pagePr>` +\n `<hp:colPr id=\"\" type=\"NEWSPAPER\" layout=\"LEFT\" colCount=\"1\" sameSz=\"1\" sameGap=\"0\"/>` +\n `<hp:footNotePr><hp:autoNumFormat type=\"DIGIT\" userChar=\"\" prefixChar=\"\" suffixChar=\"\" supscript=\"1\"/>` +\n `<hp:noteLine length=\"-1\" type=\"SOLID\" width=\"0.25 mm\" color=\"#000000\"/>` +\n `<hp:noteSpacing betweenNotes=\"283\" belowLine=\"0\" aboveLine=\"1000\"/>` +\n `<hp:numbering type=\"CONTINUOUS\" newNum=\"1\"/>` +\n `<hp:placement place=\"EACH_COLUMN\" beneathText=\"0\"/>` +\n `</hp:footNotePr>` +\n `<hp:endNotePr><hp:autoNumFormat type=\"DIGIT\" userChar=\"\" prefixChar=\"\" suffixChar=\"\" supscript=\"1\"/>` +\n `<hp:noteLine length=\"-1\" type=\"SOLID\" width=\"0.25 mm\" color=\"#000000\"/>` +\n `<hp:noteSpacing betweenNotes=\"0\" belowLine=\"0\" aboveLine=\"1000\"/>` +\n `<hp:numbering type=\"CONTINUOUS\" newNum=\"1\"/>` +\n `<hp:placement place=\"END_OF_DOCUMENT\" beneathText=\"0\"/>` +\n `</hp:endNotePr>` +\n pageBorderFill +\n `</hp:secPr>`\n );\n}\n\n// ─── 줄 정보 XML (linesegarray) ──────────────────────────────\n// 가이드 준수: 실제 시각적 줄 단위로 lineseg 생성\n\nfunction buildLinesegarray(\n text: string,\n vertPosStart: number,\n fontSize: number,\n lineSpacingPct: number,\n horzSize: number,\n): { xml: string; totalHeight: number } {\n const vertsizeLine = Math.round((fontSize * lineSpacingPct) / 100);\n const spacing = vertsizeLine - fontSize;\n const baseline = Math.round(fontSize * 0.83);\n\n if (text.length === 0) {\n const xml = `<hp:linesegarray>` +\n `<hp:lineseg textpos=\"0\" vertpos=\"${vertPosStart}\" vertsize=\"${vertsizeLine}\" ` +\n `textheight=\"${fontSize}\" baseline=\"${baseline}\" spacing=\"${spacing}\" ` +\n `horzpos=\"0\" horzsize=\"${horzSize}\" flags=\"${LINESEG_FLAGS_FIRST}\"/>` +\n `</hp:linesegarray>`;\n return { xml, totalHeight: vertsizeLine };\n }\n\n // 문자 단위 정밀 가로 폭 계산 및 자동 줄바꿈 알고리즘 (개행 문자 지원)\n const lines: { startPos: number; width: number }[] = [];\n let currentLineWidth = 0;\n let lineStartIdx = 0;\n\n for (let i = 0; i < text.length; i++) {\n const charCode = text.charCodeAt(i);\n\n // 개행 문자 (\\n 또는 \\r) 감지 시, 현재 줄 세그먼트를 무조건 마감하고 새로운 줄 시작\n if (charCode === 10 || charCode === 13) {\n lines.push({ startPos: lineStartIdx, width: currentLineWidth });\n lineStartIdx = i + 1;\n currentLineWidth = 0;\n continue;\n }\n\n let charW = fontSize * 0.55; // 기본값 (영문 소문자, 숫자 등)\n\n if (charCode >= 0xac00 && charCode <= 0xd7a3) {\n charW = fontSize; // 한글\n } else if (charCode >= 0x3130 && charCode <= 0x318f) {\n charW = fontSize; // 한글 자모\n } else if (charCode >= 0x4e00 && charCode <= 0x9fff) {\n charW = fontSize; // 한자\n } else if (charCode >= 65 && charCode <= 90) {\n charW = fontSize * 0.65; // 영문 대문자\n } else if (charCode === 32) {\n charW = fontSize * 0.32; // 공백\n } else if (charCode > 255) {\n charW = fontSize; // 기타 전각 문자\n } else {\n charW = fontSize * 0.42; // 기타 특수기호\n }\n\n if (currentLineWidth + charW > horzSize && i > lineStartIdx) {\n lines.push({ startPos: lineStartIdx, width: currentLineWidth });\n lineStartIdx = i;\n currentLineWidth = charW;\n } else {\n currentLineWidth += charW;\n }\n }\n lines.push({ startPos: lineStartIdx, width: currentLineWidth });\n\n const lineCount = lines.length;\n const linesegParts: string[] = [];\n\n for (let i = 0; i < lineCount; i++) {\n const flags = i === 0 ? LINESEG_FLAGS_FIRST : LINESEG_FLAGS_OTHER;\n const textpos = lines[i].startPos;\n linesegParts.push(\n `<hp:lineseg textpos=\"${textpos}\" ` +\n `vertpos=\"${vertPosStart + i * vertsizeLine}\" ` +\n `vertsize=\"${vertsizeLine}\" textheight=\"${fontSize}\" ` +\n `baseline=\"${baseline}\" spacing=\"${spacing}\" ` +\n `horzpos=\"0\" horzsize=\"${horzSize}\" ` +\n `flags=\"${flags}\"/>`,\n );\n }\n\n return {\n xml: `<hp:linesegarray>${linesegParts.join(\"\")}</hp:linesegarray>`,\n totalHeight: lineCount * vertsizeLine,\n };\n}\n\n/** 단락에서 순수 텍스트 추출 (줄바꿈 계산용) */\nfunction extractParaText(para: ParaNode): string {\n let text = \"\";\n const walk = (kids: any[]) => {\n for (const k of kids) {\n if (k.tag === \"span\") {\n for (const c of k.kids) {\n if (c.tag === \"txt\") {\n text += c.content;\n } else if (c.tag === \"br\") {\n text += \"\\n\";\n }\n }\n } else if (k.tag === \"link\") {\n walk(k.kids);\n }\n }\n };\n walk(para.kids);\n return text;\n}\n\nfunction fontSizeForPara(para: ParaNode, ctx: HwpxCtx): number {\n for (const kid of para.kids) {\n if (kid.tag === \"span\") {\n const id = ctx.charPrMap.get(charPrKey(kid.props));\n if (id !== undefined && ctx.charPrs[id]) return ctx.charPrs[id].height;\n }\n }\n return 1000; // 기본 10pt\n}\n\n// ─── 단락 인코딩 ─────────────────────────────────────────────\n\nfunction encodeParaPositioned(\n para: ParaNode,\n ctx: HwpxCtx,\n vertPos: number,\n secPr = \"\",\n availWidth?: number,\n hfRun = \"\",\n): { xml: string; nextVertPos: number; hasPageBreak: boolean } {\n // ✅ 표(Grid)를 포함하는 단락인지 확인\n const gridKid = para.kids.find((k): k is GridNode => k.tag === \"grid\");\n if (gridKid) {\n return encodeTablePara(para, gridKid, ctx, vertPos, secPr, hfRun);\n }\n\n const paraPrId = ctx.paraPrMap.get(paraPrKey(para.props)) ?? 0;\n const styleIDRef = para.props.styleId\n ? (ctx.styleIdToHwpxId.get(para.props.styleId) ?? 0)\n : 0;\n const fontSize = fontSizeForPara(para, ctx);\n const paraPr = ctx.paraPrs[paraPrId];\n const lineSpacing = paraPr?.lineSpacing ?? 160;\n const spacing = Math.max(0, Math.round(fontSize * (lineSpacing / 100 - 1)));\n let vertSize = fontSize + spacing;\n const horzSize = availWidth ?? ctx.availableWidth;\n\n // 코드 블록 감지 (Courier 폰트 또는 styleId \"code\")\n const isCourierFont = (kids: ParaNode[\"kids\"]): boolean =>\n kids.some(\n (k) =>\n (k.tag === \"span\" && k.props.font?.toLowerCase().includes(\"courier\")) ||\n (k.tag === \"link\" &&\n isCourierFont((k as LinkNode).kids as ParaNode[\"kids\"])),\n );\n const isCode =\n availWidth === undefined &&\n (para.props.styleId?.toLowerCase().includes(\"code\") ||\n isCourierFont(para.kids));\n\n if (isCode)\n return encodeCodeBlockPositioned(\n para,\n ctx,\n vertPos,\n secPr,\n fontSize,\n spacing,\n vertSize,\n );\n\n let runsXml = encodeParaKids(para.kids, ctx);\n if (!runsXml) runsXml = `<hp:run charPrIDRef=\"0\" charTcId=\"0\"><hp:t xml:space=\"preserve\"> </hp:t></hp:run>`;\n\n const paraText = extractParaText(para);\n const { xml: linesegXml, totalHeight } = buildLinesegarray(\n paraText,\n vertPos,\n fontSize,\n lineSpacing,\n horzSize,\n );\n\n const hasPageBreak = para.kids.some(\n (k) => k.tag === \"span\" && k.kids.some((c) => c.tag === \"pb\"),\n );\n\n const xml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"${paraPrId}\" styleIDRef=\"${styleIDRef}\" ` +\n `pageBreak=\"${hasPageBreak ? 1 : 0}\" columnBreak=\"0\" merged=\"0\" paraTcId=\"0\">` +\n secPr +\n hfRun +\n runsXml +\n linesegXml +\n `</hp:p>`;\n\n return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak };\n}\n\n/** ✅ 가이드 준수: 표를 포함하는 단락 인코딩 */\nfunction encodeTablePara(\n para: ParaNode,\n grid: GridNode,\n ctx: HwpxCtx,\n vertPos: number,\n secPr: string,\n hfRun: string,\n): { xml: string; nextVertPos: number; hasPageBreak: boolean } {\n const paraPrId = ctx.paraPrMap.get(paraPrKey(para.props)) ?? 0;\n \n // 표 알맹이 생성 (기존 로직 재사용)\n const { xml: gridXml, height: tblHeight } = buildGridXml(grid, ctx);\n \n // 가이드: 표 단락의 lineseg는 1개여야 하고, vertsize는 표 전체 높이여야 함\n const fontSize = 1000; \n const totalHeight = Math.max(1600, tblHeight);\n const baseline = 850;\n const spacing = Math.max(0, totalHeight - fontSize);\n\n const linesegXml =\n `<hp:linesegarray>` +\n `<hp:lineseg textpos=\"0\" vertpos=\"${vertPos}\" vertsize=\"${totalHeight}\" ` +\n `textheight=\"${fontSize}\" baseline=\"${baseline}\" spacing=\"${spacing}\" ` +\n `horzpos=\"0\" horzsize=\"${ctx.availableWidth}\" flags=\"1441792\"/>` +\n `</hp:linesegarray>`;\n\n const hasPageBreak = para.kids.some(\n (k) => k.tag === \"span\" && k.kids.some((c) => c.tag === \"pb\"),\n );\n\n const runId = ctx.nextElementId++;\n const xml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"${paraPrId}\" styleIDRef=\"0\" ` +\n `pageBreak=\"${hasPageBreak ? 1 : 0}\" columnBreak=\"0\" merged=\"0\" paraTcId=\"0\">` +\n secPr +\n `<hp:run id=\"${runId}\" charPrIDRef=\"0\" charTcId=\"0\">` +\n gridXml +\n `</hp:run>` +\n hfRun +\n linesegXml +\n `</hp:p>`;\n\n return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak };\n}\n\nfunction encodeCodeBlockPositioned(\n para: ParaNode,\n ctx: HwpxCtx,\n vertPos: number,\n secPr: string,\n fontSize: number,\n spacing: number,\n vertSize: number,\n): { xml: string; nextVertPos: number; hasPageBreak: boolean } {\n const codeBfId = ctx.borderFillBank.addUniform(\n { kind: \"solid\", pt: 0.5, color: \"aaaaaa\" },\n \"f4f4f4\",\n );\n const cellW = ctx.availableWidth;\n const innerW = Math.max(cellW - 510, 100);\n const subListId = ctx.nextElementId++;\n const { xml: innerXml } = encodeParaPositioned(para, ctx, 0, \"\", innerW);\n\n const paraText = extractParaText(para);\n const { xml: linesegXml, totalHeight } = buildLinesegarray(\n paraText,\n vertPos,\n fontSize,\n 160, // 코드 블록 기본 줄간격 160%\n ctx.availableWidth,\n );\n\n const xml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"0\" styleIDRef=\"0\" paraTcId=\"0\">` +\n secPr +\n `<hp:run charPrIDRef=\"0\" charTcId=\"0\">` +\n `<hp:tbl id=\"${ctx.nextElementId++}\" zOrder=\"0\" numberingType=\"TABLE\" textWrap=\"TOP_AND_BOTTOM\" textFlow=\"BOTH_SIDES\" lock=\"0\" dropcapstyle=\"None\" pageBreak=\"NONE\" rowCnt=\"1\" colCnt=\"1\" cellSpacing=\"0\" borderFillIDRef=\"${codeBfId}\" noAdjust=\"0\">` +\n `<hp:sz width=\"${cellW}\" widthRelTo=\"ABSOLUTE\" height=\"0\" heightRelTo=\"ABSOLUTE\" protect=\"0\"/>` +\n `<hp:pos treatAsChar=\"1\" affectLSpacing=\"0\" flowWithText=\"1\" allowOverlap=\"0\" holdAnchorAndSO=\"0\" vertRelTo=\"PARA\" horzRelTo=\"PARA\" vertAlign=\"TOP\" horzAlign=\"LEFT\" vertOffset=\"0\" horzOffset=\"0\"/>` +\n `<hp:outMargin left=\"138\" right=\"138\" top=\"138\" bottom=\"138\"/>` +\n `<hp:inMargin left=\"138\" right=\"138\" top=\"138\" bottom=\"138\"/>` +\n `<hp:tr><hp:tc name=\"\" header=\"0\" hasMargin=\"1\" protect=\"0\" editable=\"0\" dirty=\"0\" borderFillIDRef=\"${codeBfId}\">` +\n `<hp:subList id=\"${subListId}\" textDirection=\"HORIZONTAL\" lineWrap=\"BREAK\" vertAlign=\"CENTER\" linkListIDRef=\"0\" linkListNextIDRef=\"0\" textWidth=\"0\" textHeight=\"0\" hasTextRef=\"0\" hasNumRef=\"0\">` +\n innerXml +\n `</hp:subList>` +\n `<hp:cellAddr colAddr=\"0\" rowAddr=\"0\"/>` +\n `<hp:cellSpan colSpan=\"1\" rowSpan=\"1\"/>` +\n `<hp:cellSz width=\"${cellW}\" height=\"0\"/>` +\n `<hp:cellMargin left=\"283\" right=\"283\" top=\"141\" bottom=\"141\"/>` +\n `</hp:tc></hp:tr></hp:tbl><hp:t xml:space=\"preserve\"> </hp:t></hp:run>` +\n linesegXml +\n `</hp:p>`;\n\n return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak: false };\n}\n\nfunction encodeParaKids(kids: ParaNode[\"kids\"], ctx: HwpxCtx): string {\n let xml = \"\";\n let currentRunCharPrId: number | null = null;\n let currentRunContent = \"\";\n\n const flushRun = () => {\n if (currentRunCharPrId !== null) {\n // 내용이 없더라도 빈 hp:t를 생성하여 '텍스트 없음' 오류 방지\n const content = currentRunContent || `<hp:t xml:space=\"preserve\"> </hp:t>`;\n xml += `<hp:run charPrIDRef=\"${currentRunCharPrId}\" charTcId=\"0\">${content}</hp:run>`;\n }\n currentRunCharPrId = null;\n currentRunContent = \"\";\n };\n\n for (const kid of kids) {\n if (kid.tag === \"span\") {\n const span = kid as SpanNode;\n const charPrId = ctx.charPrMap.get(charPrKey(span.props)) ?? 0;\n \n if (currentRunCharPrId !== null && currentRunCharPrId !== charPrId) {\n flushRun();\n }\n \n currentRunCharPrId = charPrId;\n currentRunContent += encodeRunInner(span);\n } \n else if (kid.tag === \"link\") {\n const link = kid as LinkNode;\n // 링크의 첫 번째 span 스타일을 기준으로 함\n let charPrId = 0;\n if (link.kids.length > 0 && link.kids[0].tag === \"span\") {\n charPrId = ctx.charPrMap.get(charPrKey((link.kids[0] as SpanNode).props)) ?? 0;\n }\n\n if (currentRunCharPrId !== null && currentRunCharPrId !== charPrId) {\n flushRun();\n }\n\n currentRunCharPrId = charPrId;\n currentRunContent += encodeLinkInner(link, ctx);\n }\n else if (kid.tag === \"img\") {\n flushRun();\n xml += encodeImgWrapped(kid, ctx);\n }\n }\n\n flushRun();\n return xml;\n}\n\n/** hp:run 내부의 태그들만 생성 (span용) */\nfunction encodeRunInner(span: SpanNode): string {\n let xml = \"\";\n for (const kid of span.kids) {\n if (kid.tag === \"txt\") {\n const content = esc(kid.content);\n if (content) xml += `<hp:t xml:space=\"preserve\">${content}</hp:t>`;\n } else if (kid.tag === \"br\") {\n xml += `<hp:br/>`;\n } else if (kid.tag === \"pagenum\") {\n const fmt = (kid as any).format === \"roman\" ? \"ROMAN_LOWER\" \n : (kid as any).format === \"romanCaps\" ? \"ROMAN_UPPER\" : \"DIGIT\";\n xml += `<hp:pageNum pageStartsOn=\"BOTH\" formatType=\"${fmt}\"/>`;\n }\n }\n return xml;\n}\n\n/** hp:run 내부의 태그들만 생성 (link용) */\nfunction encodeLinkInner(link: LinkNode, ctx: HwpxCtx): string {\n const fieldId = 600000000 + (ctx.nextElementId++ % 100000000);\n const instanceId = 2100000000 + (ctx.nextElementId++ % 100000000);\n const url = link.href;\n\n let xml = `<hp:ctrl>` +\n `<hp:fieldBegin id=\"${instanceId}\" type=\"HYPERLINK\" name=\"\" editable=\"0\" dirty=\"1\" zorder=\"-1\" fieldid=\"${fieldId}\">` +\n `<hp:parameters cnt=\"6\" name=\"\">` +\n `<hp:integerParam name=\"Prop\">0</hp:integerParam>` +\n `<hp:stringParam name=\"Command\">${esc(url.replace(/:/g, \"\\\\:\"))};1;5;-1;</hp:stringParam>` +\n `<hp:stringParam name=\"Path\">${esc(url)}</hp:stringParam>` +\n `<hp:stringParam name=\"Category\">HWPHYPERLINK_TYPE_URL</hp:stringParam>` +\n `<hp:stringParam name=\"TargetType\">HWPHYPERLINK_TARGET_HYPERLINK</hp:stringParam>` +\n `<hp:stringParam name=\"DocOpenType\">HWPHYPERLINK_JUMP_DONTCARE</hp:stringParam>` +\n `</hp:parameters>` +\n `</hp:fieldBegin>` +\n `</hp:ctrl>`;\n\n for (const kid of link.kids) {\n if (kid.tag === \"span\") {\n xml += encodeRunInner(kid as SpanNode);\n }\n }\n\n xml += `<hp:ctrl><hp:fieldEnd beginIDRef=\"${instanceId}\"/></hp:ctrl>`;\n return xml;\n}\n\n// ─── 이미지 인코딩 (ANYTOHWP 영감: 픽셀 치수 추출) ──────────\n\nconst WRAP_MAP: Record<string, string> = {\n inline: \"TOP_AND_BOTTOM\",\n square: \"SQUARE\",\n tight: \"BOTH_SIDES\",\n through: \"BOTH_SIDES\",\n none: \"FRONT_TEXT\",\n behind: \"BEHIND_TEXT\",\n front: \"FRONT_TEXT\",\n};\nconst FLOW_MAP: Record<string, string> = {\n inline: \"BOTH_SIDES\",\n square: \"LARGEST_ONLY\",\n tight: \"BOTH_SIDES\",\n through: \"BOTH_SIDES\",\n none: \"BOTH_SIDES\",\n behind: \"BOTH_SIDES\",\n front: \"BOTH_SIDES\",\n};\n\nfunction encodeImage(img: ImgNode, ctx: HwpxCtx): string {\n // 0. 플레이스홀더 처리 (차트 등 b64가 없는 경우)\n if (!img.b64) {\n return `<hp:t xml:space=\"preserve\">${esc(img.alt || \"[개체]\")}</hp:t>`;\n }\n\n const binId = ctx.imgMap.get(img);\n if (!binId) return \"\";\n\n // ANYTOHWP 영감: PNG/JPEG 바이너리 헤더에서 실제 픽셀 치수 추출\n // img.w / img.h는 pt 단위이지만, 이미지 실제 픽셀을 HWPUNIT으로 변환하면 더 정확\n const pixelDims = readPixelDims(img.b64, img.mime);\n let wHwp: number, hHwp: number;\n\n if (pixelDims && pixelDims.w > 0 && pixelDims.h > 0) {\n // 픽셀 → pt (96dpi 기준) → HWPUNIT\n wHwp = Metric.ptToHwp((pixelDims.w * 72) / 96);\n hHwp = Metric.ptToHwp((pixelDims.h * 72) / 96);\n } else {\n wHwp = Metric.ptToHwp(img.w);\n hHwp = Metric.ptToHwp(img.h);\n }\n\n // 가용 너비 초과 방지 (비율 유지)\n if (wHwp > ctx.availableWidth) {\n hHwp = Math.round((hHwp * ctx.availableWidth) / wHwp);\n wHwp = ctx.availableWidth;\n }\n\n // 회전 중심점 (rotation center) 계산: 이미지 중앙을 기준으로 회전\n const rotationCenterX = Math.round(wHwp / 2);\n const rotationCenterY = Math.round(hHwp / 2);\n\n const layout = img.layout;\n const isInline = !layout || layout.wrap === \"inline\";\n const textWrap = layout ? (WRAP_MAP[layout.wrap] ?? \"SQUARE\") : \"SQUARE\";\n const textFlow = layout\n ? (FLOW_MAP[layout.wrap] ?? \"BOTH_SIDES\")\n : \"BOTH_SIDES\";\n const zOrder = ctx.nextZOrder++;\n\n return (\n `<hp:pic id=\"${ctx.nextElementId++}\" zOrder=\"${zOrder}\" numberingType=\"PICTURE\" ` +\n `textWrap=\"${textWrap}\" textFlow=\"${textFlow}\" lock=\"0\" dropcapstyle=\"None\" href=\"\" groupLevel=\"0\" instid=\"0\" reverse=\"0\">` +\n `<hp:offset x=\"0\" y=\"0\"/>` +\n `<hp:orgSz width=\"${wHwp}\" height=\"${hHwp}\"/>` +\n `<hp:curSz width=\"${wHwp}\" height=\"${hHwp}\"/>` +\n `<hp:flip horizontal=\"0\" vertical=\"0\"/>` +\n `<hp:rotationInfo angle=\"0\" centerX=\"${rotationCenterX}\" centerY=\"${rotationCenterY}\" rotateimage=\"1\"/>` +\n `<hp:renderingInfo>` +\n `<hc:transMatrix e1=\"1\" e2=\"0\" e3=\"0\" e4=\"0\" e5=\"1\" e6=\"0\"/>` +\n `<hc:scaMatrix e1=\"1\" e2=\"0\" e3=\"0\" e4=\"0\" e5=\"1\" e6=\"0\"/>` +\n `<hc:rotMatrix e1=\"1\" e2=\"0\" e3=\"0\" e4=\"0\" e5=\"1\" e6=\"0\"/>` +\n `</hp:renderingInfo>` +\n `<hp:imgRect>` +\n `<hc:pt0 x=\"0\" y=\"0\"/><hc:pt1 x=\"${wHwp}\" y=\"0\"/>` +\n `<hc:pt2 x=\"${wHwp}\" y=\"${hHwp}\"/><hc:pt3 x=\"0\" y=\"${hHwp}\"/>` +\n `</hp:imgRect>` +\n `<hp:imgClip left=\"0\" right=\"0\" top=\"0\" bottom=\"0\"/>` +\n `<hp:inMargin left=\"0\" right=\"0\" top=\"0\" bottom=\"0\"/>` +\n `<hp:imgDim dimwidth=\"${wHwp}\" dimheight=\"${hHwp}\"/>` +\n `<hc:img binaryItemIDRef=\"${binId}\" bright=\"0\" contrast=\"0\" effect=\"REAL_PIC\" alpha=\"0\"/>` +\n `<hp:effects/>` +\n `<hp:sz width=\"${wHwp}\" widthRelTo=\"ABSOLUTE\" height=\"${hHwp}\" heightRelTo=\"ABSOLUTE\" protect=\"0\"/>` +\n `<hp:pos treatAsChar=\"${isInline ? 1 : 0}\" affectLSpacing=\"0\" flowWithText=\"1\" ` +\n `allowOverlap=\"0\" holdAnchorAndSO=\"0\" vertRelTo=\"PARA\" horzRelTo=\"PARA\" ` +\n `vertAlign=\"TOP\" horzAlign=\"LEFT\" vertOffset=\"0\" horzOffset=\"0\"/>` +\n `<hp:outMargin left=\"0\" right=\"0\" top=\"0\" bottom=\"0\"/>` +\n `</hp:pic>`\n );\n}\n\nfunction encodeImgWrapped(img: ImgNode, ctx: HwpxCtx): string {\n const content = encodeImage(img, ctx);\n if (!img.b64) {\n return `<hp:run charPrIDRef=\"0\" charTcId=\"0\">${content}</hp:run>`;\n }\n return `<hp:run charPrIDRef=\"0\" charTcId=\"0\">${content}<hp:t xml:space=\"preserve\"> </hp:t></hp:run>`;\n}\n\n// ─── 표(Grid) 인코딩 ─────────────────────────────────────────\n\nfunction encodeGridPositioned(\n grid: GridNode,\n ctx: HwpxCtx,\n vertPos: number,\n secPr = \"\",\n hfRun = \"\",\n): { xml: string; nextVertPos: number; hasPageBreak: boolean } {\n const { xml: gridXml, height: tblHeight } = buildGridXml(grid, ctx);\n const totalHeight = Math.max(1600, tblHeight);\n const fontSize = 1000;\n const baseline = Math.round(fontSize * 0.83);\n const spacing = Math.max(0, totalHeight - fontSize);\n\n const linesegXml =\n `<hp:linesegarray>` +\n `<hp:lineseg textpos=\"0\" vertpos=\"${vertPos}\" vertsize=\"${totalHeight}\" ` +\n `textheight=\"${fontSize}\" baseline=\"${baseline}\" spacing=\"${spacing}\" ` +\n `horzpos=\"0\" horzsize=\"${ctx.availableWidth}\" flags=\"${LINESEG_FLAGS_FIRST}\"/>` +\n `</hp:linesegarray>`;\n\n const runId = ctx.nextElementId++;\n const xml =\n `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"0\" styleIDRef=\"0\" pageBreak=\"0\" columnBreak=\"0\" merged=\"0\" paraTcId=\"0\">` +\n secPr +\n hfRun +\n `<hp:run id=\"${runId}\" charPrIDRef=\"0\" charTcId=\"0\">` +\n gridXml +\n `</hp:run>` +\n linesegXml +\n `</hp:p>`;\n\n return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak: false };\n}\nfunction buildGridXml(\n grid: GridNode,\n ctx: HwpxCtx,\n): { xml: string; height: number } {\n const rowCount = grid.kids.length;\n // ... (기존 tableMap 생성 로직 동일)\n\n // 가상 2D 맵 — 병합 셀 처리\n interface CellEntry {\n type: \"real\" | \"absorbed\";\n cell?: CellNode;\n }\n const tableMap: CellEntry[][] = Array.from({ length: rowCount }, () => []);\n\n for (let ri = 0; ri < rowCount; ri++) {\n let ci = 0;\n for (const cell of grid.kids[ri].kids) {\n while (tableMap[ri][ci]) ci++;\n tableMap[ri][ci] = { type: \"real\", cell };\n for (let rr = 0; rr < cell.rs; rr++) {\n const tri = ri + rr;\n if (tri >= rowCount) break;\n for (let cc = 0; cc < cell.cs; cc++) {\n if (rr === 0 && cc === 0) continue;\n tableMap[tri][ci + cc] = { type: \"absorbed\" };\n }\n }\n ci += cell.cs;\n }\n }\n\n let colCount = 0;\n for (let ri = 0; ri < rowCount; ri++)\n colCount = Math.max(colCount, tableMap[ri].length);\n if (colCount === 0) colCount = 1;\n\n // 컬럼 너비 계산 (Bug 6: 균등 배분 금지, 원본 보존)\n const totalW = ctx.availableWidth;\n const colWidths: number[] = [];\n\n if (grid.props.colWidths && grid.props.colWidths.length === colCount) {\n // pt -> HWPUNIT 변환하여 원본 값 보존\n for (const wPt of grid.props.colWidths) {\n colWidths.push(Metric.ptToHwp(wPt));\n }\n } else {\n // 너비 정보가 없을 때만 균등 배분\n const defW = Math.round(totalW / colCount);\n for (let c = 0; c < colCount; c++) colWidths.push(defW);\n }\n\n // 본문 너비 초과 시에만 비율 축소 보정\n const rawTotal = colWidths.reduce((s, w) => s + w, 0);\n if (rawTotal > totalW && rawTotal > 0) {\n const scale = totalW / rawTotal;\n for (let i = 0; i < colWidths.length; i++) {\n colWidths[i] = Math.max(100, Math.round(colWidths[i] * scale));\n }\n }\n const actualTotal = colWidths.reduce((s, w) => s + w, 0);\n\n // 행 높이 계산\n const rowHeights: number[] = [];\n for (let ri = 0; ri < rowCount; ri++) {\n if (\n grid.kids[ri].heightPt != null &&\n (grid.kids[ri].heightPt as number) > 0\n ) {\n rowHeights.push(Metric.ptToHwp(grid.kids[ri].heightPt as number));\n } else {\n let maxH = 0;\n for (let ci = 0; ci < colCount; ci++) {\n const entry = tableMap[ri][ci];\n if (entry?.type === \"real\") {\n const h = estimateCellHeight(entry.cell!, ctx);\n if (h > maxH) maxH = h;\n }\n }\n rowHeights.push(maxH || Math.round(1000 * 1.6));\n }\n }\n const totalH = rowHeights.reduce((s, h) => s + h, 0);\n\n const defStroke = grid.props.defaultStroke ?? DEFAULT_STROKE;\n // 표 기본 테두리 — BorderFillBank에서 실제 ID 조회\n const tblBfId = ctx.borderFillBank.addUniform(defStroke);\n\n let rowsXml = \"\";\n for (let ri = 0; ri < rowCount; ri++) {\n let cellsXml = \"\";\n for (let ci = 0; ci < colCount; ci++) {\n const entry = tableMap[ri][ci];\n if (!entry || entry.type === \"absorbed\") continue;\n const cell = entry.cell!;\n const cp = cell.props;\n\n // 셀 테두리 — BorderFillBank에서 실제 ID 조회 (하드코딩 제거)\n const cellBfId = ctx.borderFillBank.addFromCellProps(cp, defStroke);\n\n let cellW = 0;\n for (let sc = ci; sc < ci + cell.cs && sc < colWidths.length; sc++)\n cellW += colWidths[sc];\n if (!cellW) cellW = Math.round(totalW / colCount) * cell.cs;\n\n const subListId = ctx.nextElementId++;\n\n // 셀 여백 (기본 141)\n const padL = cp.padL !== undefined ? Metric.ptToHwp(cp.padL) : 141;\n const padR = cp.padR !== undefined ? Metric.ptToHwp(cp.padR) : 141;\n const padT = cp.padT !== undefined ? Metric.ptToHwp(cp.padT) : 141;\n const padB = cp.padB !== undefined ? Metric.ptToHwp(cp.padB) : 141;\n\n const innerW = Math.max(cellW - padL - padR, 100);\n let parasXml = '';\n if (cell.kids.length > 0) {\n for (const kid of cell.kids) {\n if (kid.tag === 'grid') {\n // 중첩 표: <hp:p><hp:run><hp:tbl>...</hp:tbl></hp:run></hp:p> 형식으로 감싸기\n const { xml: tblXml } = buildGridXml(kid, ctx);\n const pid = ctx.nextElementId++;\n const rid = ctx.nextElementId++;\n parasXml += `<hp:p id=\"${pid}\" paraPrIDRef=\"0\" styleIDRef=\"0\" paraTcId=\"0\"><hp:run id=\"${rid}\" charPrIDRef=\"0\" charTcId=\"0\">${tblXml}</hp:run></hp:p>`;\n } else {\n parasXml += encodeParaPositioned(kid, ctx, 0, '', innerW).xml;\n }\n }\n } else {\n parasXml = `<hp:p id=\"${ctx.nextElementId++}\" paraPrIDRef=\"0\" styleIDRef=\"0\" paraTcId=\"0\"><hp:run charPrIDRef=\"0\" charTcId=\"0\"><hp:t xml:space=\"preserve\"> </hp:t></hp:run></hp:p>`;\n }\n\n const vAlign =\n cp.va === \"mid\" ? \"CENTER\" : cp.va === \"bot\" ? \"BOTTOM\" : \"TOP\";\n\n cellsXml +=\n `<hp:tc name=\"\" header=\"0\" hasMargin=\"1\" protect=\"0\" editable=\"0\" dirty=\"0\" borderFillIDRef=\"${cellBfId}\">` +\n `<hp:cellAddr colAddr=\"${ci}\" rowAddr=\"${ri}\"/>` +\n `<hp:cellSpan colSpan=\"${cell.cs}\" rowSpan=\"${cell.rs}\"/>` +\n `<hp:cellSz width=\"${cellW}\" height=\"${rowHeights[ri]}\"/>` +\n `<hp:cellMargin left=\"${padL}\" right=\"${padR}\" top=\"${padT}\" bottom=\"${padB}\"/>` +\n `<hp:subList id=\"${subListId}\" textDirection=\"HORIZONTAL\" lineWrap=\"BREAK\" vertAlign=\"${vAlign}\" ` +\n `linkListIDRef=\"0\" linkListNextIDRef=\"0\" textWidth=\"${innerW}\" textHeight=\"${Math.max(100, rowHeights[ri] - padT - padB)}\" hasTextRef=\"0\" hasNumRef=\"0\">` +\n parasXml +\n `</hp:subList>` +\n `</hp:tc>`;\n }\n rowsXml += `<hp:tr>${cellsXml}</hp:tr>`;\n }\n\n // 표 정렬 처리\n const alignMap: Record<string, string> = {\n left: 'LEFT', right: 'RIGHT', center: 'CENTER', justify: 'JUSTIFY',\n };\n const horzAlign = alignMap[grid.props.align ?? 'left'] ?? 'LEFT';\n\n const headerRow = grid.props.headerRow ? ' repeatHeader=\"1\"' : \"\";\n const xml =\n `<hp:tbl id=\"${ctx.nextElementId++}\" zOrder=\"0\" numberingType=\"TABLE\" textWrap=\"TOP_AND_BOTTOM\" textFlow=\"BOTH_SIDES\" lock=\"0\" dropcapstyle=\"None\" pageBreak=\"NONE\"${headerRow} rowCnt=\"${rowCount}\" colCnt=\"${colCount}\" cellSpacing=\"0\" borderFillIDRef=\"${tblBfId}\" noAdjust=\"0\">` +\n `<hp:sz width=\"${actualTotal}\" widthRelTo=\"ABSOLUTE\" height=\"${totalH}\" heightRelTo=\"ABSOLUTE\" protect=\"0\"/>` +\n `<hp:pos treatAsChar=\"1\" affectLSpacing=\"0\" flowWithText=\"1\" allowOverlap=\"0\" holdAnchorAndSO=\"0\" vertRelTo=\"PARA\" horzRelTo=\"PARA\" vertAlign=\"TOP\" horzAlign=\"${horzAlign}\" vertOffset=\"0\" horzOffset=\"0\"/>` +\n `<hp:outMargin left=\"138\" right=\"138\" top=\"138\" bottom=\"138\"/>` +\n `<hp:inMargin left=\"0\" right=\"0\" top=\"0\" bottom=\"0\"/>` +\n rowsXml +\n `</hp:tbl>`;\n\n return { xml, height: totalH };\n}\n\nfunction estimateCellHeight(cell: CellNode, ctx: HwpxCtx): number {\n const topPad = 141;\n const botPad = 141;\n let h = 0;\n for (const kid of cell.kids) {\n if (kid.tag === 'grid') {\n // 중첩 표 높이는 최소값으로 처리\n h += 1600;\n continue;\n }\n const para = kid;\n const fs = fontSizeForPara(para, ctx);\n const ppId = ctx.paraPrMap.get(paraPrKey(para.props));\n const pp = ppId !== undefined ? ctx.paraPrs[ppId] : null;\n const ls = pp?.lineSpacing ?? 160;\n const before = pp?.prevHwp ?? 0;\n const after = pp?.nextHwp ?? 0;\n h += Math.round((fs * ls) / 100) + before + after;\n }\n if (!h) h = Math.round(1000 * 1.6);\n return h + topPad + botPad;\n}\n\n// ─── 미리보기 텍스트 추출 ────────────────────────────────────\n\nfunction extractPreviewText(sheet?: SheetNode): string {\n if (!sheet) return \"\";\n const lines: string[] = [];\n for (const kid of sheet.kids) {\n if (kid.tag === \"para\") {\n const text = kid.kids\n .flatMap((k) =>\n k.tag === \"span\"\n ? k.kids.flatMap((c) => (c.tag === \"txt\" ? [c.content] : []))\n : [],\n )\n .join(\"\");\n if (text) lines.push(text);\n } else if (kid.tag === \"grid\") {\n for (const row of kid.kids) {\n const cells = row.kids.map((cell) =>\n cell.kids\n .flatMap((p) =>\n p.tag === 'para'\n ? p.kids.flatMap((k) =>\n k.tag === \"span\"\n ? k.kids.flatMap((c) => (c.tag === \"txt\" ? [c.content] : []))\n : [],\n )\n : [],\n )\n .join(\"\"),\n );\n lines.push(cells.join(\"\\t\"));\n }\n }\n }\n return lines.join(\"\\r\\n\");\n}\n\n// ─── XML 이스케이프 ──────────────────────────────────────────\n\nfunction esc(s: string): string {\n if (!s) return \"\";\n s = s.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n s = s.replace(/湰灧/g, \"\").replace(/\\uFEFF/g, \"\");\n // XML 1.0 비허용 제어문자 제거\n // eslint-disable-next-line no-control-regex\n s = s.replace(\n /[^\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]/gu,\n \"\",\n );\n return TextKit.escapeXml(s);\n}\n\nregistry.registerEncoder(new HwpxEncoder());\n","import type {\n DocRoot,\n ParaNode,\n SpanNode,\n GridNode,\n ContentNode,\n ImgNode,\n SheetNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport type { PageDims, GridProps, CellProps } from \"../../model/doc-props\";\nimport { A4, normalizeDims } from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport { Metric } from \"../../safety/StyleBridge\";\nimport { ArchiveKit } from \"../../toolkit/ArchiveKit\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { registry } from \"../../pipeline/registry\";\nimport { BaseEncoder } from \"../../core/BaseEncoder\";\n\ninterface ImageEntry {\n rId: string;\n name: string;\n data: Uint8Array;\n ext: string;\n}\n\nexport class DocxEncoder extends BaseEncoder {\n protected getFormat(): string {\n return \"docx\";\n }\n\n async encode(doc: DocRoot): Promise<Outcome<Uint8Array>> {\n try {\n // 모든 섹션(SheetNode)을 처리 — 첫 번째 섹션에서 헤더/푸터/페이지 설정을 가져오고\n // 이후 섹션들의 콘텐츠는 sectPr로 구분하여 단일 body에 병합한다.\n const sheets = doc.kids.length > 0 ? doc.kids : [];\n const firstSheet = sheets[0];\n const dims = normalizeDims(firstSheet?.dims ?? A4);\n\n // 모든 섹션의 콘텐츠를 합산\n const allKids: ContentNode[] = sheets.flatMap((s) => s?.kids ?? []);\n\n const images: ImageEntry[] = [];\n const ctx: EncCtx = {\n images,\n nextId: 10,\n nextImgNum: 1,\n warns: [],\n imgMap: new WeakMap(),\n };\n\n // Collect images from all content\n collectImages(allKids, ctx);\n\n // Header / footer (첫 번째 섹션 기준)\n let headerParas = firstSheet?.headers?.default;\n let footerParas = firstSheet?.footers?.default;\n const hasHeader = headerParas && headerParas.length > 0;\n const hasFooter = footerParas && footerParas.length > 0;\n\n // Collect images from header/footer\n if (hasHeader) collectImagesFromParas(headerParas!, ctx);\n if (hasFooter) collectImagesFromParas(footerParas!, ctx);\n\n const headerRId = hasHeader ? `rId${ctx.nextId++}` : \"\";\n const footerRId = hasFooter ? `rId${ctx.nextId++}` : \"\";\n\n // Numbering: collect list info from all sections\n const numInfo = collectNumbering(allKids);\n\n // kids 참조를 allKids로 통일 (후속 코드 호환)\n const kids = allKids;\n\n const entries: { name: string; data: Uint8Array }[] = [\n {\n name: \"[Content_Types].xml\",\n data: this.stringToBytes(contentTypes(images, hasHeader, hasFooter)),\n },\n { name: \"_rels/.rels\", data: this.stringToBytes(pkgRels()) },\n {\n name: \"word/document.xml\",\n data: this.stringToBytes(\n documentXml(kids, dims, ctx, headerRId, footerRId),\n ),\n },\n { name: \"word/styles.xml\", data: this.stringToBytes(stylesXml()) },\n { name: \"word/settings.xml\", data: this.stringToBytes(settingsXml()) },\n {\n name: \"word/_rels/document.xml.rels\",\n data: this.stringToBytes(\n docRels(images, headerRId, footerRId, numInfo.hasLists),\n ),\n },\n { name: \"docProps/app.xml\", data: this.stringToBytes(appXml()) },\n {\n name: \"docProps/core.xml\",\n data: this.stringToBytes(coreXml(doc.meta)),\n },\n ];\n\n // Add numbering.xml if needed\n if (numInfo.hasLists) {\n entries.push({\n name: \"word/numbering.xml\",\n data: this.stringToBytes(numberingXml(numInfo)),\n });\n }\n\n // Add header/footer files\n if (hasHeader) {\n entries.push({\n name: \"word/header1.xml\",\n data: this.stringToBytes(headerFooterXml(\"hdr\", headerParas!, ctx)),\n });\n }\n if (hasFooter) {\n entries.push({\n name: \"word/footer1.xml\",\n data: this.stringToBytes(headerFooterXml(\"ftr\", footerParas!, ctx)),\n });\n }\n\n // Add image media files\n for (const img of images) {\n entries.push({ name: `word/media/${img.name}`, data: img.data });\n }\n\n return succeed(await this.zip(entries));\n } catch (e: any) {\n return fail(`DOCX encode error: ${e?.message ?? String(e)}`);\n }\n }\n}\n\n// ─── Context ────────────────────────────────────────────────\n\ninterface EncCtx {\n images: ImageEntry[];\n nextId: number;\n nextImgNum: number;\n warns: string[];\n imgMap: WeakMap<ImgNode, string>; // ImgNode → rId (no mutation)\n}\n\n// ─── Image collection ───────────────────────────────────────\n\nfunction mimeToExt(mime: string): string {\n if (mime.includes(\"jpeg\")) return \"jpeg\";\n if (mime.includes(\"gif\")) return \"gif\";\n if (mime.includes(\"bmp\")) return \"bmp\";\n return \"png\";\n}\n\nfunction collectImages(kids: ContentNode[], ctx: EncCtx): void {\n for (const kid of kids) {\n if (kid.tag === \"para\") collectImagesFromPara(kid, ctx);\n else if (kid.tag === \"grid\") {\n for (const row of kid.kids)\n for (const cell of row.kids)\n for (const p of cell.kids)\n if (p.tag === \"para\") collectImagesFromPara(p, ctx);\n else collectImages([p], ctx);\n }\n }\n}\n\nfunction collectImagesFromParas(paras: ParaNode[], ctx: EncCtx): void {\n for (const p of paras) collectImagesFromPara(p, ctx);\n}\n\nfunction collectImagesFromPara(para: ParaNode, ctx: EncCtx): void {\n for (const kid of para.kids) {\n if (kid.tag === \"img\") registerImage(kid, ctx);\n }\n}\n\nfunction registerImage(img: ImgNode, ctx: EncCtx): void {\n if (ctx.imgMap.has(img)) return;\n const ext = mimeToExt(img.mime);\n const name = `image${ctx.nextImgNum++}.${ext}`;\n const rId = `rId${ctx.nextId++}`;\n const data = TextKit.base64Decode(img.b64);\n ctx.images.push({ rId, name, data, ext });\n ctx.imgMap.set(img, rId);\n}\n\n// ─── List/numbering collection ──────────────────────────────\n\ninterface NumInfo {\n hasLists: boolean;\n hasBullet: boolean;\n hasNumbered: boolean;\n}\n\nfunction collectNumbering(kids: ContentNode[]): NumInfo {\n let hasBullet = false;\n let hasNumbered = false;\n for (const kid of kids) {\n if (kid.tag === \"para\") {\n if (kid.props.listOrd === true) hasNumbered = true;\n else if (kid.props.listOrd === false) hasBullet = true;\n }\n }\n return { hasLists: hasBullet || hasNumbered, hasBullet, hasNumbered };\n}\n\n// ─── OOXML boilerplate ──────────────────────────────────────\n\nfunction contentTypes(\n images: ImageEntry[],\n hasHeader?: boolean,\n hasFooter?: boolean,\n): string {\n const imgDefaults = new Set<string>();\n for (const img of images) imgDefaults.add(img.ext);\n\n let defaults = `<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>\n <Default Extension=\"xml\" ContentType=\"application/xml\"/>`;\n\n for (const ext of imgDefaults) {\n const ct =\n ext === \"png\"\n ? \"image/png\"\n : ext === \"jpeg\"\n ? \"image/jpeg\"\n : ext === \"gif\"\n ? \"image/gif\"\n : \"image/bmp\";\n defaults += `\\n <Default Extension=\"${ext}\" ContentType=\"${ct}\"/>`;\n }\n\n let overrides = `<Override PartName=\"/word/document.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml\"/>\n <Override PartName=\"/word/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml\"/>\n <Override PartName=\"/word/settings.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml\"/>\n <Override PartName=\"/docProps/core.xml\" ContentType=\"application/vnd.openxmlformats-package.core-properties+xml\"/>\n <Override PartName=\"/docProps/app.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.extended-properties+xml\"/>`;\n\n if (hasHeader)\n overrides += `\\n <Override PartName=\"/word/header1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml\"/>`;\n if (hasFooter)\n overrides += `\\n <Override PartName=\"/word/footer1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml\"/>`;\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\n ${defaults}\n ${overrides}\n</Types>`;\n}\n\nfunction pkgRels(): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n <Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"word/document.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties\" Target=\"docProps/core.xml\"/>\n <Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties\" Target=\"docProps/app.xml\"/>\n</Relationships>`;\n}\n\nfunction docRels(\n images: ImageEntry[],\n headerRId?: string,\n footerRId?: string,\n hasLists?: boolean,\n): string {\n let rels = `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/>\n <Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings\" Target=\"settings.xml\"/>`;\n\n // Numbering relationship — only when lists exist\n if (hasLists) {\n rels += `\\n <Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering\" Target=\"numbering.xml\"/>`;\n }\n\n for (const img of images) {\n rels += `\\n <Relationship Id=\"${img.rId}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image\" Target=\"media/${img.name}\"/>`;\n }\n\n if (headerRId) {\n rels += `\\n <Relationship Id=\"${headerRId}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header\" Target=\"header1.xml\"/>`;\n }\n if (footerRId) {\n rels += `\\n <Relationship Id=\"${footerRId}\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer\" Target=\"footer1.xml\"/>`;\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">\n ${rels}\n</Relationships>`;\n}\n\nfunction appXml(): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\">\n <Application>hwpkit</Application>\n</Properties>`;\n}\n\nfunction coreXml(meta: any): string {\n const now = new Date().toISOString();\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n <dc:title>${esc(meta.title ?? \"\")}</dc:title>\n <dc:creator>${esc(meta.author ?? \"\")}</dc:creator>\n <dcterms:created xsi:type=\"dcterms:W3CDTF\">${meta.created ?? now}</dcterms:created>\n <dcterms:modified xsi:type=\"dcterms:W3CDTF\">${now}</dcterms:modified>\n</cp:coreProperties>`;\n}\n\nfunction stylesXml(): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:styles xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">\n <w:docDefaults>\n <w:rPrDefault><w:rPr>\n <w:rFonts w:ascii=\"맑은 고딕\" w:eastAsia=\"맑은 고딕\" w:hAnsi=\"맑은 고딕\"/>\n <w:sz w:val=\"20\"/>\n <w:szCs w:val=\"20\"/>\n </w:rPr></w:rPrDefault>\n <w:pPrDefault><w:pPr>\n <w:spacing w:after=\"0\" w:line=\"240\" w:lineRule=\"auto\"/>\n <w:jc w:val=\"both\"/>\n </w:pPr></w:pPrDefault>\n </w:docDefaults>\n <w:style w:type=\"paragraph\" w:default=\"1\" w:styleId=\"Normal\"><w:name w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"0\"><w:name w:val=\"바탕글\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"1\"><w:name w:val=\"본문\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"2\"><w:name w:val=\"개요 1\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"3\"><w:name w:val=\"개요 2\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"4\"><w:name w:val=\"개요 3\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"5\"><w:name w:val=\"개요 4\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"6\"><w:name w:val=\"개요 5\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"7\"><w:name w:val=\"개요 6\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"8\"><w:name w:val=\"개요 7\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"9\"><w:name w:val=\"개요 8\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"10\"><w:name w:val=\"개요 9\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"11\"><w:name w:val=\"개요 10\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"12\"><w:name w:val=\"쪽 번호\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"13\"><w:name w:val=\"머리말\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"14\"><w:name w:val=\"각주\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"15\"><w:name w:val=\"미주\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"16\"><w:name w:val=\"메모\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"17\"><w:name w:val=\"차례 제목\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"18\"><w:name w:val=\"차례 1\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"19\"><w:name w:val=\"차례 2\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"20\"><w:name w:val=\"차례 3\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"21\"><w:name w:val=\"본문 제목\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"22\"><w:name w:val=\"그림\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"23\"><w:name w:val=\"표\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"24\"><w:name w:val=\"수식\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"25\"><w:name w:val=\"인용문\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"26\"><w:name w:val=\"날짜\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"27\"><w:name w:val=\"발신명의\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"28\"><w:name w:val=\"제목\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"29\"><w:name w:val=\"부제목\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"30\"><w:name w:val=\"문단 제목\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"31\"><w:name w:val=\"MEMO\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"32\"><w:name w:val=\"개요\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"33\"><w:name w:val=\"표 제목\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Heading1\"><w:name w:val=\"heading 1\"/><w:basedOn w:val=\"Normal\"/><w:pPr><w:keepNext/><w:outlineLvl w:val=\"0\"/></w:pPr><w:rPr><w:b/><w:sz w:val=\"44\"/><w:szCs w:val=\"44\"/></w:rPr></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Heading2\"><w:name w:val=\"heading 2\"/><w:basedOn w:val=\"Normal\"/><w:pPr><w:keepNext/><w:outlineLvl w:val=\"1\"/></w:pPr><w:rPr><w:b/><w:sz w:val=\"36\"/><w:szCs w:val=\"36\"/></w:rPr></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Heading3\"><w:name w:val=\"heading 3\"/><w:basedOn w:val=\"Normal\"/><w:pPr><w:keepNext/><w:outlineLvl w:val=\"2\"/></w:pPr><w:rPr><w:b/><w:sz w:val=\"28\"/><w:szCs w:val=\"28\"/></w:rPr></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Header\"><w:name w:val=\"header\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"Footer\"><w:name w:val=\"footer\"/><w:basedOn w:val=\"Normal\"/></w:style>\n <w:style w:type=\"paragraph\" w:styleId=\"ListParagraph\"><w:name w:val=\"List Paragraph\"/><w:basedOn w:val=\"Normal\"/><w:pPr><w:ind w:left=\"720\"/></w:pPr></w:style>\n <w:style w:type=\"table\" w:styleId=\"TableGrid\"><w:name w:val=\"Table Grid\"/><w:tblPr><w:tblBorders><w:top w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:left w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:bottom w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:right w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:insideH w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/><w:insideV w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/></w:tblBorders></w:tblPr></w:style>\n</w:styles>`;\n}\n\nfunction settingsXml(): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:settings xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">\n <w:zoom w:percent=\"100\"/>\n <w:bordersDoNotSurroundHeader/>\n <w:bordersDoNotSurroundFooter/>\n <w:defaultTabStop w:val=\"800\"/>\n <w:compat>\n <w:spaceForUL/>\n <w:balanceSingleByteDoubleByteWidth/>\n <w:doNotLeaveBackslashAlone/>\n <w:ulTrailSpace/>\n <w:doNotExpandShiftReturn/>\n <w:adjustLineHeightInTable/>\n <w:useFELayout/>\n </w:compat>\n</w:settings>`;\n}\n\n// ─── numbering.xml ──────────────────────────────────────────\n\nfunction numberingXml(info: NumInfo): string {\n let abstractNums = \"\";\n let nums = \"\";\n\n // Bullet list: abstractNumId=0, numId=1\n if (info.hasBullet) {\n abstractNums += `<w:abstractNum w:abstractNumId=\"0\">`;\n for (let lvl = 0; lvl < 9; lvl++) {\n const marker = lvl === 0 ? \"●\" : lvl === 1 ? \"○\" : \"■\";\n const indent = (lvl + 1) * 720;\n abstractNums += `<w:lvl w:ilvl=\"${lvl}\"><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"${marker}\"/><w:pPr><w:ind w:left=\"${indent}\" w:hanging=\"360\"/></w:pPr></w:lvl>`;\n }\n abstractNums += `</w:abstractNum>`;\n nums += `<w:num w:numId=\"1\"><w:abstractNumId w:val=\"0\"/></w:num>`;\n }\n\n // Numbered list: abstractNumId=1, numId=2\n if (info.hasNumbered) {\n abstractNums += `<w:abstractNum w:abstractNumId=\"1\">`;\n for (let lvl = 0; lvl < 9; lvl++) {\n const fmt =\n lvl % 3 === 0\n ? \"decimal\"\n : lvl % 3 === 1\n ? \"lowerLetter\"\n : \"lowerRoman\";\n const indent = (lvl + 1) * 720;\n abstractNums += `<w:lvl w:ilvl=\"${lvl}\"><w:start w:val=\"1\"/><w:numFmt w:val=\"${fmt}\"/><w:lvlText w:val=\"%${lvl + 1}.\"/><w:pPr><w:ind w:left=\"${indent}\" w:hanging=\"360\"/></w:pPr></w:lvl>`;\n }\n abstractNums += `</w:abstractNum>`;\n nums += `<w:num w:numId=\"2\"><w:abstractNumId w:val=\"1\"/></w:num>`;\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:numbering xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">\n ${abstractNums}\n ${nums}\n</w:numbering>`;\n}\n\n// ─── header / footer xml ────────────────────────────────────\n\nfunction headerFooterXml(\n type: \"hdr\" | \"ftr\",\n paras: ParaNode[],\n ctx: EncCtx,\n): string {\n const tag = type === \"hdr\" ? \"w:hdr\" : \"w:ftr\";\n const body = paras.map((p) => encodeParaInner(p, ctx)).join(\"\\n\");\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<${tag} xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">\n${body}\n</${tag}>`;\n}\n\n// ─── document.xml ───────────────────────────────────────────\n\nfunction documentXml(\n kids: ContentNode[],\n dims: PageDims,\n ctx: EncCtx,\n headerRId?: string,\n footerRId?: string,\n): string {\n const body = kids.map((k) => encodeContent(k, ctx, dims)).join(\"\\n\");\n\n let sectRefs = \"\";\n if (headerRId)\n sectRefs += `\\n <w:headerReference w:type=\"default\" r:id=\"${headerRId}\"/>`;\n if (footerRId)\n sectRefs += `\\n <w:footerReference w:type=\"default\" r:id=\"${footerRId}\"/>`;\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<w:document xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">\n <w:body>\n${body}\n <w:sectPr>${sectRefs}\n <w:pgSz w:w=\"${Metric.ptToDxa(dims.wPt)}\" w:h=\"${Metric.ptToDxa(dims.hPt)}\" w:orient=\"${dims.orient ?? \"portrait\"}\"/>\n <w:pgMar w:top=\"${Metric.ptToDxa(dims.mt)}\" w:right=\"${Metric.ptToDxa(dims.mr)}\" w:bottom=\"${Metric.ptToDxa(dims.mb)}\" w:left=\"${Metric.ptToDxa(dims.ml)}\" w:header=\"709\" w:footer=\"709\" w:gutter=\"0\"/>\n </w:sectPr>\n </w:body>\n</w:document>`;\n}\n\nfunction encodeContent(\n node: ContentNode,\n ctx: EncCtx,\n dims?: PageDims,\n): string {\n return node.tag === \"grid\"\n ? encodeGrid(node, ctx, dims)\n : encodeParaInner(node, ctx);\n}\n\nfunction encodeParaInner(para: ParaNode, ctx: EncCtx): string {\n const align = para.props.align ?? \"left\";\n // P3: hwpStyleId(숫자 ID) 우선, 없으면 heading 스타일, 둘 다 없으면 빈 문자열\n let headStyle = \"\";\n if (para.props.hwpStyleId !== undefined) {\n headStyle = `<w:pStyle w:val=\"${para.props.hwpStyleId}\"/>`;\n } else if (para.props.heading) {\n headStyle = `<w:pStyle w:val=\"Heading${para.props.heading}\"/>`;\n }\n\n // List numbering\n let numPr = \"\";\n if (para.props.listOrd !== undefined) {\n const numId = para.props.listOrd ? 2 : 1;\n const ilvl = para.props.listLv ?? 0;\n numPr = `<w:pStyle w:val=\"ListParagraph\"/><w:numPr><w:ilvl w:val=\"${ilvl}\"/><w:numId w:val=\"${numId}\"/></w:numPr>`;\n }\n\n // Spacing (before / after / line height) - ensure all values are non-negative\n // ECMA-376 §17.3.1.33 spacing: line은 1/240th of a line(auto) 또는 dxa(exact/atLeast)\n let spacingXml = \"\";\n const { spaceBefore, spaceAfter, lineHeight, lineHeightFixed } = para.props;\n if (\n spaceBefore !== undefined ||\n spaceAfter !== undefined ||\n lineHeight !== undefined ||\n lineHeightFixed !== undefined\n ) {\n const parts: string[] = [];\n if (spaceBefore !== undefined)\n parts.push(`w:before=\"${Math.max(0, Metric.ptToDxa(spaceBefore))}\"`);\n if (spaceAfter !== undefined)\n parts.push(`w:after=\"${Math.max(0, Metric.ptToDxa(spaceAfter))}\"`);\n if (lineHeightFixed !== undefined) {\n // FIXED: lineRule=\"exact\", line값은 dxa (1pt = 20dxa)\n parts.push(\n `w:line=\"${Math.max(1, Metric.ptToDxa(lineHeightFixed))}\" w:lineRule=\"exact\"`,\n );\n } else if (lineHeight !== undefined) {\n parts.push(`w:line=\"${Math.round(lineHeight * 240)}\" w:lineRule=\"auto\"`);\n }\n spacingXml = `<w:spacing ${parts.join(\" \")}/>`;\n }\n\n // Indentation — ECMA-376 §17.3.1.12 ind\n // w:left = 전체 왼쪽 여백(dxa), w:right = 전체 오른쪽 여백(dxa)\n // w:firstLine = 첫 줄 추가 들여쓰기(dxa, 양수), w:hanging = 내어쓰기(dxa, 양수값으로 표현)\n let indentXml = \"\";\n const leftDxa = Math.round(Metric.ptToDxa(para.props.indentPt ?? 0));\n const rightDxa = Math.round(Metric.ptToDxa(para.props.indentRightPt ?? 0));\n const firstPt = para.props.firstLineIndentPt ?? 0;\n\n const indParts: string[] = [];\n if (leftDxa > 0) indParts.push(`w:left=\"${leftDxa}\"`);\n if (rightDxa > 0) indParts.push(`w:right=\"${rightDxa}\"`);\n if (firstPt > 0)\n indParts.push(`w:firstLine=\"${Math.round(Metric.ptToDxa(firstPt))}\"`);\n if (firstPt < 0)\n indParts.push(`w:hanging=\"${Math.round(Metric.ptToDxa(-firstPt))}\"`);\n if (indParts.length > 0) indentXml = `<w:ind ${indParts.join(\" \")}/>`;\n\n const runs = para.kids\n .map((k) => {\n if (k.tag === \"span\") return encodeRun(k, ctx);\n if (k.tag === \"img\") return encodeImage(k, ctx);\n // P9: PageNumNode가 para.kids에 직접 있는 경우 (머리말/꼬리말 등)\n if (k.tag === \"pagenum\") {\n const instr = k.format === \"total\" ? \" NUMPAGES \" : \" PAGE \";\n return `<w:r><w:fldChar w:fldCharType=\"begin\"/></w:r><w:r><w:instrText>${instr}</w:instrText></w:r><w:r><w:fldChar w:fldCharType=\"separate\"/></w:r><w:r><w:t>1</w:t></w:r><w:r><w:fldChar w:fldCharType=\"end\"/></w:r>`;\n }\n return \"\";\n })\n .join(\"\");\n\n return ` <w:p>\n <w:pPr>${headStyle}${numPr}${spacingXml}${indentXml}<w:jc w:val=\"${align === \"justify\" ? \"both\" : align}\"/></w:pPr>\n ${runs}\n </w:p>`;\n}\n\nfunction encodeRun(span: SpanNode, _ctx: EncCtx): string {\n const p = span.props;\n const rPr: string[] = [];\n if (p.b) rPr.push(\"<w:b/>\");\n if (p.i) rPr.push(\"<w:i/>\");\n if (p.u) rPr.push('<w:u w:val=\"single\"/>');\n if (p.s) rPr.push(\"<w:strike/>\");\n if (p.sup) rPr.push('<w:vertAlign w:val=\"superscript\"/>');\n if (p.sub) rPr.push('<w:vertAlign w:val=\"subscript\"/>');\n if (p.pt)\n rPr.push(\n `<w:sz w:val=\"${Metric.ptToHalfPt(p.pt)}\"/><w:szCs w:val=\"${Metric.ptToHalfPt(p.pt)}\"/>`,\n );\n if (p.color) rPr.push(`<w:color w:val=\"${p.color}\"/>`);\n if (p.font)\n rPr.push(\n `<w:rFonts w:ascii=\"${esc(p.font)}\" w:hAnsi=\"${esc(p.font)}\" w:eastAsia=\"${esc(p.font)}\"/>`,\n );\n if (p.bg) rPr.push(`<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${p.bg}\"/>`);\n\n // Process kids — text and pagenum\n const parts: string[] = [];\n for (const kid of span.kids) {\n if (kid.tag === \"txt\") {\n // __EXT_N__ or __EXT_N_W<w>_H<h>__ 자리표시자 제거\n const content = kid.content.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n if (content) {\n parts.push(\n `<w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:t xml:space=\"preserve\">${esc(content)}</w:t></w:r>`,\n );\n }\n } else if (kid.tag === \"pagenum\") {\n // P9: format === 'total' → NUMPAGES 필드, 나머지 → PAGE 필드\n const instr = kid.format === \"total\" ? \" NUMPAGES \" : \" PAGE \";\n parts.push(\n `<w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:fldChar w:fldCharType=\"begin\"/></w:r><w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:instrText>${instr}</w:instrText></w:r><w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:fldChar w:fldCharType=\"separate\"/></w:r><w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:t>1</w:t></w:r><w:r><w:rPr>${rPr.join(\"\")}</w:rPr><w:fldChar w:fldCharType=\"end\"/></w:r>`,\n );\n } else if (kid.tag === \"br\") {\n parts.push(`<w:r><w:br/></w:r>`);\n } else if (kid.tag === \"pb\") {\n parts.push(`<w:r><w:br w:type=\"page\"/></w:r>`);\n }\n }\n\n return parts.join(\"\");\n}\n\nfunction encodeImage(img: ImgNode, ctx: EncCtx): string {\n const rId = ctx.imgMap.get(img);\n if (!rId) return \"\";\n\n // Fallback to 72pt (1 inch) when w/h are 0 to prevent invisible images\n const cx = Metric.ptToEmu(img.w > 0 ? img.w : 72);\n const cy = Metric.ptToEmu(img.h > 0 ? img.h : 72);\n const alt = esc(img.alt ?? \"\");\n const docPrId = ctx.nextId++;\n\n const graphic = `<a:graphic><a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\"><pic:pic><pic:nvPicPr><pic:cNvPr id=\"0\" name=\"Image\"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip r:embed=\"${rId}\"/><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x=\"0\" y=\"0\"/><a:ext cx=\"${cx}\" cy=\"${cy}\"/></a:xfrm><a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic>`;\n\n const layout = img.layout;\n\n const isInline = !layout || layout.wrap === \"inline\";\n // topAndBottom은 반드시 anchor (float)로 처리\n const forceAnchor =\n layout?.wrap === \"topAndBottom\" ||\n layout?.wrap === \"square\" ||\n layout?.wrap === \"tight\" ||\n layout?.wrap === \"behind\" ||\n layout?.wrap === \"front\";\n if (isInline && !forceAnchor) {\n return `<w:r><w:drawing><wp:inline distT=\"0\" distB=\"0\" distL=\"0\" distR=\"0\"><wp:extent cx=\"${cx}\" cy=\"${cy}\"/><wp:docPr id=\"${docPrId}\" name=\"Image\" descr=\"${alt}\"/>${graphic}</wp:inline></w:drawing></w:r>`;\n }\n return `<w:r><w:drawing>${encodeAnchor(img, cx, cy, alt, docPrId, graphic, layout!)}</w:drawing></w:r>`;\n}\n\nfunction encodeAnchor(\n _img: ImgNode,\n cx: number,\n cy: number,\n alt: string,\n docPrId: number,\n graphic: string,\n layout: NonNullable<ImgNode[\"layout\"]>,\n): string {\n const distT = Metric.ptToEmu(layout.distT ?? 0);\n const distB = Metric.ptToEmu(layout.distB ?? 0);\n const distL = Metric.ptToEmu(layout.distL ?? 9144); // DOCX 기본 0.18pt\n const distR = Metric.ptToEmu(layout.distR ?? 9144);\n const behindDoc = layout.behindDoc || layout.wrap === \"behind\" ? \"1\" : \"0\";\n const relH = layout.zOrder ?? 251658240;\n\n // 가로 위치\n const horzRelFrom = HORZ_RELTO_DOCX[layout.horzRelTo ?? \"column\"] ?? \"column\";\n let posH: string;\n if (layout.xPt != null) {\n posH = `<wp:positionH relativeFrom=\"${horzRelFrom}\"><wp:posOffset>${Metric.ptToEmu(layout.xPt)}</wp:posOffset></wp:positionH>`;\n } else {\n const ha = HORZ_ALIGN_DOCX[layout.horzAlign ?? \"left\"] ?? \"left\";\n posH = `<wp:positionH relativeFrom=\"${horzRelFrom}\"><wp:align>${ha}</wp:align></wp:positionH>`;\n }\n\n // 세로 위치\n const vertRelFrom =\n VERT_RELTO_DOCX[layout.vertRelTo ?? \"para\"] ?? \"paragraph\";\n let posV: string;\n if (layout.yPt != null) {\n posV = `<wp:positionV relativeFrom=\"${vertRelFrom}\"><wp:posOffset>${Metric.ptToEmu(layout.yPt)}</wp:posOffset></wp:positionV>`;\n } else {\n const va = VERT_ALIGN_DOCX[layout.vertAlign ?? \"top\"] ?? \"top\";\n posV = `<wp:positionV relativeFrom=\"${vertRelFrom}\"><wp:align>${va}</wp:align></wp:positionV>`;\n }\n\n // 텍스트 감싸기\n const wrapXml =\n WRAP_DOCX[layout.wrap] ?? '<wp:wrapSquare wrapText=\"bothSides\"/>';\n\n return `<wp:anchor distT=\"${distT}\" distB=\"${distB}\" distL=\"${distL}\" distR=\"${distR}\" simplePos=\"0\" relativeHeight=\"${relH}\" behindDoc=\"${behindDoc}\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\"><wp:simplePos x=\"0\" y=\"0\"/>${posH}${posV}<wp:extent cx=\"${cx}\" cy=\"${cy}\"/><wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>${wrapXml}<wp:docPr id=\"${docPrId}\" name=\"Image\" descr=\"${alt}\"/>${graphic}</wp:anchor>`;\n}\n\nconst HORZ_RELTO_DOCX: Record<string, string> = {\n margin: \"margin\",\n column: \"column\",\n page: \"page\",\n para: \"paragraph\",\n};\nconst VERT_RELTO_DOCX: Record<string, string> = {\n margin: \"margin\",\n line: \"line\",\n page: \"page\",\n para: \"paragraph\",\n};\nconst HORZ_ALIGN_DOCX: Record<string, string> = {\n left: \"left\",\n center: \"center\",\n right: \"right\",\n};\nconst VERT_ALIGN_DOCX: Record<string, string> = {\n top: \"top\",\n center: \"center\",\n bottom: \"bottom\",\n};\n// ECMA-376 §20.4.2 wordprocessingDrawing wrapping elements\nconst WRAP_DOCX: Record<string, string> = {\n square: '<wp:wrapSquare wrapText=\"bothSides\"/>',\n tight:\n '<wp:wrapTight><wp:wrapPolygon edited=\"0\"><wp:start x=\"0\" y=\"0\"/><wp:lineTo x=\"0\" y=\"21600\"/><wp:lineTo x=\"21600\" y=\"21600\"/><wp:lineTo x=\"21600\" y=\"0\"/><wp:lineTo x=\"0\" y=\"0\"/></wp:wrapPolygon></wp:wrapTight>',\n through:\n '<wp:wrapThrough wrapText=\"bothSides\"><wp:wrapPolygon edited=\"0\"><wp:start x=\"0\" y=\"0\"/><wp:lineTo x=\"0\" y=\"21600\"/><wp:lineTo x=\"21600\" y=\"21600\"/><wp:lineTo x=\"21600\" y=\"0\"/><wp:lineTo x=\"0\" y=\"0\"/></wp:wrapPolygon></wp:wrapThrough>',\n // ECMA-376 §20.4.2.15: wrapTopAndBottom — 텍스트가 이미지 위아래로만 흐름\n topAndBottom: \"<wp:wrapTopAndBottom/>\",\n none: \"<wp:wrapNone/>\",\n behind: \"<wp:wrapNone/>\",\n front: \"<wp:wrapNone/>\",\n};\n\nfunction encodeGrid(grid: GridNode, ctx: EncCtx, dims: PageDims = A4): string {\n const gp = grid.props;\n const look = gp.look;\n\n // tblLook attributes\n const firstRow = look?.firstRow ? \"1\" : \"0\";\n const lastRow = look?.lastRow ? \"1\" : \"0\";\n const firstCol = look?.firstCol ? \"1\" : \"0\";\n const lastCol = look?.lastCol ? \"1\" : \"0\";\n const noHBand = look?.bandedRows ? \"0\" : \"1\";\n const noVBand = look?.bandedCols ? \"0\" : \"1\";\n\n const d = dims ?? A4;\n const availDxa = Metric.ptToDxa(d.wPt - d.ml - d.mr);\n\n // 1단계: 표의 가상 2D 맵핑 (Virtual Table Map) 생성\n // 'real': 데이터 셀, 'continue': 세로 병합 지속 셀, 'absorbed': 가로/세로 병합으로 흡수된 자리, 'void': 빈 공간\n interface CellMap {\n type: \"real\" | \"continue\" | \"absorbed\" | \"void\";\n cell?: any;\n width?: number;\n }\n const tableMap: CellMap[][] = Array.from(\n { length: grid.kids.length },\n () => [],\n );\n\n for (let ri = 0; ri < grid.kids.length; ri++) {\n let c = 0;\n for (const cell of grid.kids[ri].kids) {\n // 이미 이전 행의 rowspan이나 현재 행의 colspan으로 차지된 자리 건너뜀\n while (tableMap[ri][c]) c++;\n\n // 실제 데이터 셀 배치\n tableMap[ri][c] = { type: \"real\", cell, width: cell.cs };\n\n // 병합 영역(colspan, rowspan) 예약 처리\n for (let rr = 0; rr < cell.rs; rr++) {\n const targetRi = ri + rr;\n if (targetRi >= grid.kids.length) break;\n if (!tableMap[targetRi]) tableMap[targetRi] = [];\n\n for (let cc = 0; cc < cell.cs; cc++) {\n if (rr === 0 && cc === 0) continue; // 시작 셀은 이미 'real'로 처리됨\n\n if (rr > 0 && cc === 0) {\n // 세로 병합이 시작된 이후 행의 첫 번째 칸\n tableMap[targetRi][c + cc] = { type: \"continue\", width: cell.cs };\n } else {\n // 가로 병합으로 흡수된 칸 또는 세로 병합 중 가로 병합된 칸\n tableMap[targetRi][c + cc] = { type: \"absorbed\" };\n }\n }\n }\n c += cell.cs;\n }\n }\n\n // 정확한 전체 열 개수(colCount) 계산 (모든 행 중 최대 길이)\n let colCount = 0;\n for (let ri = 0; ri < grid.kids.length; ri++) {\n colCount = Math.max(colCount, tableMap[ri].length);\n }\n if (colCount === 0) colCount = 1;\n\n // 빈 공간(void) 채우기 및 colCount에 맞춰 배열 길이 정규화\n for (let ri = 0; ri < grid.kids.length; ri++) {\n for (let c = 0; c < colCount; c++) {\n if (!tableMap[ri][c]) tableMap[ri][c] = { type: \"void\" };\n }\n }\n\n // 2단계: 컬럼 너비(dxa) 계산\n const defaultColDxa = Math.round(availDxa / colCount);\n let colWidthsDxa: number[] = [];\n\n if (grid.props.colWidths && grid.props.colWidths.length > 0) {\n const srcPt = [...grid.props.colWidths];\n while (srcPt.length < colCount) srcPt.push(0);\n srcPt.length = colCount;\n\n const knownTotalPt = srcPt.filter((w) => w > 0).reduce((s, w) => s + w, 0);\n const zeroCount = srcPt.filter((w) => w <= 0).length;\n const availPt = Metric.dxaToPt(availDxa);\n\n const remainingPt = Math.max(0, availPt - knownTotalPt);\n const zeroFillPt = zeroCount > 0 ? remainingPt / zeroCount : 0;\n\n for (let i = 0; i < srcPt.length; i++) {\n if (srcPt[i] <= 0) {\n srcPt[i] = zeroFillPt > 0 ? zeroFillPt : availPt / colCount;\n }\n }\n\n colWidthsDxa = srcPt.map((w) => Math.round(Metric.ptToDxa(w)));\n const computedTotalDxa = colWidthsDxa.reduce((s, w) => s + w, 0);\n if (computedTotalDxa > availDxa) {\n const scale = availDxa / computedTotalDxa;\n colWidthsDxa = colWidthsDxa.map((w) => Math.round(w * scale));\n }\n } else {\n for (let c = 0; c < colCount; c++) colWidthsDxa.push(defaultColDxa);\n }\n\n const totalDxa = colWidthsDxa.reduce((s, w) => s + w, 0);\n const gridCols = colWidthsDxa.map((w) => `<w:gridCol w:w=\"${w}\"/>`).join(\"\");\n\n // 3단계: XML 렌더링\n const rows = tableMap\n .map((rowMap, ri) => {\n const cellXmls: string[] = [];\n\n for (let c = 0; c < colCount; c++) {\n const mapEntry = rowMap[c];\n\n // 가로 병합으로 흡수된 칸은 렌더링하지 않음 (앞선 칸의 gridSpan이 차지)\n if (mapEntry.type === \"absorbed\") continue;\n\n // 세로 병합 지속(continue), 실제 셀(real), 또는 빈 공간(void) 처리\n const isContinue = mapEntry.type === \"continue\";\n const isReal = mapEntry.type === \"real\";\n const isVoid = mapEntry.type === \"void\";\n\n if (isContinue || isReal || isVoid) {\n let cw = 0;\n const cellWidth = mapEntry.width || 1;\n\n // 너비 계산: 현재 칸부터 colspan(width) 만큼의 컬럼 너비 합산\n // colWidthsDxa 가 colCount 보다 작은 경우를 대비하여 safe 하게 처리\n const safeColWidths =\n colWidthsDxa.length >= colCount\n ? colWidthsDxa\n : [\n ...colWidthsDxa,\n ...Array(colCount - colWidthsDxa.length).fill(defaultColDxa),\n ];\n for (\n let sc = c;\n sc < c + cellWidth && sc < safeColWidths.length;\n sc++\n ) {\n cw += safeColWidths[sc];\n }\n if (cw <= 0) cw = defaultColDxa * cellWidth;\n\n const tcPrParts: string[] = [];\n tcPrParts.push(`<w:tcW w:w=\"${Math.round(cw)}\" w:type=\"dxa\"/>`);\n\n if (cellWidth > 1) {\n tcPrParts.push(`<w:gridSpan w:val=\"${cellWidth}\"/>`);\n }\n\n if (isContinue) {\n tcPrParts.push(`<w:vMerge/>`);\n }\n\n let cellContent = \"\";\n if (isReal) {\n const cell = mapEntry.cell!;\n const cp = cell.props;\n if (cell.rs > 1) tcPrParts.push(`<w:vMerge w:val=\"restart\"/>`);\n\n const borders = encodeCellBorders(cp);\n if (borders) tcPrParts.push(borders);\n if (cp.bg)\n tcPrParts.push(\n `<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${cp.bg}\"/>`,\n );\n if (cp.va) {\n const vaMap: Record<string, string> = {\n top: \"top\",\n mid: \"center\",\n bot: \"bottom\",\n };\n tcPrParts.push(`<w:vAlign w:val=\"${vaMap[cp.va] ?? \"top\"}\"/>`);\n }\n // Per-cell margin override (only when explicitly set)\n const cPadT =\n cp.padT != null ? Math.round(Metric.ptToDxa(cp.padT)) : null;\n const cPadB =\n cp.padB != null ? Math.round(Metric.ptToDxa(cp.padB)) : null;\n const cPadL =\n cp.padL != null ? Math.round(Metric.ptToDxa(cp.padL)) : null;\n const cPadR =\n cp.padR != null ? Math.round(Metric.ptToDxa(cp.padR)) : null;\n if (\n cPadT != null ||\n cPadB != null ||\n cPadL != null ||\n cPadR != null\n ) {\n const t = cPadT ?? 28;\n const b = cPadB ?? 28;\n const l = cPadL ?? 72;\n const r = cPadR ?? 72;\n tcPrParts.push(\n `<w:tcMar><w:top w:w=\"${t}\" w:type=\"dxa\"/><w:left w:w=\"${l}\" w:type=\"dxa\"/><w:bottom w:w=\"${b}\" w:type=\"dxa\"/><w:right w:w=\"${r}\" w:type=\"dxa\"/></w:tcMar>`,\n );\n }\n // Encode cell content: paragraphs and nested grids (중첩 표)\n // DOCX cells must end with <w:p>; nested <w:tbl> goes between paras\n const parts: string[] = [];\n for (const kid of cell.kids) {\n if (kid.tag === \"grid\") {\n parts.push(encodeGrid(kid, ctx)); // dims 제거 — 중첩 표는 부모 dims 불필요\n } else if (kid.tag === \"para\") {\n parts.push(encodeParaInner(kid, ctx));\n }\n }\n // DOCX 셀은 반드시 <w:p>로 끝나야 함\n const lastKid = cell.kids[cell.kids.length - 1];\n if (cell.kids.length === 0 || lastKid?.tag === \"grid\") {\n parts.push('<w:p><w:pPr><w:spacing w:after=\"0\"/></w:pPr></w:p>');\n }\n cellContent = parts.join(\"\");\n } else {\n // continue 거나 void 인 경우 빈 단락 추가\n cellContent = `<w:p><w:pPr/></w:p>`;\n }\n\n const tcPr = `<w:tcPr>${tcPrParts.join(\"\")}</w:tcPr>`;\n cellXmls.push(` <w:tc>${tcPr}${cellContent}</w:tc>`);\n }\n }\n\n const trPrParts: string[] = [];\n if (ri === 0 && (gp.headerRow || look?.firstRow)) {\n trPrParts.push(\"<w:tblHeader/>\");\n }\n // 원본 행 정보에서 높이 가져오기 (tableMap 과 grid.kids 는 같은 인덱스)\n const originalRow = grid.kids[ri];\n if (originalRow?.heightPt != null && originalRow.heightPt > 0) {\n const hDxa = Math.round(Metric.ptToDxa(originalRow.heightPt));\n trPrParts.push(`<w:trHeight w:val=\"${hDxa}\" w:hRule=\"atLeast\"/>`);\n }\n const trPr =\n trPrParts.length > 0 ? `<w:trPr>${trPrParts.join(\"\")}</w:trPr>` : \"\";\n\n return ` <w:tr>${trPr}\\n${cellXmls.join(\"\\n\")}\\n </w:tr>`;\n })\n .join(\"\\n\");\n\n // 4단계: 테두리 및 최종 테이블 XML 조립\n let tblBorders = \"\";\n const strokeKindMap: Record<string, string> = {\n solid: \"single\",\n dash: \"dash\",\n dot: \"dot\",\n double: \"double\",\n none: \"none\",\n dotDash: \"dotDash\",\n dotDotDash: \"dotDotDash\",\n triple: \"triple\",\n thinThickSmallGap: \"thinThickSmallGap\",\n thickThinSmallGap: \"thickThinSmallGap\",\n thinThickThinSmallGap: \"thinThickThinSmallGap\",\n };\n\n if (gp.defaultStroke) {\n const s = gp.defaultStroke;\n const val = strokeKindMap[s.kind] ?? \"single\";\n\n if (val === \"none\" || s.pt <= 0) {\n tblBorders =\n '<w:tblBorders><w:top w:val=\"none\"/><w:left w:val=\"none\"/><w:bottom w:val=\"none\"/><w:right w:val=\"none\"/><w:insideH w:val=\"none\"/><w:insideV w:val=\"none\"/></w:tblBorders>';\n } else {\n // DOCX sz는 1/8pt 단위. 최소 굵기 2(0.25pt) 보장\n const sz = Math.max(2, Math.round(s.pt * 8));\n // 색상 '#' 제거 및 빈 값일 경우 auto 처리\n const clr = s.color ? s.color.replace(\"#\", \"\") : \"auto\";\n const bdr = `w:val=\"${val}\" w:sz=\"${sz}\" w:space=\"0\" w:color=\"${clr}\"`;\n tblBorders = `<w:tblBorders><w:top ${bdr}/><w:left ${bdr}/><w:bottom ${bdr}/><w:right ${bdr}/><w:insideH ${bdr}/><w:insideV ${bdr}/></w:tblBorders>`;\n }\n }\n\n // ECMA-376 §17.4.58: tblJc — 표 가로 정렬 (start/center/end)\n const tblAlignMap: Record<string, string> = {\n left: \"start\",\n center: \"center\",\n right: \"end\",\n justify: \"start\",\n };\n const tblJc = gp.align\n ? `<w:jc w:val=\"${tblAlignMap[gp.align] ?? \"start\"}\"/>`\n : \"\";\n\n return ` <w:tbl>\n <w:tblPr><w:tblStyle w:val=\"TableGrid\"/><w:tblW w:w=\"${Math.round(totalDxa)}\" w:type=\"dxa\"/><w:tblLayout w:type=\"fixed\"/><w:tblLook w:val=\"04A0\" w:firstRow=\"${firstRow}\" w:lastRow=\"${lastRow}\" w:firstColumn=\"${firstCol}\" w:lastColumn=\"${lastCol}\" w:noHBand=\"${noHBand}\" w:noVBand=\"${noVBand}\"/>${tblBorders}${tblJc}<w:tblCellMar><w:top w:w=\"28\" w:type=\"dxa\"/><w:left w:w=\"72\" w:type=\"dxa\"/><w:bottom w:w=\"28\" w:type=\"dxa\"/><w:right w:w=\"72\" w:type=\"dxa\"/></w:tblCellMar></w:tblPr>\n <w:tblGrid>${gridCols}</w:tblGrid>\n${rows}\n </w:tbl>`;\n}\nfunction encodeCellBorders(cp: CellProps): string {\n if (!cp.top && !cp.bot && !cp.left && !cp.right) return \"\";\n const strokeKindMap: Record<string, string> = {\n solid: \"single\",\n dash: \"dash\",\n dot: \"dot\",\n double: \"double\",\n none: \"none\",\n dotDash: \"dotDash\",\n dotDotDash: \"dotDotDash\",\n triple: \"triple\",\n };\n\n const encode = (\n s?: { kind: string; pt: number; color: string },\n tag?: string,\n ) => {\n if (!s || !tag) return \"\";\n const val = strokeKindMap[s.kind] ?? \"single\";\n\n // 선이 없거나 굵기가 0 이하인 경우 확실하게 제거 처리\n if (val === \"none\" || s.pt <= 0) {\n return `<w:${tag} w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>`;\n }\n\n // 최소 굵기 sz=2 (0.25pt) 보장\n const sz = Math.max(2, Math.round(s.pt * 8));\n // 색상 '#' 제거 및 빈 값일 경우 auto 처리\n const clr = s.color ? s.color.replace(\"#\", \"\") : \"auto\";\n\n return `<w:${tag} w:val=\"${val}\" w:sz=\"${sz}\" w:space=\"0\" w:color=\"${clr}\"/>`;\n };\n\n return `<w:tcBorders>${encode(cp.top, \"top\")}${encode(cp.bot, \"bottom\")}${encode(cp.left, \"left\")}${encode(cp.right, \"right\")}</w:tcBorders>`;\n}\n\nfunction esc(s: string): string {\n if (!s) return \"\";\n // 1. 내부 처리용 플레이스홀더(__EXT_0__ 또는 __EXT_0_W144_H108__ 등) 제거\n s = s.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, \"\");\n\n // 2. 글자 깨짐을 유발하는 쓰레기값 및 BOM 기호 명시적 제거 (이 부분 추가!)\n s = s.replace(/湰灧/g, \"\");\n s = s.replace(/\\uFEFF/g, \"\");\n\n // 3. DOCX(XML 1.0)에서 허용하지 않는 보이지 않는 제어문자 모두 제거\n s = s.replace(/[^\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD]/g, \"\");\n\n return TextKit.escapeXml(s);\n}\n\nregistry.registerEncoder(new DocxEncoder());\n","import type { DocRoot, ParaNode, SpanNode, GridNode, ContentNode, ImgNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport type { Stroke } from '../../model/doc-props';\nimport type { EncoderOptions } from '../../contract/encoder';\nimport { succeed, fail } from '../../contract/result';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { registry } from '../../pipeline/registry';\nimport { BaseEncoder } from '../../core/BaseEncoder';\n\nexport class MdEncoder extends BaseEncoder {\n protected getFormat(): string { return 'md'; }\n\n async encode(doc: DocRoot, options?: EncoderOptions): Promise<Outcome<Uint8Array>> {\n const includeImages = options?.includeImages !== false; // default: true\n try {\n const warns: string[] = [];\n const parts: string[] = [];\n for (const sheet of doc.kids) {\n // Warn about header/footer loss\n if (sheet.headers && sheet.headers.default && sheet.headers.default.length > 0) warns.push('[SHIELD] MD: 머리글(header) 표현 불가 — 손실됨');\n if (sheet.footers && sheet.footers.default && sheet.footers.default.length > 0) warns.push('[SHIELD] MD: 바닥글(footer) 표현 불가 — 손실됨');\n\n for (const kid of sheet.kids) parts.push(encodeContent(kid, warns, includeImages));\n }\n return succeed(this.stringToBytes(parts.join('\\n\\n')), warns);\n } catch (e: any) {\n return fail(`MD encode error: ${e?.message ?? String(e)}`);\n }\n }\n}\n\nfunction encodeContent(node: ContentNode, warns: string[], includeImages: boolean): string {\n return node.tag === 'grid' ? encodeGrid(node, warns, includeImages) : encodePara(node, warns, includeImages);\n}\n\nfunction encodePara(para: ParaNode, warns: string[], includeImages: boolean): string {\n const text = para.kids.map(k => {\n if (k.tag === 'span') return encodeSpan(k, warns);\n if (k.tag === 'img') return encodeImage(k, includeImages);\n return '';\n }).join('');\n\n if (para.props.heading) return `${'#'.repeat(para.props.heading)} ${text}`;\n\n if (para.props.listOrd !== undefined) {\n const indent = ' '.repeat(para.props.listLv ?? 0);\n return `${indent}${para.props.listOrd ? '1.' : '-'} ${text}`;\n }\n\n // Alignment: use HTML fallback for non-left\n if (para.props.align && para.props.align !== 'left' && para.props.align !== 'justify') {\n return `<div align=\"${para.props.align}\">${text}</div>`;\n }\n\n return text;\n}\n\nfunction encodeSpan(span: SpanNode, warns: string[]): string {\n let hasPageNum = false;\n const textParts: string[] = [];\n for (const kid of span.kids) {\n if (kid.tag === 'txt') textParts.push(kid.content);\n else if (kid.tag === 'pagenum') {\n hasPageNum = true;\n warns.push('[SHIELD] MD: 페이지 번호 표현 불가 — 손실됨');\n }\n }\n\n let r = textParts.join('');\n if (hasPageNum && r === '') r = '[페이지 번호]';\n\n // Collect CSS styles for font/color/size/bg — use HTML span so fonts can be\n // loaded externally via the page's stylesheet or @font-face rules.\n const cssStyles: string[] = [];\n if (span.props.font) cssStyles.push(`font-family: ${span.props.font}`);\n if (span.props.pt) cssStyles.push(`font-size: ${span.props.pt}pt`);\n if (span.props.color) cssStyles.push(`color: #${span.props.color}`);\n if (span.props.bg) cssStyles.push(`background-color: #${span.props.bg}`);\n\n const hasHtmlStyle = cssStyles.length > 0;\n\n if (hasHtmlStyle) {\n // When style properties are present, use HTML for all formatting so that\n // markdown markers inside an HTML element don't break parsers.\n if (span.props.b) cssStyles.push('font-weight: bold');\n if (span.props.i) cssStyles.push('font-style: italic');\n if (span.props.s) cssStyles.push('text-decoration: line-through');\n if (span.props.u) {\n // combine underline with possible line-through\n const existing = cssStyles.find(s => s.startsWith('text-decoration:'));\n if (existing) {\n const idx = cssStyles.indexOf(existing);\n cssStyles[idx] = existing.replace('line-through', 'underline line-through');\n if (!existing.includes('line-through')) cssStyles[idx] = existing + ' underline';\n } else {\n cssStyles.push('text-decoration: underline');\n }\n }\n const styleAttr = cssStyles.join('; ');\n if (span.props.sup) return `<sup style=\"${styleAttr}\">${r}</sup>`;\n if (span.props.sub) return `<sub style=\"${styleAttr}\">${r}</sub>`;\n return `<span style=\"${styleAttr}\">${r}</span>`;\n }\n\n // No CSS styles needed — use plain Markdown formatting\n if (span.props.b && span.props.i) r = `***${r}***`;\n else if (span.props.b) r = `**${r}**`;\n else if (span.props.i) r = `*${r}*`;\n if (span.props.s) r = `~~${r}~~`;\n if (span.props.u) r = `<u>${r}</u>`;\n if (span.props.sup) r = `<sup>${r}</sup>`;\n if (span.props.sub) r = `<sub>${r}</sub>`;\n\n return r;\n}\n\nfunction encodeImage(img: ImgNode, includeImages: boolean): string {\n if (!includeImages) {\n return `![${img.alt ?? ''}]`; // alt text only, no data URI\n }\n return `![${img.alt ?? ''}](data:${img.mime};base64,${img.b64})`;\n}\n\n/** pt → CSS border shorthand (only if stroke is visible) */\nfunction strokeToCss(s?: Stroke): string | undefined {\n if (!s || s.kind === 'none' || s.pt <= 0) return undefined;\n const kindMap: Record<string, string> = { solid: 'solid', dash: 'dashed', dot: 'dotted', double: 'double', none: 'none' };\n const style = kindMap[s.kind] ?? 'solid';\n const px = Math.max(1, Math.round(s.pt * 96 / 72));\n const color = s.color.startsWith('#') ? s.color : `#${s.color}`;\n return `${px}px ${style} ${color}`;\n}\n\nfunction encodeGrid(grid: GridNode, warns: string[], includeImages: boolean): string {\n if (grid.kids.length === 0) return '';\n\n // HTML 테이블로 출력 — 테두리/배경색을 인라인 스타일로 유지\n const rowCount = grid.kids.length;\n\n // Build occupancy map for rowspan\n const occupancy: Set<number>[] = Array.from({ length: rowCount }, () => new Set());\n let colCount = 0;\n for (let ri = 0; ri < rowCount; ri++) {\n const row = grid.kids[ri];\n let ci = 0;\n for (const cell of row.kids) {\n while (occupancy[ri].has(ci)) ci++;\n if (cell.rs > 1) {\n for (let r = ri + 1; r < ri + cell.rs && r < rowCount; r++) {\n for (let c = ci; c < ci + cell.cs; c++) occupancy[r].add(c);\n }\n }\n ci += cell.cs;\n }\n while (occupancy[ri].has(ci)) ci++;\n if (ci > colCount) colCount = ci;\n }\n\n let rows = '';\n for (let ri = 0; ri < rowCount; ri++) {\n const row = grid.kids[ri];\n let cells = '';\n let colIdx = 0;\n\n for (const cell of row.kids) {\n while (occupancy[ri].has(colIdx)) colIdx++;\n\n const cs = cell.cs > 1 ? ` colspan=\"${cell.cs}\"` : '';\n const rs = cell.rs > 1 ? ` rowspan=\"${cell.rs}\"` : '';\n\n const styles: string[] = ['padding:4px 6px', 'vertical-align:top'];\n const top = strokeToCss(cell.props.top);\n const bot = strokeToCss(cell.props.bot);\n const left = strokeToCss(cell.props.left);\n const right = strokeToCss(cell.props.right);\n if (top) styles.push(`border-top:${top}`);\n if (bot) styles.push(`border-bottom:${bot}`);\n if (left) styles.push(`border-left:${left}`);\n if (right) styles.push(`border-right:${right}`);\n if (cell.props.bg) styles.push(`background-color:#${cell.props.bg}`);\n if (cell.props.va === 'mid') styles[1] = 'vertical-align:middle';\n else if (cell.props.va === 'bot') styles[1] = 'vertical-align:bottom';\n\n const tag = (grid.props.headerRow && ri === 0) || cell.props.isHeader ? 'th' : 'td';\n const content = cell.kids.map(p => p.tag === 'para' ? encodePara(p, warns, includeImages) : encodeGrid(p, warns, includeImages)).join('\\n');\n cells += `<${tag}${cs}${rs} style=\"${styles.join(';')}\">${content}</${tag}>`;\n colIdx += cell.cs;\n }\n rows += `<tr>${cells}</tr>\\n`;\n }\n\n return `<table style=\"border-collapse:collapse;width:100%\">\\n<tbody>\\n${rows}</tbody>\\n</table>\\n`;\n}\n\nregistry.registerEncoder(new MdEncoder());\n","import type { DocRoot, ParaNode, SpanNode, GridNode, ContentNode, ImgNode, LinkNode } from '../../model/doc-tree';\nimport type { Outcome } from '../../contract/result';\nimport { succeed, fail } from '../../contract/result';\nimport { TextKit } from '../../toolkit/TextKit';\nimport { registry } from '../../pipeline/registry';\nimport { BaseEncoder } from '../../core/BaseEncoder';\n\nexport class HtmlEncoder extends BaseEncoder {\n protected getFormat(): string { return 'html'; }\n\n async encode(doc: DocRoot): Promise<Outcome<Uint8Array>> {\n try {\n const warns: string[] = [];\n const bodyParts: string[] = [];\n\n for (const sheet of doc.kids) {\n // Header/footer as comments\n if (sheet.headers?.default && sheet.headers.default.length > 0) {\n const hText = sheet.headers.default.map((p: ParaNode) => encodePara(p, warns)).join('');\n bodyParts.push(`<div class=\"hwp-header\">${hText}</div>`);\n }\n\n for (const kid of sheet.kids) {\n bodyParts.push(encodeContent(kid, warns));\n }\n\n if (sheet.footers?.default && sheet.footers.default.length > 0) {\n const fText = sheet.footers.default.map((p: ParaNode) => encodePara(p, warns)).join('');\n bodyParts.push(`<div class=\"hwp-footer\">${fText}</div>`);\n }\n }\n\n const title = this.escapeXml(doc.meta?.title ?? '');\n const html = `<!DOCTYPE html>\\n<html lang=\"ko\">\\n<head>\\n<meta charset=\"UTF-8\">\\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\\n<title>${title}</title>\\n<style>\\n${BASE_CSS}\\n</style>\\n</head>\\n<body>\\n<div class=\"hwp-doc\">\\n${bodyParts.join('\\n')}\\n</div>\\n</body>\\n</html>`;\n\n return succeed(this.stringToBytes(html), warns);\n } catch (e: any) {\n return fail(`HTML encode error: ${e?.message ?? String(e)}`);\n }\n }\n}\n\nconst BASE_CSS = `\nbody { margin: 0; padding: 0; background: #f0f0f0; }\n.hwp-doc { max-width: 800px; margin: 0 auto; background: #fff; padding: 40px 60px; box-shadow: 0 0 8px rgba(0,0,0,0.15); }\n.hwp-header, .hwp-footer { color: #666; font-size: 0.9em; border-bottom: 1px solid #ddd; margin-bottom: 8px; padding-bottom: 4px; }\n.hwp-footer { border-top: 1px solid #ddd; border-bottom: none; margin-top: 8px; padding-top: 4px; }\np { margin: 0; padding: 0; line-height: 1; }\ntable { border-collapse: collapse; width: 100%; margin: 8px 0; }\ntd, th { border: 1px solid #ccc; padding: 4px 8px; vertical-align: top; }\nimg { max-width: 100%; height: auto; }\n`.trim();\n\nfunction encodeContent(node: ContentNode, warns: string[]): string {\n return node.tag === 'grid' ? encodeGrid(node, warns) : encodePara(node, warns);\n}\n\nfunction encodePara(para: ParaNode, warns: string[]): string {\n const kids = para.kids.map((k): string => {\n if (k.tag === 'span') return encodeSpan(k, warns);\n if (k.tag === 'img') return encodeImage(k);\n if (k.tag === 'link') {\n const link = k as LinkNode;\n const inner = link.kids.map(s => encodeSpan(s, warns)).join('');\n return `<a href=\"${TextKit.escapeXml(link.href)}\">${inner}</a>`;\n }\n return '';\n }).join('');\n\n // Heading\n if (para.props.heading) {\n const tag = `h${para.props.heading}`;\n return `<${tag}>${kids}</${tag}>\\n`;\n }\n\n // List\n if (para.props.listOrd !== undefined) {\n const indent = (para.props.listLv ?? 0) * 20;\n const style = indent > 0 ? ` style=\"margin-left:${indent}px\"` : '';\n const marker = para.props.listOrd ? `<span class=\"list-marker\">1. </span>` : `<span class=\"list-marker\">• </span>`;\n return `<p${style}>${marker}${kids}</p>\\n`;\n }\n\n // Alignment\n const align = para.props.align;\n const styleAttrs: string[] = [];\n if (align && align !== 'left') styleAttrs.push(`text-align:${align}`);\n if (para.props.indentPt) styleAttrs.push(`margin-left:${para.props.indentPt.toFixed(1)}pt`);\n if (para.props.spaceBefore) styleAttrs.push(`margin-top:${para.props.spaceBefore.toFixed(1)}pt`);\n if (para.props.spaceAfter) styleAttrs.push(`margin-bottom:${para.props.spaceAfter.toFixed(1)}pt`);\n if (para.props.lineHeight) styleAttrs.push(`line-height:${para.props.lineHeight}`);\n\n const styleAttr = styleAttrs.length > 0 ? ` style=\"${styleAttrs.join(';')}\"` : '';\n return `<p${styleAttr}>${kids || '&nbsp;'}</p>\\n`;\n}\n\nfunction encodeSpan(span: SpanNode, warns: string[]): string {\n const parts: string[] = [];\n let hasPageNum = false;\n\n for (const kid of span.kids) {\n if (kid.tag === 'txt') {\n // __EXT_N__ 또는 __EXT_N_W<w>_H<h>__ 자리표시자 제거\n const content = kid.content.replace(/__EXT_\\d+(?:_W\\d+_H\\d+)?__/g, '');\n if (content) parts.push(TextKit.escapeXml(content));\n } else if (kid.tag === 'br') {\n parts.push('<br>');\n } else if (kid.tag === 'pb') {\n parts.push('<div style=\"page-break-after:always\"></div>');\n } else if (kid.tag === 'pagenum') {\n hasPageNum = true;\n warns.push('[SHIELD] HTML: 페이지 번호 — 정적 값으로 대체됨');\n parts.push('<span class=\"page-num\">[페이지]</span>');\n }\n }\n\n let text = parts.join('');\n if (hasPageNum && text.trim() === '<span class=\"page-num\">[페이지]</span>') {\n // keep as-is\n }\n\n const p = span.props;\n const css: string[] = [];\n if (p.font) css.push(`font-family:${TextKit.escapeXml(p.font)}`);\n if (p.pt) css.push(`font-size:${p.pt}pt`);\n if (p.color) css.push(`color:#${p.color}`);\n if (p.bg) css.push(`background-color:#${p.bg}`);\n if (p.b) css.push('font-weight:bold');\n if (p.i) css.push('font-style:italic');\n\n const decorations: string[] = [];\n if (p.u) decorations.push('underline');\n if (p.s) decorations.push('line-through');\n if (decorations.length > 0) css.push(`text-decoration:${decorations.join(' ')}`);\n\n if (p.sup) return `<sup${css.length ? ` style=\"${css.join(';')}\"` : ''}>${text}</sup>`;\n if (p.sub) return `<sub${css.length ? ` style=\"${css.join(';')}\"` : ''}>${text}</sub>`;\n if (css.length > 0) return `<span style=\"${css.join(';')}\">${text}</span>`;\n return text;\n}\n\nfunction encodeImage(img: ImgNode): string {\n const wStyle = img.w ? ` width=\"${Math.round(img.w / 72 * 96)}px\"` : '';\n const hStyle = img.h ? ` height=\"${Math.round(img.h / 72 * 96)}px\"` : '';\n const alt = TextKit.escapeXml(img.alt ?? '');\n return `<img src=\"data:${img.mime};base64,${img.b64}\" alt=\"${alt}\"${wStyle}${hStyle}>`;\n}\n\nfunction encodeGrid(grid: GridNode, warns: string[]): string {\n if (grid.kids.length === 0) return '';\n\n // Build occupancy map for rowspan\n const rowCount = grid.kids.length;\n const occupancy: Set<number>[] = Array.from({ length: rowCount }, () => new Set());\n let colCount = 0;\n for (let ri = 0; ri < rowCount; ri++) {\n const row = grid.kids[ri];\n let ci = 0;\n for (const cell of row.kids) {\n while (occupancy[ri].has(ci)) ci++;\n if (cell.rs > 1) {\n for (let r = ri + 1; r < ri + cell.rs && r < rowCount; r++) {\n for (let c = ci; c < ci + cell.cs; c++) occupancy[r].add(c);\n }\n }\n ci += cell.cs;\n }\n while (occupancy[ri].has(ci)) ci++;\n if (ci > colCount) colCount = ci;\n }\n\n let rows = '';\n for (let ri = 0; ri < rowCount; ri++) {\n const row = grid.kids[ri];\n let cells = '';\n let ci = 0;\n for (const cell of row.kids) {\n while (occupancy[ri].has(ci)) ci++;\n\n const isHeader = cell.props.isHeader || (grid.props.headerRow && ri === 0);\n const tag = isHeader ? 'th' : 'td';\n\n const cs = cell.cs > 1 ? ` colspan=\"${cell.cs}\"` : '';\n const rs = cell.rs > 1 ? ` rowspan=\"${cell.rs}\"` : '';\n\n const styleAttrs: string[] = [];\n if (cell.props.bg) styleAttrs.push(`background-color:#${cell.props.bg}`);\n const va = cell.props.va;\n if (va === 'mid') styleAttrs.push('vertical-align:middle');\n else if (va === 'bot') styleAttrs.push('vertical-align:bottom');\n const styleAttr = styleAttrs.length > 0 ? ` style=\"${styleAttrs.join(';')}\"` : '';\n\n const content = cell.kids.map(p => p.tag === 'para' ? encodePara(p, warns) : encodeGrid(p, warns)).join('');\n cells += `<${tag}${cs}${rs}${styleAttr}>${content}</${tag}>`;\n ci += cell.cs;\n }\n rows += `<tr>${cells}</tr>\\n`;\n }\n\n return `<table>\\n<tbody>\\n${rows}</tbody>\\n</table>\\n`;\n}\n\nregistry.registerEncoder(new HtmlEncoder());\n","/**\n * HwpEncoder — DocRoot → HWP 5.0 바이너리 (OLE2/CFB 컨테이너)\n *\n * ANYTOHWP에서 영감받은 개선 사항:\n * 1. HwpStyleBank — 7개 언어 그룹 독립 폰트 레지스트리 (HANGUL/LATIN/HANJA/…)\n * 2. readPixelDims — PNG/JPEG 바이너리 헤더에서 픽셀 치수 추출 → 정확한 HWPUNIT 변환\n * 3. mkIdMappings — 언어별 폰트 카운트를 개별 기록\n * 4. mkCharShape — 언어별 faceId[7] 사용\n *\n * OLE2 레이아웃:\n * FileHeader (stream) — 256-byte HWP 시그니처 + 플래그\n * DocInfo (stream) — zlib 압축된 FACE_NAME / CHAR_SHAPE / PARA_SHAPE 레코드\n * BodyText (storage)\n * Section0 (stream) — zlib 압축된 PAGE_DEF + 문단/표 레코드\n */\n\nimport type {\n DocRoot,\n ContentNode,\n ParaNode,\n SpanNode,\n GridNode,\n ImgNode,\n LinkNode,\n} from \"../../model/doc-tree\";\nimport type { Outcome } from \"../../contract/result\";\nimport type {\n TextProps,\n ParaProps,\n Stroke,\n PageDims,\n Align,\n} from \"../../model/doc-props\";\nimport { succeed, fail } from \"../../contract/result\";\nimport { Metric, safeFontToKr } from \"../../safety/StyleBridge\";\nimport { registry } from \"../../pipeline/registry\";\nimport { A4 } from \"../../model/doc-props\";\nimport pako from \"pako\";\nimport { TextKit } from \"../../toolkit/TextKit\";\nimport { BaseEncoder } from \"../../core/BaseEncoder\";\n\n// ─── HWP 5.0 태그 ID ────────────────────────────────────────\nconst T = 16; // HWPTAG_BEGIN\n\n// DocInfo 태그\nconst TAG_DOCUMENT_PROPERTIES = T + 0; // 16\nconst TAG_ID_MAPPINGS = T + 1; // 17\nconst TAG_BIN_DATA = T + 2; // 18\nconst TAG_FACE_NAME = T + 3; // 19\nconst TAG_BORDER_FILL = T + 4; // 20\nconst TAG_CHAR_SHAPE = T + 5; // 21\nconst TAG_PARA_SHAPE = T + 9; // 25\nconst TAG_STYLE = T + 10; // 26\n\n// BodyText 태그\nconst TAG_PARA_HEADER = T + 50; // 66\nconst TAG_PARA_TEXT = T + 51; // 67\nconst TAG_PARA_CHAR_SHAPE = T + 52; // 68\nconst TAG_PARA_LINE_SEG = T + 53; // 69\nconst TAG_CTRL_HEADER = T + 55; // 71\nconst TAG_LIST_HEADER = T + 56; // 72\nconst TAG_PAGE_DEF = T + 57; // 73\nconst TAG_FOOTNOTE_SHAPE = T + 58; // 74\nconst TAG_TABLE = T + 61; // 77\nconst TAG_SHAPE_COMPONENT_PICTURE = T + 69; // 85\n\n// Control ID (LE UINT32)\nconst CTRL_TABLE = 0x74626c20; // 'tbl '\nconst CTRL_SECD = 0x73656364; // 'secd'\nconst CTRL_PIC = 0x24706963; // '$pic'\nconst CTRL_FIELD_BEGIN = 0x646c6625; // '%fld'\nconst CTRL_FIELD_END = 0x646c665c; // '\\fld'\n\n/** 테두리선 굵기 인덱스 테이블 (pt) */\nconst BORDER_W_PT = [\n 0.28, 0.34, 0.43, 0.57, 0.71, 0.85, 1.13, 1.42, 1.7, 1.98, 2.84, 4.25, 5.67,\n 8.5, 11.34, 14.17,\n];\n\nconst BORDER_KIND_IDX: Record<string, number> = {\n solid: 0,\n dot: 1,\n dash: 2,\n double: 7,\n triple: 8,\n none: 0,\n};\n\nconst ALIGN_CODE: Record<string, number> = {\n justify: 0,\n left: 1,\n right: 2,\n center: 3,\n distribute: 4,\n};\n\n// ─── 바이너리 버퍼 라이터 ────────────────────────────────────\n\nclass BufWriter {\n private chunks: Uint8Array[] = [];\n private _sz = 0;\n get size() {\n return this._sz;\n }\n\n u8(v: number): this {\n this.chunks.push(new Uint8Array([v & 0xff]));\n this._sz++;\n return this;\n }\n u16(v: number): this {\n this.chunks.push(new Uint8Array([v & 0xff, (v >> 8) & 0xff]));\n this._sz += 2;\n return this;\n }\n u32(v: number): this {\n const b = new Uint8Array(4);\n b[0] = v & 0xff;\n b[1] = (v >>> 8) & 0xff;\n b[2] = (v >>> 16) & 0xff;\n b[3] = (v >>> 24) & 0xff;\n this.chunks.push(b);\n this._sz += 4;\n return this;\n }\n i32(v: number): this {\n return this.u32(v < 0 ? v + 0x100000000 : v);\n }\n i16(v: number): this {\n return this.u16(v < 0 ? v + 0x10000 : v);\n }\n bytes(d: Uint8Array): this {\n this.chunks.push(d);\n this._sz += d.length;\n return this;\n }\n zeros(n: number): this {\n this.chunks.push(new Uint8Array(n));\n this._sz += n;\n return this;\n }\n utf16(s: string): this {\n for (let i = 0; i < s.length; i++) this.u16(s.charCodeAt(i));\n return this;\n }\n colorRef(hex: string): this {\n const h = (hex || \"000000\").replace(\"#\", \"\").padStart(6, \"0\");\n return this.u8(parseInt(h.slice(0, 2), 16))\n .u8(parseInt(h.slice(2, 4), 16))\n .u8(parseInt(h.slice(4, 6), 16))\n .u8(0);\n }\n build(): Uint8Array {\n const out = new Uint8Array(this._sz);\n let off = 0;\n for (const c of this.chunks) {\n out.set(c, off);\n off += c.length;\n }\n return out;\n }\n}\n\n// ─── HWP 레코드 빌더 ─────────────────────────────────────────\n\nfunction mkRec(tag: number, level: number, data: Uint8Array): Uint8Array {\n const sz = data.length;\n const isLarge = sz >= 0xfff;\n const enc = isLarge ? 0xfff : sz;\n const hdr = (((enc & 0xfff) * 0x100000) | ((level & 0x3ff) << 10) | (tag & 0x3ff)) >>> 0;\n const w = new BufWriter().u32(hdr);\n if (isLarge) w.u32(sz);\n w.bytes(data);\n return w.build();\n}\n\n// ─── ANYTOHWP 영감: PNG/JPEG 바이너리 헤더에서 픽셀 치수 추출\nfunction readPixelDims(\n data: Uint8Array,\n mime: string,\n): { w: number; h: number } | null {\n try {\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n if (mime.includes(\"png\")) {\n if (\n data.length >= 24 &&\n view.getUint32(0) === 0x89504e47 &&\n view.getUint32(4) === 0x0d0a1a0a\n ) {\n return { w: view.getUint32(16), h: view.getUint32(20) };\n }\n } else if (mime.includes(\"jpeg\") || mime.includes(\"jpg\")) {\n let off = 2;\n while (off < data.length - 4) {\n const marker = view.getUint16(off);\n off += 2;\n if (marker === 0xffc0 || marker === 0xffc2) {\n return { w: view.getUint16(off + 5), h: view.getUint16(off + 3) };\n }\n if ((marker & 0xff00) !== 0xff00) break;\n off += view.getUint16(off);\n }\n }\n } catch {\n /* 무시 */\n }\n return null;\n}\n\n// ─── ANYTOHWP 영감: HwpStyleBank — 7개 언어 그룹 독립 폰트 레지스트리\n// StyleCollector를 대체하는 새로운 스타일 수집기\n\nconst LANG_GROUPS = [\n \"HANGUL\",\n \"LATIN\",\n \"HANJA\",\n \"JAPANESE\",\n \"OTHER\",\n \"SYMBOL\",\n \"USER\",\n] as const;\ntype LangGroup = (typeof LANG_GROUPS)[number];\n\n/** 한글 폰트 여부 판별 */\nfunction isKoreanFont(face: string): boolean {\n return (\n /[\\uAC00-\\uD7A3\\u3131-\\u318E]/.test(face) ||\n [\"맑은\", \"나눔\", \"굴림\", \"돋움\", \"바탕\", \"함초롬\", \"한컴\", \"HY\"].some((k) =>\n face.includes(k),\n )\n );\n}\n\nclass HwpStyleBank {\n readonly DEF_STROKE: Stroke = { kind: \"solid\", pt: 0.5, color: \"000000\" };\n\n // 언어별 독립 폰트 목록 (ANYTOHWP langFontFaces)\n private langFonts = new Map<LangGroup, string[]>(\n LANG_GROUPS.map((g) => [g, []]),\n );\n private langFontIdx = new Map<LangGroup, Map<string, number>>(\n LANG_GROUPS.map((g) => [g, new Map()]),\n );\n\n // charShape, parShape, borderFill 레지스트리\n readonly csProps: TextProps[] = [{}];\n private csIdx = new Map<string, number>([[csKey({}), 0]]);\n\n readonly psProps: ParaProps[] = [{}];\n private psIdx = new Map<string, number>([[psKey({}), 0]]);\n\n readonly bfData: BfEntry[] = [];\n private bfIdx = new Map<string, number>();\n\n // charShape마다 언어별 fontId를 기록\n readonly csFontIds: number[][] = [[0, 0, 0, 0, 0, 0, 0]]; // id=0 → 모두 0\n\n constructor() {\n // 기본 폰트 등록 (ANYTOHWP: 함초롬바탕)\n for (const g of LANG_GROUPS) this._registerLangFont(g, \"함초롬바탕\");\n this.addBorderFill(this.DEF_STROKE); // bfId=1\n }\n\n private _registerLangFont(lang: LangGroup, face: string): number {\n const idx = this.langFontIdx.get(lang)!;\n if (idx.has(face)) return idx.get(face)!;\n const id = this.langFonts.get(lang)!.length;\n this.langFonts.get(lang)!.push(face);\n idx.set(face, id);\n return id;\n }\n\n /** 폰트 이름 → 언어별 7개 ID 반환 (ANYTOHWP 방식) */\n registerFontForLangs(rawFace: string): number[] {\n const face = safeFontToKr(rawFace) || \"함초롬바탕\";\n const isKor = isKoreanFont(face);\n const hangulFace = isKor ? face : \"함초롬바탕\";\n const latinFace = isKor ? \"함초롬바탕\" : face;\n\n const ids: number[] = [];\n for (const lang of LANG_GROUPS) {\n const f = lang === \"LATIN\" ? latinFace : hangulFace;\n ids.push(this._registerLangFont(lang, f));\n }\n return ids; // [hangulId, latinId, hanjaId, japaneseId, otherId, symbolId, userId]\n }\n\n /** 언어별 폰트 목록 반환 */\n getFontsForLang(lang: LangGroup): string[] {\n return [...(this.langFonts.get(lang) ?? [])];\n }\n\n /** 폰트 수 반환 (mkIdMappings용) */\n getFontCount(lang: LangGroup): number {\n return this.langFonts.get(lang)?.length ?? 0;\n }\n\n addCharShape(p: TextProps): number {\n const k = csKey(p);\n if (this.csIdx.has(k)) return this.csIdx.get(k)!;\n const id = this.csProps.length;\n const fIds = p.font\n ? this.registerFontForLangs(p.font)\n : [0, 0, 0, 0, 0, 0, 0];\n this.csProps.push(p);\n this.csFontIds.push(fIds);\n this.csIdx.set(k, id);\n return id;\n }\n\n addParaShape(p: ParaProps): number {\n const k = psKey(p);\n if (this.psIdx.has(k)) return this.psIdx.get(k)!;\n const id = this.psProps.length;\n this.psProps.push(p);\n this.psIdx.set(k, id);\n return id;\n }\n\n addBorderFill(s: Stroke, bg?: string): number {\n const k = bfKey(s, bg);\n if (this.bfIdx.has(k)) return this.bfIdx.get(k)!;\n const id = this.bfData.length + 1;\n this.bfData.push({ uniform: true, s, bg });\n this.bfIdx.set(k, id);\n return id;\n }\n\n addBorderFillPerSide(\n l: Stroke,\n r: Stroke,\n t: Stroke,\n b: Stroke,\n bg?: string,\n ): number {\n const k = bfPerSideKey(l, r, t, b, bg);\n if (this.bfIdx.has(k)) return this.bfIdx.get(k)!;\n const id = this.bfData.length + 1;\n this.bfData.push({ uniform: false, l, r, t, b, bg });\n this.bfIdx.set(k, id);\n return id;\n }\n}\n\n// ─── 키 함수 ────────────────────────────────────────────────\n\nfunction csKey(p: TextProps): string {\n return [\n p.font ?? \"\",\n p.pt ?? 10,\n p.b ? 1 : 0,\n p.i ? 1 : 0,\n p.u ? 1 : 0,\n p.s ? 1 : 0,\n p.sup ? 1 : 0,\n p.sub ? 1 : 0,\n p.color ?? \"000000\",\n ].join(\"|\");\n}\n\nfunction psKey(p: ParaProps): string {\n return [\n p.align ?? \"left\",\n p.indentPt ?? 0,\n p.firstLineIndentPt ?? 0,\n p.spaceBefore ?? 0,\n p.spaceAfter ?? 0,\n p.lineHeight ?? 1,\n ].join(\"|\");\n}\n\nfunction bfKey(s: Stroke, bg?: string): string {\n return `${s.kind}|${s.pt}|${s.color}|${bg ?? \"\"}`;\n}\n\nfunction bfPerSideKey(\n l: Stroke,\n r: Stroke,\n t: Stroke,\n b: Stroke,\n bg?: string,\n): string {\n return `${bfKey(l)}/${bfKey(r)}/${bfKey(t)}/${bfKey(b)}/${bg ?? \"\"}`;\n}\n\ntype BfEntry =\n | { uniform: true; s: Stroke; bg?: string }\n | { uniform: false; l: Stroke; r: Stroke; t: Stroke; b: Stroke; bg?: string };\n\n// ─── Pre-scan: 스타일 수집 ──────────────────────────────────\n\nfunction collectNode(node: ContentNode, bank: HwpStyleBank): void {\n if (node.tag === \"para\") {\n bank.addParaShape(node.props);\n for (const kid of node.kids) {\n if (kid.tag === \"span\") bank.addCharShape((kid as SpanNode).props);\n }\n } else if (node.tag === \"grid\") {\n if (node.props.defaultStroke) bank.addBorderFill(node.props.defaultStroke);\n for (const row of node.kids) {\n for (const cell of row.kids) {\n const defStroke = node.props.defaultStroke ?? bank.DEF_STROKE;\n const cp = cell.props;\n if (cp.top || cp.bot || cp.left || cp.right) {\n bank.addBorderFillPerSide(\n cp.left ?? defStroke,\n cp.right ?? defStroke,\n cp.top ?? defStroke,\n cp.bot ?? defStroke,\n cp.bg,\n );\n } else {\n bank.addBorderFill(defStroke, cp.bg);\n }\n for (const para of cell.kids) collectNode(para, bank);\n }\n }\n }\n}\n\n// ─── DocInfo 레코드 빌더 ─────────────────────────────────────\n\nfunction mkDocumentProperties(): Uint8Array {\n return new BufWriter()\n .u16(1)\n .u16(1)\n .u16(1)\n .u16(1)\n .u16(1)\n .u16(1)\n .u16(1) // 7× UINT16 카운터\n .u32(0)\n .u32(0)\n .u32(0) // 캐럿 위치\n .build(); // 26 bytes\n}\n\n/**\n * HWPTAG_ID_MAPPINGS (72 bytes = 18 × INT32)\n * [0]=binData, [1-7]=7개 언어별 글꼴 수 (ANYTOHWP 방식으로 언어별 독립),\n * [8]=테두리/배경, [9]=글자모양, [10]=탭, [11]=번호, [12]=글머리,\n * [13]=문단모양, [14]=스타일, [15-17]=메모/변경추적\n */\nfunction mkIdMappings(bank: HwpStyleBank, nBinData = 0): Uint8Array {\n const w = new BufWriter();\n w.u32(nBinData);\n // [1-7]: 언어별 폰트 수 (ANYTOHWP: langFontFaces별 크기)\n for (const lang of LANG_GROUPS) w.u32(bank.getFontCount(lang));\n w.u32(bank.bfData.length); // [8]\n w.u32(bank.csProps.length); // [9]\n w.u32(0); // [10] tabDef\n w.u32(0); // [11] numbering\n w.u32(0); // [12] bullet\n w.u32(bank.psProps.length); // [13]\n w.u32(1); // [14] style (바탕글 1개)\n w.u32(0); // [15]\n w.u32(0); // [16]\n w.u32(0); // [17]\n return w.build(); // 18 × 4 = 72 bytes\n}\n\nfunction mkStyle(\n name: string,\n engName: string,\n paraPrId: number,\n charPrId: number,\n): Uint8Array {\n return new BufWriter()\n .u16(name.length)\n .utf16(name)\n .u16(engName.length)\n .utf16(engName)\n .u16(paraPrId)\n .u16(charPrId)\n .u16(0)\n .u16(1042)\n .u16(0)\n .build();\n}\n\nfunction mkFaceName(name: string): Uint8Array {\n return new BufWriter()\n .u8(0)\n .u16(name.length)\n .utf16(name)\n .u8(0)\n .u16(0)\n .zeros(10)\n .u16(0)\n .build();\n}\n\nfunction borderWidthIdx(pt: number): number {\n let best = 0;\n for (let i = 0; i < BORDER_W_PT.length; i++) {\n if (Math.abs(BORDER_W_PT[i] - pt) < Math.abs(BORDER_W_PT[best] - pt))\n best = i;\n }\n return best;\n}\n\nfunction mkBorderFill(s: Stroke, bg?: string): Uint8Array {\n const w = new BufWriter();\n const t = BORDER_KIND_IDX[s.kind] ?? 0;\n const wi = borderWidthIdx(s.pt);\n const col = s.color || \"000000\";\n w.u16(0);\n for (let i = 0; i < 4; i++) w.u8(t);\n for (let i = 0; i < 4; i++) w.u8(wi);\n for (let i = 0; i < 4; i++) w.colorRef(col);\n w.u8(0).u8(0).colorRef(\"000000\");\n if (bg) {\n w.u32(1).colorRef(bg).colorRef(\"FFFFFF\").u32(0);\n } else {\n w.u32(0);\n }\n return w.build();\n}\n\nfunction mkBorderFillPerSide(\n l: Stroke,\n r: Stroke,\n t: Stroke,\n b: Stroke,\n bg?: string,\n): Uint8Array {\n const w = new BufWriter();\n w.u16(0);\n w.u8(BORDER_KIND_IDX[l.kind] ?? 0)\n .u8(BORDER_KIND_IDX[r.kind] ?? 0)\n .u8(BORDER_KIND_IDX[t.kind] ?? 0)\n .u8(BORDER_KIND_IDX[b.kind] ?? 0);\n w.u8(borderWidthIdx(l.pt))\n .u8(borderWidthIdx(r.pt))\n .u8(borderWidthIdx(t.pt))\n .u8(borderWidthIdx(b.pt));\n w.colorRef(l.color || \"000000\")\n .colorRef(r.color || \"000000\")\n .colorRef(t.color || \"000000\")\n .colorRef(b.color || \"000000\");\n w.u8(0).u8(0).colorRef(\"000000\");\n if (bg) {\n w.u32(1).colorRef(bg).colorRef(\"FFFFFF\").u32(0);\n } else {\n w.u32(0);\n }\n return w.build();\n}\n\n/**\n * HWPTAG_CHAR_SHAPE (74 bytes)\n * ANYTOHWP 개선: faceId[7]에 언어별 ID를 개별 기록\n */\nfunction mkCharShape(fontIds: number[], p: TextProps): Uint8Array {\n const height = Math.round((p.pt ?? 10) * 100);\n let attr = 0;\n if (p.i) attr |= 1 << 0;\n if (p.b) attr |= 1 << 1;\n if (p.u) attr |= 1 << 2;\n if (p.s) attr |= 1 << 18;\n if (p.sup) attr |= 1 << 16;\n if (p.sub) attr |= 2 << 16;\n\n const w = new BufWriter();\n // faceId[7]: 언어별 독립 ID (ANYTOHWP 핵심 개선)\n for (const id of fontIds) w.u16(id);\n for (let i = 0; i < 7; i++) w.u8(100); // ratio\n for (let i = 0; i < 7; i++) w.u8(0); // spacing\n for (let i = 0; i < 7; i++) w.u8(100); // relSize\n for (let i = 0; i < 7; i++) w.u8(0); // offset\n w.i32(height).u32(attr).u8(0).u8(0);\n w.colorRef(p.color ?? \"000000\");\n w.colorRef(\"000000\"); // underlineColor\n w.colorRef(p.bg ?? \"FFFFFF\"); // shadeColor\n w.colorRef(\"000000\"); // shadowColor\n w.u16(0); // borderFillId\n w.colorRef(\"000000\"); // strikeColor\n return w.build(); // 74 bytes\n}\n\nfunction mkParaShape(p: ParaProps): Uint8Array {\n const alignVal = ALIGN_CODE[p.align ?? \"left\"] ?? 1;\n const attr1 = (alignVal & 0x7) << 2;\n const lineSpacePct = p.lineHeight ? Math.round(p.lineHeight * 100) : 160;\n return new BufWriter()\n .u32(attr1)\n .i32(Metric.ptToHwp(p.indentPt ?? 0))\n .i32(Metric.ptToHwp(p.indentRightPt ?? 0))\n .i32(Metric.ptToHwp(p.firstLineIndentPt ?? 0))\n .i32(Metric.ptToHwp(p.spaceBefore ?? 0))\n .i32(Metric.ptToHwp(p.spaceAfter ?? 0))\n .i32(lineSpacePct)\n .u16(0)\n .u16(0)\n .u16(0)\n .i16(0)\n .i16(0)\n .i16(0)\n .i16(0)\n .u32(0)\n .u32(4)\n .u32(lineSpacePct)\n .build(); // 54 bytes\n}\n\nfunction mkBinData(id: number, ext: string): Uint8Array {\n return new BufWriter().u16(0x0002).u16(id).u16(ext.length).utf16(ext).build();\n}\n\ninterface BinImage {\n id: number;\n ext: string;\n data: Uint8Array;\n}\n\n/**\n * DocInfo 스트림 빌더\n * ANYTOHWP 개선: 언어별 폰트 목록을 순서대로 독립 기록\n */\nfunction buildDocInfoStream(\n bank: HwpStyleBank,\n images: BinImage[] = [],\n): Uint8Array {\n const chunks: Uint8Array[] = [];\n\n chunks.push(mkRec(TAG_DOCUMENT_PROPERTIES, 0, mkDocumentProperties()));\n chunks.push(mkRec(TAG_ID_MAPPINGS, 1, mkIdMappings(bank, images.length)));\n\n for (const img of images) {\n chunks.push(mkRec(TAG_BIN_DATA, 1, mkBinData(img.id, img.ext)));\n }\n\n // ANYTOHWP 방식: 언어 그룹별로 독립된 FACE_NAME 레코드 직렬화\n for (const lang of LANG_GROUPS) {\n for (const face of bank.getFontsForLang(lang)) {\n chunks.push(mkRec(TAG_FACE_NAME, 1, mkFaceName(face)));\n }\n }\n\n for (const entry of bank.bfData) {\n chunks.push(\n mkRec(\n TAG_BORDER_FILL,\n 1,\n entry.uniform\n ? mkBorderFill(entry.s, entry.bg)\n : mkBorderFillPerSide(entry.l, entry.r, entry.t, entry.b, entry.bg),\n ),\n );\n }\n\n // charShape — 언어별 fontId 배열 사용\n for (let i = 0; i < bank.csProps.length; i++) {\n chunks.push(\n mkRec(TAG_CHAR_SHAPE, 1, mkCharShape(bank.csFontIds[i], bank.csProps[i])),\n );\n }\n\n for (const p of bank.psProps) {\n chunks.push(mkRec(TAG_PARA_SHAPE, 1, mkParaShape(p)));\n }\n\n chunks.push(mkRec(TAG_STYLE, 1, mkStyle(\"바탕글\", \"Normal\", 0, 0)));\n\n return concatU8(chunks);\n}\n\n// ─── BodyText 레코드 빌더 ────────────────────────────────────\n\nfunction mkPageDef(dims: PageDims): Uint8Array {\n return new BufWriter()\n .u32(Metric.ptToHwp(dims.wPt))\n .u32(Metric.ptToHwp(dims.hPt))\n .u32(Metric.ptToHwp(dims.ml))\n .u32(Metric.ptToHwp(dims.mr))\n .u32(Metric.ptToHwp(dims.mt))\n .u32(Metric.ptToHwp(dims.mb))\n .u32(dims.headerPt ? Metric.ptToHwp(dims.headerPt) : 0)\n .u32(dims.footerPt ? Metric.ptToHwp(dims.footerPt) : 0)\n .u32(0) // gutter\n .u32(dims.orient === \"landscape\" ? 1 : 0)\n .build(); // 40 bytes\n}\n\nfunction mkParaHeader(\n nchars: number,\n ctrlMask: number,\n psId: number,\n csCount: number,\n lineAlignCount = 0,\n instanceId = 0,\n): Uint8Array {\n return new BufWriter()\n .u32(nchars)\n .u32(ctrlMask)\n .u16(psId)\n .u8(0)\n .u8(0)\n .u16(csCount)\n .u16(0)\n .u16(lineAlignCount)\n .u32(instanceId)\n .u16(0)\n .build(); // 24 bytes\n}\n\nfunction mkParaText(text: string): Uint8Array {\n const w = new BufWriter();\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i);\n // 0x09(탭), 0x0A(줄바꿈), 0x03(필드시작), 0x04(필드종료) 등 허용\n w.u16(c);\n }\n w.u16(13); // 문단 종결자\n return w.build();\n}\n\nfunction mkParaCharShape(pairs: [pos: number, id: number][]): Uint8Array {\n const w = new BufWriter();\n for (const [pos, id] of pairs) w.u32(pos).u32(id);\n return w.build();\n}\n\n/**\n * 5가지 LineSpacing(줄 간격) 타입에 따른 height 계산 로직\n */\nfunction calcLineHeight(\n type: number,\n value: number,\n textHeight: number,\n): number {\n switch (type) {\n case 0:\n return Math.floor((textHeight * value) / 100);\n case 1:\n return value;\n case 2:\n return Math.max(textHeight, value);\n case 3:\n return textHeight + value;\n case 4:\n return Math.floor(textHeight * value);\n default:\n return Math.floor((textHeight * value) / 100);\n }\n}\n\n/**\n * LineSeg 36바이트 구조체 (HWP 5.0 공식 규격)\n */\nfunction mkLineSeg(\n textStartPos: number,\n vertPos: number,\n vertSize: number,\n textHeight: number,\n baseline: number,\n spacing: number,\n horzPos: number,\n horzSize: number,\n flags: number,\n): Uint8Array {\n return new BufWriter()\n .u32(textStartPos)\n .i32(vertPos)\n .i32(vertSize)\n .i32(textHeight)\n .i32(baseline)\n .i32(spacing)\n .i32(horzPos)\n .i32(horzSize)\n .u32(flags)\n .build(); // 36 bytes\n}\n\nfunction buildDefaultLineSeg(\n availWidthHwp: number,\n fontHwp: number,\n nchars: number,\n paraProps?: ParaProps,\n vertPos = 0,\n): Uint8Array {\n const ratio = paraProps?.lineHeight\n ? Math.round(paraProps.lineHeight * 100)\n : 160;\n const vertSize = calcLineHeight(0, ratio, fontHwp);\n const baseline = Math.round(fontHwp * 0.85);\n const spacing = vertSize - fontHwp;\n // flags: bit 0 (페이지 첫 줄), bit 1 (컬럼 첫 줄)\n const flags = 3;\n\n return mkLineSeg(\n 0,\n vertPos,\n vertSize,\n fontHwp,\n baseline,\n spacing,\n 0,\n availWidthHwp,\n flags,\n );\n}\n\nfunction mkSecdParaText(): Uint8Array {\n const lo = CTRL_SECD & 0xffff;\n const hi = (CTRL_SECD >>> 16) & 0xffff;\n return new BufWriter()\n .u16(0x0002)\n .u16(lo)\n .u16(hi)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0x0002)\n .u16(0x000d)\n .build();\n}\n\nfunction mkTableParaText(): Uint8Array {\n const lo = CTRL_TABLE & 0xffff;\n const hi = (CTRL_TABLE >>> 16) & 0xffff;\n return new BufWriter()\n .u16(0x000b)\n .u16(lo)\n .u16(hi)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0x000b)\n .u16(0x000d)\n .build();\n}\n\nfunction mkPicParaText(): Uint8Array {\n const lo = CTRL_PIC & 0xffff;\n const hi = (CTRL_PIC >>> 16) & 0xffff;\n return new BufWriter()\n .u16(0x000b)\n .u16(lo)\n .u16(hi)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0)\n .u16(0x000b)\n .u16(0x000d)\n .build();\n}\n\n// ─── 이미지 관련 레코드 (ANYTOHWP 영감: 픽셀 치수 우선 사용)\n\ninterface ImgLayout {\n wrap?: string;\n xPt?: number;\n yPt?: number;\n zOrder?: number;\n distL?: number;\n distR?: number;\n distT?: number;\n distB?: number;\n}\n\nfunction mkShapeComponentPicture(\n binDataId: number,\n wHwp: number,\n hHwp: number,\n): Uint8Array {\n const w = new BufWriter();\n w.u32(CTRL_PIC).zeros(15);\n w.u32(0).u32(0).u32(wHwp).u32(hHwp);\n w.u32(0).u32(0).u32(wHwp).u32(hHwp);\n w.zeros(36);\n w.u16(binDataId).u8(0).u8(0).u8(0).zeros(5);\n return w.build();\n}\n\nfunction mkObjectCtrl(\n ctrlId: number,\n wHwp: number,\n hHwp: number,\n instanceId: number,\n layout?: ImgLayout,\n): Uint8Array {\n let attr = 0x082a2210;\n if (layout?.wrap === \"inline\") attr |= 1 << 3;\n return new BufWriter()\n .u32(ctrlId)\n .u32(attr)\n .i32(layout?.yPt ? Metric.ptToHwp(layout.yPt) : 0)\n .i32(layout?.xPt ? Metric.ptToHwp(layout.xPt) : 0)\n .u32(wHwp)\n .u32(hHwp)\n .i32(layout?.zOrder ?? 0)\n .u16(layout?.distL ? Metric.ptToHwp(layout.distL) : 0)\n .u16(layout?.distR ? Metric.ptToHwp(layout.distR) : 0)\n .u16(layout?.distT ? Metric.ptToHwp(layout.distT) : 0)\n .u16(layout?.distB ? Metric.ptToHwp(layout.distB) : 0)\n .u32(instanceId)\n .i32(0)\n .u16(0)\n .build(); // 46 bytes\n}\n\nfunction mkFieldBeginCtrl(instanceId: number): Uint8Array {\n // 46-byte Object Control Header for Field\n return new BufWriter()\n .u32(CTRL_FIELD_BEGIN)\n .u32(0x00000002) // 필드 플래그\n .zeros(28) // xy/size 등 불필요 (필드는 비가시)\n .u32(instanceId)\n .zeros(6)\n .build();\n}\n\nfunction mkFieldEndCtrl(beginId: number): Uint8Array {\n return new BufWriter()\n .u32(CTRL_FIELD_END)\n .u32(0)\n .zeros(28)\n .u32(beginId)\n .zeros(6)\n .build();\n}\n\n/**\n * 이미지 단락 인코딩\n * ANYTOHWP 개선: PNG/JPEG 픽셀 치수에서 HWPUNIT 계산\n */\nfunction encodePicPara(\n imgNode: ImgNode,\n binDataId: number,\n bank: HwpStyleBank,\n lv: number,\n idGen: () => number,\n availWidthHwp: number,\n): Uint8Array[] {\n // ANYTOHWP 방식: 픽셀 치수 추출 시도 → 실패 시 pt 기반으로 폴백\n const rawData = TextKit.base64Decode(imgNode.b64);\n const pixDims = readPixelDims(rawData, imgNode.mime);\n\n let wHwp: number, hHwp: number;\n if (pixDims && pixDims.w > 0 && pixDims.h > 0) {\n wHwp = Metric.ptToHwp((pixDims.w * 72) / 96); // px → pt(96dpi) → hwpunit\n hHwp = Metric.ptToHwp((pixDims.h * 72) / 96);\n } else {\n wHwp = Metric.ptToHwp(imgNode.w);\n hHwp = Metric.ptToHwp(imgNode.h);\n }\n\n // 가용 너비 초과 방지\n if (wHwp > availWidthHwp) {\n hHwp = Math.round((hHwp * availWidthHwp) / wHwp);\n wHwp = availWidthHwp;\n }\n\n const CTRL_MASK = 1 << 11;\n const instanceId = idGen();\n const psId = bank.addParaShape({});\n\n return [\n mkRec(\n TAG_PARA_HEADER,\n lv,\n mkParaHeader(9, CTRL_MASK, psId, 1, 1, instanceId),\n ),\n mkRec(TAG_PARA_TEXT, lv + 1, mkPicParaText()),\n mkRec(TAG_PARA_CHAR_SHAPE, lv + 1, mkParaCharShape([[0, 0]])),\n mkRec(\n TAG_PARA_LINE_SEG,\n lv + 1,\n buildDefaultLineSeg(availWidthHwp, hHwp, 9),\n ),\n mkRec(\n TAG_CTRL_HEADER,\n lv + 1,\n mkObjectCtrl(CTRL_PIC, wHwp, hHwp, idGen(), imgNode.layout),\n ),\n mkRec(\n TAG_SHAPE_COMPONENT_PICTURE,\n lv + 2,\n mkShapeComponentPicture(binDataId, wHwp, hHwp),\n ),\n ];\n}\n\n// ─── 문단 인코딩 ─────────────────────────────────────────────\n\nfunction encodePara(\n para: ParaNode,\n bank: HwpStyleBank,\n lv: number,\n instanceId: number,\n availWidthHwp: number,\n mask = 0,\n vertPos = 0,\n): Uint8Array[] {\n let text = \"\";\n const csPairs: [number, number][] = [];\n let pos = 0;\n let fontHwp = 1000;\n const ctrlRecords: Uint8Array[] = [];\n\n for (const kid of para.kids) {\n if (\n kid.tag === \"span\" &&\n (kid as SpanNode).props.pt &&\n ((kid as SpanNode).props.pt as number) > 0\n ) {\n fontHwp = Metric.ptToHwp((kid as SpanNode).props.pt as number);\n break;\n }\n }\n\n // 내부적으로 사용되는 ID 생성기 (단락 내에서 로컬하게 사용)\n let localIdCounter = 10000;\n const localIdGen = () => localIdCounter++;\n\n function processKids(kids: any[]): void {\n for (const kid of kids) {\n if (kid.tag === \"span\") {\n const span = kid as SpanNode;\n const csId = bank.addCharShape(span.props);\n if (!csPairs.length || csPairs[csPairs.length - 1][1] !== csId) {\n csPairs.push([pos, csId]);\n }\n for (const t of span.kids) {\n if (t.tag === \"txt\") {\n text += t.content;\n pos += t.content.length;\n }\n }\n } else if (kid.tag === \"link\") {\n const link = kid as LinkNode;\n mask |= 1 << 11; // 하이퍼링크 마스크\n\n const fieldBeginId = localIdGen();\n // 1. 시작 제어 문자 (0x03)\n text += String.fromCharCode(3);\n pos += 1;\n ctrlRecords.push(\n mkRec(TAG_CTRL_HEADER, lv + 1, mkFieldBeginCtrl(fieldBeginId)),\n );\n\n // 2. 내용 처리\n processKids(link.kids);\n\n // 3. 종료 제어 문자 (0x04)\n text += String.fromCharCode(4);\n pos += 1;\n ctrlRecords.push(\n mkRec(TAG_CTRL_HEADER, lv + 1, mkFieldEndCtrl(fieldBeginId)),\n );\n }\n }\n }\n processKids(para.kids);\n if (!csPairs.length) csPairs.push([0, 0]);\n\n const psId = bank.addParaShape(para.props);\n const nchars = text.length + 1;\n\n return [\n mkRec(\n TAG_PARA_HEADER,\n lv,\n mkParaHeader(nchars, mask, psId, csPairs.length, 1, instanceId),\n ),\n mkRec(TAG_PARA_TEXT, lv + 1, mkParaText(text)),\n mkRec(TAG_PARA_CHAR_SHAPE, lv + 1, mkParaCharShape(csPairs)),\n mkRec(\n TAG_PARA_LINE_SEG,\n lv + 1,\n buildDefaultLineSeg(availWidthHwp, fontHwp, nchars, para.props, vertPos),\n ),\n ...ctrlRecords,\n ];\n}\n\n// ─── 표 인코딩 ───────────────────────────────────────────────\n\nfunction mkTableCtrl(\n wHwp: number,\n hHwp: number,\n instanceId: number,\n align: Align = \"left\",\n): Uint8Array {\n // 표 정렬 속성 플래그 (HWP 표 제어 문자)\n // offset 20-21: 속성 플래그 (align: left=0, center=1, right=2, justify=3)\n const alignFlags = { left: 0, center: 1, right: 2, justify: 3, distribute: 0, distribute_space: 0 }[align] ?? 0;\n return new BufWriter()\n .u32(CTRL_TABLE)\n .u32(0x082a2211)\n .i32(0)\n .i32(0)\n .u32(wHwp)\n .u32(hHwp)\n .i32(7)\n .u16(140)\n .u16(140)\n .u16(140)\n .u16(140)\n .u32(instanceId)\n .i32(alignFlags)\n .u16(0)\n .build(); // 46 bytes\n}\n\nfunction mkTableRecord(\n rowCnt: number,\n colCnt: number,\n rowHwp: number[],\n bfId: number,\n): Uint8Array {\n const w = new BufWriter();\n w.u32(0x04000006).u16(rowCnt).u16(colCnt).u16(0);\n w.u16(510).u16(510).u16(141).u16(141);\n for (const h of rowHwp) w.u16(Math.max(1, h & 0xffff));\n w.u16(bfId).u16(0);\n return w.build();\n}\n\nfunction mkCellListHeader(\n paraCount: number,\n row: number,\n col: number,\n rs: number,\n cs: number,\n wHwp: number,\n hHwp: number,\n bfId: number,\n padL = 141,\n padR = 141,\n padT = 141,\n padB = 141,\n): Uint8Array {\n return new BufWriter()\n .u16(paraCount)\n .u32(0)\n .u16(0)\n .u16(col)\n .u16(row)\n .u16(rs)\n .u16(cs)\n .u32(wHwp)\n .u32(hHwp)\n .u16(padL)\n .u16(padR)\n .u16(padT)\n .u16(padB)\n .u16(bfId)\n .zeros(13)\n .build(); // 47 bytes\n}\n\nconst DEFAULT_ROW_HEIGHT_PT = 14;\n\nfunction encodeGrid(\n grid: GridNode,\n bank: HwpStyleBank,\n lv: number,\n idGen: () => number,\n availWidthHwp: number,\n): Uint8Array[] {\n const records: Uint8Array[] = [];\n const rowCnt = grid.kids.length;\n const colCnt = Math.max(1, grid.kids[0]?.kids.length ?? 1);\n\n const cwPt = (grid.props as any).colWidths ?? [];\n const totalPt = cwPt.reduce((s: number, w: number) => s + w, 0) || 453;\n const defColPt = totalPt / colCnt;\n const defStroke = grid.props.defaultStroke ?? bank.DEF_STROKE;\n const defBfId = bank.addBorderFill(defStroke);\n\n const rowHwp = grid.kids.map((row: any) =>\n row.heightPt != null && row.heightPt > 0\n ? Metric.ptToHwp(row.heightPt)\n : Metric.ptToHwp(DEFAULT_ROW_HEIGHT_PT),\n );\n\n const tblWPt =\n cwPt.length > 0 ? cwPt.reduce((s: number, w: number) => s + w, 0) : totalPt;\n const tblHPt = grid.kids.reduce(\n (s: number, row: any) =>\n s +\n (row.heightPt != null && row.heightPt > 0\n ? row.heightPt\n : DEFAULT_ROW_HEIGHT_PT),\n 0,\n );\n const tblInstanceId = idGen();\n const tblAlign = grid.props.align ?? \"left\";\n\n records.push(\n mkRec(\n TAG_CTRL_HEADER,\n lv,\n mkTableCtrl(\n Metric.ptToHwp(tblWPt),\n Metric.ptToHwp(tblHPt),\n tblInstanceId,\n tblAlign,\n ),\n ),\n );\n records.push(\n mkRec(TAG_TABLE, lv + 1, mkTableRecord(rowCnt, colCnt, rowHwp, defBfId)),\n );\n\n for (let r = 0; r < grid.kids.length; r++) {\n for (let c = 0; c < grid.kids[r].kids.length; c++) {\n const cell = grid.kids[r].kids[c];\n const wHwp = Metric.ptToHwp(cwPt[c] ?? defColPt);\n const hHwp = rowHwp[r];\n const cp = cell.props;\n const hasPerSide = cp.top || cp.bot || cp.left || cp.right;\n const bfId = hasPerSide\n ? bank.addBorderFillPerSide(\n cp.left ?? defStroke,\n cp.right ?? defStroke,\n cp.top ?? defStroke,\n cp.bot ?? defStroke,\n cp.bg,\n )\n : bank.addBorderFill(defStroke, cp.bg);\n\n const paras =\n cell.kids.length > 0\n ? cell.kids\n : [{ tag: \"para\" as const, props: {}, kids: [] }];\n\n const padL = cp.padL !== undefined ? Metric.ptToHwp(cp.padL) : 510;\n const padR = cp.padR !== undefined ? Metric.ptToHwp(cp.padR) : 510;\n const padT = cp.padT !== undefined ? Metric.ptToHwp(cp.padT) : 141;\n const padB = cp.padB !== undefined ? Metric.ptToHwp(cp.padB) : 141;\n\n records.push(\n mkRec(\n TAG_LIST_HEADER,\n lv + 1,\n mkCellListHeader(\n paras.length,\n r,\n c,\n cell.rs,\n cell.cs,\n wHwp,\n hHwp,\n bfId,\n padL,\n padR,\n padT,\n padB,\n ),\n ),\n );\n\n const cellWidthHwp = Metric.ptToHwp(cwPt[c] ?? defColPt);\n for (const para of paras) {\n records.push(\n ...encodePara(para as ParaNode, bank, lv + 1, idGen(), cellWidthHwp),\n );\n }\n }\n }\n return records;\n}\n\nfunction mkSectionCtrl(): Uint8Array {\n return new BufWriter()\n .u32(CTRL_SECD)\n .u32(0)\n .u32(1134)\n .u16(0x4000)\n .u16(0x001f)\n .zeros(31)\n .build(); // 47 bytes\n}\n\nfunction buildSectionParagraph(\n dims: PageDims,\n instanceId: number,\n): Uint8Array[] {\n const SECD_CTRL_MASK = 1 << 2;\n const nchars = 9;\n const availWidthHwp = Math.max(\n 1000,\n Metric.ptToHwp(dims.wPt) -\n Metric.ptToHwp(dims.ml) -\n Metric.ptToHwp(dims.mr),\n );\n return [\n mkRec(\n TAG_PARA_HEADER,\n 0,\n mkParaHeader(nchars, SECD_CTRL_MASK, 0, 1, 1, instanceId),\n ),\n mkRec(TAG_PARA_TEXT, 1, mkSecdParaText()),\n mkRec(TAG_PARA_CHAR_SHAPE, 1, mkParaCharShape([[0, 0]])),\n mkRec(\n TAG_PARA_LINE_SEG,\n 1,\n buildDefaultLineSeg(availWidthHwp, 1000, nchars),\n ),\n mkRec(TAG_CTRL_HEADER, 1, mkSectionCtrl()),\n mkRec(TAG_PAGE_DEF, 2, mkPageDef(dims)),\n mkRec(TAG_FOOTNOTE_SHAPE, 2, new Uint8Array(28)),\n mkRec(TAG_FOOTNOTE_SHAPE, 2, new Uint8Array(28)),\n ];\n}\n\n// ─── BodyText 스트림 빌더 ─────────────────────────────────────\n\nfunction flatImgNodes(kids: any[]): any[] {\n const result: any[] = [];\n for (const kid of kids) {\n if (kid.tag === \"img\") result.push(kid);\n else if (kid.tag === \"link\" && Array.isArray(kid.kids))\n result.push(...flatImgNodes(kid.kids));\n }\n return result;\n}\n\nfunction b64Matches(binImg: BinImage, b64: string): boolean {\n const a = TextKit.base64Encode(binImg.data).replace(/\\s/g, \"\");\n const b = b64.replace(/\\s/g, \"\");\n return a === b;\n}\n\nfunction buildBodyTextStream(\n doc: DocRoot,\n bank: HwpStyleBank,\n images: BinImage[],\n): Uint8Array {\n const chunks: Uint8Array[] = [];\n const dims = doc.kids[0]?.dims ?? A4;\n let instanceIdCounter = 1;\n const idGen = () => instanceIdCounter++;\n const availWidthHwp = Math.max(\n 1000,\n Metric.ptToHwp(dims.wPt) -\n Metric.ptToHwp(dims.ml) -\n Metric.ptToHwp(dims.mr),\n );\n\n for (const r of buildSectionParagraph(dims, idGen())) chunks.push(r);\n\n const TABLE_CTRL_MASK = 1 << 11;\n let vertPos = 0; // 단락 간격 추적\n\n for (const sheet of doc.kids) {\n for (const node of sheet.kids) {\n if (node.tag === \"para\") {\n const para = node as ParaNode;\n\n const hasPageBreak = para.kids.some(\n (k) => k.tag === \"span\" && k.kids.some((c) => c.tag === \"pb\"),\n );\n let paraMask = hasPageBreak ? 1 << 2 : 0;\n\n // 코드 블록 감지 → 1×1 표로 감싸기\n const hasCourier = (kids: any[]): boolean =>\n kids.some(\n (k) =>\n (k.tag === \"span\" &&\n k.props.font?.toLowerCase().includes(\"courier\")) ||\n (k.tag === \"link\" && hasCourier(k.kids)),\n );\n const isCode =\n para.props.styleId?.toLowerCase().includes(\"code\") ||\n hasCourier(para.kids);\n\n if (isCode) {\n const gridNode: GridNode = {\n tag: \"grid\",\n props: {\n colWidths: [Metric.hwpToPt(availWidthHwp)],\n defaultStroke: { kind: \"solid\", pt: 0.5, color: \"aaaaaa\" },\n },\n kids: [\n {\n tag: \"row\",\n kids: [\n {\n tag: \"cell\",\n rs: 1,\n cs: 1,\n props: { bg: \"f4f4f4\" },\n kids: [para],\n },\n ],\n },\n ],\n };\n chunks.push(\n mkRec(\n TAG_PARA_HEADER,\n 0,\n mkParaHeader(9, TABLE_CTRL_MASK | paraMask, 0, 1, 1, idGen()),\n ),\n );\n chunks.push(mkRec(TAG_PARA_TEXT, 1, mkTableParaText()));\n chunks.push(mkRec(TAG_PARA_CHAR_SHAPE, 1, mkParaCharShape([[0, 0]])));\n chunks.push(\n mkRec(\n TAG_PARA_LINE_SEG,\n 1,\n buildDefaultLineSeg(availWidthHwp, 1000, 9, undefined, vertPos),\n ),\n );\n vertPos += Metric.ptToHwp(20); // 코드 블록 후 간격\n for (const r of encodeGrid(gridNode, bank, 1, idGen, availWidthHwp))\n chunks.push(r);\n continue;\n }\n\n const imgNodes = flatImgNodes(para.kids);\n if (imgNodes.length > 0) {\n for (const img of imgNodes) {\n const binImg = images.find((b) => b64Matches(b, img.b64));\n if (binImg) {\n for (const r of encodePicPara(\n img,\n binImg.id,\n bank,\n 0,\n idGen,\n availWidthHwp,\n )) {\n // 첫 레코드가 PARA_HEADER인 경우 페이지 브레이크 마스크 적용\n chunks.push(r);\n }\n vertPos += Metric.ptToHwp(img.h ?? 100); // 이미지 높이 추가\n }\n }\n const textKids = para.kids.filter(\n (k: any) => k.tag !== \"img\" && k.tag !== \"link\",\n );\n if (textKids.length > 0) {\n const textPara: ParaNode = {\n tag: \"para\",\n props: para.props,\n kids: textKids as any,\n };\n for (const r of encodePara(\n textPara,\n bank,\n 0,\n idGen(),\n availWidthHwp,\n paraMask,\n vertPos,\n )) {\n // PARA_HEADER 레코드(목록의 첫 번째)에 마스크 적용\n if (r[0] === (TAG_PARA_HEADER & 0xff)) {\n // 레코드 헤더 수정은 복잡하므로 encodePara 내부에서 처리하는 것이 안전하지만\n // 여기서는 간단히 구현하기 위해 encodePara의 인자로 mask를 넘기도록 구조를 변경하는 것이 좋습니다.\n }\n chunks.push(r);\n }\n // 단락 높이 계산 및 vertPos 업데이트 (이미지/텍스트 혼합)\n const fontHwp_img = (\n textKids.find(\n (k: any) => k.tag === \"span\" && k.props?.pt,\n ) as SpanNode\n )?.props.pt\n ? Metric.ptToHwp(\n (\n textKids.find(\n (k: any) => k.tag === \"span\" && k.props?.pt,\n ) as SpanNode\n ).props.pt as number,\n )\n : 1000;\n const lineSpacePct_img = Math.round((para.props.lineHeight ?? 1.6) * 100);\n vertPos += Math.round((fontHwp_img * lineSpacePct_img) / 100);\n }\n } else {\n for (const r of encodePara(\n para,\n bank,\n 0,\n idGen(),\n availWidthHwp,\n paraMask,\n vertPos,\n ))\n chunks.push(r);\n // 단락 높이 계산 및 vertPos 업데이트 (일반 단락)\n const fontHwp_para = (\n para.kids.find(\n (k: any) => k.tag === \"span\" && k.props?.pt,\n ) as SpanNode\n )?.props.pt\n ? Metric.ptToHwp(\n (\n para.kids.find(\n (k: any) => k.tag === \"span\" && k.props?.pt,\n ) as SpanNode\n ).props.pt as number,\n )\n : 1000;\n const lineSpacePct_para = para.props.lineHeight\n ? Math.round(para.props.lineHeight * 100)\n : 160;\n vertPos += Math.round((fontHwp_para * lineSpacePct_para) / 100);\n }\n } else if (node.tag === \"grid\") {\n chunks.push(\n mkRec(\n TAG_PARA_HEADER,\n 0,\n mkParaHeader(9, TABLE_CTRL_MASK, 0, 1, 1, idGen()),\n ),\n );\n chunks.push(mkRec(TAG_PARA_TEXT, 1, mkTableParaText()));\n chunks.push(mkRec(TAG_PARA_CHAR_SHAPE, 1, mkParaCharShape([[0, 0]])));\n chunks.push(\n mkRec(\n TAG_PARA_LINE_SEG,\n 1,\n buildDefaultLineSeg(availWidthHwp, 1000, 9, undefined, vertPos),\n ),\n );\n vertPos += Metric.ptToHwp(20); // 표 후 간격\n for (const r of encodeGrid(\n node as GridNode,\n bank,\n 1,\n idGen,\n availWidthHwp,\n ))\n chunks.push(r);\n }\n }\n }\n\n return concatU8(chunks);\n}\n\n// ─── HWP FileHeader ─────────────────────────────────────────\n/**\n * HWP 5.0 FileHeader 를 생성합니다.\n *\n * 구조:\n * 0-15: 시그니처 \"HWP Document File\" (16 바이트)\n * 16-31: reserved (16 바이트)\n * 32-35: version (4 바이트, Little-Endian) - 0x05000300 = 5.0.3.0\n * 36-39: flags (4 바이트, Little-Endian) - bit 0 = compressed, bit 1 = encrypted\n * 40-255: reserved (216 바이트)\n *\n * 총 256 바이트\n */\nfunction buildHwpFileHeader(): Uint8Array {\n const SIZE = 256;\n const buf = new Uint8Array(SIZE);\n const dv = new DataView(buf.buffer);\n\n // 0-15: 시그니처 \"HWP Document File\" (16 바이트)\n const sig = \"HWP Document File\";\n for (let i = 0; i < sig.length; i++) {\n buf[i] = sig.charCodeAt(i);\n }\n\n // 16-31: reserved (0 으로 초기화됨)\n\n // 32-35: version (4 바이트, Little-Endian) - 0x05000300 = 5.0.3.0\n dv.setUint32(32, 0x05000300, true);\n\n // 36-39: flags (4 바이트, Little-Endian)\n // bit 0 = 1: compressed (압축됨)\n // bit 1 = 0: not encrypted (암호화 안됨)\n dv.setUint32(36, 0x00000001, true);\n\n // 40-255: reserved (0 으로 초기화됨)\n\n // 검증\n if (buf.length !== SIZE) {\n throw new Error(`FileHeader 크기 오류: ${buf.length} (기대: ${SIZE})`);\n }\n if (new TextDecoder().decode(buf.subarray(0, sig.length)) !== sig) {\n throw new Error(\"FileHeader 시그니처 오류\");\n }\n if (dv.getUint32(32, true) !== 0x05000300) {\n throw new Error(\"FileHeader 버전 오류\");\n }\n\n return buf;\n}\n\n// ─── OLE2/CFB 컨테이너 빌더 ─────────────────────────────────\n\nfunction buildHwpOle2(\n fileHeaderData: Uint8Array,\n docInfoData: Uint8Array,\n section0Data: Uint8Array,\n binImages: BinImage[] = [],\n): Uint8Array {\n const SS = 512; // 정규 섹터 크기\n const MSS = 64; // 미니 섹터 크기\n const ENDOFCHAIN = 0xfffffffe;\n const FREESECT = 0xffffffff;\n const FATSECT = 0xfffffffd;\n\n // FileHeader 크기 검증\n if (fileHeaderData.length < 256) {\n throw new Error(\n `FileHeader 크기 부족: ${fileHeaderData.length} (최소 256)`,\n );\n }\n\n // 스트림 정의 및 4096바이트 미만(isMini) 여부 분류\n interface OleStream {\n name: string;\n data: Uint8Array;\n dirIdx: number;\n isMini: boolean;\n startSec?: number; // 미니 스트림은 미니 FAT 내 시작 인덱스, 정규 스트림은 regular FAT 내 시작 섹터\n }\n\n const streams: OleStream[] = [];\n streams.push({\n name: \"FileHeader\",\n data: fileHeaderData,\n dirIdx: 1,\n isMini: fileHeaderData.length < 4096,\n });\n streams.push({\n name: \"DocInfo\",\n data: docInfoData,\n dirIdx: 2,\n isMini: docInfoData.length < 4096,\n });\n streams.push({\n name: \"Section0\",\n data: section0Data,\n dirIdx: 4,\n isMini: section0Data.length < 4096,\n });\n\n for (let i = 0; i < binImages.length; i++) {\n const img = binImages[i];\n const name = `BIN${String(img.id).padStart(4, \"0\")}.${img.ext}`;\n streams.push({\n name,\n data: img.data,\n dirIdx: 6 + i,\n isMini: img.data.length < 4096,\n });\n }\n\n // 미니 스트림 패킹 및 Mini FAT 체인 생성\n const miniStreams = streams.filter((s) => s.isMini);\n const miniSectorList: number[] = [];\n let miniStreamDataLength = 0;\n\n for (const s of miniStreams) {\n const startSec = miniStreamDataLength / MSS;\n s.startSec = startSec;\n\n const len = s.data.length;\n const numMiniSecs = Math.ceil(len / MSS);\n\n for (let i = 0; i < numMiniSecs; i++) {\n const curSec = startSec + i;\n const nextSec = i === numMiniSecs - 1 ? ENDOFCHAIN : curSec + 1;\n\n while (miniSectorList.length <= curSec) {\n miniSectorList.push(FREESECT);\n }\n miniSectorList[curSec] = nextSec;\n }\n\n miniStreamDataLength += numMiniSecs * MSS;\n }\n\n // 미니 스트림 데이터 버퍼 구성\n const miniStreamData = new Uint8Array(miniStreamDataLength);\n let miniStreamOffset = 0;\n for (const s of miniStreams) {\n miniStreamData.set(s.data, miniStreamOffset);\n miniStreamOffset += Math.ceil(s.data.length / MSS) * MSS;\n }\n\n // 정규 스트림 패딩 및 섹터 개수 계산\n const regularStreams = streams.filter((s) => !s.isMini);\n const regPads = regularStreams.map((s) => {\n const len = s.data.length;\n const n = Math.ceil(Math.max(len, 1) / SS) * SS;\n const out = new Uint8Array(n);\n out.set(s.data);\n return out;\n });\n const regNs = regPads.map((p) => p.length / SS);\n\n // 디렉토리 섹터 크기 결정 (엔트리 개수 비례)\n const numDirEntries = 5 + (binImages.length > 0 ? 1 + binImages.length : 0);\n const dirN = Math.max(1, Math.ceil((numDirEntries * 128) / SS));\n\n // Mini FAT 섹터 크기 결정 (1 섹터당 128개 FAT 엔트리 수용)\n const miniFatN = Math.ceil(miniSectorList.length / 128);\n\n // Mini Stream을 위한 정규 섹터 크기 결정\n const miniStreamN = Math.ceil(miniStreamData.length / SS);\n\n // 정규 FAT 섹터 수 (fatN) 계산 루프\n const totalRegStreamN = regNs.reduce((a, b) => a + b, 0);\n const neededDataSec = dirN + miniFatN + miniStreamN + totalRegStreamN;\n\n let fatN = 1;\n for (let iter = 0; iter < 10; iter++) {\n const totalSec = fatN + neededDataSec;\n const neededFat = Math.ceil(totalSec / 128);\n if (neededFat <= fatN) break;\n fatN = neededFat;\n }\n\n const totalSec = fatN + neededDataSec;\n\n // 각 정규 섹터 영역의 시작 위치 할당\n const dirStartSec = fatN;\n const miniFatStartSec = dirStartSec + dirN;\n const miniStreamStartSec = miniFatStartSec + miniFatN;\n\n let curSec = miniStreamStartSec + miniStreamN;\n for (let i = 0; i < regularStreams.length; i++) {\n regularStreams[i].startSec = curSec;\n curSec += regNs[i];\n }\n\n // 정규 FAT 버퍼 구성\n const fatBuf = new Uint8Array(fatN * SS).fill(0xff);\n const setFat = (i: number, v: number) => {\n const off = i * 4;\n fatBuf[off] = v & 0xff;\n fatBuf[off + 1] = (v >>> 8) & 0xff;\n fatBuf[off + 2] = (v >>> 16) & 0xff;\n fatBuf[off + 3] = (v >>> 24) & 0xff;\n };\n\n // FAT 섹터 자신 표시\n for (let i = 0; i < fatN; i++) {\n setFat(i, FATSECT);\n }\n\n // Directory 섹터 체인 연결\n for (let i = 0; i < dirN; i++) {\n setFat(\n dirStartSec + i,\n i + 1 < dirN ? dirStartSec + i + 1 : ENDOFCHAIN,\n );\n }\n\n // Mini FAT 섹터 체인 연결\n if (miniFatN > 0) {\n for (let i = 0; i < miniFatN; i++) {\n setFat(\n miniFatStartSec + i,\n i + 1 < miniFatN ? miniFatStartSec + i + 1 : ENDOFCHAIN,\n );\n }\n }\n\n // Mini Stream 섹터 체인 연결\n if (miniStreamN > 0) {\n for (let i = 0; i < miniStreamN; i++) {\n setFat(\n miniStreamStartSec + i,\n i + 1 < miniStreamN ? miniStreamStartSec + i + 1 : ENDOFCHAIN,\n );\n }\n }\n\n // 정규 스트림 섹터 체인 연결\n for (let i = 0; i < regularStreams.length; i++) {\n const s = regularStreams[i];\n const n = regNs[i];\n const start = s.startSec!;\n for (let j = 0; j < n; j++) {\n setFat(start + j, j + 1 < n ? start + j + 1 : ENDOFCHAIN);\n }\n }\n\n // Mini FAT 버퍼 생성\n const miniFatBuf = new Uint8Array(miniFatN * SS).fill(0xff);\n const setMiniFat = (i: number, v: number) => {\n const off = i * 4;\n miniFatBuf[off] = v & 0xff;\n miniFatBuf[off + 1] = (v >>> 8) & 0xff;\n miniFatBuf[off + 2] = (v >>> 16) & 0xff;\n miniFatBuf[off + 3] = (v >>> 24) & 0xff;\n };\n\n for (let i = 0; i < miniSectorList.length; i++) {\n setMiniFat(i, miniSectorList[i]);\n }\n\n // 디렉토리 버퍼 생성\n const dirBuf = new Uint8Array(dirN * SS);\n const dv = new DataView(dirBuf.buffer);\n\n function writeDirEntry(\n idx: number,\n name: string,\n type: number,\n left: number,\n right: number,\n child: number,\n startSec: number,\n size: number,\n ): void {\n const base = idx * 128;\n const nl = name.length;\n // OLE2: 이름은 UTF-16LE, (글자수+1)*2 바이트가 길이 필드에 기록됨\n for (let i = 0; i < nl; i++) {\n dv.setUint16(base + i * 2, name.charCodeAt(i), true);\n }\n dv.setUint16(base + 64, (nl + 1) * 2, true);\n dirBuf[base + 66] = type;\n dirBuf[base + 67] = 1; // DE_NODE (블랙 노드)\n dv.setInt32(base + 68, left, true);\n dv.setInt32(base + 72, right, true);\n dv.setInt32(base + 76, child, true);\n dv.setUint32(base + 116, startSec >>> 0, true);\n dv.setUint32(base + 120, size >>> 0, true);\n }\n\n // 모든 디렉토리 엔트리 -1 (NOSTREAM)으로 초기화\n for (let i = 0; i < dirN * 4; i++) {\n const base = i * 128;\n dv.setInt32(base + 68, -1, true);\n dv.setInt32(base + 72, -1, true);\n dv.setInt32(base + 76, -1, true);\n }\n\n // 스트림 인덱스 맵 생성\n const streamMap = new Map<number, OleStream>();\n for (const s of streams) {\n streamMap.set(s.dirIdx, s);\n }\n\n // Root Entry (0번): 미니 스트림의 루트 역할을 하며 미니 스트림 데이터를 가리킴\n writeDirEntry(\n 0,\n \"Root Entry\",\n 5,\n -1,\n -1,\n 3,\n miniStreamStartSec,\n miniStreamData.length,\n );\n\n // HWP Root Entry CLSID 설정\n const HWP_CLSID = [\n 0x20, 0xe9, 0xe3, 0xc0, 0x46, 0x35, 0xcf, 0x11, 0x8d, 0x81, 0x00, 0xaa,\n 0x00, 0x38, 0x9b, 0x71,\n ];\n for (let i = 0; i < 16; i++) {\n dirBuf[0 * 128 + 80 + i] = HWP_CLSID[i];\n }\n\n // FileHeader (1번)\n const fhStream = streamMap.get(1)!;\n writeDirEntry(\n 1,\n \"FileHeader\",\n 2,\n -1,\n -1,\n -1,\n fhStream.startSec!,\n fhStream.data.length,\n );\n\n // DocInfo (2번) - 이미지가 있는 경우 BinData(5번)를 left로 지정\n const diStream = streamMap.get(2)!;\n const docInfoLeft = binImages.length > 0 ? 5 : -1;\n writeDirEntry(\n 2,\n \"DocInfo\",\n 2,\n docInfoLeft,\n -1,\n -1,\n diStream.startSec!,\n diStream.data.length,\n );\n\n // BodyText (3번) - Root Entry 아래의 검색 허브 역할 (left: DocInfo(2), right: FileHeader(1), child: Section0(4))\n writeDirEntry(3, \"BodyText\", 1, 2, 1, 4, ENDOFCHAIN, 0);\n\n // Section0 (4번)\n const s0Stream = streamMap.get(4)!;\n writeDirEntry(\n 4,\n \"Section0\",\n 2,\n -1,\n -1,\n -1,\n s0Stream.startSec!,\n s0Stream.data.length,\n );\n\n // BinData (5번)\n if (binImages.length > 0) {\n writeDirEntry(5, \"BinData\", 1, -1, -1, 6, ENDOFCHAIN, 0);\n\n for (let i = 0; i < binImages.length; i++) {\n const imgStream = streamMap.get(6 + i)!;\n const sibling = i + 1 < binImages.length ? 7 + i : -1;\n writeDirEntry(\n 6 + i,\n imgStream.name,\n 2,\n -1,\n sibling,\n -1,\n imgStream.startSec!,\n imgStream.data.length,\n );\n }\n }\n\n // 헤더 생성 (512바이트)\n const hdr = new Uint8Array(SS);\n const hdv = new DataView(hdr.buffer);\n\n // OLE2 시그니처 (Magic)\n const MAGIC = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];\n MAGIC.forEach((b, i) => {\n hdr[i] = b;\n });\n\n hdv.setUint16(24, 0x003e, true); // Minor version\n hdv.setUint16(26, 0x0003, true); // Major version\n hdv.setUint16(28, 0xfffe, true); // Byte order (0xFFFE = 리틀 엔디안 BOM)\n hdv.setUint16(30, 0x0009, true); // Sector size exponent (2^9 = 512)\n hdv.setUint16(32, 0x0006, true); // Mini sector size exponent (2^6 = 64)\n\n hdv.setUint32(40, 0, true); // Number of Directory Sectors (Version 3에서는 0으로 채움)\n hdv.setUint32(44, fatN, true); // Number of FAT Sectors (0x002C)\n hdv.setUint32(48, dirStartSec, true); // Starting Sector of Directory Stream (0x0030)\n hdv.setUint32(52, 0, true); // Transaction Signature Number (0x0034)\n hdv.setUint32(56, 0x1000, true); // Mini Stream Cutoff Size (0x0038)\n hdv.setUint32(60, miniFatN > 0 ? miniFatStartSec : ENDOFCHAIN, true); // Starting Sector of Mini FAT (0x003C)\n hdv.setUint32(64, miniFatN, true); // Number of Mini FAT Sectors (0x0040)\n hdv.setUint32(68, ENDOFCHAIN, true); // Starting Sector of DIFAT (0x0044)\n hdv.setUint32(72, 0, true); // Number of DIFAT Sectors (0x0048)\n\n // Sector bitmap (DIFAT) 슬롯 채우기 (처음 109개 FAT 섹터 번호 지정)\n for (let i = 0; i < 109; i++) {\n hdv.setUint32(76 + i * 4, i < fatN ? i : FREESECT, true);\n }\n\n // 최종 바이트 어레이 조립 및 출력 생성\n const out = new Uint8Array(SS + totalSec * SS);\n let outOff = 0;\n\n // 1. Header (Sector -1)\n out.set(hdr, outOff);\n outOff += SS;\n\n // 2. FAT sectors\n out.set(fatBuf, outOff);\n outOff += fatN * SS;\n\n // 3. Directory sectors\n out.set(dirBuf, outOff);\n outOff += dirN * SS;\n\n // 4. Mini FAT sectors\n if (miniFatN > 0) {\n out.set(miniFatBuf, outOff);\n outOff += miniFatN * SS;\n }\n\n // 5. Mini Stream sectors (Root Entry Data)\n if (miniStreamN > 0) {\n const miniStreamPad = new Uint8Array(miniStreamN * SS);\n miniStreamPad.set(miniStreamData);\n out.set(miniStreamPad, outOff);\n outOff += miniStreamN * SS;\n }\n\n // 6. Regular Streams sectors\n for (let i = 0; i < regularStreams.length; i++) {\n out.set(regPads[i], outOff);\n outOff += regNs[i] * SS;\n }\n\n return out;\n}\n\n// ─── 유틸리티 ────────────────────────────────────────────────\n\nfunction concatU8(arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((s, a) => s + a.length, 0);\n const out = new Uint8Array(total);\n let off = 0;\n for (const a of arrays) {\n out.set(a, off);\n off += a.length;\n }\n return out;\n}\n\n// ─── OLE2 검증 ──────────────────────────────────────────────\n\nfunction validateOle2Magic(hwp: Uint8Array): boolean {\n const OLE_MAGIC = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];\n return OLE_MAGIC.every((b, i) => hwp[i] === b);\n}\n\n// ─── Encoder 진입점 ──────────────────────────────────────────\n\nexport class HwpEncoder extends BaseEncoder {\n protected getFormat(): string {\n return \"hwp\";\n }\n protected getAliases(): string[] {\n return [\"application/vnd.hancom.hwp\"];\n }\n\n async encode(doc: DocRoot): Promise<Outcome<Uint8Array>> {\n try {\n // 패스 1: 스타일 수집 (HwpStyleBank — ANYTOHWP 방식 언어별 폰트)\n const bank = new HwpStyleBank();\n for (const sheet of doc.kids) {\n for (const node of sheet.kids) collectNode(node, bank);\n }\n\n // 이미지 수집 (ANYTOHWP 개선: 픽셀 치수는 encodePicPara에서 추출)\n const images: BinImage[] = [];\n const seenB64 = new Set<string>();\n let binIdCounter = 1;\n\n function registerImg(img: any): void {\n const key = img.b64.substring(0, 50);\n if (seenB64.has(key)) return;\n seenB64.add(key);\n const raw = TextKit.base64Decode(img.b64);\n const ext =\n img.mime === \"image/png\"\n ? \"png\"\n : img.mime === \"image/gif\"\n ? \"gif\"\n : img.mime === \"image/bmp\"\n ? \"bmp\"\n : \"jpg\";\n images.push({ id: binIdCounter++, ext, data: new Uint8Array(raw) });\n }\n\n function collectImages(node: any): void {\n if (node.tag === \"para\") {\n for (const img of flatImgNodes(node.kids)) registerImg(img);\n } else if (node.tag === \"grid\") {\n for (const row of node.kids)\n for (const cell of row.kids)\n for (const para of cell.kids) collectImages(para);\n }\n }\n for (const sheet of doc.kids) {\n for (const node of sheet.kids) collectImages(node);\n }\n\n // 패스 2: 스트림 빌드\n const docInfoRaw = buildDocInfoStream(bank, images);\n const bodyRaw = buildBodyTextStream(doc, bank, images);\n\n // HWP 5.0: Zlib 헤더 없는 Raw Deflate\n const docInfoCmp = pako.deflateRaw(docInfoRaw);\n const bodyCmp = pako.deflateRaw(bodyRaw);\n\n const fileHdr = buildHwpFileHeader();\n\n // FileHeader 검증\n if (fileHdr.length !== 256) {\n return fail(\n `HwpEncoder: FileHeader 크기 오류 - ${fileHdr.length} bytes (기대: 256 bytes)`,\n );\n }\n\n const hwp = buildHwpOle2(fileHdr, docInfoCmp, bodyCmp, images);\n\n if (!validateOle2Magic(hwp)) {\n return fail(\"HwpEncoder: OLE2 매직 바이트 오류\");\n }\n\n // HWP 파일 크기 검증 (최소 512 바이트 - OLE2 헤더 1 섹터)\n if (hwp.length < 512) {\n return fail(\n `HwpEncoder: HWP 파일 크기 부족 - ${hwp.length} bytes (최소 512 bytes)`,\n );\n }\n\n return succeed(hwp);\n } catch (e: any) {\n return fail(`HwpEncoder: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n}\n\nregistry.registerEncoder(new HwpEncoder());\n","import type { DocRoot } from '../model/doc-tree';\nimport type { Outcome } from '../contract/result';\nimport type { EncoderOptions } from '../contract/encoder';\nimport { succeed, fail } from '../contract/result';\nimport { registry } from './registry';\n\n// Side-effect imports: auto-register all decoders and encoders\nimport '../decoders/hwpx/HwpxDecoder';\nimport '../decoders/hwp/HwpScanner';\nimport '../decoders/docx/DocxDecoder';\nimport '../decoders/md/MdDecoder';\nimport '../decoders/html/HtmlDecoder';\nimport '../encoders/hwpx/HwpxEncoder';\nimport '../encoders/docx/DocxEncoder';\nimport '../encoders/md/MdEncoder';\nimport '../encoders/html/HtmlEncoder';\nimport '../encoders/hwp/HwpEncoder';\n\nexport class Pipeline {\n private constructor(private raw: Uint8Array, private srcFmt: string) {}\n\n /** 파일을 열고 포맷을 자동 감지하거나 명시 */\n static open(input: Uint8Array | string, fmt?: string): Pipeline {\n if (typeof input === 'string') {\n return new Pipeline(new TextEncoder().encode(input), fmt ?? 'md');\n }\n return new Pipeline(input, fmt ?? detectFormat(input));\n }\n\n /** File/Blob 비동기 입력 */\n static async openAsync(input: File | Blob | Uint8Array | string, fmt?: string): Promise<Pipeline> {\n if (input instanceof Uint8Array || typeof input === 'string') {\n return Pipeline.open(input, fmt);\n }\n const buf = await input.arrayBuffer();\n const data = new Uint8Array(buf);\n const detectedFmt = fmt ?? (input instanceof File ? getExt(input.name) : undefined) ?? detectFormat(data);\n return new Pipeline(data, detectedFmt);\n }\n\n /** 목표 포맷으로 변환 */\n async to(targetFmt: string, options?: EncoderOptions): Promise<Outcome<Uint8Array>> {\n const decoder = registry.getDecoder(this.srcFmt);\n const encoder = registry.getEncoder(targetFmt);\n\n if (!decoder) return fail(`지원하지 않는 입력 포맷: ${this.srcFmt}`);\n if (!encoder) return fail(`지원하지 않는 출력 포맷: ${targetFmt}`);\n\n const docResult = await decoder.decode(this.raw);\n if (!docResult.ok) return docResult;\n\n const encResult = await encoder.encode(docResult.data, options);\n if (!encResult.ok) return { ...encResult, warns: [...docResult.warns, ...encResult.warns] };\n\n return { ...encResult, warns: [...docResult.warns, ...encResult.warns] };\n }\n\n /** DocRoot만 추출 (인코딩 없이) */\n async inspect(): Promise<Outcome<DocRoot>> {\n const decoder = registry.getDecoder(this.srcFmt);\n if (!decoder) return fail(`디코더 없음: ${this.srcFmt}`);\n return decoder.decode(this.raw);\n }\n}\n\nfunction detectFormat(data: Uint8Array): string {\n // HWP 파일 (OLE Compound Document)\n if (data[0] === 0xD0 && data[1] === 0xCF && data[2] === 0x11 && data[3] === 0xE0) return 'hwp';\n\n // ZIP 기반 파일 (DOCX, HWPX)\n if (data[0] === 0x50 && data[1] === 0x4B) {\n // DOCX 는 [Content_Types].xml 에 application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml 이 있음\n // HWPX 는 application/ha-xml-core-document\n const str = new TextDecoder('utf-8', { fatal: false }).decode(data.slice(0, 4096));\n if (str.includes('wordprocessingml')) return 'docx';\n if (str.includes('ha-xml')) return 'hwpx';\n if (str.includes('hwpml/')) return 'hwpx';\n if (str.includes('word/')) return 'docx';\n return 'hwpx'; // 기본값\n }\n\n return 'md';\n}\n\nfunction getExt(name: string): string | undefined {\n const parts = name.split('.');\n return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : undefined;\n}\n","import type { AnyNode, DocRoot } from '../model/doc-tree';\n\nexport type WalkCallback = (node: AnyNode, parent: AnyNode | null, depth: number) => void | 'stop';\n\nexport function walkNode(\n node: AnyNode,\n cb: WalkCallback,\n parent: AnyNode | null = null,\n depth = 0,\n): boolean {\n const result = cb(node, parent, depth);\n if (result === 'stop') return false;\n\n if ('kids' in node && Array.isArray((node as any).kids)) {\n for (const kid of (node as any).kids) {\n if (!walkNode(kid as AnyNode, cb, node, depth + 1)) return false;\n }\n }\n return true;\n}\n\nexport class TreeWalker {\n walk(root: DocRoot, cb: WalkCallback): void {\n walkNode(root, cb);\n }\n\n findAll<T extends AnyNode>(root: DocRoot, predicate: (n: AnyNode) => n is T): T[] {\n const results: T[] = [];\n walkNode(root, (n) => { if (predicate(n)) results.push(n); });\n return results;\n }\n\n extractText(root: DocRoot): string {\n const parts: string[] = [];\n walkNode(root, (n) => {\n if (n.tag === 'txt') parts.push(n.content);\n if (n.tag === 'br') parts.push('\\n');\n if (n.tag === 'pb') parts.push('\\n\\n');\n });\n return parts.join('');\n }\n}\n","import type { DocRoot, GridNode } from '../model/doc-tree';\nimport { walkNode } from './TreeWalker';\n\nexport function countNodes(root: DocRoot): Record<string, number> {\n const counts: Record<string, number> = {};\n walkNode(root, (n) => { counts[n.tag] = (counts[n.tag] ?? 0) + 1; });\n return counts;\n}\n\nexport function validateRoot(root: DocRoot): string[] {\n const errors: string[] = [];\n if (root.tag !== 'root') errors.push('Root node must have tag \"root\"');\n if (!Array.isArray(root.kids)) errors.push('Root.kids must be an array');\n if (root.kids.length === 0) errors.push('Document has no sheets');\n\n walkNode(root, (n) => {\n if (n.tag === 'cell' && n.kids.length === 0) {\n errors.push('CellNode must have at least one ParaNode child');\n }\n if (n.tag === 'grid' && (n as GridNode).kids.length === 0) {\n errors.push('GridNode must have at least one RowNode');\n }\n });\n\n return errors;\n}\n"],"mappings":"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","names":["pako","import_pako","pako","i","r","data","coreXml","stylesXml","extractDims","decodeHeaderFooter","toArr","decodePara","decodeGrid","decodeGridSimple","decodeGridFlat","decodeGridText","cellText","tableText","end","t","paraKids","ALIGN_MAP","stylesXml","mimeToExt","registerImage","esc","encodeImage","encodeContent","encodeGrid","encodeImage","encodePara","encodeContent","encodeGrid","encodeSpan","encodeImage","import_pako","TAG_FACE_NAME","TAG_BORDER_FILL","TAG_CHAR_SHAPE","TAG_PARA_SHAPE","TAG_PARA_HEADER","TAG_PARA_TEXT","TAG_PARA_CHAR_SHAPE","TAG_CTRL_HEADER","TAG_LIST_HEADER","TAG_PAGE_DEF","CTRL_TABLE","BORDER_W_PT","readPixelDims","LANG_GROUPS","encodePara","encodeGrid","curSec","out","totalSec","registerImg","collectImages","pako"]}