Skip to main content

Overview

The HTML Decoder parses HTML strings into AppFlowy Editor Document objects. It handles both simple and complex HTML structures, including nested elements, inline styles, and various formatting options.

DocumentHTMLDecoder

The main class for decoding HTML to document format.

Constructor

DocumentHTMLDecoder({
  Map<String, ElementParser> customDecoders = const {},
})

Parameters

  • customDecoders (Map<String, ElementParser>): Map of HTML tag names to custom parser functions. Default is an empty map.

Properties

enableColorParse

static bool enableColorParse = true;
Static property to enable or disable color parsing from HTML styles. When true, the decoder extracts text color and background color from inline CSS.

Methods

convert

Document convert(String input)
Converts an HTML string to a Document object. Parameters:
  • input (String): The HTML string to parse
Returns: Document - The parsed document Example:
final decoder = DocumentHTMLDecoder();
final html = '''
<h1>Hello World</h1>
<p>This is <strong>bold</strong> text.</p>
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>
''';

final document = decoder.convert(html);

Helper Function

htmlToDocument

A convenient helper function that provides a simpler API.
Document htmlToDocument(
  String html, {
  Map<String, ElementParser> customDecoders = const {},
})
Parameters:
  • html (String): The HTML string to parse
  • customDecoders (Map<String, ElementParser>): Custom decoders for specific HTML tags
Returns: Document - The parsed document Example:
import 'package:appflowy_editor/appflowy_editor.dart';

// Simple usage
final document = htmlToDocument('<h1>Title</h1><p>Content</p>');

// With custom decoders
final document = htmlToDocument(
  html,
  customDecoders: {
    'custom-tag': (element, parseDeltaElement) {
      // Custom parsing logic
      return [customNode()];
    },
  },
);

Supported HTML Tags

Headings

  • <h1> through <h6> → Heading nodes with levels 1-6

Text Formatting

  • <p> → Paragraph nodes
  • <strong> or <b> → Bold text
  • <em> or <i> → Italic text
  • <u> → Underlined text
  • <del> or <s> → Strikethrough text
  • <code> → Inline code
  • <a href="..."> → Links with href attribute
  • <span> → Styled text with inline CSS
  • <mark> → Highlighted text

Lists

  • <ul> → Bulleted list
  • <ol> → Numbered list
  • <li> → List items

Block Elements

  • <blockquote> → Quote blocks
  • <img> → Images (network URLs only)
  • <hr> → Dividers
  • <br> → Line breaks
  • <div> → Container elements

Tables

  • <table> → Table structure
  • <tr> → Table rows
  • <th> → Table headers
  • <td> → Table data cells

Inline Style Parsing

The decoder extracts formatting from inline CSS styles:

Font Weight

<span style="font-weight: bold">Bold text</span>
<span style="font-weight: 700">Also bold (≥500)</span>

Text Decoration

<span style="text-decoration: underline">Underlined</span>
<span style="text-decoration: line-through">Strikethrough</span>
<span style="text-decoration: underline line-through">Both</span>

Colors

<span style="color: #ff0000">Red text</span>
<span style="background-color: #ffff00">Yellow highlight</span>
<span style="background: rgb(255, 0, 0)">Red background</span>
Note: Color parsing can be disabled:
DocumentHTMLDecoder.enableColorParse = false;
final document = htmlToDocument(html);

Font Style

<span style="font-style: italic">Italic text</span>

Example Usage

Basic HTML Parsing

final html = '''
<h1>Welcome to AppFlowy</h1>
<h2>Features</h2>
<p>AppFlowy Editor is a <strong>highly customizable</strong> <i>rich-text editor</i></p>
<ul>
  <li>Customizable</li>
  <li>Test-covered</li>
  <li>Open source</li>
</ul>
<blockquote>Built with Flutter</blockquote>
<img src="https://example.com/image.png">
''';

final document = htmlToDocument(html);

Complex Formatting

final html = '''
<h2>👋 <strong>Welcome to</strong> <span style="font-weight: bold; font-style: italic">AppFlowy Editor</span></h2>
<p><u>Here</u> is an example <del>your</del> you can give a try</p>
<p><span style="font-weight: bold; text-decoration: line-through">Combined styles</span></p>
<p><a href="https://appflowy.io">Visit our website</a></p>
''';

final document = htmlToDocument(html);

Nested Lists

final html = '''
<ul>
  <li>Task Parent One
    <ul>
      <li>Task One + Parent
        <ul>
          <li>Task Two</li>
        </ul>
      </li>
      <li>Task Three</li>
    </ul>
  </li>
  <li>Task Four</li>
</ul>
''';

final document = htmlToDocument(html);

Tables

final html = '''
<table>
  <tr>
    <th>Header 1</th>
    <th>Header 2</th>
  </tr>
  <tr>
    <td><strong>Bold cell</strong></td>
    <td><i>Italic cell</i></td>
  </tr>
</table>
''';

final document = htmlToDocument(html);

Special Handling

Google Docs Compatibility

The decoder includes special handling for documents copied from Google Docs:
  • Handles single all-encompassing tags under the body
  • Filters out meaningless tags like <b style="font-weight:normal;">

Image Requirements

  • Only network images (HTTP/HTTPS URLs) are supported
  • Invalid or local image URLs are converted to empty paragraphs
// Supported
<img src="https://example.com/image.png">

// Not supported (converted to empty paragraph)
<img src="/local/path/image.png">
<img src="file:///path/image.png">

Empty Content

Empty text nodes with only whitespace are automatically skipped:
<p>Text</p>
    <!-- whitespace ignored -->
<p>More text</p>

Custom Decoders

Create custom decoders for specific HTML tags:
typedef ElementParser = Iterable<Node> Function(
  dom.Element element,
  (Delta, Iterable<Node>) Function(
    dom.Element element, {
    String? type,
  }) parseDeltaElement,
);

// Example: Custom video decoder
Iterable<Node> videoDecoder(
  dom.Element element,
  parseDeltaElement,
) {
  final src = element.attributes['src'];
  if (src == null) return [];
  
  return [
    Node(
      type: 'video',
      attributes: {'url': src},
    )
  ];
}

final document = htmlToDocument(
  html,
  customDecoders: {
    'video': videoDecoder,
  },
);

HTMLTags Constants

The decoder provides tag name constants:
HTMLTags.h1              // 'h1'
HTMLTags.paragraph       // 'p'
HTMLTags.bold            // 'b'
HTMLTags.italic          // 'i'
HTMLTags.underline       // 'u'
HTMLTags.strikethrough   // 's'
HTMLTags.code            // 'code'
HTMLTags.anchor          // 'a'
HTMLTags.unorderedList   // 'ul'
HTMLTags.orderedList     // 'ol'
HTMLTags.list            // 'li'
HTMLTags.blockQuote      // 'blockquote'
HTMLTags.image           // 'img'
HTMLTags.table           // 'table'
HTMLTags.divider         // 'hr'

Tag Categories

// Inline formatting elements
HTMLTags.formattingElements  // [anchor, italic, bold, underline, ...]

// Block-level elements
HTMLTags.specialElements     // [h1, h2, ul, ol, table, blockquote, ...]

// Check if tag is top-level
HTMLTags.isTopLevel('h1')    // true
HTMLTags.isTopLevel('span')  // false

See Also

Build docs developers (and LLMs) love