mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-27 18:52:14 +03:00
🐛 Fixed pasting newlines in post titles (#15794)
fixes https://github.com/TryGhost/Team/issues/2193 - When pasting a title with a newline, we now trim the string and clear newslines before pasting. - When sending the slug to the backend to generate a unique slug, we now sluggify it in the frontend before adding it to the URL to prevent issues with unsupported characters (causing possible routing problems in Pro).
This commit is contained in:
parent
23c29d0674
commit
7c3d75ade7
@ -32,6 +32,7 @@
|
||||
{{on "blur" (fn (mut this.titleIsFocused) false)}}
|
||||
{{on "mouseover" (fn (mut this.titleIsHovered) true)}}
|
||||
{{on "mouseleave" (fn (mut this.titleIsHovered) false)}}
|
||||
{{on "paste" this.cleanPastedTitle}}
|
||||
data-test-editor-title-input={{true}}
|
||||
/>
|
||||
|
||||
@ -61,4 +62,4 @@
|
||||
@postType={{@postType}}
|
||||
/> --}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -56,6 +56,20 @@ export default class GhKoenigEditorReactComponent extends Component {
|
||||
this.args.onTitleChange?.(event.target.value);
|
||||
}
|
||||
|
||||
@action
|
||||
cleanPastedTitle(event) {
|
||||
const pastedText = (event.clipboardData || window.clipboardData).getData('text');
|
||||
|
||||
if (!pastedText) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const cleanValue = pastedText.replace(/(\n|\r)+/g, ' ').trim();
|
||||
document.execCommand('insertText', false, cleanValue);
|
||||
}
|
||||
|
||||
@action
|
||||
focusTitle() {
|
||||
this.titleElement.focus();
|
||||
|
@ -32,6 +32,7 @@
|
||||
{{on "blur" (fn (mut this.titleIsFocused) false)}}
|
||||
{{on "mouseover" (fn (mut this.titleIsHovered) true)}}
|
||||
{{on "mouseleave" (fn (mut this.titleIsHovered) false)}}
|
||||
{{on "paste" this.cleanPastedTitle}}
|
||||
data-test-editor-title-input={{true}}
|
||||
/>
|
||||
|
||||
@ -56,4 +57,4 @@
|
||||
@postType={{@postType}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -43,6 +43,20 @@ export default class GhKoenigEditorComponent extends Component {
|
||||
this.args.onTitleChange?.(event.target.value);
|
||||
}
|
||||
|
||||
@action
|
||||
cleanPastedTitle(event) {
|
||||
const pastedText = (event.clipboardData || window.clipboardData).getData('text');
|
||||
|
||||
if (!pastedText) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
const cleanValue = pastedText.replace(/(\n|\r)+/g, ' ').trim();
|
||||
document.execCommand('insertText', false, cleanValue);
|
||||
}
|
||||
|
||||
@action
|
||||
focusTitle() {
|
||||
this.titleElement.focus();
|
||||
|
@ -1,6 +1,7 @@
|
||||
import RSVP from 'rsvp';
|
||||
import Service, {inject as service} from '@ember/service';
|
||||
import classic from 'ember-classic-decorator';
|
||||
import {slugify} from '@tryghost/string';
|
||||
|
||||
const {resolve} = RSVP;
|
||||
|
||||
@ -16,7 +17,8 @@ export default class SlugGeneratorService extends Service {
|
||||
return resolve('');
|
||||
}
|
||||
|
||||
url = this.get('ghostPaths.url').api('slugs', slugType, encodeURIComponent(textToSlugify));
|
||||
// We already do a partial slugify at the client side to prevent issues with Pro returning a 404 page because of invalid (encoded) characters (a newline, %0A, for example)
|
||||
url = this.get('ghostPaths.url').api('slugs', slugType, encodeURIComponent(slugify(textToSlugify)));
|
||||
|
||||
return this.ajax.request(url).then((response) => {
|
||||
let [firstSlug] = response.slugs;
|
||||
|
@ -42,7 +42,7 @@ describe('Integration: Service: slug-generator', function () {
|
||||
|
||||
it('calls correct endpoint and returns correct data', function (done) {
|
||||
let rawSlug = 'a test post';
|
||||
stubSlugEndpoint(server, 'post', rawSlug);
|
||||
stubSlugEndpoint(server, 'post', 'a-test-post');
|
||||
|
||||
let service = this.owner.lookup('service:slug-generator');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user