New: macros.ts with MacroDef, parseBlockMacro, matchInlineMacro,
buildMacroTags, processInlineMacros.
Macro syntax:
@user — bare, no args
@user() — empty parens, same as bare
@npc(Goblin King) — self-closing with args
@style(box center — block: no closing paren on first line
Content here. — content on subsequent lines
) — closing paren on its own line
Unknown macro names now render as an error:
<span class="ribbit-error">Unknown macro: @bogus</span>
The verbatim keyword causes the contents to render as literals and also
preserves line breaks.
New events with structured payloads:
change({ markdown, html })
Fires on every content edit.
save({ markdown, html })
Fires when editor.save() is called. Consumer handles persistence.
modeChange({ current, previous })
Fires on VIEW/EDIT/WYSIWYG transitions.
themeChange({ current, previous })
Fires when themes.set() switches the active theme.
ready({ markdown, html, mode, theme })
Fires after editor.run() completes first render.
Events can be registered in the constructor via the 'on' setting
or at any time via editor.on(event, callback) / editor.off().
202/202 tests passing.