Communitygithub.com

jasonadu/my-skills

영문 PDF(기술 서적, 튜토리얼, 매뉴얼 등)를 문단 단위 영한 대역, 이미지 base64 내장, 왼쪽 접이식 목차 탐색 기능을 갖춘 다중 파일 HTML 읽기 버전으로 변환합니다.

my-skills란 무엇인가요?

이 스킬은 영어 기술 PDF를 문단별로 영문과 한국어가 나란히 표시되는 대역(병렬) HTML 읽기 버전으로 변환하는 전문적인 번역 및 문서 변환 도구입니다. 사용자가 영어 PDF를 제공하고 '영한 대역 읽기', '중영 대역 HTML 읽기 버전', '문단별 번역 웹페이지' 등을 요청할 때 트리거됩니다. PyMuPDF로 PDF에서 텍스트와 이미지를 추출하고, 이미지는 base64로 인코딩하여 단일 HTML 파일에 포함시켜 오프라인에서도 열 수 있습니다. 각 장(chapter)은 하나의 독립적인 HTML 파일로 생성되며, 왼쪽 고정 접이식 목차와 오른쪽 하단의 지구본 버튼(🌐)을 통해 '영문만/한국어만/영한 대역' 세 가지 표시 모드를 전환할 수 있습니다. 코드 블록은 원문 그대로 유지하고, 한국어 문단은 연한 파란색 배경과 왼쪽 4px 컬러 바를 추가하여 시각적으로 구분합니다. 모든 파일은 소문자 하이픈 형식으로 명명되며, 최종 결과물은 zip 파일로 제공됩니다. Claude Code, Cursor 등의 AI 에이전트가 사용자를 대신하여 이 전체 작업 흐름을 자동화합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/jasonadu/my-skills/tree/HEAD/bilingual-reading

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

이중 언어 읽기 (Bilingual Reading)

개요

영어 기술 PDF를 문단 단위 영한 대역 오프라인 HTML 읽기 버전으로 만듭니다: 각 장은 자체 포함된 HTML(UTF-8, 이미지 base64 내장, 단일 파일로 오프라인 열기 가능), 왼쪽 고정 접이식 목차, 오른쪽 하단 🌐 플로팅 버튼으로 '영문만 / 한국어만 / 영한 대역'을 순환 전환하며, 페이지 이동 후에도 유지됩니다.

트리거 및 입력

  • 입력: 영문 PDF (로컬 경로 또는 URL, 먼저 로컬에 다운로드).
  • 출력: index.html + 머리말/맺음말 페이지 + chapter-NN.html (한 장 하나의 파일), 최종적으로 zip 패키지로 전달.
  • PDF에 책갈피(get_toc())가 있으면, 장 구조는 책갈피를 기준으로 먼저 사용자와 확인하고, 사용자가 "분할하지 않음"을 확인한 후에 일괄 제작합니다.

핵심 규칙 (위반 불가)

  1. 원문 문단별 전체 번역, 요약/병합하지 않음.
  2. 한 장 하나의 파일, 장을 나누지 않음; 장 내에서는 원서 페이지 순서대로 문단별로 배치.
  3. 코드 블록(<pre><code>)은 영어 원문 유지, 번역하지 않음; 중괄호가 포함된 코드는 f-string에 작성하지 않음.
  4. 한국어 문단은 연한 파란색 배경 + 왼쪽 4px 컬러 바로 영문 문단과 구분; 목록 항목의 한국어도 동일한 형식.
  5. 이미지는 압축 후 base64로 내장; 원서 한 페이지를 모두 번역한 후, 별도의 행에 페이지 표시(page_mark(pdf_page))를 추가하여 원본 PDF 페이지 번호를 표시.
  6. 파일 이름은 소문자 하이픈 사용 (chapter-01.html, front-matter.html).
  7. 목차 항목은 책갈피 레벨(l2/l3)에 따라 생성; 이전/다음 장 링크 연결, 첫/마지막 장은 비활성화 처리.

작업 흐름 개요

① 페이지 범위 결정 → ② 텍스트 추출 → ③ 이미지 추출 → ④ 이미지 압축 후 base64 변환
→ ⑤ 원문 읽고 번역 → ⑥ build_chN.py 작성 → ⑦ 중괄호 보완 → ⑧ 실행하여 생성
→ ⑨ 탐색 연결 → 검증 → 전달

먼저 샘플 장(보통 ch1)을 만들어 사용자가 스타일을 승인하도록 하고, 승인 후 book_theme.py를 정착/재사용하여 연속 일괄 제작하며 중간에 추가 확인이 필요 없습니다. 머리말/맺음말 페이지와 index.html은 마지막에 일괄 마무리합니다.

상세 단계

① 페이지 범위 결정

입력: 전체 목차 / 장 번호. PyMuPDF로 책갈피 읽기:

import fitz
doc = fitz.open("book.pdf")
toc = doc.get_toc()          # [[level, title, page_1based], ...]

1-based 페이지 번호를 PyMuPDF 0-based 범위로 변환합니다. 책갈피 페이지 번호는 실제 페이지와 종종 오프셋이 있으므로 책갈피를 기준으로 합니다; 사용자에게 장 구분을 나열하고 확인을 받은 후 작업을 시작합니다.

② 텍스트 추출

text = "".join(doc[p].get_text("text", sort=True) for p in range(start0, end0+1))
open("chN_raw.txt", "w", encoding="utf-8").write(text)

