Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/brave-rivers-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@naverpay/url-param-compressor": patch
---

llms.txt 추가

- npm 배포 결과물에 `llms.txt` 포함 (`files` 배열 업데이트)
7 changes: 7 additions & 0 deletions .changeset/bright-meadows-fall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@naverpay/es-http-status-codes": patch
---

llms.txt 추가

- npm 배포 결과물에 `llms.txt` 포함 (`files` 배열 업데이트)
7 changes: 7 additions & 0 deletions .changeset/fluffy-wolves-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@naverpay/utils": patch
---

llms.txt 추가

- npm 배포 결과물에 `llms.txt` 포함 (`files` 배열 업데이트)
7 changes: 7 additions & 0 deletions .changeset/golden-clouds-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@naverpay/react-pdf": patch
---

llms.txt 추가

- npm 배포 결과물에 `llms.txt` 포함 (`files` 배열 업데이트)
7 changes: 7 additions & 0 deletions .changeset/sunny-hawks-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@naverpay/vanilla-store": patch
---

llms.txt 추가

- npm 배포 결과물에 `llms.txt` 포함 (`files` 배열 업데이트)
7 changes: 7 additions & 0 deletions .changeset/swift-tigers-bloom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@naverpay/svg-manager": patch
---

llms.txt 추가

- npm 배포 결과물에 `llms.txt` 포함 (`files` 배열 업데이트)
81 changes: 81 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

`pie` is a monorepo of common frontend libraries maintained by the Naver Financial frontend team. It uses pnpm workspaces + Turborepo, with packages under `packages/*` and internal apps under `apps/*`.

## Commands

```bash
# Install dependencies
pnpm install

# Build all packages (respects dependency order via Turborepo)
pnpm run build

# Run all tests
pnpm run test

# Filter to a specific package
pnpm run build --filter @naverpay/utils
pnpm run test --filter @naverpay/utils

# Run tests inside a package directly
cd packages/utils && pnpm test

# Lint / format
pnpm run lint
pnpm run lint:fix
pnpm run prettier
pnpm run prettier:fix

# Docs dev server
pnpm run start --filter docs

# Full clean + reinstall
pnpm run clean
```

## Packages

Each package has its own `CLAUDE.md` with detailed architecture and API notes:

| Package | Description | CLAUDE.md |
|---|---|---|
| `@naverpay/utils` | JS/TS utility functions (formatting, masking, Korean language) | [packages/utils/CLAUDE.md](packages/utils/CLAUDE.md) |
| `@naverpay/vanilla-store` | Framework-agnostic state management with React hooks | [packages/vanilla-store/CLAUDE.md](packages/vanilla-store/CLAUDE.md) |
| `@naverpay/url-param-compressor` | URL query param compression via deflate + base64 | [packages/url-param-compressor/CLAUDE.md](packages/url-param-compressor/CLAUDE.md) |
| `@naverpay/safe-html-react-parser` | DOMPurify + html-react-parser safe wrapper | [packages/safe-html-react-parser/CLAUDE.md](packages/safe-html-react-parser/CLAUDE.md) |
| `@naverpay/react-pdf` | Korean-optimized PDF viewer (pdfjs-dist) | [packages/react-pdf/CLAUDE.md](packages/react-pdf/CLAUDE.md) |
| `@naverpay/svg-manager` | SVG unique ID scoping for React | [packages/svg-manager/CLAUDE.md](packages/svg-manager/CLAUDE.md) |
| `@naverpay/es-http-status-codes` | Auto-generated HTTP status code constants | [packages/es-http-status-codes/CLAUDE.md](packages/es-http-status-codes/CLAUDE.md) |

## Architecture

### Build

All packages build with `@naverpay/pite` (`createViteConfig`) and output both CJS (`dist/cjs/`) and ESM (`dist/esm/`). Each package's `vite.config.mjs` declares the entry point(s).

### Testing

- Most packages: **vitest** + **happy-dom**
- `es-http-status-codes`: **jest** + **ts-jest**
- `url-param-compressor`: **vitest** (Node) + **playwright** (browser) — both run on `pnpm test`

### Versioning

Uses **changesets**. Before merging a PR, create a changeset file with `pnpm changeset`. Base branch is `main`. Internal dependency updates default to `patch`.

### Code Quality

Enforced via ESLint (`@naverpay/eslint-config`), Prettier (`@naverpay/prettier-config`), and markdownlint (`@naverpay/markdown-lint`). husky + lint-staged run checks on every commit.

## Conventions

- **No breaking changes**: Avoid changes that require consumers to update their code.
- **`sideEffects: false`**: All packages declare this — do not add side effects at module load time.
- **pnpm catalog**: React-related peer dependency versions are unified in `pnpm-workspace.yaml` under `catalog:`. Use `catalog:` instead of hardcoded version ranges.
- **Test file location**: `__tests__/` directory at package root (for `utils`, `es-http-status-codes`); colocated in `src/` for `vanilla-store` and `url-param-compressor`.
- **Auto-generated files**: `packages/es-http-status-codes/src/status-code.ts` and `reason-phrase.ts` are generated — never edit directly.
45 changes: 45 additions & 0 deletions packages/es-http-status-codes/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# CLAUDE.md — @naverpay/es-http-status-codes

