dartlangeditorflutterflutter-appsflutter-examplesflutter-packageflutter-widgetquillquill-deltaquilljsreactquillrich-textrich-text-editorwysiwygwysiwyg-editor
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.6 KiB
135 lines
3.6 KiB
4 years ago
|
import 'package:flutter_quill/models/documents/attribute.dart';
|
||
|
import 'package:flutter_quill/models/rules/rule.dart';
|
||
|
import 'package:quill_delta/quill_delta.dart';
|
||
|
|
||
|
abstract class FormatRule extends Rule {
|
||
|
const FormatRule();
|
||
|
|
||
|
@override
|
||
|
RuleType get type => RuleType.FORMAT;
|
||
|
|
||
|
@override
|
||
|
validateArgs(int len, Object data, Attribute attribute) {
|
||
|
assert(len != null);
|
||
|
assert(data == null);
|
||
|
assert(attribute != null);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class ResolveLineFormatRule extends FormatRule {
|
||
|
const ResolveLineFormatRule();
|
||
|
|
||
|
@override
|
||
|
Delta applyRule(Delta document, int index,
|
||
|
{int len, Object data, Attribute attribute}) {
|
||
|
if (attribute.scope != AttributeScope.BLOCK) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
Delta delta = Delta()..retain(index);
|
||
|
DeltaIterator itr = DeltaIterator(document);
|
||
|
itr.skip(index);
|
||
|
Operation op;
|
||
|
for (int cur = 0; cur < len && itr.hasNext; cur += op.length) {
|
||
|
op = itr.next(len - cur);
|
||
|
if (op.data is! String || !(op.data as String).contains('\n')) {
|
||
|
delta.retain(op.length);
|
||
|
continue;
|
||
|
}
|
||
|
String text = op.data;
|
||
|
Delta tmp = Delta();
|
||
|
int offset = 0;
|
||
|
|
||
|
for (int lineBreak = text.indexOf('\n');
|
||
|
lineBreak >= 0;
|
||
|
lineBreak = text.indexOf('\n', offset)) {
|
||
|
tmp..retain(lineBreak - offset)..retain(1, attribute.toJson());
|
||
|
offset = lineBreak + 1;
|
||
|
}
|
||
|
tmp.retain(text.length - offset);
|
||
|
delta = delta.concat(tmp);
|
||
|
}
|
||
|
|
||
|
while (itr.hasNext) {
|
||
|
op = itr.next();
|
||
|
String text = op.data is String ? op.data as String : '';
|
||
|
int lineBreak = text.indexOf('\n');
|
||
|
if (lineBreak < 0) {
|
||
|
delta..retain(op.length);
|
||
|
continue;
|
||
|
}
|
||
|
delta..retain(lineBreak)..retain(1, attribute.toJson());
|
||
|
break;
|
||
|
}
|
||
|
return delta;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class FormatLinkAtCaretPositionRule extends FormatRule {
|
||
|
const FormatLinkAtCaretPositionRule();
|
||
|
|
||
|
@override
|
||
|
Delta applyRule(Delta document, int index,
|
||
|
{int len, Object data, Attribute attribute}) {
|
||
|
if (attribute.key != Attribute.link.key || len > 0) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
Delta delta = Delta();
|
||
|
DeltaIterator itr = DeltaIterator(document);
|
||
|
Operation before = itr.skip(index), after = itr.next();
|
||
|
int beg = index, retain = 0;
|
||
|
if (before != null && before.hasAttribute(attribute.key)) {
|
||
|
beg -= before.length;
|
||
|
retain = before.length;
|
||
|
}
|
||
|
if (after != null && after.hasAttribute(attribute.key)) {
|
||
|
retain += after.length;
|
||
|
}
|
||
|
if (retain == 0) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
delta..retain(beg)..retain(retain, attribute.toJson());
|
||
|
return delta;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class ResolveInlineFormatRule extends FormatRule {
|
||
|
const ResolveInlineFormatRule();
|
||
|
|
||
|
@override
|
||
|
Delta applyRule(Delta document, int index,
|
||
|
{int len, Object data, Attribute attribute}) {
|
||
|
if (attribute.scope != AttributeScope.BLOCK) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
Delta delta = Delta()..retain(index);
|
||
|
DeltaIterator itr = DeltaIterator(document);
|
||
|
itr.skip(index);
|
||
|
|
||
|
Operation op;
|
||
|
for (int cur = 0; cur < len && itr.hasNext; cur += op.length) {
|
||
|
op = itr.next(len - cur);
|
||
|
String text = op.data is String ? op.data as String : '';
|
||
|
int lineBreak = text.indexOf('\n');
|
||
|
if (lineBreak < 0) {
|
||
|
delta.retain(op.length, attribute.toJson());
|
||
|
continue;
|
||
|
}
|
||
|
int pos = 0;
|
||
|
while (lineBreak >= 0) {
|
||
|
delta..retain(lineBreak - pos, attribute.toJson())..retain(1);
|
||
|
pos = lineBreak + 1;
|
||
|
lineBreak = text.indexOf('\n', pos);
|
||
|
}
|
||
|
if (pos < op.length) {
|
||
|
delta.retain(op.length - pos, attribute.toJson());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return delta;
|
||
|
}
|
||
|
}
|