eslint / markdown

Lint JavaScript code blocks in Markdown documents
MIT License
406 stars 63 forks source link

Bug: TypeError: Error while loading rule 'no-irregular-whitespace': sourceCode.getAllComments is not a function #299

Closed adamlui closed 2 days ago

adamlui commented 2 days ago

Environment

ESLint version: v9.14.0 @eslint/markdown version: v6.2.1 Node version: v22.9.0 npm version: v10.9.0 Operating System: Win10

Which language are you using?

commonmark

What did you do?

Configuration ```js import js from '@eslint/js' import globals from 'globals' import json from '@eslint/json' import markdown from '@eslint/markdown' export default [ js.configs.recommended, ...markdown.configs.recommended, { ignores: ['**/*.min.js', '**/sandbox/*'] }, { rules: { 'indent': 'off', 'no-unexpected-multiline': 'off', 'key-spacing': 'off', // allow whitespace anywhere 'quotes': ['error', 'single', { 'allowTemplateLiterals': true }], // enforce single quotes except backticks to avoid escaping quotes 'comma-dangle': ['error', 'never'], // enforce no trailing commas in arrays or objects 'no-async-promise-executor': 'off', // allow promise executor functions to be async (to accomodate await lines) 'no-constant-condition': 'off', // allow constant conditions 'no-empty': 'off', // allow empty blocks 'no-inner-declarations': 'off', // allow function declarations anywhere 'no-useless-escape': 'off', // allow all escape chars cause ESLint sucks at detecting truly useless ones 'no-unused-vars': ['error', { 'caughtErrors': 'none' }] // allow unused named args in catch blocks }, languageOptions: { ecmaVersion: 'latest', sourceType: 'script', globals: { ...globals.browser, ...globals.node } } }, { files: ['**/*.mjs'], languageOptions: { sourceType: 'module' }}, { files: ['**/*.json'], ignores: ['**/package-lock.json'], language: 'json/json', ...json.configs.recommended, rules: { 'no-irregular-whitespace': 'off' } } ] ```
# 🛠️ JavaScript utilities

<img height=31 src="https://img.shields.io/badge/Downloads-3K/month-44cc11.svg?logo=npm&color=af68ff&logoColor=white&labelColor=464646&style=for-the-badge"></img>
<a href="../LICENSE.md"><img height=31 src="https://img.shields.io/badge/License-MIT-orange.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
<a href="https://github.com/adamlui/js-utils/commits/main"><img height=31 src="https://img.shields.io/github/commit-activity/m/adamlui/js-utils?label=Commits&logo=github&logoColor=white&labelColor=464646&color=blue&style=for-the-badge"></a>
<a href="https://www.codefactor.io/repository/github/adamlui/js-utils"><img height=31 src="https://img.shields.io/codefactor/grade/github/adamlui/js-utils?label=Code+Quality&logo=codefactor&logoColor=white&labelColor=464646&color=b5fc7b&style=for-the-badge"></a>
<a href="https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=adamlui_js-utils"><img height=31 src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dadamlui_js-utils%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonarcloud&logoColor=white&labelColor=464646&label=Vulnerabilities&color=gold"></a>
<img height=31 src="https://img.shields.io/badge/jsDelivr_Requests-20,000+/month-2bbbd8.svg?logo=jsdelivr&logoColor=white&labelColor=464646&style=for-the-badge">

Essential JavaScript libraries/utilities for Node.js and the web

<img height=10px width="100%" src="https://media.js-utils.org/images/separators/gradient-aqua.png?c0192d3">

### <a href="../generate-ip"><picture><source media="(prefers-color-scheme: dark)" srcset="https://media.generate-ip.org/images/icons/node-graph/white/icon55x49.png?b4eb06e"><img height=21 src="https://media.generate-ip.org/images/icons/node-graph/black/icon55x49.png?b4eb06e"></picture> generate-ip</a> <a href="https://github.com/toolleeo/cli-apps#networking"><img height=18 src="https://media.js-utils.org/images/badges/awesome/badge.svg?7b16322"></a>

