Linting and formatting

Any way to configure linting and formatting? Default is quite good, but always some annoyances.

Examples:

const payload = {
  ts: date.getTime(),
  values: data
};

return {payload: payload};


"'payload' is declared but its value is never read.(6133)", but as image shows, it complains about "payload" not being used, but it is used directly below in return object.

Same with formatting, when pasting stuff it auto-formats code in a separate step. Can ctrl+z to revert it, but annoying when pasting row after row of a long json, to ctrl+z after every paste / ctrl+v.

This is normally configured in configuration files. Would love to get my hand on those. For example prettier:

Or eslint:

Could you copy/paste that source code please, I am not seeing that issue with a simple test.

Which version of node are you using?
What have you got in the codeEditor section of settings.js?

This is just how the editor does it - you get the same behaviour in VSCode. One annoyance you eventually get used to.

I guess they just don't like returns inside if statements :-)...
(one of those heretical discussions we aren't going to join in with)

I sometimes get this warning message too but with 4.0.5 it's an error.

if (msg) {
    const test = "";
    return { payload: test };
}

Nothing special in the settings

You can disable any diagnostic code you desire in your settings.js

You can configure any setup, compilerOptions and diagnosticsOptions you desire in your settings.js

example:

...
    editorTheme: {
        codeEditor: {
            lib: "monaco", //can be "monaco" or "ace"
            options: {
                // /* theme - must match the file name of a theme in 
                //  * packages/node_modules/@node-red/editor-client/src/vendor/monaco/dist/theme
                //  * e.g. "tomorrow-night", "upstream-sunburst", "github", "my-theme"
                //  */
                theme: "github",
                /** @see https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html */
                minimap: {
                    enabled: true,
                    maxColumn: 40,
                    scale: 1,
                    showSlider : "mouseover",
                    renderCharacters: true
                },
                fontSize: 14,
                fontLigatures: true,
                fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace",
                fontWeight: "300",
                colorDecorators: true,
                showFoldingControls: 'always',
                "bracketPairColorization.enabled": true
            },
            monaco: {
                languages: {
                    typescript: {
                        javascriptDefaults: {
                            /** @see https://microsoft.github.io/monaco-editor/typedoc/interfaces/languages.typescript.CompilerOptions.html */
                            compilerOptions: {
                                target: "ESNext",
                                allowNonTsExtensions: true,
                                checkJs: true,
                                allowJs: true,
                                noUnusedLocals: true
                            },
                            /** @see https://microsoft.github.io/monaco-editor/typedoc/interfaces/languages.typescript.DiagnosticsOptions.html */
                            diagnosticsOptions: {
                                diagnosticCodesToIgnore: [
                                    1108,  //return not inside function
                                    2304,  //Cannot find name 
                                    2307,  //Cannot find module 'xxx' or its corresponding type declarations 
                                    2322,  //Type 'unknown' is not assignable to type 'string'
                                    2339,  //property does not exist on 
                                    7043,  //i forget what this one is,
                                    80001, //Convert to ES6 module  
                                    80004, //JSDoc types may be moved to TypeScript types.
                                ]
                            }
                        },
                        json: {
                            jsonDefaults: { diagnosticOptions: {} }
                        },
                        html: {
                            handlebarDefaults: {},
                            htmlDefaults: {}
                        }
                    },
                },
            },   
        },
    }
...

You can test what works for you in the Monaco Editor Playground: Monaco Editor


Not supported and currently not planned. This would be quite an undertaking.

1 Like

Please show me

I would like to but I can't reproduce it anymore. I didn't change anything. I switched between the master and 4.0.5 versions and now I don't have any more errors, just the warning.

:thinking:

In vscode, I configure the editor to behave exactly how I want it to :smiley:

Node-RED v4.0.5
Node.js v20.18.0

Welcome to Node-RED

11 Nov 12:14:28 - [info] Node-RED version: v4.0.5
11 Nov 12:14:28 - [info] Node.js version: v20.18.0
11 Nov 12:14:28 - [info] Linux 6.6.51+rpt-rpi-2712 arm64 LE
11 Nov 12:14:28 - [info] Loading palette nodes
11 Nov 12:14:30 - [info] Settings file : /data/settings.js
11 Nov 12:14:30 - [info] Context store : 'default' [module=localfilesystem]
11 Nov 12:14:30 - [info] User directory : /data
11 Nov 12:14:30 - [info] Projects directory: /data/projects
11 Nov 12:14:30 - [info] Server now running at http://127.0.0.1:1880/
11 Nov 12:14:30 - [info] Active project : ktp-a
11 Nov 12:14:30 - [info] Flows file : /data/projects/ktp-a/flows.json
11 Nov 12:14:30 - [warn] Using unencrypted credentials
11 Nov 12:14:30 - [info] Starting flows
11 Nov 12:14:30 - [info] Started flows

Source code:

const data = msg.payload;

const date = new Date();
date.setMilliseconds(0);

if (data && typeof data === 'object') {
    const payload = {
        ts: date.getTime(),
        values: data
    };

    return {payload: payload};
}

node.error("Payload field is missing or not an object", msg);
return null;

What I do to trigger the lint warning is to ctrl-click the last payload in "return {payload: payload}" to go to source / definition. Then the lightbulb and warning tooltip triggers.

Great! Looks like you can ignore a bunch of linter rules which is useful. Can you add also? If so, no undertaking at all, linting seems to be configurable. Thanks for pointing me in the right direction.

Wouldn't the same be possible for formatting also, using monaco config in settings.js?

Probably - but that might require the addition of a custom LSP - i've not investigated.

You can change a number of formatting items (all those listed in the link i provided to the monaco APIs in the demo JS)

What you cannot do is use something like prettier. That would require specific integration.

Thanks, makes a lot of sense! I'm not in the mood to go some off-road route with custom eslint added on top of monaco. What about current formatting behavior, is that some hardcoded monaco default?

Monaco has default formatting set (and we (node-red)) have applied some sane defaults like slimming down the minimap for a smaller editor).

