kordoc 2.7.1 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -315,10 +315,36 @@ declare function fillHwpx(hwpxBuffer: ArrayBuffer, values: Record<string, string
315
315
  * 순서/비순서 리스트, 수평선, 인용문, 테이블
316
316
  * jszip으로 HWPX ZIP 패키징.
317
317
  */
318
+ /** HWPX 생성 시 적용할 시각 테마 (모두 선택) */
319
+ interface HwpxTheme {
320
+ /**
321
+ * 헤딩 레벨별 텍스트 색상. 미지정 시 검정.
322
+ * 현재 charPr 매핑은 h1/h2/h3/h4 4단계 (h5, h6은 h4와 같은 charPr 공유)이므로
323
+ * 키는 1~4만 받는다.
324
+ */
325
+ headingColors?: Partial<Record<1 | 2 | 3 | 4, string>>;
326
+ /** 본문 단락 텍스트 색상. 미지정 시 검정 */
327
+ bodyColor?: string;
328
+ /**
329
+ * 인용문 텍스트 색상. 미지정 시 검정.
330
+ *
331
+ * 주의: 이 옵션을 지정하면 인용문이 별도 charPr(이탤릭)로 렌더링된다.
332
+ * 미지정 시 기존 동작 그대로 본문 charPr로 렌더링 (이탤릭 아님).
333
+ */
334
+ quoteColor?: string;
335
+ /** 표 첫 행 텍스트 색상. 미지정 시 본문과 동일 */
336
+ tableHeaderColor?: string;
337
+ /** 표 첫 행 텍스트를 굵게 표시 (기본 false) */
338
+ tableHeaderBold?: boolean;
339
+ }
340
+ /** markdownToHwpx 옵션 */
341
+ interface MarkdownToHwpxOptions {
342
+ theme?: HwpxTheme;
343
+ }
318
344
  /**
319
345
  * 마크다운 텍스트를 HWPX (ArrayBuffer)로 변환.
320
346
  */
321
- declare function markdownToHwpx(markdown: string): Promise<ArrayBuffer>;
347
+ declare function markdownToHwpx(markdown: string, options?: MarkdownToHwpxOptions): Promise<ArrayBuffer>;
322
348
 
323
349
  /**
324
350
  * Print Renderer — Markdown / IRBlock[] → PDF (puppeteer-core 기반).
@@ -465,4 +491,4 @@ interface FillFormOutput {
465
491
  */
466
492
  declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, string>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
467
493
 
468
- export { type BlockDiff, type BoundingBox, type CellContext, type CellDiff, type DiffChangeType, type DiffResult, type DocumentMetadata, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillOutputFormat, type FillResult, type FormField, type FormResult, type HwpxFillResult, type IRBlock, type IRBlockType, type IRCell, type IRTable, type ImageData, type InlineStyle, type OcrProvider, type OutlineItem, type PageMargin, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PrintOptions, type PrintPreset, VERSION, type WarningCode, type WatchOptions, blocksToMarkdown, blocksToPdf, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, extractFormFields, fillForm, fillFormFields, fillHwpx, isHwpxFile, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, markdownToHwpx, markdownToPdf, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parsePdf, parseXls, parseXlsx, renderHtml };
494
+ export { type BlockDiff, type BoundingBox, type CellContext, type CellDiff, type DiffChangeType, type DiffResult, type DocumentMetadata, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillOutputFormat, type FillResult, type FormField, type FormResult, type HwpxFillResult, type HwpxTheme, type IRBlock, type IRBlockType, type IRCell, type IRTable, type ImageData, type InlineStyle, type MarkdownToHwpxOptions, type OcrProvider, type OutlineItem, type PageMargin, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PrintOptions, type PrintPreset, VERSION, type WarningCode, type WatchOptions, blocksToMarkdown, blocksToPdf, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, extractFormFields, fillForm, fillFormFields, fillHwpx, isHwpxFile, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, markdownToHwpx, markdownToPdf, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parsePdf, parseXls, parseXlsx, renderHtml };
package/dist/index.d.ts CHANGED
@@ -315,10 +315,36 @@ declare function fillHwpx(hwpxBuffer: ArrayBuffer, values: Record<string, string
315
315
  * 순서/비순서 리스트, 수평선, 인용문, 테이블
316
316
  * jszip으로 HWPX ZIP 패키징.
317
317
  */
318
+ /** HWPX 생성 시 적용할 시각 테마 (모두 선택) */
319
+ interface HwpxTheme {
320
+ /**
321
+ * 헤딩 레벨별 텍스트 색상. 미지정 시 검정.
322
+ * 현재 charPr 매핑은 h1/h2/h3/h4 4단계 (h5, h6은 h4와 같은 charPr 공유)이므로
323
+ * 키는 1~4만 받는다.
324
+ */
325
+ headingColors?: Partial<Record<1 | 2 | 3 | 4, string>>;
326
+ /** 본문 단락 텍스트 색상. 미지정 시 검정 */
327
+ bodyColor?: string;
328
+ /**
329
+ * 인용문 텍스트 색상. 미지정 시 검정.
330
+ *
331
+ * 주의: 이 옵션을 지정하면 인용문이 별도 charPr(이탤릭)로 렌더링된다.
332
+ * 미지정 시 기존 동작 그대로 본문 charPr로 렌더링 (이탤릭 아님).
333
+ */
334
+ quoteColor?: string;
335
+ /** 표 첫 행 텍스트 색상. 미지정 시 본문과 동일 */
336
+ tableHeaderColor?: string;
337
+ /** 표 첫 행 텍스트를 굵게 표시 (기본 false) */
338
+ tableHeaderBold?: boolean;
339
+ }
340
+ /** markdownToHwpx 옵션 */
341
+ interface MarkdownToHwpxOptions {
342
+ theme?: HwpxTheme;
343
+ }
318
344
  /**
319
345
  * 마크다운 텍스트를 HWPX (ArrayBuffer)로 변환.
320
346
  */
321
- declare function markdownToHwpx(markdown: string): Promise<ArrayBuffer>;
347
+ declare function markdownToHwpx(markdown: string, options?: MarkdownToHwpxOptions): Promise<ArrayBuffer>;
322
348
 
323
349
  /**
324
350
  * Print Renderer — Markdown / IRBlock[] → PDF (puppeteer-core 기반).
@@ -465,4 +491,4 @@ interface FillFormOutput {
465
491
  */
466
492
  declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, string>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
467
493
 
468
- export { type BlockDiff, type BoundingBox, type CellContext, type CellDiff, type DiffChangeType, type DiffResult, type DocumentMetadata, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillOutputFormat, type FillResult, type FormField, type FormResult, type HwpxFillResult, type IRBlock, type IRBlockType, type IRCell, type IRTable, type ImageData, type InlineStyle, type OcrProvider, type OutlineItem, type PageMargin, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PrintOptions, type PrintPreset, VERSION, type WarningCode, type WatchOptions, blocksToMarkdown, blocksToPdf, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, extractFormFields, fillForm, fillFormFields, fillHwpx, isHwpxFile, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, markdownToHwpx, markdownToPdf, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parsePdf, parseXls, parseXlsx, renderHtml };
494
+ export { type BlockDiff, type BoundingBox, type CellContext, type CellDiff, type DiffChangeType, type DiffResult, type DocumentMetadata, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillOutputFormat, type FillResult, type FormField, type FormResult, type HwpxFillResult, type HwpxTheme, type IRBlock, type IRBlockType, type IRCell, type IRTable, type ImageData, type InlineStyle, type MarkdownToHwpxOptions, type OcrProvider, type OutlineItem, type PageMargin, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PrintOptions, type PrintPreset, VERSION, type WarningCode, type WatchOptions, blocksToMarkdown, blocksToPdf, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, extractFormFields, fillForm, fillFormFields, fillHwpx, isHwpxFile, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, markdownToHwpx, markdownToPdf, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parsePdf, parseXls, parseXlsx, renderHtml };
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  sanitizeHref,
17
17
  stripDtd,
18
18
  toArrayBuffer
19
- } from "./chunk-GNN6MHH4.js";
19
+ } from "./chunk-DLQY6FJH.js";
20
20
  import {
21
21
  parsePageRange
22
22
  } from "./chunk-SBVRCJFH.js";
