mirror of
https://github.com/discourse/discourse.git
synced 2025-03-03 17:59:20 +00:00
FEATURE: always insert images on new lines and add newline after (#12895)
This commit is contained in:
parent
54b7a0d06c
commit
d3b05f8a9c
@ -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);
|
||||
|
@ -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(),
|
||||
"\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\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\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\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\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\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\n[Uploading: image.png...]()\n\n"
|
||||
);
|
||||
|
||||
await queryAll(".wmd-controls").trigger("fileuploaddone", image1);
|
||||
assert.equal(
|
||||
queryAll(".d-editor-input").val(),
|
||||
"\n\n[Uploading: image.png...]()\n\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(),
|
||||
"\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,
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -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...]()  [Uploading: ima++ge.png...]() [Uploading: image.png...]() "
|
||||
);
|
||||
|
||||
await queryAll(".wmd-controls").trigger("fileuploaddone", data3);
|
||||
assert.equal(
|
||||
queryAll(".d-editor-input").val(),
|
||||
"[Uploading: test.png...]()  [Uploading: ima++ge.png...]()  "
|
||||
);
|
||||
|
||||
await queryAll(".wmd-controls").trigger("fileuploaddone", data1);
|
||||
assert.equal(
|
||||
queryAll(".d-editor-input").val(),
|
||||
"  [Uploading: ima++ge.png...]()  "
|
||||
);
|
||||
});
|
||||
|
||||
test("Create a topic with server side errors", async function (assert) {
|
||||
await visit("/");
|
||||
await click("#create-topic");
|
||||
|
Loading…
x
Reference in New Issue
Block a user