mirror of
https://github.com/discourse/discourse.git
synced 2024-12-01 04:59:22 -06:00
PERF: faster length calculation of composer body
Every time we type a letter the composer issues a reply length check. This is due to the interconnecting components, the title one depends on the body which means that this decision making is passed along each time, even if the title does not need it strictly. Anyway... This optimisation has 3 parts: 1. If the composer string is super long (10000 chars) we will bypass, quote stripping and space squashing. 2. Quote stripping is now done much more efficiently, we strip them all in one go 3. Space squashing eg: `hello world` to `hello world` is done in an efficient loop to avoid needing to generate superflous strings that need GC
This commit is contained in:
parent
2d5b928da9
commit
afc7830be5
@ -56,7 +56,8 @@ const CLOSED = "closed",
|
||||
categoryId: "topic.category.id",
|
||||
tags: "topic.tags",
|
||||
featuredLink: "topic.featured_link"
|
||||
};
|
||||
},
|
||||
FAST_REPLY_LENGTH_THRESHOLD = 10000;
|
||||
|
||||
export const SAVE_LABELS = {
|
||||
[EDIT]: "composer.save_edit",
|
||||
@ -445,10 +446,62 @@ const Composer = RestModel.extend({
|
||||
@computed("reply")
|
||||
replyLength(reply) {
|
||||
reply = reply || "";
|
||||
while (Quote.REGEXP.test(reply)) {
|
||||
reply = reply.replace(Quote.REGEXP, "");
|
||||
|
||||
if (reply.length > FAST_REPLY_LENGTH_THRESHOLD) {
|
||||
return reply.length;
|
||||
}
|
||||
return reply.replace(/\s+/gim, " ").trim().length;
|
||||
|
||||
if (Quote.REGEXP.test(reply)) {
|
||||
// make it global so we can strip all quotes at once
|
||||
const regex = new RegExp(Quote.REGEXP.source, "img");
|
||||
reply = reply.replace(regex, "");
|
||||
}
|
||||
|
||||
// This is in place so we do not generate any intermediate
|
||||
// strings while calculating the length, this is issued
|
||||
// every keypress in the composer so it needs to be very fast
|
||||
let len = 0,
|
||||
skipSpace = true;
|
||||
|
||||
for (let i = 0; i < reply.length; i++) {
|
||||
const code = reply.charCodeAt(i);
|
||||
|
||||
let isSpace = false;
|
||||
if (code >= 0x2000 && code <= 0x200a) {
|
||||
isSpace = true;
|
||||
} else {
|
||||
switch (code) {
|
||||
case 0x09: // \t
|
||||
case 0x0a: // \n
|
||||
case 0x0b: // \v
|
||||
case 0x0c: // \f
|
||||
case 0x0d: // \r
|
||||
case 0x20:
|
||||
case 0xa0:
|
||||
case 0x1680:
|
||||
case 0x202f:
|
||||
case 0x205f:
|
||||
case 0x3000:
|
||||
isSpace = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSpace) {
|
||||
if (!skipSpace) {
|
||||
len++;
|
||||
skipSpace = true;
|
||||
}
|
||||
} else {
|
||||
len++;
|
||||
skipSpace = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0 && skipSpace) {
|
||||
len--;
|
||||
}
|
||||
|
||||
return len;
|
||||
},
|
||||
|
||||
@on("init")
|
||||
|
Loading…
Reference in New Issue
Block a user