From 17cdecd893936c22774bfdc5a2576174bce225ff Mon Sep 17 00:00:00 2001 From: Mateus Andrade Date: Fri, 14 Nov 2025 10:07:47 -0300 Subject: [PATCH 1/2] Improve auto height bridge logic and update dependencies Refactored the autoHeightBridge to enhance content detection and height measurement, including more robust handling of renderable content and element height calculation. Updated dependencies in example/package.json to latest patch versions for expo, react, react-dom, and dev tools. These changes improve reliability and maintain compatibility with the latest ecosystem updates. --- example/package.json | 8 +- src/constants/autoHeightBridge.ts | 136 ++++++++++++++++++--------- yarn.lock | 148 +++++++++++++++++++----------- 3 files changed, 190 insertions(+), 102 deletions(-) diff --git a/example/package.json b/example/package.json index bf089e8..a21116e 100644 --- a/example/package.json +++ b/example/package.json @@ -10,10 +10,10 @@ }, "dependencies": { "@expo/metro-runtime": "~6.1.2", - "expo": "~54.0.21", + "expo": "~54.0.23", "expo-status-bar": "~3.0.8", - "react": "19.1.0", - "react-dom": "19.1.0", + "react": "19.1.1", + "react-dom": "19.1.1", "react-native": "0.81.5", "react-native-safe-area-context": "^5.6.2", "react-native-web": "~0.21.2", @@ -21,7 +21,7 @@ }, "private": true, "devDependencies": { - "react-native-builder-bob": "^0.40.14", + "react-native-builder-bob": "^0.40.15", "react-native-monorepo-config": "^0.3.0" } } diff --git a/src/constants/autoHeightBridge.ts b/src/constants/autoHeightBridge.ts index aca5f30..f421492 100644 --- a/src/constants/autoHeightBridge.ts +++ b/src/constants/autoHeightBridge.ts @@ -57,7 +57,6 @@ export const AUTO_HEIGHT_BRIDGE = `(() => { microtask: false, pendingLoads: 0, lastHeight: 0, - lastCssHeight: 0, anomalyCount: 0, fallbackTimer: null, fallbackDelay: INITIAL_FALLBACK_MS, @@ -173,13 +172,62 @@ export const AUTO_HEIGHT_BRIDGE = `(() => { return id; }; + var RENDERABLE_MEDIA_TAGS = { + IMG: true, + IFRAME: true, + VIDEO: true, + SVG: true, + CANVAS: true, + PICTURE: true, + OBJECT: true, + EMBED: true, + AUDIO: true, + }; + + var hasRenderableContent = function (node) { + if (!node || !node.childNodes || !node.childNodes.length) { + return false; + } + + var child = node.firstChild; + while (child) { + if (child.nodeType === 3) { + if (child.textContent && child.textContent.trim()) { + return true; + } + } else if (child.nodeType === 1) { + var tag = (child.tagName || '').toUpperCase(); + if (tag === 'BR') { + child = child.nextSibling; + continue; + } + + if (RENDERABLE_MEDIA_TAGS[tag]) { + return true; + } + + if (hasRenderableContent(child)) { + return true; + } + } + + child = child.nextSibling; + } + + return false; + }; + var pruneTrailingNodes = function (container) { if (!container) { return; } var isWhitespaceText = function (node) { - return node && node.nodeType === 3 && (!node.textContent || !node.textContent.trim()); + return ( + node && + node.nodeType === 3 && + (!node.textContent || !node.textContent.trim()) + ); }; var isTrimmableElement = function (node) { @@ -193,7 +241,7 @@ export const AUTO_HEIGHT_BRIDGE = `(() => { } if (tag === 'P') { - return !node.textContent || !node.textContent.trim(); + return !hasRenderableContent(node); } return false; @@ -231,66 +279,70 @@ export const AUTO_HEIGHT_BRIDGE = `(() => { } }; - var readRectHeight = function (element) { - if (!element || typeof element.getBoundingClientRect !== 'function') { + var readElementHeight = function (element) { + if (!element) { return 0; } - var rect = element.getBoundingClientRect(); - return typeof rect.height === 'number' ? rect.height : 0; - }; - - var readMaxValue = function (values) { - var max = 0; - - for (var index = 0; index < values.length; index += 1) { - var value = values[index]; - if (typeof value === 'number' && value > max) { - max = value; - } + var rectHeight = 0; + if (typeof element.getBoundingClientRect === 'function') { + var rect = element.getBoundingClientRect(); + rectHeight = rect && typeof rect.height === 'number' ? rect.height : 0; } - return max; + return Math.max( + 0, + rectHeight, + element.scrollHeight || 0, + element.offsetHeight || 0, + element.clientHeight || 0 + ); }; var measureHeight = function () { var html = document.documentElement; var body = document.body; var wrapper = ensureWrapper(); + var scrollingElement = document.scrollingElement; pruneTrailingNodes(wrapper); - var values = []; + var targets = []; - var collect = function (element) { - if (!element) { - return; - } + if (wrapper) { + targets.push(wrapper); + } - values.push( - readRectHeight(element), - element.scrollHeight || 0, - element.offsetHeight || 0, - element.clientHeight || 0 - ); - }; + if (body && targets.indexOf(body) === -1) { + targets.push(body); + } - if (wrapper) { - collect(wrapper); - } else { - if (body) { - collect(body); - } - if (html && html !== body) { - collect(html); - } + if (html && targets.indexOf(html) === -1) { + targets.push(html); + } + + if ( + scrollingElement && + scrollingElement !== body && + scrollingElement !== html && + targets.indexOf(scrollingElement) === -1 + ) { + targets.push(scrollingElement); } - if (!values.length) { + if (!targets.length) { return 0; } - return Math.max(0, Math.ceil(readMaxValue(values))); + var maxHeight = 0; + for (var index = 0; index < targets.length; index += 1) { + var value = readElementHeight(targets[index]); + if (value > maxHeight) { + maxHeight = value; + } + } + + return Math.max(0, Math.ceil(maxHeight)); }; var postHeight = function (height) { @@ -298,8 +350,6 @@ export const AUTO_HEIGHT_BRIDGE = `(() => { return; } - state.lastCssHeight = height; - var sanitized = Math.ceil(height); if (!isFinite(sanitized) || sanitized <= 0) { diff --git a/yarn.lock b/yarn.lock index 88380c1..5d7b851 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1929,9 +1929,9 @@ __metadata: languageName: node linkType: hard -"@expo/cli@npm:54.0.14": - version: 54.0.14 - resolution: "@expo/cli@npm:54.0.14" +"@expo/cli@npm:54.0.16": + version: 54.0.16 + resolution: "@expo/cli@npm:54.0.16" dependencies: "@0no-co/graphql.web": ^1.0.8 "@expo/code-signing-certificates": ^0.0.5 @@ -1941,9 +1941,9 @@ __metadata: "@expo/env": ~2.0.7 "@expo/image-utils": ^0.8.7 "@expo/json-file": ^10.0.7 - "@expo/mcp-tunnel": ~0.0.7 + "@expo/mcp-tunnel": ~0.1.0 "@expo/metro": ~54.1.0 - "@expo/metro-config": ~54.0.8 + "@expo/metro-config": ~54.0.9 "@expo/osascript": ^2.3.7 "@expo/package-manager": ^1.9.8 "@expo/plist": ^0.4.7 @@ -1966,7 +1966,7 @@ __metadata: connect: ^3.7.0 debug: ^4.3.4 env-editor: ^0.4.1 - expo-server: ^1.0.3 + expo-server: ^1.0.4 freeport-async: ^2.0.0 getenv: ^2.0.0 glob: ^10.4.2 @@ -2008,7 +2008,7 @@ __metadata: optional: true bin: expo-internal: build/bin/cli - checksum: aa051779deb94347e2fc45572a470b1c5459d53bd2eaff18dfe1b46cab670f010e2627fa1eefbc50ccf7145c823ff00c0494ca501ff40fd693d0fa15e3d1cbe5 + checksum: b603f2604df2bdc70f9b9fc63a8080729bdd876d38edfe697258407a7b04bdc9ca2ab1304d42fb61d049156c3ede31fb3fed90b5ee2ee2c3bb4f7cee93495ad1 languageName: node linkType: hard @@ -2113,9 +2113,9 @@ __metadata: languageName: node linkType: hard -"@expo/fingerprint@npm:0.15.2": - version: 0.15.2 - resolution: "@expo/fingerprint@npm:0.15.2" +"@expo/fingerprint@npm:0.15.3": + version: 0.15.3 + resolution: "@expo/fingerprint@npm:0.15.3" dependencies: "@expo/spawn-async": ^1.7.2 arg: ^5.0.2 @@ -2130,7 +2130,7 @@ __metadata: semver: ^7.6.0 bin: fingerprint: bin/cli.js - checksum: 5af7ce89c3f0d13e6f38013da5f190d91327b6cbc8ba1633a7e919feea6704c65e5d6daa2289f10f32c475ae0718a13bdbb5e05a304f8cb92d838c88ecf318e7 + checksum: ab2d8febf63de45bc9974616d73840bd5a612fbe8de46ecf49d9f137250724ff3efc9dfbd72924d283a88e29d74983e05f9e8ce517a56cf5df09c85a9ed58f72 languageName: node linkType: hard @@ -2162,9 +2162,9 @@ __metadata: languageName: node linkType: hard -"@expo/mcp-tunnel@npm:~0.0.7": - version: 0.0.8 - resolution: "@expo/mcp-tunnel@npm:0.0.8" +"@expo/mcp-tunnel@npm:~0.1.0": + version: 0.1.0 + resolution: "@expo/mcp-tunnel@npm:0.1.0" dependencies: ws: ^8.18.3 zod: ^3.25.76 @@ -2174,13 +2174,13 @@ __metadata: peerDependenciesMeta: "@modelcontextprotocol/sdk": optional: true - checksum: f3ec8933a7a33d5d54cbb98e4c59cb923b3b0a444aadd31378495b60a3cdd2d0a1229571fd8e2b2eec984eb94d02012953c396758c45e09c259dc5fa7bd057d5 + checksum: ebc0d2cfc9e945b57a5ad62cc4d43cdc989ec8195d218c524761e88384bebb69ab55ea65b3795d9d7970356a0fd1c4aba5b72e110c502cfdba3d054c8f9d454b languageName: node linkType: hard -"@expo/metro-config@npm:54.0.8, @expo/metro-config@npm:~54.0.8": - version: 54.0.8 - resolution: "@expo/metro-config@npm:54.0.8" +"@expo/metro-config@npm:54.0.9, @expo/metro-config@npm:~54.0.9": + version: 54.0.9 + resolution: "@expo/metro-config@npm:54.0.9" dependencies: "@babel/code-frame": ^7.20.0 "@babel/core": ^7.20.0 @@ -2208,7 +2208,7 @@ __metadata: peerDependenciesMeta: expo: optional: true - checksum: fa96c208c76d10f55ed26044b9b8b49ffb3e81acf85ff6acd3f865304d4410f4c3a7ce4f40d75c8a271fafc0dcb161f20e29ec4b59c5db68be33365847034d37 + checksum: c4186badd61008ca9bf220ecd5b66259bc7059161eef4879c1ab3a9b3d34e116139bcd0ddb0990b421b3c4c1d7a8018bd128b305848656c59143605f14ba0149 languageName: node linkType: hard @@ -4918,9 +4918,9 @@ __metadata: languageName: node linkType: hard -"babel-preset-expo@npm:~54.0.6": - version: 54.0.6 - resolution: "babel-preset-expo@npm:54.0.6" +"babel-preset-expo@npm:~54.0.7": + version: 54.0.7 + resolution: "babel-preset-expo@npm:54.0.7" dependencies: "@babel/helper-module-imports": ^7.25.9 "@babel/plugin-proposal-decorators": ^7.12.9 @@ -4953,7 +4953,7 @@ __metadata: optional: true expo: optional: true - checksum: 914db23267c1b32430faeac50992e76b20f1ec5ac2bfc6778483226df0d8a486adc7115f294493b5719a738954f4a787f8a2d5dfd4b84ad2d17883f7ad3a636b + checksum: b45071a65c720fd98543712f30db727e874a8a310c198675bcb75533bd3a0798e253069025d3cc7e1a1746a9e2e0b1594fbe5a2164013924bf4082f41beb71fb languageName: node linkType: hard @@ -6993,38 +6993,37 @@ __metadata: languageName: node linkType: hard -"expo-modules-autolinking@npm:3.0.19": - version: 3.0.19 - resolution: "expo-modules-autolinking@npm:3.0.19" +"expo-modules-autolinking@npm:3.0.21": + version: 3.0.21 + resolution: "expo-modules-autolinking@npm:3.0.21" dependencies: "@expo/spawn-async": ^1.7.2 chalk: ^4.1.0 commander: ^7.2.0 - glob: ^10.4.2 require-from-string: ^2.0.2 resolve-from: ^5.0.0 bin: expo-modules-autolinking: bin/expo-modules-autolinking.js - checksum: 4cd4c2f310a6fafcf830d1e92083b57edf068f00da31de458a8338063fe3c1164a459a52ea0fc8fb3441dff88d58837f3802dc8d627ad1a4aefbea30a6374769 + checksum: 50fd61a01b70bda5e879faa6c29fe4473da4ab851b3ef56e298648324a126ed73b0992e9cbd6270ee6a5e0507d9102f6916651b4ff5ce89c41b8a92aed0659b8 languageName: node linkType: hard -"expo-modules-core@npm:3.0.23": - version: 3.0.23 - resolution: "expo-modules-core@npm:3.0.23" +"expo-modules-core@npm:3.0.25": + version: 3.0.25 + resolution: "expo-modules-core@npm:3.0.25" dependencies: invariant: ^2.2.4 peerDependencies: react: "*" react-native: "*" - checksum: 6e5c873987b2cca1e9b2bf4aa642361773938daf49fe43a7ec1a06db9e3c2076cbd40f560a3752a51f5aba4fc11f4579329b8a0eaa23064543f223643dff504d + checksum: 360fa2f7295c5e2e9db403fb1e32aeb2e5c3d42964a3007b6305a8795cdb66f9c1d36d23bc62197c66319897f8b13bc0f2fc6fb88920a7ba0b13eb3422ed8201 languageName: node linkType: hard -"expo-server@npm:^1.0.3": - version: 1.0.3 - resolution: "expo-server@npm:1.0.3" - checksum: cddfd7625fb20681c5398982460d2dfd0a165f0e316b668837cedba186bb716f8186cfc9cc38041a2b2bec23000db1f7614c73c6be1c69627ae9ceff3476d4bd +"expo-server@npm:^1.0.4": + version: 1.0.4 + resolution: "expo-server@npm:1.0.4" + checksum: 830b6c16583ed2e593d3369ae45b380ca66e5861173636cee0ec36108640982813893e070db1e1f2710aef0f9382be1730344e9f22d05bb7fb5278fea001eca9 languageName: node linkType: hard @@ -7040,28 +7039,28 @@ __metadata: languageName: node linkType: hard -"expo@npm:~54.0.21": - version: 54.0.21 - resolution: "expo@npm:54.0.21" +"expo@npm:~54.0.23": + version: 54.0.23 + resolution: "expo@npm:54.0.23" dependencies: "@babel/runtime": ^7.20.0 - "@expo/cli": 54.0.14 + "@expo/cli": 54.0.16 "@expo/config": ~12.0.10 "@expo/config-plugins": ~54.0.2 "@expo/devtools": 0.1.7 - "@expo/fingerprint": 0.15.2 + "@expo/fingerprint": 0.15.3 "@expo/metro": ~54.1.0 - "@expo/metro-config": 54.0.8 + "@expo/metro-config": 54.0.9 "@expo/vector-icons": ^15.0.3 "@ungap/structured-clone": ^1.3.0 - babel-preset-expo: ~54.0.6 + babel-preset-expo: ~54.0.7 expo-asset: ~12.0.9 expo-constants: ~18.0.10 expo-file-system: ~19.0.17 expo-font: ~14.0.9 expo-keep-awake: ~15.0.7 - expo-modules-autolinking: 3.0.19 - expo-modules-core: 3.0.23 + expo-modules-autolinking: 3.0.21 + expo-modules-core: 3.0.25 pretty-format: ^29.7.0 react-refresh: ^0.14.2 whatwg-url-without-unicode: 8.0.0-3 @@ -7082,7 +7081,7 @@ __metadata: expo: bin/cli expo-modules-autolinking: bin/autolinking fingerprint: bin/fingerprint - checksum: c928fea530134ad9ff8a508ba8f529620e36ac08b1099c9b13dbeb581597920296acf5db8e11874fcaa8beaf5e49a2e06bf6a429c322decfc46dfc9e466d4f1b + checksum: 0509035d1234f04c57fe8082879df2ae4f85858def352da7f8c46fc5ed12ebd85b61f68d71adf1a46b1fe52f530367d1533c527b6394fc0392fea98771cf3fa2 languageName: node linkType: hard @@ -11688,14 +11687,14 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:19.1.0": - version: 19.1.0 - resolution: "react-dom@npm:19.1.0" +"react-dom@npm:19.1.1": + version: 19.1.1 + resolution: "react-dom@npm:19.1.1" dependencies: scheduler: ^0.26.0 peerDependencies: - react: ^19.1.0 - checksum: 1d154b6543467095ac269e61ca59db546f34ef76bcdeb90f2dad41d682cd210aae492e70c85010ed5d0a2caea225e9a55139ebc1a615ee85bf197d7f99678cdf + react: ^19.1.1 + checksum: 71d63df955e99bb58470c6ae12ebb82fa80e2a73147c387b73a31c17bcff803ce8aded52ae0c4391c9b413be0aa449249d8be7d063136826d1f0caba9720a907 languageName: node linkType: hard @@ -11752,6 +11751,38 @@ __metadata: languageName: node linkType: hard +"react-native-builder-bob@npm:^0.40.15": + version: 0.40.15 + resolution: "react-native-builder-bob@npm:0.40.15" + dependencies: + "@babel/core": ^7.25.2 + "@babel/plugin-transform-flow-strip-types": ^7.26.5 + "@babel/plugin-transform-strict-mode": ^7.24.7 + "@babel/preset-env": ^7.25.2 + "@babel/preset-react": ^7.24.7 + "@babel/preset-typescript": ^7.24.7 + arktype: ^2.1.15 + babel-plugin-syntax-hermes-parser: ^0.28.0 + browserslist: ^4.20.4 + cross-spawn: ^7.0.3 + dedent: ^0.7.0 + del: ^6.1.1 + escape-string-regexp: ^4.0.0 + fs-extra: ^10.1.0 + glob: ^8.0.3 + is-git-dirty: ^2.0.1 + json5: ^2.2.1 + kleur: ^4.1.4 + prompts: ^2.4.2 + react-native-monorepo-config: ^0.1.8 + which: ^2.0.2 + yargs: ^17.5.1 + bin: + bob: bin/bob + checksum: abe76dfce15679da3c8c475d39127bc1cb970118be3bd964b63bb6aeabe8d3eb42698f5d86b05386af12ba378f924a7a1e4e22194ca400c92e6961d2000dc682 + languageName: node + linkType: hard + "react-native-is-edge-to-edge@npm:^1.2.1": version: 1.2.1 resolution: "react-native-is-edge-to-edge@npm:1.2.1" @@ -11797,12 +11828,12 @@ __metadata: resolution: "react-native-sized-webview-example@workspace:example" dependencies: "@expo/metro-runtime": ~6.1.2 - expo: ~54.0.21 + expo: ~54.0.23 expo-status-bar: ~3.0.8 - react: 19.1.0 - react-dom: 19.1.0 + react: 19.1.1 + react-dom: 19.1.1 react-native: 0.81.5 - react-native-builder-bob: ^0.40.14 + react-native-builder-bob: ^0.40.15 react-native-monorepo-config: ^0.3.0 react-native-safe-area-context: ^5.6.2 react-native-web: ~0.21.2 @@ -12007,6 +12038,13 @@ __metadata: languageName: node linkType: hard +"react@npm:19.1.1": + version: 19.1.1 + resolution: "react@npm:19.1.1" + checksum: f2f18fea5deac87b1167365bd5160bcba64d383c26a37afa905b714ca424f423ef97d8daf53f041ab9ac25a06357fafcf0b5d3b6b84c9d1eace0e621bfeae629 + languageName: node + linkType: hard + "read-package-up@npm:^11.0.0": version: 11.0.0 resolution: "read-package-up@npm:11.0.0" From fb375981baa04c8fd373cd949d2b3b315cf52e5d Mon Sep 17 00:00:00 2001 From: Mateus Andrade Date: Fri, 14 Nov 2025 10:10:05 -0300 Subject: [PATCH 2/2] chore: release 1.0.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d1d4fdc..2d71266 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-sized-webview", - "version": "1.0.13", + "version": "1.0.14", "description": "React Native WebView that auto-sizes to match its HTML content—whether you load local HTML or full external websites—without manual measurements, timers, or layout flicker.", "main": "./lib/module/index.js", "module": "./lib/module/index.js",