Ctrl K
ComunidadGuías…

oxlint.config.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { defineConfig } from 'oxlint'
import core from 'ultracite/oxlint/core'
import react from 'ultracite/oxlint/react'
import tanstack from 'ultracite/oxlint/tanstack'

// @ts-expect-error extension
import { ignorePatterns } from './oxc.ignore.ts'

const callSiteClasses = [
  'layout',
  'motion',
  'opacity',
  'truncate',
  'focus-ring',
  'no-scrollbar',
  'scroll-fade',
  'scroll-fade-x',
  'table-scroller',
]

export default defineConfig({
  extends: [core, react, tanstack],
  ignorePatterns: [...(core.ignorePatterns || []), ...ignorePatterns],
  jsPlugins: ['oxlint-tailwindcss', '@shadcn/lint'],
  overrides: [
    {
      files: ['apps/app/src/core/{queries,runtime}/**'],
      // Kysely's case builder spells its branches .then(); no promise involved.
      rules: { 'promise/prefer-await-to-then': 'off' },
    },
    {
      files: ['apps/desktop/src/main/**'],
      // No window here: utility-process and MessagePortMain ports take no target origin.
      rules: { 'unicorn/require-post-message-target-origin': 'off' },
    },
    {
      files: ['packages/ui/src/components/**'],
      rules: {
        'shadcn/no-arbitrary-values': 'off',
        'shadcn/no-restyle': 'off',
        'shadcn/require-static-classes': 'off',
      },
    },
    {
      files: ['packages/ui/src/components/{brand,icons}/**'],
      // Logos keep their own artwork colors.
      rules: { 'shadcn/no-raw-colors': 'off' },
    },
  ],
  rules: {
    // react-compiler memoizes context values; manual useMemo is redundant here.
    'react/jsx-no-constructed-context-values': 'off',

    'shadcn/no-arbitrary-values': [
      'error',
      { allow: ['layout', 'motion', 'stroke-[1.5]'] },
    ],
    'shadcn/no-inline-styles': [
      'error',
      {
        contracts: [
          // Motion drives these through MotionValues; a class cannot.
          {
            allow: ['opacity', 'rotateX', 'scale', 'translateY'],
            pattern: '^motion\\.',
          },
        ],
      },
    ],
    'shadcn/no-raw-colors': ['error', { allow: ['fill-none'] }],
    'shadcn/no-restyle': [
      'error',
      {
        allow: callSiteClasses,
        contracts: [
          { allow: [...callSiteClasses, 'shape'], pattern: '^Skeleton$' },
          { allow: [...callSiteClasses, 'color'], pattern: '^Spinner$' },
          {
            allow: [...callSiteClasses, 'color', 'typography'],
            pattern: '^(NumberFlow|ElapsedSeconds)$',
          },
          {
            allow: [...callSiteClasses, 'spacing'],
            pattern:
              '^(InputGroupTextarea|MessageScrollerContent|MessageScrollerViewport|ResizableGroup|SidebarContent|SidebarMenu)$',
          },
          { allow: [...callSiteClasses, 'divide-y'], pattern: '^Form$' },
          {
            allow: [
              ...callSiteClasses,
              'color',
              'shape',
              'spacing',
              'typography',
            ],
            pattern:
              '^(CommandPrimitive|DropdownMenuTrigger$|ScrollArea$|TooltipTrigger$)',
          },
          // AppContextMenu wraps a complete content element in ContextMenuTrigger, a passthrough that owns no surface, so the element keeps its own effects too.
          {
            allow: [
              ...callSiteClasses,
              'color',
              'effects',
              'shape',
              'spacing',
              'typography',
            ],
            pattern: '^ContextMenuTrigger$',
          },
        ],
      },
    ],
    'shadcn/no-unknown-classes': 'error',
    'shadcn/require-static-classes': 'error',

    'tailwindcss/consistent-variant-order': 'error',
    'tailwindcss/enforce-canonical': 'error',
    'tailwindcss/enforce-consistent-important-position': 'error',
    'tailwindcss/enforce-consistent-line-wrapping': 'off',

    // oxfmt sortTailwindcss is the source of truth; this plugin's order disagrees.
    'tailwindcss/enforce-sort-order': 'off',

    'tailwindcss/no-conflicting-classes': 'error',
    'tailwindcss/no-deprecated-classes': 'error',
    'tailwindcss/no-duplicate-classes': 'error',
    'tailwindcss/no-unknown-classes': [
      'error',
      {
        allowlist: [
          'toaster',
          'typography',
          'typography-disabled',
          'bg-fd-secondary',
          'text-fd-secondary-foreground',
          'text-fd-muted-foreground',
          'fd-scroll-container',
          'placeholder:text-fd-muted-foreground',
          'text-fd-primary',
          'text-fd-error',
          'bg-fd-overlay',
          'animate-fd-fade-in',
          'animate-fd-fade-out',
          'bg-fd-card',
          'text-fd-card-foreground',
          'animate-fd-dialog-in',
          'animate-fd-dialog-out',
          'text-fd-muted-foreground/80',
          'focus-visible:ring-fd-ring',
        ],
      },
    ],
    'tailwindcss/no-unnecessary-arbitrary-value': 'error',
  },
  settings: {
    'react-hooks': { additionalEffectHooks: '(useMountedEffect)' },
    shadcn: {
      ignoreImports: '^@tamery/ui/components/(brand|icons)/',
      ui: '@tamery/ui/components',
    },
    tailwindcss: { entryPoint: 'packages/ui/src/styles/globals.css' },
  },
})