Skip to content

Releases: mCodex/react-native-sized-webview

Release 1.3.0

05 May 13:18

Choose a tag to compare

🚀 react-native-sized-webview v1.3.0

A focused release that hardens the auto-height bridge, rebuilds the example app into a tour of real-world scenarios, and sharpens the docs. No breaking changes — drop-in upgrade from 1.2.x.


✨ Highlights

  • 🛡️ Hardened bridge protocol — every message is now namespaced (__RN_SIZED_WV__:<digits>) and validated by a strict regex; user-land postMessage can no longer mutate the container height.
  • 📐 No-wrapper measurement — the bridge no longer re-parents <body> children or injects inline styles. It measures the page in place, preserving margin collapse and author CSS on margin-heavy CMS content.
  • 🔁 Dual-phase idempotent injection — the bridge runs at both injectedJavaScriptBeforeContentLoaded and injectedJavaScript, covering iOS WKWebView edge cases where the early hook is skipped on inline source.html.
  • 🧪 Frozen public handlewindow.__RN_SIZED_WEBVIEW__ is non-writable, non-configurable, and exposes only { version, refresh, destroy }.
  • 🎨 Brand-new example app — four scenario-focused demos, themed UI components, and React Compiler integration.

🛡️ Security & Correctness

  • 🔒 Strict payload validationBRIDGE_NUMBER_PATTERN is now ^\d+$ (digits only), matching exactly what the bridge emits (String(Math.ceil(height))). Decimals, hex (0x100), exponential (1e10), NaN, Infinity, signed values, and whitespace-padded inputs are all rejected as forged input.
  • 🪟 Cross-frame postMessage filter — only same-window dispatches trigger work; arbitrary origins cannot ping the bridge.
  • 🧊 Frozen global handleObject.freeze + Object.defineProperty(writable: false, configurable: false) protect the public surface from page-script tampering.
  • 📏 Anomaly tracking + clamping — measurements above MAX_REASONABLE_HEIGHT (120 000 dp) are retried and then clamped to the last known good height.
  • 🧹 Warm-up guard — sub-WARMUP_MIN_HEIGHT first measurements are dropped (fixes iOS 26 WKWebView 1px collapse on tiny initial containers).

📐 Measurement (now O(k), not O(1))

Every measurement is the Math.max of multiple authoritative layout sources, without mutating the host page's DOM or styles:

  1. body.scrollHeight / body.offsetHeight
  2. documentElement.scrollHeight / documentElement.offsetHeight
  3. lastInFlowChild.getBoundingClientRect().bottom + computedMarginBottom

Inert siblings (SCRIPT, STYLE, META, LINK, TITLE, HEAD, NOSCRIPT) and out-of-flow positions (fixed / sticky / absolute) are skipped during the last-child walk so they never short-circuit the probe.

💡 Why O(k)? k is the number of trailing inert/out-of-flow siblings (typically 0–2). Effectively constant in steady state; one layout flush per measurement.

🐛 Bug Fixes

  • 🩹 Fixed systematic under-reporting on margin-heavy content. The previous synthetic <div> wrapper broke margin collapse between the body and its first/last children, causing both wrapper.scrollHeight and body.scrollHeight to under-report. The bridge now reads the user's DOM directly.
  • 🍎 Fixed iOS WebView source-reload missing remount — added a key prop on SizedWebView in the IntroDemo so source toggles correctly remount the WebView.
  • 🎯 Fixed bridge not loading on iOS inline HTML — dual injection at both lifecycle hooks ensures the bridge always boots.
  • 👀 Fixed late-reflow under-measurementResizeObserver now observes both document.body and document.documentElement.
  • ⏱️ Adaptive bootstrap-grace fallback — re-arms while either pendingLoads > 0 or within 5s of script start; refreshed by markLoading, font loadingdone, and state.refresh. Steady-state CPU cost: zero.

🎨 Example App Rebuild

