blockGenerators method

  1. @override
Future<List<Widget>> blockGenerators(
  1. Document document
)
override

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;
}