/*! * 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] === '\\'; }