Releases: brewkits/hyper_render
v1.2.2 — 8 Bug Fixes + Android Build Fix
What's Changed
🐛 Bug Fixes
- Android build failure (
example/android/build.gradle.kts):irondash_engine_context 0.5.5compiled against android-31 conflicts withandroidx.fragment:1.7.1(minCompileSdk=34). Addedsubprojects { compileSdk = 35 }override. Closes #5. - SVG invisible with
sanitize: true(html_sanitizer.dart): Added atomic SVG sanitization path that preserves structure while stripping<script>and dangerous attributes. HyperRenderConfigidentity-compare (hyper_render_config.dart): Addedoperator==/hashCode— prevents unnecessary re-layouts on every frame when_effectiveConfigmerges@keyframesinto a new object.selectabletoggle ignored (hyper_viewer.dart):didUpdateWidgetnow creates/disposesVirtualizedSelectionControllercorrectly whenselectablechanges.- Deep-link taps silently blocked (
hyper_viewer.dart):_safeOnLinkTapnow checks bothallowedCustomSchemesANDrenderConfig.extraLinkSchemes. - CSS change bypassed section cache (
hyper_viewer.dart):_sectionHashesnow reset indidUpdateWidgetwhencustomCsschanges. - Markdown/Delta rendered as single section (
hyper_viewer.dart): Added_splitIntoSections()— large Markdown/Delta docs now chunk correctly in virtualized/paged mode. renderConfigchange partially detected (hyper_viewer.dart):didUpdateWidgetnow uses full value equality instead of only comparingvirtualizationChunkSize.- CSS float class names not detected (
html_adapter.dart):_containsFloatChildnow recognises Bootstrap/Tailwind patterns (float-left,pull-right,alignleft, etc.).
🔧 CI Fixes
benchmark.yml: Fixed JSSyntaxErrorfrom backtick-quoted fixture names inside template literal — useprocess.envinstead of direct interpolation.benchmark.yml+golden.yml: Addedpull-requests: writepermission for comment-posting steps.test.yml: Guard sub-package test steps with[ -d test ]check —hyper_render_markdown,hyper_render_highlight,hyper_render_clipboardhave no test directories.
Full Changelog: https://github.com/brewkits/hyper_render/blob/main/CHANGELOG.md
v1.2.0 — Plugin API, Paged Mode, Incremental Layout
What's new in v1.2.0
✨ New Features
Plugin API — First-class extensibility for custom HTML tags:
final registry = HyperPluginRegistry()
..register(MyChartPlugin())
..register(MyMapPlugin());
HyperViewer(html: content, pluginRegistry: registry)Paged mode — Built-in e-book / reader UI:
final controller = HyperPageController();
HyperViewer(
html: content,
mode: HyperRenderMode.paged,
pageController: controller,
)Incremental layout — Dirty-flag fingerprinting means ~90% fewer rebuilds for live-updating feeds.
CSS @Keyframes — Full animation support with custom keyframe lookup from <style> tags.
♿ Accessibility (WCAG 2.1 AA)
<img alt="…">→ discreteSemanticsNodeat image rect (WCAG 1.1.1)aria-labelon<a>elements honored (WCAG 4.1.2)
🏗️ Refactor
- Removed 31 duplicate files from root
lib/src/— canonical source now inhyper_render_core LazyImageQueuesingleton consolidated (single shared instance)
🐛 Bug Fixes
- XSS:
javascript:URLs blocked in HTML, Markdown, and Delta adapters display:noneelements no longer produce layout fragments- Selection-vs-scroll conflict resolved
- Context menu position clamped to visible bounds
📦 Infra
- All packages:
sdk >=3.5.0,csslib ^1.0.2,flutter_lints ^5.0.0 share_plus ^12.0.0, Android AGP 8.12.1, 16 KB page alignment- 36 new tests for v1.2.0 features
Migration
See MIGRATION_GUIDE for details. The public API is backwards-compatible — upgrading from v1.1.x requires no code changes.
Upgrade
dependencies:
hyper_render: ^1.2.0v1.1.2 — Binary Search Selection · DevTools v1.0.0 · 3-Pipeline CI
What's New
⚡ O(log N) Binary Search Text Selection
Hit-testing now uses _lineStartOffsets[] precomputed at layout time. Selection stays instant even on 1,000-line documents — no more O(N) linear scan per touch event.
🈶 Ruby Clipboard Format
Fully-selected ruby fragments are copied as base(ふりがな) (e.g. 東京(とうきょう)). Partial selections copy base text only, keeping character offsets consistent. 5 ruby selection pipeline bugs fixed that caused offset desynchronisation for all content after a ruby fragment.
🔭 hyper_render_devtools v1.0.0 — First Full Release
- UDT Tree inspector — browse the full document model in Flutter DevTools
- Computed Style panel — see inherited vs. declared values and specificity winners
- Float region visualizer — highlight floated-block boundaries in layout
- Demo mode — explore the inspector without a live app
🔁 3-Pipeline CI Architecture
| Pipeline | Trigger | Purpose |
|---|---|---|
Pre-flight (analyze.yml) |
Every PR/push | dart format + flutter analyze --fatal-infos, skip docs-only |
Core Validation (test.yml) |
PR: selective per-package on ubuntu-22.04 | Fast gate < 5 min |
Core Validation (test.yml) |
Push to main: 3-OS × 2-channel matrix | Full platform coverage |
Visual regression (golden.yml) |
Every PR/push | Pixel-stable, pinned Noto fonts |
Layout regression (benchmark.yml) |
Every PR/push | Hard 16 ms / 60 FPS budget per fixture |
🧪 Golden Tests — Float · RTL · CJK Coverage
9 new pixel-stable test cases:
- Float layout:
float_left,float_right,float_clear - RTL/BiDi:
rtl_arabic,rtl_hebrew,rtl_mixed - CJK + Ruby:
cjk_ruby,cjk_kinsoku,float_cjk
📊 Layout Regression Benchmark
6 HTML fixtures (simple paragraph → 100-paragraph article) with hard millisecond budgets run on every PR. Any fixture exceeding 16 ms (60 FPS) fails the build.
Upgrade
dependencies:
hyper_render: ^1.1.2No breaking changes. All previous HyperViewer APIs remain identical.
Full details in CHANGELOG.md.
v1.1.0
What's new
Rendering
- Premium visual polish: precision borders, skeleton shimmer gradient, adaptive selection colors
- Typography overhaul — font features (ligatures, proportional figures), consistent
TextHeightBehavior, retina-readyFilterQuality.mediumon all images - Anti-aliasing explicitly enabled on all paint operations
Bug fixes
- Copy/paste across block elements (
<li>,<h3>,<p>) now correctly inserts newlines - Fix
_sameLinkContext()guard — incorrect link tap targets when fragments merge across<a>boundaries - Fix float crash on unconstrained parent width
- Fix
TapGestureRecognizerleak when document is replaced - Fix
_fragmentChildMapO(N) scan → O(1) lookup in paint cycle - Fix
_nodeRectCacheO(N²) accessibility rect computation → O(N) - Fix
display:nonenot respected in_tokenizeNodeand_collectAtomicChildren
pub.dev
- All sub-packages bumped to v1.1.0 (html, markdown, highlight, clipboard, devtools)
screenshots:field added with 6 demo GIFs visible in pub.dev galleryvector_mathupdated to^2.2.0- README rewritten with absolute image URLs (GIFs now render correctly on pub.dev)
- Package description optimized for search discoverability
Tests
- 678 tests passing, 0 failures
- Added virtualized mode integration tests
- Added real URL assertions to link tap tests
- Updated golden images to match current rendering output
Demos
- New CJK languages demo
- Why HyperRender showcase with live 16-feature comparison matrix
Install
dependencies:
hyper_render: ^1.1.0Quick start
import 'package:hyper_render/hyper_render.dart';
HyperViewer(
html: articleHtml,
onLinkTap: (url) => launchUrl(Uri.parse(url)),
)HyperRender v1.0.0
HyperRender v1.0.0 — Initial Public Release
A custom RenderObject-based engine that renders HTML, Markdown, and Quill Delta natively on Flutter Canvas — without WebViews, without widget trees.
What's included
- CSS Float layout — text wrapping around floated images, architecturally impossible in widget-tree renderers
- CJK typography — Ruby/Furigana with proper centering, Kinsoku line-breaking across the full line
- Continuous text selection — select across headings, paragraphs, and table cells without widget-boundary breaks
- CSS Variables +
calc()— full custom property cascade - Flexbox and CSS Grid layout
- Smart table layout — two-pass W3C column-width algorithm, colspan/rowspan, three overflow strategies
<details>/<summary>— collapsible sections, no JavaScript required- Multi-format input — HTML, Markdown, Quill Delta
- Built-in XSS sanitization —
javascript:,vbscript:, SVG data URIs,expression()blocked by default - Virtualized rendering —
ListView.buildermode for large documents - Screenshot export —
GlobalKey.toPngBytes() - WebView fallback via
HtmlHeuristics.isComplex()
Packages published
| Package | pub.dev |
|---|---|
hyper_render |
https://pub.dev/packages/hyper_render |
hyper_render_core |
https://pub.dev/packages/hyper_render_core |
hyper_render_html |
https://pub.dev/packages/hyper_render_html |
hyper_render_markdown |
https://pub.dev/packages/hyper_render_markdown |
hyper_render_highlight |
https://pub.dev/packages/hyper_render_highlight |
hyper_render_clipboard |
https://pub.dev/packages/hyper_render_clipboard |
Benchmarks (macOS Desktop, Apple Silicon, Flutter release mode)
| Document | Parse time |
|---|---|
| 1 KB | 27 ms |
| 10 KB | 69 ms |
| 50 KB | 276 ms |
Mobile performance has not been independently verified — run benchmarks on your own hardware.