Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,25 @@ jobs:

exit $EXIT

# Sub-packages the root excludes: each one only resolves against its
# own pubspec, so analyze it in place after its own pub get.
- name: flutter analyze sub-packages
if: steps.filter.outputs.any_dart == 'true'
run: |
FAILED=""
for pkg in hyper_render_html hyper_render_markdown hyper_render_highlight \
hyper_render_math hyper_render_clipboard hyper_render_devtools \
hyper_render_epub; do
echo "::group::$pkg"
(cd "packages/$pkg" && flutter pub get >/dev/null && \
flutter analyze --no-pub --fatal-warnings --fatal-infos) || FAILED="$FAILED $pkg"
echo "::endgroup::"
done
if [ -n "$FAILED" ]; then
echo "::error::analyze failed in:$FAILED"
exit 1
fi

- name: Upload analyze report
if: always() && steps.filter.outputs.any_dart == 'true'
uses: actions/upload-artifact@v4
Expand Down
25 changes: 12 additions & 13 deletions .github/workflows/deploy_web_demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@ on:
branches: [main]
workflow_dispatch:

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

concurrency:
group: 'pages'
cancel-in-progress: true

jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
Expand All @@ -40,11 +39,11 @@ jobs:
cd example
flutter build web --release --base-href "/hyper_render/"

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
- name: Publish to gh-pages
uses: peaceiris/actions-gh-pages@v4
with:
path: example/build/web

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: example/build/web
publish_branch: gh-pages
force_orphan: true # keep gh-pages to a single commit, no history bloat
commit_message: "deploy: live web demo"
88 changes: 45 additions & 43 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ jobs:
changed_highlight: ${{ steps.filter.outputs.highlight }}
changed_clipboard: ${{ steps.filter.outputs.clipboard }}
changed_devtools: ${{ steps.filter.outputs.devtools }}
changed_math: ${{ steps.filter.outputs.math }}
changed_epub: ${{ steps.filter.outputs.epub }}
changed_root: ${{ steps.filter.outputs.root }}
changed_any_dart: ${{ steps.filter.outputs.any_dart }}
steps:
Expand All @@ -60,6 +62,10 @@ jobs:
- 'packages/hyper_render_clipboard/**'
devtools:
- 'packages/hyper_render_devtools/**'
math:
- 'packages/hyper_render_math/**'
epub:
- 'packages/hyper_render_epub/**'
root:
- 'lib/**'
- 'test/**'
Expand Down Expand Up @@ -99,45 +105,12 @@ jobs:
working-directory: example/android
run: ./gradlew assembleDebug

emulator-tests:
name: Integration Tests (Emulator)
runs-on: macos-latest
needs: path-filter
if: >-
github.event_name == 'pull_request' &&
needs.path-filter.outputs.changed_any_dart == 'true'
strategy:
fail-fast: false
matrix:
platform: [android, ios]
steps:
- uses: actions/checkout@v4
- name: Setup Java
if: matrix.platform == 'android'
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '17'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: stable
cache: true
- name: flutter pub get
run: flutter pub get
- name: Run Android Emulator Tests
if: matrix.platform == 'android'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
arch: arm64-v8a
script: flutter test test/integration/
- name: Run iOS Simulator Tests
if: matrix.platform == 'ios'
run: |
xcrun simctl list devicetypes
flutter test test/integration/ -d "iPhone 15" || flutter test test/integration/
# NOTE: the former "Integration Tests (Emulator)" job was removed. It ran
# `flutter test test/integration/` with no device target, i.e. on the host VM
# — the same tests test-pr runs below — but on macOS runners (10x the
# per-minute price), and its Android leg could not boot an x86 emulator on
# Apple Silicon (HVF_UNSUPPORTED). Real on-device coverage lives in
# example/integration_test/all_demos_test.dart (run locally with -d macos).

test-pr:
name: Tests (PR · ubuntu-22.04 · stable)
Expand Down Expand Up @@ -190,31 +163,60 @@ jobs:
needs.path-filter.outputs.changed_html == 'true' ||
needs.path-filter.outputs.changed_core == 'true'
working-directory: packages/hyper_render_html
run: flutter test --no-pub
run: flutter pub get && flutter test --no-pub

