diff --git a/chrome/content/zotero/xpcom/utilities_internal.js b/chrome/content/zotero/xpcom/utilities_internal.js index a7ac0bbdd9..fff3cd4aea 100644 --- a/chrome/content/zotero/xpcom/utilities_internal.js +++ b/chrome/content/zotero/xpcom/utilities_internal.js @@ -1164,6 +1164,29 @@ Zotero.Utilities.Internal = { }, + /** + * Get the next available numbered name that matches a base name, for use when duplicating + * + * - Given 'Foo' and ['Foo'], returns 'Foo (1)'. + * - Given 'Foo (1)' and ['Foo', 'Foo (1)'], returns 'Foo (2)' + */ + getNextName: function (name, existingNames) { + // Trim '(1)', etc. + var matches = name.match(/^(.+) \(\d+\)$/); + if (matches) { + name = matches[1].trim(); + } + var highest = 0; + for (let existingName of existingNames) { + let matches = existingName.match(/ \((\d+)\)$/); + if (matches && matches[1] > highest) { + highest = matches[1]; + } + } + return name + ' (' + ++highest + ')'; + }, + + buildLibraryMenu: function (menulist, libraries, selectedLibraryID) { var menupopup = menulist.firstChild; while (menupopup.hasChildNodes()) { diff --git a/test/tests/utilities_internalTest.js b/test/tests/utilities_internalTest.js index 20c36cfade..514c3f060c 100644 --- a/test/tests/utilities_internalTest.js +++ b/test/tests/utilities_internalTest.js @@ -200,4 +200,16 @@ describe("Zotero.Utilities.Internal", function () { assert.propertyVal(identifiers[3], "arXiv", "math.GT/0309135"); }); }); + + describe("#getNextName()", function () { + it("should get the next available numbered name", function () { + var existing = ['Name (1)', 'Name (3)']; + assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name (4)'); + }); + + it("should return 'Name (1)' if no numbered names", function () { + var existing = ['Name']; + assert.equal(Zotero.Utilities.Internal.getNextName('Name', existing), 'Name (1)'); + }); + }); })