Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
snapdragon
Advanced tools
snapdragon is an extremely pluggable, powerful and easy-to-use parser-renderer factory.
The snapdragon npm package is a highly pluggable, low-level compiler for creating compilers and other text processing applications. It provides a robust framework for parsing, compiling, and rendering custom grammars in a structured way.
Parsing
This feature allows you to define custom parsing rules. The code sample demonstrates how to create a simple text parser that recognizes sequences of lowercase letters.
const Snapdragon = require('snapdragon');
const snapdragon = new Snapdragon();
snapdragon.parser.use(function() {
this.set('text', function() {
const pos = this.position();
const m = this.match(/^[a-z]+/);
if (!m) return;
return pos(this.node({type: 'text', val: m[0]}));
});
});
const ast = snapdragon.parse('hello');
console.log(ast);
Compiling
This feature allows you to compile parsed input into a new form. The code sample shows how to compile a parsed abstract syntax tree (AST) into uppercase text.
const Snapdragon = require('snapdragon');
const snapdragon = new Snapdragon();
snapdragon.compiler.use(function(node) {
if (node.type === 'text') {
return node.val.toUpperCase();
}
});
const ast = snapdragon.parse('hello');
const result = snapdragon.compile(ast).output;
console.log(result);
Rendering
This feature involves rendering the compiled output. The code sample illustrates how to render the output of a parsed AST, adding a space after each text node.
const Snapdragon = require('snapdragon');
const snapdragon = new Snapdragon();
snapdragon.renderer.use(function(node) {
if (node.type === 'text') {
this.emit(node.val + ' '); // add space after each text node
}
});
const ast = snapdragon.parse('hello world');
const result = snapdragon.render(ast);
console.log(result);
Chevrotain is a JavaScript parser building toolkit which is similar to snapdragon but focuses more on performance and ease of use for creating complex parsers without writing too much boilerplate code. It differs from snapdragon in that it provides a richer set of built-in features for defining grammars and performing lexical analysis.
Nearley is another parser toolkit that uses a different approach by leveraging grammar files written in a special format. It is similar to snapdragon in that it allows for the creation of custom parsers, but it automates more of the process and can handle more complex, ambiguous grammars.
PEG.js is a simple parser generator that allows you to create parsers directly from a string representation of a Parsing Expression Grammar. It is similar to snapdragon in its purpose but differs in that it generates parsers from a high-level description rather than requiring manual definition of parsing behavior.
snapdragon is an extremely pluggable, powerful and easy-to-use parser-renderer factory.
Created by jonschlinkert and doowb.
Features
Install with npm
$ npm i snapdragon --save
var Snapdragon = require('snapdragon');
var snapdragon = new Snapdragon();
Parse
var ast = snapdragon.parser('some string', options)
// parser middleware that can be called by other middleware
.set('foo', function () {})
// parser middleware that will be run immediately, in the order defined
.use(bar())
.use(baz())
Render
// pass the `ast` from the parse method
var res = snapdragon.renderer(ast)
// renderer middleware, called when the name of the middleware
// matches the `node.type` (defined in a parser middleware)
.set('bar', function () {})
.set('baz', function () {})
.render()
See the examples
Try running all three examples from the command line. Just do:
node examples/basic-example.js
node examples/glob-example.js
node examples/sourcemap-example.js
Parsers
Parsers are middleware functions used for parsing a string into an ast node.
var ast = snapdragon.parser(str, options)
.use(function() {
var pos = this.position();
var m = this.match(/^\./);
if (!m) return;
return pos({
// `type` specifies the renderer to use
type: 'dot',
val: m[0]
});
})
AST node
When the parser finds a match, pos()
is called, pushing a token for that node onto the ast that looks something like:
{ type: 'dot',
val: '.',
position:
{ start: { line: 1, column: 1 },
end: { line: 1, column: 2 } }
Renderers
Renderers are named middleware functions that visit over an array of ast nodes to render a string.
var res = snapdragon.renderer(ast)
.set('dot', function (node) {
console.log(node.val)
//=> '.'
return this.emit(node.val);
})
Source maps
If you want source map support, make sure to emit the position as well.
var res = snapdragon.renderer(ast)
.set('dot', function (node) {
return this.emit(node.val, node.position);
})
A parser middleware is a function that returns an abject called a token
. This token is pushed onto the AST as a node.
Example token
{ type: 'dot',
val: '.',
position:
{ start: { line: 1, column: 1 },
end: { line: 1, column: 2 } }
Example parser middleware
Match a single .
in a string:
this.position()
.match
methodundefined
pos()
is called, which returns a token with:type
: the name of the [renderer] to useval
: The actual value captured by the regex. In this case, a .
. Note that you can capture and return whatever will be needed by the corresponding [renderer].Renderers are run when the name of the renderer middleware matches the type
defined on an ast node
(which is defined in a parser).
Example
Exercise: Parse a dot, then render it as an escaped dot.
var ast = snapdragon.parser('.')
.use(function () {
var pos = this.position();
var m = this.match(/^\./);
if (!m) return;
return pos({
// define the `type` of renderer to use
type: 'dot',
val: m[0]
})
})
var result = snapdragon.renderer(ast)
.set('dot', function (node) {
return this.emit('\\' + node.val);
})
.render()
//=> '\.'
Mark position and update node.position
.
returns
{Function}: Function used to update the position when finished.Example
var pos = this.position();
var node = pos({type: 'dot'});
Set a hint
to be used by downstream parsers.
Params
prop
{String}val
{any}returns
{Object}: Returns the Parser
instance for chaining.Example
this.hint('bracket.start', true);
Set an error message with the current line number and column.
Params
msg
{String}: Message to use in the Error.Example
this.error('Error parsing string.');
Register a parser middleware by name, so it can be called by other parsers. Parsers are added to the prototype
to allow using this
.
Params
name
{String}: Name of the parser to add to the prototype.fn
{Function}: Rule function to add to the prototype.returns
{Object} this
: to enable chaining.Example
function heading() {
//=> do stuff
}
function heading() {
//=> do stuff
}
var ast = snapdragon.parser(str, options)
.set('slash', function(){})
.set('backslash', function(){})
.parse();
Parse the currently loaded string with the specified parser middleware.
returns
{Object}: Object representing the parsed ASTExample
var ast = snapdragon.parse();
Match re
and return captures. Advances the position of the parser by the length of the captured string.
Params
re
{RegExp}returns
{Object}: Push an object representing a parsed node onto the AST.Example
// match a dot
function dot() {
var pos = this.position();
var m = this.match(/^\./);
if (!m) return;
return pos({type: 'dot', val: m[0]});
}
Add a middleware to use for parsing the string resulting in a single node on the AST
Params
fn
{Function}: Middleware function to use.returns
{Object} this
: to enable chainingExample
parser
.use(function () { ... })
.use(function () { ... });
Create an instance of Renderer
. This is only necessary if need to create your own instance.
Params
ast
{Object}: Pass the ast generated by snapdragon.parse()
options
{Object}Example
var renderer = new snapdragon.Renderer();
Set an error message with the current line number and column.
Params
message
{String}: Message to use in the Error.Example
this.error('Error parsing string.');
Register a renderer for a corresponding parser type
.
Params
name
{String}: Name of the renderer to registerfn
{Function}: Function to registerreturns
{Object} this
: for chaining.Example
var ast = snapdragon.parse(str)
.use(function() {
// `type` is the name of the renderer to use
return pos({ type: 'dot' });
})
var res = snapdragon.render(ast, options)
.set('dot', function (node) {
return this.emit(node.val);
})
.use
.set
nodes
(recursion)Snapdragon was inspired by these great projects by tj:
Install dev dependencies:
$ npm i -d && npm test
Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.
Jon Schlinkert
Brian Woodward
Copyright © 2015 Jon Schlinkert Released under the MIT license.
This file was generated by verb-cli on September 23, 2015.
FAQs
Easy-to-use plugin system for creating powerful, fast and versatile parsers and compilers, with built-in source-map support.
The npm package snapdragon receives a total of 12,847,516 weekly downloads. As such, snapdragon popularity was classified as popular.
We found that snapdragon demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.