- name: Test hyper_render_markdown
if: >-
needs.path-filter.outputs.changed_markdown == 'true' ||
needs.path-filter.outputs.changed_core == 'true'
working-directory: packages/hyper_render_markdown
run: |
if [ -d test ]; then flutter test --no-pub; else echo "No tests in this package — skipping."; fi
if [ -d test ]; then flutter pub get && flutter test --no-pub; else echo "No tests in this package — skipping."; fi

- name: Test hyper_render_highlight
if: >-
needs.path-filter.outputs.changed_highlight == 'true' ||
needs.path-filter.outputs.changed_core == 'true'
working-directory: packages/hyper_render_highlight
run: |
if [ -d test ]; then flutter test --no-pub; else echo "No tests in this package — skipping."; fi
if [ -d test ]; then flutter pub get && flutter test --no-pub; else echo "No tests in this package — skipping."; fi

- name: Test hyper_render_clipboard
if: >-
needs.path-filter.outputs.changed_clipboard == 'true' ||
needs.path-filter.outputs.changed_core == 'true'
working-directory: packages/hyper_render_clipboard
run: |
if [ -d test ]; then flutter test --no-pub; else echo "No tests in this package — skipping."; fi
if [ -d test ]; then flutter pub get && flutter test --no-pub; else echo "No tests in this package — skipping."; fi

- name: Test hyper_render_math
if: >-
needs.path-filter.outputs.changed_math == 'true' ||
needs.path-filter.outputs.changed_core == 'true'
working-directory: packages/hyper_render_math
run: flutter pub get && flutter test --no-pub

- name: Test hyper_render_epub
if: >-
needs.path-filter.outputs.changed_epub == 'true' ||
needs.path-filter.outputs.changed_root == 'true' ||
needs.path-filter.outputs.changed_core == 'true'
working-directory: packages/hyper_render_epub
run: flutter pub get && flutter test --no-pub

- name: Test hyper_render_devtools
if: >-
needs.path-filter.outputs.changed_devtools == 'true' ||
needs.path-filter.outputs.changed_core == 'true'
working-directory: packages/hyper_render_devtools
run: flutter pub get && flutter test --no-pub

# The panel imports dart:js_interop: its widget test only compiles for
# the web (@TestOn('browser')). ubuntu runners ship Chrome.
- name: Test hyper_render_devtools panel (Chrome)
if: needs.path-filter.outputs.changed_devtools == 'true'
working-directory: packages/hyper_render_devtools/devtools_ui
run: flutter pub get && flutter test --no-pub --platform chrome

- name: Upload test results
if: failure()
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 1.10.0

