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

Cover block upload completion processor #11541

Merged
merged 32 commits into from
Apr 22, 2020
Merged

Conversation

mkevins
Copy link
Contributor

@mkevins mkevins commented Mar 27, 2020

Fixes: wordpress-mobile/gutenberg-mobile#1739

Description

This PR implements the upload completion processor for the Cover block.

Related PRs:

To test:

Unit tests:

Run all unit tests in WordPress/src/test/java/org/wordpress/android/ui/posts/mediauploadcompletionprocessors/

Manual tests:
  • Close/Re-open post with an ongoing image upload - steps
  • Close post with an ongoing image upload - steps

PR submission checklist:

  • I have considered adding unit tests where possible.
  • 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.

@mkevins mkevins added Media Gutenberg Editing and display of Gutenberg blocks. gutenberg-mobile labels Mar 27, 2020
@peril-wordpress-mobile
Copy link

peril-wordpress-mobile bot commented Mar 27, 2020

Warnings
⚠️ PR is not assigned to a milestone.
⚠️ PR has more than 500 lines of code changing. Consider splitting into smaller PRs if possible.

Generated by 🚫 dangerJS

@peril-wordpress-mobile
Copy link

peril-wordpress-mobile bot commented Mar 27, 2020

You can test the changes on this Pull Request by downloading the APK here.

@peril-wordpress-mobile
Copy link

peril-wordpress-mobile bot commented Apr 7, 2020

You can trigger optional UI/connected tests for these changes by visiting CircleCI here.

@mkevins mkevins changed the title [Testing] Enable cover block uploads behind dev flag Cover block upload completion processor Apr 7, 2020
private static final Pattern PATTERN_COVER_INNER = Pattern.compile(new StringBuilder()
.append("(^.*?<div class=\"wp-block-cover__inner-container\">\\s*)")
.append("(.*)") // inner block contents
.append("(\\s*</div>\\s*</div>\\s*<!-- /wp:cover -->.*)").toString(), Pattern.DOTALL);
Copy link

Choose a reason for hiding this comment

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

oops. I had left a comment here that was wrong. you can take some inspiration from hpq which @aduth wrote. something like jsoup (random internet search) could automate the inference of the block attributes as defined in the block implementation, rather than falling back to attempts at parsing hTML with RegExp

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @dmsnell 👋 😃 , thanks for taking a look at this one. I'm using jsoup already, which is really helpful. IIRC, I encountered some minor differences in output in certain scenarios, possible because it parses to an AST and not a parse tree, however, it is probably worth revisiting, as the variations might still be acceptable to pass validation. 👍

Copy link

Choose a reason for hiding this comment

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

I encountered some minor differences in output in certain scenarios, possible because it parses to an AST and not a parse tree

Do you remember what those differences were? Any difference would have to be a bug since we're dealing with HTML/CSS selectors…

Copy link

Choose a reason for hiding this comment

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

also it looks like this entire pattern shouldn't be necessary if we process the inner blocks using a spec-compliant parser

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you remember what those differences were? Any difference would have to be a bug

Off-hand, I recall that jsoup was adding closing tags, which was problematic during at least one of the iterations toward the current implementation. It's likely this is resolved now, as the implementation no longer processes units of non-self-contained HTML, so probably worth revisiting. To be sure, this was not a bug in jsoup, but rather a limitation in a particular iteration of this implementation, in that it required serialization of the parse tree, while jsoup is designed to serialize abstract trees.

also it looks like this entire pattern shouldn't be necessary if we process the inner blocks using a spec-compliant parser

Indeed, using a spec-compliant parser would obviate the need for this, as we'd be able to handle inner blocks an a much more general way, albeit for all block types.

