koji-editor
v0.4.3
Published
A React editor component for Japanese classical texts with syntax highlighting and line numbers
Maintainers
Readme
Koji Editor
A React editor component for Japanese classical texts with syntax highlighting and line numbers.
Features
- Vertical and Horizontal Writing Modes: Supports both
vertical-rlandhorizontal-tbwriting 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
\ndelimiters) - Visual lines (horizontal mode only, based on word wrapping)
- Dynamic sizing for wrapped lines
- Logical lines (based on
- ContentEditable: Native browser editing with enhanced paste handling
Installation
npm install koji-editorUsage
import { KojiEditor } from 'koji-editor';
import 'koji-editor/style.css';
function App() {
const [text, setText] = useState('');
return (
<KojiEditor
writingMode="vertical"
srcInput={text}
showLineNumbers={true}
lineNumberMode="logical"
onInput={(editor) => setText(editor.text)}
style={{ width: '600px', height: '400px' }}
/>
);
}Props
Core Props
writingMode?: 'vertical' | 'horizontal'- Text direction (default:'vertical')srcInput?: string- Initial text contentdisabled?: boolean- Disable editingstyle?: React.CSSProperties- Container styles
Line Numbers
showLineNumbers?: boolean- Display line numbers (default:false)lineNumberMode?: 'logical' | 'visual'- Line numbering mode (default:'logical')'logical': Number lines based on\ndelimiters'visual': Number lines based on visual wrapping (horizontal mode only)
Highlighting
errors?: KojiParseError[]- Error highlightshighlights?: Array<{ start: number; end: number; className?: string }>- Custom highlights
Callbacks
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
EditorObject
All callbacks receive an EditorObject with:
{
text: string;
tokens: KojiToken[];
selection: { start: number; end: number; direction?: 'forward' | 'backward' | 'none' };
isFocused: boolean;
isDisabled: boolean;
writingMode: 'vertical' | 'horizontal';
errors: KojiParseError[];
}Ref API
For imperative control, you can use a ref to access editor methods:
import { useRef } from 'react';
import { KojiEditor, KojiEditorRef } from 'koji-editor';
function App() {
const editorRef = useRef<KojiEditorRef>(null);
const insertAtCursor = () => {
editorRef.current?.insertText('挿入テキスト');
};
return (
<>
<button onClick={insertAtCursor}>Insert Text</button>
<KojiEditor ref={editorRef} writingMode="vertical" />
</>
);
}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.
Browser Support
- Requires CSS Custom Highlight API support (Chrome/Edge 105+, Safari 17.2+)
- Visual line mode uses Range.getClientRects() (not supported in Firefox vertical mode)
Development
# Install dependencies
npm install
# Run Storybook
npm run storybook
# Build package
npm run buildLicense
MIT