sort=True는 읽기 순서를 보장하며, 다단 혼동을 방지합니다. 각 장마다 chN_raw.txt에 원문 저장.

③ 이미지 추출

scripts/extract_assets.py 사용:

python3 extract_assets.py book.pdf <start_page_1based> <end_page_1based> --out assets
  • page.get_images(full=True)로 xref 기준 중복 제거 → extract_image(xref).
  • jpx(JPEG2000), RGBA, P 모드는 통일적으로 RGB로 변환 후 JPEG 저장 (브라우저 호환).

④ 이미지 압축 후 base64 변환

위 단계와 동시에 완료 (스크립트 내장): PIL로 열기; 너비 >800px이면 비율 유지하며 800으로 축소 (LANCZOS); JPEG q≈68로 다시 저장; base64를 assets/figN-M.txt에 기록. 단일 이미지를 30~80KB로 압축.

⑤ 원문 읽고 번역

  • chN_raw.txt를 분할하여 읽음 (한 번에 500~600줄), 문단별로 번역, 그림 설명 매핑 기록 (책 속 그림, 예: 까마귀 그림을 해당 텍스트 "노트"로 변환).
  • 코드 세그먼트는 번역 건너뜀; 표는 HTML table로 변환; 목록 형태 내용도 항목별로 번역하며 병합하지 않음.

⑥ 빌드 스크립트 작성

build_chN.py 상단에 from book_theme import P, LI, CODE, INLINE, H, img_b64, page_mark, page를 작성하고, 본문은 f-string body에 작성. f-string 내 P()/LI()는 반드시 {P(...)} 형식으로 써야 평가됨; 코드 블록은 일반 문자열 변수 CODE_X = '''...'''로 추출한 후 + CODE_X로 연결. 전체 템플릿은 scripts/book_theme.py 파일 헤더 docstring 참조.

⑦ 후처리: 중괄호 보완

python3 scripts/fix_braces.py build_chN.py

라인 순회: P('/LI('로 시작하는 줄의 시작에 {를 추가하고, 뒤에서 첫 번째로 )로 끝나는 줄의 끝에 }를 추가. img_b64(/page( 호출 줄은 처리하지 않아, 실수로 }가 끝 page() 줄에 추가되는 것을 방지.

⑧ 실행하여 생성

python3 build_chN.py     # 스크립트가 파일 이름과 KB 수를 출력하면 성공

⑨ 탐색 연결

prev/next는 장 번호에 따라 채움 (ch1 prev=front-matter.html, 마지막 장 next=None), 첫/마지막 장은 disabled 자리 표시자 사용 (page() 내에서 처리됨).

마무리

  • front-matter.html, closing.html (추천 도서 목록 포함/미포함은 먼저 사용자와 협의), index.html 전체 입구 (모든 장 링크).
  • python3 -m zipfile -c bilingual_reading.zip *.html로 패키징하여 zip 전달.

분기 및 예외 처리

트리거 조건처리 방식
이미지가 jpx / RGBA / P 모드인 경우extract_assets.py에서 통일적으로 convert하여 RGB로 변환 후 JPEG 저장
f-string 내에 코드 블록 중괄호(JSON dict)가 있는 경우f-string에 작성하지 않음; CODE_X = '''...'''로 추출한 후 + CODE_X로 연결
{<P( 오기입sed 's/{<P(/{P(/g'로 수정
일괄 } 추가 시 끝 page() 줄에 실수로 추가된 경우fix_braces.py에서 이미 방지; 그래도 발생하면 해당 줄 끝의 불필요한 } 수동 삭제
사용자가 "효과를 먼저 보고 계속" 요청샘플 장만 만들고, 피드백 기다리며 중단
사용자가 "코드는 번역하지 마세요" 요청모든 <pre><code>는 영문 원문 유지 (기본값이 이미 이렇게 설정됨)
추가 문제 해결 항목references/troubleshooting.md 참조

리소스 인덱스

  • scripts/book_theme.py — 핵심 공유 모듈: CSS/JS/페이지 스켈레톤 + P, LI, CODE, INLINE, H, img_b64, page_mark, page 함수. 스타일 변경은 여기서만 수정.
  • scripts/extract_assets.py — 단계 ③④: 이미지 추출, 압축, base64 변환하여 assets/에 기록.
  • scripts/fix_braces.py — 단계 ⑦: f-string 중괄호 일괄 보완.
  • references/style-guide.md — 스타일 및 상호작용 규범 세부사항 (색상, 레이아웃, 구성 요소, 검증 대조).
  • references/troubleshooting.md — 문제 해결 표와 재사용 가능한 경험.

검증 체크리스트

  • 샘플 장 스타일이 사용자 승인 완료 (한국어 문단 연한 파란색 배경, 목록 항목 한국어 동일 형식, 페이지 표시 존재)
  • 원문 문단별 전체 번역, 코드 블록 미번역, 이미지 base64 내장되어 오프라인 열기 가능
  • 각 장 HTML 독립적으로 열기 가능, 목차 접이식 가능, 앵커 점프 정상 작동
  • 🌐 버튼 세 가지 상태 순환, 페이지 이동 후 유지 (localStorage)
  • 이전/다음 장 링크 연결 정확, 첫/마지막 장 버튼 비활성화
  • 모든 파일 UTF-8, 파일 이름 소문자 하이픈, zip 패키지로 전달

관련 스킬