mirror of
https://github.com/zulip/zulip.git
synced 2025-11-06 06:53:25 +00:00
markdown: Simulate message flags in frontend markdown processor.
This eliminates an annoying bundle of complexity that caused the frontend markdown processor's interface with the rest of Zulip's new message processing code paths being more similar to that of a new message from the server. It also cuts down on code duplication.
This commit is contained in:
@@ -268,18 +268,15 @@ test("marked_shared", () => {
|
|||||||
test("message_flags", () => {
|
test("message_flags", () => {
|
||||||
let message = {raw_content: "@**Leo**"};
|
let message = {raw_content: "@**Leo**"};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.ok(!message.mentioned);
|
assert.ok(!message.flags.includes("mentioned"));
|
||||||
assert.ok(!message.mentioned_me_directly);
|
|
||||||
|
|
||||||
message = {raw_content: "@**Cordelia, Lear's daughter**"};
|
message = {raw_content: "@**Cordelia, Lear's daughter**"};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.ok(message.mentioned);
|
assert.ok(message.flags.includes("mentioned"));
|
||||||
assert.ok(message.mentioned_me_directly);
|
|
||||||
|
|
||||||
message = {raw_content: "@**all**"};
|
message = {raw_content: "@**all**"};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.ok(message.mentioned);
|
assert.ok(message.flags.includes("wildcard_mentioned"));
|
||||||
assert.ok(!message.mentioned_me_directly);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("marked", () => {
|
test("marked", () => {
|
||||||
@@ -680,77 +677,87 @@ test("message_flags", () => {
|
|||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
|
|
||||||
assert.equal(message.is_me_message, false);
|
assert.equal(message.is_me_message, false);
|
||||||
assert.equal(message.mentioned, true);
|
assert.equal(message.flags.includes("mentioned"), true);
|
||||||
assert.equal(message.mentioned_me_directly, true);
|
assert.equal(message.flags.includes("wildcard_mentioned"), true);
|
||||||
|
|
||||||
input = "test @**everyone**";
|
input = "test @**everyone**";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.is_me_message, false);
|
assert.equal(message.is_me_message, false);
|
||||||
assert.equal(message.mentioned, true);
|
assert.equal(message.flags.includes("wildcard_mentioned"), true);
|
||||||
assert.equal(message.mentioned_me_directly, false);
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @**stream**";
|
input = "test @**stream**";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.is_me_message, false);
|
assert.equal(message.is_me_message, false);
|
||||||
assert.equal(message.mentioned, true);
|
assert.equal(message.flags.includes("wildcard_mentioned"), true);
|
||||||
assert.equal(message.mentioned_me_directly, false);
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @all";
|
input = "test @all";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @everyone";
|
input = "test @everyone";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @any";
|
input = "test @any";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @alleycat.com";
|
input = "test @alleycat.com";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @*hamletcharacters*";
|
input = "test @*hamletcharacters*";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, true);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), true);
|
||||||
|
|
||||||
input = "test @*backend*";
|
input = "test @*backend*";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @**invalid_user**";
|
input = "test @**invalid_user**";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @_**all**";
|
input = "test @_**all**";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "> test @**all**";
|
input = "> test @**all**";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "test @_*hamletcharacters*";
|
input = "test @_*hamletcharacters*";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
|
|
||||||
input = "> test @*hamletcharacters*";
|
input = "> test @*hamletcharacters*";
|
||||||
message = {topic: "No links here", raw_content: input};
|
message = {topic: "No links here", raw_content: input};
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
assert.equal(message.mentioned, false);
|
assert.equal(message.flags.includes("wildcard_mentioned"), false);
|
||||||
|
assert.equal(message.flags.includes("mentioned"), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("backend_only_linkifiers", () => {
|
test("backend_only_linkifiers", () => {
|
||||||
|
|||||||
@@ -178,25 +178,6 @@ export function insert_local_message(message_request, local_id_float) {
|
|||||||
// NOTE: This will parse synchronously. We're not using the async pipeline
|
// NOTE: This will parse synchronously. We're not using the async pipeline
|
||||||
markdown.apply_markdown(message);
|
markdown.apply_markdown(message);
|
||||||
|
|
||||||
// TODO: markdown.apply_markdown has a messy interface around
|
|
||||||
// message flags. It mutates the message to set all the message
|
|
||||||
// booleans to false via message_store.init_booleans, and then
|
|
||||||
// proceeds to mutate primarily the mentioned flag during
|
|
||||||
// rendering in a messy way.
|
|
||||||
//
|
|
||||||
// We should clean that up to instead just mutate the flags list
|
|
||||||
// on the message, to match how the Zulip API returns this
|
|
||||||
// information via flags. For now, we translate back to the flags
|
|
||||||
// namespace here, and then message_store.set_message_booleans
|
|
||||||
// will get us to the correct final flags.
|
|
||||||
//
|
|
||||||
// Locally delivered messages cannot be unread (since we sent
|
|
||||||
// them), nor can they alert the user.
|
|
||||||
message.flags = ["read"];
|
|
||||||
if (message.mentioned) {
|
|
||||||
message.flags.push("mentioned");
|
|
||||||
}
|
|
||||||
|
|
||||||
message.content_type = "text/html";
|
message.content_type = "text/html";
|
||||||
message.sender_email = people.my_current_email();
|
message.sender_email = people.my_current_email();
|
||||||
message.sender_full_name = people.my_full_name();
|
message.sender_full_name = people.my_full_name();
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import marked from "../third/marked/lib/marked";
|
|||||||
|
|
||||||
import * as blueslip from "./blueslip";
|
import * as blueslip from "./blueslip";
|
||||||
import * as linkifiers from "./linkifiers";
|
import * as linkifiers from "./linkifiers";
|
||||||
import * as message_store from "./message_store";
|
|
||||||
|
|
||||||
// This contains zulip's frontend Markdown implementation; see
|
// This contains zulip's frontend Markdown implementation; see
|
||||||
// docs/subsystems/markdown.md for docs on our Markdown syntax. The other
|
// docs/subsystems/markdown.md for docs on our Markdown syntax. The other
|
||||||
@@ -96,7 +95,9 @@ export function contains_backend_only_syntax(content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function apply_markdown(message) {
|
export function apply_markdown(message) {
|
||||||
message_store.init_booleans(message);
|
let mentioned = false;
|
||||||
|
let mentioned_group = false;
|
||||||
|
let mentioned_wildcard = false;
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
userMentionHandler(mention, silently) {
|
userMentionHandler(mention, silently) {
|
||||||
@@ -107,7 +108,8 @@ export function apply_markdown(message) {
|
|||||||
classes = "user-mention silent";
|
classes = "user-mention silent";
|
||||||
display_text = mention;
|
display_text = mention;
|
||||||
} else {
|
} else {
|
||||||
message.mentioned = true;
|
// Wildcard mention
|
||||||
|
mentioned_wildcard = true;
|
||||||
display_text = "@" + mention;
|
display_text = "@" + mention;
|
||||||
classes = "user-mention";
|
classes = "user-mention";
|
||||||
}
|
}
|
||||||
@@ -183,8 +185,8 @@ export function apply_markdown(message) {
|
|||||||
classes = "user-mention silent";
|
classes = "user-mention silent";
|
||||||
} else {
|
} else {
|
||||||
if (helpers.my_user_id() === user_id) {
|
if (helpers.my_user_id() === user_id) {
|
||||||
message.mentioned = true;
|
// Personal mention of current user.
|
||||||
message.mentioned_me_directly = true;
|
mentioned = true;
|
||||||
}
|
}
|
||||||
classes = "user-mention";
|
classes = "user-mention";
|
||||||
display_text = "@" + display_text;
|
display_text = "@" + display_text;
|
||||||
@@ -206,7 +208,8 @@ export function apply_markdown(message) {
|
|||||||
display_text = "@" + group.name;
|
display_text = "@" + group.name;
|
||||||
classes = "user-group-mention";
|
classes = "user-group-mention";
|
||||||
if (helpers.is_member_of_user_group(group.id, helpers.my_user_id())) {
|
if (helpers.is_member_of_user_group(group.id, helpers.my_user_id())) {
|
||||||
message.mentioned = true;
|
// Mentioned the current user's group.
|
||||||
|
mentioned_group = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,13 +236,32 @@ export function apply_markdown(message) {
|
|||||||
// mention yourself outside of the blockquote (and, above it). If that you do that, the
|
// mention yourself outside of the blockquote (and, above it). If that you do that, the
|
||||||
// following mentioned status is false; the backend rendering is authoritative and the
|
// following mentioned status is false; the backend rendering is authoritative and the
|
||||||
// only side effect is the lack red flash on immediately sending the message.
|
// only side effect is the lack red flash on immediately sending the message.
|
||||||
message.mentioned = false;
|
//
|
||||||
message.mentioned_me_directly = false;
|
// A better parser would be able to just ignore mentions
|
||||||
|
// inside; we just set all flags to False and let the
|
||||||
|
// server rendering correct the message flags, to avoid a
|
||||||
|
// flash of mention styling.
|
||||||
|
mentioned = false;
|
||||||
|
mentioned_group = false;
|
||||||
|
mentioned_wildcard = false;
|
||||||
return quote;
|
return quote;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Our Python-Markdown processor appends two \n\n to input
|
// Our Python-Markdown processor appends two \n\n to input
|
||||||
message.content = marked(message.raw_content + "\n\n", options).trim();
|
message.content = marked(message.raw_content + "\n\n", options).trim();
|
||||||
|
|
||||||
|
// Simulate message flags for our locally rendered
|
||||||
|
// message. Messages the user themselves sent via the browser are
|
||||||
|
// always marked as read.
|
||||||
|
message.flags = ["read"];
|
||||||
|
if (mentioned || mentioned_group) {
|
||||||
|
message.flags.push("mentioned");
|
||||||
|
}
|
||||||
|
if (mentioned_wildcard) {
|
||||||
|
message.flags.push("wildcard_mentioned");
|
||||||
|
}
|
||||||
|
|
||||||
message.is_me_message = is_status_message(message.raw_content);
|
message.is_me_message = is_status_message(message.raw_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,20 +79,6 @@ export function set_message_booleans(message) {
|
|||||||
delete message.flags;
|
delete message.flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function init_booleans(message) {
|
|
||||||
// This initializes booleans for the local-echo path where
|
|
||||||
// we don't have flags from the server yet. (We want to
|
|
||||||
// explicitly set flags to false to be consistent with other
|
|
||||||
// codepaths.)
|
|
||||||
message.unread = false;
|
|
||||||
message.historical = false;
|
|
||||||
message.starred = false;
|
|
||||||
message.mentioned = false;
|
|
||||||
message.mentioned_me_directly = false;
|
|
||||||
message.collapsed = false;
|
|
||||||
message.alerted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function update_booleans(message, flags) {
|
export function update_booleans(message, flags) {
|
||||||
// When we get server flags for local echo or message edits,
|
// When we get server flags for local echo or message edits,
|
||||||
// we are vulnerable to race conditions, so only update flags
|
// we are vulnerable to race conditions, so only update flags
|
||||||
|
|||||||
Reference in New Issue
Block a user