Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Gutenberg content parser to use in block processors #22886

Merged
merged 10 commits into from May 14, 2024

Conversation

fluiddot
Copy link
Contributor

@fluiddot fluiddot commented Mar 21, 2024

Related to wordpress-mobile/gutenberg-mobile#6696.

To test:

Note

This functionality will be tested on separate PRs where some block processors are using it.

  • Observe that all CI jobs succeed.

Regression Notes

  1. Potential unintended areas of impact
    N/A

  2. What I did to test those areas of impact (or what existing automated tests I relied on)
    N/A

  3. What automated tests I added (or what prevented me from doing so)
    N/A

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding unit tests for my changes.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

Testing checklist:

  • WordPress.com sites and self-hosted Jetpack sites.
  • Portrait and landscape orientations.
  • Light and dark modes.
  • Fonts: Larger, smaller and bold text.
  • High contrast.
  • VoiceOver.
  • Languages with large words or with letters/accents not frequently used in English.
  • Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)
  • iPhone and iPad.
  • Multi-tasking: Split view and Slide over. (iPad)

@fluiddot fluiddot added [Type] Enhancement Gutenberg Editing and display of Gutenberg blocks. labels Mar 21, 2024
@fluiddot fluiddot added this to the 24.6 milestone Mar 21, 2024
@wpmobilebot
Copy link
Contributor

wpmobilebot commented Mar 21, 2024

WordPress Alpha📲 You can test the changes from this Pull Request in WordPress Alpha by scanning the QR code below to install the corresponding build.
App NameWordPress Alpha WordPress Alpha
ConfigurationRelease-Alpha
Build Numberpr22886-3a0894c
Version24.9
Bundle IDorg.wordpress.alpha
Commit3a0894c
App Center BuildWPiOS - One-Offs #9898
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Mar 21, 2024

Jetpack Alpha📲 You can test the changes from this Pull Request in Jetpack Alpha by scanning the QR code below to install the corresponding build.
App NameJetpack Alpha Jetpack Alpha
ConfigurationRelease-Alpha
Build Numberpr22886-3a0894c
Version24.9
Bundle IDcom.jetpack.alpha
Commit3a0894c
App Center Buildjetpack-installable-builds #8947
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

public var comment: SwiftSoup.Comment
public var elements: Elements
public var blocks: [GutenbergParsedBlock]
public weak var parentBlock: GutenbergParsedBlock?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parentBlock is treated as a weak reference because the parent block also references this block via its blocks property. This will facilitate the automated deallocation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The library SwiftSoup is added via the Swift Package Manager. But we could also include it as a Pod.

}
}

private var comment: SwiftSoup.Comment
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type includes SwiftSoup to avoid conflicts with the CoreData model Comment.

@irfano
Copy link
Member

irfano commented Apr 1, 2024

I'm moving this to the next milestone since this is not a blocker, and the code freeze will be completed today.

@irfano irfano modified the milestones: 24.6, 24.7 Apr 1, 2024
@twstokes twstokes self-requested a review April 3, 2024 18:27
@twstokes
Copy link
Contributor

twstokes commented Apr 9, 2024

👋 @fluiddot - No rush on this, but I wanted to ask:

Did you evaluate what it'd take to put the processor(s) in the Mobile Gutenberg package versus the iOS app codebase? Is there something that makes the content parsers unique to the WordPress app, versus the Gutenberg project? Thanks!

@fluiddot
Copy link
Contributor Author

Did you evaluate what it'd take to put the processor(s) in the Mobile Gutenberg package versus the iOS app codebase?

Nope, I haven't explored what would be needed for moving these files to the Gutenberg Mobile package. There are several parts of the editor implemented in the client like this one that I agree seem to have a better fit in the Gutenberg Mobile. Ideally, the Gutenberg Mobile package should provide all the functionality to use the editor in any app, but the reality is that Gutenberg Mobile is quite coupled to the WP/JP app code.

Is there something that makes the content parsers unique to the WordPress app, versus the Gutenberg project?

Part of the logic is related to Gutenberg, as the structure of blocks is defined by the editor. However, there's a bit of overlap in the processing because the need of the processors is due to updating media attributes that are defined by the client. As an example, an Image block needs to be updated with the server media ID, and the media structure is defined in the WP/JP apps.

In the future, it would be great if we identify which parts should be provided by Gutenberg Mobile and which ones should be delegated to the client. However, currently, this separation is a bit blurry.

@twstokes
Copy link
Contributor

Makes sense @fluiddot, and certainly something we could defer to the future. 👍

@momo-ozawa momo-ozawa modified the milestones: 24.7, 24.8 Apr 15, 2024
@momo-ozawa
Copy link
Contributor

momo-ozawa commented Apr 15, 2024

