付智勇

添加包

要显示太多修改。

为保证性能只显示 32 of 32+ 个文件。

... ... @@ -13,6 +13,8 @@ const users = require('./routes/users')
const filterUrl = require(__dirname+'/util/filterUrl')
var tokenUtil = require('./util/tokenUtil');
const _ = require('lodash');
var status = require('./util/resTemplate')
// error handler
onerror(app)
... ... @@ -36,8 +38,7 @@ app.use(async (ctx, next) => {
if(filterUrl.indexOf(ctx.request.url) != -1){
await next();
}else if(!ctx.header.token){
ctx.response.status = 200;
ctx.response.body = {code:0,msg:'请登录'}
status.catchError(ctx,400,'请登录');
}else{
let isToken = await tokenUtil.prverifySession(ctx.header.token);
await next();
... ... @@ -45,11 +46,8 @@ app.use(async (ctx, next) => {
const ms = new Date() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
}catch (e){
console.log('返回的err',e.message)
ctx.response.status = 200;
ctx.response.body = {code:0,msg:e.message}
status.catchError(ctx,400,e.message);
}
})
// routes
... ...
... ... @@ -9,12 +9,16 @@ var userController =function (){
};
/**
* Generate documentation output.
*
* @param {TAFFY} ctx
*
* @param {object} next
*/
userController.prototype.addUser = async(ctx, next) =>{
var params = ctx.request.body;
const pw = saitMd5.md5AddSalt(params.password)
console.dir(params.password.length,7)
console.dir(params.password.length<6)
const pw = saitMd5.md5AddSalt(params.password)
if(!params.loginName){
return status.paramError('loginName');
... ... @@ -23,20 +27,26 @@ userController.prototype.addUser = async(ctx, next) =>{
}if(params.password.length < 6){
return status.paramError('password','不得小于6位');
}
var user = {
loginName:params.loginName,
password:pw.md5Pass,
salt:pw.salt,
userType:params.type
}
try{
return await userService.addUser(user)
}catch (e){
throw new Error(e);
}
}
/**
* 用户登录
*/
userController.prototype.login = async(ctx, next) =>{
const body = ctx.request.body;
if(!body.name){
return status.paramError('name');
}else if(!body.password){
... ...
../babylon/bin/babylon.js
\ No newline at end of file
... ...
../jsdoc/jsdoc.js
\ No newline at end of file
... ...
../marked/bin/marked
\ No newline at end of file
... ...
# Changelog
> **Tags:**
> - :boom: [Breaking Change]
> - :eyeglasses: [Spec Compliancy]
> - :rocket: [New Feature]
> - :bug: [Bug Fix]
> - :memo: [Documentation]
> - :house: [Internal]
> - :nail_care: [Polish]
> Semver Policy: https://github.com/babel/babylon#semver
_Note: Gaps between patch versions are faulty, broken or test releases._
See the [Babel Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md) for the pre-6.8.0 version Changelog.
## 6.17.1 (2017-05-10)
### :bug: Bug Fix
* Fix typo in flow spread operator error (Brian Ng)
* Fixed invalid number literal parsing ([#473](https://github.com/babel/babylon/pull/473)) (Alex Kuzmenko)
* Fix number parser ([#433](https://github.com/babel/babylon/pull/433)) (Alex Kuzmenko)
* Ensure non pattern shorthand props are checked for reserved words ([#479](https://github.com/babel/babylon/pull/479)) (Brian Ng)
* Remove jsx context when parsing arrow functions ([#475](https://github.com/babel/babylon/pull/475)) (Brian Ng)
* Allow super in class properties ([#499](https://github.com/babel/babylon/pull/499)) (Brian Ng)
* Allow flow class field to be named constructor ([#510](https://github.com/babel/babylon/pull/510)) (Brian Ng)
## 6.17.0 (2017-04-20)
### :bug: Bug Fix
* Cherry-pick #418 to 6.x ([#476](https://github.com/babel/babylon/pull/476)) (Sebastian McKenzie)
* Add support for invalid escapes in tagged templates ([#274](https://github.com/babel/babylon/pull/274)) (Kevin Gibbons)
* Throw error if new.target is used outside of a function ([#402](https://github.com/babel/babylon/pull/402)) (Brian Ng)
* Fix parsing of class properties ([#351](https://github.com/babel/babylon/pull/351)) (Kevin Gibbons)
* Fix parsing yield with dynamicImport ([#383](https://github.com/babel/babylon/pull/383)) (Brian Ng)
* Ensure consistent start args for parseParenItem ([#386](https://github.com/babel/babylon/pull/386)) (Brian Ng)
## 7.0.0-beta.8 (2017-04-04)
### New Feature
* Add support for flow type spread (#418) (Conrad Buck)
* Allow statics in flow interfaces (#427) (Brian Ng)
### Bug Fix
* Fix predicate attachment to match flow parser (#428) (Brian Ng)
* Add extra.raw back to JSXText and JSXAttribute (#344) (Alex Rattray)
* Fix rest parameters with array and objects (#424) (Brian Ng)
* Fix number parser (#433) (Alex Kuzmenko)
### Docs
* Fix CONTRIBUTING.md [skip ci] (#432) (Alex Kuzmenko)
### Internal
* Use babel-register script when running babel smoke tests (#442) (Brian Ng)
## 7.0.0-beta.7 (2017-03-22)
### Spec Compliancy
* Remove babylon plugin for template revision since it's stage-4 (#426) (Henry Zhu)
### Bug Fix
* Fix push-pop logic in flow (#405) (Daniel Tschinder)
## 7.0.0-beta.6 (2017-03-21)
### New Feature
* Add support for invalid escapes in tagged templates (#274) (Kevin Gibbons)
### Polish
* Improves error message when super is called outside of constructor (#408) (Arshabh Kumar Agarwal)
### Docs
* [7.0] Moved value field in spec from ObjectMember to ObjectProperty as ObjectMethod's don't have it (#415) [skip ci] (James Browning)
## 7.0.0-beta.5 (2017-03-21)
### Bug Fix
* Throw error if new.target is used outside of a function (#402) (Brian Ng)
* Fix parsing of class properties (#351) (Kevin Gibbons)
### Other
* Test runner: Detect extra property in 'actual' but not in 'expected'. (#407) (Andy)
* Optimize travis builds (#419) (Daniel Tschinder)
* Update codecov to 2.0 (#412) (Daniel Tschinder)
* Fix spec for ClassMethod: It doesn't have a function, it *is* a function. (#406) [skip ci] (Andy)
* Changed Non-existent RestPattern to RestElement which is what is actually parsed (#409) [skip ci] (James Browning)
* Upgrade flow to 0.41 (Daniel Tschinder)
* Fix watch command (#403) (Brian Ng)
* Update yarn lock (Daniel Tschinder)
* Fix watch command (#403) (Brian Ng)
* chore(package): update flow-bin to version 0.41.0 (#395) (greenkeeper[bot])
* Add estree test for correct order of directives (Daniel Tschinder)
* Add DoExpression to spec (#364) (Alex Kuzmenko)
* Mention cloning of repository in CONTRIBUTING.md (#391) [skip ci] (Sumedh Nimkarde)
* Explain how to run only one test (#389) [skip ci] (Aaron Ang)
## 7.0.0-beta.4 (2017-03-01)
* Don't consume async when checking for async func decl (#377) (Brian Ng)
* add `ranges` option [skip ci] (Henry Zhu)
* Don't parse class properties without initializers when classProperties is disabled and Flow is enabled (#300) (Andrew Levine)
## 7.0.0-beta.3 (2017-02-28)
- [7.0] Change RestProperty/SpreadProperty to RestElement/SpreadElement (#384)
- Merge changes from 6.x
## 7.0.0-beta.2 (2017-02-20)
- estree: correctly change literals in all cases (#368) (Daniel Tschinder)
## 7.0.0-beta.1 (2017-02-20)
- Fix negative number literal typeannotations (#366) (Daniel Tschinder)
- Update contributing with more test info [skip ci] (#355) (Brian Ng)
## 7.0.0-beta.0 (2017-02-15)
- Reintroduce Variance node (#333) (Daniel Tschinder)
- Rename NumericLiteralTypeAnnotation to NumberLiteralTypeAnnotation (#332) (Charles Pick)
- [7.0] Remove ForAwaitStatement, add await flag to ForOfStatement (#349) (Brandon Dail)
- chore(package): update ava to version 0.18.0 (#345) (greenkeeper[bot])
- chore(package): update babel-plugin-istanbul to version 4.0.0 (#350) (greenkeeper[bot])
- Change location of ObjectTypeIndexer to match flow (#228) (Daniel Tschinder)
- Rename flow AST Type ExistentialTypeParam to ExistsTypeAnnotation (#322) (Toru Kobayashi)
- Revert "Temporary rollback for erroring on trailing comma with spread (#154)" (#290) (Daniel Tschinder)
- Remove classConstructorCall plugin (#291) (Brian Ng)
- Update yarn.lock (Daniel Tschinder)
- Update cross-env to 3.x (Daniel Tschinder)
- [7.0] Remove node 0.10, 0.12 and 5 from Travis (#284) (Sergey Rubanov)
- Remove `String.fromCodePoint` shim (#279) (Mathias Bynens)
## 6.16.1 (2017-02-23)
### :bug: Regression
- Revert "Fix export default async function to be FunctionDeclaration" ([#375](https://github.com/babel/babylon/pull/375))
Need to modify Babel for this AST node change, so moving to 7.0.
- Revert "Don't parse class properties without initializers when classProperties plugin is disabled, and Flow is enabled" ([#376](https://github.com/babel/babylon/pull/376))
[react-native](https://github.com/facebook/react-native/issues/12542) broke with this so we reverted.
## 6.16.0 (2017-02-23)
### :rocket: New Feature
***ESTree*** compatibility as plugin ([#277](https://github.com/babel/babylon/pull/277)) (Daniel Tschinder)
We finally introduce a new compatibility layer for ESTree. To put babylon into ESTree-compatible mode the new plugin `estree` can be enabled. In this mode the parser will output an AST that is compliant to the specs of [ESTree](https://github.com/estree/estree/)
We highly recommend everyone who uses babylon outside of babel to use this plugin. This will make it much easier for users to switch between different ESTree-compatible parsers. We so far tested several projects with different parsers and exchanged their parser to babylon and in nearly all cases it worked out of the box. Some other estree-compatible parsers include `acorn`, `esprima`, `espree`, `flow-parser`, etc.
To enable `estree` mode simply add the plugin in the config:
```json
{
"plugins": [ "estree" ]
}
```
If you want to migrate your project from non-ESTree mode to ESTree, have a look at our [Readme](https://github.com/babel/babylon/#output), where all deviations are mentioned.
Add a parseExpression public method ([#213](https://github.com/babel/babylon/pull/213)) (jeromew)
Babylon exports a new function to parse a single expression
```js
import { parseExpression } from 'babylon';
const ast = parseExpression('x || y && z', options);
```
The returned AST will only consist of the expression. The options are the same as for `parse()`
Add startLine option ([#346](https://github.com/babel/babylon/pull/346)) (Raphael Mu)
A new option was added to babylon allowing to change the intial linenumber for the first line which is usually `1`.
Changing this for example to `100` will make line `1` of the input source to be marked as line `100`, line `2` as `101`, line `3` as `102`, ...
Function predicate declaration ([#103](https://github.com/babel/babylon/pull/103)) (Panagiotis Vekris)
Added support for function predicates which flow introduced in version 0.33.0
```js
declare function is_number(x: mixed): boolean %checks(typeof x === "number");
```
Allow imports in declare module ([#315](https://github.com/babel/babylon/pull/315)) (Daniel Tschinder)
Added support for imports within module declarations which flow introduced in version 0.37.0
```js
declare module "C" {
import type { DT } from "D";
declare export type CT = { D: DT };
}
```
### :eyeglasses: Spec Compliancy
Forbid semicolons after decorators in classes ([#352](https://github.com/babel/babylon/pull/352)) (Kevin Gibbons)
This example now correctly throws an error when there is a semicolon after the decorator:
```js
class A {
@a;
foo(){}
}
```
Keywords are not allowed as local specifier ([#307](https://github.com/babel/babylon/pull/307)) (Daniel Tschinder)
Using keywords in imports is not allowed anymore:
```js
import { default } from "foo";
import { a as debugger } from "foo";
```
Do not allow overwritting of primitive types ([#314](https://github.com/babel/babylon/pull/314)) (Daniel Tschinder)
In flow it is now forbidden to overwrite the primitve types `"any"`, `"mixed"`, `"empty"`, `"bool"`, `"boolean"`, `"number"`, `"string"`, `"void"` and `"null"` with your own type declaration.
Disallow import type { type a } from … ([#305](https://github.com/babel/babylon/pull/305)) (Daniel Tschinder)
The following code now correctly throws an error
```js
import type { type a } from "foo";
```
Don't parse class properties without initializers when classProperties is disabled and Flow is enabled ([#300](https://github.com/babel/babylon/pull/300)) (Andrew Levine)
Ensure that you enable the `classProperties` plugin in order to enable correct parsing of class properties. Prior to this version it was possible to parse them by enabling the `flow` plugin but this was not intended the behaviour.
If you enable the flow plugin you can only define the type of the class properties, but not initialize them.
Fix export default async function to be FunctionDeclaration ([#324](https://github.com/babel/babylon/pull/324)) (Daniel Tschinder)
Parsing the following code now returns a `FunctionDeclaration` AST node instead of `FunctionExpression`.
```js
export default async function bar() {};
```
### :nail_care: Polish
Improve error message on attempt to destructure named import ([#288](https://github.com/babel/babylon/pull/288)) (Brian Ng)
### :bug: Bug Fix
Fix negative number literal typeannotations ([#366](https://github.com/babel/babylon/pull/366)) (Daniel Tschinder)
Ensure takeDecorators is called on exported class ([#358](https://github.com/babel/babylon/pull/358)) (Brian Ng)
ESTree: correctly change literals in all cases ([#368](https://github.com/babel/babylon/pull/368)) (Daniel Tschinder)
Correctly convert RestProperty to Assignable ([#339](https://github.com/babel/babylon/pull/339)) (Daniel Tschinder)
Fix #321 by allowing question marks in type params ([#338](https://github.com/babel/babylon/pull/338)) (Daniel Tschinder)
Fix #336 by correctly setting arrow-param ([#337](https://github.com/babel/babylon/pull/337)) (Daniel Tschinder)
Fix parse error when destructuring `set` with default value ([#317](https://github.com/babel/babylon/pull/317)) (Brian Ng)
Fix ObjectTypeCallProperty static ([#298](https://github.com/babel/babylon/pull/298)) (Dan Harper)
### :house: Internal
Fix generator-method-with-computed-name spec ([#360](https://github.com/babel/babylon/pull/360)) (Alex Rattray)
Fix flow type-parameter-declaration test with unintended semantic ([#361](https://github.com/babel/babylon/pull/361)) (Alex Rattray)
Cleanup and splitup parser functions ([#295](https://github.com/babel/babylon/pull/295)) (Daniel Tschinder)
chore(package): update flow-bin to version 0.38.0 ([#313](https://github.com/babel/babylon/pull/313)) (greenkeeper[bot])
Call inner function instead of 1:1 copy to plugin ([#294](https://github.com/babel/babylon/pull/294)) (Daniel Tschinder)
Update eslint-config-babel to the latest version 🚀 ([#299](https://github.com/babel/babylon/pull/299)) (greenkeeper[bot])
Update eslint-config-babel to the latest version 🚀 ([#293](https://github.com/babel/babylon/pull/293)) (greenkeeper[bot])
devDeps: remove eslint-plugin-babel ([#292](https://github.com/babel/babylon/pull/292)) (Kai Cataldo)
Correct indent eslint rule config ([#276](https://github.com/babel/babylon/pull/276)) (Daniel Tschinder)
Fail tests that have expected.json and throws-option ([#285](https://github.com/babel/babylon/pull/285)) (Daniel Tschinder)
### :memo: Documentation
Update contributing with more test info [skip ci] ([#355](https://github.com/babel/babylon/pull/355)) (Brian Ng)
Update API documentation ([#330](https://github.com/babel/babylon/pull/330)) (Timothy Gu)
Added keywords to package.json ([#323](https://github.com/babel/babylon/pull/323)) (Dmytro)
AST spec: fix casing of `RegExpLiteral` ([#318](https://github.com/babel/babylon/pull/318)) (Mathias Bynens)
## 6.15.0 (2017-01-10)
### :eyeglasses: Spec Compliancy
Add support for Flow shorthand import type ([#267](https://github.com/babel/babylon/pull/267)) (Jeff Morrison)
This change implements flows new shorthand import syntax
and where previously you had to write this code:
```js
import {someValue} from "blah";
import type {someType} from "blah";
import typeof {someOtherValue} from "blah";
```
you can now write it like this:
```js
import {
someValue,
type someType,
typeof someOtherValue,
} from "blah";
```
For more information look at [this](https://github.com/facebook/flow/pull/2890) pull request.
flow: allow leading pipes in all positions ([#256](https://github.com/babel/babylon/pull/256)) (Vladimir Kurchatkin)
This change now allows a leading pipe everywhere types can be used:
```js
var f = (x): | 1 | 2 => 1;
```
Throw error when exporting non-declaration ([#241](https://github.com/babel/babylon/pull/241)) (Kai Cataldo)
Previously babylon parsed the following exports, although they are not valid:
```js
export typeof foo;
export new Foo();
export function() {};
export for (;;);
export while(foo);
```
### :bug: Bug Fix
Don't set inType flag when parsing property names ([#266](https://github.com/babel/babylon/pull/266)) (Vladimir Kurchatkin)
This fixes parsing of this case:
```js
const map = {
[age <= 17] : 'Too young'
};
```
Fix source location for JSXEmptyExpression nodes (fixes #248) ([#249](https://github.com/babel/babylon/pull/249)) (James Long)
The following case produced an invalid AST
```js
<div>{/* foo */}</div>
```
Use fromCodePoint to convert high value unicode entities ([#243](https://github.com/babel/babylon/pull/243)) (Ryan Duffy)
When high value unicode entities (e.g. 💩) were used in the input source code they are now correctly encoded in the resulting AST.
Rename folder to avoid Windows-illegal characters ([#281](https://github.com/babel/babylon/pull/281)) (Ryan Plant)
Allow this.state.clone() when parsing decorators ([#262](https://github.com/babel/babylon/pull/262)) (Alex Rattray)
### :house: Internal
User external-helpers ([#254](https://github.com/babel/babylon/pull/254)) (Daniel Tschinder)
Add watch script for dev ([#234](https://github.com/babel/babylon/pull/234)) (Kai Cataldo)
Freeze current plugins list for "*" option, and remove from README.md ([#245](https://github.com/babel/babylon/pull/245)) (Andrew Levine)
Prepare tests for multiple fixture runners. ([#240](https://github.com/babel/babylon/pull/240)) (Daniel Tschinder)
Add some test coverage for decorators stage-0 plugin ([#250](https://github.com/babel/babylon/pull/250)) (Andrew Levine)
Refactor tokenizer types file ([#263](https://github.com/babel/babylon/pull/263)) (Sven SAULEAU)
Update eslint-config-babel to the latest version 🚀 ([#273](https://github.com/babel/babylon/pull/273)) (greenkeeper[bot])
chore(package): update rollup to version 0.41.0 ([#272](https://github.com/babel/babylon/pull/272)) (greenkeeper[bot])
chore(package): update flow-bin to version 0.37.0 ([#255](https://github.com/babel/babylon/pull/255)) (greenkeeper[bot])
## 6.14.1 (2016-11-17)
### :bug: Bug Fix
Allow `"plugins": ["*"]` ([#229](https://github.com/babel/babylon/pull/229)) (Daniel Tschinder)
```js
{
"plugins": ["*"]
}
```
Will include all parser plugins instead of specifying each one individually. Useful for tools like babel-eslint, jscodeshift, and ast-explorer.
## 6.14.0 (2016-11-16)
### :eyeglasses: Spec Compliancy
Throw error for reserved words `enum` and `await` ([#195](https://github.com/babel/babylon/pull/195)) (Kai Cataldo)
[11.6.2.2 Future Reserved Words](http://www.ecma-international.org/ecma-262/6.0/#sec-future-reserved-words)
Babylon will throw for more reserved words such as `enum` or `await` (in strict mode).
```
class enum {} // throws
class await {} // throws in strict mode (module)
```
Optional names for function types and object type indexers ([#197](https://github.com/babel/babylon/pull/197)) (Gabe Levi)
So where you used to have to write
```js
type A = (x: string, y: boolean) => number;
type B = (z: string) => number;
type C = { [key: string]: number };
```
you can now write (with flow 0.34.0)
```js
type A = (string, boolean) => number;
type B = string => number;
type C = { [string]: number };
```
Parse flow nested array type annotations like `number[][]` ([#219](https://github.com/babel/babylon/pull/219)) (Bernhard Häussner)
Supports these form now of specifying array types:
```js
var a: number[][][][];
var b: string[][];
```
### :bug: Bug Fix
Correctly eat semicolon at the end of `DelcareModuleExports` ([#223](https://github.com/babel/babylon/pull/223)) (Daniel Tschinder)
```
declare module "foo" { declare module.exports: number }
declare module "foo" { declare module.exports: number; } // also allowed now
```
### :house: Internal
* Count Babel tests towards Babylon code coverage ([#182](https://github.com/babel/babylon/pull/182)) (Moti Zilberman)
* Fix strange line endings ([#214](https://github.com/babel/babylon/pull/214)) (Thomas Grainger)
* Add node 7 (Daniel Tschinder)
* chore(package): update flow-bin to version 0.34.0 ([#204](https://github.com/babel/babylon/pull/204)) (Greenkeeper)
## v6.13.1 (2016-10-26)
### :nail_care: Polish
- Use rollup for bundling to speed up startup time ([#190](https://github.com/babel/babylon/pull/190)) ([@drewml](https://github.com/DrewML))
```js
const babylon = require('babylon');
const ast = babylon.parse('var foo = "lol";');
```
With that test case, there was a ~95ms savings by removing the need for node to build/traverse the dependency graph.
**Without bundling**
![image](https://cloud.githubusercontent.com/assets/5233399/19420264/3133497e-93ad-11e6-9a6a-2da59c4f5c13.png)
**With bundling**
![image](https://cloud.githubusercontent.com/assets/5233399/19420267/388f556e-93ad-11e6-813e-7c5c396be322.png)
- add clean command [skip ci] ([#201](https://github.com/babel/babylon/pull/201)) (Henry Zhu)
- add ForAwaitStatement (async generator already added) [skip ci] ([#196](https://github.com/babel/babylon/pull/196)) (Henry Zhu)
## v6.13.0 (2016-10-21)
### :eyeglasses: Spec Compliancy
Property variance type annotations for Flow plugin ([#161](https://github.com/babel/babylon/pull/161)) (Sam Goldman)
> See https://flowtype.org/docs/variance.html for more information
```js
type T = { +p: T };
interface T { -p: T };
declare class T { +[k:K]: V };
class T { -[k:K]: V };
class C2 { +p: T = e };
```
Raise error on duplicate definition of __proto__ ([#183](https://github.com/babel/babylon/pull/183)) (Moti Zilberman)
```js
({ __proto__: 1, __proto__: 2 }) // Throws an error now
```
### :bug: Bug Fix
Flow: Allow class properties to be named `static` ([#184](https://github.com/babel/babylon/pull/184)) (Moti Zilberman)
```js
declare class A {
static: T;
}
```
Allow "async" as identifier for object literal property shorthand ([#187](https://github.com/babel/babylon/pull/187)) (Andrew Levine)
```js
var foo = { async, bar };
```
### :nail_care: Polish
Fix flowtype and add inType to state ([#189](https://github.com/babel/babylon/pull/189)) (Daniel Tschinder)
> This improves the performance slightly (because of hidden classes)
### :house: Internal
Fix .gitattributes line ending setting ([#191](https://github.com/babel/babylon/pull/191)) (Moti Zilberman)
Increase test coverage ([#175](https://github.com/babel/babylon/pull/175) (Moti Zilberman)
Readd missin .eslinignore for IDEs (Daniel Tschinder)
Error on missing expected.json fixture in CI ([#188](https://github.com/babel/babylon/pull/188)) (Moti Zilberman)
Add .gitattributes and .editorconfig for LF line endings ([#179](https://github.com/babel/babylon/pull/179)) (Moti Zilberman)
Fixes two tests that are failing after the merge of #172 ([#177](https://github.com/babel/babylon/pull/177)) (Moti Zilberman)
## v6.12.0 (2016-10-14)
### :eyeglasses: Spec Compliancy
Implement import() syntax ([#163](https://github.com/babel/babylon/pull/163)) (Jordan Gensler)
#### Dynamic Import
- Proposal Repo: https://github.com/domenic/proposal-dynamic-import
- Championed by [@domenic](https://github.com/domenic)
- stage-2
- [sept-28 tc39 notes](https://github.com/rwaldron/tc39-notes/blob/master/es7/2016-09/sept-28.md#113a-import)
> This repository contains a proposal for adding a "function-like" import() module loading syntactic form to JavaScript
```js
import(`./section-modules/${link.dataset.entryModule}.js`)
.then(module => {
module.loadPageInto(main);
})
```
Add EmptyTypeAnnotation ([#171](https://github.com/babel/babylon/pull/171)) (Sam Goldman)
#### EmptyTypeAnnotation
Just wasn't covered before.
```js
type T = empty;
```
### :bug: Bug Fix
Fix crash when exporting with destructuring and sparse array ([#170](https://github.com/babel/babylon/pull/170)) (Jeroen Engels)
```js
// was failing due to sparse array
export const { foo: [ ,, qux7 ] } = bar;
```
Allow keyword in Flow object declaration property names with type parameters ([#146](https://github.com/babel/babylon/pull/146)) (Dan Harper)
```js
declare class X {
foobar<T>(): void;
static foobar<T>(): void;
}
```
Allow keyword in object/class property names with Flow type parameters ([#145](https://github.com/babel/babylon/pull/145)) (Dan Harper)
```js
class Foo {
delete<T>(item: T): T {
return item;
}
}
```
Allow typeAnnotations for yield expressions ([#174](https://github.com/babel/babylon/pull/174))) (Daniel Tschinder)
```js
function *foo() {
const x = (yield 5: any);
}
```
### :nail_care: Polish
Annotate more errors with expected token ([#172](https://github.com/babel/babylon/pull/172))) (Moti Zilberman)
```js
// Unexpected token, expected ; (1:6)
{ set 1 }
```
### :house: Internal
Remove kcheck ([#173](https://github.com/babel/babylon/pull/173))) (Daniel Tschinder)
Also run flow, linting, babel tests on seperate instances (add back node 0.10)
## v6.11.6 (2016-10-12)
### :bug: Bug Fix/Regression
Fix crash when exporting with destructuring and sparse array ([#170](https://github.com/babel/babylon/pull/170)) (Jeroen Engels)
```js
// was failing with `Cannot read property 'type' of null` because of null identifiers
export const { foo: [ ,, qux7 ] } = bar;
```
## v6.11.5 (2016-10-12)
### :eyeglasses: Spec Compliancy
Fix: Check for duplicate named exports in exported destructuring assignments ([#144](https://github.com/babel/babylon/pull/144)) (Kai Cataldo)
```js
// `foo` has already been exported. Exported identifiers must be unique. (2:20)
export function foo() {};
export const { a: [{foo}] } = bar;
```
Fix: Check for duplicate named exports in exported rest elements/properties ([#164](https://github.com/babel/babylon/pull/164)) (Kai Cataldo)
```js
// `foo` has already been exported. Exported identifiers must be unique. (2:22)
export const foo = 1;
export const [bar, ...foo] = baz;
```
### :bug: Bug Fix
Fix: Allow identifier `async` for default param in arrow expression ([#165](https://github.com/babel/babylon/pull/165)) (Kai Cataldo)
```js
// this is ok now
const test = ({async = true}) => {};
```
### :nail_care: Polish
Babylon will now print out the token it's expecting if there's a `SyntaxError` ([#150](https://github.com/babel/babylon/pull/150)) (Daniel Tschinder)
```bash
# So in the case of a missing ending curly (`}`)
Module build failed: SyntaxError: Unexpected token, expected } (30:0)
28 | }
29 |
> 30 |
| ^
```
## v6.11.4 (2016-10-03)
Temporary rollback for erroring on trailing comma with spread (#154) (Henry Zhu)
## v6.11.3 (2016-10-01)
### :eyeglasses: Spec Compliancy
Add static errors for object rest (#149) ([@danez](https://github.com/danez))
> https://github.com/sebmarkbage/ecmascript-rest-spread
Object rest copies the *rest* of properties from the right hand side `obj` starting from the left to right.
```js
let { x, y, ...z } = { x: 1, y: 2, z: 3 };
// x = 1
// y = 2
// z = { z: 3 }
```
#### New Syntax Errors:
**SyntaxError**: The rest element has to be the last element when destructuring (1:10)
```bash
> 1 | let { ...x, y, z } = { x: 1, y: 2, z: 3};
| ^
# Previous behavior:
# x = { x: 1, y: 2, z: 3 }
# y = 2
# z = 3
```
Before, this was just a more verbose way of shallow copying `obj` since it doesn't actually do what you think.
**SyntaxError**: Cannot have multiple rest elements when destructuring (1:13)
```bash
> 1 | let { x, ...y, ...z } = { x: 1, y: 2, z: 3};
| ^
# Previous behavior:
# x = 1
# y = { y: 2, z: 3 }
# z = { y: 2, z: 3 }
```
Before y and z would just be the same value anyway so there is no reason to need to have both.
**SyntaxError**: A trailing comma is not permitted after the rest element (1:16)
```js
let { x, y, ...z, } = obj;
```
The rationale for this is that the use case for trailing comma is that you can add something at the end without affecting the line above. Since a RestProperty always has to be the last property it doesn't make sense.
---
get / set are valid property names in default assignment (#142) ([@jezell](https://github.com/jezell))
```js
// valid
function something({ set = null, get = null }) {}
```
## v6.11.2 (2016-09-23)
### Bug Fix
- [#139](https://github.com/babel/babylon/issues/139) Don't do the duplicate check if not an identifier (#140) @hzoo
```js
// regression with duplicate export check
SyntaxError: ./typography.js: `undefined` has already been exported. Exported identifiers must be unique. (22:13)
20 |
21 | export const { rhythm } = typography;
> 22 | export const { TypographyStyle } = typography
```
Bail out for now, and make a change to account for destructuring in the next release.
## 6.11.1 (2016-09-22)
### Bug Fix
- [#137](https://github.com/babel/babylon/pull/137) - Fix a regression with duplicate exports - it was erroring on all keys in `Object.prototype`. @danez
```javascript
export toString from './toString';
```
```bash
`toString` has already been exported. Exported identifiers must be unique. (1:7)
> 1 | export toString from './toString';
| ^
2 |
```
## 6.11.0 (2016-09-22)
### Spec Compliancy (will break CI)
- Disallow duplicate named exports ([#107](https://github.com/babel/babylon/pull/107)) @kaicataldo
```js
// Only one default export allowed per module. (2:9)
export default function() {};
export { foo as default };
// Only one default export allowed per module. (2:0)
export default {};
export default function() {};
// `Foo` has already been exported. Exported identifiers must be unique. (2:0)
export { Foo };
export class Foo {};
```
### New Feature (Syntax)
- Add support for computed class property names ([#121](https://github.com/babel/babylon/pull/121)) @motiz88
```js
// AST
interface ClassProperty <: Node {
type: "ClassProperty";
key: Identifier;
value: Expression;
computed: boolean; // added
}
```
```js
// with "plugins": ["classProperties"]
class Foo {
[x]
['y']
}
class Bar {
[p]
[m] () {}
}
```
### Bug Fix
- Fix `static` property falling through in the declare class Flow AST ([#135](https://github.com/babel/babylon/pull/135)) @danharper
```js
declare class X {
a: number;
static b: number; // static
c: number; // this was being marked as static in the AST as well
}
```
### Polish
- Rephrase "assigning/binding to rvalue" errors to include context ([#119](https://github.com/babel/babylon/pull/119)) @motiz88
```js
// Used to error with:
// SyntaxError: Assigning to rvalue (1:0)
// Now:
// Invalid left-hand side in assignment expression (1:0)
3 = 4
// Invalid left-hand side in for-in statement (1:5)
for (+i in {});
```
### Internal
- Fix call to `this.parseMaybeAssign` with correct arguments ([#133](https://github.com/babel/babylon/pull/133)) @danez
- Add semver note to changelog ([#131](https://github.com/babel/babylon/pull/131)) @hzoo
## 6.10.0 (2016-09-19)
> We plan to include some spec compliancy bugs in patch versions. An example was the multiple default exports issue.
### Spec Compliancy
* Implement ES2016 check for simple parameter list in strict mode ([#106](https://github.com/babel/babylon/pull/106)) (Timothy Gu)
> It is a Syntax Error if ContainsUseStrict of FunctionBody is true and IsSimpleParameterList of FormalParameters is false. https://tc39.github.io/ecma262/2016/#sec-function-definitions-static-semantics-early-errors
More Context: [tc39-notes](https://github.com/rwaldron/tc39-notes/blob/master/es7/2015-07/july-29.md#611-the-scope-of-use-strict-with-respect-to-destructuring-in-parameter-lists)
For example:
```js
// this errors because it uses destructuring and default parameters
// in a function with a "use strict" directive
function a([ option1, option2 ] = []) {
"use strict";
}
```
The solution would be to use a top level "use strict" or to remove the destructuring or default parameters when using a function + "use strict" or to.
### New Feature
* Exact object type annotations for Flow plugin ([#104](https://github.com/babel/babylon/pull/104)) (Basil Hosmer)
Added to flow in https://github.com/facebook/flow/commit/c710c40aa2a115435098d6c0dfeaadb023cd39b8
Looks like:
```js
var a : {| x: number, y: string |} = { x: 0, y: 'foo' };
```
### Bug Fixes
* Include `typeParameter` location in `ArrowFunctionExpression` ([#126](https://github.com/babel/babylon/pull/126)) (Daniel Tschinder)
* Error on invalid flow type annotation with default assignment ([#122](https://github.com/babel/babylon/pull/122)) (Dan Harper)
* Fix Flow return types on arrow functions ([#124](https://github.com/babel/babylon/pull/124)) (Dan Harper)
### Misc
* Add tests for export extensions ([#127](https://github.com/babel/babylon/pull/127)) (Daniel Tschinder)
* Fix Contributing guidelines [skip ci] (Daniel Tschinder)
## 6.9.2 (2016-09-09)
The only change is to remove the `babel-runtime` dependency by compiling with Babel's ES2015 loose mode. So using babylon standalone should be smaller.
## 6.9.1 (2016-08-23)
This release contains mainly small bugfixes but also updates babylons default mode to es2017. The features for `exponentiationOperator`, `asyncFunctions` and `trailingFunctionCommas` which previously needed to be activated via plugin are now enabled by default and the plugins are now no-ops.
### Bug Fixes
- Fix issues with default object params in async functions ([#96](https://github.com/babel/babylon/pull/96)) @danez
- Fix issues with flow-types and async function ([#95](https://github.com/babel/babylon/pull/95)) @danez
- Fix arrow functions with destructuring, types & default value ([#94](https://github.com/babel/babylon/pull/94)) @danharper
- Fix declare class with qualified type identifier ([#97](https://github.com/babel/babylon/pull/97)) @danez
- Remove exponentiationOperator, asyncFunctions, trailingFunctionCommas plugins and enable them by default ([#98](https://github.com/babel/babylon/pull/98)) @danez
## 6.9.0 (2016-08-16)
### New syntax support
- Add JSX spread children ([#42](https://github.com/babel/babylon/pull/42)) @calebmer
(Be aware that React is not going to support this syntax)
```js
<div>
{...todos.map(todo => <Todo key={todo.id} todo={todo}/>)}
</div>
```
- Add support for declare module.exports ([#72](https://github.com/babel/babylon/pull/72)) @danez
```js
declare module "foo" {
declare module.exports: {}
}
```
### New Features
- If supplied, attach filename property to comment node loc. ([#80](https://github.com/babel/babylon/pull/80)) @divmain
- Add identifier name to node loc field ([#90](https://github.com/babel/babylon/pull/90)) @kittens
### Bug Fixes
- Fix exponential operator to behave according to spec ([#75](https://github.com/babel/babylon/pull/75)) @danez
- Fix lookahead to not add comments to arrays which are not cloned ([#76](https://github.com/babel/babylon/pull/76)) @danez
- Fix accidental fall-through in Flow type parsing. ([#82](https://github.com/babel/babylon/pull/82)) @xiemaisi
- Only allow declares inside declare module ([#73](https://github.com/babel/babylon/pull/73)) @danez
- Small fix for parsing type parameter declarations ([#83](https://github.com/babel/babylon/pull/83)) @gabelevi
- Fix arrow param locations with flow types ([#57](https://github.com/babel/babylon/pull/57)) @danez
- Fixes SyntaxError position with flow optional type ([#65](https://github.com/babel/babylon/pull/65)) @danez
### Internal
- Add codecoverage to tests @danez
- Fix tests to not save expected output if we expect the test to fail @danez
- Make a shallow clone of babel for testing @danez
- chore(package): update cross-env to version 2.0.0 ([#77](https://github.com/babel/babylon/pull/77)) @greenkeeperio-bot
- chore(package): update ava to version 0.16.0 ([#86](https://github.com/babel/babylon/pull/86)) @greenkeeperio-bot
- chore(package): update babel-plugin-istanbul to version 2.0.0 ([#89](https://github.com/babel/babylon/pull/89)) @greenkeeperio-bot
- chore(package): update nyc to version 8.0.0 ([#88](https://github.com/babel/babylon/pull/88)) @greenkeeperio-bot
## 6.8.4 (2016-07-06)
### Bug Fixes
- Fix the location of params, when flow and default value used ([#68](https://github.com/babel/babylon/pull/68)) @danez
## 6.8.3 (2016-07-02)
### Bug Fixes
- Fix performance regression introduced in 6.8.2 with conditionals ([#63](https://github.com/babel/babylon/pull/63)) @danez
## 6.8.2 (2016-06-24)
### Bug Fixes
- Fix parse error with yielding jsx elements in generators `function* it() { yield <a></a>; }` ([#31](https://github.com/babel/babylon/pull/31)) @eldereal
- When cloning nodes do not clone its comments ([#24](https://github.com/babel/babylon/pull/24)) @danez
- Fix parse errors when using arrow functions with an spread element and return type `(...props): void => {}` ([#10](https://github.com/babel/babylon/pull/10)) @danez
- Fix leading comments added from previous node ([#23](https://github.com/babel/babylon/pull/23)) @danez
- Fix parse errors with flow's optional arguments `(arg?) => {}` ([#19](https://github.com/babel/babylon/pull/19)) @danez
- Support negative numeric type literals @kittens
- Remove line terminator restriction after await keyword @kittens
- Remove grouped type arrow restriction as it seems flow no longer has it @kittens
- Fix parse error with generic methods that have the name `get` or `set` `class foo { get() {} }` ([#55](https://github.com/babel/babylon/pull/55)) @vkurchatkin
- Fix parse error with arrow functions that have flow type parameter declarations `<T>(x: T): T => x;` ([#54](https://github.com/babel/babylon/pull/54)) @gabelevi
### Documentation
- Document AST differences from ESTree ([#41](https://github.com/babel/babylon/pull/41)) @nene
- Move ast spec from babel/babel ([#46](https://github.com/babel/babylon/pull/46)) @hzoo
### Internal
- Enable skipped tests ([#16](https://github.com/babel/babylon/pull/16)) @danez
- Add script to test latest version of babylon with babel ([#21](https://github.com/babel/babylon/pull/21)) @danez
- Upgrade test runner ava @kittens
- Add missing generate-identifier-regex script @kittens
- Rename parser context types @kittens
- Add node v6 to travis testing @hzoo
- Update to Unicode v9 ([#45](https://github.com/babel/babylon/pull/45)) @mathiasbynens
## 6.8.1 (2016-06-06)
### New Feature
- Parse type parameter declarations with defaults like `type Foo<T = string> = T`
### Bug Fixes
- Type parameter declarations need 1 or more type parameters.
- The existential type `*` is not a valid type parameter.
- The existential type `*` is a primary type
### Spec Compliancy
- The param list for type parameter declarations now consists of `TypeParameter` nodes
- New `TypeParameter` AST Node (replaces using the `Identifier` node before)
```
interface TypeParameter <: Node {
bound: TypeAnnotation;
default: TypeAnnotation;
name: string;
variance: "plus" | "minus";
}
```
## 6.8.0 (2016-05-02)
#### New Feature
##### Parse Method Parameter Decorators ([#12](https://github.com/babel/babylon/pull/12))
> [Method Parameter Decorators](https://goo.gl/8MmCMG) is now a TC39 [stage 0 proposal](https://github.com/tc39/ecma262/blob/master/stage0.md).
Examples:
```js
class Foo {
constructor(@foo() x, @bar({ a: 123 }) @baz() y) {}
}
export default function func(@foo() x, @bar({ a: 123 }) @baz() y) {}
var obj = {
method(@foo() x, @bar({ a: 123 }) @baz() y) {}
};
```
##### Parse for-await statements (w/ `asyncGenerators` plugin) ([#17](https://github.com/babel/babylon/pull/17))
There is also a new node type, `ForAwaitStatement`.
> [Async generators and for-await](https://github.com/tc39/proposal-async-iteration) are now a [stage 2 proposal](https://github.com/tc39/ecma262#current-proposals).
Example:
```js
async function f() {
for await (let x of y);
}
```
... ...
Copyright (C) 2012-2014 by various contributors (see AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
... ...
<p align="center">
<img alt="babylon" src="https://raw.githubusercontent.com/babel/logo/master/babylon.png" width="700">
</p>
<p align="center">
Babylon is a JavaScript parser used in <a href="https://github.com/babel/babel">Babel</a>.
</p>
<p align="center">
<a href="https://www.npmjs.com/package/babylon"><img alt="NPM Version" src="https://img.shields.io/npm/v/babylon.svg?style=flat"></a>
<a href="https://travis-ci.org/babel/babylon"><img alt="Travis Status" src="https://img.shields.io/travis/babel/babylon/master.svg?style=flat&label=travis"></a>
<a href="https://codecov.io/gh/babel/babylon"><img alt="Codecov Status" src="https://img.shields.io/codecov/c/github/babel/babylon/master.svg?style=flat"></a>
</p>
- The latest ECMAScript version enabled by default (ES2017).
- Comment attachment.
- Support for JSX, Flow, Typescript.
- Support for experimental language proposals (accepting PRs for anything at least [stage-0](https://github.com/tc39/proposals/blob/master/stage-0-proposals.md)).
## Contributing
Check out [contributing.md](https://github.com/babel/babylon/blob/master/CONTRIBUTING.md)
## Credits
Heavily based on [acorn](https://github.com/marijnh/acorn) and [acorn-jsx](https://github.com/RReverser/acorn-jsx),
thanks to the awesome work of [@RReverser](https://github.com/RReverser) and [@marijnh](https://github.com/marijnh).
## API
### `babylon.parse(code, [options])`
### `babylon.parseExpression(code, [options])`
`parse()` parses the provided `code` as an entire ECMAScript program, while
`parseExpression()` tries to parse a single Expression with performance in
mind. When in doubt, use `.parse()`.
### Options
- **allowImportExportEverywhere**: By default, `import` and `export`
declarations can only appear at a program's top level. Setting this
option to `true` allows them anywhere where a statement is allowed.
- **allowReturnOutsideFunction**: By default, a return statement at
the top level raises an error. Set this to `true` to accept such
code.
- **allowSuperOutsideMethod**: TODO
- **sourceType**: Indicate the mode the code should be parsed in. Can be
either `"script"` or `"module"`.
- **sourceFilename**: Correlate output AST nodes with their source filename. Useful when generating code and source maps from the ASTs of multiple input files.
- **startLine**: By default, the first line of code parsed is treated as line 1. You can provide a line number to alternatively start with. Useful for integration with other source tools.
- **plugins**: Array containing the plugins that you want to enable.
- **strictMode**: TODO
- **ranges**: Adds a `ranges` property to each node: `[node.start, node.end]`
- **tokens**: Adds all parsed tokens to a `tokens` property on the `File` node
### Output
Babylon generates AST according to [Babel AST format][].
It is based on [ESTree spec][] with the following deviations:
> There is now an `estree` plugin which reverts these deviations
- [Literal][] token is replaced with [StringLiteral][], [NumericLiteral][], [BooleanLiteral][], [NullLiteral][], [RegExpLiteral][]
- [Property][] token is replaced with [ObjectProperty][] and [ObjectMethod][]
- [MethodDefinition][] is replaced with [ClassMethod][]
- [Program][] and [BlockStatement][] contain additional `directives` field with [Directive][] and [DirectiveLiteral][]
- [ClassMethod][], [ObjectProperty][], and [ObjectMethod][] value property's properties in [FunctionExpression][] is coerced/brought into the main method node.
AST for JSX code is based on [Facebook JSX AST][] with the addition of one node type:
- `JSXText`
[Babel AST format]: https://github.com/babel/babylon/blob/master/ast/spec.md
[ESTree spec]: https://github.com/estree/estree
[Literal]: https://github.com/estree/estree/blob/master/es5.md#literal
[Property]: https://github.com/estree/estree/blob/master/es5.md#property
[MethodDefinition]: https://github.com/estree/estree/blob/master/es2015.md#methoddefinition
[StringLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#stringliteral
[NumericLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#numericliteral
[BooleanLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#booleanliteral
[NullLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#nullliteral
[RegExpLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#regexpliteral
[ObjectProperty]: https://github.com/babel/babylon/blob/master/ast/spec.md#objectproperty
[ObjectMethod]: https://github.com/babel/babylon/blob/master/ast/spec.md#objectmethod
[ClassMethod]: https://github.com/babel/babylon/blob/master/ast/spec.md#classmethod
[Program]: https://github.com/babel/babylon/blob/master/ast/spec.md#programs
[BlockStatement]: https://github.com/babel/babylon/blob/master/ast/spec.md#blockstatement
[Directive]: https://github.com/babel/babylon/blob/master/ast/spec.md#directive
[DirectiveLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#directiveliteral
[FunctionExpression]: https://github.com/babel/babylon/blob/master/ast/spec.md#functionexpression
[Facebook JSX AST]: https://github.com/facebook/jsx/blob/master/AST.md
### Semver
Babylon follows semver in most situations. The only thing to note is that some spec-compliancy bug fixes may be released under patch versions.
For example: We push a fix to early error on something like [#107](https://github.com/babel/babylon/pull/107) - multiple default exports per file. That would be considered a bug fix even though it would cause a build to fail.
### Example
```javascript
require("babylon").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",
plugins: [
// enable jsx and flow syntax
"jsx",
"flow"
]
});
```
### Plugins
| Name | Code Example |
|------|--------------|
| `estree` ([repo](https://github.com/estree/estree)) | n/a |
| `jsx` ([repo](https://facebook.github.io/jsx/)) | `<a attr="b">{s}</a>` |
| `flow` ([repo](https://github.com/facebook/flow)) | `var a: string = "";` |
| `typescript` ([repo](https://github.com/Microsoft/TypeScript)) | `var a: string = "";` |
| `doExpressions` | `var a = do { if (true) { 'hi'; } };` |
| `objectRestSpread` ([proposal](https://github.com/tc39/proposal-object-rest-spread)) | `var a = { b, ...c };` |
| `decorators` (Stage 1) and `decorators2` (Stage 2 [proposal](https://github.com/tc39/proposal-decorators)) | `@a class A {}` |
| `classProperties` ([proposal](https://github.com/tc39/proposal-class-public-fields)) | `class A { b = 1; }` |
| `classPrivateProperties` ([proposal](https://github.com/tc39/proposal-private-fields)) | `class A { #b = 1; }` |
| `exportExtensions` ([proposal 1](https://github.com/leebyron/ecmascript-export-default-from)), ([proposal 2](https://github.com/leebyron/ecmascript-export-ns-from)) | Proposal 1: `export v from "mod"` Proposal 2: `export * as ns from "mod"` |
| `asyncGenerators` ([proposal](https://github.com/tc39/proposal-async-iteration)) | `async function*() {}`, `for await (let a of b) {}` |
| `functionBind` ([proposal](https://github.com/zenparsing/es-function-bind)) | `a::b`, `::console.log` |
| `functionSent` | `function.sent` |
| `dynamicImport` ([proposal](https://github.com/tc39/proposal-dynamic-import)) | `import('./guy').then(a)` |
| `numericSeparator` ([proposal](https://github.com/samuelgoto/proposal-numeric-separator)) | `1_000_000` |
| `optionalChaining` ([proposal](https://github.com/tc39/proposal-optional-chaining)) | `a?.b` |
| `importMeta` ([proposal](https://github.com/tc39/proposal-import-meta)) | `import.meta.url` |
| `bigInt` ([proposal](https://github.com/tc39/proposal-bigint)) | `100n` |
| `optionalCatchBinding` ([proposal](https://github.com/babel/proposals/issues/7)) | `try {throw 0;} catch{do();}` |
### FAQ
#### Will Babylon support a plugin system?
Previous issues: [babel/babel#1351](https://github.com/babel/babel/issues/1351), [#500](https://github.com/babel/babylon/issues/500).
We currently aren't willing to commit to supporting the API for plugins or the resulting ecosystem (there is already enough work maintaining Babel's own plugin system). It's not clear how to make that API effective, and it would limit out ability to refactor and optimize the codebase.
Our current recommendation for those that want to create their own custom syntax is for users to fork Babylon.
To consume your custom parser, you can add to your `.babelrc` via its npm package name or require it if using JavaScript,
```json
{
"parserOpts": {
"parser": "custom-fork-of-babylon-on-npm-here"
}
}
```
... ...
#!/usr/bin/env node
/* eslint no-var: 0 */
var babylon = require("..");
var fs = require("fs");
var filename = process.argv[2];
if (!filename) {
console.error("no filename specified");
process.exit(0);
}
var file = fs.readFileSync(filename, "utf8");
var ast = babylon.parse(file);
console.log(JSON.stringify(ast, null, " "));
... ...
"use strict";
// Which Unicode version should be used?
const version = "9.0.0";
const start = require("unicode-" +
version +
"/Binary_Property/ID_Start/code-points.js").filter(function(ch) {
return ch > 0x7f;
});
let last = -1;
const cont = [0x200c, 0x200d].concat(
require("unicode-" +
version +
"/Binary_Property/ID_Continue/code-points.js").filter(function(ch) {
return ch > 0x7f && search(start, ch, last + 1) == -1;
}),
);
function search(arr, ch, starting) {
for (let i = starting; arr[i] <= ch && i < arr.length; last = i++)
if (arr[i] === ch) return i;
return -1;
}
function pad(str, width) {
while (str.length < width) str = "0" + str;
return str;
}
function esc(code) {
const hex = code.toString(16);
if (hex.length <= 2) return "\\x" + pad(hex, 2);
else return "\\u" + pad(hex, 4);
}
function generate(chars) {
const astral = [];
let re = "";
for (let i = 0, at = 0x10000; i < chars.length; i++) {
const from = chars[i];
let to = from;
while (i < chars.length - 1 && chars[i + 1] == to + 1) {
i++;
to++;
}
if (to <= 0xffff) {
if (from == to) re += esc(from);
else if (from + 1 == to) re += esc(from) + esc(to);
else re += esc(from) + "-" + esc(to);
} else {
astral.push(from - at, to - from);
at = to;
}
}
return { nonASCII: re, astral: astral };
}
const startData = generate(start);
const contData = generate(cont);
console.log('let nonASCIIidentifierStartChars = "' + startData.nonASCII + '";');
console.log('let nonASCIIidentifierChars = "' + contData.nonASCII + '";');
console.log(
"const astralIdentifierStartCodes = " +
JSON.stringify(startData.astral) +
";",
);
console.log(
"const astralIdentifierCodes = " + JSON.stringify(contData.astral) + ";",
);
... ...
此 diff 太大无法显示。
{
"_args": [
[
{
"raw": "babylon@~7.0.0-beta.19",
"scope": null,
"escapedName": "babylon",
"name": "babylon",
"rawSpec": "~7.0.0-beta.19",
"spec": ">=7.0.0-beta.19 <7.1.0",
"type": "range"
},
"/Users/fzy/project/koa2_Sequelize_project/node_modules/jsdoc"
]
],
"_from": "babylon@>=7.0.0-beta.19 <7.1.0",
"_id": "babylon@7.0.0-beta.20",
"_inCache": true,
"_location": "/babylon",
"_nodeVersion": "8.1.4",
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/babylon-7.0.0-beta.20.tgz_1503153450138_0.7646075191441923"
},
"_npmUser": {
"name": "hzoo",
"email": "hi@henryzoo.com"
},
"_npmVersion": "5.3.0",
"_phantomChildren": {},
"_requested": {
"raw": "babylon@~7.0.0-beta.19",
"scope": null,
"escapedName": "babylon",
"name": "babylon",
"rawSpec": "~7.0.0-beta.19",
"spec": ">=7.0.0-beta.19 <7.1.0",
"type": "range"
},
"_requiredBy": [
"/jsdoc"
],
"_resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.20.tgz",
"_shasum": "7dbc70cc88de13334066fe5200e0efaa30c0490e",
"_shrinkwrap": null,
"_spec": "babylon@~7.0.0-beta.19",
"_where": "/Users/fzy/project/koa2_Sequelize_project/node_modules/jsdoc",
"author": {
"name": "Sebastian McKenzie",
"email": "sebmck@gmail.com"
},
"ava": {
"files": [
"test/*.js"
],
"source": [
"src/**/*.js",
"bin/**/*.js"
]
},
"bin": {
"babylon": "./bin/babylon.js"
},
"bugs": {
"url": "https://github.com/babel/babylon/issues"
},
"changelog": {
"repo": "babel/babylon",
"labels": {
"Tag: Breaking Change": ":boom: Breaking Change",
"Tag: Bug Fix": ":bug: Bug Fix",
"Tag: Docs": ":memo: Documentation",
"Tag: Internal": ":house: Internal",
"Tag: New Feature": ":rocket: New Feature",
"Tag: Polish": ":nail_care: Polish"
}
},
"contributors": [
{
"name": "List of Acorn contributors. Updated before every release."
},
{
"name": "Adrian Rakovsky"
},
{
"name": "Alistair Braidwood"
},
{
"name": "Andres Suarez"
},
{
"name": "Aparajita Fishman"
},
{
"name": "Arian Stolwijk"
},
{
"name": "Artem Govorov"
},
{
"name": "Brandon Mills"
},
{
"name": "Charles Hughes"
},
{
"name": "Conrad Irwin"
},
{
"name": "David Bonnet"
},
{
"name": "Forbes Lindesay"
},
{
"name": "Gilad Peleg"
},
{
"name": "impinball"
},
{
"name": "Ingvar Stepanyan"
},
{
"name": "Jesse McCarthy"
},
{
"name": "Jiaxing Wang"
},
{
"name": "Joel Kemp"
},
{
"name": "Johannes Herr"
},
{
"name": "Jürg Lehni"
},
{
"name": "keeyipchan"
},
{
"name": "Kevin Kwok"
},
{
"name": "krator"
},
{
"name": "Marijn Haverbeke"
},
{
"name": "Martin Carlberg"
},
{
"name": "Mathias Bynens"
},
{
"name": "Mathieu 'p01' Henri"
},
{
"name": "Max Schaefer"
},
{
"name": "Max Zerzouri"
},
{
"name": "Mihai Bazon"
},
{
"name": "Mike Rennie"
},
{
"name": "Nick Fitzgerald"
},
{
"name": "Oskar Schöldström"
},
{
"name": "Paul Harper"
},
{
"name": "Peter Rust"
},
{
"name": "PlNG"
},
{
"name": "r-e-d"
},
{
"name": "Rich Harris"
},
{
"name": "Sebastian McKenzie"
},
{
"name": "zsjforcn"
}
],
"dependencies": {},
"description": "A JavaScript parser",
"devDependencies": {
"ava": "^0.22.0",
"babel-core": "7.0.0-alpha.18",
"babel-eslint": "8.0.0-alpha.13",
"babel-helper-fixtures": "7.0.0-alpha.18",
"babel-plugin-external-helpers": "7.0.0-alpha.18",
"babel-plugin-istanbul": "^4.1.4",
"babel-preset-env": "2.0.0-alpha.18",
"babel-preset-flow": "7.0.0-alpha.18",
"chalk": "^2.0.0",
"cross-env": "^5.0.0",
"eslint": "^4.0.0",
"eslint-config-babel": "^7.0.1",
"eslint-plugin-flowtype": "^2.34.0",
"eslint-plugin-prettier": "^2.1.2",
"flow-bin": "^0.53.0",
"graceful-fs": "^4.1.11",
"husky": "^0.14.1",
"lint-staged": "^4.0.0",
"nyc": "^11.0.3",
"prettier": "^1.5.2",
"rimraf": "^2.5.4",
"rollup": "^0.47.0",
"rollup-plugin-babel": "^3.0.1",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-watch": "^4.0.0",
"unicode-9.0.0": "~0.7.0",
"util.promisify": "^1.0.0"
},
"directories": {},
"dist": {
"integrity": "sha512-kkMTbo/6QmDD+ggF4KaeMLNvf+RfHVtC4mZJcGDZsbQvRqUgG4yWdy6fh3FZbwwLX9BD6PGmAeKN08P5O8pGLQ==",
"shasum": "7dbc70cc88de13334066fe5200e0efaa30c0490e",
"tarball": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.20.tgz"
},
"engines": {
"node": ">=4.2.0"
},
"files": [
"bin",
"lib"
],
"gitHead": "f87b81a8b173cf8b07643b3615156c2fdc5c5c2f",
"homepage": "https://babeljs.io/",
"keywords": [
"babel",
"javascript",
"parser",
"babylon"
],
"license": "MIT",
"lint-staged": {
"*.js": [
"eslint --format=codeframe --fix",
"git add"
]
},
"main": "lib/index.js",
"maintainers": [
{
"name": "thejameskyle",
"email": "me@thejameskyle.com"
},
{
"name": "sebmck",
"email": "sebmck@gmail.com"
},
{
"name": "danez",
"email": "daniel@tschinder.de"
},
{
"name": "hzoo",
"email": "hi@henryzoo.com"
},
{
"name": "loganfsmyth",
"email": "loganfsmyth@gmail.com"
}
],
"name": "babylon",
"nyc": {
"include": [
"src/**/*.js",
"bin/**/*.js"
],
"sourceMap": false,
"instrument": false
},
"optionalDependencies": {},
"readme": "<p align=\"center\">\n <img alt=\"babylon\" src=\"https://raw.githubusercontent.com/babel/logo/master/babylon.png\" width=\"700\">\n</p>\n\n<p align=\"center\">\n Babylon is a JavaScript parser used in <a href=\"https://github.com/babel/babel\">Babel</a>.\n</p>\n\n<p align=\"center\">\n <a href=\"https://www.npmjs.com/package/babylon\"><img alt=\"NPM Version\" src=\"https://img.shields.io/npm/v/babylon.svg?style=flat\"></a>\n <a href=\"https://travis-ci.org/babel/babylon\"><img alt=\"Travis Status\" src=\"https://img.shields.io/travis/babel/babylon/master.svg?style=flat&label=travis\"></a>\n <a href=\"https://codecov.io/gh/babel/babylon\"><img alt=\"Codecov Status\" src=\"https://img.shields.io/codecov/c/github/babel/babylon/master.svg?style=flat\"></a>\n</p>\n\n - The latest ECMAScript version enabled by default (ES2017).\n - Comment attachment.\n - Support for JSX, Flow, Typescript.\n - Support for experimental language proposals (accepting PRs for anything at least [stage-0](https://github.com/tc39/proposals/blob/master/stage-0-proposals.md)).\n\n## Contributing\n\nCheck out [contributing.md](https://github.com/babel/babylon/blob/master/CONTRIBUTING.md)\n\n## Credits\n\nHeavily based on [acorn](https://github.com/marijnh/acorn) and [acorn-jsx](https://github.com/RReverser/acorn-jsx),\nthanks to the awesome work of [@RReverser](https://github.com/RReverser) and [@marijnh](https://github.com/marijnh).\n\n## API\n\n### `babylon.parse(code, [options])`\n\n### `babylon.parseExpression(code, [options])`\n\n`parse()` parses the provided `code` as an entire ECMAScript program, while\n`parseExpression()` tries to parse a single Expression with performance in\nmind. When in doubt, use `.parse()`.\n\n### Options\n\n- **allowImportExportEverywhere**: By default, `import` and `export`\n declarations can only appear at a program's top level. Setting this\n option to `true` allows them anywhere where a statement is allowed.\n\n- **allowReturnOutsideFunction**: By default, a return statement at\n the top level raises an error. Set this to `true` to accept such\n code.\n\n- **allowSuperOutsideMethod**: TODO\n\n- **sourceType**: Indicate the mode the code should be parsed in. Can be\n either `\"script\"` or `\"module\"`.\n\n- **sourceFilename**: Correlate output AST nodes with their source filename. Useful when generating code and source maps from the ASTs of multiple input files.\n\n- **startLine**: By default, the first line of code parsed is treated as line 1. You can provide a line number to alternatively start with. Useful for integration with other source tools.\n\n- **plugins**: Array containing the plugins that you want to enable.\n\n- **strictMode**: TODO\n\n- **ranges**: Adds a `ranges` property to each node: `[node.start, node.end]`\n\n- **tokens**: Adds all parsed tokens to a `tokens` property on the `File` node\n\n### Output\n\nBabylon generates AST according to [Babel AST format][].\nIt is based on [ESTree spec][] with the following deviations:\n\n> There is now an `estree` plugin which reverts these deviations\n\n- [Literal][] token is replaced with [StringLiteral][], [NumericLiteral][], [BooleanLiteral][], [NullLiteral][], [RegExpLiteral][]\n- [Property][] token is replaced with [ObjectProperty][] and [ObjectMethod][]\n- [MethodDefinition][] is replaced with [ClassMethod][]\n- [Program][] and [BlockStatement][] contain additional `directives` field with [Directive][] and [DirectiveLiteral][]\n- [ClassMethod][], [ObjectProperty][], and [ObjectMethod][] value property's properties in [FunctionExpression][] is coerced/brought into the main method node.\n\nAST for JSX code is based on [Facebook JSX AST][] with the addition of one node type:\n\n- `JSXText`\n\n[Babel AST format]: https://github.com/babel/babylon/blob/master/ast/spec.md\n[ESTree spec]: https://github.com/estree/estree\n\n[Literal]: https://github.com/estree/estree/blob/master/es5.md#literal\n[Property]: https://github.com/estree/estree/blob/master/es5.md#property\n[MethodDefinition]: https://github.com/estree/estree/blob/master/es2015.md#methoddefinition\n\n[StringLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#stringliteral\n[NumericLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#numericliteral\n[BooleanLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#booleanliteral\n[NullLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#nullliteral\n[RegExpLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#regexpliteral\n[ObjectProperty]: https://github.com/babel/babylon/blob/master/ast/spec.md#objectproperty\n[ObjectMethod]: https://github.com/babel/babylon/blob/master/ast/spec.md#objectmethod\n[ClassMethod]: https://github.com/babel/babylon/blob/master/ast/spec.md#classmethod\n[Program]: https://github.com/babel/babylon/blob/master/ast/spec.md#programs\n[BlockStatement]: https://github.com/babel/babylon/blob/master/ast/spec.md#blockstatement\n[Directive]: https://github.com/babel/babylon/blob/master/ast/spec.md#directive\n[DirectiveLiteral]: https://github.com/babel/babylon/blob/master/ast/spec.md#directiveliteral\n[FunctionExpression]: https://github.com/babel/babylon/blob/master/ast/spec.md#functionexpression\n\n[Facebook JSX AST]: https://github.com/facebook/jsx/blob/master/AST.md\n\n### Semver\n\nBabylon follows semver in most situations. The only thing to note is that some spec-compliancy bug fixes may be released under patch versions.\n\nFor example: We push a fix to early error on something like [#107](https://github.com/babel/babylon/pull/107) - multiple default exports per file. That would be considered a bug fix even though it would cause a build to fail.\n\n### Example\n\n```javascript\nrequire(\"babylon\").parse(\"code\", {\n // parse in strict mode and allow module declarations\n sourceType: \"module\",\n\n plugins: [\n // enable jsx and flow syntax\n \"jsx\",\n \"flow\"\n ]\n});\n```\n\n### Plugins\n\n| Name | Code Example |\n|------|--------------|\n| `estree` ([repo](https://github.com/estree/estree)) | n/a |\n| `jsx` ([repo](https://facebook.github.io/jsx/)) | `<a attr=\"b\">{s}</a>` |\n| `flow` ([repo](https://github.com/facebook/flow)) | `var a: string = \"\";` |\n| `typescript` ([repo](https://github.com/Microsoft/TypeScript)) | `var a: string = \"\";` |\n| `doExpressions` | `var a = do { if (true) { 'hi'; } };` |\n| `objectRestSpread` ([proposal](https://github.com/tc39/proposal-object-rest-spread)) | `var a = { b, ...c };` |\n| `decorators` (Stage 1) and `decorators2` (Stage 2 [proposal](https://github.com/tc39/proposal-decorators)) | `@a class A {}` |\n| `classProperties` ([proposal](https://github.com/tc39/proposal-class-public-fields)) | `class A { b = 1; }` |\n| `classPrivateProperties` ([proposal](https://github.com/tc39/proposal-private-fields)) | `class A { #b = 1; }` |\n| `exportExtensions` ([proposal 1](https://github.com/leebyron/ecmascript-export-default-from)), ([proposal 2](https://github.com/leebyron/ecmascript-export-ns-from)) | Proposal 1: `export v from \"mod\"` Proposal 2: `export * as ns from \"mod\"` |\n| `asyncGenerators` ([proposal](https://github.com/tc39/proposal-async-iteration)) | `async function*() {}`, `for await (let a of b) {}` |\n| `functionBind` ([proposal](https://github.com/zenparsing/es-function-bind)) | `a::b`, `::console.log` |\n| `functionSent` | `function.sent` |\n| `dynamicImport` ([proposal](https://github.com/tc39/proposal-dynamic-import)) | `import('./guy').then(a)` |\n| `numericSeparator` ([proposal](https://github.com/samuelgoto/proposal-numeric-separator)) | `1_000_000` |\n| `optionalChaining` ([proposal](https://github.com/tc39/proposal-optional-chaining)) | `a?.b` |\n| `importMeta` ([proposal](https://github.com/tc39/proposal-import-meta)) | `import.meta.url` |\n| `bigInt` ([proposal](https://github.com/tc39/proposal-bigint)) | `100n` |\n| `optionalCatchBinding` ([proposal](https://github.com/babel/proposals/issues/7)) | `try {throw 0;} catch{do();}` |\n\n### FAQ\n\n#### Will Babylon support a plugin system?\n\nPrevious issues: [babel/babel#1351](https://github.com/babel/babel/issues/1351), [#500](https://github.com/babel/babylon/issues/500).\n\nWe currently aren't willing to commit to supporting the API for plugins or the resulting ecosystem (there is already enough work maintaining Babel's own plugin system). It's not clear how to make that API effective, and it would limit out ability to refactor and optimize the codebase.\n\nOur current recommendation for those that want to create their own custom syntax is for users to fork Babylon.\n\nTo consume your custom parser, you can add to your `.babelrc` via its npm package name or require it if using JavaScript,\n\n```json\n{\n \"parserOpts\": {\n \"parser\": \"custom-fork-of-babylon-on-npm-here\"\n }\n}\n```\n",
"readmeFilename": "README.md",
"repository": {
"type": "git",
"url": "git+https://github.com/babel/babylon.git"
},
"scripts": {
"build": "yarn run clean && rollup -c",
"changelog": "git log `git describe --tags --abbrev=0`..HEAD --pretty=format:' * %s (%an)' | grep -v 'Merge pull request'",
"clean": "rimraf lib",
"flow": "flow",
"lint": "eslint src bin test",
"prepublish": "cross-env BABEL_ENV=production yarn run build",
"preversion": "yarn run test && npm run changelog",
"test": "yarn run lint && yarn run flow && yarn run build -- -m && yarn run test-only",
"test-coverage": "cross-env BABEL_ENV=test yarn run build && nyc --reporter=json --reporter=text yarn run test-only",
"test-only": "ava",
"watch": "yarn run clean && rollup -c --watch"
},
"version": "7.0.0-beta.20"
}
... ...
Copyright (c) 2014 Google Inc.
Copyright (c) 2012-2014 Jeff Williams
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
... ...
# Catharsis #
A JavaScript parser for
[Google Closure Compiler](https://developers.google.com/closure/compiler/docs/js-for-compiler#types)
and [JSDoc](https://github.com/jsdoc3/jsdoc) type expressions.
Catharsis is designed to be:
+ **Accurate**. Catharsis is based on a [PEG.js](http://pegjs.majda.cz/) grammar that's designed to
handle any valid type expression. It uses a [Mocha](http://visionmedia.github.com/mocha/) test suite
to verify the parser's accuracy.
+ **Fast**. Parse results are cached, so the parser is invoked only when necessary.
+ **Flexible**. Catharsis can convert a parse result back into a type expression, or into a
description of the type expression. In addition, Catharsis can parse
[JSDoc](https://github.com/jsdoc3/jsdoc)-style type expressions.
## Example ##
```js
var catharsis = require('catharsis');
// Google Closure Compiler parsing
var type = '!Object';
var parsedType;
try {
parsedType = catharsis.parse(type); // {"type":"NameExpression,"name":"Object","nullable":false}
} catch(e) {
console.error('unable to parse %s: %s', type, e);
}
// JSDoc-style type expressions enabled
var jsdocType = 'string[]'; // Closure Compiler expects Array.<string>
var parsedJsdocType;
try {
parsedJsdocType = catharsis.parse(jsdocType, {jsdoc: true});
} catch (e) {
console.error('unable to parse %s: %s', jsdocType, e);
}
// Converting parse results back to type expressions
catharsis.stringify(parsedType); // !Object
catharsis.stringify(parsedJsdocType); // string[]
catharsis.stringify(parsedJsdocType, {restringify: true}); // Array.<string>
// Converting parse results to descriptions of the type expression
catharsis.describe(parsedType).simple; // non-null Object
catharsis.describe(parsedJsdocType).simple; // Array of string
```
See the [test/specs directory](test/specs) for more examples of Catharsis' parse results.
## Methods ##
### parse(typeExpression, options) ###
Parse a type expression, and return the parse results. Throws an error if the type expression cannot
be parsed.
When called without options, Catharsis attempts to parse type expressions in the same way as
Closure Compiler. When the `jsdoc` option is enabled, Catharsis can also parse several kinds of
type expressions that are permitted in [JSDoc](https://github.com/jsdoc3/jsdoc):
+ The string `function` is treated as a function type with no parameters.
+ The period may be omitted from type applications. For example, `Array.<string>` and
`Array<string>` will be parsed in the same way.
+ You may append `[]` to a name expression (for example, `string[]`) to interpret it as a type
application with the expression `Array` (for example, `Array.<string>`).
+ Name expressions may contain the characters `#`, `~`, `:`, and `/`.
+ Name expressions may contain a suffix that is similar to a function signature (for example,
`MyClass(foo, bar)`).
+ Name expressions may contain a reserved word.
+ Record types may use types other than name expressions for keys.
#### Parameters ####
+ `type`: A string containing a Closure Compiler type expression.
+ `options`: Options for parsing the type expression.
+ `options.jsdoc`: Specifies whether to enable parsing of JSDoc-style type expressions. Defaults
to `false`.
+ `options.useCache`: Specifies whether to use the cache of parsed types. Defaults to `true`.
#### Returns ####
An object containing the parse results. See the [test/specs directory](test/specs) for examples of
the parse results for different type expressions.
The object also includes two non-enumerable properties:
+ `jsdoc`: A boolean indicating whether the type expression was parsed with JSDoc support enabled.
+ `typeExpression`: A string containing the type expression that was parsed.
### stringify(parsedType, options) ###
Stringify `parsedType`, and return the type expression. If validation is enabled, throws an error if
the stringified type expression cannot be parsed.
#### Parameters ####
+ `parsedType`: An object containing a parsed Closure Compiler type expression.
+ `options`: Options for stringifying the parse results.
+ `options.cssClass`: Synonym for `options.linkClass`. Deprecated in version 0.8.0; will be
removed in a future version.
+ `options.htmlSafe`: Specifies whether to return an HTML-safe string that replaces left angle
brackets (`<`) with the corresponding entity (`&lt;`). **Note**: Characters in name expressions
are not escaped.
+ `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is
provided. By default, no CSS class is added.
+ `options.links`: An object whose keys are name expressions and whose values are URIs. If a
name expression matches a key in `options.links`, the name expression will be wrapped in an
HTML `<a>` tag that links to the URI. If `options.linkClass` is specified, the `<a>` tag will
include a `class` attribute. **Note**: When using this option, parsed types are always
restringified, and the resulting string is not cached.
+ `options.restringify`: Forces Catharsis to restringify the parsed type. If this option is not
specified, and the parsed type object includes a `typeExpression` property, Catharsis will
return the `typeExpression` property without modification when possible. Defaults to `false`.
+ `options.useCache`: Specifies whether to use the cache of stringified type expressions.
Defaults to `true`.
+ `options.validate`: Specifies whether to validate the stringified parse results by attempting
to parse them as a type expression. If the stringified results are not parsable by default, you
must also provide the appropriate options to pass to the `parse()` method. Defaults to `false`.
#### Returns ####
A string containing the type expression.
### describe(parsedType, options) ###
Convert a parsed type to a description of the type expression. This method is especially useful if
your users are not familiar with the syntax for type expressions.
The `describe()` method returns the description in two formats:
+ **Simple format**. A string that provides a complete description of the type expression.
+ **Extended format**. An object that separates out some of the details about the outermost type
expression, such as whether the type is optional, nullable, or repeatable.
For example, if you call `describe('?function(new:MyObject, string)=')`, it returns the following
object:
```js
{
simple: 'optional nullable function(constructs MyObject, string)',
extended: {
description: 'function(string)',
modifiers: {
functionNew: 'Returns MyObject when called with new.',
functionThis: '',
optional: 'Optional.',
nullable: 'May be null.',
repeatable: ''
},
returns: ''
}
}
```
#### Parameters ####
+ `parsedType`: An object containing a parsed Closure Compiler type expression.
+ `options`: Options for creating the description.
+ `options.codeClass`: A CSS class to add to the tag that is wrapped around type names. Used
only if `options.codeTag` is provided. By default, no CSS class is added.
+ `options.codeTag`: The name of an HTML tag (for example, `code`) to wrap around type names.
For example, if this option is set to `code`, the type expression `Array.<string>` would have
the simple description `<code>Array</code> of <code>string</code>`.
+ `options.language`: A string identifying the language in which to generate the description.
The identifier should be an
[ISO 639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (for example,
`en`). It can optionally be followed by a hyphen and an
[ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) (for example,
`en-US`). If you use values other than `en`, you must provide translation resources in
`options.resources`. Defaults to `en`.
+ `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is
provided. By default, no CSS class is added.
+ `options.links`: An object whose keys are name expressions and whose values are URIs. If a
name expression matches a key in `options.links`, the name expression will be wrapped in an
HTML `<a>` tag that links to the URI. If `options.linkClass` is specified, the `<a>` tag will
include a `class` attribute. **Note**: When using this option, the description is not cached.
+ `options.resources`: An object that specifies how to describe type expressions for a given
language. The object's property names should use the same format as `options.language`. Each
property should contain an object in the same format as the translation resources in
[res/en.json](res/en.json). If you specify a value for `options.resources.en`, it will override
the defaults in [res/en.json](res/en.json).
+ `options.useCache`: Specifies whether to use the cache of descriptions. Defaults to `true`.
### Returns ###
An object with the following properties:
+ `simple`: A string that provides a complete description of the type expression.
+ `extended`: An object containing details about the outermost type expression.
+ `extended.description`: A string that provides a basic description of the type expression,
excluding the information contained in other properties.
+ `extended.modifiers`: Information about modifiers that apply to the type expression.
+ `extended.modifiers.functionNew`: A string describing what a function returns when called
with `new`. Used only for function types.
+ `extended.modifiers.functionThis`: A string describing what the keyword `this` refers to
within a function. Used only for function types.
+ `extended.modifiers.nullable`: A string indicating whether the type is nullable or
non-nullable.
+ `extended.modifiers.optional`: A string indicating whether the type is optional.
+ `extended.modifiers.repeatable`: A string indicating whether the type can be provided
+ `extended.returns`: A string describing the function's return value. Used only for function
types.
## Installation ##
With [npm](http://npmjs.org):
npm install catharsis
Or by cloning the git repo:
git clone git://github.com/hegemonic/catharsis.git
cd catharsis
npm install
## Roadmap and known issues ##
Take a look at the [issue tracker](https://github.com/hegemonic/catharsis/issues) to see what's in
store for Catharsis.
Bug reports, feature requests, and pull requests are always welcome! If you're working on a large
pull request, please contact me in advance so I can help things go smoothly.
**Note**: The parse tree's format should not be considered final until Catharsis reaches version
1.0. I'll do my best to provide release notes for any changes.
## Changelog ##
+ 0.8.9 (July 2017): Type expressions that include an `@` sign (for example,
`module:@prefix/mymodule~myCallback`) are now supported.
+ 0.8.8 (April 2016): Corrected the description of type applications other than arrays that contain
a single type (for example, `Promise.<string>`).
+ 0.8.7 (June 2015):
+ Record types that use numeric literals as property names (for example, `{0: string}`) are now
parsed correctly.
+ Record types with a property that contains a function, with no space after the preceding colon
(for example, `{foo:function()}`), are now parsed correctly.
+ Repeatable function parameters are no longer required to be enclosed in brackets, regardless
of whether JSDoc-style type expressions are enabled. In addition, the brackets are omitted when
stringifying a parsed type expression.
+ 0.8.6 (December 2014): Improved the description of the unknown type.
+ 0.8.5 (December 2014): Added support for postfix nullable/non-nullable operators combined with the
optional operator (for example, `foo?=`).
+ 0.8.4 (December 2014): JSDoc-style nested arrays (for example, `number[][]`) are now parsed
correctly when JSDoc-style type expressions are enabled.
+ 0.8.3 (October 2014):
+ Type applications are no longer required to include a period (`.`) as a separator, regardless
of whether JSDoc-style type expressions are enabled.
+ Type unions that are not enclosed in parentheses can now include the repeatable (`...`)
modifier when JSDoc-style type expressions are enabled.
+ Name expressions may now be enclosed in single or double quotation marks when JSDoc-style
type expressions are enabled.
+ 0.8.2 (June 2014): Fixed a compatibility issue with the JSDoc fork of Mozilla Rhino.
+ 0.8.1 (June 2014): Added support for type unions that are not enclosed in parentheses, and that
contain nullable or non-nullable modifiers (for example, `!string|!number`).
+ 0.8.0 (May 2014):
+ Added a `describe()` method, which converts a parsed type to a description of the type.
+ Added a `linkClass` option to the `stringify()` method, and deprecated the existing `cssClass`
option. The `cssClass` option will be removed in a future release.
+ Clarified and corrected several sections in the `README`.
+ 0.7.1 (April 2014): In record types, property names that begin with a keyword (for example,
`undefinedHTML`) are now parsed correctly when JSDoc-style type expressions are enabled.
+ 0.7.0 (October 2013):
+ Repeatable type expressions other than name expressions (for example, `...function()`) are now
parsed and stringified correctly.
+ Type expressions that are both repeatable and either nullable or non-nullable (for example,
`...!number`) are now parsed and stringified correctly.
+ Name expressions are now parsed correctly when they match a property name in an object
instance (for example, `constructor`).
+ 0.6.0 (September 2013): Added support for the type expression `function[]` when JSDoc-style type
expressions are enabled.
+ 0.5.6 (April 2013):
+ For consistency with Google Closure Library, parentheses are no longer required around type
unions. (In previous versions, the parentheses could be omitted when JSDoc support was enabled.)
+ For consistency with Google Closure Library, you can now use postfix notation for the `?`
(nullable) and `!` (non-nullable) modifiers. For example, `?string` and `string?` are now
treated as equivalent.
+ String literals and numeric literals are now allowed as property names within name
expressions. For example, the name expression `Foo."bar"` is now parsed correctly.
+ 0.5.5 (April 2013): Corrected a parsing issue with name expressions that end with a value enclosed
in parentheses.
+ 0.5.4 (April 2013):
+ Repeatable literals (for example, `...*`) are now parsed correctly.
+ When JSDoc-style type expressions are enabled, a name expression can now contain a value
enclosed in parentheses at the end of the name expression (for example, `MyClass(2)`).
+ 0.5.3 (March 2013): The `parse()` method now correctly parses name expressions that contain
hyphens.
+ 0.5.2 (March 2013): The `parse()` method now correctly parses function types when JSDoc-style type
expressions are enabled.
+ 0.5.1 (March 2013): Newlines and extra spaces are now removed from type expressions before they
are parsed.
+ 0.5.0 (March 2013):
+ The `parse()` method's `lenient` option has been renamed to `jsdoc`. **Note**: This change is
not backwards-compatible with previous versions.
+ The `stringify()` method now accepts `cssClass` and `links` options, which you can use to
add HTML links to a type expression.
+ 0.4.3 (March 2013):
+ The `stringify()` method no longer caches HTML-safe type expressions as if they were normal
type expressions.
+ The `stringify()` method's options parameter may now include an `options.restringify`
property, and the behavior of the `options.useCache` property has changed.
+ 0.4.2 (March 2013):
+ When lenient parsing is enabled, name expressions can now contain the characters `:` and `/`.
+ When lenient parsing is enabled, a name expression followed by `[]` (for example, `string[]`)
will be interpreted as a type application with the expression `Array` (for example,
`Array.<string>`).
+ 0.4.1 (March 2013):
+ The `parse()` and `stringify()` methods now honor all of the specified options.
+ When lenient parsing is enabled, name expressions can now contain a reserved word.
+ 0.4.0 (March 2013):
+ Catharsis now supports a lenient parsing option that can parse several kinds of malformed type
expressions. See the documentation for details.
+ The objects containing parse results are now frozen.
+ The objects containing parse results now have two non-enumerable properties:
+ `lenient`: A boolean indicating whether the type expression was parsed in lenient mode.
+ `typeExpression`: A string containing the original type expression.
+ The `stringify()` method now honors the `useCache` option. If a parsed type includes a
`typeExpression` property, and `useCache` is not set to `false`, the stringified type will be
identical to the original type expression.
+ 0.3.1 (March 2013): Type expressions that begin with a reserved word, such as `integer`, are now
parsed correctly.
+ 0.3.0 (March 2013):
+ The `parse()` and `stringify()` methods are now synchronous, and the `parseSync()` and
`stringifySync()` methods have been removed. **Note**: This change is not backwards-compatible
with previous versions.
+ The parse results now use a significantly different format from previous versions. The new
format is more expressive and is similar, but not identical, to the format used by the
[doctrine](https://github.com/Constellation/doctrine) parser. **Note**: This change is not
backwards-compatible with previous versions.
+ Name expressions that contain a reserved word now include a `reservedWord: true` property.
+ Union types that are optional or nullable, or that can be passed a variable number of times,
are now parsed and stringified correctly.
+ Optional function types and record types are now parsed and stringified correctly.
+ Function types now longer include `new` or `this` properties unless the properties are defined
in the type expression. In addition, the `new` and `this` properties can now use any type
expression.
+ In record types, the key for a field type can now use any type expression.
+ Standalone single-character literals, such as ALL (`*`), are now parsed and stringified
correctly.
+ `null` and `undefined` literals with additional properties, such as `repeatable`, are now
stringified correctly.
+ 0.2.0 (November 2012):
+ Added `stringify()` and `stringifySync()` methods, which convert a parsed type to a type
expression.
+ Simplified the parse results for function signatures. **Note**: This change is not
backwards-compatible with previous versions.
+ Corrected minor errors in README.md.
+ 0.1.1 (November 2012): Added `opts` argument to `parse()` and `parseSync()` methods. **Note**: The
change to `parse()` is not backwards-compatible with previous versions.
+ 0.1.0 (November 2012): Initial release.
## License ##
[MIT license](https://github.com/hegemonic/catharsis/blob/master/LICENSE).
... ...
#!/usr/bin/env node
'use strict';
// Command-line tool that parses a type expression and dumps a JSON version of the parse tree.
var catharsis = require('../catharsis');
var path = require('path');
var util = require('util');
var command = path.basename(process.argv[1]);
var typeExpression = process.argv[2];
var opts = {
describe: false,
jsdoc: false
};
var parsedType;
function usage() {
console.log(util.format('Usage:\n %s typeExpression [--jsdoc] [--describe]', command));
}
function done(err) {
/*eslint no-process-exit: 0 */
process.exit(err === undefined ? 0 : err);
}
process.argv.slice(3).forEach(function(arg) {
var parsedArg = arg.replace(/^\-{2}/, '');
if (opts[parsedArg] !== undefined) {
opts[parsedArg] = true;
} else {
console.error('Unknown option "%s"', arg);
usage();
done(1);
}
});
if (!typeExpression) {
usage();
done(1);
} else {
try {
parsedType = catharsis.parse(typeExpression, opts);
if (opts.describe) {
parsedType = catharsis.describe(parsedType);
}
} catch (e) {
console.error(util.format('Unable to parse "%s" (exception follows):', typeExpression));
console.error(e.stack || e.message);
done(1);
}
console.log(JSON.stringify(parsedType, null, 2));
done();
}
... ...
/**
* Catharsis
* A parser for Google Closure Compiler type expressions, powered by PEG.js.
*
* @author Jeff Williams <jeffrey.l.williams@gmail.com>
* @license MIT License <http://opensource.org/licenses/mit-license.php/>
*/
'use strict';
var describe = require('./lib/describe');
var parse = require('./lib/parser').parse;
var stringify = require('./lib/stringify');
var typeExpressionCache = {
normal: {},
jsdoc: {}
};
var parsedTypeCache = {
normal: {},
htmlSafe: {}
};
var descriptionCache = {
normal: {}
};
function getTypeExpressionCache(options) {
if (options.useCache === false) {
return null;
} else if (options.jsdoc === true) {
return typeExpressionCache.jsdoc;
} else {
return typeExpressionCache.normal;
}
}
function getParsedTypeCache(options) {
if (options.useCache === false || options.links !== null || options.links !== undefined) {
return null;
} else if (options.htmlSafe === true) {
return parsedTypeCache.htmlSafe;
} else {
return parsedTypeCache.normal;
}
}
function getDescriptionCache(options) {
if (options.useCache === false || options.links !== null || options.links !== undefined) {
return null;
} else {
return descriptionCache.normal;
}
}
// can't return the original if any of the following are true:
// 1. restringification was requested
// 2. htmlSafe option was requested
// 3. links option was provided
// 4. typeExpression property is missing
function canReturnOriginalExpression(parsedType, options) {
return options.restringify !== true && options.htmlSafe !== true &&
(options.links === null || options.links === undefined) &&
Object.prototype.hasOwnProperty.call(parsedType, 'typeExpression');
}
// Add non-enumerable properties to a result object, then freeze it.
function prepareFrozenObject(obj, expr, options) {
Object.defineProperty(obj, 'jsdoc', {
value: options.jsdoc === true ? true : false
});
if (expr) {
Object.defineProperty(obj, 'typeExpression', {
value: expr
});
}
return Object.freeze(obj);
}
function cachedParse(expr, options) {
var cache = getTypeExpressionCache(options);
var parsedType;
if (cache && Object.prototype.hasOwnProperty.call(cache, expr)) {
return cache[expr];
} else {
parsedType = parse(expr, options);
parsedType = prepareFrozenObject(parsedType, expr, options);
if (cache) {
cache[expr] = parsedType;
}
return parsedType;
}
}
function cachedStringify(parsedType, options) {
var cache = getParsedTypeCache(options);
var json;
if (canReturnOriginalExpression(parsedType, options)) {
return parsedType.typeExpression;
} else if (cache) {
json = JSON.stringify(parsedType);
cache[json] = cache[json] || stringify(parsedType, options);
return cache[json];
} else {
return stringify(parsedType, options);
}
}
function cachedDescribe(parsedType, options) {
var cache = getDescriptionCache(options);
var json;
var result;
if (cache) {
json = JSON.stringify(parsedType);
cache[json] = cache[json] || describe(parsedType, options);
return cache[json];
} else {
result = describe(parsedType, options);
result = prepareFrozenObject(result, null, options);
return result;
}
}
function Catharsis() {
this.Types = require('./lib/types');
}
Catharsis.prototype.parse = function(typeExpr, options) {
options = options || {};
typeExpr = typeExpr.replace(/[\r\n]/g, '')
.replace(/\s+/g, ' ')
.trim();
return cachedParse(typeExpr, options);
};
Catharsis.prototype.stringify = function(parsedType, options) {
var result;
options = options || {};
result = cachedStringify(parsedType, options);
if (options.validate) {
this.parse(result, options);
}
return result;
};
Catharsis.prototype.describe = function(parsedType, options) {
options = options || {};
return cachedDescribe(parsedType, options);
};
module.exports = new Catharsis();
... ...
'use strict';
var _ = require('underscore-contrib');
var fs = require('fs');
var path = require('path');
var stringify = require('./stringify');
var Types = require('./types');
var util = require('util');
var DEFAULT_OPTIONS = {
language: 'en',
resources: {
en: JSON.parse(fs.readFileSync(path.join(__dirname, '../res/en.json'), 'utf8'))
}
};
// order matters for these!
var FUNCTION_DETAILS = ['new', 'this'];
var FUNCTION_DETAILS_VARIABLES = ['functionNew', 'functionThis'];
var MODIFIERS = ['optional', 'nullable', 'repeatable'];
var TEMPLATE_VARIABLES = [
'application',
'codeTagClose',
'codeTagOpen',
'element',
'field',
'functionNew',
'functionParams',
'functionReturns',
'functionThis',
'keyApplication',
'name',
'nullable',
'optional',
'param',
'prefix',
'repeatable',
'suffix',
'type'
];
var FORMATS = {
EXTENDED: 'extended',
SIMPLE: 'simple'
};
function makeTagOpen(codeTag, codeClass) {
var tagOpen = '';
var tags = codeTag ? codeTag.split(' ') : [];
tags.forEach(function(tag) {
var tagClass = codeClass ? util.format(' class="%s"', codeClass) : '';
tagOpen += util.format('<%s%s>', tag, tagClass);
});
return tagOpen;
}
function makeTagClose(codeTag) {
var tagClose = '';
var tags = codeTag ? codeTag.split(' ') : [];
tags.reverse();
tags.forEach(function(tag) {
tagClose += util.format('</%s>', tag);
});
return tagClose;
}
function Result() {
this.description = '';
this.modifiers = {
functionNew: '',
functionThis: '',
optional: '',
nullable: '',
repeatable: ''
};
this.returns = '';
}
function Context(props) {
var self = this;
props = props || {};
TEMPLATE_VARIABLES.forEach(function(variable) {
self[variable] = props[variable] || '';
});
}
function Describer(opts) {
var options;
this._useLongFormat = true;
options = this._options = _.defaults(opts || {}, DEFAULT_OPTIONS);
this._stringifyOptions = _.defaults(options, {_ignoreModifiers: true});
// use a dictionary, not a Context object, so we can more easily merge this into Context objects
this._i18nContext = {
codeTagClose: makeTagClose(options.codeTag),
codeTagOpen: makeTagOpen(options.codeTag, options.codeClass)
};
// templates start out as strings; we lazily replace them with template functions
this._templates = options.resources[options.language];
if (!this._templates) {
throw new Error('I18N resources are not available for the language ' + options.language);
}
}
function modifierKind(useLongFormat) {
return useLongFormat ? FORMATS.EXTENDED : FORMATS.SIMPLE;
}
function buildModifierStrings(describer, modifiers, type, useLongFormat) {
var result = {};
modifiers.forEach(function(modifier) {
var key = modifierKind(useLongFormat);
var modifierStrings = describer[modifier](type[modifier]);
result[modifier] = modifierStrings[key];
});
return result;
}
function addModifiers(describer, context, result, type, useLongFormat) {
var keyPrefix = 'modifiers.' + modifierKind(useLongFormat);
var modifiers = buildModifierStrings(describer, MODIFIERS, type, useLongFormat);
MODIFIERS.forEach(function(modifier) {
var modifierText = modifiers[modifier] || '';
result.modifiers[modifier] = modifierText;
if (!useLongFormat) {
context[modifier] = modifierText;
}
});
context.prefix = describer._translate(keyPrefix + '.prefix', context);
context.suffix = describer._translate(keyPrefix + '.suffix', context);
}
function addFunctionModifiers(describer, context, result, type, useLongFormat) {
var functionDetails = buildModifierStrings(describer, FUNCTION_DETAILS, type, useLongFormat);
var kind = modifierKind(useLongFormat);
var strings = [];
FUNCTION_DETAILS.forEach(function(functionDetail, i) {
var functionExtraInfo = functionDetails[functionDetail] || '';
var functionDetailsVariable = FUNCTION_DETAILS_VARIABLES[i];
result.modifiers[functionDetailsVariable] = functionExtraInfo;
if (!useLongFormat) {
context[functionDetailsVariable] += functionExtraInfo;
}
});
}
// Replace 2+ whitespace characters with a single whitespace character.
function collapseSpaces(string) {
return string.replace(/(\s)+/g, '$1');
}
Describer.prototype._stringify = function(type, typeString, useLongFormat) {
var context = new Context({
type: typeString || stringify(type, this._stringifyOptions)
});
var result = new Result();
addModifiers(this, context, result, type, useLongFormat);
result.description = this._translate('type', context).trim();
return result;
};
Describer.prototype._translate = function(key, context) {
var result;
var templateFunction = _.getPath(this._templates, key);
context = context || new Context();
if (templateFunction === undefined) {
throw new Error(util.format('The template %s does not exist for the language %s', key,
this._options.language));
}
// compile and cache the template function if necessary
if (typeof templateFunction === 'string') {
// force the templates to use the `context` object
templateFunction = templateFunction.replace(/\<\%\= /g, '<%= context.');
templateFunction = _.template(templateFunction, null, {variable: 'context'});
_.setPath(this._templates, templateFunction, key);
}
result = (templateFunction(_.extend(context, this._i18nContext)) || '')
// strip leading spaces
.replace(/^\s+/, '');
result = collapseSpaces(result);
return result;
};
Describer.prototype._modifierHelper = function(key, modifierPrefix, context) {
modifierPrefix = modifierPrefix || '';
return {
extended: key ?
this._translate(util.format('%s.%s.%s', modifierPrefix, FORMATS.EXTENDED, key),
context) :
'',
simple: key ?
this._translate(util.format('%s.%s.%s', modifierPrefix, FORMATS.SIMPLE, key), context) :
''
};
};
Describer.prototype._translateModifier = function(key, context) {
return this._modifierHelper(key, 'modifiers', context);
};
Describer.prototype._translateFunctionModifier = function(key, context) {
return this._modifierHelper(key, 'function', context);
};
function getApplicationKey(type, applications) {
if (applications.length === 1) {
if (/[Aa]rray/.test(type.expression.name)) {
return 'array';
} else {
return 'other';
}
} else if (/[Ss]tring/.test(applications[0].name)) {
// object with string keys
return 'object';
} else {
// object with non-string keys
return 'objectNonString';
}
}
Describer.prototype.application = function(type, useLongFormat) {
var applications = type.applications.slice(0);
var context = new Context();
var key = 'application.' + getApplicationKey(type, applications);
var result = new Result();
var self = this;
addModifiers(this, context, result, type, useLongFormat);
context.type = this.type(type.expression).description;
context.application = this.type(applications.pop()).description;
context.keyApplication = applications.length ? this.type(applications.pop()).description : '';
result.description = this._translate(key, context).trim();
return result;
};
function reduceMultiple(context, keyName, contextName, translate, previous, current, index, items) {
var key =
index === 0 ? '.first.many' :
index === (items.length - 1) ? '.last.many' :
'.middle.many';
key = keyName + key;
context[contextName] = items[index];
return previous + translate(key, context);
}
Describer.prototype.elements = function(type, useLongFormat) {
var context = new Context();
var items = type.elements.slice(0);
var result = new Result();
addModifiers(this, context, result, type, useLongFormat);
result.description = this._combineMultiple(items, context, 'union', 'element', useLongFormat);
return result;
};
Describer.prototype.new = function(funcNew) {
var context = new Context({'functionNew': this.type(funcNew).description});
var key = funcNew ? 'new' : '';
return this._translateFunctionModifier(key, context);
};
Describer.prototype.nullable = function(nullable) {
var key = nullable === true ? 'nullable' :
nullable === false ? 'nonNullable' :
'';
return this._translateModifier(key);
};
Describer.prototype.optional = function(optional) {
var key = (optional === true) ? 'optional' : '';
return this._translateModifier(key);
};
Describer.prototype.repeatable = function(repeatable) {
var key = (repeatable === true) ? 'repeatable' : '';
return this._translateModifier(key);
};
Describer.prototype._combineMultiple = function(items, context, keyName, contextName,
useLongFormat) {
var result = new Result();
var self = this;
var strings;
strings = typeof items[0] === 'string' ?
items.slice(0) :
items.map(function(item) {
return self.type(item).description;
});
switch(strings.length) {
case 0:
// falls through
case 1:
context[contextName] = strings[0] || '';
result.description = this._translate(keyName + '.first.one', context);
break;
case 2:
strings.forEach(function(item, idx) {
var key = keyName + (idx === 0 ? '.first' : '.last' ) + '.two';
context[contextName] = item;
result.description += self._translate(key, context);
});
break;
default:
result.description = strings.reduce(reduceMultiple.bind(null, context, keyName,
contextName, this._translate.bind(this)), '');
}
return result.description.trim();
};
Describer.prototype.params = function(params, functionContext) {
var context = new Context();
var result = new Result();
var self = this;
var strings;
// TODO: this hardcodes the order and placement of functionNew and functionThis; need to move
// this to the template (and also track whether to put a comma after the last modifier)
functionContext = functionContext || {};
params = params || [];
strings = params.map(function(param) {
return self.type(param).description;
});
if (functionContext.functionThis) {
strings.unshift(functionContext.functionThis);
}
if (functionContext.functionNew) {
strings.unshift(functionContext.functionNew);
}
result.description = this._combineMultiple(strings, context, 'params', 'param', false);
return result;
};
Describer.prototype.this = function(funcThis) {
var context = new Context({'functionThis': this.type(funcThis).description});
var key = funcThis ? 'this' : '';
return this._translateFunctionModifier(key, context);
};
Describer.prototype.type = function(type, useLongFormat) {
var result = new Result();
if (useLongFormat === undefined) {
useLongFormat = this._useLongFormat;
}
// ensure we don't use the long format for inner types
this._useLongFormat = false;
if (!type) {
return result;
}
switch(type.type) {
case Types.AllLiteral:
result = this._stringify(type, this._translate('all'), useLongFormat);
break;
case Types.FunctionType:
result = this._signature(type, useLongFormat);
break;
case Types.NameExpression:
result = this._stringify(type, null, useLongFormat);
break;
case Types.NullLiteral:
result = this._stringify(type, this._translate('null'), useLongFormat);
break;
case Types.RecordType:
result = this._record(type, useLongFormat);
break;
case Types.TypeApplication:
result = this.application(type, useLongFormat);
break;
case Types.TypeUnion:
result = this.elements(type, useLongFormat);
break;
case Types.UndefinedLiteral:
result = this._stringify(type, this._translate('undefined'), useLongFormat);
break;
case Types.UnknownLiteral:
result = this._stringify(type, this._translate('unknown'), useLongFormat);
break;
default:
throw new Error('Unknown type: ' + JSON.stringify(type));
}
return result;
};
Describer.prototype._record = function(type, useLongFormat) {
var context = new Context();
var items;
var result = new Result();
items = this._recordFields(type.fields);
addModifiers(this, context, result, type, useLongFormat);
result.description = this._combineMultiple(items, context, 'record', 'field', useLongFormat);
return result;
};
Describer.prototype._recordFields = function(fields) {
var context = new Context();
var result = [];
var self = this;
if (!fields.length) {
return result;
}
result = fields.map(function(field) {
var key = 'field.' + (field.value ? 'typed' : 'untyped');
context.name = self.type(field.key).description;
if (field.value) {
context.type = self.type(field.value).description;
}
return self._translate(key, context);
});
return result;
};
Describer.prototype._addLinks = function(nameString) {
var linkClass = '';
var options = this._options;
var result = nameString;
if (options.links && Object.prototype.hasOwnProperty.call(options.links, nameString)) {
if (options.linkClass) {
linkClass = util.format(' class="%s"', options.linkClass);
}
nameString = util.format('<a href="%s"%s>%s</a>', options.links[nameString], linkClass,
nameString);
}
return nameString;
};
Describer.prototype.result = function(type, useLongFormat) {
var context = new Context();
var description;
var key = 'function.' + modifierKind(useLongFormat) + '.returns';
var result = new Result();
context.type = this.type(type).description;
addModifiers(this, context, result, type, useLongFormat);
result.description = this._translate(key, context);
return result;
};
Describer.prototype._signature = function(type, useLongFormat) {
var context = new Context();
var functionModifiers;
var kind = modifierKind(useLongFormat);
var result = new Result();
var returns;
var self = this;
addModifiers(this, context, result, type, useLongFormat);
addFunctionModifiers(this, context, result, type, useLongFormat);
context.functionParams = this.params(type.params || [], context).description;
if (type.result) {
returns = this.result(type.result, useLongFormat);
if (useLongFormat) {
result.returns = returns.description;
} else {
context.functionReturns = returns.description;
}
}
result.description += this._translate('function.' + kind + '.signature', context).trim();
return result;
};
module.exports = function(type, options) {
var simple = new Describer(options).type(type, false);
var extended = new Describer(options).type(type);
[simple, extended].forEach(function(result) {
result.description = collapseSpaces(result.description.trim());
});
return {
simple: simple.description,
extended: extended
};
};
... ...
此 diff 太大无法显示。
'use strict';
var _ = require('underscore-contrib');
// JSON schema types
var ARRAY = 'array';
var BOOLEAN = 'boolean';
var OBJECT = 'object';
var STRING = 'string';
var UNDEFINED = 'undefined';
var TYPES = require('./types');
var TYPE_NAMES = _.values(TYPES);
module.exports = {
id: '#parsedType',
type: [OBJECT, UNDEFINED],
additionalProperties: false,
properties: {
type: {
type: STRING,
enum: TYPE_NAMES
},
// field type
key: { '$ref': '#parsedType' },
value: { '$ref': '#parsedType' },
// function type
params: {
type: ARRAY,
items: { '$ref': '#parsedType' }
},
'new': { '$ref': '#parsedType' },
'this': { '$ref': '#parsedType' },
result: {'$ref': '#parsedType' },
// name expression
name: STRING,
// record type
fields: {
type: ARRAY,
items: { '$ref': '#parsedType' }
},
// type application
expression: { '$ref': '#parsedType' },
applications: {
type: ARRAY,
minItems: 1,
maxItems: 2,
items: { '$ref': '#parsedType' }
},
// type union
elements: {
type: ARRAY,
minItems: 1,
items: { '$ref': '#parsedType' }
},
optional: BOOLEAN,
nullable: BOOLEAN,
repeatable: BOOLEAN,
reservedWord: BOOLEAN
},
required: [ 'type' ]
};
... ...
'use strict';
var Types = require('./types');
function Stringifier(options) {
this._options = options || {};
this._options.linkClass = this._options.linkClass || this._options.cssClass;
}
Stringifier.prototype.applications = function(applications) {
var result = '';
var strings = [];
if (!applications) {
return result;
}
for (var i = 0, l = applications.length; i < l; i++) {
strings.push(this.type(applications[i]));
}
if (this._options.htmlSafe) {
result = '.&lt;';
} else {
result = '.<';
}
result += strings.join(', ') + '>';
return result;
};
Stringifier.prototype.elements = function(elements) {
var result = '';
var strings = [];
if (!elements) {
return result;
}
for (var i = 0, l = elements.length; i < l; i++) {
strings.push(this.type(elements[i]));
}
result = '(' + strings.join('|') + ')';
return result;
};
Stringifier.prototype.name = function(name) {
return name || '';
};
Stringifier.prototype.new = function(funcNew) {
return funcNew ? 'new:' + this.type(funcNew) : '';
};
Stringifier.prototype.nullable = function(nullable) {
switch (nullable) {
case true:
return '?';
case false:
return '!';
default:
return '';
}
};
Stringifier.prototype.optional = function(optional) {
if (optional === true) {
return '=';
} else {
return '';
}
};
Stringifier.prototype.params = function(params) {
var result = '';
var strings = [];
if (!params || params.length === 0) {
return result;
}
for (var i = 0, l = params.length; i < l; i++) {
strings.push(this.type(params[i]));
}
result = strings.join(', ');
return result;
};
Stringifier.prototype.result = function(result) {
return result ? ': ' + this.type(result) : '';
};
Stringifier.prototype.this = function(funcThis) {
return funcThis ? 'this:' + this.type(funcThis) : '';
};
Stringifier.prototype.type = function(type) {
var typeString = '';
if (!type) {
return typeString;
}
switch(type.type) {
case Types.AllLiteral:
typeString = this._formatNameAndType(type, '*');
break;
case Types.FunctionType:
typeString = this._signature(type);
break;
case Types.NullLiteral:
typeString = this._formatNameAndType(type, 'null');
break;
case Types.RecordType:
typeString = this._record(type);
break;
case Types.TypeApplication:
typeString = this.type(type.expression) + this.applications(type.applications);
break;
case Types.UndefinedLiteral:
typeString = this._formatNameAndType(type, 'undefined');
break;
case Types.TypeUnion:
typeString = this.elements(type.elements);
break;
case Types.UnknownLiteral:
typeString = this._formatNameAndType(type, '?');
break;
default:
typeString = this._formatNameAndType(type);
}
// add optional/nullable/repeatable modifiers
if (!this._options._ignoreModifiers) {
typeString = this._addModifiers(type, typeString);
}
return typeString;
};
Stringifier.prototype.stringify = Stringifier.prototype.type;
Stringifier.prototype.key = Stringifier.prototype.type;
Stringifier.prototype._record = function(type) {
var fields = this._recordFields(type.fields);
return '{' + fields.join(', ') + '}';
};
Stringifier.prototype._recordFields = function(fields) {
var field;
var keyAndValue;
var result = [];
if (!fields) {
return result;
}
for (var i = 0, l = fields.length; i < l; i++) {
field = fields[i];
keyAndValue = this.key(field.key);
keyAndValue += field.value ? ': ' + this.type(field.value) : '';
result.push(keyAndValue);
}
return result;
};
function combineNameAndType(nameString, typeString) {
var separator = (nameString && typeString) ? ':' : '';
return nameString + separator + typeString;
}
// Adds optional, nullable, and repeatable modifiers if necessary.
Stringifier.prototype._addModifiers = function(type, typeString) {
var combined;
var optional = '';
var repeatable = '';
if (type.repeatable) {
repeatable = '...';
}
combined = this.nullable(type.nullable) + combineNameAndType('', typeString);
optional = this.optional(type.optional);
return repeatable + combined + optional;
};
Stringifier.prototype._addLinks = function(nameString) {
var openTag;
var linkClass = '';
var options = this._options;
if (options.links && Object.prototype.hasOwnProperty.call(options.links, nameString)) {
if (options.linkClass) {
linkClass = ' class="' + options.linkClass + '"';
}
openTag = '<a href="' + options.links[nameString] + '"' + linkClass + '>';
nameString = openTag + nameString + '</a>';
}
return nameString;
};
Stringifier.prototype._formatNameAndType = function(type, literal) {
var nameString = type.name || literal || '';
var typeString = type.type ? this.type(type.type) : '';
nameString = this._addLinks(nameString);
return combineNameAndType(nameString, typeString);
};
Stringifier.prototype._signature = function(type) {
var param;
var prop;
var signature;
var params = [];
// these go within the signature's parens, in this order
var props = [
'new',
'this',
'params'
];
for (var i = 0, l = props.length; i < l; i++) {
prop = props[i];
param = this[prop](type[prop]);
if (param.length > 0) {
params.push(param);
}
}
signature = 'function(' + params.join(', ') + ')';
signature += this.result(type.result);
return signature;
};
module.exports = function(type, options) {
return new Stringifier(options).stringify(type);
};
... ...
'use strict';
module.exports = Object.freeze({
// `*`
AllLiteral: 'AllLiteral',
// like `blah` in `{blah: string}`
FieldType: 'FieldType',
// like `function(string): string`
FunctionType: 'FunctionType',
// any string literal, such as `string` or `My.Namespace`
NameExpression: 'NameExpression',
// null
NullLiteral: 'NullLiteral',
// like `{foo: string}`
RecordType: 'RecordType',
// like `Array.<string>`
TypeApplication: 'TypeApplication',
// like `(number|string)`
TypeUnion: 'TypeUnion',
// undefined
UndefinedLiteral: 'UndefinedLiteral',
// `?`
UnknownLiteral: 'UnknownLiteral'
});
... ...
{
"_args": [
[
{
"raw": "catharsis@~0.8.9",
"scope": null,
"escapedName": "catharsis",
"name": "catharsis",
"rawSpec": "~0.8.9",
"spec": ">=0.8.9 <0.9.0",
"type": "range"
},
"/Users/fzy/project/koa2_Sequelize_project/node_modules/jsdoc"
]
],
"_from": "catharsis@>=0.8.9 <0.9.0",
"_id": "catharsis@0.8.9",
"_inCache": true,
"_location": "/catharsis",
"_nodeVersion": "6.10.2",
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/catharsis-0.8.9.tgz_1499903127213_0.83025440457277"
},
"_npmUser": {
"name": "hegemonic",
"email": "jeffrey.l.williams@gmail.com"
},
"_npmVersion": "3.10.10",
"_phantomChildren": {},
"_requested": {
"raw": "catharsis@~0.8.9",
"scope": null,
"escapedName": "catharsis",
"name": "catharsis",
"rawSpec": "~0.8.9",
"spec": ">=0.8.9 <0.9.0",
"type": "range"
},
"_requiredBy": [
"/jsdoc"
],
"_resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
"_shasum": "98cc890ca652dd2ef0e70b37925310ff9e90fc8b",
"_shrinkwrap": null,
"_spec": "catharsis@~0.8.9",
"_where": "/Users/fzy/project/koa2_Sequelize_project/node_modules/jsdoc",
"author": {
"name": "Jeff Williams",
"email": "jeffrey.l.williams@gmail.com"
},
"bugs": {
"url": "https://github.com/hegemonic/catharsis/issues"
},
"dependencies": {
"underscore-contrib": "~0.3.0"
},
"description": "A JavaScript parser for Google Closure Compiler and JSDoc type expressions.",
"devDependencies": {
"mocha": "~2.0.1",
"pegjs": "https://github.com/dmajda/pegjs/tarball/eaca5f0acf97b66ef141fed84aa95d4e72e33757",
"should": "~4.0.4",
"tv4": "https://github.com/geraintluff/tv4/tarball/eb7561072d44943306e5fd88b55b4a4c98cb6c75"
},
"directories": {},
"dist": {
"shasum": "98cc890ca652dd2ef0e70b37925310ff9e90fc8b",
"tarball": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz"
},
"engines": {
"node": ">= 0.10"
},
"gitHead": "e318f14f6d9b615fb2b90e8fac681b12fd98b03e",
"homepage": "https://github.com/hegemonic/catharsis#readme",
"license": "MIT",
"main": "catharsis.js",
"maintainers": [
{
"name": "hegemonic",
"email": "jeffrey.l.williams@gmail.com"
}
],
"name": "catharsis",
"optionalDependencies": {},
"readme": "# Catharsis #\n\nA JavaScript parser for\n[Google Closure Compiler](https://developers.google.com/closure/compiler/docs/js-for-compiler#types)\nand [JSDoc](https://github.com/jsdoc3/jsdoc) type expressions.\n\nCatharsis is designed to be:\n\n+ **Accurate**. Catharsis is based on a [PEG.js](http://pegjs.majda.cz/) grammar that's designed to\nhandle any valid type expression. It uses a [Mocha](http://visionmedia.github.com/mocha/) test suite\nto verify the parser's accuracy.\n+ **Fast**. Parse results are cached, so the parser is invoked only when necessary.\n+ **Flexible**. Catharsis can convert a parse result back into a type expression, or into a\ndescription of the type expression. In addition, Catharsis can parse\n[JSDoc](https://github.com/jsdoc3/jsdoc)-style type expressions.\n\n\n## Example ##\n\n```js\nvar catharsis = require('catharsis');\n\n// Google Closure Compiler parsing\nvar type = '!Object';\nvar parsedType;\ntry {\n parsedType = catharsis.parse(type); // {\"type\":\"NameExpression,\"name\":\"Object\",\"nullable\":false}\n} catch(e) {\n console.error('unable to parse %s: %s', type, e);\n}\n\n// JSDoc-style type expressions enabled\nvar jsdocType = 'string[]'; // Closure Compiler expects Array.<string>\nvar parsedJsdocType;\ntry {\n parsedJsdocType = catharsis.parse(jsdocType, {jsdoc: true});\n} catch (e) {\n console.error('unable to parse %s: %s', jsdocType, e);\n}\n\n// Converting parse results back to type expressions\ncatharsis.stringify(parsedType); // !Object\ncatharsis.stringify(parsedJsdocType); // string[]\ncatharsis.stringify(parsedJsdocType, {restringify: true}); // Array.<string>\n\n// Converting parse results to descriptions of the type expression\ncatharsis.describe(parsedType).simple; // non-null Object\ncatharsis.describe(parsedJsdocType).simple; // Array of string\n```\n\nSee the [test/specs directory](test/specs) for more examples of Catharsis' parse results.\n\n\n## Methods ##\n\n### parse(typeExpression, options) ###\nParse a type expression, and return the parse results. Throws an error if the type expression cannot\nbe parsed.\n\nWhen called without options, Catharsis attempts to parse type expressions in the same way as\nClosure Compiler. When the `jsdoc` option is enabled, Catharsis can also parse several kinds of\ntype expressions that are permitted in [JSDoc](https://github.com/jsdoc3/jsdoc):\n\n+ The string `function` is treated as a function type with no parameters.\n+ The period may be omitted from type applications. For example, `Array.<string>` and\n`Array<string>` will be parsed in the same way.\n+ You may append `[]` to a name expression (for example, `string[]`) to interpret it as a type\napplication with the expression `Array` (for example, `Array.<string>`).\n+ Name expressions may contain the characters `#`, `~`, `:`, and `/`.\n+ Name expressions may contain a suffix that is similar to a function signature (for example,\n`MyClass(foo, bar)`).\n+ Name expressions may contain a reserved word.\n+ Record types may use types other than name expressions for keys.\n\n#### Parameters ####\n+ `type`: A string containing a Closure Compiler type expression.\n+ `options`: Options for parsing the type expression.\n + `options.jsdoc`: Specifies whether to enable parsing of JSDoc-style type expressions. Defaults\n to `false`.\n + `options.useCache`: Specifies whether to use the cache of parsed types. Defaults to `true`.\n\n#### Returns ####\nAn object containing the parse results. See the [test/specs directory](test/specs) for examples of\nthe parse results for different type expressions.\n\nThe object also includes two non-enumerable properties:\n\n+ `jsdoc`: A boolean indicating whether the type expression was parsed with JSDoc support enabled.\n+ `typeExpression`: A string containing the type expression that was parsed.\n\n### stringify(parsedType, options) ###\nStringify `parsedType`, and return the type expression. If validation is enabled, throws an error if\nthe stringified type expression cannot be parsed.\n\n#### Parameters ####\n+ `parsedType`: An object containing a parsed Closure Compiler type expression.\n+ `options`: Options for stringifying the parse results.\n + `options.cssClass`: Synonym for `options.linkClass`. Deprecated in version 0.8.0; will be\n removed in a future version.\n + `options.htmlSafe`: Specifies whether to return an HTML-safe string that replaces left angle\n brackets (`<`) with the corresponding entity (`&lt;`). **Note**: Characters in name expressions\n are not escaped.\n + `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is\n provided. By default, no CSS class is added.\n + `options.links`: An object whose keys are name expressions and whose values are URIs. If a\n name expression matches a key in `options.links`, the name expression will be wrapped in an\n HTML `<a>` tag that links to the URI. If `options.linkClass` is specified, the `<a>` tag will\n include a `class` attribute. **Note**: When using this option, parsed types are always\n restringified, and the resulting string is not cached.\n + `options.restringify`: Forces Catharsis to restringify the parsed type. If this option is not\n specified, and the parsed type object includes a `typeExpression` property, Catharsis will\n return the `typeExpression` property without modification when possible. Defaults to `false`.\n + `options.useCache`: Specifies whether to use the cache of stringified type expressions.\n Defaults to `true`.\n + `options.validate`: Specifies whether to validate the stringified parse results by attempting\n to parse them as a type expression. If the stringified results are not parsable by default, you\n must also provide the appropriate options to pass to the `parse()` method. Defaults to `false`.\n\n#### Returns ####\nA string containing the type expression.\n\n### describe(parsedType, options) ###\nConvert a parsed type to a description of the type expression. This method is especially useful if\nyour users are not familiar with the syntax for type expressions.\n\nThe `describe()` method returns the description in two formats:\n\n+ **Simple format**. A string that provides a complete description of the type expression.\n+ **Extended format**. An object that separates out some of the details about the outermost type\nexpression, such as whether the type is optional, nullable, or repeatable.\n\nFor example, if you call `describe('?function(new:MyObject, string)=')`, it returns the following\nobject:\n\n```js\n{\n simple: 'optional nullable function(constructs MyObject, string)',\n extended: {\n description: 'function(string)',\n modifiers: {\n functionNew: 'Returns MyObject when called with new.',\n functionThis: '',\n optional: 'Optional.',\n nullable: 'May be null.',\n repeatable: ''\n },\n returns: ''\n }\n}\n```\n\n#### Parameters ####\n+ `parsedType`: An object containing a parsed Closure Compiler type expression.\n+ `options`: Options for creating the description.\n + `options.codeClass`: A CSS class to add to the tag that is wrapped around type names. Used\n only if `options.codeTag` is provided. By default, no CSS class is added.\n + `options.codeTag`: The name of an HTML tag (for example, `code`) to wrap around type names.\n For example, if this option is set to `code`, the type expression `Array.<string>` would have\n the simple description `<code>Array</code> of <code>string</code>`.\n + `options.language`: A string identifying the language in which to generate the description.\n The identifier should be an\n [ISO 639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (for example,\n `en`). It can optionally be followed by a hyphen and an\n [ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) (for example,\n `en-US`). If you use values other than `en`, you must provide translation resources in\n `options.resources`. Defaults to `en`.\n + `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is\n provided. By default, no CSS class is added.\n + `options.links`: An object whose keys are name expressions and whose values are URIs. If a\n name expression matches a key in `options.links`, the name expression will be wrapped in an\n HTML `<a>` tag that links to the URI. If `options.linkClass` is specified, the `<a>` tag will\n include a `class` attribute. **Note**: When using this option, the description is not cached.\n + `options.resources`: An object that specifies how to describe type expressions for a given\n language. The object's property names should use the same format as `options.language`. Each\n property should contain an object in the same format as the translation resources in\n [res/en.json](res/en.json). If you specify a value for `options.resources.en`, it will override\n the defaults in [res/en.json](res/en.json).\n + `options.useCache`: Specifies whether to use the cache of descriptions. Defaults to `true`.\n\n### Returns ###\nAn object with the following properties:\n\n+ `simple`: A string that provides a complete description of the type expression.\n+ `extended`: An object containing details about the outermost type expression.\n + `extended.description`: A string that provides a basic description of the type expression,\n excluding the information contained in other properties.\n + `extended.modifiers`: Information about modifiers that apply to the type expression.\n + `extended.modifiers.functionNew`: A string describing what a function returns when called\n with `new`. Used only for function types.\n + `extended.modifiers.functionThis`: A string describing what the keyword `this` refers to\n within a function. Used only for function types.\n + `extended.modifiers.nullable`: A string indicating whether the type is nullable or\n non-nullable.\n + `extended.modifiers.optional`: A string indicating whether the type is optional.\n + `extended.modifiers.repeatable`: A string indicating whether the type can be provided\n + `extended.returns`: A string describing the function's return value. Used only for function\n types.\n\n\n## Installation ##\n\nWith [npm](http://npmjs.org):\n\n npm install catharsis\n\nOr by cloning the git repo:\n\n git clone git://github.com/hegemonic/catharsis.git\n cd catharsis\n npm install\n\n\n## Roadmap and known issues ##\n\nTake a look at the [issue tracker](https://github.com/hegemonic/catharsis/issues) to see what's in\nstore for Catharsis.\n\nBug reports, feature requests, and pull requests are always welcome! If you're working on a large\npull request, please contact me in advance so I can help things go smoothly.\n\n**Note**: The parse tree's format should not be considered final until Catharsis reaches version\n1.0. I'll do my best to provide release notes for any changes.\n\n\n## Changelog ##\n\n+ 0.8.9 (July 2017): Type expressions that include an `@` sign (for example,\n`module:@prefix/mymodule~myCallback`) are now supported.\n+ 0.8.8 (April 2016): Corrected the description of type applications other than arrays that contain\na single type (for example, `Promise.<string>`).\n+ 0.8.7 (June 2015):\n + Record types that use numeric literals as property names (for example, `{0: string}`) are now\n parsed correctly.\n + Record types with a property that contains a function, with no space after the preceding colon\n (for example, `{foo:function()}`), are now parsed correctly.\n + Repeatable function parameters are no longer required to be enclosed in brackets, regardless\n of whether JSDoc-style type expressions are enabled. In addition, the brackets are omitted when\n stringifying a parsed type expression.\n+ 0.8.6 (December 2014): Improved the description of the unknown type.\n+ 0.8.5 (December 2014): Added support for postfix nullable/non-nullable operators combined with the\noptional operator (for example, `foo?=`).\n+ 0.8.4 (December 2014): JSDoc-style nested arrays (for example, `number[][]`) are now parsed\ncorrectly when JSDoc-style type expressions are enabled.\n+ 0.8.3 (October 2014):\n + Type applications are no longer required to include a period (`.`) as a separator, regardless\n of whether JSDoc-style type expressions are enabled.\n + Type unions that are not enclosed in parentheses can now include the repeatable (`...`)\n modifier when JSDoc-style type expressions are enabled.\n + Name expressions may now be enclosed in single or double quotation marks when JSDoc-style\n type expressions are enabled.\n+ 0.8.2 (June 2014): Fixed a compatibility issue with the JSDoc fork of Mozilla Rhino.\n+ 0.8.1 (June 2014): Added support for type unions that are not enclosed in parentheses, and that\ncontain nullable or non-nullable modifiers (for example, `!string|!number`).\n+ 0.8.0 (May 2014):\n + Added a `describe()` method, which converts a parsed type to a description of the type.\n + Added a `linkClass` option to the `stringify()` method, and deprecated the existing `cssClass`\n option. The `cssClass` option will be removed in a future release.\n + Clarified and corrected several sections in the `README`.\n+ 0.7.1 (April 2014): In record types, property names that begin with a keyword (for example,\n`undefinedHTML`) are now parsed correctly when JSDoc-style type expressions are enabled.\n+ 0.7.0 (October 2013):\n + Repeatable type expressions other than name expressions (for example, `...function()`) are now\n parsed and stringified correctly.\n + Type expressions that are both repeatable and either nullable or non-nullable (for example,\n `...!number`) are now parsed and stringified correctly.\n + Name expressions are now parsed correctly when they match a property name in an object\n instance (for example, `constructor`).\n+ 0.6.0 (September 2013): Added support for the type expression `function[]` when JSDoc-style type\nexpressions are enabled.\n+ 0.5.6 (April 2013):\n + For consistency with Google Closure Library, parentheses are no longer required around type\n unions. (In previous versions, the parentheses could be omitted when JSDoc support was enabled.)\n + For consistency with Google Closure Library, you can now use postfix notation for the `?`\n (nullable) and `!` (non-nullable) modifiers. For example, `?string` and `string?` are now\n treated as equivalent.\n + String literals and numeric literals are now allowed as property names within name\n expressions. For example, the name expression `Foo.\"bar\"` is now parsed correctly.\n+ 0.5.5 (April 2013): Corrected a parsing issue with name expressions that end with a value enclosed\nin parentheses.\n+ 0.5.4 (April 2013):\n + Repeatable literals (for example, `...*`) are now parsed correctly.\n + When JSDoc-style type expressions are enabled, a name expression can now contain a value\n enclosed in parentheses at the end of the name expression (for example, `MyClass(2)`).\n+ 0.5.3 (March 2013): The `parse()` method now correctly parses name expressions that contain\nhyphens.\n+ 0.5.2 (March 2013): The `parse()` method now correctly parses function types when JSDoc-style type\nexpressions are enabled.\n+ 0.5.1 (March 2013): Newlines and extra spaces are now removed from type expressions before they\nare parsed.\n+ 0.5.0 (March 2013):\n + The `parse()` method's `lenient` option has been renamed to `jsdoc`. **Note**: This change is\n not backwards-compatible with previous versions.\n + The `stringify()` method now accepts `cssClass` and `links` options, which you can use to\n add HTML links to a type expression.\n+ 0.4.3 (March 2013):\n + The `stringify()` method no longer caches HTML-safe type expressions as if they were normal\n type expressions.\n + The `stringify()` method's options parameter may now include an `options.restringify`\n property, and the behavior of the `options.useCache` property has changed.\n+ 0.4.2 (March 2013):\n + When lenient parsing is enabled, name expressions can now contain the characters `:` and `/`.\n + When lenient parsing is enabled, a name expression followed by `[]` (for example, `string[]`)\n will be interpreted as a type application with the expression `Array` (for example,\n `Array.<string>`).\n+ 0.4.1 (March 2013):\n + The `parse()` and `stringify()` methods now honor all of the specified options.\n + When lenient parsing is enabled, name expressions can now contain a reserved word.\n+ 0.4.0 (March 2013):\n + Catharsis now supports a lenient parsing option that can parse several kinds of malformed type\n expressions. See the documentation for details.\n + The objects containing parse results are now frozen.\n + The objects containing parse results now have two non-enumerable properties:\n + `lenient`: A boolean indicating whether the type expression was parsed in lenient mode.\n + `typeExpression`: A string containing the original type expression.\n + The `stringify()` method now honors the `useCache` option. If a parsed type includes a\n `typeExpression` property, and `useCache` is not set to `false`, the stringified type will be\n identical to the original type expression.\n+ 0.3.1 (March 2013): Type expressions that begin with a reserved word, such as `integer`, are now\nparsed correctly.\n+ 0.3.0 (March 2013):\n + The `parse()` and `stringify()` methods are now synchronous, and the `parseSync()` and\n `stringifySync()` methods have been removed. **Note**: This change is not backwards-compatible\n with previous versions.\n + The parse results now use a significantly different format from previous versions. The new\n format is more expressive and is similar, but not identical, to the format used by the\n [doctrine](https://github.com/Constellation/doctrine) parser. **Note**: This change is not\n backwards-compatible with previous versions.\n + Name expressions that contain a reserved word now include a `reservedWord: true` property.\n + Union types that are optional or nullable, or that can be passed a variable number of times,\n are now parsed and stringified correctly.\n + Optional function types and record types are now parsed and stringified correctly.\n + Function types now longer include `new` or `this` properties unless the properties are defined\n in the type expression. In addition, the `new` and `this` properties can now use any type\n expression.\n + In record types, the key for a field type can now use any type expression.\n + Standalone single-character literals, such as ALL (`*`), are now parsed and stringified\n correctly.\n + `null` and `undefined` literals with additional properties, such as `repeatable`, are now\n stringified correctly.\n+ 0.2.0 (November 2012):\n + Added `stringify()` and `stringifySync()` methods, which convert a parsed type to a type\n expression.\n + Simplified the parse results for function signatures. **Note**: This change is not\n backwards-compatible with previous versions.\n + Corrected minor errors in README.md.\n+ 0.1.1 (November 2012): Added `opts` argument to `parse()` and `parseSync()` methods. **Note**: The\nchange to `parse()` is not backwards-compatible with previous versions.\n+ 0.1.0 (November 2012): Initial release.\n\n## License ##\n\n[MIT license](https://github.com/hegemonic/catharsis/blob/master/LICENSE).\n",
"readmeFilename": "README.md",
"repository": {
"type": "git",
"url": "git+https://github.com/hegemonic/catharsis.git"
},
"scripts": {
"prepublish": "./node_modules/pegjs/bin/pegjs ./lib/parser.pegjs",
"test": "mocha"
},
"version": "0.8.9"
}
... ...
{
"all": "any type",
"application": {
"array": "<%= prefix %> <%= codeTagOpen %>Array<%= codeTagClose %> of <%= application %> <%= suffix %>",
"object": "<%= prefix %> <%= codeTagOpen %>Object<%= codeTagClose %> with <%= application %> properties <%= suffix %>",
"objectNonString": "<%= prefix %> <%= codeTagOpen %>Object<%= codeTagClose %> with <%= keyApplication %> keys and <%= application %> properties <%= suffix %>",
"other": "<%= prefix %> <%= codeTagOpen %><%= type %> containing <%= application %> <%= suffix %>"
},
"function": {
"extended": {
"new": "Returns <%= functionNew %> when called with <%= codeTagOpen %>new<%= codeTagClose %>.",
"returns": "Returns <%= type %>.",
"signature": "function(<%= functionParams %>)",
"this": "Within the function, <%= codeTagOpen %>this<%= codeTagClose %> refers to <%= functionThis %>."
},
"simple": {
"new": "constructs <%= functionNew %>",
"returns": "returns <%= type %>",
"signature": "<%= prefix %> function(<%= functionParams %>) <%= functionReturns %>",
"this": "<%= codeTagOpen %>this<%= codeTagClose %> = <%= functionThis %>"
}
},
"modifiers": {
"extended": {
"nonNullable": "Must not be null.",
"nullable": "May be null.",
"optional": "Optional.",
"prefix": "",
"repeatable": "May be provided more than once.",
"suffix": ""
},
"simple": {
"nonNullable": "non-null",
"nullable": "nullable",
"optional": "optional",
"prefix": "<%= optional %> <%= nullable %> <%= repeatable %>",
"repeatable": "repeatable",
"suffix": ""
}
},
"name": "<%= codeTagOpen %>{{ name }}<%= codeTagClose %> <%= suffix %>",
"null": "null",
"params": {
"first": {
"one": "<%= param %>",
"two": "<%= param %>, ",
"many": "<%= param %>, "
},
"middle": {
"many": "<%= param %>, "
},
"last": {
"two": "<%= param %>",
"many": "<%= param %>"
}
},
"record": {
"first": {
"one": "<%= prefix %> {<%= field %>} <%= suffix %>",
"two": "<%= prefix %> {<%= field %>, ",
"many": "<%= prefix %> {<%= field %>, "
},
"middle": {
"many": "<%= field %>, "
},
"last": {
"two": "<%= field %>} <%= suffix %>",
"many": "<%= field %>} <%= suffix %>"
}
},
"field": {
"typed": "<%= name %>: <%= type %>",
"untyped": "<%= name %>"
},
"type": "<%= prefix %> <%= codeTagOpen %><%= type %><%= codeTagClose %> <%= suffix %>",
"undefined": "undefined",
"union": {
"first": {
"one": "<%= prefix %> <%= element %> <%= suffix %>",
"two": "<%= prefix %> (<%= element %> ",
"many": "<%= prefix %> (<%= element %>, "
},
"middle": {
"many": "<%= element %>, "
},
"last": {
"two": "or <%= element %>) <%= suffix %>",
"many": "or <%= element %>) <%= suffix %>"
}
},
"unknown": "unknown"
}
... ...
## 3.0.0 ##
* Bug fixes
* Add null and undefined in type declarations
* Remove explicit engines requirement
## 2.0.2 ##
* Bug fixes
## 2.0.1 ##
* Remove unnecessary development dependencies from npm shrinkwrap
## 2.0.0 ##
* Re-write in TypeScript
* Re-write to use xmlcreate (greatly simplifies module source)
* Added support for the ECMAScript 2015 Map and Set objects
* New method of calling module:
```javascript
var js2xmlparser = require("js2xmlparser");
var root = "root";
var data = { hello: "world" };
var options = {};
// old method (no longer works):
// js2xmlparser(root, data, options);
// new method:
js2xmlparser.parse(root, data, options);
```
* New options and changes to functionality of some existing options:
* `declaration` contains additional options
* `attributeString` has additional functionality
* `valueString` has additional functionality
* The functionality provided by `prettyPrinting` is now provided by the new
`format` option, which contains additional options
* `arrayMap` is now `wrapHandlers` to reflect the fact that wrapping is
provided for both arrays and ES2015 sets
* `convertMap` is now `typeHandlers` to match the name change to `arrayMap`
* The functionality provided by `useCDATA` is now provided by the new
`cdataInvalidChars` and `cdataKeys` options, which also provide additional
functionality
* Added support for document type definitions using the `dtd` option
## 1.0.0 ##
* First stable release
* Add arrayMap feature
* Switch to semantic versioning
* Switch to Apache 2.0 license
## 0.1.9 ##
* Fix error in example.js
## 0.1.8 ##
* Reconcile readme and tests with examples
## 0.1.7 ##
* Added .gitattributes to .gitignore file
* Minor tweaks to examples
## 0.1.6 ##
* Addition of alias string option
* Minor changes to examples
* Minor fixes to tests
## 0.1.5 ##
* Bug fixes
* Minor changes to examples
## 0.1.4 ##
* Removed callFunctions option (functionality already provided by convertMap option)
* Removed wrapArray option (functionality already provided by existing array functionality)
* Escape numbers when at tbe beginning of an element name
* Edits to documentation
* Added tests
* Added copyright headers to individual JS files
## 0.1.3 ##
* Fixed crash when undefined objects are converted to strings
* Added callFunctions option
* Added wrapArray option
* Added useCDATA option
* Added convertMap option
* Added copyright year and "and other contributors" to license
## 0.1.2 ##
* Fixed crash when null objects are converted to strings
## 0.1.1 ##
* Fixed accidental truncation of XML when pretty-printing is disabled
* Removed copyright year from license
## 0.1.0 ##
* Initial release
... ...
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### Terms and Conditions for use, reproduction, and distribution
#### 1. Definitions
“License” shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
“Licensor” shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
“Legal Entity” shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, “control” means **(i)** the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the
outstanding shares, or **(iii)** beneficial ownership of such entity.
“You” (or “Your”) shall mean an individual or Legal Entity exercising
permissions granted by this License.
“Source” form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
“Object” form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
“Work” shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
“Derivative Works” shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
“Contribution” shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
“submitted” means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as “Not a Contribution.”
“Contributor” shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
#### 2. Grant of Copyright License
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
#### 3. Grant of Patent License
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
#### 4. Redistribution
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
* **(a)** You must give any other recipients of the Work or Derivative Works a copy of
this License; and
* **(b)** You must cause any modified files to carry prominent notices stating that You
changed the files; and
* **(c)** You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
#### 5. Submission of Contributions
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
#### 6. Trademarks
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
#### 7. Disclaimer of Warranty
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
#### 8. Limitation of Liability
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
#### 9. Accepting Warranty or Additional Liability
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
_END OF TERMS AND CONDITIONS_
### APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets `[]` replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same “printed page” as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
... ...
js2xmlparser
Copyright (C) 2016-2017 Michael Kourlas
## Apache License, version 2.0 ##
The following components are provided under the [Apache License, version 2.0](https://www.apache.org/licenses/LICENSE-2.0):
xmlcreate
Copyright (C) 2016-2017 Michael Kourlas
... ...
# js2xmlparser #
[![Build Status](https://travis-ci.org/michaelkourlas/node-js2xmlparser.svg?branch=master)](https://travis-ci.org/michaelkourlas/node-js2xmlparser)
[![npm version](https://badge.fury.io/js/js2xmlparser.svg)](https://badge.fury.io/js/js2xmlparser)
## Overview ##
js2xmlparser is a Node.js module that parses JavaScript objects into XML.
## Features ##
Since XML is a data-interchange format, js2xmlparser is designed primarily for
JSON-type objects, arrays and primitive data types, like many of the other
JavaScript to XML parsers currently available for Node.js.
However, js2xmlparser is capable of parsing any object, including native
JavaScript objects such as `Date` and `RegExp`, by taking advantage of each
object's `toString` function or, if this function does not exist, the `String`
constructor.
js2xmlparser also has support for the new `Map` and `Set` objects introduced in
ECMAScript 2015, treating them as JSON-type objects and arrays respectively.
Support for `Map`s is necessary to generate XML with elements in a specific
order, since JSON-type objects do not guarantee insertion order. `Map` keys are
always converted to strings using the method described above.
js2xmlparser also supports a number of constructs unique to XML:
* attributes (through an attribute property in objects)
* mixed content (through value properties in objects)
* multiple elements with the same name (through arrays)
js2xmlparser can also pretty-print the XML it outputs.
## Installation ##
The easiest way to install js2xmlparser is using npm:
```
npm install js2xmlparser
```
You can also build js2xmlparser from source using gulp:
```
git clone https://github.com/michaelkourlas/node-js2xmlparser.git
npm install
gulp
```
You'll need to install gulp first if you don't have it:
```
npm install -g gulp
```
You can then copy the folder into your node_modules directory.
The `default` target will build the production variant of js2xmlparser, run all
tests, and build the documentation.
You can build the production variant without running tests using the target
`prod`. You can also build the development version using the target `dev`. At
the moment, the only difference between the two is that the development version
includes source maps.
## Usage ##
The documentation for the current version is available [here](http://www.kourlas.com/node-js2xmlparser/docs/3.0.0/).
You can also build the documentation using gulp:
```
gulp docs
```
## Examples ##
The following example illustrates the basic usage of js2xmlparser:
```javascript
var js2xmlparser = require("js2xmlparser");
var obj = {
"firstName": "John",
"lastName": "Smith",
"dateOfBirth": new Date(1964, 7, 26),
"address": {
"@": {
"type": "home"
},
"streetAddress": "3212 22nd St",
"city": "Chicago",
"state": "Illinois",
"zip": 10000
},
"phone": [
{
"@": {
"type": "home"
},
"#": "123-555-4567"
},
{
"@": {
"type": "cell"
},
"#": "890-555-1234"
},
{
"@": {
"type": "work"
},
"#": "567-555-8901"
}
],
"email": "john@smith.com"
};
console.log(js2xmlparser.parse("person", obj));
```
This example produces the following XML:
```xml
<?xml version='1.0'?>
<person>
<firstName>John</firstName>
<lastName>Smith</lastName>
<dateOfBirth>Wed Aug 26 1964 00:00:00 GMT-0400 (Eastern Summer Time)</dateOfBirth>
<address type='home'>
<streetAddress>3212 22nd St</streetAddress>
<city>Chicago</city>
<state>Illinois</state>
<zip>10000</zip>
</address>
<phone type='home'>123-555-4567</phone>
<phone type='cell'>890-555-1234</phone>
<phone type='work'>567-555-8901</phone>
<email>john@smith.com</email>
</person>
```
Additional examples can be found in examples/example.js.
## Tests ##
js2xmlparser includes a set of tests to verify core functionality. You can run
the tests using gulp:
```
gulp test
```
The `test` target builds the production variant of js2xmlparser before running
the tests. The `test-prod` target does the same thing, while the `test-dev`
target builds the development variant first instead.
## License ##
js2xmlparser is licensed under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Please see the LICENSE.md file for more information.
... ...
import { IOptions } from "./options";
/**
* Returns a XML string representation of the specified object.
*
* @param root The name of the root XML element. When the object is converted
* to XML, it will be a child of this root element.
* @param object The object to convert to XML.
* @param options Options for parsing the object and formatting the resulting
* XML.
*
* @returns An XML string representation of the specified object.
*/
export declare function parse(root: string, object: any, options?: IOptions): string;
... ...
"use strict";
/**
* Copyright (C) 2016-2017 Michael Kourlas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var xmlcreate_1 = require("xmlcreate");
var options_1 = require("./options");
var utils_1 = require("./utils");
/**
* Parses a string into XML.
*
* @param str The string to parse into XML.
* @param parentElement The XML element or attribute that will contain the
* string.
* @param options Options for parsing the string into XML.
*
* @private
*/
function parseString(str, parentElement, options) {
var requiresCdata = function (s) {
return (options.cdataInvalidChars && (s.indexOf("<") !== -1
|| s.indexOf("&") !== -1))
|| options.cdataKeys.indexOf(parentElement.name) !== -1
|| options.cdataKeys.indexOf("*") !== -1;
};
if (parentElement instanceof xmlcreate_1.XmlElement) {
if (requiresCdata(str)) {
var cdataStrs = str.split("]]>");
for (var i = 0; i < cdataStrs.length; i++) {
if (requiresCdata(cdataStrs[i])) {
parentElement.cdata(cdataStrs[i]);
}
else {
parentElement.charData(cdataStrs[i]);
}
if (i < cdataStrs.length - 1) {
parentElement.charData("]]>");
}
}
}
else {
parentElement.charData(str);
}
}
else {
parentElement.text(str);
}
}
/**
* Parses an attribute into XML.
*
* @param name The name of the attribute.
* @param value The value of the attribute.
* @param parentElement The XML element that will contain the string.
* @param options Options for parsing the attribute into XML.
*
* @private
*/
function parseAttribute(name, value, parentElement, options) {
var attribute = parentElement.attribute(name, "");
if (utils_1.isPrimitive(value)) {
parseString(utils_1.stringify(value), attribute, options);
}
else {
throw new Error("attribute value for name '" + name + "' should be a"
+ " primitive (string, number, boolean, null, or"
+ " undefined)");
}
}
/**
* Parses an object or Map entry into XML.
*
* @param key The key associated with the object or Map entry.
* @param value The object or map entry.
* @param parentElement The XML element that will contain the object or map
* entry.
* @param options Options for parsing the object or map entry into XML.
*
* @private
*/
function parseObjectOrMapEntry(key, value, parentElement, options) {
// Alias key
if (key === options.aliasString) {
if (!utils_1.isString(value)) {
throw new Error("aliasString value for " + value
+ " should be a string");
}
parentElement.name = value;
return;
}
// Attributes key
if (key.indexOf(options.attributeString) === 0) {
if (utils_1.isObject(value)) {
for (var _i = 0, _a = Object.keys(value); _i < _a.length; _i++) {
var subkey = _a[_i];
parseAttribute(subkey, value[subkey], parentElement, options);
}
}
else {
throw new Error("attributes object for " + key + " should be an"
+ " object");
}
return;
}
// Value key
if (key.indexOf(options.valueString) === 0) {
if (utils_1.isPrimitive(value)) {
parseValue(key, value, parentElement, options);
return;
}
else {
throw new Error("value " + value + " should be a primitive"
+ " (string, number, boolean, null, or undefined)");
}
}
// Standard handling (create new element for entry)
var element = parentElement;
if (!utils_1.isArray(value) && !utils_1.isSet(value)) {
element = parentElement.element(key);
}
parseValue(key, value, element, options);
}
/**
* Parses an Object or Map into XML.
*
* @param objectOrMap The object or map to parse into XML.
* @param parentElement The XML element that will contain the object.
* @param options Options for parsing the object into XML.
*
* @private
*/
function parseObjectOrMap(objectOrMap, parentElement, options) {
if (utils_1.isMap(objectOrMap)) {
objectOrMap.forEach(function (value, key) {
parseObjectOrMapEntry(utils_1.stringify(key), value, parentElement, options);
});
}
else {
for (var _i = 0, _a = Object.keys(objectOrMap); _i < _a.length; _i++) {
var key = _a[_i];
parseObjectOrMapEntry(key, objectOrMap[key], parentElement, options);
}
}
}
/**
* Parses an array or Set into XML.
*
* @param key The key associated with the array or set to parse into XML.
* @param arrayOrSet The array or set to parse into XML.
* @param parentElement The XML element that will contain the function.
* @param options Options for parsing the array or set into XML.
*
* @private
*/
function parseArrayOrSet(key, arrayOrSet, parentElement, options) {
var arrayNameFunc;
if (options.wrapHandlers.hasOwnProperty("*")) {
arrayNameFunc = options.wrapHandlers["*"];
}
if (options.wrapHandlers.hasOwnProperty(key)) {
arrayNameFunc = options.wrapHandlers[key];
}
var arrayKey = key;
var arrayElement = parentElement;
if (!utils_1.isUndefined(arrayNameFunc)) {
var arrayNameFuncKey = arrayNameFunc(arrayKey, arrayOrSet);
if (utils_1.isString(arrayNameFuncKey)) {
arrayKey = arrayNameFuncKey;
arrayElement = parentElement.element(key);
}
else if (!utils_1.isNull(arrayNameFuncKey)) {
throw new Error("wrapHandlers function for " + arrayKey
+ " should return a string or null");
}
}
arrayOrSet.forEach(function (item) {
var element = arrayElement;
if (!utils_1.isArray(item) && !utils_1.isSet(item)) {
element = arrayElement.element(arrayKey);
}
parseValue(arrayKey, item, element, options);
});
}
/**
* Parses an arbitrary JavaScript value into XML.
*
* @param key The key associated with the value to parse into XML.
* @param value The value to parse into XML.
* @param parentElement The XML element that will contain the value.
* @param options Options for parsing the value into XML.
*
* @private
*/
function parseValue(key, value, parentElement, options) {
// If a handler for a particular type is user-defined, use that handler
// instead of the defaults
var type = Object.prototype.toString.call(value);
var handler;
if (options.typeHandlers.hasOwnProperty("*")) {
handler = options.typeHandlers["*"];
}
if (options.typeHandlers.hasOwnProperty(type)) {
handler = options.typeHandlers[type];
}
if (!utils_1.isUndefined(handler)) {
value = handler(value);
}
if (utils_1.isObject(value) || utils_1.isMap(value)) {
parseObjectOrMap(value, parentElement, options);
return;
}
if (utils_1.isArray(value) || utils_1.isSet(value)) {
parseArrayOrSet(key, value, parentElement, options);
return;
}
parseString(utils_1.stringify(value), parentElement, options);
}
/**
* Returns a XML document corresponding to the specified value.
*
* @param root The name of the root XML element. When the value is converted to
* XML, it will be a child of this root element.
* @param value The value to convert to XML.
* @param options Options for parsing the value into XML.
*
* @returns An XML document corresponding to the specified value.
*
* @private
*/
function parseToDocument(root, value, options) {
var document = new xmlcreate_1.XmlDocument(root);
if (options.declaration.include) {
document.decl(options.declaration);
}
if (options.dtd.include) {
document.dtd(options.dtd.name, options.dtd.sysId, options.dtd.pubId);
}
parseValue(root, value, document.root(), options);
return document;
}
/**
* Returns a XML string representation of the specified object.
*
* @param root The name of the root XML element. When the object is converted
* to XML, it will be a child of this root element.
* @param object The object to convert to XML.
* @param options Options for parsing the object and formatting the resulting
* XML.
*
* @returns An XML string representation of the specified object.
*/
function parse(root, object, options) {
var opts = new options_1.Options(options);
var document = parseToDocument(root, object, opts);
return document.toString(opts.format);
}
exports.parse = parse;
... ...
/**
* The options associated with parsing an object and formatting the resulting
* XML.
*/
export interface IOptions {
/**
* If an object or map contains a key that, when converted to a string,
* is equal to the value of `aliasString`, then the name of the XML element
* containing the object will be replaced with the value associated with
* said key.
*
* For example, if `aliasString` is `"="`, then the following object:
* ```javascript
* {
* "abc": {
* "=": "def"
* "__val": "ghi"
* }
* }
* ```
* will result in the following XML for a root element named `"root"`:
* ```xml
* <root>
* <def>ghi</def>
* </root>
* ```
*
* If left undefined, the default value is `"="`.
*/
aliasString?: string;
/**
* If an object or map contains a key that, when converted to a string,
* begins with the value of `attributeString`, then the value mapped by
* said key will be interpreted as attributes for the XML element for that
* object.
*
* The attribute object must be an object containing keys that map to
* primitives (string, number, boolean, null, or undefined).
*
* For example, if `attributeString` is `"@"`, then the following object:
* ```javascript
* {
* "abc": {
* "@1": {
* "ghi": "jkl",
* "mno": "pqr"
* },
* "stu": "vwx",
* "@2": {
* "yza": "bcd"
* },
* }
* }
* ```
* will result in the following XML for a root element named `"root"`:
* ```xml
* <root>
* <abc ghi='jkl' mno='pqr' yza='bcd'>
* <stu>vwx</stu>
* </abc>
* </root>
* ```
*
* If left undefined, the default value is `"@"`.
*/
attributeString?: string;
/**
* If `cdataInvalidChars` is `true`, then any text containing the
* characters `<` or `&` shall be enclosed in CDATA sections. Otherwise,
* those characters shall be replaced with XML escape characters.
*
* If left undefined, the default value is `false`.
*/
cdataInvalidChars?: boolean;
/**
* If an object or map contains a key that, when converted to a string, is
* equal to an item in `cdataKeys`, then the value mapped by said key will
* be enclosed in a CDATA section.
*
* For example, if `cdataKeys` is:
* ```javascript
* [
* "abc"
* ]
* ```
* then the following object:
* ```javascript
* {
* "abc": "def&",
* "ghi": "jkl",
* "mno": "pqr<"
* }
* ```
* will result in the following XML for a root element named `"root"`:
* ```xml
* <root>
* <abc><![CDATA[def&]]></ghi>
* <ghi>jlk</ghi>
* <mno>pqr&lt;</mno>
* </root>
* ```
*
* If `cdataKeys` has a key named `"*"`, then that entry will match all
* keys.
*
* If left undefined, the default value is an empty array.
*/
cdataKeys?: string[];
/**
* The options associated with the XML declaration.
*/
declaration?: IDeclarationOptions;
/**
* The options associated with the XML document type definition.
*/
dtd?: IDtdOptions;
/**
* The options associated with the formatting of the XML document.
*/
format?: IFormatOptions;
/**
* If an value has a type (as defined by calling `Object.prototype.toString`
* on the value) equal to a key in `typeHandlers`, then said value will be
* replaced by the return value of the function mapped to by the key in
* `typeHandlers`. This function is called with the value as a parameter.
*
* For example, if `typeHandlers` is:
* ```javascript
* {
* "[object Date]": function(value) {
* return value.getYear();
* }
* }
* ```
* then the following object:
* ```javascript
* {
* "abc": new Date(2012, 10, 31)
* }
* ```
* will result in the following XML for a root element named `"root"`:
* ```xml
* <root>
* <abc>2012</abc>
* </root>
* ```
*
* If `typeHandlers` has a key named `"*"`, then that entry will match all
* values, unless there is a more specific entry.
*
* Note that normal parsing still occurs for the value returned by the
* function; it is not directly converted to a string.
*
* If left undefined, the default value is an empty object.
*/
typeHandlers?: ITypeHandlers;
/**
* If an object or map contains a key that, when converted to a string,
* begins with the value of `valueString`, then the value mapped by said key
* will be represented as bare text within the XML element for that object.
* The value must be a primitive (string, number, boolean, null, or
* undefined).
*
* For example, if `valueString` is `"#"`, then the following object:
* ```javascript
* new Map([
* ["#1", "abc"],
* ["def", "ghi"],
* ["#2", "jkl"]
* ])
* ```
* will result in the following XML for a root element named `"root"`:
* ```xml
* <root>
* abc
* <def>ghi</def>
* jkl
* </root>
* ```
*
* If left undefined, the default value is `"#"`.
*/
valueString?: string;
/**
* If an object or map contains a key that, when converted to a string, is
* equal to a key in `wrapHandlers`, and the key in said object or map maps
* to an array or set, then all items in the array or set will be wrapped
* in an XML element with the same name as the key.
*
* The key in `wrapHandlers` must map to a function that is called with the
* key name, as well as the array or set, as parameters. This function must
* return a string, which will become the name for each XML element for
* each item in the array or set. Alternatively, this function may return
* `null` to indicate that no wrapping should occur.
*
* For example, if `wrapHandlers` is:
* ```javascript
* {
* "abc": function(key, value) {
* return "def";
* }
* }
* ```
* then the following object:
* ```javascript
* {
* "ghi": "jkl",
* "mno": {
* "pqr": ["s", "t"]
* },
* "uvw": {
* "abc": ["x", "y"]
* }
* }
* ```
* will result in the following XML for a root element named `"root"`:
* ```xml
* <root>
* <ghi>jkl</ghi>
* <mno>
* <pqr>s</pqr>
* <pqr>t</pqr>
* </mno>
* <uwv>
* <abc>
* <def>x</def>
* <def>y</def>
* </abc>
* </uwv>
* </root>
* ```
*
* If `wrapHandlers` has a key named `"*"`, then that entry will
* match all arrays and sets, unless there is a more specific entry.
*
* If left undefined, the default value is an empty object.
*/
wrapHandlers?: IWrapHandlers;
}
/**
* Implementation of the IOptions interface used to provide default values
* to fields.
*
* @private
*/
export declare class Options implements IOptions {
aliasString: string;
attributeString: string;
cdataInvalidChars: boolean;
cdataKeys: string[];
declaration: DeclarationOptions;
dtd: DtdOptions;
format: FormatOptions;
typeHandlers: TypeHandlers;
valueString: string;
wrapHandlers: WrapHandlers;
constructor(options?: IOptions);
}
/**
* The options associated with the XML declaration. An example of an XML
* declaration is as follows:
*
* ```xml
* <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
* ```
*/
export interface IDeclarationOptions {
/**
* If `include` is true, an XML declaration is included in the generated
* XML. If left undefined, the default value is `true`.
*/
include?: boolean;
/**
* The XML encoding to be included in the declaration. If defined, this
* value must be a valid encoding. If left undefined, no encoding is
* included.
*/
encoding?: string;
/**
* The XML standalone attribute to be included. If defined, this value must
* be `"yes"` or `"no"`. If left undefined, no standalone attribute is
* included.
*/
standalone?: string;
/**
* The XML version to be included in the declaration. If defined, this
* value must be a valid XML version number. If left undefined, the default
* version is `"1.0"`.
*/
version?: string;
}
/**
* Implementation of the IDeclarationOptions interface used to provide default
* values to fields.
*
* @private
*/
export declare class DeclarationOptions implements IDeclarationOptions {
include: boolean;
encoding?: string;
standalone?: string;
version?: string;
constructor(declarationOptions?: IDeclarationOptions);
}
/**
* The options associated with the XML document type definition (DTD). An
* example of an XML document type definition is as follows:
*
* ```xml
* <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
* "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
* ```
*/
export interface IDtdOptions {
/**
* If `include` is `true`, an XML DTD is included in the resulting XML. If
* left undefined, the default value is `true`.
*/
include?: boolean;
/**
* The name of the DTD. This value cannot be left undefined if `include`
* is `true`.
*/
name?: string;
/**
* The system identifier of the DTD, excluding quotation marks. If left
* undefined, no system identifier is included.
*/
sysId?: string;
/**
* The public identifier of the DTD, excluding quotation marks. If `pubId`
* is defined, `sysId` must be defined as well. If left undefined, no
* public identifier is included.
*/
pubId?: string;
}
/**
* Implementation of the IDtdOptions interface used to provide default values
* to fields.
*
* @private
*/
export declare class DtdOptions implements IDtdOptions {
include: boolean;
name?: string;
sysId?: string;
pubId?: string;
constructor(dtdOptions?: IDtdOptions);
}
/**
* The options associated with the formatting of the XML document.
*/
export interface IFormatOptions {
/**
* If `doubleQuotes` is `true`, double quotes are used in XML attributes.
* Otherwise, single quotes are used in XML attributes. If left undefined,
* the default value is `false`.
*/
doubleQuotes?: boolean;
/**
* The indent string used for pretty-printing. If left undefined, the
* default value is four spaces.
*/
indent?: string;
/**
* The newline string used for pretty-printing. If left undefined, the
* default value is `"\n"`.
*/
newline?: string;
/**
* If `pretty` is `true`, pretty-printing is enabled. If left undefined,
* the default value is `true`.
*/
pretty?: boolean;
}
/**
* Implementation of the IFormatOptions interface used to provide default values
* to fields.
*
* @private
*/
export declare class FormatOptions implements IFormatOptions {
doubleQuotes?: boolean;
indent?: string;
newline?: string;
pretty?: boolean;
constructor(formatOptions?: IFormatOptions);
}
/**
* Map for the `typeHandlers` property in the {@link IOptions} interface.
*/
export interface ITypeHandlers {
/**
* Mapping between the type of a value in an object to a function taking
* this value and returning a replacement value.
*/
[type: string]: (value: any) => any;
}
/**
* Implementation of the ITypeHandlers interface used to provide default values
* to fields.
*
* @private
*/
export declare class TypeHandlers implements ITypeHandlers {
[type: string]: (value: any) => any;
constructor(typeHandlers?: ITypeHandlers);
}
/**
* Map for the `wrapHandlers` property in the {@link IOptions} interface.
*/
export interface IWrapHandlers {
/**
* Mapping between the string version of a key in an object or map with a
* value that is an array or set to a function taking the string version
* of that key, as well as that array or set.
*
* This function returns either a string that will become the name for each
* XML element for each item in the array or set, or `null` to indicate that
* wrapping should not occur.
*/
[key: string]: (key: string, value: any) => string | null;
}
/**
* Implementation of the IWrapHandlers interface used to provide default values
* to fields.
*
* @private
*/
export declare class WrapHandlers implements IWrapHandlers {
[key: string]: (key: string, value: any) => string | null;
constructor(wrapHandlers?: IWrapHandlers);
}
... ...
/**
* Copyright (C) 2016 Michael Kourlas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
"use strict";
var utils_1 = require("./utils");
/**
* Implementation of the IOptions interface used to provide default values
* to fields.
*
* @private
*/
var Options = (function () {
function Options(options) {
if (options === void 0) { options = {}; }
this.aliasString = "=";
this.attributeString = "@";
this.cdataInvalidChars = false;
this.cdataKeys = [];
this.valueString = "#";
if (!utils_1.isObject(options)) {
throw new TypeError("options should be an Object or undefined");
}
if (!utils_1.isString(options.aliasString)) {
if (!utils_1.isUndefined(options.aliasString)) {
throw new TypeError("options.aliasString should be a string or"
+ " undefined");
}
}
else {
this.aliasString = options.aliasString;
}
if (!utils_1.isString(options.attributeString)) {
if (!utils_1.isUndefined(options.attributeString)) {
throw new TypeError("options.attributeString should be a string"
+ " or undefined");
}
}
else {
this.attributeString = options.attributeString;
}
if (!utils_1.isBoolean(options.cdataInvalidChars)) {
if (!utils_1.isUndefined(options.cdataInvalidChars)) {
throw new TypeError("options.cdataInvalidChars should be a"
+ " boolean or undefined");
}
}
else {
this.cdataInvalidChars = options.cdataInvalidChars;
}
if (!utils_1.isStringArray(options.cdataKeys)) {
if (!utils_1.isUndefined(options.cdataKeys)) {
throw new TypeError("options.cdataKeys should be an Array or" +
" undefined");
}
}
else {
this.cdataKeys = options.cdataKeys;
}
this.declaration = new DeclarationOptions(options.declaration);
this.dtd = new DtdOptions(options.dtd);
this.format = new FormatOptions(options.format);
this.typeHandlers = new TypeHandlers(options.typeHandlers);
if (!utils_1.isString(options.valueString)) {
if (!utils_1.isUndefined(options.valueString)) {
throw new TypeError("options.valueString should be a string"
+ " or undefined");
}
}
else {
this.valueString = options.valueString;
}
this.wrapHandlers = new WrapHandlers(options.wrapHandlers);
}
return Options;
}());
exports.Options = Options;
/**
* Implementation of the IDeclarationOptions interface used to provide default
* values to fields.
*
* @private
*/
var DeclarationOptions = (function () {
function DeclarationOptions(declarationOptions) {
if (declarationOptions === void 0) { declarationOptions = {}; }
this.include = true;
if (!utils_1.isObject(declarationOptions)) {
throw new TypeError("options.declaration should be an Object or"
+ " undefined");
}
if (!utils_1.isBoolean(declarationOptions.include)) {
if (!utils_1.isUndefined(declarationOptions.include)) {
throw new TypeError("options.declaration.include should be a"
+ " boolean or undefined");
}
}
else {
this.include = declarationOptions.include;
}
// Validation performed by xmlcreate
this.encoding = declarationOptions.encoding;
this.standalone = declarationOptions.standalone;
this.version = declarationOptions.version;
}
return DeclarationOptions;
}());
exports.DeclarationOptions = DeclarationOptions;
/**
* Implementation of the IDtdOptions interface used to provide default values
* to fields.
*
* @private
*/
var DtdOptions = (function () {
function DtdOptions(dtdOptions) {
if (dtdOptions === void 0) { dtdOptions = {}; }
this.include = false;
if (!utils_1.isObject(dtdOptions)) {
throw new TypeError("options.dtd should be an Object or undefined");
}
if (!utils_1.isBoolean(dtdOptions.include)) {
if (!utils_1.isUndefined(dtdOptions.include)) {
throw new TypeError("options.dtd.include should be a boolean"
+ " or undefined");
}
}
else {
this.include = dtdOptions.include;
}
// Validation performed by xmlcreate
this.name = dtdOptions.name;
this.sysId = dtdOptions.sysId;
this.pubId = dtdOptions.pubId;
}
return DtdOptions;
}());
exports.DtdOptions = DtdOptions;
/**
* Implementation of the IFormatOptions interface used to provide default values
* to fields.
*
* @private
*/
var FormatOptions = (function () {
function FormatOptions(formatOptions) {
if (formatOptions === void 0) { formatOptions = {}; }
if (!utils_1.isObject(formatOptions)) {
throw new TypeError("options.format should be an Object or"
+ " undefined");
}
// Validation performed by xmlcreate
this.doubleQuotes = formatOptions.doubleQuotes;
this.indent = formatOptions.indent;
this.newline = formatOptions.newline;
this.pretty = formatOptions.pretty;
}
return FormatOptions;
}());
exports.FormatOptions = FormatOptions;
/**
* Implementation of the ITypeHandlers interface used to provide default values
* to fields.
*
* @private
*/
var TypeHandlers = (function () {
function TypeHandlers(typeHandlers) {
if (typeHandlers === void 0) { typeHandlers = {}; }
if (!utils_1.isObject(typeHandlers)) {
throw new TypeError("options.typeHandlers should be an Object or"
+ " undefined");
}
for (var key in typeHandlers) {
if (typeHandlers.hasOwnProperty(key)) {
if (!utils_1.isFunction(typeHandlers[key])) {
throw new TypeError("options.typeHandlers['" + key + "']" +
" should be a Function");
}
else {
this[key] = typeHandlers[key];
}
}
}
}
return TypeHandlers;
}());
exports.TypeHandlers = TypeHandlers;
/**
* Implementation of the IWrapHandlers interface used to provide default values
* to fields.
*
* @private
*/
var WrapHandlers = (function () {
function WrapHandlers(wrapHandlers) {
if (wrapHandlers === void 0) { wrapHandlers = {}; }
if (!utils_1.isObject(wrapHandlers)) {
throw new TypeError("options.wrapHandlers should be an Object or"
+ " undefined");
}
for (var key in wrapHandlers) {
if (wrapHandlers.hasOwnProperty(key)) {
if (!utils_1.isFunction(wrapHandlers[key])) {
throw new TypeError("options.wrapHandlers['" + key + "']" +
" should be a Function");
}
else {
this[key] = wrapHandlers[key];
}
}
}
}
return WrapHandlers;
}());
exports.WrapHandlers = WrapHandlers;
... ...
/**
* Copyright (C) 2016 Michael Kourlas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @private
*/
export declare function isString(val: any): val is string;
/**
* @private
*/
export declare function isNumber(val: any): val is number;
/**
* @private
*/
export declare function isBoolean(val: any): val is boolean;
/**
* @private
*/
export declare function isUndefined(val: any): val is undefined;
/**
* @private
*/
export declare function isNull(val: any): val is null;
/**
* @private
*/
export declare function isPrimitive(val: any): val is (string | number | boolean | undefined | null);
/**
* @private
*/
export declare function isObject(val: any): val is Object;
/**
* @private
*/
export declare function isArray(val: any): val is any[];
/**
* @private
*/
export declare function isStringArray(val: any): val is string[];
/**
* @private
*/
export declare function isFunction(val: any): val is Function;
/**
* @private
*/
export declare function isSet(val: any): boolean;
/**
* @private
*/
export declare function isMap(val: any): boolean;
/**
* Returns a string representation of the specified value, as given by the
* value's toString() method (if it has one) or the global String() function
* (if it does not).
*
* @param value The value to convert to a string.
*
* @returns A string representation of the specified value.
*
* @private
*/
export declare function stringify(value: any): string;
... ...