Auto-generated, tree-shakable HTTP status code constants and reason phrases for TypeScript/JavaScript.

## Commands

```bash
pnpm generate # regenerate src/ from data.json
pnpm test # jest + ts-jest
pnpm build # CJS + ESM
```

## Structure

```
data.json # source of truth — list of { code, phrase, constant }
script/index.js # code generator: reads data.json → writes src/
src/
status-code.ts # AUTO-GENERATED: HttpStatusCodes, HttpStatusCode, HttpStatusCodeKeys
reason-phrase.ts # AUTO-GENERATED: ReasonPhrases
index.ts # re-exports both
__tests__/
index.test.ts # jest tests
```

## Key Rule

**Never edit `src/status-code.ts` or `src/reason-phrase.ts` directly.** They are auto-generated with the header comment `/*This file is auto-generated. Do not edit directly.*/`.

To add or change HTTP status codes, edit `data.json` and run `pnpm generate`.

## Public API

```ts
import { HttpStatusCodes, ReasonPhrases } from '@naverpay/es-http-status-codes'

HttpStatusCodes.OK // 200
HttpStatusCodes.NOT_FOUND // 404
ReasonPhrases[200] // "OK"

// Types
type HttpStatusCode // union of all numeric codes
type HttpStatusCodeKey // union of all constant name strings
HttpStatusCodeKeys // string[] of all constant names
```
41 changes: 41 additions & 0 deletions packages/es-http-status-codes/llms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# @naverpay/es-http-status-codes

> Lightweight, tree-shakable HTTP status code constants and reason phrases for TypeScript/JavaScript. Auto-generated from a canonical data source, ESM-compatible.

## Installation

```bash
npm install @naverpay/es-http-status-codes
```

## Usage

```ts
import { HttpStatusCodes, ReasonPhrases, HttpStatusCodeKeys } from '@naverpay/es-http-status-codes'

// Status code constants
HttpStatusCodes.OK // 200
HttpStatusCodes.NOT_FOUND // 404
HttpStatusCodes.INTERNAL_SERVER_ERROR // 500

// Reason phrases by numeric code
ReasonPhrases[200] // "OK"
ReasonPhrases[404] // "Not Found"
ReasonPhrases[500] // "Internal Server Error"

// All constant name strings
HttpStatusCodeKeys // ['CONTINUE', 'SWITCHING_PROTOCOLS', 'OK', ...]
```

## Types

```ts
type HttpStatusCode // union of all numeric status codes: 100 | 101 | 200 | 201 | ...
type HttpStatusCodeKey // union of all constant name strings: 'OK' | 'NOT_FOUND' | ...
```

## Notes

