Delta Text View
Версия: 1.0.0
Пакет для преобразования Delta формата (используется в Quill редакторе) в Flutter виджеты.
Описание
delta_text_view рендерит Quill Delta-документы в Flutter. Блоковые атрибуты (заголовки, списки,
цитаты, код) отображаются как текстовые префиксы (# , - , 1. , > ). Поддерживаются
произвольные embed-объекты — упоминания пользователей и emoji — через конфигурацию
MentionConfig/EmojiConfig, без привязки к конкретной модели данных.
Зависимости
dart_quill_delta— модель Delta (реэкспортируется пакетом)flutter— виджетыurl_launcher— открытие ссылок по умолчанию
Публичное API
DeltaTextView
Основной виджет для отображения Delta.
Параметры:
delta(обязательный) — документ DeltadefaultStyle(обязательный) — базовыйTextStylementionConfig— конфигурация для разбора и отображения упоминаний (null, если упоминания не нужны)emojiConfig— конфигурация для разбора emoji-эмбедов (по умолчаниюEmojiConfig(),nullотключает распознавание)emojiOnlySize— размер emoji, когда Delta состоит только из emoji-эмбедов (по умолчанию48,nullотключает автоувеличение)maxLines— ограничение по количеству строкtextAlign— выравнивание текстаoverflow— поведение при переполнении; можно задавать только когдаselectable == nullselectable—trueвключает выделение текста (SelectableDeltaTextView),false/null— обычныйText.rich;overflowразрешён только приnullselectionColor— цвет выделенияonSelectionChangedAsDelta— callback с под-Delta выделенного диапазона (илиnull, если выделение снято)onTapSelectableText— callback нажатия по выделяемому текстуonLinkTap— обработчик нажатия на ссылку; по умолчанию открываетurl_launcher, передайтеnullчтобы отключитьcontextMenuBuilder— переопределение контекстного меню выделения
Пример:
import 'package:delta_text_view/delta_text_view.dart';
DeltaTextView(
delta: delta,
defaultStyle: const TextStyle(fontSize: 16),
mentionConfig: mentionConfig,
)
MentionConfig
Конфигурация разбора и отображения упоминаний произвольного типа.
embedKey— ключ embed-объекта в Delta (по умолчанию'mention')fromJson— десериализация модели из JSON внутри embed-объекта; вернитеnull, если формат не подходитwidgetBuilder— виджет для отображения упоминанияonTap— callback нажатия на упоминание
final mentionConfig = MentionConfig(
fromJson: UserMention.fromJson,
widgetBuilder: (mention) {
final m = mention as UserMention;
return Text('@${m.name}', style: const TextStyle(color: Colors.blue));
},
onTap: ({required mention, required details}) {
final m = mention as UserMention;
print('Нажато упоминание: ${m.id}');
},
);
Модель упоминания реализует интерфейс MentionDelta:
class UserMention implements MentionDelta {
final String id;
final String name;
UserMention({required this.id, required this.name});
@override
String get displayData => name;
@override
Map<String, dynamic> toJson() => {'id': id, 'name': name};
static UserMention? fromJson(Map<String, dynamic> json) {
final id = json['id'] as String?;
final name = json['name'] as String?;
if (id == null || name == null) return null;
return UserMention(id: id, name: name);
}
}
EmojiConfig
Конфигурация разбора и отображения emoji-эмбедов.
embedKey— ключ embed-объекта в Delta (по умолчанию'emoji')widgetBuilder— виджет для отображения emoji; если не передан, используется встроенныйDefaultEmojiWidget, корректно рендерящий цветные emoji на всех платформах
Поддерживаемые атрибуты
Inline форматирование
bold— жирный текстitalic— курсивunderline— подчёркиваниеstrike— зачёркиваниеcolor— цвет текста (формат:#RRGGBBили#RGB)background— цвет фона (формат:#RRGGBBили#RGB)font— семейство шрифтаsize— размер шрифта (число или строка:small,large,huge)link— ссылка (открывается черезonLinkTap)
Block форматирование (текстовые префиксы)
header— заголовки (уровни 1-6) →# Текст,## Тексти т.д.list— списки (bullet/ordered) →- Текстили1. Текстblockquote— цитаты →> Текстcode-block— блоки кода →```\nТекстindent— отступы (добавляются пробелы)
Embed объекты
mention— упоминание пользователя (ключ настраивается черезMentionConfig.embedKey):{ "insert": { "mention": { "id": "user123", "name": "Иван Иванов" } } }emoji— emoji-эмбед (ключ настраивается черезEmojiConfig.embedKey):{ "insert": { "emoji": "😀" } }
Работа с Delta без виджетов
DeltaExtensions (методы на Delta) и String.toDelta покрывают частые операции без рендеринга:
delta.toPlainText/delta.toPlainTextWithBlockPrefixes— конвертация в текст (embed-объекты → пробел)delta.documentLength/delta.plainTextLength/delta.lineCount— длины по спецификации Quill Deltadelta.isPlainTextEmpty/delta.isPlainTextNotEmptydelta.truncateToLines(n)— обрезка доnстрокdelta.hasMention(userId)— проверка упоминания пользователя (с поддержкой@all)delta.getMentions(mentionConfig)— список упоминаний, десериализованных черезMentionConfig.fromJsondelta.stringify— сериализация в JSON-строку'...'.toDelta— строка (JSON или plain text) →Delta
DeltaParser.exceedsMaxLines(...) проверяет, помещается ли Delta в заданное число визуальных
строк при заданной ширине — используется, например, для решения о показе кнопки «Развернуть».
Примеры использования
Базовое использование
import 'package:dart_quill_delta/dart_quill_delta.dart';
import 'package:delta_text_view/delta_text_view.dart';
import 'package:flutter/material.dart';
class MessageWidget extends StatelessWidget {
final Delta delta;
const MessageWidget({required this.delta});
@override
Widget build(BuildContext context) {
return DeltaTextView(
delta: delta,
defaultStyle: const TextStyle(fontSize: 16),
mentionConfig: null,
);
}
}
С обработкой упоминаний
DeltaTextView(
delta: delta,
defaultStyle: const TextStyle(fontSize: 16),
mentionConfig: MentionConfig(
fromJson: UserMention.fromJson,
widgetBuilder: (mention) => Text('@${(mention as UserMention).name}'),
onTap: ({required mention, required details}) {
final m = mention as UserMention;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => UserProfilePage(userId: m.id)),
);
},
),
)
С ограничением количества строк
DeltaTextView(
delta: delta,
defaultStyle: const TextStyle(fontSize: 16),
mentionConfig: null,
maxLines: 3,
overflow: TextOverflow.ellipsis,
)
С выделением текста
DeltaTextView(
delta: delta,
defaultStyle: const TextStyle(fontSize: 16),
mentionConfig: null,
selectable: true,
onSelectionChangedAsDelta: (selectionDelta) {
// например, для копирования с сохранением форматирования
},
)
Структура пакета
delta_text_view/
├── lib/
│ ├── delta_text_view.dart # Главный файл экспорта
│ ├── core/
│ │ ├── delta_parser.dart # Delta -> InlineSpan/текст
│ │ ├── delta_attributes_parser.dart # Атрибуты Delta -> TextStyle
│ │ ├── delta_clipboard.dart # Внутрипроцессный буфер обмена для Delta
│ │ └── selection_to_delta_converter.dart # TextSelection -> под-Delta
│ ├── domain/
│ │ ├── extensions/ # Delta/String extensions
│ │ └── models/ # MentionDelta, MentionConfig, EmojiConfig
│ └── presentation/widgets/
│ ├── delta_text_view_widget.dart # DeltaTextView
│ ├── selectable_delta_text_view.dart # Выделяемый текст
│ ├── mention_span.dart / mention_widget.dart
│ └── emoji_span.dart / emoji_widget.dart
├── example/
│ ├── lib/main.dart # Демонстрационное приложение
│ └── pubspec.yaml
├── pubspec.yaml
└── README.md
Запуск примера
cd example
flutter pub get
flutter run -d linux
Примечания
- Всё, что не экспортируется из
lib/delta_text_view.dart, — внутренняя реализация; импортируйте толькоpackage:delta_text_view/delta_text_view.dart - Пакет не публикуется в pub.dev (
publish_to: none), подключается через git/path
Libraries
- core/delta_attributes_parser
- core/delta_clipboard
- core/delta_parser
- core/selection_to_delta_converter
- delta_text_view
- Пакет для преобразования Delta формата в Flutter виджет
- domain/extensions/delta_extensions
- domain/extensions/string_extensions
- domain/models/emoji_config
- domain/models/mention_config
- domain/models/mention_delta
- presentation/widgets/delta_text_view_widget
- presentation/widgets/emoji_span
- presentation/widgets/emoji_widget
- presentation/widgets/mention_span
- presentation/widgets/mention_widget
- presentation/widgets/selectable_delta_text_view