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

Create the proper shortcode on paste #21864

Merged
merged 4 commits into from
Apr 29, 2020
Merged

Create the proper shortcode on paste #21864

merged 4 commits into from
Apr 29, 2020

Conversation

oandregal
Copy link
Member

@oandregal oandregal commented Apr 24, 2020

Fixes #21103

How to test

  • Create a new post
  • Paste the following into a paragraph block: [gallery ids="13,12,14"] (change these ids for ids of elements in your media library).
  • Expected result is that a gallery block should be created.

@oandregal oandregal self-assigned this Apr 24, 2020
@oandregal oandregal added [Feature] Paste [Type] Bug An existing feature does not function as intended labels Apr 24, 2020
@github-actions
Copy link

github-actions bot commented Apr 24, 2020

Size Change: -28.5 kB (3%)

Total Size: 816 kB

Filename Size Change
build/annotations/index.js 3.62 kB +3 B (0%)
build/api-fetch/index.js 4.08 kB +3 B (0%)
build/autop/index.js 2.82 kB -3 B (0%)
build/block-directory/index.js 6.23 kB -7 B (0%)
build/block-editor/index.js 106 kB +529 B (0%)
build/block-editor/style-rtl.css 10.2 kB +158 B (1%)
build/block-editor/style.css 10.2 kB +159 B (1%)
build/block-library/editor-rtl.css 7.03 kB -24 B (0%)
build/block-library/editor.css 7.03 kB -24 B (0%)
build/block-library/index.js 114 kB +1.36 kB (1%)
build/block-library/style-rtl.css 7.14 kB +3 B (0%)
build/block-library/style.css 7.14 kB +2 B (0%)
build/block-serialization-default-parser/index.js 1.88 kB +1 B
build/block-serialization-spec-parser/index.js 3.1 kB -1 B
build/blocks/index.js 48.1 kB -9.58 kB (19%) 👏
build/components/index.js 179 kB -18.9 kB (10%) 👏
build/components/style-rtl.css 16.9 kB -8 B (0%)
build/components/style.css 16.9 kB -8 B (0%)
build/compose/index.js 6.66 kB +3 B (0%)
build/core-data/index.js 11.4 kB +11 B (0%)
build/data/index.js 8.44 kB +7 B (0%)
build/date/index.js 5.47 kB +3 B (0%)
build/dom-ready/index.js 568 B -1 B
build/edit-navigation/index.js 3.54 kB -2 B (0%)
build/edit-post/index.js 27.6 kB -592 B (2%)
build/edit-post/style-rtl.css 12.2 kB -286 B (2%)
build/edit-post/style.css 12.2 kB -287 B (2%)
build/edit-site/index.js 10.9 kB +83 B (0%)
build/edit-site/style-rtl.css 5.11 kB -132 B (2%)
build/edit-site/style.css 5.11 kB -131 B (2%)
build/edit-widgets/index.js 7.5 kB -837 B (11%) 👏
build/edit-widgets/style-rtl.css 4.67 kB -339 B (7%)
build/edit-widgets/style.css 4.66 kB -342 B (7%)
build/editor/index.js 43.6 kB +279 B (0%)
build/element/index.js 4.65 kB -2 B (0%)
build/format-library/index.js 7.63 kB +314 B (4%)
build/i18n/index.js 3.56 kB +1 B
build/is-shallow-equal/index.js 710 B -1 B
build/keyboard-shortcuts/index.js 2.51 kB -2 B (0%)
build/list-reusable-blocks/index.js 3.12 kB +2 B (0%)
build/media-utils/index.js 5.29 kB +3 B (0%)
build/notices/index.js 1.79 kB +1 B
build/nux/index.js 3.4 kB -3 B (0%)
build/plugins/index.js 2.67 kB -1 B
build/primitives/index.js 1.5 kB +7 B (0%)
build/redux-routine/index.js 2.85 kB +8 B (0%)
build/rich-text/index.js 14.8 kB +9 B (0%)
build/server-side-render/index.js 2.68 kB +6 B (0%)
build/url/index.js 4.02 kB +2 B (0%)
build/viewport/index.js 1.84 kB +1 B
build/warning/index.js 1.14 kB -1 B
build/wordcount/index.js 1.18 kB +2 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.02 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/style-rtl.css 760 B 0 B
build/block-directory/style.css 761 B 0 B
build/block-library/theme-rtl.css 683 B 0 B
build/block-library/theme.css 685 B 0 B
build/data-controls/index.js 1.29 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom/index.js 3.1 kB 0 B
build/edit-navigation/style-rtl.css 485 B 0 B
build/edit-navigation/style.css 485 B 0 B
build/editor/editor-styles-rtl.css 428 B 0 B
build/editor/editor-styles.css 431 B 0 B
build/editor/style-rtl.css 3.27 kB 0 B
build/editor/style.css 3.27 kB 0 B
build/escape-html/index.js 733 B 0 B
build/format-library/style-rtl.css 502 B 0 B
build/format-library/style.css 502 B 0 B
build/hooks/index.js 2.13 kB 0 B
build/html-entities/index.js 622 B 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/style-rtl.css 226 B 0 B
build/list-reusable-blocks/style.css 226 B 0 B
build/nux/style-rtl.css 616 B 0 B
build/nux/style.css 613 B 0 B
build/priority-queue/index.js 789 B 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.28 kB 0 B

