WebComponent(spec) builds a custom-element base class from a spec: shadow root or declarative shadow DOM, template, shared stylesheet (adopted, or a <style> once per root for light DOM), reflected props with two-way attribute sync, a per-connection AbortSignal, host event wiring, and typed element refs. Types derive exact observedAttributes, prop value types, ref element types from selectors, and reject prop names that collide with the base class or mixin members. Tooling: strict tsconfig, type-aware oxlint, oxfmt, and Vitest browser mode (Chromium) with type tests.
57 lines
2.0 KiB
TypeScript
57 lines
2.0 KiB
TypeScript
import { defineConfig } from 'oxlint';
|
|
|
|
export default defineConfig({
|
|
plugins: ['typescript', 'unicorn', 'oxc', 'import', 'promise'],
|
|
categories: {
|
|
correctness: 'error',
|
|
suspicious: 'error',
|
|
pedantic: 'error',
|
|
perf: 'error',
|
|
restriction: 'error',
|
|
},
|
|
rules: {
|
|
// Guards for code compiled down to pre-ES2018/2020; this targets ESNext.
|
|
'oxc/no-optional-chaining': 'off',
|
|
'oxc/no-rest-spread-properties': 'off',
|
|
'oxc/no-async-await': 'off',
|
|
// `void promise;` is how `no-floating-promises` says to ignore one on purpose.
|
|
'eslint/no-void': ['error', { allowAsStatement: true }],
|
|
// `undefined` is a real prop value (`userId: number | undefined`).
|
|
'eslint/no-undefined': 'off',
|
|
// Members are public by default and private via `#`; `public` is noise.
|
|
'typescript/explicit-member-accessibility': 'off',
|
|
// DOM types can't be deeply readonly, so every `Element` parameter fails.
|
|
'typescript/prefer-readonly-parameter-types': 'off',
|
|
// `function foo()` over `const foo = () => ...`. Inline callbacks
|
|
// (`.map((x) => ...)`) and arrows that use `this` aren't affected.
|
|
'eslint/func-style': ['error', 'declaration'],
|
|
// The mixin's hooks are deliberately empty methods for subclasses to override.
|
|
'eslint/class-methods-use-this': [
|
|
'error',
|
|
{
|
|
exceptMethods: ['handleEvent', 'onConnect', 'onDisconnect', 'onPropChange'],
|
|
ignoreOverrideMethods: true,
|
|
},
|
|
],
|
|
},
|
|
overrides: [
|
|
{
|
|
files: ['test/**/*.ts'],
|
|
plugins: ['typescript', 'unicorn', 'oxc', 'import', 'promise', 'vitest'],
|
|
rules: {
|
|
// Tests import the source under test from `../src`.
|
|
'import/no-relative-parent-imports': 'off',
|
|
// `describe` callbacks are long, and each test of a class factory
|
|
// needs its own small class.
|
|
'eslint/max-lines-per-function': 'off',
|
|
'eslint/max-classes-per-file': 'off',
|
|
},
|
|
},
|
|
],
|
|
env: {
|
|
builtin: true,
|
|
browser: true,
|
|
},
|
|
ignorePatterns: ['dist/'],
|
|
});
|