@mkevins mkevins requested a review from chipsnyder April 10, 2020 11:59
@mkevins mkevins marked this pull request as ready for review April 10, 2020 12:00
* @return A string containing content with ids and urls replaced
*/
String processInnerBlock(String block) {
return block;
Copy link

Choose a reason for hiding this comment

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

Is there a reason to not make the default processor process inner blocks? It will come surprisingly often that the blocks we care about are nested, for example, when people build with the full-site-editing layout blocks, or the Group block, or the Quote block, or the Gallery block…

Copy link
Contributor Author

@mkevins mkevins Apr 13, 2020

Choose a reason for hiding this comment

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

Is there a reason to not make the default processor process inner blocks?

For the current implementation of the processors, they are not full-blown parsers, but part of their behavior resembles a parser. Instead, the processors are only concerned with a subset of block types (image, video, etc.). To hopefully clarify: when processContent encounters a Group block, it does not match on that block, but if that block's inner contents contains a media-containing block, that will match and be processed further (via processBlock), while all content preceeding that match is treated as a raw string. This is a way to produce the desired output without the need to implement any serialization logic for all potential block types.

/**
* Pattern to match background-image url in cover block html content
*/
private static final Pattern PATTERN_BACKGROUND_IMAGE_URL = Pattern.compile("background-image:url\\([^\\)]+\\)");
Copy link

Choose a reason for hiding this comment

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

so definitely there's an issue with blocks defining their attributes in the "JSON attributes" vs. inside HTML, but instead of hard-coding a string-matching pattern we can go back to jsoup as you were doing and hard-code the known attribute definition, which would then end up looking like this…

JSONAttribute backgroundImageUrl = new JSONAttribute("url", JSONAttribute.String);

I'm sure there's a million ways to do this. The main point I was trying to make is that we can rely on the structural form of the data instead of processing the HTML string as if it were plain text. It's quite possible to have background-image:url inside the block in a way that isn't meant to indicate a different background, and this string-matching might end up paving a road of headaches to debug 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's quite possible to have background-image:url inside the block in a way that isn't meant to indicate a different background, and this string-matching might end up paving a road of headaches to debug

Ah, indeed! I wonder if there is a misunderstanding about how this pattern is currently used. This only matches on the style attribute within the parsed HTML of a matching block, and so the string replacement is restricted to that particular inline style. In other words, it will not replace similar text within the content of HTML (e.g. a caption, a paragraph, etc.). Perhaps the Javadoc could be made more specific.

// replace background-image url in style attribute
String style = PATTERN_BACKGROUND_IMAGE_URL.matcher(targetDiv.attr("style"))
.replaceFirst(String.format("background-image:url(%1$s)", mRemoteUrl));
targetDiv.attr("style", style);
Copy link

Choose a reason for hiding this comment

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

hm…I'm seeing the cover block actually store the background imagine inside the JSON attributes. this will deifnitely update the style, but won't the newly-uploaded image get wiped out after someone loads the post in the editor again and there's a mismatch between what the attributes indicate and what HTML has been generated?

we probably need to update both places.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we probably need to update both places

The Json attributes are updated in an earlier step via the abstract method processBlockJsonAttributes. For Cover block, the id is used to check for a match first, and the url is mutated a match with the local id is found. The replacement within the style attribute only occurs subsequently, if that condition is met.

Copy link
Contributor

@chipsnyder chipsnyder left a comment

Choose a reason for hiding this comment

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

LGTM! Everything was working as expected. Nice work!

  • ✅ Close/Re-open post with an ongoing image upload - steps
  • ✅ Close post with an ongoing image upload - steps

@pinarol
Copy link
Contributor

pinarol commented Apr 17, 2020

Friendly reminder: We should merge into gutenberg/after_1.26.0 instead of develop until Monday. After Monday we can target develop again.

Copy link
Contributor

@chipsnyder chipsnyder left a comment

Choose a reason for hiding this comment

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

Reran some test cases and took a look at the changes. Nice catch! Looks good 🥳

@mkevins
Copy link
Contributor Author

mkevins commented Apr 22, 2020

Thanks for reviewing and testing 👍 .

@mkevins mkevins merged commit b3d296e into develop Apr 22, 2020
@mkevins mkevins deleted the feature/cover-block-uploads branch April 22, 2020 07:28
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. Media
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cover block: Allow uploading image
4 participants