parse-function !npm versionnpmv-imgnpmv-url !github releasegithub-release-imggithub-release-url !mit Licenselicense-imglicense-url !NPM Downloads Weeklydownloads-weekly-imgdownloads-weekly-url !NPM Downloads Totaldownloads-total-imgdownloads-total-url
Parse a function into an object using espree, acorn or babylon parsers. Extensible through Smart Plugins
You might also be interested in hela.
Quality Assurance :100:
!Code Climatecodeclimate-imgcodeclimate-url !Code Style Standardstandard-imgstandard-url !Linux Buildtravis-imgtravis-url !Code Coveragecodecov-imgcodecov-url !Dependencies Statusdependencies-imgdependencies-url !Renovate App Statusrenovate-imgrenovate-urlIf you have any how-to kind of questions, please read Code of Conduct and join the chat room or open an issueopen-issue-url.
You may also read the Contributing Guide. There, beside "How to contribute?", we describe everything stated by the badges.
!tunnckoCore supportgitterchat-imggitterchat-url !Code Format Prettierprettier-imgprettier-url !node security statusnodesecurity-imgnodesecurity-url !conventional Commitsccommits-imgccommits-url !semantic releasesemantic-release-imgsemantic-release-url !Node Version Requirednodeversion-imgnodeversion-url
Features
- Always up-to-date: auto-publish new version when new version of dependency is out, Renovate
- Standard: using StandardJS, Prettier, SemVer, Semantic Release and conventional commits
- Smart Plugins: for extending the core API or the end Result, see .use method and Plugins Architecture
- Extensible: using plugins for working directly on AST nodes, see the Plugins Architecture
- ES2017 Ready: by using
.parseExpression
method of the babylonv7.x
parser - Customization: allows switching the parser, through
options.parse
- Support for: arrow functions, default parameters, generators and async/await functions
- Stable: battle-tested in production and against all parsers - espree, acorn, babylon
- Tested: with 275+ tests for 200% coverage
Table of Contents
Throws in one specific case Function named "anonymous" Real anonymous function Plugins Architecture parseFunction .parse .use .define Result(TOC generated by verb using markdown-toc)
Install
This project requires Node.jsnodeversion-url v6 and above. Use yarn v1 / npm v5 or above to install it.$ yarn add parse-function
Which version to use?
There's no breaking changes between thev2.x
version. The only breaking is v2.1
which also is not
working properly, so no use it.Use v2.0.x
When you don't need support for
arrow functions
and es6 default params
. This version
uses a RegExp expression to work.Use v2.2.x
Only when you need a basic support for
es6 features
like arrow functions. This version
uses a RegExp expression to work.Use v2.3.x
When you want full support for
arrow functions
and es6 default params
. Where this "full",
means "almost full", because it has bugs. This version also uses (acorn.parse
) real parser
to do the parsing.Use v3.x
When you want to use different parser instead of the default
babylon.parse
, by passing custom
parse function to the options.parse
option. From this version we require node >= 4
.Use v4.x
When you want full customization and most stable support for old and modern features. This version uses
babylon.parseExpression
for parsing and provides a Plugins API.
See the Features section for more info.Use v5.x
It is basically the same as
v4
, but requires Node 6 & npm 5. Another is boilerplate stuff.back to top
Notes
Throws in one specific case
see: issue #3 and test/index.js#L229-L235
It may throw in one specific case, otherwise it won't throw, so you should relay on the
result.isValid
for sure.Function named "anonymous"
see: test/index.js#L319-L324 and Result section
If you pass a function which is named "anonymous" the
result.name
will be 'anonymous'
,
but the result.isAnonymous
will be false
and result.isNamed
will be true
, because
in fact it's a named function.Real anonymous function
see: test/index.js#L326-L331 and Result section
Only if you pass really an anonymous function you will get
result.name
equal to null
,
result.isAnonymous
equal to true
and result.isNamed
equal to false
.back to top
Plugins Architecture
see: the .use method, test/index.js#L305-L317 and test/index.js#L396-L414
A more human description of the plugin mechanism. Plugins are synchronous - no support and no need for async plugins here, but notice that you can do that manually, because that exact architecture.
The first function that is passed to the .use method is used for extending the core API, for example adding a new method to the
app
instance. That function is immediately invoked.const parseFunction = require('parse-function')
const app = parseFunction()
app.use((self) => {
// self is same as `app`
console.log(self.use)
console.log(self.parse)
console.log(self.define)
self.define(self, 'foo', (bar) => bar + 1)
})
console.log(app.foo(2)) // => 3
On the other side, if you want to access the AST of the parser, you should return a function from that plugin, which function is passed with
(node, result)
signature.This function is lazy plugin, it is called only when the .parse method is called.
const parseFunction = require('parse-function')
const app = parseFunction()
app.use((self) => {
console.log('immediately called')
return (node, result) => {
console.log('called only when .parse is invoked')
console.log(node)
console.log(result)
}
})
Where 1) the
node
argument is an object - actual and real AST Node coming from the parser
and 2) the result
is an object too - the end Result, on which
you can add more properties if you want.back to top
API
Review carefully the provided examples and the working tests.parseFunction
Initializes with optional opts
object which is passed directly
to the desired parser and returns an object
with .use
and .parse
methods. The default parse which
is used is babylon's .parseExpression
method from v7
.Params
opts
{Object}: optional, merged with options passed to.parse
methodreturns
{Object}:app
object with.use
and.parse
methods
Example
const parseFunction = require('parse-function')
const app = parseFunction({
ecmaVersion: 2017
})
const fixtureFn = (a, b, c) => {
a = b + c
return a + 2
}
const result = app.parse(fixtureFn)
console.log(result)
// see more
console.log(result.name) // => null
console.log(result.isNamed) // => false
console.log(result.isArrow) // => true
console.log(result.isAnonymous) // => true
// array of names of the arguments
console.log(result.args) // => ['a', 'b', 'c']
// comma-separated names of the arguments
console.log(result.params) // => 'a, b, c'
.parse
Parse a givenwith useful properties - such ascode
and returns aresult
object
name
, body
and args
.
By default it uses Babylon parser, but you can switch it by
passing options.parse
- for example options.parse: acorn.parse
.
In the below example will show how to use acorn
parser, instead
of the default one.Params
code
{Function|String}: any kind of function or string to be parsedoptions
{Object}: directly passed to the parser - babylon, acorn, espreeoptions.parse
{Function}: by defaultbabylon.parseExpression
, alloptions
are passed as second argument to that provided functionreturns
{Object}:result
see result section for more info
Example
const acorn = require('acorn')
const parseFn = require('parse-function')
const app = parseFn()
const fn = function foo (bar, baz) { return bar * baz }
const result = app.parse(fn, {
parse: acorn.parse,
ecmaVersion: 2017
})
console.log(result.name) // => 'foo'
console.log(result.args) // => ['bar', 'baz']
console.log(result.body) // => ' return bar * baz '
console.log(result.isNamed) // => true
console.log(result.isArrow) // => false
console.log(result.isAnonymous) // => false
console.log(result.isGenerator) // => false
.use
Add a pluginfn
function for extending the API or working on the AST nodes. Thefn
is immediately invoked and passed withapp
argument which is instance ofparseFunction()
call. Thatfn
may return another function that accepts(node, result)
signature, wherenode
is an AST node andresult
is an object which will be returned result from the.parse
method. This retuned function is called on each node only when.parse
method is called.
See Plugins Architecture section.
Params
fn
{Function}: plugin to be calledreturns
{Object}:app
instance for chaining
Example
// plugin extending the `app`
app.use((app) => {
app.define(app, 'hello', (place) => `Hello ${place}!`)
})
const hi = app.hello('World')
console.log(hi) // => 'Hello World!'
// or plugin that works on AST nodes
app.use((app) => (node, result) => {
if (node.type === 'ArrowFunctionExpression') {
result.thatIsArrow = true
}
return result
})
const result = app.parse((a, b) => (a + b + 123))
console.log(result.name) // => null
console.log(result.isArrow) // => true
console.log(result.thatIsArrow) // => true
const result = app.parse(function foo () { return 123 })
console.log(result.name) // => 'foo'
console.log(result.isArrow) // => false
console.log(result.thatIsArrow) // => undefined
.define
Define a non-enumerable property on an object. Justa convenience mirror of the define-property library, so check out its docs. Useful to be used in plugins.
Params
obj
{Object}: the object on which to define the propertyprop
{String}: the name of the property to be defined or modifiedval
{Any}: the descriptor for the property being defined or modifiedreturns
{Object}:obj
the passed object, but modified
Example
const parseFunction = require('parse-function')
const app = parseFunction()
// use it like `define-property` lib
const obj = {}
app.define(obj, 'hi', 'world')
console.log(obj) // => { hi: 'world' }
// or define a custom plugin that adds `.foo` property
// to the end result, returned from `app.parse`
app.use((app) => {
return (node, result) => {
// this function is called
// only when `.parse` is called
app.define(result, 'foo', 123)
return result
}
})
// fixture function to be parsed
const asyncFn = async (qux) => {
const bar = await Promise.resolve(qux)
return bar
}
const result = app.parse(asyncFn)
console.log(result.name) // => null
console.log(result.foo) // => 123
console.log(result.args) // => ['qux']
console.log(result.isAsync) // => true
console.log(result.isArrow) // => true
console.log(result.isNamed) // => false
console.log(result.isAnonymous) // => true
back to top
Result
In the result object you havethat can be useful to determine what the function is - arrow, regular, async/await or generator.name
,args
,params
,body
and few hidden properties
name
{String|null}: name of the passed function ornull
if anonymousargs
{Array}: arguments of the functionparams
{String}: comma-separated list representing theargs
defaults
{Object}: key/value pairs, useful when use ES2015 default argumentsbody
{String}: actual body of the function, respects trailing newlines and whitespacesisValid
{Boolean}: is the given value valid or not, that's because it never throws!isAsync
{Boolean}:true
if function is ES2015 async/await functionisArrow
{Boolean}:true
if the function is arrow functionisNamed
{Boolean}:true
if function has name, orfalse
if is anonymousisGenerator
{Boolean}:true
if the function is ES2015 generator functionisAnonymous
{Boolean}:true
if the function don't have name
back to top
Related
- acorn: ECMAScript parser | homepage
- babylon: A JavaScript parser | homepage
- charlike-cli: Command line interface for the charlike project scaffolder. | homepage
- espree: An Esprima-compatible JavaScript parser built on Acorn | homepage
- hela: Powerful & flexible task runner framework in 80 lines, based on execa… more | homepage
- parse-semver: Parse, normalize and validate given semver shorthand (e.g. gulp@v3.8.10) to object. | homepage to object.")
Contributing
Pull requests and stars are always welcome. For bugs and feature requests, please create an issueopen-issue-url.Please read the Contributing Guide and Code of Conduct documents for advices.
Author
License
Copyright © 2016-2017, Charlike Mike Reagent. Released under the MIT License.This file was generated by verb-generate-readme, v0.6.0, on October 09, 2017.
Project scaffolded and managed with hela.