# Modules

> Every block, mark, UI and AI module, with what it adds and what it weighs.

Each module below has its own page, generated from the module itself: the text is its JSDoc, the contract is read off the module object, the size is measured from the built package, and the acceptance criteria are the rows of the feature table it cites. None of it can drift from the code.

| Module | What it adds | JS gzip | CSS gzip |
| --- | --- | --- | --- |
| [blocks/paragraph](#/docs/modules/blocks/paragraph) | Paragraph — the one block type core ships with; every other type is a module. | core | — |
| [blocks/heading](#/docs/modules/blocks/heading) | Heading 1–3 — `level` prop; the element is recreated only when the level changes. | 0.56 KB | 0.16 KB |
| [blocks/todo](#/docs/modules/blocks/todo) | To-do — `checked` prop. The checkbox sits outside the editable region, so toggling it never moves the caret. | 0.79 KB | 0.55 KB |
| [blocks/list](#/docs/modules/blocks/list) | List item — bullets and numbers are one module: `ordered` switches a CSS counter, so numbering stays right after any reorder. | 0.52 KB | 0.29 KB |
| [blocks/quote](#/docs/modules/blocks/quote) | Quote — `<blockquote>`; `> ` input rule. Nested blocks sit inside its border. | 0.33 KB | 0.14 KB |
| [blocks/divider](#/docs/modules/blocks/divider) | Divider — a void `<hr>`, never editable; `---` input rule. | 0.29 KB | 0.12 KB |
| [blocks/code](#/docs/modules/blocks/code) | Code block — plain text in a `<pre>`; colours are painted with the CSS Custom Highlight API, so the editable region holds nothing but text and the caret behaves exactly as in plain text. | 2.23 KB | 0.51 KB |
| [blocks/table](#/docs/modules/blocks/table) | Table — a grid of per-cell editable blocks: the table's children are paragraphs laid out row by row, `cols` wide, on a CSS grid. | 2.47 KB | 0.69 KB |
| [blocks/chart](#/docs/modules/blocks/chart) | Chart — hand-written SVG line, bar, area and pie charts drawn from a table block: the first row names the series, the first column labels the points, the other cells are numbers. | 1.91 KB | 0.65 KB |
| [blocks/math](#/docs/modules/blocks/math) | Equations — LaTeX compiled to MathML that the browser renders itself: no JS renderer, no fonts. | 4.83 KB | 0.62 KB |
| [blocks/columns](#/docs/modules/blocks/columns) | Columns — a container of columns on a CSS grid; each column holds ordinary blocks, and blocks drag between columns like anywhere else (an empty column still takes a drop). | 0.63 KB | 0.25 KB |
| [blocks/image](#/docs/modules/blocks/image) | Image — an `<img>` block. Paste or drop image files, or choose them from "/image". | 0.93 KB | 0.17 KB |
| [blocks/embed](#/docs/modules/blocks/embed) | Embed — allow-listed providers (YouTube, Vimeo, Loom, CodePen, Spotify) play in a sandboxed `<iframe>` that loads only when clicked, so nothing third-party is fetched until then. | 1.27 KB | 0.51 KB |
| [marks/bold](#/docs/modules/marks/bold) | Bold — `<strong>`, ⌘B, `**text**`. Pasted HTML counts font-weight too (Google Docs wraps everything in `<b style="font-weight:normal">`). | 0.24 KB | — |
| [marks/italic](#/docs/modules/marks/italic) | Italic — `<em>`, ⌘I, `*text*` or `_text_`. | 0.22 KB | — |
| [marks/strike](#/docs/modules/marks/strike) | Strikethrough — `<s>`, ⌘⇧S, `~~text~~`. | 0.25 KB | — |
| [marks/code](#/docs/modules/marks/code) | Inline code — `<code>`, ⌘E, ``text``. Typing at its end continues as plain text. | 0.17 KB | — |
| [marks/link](#/docs/modules/marks/link) | Link — `<a href>` rendered with rel="noopener noreferrer"; every href is validated before it is committed (http, https, mailto, tel or relative). | 0.67 KB | — |
| [ui/slash](#/docs/modules/ui/slash) | Slash menu — "/" opens a menu built from `registry.slash`: every module contributes its own entries, so registering a module is all it takes to appear. | 1.36 KB | 0.49 KB |
| [ui/toolbar](#/docs/modules/ui/toolbar) | Selection toolbar — floats over a text selection with one button per registered mark. | 1.29 KB | 0.71 KB |
| [ui/dnd](#/docs/modules/ui/dnd) | Drag & drop blocks with Pointer Events — no HTML5 drag-and-drop, so it works with touch and the drop target is exact. | 1.84 KB | 0.47 KB |
| [ui/emoji](#/docs/modules/ui/emoji) | Emoji — type ":" and a name. The 1,900-emoji index is a static file fetched the first time a ":" is typed; it is never part of any bundle. | 0.31 KB | — |
| [ai/diff](#/docs/modules/ai/diff) | Word-level Myers diff: text is split into words, whitespace runs and punctuation, and the shortest edit script between the two token lists is found in O(ND). | 0.65 KB | — |
| [ai/pending](#/docs/modules/ai/pending) | AI edits as a reviewable diff. A proposal is a valid but uncommitted transaction: the document is untouched until you accept. | 1.57 KB | 0.64 KB |

```js module.js
import { Editor } from 'verbal-editor';
import heading from 'verbal-editor/blocks/heading';

// Everything on a module's page is read from objects like this one.
console.log(heading.type, Object.keys(heading.schema?.props ?? {}), new Editor({ blocks: [heading] }).registry.slash.length);
```
