# flutter_html **Repository Path**: plugin-flutter/flutter_html ## Basic Information - **Project Name**: flutter_html - **Description**: 富文本flutter_html富文本flutter_html - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-05-24 - **Last Updated**: 2023-07-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # flutter_html [![pub package](https://img.shields.io/pub/v/flutter_html.svg)](https://pub.dev/packages/flutter_html) [![codecov](https://codecov.io/gh/Sub6Resources/flutter_html/branch/master/graph/badge.svg)](https://codecov.io/gh/Sub6Resources/flutter_html) [![CircleCI](https://circleci.com/gh/Sub6Resources/flutter_html.svg?style=svg)](https://circleci.com/gh/Sub6Resources/flutter_html) [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/Sub6Resources/flutter_html/blob/master/LICENSE) A Flutter widget for rendering HTML and CSS as Flutter widgets.
Screenshot 1 Screenshot 2 Screenshot 3
A Screenshot of flutter_html Another Screenshot of flutter_html Yet another Screenshot of flutter_html
## Table of Contents: - [Installing](#installing) - [Currently Supported HTML Tags](#currently-supported-html-tags) - [Currently Supported CSS Attributes](#currently-supported-css-attributes) - [Currently Supported Inline CSS Attributes](#currently-supported-inline-css-attributes) - [Why flutter_html?](#why-this-package) - [API Reference](#api-reference) - [Constructors](#constructors) - [Selectable Text](#selectable-text) - [Parameters Table](#parameters) - [Getters](#getters) - [Data](#data) - [Document](#document) - [onLinkTap](#onlinktap) - [customRender](#customrender) - [onImageError](#onimageerror) - [onMathError](#onmatherror) - [onImageTap](#onimagetap) - [tagsList](#tagslist) - [style](#style) - [navigationDelegateForIframe](#navigationdelegateforiframe) - [customImageRender](#customimagerender) - [typedef ImageSourceMatcher (with examples)](#typedef-imagesourcematcher) - [typedef ImageRender (with examples)](#typedef-imagerender) - [Extended examples](#example-usages---customimagerender) - [Rendering Reference](#rendering-reference) - [Image](#image) - [Iframe](#iframe) - [Audio](#audio) - [Video](#video) - [SVG](#svg) - [MathML](#mathml) - [Tex](#tex) - [Table](#table) - [Notes](#notes) - [Migration Guide](#migration-guides) - [Contribution Guide](#contribution-guide) ## Installing: Add the following to your `pubspec.yaml` file: dependencies: flutter_html: ^2.2.1 ## Currently Supported HTML Tags: | | | | | | | | | | | | |------------|-----------|-------|-------------|---------|---------|-------|------|--------|--------|--------| |`a` | `abbr` | `acronym`| `address` | `article`| `aside` | `audio`| `b` | `bdi` | `bdo` | `big` | |`blockquote`| `body` | `br` | `caption` | `cite` | `code` | `data`| `dd` | `del` | `details` | `dfn` | | `div` | `dl` | `dt` | `em` | `figcaption`| `figure`| `footer`| `font` | `h1` | `h2` | `h3` | | `h4` | `h5` |`h6` | `header` | `hr` | `i` | `iframe`| `img` | `ins` | `kbd`| `li` | | `main` | `mark` | `nav` | `noscript`|`ol` | `p` | `pre` | `q` | `rp` | `rt` | `ruby` | | `s` | `samp` | `section` | `small` | `span`| `strike` | `strong`| `sub` | `sup` | `summary` | `svg`| | `table` | `tbody` | `td` | `template` | `tfoot` | `th` | `thead` |`time` | `tr` | `tt` | `u` | | `ul` | `var` | `video` | `math`: | `mrow` | `msup` | `msub` | `mover` | `munder` | `msubsup` | `moverunder` | | `mfrac` | `mlongdiv` | `msqrt` | `mroot` | `mi` | `mn` | `mo` | | | | | ## Currently Supported CSS Attributes: | | | | | | | | |------------------|--------|------------|----------|--------------|------------------------|------------| |`background-color`| `color`| `direction`| `display`| `font-family`| `font-feature-settings`| `font-size`| |`font-style` | `font-weight`| `height` | `letter-spacing`| `line-height`| `list-style-type` | `list-style-position`| |`padding` | `margin`| `text-align`| `text-decoration`| `text-decoration-color`| `text-decoration-style`| `text-decoration-thickness`| |`text-shadow` | `vertical-align`| `white-space`| `width` | `word-spacing`| | | ## Currently Supported Inline CSS Attributes: | | | | | | | | |------------------|--------|------------|----------|--------------|------------------------|------------| |`background-color`| `border` (including specific directions) | `color`| `direction`| `display`| `font-family`| `font-feature-settings` | | `font-size`|`font-style` | `font-weight`| `line-height` | `list-style-type` | `list-style-position`|`padding` (including specific directions) | | `margin` (including specific directions) | `text-align`| `text-decoration`| `text-decoration-color`| `text-decoration-style`| `text-shadow` | | Don't see a tag or attribute you need? File a feature request or contribute to the project! ## Why this package? This package is designed with simplicity in mind. Originally created to allow basic rendering of HTML content into the Flutter widget tree, this project has expanded to include support for basic styling as well! If you need something more robust and customizable, the package also provides a number of optional custom APIs for extremely granular control over widget rendering! ## API Reference: For the full API reference, see [here](https://pub.dev/documentation/flutter_html/latest/). For a full example, see [here](https://github.com/Sub6Resources/flutter_html/tree/master/example). Below, you will find brief descriptions of the parameters the`Html` widget accepts and some code snippets to help you use this package. ### Constructors: The package currently has two different constructors - `Html()` and `Html.fromDom()`. The `Html()` constructor is for those who would like to directly pass HTML from the source to the package to be rendered. If you would like to modify or sanitize the HTML before rendering it, then `Html.fromDom()` is for you - you can convert the HTML string to a `Document` and use its methods to modify the HTML as you wish. Then, you can directly pass the modified `Document` to the package. This eliminates the need to parse the modified `Document` back to a string, pass to `Html()`, and convert back to a `Document`, thus cutting down on load times. #### Selectable Text The package also has two constructors for selectable text support - `SelectableHtml()` and `SelectableHtml.fromDom()`. The difference between the two is the same as noted above. Please note: Due to Flutter [#38474](https://github.com/flutter/flutter/issues/38474), selectable text support is significantly watered down compared to the standard non-selectable version of the widget. The changes are as follows: 1. The list of tags that can be rendered is significantly reduced. Key omissions include no support for images/video/audio, table, and ul/ol. 2. No support for `customRender`, `customImageRender`, `onImageError`, `onImageTap`, `onMathError`, and `navigationDelegateForIframe`. (Support for `customRender` may be added in the future). 3. Styling support is significantly reduced. Only text-related styling works (e.g. bold or italic), while container related styling (e.g. borders or padding/margin) do not work. Once the above issue is resolved, the aforementioned compromises will go away. Currently the `SelectableText.rich()` constructor does not support `WidgetSpan`s, resulting in the feature losses above. ### Parameters: | Parameters | Description | |--------------|-----------------| | `data` | The HTML data passed to the `Html` widget. This is required and cannot be null when using `Html()`. | | `document` | The DOM document passed to the `Html` widget. This is required and cannot be null when using `Html.fromDom()`. | | `onLinkTap` | A function that defines what the widget should do when a link is tapped. The function exposes the `src` of the link as a `String` to use in your implementation. | | `customRender` | A powerful API that allows you to customize everything when rendering a specific HTML tag. | | `onImageError` | A function that defines what the widget should do when an image fails to load. The function exposes the exception `Object` and `StackTrace` to use in your implementation. | | `onMathError` | A function that defines what the widget should do when a math fails to render. The function exposes the parsed Tex `String`, as well as the error and error with type from `flutter_math` as a `String`. | | `shrinkWrap` | A `bool` used while rendering different widgets to specify whether they should be shrink-wrapped or not, like `ContainerSpan` | | `onImageTap` | A function that defines what the widget should do when an image is tapped. The function exposes the `src` of the image as a `String` to use in your implementation. | | `tagsList` | A list of elements the `Html` widget should render. The list should contain the tags of the HTML elements you wish to include. | | `style` | A powerful API that allows you to customize the style that should be used when rendering a specific HTMl tag. | | `navigationDelegateForIframe` | Allows you to set the `NavigationDelegate` for the `WebView`s of all the iframes rendered by the `Html` widget. | | `customImageRender` | A powerful API that allows you to fully customize how images are loaded. | | `selectionControls` | A custom text selection controls that allow you to override default toolbar and build toolbar with custom text selection options. See an [example](https://github.com/justinmc/flutter-text-selection-menu-examples/blob/master/lib/custom_menu_page.dart). | ### Getters: 1. `Html.tags`. This provides a list of all the tags the package renders. The main use case is to assist in excluding elements using `tagsList`. See an [example](#example-usage---tagslist---excluding-tags) below. 2. `SelectableHtml.tags`. This provides a list of all the tags that can be rendered in selectable mode. ### Data: The HTML data passed to the `Html` widget as a `String`. This is required and cannot be null when using `Html`. Any HTML tags in the `String` that are not supported by the package will not be rendered. #### Example Usage - Data: ```dart Widget html = Html( data: """

