Options.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var helper = require('./helper.js');
  4. var l33tTable = require('./data/l33tTable.js');
  5. var translationKeys = require('./data/translationKeys.js');
  6. class Options {
  7. constructor() {
  8. this.matchers = {};
  9. this.l33tTable = l33tTable;
  10. this.dictionary = {
  11. userInputs: []
  12. };
  13. this.rankedDictionaries = {};
  14. this.rankedDictionariesMaxWordSize = {};
  15. this.translations = translationKeys;
  16. this.graphs = {};
  17. this.useLevenshteinDistance = false;
  18. this.levenshteinThreshold = 2;
  19. this.l33tMaxSubstitutions = 100;
  20. this.maxLength = 256;
  21. this.setRankedDictionaries();
  22. }
  23. // eslint-disable-next-line max-statements,complexity
  24. setOptions(options = {}) {
  25. if (options.l33tTable) {
  26. this.l33tTable = options.l33tTable;
  27. }
  28. if (options.dictionary) {
  29. this.dictionary = options.dictionary;
  30. this.setRankedDictionaries();
  31. }
  32. if (options.translations) {
  33. this.setTranslations(options.translations);
  34. }
  35. if (options.graphs) {
  36. this.graphs = options.graphs;
  37. }
  38. if (options.useLevenshteinDistance !== undefined) {
  39. this.useLevenshteinDistance = options.useLevenshteinDistance;
  40. }
  41. if (options.levenshteinThreshold !== undefined) {
  42. this.levenshteinThreshold = options.levenshteinThreshold;
  43. }
  44. if (options.l33tMaxSubstitutions !== undefined) {
  45. this.l33tMaxSubstitutions = options.l33tMaxSubstitutions;
  46. }
  47. if (options.maxLength !== undefined) {
  48. this.maxLength = options.maxLength;
  49. }
  50. }
  51. setTranslations(translations) {
  52. if (this.checkCustomTranslations(translations)) {
  53. this.translations = translations;
  54. } else {
  55. throw new Error('Invalid translations object fallback to keys');
  56. }
  57. }
  58. checkCustomTranslations(translations) {
  59. let valid = true;
  60. Object.keys(translationKeys).forEach(type => {
  61. if (type in translations) {
  62. const translationType = type;
  63. Object.keys(translationKeys[translationType]).forEach(key => {
  64. if (!(key in translations[translationType])) {
  65. valid = false;
  66. }
  67. });
  68. } else {
  69. valid = false;
  70. }
  71. });
  72. return valid;
  73. }
  74. setRankedDictionaries() {
  75. const rankedDictionaries = {};
  76. const rankedDictionariesMaxWorkSize = {};
  77. Object.keys(this.dictionary).forEach(name => {
  78. rankedDictionaries[name] = this.getRankedDictionary(name);
  79. rankedDictionariesMaxWorkSize[name] = this.getRankedDictionariesMaxWordSize(name);
  80. });
  81. this.rankedDictionaries = rankedDictionaries;
  82. this.rankedDictionariesMaxWordSize = rankedDictionariesMaxWorkSize;
  83. }
  84. getRankedDictionariesMaxWordSize(name) {
  85. const data = this.dictionary[name].map(el => {
  86. if (typeof el !== 'string') {
  87. return el.toString().length;
  88. }
  89. return el.length;
  90. });
  91. // do not use Math.max(...data) because it can result in max stack size error because every entry will be used as an argument
  92. if (data.length === 0) {
  93. return 0;
  94. }
  95. return data.reduce((a, b) => Math.max(a, b), -Infinity);
  96. }
  97. getRankedDictionary(name) {
  98. const list = this.dictionary[name];
  99. if (name === 'userInputs') {
  100. const sanitizedInputs = [];
  101. list.forEach(input => {
  102. const inputType = typeof input;
  103. if (inputType === 'string' || inputType === 'number' || inputType === 'boolean') {
  104. sanitizedInputs.push(input.toString().toLowerCase());
  105. }
  106. });
  107. return helper.buildRankedDictionary(sanitizedInputs);
  108. }
  109. return helper.buildRankedDictionary(list);
  110. }
  111. extendUserInputsDictionary(dictionary) {
  112. if (this.dictionary.userInputs) {
  113. this.dictionary.userInputs = [...this.dictionary.userInputs, ...dictionary];
  114. } else {
  115. this.dictionary.userInputs = dictionary;
  116. }
  117. this.rankedDictionaries.userInputs = this.getRankedDictionary('userInputs');
  118. this.rankedDictionariesMaxWordSize.userInputs = this.getRankedDictionariesMaxWordSize('userInputs');
  119. }
  120. addMatcher(name, matcher) {
  121. if (this.matchers[name]) {
  122. console.info(`Matcher ${name} already exists`);
  123. } else {
  124. this.matchers[name] = matcher;
  125. }
  126. }
  127. }
  128. const zxcvbnOptions = new Options();
  129. exports.Options = Options;
  130. exports.default = zxcvbnOptions;
  131. //# sourceMappingURL=Options.js.map