Skip to content

Commit ecafa19

Browse files
Merge pull request #18: DevTools v2 + stylesheet var()/url()/calc() fixes (1.10.0)
DevTools v2: timeline, selection, live CSS variables, snapshot export + stylesheet var() fixes
2 parents 13d929f + fa96c33 commit ecafa19

77 files changed

Lines changed: 72721 additions & 51477 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/analyze.yml‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,25 @@ jobs:
131131
132132
exit $EXIT
133133
134+
# Sub-packages the root excludes: each one only resolves against its
135+
# own pubspec, so analyze it in place after its own pub get.
136+
- name: flutter analyze sub-packages
137+
if: steps.filter.outputs.any_dart == 'true'
138+
run: |
139+
FAILED=""
140+
for pkg in hyper_render_html hyper_render_markdown hyper_render_highlight \
141+
hyper_render_math hyper_render_clipboard hyper_render_devtools \
142+
hyper_render_epub; do
143+
echo "::group::$pkg"
144+
(cd "packages/$pkg" && flutter pub get >/dev/null && \
145+
flutter analyze --no-pub --fatal-warnings --fatal-infos) || FAILED="$FAILED $pkg"
146+
echo "::endgroup::"
147+
done
148+
if [ -n "$FAILED" ]; then
149+
echo "::error::analyze failed in:$FAILED"
150+
exit 1
151+
fi
152+
134153
- name: Upload analyze report
135154
if: always() && steps.filter.outputs.any_dart == 'true'
136155
uses: actions/upload-artifact@v4

‎.github/workflows/deploy_web_demo.yml‎

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,19 @@ on:
55
branches: [main]
66
workflow_dispatch:
77

8+
# Pages is served from the gh-pages branch ("Deploy from a branch"), so the
9+
# build is pushed there. The previous actions/deploy-pages flow needed the
10+
# github-pages environment to allow `main`, which it doesn't — every run
11+
# failed and the live demo stayed on v1.7.1.
812
permissions:
9-
contents: read
10-
pages: write
11-
id-token: write
13+
contents: write
1214

1315
concurrency:
1416
group: 'pages'
1517
cancel-in-progress: true
1618

1719
jobs:
1820
deploy:
19-
environment:
20-
name: github-pages
21-
url: ${{ steps.deployment.outputs.page_url }}
2221
runs-on: ubuntu-latest
2322
steps:
2423
- name: Checkout repository
@@ -40,11 +39,11 @@ jobs:
4039
cd example
4140
flutter build web --release --base-href "/hyper_render/"
4241
43-
- name: Upload artifact
44-
uses: actions/upload-pages-artifact@v3
42+
- name: Publish to gh-pages
43+
uses: peaceiris/actions-gh-pages@v4
4544
with:
46-
path: example/build/web
47-
48-
- name: Deploy to GitHub Pages
49-
id: deployment
50-
uses: actions/deploy-pages@v4
45+
github_token: ${{ secrets.GITHUB_TOKEN }}
46+
publish_dir: example/build/web
47+
publish_branch: gh-pages
48+
force_orphan: true # keep gh-pages to a single commit, no history bloat
49+
commit_message: "deploy: live web demo"

‎.github/workflows/test.yml‎

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ jobs:
4040
changed_highlight: ${{ steps.filter.outputs.highlight }}
4141
changed_clipboard: ${{ steps.filter.outputs.clipboard }}
4242
changed_devtools: ${{ steps.filter.outputs.devtools }}
43+
changed_math: ${{ steps.filter.outputs.math }}
44+
changed_epub: ${{ steps.filter.outputs.epub }}
4345
changed_root: ${{ steps.filter.outputs.root }}
4446
changed_any_dart: ${{ steps.filter.outputs.any_dart }}
4547
steps:
@@ -60,6 +62,10 @@ jobs:
6062
- 'packages/hyper_render_clipboard/**'
6163
devtools:
6264
- 'packages/hyper_render_devtools/**'
65+
math:
66+
- 'packages/hyper_render_math/**'
67+
epub:
68+
- 'packages/hyper_render_epub/**'
6369
root:
6470
- 'lib/**'
6571
- 'test/**'
@@ -99,45 +105,12 @@ jobs:
99105
working-directory: example/android
100106
run: ./gradlew assembleDebug
101107