Demo Page

This is a fantastic product that you should buy!

Features

""", ); ``` ### Document: The DOM document passed to the `Html` widget as a `Document`. This is required and cannot be null when using `Html.fromDom()`. Any HTML tags in the document that are not supported by the package will not be rendered. Using the `Html.fromDom()` constructor can be useful when you would like to sanitize the HTML string yourself before passing it to the package. #### Example Usage - Document: ```dart import 'package:html/parser.dart' as htmlparser; import 'package:html/dom.dart' as dom; ... String htmlData = """

Demo Page

This is a fantastic product that you should buy!

Features

"""; dom.Document document = htmlparser.parse(htmlData); /// sanitize or query document here Widget html = Html( document: document, ); ``` ### onLinkTap: A function that defines what the widget should do when a link is tapped. #### Example Usage - onLinkTap: ```dart Widget html = Html( data: """

Linking to websites has never been easier.

""", onLinkTap: (String? url, RenderContext context, Map attributes, dom.Element? element) { //open URL in webview, or launch URL in browser, or any other logic here } ); ``` Inner links (such as `Back to the top` will work out of the box by scrolling the viewport, as long as your `Html` widget is wrapped in a scroll container such as a `SingleChildScrollView`. ### customRender: A powerful API that allows you to customize everything when rendering a specific HTML tag. This means you can change the default behaviour or add support for HTML elements that aren't supported natively. You can also make up your own custom tags in your HTML! `customRender` accepts a `Map`. The `CustomRender` type is a function that requires a `Widget` or `InlineSpan` to be returned. It exposes `RenderContext` and the `Widget` that would have been rendered by `Html` without a `customRender` defined. The `RenderContext` contains the build context, styling and the HTML element, with attrributes and its subtree,. To use this API, set the key as the tag of the HTML element you wish to provide a custom implementation for, and create a function with the above parameters that returns a `Widget` or `InlineSpan`. Note: If you add any custom tags, you must add these tags to the [`tagsList`](#tagslist) parameter, otherwise they will not be rendered. See below for an example. #### Example Usages - customRender: 1. Simple example - rendering custom HTML tags ```dart Widget html = Html( data: """

