Lint imported object destructuring [duplicate] - javascript

The rule that I'm looking should show error in this case:
import {MY_CONSTANT1, MY_CONSTANT2, MY_CONSTANT3}
And considered as fine in this case:
import {
MY_CONSTANT1,
MY_CONSTANT2,
MY_CONSTANT3
}
Is there such eslint rule?

I was looking for such a rule for both import and export declaration.
As a result I've made a plugin with autofix.
So plugin transforms the code
import { k1, k2 } from 'something'
into
import {
k1,
k2
} from 'something'
and code
export { name1, name2, nameN }
into
export {
name1,
name2,
nameN
}

Edit:
Anton Antonov made a plugin that enforces this rule better than object-curly-newline can: https://stackoverflow.com/a/60477269/6179417
Old answer
Add the object-curly-newline rule to your .eslintrc.json, where at least ImportDeclaration is set to always (the other settings have no effect for enforcing newlines in import declarations).
Example:
"object-curly-newline": ["error", {
"ObjectExpression": "always",
"ObjectPattern": { "multiline": true },
"ImportDeclaration": "always",
"ExportDeclaration": { "multiline": true, "minProperties": 3 }
}]
This pattern will now result in an error:
While this is valid:
However, there is a catch - this rule only requires newlines after the opening brace and before the closing brace, so you can still double up on imports as long as they have newlines in between the braces:

Update on Anton Antonov answer for eslint 8
Because Anton Antonovs repository has been archived and gives meta.fixable error with eslint 8. I Recommend to use ruudandriessen fork of the project .
How to use fork:
Install fork
npm install eslint-plugin-modules-newlines --save-dev
Change all references inside eslint config file of modules-newline -> modules-newlines
Error:
ESLint: Fixable rules must set the `meta.fixable` property to "code" or "whitespace".
Occurred while linting ... Rule: "modules-newline/import-declaration-newline".
Please see the 'ESLint' output channel for details.

I was looking for the solution and unfortunately have only found your question. I have decided to learn a bit about how eslint works and how to write your own plugins and created mine. If you know the parsed the AST node structure it is really easy to work with. Here is the plugin's main file. Autofix is more tricky though so I do not include it as it biased towards my formatting standards.
module.exports = {
rules: {
'single-import-per-line': {
create (context) {
return {
ImportDeclaration(node) {
if (node.specifiers.length < 2) {
return;
}
let previousImport = node.specifiers[0];
for (let i = 1; i < node.specifiers.length; i++) {
const currentImport = node.specifiers[i];
// Omit the first condition if you want to put default imports on a new line as well
if (previousImport.type !== 'ImportDefaultSpecifier'
&& currentImport.loc.start.line === previousImport.loc.end.line
) {
context.report({ node, message: 'Your message' });
return;
}
previousImport = currentImport;
}
},
};
},
},
},
};

you can try this
"semicolon": [true, "always"]

Related

How to tell a JavaScript formatter to add blank lines between function definitions?

I have some JS files which I want to format nicer with a CLI formatter tool like Prettier. I tried Prettier itself, but I was surprised to find that it doesn't add blank lines between function definitions. I think this would enhance visual structure significantly.
An example might clarify what I'm after. Given the input source code:
import {foo, bar} from "./myfoobar.js"
export var myfirstfunc = function (para) {
...
}
// mysecondfunc does wonderful things
export var mysecondfunc = function (more, para) {
...
}
I would like to see the following output code with blank lines:
import {foo, bar} from "./myfoobar.js"
export var myfirstfunc = function (para) {
...
}
// mysecondfunc does wonderful things
export var mysecondfunc = function (more, para) {
...
}
In my test Prettier doesn't do this. Is there a way to tell Prettier -- or another formatter -- to do this kind of visual structuring?
You can achieve something similar to this by using ESLint's padding-line-between-statements rule. Any sort of STATEMENT_TYPE (such as export, import, var) can be specified to require a blank line between it and another given STATEMENT_TYPE (or wildcard, to match anything).
The following config:
padding-line-between-statements: [
"error",
{ blankLine: "always", prev: "export", next: "*" },
{ blankLine: "always", prev: "import", next: "*" },
{ blankLine: "always", prev: "var", next: "*" },
]
results in automatically fixed code of:
import {foo, bar} from "./myfoobar.js"
export var myfirstfunc = function (para) {
}
// mysecondfunc does wonderful things
export var mysecondfunc = function (more, para) {
}
Demo
Any IDE that supports ESLint's auto-fixing (such as VSCode) should be able to implement this.
Feel free to tweak with the config settings objects to require spaces between different types of statements as desired.

Replacing variable with #rollup/plugin-replace throws error

