js-restructure
Advanced tools
Comparing version 1.1.0 to 1.1.1
58
index.js
@@ -1,2 +0,4 @@ | ||
module.exports = function matcher(obj, flags) { | ||
module.exports = matcher; | ||
function matcher(obj, flags) { | ||
"use strict"; | ||
@@ -7,21 +9,6 @@ var props = Object.getOwnPropertyNames(obj); | ||
if(!isNaN(c)) { | ||
throw new TypeError("Objects with numeric keys are not supported."+ | ||
"Got object with key: "+c); | ||
} | ||
var val = obj[c]; | ||
// convert objects that are not matchers or REs to nested parsers | ||
if (Object(val) === val && !val.re && !val.source) { | ||
val = matcher(val); | ||
throw new TypeError("Objects with numeric keys are not supported." + | ||
"Got object with key: " + c + " for object: " + obj); | ||
} | ||
if(val.re) { | ||
// accept parser arguments, | ||
parserArgs.push(val); // add the parser | ||
val = val._nonCapturingRe; // don't capture for re arguments. | ||
} else if (val.source) { | ||
val = val.source; // accept RE arguments | ||
} else { | ||
parserArgs.push(null); | ||
} | ||
var val = getVal(obj, c, parserArgs); | ||
if(c[0] === "_") return p + val; | ||
@@ -31,10 +18,7 @@ else return p + "(" + val + ")"; | ||
var _nonCapturingRe = props.reduce( function(prev, cur) { | ||
return prev + obj[cur]; | ||
}, ""); | ||
var _nonCapturingRe = props.map(function(p) { return obj[p]; }).join(""); | ||
props = props.filter(function(x) { return x[0] !== "_"; }); | ||
var parser = function(pattern) { | ||
var parser = function(str) { | ||
var o = {}; | ||
var res = re.exec(pattern); | ||
var res = re.exec(str); | ||
if(res === null) return null; | ||
@@ -53,2 +37,24 @@ for(var i = 0; i < res.length; i++) { | ||
return parser; | ||
}; | ||
} | ||
function getVal(obj, prop, extraParsers) { | ||
var val = obj[prop]; | ||
var isParser = Boolean(val.re); | ||
var isRegExp = Boolean(val.source); | ||
var isObject = Object(val) === val; | ||
// convert objects that are not matchers or RegExps to nested parsers | ||
if (isObject && !isParser && !isRegExp) { | ||
val = matcher(val); | ||
} | ||
isParser = Boolean(val.re); // update in case we now converted it to a parser | ||
if (isParser) { // accept parsers as arguments | ||
extraParsers.push(val); // note this is a parser | ||
val = val._nonCapturingRe; // don't capture for parser arguments | ||
} else if (isRegExp) { | ||
extraParsers.push(null); // not a parser | ||
val = val.source; | ||
} else { | ||
extraParsers.push(null); // not a parser | ||
} | ||
return val; | ||
} |
{ | ||
"name": "js-restructure", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "This package provides a nifty way to match against regular expressions\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001b[D\u001bconstruct and match against regular expressions.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -7,2 +7,7 @@ # js-restructure | ||
- [Motivation](https://github.com/benjamingr/js-restructure#motivation) | ||
- [API Docs](https://github.com/benjamingr/js-restructure/blob/master/API.md) | ||
- [Installation](https://github.com/benjamingr/js-restructure#installation) | ||
- [Contribution](https://github.com/benjamingr/js-restructure#contribution) | ||
Here is a very simple email address parser: | ||
@@ -42,2 +47,6 @@ | ||
## Motivation | ||
Matching nested RegExps is hard to read. The goal of this package is to allow users to match common patterns without having to parse the capturing groups of complex regular expressions and put those in object fields. This "shims" the lack of lack of named capturing groups in JavaScript. | ||
## Installation | ||
@@ -47,3 +56,3 @@ | ||
Or in the browser | ||
Or in the browser: | ||
@@ -56,34 +65,2 @@ <script src='https://wzrd.in/standalone/js-restructure@latest'></script> | ||
## API | ||
The basic fundamental unit of js-restructure is a parser. A parser is created by passing an object to the matcher function (the one you `require`, in the browser this is `window.jsRestructure`). | ||
Creating a parser: | ||
matcher(T object) -> Parser | ||
For example: | ||
var parser = matcher({x : A }); | ||
**Note:** The parser ignores properties that start with `_`, if you have properties that you do not want to capture but need to specify parts of the RE, start them with `_`. | ||
You can nest objects and parsers inside a parser: | ||
var parser2 = matcher({x : parser}); // can nest parsers to create nested results | ||
var parser3 = matcher({x : {x: 3}}); // will create a nested object when parsing | ||
A parser is itself a function that can be passed a string, it returns an object of the type passed when creating the parser or null if the parsing failed: | ||
Parser:: (string[, flags]) => T? | ||
For example: | ||
var parser = matcher({x : A }); | ||
parser("A").x; // A | ||
parser("B"); // null, no match | ||
The second flags parameter is optional and allows setting RE flags like "i" for case insensitivity. | ||
The parser also exposes a `.re` property so the resulting RegExp can be checked and reused. | ||
## Browser Support | ||
@@ -108,3 +85,2 @@ | ||
- measure performance | ||
- sugar | ||
- sugar |
27
tests.js
@@ -17,2 +17,10 @@ var matcher = require("./index.js"); | ||
}); | ||
it("ignores patterns with _", function() { | ||
var m = matcher({_:"[A-Z]+"})("AB"); | ||
assert.equal(m._, undefined); | ||
}); | ||
it("ignores patterns containing _", function() { | ||
var m = matcher({_1:"[A-Z]+"})("AB"); | ||
assert.equal(m._1, undefined); | ||
}); | ||
it("matches lazily when it has to", function() { | ||
@@ -139,9 +147,10 @@ var m = matcher({x:"[A-Z]+?", _:"C"})("ABCD"); | ||
describe("the parser", function() { | ||
describe("the parser nesting abilities", function() { | ||
it("should accept nested objects", function() { | ||
var p = matcher({x: {x:"A"}})("A"); | ||
var m = matcher({x: {x: "A"}}); | ||
var p = m("A"); | ||
assert.equal(p.x.x, "A"); | ||
}); | ||
it("should accept multiple nested objects", function() { | ||
var p = matcher({x: {x:"A"}, y: {y: "B"}})("AB"); | ||
var p = matcher({x: {x: "A"}, y: {y: "B"}})("AB"); | ||
assert.equal(p.x.x, "A"); | ||
@@ -163,3 +172,3 @@ assert.equal(p.y.y, "B"); | ||
var m1 = matcher({x: "A"}); | ||
var m2 = matcher({x: m1, y:m1 }); | ||
var m2 = matcher({x: m1, y: m1 }); | ||
var p = m2("AA"); | ||
@@ -171,3 +180,3 @@ assert.equal(p.x.x, "A"); | ||
var m1 = matcher({x: "A"}); | ||
var m2 = matcher({x: m1, y:m1 }); | ||
var m2 = matcher({x: m1, y: m1 }); | ||
var p = m2("AA"); | ||
@@ -177,2 +186,10 @@ assert.equal(p.x.x, "A"); | ||
}); | ||
it("should be able to mix REs with objects", function() { | ||
var m1 = matcher({x: "A"}); | ||
var m2 = matcher({x: m1, y: /a/ }); | ||
var p = m2("Aa"); | ||
assert.equal(p.x.x, "A"); | ||
assert.equal(p.y, "a"); | ||
}); | ||
}); |
12654
6
238
81