Display bird element and flutter element

""", customRender: { "bird": (RenderContext context, Widget child) { return TextSpan(text: "🐦"); }, "flutter": (RenderContext context, Widget child) { return FlutterLogo( style: (context.tree.element!.attributes['horizontal'] != null) ? FlutterLogoStyle.horizontal : FlutterLogoStyle.markOnly, textColor: context.style.color!, size: context.style.fontSize!.size! * 5, ); }, }, tagsList: Html.tags..addAll(["bird", "flutter"]), ); ``` 2. Complex example - wrapping the default widget with your own, in this case placing a horizontal scroll around a (potentially too wide) table.
View code ```dart Widget html = Html( data: """
Monthly savings
January February March April May June July August September October November December
\$100 \$50 \$80 \$60 \$90 \$140 \$110 \$80 \$90 \$60 \$40 \$70
\90 \$60 \$80 \$80 \$100 \$160 \$150 \$110 \$100 \$60 \$30 \$80
""", customRender: { "table": (context, child) { return SingleChildScrollView( scrollDirection: Axis.horizontal, child: (context.tree as TableLayoutElement).toWidget(context), ); } }, ); ```
3. Complex example - rendering an `iframe` differently based on whether it is an embedded youtube video or some other embedded content.
View code ```dart Widget html = Html( data: """

