Repository navigation
feat: RSS-CORE-00 swagger editor - #16
Conversation
- Added @uiw/react-codemirror with JSON/YAML support - Created reusable CodeEditor in shared/ui with readonly and transparent props - Applied custom dark theme and syntax highlighting via SCSS and JS - Integrated CodeEditor into SwaggerEditor widget
- Create format-converter feature to detect and convert between JSON and YAML - Implement FormatToggle UI component with unknown state handling - Integrate format converter logic and toggle into SwaggerEditor widget - Add i18n support for the format converter UI
- Integrate `@stoplight/spectral-core` to parse and validate OpenAPI schemas in both JSON and YAML formats. - Add `CodeMirror Linter` adapter to display validation errors directly in the editor with inline tooltips. - Customize the Spectral `oas` ruleset to ignore annoying stylistic rules and focus only on structural errors. - Add comprehensive unit tests for the schema validation utility.
- Implemented `ValidationStatus` and `ValidationFeedback` UI components to visualize schema validity and error counts. - Added `next-intl` localization support for all new validation UI elements. - Integrated CodeMirror's `onUpdate` listener to efficiently extract real-time lint diagnostics without causing redundant validation runs. - Created a responsive split-view layout for the `HomePage` using Flexbox and aspect-ratio media queries. - Assembled the main page by integrating the `SwaggerEditor` into the primary pane and adding a placeholder stub for the `SwaggerViewer`.
- Refactor SwaggerEditor to operate as a fully controlled component by removing its internal local state. - Implement a custom useDebounce hook to optimize performance during user input. - Lift state management up to the HomePage to track raw text and validation status.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
||
| return ( | ||
| <html lang={locale} className={`${ibmPlexSans.variable} ${spaceGrotesk.variable}`}> | ||
| <html lang={locale} className={`${ibmPlexSans.variable} ${spaceGrotesk.variable} ${jetBrainsMono.variable}`}> |
There was a problem hiding this comment.
can we use lib for styles like classname here?
| import yaml from 'yaml'; | ||
|
|
||
| export function detectFormat(text: string): DetectedFormat { | ||
| if (!text.trim()) return 'unknown'; |
There was a problem hiding this comment.
it's not a good idea use 'unknown' as a returned value. use null or at least add 'unknown' to constants
|
|
||
| return ( | ||
| <div className={styles.wrapper}> | ||
| <Badge className={styles.badge} color={isUnknown ? 'red' : 'gray'}> |
There was a problem hiding this comment.
better use "success" | "error" | "default" | "active"
for example. just because it adds some description to value and allow you to change colors easily
but now you can leave it like it is
|
|
||
| <Button className={styles.button} variant="tertiary" type="button" onClick={onClick} disabled={isUnknown}> | ||
| <ConvertIcon className={styles.convertIcon} />{' '} | ||
| {isUnknown ? t('cannot_convert') : t('convert_to', { format: oppositeFormat.toUpperCase() })} |
There was a problem hiding this comment.
it's ok, but you also can wrap oppositeFormat with span and add a text transform style
| return { | ||
| from: from, | ||
| to: to, | ||
| severity: severity, | ||
| message: issue.message, | ||
| }; | ||
| }); |
There was a problem hiding this comment.
| return { | |
| from: from, | |
| to: to, | |
| severity: severity, | |
| message: issue.message, | |
| }; | |
| }); | |
| return { | |
| from, | |
| to, | |
| severity, | |
| message: issue.message, | |
| }; | |
| }); |
| try { | ||
| const parsed = yaml.parse(debouncedText) as unknown; | ||
| if (typeof parsed === 'object' && parsed !== null) { | ||
| return parsed as Record<string, unknown>; | ||
| } | ||
| } catch { | ||
| // ignore this | ||
| } |
There was a problem hiding this comment.
i saw this before. let's optimize it
| return null; | ||
| }, [debouncedText, isSchemaValid]); | ||
|
|
||
| console.log(parsedSchema); // ? For the time being, as there is no Swagger Viewer |
There was a problem hiding this comment.
| console.log(parsedSchema); // ? For the time being, as there is no Swagger Viewer | |
| console.log(parsedSchema); // TODO: Remove after add Swagger Viewer (<TICKET_FOR_IT>) |
| syntaxTheme, | ||
| EditorState.readOnly.of(readonly), | ||
| ]; | ||
| const extensions = [props.extensions || [], ...baseExtensions]; |
There was a problem hiding this comment.
maybe you want smth like this?
| const extensions = [props.extensions || [], ...baseExtensions]; | |
| const extensions = [...(props.extensions || []), ...baseExtensions]; |
and why props.extensions, not extensions?
| const handleEditorUpdate = useCallback((viewUpdate: ViewUpdate) => { | ||
| let errors = 0; | ||
| let warnings = 0; | ||
| forEachDiagnostic(viewUpdate.state, (diag) => { | ||
| if (diag.severity === 'error') errors++; | ||
| if (diag.severity === 'warning') warnings++; | ||
| }); | ||
|
|
||
| setValidation((prev) => { | ||
| if (prev.errors !== errors || prev.warnings !== warnings) { | ||
| return { errors, warnings }; | ||
| } | ||
| return prev; | ||
| }); | ||
| }, []); |
There was a problem hiding this comment.
| const handleEditorUpdate = useCallback((viewUpdate: ViewUpdate) => { | |
| let errors = 0; | |
| let warnings = 0; | |
| forEachDiagnostic(viewUpdate.state, (diag) => { | |
| if (diag.severity === 'error') errors++; | |
| if (diag.severity === 'warning') warnings++; | |
| }); | |
| setValidation((prev) => { | |
| if (prev.errors !== errors || prev.warnings !== warnings) { | |
| return { errors, warnings }; | |
| } | |
| return prev; | |
| }); | |
| }, []); | |
| const handleEditorUpdate = useCallback((viewUpdate: ViewUpdate) => { | |
| let errors = 0; | |
| let warnings = 0; | |
| forEachDiagnostic(viewUpdate.state, (diag) => { | |
| if (diag.severity === 'error') errors++; | |
| if (diag.severity === 'warning') warnings++; | |
| }); | |
| setErrorsCount(errors); | |
| setWarningsCount(warnings); | |
| }, []); |
|
@CodeRabbit review |
✅ Action performedReview finished.
|
📝 WalkthroughWalkthroughДобавлена новая функциональность Swagger Editor: детектирование и конвертация JSON/YAML, валидация OpenAPI-схем через Spectral, CodeMirror-редактор с подсветкой и линтером, UI-компоненты статуса/фидбэка, виджет SwaggerEditor и интеграция на домашней странице. Также переименованы default-экспорты страниц, обновлены конфигурация сборки, зависимости, локализация и глобальные стили. ChangesФункциональность Swagger Editor
Estimated code review effort: 3 (Moderate) | ~30 minutes Инфраструктура, конфигурация и стили
Estimated code review effort: 2 (Simple) | ~15 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant SwaggerEditor
participant CodeEditor
participant openapiLinter
participant validateSchema
participant FormatToggle
User->>CodeEditor: ввод текста
CodeEditor->>SwaggerEditor: onEditorUpdate(viewUpdate)
SwaggerEditor->>openapiLinter: анализ документа
openapiLinter->>validateSchema: validateSchema(text)
validateSchema-->>openapiLinter: диагностики (issues)
openapiLinter-->>SwaggerEditor: Diagnostic[]
SwaggerEditor->>SwaggerEditor: подсчёт errorsCount/warningsCount
SwaggerEditor-->>User: ValidationStatus/ValidationFeedback
User->>FormatToggle: клик "convert_to"
FormatToggle->>SwaggerEditor: onToggle(newFormat)
SwaggerEditor->>SwaggerEditor: convertFormat(value, newFormat)
SwaggerEditor-->>CodeEditor: onChange(convertedText)
Estimated code review effort: 3 (Moderate) | ~30 minutes Related issues: Не указаны в предоставленных данных. Related PRs: Не указаны в предоставленных данных. Suggested labels: feature, frontend, needs-review Suggested reviewers: Не указаны в предоставленных данных. 🐰 В норке кроликов кипит работа, 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (5)
package.json (1)
5-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueДублирование fallback-конфигурации fs/path/url с
next.config.ts.Поле
browserздесь иresolve.fallbackвnext.config.ts(Line 6-20) решают одну и ту же задачу — отключение подмешивания Node-модулейfs/path/urlв клиентскую сборку. Если оставить обе настройки, есть риск рассинхронизации при последующих правках одной из них без другой.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@package.json` around lines 5 - 9, Remove the duplicated browser fallback block from package.json and keep the Node module exclusions in a single place, since next.config.ts already handles the fs/path/url client-bundling fallback. Update the configuration so only one source of truth remains for disabling fs, path, and url, and make sure any references in the build setup stay aligned with the existing next.config.ts resolve.fallback settings.next.config.ts (1)
6-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winЗамените
unknown-каст на официальный тип Webpack-конфига.Приведение
configкunknown, а затем к самодельной форме{ resolve?: { fallback?: ... } }отключает проверку типов для остальной части конфига. Next.js предоставляет типизированный колбэк черезNextConfig['webpack'](или типConfigurationизwebpack), что безопаснее при дальнейшем расширении хука.♻️ Пример более типобезопасного варианта
- webpack: (config: unknown, { isServer }: { isServer: boolean }) => { - const webpackConfig = config as { resolve?: { fallback?: Record<string, boolean | string> } }; - if (!isServer) { - if (!webpackConfig.resolve) { - webpackConfig.resolve = {}; - } - webpackConfig.resolve.fallback = { - ...(webpackConfig.resolve.fallback || {}), + webpack: (config, { isServer }) => { + if (!isServer) { + config.resolve = config.resolve ?? {}; + config.resolve.fallback = { + ...(config.resolve.fallback ?? {}), fs: false, path: false, url: false, }; } - return webpackConfig; + return config; },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@next.config.ts` around lines 6 - 20, The webpack hook in next.config.ts is weakening type safety by casting config through unknown and a partial fallback shape. Update the NextConfig.webpack callback to use the official Next.js/webpack types (for example NextConfig['webpack'] or webpack Configuration) and remove the manual cast so the existing logic in webpackConfig.resolve.fallback stays type-checked while still preserving the fs, path, and url fallbacks.src/features/format-converter/lib/convert-format.ts (1)
4-22: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueДублирование логики парсинга/валидации.
convertToJsonиconvertToYamlдублируют одинаковый блокtry { yaml.parse → проверка типа }. Можно вынести общий helper для парсинга и валидации, чтобы избежать дублирования при добавлении новых форматов в будущем.♻️ Пример рефакторинга
+function parseStructured(text: string): Record<string, unknown> | unknown[] | null { + try { + const jsObject = yaml.parse(text) as unknown; + if (typeof jsObject !== 'object' || jsObject === null) return null; + return jsObject as Record<string, unknown> | unknown[]; + } catch { + return null; + } +} + export function convertToJson(text: string): string | null { - try { - const jsObject = yaml.parse(text) as unknown; - if (typeof jsObject !== 'object' || jsObject === null) return null; - return JSON.stringify(jsObject, null, 2); - } catch { - return null; - } + const jsObject = parseStructured(text); + return jsObject === null ? null : JSON.stringify(jsObject, null, 2); } export function convertToYaml(text: string): string | null { - try { - const jsObject = yaml.parse(text) as unknown; - if (typeof jsObject !== 'object' || jsObject === null) return null; - return yaml.stringify(jsObject); - } catch { - return null; - } + const jsObject = parseStructured(text); + return jsObject === null ? null : yaml.stringify(jsObject); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/features/format-converter/lib/convert-format.ts` around lines 4 - 22, Both convertToJson and convertToYaml duplicate the same yaml.parse plus object/null validation logic, so extract that shared parsing/validation into a common helper in convert-format.ts and have both functions reuse it. Keep the existing behavior and return values unchanged, but centralize the try/catch and object check so future format converters can call the same helper instead of repeating the block.src/widgets/swagger-editor/ui/swagger-editor.module.scss (1)
22-25: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueЗахардкоженный цвет вместо дизайн-токена.
.editorиспользуетrgba(0, 0, 0, 0.2)напрямую, тогда как остальные стили редактора (theme.ts,.toolbar) используют CSS-переменныеvar(--bg-surface-*). Стоит привести к единому подходу для консистентности темизации.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/widgets/swagger-editor/ui/swagger-editor.module.scss` around lines 22 - 25, The .editor rule is using a hardcoded rgba background instead of the shared theme token approach. Update the background-color in swagger-editor.module.scss to use the same CSS variable pattern as the related theme.ts and .toolbar styles, so SwaggerEditor stays consistent with the rest of the themed UI and locates through the .editor selector.src/widgets/swagger-editor/ui/swagger-editor.tsx (1)
40-44: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win
detectFormatвызывается на каждое нажатие клавиши без debounce.
onTextChangeпарсит весь текст документа (JSON.parse+yaml.parse) синхронно при каждом изменении редактора. Для больших OpenAPI-спецификаций это может заметно замедлять ввод, в отличие отopenapiLinter, у которого есть встроенный debounce. В кодовой базе уже есть хукuseDebounce, применяемый для аналогичной задачи (YAML-парсинг) на HomePage — стоит применить его и здесь.♻️ Пример применения debounce к определению формата
- const onTextChange = (newText: string) => { - const detected = detectFormat(newText); - setCurrentFormat(detected); - onChange?.(newText); - }; + const debouncedText = useDebounce(value, 300); + + useEffect(() => { + setCurrentFormat(detectFormat(debouncedText)); + }, [debouncedText]); + + const onTextChange = (newText: string) => { + onChange?.(newText); + };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/widgets/swagger-editor/ui/swagger-editor.tsx` around lines 40 - 44, The format detection in onTextChange is running synchronously on every keystroke and should be debounced to avoid blocking edits on large specs. Update swagger-editor.tsx so detectFormat is wrapped with the existing useDebounce pattern used elsewhere in the codebase (for example, the HomePage YAML parsing flow), and have onTextChange update currentFormat from the debounced result while still forwarding newText through onChange?. The key symbols to adjust are onTextChange, detectFormat, setCurrentFormat, and useDebounce.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/features/schema-validator/lib/validate-schema.ts`:
- Around line 6-26: The module-level Spectral instance in validateSchema is
shared across concurrent validateSchema() calls, which can cause race conditions
when setRuleset/run are used in parallel. Update validateSchema to create a
fresh Spectral instance and apply myRuleset per invocation, or otherwise
serialize access to the shared instance, so each run operates on its own
isolated configuration.
In
`@src/features/schema-validator/ui/validation-feedback/validation-feedback.module.scss`:
- Around line 1-9: Remove the empty blank line inside the .wrapper rule in
validation-feedback.module.scss so the declarations are contiguous and satisfy
stylelint’s declaration-empty-line-before rule; keep the styling in the same
.wrapper selector and eliminate the spacing before the display declaration.
In
`@src/features/schema-validator/ui/validation-status/validation-status.module.scss`:
- Around line 1-11: The .badge rule in validation-status.module.scss has an
empty line before the display declaration that violates stylelint’s
declaration-empty-line-before rule. Remove the blank line inside the .badge
block so the declarations stay contiguous, and keep the fix limited to the
.badge style block in validation-status.module.scss.
In `@src/shared/ui/arc-background/arc-background.module.scss`:
- Around line 22-65: The `.arc`, `.arc::before`, and `.arc::after` rules in
`arc-background.module.scss` contain extra blank lines before declarations that
violate `declaration-empty-line-before`. Remove the empty lines between the
related properties in these selectors, especially before `border`, `filter`, and
`box-shadow`, so the stylesheet matches the lint rule without changing the
visual styles.
In `@src/shared/ui/badge/badge.module.scss`:
- Around line 7-17: Remove the extra blank lines before the CSS declarations in
badge.module.scss so the block follows declaration-empty-line-before
consistently. Update the badge styles by keeping the declarations for
border-radius, font-family, and font-size contiguous with the surrounding
properties in the same rule.
In `@src/shared/ui/button/button.module.scss`:
- Around line 54-71: The .tertiary rule in button.module.scss has empty lines
before the border and padding declarations, which violates
declaration-empty-line-before. Remove the extra blank lines inside the .tertiary
block so the declarations are grouped consistently, keeping the existing styling
and hover rules unchanged.
In `@src/widgets/swagger-editor/ui/swagger-editor.module.scss`:
- Around line 9-20: In the .toolbar style block of swagger-editor.module.scss,
remove the duplicated display and align-items declarations and clean up the
extra blank line left by the merge artifact. Keep a single set of layout
properties in .toolbar, preserving the intended flex layout by leaving the final
justify-content and gap settings alongside one display and one align-items
declaration.
---
Nitpick comments:
In `@next.config.ts`:
- Around line 6-20: The webpack hook in next.config.ts is weakening type safety
by casting config through unknown and a partial fallback shape. Update the
NextConfig.webpack callback to use the official Next.js/webpack types (for
example NextConfig['webpack'] or webpack Configuration) and remove the manual
cast so the existing logic in webpackConfig.resolve.fallback stays type-checked
while still preserving the fs, path, and url fallbacks.
In `@package.json`:
- Around line 5-9: Remove the duplicated browser fallback block from
package.json and keep the Node module exclusions in a single place, since
next.config.ts already handles the fs/path/url client-bundling fallback. Update
the configuration so only one source of truth remains for disabling fs, path,
and url, and make sure any references in the build setup stay aligned with the
existing next.config.ts resolve.fallback settings.
In `@src/features/format-converter/lib/convert-format.ts`:
- Around line 4-22: Both convertToJson and convertToYaml duplicate the same
yaml.parse plus object/null validation logic, so extract that shared
parsing/validation into a common helper in convert-format.ts and have both
functions reuse it. Keep the existing behavior and return values unchanged, but
centralize the try/catch and object check so future format converters can call
the same helper instead of repeating the block.
In `@src/widgets/swagger-editor/ui/swagger-editor.module.scss`:
- Around line 22-25: The .editor rule is using a hardcoded rgba background
instead of the shared theme token approach. Update the background-color in
swagger-editor.module.scss to use the same CSS variable pattern as the related
theme.ts and .toolbar styles, so SwaggerEditor stays consistent with the rest of
the themed UI and locates through the .editor selector.
In `@src/widgets/swagger-editor/ui/swagger-editor.tsx`:
- Around line 40-44: The format detection in onTextChange is running
synchronously on every keystroke and should be debounced to avoid blocking edits
on large specs. Update swagger-editor.tsx so detectFormat is wrapped with the
existing useDebounce pattern used elsewhere in the codebase (for example, the
HomePage YAML parsing flow), and have onTextChange update currentFormat from the
debounced result while still forwarding newText through onChange?. The key
symbols to adjust are onTextChange, detectFormat, setCurrentFormat, and
useDebounce.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: bb2df897-34c0-439f-9274-bc037a3fa708
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (48)
.commitlintrc.jsonapp/[locale]/about/page.tsxapp/[locale]/history/page.tsxapp/[locale]/home/page.tsxapp/[locale]/layout.tsxapp/[locale]/login/page.tsxapp/[locale]/register/page.tsxmessages/en.jsonmessages/ru.jsonnext.config.tspackage.jsonsrc/app/styles/abstract/_constants.scsssrc/features/.gitkeepsrc/features/format-converter/index.tssrc/features/format-converter/lib/convert-format.test.tssrc/features/format-converter/lib/convert-format.tssrc/features/format-converter/lib/detect-format.test.tssrc/features/format-converter/lib/detect-format.tssrc/features/format-converter/ui/format-toggle.module.scsssrc/features/format-converter/ui/format-toggle.tsxsrc/features/schema-validator/index.tssrc/features/schema-validator/lib/codemirror-linter.tssrc/features/schema-validator/lib/validate-schema.test.tssrc/features/schema-validator/lib/validate-schema.tssrc/features/schema-validator/ui/validation-feedback/validation-feedback.module.scsssrc/features/schema-validator/ui/validation-feedback/validation-feedback.tsxsrc/features/schema-validator/ui/validation-status/validation-status.module.scsssrc/features/schema-validator/ui/validation-status/validation-status.tsxsrc/pages/.gitkeepsrc/pages/home-page/index.tssrc/pages/home-page/ui/home-page.module.scsssrc/pages/home-page/ui/home-page.tsxsrc/shared/lib/hooks/index.tssrc/shared/lib/hooks/use-debounce.tssrc/shared/types/format.tssrc/shared/ui/arc-background/arc-background.module.scsssrc/shared/ui/badge/badge.module.scsssrc/shared/ui/badge/badge.tsxsrc/shared/ui/button/button.module.scsssrc/shared/ui/button/button.tsxsrc/shared/ui/code-editor/index.tssrc/shared/ui/code-editor/lib/theme.tssrc/shared/ui/code-editor/ui/code-editor.module.scsssrc/shared/ui/code-editor/ui/code-editor.tsxsrc/widgets/.gitkeepsrc/widgets/swagger-editor/index.tssrc/widgets/swagger-editor/ui/swagger-editor.module.scsssrc/widgets/swagger-editor/ui/swagger-editor.tsx
| const spectral = new Spectral(); | ||
|
|
||
| const myRuleset: RulesetDefinition = { | ||
| extends: [oas as unknown as RulesetDefinition], | ||
| rules: { | ||
| 'info-contact': 'off', | ||
| 'info-description': 'off', | ||
| 'info-license': 'off', | ||
| 'license-url': 'off', | ||
| 'openapi-tags': 'off', | ||
| 'operation-description': 'off', | ||
| 'operation-tags': 'off', | ||
| 'operation-tag-defined': 'off', | ||
| 'operation-operationId': 'off', | ||
| 'operation-operationId-valid-in-url': 'off', | ||
| 'tag-description': 'off', | ||
| 'oas3-api-servers': 'off', | ||
| }, | ||
| }; | ||
|
|
||
| spectral.setRuleset(myRuleset); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Is a single @stoplight/spectral-core Spectral instance safe for concurrent parallel run() calls?
💡 Result:
A single Spectral instance from @stoplight/spectral-core is not designed for concurrent parallel run calls, and utilizing it in this manner may lead to unpredictable behavior or race conditions. The Spectral class maintains internal state related to the ruleset and configuration (such as the resolver and registered formats) [1][2]. When you call run, the instance uses this internal state to process the provided document [3]. Because the instance is stateful, performing multiple concurrent linting operations on a single instance can result in internal state contention [4]. If you need to perform concurrent linting, the recommended and safe approach is to instantiate a new Spectral instance for each parallel task, or to use a pool of instances if performance overhead is a concern [1][5][6]. Each instance should be configured independently to avoid shared state issues.
Citations:
- 1: https://github.com/stoplightio/spectral/blob/develop/docs/guides/3-javascript.md
- 2: https://github.com/stoplightio/spectral/blob/develop/docs/migration-guides/6.0.md
- 3: Publicly export spectral-core utils functions stoplightio/spectral#2260
- 4: stoplightio/spectral@fb72fc4
- 5: How to use in code? stoplightio/spectral#2875
- 6: Why the code below doesn't return with an error? stoplightio/spectral#1967
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the target file and its size first
git ls-files src/features/schema-validator/lib/validate-schema.ts
wc -l src/features/schema-validator/lib/validate-schema.ts
# Inspect the target file with line numbers
cat -n src/features/schema-validator/lib/validate-schema.ts
# Find call sites / exports related to validateSchema
rg -n "validateSchema|Spectral|setRuleset|run\(" src/features -SRepository: FierceSloth/swagger-editor-app
Length of output: 2926
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the linter integration and tests
cat -n src/features/schema-validator/lib/codemirror-linter.ts
printf '\n---\n'
cat -n src/features/schema-validator/lib/validate-schema.test.ts
# Check for any serialization / memoization around validateSchema usage
rg -n "validateSchema|linter|lint|queue|serialize|mutex|debounce|throttle|cancel" src/features/schema-validator -SRepository: FierceSloth/swagger-editor-app
Length of output: 4972
Не переиспользовать один Spectral для параллельных run()
Spectral здесь хранится на уровне модуля, а validateSchema() вызывается асинхронно без сериализации. При одновременных запусках линтера лучше создавать Spectral/ruleset на вызов или защищать общий инстанс очередью, иначе возможны гонки и нестабильные результаты.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/features/schema-validator/lib/validate-schema.ts` around lines 6 - 26,
The module-level Spectral instance in validateSchema is shared across concurrent
validateSchema() calls, which can cause race conditions when setRuleset/run are
used in parallel. Update validateSchema to create a fresh Spectral instance and
apply myRuleset per invocation, or otherwise serialize access to the shared
instance, so each run operates on its own isolated configuration.
| .wrapper { | ||
| padding: 0.75rem 1.5rem; | ||
| background-color: var(--bg-surface-1); | ||
| border-top: 1px solid var(--bg-surface-2); | ||
|
|
||
| display: flex; | ||
| align-items: center; | ||
| gap: 0.75rem; | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Убрать пустую строку перед объявлением, чтобы пройти stylelint.
Static analysis сообщает об ошибке declaration-empty-line-before на строке 6.
🎨 Предложенное исправление
.wrapper {
padding: 0.75rem 1.5rem;
background-color: var(--bg-surface-1);
border-top: 1px solid var(--bg-surface-2);
-
display: flex;
align-items: center;
gap: 0.75rem;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .wrapper { | |
| padding: 0.75rem 1.5rem; | |
| background-color: var(--bg-surface-1); | |
| border-top: 1px solid var(--bg-surface-2); | |
| display: flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| } | |
| .wrapper { | |
| padding: 0.75rem 1.5rem; | |
| background-color: var(--bg-surface-1); | |
| border-top: 1px solid var(--bg-surface-2); | |
| display: flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| } |
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 6-6: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/features/schema-validator/ui/validation-feedback/validation-feedback.module.scss`
around lines 1 - 9, Remove the empty blank line inside the .wrapper rule in
validation-feedback.module.scss so the declarations are contiguous and satisfy
stylelint’s declaration-empty-line-before rule; keep the styling in the same
.wrapper selector and eliminate the spacing before the display declaration.
Source: Linters/SAST tools
| .badge { | ||
| font-family: var(--font-mono); | ||
| border-radius: var(--radius-pill); | ||
| font-size: 10px; | ||
| padding: 0.25rem 0.75rem; | ||
|
|
||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| gap: 0.3rem; | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Пустая строка перед объявлением нарушает правило stylelint.
Stylelint (declaration-empty-line-before) указывает на пустую строку перед display: flex; (строка 7, после пустой строки 6).
🧹 Исправление
padding: 0.25rem 0.75rem;
-
display: flex;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .badge { | |
| font-family: var(--font-mono); | |
| border-radius: var(--radius-pill); | |
| font-size: 10px; | |
| padding: 0.25rem 0.75rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.3rem; | |
| } | |
| .badge { | |
| font-family: var(--font-mono); | |
| border-radius: var(--radius-pill); | |
| font-size: 10px; | |
| padding: 0.25rem 0.75rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.3rem; | |
| } |
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 7-7: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/features/schema-validator/ui/validation-status/validation-status.module.scss`
around lines 1 - 11, The .badge rule in validation-status.module.scss has an
empty line before the display declaration that violates stylelint’s
declaration-empty-line-before rule. Remove the blank line inside the .badge
block so the declarations stay contiguous, and keep the fix limited to the
.badge style block in validation-status.module.scss.
Source: Linters/SAST tools
| transform: translate(-70%, -50%); | ||
| background: #000; | ||
|
|
||
| opacity: 0.8; | ||
|
|
||
| box-shadow: 0 0 150px 30px rgba(var(--fringe-rgb), 0.1); | ||
|
|
||
| animation: breathe 8s ease-in-out infinite alternate; | ||
| } | ||
|
|
||
| .arc::before { | ||
| content: ""; | ||
| content: ''; | ||
| position: absolute; | ||
| inset: 0; | ||
| border-radius: 60%; | ||
| opacity: 0.7; | ||
|
|
||
| border: 7px solid rgba(var(--core-rgb), 0.95); | ||
|
|
||
| filter: blur(0.5px); | ||
|
|
||
| box-shadow: | ||
| filter: blur(0.5px); | ||
|
|
||
| box-shadow: | ||
| 0 0 6px 1px rgba(var(--core-rgb), 0.9), | ||
| inset 0 0 6px 1px rgba(var(--core-rgb), 0.9), | ||
|
|
||
| 0 0 20px 10px rgba(var(--core-glow-rgb), 0.6), | ||
| inset 0 0 20px 10px rgba(var(--core-glow-rgb), 0.6), | ||
|
|
||
| 0 0 50px 12px rgba(var(--core-glow-rgb), 0.55), | ||
| inset 0 0 50px 12px rgba(var(--core-glow-rgb), 0.55), | ||
|
|
||
| 0 0 100px 25px rgba(var(--core-glow-rgb), 0.25), | ||
| inset 0 0 100px 25px rgba(var(--core-glow-rgb), 0.25), | ||
|
|
||
| 0 0 200px 32px rgba(var(--core-glow-rgb), 0.15), | ||
| inset 0 0 200px 32px rgba(var(--core-glow-rgb), 0.15); | ||
| } | ||
|
|
||
| .arc::after { | ||
| content: ""; | ||
| content: ''; | ||
| position: absolute; | ||
| inset: -40px; | ||
| inset: -40px; | ||
| border-radius: 50%; | ||
|
|
||
| border: 1px solid rgba(var(--fringe-rgb), 0.7); | ||
| filter: blur(1px); | ||
| box-shadow: | ||
| filter: blur(1px); | ||
|
|
||
| box-shadow: |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Лишние пустые строки перед объявлениями (stylelint).
Статический анализ фиксирует нарушение declaration-empty-line-before в нескольких местах внутри .arc, .arc::before и .arc::after (строки 22, 25, 27, 29, 39, 41, 43-53, 62).
🎨 Предлагаемое исправление
.arc {
...
- transform: translate(-70%, -50%);
- background: `#000`;
+ transform: translate(-70%, -50%);
+ background: `#000`;
opacity: 0.8;
-
- box-shadow: 0 0 150px 30px rgba(var(--fringe-rgb), 0.1);
+ box-shadow: 0 0 150px 30px rgba(var(--fringe-rgb), 0.1);
- animation: breathe 8s ease-in-out infinite alternate;
+ animation: breathe 8s ease-in-out infinite alternate;
}Аналогично убрать пустые строки перед border, filter, box-shadow в .arc::before и .arc::after.
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 22-22: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 25-25: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 27-27: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 29-29: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 39-39: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 41-41: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 43-53: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 62-62: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/shared/ui/arc-background/arc-background.module.scss` around lines 22 -
65, The `.arc`, `.arc::before`, and `.arc::after` rules in
`arc-background.module.scss` contain extra blank lines before declarations that
violate `declaration-empty-line-before`. Remove the empty lines between the
related properties in these selectors, especially before `border`, `filter`, and
`box-shadow`, so the stylesheet matches the lint rule without changing the
visual styles.
Source: Linters/SAST tools
| border-radius: 4px; | ||
| border: 1px solid var(--badge-border-color); | ||
| background-color: var(--badge-color); | ||
| padding: 4px 12px; | ||
|
|
||
| font-family: var(--font-ui), monospace; | ||
| white-space: nowrap; | ||
| transition: color 0.3s ease; | ||
| } | ||
|
|
||
| .text { | ||
| color: var(--badge-text-color); | ||
| font-size: 12px; | ||
| color: var(--badge-text-color); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Лишние пустые строки перед объявлениями (stylelint).
Аналогично другим файлам, добавленные пустые строки перед border-radius (строка 7), font-family (строка 12) и font-size (строка 16) нарушают правило declaration-empty-line-before.
🎨 Предлагаемое исправление
gap: 0.8rem;
-
border-radius: 4px;
border: 1px solid var(--badge-border-color);
background-color: var(--badge-color);
padding: 4px 12px;
- font-family: var(--font-ui), monospace;
+ font-family: var(--font-ui), monospace;
white-space: nowrap;
transition: color 0.3s ease;
- font-size: 12px;
+ font-size: 12px;
color: var(--badge-text-color);🧰 Tools
🪛 Stylelint (17.14.0)
[error] 7-7: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 12-12: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 16-16: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/shared/ui/badge/badge.module.scss` around lines 7 - 17, Remove the extra
blank lines before the CSS declarations in badge.module.scss so the block
follows declaration-empty-line-before consistently. Update the badge styles by
keeping the declarations for border-radius, font-family, and font-size
contiguous with the surrounding properties in the same rule.
Source: Linters/SAST tools
|
|
||
| .tertiary { | ||
| font-family: var(--font-mono); | ||
| font-size: 12px; | ||
| font-weight: 500; | ||
| color: var(--text-primary); | ||
|
|
||
| border: 1px solid transparent; | ||
| border-radius: 4px; | ||
|
|
||
| padding: 0.25rem 0.75rem; | ||
| transition: all 0.1s; | ||
|
|
||
| &:hover { | ||
| background-color: var(--bg-surface-2); | ||
| border-color: var(--bg-surface-3); | ||
| } | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Лишние пустые строки перед объявлениями (stylelint).
Пустые строки перед border (строка 61) и padding (строка 64) в .tertiary нарушают declaration-empty-line-before.
🎨 Предлагаемое исправление
color: var(--text-primary);
-
border: 1px solid transparent;
border-radius: 4px;
- padding: 0.25rem 0.75rem;
+ padding: 0.25rem 0.75rem;
transition: all 0.1s;🧰 Tools
🪛 Stylelint (17.14.0)
[error] 61-61: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 64-64: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/shared/ui/button/button.module.scss` around lines 54 - 71, The .tertiary
rule in button.module.scss has empty lines before the border and padding
declarations, which violates declaration-empty-line-before. Remove the extra
blank lines inside the .tertiary block so the declarations are grouped
consistently, keeping the existing styling and hover rules unchanged.
Source: Linters/SAST tools
| .toolbar { | ||
| display: flex; | ||
| align-items: center; | ||
| padding: 0.75rem 1.5rem; | ||
| background-color: var(--bg-surface-1); | ||
| border-bottom: 1px solid var(--bg-surface-2); | ||
|
|
||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| gap: 0.75rem; | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Дублирование свойств display и align-items в .toolbar.
Statлint фиксирует дублирование display (строки 10 и 16) и align-items (строки 11 и 17), а также лишнюю пустую строку перед объявлением (строка 16) — похоже на артефакт слияния кода.
🧹 Предложенное исправление
.toolbar {
display: flex;
align-items: center;
padding: 0.75rem 1.5rem;
background-color: var(--bg-surface-1);
border-bottom: 1px solid var(--bg-surface-2);
-
- display: flex;
- align-items: center;
justify-content: space-between;
gap: 0.75rem;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .toolbar { | |
| display: flex; | |
| align-items: center; | |
| padding: 0.75rem 1.5rem; | |
| background-color: var(--bg-surface-1); | |
| border-bottom: 1px solid var(--bg-surface-2); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 0.75rem; | |
| } | |
| .toolbar { | |
| display: flex; | |
| align-items: center; | |
| padding: 0.75rem 1.5rem; | |
| background-color: var(--bg-surface-1); | |
| border-bottom: 1px solid var(--bg-surface-2); | |
| justify-content: space-between; | |
| gap: 0.75rem; | |
| } |
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 10-10: Duplicate property "display" (declaration-block-no-duplicate-properties)
(declaration-block-no-duplicate-properties)
[error] 11-11: Duplicate property "align-items" (declaration-block-no-duplicate-properties)
(declaration-block-no-duplicate-properties)
[error] 16-16: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/widgets/swagger-editor/ui/swagger-editor.module.scss` around lines 9 -
20, In the .toolbar style block of swagger-editor.module.scss, remove the
duplicated display and align-items declarations and clean up the extra blank
line left by the merge artifact. Keep a single set of layout properties in
.toolbar, preserving the intended flex layout by leaving the final
justify-content and gap settings alongside one display and one align-items
declaration.
Source: Linters/SAST tools
- Replace 'unknown' magic string with null in DetectedFormat type - Extract parseToObject helper to shared/lib to eliminate duplicated yaml parsing - Replace nested ternary with getStatus function in ValidationFeedback - Split validation object state into separate errorsCount/warningsCount states - Derive currentFormat via useMemo with debounce instead of useState + useEffect - Sync package-lock.json
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
src/pages/home-page/ui/home-page.tsx (1)
12-21: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winНезависимый повторный дебаунс дублирует и рассинхронизирует состояние с
SwaggerEditor.
HomePageдебаунситrawTextс задержкой 500 мс, при этомSwaggerEditorуже дебаунсит то же значение внутри себя с задержкой 300 мс для вычисленияisSchemaValid. ПосколькуisSchemaValidустанавливается раньше (по факту стабилизации текста через 300 мс), аdebouncedTextвHomePageобновляется на 200 мс позже, между этими моментамиparsedSchemaможет быть вычислен по устаревшему снимку текста, отличному от того, что был признан валидным. Сейчас это заметно только вconsole.log, но станет функциональной проблемой после интеграции реального SwaggerViewer.Поскольку
isSchemaValidуже гарантирует стабильность текста к моментуtrue, проще убрать локальный дебаунс вHomePageи использоватьrawTextнапрямую.Предлагаемая правка
const [rawText, setRawText] = useState(''); const [isSchemaValid, setIsSchemaValid] = useState(false); - const debouncedText = useDebounce(rawText, 500); - const parsedSchema = useMemo(() => { - if (!isSchemaValid || !debouncedText) return null; + if (!isSchemaValid || !rawText) return null; - return parseToObject(debouncedText); - }, [debouncedText, isSchemaValid]); + return parseToObject(rawText); + }, [rawText, isSchemaValid]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/home-page/ui/home-page.tsx` around lines 12 - 21, `HomePage` is applying a second debounce through `useDebounce`, which can make `parsedSchema` lag behind the validation state already provided by `SwaggerEditor`. Remove the local debounced value and derive `parsedSchema` directly from `rawText` once `isSchemaValid` is true, keeping the `useMemo` logic in `home-page.tsx` aligned with `SwaggerEditor`’s existing debounce. Update the `parsedSchema` computation to use the current text state instead of `debouncedText`, and adjust the dependency list accordingly so the parsed object always matches the validated input.
🧹 Nitpick comments (3)
src/app/styles/style.scss (1)
11-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winВынесите
80pxв CSS-переменную, связанную с высотой хедера.Значение
padding-top: 80pxжёстко привязано к высотеHeader, но не связано с ней явно. При изменении высоты хедера придётся синхронизировать вручную в двух местах.♻️ Пример рефактора
+:root { + --header-height: 80px; +} + main { flex: 1; - padding-top: 80px; + padding-top: var(--header-height); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/styles/style.scss` around lines 11 - 14, The hardcoded 80px in the main layout styles is duplicated header spacing and should be tied to the Header height via a CSS variable. Update the styles in style.scss so main uses a shared custom property for top padding instead of a literal value, and define or reuse that variable where the Header height is established so changes stay in sync.src/widgets/footer/ui/footer.tsx (1)
23-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueСтрока "RS School 2026" не локализована.
В отличие от остальных текстов в футере (
t('about'),t('team1'),t('team2')), эта строка захардкожена. Если это осознанно (название курса/бренд), можно игнорировать, иначе стоит перенести вmessages/*.json.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/widgets/footer/ui/footer.tsx` around lines 23 - 30, The footer label "RS School 2026" in the Footer component is hardcoded while other footer texts use localization. Update the Footer JSX to source this text through the existing i18n/messages flow (or confirm it is intentionally a brand name and leave it unchanged), using the Footer component and its t(...) calls as the location to adjust.src/widgets/swagger-editor/ui/swagger-editor.tsx (1)
60-68: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winМассив
extensionsпересоздаётся на каждый рендер.
extensions={[openapiLinter]}создаёт новый массив при каждом рендереSwaggerEditor, а компонент ре-рендерится на каждое изменениеvalue(то есть на каждое нажатие клавиши). Официальная документация@uiw/react-codemirrorрекомендует определятьextensionsвне компонента или мемоизировать черезuseMemo, так как смена ссылки вызывает дорогостоящую переконфигурацию редактора.Предлагаемая правка
+ const extensions = useMemo(() => [openapiLinter], []); + return ( <div className={styles.wrapper}> ... <CodeEditor value={value} height="100%" onChange={onChange} format={currentFormat ?? undefined} className={styles.editor} - extensions={[openapiLinter]} + extensions={extensions} onUpdate={onEditorUpdate} />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/widgets/swagger-editor/ui/swagger-editor.tsx` around lines 60 - 68, The `SwaggerEditor` component is recreating the `extensions` array on every render, which forces unnecessary CodeMirror reconfiguration. Update `swagger-editor.tsx` so the `CodeEditor` call uses a stable `extensions` reference by moving the array out of `SwaggerEditor` or memoizing it with `useMemo` around `openapiLinter`. Keep the change localized to the `SwaggerEditor`/`CodeEditor` props so the editor only reconfigures when the actual extension changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/checks.yml:
- Around line 14-15: The `actions/checkout@v4` step is leaving `GITHUB_TOKEN`
available to later steps via git credentials. Update the checkout configuration
to disable credential persistence by setting `persist-credentials` to false on
the Checkout step in the workflow.
In `@src/shared/ui/button-link/button-link.module.scss`:
- Around line 7-14: Remove the empty lines before the declarations in the
button-link.module.scss stylesheet so the block follows the project’s
declaration formatting rules. Adjust the declaration group around font-size,
line-height, font-weight, text-decoration, cursor, transition, and border-radius
to be contiguous, matching the expected stylelint configuration in CI.
In `@src/widgets/header/ui/header.tsx`:
- Line 3: The auth check used by Header is a stub that always returns false, so
PrivateNavigation can never render. Update isAuthenticated from
src/shared/lib/auth/is-authenticated to read real authentication state (or
remove the conditional in Header if auth is not wired yet), and make sure the
Header component uses the corrected auth source so the public/private navigation
branch can actually be reached.
In `@src/widgets/header/ui/private-navigation/private-navigation.tsx`:
- Around line 18-20: The “sign out” Button in private-navigation currently
renders without any click handler, so it does nothing when pressed. Update the
Button used for signOutLabel in private-navigation to wire in the existing
logout/sign-out action via an onClick handler, and if needed pass the handler
into this component through its props so the click can trigger the actual exit
flow.
---
Duplicate comments:
In `@src/pages/home-page/ui/home-page.tsx`:
- Around line 12-21: `HomePage` is applying a second debounce through
`useDebounce`, which can make `parsedSchema` lag behind the validation state
already provided by `SwaggerEditor`. Remove the local debounced value and derive
`parsedSchema` directly from `rawText` once `isSchemaValid` is true, keeping the
`useMemo` logic in `home-page.tsx` aligned with `SwaggerEditor`’s existing
debounce. Update the `parsedSchema` computation to use the current text state
instead of `debouncedText`, and adjust the dependency list accordingly so the
parsed object always matches the validated input.
---
Nitpick comments:
In `@src/app/styles/style.scss`:
- Around line 11-14: The hardcoded 80px in the main layout styles is duplicated
header spacing and should be tied to the Header height via a CSS variable.
Update the styles in style.scss so main uses a shared custom property for top
padding instead of a literal value, and define or reuse that variable where the
Header height is established so changes stay in sync.
In `@src/widgets/footer/ui/footer.tsx`:
- Around line 23-30: The footer label "RS School 2026" in the Footer component
is hardcoded while other footer texts use localization. Update the Footer JSX to
source this text through the existing i18n/messages flow (or confirm it is
intentionally a brand name and leave it unchanged), using the Footer component
and its t(...) calls as the location to adjust.
In `@src/widgets/swagger-editor/ui/swagger-editor.tsx`:
- Around line 60-68: The `SwaggerEditor` component is recreating the
`extensions` array on every render, which forces unnecessary CodeMirror
reconfiguration. Update `swagger-editor.tsx` so the `CodeEditor` call uses a
stable `extensions` reference by moving the array out of `SwaggerEditor` or
memoizing it with `useMemo` around `openapiLinter`. Keep the change localized to
the `SwaggerEditor`/`CodeEditor` props so the editor only reconfigures when the
actual extension changes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 18f884ea-a235-48c4-bfcf-2f622baee7a2
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/logo.pngis excluded by!**/*.png
📒 Files selected for processing (40)
.github/workflows/checks.ymlapp/[locale]/layout.tsxmessages/en.jsonmessages/ru.jsonsrc/app/styles/style.scsssrc/features/format-converter/lib/convert-format.tssrc/features/format-converter/lib/detect-format.test.tssrc/features/format-converter/lib/detect-format.tssrc/features/format-converter/ui/format-toggle.module.scsssrc/features/format-converter/ui/format-toggle.tsxsrc/features/language-switcher/index.tssrc/features/language-switcher/ui/language-switcher.module.scsssrc/features/language-switcher/ui/language-switcher.tsxsrc/features/schema-validator/lib/codemirror-linter.tssrc/features/schema-validator/ui/validation-feedback/validation-feedback.tsxsrc/pages/home-page/ui/home-page.tsxsrc/shared/config/routes.tssrc/shared/lib/auth/is-authenticated.tssrc/shared/lib/parse-to-object.tssrc/shared/types/format.tssrc/shared/ui/button-link/button-link.module.scsssrc/shared/ui/button-link/button-link.test.tsxsrc/shared/ui/button-link/button-link.tsxsrc/shared/ui/button-link/index.tssrc/shared/ui/code-editor/ui/code-editor.tsxsrc/widgets/footer/index.tssrc/widgets/footer/ui/footer.module.scsssrc/widgets/footer/ui/footer.tsxsrc/widgets/header/index.tssrc/widgets/header/ui/header.module.scsssrc/widgets/header/ui/header.tsxsrc/widgets/header/ui/logo/index.tssrc/widgets/header/ui/logo/logo.tsxsrc/widgets/header/ui/page-navigation/index.tssrc/widgets/header/ui/page-navigation/page-navigation.tsxsrc/widgets/header/ui/private-navigation/index.tssrc/widgets/header/ui/private-navigation/private-navigation.tsxsrc/widgets/header/ui/public-navigation/index.tssrc/widgets/header/ui/public-navigation/public-navigation.tsxsrc/widgets/swagger-editor/ui/swagger-editor.tsx
✅ Files skipped from review due to trivial changes (11)
- src/features/language-switcher/ui/language-switcher.tsx
- src/shared/lib/parse-to-object.ts
- src/shared/config/routes.ts
- src/widgets/header/ui/logo/logo.tsx
- src/widgets/footer/ui/footer.module.scss
- src/features/language-switcher/index.ts
- src/shared/lib/auth/is-authenticated.ts
- src/widgets/header/ui/private-navigation/index.ts
- src/features/format-converter/ui/format-toggle.module.scss
- src/widgets/header/ui/page-navigation/index.ts
- src/widgets/header/ui/header.module.scss
🚧 Files skipped from review as they are similar to previous changes (6)
- src/shared/types/format.ts
- src/features/format-converter/ui/format-toggle.tsx
- src/features/schema-validator/lib/codemirror-linter.ts
- messages/ru.json
- src/shared/ui/code-editor/ui/code-editor.tsx
- src/features/schema-validator/ui/validation-feedback/validation-feedback.tsx
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 4
♻️ Duplicate comments (1)
src/pages/home-page/ui/home-page.tsx (1)
12-21: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winНезависимый повторный дебаунс дублирует и рассинхронизирует состояние с
SwaggerEditor.
HomePageдебаунситrawTextс задержкой 500 мс, при этомSwaggerEditorуже дебаунсит то же значение внутри себя с задержкой 300 мс для вычисленияisSchemaValid. ПосколькуisSchemaValidустанавливается раньше (по факту стабилизации текста через 300 мс), аdebouncedTextвHomePageобновляется на 200 мс позже, между этими моментамиparsedSchemaможет быть вычислен по устаревшему снимку текста, отличному от того, что был признан валидным. Сейчас это заметно только вconsole.log, но станет функциональной проблемой после интеграции реального SwaggerViewer.Поскольку
isSchemaValidуже гарантирует стабильность текста к моментуtrue, проще убрать локальный дебаунс вHomePageи использоватьrawTextнапрямую.Предлагаемая правка
const [rawText, setRawText] = useState(''); const [isSchemaValid, setIsSchemaValid] = useState(false); - const debouncedText = useDebounce(rawText, 500); - const parsedSchema = useMemo(() => { - if (!isSchemaValid || !debouncedText) return null; + if (!isSchemaValid || !rawText) return null; - return parseToObject(debouncedText); - }, [debouncedText, isSchemaValid]); + return parseToObject(rawText); + }, [rawText, isSchemaValid]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/pages/home-page/ui/home-page.tsx` around lines 12 - 21, `HomePage` is applying a second debounce through `useDebounce`, which can make `parsedSchema` lag behind the validation state already provided by `SwaggerEditor`. Remove the local debounced value and derive `parsedSchema` directly from `rawText` once `isSchemaValid` is true, keeping the `useMemo` logic in `home-page.tsx` aligned with `SwaggerEditor`’s existing debounce. Update the `parsedSchema` computation to use the current text state instead of `debouncedText`, and adjust the dependency list accordingly so the parsed object always matches the validated input.
🧹 Nitpick comments (3)
src/app/styles/style.scss (1)
11-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winВынесите
80pxв CSS-переменную, связанную с высотой хедера.Значение
padding-top: 80pxжёстко привязано к высотеHeader, но не связано с ней явно. При изменении высоты хедера придётся синхронизировать вручную в двух местах.♻️ Пример рефактора
+:root { + --header-height: 80px; +} + main { flex: 1; - padding-top: 80px; + padding-top: var(--header-height); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/styles/style.scss` around lines 11 - 14, The hardcoded 80px in the main layout styles is duplicated header spacing and should be tied to the Header height via a CSS variable. Update the styles in style.scss so main uses a shared custom property for top padding instead of a literal value, and define or reuse that variable where the Header height is established so changes stay in sync.src/widgets/footer/ui/footer.tsx (1)
23-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueСтрока "RS School 2026" не локализована.
В отличие от остальных текстов в футере (
t('about'),t('team1'),t('team2')), эта строка захардкожена. Если это осознанно (название курса/бренд), можно игнорировать, иначе стоит перенести вmessages/*.json.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/widgets/footer/ui/footer.tsx` around lines 23 - 30, The footer label "RS School 2026" in the Footer component is hardcoded while other footer texts use localization. Update the Footer JSX to source this text through the existing i18n/messages flow (or confirm it is intentionally a brand name and leave it unchanged), using the Footer component and its t(...) calls as the location to adjust.src/widgets/swagger-editor/ui/swagger-editor.tsx (1)
60-68: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winМассив
extensionsпересоздаётся на каждый рендер.
extensions={[openapiLinter]}создаёт новый массив при каждом рендереSwaggerEditor, а компонент ре-рендерится на каждое изменениеvalue(то есть на каждое нажатие клавиши). Официальная документация@uiw/react-codemirrorрекомендует определятьextensionsвне компонента или мемоизировать черезuseMemo, так как смена ссылки вызывает дорогостоящую переконфигурацию редактора.Предлагаемая правка
+ const extensions = useMemo(() => [openapiLinter], []); + return ( <div className={styles.wrapper}> ... <CodeEditor value={value} height="100%" onChange={onChange} format={currentFormat ?? undefined} className={styles.editor} - extensions={[openapiLinter]} + extensions={extensions} onUpdate={onEditorUpdate} />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/widgets/swagger-editor/ui/swagger-editor.tsx` around lines 60 - 68, The `SwaggerEditor` component is recreating the `extensions` array on every render, which forces unnecessary CodeMirror reconfiguration. Update `swagger-editor.tsx` so the `CodeEditor` call uses a stable `extensions` reference by moving the array out of `SwaggerEditor` or memoizing it with `useMemo` around `openapiLinter`. Keep the change localized to the `SwaggerEditor`/`CodeEditor` props so the editor only reconfigures when the actual extension changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/checks.yml:
- Around line 14-15: The `actions/checkout@v4` step is leaving `GITHUB_TOKEN`
available to later steps via git credentials. Update the checkout configuration
to disable credential persistence by setting `persist-credentials` to false on
the Checkout step in the workflow.
In `@src/shared/ui/button-link/button-link.module.scss`:
- Around line 7-14: Remove the empty lines before the declarations in the
button-link.module.scss stylesheet so the block follows the project’s
declaration formatting rules. Adjust the declaration group around font-size,
line-height, font-weight, text-decoration, cursor, transition, and border-radius
to be contiguous, matching the expected stylelint configuration in CI.
In `@src/widgets/header/ui/header.tsx`:
- Line 3: The auth check used by Header is a stub that always returns false, so
PrivateNavigation can never render. Update isAuthenticated from
src/shared/lib/auth/is-authenticated to read real authentication state (or
remove the conditional in Header if auth is not wired yet), and make sure the
Header component uses the corrected auth source so the public/private navigation
branch can actually be reached.
In `@src/widgets/header/ui/private-navigation/private-navigation.tsx`:
- Around line 18-20: The “sign out” Button in private-navigation currently
renders without any click handler, so it does nothing when pressed. Update the
Button used for signOutLabel in private-navigation to wire in the existing
logout/sign-out action via an onClick handler, and if needed pass the handler
into this component through its props so the click can trigger the actual exit
flow.
---
Duplicate comments:
In `@src/pages/home-page/ui/home-page.tsx`:
- Around line 12-21: `HomePage` is applying a second debounce through
`useDebounce`, which can make `parsedSchema` lag behind the validation state
already provided by `SwaggerEditor`. Remove the local debounced value and derive
`parsedSchema` directly from `rawText` once `isSchemaValid` is true, keeping the
`useMemo` logic in `home-page.tsx` aligned with `SwaggerEditor`’s existing
debounce. Update the `parsedSchema` computation to use the current text state
instead of `debouncedText`, and adjust the dependency list accordingly so the
parsed object always matches the validated input.
---
Nitpick comments:
In `@src/app/styles/style.scss`:
- Around line 11-14: The hardcoded 80px in the main layout styles is duplicated
header spacing and should be tied to the Header height via a CSS variable.
Update the styles in style.scss so main uses a shared custom property for top
padding instead of a literal value, and define or reuse that variable where the
Header height is established so changes stay in sync.
In `@src/widgets/footer/ui/footer.tsx`:
- Around line 23-30: The footer label "RS School 2026" in the Footer component
is hardcoded while other footer texts use localization. Update the Footer JSX to
source this text through the existing i18n/messages flow (or confirm it is
intentionally a brand name and leave it unchanged), using the Footer component
and its t(...) calls as the location to adjust.
In `@src/widgets/swagger-editor/ui/swagger-editor.tsx`:
- Around line 60-68: The `SwaggerEditor` component is recreating the
`extensions` array on every render, which forces unnecessary CodeMirror
reconfiguration. Update `swagger-editor.tsx` so the `CodeEditor` call uses a
stable `extensions` reference by moving the array out of `SwaggerEditor` or
memoizing it with `useMemo` around `openapiLinter`. Keep the change localized to
the `SwaggerEditor`/`CodeEditor` props so the editor only reconfigures when the
actual extension changes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 18f884ea-a235-48c4-bfcf-2f622baee7a2
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/logo.pngis excluded by!**/*.png
📒 Files selected for processing (40)
.github/workflows/checks.ymlapp/[locale]/layout.tsxmessages/en.jsonmessages/ru.jsonsrc/app/styles/style.scsssrc/features/format-converter/lib/convert-format.tssrc/features/format-converter/lib/detect-format.test.tssrc/features/format-converter/lib/detect-format.tssrc/features/format-converter/ui/format-toggle.module.scsssrc/features/format-converter/ui/format-toggle.tsxsrc/features/language-switcher/index.tssrc/features/language-switcher/ui/language-switcher.module.scsssrc/features/language-switcher/ui/language-switcher.tsxsrc/features/schema-validator/lib/codemirror-linter.tssrc/features/schema-validator/ui/validation-feedback/validation-feedback.tsxsrc/pages/home-page/ui/home-page.tsxsrc/shared/config/routes.tssrc/shared/lib/auth/is-authenticated.tssrc/shared/lib/parse-to-object.tssrc/shared/types/format.tssrc/shared/ui/button-link/button-link.module.scsssrc/shared/ui/button-link/button-link.test.tsxsrc/shared/ui/button-link/button-link.tsxsrc/shared/ui/button-link/index.tssrc/shared/ui/code-editor/ui/code-editor.tsxsrc/widgets/footer/index.tssrc/widgets/footer/ui/footer.module.scsssrc/widgets/footer/ui/footer.tsxsrc/widgets/header/index.tssrc/widgets/header/ui/header.module.scsssrc/widgets/header/ui/header.tsxsrc/widgets/header/ui/logo/index.tssrc/widgets/header/ui/logo/logo.tsxsrc/widgets/header/ui/page-navigation/index.tssrc/widgets/header/ui/page-navigation/page-navigation.tsxsrc/widgets/header/ui/private-navigation/index.tssrc/widgets/header/ui/private-navigation/private-navigation.tsxsrc/widgets/header/ui/public-navigation/index.tssrc/widgets/header/ui/public-navigation/public-navigation.tsxsrc/widgets/swagger-editor/ui/swagger-editor.tsx
✅ Files skipped from review due to trivial changes (11)
- src/features/language-switcher/ui/language-switcher.tsx
- src/shared/lib/parse-to-object.ts
- src/shared/config/routes.ts
- src/widgets/header/ui/logo/logo.tsx
- src/widgets/footer/ui/footer.module.scss
- src/features/language-switcher/index.ts
- src/shared/lib/auth/is-authenticated.ts
- src/widgets/header/ui/private-navigation/index.ts
- src/features/format-converter/ui/format-toggle.module.scss
- src/widgets/header/ui/page-navigation/index.ts
- src/widgets/header/ui/header.module.scss
🚧 Files skipped from review as they are similar to previous changes (6)
- src/shared/types/format.ts
- src/features/format-converter/ui/format-toggle.tsx
- src/features/schema-validator/lib/codemirror-linter.ts
- messages/ru.json
- src/shared/ui/code-editor/ui/code-editor.tsx
- src/features/schema-validator/ui/validation-feedback/validation-feedback.tsx
🛑 Comments failed to post (4)
.github/workflows/checks.yml (1)
14-15: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Отключить persist-credentials для checkout.
actions/checkout@v4по умолчанию сохраняетGITHUB_TOKENв.git/config, доступный для всех последующих шагов job (npm ci,npm run build), включая код зависимостей и их install/postinstall-скрипты. Это увеличивает поверхность атаки при supply-chain компрометации npm-пакета.🔒️ Предлагаемый фикс
- name: Checkout uses: actions/checkout@v4 + with: + persist-credentials: false📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.- name: Checkout uses: actions/checkout@v4 with: persist-credentials: false🧰 Tools
🪛 zizmor (1.26.1)
[warning] 14-15: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/checks.yml around lines 14 - 15, The `actions/checkout@v4` step is leaving `GITHUB_TOKEN` available to later steps via git credentials. Update the checkout configuration to disable credential persistence by setting `persist-credentials` to false on the Checkout step in the workflow.Source: Linters/SAST tools
src/shared/ui/button-link/button-link.module.scss (1)
7-14: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Уберите пустые строки перед декларациями.
Stylelint уже ругается на
font-sizeиborder-radius; в текущем виде файл не пройдет проверку стилей, если правилоdeclaration-empty-line-beforeвключено в CI.🧰 Tools
🪛 Stylelint (17.14.0)
[error] 7-7: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
[error] 14-14: Expected no empty line before declaration (declaration-empty-line-before)
(declaration-empty-line-before)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/shared/ui/button-link/button-link.module.scss` around lines 7 - 14, Remove the empty lines before the declarations in the button-link.module.scss stylesheet so the block follows the project’s declaration formatting rules. Adjust the declaration group around font-size, line-height, font-weight, text-decoration, cursor, transition, and border-radius to be contiguous, matching the expected stylelint configuration in CI.Source: Linters/SAST tools
src/widgets/header/ui/header.tsx (1)
3-3: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail printf '\n== files ==\n' git ls-files 'src/widgets/header/ui/header.tsx' 'src/shared/lib/auth/is-authenticated.ts' || true printf '\n== outline header ==\n' ast-grep outline src/widgets/header/ui/header.tsx --view expanded || true printf '\n== outline auth helper ==\n' ast-grep outline src/shared/lib/auth/is-authenticated.ts --view expanded || true printf '\n== header contents ==\n' cat -n src/widgets/header/ui/header.tsx printf '\n== auth helper contents ==\n' cat -n src/shared/lib/auth/is-authenticated.ts printf '\n== search auth usages ==\n' rg -n "isAuthenticated|PrivateNavigation|PublicNavigation|login|session|cookie|auth" src -g '!**/*.map' || trueRepository: FierceSloth/swagger-editor-app
Length of output: 3271
isAuthenticatedвсегдаfalse, поэтомуPrivateNavigationнедостижим.
src/shared/lib/auth/is-authenticated.ts:1сейчас экспортируетfalse, из-за чегоHeaderвсегда показываетPublicNavigation. Замените это на реальное состояние аутентификации или уберите условие, пока auth-логика не подключена.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/widgets/header/ui/header.tsx` at line 3, The auth check used by Header is a stub that always returns false, so PrivateNavigation can never render. Update isAuthenticated from src/shared/lib/auth/is-authenticated to read real authentication state (or remove the conditional in Header if auth is not wired yet), and make sure the Header component uses the corrected auth source so the public/private navigation branch can actually be reached.src/widgets/header/ui/private-navigation/private-navigation.tsx (1)
18-20: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash set -euo pipefail # Map the target file and related symbols first ast-grep outline src/widgets/header/ui/private-navigation/private-navigation.tsx --view expanded || true # Find references to the private navigation component and sign-out handling rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \ 'private-navigation|signOutLabel|onSignOut|sign out|signOut|logout|log out' src . || trueRepository: FierceSloth/swagger-editor-app
Length of output: 1794
🏁 Script executed:
#!/bin/bash set -euo pipefail # Read the target file and its immediate related files if found wc -l src/widgets/header/ui/private-navigation/private-navigation.tsx 2>/dev/null || true cat -n src/widgets/header/ui/private-navigation/private-navigation.tsx 2>/dev/null || trueRepository: FierceSloth/swagger-editor-app
Length of output: 997
🏁 Script executed:
#!/bin/bash set -euo pipefail # Inspect the Button component API if it is local to the repository fd -a 'Button.*' src . 2>/dev/null || true rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \ 'export .*Button|function Button|const Button|type ButtonProps|interface ButtonProps' src . || trueRepository: FierceSloth/swagger-editor-app
Length of output: 1576
🏁 Script executed:
#!/bin/bash set -euo pipefail # Read the target file and locate the Button component usage context wc -l src/widgets/header/ui/private-navigation/private-navigation.tsx cat -n src/widgets/header/ui/private-navigation/private-navigation.tsx | sed -n '1,220p'Repository: FierceSloth/swagger-editor-app
Length of output: 997
🏁 Script executed:
#!/bin/bash set -euo pipefail # Inspect the Button implementation and the header context for a sign-out action wc -l src/shared/ui/button/button.tsx src/widgets/header/ui/header.tsx src/widgets/header/ui/private-navigation/private-navigation.tsx echo '--- button.tsx ---' cat -n src/shared/ui/button/button.tsx | sed -n '1,220p' echo '--- header.tsx ---' cat -n src/widgets/header/ui/header.tsx | sed -n '1,220p'Repository: FierceSloth/swagger-editor-app
Length of output: 2284
🏁 Script executed:
#!/bin/bash set -euo pipefail # Look for any logout/sign-out handler or auth action used in the header area rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' \ 'signOut|sign out|logout|log out|auth.*sign|onSignOut|handleSignOut|handleLogout|logout' srcRepository: FierceSloth/swagger-editor-app
Length of output: 615
Кнопка «Выйти» не работает
ButtonдляsignOutLabelрендерится безonClick, поэтому по клику ничего не происходит. Нужен обработчик выхода.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/widgets/header/ui/private-navigation/private-navigation.tsx` around lines 18 - 20, The “sign out” Button in private-navigation currently renders without any click handler, so it does nothing when pressed. Update the Button used for signOutLabel in private-navigation to wire in the existing logout/sign-out action via an onClick handler, and if needed pass the handler into this component through its props so the click can trigger the actual exit flow.
📋 Trello Task ID
⚡️ Summary
Merge the Swagger Editor epic into develop. This includes integrating a code editor for API specifications, implementing format conversion (JSON/YAML), adding OpenAPI schema validation, creating the main responsive split view, and synchronizing state between the editor and viewer.
Included stories:
🛠 Type of change
feat(New feature)fix(Bug fix)refactor(Code improvement / Refactoring without changing logic)style(Formatting, CSS)docs(Documentation)chore(Configs, Build)test(Testing)Summary by CodeRabbit
New Features
Bug Fixes