hyper_render_core 1.3.0
hyper_render_core: ^1.3.0 copied to clipboard
Core engine for HyperRender. Universal Document Tree, single-RenderObject layout with CSS float, Flexbox, Grid, CJK typography, and crash-free text selection.
Changelog — hyper_render_core #
1.3.0 - 2026-05-03 #
✨ New Features #
HyperNodePlugin/HyperPluginRegistry(src/interfaces/node_plugin.dart): Plugin API for custom widget rendering of arbitrary HTML tag names. Block tier (full-width, CSS margins) and inline tier (flows with text, intrinsic-measured) supported.- Plugin layout wiring (
render_hyper_box.dart,render_hyper_box_layout.dart):blockPluginTags/inlinePluginTagssets added toRenderHyperBoxwith layout-invalidating setters._tokenizeNodeintercepts plugin tags; Step 1.7_measureInlinePluginFragments()queries child intrinsic dimensions before line layout runs. - Plugin widget wiring (
hyper_render_widget.dart):pluginRegistryfield added;_collectAtomicChildrenchecks plugin registry first;createRenderObject/updateRenderObjectsync tag sets to the render object. - CSS: Box shadow, linear-gradient, advanced border styles (dashed/dotted)
- CSS: Full Flexbox support (direction, wrap, gap, align-self, grow/shrink/basis)
- CSS: CSS Variables
var(),transition,animation-*parsing - CSS:
computed_styleexpanded with 120+ additional properties - CSS Grid:
display: gridwithgrid-template-columns,span,gap - Style:
resolver.dartexpanded — specificity engine, cascade improvements - Widgets:
HyperRenderWidget— adaptive selection colors, theme-aware; newenableComplexFiltersflag to gatesaveLayercalls for backdrop-filter/filter effects - Widgets:
HyperSelectionOverlay— improved handle rendering with tight bounding boxes - Rendering:
render_hyper_box_layout.dart— float algorithm improvements; O(1)_fragmentChildMapchild lookup; O(1)_nodeRectCacheaccessibility rect lookup - Rendering:
render_hyper_box_paint.dart— retina-ready images, anti-aliasing - Performance:
_buildNodeRectCache()builds O(1) accessibility rects during layout (Step 8), depth-capped at 32 levels
♿ Accessibility (WCAG 2.1 AA) #
<img alt>→ discreteSemanticsNode: Images with non-emptyalttext now generate an individualSemanticsNodeat the image's layout rect — VoiceOver/TalkBack users can navigate to images element-by-element (WCAG 1.1.1)aria-labelhonored on<a>elements: Anchor elements witharia-labelnow use that attribute as the link's accessible label instead of accumulated text content (WCAG 4.1.2)
🐛 Bug Fixes #
HyperRenderWidgetcompilation error: Resolved a signature mismatch in recursive widget construction wherecodeHighlighterwas passed outside ofconfigandpluginRegistrywas missing- Float layout: Explicit CSS
widthandheightproperties are now correctly respected for non-image float elements - Plugin propagation:
pluginRegistryis correctly passed to nested renderers, allowing custom tags to work inside floated containers - Scroll vs. text-selection conflict: Removed
PointerMoveEventselection tracking fromhandleEvent— selection now initiated viaLongPressGestureRecognizerat the widget layer - Context menu outside hit-testable bounds:
Positioned(top: menuY - 56)clamped to0.0— Copy button is always reachable near the top of the widget display:nonenot respected: Guard in_tokenizeNode— elements withdisplay:noneproduce no layout fragments_TextPainterKeyhash collision: ReplacedObject.hash()int key with full value-equality struct — eliminates subtle layout glitches on large documents- Inline images not loaded after async parse:
documentsetter now calls_loadImages()when the render box is attached - Image loading spinner invisible:
frameBuilderno longer wraps theloadingBuilderplaceholder inAnimatedOpacity(opacity:0)—TweenAnimationBuilderfade-in applied on first decoded frame instead - Ruby selection — 5 bugs fixed:
FragmentType.rubywas silently skipped in every selection pipeline step, causing character offset desynchronisation for all content after a ruby fragment LineInfo.characterCount: now counts ruby base-text characters (was 0 for ruby fragments)details_widget.dart: Fixed undefinedDetailsNodeclass — field type changed toUDTNodewithattributes.containsKey('open')for HTML-spec-compliant initial state- Selection:
getSelectedText()now inserts\nat block element boundaries so copied text respects paragraph/list structure - Layout Bug 1:
characterOffsetno longer addstrimmedLeadingto second fragment — selection mapping was off by the number of trimmed leading spaces - Layout Bug 2:
_sameLinkContext()guard prevents merging text nodes from different<a>ancestors — fixes incorrect link tap targets - Layout Bug 3:
_layoutFloat()early-returns when_maxWidth.isInfinite— prevents crash in unconstrained layouts; usesgetMaxIntrinsicWidth/Heightinstead ofchild.layout()to eliminate double-layout - Layout Bug 4: Null/empty guard in
_measureFragmentsforfragment.text— no longer crashes on atomic/ruby fragments - Memory:
_disposeLinkRecognizers()called indocumentsetter — fixes recognizer leak when document is replaced - Nested decorations:
nodeToDecoratedchanged fromMap<UDTNode, UDTNode>toMap<UDTNode, List<UDTNode>>— inner spans no longer overwrite outer spans prefer_const_constructors:HyperPluginBuildContextconstruction changed toconst
🔬 Tests #
- +17 tests —
ruby_layout_test.dart:LineInfo.characterCountwith ruby, selection offset accumulation - +27 tests —
ruby_layout_test.dart: RubyNode model, Fragment.ruby lifecycle, document tree traversal - +30 tests —
float_layout_test.dart: HyperFloat/HyperClear enums, node construction, LineInfo insets - +44 tests —
text_breaking_test.dart: canBreak, isWhitespace, ComputedStyle overflow, CJK/Kinsoku - +52 tests —
layout_algorithm_test.dart: characterOffset regression, rect computation, link context - +32 tests —
details_element_test.dart:<details>/<summary>model and widget open/close behavior - +53 tests —
rtl_bidi_test.dart: HyperTextDirection, hyperDirection inheritance, Arabic/Hebrew text, RTL widget integration dart fixapplied to test files: 73prefer_constissues resolved — 0 analyzer issues
1.2.0 - 2026-03-30 #
- First stable release. Core UDT model, RenderObject engine, plugin interfaces.