Skip to content

Commit

Permalink
Try not to break words when quoting original message during replies
Browse files Browse the repository at this point in the history
  • Loading branch information
tadzik committed Jul 21, 2021
1 parent 9cb96f3 commit 123f5b7
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 11 deletions.
1 change: 1 addition & 0 deletions changelog.d/1428.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Truncate original messages more gently when replying
16 changes: 16 additions & 0 deletions spec/unit/TrimString.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,20 @@ describe("trimString", function() {

done();
});

it('should stop trimming at the word boundary if reasonable', (done) => {
const input = "this sentence is waaaaay too long";
const result = trimString(input, 20);
expect(result).toEqual('this sentence is');

done();
});

it('should give up looking for a word boundary if result would become too short', (done) => {
const input = "we're in Llanfairpwllgwyngyll";
const result = trimString(input, 24);
expect(result).toContain("we're in Llan");

done();
});
});
35 changes: 24 additions & 11 deletions src/util/TrimString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,33 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// a unicode-aware substring(0, $x)
// since trimRight()/trimEnd() may break unicode characters
function trimTrailingWhitespace(input: string): string {
return input.replace(/\s*$/u, '');
}

// a unicode-aware substring(0, $x) that tries to not break words if possible
export function trimString(input: string, maxLength: number): string {
const re = new RegExp(`^([\\s\\S]{0,${maxLength}})`, 'u');
const re = new RegExp(`^([\\s\\S]{0,${maxLength}})(\\p{L}?)`, 'u');
const match = input.match(re);

let trimmed: string;
if (match) {
trimmed = match[1];
}
else {
if (!match) {
// fallback to a dumb substring() if the regex failed for any reason
trimmed = input.substring(0, maxLength);
return trimTrailingWhitespace(input.substring(0, maxLength));
}

const trimmed = trimTrailingWhitespace(match[1]);

if (match[2]) {
// find as much as you can that is followed by a word boundary,
// shorter than what we have now, but at least 75% of the desired length
const smallerMatch = trimmed.match(/^([\s\S]*\S)\b[\s\S]/u);
const minLength = maxLength * 0.75;

if (smallerMatch && smallerMatch[1].length >= minLength) {
return smallerMatch[1];
}
}
//
// trimRight()/trimEnd() may break unicode characters
return trimmed.replace(/\s*$/u, '');

return trimmed;
}

0 comments on commit 123f5b7

Please sign in to comment.