AK-21/Graphite-Industrial-Intelligence
0
1'use strict';2 3const fill = require('fill-range');4const stringify = require('./stringify');5const utils = require('./utils');6 7const append = (queue = '', stash = '', enclose = false) => {8 const result = [];9 10 queue = [].concat(queue);11 stash = [].concat(stash);12 13 if (!stash.length) return queue;14 if (!queue.length) {15 return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash;16 }17 18 for (const item of queue) {19 if (Array.isArray(item)) {20 for (const value of item) {21 result.push(append(value, stash, enclose));22 }23 } else {24 for (let ele of stash) {25 if (enclose === true && typeof ele === 'string') ele = `{${ele}}`;26 result.push(Array.isArray(ele) ? append(item, ele, enclose) : item + ele);27 }28 }29 }30 return utils.flatten(result);31};32 33const expand = (ast, options = {}) => {34 const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit;35 36 const walk = (node, parent = {}) => {37 node.queue = [];38 39 let p = parent;40 let q = parent.queue;41 42 while (p.type !== 'brace' && p.type !== 'root' && p.parent) {43 p = p.parent;44 q = p.queue;45 }46 47 if (node.invalid || node.dollar) {48 q.push(append(q.pop(), stringify(node, options)));49 return;50 }51 52 if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) {53 q.push(append(q.pop(), ['{}']));54 return;55 }56 57 if (node.nodes && node.ranges > 0) {58 const args = utils.reduce(node.nodes);59 60 if (utils.exceedsLimit(...args, options.step, rangeLimit)) {61 throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');62 }63 64 let range = fill(...args, options);65 if (range.length === 0) {66 range = stringify(node, options);67 }68 69 q.push(append(q.pop(), range));70 node.nodes = [];71 return;72 }73 74 const enclose = utils.encloseBrace(node);75 let queue = node.queue;76 let block = node;77 78 while (block.type !== 'brace' && block.type !== 'root' && block.parent) {79 block = block.parent;80 queue = block.queue;81 }82 83 for (let i = 0; i < node.nodes.length; i++) {84 const child = node.nodes[i];85 86 if (child.type === 'comma' && node.type === 'brace') {87 if (i === 1) queue.push('');88 queue.push('');89 continue;90 }91 92 if (child.type === 'close') {93 q.push(append(q.pop(), queue, enclose));94 continue;95 }96 97 if (child.value && child.type !== 'open') {98 queue.push(append(queue.pop(), child.value));99 continue;100 }101 102 if (child.nodes) {103 walk(child, node);104 }105 }106 107 return queue;108 };109 110 return utils.flatten(walk(ast));111};112 113module.exports = expand;114 