{"owner":"swagger-api","repo":"swagger-ui","hasSkills":true,"totalSkillsCount":5,"totalTokensCount":21787,"categories":["plugin-manifest","anthropic-skill","claude-rule"],"hasMcp":false,"mcpConfig":null,"found":["src/core/plugins/err/error-transformers/README.md","src/core/plugins/deep-linking/README.md",".claude/skills/README.md","CLAUDE.md",".claude/skills/add-oas-support.md"],"skills":{"src/core/plugins/err/error-transformers/README.md":"# Error transformers\n\nError transformers provide a standard interface for making generated error messages more useful to end users.\n\n### Inputs & outputs\n\nEach transformer's `transform` function is given an Immutable List of Immutable Maps as its first argument.\n\nIt is expected that each `transform` function returns a List of similarly-formed Maps.\n\nThese errors originate from the Redux error actions that add errors to state. Errors are transformed before being passed into the reducer.\n\nIt's important that all the keys present in each error (specifically, `line`, `level`, `message`, `source`, and `type`) are present when the transformer is finished.\n\n##### Deleting an error\n\nIf you want to delete an error completely, you can overwrite it with `null`. The null value will be filtered out of the transformed error array before the errors are returned.\nå\n\n### Example transformer\n\nThis transformer will increase all your line numbers by 10.\n\n```\nexport function transform(errors) {\n  return errors.map(err => {\n    err.line += 10\n    return err\n  })\n}\n```\n","src/core/plugins/deep-linking/README.md":"See `docs/deep-linking.md`.\n",".claude/skills/README.md":"# Swagger UI Claude Skills\n\nThis directory contains custom skills for working with the Swagger UI codebase in Claude Code.\n\n## Available Skills\n\n### `/add-oas-support` - Add OpenAPI Specification Version Support\n\nComprehensive skill for adding support for a new OpenAPI Specification version to Swagger UI.\n\n**Usage:**\n```\n/add-oas-support --version 4.0 --type major\n/add-oas-support --version 3.2 --type minor\n```\n\n**Parameters:**\n- `--version` (required): The OpenAPI version to add support for (e.g., \"3.2\", \"4.0\")\n- `--type` (optional): Version type - \"major\" or \"minor\" (default: \"minor\")\n\n**Structure:**\nThe skill includes both a **Quick Reference** section at the top for experienced developers, and a **comprehensive guide** below for detailed implementation instructions.\n\n**What it does:**\n1. **Analyzes the target OAS version specification using WebFetch**\n   - Fetches official spec from https://spec.openapis.org/\n   - Systematically identifies new/modified/removed fields\n   - Maps specification changes to Swagger UI components\n   - Creates specification change document\n2. Creates the plugin directory structure\n3. Implements version detection logic\n4. Creates selector factories and component wrappers\n5. Implements new feature components based on spec analysis\n6. Handles authentication changes\n7. Registers plugin in presets\n8. Adds unit and E2E tests\n9. Updates documentation\n10. Runs full test suite\n\n**Key Features:**\n- ✅ **Quick Reference** section for rapid development\n- ✅ Comprehensive specification analysis workflow using WebFetch\n- ✅ Detailed mapping table from spec changes → components (15+ change types)\n- ✅ Real examples from OAS 3.1 implementation (6 detailed examples)\n- ✅ Iterative spec-driven development approach\n- ✅ Component-by-component verification checklist\n- ✅ Best practices for continuous spec reference\n- ✅ WebFetch query templates for spec analysis\n- ✅ Common pitfalls and solutions\n- ✅ Pre-submit checklist\n\n**Based on:**\nThis skill follows the patterns established by the OAS 3.1 implementation (commit history analyzed from `src/core/plugins/oas31/`).\n\n**Key patterns:**\n- Plugin-based architecture with Redux state management\n- Selector factories for version-specific logic\n- Component wrapping for conditional rendering\n- afterLoad lifecycle hooks for function overrides\n- Plugin loading order (new version loaded LAST)\n\n**Prerequisites:**\n- Understanding of Swagger UI plugin architecture\n- Access to the new OAS specification document\n- All existing tests passing\n\n**Example workflow:**\n\nAdding OAS 4.0 support:\n```\n# Start the skill\n/add-oas-support --version 4.0 --type major\n\n# Claude will:\n# 1. Ask about new features in OAS 4.0\n# 2. Create plugin directory structure\n# 3. Generate boilerplate code\n# 4. Guide through implementation\n# 5. Add tests\n# 6. Update documentation\n# 7. Verify build\n```\n\n## Creating New Skills\n\nTo create a new skill for Swagger UI:\n\n1. Create a markdown file in `.claude/skills/`\n2. Add frontmatter with skill metadata:\n   ```yaml\n   ---\n   name: skill-name\n   description: Brief description\n   args:\n     param1:\n       description: \"Parameter description\"\n       required: true\n       type: string\n   ---\n   ```\n3. Write comprehensive instructions following the patterns in existing skills\n4. Document common pitfalls and best practices\n5. Include code templates with placeholders\n6. Add to this README\n\n## Skill Development Guidelines\n\nWhen creating skills for Swagger UI:\n\n1. **Follow project conventions:**\n   - No semicolons\n   - Double quotes\n   - @prettier pragma in all new files\n   - .jsx extension for React components\n\n2. **Use the plugin architecture:**\n   - Don't modify core unnecessarily\n   - Follow established patterns\n   - Load new plugins at the end of presets\n\n3. **Include comprehensive tests:**\n   - Unit tests for logic\n   - Component tests for UI\n   - E2E tests for integration\n\n4. **Document thoroughly:**\n   - Update CLAUDE.md\n   - Update relevant docs\n   - Add inline JSDoc comments\n\n5. **Security first:**\n   - Use DOMPurify for HTML\n   - Validate all input\n   - Follow OWASP guidelines\n\n## Contributing\n\nTo contribute new skills:\n\n1. Fork the repository\n2. Create skill in `.claude/skills/`\n3. Test thoroughly\n4. Update this README\n5. Submit pull request\n\n## Resources\n\n- **CLAUDE.md** - Comprehensive codebase guide\n- **Plugin API** - `docs/customization/plugin-api.md`\n- **Development Setup** - `docs/development/setting-up.md`\n- **Contributing Guide** - https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md\n","CLAUDE.md":"# CLAUDE.md - Swagger UI Codebase Guide\n\n> **Last Updated:** 2026-02-24\n> **Version:** 5.32.0 (in development)\n> **Purpose:** Comprehensive guide for AI assistants working with the Swagger UI codebase\n\n---\n\n## Table of Contents\n\n1. [Repository Overview](#repository-overview)\n2. [Project Architecture](#project-architecture)\n3. [Development Setup](#development-setup)\n4. [Build System](#build-system)\n5. [Testing Infrastructure](#testing-infrastructure)\n6. [Code Style & Conventions](#code-style--conventions)\n7. [Git Workflow](#git-workflow)\n8. [Plugin Architecture](#plugin-architecture)\n9. [Key Files & Directories](#key-files--directories)\n10. [Common Workflows](#common-workflows)\n11. [Important Guidelines](#important-guidelines)\n\n---\n\n## Repository Overview\n\n### What is Swagger UI?\n\nSwagger UI is a tool that allows developers to visualize and interact with API resources without having implementation logic in place. It's automatically generated from OpenAPI (formerly Swagger) Specification documents.\n\n### Multi-Package Monorepo Structure\n\nThis repository publishes **three different npm packages**:\n\n1. **swagger-ui** (main package)\n   - Traditional npm module for single-page applications\n   - Entry: `dist/swagger-ui.js`\n   - ES Module: `dist/swagger-ui-es-bundle-core.js`\n   - Includes dependency resolution via Webpack/Browserify\n\n2. **swagger-ui-dist** (distribution package)\n   - Dependency-free module for server-side projects\n   - Published separately via GitHub workflow\n   - Template location: `swagger-ui-dist-package/`\n\n3. **swagger-ui-react** (React component)\n   - React wrapper component\n   - Location: `flavors/swagger-ui-react/`\n   - Uses React hooks\n   - Released separately via GitHub workflow\n\n### OpenAPI Specification Compatibility\n\n- **Current Support:** OpenAPI 2.0, 3.0.x, 3.1.x\n- **Latest Version:** v5.31.0 (supports up to OpenAPI 3.1.2)\n\n### License\n\nApache 2.0 - See LICENSE and NOTICE files for details.\n\n---\n\n## Project Architecture\n\n### Technology Stack\n\n**Core Framework:**\n- React 18 (>=16.8.0 <20) - UI components\n- Redux 5.0.1 - State management\n- Redux Immutable 4.0.0 - Immutable state\n- Immutable.js 3.x - Immutable data structures\n- React Redux 9.2.0 - React-Redux bindings\n\n**API & Schema Processing:**\n- swagger-client 3.36.0 - OpenAPI client\n- js-yaml 4.1.1 - YAML parsing\n- remarkable 2.0.1 - Markdown rendering\n\n**Security:**\n- DOMPurify 3.2.6 - HTML sanitization (CRITICAL for XSS prevention)\n- serialize-error 8.1.0 - Error serialization\n\n**Build Tools:**\n- Webpack 5.97.1 - Module bundling\n- Babel 7.26.x - JavaScript transpilation\n- sass-embedded 1.86.0 - SCSS compilation\n- PostCSS - CSS processing\n\n**Testing:**\n- Jest 29.7.0 - Unit testing\n- Cypress 14.2.0 - E2E testing\n- Enzyme 3.11.0 - React component testing\n\n**Development:**\n- ESLint 8.57.0 - JavaScript linting\n- Prettier 3.5.3 - Code formatting\n- Stylelint 16.19.1 - CSS linting\n- Husky 9.1.7 - Git hooks\n- lint-staged 15.5.0 - Pre-commit linting\n\n### Plugin-Based Architecture\n\nSwagger UI uses a **sophisticated plugin system** powered by Redux. The core system (`src/core/system.js`) manages:\n\n- Plugin registration and lifecycle\n- Redux store creation and middleware\n- State plugin combination\n- Action/selector binding\n- Configuration management\n\n**26 Core Plugins** (in `src/core/plugins/`):\n- `auth` - Authentication handling\n- `configs` - Configuration management\n- `deep-linking` - URL-based navigation\n- `download-url` - Spec downloading\n- `err` - Error handling and transformation\n- `filter` - API filtering\n- `icons` - Icon components\n- `json-schema-2020-12` - JSON Schema 2020-12 support\n- `json-schema-2020-12-samples` - Sample generation\n- `json-schema-5` - JSON Schema Draft 5 support\n- `json-schema-5-samples` - Sample generation for Draft 5\n- `layout` - Layout system\n- `logs` - Logging\n- `oas3` - OpenAPI 3.0.x support\n- `oas31` - OpenAPI 3.1.x support\n- `oas32` - OpenAPI 3.2.x support\n- `on-complete` - Completion callbacks\n- `request-snippets` - Code snippet generation\n- `safe-render` - Safe component rendering\n- `spec` - Specification handling\n- `swagger-client` - API client integration\n- `syntax-highlighting` - Code highlighting\n- `util` - Utilities\n- `versions` - Version detection\n- `view` - View rendering\n- `view-legacy` - Legacy view support\n\n---\n\n## Development Setup\n\n### Prerequisites\n\n- **Node.js:** >=24.22 (Node 24.x recommended, as defined in `.nvmrc`)\n- **npm:** >=11.19.1\n- **Git:** Any version\n- **JDK 7+:** Required for Nightwatch.js integration tests\n\n### Installation Steps\n\n```bash\n# Clone the repository\ngit clone https://github.com/swagger-api/swagger-ui.git\ncd swagger-ui\n\n# Install dependencies\nnpm install\n\n# Initialize Husky (optional, for git hooks)\nnpx husky init\n\n# Start development server\nnpm run dev\n\n# Open http://localhost:3200/\n```\n\n### Development Server\n\nThe `npm run dev` command starts a hot-reloading Webpack dev server on **port 3200**.\n\n### Using Local API Definitions\n\nEdit `dev-helpers/dev-helper-initializer.js` to change the spec URL:\n\n```javascript\n// Replace\nurl: \"https://petstore.swagger.io/v2/swagger.json\",\n\n// With\nurl: \"./examples/your-local-api-definition.yaml\",\n```\n\n**Important:** Local files must be in the `dev-helpers/` directory or subdirectory. Use `dev-helpers/examples/` (already in `.gitignore`).\n\n---\n\n## Build System\n\n### Babel Environments\n\nThree Babel environments configured in `babel.config.js`:\n\n1. **development/production** - Browser builds with `modules: \"auto\"`\n2. **commonjs** - CommonJS modules with `modules: \"commonjs\"` for Node.js\n3. **esm** - ES modules with `modules: false` for modern bundlers\n\n### Babel Aliases\n\n```javascript\n{\n  root: \".\",\n  core: \"./src/core\"\n}\n```\n\n### Browserslist Environments\n\nDefined in `.browserslistrc`:\n\n- `[browser-production]` - Production browser targets\n- `[browser-development]` - Latest Chrome, Firefox, Safari\n- `[isomorphic-production]` - Browser + Node targets\n- `[node-production]` - Maintained Node versions\n- `[node-development]` - Node 24\n\n### Build Commands\n\n```bash\n# Full build (stylesheets + all bundles)\nnpm run build\n\n# Individual builds\nnpm run build:core              # Core bundle (browser)\nnpm run build:bundle            # Isomorphic bundle\nnpm run build:standalone        # Standalone preset\nnpm run build:es:bundle         # ES module bundle\nnpm run build:es:bundle:core    # ES module core\nnpm run build-stylesheets       # CSS only\n\n# Clean build artifacts\nnpm run clean\n```\n\n### Build Output (dist/)\n\n- `swagger-ui.js` - Core bundle (CommonJS)\n- `swagger-ui.css` - Compiled styles\n- `swagger-ui-bundle.js` - Isomorphic bundle\n- `swagger-ui-standalone-preset.js` - Standalone preset\n- `swagger-ui-es-bundle.js` - ES module bundle\n- `swagger-ui-es-bundle-core.js` - ES module core\n- `oauth2-redirect.html` - OAuth2 redirect page\n\n### Webpack Configurations\n\nLocated in `webpack/` directory:\n\n- `_config-builder.js` - Base configuration\n- `core.js` - Core build\n- `bundle.js` - Bundle build\n- `standalone.js` - Standalone build\n- `es-bundle.js` - ES bundle\n- `es-bundle-core.js` - ES core bundle\n- `stylesheets.js` - CSS build\n- `dev.js` - Development server\n- `dev-e2e.js` - E2E testing server\n\n---\n\n## Testing Infrastructure\n\n### Unit Tests (Jest)\n\n**Configuration:** `config/jest/jest.unit.config.js`\n\n**Environment:** jsdom (simulates browser environment)\n\n**Location:** `test/unit/`\n\n**Command:**\n```bash\nnpm run test:unit\n```\n\n**Key Features:**\n- 37 unit test files\n- Tests for core plugins, components, system\n- XSS security tests\n- Silent mode enabled by default (set to `false` for console output)\n- Module name mapper for SVG and standalone imports\n- Transform ignore patterns for node_modules exceptions\n\n**Setup Files:**\n- `test/unit/jest-shim.js` - Polyfills and shims\n- `test/unit/setup.js` - Test environment setup\n\n### E2E Tests (Cypress)\n\n**Configuration:** `cypress.config.js`\n\n**Location:** `test/e2e-cypress/`\n\n**Base URL:** http://localhost:3230/\n\n**Commands:**\n```bash\n# Run all E2E tests\nnpm run cy:ci\n\n# Interactive Cypress runner\nnpm run cy:dev\n\n# Headless run\nnpm run cy:run\n\n# Start servers and run tests\nnpm run cy:start     # Starts webpack + mock API\n```\n\n**Structure:**\n- `test/e2e-cypress/e2e/` - Test specs (99 test files)\n- `test/e2e-cypress/static/` - Test fixtures and documents\n- `test/e2e-cypress/support/` - Test helpers and commands\n\n**Test Categories:**\n- `a11y/**/*cy.js` - Accessibility tests\n- `security/**/*cy.js` - Security tests\n- `bugs/**/*cy.js` - Bug regression tests\n- `features/**/*cy.js` - Feature tests\n\n**Mock API Server:**\n```bash\nnpm run cy:mock-api  # JSON Server on port 3204\n```\n\n### Artifact Tests\n\n**Configuration:** `config/jest/jest.artifact.config.js`\n\n**Purpose:** Verify build artifacts export correctly\n\n**Command:**\n```bash\nnpm run test:artifact\n```\n\n### Complete Test Suite\n\n```bash\nnpm test  # Runs: lint-errors + test:unit + cy:ci\n```\n\n### CI/CD Testing\n\n**GitHub Actions Workflow:** `.github/workflows/nodejs.yml`\n\n**Two Jobs:**\n1. **build** - Lint, unit tests, build, artifact tests\n2. **e2e-tests** - Cypress tests (matrix strategy with 3 containers)\n\n**Branches:** `main`, `next`\n\n---\n\n## Code Style & Conventions\n\n### ESLint Configuration\n\n**File:** `.eslintrc.js`\n\n**Parser:** `@babel/eslint-parser`\n\n**Key Rules:**\n- `semi: [2, \"never\"]` - **No semicolons**\n- `quotes: [2, \"double\"]` - **Double quotes** (allow template literals)\n- `no-unused-vars: 2` - Error on unused variables\n- `camelcase: [\"error\"]` - Enforce camelCase (with exceptions for UNSAFE_, request generators, etc.)\n- `no-console: [2, {allow: [\"warn\", \"error\"]}]` - Only `console.warn` and `console.error` allowed\n- `react/jsx-no-bind: 1` - Warning for JSX bind\n- `react/jsx-filename-extension: 2` - JSX only in `.jsx` files\n- `import/no-extraneous-dependencies: 2` - Error on extraneous dependencies\n\n**Extends:**\n- `eslint:recommended`\n- `plugin:react/recommended`\n- `plugin:prettier/recommended`\n\n### Prettier Configuration\n\n**File:** `.prettierrc.yaml`\n\n**Settings:**\n```yaml\nsemi: false              # No semicolons\ntrailingComma: es5       # ES5 trailing commas\nendOfLine: lf            # Unix line endings\nrequirePragma: true      # Require @prettier pragma\ninsertPragma: true       # Insert @prettier pragma\n```\n\n**IMPORTANT:** Prettier requires `@prettier` pragma comment at the top of files:\n```javascript\n/**\n * @prettier\n */\n```\n\n### Stylelint Configuration\n\n**File:** `stylelint.config.js`\n\n**Custom Syntax:** `postcss-scss`\n\n**Rules:**\n- Uses `stylelint-prettier` plugin\n- Prettier integration without pragma requirement\n\n### Pre-commit Hooks\n\n**Husky:** `.husky/pre-commit` runs `npx lint-staged`\n\n**Lint-staged Configuration:** `.lintstagedrc`\n```json\n{\n  \"*.{js,jsx}\": [\"eslint --max-warnings 0\"],\n  \"*.scss\": [\"stylelint '**/*.scss'\"]\n}\n```\n\n**Critical:** All staged JS/JSX/SCSS files are linted with **zero warnings tolerance**.\n\n### File Structure Conventions\n\n**TypeScript (REQUIRED for all new files):**\n- All new source files must be written in TypeScript (`.ts` / `.tsx`)\n- Use `.tsx` for React components, `.ts` for all other modules\n- Existing `.js` / `.jsx` files are not required to be migrated, but new code must not be added in plain JavaScript\n\n**Components:**\n- Location: `src/core/components/`\n- Extension: `.tsx` (React components — TypeScript)\n- Format: PascalCase for component names\n\n**Styles:**\n- Location: `src/style/`\n- Extension: `.scss`\n- Format: SCSS with PostCSS processing\n- Dark mode: `_dark-mode.scss`\n\n**Tests:**\n- Unit: `test/unit/` (mirrors source structure)\n- E2E: `test/e2e-cypress/e2e/`\n- Naming: `*.test.ts`, `*.spec.ts`, `*.cy.ts` (Cypress) — use `.tsx` variants when JSX is involved\n\n---\n\n## Git Workflow\n\n### Branch Strategy\n\n**Main Branches:**\n- `main` - Production releases\n- `next` - Next version development\n\n**Feature Branches:**\n- Should branch from `main` or `next`\n- Use descriptive names\n\n### Commit Conventions\n\n**Format:** Conventional Commits (enforced by commitlint)\n\n**Structure:**\n```\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n```\n\n**Types:**\n- `feat` - New feature\n- `fix` - Bug fix\n- `docs` - Documentation changes\n- `style` - Code style changes (formatting)\n- `refactor` - Code refactoring\n- `test` - Test additions/changes\n- `chore` - Build/tooling changes\n- `perf` - Performance improvements\n\n**Example:**\n```\nfeat(oas3): add support for OpenAPI 3.1.1 callbacks\n\nImplement callback rendering for OAS 3.1.1 specifications\nwith proper schema resolution and example generation.\n\nFixes #12345\n```\n\n### Pull Request Process\n\n**Template:** `.github/pull_request_template.md`\n\n**Required Sections:**\n1. **Description** - Detailed change description\n2. **Motivation and Context** - Why the change is needed\n3. **How Has This Been Tested?** - Manual testing details\n4. **Screenshots** - If UI changes\n\n**Checklist:**\n- [ ] Code type (no code/dependencies/bug fix/improvement/feature)\n- [ ] Breaking changes identification\n- [ ] Documentation updates\n- [ ] Test coverage\n- [ ] All tests passing\n\n**CI Checks:**\n- ESLint (error-only mode)\n- Unit tests (Jest)\n- Build verification\n- Artifact tests\n- E2E tests (Cypress)\n\n### Release Process\n\n**Tool:** release-it with conventional-changelog\n\n**Command:**\n```bash\nnpm run automated-release\n```\n\n**Workflows:**\n- `.github/workflows/release-swagger-ui.yml`\n- `.github/workflows/release-swagger-ui-dist.yml`\n- `.github/workflows/release-swagger-ui-react.yml`\n- `.github/workflows/release-swagger-ui-packagist.yml`\n\n---\n\n## Plugin Architecture\n\n### Core System (`src/core/system.js`)\n\nThe plugin system is the heart of Swagger UI. It uses Redux for state management with a custom plugin registration system.\n\n### Plugin Structure\n\nEach plugin is a JavaScript object/function that returns:\n\n```javascript\n{\n  statePlugins: {\n    [pluginName]: {\n      actions: {},      // Redux actions\n      reducers: {},     // Redux reducers\n      selectors: {},    // Reselect selectors\n      wrapActions: {},  // Action middleware\n      wrapSelectors: {} // Selector middleware\n    }\n  },\n  components: {},       // React components\n  fn: {},              // Utility functions\n  rootInjects: {},     // Root-level injections\n  afterLoad: Function  // Lifecycle hook\n}\n```\n\n### Key Plugin Locations\n\n**Core Plugins:** `src/core/plugins/`\n\nEach plugin has:\n- `index.js` - Main export\n- `actions.js` - Redux actions\n- `reducers.js` - Redux reducers\n- `selectors.js` - State selectors\n- `wrap-actions.js` - Action middleware\n- `wrap-selectors.js` - Selector middleware\n- Component files (`.jsx`)\n\n### Creating a Plugin\n\nSee documentation: `docs/customization/plugin-api.md`\n\n### Cross-Plugin Import Guidelines\n\n**IMPORTANT:** Avoid cross-plugin imports to maintain plugin independence and modularity.\n\n**Pattern to Follow:**\n- Each plugin should be self-contained with its own components, utilities, and functions\n- When OAS version plugins (oas3, oas31, oas32) need similar functionality, create self-contained copies within each plugin\n- Wrap components should import from their own plugin's components, not from other plugins\n\n**Example Structure:**\n```\nsrc/core/plugins/oas32/\n├── json-schema-2020-12-extensions/\n│   ├── components/              # Self-contained components\n│   │   └── keywords/\n│   │       ├── Description.jsx\n│   │       └── Properties.jsx\n│   ├── wrap-components/         # Wrappers for components\n│   │   └── keywords/\n│   │       ├── Description.jsx  # Imports from ../../components/\n│   │       └── Properties.jsx   # Not from ../../../../oas31/\n│   └── fn.js                    # Self-contained utilities\n```\n\n**Why This Matters:**\n- Prevents tight coupling between plugins\n- Makes plugins easier to test in isolation\n- Allows independent versioning and updates\n- Reduces risk of breaking changes across plugins\n- Improves code maintainability\n\n**Exceptions:**\n- Shared core utilities in `src/core/utils/` are acceptable\n- System-level functions in `src/core/system.js` are acceptable\n- Base components in `src/core/components/` are acceptable\n\n### Preset System\n\n**Base Preset:** `src/core/presets/base.js`\n\n**Standalone Preset:** `src/standalone/presets/standalone.js`\n\nPresets are collections of plugins bundled together for specific use cases.\n\n---\n\n## Key Files & Directories\n\n### Critical Source Files\n\n```\nsrc/\n├── core/\n│   ├── system.js                 # Plugin system & Redux store\n│   ├── components/               # 59 React components\n│   ├── plugins/                  # 26 core plugins\n│   ├── presets/                  # Preset configurations\n│   ├── utils/                    # Utility functions\n│   └── config/                   # Configuration system\n├── standalone/\n│   ├── plugins/                  # TopBar, StandaloneLayout\n│   └── presets/                  # Standalone preset\n├── style/                        # SCSS stylesheets\n│   ├── _dark-mode.scss          # Dark mode styles\n│   └── main.scss                # Main stylesheet entry\n└── index.js                      # Main package entry\n```\n\n### Configuration Files\n\n```\n.\n├── package.json                  # Dependencies & scripts\n├── babel.config.js              # Babel configuration\n├── .eslintrc.js                 # ESLint rules\n├── .prettierrc.yaml             # Prettier settings\n├── stylelint.config.js          # Stylelint rules\n├── .browserslistrc              # Browser targets\n├── .nvmrc                       # Node version (24.x)\n├── .lintstagedrc                # Pre-commit linting\n└── cypress.config.js            # Cypress E2E config\n```\n\n### Build & Tooling\n\n```\nwebpack/\n├── _config-builder.js           # Base Webpack config\n├── core.js                      # Core build\n├── bundle.js                    # Bundle build\n├── standalone.js                # Standalone build\n├── es-bundle.js                 # ES bundle build\n├── es-bundle-core.js           # ES core bundle\n├── stylesheets.js              # CSS compilation\n├── dev.js                       # Dev server\n└── dev-e2e.js                  # E2E dev server\n\nconfig/jest/\n├── jest.unit.config.js          # Unit test config\n└── jest.artifact.config.js      # Artifact test config\n```\n\n### Documentation\n\n```\ndocs/\n├── usage/\n│   ├── installation.md\n│   ├── configuration.md\n│   ├── cors.md\n│   ├── oauth2.md\n│   ├── deep-linking.md\n│   ├── version-detection.md\n│   └── limitations.md\n├── customization/\n│   ├── overview.md\n│   ├── plugin-api.md\n│   └── custom-layout.md\n└── development/\n    ├── setting-up.md\n    └── scripts.md\n```\n\n### Testing\n\n```\ntest/\n├── unit/                        # Jest unit tests (37 files)\n│   ├── setup.js                # Test environment setup\n│   └── jest-shim.js           # Polyfills\n├── e2e-cypress/                 # Cypress E2E tests (99 files)\n│   ├── e2e/                    # Test specs\n│   ├── static/                 # Fixtures\n│   └── support/                # Helpers\n└── e2e-selenium/               # Legacy Selenium tests\n```\n\n### Distribution\n\n```\nflavors/\n└── swagger-ui-react/            # React component wrapper\n\nswagger-ui-dist-package/         # Template for dist package\n\ndist/                            # Build output (generated)\n├── swagger-ui.js\n├── swagger-ui.css\n├── swagger-ui-bundle.js\n├── swagger-ui-standalone-preset.js\n├── swagger-ui-es-bundle.js\n├── swagger-ui-es-bundle-core.js\n└── oauth2-redirect.html\n```\n\n---\n\n## Common Workflows\n\n### Making Code Changes\n\n1. **Read before modifying:**\n   ```bash\n   # ALWAYS read files before editing them\n   # Understand the existing code structure\n   ```\n\n2. **Follow the style guide:**\n   - Use double quotes\n   - No semicolons\n   - Add `@prettier` pragma to new files\n   - Use `.jsx` extension for React components\n\n3. **Run linters:**\n   ```bash\n   npm run lint          # Check for errors and warnings\n   npm run lint-fix      # Auto-fix JavaScript issues\n   npm run lint-styles   # Check SCSS\n   npm run lint-styles-fix  # Auto-fix SCSS\n   ```\n\n4. **Test your changes:**\n   ```bash\n   npm run test:unit     # Run unit tests\n   npm run cy:dev        # Interactive E2E testing\n   npm run build         # Verify build works\n   npm run test:artifact # Verify artifacts\n   ```\n\n### Adding a New Component\n\n1. Create component in `src/core/components/` or appropriate plugin directory\n2. Use `.tsx` extension (TypeScript — required for all new files)\n3. Add `@prettier` pragma\n4. Follow React best practices (functional components, hooks)\n5. Add PropTypes validation\n6. Create corresponding test in `test/unit/`\n7. Export from plugin's `index.js` if needed\n\n### Adding a New Plugin\n\n1. Create directory in `src/core/plugins/[plugin-name]/`\n2. Create `index.ts` with plugin structure (TypeScript — required for all new files)\n3. Add actions, reducers, selectors as needed\n4. Register plugin in preset (e.g., `src/core/presets/base.js`)\n5. Add tests in `test/unit/core/plugins/[plugin-name]/`\n6. Document the plugin\n\n### Fixing a Bug\n\n1. **Reproduce the bug:**\n   - Add a failing test in `test/unit/` or `test/e2e-cypress/`\n   - Document reproduction steps\n\n2. **Fix the issue:**\n   - Make minimal changes to fix the bug\n   - Avoid refactoring unless necessary\n   - Ensure the test now passes\n\n3. **Verify:**\n   ```bash\n   npm run test:unit\n   npm run build\n   npm run test:artifact\n   ```\n\n4. **Create PR:**\n   - Reference the issue number\n   - Include before/after behavior\n   - Add screenshots if UI-related\n\n### Adding a Feature\n\n1. **Plan the feature:**\n   - Review existing architecture\n   - Identify affected plugins/components\n   - Consider OpenAPI spec compatibility\n\n2. **Implement:**\n   - Follow plugin architecture patterns\n   - Add configuration options if needed\n   - Update presets if necessary\n\n3. **Test thoroughly:**\n   - Unit tests for logic\n   - Component tests for UI\n   - E2E tests for integration\n   - Test with various OpenAPI specs\n\n4. **Document:**\n   - Update `docs/` if user-facing\n   - Add JSDoc comments for APIs\n   - Update README if needed\n\n### Security Considerations\n\n1. **XSS Prevention:**\n   - ALWAYS use DOMPurify for user-provided HTML\n   - Sanitize all external input\n   - Review `test/unit/xss/` for examples\n   - Never use `dangerouslySetInnerHTML` without sanitization\n\n2. **Input Validation:**\n   - Validate API responses\n   - Handle malformed OpenAPI specs gracefully\n   - Check for prototype pollution\n\n3. **Dependency Security:**\n   ```bash\n   npm run security-audit     # Run security audit\n   ```\n\n### Working with OpenAPI Specs\n\n**Testing Different Versions:**\n- OAS 2.0: Use `src/core/plugins/swagger-client/`\n- OAS 3.0.x: Use `src/core/plugins/oas3/`\n- OAS 3.1.x: Use `src/core/plugins/oas31/`\n- OAS 3.2.x: Use `src/core/plugins/oas32/`\n\n**Adding Test Specs:**\n- Add to `test/e2e-cypress/static/documents/`\n- Reference in E2E tests\n\n---\n\n## Important Guidelines\n\n### DO's ✅\n\n1. **Always read files before modifying them**\n2. **Write all new files in TypeScript** - use `.ts` for modules, `.tsx` for React components\n3. **Follow the no-semicolon convention**\n4. **Use double quotes for strings**\n5. **Add `@prettier` pragma to all new files**\n6. **Use `.tsx` extension for new React components** (TypeScript JSX)\n7. **Write tests for new features and bug fixes**\n8. **Run linters before committing** (automatic via husky)\n9. **Use DOMPurify for HTML sanitization**\n10. **Follow conventional commit format**\n11. **Update documentation for user-facing changes**\n12. **Test with multiple OpenAPI spec versions**\n13. **Check browser compatibility** (see `.browserslistrc`)\n14. **Use the plugin architecture** - don't modify core unnecessarily\n15. **Preserve backward compatibility** unless explicitly breaking\n16. **Run full test suite before submitting PR**\n17. **Keep plugins self-contained** - avoid cross-plugin imports (see [Cross-Plugin Import Guidelines](#cross-plugin-import-guidelines))\n\n### DON'Ts ❌\n\n1. **Don't write new files in plain JavaScript** - all new files must be TypeScript (`.ts` / `.tsx`)\n2. **Don't use semicolons** - project convention\n3. **Don't use single quotes** - use double quotes\n4. **Don't skip the @prettier pragma** - required for formatting\n5. **Don't put React in `.ts` files** - use `.tsx` for JSX\n6. **Don't commit files in `dev-helpers/`** (except core files)\n7. **Don't commit build artifacts** (`dist/` is gitignored)\n8. **Don't skip tests** - they run in CI\n9. **Don't bypass ESLint** - pre-commit hook enforces\n10. **Don't use `console.log`** - only `console.warn` and `console.error`\n11. **Don't render unsanitized HTML** - XSS vulnerability\n12. **Don't modify `package-lock.json` manually**\n13. **Don't push directly to `main` or `next`**\n14. **Don't ignore Cypress test failures**\n15. **Don't add dependencies without justification**\n16. **Don't break the build** - verify with `npm run build`\n17. **Don't import from other plugins** - create self-contained copies instead (e.g., don't import from `oas31` in `oas32`)\n\n### When Working with AI Assistants\n\n**Before Making Changes:**\n1. Read the affected files completely\n2. Understand the plugin architecture\n3. Check for existing tests\n4. Review related documentation\n\n**During Development:**\n1. Make minimal, focused changes\n2. Follow existing patterns in the codebase\n3. Add tests alongside code changes\n4. Run linters frequently\n\n**After Changes:**\n1. Verify all tests pass\n2. Check build completes successfully\n3. Test artifact exports\n4. Review for security issues\n5. Update relevant documentation\n\n**Communication:**\n- Be explicit about file locations\n- Use line number references (e.g., `src/core/system.js:96`)\n- Provide context for changes\n- Mention any breaking changes clearly\n\n### Performance Considerations\n\n1. **Immutable.js:**\n   - Use Immutable data structures for state\n   - Use `.toJS()` sparingly (expensive)\n   - Prefer Immutable operations\n\n2. **React:**\n   - Use React.memo for pure components\n   - Implement shouldComponentUpdate for class components\n   - Avoid inline function definitions in render\n\n3. **Redux:**\n   - Use reselect for memoized selectors\n   - Keep reducers pure and fast\n   - Avoid large state trees\n\n4. **Bundle Size:**\n   - Check bundle size with `npm run deps-size`\n   - Review dependency licenses with `npm run deps-license`\n   - Consider code splitting for large features\n\n### Debugging Tips\n\n**Development Server:**\n```bash\nnpm run dev\n# Open http://localhost:3200/\n# Hot reload enabled\n# Unminified stack traces\n```\n\n**Redux DevTools:**\n- Extension supported\n- State inspection available\n- Time-travel debugging\n\n**Cypress Interactive Mode:**\n```bash\nnpm run cy:dev\n# Visual test runner\n# Step-through debugging\n# Network inspection\n```\n\n**Jest Watch Mode:**\n```bash\nnpm run test:unit -- --watch\n# Re-run on file changes\n# Filter by file name or test name\n```\n\n**Source Maps:**\n- Generated for all builds\n- Enable in browser DevTools\n- Original source debugging\n\n---\n\n## Quick Reference\n\n### Essential Commands\n\n```bash\n# Development\nnpm run dev              # Start dev server (port 3200)\nnpm start                # Static file server (port 3002)\n\n# Building\nnpm run build            # Full production build\nnpm run clean            # Remove dist/\n\n# Testing\nnpm test                 # Full test suite (lint + unit + E2E)\nnpm run test:unit        # Jest unit tests\nnpm run cy:dev           # Cypress interactive\nnpm run cy:ci            # Cypress CI mode\nnpm run test:artifact    # Artifact verification\n\n# Linting\nnpm run lint             # ESLint (errors + warnings)\nnpm run lint-errors      # ESLint (errors only)\nnpm run lint-fix         # Auto-fix ESLint issues\nnpm run lint-styles      # Stylelint\nnpm run lint-styles-fix  # Auto-fix Stylelint issues\n\n# Security\nnpm run security-audit   # Run npm audit\n\n# Dependencies\nnpm run deps-check       # Size and license report\n```\n\n### File Paths\n\n```\nCore System:           src/core/system.js\nMain Entry:            src/index.js\nReact Entry:           flavors/swagger-ui-react/index.jsx\nComponents:            src/core/components/\nPlugins:               src/core/plugins/\nStyles:                src/style/\nTests (Unit):          test/unit/\nTests (E2E):           test/e2e-cypress/e2e/\nBuild Output:          dist/\n```\n\n### Port Reference\n\n- **3200** - Development server (webpack-dev-server)\n- **3002** - Static file server (local-web-server)\n- **3204** - Mock API server (json-server)\n- **3230** - E2E test server (webpack-dev-server)\n\n---\n\n## Additional Resources\n\n### Documentation\n\n- **Setup Guide:** `docs/development/setting-up.md`\n- **Scripts Reference:** `docs/development/scripts.md`\n- **Plugin API:** `docs/customization/plugin-api.md`\n- **Configuration:** `docs/usage/configuration.md`\n- **OAuth2 Setup:** `docs/usage/oauth2.md`\n\n### External Links\n\n- **Homepage:** https://swagger.io/tools/swagger-ui/\n- **Repository:** https://github.com/swagger-api/swagger-ui\n- **npm (main):** https://www.npmjs.com/package/swagger-ui\n- **npm (dist):** https://www.npmjs.com/package/swagger-ui-dist\n- **npm (react):** https://www.npmjs.com/package/swagger-ui-react\n- **OpenAPI Spec:** https://spec.openapis.org/\n\n### Community\n\n- **Issues:** https://github.com/swagger-api/swagger-ui/issues\n- **Good First Issues:** https://github.com/swagger-api/swagger-ui/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%22\n- **Security:** security@swagger.io\n- **Contributing:** https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md\n\n---\n\n**Note:** This document should be updated whenever major architectural changes, new conventions, or significant workflows are introduced to the codebase.\n",".claude/skills/add-oas-support.md":"---\nname: add-oas-support\ndescription: Add support for a new OpenAPI Specification version to Swagger UI\nargs:\n  version:\n    description: \"OpenAPI version to add support for (e.g., 3.2, 4.0)\"\n    required: true\n    type: string\n  type:\n    description: \"Version type: 'major' for new major version, 'minor' for patch/minor\"\n    required: false\n    type: string\n    default: \"minor\"\n---\n\n# Add OpenAPI Specification Version Support\n\nThis skill guides you through adding support for a new OpenAPI Specification (OAS) version to Swagger UI, following the established architectural patterns from OAS 3.1 implementation.\n\n---\n\n## 📌 Quick Reference\n\n> **New to this skill?** Skip to [Prerequisites](#prerequisites) for the full guide.\n> **Already familiar?** Use this quick reference for rapid development.\n\n### 🚀 Quick Start\n\n```bash\n# Major version (e.g., OAS 4.0)\n/add-oas-support --version 4.0 --type major\n\n# Minor version (e.g., OAS 3.2)\n/add-oas-support --version 3.2 --type minor\n```\n\n### 📋 Essential Checklist\n\n#### Phase 1: Specification Analysis ⭐ MOST IMPORTANT\n- [ ] Access official spec at **https://spec.openapis.org/oas/v{VERSION}/**\n- [ ] Use WebFetch to analyze spec systematically\n- [ ] Create specification change document\n- [ ] Map changes to components using [mapping table](#step-1d-map-specification-changes-to-swagger-ui-components)\n\n#### Phase 2: Implementation\n- [ ] Create plugin directory structure\n- [ ] Implement version detection (`isOAS{VERSION}`)\n- [ ] Create selector factories\n- [ ] Implement components for each spec change\n- [ ] Wrap existing components if modified\n- [ ] Register plugin in preset (LAST position)\n\n#### Phase 3: Testing & Documentation\n- [ ] Add unit tests\n- [ ] Add E2E tests with spec examples\n- [ ] Update documentation\n- [ ] Verify build & run full test suite\n\n### 🔍 WebFetch Queries for Spec Analysis\n\n```javascript\n// 1. Fetch main spec differences\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all new top-level fields, modified fields, and removed fields compared to version {PREV_VERSION}\"\n)\n\n// 2. Analyze new feature\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Describe the '{NEW_FIELD}' field: structure, type, purpose, required/optional, and provide examples\"\n)\n\n// 3. Check JSON Schema version\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"What JSON Schema version does this use? List changes from {PREV_JSON_SCHEMA_VERSION}\"\n)\n\n// 4. Security schemes\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all security scheme types, highlighting new or changed types\"\n)\n```\n\n### 🗺️ Spec Change → Component Mapping (Quick)\n\n| Spec Change | Component Action | File Location |\n|-------------|------------------|---------------|\n| **New top-level field (Object)** | Create new component | `components/{field}.jsx` |\n| **New top-level field (String)** | Add to info or create display | `components/{field}.jsx` |\n| **Modified Info object** | Wrap Info component | `wrap-components/info.jsx` |\n| **New info subfield** | Create component + wrap Info | `components/info-{field}.jsx` |\n| **New auth type** | Create auth component | `components/auth/{type}.jsx` |\n| **Modified security** | Wrap auth selector | `auth-extensions/wrap-selectors.js` |\n| **New operation field** | Extend Operation/selector | `spec-extensions/selectors.js` |\n| **JSON Schema keyword** | Create keyword component | `json-schema-{V}-extensions/` |\n| **JSON Schema version** | Create entire new plugin | `plugins/json-schema-{V}/` |\n\nSee [full mapping table with examples](#step-1d-map-specification-changes-to-swagger-ui-components) for detailed guidance.\n\n### 📝 Component Implementation Pattern\n\n**For each new feature:**\n\n1. **Check spec first:**\n   ```javascript\n   WebFetch(url, \"Describe {field} structure, type, examples\")\n   ```\n\n2. **Create selector:**\n   ```javascript\n   // spec-extensions/selectors.js\n   export const selectNewField = createSelector(\n     (state) => state,\n     (state) => state.getIn([\"spec\", \"json\", \"newField\"])\n   )\n   ```\n\n3. **Create component:**\n   ```javascript\n   // components/new-field.jsx\n   const NewField = ({ specSelectors, getComponent }) => {\n     const data = specSelectors.selectNewField()\n     if (!data) return null\n     return <div>{/* render based on spec structure */}</div>\n   }\n   ```\n\n4. **Register in plugin:**\n   ```javascript\n   // index.js\n   components: { NewField },\n   statePlugins: {\n     spec: {\n       selectors: {\n         selectNewField: createOnlyOAS{V}Selector(selectNewField)\n       }\n     }\n   }\n   ```\n\n5. **Add tests** (unit + E2E with spec examples)\n\n### ⚠️ Common Pitfalls\n\n1. ❌ **Guessing field structure** → ✅ Always check spec with WebFetch\n2. ❌ **Forgetting @prettier pragma** → ✅ Add to all new files\n3. ❌ **Wrong plugin load order** → ✅ New plugin LAST in preset\n4. ❌ **Using semicolons** → ✅ No semicolons (project convention)\n5. ❌ **Single quotes** → ✅ Use double quotes\n6. ❌ **Skipping spec examples** → ✅ Use as test fixtures\n7. ❌ **Hardcoded assumptions** → ✅ Verify everything in spec\n8. ❌ **`props.Ori` in ComponentWrapper** → ✅ Use `props.originalComponent` (see Pattern 3)\n9. ❌ **Copying entire Info component for minor version** → ✅ Use OpenAPIVersion wrapper + `getComponent(\"OAS{PREV}Info\")`\n10. ❌ **OAS{VERSION} logic in OAS{PREV} plugin** → ✅ Each version's logic lives in its own plugin\n11. ❌ **`isOAS{PREV}` wrapper on minor version** → ✅ Only add if regex overlaps; minor bumps don't need it\n12. ❌ **New HTTP method in core `validOperationMethods`** → ✅ Add to `OPERATION_METHODS` + wrap with `createOnlyOAS{VERSION}SelectorWrapper`\n13. ❌ **Assuming new OAS meta-schema = new JSON Schema dialect** → ✅ Verify — OAS 3.2 still uses JSON Schema 2020-12\n14. ❌ **Inline version guard in wrap-components** → ✅ Always use `createOnlyOAS{VERSION}ComponentWrapper`; never write `(Original, system) => (props) => { if (...isOAS{VERSION}...) }` by hand — even expanding an existing guard (`isOAS31 || isOAS32`) is wrong; add dedicated wrap-components in the new plugin instead\n\n### ✅ Pre-Submit Checklist\n\n- [ ] All spec changes mapped to components\n- [ ] All components reference spec in comments\n- [ ] Tests use examples from spec\n- [ ] Version detection regex correct\n- [ ] Plugin loaded last in preset\n- [ ] All tests passing (lint + unit + E2E)\n- [ ] Build completes successfully\n- [ ] Documentation updated\n- [ ] No semicolons, double quotes everywhere\n- [ ] @prettier pragma in all new files\n\n### 📚 Quick Links\n\n- **OAS Specs:** https://spec.openapis.org/\n- **OAS 3.1:** https://spec.openapis.org/oas/v3.1.0/\n- **OAS 3.0:** https://spec.openapis.org/oas/v3.0.3/\n- **JSON Schema:** https://json-schema.org/\n- **CLAUDE.md:** Complete codebase guide\n\n### 🔖 Full Guide Navigation\n\nNeed detailed guidance? Jump to these sections:\n\n- **[Prerequisites](#prerequisites)** - Setup and requirements\n- **[Architecture Overview](#architecture-overview)** - Plugin system explained\n- **[Key Design Patterns](#key-design-patterns-from-oas-31)** - Code patterns from OAS 3.1\n- **[Step 1: Analyze Specification](#step-1-analyze-new-oas-version-specification)** - ⭐ Complete spec analysis workflow\n  - [1D: Mapping Table](#step-1d-map-specification-changes-to-swagger-ui-components) - 15+ spec change types\n  - [1E: Real Examples](#step-1e-examples-oas-31-specification-changes--components) - 6 detailed examples\n  - [1H: WebFetch Workflow](#step-1h-using-webfetch-to-analyze-specifications) - Spec analysis with WebFetch\n- **[Step 2-17: Implementation](#step-2-create-plugin-directory-structure)** - Complete implementation steps\n- **[Practical Workflow](#practical-workflow-from-spec-to-components)** - End-to-end example\n- **[Best Practices](#best-practices-iterative-spec-driven-development)** - Spec-driven development\n- **[Common Pitfalls](#common-pitfalls)** - What to avoid\n- **[Final Checklist](#final-checklist)** - Pre-submission verification\n\n---\n\n**Remember: The specification at https://spec.openapis.org/ is your source of truth!**\n\n---\n\n## Prerequisites\n\nBefore starting, ensure:\n- You understand the Swagger UI plugin architecture\n- You've read the CLAUDE.md guide\n- You have the OAS specification document for the new version\n- All tests pass: `npm test`\n\n## Architecture Overview\n\nAdding OAS version support involves:\n\n1. **Plugin Creation** - New plugin following established patterns\n2. **Version Detection** - Regex-based version identifier\n3. **Selector Factories** - Conditional logic for version-specific features\n4. **Component Implementation** - New/wrapped components for rendering\n5. **State Management** - Redux selectors/actions for new features\n6. **Lifecycle Hooks** - afterLoad modifications\n7. **Preset Registration** - Plugin loading order\n8. **Testing** - Unit and E2E tests\n9. **Documentation** - Update guides and README\n\n## Key Design Patterns (from OAS 3.1)\n\n### Pattern 1: Version Detection\n```javascript\nexport const isOAS{VERSION} = (jsSpec) => {\n  const oasVersion = jsSpec.get(\"openapi\")\n  return (\n    typeof oasVersion === \"string\" && /^{MAJOR}\\.{MINOR}\\.(?:[1-9]\\d*|0)$/.test(oasVersion)\n  )\n}\n```\n\n### Pattern 2: Selector Factories\n\n**createOnlyOAS{VERSION}Selector** - Features exclusive to this version:\n```javascript\nexport const createOnlyOAS{VERSION}Selector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(system)\n        : selectedValue\n    } else {\n      return null\n    }\n  }\n```\n\n**createOnlyOAS{VERSION}SelectorWrapper** - Override previous versions:\n```javascript\nexport const createOnlyOAS{VERSION}SelectorWrapper =\n  (selector) =>\n  (oriSelector, system) =>\n  (state, ...args) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(oriSelector, system)\n        : selectedValue\n    } else {\n      return oriSelector(...args)\n    }\n  }\n```\n\n### Pattern 3: Component Wrappers\n\n**⚠️ IMPORTANT: `originalComponent` prop name, not `Ori`**\n\n`createOnlyOAS{VERSION}ComponentWrapper` passes the original component as `originalComponent` in props (NOT `Ori` — that's the OAS3/OAS30ComponentWrapFactory convention). Use `const { originalComponent: Ori } = props` to access it.\n\n**Pattern A — Reuse previous version's component via getComponent:**\n```javascript\nconst ComponentWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => {\n  const system = getSystem()\n  const OAS{PREV_VERSION}Component = system.getComponent(\"OAS{PREV_VERSION}Component\", true)\n  return <OAS{PREV_VERSION}Component />\n})\n```\n\n**Pattern B — Render original component with extra props (e.g. version badge):**\n```javascript\n// Use `originalComponent` (NOT `Ori`) — that's the prop name createOnlyOAS{VERSION}ComponentWrapper passes\nconst OpenAPIVersionWrapper = createOnlyOAS{VERSION}ComponentWrapper((props) => {\n  const { originalComponent: Ori } = props\n  return <Ori oasVersion=\"{VERSION}\" />\n})\n```\n\n### Pattern 4: Function Wrapping\n```javascript\nexport const wrapOAS{VERSION}Fn = (fn, system) => {\n  const { fn: systemFn, specSelectors } = system\n  return Object.fromEntries(\n    Object.entries(fn).map(([name, newImpl]) => {\n      const oriImpl = systemFn[name]\n      const impl = (...args) =>\n        specSelectors.isOAS{VERSION}()\n          ? newImpl(...args)\n          : typeof oriImpl === \"function\"\n            ? oriImpl(...args)\n            : undefined\n      return [name, impl]\n    })\n  )\n}\n```\n\n## Implementation Steps\n\n### Step 1: Analyze New OAS Version Specification\n\n**CRITICAL: Always start by reviewing the official specification at https://spec.openapis.org/**\n\n#### 1A. Access the Official Specification\n\n**Primary Resource:** https://spec.openapis.org/\n\n**Available Versions:**\n- OAS 2.0: https://spec.openapis.org/oas/v2.0/\n- OAS 3.0.x: https://spec.openapis.org/oas/v3.0.3/\n- OAS 3.1.x: https://spec.openapis.org/oas/v3.1.0/\n- Future versions will follow the pattern: https://spec.openapis.org/oas/v{MAJOR}.{MINOR}.{PATCH}/\n\n**What to download:**\n1. The specification document (usually in HTML or Markdown format)\n2. JSON Schema definitions (if available)\n3. Example specification files\n4. Change log or migration guide (if available)\n\n#### 1B. Systematic Specification Analysis\n\nUse the WebFetch tool to retrieve and analyze the specification:\n\n```bash\n# Example for analyzing OAS 4.0 (hypothetical)\nWebFetch(\"https://spec.openapis.org/oas/v4.0.0/\", \"List all new top-level fields, objects, and keywords introduced in this version compared to OAS 3.1\")\n```\n\n**Read these sections carefully:**\n\n1. **Version Number Section**\n   - Confirm the exact version format (e.g., \"4.0.0\", \"3.2.0\")\n   - Note any version detection changes\n\n2. **OpenAPI Object (Root Level)**\n   - New top-level fields (e.g., `webhooks` in OAS 3.1)\n   - Modified existing fields\n   - Removed/deprecated fields\n\n3. **Info Object**\n   - New fields (e.g., `summary` in OAS 3.1)\n   - Changes to `license`, `contact`, etc.\n\n4. **Paths Object & Operations**\n   - New operation-level fields\n   - Changes to parameters, request bodies, responses\n   - New callback syntax or features\n\n5. **Components Object**\n   - New component types\n   - Schema changes (especially JSON Schema version)\n   - New security schemes\n\n6. **Security Object**\n   - New authentication types (e.g., `mutualTLS` in OAS 3.1)\n   - Changes to OAuth2 flows\n   - New security-related fields\n\n7. **Schema Object**\n   - JSON Schema version change (critical!)\n   - New keywords (e.g., `examples` vs `example`)\n   - Type system changes\n\n#### 1C. Create Specification Change Document\n\nCreate a structured document listing all changes:\n\n**Template:**\n```markdown\n# OpenAPI {VERSION} Specification Analysis\n\n## Version Information\n- Version: {MAJOR}.{MINOR}.{PATCH}\n- Release Date: YYYY-MM-DD\n- Previous Version: {PREVIOUS_VERSION}\n- JSON Schema Version: Draft {VERSION} or {YEAR}\n\n## New Top-Level Fields\n1. **`newField`** (Type: Object)\n   - Location: Root level\n   - Purpose: Description from spec\n   - Required: Yes/No\n   - Example from spec: {...}\n   - Swagger UI Impact: Needs new component in BaseLayout\n\n## Modified Existing Fields\n1. **`info`**\n   - New subfields: `summary`, `newField`\n   - Changed behavior: Description\n   - Swagger UI Impact: Need to wrap Info component\n\n## New Operation-Level Features\n1. **`newOperationField`**\n   - Purpose: Description\n   - Swagger UI Impact: Extend Operation component\n\n## New Authentication Types\n1. **`newAuthType`**\n   - Type name: \"newAuthType\"\n   - Fields: {...}\n   - Swagger UI Impact: New auth component needed\n\n## JSON Schema Changes\n- Version change: Draft 2020-12 → Draft 2024\n- New keywords: `keyword1`, `keyword2`\n- Removed keywords: `oldKeyword`\n- Swagger UI Impact: New json-schema plugin needed\n\n## Breaking Changes\n1. Removed `x-deprecated-field`\n2. Changed behavior of `existingField`\n3. Required fields now enforced\n\n## Deprecated Features\n1. `oldField` - Use `newField` instead\n2. `oldAuthType` - Use `newAuthType` instead\n\n## Examples from Specification\n- Link to example files\n- Notable edge cases to test\n```\n\n#### 1D. Map Specification Changes to Swagger UI Components\n\n**CRITICAL MAPPING GUIDE:** Use this table to determine what components to create/modify:\n\n| Spec Change Type | Swagger UI Component Type | Location | Example from OAS 3.1 |\n|-----------------|---------------------------|----------|---------------------|\n| **New Top-Level Field (Object)** | New standalone component | `components/{feature-name}.jsx` | `webhooks` → `Webhooks.jsx` |\n| **New Top-Level Field (String/Primitive)** | Add to existing layout component or create info component | `components/{field-name}.jsx` | `jsonSchemaDialect` → `JsonSchemaDialect.jsx` |\n| **Modified Info Object** | Wrap Info component OR create OAS{VERSION}Info | `wrap-components/info.jsx` | `info.summary` → Wrapped InfoContainer |\n| **New Info Subfield** | Create new component, render in Info | `components/info-{field}.jsx` | `info.license.identifier` → OAS31License |\n| **Modified License/Contact** | Wrap component | `wrap-components/license.jsx` | `license.identifier` → Wrapped License |\n| **New Authentication Type** | New auth component | `components/auth/{type}.jsx` | `mutualTLS` → `MutualTLSAuth.jsx` |\n| **Modified Security Scheme** | Wrap auth selector | `auth-extensions/wrap-selectors.js` | mutualTLS → `definitionsToAuthorize` wrapper |\n| **New Operation Field** | Extend Operation or create plugin selector | `spec-extensions/selectors.js` | N/A in OAS 3.1 |\n| **New Callback Feature** | Extend Callbacks component or wrap | `wrap-components/callbacks.jsx` | Enhanced in OAS 3.1 |\n| **New Parameter Type** | Extend Parameters component | `components/parameters/` | N/A in OAS 3.1 |\n| **New Response Feature** | Extend Responses component | `components/responses/` | N/A in OAS 3.1 |\n| **New Media Type Feature** | Modify media-type component or fn | `oas{PREV}-extensions/fn.js` | File upload detection changes |\n| **JSON Schema Keyword** | New keyword component | `json-schema-{VERSION}-extensions/components/keywords/` | `example` → `JSONSchema202012KeywordExample.jsx` |\n| **JSON Schema Version Change** | Entire new plugin + samples plugin | `plugins/json-schema-{VERSION}/` | JSON Schema 2020-12 plugin |\n| **Modified Schema Rendering** | Wrap schema component | `wrap-components/model.jsx` | Models → OAS31Models wrapper |\n| **Version Detection Field** | Update VersionPragmaFilter | `components/version-pragma-filter.jsx` | Updated for isOAS31 |\n| **Deprecated Field** | Remove or add deprecation warning | Component showing warning | N/A in OAS 3.1 |\n\n#### 1E. Examples: OAS 3.1 Specification Changes → Components\n\n**Example 1: `webhooks` Top-Level Field**\n\n**From Spec (OAS 3.1):**\n```yaml\nopenapi: 3.1.0\nwebhooks:\n  newPet:\n    post:\n      requestBody:\n        description: Information about a new pet\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Pet'\n      responses:\n        '200':\n          description: Return a 200 status\n```\n\n**Mapping Decision:**\n- Type: New top-level field (Object containing operations)\n- Location in spec: Root level, same structure as `paths`\n- Swagger UI component: New standalone component\n- File: `src/core/plugins/oas31/components/webhooks.jsx`\n- Rendering: Reuses Operations component to render webhook operations\n- Selector: `selectWebhooks` in `spec-extensions/selectors.js`\n- Layout integration: Added to BaseLayout or StandaloneLayout\n\n**Example 2: `info.summary` Field**\n\n**From Spec (OAS 3.1):**\n```yaml\ninfo:\n  title: My API\n  summary: A brief summary of the API   # NEW in OAS 3.1\n  description: Detailed description...\n  version: 1.0.0\n```\n\n**Mapping Decision:**\n- Type: New subfield in existing Info object\n- Location: `info.summary`\n- Swagger UI component: Wrap existing Info component\n- File: `src/core/plugins/oas31/wrap-components/info.jsx` + `src/core/plugins/oas31/components/info.jsx`\n- Selector: `selectInfoSummary` (if needed)\n- Rendering: Display summary above or below title\n\n**Example 3: `mutualTLS` Authentication Type**\n\n**From Spec (OAS 3.1):**\n```yaml\ncomponents:\n  securitySchemes:\n    myMutualTLS:\n      type: mutualTLS    # NEW in OAS 3.1\n      description: Client certificate authentication\n```\n\n**Mapping Decision:**\n- Type: New authentication scheme type\n- Location: `components.securitySchemes[name].type`\n- Swagger UI component: New auth component\n- File: `src/core/plugins/oas31/components/auth/mutual-tls-auth.jsx`\n- Selector wrapper: `auth-extensions/wrap-selectors.js` → `definitionsToAuthorize`\n- Rendering: Display in authorize modal with certificate upload UI\n\n**Example 4: `license.identifier` Field**\n\n**From Spec (OAS 3.1):**\n```yaml\ninfo:\n  license:\n    name: Apache 2.0\n    identifier: Apache-2.0    # NEW in OAS 3.1 (SPDX ID)\n    url: https://www.apache.org/licenses/LICENSE-2.0.html\n```\n\n**Mapping Decision:**\n- Type: New optional field in license object (alternative to url)\n- Location: `info.license.identifier`\n- Swagger UI component: Wrap License component + create selector\n- File: `src/core/plugins/oas31/wrap-components/license.jsx` + selector in `spec-extensions/selectors.js`\n- Logic: If `identifier` exists, construct URL from SPDX registry\n- Rendering: Make license text a hyperlink to SPDX page\n\n**Example 5: JSON Schema 2020-12 Keywords**\n\n**From Spec (OAS 3.1):**\n```yaml\n# OAS 3.1 uses JSON Schema 2020-12 which includes:\ncomponents:\n  schemas:\n    Pet:\n      type: object\n      properties:\n        name:\n          type: string\n          example: Fluffy        # Changed from 'examples' array in OAS 3.0\n      xml:                       # Now a JSON Schema keyword, not OAS-specific\n        name: pet\n      externalDocs:              # Now a JSON Schema keyword\n        url: https://example.com\n      discriminator:             # Now a JSON Schema keyword\n        propertyName: petType\n```\n\n**Mapping Decision:**\n- Type: JSON Schema version upgrade (Draft 7 → 2020-12)\n- Location: Schema objects throughout spec\n- Swagger UI components: Entire new plugin\n- Files:\n  - `src/core/plugins/json-schema-2020-12/` (main plugin)\n  - `src/core/plugins/json-schema-2020-12-samples/` (sample generation)\n  - `src/core/plugins/json-schema-2020-12/components/keywords/example.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/xml.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/discriminator.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/external-docs.jsx`\n- Integration: OAS31 plugin extends JSON Schema 2020-12 keywords in `json-schema-2020-12-extensions/`\n\n**Example 6: `jsonSchemaDialect` Top-Level Field**\n\n**From Spec (OAS 3.1):**\n```yaml\nopenapi: 3.1.0\njsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base  # NEW in OAS 3.1\n```\n\n**Mapping Decision:**\n- Type: New top-level field (String/URI)\n- Location: Root level\n- Swagger UI component: Simple display component\n- File: `src/core/plugins/oas31/components/json-schema-dialect.jsx`\n- Selector: `selectJsonSchemaDialectField` in `spec-extensions/selectors.js`\n- Rendering: Show in info section with warning if non-default\n\n#### 1F. Specification Analysis Checklist\n\nUse WebFetch and Read tools to systematically check:\n\n- [ ] **Accessed official spec at https://spec.openapis.org/**\n- [ ] **Downloaded specification document**\n- [ ] **Read version number section**\n- [ ] **Analyzed OpenAPI Object (root level) changes**\n- [ ] **Reviewed Info Object modifications**\n- [ ] **Checked Paths/Operations changes**\n- [ ] **Examined Components Object updates**\n- [ ] **Identified Security Scheme changes**\n- [ ] **Analyzed Schema Object / JSON Schema version**\n- [ ] **Listed all new top-level fields**\n- [ ] **Listed all modified existing fields**\n- [ ] **Documented breaking changes**\n- [ ] **Identified deprecated features**\n- [ ] **Found example specifications**\n- [ ] **Created specification change document**\n- [ ] **Mapped changes to Swagger UI components using table above**\n- [ ] **Prioritized implementation order**\n\n#### 1G. Questions to Answer During Analysis\n\n**Version Type:**\n- Is this a major version (4.0) or minor version (3.2)?\n- Are there breaking changes?\n- Is backward compatibility maintained?\n\n**JSON Schema:**\n- Does it use a new JSON Schema version?\n- What new keywords are available?\n- Are there removed/deprecated keywords?\n\n**Top-Level Changes:**\n- What new top-level fields are added?\n- Which existing fields have new subfields?\n- Any removed top-level fields?\n\n**Operation Changes:**\n- Are there new operation-level features?\n- Changes to parameters, request bodies, responses?\n- New callback or link syntax?\n\n**Security Changes:**\n- What authentication types are new/changed?\n- OAuth2 flow modifications?\n- New security requirements?\n\n**Media Type Changes:**\n- Are there new media type features?\n- File upload handling changes?\n- Encoding changes?\n\n**Component Mapping:**\n- Which components need to be created from scratch?\n- Which existing components need to be wrapped?\n- What selectors are required?\n- Are new plugins needed (e.g., for JSON Schema)?\n\n**Implementation Priority:**\n- What's the critical path for basic rendering?\n- Which features can be added incrementally?\n- What has the highest user impact?\n\n### Step 1H: Using WebFetch to Analyze Specifications\n\n**Always use WebFetch tool to retrieve and analyze the specification systematically.**\n\n**Step-by-step WebFetch workflow:**\n\n1. **Fetch the specification landing page:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Provide a summary of this OpenAPI Specification version, including links to the full specification document and any change logs or migration guides.\"\n)\n```\n\n2. **Analyze the specification structure:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all top-level fields in the OpenAPI Object for this version. For each field, indicate if it is new, modified, or unchanged from version {PREVIOUS_VERSION}.\"\n)\n```\n\n3. **Deep dive into new features:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Describe the '{NEW_FIELD}' field in detail: its type, structure, purpose, whether it's required, and provide examples from the specification.\"\n)\n```\n\n4. **Analyze security changes:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all security scheme types supported in this version. Highlight any new or changed security scheme types compared to {PREVIOUS_VERSION}.\"\n)\n```\n\n5. **Check JSON Schema compatibility:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"What version of JSON Schema does this OpenAPI Specification version use? List any specific dialect or modifications to JSON Schema.\"\n)\n```\n\n6. **Find example specifications:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Provide links to example OpenAPI specification files for this version, particularly examples that demonstrate new features.\"\n)\n```\n\n**Real example from analyzing OAS 3.1:**\n\n```javascript\n// 1. Initial analysis\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"List all new fields and features introduced in OpenAPI 3.1.0 compared to OpenAPI 3.0.3\"\n)\n\n// Response would include:\n// - webhooks field (new top-level)\n// - info.summary (new)\n// - info.license.identifier (new)\n// - jsonSchemaDialect (new top-level)\n// - mutualTLS security scheme type (new)\n// - JSON Schema 2020-12 (changed from Draft 7)\n\n// 2. Deep dive into webhooks\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"Explain the 'webhooks' field in detail: structure, purpose, and provide a complete example\"\n)\n\n// 3. Understand JSON Schema changes\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"What are the differences between JSON Schema Draft 7 (used in OAS 3.0) and JSON Schema 2020-12 (used in OAS 3.1) that affect schema definitions?\"\n)\n```\n\n**Pro tip:** Use multiple targeted queries rather than one broad query. This gives more precise information for each component you need to implement.\n\n### Step 2: Create Plugin Directory Structure\n\n**Directory:** `src/core/plugins/oas{VERSION_NUMBER}/`\n\n**Files to Create:**\n```\nsrc/core/plugins/oas{VERSION_NUMBER}/\n├── index.js                          # Main plugin export\n├── fn.js                             # Selector/function factories\n├── selectors.js                      # Version-specific selectors (if needed)\n├── after-load.js                     # Lifecycle hook\n├── auth-extensions/                  # Authentication features\n│   └── wrap-selectors.js\n├── oas{PREVIOUS_VERSION}-extensions/ # Extensions to previous version\n│   └── fn.js\n├── spec-extensions/                  # Spec-level features\n│   ├── selectors.js\n│   └── wrap-selectors.js\n├── components/                       # New components\n│   ├── version-pragma-filter.jsx\n│   ├── {new-feature-1}.jsx\n│   └── auth/\n│       └── {new-auth-type}.jsx\n├── wrap-components/                  # Component wrappers\n│   ├── info.jsx\n│   ├── license.jsx\n│   └── {existing-component}.jsx\n└── json-schema-{VERSION}-extensions/ # If new JSON Schema version\n    ├── fn.js\n    ├── components/keywords/\n    └── wrap-components/keywords/\n```\n\n**Create the directories:**\n```bash\nmkdir -p src/core/plugins/oas{VERSION_NUMBER}/{auth-extensions,oas{PREVIOUS_VERSION}-extensions,spec-extensions,components/auth,wrap-components}\n```\n\n### Step 3: Implement Version Detection (fn.js)\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/fn.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\n/**\n * Detects if a spec is OpenAPI {MAJOR}.{MINOR}.x\n */\nexport const isOAS{VERSION} = (jsSpec) => {\n  const oasVersion = jsSpec.get(\"openapi\")\n  return (\n    typeof oasVersion === \"string\" &&\n    /^{MAJOR}\\.{MINOR}\\.(?:[1-9]\\d*|0)$/.test(oasVersion)\n  )\n}\n\n/**\n * Creates a selector that only returns a value for OAS {VERSION} specs\n */\nexport const createOnlyOAS{VERSION}Selector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(system)\n        : selectedValue\n    } else {\n      return null\n    }\n  }\n\n/**\n * Creates a selector wrapper that uses new impl for OAS {VERSION}, falls back to original\n */\nexport const createOnlyOAS{VERSION}SelectorWrapper =\n  (selector) =>\n  (oriSelector, system) =>\n  (state, ...args) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(oriSelector, system)\n        : selectedValue\n    } else {\n      return oriSelector(...args)\n    }\n  }\n\n/**\n * Creates a system-aware selector\n */\nexport const createSystemSelector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    const selectedValue = selector(state, system, ...args)\n    return typeof selectedValue === \"function\"\n      ? selectedValue(system)\n      : selectedValue\n  }\n\n/**\n * Creates a component wrapper that only renders for OAS {VERSION}.\n * When active, passes `originalComponent` (the unwrapped original) and\n * `getSystem` as extra props. Access the original via:\n *   const { originalComponent: Ori } = props\n * NOT via `props.Ori` — that's the OAS3/OAS30ComponentWrapFactory convention.\n */\nexport const createOnlyOAS{VERSION}ComponentWrapper =\n  (Component) => (Original, system) => (props) => {\n    if (system.specSelectors.isOAS{VERSION}()) {\n      return (\n        <Component\n          {...props}\n          originalComponent={Original}\n          getSystem={system.getSystem}\n        />\n      )\n    }\n\n    return <Original {...props} />\n  }\n\n/**\n * Wraps functions to conditionally use OAS {VERSION} implementations\n */\nexport const wrapOAS{VERSION}Fn = (fn, system) => {\n  const { fn: systemFn, specSelectors } = system\n  return Object.fromEntries(\n    Object.entries(fn).map(([name, newImpl]) => {\n      const oriImpl = systemFn[name]\n      const impl = (...args) =>\n        specSelectors.isOAS{VERSION}()\n          ? newImpl(...args)\n          : typeof oriImpl === \"function\"\n            ? oriImpl(...args)\n            : undefined\n      return [name, impl]\n    })\n  )\n}\n```\n\n### Step 4: Create Main Plugin Export (index.js)\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/index.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport afterLoad from \"./after-load.js\"\nimport {\n  isOAS{VERSION},\n  createSystemSelector,\n  createOnlyOAS{VERSION}Selector,\n  createOnlyOAS{VERSION}SelectorWrapper,\n  createOnlyOAS{VERSION}ComponentWrapper,\n} from \"./fn.js\"\n\n// Import spec extensions\nimport * as specExtensionsSelectors from \"./spec-extensions/selectors.js\"\nimport * as specExtensionsWrapSelectors from \"./spec-extensions/wrap-selectors.js\"\n\n// Import auth extensions\nimport * as authExtensionsWrapSelectors from \"./auth-extensions/wrap-selectors.js\"\n\n// Import OAS{PREVIOUS_VERSION} extensions\nimport * as oas{PREVIOUS_VERSION}ExtensionsFn from \"./oas{PREVIOUS_VERSION}-extensions/fn.js\"\n\n// Import components\nimport VersionPragmaFilter from \"./components/version-pragma-filter.jsx\"\n// Import new feature components here\n\n// Import wrap components\nimport InfoWrapper from \"./wrap-components/info.jsx\"\n// Import other wrappers here\n\n/**\n * OpenAPI {MAJOR}.{MINOR} Plugin\n *\n * Adds support for OpenAPI Specification {MAJOR}.{MINOR}.x\n *\n * This plugin should be loaded AFTER:\n * - oas{PREVIOUS_VERSION} plugin\n * - json-schema-{JSON_SCHEMA_VERSION} plugin (if applicable)\n *\n * It wraps and overrides components/selectors from previous versions.\n */\nconst OpenAPI{VERSION}Plugin = ({ fn }) => {\n  return {\n    fn: {\n      oas{VERSION_NUMBER}: {\n        isOAS{VERSION},\n        createSystemSelector,\n        createOnlyOAS{VERSION}Selector,\n        createOnlyOAS{VERSION}SelectorWrapper,\n        createOnlyOAS{VERSION}ComponentWrapper,\n      },\n    },\n    components: {\n      // New components\n      OAS{VERSION}VersionPragmaFilter: VersionPragmaFilter,\n      // Add new feature components here\n    },\n    wrapComponents: {\n      // Wrapped components\n      VersionPragmaFilter: (Ori, system) =>\n        system.specSelectors.isOAS{VERSION}()\n          ? system.getComponent(\"OAS{VERSION}VersionPragmaFilter\", true)\n          : Ori,\n      InfoContainer: InfoWrapper,\n      // Add other wrappers here\n    },\n    statePlugins: {\n      spec: {\n        selectors: {\n          // Add version detection selector\n          isOAS{VERSION}: createSystemSelector(specExtensionsSelectors.selectIsOAS{VERSION}),\n          // Add new feature selectors here\n        },\n        wrapSelectors: {\n          // Wrap previous version selectors if needed\n          ...specExtensionsWrapSelectors,\n        },\n      },\n      auth: {\n        wrapSelectors: {\n          // Add auth extensions if needed\n          ...authExtensionsWrapSelectors,\n        },\n      },\n      oas{VERSION_NUMBER}: {\n        selectors: {\n          // Plugin-specific selectors\n        },\n      },\n    },\n    afterLoad,\n  }\n}\n\nexport default OpenAPI{VERSION}Plugin\n```\n\n### Step 5: Implement Spec Extensions\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/selectors.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createSelector } from \"reselect\"\nimport { isOAS{VERSION} } from \"../fn.js\"\n\n/**\n * Detects if the current spec is OAS {VERSION}\n */\nexport const selectIsOAS{VERSION} = (state, system) => () => {\n  const spec = system.specSelectors.specJson()\n  return isOAS{VERSION}(spec)\n}\n\n// Add selectors for new OAS {VERSION} fields here\n// Example:\n// export const selectNewField = createSelector(\n//   (state) => state,\n//   (state) => {\n//     const spec = state.getIn([\"spec\", \"json\"])\n//     return spec.get(\"newField\")\n//   }\n// )\n```\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/wrap-selectors.js`\n\n**⚠️ Minor version: DON'T wrap `isOAS{PREV}` unless the regex actually matches both versions.** For example, OAS 3.1's `isOAS31` regex (`/^3\\.1\\./`) will never match `3.2.x`, so wrapping it to return `false` is dead code. Only add the `isOAS{PREV}` override if the previous version's detection regex would incorrectly match the new version.\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createOnlyOAS{VERSION}SelectorWrapper } from \"../fn.js\"\n\n// Ensure OAS {VERSION} specs are recognized as OAS 3.x (needed when major version number didn't change)\nexport const isOAS3 =\n  (oriSelector, system) =>\n  (state, ...args) => {\n    const isOAS{VERSION} = system.specSelectors.isOAS{VERSION}()\n    return isOAS{VERSION} || oriSelector(...args)\n  }\n\n// ONLY add isOAS{PREV} wrapper if the previous version's regex could match this new version.\n// For a minor version bump (e.g. 3.1 → 3.2), the previous regex won't match, so DON'T add this.\n// export const isOAS{PREV} = createOnlyOAS{VERSION}SelectorWrapper((state) => () => false)\n```\n\n### Step 6: Create Version Pragma Filter Component\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst OAS{VERSION}VersionPragmaFilter = ({ bypass, isSwagger2, isOAS3, isOAS{PREVIOUS_VERSION}, isOAS{VERSION} }) => {\n  // Handle version detection logic\n  const isAmbiguous =\n    (isSwagger2 && isOAS3) ||\n    (isSwagger2 && isOAS{PREVIOUS_VERSION}) ||\n    (isSwagger2 && isOAS{VERSION}) ||\n    (isOAS3 && isOAS{PREVIOUS_VERSION}) ||\n    (isOAS3 && isOAS{VERSION}) ||\n    (isOAS{PREVIOUS_VERSION} && isOAS{VERSION})\n\n  const isMissing = !isSwagger2 && !isOAS3 && !isOAS{PREVIOUS_VERSION} && !isOAS{VERSION}\n\n  if (bypass) {\n    return null\n  }\n\n  if (isAmbiguous) {\n    return (\n      <div className=\"version-pragma\">\n        <div className=\"version-pragma__message version-pragma__message--ambiguous\">\n          <div>\n            <h3>Unable to render this document, as it contains multiple OpenAPI version fields.</h3>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  if (isMissing) {\n    return (\n      <div className=\"version-pragma\">\n        <div className=\"version-pragma__message version-pragma__message--missing\">\n          <div>\n            <h3>Unable to render this document, as it doesn&apos;t contain an OpenAPI version field.</h3>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  return null\n}\n\nOAS{VERSION}VersionPragmaFilter.propTypes = {\n  bypass: PropTypes.bool,\n  isSwagger2: PropTypes.bool.isRequired,\n  isOAS3: PropTypes.bool.isRequired,\n  isOAS{PREVIOUS_VERSION}: PropTypes.bool.isRequired,\n  isOAS{VERSION}: PropTypes.bool.isRequired,\n}\n\nOAS{VERSION}VersionPragmaFilter.defaultProps = {\n  bypass: false,\n}\n\nexport default OAS{VERSION}VersionPragmaFilter\n```\n\n### Step 7: Implement New Feature Components\n\nFor each new feature in the OAS specification:\n\n**Example: New Feature Component**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst NewFeature = ({ getComponent, specSelectors }) => {\n  const newFeature = specSelectors.selectNewFeature()\n\n  if (!newFeature || !newFeature.size) {\n    return null\n  }\n\n  // Render the new feature\n  return (\n    <div className=\"opblock-tag-section\">\n      <h3>New Feature</h3>\n      {/* Render logic here */}\n    </div>\n  )\n}\n\nNewFeature.propTypes = {\n  specSelectors: PropTypes.object.isRequired,\n  getComponent: PropTypes.func.isRequired,\n}\n\nexport default NewFeature\n```\n\n### Step 8: Create Component Wrappers\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/wrap-components/info.jsx`\n\n**⚠️ Minor version (e.g. 3.2): don't create a new Info component.** If the Info object is identical to the previous version, reuse `OAS{PREV_VERSION}Info` via `getComponent` instead of copying the whole component. Only create a new Info component for major versions with significant structural changes.\n\n**Template (minor version — reuse previous Info):**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport { createOnlyOAS{VERSION}ComponentWrapper } from \"../fn.js\"\n\nconst InfoWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => {\n  const system = getSystem()\n  const OAS{PREV_VERSION}Info = system.getComponent(\"OAS{PREV_VERSION}Info\", true)\n  return <OAS{PREV_VERSION}Info />\n})\n\nexport default InfoWrapper\n```\n\n**Also — OpenAPIVersion wrapper (minor version — change version badge only):**\n\nFor minor versions where the only Info difference is the version badge, use the OpenAPIVersion wrapper pattern instead of wrapping InfoContainer at all:\n\n```javascript\n// wrap-components/openapi-version.jsx\n/**\n * @prettier\n */\nimport React from \"react\"\nimport { createOnlyOAS{VERSION}ComponentWrapper } from \"../fn.js\"\n\nexport default createOnlyOAS{VERSION}ComponentWrapper((props) => {\n  const { originalComponent: Ori } = props  // NOT `Ori` from props directly — use `originalComponent`\n  return <Ori oasVersion=\"{MAJOR}.{MINOR}\" />\n})\n```\n\nThen register it in index.js:\n```javascript\nwrapComponents: {\n  OpenAPIVersion: OpenAPIVersionWrapper,  // changes the version badge shown in the Info header\n}\n```\n\n### Step 9: Implement afterLoad Hook\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/after-load.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { wrapOAS{VERSION}Fn } from \"./fn.js\"\n\n/**\n * afterLoad hook for OAS {VERSION} plugin\n *\n * This hook runs after all plugins are loaded and allows\n * modification of the system's functions and behaviors.\n */\nfunction afterLoad({ fn, getSystem }) {\n  const system = getSystem()\n\n  // Override functions that differ in OAS {VERSION}\n  if (typeof fn.sampleFromSchema === \"function\") {\n    // Example: Wrap sample generation if JSON Schema version changed\n    // const wrappedFns = wrapOAS{VERSION}Fn({\n    //   sampleFromSchema: fn.jsonSchema{VERSION}.sampleFromSchema,\n    // }, system)\n    // Object.assign(this.fn, wrappedFns)\n  }\n\n  // Override other functions as needed\n  // Example: File upload detection\n  // if (typeof fn.isFileUploadIntended === \"function\") {\n  //   const wrappedFns = wrapOAS{VERSION}Fn({\n  //     isFileUploadIntended: makeIsFileUploadIntended(system),\n  //   }, system)\n  //   Object.assign(this.fn, wrappedFns)\n  // }\n}\n\nexport default afterLoad\n```\n\n### Step 10: Handle Authentication Changes\n\nIf new authentication types are introduced:\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/auth/{auth-type}.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst NewAuthType = ({ schema, name, getComponent, onChange, authorized }) => {\n  const authValue = authorized && authorized.getIn([name])\n\n  const Input = getComponent(\"Input\")\n  const Button = getComponent(\"Button\")\n\n  // Render auth UI\n  return (\n    <div>\n      <h4>{schema.get(\"description\") || `${name} (${schema.get(\"type\")})`}</h4>\n      {/* Auth UI here */}\n    </div>\n  )\n}\n\nNewAuthType.propTypes = {\n  schema: PropTypes.object.isRequired,\n  name: PropTypes.string.isRequired,\n  getComponent: PropTypes.func.isRequired,\n  onChange: PropTypes.func.isRequired,\n  authorized: PropTypes.object,\n}\n\nexport default NewAuthType\n```\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/auth-extensions/wrap-selectors.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createOnlyOAS{VERSION}SelectorWrapper } from \"../fn.js\"\nimport { Map } from \"immutable\"\n\n/**\n * Wraps definitionsToAuthorize to include new auth types\n */\nexport const definitionsToAuthorize = createOnlyOAS{VERSION}SelectorWrapper(\n  (state, system) =>\n    (oriSelector) => {\n      const definitions = oriSelector()\n      const securityDefinitions = system.specSelectors.securityDefinitions() || Map()\n\n      // Add new auth types to definitions\n      return definitions.map((definition) => {\n        const schema = securityDefinitions.get(definition.get(\"name\"))\n        if (schema && schema.get(\"type\") === \"newAuthType\") {\n          // Add new auth type logic\n          return definition.set(\"newAuthType\", true)\n        }\n        return definition\n      })\n    }\n)\n```\n\n### Step 11: Register Plugin in Preset\n\n**File:** `src/core/presets/apis/index.js`\n\n**Add import:**\n```javascript\nimport OpenAPI{VERSION}Plugin from \"../../plugins/oas{VERSION_NUMBER}/index.js\"\n```\n\n**Add to preset array (IMPORTANT: add at the end):**\n```javascript\nexport default function PresetApis() {\n  return [\n    BasePreset,\n    OpenAPI30Plugin,\n    // ... other plugins\n    OpenAPI{PREVIOUS_VERSION}Plugin,\n    OpenAPI{VERSION}Plugin,  // Load LAST to override previous versions\n  ]\n}\n```\n\n**Why load last?**\n- Wrap-components override previous versions\n- Wrap-selectors intercept earlier selectors\n- afterLoad modifications apply to dependencies\n\n### Step 12: Add Unit Tests\n\n**Directory:** `test/unit/core/plugins/oas{VERSION_NUMBER}/`\n\n**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/fn.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { fromJS } from \"immutable\"\nimport { isOAS{VERSION} } from \"src/core/plugins/oas{VERSION_NUMBER}/fn.js\"\n\ndescribe(\"oas{VERSION_NUMBER} plugin - fn - isOAS{VERSION}\", () => {\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.0\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.1\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.1\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.25\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.25\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should NOT match OpenAPI {MAJOR}.{MINOR}\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match OpenAPI {MAJOR}.{MINOR}.01 (leading zero)\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.01\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match OpenAPI {DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0\", () => {\n    const spec = fromJS({ openapi: \"{DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match swagger: 2.0\", () => {\n    const spec = fromJS({ swagger: \"2.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should handle null spec\", () => {\n    const spec = fromJS({})\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n})\n```\n\n**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport { shallow } from \"enzyme\"\nimport OAS{VERSION}VersionPragmaFilter from \"src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx\"\n\ndescribe(\"OAS{VERSION}VersionPragmaFilter\", () => {\n  it(\"should render nothing when bypass is true\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={true}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.type()).toBe(null)\n  })\n\n  it(\"should render nothing when version is valid\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.type()).toBe(null)\n  })\n\n  it(\"should render error when version is ambiguous\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={true}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.find(\".version-pragma__message--ambiguous\")).toHaveLength(1)\n  })\n\n  it(\"should render error when version is missing\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={false}\n      />\n    )\n    expect(wrapper.find(\".version-pragma__message--missing\")).toHaveLength(1)\n  })\n})\n```\n\n### Step 13: Add E2E Tests\n\n**Directory:** `test/e2e-cypress/e2e/features/oas{VERSION_NUMBER}/`\n\n**Create test spec file:**\n```javascript\n/**\n * @prettier\n */\n\ndescribe(\"OpenAPI {MAJOR}.{MINOR} features\", () => {\n  it(\"should detect OAS {VERSION} version\", () => {\n    cy.visit(\"/oas{VERSION_NUMBER}-spec.html\")\n    cy.get(\".information-container .version\").should(\"contain\", \"{MAJOR}.{MINOR}.0\")\n  })\n\n  // Add tests for new features\n  it(\"should render new feature X\", () => {\n    cy.visit(\"/oas{VERSION_NUMBER}-spec.html\")\n    cy.get(\".opblock-tag-section\").should(\"contain\", \"New Feature\")\n  })\n})\n```\n\n**Add test fixtures:**\n- Create sample OAS {VERSION} spec in `test/e2e-cypress/static/documents/oas{VERSION_NUMBER}/`\n- Create HTML fixture in `test/e2e-cypress/static/` referencing the spec\n\n### Step 14: Update Documentation\n\n**Files to update:**\n\n1. **README.md** - Add OAS {VERSION} to supported versions\n2. **CLAUDE.md** - Add plugin to list and update version compatibility\n3. **docs/usage/version-detection.md** - Document new version detection\n4. **package.json** - Update description if needed\n\n**Example README.md update:**\n```markdown\n### OpenAPI Specification Compatibility\n\n- **OpenAPI 2.0** (Swagger)\n- **OpenAPI 3.0.x**\n- **OpenAPI 3.1.x**\n- **OpenAPI {MAJOR}.{MINOR}.x** ⭐ NEW\n```\n\n### Step 15: Verify Build\n\n**Run full build:**\n```bash\nnpm run clean\nnpm run build\n```\n\n**Check dist/ output:**\n- `dist/swagger-ui.js` - Should include new plugin\n- `dist/swagger-ui.css` - Should include new styles (if any)\n- Bundle size should be reasonable\n\n**Run artifact tests:**\n```bash\nnpm run test:artifact\n```\n\n### Step 16: Run Full Test Suite\n\n```bash\nnpm run lint-errors      # ESLint errors only\nnpm run test:unit        # Jest unit tests\nnpm run cy:ci            # Cypress E2E tests\n```\n\n**All tests must pass before submitting PR.**\n\n### Step 17: Create Pull Request\n\n**Commit message format:**\n```\nfeat(oas{VERSION_NUMBER}): add support for OpenAPI {MAJOR}.{MINOR}\n\nImplement OpenAPI {MAJOR}.{MINOR}.x specification support with:\n- Version detection and plugin architecture\n- New feature X rendering\n- New authentication type Y support\n- JSON Schema {VERSION} integration (if applicable)\n\nCloses #{ISSUE_NUMBER}\n```\n\n**PR checklist:**\n- [ ] All tests passing\n- [ ] New feature components implemented\n- [ ] Unit tests added\n- [ ] E2E tests added\n- [ ] Documentation updated\n- [ ] Build completes successfully\n- [ ] No ESLint errors\n- [ ] Follows existing code patterns\n\n## Common Pitfalls\n"},"files":{"src/core/plugins/err/error-transformers/README.md":"# Error transformers\n\nError transformers provide a standard interface for making generated error messages more useful to end users.\n\n### Inputs & outputs\n\nEach transformer's `transform` function is given an Immutable List of Immutable Maps as its first argument.\n\nIt is expected that each `transform` function returns a List of similarly-formed Maps.\n\nThese errors originate from the Redux error actions that add errors to state. Errors are transformed before being passed into the reducer.\n\nIt's important that all the keys present in each error (specifically, `line`, `level`, `message`, `source`, and `type`) are present when the transformer is finished.\n\n##### Deleting an error\n\nIf you want to delete an error completely, you can overwrite it with `null`. The null value will be filtered out of the transformed error array before the errors are returned.\nå\n\n### Example transformer\n\nThis transformer will increase all your line numbers by 10.\n\n```\nexport function transform(errors) {\n  return errors.map(err => {\n    err.line += 10\n    return err\n  })\n}\n```\n","src/core/plugins/deep-linking/README.md":"See `docs/deep-linking.md`.\n",".claude/skills/README.md":"# Swagger UI Claude Skills\n\nThis directory contains custom skills for working with the Swagger UI codebase in Claude Code.\n\n## Available Skills\n\n### `/add-oas-support` - Add OpenAPI Specification Version Support\n\nComprehensive skill for adding support for a new OpenAPI Specification version to Swagger UI.\n\n**Usage:**\n```\n/add-oas-support --version 4.0 --type major\n/add-oas-support --version 3.2 --type minor\n```\n\n**Parameters:**\n- `--version` (required): The OpenAPI version to add support for (e.g., \"3.2\", \"4.0\")\n- `--type` (optional): Version type - \"major\" or \"minor\" (default: \"minor\")\n\n**Structure:**\nThe skill includes both a **Quick Reference** section at the top for experienced developers, and a **comprehensive guide** below for detailed implementation instructions.\n\n**What it does:**\n1. **Analyzes the target OAS version specification using WebFetch**\n   - Fetches official spec from https://spec.openapis.org/\n   - Systematically identifies new/modified/removed fields\n   - Maps specification changes to Swagger UI components\n   - Creates specification change document\n2. Creates the plugin directory structure\n3. Implements version detection logic\n4. Creates selector factories and component wrappers\n5. Implements new feature components based on spec analysis\n6. Handles authentication changes\n7. Registers plugin in presets\n8. Adds unit and E2E tests\n9. Updates documentation\n10. Runs full test suite\n\n**Key Features:**\n- ✅ **Quick Reference** section for rapid development\n- ✅ Comprehensive specification analysis workflow using WebFetch\n- ✅ Detailed mapping table from spec changes → components (15+ change types)\n- ✅ Real examples from OAS 3.1 implementation (6 detailed examples)\n- ✅ Iterative spec-driven development approach\n- ✅ Component-by-component verification checklist\n- ✅ Best practices for continuous spec reference\n- ✅ WebFetch query templates for spec analysis\n- ✅ Common pitfalls and solutions\n- ✅ Pre-submit checklist\n\n**Based on:**\nThis skill follows the patterns established by the OAS 3.1 implementation (commit history analyzed from `src/core/plugins/oas31/`).\n\n**Key patterns:**\n- Plugin-based architecture with Redux state management\n- Selector factories for version-specific logic\n- Component wrapping for conditional rendering\n- afterLoad lifecycle hooks for function overrides\n- Plugin loading order (new version loaded LAST)\n\n**Prerequisites:**\n- Understanding of Swagger UI plugin architecture\n- Access to the new OAS specification document\n- All existing tests passing\n\n**Example workflow:**\n\nAdding OAS 4.0 support:\n```\n# Start the skill\n/add-oas-support --version 4.0 --type major\n\n# Claude will:\n# 1. Ask about new features in OAS 4.0\n# 2. Create plugin directory structure\n# 3. Generate boilerplate code\n# 4. Guide through implementation\n# 5. Add tests\n# 6. Update documentation\n# 7. Verify build\n```\n\n## Creating New Skills\n\nTo create a new skill for Swagger UI:\n\n1. Create a markdown file in `.claude/skills/`\n2. Add frontmatter with skill metadata:\n   ```yaml\n   ---\n   name: skill-name\n   description: Brief description\n   args:\n     param1:\n       description: \"Parameter description\"\n       required: true\n       type: string\n   ---\n   ```\n3. Write comprehensive instructions following the patterns in existing skills\n4. Document common pitfalls and best practices\n5. Include code templates with placeholders\n6. Add to this README\n\n## Skill Development Guidelines\n\nWhen creating skills for Swagger UI:\n\n1. **Follow project conventions:**\n   - No semicolons\n   - Double quotes\n   - @prettier pragma in all new files\n   - .jsx extension for React components\n\n2. **Use the plugin architecture:**\n   - Don't modify core unnecessarily\n   - Follow established patterns\n   - Load new plugins at the end of presets\n\n3. **Include comprehensive tests:**\n   - Unit tests for logic\n   - Component tests for UI\n   - E2E tests for integration\n\n4. **Document thoroughly:**\n   - Update CLAUDE.md\n   - Update relevant docs\n   - Add inline JSDoc comments\n\n5. **Security first:**\n   - Use DOMPurify for HTML\n   - Validate all input\n   - Follow OWASP guidelines\n\n## Contributing\n\nTo contribute new skills:\n\n1. Fork the repository\n2. Create skill in `.claude/skills/`\n3. Test thoroughly\n4. Update this README\n5. Submit pull request\n\n## Resources\n\n- **CLAUDE.md** - Comprehensive codebase guide\n- **Plugin API** - `docs/customization/plugin-api.md`\n- **Development Setup** - `docs/development/setting-up.md`\n- **Contributing Guide** - https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md\n","CLAUDE.md":"# CLAUDE.md - Swagger UI Codebase Guide\n\n> **Last Updated:** 2026-02-24\n> **Version:** 5.32.0 (in development)\n> **Purpose:** Comprehensive guide for AI assistants working with the Swagger UI codebase\n\n---\n\n## Table of Contents\n\n1. [Repository Overview](#repository-overview)\n2. [Project Architecture](#project-architecture)\n3. [Development Setup](#development-setup)\n4. [Build System](#build-system)\n5. [Testing Infrastructure](#testing-infrastructure)\n6. [Code Style & Conventions](#code-style--conventions)\n7. [Git Workflow](#git-workflow)\n8. [Plugin Architecture](#plugin-architecture)\n9. [Key Files & Directories](#key-files--directories)\n10. [Common Workflows](#common-workflows)\n11. [Important Guidelines](#important-guidelines)\n\n---\n\n## Repository Overview\n\n### What is Swagger UI?\n\nSwagger UI is a tool that allows developers to visualize and interact with API resources without having implementation logic in place. It's automatically generated from OpenAPI (formerly Swagger) Specification documents.\n\n### Multi-Package Monorepo Structure\n\nThis repository publishes **three different npm packages**:\n\n1. **swagger-ui** (main package)\n   - Traditional npm module for single-page applications\n   - Entry: `dist/swagger-ui.js`\n   - ES Module: `dist/swagger-ui-es-bundle-core.js`\n   - Includes dependency resolution via Webpack/Browserify\n\n2. **swagger-ui-dist** (distribution package)\n   - Dependency-free module for server-side projects\n   - Published separately via GitHub workflow\n   - Template location: `swagger-ui-dist-package/`\n\n3. **swagger-ui-react** (React component)\n   - React wrapper component\n   - Location: `flavors/swagger-ui-react/`\n   - Uses React hooks\n   - Released separately via GitHub workflow\n\n### OpenAPI Specification Compatibility\n\n- **Current Support:** OpenAPI 2.0, 3.0.x, 3.1.x\n- **Latest Version:** v5.31.0 (supports up to OpenAPI 3.1.2)\n\n### License\n\nApache 2.0 - See LICENSE and NOTICE files for details.\n\n---\n\n## Project Architecture\n\n### Technology Stack\n\n**Core Framework:**\n- React 18 (>=16.8.0 <20) - UI components\n- Redux 5.0.1 - State management\n- Redux Immutable 4.0.0 - Immutable state\n- Immutable.js 3.x - Immutable data structures\n- React Redux 9.2.0 - React-Redux bindings\n\n**API & Schema Processing:**\n- swagger-client 3.36.0 - OpenAPI client\n- js-yaml 4.1.1 - YAML parsing\n- remarkable 2.0.1 - Markdown rendering\n\n**Security:**\n- DOMPurify 3.2.6 - HTML sanitization (CRITICAL for XSS prevention)\n- serialize-error 8.1.0 - Error serialization\n\n**Build Tools:**\n- Webpack 5.97.1 - Module bundling\n- Babel 7.26.x - JavaScript transpilation\n- sass-embedded 1.86.0 - SCSS compilation\n- PostCSS - CSS processing\n\n**Testing:**\n- Jest 29.7.0 - Unit testing\n- Cypress 14.2.0 - E2E testing\n- Enzyme 3.11.0 - React component testing\n\n**Development:**\n- ESLint 8.57.0 - JavaScript linting\n- Prettier 3.5.3 - Code formatting\n- Stylelint 16.19.1 - CSS linting\n- Husky 9.1.7 - Git hooks\n- lint-staged 15.5.0 - Pre-commit linting\n\n### Plugin-Based Architecture\n\nSwagger UI uses a **sophisticated plugin system** powered by Redux. The core system (`src/core/system.js`) manages:\n\n- Plugin registration and lifecycle\n- Redux store creation and middleware\n- State plugin combination\n- Action/selector binding\n- Configuration management\n\n**26 Core Plugins** (in `src/core/plugins/`):\n- `auth` - Authentication handling\n- `configs` - Configuration management\n- `deep-linking` - URL-based navigation\n- `download-url` - Spec downloading\n- `err` - Error handling and transformation\n- `filter` - API filtering\n- `icons` - Icon components\n- `json-schema-2020-12` - JSON Schema 2020-12 support\n- `json-schema-2020-12-samples` - Sample generation\n- `json-schema-5` - JSON Schema Draft 5 support\n- `json-schema-5-samples` - Sample generation for Draft 5\n- `layout` - Layout system\n- `logs` - Logging\n- `oas3` - OpenAPI 3.0.x support\n- `oas31` - OpenAPI 3.1.x support\n- `oas32` - OpenAPI 3.2.x support\n- `on-complete` - Completion callbacks\n- `request-snippets` - Code snippet generation\n- `safe-render` - Safe component rendering\n- `spec` - Specification handling\n- `swagger-client` - API client integration\n- `syntax-highlighting` - Code highlighting\n- `util` - Utilities\n- `versions` - Version detection\n- `view` - View rendering\n- `view-legacy` - Legacy view support\n\n---\n\n## Development Setup\n\n### Prerequisites\n\n- **Node.js:** >=24.22 (Node 24.x recommended, as defined in `.nvmrc`)\n- **npm:** >=11.19.1\n- **Git:** Any version\n- **JDK 7+:** Required for Nightwatch.js integration tests\n\n### Installation Steps\n\n```bash\n# Clone the repository\ngit clone https://github.com/swagger-api/swagger-ui.git\ncd swagger-ui\n\n# Install dependencies\nnpm install\n\n# Initialize Husky (optional, for git hooks)\nnpx husky init\n\n# Start development server\nnpm run dev\n\n# Open http://localhost:3200/\n```\n\n### Development Server\n\nThe `npm run dev` command starts a hot-reloading Webpack dev server on **port 3200**.\n\n### Using Local API Definitions\n\nEdit `dev-helpers/dev-helper-initializer.js` to change the spec URL:\n\n```javascript\n// Replace\nurl: \"https://petstore.swagger.io/v2/swagger.json\",\n\n// With\nurl: \"./examples/your-local-api-definition.yaml\",\n```\n\n**Important:** Local files must be in the `dev-helpers/` directory or subdirectory. Use `dev-helpers/examples/` (already in `.gitignore`).\n\n---\n\n## Build System\n\n### Babel Environments\n\nThree Babel environments configured in `babel.config.js`:\n\n1. **development/production** - Browser builds with `modules: \"auto\"`\n2. **commonjs** - CommonJS modules with `modules: \"commonjs\"` for Node.js\n3. **esm** - ES modules with `modules: false` for modern bundlers\n\n### Babel Aliases\n\n```javascript\n{\n  root: \".\",\n  core: \"./src/core\"\n}\n```\n\n### Browserslist Environments\n\nDefined in `.browserslistrc`:\n\n- `[browser-production]` - Production browser targets\n- `[browser-development]` - Latest Chrome, Firefox, Safari\n- `[isomorphic-production]` - Browser + Node targets\n- `[node-production]` - Maintained Node versions\n- `[node-development]` - Node 24\n\n### Build Commands\n\n```bash\n# Full build (stylesheets + all bundles)\nnpm run build\n\n# Individual builds\nnpm run build:core              # Core bundle (browser)\nnpm run build:bundle            # Isomorphic bundle\nnpm run build:standalone        # Standalone preset\nnpm run build:es:bundle         # ES module bundle\nnpm run build:es:bundle:core    # ES module core\nnpm run build-stylesheets       # CSS only\n\n# Clean build artifacts\nnpm run clean\n```\n\n### Build Output (dist/)\n\n- `swagger-ui.js` - Core bundle (CommonJS)\n- `swagger-ui.css` - Compiled styles\n- `swagger-ui-bundle.js` - Isomorphic bundle\n- `swagger-ui-standalone-preset.js` - Standalone preset\n- `swagger-ui-es-bundle.js` - ES module bundle\n- `swagger-ui-es-bundle-core.js` - ES module core\n- `oauth2-redirect.html` - OAuth2 redirect page\n\n### Webpack Configurations\n\nLocated in `webpack/` directory:\n\n- `_config-builder.js` - Base configuration\n- `core.js` - Core build\n- `bundle.js` - Bundle build\n- `standalone.js` - Standalone build\n- `es-bundle.js` - ES bundle\n- `es-bundle-core.js` - ES core bundle\n- `stylesheets.js` - CSS build\n- `dev.js` - Development server\n- `dev-e2e.js` - E2E testing server\n\n---\n\n## Testing Infrastructure\n\n### Unit Tests (Jest)\n\n**Configuration:** `config/jest/jest.unit.config.js`\n\n**Environment:** jsdom (simulates browser environment)\n\n**Location:** `test/unit/`\n\n**Command:**\n```bash\nnpm run test:unit\n```\n\n**Key Features:**\n- 37 unit test files\n- Tests for core plugins, components, system\n- XSS security tests\n- Silent mode enabled by default (set to `false` for console output)\n- Module name mapper for SVG and standalone imports\n- Transform ignore patterns for node_modules exceptions\n\n**Setup Files:**\n- `test/unit/jest-shim.js` - Polyfills and shims\n- `test/unit/setup.js` - Test environment setup\n\n### E2E Tests (Cypress)\n\n**Configuration:** `cypress.config.js`\n\n**Location:** `test/e2e-cypress/`\n\n**Base URL:** http://localhost:3230/\n\n**Commands:**\n```bash\n# Run all E2E tests\nnpm run cy:ci\n\n# Interactive Cypress runner\nnpm run cy:dev\n\n# Headless run\nnpm run cy:run\n\n# Start servers and run tests\nnpm run cy:start     # Starts webpack + mock API\n```\n\n**Structure:**\n- `test/e2e-cypress/e2e/` - Test specs (99 test files)\n- `test/e2e-cypress/static/` - Test fixtures and documents\n- `test/e2e-cypress/support/` - Test helpers and commands\n\n**Test Categories:**\n- `a11y/**/*cy.js` - Accessibility tests\n- `security/**/*cy.js` - Security tests\n- `bugs/**/*cy.js` - Bug regression tests\n- `features/**/*cy.js` - Feature tests\n\n**Mock API Server:**\n```bash\nnpm run cy:mock-api  # JSON Server on port 3204\n```\n\n### Artifact Tests\n\n**Configuration:** `config/jest/jest.artifact.config.js`\n\n**Purpose:** Verify build artifacts export correctly\n\n**Command:**\n```bash\nnpm run test:artifact\n```\n\n### Complete Test Suite\n\n```bash\nnpm test  # Runs: lint-errors + test:unit + cy:ci\n```\n\n### CI/CD Testing\n\n**GitHub Actions Workflow:** `.github/workflows/nodejs.yml`\n\n**Two Jobs:**\n1. **build** - Lint, unit tests, build, artifact tests\n2. **e2e-tests** - Cypress tests (matrix strategy with 3 containers)\n\n**Branches:** `main`, `next`\n\n---\n\n## Code Style & Conventions\n\n### ESLint Configuration\n\n**File:** `.eslintrc.js`\n\n**Parser:** `@babel/eslint-parser`\n\n**Key Rules:**\n- `semi: [2, \"never\"]` - **No semicolons**\n- `quotes: [2, \"double\"]` - **Double quotes** (allow template literals)\n- `no-unused-vars: 2` - Error on unused variables\n- `camelcase: [\"error\"]` - Enforce camelCase (with exceptions for UNSAFE_, request generators, etc.)\n- `no-console: [2, {allow: [\"warn\", \"error\"]}]` - Only `console.warn` and `console.error` allowed\n- `react/jsx-no-bind: 1` - Warning for JSX bind\n- `react/jsx-filename-extension: 2` - JSX only in `.jsx` files\n- `import/no-extraneous-dependencies: 2` - Error on extraneous dependencies\n\n**Extends:**\n- `eslint:recommended`\n- `plugin:react/recommended`\n- `plugin:prettier/recommended`\n\n### Prettier Configuration\n\n**File:** `.prettierrc.yaml`\n\n**Settings:**\n```yaml\nsemi: false              # No semicolons\ntrailingComma: es5       # ES5 trailing commas\nendOfLine: lf            # Unix line endings\nrequirePragma: true      # Require @prettier pragma\ninsertPragma: true       # Insert @prettier pragma\n```\n\n**IMPORTANT:** Prettier requires `@prettier` pragma comment at the top of files:\n```javascript\n/**\n * @prettier\n */\n```\n\n### Stylelint Configuration\n\n**File:** `stylelint.config.js`\n\n**Custom Syntax:** `postcss-scss`\n\n**Rules:**\n- Uses `stylelint-prettier` plugin\n- Prettier integration without pragma requirement\n\n### Pre-commit Hooks\n\n**Husky:** `.husky/pre-commit` runs `npx lint-staged`\n\n**Lint-staged Configuration:** `.lintstagedrc`\n```json\n{\n  \"*.{js,jsx}\": [\"eslint --max-warnings 0\"],\n  \"*.scss\": [\"stylelint '**/*.scss'\"]\n}\n```\n\n**Critical:** All staged JS/JSX/SCSS files are linted with **zero warnings tolerance**.\n\n### File Structure Conventions\n\n**TypeScript (REQUIRED for all new files):**\n- All new source files must be written in TypeScript (`.ts` / `.tsx`)\n- Use `.tsx` for React components, `.ts` for all other modules\n- Existing `.js` / `.jsx` files are not required to be migrated, but new code must not be added in plain JavaScript\n\n**Components:**\n- Location: `src/core/components/`\n- Extension: `.tsx` (React components — TypeScript)\n- Format: PascalCase for component names\n\n**Styles:**\n- Location: `src/style/`\n- Extension: `.scss`\n- Format: SCSS with PostCSS processing\n- Dark mode: `_dark-mode.scss`\n\n**Tests:**\n- Unit: `test/unit/` (mirrors source structure)\n- E2E: `test/e2e-cypress/e2e/`\n- Naming: `*.test.ts`, `*.spec.ts`, `*.cy.ts` (Cypress) — use `.tsx` variants when JSX is involved\n\n---\n\n## Git Workflow\n\n### Branch Strategy\n\n**Main Branches:**\n- `main` - Production releases\n- `next` - Next version development\n\n**Feature Branches:**\n- Should branch from `main` or `next`\n- Use descriptive names\n\n### Commit Conventions\n\n**Format:** Conventional Commits (enforced by commitlint)\n\n**Structure:**\n```\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n```\n\n**Types:**\n- `feat` - New feature\n- `fix` - Bug fix\n- `docs` - Documentation changes\n- `style` - Code style changes (formatting)\n- `refactor` - Code refactoring\n- `test` - Test additions/changes\n- `chore` - Build/tooling changes\n- `perf` - Performance improvements\n\n**Example:**\n```\nfeat(oas3): add support for OpenAPI 3.1.1 callbacks\n\nImplement callback rendering for OAS 3.1.1 specifications\nwith proper schema resolution and example generation.\n\nFixes #12345\n```\n\n### Pull Request Process\n\n**Template:** `.github/pull_request_template.md`\n\n**Required Sections:**\n1. **Description** - Detailed change description\n2. **Motivation and Context** - Why the change is needed\n3. **How Has This Been Tested?** - Manual testing details\n4. **Screenshots** - If UI changes\n\n**Checklist:**\n- [ ] Code type (no code/dependencies/bug fix/improvement/feature)\n- [ ] Breaking changes identification\n- [ ] Documentation updates\n- [ ] Test coverage\n- [ ] All tests passing\n\n**CI Checks:**\n- ESLint (error-only mode)\n- Unit tests (Jest)\n- Build verification\n- Artifact tests\n- E2E tests (Cypress)\n\n### Release Process\n\n**Tool:** release-it with conventional-changelog\n\n**Command:**\n```bash\nnpm run automated-release\n```\n\n**Workflows:**\n- `.github/workflows/release-swagger-ui.yml`\n- `.github/workflows/release-swagger-ui-dist.yml`\n- `.github/workflows/release-swagger-ui-react.yml`\n- `.github/workflows/release-swagger-ui-packagist.yml`\n\n---\n\n## Plugin Architecture\n\n### Core System (`src/core/system.js`)\n\nThe plugin system is the heart of Swagger UI. It uses Redux for state management with a custom plugin registration system.\n\n### Plugin Structure\n\nEach plugin is a JavaScript object/function that returns:\n\n```javascript\n{\n  statePlugins: {\n    [pluginName]: {\n      actions: {},      // Redux actions\n      reducers: {},     // Redux reducers\n      selectors: {},    // Reselect selectors\n      wrapActions: {},  // Action middleware\n      wrapSelectors: {} // Selector middleware\n    }\n  },\n  components: {},       // React components\n  fn: {},              // Utility functions\n  rootInjects: {},     // Root-level injections\n  afterLoad: Function  // Lifecycle hook\n}\n```\n\n### Key Plugin Locations\n\n**Core Plugins:** `src/core/plugins/`\n\nEach plugin has:\n- `index.js` - Main export\n- `actions.js` - Redux actions\n- `reducers.js` - Redux reducers\n- `selectors.js` - State selectors\n- `wrap-actions.js` - Action middleware\n- `wrap-selectors.js` - Selector middleware\n- Component files (`.jsx`)\n\n### Creating a Plugin\n\nSee documentation: `docs/customization/plugin-api.md`\n\n### Cross-Plugin Import Guidelines\n\n**IMPORTANT:** Avoid cross-plugin imports to maintain plugin independence and modularity.\n\n**Pattern to Follow:**\n- Each plugin should be self-contained with its own components, utilities, and functions\n- When OAS version plugins (oas3, oas31, oas32) need similar functionality, create self-contained copies within each plugin\n- Wrap components should import from their own plugin's components, not from other plugins\n\n**Example Structure:**\n```\nsrc/core/plugins/oas32/\n├── json-schema-2020-12-extensions/\n│   ├── components/              # Self-contained components\n│   │   └── keywords/\n│   │       ├── Description.jsx\n│   │       └── Properties.jsx\n│   ├── wrap-components/         # Wrappers for components\n│   │   └── keywords/\n│   │       ├── Description.jsx  # Imports from ../../components/\n│   │       └── Properties.jsx   # Not from ../../../../oas31/\n│   └── fn.js                    # Self-contained utilities\n```\n\n**Why This Matters:**\n- Prevents tight coupling between plugins\n- Makes plugins easier to test in isolation\n- Allows independent versioning and updates\n- Reduces risk of breaking changes across plugins\n- Improves code maintainability\n\n**Exceptions:**\n- Shared core utilities in `src/core/utils/` are acceptable\n- System-level functions in `src/core/system.js` are acceptable\n- Base components in `src/core/components/` are acceptable\n\n### Preset System\n\n**Base Preset:** `src/core/presets/base.js`\n\n**Standalone Preset:** `src/standalone/presets/standalone.js`\n\nPresets are collections of plugins bundled together for specific use cases.\n\n---\n\n## Key Files & Directories\n\n### Critical Source Files\n\n```\nsrc/\n├── core/\n│   ├── system.js                 # Plugin system & Redux store\n│   ├── components/               # 59 React components\n│   ├── plugins/                  # 26 core plugins\n│   ├── presets/                  # Preset configurations\n│   ├── utils/                    # Utility functions\n│   └── config/                   # Configuration system\n├── standalone/\n│   ├── plugins/                  # TopBar, StandaloneLayout\n│   └── presets/                  # Standalone preset\n├── style/                        # SCSS stylesheets\n│   ├── _dark-mode.scss          # Dark mode styles\n│   └── main.scss                # Main stylesheet entry\n└── index.js                      # Main package entry\n```\n\n### Configuration Files\n\n```\n.\n├── package.json                  # Dependencies & scripts\n├── babel.config.js              # Babel configuration\n├── .eslintrc.js                 # ESLint rules\n├── .prettierrc.yaml             # Prettier settings\n├── stylelint.config.js          # Stylelint rules\n├── .browserslistrc              # Browser targets\n├── .nvmrc                       # Node version (24.x)\n├── .lintstagedrc                # Pre-commit linting\n└── cypress.config.js            # Cypress E2E config\n```\n\n### Build & Tooling\n\n```\nwebpack/\n├── _config-builder.js           # Base Webpack config\n├── core.js                      # Core build\n├── bundle.js                    # Bundle build\n├── standalone.js                # Standalone build\n├── es-bundle.js                 # ES bundle build\n├── es-bundle-core.js           # ES core bundle\n├── stylesheets.js              # CSS compilation\n├── dev.js                       # Dev server\n└── dev-e2e.js                  # E2E dev server\n\nconfig/jest/\n├── jest.unit.config.js          # Unit test config\n└── jest.artifact.config.js      # Artifact test config\n```\n\n### Documentation\n\n```\ndocs/\n├── usage/\n│   ├── installation.md\n│   ├── configuration.md\n│   ├── cors.md\n│   ├── oauth2.md\n│   ├── deep-linking.md\n│   ├── version-detection.md\n│   └── limitations.md\n├── customization/\n│   ├── overview.md\n│   ├── plugin-api.md\n│   └── custom-layout.md\n└── development/\n    ├── setting-up.md\n    └── scripts.md\n```\n\n### Testing\n\n```\ntest/\n├── unit/                        # Jest unit tests (37 files)\n│   ├── setup.js                # Test environment setup\n│   └── jest-shim.js           # Polyfills\n├── e2e-cypress/                 # Cypress E2E tests (99 files)\n│   ├── e2e/                    # Test specs\n│   ├── static/                 # Fixtures\n│   └── support/                # Helpers\n└── e2e-selenium/               # Legacy Selenium tests\n```\n\n### Distribution\n\n```\nflavors/\n└── swagger-ui-react/            # React component wrapper\n\nswagger-ui-dist-package/         # Template for dist package\n\ndist/                            # Build output (generated)\n├── swagger-ui.js\n├── swagger-ui.css\n├── swagger-ui-bundle.js\n├── swagger-ui-standalone-preset.js\n├── swagger-ui-es-bundle.js\n├── swagger-ui-es-bundle-core.js\n└── oauth2-redirect.html\n```\n\n---\n\n## Common Workflows\n\n### Making Code Changes\n\n1. **Read before modifying:**\n   ```bash\n   # ALWAYS read files before editing them\n   # Understand the existing code structure\n   ```\n\n2. **Follow the style guide:**\n   - Use double quotes\n   - No semicolons\n   - Add `@prettier` pragma to new files\n   - Use `.jsx` extension for React components\n\n3. **Run linters:**\n   ```bash\n   npm run lint          # Check for errors and warnings\n   npm run lint-fix      # Auto-fix JavaScript issues\n   npm run lint-styles   # Check SCSS\n   npm run lint-styles-fix  # Auto-fix SCSS\n   ```\n\n4. **Test your changes:**\n   ```bash\n   npm run test:unit     # Run unit tests\n   npm run cy:dev        # Interactive E2E testing\n   npm run build         # Verify build works\n   npm run test:artifact # Verify artifacts\n   ```\n\n### Adding a New Component\n\n1. Create component in `src/core/components/` or appropriate plugin directory\n2. Use `.tsx` extension (TypeScript — required for all new files)\n3. Add `@prettier` pragma\n4. Follow React best practices (functional components, hooks)\n5. Add PropTypes validation\n6. Create corresponding test in `test/unit/`\n7. Export from plugin's `index.js` if needed\n\n### Adding a New Plugin\n\n1. Create directory in `src/core/plugins/[plugin-name]/`\n2. Create `index.ts` with plugin structure (TypeScript — required for all new files)\n3. Add actions, reducers, selectors as needed\n4. Register plugin in preset (e.g., `src/core/presets/base.js`)\n5. Add tests in `test/unit/core/plugins/[plugin-name]/`\n6. Document the plugin\n\n### Fixing a Bug\n\n1. **Reproduce the bug:**\n   - Add a failing test in `test/unit/` or `test/e2e-cypress/`\n   - Document reproduction steps\n\n2. **Fix the issue:**\n   - Make minimal changes to fix the bug\n   - Avoid refactoring unless necessary\n   - Ensure the test now passes\n\n3. **Verify:**\n   ```bash\n   npm run test:unit\n   npm run build\n   npm run test:artifact\n   ```\n\n4. **Create PR:**\n   - Reference the issue number\n   - Include before/after behavior\n   - Add screenshots if UI-related\n\n### Adding a Feature\n\n1. **Plan the feature:**\n   - Review existing architecture\n   - Identify affected plugins/components\n   - Consider OpenAPI spec compatibility\n\n2. **Implement:**\n   - Follow plugin architecture patterns\n   - Add configuration options if needed\n   - Update presets if necessary\n\n3. **Test thoroughly:**\n   - Unit tests for logic\n   - Component tests for UI\n   - E2E tests for integration\n   - Test with various OpenAPI specs\n\n4. **Document:**\n   - Update `docs/` if user-facing\n   - Add JSDoc comments for APIs\n   - Update README if needed\n\n### Security Considerations\n\n1. **XSS Prevention:**\n   - ALWAYS use DOMPurify for user-provided HTML\n   - Sanitize all external input\n   - Review `test/unit/xss/` for examples\n   - Never use `dangerouslySetInnerHTML` without sanitization\n\n2. **Input Validation:**\n   - Validate API responses\n   - Handle malformed OpenAPI specs gracefully\n   - Check for prototype pollution\n\n3. **Dependency Security:**\n   ```bash\n   npm run security-audit     # Run security audit\n   ```\n\n### Working with OpenAPI Specs\n\n**Testing Different Versions:**\n- OAS 2.0: Use `src/core/plugins/swagger-client/`\n- OAS 3.0.x: Use `src/core/plugins/oas3/`\n- OAS 3.1.x: Use `src/core/plugins/oas31/`\n- OAS 3.2.x: Use `src/core/plugins/oas32/`\n\n**Adding Test Specs:**\n- Add to `test/e2e-cypress/static/documents/`\n- Reference in E2E tests\n\n---\n\n## Important Guidelines\n\n### DO's ✅\n\n1. **Always read files before modifying them**\n2. **Write all new files in TypeScript** - use `.ts` for modules, `.tsx` for React components\n3. **Follow the no-semicolon convention**\n4. **Use double quotes for strings**\n5. **Add `@prettier` pragma to all new files**\n6. **Use `.tsx` extension for new React components** (TypeScript JSX)\n7. **Write tests for new features and bug fixes**\n8. **Run linters before committing** (automatic via husky)\n9. **Use DOMPurify for HTML sanitization**\n10. **Follow conventional commit format**\n11. **Update documentation for user-facing changes**\n12. **Test with multiple OpenAPI spec versions**\n13. **Check browser compatibility** (see `.browserslistrc`)\n14. **Use the plugin architecture** - don't modify core unnecessarily\n15. **Preserve backward compatibility** unless explicitly breaking\n16. **Run full test suite before submitting PR**\n17. **Keep plugins self-contained** - avoid cross-plugin imports (see [Cross-Plugin Import Guidelines](#cross-plugin-import-guidelines))\n\n### DON'Ts ❌\n\n1. **Don't write new files in plain JavaScript** - all new files must be TypeScript (`.ts` / `.tsx`)\n2. **Don't use semicolons** - project convention\n3. **Don't use single quotes** - use double quotes\n4. **Don't skip the @prettier pragma** - required for formatting\n5. **Don't put React in `.ts` files** - use `.tsx` for JSX\n6. **Don't commit files in `dev-helpers/`** (except core files)\n7. **Don't commit build artifacts** (`dist/` is gitignored)\n8. **Don't skip tests** - they run in CI\n9. **Don't bypass ESLint** - pre-commit hook enforces\n10. **Don't use `console.log`** - only `console.warn` and `console.error`\n11. **Don't render unsanitized HTML** - XSS vulnerability\n12. **Don't modify `package-lock.json` manually**\n13. **Don't push directly to `main` or `next`**\n14. **Don't ignore Cypress test failures**\n15. **Don't add dependencies without justification**\n16. **Don't break the build** - verify with `npm run build`\n17. **Don't import from other plugins** - create self-contained copies instead (e.g., don't import from `oas31` in `oas32`)\n\n### When Working with AI Assistants\n\n**Before Making Changes:**\n1. Read the affected files completely\n2. Understand the plugin architecture\n3. Check for existing tests\n4. Review related documentation\n\n**During Development:**\n1. Make minimal, focused changes\n2. Follow existing patterns in the codebase\n3. Add tests alongside code changes\n4. Run linters frequently\n\n**After Changes:**\n1. Verify all tests pass\n2. Check build completes successfully\n3. Test artifact exports\n4. Review for security issues\n5. Update relevant documentation\n\n**Communication:**\n- Be explicit about file locations\n- Use line number references (e.g., `src/core/system.js:96`)\n- Provide context for changes\n- Mention any breaking changes clearly\n\n### Performance Considerations\n\n1. **Immutable.js:**\n   - Use Immutable data structures for state\n   - Use `.toJS()` sparingly (expensive)\n   - Prefer Immutable operations\n\n2. **React:**\n   - Use React.memo for pure components\n   - Implement shouldComponentUpdate for class components\n   - Avoid inline function definitions in render\n\n3. **Redux:**\n   - Use reselect for memoized selectors\n   - Keep reducers pure and fast\n   - Avoid large state trees\n\n4. **Bundle Size:**\n   - Check bundle size with `npm run deps-size`\n   - Review dependency licenses with `npm run deps-license`\n   - Consider code splitting for large features\n\n### Debugging Tips\n\n**Development Server:**\n```bash\nnpm run dev\n# Open http://localhost:3200/\n# Hot reload enabled\n# Unminified stack traces\n```\n\n**Redux DevTools:**\n- Extension supported\n- State inspection available\n- Time-travel debugging\n\n**Cypress Interactive Mode:**\n```bash\nnpm run cy:dev\n# Visual test runner\n# Step-through debugging\n# Network inspection\n```\n\n**Jest Watch Mode:**\n```bash\nnpm run test:unit -- --watch\n# Re-run on file changes\n# Filter by file name or test name\n```\n\n**Source Maps:**\n- Generated for all builds\n- Enable in browser DevTools\n- Original source debugging\n\n---\n\n## Quick Reference\n\n### Essential Commands\n\n```bash\n# Development\nnpm run dev              # Start dev server (port 3200)\nnpm start                # Static file server (port 3002)\n\n# Building\nnpm run build            # Full production build\nnpm run clean            # Remove dist/\n\n# Testing\nnpm test                 # Full test suite (lint + unit + E2E)\nnpm run test:unit        # Jest unit tests\nnpm run cy:dev           # Cypress interactive\nnpm run cy:ci            # Cypress CI mode\nnpm run test:artifact    # Artifact verification\n\n# Linting\nnpm run lint             # ESLint (errors + warnings)\nnpm run lint-errors      # ESLint (errors only)\nnpm run lint-fix         # Auto-fix ESLint issues\nnpm run lint-styles      # Stylelint\nnpm run lint-styles-fix  # Auto-fix Stylelint issues\n\n# Security\nnpm run security-audit   # Run npm audit\n\n# Dependencies\nnpm run deps-check       # Size and license report\n```\n\n### File Paths\n\n```\nCore System:           src/core/system.js\nMain Entry:            src/index.js\nReact Entry:           flavors/swagger-ui-react/index.jsx\nComponents:            src/core/components/\nPlugins:               src/core/plugins/\nStyles:                src/style/\nTests (Unit):          test/unit/\nTests (E2E):           test/e2e-cypress/e2e/\nBuild Output:          dist/\n```\n\n### Port Reference\n\n- **3200** - Development server (webpack-dev-server)\n- **3002** - Static file server (local-web-server)\n- **3204** - Mock API server (json-server)\n- **3230** - E2E test server (webpack-dev-server)\n\n---\n\n## Additional Resources\n\n### Documentation\n\n- **Setup Guide:** `docs/development/setting-up.md`\n- **Scripts Reference:** `docs/development/scripts.md`\n- **Plugin API:** `docs/customization/plugin-api.md`\n- **Configuration:** `docs/usage/configuration.md`\n- **OAuth2 Setup:** `docs/usage/oauth2.md`\n\n### External Links\n\n- **Homepage:** https://swagger.io/tools/swagger-ui/\n- **Repository:** https://github.com/swagger-api/swagger-ui\n- **npm (main):** https://www.npmjs.com/package/swagger-ui\n- **npm (dist):** https://www.npmjs.com/package/swagger-ui-dist\n- **npm (react):** https://www.npmjs.com/package/swagger-ui-react\n- **OpenAPI Spec:** https://spec.openapis.org/\n\n### Community\n\n- **Issues:** https://github.com/swagger-api/swagger-ui/issues\n- **Good First Issues:** https://github.com/swagger-api/swagger-ui/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%22\n- **Security:** security@swagger.io\n- **Contributing:** https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md\n\n---\n\n**Note:** This document should be updated whenever major architectural changes, new conventions, or significant workflows are introduced to the codebase.\n",".claude/skills/add-oas-support.md":"---\nname: add-oas-support\ndescription: Add support for a new OpenAPI Specification version to Swagger UI\nargs:\n  version:\n    description: \"OpenAPI version to add support for (e.g., 3.2, 4.0)\"\n    required: true\n    type: string\n  type:\n    description: \"Version type: 'major' for new major version, 'minor' for patch/minor\"\n    required: false\n    type: string\n    default: \"minor\"\n---\n\n# Add OpenAPI Specification Version Support\n\nThis skill guides you through adding support for a new OpenAPI Specification (OAS) version to Swagger UI, following the established architectural patterns from OAS 3.1 implementation.\n\n---\n\n## 📌 Quick Reference\n\n> **New to this skill?** Skip to [Prerequisites](#prerequisites) for the full guide.\n> **Already familiar?** Use this quick reference for rapid development.\n\n### 🚀 Quick Start\n\n```bash\n# Major version (e.g., OAS 4.0)\n/add-oas-support --version 4.0 --type major\n\n# Minor version (e.g., OAS 3.2)\n/add-oas-support --version 3.2 --type minor\n```\n\n### 📋 Essential Checklist\n\n#### Phase 1: Specification Analysis ⭐ MOST IMPORTANT\n- [ ] Access official spec at **https://spec.openapis.org/oas/v{VERSION}/**\n- [ ] Use WebFetch to analyze spec systematically\n- [ ] Create specification change document\n- [ ] Map changes to components using [mapping table](#step-1d-map-specification-changes-to-swagger-ui-components)\n\n#### Phase 2: Implementation\n- [ ] Create plugin directory structure\n- [ ] Implement version detection (`isOAS{VERSION}`)\n- [ ] Create selector factories\n- [ ] Implement components for each spec change\n- [ ] Wrap existing components if modified\n- [ ] Register plugin in preset (LAST position)\n\n#### Phase 3: Testing & Documentation\n- [ ] Add unit tests\n- [ ] Add E2E tests with spec examples\n- [ ] Update documentation\n- [ ] Verify build & run full test suite\n\n### 🔍 WebFetch Queries for Spec Analysis\n\n```javascript\n// 1. Fetch main spec differences\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all new top-level fields, modified fields, and removed fields compared to version {PREV_VERSION}\"\n)\n\n// 2. Analyze new feature\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Describe the '{NEW_FIELD}' field: structure, type, purpose, required/optional, and provide examples\"\n)\n\n// 3. Check JSON Schema version\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"What JSON Schema version does this use? List changes from {PREV_JSON_SCHEMA_VERSION}\"\n)\n\n// 4. Security schemes\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all security scheme types, highlighting new or changed types\"\n)\n```\n\n### 🗺️ Spec Change → Component Mapping (Quick)\n\n| Spec Change | Component Action | File Location |\n|-------------|------------------|---------------|\n| **New top-level field (Object)** | Create new component | `components/{field}.jsx` |\n| **New top-level field (String)** | Add to info or create display | `components/{field}.jsx` |\n| **Modified Info object** | Wrap Info component | `wrap-components/info.jsx` |\n| **New info subfield** | Create component + wrap Info | `components/info-{field}.jsx` |\n| **New auth type** | Create auth component | `components/auth/{type}.jsx` |\n| **Modified security** | Wrap auth selector | `auth-extensions/wrap-selectors.js` |\n| **New operation field** | Extend Operation/selector | `spec-extensions/selectors.js` |\n| **JSON Schema keyword** | Create keyword component | `json-schema-{V}-extensions/` |\n| **JSON Schema version** | Create entire new plugin | `plugins/json-schema-{V}/` |\n\nSee [full mapping table with examples](#step-1d-map-specification-changes-to-swagger-ui-components) for detailed guidance.\n\n### 📝 Component Implementation Pattern\n\n**For each new feature:**\n\n1. **Check spec first:**\n   ```javascript\n   WebFetch(url, \"Describe {field} structure, type, examples\")\n   ```\n\n2. **Create selector:**\n   ```javascript\n   // spec-extensions/selectors.js\n   export const selectNewField = createSelector(\n     (state) => state,\n     (state) => state.getIn([\"spec\", \"json\", \"newField\"])\n   )\n   ```\n\n3. **Create component:**\n   ```javascript\n   // components/new-field.jsx\n   const NewField = ({ specSelectors, getComponent }) => {\n     const data = specSelectors.selectNewField()\n     if (!data) return null\n     return <div>{/* render based on spec structure */}</div>\n   }\n   ```\n\n4. **Register in plugin:**\n   ```javascript\n   // index.js\n   components: { NewField },\n   statePlugins: {\n     spec: {\n       selectors: {\n         selectNewField: createOnlyOAS{V}Selector(selectNewField)\n       }\n     }\n   }\n   ```\n\n5. **Add tests** (unit + E2E with spec examples)\n\n### ⚠️ Common Pitfalls\n\n1. ❌ **Guessing field structure** → ✅ Always check spec with WebFetch\n2. ❌ **Forgetting @prettier pragma** → ✅ Add to all new files\n3. ❌ **Wrong plugin load order** → ✅ New plugin LAST in preset\n4. ❌ **Using semicolons** → ✅ No semicolons (project convention)\n5. ❌ **Single quotes** → ✅ Use double quotes\n6. ❌ **Skipping spec examples** → ✅ Use as test fixtures\n7. ❌ **Hardcoded assumptions** → ✅ Verify everything in spec\n8. ❌ **`props.Ori` in ComponentWrapper** → ✅ Use `props.originalComponent` (see Pattern 3)\n9. ❌ **Copying entire Info component for minor version** → ✅ Use OpenAPIVersion wrapper + `getComponent(\"OAS{PREV}Info\")`\n10. ❌ **OAS{VERSION} logic in OAS{PREV} plugin** → ✅ Each version's logic lives in its own plugin\n11. ❌ **`isOAS{PREV}` wrapper on minor version** → ✅ Only add if regex overlaps; minor bumps don't need it\n12. ❌ **New HTTP method in core `validOperationMethods`** → ✅ Add to `OPERATION_METHODS` + wrap with `createOnlyOAS{VERSION}SelectorWrapper`\n13. ❌ **Assuming new OAS meta-schema = new JSON Schema dialect** → ✅ Verify — OAS 3.2 still uses JSON Schema 2020-12\n14. ❌ **Inline version guard in wrap-components** → ✅ Always use `createOnlyOAS{VERSION}ComponentWrapper`; never write `(Original, system) => (props) => { if (...isOAS{VERSION}...) }` by hand — even expanding an existing guard (`isOAS31 || isOAS32`) is wrong; add dedicated wrap-components in the new plugin instead\n\n### ✅ Pre-Submit Checklist\n\n- [ ] All spec changes mapped to components\n- [ ] All components reference spec in comments\n- [ ] Tests use examples from spec\n- [ ] Version detection regex correct\n- [ ] Plugin loaded last in preset\n- [ ] All tests passing (lint + unit + E2E)\n- [ ] Build completes successfully\n- [ ] Documentation updated\n- [ ] No semicolons, double quotes everywhere\n- [ ] @prettier pragma in all new files\n\n### 📚 Quick Links\n\n- **OAS Specs:** https://spec.openapis.org/\n- **OAS 3.1:** https://spec.openapis.org/oas/v3.1.0/\n- **OAS 3.0:** https://spec.openapis.org/oas/v3.0.3/\n- **JSON Schema:** https://json-schema.org/\n- **CLAUDE.md:** Complete codebase guide\n\n### 🔖 Full Guide Navigation\n\nNeed detailed guidance? Jump to these sections:\n\n- **[Prerequisites](#prerequisites)** - Setup and requirements\n- **[Architecture Overview](#architecture-overview)** - Plugin system explained\n- **[Key Design Patterns](#key-design-patterns-from-oas-31)** - Code patterns from OAS 3.1\n- **[Step 1: Analyze Specification](#step-1-analyze-new-oas-version-specification)** - ⭐ Complete spec analysis workflow\n  - [1D: Mapping Table](#step-1d-map-specification-changes-to-swagger-ui-components) - 15+ spec change types\n  - [1E: Real Examples](#step-1e-examples-oas-31-specification-changes--components) - 6 detailed examples\n  - [1H: WebFetch Workflow](#step-1h-using-webfetch-to-analyze-specifications) - Spec analysis with WebFetch\n- **[Step 2-17: Implementation](#step-2-create-plugin-directory-structure)** - Complete implementation steps\n- **[Practical Workflow](#practical-workflow-from-spec-to-components)** - End-to-end example\n- **[Best Practices](#best-practices-iterative-spec-driven-development)** - Spec-driven development\n- **[Common Pitfalls](#common-pitfalls)** - What to avoid\n- **[Final Checklist](#final-checklist)** - Pre-submission verification\n\n---\n\n**Remember: The specification at https://spec.openapis.org/ is your source of truth!**\n\n---\n\n## Prerequisites\n\nBefore starting, ensure:\n- You understand the Swagger UI plugin architecture\n- You've read the CLAUDE.md guide\n- You have the OAS specification document for the new version\n- All tests pass: `npm test`\n\n## Architecture Overview\n\nAdding OAS version support involves:\n\n1. **Plugin Creation** - New plugin following established patterns\n2. **Version Detection** - Regex-based version identifier\n3. **Selector Factories** - Conditional logic for version-specific features\n4. **Component Implementation** - New/wrapped components for rendering\n5. **State Management** - Redux selectors/actions for new features\n6. **Lifecycle Hooks** - afterLoad modifications\n7. **Preset Registration** - Plugin loading order\n8. **Testing** - Unit and E2E tests\n9. **Documentation** - Update guides and README\n\n## Key Design Patterns (from OAS 3.1)\n\n### Pattern 1: Version Detection\n```javascript\nexport const isOAS{VERSION} = (jsSpec) => {\n  const oasVersion = jsSpec.get(\"openapi\")\n  return (\n    typeof oasVersion === \"string\" && /^{MAJOR}\\.{MINOR}\\.(?:[1-9]\\d*|0)$/.test(oasVersion)\n  )\n}\n```\n\n### Pattern 2: Selector Factories\n\n**createOnlyOAS{VERSION}Selector** - Features exclusive to this version:\n```javascript\nexport const createOnlyOAS{VERSION}Selector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(system)\n        : selectedValue\n    } else {\n      return null\n    }\n  }\n```\n\n**createOnlyOAS{VERSION}SelectorWrapper** - Override previous versions:\n```javascript\nexport const createOnlyOAS{VERSION}SelectorWrapper =\n  (selector) =>\n  (oriSelector, system) =>\n  (state, ...args) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(oriSelector, system)\n        : selectedValue\n    } else {\n      return oriSelector(...args)\n    }\n  }\n```\n\n### Pattern 3: Component Wrappers\n\n**⚠️ IMPORTANT: `originalComponent` prop name, not `Ori`**\n\n`createOnlyOAS{VERSION}ComponentWrapper` passes the original component as `originalComponent` in props (NOT `Ori` — that's the OAS3/OAS30ComponentWrapFactory convention). Use `const { originalComponent: Ori } = props` to access it.\n\n**Pattern A — Reuse previous version's component via getComponent:**\n```javascript\nconst ComponentWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => {\n  const system = getSystem()\n  const OAS{PREV_VERSION}Component = system.getComponent(\"OAS{PREV_VERSION}Component\", true)\n  return <OAS{PREV_VERSION}Component />\n})\n```\n\n**Pattern B — Render original component with extra props (e.g. version badge):**\n```javascript\n// Use `originalComponent` (NOT `Ori`) — that's the prop name createOnlyOAS{VERSION}ComponentWrapper passes\nconst OpenAPIVersionWrapper = createOnlyOAS{VERSION}ComponentWrapper((props) => {\n  const { originalComponent: Ori } = props\n  return <Ori oasVersion=\"{VERSION}\" />\n})\n```\n\n### Pattern 4: Function Wrapping\n```javascript\nexport const wrapOAS{VERSION}Fn = (fn, system) => {\n  const { fn: systemFn, specSelectors } = system\n  return Object.fromEntries(\n    Object.entries(fn).map(([name, newImpl]) => {\n      const oriImpl = systemFn[name]\n      const impl = (...args) =>\n        specSelectors.isOAS{VERSION}()\n          ? newImpl(...args)\n          : typeof oriImpl === \"function\"\n            ? oriImpl(...args)\n            : undefined\n      return [name, impl]\n    })\n  )\n}\n```\n\n## Implementation Steps\n\n### Step 1: Analyze New OAS Version Specification\n\n**CRITICAL: Always start by reviewing the official specification at https://spec.openapis.org/**\n\n#### 1A. Access the Official Specification\n\n**Primary Resource:** https://spec.openapis.org/\n\n**Available Versions:**\n- OAS 2.0: https://spec.openapis.org/oas/v2.0/\n- OAS 3.0.x: https://spec.openapis.org/oas/v3.0.3/\n- OAS 3.1.x: https://spec.openapis.org/oas/v3.1.0/\n- Future versions will follow the pattern: https://spec.openapis.org/oas/v{MAJOR}.{MINOR}.{PATCH}/\n\n**What to download:**\n1. The specification document (usually in HTML or Markdown format)\n2. JSON Schema definitions (if available)\n3. Example specification files\n4. Change log or migration guide (if available)\n\n#### 1B. Systematic Specification Analysis\n\nUse the WebFetch tool to retrieve and analyze the specification:\n\n```bash\n# Example for analyzing OAS 4.0 (hypothetical)\nWebFetch(\"https://spec.openapis.org/oas/v4.0.0/\", \"List all new top-level fields, objects, and keywords introduced in this version compared to OAS 3.1\")\n```\n\n**Read these sections carefully:**\n\n1. **Version Number Section**\n   - Confirm the exact version format (e.g., \"4.0.0\", \"3.2.0\")\n   - Note any version detection changes\n\n2. **OpenAPI Object (Root Level)**\n   - New top-level fields (e.g., `webhooks` in OAS 3.1)\n   - Modified existing fields\n   - Removed/deprecated fields\n\n3. **Info Object**\n   - New fields (e.g., `summary` in OAS 3.1)\n   - Changes to `license`, `contact`, etc.\n\n4. **Paths Object & Operations**\n   - New operation-level fields\n   - Changes to parameters, request bodies, responses\n   - New callback syntax or features\n\n5. **Components Object**\n   - New component types\n   - Schema changes (especially JSON Schema version)\n   - New security schemes\n\n6. **Security Object**\n   - New authentication types (e.g., `mutualTLS` in OAS 3.1)\n   - Changes to OAuth2 flows\n   - New security-related fields\n\n7. **Schema Object**\n   - JSON Schema version change (critical!)\n   - New keywords (e.g., `examples` vs `example`)\n   - Type system changes\n\n#### 1C. Create Specification Change Document\n\nCreate a structured document listing all changes:\n\n**Template:**\n```markdown\n# OpenAPI {VERSION} Specification Analysis\n\n## Version Information\n- Version: {MAJOR}.{MINOR}.{PATCH}\n- Release Date: YYYY-MM-DD\n- Previous Version: {PREVIOUS_VERSION}\n- JSON Schema Version: Draft {VERSION} or {YEAR}\n\n## New Top-Level Fields\n1. **`newField`** (Type: Object)\n   - Location: Root level\n   - Purpose: Description from spec\n   - Required: Yes/No\n   - Example from spec: {...}\n   - Swagger UI Impact: Needs new component in BaseLayout\n\n## Modified Existing Fields\n1. **`info`**\n   - New subfields: `summary`, `newField`\n   - Changed behavior: Description\n   - Swagger UI Impact: Need to wrap Info component\n\n## New Operation-Level Features\n1. **`newOperationField`**\n   - Purpose: Description\n   - Swagger UI Impact: Extend Operation component\n\n## New Authentication Types\n1. **`newAuthType`**\n   - Type name: \"newAuthType\"\n   - Fields: {...}\n   - Swagger UI Impact: New auth component needed\n\n## JSON Schema Changes\n- Version change: Draft 2020-12 → Draft 2024\n- New keywords: `keyword1`, `keyword2`\n- Removed keywords: `oldKeyword`\n- Swagger UI Impact: New json-schema plugin needed\n\n## Breaking Changes\n1. Removed `x-deprecated-field`\n2. Changed behavior of `existingField`\n3. Required fields now enforced\n\n## Deprecated Features\n1. `oldField` - Use `newField` instead\n2. `oldAuthType` - Use `newAuthType` instead\n\n## Examples from Specification\n- Link to example files\n- Notable edge cases to test\n```\n\n#### 1D. Map Specification Changes to Swagger UI Components\n\n**CRITICAL MAPPING GUIDE:** Use this table to determine what components to create/modify:\n\n| Spec Change Type | Swagger UI Component Type | Location | Example from OAS 3.1 |\n|-----------------|---------------------------|----------|---------------------|\n| **New Top-Level Field (Object)** | New standalone component | `components/{feature-name}.jsx` | `webhooks` → `Webhooks.jsx` |\n| **New Top-Level Field (String/Primitive)** | Add to existing layout component or create info component | `components/{field-name}.jsx` | `jsonSchemaDialect` → `JsonSchemaDialect.jsx` |\n| **Modified Info Object** | Wrap Info component OR create OAS{VERSION}Info | `wrap-components/info.jsx` | `info.summary` → Wrapped InfoContainer |\n| **New Info Subfield** | Create new component, render in Info | `components/info-{field}.jsx` | `info.license.identifier` → OAS31License |\n| **Modified License/Contact** | Wrap component | `wrap-components/license.jsx` | `license.identifier` → Wrapped License |\n| **New Authentication Type** | New auth component | `components/auth/{type}.jsx` | `mutualTLS` → `MutualTLSAuth.jsx` |\n| **Modified Security Scheme** | Wrap auth selector | `auth-extensions/wrap-selectors.js` | mutualTLS → `definitionsToAuthorize` wrapper |\n| **New Operation Field** | Extend Operation or create plugin selector | `spec-extensions/selectors.js` | N/A in OAS 3.1 |\n| **New Callback Feature** | Extend Callbacks component or wrap | `wrap-components/callbacks.jsx` | Enhanced in OAS 3.1 |\n| **New Parameter Type** | Extend Parameters component | `components/parameters/` | N/A in OAS 3.1 |\n| **New Response Feature** | Extend Responses component | `components/responses/` | N/A in OAS 3.1 |\n| **New Media Type Feature** | Modify media-type component or fn | `oas{PREV}-extensions/fn.js` | File upload detection changes |\n| **JSON Schema Keyword** | New keyword component | `json-schema-{VERSION}-extensions/components/keywords/` | `example` → `JSONSchema202012KeywordExample.jsx` |\n| **JSON Schema Version Change** | Entire new plugin + samples plugin | `plugins/json-schema-{VERSION}/` | JSON Schema 2020-12 plugin |\n| **Modified Schema Rendering** | Wrap schema component | `wrap-components/model.jsx` | Models → OAS31Models wrapper |\n| **Version Detection Field** | Update VersionPragmaFilter | `components/version-pragma-filter.jsx` | Updated for isOAS31 |\n| **Deprecated Field** | Remove or add deprecation warning | Component showing warning | N/A in OAS 3.1 |\n\n#### 1E. Examples: OAS 3.1 Specification Changes → Components\n\n**Example 1: `webhooks` Top-Level Field**\n\n**From Spec (OAS 3.1):**\n```yaml\nopenapi: 3.1.0\nwebhooks:\n  newPet:\n    post:\n      requestBody:\n        description: Information about a new pet\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Pet'\n      responses:\n        '200':\n          description: Return a 200 status\n```\n\n**Mapping Decision:**\n- Type: New top-level field (Object containing operations)\n- Location in spec: Root level, same structure as `paths`\n- Swagger UI component: New standalone component\n- File: `src/core/plugins/oas31/components/webhooks.jsx`\n- Rendering: Reuses Operations component to render webhook operations\n- Selector: `selectWebhooks` in `spec-extensions/selectors.js`\n- Layout integration: Added to BaseLayout or StandaloneLayout\n\n**Example 2: `info.summary` Field**\n\n**From Spec (OAS 3.1):**\n```yaml\ninfo:\n  title: My API\n  summary: A brief summary of the API   # NEW in OAS 3.1\n  description: Detailed description...\n  version: 1.0.0\n```\n\n**Mapping Decision:**\n- Type: New subfield in existing Info object\n- Location: `info.summary`\n- Swagger UI component: Wrap existing Info component\n- File: `src/core/plugins/oas31/wrap-components/info.jsx` + `src/core/plugins/oas31/components/info.jsx`\n- Selector: `selectInfoSummary` (if needed)\n- Rendering: Display summary above or below title\n\n**Example 3: `mutualTLS` Authentication Type**\n\n**From Spec (OAS 3.1):**\n```yaml\ncomponents:\n  securitySchemes:\n    myMutualTLS:\n      type: mutualTLS    # NEW in OAS 3.1\n      description: Client certificate authentication\n```\n\n**Mapping Decision:**\n- Type: New authentication scheme type\n- Location: `components.securitySchemes[name].type`\n- Swagger UI component: New auth component\n- File: `src/core/plugins/oas31/components/auth/mutual-tls-auth.jsx`\n- Selector wrapper: `auth-extensions/wrap-selectors.js` → `definitionsToAuthorize`\n- Rendering: Display in authorize modal with certificate upload UI\n\n**Example 4: `license.identifier` Field**\n\n**From Spec (OAS 3.1):**\n```yaml\ninfo:\n  license:\n    name: Apache 2.0\n    identifier: Apache-2.0    # NEW in OAS 3.1 (SPDX ID)\n    url: https://www.apache.org/licenses/LICENSE-2.0.html\n```\n\n**Mapping Decision:**\n- Type: New optional field in license object (alternative to url)\n- Location: `info.license.identifier`\n- Swagger UI component: Wrap License component + create selector\n- File: `src/core/plugins/oas31/wrap-components/license.jsx` + selector in `spec-extensions/selectors.js`\n- Logic: If `identifier` exists, construct URL from SPDX registry\n- Rendering: Make license text a hyperlink to SPDX page\n\n**Example 5: JSON Schema 2020-12 Keywords**\n\n**From Spec (OAS 3.1):**\n```yaml\n# OAS 3.1 uses JSON Schema 2020-12 which includes:\ncomponents:\n  schemas:\n    Pet:\n      type: object\n      properties:\n        name:\n          type: string\n          example: Fluffy        # Changed from 'examples' array in OAS 3.0\n      xml:                       # Now a JSON Schema keyword, not OAS-specific\n        name: pet\n      externalDocs:              # Now a JSON Schema keyword\n        url: https://example.com\n      discriminator:             # Now a JSON Schema keyword\n        propertyName: petType\n```\n\n**Mapping Decision:**\n- Type: JSON Schema version upgrade (Draft 7 → 2020-12)\n- Location: Schema objects throughout spec\n- Swagger UI components: Entire new plugin\n- Files:\n  - `src/core/plugins/json-schema-2020-12/` (main plugin)\n  - `src/core/plugins/json-schema-2020-12-samples/` (sample generation)\n  - `src/core/plugins/json-schema-2020-12/components/keywords/example.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/xml.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/discriminator.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/external-docs.jsx`\n- Integration: OAS31 plugin extends JSON Schema 2020-12 keywords in `json-schema-2020-12-extensions/`\n\n**Example 6: `jsonSchemaDialect` Top-Level Field**\n\n**From Spec (OAS 3.1):**\n```yaml\nopenapi: 3.1.0\njsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base  # NEW in OAS 3.1\n```\n\n**Mapping Decision:**\n- Type: New top-level field (String/URI)\n- Location: Root level\n- Swagger UI component: Simple display component\n- File: `src/core/plugins/oas31/components/json-schema-dialect.jsx`\n- Selector: `selectJsonSchemaDialectField` in `spec-extensions/selectors.js`\n- Rendering: Show in info section with warning if non-default\n\n#### 1F. Specification Analysis Checklist\n\nUse WebFetch and Read tools to systematically check:\n\n- [ ] **Accessed official spec at https://spec.openapis.org/**\n- [ ] **Downloaded specification document**\n- [ ] **Read version number section**\n- [ ] **Analyzed OpenAPI Object (root level) changes**\n- [ ] **Reviewed Info Object modifications**\n- [ ] **Checked Paths/Operations changes**\n- [ ] **Examined Components Object updates**\n- [ ] **Identified Security Scheme changes**\n- [ ] **Analyzed Schema Object / JSON Schema version**\n- [ ] **Listed all new top-level fields**\n- [ ] **Listed all modified existing fields**\n- [ ] **Documented breaking changes**\n- [ ] **Identified deprecated features**\n- [ ] **Found example specifications**\n- [ ] **Created specification change document**\n- [ ] **Mapped changes to Swagger UI components using table above**\n- [ ] **Prioritized implementation order**\n\n#### 1G. Questions to Answer During Analysis\n\n**Version Type:**\n- Is this a major version (4.0) or minor version (3.2)?\n- Are there breaking changes?\n- Is backward compatibility maintained?\n\n**JSON Schema:**\n- Does it use a new JSON Schema version?\n- What new keywords are available?\n- Are there removed/deprecated keywords?\n\n**Top-Level Changes:**\n- What new top-level fields are added?\n- Which existing fields have new subfields?\n- Any removed top-level fields?\n\n**Operation Changes:**\n- Are there new operation-level features?\n- Changes to parameters, request bodies, responses?\n- New callback or link syntax?\n\n**Security Changes:**\n- What authentication types are new/changed?\n- OAuth2 flow modifications?\n- New security requirements?\n\n**Media Type Changes:**\n- Are there new media type features?\n- File upload handling changes?\n- Encoding changes?\n\n**Component Mapping:**\n- Which components need to be created from scratch?\n- Which existing components need to be wrapped?\n- What selectors are required?\n- Are new plugins needed (e.g., for JSON Schema)?\n\n**Implementation Priority:**\n- What's the critical path for basic rendering?\n- Which features can be added incrementally?\n- What has the highest user impact?\n\n### Step 1H: Using WebFetch to Analyze Specifications\n\n**Always use WebFetch tool to retrieve and analyze the specification systematically.**\n\n**Step-by-step WebFetch workflow:**\n\n1. **Fetch the specification landing page:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Provide a summary of this OpenAPI Specification version, including links to the full specification document and any change logs or migration guides.\"\n)\n```\n\n2. **Analyze the specification structure:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all top-level fields in the OpenAPI Object for this version. For each field, indicate if it is new, modified, or unchanged from version {PREVIOUS_VERSION}.\"\n)\n```\n\n3. **Deep dive into new features:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Describe the '{NEW_FIELD}' field in detail: its type, structure, purpose, whether it's required, and provide examples from the specification.\"\n)\n```\n\n4. **Analyze security changes:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all security scheme types supported in this version. Highlight any new or changed security scheme types compared to {PREVIOUS_VERSION}.\"\n)\n```\n\n5. **Check JSON Schema compatibility:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"What version of JSON Schema does this OpenAPI Specification version use? List any specific dialect or modifications to JSON Schema.\"\n)\n```\n\n6. **Find example specifications:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Provide links to example OpenAPI specification files for this version, particularly examples that demonstrate new features.\"\n)\n```\n\n**Real example from analyzing OAS 3.1:**\n\n```javascript\n// 1. Initial analysis\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"List all new fields and features introduced in OpenAPI 3.1.0 compared to OpenAPI 3.0.3\"\n)\n\n// Response would include:\n// - webhooks field (new top-level)\n// - info.summary (new)\n// - info.license.identifier (new)\n// - jsonSchemaDialect (new top-level)\n// - mutualTLS security scheme type (new)\n// - JSON Schema 2020-12 (changed from Draft 7)\n\n// 2. Deep dive into webhooks\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"Explain the 'webhooks' field in detail: structure, purpose, and provide a complete example\"\n)\n\n// 3. Understand JSON Schema changes\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"What are the differences between JSON Schema Draft 7 (used in OAS 3.0) and JSON Schema 2020-12 (used in OAS 3.1) that affect schema definitions?\"\n)\n```\n\n**Pro tip:** Use multiple targeted queries rather than one broad query. This gives more precise information for each component you need to implement.\n\n### Step 2: Create Plugin Directory Structure\n\n**Directory:** `src/core/plugins/oas{VERSION_NUMBER}/`\n\n**Files to Create:**\n```\nsrc/core/plugins/oas{VERSION_NUMBER}/\n├── index.js                          # Main plugin export\n├── fn.js                             # Selector/function factories\n├── selectors.js                      # Version-specific selectors (if needed)\n├── after-load.js                     # Lifecycle hook\n├── auth-extensions/                  # Authentication features\n│   └── wrap-selectors.js\n├── oas{PREVIOUS_VERSION}-extensions/ # Extensions to previous version\n│   └── fn.js\n├── spec-extensions/                  # Spec-level features\n│   ├── selectors.js\n│   └── wrap-selectors.js\n├── components/                       # New components\n│   ├── version-pragma-filter.jsx\n│   ├── {new-feature-1}.jsx\n│   └── auth/\n│       └── {new-auth-type}.jsx\n├── wrap-components/                  # Component wrappers\n│   ├── info.jsx\n│   ├── license.jsx\n│   └── {existing-component}.jsx\n└── json-schema-{VERSION}-extensions/ # If new JSON Schema version\n    ├── fn.js\n    ├── components/keywords/\n    └── wrap-components/keywords/\n```\n\n**Create the directories:**\n```bash\nmkdir -p src/core/plugins/oas{VERSION_NUMBER}/{auth-extensions,oas{PREVIOUS_VERSION}-extensions,spec-extensions,components/auth,wrap-components}\n```\n\n### Step 3: Implement Version Detection (fn.js)\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/fn.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\n/**\n * Detects if a spec is OpenAPI {MAJOR}.{MINOR}.x\n */\nexport const isOAS{VERSION} = (jsSpec) => {\n  const oasVersion = jsSpec.get(\"openapi\")\n  return (\n    typeof oasVersion === \"string\" &&\n    /^{MAJOR}\\.{MINOR}\\.(?:[1-9]\\d*|0)$/.test(oasVersion)\n  )\n}\n\n/**\n * Creates a selector that only returns a value for OAS {VERSION} specs\n */\nexport const createOnlyOAS{VERSION}Selector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(system)\n        : selectedValue\n    } else {\n      return null\n    }\n  }\n\n/**\n * Creates a selector wrapper that uses new impl for OAS {VERSION}, falls back to original\n */\nexport const createOnlyOAS{VERSION}SelectorWrapper =\n  (selector) =>\n  (oriSelector, system) =>\n  (state, ...args) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(oriSelector, system)\n        : selectedValue\n    } else {\n      return oriSelector(...args)\n    }\n  }\n\n/**\n * Creates a system-aware selector\n */\nexport const createSystemSelector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    const selectedValue = selector(state, system, ...args)\n    return typeof selectedValue === \"function\"\n      ? selectedValue(system)\n      : selectedValue\n  }\n\n/**\n * Creates a component wrapper that only renders for OAS {VERSION}.\n * When active, passes `originalComponent` (the unwrapped original) and\n * `getSystem` as extra props. Access the original via:\n *   const { originalComponent: Ori } = props\n * NOT via `props.Ori` — that's the OAS3/OAS30ComponentWrapFactory convention.\n */\nexport const createOnlyOAS{VERSION}ComponentWrapper =\n  (Component) => (Original, system) => (props) => {\n    if (system.specSelectors.isOAS{VERSION}()) {\n      return (\n        <Component\n          {...props}\n          originalComponent={Original}\n          getSystem={system.getSystem}\n        />\n      )\n    }\n\n    return <Original {...props} />\n  }\n\n/**\n * Wraps functions to conditionally use OAS {VERSION} implementations\n */\nexport const wrapOAS{VERSION}Fn = (fn, system) => {\n  const { fn: systemFn, specSelectors } = system\n  return Object.fromEntries(\n    Object.entries(fn).map(([name, newImpl]) => {\n      const oriImpl = systemFn[name]\n      const impl = (...args) =>\n        specSelectors.isOAS{VERSION}()\n          ? newImpl(...args)\n          : typeof oriImpl === \"function\"\n            ? oriImpl(...args)\n            : undefined\n      return [name, impl]\n    })\n  )\n}\n```\n\n### Step 4: Create Main Plugin Export (index.js)\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/index.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport afterLoad from \"./after-load.js\"\nimport {\n  isOAS{VERSION},\n  createSystemSelector,\n  createOnlyOAS{VERSION}Selector,\n  createOnlyOAS{VERSION}SelectorWrapper,\n  createOnlyOAS{VERSION}ComponentWrapper,\n} from \"./fn.js\"\n\n// Import spec extensions\nimport * as specExtensionsSelectors from \"./spec-extensions/selectors.js\"\nimport * as specExtensionsWrapSelectors from \"./spec-extensions/wrap-selectors.js\"\n\n// Import auth extensions\nimport * as authExtensionsWrapSelectors from \"./auth-extensions/wrap-selectors.js\"\n\n// Import OAS{PREVIOUS_VERSION} extensions\nimport * as oas{PREVIOUS_VERSION}ExtensionsFn from \"./oas{PREVIOUS_VERSION}-extensions/fn.js\"\n\n// Import components\nimport VersionPragmaFilter from \"./components/version-pragma-filter.jsx\"\n// Import new feature components here\n\n// Import wrap components\nimport InfoWrapper from \"./wrap-components/info.jsx\"\n// Import other wrappers here\n\n/**\n * OpenAPI {MAJOR}.{MINOR} Plugin\n *\n * Adds support for OpenAPI Specification {MAJOR}.{MINOR}.x\n *\n * This plugin should be loaded AFTER:\n * - oas{PREVIOUS_VERSION} plugin\n * - json-schema-{JSON_SCHEMA_VERSION} plugin (if applicable)\n *\n * It wraps and overrides components/selectors from previous versions.\n */\nconst OpenAPI{VERSION}Plugin = ({ fn }) => {\n  return {\n    fn: {\n      oas{VERSION_NUMBER}: {\n        isOAS{VERSION},\n        createSystemSelector,\n        createOnlyOAS{VERSION}Selector,\n        createOnlyOAS{VERSION}SelectorWrapper,\n        createOnlyOAS{VERSION}ComponentWrapper,\n      },\n    },\n    components: {\n      // New components\n      OAS{VERSION}VersionPragmaFilter: VersionPragmaFilter,\n      // Add new feature components here\n    },\n    wrapComponents: {\n      // Wrapped components\n      VersionPragmaFilter: (Ori, system) =>\n        system.specSelectors.isOAS{VERSION}()\n          ? system.getComponent(\"OAS{VERSION}VersionPragmaFilter\", true)\n          : Ori,\n      InfoContainer: InfoWrapper,\n      // Add other wrappers here\n    },\n    statePlugins: {\n      spec: {\n        selectors: {\n          // Add version detection selector\n          isOAS{VERSION}: createSystemSelector(specExtensionsSelectors.selectIsOAS{VERSION}),\n          // Add new feature selectors here\n        },\n        wrapSelectors: {\n          // Wrap previous version selectors if needed\n          ...specExtensionsWrapSelectors,\n        },\n      },\n      auth: {\n        wrapSelectors: {\n          // Add auth extensions if needed\n          ...authExtensionsWrapSelectors,\n        },\n      },\n      oas{VERSION_NUMBER}: {\n        selectors: {\n          // Plugin-specific selectors\n        },\n      },\n    },\n    afterLoad,\n  }\n}\n\nexport default OpenAPI{VERSION}Plugin\n```\n\n### Step 5: Implement Spec Extensions\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/selectors.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createSelector } from \"reselect\"\nimport { isOAS{VERSION} } from \"../fn.js\"\n\n/**\n * Detects if the current spec is OAS {VERSION}\n */\nexport const selectIsOAS{VERSION} = (state, system) => () => {\n  const spec = system.specSelectors.specJson()\n  return isOAS{VERSION}(spec)\n}\n\n// Add selectors for new OAS {VERSION} fields here\n// Example:\n// export const selectNewField = createSelector(\n//   (state) => state,\n//   (state) => {\n//     const spec = state.getIn([\"spec\", \"json\"])\n//     return spec.get(\"newField\")\n//   }\n// )\n```\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/wrap-selectors.js`\n\n**⚠️ Minor version: DON'T wrap `isOAS{PREV}` unless the regex actually matches both versions.** For example, OAS 3.1's `isOAS31` regex (`/^3\\.1\\./`) will never match `3.2.x`, so wrapping it to return `false` is dead code. Only add the `isOAS{PREV}` override if the previous version's detection regex would incorrectly match the new version.\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createOnlyOAS{VERSION}SelectorWrapper } from \"../fn.js\"\n\n// Ensure OAS {VERSION} specs are recognized as OAS 3.x (needed when major version number didn't change)\nexport const isOAS3 =\n  (oriSelector, system) =>\n  (state, ...args) => {\n    const isOAS{VERSION} = system.specSelectors.isOAS{VERSION}()\n    return isOAS{VERSION} || oriSelector(...args)\n  }\n\n// ONLY add isOAS{PREV} wrapper if the previous version's regex could match this new version.\n// For a minor version bump (e.g. 3.1 → 3.2), the previous regex won't match, so DON'T add this.\n// export const isOAS{PREV} = createOnlyOAS{VERSION}SelectorWrapper((state) => () => false)\n```\n\n### Step 6: Create Version Pragma Filter Component\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst OAS{VERSION}VersionPragmaFilter = ({ bypass, isSwagger2, isOAS3, isOAS{PREVIOUS_VERSION}, isOAS{VERSION} }) => {\n  // Handle version detection logic\n  const isAmbiguous =\n    (isSwagger2 && isOAS3) ||\n    (isSwagger2 && isOAS{PREVIOUS_VERSION}) ||\n    (isSwagger2 && isOAS{VERSION}) ||\n    (isOAS3 && isOAS{PREVIOUS_VERSION}) ||\n    (isOAS3 && isOAS{VERSION}) ||\n    (isOAS{PREVIOUS_VERSION} && isOAS{VERSION})\n\n  const isMissing = !isSwagger2 && !isOAS3 && !isOAS{PREVIOUS_VERSION} && !isOAS{VERSION}\n\n  if (bypass) {\n    return null\n  }\n\n  if (isAmbiguous) {\n    return (\n      <div className=\"version-pragma\">\n        <div className=\"version-pragma__message version-pragma__message--ambiguous\">\n          <div>\n            <h3>Unable to render this document, as it contains multiple OpenAPI version fields.</h3>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  if (isMissing) {\n    return (\n      <div className=\"version-pragma\">\n        <div className=\"version-pragma__message version-pragma__message--missing\">\n          <div>\n            <h3>Unable to render this document, as it doesn&apos;t contain an OpenAPI version field.</h3>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  return null\n}\n\nOAS{VERSION}VersionPragmaFilter.propTypes = {\n  bypass: PropTypes.bool,\n  isSwagger2: PropTypes.bool.isRequired,\n  isOAS3: PropTypes.bool.isRequired,\n  isOAS{PREVIOUS_VERSION}: PropTypes.bool.isRequired,\n  isOAS{VERSION}: PropTypes.bool.isRequired,\n}\n\nOAS{VERSION}VersionPragmaFilter.defaultProps = {\n  bypass: false,\n}\n\nexport default OAS{VERSION}VersionPragmaFilter\n```\n\n### Step 7: Implement New Feature Components\n\nFor each new feature in the OAS specification:\n\n**Example: New Feature Component**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst NewFeature = ({ getComponent, specSelectors }) => {\n  const newFeature = specSelectors.selectNewFeature()\n\n  if (!newFeature || !newFeature.size) {\n    return null\n  }\n\n  // Render the new feature\n  return (\n    <div className=\"opblock-tag-section\">\n      <h3>New Feature</h3>\n      {/* Render logic here */}\n    </div>\n  )\n}\n\nNewFeature.propTypes = {\n  specSelectors: PropTypes.object.isRequired,\n  getComponent: PropTypes.func.isRequired,\n}\n\nexport default NewFeature\n```\n\n### Step 8: Create Component Wrappers\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/wrap-components/info.jsx`\n\n**⚠️ Minor version (e.g. 3.2): don't create a new Info component.** If the Info object is identical to the previous version, reuse `OAS{PREV_VERSION}Info` via `getComponent` instead of copying the whole component. Only create a new Info component for major versions with significant structural changes.\n\n**Template (minor version — reuse previous Info):**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport { createOnlyOAS{VERSION}ComponentWrapper } from \"../fn.js\"\n\nconst InfoWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => {\n  const system = getSystem()\n  const OAS{PREV_VERSION}Info = system.getComponent(\"OAS{PREV_VERSION}Info\", true)\n  return <OAS{PREV_VERSION}Info />\n})\n\nexport default InfoWrapper\n```\n\n**Also — OpenAPIVersion wrapper (minor version — change version badge only):**\n\nFor minor versions where the only Info difference is the version badge, use the OpenAPIVersion wrapper pattern instead of wrapping InfoContainer at all:\n\n```javascript\n// wrap-components/openapi-version.jsx\n/**\n * @prettier\n */\nimport React from \"react\"\nimport { createOnlyOAS{VERSION}ComponentWrapper } from \"../fn.js\"\n\nexport default createOnlyOAS{VERSION}ComponentWrapper((props) => {\n  const { originalComponent: Ori } = props  // NOT `Ori` from props directly — use `originalComponent`\n  return <Ori oasVersion=\"{MAJOR}.{MINOR}\" />\n})\n```\n\nThen register it in index.js:\n```javascript\nwrapComponents: {\n  OpenAPIVersion: OpenAPIVersionWrapper,  // changes the version badge shown in the Info header\n}\n```\n\n### Step 9: Implement afterLoad Hook\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/after-load.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { wrapOAS{VERSION}Fn } from \"./fn.js\"\n\n/**\n * afterLoad hook for OAS {VERSION} plugin\n *\n * This hook runs after all plugins are loaded and allows\n * modification of the system's functions and behaviors.\n */\nfunction afterLoad({ fn, getSystem }) {\n  const system = getSystem()\n\n  // Override functions that differ in OAS {VERSION}\n  if (typeof fn.sampleFromSchema === \"function\") {\n    // Example: Wrap sample generation if JSON Schema version changed\n    // const wrappedFns = wrapOAS{VERSION}Fn({\n    //   sampleFromSchema: fn.jsonSchema{VERSION}.sampleFromSchema,\n    // }, system)\n    // Object.assign(this.fn, wrappedFns)\n  }\n\n  // Override other functions as needed\n  // Example: File upload detection\n  // if (typeof fn.isFileUploadIntended === \"function\") {\n  //   const wrappedFns = wrapOAS{VERSION}Fn({\n  //     isFileUploadIntended: makeIsFileUploadIntended(system),\n  //   }, system)\n  //   Object.assign(this.fn, wrappedFns)\n  // }\n}\n\nexport default afterLoad\n```\n\n### Step 10: Handle Authentication Changes\n\nIf new authentication types are introduced:\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/auth/{auth-type}.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst NewAuthType = ({ schema, name, getComponent, onChange, authorized }) => {\n  const authValue = authorized && authorized.getIn([name])\n\n  const Input = getComponent(\"Input\")\n  const Button = getComponent(\"Button\")\n\n  // Render auth UI\n  return (\n    <div>\n      <h4>{schema.get(\"description\") || `${name} (${schema.get(\"type\")})`}</h4>\n      {/* Auth UI here */}\n    </div>\n  )\n}\n\nNewAuthType.propTypes = {\n  schema: PropTypes.object.isRequired,\n  name: PropTypes.string.isRequired,\n  getComponent: PropTypes.func.isRequired,\n  onChange: PropTypes.func.isRequired,\n  authorized: PropTypes.object,\n}\n\nexport default NewAuthType\n```\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/auth-extensions/wrap-selectors.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createOnlyOAS{VERSION}SelectorWrapper } from \"../fn.js\"\nimport { Map } from \"immutable\"\n\n/**\n * Wraps definitionsToAuthorize to include new auth types\n */\nexport const definitionsToAuthorize = createOnlyOAS{VERSION}SelectorWrapper(\n  (state, system) =>\n    (oriSelector) => {\n      const definitions = oriSelector()\n      const securityDefinitions = system.specSelectors.securityDefinitions() || Map()\n\n      // Add new auth types to definitions\n      return definitions.map((definition) => {\n        const schema = securityDefinitions.get(definition.get(\"name\"))\n        if (schema && schema.get(\"type\") === \"newAuthType\") {\n          // Add new auth type logic\n          return definition.set(\"newAuthType\", true)\n        }\n        return definition\n      })\n    }\n)\n```\n\n### Step 11: Register Plugin in Preset\n\n**File:** `src/core/presets/apis/index.js`\n\n**Add import:**\n```javascript\nimport OpenAPI{VERSION}Plugin from \"../../plugins/oas{VERSION_NUMBER}/index.js\"\n```\n\n**Add to preset array (IMPORTANT: add at the end):**\n```javascript\nexport default function PresetApis() {\n  return [\n    BasePreset,\n    OpenAPI30Plugin,\n    // ... other plugins\n    OpenAPI{PREVIOUS_VERSION}Plugin,\n    OpenAPI{VERSION}Plugin,  // Load LAST to override previous versions\n  ]\n}\n```\n\n**Why load last?**\n- Wrap-components override previous versions\n- Wrap-selectors intercept earlier selectors\n- afterLoad modifications apply to dependencies\n\n### Step 12: Add Unit Tests\n\n**Directory:** `test/unit/core/plugins/oas{VERSION_NUMBER}/`\n\n**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/fn.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { fromJS } from \"immutable\"\nimport { isOAS{VERSION} } from \"src/core/plugins/oas{VERSION_NUMBER}/fn.js\"\n\ndescribe(\"oas{VERSION_NUMBER} plugin - fn - isOAS{VERSION}\", () => {\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.0\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.1\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.1\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.25\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.25\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should NOT match OpenAPI {MAJOR}.{MINOR}\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match OpenAPI {MAJOR}.{MINOR}.01 (leading zero)\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.01\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match OpenAPI {DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0\", () => {\n    const spec = fromJS({ openapi: \"{DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match swagger: 2.0\", () => {\n    const spec = fromJS({ swagger: \"2.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should handle null spec\", () => {\n    const spec = fromJS({})\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n})\n```\n\n**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport { shallow } from \"enzyme\"\nimport OAS{VERSION}VersionPragmaFilter from \"src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx\"\n\ndescribe(\"OAS{VERSION}VersionPragmaFilter\", () => {\n  it(\"should render nothing when bypass is true\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={true}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.type()).toBe(null)\n  })\n\n  it(\"should render nothing when version is valid\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.type()).toBe(null)\n  })\n\n  it(\"should render error when version is ambiguous\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={true}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.find(\".version-pragma__message--ambiguous\")).toHaveLength(1)\n  })\n\n  it(\"should render error when version is missing\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={false}\n      />\n    )\n    expect(wrapper.find(\".version-pragma__message--missing\")).toHaveLength(1)\n  })\n})\n```\n\n### Step 13: Add E2E Tests\n\n**Directory:** `test/e2e-cypress/e2e/features/oas{VERSION_NUMBER}/`\n\n**Create test spec file:**\n```javascript\n/**\n * @prettier\n */\n\ndescribe(\"OpenAPI {MAJOR}.{MINOR} features\", () => {\n  it(\"should detect OAS {VERSION} version\", () => {\n    cy.visit(\"/oas{VERSION_NUMBER}-spec.html\")\n    cy.get(\".information-container .version\").should(\"contain\", \"{MAJOR}.{MINOR}.0\")\n  })\n\n  // Add tests for new features\n  it(\"should render new feature X\", () => {\n    cy.visit(\"/oas{VERSION_NUMBER}-spec.html\")\n    cy.get(\".opblock-tag-section\").should(\"contain\", \"New Feature\")\n  })\n})\n```\n\n**Add test fixtures:**\n- Create sample OAS {VERSION} spec in `test/e2e-cypress/static/documents/oas{VERSION_NUMBER}/`\n- Create HTML fixture in `test/e2e-cypress/static/` referencing the spec\n\n### Step 14: Update Documentation\n\n**Files to update:**\n\n1. **README.md** - Add OAS {VERSION} to supported versions\n2. **CLAUDE.md** - Add plugin to list and update version compatibility\n3. **docs/usage/version-detection.md** - Document new version detection\n4. **package.json** - Update description if needed\n\n**Example README.md update:**\n```markdown\n### OpenAPI Specification Compatibility\n\n- **OpenAPI 2.0** (Swagger)\n- **OpenAPI 3.0.x**\n- **OpenAPI 3.1.x**\n- **OpenAPI {MAJOR}.{MINOR}.x** ⭐ NEW\n```\n\n### Step 15: Verify Build\n\n**Run full build:**\n```bash\nnpm run clean\nnpm run build\n```\n\n**Check dist/ output:**\n- `dist/swagger-ui.js` - Should include new plugin\n- `dist/swagger-ui.css` - Should include new styles (if any)\n- Bundle size should be reasonable\n\n**Run artifact tests:**\n```bash\nnpm run test:artifact\n```\n\n### Step 16: Run Full Test Suite\n\n```bash\nnpm run lint-errors      # ESLint errors only\nnpm run test:unit        # Jest unit tests\nnpm run cy:ci            # Cypress E2E tests\n```\n\n**All tests must pass before submitting PR.**\n\n### Step 17: Create Pull Request\n\n**Commit message format:**\n```\nfeat(oas{VERSION_NUMBER}): add support for OpenAPI {MAJOR}.{MINOR}\n\nImplement OpenAPI {MAJOR}.{MINOR}.x specification support with:\n- Version detection and plugin architecture\n- New feature X rendering\n- New authentication type Y support\n- JSON Schema {VERSION} integration (if applicable)\n\nCloses #{ISSUE_NUMBER}\n```\n\n**PR checklist:**\n- [ ] All tests passing\n- [ ] New feature components implemented\n- [ ] Unit tests added\n- [ ] E2E tests added\n- [ ] Documentation updated\n- [ ] Build completes successfully\n- [ ] No ESLint errors\n- [ ] Follows existing code patterns\n\n## Common Pitfalls\n"},"items":[{"name":"add-oas-support.md","path":".claude/skills/add-oas-support.md","rawUrl":"https://raw.githubusercontent.com/swagger-api/swagger-ui/HEAD/.claude/skills/add-oas-support.md","title":"add-oas-support","category":"anthropic-skill","format":"markdown","content":"---\nname: add-oas-support\ndescription: Add support for a new OpenAPI Specification version to Swagger UI\nargs:\n  version:\n    description: \"OpenAPI version to add support for (e.g., 3.2, 4.0)\"\n    required: true\n    type: string\n  type:\n    description: \"Version type: 'major' for new major version, 'minor' for patch/minor\"\n    required: false\n    type: string\n    default: \"minor\"\n---\n\n# Add OpenAPI Specification Version Support\n\nThis skill guides you through adding support for a new OpenAPI Specification (OAS) version to Swagger UI, following the established architectural patterns from OAS 3.1 implementation.\n\n---\n\n## 📌 Quick Reference\n\n> **New to this skill?** Skip to [Prerequisites](#prerequisites) for the full guide.\n> **Already familiar?** Use this quick reference for rapid development.\n\n### 🚀 Quick Start\n\n```bash\n# Major version (e.g., OAS 4.0)\n/add-oas-support --version 4.0 --type major\n\n# Minor version (e.g., OAS 3.2)\n/add-oas-support --version 3.2 --type minor\n```\n\n### 📋 Essential Checklist\n\n#### Phase 1: Specification Analysis ⭐ MOST IMPORTANT\n- [ ] Access official spec at **https://spec.openapis.org/oas/v{VERSION}/**\n- [ ] Use WebFetch to analyze spec systematically\n- [ ] Create specification change document\n- [ ] Map changes to components using [mapping table](#step-1d-map-specification-changes-to-swagger-ui-components)\n\n#### Phase 2: Implementation\n- [ ] Create plugin directory structure\n- [ ] Implement version detection (`isOAS{VERSION}`)\n- [ ] Create selector factories\n- [ ] Implement components for each spec change\n- [ ] Wrap existing components if modified\n- [ ] Register plugin in preset (LAST position)\n\n#### Phase 3: Testing & Documentation\n- [ ] Add unit tests\n- [ ] Add E2E tests with spec examples\n- [ ] Update documentation\n- [ ] Verify build & run full test suite\n\n### 🔍 WebFetch Queries for Spec Analysis\n\n```javascript\n// 1. Fetch main spec differences\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all new top-level fields, modified fields, and removed fields compared to version {PREV_VERSION}\"\n)\n\n// 2. Analyze new feature\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Describe the '{NEW_FIELD}' field: structure, type, purpose, required/optional, and provide examples\"\n)\n\n// 3. Check JSON Schema version\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"What JSON Schema version does this use? List changes from {PREV_JSON_SCHEMA_VERSION}\"\n)\n\n// 4. Security schemes\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all security scheme types, highlighting new or changed types\"\n)\n```\n\n### 🗺️ Spec Change → Component Mapping (Quick)\n\n| Spec Change | Component Action | File Location |\n|-------------|------------------|---------------|\n| **New top-level field (Object)** | Create new component | `components/{field}.jsx` |\n| **New top-level field (String)** | Add to info or create display | `components/{field}.jsx` |\n| **Modified Info object** | Wrap Info component | `wrap-components/info.jsx` |\n| **New info subfield** | Create component + wrap Info | `components/info-{field}.jsx` |\n| **New auth type** | Create auth component | `components/auth/{type}.jsx` |\n| **Modified security** | Wrap auth selector | `auth-extensions/wrap-selectors.js` |\n| **New operation field** | Extend Operation/selector | `spec-extensions/selectors.js` |\n| **JSON Schema keyword** | Create keyword component | `json-schema-{V}-extensions/` |\n| **JSON Schema version** | Create entire new plugin | `plugins/json-schema-{V}/` |\n\nSee [full mapping table with examples](#step-1d-map-specification-changes-to-swagger-ui-components) for detailed guidance.\n\n### 📝 Component Implementation Pattern\n\n**For each new feature:**\n\n1. **Check spec first:**\n   ```javascript\n   WebFetch(url, \"Describe {field} structure, type, examples\")\n   ```\n\n2. **Create selector:**\n   ```javascript\n   // spec-extensions/selectors.js\n   export const selectNewField = createSelector(\n     (state) => state,\n     (state) => state.getIn([\"spec\", \"json\", \"newField\"])\n   )\n   ```\n\n3. **Create component:**\n   ```javascript\n   // components/new-field.jsx\n   const NewField = ({ specSelectors, getComponent }) => {\n     const data = specSelectors.selectNewField()\n     if (!data) return null\n     return <div>{/* render based on spec structure */}</div>\n   }\n   ```\n\n4. **Register in plugin:**\n   ```javascript\n   // index.js\n   components: { NewField },\n   statePlugins: {\n     spec: {\n       selectors: {\n         selectNewField: createOnlyOAS{V}Selector(selectNewField)\n       }\n     }\n   }\n   ```\n\n5. **Add tests** (unit + E2E with spec examples)\n\n### ⚠️ Common Pitfalls\n\n1. ❌ **Guessing field structure** → ✅ Always check spec with WebFetch\n2. ❌ **Forgetting @prettier pragma** → ✅ Add to all new files\n3. ❌ **Wrong plugin load order** → ✅ New plugin LAST in preset\n4. ❌ **Using semicolons** → ✅ No semicolons (project convention)\n5. ❌ **Single quotes** → ✅ Use double quotes\n6. ❌ **Skipping spec examples** → ✅ Use as test fixtures\n7. ❌ **Hardcoded assumptions** → ✅ Verify everything in spec\n8. ❌ **`props.Ori` in ComponentWrapper** → ✅ Use `props.originalComponent` (see Pattern 3)\n9. ❌ **Copying entire Info component for minor version** → ✅ Use OpenAPIVersion wrapper + `getComponent(\"OAS{PREV}Info\")`\n10. ❌ **OAS{VERSION} logic in OAS{PREV} plugin** → ✅ Each version's logic lives in its own plugin\n11. ❌ **`isOAS{PREV}` wrapper on minor version** → ✅ Only add if regex overlaps; minor bumps don't need it\n12. ❌ **New HTTP method in core `validOperationMethods`** → ✅ Add to `OPERATION_METHODS` + wrap with `createOnlyOAS{VERSION}SelectorWrapper`\n13. ❌ **Assuming new OAS meta-schema = new JSON Schema dialect** → ✅ Verify — OAS 3.2 still uses JSON Schema 2020-12\n14. ❌ **Inline version guard in wrap-components** → ✅ Always use `createOnlyOAS{VERSION}ComponentWrapper`; never write `(Original, system) => (props) => { if (...isOAS{VERSION}...) }` by hand — even expanding an existing guard (`isOAS31 || isOAS32`) is wrong; add dedicated wrap-components in the new plugin instead\n\n### ✅ Pre-Submit Checklist\n\n- [ ] All spec changes mapped to components\n- [ ] All components reference spec in comments\n- [ ] Tests use examples from spec\n- [ ] Version detection regex correct\n- [ ] Plugin loaded last in preset\n- [ ] All tests passing (lint + unit + E2E)\n- [ ] Build completes successfully\n- [ ] Documentation updated\n- [ ] No semicolons, double quotes everywhere\n- [ ] @prettier pragma in all new files\n\n### 📚 Quick Links\n\n- **OAS Specs:** https://spec.openapis.org/\n- **OAS 3.1:** https://spec.openapis.org/oas/v3.1.0/\n- **OAS 3.0:** https://spec.openapis.org/oas/v3.0.3/\n- **JSON Schema:** https://json-schema.org/\n- **CLAUDE.md:** Complete codebase guide\n\n### 🔖 Full Guide Navigation\n\nNeed detailed guidance? Jump to these sections:\n\n- **[Prerequisites](#prerequisites)** - Setup and requirements\n- **[Architecture Overview](#architecture-overview)** - Plugin system explained\n- **[Key Design Patterns](#key-design-patterns-from-oas-31)** - Code patterns from OAS 3.1\n- **[Step 1: Analyze Specification](#step-1-analyze-new-oas-version-specification)** - ⭐ Complete spec analysis workflow\n  - [1D: Mapping Table](#step-1d-map-specification-changes-to-swagger-ui-components) - 15+ spec change types\n  - [1E: Real Examples](#step-1e-examples-oas-31-specification-changes--components) - 6 detailed examples\n  - [1H: WebFetch Workflow](#step-1h-using-webfetch-to-analyze-specifications) - Spec analysis with WebFetch\n- **[Step 2-17: Implementation](#step-2-create-plugin-directory-structure)** - Complete implementation steps\n- **[Practical Workflow](#practical-workflow-from-spec-to-components)** - End-to-end example\n- **[Best Practices](#best-practices-iterative-spec-driven-development)** - Spec-driven development\n- **[Common Pitfalls](#common-pitfalls)** - What to avoid\n- **[Final Checklist](#final-checklist)** - Pre-submission verification\n\n---\n\n**Remember: The specification at https://spec.openapis.org/ is your source of truth!**\n\n---\n\n## Prerequisites\n\nBefore starting, ensure:\n- You understand the Swagger UI plugin architecture\n- You've read the CLAUDE.md guide\n- You have the OAS specification document for the new version\n- All tests pass: `npm test`\n\n## Architecture Overview\n\nAdding OAS version support involves:\n\n1. **Plugin Creation** - New plugin following established patterns\n2. **Version Detection** - Regex-based version identifier\n3. **Selector Factories** - Conditional logic for version-specific features\n4. **Component Implementation** - New/wrapped components for rendering\n5. **State Management** - Redux selectors/actions for new features\n6. **Lifecycle Hooks** - afterLoad modifications\n7. **Preset Registration** - Plugin loading order\n8. **Testing** - Unit and E2E tests\n9. **Documentation** - Update guides and README\n\n## Key Design Patterns (from OAS 3.1)\n\n### Pattern 1: Version Detection\n```javascript\nexport const isOAS{VERSION} = (jsSpec) => {\n  const oasVersion = jsSpec.get(\"openapi\")\n  return (\n    typeof oasVersion === \"string\" && /^{MAJOR}\\.{MINOR}\\.(?:[1-9]\\d*|0)$/.test(oasVersion)\n  )\n}\n```\n\n### Pattern 2: Selector Factories\n\n**createOnlyOAS{VERSION}Selector** - Features exclusive to this version:\n```javascript\nexport const createOnlyOAS{VERSION}Selector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(system)\n        : selectedValue\n    } else {\n      return null\n    }\n  }\n```\n\n**createOnlyOAS{VERSION}SelectorWrapper** - Override previous versions:\n```javascript\nexport const createOnlyOAS{VERSION}SelectorWrapper =\n  (selector) =>\n  (oriSelector, system) =>\n  (state, ...args) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(oriSelector, system)\n        : selectedValue\n    } else {\n      return oriSelector(...args)\n    }\n  }\n```\n\n### Pattern 3: Component Wrappers\n\n**⚠️ IMPORTANT: `originalComponent` prop name, not `Ori`**\n\n`createOnlyOAS{VERSION}ComponentWrapper` passes the original component as `originalComponent` in props (NOT `Ori` — that's the OAS3/OAS30ComponentWrapFactory convention). Use `const { originalComponent: Ori } = props` to access it.\n\n**Pattern A — Reuse previous version's component via getComponent:**\n```javascript\nconst ComponentWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => {\n  const system = getSystem()\n  const OAS{PREV_VERSION}Component = system.getComponent(\"OAS{PREV_VERSION}Component\", true)\n  return <OAS{PREV_VERSION}Component />\n})\n```\n\n**Pattern B — Render original component with extra props (e.g. version badge):**\n```javascript\n// Use `originalComponent` (NOT `Ori`) — that's the prop name createOnlyOAS{VERSION}ComponentWrapper passes\nconst OpenAPIVersionWrapper = createOnlyOAS{VERSION}ComponentWrapper((props) => {\n  const { originalComponent: Ori } = props\n  return <Ori oasVersion=\"{VERSION}\" />\n})\n```\n\n### Pattern 4: Function Wrapping\n```javascript\nexport const wrapOAS{VERSION}Fn = (fn, system) => {\n  const { fn: systemFn, specSelectors } = system\n  return Object.fromEntries(\n    Object.entries(fn).map(([name, newImpl]) => {\n      const oriImpl = systemFn[name]\n      const impl = (...args) =>\n        specSelectors.isOAS{VERSION}()\n          ? newImpl(...args)\n          : typeof oriImpl === \"function\"\n            ? oriImpl(...args)\n            : undefined\n      return [name, impl]\n    })\n  )\n}\n```\n\n## Implementation Steps\n\n### Step 1: Analyze New OAS Version Specification\n\n**CRITICAL: Always start by reviewing the official specification at https://spec.openapis.org/**\n\n#### 1A. Access the Official Specification\n\n**Primary Resource:** https://spec.openapis.org/\n\n**Available Versions:**\n- OAS 2.0: https://spec.openapis.org/oas/v2.0/\n- OAS 3.0.x: https://spec.openapis.org/oas/v3.0.3/\n- OAS 3.1.x: https://spec.openapis.org/oas/v3.1.0/\n- Future versions will follow the pattern: https://spec.openapis.org/oas/v{MAJOR}.{MINOR}.{PATCH}/\n\n**What to download:**\n1. The specification document (usually in HTML or Markdown format)\n2. JSON Schema definitions (if available)\n3. Example specification files\n4. Change log or migration guide (if available)\n\n#### 1B. Systematic Specification Analysis\n\nUse the WebFetch tool to retrieve and analyze the specification:\n\n```bash\n# Example for analyzing OAS 4.0 (hypothetical)\nWebFetch(\"https://spec.openapis.org/oas/v4.0.0/\", \"List all new top-level fields, objects, and keywords introduced in this version compared to OAS 3.1\")\n```\n\n**Read these sections carefully:**\n\n1. **Version Number Section**\n   - Confirm the exact version format (e.g., \"4.0.0\", \"3.2.0\")\n   - Note any version detection changes\n\n2. **OpenAPI Object (Root Level)**\n   - New top-level fields (e.g., `webhooks` in OAS 3.1)\n   - Modified existing fields\n   - Removed/deprecated fields\n\n3. **Info Object**\n   - New fields (e.g., `summary` in OAS 3.1)\n   - Changes to `license`, `contact`, etc.\n\n4. **Paths Object & Operations**\n   - New operation-level fields\n   - Changes to parameters, request bodies, responses\n   - New callback syntax or features\n\n5. **Components Object**\n   - New component types\n   - Schema changes (especially JSON Schema version)\n   - New security schemes\n\n6. **Security Object**\n   - New authentication types (e.g., `mutualTLS` in OAS 3.1)\n   - Changes to OAuth2 flows\n   - New security-related fields\n\n7. **Schema Object**\n   - JSON Schema version change (critical!)\n   - New keywords (e.g., `examples` vs `example`)\n   - Type system changes\n\n#### 1C. Create Specification Change Document\n\nCreate a structured document listing all changes:\n\n**Template:**\n```markdown\n# OpenAPI {VERSION} Specification Analysis\n\n## Version Information\n- Version: {MAJOR}.{MINOR}.{PATCH}\n- Release Date: YYYY-MM-DD\n- Previous Version: {PREVIOUS_VERSION}\n- JSON Schema Version: Draft {VERSION} or {YEAR}\n\n## New Top-Level Fields\n1. **`newField`** (Type: Object)\n   - Location: Root level\n   - Purpose: Description from spec\n   - Required: Yes/No\n   - Example from spec: {...}\n   - Swagger UI Impact: Needs new component in BaseLayout\n\n## Modified Existing Fields\n1. **`info`**\n   - New subfields: `summary`, `newField`\n   - Changed behavior: Description\n   - Swagger UI Impact: Need to wrap Info component\n\n## New Operation-Level Features\n1. **`newOperationField`**\n   - Purpose: Description\n   - Swagger UI Impact: Extend Operation component\n\n## New Authentication Types\n1. **`newAuthType`**\n   - Type name: \"newAuthType\"\n   - Fields: {...}\n   - Swagger UI Impact: New auth component needed\n\n## JSON Schema Changes\n- Version change: Draft 2020-12 → Draft 2024\n- New keywords: `keyword1`, `keyword2`\n- Removed keywords: `oldKeyword`\n- Swagger UI Impact: New json-schema plugin needed\n\n## Breaking Changes\n1. Removed `x-deprecated-field`\n2. Changed behavior of `existingField`\n3. Required fields now enforced\n\n## Deprecated Features\n1. `oldField` - Use `newField` instead\n2. `oldAuthType` - Use `newAuthType` instead\n\n## Examples from Specification\n- Link to example files\n- Notable edge cases to test\n```\n\n#### 1D. Map Specification Changes to Swagger UI Components\n\n**CRITICAL MAPPING GUIDE:** Use this table to determine what components to create/modify:\n\n| Spec Change Type | Swagger UI Component Type | Location | Example from OAS 3.1 |\n|-----------------|---------------------------|----------|---------------------|\n| **New Top-Level Field (Object)** | New standalone component | `components/{feature-name}.jsx` | `webhooks` → `Webhooks.jsx` |\n| **New Top-Level Field (String/Primitive)** | Add to existing layout component or create info component | `components/{field-name}.jsx` | `jsonSchemaDialect` → `JsonSchemaDialect.jsx` |\n| **Modified Info Object** | Wrap Info component OR create OAS{VERSION}Info | `wrap-components/info.jsx` | `info.summary` → Wrapped InfoContainer |\n| **New Info Subfield** | Create new component, render in Info | `components/info-{field}.jsx` | `info.license.identifier` → OAS31License |\n| **Modified License/Contact** | Wrap component | `wrap-components/license.jsx` | `license.identifier` → Wrapped License |\n| **New Authentication Type** | New auth component | `components/auth/{type}.jsx` | `mutualTLS` → `MutualTLSAuth.jsx` |\n| **Modified Security Scheme** | Wrap auth selector | `auth-extensions/wrap-selectors.js` | mutualTLS → `definitionsToAuthorize` wrapper |\n| **New Operation Field** | Extend Operation or create plugin selector | `spec-extensions/selectors.js` | N/A in OAS 3.1 |\n| **New Callback Feature** | Extend Callbacks component or wrap | `wrap-components/callbacks.jsx` | Enhanced in OAS 3.1 |\n| **New Parameter Type** | Extend Parameters component | `components/parameters/` | N/A in OAS 3.1 |\n| **New Response Feature** | Extend Responses component | `components/responses/` | N/A in OAS 3.1 |\n| **New Media Type Feature** | Modify media-type component or fn | `oas{PREV}-extensions/fn.js` | File upload detection changes |\n| **JSON Schema Keyword** | New keyword component | `json-schema-{VERSION}-extensions/components/keywords/` | `example` → `JSONSchema202012KeywordExample.jsx` |\n| **JSON Schema Version Change** | Entire new plugin + samples plugin | `plugins/json-schema-{VERSION}/` | JSON Schema 2020-12 plugin |\n| **Modified Schema Rendering** | Wrap schema component | `wrap-components/model.jsx` | Models → OAS31Models wrapper |\n| **Version Detection Field** | Update VersionPragmaFilter | `components/version-pragma-filter.jsx` | Updated for isOAS31 |\n| **Deprecated Field** | Remove or add deprecation warning | Component showing warning | N/A in OAS 3.1 |\n\n#### 1E. Examples: OAS 3.1 Specification Changes → Components\n\n**Example 1: `webhooks` Top-Level Field**\n\n**From Spec (OAS 3.1):**\n```yaml\nopenapi: 3.1.0\nwebhooks:\n  newPet:\n    post:\n      requestBody:\n        description: Information about a new pet\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Pet'\n      responses:\n        '200':\n          description: Return a 200 status\n```\n\n**Mapping Decision:**\n- Type: New top-level field (Object containing operations)\n- Location in spec: Root level, same structure as `paths`\n- Swagger UI component: New standalone component\n- File: `src/core/plugins/oas31/components/webhooks.jsx`\n- Rendering: Reuses Operations component to render webhook operations\n- Selector: `selectWebhooks` in `spec-extensions/selectors.js`\n- Layout integration: Added to BaseLayout or StandaloneLayout\n\n**Example 2: `info.summary` Field**\n\n**From Spec (OAS 3.1):**\n```yaml\ninfo:\n  title: My API\n  summary: A brief summary of the API   # NEW in OAS 3.1\n  description: Detailed description...\n  version: 1.0.0\n```\n\n**Mapping Decision:**\n- Type: New subfield in existing Info object\n- Location: `info.summary`\n- Swagger UI component: Wrap existing Info component\n- File: `src/core/plugins/oas31/wrap-components/info.jsx` + `src/core/plugins/oas31/components/info.jsx`\n- Selector: `selectInfoSummary` (if needed)\n- Rendering: Display summary above or below title\n\n**Example 3: `mutualTLS` Authentication Type**\n\n**From Spec (OAS 3.1):**\n```yaml\ncomponents:\n  securitySchemes:\n    myMutualTLS:\n      type: mutualTLS    # NEW in OAS 3.1\n      description: Client certificate authentication\n```\n\n**Mapping Decision:**\n- Type: New authentication scheme type\n- Location: `components.securitySchemes[name].type`\n- Swagger UI component: New auth component\n- File: `src/core/plugins/oas31/components/auth/mutual-tls-auth.jsx`\n- Selector wrapper: `auth-extensions/wrap-selectors.js` → `definitionsToAuthorize`\n- Rendering: Display in authorize modal with certificate upload UI\n\n**Example 4: `license.identifier` Field**\n\n**From Spec (OAS 3.1):**\n```yaml\ninfo:\n  license:\n    name: Apache 2.0\n    identifier: Apache-2.0    # NEW in OAS 3.1 (SPDX ID)\n    url: https://www.apache.org/licenses/LICENSE-2.0.html\n```\n\n**Mapping Decision:**\n- Type: New optional field in license object (alternative to url)\n- Location: `info.license.identifier`\n- Swagger UI component: Wrap License component + create selector\n- File: `src/core/plugins/oas31/wrap-components/license.jsx` + selector in `spec-extensions/selectors.js`\n- Logic: If `identifier` exists, construct URL from SPDX registry\n- Rendering: Make license text a hyperlink to SPDX page\n\n**Example 5: JSON Schema 2020-12 Keywords**\n\n**From Spec (OAS 3.1):**\n```yaml\n# OAS 3.1 uses JSON Schema 2020-12 which includes:\ncomponents:\n  schemas:\n    Pet:\n      type: object\n      properties:\n        name:\n          type: string\n          example: Fluffy        # Changed from 'examples' array in OAS 3.0\n      xml:                       # Now a JSON Schema keyword, not OAS-specific\n        name: pet\n      externalDocs:              # Now a JSON Schema keyword\n        url: https://example.com\n      discriminator:             # Now a JSON Schema keyword\n        propertyName: petType\n```\n\n**Mapping Decision:**\n- Type: JSON Schema version upgrade (Draft 7 → 2020-12)\n- Location: Schema objects throughout spec\n- Swagger UI components: Entire new plugin\n- Files:\n  - `src/core/plugins/json-schema-2020-12/` (main plugin)\n  - `src/core/plugins/json-schema-2020-12-samples/` (sample generation)\n  - `src/core/plugins/json-schema-2020-12/components/keywords/example.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/xml.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/discriminator.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/external-docs.jsx`\n- Integration: OAS31 plugin extends JSON Schema 2020-12 keywords in `json-schema-2020-12-extensions/`\n\n**Example 6: `jsonSchemaDialect` Top-Level Field**\n\n**From Spec (OAS 3.1):**\n```yaml\nopenapi: 3.1.0\njsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base  # NEW in OAS 3.1\n```\n\n**Mapping Decision:**\n- Type: New top-level field (String/URI)\n- Location: Root level\n- Swagger UI component: Simple display component\n- File: `src/core/plugins/oas31/components/json-schema-dialect.jsx`\n- Selector: `selectJsonSchemaDialectField` in `spec-extensions/selectors.js`\n- Rendering: Show in info section with warning if non-default\n\n#### 1F. Specification Analysis Checklist\n\nUse WebFetch and Read tools to systematically check:\n\n- [ ] **Accessed official spec at https://spec.openapis.org/**\n- [ ] **Downloaded specification document**\n- [ ] **Read version number section**\n- [ ] **Analyzed OpenAPI Object (root level) changes**\n- [ ] **Reviewed Info Object modifications**\n- [ ] **Checked Paths/Operations changes**\n- [ ] **Examined Components Object updates**\n- [ ] **Identified Security Scheme changes**\n- [ ] **Analyzed Schema Object / JSON Schema version**\n- [ ] **Listed all new top-level fields**\n- [ ] **Listed all modified existing fields**\n- [ ] **Documented breaking changes**\n- [ ] **Identified deprecated features**\n- [ ] **Found example specifications**\n- [ ] **Created specification change document**\n- [ ] **Mapped changes to Swagger UI components using table above**\n- [ ] **Prioritized implementation order**\n\n#### 1G. Questions to Answer During Analysis\n\n**Version Type:**\n- Is this a major version (4.0) or minor version (3.2)?\n- Are there breaking changes?\n- Is backward compatibility maintained?\n\n**JSON Schema:**\n- Does it use a new JSON Schema version?\n- What new keywords are available?\n- Are there removed/deprecated keywords?\n\n**Top-Level Changes:**\n- What new top-level fields are added?\n- Which existing fields have new subfields?\n- Any removed top-level fields?\n\n**Operation Changes:**\n- Are there new operation-level features?\n- Changes to parameters, request bodies, responses?\n- New callback or link syntax?\n\n**Security Changes:**\n- What authentication types are new/changed?\n- OAuth2 flow modifications?\n- New security requirements?\n\n**Media Type Changes:**\n- Are there new media type features?\n- File upload handling changes?\n- Encoding changes?\n\n**Component Mapping:**\n- Which components need to be created from scratch?\n- Which existing components need to be wrapped?\n- What selectors are required?\n- Are new plugins needed (e.g., for JSON Schema)?\n\n**Implementation Priority:**\n- What's the critical path for basic rendering?\n- Which features can be added incrementally?\n- What has the highest user impact?\n\n### Step 1H: Using WebFetch to Analyze Specifications\n\n**Always use WebFetch tool to retrieve and analyze the specification systematically.**\n\n**Step-by-step WebFetch workflow:**\n\n1. **Fetch the specification landing page:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Provide a summary of this OpenAPI Specification version, including links to the full specification document and any change logs or migration guides.\"\n)\n```\n\n2. **Analyze the specification structure:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all top-level fields in the OpenAPI Object for this version. For each field, indicate if it is new, modified, or unchanged from version {PREVIOUS_VERSION}.\"\n)\n```\n\n3. **Deep dive into new features:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Describe the '{NEW_FIELD}' field in detail: its type, structure, purpose, whether it's required, and provide examples from the specification.\"\n)\n```\n\n4. **Analyze security changes:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all security scheme types supported in this version. Highlight any new or changed security scheme types compared to {PREVIOUS_VERSION}.\"\n)\n```\n\n5. **Check JSON Schema compatibility:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"What version of JSON Schema does this OpenAPI Specification version use? List any specific dialect or modifications to JSON Schema.\"\n)\n```\n\n6. **Find example specifications:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Provide links to example OpenAPI specification files for this version, particularly examples that demonstrate new features.\"\n)\n```\n\n**Real example from analyzing OAS 3.1:**\n\n```javascript\n// 1. Initial analysis\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"List all new fields and features introduced in OpenAPI 3.1.0 compared to OpenAPI 3.0.3\"\n)\n\n// Response would include:\n// - webhooks field (new top-level)\n// - info.summary (new)\n// - info.license.identifier (new)\n// - jsonSchemaDialect (new top-level)\n// - mutualTLS security scheme type (new)\n// - JSON Schema 2020-12 (changed from Draft 7)\n\n// 2. Deep dive into webhooks\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"Explain the 'webhooks' field in detail: structure, purpose, and provide a complete example\"\n)\n\n// 3. Understand JSON Schema changes\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"What are the differences between JSON Schema Draft 7 (used in OAS 3.0) and JSON Schema 2020-12 (used in OAS 3.1) that affect schema definitions?\"\n)\n```\n\n**Pro tip:** Use multiple targeted queries rather than one broad query. This gives more precise information for each component you need to implement.\n\n### Step 2: Create Plugin Directory Structure\n\n**Directory:** `src/core/plugins/oas{VERSION_NUMBER}/`\n\n**Files to Create:**\n```\nsrc/core/plugins/oas{VERSION_NUMBER}/\n├── index.js                          # Main plugin export\n├── fn.js                             # Selector/function factories\n├── selectors.js                      # Version-specific selectors (if needed)\n├── after-load.js                     # Lifecycle hook\n├── auth-extensions/                  # Authentication features\n│   └── wrap-selectors.js\n├── oas{PREVIOUS_VERSION}-extensions/ # Extensions to previous version\n│   └── fn.js\n├── spec-extensions/                  # Spec-level features\n│   ├── selectors.js\n│   └── wrap-selectors.js\n├── components/                       # New components\n│   ├── version-pragma-filter.jsx\n│   ├── {new-feature-1}.jsx\n│   └── auth/\n│       └── {new-auth-type}.jsx\n├── wrap-components/                  # Component wrappers\n│   ├── info.jsx\n│   ├── license.jsx\n│   └── {existing-component}.jsx\n└── json-schema-{VERSION}-extensions/ # If new JSON Schema version\n    ├── fn.js\n    ├── components/keywords/\n    └── wrap-components/keywords/\n```\n\n**Create the directories:**\n```bash\nmkdir -p src/core/plugins/oas{VERSION_NUMBER}/{auth-extensions,oas{PREVIOUS_VERSION}-extensions,spec-extensions,components/auth,wrap-components}\n```\n\n### Step 3: Implement Version Detection (fn.js)\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/fn.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\n/**\n * Detects if a spec is OpenAPI {MAJOR}.{MINOR}.x\n */\nexport const isOAS{VERSION} = (jsSpec) => {\n  const oasVersion = jsSpec.get(\"openapi\")\n  return (\n    typeof oasVersion === \"string\" &&\n    /^{MAJOR}\\.{MINOR}\\.(?:[1-9]\\d*|0)$/.test(oasVersion)\n  )\n}\n\n/**\n * Creates a selector that only returns a value for OAS {VERSION} specs\n */\nexport const createOnlyOAS{VERSION}Selector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(system)\n        : selectedValue\n    } else {\n      return null\n    }\n  }\n\n/**\n * Creates a selector wrapper that uses new impl for OAS {VERSION}, falls back to original\n */\nexport const createOnlyOAS{VERSION}SelectorWrapper =\n  (selector) =>\n  (oriSelector, system) =>\n  (state, ...args) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(oriSelector, system)\n        : selectedValue\n    } else {\n      return oriSelector(...args)\n    }\n  }\n\n/**\n * Creates a system-aware selector\n */\nexport const createSystemSelector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    const selectedValue = selector(state, system, ...args)\n    return typeof selectedValue === \"function\"\n      ? selectedValue(system)\n      : selectedValue\n  }\n\n/**\n * Creates a component wrapper that only renders for OAS {VERSION}.\n * When active, passes `originalComponent` (the unwrapped original) and\n * `getSystem` as extra props. Access the original via:\n *   const { originalComponent: Ori } = props\n * NOT via `props.Ori` — that's the OAS3/OAS30ComponentWrapFactory convention.\n */\nexport const createOnlyOAS{VERSION}ComponentWrapper =\n  (Component) => (Original, system) => (props) => {\n    if (system.specSelectors.isOAS{VERSION}()) {\n      return (\n        <Component\n          {...props}\n          originalComponent={Original}\n          getSystem={system.getSystem}\n        />\n      )\n    }\n\n    return <Original {...props} />\n  }\n\n/**\n * Wraps functions to conditionally use OAS {VERSION} implementations\n */\nexport const wrapOAS{VERSION}Fn = (fn, system) => {\n  const { fn: systemFn, specSelectors } = system\n  return Object.fromEntries(\n    Object.entries(fn).map(([name, newImpl]) => {\n      const oriImpl = systemFn[name]\n      const impl = (...args) =>\n        specSelectors.isOAS{VERSION}()\n          ? newImpl(...args)\n          : typeof oriImpl === \"function\"\n            ? oriImpl(...args)\n            : undefined\n      return [name, impl]\n    })\n  )\n}\n```\n\n### Step 4: Create Main Plugin Export (index.js)\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/index.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport afterLoad from \"./after-load.js\"\nimport {\n  isOAS{VERSION},\n  createSystemSelector,\n  createOnlyOAS{VERSION}Selector,\n  createOnlyOAS{VERSION}SelectorWrapper,\n  createOnlyOAS{VERSION}ComponentWrapper,\n} from \"./fn.js\"\n\n// Import spec extensions\nimport * as specExtensionsSelectors from \"./spec-extensions/selectors.js\"\nimport * as specExtensionsWrapSelectors from \"./spec-extensions/wrap-selectors.js\"\n\n// Import auth extensions\nimport * as authExtensionsWrapSelectors from \"./auth-extensions/wrap-selectors.js\"\n\n// Import OAS{PREVIOUS_VERSION} extensions\nimport * as oas{PREVIOUS_VERSION}ExtensionsFn from \"./oas{PREVIOUS_VERSION}-extensions/fn.js\"\n\n// Import components\nimport VersionPragmaFilter from \"./components/version-pragma-filter.jsx\"\n// Import new feature components here\n\n// Import wrap components\nimport InfoWrapper from \"./wrap-components/info.jsx\"\n// Import other wrappers here\n\n/**\n * OpenAPI {MAJOR}.{MINOR} Plugin\n *\n * Adds support for OpenAPI Specification {MAJOR}.{MINOR}.x\n *\n * This plugin should be loaded AFTER:\n * - oas{PREVIOUS_VERSION} plugin\n * - json-schema-{JSON_SCHEMA_VERSION} plugin (if applicable)\n *\n * It wraps and overrides components/selectors from previous versions.\n */\nconst OpenAPI{VERSION}Plugin = ({ fn }) => {\n  return {\n    fn: {\n      oas{VERSION_NUMBER}: {\n        isOAS{VERSION},\n        createSystemSelector,\n        createOnlyOAS{VERSION}Selector,\n        createOnlyOAS{VERSION}SelectorWrapper,\n        createOnlyOAS{VERSION}ComponentWrapper,\n      },\n    },\n    components: {\n      // New components\n      OAS{VERSION}VersionPragmaFilter: VersionPragmaFilter,\n      // Add new feature components here\n    },\n    wrapComponents: {\n      // Wrapped components\n      VersionPragmaFilter: (Ori, system) =>\n        system.specSelectors.isOAS{VERSION}()\n          ? system.getComponent(\"OAS{VERSION}VersionPragmaFilter\", true)\n          : Ori,\n      InfoContainer: InfoWrapper,\n      // Add other wrappers here\n    },\n    statePlugins: {\n      spec: {\n        selectors: {\n          // Add version detection selector\n          isOAS{VERSION}: createSystemSelector(specExtensionsSelectors.selectIsOAS{VERSION}),\n          // Add new feature selectors here\n        },\n        wrapSelectors: {\n          // Wrap previous version selectors if needed\n          ...specExtensionsWrapSelectors,\n        },\n      },\n      auth: {\n        wrapSelectors: {\n          // Add auth extensions if needed\n          ...authExtensionsWrapSelectors,\n        },\n      },\n      oas{VERSION_NUMBER}: {\n        selectors: {\n          // Plugin-specific selectors\n        },\n      },\n    },\n    afterLoad,\n  }\n}\n\nexport default OpenAPI{VERSION}Plugin\n```\n\n### Step 5: Implement Spec Extensions\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/selectors.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createSelector } from \"reselect\"\nimport { isOAS{VERSION} } from \"../fn.js\"\n\n/**\n * Detects if the current spec is OAS {VERSION}\n */\nexport const selectIsOAS{VERSION} = (state, system) => () => {\n  const spec = system.specSelectors.specJson()\n  return isOAS{VERSION}(spec)\n}\n\n// Add selectors for new OAS {VERSION} fields here\n// Example:\n// export const selectNewField = createSelector(\n//   (state) => state,\n//   (state) => {\n//     const spec = state.getIn([\"spec\", \"json\"])\n//     return spec.get(\"newField\")\n//   }\n// )\n```\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/wrap-selectors.js`\n\n**⚠️ Minor version: DON'T wrap `isOAS{PREV}` unless the regex actually matches both versions.** For example, OAS 3.1's `isOAS31` regex (`/^3\\.1\\./`) will never match `3.2.x`, so wrapping it to return `false` is dead code. Only add the `isOAS{PREV}` override if the previous version's detection regex would incorrectly match the new version.\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createOnlyOAS{VERSION}SelectorWrapper } from \"../fn.js\"\n\n// Ensure OAS {VERSION} specs are recognized as OAS 3.x (needed when major version number didn't change)\nexport const isOAS3 =\n  (oriSelector, system) =>\n  (state, ...args) => {\n    const isOAS{VERSION} = system.specSelectors.isOAS{VERSION}()\n    return isOAS{VERSION} || oriSelector(...args)\n  }\n\n// ONLY add isOAS{PREV} wrapper if the previous version's regex could match this new version.\n// For a minor version bump (e.g. 3.1 → 3.2), the previous regex won't match, so DON'T add this.\n// export const isOAS{PREV} = createOnlyOAS{VERSION}SelectorWrapper((state) => () => false)\n```\n\n### Step 6: Create Version Pragma Filter Component\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst OAS{VERSION}VersionPragmaFilter = ({ bypass, isSwagger2, isOAS3, isOAS{PREVIOUS_VERSION}, isOAS{VERSION} }) => {\n  // Handle version detection logic\n  const isAmbiguous =\n    (isSwagger2 && isOAS3) ||\n    (isSwagger2 && isOAS{PREVIOUS_VERSION}) ||\n    (isSwagger2 && isOAS{VERSION}) ||\n    (isOAS3 && isOAS{PREVIOUS_VERSION}) ||\n    (isOAS3 && isOAS{VERSION}) ||\n    (isOAS{PREVIOUS_VERSION} && isOAS{VERSION})\n\n  const isMissing = !isSwagger2 && !isOAS3 && !isOAS{PREVIOUS_VERSION} && !isOAS{VERSION}\n\n  if (bypass) {\n    return null\n  }\n\n  if (isAmbiguous) {\n    return (\n      <div className=\"version-pragma\">\n        <div className=\"version-pragma__message version-pragma__message--ambiguous\">\n          <div>\n            <h3>Unable to render this document, as it contains multiple OpenAPI version fields.</h3>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  if (isMissing) {\n    return (\n      <div className=\"version-pragma\">\n        <div className=\"version-pragma__message version-pragma__message--missing\">\n          <div>\n            <h3>Unable to render this document, as it doesn&apos;t contain an OpenAPI version field.</h3>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  return null\n}\n\nOAS{VERSION}VersionPragmaFilter.propTypes = {\n  bypass: PropTypes.bool,\n  isSwagger2: PropTypes.bool.isRequired,\n  isOAS3: PropTypes.bool.isRequired,\n  isOAS{PREVIOUS_VERSION}: PropTypes.bool.isRequired,\n  isOAS{VERSION}: PropTypes.bool.isRequired,\n}\n\nOAS{VERSION}VersionPragmaFilter.defaultProps = {\n  bypass: false,\n}\n\nexport default OAS{VERSION}VersionPragmaFilter\n```\n\n### Step 7: Implement New Feature Components\n\nFor each new feature in the OAS specification:\n\n**Example: New Feature Component**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst NewFeature = ({ getComponent, specSelectors }) => {\n  const newFeature = specSelectors.selectNewFeature()\n\n  if (!newFeature || !newFeature.size) {\n    return null\n  }\n\n  // Render the new feature\n  return (\n    <div className=\"opblock-tag-section\">\n      <h3>New Feature</h3>\n      {/* Render logic here */}\n    </div>\n  )\n}\n\nNewFeature.propTypes = {\n  specSelectors: PropTypes.object.isRequired,\n  getComponent: PropTypes.func.isRequired,\n}\n\nexport default NewFeature\n```\n\n### Step 8: Create Component Wrappers\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/wrap-components/info.jsx`\n\n**⚠️ Minor version (e.g. 3.2): don't create a new Info component.** If the Info object is identical to the previous version, reuse `OAS{PREV_VERSION}Info` via `getComponent` instead of copying the whole component. Only create a new Info component for major versions with significant structural changes.\n\n**Template (minor version — reuse previous Info):**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport { createOnlyOAS{VERSION}ComponentWrapper } from \"../fn.js\"\n\nconst InfoWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => {\n  const system = getSystem()\n  const OAS{PREV_VERSION}Info = system.getComponent(\"OAS{PREV_VERSION}Info\", true)\n  return <OAS{PREV_VERSION}Info />\n})\n\nexport default InfoWrapper\n```\n\n**Also — OpenAPIVersion wrapper (minor version — change version badge only):**\n\nFor minor versions where the only Info difference is the version badge, use the OpenAPIVersion wrapper pattern instead of wrapping InfoContainer at all:\n\n```javascript\n// wrap-components/openapi-version.jsx\n/**\n * @prettier\n */\nimport React from \"react\"\nimport { createOnlyOAS{VERSION}ComponentWrapper } from \"../fn.js\"\n\nexport default createOnlyOAS{VERSION}ComponentWrapper((props) => {\n  const { originalComponent: Ori } = props  // NOT `Ori` from props directly — use `originalComponent`\n  return <Ori oasVersion=\"{MAJOR}.{MINOR}\" />\n})\n```\n\nThen register it in index.js:\n```javascript\nwrapComponents: {\n  OpenAPIVersion: OpenAPIVersionWrapper,  // changes the version badge shown in the Info header\n}\n```\n\n### Step 9: Implement afterLoad Hook\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/after-load.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { wrapOAS{VERSION}Fn } from \"./fn.js\"\n\n/**\n * afterLoad hook for OAS {VERSION} plugin\n *\n * This hook runs after all plugins are loaded and allows\n * modification of the system's functions and behaviors.\n */\nfunction afterLoad({ fn, getSystem }) {\n  const system = getSystem()\n\n  // Override functions that differ in OAS {VERSION}\n  if (typeof fn.sampleFromSchema === \"function\") {\n    // Example: Wrap sample generation if JSON Schema version changed\n    // const wrappedFns = wrapOAS{VERSION}Fn({\n    //   sampleFromSchema: fn.jsonSchema{VERSION}.sampleFromSchema,\n    // }, system)\n    // Object.assign(this.fn, wrappedFns)\n  }\n\n  // Override other functions as needed\n  // Example: File upload detection\n  // if (typeof fn.isFileUploadIntended === \"function\") {\n  //   const wrappedFns = wrapOAS{VERSION}Fn({\n  //     isFileUploadIntended: makeIsFileUploadIntended(system),\n  //   }, system)\n  //   Object.assign(this.fn, wrappedFns)\n  // }\n}\n\nexport default afterLoad\n```\n\n### Step 10: Handle Authentication Changes\n\nIf new authentication types are introduced:\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/auth/{auth-type}.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst NewAuthType = ({ schema, name, getComponent, onChange, authorized }) => {\n  const authValue = authorized && authorized.getIn([name])\n\n  const Input = getComponent(\"Input\")\n  const Button = getComponent(\"Button\")\n\n  // Render auth UI\n  return (\n    <div>\n      <h4>{schema.get(\"description\") || `${name} (${schema.get(\"type\")})`}</h4>\n      {/* Auth UI here */}\n    </div>\n  )\n}\n\nNewAuthType.propTypes = {\n  schema: PropTypes.object.isRequired,\n  name: PropTypes.string.isRequired,\n  getComponent: PropTypes.func.isRequired,\n  onChange: PropTypes.func.isRequired,\n  authorized: PropTypes.object,\n}\n\nexport default NewAuthType\n```\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/auth-extensions/wrap-selectors.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createOnlyOAS{VERSION}SelectorWrapper } from \"../fn.js\"\nimport { Map } from \"immutable\"\n\n/**\n * Wraps definitionsToAuthorize to include new auth types\n */\nexport const definitionsToAuthorize = createOnlyOAS{VERSION}SelectorWrapper(\n  (state, system) =>\n    (oriSelector) => {\n      const definitions = oriSelector()\n      const securityDefinitions = system.specSelectors.securityDefinitions() || Map()\n\n      // Add new auth types to definitions\n      return definitions.map((definition) => {\n        const schema = securityDefinitions.get(definition.get(\"name\"))\n        if (schema && schema.get(\"type\") === \"newAuthType\") {\n          // Add new auth type logic\n          return definition.set(\"newAuthType\", true)\n        }\n        return definition\n      })\n    }\n)\n```\n\n### Step 11: Register Plugin in Preset\n\n**File:** `src/core/presets/apis/index.js`\n\n**Add import:**\n```javascript\nimport OpenAPI{VERSION}Plugin from \"../../plugins/oas{VERSION_NUMBER}/index.js\"\n```\n\n**Add to preset array (IMPORTANT: add at the end):**\n```javascript\nexport default function PresetApis() {\n  return [\n    BasePreset,\n    OpenAPI30Plugin,\n    // ... other plugins\n    OpenAPI{PREVIOUS_VERSION}Plugin,\n    OpenAPI{VERSION}Plugin,  // Load LAST to override previous versions\n  ]\n}\n```\n\n**Why load last?**\n- Wrap-components override previous versions\n- Wrap-selectors intercept earlier selectors\n- afterLoad modifications apply to dependencies\n\n### Step 12: Add Unit Tests\n\n**Directory:** `test/unit/core/plugins/oas{VERSION_NUMBER}/`\n\n**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/fn.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { fromJS } from \"immutable\"\nimport { isOAS{VERSION} } from \"src/core/plugins/oas{VERSION_NUMBER}/fn.js\"\n\ndescribe(\"oas{VERSION_NUMBER} plugin - fn - isOAS{VERSION}\", () => {\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.0\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.1\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.1\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.25\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.25\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should NOT match OpenAPI {MAJOR}.{MINOR}\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match OpenAPI {MAJOR}.{MINOR}.01 (leading zero)\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.01\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match OpenAPI {DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0\", () => {\n    const spec = fromJS({ openapi: \"{DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match swagger: 2.0\", () => {\n    const spec = fromJS({ swagger: \"2.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should handle null spec\", () => {\n    const spec = fromJS({})\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n})\n```\n\n**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport { shallow } from \"enzyme\"\nimport OAS{VERSION}VersionPragmaFilter from \"src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx\"\n\ndescribe(\"OAS{VERSION}VersionPragmaFilter\", () => {\n  it(\"should render nothing when bypass is true\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={true}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.type()).toBe(null)\n  })\n\n  it(\"should render nothing when version is valid\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.type()).toBe(null)\n  })\n\n  it(\"should render error when version is ambiguous\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={true}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.find(\".version-pragma__message--ambiguous\")).toHaveLength(1)\n  })\n\n  it(\"should render error when version is missing\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={false}\n      />\n    )\n    expect(wrapper.find(\".version-pragma__message--missing\")).toHaveLength(1)\n  })\n})\n```\n\n### Step 13: Add E2E Tests\n\n**Directory:** `test/e2e-cypress/e2e/features/oas{VERSION_NUMBER}/`\n\n**Create test spec file:**\n```javascript\n/**\n * @prettier\n */\n\ndescribe(\"OpenAPI {MAJOR}.{MINOR} features\", () => {\n  it(\"should detect OAS {VERSION} version\", () => {\n    cy.visit(\"/oas{VERSION_NUMBER}-spec.html\")\n    cy.get(\".information-container .version\").should(\"contain\", \"{MAJOR}.{MINOR}.0\")\n  })\n\n  // Add tests for new features\n  it(\"should render new feature X\", () => {\n    cy.visit(\"/oas{VERSION_NUMBER}-spec.html\")\n    cy.get(\".opblock-tag-section\").should(\"contain\", \"New Feature\")\n  })\n})\n```\n\n**Add test fixtures:**\n- Create sample OAS {VERSION} spec in `test/e2e-cypress/static/documents/oas{VERSION_NUMBER}/`\n- Create HTML fixture in `test/e2e-cypress/static/` referencing the spec\n\n### Step 14: Update Documentation\n\n**Files to update:**\n\n1. **README.md** - Add OAS {VERSION} to supported versions\n2. **CLAUDE.md** - Add plugin to list and update version compatibility\n3. **docs/usage/version-detection.md** - Document new version detection\n4. **package.json** - Update description if needed\n\n**Example README.md update:**\n```markdown\n### OpenAPI Specification Compatibility\n\n- **OpenAPI 2.0** (Swagger)\n- **OpenAPI 3.0.x**\n- **OpenAPI 3.1.x**\n- **OpenAPI {MAJOR}.{MINOR}.x** ⭐ NEW\n```\n\n### Step 15: Verify Build\n\n**Run full build:**\n```bash\nnpm run clean\nnpm run build\n```\n\n**Check dist/ output:**\n- `dist/swagger-ui.js` - Should include new plugin\n- `dist/swagger-ui.css` - Should include new styles (if any)\n- Bundle size should be reasonable\n\n**Run artifact tests:**\n```bash\nnpm run test:artifact\n```\n\n### Step 16: Run Full Test Suite\n\n```bash\nnpm run lint-errors      # ESLint errors only\nnpm run test:unit        # Jest unit tests\nnpm run cy:ci            # Cypress E2E tests\n```\n\n**All tests must pass before submitting PR.**\n\n### Step 17: Create Pull Request\n\n**Commit message format:**\n```\nfeat(oas{VERSION_NUMBER}): add support for OpenAPI {MAJOR}.{MINOR}\n\nImplement OpenAPI {MAJOR}.{MINOR}.x specification support with:\n- Version detection and plugin architecture\n- New feature X rendering\n- New authentication type Y support\n- JSON Schema {VERSION} integration (if applicable)\n\nCloses #{ISSUE_NUMBER}\n```\n\n**PR checklist:**\n- [ ] All tests passing\n- [ ] New feature components implemented\n- [ ] Unit tests added\n- [ ] E2E tests added\n- [ ] Documentation updated\n- [ ] Build completes successfully\n- [ ] No ESLint errors\n- [ ] Follows existing code patterns\n\n## Common Pitfalls\n","frontmatter":{"name":"add-oas-support","description":"Add support for a new OpenAPI Specification version to Swagger UI","args":{"version":{"description":"OpenAPI version to add support for (e.g., 3.2, 4.0)","required":true,"type":"string"},"type":{"description":"Version type: 'major' for new major version, 'minor' for patch/minor","required":false,"type":"string","default":"minor"}}},"isInternal":false,"tokens":12829,"sizeBytes":50344},{"name":"README.md","path":".claude/skills/README.md","rawUrl":"https://raw.githubusercontent.com/swagger-api/swagger-ui/HEAD/.claude/skills/README.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Swagger UI Claude Skills\n\nThis directory contains custom skills for working with the Swagger UI codebase in Claude Code.\n\n## Available Skills\n\n### `/add-oas-support` - Add OpenAPI Specification Version Support\n\nComprehensive skill for adding support for a new OpenAPI Specification version to Swagger UI.\n\n**Usage:**\n```\n/add-oas-support --version 4.0 --type major\n/add-oas-support --version 3.2 --type minor\n```\n\n**Parameters:**\n- `--version` (required): The OpenAPI version to add support for (e.g., \"3.2\", \"4.0\")\n- `--type` (optional): Version type - \"major\" or \"minor\" (default: \"minor\")\n\n**Structure:**\nThe skill includes both a **Quick Reference** section at the top for experienced developers, and a **comprehensive guide** below for detailed implementation instructions.\n\n**What it does:**\n1. **Analyzes the target OAS version specification using WebFetch**\n   - Fetches official spec from https://spec.openapis.org/\n   - Systematically identifies new/modified/removed fields\n   - Maps specification changes to Swagger UI components\n   - Creates specification change document\n2. Creates the plugin directory structure\n3. Implements version detection logic\n4. Creates selector factories and component wrappers\n5. Implements new feature components based on spec analysis\n6. Handles authentication changes\n7. Registers plugin in presets\n8. Adds unit and E2E tests\n9. Updates documentation\n10. Runs full test suite\n\n**Key Features:**\n- ✅ **Quick Reference** section for rapid development\n- ✅ Comprehensive specification analysis workflow using WebFetch\n- ✅ Detailed mapping table from spec changes → components (15+ change types)\n- ✅ Real examples from OAS 3.1 implementation (6 detailed examples)\n- ✅ Iterative spec-driven development approach\n- ✅ Component-by-component verification checklist\n- ✅ Best practices for continuous spec reference\n- ✅ WebFetch query templates for spec analysis\n- ✅ Common pitfalls and solutions\n- ✅ Pre-submit checklist\n\n**Based on:**\nThis skill follows the patterns established by the OAS 3.1 implementation (commit history analyzed from `src/core/plugins/oas31/`).\n\n**Key patterns:**\n- Plugin-based architecture with Redux state management\n- Selector factories for version-specific logic\n- Component wrapping for conditional rendering\n- afterLoad lifecycle hooks for function overrides\n- Plugin loading order (new version loaded LAST)\n\n**Prerequisites:**\n- Understanding of Swagger UI plugin architecture\n- Access to the new OAS specification document\n- All existing tests passing\n\n**Example workflow:**\n\nAdding OAS 4.0 support:\n```\n# Start the skill\n/add-oas-support --version 4.0 --type major\n\n# Claude will:\n# 1. Ask about new features in OAS 4.0\n# 2. Create plugin directory structure\n# 3. Generate boilerplate code\n# 4. Guide through implementation\n# 5. Add tests\n# 6. Update documentation\n# 7. Verify build\n```\n\n## Creating New Skills\n\nTo create a new skill for Swagger UI:\n\n1. Create a markdown file in `.claude/skills/`\n2. Add frontmatter with skill metadata:\n   ```yaml\n   ---\n   name: skill-name\n   description: Brief description\n   args:\n     param1:\n       description: \"Parameter description\"\n       required: true\n       type: string\n   ---\n   ```\n3. Write comprehensive instructions following the patterns in existing skills\n4. Document common pitfalls and best practices\n5. Include code templates with placeholders\n6. Add to this README\n\n## Skill Development Guidelines\n\nWhen creating skills for Swagger UI:\n\n1. **Follow project conventions:**\n   - No semicolons\n   - Double quotes\n   - @prettier pragma in all new files\n   - .jsx extension for React components\n\n2. **Use the plugin architecture:**\n   - Don't modify core unnecessarily\n   - Follow established patterns\n   - Load new plugins at the end of presets\n\n3. **Include comprehensive tests:**\n   - Unit tests for logic\n   - Component tests for UI\n   - E2E tests for integration\n\n4. **Document thoroughly:**\n   - Update CLAUDE.md\n   - Update relevant docs\n   - Add inline JSDoc comments\n\n5. **Security first:**\n   - Use DOMPurify for HTML\n   - Validate all input\n   - Follow OWASP guidelines\n\n## Contributing\n\nTo contribute new skills:\n\n1. Fork the repository\n2. Create skill in `.claude/skills/`\n3. Test thoroughly\n4. Update this README\n5. Submit pull request\n\n## Resources\n\n- **CLAUDE.md** - Comprehensive codebase guide\n- **Plugin API** - `docs/customization/plugin-api.md`\n- **Development Setup** - `docs/development/setting-up.md`\n- **Contributing Guide** - https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md\n","isInternal":false,"tokens":1066,"sizeBytes":4560},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/swagger-api/swagger-ui/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md - Swagger UI Codebase Guide\n\n> **Last Updated:** 2026-02-24\n> **Version:** 5.32.0 (in development)\n> **Purpose:** Comprehensive guide for AI assistants working with the Swagger UI codebase\n\n---\n\n## Table of Contents\n\n1. [Repository Overview](#repository-overview)\n2. [Project Architecture](#project-architecture)\n3. [Development Setup](#development-setup)\n4. [Build System](#build-system)\n5. [Testing Infrastructure](#testing-infrastructure)\n6. [Code Style & Conventions](#code-style--conventions)\n7. [Git Workflow](#git-workflow)\n8. [Plugin Architecture](#plugin-architecture)\n9. [Key Files & Directories](#key-files--directories)\n10. [Common Workflows](#common-workflows)\n11. [Important Guidelines](#important-guidelines)\n\n---\n\n## Repository Overview\n\n### What is Swagger UI?\n\nSwagger UI is a tool that allows developers to visualize and interact with API resources without having implementation logic in place. It's automatically generated from OpenAPI (formerly Swagger) Specification documents.\n\n### Multi-Package Monorepo Structure\n\nThis repository publishes **three different npm packages**:\n\n1. **swagger-ui** (main package)\n   - Traditional npm module for single-page applications\n   - Entry: `dist/swagger-ui.js`\n   - ES Module: `dist/swagger-ui-es-bundle-core.js`\n   - Includes dependency resolution via Webpack/Browserify\n\n2. **swagger-ui-dist** (distribution package)\n   - Dependency-free module for server-side projects\n   - Published separately via GitHub workflow\n   - Template location: `swagger-ui-dist-package/`\n\n3. **swagger-ui-react** (React component)\n   - React wrapper component\n   - Location: `flavors/swagger-ui-react/`\n   - Uses React hooks\n   - Released separately via GitHub workflow\n\n### OpenAPI Specification Compatibility\n\n- **Current Support:** OpenAPI 2.0, 3.0.x, 3.1.x\n- **Latest Version:** v5.31.0 (supports up to OpenAPI 3.1.2)\n\n### License\n\nApache 2.0 - See LICENSE and NOTICE files for details.\n\n---\n\n## Project Architecture\n\n### Technology Stack\n\n**Core Framework:**\n- React 18 (>=16.8.0 <20) - UI components\n- Redux 5.0.1 - State management\n- Redux Immutable 4.0.0 - Immutable state\n- Immutable.js 3.x - Immutable data structures\n- React Redux 9.2.0 - React-Redux bindings\n\n**API & Schema Processing:**\n- swagger-client 3.36.0 - OpenAPI client\n- js-yaml 4.1.1 - YAML parsing\n- remarkable 2.0.1 - Markdown rendering\n\n**Security:**\n- DOMPurify 3.2.6 - HTML sanitization (CRITICAL for XSS prevention)\n- serialize-error 8.1.0 - Error serialization\n\n**Build Tools:**\n- Webpack 5.97.1 - Module bundling\n- Babel 7.26.x - JavaScript transpilation\n- sass-embedded 1.86.0 - SCSS compilation\n- PostCSS - CSS processing\n\n**Testing:**\n- Jest 29.7.0 - Unit testing\n- Cypress 14.2.0 - E2E testing\n- Enzyme 3.11.0 - React component testing\n\n**Development:**\n- ESLint 8.57.0 - JavaScript linting\n- Prettier 3.5.3 - Code formatting\n- Stylelint 16.19.1 - CSS linting\n- Husky 9.1.7 - Git hooks\n- lint-staged 15.5.0 - Pre-commit linting\n\n### Plugin-Based Architecture\n\nSwagger UI uses a **sophisticated plugin system** powered by Redux. The core system (`src/core/system.js`) manages:\n\n- Plugin registration and lifecycle\n- Redux store creation and middleware\n- State plugin combination\n- Action/selector binding\n- Configuration management\n\n**26 Core Plugins** (in `src/core/plugins/`):\n- `auth` - Authentication handling\n- `configs` - Configuration management\n- `deep-linking` - URL-based navigation\n- `download-url` - Spec downloading\n- `err` - Error handling and transformation\n- `filter` - API filtering\n- `icons` - Icon components\n- `json-schema-2020-12` - JSON Schema 2020-12 support\n- `json-schema-2020-12-samples` - Sample generation\n- `json-schema-5` - JSON Schema Draft 5 support\n- `json-schema-5-samples` - Sample generation for Draft 5\n- `layout` - Layout system\n- `logs` - Logging\n- `oas3` - OpenAPI 3.0.x support\n- `oas31` - OpenAPI 3.1.x support\n- `oas32` - OpenAPI 3.2.x support\n- `on-complete` - Completion callbacks\n- `request-snippets` - Code snippet generation\n- `safe-render` - Safe component rendering\n- `spec` - Specification handling\n- `swagger-client` - API client integration\n- `syntax-highlighting` - Code highlighting\n- `util` - Utilities\n- `versions` - Version detection\n- `view` - View rendering\n- `view-legacy` - Legacy view support\n\n---\n\n## Development Setup\n\n### Prerequisites\n\n- **Node.js:** >=24.22 (Node 24.x recommended, as defined in `.nvmrc`)\n- **npm:** >=11.19.1\n- **Git:** Any version\n- **JDK 7+:** Required for Nightwatch.js integration tests\n\n### Installation Steps\n\n```bash\n# Clone the repository\ngit clone https://github.com/swagger-api/swagger-ui.git\ncd swagger-ui\n\n# Install dependencies\nnpm install\n\n# Initialize Husky (optional, for git hooks)\nnpx husky init\n\n# Start development server\nnpm run dev\n\n# Open http://localhost:3200/\n```\n\n### Development Server\n\nThe `npm run dev` command starts a hot-reloading Webpack dev server on **port 3200**.\n\n### Using Local API Definitions\n\nEdit `dev-helpers/dev-helper-initializer.js` to change the spec URL:\n\n```javascript\n// Replace\nurl: \"https://petstore.swagger.io/v2/swagger.json\",\n\n// With\nurl: \"./examples/your-local-api-definition.yaml\",\n```\n\n**Important:** Local files must be in the `dev-helpers/` directory or subdirectory. Use `dev-helpers/examples/` (already in `.gitignore`).\n\n---\n\n## Build System\n\n### Babel Environments\n\nThree Babel environments configured in `babel.config.js`:\n\n1. **development/production** - Browser builds with `modules: \"auto\"`\n2. **commonjs** - CommonJS modules with `modules: \"commonjs\"` for Node.js\n3. **esm** - ES modules with `modules: false` for modern bundlers\n\n### Babel Aliases\n\n```javascript\n{\n  root: \".\",\n  core: \"./src/core\"\n}\n```\n\n### Browserslist Environments\n\nDefined in `.browserslistrc`:\n\n- `[browser-production]` - Production browser targets\n- `[browser-development]` - Latest Chrome, Firefox, Safari\n- `[isomorphic-production]` - Browser + Node targets\n- `[node-production]` - Maintained Node versions\n- `[node-development]` - Node 24\n\n### Build Commands\n\n```bash\n# Full build (stylesheets + all bundles)\nnpm run build\n\n# Individual builds\nnpm run build:core              # Core bundle (browser)\nnpm run build:bundle            # Isomorphic bundle\nnpm run build:standalone        # Standalone preset\nnpm run build:es:bundle         # ES module bundle\nnpm run build:es:bundle:core    # ES module core\nnpm run build-stylesheets       # CSS only\n\n# Clean build artifacts\nnpm run clean\n```\n\n### Build Output (dist/)\n\n- `swagger-ui.js` - Core bundle (CommonJS)\n- `swagger-ui.css` - Compiled styles\n- `swagger-ui-bundle.js` - Isomorphic bundle\n- `swagger-ui-standalone-preset.js` - Standalone preset\n- `swagger-ui-es-bundle.js` - ES module bundle\n- `swagger-ui-es-bundle-core.js` - ES module core\n- `oauth2-redirect.html` - OAuth2 redirect page\n\n### Webpack Configurations\n\nLocated in `webpack/` directory:\n\n- `_config-builder.js` - Base configuration\n- `core.js` - Core build\n- `bundle.js` - Bundle build\n- `standalone.js` - Standalone build\n- `es-bundle.js` - ES bundle\n- `es-bundle-core.js` - ES core bundle\n- `stylesheets.js` - CSS build\n- `dev.js` - Development server\n- `dev-e2e.js` - E2E testing server\n\n---\n\n## Testing Infrastructure\n\n### Unit Tests (Jest)\n\n**Configuration:** `config/jest/jest.unit.config.js`\n\n**Environment:** jsdom (simulates browser environment)\n\n**Location:** `test/unit/`\n\n**Command:**\n```bash\nnpm run test:unit\n```\n\n**Key Features:**\n- 37 unit test files\n- Tests for core plugins, components, system\n- XSS security tests\n- Silent mode enabled by default (set to `false` for console output)\n- Module name mapper for SVG and standalone imports\n- Transform ignore patterns for node_modules exceptions\n\n**Setup Files:**\n- `test/unit/jest-shim.js` - Polyfills and shims\n- `test/unit/setup.js` - Test environment setup\n\n### E2E Tests (Cypress)\n\n**Configuration:** `cypress.config.js`\n\n**Location:** `test/e2e-cypress/`\n\n**Base URL:** http://localhost:3230/\n\n**Commands:**\n```bash\n# Run all E2E tests\nnpm run cy:ci\n\n# Interactive Cypress runner\nnpm run cy:dev\n\n# Headless run\nnpm run cy:run\n\n# Start servers and run tests\nnpm run cy:start     # Starts webpack + mock API\n```\n\n**Structure:**\n- `test/e2e-cypress/e2e/` - Test specs (99 test files)\n- `test/e2e-cypress/static/` - Test fixtures and documents\n- `test/e2e-cypress/support/` - Test helpers and commands\n\n**Test Categories:**\n- `a11y/**/*cy.js` - Accessibility tests\n- `security/**/*cy.js` - Security tests\n- `bugs/**/*cy.js` - Bug regression tests\n- `features/**/*cy.js` - Feature tests\n\n**Mock API Server:**\n```bash\nnpm run cy:mock-api  # JSON Server on port 3204\n```\n\n### Artifact Tests\n\n**Configuration:** `config/jest/jest.artifact.config.js`\n\n**Purpose:** Verify build artifacts export correctly\n\n**Command:**\n```bash\nnpm run test:artifact\n```\n\n### Complete Test Suite\n\n```bash\nnpm test  # Runs: lint-errors + test:unit + cy:ci\n```\n\n### CI/CD Testing\n\n**GitHub Actions Workflow:** `.github/workflows/nodejs.yml`\n\n**Two Jobs:**\n1. **build** - Lint, unit tests, build, artifact tests\n2. **e2e-tests** - Cypress tests (matrix strategy with 3 containers)\n\n**Branches:** `main`, `next`\n\n---\n\n## Code Style & Conventions\n\n### ESLint Configuration\n\n**File:** `.eslintrc.js`\n\n**Parser:** `@babel/eslint-parser`\n\n**Key Rules:**\n- `semi: [2, \"never\"]` - **No semicolons**\n- `quotes: [2, \"double\"]` - **Double quotes** (allow template literals)\n- `no-unused-vars: 2` - Error on unused variables\n- `camelcase: [\"error\"]` - Enforce camelCase (with exceptions for UNSAFE_, request generators, etc.)\n- `no-console: [2, {allow: [\"warn\", \"error\"]}]` - Only `console.warn` and `console.error` allowed\n- `react/jsx-no-bind: 1` - Warning for JSX bind\n- `react/jsx-filename-extension: 2` - JSX only in `.jsx` files\n- `import/no-extraneous-dependencies: 2` - Error on extraneous dependencies\n\n**Extends:**\n- `eslint:recommended`\n- `plugin:react/recommended`\n- `plugin:prettier/recommended`\n\n### Prettier Configuration\n\n**File:** `.prettierrc.yaml`\n\n**Settings:**\n```yaml\nsemi: false              # No semicolons\ntrailingComma: es5       # ES5 trailing commas\nendOfLine: lf            # Unix line endings\nrequirePragma: true      # Require @prettier pragma\ninsertPragma: true       # Insert @prettier pragma\n```\n\n**IMPORTANT:** Prettier requires `@prettier` pragma comment at the top of files:\n```javascript\n/**\n * @prettier\n */\n```\n\n### Stylelint Configuration\n\n**File:** `stylelint.config.js`\n\n**Custom Syntax:** `postcss-scss`\n\n**Rules:**\n- Uses `stylelint-prettier` plugin\n- Prettier integration without pragma requirement\n\n### Pre-commit Hooks\n\n**Husky:** `.husky/pre-commit` runs `npx lint-staged`\n\n**Lint-staged Configuration:** `.lintstagedrc`\n```json\n{\n  \"*.{js,jsx}\": [\"eslint --max-warnings 0\"],\n  \"*.scss\": [\"stylelint '**/*.scss'\"]\n}\n```\n\n**Critical:** All staged JS/JSX/SCSS files are linted with **zero warnings tolerance**.\n\n### File Structure Conventions\n\n**TypeScript (REQUIRED for all new files):**\n- All new source files must be written in TypeScript (`.ts` / `.tsx`)\n- Use `.tsx` for React components, `.ts` for all other modules\n- Existing `.js` / `.jsx` files are not required to be migrated, but new code must not be added in plain JavaScript\n\n**Components:**\n- Location: `src/core/components/`\n- Extension: `.tsx` (React components — TypeScript)\n- Format: PascalCase for component names\n\n**Styles:**\n- Location: `src/style/`\n- Extension: `.scss`\n- Format: SCSS with PostCSS processing\n- Dark mode: `_dark-mode.scss`\n\n**Tests:**\n- Unit: `test/unit/` (mirrors source structure)\n- E2E: `test/e2e-cypress/e2e/`\n- Naming: `*.test.ts`, `*.spec.ts`, `*.cy.ts` (Cypress) — use `.tsx` variants when JSX is involved\n\n---\n\n## Git Workflow\n\n### Branch Strategy\n\n**Main Branches:**\n- `main` - Production releases\n- `next` - Next version development\n\n**Feature Branches:**\n- Should branch from `main` or `next`\n- Use descriptive names\n\n### Commit Conventions\n\n**Format:** Conventional Commits (enforced by commitlint)\n\n**Structure:**\n```\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n```\n\n**Types:**\n- `feat` - New feature\n- `fix` - Bug fix\n- `docs` - Documentation changes\n- `style` - Code style changes (formatting)\n- `refactor` - Code refactoring\n- `test` - Test additions/changes\n- `chore` - Build/tooling changes\n- `perf` - Performance improvements\n\n**Example:**\n```\nfeat(oas3): add support for OpenAPI 3.1.1 callbacks\n\nImplement callback rendering for OAS 3.1.1 specifications\nwith proper schema resolution and example generation.\n\nFixes #12345\n```\n\n### Pull Request Process\n\n**Template:** `.github/pull_request_template.md`\n\n**Required Sections:**\n1. **Description** - Detailed change description\n2. **Motivation and Context** - Why the change is needed\n3. **How Has This Been Tested?** - Manual testing details\n4. **Screenshots** - If UI changes\n\n**Checklist:**\n- [ ] Code type (no code/dependencies/bug fix/improvement/feature)\n- [ ] Breaking changes identification\n- [ ] Documentation updates\n- [ ] Test coverage\n- [ ] All tests passing\n\n**CI Checks:**\n- ESLint (error-only mode)\n- Unit tests (Jest)\n- Build verification\n- Artifact tests\n- E2E tests (Cypress)\n\n### Release Process\n\n**Tool:** release-it with conventional-changelog\n\n**Command:**\n```bash\nnpm run automated-release\n```\n\n**Workflows:**\n- `.github/workflows/release-swagger-ui.yml`\n- `.github/workflows/release-swagger-ui-dist.yml`\n- `.github/workflows/release-swagger-ui-react.yml`\n- `.github/workflows/release-swagger-ui-packagist.yml`\n\n---\n\n## Plugin Architecture\n\n### Core System (`src/core/system.js`)\n\nThe plugin system is the heart of Swagger UI. It uses Redux for state management with a custom plugin registration system.\n\n### Plugin Structure\n\nEach plugin is a JavaScript object/function that returns:\n\n```javascript\n{\n  statePlugins: {\n    [pluginName]: {\n      actions: {},      // Redux actions\n      reducers: {},     // Redux reducers\n      selectors: {},    // Reselect selectors\n      wrapActions: {},  // Action middleware\n      wrapSelectors: {} // Selector middleware\n    }\n  },\n  components: {},       // React components\n  fn: {},              // Utility functions\n  rootInjects: {},     // Root-level injections\n  afterLoad: Function  // Lifecycle hook\n}\n```\n\n### Key Plugin Locations\n\n**Core Plugins:** `src/core/plugins/`\n\nEach plugin has:\n- `index.js` - Main export\n- `actions.js` - Redux actions\n- `reducers.js` - Redux reducers\n- `selectors.js` - State selectors\n- `wrap-actions.js` - Action middleware\n- `wrap-selectors.js` - Selector middleware\n- Component files (`.jsx`)\n\n### Creating a Plugin\n\nSee documentation: `docs/customization/plugin-api.md`\n\n### Cross-Plugin Import Guidelines\n\n**IMPORTANT:** Avoid cross-plugin imports to maintain plugin independence and modularity.\n\n**Pattern to Follow:**\n- Each plugin should be self-contained with its own components, utilities, and functions\n- When OAS version plugins (oas3, oas31, oas32) need similar functionality, create self-contained copies within each plugin\n- Wrap components should import from their own plugin's components, not from other plugins\n\n**Example Structure:**\n```\nsrc/core/plugins/oas32/\n├── json-schema-2020-12-extensions/\n│   ├── components/              # Self-contained components\n│   │   └── keywords/\n│   │       ├── Description.jsx\n│   │       └── Properties.jsx\n│   ├── wrap-components/         # Wrappers for components\n│   │   └── keywords/\n│   │       ├── Description.jsx  # Imports from ../../components/\n│   │       └── Properties.jsx   # Not from ../../../../oas31/\n│   └── fn.js                    # Self-contained utilities\n```\n\n**Why This Matters:**\n- Prevents tight coupling between plugins\n- Makes plugins easier to test in isolation\n- Allows independent versioning and updates\n- Reduces risk of breaking changes across plugins\n- Improves code maintainability\n\n**Exceptions:**\n- Shared core utilities in `src/core/utils/` are acceptable\n- System-level functions in `src/core/system.js` are acceptable\n- Base components in `src/core/components/` are acceptable\n\n### Preset System\n\n**Base Preset:** `src/core/presets/base.js`\n\n**Standalone Preset:** `src/standalone/presets/standalone.js`\n\nPresets are collections of plugins bundled together for specific use cases.\n\n---\n\n## Key Files & Directories\n\n### Critical Source Files\n\n```\nsrc/\n├── core/\n│   ├── system.js                 # Plugin system & Redux store\n│   ├── components/               # 59 React components\n│   ├── plugins/                  # 26 core plugins\n│   ├── presets/                  # Preset configurations\n│   ├── utils/                    # Utility functions\n│   └── config/                   # Configuration system\n├── standalone/\n│   ├── plugins/                  # TopBar, StandaloneLayout\n│   └── presets/                  # Standalone preset\n├── style/                        # SCSS stylesheets\n│   ├── _dark-mode.scss          # Dark mode styles\n│   └── main.scss                # Main stylesheet entry\n└── index.js                      # Main package entry\n```\n\n### Configuration Files\n\n```\n.\n├── package.json                  # Dependencies & scripts\n├── babel.config.js              # Babel configuration\n├── .eslintrc.js                 # ESLint rules\n├── .prettierrc.yaml             # Prettier settings\n├── stylelint.config.js          # Stylelint rules\n├── .browserslistrc              # Browser targets\n├── .nvmrc                       # Node version (24.x)\n├── .lintstagedrc                # Pre-commit linting\n└── cypress.config.js            # Cypress E2E config\n```\n\n### Build & Tooling\n\n```\nwebpack/\n├── _config-builder.js           # Base Webpack config\n├── core.js                      # Core build\n├── bundle.js                    # Bundle build\n├── standalone.js                # Standalone build\n├── es-bundle.js                 # ES bundle build\n├── es-bundle-core.js           # ES core bundle\n├── stylesheets.js              # CSS compilation\n├── dev.js                       # Dev server\n└── dev-e2e.js                  # E2E dev server\n\nconfig/jest/\n├── jest.unit.config.js          # Unit test config\n└── jest.artifact.config.js      # Artifact test config\n```\n\n### Documentation\n\n```\ndocs/\n├── usage/\n│   ├── installation.md\n│   ├── configuration.md\n│   ├── cors.md\n│   ├── oauth2.md\n│   ├── deep-linking.md\n│   ├── version-detection.md\n│   └── limitations.md\n├── customization/\n│   ├── overview.md\n│   ├── plugin-api.md\n│   └── custom-layout.md\n└── development/\n    ├── setting-up.md\n    └── scripts.md\n```\n\n### Testing\n\n```\ntest/\n├── unit/                        # Jest unit tests (37 files)\n│   ├── setup.js                # Test environment setup\n│   └── jest-shim.js           # Polyfills\n├── e2e-cypress/                 # Cypress E2E tests (99 files)\n│   ├── e2e/                    # Test specs\n│   ├── static/                 # Fixtures\n│   └── support/                # Helpers\n└── e2e-selenium/               # Legacy Selenium tests\n```\n\n### Distribution\n\n```\nflavors/\n└── swagger-ui-react/            # React component wrapper\n\nswagger-ui-dist-package/         # Template for dist package\n\ndist/                            # Build output (generated)\n├── swagger-ui.js\n├── swagger-ui.css\n├── swagger-ui-bundle.js\n├── swagger-ui-standalone-preset.js\n├── swagger-ui-es-bundle.js\n├── swagger-ui-es-bundle-core.js\n└── oauth2-redirect.html\n```\n\n---\n\n## Common Workflows\n\n### Making Code Changes\n\n1. **Read before modifying:**\n   ```bash\n   # ALWAYS read files before editing them\n   # Understand the existing code structure\n   ```\n\n2. **Follow the style guide:**\n   - Use double quotes\n   - No semicolons\n   - Add `@prettier` pragma to new files\n   - Use `.jsx` extension for React components\n\n3. **Run linters:**\n   ```bash\n   npm run lint          # Check for errors and warnings\n   npm run lint-fix      # Auto-fix JavaScript issues\n   npm run lint-styles   # Check SCSS\n   npm run lint-styles-fix  # Auto-fix SCSS\n   ```\n\n4. **Test your changes:**\n   ```bash\n   npm run test:unit     # Run unit tests\n   npm run cy:dev        # Interactive E2E testing\n   npm run build         # Verify build works\n   npm run test:artifact # Verify artifacts\n   ```\n\n### Adding a New Component\n\n1. Create component in `src/core/components/` or appropriate plugin directory\n2. Use `.tsx` extension (TypeScript — required for all new files)\n3. Add `@prettier` pragma\n4. Follow React best practices (functional components, hooks)\n5. Add PropTypes validation\n6. Create corresponding test in `test/unit/`\n7. Export from plugin's `index.js` if needed\n\n### Adding a New Plugin\n\n1. Create directory in `src/core/plugins/[plugin-name]/`\n2. Create `index.ts` with plugin structure (TypeScript — required for all new files)\n3. Add actions, reducers, selectors as needed\n4. Register plugin in preset (e.g., `src/core/presets/base.js`)\n5. Add tests in `test/unit/core/plugins/[plugin-name]/`\n6. Document the plugin\n\n### Fixing a Bug\n\n1. **Reproduce the bug:**\n   - Add a failing test in `test/unit/` or `test/e2e-cypress/`\n   - Document reproduction steps\n\n2. **Fix the issue:**\n   - Make minimal changes to fix the bug\n   - Avoid refactoring unless necessary\n   - Ensure the test now passes\n\n3. **Verify:**\n   ```bash\n   npm run test:unit\n   npm run build\n   npm run test:artifact\n   ```\n\n4. **Create PR:**\n   - Reference the issue number\n   - Include before/after behavior\n   - Add screenshots if UI-related\n\n### Adding a Feature\n\n1. **Plan the feature:**\n   - Review existing architecture\n   - Identify affected plugins/components\n   - Consider OpenAPI spec compatibility\n\n2. **Implement:**\n   - Follow plugin architecture patterns\n   - Add configuration options if needed\n   - Update presets if necessary\n\n3. **Test thoroughly:**\n   - Unit tests for logic\n   - Component tests for UI\n   - E2E tests for integration\n   - Test with various OpenAPI specs\n\n4. **Document:**\n   - Update `docs/` if user-facing\n   - Add JSDoc comments for APIs\n   - Update README if needed\n\n### Security Considerations\n\n1. **XSS Prevention:**\n   - ALWAYS use DOMPurify for user-provided HTML\n   - Sanitize all external input\n   - Review `test/unit/xss/` for examples\n   - Never use `dangerouslySetInnerHTML` without sanitization\n\n2. **Input Validation:**\n   - Validate API responses\n   - Handle malformed OpenAPI specs gracefully\n   - Check for prototype pollution\n\n3. **Dependency Security:**\n   ```bash\n   npm run security-audit     # Run security audit\n   ```\n\n### Working with OpenAPI Specs\n\n**Testing Different Versions:**\n- OAS 2.0: Use `src/core/plugins/swagger-client/`\n- OAS 3.0.x: Use `src/core/plugins/oas3/`\n- OAS 3.1.x: Use `src/core/plugins/oas31/`\n- OAS 3.2.x: Use `src/core/plugins/oas32/`\n\n**Adding Test Specs:**\n- Add to `test/e2e-cypress/static/documents/`\n- Reference in E2E tests\n\n---\n\n## Important Guidelines\n\n### DO's ✅\n\n1. **Always read files before modifying them**\n2. **Write all new files in TypeScript** - use `.ts` for modules, `.tsx` for React components\n3. **Follow the no-semicolon convention**\n4. **Use double quotes for strings**\n5. **Add `@prettier` pragma to all new files**\n6. **Use `.tsx` extension for new React components** (TypeScript JSX)\n7. **Write tests for new features and bug fixes**\n8. **Run linters before committing** (automatic via husky)\n9. **Use DOMPurify for HTML sanitization**\n10. **Follow conventional commit format**\n11. **Update documentation for user-facing changes**\n12. **Test with multiple OpenAPI spec versions**\n13. **Check browser compatibility** (see `.browserslistrc`)\n14. **Use the plugin architecture** - don't modify core unnecessarily\n15. **Preserve backward compatibility** unless explicitly breaking\n16. **Run full test suite before submitting PR**\n17. **Keep plugins self-contained** - avoid cross-plugin imports (see [Cross-Plugin Import Guidelines](#cross-plugin-import-guidelines))\n\n### DON'Ts ❌\n\n1. **Don't write new files in plain JavaScript** - all new files must be TypeScript (`.ts` / `.tsx`)\n2. **Don't use semicolons** - project convention\n3. **Don't use single quotes** - use double quotes\n4. **Don't skip the @prettier pragma** - required for formatting\n5. **Don't put React in `.ts` files** - use `.tsx` for JSX\n6. **Don't commit files in `dev-helpers/`** (except core files)\n7. **Don't commit build artifacts** (`dist/` is gitignored)\n8. **Don't skip tests** - they run in CI\n9. **Don't bypass ESLint** - pre-commit hook enforces\n10. **Don't use `console.log`** - only `console.warn` and `console.error`\n11. **Don't render unsanitized HTML** - XSS vulnerability\n12. **Don't modify `package-lock.json` manually**\n13. **Don't push directly to `main` or `next`**\n14. **Don't ignore Cypress test failures**\n15. **Don't add dependencies without justification**\n16. **Don't break the build** - verify with `npm run build`\n17. **Don't import from other plugins** - create self-contained copies instead (e.g., don't import from `oas31` in `oas32`)\n\n### When Working with AI Assistants\n\n**Before Making Changes:**\n1. Read the affected files completely\n2. Understand the plugin architecture\n3. Check for existing tests\n4. Review related documentation\n\n**During Development:**\n1. Make minimal, focused changes\n2. Follow existing patterns in the codebase\n3. Add tests alongside code changes\n4. Run linters frequently\n\n**After Changes:**\n1. Verify all tests pass\n2. Check build completes successfully\n3. Test artifact exports\n4. Review for security issues\n5. Update relevant documentation\n\n**Communication:**\n- Be explicit about file locations\n- Use line number references (e.g., `src/core/system.js:96`)\n- Provide context for changes\n- Mention any breaking changes clearly\n\n### Performance Considerations\n\n1. **Immutable.js:**\n   - Use Immutable data structures for state\n   - Use `.toJS()` sparingly (expensive)\n   - Prefer Immutable operations\n\n2. **React:**\n   - Use React.memo for pure components\n   - Implement shouldComponentUpdate for class components\n   - Avoid inline function definitions in render\n\n3. **Redux:**\n   - Use reselect for memoized selectors\n   - Keep reducers pure and fast\n   - Avoid large state trees\n\n4. **Bundle Size:**\n   - Check bundle size with `npm run deps-size`\n   - Review dependency licenses with `npm run deps-license`\n   - Consider code splitting for large features\n\n### Debugging Tips\n\n**Development Server:**\n```bash\nnpm run dev\n# Open http://localhost:3200/\n# Hot reload enabled\n# Unminified stack traces\n```\n\n**Redux DevTools:**\n- Extension supported\n- State inspection available\n- Time-travel debugging\n\n**Cypress Interactive Mode:**\n```bash\nnpm run cy:dev\n# Visual test runner\n# Step-through debugging\n# Network inspection\n```\n\n**Jest Watch Mode:**\n```bash\nnpm run test:unit -- --watch\n# Re-run on file changes\n# Filter by file name or test name\n```\n\n**Source Maps:**\n- Generated for all builds\n- Enable in browser DevTools\n- Original source debugging\n\n---\n\n## Quick Reference\n\n### Essential Commands\n\n```bash\n# Development\nnpm run dev              # Start dev server (port 3200)\nnpm start                # Static file server (port 3002)\n\n# Building\nnpm run build            # Full production build\nnpm run clean            # Remove dist/\n\n# Testing\nnpm test                 # Full test suite (lint + unit + E2E)\nnpm run test:unit        # Jest unit tests\nnpm run cy:dev           # Cypress interactive\nnpm run cy:ci            # Cypress CI mode\nnpm run test:artifact    # Artifact verification\n\n# Linting\nnpm run lint             # ESLint (errors + warnings)\nnpm run lint-errors      # ESLint (errors only)\nnpm run lint-fix         # Auto-fix ESLint issues\nnpm run lint-styles      # Stylelint\nnpm run lint-styles-fix  # Auto-fix Stylelint issues\n\n# Security\nnpm run security-audit   # Run npm audit\n\n# Dependencies\nnpm run deps-check       # Size and license report\n```\n\n### File Paths\n\n```\nCore System:           src/core/system.js\nMain Entry:            src/index.js\nReact Entry:           flavors/swagger-ui-react/index.jsx\nComponents:            src/core/components/\nPlugins:               src/core/plugins/\nStyles:                src/style/\nTests (Unit):          test/unit/\nTests (E2E):           test/e2e-cypress/e2e/\nBuild Output:          dist/\n```\n\n### Port Reference\n\n- **3200** - Development server (webpack-dev-server)\n- **3002** - Static file server (local-web-server)\n- **3204** - Mock API server (json-server)\n- **3230** - E2E test server (webpack-dev-server)\n\n---\n\n## Additional Resources\n\n### Documentation\n\n- **Setup Guide:** `docs/development/setting-up.md`\n- **Scripts Reference:** `docs/development/scripts.md`\n- **Plugin API:** `docs/customization/plugin-api.md`\n- **Configuration:** `docs/usage/configuration.md`\n- **OAuth2 Setup:** `docs/usage/oauth2.md`\n\n### External Links\n\n- **Homepage:** https://swagger.io/tools/swagger-ui/\n- **Repository:** https://github.com/swagger-api/swagger-ui\n- **npm (main):** https://www.npmjs.com/package/swagger-ui\n- **npm (dist):** https://www.npmjs.com/package/swagger-ui-dist\n- **npm (react):** https://www.npmjs.com/package/swagger-ui-react\n- **OpenAPI Spec:** https://spec.openapis.org/\n\n### Community\n\n- **Issues:** https://github.com/swagger-api/swagger-ui/issues\n- **Good First Issues:** https://github.com/swagger-api/swagger-ui/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%22\n- **Security:** security@swagger.io\n- **Contributing:** https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md\n\n---\n\n**Note:** This document should be updated whenever major architectural changes, new conventions, or significant workflows are introduced to the codebase.\n","isInternal":false,"tokens":7668,"sizeBytes":30002},{"name":"README.md","path":"src/core/plugins/deep-linking/README.md","rawUrl":"https://raw.githubusercontent.com/swagger-api/swagger-ui/HEAD/src/core/plugins/deep-linking/README.md","title":"deep-linking Documentation","category":"plugin-manifest","format":"markdown","content":"See `docs/deep-linking.md`.\n","isInternal":false,"tokens":9,"sizeBytes":28},{"name":"README.md","path":"src/core/plugins/err/error-transformers/README.md","rawUrl":"https://raw.githubusercontent.com/swagger-api/swagger-ui/HEAD/src/core/plugins/err/error-transformers/README.md","title":"error-transformers Documentation","category":"plugin-manifest","format":"markdown","content":"# Error transformers\n\nError transformers provide a standard interface for making generated error messages more useful to end users.\n\n### Inputs & outputs\n\nEach transformer's `transform` function is given an Immutable List of Immutable Maps as its first argument.\n\nIt is expected that each `transform` function returns a List of similarly-formed Maps.\n\nThese errors originate from the Redux error actions that add errors to state. Errors are transformed before being passed into the reducer.\n\nIt's important that all the keys present in each error (specifically, `line`, `level`, `message`, `source`, and `type`) are present when the transformer is finished.\n\n##### Deleting an error\n\nIf you want to delete an error completely, you can overwrite it with `null`. The null value will be filtered out of the transformed error array before the errors are returned.\nå\n\n### Example transformer\n\nThis transformer will increase all your line numbers by 10.\n\n```\nexport function transform(errors) {\n  return errors.map(err => {\n    err.line += 10\n    return err\n  })\n}\n```\n","isInternal":false,"tokens":215,"sizeBytes":1064}],"systemPromptSnippet":"<yakaai_skills repo=\"swagger-api/swagger-ui\">\n<!-- File: .claude/skills/add-oas-support.md (Tokens: ~12829 | Category: anthropic-skill) -->\n---\nname: add-oas-support\ndescription: Add support for a new OpenAPI Specification version to Swagger UI\nargs:\n  version:\n    description: \"OpenAPI version to add support for (e.g., 3.2, 4.0)\"\n    required: true\n    type: string\n  type:\n    description: \"Version type: 'major' for new major version, 'minor' for patch/minor\"\n    required: false\n    type: string\n    default: \"minor\"\n---\n\n# Add OpenAPI Specification Version Support\n\nThis skill guides you through adding support for a new OpenAPI Specification (OAS) version to Swagger UI, following the established architectural patterns from OAS 3.1 implementation.\n\n---\n\n## 📌 Quick Reference\n\n> **New to this skill?** Skip to [Prerequisites](#prerequisites) for the full guide.\n> **Already familiar?** Use this quick reference for rapid development.\n\n### 🚀 Quick Start\n\n```bash\n# Major version (e.g., OAS 4.0)\n/add-oas-support --version 4.0 --type major\n\n# Minor version (e.g., OAS 3.2)\n/add-oas-support --version 3.2 --type minor\n```\n\n### 📋 Essential Checklist\n\n#### Phase 1: Specification Analysis ⭐ MOST IMPORTANT\n- [ ] Access official spec at **https://spec.openapis.org/oas/v{VERSION}/**\n- [ ] Use WebFetch to analyze spec systematically\n- [ ] Create specification change document\n- [ ] Map changes to components using [mapping table](#step-1d-map-specification-changes-to-swagger-ui-components)\n\n#### Phase 2: Implementation\n- [ ] Create plugin directory structure\n- [ ] Implement version detection (`isOAS{VERSION}`)\n- [ ] Create selector factories\n- [ ] Implement components for each spec change\n- [ ] Wrap existing components if modified\n- [ ] Register plugin in preset (LAST position)\n\n#### Phase 3: Testing & Documentation\n- [ ] Add unit tests\n- [ ] Add E2E tests with spec examples\n- [ ] Update documentation\n- [ ] Verify build & run full test suite\n\n### 🔍 WebFetch Queries for Spec Analysis\n\n```javascript\n// 1. Fetch main spec differences\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all new top-level fields, modified fields, and removed fields compared to version {PREV_VERSION}\"\n)\n\n// 2. Analyze new feature\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Describe the '{NEW_FIELD}' field: structure, type, purpose, required/optional, and provide examples\"\n)\n\n// 3. Check JSON Schema version\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"What JSON Schema version does this use? List changes from {PREV_JSON_SCHEMA_VERSION}\"\n)\n\n// 4. Security schemes\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all security scheme types, highlighting new or changed types\"\n)\n```\n\n### 🗺️ Spec Change → Component Mapping (Quick)\n\n| Spec Change | Component Action | File Location |\n|-------------|------------------|---------------|\n| **New top-level field (Object)** | Create new component | `components/{field}.jsx` |\n| **New top-level field (String)** | Add to info or create display | `components/{field}.jsx` |\n| **Modified Info object** | Wrap Info component | `wrap-components/info.jsx` |\n| **New info subfield** | Create component + wrap Info | `components/info-{field}.jsx` |\n| **New auth type** | Create auth component | `components/auth/{type}.jsx` |\n| **Modified security** | Wrap auth selector | `auth-extensions/wrap-selectors.js` |\n| **New operation field** | Extend Operation/selector | `spec-extensions/selectors.js` |\n| **JSON Schema keyword** | Create keyword component | `json-schema-{V}-extensions/` |\n| **JSON Schema version** | Create entire new plugin | `plugins/json-schema-{V}/` |\n\nSee [full mapping table with examples](#step-1d-map-specification-changes-to-swagger-ui-components) for detailed guidance.\n\n### 📝 Component Implementation Pattern\n\n**For each new feature:**\n\n1. **Check spec first:**\n   ```javascript\n   WebFetch(url, \"Describe {field} structure, type, examples\")\n   ```\n\n2. **Create selector:**\n   ```javascript\n   // spec-extensions/selectors.js\n   export const selectNewField = createSelector(\n     (state) => state,\n     (state) => state.getIn([\"spec\", \"json\", \"newField\"])\n   )\n   ```\n\n3. **Create component:**\n   ```javascript\n   // components/new-field.jsx\n   const NewField = ({ specSelectors, getComponent }) => {\n     const data = specSelectors.selectNewField()\n     if (!data) return null\n     return <div>{/* render based on spec structure */}</div>\n   }\n   ```\n\n4. **Register in plugin:**\n   ```javascript\n   // index.js\n   components: { NewField },\n   statePlugins: {\n     spec: {\n       selectors: {\n         selectNewField: createOnlyOAS{V}Selector(selectNewField)\n       }\n     }\n   }\n   ```\n\n5. **Add tests** (unit + E2E with spec examples)\n\n### ⚠️ Common Pitfalls\n\n1. ❌ **Guessing field structure** → ✅ Always check spec with WebFetch\n2. ❌ **Forgetting @prettier pragma** → ✅ Add to all new files\n3. ❌ **Wrong plugin load order** → ✅ New plugin LAST in preset\n4. ❌ **Using semicolons** → ✅ No semicolons (project convention)\n5. ❌ **Single quotes** → ✅ Use double quotes\n6. ❌ **Skipping spec examples** → ✅ Use as test fixtures\n7. ❌ **Hardcoded assumptions** → ✅ Verify everything in spec\n8. ❌ **`props.Ori` in ComponentWrapper** → ✅ Use `props.originalComponent` (see Pattern 3)\n9. ❌ **Copying entire Info component for minor version** → ✅ Use OpenAPIVersion wrapper + `getComponent(\"OAS{PREV}Info\")`\n10. ❌ **OAS{VERSION} logic in OAS{PREV} plugin** → ✅ Each version's logic lives in its own plugin\n11. ❌ **`isOAS{PREV}` wrapper on minor version** → ✅ Only add if regex overlaps; minor bumps don't need it\n12. ❌ **New HTTP method in core `validOperationMethods`** → ✅ Add to `OPERATION_METHODS` + wrap with `createOnlyOAS{VERSION}SelectorWrapper`\n13. ❌ **Assuming new OAS meta-schema = new JSON Schema dialect** → ✅ Verify — OAS 3.2 still uses JSON Schema 2020-12\n14. ❌ **Inline version guard in wrap-components** → ✅ Always use `createOnlyOAS{VERSION}ComponentWrapper`; never write `(Original, system) => (props) => { if (...isOAS{VERSION}...) }` by hand — even expanding an existing guard (`isOAS31 || isOAS32`) is wrong; add dedicated wrap-components in the new plugin instead\n\n### ✅ Pre-Submit Checklist\n\n- [ ] All spec changes mapped to components\n- [ ] All components reference spec in comments\n- [ ] Tests use examples from spec\n- [ ] Version detection regex correct\n- [ ] Plugin loaded last in preset\n- [ ] All tests passing (lint + unit + E2E)\n- [ ] Build completes successfully\n- [ ] Documentation updated\n- [ ] No semicolons, double quotes everywhere\n- [ ] @prettier pragma in all new files\n\n### 📚 Quick Links\n\n- **OAS Specs:** https://spec.openapis.org/\n- **OAS 3.1:** https://spec.openapis.org/oas/v3.1.0/\n- **OAS 3.0:** https://spec.openapis.org/oas/v3.0.3/\n- **JSON Schema:** https://json-schema.org/\n- **CLAUDE.md:** Complete codebase guide\n\n### 🔖 Full Guide Navigation\n\nNeed detailed guidance? Jump to these sections:\n\n- **[Prerequisites](#prerequisites)** - Setup and requirements\n- **[Architecture Overview](#architecture-overview)** - Plugin system explained\n- **[Key Design Patterns](#key-design-patterns-from-oas-31)** - Code patterns from OAS 3.1\n- **[Step 1: Analyze Specification](#step-1-analyze-new-oas-version-specification)** - ⭐ Complete spec analysis workflow\n  - [1D: Mapping Table](#step-1d-map-specification-changes-to-swagger-ui-components) - 15+ spec change types\n  - [1E: Real Examples](#step-1e-examples-oas-31-specification-changes--components) - 6 detailed examples\n  - [1H: WebFetch Workflow](#step-1h-using-webfetch-to-analyze-specifications) - Spec analysis with WebFetch\n- **[Step 2-17: Implementation](#step-2-create-plugin-directory-structure)** - Complete implementation steps\n- **[Practical Workflow](#practical-workflow-from-spec-to-components)** - End-to-end example\n- **[Best Practices](#best-practices-iterative-spec-driven-development)** - Spec-driven development\n- **[Common Pitfalls](#common-pitfalls)** - What to avoid\n- **[Final Checklist](#final-checklist)** - Pre-submission verification\n\n---\n\n**Remember: The specification at https://spec.openapis.org/ is your source of truth!**\n\n---\n\n## Prerequisites\n\nBefore starting, ensure:\n- You understand the Swagger UI plugin architecture\n- You've read the CLAUDE.md guide\n- You have the OAS specification document for the new version\n- All tests pass: `npm test`\n\n## Architecture Overview\n\nAdding OAS version support involves:\n\n1. **Plugin Creation** - New plugin following established patterns\n2. **Version Detection** - Regex-based version identifier\n3. **Selector Factories** - Conditional logic for version-specific features\n4. **Component Implementation** - New/wrapped components for rendering\n5. **State Management** - Redux selectors/actions for new features\n6. **Lifecycle Hooks** - afterLoad modifications\n7. **Preset Registration** - Plugin loading order\n8. **Testing** - Unit and E2E tests\n9. **Documentation** - Update guides and README\n\n## Key Design Patterns (from OAS 3.1)\n\n### Pattern 1: Version Detection\n```javascript\nexport const isOAS{VERSION} = (jsSpec) => {\n  const oasVersion = jsSpec.get(\"openapi\")\n  return (\n    typeof oasVersion === \"string\" && /^{MAJOR}\\.{MINOR}\\.(?:[1-9]\\d*|0)$/.test(oasVersion)\n  )\n}\n```\n\n### Pattern 2: Selector Factories\n\n**createOnlyOAS{VERSION}Selector** - Features exclusive to this version:\n```javascript\nexport const createOnlyOAS{VERSION}Selector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(system)\n        : selectedValue\n    } else {\n      return null\n    }\n  }\n```\n\n**createOnlyOAS{VERSION}SelectorWrapper** - Override previous versions:\n```javascript\nexport const createOnlyOAS{VERSION}SelectorWrapper =\n  (selector) =>\n  (oriSelector, system) =>\n  (state, ...args) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(oriSelector, system)\n        : selectedValue\n    } else {\n      return oriSelector(...args)\n    }\n  }\n```\n\n### Pattern 3: Component Wrappers\n\n**⚠️ IMPORTANT: `originalComponent` prop name, not `Ori`**\n\n`createOnlyOAS{VERSION}ComponentWrapper` passes the original component as `originalComponent` in props (NOT `Ori` — that's the OAS3/OAS30ComponentWrapFactory convention). Use `const { originalComponent: Ori } = props` to access it.\n\n**Pattern A — Reuse previous version's component via getComponent:**\n```javascript\nconst ComponentWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => {\n  const system = getSystem()\n  const OAS{PREV_VERSION}Component = system.getComponent(\"OAS{PREV_VERSION}Component\", true)\n  return <OAS{PREV_VERSION}Component />\n})\n```\n\n**Pattern B — Render original component with extra props (e.g. version badge):**\n```javascript\n// Use `originalComponent` (NOT `Ori`) — that's the prop name createOnlyOAS{VERSION}ComponentWrapper passes\nconst OpenAPIVersionWrapper = createOnlyOAS{VERSION}ComponentWrapper((props) => {\n  const { originalComponent: Ori } = props\n  return <Ori oasVersion=\"{VERSION}\" />\n})\n```\n\n### Pattern 4: Function Wrapping\n```javascript\nexport const wrapOAS{VERSION}Fn = (fn, system) => {\n  const { fn: systemFn, specSelectors } = system\n  return Object.fromEntries(\n    Object.entries(fn).map(([name, newImpl]) => {\n      const oriImpl = systemFn[name]\n      const impl = (...args) =>\n        specSelectors.isOAS{VERSION}()\n          ? newImpl(...args)\n          : typeof oriImpl === \"function\"\n            ? oriImpl(...args)\n            : undefined\n      return [name, impl]\n    })\n  )\n}\n```\n\n## Implementation Steps\n\n### Step 1: Analyze New OAS Version Specification\n\n**CRITICAL: Always start by reviewing the official specification at https://spec.openapis.org/**\n\n#### 1A. Access the Official Specification\n\n**Primary Resource:** https://spec.openapis.org/\n\n**Available Versions:**\n- OAS 2.0: https://spec.openapis.org/oas/v2.0/\n- OAS 3.0.x: https://spec.openapis.org/oas/v3.0.3/\n- OAS 3.1.x: https://spec.openapis.org/oas/v3.1.0/\n- Future versions will follow the pattern: https://spec.openapis.org/oas/v{MAJOR}.{MINOR}.{PATCH}/\n\n**What to download:**\n1. The specification document (usually in HTML or Markdown format)\n2. JSON Schema definitions (if available)\n3. Example specification files\n4. Change log or migration guide (if available)\n\n#### 1B. Systematic Specification Analysis\n\nUse the WebFetch tool to retrieve and analyze the specification:\n\n```bash\n# Example for analyzing OAS 4.0 (hypothetical)\nWebFetch(\"https://spec.openapis.org/oas/v4.0.0/\", \"List all new top-level fields, objects, and keywords introduced in this version compared to OAS 3.1\")\n```\n\n**Read these sections carefully:**\n\n1. **Version Number Section**\n   - Confirm the exact version format (e.g., \"4.0.0\", \"3.2.0\")\n   - Note any version detection changes\n\n2. **OpenAPI Object (Root Level)**\n   - New top-level fields (e.g., `webhooks` in OAS 3.1)\n   - Modified existing fields\n   - Removed/deprecated fields\n\n3. **Info Object**\n   - New fields (e.g., `summary` in OAS 3.1)\n   - Changes to `license`, `contact`, etc.\n\n4. **Paths Object & Operations**\n   - New operation-level fields\n   - Changes to parameters, request bodies, responses\n   - New callback syntax or features\n\n5. **Components Object**\n   - New component types\n   - Schema changes (especially JSON Schema version)\n   - New security schemes\n\n6. **Security Object**\n   - New authentication types (e.g., `mutualTLS` in OAS 3.1)\n   - Changes to OAuth2 flows\n   - New security-related fields\n\n7. **Schema Object**\n   - JSON Schema version change (critical!)\n   - New keywords (e.g., `examples` vs `example`)\n   - Type system changes\n\n#### 1C. Create Specification Change Document\n\nCreate a structured document listing all changes:\n\n**Template:**\n```markdown\n# OpenAPI {VERSION} Specification Analysis\n\n## Version Information\n- Version: {MAJOR}.{MINOR}.{PATCH}\n- Release Date: YYYY-MM-DD\n- Previous Version: {PREVIOUS_VERSION}\n- JSON Schema Version: Draft {VERSION} or {YEAR}\n\n## New Top-Level Fields\n1. **`newField`** (Type: Object)\n   - Location: Root level\n   - Purpose: Description from spec\n   - Required: Yes/No\n   - Example from spec: {...}\n   - Swagger UI Impact: Needs new component in BaseLayout\n\n## Modified Existing Fields\n1. **`info`**\n   - New subfields: `summary`, `newField`\n   - Changed behavior: Description\n   - Swagger UI Impact: Need to wrap Info component\n\n## New Operation-Level Features\n1. **`newOperationField`**\n   - Purpose: Description\n   - Swagger UI Impact: Extend Operation component\n\n## New Authentication Types\n1. **`newAuthType`**\n   - Type name: \"newAuthType\"\n   - Fields: {...}\n   - Swagger UI Impact: New auth component needed\n\n## JSON Schema Changes\n- Version change: Draft 2020-12 → Draft 2024\n- New keywords: `keyword1`, `keyword2`\n- Removed keywords: `oldKeyword`\n- Swagger UI Impact: New json-schema plugin needed\n\n## Breaking Changes\n1. Removed `x-deprecated-field`\n2. Changed behavior of `existingField`\n3. Required fields now enforced\n\n## Deprecated Features\n1. `oldField` - Use `newField` instead\n2. `oldAuthType` - Use `newAuthType` instead\n\n## Examples from Specification\n- Link to example files\n- Notable edge cases to test\n```\n\n#### 1D. Map Specification Changes to Swagger UI Components\n\n**CRITICAL MAPPING GUIDE:** Use this table to determine what components to create/modify:\n\n| Spec Change Type | Swagger UI Component Type | Location | Example from OAS 3.1 |\n|-----------------|---------------------------|----------|---------------------|\n| **New Top-Level Field (Object)** | New standalone component | `components/{feature-name}.jsx` | `webhooks` → `Webhooks.jsx` |\n| **New Top-Level Field (String/Primitive)** | Add to existing layout component or create info component | `components/{field-name}.jsx` | `jsonSchemaDialect` → `JsonSchemaDialect.jsx` |\n| **Modified Info Object** | Wrap Info component OR create OAS{VERSION}Info | `wrap-components/info.jsx` | `info.summary` → Wrapped InfoContainer |\n| **New Info Subfield** | Create new component, render in Info | `components/info-{field}.jsx` | `info.license.identifier` → OAS31License |\n| **Modified License/Contact** | Wrap component | `wrap-components/license.jsx` | `license.identifier` → Wrapped License |\n| **New Authentication Type** | New auth component | `components/auth/{type}.jsx` | `mutualTLS` → `MutualTLSAuth.jsx` |\n| **Modified Security Scheme** | Wrap auth selector | `auth-extensions/wrap-selectors.js` | mutualTLS → `definitionsToAuthorize` wrapper |\n| **New Operation Field** | Extend Operation or create plugin selector | `spec-extensions/selectors.js` | N/A in OAS 3.1 |\n| **New Callback Feature** | Extend Callbacks component or wrap | `wrap-components/callbacks.jsx` | Enhanced in OAS 3.1 |\n| **New Parameter Type** | Extend Parameters component | `components/parameters/` | N/A in OAS 3.1 |\n| **New Response Feature** | Extend Responses component | `components/responses/` | N/A in OAS 3.1 |\n| **New Media Type Feature** | Modify media-type component or fn | `oas{PREV}-extensions/fn.js` | File upload detection changes |\n| **JSON Schema Keyword** | New keyword component | `json-schema-{VERSION}-extensions/components/keywords/` | `example` → `JSONSchema202012KeywordExample.jsx` |\n| **JSON Schema Version Change** | Entire new plugin + samples plugin | `plugins/json-schema-{VERSION}/` | JSON Schema 2020-12 plugin |\n| **Modified Schema Rendering** | Wrap schema component | `wrap-components/model.jsx` | Models → OAS31Models wrapper |\n| **Version Detection Field** | Update VersionPragmaFilter | `components/version-pragma-filter.jsx` | Updated for isOAS31 |\n| **Deprecated Field** | Remove or add deprecation warning | Component showing warning | N/A in OAS 3.1 |\n\n#### 1E. Examples: OAS 3.1 Specification Changes → Components\n\n**Example 1: `webhooks` Top-Level Field**\n\n**From Spec (OAS 3.1):**\n```yaml\nopenapi: 3.1.0\nwebhooks:\n  newPet:\n    post:\n      requestBody:\n        description: Information about a new pet\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/Pet'\n      responses:\n        '200':\n          description: Return a 200 status\n```\n\n**Mapping Decision:**\n- Type: New top-level field (Object containing operations)\n- Location in spec: Root level, same structure as `paths`\n- Swagger UI component: New standalone component\n- File: `src/core/plugins/oas31/components/webhooks.jsx`\n- Rendering: Reuses Operations component to render webhook operations\n- Selector: `selectWebhooks` in `spec-extensions/selectors.js`\n- Layout integration: Added to BaseLayout or StandaloneLayout\n\n**Example 2: `info.summary` Field**\n\n**From Spec (OAS 3.1):**\n```yaml\ninfo:\n  title: My API\n  summary: A brief summary of the API   # NEW in OAS 3.1\n  description: Detailed description...\n  version: 1.0.0\n```\n\n**Mapping Decision:**\n- Type: New subfield in existing Info object\n- Location: `info.summary`\n- Swagger UI component: Wrap existing Info component\n- File: `src/core/plugins/oas31/wrap-components/info.jsx` + `src/core/plugins/oas31/components/info.jsx`\n- Selector: `selectInfoSummary` (if needed)\n- Rendering: Display summary above or below title\n\n**Example 3: `mutualTLS` Authentication Type**\n\n**From Spec (OAS 3.1):**\n```yaml\ncomponents:\n  securitySchemes:\n    myMutualTLS:\n      type: mutualTLS    # NEW in OAS 3.1\n      description: Client certificate authentication\n```\n\n**Mapping Decision:**\n- Type: New authentication scheme type\n- Location: `components.securitySchemes[name].type`\n- Swagger UI component: New auth component\n- File: `src/core/plugins/oas31/components/auth/mutual-tls-auth.jsx`\n- Selector wrapper: `auth-extensions/wrap-selectors.js` → `definitionsToAuthorize`\n- Rendering: Display in authorize modal with certificate upload UI\n\n**Example 4: `license.identifier` Field**\n\n**From Spec (OAS 3.1):**\n```yaml\ninfo:\n  license:\n    name: Apache 2.0\n    identifier: Apache-2.0    # NEW in OAS 3.1 (SPDX ID)\n    url: https://www.apache.org/licenses/LICENSE-2.0.html\n```\n\n**Mapping Decision:**\n- Type: New optional field in license object (alternative to url)\n- Location: `info.license.identifier`\n- Swagger UI component: Wrap License component + create selector\n- File: `src/core/plugins/oas31/wrap-components/license.jsx` + selector in `spec-extensions/selectors.js`\n- Logic: If `identifier` exists, construct URL from SPDX registry\n- Rendering: Make license text a hyperlink to SPDX page\n\n**Example 5: JSON Schema 2020-12 Keywords**\n\n**From Spec (OAS 3.1):**\n```yaml\n# OAS 3.1 uses JSON Schema 2020-12 which includes:\ncomponents:\n  schemas:\n    Pet:\n      type: object\n      properties:\n        name:\n          type: string\n          example: Fluffy        # Changed from 'examples' array in OAS 3.0\n      xml:                       # Now a JSON Schema keyword, not OAS-specific\n        name: pet\n      externalDocs:              # Now a JSON Schema keyword\n        url: https://example.com\n      discriminator:             # Now a JSON Schema keyword\n        propertyName: petType\n```\n\n**Mapping Decision:**\n- Type: JSON Schema version upgrade (Draft 7 → 2020-12)\n- Location: Schema objects throughout spec\n- Swagger UI components: Entire new plugin\n- Files:\n  - `src/core/plugins/json-schema-2020-12/` (main plugin)\n  - `src/core/plugins/json-schema-2020-12-samples/` (sample generation)\n  - `src/core/plugins/json-schema-2020-12/components/keywords/example.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/xml.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/discriminator.jsx`\n  - `src/core/plugins/json-schema-2020-12/components/keywords/external-docs.jsx`\n- Integration: OAS31 plugin extends JSON Schema 2020-12 keywords in `json-schema-2020-12-extensions/`\n\n**Example 6: `jsonSchemaDialect` Top-Level Field**\n\n**From Spec (OAS 3.1):**\n```yaml\nopenapi: 3.1.0\njsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/base  # NEW in OAS 3.1\n```\n\n**Mapping Decision:**\n- Type: New top-level field (String/URI)\n- Location: Root level\n- Swagger UI component: Simple display component\n- File: `src/core/plugins/oas31/components/json-schema-dialect.jsx`\n- Selector: `selectJsonSchemaDialectField` in `spec-extensions/selectors.js`\n- Rendering: Show in info section with warning if non-default\n\n#### 1F. Specification Analysis Checklist\n\nUse WebFetch and Read tools to systematically check:\n\n- [ ] **Accessed official spec at https://spec.openapis.org/**\n- [ ] **Downloaded specification document**\n- [ ] **Read version number section**\n- [ ] **Analyzed OpenAPI Object (root level) changes**\n- [ ] **Reviewed Info Object modifications**\n- [ ] **Checked Paths/Operations changes**\n- [ ] **Examined Components Object updates**\n- [ ] **Identified Security Scheme changes**\n- [ ] **Analyzed Schema Object / JSON Schema version**\n- [ ] **Listed all new top-level fields**\n- [ ] **Listed all modified existing fields**\n- [ ] **Documented breaking changes**\n- [ ] **Identified deprecated features**\n- [ ] **Found example specifications**\n- [ ] **Created specification change document**\n- [ ] **Mapped changes to Swagger UI components using table above**\n- [ ] **Prioritized implementation order**\n\n#### 1G. Questions to Answer During Analysis\n\n**Version Type:**\n- Is this a major version (4.0) or minor version (3.2)?\n- Are there breaking changes?\n- Is backward compatibility maintained?\n\n**JSON Schema:**\n- Does it use a new JSON Schema version?\n- What new keywords are available?\n- Are there removed/deprecated keywords?\n\n**Top-Level Changes:**\n- What new top-level fields are added?\n- Which existing fields have new subfields?\n- Any removed top-level fields?\n\n**Operation Changes:**\n- Are there new operation-level features?\n- Changes to parameters, request bodies, responses?\n- New callback or link syntax?\n\n**Security Changes:**\n- What authentication types are new/changed?\n- OAuth2 flow modifications?\n- New security requirements?\n\n**Media Type Changes:**\n- Are there new media type features?\n- File upload handling changes?\n- Encoding changes?\n\n**Component Mapping:**\n- Which components need to be created from scratch?\n- Which existing components need to be wrapped?\n- What selectors are required?\n- Are new plugins needed (e.g., for JSON Schema)?\n\n**Implementation Priority:**\n- What's the critical path for basic rendering?\n- Which features can be added incrementally?\n- What has the highest user impact?\n\n### Step 1H: Using WebFetch to Analyze Specifications\n\n**Always use WebFetch tool to retrieve and analyze the specification systematically.**\n\n**Step-by-step WebFetch workflow:**\n\n1. **Fetch the specification landing page:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Provide a summary of this OpenAPI Specification version, including links to the full specification document and any change logs or migration guides.\"\n)\n```\n\n2. **Analyze the specification structure:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all top-level fields in the OpenAPI Object for this version. For each field, indicate if it is new, modified, or unchanged from version {PREVIOUS_VERSION}.\"\n)\n```\n\n3. **Deep dive into new features:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Describe the '{NEW_FIELD}' field in detail: its type, structure, purpose, whether it's required, and provide examples from the specification.\"\n)\n```\n\n4. **Analyze security changes:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"List all security scheme types supported in this version. Highlight any new or changed security scheme types compared to {PREVIOUS_VERSION}.\"\n)\n```\n\n5. **Check JSON Schema compatibility:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"What version of JSON Schema does this OpenAPI Specification version use? List any specific dialect or modifications to JSON Schema.\"\n)\n```\n\n6. **Find example specifications:**\n```javascript\nWebFetch(\n  \"https://spec.openapis.org/oas/v{VERSION}/\",\n  \"Provide links to example OpenAPI specification files for this version, particularly examples that demonstrate new features.\"\n)\n```\n\n**Real example from analyzing OAS 3.1:**\n\n```javascript\n// 1. Initial analysis\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"List all new fields and features introduced in OpenAPI 3.1.0 compared to OpenAPI 3.0.3\"\n)\n\n// Response would include:\n// - webhooks field (new top-level)\n// - info.summary (new)\n// - info.license.identifier (new)\n// - jsonSchemaDialect (new top-level)\n// - mutualTLS security scheme type (new)\n// - JSON Schema 2020-12 (changed from Draft 7)\n\n// 2. Deep dive into webhooks\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"Explain the 'webhooks' field in detail: structure, purpose, and provide a complete example\"\n)\n\n// 3. Understand JSON Schema changes\nWebFetch(\n  \"https://spec.openapis.org/oas/v3.1.0/\",\n  \"What are the differences between JSON Schema Draft 7 (used in OAS 3.0) and JSON Schema 2020-12 (used in OAS 3.1) that affect schema definitions?\"\n)\n```\n\n**Pro tip:** Use multiple targeted queries rather than one broad query. This gives more precise information for each component you need to implement.\n\n### Step 2: Create Plugin Directory Structure\n\n**Directory:** `src/core/plugins/oas{VERSION_NUMBER}/`\n\n**Files to Create:**\n```\nsrc/core/plugins/oas{VERSION_NUMBER}/\n├── index.js                          # Main plugin export\n├── fn.js                             # Selector/function factories\n├── selectors.js                      # Version-specific selectors (if needed)\n├── after-load.js                     # Lifecycle hook\n├── auth-extensions/                  # Authentication features\n│   └── wrap-selectors.js\n├── oas{PREVIOUS_VERSION}-extensions/ # Extensions to previous version\n│   └── fn.js\n├── spec-extensions/                  # Spec-level features\n│   ├── selectors.js\n│   └── wrap-selectors.js\n├── components/                       # New components\n│   ├── version-pragma-filter.jsx\n│   ├── {new-feature-1}.jsx\n│   └── auth/\n│       └── {new-auth-type}.jsx\n├── wrap-components/                  # Component wrappers\n│   ├── info.jsx\n│   ├── license.jsx\n│   └── {existing-component}.jsx\n└── json-schema-{VERSION}-extensions/ # If new JSON Schema version\n    ├── fn.js\n    ├── components/keywords/\n    └── wrap-components/keywords/\n```\n\n**Create the directories:**\n```bash\nmkdir -p src/core/plugins/oas{VERSION_NUMBER}/{auth-extensions,oas{PREVIOUS_VERSION}-extensions,spec-extensions,components/auth,wrap-components}\n```\n\n### Step 3: Implement Version Detection (fn.js)\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/fn.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\n/**\n * Detects if a spec is OpenAPI {MAJOR}.{MINOR}.x\n */\nexport const isOAS{VERSION} = (jsSpec) => {\n  const oasVersion = jsSpec.get(\"openapi\")\n  return (\n    typeof oasVersion === \"string\" &&\n    /^{MAJOR}\\.{MINOR}\\.(?:[1-9]\\d*|0)$/.test(oasVersion)\n  )\n}\n\n/**\n * Creates a selector that only returns a value for OAS {VERSION} specs\n */\nexport const createOnlyOAS{VERSION}Selector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(system)\n        : selectedValue\n    } else {\n      return null\n    }\n  }\n\n/**\n * Creates a selector wrapper that uses new impl for OAS {VERSION}, falls back to original\n */\nexport const createOnlyOAS{VERSION}SelectorWrapper =\n  (selector) =>\n  (oriSelector, system) =>\n  (state, ...args) => {\n    if (system.getSystem().specSelectors.isOAS{VERSION}()) {\n      const selectedValue = selector(state, ...args)\n      return typeof selectedValue === \"function\"\n        ? selectedValue(oriSelector, system)\n        : selectedValue\n    } else {\n      return oriSelector(...args)\n    }\n  }\n\n/**\n * Creates a system-aware selector\n */\nexport const createSystemSelector =\n  (selector) =>\n  (state, ...args) =>\n  (system) => {\n    const selectedValue = selector(state, system, ...args)\n    return typeof selectedValue === \"function\"\n      ? selectedValue(system)\n      : selectedValue\n  }\n\n/**\n * Creates a component wrapper that only renders for OAS {VERSION}.\n * When active, passes `originalComponent` (the unwrapped original) and\n * `getSystem` as extra props. Access the original via:\n *   const { originalComponent: Ori } = props\n * NOT via `props.Ori` — that's the OAS3/OAS30ComponentWrapFactory convention.\n */\nexport const createOnlyOAS{VERSION}ComponentWrapper =\n  (Component) => (Original, system) => (props) => {\n    if (system.specSelectors.isOAS{VERSION}()) {\n      return (\n        <Component\n          {...props}\n          originalComponent={Original}\n          getSystem={system.getSystem}\n        />\n      )\n    }\n\n    return <Original {...props} />\n  }\n\n/**\n * Wraps functions to conditionally use OAS {VERSION} implementations\n */\nexport const wrapOAS{VERSION}Fn = (fn, system) => {\n  const { fn: systemFn, specSelectors } = system\n  return Object.fromEntries(\n    Object.entries(fn).map(([name, newImpl]) => {\n      const oriImpl = systemFn[name]\n      const impl = (...args) =>\n        specSelectors.isOAS{VERSION}()\n          ? newImpl(...args)\n          : typeof oriImpl === \"function\"\n            ? oriImpl(...args)\n            : undefined\n      return [name, impl]\n    })\n  )\n}\n```\n\n### Step 4: Create Main Plugin Export (index.js)\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/index.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport afterLoad from \"./after-load.js\"\nimport {\n  isOAS{VERSION},\n  createSystemSelector,\n  createOnlyOAS{VERSION}Selector,\n  createOnlyOAS{VERSION}SelectorWrapper,\n  createOnlyOAS{VERSION}ComponentWrapper,\n} from \"./fn.js\"\n\n// Import spec extensions\nimport * as specExtensionsSelectors from \"./spec-extensions/selectors.js\"\nimport * as specExtensionsWrapSelectors from \"./spec-extensions/wrap-selectors.js\"\n\n// Import auth extensions\nimport * as authExtensionsWrapSelectors from \"./auth-extensions/wrap-selectors.js\"\n\n// Import OAS{PREVIOUS_VERSION} extensions\nimport * as oas{PREVIOUS_VERSION}ExtensionsFn from \"./oas{PREVIOUS_VERSION}-extensions/fn.js\"\n\n// Import components\nimport VersionPragmaFilter from \"./components/version-pragma-filter.jsx\"\n// Import new feature components here\n\n// Import wrap components\nimport InfoWrapper from \"./wrap-components/info.jsx\"\n// Import other wrappers here\n\n/**\n * OpenAPI {MAJOR}.{MINOR} Plugin\n *\n * Adds support for OpenAPI Specification {MAJOR}.{MINOR}.x\n *\n * This plugin should be loaded AFTER:\n * - oas{PREVIOUS_VERSION} plugin\n * - json-schema-{JSON_SCHEMA_VERSION} plugin (if applicable)\n *\n * It wraps and overrides components/selectors from previous versions.\n */\nconst OpenAPI{VERSION}Plugin = ({ fn }) => {\n  return {\n    fn: {\n      oas{VERSION_NUMBER}: {\n        isOAS{VERSION},\n        createSystemSelector,\n        createOnlyOAS{VERSION}Selector,\n        createOnlyOAS{VERSION}SelectorWrapper,\n        createOnlyOAS{VERSION}ComponentWrapper,\n      },\n    },\n    components: {\n      // New components\n      OAS{VERSION}VersionPragmaFilter: VersionPragmaFilter,\n      // Add new feature components here\n    },\n    wrapComponents: {\n      // Wrapped components\n      VersionPragmaFilter: (Ori, system) =>\n        system.specSelectors.isOAS{VERSION}()\n          ? system.getComponent(\"OAS{VERSION}VersionPragmaFilter\", true)\n          : Ori,\n      InfoContainer: InfoWrapper,\n      // Add other wrappers here\n    },\n    statePlugins: {\n      spec: {\n        selectors: {\n          // Add version detection selector\n          isOAS{VERSION}: createSystemSelector(specExtensionsSelectors.selectIsOAS{VERSION}),\n          // Add new feature selectors here\n        },\n        wrapSelectors: {\n          // Wrap previous version selectors if needed\n          ...specExtensionsWrapSelectors,\n        },\n      },\n      auth: {\n        wrapSelectors: {\n          // Add auth extensions if needed\n          ...authExtensionsWrapSelectors,\n        },\n      },\n      oas{VERSION_NUMBER}: {\n        selectors: {\n          // Plugin-specific selectors\n        },\n      },\n    },\n    afterLoad,\n  }\n}\n\nexport default OpenAPI{VERSION}Plugin\n```\n\n### Step 5: Implement Spec Extensions\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/selectors.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createSelector } from \"reselect\"\nimport { isOAS{VERSION} } from \"../fn.js\"\n\n/**\n * Detects if the current spec is OAS {VERSION}\n */\nexport const selectIsOAS{VERSION} = (state, system) => () => {\n  const spec = system.specSelectors.specJson()\n  return isOAS{VERSION}(spec)\n}\n\n// Add selectors for new OAS {VERSION} fields here\n// Example:\n// export const selectNewField = createSelector(\n//   (state) => state,\n//   (state) => {\n//     const spec = state.getIn([\"spec\", \"json\"])\n//     return spec.get(\"newField\")\n//   }\n// )\n```\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/spec-extensions/wrap-selectors.js`\n\n**⚠️ Minor version: DON'T wrap `isOAS{PREV}` unless the regex actually matches both versions.** For example, OAS 3.1's `isOAS31` regex (`/^3\\.1\\./`) will never match `3.2.x`, so wrapping it to return `false` is dead code. Only add the `isOAS{PREV}` override if the previous version's detection regex would incorrectly match the new version.\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createOnlyOAS{VERSION}SelectorWrapper } from \"../fn.js\"\n\n// Ensure OAS {VERSION} specs are recognized as OAS 3.x (needed when major version number didn't change)\nexport const isOAS3 =\n  (oriSelector, system) =>\n  (state, ...args) => {\n    const isOAS{VERSION} = system.specSelectors.isOAS{VERSION}()\n    return isOAS{VERSION} || oriSelector(...args)\n  }\n\n// ONLY add isOAS{PREV} wrapper if the previous version's regex could match this new version.\n// For a minor version bump (e.g. 3.1 → 3.2), the previous regex won't match, so DON'T add this.\n// export const isOAS{PREV} = createOnlyOAS{VERSION}SelectorWrapper((state) => () => false)\n```\n\n### Step 6: Create Version Pragma Filter Component\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst OAS{VERSION}VersionPragmaFilter = ({ bypass, isSwagger2, isOAS3, isOAS{PREVIOUS_VERSION}, isOAS{VERSION} }) => {\n  // Handle version detection logic\n  const isAmbiguous =\n    (isSwagger2 && isOAS3) ||\n    (isSwagger2 && isOAS{PREVIOUS_VERSION}) ||\n    (isSwagger2 && isOAS{VERSION}) ||\n    (isOAS3 && isOAS{PREVIOUS_VERSION}) ||\n    (isOAS3 && isOAS{VERSION}) ||\n    (isOAS{PREVIOUS_VERSION} && isOAS{VERSION})\n\n  const isMissing = !isSwagger2 && !isOAS3 && !isOAS{PREVIOUS_VERSION} && !isOAS{VERSION}\n\n  if (bypass) {\n    return null\n  }\n\n  if (isAmbiguous) {\n    return (\n      <div className=\"version-pragma\">\n        <div className=\"version-pragma__message version-pragma__message--ambiguous\">\n          <div>\n            <h3>Unable to render this document, as it contains multiple OpenAPI version fields.</h3>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  if (isMissing) {\n    return (\n      <div className=\"version-pragma\">\n        <div className=\"version-pragma__message version-pragma__message--missing\">\n          <div>\n            <h3>Unable to render this document, as it doesn&apos;t contain an OpenAPI version field.</h3>\n          </div>\n        </div>\n      </div>\n    )\n  }\n\n  return null\n}\n\nOAS{VERSION}VersionPragmaFilter.propTypes = {\n  bypass: PropTypes.bool,\n  isSwagger2: PropTypes.bool.isRequired,\n  isOAS3: PropTypes.bool.isRequired,\n  isOAS{PREVIOUS_VERSION}: PropTypes.bool.isRequired,\n  isOAS{VERSION}: PropTypes.bool.isRequired,\n}\n\nOAS{VERSION}VersionPragmaFilter.defaultProps = {\n  bypass: false,\n}\n\nexport default OAS{VERSION}VersionPragmaFilter\n```\n\n### Step 7: Implement New Feature Components\n\nFor each new feature in the OAS specification:\n\n**Example: New Feature Component**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst NewFeature = ({ getComponent, specSelectors }) => {\n  const newFeature = specSelectors.selectNewFeature()\n\n  if (!newFeature || !newFeature.size) {\n    return null\n  }\n\n  // Render the new feature\n  return (\n    <div className=\"opblock-tag-section\">\n      <h3>New Feature</h3>\n      {/* Render logic here */}\n    </div>\n  )\n}\n\nNewFeature.propTypes = {\n  specSelectors: PropTypes.object.isRequired,\n  getComponent: PropTypes.func.isRequired,\n}\n\nexport default NewFeature\n```\n\n### Step 8: Create Component Wrappers\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/wrap-components/info.jsx`\n\n**⚠️ Minor version (e.g. 3.2): don't create a new Info component.** If the Info object is identical to the previous version, reuse `OAS{PREV_VERSION}Info` via `getComponent` instead of copying the whole component. Only create a new Info component for major versions with significant structural changes.\n\n**Template (minor version — reuse previous Info):**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport { createOnlyOAS{VERSION}ComponentWrapper } from \"../fn.js\"\n\nconst InfoWrapper = createOnlyOAS{VERSION}ComponentWrapper(({ getSystem }) => {\n  const system = getSystem()\n  const OAS{PREV_VERSION}Info = system.getComponent(\"OAS{PREV_VERSION}Info\", true)\n  return <OAS{PREV_VERSION}Info />\n})\n\nexport default InfoWrapper\n```\n\n**Also — OpenAPIVersion wrapper (minor version — change version badge only):**\n\nFor minor versions where the only Info difference is the version badge, use the OpenAPIVersion wrapper pattern instead of wrapping InfoContainer at all:\n\n```javascript\n// wrap-components/openapi-version.jsx\n/**\n * @prettier\n */\nimport React from \"react\"\nimport { createOnlyOAS{VERSION}ComponentWrapper } from \"../fn.js\"\n\nexport default createOnlyOAS{VERSION}ComponentWrapper((props) => {\n  const { originalComponent: Ori } = props  // NOT `Ori` from props directly — use `originalComponent`\n  return <Ori oasVersion=\"{MAJOR}.{MINOR}\" />\n})\n```\n\nThen register it in index.js:\n```javascript\nwrapComponents: {\n  OpenAPIVersion: OpenAPIVersionWrapper,  // changes the version badge shown in the Info header\n}\n```\n\n### Step 9: Implement afterLoad Hook\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/after-load.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { wrapOAS{VERSION}Fn } from \"./fn.js\"\n\n/**\n * afterLoad hook for OAS {VERSION} plugin\n *\n * This hook runs after all plugins are loaded and allows\n * modification of the system's functions and behaviors.\n */\nfunction afterLoad({ fn, getSystem }) {\n  const system = getSystem()\n\n  // Override functions that differ in OAS {VERSION}\n  if (typeof fn.sampleFromSchema === \"function\") {\n    // Example: Wrap sample generation if JSON Schema version changed\n    // const wrappedFns = wrapOAS{VERSION}Fn({\n    //   sampleFromSchema: fn.jsonSchema{VERSION}.sampleFromSchema,\n    // }, system)\n    // Object.assign(this.fn, wrappedFns)\n  }\n\n  // Override other functions as needed\n  // Example: File upload detection\n  // if (typeof fn.isFileUploadIntended === \"function\") {\n  //   const wrappedFns = wrapOAS{VERSION}Fn({\n  //     isFileUploadIntended: makeIsFileUploadIntended(system),\n  //   }, system)\n  //   Object.assign(this.fn, wrappedFns)\n  // }\n}\n\nexport default afterLoad\n```\n\n### Step 10: Handle Authentication Changes\n\nIf new authentication types are introduced:\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/components/auth/{auth-type}.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport PropTypes from \"prop-types\"\n\nconst NewAuthType = ({ schema, name, getComponent, onChange, authorized }) => {\n  const authValue = authorized && authorized.getIn([name])\n\n  const Input = getComponent(\"Input\")\n  const Button = getComponent(\"Button\")\n\n  // Render auth UI\n  return (\n    <div>\n      <h4>{schema.get(\"description\") || `${name} (${schema.get(\"type\")})`}</h4>\n      {/* Auth UI here */}\n    </div>\n  )\n}\n\nNewAuthType.propTypes = {\n  schema: PropTypes.object.isRequired,\n  name: PropTypes.string.isRequired,\n  getComponent: PropTypes.func.isRequired,\n  onChange: PropTypes.func.isRequired,\n  authorized: PropTypes.object,\n}\n\nexport default NewAuthType\n```\n\n**File:** `src/core/plugins/oas{VERSION_NUMBER}/auth-extensions/wrap-selectors.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { createOnlyOAS{VERSION}SelectorWrapper } from \"../fn.js\"\nimport { Map } from \"immutable\"\n\n/**\n * Wraps definitionsToAuthorize to include new auth types\n */\nexport const definitionsToAuthorize = createOnlyOAS{VERSION}SelectorWrapper(\n  (state, system) =>\n    (oriSelector) => {\n      const definitions = oriSelector()\n      const securityDefinitions = system.specSelectors.securityDefinitions() || Map()\n\n      // Add new auth types to definitions\n      return definitions.map((definition) => {\n        const schema = securityDefinitions.get(definition.get(\"name\"))\n        if (schema && schema.get(\"type\") === \"newAuthType\") {\n          // Add new auth type logic\n          return definition.set(\"newAuthType\", true)\n        }\n        return definition\n      })\n    }\n)\n```\n\n### Step 11: Register Plugin in Preset\n\n**File:** `src/core/presets/apis/index.js`\n\n**Add import:**\n```javascript\nimport OpenAPI{VERSION}Plugin from \"../../plugins/oas{VERSION_NUMBER}/index.js\"\n```\n\n**Add to preset array (IMPORTANT: add at the end):**\n```javascript\nexport default function PresetApis() {\n  return [\n    BasePreset,\n    OpenAPI30Plugin,\n    // ... other plugins\n    OpenAPI{PREVIOUS_VERSION}Plugin,\n    OpenAPI{VERSION}Plugin,  // Load LAST to override previous versions\n  ]\n}\n```\n\n**Why load last?**\n- Wrap-components override previous versions\n- Wrap-selectors intercept earlier selectors\n- afterLoad modifications apply to dependencies\n\n### Step 12: Add Unit Tests\n\n**Directory:** `test/unit/core/plugins/oas{VERSION_NUMBER}/`\n\n**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/fn.js`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport { fromJS } from \"immutable\"\nimport { isOAS{VERSION} } from \"src/core/plugins/oas{VERSION_NUMBER}/fn.js\"\n\ndescribe(\"oas{VERSION_NUMBER} plugin - fn - isOAS{VERSION}\", () => {\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.0\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.1\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.1\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should match OpenAPI {MAJOR}.{MINOR}.25\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.25\" })\n    expect(isOAS{VERSION}(spec)).toBe(true)\n  })\n\n  it(\"should NOT match OpenAPI {MAJOR}.{MINOR}\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match OpenAPI {MAJOR}.{MINOR}.01 (leading zero)\", () => {\n    const spec = fromJS({ openapi: \"{MAJOR}.{MINOR}.01\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match OpenAPI {DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0\", () => {\n    const spec = fromJS({ openapi: \"{DIFFERENT_MAJOR}.{DIFFERENT_MINOR}.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should NOT match swagger: 2.0\", () => {\n    const spec = fromJS({ swagger: \"2.0\" })\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n\n  it(\"should handle null spec\", () => {\n    const spec = fromJS({})\n    expect(isOAS{VERSION}(spec)).toBe(false)\n  })\n})\n```\n\n**File:** `test/unit/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx`\n\n**Template:**\n```javascript\n/**\n * @prettier\n */\n\nimport React from \"react\"\nimport { shallow } from \"enzyme\"\nimport OAS{VERSION}VersionPragmaFilter from \"src/core/plugins/oas{VERSION_NUMBER}/components/version-pragma-filter.jsx\"\n\ndescribe(\"OAS{VERSION}VersionPragmaFilter\", () => {\n  it(\"should render nothing when bypass is true\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={true}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.type()).toBe(null)\n  })\n\n  it(\"should render nothing when version is valid\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.type()).toBe(null)\n  })\n\n  it(\"should render error when version is ambiguous\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={true}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={true}\n      />\n    )\n    expect(wrapper.find(\".version-pragma__message--ambiguous\")).toHaveLength(1)\n  })\n\n  it(\"should render error when version is missing\", () => {\n    const wrapper = shallow(\n      <OAS{VERSION}VersionPragmaFilter\n        bypass={false}\n        isSwagger2={false}\n        isOAS3={false}\n        isOAS{PREVIOUS_VERSION}={false}\n        isOAS{VERSION}={false}\n      />\n    )\n    expect(wrapper.find(\".version-pragma__message--missing\")).toHaveLength(1)\n  })\n})\n```\n\n### Step 13: Add E2E Tests\n\n**Directory:** `test/e2e-cypress/e2e/features/oas{VERSION_NUMBER}/`\n\n**Create test spec file:**\n```javascript\n/**\n * @prettier\n */\n\ndescribe(\"OpenAPI {MAJOR}.{MINOR} features\", () => {\n  it(\"should detect OAS {VERSION} version\", () => {\n    cy.visit(\"/oas{VERSION_NUMBER}-spec.html\")\n    cy.get(\".information-container .version\").should(\"contain\", \"{MAJOR}.{MINOR}.0\")\n  })\n\n  // Add tests for new features\n  it(\"should render new feature X\", () => {\n    cy.visit(\"/oas{VERSION_NUMBER}-spec.html\")\n    cy.get(\".opblock-tag-section\").should(\"contain\", \"New Feature\")\n  })\n})\n```\n\n**Add test fixtures:**\n- Create sample OAS {VERSION} spec in `test/e2e-cypress/static/documents/oas{VERSION_NUMBER}/`\n- Create HTML fixture in `test/e2e-cypress/static/` referencing the spec\n\n### Step 14: Update Documentation\n\n**Files to update:**\n\n1. **README.md** - Add OAS {VERSION} to supported versions\n2. **CLAUDE.md** - Add plugin to list and update version compatibility\n3. **docs/usage/version-detection.md** - Document new version detection\n4. **package.json** - Update description if needed\n\n**Example README.md update:**\n```markdown\n### OpenAPI Specification Compatibility\n\n- **OpenAPI 2.0** (Swagger)\n- **OpenAPI 3.0.x**\n- **OpenAPI 3.1.x**\n- **OpenAPI {MAJOR}.{MINOR}.x** ⭐ NEW\n```\n\n### Step 15: Verify Build\n\n**Run full build:**\n```bash\nnpm run clean\nnpm run build\n```\n\n**Check dist/ output:**\n- `dist/swagger-ui.js` - Should include new plugin\n- `dist/swagger-ui.css` - Should include new styles (if any)\n- Bundle size should be reasonable\n\n**Run artifact tests:**\n```bash\nnpm run test:artifact\n```\n\n### Step 16: Run Full Test Suite\n\n```bash\nnpm run lint-errors      # ESLint errors only\nnpm run test:unit        # Jest unit tests\nnpm run cy:ci            # Cypress E2E tests\n```\n\n**All tests must pass before submitting PR.**\n\n### Step 17: Create Pull Request\n\n**Commit message format:**\n```\nfeat(oas{VERSION_NUMBER}): add support for OpenAPI {MAJOR}.{MINOR}\n\nImplement OpenAPI {MAJOR}.{MINOR}.x specification support with:\n- Version detection and plugin architecture\n- New feature X rendering\n- New authentication type Y support\n- JSON Schema {VERSION} integration (if applicable)\n\nCloses #{ISSUE_NUMBER}\n```\n\n**PR checklist:**\n- [ ] All tests passing\n- [ ] New feature components implemented\n- [ ] Unit tests added\n- [ ] E2E tests added\n- [ ] Documentation updated\n- [ ] Build completes successfully\n- [ ] No ESLint errors\n- [ ] Follows existing code patterns\n\n## Common Pitfalls\n\n<!-- File: .claude/skills/README.md (Tokens: ~1066 | Category: anthropic-skill) -->\n# Swagger UI Claude Skills\n\nThis directory contains custom skills for working with the Swagger UI codebase in Claude Code.\n\n## Available Skills\n\n### `/add-oas-support` - Add OpenAPI Specification Version Support\n\nComprehensive skill for adding support for a new OpenAPI Specification version to Swagger UI.\n\n**Usage:**\n```\n/add-oas-support --version 4.0 --type major\n/add-oas-support --version 3.2 --type minor\n```\n\n**Parameters:**\n- `--version` (required): The OpenAPI version to add support for (e.g., \"3.2\", \"4.0\")\n- `--type` (optional): Version type - \"major\" or \"minor\" (default: \"minor\")\n\n**Structure:**\nThe skill includes both a **Quick Reference** section at the top for experienced developers, and a **comprehensive guide** below for detailed implementation instructions.\n\n**What it does:**\n1. **Analyzes the target OAS version specification using WebFetch**\n   - Fetches official spec from https://spec.openapis.org/\n   - Systematically identifies new/modified/removed fields\n   - Maps specification changes to Swagger UI components\n   - Creates specification change document\n2. Creates the plugin directory structure\n3. Implements version detection logic\n4. Creates selector factories and component wrappers\n5. Implements new feature components based on spec analysis\n6. Handles authentication changes\n7. Registers plugin in presets\n8. Adds unit and E2E tests\n9. Updates documentation\n10. Runs full test suite\n\n**Key Features:**\n- ✅ **Quick Reference** section for rapid development\n- ✅ Comprehensive specification analysis workflow using WebFetch\n- ✅ Detailed mapping table from spec changes → components (15+ change types)\n- ✅ Real examples from OAS 3.1 implementation (6 detailed examples)\n- ✅ Iterative spec-driven development approach\n- ✅ Component-by-component verification checklist\n- ✅ Best practices for continuous spec reference\n- ✅ WebFetch query templates for spec analysis\n- ✅ Common pitfalls and solutions\n- ✅ Pre-submit checklist\n\n**Based on:**\nThis skill follows the patterns established by the OAS 3.1 implementation (commit history analyzed from `src/core/plugins/oas31/`).\n\n**Key patterns:**\n- Plugin-based architecture with Redux state management\n- Selector factories for version-specific logic\n- Component wrapping for conditional rendering\n- afterLoad lifecycle hooks for function overrides\n- Plugin loading order (new version loaded LAST)\n\n**Prerequisites:**\n- Understanding of Swagger UI plugin architecture\n- Access to the new OAS specification document\n- All existing tests passing\n\n**Example workflow:**\n\nAdding OAS 4.0 support:\n```\n# Start the skill\n/add-oas-support --version 4.0 --type major\n\n# Claude will:\n# 1. Ask about new features in OAS 4.0\n# 2. Create plugin directory structure\n# 3. Generate boilerplate code\n# 4. Guide through implementation\n# 5. Add tests\n# 6. Update documentation\n# 7. Verify build\n```\n\n## Creating New Skills\n\nTo create a new skill for Swagger UI:\n\n1. Create a markdown file in `.claude/skills/`\n2. Add frontmatter with skill metadata:\n   ```yaml\n   ---\n   name: skill-name\n   description: Brief description\n   args:\n     param1:\n       description: \"Parameter description\"\n       required: true\n       type: string\n   ---\n   ```\n3. Write comprehensive instructions following the patterns in existing skills\n4. Document common pitfalls and best practices\n5. Include code templates with placeholders\n6. Add to this README\n\n## Skill Development Guidelines\n\nWhen creating skills for Swagger UI:\n\n1. **Follow project conventions:**\n   - No semicolons\n   - Double quotes\n   - @prettier pragma in all new files\n   - .jsx extension for React components\n\n2. **Use the plugin architecture:**\n   - Don't modify core unnecessarily\n   - Follow established patterns\n   - Load new plugins at the end of presets\n\n3. **Include comprehensive tests:**\n   - Unit tests for logic\n   - Component tests for UI\n   - E2E tests for integration\n\n4. **Document thoroughly:**\n   - Update CLAUDE.md\n   - Update relevant docs\n   - Add inline JSDoc comments\n\n5. **Security first:**\n   - Use DOMPurify for HTML\n   - Validate all input\n   - Follow OWASP guidelines\n\n## Contributing\n\nTo contribute new skills:\n\n1. Fork the repository\n2. Create skill in `.claude/skills/`\n3. Test thoroughly\n4. Update this README\n5. Submit pull request\n\n## Resources\n\n- **CLAUDE.md** - Comprehensive codebase guide\n- **Plugin API** - `docs/customization/plugin-api.md`\n- **Development Setup** - `docs/development/setting-up.md`\n- **Contributing Guide** - https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md\n\n<!-- File: CLAUDE.md (Tokens: ~7668 | Category: claude-rule) -->\n# CLAUDE.md - Swagger UI Codebase Guide\n\n> **Last Updated:** 2026-02-24\n> **Version:** 5.32.0 (in development)\n> **Purpose:** Comprehensive guide for AI assistants working with the Swagger UI codebase\n\n---\n\n## Table of Contents\n\n1. [Repository Overview](#repository-overview)\n2. [Project Architecture](#project-architecture)\n3. [Development Setup](#development-setup)\n4. [Build System](#build-system)\n5. [Testing Infrastructure](#testing-infrastructure)\n6. [Code Style & Conventions](#code-style--conventions)\n7. [Git Workflow](#git-workflow)\n8. [Plugin Architecture](#plugin-architecture)\n9. [Key Files & Directories](#key-files--directories)\n10. [Common Workflows](#common-workflows)\n11. [Important Guidelines](#important-guidelines)\n\n---\n\n## Repository Overview\n\n### What is Swagger UI?\n\nSwagger UI is a tool that allows developers to visualize and interact with API resources without having implementation logic in place. It's automatically generated from OpenAPI (formerly Swagger) Specification documents.\n\n### Multi-Package Monorepo Structure\n\nThis repository publishes **three different npm packages**:\n\n1. **swagger-ui** (main package)\n   - Traditional npm module for single-page applications\n   - Entry: `dist/swagger-ui.js`\n   - ES Module: `dist/swagger-ui-es-bundle-core.js`\n   - Includes dependency resolution via Webpack/Browserify\n\n2. **swagger-ui-dist** (distribution package)\n   - Dependency-free module for server-side projects\n   - Published separately via GitHub workflow\n   - Template location: `swagger-ui-dist-package/`\n\n3. **swagger-ui-react** (React component)\n   - React wrapper component\n   - Location: `flavors/swagger-ui-react/`\n   - Uses React hooks\n   - Released separately via GitHub workflow\n\n### OpenAPI Specification Compatibility\n\n- **Current Support:** OpenAPI 2.0, 3.0.x, 3.1.x\n- **Latest Version:** v5.31.0 (supports up to OpenAPI 3.1.2)\n\n### License\n\nApache 2.0 - See LICENSE and NOTICE files for details.\n\n---\n\n## Project Architecture\n\n### Technology Stack\n\n**Core Framework:**\n- React 18 (>=16.8.0 <20) - UI components\n- Redux 5.0.1 - State management\n- Redux Immutable 4.0.0 - Immutable state\n- Immutable.js 3.x - Immutable data structures\n- React Redux 9.2.0 - React-Redux bindings\n\n**API & Schema Processing:**\n- swagger-client 3.36.0 - OpenAPI client\n- js-yaml 4.1.1 - YAML parsing\n- remarkable 2.0.1 - Markdown rendering\n\n**Security:**\n- DOMPurify 3.2.6 - HTML sanitization (CRITICAL for XSS prevention)\n- serialize-error 8.1.0 - Error serialization\n\n**Build Tools:**\n- Webpack 5.97.1 - Module bundling\n- Babel 7.26.x - JavaScript transpilation\n- sass-embedded 1.86.0 - SCSS compilation\n- PostCSS - CSS processing\n\n**Testing:**\n- Jest 29.7.0 - Unit testing\n- Cypress 14.2.0 - E2E testing\n- Enzyme 3.11.0 - React component testing\n\n**Development:**\n- ESLint 8.57.0 - JavaScript linting\n- Prettier 3.5.3 - Code formatting\n- Stylelint 16.19.1 - CSS linting\n- Husky 9.1.7 - Git hooks\n- lint-staged 15.5.0 - Pre-commit linting\n\n### Plugin-Based Architecture\n\nSwagger UI uses a **sophisticated plugin system** powered by Redux. The core system (`src/core/system.js`) manages:\n\n- Plugin registration and lifecycle\n- Redux store creation and middleware\n- State plugin combination\n- Action/selector binding\n- Configuration management\n\n**26 Core Plugins** (in `src/core/plugins/`):\n- `auth` - Authentication handling\n- `configs` - Configuration management\n- `deep-linking` - URL-based navigation\n- `download-url` - Spec downloading\n- `err` - Error handling and transformation\n- `filter` - API filtering\n- `icons` - Icon components\n- `json-schema-2020-12` - JSON Schema 2020-12 support\n- `json-schema-2020-12-samples` - Sample generation\n- `json-schema-5` - JSON Schema Draft 5 support\n- `json-schema-5-samples` - Sample generation for Draft 5\n- `layout` - Layout system\n- `logs` - Logging\n- `oas3` - OpenAPI 3.0.x support\n- `oas31` - OpenAPI 3.1.x support\n- `oas32` - OpenAPI 3.2.x support\n- `on-complete` - Completion callbacks\n- `request-snippets` - Code snippet generation\n- `safe-render` - Safe component rendering\n- `spec` - Specification handling\n- `swagger-client` - API client integration\n- `syntax-highlighting` - Code highlighting\n- `util` - Utilities\n- `versions` - Version detection\n- `view` - View rendering\n- `view-legacy` - Legacy view support\n\n---\n\n## Development Setup\n\n### Prerequisites\n\n- **Node.js:** >=24.22 (Node 24.x recommended, as defined in `.nvmrc`)\n- **npm:** >=11.19.1\n- **Git:** Any version\n- **JDK 7+:** Required for Nightwatch.js integration tests\n\n### Installation Steps\n\n```bash\n# Clone the repository\ngit clone https://github.com/swagger-api/swagger-ui.git\ncd swagger-ui\n\n# Install dependencies\nnpm install\n\n# Initialize Husky (optional, for git hooks)\nnpx husky init\n\n# Start development server\nnpm run dev\n\n# Open http://localhost:3200/\n```\n\n### Development Server\n\nThe `npm run dev` command starts a hot-reloading Webpack dev server on **port 3200**.\n\n### Using Local API Definitions\n\nEdit `dev-helpers/dev-helper-initializer.js` to change the spec URL:\n\n```javascript\n// Replace\nurl: \"https://petstore.swagger.io/v2/swagger.json\",\n\n// With\nurl: \"./examples/your-local-api-definition.yaml\",\n```\n\n**Important:** Local files must be in the `dev-helpers/` directory or subdirectory. Use `dev-helpers/examples/` (already in `.gitignore`).\n\n---\n\n## Build System\n\n### Babel Environments\n\nThree Babel environments configured in `babel.config.js`:\n\n1. **development/production** - Browser builds with `modules: \"auto\"`\n2. **commonjs** - CommonJS modules with `modules: \"commonjs\"` for Node.js\n3. **esm** - ES modules with `modules: false` for modern bundlers\n\n### Babel Aliases\n\n```javascript\n{\n  root: \".\",\n  core: \"./src/core\"\n}\n```\n\n### Browserslist Environments\n\nDefined in `.browserslistrc`:\n\n- `[browser-production]` - Production browser targets\n- `[browser-development]` - Latest Chrome, Firefox, Safari\n- `[isomorphic-production]` - Browser + Node targets\n- `[node-production]` - Maintained Node versions\n- `[node-development]` - Node 24\n\n### Build Commands\n\n```bash\n# Full build (stylesheets + all bundles)\nnpm run build\n\n# Individual builds\nnpm run build:core              # Core bundle (browser)\nnpm run build:bundle            # Isomorphic bundle\nnpm run build:standalone        # Standalone preset\nnpm run build:es:bundle         # ES module bundle\nnpm run build:es:bundle:core    # ES module core\nnpm run build-stylesheets       # CSS only\n\n# Clean build artifacts\nnpm run clean\n```\n\n### Build Output (dist/)\n\n- `swagger-ui.js` - Core bundle (CommonJS)\n- `swagger-ui.css` - Compiled styles\n- `swagger-ui-bundle.js` - Isomorphic bundle\n- `swagger-ui-standalone-preset.js` - Standalone preset\n- `swagger-ui-es-bundle.js` - ES module bundle\n- `swagger-ui-es-bundle-core.js` - ES module core\n- `oauth2-redirect.html` - OAuth2 redirect page\n\n### Webpack Configurations\n\nLocated in `webpack/` directory:\n\n- `_config-builder.js` - Base configuration\n- `core.js` - Core build\n- `bundle.js` - Bundle build\n- `standalone.js` - Standalone build\n- `es-bundle.js` - ES bundle\n- `es-bundle-core.js` - ES core bundle\n- `stylesheets.js` - CSS build\n- `dev.js` - Development server\n- `dev-e2e.js` - E2E testing server\n\n---\n\n## Testing Infrastructure\n\n### Unit Tests (Jest)\n\n**Configuration:** `config/jest/jest.unit.config.js`\n\n**Environment:** jsdom (simulates browser environment)\n\n**Location:** `test/unit/`\n\n**Command:**\n```bash\nnpm run test:unit\n```\n\n**Key Features:**\n- 37 unit test files\n- Tests for core plugins, components, system\n- XSS security tests\n- Silent mode enabled by default (set to `false` for console output)\n- Module name mapper for SVG and standalone imports\n- Transform ignore patterns for node_modules exceptions\n\n**Setup Files:**\n- `test/unit/jest-shim.js` - Polyfills and shims\n- `test/unit/setup.js` - Test environment setup\n\n### E2E Tests (Cypress)\n\n**Configuration:** `cypress.config.js`\n\n**Location:** `test/e2e-cypress/`\n\n**Base URL:** http://localhost:3230/\n\n**Commands:**\n```bash\n# Run all E2E tests\nnpm run cy:ci\n\n# Interactive Cypress runner\nnpm run cy:dev\n\n# Headless run\nnpm run cy:run\n\n# Start servers and run tests\nnpm run cy:start     # Starts webpack + mock API\n```\n\n**Structure:**\n- `test/e2e-cypress/e2e/` - Test specs (99 test files)\n- `test/e2e-cypress/static/` - Test fixtures and documents\n- `test/e2e-cypress/support/` - Test helpers and commands\n\n**Test Categories:**\n- `a11y/**/*cy.js` - Accessibility tests\n- `security/**/*cy.js` - Security tests\n- `bugs/**/*cy.js` - Bug regression tests\n- `features/**/*cy.js` - Feature tests\n\n**Mock API Server:**\n```bash\nnpm run cy:mock-api  # JSON Server on port 3204\n```\n\n### Artifact Tests\n\n**Configuration:** `config/jest/jest.artifact.config.js`\n\n**Purpose:** Verify build artifacts export correctly\n\n**Command:**\n```bash\nnpm run test:artifact\n```\n\n### Complete Test Suite\n\n```bash\nnpm test  # Runs: lint-errors + test:unit + cy:ci\n```\n\n### CI/CD Testing\n\n**GitHub Actions Workflow:** `.github/workflows/nodejs.yml`\n\n**Two Jobs:**\n1. **build** - Lint, unit tests, build, artifact tests\n2. **e2e-tests** - Cypress tests (matrix strategy with 3 containers)\n\n**Branches:** `main`, `next`\n\n---\n\n## Code Style & Conventions\n\n### ESLint Configuration\n\n**File:** `.eslintrc.js`\n\n**Parser:** `@babel/eslint-parser`\n\n**Key Rules:**\n- `semi: [2, \"never\"]` - **No semicolons**\n- `quotes: [2, \"double\"]` - **Double quotes** (allow template literals)\n- `no-unused-vars: 2` - Error on unused variables\n- `camelcase: [\"error\"]` - Enforce camelCase (with exceptions for UNSAFE_, request generators, etc.)\n- `no-console: [2, {allow: [\"warn\", \"error\"]}]` - Only `console.warn` and `console.error` allowed\n- `react/jsx-no-bind: 1` - Warning for JSX bind\n- `react/jsx-filename-extension: 2` - JSX only in `.jsx` files\n- `import/no-extraneous-dependencies: 2` - Error on extraneous dependencies\n\n**Extends:**\n- `eslint:recommended`\n- `plugin:react/recommended`\n- `plugin:prettier/recommended`\n\n### Prettier Configuration\n\n**File:** `.prettierrc.yaml`\n\n**Settings:**\n```yaml\nsemi: false              # No semicolons\ntrailingComma: es5       # ES5 trailing commas\nendOfLine: lf            # Unix line endings\nrequirePragma: true      # Require @prettier pragma\ninsertPragma: true       # Insert @prettier pragma\n```\n\n**IMPORTANT:** Prettier requires `@prettier` pragma comment at the top of files:\n```javascript\n/**\n * @prettier\n */\n```\n\n### Stylelint Configuration\n\n**File:** `stylelint.config.js`\n\n**Custom Syntax:** `postcss-scss`\n\n**Rules:**\n- Uses `stylelint-prettier` plugin\n- Prettier integration without pragma requirement\n\n### Pre-commit Hooks\n\n**Husky:** `.husky/pre-commit` runs `npx lint-staged`\n\n**Lint-staged Configuration:** `.lintstagedrc`\n```json\n{\n  \"*.{js,jsx}\": [\"eslint --max-warnings 0\"],\n  \"*.scss\": [\"stylelint '**/*.scss'\"]\n}\n```\n\n**Critical:** All staged JS/JSX/SCSS files are linted with **zero warnings tolerance**.\n\n### File Structure Conventions\n\n**TypeScript (REQUIRED for all new files):**\n- All new source files must be written in TypeScript (`.ts` / `.tsx`)\n- Use `.tsx` for React components, `.ts` for all other modules\n- Existing `.js` / `.jsx` files are not required to be migrated, but new code must not be added in plain JavaScript\n\n**Components:**\n- Location: `src/core/components/`\n- Extension: `.tsx` (React components — TypeScript)\n- Format: PascalCase for component names\n\n**Styles:**\n- Location: `src/style/`\n- Extension: `.scss`\n- Format: SCSS with PostCSS processing\n- Dark mode: `_dark-mode.scss`\n\n**Tests:**\n- Unit: `test/unit/` (mirrors source structure)\n- E2E: `test/e2e-cypress/e2e/`\n- Naming: `*.test.ts`, `*.spec.ts`, `*.cy.ts` (Cypress) — use `.tsx` variants when JSX is involved\n\n---\n\n## Git Workflow\n\n### Branch Strategy\n\n**Main Branches:**\n- `main` - Production releases\n- `next` - Next version development\n\n**Feature Branches:**\n- Should branch from `main` or `next`\n- Use descriptive names\n\n### Commit Conventions\n\n**Format:** Conventional Commits (enforced by commitlint)\n\n**Structure:**\n```\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n```\n\n**Types:**\n- `feat` - New feature\n- `fix` - Bug fix\n- `docs` - Documentation changes\n- `style` - Code style changes (formatting)\n- `refactor` - Code refactoring\n- `test` - Test additions/changes\n- `chore` - Build/tooling changes\n- `perf` - Performance improvements\n\n**Example:**\n```\nfeat(oas3): add support for OpenAPI 3.1.1 callbacks\n\nImplement callback rendering for OAS 3.1.1 specifications\nwith proper schema resolution and example generation.\n\nFixes #12345\n```\n\n### Pull Request Process\n\n**Template:** `.github/pull_request_template.md`\n\n**Required Sections:**\n1. **Description** - Detailed change description\n2. **Motivation and Context** - Why the change is needed\n3. **How Has This Been Tested?** - Manual testing details\n4. **Screenshots** - If UI changes\n\n**Checklist:**\n- [ ] Code type (no code/dependencies/bug fix/improvement/feature)\n- [ ] Breaking changes identification\n- [ ] Documentation updates\n- [ ] Test coverage\n- [ ] All tests passing\n\n**CI Checks:**\n- ESLint (error-only mode)\n- Unit tests (Jest)\n- Build verification\n- Artifact tests\n- E2E tests (Cypress)\n\n### Release Process\n\n**Tool:** release-it with conventional-changelog\n\n**Command:**\n```bash\nnpm run automated-release\n```\n\n**Workflows:**\n- `.github/workflows/release-swagger-ui.yml`\n- `.github/workflows/release-swagger-ui-dist.yml`\n- `.github/workflows/release-swagger-ui-react.yml`\n- `.github/workflows/release-swagger-ui-packagist.yml`\n\n---\n\n## Plugin Architecture\n\n### Core System (`src/core/system.js`)\n\nThe plugin system is the heart of Swagger UI. It uses Redux for state management with a custom plugin registration system.\n\n### Plugin Structure\n\nEach plugin is a JavaScript object/function that returns:\n\n```javascript\n{\n  statePlugins: {\n    [pluginName]: {\n      actions: {},      // Redux actions\n      reducers: {},     // Redux reducers\n      selectors: {},    // Reselect selectors\n      wrapActions: {},  // Action middleware\n      wrapSelectors: {} // Selector middleware\n    }\n  },\n  components: {},       // React components\n  fn: {},              // Utility functions\n  rootInjects: {},     // Root-level injections\n  afterLoad: Function  // Lifecycle hook\n}\n```\n\n### Key Plugin Locations\n\n**Core Plugins:** `src/core/plugins/`\n\nEach plugin has:\n- `index.js` - Main export\n- `actions.js` - Redux actions\n- `reducers.js` - Redux reducers\n- `selectors.js` - State selectors\n- `wrap-actions.js` - Action middleware\n- `wrap-selectors.js` - Selector middleware\n- Component files (`.jsx`)\n\n### Creating a Plugin\n\nSee documentation: `docs/customization/plugin-api.md`\n\n### Cross-Plugin Import Guidelines\n\n**IMPORTANT:** Avoid cross-plugin imports to maintain plugin independence and modularity.\n\n**Pattern to Follow:**\n- Each plugin should be self-contained with its own components, utilities, and functions\n- When OAS version plugins (oas3, oas31, oas32) need similar functionality, create self-contained copies within each plugin\n- Wrap components should import from their own plugin's components, not from other plugins\n\n**Example Structure:**\n```\nsrc/core/plugins/oas32/\n├── json-schema-2020-12-extensions/\n│   ├── components/              # Self-contained components\n│   │   └── keywords/\n│   │       ├── Description.jsx\n│   │       └── Properties.jsx\n│   ├── wrap-components/         # Wrappers for components\n│   │   └── keywords/\n│   │       ├── Description.jsx  # Imports from ../../components/\n│   │       └── Properties.jsx   # Not from ../../../../oas31/\n│   └── fn.js                    # Self-contained utilities\n```\n\n**Why This Matters:**\n- Prevents tight coupling between plugins\n- Makes plugins easier to test in isolation\n- Allows independent versioning and updates\n- Reduces risk of breaking changes across plugins\n- Improves code maintainability\n\n**Exceptions:**\n- Shared core utilities in `src/core/utils/` are acceptable\n- System-level functions in `src/core/system.js` are acceptable\n- Base components in `src/core/components/` are acceptable\n\n### Preset System\n\n**Base Preset:** `src/core/presets/base.js`\n\n**Standalone Preset:** `src/standalone/presets/standalone.js`\n\nPresets are collections of plugins bundled together for specific use cases.\n\n---\n\n## Key Files & Directories\n\n### Critical Source Files\n\n```\nsrc/\n├── core/\n│   ├── system.js                 # Plugin system & Redux store\n│   ├── components/               # 59 React components\n│   ├── plugins/                  # 26 core plugins\n│   ├── presets/                  # Preset configurations\n│   ├── utils/                    # Utility functions\n│   └── config/                   # Configuration system\n├── standalone/\n│   ├── plugins/                  # TopBar, StandaloneLayout\n│   └── presets/                  # Standalone preset\n├── style/                        # SCSS stylesheets\n│   ├── _dark-mode.scss          # Dark mode styles\n│   └── main.scss                # Main stylesheet entry\n└── index.js                      # Main package entry\n```\n\n### Configuration Files\n\n```\n.\n├── package.json                  # Dependencies & scripts\n├── babel.config.js              # Babel configuration\n├── .eslintrc.js                 # ESLint rules\n├── .prettierrc.yaml             # Prettier settings\n├── stylelint.config.js          # Stylelint rules\n├── .browserslistrc              # Browser targets\n├── .nvmrc                       # Node version (24.x)\n├── .lintstagedrc                # Pre-commit linting\n└── cypress.config.js            # Cypress E2E config\n```\n\n### Build & Tooling\n\n```\nwebpack/\n├── _config-builder.js           # Base Webpack config\n├── core.js                      # Core build\n├── bundle.js                    # Bundle build\n├── standalone.js                # Standalone build\n├── es-bundle.js                 # ES bundle build\n├── es-bundle-core.js           # ES core bundle\n├── stylesheets.js              # CSS compilation\n├── dev.js                       # Dev server\n└── dev-e2e.js                  # E2E dev server\n\nconfig/jest/\n├── jest.unit.config.js          # Unit test config\n└── jest.artifact.config.js      # Artifact test config\n```\n\n### Documentation\n\n```\ndocs/\n├── usage/\n│   ├── installation.md\n│   ├── configuration.md\n│   ├── cors.md\n│   ├── oauth2.md\n│   ├── deep-linking.md\n│   ├── version-detection.md\n│   └── limitations.md\n├── customization/\n│   ├── overview.md\n│   ├── plugin-api.md\n│   └── custom-layout.md\n└── development/\n    ├── setting-up.md\n    └── scripts.md\n```\n\n### Testing\n\n```\ntest/\n├── unit/                        # Jest unit tests (37 files)\n│   ├── setup.js                # Test environment setup\n│   └── jest-shim.js           # Polyfills\n├── e2e-cypress/                 # Cypress E2E tests (99 files)\n│   ├── e2e/                    # Test specs\n│   ├── static/                 # Fixtures\n│   └── support/                # Helpers\n└── e2e-selenium/               # Legacy Selenium tests\n```\n\n### Distribution\n\n```\nflavors/\n└── swagger-ui-react/            # React component wrapper\n\nswagger-ui-dist-package/         # Template for dist package\n\ndist/                            # Build output (generated)\n├── swagger-ui.js\n├── swagger-ui.css\n├── swagger-ui-bundle.js\n├── swagger-ui-standalone-preset.js\n├── swagger-ui-es-bundle.js\n├── swagger-ui-es-bundle-core.js\n└── oauth2-redirect.html\n```\n\n---\n\n## Common Workflows\n\n### Making Code Changes\n\n1. **Read before modifying:**\n   ```bash\n   # ALWAYS read files before editing them\n   # Understand the existing code structure\n   ```\n\n2. **Follow the style guide:**\n   - Use double quotes\n   - No semicolons\n   - Add `@prettier` pragma to new files\n   - Use `.jsx` extension for React components\n\n3. **Run linters:**\n   ```bash\n   npm run lint          # Check for errors and warnings\n   npm run lint-fix      # Auto-fix JavaScript issues\n   npm run lint-styles   # Check SCSS\n   npm run lint-styles-fix  # Auto-fix SCSS\n   ```\n\n4. **Test your changes:**\n   ```bash\n   npm run test:unit     # Run unit tests\n   npm run cy:dev        # Interactive E2E testing\n   npm run build         # Verify build works\n   npm run test:artifact # Verify artifacts\n   ```\n\n### Adding a New Component\n\n1. Create component in `src/core/components/` or appropriate plugin directory\n2. Use `.tsx` extension (TypeScript — required for all new files)\n3. Add `@prettier` pragma\n4. Follow React best practices (functional components, hooks)\n5. Add PropTypes validation\n6. Create corresponding test in `test/unit/`\n7. Export from plugin's `index.js` if needed\n\n### Adding a New Plugin\n\n1. Create directory in `src/core/plugins/[plugin-name]/`\n2. Create `index.ts` with plugin structure (TypeScript — required for all new files)\n3. Add actions, reducers, selectors as needed\n4. Register plugin in preset (e.g., `src/core/presets/base.js`)\n5. Add tests in `test/unit/core/plugins/[plugin-name]/`\n6. Document the plugin\n\n### Fixing a Bug\n\n1. **Reproduce the bug:**\n   - Add a failing test in `test/unit/` or `test/e2e-cypress/`\n   - Document reproduction steps\n\n2. **Fix the issue:**\n   - Make minimal changes to fix the bug\n   - Avoid refactoring unless necessary\n   - Ensure the test now passes\n\n3. **Verify:**\n   ```bash\n   npm run test:unit\n   npm run build\n   npm run test:artifact\n   ```\n\n4. **Create PR:**\n   - Reference the issue number\n   - Include before/after behavior\n   - Add screenshots if UI-related\n\n### Adding a Feature\n\n1. **Plan the feature:**\n   - Review existing architecture\n   - Identify affected plugins/components\n   - Consider OpenAPI spec compatibility\n\n2. **Implement:**\n   - Follow plugin architecture patterns\n   - Add configuration options if needed\n   - Update presets if necessary\n\n3. **Test thoroughly:**\n   - Unit tests for logic\n   - Component tests for UI\n   - E2E tests for integration\n   - Test with various OpenAPI specs\n\n4. **Document:**\n   - Update `docs/` if user-facing\n   - Add JSDoc comments for APIs\n   - Update README if needed\n\n### Security Considerations\n\n1. **XSS Prevention:**\n   - ALWAYS use DOMPurify for user-provided HTML\n   - Sanitize all external input\n   - Review `test/unit/xss/` for examples\n   - Never use `dangerouslySetInnerHTML` without sanitization\n\n2. **Input Validation:**\n   - Validate API responses\n   - Handle malformed OpenAPI specs gracefully\n   - Check for prototype pollution\n\n3. **Dependency Security:**\n   ```bash\n   npm run security-audit     # Run security audit\n   ```\n\n### Working with OpenAPI Specs\n\n**Testing Different Versions:**\n- OAS 2.0: Use `src/core/plugins/swagger-client/`\n- OAS 3.0.x: Use `src/core/plugins/oas3/`\n- OAS 3.1.x: Use `src/core/plugins/oas31/`\n- OAS 3.2.x: Use `src/core/plugins/oas32/`\n\n**Adding Test Specs:**\n- Add to `test/e2e-cypress/static/documents/`\n- Reference in E2E tests\n\n---\n\n## Important Guidelines\n\n### DO's ✅\n\n1. **Always read files before modifying them**\n2. **Write all new files in TypeScript** - use `.ts` for modules, `.tsx` for React components\n3. **Follow the no-semicolon convention**\n4. **Use double quotes for strings**\n5. **Add `@prettier` pragma to all new files**\n6. **Use `.tsx` extension for new React components** (TypeScript JSX)\n7. **Write tests for new features and bug fixes**\n8. **Run linters before committing** (automatic via husky)\n9. **Use DOMPurify for HTML sanitization**\n10. **Follow conventional commit format**\n11. **Update documentation for user-facing changes**\n12. **Test with multiple OpenAPI spec versions**\n13. **Check browser compatibility** (see `.browserslistrc`)\n14. **Use the plugin architecture** - don't modify core unnecessarily\n15. **Preserve backward compatibility** unless explicitly breaking\n16. **Run full test suite before submitting PR**\n17. **Keep plugins self-contained** - avoid cross-plugin imports (see [Cross-Plugin Import Guidelines](#cross-plugin-import-guidelines))\n\n### DON'Ts ❌\n\n1. **Don't write new files in plain JavaScript** - all new files must be TypeScript (`.ts` / `.tsx`)\n2. **Don't use semicolons** - project convention\n3. **Don't use single quotes** - use double quotes\n4. **Don't skip the @prettier pragma** - required for formatting\n5. **Don't put React in `.ts` files** - use `.tsx` for JSX\n6. **Don't commit files in `dev-helpers/`** (except core files)\n7. **Don't commit build artifacts** (`dist/` is gitignored)\n8. **Don't skip tests** - they run in CI\n9. **Don't bypass ESLint** - pre-commit hook enforces\n10. **Don't use `console.log`** - only `console.warn` and `console.error`\n11. **Don't render unsanitized HTML** - XSS vulnerability\n12. **Don't modify `package-lock.json` manually**\n13. **Don't push directly to `main` or `next`**\n14. **Don't ignore Cypress test failures**\n15. **Don't add dependencies without justification**\n16. **Don't break the build** - verify with `npm run build`\n17. **Don't import from other plugins** - create self-contained copies instead (e.g., don't import from `oas31` in `oas32`)\n\n### When Working with AI Assistants\n\n**Before Making Changes:**\n1. Read the affected files completely\n2. Understand the plugin architecture\n3. Check for existing tests\n4. Review related documentation\n\n**During Development:**\n1. Make minimal, focused changes\n2. Follow existing patterns in the codebase\n3. Add tests alongside code changes\n4. Run linters frequently\n\n**After Changes:**\n1. Verify all tests pass\n2. Check build completes successfully\n3. Test artifact exports\n4. Review for security issues\n5. Update relevant documentation\n\n**Communication:**\n- Be explicit about file locations\n- Use line number references (e.g., `src/core/system.js:96`)\n- Provide context for changes\n- Mention any breaking changes clearly\n\n### Performance Considerations\n\n1. **Immutable.js:**\n   - Use Immutable data structures for state\n   - Use `.toJS()` sparingly (expensive)\n   - Prefer Immutable operations\n\n2. **React:**\n   - Use React.memo for pure components\n   - Implement shouldComponentUpdate for class components\n   - Avoid inline function definitions in render\n\n3. **Redux:**\n   - Use reselect for memoized selectors\n   - Keep reducers pure and fast\n   - Avoid large state trees\n\n4. **Bundle Size:**\n   - Check bundle size with `npm run deps-size`\n   - Review dependency licenses with `npm run deps-license`\n   - Consider code splitting for large features\n\n### Debugging Tips\n\n**Development Server:**\n```bash\nnpm run dev\n# Open http://localhost:3200/\n# Hot reload enabled\n# Unminified stack traces\n```\n\n**Redux DevTools:**\n- Extension supported\n- State inspection available\n- Time-travel debugging\n\n**Cypress Interactive Mode:**\n```bash\nnpm run cy:dev\n# Visual test runner\n# Step-through debugging\n# Network inspection\n```\n\n**Jest Watch Mode:**\n```bash\nnpm run test:unit -- --watch\n# Re-run on file changes\n# Filter by file name or test name\n```\n\n**Source Maps:**\n- Generated for all builds\n- Enable in browser DevTools\n- Original source debugging\n\n---\n\n## Quick Reference\n\n### Essential Commands\n\n```bash\n# Development\nnpm run dev              # Start dev server (port 3200)\nnpm start                # Static file server (port 3002)\n\n# Building\nnpm run build            # Full production build\nnpm run clean            # Remove dist/\n\n# Testing\nnpm test                 # Full test suite (lint + unit + E2E)\nnpm run test:unit        # Jest unit tests\nnpm run cy:dev           # Cypress interactive\nnpm run cy:ci            # Cypress CI mode\nnpm run test:artifact    # Artifact verification\n\n# Linting\nnpm run lint             # ESLint (errors + warnings)\nnpm run lint-errors      # ESLint (errors only)\nnpm run lint-fix         # Auto-fix ESLint issues\nnpm run lint-styles      # Stylelint\nnpm run lint-styles-fix  # Auto-fix Stylelint issues\n\n# Security\nnpm run security-audit   # Run npm audit\n\n# Dependencies\nnpm run deps-check       # Size and license report\n```\n\n### File Paths\n\n```\nCore System:           src/core/system.js\nMain Entry:            src/index.js\nReact Entry:           flavors/swagger-ui-react/index.jsx\nComponents:            src/core/components/\nPlugins:               src/core/plugins/\nStyles:                src/style/\nTests (Unit):          test/unit/\nTests (E2E):           test/e2e-cypress/e2e/\nBuild Output:          dist/\n```\n\n### Port Reference\n\n- **3200** - Development server (webpack-dev-server)\n- **3002** - Static file server (local-web-server)\n- **3204** - Mock API server (json-server)\n- **3230** - E2E test server (webpack-dev-server)\n\n---\n\n## Additional Resources\n\n### Documentation\n\n- **Setup Guide:** `docs/development/setting-up.md`\n- **Scripts Reference:** `docs/development/scripts.md`\n- **Plugin API:** `docs/customization/plugin-api.md`\n- **Configuration:** `docs/usage/configuration.md`\n- **OAuth2 Setup:** `docs/usage/oauth2.md`\n\n### External Links\n\n- **Homepage:** https://swagger.io/tools/swagger-ui/\n- **Repository:** https://github.com/swagger-api/swagger-ui\n- **npm (main):** https://www.npmjs.com/package/swagger-ui\n- **npm (dist):** https://www.npmjs.com/package/swagger-ui-dist\n- **npm (react):** https://www.npmjs.com/package/swagger-ui-react\n- **OpenAPI Spec:** https://spec.openapis.org/\n\n### Community\n\n- **Issues:** https://github.com/swagger-api/swagger-ui/issues\n- **Good First Issues:** https://github.com/swagger-api/swagger-ui/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%22\n- **Security:** security@swagger.io\n- **Contributing:** https://github.com/swagger-api/.github/blob/HEAD/CONTRIBUTING.md\n\n---\n\n**Note:** This document should be updated whenever major architectural changes, new conventions, or significant workflows are introduced to the codebase.\n\n<!-- File: src/core/plugins/deep-linking/README.md (Tokens: ~9 | Category: plugin-manifest) -->\nSee `docs/deep-linking.md`.\n\n<!-- File: src/core/plugins/err/error-transformers/README.md (Tokens: ~215 | Category: plugin-manifest) -->\n# Error transformers\n\nError transformers provide a standard interface for making generated error messages more useful to end users.\n\n### Inputs & outputs\n\nEach transformer's `transform` function is given an Immutable List of Immutable Maps as its first argument.\n\nIt is expected that each `transform` function returns a List of similarly-formed Maps.\n\nThese errors originate from the Redux error actions that add errors to state. Errors are transformed before being passed into the reducer.\n\nIt's important that all the keys present in each error (specifically, `line`, `level`, `message`, `source`, and `type`) are present when the transformer is finished.\n\n##### Deleting an error\n\nIf you want to delete an error completely, you can overwrite it with `null`. The null value will be filtered out of the transformed error array before the errors are returned.\nå\n\n### Example transformer\n\nThis transformer will increase all your line numbers by 10.\n\n```\nexport function transform(errors) {\n  return errors.map(err => {\n    err.line += 10\n    return err\n  })\n}\n```\n</yakaai_skills>"}