Skip to main content

create-lesson-from-pdf

Create a new L2-x Korean lesson in this app from a "L2-xPDF Viewer.pdf" file under docs/lessons/. Use whenever the user asks to add, build, or generate a lesson from a lesson PDF. Covers extracting dialogues/vocabulary, cropping image assets from the PDF, wiring the lesson into courseLessons.js, updating the test, and verifying.

설치로 이동

소스 정보

저장소
ryantsai/LearnKoreanQuick
최근 소스 활동
2026년 6월 19일 01:02
감지된 SKILL.md 언어
영어
스타
0
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
3 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
create-lesson-from-pdf
description
Create a new L2-x Korean lesson in this app from a "L2-xPDF Viewer.pdf" file under docs/lessons/. Use whenever the user asks to add, build, or generate a lesson from a lesson PDF. Covers extracting dialogues/vocabulary, cropping image assets from the PDF, wiring the lesson into courseLessons.js, updating the test, and verifying.
# Create a lesson from a PDF This skill turns a `docs/lessons/L2-<n>PDF Viewer.pdf` into a fully wired lesson in the "Learn Korean Quick" app, matching the structure of the existing L2-1 … L2-6 lessons. ## When to use The user says something like "create L2-7 from the PDF", "add the next lesson", or "do L2-8 (L2-8PDF Viewer.pdf)". Each lesson PDF follows the same Gjun/ABC Online template: a title slide, 學習目標, 情境對話, 相關單字學習 (vocab photos), 單字練習, optional 句型教學 / learning tabs, 對話練習, 重點回顧, and a closing 再見 slide. ## Before you start 1. Confirm the PDF exists: `docs/lessons/L2-<n>PDF Viewer.pdf`. 2. Ask the user (only if unstated) whether to work on a feature branch or commit directly to `main`. Default to a feature branch + PR unless told otherwise. 3. Read the PDF with the Read tool to extract every Korean line, its 中文 meaning, and the vocabulary list. The 情境對話 (page ~3) and 對話練習 (later page) become the two dialogues. ## Key files - `src/data/courseLessons.js` — all lesson data. Structure: imports → helpers (`word`, `withVocabImages`, `line`, `courseAsset`) → word arrays `l21`, `l22`, … → `export const courseLessons = [ … ]`. - `src/data/courseLessons.test.js` — validates lesson shape AND that every referenced PNG exists on disk. **You must update the id list** near the top: `expect(courseLessons.map((l) => l.id)).toEqual([... , "l2-<n>"])`. - `public/assets/course-lessons/` — where lesson PNGs live. Naming is strict (see below). - `src/utils/hangul.js` — `decomposeHangulWord(hangul, roman)` powers the word inspector. ## Helpers and data shape ```js word(text, roman, zh) // builds { text, roman, zh, syllables } withVocabImages("l2-<n>", [words]) // attaches vocab-01..NN images by index line(speaker, ko, zh, tokens) // one dialogue line; tokens is an array of word objects courseAsset("l2-<n>-…") // -> assetPath("assets/course-lessons/<name>.png") ``` Lesson object (copy the most recent simple lesson, e.g. l2-5 / l2-6, as a template): ```js { id: "l2-<n>", label: "L2-<n>", titleKo: "<Korean title from slide 1>", titleZh: "<中文 title>", theme: "<short 中文 theme>", sourcePdf: "docs/lessons/L2-<n>PDF Viewer.pdf", media: { hero: courseAsset("l2-<n>-dialogue-person") }, dialogues: [ { title: "情境對話", image: courseAsset("l2-<n>-dialogue-person"), objectImage: courseAsset("l2-<n>-dialogue-object"), lines: [ /* >=4 lines */ ] }, { title: "對話練習", image: courseAsset("l2-<n>-practice-person"), objectImage: courseAsset("l2-<n>-practice-visual"), lines: [ /* >=4 lines */ ] } ], vocabulary: withVocabImages("l2-<n>", [ /* >=12 word() entries */ ]) } ``` Define a `const l2<n> = [ word(...), ... ]` array for the dialogue vocabulary and reference entries by index in `line(...)` tokens (reuse repeated words by index). One-off words that only appear once can be inlined with `word("아", "a", "啊")` directly in the tokens array. Some older lessons (l2-3, l2-4) also have a `guide` field (numbers/dates learning tab) with its own test assertions. Only add a `guide` if the PDF has an equivalent reference grid; otherwise follow the simpler dialogues+vocabulary shape above. ## Romanization rule (critical — the test enforces it) `decomposeHangulWord` splits `roman` on `-` and asserts `syllables.length === [...text].length`. So **the roman string must have exactly one hyphen-separated segment per Hangul character, including spaces**: - `크게` → `"keu-ge"` (2) `착각했어요` → `"chak-ga-kae-sseo-yo"` (5) - For words with a space, the space counts as a character: `버스 정류장` → 6 syllables, so `"beo-seu jeong-nyu-jang"` (the space sits inside the middle segment, total segments = 6). - Use the *pronounced* romanization (liaison/assimilation): `웃는게` → `"un-neun-ge"`, `발음이` → `"ba-reum-i"`, `많이` → `"ma-ni"`. Count `[...text].length` for every word and make the hyphen segments match, or the test fails. ## Image assets Required PNGs in `public/assets/course-lessons/` (the test fails if any are missing): - `l2-<n>-dialogue-person` — also used as `media.hero` - `l2-<n>-dialogue-object` — supporting image from the 情境對話 slide - `l2-<n>-practice-person` — person from the 對話練習 slide - `l2-<n>-practice-visual` — supporting image from the 對話練習 / 句型教學 slide - `l2-<n>-vocab-01` … `l2-<n>-vocab-12` (one per vocabulary word, ≥12) Generate them by rasterizing PDF pages with PyMuPDF + PIL and cropping fractional boxes. Use the bundled helper script as a starting point: ```bash python .claude/skills/create-lesson-from-pdf/crop_assets.py "docs/lessons/L2-<n>PDF Viewer.pdf" l2-<n> ``` Then **visually verify** each crop with the Read tool and adjust the fractional boxes in the script until subjects are well framed. The 相關單字學習 vocab slides lay photos out in left/ center/right thirds (≈ x 0.07–0.34 / 0.37–0.63 / 0.66–0.93, y ≈ 0.27–0.61). Render to a temp dir first (e.g. `tmp_l2n/`) to calibrate, then delete it before committing. ## Verify, then commit 1. `npx vitest run --exclude "**/.claude/**"` — the `--exclude` skips stale local worktrees under `.claude/`; all tests must pass (the id-list assertion catches a forgotten test edit). 2. `npm run build` — must succeed. 3. Optionally verify in the browser (Playwright/preview) that the new lesson renders. 4. Clean up any temp render dirs. Stage assets + the two source files. 5. Commit. End the message with: `Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>` 6. Push (and open a PR if working on a feature branch). Only commit/push when the user asked. ## Checklist - [ ] PDF read; all Korean lines + 中文 + vocab extracted - [ ] 16 PNGs cropped, visually checked, correctly named - [ ] `const l2<n>` array + lesson object added after the previous lesson - [ ] `vocabulary` has ≥12 words; each dialogue has ≥4 lines - [ ] every roman string's hyphen-segment count == its Hangul char count - [ ] test id list updated to include `"l2-<n>"` - [ ] `npx vitest run --exclude "**/.claude/**"` and `npm run build` both pass - [ ] temp artifacts removed; committed with co-author trailer; pushed
GitHub에서 보기