$ npm install @putout/plugin-putout
πPutout plugin helps with plugins development.
npm i @putout/plugin-putout -D
{
"rules": {
"putout/apply-create-test": "on",
"putout/apply-processors-destructuring": "on",
"putout/apply-async-formatter": "on",
"putout/apply-declare": "on",
"putout/apply-rename": "on",
"putout/apply-remove": "on",
"putout/apply-insert-before": "on",
"putout/apply-insert-after": "on",
"putout/apply-short-processors": "on",
"putout/apply-namespace-specifier": "on",
"putout/apply-for-of-to-track-file": "on",
"putout/add-places-to-compare-places": "on",
"putout/add-test-args": "on",
"putout/add-traverse-args": "on",
"putout/add-track-file": "on",
"putout/add-await-to-progress": "on",
"putout/add-index-to-import": "on",
"putout/check-match": "on",
"putout/check-replace-code": ["on", {
"once": true
}],
"putout/convert-putout-test-to-create-test": "on",
"putout/convert-to-no-transform-code": "on",
"putout/convert-number-to-numeric": "on",
"putout/convert-replace-with": "on",
"putout/convert-replace-with-multiple": "on",
"putout/convert-replace-to-function": "on",
"putout/convert-match-to-function": "on",
"putout/convert-babel-types": "on",
"putout/convert-destructuring-to-identifier": "on",
"putout/convert-node-to-path-in-get-template-values": "on",
"putout/convert-traverse-to-include": "on",
"putout/convert-traverse-to-replace": "on",
"putout/convert-traverse-to-scan": "on",
"putout/convert-process-to-find": "on",
"putout/convert-method-to-property": "on",
"putout/convert-add-argument-to-add-args": "on",
"putout/convert-dirname-to-url": "on",
"putout/convert-url-to-dirname": "on",
"putout/convert-report-to-function": "on",
"putout/convert-get-rule-to-require": "on",
"putout/convert-progress-to-track-file": "on",
"putout/create-test": "on",
"putout/shorten-imports": "on",
"putout/declare": "on",
"putout/includer": "on",
"putout/move-require-on-top-level": "on",
"putout/replace-test-message": "on",
"putout/remove-unused-get-properties-argument": "on",
"putout/remove-empty-array-from-process": "on",
"putout/simplify-replace-template": "on"
}
}
test('', async (t) => {
await t.process({});
});
test('', async ({process}) => {
await process({});
});
Apply short names of processors, for example __json
instead of __putout_processor_json
. Checkout out in πPutout Editor.
export const match = () => ({
'__putout_processor_ignore(__a)': ({__a}) => {
const list = __a.elements.map(getValue);
},
'__putout_processor_filesystem(__a)': ({__a}) => {
const list = __a.elements.map(getValue);
},
});
export const match = () => ({
[__ignore]: ({__array}) => {
const list = __array.elements.map(getValue);
},
[__filesystem]: ({__object}) => {
const list = __object.elements.map(getValue);
},
});
Better use rename(path, from, to)
method of operator
.
Check out in πPutout Editor.
export const fix = ({path, from, to}) => {
path.scope.rename(from, to);
};
import {operator} from 'putout';
const {rename} = operator;
export const fix = ({path, from, to}) => {
rename(path, from, to);
};
Better to use remove(path)
method of operator
.
It helps to preserve comments.
export const fix = (path) => {
path.remove();
};
import {operator} from 'putout';
const {remove} = operator;
export const fix = (path) => {
remove(path);
};
Better to use insertBefore(a, b)
method of operator
.
export const fix = (path) => {
path.insertBefore(path.get('init'));
};
import {operator} from 'putout';
const {insertBefore} = operator;
export const fix = (path) => {
insertBefore(path, path.get('init'));
};
Better to use insertAfter(a, b)
method of operator
.
It helps to avoid duplication of comments.
export const fix = (path) => {
path.insertAfter(path.get('init'));
};
import {operator} from 'putout';
const {insertAfter} = operator;
export const fix = (path) => {
insertAfter(path, path.get('init'));
};
Better to use Declareator
instead of operator.declare()
.
Check out in πPutout Editor.
const {operator} = require('putout');
const {declare} = operator;
module.exports = declare({
tryCatch: `import tryCatch from 'try-catch'`,
tryToCatch: `import tryToCatch from 'try-to-catch'`,
});
module.exports.declare = () => ({
tryCatch: `import tryCatch from 'try-catch'`,
tryToCatch: `import tryToCatch from 'try-to-catch'`,
});
test('formatter: codeframea', (t) => {
t.format(codeframe, 1);
t.end();
});
test('formatter: codeframea', async ({format}) => {
await format(codeframe, 1);
});
const test = require('@putout/test')({
'remove-debugger': plugin,
});
const {createTest} = require('@putout/test');
const test = createTest({
'remove-debugger': plugin,
});
The Generator object is returned by a
generator function
and it conforms to both the iterable protocol and theiterator
protocol.(c) MDN
trackFile
is generator function used to count progress that can be used in Scanner.
Checkout in πPutout Editor
module.exports.scan = (path, {push, trackFile}) => {
trackFile(path, '*.swp').map(push);
};
module.exports.scan = (path, {push, trackFile}) => {
for (const file of trackFile(path, '*.swp')) {
push(file);
}
};
Add properties to createTest
options, here is exmample of .putout.json
:
{
"rules": {
"putout/create-test": ["on", {
"add": [
["printer", "putout"]
]
}]
}
}
Check it out in πPutout Editor.
createTest(__dirname, {
'putout/create-test': plugin,
});
createTest(__dirname, {
printer: 'putout',
plugins: [
['putout/create-test', plugin],
],
});
Prevent Babel
warning: The node type NumberLiteral has been renamed to NumericLiteral
.
const {isNumberLiteral} = types;
isNumberLiteral(node);
const {isNumericLiteral} = types;
isNumericLiteral(node);
Fixes results of @putout/convert-commonjs-to-esm work.
import putoutTest from '@putout/test';
const test = putoutTest(__dirname, {
'remove-unused-variables': rmVars,
});
import {createTest} from '@putout/test';
const test = createTest(__dirname, {
'remove-unused-variables': rmVars,
});
test('plugin-apply-destructuring: transform: array: destructuring', (t) => {
const code = 'const {name} = array[0]';
t.transform(code, '');
t.end();
});
test('plugin-apply-destructuring: transform: array: destructuring', (t) => {
const code = 'const {name} = array[0]';
t.noTransformCode(code);
t.end();
});
module.exports.fix = (path) => {
path.replaceWith(Identifier('hello'));
};
const {replaceWith} = require('putout').operator;
module.exports.fix = (path) => {
replaceWith(path, Identifier('hello'));
};
module.exports.fix = (path) => {
path.replaceWithMultiple([
Identifier('hello'),
]);
};
const {replaceWithMultiple} = require('putout').operator;
module.exports.fix = (path) => {
replaceWithMultiple(path, [
Identifier('hello'),
]);
};
module.exports.replace = {
'let __a = __b': 'const __b = __a',
};
module.exports.replace = () => ({
'let __a = __b': 'const __b = __a',
});
module.exports.match = {
'let __a = __b': () => false,
};
module.exports.match = () => ({
'let __a = __b': () => false,
});
const {
ObjectExpression,
SpreadElement,
isObjectExpression,
isIdentifier,
} = require('@babel/types');
const {
ObjectExpression,
SpreadElement,
isObjectExpression,
isIdentifier,
} = require('putout').types;
module.exports.replace = () => ({
'const __a = __b': ({}) => {},
'const __c = __d': ({}, path) => {},
});
module.exports.replace = () => ({
'const __a = __b': (vars) => {},
'const __c = __d': (vars, path) => {},
});
const {__a, __b} = getTemplateValues(path.node, 'const __a = __b');
const {__a, __b} = getTemplateValues(path, 'const __a = __b');
const parseOptions = require('putout/lib/parse-options');
const parseOptions = require('putout/parse-options');
module.exports.traverse = ({push}) => ({
TSTypeAssertion(path) {
push(path);
},
});
module.exports.include = () => [
'TSTypeAssertion',
];
module.exports.traverse = () => ({
'async (__a) => __b': 'async ({process}) => __b',
});
module.exports.replace = () => ({
'async (__a) => __b': 'async ({process}) => __b',
});
Checkout in πPutout Editor:
module.exports.traverse = ({push, options}) => ({
[__filesystem](path) {
const {names} = options;
for (const name of names) {
const files = findFile(path, name);
for (const file of files) {
push({
name,
path: file,
});
}
}
},
});
module.exports.scan = (path, {push, options}) => {
const {names} = options;
for (const name of names) {
const files = findFile(path, name);
for (const file of files) {
push(file, {
name,
});
}
}
};
module.exports.preProcess = () => {};
module.exports.postProcess = () => {};
module.exports.branch = (rawSource) => [];
module.exports.merge = (processedSource, list) => '';
convert-destructuring-to-identifier
which is Replacer
, while convert-method-to-property
is Includer
(searches for ObjectMethod
node);module.exports.match = () => ({
'module.exports.traverse = __a'({}, path) {},
});
module.exports.match = () => ({
'module.exports.traverse = __a': ({}, path) => {},
});
Checks that Replacer transform is possible.
Pass once=false
to always fail no matter how many fixCounts
passed.
module.exports.replace = () => ({
'if (__a = __b) __body': 'if (__a === "__b") __body',
});
βοΈ There is no fix
for this rule, it used internally to be more confident about test coverage
, because of declaration form, transforms cannon be checked by nyc
and c8
, and uncovered lines can find unfixable false positives when running on code.
This is additional tests, if you forget to test some case (from a big list of rules that is supported) it will be checked with this rule
and make transforms more stable.
Checks that Replacer match()
keys exists in replace
.
Checkout in πPutout Editor.
module.exports.match = () => ({
'__a = __b': (vars, path) => {},
});
module.exports.replace = () => ({
'__a = __': '__a',
});
βοΈ There is no fix
for this rule, it used internally to be more confident about test coverage
, because of declaration form, transforms cannon be checked by nyc
and c8
, and uncovered lines can find unfixable false positives when running on code.
This is additional tests, if you forget to test some case (from a big list of rules that is supported) it will be checked with this rule
and make transforms more stable.
Depends on @putout/convert-esm-to-commonjs and @putout/declare.
compare(a, 'const __a = __b');
isIdentifier(a);
const {operator, types} = require('putout');
const {compare} = operator;
const {isIdentifier} = types;
compare(a, 'const __a = __b');
isIdentifier(a);
comparePlaces
takes two or more arguments.
Checkout in πPutout Editor.
comparePlaces('hello');
comparePlaces('hello', []);
test('', () => {
comparePlaces();
});
test('', ({comparePlaces}) => {
comparePlaces();
});
Checkout in πPutout Editor. Supported args:
push
:module.exports.traverse = () => ({
'__a.replace(/__b/g, __c)': (path) => {
push(path);
},
});
module.exports.traverse = ({push}) => ({
'__a.replace(/__b/g, __c)': (path) => {
push(path);
},
});
module.exports.traverse = () => ({
ImportDeclaration(path) {
const {node} = path;
const {name} = node.specifiers[0].local;
store('name', name);
},
});
module.exports.traverse = ({store}) => ({
ImportDeclaration(path) {
const {node} = path;
const {name} = node.specifiers[0].local;
store('name', name);
},
});
export const traverse = () => ({
ImportDeclaration(path) {
listStore(path);
},
});
module.exports.traverse = ({listStore}) => ({
ImportDeclaration(path) {
listStore(path);
},
});
export const traverse = () => ({
'module.exports.match = __object': pathStore,
});
export const traverse = ({pathStore}) => ({
'module.exports.match = __object': pathStore,
});
Checkout in πPutout Editor.
test('', ({progress}) => {
progress();
});
test('', async ({progress}) => {
await progress();
});
Checkout in πPutout Editor.
export const scan = (root, {push, progress}) => {
trackFile();
};
export const scan = (root, {push, progress, trackFile}) => {
trackFile();
};
ESM doesn't add index.js
, so it can be left after @putout/plugin-convert-esm-to-commonjs
.
Checkout in πPutout Editor.
import insertRust from './insert-rust.js';
import addAction from './add-action.js';
export const rules = {};
import insertRust from './insert-rust/index.js';
import addAction from './add-action/index.js';
export const rules = {};
const {operator} = require('putout');
const {addArgument} = operator;
module.exports = addArgument({
t: ['t', 'test("__a", (__args) => __body)'],
});
const {operator} = require('putout');
const {addArgs} = operator;
module.exports = addArgs({
t: ['t', 'test("__a", (__args) => __body)'],
});
import {createTest} from '@putout/test';
import plugin from '@putout/plugin-debugger';
import {createSimport} from 'simport';
const {__dirname} = createSimport(import.meta.url);
const test = createTest(__dirname, {
'remove-debugger': plugin,
});
import {createTest} from '@putout/test';
import plugin from '@putout/plugin-debugger';
const test = createTest(import.meta.url, {
'remove-debugger': plugin,
});
const {createTest} = require('@putout/test');
const plugin = require('@putout/plugin-debugger');
const test = createTest(__dirname, {
'remove-debugger': plugin,
});
const {createTest} = require('@putout/test');
const plugin = require('@putout/plugin-debugger');
const test = createTest(import.meta.url, {
'remove-debugger': plugin,
});
module.exports.report = `'report' should be a 'function'`;
module.exports.report = () => `'report' should be a 'function'`;
Checkout in πPutout Editor.
module.exports.scan = (root, {push, progress}) => {
const files = findFile(root, ['*']);
const n = files.length;
for (const [i, file] of files.entries()) {
push(file);
progress({
i,
n,
});
}
};
module.exports.scan = (root, {push, trackFile}) => {
for (const file of trackFile(root, ['*'])) {
push(file);
}
};
dynamicRequireTargets
;Checkout in πPutout Editor.
module.exports.rules = {
...getRule('remove-unused-variables'),
};
const removeUnusedVariables = require('./remove-unused-variables');
module.exports.rules = {
'remove-unused-variables': removeUnusedVariables,
};
const test = require('@putout/test')(__dirname, {
'remove-debugger': require('..'),
});
test('remove debugger: report', (t) => {
t.transform('debugger', {
'remove-debugger': require('..'),
});
t.end();
});
const removeDebugger = require('..');
const test = require('@putout/test')(__dirname, {
'remove-debugger': removeDebugger,
});
test('remove debugger: report', (t) => {
t.transform('debugger', {
'remove-debugger': removeDebugger,
});
t.end();
});
module.exports.include = () => 'cons __a = __b';
module.exports.exclude = () => 'var __a = __b';
module.exports.include = 'cons __a = __b';
module.exports.exclude = 'var __a = __b';
module.exports.include = [
'cons __a = __b',
];
module.exports.exclude = [
'var __a = __b',
];
module.exports.include = () => [
'cons __a = __b',
];
module.exports.exclude = () => [
'var __a = __b',
];
module.exports.include = () => [
'cons __a = __b',
];
module.exports.exclude = () => [
'var __a = __b',
];
module.exports.include = () => [
'cons __a = __b',
];
module.exports.exclude = () => [
'var __a = __b',
];
Checks that test message
and used operator
are synchronized.
Check it out in πPutout Editor.
test('plugin-putout: rename-operate-to-operator: transform: operator exist', (t) => {
t.noTransform('operator');
t.end();
});
test('plugin-putout: rename-operate-to-operator: report: operator exist', (t) => {
t.noReport('operator');
t.end();
});
test('plugin-putout: rename-operate-to-operator: no transform: operator exist', (t) => {
t.noTransform('operator');
t.end();
});
test('plugin-putout: rename-operate-to-operator: no report: operator exist', (t) => {
t.noReport('operator');
t.end();
});
Check it out in πPutout Editor.
await process('input', []);
await process('input');
Check it out in πPutout Editor.
const {
overridesPath,
parserPath,
rulesPath,
} = getProperties(__jsonPath, [
'parser',
'rules',
'overrides',
'extends',
]);
const {
overridesPath,
parserPath,
rulesPath,
} = getProperties(__jsonPath, ['parser', 'rules', 'extends']);
Checkout in πPutout Editor.
module.exports.replace = () => ({
'if (__a) {__b} else {__c}': () => 'if (__a) __b; else __c',
});
module.exports.replace = () => ({
'if (__a) {__b} else {__c}': 'if (__a) __b; else __c',
});
MIT
© 2010 - cnpmjs.org x YWFE | Home | YWFE