From a0dd16d7de4d770c4eead0a919d7e2ff83edc784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguye=CC=82=CC=83n=20Tua=CC=82=CC=81n=20Vie=CC=A3=CC=82t?= Date: Sat, 10 Oct 2026 16:07:31 +0700 Subject: [PATCH] =?UTF-8?q?chore:=201.13.1=20=E2=80=94=20slimmer=20archive?= =?UTF-8?q?,=20corrected=20docs=20(widgetBuilder=20signature,=20box-sizing?= =?UTF-8?q?,=20position)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pubignore | 9 +++++++++ CHANGELOG.md | 8 ++++++++ MIGRATION.md | 2 +- README.md | 6 +++--- doc/CSS_PROPERTIES_MATRIX.md | 4 ++-- doc/LIMITATIONS.md | 2 +- doc/PERFORMANCE_TUNING.md | 16 ++++++++-------- doc/README.md | 2 +- doc/SECURITY_BEST_PRACTICES.md | 6 +++--- doc/SUPPORTED_HTML.md | 6 +++--- example/lib/formula_demo.dart | 7 +++---- pubspec.yaml | 2 +- test/docs_matrix_sync_test.dart | 4 ++++ 13 files changed, 47 insertions(+), 27 deletions(-) diff --git a/.pubignore b/.pubignore index ac9cb9c..fb5939c 100644 --- a/.pubignore +++ b/.pubignore @@ -71,3 +71,12 @@ coverage/ # macOS artifacts **/.DS_Store **/Pods/ + +# Sub-packages are published on their own; the root package depends on +# hyper_render_core through pub.dev, so shipping their sources only doubles +# the archive size. +packages/ + +# Screen-recording entry point for the README GIFs (reads a local /tmp file); +# nothing imports it. +example/lib/demo_auto_player.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index af61ff5..b29705e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 1.13.1 + +Packaging and documentation only; no code changes in the library. + +- **Smaller download:** the archive no longer ships `packages/` (the sub-packages are published on their own and `hyper_render_core` is a normal pub.dev dependency) or the GIF-recording entry point `example/lib/demo_auto_player.dart`. About 32 MB → 18 MB. +- **Docs corrected:** every `widgetBuilder: (context, node) { ... }` example (README, MIGRATION, security and performance guides) did not compile. The callback is `Widget? Function(UDTNode node)`. `node.isImage` does not exist; examples use `node.tagName == 'img'`. +- **Docs no longer over-claim:** `box-sizing` and `position: relative` were listed as supported. They are parsed but not applied (`width` always sizes the content box; `top`/`left` do not move the element). The CSS matrix, `SUPPORTED_HTML.md` and `LIMITATIONS.md` now say so, and the docs-sync test guards both rows. + ## 1.13.0 - **Character-range highlight boxes:** `RenderHyperBox.getBoxesForCharRange(charStart, charEnd)` returns the rects of a character range, for drawing your own highlights (search hits, annotations, read-aloud). Offsets are local to each `RenderHyperBox`, so in virtualized / `auto` mode (>10k chars) they restart at 0 per chunk. Also new: `RenderHyperBox.debugLineFragments()` for the laid-out fragment geometry. By [@DrkXo](https://github.com/DrkXo) ([#26](https://github.com/brewkits/hyper_render/pull/26)). diff --git a/MIGRATION.md b/MIGRATION.md index f20585b..8555385 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -114,7 +114,7 @@ HtmlWidget( // HyperRender HyperViewer( html: html, - widgetBuilder: (context, node) { + widgetBuilder: (node) { if (node is AtomicNode && node.tagName == 'iframe') return MyWidget(); return null; // fall through to default rendering }, diff --git a/README.md b/README.md index b040a5f..322182b 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Already using `flutter_html`? You don't need to rewrite your widget tree or lear ```dart // 1. In your pubspec.yaml: // dependencies: -// hyper_render: ^1.13.0 +// hyper_render: ^1.13.1 // 2. In your Dart file — replace this single line: // ❌ import 'package:flutter_html/flutter_html.dart'; @@ -68,7 +68,7 @@ Html( ```yaml dependencies: - hyper_render: ^1.13.0 + hyper_render: ^1.13.1 ``` ```dart @@ -432,7 +432,7 @@ ctrl.scrollToOffset(1200); // absolute pixel offset ```dart HyperViewer( html: html, - widgetBuilder: (context, node) { + widgetBuilder: (node) { if (node is AtomicNode && node.tagName == 'iframe') { return YoutubePlayer(url: node.attributes['src'] ?? ''); } diff --git a/doc/CSS_PROPERTIES_MATRIX.md b/doc/CSS_PROPERTIES_MATRIX.md index 944f926..c751aa1 100644 --- a/doc/CSS_PROPERTIES_MATRIX.md +++ b/doc/CSS_PROPERTIES_MATRIX.md @@ -45,7 +45,7 @@ This document lists CSS property support in HyperRender. | `border-style` | ✅ | solid, dashed, dotted, double, none | Custom styles beyond Flutter defaults | | `border-color` | ✅ | All color formats | | | `border-radius` | ✅ | px, % | All 4 corners + shorthand | -| `box-sizing` | ✅ | border-box, content-box | Full support | +| `box-sizing` | ❌ | — | Parsed, not applied: `width` always sizes the content box, so `border-box` is ignored (measured: `width:200px;padding:20px` wraps at 200px with or without it) | | `aspect-ratio` | ✅ | W/H, bare number, auto | Applied to img/video sizing (v1.4.0) | --- @@ -59,7 +59,7 @@ This document lists CSS property support in HyperRender. | `opacity` | ✅ | 0-1 | | | `overflow` | ⚠️ | hidden, visible | No scroll support | | `position: static` | ✅ | static | Default | -| `position: relative` | ✅ | relative | Supported | +| `position: relative` | ❌ | — | Parsed, not applied: `top` / `left` offsets do not move the element | | `position: absolute` | ❌ | — | Use `pluginRegistry` for overlay widgets | | `position: fixed` | ❌ | — | Use `pluginRegistry` for overlay widgets | | `top` / `right` / `bottom` / `left` | ❌ | — | Requires absolute/fixed; not supported | diff --git a/doc/LIMITATIONS.md b/doc/LIMITATIONS.md index a0e75cf..419b403 100644 --- a/doc/LIMITATIONS.md +++ b/doc/LIMITATIONS.md @@ -46,7 +46,7 @@ are silently ignored. | Property | Limitation | |----------|------------| | `opacity` | Applied per-element; stacking context opacity not propagated | -| `position: relative` | Supported but child `absolute` positioning is not | +| `position: relative` / `box-sizing: border-box` | Parsed but not applied: no offset for `relative`, and `width` always sizes the content box | | `calc()` | Arithmetic on px/em/rem only; `%` in calc not resolved | | `text-align` | Center/right/justify on canvas paragraphs, LTR and box-level RTL (`textDirection: rtl`). An explicit `text-align` overrides RTL's default right edge; `justify` in RTL is not yet distributed (keeps the start edge) | | `float` scope | A float reserves a box from the element's own `width`/`height`; it does **not** lay the floated element's content out inside that box. So float works for replaced elements (``) and for empty, explicitly sized boxes (`
`) — text wraps beside both. It does **not** work for an element sized by its own text: a floated `
` with content renders that content in normal flow while still reserving a phantom float box, which can make the block *taller* than not floating it; a floated inline `` (the drop-cap idiom) has no effect at all. Pinned by `test/flagship_execution_audit_test.dart` | diff --git a/doc/PERFORMANCE_TUNING.md b/doc/PERFORMANCE_TUNING.md index 4964bed..680f3c4 100644 --- a/doc/PERFORMANCE_TUNING.md +++ b/doc/PERFORMANCE_TUNING.md @@ -1,7 +1,7 @@ # Performance Tuning Guide -Last Updated: June 2026 -Version: 1.4.0 +Last Updated: October 2026 +Version: 1.13.0 This guide helps you optimize HyperRender performance for different use cases. @@ -40,7 +40,7 @@ DON'T: HyperRender offers 3 render modes optimized for different scenarios: -### 1. HyperRenderMode.sync (Default for small content) +### 1. HyperRenderMode.sync (best for small content) How it works: - Parses HTML on main thread (synchronous) @@ -170,7 +170,7 @@ void main() { ```dart HyperViewer( html: content, - widgetBuilder: (context, node) { + widgetBuilder: (node) { if (node is AtomicNode && node.tagName == 'img') { final src = node.src; if (src == null) return null; @@ -421,8 +421,8 @@ HyperViewer( ) // Lazy-load images -widgetBuilder: (context, node) { - if (node is AtomicNode && node.isImage) { +widgetBuilder: (node) { + if (node is AtomicNode && node.tagName == 'img') { return CachedNetworkImage( imageUrl: node.src!, placeholder: (context, url) => Shimmer(...), @@ -513,8 +513,8 @@ HyperViewer( ```dart HyperViewer( html: content, - widgetBuilder: (context, node) { - if (node is AtomicNode && node.isImage) { + widgetBuilder: (node) { + if (node is AtomicNode && node.tagName == 'img') { return CachedNetworkImage( imageUrl: node.src!, memCacheWidth: 800, diff --git a/doc/README.md b/doc/README.md index e49f842..a719a60 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,6 +1,6 @@ # HyperRender Documentation -Welcome to the documentation for **HyperRender v1.13.0** — the high-performance HTML/Markdown renderer for Flutter. +Welcome to the documentation for **HyperRender v1.13.1** — the high-performance HTML/Markdown renderer for Flutter. ## Documentation Index diff --git a/doc/SECURITY_BEST_PRACTICES.md b/doc/SECURITY_BEST_PRACTICES.md index 4f8817b..5811ae1 100644 --- a/doc/SECURITY_BEST_PRACTICES.md +++ b/doc/SECURITY_BEST_PRACTICES.md @@ -270,7 +270,7 @@ When using `widgetBuilder`, validate the input: ```dart HyperViewer( html: content, - widgetBuilder: (context, node) { + widgetBuilder: (node) { // Validate node properties if (node.tagName == 'custom-widget') { final dataUrl = node.attributes['data-url']; @@ -295,7 +295,7 @@ HyperViewer( ```dart HyperViewer( html: content, - widgetBuilder: (context, node) { + widgetBuilder: (node) { if (node is AtomicNode && node.isVideo) { final videoUrl = node.src; @@ -412,7 +412,7 @@ Defense: allowedTags: const {'p', 'strong', 'em'}, // No 'img' // Option 2: Proxy images through your server -widgetBuilder: (context, node) { +widgetBuilder: (node) { if (node is AtomicNode && node.tagName == 'img') { final src = node.src; if (src != null && src.startsWith('https://yourcdn.com/')) { diff --git a/doc/SUPPORTED_HTML.md b/doc/SUPPORTED_HTML.md index 4dd8d2a..2a30ea1 100644 --- a/doc/SUPPORTED_HTML.md +++ b/doc/SUPPORTED_HTML.md @@ -97,7 +97,7 @@ or the `fallbackBuilder` parameter to delegate to a WebView or other renderer. | `border` | width, style, color | | `border-style` | solid, dashed, dotted, double, none | | `border-radius` | px, % | -| `box-sizing` | border-box, content-box | +| `box-sizing` | **Not applied** — `width` always sizes the content box | | `overflow` | visible, hidden | ### Layout @@ -107,7 +107,7 @@ or the `fallbackBuilder` parameter to delegate to a WebView or other renderer. | `display` | block, inline, inline-block, none, flex, grid, table | | `float` | left, right, none (Full wrapping support) | | `clear` | left, right, both, none | -| `position` | **relative only** | +| `position` | **Not applied** — `static` flow only (no `relative` offsets, `absolute`, `fixed`) | | Flexbox | Containers and items, incl. wrapping flex on a dedicated `RenderFlexWrap` (v1.9.0). Not applied: `align-content`; `flex-basis` drives wrapping containers only | | CSS Grid | `grid-template-columns/rows` (px, fr, auto, repeat), `grid-column/row` span, gap (v1.2.0). Not applied: `grid-auto-flow`, `align-content` | @@ -162,4 +162,4 @@ or the `fallbackBuilder` parameter to delegate to a WebView or other renderer. --- -*Last updated: April 29, 2026 — HyperRender v1.3.0* +*Last updated: October 10, 2026 — HyperRender v1.13.0* diff --git a/example/lib/formula_demo.dart b/example/lib/formula_demo.dart index a857cae..2e9f753 100644 --- a/example/lib/formula_demo.dart +++ b/example/lib/formula_demo.dart @@ -519,10 +519,9 @@ FormulaWidget( color: DemoColors.warning), _CodeSnippet( code: r'''// Apply flutter_math_fork to ALL formulas in a document -HyperViewer( - html: myDeltaJson, - format: HyperRenderFormat.delta, - widgetBuilder: (context, node) { +HyperViewer.delta( + delta: myDeltaJson, + widgetBuilder: (node) { if (node is AtomicNode && node.tagName == 'formula') { final formula = node.attributes['data'] ?? ''; return Math.tex(formula, diff --git a/pubspec.yaml b/pubspec.yaml index d5cbd56..e7b7e8a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: hyper_render description: "The only Flutter HTML/Markdown renderer with CSS float layout, crash-free text selection at any document size, CJK Ruby typography, and AI/LLM token streaming." -version: 1.13.0 +version: 1.13.1 homepage: https://github.com/brewkits/hyper_render repository: https://github.com/brewkits/hyper_render issue_tracker: https://github.com/brewkits/hyper_render/issues diff --git a/test/docs_matrix_sync_test.dart b/test/docs_matrix_sync_test.dart index 0d2add9..324e2b8 100644 --- a/test/docs_matrix_sync_test.dart +++ b/test/docs_matrix_sync_test.dart @@ -48,6 +48,10 @@ const _executionVerified = [ const _mustNotBeFull = [ 'position: absolute', 'position: fixed', + // Parsed into ComputedStyle and read by nothing in the render path; checked + // by laying out `width:200px;padding:20px` with and without border-box. + 'position: relative', + 'box-sizing', 'z-index', // Parsed into ComputedStyle and read by nothing in the render path — // measured, not assumed, by test/flagship_execution_audit_test.dart.