feat: 랜딩 페이지에 MathLive 기반 수학 점역 데모 추가 및 한글·수학 탭 통합 - #177
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- MathTransInput: 박스 전체 클릭 시 math-field 포커스(TransInput과 동일 동작) - readArg: 미종료 중괄호 내용 보존, 제어기호 인자 균형 유지 - DemoChrome: 한글·수학 데모 공통 헤딩/화살표 컴포넌트 추출 - DemoTabs: type=button, aria-controls, role=tabpanel, 좌우 화살표 키 이동 - MathTransInput: latex 상태를 부모에서 단일 관리(controlled), placeholder 흐름 배치로 매직 넘버 제거 - 입출력 박스를 동일 flex-basis 2단 구조로 맞춰 크기(498×500) 통일 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
owjs3901
left a comment
There was a problem hiding this comment.
superpowers 를 gitignore에 추가요망
- Trans/MathTrans/MathTransInput의 세로 컨테이너를 Flex→VStack으로 변경 - VStack 기본값과 중복되는 flexDirection="column" 및 불필요한 w="100%" 제거 - DemoArrow의 transform 기본값 rotate(0deg)→null (항등 변환이라 불필요) - 미사용 Flex import 정리 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- MathTransInput: math-field의 인라인 style을 css()로 전환 - Trans/MathTrans: VStack 기본값과 중복되는 flexDirection 맨 앞 column을 null로 - docs/superpowers 플랜 문서 2개 제거
바깥 컨테이너가 row 방향 flex라 align-items stretch가 가로를 늘리지 않아 w=100%가 제거되면 입력·출력 박스 너비가 어긋난다. w=100% 대신 flex=1로 가로를 채워 박스 크기 동일을 유지하면서 명시적 w=100%를 제거한다.
owjs3901
left a comment
There was a problem hiding this comment.
폰트에 라이센스 문제가 없는지 확인합시다, 만약 걱정되면 link 태그를 통해서 해결하면 좋을 것 같아요
| maskPosition="center" | ||
| maskRepeat="no-repeat" | ||
| maskSize="contain" | ||
| w={['17px', null, null, '28px']} |
| as="button" | ||
| bg={mode === key ? '$text' : 'transparent'} | ||
| border="1px solid $text" | ||
| borderRadius="9999px" |
There was a problem hiding this comment.
border-radius: 50%는 가로 반경이 폭의 절반, 세로 반경이 높이의 절반이라 가로로 긴 버튼에서는 타원이 됩니다. 저장소 기존 알약 버튼(components/home/PillButton.tsx)은 1000px을 쓰고 있어 우선 그 값으로 맞춰뒀습니다. 혹시 타원형으로 수정하는 바가 더 좋을까요?
| <MathTransInput | ||
| latex={latex} | ||
| onLatexChange={setLatex} | ||
| placeholder="수식을 입력하면 이곳에 수학 점자가 표시됩니다." | ||
| /> | ||
| <DemoArrow /> | ||
| <TransInput | ||
| blurPlaceholder={'예: 사분의 삼 → ⠼⠙⠌⠼⠉'} | ||
| focusPlaceholder={'예: 사분의 삼 → ⠼⠙⠌⠼⠉'} | ||
| readOnly | ||
| value={braille} | ||
| /> |
There was a problem hiding this comment.
이것만 따로 클라이언트 컴포넌트로 뺴는게 맞습니다
There was a problem hiding this comment.
반영했습니다. 입출력부를 MathTransPanel.tsx로 분리하고, MathTrans는 헤딩만 남기면서 'use client'를 뗐습니다.
| const braille = latex.trim() ? translateToUnicode(`$${latex}$`) : '' | ||
|
|
||
| return ( | ||
| <VStack flex="1" gap={['16px', null, null, '30px']}> |
There was a problem hiding this comment.
flex 1 위 피드백과 같이 개선되어야 합니다
| export function normalizeFracBraces(latex: string): string { | ||
| let out = '' | ||
| let i = 0 | ||
| while (i < latex.length) { | ||
| if (latex.startsWith('\\frac', i) && !/[a-zA-Z]/.test(latex[i + 5] ?? '')) { | ||
| const [num, j] = readArg(latex, i + 5) | ||
| const [den, k] = readArg(latex, j) | ||
| out += `\\frac${num}${den}` | ||
| i = k | ||
| continue | ||
| } | ||
| out += latex[i] | ||
| i += 1 | ||
| } | ||
| return out | ||
| } | ||
|
|
||
| /** i 위치부터 LaTeX 인자 하나를 읽어 중괄호로 감싼 형태와 다음 인덱스를 돌려준다. */ | ||
| function readArg(latex: string, i: number): [string, number] { | ||
| while (latex[i] === ' ') i += 1 | ||
| if (latex[i] === '{') { | ||
| let depth = 0 | ||
| let j = i | ||
| do { | ||
| if (latex[j] === '{') depth += 1 | ||
| else if (latex[j] === '}') depth -= 1 | ||
| j += 1 | ||
| } while (j < latex.length && depth > 0) | ||
| // depth === 0 이면 짝이 맞는 '}' 를 j-1 에서 소비한 것이고, | ||
| // depth > 0 이면 닫는 중괄호 없이 끝난 것이라 내용을 j 까지 살린다. | ||
| const end = depth === 0 ? j - 1 : j | ||
| return [`{${normalizeFracBraces(latex.slice(i + 1, end))}}`, j] | ||
| } | ||
| if (latex[i] === '\\') { | ||
| let j = i + 1 | ||
| while (j < latex.length && /[a-zA-Z]/.test(latex[j] ?? '')) j += 1 | ||
| // 제어기호(\, \! 등)는 백슬래시 뒤에 글자가 없으므로 기호 한 글자를 포함시킨다. | ||
| if (j === i + 1 && j < latex.length) j += 1 | ||
| return [`{${latex.slice(i, j)}}`, j] | ||
| } | ||
| return [`{${latex[i] ?? ''}}`, i + 1] | ||
| } |
There was a problem hiding this comment.
normalizeFracBraces.ts로 분리했습니다. 파서라 회귀 테스트도 붙였고 bun test에서 돌아갑니다.
| // 바깥 Flex 는 padding 없는 flex 아이템으로, 출력측 TransInput 의 외곽 | ||
| // Flex(flex=1 h=100% w=100%)와 flex-basis 를 동일하게 맞춰 좌우 박스 너비를 | ||
| // 같게 한다. 실제 배경/여백은 안쪽 박스가 담당한다. | ||
| <Flex flex="1" h="100%" w="100%"> |
| bg="$containerBackground" | ||
| borderRadius={['16px', null, null, '30px']} | ||
| cursor="text" | ||
| flex="1" |
…ve-git#10 dev-five-git#11) - 전역 box-sizing:border-box 로 padding 이 flex-basis 를 어긋내지 않으므로 바깥 Flex 래퍼를 제거하고, 대신 minW=0 으로 콘텐츠 최소 폭 확장을 막는다. - 안쪽 Flex flexDirection=column 을 VStack 으로 교체. - oxlint 지적(prop 정렬, no-namespace) 정리.
…five-git#7) 세로 높이는 데모 안쪽 행의 h=[auto,500px] 하나가 결정하므로 그 위 체인 (DemoTabs 루트/tabpanel, Trans/MathTrans 루트)의 flex=1 은 전부 no-op 이었다.
…ve-git#3) DemoChrome 은 devup 린트 규칙(파일명=컴포넌트명)에 맞춰 DemoHeading.tsx / DemoArrow.tsx 로 분리했다.
브라우저에서 측정한 결과 래퍼 제거 시 좌우 박스가 538/458 로 어긋났다. flex-basis:0 이라도 flex 아이템의 border-box 크기는 padding 합보다 작아질 수 없어(좌우 40px x2 = 80px), padding 을 가진 아이템이 그만큼 기본 크기를 더 갖는다. box-sizing:border-box 로는 해결되지 않는 문제라 래퍼를 되살리고 주석을 정정했다. 같이 빠졌던 minH=25dvh 도 복구(모바일 121px -> 203px, 출력 박스와 동일).
…-git#9 dev-five-git#10) - dev-five-git#5 탭 borderRadius 를 50% 로 변경 - dev-five-git#6 수학 데모의 입출력부를 MathTransPanel 클라이언트 컴포넌트로 분리, MathTrans 는 헤딩만 남기고 use client 제거 - dev-five-git#9 dev-five-git#10 MathTransInput 의 flex=1 두 개 제거, 좌우 폭 분배는 호출부 (MathTransPanel 의 행)에서 selectors 로 지정
…dev-five-git#4 dev-five-git#5) dev-five-git#4 의 취지대로 호출부에서 alignItems=center 를 빼 자식이 기본값 stretch 로 펼쳐지게 했다. 덕분에 MathTransInput 루트의 h=100% w=100% 가 불필요해져 제거했고, 가운데 화살표만 alignSelf=center 로 유지한다.
지금 KaTeX 폰트는 모두 MIT 라이선스인데 재배포, 상업적 이용에 제약은 없고 저작권 고지 의무가 있어서 public/mathlive/LICENSE.txt에 출처와 라이선스 전문을 추가했습니다. |
Codecov Report✅ All modified and coverable lines are covered by tests.
🚀 New features to boost your workflow:
|
Changepacks |
개요
랜딩 페이지에 수학 점역 체험 데모를 추가하고, 기존 한글 점역 데모와 함께 '한글' / '수학' 탭 토글 하나로 통합했습니다. 사용자는 MathLive 화면 수식 키보드로 수식을 WYSIWYG 편집하고, 자동 생성된 LaTeX가 실시간으로 한국 수학 점자로 변환되는 것을 체험할 수 있습니다.
주요 변경
수학 점역 데모
mathlive@^0.110.0도입, MathLive 폰트를public/mathlive/fonts/에 self-host (braillify의 "외부 연결 없이 실행" 원칙 유지 — CDN 미사용)MathTransInput— MathLive<math-field>웹 컴포넌트 래퍼. SSR 회피(동적 import), 데스크톱에서도 가상 수식 키보드 노출(manual정책), 언마운트 시 키보드 자동 닫힘$...$로 감싸 기존 braillify WASMtranslateToUnicode에 전달 — 코어 엔진(libs/braillify) 무수정한글·수학 탭 통합
DemoTabs— '한글'/'수학' 탭 토글(기본 '한글'). WAI-ARIAtablist/tab/tabpanel, 좌우 화살표 키 이동 지원DemoChrome— 한글·수학 데모가 공유하는 헤딩/화살표 컴포넌트 추출세부 보정
\frac정규화: MathLive의 중괄호 생략 직렬화(\frac34)를 braillify가 인식하는\frac{3}{4}정규형으로 변환. 미종료 중괄호·제어기호 인자도 안전하게 처리검증
bun run build통과, 기존 테스트 스위트 14,165개 전부 통과(회귀 없음)학교→⠚⠁⠈⠬), 수학 변환(x²+1→⠭⠘⠼⠃⠢⠼⠁,¾→⠼⠙⠌⠼⠉), 탭 전환/화살표 키 이동, 가상 키보드 열림·닫힘, 다크 테마 가독성, 폰트 로컬 서빙(404 없음)알려진 후속 작업 (이 PR 범위 밖)
\frac34을 직접 분수로 인식하도록 일반화 — 현재는 랜딩측normalizeFracBraces로 경계에서 처리. 엔진 수정은 별도 서브시스템(Rust + PDF 근거 테스트)이라 분리함.