102-
emulator-tests:
103-
name: Integration Tests (Emulator)
104-
runs-on: macos-latest
105-
needs: path-filter
106-
if: >-
107-
github.event_name == 'pull_request' &&
108-
needs.path-filter.outputs.changed_any_dart == 'true'
109-
strategy:
110-
fail-fast: false
111-
matrix:
112-
platform: [android, ios]
113-
steps:
114-
- uses: actions/checkout@v4
115-
- name: Setup Java
116-
if: matrix.platform == 'android'
117-
uses: actions/setup-java@v3
118-
with:
119-
distribution: 'zulu'
120-
java-version: '17'
121-
- name: Setup Flutter
122-
uses: subosito/flutter-action@v2
123-
with:
124-
flutter-version: ${{ env.FLUTTER_VERSION }}
125-
channel: stable
126-
cache: true
127-
- name: flutter pub get
128-
run: flutter pub get
129-
- name: Run Android Emulator Tests
130-
if: matrix.platform == 'android'
131-
uses: reactivecircus/android-emulator-runner@v2
132-
with:
133-
api-level: 29
134-
arch: arm64-v8a
135-
script: flutter test test/integration/
136-
- name: Run iOS Simulator Tests
137-
if: matrix.platform == 'ios'
138-
run: |
139-
xcrun simctl list devicetypes
140-
flutter test test/integration/ -d "iPhone 15" || flutter test test/integration/
108+
# NOTE: the former "Integration Tests (Emulator)" job was removed. It ran
109+
# `flutter test test/integration/` with no device target, i.e. on the host VM
110+
# — the same tests test-pr runs below — but on macOS runners (10x the
111+
# per-minute price), and its Android leg could not boot an x86 emulator on
112+
# Apple Silicon (HVF_UNSUPPORTED). Real on-device coverage lives in
113+
# example/integration_test/all_demos_test.dart (run locally with -d macos).
141114

142115
test-pr:
143116
name: Tests (PR · ubuntu-22.04 · stable)
@@ -190,31 +163,60 @@ jobs:
190163
needs.path-filter.outputs.changed_html == 'true' ||
191164
needs.path-filter.outputs.changed_core == 'true'
192165
working-directory: packages/hyper_render_html
193-
run: flutter test --no-pub
166+
run: flutter pub get && flutter test --no-pub
194167

195168
- name: Test hyper_render_markdown
196169
if: >-
197170
needs.path-filter.outputs.changed_markdown == 'true' ||
198171
needs.path-filter.outputs.changed_core == 'true'
199172
working-directory: packages/hyper_render_markdown
200173
run: |
201-
if [ -d test ]; then flutter test --no-pub; else echo "No tests in this package — skipping."; fi
174+
if [ -d test ]; then flutter pub get && flutter test --no-pub; else echo "No tests in this package — skipping."; fi
202175
203176
- name: Test hyper_render_highlight
204177
if: >-
205178
needs.path-filter.outputs.changed_highlight == 'true' ||
206179
needs.path-filter.outputs.changed_core == 'true'
207180
working-directory: packages/hyper_render_highlight
208181
run: |
209-
if [ -d test ]; then flutter test --no-pub; else echo "No tests in this package — skipping."; fi
182+
if [ -d test ]; then flutter pub get && flutter test --no-pub; else echo "No tests in this package — skipping."; fi
210183
211184
- name: Test hyper_render_clipboard
212185
if: >-
213186
needs.path-filter.outputs.changed_clipboard == 'true' ||
214187
needs.path-filter.outputs.changed_core == 'true'
215188
working-directory: packages/hyper_render_clipboard
216189
run: |
217-
if [ -d test ]; then flutter test --no-pub; else echo "No tests in this package — skipping."; fi
190+
if [ -d test ]; then flutter pub get && flutter test --no-pub; else echo "No tests in this package — skipping."; fi
191+
192+
- name: Test hyper_render_math
193+
if: >-
194+
needs.path-filter.outputs.changed_math == 'true' ||
195+
needs.path-filter.outputs.changed_core == 'true'
196+
working-directory: packages/hyper_render_math
197+
run: flutter pub get && flutter test --no-pub
198+
199+
- name: Test hyper_render_epub
200+
if: >-
201+
needs.path-filter.outputs.changed_epub == 'true' ||
202+
needs.path-filter.outputs.changed_root == 'true' ||
203+
needs.path-filter.outputs.changed_core == 'true'
204+
working-directory: packages/hyper_render_epub
205+
run: flutter pub get && flutter test --no-pub
206+
207+
- name: Test hyper_render_devtools
208+
if: >-
209+
needs.path-filter.outputs.changed_devtools == 'true' ||
210+
needs.path-filter.outputs.changed_core == 'true'
211+
working-directory: packages/hyper_render_devtools
212+
run: flutter pub get && flutter test --no-pub
213+
214+
# The panel imports dart:js_interop: its widget test only compiles for
215+
# the web (@TestOn('browser')). ubuntu runners ship Chrome.
216+
- name: Test hyper_render_devtools panel (Chrome)
217+
if: needs.path-filter.outputs.changed_devtools == 'true'
218+
working-directory: packages/hyper_render_devtools/devtools_ui
219+
run: flutter pub get && flutter test --no-pub --platform chrome
218220

