$npx -y skills add tobyilee/book-writer --skill epub-buildBuild a standards-compliant EPUB 3 file from a manuscript markdown, cover image, and book_manifest.json using the bundled pandoc-based script. Output is 책-제목-v{version}.epub with the manifest's author (defaults to Toby-AI), accompanied by a paired 책 소개 markdown ({책-제목}-v{version}
| 1 | # EPUB Build |
| 2 | |
| 3 | 통합 원고·표지·매니페스트를 입력받아 EPUB 3 파일을 생성하고, 같은 폴더에 책 소개 markdown을 함께 만든다. EPUB 변환은 결정적 빌드를 위해 `scripts/build_epub.sh` 스크립트에 위임하고, 책 소개 markdown은 `epub-builder` 에이전트가 매니페스트·계획·통합 원고를 읽어 직접 작성한다. |
| 4 | |
| 5 | ## 절차 |
| 6 | |
| 7 | 1. **입력 검증** — 세 파일이 모두 존재하는지 |
| 8 | - `{slug}/04_manuscript.md` |
| 9 | - `{slug}/cover.png` |
| 10 | - `{slug}/book_manifest.json` |
| 11 | 2. **매니페스트 필드 점검** |
| 12 | - `title` 비어있지 않음 |
| 13 | - `author` 필드 존재 (기본값 `Toby-AI`, 사용자 지정 시 매니페스트 값을 그대로 사용) |
| 14 | - `language` 존재 (`ko`) |
| 15 | - `version` 존재 (예: `1.0.0`) |
| 16 | - `identifier` (옵션) — 비어 있거나 플레이스홀더 `urn:uuid:...`이면 스크립트가 `urn:uuid:{uuid4}` 한 번 발급 후 매니페스트에 기록한다. **신간에 1회 발급되고 이후 재빌드에서 그대로 보존(불변)** — version/date만 바뀐다. `_prev`에 다른 식별자가 있으면 경고 |
| 17 | - `cover_alt` (옵션) — 표지 대체 텍스트. 비어 있으면 기본값 `{title} 표지`. 스크립트가 표지 xhtml에 실제 alt(또는 SVG 표지의 `role="img"`+`aria-label`+`<title>`)로 주입해 a11y 대체 텍스트 주장을 뒷받침한다 |
| 18 | - `license` (옵션) — 비어 있으면 하네스 기본값 `CC BY-NC-SA 4.0` 적용. 다른 라이선스를 쓰려면 명시 (`"CC BY 4.0"`, `"CC0"`, `"All rights reserved"` 등) |
| 19 | - `harness_version` (옵션) — 비어 있으면 루트 `VERSION` 파일에서 자동 주입 |
| 20 | - `rights` (옵션) — 비어 있으면 `© {year} {author} — Licensed under {license}`로 자동 생성 |
| 21 | 3. **스크립트 실행** — `scripts/build_epub.sh {slug}` |
| 22 | 4. **결과 검증** |
| 23 | - 파일 존재, 크기 ≥ 50KB |
| 24 | - `epubcheck` 실행 결과 점검 — **`epubcheck` 실패는 빌드 실패다(각주가 아님).** `EPUBCHECK_STRICT`(기본 켜짐 `1`)일 때 설치+실패면 빌드 로그를 쓴 뒤 종료 코드 `5`로 실패. `epubcheck`가 **미설치**면 EPUB은 검증되지 않은(UNVALIDATED) 상태로 산출되며 `brew install epubcheck` 안내를 stderr·빌드 로그에 남긴다 (`EPUBCHECK_STRICT=0`으로 실패를 경고로 강등 가능) |
| 25 | 5. **책 소개 markdown 생성** — EPUB과 같은 폴더(프로젝트 루트)에 `{책-제목}-v{version}.md` 작성 |
| 26 | - 파일명 슬러그화 규칙은 EPUB과 동일 (공백→하이픈, 특수문자 제거) |
| 27 | - 콘텐츠 템플릿·작성 원칙은 `epub-builder` 에이전트의 "책 소개 markdown" 섹션 참조 |
| 28 | - 소스: `book_manifest.json` (메타), `02_plan.md` (독자·아크), `04_manuscript.md` (실제 차례) |
| 29 | - 같은 버전 파일이 이미 있으면 `_prev/`로 이동 후 신규 작성 |
| 30 | 6. **기록** — `{slug}/build_log.md`에 명령, 출력, 크기, 검증 결과, 책 소개 md 경로 |
| 31 | |
| 32 | ## 스크립트 개요 (`scripts/build_epub.sh`) |
| 33 | |
| 34 | pandoc을 이용해 원고와 메타데이터를 EPUB으로 변환한다. 요점: |
| 35 | |
| 36 | ```bash |
| 37 | pandoc {manuscript} \ |
| 38 | --from markdown \ |
| 39 | --to epub3 \ |
| 40 | --metadata-file={manifest_yaml} \ |
| 41 | --resource-path={slug} \ |
| 42 | --epub-cover-image={cover} \ |
| 43 | --css={styles/epub.css} \ |
| 44 | --toc --toc-depth=2 \ |
| 45 | --output {output_path} |
| 46 | ``` |
| 47 | |
| 48 | 매니페스트(JSON)를 YAML로 변환한 뒤 pandoc에 전달한다. `--resource-path={slug}`로 상대 이미지 경로(예: `figures/fig-NN.svg`)가 슬러그 디렉터리 기준으로 해석된다. 스크립트 전문은 `scripts/build_epub.sh` 참조. |
| 49 | |
| 50 | ## 스타일시트 (base 타이포그래피 + 구조화 블록, v1.8.0+) |
| 51 | |
| 52 | `styles/epub.css`를 스크립트가 자동으로 임베드한다(스크립트 위치 기준 상대 경로). pandoc 3.x의 `--css`는 EPUB 기본 스타일시트를 **대체**하므로, 이 파일은 **기본 타이포그래피(표·코드·인용·헤딩·figure)** 와 **구조화 블록 클래스**(`meta`/`ingredients`/`steps`/`tip`/`warning`/`itinerary`, 태스크 리스트)를 함께 제공한다. 한글 본문 폰트 스택·모노스페이스 코드 폰트·다크 모드(`prefers-color-scheme: dark`) 대비까지 포함한다. 실용서(practical) 챕터는 블록 클래스를 pandoc fenced div(`::: meta` 등)로 작성한다(규약은 `profiles/practical/scaffolds.md`). CSS 파일이 없으면 스크립트는 `--css` 없이 진행한다(이 경우 기본 타이포그래피도 빠지므로 권장하지 않음). |
| 53 | |
| 54 | ## 식별자(identifier) 발급·보존 |
| 55 | |
| 56 | EPUB의 `urn:uuid:*` 식별자는 **신간에 1회 발급**되고 이후 재빌드에서 **그대로 보존된다(불변)** — 재빌드 때는 version/date만 바뀐다. 매니페스트의 `identifier`가 비어 있거나 플레이스홀더 `urn:uuid:...`이면 스크립트가 `urn:uuid:{uuid4}`를 발급해 매니페스트에 기록한다. 한 번 발급된 식별자는 수동으로 바꾸지 않는다. `_prev`에 다른 식별자가 있으면 경고를 출력한다. |
| 57 | |
| 58 | ## 그림(figure) — mermaid 사전 처리 (옵션) |
| 59 | |
| 60 | 구조·관계를 나타내는 그림은 본문에 ```` ```mermaid ```` fenced 블록 + `그림 N. {설명}` 캡션 줄로 작성한다(챕터별 N 번호). 빌드 시 `mmdc`가 설치되어 있으면 pandoc 전에 각 블록을 `{slug}/figures/fig-NN.svg`로 렌더하고 fence를 ``로 치환한다. `mmdc`가 없으면 fence를 그대로 두고(코드 블록으로 렌더) 경고만 남긴다 — **mmdc는 하드 의존성이 아니다**(옵션 epubcheck와 동일 패턴). |
| 61 | |
| 62 | ## 파일명 규칙 |
| 63 | |
| 64 | - `{책-제목}-v{version}.epub` |
| 65 | - 제목의 공백·유니코드 대시(U+2010–U+2015) 연속은 하나의 `-`로 축약 |
| 66 | - 첫 번째 em-dash(`—`)나 콜론(`:`) 뒤의 부제는 잘라내고 **메인 제목만** 파일명에 사용 |
| 67 | - Windows 금지 문자(`\ / : * ? " < > |`)는 제거 |
| 68 | - 앞뒤 하이픈은 제거, 최대 60자로 제한 |
| 69 | - 짝을 이루는 책 소개 `.md`의 stem은 EPUB과 **동일**해야 한다 |
| 70 | - 예: `데이터베이스 인덱스 — 깊이 있는 안내` → `데이터베이스-인덱스-v1.0.0.epub` |
| 71 | |
| 72 | ## 버전 관리 |
| 73 | |
| 74 | - 초기 빌드: `v1.0.0` |
| 75 | - 오탈자 수정: patch 증가 → `v1.0.1` |
| 76 | - 챕터 개정: minor 증가 → `v1.1.0` |
| 77 | - 구조 재편: major 증가 → `v2.0.0` |
| 78 | - 기존 파일을 덮어쓰지 말고 새 파일로 공존 |
| 79 | |
| 80 | ## 검증 체크 |
| 81 | |
| 82 | - [ ] EPUB 파일 생성됨 |
| 83 | - [ ] 파일 크기 ≥ 50KB |
| 84 | - [ ] `unzip -l`로 내부 구조 확인 가능 |
| 85 | - [ ] 메타 조회: `pandoc -f epub -t plain --template=metadata.tpl` 등 |
| 86 | - [ ] `epubcheck` 통과 — 실패는 빌드 실패(`EPUBCHECK_STRICT` 기본 켜짐 → 종료 코드 `5`). 미설치 시 EPUB은 검증되지 않음(`brew install epubcheck` 권장) |
| 87 | - [ ] 표지 alt 텍스트가 표지 xhtml에 실제로 들어갔는지 (`<img alt>` 또는 SVG `aria-label`/`<title>`) |
| 88 | - [ ] 재빌드 후에도 `identifier`(`urn:uuid:*`)가 직전 빌드와 동일한지 |
| 89 | - [ ] 책 소개 md (`{책-제목}-v{version}.md`)가 EPUB 옆에 존재하고, 차례·저자·버전이 매니페스트와 일치 |
| 90 | - [ ] `unzip -p {output} OEBPS/content.opf | grep -i rights` — `rights` 메타에 라이선스 문구 포함 (`Licensed under {license}` 또는 매니페스트의 명시값) |
| 91 | - [ ] `04_manuscript.md`의 `## 판권` 섹션이 매니페스트의 `licens |