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