219221
- name: Upload test results
220222
if: failure()

‎CHANGELOG.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 1.10.0
4+
5+
- **`var()` in `<style>` / `customCss` now resolves** (fix in `hyper_render_core`). It previously produced nothing; only inline `style=""` worked. Pages that used it will now render with those values.
6+
- **Requires `hyper_render_core` `^1.10.0`.** `HyperViewer` uses the new `StyleResolver.customPropertyOverrides` and `HyperRenderDebugHooks.cssVariableOverrides`.
7+
- **DevTools live CSS-variable editing** — in debug builds `HyperViewer` listens to `HyperRenderDebugHooks.cssVariableOverrides` and re-parses when `hyper_render_devtools` overrides a `--var`. This is a no-op in release builds.
8+
39
## 1.9.1
410

511
- **`FlexWrapParentData` was missing from the root barrel's `show` list.** `FlexWrapItem`, `FlexWrapLayout` and `RenderFlexWrap` shipped in 1.9.0, but the parent-data type — part of their public signatures — did not, so it was unreachable via `package:hyper_render/hyper_render.dart`. Found by compile-checking the published 1.9.0 artifacts from a throwaway consumer project. Workaround on 1.9.0: import it from `package:hyper_render_core/hyper_render_core.dart`, which does export it.

‎README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Already using `flutter_html`? You don't need to rewrite your widget tree or lear
3434
```dart
3535
// 1. In your pubspec.yaml:
3636
// dependencies:
37-
// hyper_render: ^1.9.0
37+
// hyper_render: ^1.10.0
3838
3939
// 2. In your Dart file — replace this single line:
4040
// ❌ import 'package:flutter_html/flutter_html.dart';
@@ -68,7 +68,7 @@ Html(
6868

6969
```yaml
7070
dependencies:
71-
hyper_render: ^1.9.0
71+
hyper_render: ^1.10.0
7272
```
7373
7474
```dart
@@ -477,7 +477,7 @@ HTML / Markdown / Quill Delta
477477
| [`hyper_render_html`](https://pub.dev/packages/hyper_render_html) | [![pub](https://img.shields.io/pub/v/hyper_render_html.svg)](https://pub.dev/packages/hyper_render_html) | HTML + CSS parser |
478478
| [`hyper_render_markdown`](https://pub.dev/packages/hyper_render_markdown) | [![pub](https://img.shields.io/pub/v/hyper_render_markdown.svg)](https://pub.dev/packages/hyper_render_markdown) | Markdown adapter (GFM) |
479479
| [`hyper_render_highlight`](https://pub.dev/packages/hyper_render_highlight) | [![pub](https://img.shields.io/pub/v/hyper_render_highlight.svg)](https://pub.dev/packages/hyper_render_highlight) | Syntax highlighting for `<code>` / `<pre>` blocks |
480-
| [`hyper_render_devtools`](https://pub.dev/packages/hyper_render_devtools) | [![pub](https://img.shields.io/pub/v/hyper_render_devtools.svg)](https://pub.dev/packages/hyper_render_devtools) | Flutter DevTools extension — UDT inspector, computed styles, float visualizer |
480+
| [`hyper_render_devtools`](https://pub.dev/packages/hyper_render_devtools) | [![pub](https://img.shields.io/pub/v/hyper_render_devtools.svg)](https://pub.dev/packages/hyper_render_devtools) | Flutter DevTools extension — UDT inspector, computed styles, layout fragments |
481481

482482
### Optional add-ons
483483

‎ROADMAP.md‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ This document outlines the architectural roadmap for **HyperRender** to become t
88

99
| Version | Target Date | Strategic Focus | Key Differentiators |
1010
| :--- | :--- | :--- | :--- |
11-
| **v1.7.0** | Current | **Production Hardening & Drop-in Migration** | Single RenderObject, 100% WASM support, 160/160 pub score, 30s `flutter_html` drop-in layer. |
12-
| **v1.8.0** | Q3 2026 | **AI & LLM Token-Streaming Engine** | Frame-throttled token updates with adaptive backoff, transient syntax auto-repair, auto-scroll locking. Tail-only layout invalidation remains a separate, unscheduled epic — see below. |
13-
| **v1.9.0** | Q4 2026 | **Native Vector Diagramming & Headless Export** | Pure Canvas/Vector Mermaid.js & GraphViz (Zero-WebView), Headless Image & PDF byte stream generator. |
11+
| **v1.7.0** | Shipped | **Production Hardening & Drop-in Migration** | Single RenderObject, 100% WASM support, 160/160 pub score, 30s `flutter_html` drop-in layer. |
12+
| **v1.8.0** | Shipped | **AI & LLM Token-Streaming Engine** | Frame-throttled token updates with adaptive backoff, transient syntax auto-repair, auto-scroll locking. Tail-only layout invalidation remains a separate, unscheduled epic — see below. |
13+
| **v1.9.0** | Shipped | **Wrapping Flexbox** | `flex-wrap: wrap` on a dedicated `RenderFlexWrap` (#15). |
14+
| **v1.10.0** | Current | **DevTools v2 & Stylesheet CSS Correctness** | Timeline / Selection / live CSS-variable / snapshot DevTools tabs; stylesheet `var()`, `url()`, `calc()` and `:root` fixed. |
15+
| **Next** | Unscheduled | **Native Vector Diagramming & Headless Export** | Pure Canvas/Vector Mermaid.js & GraphViz (Zero-WebView), Headless Image & PDF byte stream generator. |
1416
| **v2.0.0** | Q1 2027 | **Interactive Editorial & Magazine Typography** | Medium-style Text Annotation/Highlighting layer, Multi-column layout (`column-count`), Z-Index Stacking Context, Vertical Text (`writing-mode: vertical-rl`). |
1517

1618
---
@@ -32,7 +34,7 @@ This document outlines the architectural roadmap for **HyperRender** to become t
3234

3335
---
3436

35-
## 📊 v1.9.0: Native Vector Diagramming & Headless Export (WebView Replacement)
37+
## 📊 Next (unscheduled): Native Vector Diagramming & Headless Export (WebView Replacement)
3638

3739
### 1. Native Mermaid.js & GraphViz Vector Engine (Zero-WebView)
3840
- **Problem**: Technical docs, GitHub clients, and EdTech apps embed WebViews solely for Mermaid diagrams, adding 50MB+ RAM overhead per instance with poor gesture response.

‎analysis_options.yaml‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,15 @@ analyzer:
1212
# Sub-packages have their own pubspec.yaml and analysis_options.yaml.
1313
# Excluding them prevents "uri_does_not_exist" errors for deps that are
1414
# only declared in those packages (super_clipboard, devtools_extensions…).
15+
# Only hyper_render_core resolves from the root package config; every
16+
# other sub-package is analyzed in its own directory (see analyze.yml).
1517
- packages/hyper_render_clipboard/**
1618
- packages/hyper_render_devtools/**
19+
- packages/hyper_render_epub/**
20+
- packages/hyper_render_highlight/**
21+
- packages/hyper_render_html/**
22+
- packages/hyper_render_markdown/**
23+
- packages/hyper_render_math/**
1724
errors:
1825
# Monorepo: sub-packages use path: deps for local development.
1926
# The publish workflow swaps to version: deps before pub publish.

‎doc/CSS_PROPERTIES_MATRIX.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# CSS Properties Support Matrix
22

3-
Last Updated: September 6, 2026
4-
Version: 1.9.1
3+
Last Updated: October 2, 2026
4+
Version: 1.10.0
55

66
This document lists CSS property support in HyperRender.
77

@@ -199,9 +199,9 @@ This document lists CSS property support in HyperRender.
199199
| Feature | Status | Supported Values | Notes |
200200
|---------|--------|------------------|-------|
201201
| `--custom-property` | ✅ | Any value | Custom properties are inherited along parent chain. |
202-
| `var(--name)` | ✅ | — | Resolved at cascade time with parent-chain lookup |
202+
| `var(--name)` | ✅ | — | In stylesheets (`<style>`, `customCss`) and inline. Before 1.10.0 only inline `style=""` resolved. Custom properties are cascaded before substitution; expansion is capped at 16 KB |
203203
| `var(--name, fallback)` | ✅ | — | Fallback used when variable not defined |
204-
| `calc()` | ✅ | px, em, rem, unitless | Correct operator precedence (`*`/`/` before `+`/`-`) |
204+
| `calc()` | ✅ | px, em, rem, unitless | Correct operator precedence (`*`/`/` before `+`/`-`). Stylesheet `calc()` resolves as of 1.10.0 (inline only before). `min()`/`max()`/`clamp()` are not evaluated |
205205
| `calc()` with `var()` | ✅ | — | `var()` resolved first, then arithmetic |
206206

207207
---

‎doc/LIMITATIONS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ are silently ignored.
2929
| `text-shadow` | ✅ Multiple shadows, blur supported |
3030
| `filter` / `backdrop-filter` | ✅ blur, brightness, contrast supported |
3131
| `@keyframes` | ✅ Parsed from `<style>` tags automatically |
32-
| `background-image` | ✅ url() and `linear-gradient()` supported |
32+
| `background-image` | ⚠️ `linear-gradient()` paints; `url()` is parsed (and scheme-checked) but no background image is painted |
3333
| `background-size` | ✅ cover, contain, fill supported |
3434
| `background-position` | ✅ Supported since v1.3.1 |
3535
| `background-repeat` | ✅ repeat/repeat-x/repeat-y/no-repeat/space/round supported since v1.3.1 |

‎doc/MIGRATION_GUIDE.md‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
# Migration Guide
22

3-
> **Current version: v1.4.0**
3+
> **Current version: v1.10.0**
4+
5+
## Upgrading to v1.10.0
6+
7+
No API changes, but **rendering can change** for pages that relied on CSS which used to be silently ignored:
8+
9+
- **`var()`, `url()` and `calc()` in `<style>` / `customCss` now resolve.** Before 1.10.0 they only worked in inline `style=""`. A page with `:root { --brand: … } p { color: var(--brand) }` now gets the brand color instead of the default.
10+
- **`:root` matches only the document root.** It used to match every element, so `:root { font-size: 125% }` compounded at each nesting level and `:root { --x }` reset descendant overrides.
11+
- **Stylesheet background URLs follow the `<img src>` scheme policy** (no `javascript:`, `file:`, `data:image/svg`, …).
12+
13+
```yaml
14+
dependencies:
15+
hyper_render: ^1.10.0
16+
hyper_render_devtools: ^1.8.0 # optional: new Timeline / Selection / CSS Vars / Export tabs
17+
```
418
519
## Upgrading to v1.4.0
620

0 commit comments

Comments
 (0)