API des plugins
Un plugin de bloc est une seule déclaration couvrant toutes les surfaces qu'un bloc touche : son schéma, sa vue et chacune de ses projections. Cette totalité est délibérée — un bloc ne doit pas pouvoir s'afficher sans dire comment il survit à un export.
BlockPlugin
| Nom | Type | Description |
|---|---|---|
| apiVersion* | 1 | The plugin contract version this was written against. Checked at registration, so a plugin from a future contract fails loudly by name instead of misbehaving. It also lets v1 and v2 plugins run side by side during a migration, rather than every author breaking on one flag day. |
| autoformat | AutoformatRule[] | Markdown shortcuts that turn a paragraph into this block as you type — `\`\`\`` for code, the way `- ` makes a list. Consulted before the built-in table, so a plugin may claim a prefix. It lives on the model half rather than the view because autoformat is a core command: a headless host applying an edit gets the same behaviour. |
| html | function | Static HTML for export and server rendering. Returns a string rather than a live element, so it runs with no DOM and the same block renders identically in a CLI, on a server and in a browser. |
| normalize | function | Document invariants this block type repairs, run on every transaction that changed structure. The extension point a table forced into existence, and the one a block with *internal* structure cannot do without: a row that lost a cell, a container left empty, a span pointing at a row that no longer exists. It runs on the model, so a headless import is normalized exactly like a keystroke — ProseMirror's `fixTables` is the same idea, exposed as a command because its plugins cannot reach the state's apply loop. Write it as a *repair*, not a validation: read the doc, emit the ops that make it legal through `tx`, return whether you emitted any. It must be idempotent — it will see its own output on the next transaction. |
| schema* | BlockSpec | The block's declarative description: type, version, whether it carries inline text, its default props. JSON-serializable and free of behaviour on purpose. The static renderer and a future Swift port consume it without executing any JavaScript, which they could not do if rendering functions lived inside it. |
| view | unknown | Editing-surface behaviour. Lives in the `@nbe/dom` layer, so it is typed as unknown here and refined there — `core` must never depend on the DOM. |
MarkdownProjection
Les deux directions sont requises, et c'est le point : n'implémenter que la sérialisation, c'est écrire un bloc qui se dégrade silencieusement au réimport. Quand un format ne peut vraiment pas représenter un bloc, on le déclare avec lossy() plutôt que d'omettre la fonction.
| Nom | Type | Description |
|---|---|---|
| fromMarkdown* | MarkdownRule[] | Recognise this block in markdown. Consulted in precedence order, and the first matching rule wins. |
| lossyReason | string | Set when this format cannot represent the block faithfully. Read by tooling and by the docs table — never at runtime — so the loss is discoverable instead of discovered. |
| toMarkdown* | string[] |
Fonctions
at
at(precedence: Precedence, value: T): Ranked<T>Tag a contribution with a precedence.
Paramètres
precedence: Precedence— Which category this contribution belongs to.value: T— The contribution itself.
Retourne
Ranked<T>
keys: { Enter: at('high', handleEnterInsideTable) }byPrecedence
byPrecedence(items: T | Ranked<T>[]): T[]Sort contributions by category, then by the order they were registered in.
Paramètres
items: T | Ranked<T>[]— Contributions, tagged or not.
Retourne
T[]
lossy
lossy(reason: string, fallback: function): MarkdownProjectionDeclare that a format cannot represent this block faithfully.
Paramètres
reason: string— What this format cannot carry, in one sentence. Surfaced in the documentation rather than read at runtime.fallback: function— What to emit instead.
Retourne
MarkdownProjection
markdown: lossy('les colonnes sont aplaties', (b) => [`<!-- ${b.type} -->`])PluginRegistry
Par éditeur, jamais globale au module. Deux éditeurs sur une même page est la deuxième démo qu'on écrit, et un registre global rend impossible d'y avoir des jeux de blocs différents.
all
all(): BlockPlugin[]Every registered plugin, for building the schema or a projection table.
Retourne
BlockPlugin[]