Problem
I am trying to inject / replace environment variables with #rollup/plugin-replace. Unfortunately, I get this error:
TypeError: can't convert undefined to object
Code
// rollup.config.js
import replace from "#rollup/plugin-replace";
import { config } from "dotenv";
config();
export default {
// ...
plugins: [
replace({
values: { YOUTUBE_API: JSON.stringify(process.env.YOUTUBE_API) },
preventAssignment: true,
}),
// ...
}
And I call it like this:
onMount(() => {
(async function getPopular() {
videos = await axios.get("https://www.googleapis.com/youtube/v3/videos", {
part: "id, snippet, suggestions",
chart: "mostPopular",
key: YOUTUBE_API,
});
})();
});
What I tried
I logged out the variable and so can confirm that it exists. Also, if I remove the stringify function, I get another error:
ReferenceError: blablabblub is not defined
I have done this successfully in other projects. What the heck is wrong here?
So after some digging around with the same issue, I found it was related to object assignment. For example:
export default {
// ...
plugins: [
replace({
values: {
env: {
API_URL: process.env.API_URL,
API_VERSION: process.env.API_VERSION,
}
},
preventAssignment: true,
}),
// ...
}
// in some JS or Svelte file
const config = {
host: env.API_URL,
version: env.API_VERSION
}
// The above will result in a reference error of 'env' not being defined.
// in the same JS or Svelte file..
const envVars = env;
const config = {
host: envVars.API_URL,
version: envVars.API_VERSION
}
// this works just fine!
I haven't had anymore time to investigate, but my gut feeling is that rollup won't replace variable names when they are nested inside an object assignment. It might be nice for an optional flag to allow this, but it might also get very messy hence why they didn't do it.
I hope this helps if it's still an issue for you.

How To import sanitize.js to react apps Function / class not found

I've some problem, in my project I need to add Sanitize.js on my project, I've copied to my own 3rd party folder ex vendor
to import it I'm using
import {san} from '../../vendor/Sanitize' //There's No error when compiling this one
but there's an error when I run the page, I'm trying to call the function from Sanitize.js as in readme saying to use it just do like this
var s = new san.Sanitize({
elements: ['a', 'span'],
attributes: {
a: ['href', 'title'],
span: ['class']
},
protocols: {
a: { href: ['http', 'https', 'mailto'] }
}
});
s.clean_node(p);
The Error is
san.Sanitize is not a function/ class constructor
Any idea why this is happening? or did I miss something? There's no Error in compiling process, the error only occurs when I try to run the web page,
Because Sanitize.js is not a module.
Maybe you can try the following solution:
Add export default Sanitize; in end of sanitize.js.
Use import Sanitize from "./sanitize"; to import it.
Remove the following code from sanitize.js.
if ( typeof define === "function" ) {
define( "sanitize", [], function () { return Sanitize; } );
}

VS code object rest/spread operator error

In VS Code editor the JSHint tells me that code below has an error.
const pageSubpartsComponents = {
'page-header': PageHeader,
'page-footer': PageFooter
};
const routes = [{
path: '/',
components: {
default: DefaultLayout,
...pageSubpartsComponents
}
}];
...pageSubpartsComponents has text correction.
The error I get is:
[jshint] Expected '}' to match '{' from line 6 and instead saw
'pageSubpartsComponents'. (E020)
I have .jshintrc file and inside this code:
{
"esversion": 6
}
I know that rest/spread operator is not part of the ES6 but it doesn't allows me to use higher version of ES.
VS Code v 1.25.0-insider
jshint v 0.10.19
What else should I use? Does anyone solve this already?

Javascript Unable to validate computed reference to imported namespace

Not sure if I need to add another jshint library or if I should do this a different way.
I have a file (for explanations reasons we'll call it stuff-functions.js) that exports functions like this...
export function a() {
return 'stuff';
}
export function b() {
return 'more stuff';
}
export function c() {
return 'even more stuff';
}
In another file I'm importing that file and calling that function by an argument...
import * as stuffFunctions from './stuff-functions'
export default class someReactClass {
myFunc(functionToCall) {
return stuffFunctions[functionToCall]();
}
...
}
It works fine, but in the console I'm getting an eslint error...
Unable to validate computed reference to imported namespace 'stuffFunctions'
So, should I go about this differently or hunt down some sort of eslint library that allows for this?
EDIT...
I've added this line to stop the error // eslint-disable-line
I was just curious if there was a better way to do this. Maybe something like...
import {a, b, c} from './stuff-functions';
export default class someReactClass {
myFunc(functionToCall) {
const myStuffFunctions = {
a: a,
b: b,
c: c
};
return myStuffFunctions[functionToCall]();
}
...
}
Seems redundant though. :/
The error is being reported by the import/namespace rule in the eslint-plugin-import plugin. It's occurring because you are deciding which imported function will be called at runtime:
stuffFunctions[functionToCall]();
The plugin's static analysis cannot verify that this is a valid import and it reports it as an error.
The simplest solution would be to add an ESLint comment to reconfigure the rule to allow computed references:
/*eslint import/namespace: ['error', { allowComputed: true }]*/
import * as stuffFunctions from './stuff-functions'
export default class someReactClass {
myFunc(functionToCall) {
return stuffFunctions[functionToCall]();
}
...
}

Categories