compile.js
 1  'use strict';
 2  
 3  const fill = require('fill-range');
 4  const utils = require('./utils');
 5  
 6  const compile = (ast, options = {}) => {
 7    let walk = (node, parent = {}) => {
 8      let invalidBlock = utils.isInvalidBrace(parent);
 9      let invalidNode = node.invalid === true && options.escapeInvalid === true;
10      let invalid = invalidBlock === true || invalidNode === true;
11      let prefix = options.escapeInvalid === true ? '\\' : '';
12      let output = '';
13  
14      if (node.isOpen === true) {
15        return prefix + node.value;
16      }
17      if (node.isClose === true) {
18        return prefix + node.value;
19      }
20  
21      if (node.type === 'open') {
22        return invalid ? (prefix + node.value) : '(';
23      }
24  
25      if (node.type === 'close') {
26        return invalid ? (prefix + node.value) : ')';
27      }
28  
29      if (node.type === 'comma') {
30        return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|');
31      }
32  
33      if (node.value) {
34        return node.value;
35      }
36  
37      if (node.nodes && node.ranges > 0) {
38        let args = utils.reduce(node.nodes);
39        let range = fill(...args, { ...options, wrap: false, toRegex: true });
40  
41        if (range.length !== 0) {
42          return args.length > 1 && range.length > 1 ? `(${range})` : range;
43        }
44      }
45  
46      if (node.nodes) {
47        for (let child of node.nodes) {
48          output += walk(child, node);
49        }
50      }
51      return output;
52    };
53  
54    return walk(ast);
55  };
56  
57  module.exports = compile;