All plugins / gogoga Table

gogoga Table

Notion-style tables: click a cell to edit, merge, sort, status columns. Still plain Markdown.

v0.8.4In community directoryMIT

Install

  1. Open Settings → Community plugins and turn off Restricted mode.
  2. Click Browse and search for gogoga Table.
  3. Click Install, then Enable. Check for updates on the same page.

The directory downloads files from GitHub. If it hangs or fails, use the offline package instead.

Tables that look and feel like Notion or Feishu docs: click a cell to edit, color cells and resize columns in a click or a drag. Files stay plain Markdown tables, so they read fine without the plugin, on mobile and on GitHub.

The interface follows Obsidian's language setting (English and Simplified Chinese). Works on desktop and mobile.

Usage

It works as soon as it's on: Markdown tables in Live Preview and Reading view become gogoga tables, with no new syntax to learn.

  • Edit: click a cell to select it and just type to replace it; double-click or press Enter to edit the existing text. While editing, Enter finishes and moves down, Shift+Enter adds a line break inside the cell, Tab / Shift+Tab move sideways, Esc cancels. Tab in the last cell adds a row.
  • Selected cell: arrow keys move, Delete clears, ⌘Z / ⌘⇧Z undo and redo (same history as the editor). Moving up from the first row, down from the last, or pressing Esc puts the cursor back in the text around the table.
  • Select a range: drag across cells, Shift+click, or Shift+arrow keys. Color, align or clear (Delete) a whole range at once; right-click inside a range to act on all of it, and Esc goes back to a single cell.
  • Copy and paste: ⌘C / ⌘X copy the selected cells as tab-separated text (Excel, Numbers) plus a styled HTML table (backgrounds, text colors, bold, alignment, widths, merges) that keeps its look in Feishu, Word or email; pasting back into a gogoga table uses the Markdown source, so links and bold survive. ⌘V pastes tables copied from Excel, Feishu or web pages, tab-separated text, or Markdown table source, starting at the selected cell and adding rows and columns as needed; copy one cell and paste over a range to fill every cell.
  • Paste to create a table: paste a table copied from Excel, WPS, Numbers, Feishu, Google Sheets or a web page into your note and it becomes a table, with the first row as the header and blank lines added around it. This only happens when the clipboard holds just a table (at least 2 rows and 2 columns); inside code blocks, math and frontmatter it pastes as plain text.
  • Merge cells: select a range and right-click → Merge cells; the merged cell shows all their text and nothing is lost; unmerging gives each cell its own text back. Right-click a merged cell → Unmerge cells. Inserting rows or columns inside a merged area grows it, deleting shrinks it.
  • Add rows and columns: hover the table and use the plus buttons on the right and bottom edges.
  • Row and column handles: hover a cell to show handles on its row's left edge and its column's top edge. Drag a handle to reorder rows or columns (backgrounds, widths and merges move along); click it for the row / column menu: insert, move, color the whole row or column, delete; the column menu also has alignment and auto width.
  • Right-click a cell: insert rows and columns, alignment, background, clear, delete.
  • Column width: drag the right edge of a header cell; double-click it to go back to auto.
  • Backgrounds: gray, red, orange, yellow, green, blue and purple, taken from your theme's colors and softened, so they work in light and dark mode.
  • Fill handle: drag the small square at the bottom-right of a selection to continue a series down or right: numbers count up, numbered text (Item 1), dates, weekdays and months continue, anything else is copied; hold ⌥ to always copy. Dragging past the edge adds rows or columns.
  • Table menu (top-left corner): style for this table (Default, Zebra, Minimal, Three-line) and row spacing, first column as header, align the whole table, distribute columns evenly, fit to page width, auto width for all columns, clear all colors.
  • Sort: from the column menu, A→Z or Z→A; numbers by value, dates by time, Chinese by pinyin, empty cells last; a total row stays put.
  • Duplicate and insert many: Duplicate row / column in the row and column menus; select several rows (or columns) and insert to add that many at once.
  • Checkboxes: [ ] or [x] in a cell becomes a clickable checkbox; Space toggles a selected one; right-click → Turn into checkbox.
  • Text color: the row of "A" swatches under the backgrounds in the right-click menu.
  • Total row: column menu → Total → Sum, Average, Count, Max or Min adds a "Total" row at the bottom that updates as the data changes; new rows go above it.
  • Status columns: column menu → Use as status column turns the values into colored labels, offers existing statuses while editing, and gives new ones a color; right-click a status to recolor it everywhere.
  • While editing a cell: ⌘B bold, ⌘I italic, ⌘⇧X strikethrough, ⌘⇧H highlight, ⌘K link; type [[ for note links and # for tags. Obsidian's editor shortcuts never touch the note around the table while you're in it.
  • Commands: Insert table (pick the size on a grid), Convert selected text (CSV or tab-separated) to table, and row/column insert, duplicate, delete, sort, merge, align and more, all in the command palette and bindable to hotkeys.
  • Long and wide tables: the header sticks to the top as you scroll down, and a soft shadow on either side shows when a wide table can scroll sideways.
  • Mobile: tap a cell to edit, long-press for the menu, swipe to scroll as usual; after tapping a cell its row and column handles appear, and you can drag them with a finger.
  • Bold, links, [[link\|alias]], tags and math render inside cells, and links open on click.

Settings

  • Enhance Markdown tables (on by default): turn off to go back to Obsidian's own tables.
  • Style: Default (Notion-like: square corners, faint lines, a light header), Zebra, Minimal.
  • Row spacing: Comfortable, Compact.

What's stored in your notes

The table is a standard GFM table, with alignment in the standard :---: form. Column widths, backgrounds and merged cells, which Markdown can't express, go in one HTML comment right below the table:

| Plan | Price | Storage |
| :--- | :---: | ---: |
| Basic | $1 | 5 GB |
<!-- gogoga-table: {"w":[120,null,200],"bg":{"B2":"yellow"},"merge":["A3:B3"]} -->
  • Elsewhere, merged cells show as ordinary cells: the top-left one has the text and the rest are empty, so nothing is lost.
  • Cells are addressed like Excel: columns A, B, C, and row 1 is the header. Inserting, deleting or moving rows and columns updates the comment.
  • Other editors don't show the comment, and in Obsidian the plugin hides it. It sits below the table because a comment directly above stops Obsidian's own Live Preview from recognizing the table.
  • No comment is written when there are no widths or colors. If the comment is broken or removed, the table still shows, just without widths and colors.
  • Tables padded with spaces stay aligned after edits (CJK characters count as two columns), and tables without outer pipes are written back without them.

Performance

Summary

  • Tables up to a few hundred rows (a few thousand cells) are smooth: on 200 rows × 10 columns (2,000 cells), everything takes under 0.3 s, and selecting a cell or pressing an arrow key takes about 20 ms.
  • Tables with tens of thousands of cells open, scroll, select and take cell edits fine, but structural changes are slow: on 1,000 rows × 20 columns (20,000 cells), opening takes about 0.4 s, selecting about 0.15 s and editing a cell about 0.1 s; inserting a row, sorting or undoing takes 0.5–10 s. Most of that is Obsidian's own native table, which is just as slow without this plugin (see "Bottlenecks" below).
  • Recommendation: keep a table to a few thousand cells. For more data, split it into several tables, or use Obsidian Bases or a CSV file.

Stress test results

Measured in Obsidian 1.15 (macOS, Apple Silicon) with real mouse and keyboard events, from the input event to the next painted frame.

Action 200 rows × 10 columns 1,000 rows × 20 columns
Open the note until the table is drawn 0.05 s 0.4 s
Switch to Reading view 0.1 s 0.7 s
Select a cell 0.02 s 0.15 s
Move with an arrow key 0.01 s 0.1 s
Select 50 rows 0.01 s 0.1 s
Crosshair following the mouse — 0.06 s
Longest frame while scrolling 0.02 s 0.09 s
Edit a cell and write it back 0.1 s 0.1 s (2–3 s for the first edit within seconds of opening the note)
Insert a row 0.15 s 3.2 s
Sort by a column 0.1–0.26 s 3.4–10.5 s
Undo 0.2 s 0.5–14 s

The same 1,000 × 20 table without this plugin, with changes of the same size made to Obsidian's native table:

Change Native table
Change a few characters in one cell 0.16–3.1 s
Insert a row 3.1–3.4 s
Reorder all body rows (like sorting) 0.07–11 s

In 0.4.0 and earlier, the same 1,000 × 20 table took 1.6 s to open, 2.4 s to switch to Reading view, 0.2 s to select a cell and up to 9.5 s to undo. This version adds these optimizations:

  • Plain-text and number cells are shown directly instead of going through Markdown rendering one by one.
  • Selecting, arrow keys and the crosshair update only the cells that changed.
  • The crosshair is drawn as bands over the table instead of a style on each cell.
  • Writing back to the note changes only the characters that changed instead of replacing the whole table, so Obsidian's native table updates just that cell instead of rebuilding: editing a cell on a 20,000-cell table goes from about 3 s (over 10 s at worst) to about 0.1 s.

The table processing itself is fast: on 2,000 rows × 20 columns, parsing, writing back, inserting, moving and sorting each take a few milliseconds, and finding every table in a note with 200 tables takes about 3 ms.

Bottlenecks and limits

  1. Obsidian's own native table (the main reason edits are slow). In Live Preview, Obsidian builds its own table object for every table, even when this plugin's table covers it and it is never shown. When the table text changes:

    • If every change falls inside a single cell, it updates only those cells. (Cell edits in this plugin write back only the changed characters, so they take this path.)
    • Inserting or deleting rows, sorting or replacing the whole table makes it rebuild the entire table right away.

    On a 20,000-cell table that takes 3–10 s, and it varies a lot depending on whether Obsidian has finished parsing the whole note. It happens without this plugin too: that is the native table's own speed. Obsidian skips the rebuild in only two cases: changes made by its own table editor (which carry an internal marker), and tables containing a search highlight. Both are Obsidian internals that plugins can't reach. Relying on them would break the plugin when Obsidian updates, possibly to the point of tables not showing at all, so this plugin doesn't.

  2. Selecting and arrow keys take about 0.1 s in big tables. Selecting a cell makes the browser lay out and repaint the whole table, which alone takes tens of milliseconds on 20,000 cells. The hidden input that receives typing has to move into the selected cell, so that the IME candidate window shows up in the right place, and that move triggers a relayout of the whole table.

  3. Every row is drawn. There's no rendering of only the visible rows, so bigger tables take longer to open and to switch views, roughly 20 ms per 1,000 cells. The same goes for Reading view.

Running the stress tests

  • The processing stress test is scripts/tests/perf.test.ts. It runs with npm test (and in CI), with generous limits that only catch changes that make things several times slower.
  • The UI stress test (t_perf.py) lives in the e2e scripts outside this repository and runs inside Obsidian. It prints the timing table above, and turns the plugin off to time Obsidian's native table on the same note for comparison.

Current scope

  • An Advanced Tables formula comment (<!-- TBLFM -->) or a block id (^id) under a table is kept as is, with our comment after it, so formulas and block references keep working.
  • Tables at the start of a line, and tables indented under a list item (right after the item or after one blank line, every row with the same indentation). Tables in code blocks, quotes and callouts (lines starting with >), and indented text outside lists, are left to Obsidian.
  • A table directly after a paragraph (no blank line in between) is left to Obsidian.

Changelog

0.8.4
2026-11-12

Fixed

  • With the first column frozen in the Zebra style, every other row of the frozen column was see-through: columns scrolled underneath showed through it and the text overlapped. The frozen column is now opaque in every row.
  • When a selected range doesn't include the first column, its blue box now goes under the frozen column instead of lying on top of it.
0.8.3
2026-11-12

Changed

  • Adjusted how the PDF export sets column widths so the plugin passes the community plugin review. No change in behavior.
0.8.2
2026-11-12

Fixed

  • Export to PDF now prints tables the way they look in the note: cell colors, column widths, merged cells, the table style and alignment. Before, the PDF showed Obsidian's plain table. Handles, buttons and selection are not printed.
  • In the PDF, a table whose set column widths add up to more than the page is shrunk to the page width, keeping the columns' proportions, instead of being cut off on the right.
0.8.1
2026-11-11

Fixed

  • When a table (with its comment) is the last thing in a note, clicking below it now puts the cursor on a new line under the table. Before, the cursor landed at the end of the table's last row, and pressing Enter split the table from its comment: the <!-- gogoga-table … --> line showed up as text and the table lost its colors and column widths (#5).
  • When a table is at the end of a note and the file is changed from outside (sync, another plugin) starting at the table's end, the editor now picks up the change. Before, it could be mistaken for Obsidian reformatting the table and dropped, leaving the editor out of step with the file.
Show all 14 releases
0.8.0
2026-11-10

Added

  • Two new items in the table's corner menu, Indent (under the list item above) and Outdent (move out of the list). In Live Preview the table is drawn over its lines, so Tab can't indent it; now the whole table (with its comment) can be moved under the nearest list item above, becoming that item's note (in gogoga Mind Map, that node's note), or moved out after the list. ⌘Z undoes it.

Fixed

  • In reading view, an indented table written right below a list item (the way gogoga Mind Map stores node notes) is now drawn as a table instead of showing | a | b | source. Before, this only worked with a blank line between them.
  • Copying part of a colored text while editing a cell no longer pastes as a half <span …> tag, and Shift+Enter inside colored text keeps each line complete.
0.7.0
2026-11-10

Added

  • Show formatting while editing a cell setting (off by default): the cell editor becomes a CodeMirror editor like gogoga Mind Map's node editor — bold, italic, text colors, highlighter colors and underline show as formatted while you type, tags like <span style=…> stay hidden and are kept paired when you delete text, and long colored text no longer turns into a wall of tags. Typing or using an input method on a selected cell still starts editing right away. The editor is only created for a table when you first select one of its cells.

Changed

  • Drag handles work like native tables (#2): the row handle appears when the mouse is in the first column, the column handle when it's on the header row, instead of on every hovered cell. Handles hide while scrolling and come back when the mouse moves, so they no longer jump with the sticky header or lag behind the row under the mouse.

Fixed

  • The sticky header no longer shakes when scrolling quickly with a trackpad (#2), for example when scrolling up from a table further down into a long table. Tables that don't scroll sideways now use the browser's native sticky positioning, which stays put while the editor redraws content during the scroll; wide tables move the header in whole device pixels. With the header stuck to the top, the column handle shows fully inside the header instead of being cut in half.
  • In reading view, the table menu button and the row handle are no longer cut in half on the left: Obsidian's table wrapper used to clip everything outside the table border. Tables that don't scroll sideways now also stick their header natively in reading view.
  • Reading view tables are taken over again when Obsidian passes an empty note text to plugins (seen in a real vault after reloading): the text is read from the open note instead, so tables don't silently stay native.
  • A table inside a list item could lose its indent in Live Preview and line up with the left margin instead of the list text, when the same spot had held a top-level table before (for example after switching notes).
  • In reading view, tables far down a long note (rendered before Obsidian attaches them to the page) now get a sticky header too; before, the header stayed put once you scrolled to them.
  • When scrolling quickly, the sticky header no longer lets the text underneath show through along its top edge or between two header rows: headers of tables that can stick now always have an opaque background.
0.6.0
2026-11-09

Added

  • Format bar when selecting text in a cell setting (off by default): while editing a cell, selecting text shows the same bar as gogoga Mind Map — bold, italic, strikethrough, underline, highlight, text colors, highlighter colors and clear. It works in Live Preview and reading view. Mod+U now underlines the selected text while editing (<u>…</u>).

Changed

  • Deleting rows and columns follows the selection (#4): after selecting several cells, the right-click menu (and the row / column handle menus) offers Delete 2 rows / Delete 3 columns and so on, instead of greying out Delete row and Delete column. The header row still can't be deleted, and at least one data row and one column are kept.

Fixed

  • With crosshair highlight on, the row highlight now grows with the cell when the text wraps while editing, instead of covering only the first line.
0.5.1
2026-11-09

Fixed

  • In notes with tables, clicking text below the tables could land on the next line, for example clicking the paragraph right above a heading selected the heading instead. Each table's top and bottom margin wasn't counted in its height, so every table shifted the lines after it by 18 px.
0.5.0
2026-11-08

Added

  • Paste a table copied from Excel, WPS, Numbers, Feishu, Google Sheets or a web page into your note and it becomes a table, with the first row as the header (#1). Only content that is just a table (at least 2 rows and 2 columns) is converted; inside code blocks, math and frontmatter it pastes as before. Undo once to get back.

Fixed

  • Long tables no longer jitter while scrolling: the sticky header used to trail one step behind every scroll and snap back. On desktop the browser now moves the header in the same frame as the scroll; older environments keep the previous behavior. (#2)
  • The sticky header now works in Reading view too; it used to stay at the top of the table there.
0.4.1
2026-11-08

Changed

  • Big tables are much faster: plain-text and number cells skip Markdown rendering, and selecting, arrow keys and the crosshair only update what changed. On a 1000 × 20 table, opening goes from 1.6 s to 0.4 s, undo from 9 s to 0.5 s, moving the selection from about 0.2 s to under 0.1 s, and switching to Reading view from 2.4 s to 0.6 s.
  • Editing a cell in a big table is much faster: writing back changes only the characters that changed instead of replacing the whole table, so Obsidian's own native table updates just that cell instead of rebuilding it. On a 1000 × 20 table, editing a cell goes from about 3 s (over 10 s at worst) to about 0.1 s.
0.4.0
2026-11-08

Added

  • Multi-row headers: in the table's top-left menu, set Header rows to 2 or 3. Those rows are drawn as the header and stick together at the top, and sorting, totals and fill skip them, which suits grouped headers such as "Q1" over "Jan Feb Mar". Inserting or deleting rows inside the header adjusts the count, and merges can't cross the line between header and body. The file keeps the first row as the Markdown header and stores the count in the comment below the table; without the plugin the other rows show as ordinary rows.
  • Freeze the header column: with First column as header on, the menu gains Freeze header column, which keeps the first column pinned on the left with a shadow along its edge while the table scrolls sideways. Turning the header column off removes the freeze too.
  • Crosshair highlight (in settings, off by default): selecting a cell tints its whole row and column so large tables are easier to follow; On selected and hovered cells follows the mouse as well.

Changed

  • When a wide table scrolls sideways, the cut-off side now fades out. The old grey shadow sat a little inside the actual edge, leaving part of a column showing past it, which looked unfinished.
0.3.0
2026-11-07

Added

  • Delete table in the menu of the table button (top-left corner): removes the whole table along with its comment line; ⌘Z brings it back in Live Preview.
0.2.0
2026-11-07

Added

  • Tables indented under a list item (how gogoga Mind Map stores a table under a node) now become gogoga tables too. Obsidian doesn't render them in Live Preview, only the source, and in Reading view a table written right under the list item shows as plain text; now both views show a table aligned with the list item's text that you can edit, and write-back keeps each line's indentation.

Fixed

  • Giving header cells a background (click the header row's handle → Background, or select header cells) had no effect: the header's default light gray covered it, also with the Minimal and Three-line styles and while the header was stuck to the top. Header colors now show, sticky header included.
  • After scrolling a wide table sideways, the row handle and the table button in the top-left corner scrolled out of sight with it. They now stay at the visible left edge, and hide when their row or column is scrolled out.
0.1.0
2026-11-06

Added

  • First version: Markdown tables in Live Preview and Reading view become Notion-style tables. Click a cell to edit, Enter / Tab to move, add rows and columns, row and column handles plus a right-click menu, drag to resize columns, seven cell backgrounds, three styles and two row spacings; on mobile, tap to edit and long-press for the menu. Select a range to color, align or clear it at once; copy and paste with Excel, Feishu and the web; merge cells; drag row and column handles to reorder; sticky headers on long tables and scroll hints on wide ones. Fill handle; a per-table corner menu (style, three-line style, header column, align all, distribute or fit widths); sort by column; duplicate rows and columns and insert many at once; checkboxes; text colors; total rows; status columns; formatting keys plus [[ link and # tag completion while editing; Insert table and Convert text to table commands. Styled HTML copy. Coexists with Advanced Tables formulas and block ids. Files stay plain Markdown tables, with widths, colors, merges and more in one comment below the table.