You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
3.6 KiB
171 lines
3.6 KiB
/*! |
|
* split-string <https://github.com/jonschlinkert/split-string> |
|
* |
|
* Copyright (c) 2015-2017, Jon Schlinkert. |
|
* Released under the MIT License. |
|
*/ |
|
|
|
'use strict'; |
|
|
|
var extend = require('extend-shallow'); |
|
|
|
module.exports = function(str, options, fn) { |
|
if (typeof str !== 'string') { |
|
throw new TypeError('expected a string'); |
|
} |
|
|
|
if (typeof options === 'function') { |
|
fn = options; |
|
options = null; |
|
} |
|
|
|
// allow separator to be defined as a string |
|
if (typeof options === 'string') { |
|
options = { sep: options }; |
|
} |
|
|
|
var opts = extend({sep: '.'}, options); |
|
var quotes = opts.quotes || ['"', "'", '`']; |
|
var brackets; |
|
|
|
if (opts.brackets === true) { |
|
brackets = { |
|
'<': '>', |
|
'(': ')', |
|
'[': ']', |
|
'{': '}' |
|
}; |
|
} else if (opts.brackets) { |
|
brackets = opts.brackets; |
|
} |
|
|
|
var tokens = []; |
|
var stack = []; |
|
var arr = ['']; |
|
var sep = opts.sep; |
|
var len = str.length; |
|
var idx = -1; |
|
var closeIdx; |
|
|
|
function expected() { |
|
if (brackets && stack.length) { |
|
return brackets[stack[stack.length - 1]]; |
|
} |
|
} |
|
|
|
while (++idx < len) { |
|
var ch = str[idx]; |
|
var next = str[idx + 1]; |
|
var tok = { val: ch, idx: idx, arr: arr, str: str }; |
|
tokens.push(tok); |
|
|
|
if (ch === '\\') { |
|
tok.val = keepEscaping(opts, str, idx) === true ? (ch + next) : next; |
|
tok.escaped = true; |
|
if (typeof fn === 'function') { |
|
fn(tok); |
|
} |
|
arr[arr.length - 1] += tok.val; |
|
idx++; |
|
continue; |
|
} |
|
|
|
if (brackets && brackets[ch]) { |
|
stack.push(ch); |
|
var e = expected(); |
|
var i = idx + 1; |
|
|
|
if (str.indexOf(e, i + 1) !== -1) { |
|
while (stack.length && i < len) { |
|
var s = str[++i]; |
|
if (s === '\\') { |
|
s++; |
|
continue; |
|
} |
|
|
|
if (quotes.indexOf(s) !== -1) { |
|
i = getClosingQuote(str, s, i + 1); |
|
continue; |
|
} |
|
|
|
e = expected(); |
|
if (stack.length && str.indexOf(e, i + 1) === -1) { |
|
break; |
|
} |
|
|
|
if (brackets[s]) { |
|
stack.push(s); |
|
continue; |
|
} |
|
|
|
if (e === s) { |
|
stack.pop(); |
|
} |
|
} |
|
} |
|
|
|
closeIdx = i; |
|
if (closeIdx === -1) { |
|
arr[arr.length - 1] += ch; |
|
continue; |
|
} |
|
|
|
ch = str.slice(idx, closeIdx + 1); |
|
tok.val = ch; |
|
tok.idx = idx = closeIdx; |
|
} |
|
|
|
if (quotes.indexOf(ch) !== -1) { |
|
closeIdx = getClosingQuote(str, ch, idx + 1); |
|
if (closeIdx === -1) { |
|
arr[arr.length - 1] += ch; |
|
continue; |
|
} |
|
|
|
if (keepQuotes(ch, opts) === true) { |
|
ch = str.slice(idx, closeIdx + 1); |
|
} else { |
|
ch = str.slice(idx + 1, closeIdx); |
|
} |
|
|
|
tok.val = ch; |
|
tok.idx = idx = closeIdx; |
|
} |
|
|
|
if (typeof fn === 'function') { |
|
fn(tok, tokens); |
|
ch = tok.val; |
|
idx = tok.idx; |
|
} |
|
|
|
if (tok.val === sep && tok.split !== false) { |
|
arr.push(''); |
|
continue; |
|
} |
|
|
|
arr[arr.length - 1] += tok.val; |
|
} |
|
|
|
return arr; |
|
}; |
|
|
|
function getClosingQuote(str, ch, i, brackets) { |
|
var idx = str.indexOf(ch, i); |
|
if (str.charAt(idx - 1) === '\\') { |
|
return getClosingQuote(str, ch, idx + 1); |
|
} |
|
return idx; |
|
} |
|
|
|
function keepQuotes(ch, opts) { |
|
if (opts.keepDoubleQuotes === true && ch === '"') return true; |
|
if (opts.keepSingleQuotes === true && ch === "'") return true; |
|
return opts.keepQuotes; |
|
} |
|
|
|
function keepEscaping(opts, str, idx) { |
|
if (typeof opts.keepEscaping === 'function') { |
|
return opts.keepEscaping(str, idx); |
|
} |
|
return opts.keepEscaping === true || str[idx + 1] === '\\'; |
|
}
|
|
|