compressed-size-action

const pieces = shortcodeConverter( HTML );

// The call to shortcodeConverter will always return more than one element
// if shortcodes are matched. The reason is when shortcodes are matched
// empty HTML strings are included.
const hasShortcodes = pieces.length > 1;

if ( mode === 'INLINE' && ! hasShortcodes ) {
Copy link
Member Author

Choose a reason for hiding this comment

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

It seems to me that this should be fine because shortcodes are converted to blocks, which can't be inline. cc @ellatrix

Copy link
Member Author

@oandregal oandregal Apr 24, 2020

Choose a reason for hiding this comment

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

I've only checked the default shortcodes, though. Perhaps there is some 3rd party shortcode that could be converted into inline formats. However, I don't see that's possible to do right now with the transformations API.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I think it's fine if all the tests pass.

Copy link
Contributor

Choose a reason for hiding this comment

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

I disagree, I think it's fairly important to respect any third-party inline shortcodes. In my experience, the use cases are many and contemplate anything from inline formatting to marking positions in the document. (The question of whether shortcodes remain the right tool is not ours to ask here!)

It seems to me that this should be fine because shortcodes are converted to blocks, which can't be inline

Because even shortcodes that don't have a known associated block type will be picked up by the catch-all Shortcode block, we would be suddenly forcing all shortcodes to be block-like. One could let the editor differentiate between shortcodes with a known block type (which can never be inline) and unknown shortcodes (which may or not be inline), but I'd honestly stay away from implementing that. It would introduce a lot of complexity for little benefit.

Instead, it would be more interesting if the block editor were smart enough to decide when a pasted shortcode is meant to be inline or not. If it is, the editor should abstain from trying to make it a block. Concretely, these are some behaviours to consider:

  1. Start a new line (i.e. a blank Paragraph) and paste a shortcode → Add a block for that shortcode.
  2. Place the caret in the middle of some text and paste a shortcode → Insert the shortcode text verbatim, no new blocks.
  3. Place the caret at the end of a paragraph of text and paste a shortcode → …? (up to us to decide)

@oandregal oandregal added the [Feature] Shortcodes Related to shortcode functionality label Apr 24, 2020
@oandregal
Copy link
Member Author

cc @hrkhal you may be interested in testing this one.

@oandregal oandregal changed the title Prevent content with shortcodes to be pasted inline Create the proper shortcode on paste Apr 27, 2020
@ellatrix
Copy link
Member

Maybe it's good to have @mcsf's opinion as well, since you did some work on this. :)

@oandregal oandregal requested a review from mcsf April 27, 2020 09:53
@mcsf
Copy link
Contributor

mcsf commented Apr 27, 2020

I can't recall: were there specific Puppeteer issues keeping from having e2e tests for pasting? It could be nice to add some.

const pieces = shortcodeConverter( HTML );

// The call to shortcodeConverter will always return more than one element
// if shortcodes are matched. The reason is when shortcodes are matched
// empty HTML strings are included.
const hasShortcodes = pieces.length > 1;

