parseQuillDeltaOps function
- List deltaOps, {
- Editor? customEditor,
- List<
BlockDeltaFormat> blockFormats = defaultBlockFormats, - List<
DeltaBlockMergeRule> blockMergeRules = defaultBlockMergeRules, - List<
InlineDeltaFormat> inlineFormats = defaultInlineFormats, - List<
InlineEmbedFormat> inlineEmbedFormats = const [], - List<
BlockDeltaFormat> embedBlockFormats = defaultEmbedBockFormats,
Parses a list of Quill Delta operations (as JSON) into a MutableDocument.
This parser is the same as parseQuillDeltaDocument except that this method directly accepts the operations list instead of the whole document map. This method is provided for convenience because in some situations only the operations are exchanged, rather than the whole document object.
An Editor is used to insert content in the final document. For typical Delta
formats, the default configuration for an Editor should work fine, and that's
what this method uses. However, some apps need to run custom commands, especially
for custom inline embeds. In that case, you can provide a customEditor, which
is configured however you'd like. The customEditor must contain a MutableDocument
and a MutableComposer. The document must be empty.
Merging consecutive blocks
The Delta format creates some ambiguity around when multiple lines should be combined into a single block vs one block per line. E.g., a code block with multiple lines of code vs a series of independent code blocks.
blockMergeRules explicitly tells the parser which consecutive
DocumentNodes should be merged together when not separated by an unstyled
newline in the given deltas.
Example of consecutive code blocks that would be merged (if requested):
[
{ "insert": "Code line one" },
{ "insert": "\n", "attributed": { "code-block": "plain"} },
{ "insert": "Code line two" },
{ "insert": "\n", "attributed": { "code-block": "plain"} },
]
Example of code blocks, separated by an unstyled newline, that wouldn't be merged:
[
{ "insert": "Code line one" },
{ "insert": "\n", "attributed": { "code-block": "plain"} },
{ "insert": "\n" },
{ "insert": "Code line two" },
{ "insert": "\n", "attributed": { "code-block": "plain"} },
]
Implementation
MutableDocument parseQuillDeltaOps(
List<dynamic> deltaOps, {
Editor? customEditor,
List<BlockDeltaFormat> blockFormats = defaultBlockFormats,
List<DeltaBlockMergeRule> blockMergeRules = defaultBlockMergeRules,
List<InlineDeltaFormat> inlineFormats = defaultInlineFormats,
List<InlineEmbedFormat> inlineEmbedFormats = const [],
List<BlockDeltaFormat> embedBlockFormats = defaultEmbedBockFormats,
}) {
// Deserialize the delta operations JSON into a Dart data structure.
final deltaDocument = Delta.fromJson(deltaOps);
late final MutableDocument document;
late final MutableDocumentComposer composer;
late final Editor editor;
if (customEditor != null) {
// Use the provided custom editor.
if (customEditor.context.maybeDocument == null) {
throw Exception("The provided customEditor must contain a MutableDocument in its editables.");
}
if (customEditor.context.maybeComposer == null) {
throw Exception("The provided customEditor must contain a MutableDocumentComposer in its editables.");
}
editor = customEditor;
document = editor.context.document;
composer = editor.context.composer;
if (document.nodeCount > 1 ||
document.first is! ParagraphNode ||
(document.first as ParagraphNode).text.length > 0) {
throw Exception("The customEditor document must be empty (contain a single, empty ParagraphNode).");
}
} else {
// Create a new, empty Super Editor document.
document = MutableDocument.empty();
composer = MutableDocumentComposer();
editor = Editor(
editables: {
Editor.documentKey: document,
Editor.composerKey: composer,
},
requestHandlers: List.from(defaultRequestHandlers),
// No reactions. Follow the delta operations exactly.
reactionPipeline: [],
);
}
// Place the caret in the (only) empty paragraph so we can begin applying
// deltas to the document.
final firstParagraph = document.first as ParagraphNode;
composer.setSelectionWithReason(
DocumentSelection.collapsed(
position: DocumentPosition(
nodeId: firstParagraph.id,
nodePosition: const TextNodePosition(offset: 0),
),
),
SelectionReason.contentChange,
);
// Run every Quill Delta operation on the empty document. At the end of this
// process the Super Editor document will reflect the desired Quill Delta
// document state.
for (final delta in deltaDocument.operations) {
delta.applyToDocument(
editor,
blockFormats: blockFormats,
blockMergeRules: blockMergeRules,
inlineFormats: inlineFormats,
inlineEmbedFormats: inlineEmbedFormats,
embedBlockFormats: embedBlockFormats,
);
}
return document;
}