mirror of
https://github.com/nihonbuzz/nihonbuzz-academy.git
synced 2026-01-27 02:41:58 +07:00
feat: implement Phase 7 (Course Player v2, Furigana, XP System, Integrated Vocab)
This commit is contained in:
48
resources/js/lib/furigana.tsx
Normal file
48
resources/js/lib/furigana.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
|
||||
/**
|
||||
* Parses a string with Japanese Furigana format {kanji|reading}
|
||||
* into HTML <ruby> tags.
|
||||
*/
|
||||
export function parseFurigana(text: string): React.ReactNode[] {
|
||||
if (!text) return [];
|
||||
|
||||
const regex = /\{([^|]+)\|([^}]+)\}/g;
|
||||
const parts = [];
|
||||
let lastIndex = 0;
|
||||
let match;
|
||||
|
||||
while ((match = regex.exec(text)) !== null) {
|
||||
// Add text before match
|
||||
if (match.index > lastIndex) {
|
||||
parts.push(text.substring(lastIndex, match.index));
|
||||
}
|
||||
|
||||
// Add ruby tag
|
||||
const [fullMatch, kanji, reading] = match;
|
||||
parts.push(
|
||||
<ruby key={match.index} className="ruby-text">
|
||||
{kanji}
|
||||
<rt className="text-[0.6em] opacity-80">{reading}</rt>
|
||||
</ruby>
|
||||
);
|
||||
|
||||
lastIndex = regex.lastIndex;
|
||||
}
|
||||
|
||||
// Add remaining text
|
||||
if (lastIndex < text.length) {
|
||||
parts.push(text.substring(lastIndex));
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
interface FuriganaTextProps {
|
||||
text: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const FuriganaText: React.FC<FuriganaTextProps> = ({ text, className }) => {
|
||||
return <span className={className}>{parseFurigana(text)}</span>;
|
||||
};
|
||||
Reference in New Issue
Block a user