'use strict'; 
 | 
  
 | 
const fill = require('fill-range'); 
 | 
const stringify = require('./stringify'); 
 | 
const utils = require('./utils'); 
 | 
  
 | 
const append = (queue = '', stash = '', enclose = false) => { 
 | 
  let result = []; 
 | 
  
 | 
  queue = [].concat(queue); 
 | 
  stash = [].concat(stash); 
 | 
  
 | 
  if (!stash.length) return queue; 
 | 
  if (!queue.length) { 
 | 
    return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; 
 | 
  } 
 | 
  
 | 
  for (let item of queue) { 
 | 
    if (Array.isArray(item)) { 
 | 
      for (let value of item) { 
 | 
        result.push(append(value, stash, enclose)); 
 | 
      } 
 | 
    } else { 
 | 
      for (let ele of stash) { 
 | 
        if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; 
 | 
        result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele)); 
 | 
      } 
 | 
    } 
 | 
  } 
 | 
  return utils.flatten(result); 
 | 
}; 
 | 
  
 | 
const expand = (ast, options = {}) => { 
 | 
  let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; 
 | 
  
 | 
  let walk = (node, parent = {}) => { 
 | 
    node.queue = []; 
 | 
  
 | 
    let p = parent; 
 | 
    let q = parent.queue; 
 | 
  
 | 
    while (p.type !== 'brace' && p.type !== 'root' && p.parent) { 
 | 
      p = p.parent; 
 | 
      q = p.queue; 
 | 
    } 
 | 
  
 | 
    if (node.invalid || node.dollar) { 
 | 
      q.push(append(q.pop(), stringify(node, options))); 
 | 
      return; 
 | 
    } 
 | 
  
 | 
    if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { 
 | 
      q.push(append(q.pop(), ['{}'])); 
 | 
      return; 
 | 
    } 
 | 
  
 | 
    if (node.nodes && node.ranges > 0) { 
 | 
      let args = utils.reduce(node.nodes); 
 | 
  
 | 
      if (utils.exceedsLimit(...args, options.step, rangeLimit)) { 
 | 
        throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); 
 | 
      } 
 | 
  
 | 
      let range = fill(...args, options); 
 | 
      if (range.length === 0) { 
 | 
        range = stringify(node, options); 
 | 
      } 
 | 
  
 | 
      q.push(append(q.pop(), range)); 
 | 
      node.nodes = []; 
 | 
      return; 
 | 
    } 
 | 
  
 | 
    let enclose = utils.encloseBrace(node); 
 | 
    let queue = node.queue; 
 | 
    let block = node; 
 | 
  
 | 
    while (block.type !== 'brace' && block.type !== 'root' && block.parent) { 
 | 
      block = block.parent; 
 | 
      queue = block.queue; 
 | 
    } 
 | 
  
 | 
    for (let i = 0; i < node.nodes.length; i++) { 
 | 
      let child = node.nodes[i]; 
 | 
  
 | 
      if (child.type === 'comma' && node.type === 'brace') { 
 | 
        if (i === 1) queue.push(''); 
 | 
        queue.push(''); 
 | 
        continue; 
 | 
      } 
 | 
  
 | 
      if (child.type === 'close') { 
 | 
        q.push(append(q.pop(), queue, enclose)); 
 | 
        continue; 
 | 
      } 
 | 
  
 | 
      if (child.value && child.type !== 'open') { 
 | 
        queue.push(append(queue.pop(), child.value)); 
 | 
        continue; 
 | 
      } 
 | 
  
 | 
      if (child.nodes) { 
 | 
        walk(child, node); 
 | 
      } 
 | 
    } 
 | 
  
 | 
    return queue; 
 | 
  }; 
 | 
  
 | 
  return utils.flatten(walk(ast)); 
 | 
}; 
 | 
  
 | 
module.exports = expand; 
 |