halkyon/packages/halkyon_editor/README.md

65 lines
2.9 KiB
Markdown
Raw Normal View History

# halkyon_editor
Halkyon's rich text, shared by its apps: the document as an app keeps it, the
one editor and the one read-only view of it, built on
[`appflowy_editor`](https://github.com/AppFlowy-IO/appflowy-editor) (our fork,
pinned, as every app's), with their texts in British English, American English
and German. Moved out of Halkyon Learn on 6 Nov 2026, when Halkyon Todo took
editor documents too (ADR 0033, D37).
## Using it
An app installs `HalkyonEditorLocalizations.delegate` beside its other
delegates, and halkyon_ui's, whose sheets the Insert menu opens in.
```dart
// Stored: RichContent is the editor's document JSON and its format's version.
final content = RichContent.plain('Buy milk'); // or RichContent.empty()
content.plainText; // 'Buy milk'
content.isBlank; // false
final stored = content.toJson();
RichContent.fromJson(stored);
RichContentEditor(
initialContent: content,
onChanged: (content) => save(content),
formatBar: true,
);
RichContentView(content: content);
```
## What it holds
- **`RichContent`** (`lib/src/content/`): pure Dart, the document in JSON.
`content_blocks.dart` names every block's type and attributes across the
apps, for `plainText` and for what a block's type is called for good.
- **`RichContentEditor`, `RichContentView`** (`lib/src/editor/`): the editor,
with the `FormatBar` docked below it while it has the focus, copying and
pasting that keep the formats (`EditorClipboard`), links (`editLink`, Ctrl+K)
and superscript and subscript; the view, display only, taking the height of
its content.
- **`EditorBlocks`**: what an editor knows. `basicBlocks` is what it knows
without an app (the editor's own builders; headings, lists, a checklist, a
quote, a divider and a table to insert). An app adds its own blocks, and
passes them as `blocks:` or through `EditorBlocksScope`, with:
- `builders`, `insertable` (the Insert sheet and the desktop's `/` menu show
the same list) and `shortcuts`;
- `textMarks`, how marks of its own are drawn, each wrapping the one before
it, and `formatActions`, their buttons, after subscript;
- `onEditorClosed`, for what its text left outside the editor.
`plus` joins two sets, `offering` narrows what is offered and nothing else.
- **`AtomicBlock`, `BlockNotice`**: for an app's block taken whole, selected
and removed as one. A type nothing knows shows as needing a newer app, and
stays as it is.
`RichContentEditor`'s `wrapEditor` puts what an app adds around the editor
itself, knowing its state and focus (Learn's check of the spelling).
Editors are tested as in Learn: host one in a scrollable body with a slot of
fixed height, `pump(const Duration(seconds: 1))` after changes, and find its
text with `findRichText: true`.
## Licence
GNU Affero General Public License, version 3 or any later version
(`AGPL-3.0-or-later`), as the other packages of the apps; see [LICENSE](LICENSE).