FIX: remove fast-edit regex and string replacement (#25496)

This change removes the regex we used previously, which only allowed ASCII characters in fast-edit. Now multi-language content  can be used with fast-edit.

It also removes the string replacement we relied on in the past to catch various forms of punctuation marks, as this no longer appears necessary (possibly since this component was updated to use Glimmer).
This commit is contained in:
David Battersby 2024-01-31 18:26:43 +08:00 committed by GitHub
parent e944468162
commit 52249fad11
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 76 additions and 20 deletions

View File

@ -5,7 +5,6 @@ import { on } from "@ember/modifier";
import { action } from "@ember/object";
import DButton from "discourse/components/d-button";
import PluginOutlet from "discourse/components/plugin-outlet";
import { fixQuotes } from "discourse/components/post-text-selection";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { translateModKey } from "discourse/lib/utilities";
@ -52,10 +51,7 @@ export default class FastEdit extends Component {
try {
const result = await ajax(`/posts/${this.args.post.id}`);
const newRaw = result.raw.replace(
fixQuotes(this.args.initialValue),
fixQuotes(this.value)
);
const newRaw = result.raw.replace(this.args.initialValue, this.value);
await this.args.post.save({ raw: newRaw });
} catch (error) {

View File

@ -31,12 +31,6 @@ function getQuoteTitle(element) {
return titleEl.textContent.trim().replace(/:$/, "");
}
export function fixQuotes(str) {
// u+201c, u+201d = “ ”
// u+2018, u+2019 =
return str.replace(/[\u201C\u201D]/g, '"').replace(/[\u2018\u2019]/g, "'");
}
export default class PostTextSelection extends Component {
@service appEvents;
@service capabilities;
@ -177,14 +171,12 @@ export default class PostTextSelection extends Component {
if (this.canEditPost) {
const regexp = new RegExp(escapeRegExp(quoteState.buffer), "gi");
const matches = cooked.innerHTML.match(regexp);
const non_ascii_regex = /[^\x00-\x7F]/;
if (
quoteState.buffer.length === 0 ||
quoteState.buffer.includes("|") || // tables are too complex
quoteState.buffer.match(/\n/g) || // linebreaks are too complex
matches?.length > 1 || // duplicates are too complex
non_ascii_regex.test(quoteState.buffer) // non-ascii chars break fast-edit
matches?.length > 1 // duplicates are too complex
) {
supportsFastEdit = false;
} else if (matches?.length === 1) {

View File

@ -86,18 +86,39 @@ acceptance("Fast Edit", function (needs) {
assert.dom(".d-editor-input").exists();
});
test("Opens full composer when editing non-ascii characters", async function (assert) {
test("Works with diacritics", async function (assert) {
await visit("/t/internationalization-localization/280");
query("#post_2 .cooked").append(
`Je suis désolé, ”comment ça va”? A bientôt!`
);
query("#post_2 .cooked").append(`Je suis désolé, comment ça va?`);
const textNode = query("#post_2 .cooked").childNodes[2];
await selectText(textNode);
await click(".quote-button .quote-edit-label");
assert.dom("#fast-edit-input").doesNotExist();
assert.dom(".d-editor-input").exists();
assert.dom("#fast-edit-input").exists();
});
test("Works with CJK ranges", async function (assert) {
await visit("/t/internationalization-localization/280");
query("#post_2 .cooked").append(`这是一个测试`);
const textNode = query("#post_2 .cooked").childNodes[2];
await selectText(textNode);
await click(".quote-button .quote-edit-label");
assert.dom("#fast-edit-input").exists();
});
test("Works with emoji", async function (assert) {
await visit("/t/internationalization-localization/280");
query("#post_2 .cooked").append(`This is great 👍`);
const textNode = query("#post_2 .cooked").childNodes[2];
await selectText(textNode);
await click(".quote-button .quote-edit-label");
assert.dom("#fast-edit-input").exists();
});
});

View File

@ -6,6 +6,9 @@ describe "Post selection | Fast edit", type: :system do
fab!(:topic)
fab!(:post) { Fabricate(:post, topic: topic) }
fab!(:post_2) { Fabricate(:post, topic: topic, raw: "It twas a great “time”!") }
fab!(:spanish_post) { Fabricate(:post, topic: topic, raw: "Hola Juan, ¿cómo estás?") }
fab!(:chinese_post) { Fabricate(:post, topic: topic, raw: "这是一个测试") }
fab!(:post_with_emoji) { Fabricate(:post, topic: topic, raw: "Good morning :wave:!") }
fab!(:current_user) { Fabricate(:admin) }
before { sign_in(current_user) }
@ -52,5 +55,49 @@ describe "Post selection | Fast edit", type: :system do
text: "It twas a great “day”!",
)
end
it "saves when text contains diacratics" do
topic_page.visit_topic(topic)
select_text_range("#{topic_page.post_by_number_selector(3)} .cooked p", 11, 12)
topic_page.click_fast_edit_button
fast_editor.fill_content("¿está todo bien?")
fast_editor.save
expect(page).to have_selector(
"#{topic_page.post_by_number_selector(3)} .cooked p",
text: "Hola Juan, ¿está todo bien?",
)
end
it "saves when text contains CJK ranges" do
topic_page.visit_topic(topic)
select_text_range("#{topic_page.post_by_number_selector(4)} .cooked p", 0, 2)
topic_page.click_fast_edit_button
fast_editor.fill_content("今天")
fast_editor.save
expect(page).to have_selector(
"#{topic_page.post_by_number_selector(4)} .cooked p",
text: "今天一个测试",
)
end
it "saves when text contains emoji" do
topic_page.visit_topic(topic)
select_text_range("#{topic_page.post_by_number_selector(5)} .cooked p", 5, 7)
topic_page.click_fast_edit_button
fast_editor.fill_content("day")
fast_editor.save
expect(page).to have_no_css("#fast-edit-input")
expect(post_with_emoji.raw).to eq("Good day :wave:!")
end
end
end