Skip to content
Snippets Groups Projects
index.umd.js 74.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*!
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
     * json-schema-faker v0.5.0-rc20
    
     * (c) Alvaro Cabrera <pateketrueke@gmail.com> (https://soypache.co)
     * Released under the MIT License.
     */
    (function (global, factory) {
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('json-schema-ref-parser'), require('jsonpath-plus')) :
      typeof define === 'function' && define.amd ? define(['json-schema-ref-parser', 'jsonpath-plus'], factory) :
      (global = global || self, global.JSONSchemaFaker = factory(global.$RefParser, global.jsonpathPlus));
    }(this, function ($RefParser, jsonpathPlus) { 'use strict';
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      $RefParser = $RefParser && $RefParser.hasOwnProperty('default') ? $RefParser['default'] : $RefParser;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      /**
       * This class defines a registry for custom formats used within JSF.
       */
      var Registry = function Registry() {
        // empty by default
        this.data = {};
      };
      /**
       * Unregisters custom format(s)
       * @param name
       */
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      Registry.prototype.unregister = function unregister (name) {
        if (!name) {
          this.data = {};
        } else {
          delete this.data[name];
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      /**
       * Registers custom format
       */
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      Registry.prototype.register = function register (name, callback) {
        this.data[name] = callback;
      };
      /**
       * Register many formats at one shot
       */
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      Registry.prototype.registerMany = function registerMany (formats) {
          var this$1 = this;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        Object.keys(formats).forEach(function (name) {
          this$1.data[name] = formats[name];
        });
      };
      /**
       * Returns element by registry key
       */
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      Registry.prototype.get = function get (name) {
        var format = this.data[name];
        return format;
      };
      /**
       * Returns the whole registry content
       */
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      Registry.prototype.list = function list () {
        return this.data;
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var defaults = {};
      defaults.defaultInvalidTypeProduct = null;
      defaults.defaultRandExpMax = 10;
      defaults.ignoreProperties = [];
      defaults.ignoreMissingRefs = false;
      defaults.failOnInvalidTypes = true;
      defaults.failOnInvalidFormat = true;
      defaults.alwaysFakeOptionals = false;
      defaults.optionalsProbability = false;
      defaults.fixedProbabilities = false;
      defaults.useExamplesValue = false;
      defaults.useDefaultValue = false;
      defaults.requiredOnly = false;
      defaults.minItems = 0;
      defaults.maxItems = null;
      defaults.minLength = 0;
      defaults.maxLength = null;
      defaults.resolveJsonPath = false;
      defaults.reuseProperties = false;
      defaults.fillProperties = true;
      defaults.random = Math.random;
      /**
       * This class defines a registry for custom settings used within JSF.
       */
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var OptionRegistry = /*@__PURE__*/(function (Registry) {
        function OptionRegistry() {
          Registry.call(this);
          this.data = Object.assign({}, defaults);
          this._defaults = defaults;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        if ( Registry ) OptionRegistry.__proto__ = Registry;
        OptionRegistry.prototype = Object.create( Registry && Registry.prototype );
        OptionRegistry.prototype.constructor = OptionRegistry;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        var prototypeAccessors = { defaults: { configurable: true } };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        prototypeAccessors.defaults.get = function () {
          return Object.assign({}, this._defaults);
        };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        Object.defineProperties( OptionRegistry.prototype, prototypeAccessors );
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        return OptionRegistry;
      }(Registry));
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var registry = new OptionRegistry();
      /**
       * Custom option API
       *
       * @param nameOrOptionMap
       * @returns {any}
       */
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      function optionAPI(nameOrOptionMap, optionalValue) {
        if (typeof nameOrOptionMap === 'string') {
          if (typeof optionalValue !== 'undefined') {
            return registry.register(nameOrOptionMap, optionalValue);
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          return registry.get(nameOrOptionMap);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        return registry.registerMany(nameOrOptionMap);
      }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      optionAPI.getDefaults = function () { return registry.defaults; };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var ALL_TYPES = ['array', 'object', 'integer', 'number', 'string', 'boolean', 'null'];
      var MOST_NEAR_DATETIME = 2524608000000;
      var MIN_INTEGER = -100000000;
      var MAX_INTEGER = 100000000;
      var MIN_NUMBER = -100;
      var MAX_NUMBER = 100;
      var env = {
        ALL_TYPES: ALL_TYPES,
        MIN_NUMBER: MIN_NUMBER,
        MAX_NUMBER: MAX_NUMBER,
        MIN_INTEGER: MIN_INTEGER,
        MAX_INTEGER: MAX_INTEGER,
        MOST_NEAR_DATETIME: MOST_NEAR_DATETIME
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      function createCommonjsModule(fn, module) {
      	return module = { exports: {} }, fn(module, module.exports), module.exports;
      }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var types = {
        ROOT       : 0,
        GROUP      : 1,
        POSITION   : 2,
        SET        : 3,
        RANGE      : 4,
        REPETITION : 5,
        REFERENCE  : 6,
        CHAR       : 7,
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      const INTS = () => [{ type: types.RANGE , from: 48, to: 57 }];
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      const WORDS = () => {
        return [
          { type: types.CHAR, value: 95 },
          { type: types.RANGE, from: 97, to: 122 },
          { type: types.RANGE, from: 65, to: 90 }
        ].concat(INTS());
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      const WHITESPACE = () => {
        return [
          { type: types.CHAR, value: 9 },
          { type: types.CHAR, value: 10 },
          { type: types.CHAR, value: 11 },
          { type: types.CHAR, value: 12 },
          { type: types.CHAR, value: 13 },
          { type: types.CHAR, value: 32 },
          { type: types.CHAR, value: 160 },
          { type: types.CHAR, value: 5760 },
          { type: types.RANGE, from: 8192, to: 8202 },
          { type: types.CHAR, value: 8232 },
          { type: types.CHAR, value: 8233 },
          { type: types.CHAR, value: 8239 },
          { type: types.CHAR, value: 8287 },
          { type: types.CHAR, value: 12288 },
          { type: types.CHAR, value: 65279 }
        ];
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      const NOTANYCHAR = () => {
        return [
          { type: types.CHAR, value: 10 },
          { type: types.CHAR, value: 13 },
          { type: types.CHAR, value: 8232 },
          { type: types.CHAR, value: 8233 },
        ];
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      // Predefined class objects.
      var words = () => ({ type: types.SET, set: WORDS(), not: false });
      var notWords = () => ({ type: types.SET, set: WORDS(), not: true });
      var ints = () => ({ type: types.SET, set: INTS(), not: false });
      var notInts = () => ({ type: types.SET, set: INTS(), not: true });
      var whitespace = () => ({ type: types.SET, set: WHITESPACE(), not: false });
      var notWhitespace = () => ({ type: types.SET, set: WHITESPACE(), not: true });
      var anyChar = () => ({ type: types.SET, set: NOTANYCHAR(), not: true });
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var sets = {
      	words: words,
      	notWords: notWords,
      	ints: ints,
      	notInts: notInts,
      	whitespace: whitespace,
      	notWhitespace: notWhitespace,
      	anyChar: anyChar
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var util = createCommonjsModule(function (module, exports) {
      const CTRL = '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ ?';
      const SLSH = { '0': 0, 't': 9, 'n': 10, 'v': 11, 'f': 12, 'r': 13 };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      /**
       * Finds character representations in str and convert all to
       * their respective characters
       *
       * @param {String} str
       * @return {String}
       */
      exports.strToChars = function(str) {
        /* jshint maxlen: false */
        var chars_regex = /(\[\\b\])|(\\)?\\(?:u([A-F0-9]{4})|x([A-F0-9]{2})|(0?[0-7]{2})|c([@A-Z[\\\]^?])|([0tnvfr]))/g;
        str = str.replace(chars_regex, function(s, b, lbs, a16, b16, c8, dctrl, eslsh) {
          if (lbs) {
            return s;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          var code = b ? 8 :
            a16   ? parseInt(a16, 16) :
            b16   ? parseInt(b16, 16) :
            c8    ? parseInt(c8,   8) :
            dctrl ? CTRL.indexOf(dctrl) :
            SLSH[eslsh];
    
          var c = String.fromCharCode(code);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          // Escape special regex characters.
          if (/[[\]{}^$.|?*+()]/.test(c)) {
            c = '\\' + c;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          return c;
        });
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        return str;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      /**
       * turns class into tokens
       * reads str until it encounters a ] not preceeded by a \
       *
       * @param {String} str
       * @param {String} regexpStr
       * @return {Array.<Array.<Object>, Number>}
       */
      exports.tokenizeClass = (str, regexpStr) => {
        /* jshint maxlen: false */
        var tokens = [];
        var regexp = /\\(?:(w)|(d)|(s)|(W)|(D)|(S))|((?:(?:\\)(.)|([^\]\\]))-(?:\\)?([^\]]))|(\])|(?:\\)?([^])/g;
        var rs, c;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        while ((rs = regexp.exec(str)) != null) {
          if (rs[1]) {
            tokens.push(sets.words());
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else if (rs[2]) {
            tokens.push(sets.ints());
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else if (rs[3]) {
            tokens.push(sets.whitespace());
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else if (rs[4]) {
            tokens.push(sets.notWords());
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else if (rs[5]) {
            tokens.push(sets.notInts());
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else if (rs[6]) {
            tokens.push(sets.notWhitespace());
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else if (rs[7]) {
            tokens.push({
              type: types.RANGE,
              from: (rs[8] || rs[9]).charCodeAt(0),
              to: rs[10].charCodeAt(0),
            });
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else if ((c = rs[12])) {
            tokens.push({
              type: types.CHAR,
              value: c.charCodeAt(0),
            });
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else {
            return [tokens, regexp.lastIndex];
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        exports.error(regexpStr, 'Unterminated character class');
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      /**
       * Shortcut to throw errors.
       *
       * @param {String} regexp
       * @param {String} msg
       */
      exports.error = (regexp, msg) => {
        throw new SyntaxError('Invalid regular expression: /' + regexp + '/: ' + msg);
      };
      });
      var util_1 = util.strToChars;
      var util_2 = util.tokenizeClass;
      var util_3 = util.error;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var wordBoundary = () => ({ type: types.POSITION, value: 'b' });
      var nonWordBoundary = () => ({ type: types.POSITION, value: 'B' });
      var begin = () => ({ type: types.POSITION, value: '^' });
      var end = () => ({ type: types.POSITION, value: '$' });
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var positions = {
      	wordBoundary: wordBoundary,
      	nonWordBoundary: nonWordBoundary,
      	begin: begin,
      	end: end
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var lib = (regexpStr) => {
        var i = 0, l, c,
          start = { type: types.ROOT, stack: []},
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          // Keep track of last clause/group and stack.
          lastGroup = start,
          last = start.stack,
          groupStack = [];
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        var repeatErr = (i) => {
          util.error(regexpStr, `Nothing to repeat at column ${i - 1}`);
        };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        // Decode a few escaped characters.
        var str = util.strToChars(regexpStr);
        l = str.length;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        // Iterate through each character in string.
        while (i < l) {
          c = str[i++];
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          switch (c) {
            // Handle escaped characters, inclues a few sets.
            case '\\':
              c = str[i++];
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              switch (c) {
                case 'b':
                  last.push(positions.wordBoundary());
                  break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                case 'B':
                  last.push(positions.nonWordBoundary());
                  break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                case 'w':
                  last.push(sets.words());
                  break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                case 'W':
                  last.push(sets.notWords());
                  break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                case 'd':
                  last.push(sets.ints());
                  break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                case 'D':
                  last.push(sets.notInts());
                  break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                case 's':
                  last.push(sets.whitespace());
                  break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                case 'S':
                  last.push(sets.notWhitespace());
                  break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                default:
                  // Check if c is integer.
                  // In which case it's a reference.
                  if (/\d/.test(c)) {
                    last.push({ type: types.REFERENCE, value: parseInt(c, 10) });
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                  // Escaped character.
                  } else {
                    last.push({ type: types.CHAR, value: c.charCodeAt(0) });
                  }
              }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            // Positionals.
            case '^':
              last.push(positions.begin());
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case '$':
              last.push(positions.end());
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            // Handle custom sets.
            case '[':
              // Check if this class is 'anti' i.e. [^abc].
              var not;
              if (str[i] === '^') {
                not = true;
                i++;
              } else {
                not = false;
              }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // Get all the characters in class.
              var classTokens = util.tokenizeClass(str.slice(i), regexpStr);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // Increase index by length of class.
              i += classTokens[1];
              last.push({
                type: types.SET,
                set: classTokens[0],
                not,
              });
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            // Class of any character except \n.
            case '.':
              last.push(sets.anyChar());
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            // Push group onto stack.
            case '(':
              // Create group.
              var group = {
                type: types.GROUP,
                stack: [],
                remember: true,
              };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              c = str[i];
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // If if this is a special kind of group.
              if (c === '?') {
                c = str[i + 1];
                i += 2;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                // Match if followed by.
                if (c === '=') {
                  group.followedBy = true;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                // Match if not followed by.
                } else if (c === '!') {
                  group.notFollowedBy = true;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                } else if (c !== ':') {
                  util.error(regexpStr,
                    `Invalid group, character '${c}'` +
                    ` after '?' at column ${i - 1}`);
                }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                group.remember = false;
              }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // Insert subgroup into current group stack.
              last.push(group);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // Remember the current group for when the group closes.
              groupStack.push(lastGroup);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // Make this new group the current group.
              lastGroup = group;
              last = group.stack;
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            // Pop group out of stack.
            case ')':
              if (groupStack.length === 0) {
                util.error(regexpStr, `Unmatched ) at column ${i - 1}`);
              }
              lastGroup = groupStack.pop();
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // Check if this group has a PIPE.
              // To get back the correct last stack.
              last = lastGroup.options ?
                lastGroup.options[lastGroup.options.length - 1] : lastGroup.stack;
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            // Use pipe character to give more choices.
            case '|':
              // Create array where options are if this is the first PIPE
              // in this clause.
              if (!lastGroup.options) {
                lastGroup.options = [lastGroup.stack];
                delete lastGroup.stack;
              }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // Create a new stack and add to options for rest of clause.
              var stack = [];
              lastGroup.options.push(stack);
              last = stack;
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            // Repetition.
            // For every repetition, remove last element from last stack
            // then insert back a RANGE object.
            // This design is chosen because there could be more than
            // one repetition symbols in a regex i.e. `a?+{2,3}`.
            case '{':
              var rs = /^(\d+)(,(\d+)?)?\}/.exec(str.slice(i)), min, max;
              if (rs !== null) {
                if (last.length === 0) {
                  repeatErr(i);
                }
                min = parseInt(rs[1], 10);
                max = rs[2] ? rs[3] ? parseInt(rs[3], 10) : Infinity : min;
                i += rs[0].length;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
                last.push({
                  type: types.REPETITION,
                  min,
                  max,
                  value: last.pop(),
                });
              } else {
                last.push({
                  type: types.CHAR,
                  value: 123,
                });
              }
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case '?':
              if (last.length === 0) {
                repeatErr(i);
              }
              last.push({
                type: types.REPETITION,
                min: 0,
                max: 1,
                value: last.pop(),
              });
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case '+':
              if (last.length === 0) {
                repeatErr(i);
              }
              last.push({
                type: types.REPETITION,
                min: 1,
                max: Infinity,
                value: last.pop(),
              });
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case '*':
              if (last.length === 0) {
                repeatErr(i);
              }
              last.push({
                type: types.REPETITION,
                min: 0,
                max: Infinity,
                value: last.pop(),
              });
              break;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            // Default is a character that is not `\[](){}?+*^$`.
            default:
              last.push({
                type: types.CHAR,
                value: c.charCodeAt(0),
              });
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        // Check if any groups have not been closed.
        if (groupStack.length !== 0) {
          util.error(regexpStr, 'Unterminated group');
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        return start;
      };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var types_1 = types;
      lib.types = types_1;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      /* eslint indent: 4 */
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      // Private helper class
      class SubRange {
          constructor(low, high) {
              this.low = low;
              this.high = high;
              this.length = 1 + high - low;
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          overlaps(range) {
              return !(this.high < range.low || this.low > range.high);
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          touches(range) {
              return !(this.high + 1 < range.low || this.low - 1 > range.high);
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          // Returns inclusive combination of SubRanges as a SubRange.
          add(range) {
              return new SubRange(
                  Math.min(this.low, range.low),
                  Math.max(this.high, range.high)
              );
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          // Returns subtraction of SubRanges as an array of SubRanges.
          // (There's a case where subtraction divides it in 2)
          subtract(range) {
              if (range.low <= this.low && range.high >= this.high) {
                  return [];
              } else if (range.low > this.low && range.high < this.high) {
                  return [
                      new SubRange(this.low, range.low - 1),
                      new SubRange(range.high + 1, this.high)
                  ];
              } else if (range.low <= this.low) {
                  return [new SubRange(range.high + 1, this.high)];
              } else {
                  return [new SubRange(this.low, range.low - 1)];
              }
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          toString() {
              return this.low == this.high ?
                  this.low.toString() : this.low + '-' + this.high;
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      class DRange {
          constructor(a, b) {
              this.ranges = [];
              this.length = 0;
              if (a != null) this.add(a, b);
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          _update_length() {
              this.length = this.ranges.reduce((previous, range) => {
                  return previous + range.length;
              }, 0);
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          add(a, b) {
              var _add = (subrange) => {
                  var i = 0;
                  while (i < this.ranges.length && !subrange.touches(this.ranges[i])) {
                      i++;
                  }
                  var newRanges = this.ranges.slice(0, i);
                  while (i < this.ranges.length && subrange.touches(this.ranges[i])) {
                      subrange = subrange.add(this.ranges[i]);
                      i++;
                  }
                  newRanges.push(subrange);
                  this.ranges = newRanges.concat(this.ranges.slice(i));
                  this._update_length();
              };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              if (a instanceof DRange) {
                  a.ranges.forEach(_add);
              } else {
                  if (b == null) b = a;
                  _add(new SubRange(a, b));
              }
              return this;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          subtract(a, b) {
              var _subtract = (subrange) => {
                  var i = 0;
                  while (i < this.ranges.length && !subrange.overlaps(this.ranges[i])) {
                      i++;
                  }
                  var newRanges = this.ranges.slice(0, i);
                  while (i < this.ranges.length && subrange.overlaps(this.ranges[i])) {
                      newRanges = newRanges.concat(this.ranges[i].subtract(subrange));
                      i++;
                  }
                  this.ranges = newRanges.concat(this.ranges.slice(i));
                  this._update_length();
              };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              if (a instanceof DRange) {
                  a.ranges.forEach(_subtract);
              } else {
                  if (b == null) b = a;
                  _subtract(new SubRange(a, b));
              }
              return this;
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          intersect(a, b) {
              var newRanges = [];
              var _intersect = (subrange) => {
                  var i = 0;
                  while (i < this.ranges.length && !subrange.overlaps(this.ranges[i])) {
                      i++;
                  }
                  while (i < this.ranges.length && subrange.overlaps(this.ranges[i])) {
                      var low = Math.max(this.ranges[i].low, subrange.low);
                      var high = Math.min(this.ranges[i].high, subrange.high);
                      newRanges.push(new SubRange(low, high));
                      i++;
                  }
              };
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              if (a instanceof DRange) {
                  a.ranges.forEach(_intersect);
              } else {
                  if (b == null) b = a;
                  _intersect(new SubRange(a, b));
              }
              this.ranges = newRanges;
              this._update_length();
              return this;
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          index(index) {
              var i = 0;
              while (i < this.ranges.length && this.ranges[i].length <= index) {
                  index -= this.ranges[i].length;
                  i++;
              }
              return this.ranges[i].low + index;
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          toString() {
              return '[ ' + this.ranges.join(', ') + ' ]';
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          clone() {
              return new DRange(this);
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var lib$1 = DRange;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      const types$1  = lib.types;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
      var randexp = class RandExp {
        /**
         * @constructor
         * @param {RegExp|String} regexp
         * @param {String} m
         */
        constructor(regexp, m) {
          this._setDefaults(regexp);
          if (regexp instanceof RegExp) {
            this.ignoreCase = regexp.ignoreCase;
            this.multiline = regexp.multiline;
            regexp = regexp.source;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          } else if (typeof regexp === 'string') {
            this.ignoreCase = m && m.indexOf('i') !== -1;
            this.multiline = m && m.indexOf('m') !== -1;
          } else {
            throw new Error('Expected a regexp or string');
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          this.tokens = lib(regexp);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**
         * Checks if some custom properties have been set for this regexp.
         *
         * @param {RandExp} randexp
         * @param {RegExp} regexp
         */
        _setDefaults(regexp) {
          // When a repetitional token has its max set to Infinite,
          // randexp won't actually generate a random amount between min and Infinite
          // instead it will see Infinite as min + 100.
          this.max = regexp.max != null ? regexp.max :
            RandExp.prototype.max != null ? RandExp.prototype.max : 100;
    
          // This allows expanding to include additional characters
          // for instance: RandExp.defaultRange.add(0, 65535);
          this.defaultRange = regexp.defaultRange ?
            regexp.defaultRange : this.defaultRange.clone();
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          if (regexp.randInt) {
            this.randInt = regexp.randInt;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**
         * Generates the random string.
         *
         * @return {String}
         */
        gen() {
          return this._gen(this.tokens, []);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**
         * Generate random string modeled after given tokens.
         *
         * @param {Object} token
         * @param {Array.<String>} groups
         * @return {String}
         */
        _gen(token, groups) {
          var stack, str, n, i, l;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          switch (token.type) {
            case types$1.ROOT:
            case types$1.GROUP:
              // Ignore lookaheads for now.
              if (token.followedBy || token.notFollowedBy) { return ''; }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              // Insert placeholder until group string is generated.
              if (token.remember && token.groupNumber === undefined) {
                token.groupNumber = groups.push(null) - 1;
              }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              stack = token.options ?
                this._randSelect(token.options) : token.stack;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              str = '';
              for (i = 0, l = stack.length; i < l; i++) {
                str += this._gen(stack[i], groups);
              }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              if (token.remember) {
                groups[token.groupNumber] = str;
              }
              return str;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case types$1.POSITION:
              // Do nothing for now.
              return '';
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case types$1.SET:
              var expandedSet = this._expand(token);
              if (!expandedSet.length) { return ''; }
              return String.fromCharCode(this._randSelect(expandedSet));
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case types$1.REPETITION:
              // Randomly generate number between min and max.
              n = this.randInt(token.min,
                token.max === Infinity ? token.min + this.max : token.max);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              str = '';
              for (i = 0; i < n; i++) {
                str += this._gen(token.value, groups);
              }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
              return str;
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case types$1.REFERENCE:
              return groups[token.value - 1] || '';
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            case types$1.CHAR:
              var code = this.ignoreCase && this._randBool() ?
                this._toOtherCase(token.value) : token.value;
              return String.fromCharCode(code);
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**
         * If code is alphabetic, converts to other case.
         * If not alphabetic, returns back code.
         *
         * @param {Number} code
         * @return {Number}
         */
        _toOtherCase(code) {
          return code + (97 <= code && code <= 122 ? -32 :
            65 <= code && code <= 90  ?  32 : 0);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**
         * Randomly returns a true or false value.
         *
         * @return {Boolean}
         */
        _randBool() {
          return !this.randInt(0, 1);
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**
         * Randomly selects and returns a value from the array.
         *
         * @param {Array.<Object>} arr
         * @return {Object}
         */
        _randSelect(arr) {
          if (arr instanceof lib$1) {
            return arr.index(this.randInt(0, arr.length - 1));
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
          return arr[this.randInt(0, arr.length - 1)];
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**
         * expands a token to a DiscontinuousRange of characters which has a
         * length and an index function (for random selecting)
         *
         * @param {Object} token
         * @return {DiscontinuousRange}
         */
        _expand(token) {
          if (token.type === lib.types.CHAR) {
            return new lib$1(token.value);
          } else if (token.type === lib.types.RANGE) {
            return new lib$1(token.from, token.to);
          } else {
            let drange = new lib$1();
            for (let i = 0; i < token.set.length; i++) {
              let subrange = this._expand(token.set[i]);
              drange.add(subrange);
              if (this.ignoreCase) {
                for (let j = 0; j < subrange.length; j++) {
                  let code = subrange.index(j);
                  let otherCaseCode = this._toOtherCase(code);
                  if (code !== otherCaseCode) {
                    drange.add(otherCaseCode);
                  }
                }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
            if (token.not) {
              return this.defaultRange.clone().subtract(drange);
            } else {
              return this.defaultRange.clone().intersect(drange);
            }
          }
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**
         * Randomly generates and returns a number between a and b (inclusive).
         *
         * @param {Number} a
         * @param {Number} b
         * @return {Number}
         */
        randInt(a, b) {
          return a + Math.floor(Math.random() * (1 + b - a));
    
    Alvaro Cabrera Durán's avatar
    Alvaro Cabrera Durán committed
        /**