npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ssabrojs/hwpxjs

v0.2.0

Published

HWPX(OWPML) 문서 파싱 및 HWP 변환을 위한 TypeScript 라이브러리 - 텍스트/HTML 추출, 이미지/스타일 지원

Readme

hwpxjs

HWPX(OWPML) 문서 파싱과 텍스트/메타데이터 추출을 위한 TypeScript 라이브러리. HWP 파일 변환 기능도 지원합니다.

주요 기능

  • HWPX 파싱: ZIP+XML 파싱, 섹션/문단 텍스트 추출, HTML 변환
  • HWP 변환: HWP 파일을 HWPX로 변환 (순수 TypeScript 구현)
  • 스타일 지원: 표/이미지/스타일(굵게/기울임/밑줄/색상/크기) 처리
  • 템플릿 처리: 템플릿 치환({{key}}) 및 폴더 일괄 변환
  • 문서 생성: 평문 텍스트 → .hwpx 생성
  • 브라우저 지원: 드래그&드롭 뷰어 제공

설치

의존성 설치 전, 먼저 승인해 주세요.

pnpm add @ssabrojs/hwpxjs

라이브러리 사용법

기본 HWPX 파일 처리

import HwpxReader from "@ssabrojs/hwpxjs";

// 파일에서 HWPX 읽기
const reader = new HwpxReader();
await reader.loadFromFile("./document.hwpx");

// 또는 ArrayBuffer에서 읽기
const buffer = await fetch("/document.hwpx").then(r => r.arrayBuffer());
await reader.loadFromArrayBuffer(buffer);

// 문서 정보 확인
const info = await reader.getDocumentInfo();
console.log(info);
// {
//   title: "문서 제목",
//   creator: "작성자",
//   subject: "주제",
//   description: "설명",
//   publisher: "발행처",
//   contributor: "기여자",
//   date: "2024-01-01",
//   type: "문서",
//   format: "application/hwpx",
//   identifier: "document-id",
//   source: "출처",
//   language: "ko",
//   relation: "관련",
//   coverage: "범위",
//   rights: "권한"
// }

// 텍스트 추출
const text = await reader.extractText();
console.log(text); // "문서의 모든 텍스트 내용..."

// 이미지 목록 확인
const images = await reader.listImages();
console.log(images);
// [
//   { binPath: "BinData/0.jpg", width: 200, height: 150, format: "jpg" },
//   { binPath: "BinData/1.png", width: 300, height: 200, format: "png" }
// ]

HTML 변환 (고급 옵션)

// 기본 HTML 변환
const basicHtml = await reader.extractHtml();

// 모든 옵션을 포함한 HTML 변환
const fullHtml = await reader.extractHtml({
  // 문단 태그 설정
  paragraphTag: "p",

  // 테이블 CSS 클래스
  tableClassName: "hwpx-table",

  // 렌더링 옵션
  renderImages: true,       // 이미지 포함
  renderTables: true,       // 테이블 포함
  renderStyles: true,       // 스타일 적용 (굵게, 기울임, 색상 등)

  // 이미지 처리
  embedImages: true,        // Base64로 이미지 임베드
  imageSrcResolver: (binPath) => {
    // 커스텀 이미지 경로 생성
    return `/static/images/${binPath.replace('BinData/', '')}`;
  },

  // 테이블 헤더 처리
  tableHeaderFirstRow: true // 첫 번째 행을 <th>로 처리
});

console.log(fullHtml);
// <!DOCTYPE html>
// <html><head><style>.hwpx-table { border-collapse: collapse; }</style></head>
// <body><p>문서 내용...</p><img src="data:image/jpeg;base64,..." /></body></html>

HWP 파일 변환 (순수 TypeScript)

import { HwpConverter } from "@ssabrojs/hwpxjs";

// 변환기 초기화
const converter = new HwpConverter({
  verbose: true  // 변환 과정 로그 출력
});

// HWP 변환 가능 여부 확인
if (converter.isAvailable()) {
  console.log("HWP 변환 기능 사용 가능");
}

// HWP → HWPX 변환
const result = await converter.convertHwpToHwpx("input.hwp", "output.hwpx");
if (result.success) {
  console.log(`변환 성공: ${result.inputPath} → ${result.outputPath}`);
  console.log(`처리 시간: ${result.processingTime}ms`);
} else {
  console.error(`변환 실패: ${result.error}`);
}

// HWP에서 텍스트만 추출
try {
  const hwpText = await converter.convertHwpToText("input.hwp");
  console.log("HWP 텍스트 내용:", hwpText);
} catch (error) {
  console.error("HWP 텍스트 추출 실패:", error.message);
}

문서 생성 (HwpxWriter)

import { HwpxWriter } from "@ssabrojs/hwpxjs";

// 평문 텍스트로 HWPX 생성
const writer = new HwpxWriter();
const textContent = `첫 번째 문단입니다.

두 번째 문단입니다.
여러 줄로 구성된 내용도 가능합니다.`;

await writer.createFromText(textContent, "output.hwpx");
console.log("HWPX 파일이 생성되었습니다.");

