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
|
const filename = uploadFilenamePlaceholder
|
||||||
? uploadFilenamePlaceholder
|
? uploadFilenamePlaceholder
|
||||||
: clipboard;
|
: 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")
|
@discourseComputed("composer.requiredCategoryMissing")
|
||||||
@ -888,6 +894,18 @@ export default Component.extend({
|
|||||||
return element.tagName === "ASIDE" && element.classList.contains("quote");
|
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: {
|
actions: {
|
||||||
importQuote(toolbarEvent) {
|
importQuote(toolbarEvent) {
|
||||||
this.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 { click, fillIn, visit } from "@ember/test-helpers";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
|
|
||||||
@ -28,7 +32,7 @@ async function writeInComposer(assert) {
|
|||||||
await fillIn(".d-editor-input", "[test|attachment](upload://asdsad.png)");
|
await fillIn(".d-editor-input", "[test|attachment](upload://asdsad.png)");
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptance("Composer Attachment", function (needs) {
|
acceptance("Composer Attachment - Cooking", function (needs) {
|
||||||
needs.user();
|
needs.user();
|
||||||
needs.pretender(pretender);
|
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");
|
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) {
|
test("Create a topic with server side errors", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click("#create-topic");
|
await click("#create-topic");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user