✂️ Dart Quill Delta Simplify
This is a package designed to facilitate the manipulation of documents in the Quill Delta format within the Flutter ecosystem. The Quill Delta format is a data structure used by the Quill text editor and Fluter Quill to represent rich content, including text, attributes (such as bold or italic), and multimedia insertions.
❓ Why use it?
Manipulating content in a Delta
format can be complex, especially when dealing with advanced operations such as searching, modifying, or filtering text based on specific attributes or patterns. Dart Quill Delta Simplify addresses this complexity by providing a user-friendly and powerful API that allows developers to perform these operations with ease and precision.
📚 Quill Delta Documentation
For detailed API usage information, refer to the official Dart Quill Delta docs.
📎 QueryDelta Documentation
For detailed usage and more complete examples of the API, you can see:
Insert.md Replace.md Format.md Delete.md Diff.md Matching.md Extras.md
🔎 Introduction to QueryDelta
The QueryDelta
class is a query builder designed to create and modify Delta
objects by applying various conditions. It allows for conditional operations and tracks changes made to the delta during the modification process. The purpose of QueryDelta
is to provide a structured way to manipulate a Delta
object, while keeping track of applied changes through conditions and ensuring the integrity of the final result.
QueryDelta({
required Delta delta,
})
🛠️ Building the final Delta
This is the key to finalizing the changes made to the QueryDelta
. It applies all the conditions that were added to the query and generates the final Delta
. This method is essential, as no modifications will be applied to the Delta
until build()
is run.
BuildResult build({
// A function that converts an unknown object type to a list of `Operation` objects
// use it in case of you use a custom condition and it returns a type that is not supported
// by default. Supported: [Iterable<Operation>, Operation, String, Map<String,dynamic>]
List<Operation> Function(Object)? unknownObjectTypeBuilder,
// Determines whether conditions should be reused. If set to `true`, previously used conditions will be ignored
bool preventReuseConditions = true,
// Controls whether ignore conditions should persist when building the final `Delta`
bool maintainIgnoresConditions = true,
});
🔨 Pushing conditions
The push
method is used to add a single Condition
to the QueryDelta
. Each condition added to the QueryDelta
defines a rule or requirement for modifying the Delta
. These conditions are applied in order, so the order in which you add them is important for the final result.
QueryDelta push(Condition condition);
📖 Some examples (using regular operations)
1. Checking if exist a part of text or an Embed into the Delta
import 'package:dart_quill_delta_simplify/dart_quill_delta_simplify.dart';
final QueryDelta query = QueryDelta(
delta: Delta()
..insert('This is my example delta\nUsing ')
..insert('contains', {'code': true})
..insert(' method, we can check if exit a portion of text')
..insert(' without too much code\n'));
/*
* You can use too contains method with Delta class:
* delta.contains(target: ' This');
*/
print(query.contains(target: 'This')); // true
print(query.contains(target: 'is ')); // false
2. Inserting Text at a Specific Position
import 'package:quill_delta/quill_delta.dart';
import 'package:dart_quill_delta_simplify/query_delta.dart';
void main() {
final Delta delta = Delta()..insert('Hello!');
final QueryDelta queryDelta = QueryDelta(delta: delta); // or delta.toQuery
// Insert ' World' after 'Hello'
final BuildResult newDelta = queryDelta
.insert(
insert: ' World',
target: 'Hello',
startPoint: 5,
)
.build();
/*
* You can use too with Delta class:
* delta.simpleInsert(
* insert: ' World',
* target: 'Hello',
* startPoint: 5,
* );
*/
print(newDelta.delta); // Should print [{"insert": "Hello World!"}]
}
3. Replacing Text Based on a Condition
import 'package:quill_delta/quill_delta.dart';
import 'package:dart_quill_delta_simplify/query_delta.dart';
void main() {
final Delta delta = Delta()..insert('Hello World!');
final QueryDelta queryDelta = QueryDelta(delta: delta); // or delta.toQuery
// Replace 'World' with 'Dart'
final BuildResult newDelta = queryDelta
.replace(
replace: 'Dart',
target: 'World',
range: null,
)
.build();
/*
* You can use too:
* delta.simpleReplace(
* replace: 'Dart',
* target: 'World',
* range: null,
* );
*/
print(newDelta.delta); // Should print [{"insert": "Hello Dart!"}]
}
4. Formatting a Text Segment
import 'package:dart_quill_delta_simplify/dart_quill_delta_simplify.dart';
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill/quill_delta.dart';
void main() {
final Delta delta = Delta()..insert('Hello World!');
final QueryDelta queryDelta = QueryDelta(delta: delta); // or delta.toQuery
// Format the second part 'World' to be italic
final BuildResult updatedDelta = queryDelta
.format(
attribute: Attribute.italic,
offset: 6,
len: 5,
)
.build();
/*
* You can use too with Delta class:
* delta.simpleFormat(
* attribute: Attribute.italic,
* offset: 6,
* len: 5,
* );
*/
// Should print [{"insert": "Hello"}, {"insert": " World", "attributes": {"italic": true}}]
print(updatedDelta.delta);
}
5. Deleting a Specific Text Segment
import 'package:quill_delta/quill_delta.dart';
import 'package:dart_quill_delta_simplify/query_delta.dart';
void main() {
final Delta delta = Delta()..insert('Hello World!');
final QueryDelta queryDelta = QueryDelta(delta: delta); // to delta.toQuery
// Delete 'World' from the text
final BuildResult newDelta = queryDelta
.delete(
target: null,
startPoint: 6,
lengthOfDeletion: 5,
)
.build();
/*
* You can use too with Delta class:
* delta.simpleDelete(
* target: 'World',
* startPointOffset: 6,
* len: 5,
*);
*/
print(newDelta.delta); // Should print '[{"insert": "Hello!"}]'
}
6. Ignoring a Part of the Delta
import 'package:quill_delta/quill_delta.dart';
import 'package:dart_quill_delta_simplify/query_delta.dart';
void main() {
final Delta delta = Delta()..insert('Hello World!\n');
final QueryDelta queryDelta = QueryDelta(delta: delta); // or delta.toQuery
// Ignore the first 5 characters ('Hello')
final BuildResult newDelta = queryDelta
.ignorePart(0, len: 5)
.delete(
target: null,
startPoint: 0,
lengthOfDeletion: 5,
)
.build(); // no changes ocurrs since the deletion is into the Range of the Ignore Part
print(newDelta.delta); // Should print [{"insert": "Hello World!\n"}]
}
7. Search for Specific Text in a Delta
import 'package:quill_delta/quill_delta.dart';
import 'package:dart_quill_delta_simplify/query_delta.dart';
void main() {
final Delta delta = Delta()..insert('Hello World!');
final QueryDelta queryDelta = QueryDelta(delta: delta); // or delta.toQuery
// Search for the first occurrence of the word 'World'
final DeltaRangeResult? match = queryDelta
.firstMatch(
RegExp('World'),
null,
);
/*
* Or you can use allMatches to multiple occurrences
* final List<DeltaRangeResult> match = queryDelta
* .allMatches(
* RegExp('World'),
* null,
* );
*
* You can use too with Delta class:
* final DeltaRangeResult? match2 = delta.firstMatch(
* RegExp('World'),
* null,
* );
* or
* final List<DeltaRangeResult> match = delta.allMatches(
* RegExp('World'),
* null,
* );
*/
if (match != null) {
print(match); // DeltaRangeResult(delta: [{"insert": "World"}], Offset: [6, 10])
} else {
print('No match found');
}
}
8. Filter Segments of Text with a Specific Attribute
import 'package:quill_delta/quill_delta.dart';
import 'package:dart_quill_delta_simplify/query_delta.dart';
void main() {
final Delta delta = Delta()
..insert('Hello', {'bold': true})
..insert(' World')
..insert('!', {'italic': true});
final QueryDelta queryDelta = QueryDelta(delta: delta); // or delta.toQuery
// Retrieve all segments with the 'bold' attribute
final List<DeltaRangeResult> boldMatches = queryDelta.matchAttributes(
inlineAttrs: {'bold': true},
blockAttrs: null,
blockAttrKeys: null,
inlineAttrKeys: null,
);
/*
* You can use too with Delta class:
* final List<DeltaRangeResult> matches = delta.matchAttributes(
* inlineAttrs: {'bold': true},
* blockAttrs: null,
* blockAttrKeys: null,
* inlineAttrKeys: null,
* );
*/
print(boldMatches.toString());
}
🌳 Contributing
We greatly appreciate your time and effort.
To keep the project consistent and maintainable, we have a few guidelines that we ask all contributors to follow. These guidelines help ensure that everyone can understand and work with the code easier.
See Contributing for more details.