FEATURE: always insert images on new lines and add newline after (#12895)

This commit is contained in:
Andrei Prigorshnev 2021-04-30 12:38:28 +04:00 committed by GitHub
parent 54b7a0d06c
commit d3b05f8a9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 220 additions and 99 deletions

View File

@ -73,7 +73,13 @@ export default Component.extend({
const filename = uploadFilenamePlaceholder
? uploadFilenamePlaceholder
: clipboard;
return `[${I18n.t("uploading_filename", { filename })}]() `;
let placeholder = `[${I18n.t("uploading_filename", { filename })}]()\n`;
if (!this._cursorIsOnEmptyLine()) {
placeholder = `\n${placeholder}`;
}
return placeholder;
},
@discourseComputed("composer.requiredCategoryMissing")
@ -888,6 +894,18 @@ export default Component.extend({
return element.tagName === "ASIDE" && element.classList.contains("quote");
},
_cursorIsOnEmptyLine() {
const textArea = this.element.querySelector(".d-editor-input");
const selectionStart = textArea.selectionStart;
if (selectionStart === 0) {
return true;
} else if (textArea.value.charAt(selectionStart - 1) === "\n") {
return true;
} else {
return false;
}
},
actions: {
importQuote(toolbarEvent) {
this.importQuote(toolbarEvent);

View File

@ -1,4 +1,8 @@
import { acceptance, queryAll } from "discourse/tests/helpers/qunit-helpers";
import {
acceptance,
query,
queryAll,
} from "discourse/tests/helpers/qunit-helpers";
import { click, fillIn, visit } from "@ember/test-helpers";
import { test } from "qunit";
@ -28,7 +32,7 @@ async function writeInComposer(assert) {
await fillIn(".d-editor-input", "[test|attachment](upload://asdsad.png)");
}
acceptance("Composer Attachment", function (needs) {
acceptance("Composer Attachment - Cooking", function (needs) {
needs.user();
needs.pretender(pretender);
@ -54,3 +58,198 @@ acceptance("Composer Attachment - Secure Media Enabled", function (needs) {
);
});
});
acceptance("Composer Attachment - Upload Placeholder", function (needs) {
needs.user();
test("should insert a newline before and after an image when pasting into an empty composer", async function (assert) {
await visit("/");
await click("#create-topic");
const image = createImage("avatar.png", "/images/avatar.png?1", 200, 300);
await queryAll(".wmd-controls").trigger("fileuploadsend", image);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: avatar.png...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image);
assert.equal(
queryAll(".d-editor-input").val(),
"![avatar|200x300](/images/avatar.png?1)\n"
);
});
test("should insert a newline after an image when pasting into a blank line", async function (assert) {
await visit("/");
await click("#create-topic");
await fillIn(".d-editor-input", "The image:\n");
const image = createImage("avatar.png", "/images/avatar.png?1", 200, 300);
await queryAll(".wmd-controls").trigger("fileuploadsend", image);
assert.equal(
queryAll(".d-editor-input").val(),
"The image:\n[Uploading: avatar.png...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image);
assert.equal(
queryAll(".d-editor-input").val(),
"The image:\n![avatar|200x300](/images/avatar.png?1)\n"
);
});
test("should insert a newline before and after an image when pasting into a non blank line", async function (assert) {
await visit("/");
await click("#create-topic");
await fillIn(".d-editor-input", "The image:");
const image = createImage("avatar.png", "/images/avatar.png?1", 200, 300);
await queryAll(".wmd-controls").trigger("fileuploadsend", image);
assert.equal(
queryAll(".d-editor-input").val(),
"The image:\n[Uploading: avatar.png...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image);
assert.equal(
queryAll(".d-editor-input").val(),
"The image:\n![avatar|200x300](/images/avatar.png?1)\n"
);
});
test("should insert a newline before and after an image when pasting with cursor in the middle of the line", async function (assert) {
await visit("/");
await click("#create-topic");
await fillIn(".d-editor-input", "The image Text after the image.");
const textArea = query(".d-editor-input");
textArea.selectionStart = 10;
textArea.selectionEnd = 10;
const image = createImage("avatar.png", "/images/avatar.png?1", 200, 300);
await queryAll(".wmd-controls").trigger("fileuploadsend", image);
assert.equal(
queryAll(".d-editor-input").val(),
"The image \n[Uploading: avatar.png...]()\nText after the image."
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image);
assert.equal(
queryAll(".d-editor-input").val(),
"The image \n![avatar|200x300](/images/avatar.png?1)\nText after the image."
);
});
test("should insert a newline before and after an image when pasting with text selected", async function (assert) {
await visit("/");
await click("#create-topic");
const image = createImage("avatar.png", "/images/avatar.png?1", 200, 300);
await fillIn(
".d-editor-input",
"The image [paste here] Text after the image."
);
const textArea = query(".d-editor-input");
textArea.selectionStart = 10;
textArea.selectionEnd = 23;
await queryAll(".wmd-controls").trigger("fileuploadsend", image);
assert.equal(
queryAll(".d-editor-input").val(),
"The image \n[Uploading: avatar.png...]()\n Text after the image."
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image);
assert.equal(
queryAll(".d-editor-input").val(),
"The image \n![avatar|200x300](/images/avatar.png?1)\n Text after the image."
);
});
test("pasting several images", async function (assert) {
await visit("/");
await click("#create-topic");
const image1 = createImage("test.png", "/images/avatar.png?1", 200, 300);
const image2 = createImage("test.png", "/images/avatar.png?2", 100, 200);
const image3 = createImage("image.png", "/images/avatar.png?3", 300, 400);
const image4 = createImage("image.png", "/images/avatar.png?4", 300, 400);
await queryAll(".wmd-controls").trigger("fileuploadsend", image1);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploadsend", image2);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]()\n[Uploading: test.png(1)...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploadsend", image4);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]()\n[Uploading: test.png(1)...]()\n[Uploading: image.png...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploadsend", image3);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]()\n[Uploading: test.png(1)...]()\n[Uploading: image.png...]()\n[Uploading: image.png(1)...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image2);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]()\n![test|100x200](/images/avatar.png?2)\n[Uploading: image.png...]()\n[Uploading: image.png(1)...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image3);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]()\n![test|100x200](/images/avatar.png?2)\n[Uploading: image.png...]()\n![image|300x400](/images/avatar.png?3)\n"
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image1);
assert.equal(
queryAll(".d-editor-input").val(),
"![test|200x300](/images/avatar.png?1)\n![test|100x200](/images/avatar.png?2)\n[Uploading: image.png...]()\n![image|300x400](/images/avatar.png?3)\n"
);
});
test("should accept files with unescaped characters", async function (assert) {
await visit("/");
await click("#create-topic");
const image = createImage("ima++ge.png", "/images/avatar.png?4", 300, 400);
await queryAll(".wmd-controls").trigger("fileuploadsend", image);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: ima++ge.png...]()\n"
);
await queryAll(".wmd-controls").trigger("fileuploaddone", image);
assert.equal(
queryAll(".d-editor-input").val(),
"![ima++ge|300x400](/images/avatar.png?4)\n"
);
});
function createImage(name, url, width, height) {
const file = new Blob([""], { type: "image/png" });
file.name = name;
return {
files: [file],
result: {
original_filename: name,
thumbnail_width: width,
thumbnail_height: height,
url: url,
},
};
}
});

View File

@ -118,102 +118,6 @@ acceptance("Composer", function (needs) {
assert.ok(!exists(".bootbox.modal"), "the confirmation can be cancelled");
});
test("Composer upload placeholder", async function (assert) {
await visit("/");
await click("#create-topic");
const file1 = new Blob([""], { type: "image/png" });
file1.name = "test.png";
const data1 = {
files: [file1],
result: {
original_filename: "test.png",
thumbnail_width: 200,
thumbnail_height: 300,
url: "/images/avatar.png?1",
},
};
const file2 = new Blob([""], { type: "image/png" });
file2.name = "test.png";
const data2 = {
files: [file2],
result: {
original_filename: "test.png",
thumbnail_width: 100,
thumbnail_height: 200,
url: "/images/avatar.png?2",
},
};
const file3 = new Blob([""], { type: "image/png" });
file3.name = "image.png";
const data3 = {
files: [file3],
result: {
original_filename: "image.png",
thumbnail_width: 300,
thumbnail_height: 400,
url: "/images/avatar.png?3",
},
};
const file4 = new Blob([""], { type: "image/png" });
file4.name = "ima++ge.png";
const data4 = {
files: [file4],
result: {
original_filename: "ima++ge.png",
thumbnail_width: 300,
thumbnail_height: 400,
url: "/images/avatar.png?3",
},
};
await queryAll(".wmd-controls").trigger("fileuploadsend", data1);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]() "
);
await queryAll(".wmd-controls").trigger("fileuploadsend", data2);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]() [Uploading: test.png(1)...]() "
);
await queryAll(".wmd-controls").trigger("fileuploadsend", data4);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]() [Uploading: test.png(1)...]() [Uploading: ima++ge.png...]() ",
"should accept files with unescaped characters"
);
await queryAll(".wmd-controls").trigger("fileuploadsend", data3);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]() [Uploading: test.png(1)...]() [Uploading: ima++ge.png...]() [Uploading: image.png...]() "
);
await queryAll(".wmd-controls").trigger("fileuploaddone", data2);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]() ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() [Uploading: image.png...]() "
);
await queryAll(".wmd-controls").trigger("fileuploaddone", data3);
assert.equal(
queryAll(".d-editor-input").val(),
"[Uploading: test.png...]() ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() ![image|300x400](/images/avatar.png?3) "
);
await queryAll(".wmd-controls").trigger("fileuploaddone", data1);
assert.equal(
queryAll(".d-editor-input").val(),
"![test|200x300](/images/avatar.png?1) ![test|100x200](/images/avatar.png?2) [Uploading: ima++ge.png...]() ![image|300x400](/images/avatar.png?3) "
);
});
test("Create a topic with server side errors", async function (assert) {
await visit("/");
await click("#create-topic");