Introduction
Welcome! And thank you for checking out boustro 😎
What is boustro?
Boustro is a rich text editor for Flutter.
About the documentation
This documentation is a work in progress. Greyed out chapters in the navigation bar have not yet been written.
If you want to try out boustro, for now, the best way to get started is to check out the example.
This documentation is built with mdBook.
Goals
Boustro aims to be an easy to use, fully-featured, but extremely flexible rich text editor.
The following are goals for Boustro:
- Pick and choose formatting and embed options.
- Fully customizable without touching the source code.
- Built-in formatting options and paragraph types for common use cases.
- Beautiful default dark and light theme.
- Built-in serialization that's easily extendable for custom paragraphs.
Model
This chapter describes how rich text content is represented in boustro. The terminology from this chapter is used throughout the book.
Document
A document in boustro is a list of lines of formatted text and embeddable content (called embeds).
An immutable document is represented by a Document
.
While editing a document, its state is maintained by a DocumentController
.
A document holds a collection of Paragraphs
.
Paragraphs are either a line of rich text —
or an embed —
which can be any custom content, for example an image or a code block.
Text
A text line represents rich text using a spanned string. Text lines can be modified with line modifiers. These modifiers wrap a line of text and can modify how they are displayed or override their style. Boustro has a modifier for bullet lists.
Spanned strings hold text, along with a list of spans that apply formatting or attach gestures to
the text. The mutable version of a SpannedString
is a SpannedTextEditingController
—
a subclass of Flutter's TextEditingController
that manages formatting of its text.
Both SpannedString
and SpannedTextEditingController
maintain a SpanList
.
SpanList
is an immutable list of AttributeSpan
.
Attribute spans hold an attribute and a range:
Range
: range in the source text to which the attribute is applied. The boundaries of the range are indices into the source text, using Unicode (Extended) Grapheme Clusters (EGC) as the unit. EGC map to user-perceived characters. EGC indices are used to prevent indices in the middle of user-perceived characters. If you use aRange
directly, you likely want to use thecharacters
package.TextAttribute
: The attribute can be resolved to aTextStyle
(to apply formatting) and gestures (for example tap handler that opens a hyperlink) with itsresolve
method, which can optionally use anAttributeTheme
to resolve to a style and gestures. The attribute also definesSpanExpandRules
which determine how the span responds to insertions in the source text.
Embeds
An embed, in boustro, is a custom piece of content that can be embedded in rich text.
Visually, an embed can be any widget, and users can define different widgets for the editable and view-only version of the embed.
See Embeds to learn how embeds work and how to create custom embeds.
Component
A component is any implementation of TextAttribute
, LineModifier
or ParagraphEmbed
. This
concept is not used within boustro itself, but it's useful to define it for talking about
customization in boustro.
Customization
Boustro is designed to be extremely customizable.
To learn how to:
- Theme
boustro
widgets such as the editor and the toolbar, see Theming boustro. - Create and theme attributes, see Attributes.
- Create and theme paragraphs, see Paragraphs.
Built-in components
Boustro — the rich text editor itself — does not know how to apply .
Boustro uses abstractions to make it as extensible1 as possible. Any text attributes and paragraphs2 can be defined in user code.
Boustro provides a range of built-in components that are commonly required in a rich text editor. Here, you'll find a list of components provided.
Attributes
- Bold
- Italic
- Underline
- Strikethrough
- Link (with user-defined callback)
Paragraphs
- Bullet list (TODO)
- Numbered list (TODO)
- Blockquote (TODO)
- Image
- Code block (TODO)
If you're missing a component that is generally useful, please open an issue to request it.
For an explanation of these concepts, see Model.
See Customization for more information about the different ways in which boustro can be customized.
boustro
Changelog
0.2.0
- Changed: Merged
boustro_starter
andflutter_spanned_controller
intoboustro
for easier consumption and development. You can find the old changelogs for those packages in the history of the Git repository. - Changed: Boustro now uses marker characters to detect backspace on empty lines. See this blog post for an explanation on why that's necessary. It uses space characters so capitalization on iOS works properly. They are replaced with zero-width spaces when rendered.
- Added:
BoustroScaffold
widget that provies a default layout and maintains editor focus when clicking the toolbar. - Added: Link toolbar item support for custom validator and input processor.
- Fixed: Link toolbar item URI's does not prepend
https://
for URI's that contain a protocol.
0.1.1
- Added textSelectable flag to DocumentView.
0.1.0
Initial publish.
Package (pub.dev)
API reference
Contribute to boustro
Boustro is still a very young project that I'm developing for my own (proprietary) app. I do, however, wish for boustro to become a great solution for anyone requiring rich text editing capabilities in their Flutter app.
Bug fixes or small improvements are welcome. For design discussions or feature requests, please open an issue.