- **`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.
- **Requires `hyper_render_core` `^1.10.0`.** `HyperViewer` uses the new `StyleResolver.customPropertyOverrides` and `HyperRenderDebugHooks.cssVariableOverrides`.
- **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.

## 1.9.1

- **`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.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Already using `flutter_html`? You don't need to rewrite your widget tree or lear
```dart
// 1. In your pubspec.yaml:
// dependencies:
// hyper_render: ^1.9.0
// hyper_render: ^1.10.0

// 2. In your Dart file — replace this single line:
// ❌ import 'package:flutter_html/flutter_html.dart';
Expand Down Expand Up @@ -68,7 +68,7 @@ Html(

```yaml
dependencies:
hyper_render: ^1.9.0
hyper_render: ^1.10.0
```

```dart
Expand Down Expand Up @@ -477,7 +477,7 @@ HTML / Markdown / Quill Delta
| [`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 |
| [`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) |
| [`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 |
| [`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 |
| [`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 |

### Optional add-ons

Expand Down
10 changes: 6 additions & 4 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ This document outlines the architectural roadmap for **HyperRender** to become t

| Version | Target Date | Strategic Focus | Key Differentiators |
| :--- | :--- | :--- | :--- |
| **v1.7.0** | Current | **Production Hardening & Drop-in Migration** | Single RenderObject, 100% WASM support, 160/160 pub score, 30s `flutter_html` drop-in layer. |
| **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. |
| **v1.9.0** | Q4 2026 | **Native Vector Diagramming & Headless Export** | Pure Canvas/Vector Mermaid.js & GraphViz (Zero-WebView), Headless Image & PDF byte stream generator. |
| **v1.7.0** | Shipped | **Production Hardening & Drop-in Migration** | Single RenderObject, 100% WASM support, 160/160 pub score, 30s `flutter_html` drop-in layer. |
| **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. |
| **v1.9.0** | Shipped | **Wrapping Flexbox** | `flex-wrap: wrap` on a dedicated `RenderFlexWrap` (#15). |
| **v1.10.0** | Current | **DevTools v2 & Stylesheet CSS Correctness** | Timeline / Selection / live CSS-variable / snapshot DevTools tabs; stylesheet `var()`, `url()`, `calc()` and `:root` fixed. |
| **Next** | Unscheduled | **Native Vector Diagramming & Headless Export** | Pure Canvas/Vector Mermaid.js & GraphViz (Zero-WebView), Headless Image & PDF byte stream generator. |
| **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`). |

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

---

## 📊 v1.9.0: Native Vector Diagramming & Headless Export (WebView Replacement)
## 📊 Next (unscheduled): Native Vector Diagramming & Headless Export (WebView Replacement)

### 1. Native Mermaid.js & GraphViz Vector Engine (Zero-WebView)
- **Problem**: Technical docs, GitHub clients, and EdTech apps embed WebViews solely for Mermaid diagrams, adding 50MB+ RAM overhead per instance with poor gesture response.
Expand Down
7 changes: 7 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ analyzer:
# Sub-packages have their own pubspec.yaml and analysis_options.yaml.
# Excluding them prevents "uri_does_not_exist" errors for deps that are
# only declared in those packages (super_clipboard, devtools_extensions…).
# Only hyper_render_core resolves from the root package config; every
# other sub-package is analyzed in its own directory (see analyze.yml).
- packages/hyper_render_clipboard/**
- packages/hyper_render_devtools/**
- packages/hyper_render_epub/**
- packages/hyper_render_highlight/**
- packages/hyper_render_html/**
- packages/hyper_render_markdown/**
- packages/hyper_render_math/**
errors:
# Monorepo: sub-packages use path: deps for local development.
# The publish workflow swaps to version: deps before pub publish.
Expand Down
8 changes: 4 additions & 4 deletions doc/CSS_PROPERTIES_MATRIX.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# CSS Properties Support Matrix

Last Updated: September 6, 2026
Version: 1.9.1
Last Updated: October 2, 2026
Version: 1.10.0

This document lists CSS property support in HyperRender.

Expand Down Expand Up @@ -199,9 +199,9 @@ This document lists CSS property support in HyperRender.
| Feature | Status | Supported Values | Notes |
|---------|--------|------------------|-------|
| `--custom-property` | ✅ | Any value | Custom properties are inherited along parent chain. |
| `var(--name)` | ✅ | — | Resolved at cascade time with parent-chain lookup |
| `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 |
| `var(--name, fallback)` | ✅ | — | Fallback used when variable not defined |
| `calc()` | ✅ | px, em, rem, unitless | Correct operator precedence (`*`/`/` before `+`/`-`) |
| `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 |
| `calc()` with `var()` | ✅ | — | `var()` resolved first, then arithmetic |

---
Expand Down
2 changes: 1 addition & 1 deletion doc/LIMITATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ are silently ignored.
| `text-shadow` | ✅ Multiple shadows, blur supported |
| `filter` / `backdrop-filter` | ✅ blur, brightness, contrast supported |
| `@keyframes` | ✅ Parsed from `<style>` tags automatically |
| `background-image` | ✅ url() and `linear-gradient()` supported |
| `background-image` | ⚠️ `linear-gradient()` paints; `url()` is parsed (and scheme-checked) but no background image is painted |
| `background-size` | ✅ cover, contain, fill supported |
| `background-position` | ✅ Supported since v1.3.1 |
| `background-repeat` | ✅ repeat/repeat-x/repeat-y/no-repeat/space/round supported since v1.3.1 |
Expand Down
16 changes: 15 additions & 1 deletion doc/MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# Migration Guide

> **Current version: v1.4.0**
> **Current version: v1.10.0**

## Upgrading to v1.10.0

No API changes, but **rendering can change** for pages that relied on CSS which used to be silently ignored:

- **`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.
- **`: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.
- **Stylesheet background URLs follow the `<img src>` scheme policy** (no `javascript:`, `file:`, `data:image/svg`, …).

```yaml
dependencies:
hyper_render: ^1.10.0
hyper_render_devtools: ^1.8.0 # optional: new Timeline / Selection / CSS Vars / Export tabs
```

## Upgrading to v1.4.0

Expand Down
Loading
Loading