npm.io
1.1.2 • Published 1 month ago

@skagerakenergi/biome-config

Licence
ISC
Version
1.1.2
Deps
0
Size
16 kB
Vulns
0
Weekly
0

@skagerakenergi/biome-config

npm version GitHub license

Shared Biome configuration for Skagerak Energi projects. Covers formatting, TypeScript/Vue linting, and HTML accessibility rules — including Vue <template> a11y via a dedicated second-pass config.


Installation

npm install --save-dev @skagerakenergi/biome-config @biomejs/biome
# or
pnpm add -D @skagerakenergi/biome-config @biomejs/biome

Quick Start

1. biome.json — formatting + standard linting
{
  "$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
  "extends": ["@skagerakenergi/biome-config/biome.json"]
}
2. biome.a11y.json — Vue template accessibility (second pass)

Create a second config file at your project root:

{
  "$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
  "extends": ["./biome.json"],
  "html": {
    "experimentalFullSupportEnabled": true
  },
  "formatter": {
    "enabled": false
  }
}

Why two files? Biome's experimentalFullSupportEnabled unlocks a11y linting of Vue <template> blocks but breaks biome format for Vue files (closed upstream as not planned). Keeping it in a formatter-off second config gives you both features safely until this is fixed upstream


{
  "scripts": {
    "format":    "biome format --write .",
    "lint":      "biome check .",
    "lint:fix":  "biome check --write .",
    "lint:a11y": "biome lint --config-path biome.a11y.json .",
    "check":     "biome check . && biome lint --config-path biome.a11y.json .",
    "check:fix": "biome check --write . && biome lint --config-path biome.a11y.json ."
  }
}
Script What it does
format Formats all files (Vue indentScriptAndStyle, quote style, etc.)
lint Checks for lint errors and formatter drift; does not write anything
lint:fix biome check --write: applies formatter and safe lint fixes in one pass
lint:a11y Lints Vue <template> a11y; does not reformat
check Both passes — full coverage, no writes
check:fix Both passes — formats + applies safe lint fixes

--write vs --fix: They are synonyms in Biome. This config uses --write throughout (the canonical modern form) to avoid ambiguity. biome check --write applies both the formatter and safe lint fixes in a single pass; it is equivalent to running biome format --write and biome lint --write together.

Why check:fix instead of format + lint:fix?

The two passes are designed to be safe in any order and will never undo each other:

  • Pass 1 (biome check --write) formats and fixes script-level issues.
    It is blind to Vue template a11y (no experimentalFullSupportEnabled).
  • Pass 2 (biome lint --config-path biome.a11y.json) detects template a11y violations.
    It cannot reformat because formatter.enabled is false.

CI Setup

Run both passes as separate steps:

# GitHub Actions example
- name: Format & lint
  run: biome check .

- name: Vue template a11y
  run: biome lint --config-path biome.a11y.json .

Or combine them in one step:

- name: Full check
  run: pnpm check

What's Included

Formatter
  • 2-space indent, LF line endings, 100-char line width
  • Single quotes, no semicolons (ASI), trailing commas off
  • indentScriptAndStyle: true for Vue/HTML files
  • selfCloseVoidElements: always
  • Respects .editorconfig
Linter rules
Category Rules
a11y All 15 Biome 2.4 accessibility rules (applied to .html; Vue templates via biome.a11y.json)
suspicious noVar, noExplicitAny, noExtraNonNullAssertion, noNonNullAssertedOptionalChain, noUnsafeDeclarationMerging, noMisleadingInstantiator, useNamespaceKeyword
style noCommonJs, noNamespace, useArrayLiterals, useAsConstAssertion, useConst
complexity noArguments, noUselessTypeConstraint
correctness noUnusedVariables, noVueDuplicateKeys, noVueReservedKeys, noVueReservedProps
Vue / TypeScript overrides
  • noUnusedVariables and noUnusedImports are off for .vue files (template references aren't visible to the script-only parser).
  • useConst and useImportType are off for .vue / .svelte / .astro files.
  • JS files (.js, .cjs, .mjs) use semicolons: always.
Ignored paths (hardcoded via files.includes)

**/node_modules, **/dist, **/dist-ssr, **/.quasar, **/.nuxt, **/.next, **/.output, **/build, **/coverage, **/.vitepress/cache, **/.vitepress/dist

These live in files.includes so they apply to every tool (formatter, linter, assist) without per-tool repetition. Consumers can extend the list by adding exclusions to their own files.includes.

VCS integration

vcs.useIgnoreFile: true — your .gitignore is automatically respected on top of the hardcoded ignores.


Known Upstream Biome Bugs

These are confirmed issues in Biome itself that affect this config. Workarounds are documented below.

1. --config-path resets VCS root resolution

When you run biome lint --config-path biome.a11y.json, Biome resolves the VCS root relative to the config file path rather than the working directory. This means vcs.useIgnoreFile: true in the shared config may not respect your .gitignore, and directories like dist/ can be scanned even though they are excluded by files.includes in the main config.

Workaround: Ensure your project root contains a .gitignore that also excludes build artefacts, or add them explicitly to your biome.a11y.json via files.includes. The hardcoded files.includes exclusions in this shared config are not affected (they resolve correctly via extends).

The root cause is that experimentalFullSupportEnabled is genuinely experimental — Biome's HTML/template support is still being stabilised and the flag re-initialises rule defaults without honouring the inherited recommended: false. Enabling it in biome.a11y.json causes Biome to activate its full recommended ruleset, overriding the linter.rules.recommended: false setting inherited from the shared config. Rules not explicitly configured here (e.g. noNonNullAssertion, useTemplate, useLiteralKeys) may fire unexpectedly.

Workaround: Explicitly disable any unwanted rules in your biome.a11y.json:

{
  "$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
  "extends": ["./biome.json"],
  "html": { "experimentalFullSupportEnabled": true },
  "formatter": { "enabled": false },
  "linter": {
    "rules": {
      "style": {
        "noNonNullAssertion": "off",
        "useTemplate": "off",
        "useLiteralKeys": "off"
      }
    }
  }
}

Custom Overrides

Add any project-specific rules after extends in your biome.json:

{
  "$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
  "extends": ["@skagerakenergi/biome-config/biome.json"],
  "linter": {
    "rules": {
      "style": {
        "useConst": "off"
      }
    }
  }
}

To add extra path exclusions, extend files.includes with only your exclusions — do not repeat **, as it is already provided by the shared config (repeating it triggers a noBiomeFirstException warning):

{
  "$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
  "extends": ["@skagerakenergi/biome-config/biome.json"],
  "files": {
    "includes": ["!**/generated/**", "!**/vendor/**"]
  }
}

To disable VCS integration:

{
  "$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
  "extends": ["@skagerakenergi/biome-config/biome.json"],
  "vcs": {
    "enabled": false
  }
}