Table
Description
- Pressing the button opens a size grid (up to 8×8) instead of a toggle. It inserts a table with a header row and moves the caret into the first cell.
- Commands appear in the context row only while the caret is inside a table: insert row above/below, delete row, insert column left/right, delete column, header this row, header this column, delete table — plus merge cells and split cell.
- Header row/column apply to the line the caret is in — not a fixed first row or column. With cells selected, every line the selection covers is affected. Press again to turn it back.
- Press a cell and drag onto another cell to select a rectangle of cells; their background tints. Merge cells joins the rectangle into one cell — contents are joined with line breaks, empty cells are skipped. With the caret in a merged cell, split cell restores the covered slots as empty cells. Non-rectangular (L-shaped) selections never offer merge.
- Cells can be selected from the keyboard too — the same rules as Excel.
Shift+Arrowgrows the rectangle,Ctrl+Arrow(Cmdon macOS) jumps to the edge of the table and drops the selection, andCtrl+Shift+Arrowextends all the way to the edge.Cmdcounts the same asCtrlbecause macOS takesCtrl+Arrowfor Mission Control. These only bind inside a table cell, so they behave normally in body text. Tabmoves to the next cell,Shift+Tabto the previous. ATabat the very end of the table is left alone. Arrow keys move by grid, not by screen position — screen coordinates slide into the wrong column when cell widths differ.- Cell
colspanandrowspansurvive — merges are stored as the standard attributes that mean exactly that. Everything else (border,width,class) is dropped. Nested tables are not supported. Broken grids (ragged rows, spans past the edge) are repaired into a gap-free grid: spans are clamped and uncovered slots are filled with empty cells.theadandtfootare folded into the firsttbody. - Header row and header column are the cells of that line retagged as
th— there is no separatethead. - Borders, cell padding and header backgrounds are not frozen into the value. They belong to the sheet, so the host needs
nabi.css(or its own table CSS) for lines to show. - The table itself is an object block but its cells hold text. When the caret touches it from outside it enters the first cell of that edge row instead of selecting the whole table — the top row coming down, the bottom row coming up, both at the left. Inside a cell the toolbar keeps marks only.
- Object blocks placed inside a cell (image, divider, code) are hoisted out of the table by the filter.
Sortable tables — a viewer-side feature
Toggle sorting in the context row puts a single data-nabi-sortable marker on the table. That marker is all that is stored — the editor only shows an "it's on" badge in the top corner, and the real sort buttons appear on the viewing side: the preview, and any host page with nabiViewer attached.
- Every cell of the header row (the first row) gets a button cycling three states — original (gray) → descending (▼) → ascending (▲) → original again. Clicking another column starts it at descending and returns the previous column to original.
- A column of pure numbers sorts numerically —
9comes before10. Thousands commas, decimals and negatives are recognized. Mixed content ($1,234) makes it a text column. The choice is made once per column, not per pair of cells — that is what keeps the order always consistent. - Empty cells go last in both directions. Rows with equal values keep their relative order (stable sort).
- The sort state is viewer state, not document state — a refresh returns to the original order, and
getHtml()contains neither buttons nor a changed row order. - Sorting and merged cells cannot coexist in one table. Merging drops the marker on the spot, the filter strips it from any HTML that arrives with merges, and if it still survives (hand-written HTML) the viewer refuses to build buttons.
Demo
Wings
HTMLLoading the editor…
PreviewThe value above, drawn the way a reader sees it (nabiViewer). Click a table header to sort.
Install
npm install nabi-noteCode
import { nabi } from 'nabi-note'
import 'nabi-note/style.css'
nabi.create('#editor', {
wings: [],
locale: 'en',
onChange: (html) => save(html),
})