# TATE — Vertical Writing Mode for Obsidian An Obsidian plugin that brings authentic vertical writing (縦書き) to your notes. Renders and edits Japanese text in the traditional top-to-bottom, right-to-left layout — with smooth editing even on files with over a million characters. [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/T6T71YGS7B) [日本語版 README はこちら](README-ja.md) ## Features ### Ruby, Tate-chu-yoko, Emphasis Marks, and Headings via Aozora Notation The plugin supports the annotation syntax used by [Aozora Bunko](https://www.aozora.gr.jp/), a digital library of Japanese literature. | Notation | Renders as | |----------|------------| | `|東京《とうきょう》` or `東京《とうきょう》` (consecutive kanji) | Ruby (furigana) | | `2025[#「2025」は縦中横]` | Tate-chu-yoko (digits/latin rotated upright) | | `春[#「春」に傍点]` | Emphasis dots (sesame marks) | | `序章[#「序章」は大見出し]` | Large heading (bold, 1.3×) | | `第一節[#「第一節」は中見出し]` | Mid heading (bold, 1.2×) | | `はじめに[#「はじめに」は小見出し]` | Small heading (bold, 1.1×) | **Applying via Command Palette** Select text, open the command palette (`Ctrl+P` / `Cmd+P`), and run one of: - `Add ruby to selection (ruby)` - `Make selection tate-chu-yoko (tate-chu-yoko: tcy)` - `Add emphasis marks to selection (bouten)` - `選択テキストを大見出しに設定` - `選択テキストを中見出しに設定` - `選択テキストを小見出しに設定` All annotations are applied to the selected text range. If the selection already contains an existing annotation, the command is blocked and a notice is shown instead. **Removing Annotations** Run `選択範囲の青空記法を解除する` from the command palette to strip all Aozora annotations within the current selection, replacing each with its base text (for ruby, the reading is discarded and only the base characters remain). - If any part of an annotation overlaps the selection, the entire annotation is removed. - Works with a collapsed cursor: if the cursor is positioned inside or immediately adjacent to an annotation element, that annotation is removed — useful when inline expansion is suppressed. - Works with a document-wide selection (`Cmd+A` / `Ctrl+A`): all annotations in the file are removed in one step. - If no annotation is found in the current selection, a notice is shown. **Inline Editing** Moving the cursor into a ruby, tate-chu-yoko, emphasis mark, or heading element expands it into raw Aozora text in place — the same behavior as Obsidian's Markdown editor. Moving the cursor out collapses it back to the rendered form. Pressing **Enter** while an element is expanded also collapses it immediately. **Live Conversion** Typing an Aozora annotation in full and closing it with `》` (ruby) or `]` (tcy, bouten, headings) converts the notation to its rendered form on the spot, without using the command palette. ### Auto-indent and Typography Helpers Four independent settings refine how text is entered in the vertical view. All of them write actual full-width space characters (U+3000) into the file — not just visual CSS indentation. | Setting | What it does | |---------|--------------| | **Convert half-width space to full-width** | Replaces a typed half-width space (Space key) with a full-width space ` `. Applies everywhere except paste. | | **Auto-indent on input** | Inserts one full-width space at the start of a line when a character is typed there (covers both direct input and Japanese IME). | | **Match preceding paragraph indent** | When Enter is pressed to start a new paragraph, automatically inserts the same number of leading full-width spaces as the preceding paragraph. Works independently of the setting above. | | **Remove bracket indent** | When a full-width opening bracket (`「『(` etc.) is typed after leading spaces, removes one leading space — following traditional Japanese typography where brackets are not indented. | All four are on by default. ### Line-break Rules (Kinsoku) Controls which characters are forbidden at the start or end of a line (punctuation, brackets, etc.) via the CSS `line-break` property. | Rule | Description | |------|-------------| | `Normal` | Standard kinsoku rules (default) | | `Strict` | Strictest — small kana (っ, ゅ, etc.) are also kept from line starts | | `Loose` | Newspaper style — relaxed rules that favor tighter wrapping | | `Anywhere` | No restrictions — break anywhere | ### Incremental Search and Replace Open the search panel from the command palette: - **`検索 (search)`** — opens the panel with the search field focused. - **`置換 (replace)`** — opens the panel with the replace field expanded and focused. As you type in the search field, all matches are highlighted instantly and the nearest hit at or after your cursor position is focused. Use the ▶/▼ toggle button at the left of the panel to show or hide the replace field. **Search field focused** | Action | Key / Button | |--------|-------------| | Next hit | **Enter** or ↓ button | | Previous hit | **Shift+Enter** or ↑ button | | Close panel | **Esc** or × button | **Replace field focused** | Action | Key / Button | |--------|-------------| | Replace current hit and move to next | **Enter** or 置換 button | | Replace all hits at once | 全置換 button | | Close panel | **Esc** | **Tab** moves focus from the search field to the replace field (and back). When a match partially overlaps a ruby, tate-chu-yoko, emphasis mark, or heading annotation, the annotation is stripped and only the unmatched portion of the base text is preserved as plain text. Closing the panel restores the cursor to the last navigated hit, or to the position it was at when the panel was opened if no navigation occurred. ### Heading Outline Panel The outline panel lists all heading annotations in the current file in a dedicated sidebar and lets you jump to any heading with a single click. **Opening the panel** - Run `アウトラインパネルを開く` from the command palette (only available while the vertical writing view is open). - Or click the **tally-3 icon** (☰) in the vertical writing view's toolbar. **Navigation** Click any entry to move the cursor to that heading and bring the vertical writing view to the front. - Large headings are shown at the leftmost indent level (bold). - Mid headings are indented one level. - Small headings are indented two levels. **Live updates** The outline refreshes automatically whenever the file content changes. It clears when the vertical writing view is closed. ### Other Features - **Bidirectional real-time sync:** Edits and Undo/Redo operations stay in sync with the Obsidian Markdown view in real time. - **Character count in the status bar:** The character count (excluding Aozora notation) is displayed in the Obsidian status bar. - **Smooth editing on large files:** Input and Undo/Redo remain responsive even on large files. (On very large files there may be a brief lag before editing becomes available after the file finishes loading.) - **Cursor position persistence:** The cursor position is saved when a file is closed and automatically restored the next time it is opened. ## Installation (from source) 1. Clone the repository and build: ```bash git clone https://github.com/nekoe/obsidian-tate cd obsidian-tate npm install npm run build ``` 2. Copy the build output to your Obsidian plugins folder: ```bash cp main.js manifest.json styles.css {YOUR_VAULT_PATH}/.obsidian/plugins/tate/ ``` 3. Enable the plugin in Obsidian under **Settings → Community Plugins**. ## Usage - Run `縦書きビューを開く` from the command palette (`Ctrl+P` / `Cmd+P`). - The view opens as a tab and automatically loads the active file. - Edits are kept in sync with the underlying Obsidian file in both directions. ## Known Limitations - **IME input after annotation elements:** Placing the cursor immediately after a bouten, ruby, or heading element and entering text via IME may cause the composition text to temporarily appear inside the element (e.g. for bouten, with sesame marks applied). The text moves to the correct position once the input is confirmed. - **Deletion at ruby/tate-chu-yoko boundaries:** Pressing Delete or Backspace with the cursor placed at the very start or end of a ruby or tate-chu-yoko element does not delete the adjacent character. To delete, either select the text first, or expand the element inline and delete from within. - **Consecutive Aozora notation input:** Typing one Aozora notation immediately after another may cause the second notation to be inserted incorrectly or cursor movement to behave unexpectedly. - **Typing into a line-initial Aozora element:** When an Aozora notation element appears at the very start of a line, placing the cursor at the line beginning triggers its inline expansion automatically. Any characters typed while expanded are inserted inside the element, but once it collapses they are treated as plain text. ## Settings Configure under **Settings → TATE**: | Setting | Description | Default | |---------|-------------|---------| | Font family | Font used in the vertical view (CSS `font-family` syntax) | Hiragino Mincho ProN | | Font size | Font size in the vertical view (px) | 22 | | Convert half-width space to full-width | Replace typed space with full-width space ` ` | On | | Auto-indent on input | Insert one ` ` at line start when a character is typed | On | | Match preceding paragraph indent | On Enter, copy the indent of the paragraph above | On | | Remove bracket indent | Remove one leading ` ` when a full-width bracket is typed after spaces | On | | Line-break rule | Kinsoku rule set for line start/end restrictions | Normal | | Suppress ruby inline expansion | Do not expand ruby when cursor enters it (Experimental) | Off | | Suppress tcy inline expansion | Do not expand tate-chu-yoko when cursor enters it (Experimental) | Off | | Suppress bouten inline expansion | Do not expand emphasis marks when cursor enters them (Experimental) | Off | | Suppress heading inline expansion | Do not expand headings when cursor enters them (Experimental) | Off |