if ( mode === 'INLINE' && ! hasShortcodes ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I disagree, I think it's fairly important to respect any third-party inline shortcodes. In my experience, the use cases are many and contemplate anything from inline formatting to marking positions in the document. (The question of whether shortcodes remain the right tool is not ours to ask here!)

It seems to me that this should be fine because shortcodes are converted to blocks, which can't be inline

Because even shortcodes that don't have a known associated block type will be picked up by the catch-all Shortcode block, we would be suddenly forcing all shortcodes to be block-like. One could let the editor differentiate between shortcodes with a known block type (which can never be inline) and unknown shortcodes (which may or not be inline), but I'd honestly stay away from implementing that. It would introduce a lot of complexity for little benefit.

Instead, it would be more interesting if the block editor were smart enough to decide when a pasted shortcode is meant to be inline or not. If it is, the editor should abstain from trying to make it a block. Concretely, these are some behaviours to consider:

  1. Start a new line (i.e. a blank Paragraph) and paste a shortcode → Add a block for that shortcode.
  2. Place the caret in the middle of some text and paste a shortcode → Insert the shortcode text verbatim, no new blocks.
  3. Place the caret at the end of a paragraph of text and paste a shortcode → …? (up to us to decide)

@oandregal
Copy link
Member Author

@mcsf I've pushed a different approach that implements your suggestion.

I think it's simpler if we left the use case 3 as it is at the moment, otherwise, we may be preventing the use of certain inline shortcodes that may behave like the end of block markers (by virtue of converting them blocks).

@mcsf
Copy link
Contributor

mcsf commented Apr 28, 2020

I think it's simpler if we left the use case 3 as it is at the moment, otherwise, we may be preventing the use of certain inline shortcodes that may behave like the end of block markers (by virtue of converting them blocks).

Yeah, this makes sense.

Copy link
Contributor

@mcsf mcsf left a comment

Choose a reason for hiding this comment

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

Looks good now, thanks for fixing!

@oandregal oandregal merged commit 2676705 into master Apr 29, 2020
@oandregal oandregal deleted the fix/shortcode-paste branch April 29, 2020 07:45
@github-actions github-actions bot added this to the Gutenberg 8.1 milestone Apr 29, 2020
@@ -39,6 +39,7 @@ import {
} from '@wordpress/rich-text';
import deprecated from '@wordpress/deprecated';
import { isURL } from '@wordpress/url';
import { regexp } from '@wordpress/shortcode';
Copy link
Member

Choose a reason for hiding this comment

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

I didn't see this code at the time of approval. I feel like this belongs in the paste handler together with the rest of the short code logic?

Copy link
Member Author

@oandregal oandregal May 4, 2020

Choose a reason for hiding this comment

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

I think code may have changed since your approval and Miguel's. I didn't think of pinging you for your re-approval after Miguel's approved changes, sorry.

However, I don't know how we can move this logic to the paste handler. The trick here is to switch to BLOCKS mode if 1) we're in an empty line and 2) the pasted text is a shortcode. This logic requires knowledge of the rich text value and the pasted content. My thinking was that having this on the rich-text component would make sense as we already do the same for URLs. How does this look? Happy to refactor if another approach is preferred.

Copy link
Member

Choose a reason for hiding this comment

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

Also the dependencies are missing in the package file

Copy link
Member

Choose a reason for hiding this comment

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

Also the dependencies are missing in the package file

Aside: I thought we had an ESLint rule which verified that any referenced dependencies should be listed in package.json 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

Ouch 😞 Here's the fix for the missing dependency #22086

Not sure I've done this before so I may have missed something.

Copy link
Member

Choose a reason for hiding this comment

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

Very strange indeed. It fails locally!

 ⇒ npm run lint-js                                                        

> gutenberg@8.0.0 lint-js /Users/andrew/Documents/Code/gutenberg
> wp-scripts lint-js


/Users/andrew/Documents/Code/gutenberg/packages/block-editor/src/components/rich-text/index.js
  42:1  error  '@wordpress/shortcode' should be listed in the project's dependencies. Run 'npm i -S @wordpress/shortcode' to add it  import/no-extraneous-dependencies

✖ 1 problem (1 error, 0 warnings)

Copy link
Member Author

Choose a reason for hiding this comment

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

The Travis job for this PR didn't report anything neither for all subsequent PRs. Just looked at the logs and there aren't any messages about the failure either (it could be that the exit code was wrong for some reason but the message was there).

I can confirm that npm run lint-js and npm run lint do fail locally on master prior to the merge of #22086 Puzzling.

Copy link
Contributor

Choose a reason for hiding this comment

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

Aside: I thought we had an ESLint rule which verified that any referenced dependencies should be listed in package.json 🤔

Oh, that's unfortunate, I let my guard down too. 😞

I didn't see this code at the time of approval. I feel like this belongs in the paste handler together with the rest of the short code logic?

Perhaps, but there are a lot of symmetries with what we do with pasted URLs and embeds. Whatever we do, we should do for both shortcodes and embeds. Perhaps that means letting pasteHandler choose whether to force mode: 'BLOCKS' when initial mode is 'AUTO'; perhaps that means exposing a utility like inferMode or shouldForceBlocksMode from @wordpress/blocks that RichText can use.

Copy link
Member

Choose a reason for hiding this comment

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

Very strange indeed. It fails locally!

After some more debugging, I think I've figured it out.

Fix (and debugging details) at: #22088

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I don't mind the code, it's something we can always easily change. I was thinking we could also pass empty state to the raw handler. I just thought it might be nice to keep shortcode dependencies in the raw handler since it already depends on it and RichText doesn't. I just noticed the code when I saw the package error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Paste [Feature] Shortcodes Related to shortcode functionality [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Shortcode transforms on paste no longer work
4 participants