UNPKG

10.5 kBMarkdownView Raw
1# levn [![Build Status](https://travis-ci.org/gkz/levn.png)](https://travis-ci.org/gkz/levn) <a name="levn" />
2__Light ECMAScript (JavaScript) Value Notation__
3Levn is a library which allows you to parse a string into a JavaScript value based on an expected type. It is meant for short amounts of human entered data (eg. config files, command line arguments).
4
5Levn aims to concisely describe JavaScript values in text, and allow for the extraction and validation of those values. Levn uses [type-check](https://github.com/gkz/type-check) for its type format, and to validate the results. MIT license. Version 0.4.1.
6
7__How is this different than JSON?__ levn is meant to be written by humans only, is (due to the previous point) much more concise, can be validated against supplied types, has regex and date literals, and can easily be extended with custom types. On the other hand, it is probably slower and thus less efficient at transporting large amounts of data, which is fine since this is not its purpose.
8
9 npm install levn
10
11For updates on levn, [follow me on twitter](https://twitter.com/gkzahariev).
12
13
14## Quick Examples
15
16```js
17var parse = require('levn').parse;
18parse('Number', '2'); // 2
19parse('String', '2'); // '2'
20parse('String', 'levn'); // 'levn'
21parse('String', 'a b'); // 'a b'
22parse('Boolean', 'true'); // true
23
24parse('Date', '#2011-11-11#'); // (Date object)
25parse('Date', '2011-11-11'); // (Date object)
26parse('RegExp', '/[a-z]/gi'); // /[a-z]/gi
27parse('RegExp', 're'); // /re/
28parse('Int', '2'); // 2
29
30parse('Number | String', 'str'); // 'str'
31parse('Number | String', '2'); // 2
32
33parse('[Number]', '[1,2,3]'); // [1,2,3]
34parse('(String, Boolean)', '(hi, false)'); // ['hi', false]
35parse('{a: String, b: Number}', '{a: str, b: 2}'); // {a: 'str', b: 2}
36
37// at the top level, you can ommit surrounding delimiters
38parse('[Number]', '1,2,3'); // [1,2,3]
39parse('(String, Boolean)', 'hi, false'); // ['hi', false]
40parse('{a: String, b: Number}', 'a: str, b: 2'); // {a: 'str', b: 2}
41
42// wildcard - auto choose type
43parse('*', '[hi,(null,[42]),{k: true}]'); // ['hi', [null, [42]], {k: true}]
44```
45## Usage
46
47`require('levn');` returns an object that exposes three properties. `VERSION` is the current version of the library as a string. `parse` and `parsedTypeParse` are functions.
48
49```js
50// parse(type, input, options);
51parse('[Number]', '1,2,3'); // [1, 2, 3]
52
53// parsedTypeParse(parsedType, input, options);
54var parsedType = require('type-check').parseType('[Number]');
55parsedTypeParse(parsedType, '1,2,3'); // [1, 2, 3]
56```
57
58### parse(type, input, options)
59
60`parse` casts the string `input` into a JavaScript value according to the specified `type` in the [type format](https://github.com/gkz/type-check#type-format) (and taking account the optional `options`) and returns the resulting JavaScript value.
61
62##### arguments
63* type - `String` - the type written in the [type format](https://github.com/gkz/type-check#type-format) which to check against
64* input - `String` - the value written in the [levn format](#levn-format)
65* options - `Maybe Object` - an optional parameter specifying additional [options](#options)
66
67##### returns
68`*` - the resulting JavaScript value
69
70##### example
71```js
72parse('[Number]', '1,2,3'); // [1, 2, 3]
73```
74
75### parsedTypeParse(parsedType, input, options)
76
77`parsedTypeParse` casts the string `input` into a JavaScript value according to the specified `type` which has already been parsed (and taking account the optional `options`) and returns the resulting JavaScript value. You can parse a type using the [type-check](https://github.com/gkz/type-check) library's `parseType` function.
78
79##### arguments
80* type - `Object` - the type in the parsed type format which to check against
81* input - `String` - the value written in the [levn format](#levn-format)
82* options - `Maybe Object` - an optional parameter specifying additional [options](#options)
83
84##### returns
85`*` - the resulting JavaScript value
86
87##### example
88```js
89var parsedType = require('type-check').parseType('[Number]');
90parsedTypeParse(parsedType, '1,2,3'); // [1, 2, 3]
91```
92
93## Levn Format
94
95Levn can use the type information you provide to choose the appropriate value to produce from the input. For the same input, it will choose a different output value depending on the type provided. For example, `parse('Number', '2')` will produce the number `2`, but `parse('String', '2')` will produce the string `"2"`.
96
97If you do not provide type information, and simply use `*`, levn will parse the input according the unambiguous "explicit" mode, which we will now detail - you can also set the `explicit` option to true manually in the [options](#options).
98
99* `"string"`, `'string'` are parsed as a String, eg. `"a msg"` is `"a msg"`
100* `#date#` is parsed as a Date, eg. `#2011-11-11#` is `new Date('2011-11-11')`
101* `/regexp/flags` is parsed as a RegExp, eg. `/re/gi` is `/re/gi`
102* `undefined`, `null`, `NaN`, `true`, and `false` are all their JavaScript equivalents
103* `[element1, element2, etc]` is an Array, and the casting procedure is recursively applied to each element. Eg. `[1,2,3]` is `[1,2,3]`.
104* `(element1, element2, etc)` is an tuple, and the casting procedure is recursively applied to each element. Eg. `(1, a)` is `(1, a)` (is `[1, 'a']`).
105* `{key1: val1, key2: val2, ...}` is an Object, and the casting procedure is recursively applied to each property. Eg. `{a: 1, b: 2}` is `{a: 1, b: 2}`.
106* Any test which does not fall under the above, and which does not contain special characters (`[``]``(``)``{``}``:``,`) is a string, eg. `$12- blah` is `"$12- blah"`.
107
108If you do provide type information, you can make your input more concise as the program already has some information about what it expects. Please see the [type format](https://github.com/gkz/type-check#type-format) section of [type-check](https://github.com/gkz/type-check) for more information about how to specify types. There are some rules about what levn can do with the information:
109
110* If a String is expected, and only a String, all characters of the input (including any special ones) will become part of the output. Eg. `[({})]` is `"[({})]"`, and `"hi"` is `'"hi"'`.
111* If a Date is expected, the surrounding `#` can be omitted from date literals. Eg. `2011-11-11` is `new Date('2011-11-11')`.
112* If a RegExp is expected, no flags need to be specified, and the regex is not using any of the special characters,the opening and closing `/` can be omitted - this will have the affect of setting the source of the regex to the input. Eg. `regex` is `/regex/`.
113* If an Array is expected, and it is the root node (at the top level), the opening `[` and closing `]` can be omitted. Eg. `1,2,3` is `[1,2,3]`.
114* If a tuple is expected, and it is the root node (at the top level), the opening `(` and closing `)` can be omitted. Eg. `1, a` is `(1, a)` (is `[1, 'a']`).
115* If an Object is expected, and it is the root node (at the top level), the opening `{` and closing `}` can be omitted. Eg `a: 1, b: 2` is `{a: 1, b: 2}`.
116
117If you list multiple types (eg. `Number | String`), it will first attempt to cast to the first type and then validate - if the validation fails it will move on to the next type and so forth, left to right. You must be careful as some types will succeed with any input, such as String. Thus put String at the end of your list. In non-explicit mode, Date and RegExp will succeed with a large variety of input - also be careful with these and list them near the end if not last in your list.
118
119Whitespace between special characters and elements is inconsequential.
120
121## Options
122
123Options is an object. It is an optional parameter to the `parse` and `parsedTypeParse` functions.
124
125### Explicit
126
127A `Boolean`. By default it is `false`.
128
129__Example:__
130
131```js
132parse('RegExp', 're', {explicit: false}); // /re/
133parse('RegExp', 're', {explicit: true}); // Error: ... does not type check...
134parse('RegExp | String', 're', {explicit: true}); // 're'
135```
136
137`explicit` sets whether to be in explicit mode or not. Using `*` automatically activates explicit mode. For more information, read the [levn format](#levn-format) section.
138
139### customTypes
140
141An `Object`. Empty `{}` by default.
142
143__Example:__
144
145```js
146var options = {
147 customTypes: {
148 Even: {
149 typeOf: 'Number',
150 validate: function (x) {
151 return x % 2 === 0;
152 },
153 cast: function (x) {
154 return {type: 'Just', value: parseInt(x)};
155 }
156 }
157 }
158}
159parse('Even', '2', options); // 2
160parse('Even', '3', options); // Error: Value: "3" does not type check...
161```
162
163__Another Example:__
164```js
165function Person(name, age){
166 this.name = name;
167 this.age = age;
168}
169var options = {
170 customTypes: {
171 Person: {
172 typeOf: 'Object',
173 validate: function (x) {
174 x instanceof Person;
175 },
176 cast: function (value, options, typesCast) {
177 var name, age;
178 if ({}.toString.call(value).slice(8, -1) !== 'Object') {
179 return {type: 'Nothing'};
180 }
181 name = typesCast(value.name, [{type: 'String'}], options);
182 age = typesCast(value.age, [{type: 'Numger'}], options);
183 return {type: 'Just', value: new Person(name, age)};
184 }
185 }
186}
187parse('Person', '{name: Laura, age: 25}', options); // Person {name: 'Laura', age: 25}
188```
189
190`customTypes` is an object whose keys are the name of the types, and whose values are an object with three properties, `typeOf`, `validate`, and `cast`. For more information about `typeOf` and `validate`, please see the [custom types](https://github.com/gkz/type-check#custom-types) section of type-check.
191
192`cast` is a function which receives three arguments, the value under question, options, and the typesCast function. In `cast`, attempt to cast the value into the specified type. If you are successful, return an object in the format `{type: 'Just', value: CAST-VALUE}`, if you know it won't work, return `{type: 'Nothing'}`. You can use the `typesCast` function to cast any child values. Remember to pass `options` to it. In your function you can also check for `options.explicit` and act accordingly.
193
194## Technical About
195
196`levn` is written in [LiveScript](http://livescript.net/) - a language that compiles to JavaScript. It uses [type-check](https://github.com/gkz/type-check) to both parse types and validate values. It also uses the [prelude.ls](http://preludels.com/) library.