Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Biome.js for local linting #5587

Draft
wants to merge 19 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .esbuild/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { build } from 'esbuild';
import { mkdir, writeFile } from 'node:fs/promises';
import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js';
import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
import { type MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';

const shouldVisualize = process.argv.includes('--visualize');

Expand Down
2 changes: 1 addition & 1 deletion .esbuild/jisonPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { readFile } from 'node:fs/promises';
import { transformJison } from '../.build/jisonTransformer.js';
import { Plugin } from 'esbuild';
import type { Plugin } from 'esbuild';

export const jisonPlugin: Plugin = {
name: 'jison',
Expand Down
2 changes: 1 addition & 1 deletion .esbuild/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const external: string[] = ['require', 'fs', 'path'];
const { name, file, packageName } = packageOptions[entryName];
const outFileName = getFileName(name, options);
let output: BuildOptions = buildOptions({
const output: BuildOptions = buildOptions({
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
entryPoints: {
[outFileName]: `src/${file}`,
Expand Down
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = {
'plugin:json/recommended',
'plugin:markdown/recommended-legacy',
'plugin:@cspell/recommended',
'prettier',
'biome',
],
plugins: [
'@typescript-eslint',
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ jobs:
- name: Run Linting
shell: bash
run: |
if ! pnpm run lint; then
if ! pnpm run lint:ci; then
# print a nice error message on lint failure
ERROR_MESSAGE='Running `pnpm run lint` failed.'
ERROR_MESSAGE='Running `pnpm run lint:ci` failed.'
ERROR_MESSAGE+=' Running `pnpm -w run lint:fix` may fix this issue. '
ERROR_MESSAGE+=" If this error doesn't occur on your local machine,"
ERROR_MESSAGE+=' make sure your packages are up-to-date by running `pnpm install`.'
Expand Down
6 changes: 1 addition & 5 deletions .lintstagedrc.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
export default {
'!(docs/**/*)*.{ts,js,html,md,mts}': [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds like biome doesn't yet support HTML and MD files:

https://biomejs.dev/internals/language-support

'eslint --cache --cache-strategy content --fix',
// don't cache prettier yet, since we use `prettier-plugin-jsdoc`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably remove prettier-plugin-jsdoc, if prettier will no longer be used for linting JS code.

// and prettier doesn't invalidate cache on plugin updates"
// https://prettier.io/docs/en/cli.html#--cache
'prettier --write',
'biome check --no-errors-on-unmatched --files-ignore-unknown=true --write',
],
'.cspell/*.txt': ['tsx scripts/fixCSpell.ts'],
'**/*.jison': ['pnpm -w run lint:jison'],
Expand Down
18 changes: 0 additions & 18 deletions .prettierignore

This file was deleted.

8 changes: 0 additions & 8 deletions .prettierrc.json

This file was deleted.

4 changes: 2 additions & 2 deletions .vite/build.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { build, InlineConfig, type PluginOption } from 'vite';
import { build, type InlineConfig, type PluginOption } from 'vite';
import { resolve } from 'path';
import { fileURLToPath } from 'url';
import jisonPlugin from './jisonPlugin.js';
Expand Down Expand Up @@ -48,7 +48,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
const external: (string | RegExp)[] = ['require', 'fs', 'path'];
console.log(entryName, packageOptions[entryName]);
const { name, file, packageName } = packageOptions[entryName];
let output: OutputOptions = [
const output: OutputOptions = [
{
name,
format: 'esm',
Expand Down
2 changes: 1 addition & 1 deletion .vite/jsonSchemaPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PluginOption } from 'vite';
import type { PluginOption } from 'vite';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';

/**
Expand Down
229 changes: 229 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.2/schema.json",
"files": {
"ignore": [
"**/contributor-names.json",
"**/generated/",
"**/knsv*.html",
"**/local*.html",
"**/stats/",
"**/user-avatars/*",
"./.vscode/**",
"cypress/platform/current.html",
"cypress/platform/experimental.html",
"cypress/platform/xss3.html",
"cypress/screenshots/",
"cypress/snapshots/",
"demos/dev/**",
"packages/mermaid/src/config.type.ts"
]
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 100,
"attributePosition": "auto"
},
"organizeImports": { "enabled": false },
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"complexity": {
"noBannedTypes": "error",
"noExtraBooleanCast": "error",
"noMultipleSpacesInRegularExpressionLiterals": "error",
"noUselessCatch": "error",
"noUselessThisAlias": "error",
"noUselessTypeConstraint": "error",
"noWith": "error",
"useFlatMap": "error"
},
"correctness": {
"noConstAssign": "error",
"noConstantCondition": "error",
"noEmptyCharacterClassInRegex": "error",
"noEmptyPattern": "error",
"noGlobalObjectCalls": "error",
"noInnerDeclarations": "error",
"noInvalidConstructorSuper": "error",
"noNewSymbol": "error",
"noNonoctalDecimalEscape": "error",
"noPrecisionLoss": "error",
"noSelfAssign": "error",
"noSetterReturn": "error",
"noSwitchDeclarations": "error",
"noUndeclaredVariables": "error",
"noUnreachable": "error",
"noUnreachableSuper": "error",
"noUnsafeFinally": "error",
"noUnsafeOptionalChaining": "error",
"noUnusedLabels": "error",
"noUnusedVariables": "off",
"useArrayLiterals": "off",
"useIsNan": "error",
"useValidForDirection": "error",
"useYield": "error"
},
"style": {
"noNamespace": "error",
"useAsConstAssertion": "error",
"useBlockStatements": "error",
"useForOf": "error",
"useImportType": "error",
"useNamingConvention": {
"level": "off",
"options": { "strictCase": false }
}
},
"suspicious": {
"noAssignInExpressions": "warn",
"noAsyncPromiseExecutor": "error",
"noCatchAssign": "error",
"noClassAssign": "error",
"noCompareNegZero": "error",
"noConsoleLog": "off",
"noControlCharactersInRegex": "error",
"noDebugger": "error",
"noDuplicateCase": "error",
"noDuplicateClassMembers": "error",
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"noEmptyBlockStatements": "off",
"noExplicitAny": "off",
"noExtraNonNullAssertion": "error",
"noFallthroughSwitchClause": "error",
"noFunctionAssign": "error",
"noGlobalAssign": "error",
"noImportAssign": "error",
"noMisleadingCharacterClass": "error",
"noMisleadingInstantiator": "error",
"noPrototypeBuiltins": "off",
"noRedeclare": "error",
"noShadowRestrictedNames": "error",
"noUnsafeDeclarationMerging": "error",
"noUnsafeNegation": "error",
"useGetterReturn": "error",
"useIsArray": "error",
"useValidTypeof": "error"
}
}
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "es5",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"quoteStyle": "single",
"attributePosition": "auto"
},
"globals": [
"it",
"describe",
"beforeEach",
"beforeAll",
"afterEach",
"cy",
"expect",
"context",
"Cypress"
]
},
"overrides": [
{
"include": ["cypress/**", "demos/**", "**/scripts"],
"linter": { "rules": { "suspicious": { "noConsoleLog": "off" } } }
},
{ "include": ["*.{js,jsx,mjs,cjs}"], "linter": { "rules": {} } },
{ "include": ["*.{ts,tsx}"], "linter": { "rules": {} } },
{
"include": ["*.spec.{ts,js}", "cypress/**", "demos/**", "**/docs/**"],
"linter": {
"rules": {
"correctness": { "noUnusedVariables": "off" },
"style": {
"useNamingConvention": "off"
}
}
}
},
{
"include": ["*.spec.{ts,js}", "tests/**", "cypress/**/*.js"],
"linter": {
"rules": {
"style": {
"useNamingConvention": "off"
}
}
}
},
{
"include": ["*.html", "*.md", "**/*.md/*"],
"linter": {
"rules": {
"correctness": {
"noUndeclaredVariables": "off",
"noUnusedVariables": "off"
},
"style": { "noVar": "error" }
}
}
},
{ "include": ["*.md"] },
{
"include": ["**/*.md/**"],
"linter": {
"rules": {
"correctness": {
"noUndeclaredVariables": "off",
"noUnusedVariables": "off"
}
}
}
},
{
"include": ["*.ts", "*.tsx", "*.mts", "*.cts"],
"linter": {
"rules": {
"correctness": {
"noConstAssign": "off",
"noGlobalObjectCalls": "off",
"noInvalidConstructorSuper": "off",
"noNewSymbol": "off",
"noSetterReturn": "off",
"noUndeclaredVariables": "off",
"noUnreachable": "off",
"noUnreachableSuper": "off"
},
"style": {
"noArguments": "error",
"noVar": "error",
"useConst": "error"
},
"suspicious": {
"noDuplicateClassMembers": "off",
"noDuplicateObjectKeys": "off",
"noDuplicateParameters": "off",
"noFunctionAssign": "off",
"noImportAssign": "off",
"noRedeclare": "off",
"noUnsafeNegation": "off",
"useGetterReturn": "off"
}
}
}
}
],
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
}
}
18 changes: 7 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
"dev:vite": "tsx .vite/server.ts",
"dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev:vite",
"release": "pnpm build",
"lint": "cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content . && pnpm lint:jison && prettier --cache --check .",
"lint:fix": "cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content --fix . && prettier --write . && tsx scripts/fixCSpell.ts",
"lint": "pnpm biome check && pnpm lint:jison",
"lint:fix": "pnpm biome check --write",
"lint:ci": "pnpm lint && cross-env NODE_OPTIONS=--max_old_space_size=16384 eslint --cache --cache-strategy content .",
Comment on lines +28 to +30
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of making the CI linting different from local linting. It also means people will have to manually fix ESLint issues/CSpell issues.

Having git commit be fast is nice, but if I'm running pnpm run lint, it's usually because I want to check if something is going to pass CI or not.

Would it be better to make a lint:fast or lint:slow script?

Suggested change
"lint": "pnpm biome check && pnpm lint:jison",
"lint:fix": "pnpm biome check --write",
"lint:ci": "pnpm lint && cross-env NODE_OPTIONS=--max_old_space_size=16384 eslint --cache --cache-strategy content .",
"lint:fast": "pnpm biome check && pnpm lint:jison",
"lint:fast:fix": "pnpm biome check --write",
"lint": "pnpm lint:fast && cross-env NODE_OPTIONS=--max_old_space_size=16384 eslint --cache --cache-strategy content .",
"lint:fix": "pnpm lint:fast:fix && cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content --fix . && tsx scripts/fixCSpell.ts",

If pnpm lint skips running eslint by default, I'd recommend adding something like: `echo 'Skipping slow eslint-ing, run 'pnpm lint:slow' if you want to test this'.


Whichever option you pick, please update all mentions of lint:fix, e.g. in like:

mermaid/run

Lines 80 to 81 in 4a7489a

$(bold ./$name pnpm -w run lint:fix)
Run prettier and ES lint

and

ERROR_MESSAGE+=' Running `pnpm -w run lint:fix` may fix this issue. '
ERROR_MESSAGE+=" If this error doesn't occur on your local machine,"
ERROR_MESSAGE+=' make sure your packages are up-to-date by running `pnpm install`.'
ERROR_MESSAGE+=' You may also need to delete your prettier cache by running'
ERROR_MESSAGE+=' `rm ./node_modules/.cache/prettier/.prettier-cache`.'

"lint:jison": "tsx ./scripts/jison/lint.mts",
"contributors": "tsx scripts/updateContributors.ts",
"cypress": "cypress run",
Expand All @@ -51,18 +52,13 @@
"author": "Knut Sveidqvist",
"license": "MIT",
"standard": {
"ignore": [
"**/parser/*.js",
"dist/**/*.js",
"cypress/**/*.js"
],
"globals": [
"page"
]
"ignore": ["**/parser/*.js", "dist/**/*.js", "cypress/**/*.js"],
"globals": ["page"]
},
"devDependencies": {
"@applitools/eyes-cypress": "^3.42.3",
"@argos-ci/cypress": "^2.0.5",
"@biomejs/biome": "1.8.2",
"@cspell/eslint-plugin": "^8.6.0",
"@cypress/code-coverage": "^3.12.30",
"@rollup/plugin-typescript": "^11.1.6",
Expand Down Expand Up @@ -90,7 +86,7 @@
"cypress-image-snapshot": "^4.0.1",
"esbuild": "^0.20.2",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-biome": "^1.7.3",
"eslint-plugin-cypress": "^2.15.1",
"eslint-plugin-html": "^8.0.0",
"eslint-plugin-jest": "^27.9.0",
Expand Down
Loading
Loading