- `HttpStatusCodes` is a `const` object — values are inferred as literal number types, enabling exhaustive checks.
- `sideEffects: false` — individual constants are tree-shakable in bundlers that support it.
- The source files (`src/status-code.ts`, `src/reason-phrase.ts`) are auto-generated from `data.json`. Do not edit them directly.
3 changes: 2 additions & 1 deletion packages/es-http-status-codes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"./package.json": "./package.json"
},
"files": [
"dist"
"dist",
"llms.txt"
],
"scripts": {
"clean": "rm -rf dist",
Expand Down
57 changes: 57 additions & 0 deletions packages/react-pdf/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# CLAUDE.md — @naverpay/react-pdf

React PDF viewer built on `pdfjs-dist`, optimized for Korean documents. Exports CSS separately (`@naverpay/react-pdf/style.css`).

## Commands

```bash
pnpm build # CJS + ESM (no tests in this package)
```

## Structure

```
src/
index.ts # public exports
components/
PdfViewer.tsx # top-level component (entry point for consumers)
Pages.tsx # renders all pages via IntersectionObserver
page/
Canvas.tsx # renders a single PDF page onto <canvas>
layer/
Text.tsx # text layer (enables text selection)
Annotation.tsx # annotation layer (links, etc.)
contexts/
pdf.tsx # PDFDocumentProxy + viewer config context
page.tsx # per-page context
hooks/
useInfiniteScroll.ts # IntersectionObserver-based lazy page loading
useIsomorphicLayoutEffect.ts # useLayoutEffect on client, useEffect on SSR
usePdfViewerPageWidth.ts # measures container width for responsive rendering
utils/
pdf.ts # getPdfDocument wrapper
text.ts # text layer utilities
link-service.ts # external link handling for annotations
debounce.ts # local debounce (not from @naverpay/utils)
```

## PdfViewer Props

Key props on `<PdfViewer>`:

- `pdfUrl` — required, URL of the PDF file
- `pdfWorkerSource` — path to `pdf.worker.js` (consumers must configure)
- `cMapUrl`, `cMapCompressed` — for older PDFs requiring cmap support (Korean fonts)
- `withCredentials` — passes cookies for authenticated PDF endpoints
- `lazyLoading` — default `true`, uses IntersectionObserver for deferred page rendering
- `onClickWords` — `{ target: string | RegExp, callback }[]` for clickable text
- `header`, `footer` — ReactNode rendered above/below the PDF pages
- `onLoadPDFRender`, `onErrorPDFRender` — load lifecycle callbacks
- `externalLinkTarget` — default `'_blank'`

## Key Details

- PDF fingerprint comparison prevents unnecessary re-renders when `pdfUrl` doesn't change.
- `tokenize` prop is automatically set to `true` when `onClickWords` is provided.
- Consumers must import `@naverpay/react-pdf/style.css` separately.
- No tests exist in this package currently.
53 changes: 53 additions & 0 deletions packages/react-pdf/llms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# @naverpay/react-pdf

> React PDF viewer component built on pdfjs-dist, optimized for Korean documents. Supports lazy page loading, text selection, annotation layers, and clickable word callbacks.

## Installation

```bash
npm install @naverpay/react-pdf
```

Import the stylesheet separately:

```ts
import '@naverpay/react-pdf/style.css'
```

## Usage

```tsx
import { PdfViewer } from '@naverpay/react-pdf'
import '@naverpay/react-pdf/style.css'

<PdfViewer
pdfUrl="https://example.com/document.pdf"
pdfWorkerSource="/pdf.worker.min.js"
onLoadPDFRender={() => console.log('loaded')}
onErrorPDFRender={(e) => console.error(e)}
/>
```

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `pdfUrl` | `string` | required | URL of the PDF file |
| `pdfWorkerSource` | `string` | — | Path to `pdf.worker.js` |
| `cMapUrl` | `string` | — | URL for cmap files (Korean font support for older PDFs) |
| `cMapCompressed` | `boolean` | — | Whether cmap files are compressed |
| `withCredentials` | `boolean` | — | Send cookies with the PDF request |
| `lazyLoading` | `boolean` | `true` | Defer rendering of off-screen pages via IntersectionObserver |
| `externalLinkTarget` | `string` | `'_blank'` | Target for annotation links |
| `onClickWords` | `{ target: string \| RegExp, callback: () => void }[]` | — | Callbacks for clicking specific words in the text layer |
| `header` | `ReactNode` | — | Rendered above the PDF pages |
| `footer` | `ReactNode` | — | Rendered below the PDF pages |
| `style` | `CSSProperties` | `{}` | Style for the outermost container `<div>` |
| `onLoadPDFRender` | `() => void` | — | Called after PDF loads successfully |
| `onErrorPDFRender` | `(e: unknown) => void` | — | Called if PDF loading fails |

## Notes

- The consumer is responsible for hosting `pdf.worker.js` and providing its path via `pdfWorkerSource`.
- `tokenize` is automatically enabled when `onClickWords` is provided.
- PDF fingerprints are compared to avoid re-rendering when the same URL reloads.
3 changes: 2 additions & 1 deletion packages/react-pdf/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"react-pdf"
],
"files": [
"dist"
"dist",
"llms.txt"
],
"scripts": {
"clean": "rm -rf dist",
Expand Down
46 changes: 46 additions & 0 deletions packages/safe-html-react-parser/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# CLAUDE.md — @naverpay/safe-html-react-parser

Wraps `html-react-parser` with `isomorphic-dompurify` to sanitize HTML before parsing into React elements. Works in both SSR (Node) and browser environments.

## Commands

```bash
pnpm run test:memory # vitest run (no watch)
pnpm build # CJS + ESM
```

## Structure

```
src/
index.ts # safeParse(), SafeParseOptions, DEFAULT_SANITIZE_CONFIG
utils/
dompurify.ts # thin wrapper around isomorphic-dompurify
```

## Public API

```ts
safeParse(htmlString: string, options?: SafeParseOptions): ReactNode | null
```

`SafeParseOptions` extends `HTMLReactParserOptions` with:

- `sanitizeConfig?: SanitizeConfig` — DOMPurify config (defaults to `DEFAULT_SANITIZE_CONFIG`)
- `preserveCustomTags?: string[]` — custom elements to preserve through sanitization

`DEFAULT_SANITIZE_CONFIG` allows: `p br strong em b i u span div h1-h6 h ul ol li dl dt dd a img` with `KEEP_CONTENT: true`.

## Key Design Decisions

**CJS/ESM interop quirk**: `html-react-parser` re-exports its CJS default in a non-standard way. The actual parse function is resolved as:

```ts
htmlReactParser.default?.default || htmlReactParser.default || htmlReactParser
```

Do not change this without verifying both CJS and ESM builds.

**Custom tag preservation**: DOMPurify strips unknown tags. To preserve custom tags, `preserveCustomTags` temporarily converts them to `<span data-custom-tag="...">` before sanitization, then restores them via the `replace` option in `html-react-parser`.

**Returns `null`** if the sanitized HTML is empty/falsy.
Loading
Loading