Google iframe:

YouTube iframe:

""", customRender: { "iframe": (RenderContext context, Widget child) { final attrs = context.tree.element?.attributes; if (attrs != null) { double? width = double.tryParse(attrs['width'] ?? ""); double? height = double.tryParse(attrs['height'] ?? ""); return Container( width: width ?? (height ?? 150) * 2, height: height ?? (width ?? 300) / 2, child: WebView( initialUrl: attrs['src'] ?? "about:blank", javascriptMode: JavascriptMode.unrestricted, //no need for scrolling gesture recognizers on embedded youtube, so set gestureRecognizers null //on other iframe content scrolling might be necessary, so use VerticalDragGestureRecognizer gestureRecognizers: attrs['src'] != null && attrs['src']!.contains("youtube.com/embed") ? null : [ Factory(() => VerticalDragGestureRecognizer()) ].toSet(), navigationDelegate: (NavigationRequest request) async { //no need to load any url besides the embedded youtube url when displaying embedded youtube, so prevent url loading //on other iframe content allow all url loading if (attrs['src'] != null && attrs['src']!.contains("youtube.com/embed")) { if (!request.url.contains("youtube.com/embed")) { return NavigationDecision.prevent; } else { return NavigationDecision.navigate; } } else { return NavigationDecision.navigate; } }, ), ); } else { return Container(height: 0); } } } ); ```
More example usages and in-depth details available [here](https://github.com/Sub6Resources/flutter_html/wiki/All-About-customRender). ### onImageError: A function that defines what the widget should do when an image fails to load. The function exposes the exception `Object` and `StackTrace` to use in your implementation. #### Example Usage - onImageError: ```dart Widget html = Html( data: """Alt Text of an intentionally broken image""", onImageError: (Exception exception, StackTrace stackTrace) { FirebaseCrashlytics.instance.recordError(exception, stackTrace); }, ); ``` ### onMathError: A function that defines what the widget should do when a math fails to render. The function exposes the parsed Tex `String`, as well as the error and error with type from `flutter_math` as a `String`. #### Example Usage - onMathError: ```dart Widget html = Html( data: """""", onMathError: (String parsedTex, String error, String errorWithType) { //your logic here. A Widget must be returned from this function: return Text(error); //you can also try and fix the parsing yourself: return Math.tex(correctedParsedTex); }, ); ``` ### onImageTap: A function that defines what the widget should do when an image is tapped. #### Example Usage - onImageTap: ```dart Widget html = Html( data: """Google""", onImageTap: (String? url, RenderContext context, Map attributes, dom.Element? element) { //open image in webview, or launch image in browser, or any other logic here } ); ``` ### tagsList: A list of elements the `Html` widget should render. The list should contain the tags of the HTML elements you wish to whitelist. #### Example Usage - tagsList - Excluding Tags: You may have instances where you can choose between two different types of HTML tags to display the same content. In the example below, the `