Package Exports
- @putout/printer
Readme
Printer 
Prints Babel AST to readable JavaScript.
- βοΈ Similar to Recast, but twice faster, also simpler and easier in maintenance, since it supports only Babel.
- βοΈ As opinionated as Prettier, but has more user-friendly output and works directly with AST.
- βοΈ Like ESLint but works directly with Babel AST.
- βοΈ Easily extandable with help of Overrides.
Supports:
- β ES2023;
- β JSX;
- β TypeScript;
Install
npm i @putout/printerπ Support of Printer
Printer has first class support from πPutout with help of @putout/plugin-printer. So install:
npm i @putout/plugin-printer -aDAnd update .putout.json:
{
"printer": "putout",
"plugins": [
"printer"
]
}To benefit from it.
API
const {write} = require('@putout/printer');
const {parse} = require('@babel/parser');
const ast = parse('const a = (b, c) => {const d = 5; return a;}');
write(ast);
// returns
`
const a = (b, c) => {
const d = 5;
return a;
};
`;Overrides
When you need to extend syntax of @putout/printer just pass a function which receives:
path, Babel Pathwrite, a function to output result of printing into token array;
When path contains to dashes __ and name, it is the same as: write(path.get('right')), and this is
actually traverse(path.get('right')) shortened to simplify read and process.
Here is how you can override AssignmentPattern:
const ast = parse('const {a = 5} = b');
write(ast, {
format: {
indent: ' ',
newline: '\n',
space: ' ',
comments: true,
splitter: '\n',
},
visitors: {
AssignmentPattern(path, {write}) {
write('/* [hello world] */= ');
write('__right');
},
},
});
// returns
'const {a/* [hello world] */= 5} = b;\n';format
With help of format you can override next options:
const overrides = {
format: {
indent: ' ',
newline: '\n',
space: ' ',
comments: true,
splitter: '\n',
},
};indent- use two spaces, tabs, or anything you want;newline- symbol for used for line separation;space- default symbol used for space character;comments- produce comments in output or skip them;splitter- mandatory symbol that used inside of statements like this:
Default options produce:
if (a > 3)
console.log('ok');
else
console.log('not ok');But you can override them with:
const overrides = {
format: {
indent: '',
newline: '',
space: '',
splitter: ' ',
},
};And have minified code:
if (a > 3)
console.log('ok');
else
console.log('not ok');write
Used in previous example write can be used for a couple purposes:
- to write
string; - to write
nodewhenobjectpassed; - to write
nodewhenstringstarted with__;
write(ast, {
visitors: {
AssignmentPattern(path, {write, maybe}) {
maybe.write.newline(path.parentPath.isCallExpression());
write('/* [hello world] */= ');
write('__right');
},
},
});maybe
When you need some condition use maybe. For example, to add newline only when parent node is CallExpression you
can use maybe.write.newline(condition):
write(ast, {
visitors: {
AssignmentPattern(path, {write, maybe}) {
maybe.write.newline(path.parentPath.isCallExpression());
write(' /* [hello world] */= ');
write('__right');
},
},
});write
When are you going to output string you can use low-level function write:
write(ast, {
visitors: {
BlockStatement(path, {write}) {
write('hello');
},
},
});indent
When you need to add indentation use indent, for example when you output body,
you need to increment indentation, and then decrement it back:
write(ast, {
visitors: {
BlockStatement(path, {write, indent}) {
write('{');
indent.inc();
indent();
write('some;');
indent.dec();
write('{');
},
},
});traverse
When are you needing to traverse node, you can use traverse:
write(ast, {
visitors: {
AssignmentExpression(path, {traverse}) {
traverse(path.get('left'));
},
},
});This is the same as write('__left') but more low-level, and supports only objects.
Speed Comparison
About speed, for file speed.js:
const putout = require('putout');
const {readFileSync} = require('fs');
const parser = require('@babel/parser');
const code = readFileSync('./lib/tokenize/tokenize.js', 'utf8');
const ast = parser.parse(code);
speed('recast');
speed('putout');
function speed(printer) {
console.time(printer);
for (let i = 0; i < 1000; i++) {
putout(code, {
printer,
plugins: [
'remove-unused-variables',
],
});
}
console.timeEnd(printer);
}With contents of tokenize.js, we have:

License
MIT