👋 Hey @fluiddot, I'm bumping this PR to 24.8 since it's code freeze day. If this PR needs to target 24.7, please target the release branch once it's been cut. Thanks!

@kean
Copy link
Contributor

kean commented Apr 25, 2024

Did you evaluate what it'd take to put the processor(s) in the Mobile Gutenberg package versus the iOS app codebase?

There is a good reason for consolidating this code in Gutenberg. The app and the editor produce different results when handling uploads.

Here's an example of PostCoordinator using its logic:

<!-- wp:image {\"id\":1431,\"sizeSlug\":\"large\"} -->
  <figure class=\"wp-block-image size-large\">
    <img src=\"https://alextest41234.files.wordpress.com/2024/04/img_0005-2-1.jpg?w=1024\"  class=\"wp-image-1431\"/>
  </figure>
<!-- /wp:image -->

And here's Gutenberg:

<!-- wp:image {\"id\":1431,\"sizeSlug\":\"large\"} -->
  <figure class=\"wp-block-image size-large\">
    <img src=\"https://alextest41234.files.wordpress.com/2024/04/img_0005-2-1.jpg?w=1024\" alt=\"\"
class=\"wp-image-1431\"/>
  </figure>
<!-- /wp:image -->

Notice an alt tag. It leads to situation where the app thinks there are changes to the post when the are none. Discussion here: p1714049179672299/1714047410.810349-slack-C06GRKUGDNX.

re: performance

To address the performance issues, I recommend moving this code to the background. I can make this change in the scope of the current project since I'm working in this area.

@fluiddot
Copy link
Contributor Author

There is a good reason for consolidating this code in Gutenberg. The app and the editor produce different results when handling uploads.

Here's an example of PostCoordinator using its logic:

<!-- wp:image {\"id\":1431,\"sizeSlug\":\"large\"} -->
  <figure class=\"wp-block-image size-large\">
    <img src=\"https://alextest41234.files.wordpress.com/2024/04/img_0005-2-1.jpg?w=1024\"  class=\"wp-image-1431\"/>
  </figure>
<!-- /wp:image -->

And here's Gutenberg:

<!-- wp:image {\"id\":1431,\"sizeSlug\":\"large\"} -->
  <figure class=\"wp-block-image size-large\">
    <img src=\"https://alextest41234.files.wordpress.com/2024/04/img_0005-2-1.jpg?w=1024\" alt=\"\"
class=\"wp-image-1431\"/>
  </figure>
<!-- /wp:image -->

Notice an alt tag. It leads to situation where the app thinks there are changes to the post when the are none. Discussion here: p1714049179672299/1714047410.810349-slack-C06GRKUGDNX.

I agree that consolidating the block processors within the Gutenberg Mobile project could be beneficial. However, I don't believe it will directly address the core issue. The main challenge stems from the fact that the logic for generating the block's markup resides on the JavaScript side (Gutenberg). Currently, the block processors are detached from Gutenberg, requiring them to stay updated with the logic of each block. Given that this is a manual process, discrepancies, as you highlighted @kean, can arise. While finding a method to synchronize the block processors with Gutenberg's logic would be ideal, I anticipate it would introduce considerable complexity.

To address the performance issues, I recommend moving this code to the background. I can make this change in the scope of the current project since I'm working in this area.

Please correct me if I'm mistaken, but even if we move the code to the background, the post-saving process will still be time-consuming due to the required processing. Is that correct?

@kean
Copy link
Contributor

kean commented Apr 25, 2024

Please correct me if I'm mistaken, but even if we move the code to the background, the post-saving process will still be time-consuming due to the required processing. Is that correct?

"30 media items: 5.250 seconds" – oh, I didn't know we we talking seconds 😨
I assumed it was just micro main thread hangs.

@kean
Copy link
Contributor

kean commented Apr 25, 2024

While finding a method to synchronize the block processors with Gutenberg's logic would be ideal, I anticipate it would introduce considerable complexity.

There is one more variable: the server. I noticed that it modifies the content before saving. For example, it might end up removing redundant spaces between tag attributes. So, it's really hard to get a canonical representation of a post.

generating the block's markup resides on the JavaScript side (Gutenberg)

An app can call JavaScript directly with little overhead.

@fluiddot
Copy link
Contributor Author

There is one more variable: the server. I noticed that it modifies the content before saving. For example, it might end up removing redundant spaces between tag attributes. So, it's really hard to get a canonical representation of a post.

Good point. That's definitely another factor to take into account. Usually, when changes are made to a block (either in the frontend or the backend) they are updated in the same Gutenberg version. In most cases, those changes are also made in the mobile native version (i.e. Gutenberg Mobile). However, the web version doesn't have the same concept of block processors that are run outside the context of the editor, like the case of the app. Hence, in case we consolidate them in the Gutenberg repo, it will take time for Gutenberg contributors to be aware of the need to update them.

An app can call JavaScript directly with little overhead.

True. We could consider a potential workaround where the block processor resides on the JavaScript side and imports the necessary code from Gutenberg to process the block. It's worth noting that, as far as I know, such an approach doesn't currently exist, so it would require building it from scratch.

@kean
Copy link
Contributor

kean commented Apr 25, 2024

@fluiddot, I extracted the processors and moved the work to the background thread #23093. This code will only run for a small fraction of the users eligible to test the "Offline Mode" changes.

@@ -64,6 +64,15 @@
"version": "0.2.3"
}
},
{
"package": "SwiftSoup",
"repositoryURL": "https://github.com/scinfu/SwiftSoup.git",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size of the dependency is a bit concerning:

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Swift                           58           1709           3707          10315

It should not affect incremental builds, I think it's something to be considered.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest considering wrapping https://developer.wordpress.org/block-editor/reference-guides/packages/packages-blocks/ and other related WordPress JS APIs in Objective-C and invoking them using JavaScriptCore. This way, we'll be able to reuse the existing parser. You can run Javascript in background on iOS to ensure that processing doesn't take a lot of time.

A native package that would wrap the existing JS packages could be useful for more scenarios than this. For example, the app could use it for addressing the "dangling" media uploads issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size of the dependency is a bit concerning:
[...]
It should not affect incremental builds, I think it's something to be considered.

I haven't checked how much this library increases the binary. If it's significant we might consider other libraries.

I would suggest considering wrapping https://developer.wordpress.org/block-editor/reference-guides/packages/packages-blocks/ and other related WordPress JS APIs in Objective-C and invoking them using JavaScriptCore. This way, we'll be able to reuse the existing parser. You can run Javascript in background on iOS to ensure that processing doesn't take a lot of time.

A native package that would wrap the existing JS packages could be useful for more scenarios than this. For example, the app could use it for addressing the "dangling" media uploads issue.

This approach is intriguing and would certainly ensure consistent results when processing a block compared to Gutenberg. As a long-term solution, I'd advocate exploring this approach. However, I believe it would entail significant complexity in implementation, particularly regarding how to bundle the necessary code and potential tweaks to the Gutenberg code. @kean not sure if with your comment you're proposing following this instead of the refactor implemented in this PR. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your comment you're proposing following this instead of the refactor implemented in this PR. WDYT?

It's more long-term. I worked with JS-based packages before, so I know it should be feasible, but I don't know how much effort it would take.

particularly regarding how to bundle the necessary code

These packages are already part of the Gutenberg-mobile project, aren't they?

Copy link
Contributor Author

@fluiddot fluiddot Apr 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These packages are already part of the Gutenberg-mobile project, aren't they?

Yes, but we bundled them with Metro and files are compiled with Hermes (the setup for React Native). I presume the output of this setup won't be supported natively. We'd need to generate a new bundle compatible with JavaScriptCore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The app doesn't need to use these JS files directly. It could part of the existing Gutenberg framework.

@dvdchr dvdchr modified the milestones: 24.8, 24.9 Apr 29, 2024
@dvdchr
Copy link
Contributor

dvdchr commented Apr 29, 2024

Hi @fluiddot 👋 , I'm bumping this PR's milestone to 24.9 since I'm starting code freeze. Feel free to re-target this to the release branch if this is a blocker or intended for 24.8.

@salimbraksa
Copy link
Contributor

Hey @fluiddot, I'm bumping the milestone for this PR to 25.0 as I'm starting the code freeze. If this PR needs to go into 24.9, please go ahead and re-target it to the release branch.

Copy link
Contributor

@twstokes twstokes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM @fluiddot! Sorry for the delay. I'm getting the branch caught up with trunk and letting CI run. If we're all green then I'll merge. Thanks for the hard work! 🚀

@twstokes twstokes merged commit 20d87aa into trunk May 14, 2024
24 checks passed
@twstokes twstokes deleted the add/gutenberg-content-parsing branch May 14, 2024 19:50
@@ -48,6 +48,7 @@
* [**] Block editor: Highlight text fixes [https://github.com/WordPress/gutenberg/pull/57650]
* [*] [Jetpack-only] Stats: Eliminated common error causes in the Insights tab. [#22890]
* [*] [Jetpack-only] Reader: Fix displaying stale site information [#22885]
* [*] [internal] Incorporate a parser to handle Gutenberg blocks more efficiently for improved performance [#22886]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems this entry landed in the wrong section, I'll update it in another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Gutenberg Editing and display of Gutenberg blocks. [Type] Enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants