Gathering detailed insights and metrics for astring
Gathering detailed insights and metrics for astring
Gathering detailed insights and metrics for astring
Gathering detailed insights and metrics for astring
🌳 Tiny and fast JavaScript code generator from an ESTree-compliant AST.
npm install astring
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
1,176 Stars
838 Commits
56 Forks
10 Watching
14 Branches
14 Contributors
Updated on 20 Nov 2024
JavaScript (100%)
Cumulative downloads
Total Downloads
Last day
-6.8%
393,891
Compared to previous day
Last week
3.6%
2,329,828
Compared to previous week
Last month
10.5%
9,616,162
Compared to previous month
Last year
75%
85,533,855
Compared to previous year
28
🌳 Tiny and fast JavaScript code generator from an ESTree-compliant AST.
:warning: Astring relies on
String.prototype.repeat(amount)
andString.prototype.endsWith(string)
. If the environment running Astring does not define these methods, usestring.prototype.repeat
,string.prototype.endsWith
orbabel-polyfill
.
Install with the Node Package Manager:
1npm install astring
Or install with JSR:
1deno add @davidbonnet/astring
Alternatively, checkout this repository and install the development dependencies to build the module file:
1git clone https://github.com/davidbonnet/astring.git 2cd astring 3npm install
Import it from Deno's third party module repository:
1const { generate } = await import('https://deno.land/x/astring/src/astring.js')
With JavaScript 6 modules:
1import { generate } from 'astring'
With CommonJS:
1const { generate } = require('astring')
A browser-ready minified bundle containing Astring is available at dist/astring.min.js
. The module exposes a global variable astring
:
1<script src="astring.min.js" type="text/javascript"></script> 2<script type="text/javascript"> 3 var generate = astring.generate 4</script>
The astring
module exposes the following properties:
generate(node: object, options: object): string | object
Returns a string representing the rendered code of the provided AST node
. However, if an output
stream is provided in the options
, it writes to that stream and returns it.
The options
are:
indent
: string to use for indentation (defaults to "␣␣"
)lineEnd
: string to use for line endings (defaults to "\n"
)startingIndentLevel
: indent level to start from (defaults to 0
)comments
: generate comments if true
(defaults to false
)output
: output stream to write the rendered code to (defaults to null
)generator
: custom code generator (defaults to GENERATOR
)sourceMap
: source map generator (defaults to null
)expressionsPrecedence
: custom map of node types and their precedence level (defaults to EXPRESSIONS_PRECEDENCE
)GENERATOR: object
Base generator that can be used to extend Astring.
EXPRESSIONS_PRECEDENCE: object
Mapping of node types and their precedence level to let the generator know when to use parentheses.
NEEDS_PARENTHESES: number
Default precedence level that always triggers the use of parentheses.
baseGenerator: object
:warning: Deprecated, use
GENERATOR
instead.
Operations per second for generating each sample code from a pre-parsed AST:
code sample (length) | escodegen | astring | uglify | babel | prettier |
---|---|---|---|---|---|
tiny code (11) | 1,257,527 | 7,185,642 | 129,467 | 156,184 | 333 |
everything (8532) | 1,366 | 8,008 | 0 | 346 | 64 |
Operations per second for parsing and generating each sample code:
code sample (length) | acorn + astring | meriyah + astring | buble | sucrase |
---|---|---|---|---|
tiny code (11) | 92,578 | 864,665 | 25,911 | 575,370 |
everything (8532) | 706 | 1,425 | 132 | 1,403 |
The following examples are written in JavaScript 5 with Astring imported à la CommonJS.
This example uses Acorn, a blazingly fast JavaScript AST producer and therefore the perfect companion of Astring.
1// Make sure acorn and astring modules are imported 2 3// Set example code 4var code = 'let answer = 4 + 7 * 5 + 3;\n' 5// Parse it into an AST 6var ast = acorn.parse(code, { ecmaVersion: 6 }) 7// Format it into a code string 8var formattedCode = astring.generate(ast) 9// Check it 10console.log(code === formattedCode ? 'It works!' : 'Something went wrong…')
This example uses the source map generator from the Source Map module.
1// Make sure acorn, sourceMap and astring modules are imported 2 3var code = 'function add(a, b) { return a + b; }\n' 4var ast = acorn.parse(code, { 5 ecmaVersion: 6, 6 sourceType: 'module', 7 // Locations are needed in order for the source map generator to work 8 locations: true, 9}) 10// Create empty source map generator 11var map = new sourceMap.SourceMapGenerator({ 12 // Source file name must be set and will be used for mappings 13 file: 'script.js', 14}) 15var formattedCode = generate(ast, { 16 // Enable source maps 17 sourceMap: map, 18}) 19// Display generated source map 20console.log(map.toString())
This example for Node shows how to use writable streams to get the rendered code.
1// Make sure acorn and astring modules are imported 2 3// Set example code 4var code = 'let answer = 4 + 7 * 5 + 3;\n' 5// Parse it into an AST 6var ast = acorn.parse(code, { ecmaVersion: 6 }) 7// Format it and write the result to stdout 8var stream = astring.generate(ast, { 9 output: process.stdout, 10}) 11// The returned value is the output stream 12console.log('Does stream equal process.stdout?', stream === process.stdout)
Astring supports comment generation, provided they are stored on the AST nodes. To do so, this example uses Astravel, a fast AST traveller and modifier.
1// Make sure acorn, astravel and astring modules are imported 2 3// Set example code 4var code = 5 [ 6 '// Compute the answer to everything', 7 'let answer = 4 + 7 * 5 + 3;', 8 '// Display it', 9 'console.log(answer);', 10 ].join('\n') + '\n' 11// Parse it into an AST and retrieve the list of comments 12var comments = [] 13var ast = acorn.parse(code, { 14 ecmaVersion: 6, 15 locations: true, 16 onComment: comments, 17}) 18// Attach comments to AST nodes 19astravel.attachComments(ast, comments) 20// Format it into a code string 21var formattedCode = astring.generate(ast, { 22 comments: true, 23}) 24// Check it 25console.log(code === formattedCode ? 'It works!' : 'Something went wrong…')
Astring can easily be extended by updating or passing a custom code generator
. A code generator
consists of a mapping of node names and functions that take two arguments: node
and state
. The node
points to the node from which to generate the code and the state
exposes the write
method that takes generated code strings.
This example shows how to support the await
keyword which is part of the asynchronous functions proposal. The corresponding AwaitExpression
node is based on this suggested definition.
1// Make sure the astring module is imported and that `Object.assign` is defined 2 3// Create a custom generator that inherits from Astring's base generator 4var customGenerator = Object.assign({}, astring.GENERATOR, { 5 AwaitExpression: function (node, state) { 6 state.write('await ') 7 var argument = node.argument 8 if (argument != null) { 9 this[argument.type](argument, state) 10 } 11 }, 12}) 13// Obtain a custom AST somehow (note that this AST is not obtained from a valid code) 14var ast = { 15 type: 'AwaitExpression', 16 argument: { 17 type: 'CallExpression', 18 callee: { 19 type: 'Identifier', 20 name: 'callable', 21 }, 22 arguments: [], 23 }, 24} 25// Format it 26var code = astring.generate(ast, { 27 generator: customGenerator, 28}) 29// Check it 30console.log( 31 code === 'await callable();\n' ? 'It works!' : 'Something went wrong…', 32)
The bin/astring
utility can be used to convert a JSON-formatted ESTree compliant AST of a JavaScript code. It accepts the following arguments:
-i
, --indent
: string to use as indentation (defaults to "␣␣"
)-l
, --line-end
: string to use for line endings (defaults to "\n"
)-s
, --starting-indent-level
: indent level to start from (defaults to 0
)-h
, --help
: print a usage message and exit-v
, --version
: print package version and exitThe utility reads the AST from a provided list of files or from stdin
if none is supplied and prints the generated code.
As in the previous example, these examples use Acorn to get the JSON-formatted AST. This command pipes the AST output by Acorn from a script.js
file to Astring and writes the formatted JavaScript code into a result.js
file:
1acorn --ecma6 script.js | astring > result.js
This command does the same, but reads the AST from an intermediary file:
1acorn --ecma6 script.js > ast.json 2astring ast.json > result.js
This command reads JavaScript 6 code from stdin
and outputs a prettified version:
1cat | acorn --ecma6 | astring
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 4
Details
Reason
Found 2/28 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
19 existing vulnerabilities detected
Details
Score
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More