diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml
new file mode 100644
index 000000000..2a00db911
--- /dev/null
+++ b/.github/workflows/copilot-setup-steps.yml
@@ -0,0 +1,24 @@
+name: "Copilot Setup Steps"
+
+on:
+ workflow_dispatch:
+ push:
+ paths:
+ - .github/workflows/copilot-setup-steps.yml
+
+permissions:
+ contents: read
+
+jobs:
+ copilot-setup-steps:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+
+ - name: Setup Flutter
+ uses: subosito/flutter-action@fd55f4c5af5b953cc57a2be44cb082c8f6635e8e # v2.21.0
+ with:
+ cache: true
+
+ - run: ./tool/pub-get.sh
diff --git a/.vscode/mcp.json b/.vscode/mcp.json
new file mode 100644
index 000000000..167979c25
--- /dev/null
+++ b/.vscode/mcp.json
@@ -0,0 +1,8 @@
+{
+ "servers": {
+ "context7": {
+ "type": "http",
+ "url": "https://mcp.context7.com/mcp"
+ }
+ }
+}
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 000000000..7fa2cf0a4
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,30 @@
+# Repository Guidelines
+
+## Project Structure & Module Organization
+
+- `packages/`: Dart/Flutter packages. Core at `packages/core`, public wrapper at `packages/enhanced`, and feature add‑ons under `packages/fwfh_*`.
+- `demo_app/`: Example Flutter app for manual testing and screenshots.
+- `tool/`: Helper scripts (notably `tool/test.sh`).
+- `docs/`, `.github/`: Documentation and CI.
+ - Use `context7CompatibleLibraryID=/flutter/website` with `context7.get-library-docs` tool for latest Flutter documentation.
+- Tests live in each package’s `test/` and in `demo_app/test/`. Golden assets are under `test/images/`.
+
+## Build, Test, and Development Commands
+
+- Install latest deps: `./tool/pub-get.sh`.
+- Analyze all + run tests: `./tool/test.sh` (accepts extra flags like `--coverage` or `--update-goldens`).
+- Format code: `dart format .`.
+- Per‑package checks: `flutter analyze` and `flutter test` from each package dir.
+
+## Coding Style & Naming Conventions
+
+- Dart style with 2‑space indentation; keep lines focused and readable.
+- Lints: `package:lint` plus repo rules (see each `analysis_options.yaml`). Prefer relative imports, avoid relative `lib/` imports.
+- Names: classes `PascalCase`, members `camelCase`, constants `SCREAMING_SNAKE_CASE`, private with leading `_`.
+
+## Testing Guidelines
+
+- Frameworks: `flutter_test`, `test`, and `golden_toolkit` for widget/golden tests.
+- Location: place tests next to code in `package/test/*.dart` with `_test.dart` suffix.
+- Goldens: store expected images under `test/images/`; regenerate with `--update-goldens` and review diffs.
+- Web interop (when applicable): see `packages/fwfh_webview` integration tests; ensure Chrome/driver available if running locally.
diff --git a/packages/core/README.md b/packages/core/README.md
index 377f01f07..033ea0b8e 100644
--- a/packages/core/README.md
+++ b/packages/core/README.md
@@ -63,14 +63,23 @@ HtmlWidget(
// render a custom widget that inlines with surrounding text
return InlineCustomWidget(
child: FizzBuzzWidget(),
- )
+ );
}
return null;
},
// this callback will be triggered when user taps a link
- onTapUrl: (url) => print('tapped $url'),
+ // return true to indicate the tap has been handled
+ onTapUrl: (url) {
+ debugPrint('tapped $url');
+ return true;
+ },
+
+ // this callback will be triggered when user taps an image
+ onTapImage: (image) {
+ debugPrint('image tapped: \'${image.sources.first.url}\'');
+ },
// select the render mode for HTML body
// by default, a simple `Column` is rendered
@@ -82,6 +91,13 @@ HtmlWidget(
),
```
+## Callbacks
+
+- onTapUrl: return `true` to indicate the URL tap was handled; when not handled and the URL is an in-page anchor (e.g. `#id` or `${baseUrl}#id`), it scrolls to the anchor automatically.
+- onTapImage: receives `ImageMetadata`; access the first source via `image.sources.first.url`.
+- onLoadingBuilder: shown while the widget/image is loading; receives `loadingProgress` (0.0–1.0 or null).
+- onErrorBuilder: shown when a complex element fails to render; receives the thrown `error`.
+
## Features
### HTML tags
@@ -192,6 +208,6 @@ The [enhanced](https://pub.dev/packages/flutter_widget_from_html) package uses a
- [fwfh_url_launcher](https://pub.dev/packages/fwfh_url_launcher) to launch URLs
- [fwfh_webview](https://pub.dev/packages/fwfh_webview) for IFRAME support
-See [the extensibility document](https://github.com/daohoangson/flutter_widget_from_html/blob/v0.14.2/docs/extensibility.md) for detailed information.
+See [the extensibility document](https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/extensibility.md) for detailed information.
diff --git a/packages/enhanced/README.md b/packages/enhanced/README.md
index b54298a84..ab3e51f50 100644
--- a/packages/enhanced/README.md
+++ b/packages/enhanced/README.md
@@ -84,14 +84,23 @@ HtmlWidget(
// render a custom widget inline with surrounding text
return InlineCustomWidget(
child: FizzBuzzWidget(),
- )
+ );
}
return null;
},
// this callback will be triggered when user taps a link
- onTapUrl: (url) => print('tapped $url'),
+ // return true to indicate the tap has been handled
+ onTapUrl: (url) {
+ debugPrint('tapped $url');
+ return true;
+ },
+
+ // this callback will be triggered when user taps an image
+ onTapImage: (image) {
+ debugPrint('image tapped: \'${image.sources.first.url}\'');
+ },
// select the render mode for HTML body
// by default, a simple `Column` is rendered
@@ -103,6 +112,13 @@ HtmlWidget(
),
```
+## Callbacks
+
+- onTapUrl: return `true` to indicate the URL tap was handled; when not handled and the URL is an in-page anchor (e.g. `#id` or `${baseUrl}#id`), it scrolls to the anchor automatically.
+- onTapImage: receives `ImageMetadata`; access the first source via `image.sources.first.url`.
+- onLoadingBuilder: shown while the widget/image is loading; receives `loadingProgress` (0.0–1.0 or null).
+- onErrorBuilder: shown when a complex element fails to render; receives the thrown `error`.
+
## Features
### HTML tags
@@ -203,6 +219,6 @@ These tags and their contents will be ignored:
The [core](https://pub.dev/packages/flutter_widget_from_html_core) package implements widget building logic with high testing coverage to ensure correctness. It tries to render an optimal tree by using `RichText` with specific `TextStyle`, merging text spans together, showing images in sized box, etc. The idea is to build a solid foundation for apps to customize.
-See [the extensibility document](https://github.com/daohoangson/flutter_widget_from_html/blob/v0.14.2/docs/extensibility.md) for detailed information.
+See [the extensibility document](https://github.com/daohoangson/flutter_widget_from_html/blob/master/docs/extensibility.md) for detailed information.