A React editor component for Japanese classical texts with syntax highlighting and line numbers
npm install koji-editorA React editor component for Japanese classical texts with syntax highlighting and line numbers.
- Vertical and Horizontal Writing Modes: Supports both vertical-rl and horizontal-tb writing modes
- Syntax Highlighting: Uses CSS Custom Highlight API for efficient highlighting of:
- Furigana (reading aids)
- Kaeriten (return marks)
- Okurigana (inflectional kana)
- Annotations
- Block and inline tags
- Line Numbers: Optional line number display with support for:
- Logical lines (based on \n delimiters)
- Visual lines (horizontal mode only, based on word wrapping)
- Dynamic sizing for wrapped lines
- ContentEditable: Native browser editing with enhanced paste handling
``bash`
npm install koji-editor
`tsx
import { KojiEditor } from 'koji-editor';
import 'koji-editor/style.css';
function App() {
const [text, setText] = useState('');
return (
srcInput={text}
showLineNumbers={true}
lineNumberMode="logical"
onInput={(editor) => setText(editor.text)}
style={{ width: '600px', height: '400px' }}
/>
);
}
`
- writingMode?: 'vertical' | 'horizontal' - Text direction (default: 'vertical')srcInput?: string
- - Initial text contentdisabled?: boolean
- - Disable editingstyle?: React.CSSProperties
- - Container styles
- showLineNumbers?: boolean - Display line numbers (default: false)lineNumberMode?: 'logical' | 'visual'
- - Line numbering mode (default: 'logical')'logical'
- : Number lines based on \n delimiters'visual'
- : Number lines based on visual wrapping (horizontal mode only)
- errors?: KojiParseError[] - Error highlightshighlights?: Array<{ start: number; end: number; className?: string }>
- - Custom highlights
- onInput?: (editor: EditorObject) => void - Called when text changesonFocused?: (editor: EditorObject) => void
- - Called when editor gains focusonBlurred?: (editor: EditorObject) => void
- - Called when editor loses focusonSelectionChange?: (editor: EditorObject) => void
- - Called when selection changes
All callbacks receive an EditorObject with:
`typescript`
{
text: string;
tokens: KojiToken[];
selection: { start: number; end: number; direction?: 'forward' | 'backward' | 'none' };
isFocused: boolean;
isDisabled: boolean;
writingMode: 'vertical' | 'horizontal';
errors: KojiParseError[];
}
For imperative control, you can use a ref to access editor methods:
`tsx
import { useRef } from 'react';
import { KojiEditor, KojiEditorRef } from 'koji-editor';
function App() {
const editorRef = useRef
const insertAtCursor = () => {
editorRef.current?.insertText('挿入テキスト');
};
return (
<>
>
);
}
`
#### Available Ref Methods
- getEditorObject(): EditorObject - Get current editor statesetText(text: string): void
- - Set editor textsetSelection(start: number, end: number): void
- - Set selection rangefocus(): void
- - Focus the editorblur(): void
- - Blur the editorgetText(): string
- - Get current textgetTokens(): KojiToken[]
- - Get tokenized contentgetSelection(): { start, end, direction }
- - Get current selectioninsertText(text: string): void
- - Insert text at cursor positionreplaceText(start: number, end: number, text: string): void
- - Replace text range
Note: Using ref methods will trigger the onInput callback with the updated editor state.
- Requires CSS Custom Highlight API support (Chrome/Edge 105+, Safari 17.2+)
- Visual line mode uses Range.getClientRects() (not supported in Firefox vertical mode)
`bashInstall dependencies
npm install
MIT