diff --git a/package-lock.json b/package-lock.json
index 3f870188cca..5f4905528f4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,7 +6,7 @@
"packages": {
"": {
"name": "@swagger-api/swagger-editor",
- "version": "5.0.0-alpha.9",
+ "version": "5.0.0-alpha.10",
"license": "Apache-2.0",
"dependencies": {
"@asyncapi/avro-schema-parser": "^1.0.1",
@@ -18,7 +18,11 @@
"@emotion/styled": "^11.9.3",
"@mui/material": "^5.9.1",
"@primer/octicons-react": "^17.3.0",
+ "@swagger-api/apidom-core": "^0.36.0",
"@swagger-api/apidom-ls": "^0.36.0",
+ "@swagger-api/apidom-ns-api-design-systems": "^0.36.0",
+ "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.36.0",
+ "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.36.0",
"@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.36.0",
"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.36.0",
"@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.36.0",
diff --git a/package.json b/package.json
index fdddabf9d46..ccc895b6a95 100644
--- a/package.json
+++ b/package.json
@@ -62,7 +62,11 @@
"@emotion/styled": "^11.9.3",
"@mui/material": "^5.9.1",
"@primer/octicons-react": "^17.3.0",
+ "@swagger-api/apidom-core": "^0.36.0",
"@swagger-api/apidom-ls": "^0.36.0",
+ "@swagger-api/apidom-ns-api-design-systems": "^0.36.0",
+ "@swagger-api/apidom-parser-adapter-api-design-systems-json": "^0.36.0",
+ "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": "^0.36.0",
"@swagger-api/apidom-parser-adapter-asyncapi-json-2": "^0.36.0",
"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": "^0.36.0",
"@swagger-api/apidom-parser-adapter-openapi-json-3-1": "^0.36.0",
diff --git a/src/App.jsx b/src/App.jsx
index 9d95f53e914..b5e5ad6da2c 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -17,6 +17,7 @@ import EditorMonacoPlugin from './plugins/editor-monaco/index.js';
import EditorPreviewPlugin from './plugins/editor-preview/index.js';
import EditorPreviewSwaggerUIPlugin from './plugins/editor-preview-swagger-ui/index.js';
import EditorPreviewAsyncAPIPlugin from './plugins/editor-preview-asyncapi/index.js';
+import EditorPreviewApiDesignSystemsPlugin from './plugins/editor-preview-api-design-systems/index.js';
import EditorContentReadOnlyPlugin from './plugins/editor-content-read-only/index.js';
import EditorContentOriginPlugin from './plugins/editor-content-origin/index.js';
import EditorContentTypePlugin from './plugins/editor-content-type/index.js';
@@ -68,6 +69,7 @@ SwaggerEditor.plugins = {
EditorPreview: EditorPreviewPlugin,
EditorPreviewSwaggerUI: EditorPreviewSwaggerUIPlugin,
EditorPreviewAsyncAPI: EditorPreviewAsyncAPIPlugin,
+ EditorPreviewApiDesignSystems: EditorPreviewApiDesignSystemsPlugin,
TopBar: TopBarPlugin,
SplashScreenPlugin,
Layout: LayoutPlugin,
@@ -88,6 +90,7 @@ SwaggerEditor.presets = {
EditorPreviewPlugin,
EditorPreviewSwaggerUIPlugin,
EditorPreviewAsyncAPIPlugin,
+ EditorPreviewApiDesignSystemsPlugin,
TopBarPlugin,
SplashScreenPlugin,
LayoutPlugin,
@@ -109,6 +112,7 @@ SwaggerEditor.presets = {
EditorPreviewPlugin,
EditorPreviewSwaggerUIPlugin,
EditorPreviewAsyncAPIPlugin,
+ EditorPreviewApiDesignSystemsPlugin,
TopBarPlugin,
SplashScreenPlugin,
LayoutPlugin,
diff --git a/src/plugins/editor-content-fixtures/index.js b/src/plugins/editor-content-fixtures/index.js
index 911e451ad3f..7c59e2867e7 100644
--- a/src/plugins/editor-content-fixtures/index.js
+++ b/src/plugins/editor-content-fixtures/index.js
@@ -3,6 +3,7 @@ import selectAsyncAPI240PetstoreJSON from './selectors/selectAsyncAPI240Petstore
import selectOpenAPI20JSON from './selectors/selectOpenAPI20JSON.js';
import selectOpenAPI303JSON from './selectors/selectOpenAPI303JSON.js';
import selectOpenAPI310JSON from './selectors/selectOpenAPI310JSON.js';
+import selectAPIDesignSystemsJSON from './selectors/selectAPIDesignSystemsJSON.js';
const EditorContentFixturesPlugin = () => ({
statePlugins: {
@@ -13,6 +14,7 @@ const EditorContentFixturesPlugin = () => ({
selectOpenAPI20JSON,
selectOpenAPI303JSON,
selectOpenAPI310JSON,
+ selectAPIDesignSystemsJSON,
},
},
},
diff --git a/src/plugins/editor-content-fixtures/selectors/selectAPIDesignSystemsJSON.js b/src/plugins/editor-content-fixtures/selectors/selectAPIDesignSystemsJSON.js
new file mode 100644
index 00000000000..bdd1bd2228f
--- /dev/null
+++ b/src/plugins/editor-content-fixtures/selectors/selectAPIDesignSystemsJSON.js
@@ -0,0 +1,358 @@
+const selectAPIDesignSystemsJSON = () => `{
+ "version": "2021-05-07",
+ "info": {
+ "title": "SmartBear API Guidelines",
+ "description": "A machine and human readable version of the SmartBear API Style Guide aimed at promoting living API Style Governance across various tools and teams, leading to improved API quality.\\nSee the [SmartBear Standards and Guidelines](https://github.com/SmartBear/api-standards-and-guidelines) repo for a traditional view of the static guidelines.\\n"
+ },
+ "principles": [
+ {
+ "iri": "urn:apidesign.systems:principle:robustness",
+ "level": "must"
+ },
+ {
+ "iri": "urn:apidesign.systems:principle:rmm:level2",
+ "level": "must"
+ },
+ {
+ "iri": "urn:apidesign.systems:principle:rmm:level3",
+ "level": "should"
+ }
+ ],
+ "standards": [
+ {
+ "iri": "urn:ietf:rfc:6648",
+ "level": "must"
+ },
+ {
+ "iri": "urn:ietf:rfc:7807",
+ "level": "must"
+ },
+ {
+ "iri": "urn:ietf:rfc:7231",
+ "level": "should"
+ },
+ {
+ "iri": "urn:ietf:rfc:6585",
+ "level": "may"
+ },
+ {
+ "iri": "urn:ietf:rfc:5788",
+ "level": "may"
+ },
+ {
+ "iri": "urn:ietf:draft:http-semantics",
+ "level": "may"
+ }
+ ],
+ "scenarios": [
+ {
+ "description": "SB-API-010 - Only apply standard HTTP methods",
+ "when": [
+ "http",
+ "transaction"
+ ],
+ "then": [
+ {
+ "subject": [
+ "http",
+ "request",
+ "method"
+ ],
+ "level": "may",
+ "values": [
+ "get",
+ "post",
+ "put",
+ "patch",
+ "delete"
+ ]
+ },
+ {
+ "subject": [
+ "http",
+ "request",
+ "header"
+ ],
+ "level": "may",
+ "values": [
+ "Accept",
+ "Accept-Charset",
+ "Authorization",
+ "Content-Language",
+ "Content-Type",
+ "Link",
+ "Prefer"
+ ]
+ },
+ {
+ "subject": [
+ "http",
+ "request",
+ "header",
+ "Content-Type"
+ ],
+ "level": "may",
+ "values": [
+ "application/json",
+ "application/hal+json"
+ ]
+ },
+ {
+ "subject": [
+ "http",
+ "response",
+ "header",
+ "Content-Type"
+ ],
+ "level": "should",
+ "values": [
+ "application/hal+json"
+ ]
+ },
+ {
+ "subject": [
+ "http",
+ "response",
+ "header",
+ "Content-Type"
+ ],
+ "level": "may",
+ "values": [
+ "application/json",
+ "application/hal+json",
+ "application/problem+json"
+ ]
+ }
+ ]
+ },
+ {
+ "description": "GET Methods - Allowed status codes",
+ "when": [
+ "http",
+ "request",
+ "method",
+ "get"
+ ],
+ "then": [
+ {
+ "subject": [
+ "http",
+ "response",
+ "status_code"
+ ],
+ "level": "may",
+ "values": [
+ "200",
+ "304",
+ "400",
+ "401",
+ "403",
+ "404",
+ "405",
+ "422",
+ "429",
+ "500",
+ "501",
+ "503"
+ ]
+ }
+ ]
+ },
+ {
+ "description": "POST Method - Allowed status codes",
+ "when": [
+ "http",
+ "request",
+ "method",
+ "post"
+ ],
+ "then": [
+ {
+ "subject": [
+ "http",
+ "response",
+ "status_code"
+ ],
+ "level": "may",
+ "values": [
+ "200",
+ "201",
+ "202",
+ "400",
+ "401",
+ "403",
+ "404",
+ "405",
+ "409",
+ "415",
+ "422",
+ "429",
+ "500",
+ "501",
+ "503"
+ ]
+ }
+ ]
+ },
+ {
+ "description": "PUT Method - Allowed status codes",
+ "when": [
+ "http",
+ "request",
+ "method",
+ "put"
+ ],
+ "then": [
+ {
+ "subject": [
+ "http",
+ "response",
+ "status_code"
+ ],
+ "level": "may",
+ "values": [
+ "200",
+ "201",
+ "202",
+ "204",
+ "400",
+ "401",
+ "403",
+ "404",
+ "405",
+ "409",
+ "412",
+ "415",
+ "422",
+ "429",
+ "500",
+ "501",
+ "503"
+ ]
+ }
+ ]
+ },
+ {
+ "description": "PATCH Method - Allowed status codes",
+ "when": [
+ "http",
+ "request",
+ "method",
+ "patch"
+ ],
+ "then": [
+ {
+ "subject": [
+ "http",
+ "response",
+ "status_code"
+ ],
+ "level": "may",
+ "values": [
+ "200",
+ "202",
+ "204",
+ "400",
+ "401",
+ "403",
+ "404",
+ "405",
+ "409",
+ "412",
+ "415",
+ "422",
+ "429",
+ "500",
+ "501",
+ "503"
+ ]
+ }
+ ]
+ },
+ {
+ "description": "DELETE Method - Allowed status codes",
+ "when": [
+ "http",
+ "request",
+ "method",
+ "delete"
+ ],
+ "then": [
+ {
+ "subject": [
+ "http",
+ "response",
+ "status_code"
+ ],
+ "level": "may",
+ "values": [
+ "200",
+ "202",
+ "204",
+ "400",
+ "401",
+ "403",
+ "404",
+ "405",
+ "409",
+ "412",
+ "415",
+ "422",
+ "429",
+ "500",
+ "501",
+ "503"
+ ]
+ }
+ ]
+ },
+ {
+ "description": "Client Errors must return \`application/problem+json\`",
+ "when": [
+ "http",
+ "response",
+ "status_code",
+ "client_error"
+ ],
+ "then": [
+ {
+ "subject": [
+ "http",
+ "response",
+ "header",
+ "Content-Type"
+ ],
+ "level": "must",
+ "values": [
+ "application/problem+json"
+ ]
+ }
+ ]
+ },
+ {
+ "description": "Server Errors must return \`application/problem+json\`",
+ "when": [
+ "http",
+ "response",
+ "status_code",
+ "server_error"
+ ],
+ "then": [
+ {
+ "subject": [
+ "http",
+ "response",
+ "header",
+ "Content-Type"
+ ],
+ "level": "must",
+ "values": [
+ "application/problem+json"
+ ]
+ }
+ ]
+ }
+ ]
+}`;
+
+export default selectAPIDesignSystemsJSON;
diff --git a/src/plugins/editor-content-type/actions.js b/src/plugins/editor-content-type/actions.js
index 53d95764196..a4433586c20 100644
--- a/src/plugins/editor-content-type/actions.js
+++ b/src/plugins/editor-content-type/actions.js
@@ -3,6 +3,14 @@ import { detectionRegExp as detectionRegExpAsyncAPIJSON2 } from '@swagger-api/ap
import { detectionRegExp as detectionRegExpAsyncAPIYAML2 } from '@swagger-api/apidom-parser-adapter-asyncapi-yaml-2';
import { detectionRegExp as detectionRegExpOpenAPIJSON31x } from '@swagger-api/apidom-parser-adapter-openapi-json-3-1';
import { detectionRegExp as detectionRegExpOpenAPIYAML31x } from '@swagger-api/apidom-parser-adapter-openapi-yaml-3-1';
+import {
+ detectionRegExp as detectionRegExpApiDesignSystemsJSON,
+ detect as detectAPIDesignSystemsJSON,
+} from '@swagger-api/apidom-parser-adapter-api-design-systems-json';
+import {
+ detectionRegExp as detectionRegExpApiDesignSystemsYAML,
+ detect as detectAPIDesignSystemsYAML,
+} from '@swagger-api/apidom-parser-adapter-api-design-systems-yaml';
/**
* Action types.
@@ -132,6 +140,26 @@ export const detectContentType = (content) => {
return;
}
+ const apiDesignSystemsJSONMatch = content.match(detectionRegExpApiDesignSystemsJSON);
+ if (apiDesignSystemsJSONMatch !== null && (await detectAPIDesignSystemsJSON(content))) {
+ const { groups } = apiDesignSystemsJSONMatch;
+ const version = groups?.version_json;
+ const contentType = `application/vnd.aai.apidesignsystems+json;version=${version}`;
+
+ editorActions.detectContentTypeSuccess({ contentType, content, requestId });
+ return;
+ }
+
+ const apiDesignSystemsYAMLMatch = content.match(detectionRegExpApiDesignSystemsYAML);
+ if (apiDesignSystemsYAMLMatch !== null && (await detectAPIDesignSystemsYAML(content))) {
+ const { groups } = apiDesignSystemsYAMLMatch;
+ const version = groups?.version_json || groups?.version_yaml;
+ const contentType = `application/vnd.aai.apidesignsystems+yaml;version=${version}`;
+
+ editorActions.detectContentTypeSuccess({ contentType, content, requestId });
+ return;
+ }
+
if (fn.isValidJSON(content)) {
const contentType = 'application/json';
diff --git a/src/plugins/editor-content-type/index.js b/src/plugins/editor-content-type/index.js
index 8b1f88d76dc..b569a3e6b12 100644
--- a/src/plugins/editor-content-type/index.js
+++ b/src/plugins/editor-content-type/index.js
@@ -16,6 +16,7 @@ import {
selectIsContentTypeOpenAPI20,
selectIsContentTypeOpenAPI30x,
selectIsContentTypeOpenAPI31x,
+ selectIsContentTypeAPIDesignSystems,
selectInferFileExtensionFromContent,
selectInferFileNameFromContent,
selectInferFileNameWithExtensionFromContent,
@@ -47,6 +48,7 @@ const EditorContentTypePlugin = () => {
selectIsContentTypeOpenAPI20,
selectIsContentTypeOpenAPI30x,
selectIsContentTypeOpenAPI31x,
+ selectIsContentTypeAPIDesignSystems,
selectInferFileExtensionFromContent,
selectInferFileNameFromContent,
selectInferFileNameWithExtensionFromContent,
diff --git a/src/plugins/editor-content-type/selectors.js b/src/plugins/editor-content-type/selectors.js
index 6b26bc9b0e2..465d35dcd9d 100644
--- a/src/plugins/editor-content-type/selectors.js
+++ b/src/plugins/editor-content-type/selectors.js
@@ -46,6 +46,13 @@ export const selectIsContentTypeAsyncAPI2 = createSelector(
}
);
+export const selectIsContentTypeAPIDesignSystems = createSelector(
+ selectContentType,
+ (contentType) => {
+ return contentType !== null && contentType.startsWith('application/vnd.aai.apidesignsystems');
+ }
+);
+
export const selectIsContentFormatJSON = createSelector(selectContentType, (contentType) => {
return (
contentType !== null && (contentType === 'application/json' || contentType.includes('+json'))
diff --git a/src/plugins/editor-preview-api-design-systems/actions.js b/src/plugins/editor-preview-api-design-systems/actions.js
new file mode 100644
index 00000000000..3338bb9d8c8
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/actions.js
@@ -0,0 +1,68 @@
+import ShortUniqueId from 'short-unique-id';
+import { parse as parseJSON } from '@swagger-api/apidom-parser-adapter-api-design-systems-json';
+import { parse as parseYAML } from '@swagger-api/apidom-parser-adapter-api-design-systems-yaml';
+
+/**
+ * Action types.
+ */
+
+export const EDITOR_PREVIEW_ADS_PREVIEW_UNMOUNTED =
+ 'editor_preview_api_design_systems_preview_unmounted';
+
+export const EDITOR_PREVIEW_ADS_PARSE_STARTED = 'editor_preview_api_design_systems_parse_started';
+export const EDITOR_PREVIEW_ADS_PARSE_SUCCESS = 'editor_preview_api_design_systems_parse_success';
+export const EDITOR_PREVIEW_ADS_PARSE_FAILURE = 'editor_preview_api_design_systems_parse_failure';
+
+/**
+ * Action creators.
+ */
+
+export const previewUnmounted = () => ({
+ type: EDITOR_PREVIEW_ADS_PREVIEW_UNMOUNTED,
+});
+
+export const parseStarted = ({ content, contentType, requestId }) => ({
+ type: EDITOR_PREVIEW_ADS_PARSE_STARTED,
+ payload: content,
+ meta: {
+ contentType,
+ requestId,
+ },
+});
+
+export const parseSuccess = ({ parseResult, content, contentType, requestId }) => ({
+ type: EDITOR_PREVIEW_ADS_PARSE_SUCCESS,
+ payload: parseResult,
+ meta: { content, contentType, requestId },
+});
+
+export const parseFailure = ({ error, content, contentType, requestId }) => ({
+ type: EDITOR_PREVIEW_ADS_PARSE_FAILURE,
+ payload: error,
+ error: true,
+ meta: { content, contentType, requestId },
+});
+
+/**
+ * Async thunks.
+ */
+
+export const parse = ({ content, contentType, parserOptions = {} }) => {
+ const uid = new ShortUniqueId({ length: 10 });
+
+ return async (system) => {
+ const { editorPreviewADSActions } = system;
+ const requestId = uid();
+
+ editorPreviewADSActions.parseStarted({ content, contentType, requestId });
+
+ const parseAPIDesignSystemsDefinition = contentType.includes('+json') ? parseJSON : parseYAML;
+
+ try {
+ const parseResult = await parseAPIDesignSystemsDefinition(content, parserOptions);
+ editorPreviewADSActions.parseSuccess({ parseResult, content, contentType, requestId });
+ } catch (error) {
+ editorPreviewADSActions.parseFailure({ error, content, contentType, requestId });
+ }
+ };
+};
diff --git a/src/plugins/editor-preview-api-design-systems/components/EditorPreviewAPIDesignSystems.jsx b/src/plugins/editor-preview-api-design-systems/components/EditorPreviewAPIDesignSystems.jsx
new file mode 100644
index 00000000000..8eb4f729d55
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/EditorPreviewAPIDesignSystems.jsx
@@ -0,0 +1,48 @@
+import React, { useEffect } from 'react';
+import PropTypes from 'prop-types';
+
+const Parsing = () =>
Parsing...
;
+
+const EditorPreviewAPIDesignSystems = ({
+ getComponent,
+ editorPreviewADSActions,
+ editorPreviewADSSelectors,
+}) => {
+ const Main = getComponent('ADSMain', true);
+ const ParseErrors = getComponent('EditorPreviewAPIDesignSystemsParseErrors', true);
+ const isParseInProgress = editorPreviewADSSelectors.selectIsParseInProgress();
+ const isParseSuccess = editorPreviewADSSelectors.selectIsParseSuccess();
+ const isParseFailure = editorPreviewADSSelectors.selectIsParseFailure();
+ const parseError = editorPreviewADSSelectors.selectParseError();
+
+ useEffect(() => {
+ return () => {
+ editorPreviewADSActions.previewUnmounted();
+ };
+ }, [editorPreviewADSActions]);
+
+ return (
+
+ {isParseInProgress && }
+ {isParseSuccess && }
+ {isParseFailure && }
+
+ );
+};
+
+EditorPreviewAPIDesignSystems.propTypes = {
+ getComponent: PropTypes.func.isRequired,
+ editorPreviewADSActions: PropTypes.shape({
+ previewUnmounted: PropTypes.func.isRequired,
+ }).isRequired,
+ editorPreviewADSSelectors: PropTypes.shape({
+ selectIsParseInProgress: PropTypes.func.isRequired,
+ selectIsParseSuccess: PropTypes.func.isRequired,
+ selectIsParseFailure: PropTypes.func.isRequired,
+ selectParseResult: PropTypes.func.isRequired,
+ selectParseError: PropTypes.func.isRequired,
+ selectMainElement: PropTypes.func.isRequired,
+ }).isRequired,
+};
+
+export default EditorPreviewAPIDesignSystems;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Info.jsx b/src/plugins/editor-preview-api-design-systems/components/Info.jsx
new file mode 100644
index 00000000000..08c8d4f1202
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Info.jsx
@@ -0,0 +1,60 @@
+import PropTypes from 'prop-types';
+
+const Info = ({ editorPreviewADSSelectors }) => {
+ const version = editorPreviewADSSelectors.selectVersion();
+ const info = editorPreviewADSSelectors.selectInfo();
+ const principles = editorPreviewADSSelectors.selectPrinciplesCount();
+ const standards = editorPreviewADSSelectors.selectStandardsCount();
+ const scenarios = editorPreviewADSSelectors.selectScenariosCount();
+
+ if (info === null) return null;
+
+ return (
+
+
+
+ {info.title}
+
+
+ {version}
+
+
+ ADS
+
+
+
+
+
+
+
+ {principles} Principles
+
+
+ {standards} Standards
+
+
+ {scenarios} Scenarios
+
+
+
+
+
+
+ );
+};
+
+Info.propTypes = {
+ editorPreviewADSSelectors: PropTypes.shape({
+ selectVersion: PropTypes.func.isRequired,
+ selectInfo: PropTypes.func.isRequired,
+ selectPrinciplesCount: PropTypes.func.isRequired,
+ selectStandardsCount: PropTypes.func.isRequired,
+ selectScenariosCount: PropTypes.func.isRequired,
+ }).isRequired,
+};
+
+export default Info;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Main.jsx b/src/plugins/editor-preview-api-design-systems/components/Main.jsx
new file mode 100644
index 00000000000..ffcbe416210
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Main.jsx
@@ -0,0 +1,30 @@
+import PropTypes from 'prop-types';
+
+const Main = ({ getComponent }) => {
+ const Info = getComponent('ADSInfo', true);
+ const Principles = getComponent('ADSPrinciples', true);
+ const Standards = getComponent('ADSStandards', true);
+ const Scenarios = getComponent('ADSScenarios', true);
+
+ return (
+
+ );
+};
+
+Main.propTypes = {
+ getComponent: PropTypes.func.isRequired,
+};
+
+export default Main;
diff --git a/src/plugins/editor-preview-api-design-systems/components/ParseErrors.jsx b/src/plugins/editor-preview-api-design-systems/components/ParseErrors.jsx
new file mode 100644
index 00000000000..2b29adc87dc
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/ParseErrors.jsx
@@ -0,0 +1,24 @@
+import PropTypes from 'prop-types';
+
+const ParseErrors = ({ error }) => {
+ return (
+
+
+
+
+
+
Invalid API Design Systems definition.
+
Please fix the error: {error.message}
+
+
+
+
+
+ );
+};
+
+ParseErrors.propTypes = {
+ error: PropTypes.shape({ message: PropTypes.string }).isRequired,
+};
+
+export default ParseErrors;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Principle.jsx b/src/plugins/editor-preview-api-design-systems/components/Principle.jsx
new file mode 100644
index 00000000000..43a74620973
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Principle.jsx
@@ -0,0 +1,27 @@
+import PropTypes from 'prop-types';
+
+const Principle = ({ name, iri, level }) => {
+ return (
+
+ |
+ {iri}
+ |
+
+ {level}
+ |
+ {name} |
+
+ );
+};
+
+Principle.propTypes = {
+ name: PropTypes.string,
+ iri: PropTypes.string.isRequired,
+ level: PropTypes.string.isRequired,
+};
+
+Principle.defaultProps = {
+ name: '',
+};
+
+export default Principle;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Principles.jsx b/src/plugins/editor-preview-api-design-systems/components/Principles.jsx
new file mode 100644
index 00000000000..90d08dbb1bb
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Principles.jsx
@@ -0,0 +1,72 @@
+import PropTypes from 'prop-types';
+
+const Principles = ({ editorPreviewADSSelectors, getComponent }) => {
+ const principlesCount = editorPreviewADSSelectors.selectPrinciplesCount();
+ const principles = editorPreviewADSSelectors.selectPrinciples();
+ const Principle = getComponent('ADSPrinciple');
+
+ return (
+
+
+
+
+ {principlesCount} Principles
+
+
+
+
+
+
+
+
Principles guide how decisions in API design and delivery should be made.
+
+
+
+
+
+
+
+
+
+ |
+ Internationalized Resource Identifiers
+ |
+
+ level
+ |
+ Name |
+
+
+
+ {principles.map((principle) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+Principles.propTypes = {
+ getComponent: PropTypes.func.isRequired,
+ editorPreviewADSSelectors: PropTypes.shape({
+ selectPrinciplesCount: PropTypes.func.isRequired,
+ selectPrinciples: PropTypes.func.isRequired,
+ }).isRequired,
+};
+
+export default Principles;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Requirement.jsx b/src/plugins/editor-preview-api-design-systems/components/Requirement.jsx
new file mode 100644
index 00000000000..361611c5893
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Requirement.jsx
@@ -0,0 +1,33 @@
+import PropTypes from 'prop-types';
+import { RequirementElement } from '@swagger-api/apidom-ns-api-design-systems';
+
+const Requirement = ({ editorPreviewADSSelectors, element }) => {
+ const subject = editorPreviewADSSelectors.selectStandardIdentifier({
+ standardIdentifier: element.subject,
+ });
+ const level = editorPreviewADSSelectors.selectRequirementLevel({ requirementElement: element });
+ const values = editorPreviewADSSelectors.selectRequirementValues({ requirementElement: element });
+
+ return (
+
+ | {subject} |
+
+ {level}
+ |
+
+ {values}
+ |
+
+ );
+};
+
+Requirement.propTypes = {
+ element: PropTypes.instanceOf(RequirementElement).isRequired,
+ editorPreviewADSSelectors: PropTypes.shape({
+ selectStandardIdentifier: PropTypes.func.isRequired,
+ selectRequirementLevel: PropTypes.func.isRequired,
+ selectRequirementValues: PropTypes.func.isRequired,
+ }).isRequired,
+};
+
+export default Requirement;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Scenario.jsx b/src/plugins/editor-preview-api-design-systems/components/Scenario.jsx
new file mode 100644
index 00000000000..044b2aa67a1
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Scenario.jsx
@@ -0,0 +1,76 @@
+import PropTypes from 'prop-types';
+import { ScenarioElement } from '@swagger-api/apidom-ns-api-design-systems';
+
+const Scenario = ({ getComponent, editorPreviewADSSelectors, element }) => {
+ const scenarioName = editorPreviewADSSelectors.selectStandardIdentifier({
+ standardIdentifier: element.when,
+ });
+ const description = editorPreviewADSSelectors.selectScenarioDescription({
+ scenarioElement: element,
+ });
+ const requirements = editorPreviewADSSelectors.selectScenarioRequirements({
+ scenarioElement: element,
+ });
+ const Requirement = getComponent('ADSRequirement', true);
+
+ return (
+
+
+
+
+
+ );
+};
+
+Scenario.propTypes = {
+ element: PropTypes.instanceOf(ScenarioElement).isRequired,
+ getComponent: PropTypes.func.isRequired,
+ editorPreviewADSSelectors: PropTypes.shape({
+ selectStandardIdentifier: PropTypes.func.isRequired,
+ selectScenarioDescription: PropTypes.func.isRequired,
+ selectScenarioRequirements: PropTypes.func.isRequired,
+ }).isRequired,
+};
+
+export default Scenario;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Scenarios.jsx b/src/plugins/editor-preview-api-design-systems/components/Scenarios.jsx
new file mode 100644
index 00000000000..c02ad07c9dc
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Scenarios.jsx
@@ -0,0 +1,40 @@
+import PropTypes from 'prop-types';
+
+const Scenarios = ({ getComponent, editorPreviewADSSelectors }) => {
+ const scenariosCount = editorPreviewADSSelectors.selectScenariosCount();
+ const scenarios = editorPreviewADSSelectors.selectScenarios();
+ const Scenario = getComponent('ADSScenario', true);
+
+ return (
+
+
+
+
+
+
+
+ {scenarios.map((scenarioElement) => {
+ const key = editorPreviewADSSelectors.selectStandardIdentifier({
+ standardIdentifier: scenarioElement.when,
+ });
+ return ;
+ })}
+
+
+
+ );
+};
+
+Scenarios.propTypes = {
+ editorPreviewADSSelectors: PropTypes.shape({
+ selectScenariosCount: PropTypes.func.isRequired,
+ selectScenarios: PropTypes.func.isRequired,
+ selectStandardIdentifier: PropTypes.func.isRequired,
+ }).isRequired,
+ getComponent: PropTypes.func.isRequired,
+};
+
+export default Scenarios;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Standard.jsx b/src/plugins/editor-preview-api-design-systems/components/Standard.jsx
new file mode 100644
index 00000000000..ddc79e20774
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Standard.jsx
@@ -0,0 +1,27 @@
+import PropTypes from 'prop-types';
+
+const Standard = ({ name, iri, level }) => {
+ return (
+
+ |
+ {iri}
+ |
+
+ {level}
+ |
+ {name} |
+
+ );
+};
+
+Standard.propTypes = {
+ name: PropTypes.string,
+ iri: PropTypes.string.isRequired,
+ level: PropTypes.string.isRequired,
+};
+
+Standard.defaultProps = {
+ name: '',
+};
+
+export default Standard;
diff --git a/src/plugins/editor-preview-api-design-systems/components/Standards.jsx b/src/plugins/editor-preview-api-design-systems/components/Standards.jsx
new file mode 100644
index 00000000000..360a01a858a
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/Standards.jsx
@@ -0,0 +1,75 @@
+import PropTypes from 'prop-types';
+
+const Standards = ({ editorPreviewADSSelectors, getComponent }) => {
+ const standardsCount = editorPreviewADSSelectors.selectStandardsCount();
+ const standards = editorPreviewADSSelectors.selectStandards();
+ const Standard = getComponent('ADSStandard');
+
+ return (
+
+
+
+
+ {standardsCount} Standards
+
+
+
+
+
+
+
+
+ Standards are industry best practices (e.g. RFCs) that shall influence the rules
+ for API design.
+
+
+
+
+
+
+
+
+
+
+ |
+ Internationalized Resource Identifiers
+ |
+
+ level
+ |
+ Name |
+
+
+
+ {standards.map((principle) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+Standards.propTypes = {
+ getComponent: PropTypes.func.isRequired,
+ editorPreviewADSSelectors: PropTypes.shape({
+ selectStandardsCount: PropTypes.func.isRequired,
+ selectStandards: PropTypes.func.isRequired,
+ }).isRequired,
+};
+
+export default Standards;
diff --git a/src/plugins/editor-preview-api-design-systems/components/_all.scss b/src/plugins/editor-preview-api-design-systems/components/_all.scss
new file mode 100644
index 00000000000..3cdb008a214
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/components/_all.scss
@@ -0,0 +1,22 @@
+.swagger-editor__editor-preview-api-design-systems .summary-pill {
+ background-color: #a004bf !important;
+}
+
+.swagger-editor__editor-preview-api-design-systems .model-box {
+ background: rgba(0,0,0,.1) !important;
+}
+
+.swagger-editor__editor-preview-api-design-systems table.ads-principles tbody tr td:first-of-type {
+ padding-left: 0;
+}
+
+.swagger-editor__editor-preview-api-design-systems .value-pill {
+ background-color: rgb(127, 156, 245);
+ border-bottom-color: rgb(203, 213, 224);
+ border-bottom-left-radius: 4px;
+ color: rgb(255, 255, 255);
+ display: inline-block;
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 12px;
+ font-weight: 700;
+}
diff --git a/src/plugins/editor-preview-api-design-systems/index.js b/src/plugins/editor-preview-api-design-systems/index.js
new file mode 100644
index 00000000000..b7c39e08012
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/index.js
@@ -0,0 +1,100 @@
+import { previewUnmounted, parse, parseStarted, parseSuccess, parseFailure } from './actions.js';
+import { detectContentTypeSuccess as detectContentTypeSuccessWrap } from './wrap-actions.js';
+import {
+ selectParseStatus,
+ selectIsParseInProgress,
+ selectIsParseFailure,
+ selectIsParseSuccess,
+ selectParseResult,
+ selectParseError,
+ selectMainElement,
+ selectVersion,
+ selectInfo,
+ selectPrinciplesCount,
+ selectStandardsCount,
+ selectScenariosCount,
+ selectPrinciples,
+ selectStandards,
+ selectScenarios,
+ selectStandardIdentifier,
+ selectScenarioDescription,
+ selectScenarioRequirements,
+ selectRequirementLevel,
+ selectRequirementValues,
+} from './selectors.js';
+import reducers from './reducers.js';
+import Main from './components/Main.jsx';
+import Info from './components/Info.jsx';
+import Principles from './components/Principles.jsx';
+import Principle from './components/Principle.jsx';
+import Standards from './components/Standards.jsx';
+import Standard from './components/Standard.jsx';
+import Scenarios from './components/Scenarios.jsx';
+import Scenario from './components/Scenario.jsx';
+import Requirement from './components/Requirement.jsx';
+import EditorPreviewAPIDesignSystems from './components/EditorPreviewAPIDesignSystems.jsx';
+import ParseErrors from './components/ParseErrors.jsx';
+import EditorPreviewWrapper from './wrap-components/EditorPreviewWrapper.jsx';
+
+const EditorPreviewApiDesignSystemsPlugin = () => {
+ return {
+ components: {
+ ADSMain: Main,
+ ADSInfo: Info,
+ ADSPrinciples: Principles,
+ ADSPrinciple: Principle,
+ ADSStandards: Standards,
+ ADSStandard: Standard,
+ ADSScenarios: Scenarios,
+ ADSScenario: Scenario,
+ ADSRequirement: Requirement,
+ EditorPreviewAPIDesignSystems,
+ EditorPreviewAPIDesignSystemsParseErrors: ParseErrors,
+ },
+ wrapComponents: {
+ EditorPreviewPane: EditorPreviewWrapper,
+ },
+ statePlugins: {
+ editor: {
+ wrapActions: {
+ detectContentTypeSuccess: detectContentTypeSuccessWrap,
+ },
+ },
+ editorPreviewADS: {
+ actions: {
+ previewUnmounted,
+
+ parse,
+ parseStarted,
+ parseSuccess,
+ parseFailure,
+ },
+ selectors: {
+ selectParseStatus,
+ selectIsParseInProgress,
+ selectIsParseSuccess,
+ selectIsParseFailure,
+ selectParseResult,
+ selectParseError,
+ selectMainElement,
+ selectVersion,
+ selectInfo,
+ selectPrinciplesCount,
+ selectStandardsCount,
+ selectScenariosCount,
+ selectPrinciples,
+ selectStandards,
+ selectScenarios,
+ selectStandardIdentifier,
+ selectScenarioDescription,
+ selectScenarioRequirements,
+ selectRequirementLevel,
+ selectRequirementValues,
+ },
+ reducers,
+ },
+ },
+ };
+};
+
+export default EditorPreviewApiDesignSystemsPlugin;
diff --git a/src/plugins/editor-preview-api-design-systems/namespace.js b/src/plugins/editor-preview-api-design-systems/namespace.js
new file mode 100644
index 00000000000..3c7e8314838
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/namespace.js
@@ -0,0 +1,6 @@
+import { createNamespace } from '@swagger-api/apidom-core';
+import namespace from '@swagger-api/apidom-ns-api-design-systems';
+
+const apiDesignSystemsNamespace = createNamespace(namespace);
+
+export default apiDesignSystemsNamespace;
diff --git a/src/plugins/editor-preview-api-design-systems/reducers.js b/src/plugins/editor-preview-api-design-systems/reducers.js
new file mode 100644
index 00000000000..bd0c58aebea
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/reducers.js
@@ -0,0 +1,89 @@
+import { toString } from '@swagger-api/apidom-core';
+
+import apiDesignSystemsNamespace from './namespace.js';
+import {
+ EDITOR_PREVIEW_ADS_PREVIEW_UNMOUNTED,
+ EDITOR_PREVIEW_ADS_PARSE_STARTED,
+ EDITOR_PREVIEW_ADS_PARSE_SUCCESS,
+ EDITOR_PREVIEW_ADS_PARSE_FAILURE,
+} from './actions.js';
+
+export const IDLE_STATUS = 'idle';
+export const PARSING_STATUS = 'parsing';
+export const SUCCESS_STATUS = 'success';
+export const FAILURE_STATUS = 'failure';
+
+export const initialState = {
+ parseStatus: IDLE_STATUS,
+ parseRequestId: null,
+ parseResult: null,
+ parseError: null,
+};
+
+/**
+ * Case reducers modeled as finite state machine.
+ */
+
+const previewUnmountedReducer = (state) => {
+ const { parseStatus, parseRequestId, parseResult, parseErrors } = initialState;
+
+ return state.merge({
+ parseStatus,
+ parseRequestId,
+ parseResult,
+ parseErrors,
+ });
+};
+
+const parseStartedReducer = (state, action) => {
+ return state.merge({
+ parseStatus: PARSING_STATUS,
+ parseRequestId: action.meta.requestId,
+ });
+};
+
+const parseSuccessReducer = (state, action) => {
+ const status = state.get('parseStatus') || IDLE_STATUS;
+ const requestId = state.get('parseRequestId');
+
+ if (status === PARSING_STATUS && requestId === action.meta.requestId) {
+ return state.merge({
+ parseStatus: SUCCESS_STATUS,
+ parseRequestId: null,
+ parseResult: toString(action.payload, apiDesignSystemsNamespace),
+ parseErrors: null,
+ });
+ }
+
+ return state;
+};
+
+const parseFailureReducer = (state, action) => {
+ const status = state.get('parseStatus') || IDLE_STATUS;
+ const requestId = state.get('parseRequestId');
+
+ if (status === PARSING_STATUS && requestId === action.meta.requestId) {
+ return state.merge({
+ parseStatus: FAILURE_STATUS,
+ parseRequestId: null,
+ parseResult: null,
+ parseErrors: action.payload,
+ });
+ }
+
+ return state;
+};
+
+/**
+ * Root reducer for this plugin.
+ */
+
+const reducers = {
+ [EDITOR_PREVIEW_ADS_PREVIEW_UNMOUNTED]: previewUnmountedReducer,
+
+ [EDITOR_PREVIEW_ADS_PARSE_STARTED]: parseStartedReducer,
+ [EDITOR_PREVIEW_ADS_PARSE_SUCCESS]: parseSuccessReducer,
+ [EDITOR_PREVIEW_ADS_PARSE_FAILURE]: parseFailureReducer,
+};
+
+export default reducers;
diff --git a/src/plugins/editor-preview-api-design-systems/selectors.js b/src/plugins/editor-preview-api-design-systems/selectors.js
new file mode 100644
index 00000000000..9369f0fb1c5
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/selectors.js
@@ -0,0 +1,161 @@
+import { createSelector } from 'reselect';
+import { from, toValue, isStringElement, isArrayElement } from '@swagger-api/apidom-core';
+import {
+ isMainElement,
+ isInfoElement,
+ isPrincipleElement,
+ isStandardElement,
+ isScenarioElement,
+ isStandardIdentifierElement,
+ isRequirementLevelElement,
+} from '@swagger-api/apidom-ns-api-design-systems';
+
+import apiDesignSystemsNamespace from './namespace.js';
+import { initialState, FAILURE_STATUS, PARSING_STATUS, SUCCESS_STATUS } from './reducers.js';
+
+const selectState = (state) => state;
+
+export const selectParseResult = createSelector(selectState, (state) => {
+ const parseResult = state.get('parseResult', initialState.parseResult);
+
+ if (typeof parseResult !== 'string') {
+ return null;
+ }
+
+ return from(parseResult, apiDesignSystemsNamespace);
+});
+
+export const selectParseError = createSelector(selectState, (state) => {
+ return state.get('parseError', initialState.parseResult);
+});
+
+export const selectParseStatus = (state) => state.get('parseStatus') || initialState.parseStatus;
+
+export const selectIsParseInProgress = createSelector(
+ selectParseStatus,
+ selectParseResult,
+ selectParseError,
+ (parseStatus, parseResult, parseErrors) => {
+ return parseStatus === PARSING_STATUS && parseResult === null && parseErrors === null;
+ }
+);
+
+export const selectIsParseSuccess = createSelector(
+ selectParseStatus,
+ (parseStatus) => parseStatus === SUCCESS_STATUS
+);
+
+export const selectIsParseFailure = createSelector(
+ selectParseStatus,
+ (parseStatus) => parseStatus === FAILURE_STATUS
+);
+
+export const selectMainElement = createSelector(selectParseResult, (parseResult) => {
+ if (parseResult === null) return null;
+
+ const { result } = parseResult;
+
+ return isMainElement(result) ? result : null;
+});
+
+export const selectVersion = createSelector(selectMainElement, (mainElement) => {
+ if (mainElement === null) return null;
+
+ const { version } = mainElement;
+
+ return isStringElement(version) ? toValue(version) : '2021-05-07';
+});
+
+export const selectInfo = createSelector(selectMainElement, (mainElement) => {
+ if (mainElement === null) return null;
+
+ const { info } = mainElement;
+
+ return isInfoElement(info) ? toValue(info) : null;
+});
+
+export const selectPrinciplesCount = createSelector(selectMainElement, (mainElement) => {
+ if (mainElement === null) return null;
+
+ const { principles } = mainElement;
+
+ return isArrayElement(principles) ? principles.length : 0;
+});
+
+export const selectStandardsCount = createSelector(selectMainElement, (mainElement) => {
+ if (mainElement === null) return null;
+
+ const { standards } = mainElement;
+
+ return isArrayElement(standards) ? standards.length : 0;
+});
+
+export const selectScenariosCount = createSelector(selectMainElement, (mainElement) => {
+ if (mainElement === null) return null;
+
+ const { scenarios } = mainElement;
+
+ return isArrayElement(scenarios) ? scenarios.length : 0;
+});
+
+export const selectPrinciples = createSelector(selectMainElement, (mainElement) => {
+ if (mainElement === null) return [];
+
+ const { principles } = mainElement;
+
+ if (!isArrayElement(principles)) return [];
+
+ return principles.filter(isPrincipleElement).toValue();
+});
+
+export const selectStandards = createSelector(selectMainElement, (mainElement) => {
+ if (mainElement === null) return [];
+
+ const { standards } = mainElement;
+
+ if (!isArrayElement(standards)) return [];
+
+ return standards.filter(isStandardElement).toValue();
+});
+
+export const selectScenarios = createSelector(selectMainElement, (mainElement) => {
+ if (mainElement === null) return [];
+
+ const { scenarios } = mainElement;
+
+ if (!isArrayElement(scenarios)) return [];
+
+ return scenarios.filter(isScenarioElement).elements;
+});
+
+export const selectStandardIdentifier = (state, { standardIdentifier }) => {
+ if (!isStandardIdentifierElement(standardIdentifier)) return '[]';
+
+ return `[${String(toValue(standardIdentifier)).replaceAll(',', ' > ')}]`;
+};
+
+export const selectScenarioDescription = (state, { scenarioElement }) => {
+ if (!isScenarioElement(scenarioElement)) return '';
+ if (!isStringElement(scenarioElement.description)) return '';
+
+ return toValue(scenarioElement.description);
+};
+
+export const selectScenarioRequirements = (state, { scenarioElement }) => {
+ if (!isScenarioElement(scenarioElement)) return [];
+ if (!isArrayElement(scenarioElement.then)) return [];
+
+ return scenarioElement.then.content;
+};
+
+export const selectRequirementLevel = (state, { requirementElement }) => {
+ if (!isRequirementLevelElement(requirementElement.level)) return 'unknown';
+
+ return toValue(requirementElement.level);
+};
+
+export const selectRequirementValues = (state, { requirementElement }) => {
+ if (!isArrayElement(requirementElement.values)) return 'unknown';
+
+ return String(toValue(requirementElement.values)).replaceAll(',', ', ');
+};
diff --git a/src/plugins/editor-preview-api-design-systems/wrap-actions.js b/src/plugins/editor-preview-api-design-systems/wrap-actions.js
new file mode 100644
index 00000000000..e7c0b02437d
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/wrap-actions.js
@@ -0,0 +1,16 @@
+import createSafeActionWrapper from '../../utils/create-safe-action-wrapper.js';
+
+// eslint-disable-next-line import/prefer-default-export
+export const detectContentTypeSuccess = createSafeActionWrapper(
+ (oriAction, system) =>
+ ({ content }) => {
+ const { editorSelectors, editorPreviewADSActions } = system;
+
+ if (editorSelectors.selectIsContentTypeAPIDesignSystems()) {
+ const contentType = editorSelectors.selectContentType();
+ const parserOptions = {};
+
+ editorPreviewADSActions.parse({ content, contentType, parserOptions });
+ }
+ }
+);
diff --git a/src/plugins/editor-preview-api-design-systems/wrap-components/EditorPreviewWrapper.jsx b/src/plugins/editor-preview-api-design-systems/wrap-components/EditorPreviewWrapper.jsx
new file mode 100644
index 00000000000..c7610b80e2b
--- /dev/null
+++ b/src/plugins/editor-preview-api-design-systems/wrap-components/EditorPreviewWrapper.jsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const EditorPreviewWrapper = (Original, system) => {
+ const EditorPreview = ({ editorSelectors, getComponent }) => {
+ const EditorPreviewAPIDesignSystems = getComponent('EditorPreviewAPIDesignSystems', true);
+
+ return editorSelectors.selectIsContentTypeAPIDesignSystems() ? (
+
+ ) : (
+ // eslint-disable-line react/jsx-props-no-spreading
+ );
+ };
+
+ EditorPreview.propTypes = {
+ editorSelectors: PropTypes.oneOfType([
+ PropTypes.shape({
+ selectIsContentTypeAPIDesignSystems: PropTypes.func.isRequired,
+ }),
+ ]).isRequired,
+ getComponent: PropTypes.func.isRequired,
+ };
+
+ return EditorPreview;
+};
+
+export default EditorPreviewWrapper;
diff --git a/src/plugins/editor-preview-asyncapi/reducers.js b/src/plugins/editor-preview-asyncapi/reducers.js
index 20d31a92e41..b5807e774a6 100644
--- a/src/plugins/editor-preview-asyncapi/reducers.js
+++ b/src/plugins/editor-preview-asyncapi/reducers.js
@@ -65,10 +65,11 @@ const parseRefErrorsReducer = (action) => {
*/
const previewUnmountedReducer = (state) => {
- const { parseStatus, parseResult, parseErrors } = initialState;
+ const { parseStatus, parseRequestId, parseResult, parseErrors } = initialState;
return state.merge({
parseStatus,
+ parseRequestId,
parseResult,
parseErrors,
});
diff --git a/src/plugins/editor-preview/components/EditorPreviewFallback.jsx b/src/plugins/editor-preview/components/EditorPreviewFallback.jsx
index 4c89772a8e2..20b2acfca96 100644
--- a/src/plugins/editor-preview/components/EditorPreviewFallback.jsx
+++ b/src/plugins/editor-preview/components/EditorPreviewFallback.jsx
@@ -1,5 +1,5 @@
const EditorPreviewFallback = () => (
-
+
diff --git a/src/plugins/top-bar/components/EditMenu/EditMenu.jsx b/src/plugins/top-bar/components/EditMenu/EditMenu.jsx
index d957ff8df50..15426218b91 100644
--- a/src/plugins/top-bar/components/EditMenu/EditMenu.jsx
+++ b/src/plugins/top-bar/components/EditMenu/EditMenu.jsx
@@ -34,6 +34,10 @@ const EditMenu = (props) => {
'TopBarEditMenuLoadOpenAPI31FixtureMenuItem',
true
);
+ const LoadAPIDesignSystemsFixtureMenuItem = getComponent(
+ 'TopBarEditMenuLoadAPIDesignSystemsFixtureMenuItem',
+ true
+ );
const editMenuHandler = useRef(null);
const handleClearClick = useCallback(() => {
@@ -63,6 +67,9 @@ const EditMenu = (props) => {
const handleLoadAsyncAPI24PetstoreFixtureClick = useCallback(() => {
editMenuHandler.current.loadAsyncAPI24PetstoreFixture();
}, []);
+ const loadAPIDesignSystemsFixtureClick = useCallback(() => {
+ editMenuHandler.current.loadAPIDesignSystemsFixture();
+ }, []);
return (
<>
@@ -79,6 +86,7 @@ const EditMenu = (props) => {
+
>
);
diff --git a/src/plugins/top-bar/components/EditMenu/EditMenuHandler.jsx b/src/plugins/top-bar/components/EditMenu/EditMenuHandler.jsx
index c7a460a0caa..9f8c96264c7 100644
--- a/src/plugins/top-bar/components/EditMenu/EditMenuHandler.jsx
+++ b/src/plugins/top-bar/components/EditMenu/EditMenuHandler.jsx
@@ -46,6 +46,10 @@ const EditMenuHandler = forwardRef((props, ref) => {
const content = editorContentFixturesSelectors.selectAsyncAPI240PetstoreJSON();
editorActions.setContent(content, 'fixture-load');
},
+ loadAPIDesignSystemsFixture() {
+ const content = editorContentFixturesSelectors.selectAPIDesignSystemsJSON();
+ editorActions.setContent(content, 'fixture-load');
+ },
}));
return (
@@ -68,6 +72,7 @@ EditMenuHandler.propTypes = {
selectOpenAPI310JSON: PropTypes.func.isRequired,
selectAsyncAPI240JSON: PropTypes.func.isRequired,
selectAsyncAPI240PetstoreJSON: PropTypes.func.isRequired,
+ selectAPIDesignSystemsJSON: PropTypes.func.isRequired,
}).isRequired,
};
diff --git a/src/plugins/top-bar/components/EditMenu/items/LoadAPIDesignSystemsMenuItem.jsx b/src/plugins/top-bar/components/EditMenu/items/LoadAPIDesignSystemsMenuItem.jsx
new file mode 100644
index 00000000000..a1553a5c890
--- /dev/null
+++ b/src/plugins/top-bar/components/EditMenu/items/LoadAPIDesignSystemsMenuItem.jsx
@@ -0,0 +1,23 @@
+import PropTypes from 'prop-types';
+
+const LoadAPIDesignSystemsFixtureMenuItem = ({ getComponent, onClick, children }) => {
+ const DropdownMenuItem = getComponent('DropdownMenuItem');
+
+ return (
+
+ {children || 'Load API Design Systems Fixture'}
+
+ );
+};
+
+LoadAPIDesignSystemsFixtureMenuItem.propTypes = {
+ getComponent: PropTypes.func.isRequired,
+ children: PropTypes.node,
+ onClick: PropTypes.func.isRequired,
+};
+
+LoadAPIDesignSystemsFixtureMenuItem.defaultProps = {
+ children: null,
+};
+
+export default LoadAPIDesignSystemsFixtureMenuItem;
diff --git a/src/plugins/top-bar/index.js b/src/plugins/top-bar/index.js
index 65c7cc9b59b..3bf4f8bf9f8 100644
--- a/src/plugins/top-bar/index.js
+++ b/src/plugins/top-bar/index.js
@@ -18,6 +18,7 @@ import LoadAsyncAPI24PetstoreFixtureMenuItem from './components/EditMenu/items/L
import LoadOpenAPI20FixtureMenuItem from './components/EditMenu/items/LoadOpenAPI20FixtureMenuItem.jsx';
import LoadOpenAPI30FixtureMenuItem from './components/EditMenu/items/LoadOpenAPI30FixtureMenuItem.jsx';
import LoadOpenAPI31FixtureMenuItem from './components/EditMenu/items/LoadOpenAPI31FixtureMenuItem.jsx';
+import LoadAPIDesignSystemsFixtureMenuItem from './components/EditMenu/items/LoadAPIDesignSystemsMenuItem.jsx';
import OpenAPI3GenerateServerMenu from './components/GenerateServerMenu/OpenAPI3GenerateServerMenu.jsx';
import OpenAPI3GenerateClientMenu from './components/GenerateServerMenu/OpenAPI3GenerateClientMenu.jsx';
import OpenAPI2GenerateServerMenu from './components/GenerateServerMenu/OpenAPI2GenerateServerMenu.jsx';
@@ -152,6 +153,7 @@ const TopBarPlugin = () => ({
TopBarEditMenuLoadOpenAPI20FixtureMenuItem: LoadOpenAPI20FixtureMenuItem,
TopBarEditMenuLoadOpenAPI30FixtureMenuItem: LoadOpenAPI30FixtureMenuItem,
TopBarEditMenuLoadOpenAPI31FixtureMenuItem: LoadOpenAPI31FixtureMenuItem,
+ TopBarEditMenuLoadAPIDesignSystemsFixtureMenuItem: LoadAPIDesignSystemsFixtureMenuItem,
TopBarOpenAPI3GenerateServerMenu: OpenAPI3GenerateServerMenu,
TopBarOpenAPI3GenerateClientMenu: OpenAPI3GenerateClientMenu,
diff --git a/src/styles/main.scss b/src/styles/main.scss
index d32267383d4..d0555a3304d 100644
--- a/src/styles/main.scss
+++ b/src/styles/main.scss
@@ -6,6 +6,7 @@
@import '../plugins/editor-textarea/components/all';
@import '../plugins/editor-monaco/components/all';
@import '../plugins/editor-preview-asyncapi/components/all';
+@import '../plugins/editor-preview-api-design-systems/components/all';
.ReactModalPortal {
@import './modal';