오류 처리 및 예외 상황

import HwpxReader, { HwpxError, HwpConverter } from "@ssabrojs/hwpxjs";

try {
  const reader = new HwpxReader();
  await reader.loadFromFile("document.hwpx");

  const text = await reader.extractText();
  console.log(text);

} catch (error) {
  if (error instanceof HwpxError) {
    switch (error.code) {
      case 'FILE_NOT_FOUND':
        console.error("파일을 찾을 수 없습니다:", error.message);
        break;
      case 'INVALID_FORMAT':
        console.error("유효하지 않은 HWPX 형식입니다:", error.message);
        break;
      case 'PARSING_ERROR':
        console.error("파싱 중 오류가 발생했습니다:", error.message);
        break;
      default:
        console.error("알 수 없는 오류:", error.message);
    }
  } else {
    console.error("시스템 오류:", error.message);
  }
}

// HWP 변환 오류 처리
const converter = new HwpConverter();
const result = await converter.convertHwpToHwpx("input.hwp", "output.hwpx");

if (!result.success) {
  console.error(`변환 실패: ${result.error}`);
  console.error(`입력 파일: ${result.inputPath}`);
  console.error(`출력 파일: ${result.outputPath}`);
}

고급 사용 시나리오

// 배치 처리: 여러 파일 일괄 변환
import fs from 'fs/promises';
import path from 'path';

async function batchConvertHwpx(inputDir: string, outputDir: string) {
  const files = await fs.readdir(inputDir);
  const hwpxFiles = files.filter(file => file.endsWith('.hwpx'));

  for (const file of hwpxFiles) {
    try {
      const reader = new HwpxReader();
      await reader.loadFromFile(path.join(inputDir, file));

      const html = await reader.extractHtml({
        renderImages: true,
        embedImages: true,
        renderStyles: true
      });

      const outputFile = path.join(outputDir, file.replace('.hwpx', '.html'));
      await fs.writeFile(outputFile, html, 'utf8');

      console.log(`변환 완료: ${file} → ${path.basename(outputFile)}`);
    } catch (error) {
      console.error(`변환 실패 (${file}):`, error.message);
    }
  }
}

// 템플릿 치환 처리
async function processTemplate(templatePath: string, data: any, outputPath: string) {
  const reader = new HwpxReader();
  await reader.loadFromFile(templatePath);

  let html = await reader.extractHtml();

  // {{key}} 형식의 템플릿 치환
  Object.keys(data).forEach(key => {
    const regex = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
    html = html.replace(regex, data[key]);
  });

  await fs.writeFile(outputPath, html, 'utf8');
}

// 사용 예제
await batchConvertHwpx('./input', './output');
await processTemplate('./template.hwpx', {
  name: '홍길동',
  date: '2024-01-01'
}, './result.html');

CLI 사용법

기본 HWPX 명령어

# 문서 정보 확인
hwpxjs inspect document.hwpx
# 출력:
# Title: 보고서 제목
# Creator: 홍길동
# Date: 2024-01-15
# Format: application/hwpx
# Pages: 5, Sections: 3

# 텍스트 추출 (콘솔 출력)
hwpxjs txt document.hwpx
# 출력: 문서의 모든 텍스트 내용...

# 텍스트를 파일로 저장
hwpxjs txt document.hwpx > extracted.txt

# HTML 변환 (이미지/스타일 포함)
hwpxjs html document.hwpx > output.html

# HTML 변환 후 브라우저에서 바로 열기 (Windows)
hwpxjs html document.hwpx > output.html && start output.html

# 여러 파일 처리
hwpxjs txt *.hwpx  # 현재 폴더의 모든 .hwpx 파일에서 텍스트 추출

HWP 파일 처리 (새로운 기능!)

# HWP → HWPX 변환
hwpxjs convert:hwp document.hwp converted.hwpx
# 출력: HWP 파일이 HWPX로 변환되었습니다: document.hwp → converted.hwpx

# HWP에서 텍스트만 추출
hwpxjs hwp:txt document.hwp
# 출력: HWP 파일의 텍스트 내용...

# HWP 텍스트를 파일로 저장
hwpxjs hwp:txt document.hwp > hwp_text.txt

# 여러 HWP 파일 일괄 변환
for file in *.hwp; do
  hwpxjs convert:hwp "$file" "${file%.hwp}.hwpx"
done

문서 생성

# 평문 텍스트에서 HWPX 생성
hwpxjs write:txt notes.txt output.hwpx
echo "변환 완료: notes.txt → output.hwpx"

# 여러 줄 텍스트로 HWPX 생성
echo -e "첫 번째 줄\n\n두 번째 문단\n세 번째 줄" > content.txt
hwpxjs write:txt content.txt document.hwpx

# 파이프를 통한 텍스트 입력
echo "동적으로 생성된 내용" | hwpxjs write:txt - dynamic.hwpx

템플릿 처리

# 템플릿 파일과 JSON 데이터로 HTML 생성
hwpxjs html:tpl template.hwpx data.json > result.html

