diff --git a/async/index.browser.js b/async/index.browser.js index 68362643..2ead6973 100644 --- a/async/index.browser.js +++ b/async/index.browser.js @@ -4,39 +4,38 @@ var crypto = self.crypto || self.msCrypto // This alphabet uses a-z A-Z 0-9 _- symbols. -// Despite the fact the source code is quite long, its entropy -// is low and there are lots of duplicates - just what compressors -// like GZIP and Brotli likes the best. -var i -var url = '_-' + String.fromCharCode( - // ASCII codes for 0...9 - i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +// Symbols are generated for better gzip compression. +// Final url is +// '-_zyxwvutsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA' +var url = '-_' - // ASCII codes for A...Z - i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +var i = 36 +while (i--) { + // 36 is radix. + // Number.prototype.toString(36) returns number in Base36 representation. + // Base36 is like hex, + // but Base36 is represented using the numerals 0–9 and the Latin letters a-z + url += i.toString(36) +} - // ASCII codes for a...z - i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1 -) +i = 36 +// Loop from 36 to 10 (from Z to A in Base36) +while (i-- - 10) { + url += i.toString(36).toUpperCase() +} module.exports = function (size) { - size = size || 21 var id = '' - var bytes = crypto.getRandomValues(new Uint8Array(size)) + var bytes = crypto.getRandomValues(new Uint8Array(size || 21)) + i = size || 21 + // Compact alternative for `for (var i = 0; i < size; i++)` - while (size--) { + while (i--) { // We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. // This mask reduces random byte 0-255 to 0-63 values. // There is no need in `|| ''` and `* 1.6` hacks in here, // because bitmask trim bytes exact to alphabet size. - id += url[bytes[size] & 63] + id += url[bytes[i] & 63] } return Promise.resolve(id) } diff --git a/index.browser.js b/index.browser.js index ea4e395f..2f5e2f65 100644 --- a/index.browser.js +++ b/index.browser.js @@ -21,39 +21,38 @@ if (process.env.NODE_ENV !== 'production') { var crypto = self.crypto || self.msCrypto // This alphabet uses a-z A-Z 0-9 _- symbols. -// Despite the fact the source code is quite long, its entropy -// is low and there are lots of duplicates - just what compressors -// like GZIP and Brotli likes the best. -var i -var url = '_-' + String.fromCharCode( - // ASCII codes for 0...9 - i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +// Symbols are generated for better gzip compression. +// Final url is +// '-_zyxwvutsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA' +var url = '-_' - // ASCII codes for A...Z - i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +var i = 36 +while (i--) { + // 36 is radix. + // Number.prototype.toString(36) returns number in Base36 representation. + // Base36 is like hex, + // but Base36 is represented using the numerals 0–9 and the Latin letters a-z + url += i.toString(36) +} - // ASCII codes for a...z - i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1 -) +i = 36 +// Loop from 36 to 10 (from Z to A in Base36) +while (i-- - 10) { + url += i.toString(36).toUpperCase() +} module.exports = function (size) { - size = size || 21 var id = '' - var bytes = crypto.getRandomValues(new Uint8Array(size)) + var bytes = crypto.getRandomValues(new Uint8Array(size || 21)) + i = size || 21 + // Compact alternative for `for (var i = 0; i < size; i++)` - while (size--) { + while (i--) { // We can’t use bytes bigger than the alphabet. 63 is 00111111 bitmask. // This mask reduces random byte 0-255 to 0-63 values. // There is no need in `|| ''` and `* 1.6` hacks in here, // because bitmask trim bytes exact to alphabet size. - id += url[bytes[size] & 63] + id += url[bytes[i] & 63] } return id } diff --git a/non-secure/index.js b/non-secure/index.js index 08c4e319..94f0cbd9 100644 --- a/non-secure/index.js +++ b/non-secure/index.js @@ -1,25 +1,23 @@ // This alphabet uses a-z A-Z 0-9 _- symbols. -// Despite the fact the source code is quite long, its entropy -// is low and there are lots of duplicates - just what compressors -// like GZIP and Brotli likes the best. -var i -var url = '_-' + String.fromCharCode( - // ASCII codes for 0...9 - i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +// Symbols are generated for better gzip compression. +// Final url is +// '-_zyxwvutsrqponmlkjihgfedcba9876543210ZYXWVUTSRQPONMLKJIHGFEDCBA' +var url = '-_' - // ASCII codes for A...Z - i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, +var i = 36 +while (i--) { + // 36 is radix. + // Number.prototype.toString(36) returns number in Base36 representation. + // Base36 is like hex, + // but Base36 is represented using the numerals 0–9 and the Latin letters a-z + url += i.toString(36) +} - // ASCII codes for a...z - i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1 -) +i = 36 +// Loop from 36 to 10 (from Z to A in Base36) +while (i-- - 10) { + url += i.toString(36).toUpperCase() +} /** * Generate URL-friendly unique ID. This method use non-secure predictable @@ -37,10 +35,10 @@ var url = '_-' + String.fromCharCode( * @function */ module.exports = function (size) { - size = size || 21 var id = '' + i = size || 21 // Compact alternative for `for (var i = 0; i < size; i++)` - while (size--) { + while (i--) { // `| 0` is compact and faster alternative for `Math.floor()` id += url[Math.random() * 64 | 0] } diff --git a/package.json b/package.json index c90d26e9..2e3f8619 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "size-limit": [ { "path": "index.js", - "limit": "127 B" + "limit": "119 B" }, { "path": "generate.js", @@ -78,7 +78,7 @@ }, { "path": "non-secure/index.js", - "limit": "89 B" + "limit": "82 B" }, { "path": "non-secure/generate.js", @@ -86,7 +86,7 @@ }, { "path": "async/index.js", - "limit": "139 B" + "limit": "130 B" }, { "path": "async/generate.js", diff --git a/url.js b/url.js index 5be82d1c..cf95ea4d 100644 --- a/url.js +++ b/url.js @@ -3,8 +3,6 @@ // is low and there are lots of duplicates - just what compressors // like GZIP and Brotli likes the best. -var i - /** * URL safe symbols. * @@ -15,20 +13,14 @@ var i * const url = require('nanoid/url') * generate(url, 10) //=> "Uakgb_J5m9" */ -module.exports = '_-' + String.fromCharCode( - // ASCII codes for 0...9 - i = 48, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, - - // ASCII codes for A...Z - i += 8, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, - // ASCII codes for a...z - i += 7, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, i += 1, - i += 1, i += 1 -) +module.exports = '-_' +var i = 36 +while (i--) { + // 36 is radix. + // Number.prototype.toString(36) returns number in Base36 representation. + // Base36 is like hex, + // but Base36 is represented using the numerals 0–9 and the Latin letters a-z + module.exports += i.toString(36) + i > 9 && (module.exports += i.toString(36).toUpperCase()) +}