The example app is now a modular tour of four scenarios:

  • 🧩 IntroDemo — short ↔ extended HTML toggle showing dynamic re-measurement.
  • 🌐 RemoteSitePicker — full external websites loaded by URL.
  • 🔤 GoogleFontDemo — late web-font reflow + document.fonts.loadingdone handling.
  • 📰 LongArticleDemo — long-form CMS content with margins, images, and headings.

Plus:

  • 🎨 Reusable PillButton and SectionHeader components on a shared theme (colors, spacing, radius).
  • 📦 Static HTML samples extracted into a dedicated articleSamples.ts data module.
  • React Compiler integration via babel-plugin-react-compiler.

📚 Documentation

  • 📖 Rewritten README — clearer demo walkthrough, accurate "How It Works" pipeline (no more references to a wrapper that no longer exists), and explicit performance characteristics.
  • 🧠 Spec-correct commentsgetBoundingClientRect is now described as viewport-relative (per CSSOM View) with the documented assumption that the host RN component sets scrollEnabled={false}.
  • ✍️ Copy-pasteable JSDoc examples — the useAutoHeight example now imports View from react-native.

🧰 Internals

  • ➖ Removed unused RENDERABLE_MEDIA_TAGS constant — smaller injected payload.
  • 🧼 Removed applyBaseStyles (no more inline overrides of user CSS on body/html).
  • 🧼 Removed pruneTrailingNodes, hasMeaningfulText, hasRenderableContent, ensureWrapper, and the state.wrapper / state.domDirty machinery.

📦 Compatibility

  • ✅ React Native 0.83+
  • ✅ React 19+
  • ✅ iOS 16+, Android API 24+
  • ✅ Compatible with the React Compiler

⬆️ Upgrading

yarn add react-native-sized-webview@1.3.0
# or
npm install react-native-sized-webview@1.3.0

No API changes. If you were importing the bridge string or hook directly:

import { View } from 'react-native';
import { WebView } from 'react-native-webview';
import { AUTO_HEIGHT_BRIDGE, useAutoHeight } from 'react-native-sized-webview';

function CustomSizedView({ html }: { html: string }) {
  const { height, setHeightFromPayload } = useAutoHeight({ minHeight: 0 });
  return (
    <View style={{ height }}>
      <WebView
        source={{ html }}
        injectedJavaScriptBeforeContentLoaded={AUTO_HEIGHT_BRIDGE}
        injectedJavaScript={AUTO_HEIGHT_BRIDGE}
        onMessage={(e) => setHeightFromPayload(e.nativeEvent.data)}
      />
    </View>
  );
}

Release 1.1.1

04 May 20:46

Choose a tag to compare

🚀 react-native-sized-webview v1.1.1

This release improves auto-height reliability for real-world HTML content rendered inside React Native WebView, especially rich-text/editor output with links, paragraphs, trailing empty blocks, non-breaking spaces, and platform-specific WebView layout quirks.

🐛 Fixed

  • Fixed cases where valid HTML content could be visually cut off because the injected height bridge undercounted the rendered document height.
  • Improved handling of editor-generated trailing nodes such as <p><br></p> without accidentally treating visible content as empty.
  • Fixed meaningful text detection for non-breaking spaces (&nbsp;), which can render visible layout content but was previously treated like empty whitespace by String.prototype.trim().

✨ Improved

  • Added a bounded rendered-content measurement pass that inspects actual DOM layout bounds as a fallback to scrollHeight, offsetHeight, and clientHeight.
  • Height measurement now considers the wrapper, body, and html elements instead of relying only on the internal wrapper.
  • Improved resilience for margin collapsing, overflow, and WKWebView cases where standard height properties may underreport content size.
  • Added a scan cap to keep measurement graceful on large documents and avoid expensive unbounded DOM traversal.
  • Simplified the generated TypeScript declaration for the injected bridge to expose it as a string instead of emitting a very large literal type.

💡 Why It Matters

