### Changelog Entry Example
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/runbook/release.md
An example of a changelog entry for a new version, listing features and fixes with references to PRs/issues and contributors.
```markdown
## 0.17.2
- Add `text-emphasis` / `text-emphasis-style` support (#1561, authored by @CaptainDario)
- Fix border-radius with background-color for inline elements (#1569)
```
--------------------------------
### Register Custom BuildOp for Rendering
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/extensibility.md
Implement complex functionalities by registering a `BuildOp`. This example shows how to modify the tree on parsing or customize block rendering.
```dart
tree.register(BuildOp(
onParsed: (tree) {
// can be used to change text, inline contents, etc.
return tree..append(...);
},
onRenderBlock: (tree, child) {
// use this to render special widget, wrap it into something else, etc.
return MyCustomWidget(child: child);
},
// depending on the rendering logic, you may need to adjust the execution order to "jump the line"
priority: 9999,
));
```
--------------------------------
### BuildOp: Modifying Build Tree (Before)
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/migration.md
This example shows the older method of modifying the build tree using detach, insertBefore, and insertAfter within the onTreeFlattening callback.
```dart
final oldOp = BuildOp(
onTreeFlattening: (meta, tree) {
final foo = WidgetBit.inline(tree.parent!, Text('foo'));
foo.insertBefore(tree);
tree.detach();
}
)
```
--------------------------------
### Implement Custom WidgetFactory with Chewie
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/packages/fwfh_chewie/README.md
Extend WidgetFactory and mix in ChewieFactory to enable Chewie video playback within HtmlWidget. This setup is necessary for rendering video tags.
```dart
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:fwfh_chewie/fwfh_chewie.dart';
// ...
HtmlWidget(
html,
factoryBuilder: () => MyWidgetFactory(),
)
// ...
class MyWidgetFactory extends WidgetFactory with ChewieFactory {
}
```
--------------------------------
### BuildOp: Modifying Build Tree (After)
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/migration.md
The new approach uses the onParsed callback to return a new tree, allowing for more declarative modifications. This example demonstrates creating a new subtree and appending a custom widget.
```dart
final newOp = BuildOp(
onParsed: (tree) {
final newTree = tree.parent.sub();
newTree.append(WidgetBit.inline(tree, Text('foo')));
return newTree;
}
)
```
--------------------------------
### Replace Smilie Image with Emoji
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/extensibility.md
This example demonstrates replacing inline smilie images with corresponding emojis by creating a custom `WidgetFactory` and `BuildOp`.
```dart
const kHtml = """
Hello !
How are you ?
""";
const kSmilies = {':)': '๐'};
class SmilieScreen extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text('SmilieScreen'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: HtmlWidget(
kHtml,
factoryBuilder: () => _SmiliesWidgetFactory(),
),
),
);
}
class _SmiliesWidgetFactory extends WidgetFactory {
final smilieOp = BuildOp(
onParsed: (tree) {
final alt = tree.element.attributes['alt'];
return tree..addText(kSmilies[alt] ?? alt ?? '');
},
);
@override
void parse(BuildTree tree) {
final e = tree.element;
if (e.localName == 'img' &&
e.classes.contains('smilie') &&
e.attributes.containsKey('alt')) {
tree.register(smilieOp);
return;
}
return super.parse(tree);
}
}
```
--------------------------------
### Compose Custom WidgetFactory with Mixins
Source: https://context7.com/daohoangson/flutter_widget_from_html/llms.txt
Combine specific mixins to create a custom `WidgetFactory`. This example includes mixins for cached network images, URL launching, and SVG rendering. Configure mixin getters like `svgAllowDrawingOutsideViewBox` to customize behavior. Use this custom factory with `HtmlWidget` to control how HTML content is rendered.
```dart
// pubspec.yaml
// dependencies:
// flutter_widget_from_html_core: ^0.17.2
// fwfh_cached_network_image: ^0.16.0
// fwfh_url_launcher: ^0.16.0
// fwfh_svg: ^0.16.0
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:fwfh_cached_network_image/fwfh_cached_network_image.dart';
import 'package:fwfh_url_launcher/fwfh_url_launcher.dart';
import 'package:fwfh_svg/fwfh_svg.dart';
import 'package:flutter/material.dart';
// Combine only the mixins you need
class AppWidgetFactory extends WidgetFactory
with CachedNetworkImageFactory, UrlLauncherFactory, SvgFactory {
// Optional: override any mixin getter to configure behavior
@override
bool get svgAllowDrawingOutsideViewBox => false;
}
class ContentWidget extends StatelessWidget {
final String html;
const ContentWidget({super.key, required this.html});
static final _factory = AppWidgetFactory();
@override
Widget build(BuildContext context) {
return HtmlWidget(
html,
factoryBuilder: () => _factory,
renderMode: RenderMode.column,
textStyle: const TextStyle(fontSize: 15, height: 1.5),
customStylesBuilder: (element) {
if (element.localName == 'code') {
return {'background-color': '#f4f4f4', 'font-family': 'monospace'};
}
return null;
},
onTapUrl: (url) {
// Handle internal links manually; let UrlLauncherFactory open the rest
if (url.startsWith('/')) {
debugPrint('Internal navigation to $url');
return true; // handled
}
return false; // delegate to url_launcher
},
);
}
}
```
--------------------------------
### Create a Custom WidgetFactory
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/extensibility.md
Extend `WidgetFactory` to gain complete control over the rendering process. Override methods like `parse` to modify how the DOM is converted into Flutter widgets. This example shows a basic extension.
```dart
class _MyWidgetFactory extends WidgetFactory {
@override
void parse(BuildTree tree) {
// do something
super.parse(tree);
}
}
// somewhere in your app
HtmlWidget(
'Hello World!',
factoryBuilder: () => _MyWidgetFactory(),
),
```
--------------------------------
### Implement Custom WidgetFactory with CachedNetworkImageFactory
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/packages/fwfh_cached_network_image/README.md
Extend WidgetFactory and mix in CachedNetworkImageFactory to enable cached network image rendering within HtmlWidget. This setup is used when initializing HtmlWidget with a custom factory.
```dart
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:fwfh_cached_network_image/fwfh_cached_network_image.dart';
// ...
HtmlWidget(
html,
factoryBuilder: () => MyWidgetFactory(),
)
// ...
class MyWidgetFactory extends WidgetFactory with CachedNetworkImageFactory {}
```
--------------------------------
### Update Demo App Files Script
Source: https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/runbook/release.md
Execute this script to regenerate platform files and pubspec.lock for the demo application. The changes should then be committed.
```sh
./tool/update-demo_app-files.sh
```
--------------------------------
### Embed Media with ChewieFactory and JustAudioFactory
Source: https://context7.com/daohoangson/flutter_widget_from_html/llms.txt
Combine `ChewieFactory` for `