flutter_matrix_html 0.1.1

  • Readme
  • Changelog
  • Example
  • Installing
  • 49

flutter_html #

pub package CircleCI

Note: 1.0.0-pre.1 has been released! See the Migration Guide if you'd like to take advantage of all the new features of 1.0.0! Also, check out the Prerelease Changelog. Version 1.0.0 is currently on the new-parser branch. This README will be updated when 1.0.0 is merged into the master branch.

A Flutter widget for rendering static html tags as Flutter widgets. (Will render over 70 different html tags!)

A Screenshot of flutter_html

Installing: #

Add the following to your pubspec.yaml file:

dependencies:
  flutter_html: ^0.11.1

Currently Supported HTML Tags: #

a, abbr, acronym, address, article, aside, b, bdi, bdo, big, blockquote, body, br, caption, cite, code, data, dd, del, dfn, div, dl, dt, em, figcaption, figure, footer, h1, h2, h3, h4, h5, h6, header, hr, i, img, ins, kbd, li, main, mark, nav, noscript, ol, p, pre, q, rp, rt, ruby, s, samp, section, small, span, strike, strong, sub, sup, table, tbody, td, template, tfoot, th, thead, time, tr, tt, u, ul, var

Roadmap #

View the development roadmap in the wiki

Partially supported elements: #

These are common elements that aren't yet fully supported, but won't be ignored and will still render somewhat correctly.

center, font

List of planned supported elements: #

These are elements that are planned, but present a specific challenge that makes them somewhat difficult to implement.

audio, details, source, summary, svg, track, video, wbr

List of elements that I don't plan on implementing: #

Feel free to open an issue if you have a good reason and feel like you can convince me to implement them. A well written and complete pull request implementing one of these is always welcome, though I cannot promise I will merge them.

Note: These unsupported tags will just be ignored.

applet, area, base, basefont, button, canvas, col, colgroup, datalist, dialog, dir, embed, fieldset, form, frame, frameset, head, iframe, input, label, legend, link, map, meta, meter, noframe, object, optgroup, option, output, param, picture, progress, script, select, style, textarea, title

Why this package? #

This package is designed with simplicity in mind. Flutter currently does not support rendering of web content into the widget tree. This package is designed to be a reasonable alternative for rendering static web content until official support is added.

Update: #

The official Flutter WebView package has been created and is in a developer preview. It's not stable yet, so I'll continue to support this project at least until webview_flutter hits 1.0.0.

Check out the official Flutter WebView package here: https://pub.dartlang.org/packages/webview_flutter

Example Usage: #

Html(
  data: """
    <!--For a much more extensive example, look at example/main.dart-->
    <div>
      <h1>Demo Page</h1>
      <p>This is a fantastic nonexistent product that you should buy!</p>
      <h2>Pricing</h2>
      <p>Lorem ipsum <b>dolor</b> sit amet.</p>
      <h2>The Team</h2>
      <p>There isn't <i>really</i> a team...</p>
      <h2>Installation</h2>
      <p>You <u>cannot</u> install a nonexistent product!</p>
      <!--You can pretty much put any html in here!-->
    </div>
  """,
  //Optional parameters:
  padding: EdgeInsets.all(8.0),
  backgroundColor: Colors.white70,
  defaultTextStyle: TextStyle(fontFamily: 'serif'),
  linkStyle: const TextStyle(
    color: Colors.redAccent,
  ),
  onLinkTap: (url) {
    // open url in a webview
  },
  onImageTap: (src) {
    // Display the image in large form.
  },
  //Must have useRichText set to false for this to work.
  customRender: (node, children) {
    if(node is dom.Element) {
      switch(node.localName) {
        case "video": return Chewie(...);
        case "custom_tag": return CustomWidget(...);
      }
    }
  },
  customTextAlign: (dom.Node node) {
    if (node is dom.Element) {
      switch (node.localName) {
        case "p":
          return TextAlign.justify;
      }
    }
  },
  customTextStyle: (dom.Node node, TextStyle baseStyle) {
    if (node is dom.Element) {
      switch (node.localName) {
        case "p":
          return baseStyle.merge(TextStyle(height: 2, fontSize: 20));
      }
    }
    return baseStyle;
  },
)

useRichText parameter #

