hyper_render_core 1.3.2
hyper_render_core: ^1.3.2 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.2 - 2026-05-19 #
๐ Security #
UrlSafety.isSafeadded (lib/src/util/url_safety.dart) โ canonical scheme blocklist (javascript:,vbscript:,data:image/svg, non-imagedata:,file:,mhtml:,about:) with control-character smuggling defence. The rootHtmlSanitizer.isSafeUrland the markdown sub-package's URL gate now both delegate here so no scheme can drift between adapters.HyperViewer.markdown(sanitize:true)pre-sanitises markdown content viaHtmlSanitizerso raw<script>/<style>/<iframe>blocks can no longer surviveenableInlineHtml.
๐ Critical Layout Fix #
- Unbounded-width crash eliminated โ
RenderHyperBox.performLayoutand_computeHeightForWidthnow clamp_maxWidthto_kUnboundedWidthFallback = 800.0when constraints aredouble.infinity(Row without Expanded, horizontalSingleChildScrollView, intrinsic queries from unbounded parents). Previously_FlexFragment.layoutpropagated infinity intoBoxConstraints(minWidth: โ)and tripped Flutter'sminWidth < double.infinityassertion.
๐ Selection & Ellipsis #
text-overflow: ellipsisno longer leaks hidden text via copy โFragment.ellipsisVisibleLengthrecords how many leading characters survive each truncation pass;getSelectedTextclamps the visible range against it and skips fully-suppressed fragments. State is reset at the top of every_performLineLayoutso a wider re-layout un-hides text that was previously truncated.- Selection drag is now lenient on edge overshoot โ
_lineIndexAt(dy, clampOutOfBounds: true)is used during handle drag, so a finger that drifts past the first/last line by a pixel snaps to the nearest line instead of freezing. Tap hit-testing (_findFragmentAtPosition) keeps the strict semantics. - Dead
_characterToFragment/_fragmentRangesfields removed โ they were populated in_buildCharacterMappingeach layout but never read. Layout micro-saving and one less GC pressure point.
๐ Table #
- Cell BlockNode content no longer disappears โ when
cellContentBuilderisnulland a cell contains<div>/<p>children,_buildCellContentnow renders the inline run plus each block child via a defaultColumn/Textfallback. Previously only callers that went throughHyperRenderWidget(which auto-supplies a builder) were safe. - Total-cell cap
_kMaxTotalCells = 100 000โ a pathological<table>whoserowCount ร columnCountexceeds the cap now renders a visible "Table too large to render" placeholder instead of allocating an 8 MBnullgrid on the UI thread.
๐ Animations #
HyperAnimatedWidgetcontroller lifecycle hardened โ switched fromSingleTickerProviderStateMixintoTickerProviderStateMixin; the previous mixin asserted on the secondcreateTicker()whendidUpdateWidgetrecreated the controller. The start delay now uses a retainedTimerthat is cancelled ondidUpdateWidget/dispose, eliminating duplicateforward()calls in fast-rebuild scenarios.
๐งช Tests #
- +27 tests added across
url_safety_test,animation_controller_race_test,table_review_fixes_test. Full sub-package suite green.
1.3.1 - 2026-05-14 #
โจ New CSS Properties #
list-style-type: All 11 values โdisc,circle,square,decimal,decimal-leading-zero,lower-alpha,upper-alpha,lower-latin,upper-latin,lower-roman,upper-roman,nonelist-style-position:inside/outside(default)list-styleshorthand: parses<type> <position>in any orderbackground-repeat:repeat,repeat-x,repeat-y,no-repeat,space,roundbackground-position: keyword (center,top left, etc.) and percentage values
๐ Performance #
- Selection rects cached:
getSelectionRects()called once per drag event (was 3ร); stored in_selectionRectsfield โ eliminates redundant layout walks during selection drag - Auto-scroll proportional speed:
_autoScrollIfNearEdgenow scales 0โ20 px/frame based on finger distance from edge (was fixed 15 px/frame) HyperTeardropHandlePainterdeduplicated: renamed toHyperTeardropHandlePainter, made public, and exported from core; duplicate in the virtualized overlay deleted
๐ Bug Fixes #
- Edge-to-edge images:
_kImageMarginset to0.0โwidth: 100%images now truly fill their container with no internal margin offset
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.