π Pluggable and configurable JavaScript Linter, code transformer and formatter with built-in ESLint and Babel support for js, jsx typescript, flow, markdown, yaml and json. Write declarative codemods in a simplest possible way π
MIT License
Published by coderaiser over 2 years ago
Once you realize that the world is your own projection, you are free of it. You need not free yourself of a world that does not exist, except in your own imagination! However is the picture, beautiful or ugly, you are painting it and you are not bound by it. Realize that there is nobody to force it on you, that it is due to the habit of taking the imaginary to be real. See the imaginary as imaginary and be free of fear.
(c) Sri Nisargadatta Maharaj
When you changed implementation of a plugin, and want to update fixtures you can run the test with UPDATE
env variable:
UPDATE=1 npm test
It will update all your fixtures and remove unused fixture
files for noReport
and noTransform
.
promises/remove-useless-await
In the mirror of your mind all kinds of pictures appear and disappear. Knowing that they are entirely your own creations, watch them silently come and go. Be alert, but not perturbed. This attitude of silent observation is the very foundation of yoga. You see the picture, but you are not the picture.
(c) Sri Nisargadatta Maharaj
-const hello = await 'world';
+const hello = 'world'
madrun/add-cut-env
Instead of searching for what you do not have, find out what it is that you have never lost.
(c) Sri Nisargadatta Maharaj
export default {
- 'test': () => [env, 'test:only'],
+ 'test': async () => [env, await cutEnv('test:only')],
'test:only': () => [env, 'npm test'],
};
Shift your attention from words to silence and you will hear.
(c) Sri Nisargadatta Maharaj
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Published by coderaiser over 2 years ago
Among the maxims on Lord Naoshigeβs wall there was this one: βMatters ofβ great concern should be treated lightly.β
Master lttei commented, βMatters of small concern should be treated seriously.β(c) Yamamoto Tsunetomo "Hagakure"
Hi folks!
The time is came for a new release π !
We drop support of node versions < 16. "Why is so?" - you ask. The main goal of πPutout
is bringing best practices in software development process. And one of best practices is updating dependencies in time.
Node v16
stable, LTS, and I see no reason to wait for about a year while everybody drop v14
.
Anyways if you cannot upgrade just use πPutout
v24, and if you have any problems create an issue I'm always here to help :).
apply-array-at
Among oneβs affairs there should not be more than two or three matters of what one could call great concern.
If these are deliberated upon during ordinary times, they can be understood. Thinking about things previously
and then handling them lightly when the time comes is what this is all about.(c) Yamamoto Tsunetomo "Hagakure"
The second reason of dropping old versions is adapting and popularizing new constructions like array.at()
. So from now on @putout/plugin-apply-array-at
is bundled and will help you, when you want to get last element of an array.
const array = [1, 2, 3];
console.log(array[array.length - 1]);
const array = [1, 2, 3];
console.log(array.at(-1));
apply-array-at
is written in π¦PutoutScript and looks this way:
module.exports.replace = () => ({
'__a[__a.length - __b]': '__a.at(-__b)',
});
So much power in so little code, breathtaking isn't it π?
βοΈ Wandering why still in CommonJS
and not ESM
? Worry not! Wait until https://github.com/eslint/eslint/issues/15394 resolved: we need eslint-plugin-putout
working! Anyways convert-commonjs-to-esm
is ready π€Ί, and when the time is come β conversion unavoidable β.
try-catch
With help of try-catch
rules big and ugly try-catch
blocks will be converted to small and beautiful calls.
try {
say('hello');
} catch (error) {
log(error);
}
import tryCatch from 'try-catch';
const [error] = tryCatch(say, 'hello');
if (error)
log(error);
This all possible with help of:
Here is reasoning of using try-catch
instead of old syntax construction.
To face an event anew solve it lightly is difficult if you are not resolved beforehand,
and there will always be uncertainty in hitting your mark.
However, if the foundation is laid previously, you can think of the saying,
βMatters of great concern should be treated lightly,β as your own basis for action.(c) Yamamoto Tsunetomo "Hagakure"
Node v14 has one type of loaders:
And node v16 has other:
That's not fun at all to support both of them π ...
βοΈ So mock-import
, zenload
and π©EScover
also updated to support only latest version of API.
That's all for today. Have a good day and take care of your codebases π¦!
βοΈ Looks like 'match' property value is not a 'function', but 'string' with value 'xxx'.
βοΈ Cannot determine type of plugin fn. Here is list of supported plugins: https://git.io/JqcMn
βοΈ Looks like you passed template value with a wrong type. Allowed: string, node and path. Received: true
Published by coderaiser over 2 years ago
These three attributes, Sat, Chit, and Ananda
(Existence, Consciousness, and Bliss),
Do not actually define Brahman.
A poison is poison to others,
But not to itself.Shininess, hardness, and yellowness,
Together signify gold.
Stickiness, sweetness, and viscosity,
Together signify honey.(c) Jnaneshwara "AmαΉitβΔnubhava"
(c) Cipactli
Hi folks!
Today we talk about changes that will make installing πPutout
faster.
promises
@putout/plugin-promises
merged rules:
apply-top-level-await
remove-useless-async
remove-useless-await
remove-empty
@putout/plugin-remove-empty
merged remove-empty-pattern
.
destruct
in remove-useless-variables
remove-useless-variables
can do a lit bit more π.
-function hello(args) {
- const {a, b} = args;
-}
+function hello({a, b}) {
+}
Take a look at draft if you want to see how it works.
remove-unused-variables
got more powerfulNow it supports ClassProperties
(#96), and code:
import thing from β./thing.jsβ;
const pi = Math.PI;
export default class {
static t = thing;
static mathPi = pi;
t = thing;
}
will be linted with no false positives:
1:7 error "thing" is defined but never used remove-unused-variables
3:6 error "pi" is defined but never used remove-unused-variables */
Thanks for reporting to @adamdicarlo!
If you want help, and don't know how, take a look at good first issue label :).
That's all for today, cheers π!
Published by coderaiser over 2 years ago
βThere is nothing outside of yourself that can ever enable you to get better, stronger, richer, quicker, or smarter.
Everything is within. Everything exists. Seek nothing outside of yourself.β
(c) Miyamoto Musashi
Hi folks!
Today we talk about @putout/compare. It used a lot in Replacer
and Includer
.
Long time ago for simplification when types of nodes are different comparing started to go upwards.
But π©ESCover
needs to preserve comparing with:
compare(path, 'const __a = __b', {
findUp: false,
});
So:
const operator = getOperator(ret.argument || ret);
Can be converted to:
const operator = (__c4['π§¨'](4, 17), getOperator((__c4['π§¨'](4, 29), ret.argument) || (__c4['π§¨'](4, 45), ret)));
Instead of:
const operator = (__c4['π§¨'](4, 17), getOperator(ret.argument || ret));
While SequenceExpressions
like (__c4['π§¨'](__d, __e), __f)
are excluded.
Speca
?Well, β¨οΈSpeca
is a test generator based on πPutout
. Some cases wasn't covered, so I trapped on this.
Here is how it looks like:
That's all for today π!
Published by coderaiser over 2 years ago
ESLint
The baby looks at things all day without winking; that is because his eyes are not focused on any particular object. He goes without knowing where he is going, and stops without knowing what he is doing. He merges himself within the surroundings and moves along with it. These are the principles of mental hygiene.β
β Chuang-Tzu
Hi folks!
Now you can test ESLint
in a simplest possible way, using @putout/test.
All you need is create test:
import {createTest} from '@putout/test/eslint';
const test = createTest(import.meta.url);
And process
:
test('test: eslint: transform', async ({process}) => {
await process('operator-linebreak');
});
When you want to pass options:
test('test: eslint: transform', async ({process}) => {
await process('operator-linebreak', {
rules: {
'putout/putout': {
rules: {
'convert-esm-to-commonjs': 'on',
},
},
},
});
});
When you want to compare found places:
test('eslint-config: operator-line-break', async ({comparePlaces}) => {
await comparePlaces('operator-linebreak', [{
"message": "There should be no line break before or after '='.",
"position": {
"column": 1,
"line": 2,
},
"rule": "operator-linebreak (eslint)",
}]);
});
That's all for today :)!
Published by coderaiser over 2 years ago
ESLint
APIForget the years, forget distinctions. Leap into the boundless and make it your home!
Zhuangzi
Hi foks! Let's talk about ESLint
API
a little bit more.
ESLint
begins his work as a formatter when πPutout
done his transformations. That's why it used a lot in different parts of application, for testing purpose and using API
in a simplest possible way. You can access it with:
import {eslint} from 'putout/eslint';
To use it simply write:
const [source, places] = await eslint({
name: 'hello.js',
code: `const t = 'hi'\n`,
fix: false,
config: {
extends: [
'plugin:putout/recommended',
],
},
});
Isn't it looks similar to πPutout
way? It definitely is! But... It has a couple differences you should remember:
Putout
returns object with code
and places
properties.
ESLint
has a name
property that is used to calculate configuration file.
If you want to apply πPutout
transformations using putout/putout
ESLint
rule, enable putout
with the same called flag:
const [source, places] = await eslint({
name: 'hello.js',
code: `const t = 'hi'\n`,
fix: true,
putout: true,
config: {
extends: [
'plugin:putout/recommended',
],
},
});
It is disabled by default, because ESLint
always runs after πPutout
transformations, so there is no need to traverse tree again.
ESCover
?π©ESCover
is ready to be used in a regular basis π!
The only thing is: it works with EcmaScript Modules
only. And this is for a reason: for CommonJS
you can use c8
and nyc/istanbul
. But there is no tool that shows coverage for files changed with node loaders
.
ESCover
?Inside of π©ESCover
you can find the plugin for πPutout
which sets markers that should be called.
Results saved to coverage/lcov.info
to read them when done.
-βοΈ lcov
was created in 2002
, almost twenty years ago.
-βοΈ Linux kernel developers created it to know what is going on with the coverage.
-βοΈ It's written in PERL
and has text based format.
-βοΈ This is most popular coverage format of all times supported by a lot of tools (like coveralls).
So if we run our ESM
application with:
estrace npm test
We will receive something similar to:
SF:/Users/coderaiser/escover/lib/transform.js
DA:1,1
DA:3,1
DA:7,1
DA:9,1
DA:10,1
DA:12,1
DA:24,1
DA:25,1
DA:27,1
DA:28,1
DA:29,1
DA:32,1
end_of_record
Where:
SF
- is path to source;DA
- is line number, and count of running;end_of_record
latest recored for current file entry;As for me this is really human readable, and very compact form. The only thing I don't get for now is: counters, I see no reason why do I need them π€·ββοΈ, if you have a reason create an issue. It can be added in one line of code.
That's all for today!
Have a nice day π!
Published by coderaiser over 2 years ago
Published by coderaiser almost 3 years ago
Published by coderaiser almost 3 years ago
Where can I find a man who has forgotten words so I can have a word with him?
(c) Zhuangzi
Hi folks!
When you removing a variable, or manipulate in any way with it, for example
import {readFile} from 'fs/promises';
import {writeFile} from 'fs/promises';
log(readFile, writeFile);
Will be converted with merge-duplicate-imports
to:
import {readFile, writeFile} from 'fs/promises';
log(readFile, writeFile);
But! When you have declare-undefined-variables enabled: you in trouble! And most likely see error message like this:
TypeError: Cannot read properties of undefined (reading 'buildError')
This is the way Babel
tries to tell you that there is names collision, and code contains a couple variables with the same name.
The thing is merge-duplicate-imports
doesn't crawl the tree with help of:
path.scope.getProgramParent().crawl();
It only removes old nodes, and adds a new one.
This is a thing that adds variables to bindings
object, so other plugins can determine whether they declared or not.
But worry not! This behaviour was fixed in even more! You don't ever need to think about was AST
crawled after your plugin made fixes or not. From now it's crawled on every fix π !
That's all for today! Have a nice weekend!
Published by coderaiser almost 3 years ago
Published by coderaiser almost 3 years ago