Draft
Conversation
When window.open() fails (common on mobile browsers like Firefox Mobile), fall back to navigating the current tab with scraped data encoded as JSON in a _data URL parameter. The PHP backend parses and sanitizes this inline data through the same limit_* methods used for POST data, and the React app skips the postMessage listener when inline data mode is active. Arrays are trimmed (5 images, 3 embeds) in the fallback path to keep URL length manageable. See #50
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves Press This bookmarklet compatibility on mobile browsers where window.open() commonly fails by introducing a current-tab navigation fallback that carries scraped data inline.
Changes:
- Add a popup-blocked fallback in the bookmarklet that navigates the current tab and passes scraped data via a
_dataJSON URL parameter (with some array trimming). - Extend the PHP bootstrap to parse/merge
_datausing existinglimit_*sanitizers and expose aninlineDataModeflag to the React app. - Update the React app to skip the postMessage listener when inline data mode is active, and add tests for the new behavior.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
assets/bookmarklet.js |
Adds popup-blocked fallback to current-tab navigation with _data JSON payload and trims large arrays. |
assets/bookmarklet.min.js |
Regenerates minified bookmarklet to include the fallback behavior. |
class-wp-press-this-plugin.php |
Parses _data, merges sanitized inline values into $data, tracks inlineDataMode, and adjusts proxy/content generation behavior. |
src/App.js |
Skips postMessage listening when inlineDataMode is enabled. |
tests/bookmarklet/bookmarklet.test.js |
Adds assertions that fallback navigation and trimming logic exist in the bookmarklet source. |
tests/php/test-integration.php |
Adds integration tests covering _data parsing, precedence rules, and invalid JSON handling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
class-wp-press-this-plugin.php
Outdated
Comment on lines
+801
to
+829
| // Process media arrays. | ||
| foreach ( array( '_images', '_embeds', '_og_video' ) as $type ) { | ||
| if ( empty( $inline_data[ $type ] ) || ! is_array( $inline_data[ $type ] ) ) { | ||
| continue; | ||
| } | ||
|
|
||
| if ( ! isset( $data[ $type ] ) ) { | ||
| $data[ $type ] = array(); | ||
| } | ||
|
|
||
| $items = $this->limit_array( $inline_data[ $type ] ); | ||
|
|
||
| foreach ( $items as $value ) { | ||
| if ( '_images' === $type ) { | ||
| $value = $this->limit_img( $value ); | ||
| } else { | ||
| $value = $this->limit_embed( $value ); | ||
| } | ||
|
|
||
| if ( ! empty( $value ) && ! in_array( $value, $data[ $type ], true ) ) { | ||
| if ( '_og_video' === $type ) { | ||
| if ( ! isset( $data['_embeds'] ) ) { | ||
| $data['_embeds'] = array(); | ||
| } | ||
| if ( ! in_array( $value, $data['_embeds'], true ) ) { | ||
| $data['_embeds'][] = $value; | ||
| } | ||
| } else { | ||
| $data[ $type ][] = $value; |
Comment on lines
+873
to
+875
| $this->inline_data_mode = true; | ||
| } | ||
| } |
Comment on lines
+347
to
+357
| // Popup blocked (common on mobile browsers). Navigate current window with inline data. | ||
| // Trim arrays to limit URL length for the fallback path. | ||
| if ( scrapedData._images && scrapedData._images.length > 5 ) { | ||
| scrapedData._images = scrapedData._images.slice( 0, 5 ); | ||
| } | ||
| if ( scrapedData._embeds && scrapedData._embeds.length > 3 ) { | ||
| scrapedData._embeds = scrapedData._embeds.slice( 0, 3 ); | ||
| } | ||
|
|
||
| top.location.href = pt_url + '&_data=' + encURI( JSON.stringify( scrapedData ) ); | ||
| } |
Comment on lines
+185
to
+190
| // Skip if inline data mode — data was passed via URL, not postMessage. | ||
| if ( | ||
| ! data.postMessageMode || | ||
| data.inlineDataMode || | ||
| postMessageReceived | ||
| ) { |
- Respect enable_press_this_media_discovery filter for inline data path - Build minimal fallback payload (only used meta keys, canonical/shortlink) with 7500-char URL cap to avoid browser truncation - Override pm=0 in fallback URL so app doesn't wait for postMessage - Strip _data param from browser history via replaceState Fixes #50
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
window.open()fails (common on mobile browsers like Firefox Mobile/Fenix), falls back to navigating the current tab with scraped data encoded as JSON in a_dataURL parameterlimit_*methods used for POST datapmflag overridden to0in fallback URL so the app doesn't wait for postMessage data that will never arrive_dataparam stripped from browser history viareplaceStateto avoid leaking scraped contentenable_press_this_media_discoveryfilter, matching the POST data pathCompatibility note
PR #90 (HTML selection capture) touches the same files. When both merge, the second will need:
bookmarklet.min.jssel_htmlto the inline data field map in PHP so HTML selections work in the fallback path tooTest plan
_dataparam parsing, non-override of existing params, invalid JSON handlingpopup = nullin bookmarklet.js, verify current-tab navigation with_dataparam loads editor with scraped content_datais stripped from the URL bar after the app loads in fallback modeFixes #50