Skip to content

Commit

Permalink
FIX: remove fast-edit regex and string replacement (#25496)
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
dbattersby committed Jan 31, 2024
1 parent e944468 commit 52249fa
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 20 deletions.
Expand Up @@ -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";
Expand Down Expand Up @@ -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) {
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
Expand Up @@ -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();
});
});
47 changes: 47 additions & 0 deletions spec/system/post_selection_fast_edit_spec.rb
Expand Up @@ -6,6 +6,9 @@
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) }
Expand Down Expand Up @@ -52,5 +55,49 @@
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

1 comment on commit 52249fa

@discoursebot
Copy link

Choose a reason for hiding this comment

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

This commit has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/fast-edit-supports-only-a-z/289177/13

Please sign in to comment.