# data.json 예제:
# {
#   "name": "홍길동",
#   "date": "2024-01-15",
#   "title": "월간 보고서"
# }

# 템플릿에서 {{name}}, {{date}}, {{title}} 등이 치환됨

일괄 처리

# 폴더의 모든 HWPX를 HTML로 변환
hwpxjs batch ./input_hwpx ./output_html
# 출력:
# 변환 완료: document1.hwpx → document1.html
# 변환 완료: document2.hwpx → document2.html

# 템플릿 일괄 처리 (각 HWPX마다 대응하는 JSON 파일 필요)
hwpxjs batch:tpl ./templates ./data ./output
# 구조:
# ./templates/report1.hwpx + ./data/report1.json → ./output/report1.html
# ./templates/report2.hwpx + ./data/report2.json → ./output/report2.html

# 디렉토리 구조 예제
mkdir -p input output
cp *.hwpx input/
hwpxjs batch input/ output/
ls output/  # 변환된 HTML 파일들 확인

고급 CLI 사용 패턴

# 파이프라인을 통한 연속 처리
find ./documents -name "*.hwpx" -exec hwpxjs txt {} \; > all_text.txt

# 조건부 처리 (오류 발생 시 계속 진행)
for file in *.hwpx; do
  hwpxjs html "$file" > "${file%.hwpx}.html" 2>/dev/null || echo "Failed: $file"
done

# 병렬 처리 (GNU parallel 사용)
parallel hwpxjs txt {} \> {.}.txt ::: *.hwpx

# 메타데이터만 추출해서 CSV로 정리
echo "파일명,제목,작성자,날짜" > metadata.csv
for file in *.hwpx; do
  info=$(hwpxjs inspect "$file" 2>/dev/null)
  echo "$file,$(echo "$info" | grep "Title:" | cut -d: -f2-),$(echo "$info" | grep "Creator:" | cut -d: -f2-),$(echo "$info" | grep "Date:" | cut -d: -f2-)" >> metadata.csv
done

# 큰 파일 처리 시 진행 상황 표시
total=$(ls *.hwpx | wc -l)
current=0
for file in *.hwpx; do
  current=$((current + 1))
  echo "처리 중 ($current/$total): $file"
  hwpxjs html "$file" > "html/${file%.hwpx}.html"
done

오류 처리 및 디버깅

# 상세한 오류 메시지 확인
hwpxjs txt problematic.hwpx 2>&1

# 파일 형식 검증
hwpxjs inspect suspicious.hwpx || echo "유효하지 않은 HWPX 파일"

# 변환 가능한 파일만 필터링
for file in *.hwpx; do
  if hwpxjs inspect "$file" >/dev/null 2>&1; then
    echo "처리 가능: $file"
    hwpxjs html "$file" > "output/${file%.hwpx}.html"
  else
    echo "처리 불가: $file"
  fi
done

# 로그 파일 생성
hwpxjs batch input/ output/ 2>&1 | tee conversion.log

시스템 통합 예제

# cron으로 정기 변환 (매일 오전 9시)
# crontab -e
# 0 9 * * * cd /path/to/documents && hwpxjs batch ./incoming ./processed >> /var/log/hwpx-convert.log 2>&1

# 웹 서버와 연동 (새 파일 감지 후 자동 변환)
inotifywait -m ./uploads -e create -e moved_to |
  while read path action file; do
    if [[ "$file" == *.hwpx ]]; then
      echo "새 파일 감지: $file"
      hwpxjs html "$path$file" > "./web/html/${file%.hwpx}.html"
      echo "변환 완료: ${file%.hwpx}.html"
    fi
  done

# Git 후크로 자동 문서 변환 (.git/hooks/post-receive)
#!/bin/bash
cd /path/to/repo
if git diff-tree --name-only -r HEAD^ HEAD | grep -q "\.hwpx$"; then
  echo "HWPX 파일 변경 감지, HTML 재생성 중..."
  hwpxjs batch ./docs ./web/html/
  echo "문서 변환 완료"
fi

브라우저 데모

정적 파일을 브라우저에서 직접 여세요:

examples/browser/index.html

드래그&드롭으로 .hwpx를 올리면 텍스트/간단 HTML/요약을 표시합니다. 구현은 JSZip CDN + DOMParser 기반이며 번들 없이 동작합니다.

HTML 옵션 요약

  • paragraphTag: 기본 "p"
  • tableClassName: 기본 "hwpx-table"
  • renderImages/renderTables/renderStyles: 기본 true
  • embedImages: 기본 false (true 시 data: URL로 인라인)
  • tableHeaderFirstRow: 기본 false (true 시 첫 행을 <th> 처리)
  • imageSrcResolver(binPath): 출력용 이미지 경로 커스터마이즈

구현 메모

  • 구현은 패키지 구조(Contents/content.hpf, Contents/section*.xml)와 hp:t 텍스트 기준 추출에 초점을 맞췄습니다. 자세한 구조: HWPX 포맷 구조 살펴보기
  • 암호화 문서는 META-INF/manifest.xml 존재로 우선 감지하며, 복호화는 미지원입니다.