> Randomly generate, format, and validate IPv4 + IPv6 + MAC addresses.
<br>[Install](../generate-ip#-installation) /
[Readme](../generate-ip#readme) /
[API usage](../generate-ip#-api-usage) /
[CLI usage](../generate-ip#-command-line-usage) /
[Discuss](https://github.js-utils.org/discussions)

### [🔒 generate-pw](../generate-pw) &nbsp;<a href="https://github.com/toolleeo/cli-apps#password-managers"><img height=18 src="https://media.js-utils.org/images/badges/awesome/badge.svg?7b16322"></a>

> Randomly generate, strengthen, and validate cryptographically-secure passwords.
<br>[Install](../generate-pw#-installation) /
[Readme](../generate-pw#readme) /
[API usage](../generate-pw#-api-usage) /
[CLI usage](../generate-pw#-command-line-usage) /
[Discuss](https://github.js-utils.org/discussions)

### <a href="../geolocate"><picture><source media="(prefers-color-scheme: dark)" srcset="https://media.geolocatejs.org/images/icons/wire-globe/white/icon32.png?e735b99"><img height=22 src="https://media.geolocatejs.org/images/icons/wire-globe/black/icon32.png?e735b99"></picture> geolocate</a>

> Fetch IP geolocation data from the CLI.
<br>[Install](../geolocate#-installation) /
[Readme](../geolocate#readme) /
[CLI usage](../geolocate#-command-line-usage) /
[API usage](../geolocate#-api-usage) /
[Discuss](https://github.js-utils.org/discussions)

### [🖼️ img-to-webp](../img-to-webp)

> Recursively compress all images to WEBPs.
<br>[Download](https://cdn.jsdelivr.net/gh/adamlui/js-utils/img-to-webp/img-to-webp.js) /
[Discuss](https://github.js-utils.org/discussions)

### [</> minify.js](../minify.js) &nbsp;<a href="https://github.com/toolleeo/cli-apps#programming"><img height=18 src="https://media.js-utils.org/images/badges/awesome/badge.svg?7b16322"></a>

> Recursively minify all JavaScript files.
<br>[Install](../minify.js/node.js#-installation) /
[Readme](../minify.js/node.js#readme) /
[CLI usage](../minify.js/node.js#-command-line-usage) /
[API usage](../minify.js/node.js#-api-usage) /
[Discuss](https://github.js-utils.org/discussions)

### [{ } scss-to-css](../scss-to-css/node.js) &nbsp;<a href="https://github.com/toolleeo/cli-apps#conversion"><img height=18 src="https://media.js-utils.org/images/badges/awesome/badge.svg?7b16322"></a>

> Recursively compile all SCSS files into minified CSS.
<br>[Install](../scss-to-css/node.js/#-installation) /
[Readme](../scss-to-css/node.js/#readme) /
[CLI usage](../scss-to-css/node.js/#-command-line-usage) /
[API usage](../scss-to-css/node.js/#-api-usage) /
[Discuss](https://github.js-utils.org/discussions)

<img height=6px width="100%" src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/aqua.png">

<picture><source media="(prefers-color-scheme: dark)" srcset="https://media.js-utils.org/images/icons/tag/white/icon16.svg?7b16322"><img height=14 src="https://media.js-utils.org/images/icons/tag/dark-gray/icon16.svg?7b16322"></picture> <a href="https://js-utils.org/releases">**Latest releases**</a> /
<a href="https://github.js-utils.org/discussions">Discuss</a> /
<a href="#%EF%B8%8F-javascript-utilities">Back to top ↑</a>

What did you expect to happen?

Lint the README.md

What actually happened?

Oops! Something went wrong! :(

ESLint: 9.14.0

TypeError: Error while loading rule 'no-irregular-whitespace': sourceCode.getAllComments is not a function
Occurred while linting e:\js\utils\docs\README.md
    at Object.create (e:\js\utils\node_modules\eslint\lib\rules\no-irregular-whitespace.js:87:41)
    at createRuleListeners (e:\js\utils\node_modules\eslint\lib\linter\linter.js:943:21)
    at e:\js\utils\node_modules\eslint\lib\linter\linter.js:1068:84
    at Array.forEach (<anonymous>)
    at runRules (e:\js\utils\node_modules\eslint\lib\linter\linter.js:999:34)
    at #flatVerifyWithoutProcessors (e:\js\utils\node_modules\eslint\lib\linter\linter.js:1911:31)
    at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (e:\js\utils\node_modules\eslint\lib\linter\linter.js:1992:49)
    at Linter._verifyWithFlatConfigArray (e:\js\utils\node_modules\eslint\lib\linter\linter.js:2081:21)
    at Linter.verify (e:\js\utils\node_modules\eslint\lib\linter\linter.js:1528:61)
    at Linter.verifyAndFix (e:\js\utils\node_modules\eslint\lib\linter\linter.js:2319:29)

Oops! Something went wrong! :(

ESLint: 9.14.0

AbortError: The operation was aborted
    at checkAborted (node:internal/fs/promises:473:11)
    at Object.readFile (node:internal/fs/promises:1236:3)
    at retrier.retry.signal (e:\js\utils\node_modules\eslint\lib\eslint\eslint.js:803:47)
    at #call (e:\js\utils\node_modules\@humanwhocodes\retry\dist\retrier.cjs:298:22)
    at e:\js\utils\node_modules\@humanwhocodes\retry\dist\retrier.cjs:360:44
    at #processPending (e:\js\utils\node_modules\@humanwhocodes\retry\dist\retrier.cjs:399:19)
    at e:\js\utils\node_modules\@humanwhocodes\retry\dist\retrier.cjs:313:33
    at <anonymous>

Oops! Something went wrong! :(

ESLint: 9.14.0

AbortError: The operation was aborted
    at checkAborted (node:internal/fs/promises:473:11)
    at readFileHandle (node:internal/fs/promises:516:3)
    at Object.readFile (node:internal/fs/promises:1239:24)

Link to Minimal Reproducible Example

https://github.com/adamlui/js-utils

Participation

Additional comments

Same error as https://github.com/eslint/json/issues/56

adamlui commented 2 days ago

I temporarily added rules: { 'no-irregular-whitespace': 'off' } to the config to bypass error until the bug is patched

fasttime commented 2 days ago

This is working as intended as per discussion in eslint/json#56, so closing.

adamlui commented 1 day ago

@fasttime check it out, I formatted markdown config like this to align w/ all my other configs:

...
    {
        files: ['**/*.md'], language: 'markdown/commonmark', plugins: { markdown },
        rules: {
            ...markdown.configs.recommended[0].rules,
            'markdown/heading-increment': 'off', // allow headings to skip levels
            'markdown/fenced-code-language': 'off' // allow code blocks w/ no language specified
        }
    },
...

...and it lints MD correctly, and look how beautifully cohesive and maintainable config file now is:

import js from '@eslint/js'
import globals from 'globals'
import json from '@eslint/json'
import markdown from '@eslint/markdown'
import eslintPluginYml from 'eslint-plugin-yml'

export default [
    {
        files: ['**/*.js', '**/*.mjs'], ...js.configs.recommended,
        rules: {
            'indent': 'off', 'no-unexpected-multiline': 'off', 'key-spacing': 'off', // allow whitespace anywhere
            'quotes': ['error', 'single', { 'allowTemplateLiterals': true }], // enforce single quotes except backticks to avoid escaping quotes
            'comma-dangle': ['error', 'never'], // enforce no trailing commas in arrays or objects
            'no-async-promise-executor': 'off', // allow promise executor functions to be async (to accomodate await lines)
            'no-constant-condition': 'off', // allow constant conditions
            'no-empty': 'off', // allow empty blocks
            'no-inner-declarations': 'off', // allow function declarations anywhere
            'no-useless-escape': 'off', // allow all escape chars cause ESLint sucks at detecting truly useless ones
            'no-unused-vars': ['error', { 'caughtErrors': 'none' }] // allow unused named args in catch blocks
        },
        languageOptions: {
            ecmaVersion: 'latest', sourceType: 'script',
            globals: {
                ...globals.browser, ...globals.node, ...globals.greasemonkey,
                chatgpt: 'readonly', chrome: 'readonly', CryptoJS: 'readonly', dom: 'readonly', GM_cookie: 'readonly',
                hljs: 'readonly', ipv4: 'readonly', marked: 'readonly', renderMathInElement: 'readonly'
            }
        }
    },
    { files: ['**/*.mjs', '**/components/*.js', '**/lib/*.js'], languageOptions: { sourceType: 'module' }},
    { files: ['**/*.json'], ignores: ['**/package-lock.json'], language: 'json/json', ...json.configs.recommended },
    {
        files: ['**/*.md'], language: 'markdown/commonmark', plugins: { markdown },
        rules: {
            ...markdown.configs.recommended[0].rules,
            'markdown/heading-increment': 'off', // allow headings to skip levels
            'markdown/fenced-code-language': 'off' // allow code blocks w/ no language specified
        }
    },
    { files: ['**/*.yaml, **/*.yml'], ...eslintPluginYml.configs['flat/standard'][1] }
]

... no outer-level configs.recommendeds to guess if it includes files, every config obj just leads w/ files to allow for easy scanning/adding/maintenance of new plug-ins/rules isolated to each language (thanks to your suggestion for js.configs.recommended)

This is what new 1st-party plug-ins should aim for, keep easy maintenance of config file in mind (@eslint/json got it right since it is new I think so mindset evolved)

fasttime commented 1 day ago

Glad you managed to fix your config in a way that makes it easy to maintain @adamlui. Indeed it is fine to use only certain elements of a config array like configs.recommended[0] or configs['flat/standard'][1] as long as the structure of those arrays doesn't change.