'How can I render custom widget according to html tags using flutter_html package?

I have a HTML document and I want to render it with Flutter using flutter_html plugin. I want to render different typography differently. Eg. I want to have different font and size for bold and different for non-bold.

I tried reading the documentation which has a property for the Html constructor called customRenderer, I couldn't understand the implementation for it.

Below is the code from documentation.

  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>
    """,
    padding: EdgeInsets.all(8.0),
    backgroundColor: Colors.white70,
    defaultTextStyle: TextStyle(fontFamily: 'serif'),
    linkStyle: const TextStyle(
      color: Colors.redAccent,
    ),
    onLinkTap: (url) {
    },
    customRender: (node, children) {
      if(node is dom.Element) {
        switch(node.localName) {
          case "video": return Chewie(...);
          case "custom_tag": return CustomWidget(...);
        }
      }
    },
  )

If I just can change font size and font family according to the tag name, it will do.



Solution 1:[1]

On mobile you can use webview_flutter to display html script on a page.

WebView(
  javascriptMode: JavascriptMode.unrestricted,
  onWebViewCreated: (WebViewController webViewController) {
    final String contentBase64 = base64Encode(const Utf8Encoder().convert(Source.html));
    webViewController.loadUrl('data:text/html;base64,$contentBase64');
  },
),

If you're planning to use this on web, you can use dart:html

void main() {
  // ignore: undefined_prefixed_name
  ui.platformViewRegistry.registerViewFactory(
      'html-view-tag',
      (int viewId) => IFrameElement()
        ..srcdoc = Source.html
        ..style.border = 'none');

  runApp(const MyApp());
}

and on your Screen, add HtmlElementView like a Widget

body: Center(
  child: HtmlElementView(viewType: 'html-view-tag')
),

I just defined the source html like this

class Source {
  static const html =
      '<!--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>';
}

Solution 2:[2]

Here's a sample using flutter_html. (as of typing this you should go with flutter_html_all. Same package but there has been some renaming. customRender is now customRenders (plural))

return Html(
    data: <span>Some normal HTML</span> then appears a <customtag>Some data in this one</customtag>,
    tagsList: Html.tags..addAll(['customtag']),
    customRenders:
    {
        customTagMatcher(): CustomRender.widget(widget: (context, buildChildren)
        {
            final element = context.tree.element!;

            // Your conditions with the element.
            // finally return your own custom widget:
            return Container(child: Text('My custom widget...'));
        }),
    }
);

CustomRenderMatcher customTagMatcher() => (context) => context.tree.element?.localName == 'customtag';

More info: https://github.com/Sub6Resources/flutter_html#customrenders https://github.com/Sub6Resources/flutter_html/discussions/973

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Omatt
Solution 2 Michal Šrůtek