Socket
Socket
Sign inDemoInstall

split-string

Package Overview
Dependencies
8
Maintainers
2
Versions
19
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.0.0 to 5.0.0

293

index.js
/*!
* split-string <https://github.com/jonschlinkert/split-string>
*
* Copyright (c) 2015-2017, Jon Schlinkert.
* Copyright (c) 2015-2018, Jon Schlinkert.
* Released under the MIT License.

@@ -10,3 +10,8 @@ */

var extend = require('extend-shallow');
const Lexer = require('snapdragon-lexer');
const union = require('arr-union');
const defaults = {
brackets: { '<': '>', '(': ')', '[': ']', '{': '}' },
quotes: { '"': '"', "'": "'", '`': '`', '“': '”' }
};

@@ -23,163 +28,197 @@ module.exports = function(str, options, fn) {

// allow separator to be defined as a string
if (typeof options === 'string') {
options = { sep: options };
}
var opts = extend({sep: '.'}, options);
var quotes = opts.quotes || {
'"': '"',
"'": "'",
'`': '`',
'“': '”'
const opts = Object.assign({ separator: '.' }, options);
const sep = opts.sep || opts.separator;
const lexer = new Lexer(str, opts);
lexer.split = (token) => {
if (typeof lexer.options.split === 'function') {
return lexer.options.split.call(lexer, token);
}
return true;
};
if (Array.isArray(quotes)) {
quotes = quotes.reduce(function(acc, ele) {
acc[ele] = ele;
return acc;
}, {});
}
// brackets support
const brackets = opts.brackets === true ? defaults.brackets : opts.brackets;
var brackets;
if (opts.brackets === true) {
brackets = {
'<': '>',
'(': ')',
'[': ']',
'{': '}'
};
} else if (opts.brackets) {
brackets = opts.brackets;
}
// quotes support
const quotes = opts.quotes === true || typeof opts.quotes === 'undefined'
? defaults.quotes
: opts.quotes;
var tokens = [];
var stack = [];
var arr = [''];
var sep = opts.sep;
var len = str.length;
var idx = -1;
var closeIdx;
const openChars = brackets ? Object.keys(brackets) : [];
const closeChars = brackets ? Object.values(brackets) : [];
const quoteChars = union(Object.keys(quotes), Object.values(quotes));
const openStr = brackets ? escape(openChars) : '';
const closeStr = brackets ? escape(closeChars) : '';
const quoteStr = quotes ? escape(quoteChars) : '';
const textRegexp = new RegExp(`^[^\\\\${sep + openStr + closeStr + quoteStr}]+`);
function expected() {
if (brackets && stack.length) {
return brackets[stack[stack.length - 1]];
/**
* Handlers
*/
lexer.capture('escape', /^\\(.)/, function(token) {
token.escaped = true;
if (opts.keepEscaping !== true && token.value !== '\\\\') {
token.value = token.value.slice(1);
}
}
if (fn) fn.call(this, token);
return token;
});
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);
lexer.capture('separator', toRegexp(escape(sep.split(''))), function(token) {
if (fn) fn.call(this, token);
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 (typeof token.split === 'function' && token.split() === false) {
return token;
}
if (lexer.split(token) === false) {
return token;
}
if (brackets && brackets[ch]) {
stack.push(ch);
var e = expected();
var i = idx + 1;
if (!this.stack.length && this.last(this.stash) !== '') {
this.stash.push('');
}
if (!this.isInside('quote') && !this.isInside('bracket')) {
token.value = '';
}
return token;
});
if (str.indexOf(e, i + 1) !== -1) {
while (stack.length && i < len) {
var s = str[++i];
if (s === '\\') {
s++;
continue;
}
lexer.capture('text', textRegexp, (token) => {
if (fn) fn.call(lexer, token);
return token;
});
if (quotes[s]) {
i = getClosingQuote(str, quotes[s], i + 1);
continue;
}
if (quotes) {
lexer.capture('quote', toRegexp(quoteStr), function(token) {
if (this.isInside('bracket')) return token;
e = expected();
if (stack.length && str.indexOf(e, i + 1) === -1) {
break;
}
let val = token.match[0];
token.append = false;
if (brackets[s]) {
stack.push(s);
continue;
}
if (e === s) {
stack.pop();
}
}
if (!keepQuotes(val, opts)) {
token.value = '';
}
closeIdx = i;
if (closeIdx === -1) {
arr[arr.length - 1] += ch;
continue;
}
if (this.isClose(val)) {
const open = this.stack.pop();
open.closed = true;
this.unwind(open, true);
this.append(token.value);
ch = str.slice(idx, closeIdx + 1);
tok.val = ch;
tok.idx = idx = closeIdx;
}
if (quotes[ch]) {
closeIdx = getClosingQuote(str, quotes[ch], idx + 1);
if (closeIdx === -1) {
arr[arr.length - 1] += ch;
continue;
} else {
token.isClose = value => value === quotes[val];
token.queue = [];
this.stack.push(token);
}
return token;
});
}
if (keepQuotes(ch, opts) === true) {
ch = str.slice(idx, closeIdx + 1);
} else {
ch = str.slice(idx + 1, closeIdx);
if (brackets) {
lexer.capture('bracket', toRegexp(openStr), function(token) {
token.isClose = value => value === brackets[token.value];
token.append = false;
token.queue = [];
this.stack.push(token);
return token;
});
lexer.capture('bracket.close', toRegexp(closeStr), function(token) {
if (this.isClose(token.value)) {
const open = this.stack.pop();
open.value += open.queue.join('');
this.append(open.value);
}
return token;
});
}
tok.val = ch;
tok.idx = idx = closeIdx;
/**
* Custom lexer methods
*/
lexer.isClose = function(ch) {
const open = this.stack.last;
if (open && typeof open.isClose === 'function') {
return open.isClose(ch);
}
};
if (typeof fn === 'function') {
fn(tok, tokens);
ch = tok.val;
idx = tok.idx;
lexer.append = function(val) {
if (!val) return;
const last = this.stack.last;
if (last && Array.isArray(last.queue)) {
last.queue.push(val);
} else {
this.stash[this.stash.length - 1] += val;
}
};
if (tok.val === sep && tok.split !== false) {
arr.push('');
continue;
// add queued strings back to the stash
lexer.unwind = function(token, append) {
switch (token && token.type) {
case 'bracket':
const segs = token.queue.join('').split('.');
this.append(token.value);
this.append(segs.shift());
this.stash = this.stash.concat(segs);
break;
case 'quote':
const quote = token.closed && !keepQuotes(token.match[0], opts) ? '' : token.match[0];
this.append(quote);
this.append(token.queue.shift());
while (token.queue.length) {
const val = token.queue.shift();
if (append) {
this.append(val);
continue;
}
if (val !== sep) {
this.stash.push(val);
}
}
break;
default: {
break;
}
}
};
arr[arr.length - 1] += tok.val;
// start tokenizing
lexer.tokenize(str);
// ensure the stack is empty
if (lexer.options.strict === true) {
lexer.fail();
}
return arr;
lexer.unwind(lexer.stack.pop());
lexer.fail();
return lexer.stash;
};
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 toRegexp(str) {
return new RegExp(`^(?=.)[${str}]`);
}
function keepQuotes(ch, opts) {
if (opts.keepDoubleQuotes === true && (ch === '"' || ch === '“' || ch === '”')) return true;
if (opts.keepSingleQuotes === true && ch === "'") return true;
return opts.keepQuotes;
function escape(arr) {
return '\\' + arr.join('\\');
}
function keepEscaping(opts, str, idx) {
if (typeof opts.keepEscaping === 'function') {
return opts.keepEscaping(str, idx);
function keepQuotes(ch, opts) {
if (opts.keepSmartQuotes === true && (ch === '“' || ch === '”')) {
return true;
}
return opts.keepEscaping === true || str[idx + 1] === '\\';
if (opts.keepDoubleQuotes === true && ch === '"') {
return true;
}
if (opts.keepSingleQuotes === true && ch === '\'') {
return true;
}
if (opts.keepBackticks === true && ch === '`') {
return true;
}
return opts.keepQuotes;
}
{
"name": "split-string",
"description": "Split a string on a character except when the character is escaped.",
"version": "4.0.0",
"version": "5.0.0",
"homepage": "https://github.com/jonschlinkert/split-string",

@@ -24,10 +24,12 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)",

"scripts": {
"test": "mocha"
"test": "nyc mocha"
},
"dependencies": {
"extend-shallow": "^3.0.0"
"arr-union": "^3.1.0",
"snapdragon-lexer": "^2.0.0"
},
"devDependencies": {
"mocha": "^3.5.3",
"gulp-format-md": "^1.0.0",
"mocha": "^3.5.3"
"nyc": "^11.4.1"
},

@@ -40,2 +42,8 @@ "keywords": [

],
"nyc": {
"reporter": [
"lcov",
"text-summary"
]
},
"verb": {

@@ -42,0 +50,0 @@ "toc": false,

@@ -31,3 +31,3 @@ # split-string [![NPM version](https://img.shields.io/npm/v/split-string.svg?style=flat)](https://www.npmjs.com/package/split-string) [![NPM monthly downloads](https://img.shields.io/npm/dm/split-string.svg?style=flat)](https://npmjs.org/package/split-string) [![NPM total downloads](https://img.shields.io/npm/dt/split-string.svg?style=flat)](https://npmjs.org/package/split-string) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/split-string.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/split-string)

**Bad**
**This is bad**

@@ -42,3 +42,3 @@ ```js

**Good**
**This is good**

@@ -124,8 +124,10 @@ ```js

// support only the specified brackets
split('[a.b].(c.d)', {brackets: {'[': ']'}});
//=> [ '[a.b]', '(c', 'd)' ]
// support only the specified bracket types
split('«a.b».⟨c.d⟩', {brackets: {'«': '»', '⟨': '⟩'}});
//=> [ '«a.b»', '⟨c.d⟩' ]
split('a.{a.[{b.c}].d}.e', {brackets: {'[': ']'}});
//=> [ 'a', '{a', '[{b.c}]', 'd}', 'e' ]
```
### options.sep
### options.separator

@@ -136,3 +138,3 @@ **Type**: `string`

The separator/character to split on.
The separator/character to split on. Aliased as `options.sep` for backwards compatibility with versions <4.0.

@@ -142,6 +144,6 @@ **Example**

```js
split('a.b,c', {sep: ','});
split('a.b,c', {separator: ','});
//=> ['a.b', 'c']
// you can also pass the separator as string as the last argument
// you can also pass the separator as a string as the last argument
split('a.b,c', ',');

@@ -237,8 +239,8 @@ //=> ['a.b', 'c']

```js
var arr = split('a.b', function(tok) {
if (tok.arr[tok.arr.length - 1] === 'a') {
tok.split = false;
var res = split('a.b', function(token) {
if (token.tokens[0] === 'a') {
token.split = false;
}
});
console.log(arr);
console.log(res);
//=> ['a.b']

@@ -249,11 +251,17 @@ ```

The `tok` object has the following properties:
The `token` object has the following properties:
* `tok.val` (string) The current value about to be pushed onto the result array
* `tok.idx` (number) the current index in the string
* `tok.str` (string) the entire string
* `tok.arr` (array) the result array
* `token.val` (string) The current value about to be pushed onto the result array
* `token.index` (number) the current index in the string
* `token.input` (string) the entire input string
* `token.tokens` (array) the result array
## Release history
### v4.0.0 - 2017-11-22
**Changed**
* `options.quotes` should now be formatted as an object
### v3.0.0 - 2017-06-17

@@ -284,3 +292,2 @@

</details>
<details>

@@ -312,3 +319,3 @@ <summary><strong>Building docs</strong></summary>

| --- | --- |
| 34 | [jonschlinkert](https://github.com/jonschlinkert) |
| 36 | [jonschlinkert](https://github.com/jonschlinkert) |
| 10 | [doowb](https://github.com/doowb) |

@@ -320,2 +327,3 @@

* [linkedin/in/jonschlinkert](https://linkedin.com/in/jonschlinkert)
* [github/jonschlinkert](https://github.com/jonschlinkert)

@@ -326,3 +334,3 @@ * [twitter/jonschlinkert](https://twitter.com/jonschlinkert)

Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT License](LICENSE).

@@ -332,2 +340,2 @@

_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on November 22, 2017._
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on January 08, 2018._

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc