diff --git a/chrome/content/zotero/xpcom/debug.js b/chrome/content/zotero/xpcom/debug.js index 2632beba2e..069c3cc8cb 100644 --- a/chrome/content/zotero/xpcom/debug.js +++ b/chrome/content/zotero/xpcom/debug.js @@ -158,7 +158,7 @@ Zotero.Debug = new function () { if (maxLineLength) { for (var i=0, len=output.length; i maxLineLength) { - output[i] = Zotero.Utilities.ellipsize(output[i], maxLineLength, true); + output[i] = Zotero.Utilities.ellipsize(output[i], maxLineLength, false, true); } } } diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js index d87ab9f1a4..85d1d027e9 100644 --- a/chrome/content/zotero/xpcom/utilities.js +++ b/chrome/content/zotero/xpcom/utilities.js @@ -842,18 +842,32 @@ Zotero.Utilities = { /** * Shorten and add an ellipsis to a string if necessary * - * @param {String} str - * @param {Integer} len - * @param {Boolean} [countChars=false] + * @param {String} str + * @param {Integer} len + * @param {Boolean} [wordBoundary=false] + * @param {Boolean} [countChars=false] */ - "ellipsize":function (str, len, countChars) { + ellipsize: function (str, len, wordBoundary = false, countChars) { if (!len) { throw ("Length not specified in Zotero.Utilities.ellipsize()"); } - if (str.length > len) { - return str.substr(0, len) + '\u2026' + (countChars ? ' (' + str.length + ' chars)' : ''); + if (str.length <= len) { + return str; } - return str; + let radius = Math.min(len, 5); + if (wordBoundary) { + let min = len - radius; + // If next character is a space, include that so we stop at len + if (str.charAt(len).match(/\s/)) { + radius++; + } + // Remove trailing characters and spaces, up to radius + str = str.substr(0, min) + str.substr(min, radius).replace(/\W*\s\S*$/, ""); + } + else { + str = str.substr(0, len) + } + return str + '\u2026' + (countChars ? ' (' + str.length + ' chars)' : ''); }, /** diff --git a/test/tests/utilitiesTest.js b/test/tests/utilitiesTest.js index 3a831d101a..6791a70e8f 100644 --- a/test/tests/utilitiesTest.js +++ b/test/tests/utilitiesTest.js @@ -370,4 +370,36 @@ describe("Zotero.Utilities", function() { assert.equal(item.getField('title'), jsonAttachment.title, 'title imported correctly'); }); }); + + describe("#ellipsize()", function () { + describe("with wordBoundary", function () { + it("should truncate at word boundary", function* () { + assert.equal(Zotero.Utilities.ellipsize("abc def ghi", 3, true), "abc…"); + }); + + it("should trim whitespace after word boundary", function* () { + assert.equal(Zotero.Utilities.ellipsize("abc def ghi", 4, true), "abc…"); + }); + + it("should trim characters after word boundary", function () { + assert.equal(Zotero.Utilities.ellipsize("abc def ghi", 5, true), "abc…"); + }); + + it("should truncate in the middle of a word", function () { + assert.equal(Zotero.Utilities.ellipsize("abcdefghi", 6, true), "abcdef…"); + }); + + it("should truncate at word boundary with previous space within radius", function () { + assert.equal(Zotero.Utilities.ellipsize("abc def ghi", 7, true), "abc def…"); + }); + + it("should return string as is if shorter than length", function () { + assert.equal(Zotero.Utilities.ellipsize("abcdefg", 8, true), "abcdefg"); + }); + + it("should return string as is if equal to length", function () { + assert.equal(Zotero.Utilities.ellipsize("abcdefgh", 8, true), "abcdefgh"); + }); + }); + }); });