# mmo.editor — overview for AI code generation
`mmo.editor` is Marc Mouret's rich-text (WYSIWYG) editor: one [`.jhs`](../../../client/docs/mcp/JHS-Syntax.md)
custom element, ``, built on **mmo.client**, plus a small registry of JavaScript tools that make its
toolbar. It edits html with the browser's `contenteditable`; it has no block model and no json format of its own:
what goes in and comes out is plain, clean html.
Read `mmo.client`'s own overview first (the `mmo-client` skill): `` is an ordinary `.jhs`
`CustomShadowElement`, its styles are Simple CSS on the design tokens, and its JS files are bundled by
`MMO\client\JSCompiler` from their `MMO.provide()`/`MMO.require()` declarations (there is no Closure any more).
## What's here
- **`src/customElements/mmo-editor.jhs`** — the element, and a `` holding the few
document-level rules the editing needs (placeholder, selected image, table cell outlines). The element renders
that view once into `document.head`.
- **`src/js/editor.js`** — the `MMO.editor` namespace: the tool registry (`registeredTools`), the default toolbars
(`DEFAULT_TOOLS`, `INLINE_TOOLS`), the html sanitizer (`sanitize()`, driven by `ALLOWED_TAGS`/`ALLOWED_STYLES`),
selection helpers (`getRange`, `setRange`, `serializeRange`, `closest`, `closestBlock`) and the keyboard
helpers (`matchShortcut`, `shortcutLabel`: `Mod` is Ctrl, or ⌘ on a mac).
- **`src/js/History.js`** — `MMO.editor.History`, the undo/redo stack of one region (html + selection snapshots).
- **`src/js/Tool.js`** — the base classes: `MMO.editor.Tool`, `MMO.editor.CommandTool` (a `document.execCommand`),
`MMO.editor.PopoverTool` (a button opening a panel).
- **`src/js/tools/*.js`** — the tools (below).
- **`src/icons/editor-*.svg`** — the toolbar icons, added to the theme's svg sprite (``).
- **`src/bootstrap.php`** — only configuration: it adds the three asset globs above to `MMO\client\Theme`
(`?jhs`, `?js`, `?svg`). The package has no php class.
- **`demo/www`** — `http://localhost/MMO/master/libs/editor`: a field in a form (value, submit, reset, read only)
and the inline mode, with their events.
The git-tracked **`.mmo/`** folder is an older port of Editor.js (`Block/`, `BlockRenderer/`, `editorjs/`, ...). It
is not loaded (`mmo.json`'s `sources` is `src` only): historical reference, don't build on it.
## Using ``
```html
A title: one line, text formatting only
A block of the page
```
Attributes: `tools` (names separated by `,`, groups by `|`; default `MMO.editor.DEFAULT_TOOLS`), `readonly`,
`placeholder`, `upload-url`, `name`, `inline` (read once, at connection).
JS: `value` (get/set the clean html; `''` when empty), `readonly`, `region` (the region being edited),
`exec(tool, ...args)`, `command(name, value)`, `insertHTML(html)` (sanitized), `insertNodes(node)` (as is),
`insertFiles(files)`, `undo()`, `redo()`, `toggleSource()`, `edit(region)` / `stopEdit()` (inline mode).
It is a form-associated element: `FormData`, `form.reset()` and `disabled` fieldsets work.
Events: `input` (every change), `change` (a field losing the focus changed; inline: a region stops being edited
changed, `event.detail = {region, value}`), `edit` (inline: a region starts being edited, `detail.region`).
Behaviour worth knowing:
- The content stays in the **light dom**: the page's css styles it (true WYSIWYG) and `window.getSelection()`
works. The toolbar and the panels are in the shadow root.
- The element is upgraded before its children are parsed: regions are set up in `domReady()`. A `value` set
before that is kept and applied then.
- Everything that comes in is sanitized (`MMO.editor.sanitize`): initial content of a field, `value`, paste,
drop, source view. Kept: `p h1-h6 blockquote pre ul ol li b i u s sub sup code mark span a img hr br table…`;
`style` only for `text-align`, an image `width`, and `color`/`background-color` **as design tokens**
(`var(--mmo-color-…)`); `href`/`src` only `http(s)`, `mailto`, `tel`, relative, or `data:image/…` for images.
The inline mode does **not** sanitize the page's regions when they start being edited (they are the page's own
markup), only what is pasted into them.
- Undo/redo is the editor's own (`MMO.editor.History`), not the browser's: Ctrl+Z, Ctrl+Shift+Z, Ctrl+Y and the
context menu all go through it. Typing is grouped until a 600ms pause.
- Markdown-like shortcuts at the start of a paragraph: `# `…`#### `, `- `/`* `, `1. `, `> `, ```` ``` ````.
- Tab nests a list item (Shift+Tab un-nests), moves between table cells (adds a row at the end).
- Images: toolbar (file or url), paste, drop. With `upload-url`, the file is POSTed (multipart field `file`) and
the json answer's `url` (or `data.url`, `data[0].url`, `location`) replaces the local preview; without it, the
image is embedded as a `data:` url. Clicking an image selects it (Delete removes it), double-clicking opens the
image tool (description, width).
## The tools
| name | what | shortcut |
|---|---|---|
| `undo`, `redo` | history | Mod+Z, Mod+Shift+Z |
| `format` | paragraph / heading 1-4 / code block (a `