parseDeltaToSpans static method
List<InlineSpan>
parseDeltaToSpans({
- MentionConfig? mentionConfig,
- EmojiConfig? emojiConfig,
- required Delta delta,
- TextStyle? baseStyle,
- void onMentionSelectedAsDelta()?,
- bool applyBlockPrefixes = false,
- TextSelection? selectionRange,
- Color? selectionColor,
- void onLinkTap(
- String url
Implementation
static List<InlineSpan> parseDeltaToSpans({
MentionConfig? mentionConfig,
EmojiConfig? emojiConfig,
required Delta delta,
TextStyle? baseStyle,
void Function(Delta)? onMentionSelectedAsDelta,
bool applyBlockPrefixes = false,
TextSelection? selectionRange,
Color? selectionColor,
void Function(String url)? onLinkTap,
}) {
final spans = <InlineSpan>[];
var currentOffset = 0;
final ops = delta.toJson() as List<dynamic>;
if (!applyBlockPrefixes) {
for (var i = 0; i < ops.length; i++) {
final op = ops[i];
var insert = op['insert'];
if (insert == null) continue;
final attr = op['attributes'] as Map<String, dynamic>?;
if (i == ops.length - 1 && insert is String) {
if (insert.endsWith('\n')) {
insert = insert.substring(0, insert.length - 1);
}
if (insert.isEmpty && attr == null && spans.isNotEmpty) {
continue;
}
}
final generated = _opToSpans(
mentionConfig: mentionConfig,
emojiConfig: emojiConfig,
insert: insert,
attributes: attr,
baseStyle: baseStyle,
offset: currentOffset,
selection: selectionRange,
selectionColor: selectionColor,
onMentionSelected: onMentionSelectedAsDelta,
onLinkTap: onLinkTap,
);
spans.addAll(generated);
currentOffset += insert is String ? insert.length : 1;
}
return spans;
}
final lines = <({List<dynamic> ops, Map<String, dynamic>? blockAttr})>[];
var lineOps = <dynamic>[];
for (final op in ops) {
final insert = op['insert'];
final attr = op['attributes'] as Map<String, dynamic>?;
if (insert is String) {
final parts = insert.split('\n');
for (var i = 0; i < parts.length; i++) {
if (parts[i].isNotEmpty) {
lineOps.add({'insert': parts[i], 'attributes': attr});
}
if (i < parts.length - 1) {
lines.add((ops: List.from(lineOps), blockAttr: attr));
lineOps = [];
}
}
} else {
lineOps.add(op);
}
}
if (lineOps.isNotEmpty) {
lines.add((ops: lineOps, blockAttr: null));
}
if (lines.isNotEmpty && lines.last.ops.isEmpty && lines.last.blockAttr == null) {
lines.removeLast();
}
var orderedCounter = 0;
for (var lineIdx = 0; lineIdx < lines.length; lineIdx++) {
final line = lines[lineIdx];
final blockAttr = line.blockAttr;
final isOrdered = blockAttr?['list'] == 'ordered';
if (isOrdered) {
final realIndex = blockAttr?['list-real-index'] as int?;
if (realIndex != null) {
orderedCounter = realIndex;
} else {
// Fallback: индекс не задан явно — продолжаем автонумерацию.
orderedCounter++;
}
} else if (blockAttr?['list'] == null) {
orderedCounter = 0;
}
if (lineIdx > 0) {
spans.add(TextSpan(text: '\n', style: baseStyle));
currentOffset += 1;
}
for (var i = 0; i < line.ops.length; i++) {
final op = line.ops[i];
final insert = op['insert'];
final attr = op['attributes'] as Map<String, dynamic>?;
if (i == 0 && insert is String && blockAttr != null) {
final prefix = isOrdered ? '$orderedCounter. ' : blockAttr.blockPrefixInfo.$1;
if (prefix.isNotEmpty) {
spans.add(TextSpan(text: prefix, style: baseStyle));
currentOffset += prefix.length;
}
}
final generated = _opToSpans(
mentionConfig: mentionConfig,
emojiConfig: emojiConfig,
insert: insert,
attributes: attr,
baseStyle: baseStyle,
offset: currentOffset,
selection: selectionRange,
selectionColor: selectionColor,
onMentionSelected: onMentionSelectedAsDelta,
onLinkTap: onLinkTap,
);
spans.addAll(generated);
currentOffset += insert is String ? insert.length : 1;
}
}
return spans;
}