blockGenerators method
This function generate widgets to create a book with custom views of the content
Implementation
@override
Future<List<pw.Widget>> blockGenerators(Document document) async {
final List<Paragraph> paragraphs = <Paragraph>[...document.paragraphs];
for (int i = 0; i < paragraphs.length; i++) {
final Paragraph paragraph = paragraphs.elementAt(i);
final Map<String, dynamic>? blockAttributes = paragraph.blockAttributes;
final List<pw.InlineSpan> spansToWrap = <pw.InlineSpan>[];
final List<pw.InlineSpan> inlineSpansToMerge = <pw.InlineSpan>[];
bool goToNextParagraph = false;
for (CustomWidget customBuilder in super.customBuilders) {
if (customBuilder.predicate(paragraph)) {
contentPerPage.add(customBuilder.widgetCallback(
paragraph, paragraph.blockAttributes));
goToNextParagraph = true;
break;
}
}
if (goToNextParagraph) continue;
verifyBlock(blockAttributes);
//verify if paragraph is just a simple new line
if (paragraph.lines.length == 1 &&
paragraph.lines.firstOrNull?.data == '\n' &&
blockAttributes == null) {
final List<pw.InlineSpan> spans = await getRichTextInlineStyles.call(
paragraph.lines.first, defaultTextStyle);
_applyInlineParagraph(contentPerPage, spans);
continue;
}
//verify if the data line is a embed
if (paragraph.type == ParagraphType.embed &&
paragraph.lines.firstOrNull?.data is Map) {
final Line line = paragraph.lines.first;
if ((line.data as Map<String, dynamic>)['video'] != null) {
contentPerPage.add(pw.RichText(
text: pw.TextSpan(
text: (line.data as Map<String, dynamic>)['video'])));
continue;
}
//avoid any another embed that is not a image
if ((line.data as Map<String, dynamic>)['image'] == null) continue;
if (onDetectImageBlock != null) {
contentPerPage
.add(onDetectImageBlock!.call(line, paragraph.blockAttributes));
continue;
}
contentPerPage.add(await getImageBlock.call(line,
(blockAttributes?['align'] as String?)?.resolvePdfBlockAlign));
continue;
}
for (int l = 0; l < paragraph.lines.length; l++) {
final Line line = paragraph.lines.elementAt(l);
if (paragraph.type == ParagraphType.block || blockAttributes != null) {
if ((line.data is Map)) {
if ((line.data as Map)['video'] != null) {
spansToWrap.add(pw.TextSpan(
text: '\n${(line.data as Map<String, dynamic>)['video']}\n'));
continue;
}
//avoid any another embed that is not a image
if ((line.data as Map)['image'] == null) continue;
if (onDetectImageBlock != null) {
final pw.Widget widget =
onDetectImageBlock!.call(line, paragraph.blockAttributes);
spansToWrap.add(pw.WidgetSpan(child: widget));
continue;
}
final pw.Widget widget = await getImageBlock.call(line,
(blockAttributes?['align'] as String?)?.resolvePdfBlockAlign);
spansToWrap.add(pw.WidgetSpan(child: widget));
continue;
}
final (pw.TextStyle style, bool addFontSize) =
_getInlineTextStyle(blockAttributes);
if (line.attributes?['link'] != null) {
if (onDetectLink != null) {
spansToWrap
.addAll(onDetectLink!.call(line, paragraph.blockAttributes));
continue;
}
spansToWrap
.addAll(await getLinkStyle.call(line, style, addFontSize));
continue;
}
if (onDetectInlineRichTextStyles != null) {
spansToWrap.addAll(onDetectInlineRichTextStyles!
.call(line, paragraph.blockAttributes));
continue;
}
spansToWrap.addAll(await getRichTextInlineStyles.call(
line, style, false, addFontSize));
} else if (paragraph.type == ParagraphType.inline ||
blockAttributes == null) {
if (line.data is Map) {
if ((line.data as Map)['video'] != null) {
inlineSpansToMerge.add(pw.TextSpan(
text: '\n${(line.data as Map<String, dynamic>)['video']}\n'));
continue;
}
//avoid any another embed that is not a image
if ((line.data as Map)['image'] == null) continue;
if (onDetectImageBlock != null) {
final pw.Widget widget =
onDetectImageBlock!.call(line, paragraph.blockAttributes);
inlineSpansToMerge.add(pw.WidgetSpan(child: widget));
continue;
}
final pw.Widget widget = await getImageBlock.call(line,
(blockAttributes?['align'] as String?)?.resolvePdfBlockAlign);
inlineSpansToMerge.add(pw.WidgetSpan(child: widget));
continue;
} else if (line.attributes != null) {
if (onDetectInlineRichTextStyles != null) {
inlineSpansToMerge.addAll(onDetectInlineRichTextStyles!
.call(line, paragraph.blockAttributes));
continue;
}
inlineSpansToMerge.addAll(
await getRichTextInlineStyles.call(line, defaultTextStyle));
continue;
}
if (onDetectCommonText != null) {
inlineSpansToMerge.addAll(
onDetectCommonText!.call(line, paragraph.blockAttributes));
continue;
}
//if it doesn't have attrs then just put the content
inlineSpansToMerge.add(
pw.TextSpan(text: line.data as String, style: defaultTextStyle));
}
}
//then put the block styles
if (blockAttributes != null) {
_applyBlockAttributes(
spansToWrap,
blockAttributes,
);
}
_applyInlineParagraph(contentPerPage, inlineSpansToMerge);
}
return contentPerPage;
}