Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add param to override react component config #363

Merged
merged 5 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.idea/
.DS_Store
node_modules
test/output
output
sample
coverage
coverage
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ npm install -g @asyncapi/generator

## Supported parameters

| Name | Description | Required | Default | Allowed values | Example |
| Name | Description | Required | Default | Allowed values | Example |
|---|---|---|---|---|---|
| sidebarOrganization | Defines how the sidebar should be organized. Set its value to `byTagsNoRoot` to categorize operations by operations tags. Set its value to `byTags` when you have tags on a root level. These tags are used to model tags navigation and need to have the same tags in operations. | No | undefined | `byTags`, `byTagsNoRoot` | `byTagsNoRoot` |
| baseHref | Sets the base URL for links and forms. | No | `/` | *Any* | `/docs` |
| version | Override the version of your application provided under `info.version` location in the specification file. | No | Version is taken from the spec file. | *Any* ([See Semver versionning](https://semver.org/)) | `1.0.0` |
| version | Override the version of your application provided under `info.version` location in the specification file. | No | Version is taken from the spec file. | *Any* ([See Semver versioning](https://semver.org/)) | `1.0.0` |
BTOdell marked this conversation as resolved.
Show resolved Hide resolved
| singleFile | Set output into one html-file with styles and scripts inside | No | `false` | `true`,`false` | `true` |
| outFilename | The filename of the output file. | No | `index.html` | *Any* | `asyncapi.html` |
| pdf | Generates output HTML as PDF | No | `false` | `true,false` | `false` |
| config | Inline stringified JSON or a path to a JSON file to override default React component config. The config override is merged with the default config using the [JSON Merge Patch](https://tools.ietf.org/html/rfc7386) algorithm. | No | `{ "show": { "sidebar": true }, "sidebar": { "showOperations": "byDefault" } }` | [JSON config for the React component](https://github.com/asyncapi/asyncapi-react/blob/next/docs/configuration/config-modification.md#definition) | `{"show":{"sidebar":false}}` |

> **NOTE**: If you only generate an HTML website, set the environment variable `PUPPETEER_SKIP_CHROMIUM_DOWNLOAD` to `true` and the generator will skip downloading chromium.

Expand Down
50 changes: 47 additions & 3 deletions filters/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,59 @@ const { AsyncAPIDocument } = require('@asyncapi/parser');

const filter = module.exports;

function isJsonObject(o) {
return o && typeof o === 'object' && !Array.isArray(o);
}

/**
* Performs a recursive deep merge while assuming only simple JSON types are used.
*/
function mergeInto(from, to) {
for (const key in from) {
if (!Object.prototype.hasOwnProperty.call(from, key)) {
continue;
}
if (isJsonObject(from[key])) {
if (!isJsonObject(to[key])) {
to[key] = {};
}
mergeInto(from[key], to[key]);
} else {
// Override with non-object JSON value
to[key] = from[key];
}
}
}

/**
* Prepares configuration for component.
*/
function prepareConfiguration(params = {}) {
const config = { show: { sidebar: true }, sidebar: { showOperations: 'byDefault' } };
// Apply config override
if (params.config) {
let configOverride;
try {
// Attempt to parse inline stringified JSON
configOverride = JSON.parse(params.config);
} catch (jsonErr) {
// Failed to parse JSON string...
try {
// Attempt to read as JSON file and parse contents
configOverride = JSON.parse(fs.readFileSync(params.config, "utf8"));
} catch (err) {
console.error("Failed to parse config override JSON", jsonErr, err);
throw err;
}
}
if (isJsonObject(configOverride)) {
mergeInto(configOverride, config);
}
}
// Apply explicit config properties
if (params.sidebarOrganization === 'byTags') {
config.sidebar.showOperations = 'bySpecTags';
}
if (params.sidebarOrganization === 'byTagsNoRoot') {
} else if (params.sidebarOrganization === 'byTagsNoRoot') {
config.sidebar.showOperations = 'byOperationsTags';
}
return config;
Expand Down Expand Up @@ -59,7 +103,7 @@ function includeFile(pathFile) {
filter.includeFile = includeFile;

/**
* Stringifies the specification with escaping circular refs
* Stringifies the specification with escaping circular refs
* and annotates that specification is parsed.
*/
function stringifySpec(asyncapi) {
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@
"pdf": {
"description": "Set to `true` to get index.pdf generated next to your index.html",
"default": false
},
"config": {
"description": "Stringified JSON or a path to a JSON file to override the default React component config. The config override is merged with the default config using the [JSON Merge Patch](https://tools.ietf.org/html/rfc7386) algorithm.",
"default": "",
"required": false
}
},
"generator": ">=1.8.27 <2.0.0",
Expand Down
24 changes: 20 additions & 4 deletions test/filters/all.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { hljs } from '@asyncapi/react-component';
import { AsyncAPIDocument } from "@asyncapi/parser";

import {
import {
includeFile,
loadLanguagesConfig,
stringifySpec,
Expand Down Expand Up @@ -56,12 +56,12 @@ describe('Filters', () => {
}
schema.properties.bar = schema;
const doc = new AsyncAPIDocument({ asyncapi: '2.0.0', components: { schemas: { dummySchema: schema } }});

const expected = `{"asyncapi":"2.0.0","components":{"schemas":{"dummySchema":{"type":"object","properties":{"foo":{"type":"string","x-parser-schema-id":"<anonymous-schema-1>"},"bar":"$ref:$.components.schemas.dummySchema"},"x-parser-schema-id":"dummySchema","x-parser-circular-props":["bar"]}}},"x-parser-spec-parsed":true,"x-parser-spec-stringified":true}`;
const expectedParsed = {
asyncapi: '2.0.0',
components: {
schemas: {
components: {
schemas: {
dummySchema: {
type: 'object',
properties: {
Expand Down Expand Up @@ -108,6 +108,22 @@ describe('Filters', () => {
const result = stringifyConfiguration(params);
expect(result).toEqual(expected);
});

it('should allow override of react component config', async () => {
const params = { config: '{"show":{"sidebar":false}}' };
const expected = '{"show":{"sidebar":false},"sidebar":{"showOperations":"byDefault"}}';

const result = stringifyConfiguration(params);
expect(result).toEqual(expected);
});

it('should allow override of nested react component config', async () => {
const params = { config: '{"show":{"operations":false}}' };
const expected = '{"show":{"sidebar":true,"operations":false},"sidebar":{"showOperations":"byDefault"}}';

const result = stringifyConfiguration(params);
expect(result).toEqual(expected);
});
});

describe('.renderSpec', () => {
Expand Down