mirror of
https://github.com/Redocly/redoc.git
synced 2025-07-13 01:32:19 +03:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ba863af102 | ||
|
ce27184254 | ||
|
3ae251b7e4 | ||
|
00bc6edfc4 | ||
|
45476135ad | ||
|
05a04c85ed | ||
|
2db293bfb2 | ||
|
1b4126fde4 | ||
|
1fa13270a1 | ||
|
7cedd59826 | ||
|
cab07bad3b |
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,3 +1,17 @@
|
|||
# [2.5.0](https://github.com/Redocly/redoc/compare/v2.4.0...v2.5.0) (2025-04-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* enhance accessibility for menu items with keyboard support ([#2655](https://github.com/Redocly/redoc/issues/2655)) ([2db293b](https://github.com/Redocly/redoc/commit/2db293bfb2973497dd33f31dc99e97f5bb90bbe8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add keyboard navigation support to JsonViewer component ([#2654](https://github.com/Redocly/redoc/issues/2654)) ([1b4126f](https://github.com/Redocly/redoc/commit/1b4126fde4531387f49c90f52efbd0c0e5f7b6ea))
|
||||
|
||||
|
||||
|
||||
# [2.4.0](https://github.com/Redocly/redoc/compare/v2.3.0...v2.4.0) (2025-02-07)
|
||||
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@ With Redocly CLI, you can bundle your OpenAPI definition and API documentation
|
|||
|
||||
First, you need to install the `@redocly/cli` package.
|
||||
|
||||
You can install it [globally](../../cli/installation.md#install-globally) using npm or Yarn.
|
||||
You can install it [globally](../../cli/installation#install-globally) using npm.
|
||||
|
||||
Or you can install it during [runtime](../../cli/installation.md#use-npx-at-runtime) using npx or Docker.
|
||||
Or you can install it during [runtime](../../cli/installation#use-npx-at-runtime) using npx or Docker.
|
||||
|
||||
## Step 2 - Build the HTML file
|
||||
|
||||
|
@ -27,9 +27,9 @@ replacing `apis/openapi.yaml` with your API definition file's name and path:
|
|||
redocly build-docs apis/openapi.yaml
|
||||
```
|
||||
|
||||
See the [build-docs](../../cli/commands/build-docs.md) documentation for more information
|
||||
See the [build-docs](../../cli/commands/build-docs) documentation for more information
|
||||
on the different options and ways you can use the command.
|
||||
|
||||
Also, check out [Redocly CLI commands](../../cli/commands/index.md), for more
|
||||
Also, check out [Redocly CLI commands](../../cli/commands), for more
|
||||
information on the different things you can do with Redocly CLI including
|
||||
linting, splitting, and bundling your API definition file.
|
||||
|
|
|
@ -45,34 +45,6 @@ section in the documentation.
|
|||
|
||||
If you want to view your Redoc output locally, you can simulate an HTTP server.
|
||||
|
||||
#### Redocly CLI
|
||||
|
||||
Redocly CLI is an open source command-line tool that includes a command
|
||||
for simulating an HTTP server to provide a preview of your OpenAPI definition locally.
|
||||
|
||||
If you have [Redocly CLI](https://redocly.com/docs/cli/#installation-and-usage) installed, `cd` into your
|
||||
project directory and run the following command:
|
||||
|
||||
```bash
|
||||
redocly preview-docs openapi.yaml
|
||||
```
|
||||
|
||||
Replace `openapi.yaml` in the example command with the file path to your OpenAPI definition.
|
||||
|
||||
By default, without providing a port, the preview starts on port 8080, and can be accessed at `http://localhost:8080`.
|
||||
To exit the preview, use `control+C`.
|
||||
|
||||
You can alter the port if you are using 8080 already, for example:
|
||||
|
||||
```bash
|
||||
redocly preview-docs -p 8888 openapi.yaml
|
||||
```
|
||||
|
||||
Replace `openapi.yaml` in the example command with the file path to your OpenAPI definition.
|
||||
|
||||
For more information about the `preview-docs` command, refer to
|
||||
[Redocly CLI commands](https://redocly.com/docs/cli/commands/preview-docs/#preview-docs) in the Redocly CLI documentation.
|
||||
|
||||
#### Python
|
||||
|
||||
If you have [Python 3](https://www.python.org/downloads/) installed, `cd` into your
|
||||
|
|
|
@ -57,7 +57,7 @@ Check out the [deployment documentation](./deployment/intro.md) for more options
|
|||
|
||||
Redoc is highly configurable. Each deployment option accepts configuration in a way that's appropriate to that platform, but the options are the same for each. For example:
|
||||
|
||||
* Using [Redocly CLI](../cli/index.md), configuration goes in the `redocly.yaml` file, or can be supplied as command line parameters, such as `--theme.openapi.disableSearch`.
|
||||
* Using [Redocly CLI](../cli), configuration goes in the `redocly.yaml` file, or can be supplied as command line parameters, such as `--theme.openapi.disableSearch`.
|
||||
* Using HTML or React, configure by setting `option` in the tag.
|
||||
|
||||
Here's a sample `redocly.yaml` configuration file, showing a few common settings and tweaking some of the visual theme settings:
|
||||
|
@ -85,13 +85,13 @@ theme:
|
|||
Redocly CLI detects a file named `redocly.yaml` in the same directory as you run the command and uses it. See the documentation with a command like this:
|
||||
|
||||
```sh
|
||||
redocly preview-docs openapi.yaml
|
||||
redocly build-docs openapi.yaml
|
||||
```
|
||||
|
||||
There are many, many more options available. Visit the [configuration reference](./config.md) for a complete list.
|
||||
|
||||
## Next steps
|
||||
|
||||
* If you are new to OpenAPI, try the [OpenAPI starter project](../cli/openapi-starter.md) for a great introduction.
|
||||
* If you are new to OpenAPI, try the [OpenAPI starter project](../cli/openapi-starter) for a great introduction.
|
||||
* Ready to build documentation from an existing OpenAPI file? Go to the [Redoc quickstart](./quickstart.md) and get started.
|
||||
* Learn more about the project by visiting [Redoc on GitHub](https://github.com/Redocly/redoc).
|
||||
|
|
|
@ -12,38 +12,39 @@ You can use the following [vendor extensions](https://redocly.com/docs/openapi-v
|
|||
- [x-tagGroups example](#x-taggroups-example)
|
||||
- [Info Object](#info-object)
|
||||
- [x-logo](#x-logo)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-2)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-1)
|
||||
- [Logo Object](#logo-object)
|
||||
- [Fixed fields](#fixed-fields-1)
|
||||
- [x-logo example](#x-logo-example)
|
||||
- [Tag Object](#tag-object)
|
||||
- [x-traitTag](#x-traittag)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-3)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-2)
|
||||
- [x-traitTag example](#x-traittag-example)
|
||||
- [x-displayName](#x-displayname)
|
||||
- [Operation Object vendor extensions](#operation-object-vendor-extensions)
|
||||
- [x-codeSamples](#x-codesamples)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-4)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-3)
|
||||
- [Code Sample Object](#code-sample-object)
|
||||
- [Fixed fields](#fixed-fields-2)
|
||||
- [Code Sample Object example](#code-sample-object-example)
|
||||
- [x-badges](#x-badges)
|
||||
- [Parameter Object](#parameter-object)
|
||||
- [x-examples](#x-examples)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-5)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-4)
|
||||
- [Response Object vendor extensions](#response-object-vendor-extensions)
|
||||
- [x-summary](#x-summary)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-6)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-5)
|
||||
- [Schema Object](#schema-object)
|
||||
- [x-nullable](#x-nullable)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-7)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-6)
|
||||
- [x-additionalPropertiesName](#x-additionalpropertiesname)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-9)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-7)
|
||||
- [x-additionalPropertiesName example](#x-additionalpropertiesname-example)
|
||||
- [x-explicitMappingOnly](#x-explicitmappingonly)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-10)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-8)
|
||||
- [x-explicitMappingOnly example](#x-explicitmappingonly-example)
|
||||
- [x-enumDescriptions](#x-enumdescriptions)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-11)
|
||||
- [How to use with Redoc](#how-to-use-with-redoc-9)
|
||||
- [x-enumDescriptions example](#x-enumdescriptions-example)
|
||||
|
||||
## Swagger Object
|
||||
|
@ -67,6 +68,7 @@ Before you use `x-tagGroups`, make sure you **add all tags to a group**, since a
|
|||
#### Tag Group Object
|
||||
Information about tags group
|
||||
##### Fixed fields
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :---------- | :--------: | :---------- |
|
||||
| name | string | The group name |
|
||||
|
@ -120,6 +122,7 @@ Extends the OpenAPI [Info Object](https://redocly.com/docs/openapi-visual-refere
|
|||
The information about API logo
|
||||
|
||||
#### Fixed fields
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :-------------- | :------: | :---------- |
|
||||
| url | string | The URL pointing to the spec logo. MUST be in the format of a URL. It SHOULD be an absolute URL so your API definition is usable from any location |
|
||||
|
@ -158,6 +161,7 @@ info:
|
|||
Extends the OpenAPI [Tag Object](https://redocly.com/docs/openapi-visual-reference/tags/)
|
||||
|
||||
### x-traitTag
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :------------- | :------: | :---------- |
|
||||
| x-traitTag | boolean | In Swagger two operations can have multiple tags. This property distinguishes between tags that are used to group operations (default) from tags that are used to mark operation with certain trait (`true` value) |
|
||||
|
@ -192,6 +196,7 @@ x-traitTag: true
|
|||
Extends the OpenAPI [Operation Object](https://redocly.com/docs/openapi-visual-reference/operation/)
|
||||
|
||||
### x-codeSamples
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :------------- | :------: | :---------- |
|
||||
| x-codeSamples | [ [Code Sample Object](#code-sample-object) ] | A list of code samples associated with operation |
|
||||
|
@ -205,6 +210,7 @@ Extends the OpenAPI [Operation Object](https://redocly.com/docs/openapi-visual-r
|
|||
Operation code sample
|
||||
|
||||
#### Fixed fields
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :---------- | :------: | :----------- |
|
||||
| lang | string | Code sample language. Value should be one of the following [list](https://github.com/github/linguist/blob/master/lib/linguist/popular.yml) |
|
||||
|
@ -227,6 +233,7 @@ source: console.log('Hello World');
|
|||
```
|
||||
|
||||
### x-badges
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :------------- | :------: | :---------- |
|
||||
| x-badges | [[Badge Object](https://redocly.com/docs/realm/author/reference/openapi-extensions/x-badges#badge-object)] | A list of badges associated with the operation |
|
||||
|
@ -235,6 +242,7 @@ source: console.log('Hello World');
|
|||
Extends the OpenAPI [Parameter Object](https://redocly.com/docs/openapi-visual-reference/parameter/)
|
||||
|
||||
### x-examples
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :------------- | :------: | :---------- |
|
||||
| x-examples | [Example Object](https://redocly.com/docs/openapi-visual-reference/example/) | Object that contains examples for the request. Applies when `in` is `body` and mime-type is `application/json` |
|
||||
|
@ -246,6 +254,7 @@ Extends the OpenAPI [Parameter Object](https://redocly.com/docs/openapi-visual-r
|
|||
Extends the OpenAPI [Response Object](https://redocly.com/docs/openapi-visual-reference/response/).
|
||||
|
||||
### x-summary
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :------------- | :------: | :---------- |
|
||||
| x-summary | string | a short summary of the response |
|
||||
|
@ -257,6 +266,7 @@ If specified, you can use `x-summary` as the response button text, with descript
|
|||
Extends the OpenAPI [Schema Object](https://redocly.com/docs/openapi-visual-reference/schemas/)
|
||||
|
||||
### x-nullable
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :------------- | :------: | :---------- |
|
||||
| x-nullable | boolean | marks schema as a nullable |
|
||||
|
@ -325,6 +335,7 @@ Pet:
|
|||
Shows in the selectpicker only the items `cat` and `bee`, even though the `Dog` class inherits from the `Pet` class.
|
||||
|
||||
### x-enumDescriptions
|
||||
|
||||
| Field Name | Type | Description |
|
||||
| :------------- | :------: | :---------- |
|
||||
| x-enumDescriptions | [[Enum Description Object](https://redocly.com/docs/realm/author/reference/openapi-extensions/x-enum-descriptions#enum-description-object)] | A list of the enum values and descriptions to include in the documentation. |
|
||||
|
|
1085
package-lock.json
generated
1085
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "redoc",
|
||||
"version": "2.4.0",
|
||||
"version": "2.5.0",
|
||||
"description": "ReDoc",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -93,7 +93,7 @@
|
|||
"cypress": "^13.8.1",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-to-json": "^3.6.2",
|
||||
"esbuild-loader": "^3.0.1",
|
||||
"esbuild-loader": "^4.3.0",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-plugin-import": "^2.23.4",
|
||||
"eslint-plugin-react": "^7.34.2",
|
||||
|
@ -141,7 +141,7 @@
|
|||
"@redocly/openapi-core": "^1.4.0",
|
||||
"classnames": "^2.3.2",
|
||||
"decko": "^1.2.0",
|
||||
"dompurify": "^3.0.6",
|
||||
"dompurify": "^3.2.4",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"json-pointer": "^0.6.2",
|
||||
"lunr": "^2.3.9",
|
||||
|
|
|
@ -41,6 +41,7 @@ const Json = (props: JsonProps) => {
|
|||
<OptionsContext.Consumer>
|
||||
{options => (
|
||||
<PrismDiv
|
||||
tabIndex={0}
|
||||
className={props.className}
|
||||
// tslint:disable-next-line
|
||||
ref={node => setNode(node!)}
|
||||
|
|
|
@ -6,11 +6,14 @@ import { StylingMarkdownProps } from './Markdown';
|
|||
import { StyledMarkdownBlock } from './styled.elements';
|
||||
import styled from 'styled-components';
|
||||
|
||||
// Workaround for DOMPurify type issues (https://github.com/cure53/DOMPurify/issues/1034)
|
||||
const dompurify = DOMPurify['default'] as DOMPurify.DOMPurify;
|
||||
|
||||
const StyledMarkdownSpan = styled(StyledMarkdownBlock)`
|
||||
display: inline;
|
||||
`;
|
||||
|
||||
const sanitize = (sanitize, html) => (sanitize ? DOMPurify.sanitize(html) : html);
|
||||
const sanitize = (sanitize, html) => (sanitize ? dompurify.sanitize(html) : html);
|
||||
|
||||
export function SanitizedMarkdownHTML({
|
||||
inline,
|
||||
|
|
|
@ -2,14 +2,14 @@ import { observer } from 'mobx-react';
|
|||
import * as React from 'react';
|
||||
|
||||
import { ShelfIcon } from '../../common-elements/shelfs';
|
||||
import type { IMenuItem } from '../../services';
|
||||
import { OperationModel } from '../../services';
|
||||
import { shortenHTTPVerb } from '../../utils/openapi';
|
||||
import { MenuItems } from './MenuItems';
|
||||
import { MenuItemLabel, MenuItemLi, MenuItemTitle, OperationBadge } from './styled.elements';
|
||||
import { l } from '../../services/Labels';
|
||||
import { scrollIntoViewIfNeeded } from '../../utils';
|
||||
import { shortenHTTPVerb } from '../../utils/openapi';
|
||||
import { OptionsContext } from '../OptionsProvider';
|
||||
import type { IMenuItem } from '../../services';
|
||||
import { MenuItems } from './MenuItems';
|
||||
import { MenuItemLabel, MenuItemLi, MenuItemTitle, OperationBadge } from './styled.elements';
|
||||
|
||||
export interface MenuItemProps {
|
||||
item: IMenuItem;
|
||||
|
@ -47,9 +47,18 @@ export class MenuItem extends React.Component<MenuItemProps> {
|
|||
<MenuItemLi
|
||||
tabIndex={0}
|
||||
onClick={this.activate}
|
||||
onKeyDown={evt => {
|
||||
// Space or Enter key will activate the menu item
|
||||
if (evt.key === 'Enter' || evt.key === ' ') {
|
||||
this.props.onActivate!(this.props.item);
|
||||
evt.stopPropagation();
|
||||
}
|
||||
}}
|
||||
depth={item.depth}
|
||||
data-item-id={item.id}
|
||||
role="menuitem"
|
||||
aria-label={item.sidebarLabel}
|
||||
aria-expanded={item.expanded}
|
||||
>
|
||||
{item.type === 'operation' ? (
|
||||
<OperationMenuItemContent {...this.props} item={item as OperationModel} />
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { mount, ReactWrapper } from 'enzyme';
|
||||
import * as React from 'react';
|
||||
import { act } from 'react';
|
||||
|
||||
import { JsonViewer } from '../';
|
||||
import { withTheme } from '../testProviders';
|
||||
|
@ -50,5 +51,54 @@ describe('Components', () => {
|
|||
expect(flatDataComponent.html()).not.toContain('Expand all');
|
||||
expect(flatDataComponent.html()).not.toContain('Collapse all');
|
||||
});
|
||||
|
||||
describe('Keyboard Navigation', () => {
|
||||
let component: ReactWrapper;
|
||||
const data = {
|
||||
a: 1,
|
||||
b: {
|
||||
c:
|
||||
// Long string to test horizontal scrolling
|
||||
Array(100).fill('hello').join(''),
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
component = mount(withTheme(<JsonViewer data={data} />));
|
||||
ClipboardService.copySelected = origCopySelected;
|
||||
});
|
||||
|
||||
test('should handle arrow key navigation', () => {
|
||||
const prismDiv = component.find('div[tabIndex=0]');
|
||||
const divElement = prismDiv.getDOMNode();
|
||||
|
||||
// Mock scrollLeft before events
|
||||
Object.defineProperty(divElement, 'scrollLeft', {
|
||||
get: jest.fn(() => 0),
|
||||
set: jest.fn(),
|
||||
});
|
||||
|
||||
// Trigger events inside act()
|
||||
act(() => {
|
||||
divElement.dispatchEvent(
|
||||
new KeyboardEvent('keydown', {
|
||||
key: 'ArrowRight',
|
||||
bubbles: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
act(() => {
|
||||
divElement.dispatchEvent(
|
||||
new KeyboardEvent('keydown', {
|
||||
key: 'ArrowLeft',
|
||||
bubbles: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
expect(divElement.scrollLeft).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user