Skip to content

fix(eslint-plugin): check styleOrder only where the build reads it - #733

Open
owjs3901 wants to merge 2 commits into
mainfrom
fix/eslint-autofix-scope
Open

owjs3901 wants to merge 2 commits into
mainfrom
fix/eslint-autofix-scope

Conversation

@owjs3901

@owjs3901 owjs3901 commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Refs #684 (TOOL-01, TOOL-02, KNOWN-14 필수 항목)

main 기준 단독 PR입니다. 먼저 병합되어야 할 PR은 없습니다. Rust 1.99 clippy 수정(테스트 단언 형식)이 함께 들어 있습니다.

요약

  • 조사 결과 TOOL-01 / TOOL-02 / KNOWN-14는 main에 이미 들어간 fix(eslint-plugin): check only the values the build reads as styles #697(공유 스타일 위치 분류기 style-position.ts)로 해결되어 있었습니다. 설문 픽스처(unrelated-arrays.jsx, unrelated-properties.jsx, known14.jsx)와 추가 케이스 20여 개를 실제 ESLint verifyAndFix로 다시 돌려 확인했습니다.
  • 같은 문제가 남아 있던 style-order-range를 같은 원칙으로 고쳤습니다. 빌드가 styleOrder를 읽는 곳(컴포넌트의 prop, css/globalCss/keyframes에 넘긴 스타일 객체의 최상위 키)에서만 검사합니다.
  • ImportStorage.checkContextType가 name in imports로 판정해 toString(), constructor() 같은 Object.prototype 이름 호출도 스타일 유틸로 취급하던 버그를 고쳤습니다.

동작

  • 전: <Box icon={<div styleOrder={0} />} />, css({ _hover: { styleOrder: 0 } }), 중첩 css() 호출을 감싼 객체 등에서 오탐이 났고, 중첩 호출이 끝나면 바깥 컨텍스트가 지워져 바깥 styleOrder를 놓쳤습니다.
  • 후: 스타일 객체의 최상위 styleOrder와 컴포넌트 prop만 검사합니다. css(base, { styleOrder: 300 })처럼 여러 인자 중 객체 인자도 검사합니다(빌드가 읽는 형태).
  • 배열/typography/media 규칙: 비스타일 데이터(data-*, aria-*, 핸들러, props, styleVars, 다른 함수 인자, imports/fontFaces/params)는 보고도 수정도 하지 않고, 스타일 데이터는 계속 수정됩니다(회귀 테스트 기존 포함).
  • KNOWN-14: 함수 안의 const fade = keyframes(...) / css(...) 결과를 css-utils-literal-only가 정적으로 인정합니다(블록, 화살표 함수, 클래스 메서드, 네임스페이스 import 확인).

새로 생기는 오류

없음. 빌드 오류는 추가되지 않았고 lint 진단만 줄었습니다(오탐 제거).

남는 한계

  • styled(...) 인자와 Emotion/styled-components/StyleX 별칭의 배열 규칙 적용은 아직 없습니다(보고만 하지 않음 = 안전한 쪽). TOOL-03/TOOL-04 범위입니다.
  • 변수에 담은 스타일 객체(const s = { w: [1, 1] }; css(s))는 검사하지 않습니다(놓치는 쪽, 수정하지 않음).

검증

  • bun test: 5479 pass / 0 fail, 커버리지 100%. bun lint: 오류 0, 기존 경고 2개.
  • cargo fmt, cargo +1.99 clippy --workspace --all-targets -D warnings 통과, cargo test --workspace 통과.
  • 새 RuleTester 케이스: 중첩 데이터/요소 prop/props의 styleOrder, 계산된 키, 다른 호출, toString()/new Foo()는 무시, 여러 인자 css(base, {...})와 중첩 css()의 바깥 키는 보고.
  • 실제 ESLint 실행(설문 픽스처): data-config={{ values: [1, 1] }}, { typography: '$heading' }, { '@media print': ... }은 변경 없음, <Box w={[1, 1]} typography="$heading" />은 w={1} typography="heading"로 수정.

Refs #684

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@codecov

codecov Bot commented Oct 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
bindings/devup-ui-wasm/src/lib.rs 100.00% <ø> (ø)
libs/css/src/theme_tokens.rs 100.00% <ø> (ø)
libs/extractor/src/lib.rs 100.00% <ø> (ø)
libs/extractor/src/tailwind.rs 100.00% <100.00%> (ø)
...eslint-plugin/src/rules/style-order-range/index.ts 100.00% <100.00%> (ø)
packages/eslint-plugin/src/utils/import-storage.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Refs #684

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Changepacks

