2018-11-27 19:56:46 -05:00
|
|
|
const words = require('./words')
|
2018-11-26 22:24:31 -05:00
|
|
|
const digits = '0123456789'
|
2020-06-15 22:29:41 -04:00
|
|
|
const symbols = '`~!@#$%^&*()_+-=,./<>?;:|[]{} '
|
|
|
|
const defaultSymbol = '-'
|
2018-11-26 22:24:31 -05:00
|
|
|
|
2018-11-27 19:56:46 -05:00
|
|
|
function getWordList (name) {
|
2018-12-04 18:50:30 -05:00
|
|
|
if (['small', 'medium', 'large'].includes(name)) {
|
2018-11-26 22:24:31 -05:00
|
|
|
return words[name]
|
|
|
|
}
|
|
|
|
throw new Error(`Invalid word list: ${name}`)
|
|
|
|
}
|
|
|
|
|
2018-11-27 19:56:46 -05:00
|
|
|
function getWords (list, indices) {
|
2018-11-26 22:24:31 -05:00
|
|
|
return Array.from(indices).map(index => list[index % list.length])
|
|
|
|
}
|
|
|
|
|
2018-11-27 19:56:46 -05:00
|
|
|
function capitalize (string) {
|
2018-11-26 22:24:31 -05:00
|
|
|
return string[0].toUpperCase() + string.slice(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
function pickWords (list, number) {
|
|
|
|
const array = new Uint16Array(number)
|
|
|
|
window.crypto.getRandomValues(array)
|
|
|
|
return getWords(list, array)
|
|
|
|
}
|
|
|
|
|
2018-12-04 19:49:47 -05:00
|
|
|
function getChar (choices, index) {
|
|
|
|
return choices[index % choices.length]
|
|
|
|
}
|
|
|
|
|
|
|
|
function pickChar (choices) {
|
2018-11-26 22:24:31 -05:00
|
|
|
const array = new Uint32Array(1)
|
|
|
|
window.crypto.getRandomValues(array)
|
2018-12-04 19:49:47 -05:00
|
|
|
const index = array[0]
|
|
|
|
return getChar(choices, index)
|
2018-11-26 22:24:31 -05:00
|
|
|
}
|
|
|
|
|
2018-11-27 19:56:46 -05:00
|
|
|
function generate (options) {
|
2018-11-26 22:24:31 -05:00
|
|
|
let words = pickWords(getWordList(options.list), options.count)
|
|
|
|
|
|
|
|
if (options.capitalize) {
|
|
|
|
words = words.map(capitalize)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options.digit) {
|
|
|
|
words.push(pickChar(digits))
|
|
|
|
}
|
|
|
|
|
2020-06-15 22:29:41 -04:00
|
|
|
return words.join(options.symbol ? options.separator : '')
|
2018-11-26 22:24:31 -05:00
|
|
|
}
|
|
|
|
|
2018-11-27 19:56:46 -05:00
|
|
|
function lengthBits (list) {
|
2018-11-26 22:24:31 -05:00
|
|
|
return Math.log2(list.length)
|
|
|
|
}
|
|
|
|
|
2020-06-15 22:29:41 -04:00
|
|
|
function bitsForSymbol (symbol) {
|
|
|
|
return symbol === defaultSymbol ? 1 : lengthBits(symbols)
|
|
|
|
}
|
|
|
|
|
2018-11-27 19:56:46 -05:00
|
|
|
function computeBits (options) {
|
2018-11-26 22:24:31 -05:00
|
|
|
const wordBits = lengthBits(getWordList(options.list))
|
|
|
|
const capsBits = options.capitalize ? 1 : 0
|
2020-06-15 22:29:41 -04:00
|
|
|
const symbolBits = options.symbol ? bitsForSymbol(options.separator) : 0
|
2018-11-26 22:24:31 -05:00
|
|
|
const digitBits = options.digit ? lengthBits(digits) : 0
|
|
|
|
|
|
|
|
return wordBits * options.count + capsBits + symbolBits + digitBits
|
|
|
|
}
|
2018-11-27 22:21:02 -05:00
|
|
|
|
|
|
|
module.exports = {
|
2020-06-15 22:29:41 -04:00
|
|
|
getWordList, getWords, capitalize, generate, getChar, lengthBits, computeBits,
|
|
|
|
symbols, defaultSymbol,
|
2018-11-27 22:21:02 -05:00
|
|
|
}
|