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

@tipp/pdf-builder

v1.0.8

Published

pdfmake 기반 PDF 생성 라이브러리 - metaJson + data를 받아 PDF Buffer 생성

Downloads

1,516

Readme

@tipp/pdf-builder

pdfmake 기반 PDF 생성 라이브러리입니다. metaJson과 data를 받아 PDF Buffer를 생성합니다.

특징

  • 메타 기반 PDF 생성: JSON 형태의 메타 정보로 PDF 문서를 정의
  • 데이터 바인딩: {{path}} 템플릿과 $path 바인딩 지원
  • 컴포넌트 아키텍처: 재사용 가능한 컴포넌트 시스템
  • 페이지 분할: 멀티 페이지 및 페이지 구분 지원
  • 커스텀 프리셋: 문서 스타일 프리셋 및 푸터 프리셋

설치

pnpm add @tipp/pdf-builder

빠른 시작

import { buildPdf, registerDefaultComponents } from '@tipp/pdf-builder';
import type { PdfMeta } from '@tipp/pdf-builder';

// 기본 컴포넌트 등록
registerDefaultComponents();

// PDF 메타 정의
const meta: PdfMeta = {
  pages: [
    {
      sections: [
        {
          type: 'sectionHeading',
          config: { text: 'Hello World', level: 1 },
        },
        {
          type: 'paragraph',
          config: { text: '{{greeting}}' },
        },
      ],
    },
  ],
};

// 데이터
const data = {
  greeting: 'Welcome to PDF Builder!',
};

// PDF 생성
const buffer = await buildPdf(meta, data);

// 파일로 저장
fs.writeFileSync('output.pdf', buffer);

핵심 개념

PdfMeta 구조

type PdfMeta = {
  docPreset?: string;        // 문서 프리셋 ('default' 등)
  defaultStyle?: Style;      // 기본 스타일
  styles?: StyleDictionary;  // 커스텀 스타일
  pages: PageConfig[];       // 페이지 목록
};

type PageConfig = {
  layout?: PageLayout;       // 페이지 레이아웃
  pageBreak?: 'after' | 'before' | 'none';
  sections: SectionConfig[]; // 섹션 목록
};

type SectionConfig = {
  type: string;              // 컴포넌트 타입
  config: Record<string, unknown>;  // 컴포넌트 설정
};

참고: SectionConfig는 커스텀 컴포넌트도 허용하기 때문에 최종적으로는 type: string 형태를 유지합니다.
다만 기본(built-in) 컴포넌트(table, sectionTitle, tableOfContents 등)는 type에 따라 config 타입이 자동완성되도록 구현되어 있습니다.

pageBreak를 생략하면 기본값은 'after'로 동작합니다. (단, 마지막 페이지에는 자동으로 'after'가 적용되지 않습니다.)

데이터 바인딩

  • 템플릿 치환: {{path.to.value}} 형식으로 데이터 값을 문자열에 삽입
  • 직접 바인딩: $path.to.value 형식으로 설정 값을 데이터에서 가져옴
  • 배열 인덱스: items.0.name 형식으로 배열 요소 접근
// 데이터
const data = {
  user: { name: 'John' },
  items: ['First', 'Second'],
};

// 템플릿 치환
{ text: 'Hello, {{user.name}}!' }  // => 'Hello, John!'

// 직접 바인딩
{ items: '$items' }  // => ['First', 'Second']

기본 컴포넌트

헤더

  • commonHeader - 문서 헤더 (제목, 부제목, 로고)
  • sectionTitle - 섹션 타이틀 (번호 + 제목)
{
  type: 'commonHeader',
  config: {
    title: '성과평가 피드백 분석 리포트',
    subtitle: '성과평가 피드백 대화 모델 O-FEAR-S 기반',
  },
}

텍스트

  • text - 기본 텍스트
  • paragraph - 단락
  • sectionHeading - 섹션 헤딩 (레벨 1-4)
{ type: 'sectionHeading', config: { text: '요약', level: 2 } }
{ type: 'paragraph', config: { text: '{{report.summary}}' } }

테이블

  • table - 통합 테이블 (DSL + layoutPreset)

기본 사용 예시

{
  type: 'table',
  config: {
    widths: [60, '*'],
    rows: [
      [{ kind: 'label', text: '설명' }, { kind: 'value', text: '{{reportData.summary.comment}}' }],
      [{ kind: 'label', text: '대화 예시' }, { kind: 'value', text: '{{reportData.skills.0.example1}}' }],
    ],
    layoutPreset: 'gridThin',
    margin: [0, 0, 0, 24],
  },
}

셀 DSL(rows) 요약

  • 리터럴: string | number | null (null은 rowSpan/colSpan placeholder 용도)
  • 객체: { kind, text, overrides }
    • kind: label | value
    • overrides: colSpan/rowSpan/alignment/fillColor/color/weight/fontSize/lineHeight/style/margin/decoration/borderOff 등 최소 오버라이드

layoutPreset

  • gridThin (기본): 얇은 grid
  • noBorders: border 제거

borderOff

  • 기본은 grid이며, 특정 셀의 border를 끄려면 overrides.borderOff를 사용합니다.
  • 값은 ['left' | 'top' | 'right' | 'bottom'] 배열입니다.

예제

examples/ 디렉토리에서 다양한 예제를 확인할 수 있습니다:

  • basic/ - 기본 사용 예제
  • coaching-report/ - 코칭 리포트 형식 예제
  • complex-layout/ - 복잡한 레이아웃 예제
  • ai-training-ofears-report/ - AI Training O-FEAR-S 리포트 예제 (backend 리포트 구성 참고)
  • ai-training-openfans-report/ - AI Training OPEN FANS 리포트 예제 (backend 리포트 구성 참고)
# 예제 실행
npx tsx examples/basic/index.ts

# 코칭 리포트 예제 실행 (생성 파일: examples/coaching-report/output/coaching-report.pdf)
npx tsx examples/coaching-report/index.ts

# 복잡 레이아웃 예제 실행
npx tsx examples/complex-layout/index.ts

# AI Training O-FEAR-S 리포트 예제 실행
npx tsx examples/ai-training-ofears-report/index.ts

# AI Training OPEN FANS 리포트 예제 실행
npx tsx examples/ai-training-openfans-report/index.ts

API 문서

자세한 API 문서는 docs/API.md를 참조하세요.

라이선스

MIT