@devup-ui/wasm@1.0.82 → 1.0.83 - bindings/devup-ui-wasm/package.json

Patch

  • style-order-range only checks styleOrder where the build reads it: a prop of a Devup UI component and a top-level key of a style object passed to css/globalCss/keyframes. A styleOrder key in nested data, in a prop value such as an element passed as a prop, or in a call of a function sharing a name with an Object.prototype member is no longer reported. The array, typography and media rules already skip non-style data, and css-utils-literal-only accepts a css()/keyframes() result held in a const inside a function. No new build errors.
  • globalCss: theme tokens ($text) resolve to var(--text) in global rules instead of being written as invalid $text; imports given as { url, query } objects with unquoted keys are emitted instead of dropped; an '@layer name' key puts the rules it holds in that cascade layer (layers nest as base.reset) instead of flattening them into invalid declarations, and a layer name that is not one identifier is a build error
  • Theme CSS: a color only one variant defines is defined in that variant; a variant renders dark only when it is named dark or listed as dark in the new theme.colorScheme, others light, and light-dark() only encodes a light default with one dark variant; theme names that are not CSS identifiers are quoted in [data-theme]; typography emits fontStyle and textTransform; color variables come out in a fixed order. $tokens with dashes (text-primary) resolve instead of breaking into var(--text)-primary, and dotted length and shadow names are declared with dashes like their references. registerTheme reports, with the theme path, a token name the $token syntax cannot reach and two tokens of a variant that become the same CSS variable (a-b and a.b)

@devup-ui/bun-plugin@1.0.21 → 1.0.22 - packages/bun-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/plugin-utils' via a local workspace dependency

@devup-ui/components@0.1.59 → 0.1.60 - packages/components/package.json

Patch

  • Auto-update: depends on '@devup-ui/vite-plugin' via a local workspace dependency

@devup-ui/eslint-plugin@1.0.21 → 1.0.22 - packages/eslint-plugin/package.json

Patch

  • style-order-range only checks styleOrder where the build reads it: a prop of a Devup UI component and a top-level key of a style object passed to css/globalCss/keyframes. A styleOrder key in nested data, in a prop value such as an element passed as a prop, or in a call of a function sharing a name with an Object.prototype member is no longer reported. The array, typography and media rules already skip non-style data, and css-utils-literal-only accepts a css()/keyframes() result held in a const inside a function. No new build errors.
  • no-duplicate-value, no-useless-responsive, no-useless-tailing-nulls, no-typography-token-prefix and prefer-media-shorthand only report and fix values the build reads as styles: style props of Box, Flex and the other style components and the arguments of css, globalCss and keyframes, through style objects, responsive arrays, conditions and spreads. Arrays and keys in props the component passes through (data-, aria-, event handlers, HTML attributes, props, styleVars), in arguments of other functions and under imports/fontFaces/params are left alone, where autofix used to rewrite them; styles of a component nested in another's prop are checked too. css-utils-literal-only reads a css() or keyframes() result held in a const of any scope as static, as the build does

@devup-ui/next-plugin@1.0.89 → 1.0.90 - packages/next-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/plugin-utils' via a local workspace dependency

@devup-ui/plugin-utils@1.0.16 → 1.0.17 - packages/plugin-utils/package.json

Patch

  • Theme CSS: a color only one variant defines is defined in that variant; a variant renders dark only when it is named dark or listed as dark in the new theme.colorScheme, others light, and light-dark() only encodes a light default with one dark variant; theme names that are not CSS identifiers are quoted in [data-theme]; typography emits fontStyle and textTransform; color variables come out in a fixed order. $tokens with dashes (text-primary) resolve instead of breaking into var(--text)-primary, and dotted length and shadow names are declared with dashes like their references. registerTheme reports, with the theme path, a token name the $token syntax cannot reach and two tokens of a variant that become the same CSS variable (a-b and a.b)

@devup-ui/rsbuild-plugin@1.0.66 → 1.0.67 - packages/rsbuild-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/plugin-utils' via a local workspace dependency

@devup-ui/vite-plugin@1.0.72 → 1.0.73 - packages/vite-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/plugin-utils' via a local workspace dependency

@devup-ui/webpack-plugin@1.0.70 → 1.0.71 - packages/webpack-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/plugin-utils' via a local workspace dependency

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant