Repository navigation
release: 1.11.0 — dark mode text color, body/html color, :root fix (#20), block plugins on custom tags (#22), docs fixes - #21
Conversation
…oot only (#20) HyperViewer's unstyled text was always the fixed dark gray #1F2937 with no way to change it, so it was unreadable on dark surfaces. - Dark Theme: default text color is colorScheme.onSurface. Light theme output is unchanged. A theme toggle re-resolves in place (no loading state, scroll position kept). - New HyperViewer(textColor:), a host override that wins over the content's html/:root/body color but not over an element's own color. - body { color } and html { color } now apply (no UDT node is tagged body or html, so they never matched). Layered html < :root < body. - :root matched every top-level block because it tested parent == null, which top-level blocks also satisfy; it now tests node is DocumentNode. - StyleResolver.ensureReadableOnOwnBackground: an element with its own opaque background and no color of its own no longer inherits text under 3:1 contrast (blockquote, kbd, th, author backgrounds). Enabled only when the host supplies a default color. - customCss doc example used body { font-size }, which is still ignored.
|
| Fixture | Budget (ms) | Median (ms) | P95 (ms) | |
|---|---|---|---|---|
| ❌ | simple_paragraph |
8 | 12 | 20 |
| ✅ | mixed_inline |
10 | 10 | 11 |
| ✅ | float_layout |
12 | 11 | 18 |
| ❌ | table_20_rows |
14 | 30 | 39 |
| ✅ | cjk_ruby |
14 | 7 | 8 |
| ❌ | large_article |
16 | 27 | 50 |
One or more fixtures exceeded the 16 ms budget.
Flutter
3.41.5· ubuntu-22.04
Informational, does not block merge: CI runners use software
rendering and are 2-3x slower than the devices the budgets are
calibrated for. Compare against the base branch; if a fixture
regressed relative to it, profile with:
flutter test benchmark/layout_regression.dart --reporter expandedand check _performLineLayout / _buildCharacterMapping for
any new O(N²) or O(N log N) paths introduced in this PR.
…r painted
A custom tag (<info-box>, <x-badge>) has no UA display style, so the HTML
adapters build it as an InlineNode. _handleInlineNode only consulted the
inline plugin tags, so a registered BLOCK plugin on such a tag never reached
_tokenizeBlockPlugin: its widget was built, linked to no fragment, sized 0x0
and not painted ('More child widgets than fragments' in debug).
A registered block tag is now handled as a block whatever its node type.
The existing plugin tests hand-built BlockNodes or asserted findsOneWidget,
which a 0x0 widget satisfies. The new tests assert size, position between the
neighbouring paragraphs, painted pixels, stacking, virtualized mode, that the
plugin owns its children, and that unregistered and inline plugins are
unaffected.
…emo fixes - hyper_render_epub 0.1.3: EpubReader(textColor:) forwarded to HyperViewer; requires hyper_render/core ^1.11.0. - Versions: hyper_render 1.11.0, hyper_render_core 1.11.0. CHANGELOGs, README (Dark Mode section, API table), MIGRATION_GUIDE, CSS matrix, ROADMAP. - test/integration/dark_mode_hardening_test.dart: security (hostile body colors, var() bomb, 5000-rule sheet), stress (40 theme toggles in sync / virtualized / paged, in-flight parse, streaming) and performance. - example: DEMO_THEME=dark|light define for the all-demos drive; fix a RenderFlex overflow in the accessibility demo (controls now scroll and are capped) and ListTile-inside-ColoredBox assertions in the security and accessibility demos (Material instead of Container(color:)). - customCss dartdoc now says the document's own <style> wins at equal specificity.
…tyle # Conflicts: # packages/hyper_render_core/CHANGELOG.md
… fixes, body/html !important layering Docs (each was checked against the code): - hyper_render_clipboard README, usage guide, example and dartdoc, and the root README, showed HyperViewer(imageClipboardHandler:) and onImageLongPress, which do not exist, so the documented setup did not compile. Rewritten to the real route (HyperImage via widgetBuilder); documented_usage_test.dart now compiles and runs that snippet. - example/MULTIMEDIA_EXAMPLES.md used HyperViewer(mediaBuilder:) (a parameter of HtmlToSpanConverter only), a nonexistent HyperMediaBuilder, a missing example file and a stale issue URL. Rewritten to widgetBuilder; the unreleased hyper_render_media is labelled planned. - Root README epub snippet used EpubBook.openBytes and EpubReader(book:, onChapterChanged:), neither of which exist. Engine: a body color now sits above html / :root including their !important forms (an element's own declaration beats what it inherits), as in a browser. Tests cover html-important alone, html-important vs body, :root-important vs body, and markdown in virtualized mode (the sync-fallback parse path). Example app: - ai_streaming_demo: the three stream buttons overflowed a 390pt phone by 21px (Row -> Wrap). Found by driving all 27 demos on the iOS simulator. - example/ios: raise the deployment target 13 -> 15 (Xcode 26 rejects < 15), as macOS was raised to 12 in 1.10.0. Verified: all 27 demos open with 0 FlutterErrors on iOS (dark theme); 100% of the lines added in hyper_viewer.dart / resolver.dart are exercised by tests.
|
| Fixture | Budget (ms) | Median (ms) | P95 (ms) | |
|---|---|---|---|---|
| ❌ | simple_paragraph |
8 | 17 | 26 |
| ❌ | mixed_inline |
10 | 14 | 15 |
| ❌ | float_layout |
12 | 14 | 19 |
| ❌ | table_20_rows |
14 | 43 | 65 |
| ✅ | cjk_ruby |
14 | 9 | 11 |
| ❌ | large_article |
16 | 37 | 65 |
One or more fixtures exceeded the 16 ms budget.
Flutter
3.41.5· ubuntu-22.04
Informational, does not block merge: CI runners use software
rendering and are 2-3x slower than the devices the budgets are
calibrated for. Compare against the base branch; if a fixture
regressed relative to it, profile with:
flutter test benchmark/layout_regression.dart --reporter expandedand check _performLineLayout / _buildCharacterMapping for
any new O(N²) or O(N log N) paths introduced in this PR.
…e API, keep logs out of the archive - hyper_render_clipboard 1.7.3: docs-only release so pub.dev stops showing the HyperViewer(imageClipboardHandler:) snippet that never compiled. - Deprecate HyperRenderTheme / HyperRenderThemeData: nothing reads them, so setting them never had any effect. - .pubignore: *.log and .DS_Store. .pubignore replaces .gitignore for pub, so the untracked flutter_0N.log crash reports (local paths, commands) were being packed into the 32 MB root archive. - CHANGELOG: fix a bullet that contradicted itself about EpubReader.textColor and wrongly said EpubReader needs !important. HyperViewer.customCss precedes the document <style> (!important needed); EpubReader appends the reader's CSS after the chapter's (plain wins). Both directions now have a test. - Known limitation noted: link / inline code / <mark> colors are still tuned for light surfaces. - Rename a hardening test to say what it asserts.
|
| Fixture | Budget (ms) | Median (ms) | P95 (ms) | |
|---|---|---|---|---|
| ❌ | simple_paragraph |
8 | 15 | 23 |
| ❌ | mixed_inline |
10 | 13 | 13 |
| ✅ | float_layout |
12 | 12 | 21 |
| ❌ | table_20_rows |
14 | 32 | 53 |
| ✅ | cjk_ruby |
14 | 8 | 10 |
| ❌ | large_article |
16 | 26 | 47 |
One or more fixtures exceeded the 16 ms budget.
Flutter
3.41.5· ubuntu-22.04
Informational, does not block merge: CI runners use software
rendering and are 2-3x slower than the devices the budgets are
calibrated for. Compare against the base branch; if a fixture
regressed relative to it, profile with:
flutter test benchmark/layout_regression.dart --reporter expandedand check _performLineLayout / _buildCharacterMapping for
any new O(N²) or O(N log N) paths introduced in this PR.
…ce per round) The 3x bound was measured at ~1.1x in isolation (body/html rules 1.02x, override 1.09x, guard 1.12x) but read 2.07x once under build load with only 5 samples taken by an awkward double call. Take the minimum of 9 single runs per variant so a busy runner does not flake it.
|
| Fixture | Budget (ms) | Median (ms) | P95 (ms) | |
|---|---|---|---|---|
| ❌ | simple_paragraph |
8 | 17 | 25 |
| ❌ | mixed_inline |
10 | 14 | 15 |
| ❌ | float_layout |
12 | 14 | 29 |
| ❌ | table_20_rows |
14 | 50 | 77 |
| ✅ | cjk_ruby |
14 | 11 | 13 |
| ❌ | large_article |
16 | 40 | 82 |
One or more fixtures exceeded the 16 ms budget.
Flutter
3.41.5· ubuntu-22.04
Informational, does not block merge: CI runners use software
rendering and are 2-3x slower than the devices the budgets are
calibrated for. Compare against the base branch; if a fixture
regressed relative to it, profile with:
flutter test benchmark/layout_regression.dart --reporter expandedand check _performLineLayout / _buildCharacterMapping for
any new O(N²) or O(N log N) paths introduced in this PR.
Release candidate for 1.11.0. Fixes #20 and includes #22 (merge this one; GitHub will mark #22 as merged).
What ships
hyper_render_corebody/htmlcolor,:rootfix, contrast guard, block plugins on custom tags (#22), deprecates deadHyperRenderThemehyper_renderHyperViewer(textColor:), theme-aware default; requires core^1.11.0hyper_render_epubEpubReader(textColor:); requires root/core^1.11.0hyper_render_clipboardHyperViewer(imageClipboardHandler:), which never existed)lib/identical to the published versions; theircore ^1.xconstraints still resolveEngine / API
Theme(colorScheme.onSurface); light themes unchanged.HyperViewer(textColor:)overrides it.body { color }/html { color }now apply (they never matched);:rootmatches only the document root (1.10.0'sparent == nullcheck also matched top-level blocks). Elements with their own light background keep readable text (3:1 guard, only active when a theme/textColorsupplies a default).<info-box>) were laid out at 0×0 and never painted.HyperRenderTheme/HyperRenderThemeDatadeprecated (nothing read them).Behavior changes (also in CHANGELOG + MIGRATION_GUIDE)
Theme(white email pane) now gets light text — passtextColor:.body { color }now renders in it.:root { … }no longer styles every top-level block.Docs corrected (each checked against the code)
Clipboard README/guide/example/dartdoc, root README (clipboard + epub snippets used APIs that don't exist),
example/MULTIMEDIA_EXAMPLES.md(HyperViewer(mediaBuilder:), a nonexistentHyperMediaBuilder),customCsspriority wording..pubignorenow excludes*.log/.DS_Store(the 32 MB root archive was packing localflutter_0N.logcrash reports).Verification
dark_mode_text_color_test(39, pixel-based),dark_mode_hardening_test(12: security / stress / performance),block_plugin_custom_tag_test(7), epub +5, clipboarddocumented_usage_test(+2). Mutation-checked: reverting:root, the host override, html/body ordering, the guard, or the plugin fix each fails tests. 100% of the lines added inhyper_viewer.dart,resolver.dartand the layout fix are exercised.flutter analyze+dart formatclean everywhere.FlutterError, logs free of Layout Warning / overflow: macOS light, macOS dark, iOS simulator light (after the fixes), iOS dark. Found and fixed by this: AI streaming demo 21px overflow, ListTile-inside-ColoredBox assertions and an overflow in the security/accessibility demos, iOS deployment target 13 → 15 (Xcode 26).lib/.Not verified
main; there is noworkflow_dispatchontest.yml, so it cannot be run before merging.performance_monitor_test.dart(Duration > 0assertions with the coarse web timer). They fail identically onv1.10.0, are unrelated to this PR, and CI does not run core on Chrome.Known limitation
Link blue, inline
<code>/<pre>and<mark>colors are still tuned for light surfaces.