index.js
 1  'use strict';
 2  module.exports = balanced;
 3  function balanced(a, b, str) {
 4    if (a instanceof RegExp) a = maybeMatch(a, str);
 5    if (b instanceof RegExp) b = maybeMatch(b, str);
 6  
 7    var r = range(a, b, str);
 8  
 9    return r && {
10      start: r[0],
11      end: r[1],
12      pre: str.slice(0, r[0]),
13      body: str.slice(r[0] + a.length, r[1]),
14      post: str.slice(r[1] + b.length)
15    };
16  }
17  
18  function maybeMatch(reg, str) {
19    var m = str.match(reg);
20    return m ? m[0] : null;
21  }
22  
23  balanced.range = range;
24  function range(a, b, str) {
25    var begs, beg, left, right, result;
26    var ai = str.indexOf(a);
27    var bi = str.indexOf(b, ai + 1);
28    var i = ai;
29  
30    if (ai >= 0 && bi > 0) {
31      if(a===b) {
32        return [ai, bi];
33      }
34      begs = [];
35      left = str.length;
36  
37      while (i >= 0 && !result) {
38        if (i == ai) {
39          begs.push(i);
40          ai = str.indexOf(a, i + 1);
41        } else if (begs.length == 1) {
42          result = [ begs.pop(), bi ];
43        } else {
44          beg = begs.pop();
45          if (beg < left) {
46            left = beg;
47            right = bi;
48          }
49  
50          bi = str.indexOf(b, i + 1);
51        }
52  
53        i = ai < bi && ai >= 0 ? ai : bi;
54      }
55  
56      if (begs.length) {
57        result = [ left, right ];
58      }
59    }
60  
61    return result;
62  }