Index
# 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

The initial 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 `