mirror of
https://github.com/zulip/zulip.git
synced 2025-10-24 08:33:43 +00:00
Compare commits
18 Commits
5.7
...
shared-0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ff2bcf62a | ||
|
|
7de1e7c477 | ||
|
|
b7f670f5a0 | ||
|
|
2a240d3e19 | ||
|
|
efdf2c8fe3 | ||
|
|
71c12e313c | ||
|
|
da6d687215 | ||
|
|
58799c6ca1 | ||
|
|
8d9e6d6b87 | ||
|
|
935cb605a5 | ||
|
|
ca38b33346 | ||
|
|
0008a76703 | ||
|
|
d9bf8baca1 | ||
|
|
46b19fe8bd | ||
|
|
c1103e4c7b | ||
|
|
c8dba33408 | ||
|
|
6ea9947991 | ||
|
|
12e8f0f5ea |
12
.mailmap
12
.mailmap
@@ -12,6 +12,8 @@
|
||||
# # shows raw names/emails, filtered by mapped name:
|
||||
# $ git log --format='%an %ae' --author=$NAME | uniq -c
|
||||
|
||||
Adam Benesh <Adam.Benesh@gmail.com> <Adam-Daniel.Benesh@t-systems.com>
|
||||
Adam Benesh <Adam.Benesh@gmail.com>
|
||||
Alex Vandiver <alexmv@zulip.com> <alex@chmrr.net>
|
||||
Alex Vandiver <alexmv@zulip.com> <github@chmrr.net>
|
||||
Allen Rabinovich <allenrabinovich@yahoo.com> <allenr@humbughq.com>
|
||||
@@ -20,6 +22,9 @@ Alya Abbott <alya@zulip.com> <2090066+alya@users.noreply.github.com>
|
||||
Aman Agrawal <amanagr@zulip.com> <f2016561@pilani.bits-pilani.ac.in>
|
||||
Anders Kaseorg <anders@zulip.com> <anders@zulipchat.com>
|
||||
Anders Kaseorg <anders@zulip.com> <andersk@mit.edu>
|
||||
Aryan Shridhar <aryanshridhar7@gmail.com> <53977614+aryanshridhar@users.noreply.github.com>
|
||||
Aryan Shridhar <aryanshridhar7@gmail.com>
|
||||
Ashwat Kumar Singh <ashwat.kumarsingh.met20@itbhu.ac.in>
|
||||
Austin Riba <austin@zulip.com> <austin@m51.io>
|
||||
BIKI DAS <bikid475@gmail.com>
|
||||
Brock Whittaker <brock@zulipchat.com> <bjwhitta@asu.edu>
|
||||
@@ -37,6 +42,7 @@ Jeff Arnold <jbarnold@gmail.com> <jbarnold@humbughq.com>
|
||||
Jeff Arnold <jbarnold@gmail.com> <jbarnold@zulip.com>
|
||||
Jessica McKellar <jesstess@mit.edu> <jesstess@humbughq.com>
|
||||
Jessica McKellar <jesstess@mit.edu> <jesstess@zulip.com>
|
||||
Julia Bichler <julia.bichler@tum.de> <74348920+juliaBichler01@users.noreply.github.com>
|
||||
Kevin Mehall <km@kevinmehall.net> <kevin@humbughq.com>
|
||||
Kevin Mehall <km@kevinmehall.net> <kevin@zulip.com>
|
||||
Kevin Scott <kevin.scott.98@gmail.com>
|
||||
@@ -45,11 +51,13 @@ Mateusz Mandera <mateusz.mandera@zulip.com> <mateusz.mandera@protonmail.com>
|
||||
m-e-l-u-h-a-n <purushottam.tiwari.cd.cse19@itbhu.ac.in>
|
||||
Palash Raghuwanshi <singhpalash0@gmail.com>
|
||||
Parth <mittalparth22@gmail.com>
|
||||
Priyam Seth <sethpriyam1@gmail.com> <b19188@students.iitmandi.ac.in>
|
||||
Ray Kraesig <rkraesig@zulip.com> <rkraesig@zulipchat.com>
|
||||
Reid Barton <rwbarton@gmail.com> <rwbarton@humbughq.com>
|
||||
Rishi Gupta <rishig@zulipchat.com> <rishig+git@mit.edu>
|
||||
Rishi Gupta <rishig@zulipchat.com> <rishig@kandralabs.com>
|
||||
Rishi Gupta <rishig@zulipchat.com> <rishig@users.noreply.github.com>
|
||||
Reid Barton <rwbarton@gmail.com> <rwbarton@humbughq.com>
|
||||
Rishabh Maheshwari <b20063@students.iitmandi.ac.in>
|
||||
Sayam Samal <samal.sayam@gmail.com>
|
||||
Scott Feeney <scott@oceanbase.org> <scott@humbughq.com>
|
||||
Scott Feeney <scott@oceanbase.org> <scott@zulip.com>
|
||||
@@ -71,3 +79,5 @@ Sahil Batra <sahil@zulip.com> <sahilbatra839@gmail.com>
|
||||
Yash RE <33805964+YashRE42@users.noreply.github.com> <YashRE42@github.com>
|
||||
Yash RE <33805964+YashRE42@users.noreply.github.com>
|
||||
Yogesh Sirsat <yogeshsirsat56@gmail.com>
|
||||
Zeeshan Equbal <equbalzeeshan@gmail.com> <54993043+zee-bit@users.noreply.github.com>
|
||||
Zeeshan Equbal <equbalzeeshan@gmail.com>
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
# Version history
|
||||
|
||||
This page contains the release history for the Zulip 5.x stable
|
||||
release series. See the [current Zulip changelog][latest-changelog]
|
||||
for newer release series, or the [commit log][commit-log] for an
|
||||
up-to-date list of raw changes.
|
||||
This page the release history for the Zulip server. See also the
|
||||
[Zulip release lifecycle](../overview/release-lifecycle.md).
|
||||
|
||||
## Zulip 6.x series
|
||||
|
||||
### 6.0 -- unreleased
|
||||
|
||||
This section is an incomplete draft of the release notes for the next
|
||||
major release, and is only updated occasionally. See the [commit
|
||||
log][commit-log] for an up-to-date list of raw changes.
|
||||
|
||||
#### Upgrade notes for 6.0
|
||||
|
||||
- None yet.
|
||||
|
||||
## Zulip 5.x series
|
||||
|
||||
@@ -1566,7 +1576,7 @@ Zulip installations; it has minimal changes for existing servers.
|
||||
disruption by running this migration first, before beginning the
|
||||
user-facing downtime. However, if you'd like to watch the downtime
|
||||
phase of the upgrade closely, we recommend
|
||||
[running them first manually](https://zulip.readthedocs.io/en/1.9.0/production/expensive-migrations.html)
|
||||
running them first manually
|
||||
as well as the usual trick of doing an apt upgrade first.
|
||||
|
||||
#### Full feature changelog
|
||||
@@ -1955,7 +1965,7 @@ running a version from before 1.7 should upgrade directly to 1.7.1.
|
||||
minimizes disruption by running these first, before beginning the
|
||||
user-facing downtime. However, if you'd like to watch the downtime
|
||||
phase of the upgrade closely, we recommend
|
||||
[running them first manually](https://zulip.readthedocs.io/en/1.9.0/production/expensive-migrations.html)
|
||||
running them first manually
|
||||
as well as the usual trick of doing an apt upgrade first.
|
||||
|
||||
- We've removed support for an uncommon legacy deployment model where
|
||||
@@ -2580,15 +2590,17 @@ running a version from before 1.7 should upgrade directly to 1.7.1.
|
||||
This section links to the upgrade notes from past releases, so you can
|
||||
easily read them all when upgrading across multiple releases.
|
||||
|
||||
- [Upgrade notes for 5.0](#upgrade-notes-for-50)
|
||||
- [Upgrade notes for 4.0](#upgrade-notes-for-40)
|
||||
- [Upgrade notes for 3.0](#upgrade-notes-for-30)
|
||||
- [Upgrade notes for 2.1.5](#upgrade-notes-for-215)
|
||||
- [Upgrade notes for 2.1.0](#upgrade-notes-for-210)
|
||||
- [Upgrade notes for 2.0.0](#upgrade-notes-for-200)
|
||||
- [Upgrade notes for 1.9.0](#upgrade-notes-for-190)
|
||||
- [Upgrade notes for 1.8.0](#upgrade-notes-for-180)
|
||||
- [Upgrade notes for 1.7.0](#upgrade-notes-for-170)
|
||||
- [Draft upgrade notes for 6.0](#upgrade-notes-for-60)
|
||||
|
||||
* [Upgrade notes for 5.0](#upgrade-notes-for-50)
|
||||
* [Upgrade notes for 4.0](#upgrade-notes-for-40)
|
||||
* [Upgrade notes for 3.0](#upgrade-notes-for-30)
|
||||
* [Upgrade notes for 2.1.5](#upgrade-notes-for-215)
|
||||
* [Upgrade notes for 2.1.0](#upgrade-notes-for-210)
|
||||
* [Upgrade notes for 2.0.0](#upgrade-notes-for-200)
|
||||
* [Upgrade notes for 1.9.0](#upgrade-notes-for-190)
|
||||
* [Upgrade notes for 1.8.0](#upgrade-notes-for-180)
|
||||
* [Upgrade notes for 1.7.0](#upgrade-notes-for-170)
|
||||
|
||||
[docker-zulip]: https://github.com/zulip/docker-zulip
|
||||
[commit-log]: https://github.com/zulip/zulip/commits/main
|
||||
|
||||
149
frontend_tests/node_tests/markdown_parse.js
Normal file
149
frontend_tests/node_tests/markdown_parse.js
Normal file
@@ -0,0 +1,149 @@
|
||||
"use strict";
|
||||
|
||||
const {strict: assert} = require("assert");
|
||||
|
||||
const {zrequire} = require("../zjsunit/namespace");
|
||||
const {run_test} = require("../zjsunit/test");
|
||||
|
||||
const markdown = zrequire("markdown");
|
||||
|
||||
const my_id = 101;
|
||||
|
||||
const user_map = new Map();
|
||||
user_map.set(my_id, "Me Myself");
|
||||
user_map.set(105, "greg");
|
||||
|
||||
function get_actual_name_from_user_id(user_id) {
|
||||
return user_map.get(user_id);
|
||||
}
|
||||
|
||||
function get_user_id_from_name(name) {
|
||||
for (const [user_id, _name] of user_map.entries()) {
|
||||
if (name === _name) {
|
||||
return user_id;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function is_valid_full_name_and_user_id(name, user_id) {
|
||||
return user_map.has(user_id) && user_map.get(user_id) === name;
|
||||
}
|
||||
|
||||
function my_user_id() {
|
||||
return my_id;
|
||||
}
|
||||
|
||||
function is_valid_user_id(user_id) {
|
||||
return user_map.has(user_id);
|
||||
}
|
||||
|
||||
const staff_group = {
|
||||
id: 201,
|
||||
name: "Staff",
|
||||
};
|
||||
|
||||
const user_group_map = new Map();
|
||||
user_group_map.set(staff_group.name, staff_group);
|
||||
|
||||
function get_user_group_from_name(name) {
|
||||
return user_group_map.get(name);
|
||||
}
|
||||
|
||||
function is_member_of_user_group(user_group_id, user_id) {
|
||||
assert.equal(user_group_id, staff_group.id);
|
||||
assert.equal(user_id, my_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
const social = {
|
||||
stream_id: 301,
|
||||
name: "social",
|
||||
};
|
||||
|
||||
const sub_map = new Map();
|
||||
sub_map.set(social.name, social);
|
||||
|
||||
function get_stream_by_name(name) {
|
||||
return sub_map.get(name);
|
||||
}
|
||||
|
||||
function stream_hash(stream_id) {
|
||||
return `stream-${stream_id}`;
|
||||
}
|
||||
|
||||
function stream_topic_hash(stream_id, topic) {
|
||||
return `stream-${stream_id}-topic-${topic}`;
|
||||
}
|
||||
|
||||
const helper_config = {
|
||||
// user stuff
|
||||
get_actual_name_from_user_id,
|
||||
get_user_id_from_name,
|
||||
is_valid_full_name_and_user_id,
|
||||
is_valid_user_id,
|
||||
my_user_id,
|
||||
|
||||
// user groups
|
||||
get_user_group_from_name,
|
||||
is_member_of_user_group,
|
||||
|
||||
// stream hashes
|
||||
get_stream_by_name,
|
||||
stream_hash,
|
||||
stream_topic_hash,
|
||||
|
||||
// settings
|
||||
should_translate_emoticons: () => false,
|
||||
};
|
||||
|
||||
function assert_parse(raw_content, expected_content) {
|
||||
const {content} = markdown.parse({raw_content, helper_config});
|
||||
assert.equal(content, expected_content);
|
||||
}
|
||||
|
||||
function test(label, f) {
|
||||
markdown.setup();
|
||||
run_test(label, f);
|
||||
}
|
||||
|
||||
test("basics", () => {
|
||||
assert_parse("boring", "<p>boring</p>");
|
||||
assert_parse("**bold**", "<p><strong>bold</strong></p>");
|
||||
});
|
||||
|
||||
test("user mentions", () => {
|
||||
assert_parse("@**greg**", '<p><span class="user-mention" data-user-id="105">@greg</span></p>');
|
||||
|
||||
assert_parse("@**|105**", '<p><span class="user-mention" data-user-id="105">@greg</span></p>');
|
||||
|
||||
assert_parse(
|
||||
"@**greg|105**",
|
||||
'<p><span class="user-mention" data-user-id="105">@greg</span></p>',
|
||||
);
|
||||
|
||||
assert_parse(
|
||||
"@**Me Myself|101**",
|
||||
'<p><span class="user-mention" data-user-id="101">@Me Myself</span></p>',
|
||||
);
|
||||
});
|
||||
|
||||
test("user group mentions", () => {
|
||||
assert_parse(
|
||||
"@*Staff*",
|
||||
'<p><span class="user-group-mention" data-user-group-id="201">@Staff</span></p>',
|
||||
);
|
||||
});
|
||||
|
||||
test("stream links", () => {
|
||||
assert_parse(
|
||||
"#**social**",
|
||||
'<p><a class="stream" data-stream-id="301" href="/stream-301">#social</a></p>',
|
||||
);
|
||||
|
||||
assert_parse(
|
||||
"#**social>lunch**",
|
||||
'<p><a class="stream-topic" data-stream-id="301" href="/stream-301-topic-lunch">#social > lunch</a></p>',
|
||||
);
|
||||
});
|
||||
@@ -61,7 +61,7 @@ class zulip::profile::base {
|
||||
}
|
||||
}
|
||||
package { 'ntp': ensure => 'purged', before => Package['chrony'] }
|
||||
service { 'chrony': ensure => 'running', require => Package['chrony'] }
|
||||
service { 'chrony': require => Package['chrony'] }
|
||||
package { $base_packages: ensure => 'installed' }
|
||||
|
||||
group { 'zulip':
|
||||
|
||||
@@ -161,6 +161,7 @@ export function build_page() {
|
||||
settings_config.create_web_public_stream_policy_values,
|
||||
disable_enable_spectator_access_setting: !page_params.server_web_public_streams_enabled,
|
||||
can_sort_by_email: settings_data.show_email(),
|
||||
realm_push_notifications_enabled: page_params.realm_push_notifications_enabled,
|
||||
};
|
||||
|
||||
if (options.realm_logo_source !== "D" && options.realm_night_logo_source === "D") {
|
||||
|
||||
@@ -1,22 +1,10 @@
|
||||
import marked from "../third/marked/lib/marked";
|
||||
|
||||
import * as blueslip from "./blueslip";
|
||||
import * as markdown from "./markdown";
|
||||
|
||||
const linkifier_map = new Map();
|
||||
export let linkifier_list = [];
|
||||
const linkifier_map = new Map(); // regex -> url
|
||||
|
||||
function handleLinkifier(pattern, matches) {
|
||||
let url = linkifier_map.get(pattern);
|
||||
|
||||
let current_group = 1;
|
||||
|
||||
for (const match of matches) {
|
||||
const back_ref = "\\" + current_group;
|
||||
url = url.replace(back_ref, match);
|
||||
current_group += 1;
|
||||
}
|
||||
|
||||
return url;
|
||||
export function get_linkifier_map() {
|
||||
return linkifier_map;
|
||||
}
|
||||
|
||||
function python_to_js_linkifier(pattern, url) {
|
||||
@@ -78,11 +66,7 @@ function python_to_js_linkifier(pattern, url) {
|
||||
}
|
||||
|
||||
export function update_linkifier_rules(linkifiers) {
|
||||
// Update the marked parser with our particular set of linkifiers
|
||||
linkifier_map.clear();
|
||||
linkifier_list = [];
|
||||
|
||||
const marked_rules = [];
|
||||
|
||||
for (const linkifier of linkifiers) {
|
||||
const [regex, final_url] = python_to_js_linkifier(linkifier.pattern, linkifier.url_format);
|
||||
@@ -92,18 +76,12 @@ export function update_linkifier_rules(linkifiers) {
|
||||
}
|
||||
|
||||
linkifier_map.set(regex, final_url);
|
||||
linkifier_list.push({
|
||||
pattern: regex,
|
||||
url_format: final_url,
|
||||
});
|
||||
marked_rules.push(regex);
|
||||
}
|
||||
|
||||
marked.InlineLexer.rules.zulip.linkifiers = marked_rules;
|
||||
// Update our parser with our particular set of linkifiers.
|
||||
markdown.set_linkifier_regexes(Array.from(linkifier_map.keys()));
|
||||
}
|
||||
|
||||
export function initialize(linkifiers) {
|
||||
update_linkifier_rules(linkifiers);
|
||||
|
||||
marked.setOptions({linkifierHandler: handleLinkifier});
|
||||
}
|
||||
|
||||
@@ -23,8 +23,9 @@ import * as linkifiers from "./linkifiers";
|
||||
// for example usage.
|
||||
let helpers;
|
||||
|
||||
// Regexes that match some of our common backend-only Markdown syntax
|
||||
const backend_only_markdown_re = [
|
||||
// If we see preview-related syntax in our content, we will need the
|
||||
// backend to render it.
|
||||
const preview_regexes = [
|
||||
// Inline image previews, check for contiguous chars ending in image suffix
|
||||
// To keep the below regexes simple, split them out for the end-of-message case
|
||||
|
||||
@@ -33,9 +34,13 @@ const backend_only_markdown_re = [
|
||||
|
||||
// Twitter and youtube links are given previews
|
||||
|
||||
/\S*(?:twitter|youtube).com\/\S*/,
|
||||
/\S*(?:twitter|youtube)\.com\/\S*/,
|
||||
];
|
||||
|
||||
function contains_preview_link(content) {
|
||||
return preview_regexes.some((re) => re.test(content));
|
||||
}
|
||||
|
||||
export function translate_emoticons_to_names(text) {
|
||||
// Translates emoticons in a string to their colon syntax.
|
||||
let translated = text;
|
||||
@@ -76,25 +81,36 @@ export function translate_emoticons_to_names(text) {
|
||||
return translated;
|
||||
}
|
||||
|
||||
function contains_problematic_linkifier(content) {
|
||||
// If a linkifier doesn't start with some specified characters
|
||||
// then don't render it locally. It is workaround for the fact that
|
||||
// javascript regex doesn't support lookbehind.
|
||||
for (const re of linkifiers.get_linkifier_map().keys()) {
|
||||
const pattern = /[^\s"'(,:<]/.source + re.source + /(?!\w)/.source;
|
||||
const regex = new RegExp(pattern);
|
||||
if (regex.test(content)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function contains_backend_only_syntax(content) {
|
||||
// Try to guess whether or not a message contains syntax that only the
|
||||
// backend Markdown processor can correctly handle.
|
||||
// If it doesn't, we can immediately render it client-side for local echo.
|
||||
const markedup = backend_only_markdown_re.find((re) => re.test(content));
|
||||
|
||||
// If a linkifier doesn't start with some specified characters
|
||||
// then don't render it locally. It is workaround for the fact that
|
||||
// javascript regex doesn't support lookbehind.
|
||||
const linkifier_list = linkifiers.linkifier_list;
|
||||
const false_linkifier_match = linkifier_list.find((re) => {
|
||||
const pattern = /[^\s"'(,:<]/.source + re.pattern.source + /(?!\w)/.source;
|
||||
const regex = new RegExp(pattern);
|
||||
return regex.test(content);
|
||||
});
|
||||
return markedup !== undefined || false_linkifier_match !== undefined;
|
||||
return contains_preview_link(content) || contains_problematic_linkifier(content);
|
||||
}
|
||||
|
||||
export function apply_markdown(message) {
|
||||
export function parse({raw_content, helper_config}) {
|
||||
// Given the raw markdown content of a message (raw_content)
|
||||
// we return the HTML content (content) and flags.
|
||||
// Our caller passes a helper_config object that has several
|
||||
// helper functions for getting info about users, streams, etc.
|
||||
|
||||
helpers = helper_config;
|
||||
|
||||
let mentioned = false;
|
||||
let mentioned_group = false;
|
||||
let mentioned_wildcard = false;
|
||||
@@ -249,20 +265,20 @@ export function apply_markdown(message) {
|
||||
};
|
||||
|
||||
// Our Python-Markdown processor appends two \n\n to input
|
||||
message.content = marked(message.raw_content + "\n\n", options).trim();
|
||||
const content = marked(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"];
|
||||
const flags = ["read"];
|
||||
if (mentioned || mentioned_group) {
|
||||
message.flags.push("mentioned");
|
||||
flags.push("mentioned");
|
||||
}
|
||||
if (mentioned_wildcard) {
|
||||
message.flags.push("wildcard_mentioned");
|
||||
flags.push("wildcard_mentioned");
|
||||
}
|
||||
|
||||
message.is_me_message = is_status_message(message.raw_content);
|
||||
return {content, flags};
|
||||
}
|
||||
|
||||
export function add_topic_links(message) {
|
||||
@@ -272,11 +288,8 @@ export function add_topic_links(message) {
|
||||
}
|
||||
const topic = message.topic;
|
||||
const links = [];
|
||||
const linkifier_list = linkifiers.linkifier_list;
|
||||
|
||||
for (const linkifier of linkifier_list) {
|
||||
const pattern = linkifier.pattern;
|
||||
const url = linkifier.url_format;
|
||||
for (const [pattern, url] of linkifiers.get_linkifier_map().entries()) {
|
||||
let match;
|
||||
while ((match = pattern.exec(topic)) !== null) {
|
||||
let link_url = url;
|
||||
@@ -360,6 +373,20 @@ function handleEmoji(emoji_name) {
|
||||
return alt_text;
|
||||
}
|
||||
|
||||
function handleLinkifier(pattern, matches) {
|
||||
let url = linkifiers.get_linkifier_map().get(pattern);
|
||||
|
||||
let current_group = 1;
|
||||
|
||||
for (const match of matches) {
|
||||
const back_ref = "\\" + current_group;
|
||||
url = url.replace(back_ref, match);
|
||||
current_group += 1;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
function handleTimestamp(time) {
|
||||
let timeobject;
|
||||
if (Number.isNaN(Number(time))) {
|
||||
@@ -422,8 +449,15 @@ function handleTex(tex, fullmatch) {
|
||||
}
|
||||
}
|
||||
|
||||
export function initialize(helper_config) {
|
||||
helpers = helper_config;
|
||||
export function set_linkifier_regexes(regexes) {
|
||||
// This needs to be called any time we modify our linkifier regexes,
|
||||
// until we find a less clumsy way to handle this.
|
||||
marked.InlineLexer.rules.zulip.linkifiers = regexes;
|
||||
}
|
||||
|
||||
export function setup() {
|
||||
// Once we focus on supporting other platforms such as mobile,
|
||||
// we will export this function.
|
||||
|
||||
function disable_markdown_regex(rules, name) {
|
||||
rules[name] = {
|
||||
@@ -495,6 +529,7 @@ export function initialize(helper_config) {
|
||||
smartypants: false,
|
||||
zulip: true,
|
||||
emojiHandler: handleEmoji,
|
||||
linkifierHandler: handleLinkifier,
|
||||
unicodeEmojiHandler: handleUnicodeEmoji,
|
||||
streamHandler: handleStream,
|
||||
streamTopicHandler: handleStreamTopic,
|
||||
@@ -504,3 +539,28 @@ export function initialize(helper_config) {
|
||||
preprocessors: [preprocess_code_blocks, preprocess_translate_emoticons],
|
||||
});
|
||||
}
|
||||
|
||||
// NOTE: Everything below this line is likely to be webapp-specific
|
||||
// and won't be used by future platforms such as mobile.
|
||||
// We may eventually move this code to a new file, but we want
|
||||
// to wait till the dust settles a bit on some other changes first.
|
||||
|
||||
let webapp_helpers;
|
||||
|
||||
export function initialize(helper_config) {
|
||||
// This is generally only intended to be called by the webapp. Most
|
||||
// other platforms should call setup().
|
||||
webapp_helpers = helper_config;
|
||||
helpers = helper_config;
|
||||
setup();
|
||||
}
|
||||
|
||||
export function apply_markdown(message) {
|
||||
// This is generally only intended to be called by the webapp. Most
|
||||
// other platforms should call parse().
|
||||
const raw_content = message.raw_content;
|
||||
const {content, flags} = parse({raw_content, helper_config: webapp_helpers});
|
||||
message.content = content;
|
||||
message.flags = flags;
|
||||
message.is_me_message = is_status_message(raw_content);
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ export function build_page() {
|
||||
user_can_change_avatar: settings_data.user_can_change_avatar(),
|
||||
user_role_text: people.get_user_type(page_params.user_id),
|
||||
default_language_name: settings_display.user_default_language_name,
|
||||
realm_push_notifications_enabled: page_params.realm_push_notifications_enabled,
|
||||
settings_object: user_settings,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zulip/shared",
|
||||
"version": "0.0.9",
|
||||
"version": "0.0.10",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"katex": "^0.15.3",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<th colspan="2" width="28%">{{t "Desktop"}}</th>
|
||||
<th rowspan="2" width="14%" class="{{#if show_push_notifications_tooltip.push_notifications}}control-label-disabled{{/if}}">
|
||||
{{t "Mobile"}}
|
||||
{{#if (not page_params.realm_push_notifications_enabled) }}
|
||||
{{#if (not realm_push_notifications_enabled) }}
|
||||
<i class="fa fa-question-circle settings-info-icon tippy-zulip-tooltip" data-tippy-content="{{t 'Mobile push notifications are not configured on this server.' }}"></i>
|
||||
{{/if}}
|
||||
</th>
|
||||
|
||||
@@ -18,6 +18,11 @@ clients should check the `zulip_feature_level` field, present in the
|
||||
/register`](/api/register-queue) responses, to determine the API
|
||||
format used by the Zulip server that they are interacting with.
|
||||
|
||||
## Changes in Zulip 6.0
|
||||
|
||||
Feature levels 123-124 are reserved for future use in 5.x maintenance
|
||||
releases.
|
||||
|
||||
## Changes in Zulip 5.0
|
||||
|
||||
**Feature level 122**
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
<li><a href="/team/">{{ _("Team") }}</a> & <a href="/history/">{{ _("History") }}</a></li>
|
||||
<li><a href="https://twitter.com/zulip/">Twitter</a></li>
|
||||
<li><a href="/jobs/">{{ _("Jobs") }}</a></li>
|
||||
<li><a href="/attribution">Website attributions</a></li>
|
||||
<li><a href="/attribution">{{ _("Website attributions") }}</a></li>
|
||||
<li><a href="https://github.com/sponsors/zulip">{{ _("Sponsor Zulip") }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,8 @@ import sys
|
||||
from collections import defaultdict
|
||||
from typing import Dict, List
|
||||
|
||||
bot_commits = 0
|
||||
|
||||
|
||||
def add_log(committer_dict: Dict[str, int], input: List[str]) -> None:
|
||||
for dataset in input:
|
||||
@@ -15,6 +17,8 @@ def add_log(committer_dict: Dict[str, int], input: List[str]) -> None:
|
||||
|
||||
if committer_name.endswith("[bot]"):
|
||||
# Exclude dependabot[bot] and other GitHub bots.
|
||||
global bot_commits
|
||||
bot_commits += commit_count
|
||||
continue
|
||||
|
||||
committer_dict[committer_name] += commit_count
|
||||
@@ -131,11 +135,21 @@ print(
|
||||
f"Commit range {lower_zulip_version}..{upper_zulip_version} corresponds to {lower_time} to {upper_time}"
|
||||
)
|
||||
|
||||
repository_dict: Dict[str, int] = defaultdict(int)
|
||||
out_dict: Dict[str, int] = defaultdict(int)
|
||||
subprocess.check_call(["git", "fetch"], cwd=find_path("zulip"))
|
||||
zulip = retrieve_log("zulip", lower_zulip_version, upper_zulip_version)
|
||||
print(f"Commit range for zulip/zulip: {lower_zulip_version[0:12]}..{upper_zulip_version[0:12]}")
|
||||
add_log(out_dict, zulip)
|
||||
commit_count = len(
|
||||
subprocess.check_output(
|
||||
["git", "log", "--pretty=oneline", f"{lower_zulip_version}..{upper_zulip_version}"],
|
||||
cwd=find_path("zulip"),
|
||||
text=True,
|
||||
).splitlines()
|
||||
)
|
||||
repo_log = retrieve_log("zulip", lower_zulip_version, upper_zulip_version)
|
||||
print(
|
||||
f"{commit_count} commits from zulip/zulip: {lower_zulip_version[0:12]}..{upper_zulip_version[0:12]}"
|
||||
)
|
||||
add_log(out_dict, repo_log)
|
||||
|
||||
# TODO: We should migrate the last couple repositories to use the
|
||||
# `main` default branch name and then simplify this.
|
||||
@@ -163,9 +177,16 @@ for (full_repository, branch) in [
|
||||
subprocess.check_call(["git", "fetch"], cwd=find_path(repository))
|
||||
lower_repo_version = find_last_commit_before_time(repository, branch, lower_time)
|
||||
upper_repo_version = find_last_commit_before_time(repository, branch, upper_time)
|
||||
commit_count = len(
|
||||
subprocess.check_output(
|
||||
["git", "log", "--pretty=oneline", f"{lower_repo_version}..{upper_repo_version}"],
|
||||
cwd=find_path(repository),
|
||||
text=True,
|
||||
).splitlines()
|
||||
)
|
||||
repo_log = retrieve_log(repository, lower_repo_version, upper_repo_version)
|
||||
print(
|
||||
f"Commit range for {full_repository}: {lower_repo_version[0:12]}..{upper_repo_version[0:12]}"
|
||||
f"{commit_count} commits from {full_repository}: {lower_repo_version[0:12]}..{upper_repo_version[0:12]}"
|
||||
)
|
||||
add_log(out_dict, repo_log)
|
||||
|
||||
@@ -177,7 +198,8 @@ for committer_name, commit_count in sorted(
|
||||
print(str(commit_count) + "\t" + committer_name)
|
||||
grand_total += commit_count
|
||||
|
||||
print(f"Excluded {bot_commits} commits authored by bots.")
|
||||
print(
|
||||
f"{grand_total} total commits by {len(out_dict)} contributors between "
|
||||
f"{lower_zulip_version} and {upper_repo_version}."
|
||||
f"{lower_zulip_version} and {upper_zulip_version}."
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
|
||||
ZULIP_VERSION = "5.0"
|
||||
ZULIP_VERSION = "6.0-dev+git"
|
||||
|
||||
# Add information on number of commits and commit hash to version, if available
|
||||
zulip_git_version_file = os.path.join(
|
||||
|
||||
@@ -978,7 +978,6 @@ class StreamAdminTest(ZulipTestCase):
|
||||
self.assertTrue(attachment.is_realm_public)
|
||||
|
||||
params = {
|
||||
"stream_name": orjson.dumps("test_stream").decode(),
|
||||
"is_private": orjson.dumps(True).decode(),
|
||||
"history_public_to_subscribers": orjson.dumps(True).decode(),
|
||||
}
|
||||
@@ -1000,7 +999,6 @@ class StreamAdminTest(ZulipTestCase):
|
||||
self.assertFalse(validate_attachment_request_for_spectator_access(realm, attachment))
|
||||
|
||||
params = {
|
||||
"stream_name": orjson.dumps("test_stream").decode(),
|
||||
"is_private": orjson.dumps(False).decode(),
|
||||
"is_web_public": orjson.dumps(True).decode(),
|
||||
"history_public_to_subscribers": orjson.dumps(True).decode(),
|
||||
@@ -1025,7 +1023,6 @@ class StreamAdminTest(ZulipTestCase):
|
||||
self.assertTrue(attachment.is_realm_public)
|
||||
|
||||
params = {
|
||||
"stream_name": orjson.dumps("test_stream").decode(),
|
||||
"is_private": orjson.dumps(False).decode(),
|
||||
"is_web_public": orjson.dumps(False).decode(),
|
||||
"history_public_to_subscribers": orjson.dumps(True).decode(),
|
||||
|
||||
Reference in New Issue
Block a user