mirror of
https://github.com/Redocly/redoc.git
synced 2025-07-30 09:59:45 +03:00
DOP-3505: Redoc CLI ingests version data from json file (#15)
This commit is contained in:
parent
2d61688fcc
commit
da330e9178
29
README.md
29
README.md
|
@ -40,6 +40,35 @@ With `node` installed, run by doing the following:
|
|||
node <path/to/redoc/cli/index.js> build <path/to/spec/file/or/url> --options=<path/to/options.json> --output=<path/to/custom/output/file/name.html>
|
||||
```
|
||||
|
||||
#### Versioned Options in the CLI
|
||||
|
||||
If wanting to add versioning support in your build, you must create a JSON file with the following data structure (replace example values with any mock values):
|
||||
|
||||
```
|
||||
{
|
||||
"active": {
|
||||
"apiVersion": "2.0",
|
||||
"resourceVersion": "2023-02-14"
|
||||
},
|
||||
"rootUrl": "https://mongodb.com/docs/atlas/reference/api-resources-spec/v2",
|
||||
"resourceVersions": ["2022-09-09", "2022-10-18", "2023-02-14"]
|
||||
}
|
||||
```
|
||||
|
||||
After doing so, run the build much the same as above but with the following option added:
|
||||
Note: the path to the version data option JSON file should be referenced in relation to the `redoc/cli` directory
|
||||
|
||||
```
|
||||
--options.versionData=<path/to/mock/data/file.json/from/cli/directory>
|
||||
```
|
||||
|
||||
Such as:
|
||||
Note: this is referencing a JSON file in the root directory
|
||||
|
||||
```
|
||||
node <path/to/redoc/cli/index.js> build <path/to/spec/file/or/url> --options.versionData=../version-data.json
|
||||
```
|
||||
|
||||
### Releasing
|
||||
|
||||
The Redoc React component and the Redoc CLI have 2 separate release processes. Because the Redoc CLI pulls its version of Redoc from GitHub, build artifacts are included in the version tag being installed.
|
||||
|
|
|
@ -27,4 +27,29 @@ describe('build', () => {
|
|||
expect(result).toContain('Found .redocly.yaml and using features.openapi options');
|
||||
expect(result).toContain('bundled successfully');
|
||||
});
|
||||
|
||||
it('should ingest version data from json file', () => {
|
||||
const pathToTestData = '__test__/data/version-data.json';
|
||||
const r = spawnSync(
|
||||
'ts-node',
|
||||
[
|
||||
'../../../index.ts',
|
||||
'build',
|
||||
' ../../../../demo/openapi.yaml',
|
||||
'--output=redoc-test.html',
|
||||
`--options.versionData=${pathToTestData}`,
|
||||
],
|
||||
{
|
||||
cwd: __dirname,
|
||||
shell: true,
|
||||
},
|
||||
);
|
||||
|
||||
const out = r.stdout.toString('utf-8');
|
||||
const err = r.stderr.toString('utf-8');
|
||||
const result = `${out}\n${err}`;
|
||||
|
||||
expect(result).toContain(`Found ${pathToTestData} and using version data.`);
|
||||
expect(result).toContain('bundled successfully');
|
||||
});
|
||||
});
|
||||
|
|
8
cli/__test__/data/version-data.json
Normal file
8
cli/__test__/data/version-data.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"active": {
|
||||
"apiVersion": "2.0",
|
||||
"resourceVersion": "2023-02-14"
|
||||
},
|
||||
"rootUrl": "https://mongodb.com/docs/atlas/reference/api-resources-spec/v2",
|
||||
"resourceVersions": ["2022-09-09", "2022-10-18", "2028-02-14"]
|
||||
}
|
16
cli/index.ts
16
cli/index.ts
|
@ -439,6 +439,22 @@ function handleError(error: Error) {
|
|||
function getObjectOrJSON(options) {
|
||||
switch (typeof options) {
|
||||
case 'object':
|
||||
if (options?.versionData) {
|
||||
const { versionData: versionPath } = options;
|
||||
const versionFilePath = resolve(__dirname, versionPath);
|
||||
try {
|
||||
if (existsSync(versionFilePath) && lstatSync(versionFilePath).isFile()) {
|
||||
const versionData = JSON.parse(readFileSync(versionFilePath, 'utf-8'));
|
||||
options.versionData = versionData;
|
||||
console.log(`Found ${versionPath} and using version data.`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(
|
||||
`Encountered error:\n\n${versionPath}\n\nis not a file with a valid JSON object.`,
|
||||
);
|
||||
handleError(e);
|
||||
}
|
||||
}
|
||||
return options;
|
||||
case 'string':
|
||||
try {
|
||||
|
|
|
@ -4,7 +4,7 @@ describe('Menu', () => {
|
|||
});
|
||||
|
||||
it('should have valid items count', () => {
|
||||
cy.get('.menu-content').find('li').should('have.length', 35);
|
||||
cy.get('.menu-content').find('li').not('[role="option"]').should('have.length', 35);
|
||||
});
|
||||
|
||||
it('should have a back button', () => {
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
|
||||
import { SearchBox } from '../SearchBox/SearchBox';
|
||||
import { StoreProvider } from '../StoreBuilder';
|
||||
import { VersionSelector } from '../VersionSelector';
|
||||
|
||||
export interface RedocProps {
|
||||
store: AppStore;
|
||||
|
@ -69,6 +70,9 @@ export class Redoc extends React.Component<RedocProps> {
|
|||
/>
|
||||
)) ||
|
||||
null}
|
||||
{options.versionData && typeof options.versionData == 'object' && (
|
||||
<VersionSelector {...options.versionData} />
|
||||
)}
|
||||
<SideMenu menu={menu} />
|
||||
</StickyResponsiveSidebar>
|
||||
<ApiContentWrap className="api-content">
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
StyledMenuList,
|
||||
StyledDisplay,
|
||||
StyledDropdown,
|
||||
StyledSelected,
|
||||
} from './styled.elements';
|
||||
import { Option } from './Option';
|
||||
import { VersionSelectorProps } from './types';
|
||||
|
@ -42,9 +43,7 @@ const VersionSelectorComponent = ({
|
|||
{description && <StyledDescription>{description}</StyledDescription>}
|
||||
<StyledButton onClick={() => setOpen(!open)}>
|
||||
<StyledDisplay>
|
||||
<div>
|
||||
<div>{resourceVersions[selectedIdx]}</div>
|
||||
</div>
|
||||
<StyledSelected>{resourceVersions[selectedIdx]}</StyledSelected>
|
||||
<ArrowIcon open={open} />
|
||||
</StyledDisplay>
|
||||
</StyledButton>
|
||||
|
|
|
@ -10,7 +10,7 @@ const transitionDuration = {
|
|||
slower: 300,
|
||||
} as const;
|
||||
|
||||
export const ArrowIcon = styled(ArrowSvg)`
|
||||
export const ArrowIcon = styled(ArrowSvg)<{ open: boolean }>`
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
|
@ -101,12 +101,17 @@ export const StyledMenuList = styled.ul`
|
|||
`;
|
||||
|
||||
export const StyledDisplay = styled.div`
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 16px;
|
||||
gap: 6px;
|
||||
padding: 0 4px 0 12px;
|
||||
`;
|
||||
|
||||
export const StyledSelected = styled.div`
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
export const disabledOptionStyle = css`
|
||||
cursor: not-allowed;
|
||||
color: ${palette.gray.base};
|
||||
|
|
|
@ -354,6 +354,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/packSize",
|
||||
|
@ -687,6 +688,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/type",
|
||||
|
@ -1007,6 +1009,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog",
|
||||
|
@ -1389,6 +1392,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Cat/properties/type",
|
||||
|
@ -1734,6 +1738,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Cat/properties/packSize",
|
||||
|
@ -2050,6 +2055,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Cat",
|
||||
|
@ -2391,6 +2397,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Pet",
|
||||
|
@ -2762,6 +2769,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/packSize",
|
||||
|
@ -3095,6 +3103,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog/properties/type",
|
||||
|
@ -3415,6 +3424,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
|||
},
|
||||
"unstable_ignoreMimeParameters": false,
|
||||
"untrustedSpec": false,
|
||||
"versionData": undefined,
|
||||
},
|
||||
"pattern": undefined,
|
||||
"pointer": "#/components/schemas/Dog",
|
||||
|
|
|
@ -17,12 +17,12 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = `
|
|||
class="sc-hKFxyN hYrDYQ"
|
||||
>
|
||||
<div
|
||||
class="sc-iCoGMd fgtoGu"
|
||||
class="sc-iCoGMd gojxeT"
|
||||
>
|
||||
<div>
|
||||
<div>
|
||||
2023-01-01
|
||||
</div>
|
||||
<div
|
||||
class="sc-fujyAs hQJiDC"
|
||||
>
|
||||
2023-01-01
|
||||
</div>
|
||||
<svg
|
||||
fill="none"
|
||||
|
@ -44,7 +44,7 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = `
|
|||
</div>
|
||||
<div
|
||||
aria-labelledby="View a different version of documentation."
|
||||
class="sc-jrsJWt ofjNY"
|
||||
class="sc-kEqXSa litKaz"
|
||||
role="listbox"
|
||||
tabindex="-1"
|
||||
>
|
||||
|
@ -54,44 +54,44 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = `
|
|||
>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="sc-fujyAs iIVhNL"
|
||||
class="sc-pNWdM glxGCd"
|
||||
role="option"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="sc-kEqXSa cBTyJc"
|
||||
class="sc-iqAclL dXUzZL"
|
||||
/>
|
||||
<span
|
||||
class="sc-pNWdM irvinq"
|
||||
class="sc-jrsJWt hDLwjI"
|
||||
>
|
||||
2021-09-09
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="false"
|
||||
class="sc-fujyAs iIVhNL"
|
||||
class="sc-pNWdM glxGCd"
|
||||
role="option"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="sc-kEqXSa cBTyJc"
|
||||
class="sc-iqAclL dXUzZL"
|
||||
/>
|
||||
<span
|
||||
class="sc-pNWdM irvinq"
|
||||
class="sc-jrsJWt hDLwjI"
|
||||
>
|
||||
2022-10-18
|
||||
</span>
|
||||
</li>
|
||||
<li
|
||||
aria-selected="true"
|
||||
class="sc-fujyAs Ywdfd"
|
||||
class="sc-pNWdM jlRKTH"
|
||||
role="option"
|
||||
selected=""
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
aria-label="Checkmark Icon"
|
||||
class="sc-iqAclL ejyrfD"
|
||||
class="sc-crzoAE gdYtkZ"
|
||||
height="16"
|
||||
role="img"
|
||||
viewBox="0 0 16 16"
|
||||
|
@ -105,7 +105,7 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = `
|
|||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="sc-pNWdM irvinq"
|
||||
class="sc-jrsJWt hDLwjI"
|
||||
>
|
||||
2023-01-01
|
||||
</span>
|
||||
|
|
|
@ -61,6 +61,16 @@ export interface RedocRawOptions {
|
|||
backNavigationPath?: string;
|
||||
ignoreIncompatibleTypes?: boolean | string;
|
||||
siteTitle?: string;
|
||||
versionData?: string;
|
||||
}
|
||||
|
||||
export interface VersionData {
|
||||
active: {
|
||||
apiVersion: string;
|
||||
resourceVersion: string;
|
||||
};
|
||||
rootUrl: string;
|
||||
resourceVersions: string[];
|
||||
}
|
||||
|
||||
export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean {
|
||||
|
@ -269,6 +279,7 @@ export class RedocNormalizedOptions {
|
|||
backNavigationPath?: string;
|
||||
ignoreIncompatibleTypes: boolean;
|
||||
siteTitle?: string;
|
||||
versionData?: string | VersionData;
|
||||
|
||||
constructor(raw: RedocRawOptions, defaults: RedocRawOptions = {}) {
|
||||
raw = { ...defaults, ...raw };
|
||||
|
@ -351,5 +362,6 @@ export class RedocNormalizedOptions {
|
|||
this.backNavigationPath = raw.backNavigationPath;
|
||||
this.ignoreIncompatibleTypes = argValueToBoolean(raw.ignoreIncompatibleTypes);
|
||||
this.siteTitle = raw.siteTitle;
|
||||
this.versionData = raw.versionData;
|
||||
}
|
||||
}
|
||||
|
|
8
version-data.json
Normal file
8
version-data.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"active": {
|
||||
"apiVersion": "2.0",
|
||||
"resourceVersion": "2023-02-14"
|
||||
},
|
||||
"rootUrl": "https://mongodb.com/docs/atlas/reference/api-resources-spec/v2",
|
||||
"resourceVersions": ["2022-09-09", "2022-10-18", "2023-02-14"]
|
||||
}
|
Loading…
Reference in New Issue
Block a user