Skip to content

Commit

Permalink
feat: add param to override react component config (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
BTOdell authored Sep 8, 2022
1 parent 3f840dd commit 337cd6c
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 10 deletions.
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` |
| 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

0 comments on commit 337cd6c

Please sign in to comment.