@@ -18298,7 +18298,15 @@ function setRunText(runEl, text) {
18298
18298
  for (let i = 1; i < tElements.length; i++) {
18299
18299
  clearChildren(tElements[i]);
18300
18300
  }
18301
+ return;
18301
18302
  }
18303
+ if (!text) return;
18304
+ const doc = runEl.ownerDocument;
18305
+ const ns = runEl.namespaceURI;
18306
+ const qualifiedName = runEl.prefix ? `${runEl.prefix}:t` : "t";
18307
+ const tEl = ns ? doc.createElementNS(ns, qualifiedName) : doc.createElement(qualifiedName);
18308
+ tEl.appendChild(doc.createTextNode(text));
18309
+ runEl.appendChild(tEl);
18302
18310
  }
18303
18311
  function clearChildren(el) {
18304
18312
  while (el.firstChild) el.removeChild(el.firstChild);
@@ -18389,6 +18397,8 @@ var CHAR_H1 = 5;
18389
18397
  var CHAR_H2 = 6;
18390
18398
  var CHAR_H3 = 7;
18391
18399
  var CHAR_H4 = 8;
18400
+ var CHAR_TABLE_HEADER = 9;
18401
+ var CHAR_QUOTE = 10;
18392
18402
  var PARA_NORMAL = 0;
18393
18403
  var PARA_H1 = 1;
18394
18404
  var PARA_H2 = 2;
@@ -18397,14 +18407,30 @@ var PARA_H4 = 4;
18397
18407
  var PARA_CODE = 5;
18398
18408
  var PARA_QUOTE = 6;
18399
18409
  var PARA_LIST = 7;
18400
- async function markdownToHwpx(markdown) {
18410
+ var DEFAULT_TEXT_COLOR = "#000000";
18411
+ function resolveTheme(theme) {
18412
+ return {
18413
+ h1: theme?.headingColors?.[1] ?? DEFAULT_TEXT_COLOR,
18414
+ h2: theme?.headingColors?.[2] ?? DEFAULT_TEXT_COLOR,
18415
+ h3: theme?.headingColors?.[3] ?? DEFAULT_TEXT_COLOR,
18416
+ h4: theme?.headingColors?.[4] ?? theme?.headingColors?.[3] ?? DEFAULT_TEXT_COLOR,
18417
+ body: theme?.bodyColor ?? DEFAULT_TEXT_COLOR,
18418
+ quote: theme?.quoteColor ?? DEFAULT_TEXT_COLOR,
18419
+ /** quoteColor가 명시되었는지 — blockquote charPr 분기에 사용 (baseline 호환) */
18420
+ hasQuoteOption: theme?.quoteColor !== void 0,
18421
+ tableHeader: theme?.tableHeaderColor ?? theme?.bodyColor ?? DEFAULT_TEXT_COLOR,
18422
+ tableHeaderBold: !!theme?.tableHeaderBold
18423
+ };
18424
+ }
18425
+ async function markdownToHwpx(markdown, options) {
18426
+ const theme = resolveTheme(options?.theme);
18401
18427
  const blocks = parseMarkdownToBlocks(markdown);
18402
- const sectionXml = blocksToSectionXml(blocks);
18428
+ const sectionXml = blocksToSectionXml(blocks, theme);
18403
18429
  const zip = new JSZip6();
18404
18430
  zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
18405
18431
  zip.file("META-INF/container.xml", generateContainerXml());
18406
18432
  zip.file("Contents/content.hpf", generateManifest());
18407
- zip.file("Contents/header.xml", generateHeaderXml());
18433
+ zip.file("Contents/header.xml", generateHeaderXml(theme));
18408
18434
  zip.file("Contents/section0.xml", sectionXml);
18409
18435
  zip.file("Preview/PrvText.txt", buildPrvText(blocks));
18410
18436
  return await zip.generateAsync({ type: "arraybuffer" });
@@ -18584,11 +18610,11 @@ function generateManifest() {
18584
18610
  </opf:spine>
18585
18611
  </opf:package>`;
18586
18612
  }
18587
- function charPr(id, height, bold, italic, fontId = 0) {
18613
+ function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR) {
18588
18614
  const boldAttr = bold ? ` bold="1"` : "";
18589
18615
  const italicAttr = italic ? ` italic="1"` : "";
18590
18616
  const effFont = bold ? 2 : fontId;
18591
- return ` <hh:charPr id="${id}" height="${height}" textColor="#000000" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="0"${boldAttr}${italicAttr}>
18617
+ return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="0"${boldAttr}${italicAttr}>
18592
18618
  <hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
18593
18619
  <hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
18594
18620
  <hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
@@ -18608,7 +18634,7 @@ function paraPr(id, opts = {}) {
18608
18634
  <hh:border borderFillIDRef="0" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0"/>
18609
18635
  </hh:paraPr>`;
18610
18636
  }
18611
- function generateHeaderXml() {
18637
+ function generateHeaderXml(theme) {
18612
18638
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
18613
18639
  <hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" version="1.4" secCnt="1">
18614
18640
  <hh:beginNum page="1" footnote="1" endnote="1" pic="1" tbl="1" equation="1"/>
@@ -18684,16 +18710,18 @@ function generateHeaderXml() {
18684
18710
  <hh:fillInfo/>
18685
18711
  </hh:borderFill>
18686
18712
  </hh:borderFills>
18687
- <hh:charProperties itemCnt="9">
18688
- ${charPr(0, 1e3, false, false)}
18689
- ${charPr(1, 1e3, true, false)}
18690
- ${charPr(2, 1e3, false, true)}
18691
- ${charPr(3, 1e3, true, true)}
18713
+ <hh:charProperties itemCnt="11">
18714
+ ${charPr(0, 1e3, false, false, 0, theme.body)}
18715
+ ${charPr(1, 1e3, true, false, 0, theme.body)}
18716
+ ${charPr(2, 1e3, false, true, 0, theme.body)}
18717
+ ${charPr(3, 1e3, true, true, 0, theme.body)}
18692
18718
  ${charPr(4, 900, false, false, 1)}
18693
- ${charPr(5, 1800, true, false, 1)}
18694
- ${charPr(6, 1400, true, false, 1)}
18695
- ${charPr(7, 1200, true, false, 1)}
18696
- ${charPr(8, 1100, true, false, 1)}
18719
+ ${charPr(5, 1800, true, false, 1, theme.h1)}
18720
+ ${charPr(6, 1400, true, false, 1, theme.h2)}
18721
+ ${charPr(7, 1200, true, false, 1, theme.h3)}
18722
+ ${charPr(8, 1100, true, false, 1, theme.h4)}
18723
+ ${charPr(CHAR_TABLE_HEADER, 1e3, theme.tableHeaderBold, false, 0, theme.tableHeader)}
18724
+ ${charPr(CHAR_QUOTE, 1e3, false, true, 0, theme.quote)}
18697
18725
  </hh:charProperties>
18698
18726
  <hh:tabProperties itemCnt="0"/>
18699
18727
  <hh:numberings itemCnt="0"/>
@@ -18723,7 +18751,7 @@ var tableIdCounter = TABLE_ID_BASE;
18723
18751
  function nextTableId() {
18724
18752
  return ++tableIdCounter;
18725
18753
  }
18726
- function generateTable(rows) {
18754
+ function generateTable(rows, theme) {
18727
18755
  const rowCnt = rows.length;
18728
18756
  const colCnt = Math.max(...rows.map((r) => r.length), 1);
18729
18757
  const cellW = Math.floor(44e3 / colCnt);
@@ -18731,12 +18759,15 @@ function generateTable(rows) {
18731
18759
  const tblW = cellW * colCnt;
18732
18760
  const tblH = cellH * rowCnt;
18733
18761
  const tblId = nextTableId();
18762
+ const useHeaderStyle = theme.tableHeader !== theme.body || theme.tableHeaderBold;
18734
18763
  const trElements = rows.map((row, rowIdx) => {
18735
18764
  const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
18765
+ const isHeaderRow = rowIdx === 0;
18766
+ const headerCharPr = isHeaderRow && useHeaderStyle ? CHAR_TABLE_HEADER : CHAR_NORMAL;
18736
18767
  const tdElements = cells.map((cell, colIdx) => {
18737
- const runs = generateRuns(cell);
18768
+ const runs = generateRuns(cell, headerCharPr);
18738
18769
  const p = `<hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p>`;
18739
- return `<hp:tc name="" header="${rowIdx === 0 ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="1"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${p}</hp:subList><hp:cellAddr colAddr="${colIdx}" rowAddr="${rowIdx}"/><hp:cellSpan colSpan="1" rowSpan="1"/><hp:cellSz width="${cellW}" height="${cellH}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
18770
+ return `<hp:tc name="" header="${isHeaderRow ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="1"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${p}</hp:subList><hp:cellAddr colAddr="${colIdx}" rowAddr="${rowIdx}"/><hp:cellSpan colSpan="1" rowSpan="1"/><hp:cellSz width="${cellW}" height="${cellH}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
18740
18771
  }).join("");
18741
18772
  return `<hp:tr>${tdElements}</hp:tr>`;
18742
18773
  }).join("");
@@ -18744,7 +18775,7 @@ function generateTable(rows) {
18744
18775
  const tbl = `<hp:tbl id="${tblId}" zOrder="0" numberingType="TABLE" pageBreak="CELL" repeatHeader="0" rowCnt="${rowCnt}" colCnt="${colCnt}" cellSpacing="0" borderFillIDRef="1" noShading="0">${tblInner}</hp:tbl>`;
18745
18776
  return `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${tbl}</hp:run></hp:p>`;
18746
18777
  }
18747
- function blocksToSectionXml(blocks) {
18778
+ function blocksToSectionXml(blocks, theme) {
18748
18779
  const paraXmls = [];
18749
18780
  let isFirst = true;
18750
18781
  const orderedCounters = {};
@@ -18773,7 +18804,11 @@ function blocksToSectionXml(blocks) {
18773
18804
  break;
18774
18805
  }
18775
18806
  case "blockquote":
18776
- xml = generateParagraph(block.text || "", PARA_QUOTE);
18807
+ xml = generateParagraph(
18808
+ block.text || "",
18809
+ PARA_QUOTE,
18810
+ theme.hasQuoteOption ? CHAR_QUOTE : CHAR_NORMAL
18811
+ );
18777
18812
  break;
18778
18813
  case "list_item": {
18779
18814
  const indent = block.indent || 0;
@@ -18806,7 +18841,7 @@ function blocksToSectionXml(blocks) {
18806
18841
  paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
18807
18842
  isFirst = false;
18808
18843
  }
18809
- xml = generateTable(block.rows);
18844
+ xml = generateTable(block.rows, theme);
18810
18845
  }
18811
18846
  break;
18812
18847
  }
@@ -19246,7 +19281,7 @@ async function parseHwp(buffer, options) {
19246
19281
  async function parsePdf(buffer, options) {
19247
19282
  let parsePdfDocument;
19248
19283
  try {
19249
- const mod = await import("./parser-6L6DZCOB.js");
19284
+ const mod = await import("./parser-ZQQM6J7T.js");
19250
19285
  parsePdfDocument = mod.parsePdfDocument;
19251
19286
  } catch {
19252
19287
  return {