This package has a known issue where text does not wrap correctly. Setting useRichText to true fixes the issue by using an alternate parser. The alternate parser, however, does not support the customRender callback, and several elements supported by the default parser are not supported by the alternate parser (see #61 for a list).

[0.1.1] - 26th June 2020: #

  • Fixes of span tags at the start causing unwanted linebreaks
  • Fixes with images not always loading properly

example/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:html/dom.dart' as dom;

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: SingleChildScrollView(
          child: Html(
            data: """
    <div>
      <div id="header_set">
      <h1>Header 1</h1>
      <h2>Header 2</h2>
      <h3>Header 3</h3>
      <h4>Header 4</h4>
      <h5>Header 5</h5>
      <h6>Header 6</h6>
      <hr />
      Below hr
      <b>Bold</b>
      </div>
      <h1>Demo Page</h1>
      <p>This is a <u>fantastic</u> nonexistent product that you should really really really consider buying!</p>
      <a href="https://github.com">https://github.com</a><br />
      <br />
      <h2>Pricing</h2>
      <p>Lorem ipsum <b>dolor</b> sit amet.</p>
      <center>
        This is some center text... <abbr>ABBR</abbr> and <acronym>ACRONYM</acronym>
      </center>
      <h2>The Team</h2>
      <p>There isn't <i>really</i> a team...</p>
      <h2>Installation</h2>
      <p>You <u>cannot</u> install a nonexistent product!</p>
      <h2>Don't ask me to find <em>x</em> in</h2>
      <p>log<sub>2</sub>(<em>x</em><sup>2</sup> - 6<em>x</em>) = 3 + log<sub>2</sub>(1 - <em>x</em>)</p>
      <div id="bdi_test">
        <h3><code>bdi</code> and <code>bdo</code> Test:</h3>
        <p>
        In the example below, usernames are shown along with the number of points in a contest.
        If the bdi element is not supported in the browser, the username of the Arabic user would confuse the text (the bidirectional algorithm would put the colon and the number "90" next to the word "User" rather than next to the word "points").
        </p>
        
        <ul>
         <li>User <bdi>hrefs</bdi>: 60 points</li>
         <li>User <bdi>jdoe</bdi>: 80 points</li>
         <li>User <bdi>إيان</bdi>: 90 points</li>
         <bdo dir="rtl">Swapped!</bdo>
         <bdo dir="ltr">This text will go left to right!</bdo>
         <bdo dir="rtl">With bdi: User <bdi>إيان</bdi>: 90 points</bdo>
         <bdo dir="rtl">Without bdi: User إيان: 90 points</bdo>
         <bdo dir="ltr">ltr w/ bdi: User <bdi>إيان</bdi>: 90 points</bdo>
         <bdo dir="ltr">ltr w/o bdi: User إيان: 90 points</bdo>
        </ul>
      </div>
            <div>
              <table>
              <caption>This is the table's caption</caption>
                <tr><th>Head 1<sup>*</sup></th><th>Head 2</th><th>Head 3</th></tr>
                <tr><td>Data 1</td><td>Long Data 2</td><td>Really, realllllly, long data 3</td></tr>
                <tr><td>Data 1</td><td>Long <b>Data</b> 2</td><td>Really, realllllly, long data 3</td></tr>
                <tr><td>Data 1</td><td>Long Data 2</td><td>Really, realllllly, long data 3</td></tr>
                <tr><td>Different 1</td><td>Different reallllllly long 2</td><td>Diff 3</td></tr>
                <tr><td colspan="2">This spans 2 columns</td><td>Normal td</td></tr>
                <tfoot>
                <tr><td>In foot 1</td><td>In foot 2</td><td>In foot long 2</td></tr>
                </tfoot>
              </table>
            </div>
            <div>Nested div</div>
            <div>
            <pre>
            jQuery("#monkey");
            </pre>
            <br />
            <p><q>This is a fancy quote</q></p>
            <br />
            <br />
            Second nested div<br />
            <figure>
            <img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" />
            <figcaption>Available on GitHub</figcaption>
            </figure>
            </div>
            <div>Third nested div</div>
          </div>
          <h1>Second header</h1>
          <h1>Third header</h1>
          <div>Fourth div</div>
  """,
            //Optional parameters:
            padding: EdgeInsets.all(8.0),
            linkStyle: const TextStyle(
              color: Colors.redAccent,
              decorationColor: Colors.redAccent,
              decoration: TextDecoration.underline,
            ),
            onLinkTap: (url) {
              print("Opening $url...");
            },
            onImageTap: (src) {
              print(src);
            },
            //Must have useRichText set to false for this to work
            customRender: (node, children) {
              if (node is dom.Element) {
                switch (node.localName) {
                  case "custom_tag":
                    return Column(children: children);
                }
              }
              return null;
            },
            customTextAlign: (dom.Node node) {
              if (node is dom.Element) {
                switch (node.localName) {
                  case "p":
                    return TextAlign.justify;
                }
              }
              return null;
            },
            customTextStyle: (dom.Node node, TextStyle baseStyle) {
              if (node is dom.Element) {
                switch (node.localName) {
                  case "p":
                    return baseStyle.merge(TextStyle(height: 2, fontSize: 20));
                }
              }
              return baseStyle;
            },
          ),
        ),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_matrix_html: ^0.1.1

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flutter_matrix_html/flutter_html.dart';
import 'package:flutter_matrix_html/html_parser.dart';
import 'package:flutter_matrix_html/image_properties.dart';
import 'package:flutter_matrix_html/pill.dart';
import 'package:flutter_matrix_html/rich_text_parser.dart';
import 'package:flutter_matrix_html/spoiler.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
73
Health:
Code health derived from static analysis. [more]
3
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
60
Overall:
Weighted score of the above. [more]
49
Learn more about scoring.

We analyzed this package on Jul 9, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.14
  • Flutter: 1.17.5

Health issues and suggestions

Fix lib/rich_text_parser.dart. (-90.43 points)

Analysis of lib/rich_text_parser.dart failed with 8 errors, 9 hints, including:

line 35 col 1: Undefined class 'extension'.

line 35 col 1: This requires the 'extension-methods' experiment to be enabled.

line 35 col 20: Undefined class 'on'.

line 35 col 23: Functions must have an explicit list of parameters.

line 36 col 3: Can't have modifier 'static' here.

Fix lib/pill.dart. (-26.86 points)

Analysis of lib/pill.dart failed with 1 error, 5 hints, including:

line 58 col 17: This requires the 'control-flow-collections' experiment to be enabled.

line 3 col 8: Unused import: 'package:flutter_advanced_networkimage/provider.dart'.

line 8 col 9: The class 'Future' wasn't exported from 'dart:core' until version 2.1, but this code is required to be able to run on earlier versions.

line 22 col 30: The class 'Future' wasn't exported from 'dart:core' until version 2.1, but this code is required to be able to run on earlier versions.

line 36 col 29: Avoid using braces in interpolation when not needed.

Fix lib/flutter_html.dart. (-25 points)

Analysis of lib/flutter_html.dart failed with 1 error:

line 41 col 9: Color isn't a type.

Fix lib/html_parser.dart. (-25 points)

Analysis of lib/html_parser.dart failed with 1 error:

line 906 col 19: Color isn't a type.

Fix lib/spoiler.dart. (-25 points)

Analysis of lib/spoiler.dart failed with 1 error:

line 25 col 11: This requires the 'control-flow-collections' experiment to be enabled.

Maintenance issues and suggestions

No valid SDK. (-20 points)

The analysis could not detect a valid SDK that can use this package.

Use constrained dependencies. (-20 points)

The pubspec.yaml contains 1 dependency without version constraints. Specify version ranges for the following dependencies: flutter_advanced_networkimage.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.19.0 <3.0.0
flutter 0.0.0
flutter_advanced_networkimage any 0.7.0
html ^0.14.0 0.14.0+3
Transitive dependencies
charcode 1.1.3
collection 1.14.12 1.14.13
convert 2.1.1
csslib 0.16.1
file 5.2.1
flutter_svg 0.17.4 0.18.0
http 0.12.1
http_parser 3.1.4
intl 0.16.1
meta 1.1.8 1.2.2
path 1.7.0
path_drawing 0.4.1
path_parsing 0.1.4
path_provider 1.6.11
path_provider_linux 0.0.1+2
path_provider_macos 0.0.4+3
path_provider_platform_interface 1.0.2
pedantic 1.9.0 1.9.2
petitparser 3.0.4
platform 2.2.1
plugin_platform_interface 1.0.2
process 3.0.13
sky_engine 0.0.99
source_span 1.7.0
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6 1.2.0
vector_math 2.0.8 2.1.0-nullsafety
xdg_directories 0.1.0
xml 3.7.0 4.2.0
Dev dependencies
flutter_test