terms: per-pack storage + import from another pack (v0.3.2)

- store.ts: 약관을 manifest/terms/<packKey>/ 폴더별로 저장. 첫 접근 시
  legacy 전역 .md 파일을 시드로 자동 복사한다.
- importTerms() 추가: 다른 음악퀴즈의 .md + _meta.json 을 현재 pack 으로
  복사한다. 동일 kind 는 source 값으로 덮어쓴다.
- /op/agreement 라우트를 세 단계로 분리:
  · /op/agreement → 음악퀴즈 카드 선택 페이지
  · /op/agreement/:packName → 해당 pack 의 약관 목록 + 추가 + 불러오기
  · /op/agreement/:packName/:kind → 에디터
- 공개 라우트도 /manifest/terms/:packKey/:fileName 으로 변경.
- 설치기 main.ts: state.selectedKey 를 약관 URL 에 포함하도록 수정 (메인 +
  rp 양쪽). pack 미선택 상태에서는 에러 반환.
- termsEditor.js: PACK_KEY 를 받아 저장 URL 에 포함.
- 다른 음악퀴즈 후보 select + 확인 모달 + locale 추가.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 01:29:04 +09:00
parent c14b0507c7
commit 25977d894b
11 changed files with 429 additions and 141 deletions

View File

@@ -136,6 +136,9 @@
"terms": {
"browserTitle": "약관 수정",
"title": "약관 수정",
"pickPackHint": "약관을 수정할 음악퀴즈를 선택하세요. 각 음악퀴즈마다 약관을 따로 보관합니다.",
"packBrowserTitle": "{{name}} — 약관 수정",
"packTitle": "{{name}} 약관 수정",
"hint": "수정할 약관을 선택하세요. 사이트에서 저장한 내용은 인스톨러가 약관 동의 화면에서 사용합니다.",
"editorBrowserTitle": "{{label}} 편집",
"editorTitle": "{{label}}",
@@ -169,7 +172,16 @@
"deleteConfirm": "정말 \"{{label}}\" 약관을 삭제할까요? 이 동작은 되돌릴 수 없습니다.",
"invalidKind": "식별자는 소문자/숫자/하이픈만, 32자 이내여야 합니다.",
"createFailed": "약관 추가 실패",
"cannotDeleteBuiltin": "기본 약관은 삭제할 수 없습니다."
"cannotDeleteBuiltin": "기본 약관은 삭제할 수 없습니다.",
"importHeading": "다른 음악퀴즈에서 불러오기",
"importSourceLabel": "가져올 음악퀴즈",
"importSourcePlaceholder": "음악퀴즈를 선택하세요",
"importHint": "선택한 음악퀴즈의 모든 약관(.md + 라벨)을 현재 음악퀴즈로 복사합니다. 같은 식별자의 약관이 있으면 덮어씁니다.",
"importButton": "불러오기",
"importEmpty": "불러올 수 있는 다른 음악퀴즈가 없습니다.",
"importConfirm": "선택한 음악퀴즈의 약관을 현재 음악퀴즈로 복사합니다. 같은 식별자의 약관은 덮어쓰여집니다. 진행할까요?",
"importFailed": "약관 불러오기 실패",
"invalidImportSource": "올바르지 않은 음악퀴즈입니다."
},
"datapack": {
"browserTitle": "데이터팩 수정",