-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Fix empty link preview after creating link from empty selection #58863
Conversation
} else if ( newText === richTextText ) { | ||
newValue = applyFormat( value, linkFormat ); | ||
} else { | ||
// Scenario: we have any active text selection or an active format. | ||
let newValue; | ||
|
||
if ( newText === richTextText ) { | ||
// If we're not updating the text then ignore. | ||
newValue = applyFormat( value, linkFormat ); | ||
} else { | ||
// Create new RichText value for the new text in order that we | ||
// can apply formats to it. | ||
newValue = create( { text: newText } ); | ||
|
||
// Apply the new Link format to this new text value. | ||
newValue = applyFormat( | ||
newValue, | ||
linkFormat, | ||
0, | ||
newText.length | ||
); | ||
|
||
// Get the boundaries of the active link format. | ||
const boundary = getFormatBoundary( value, { | ||
type: 'core/link', | ||
} ); | ||
|
||
// Split the value at the start of the active link format. | ||
// Passing "start" as the 3rd parameter is required to ensure | ||
// the second half of the split value is split at the format's | ||
// start boundary and avoids relying on the value's "end" property | ||
// which may not correspond correctly. | ||
const [ valBefore, valAfter ] = split( | ||
value, | ||
boundary.start, | ||
boundary.start | ||
); | ||
|
||
// Update the original (full) RichTextValue replacing the | ||
// target text with the *new* RichTextValue containing: | ||
// 1. The new text content. | ||
// 2. The new link format. | ||
// As "replace" will operate on the first match only, it is | ||
// run only against the second half of the value which was | ||
// split at the active format's boundary. This avoids a bug | ||
// with incorrectly targetted replacements. | ||
// See: https://github.com/WordPress/gutenberg/issues/41771. | ||
// Note original formats will be lost when applying this change. | ||
// That is expected behaviour. | ||
// See: https://github.com/WordPress/gutenberg/pull/33849#issuecomment-936134179. | ||
const newValAfter = replace( valAfter, richTextText, newValue ); | ||
|
||
newValue = concat( valBefore, newValAfter ); | ||
} | ||
|
||
onChange( newValue ); | ||
// Scenario: Editing an existing link. | ||
|
||
// Create new RichText value for the new text in order that we | ||
// can apply formats to it. | ||
newValue = create( { text: newText } ); | ||
// Apply the new Link format to this new text value. | ||
newValue = applyFormat( newValue, linkFormat, 0, newText.length ); | ||
|
||
// Get the boundaries of the active link format. | ||
const boundary = getFormatBoundary( value, { | ||
type: 'core/link', | ||
} ); | ||
|
||
// Split the value at the start of the active link format. | ||
// Passing "start" as the 3rd parameter is required to ensure | ||
// the second half of the split value is split at the format's | ||
// start boundary and avoids relying on the value's "end" property | ||
// which may not correspond correctly. | ||
const [ valBefore, valAfter ] = split( | ||
value, | ||
boundary.start, | ||
boundary.start | ||
); | ||
|
||
// Update the original (full) RichTextValue replacing the | ||
// target text with the *new* RichTextValue containing: | ||
// 1. The new text content. | ||
// 2. The new link format. | ||
// As "replace" will operate on the first match only, it is | ||
// run only against the second half of the value which was | ||
// split at the active format's boundary. This avoids a bug | ||
// with incorrectly targetted replacements. | ||
// See: https://github.com/WordPress/gutenberg/issues/41771. | ||
// Note original formats will be lost when applying this change. | ||
// That is expected behaviour. | ||
// See: https://github.com/WordPress/gutenberg/pull/33849#issuecomment-936134179. | ||
const newValAfter = replace( valAfter, richTextText, newValue ); | ||
|
||
newValue = concat( valBefore, newValAfter ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not change any of these lines. The linter was complaining about the if / else / if / else, so I switched the format.
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Size Change: +5 B (0%) Total Size: 1.71 MB
ℹ️ View Unchanged
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this PR better than mine because the code and solution makes more sense by comparison - in my PR the solution is way more fragile and unexpected and hides the problem for later. This PR solves the bug correctly 👏🏻
However I like the UX in my PR, whereas the UI is closed and the user can continue to write immediately after inserting the link.
0, | ||
newText.length | ||
value.start, | ||
value.end + newText.length |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't start and end same if isCollapsed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it should be 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, they are the same. Not sure why I did it that way. Probably clearer to use value.start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me
What?
When creating a link from an empty selection, the link control popover would say there's no link. This sets the correct active link.
Why?
Bug fix.
How?
We need to apply the active format in order to have an active link, which applyFormat handles. Previously, the formats were applied, and then inserted, so it would remove all the active formats. By inserting, and then applying formats, we can set the correct active format.
Testing Instructions
Screenshots or screencast