Everything you see in IStandaloneEditorConstructionOptions | Monaco Editor API is what you can affect.

you can try them out in the playground

1 Like

Thanks again, great documentation there. I realize it has quite a lot of options, but limited for more fine-grained details. Stumbled over this description of flow linter - nrlint:

Looks promising:

But it doesn't look like it is included by default, so must be installed manually?

Edit: Tried it out, amazing! Might even add eslint rules there.

Played around with nrlint a bit. One thing I didn't understand, the guide has a command to generate a default config file:

  • .nrlintrc.js

Editing this file doesn't seem to change anything in node red, so presumably this is for CLI only? But where is the config file stored for the rules used in node red? I can edit rules in node red editor, but can't find anywhere it is stored. Is it hidden deep inside npm folders somewhere (.npm or node_modules)?

Open the description field of a node where you have applied an ignore and/or the tabs documentation tab.

Sorry I don't understand. Description field is empty for any particular node. Documentation tab looks like normal.

I'm talking about function-eslint value here:

Can open it in editor like this:

Edit: Wow, it goes into user settings! Hehe. I had .config.users.json under gitignore.

Definitely don't see that in VSCode:

function fred() {
    const date = new Date();
    const data = {}
    if (true) {
        const payload = {
            ts: date.getTime(),
            values: data
        };
        
        return {payload: payload};
    }
    return null;
}

And not in a function node either:

Whatever you see or don't see in VSCode is configurable in eslint or in parts vs code settings.json, no? In my experience, you can take control and choose what and how is displayed.

After some thought I think it makes a lot of sense to have nrlint rules in user settings. Because they ought to be configured individually. The main rules in the nrlint file is then used for CD/CI pipeline as normal.