parse method

void parse (
  1. BuildMetadata meta
)

Parses meta for build ops and text styles.

Implementation

void parse(BuildMetadata meta) {
  final attrs = meta.element.attributes;

  switch (meta.element.localName) {
    case kTagA:
      _tagA ??= TagA(this, () => _widget?.hyperlinkColor).buildOp;
      meta.register(_tagA);
      break;

    case 'abbr':
    case 'acronym':
      meta.tsb(
        TextStyleOps.textDeco,
        TextDeco(style: TextDecorationStyle.dotted, under: true),
      );
      break;

    case 'address':
      meta
        ..isBlockElement = true
        ..tsb(TextStyleOps.fontStyle, FontStyle.italic);
      break;

    case 'article':
    case 'aside':
    case 'div':
    case 'figcaption':
    case 'footer':
    case 'header':
    case 'main':
    case 'nav':
    case 'section':
      meta.isBlockElement = true;
      break;

    case 'blockquote':
    case 'figure':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '1em 40px';
      break;

    case 'b':
    case 'strong':
      meta.tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;

    case 'big':
      meta.tsb(_tsbFontSize, kCssFontSizeLarger);
      break;

    case 'br':
      _tagBr ??= BuildOp(onPieces: (_, p) => p..last.text.addNewLine());
      meta.register(_tagBr);
      break;

    case 'center':
      meta[kCssTextAlign] = kCssTextAlignCenter;
      break;

    case 'cite':
    case 'dfn':
    case 'em':
    case 'i':
    case 'var':
      meta.tsb(TextStyleOps.fontStyle, FontStyle.italic);
      break;

    case kTagCode:
    case kTagPre:
    case kTagTt:
      _tagCode ??= TagCode(this).buildOp;
      meta.register(_tagCode);
      break;

    case 'dd':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '0 0 1em 40px';
      break;
    case 'dl':
      meta.isBlockElement = true;
      break;
    case 'dt':
      meta
        ..isBlockElement = true
        ..tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;

    case 'del':
    case 's':
    case 'strike':
      meta.tsb(TextStyleOps.textDeco, TextDeco(strike: true));
      break;

    case kTagFont:
      _tagFont ??= TagFont(this).buildOp;
      meta.register(_tagFont);
      break;

    case 'hr':
      _tagHr ??= BuildOp(
        defaultStyles: (_) => const {'margin-bottom': '1em'},
        onWidgets: (meta, _) => [buildDivider(meta)],
      );
      meta.register(_tagHr);
      break;

    case 'h1':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '0.67em 0'
        ..tsb(_tsbFontSize, '2em')
        ..tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;
    case 'h2':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '0.83em 0'
        ..tsb(_tsbFontSize, '1.5em')
        ..tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;
    case 'h3':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '1em 0'
        ..tsb(_tsbFontSize, '1.17em')
        ..tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;
    case 'h4':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '1.33em 0'
        ..tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;
    case 'h5':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '1.67em 0'
        ..tsb(_tsbFontSize, '0.83em')
        ..tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;
    case 'h6':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '2.33em 0'
        ..tsb(_tsbFontSize, '0.67em')
        ..tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;

    case 'iframe':
    case 'script':
    case 'style':
    case 'svg':
      // actually `script` and `style` are not required here
      // our parser will put those elements into document.head anyway
      meta.isNotRenderable = true;
      break;

    case kTagImg:
      _tagImg ??= TagImg(this).buildOp;
      meta.register(_tagImg);

      if (attrs.containsKey(kAttributeImgHeight)) {
        meta[kCssHeight] = '${attrs[kAttributeImgHeight]}px';
      }
      if (attrs.containsKey(kAttributeImgWidth)) {
        meta[kCssWidth] = '${attrs[kAttributeImgWidth]}px';
      }
      break;

    case 'ins':
    case 'u':
      meta.tsb(TextStyleOps.textDeco, TextDeco(under: true));
      break;

    case 'kbd':
    case 'samp':
      meta.tsb(TextStyleOps.fontFamily, [kTagCodeFont1, kTagCodeFont2]);
      break;

    case kTagOrderedList:
    case kTagUnorderedList:
      meta.register(TagLi(this, meta).op);
      break;

    case 'mark':
      meta
        ..[kCssBackgroundColor] = '#ff0'
        ..tsb(TextStyleOps.color, Color.fromARGB(255, 0, 0, 0));
      break;

    case 'p':
      meta
        ..isBlockElement = true
        ..[kCssMargin] = '1em 0';
      break;

    case kTagQ:
      _tagQ ??= TagQ(this).buildOp;
      meta.register(_tagQ);
      break;

    case kTagRuby:
      meta.register(TagRuby(this, meta).op);
      break;

    case 'small':
      meta.tsb(_tsbFontSize, kCssFontSizeSmaller);
      break;

    case 'sub':
      meta
        ..[kCssVerticalAlign] = kCssVerticalAlignSub
        ..tsb(_tsbFontSize, kCssFontSizeSmaller);
      break;
    case 'sup':
      meta
        ..[kCssVerticalAlign] = kCssVerticalAlignSuper
        ..tsb(_tsbFontSize, kCssFontSizeSmaller);
      break;

    case kTagTable:
      meta
        ..[kCssDisplay] = kCssDisplayTable
        ..register(TagTable.cellPaddingOp(
            tryParseDoubleFromMap(attrs, kAttributeCellPadding) ?? 1));
      break;
    case kTagTableHeaderCell:
      meta.tsb(TextStyleOps.fontWeight, FontWeight.bold);
      break;
    case kTagTableCaption:
      meta[kCssTextAlign] = kCssTextAlignCenter;
      break;
  }

  for (final attribute in attrs.entries) {
    switch (attribute.key) {
      case kAttributeAlign:
        meta[kCssTextAlign] = attribute.value;
        break;
      case kAttributeDir:
        meta[kCssDirection] = attribute.value;
        break;
    }
  }
}