Some WebView content can render beyond the height reported by common DOM properties. This is especially noticeable with rich HTML from CMS/editor sources, where trailing paragraphs, links, non-breaking spaces, and collapsed margins are common. The new measurement strategy follows the browser's rendered layout more closely, reducing clipped text while keeping the algorithm conservative and performant.

Release 1.1.0

24 Apr 18:23

Choose a tag to compare

  • Merge pull request #4 from mCodex/refactor/bumpDependencies (ee9fe39)
  • fix: revert version to 1.0.15 in package.json (96bf6ab)
  • Add tests for invalid height payloads (1f4c06c)
  • Guard bridge messages, optimize DOM measurements (5a7c875)
  • Release 1.1.0: safer defaults & bridge protocol (1e1f6e7)

Release 1.0.15

16 Dec 15:04

Choose a tag to compare

  • chore: remove conventional changelog plugin configuration (51570fe)
  • Merge pull request #2 from mCodex/fix/emptyHTMLTagsCleanup (8822ca3)
  • chore: updating dependencies (13b63c9)
  • Merge pull request #1 from mCodex/fix/emptyHTMLTagsCleanup (6e4231b)

Release 1.0.14

14 Nov 13:10

Choose a tag to compare

1.0.14 (2025-11-14)

  • Improve auto height bridge logic and update dependencies (17cdecd)

Full Changelog: v1.0.14...v1.0.14

Release 1.0.13

05 Nov 17:36

Choose a tag to compare

Release Notes

🚀 What’s New

  • 📐 Reworked the bridge measurement pipeline to trust the dedicated wrapper first, eliminating runaway heights from documentElement scroll math.
  • 🖼 Media now registers with a shared ResizeObserver and uses decode()/load events so late-loading images, iframes, and videos snap to the correct height without extra network fetches.
  • 🛡️ Added a sanity guard that retries and then clamps extreme height spikes (>120 000 px), keeping layout safe even when third-party markup misbehaves.

🔧 Quality & Stability

  • 🔁 Fallback loop now resets gracefully—the bridge retries a few times, then falls back to the last good measurement instead of spamming postMessage.
  • 🧼 Trailing <br>/empty <p> trimming remains in place, but paired with smarter wrapper rebuilds so DOM rewrites stay rock solid.
  • 📄 README refreshed to document the new safety checks, media pipeline, and overall sizing strategy.

📚 Docs & DX

  • ✍️ Updated highlights and architecture notes to match the modernized bridge so the README sells the current behavior clearly.
  • 🧪 Example app stays focused on real-world scenarios after removing the temporary debug toggle.

Thanks to these changes, react-native-sized-webview now handles dynamic, rich content (and the occasional flaky CMS export) with a whole lot more confidence. Enjoy the smoother sizing! 💪

Full Changelog: v1.0.12...v1.0.13

Release 1.0.4

05 Nov 14:00

Choose a tag to compare

1.0.4 (2025-11-05)

  • fix(autoHeightBridge): simplify height measurement, ensure body/html sizing, and extend update timeo (463b5e2)

Full Changelog: v1.0.3...v1.0.4

Release 1.0.3

05 Nov 13:49

Choose a tag to compare

1.0.3 (2025-11-05)

  • fix(autoHeightBridge): use getMaxHeight for measurement and account for devicePixelRatio (cadfb67)

Full Changelog: v1.0.2...v1.0.3

Release 1.0.2

04 Nov 14:28

Choose a tag to compare

1.0.2 (2025-11-04)

  • chore: improve JSDoc, tighten typings and update package keywords (99588fa)

Full Changelog: v1.0.1...v1.0.2

Release 1.0.1

03 Nov 19:46

Choose a tag to compare

1.0.1 (2025-11-03)

  • chore(example): move react-native-safe-area-context dependency into example package.json (3c320fa)
  • chore(package.json): remove src from packaged files and ignore .map artifacts (677726c)
  • ci: add yarn prepare step to build-web job before exporting web example (f3c0915)

Full Changelog: v1.0.0...v1.0.1