├── .agignore ├── .browserslistrc ├── .commitlintrc.json ├── .dockerignore ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ ├── Feature_request.md │ └── Support.md ├── dependabot.yaml ├── lock.yml ├── pull_request_template.md └── workflows │ ├── codeql.yml │ ├── dependabot-merge.yml │ ├── docker-build-push.yml │ ├── docker-image-check.yml │ ├── nodejs.yml │ ├── release-swagger-ui-react.yml │ └── release-swagger-ui.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .lintstagedrc ├── .npmignore ├── .npmrc ├── .nvmrc ├── .prettierrc.yaml ├── .releaserc ├── Dockerfile ├── LICENSE ├── NOTICE ├── README.md ├── SECURITY.md ├── babel.config.js ├── composer.json ├── config ├── .eslintrc └── jest │ ├── jest.artifact.config.js │ └── jest.unit.config.js ├── cypress.config.js ├── dev-helpers ├── dev-helper-initializer.js ├── index.html ├── oauth2-redirect.html └── style.css ├── dist ├── favicon-16x16.png ├── favicon-32x32.png ├── index.css ├── index.html ├── oauth2-redirect.html ├── swagger-initializer.js ├── swagger-ui-bundle.js ├── swagger-ui-es-bundle-core.js ├── swagger-ui-es-bundle.js ├── swagger-ui-standalone-preset.js ├── swagger-ui.css └── swagger-ui.js ├── docker ├── configurator │ ├── helpers.js │ ├── index.js │ ├── oauth.js │ ├── translator.js │ └── variables.js ├── cors.conf ├── default.conf.template ├── docker-entrypoint.d │ └── 40-swagger-ui.sh └── embedding.conf ├── flavors └── swagger-ui-react │ ├── README.md │ ├── dist │ └── .npmrc │ ├── index.jsx │ └── release │ ├── create-manifest.js │ ├── run.sh │ └── template.json ├── package-lock.json ├── package.json ├── release ├── .release-it.json ├── check-for-breaking-changes.sh └── get-changelog.sh ├── snapcraft.yaml ├── src ├── .eslintrc ├── core │ ├── assets │ │ └── rolling-load.svg │ ├── components │ │ ├── app.jsx │ │ ├── auth │ │ │ ├── api-key-auth.jsx │ │ │ ├── auth-item.jsx │ │ │ ├── authorization-popup.jsx │ │ │ ├── authorize-btn.jsx │ │ │ ├── authorize-operation-btn.jsx │ │ │ ├── auths.jsx │ │ │ ├── basic-auth.jsx │ │ │ ├── error.jsx │ │ │ └── oauth2.jsx │ │ ├── clear.jsx │ │ ├── contact.jsx │ │ ├── content-type.jsx │ │ ├── copy-to-clipboard-btn.jsx │ │ ├── curl.jsx │ │ ├── debug.jsx │ │ ├── deep-link.jsx │ │ ├── errors.jsx │ │ ├── example.jsx │ │ ├── examples-select-value-retainer.jsx │ │ ├── examples-select.jsx │ │ ├── execute.jsx │ │ ├── footer.jsx │ │ ├── headers.jsx │ │ ├── info.jsx │ │ ├── initialized-input.jsx │ │ ├── jump-to-path.jsx │ │ ├── layout-utils.jsx │ │ ├── layouts │ │ │ ├── base.jsx │ │ │ └── xpane.jsx │ │ ├── license.jsx │ │ ├── live-response.jsx │ │ ├── online-validator-badge.jsx │ │ ├── openapi-version.jsx │ │ ├── operation-extension-row.jsx │ │ ├── operation-extensions.jsx │ │ ├── operation-summary-method.jsx │ │ ├── operation-summary-path.jsx │ │ ├── operation-summary.jsx │ │ ├── operation-tag.jsx │ │ ├── operation.jsx │ │ ├── operations.jsx │ │ ├── overview.jsx │ │ ├── param-body.jsx │ │ ├── parameter-extension.jsx │ │ ├── parameter-include-empty.jsx │ │ ├── parameter-row.jsx │ │ ├── parameters │ │ │ ├── index.js │ │ │ └── parameters.jsx │ │ ├── property.jsx │ │ ├── providers │ │ │ ├── README.md │ │ │ └── markdown.jsx │ │ ├── response-body.jsx │ │ ├── response-extension.jsx │ │ ├── response.jsx │ │ ├── responses.jsx │ │ ├── svg-assets.jsx │ │ ├── system-wrapper.jsx │ │ ├── try-it-out-button.jsx │ │ ├── version-pragma-filter.jsx │ │ └── version-stamp.jsx │ ├── config │ │ ├── defaults.js │ │ ├── factorization │ │ │ ├── inline-plugin.js │ │ │ └── system.js │ │ ├── index.js │ │ ├── merge.js │ │ ├── sources │ │ │ ├── query.js │ │ │ ├── runtime.js │ │ │ └── url.js │ │ └── type-cast │ │ │ ├── index.js │ │ │ ├── mappings.js │ │ │ └── type-casters │ │ │ ├── array.js │ │ │ ├── boolean.js │ │ │ ├── dom-node.js │ │ │ ├── filter.js │ │ │ ├── function.js │ │ │ ├── nullable-array.js │ │ │ ├── nullable-function.js │ │ │ ├── nullable-string.js │ │ │ ├── number.js │ │ │ ├── object.js │ │ │ ├── sorter.js │ │ │ ├── string.js │ │ │ ├── syntax-highlight.js │ │ │ └── undefined-string.js │ ├── containers │ │ ├── OperationContainer.jsx │ │ ├── authorize-btn.jsx │ │ ├── filter.jsx │ │ └── info.jsx │ ├── index.js │ ├── oauth2-authorize.js │ ├── plugins │ │ ├── auth │ │ │ ├── actions.js │ │ │ ├── components │ │ │ │ ├── lock-auth-icon.jsx │ │ │ │ └── unlock-auth-icon.jsx │ │ │ ├── configs-extensions │ │ │ │ └── wrap-actions.js │ │ │ ├── index.js │ │ │ ├── reducers.js │ │ │ ├── selectors.js │ │ │ ├── spec-extensions │ │ │ │ └── wrap-actions.js │ │ │ └── wrap-actions.js │ │ ├── configs │ │ │ ├── actions.js │ │ │ ├── fn.js │ │ │ ├── index.js │ │ │ ├── reducers.js │ │ │ └── selectors.js │ │ ├── deep-linking │ │ │ ├── README.md │ │ │ ├── helpers.js │ │ │ ├── index.js │ │ │ ├── layout.js │ │ │ ├── operation-tag-wrapper.jsx │ │ │ └── operation-wrapper.jsx │ │ ├── download-url │ │ │ └── index.js │ │ ├── err │ │ │ ├── actions.js │ │ │ ├── error-transformers │ │ │ │ ├── README.md │ │ │ │ ├── hook.js │ │ │ │ └── transformers │ │ │ │ │ ├── not-of-type.js │ │ │ │ │ └── parameter-oneof.js │ │ │ ├── index.js │ │ │ ├── reducers.js │ │ │ └── selectors.js │ │ ├── filter │ │ │ ├── index.js │ │ │ └── opsFilter.js │ │ ├── icons │ │ │ ├── components │ │ │ │ ├── arrow-down.jsx │ │ │ │ ├── arrow-up.jsx │ │ │ │ ├── arrow.jsx │ │ │ │ ├── close.jsx │ │ │ │ ├── copy.jsx │ │ │ │ ├── lock.jsx │ │ │ │ └── unlock.jsx │ │ │ └── index.js │ │ ├── json-schema-2020-12-samples │ │ │ ├── fn │ │ │ │ ├── api │ │ │ │ │ ├── encoderAPI.js │ │ │ │ │ ├── formatAPI.js │ │ │ │ │ ├── mediaTypeAPI.js │ │ │ │ │ └── optionAPI.js │ │ │ │ ├── class │ │ │ │ │ ├── EncoderRegistry.js │ │ │ │ │ ├── FormatRegistry.js │ │ │ │ │ ├── MediaTypeRegistry.js │ │ │ │ │ ├── OptionRegistry.js │ │ │ │ │ └── Registry.js │ │ │ │ ├── core │ │ │ │ │ ├── constants.js │ │ │ │ │ ├── example.js │ │ │ │ │ ├── merge.js │ │ │ │ │ ├── predicates.js │ │ │ │ │ ├── random.js │ │ │ │ │ ├── type.js │ │ │ │ │ └── utils.js │ │ │ │ ├── encoders │ │ │ │ │ ├── 7bit.js │ │ │ │ │ ├── 8bit.js │ │ │ │ │ ├── base16.js │ │ │ │ │ ├── base32.js │ │ │ │ │ ├── base64.js │ │ │ │ │ ├── base64url.js │ │ │ │ │ ├── binary.js │ │ │ │ │ └── quoted-printable.js │ │ │ │ ├── generators │ │ │ │ │ ├── date-time.js │ │ │ │ │ ├── date.js │ │ │ │ │ ├── double.js │ │ │ │ │ ├── duration.js │ │ │ │ │ ├── email.js │ │ │ │ │ ├── float.js │ │ │ │ │ ├── hostname.js │ │ │ │ │ ├── idn-email.js │ │ │ │ │ ├── idn-hostname.js │ │ │ │ │ ├── int32.js │ │ │ │ │ ├── int64.js │ │ │ │ │ ├── ipv4.js │ │ │ │ │ ├── ipv6.js │ │ │ │ │ ├── iri-reference.js │ │ │ │ │ ├── iri.js │ │ │ │ │ ├── json-pointer.js │ │ │ │ │ ├── media-types │ │ │ │ │ │ ├── application.js │ │ │ │ │ │ ├── audio.js │ │ │ │ │ │ ├── image.js │ │ │ │ │ │ ├── text.js │ │ │ │ │ │ └── video.js │ │ │ │ │ ├── password.js │ │ │ │ │ ├── regex.js │ │ │ │ │ ├── relative-json-pointer.js │ │ │ │ │ ├── time.js │ │ │ │ │ ├── uri-reference.js │ │ │ │ │ ├── uri-template.js │ │ │ │ │ ├── uri.js │ │ │ │ │ └── uuid.js │ │ │ │ ├── get-json-sample-schema.js │ │ │ │ ├── get-sample-schema.js │ │ │ │ ├── get-xml-sample-schema.js │ │ │ │ ├── get-yaml-sample-schema.js │ │ │ │ ├── index.js │ │ │ │ ├── main.js │ │ │ │ └── types │ │ │ │ │ ├── array.js │ │ │ │ │ ├── boolean.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── integer.js │ │ │ │ │ ├── null.js │ │ │ │ │ ├── number.js │ │ │ │ │ ├── object.js │ │ │ │ │ └── string.js │ │ │ └── index.js │ │ ├── json-schema-2020-12 │ │ │ ├── components │ │ │ │ ├── Accordion │ │ │ │ │ ├── Accordion.jsx │ │ │ │ │ └── _accordion.scss │ │ │ │ ├── ExpandDeepButton │ │ │ │ │ ├── ExpandDeepButton.jsx │ │ │ │ │ └── _expand-deep-button.scss │ │ │ │ ├── JSONSchema │ │ │ │ │ ├── JSONSchema.jsx │ │ │ │ │ └── _json-schema.scss │ │ │ │ ├── JSONViewer │ │ │ │ │ ├── JSONViewer.jsx │ │ │ │ │ └── _json-viewer.scss │ │ │ │ ├── _all.scss │ │ │ │ ├── _mixins.scss │ │ │ │ ├── icons │ │ │ │ │ └── ChevronRight.jsx │ │ │ │ └── keywords │ │ │ │ │ ├── $anchor.jsx │ │ │ │ │ ├── $comment.jsx │ │ │ │ │ ├── $defs.jsx │ │ │ │ │ ├── $dynamicAnchor.jsx │ │ │ │ │ ├── $dynamicRef.jsx │ │ │ │ │ ├── $id.jsx │ │ │ │ │ ├── $ref.jsx │ │ │ │ │ ├── $schema.jsx │ │ │ │ │ ├── $vocabulary │ │ │ │ │ ├── $vocabulary.jsx │ │ │ │ │ └── _$vocabulary.scss │ │ │ │ │ ├── AdditionalProperties.jsx │ │ │ │ │ ├── AllOf.jsx │ │ │ │ │ ├── AnyOf.jsx │ │ │ │ │ ├── Const │ │ │ │ │ ├── Const.jsx │ │ │ │ │ └── _const.scss │ │ │ │ │ ├── Constraint │ │ │ │ │ ├── Constraint.jsx │ │ │ │ │ └── _constraint.scss │ │ │ │ │ ├── Contains.jsx │ │ │ │ │ ├── ContentSchema.jsx │ │ │ │ │ ├── Default │ │ │ │ │ ├── Default.jsx │ │ │ │ │ └── _default.scss │ │ │ │ │ ├── DependentRequired │ │ │ │ │ ├── DependentRequired.jsx │ │ │ │ │ └── _dependent-required.scss │ │ │ │ │ ├── DependentSchemas.jsx │ │ │ │ │ ├── Deprecated.jsx │ │ │ │ │ ├── Description │ │ │ │ │ ├── Description.jsx │ │ │ │ │ └── _description.scss │ │ │ │ │ ├── Else.jsx │ │ │ │ │ ├── Enum │ │ │ │ │ ├── Enum.jsx │ │ │ │ │ └── _enum.scss │ │ │ │ │ ├── Examples │ │ │ │ │ ├── Examples.jsx │ │ │ │ │ └── _examples.scss │ │ │ │ │ ├── ExtensionKeywords │ │ │ │ │ ├── ExtensionKeywords.jsx │ │ │ │ │ └── _extension-keywords.scss │ │ │ │ │ ├── If.jsx │ │ │ │ │ ├── Items.jsx │ │ │ │ │ ├── Not.jsx │ │ │ │ │ ├── OneOf.jsx │ │ │ │ │ ├── PatternProperties │ │ │ │ │ ├── PatternProperties.jsx │ │ │ │ │ └── _pattern-properties.scss │ │ │ │ │ ├── PrefixItems.jsx │ │ │ │ │ ├── Properties │ │ │ │ │ ├── Properties.jsx │ │ │ │ │ └── _properties.scss │ │ │ │ │ ├── PropertyNames.jsx │ │ │ │ │ ├── ReadOnly.jsx │ │ │ │ │ ├── Then.jsx │ │ │ │ │ ├── Title │ │ │ │ │ ├── Title.jsx │ │ │ │ │ └── _title.scss │ │ │ │ │ ├── Type.jsx │ │ │ │ │ ├── UnevaluatedItems.jsx │ │ │ │ │ ├── UnevaluatedProperties.jsx │ │ │ │ │ ├── WriteOnly.jsx │ │ │ │ │ └── _all.scss │ │ │ ├── context.js │ │ │ ├── enum.js │ │ │ ├── fn.js │ │ │ ├── hoc.jsx │ │ │ ├── hooks.js │ │ │ ├── index.js │ │ │ └── prop-types.js │ │ ├── json-schema-5-samples │ │ │ ├── fn │ │ │ │ ├── get-json-sample-schema.js │ │ │ │ ├── get-sample-schema.js │ │ │ │ ├── get-xml-sample-schema.js │ │ │ │ ├── get-yaml-sample-schema.js │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── json-schema-5 │ │ │ ├── components │ │ │ │ ├── array-model.jsx │ │ │ │ ├── enum-model.jsx │ │ │ │ ├── json-schema-components.jsx │ │ │ │ ├── model-collapse.jsx │ │ │ │ ├── model-example.jsx │ │ │ │ ├── model-extensions.jsx │ │ │ │ ├── model-wrapper.jsx │ │ │ │ ├── model.jsx │ │ │ │ ├── models.jsx │ │ │ │ ├── object-model.jsx │ │ │ │ ├── primitive-model.jsx │ │ │ │ └── schemes.jsx │ │ │ ├── containers │ │ │ │ └── schemes.jsx │ │ │ ├── fn.js │ │ │ └── index.js │ │ ├── layout │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── reducers.js │ │ │ ├── selectors.js │ │ │ └── spec-extensions │ │ │ │ └── wrap-selector.js │ │ ├── logs │ │ │ └── index.js │ │ ├── oas3 │ │ │ ├── actions.js │ │ │ ├── auth-extensions │ │ │ │ └── wrap-selectors.js │ │ │ ├── components │ │ │ │ ├── auth │ │ │ │ │ └── http-auth.jsx │ │ │ │ ├── callbacks.jsx │ │ │ │ ├── index.js │ │ │ │ ├── operation-link.jsx │ │ │ │ ├── operation-servers.jsx │ │ │ │ ├── request-body-editor.jsx │ │ │ │ ├── request-body.jsx │ │ │ │ ├── servers-container.jsx │ │ │ │ └── servers.jsx │ │ │ ├── fn.js │ │ │ ├── helpers.jsx │ │ │ ├── index.js │ │ │ ├── reducers.js │ │ │ ├── selectors.js │ │ │ ├── spec-extensions │ │ │ │ ├── selectors.js │ │ │ │ └── wrap-selectors.js │ │ │ └── wrap-components │ │ │ │ ├── auth │ │ │ │ └── auth-item.jsx │ │ │ │ ├── index.js │ │ │ │ ├── json-schema-string.jsx │ │ │ │ ├── markdown.jsx │ │ │ │ ├── model.jsx │ │ │ │ ├── online-validator-badge.js │ │ │ │ └── openapi-version.jsx │ │ ├── oas31 │ │ │ ├── after-load.js │ │ │ ├── auth-extensions │ │ │ │ └── wrap-selectors.js │ │ │ ├── components │ │ │ │ ├── _all.scss │ │ │ │ ├── auth │ │ │ │ │ ├── auths.jsx │ │ │ │ │ └── mutual-tls-auth.jsx │ │ │ │ ├── contact.jsx │ │ │ │ ├── info.jsx │ │ │ │ ├── json-schema-dialect.jsx │ │ │ │ ├── license.jsx │ │ │ │ ├── model │ │ │ │ │ ├── _model.scss │ │ │ │ │ └── model.jsx │ │ │ │ ├── models │ │ │ │ │ ├── _models.scss │ │ │ │ │ └── models.jsx │ │ │ │ ├── version-pragma-filter.jsx │ │ │ │ └── webhooks.jsx │ │ │ ├── fn.js │ │ │ ├── index.js │ │ │ ├── json-schema-2020-12-extensions │ │ │ │ ├── components │ │ │ │ │ └── keywords │ │ │ │ │ │ ├── Description.jsx │ │ │ │ │ │ ├── Discriminator │ │ │ │ │ │ ├── Discriminator.jsx │ │ │ │ │ │ └── DiscriminatorMapping.jsx │ │ │ │ │ │ ├── Example.jsx │ │ │ │ │ │ ├── ExternalDocs.jsx │ │ │ │ │ │ ├── OpenAPIExtensions.jsx │ │ │ │ │ │ ├── Properties.jsx │ │ │ │ │ │ └── Xml.jsx │ │ │ │ ├── fn.js │ │ │ │ └── wrap-components │ │ │ │ │ └── keywords │ │ │ │ │ ├── Description.jsx │ │ │ │ │ ├── Examples.jsx │ │ │ │ │ └── Properties.jsx │ │ │ ├── oas3-extensions │ │ │ │ └── fn.js │ │ │ ├── selectors.js │ │ │ ├── spec-extensions │ │ │ │ ├── selectors.js │ │ │ │ └── wrap-selectors.js │ │ │ └── wrap-components │ │ │ │ ├── auth │ │ │ │ └── auth-item.jsx │ │ │ │ ├── auths.jsx │ │ │ │ ├── contact.jsx │ │ │ │ ├── info.jsx │ │ │ │ ├── license.jsx │ │ │ │ ├── model.jsx │ │ │ │ ├── models.jsx │ │ │ │ └── version-pragma-filter.jsx │ │ ├── on-complete │ │ │ └── index.js │ │ ├── request-snippets │ │ │ ├── fn.js │ │ │ ├── index.js │ │ │ ├── request-snippets.jsx │ │ │ └── selectors.js │ │ ├── safe-render │ │ │ ├── components │ │ │ │ ├── error-boundary.jsx │ │ │ │ └── fallback.jsx │ │ │ ├── fn.jsx │ │ │ └── index.js │ │ ├── spec │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── reducers.js │ │ │ ├── selectors.js │ │ │ └── wrap-actions.js │ │ ├── swagger-client │ │ │ ├── configs-wrap-actions.js │ │ │ └── index.js │ │ ├── syntax-highlighting │ │ │ ├── after-load.js │ │ │ ├── components │ │ │ │ ├── HighlightCode.jsx │ │ │ │ ├── PlainTextViewer.jsx │ │ │ │ └── SyntaxHighlighter.jsx │ │ │ ├── index.js │ │ │ ├── root-injects.js │ │ │ └── wrap-components │ │ │ │ └── SyntaxHighlighter.jsx │ │ ├── util │ │ │ └── index.js │ │ ├── versions │ │ │ ├── after-load.js │ │ │ └── index.js │ │ ├── view-legacy │ │ │ ├── index.js │ │ │ └── root-injects.jsx │ │ └── view │ │ │ ├── fn.js │ │ │ ├── index.js │ │ │ └── root-injects.jsx │ ├── presets │ │ ├── apis │ │ │ └── index.js │ │ └── base │ │ │ ├── index.js │ │ │ └── plugins │ │ │ ├── core-components │ │ │ └── index.js │ │ │ └── form-components │ │ │ └── index.js │ ├── system.js │ ├── utils │ │ ├── create-html-ready-id.js │ │ ├── get-parameter-schema.js │ │ ├── index.js │ │ ├── jsonParse.js │ │ ├── memoizeN.js │ │ └── url.js │ └── window.js ├── index.js ├── standalone │ ├── plugins │ │ ├── stadalone-layout │ │ │ ├── components │ │ │ │ └── StandaloneLayout.jsx │ │ │ └── index.js │ │ └── top-bar │ │ │ ├── assets │ │ │ └── logo_small.svg │ │ │ ├── components │ │ │ ├── Logo.jsx │ │ │ └── TopBar.jsx │ │ │ └── index.js │ └── presets │ │ └── standalone │ │ └── index.js └── style │ ├── _authorize.scss │ ├── _buttons.scss │ ├── _errors.scss │ ├── _form.scss │ ├── _information.scss │ ├── _layout.scss │ ├── _markdown.scss │ ├── _mixins.scss │ ├── _modal.scss │ ├── _models.scss │ ├── _servers.scss │ ├── _split-pane-mode.scss │ ├── _table.scss │ ├── _topbar.scss │ ├── _type.scss │ ├── _variables.scss │ └── main.scss ├── stylelint.config.js ├── swagger-ui-dist-package ├── .npmignore ├── .npmrc ├── README.md ├── absolute-path.js ├── deploy.sh ├── index.js └── package.json └── webpack ├── _config-builder.js ├── _helpers.js ├── bundle.js ├── core.js ├── dev-e2e.js ├── dev.js ├── es-bundle-core.js ├── es-bundle.js ├── standalone.js └── stylesheets.js /.agignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | [node-production] 2 | maintained node versions 3 | 4 | [node-development] 5 | node 22 6 | 7 | [browser-production] 8 | > 1% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | 13 | [browser-development] 14 | last 1 chrome version 15 | last 1 firefox version 16 | last 1 safari version 17 | 18 | [isomorphic-production] 19 | > 1% 20 | last 2 versions 21 | Firefox ESR 22 | not dead 23 | maintained node versions 24 | 25 | [isomorphic-development] 26 | last 1 chrome version 27 | last 1 firefox version 28 | last 1 safari version 29 | node 22 30 | -------------------------------------------------------------------------------- /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@commitlint/config-conventional" 4 | ], 5 | "rules": { 6 | "header-max-length": [ 7 | 2, 8 | "always", 9 | 69 10 | ], 11 | "scope-case": [ 12 | 2, 13 | "always", 14 | [ 15 | "camel-case", 16 | "kebab-case", 17 | "upper-case" 18 | ] 19 | ], 20 | "subject-case": [ 21 | 0, 22 | "always" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /.git 2 | /.github 3 | /dev-helpers 4 | /docs 5 | /src 6 | /swagger-ui-dist-package 7 | /test 8 | /node_modules -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | indent_style = space 6 | indent_size = 2 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | [*.md] 10 | trim_trailing_whitespace = false 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | test/e2e-selenium/ 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | docker-run.sh text eol=lf 2 | /dist/*.map export-ignore 3 | /test export-ignore 4 | /docs export-ignore -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest a new feature or enhancement for this project 4 | 5 | --- 6 | 7 | ### Content & configuration 8 | 9 | Swagger/OpenAPI definition: 10 | ```yaml 11 | # your YAML here 12 | ``` 13 | 14 | Swagger-UI configuration options: 15 | ```js 16 | SwaggerUI({ 17 | // your config options here 18 | }) 19 | ``` 20 | 21 | ``` 22 | ?yourQueryStringConfig 23 | ``` 24 | 25 | 26 | ### Is your feature request related to a problem? 27 | 31 | 32 | ### Describe the solution you'd like 33 | 34 | 35 | ### Describe alternatives you've considered 36 | 40 | 41 | ### Additional context 42 | 43 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "23:00" 8 | commit-message: 9 | prefix: "chore" 10 | include: "scope" 11 | open-pull-requests-limit: 3 12 | ignore: 13 | # node-fetch must be synced manually 14 | - dependency-name: "node-fetch" 15 | 16 | - package-ecosystem: "docker" 17 | # Look for a `Dockerfile` in the `root` directory 18 | directory: "/" 19 | # Check for updates once a week 20 | schedule: 21 | interval: "weekly" 22 | time: "23:00" 23 | 24 | - package-ecosystem: "github-actions" 25 | target-branch: "master" 26 | directory: "/" 27 | schedule: 28 | interval: "daily" 29 | time: "23:00" 30 | commit-message: 31 | prefix: "chore" 32 | include: "scope" 33 | open-pull-requests-limit: 3 34 | 35 | 36 | -------------------------------------------------------------------------------- /.github/lock.yml: -------------------------------------------------------------------------------- 1 | daysUntilLock: 365 2 | skipCreatedBefore: 2017-03-29 # initial release of Swagger UI 3.0.0 3 | exemptLabels: [] 4 | lockLabel: "locked-by: lock-bot" 5 | setLockReason: false 6 | only: issues 7 | lockComment: false 8 | # lockComment: | 9 | # Locking due to inactivity. 10 | 11 | # This is done to avoid resurrecting old issues and bumping long threads with new, possibly unrelated content. 12 | 13 | # If you think you're experiencing something similar to what you've found here: please [open a new issue](https://github.com/swagger-api/swagger-ui/issues/new/choose), follow the template, and reference this issue in your report. 14 | 15 | # Thanks! 16 | -------------------------------------------------------------------------------- /.github/workflows/docker-image-check.yml: -------------------------------------------------------------------------------- 1 | name: Security scan for docker image 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '30 4 * * *' 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Run Trivy vulnerability scanner 16 | uses: aquasecurity/trivy-action@master 17 | with: 18 | image-ref: 'docker.swagger.io/swaggerapi/swagger-ui:unstable' 19 | format: 'table' 20 | exit-code: '1' 21 | ignore-unfixed: true 22 | vuln-type: 'os,library' 23 | severity: 'CRITICAL,HIGH' 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | .vscode 4 | .deps_check 5 | .DS_Store 6 | .env.local 7 | .env.development.local 8 | .env.test.local 9 | .env.production.local 10 | .nyc_output 11 | npm-debug.log* 12 | .eslintcache 13 | *.iml 14 | selenium-debug.log 15 | chromedriver.log 16 | test/e2e/db.json 17 | docs/_book 18 | dev-helpers/examples 19 | 20 | # dist 21 | flavors/**/dist/* 22 | /lib 23 | /es 24 | dist/log* 25 | /swagger-ui-*.tgz 26 | 27 | # Cypress 28 | test/e2e-cypress/screenshots 29 | test/e2e-cypress/videos 30 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | npx commitlint -e 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged 2 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.{js,jsx}": ["eslint --max-warnings 0"], 3 | "*.scss": ["stylelint '**/*.scss'"] 4 | } 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | */ 3 | !README.md 4 | !NOTICE 5 | !package.json 6 | !dist/swagger-ui.js 7 | !dist/swagger-ui.js.map 8 | !dist/swagger-ui-bundle.js 9 | !dist/swagger-ui-standalone-preset.js 10 | !dist/swagger-ui-es-bundle.js 11 | !dist/swagger-ui-es-bundle-core.js 12 | !dist/swagger-ui-es-bundle-core.js.map 13 | !dist/swagger-ui.css 14 | !dist/swagger-ui.css.map 15 | !dist/oauth2-redirect.html 16 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-prefix="=" 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 22.11.0 2 | -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | semi: false 2 | trailingComma: es5 3 | endOfLine: lf 4 | requirePragma: true 5 | insertPragma: true 6 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | {"name": "master"} 4 | ], 5 | "tagFormat": "v${version}", 6 | "plugins": [ 7 | "@semantic-release/commit-analyzer", 8 | [ 9 | "@semantic-release/exec", 10 | { 11 | "verifyReleaseCmd": "echo \"NEXT_RELEASE_VERSION=${nextRelease.version}\" >> $GITHUB_ENV" 12 | } 13 | ], 14 | "@semantic-release/release-notes-generator", 15 | "@semantic-release/npm", 16 | "@semantic-release/github", 17 | ["@semantic-release/git", { 18 | "assets": [ 19 | "package.json", 20 | "package-lock.json" 21 | ], 22 | "message": "chore(release): cut the ${nextRelease.version} release\n\n${nextRelease.notes}" 23 | }] 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | swagger-ui 2 | Copyright 2020-2021 SmartBear Software Inc. 3 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | If you believe you've found an exploitable security issue in Swagger UI, 4 | **please don't create a public issue**. 5 | 6 | 7 | ## Supported versions 8 | 9 | This is the list of versions of `swagger-ui` which are 10 | currently being supported with security updates. 11 | 12 | | Version | Supported | Notes | 13 | |---------|--------------------|---------------------------------| 14 | | 5.x | :white_check_mark: | Active LTS | 15 | | 4.x | :x: | End-of-life as of August 2023 | 16 | | 3.x | :x: | End-of-life as of November 2021 | 17 | | 2.x | :x: | End-of-life as of 2017 | 18 | 19 | ## Reporting a vulnerability 20 | 21 | To report a vulnerability please send an email with the details to [security@swagger.io](mailto:security@swagger.io). 22 | 23 | We'll acknowledge receipt of your report ASAP, and set expectations on how we plan to handle it. 24 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "swagger-api/swagger-ui", 3 | "description": " Swagger UI is a collection of HTML, Javascript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.", 4 | "keywords": [ 5 | "Swagger", 6 | "OpenAPI", 7 | "specification", 8 | "documentation", 9 | "API", 10 | "UI" 11 | ], 12 | "homepage": "http://swagger.io", 13 | "license": "Apache-2.0", 14 | "authors": [ 15 | { 16 | "name": "Anna Bodnia", 17 | "email": "anna.bodnia@gmail.com" 18 | }, 19 | { 20 | "name": "Buu Nguyen", 21 | "email": "buunguyen@gmail.com" 22 | }, 23 | { 24 | "name": "Josh Ponelat", 25 | "email": "jponelat@gmail.com" 26 | }, 27 | { 28 | "name": "Kyle Shockey", 29 | "email": "kyleshockey1@gmail.com" 30 | }, 31 | { 32 | "name": "Robert Barnwell", 33 | "email": "robert@robertismy.name" 34 | }, 35 | { 36 | "name": "Sahar Jafari", 37 | "email": "shr.jafari@gmail.com" 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /config/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "import/no-unresolved": 0, 4 | "import/extensions": 0, 5 | "quotes": ["error", "single"], 6 | "semi": ["error", "always"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /config/jest/jest.artifact.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | rootDir: path.join(__dirname, '..', '..'), 5 | testEnvironment: 'jsdom', 6 | testMatch: ['**/test/build-artifacts/**/*.js'], 7 | setupFiles: ['/test/unit/jest-shim.js'], 8 | transformIgnorePatterns: ['/node_modules/(?!(swagger-client|react-syntax-highlighter)/)'], 9 | }; 10 | -------------------------------------------------------------------------------- /config/jest/jest.unit.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | rootDir: path.join(__dirname, '..', '..'), 5 | testEnvironment: 'jest-environment-jsdom', 6 | testMatch: [ 7 | '**/test/unit/*.js?(x)', 8 | '**/test/unit/**/*.js?(x)', 9 | ], 10 | setupFiles: ['/test/unit/jest-shim.js'], 11 | setupFilesAfterEnv: ['/test/unit/setup.js'], 12 | testPathIgnorePatterns: [ 13 | '/node_modules/', 14 | '/test/build-artifacts/', 15 | '/test/unit/jest-shim.js', 16 | '/test/unit/setup.js', 17 | ], 18 | moduleNameMapper: { 19 | '^.+\\.svg$': 'jest-transform-stub' 20 | }, 21 | transformIgnorePatterns: ['/node_modules/(?!(sinon|react-syntax-highlighter|@asamuzakjp/css-color)/)'], 22 | silent: true, // set to `false` to allow console.* calls to be printed 23 | }; 24 | -------------------------------------------------------------------------------- /cypress.config.js: -------------------------------------------------------------------------------- 1 | const { defineConfig } = require("cypress") 2 | 3 | const startOAuthServer = require("./test/e2e-cypress/support/helpers/oauth2-server") 4 | 5 | module.exports = defineConfig({ 6 | fileServerFolder: "test/e2e-cypress/static", 7 | fixturesFolder: "test/e2e-cypress/fixtures", 8 | screenshotsFolder: "test/e2e-cypress/screenshots", 9 | videosFolder: "test/e2e-cypress/videos", 10 | video: false, 11 | e2e: { 12 | baseUrl: "http://localhost:3230/", 13 | supportFile: "test/e2e-cypress/support/e2e.js", 14 | specPattern: "test/e2e-cypress/e2e/**/*.cy.{js,jsx}", 15 | setupNodeEvents: () => { 16 | startOAuthServer() 17 | }, 18 | }, 19 | }) 20 | -------------------------------------------------------------------------------- /dev-helpers/dev-helper-initializer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | window.onload = function() { 3 | window["SwaggerUIBundle"] = window["swagger-ui-bundle"] 4 | window["SwaggerUIStandalonePreset"] = window["swagger-ui-standalone-preset"] 5 | // Build a system 6 | const ui = SwaggerUIBundle({ 7 | url: "https://petstore.swagger.io/v2/swagger.json", 8 | dom_id: "#swagger-ui", 9 | presets: [ 10 | SwaggerUIBundle.presets.apis, 11 | SwaggerUIStandalonePreset 12 | ], 13 | plugins: [ 14 | SwaggerUIBundle.plugins.DownloadUrl 15 | ], 16 | // requestSnippetsEnabled: true, 17 | layout: "StandaloneLayout" 18 | }) 19 | 20 | window.ui = ui 21 | 22 | ui.initOAuth({ 23 | clientId: "your-client-id", 24 | clientSecret: "your-client-secret-if-required", 25 | realm: "your-realms", 26 | appName: "your-app-name", 27 | scopeSeparator: " ", 28 | scopes: "openid profile email phone address", 29 | additionalQueryStringParams: {}, 30 | useBasicAuthenticationWithAccessCodeGrant: false, 31 | usePkceWithAuthorizationCodeGrant: false 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /dev-helpers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Swagger UI 8 | 9 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /dev-helpers/style.css: -------------------------------------------------------------------------------- 1 | html 2 | { 3 | box-sizing: border-box; 4 | overflow: -moz-scrollbars-vertical; 5 | overflow-y: scroll; 6 | } 7 | 8 | *, 9 | *:before, 10 | *:after 11 | { 12 | box-sizing: inherit; 13 | } 14 | 15 | body 16 | { 17 | margin:0; 18 | background: #fafafa; 19 | } 20 | -------------------------------------------------------------------------------- /dist/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swagger-api/swagger-ui/4680916cd91d4c9e7caabef0a1c677e2ab011118/dist/favicon-16x16.png -------------------------------------------------------------------------------- /dist/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swagger-api/swagger-ui/4680916cd91d4c9e7caabef0a1c677e2ab011118/dist/favicon-32x32.png -------------------------------------------------------------------------------- /dist/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | overflow: -moz-scrollbars-vertical; 4 | overflow-y: scroll; 5 | } 6 | 7 | *, 8 | *:before, 9 | *:after { 10 | box-sizing: inherit; 11 | } 12 | 13 | body { 14 | margin: 0; 15 | background: #fafafa; 16 | } 17 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /dist/swagger-initializer.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | // 3 | 4 | // the following lines will be replaced by docker/configurator, when it runs in a docker-container 5 | window.ui = SwaggerUIBundle({ 6 | url: "https://petstore.swagger.io/v2/swagger.json", 7 | dom_id: '#swagger-ui', 8 | deepLinking: true, 9 | presets: [ 10 | SwaggerUIBundle.presets.apis, 11 | SwaggerUIStandalonePreset 12 | ], 13 | plugins: [ 14 | SwaggerUIBundle.plugins.DownloadUrl 15 | ], 16 | layout: "StandaloneLayout" 17 | }); 18 | 19 | // 20 | }; 21 | -------------------------------------------------------------------------------- /docker/configurator/helpers.js: -------------------------------------------------------------------------------- 1 | module.exports.indent = function indent(str, len, fromLine = 0) { 2 | 3 | return str 4 | .split("\n") 5 | .map((line, i) => { 6 | if (i + 1 >= fromLine) { 7 | return `${Array(len + 1).join(" ")}${line}` 8 | } else { 9 | return line 10 | } 11 | }) 12 | .join("\n") 13 | } -------------------------------------------------------------------------------- /docker/cors.conf: -------------------------------------------------------------------------------- 1 | add_header 'Access-Control-Allow-Origin' '*' always; 2 | add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; 3 | # 4 | # Custom headers and headers various browsers *should* be OK with but aren't 5 | # 6 | add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always; 7 | # 8 | # Tell client that this pre-flight info is valid for 20 days 9 | # 10 | add_header 'Access-Control-Max-Age' $access_control_max_age always; 11 | 12 | if ($request_method = OPTIONS) { 13 | return 204; 14 | } 15 | -------------------------------------------------------------------------------- /docker/default.conf.template: -------------------------------------------------------------------------------- 1 | types { 2 | text/plain yaml; 3 | text/plain yml; 4 | } 5 | 6 | gzip on; 7 | gzip_static on; 8 | gzip_disable "msie6"; 9 | 10 | gzip_vary on; 11 | gzip_types text/plain text/css application/javascript; 12 | 13 | map $request_method $access_control_max_age { 14 | OPTIONS 1728000; # 20 days 15 | } 16 | server_tokens off; # Hide Nginx version 17 | 18 | server { 19 | listen $PORT; 20 | server_name localhost; 21 | index index.html index.htm; 22 | 23 | location $BASE_URL { 24 | absolute_redirect off; 25 | alias /usr/share/nginx/html/; 26 | expires 1d; 27 | 28 | location ~ swagger-initializer.js { 29 | expires -1; 30 | include templates/cors.conf; 31 | } 32 | 33 | location ~* \.(?:json|yml|yaml)$ { 34 | #SWAGGER_ROOT 35 | expires -1; 36 | 37 | include templates/cors.conf; 38 | } 39 | 40 | include templates/cors.conf; 41 | include templates/embedding.conf; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docker/embedding.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Prevent displaying inside an iframe 3 | # 4 | add_header 'X-Frame-Options' 'DENY' always; 5 | add_header 'Content-Security-Policy' "frame-ancestors 'none'" always; 6 | -------------------------------------------------------------------------------- /flavors/swagger-ui-react/dist/.npmrc: -------------------------------------------------------------------------------- 1 | //registry.npmjs.org/:_authToken=${NPM_TOKEN} 2 | -------------------------------------------------------------------------------- /flavors/swagger-ui-react/release/create-manifest.js: -------------------------------------------------------------------------------- 1 | const jsonMerger = require("json-merger") 2 | 3 | const result = jsonMerger.mergeFiles(["../../../package.json", "template.json"]) 4 | 5 | if (process.env.REACT_FLAVOR_VERSION_IDENTIFIER) { 6 | result.version = process.env.REACT_FLAVOR_VERSION_IDENTIFIER 7 | } 8 | 9 | process.stdout.write(JSON.stringify(result, null, 2)) 10 | -------------------------------------------------------------------------------- /flavors/swagger-ui-react/release/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "react": { 4 | "$remove": true 5 | }, 6 | "react-dom": { 7 | "$remove": true 8 | } 9 | }, 10 | "scripts": { 11 | "$remove": true 12 | }, 13 | "devDependencies": { 14 | "$remove": true 15 | }, 16 | "config": { 17 | "$remove": true 18 | }, 19 | "name": "swagger-ui-react", 20 | "main": "index.cjs", 21 | "module": "index.mjs", 22 | "exports": { 23 | "$replace": { 24 | "./swagger-ui.css": "./swagger-ui.css", 25 | ".": { 26 | "import": "./index.mjs", 27 | "require": "./index.cjs" 28 | } 29 | } 30 | }, 31 | "imports": { 32 | "$replace": { 33 | "#swagger-ui": { 34 | "browser": { 35 | "import": "./swagger-ui-es-bundle-core.js", 36 | "require": "./swagger-ui.js" 37 | }, 38 | "node": { 39 | "import": "./swagger-ui-bundle.js", 40 | "require": "./swagger-ui-es-bundle.js" 41 | }, 42 | "default": { 43 | "import": "./swagger-ui-bundle.js", 44 | "require": "./swagger-ui-es-bundle.js" 45 | } 46 | } 47 | } 48 | }, 49 | "peerDependencies": { 50 | "react": ">=16.8.0 <19", 51 | "react-dom": ">=16.8.0 <19" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /release/.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "before:bump": [ 4 | "./release/check-for-breaking-changes.sh ${latestVersion} ${version}", 5 | "npm update swagger-client", 6 | "npm test" 7 | ], 8 | "after:bump": ["npm run build"], 9 | "after:release": "export GIT_TAG=v${version} && echo GIT_TAG=v${version} > release/.version" 10 | }, 11 | "git": { 12 | "requireUpstream": false, 13 | "changelog": "./release/get-changelog.sh", 14 | "commitMessage": "chore(release): cut the v${version} release", 15 | "tagName": "v${version}", 16 | "push": false 17 | }, 18 | "github": { 19 | "release": true, 20 | "releaseName": "Swagger UI v${version} Released!", 21 | "draft": true 22 | }, 23 | "plugins": { 24 | "@release-it/conventional-changelog": { 25 | "preset": "angular" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /release/check-for-breaking-changes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CURRENT_VERSION=$1 3 | NEXT_VERSION=$2 4 | CURRENT_MAJOR=${CURRENT_VERSION:0:1} 5 | NEXT_MAJOR=${NEXT_VERSION:0:1} 6 | 7 | if [ "$CURRENT_MAJOR" -ne "$NEXT_MAJOR" ] ; 8 | then if [ "$BREAKING_OKAY" = "true" ]; 9 | then echo "breaking change detected but BREAKING_OKAY is set; continuing." && exit 0; 10 | else echo "breaking change detected and BREAKING_OKAY is not set; aborting." && exit 1; 11 | fi; 12 | fi; 13 | 14 | echo "next version is not a breaking change; continuing."; -------------------------------------------------------------------------------- /release/get-changelog.sh: -------------------------------------------------------------------------------- 1 | echo "_No release summary included._\n\n#### Changelog\n" 2 | 3 | PREV_RELEASE_REF=$(git log --pretty=oneline | grep ' release: ' | head -n 2 | tail -n 1 | cut -f 1 -d " ") 4 | 5 | git log --pretty=oneline $PREV_RELEASE_REF..HEAD | awk '{ $1=""; print}' | sed -e 's/^[ \t]*//' | sed 's/^feat/0,feat/' | sed 's/^improve/1,improve/' | sed 's/^fix/2,fix/'| sort | sed 's/^[0-2],//' | sed 's/^/* /' 6 | -------------------------------------------------------------------------------- /snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: swagger-ui 2 | version: master 3 | summary: The World's Most Popular API Framework 4 | description: | 5 | Swagger UI is part of the Swagger project. The Swagger project allows you to 6 | produce, visualize and consume your OWN RESTful services. No proxy or 3rd 7 | party services required. Do it your own way. 8 | 9 | Swagger UI is a dependency-free collection of HTML, Javascript, and CSS 10 | assets that dynamically generate beautiful documentation and sandbox from a 11 | Swagger-compliant API. Because Swagger UI has no dependencies, you can host 12 | it in any server environment, or on your local machine. 13 | 14 | grade: devel 15 | confinement: strict 16 | 17 | apps: 18 | swagger-ui: 19 | command: sh -c \"cd $SNAP/lib/node_modules/swagger-ui/dist && http-server -a localhost -p 8080\" 20 | daemon: simple 21 | plugs: [network, network-bind] 22 | 23 | parts: 24 | swagger-ui: 25 | source: . 26 | plugin: nodejs 27 | npm-run: [build] 28 | node-packages: [handlebars, http-server] 29 | -------------------------------------------------------------------------------- /src/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "import/no-extraneous-dependencies": [ 4 | 2, 5 | { 6 | "devDependencies": false 7 | } 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/core/assets/rolling-load.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/core/components/app.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | class App extends React.Component { 8 | getLayout() { 9 | const { getComponent, layoutSelectors } = this.props 10 | const layoutName = layoutSelectors.current() 11 | const Component = getComponent(layoutName, true) 12 | 13 | return Component 14 | ? Component 15 | : () =>

No layout defined for "{layoutName}"

16 | } 17 | 18 | render() { 19 | const Layout = this.getLayout() 20 | 21 | return 22 | } 23 | } 24 | 25 | App.propTypes = { 26 | getComponent: PropTypes.func.isRequired, 27 | layoutSelectors: PropTypes.object.isRequired, 28 | } 29 | 30 | export default App 31 | -------------------------------------------------------------------------------- /src/core/components/auth/authorize-btn.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default class AuthorizeBtn extends React.Component { 5 | static propTypes = { 6 | onClick: PropTypes.func, 7 | isAuthorized: PropTypes.bool, 8 | showPopup: PropTypes.bool, 9 | getComponent: PropTypes.func.isRequired 10 | } 11 | 12 | render() { 13 | let { isAuthorized, showPopup, onClick, getComponent } = this.props 14 | 15 | //must be moved out of button component 16 | const AuthorizationPopup = getComponent("authorizationPopup", true) 17 | const LockAuthIcon = getComponent("LockAuthIcon", true) 18 | const UnlockAuthIcon = getComponent("UnlockAuthIcon", true) 19 | 20 | return ( 21 |
22 | 26 | { showPopup && } 27 |
28 | ) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/core/components/auth/authorize-operation-btn.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default class AuthorizeOperationBtn extends React.Component { 5 | static propTypes = { 6 | isAuthorized: PropTypes.bool.isRequired, 7 | onClick: PropTypes.func, 8 | getComponent: PropTypes.func.isRequired 9 | } 10 | 11 | onClick =(e) => { 12 | e.stopPropagation() 13 | let { onClick } = this.props 14 | 15 | if(onClick) { 16 | onClick() 17 | } 18 | } 19 | 20 | render() { 21 | let { isAuthorized, getComponent } = this.props 22 | 23 | const LockAuthOperationIcon = getComponent("LockAuthOperationIcon", true) 24 | const UnlockAuthOperationIcon = getComponent("UnlockAuthOperationIcon", true) 25 | 26 | return ( 27 | 32 | 33 | ) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/core/components/auth/error.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default class AuthError extends React.Component { 5 | 6 | static propTypes = { 7 | error: PropTypes.object.isRequired 8 | } 9 | 10 | render() { 11 | let { error } = this.props 12 | 13 | let level = error.get("level") 14 | let message = error.get("message") 15 | let source = error.get("source") 16 | 17 | return ( 18 |
19 | { source } { level } 20 | { message } 21 |
22 | ) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/core/components/clear.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default class Clear extends Component { 5 | 6 | onClick =() => { 7 | let { specActions, path, method } = this.props 8 | specActions.clearResponse( path, method ) 9 | specActions.clearRequest( path, method ) 10 | } 11 | 12 | render(){ 13 | return ( 14 | 17 | ) 18 | } 19 | 20 | static propTypes = { 21 | specActions: PropTypes.object.isRequired, 22 | path: PropTypes.string.isRequired, 23 | method: PropTypes.string.isRequired, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/core/components/copy-to-clipboard-btn.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { CopyToClipboard } from "react-copy-to-clipboard" 3 | import PropTypes from "prop-types" 4 | 5 | /** 6 | * @param {{ getComponent: func, textToCopy: string }} props 7 | * @returns {JSX.Element} 8 | * @constructor 9 | */ 10 | export default class CopyToClipboardBtn extends React.Component { 11 | render() { 12 | let { getComponent } = this.props 13 | 14 | const CopyIcon = getComponent("CopyIcon") 15 | 16 | return ( 17 |
18 | 19 | 20 | 21 |
22 | ) 23 | } 24 | 25 | static propTypes = { 26 | getComponent: PropTypes.func.isRequired, 27 | textToCopy: PropTypes.string.isRequired, 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/core/components/deep-link.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export const DeepLink = ({ enabled, path, text }) => { 5 | return ( 6 | e.preventDefault() : null} 8 | href={enabled ? `#/${path}` : null}> 9 | {text} 10 | 11 | ) 12 | } 13 | DeepLink.propTypes = { 14 | enabled: PropTypes.bool, 15 | isShown: PropTypes.bool, 16 | path: PropTypes.string, 17 | text: PropTypes.node 18 | } 19 | 20 | export default DeepLink 21 | -------------------------------------------------------------------------------- /src/core/components/footer.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export default class Footer extends React.Component { 4 | render() { 5 | return ( 6 |
7 | ) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/core/components/jump-to-path.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | // Nothing by default- component can be overridden by another plugin. 4 | 5 | export default class JumpToPath extends React.Component { 6 | render() { 7 | return null 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/core/components/license.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | import { safeBuildUrl, sanitizeUrl } from "core/utils/url" 7 | 8 | class License extends React.Component { 9 | static propTypes = { 10 | license: PropTypes.object, 11 | getComponent: PropTypes.func.isRequired, 12 | specSelectors: PropTypes.object.isRequired, 13 | selectedServer: PropTypes.string, 14 | url: PropTypes.string.isRequired, 15 | } 16 | 17 | render() { 18 | const { license, getComponent, selectedServer, url: specUrl } = this.props 19 | const name = license.get("name", "License") 20 | const url = safeBuildUrl(license.get("url"), specUrl, { selectedServer }) 21 | 22 | const Link = getComponent("Link") 23 | 24 | return ( 25 |
26 | {url ? ( 27 |
28 | 29 | {name} 30 | 31 |
32 | ) : ( 33 | {name} 34 | )} 35 |
36 | ) 37 | } 38 | } 39 | 40 | export default License 41 | -------------------------------------------------------------------------------- /src/core/components/openapi-version.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | 5 | const OpenAPIVersion = ({ oasVersion }) => ( 6 | 7 |
OAS {oasVersion}
8 |
9 | ) 10 | 11 | OpenAPIVersion.propTypes = { 12 | oasVersion: PropTypes.string.isRequired 13 | } 14 | 15 | export default OpenAPIVersion 16 | -------------------------------------------------------------------------------- /src/core/components/operation-extension-row.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export const OperationExtRow = ({ xKey, xVal }) => { 5 | const xNormalizedValue = !xVal ? null : xVal.toJS ? xVal.toJS() : xVal 6 | 7 | return ( 8 | { xKey } 9 | { JSON.stringify(xNormalizedValue) } 10 | ) 11 | } 12 | OperationExtRow.propTypes = { 13 | xKey: PropTypes.string, 14 | xVal: PropTypes.any 15 | } 16 | 17 | export default OperationExtRow 18 | -------------------------------------------------------------------------------- /src/core/components/operation-extensions.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export const OperationExt = ({ extensions, getComponent }) => { 5 | let OperationExtRow = getComponent("OperationExtRow") 6 | return ( 7 |
8 |
9 |

Extensions

10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | { 22 | extensions.entrySeq().map(([k, v]) => ) 23 | } 24 | 25 |
FieldValue
26 |
27 |
28 | ) 29 | } 30 | OperationExt.propTypes = { 31 | extensions: PropTypes.object.isRequired, 32 | getComponent: PropTypes.func.isRequired 33 | } 34 | 35 | export default OperationExt 36 | -------------------------------------------------------------------------------- /src/core/components/operation-summary-method.jsx: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from "react" 2 | import PropTypes from "prop-types" 3 | import { Iterable } from "immutable" 4 | 5 | export default class OperationSummaryMethod extends PureComponent { 6 | 7 | static propTypes = { 8 | operationProps: PropTypes.instanceOf(Iterable).isRequired, 9 | method: PropTypes.string.isRequired, 10 | } 11 | 12 | static defaultProps = { 13 | operationProps: null, 14 | } 15 | render() { 16 | 17 | let { 18 | method, 19 | } = this.props 20 | 21 | return ( 22 | {method.toUpperCase()} 23 | ) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/core/components/parameter-extension.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export const ParameterExt = ({ xKey, xVal }) => { 5 | return
{ xKey }: { String(xVal) }
6 | } 7 | ParameterExt.propTypes = { 8 | xKey: PropTypes.string, 9 | xVal: PropTypes.any 10 | } 11 | 12 | export default ParameterExt 13 | -------------------------------------------------------------------------------- /src/core/components/parameters/index.js: -------------------------------------------------------------------------------- 1 | export { default as Parameters } from "./parameters" 2 | -------------------------------------------------------------------------------- /src/core/components/property.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export const Property = ({ propKey, propVal, propClass }) => { 5 | return ( 6 | 7 |
{ propKey }: { String(propVal) }
8 | ) 9 | } 10 | Property.propTypes = { 11 | propKey: PropTypes.string, 12 | propVal: PropTypes.any, 13 | propClass: PropTypes.string 14 | } 15 | 16 | export default Property 17 | -------------------------------------------------------------------------------- /src/core/components/providers/README.md: -------------------------------------------------------------------------------- 1 | # Providers 2 | 3 | Providers are generic bridges to third-party components. They provide two benefits: 4 | 5 | 1. ability for plugins to override third-party components, because providers are loaded through `getComponent` 6 | 2. allows us to avoid painting ourselves into a corner with a third-party component 7 | -------------------------------------------------------------------------------- /src/core/components/response-extension.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export const ResponseExtension = ({ xKey, xVal }) => { 5 | return
{ xKey }: { String(xVal) }
6 | } 7 | ResponseExtension.propTypes = { 8 | xKey: PropTypes.string, 9 | xVal: PropTypes.any 10 | } 11 | 12 | export default ResponseExtension 13 | -------------------------------------------------------------------------------- /src/core/components/system-wrapper.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swagger-api/swagger-ui/4680916cd91d4c9e7caabef0a1c677e2ab011118/src/core/components/system-wrapper.jsx -------------------------------------------------------------------------------- /src/core/components/version-stamp.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | const VersionStamp = ({ version }) => { 5 | return
 { version } 
6 | } 7 | 8 | VersionStamp.propTypes = { 9 | version: PropTypes.string.isRequired 10 | } 11 | 12 | export default VersionStamp 13 | -------------------------------------------------------------------------------- /src/core/config/factorization/inline-plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | const InlinePluginFactorization = (options) => () => ({ 6 | fn: options.fn, 7 | components: options.components, 8 | }) 9 | 10 | export default InlinePluginFactorization 11 | -------------------------------------------------------------------------------- /src/core/config/factorization/system.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import deepExtend from "deep-extend" 5 | 6 | const systemFactorization = (options) => { 7 | const state = deepExtend( 8 | { 9 | layout: { 10 | layout: options.layout, 11 | filter: options.filter, 12 | }, 13 | spec: { 14 | spec: "", 15 | url: options.url, 16 | }, 17 | requestSnippets: options.requestSnippets, 18 | }, 19 | options.initialState 20 | ) 21 | 22 | if (options.initialState) { 23 | /** 24 | * If the user sets a key as `undefined`, that signals to us that we 25 | * should delete the key entirely. 26 | * known usage: Swagger-Editor validate plugin tests 27 | */ 28 | for (const [key, value] of Object.entries(options.initialState)) { 29 | if (value === undefined) { 30 | delete state[key] 31 | } 32 | } 33 | } 34 | 35 | return { 36 | system: { 37 | configs: options.configs, 38 | }, 39 | plugins: options.presets, 40 | state, 41 | } 42 | } 43 | 44 | export default systemFactorization 45 | -------------------------------------------------------------------------------- /src/core/config/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | export { default as inlinePluginOptionsFactorization } from "./factorization/inline-plugin" 5 | export { default as systemOptionsFactorization } from "./factorization/system" 6 | export { default as optionsFromQuery } from "./sources/query" 7 | export { default as optionsFromURL } from "./sources/url" 8 | export { default as optionsFromRuntime } from "./sources/runtime" 9 | export { default as defaultOptions } from "./defaults" 10 | export { default as mergeOptions } from "./merge" 11 | export { default as typeCastOptions } from "./type-cast" 12 | export { default as typeCastMappings } from "./type-cast/mappings" 13 | -------------------------------------------------------------------------------- /src/core/config/sources/query.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import set from "lodash/set" 5 | import { parseSearch } from "core/utils" 6 | 7 | /** 8 | * Receives options from the query string of the URL where SwaggerUI 9 | * is being served. 10 | */ 11 | 12 | const optionsFromQuery = () => (options) => { 13 | const urlSearchParams = options.queryConfigEnabled ? parseSearch() : {} 14 | 15 | return Object.entries(urlSearchParams).reduce((acc, [key, value]) => { 16 | // TODO(oliwia.rogala@smartbear.com): drop support for `config` in the next major release 17 | if (key === "config") { 18 | acc["configUrl"] = value 19 | } else if (key === "urls.primaryName") { 20 | acc[key] = value 21 | } else { 22 | acc = set(acc, key, value) 23 | } 24 | return acc 25 | }, {}) 26 | } 27 | 28 | export default optionsFromQuery 29 | -------------------------------------------------------------------------------- /src/core/config/sources/runtime.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | * 4 | * Receives options at runtime. 5 | */ 6 | 7 | /* eslint-disable no-undef */ 8 | const optionsFromRuntime = () => () => { 9 | const options = {} 10 | 11 | if (globalThis.location) { 12 | options.oauth2RedirectUrl = `${globalThis.location.protocol}//${globalThis.location.host}${globalThis.location.pathname.substring(0, globalThis.location.pathname.lastIndexOf("/"))}/oauth2-redirect.html` 13 | } 14 | 15 | return options 16 | } 17 | 18 | export default optionsFromRuntime 19 | -------------------------------------------------------------------------------- /src/core/config/sources/url.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | * Receives options from a remote URL. 4 | */ 5 | const makeDeferred = () => { 6 | const deferred = {} 7 | deferred.promise = new Promise((resolve, reject) => { 8 | deferred.resolve = resolve 9 | deferred.reject = reject 10 | }) 11 | return deferred 12 | } 13 | 14 | const optionsFromURL = 15 | ({ url, system }) => 16 | async (options) => { 17 | if (!url) return {} 18 | if (typeof system.configsActions?.getConfigByUrl !== "function") return {} 19 | const deferred = makeDeferred() 20 | const callback = (fetchedOptions) => { 21 | // receives null on remote URL fetch failure 22 | deferred.resolve(fetchedOptions) 23 | } 24 | 25 | system.configsActions.getConfigByUrl( 26 | { 27 | url, 28 | loadRemoteConfig: true, 29 | requestInterceptor: options.requestInterceptor, 30 | responseInterceptor: options.responseInterceptor, 31 | }, 32 | callback 33 | ) 34 | 35 | return deferred.promise 36 | } 37 | 38 | export default optionsFromURL 39 | -------------------------------------------------------------------------------- /src/core/config/type-cast/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import has from "lodash/has" 5 | import get from "lodash/get" 6 | import set from "lodash/fp/set" 7 | 8 | import mappings from "./mappings" 9 | 10 | const typeCast = (options) => { 11 | return Object.entries(mappings).reduce( 12 | (acc, [optionPath, { typeCaster, defaultValue }]) => { 13 | if (has(acc, optionPath)) { 14 | const uncasted = get(acc, optionPath) 15 | const casted = typeCaster(uncasted, defaultValue) 16 | acc = set(optionPath, casted, acc) 17 | } 18 | return acc 19 | }, 20 | { ...options } 21 | ) 22 | } 23 | 24 | export default typeCast 25 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const arrayTypeCaster = (value, defaultValue = []) => 5 | Array.isArray(value) ? value : defaultValue 6 | 7 | export default arrayTypeCaster 8 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/boolean.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const booleanTypeCaster = (value, defaultValue = false) => 5 | value === true || value === "true" || value === 1 || value === "1" 6 | ? true 7 | : value === false || value === "false" || value === 0 || value === "0" 8 | ? false 9 | : defaultValue 10 | 11 | export default booleanTypeCaster 12 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/dom-node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const domNodeTypeCaster = (value) => 5 | value === null || value === "null" ? null : value 6 | 7 | export default domNodeTypeCaster 8 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import booleanTypeCaster from "./boolean" 5 | 6 | const filterTypeCaster = (value) => { 7 | const defaultValue = String(value) 8 | return booleanTypeCaster(value, defaultValue) 9 | } 10 | 11 | export default filterTypeCaster 12 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/function.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const functionTypeCaster = (value, defaultValue) => 5 | typeof value === "function" ? value : defaultValue 6 | 7 | export default functionTypeCaster 8 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/nullable-array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const nullableArrayTypeCaster = (value) => (Array.isArray(value) ? value : null) 5 | 6 | export default nullableArrayTypeCaster 7 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/nullable-function.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const nullableFunctionTypeCaster = (value) => 5 | typeof value === "function" ? value : null 6 | 7 | export default nullableFunctionTypeCaster 8 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/nullable-string.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const nullableStringTypeCaster = (value) => 5 | value === null || value === "null" ? null : String(value) 6 | 7 | export default nullableStringTypeCaster 8 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const numberTypeCaster = (value, defaultValue = -1) => { 5 | const parsedValue = parseInt(value, 10) 6 | return Number.isNaN(parsedValue) ? defaultValue : parsedValue 7 | } 8 | 9 | export default numberTypeCaster 10 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/object.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import isPlainObject from "lodash/isPlainObject" 5 | 6 | const objectTypeCaster = (value, defaultValue = {}) => 7 | isPlainObject(value) ? value : defaultValue 8 | 9 | export default objectTypeCaster 10 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/sorter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const sorterTypeCaster = (value) => 5 | typeof value === "function" || typeof value === "string" ? value : null 6 | 7 | export default sorterTypeCaster 8 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/string.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const stringTypeCaster = (value) => String(value) 5 | 6 | export default stringTypeCaster 7 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/syntax-highlight.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import isPlainObject from "lodash/isPlainObject" 5 | 6 | const syntaxHighlightTypeCaster = (value, defaultValue) => { 7 | return isPlainObject(value) 8 | ? value 9 | : value === false || value === "false" || value === 0 || value === "0" 10 | ? { activated: false } 11 | : defaultValue 12 | } 13 | 14 | export default syntaxHighlightTypeCaster 15 | -------------------------------------------------------------------------------- /src/core/config/type-cast/type-casters/undefined-string.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const undefinedStringTypeCaster = (value) => 5 | value === undefined || value === "undefined" ? undefined : String(value) 6 | 7 | export default undefinedStringTypeCaster 8 | -------------------------------------------------------------------------------- /src/core/containers/authorize-btn.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default class AuthorizeBtnContainer extends React.Component { 5 | 6 | static propTypes = { 7 | specActions: PropTypes.object.isRequired, 8 | specSelectors: PropTypes.object.isRequired, 9 | authActions: PropTypes.object.isRequired, 10 | authSelectors: PropTypes.object.isRequired, 11 | getComponent: PropTypes.func.isRequired 12 | } 13 | 14 | render () { 15 | const { authActions, authSelectors, specSelectors, getComponent} = this.props 16 | 17 | const securityDefinitions = specSelectors.securityDefinitions() 18 | const authorizableDefinitions = authSelectors.definitionsToAuthorize() 19 | 20 | const AuthorizeBtn = getComponent("authorizeBtn") 21 | 22 | return securityDefinitions ? ( 23 | authActions.showDefinitions(authorizableDefinitions)} 25 | isAuthorized={!!authSelectors.authorized().size} 26 | showPopup={!!authSelectors.shownDefinitions()} 27 | getComponent={getComponent} 28 | /> 29 | ) : null 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/core/containers/info.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default class InfoContainer extends React.Component { 5 | 6 | static propTypes = { 7 | specActions: PropTypes.object.isRequired, 8 | specSelectors: PropTypes.object.isRequired, 9 | getComponent: PropTypes.func.isRequired, 10 | oas3Selectors: PropTypes.func.isRequired, 11 | } 12 | 13 | render () { 14 | const {specSelectors, getComponent, oas3Selectors} = this.props 15 | 16 | const info = specSelectors.info() 17 | const url = specSelectors.url() 18 | const basePath = specSelectors.basePath() 19 | const host = specSelectors.host() 20 | const externalDocs = specSelectors.externalDocs() 21 | const selectedServer = oas3Selectors.selectedServer() 22 | 23 | const Info = getComponent("info") 24 | 25 | return ( 26 |
27 | {info && info.count() ? ( 28 | 30 | ) : null} 31 |
32 | ) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/core/plugins/auth/components/lock-auth-icon.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | import omit from "lodash/omit" 7 | 8 | class LockAuthIcon extends React.Component { 9 | mapStateToProps(state, props) { 10 | const ownProps = omit(props, Object.keys(props.getSystem())) 11 | return { state, ownProps } 12 | } 13 | 14 | render() { 15 | const { getComponent, ownProps } = this.props 16 | const LockIcon = getComponent("LockIcon") 17 | 18 | return 19 | } 20 | } 21 | 22 | LockAuthIcon.propTypes = { 23 | getComponent: PropTypes.func.isRequired, 24 | ownProps: PropTypes.shape({}).isRequired, 25 | } 26 | 27 | export default LockAuthIcon 28 | -------------------------------------------------------------------------------- /src/core/plugins/auth/components/unlock-auth-icon.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | import omit from "lodash/omit" 7 | 8 | class UnlockAuthIcon extends React.Component { 9 | mapStateToProps(state, props) { 10 | const ownProps = omit(props, Object.keys(props.getSystem())) 11 | return { state, ownProps } 12 | } 13 | 14 | render() { 15 | const { getComponent, ownProps } = this.props 16 | const UnlockIcon = getComponent("UnlockIcon") 17 | 18 | return 19 | } 20 | } 21 | 22 | UnlockAuthIcon.propTypes = { 23 | getComponent: PropTypes.func.isRequired, 24 | ownProps: PropTypes.shape({}).isRequired, 25 | } 26 | 27 | export default UnlockAuthIcon 28 | -------------------------------------------------------------------------------- /src/core/plugins/auth/configs-extensions/wrap-actions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | export const loaded = (oriAction, system) => (payload) => { 5 | const { getConfigs, authActions } = system 6 | const configs = getConfigs() 7 | 8 | oriAction(payload) 9 | 10 | // check if we should restore authorization data from localStorage 11 | if (configs.persistAuthorization) { 12 | const authorized = localStorage.getItem("authorized") 13 | if (authorized) { 14 | authActions.restoreAuthorization({ 15 | authorized: JSON.parse(authorized), 16 | }) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/core/plugins/auth/spec-extensions/wrap-actions.js: -------------------------------------------------------------------------------- 1 | // Add security to the final `execute` call ( via `extras` ) 2 | export const execute = ( oriAction, { authSelectors, specSelectors }) => ({ path, method, operation, extras }) => { 3 | let securities = { 4 | authorized: authSelectors.authorized() && authSelectors.authorized().toJS(), 5 | definitions: specSelectors.securityDefinitions() && specSelectors.securityDefinitions().toJS(), 6 | specSecurity: specSelectors.security() && specSelectors.security().toJS() 7 | } 8 | 9 | return oriAction({ path, method, operation, securities, ...extras }) 10 | } 11 | -------------------------------------------------------------------------------- /src/core/plugins/configs/fn.js: -------------------------------------------------------------------------------- 1 | import YAML from "js-yaml" 2 | 3 | export const parseConfig = (yaml, system) => { 4 | try { 5 | return YAML.load(yaml) 6 | } catch(e) { 7 | if (system) { 8 | system.errActions.newThrownErr( new Error(e) ) 9 | } 10 | return {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/core/plugins/configs/index.js: -------------------------------------------------------------------------------- 1 | import * as actions from "./actions" 2 | import * as selectors from "./selectors" 3 | import reducers from "./reducers" 4 | 5 | export default function configsPlugin() { 6 | 7 | return { 8 | statePlugins: { 9 | configs: { 10 | reducers, 11 | actions, 12 | selectors, 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/core/plugins/configs/reducers.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from "immutable" 2 | 3 | import { 4 | UPDATE_CONFIGS, 5 | TOGGLE_CONFIGS, 6 | } from "./actions" 7 | 8 | export default { 9 | 10 | [UPDATE_CONFIGS]: (state, action) => { 11 | return state.merge(fromJS(action.payload)) 12 | }, 13 | 14 | [TOGGLE_CONFIGS]: (state, action) => { 15 | const configName = action.payload 16 | const oriVal = state.get(configName) 17 | return state.set(configName, !oriVal) 18 | }, 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/core/plugins/configs/selectors.js: -------------------------------------------------------------------------------- 1 | // Just get the config value ( it can possibly be an immutable object) 2 | export const get = (state, path) => { 3 | return state.getIn(Array.isArray(path) ? path : [path]) 4 | } 5 | -------------------------------------------------------------------------------- /src/core/plugins/deep-linking/README.md: -------------------------------------------------------------------------------- 1 | See `docs/deep-linking.md`. 2 | -------------------------------------------------------------------------------- /src/core/plugins/deep-linking/helpers.js: -------------------------------------------------------------------------------- 1 | export const setHash = (value) => { 2 | if(value) { 3 | return history.pushState(null, null, `#${value}`) 4 | } else { 5 | return window.location.hash = "" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/core/plugins/deep-linking/index.js: -------------------------------------------------------------------------------- 1 | import layout from "./layout" 2 | import OperationWrapper from "./operation-wrapper" 3 | import OperationTagWrapper from "./operation-tag-wrapper" 4 | 5 | export default function() { 6 | return [layout, { 7 | statePlugins: { 8 | configs: { 9 | wrapActions: { 10 | loaded: (ori, system) => (...args) => { 11 | ori(...args) 12 | // location.hash was an UTF-16 String, here is required UTF-8 13 | const hash = decodeURIComponent(window.location.hash) 14 | system.layoutActions.parseDeepLinkHash(hash) 15 | } 16 | } 17 | } 18 | }, 19 | wrapComponents: { 20 | operation: OperationWrapper, 21 | OperationTag: OperationTagWrapper, 22 | }, 23 | }] 24 | } 25 | -------------------------------------------------------------------------------- /src/core/plugins/deep-linking/operation-tag-wrapper.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { PropTypes } from "prop-types" 3 | 4 | const Wrapper = (Ori, system) => class OperationTagWrapper extends React.Component { 5 | 6 | static propTypes = { 7 | tag: PropTypes.object.isRequired, 8 | } 9 | 10 | onLoad = (ref) => { 11 | const { tag } = this.props 12 | const isShownKey = ["operations-tag", tag] 13 | system.layoutActions.readyToScroll(isShownKey, ref) 14 | } 15 | 16 | render() { 17 | return ( 18 | 19 | 20 | 21 | ) 22 | } 23 | } 24 | 25 | export default Wrapper 26 | -------------------------------------------------------------------------------- /src/core/plugins/deep-linking/operation-wrapper.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import ImPropTypes from "react-immutable-proptypes" 3 | 4 | const Wrapper = (Ori, system) => class OperationWrapper extends React.Component { 5 | 6 | static propTypes = { 7 | operation: ImPropTypes.map.isRequired, 8 | } 9 | 10 | onLoad = (ref) => { 11 | const { operation } = this.props 12 | const { tag, operationId } = operation.toObject() 13 | let { isShownKey } = operation.toObject() 14 | isShownKey = isShownKey || ["operations", tag, operationId] 15 | system.layoutActions.readyToScroll(isShownKey, ref) 16 | } 17 | 18 | render() { 19 | return ( 20 | 21 | 22 | 23 | ) 24 | } 25 | } 26 | 27 | export default Wrapper 28 | -------------------------------------------------------------------------------- /src/core/plugins/err/error-transformers/README.md: -------------------------------------------------------------------------------- 1 | # Error transformers 2 | 3 | Error transformers provide a standard interface for making generated error messages more useful to end users. 4 | 5 | ### Inputs & outputs 6 | 7 | Each transformer's `transform` function is given an Immutable List of Immutable Maps as its first argument. 8 | 9 | It is expected that each `transform` function returns a List of similarly-formed Maps. 10 | 11 | These errors originate from the Redux error actions that add errors to state. Errors are transformed before being passed into the reducer. 12 | 13 | It's important that all the keys present in each error (specifically, `line`, `level`, `message`, `source`, and `type`) are present when the transformer is finished. 14 | 15 | ##### Deleting an error 16 | 17 | If you want to delete an error completely, you can overwrite it with `null`. The null value will be filtered out of the transformed error array before the errors are returned. 18 | å 19 | 20 | ### Example transformer 21 | 22 | This transformer will increase all your line numbers by 10. 23 | 24 | ``` 25 | export function transform(errors) { 26 | return errors.map(err => { 27 | err.line += 10 28 | return err 29 | }) 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /src/core/plugins/err/error-transformers/transformers/not-of-type.js: -------------------------------------------------------------------------------- 1 | export function transform(errors) { 2 | // JSONSchema refers to the current object being validated 3 | // as 'instance'. This isn't helpful to users, so we remove it. 4 | return errors 5 | .map(err => { 6 | let seekStr = "is not of a type(s)" 7 | let i = err.get("message").indexOf(seekStr) 8 | if(i > -1) { 9 | let types = err.get("message").slice(i + seekStr.length).split(",") 10 | return err.set("message", err.get("message").slice(0, i) + makeNewMessage(types)) 11 | } else { 12 | return err 13 | } 14 | }) 15 | } 16 | 17 | function makeNewMessage(types) { 18 | return types.reduce((p, c, i, arr) => { 19 | if(i === arr.length - 1 && arr.length > 1) { 20 | return p + "or " + c 21 | } else if(arr[i+1] && arr.length > 2) { 22 | return p + c + ", " 23 | } else if(arr[i+1]) { 24 | return p + c + " " 25 | } else { 26 | return p + c 27 | } 28 | }, "should be a") 29 | } 30 | -------------------------------------------------------------------------------- /src/core/plugins/err/index.js: -------------------------------------------------------------------------------- 1 | import makeReducers from "./reducers" 2 | import * as actions from "./actions" 3 | import * as selectors from "./selectors" 4 | 5 | export default function(system) { 6 | return { 7 | statePlugins: { 8 | err: { 9 | reducers: makeReducers(system), 10 | actions, 11 | selectors 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/core/plugins/err/selectors.js: -------------------------------------------------------------------------------- 1 | import { List } from "immutable" 2 | import { createSelector } from "reselect" 3 | 4 | const state = state => state 5 | 6 | export const allErrors = createSelector( 7 | state, 8 | err => err.get("errors", List()) 9 | ) 10 | 11 | export const lastError = createSelector( 12 | allErrors, 13 | all => all.last() 14 | ) 15 | 16 | -------------------------------------------------------------------------------- /src/core/plugins/filter/index.js: -------------------------------------------------------------------------------- 1 | import opsFilter from "./opsFilter" 2 | 3 | export default function() { 4 | return { 5 | fn: { 6 | opsFilter 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/core/plugins/filter/opsFilter.js: -------------------------------------------------------------------------------- 1 | export default function(taggedOps, phrase) { 2 | return taggedOps.filter((tagObj, tag) => tag.indexOf(phrase) !== -1) 3 | } 4 | -------------------------------------------------------------------------------- /src/core/plugins/icons/components/arrow-down.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const ArrowDown = ({ className = null, width = 20, height = 20, ...rest }) => ( 8 | 20 | ) 21 | 22 | ArrowDown.propTypes = { 23 | className: PropTypes.string, 24 | width: PropTypes.string, 25 | height: PropTypes.string, 26 | } 27 | 28 | export default ArrowDown 29 | -------------------------------------------------------------------------------- /src/core/plugins/icons/components/arrow-up.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const ArrowUp = ({ className = null, width = 20, height = 20, ...rest }) => ( 8 | 20 | ) 21 | 22 | ArrowUp.propTypes = { 23 | className: PropTypes.string, 24 | width: PropTypes.string, 25 | height: PropTypes.string, 26 | } 27 | 28 | export default ArrowUp 29 | -------------------------------------------------------------------------------- /src/core/plugins/icons/components/arrow.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const Arrow = ({ className = null, width = 20, height = 20, ...rest }) => ( 8 | 20 | ) 21 | 22 | Arrow.propTypes = { 23 | className: PropTypes.string, 24 | width: PropTypes.string, 25 | height: PropTypes.string, 26 | } 27 | 28 | export default Arrow 29 | -------------------------------------------------------------------------------- /src/core/plugins/icons/components/close.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const Close = ({ className = null, width = 20, height = 20, ...rest }) => ( 8 | 20 | ) 21 | 22 | Close.propTypes = { 23 | className: PropTypes.string, 24 | width: PropTypes.string, 25 | height: PropTypes.string, 26 | } 27 | 28 | export default Close 29 | -------------------------------------------------------------------------------- /src/core/plugins/icons/components/copy.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const Copy = ({ className = null, width = 15, height = 16, ...rest }) => ( 8 | 26 | ) 27 | 28 | Copy.propTypes = { 29 | className: PropTypes.string, 30 | width: PropTypes.string, 31 | height: PropTypes.string, 32 | } 33 | 34 | export default Copy 35 | -------------------------------------------------------------------------------- /src/core/plugins/icons/components/lock.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const Lock = ({ className = null, width = 20, height = 20, ...rest }) => ( 8 | 20 | ) 21 | 22 | Lock.propTypes = { 23 | className: PropTypes.string, 24 | width: PropTypes.string, 25 | height: PropTypes.string, 26 | } 27 | 28 | export default Lock 29 | -------------------------------------------------------------------------------- /src/core/plugins/icons/components/unlock.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const Unlock = ({ className = null, width = 20, height = 20, ...rest }) => ( 8 | 20 | ) 21 | 22 | Unlock.propTypes = { 23 | className: PropTypes.string, 24 | width: PropTypes.string, 25 | height: PropTypes.string, 26 | } 27 | 28 | export default Unlock 29 | -------------------------------------------------------------------------------- /src/core/plugins/icons/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import ArrowUpIcon from "./components/arrow-up" 5 | import ArrowDownIcon from "./components/arrow-down" 6 | import ArrowIcon from "./components/arrow" 7 | import CloseIcon from "./components/close" 8 | import CopyIcon from "./components/copy" 9 | import LockIcon from "./components/lock" 10 | import UnlockIcon from "./components/unlock" 11 | 12 | const IconsPlugin = () => ({ 13 | components: { 14 | ArrowUpIcon, 15 | ArrowDownIcon, 16 | ArrowIcon, 17 | CloseIcon, 18 | CopyIcon, 19 | LockIcon, 20 | UnlockIcon, 21 | }, 22 | }) 23 | 24 | export default IconsPlugin 25 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/api/encoderAPI.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | import EncoderRegistry from "../class/EncoderRegistry" 6 | 7 | const registry = new EncoderRegistry() 8 | 9 | const encoderAPI = (encodingName, encoder) => { 10 | if (typeof encoder === "function") { 11 | return registry.register(encodingName, encoder) 12 | } else if (encoder === null) { 13 | return registry.unregister(encodingName) 14 | } 15 | 16 | return registry.get(encodingName) 17 | } 18 | encoderAPI.getDefaults = () => registry.defaults 19 | 20 | export default encoderAPI 21 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/api/formatAPI.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | import FormatRegistry from "../class/FormatRegistry" 6 | 7 | const registry = new FormatRegistry() 8 | 9 | const formatAPI = (format, generator) => { 10 | if (typeof generator === "function") { 11 | return registry.register(format, generator) 12 | } else if (generator === null) { 13 | return registry.unregister(format) 14 | } 15 | 16 | return registry.get(format) 17 | } 18 | formatAPI.getDefaults = () => registry.defaults 19 | 20 | export default formatAPI 21 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/api/mediaTypeAPI.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | import MediaTypeRegistry from "../class/MediaTypeRegistry" 6 | 7 | const registry = new MediaTypeRegistry() 8 | 9 | const mediaTypeAPI = (mediaType, generator) => { 10 | if (typeof generator === "function") { 11 | return registry.register(mediaType, generator) 12 | } else if (generator === null) { 13 | return registry.unregister(mediaType) 14 | } 15 | 16 | const mediaTypeNoParams = mediaType.split(";").at(0) 17 | const topLevelMediaType = `${mediaTypeNoParams.split("/").at(0)}/*` 18 | 19 | return ( 20 | registry.get(mediaType) || 21 | registry.get(mediaTypeNoParams) || 22 | registry.get(topLevelMediaType) 23 | ) 24 | } 25 | mediaTypeAPI.getDefaults = () => registry.defaults 26 | 27 | export default mediaTypeAPI 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/api/optionAPI.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | import OptionRegistry from "../class/OptionRegistry" 6 | 7 | const registry = new OptionRegistry() 8 | 9 | const optionAPI = (optionName, optionValue) => { 10 | if (typeof optionValue !== "undefined") { 11 | registry.register(optionName, optionValue) 12 | } 13 | 14 | return registry.get(optionName) 15 | } 16 | 17 | export default optionAPI 18 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/class/EncoderRegistry.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import Registry from "./Registry" 5 | import encode7bit from "../encoders/7bit" 6 | import encode8bit from "../encoders/8bit" 7 | import encodeBinary from "../encoders/binary" 8 | import encodeQuotedPrintable from "../encoders/quoted-printable" 9 | import encodeBase16 from "../encoders/base16" 10 | import encodeBase32 from "../encoders/base32" 11 | import encodeBase64 from "../encoders/base64" 12 | import encodeBase64Url from "../encoders/base64url" 13 | 14 | class EncoderRegistry extends Registry { 15 | #defaults = { 16 | "7bit": encode7bit, 17 | "8bit": encode8bit, 18 | binary: encodeBinary, 19 | "quoted-printable": encodeQuotedPrintable, 20 | base16: encodeBase16, 21 | base32: encodeBase32, 22 | base64: encodeBase64, 23 | base64url: encodeBase64Url, 24 | } 25 | 26 | data = { ...this.#defaults } 27 | 28 | get defaults() { 29 | return { ...this.#defaults } 30 | } 31 | } 32 | 33 | export default EncoderRegistry 34 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/class/MediaTypeRegistry.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import Registry from "./Registry" 5 | import textMediaTypesGenerators from "../generators/media-types/text" 6 | import imageMediaTypesGenerators from "../generators/media-types/image" 7 | import audioMediaTypesGenerators from "../generators/media-types/audio" 8 | import videoMediaTypesGenerators from "../generators/media-types/video" 9 | import applicationMediaTypesGenerators from "../generators/media-types/application" 10 | 11 | class MediaTypeRegistry extends Registry { 12 | #defaults = { 13 | ...textMediaTypesGenerators, 14 | ...imageMediaTypesGenerators, 15 | ...audioMediaTypesGenerators, 16 | ...videoMediaTypesGenerators, 17 | ...applicationMediaTypesGenerators, 18 | } 19 | 20 | data = { ...this.#defaults } 21 | 22 | get defaults() { 23 | return { ...this.#defaults } 24 | } 25 | } 26 | 27 | export default MediaTypeRegistry 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/class/OptionRegistry.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import Registry from "./Registry" 5 | 6 | class OptionRegistry extends Registry { 7 | #defaults = {} 8 | 9 | data = { ...this.#defaults } 10 | 11 | get defaults() { 12 | return { ...this.#defaults } 13 | } 14 | } 15 | 16 | export default OptionRegistry 17 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/class/Registry.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | class Registry { 5 | data = {} 6 | 7 | register(name, value) { 8 | this.data[name] = value 9 | } 10 | 11 | unregister(name) { 12 | if (typeof name === "undefined") { 13 | this.data = {} 14 | } else { 15 | delete this.data[name] 16 | } 17 | } 18 | 19 | get(name) { 20 | return this.data[name] 21 | } 22 | } 23 | 24 | export default Registry 25 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/core/constants.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | export const SCALAR_TYPES = ["number", "integer", "string", "boolean", "null"] 5 | 6 | export const ALL_TYPES = ["array", "object", ...SCALAR_TYPES] 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/core/predicates.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import isPlainObject from "lodash/isPlainObject" 5 | 6 | export const isBooleanJSONSchema = (schema) => { 7 | return typeof schema === "boolean" 8 | } 9 | 10 | export const isJSONSchemaObject = (schema) => { 11 | return isPlainObject(schema) 12 | } 13 | 14 | export const isJSONSchema = (schema) => { 15 | return isBooleanJSONSchema(schema) || isJSONSchemaObject(schema) 16 | } 17 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/core/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { isBooleanJSONSchema, isJSONSchemaObject } from "./predicates" 5 | 6 | export const fromJSONBooleanSchema = (schema) => { 7 | if (schema === false) { 8 | return { not: {} } 9 | } 10 | 11 | return {} 12 | } 13 | 14 | export const typeCast = (schema) => { 15 | if (isBooleanJSONSchema(schema)) { 16 | return fromJSONBooleanSchema(schema) 17 | } 18 | if (!isJSONSchemaObject(schema)) { 19 | return {} 20 | } 21 | 22 | return schema 23 | } 24 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/encoders/7bit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const encode7bit = (content) => Buffer.from(content).toString("ascii") 5 | 6 | export default encode7bit 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/encoders/8bit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const encode8bit = (content) => Buffer.from(content).toString("utf8") 5 | 6 | export default encode8bit 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/encoders/base16.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const encodeBase16 = (content) => Buffer.from(content).toString("hex") 5 | 6 | export default encodeBase16 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/encoders/base32.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const encodeBase32 = (content) => { 5 | const utf8Value = Buffer.from(content).toString("utf8") 6 | const base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" 7 | let paddingCount = 0 8 | let base32Str = "" 9 | let buffer = 0 10 | let bufferLength = 0 11 | 12 | for (let i = 0; i < utf8Value.length; i++) { 13 | buffer = (buffer << 8) | utf8Value.charCodeAt(i) 14 | bufferLength += 8 15 | 16 | while (bufferLength >= 5) { 17 | base32Str += base32Alphabet.charAt((buffer >>> (bufferLength - 5)) & 31) 18 | bufferLength -= 5 19 | } 20 | } 21 | 22 | if (bufferLength > 0) { 23 | base32Str += base32Alphabet.charAt((buffer << (5 - bufferLength)) & 31) 24 | paddingCount = (8 - ((utf8Value.length * 8) % 5)) % 5 25 | } 26 | 27 | for (let i = 0; i < paddingCount; i++) { 28 | base32Str += "=" 29 | } 30 | 31 | return base32Str 32 | } 33 | 34 | export default encodeBase32 35 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/encoders/base64.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const encodeBase64 = (content) => Buffer.from(content).toString("base64") 5 | 6 | export default encodeBase64 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/encoders/base64url.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const encodeBase64Url = (content) => Buffer.from(content).toString("base64url") 5 | 6 | export default encodeBase64Url 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/encoders/binary.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const encodeBinary = (content) => Buffer.from(content).toString("binary") 5 | 6 | export default encodeBinary 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/encoders/quoted-printable.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const encodeQuotedPrintable = (content) => { 5 | let quotedPrintable = "" 6 | 7 | for (let i = 0; i < content.length; i++) { 8 | const charCode = content.charCodeAt(i) 9 | 10 | if (charCode === 61) { 11 | // ASCII content of "=" 12 | quotedPrintable += "=3D" 13 | } else if ( 14 | (charCode >= 33 && charCode <= 60) || 15 | (charCode >= 62 && charCode <= 126) || 16 | charCode === 9 || 17 | charCode === 32 18 | ) { 19 | quotedPrintable += content.charAt(i) 20 | } else if (charCode === 13 || charCode === 10) { 21 | quotedPrintable += "\r\n" 22 | } else if (charCode > 126) { 23 | // convert non-ASCII characters to UTF-8 and encode each byte 24 | const utf8 = unescape(encodeURIComponent(content.charAt(i))) 25 | for (let j = 0; j < utf8.length; j++) { 26 | quotedPrintable += 27 | "=" + ("0" + utf8.charCodeAt(j).toString(16)).slice(-2).toUpperCase() 28 | } 29 | } else { 30 | quotedPrintable += 31 | "=" + ("0" + charCode.toString(16)).slice(-2).toUpperCase() 32 | } 33 | } 34 | 35 | return quotedPrintable 36 | } 37 | 38 | export default encodeQuotedPrintable 39 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/date-time.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const dateTimeGenerator = () => new Date().toISOString() 5 | 6 | export default dateTimeGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/date.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const dateGenerator = () => new Date().toISOString().substring(0, 10) 5 | 6 | export default dateGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/double.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const doubleGenerator = () => 0.1 5 | 6 | export default doubleGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/duration.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const durationGenerator = () => "P3D" // expresses a duration of 3 days 5 | 6 | export default durationGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/email.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const emailGenerator = () => "user@example.com" 5 | 6 | export default emailGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/float.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const floatGenerator = () => 0.1 5 | 6 | export default floatGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/hostname.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const hostnameGenerator = () => "example.com" 5 | 6 | export default hostnameGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/idn-email.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const idnEmailGenerator = () => "실례@example.com" 5 | 6 | export default idnEmailGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/idn-hostname.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const idnHostnameGenerator = () => "실례.com" 5 | 6 | export default idnHostnameGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/int32.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const int32Generator = () => 0 5 | 6 | export default int32Generator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/int64.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const int64Generator = () => 0 5 | 6 | export default int64Generator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/ipv4.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const ipv4Generator = () => "198.51.100.42" 5 | 6 | export default ipv4Generator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/ipv6.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const ipv6Generator = () => "2001:0db8:5b96:0000:0000:426f:8e17:642a" 5 | 6 | export default ipv6Generator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/iri-reference.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const iriReferenceGenerator = () => "path/실례.html" 5 | 6 | export default iriReferenceGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/iri.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const iriGenerator = () => "https://실례.com/" 5 | 6 | export default iriGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/json-pointer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const jsonPointerGenerator = () => "/a/b/c" 5 | 6 | export default jsonPointerGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/application.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { bytes } from "../../core/random" 5 | 6 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types 7 | const applicationMediaTypesGenerators = { 8 | "application/json": () => '{"key":"value"}', 9 | "application/ld+json": () => '{"name": "John Doe"}', 10 | "application/x-httpd-php": () => "Hello World!

'; ?>", 11 | "application/rtf": () => String.raw`{\rtf1\adeflang1025\ansi\ansicpg1252\uc1`, 12 | "application/x-sh": () => 'echo "Hello World!"', 13 | "application/xhtml+xml": () => "

content

", 14 | "application/*": () => bytes(25).toString("binary"), 15 | } 16 | 17 | export default applicationMediaTypesGenerators 18 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/audio.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { bytes } from "../../core/random" 5 | 6 | const audioMediaTypesGenerators = { 7 | "audio/*": () => bytes(25).toString("binary"), 8 | } 9 | 10 | export default audioMediaTypesGenerators 11 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/image.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { bytes } from "../../core/random" 5 | 6 | const imageMediaTypesGenerators = { 7 | "image/*": () => bytes(25).toString("binary"), 8 | } 9 | 10 | export default imageMediaTypesGenerators 11 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/text.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types 6 | const textMediaTypesGenerators = { 7 | "text/plain": () => "string", 8 | "text/css": () => ".selector { border: 1px solid red }", 9 | "text/csv": () => "value1,value2,value3", 10 | "text/html": () => "

content

", 11 | "text/calendar": () => "BEGIN:VCALENDAR", 12 | "text/javascript": () => "console.dir('Hello world!');", 13 | "text/xml": () => 'John Doe', 14 | "text/*": () => "string", 15 | } 16 | 17 | export default textMediaTypesGenerators 18 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/media-types/video.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { bytes } from "../../core/random" 5 | 6 | const videoMediaTypesGenerators = { 7 | "video/*": () => bytes(25).toString("binary"), 8 | } 9 | 10 | export default videoMediaTypesGenerators 11 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/password.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const passwordGenerator = () => "********" 5 | 6 | export default passwordGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/regex.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const regexGenerator = () => "^[a-z]+$" 5 | 6 | export default regexGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/relative-json-pointer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const relativeJsonPointerGenerator = () => "1/0" 5 | 6 | export default relativeJsonPointerGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/time.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const timeGenerator = () => new Date().toISOString().substring(11) 5 | 6 | export default timeGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/uri-reference.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const uriReferenceGenerator = () => "path/index.html" 5 | 6 | export default uriReferenceGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/uri-template.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const uriTemplateGenerator = () => 5 | "https://example.com/dictionary/{term:1}/{term}" 6 | 7 | export default uriTemplateGenerator 8 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/uri.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const uriGenerator = () => "https://example.com/" 5 | 6 | export default uriGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/generators/uuid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const uuidGenerator = () => "3fa85f64-5717-4562-b3fc-2c963f66afa6" 5 | 6 | export default uuidGenerator 7 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/get-json-sample-schema.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import some from "lodash/some" 5 | 6 | const shouldStringifyTypesConfig = [ 7 | { 8 | when: /json/, 9 | shouldStringifyTypes: ["string"], 10 | }, 11 | ] 12 | const defaultStringifyTypes = ["object"] 13 | const makeGetJsonSampleSchema = 14 | (getSystem) => (schema, config, contentType, exampleOverride) => { 15 | const { fn } = getSystem() 16 | const res = fn.jsonSchema202012.memoizedSampleFromSchema( 17 | schema, 18 | config, 19 | exampleOverride 20 | ) 21 | const resType = typeof res 22 | 23 | const typesToStringify = shouldStringifyTypesConfig.reduce( 24 | (types, nextConfig) => 25 | nextConfig.when.test(contentType) 26 | ? [...types, ...nextConfig.shouldStringifyTypes] 27 | : types, 28 | defaultStringifyTypes 29 | ) 30 | 31 | return some(typesToStringify, (x) => x === resType) 32 | ? JSON.stringify(res, null, 2) 33 | : res 34 | } 35 | 36 | export default makeGetJsonSampleSchema 37 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/get-sample-schema.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const makeGetSampleSchema = 5 | (getSystem) => 6 | (schema, contentType = "", config = {}, exampleOverride = undefined) => { 7 | const { fn } = getSystem() 8 | 9 | if (typeof schema?.toJS === "function") { 10 | schema = schema.toJS() 11 | } 12 | if (typeof exampleOverride?.toJS === "function") { 13 | exampleOverride = exampleOverride.toJS() 14 | } 15 | 16 | if (/xml/.test(contentType)) { 17 | return fn.jsonSchema202012.getXmlSampleSchema( 18 | schema, 19 | config, 20 | exampleOverride 21 | ) 22 | } 23 | if (/(yaml|yml)/.test(contentType)) { 24 | return fn.jsonSchema202012.getYamlSampleSchema( 25 | schema, 26 | config, 27 | contentType, 28 | exampleOverride 29 | ) 30 | } 31 | return fn.jsonSchema202012.getJsonSampleSchema( 32 | schema, 33 | config, 34 | contentType, 35 | exampleOverride 36 | ) 37 | } 38 | 39 | export default makeGetSampleSchema 40 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/get-xml-sample-schema.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const makeGetXmlSampleSchema = 5 | (getSystem) => (schema, config, exampleOverride) => { 6 | const { fn } = getSystem() 7 | 8 | if (schema && !schema.xml) { 9 | schema.xml = {} 10 | } 11 | if (schema && !schema.xml.name) { 12 | if ( 13 | !schema.$$ref && 14 | (schema.type || 15 | schema.items || 16 | schema.properties || 17 | schema.additionalProperties) 18 | ) { 19 | // eslint-disable-next-line quotes 20 | return '\n' 21 | } 22 | if (schema.$$ref) { 23 | let match = schema.$$ref.match(/\S*\/(\S+)$/) 24 | schema.xml.name = match[1] 25 | } 26 | } 27 | 28 | return fn.jsonSchema202012.memoizedCreateXMLExample( 29 | schema, 30 | config, 31 | exampleOverride 32 | ) 33 | } 34 | 35 | export default makeGetXmlSampleSchema 36 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/get-yaml-sample-schema.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import YAML, { JSON_SCHEMA } from "js-yaml" 5 | 6 | const makeGetYamlSampleSchema = 7 | (getSystem) => (schema, config, contentType, exampleOverride) => { 8 | const { fn } = getSystem() 9 | const jsonExample = fn.jsonSchema202012.getJsonSampleSchema( 10 | schema, 11 | config, 12 | contentType, 13 | exampleOverride 14 | ) 15 | let yamlString 16 | try { 17 | yamlString = YAML.dump( 18 | YAML.load(jsonExample), 19 | { 20 | lineWidth: -1, // don't generate line folds 21 | }, 22 | { schema: JSON_SCHEMA } 23 | ) 24 | if (yamlString[yamlString.length - 1] === "\n") { 25 | yamlString = yamlString.slice(0, yamlString.length - 1) 26 | } 27 | } catch (e) { 28 | console.error(e) 29 | return "error: could not generate yaml example" 30 | } 31 | return yamlString.replace(/\t/g, " ") 32 | } 33 | 34 | export default makeGetYamlSampleSchema 35 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | export { 5 | sampleFromSchema, 6 | sampleFromSchemaGeneric, 7 | createXMLExample, 8 | memoizedSampleFromSchema, 9 | memoizedCreateXMLExample, 10 | } from "./main" 11 | export { default as optionAPI } from "./api/optionAPI" 12 | export { default as encoderAPI } from "./api/encoderAPI" 13 | export { default as formatAPI } from "./api/formatAPI" 14 | export { default as mediaTypeAPI } from "./api/mediaTypeAPI" 15 | export { default as mergeJsonSchema } from "./core/merge" 16 | export { foldType } from "./core/type" 17 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/types/boolean.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | const booleanType = (schema) => { 6 | return typeof schema.default === "boolean" ? schema.default : true 7 | } 8 | 9 | export default booleanType 10 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/types/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import arrayType from "./array" 5 | import objectType from "./object" 6 | import stringType from "./string" 7 | import numberType from "./number" 8 | import integerType from "./integer" 9 | import booleanType from "./boolean" 10 | import nullType from "./null" 11 | 12 | const typeMap = { 13 | array: arrayType, 14 | object: objectType, 15 | string: stringType, 16 | number: numberType, 17 | integer: integerType, 18 | boolean: booleanType, 19 | null: nullType, 20 | } 21 | 22 | export default new Proxy(typeMap, { 23 | get(target, prop) { 24 | if (typeof prop === "string" && Object.hasOwn(target, prop)) { 25 | return target[prop] 26 | } 27 | 28 | return () => `Unknown Type: ${prop}` 29 | }, 30 | }) 31 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/types/integer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { integer as randomInteger } from "../core/random" 5 | import formatAPI from "../api/formatAPI" 6 | import int32Generator from "../generators/int32" 7 | import int64Generator from "../generators/int64" 8 | import { applyNumberConstraints } from "./number" 9 | 10 | const generateFormat = (schema) => { 11 | const { format } = schema 12 | 13 | const formatGenerator = formatAPI(format) 14 | if (typeof formatGenerator === "function") { 15 | return formatGenerator(schema) 16 | } 17 | 18 | switch (format) { 19 | case "int32": { 20 | return int32Generator() 21 | } 22 | case "int64": { 23 | return int64Generator() 24 | } 25 | } 26 | 27 | return randomInteger() 28 | } 29 | 30 | const integerType = (schema) => { 31 | const { format } = schema 32 | let generatedInteger 33 | 34 | if (typeof format === "string") { 35 | generatedInteger = generateFormat(schema) 36 | } else { 37 | generatedInteger = randomInteger() 38 | } 39 | 40 | return applyNumberConstraints(generatedInteger, schema) 41 | } 42 | 43 | export default integerType 44 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/types/null.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | const nullType = () => { 6 | return null 7 | } 8 | 9 | export default nullType 10 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12-samples/fn/types/object.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | const objectType = () => { 6 | throw new Error("Not implemented") 7 | } 8 | 9 | export default objectType 10 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/Accordion/_accordion.scss: -------------------------------------------------------------------------------- 1 | .json-schema-2020-12-accordion { 2 | outline: none; 3 | border: none; 4 | padding-left: 0; 5 | 6 | &__children { 7 | display: inline-block; 8 | } 9 | 10 | &__icon { 11 | width: 18px; 12 | height: 18px; 13 | display: inline-block; 14 | vertical-align: bottom; 15 | 16 | &--expanded { 17 | transition: transform 0.15s ease-in; 18 | transform: rotate(-90deg); 19 | transform-origin: 50% 50%; 20 | } 21 | 22 | &--collapsed { 23 | transition: transform 0.15s ease-in; 24 | transform: rotate(0deg); 25 | transform-origin: 50% 50%; 26 | } 27 | 28 | & svg { 29 | height: 20px; 30 | width: 20px; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/ExpandDeepButton/ExpandDeepButton.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React, { useCallback } from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const ExpandDeepButton = ({ expanded, onClick }) => { 8 | const handleExpansion = useCallback( 9 | (event) => { 10 | onClick(event, !expanded) 11 | }, 12 | [expanded, onClick] 13 | ) 14 | 15 | return ( 16 | 23 | ) 24 | } 25 | 26 | ExpandDeepButton.propTypes = { 27 | expanded: PropTypes.bool.isRequired, 28 | onClick: PropTypes.func.isRequired, 29 | } 30 | 31 | export default ExpandDeepButton 32 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/ExpandDeepButton/_expand-deep-button.scss: -------------------------------------------------------------------------------- 1 | @use "./../../../../../style/variables" as *; 2 | @use "./../../../../../style/type"; 3 | 4 | .json-schema-2020-12-expand-deep-button { 5 | @include type.text_headline($section-models-model-title-font-color); 6 | font-size: 12px; 7 | color: rgb(175, 174, 174); 8 | border: none; 9 | padding-right: 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/JSONSchema/_json-schema.scss: -------------------------------------------------------------------------------- 1 | @use "./../../../../../style/variables" as *; 2 | @use "./../../components/mixins"; 3 | 4 | .json-schema-2020-12 { 5 | margin: 0 20px 15px 20px; 6 | border-radius: 4px; 7 | padding: 12px 0 12px 20px; 8 | background-color: rgba( 9 | $section-models-model-container-background-color, 10 | 0.05 11 | ); 12 | 13 | &:first-of-type { 14 | margin: 20px; 15 | } 16 | 17 | &:last-of-type { 18 | margin: 0 20px; 19 | } 20 | 21 | &--embedded { 22 | background-color: inherit; 23 | padding: 0 inherit 0 inherit; 24 | } 25 | 26 | &-body { 27 | @include mixins.expansion-border; 28 | margin: 2px 0; 29 | 30 | &--collapsed { 31 | display: none; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/JSONViewer/_json-viewer.scss: -------------------------------------------------------------------------------- 1 | @use "./../mixins"; 2 | @use "./../keywords/all"; 3 | 4 | .json-schema-2020-12-json-viewer { 5 | @include mixins.json-schema-2020-12-keyword; 6 | } 7 | 8 | .json-schema-2020-12-json-viewer__name--secondary 9 | + .json-schema-2020-12-json-viewer__value--secondary::before { 10 | content: "="; 11 | } 12 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/_all.scss: -------------------------------------------------------------------------------- 1 | @use "./JSONViewer/json-viewer"; 2 | @use "./JSONSchema/json-schema"; 3 | @use "./Accordion/accordion"; 4 | @use "./ExpandDeepButton/expand-deep-button"; 5 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/icons/ChevronRight.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | const ChevronRight = () => ( 7 | 13 | 14 | 15 | ) 16 | 17 | export default ChevronRight 18 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/$anchor.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const $anchor = ({ schema }) => { 9 | if (!schema?.$anchor) return null 10 | 11 | return ( 12 |
13 | 14 | $anchor 15 | 16 | 17 | {schema.$anchor} 18 | 19 |
20 | ) 21 | } 22 | 23 | $anchor.propTypes = { 24 | schema: schema.isRequired, 25 | } 26 | 27 | export default $anchor 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/$comment.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const $comment = ({ schema }) => { 9 | if (!schema?.$comment) return null 10 | 11 | return ( 12 |
13 | 14 | $comment 15 | 16 | 17 | {schema.$comment} 18 | 19 |
20 | ) 21 | } 22 | 23 | $comment.propTypes = { 24 | schema: schema.isRequired, 25 | } 26 | 27 | export default $comment 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/$dynamicAnchor.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const $dynamicAnchor = ({ schema }) => { 9 | if (!schema?.$dynamicAnchor) return null 10 | 11 | return ( 12 |
13 | 14 | $dynamicAnchor 15 | 16 | 17 | {schema.$dynamicAnchor} 18 | 19 |
20 | ) 21 | } 22 | 23 | $dynamicAnchor.propTypes = { 24 | schema: schema.isRequired, 25 | } 26 | 27 | export default $dynamicAnchor 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/$dynamicRef.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const $dynamicRef = ({ schema }) => { 9 | if (!schema?.$dynamicRef) return null 10 | 11 | return ( 12 |
13 | 14 | $dynamicRef 15 | 16 | 17 | {schema.$dynamicRef} 18 | 19 |
20 | ) 21 | } 22 | 23 | $dynamicRef.propTypes = { 24 | schema: schema.isRequired, 25 | } 26 | 27 | export default $dynamicRef 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/$id.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const $id = ({ schema }) => { 9 | if (!schema?.$id) return null 10 | 11 | return ( 12 |
13 | 14 | $id 15 | 16 | 17 | {schema.$id} 18 | 19 |
20 | ) 21 | } 22 | 23 | $id.propTypes = { 24 | schema: schema.isRequired, 25 | } 26 | 27 | export default $id 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/$ref.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const $ref = ({ schema }) => { 9 | if (!schema?.$ref) return null 10 | 11 | return ( 12 |
13 | 14 | $ref 15 | 16 | 17 | {schema.$ref} 18 | 19 |
20 | ) 21 | } 22 | 23 | $ref.propTypes = { 24 | schema: schema.isRequired, 25 | } 26 | 27 | export default $ref 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/$schema.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const $schema = ({ schema }) => { 9 | if (!schema?.$schema) return null 10 | 11 | return ( 12 |
13 | 14 | $schema 15 | 16 | 17 | {schema.$schema} 18 | 19 |
20 | ) 21 | } 22 | 23 | $schema.propTypes = { 24 | schema: schema.isRequired, 25 | } 26 | 27 | export default $schema 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/$vocabulary/_$vocabulary.scss: -------------------------------------------------------------------------------- 1 | @use "./../../../components/mixins"; 2 | 3 | .json-schema-2020-12 { 4 | &-keyword--\$vocabulary { 5 | ul { 6 | @include mixins.expansion-border; 7 | } 8 | } 9 | 10 | &-\$vocabulary-uri { 11 | margin-left: 35px; 12 | 13 | &--disabled { 14 | text-decoration: line-through; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Const/Const.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../../prop-types" 7 | import { useComponent, useFn } from "../../../hooks" 8 | 9 | const Const = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONViewer = useComponent("JSONViewer") 12 | 13 | if (!fn.hasKeyword(schema, "const")) return null 14 | 15 | return ( 16 | 21 | ) 22 | } 23 | 24 | Const.propTypes = { 25 | schema: schema.isRequired, 26 | } 27 | 28 | export default Const 29 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Const/_const.scss: -------------------------------------------------------------------------------- 1 | @use "./../../mixins"; 2 | 3 | .json-schema-2020-12-keyword--const { 4 | .json-schema-2020-12-json-viewer__name { 5 | @include mixins.json-schema-2020-12-keyword--primary; 6 | } 7 | 8 | .json-schema-2020-12-json-viewer__value { 9 | @include mixins.json-schema-2020-12-keyword--primary; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Constraint/Constraint.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | import { isPlainObject } from "../../../fn" 8 | 9 | /** 10 | * This component represents various constraint keywords 11 | * from JSON Schema 2020-12 validation vocabulary. 12 | */ 13 | const Constraint = ({ constraint }) => { 14 | if ( 15 | !isPlainObject(constraint) || 16 | typeof constraint.scope !== "string" || 17 | typeof constraint.value !== "string" 18 | ) { 19 | return null 20 | } 21 | 22 | return ( 23 | 26 | {constraint.value} 27 | 28 | ) 29 | } 30 | 31 | Constraint.propTypes = { 32 | constraint: PropTypes.shape({ 33 | scope: PropTypes.oneOf(["number", "string", "array", "object"]).isRequired, 34 | value: PropTypes.string.isRequired, 35 | }).isRequired, 36 | } 37 | 38 | export default React.memo(Constraint) 39 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Constraint/_constraint.scss: -------------------------------------------------------------------------------- 1 | @use "./../../../../../../style/type"; 2 | 3 | .json-schema-2020-12__constraint { 4 | @include type.text_code(); 5 | margin-left: 10px; 6 | line-height: 1.5; 7 | padding: 1px 3px; 8 | color: white; 9 | background-color: #805ad5; 10 | border-radius: 4px; 11 | 12 | &--string { 13 | color: white; 14 | background-color: #d69e2e; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Contains.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const Contains = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "contains")) return null 17 | 18 | const name = ( 19 | 20 | Contains 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 27 |
28 | ) 29 | } 30 | 31 | Contains.propTypes = { 32 | schema: schema.isRequired, 33 | } 34 | 35 | export default Contains 36 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/ContentSchema.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const ContentSchema = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "contentSchema")) return null 17 | 18 | const name = ( 19 | 20 | Content schema 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 31 |
32 | ) 33 | } 34 | 35 | ContentSchema.propTypes = { 36 | schema: schema.isRequired, 37 | } 38 | 39 | export default ContentSchema 40 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Default/Default.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../../prop-types" 7 | import { useComponent, useFn } from "../../../hooks" 8 | 9 | const Default = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONViewer = useComponent("JSONViewer") 12 | 13 | if (!fn.hasKeyword(schema, "default")) return null 14 | 15 | return ( 16 | 21 | ) 22 | } 23 | 24 | Default.propTypes = { 25 | schema: schema.isRequired, 26 | } 27 | 28 | export default Default 29 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Default/_default.scss: -------------------------------------------------------------------------------- 1 | @use "./../../mixins"; 2 | 3 | .json-schema-2020-12-keyword--default { 4 | .json-schema-2020-12-json-viewer__name { 5 | @include mixins.json-schema-2020-12-keyword--primary; 6 | } 7 | 8 | .json-schema-2020-12-json-viewer__value { 9 | @include mixins.json-schema-2020-12-keyword--primary; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/DependentRequired.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | import * as propTypes from "../../../prop-types" 8 | 9 | const DependentRequired = ({ dependentRequired }) => { 10 | if (!Array.isArray(dependentRequired) || dependentRequired.length === 0) { 11 | return null 12 | } 13 | 14 | return ( 15 |
16 | 17 | Required when defined 18 | 19 |
    20 | {dependentRequired.map((propertyName) => ( 21 |
  • 22 | 23 | {propertyName} 24 | 25 |
  • 26 | ))} 27 |
28 |
29 | ) 30 | } 31 | 32 | DependentRequired.propTypes = { 33 | schema: propTypes.schema.isRequired, 34 | dependentRequired: PropTypes.arrayOf(PropTypes.string).isRequired, 35 | } 36 | 37 | export default DependentRequired 38 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/DependentRequired/_dependent-required.scss: -------------------------------------------------------------------------------- 1 | .json-schema-2020-12-keyword--dependentRequired { 2 | & > ul { 3 | display: inline-block; 4 | padding: 0; 5 | margin: 0; 6 | 7 | li { 8 | display: inline; 9 | list-style-type: none; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Deprecated.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const Deprecated = ({ schema }) => { 9 | if (schema?.deprecated !== true) return null 10 | 11 | return ( 12 | 13 | deprecated 14 | 15 | ) 16 | } 17 | 18 | Deprecated.propTypes = { 19 | schema: schema.isRequired, 20 | } 21 | 22 | export default Deprecated 23 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Description/Description.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../../prop-types" 7 | 8 | const Description = ({ schema }) => { 9 | if (!schema?.description) return null 10 | 11 | return ( 12 |
13 |
14 | {schema.description} 15 |
16 |
17 | ) 18 | } 19 | 20 | Description.propTypes = { 21 | schema: schema.isRequired, 22 | } 23 | 24 | export default Description 25 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Description/_description.scss: -------------------------------------------------------------------------------- 1 | .json-schema-2020-12-keyword--description { 2 | color: #6b6b6b; 3 | font-size: 12px; 4 | margin-left: 20px; 5 | 6 | & p { 7 | margin: 0; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Else.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const Else = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "else")) return null 17 | 18 | const name = ( 19 | 20 | Else 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 27 |
28 | ) 29 | } 30 | 31 | Else.propTypes = { 32 | schema: schema.isRequired, 33 | } 34 | 35 | export default Else 36 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Enum/Enum.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../../prop-types" 7 | import { useComponent } from "../../../hooks" 8 | 9 | const Enum = ({ schema }) => { 10 | const JSONViewer = useComponent("JSONViewer") 11 | 12 | if (!Array.isArray(schema?.enum)) return null 13 | 14 | return ( 15 | 20 | ) 21 | } 22 | 23 | Enum.propTypes = { 24 | schema: schema.isRequired, 25 | } 26 | 27 | export default Enum 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Enum/_enum.scss: -------------------------------------------------------------------------------- 1 | @use "./../../mixins"; 2 | 3 | .json-schema-2020-12-keyword--enum { 4 | .json-schema-2020-12-json-viewer__name { 5 | @include mixins.json-schema-2020-12-keyword--primary; 6 | } 7 | 8 | .json-schema-2020-12-json-viewer__value { 9 | @include mixins.json-schema-2020-12-keyword--primary; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Examples/Examples.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../../prop-types" 7 | import { useComponent } from "../../../hooks" 8 | 9 | const Examples = ({ schema }) => { 10 | const examples = schema?.examples || [] 11 | const JSONViewer = useComponent("JSONViewer") 12 | 13 | if (!Array.isArray(examples) || examples.length === 0) { 14 | return null 15 | } 16 | 17 | return ( 18 | 23 | ) 24 | } 25 | 26 | Examples.propTypes = { 27 | schema: schema.isRequired, 28 | } 29 | 30 | export default Examples 31 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Examples/_examples.scss: -------------------------------------------------------------------------------- 1 | @use "./../../mixins"; 2 | 3 | .json-schema-2020-12-keyword--examples { 4 | .json-schema-2020-12-json-viewer__name { 5 | @include mixins.json-schema-2020-12-keyword--primary; 6 | } 7 | 8 | .json-schema-2020-12-json-viewer__value { 9 | @include mixins.json-schema-2020-12-keyword--primary; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/ExtensionKeywords/_extension-keywords.scss: -------------------------------------------------------------------------------- 1 | @use "./../../mixins"; 2 | 3 | .json-schema-2020-12-json-viewer-extension-keyword { 4 | .json-schema-2020-12-json-viewer__name { 5 | @include mixins.json-schema-2020-12-keyword--extension; 6 | } 7 | 8 | .json-schema-2020-12-json-viewer__value { 9 | @include mixins.json-schema-2020-12-keyword--extension; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/If.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const If = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "if")) return null 17 | 18 | const name = ( 19 | 20 | If 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 27 |
28 | ) 29 | } 30 | 31 | If.propTypes = { 32 | schema: schema.isRequired, 33 | } 34 | 35 | export default If 36 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Items.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const Items = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "items")) return null 17 | 18 | const name = ( 19 | 20 | Items 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 27 |
28 | ) 29 | } 30 | 31 | Items.propTypes = { 32 | schema: schema.isRequired, 33 | } 34 | 35 | export default Items 36 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Not.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const Not = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "not")) return null 17 | 18 | const name = ( 19 | 20 | Not 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 27 |
28 | ) 29 | } 30 | 31 | Not.propTypes = { 32 | schema: schema.isRequired, 33 | } 34 | 35 | export default Not 36 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/PatternProperties/_pattern-properties.scss: -------------------------------------------------------------------------------- 1 | @use "./../../../../../../style/variables" as *; 2 | 3 | .json-schema-2020-12 { 4 | &-keyword--patternProperties { 5 | ul { 6 | margin: 0; 7 | padding: 0; 8 | border: none; 9 | } 10 | 11 | .json-schema-2020-12__title:first-of-type::before { 12 | color: $prop-type-font-color; 13 | content: "/"; 14 | } 15 | 16 | .json-schema-2020-12__title:first-of-type::after { 17 | color: $prop-type-font-color; 18 | content: "/"; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Properties/_properties.scss: -------------------------------------------------------------------------------- 1 | .json-schema-2020-12 { 2 | &-keyword--properties { 3 | & > ul { 4 | margin: 0; 5 | padding: 0; 6 | border: none; 7 | } 8 | } 9 | 10 | &-property { 11 | list-style-type: none; 12 | 13 | &--required { 14 | & 15 | > .json-schema-2020-12:first-of-type 16 | > .json-schema-2020-12-head 17 | .json-schema-2020-12__title:after { 18 | content: "*"; 19 | color: red; 20 | font-weight: bold; 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/PropertyNames.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const PropertyNames = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | const name = ( 13 | 14 | Property names 15 | 16 | ) 17 | 18 | /** 19 | * Rendering. 20 | */ 21 | if (!fn.hasKeyword(schema, "propertyNames")) return null 22 | 23 | return ( 24 |
25 | 30 |
31 | ) 32 | } 33 | 34 | PropertyNames.propTypes = { 35 | schema: schema.isRequired, 36 | } 37 | 38 | export default PropertyNames 39 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/ReadOnly.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const ReadOnly = ({ schema }) => { 9 | if (schema?.readOnly !== true) return null 10 | 11 | return ( 12 | 13 | read-only 14 | 15 | ) 16 | } 17 | 18 | ReadOnly.propTypes = { 19 | schema: schema.isRequired, 20 | } 21 | 22 | export default ReadOnly 23 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Then.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const Then = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "then")) return null 17 | 18 | const name = ( 19 | 20 | Then 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 27 |
28 | ) 29 | } 30 | 31 | Then.propTypes = { 32 | schema: schema.isRequired, 33 | } 34 | 35 | export default Then 36 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Title/Title.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | import { schema } from "../../../prop-types" 8 | import { useFn } from "../../../hooks" 9 | 10 | const Title = ({ title = "", schema }) => { 11 | const fn = useFn() 12 | const renderedTitle = title || fn.getTitle(schema) 13 | 14 | if (!renderedTitle) return null 15 | 16 | return
{renderedTitle}
17 | } 18 | 19 | Title.propTypes = { 20 | title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), 21 | schema: schema.isRequired, 22 | } 23 | 24 | export default Title 25 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Title/_title.scss: -------------------------------------------------------------------------------- 1 | @use "./../../../../../../style/variables" as *; 2 | @use "./../../../../../../style/type"; 3 | 4 | .json-schema-2020-12 { 5 | &__title { 6 | @include type.text_headline($section-models-model-title-font-color); 7 | display: inline-block; 8 | font-weight: bold; 9 | font-size: 12px; 10 | line-height: normal; 11 | 12 | & .json-schema-2020-12-keyword__name { 13 | margin: 0; 14 | } 15 | } 16 | 17 | &-property { 18 | margin: 7px 0; 19 | 20 | .json-schema-2020-12__title { 21 | @include type.text_code(); 22 | font-size: 12px; 23 | vertical-align: middle; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/Type.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | import { schema } from "../../prop-types" 8 | import { useFn } from "../../hooks" 9 | 10 | const Type = ({ schema, isCircular = false }) => { 11 | const fn = useFn() 12 | const type = fn.getType(schema) 13 | const circularSuffix = isCircular ? " [circular]" : "" 14 | 15 | return ( 16 | 17 | {`${type}${circularSuffix}`} 18 | 19 | ) 20 | } 21 | 22 | Type.propTypes = { 23 | schema: schema.isRequired, 24 | isCircular: PropTypes.bool, 25 | } 26 | 27 | export default Type 28 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/UnevaluatedItems.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const UnevaluatedItems = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "unevaluatedItems")) return null 17 | 18 | const name = ( 19 | 20 | Unevaluated items 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 31 |
32 | ) 33 | } 34 | 35 | UnevaluatedItems.propTypes = { 36 | schema: schema.isRequired, 37 | } 38 | 39 | export default UnevaluatedItems 40 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/UnevaluatedProperties.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | import { useFn, useComponent } from "../../hooks" 8 | 9 | const UnevaluatedProperties = ({ schema }) => { 10 | const fn = useFn() 11 | const JSONSchema = useComponent("JSONSchema") 12 | 13 | /** 14 | * Rendering. 15 | */ 16 | if (!fn.hasKeyword(schema, "unevaluatedProperties")) return null 17 | 18 | const name = ( 19 | 20 | Unevaluated properties 21 | 22 | ) 23 | 24 | return ( 25 |
26 | 31 |
32 | ) 33 | } 34 | 35 | UnevaluatedProperties.propTypes = { 36 | schema: schema.isRequired, 37 | } 38 | 39 | export default UnevaluatedProperties 40 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/WriteOnly.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { schema } from "../../prop-types" 7 | 8 | const WriteOnly = ({ schema }) => { 9 | if (schema?.writeOnly !== true) return null 10 | 11 | return ( 12 | 13 | write-only 14 | 15 | ) 16 | } 17 | 18 | WriteOnly.propTypes = { 19 | schema: schema.isRequired, 20 | } 21 | 22 | export default WriteOnly 23 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/components/keywords/_all.scss: -------------------------------------------------------------------------------- 1 | @use "./../../../../../style/variables" as *; 2 | @use "./../mixins"; 3 | @use "./$vocabulary/$vocabulary" as vocabulary; 4 | @use "./Const/const"; 5 | @use "./Constraint/constraint"; 6 | @use "./Default/default"; 7 | @use "./DependentRequired/dependent-required"; 8 | @use "./Description/description"; 9 | @use "./Enum/enum"; 10 | @use "./Examples/examples"; 11 | @use "./ExtensionKeywords/extension-keywords"; 12 | @use "./PatternProperties/pattern-properties"; 13 | @use "./Properties/properties"; 14 | @use "./Title/title"; 15 | 16 | .json-schema-2020-12-keyword { 17 | @include mixins.json-schema-2020-12-keyword; 18 | } 19 | 20 | .json-schema-2020-12-keyword__name--secondary 21 | + .json-schema-2020-12-keyword__value--secondary::before { 22 | content: "="; 23 | } 24 | 25 | .json-schema-2020-12__attribute { 26 | font-family: monospace; 27 | color: $text-code-default-font-color; 28 | font-size: 12px; 29 | text-transform: lowercase; 30 | padding-left: 10px; 31 | 32 | &--primary { 33 | color: $prop-type-font-color; 34 | } 35 | 36 | &--muted { 37 | color: gray; 38 | } 39 | 40 | &--warning { 41 | color: red; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/context.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { createContext } from "react" 5 | 6 | export const JSONSchemaContext = createContext(null) 7 | JSONSchemaContext.displayName = "JSONSchemaContext" 8 | 9 | export const JSONSchemaLevelContext = createContext(0) 10 | JSONSchemaLevelContext.displayName = "JSONSchemaLevelContext" 11 | 12 | export const JSONSchemaCyclesContext = createContext(new Set()) 13 | 14 | export const JSONSchemaPathContext = createContext([]) 15 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/enum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | export class JSONSchemaIsExpandedState { 5 | static Collapsed = "collapsed" 6 | 7 | static Expanded = "expanded" 8 | 9 | static DeeplyExpanded = "deeply-expanded" 10 | } 11 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-2020-12/prop-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import PropTypes from "prop-types" 5 | 6 | export const objectSchema = PropTypes.object 7 | 8 | export const booleanSchema = PropTypes.bool 9 | 10 | export const schema = PropTypes.oneOfType([objectSchema, booleanSchema]) 11 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-5-samples/fn/get-json-sample-schema.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import some from "lodash/some" 5 | 6 | const shouldStringifyTypesConfig = [ 7 | { 8 | when: /json/, 9 | shouldStringifyTypes: ["string"], 10 | }, 11 | ] 12 | const defaultStringifyTypes = ["object"] 13 | const makeGetJsonSampleSchema = 14 | (getSystem) => (schema, config, contentType, exampleOverride) => { 15 | const { fn } = getSystem() 16 | const res = fn.memoizedSampleFromSchema(schema, config, exampleOverride) 17 | const resType = typeof res 18 | 19 | const typesToStringify = shouldStringifyTypesConfig.reduce( 20 | (types, nextConfig) => 21 | nextConfig.when.test(contentType) 22 | ? [...types, ...nextConfig.shouldStringifyTypes] 23 | : types, 24 | defaultStringifyTypes 25 | ) 26 | 27 | return some(typesToStringify, (x) => x === resType) 28 | ? JSON.stringify(res, null, 2) 29 | : res 30 | } 31 | 32 | export default makeGetJsonSampleSchema 33 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-5-samples/fn/get-sample-schema.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const makeGetSampleSchema = 5 | (getSystem) => 6 | (schema, contentType = "", config = {}, exampleOverride = undefined) => { 7 | const { fn } = getSystem() 8 | 9 | if (typeof schema?.toJS === "function") { 10 | schema = schema.toJS() 11 | } 12 | if (typeof exampleOverride?.toJS === "function") { 13 | exampleOverride = exampleOverride.toJS() 14 | } 15 | 16 | if (/xml/.test(contentType)) { 17 | return fn.getXmlSampleSchema(schema, config, exampleOverride) 18 | } 19 | if (/(yaml|yml)/.test(contentType)) { 20 | return fn.getYamlSampleSchema( 21 | schema, 22 | config, 23 | contentType, 24 | exampleOverride 25 | ) 26 | } 27 | return fn.getJsonSampleSchema(schema, config, contentType, exampleOverride) 28 | } 29 | 30 | export default makeGetSampleSchema 31 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-5-samples/fn/get-xml-sample-schema.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | const makeGetXmlSampleSchema = 5 | (getSystem) => (schema, config, exampleOverride) => { 6 | const { fn } = getSystem() 7 | 8 | if (schema && !schema.xml) { 9 | schema.xml = {} 10 | } 11 | if (schema && !schema.xml.name) { 12 | if ( 13 | !schema.$$ref && 14 | (schema.type || 15 | schema.items || 16 | schema.properties || 17 | schema.additionalProperties) 18 | ) { 19 | // eslint-disable-next-line quotes 20 | return '\n' 21 | } 22 | if (schema.$$ref) { 23 | let match = schema.$$ref.match(/\S*\/(\S+)$/) 24 | schema.xml.name = match[1] 25 | } 26 | } 27 | 28 | return fn.memoizedCreateXMLExample(schema, config, exampleOverride) 29 | } 30 | 31 | export default makeGetXmlSampleSchema 32 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-5-samples/fn/get-yaml-sample-schema.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import YAML, { JSON_SCHEMA } from "js-yaml" 5 | 6 | const makeGetYamlSampleSchema = 7 | (getSystem) => (schema, config, contentType, exampleOverride) => { 8 | const { fn } = getSystem() 9 | const jsonExample = fn.getJsonSampleSchema( 10 | schema, 11 | config, 12 | contentType, 13 | exampleOverride 14 | ) 15 | let yamlString 16 | try { 17 | yamlString = YAML.dump( 18 | YAML.load(jsonExample), 19 | { 20 | lineWidth: -1, // don't generate line folds 21 | }, 22 | { schema: JSON_SCHEMA } 23 | ) 24 | if (yamlString[yamlString.length - 1] === "\n") { 25 | yamlString = yamlString.slice(0, yamlString.length - 1) 26 | } 27 | } catch (e) { 28 | console.error(e) 29 | return "error: could not generate yaml example" 30 | } 31 | return yamlString.replace(/\t/g, " ") 32 | } 33 | 34 | export default makeGetYamlSampleSchema 35 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-5/components/enum-model.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import ImPropTypes from "react-immutable-proptypes" 3 | 4 | const EnumModel = ({ value, getComponent }) => { 5 | let ModelCollapse = getComponent("ModelCollapse") 6 | let collapsedContent = Array [ { value.count() } ] 7 | return 8 | Enum:
9 | 10 | [ { value.map(String).join(", ") } ] 11 | 12 |
13 | } 14 | EnumModel.propTypes = { 15 | value: ImPropTypes.iterable, 16 | getComponent: ImPropTypes.func 17 | } 18 | 19 | export default EnumModel 20 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-5/components/model-extensions.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | import { immutableToJS } from "core/utils" 7 | import ImPropTypes from "react-immutable-proptypes" 8 | 9 | export const ModelExtensions = ({ extensions, propClass = "" }) => { 10 | return extensions 11 | .entrySeq() 12 | .map(([key, value]) => { 13 | const normalizedValue = immutableToJS(value) ?? null 14 | 15 | return ( 16 | 17 | {key} 18 | {JSON.stringify(normalizedValue)} 19 | 20 | ) 21 | }) 22 | .toArray() 23 | } 24 | 25 | ModelExtensions.propTypes = { 26 | extensions: ImPropTypes.map.isRequired, 27 | propClass: PropTypes.string, 28 | } 29 | -------------------------------------------------------------------------------- /src/core/plugins/json-schema-5/containers/schemes.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default class SchemesContainer extends React.Component { 5 | 6 | static propTypes = { 7 | specActions: PropTypes.object.isRequired, 8 | specSelectors: PropTypes.object.isRequired, 9 | getComponent: PropTypes.func.isRequired 10 | } 11 | 12 | render () { 13 | const {specActions, specSelectors, getComponent} = this.props 14 | 15 | const currentScheme = specSelectors.operationScheme() 16 | const schemes = specSelectors.schemes() 17 | 18 | const Schemes = getComponent("schemes") 19 | 20 | const schemesArePresent = schemes && schemes.size 21 | 22 | return schemesArePresent ? ( 23 | 28 | ) : null 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/core/plugins/layout/actions.js: -------------------------------------------------------------------------------- 1 | import { normalizeArray } from "core/utils" 2 | 3 | export const UPDATE_LAYOUT = "layout_update_layout" 4 | export const UPDATE_FILTER = "layout_update_filter" 5 | export const UPDATE_MODE = "layout_update_mode" 6 | export const SHOW = "layout_show" 7 | 8 | // export const ONLY_SHOW = "layout_only_show" 9 | 10 | export function updateLayout(layout) { 11 | return { 12 | type: UPDATE_LAYOUT, 13 | payload: layout 14 | } 15 | } 16 | 17 | export function updateFilter(filter) { 18 | return { 19 | type: UPDATE_FILTER, 20 | payload: filter 21 | } 22 | } 23 | 24 | export function show(thing, shown=true) { 25 | thing = normalizeArray(thing) 26 | return { 27 | type: SHOW, 28 | payload: {thing, shown} 29 | } 30 | } 31 | 32 | // Simple string key-store, used for 33 | export function changeMode(thing, mode="") { 34 | thing = normalizeArray(thing) 35 | return { 36 | type: UPDATE_MODE, 37 | payload: {thing, mode} 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/core/plugins/layout/index.js: -------------------------------------------------------------------------------- 1 | import reducers from "./reducers" 2 | import * as actions from "./actions" 3 | import * as selectors from "./selectors" 4 | import * as wrapSelectors from "./spec-extensions/wrap-selector" 5 | 6 | export default function() { 7 | return { 8 | statePlugins: { 9 | layout: { 10 | reducers, 11 | actions, 12 | selectors 13 | }, 14 | spec: { 15 | wrapSelectors 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/core/plugins/layout/reducers.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from "immutable" 2 | import { 3 | UPDATE_LAYOUT, 4 | UPDATE_FILTER, 5 | UPDATE_MODE, 6 | SHOW 7 | } from "./actions" 8 | 9 | export default { 10 | 11 | [UPDATE_LAYOUT]: (state, action) => state.set("layout", action.payload), 12 | 13 | [UPDATE_FILTER]: (state, action) => state.set("filter", action.payload), 14 | 15 | [SHOW]: (state, action) => { 16 | const isShown = action.payload.shown 17 | // This is one way to serialize an array, another (preferred) is to convert to json-pointer 18 | // TODO: use json-pointer serilization instead of fromJS(...), for performance 19 | const thingToShow = fromJS(action.payload.thing) 20 | // This is a map of paths to bools 21 | // eg: [one, two] => true 22 | // eg: [one] => false 23 | return state.update("shown", fromJS({}), a => a.set(thingToShow, isShown)) 24 | }, 25 | 26 | [UPDATE_MODE]: (state, action) => { 27 | let thing = action.payload.thing 28 | let mode = action.payload.mode 29 | return state.setIn(["modes"].concat(thing), (mode || "") + "") 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/core/plugins/layout/selectors.js: -------------------------------------------------------------------------------- 1 | import { createSelector } from "reselect" 2 | import { normalizeArray } from "core/utils" 3 | import { fromJS } from "immutable" 4 | 5 | const state = state => state 6 | 7 | export const current = state => state.get("layout") 8 | 9 | export const currentFilter = state => state.get("filter") 10 | 11 | export const isShown = (state, thing, def) => { 12 | thing = normalizeArray(thing) 13 | return state.get("shown", fromJS({})).get(fromJS(thing), def) 14 | } 15 | 16 | export const whatMode = (state, thing, def="") => { 17 | thing = normalizeArray(thing) 18 | return state.getIn(["modes", ...thing], def) 19 | } 20 | 21 | export const showSummary = createSelector( 22 | state, 23 | state => !isShown(state, "editor") 24 | ) 25 | -------------------------------------------------------------------------------- /src/core/plugins/layout/spec-extensions/wrap-selector.js: -------------------------------------------------------------------------------- 1 | 2 | export const taggedOperations = (oriSelector, system) => (state, ...args) => { 3 | let taggedOps = oriSelector(state, ...args) 4 | 5 | const { fn, layoutSelectors, getConfigs } = system.getSystem() 6 | const configs = getConfigs() 7 | const { maxDisplayedTags } = configs 8 | 9 | // Filter, if requested 10 | let filter = layoutSelectors.currentFilter() 11 | if (filter) { 12 | if (filter !== true) { 13 | taggedOps = fn.opsFilter(taggedOps, filter) 14 | } 15 | } 16 | // Limit to [max] items, if specified 17 | if (maxDisplayedTags >= 0) { 18 | taggedOps = taggedOps.slice(0, maxDisplayedTags) 19 | } 20 | 21 | return taggedOps 22 | } 23 | -------------------------------------------------------------------------------- /src/core/plugins/logs/index.js: -------------------------------------------------------------------------------- 1 | export default function ({configs}) { 2 | 3 | const levels = { 4 | "debug": 0, 5 | "info": 1, 6 | "log": 2, 7 | "warn": 3, 8 | "error": 4 9 | } 10 | 11 | const getLevel = (level) => levels[level] || -1 12 | 13 | let { logLevel } = configs 14 | let logLevelInt = getLevel(logLevel) 15 | 16 | function log(level, ...args) { 17 | if(getLevel(level) >= logLevelInt) 18 | // eslint-disable-next-line no-console 19 | console[level](...args) 20 | } 21 | 22 | log.warn = log.bind(null, "warn") 23 | log.error = log.bind(null, "error") 24 | log.info = log.bind(null, "info") 25 | log.debug = log.bind(null, "debug") 26 | 27 | return { rootInjects: { log } } 28 | } 29 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/components/index.js: -------------------------------------------------------------------------------- 1 | import Callbacks from "./callbacks" 2 | import RequestBody from "./request-body" 3 | import OperationLink from "./operation-link" 4 | import Servers from "./servers" 5 | import ServersContainer from "./servers-container" 6 | import RequestBodyEditor from "./request-body-editor" 7 | import HttpAuth from "./auth/http-auth" 8 | import OperationServers from "./operation-servers" 9 | 10 | export default { 11 | Callbacks, 12 | HttpAuth, 13 | RequestBody, 14 | Servers, 15 | ServersContainer, 16 | RequestBodyEditor, 17 | OperationServers, 18 | operationLink: OperationLink, 19 | } 20 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/components/servers-container.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | export default class ServersContainer extends React.Component { 5 | 6 | static propTypes = { 7 | specSelectors: PropTypes.object.isRequired, 8 | oas3Selectors: PropTypes.object.isRequired, 9 | oas3Actions: PropTypes.object.isRequired, 10 | getComponent: PropTypes.func.isRequired, 11 | } 12 | 13 | render () { 14 | const {specSelectors, oas3Selectors, oas3Actions, getComponent} = this.props 15 | 16 | const servers = specSelectors.servers() 17 | 18 | const Servers = getComponent("Servers") 19 | 20 | return servers && servers.size ? ( 21 |
22 | Servers 23 | 31 |
) : null 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/fn.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { Map } from "immutable" 5 | import isPlainObject from "lodash/isPlainObject" 6 | 7 | export const makeIsFileUploadIntended = (getSystem) => { 8 | const isFileUploadIntended = (schema, mediaType = null) => { 9 | const { getConfigs, fn } = getSystem() 10 | const { fileUploadMediaTypes } = getConfigs() 11 | const isFileUploadMediaType = 12 | typeof mediaType === "string" && 13 | fileUploadMediaTypes.some((fileUploadMediaType) => 14 | mediaType.startsWith(fileUploadMediaType) 15 | ) 16 | 17 | if (isFileUploadMediaType) { 18 | return true 19 | } 20 | 21 | const isSchemaImmutable = Map.isMap(schema) 22 | 23 | if (!isSchemaImmutable && !isPlainObject(schema)) { 24 | return false 25 | } 26 | 27 | const format = isSchemaImmutable ? schema.get("format") : schema.format 28 | 29 | return ( 30 | fn.hasSchemaType(schema, "string") && ["binary", "byte"].includes(format) 31 | ) 32 | } 33 | 34 | return isFileUploadIntended 35 | } 36 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import * as specWrapSelectors from "./spec-extensions/wrap-selectors" 5 | import * as authWrapSelectors from "./auth-extensions/wrap-selectors" 6 | import * as specSelectors from "./spec-extensions/selectors" 7 | import components from "./components" 8 | import wrapComponents from "./wrap-components" 9 | import * as actions from "./actions" 10 | import * as selectors from "./selectors" 11 | import reducers from "./reducers" 12 | import { makeIsFileUploadIntended } from "./fn" 13 | 14 | export default function ({ getSystem }) { 15 | const isFileUploadIntended = makeIsFileUploadIntended(getSystem) 16 | 17 | return { 18 | components, 19 | wrapComponents, 20 | statePlugins: { 21 | spec: { 22 | wrapSelectors: specWrapSelectors, 23 | selectors: specSelectors, 24 | }, 25 | auth: { 26 | wrapSelectors: authWrapSelectors, 27 | }, 28 | oas3: { 29 | actions: { ...actions }, 30 | reducers, 31 | selectors: { ...selectors }, 32 | }, 33 | }, 34 | fn: { 35 | isFileUploadIntended, 36 | isFileUploadIntendedOAS30: isFileUploadIntended, 37 | }, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/wrap-components/auth/auth-item.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { OAS3ComponentWrapFactory } from "../../helpers" 3 | 4 | export default OAS3ComponentWrapFactory(({ Ori, ...props }) => { 5 | const { 6 | schema, getComponent, errSelectors, authorized, onAuthChange, name, authSelectors 7 | } = props 8 | 9 | const HttpAuth = getComponent("HttpAuth") 10 | const type = schema.get("type") 11 | 12 | 13 | if(type === "http") { 14 | return 22 | } else { 23 | return 24 | } 25 | }) 26 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/wrap-components/index.js: -------------------------------------------------------------------------------- 1 | import Markdown from "./markdown" 2 | import AuthItem from "./auth/auth-item" 3 | import OnlineValidatorBadge from "./online-validator-badge" 4 | import Model from "./model" 5 | import JsonSchema_string from "./json-schema-string" 6 | import OpenAPIVersion from "./openapi-version" 7 | 8 | export default { 9 | Markdown, 10 | AuthItem, 11 | OpenAPIVersion, 12 | JsonSchema_string, 13 | model: Model, 14 | onlineValidatorBadge: OnlineValidatorBadge, 15 | } 16 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/wrap-components/json-schema-string.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { OAS3ComponentWrapFactory } from "../helpers" 3 | 4 | export default OAS3ComponentWrapFactory(({ Ori, ...props }) => { 5 | const { 6 | schema, 7 | getComponent, 8 | errors, 9 | onChange, 10 | fn 11 | } = props 12 | 13 | const isFileUploadIntended = fn.isFileUploadIntended(schema) 14 | const Input = getComponent("Input") 15 | 16 | if (isFileUploadIntended) { 17 | return { 21 | onChange(e.target.files[0]) 22 | }} 23 | disabled={Ori.isDisabled}/> 24 | } else { 25 | return 26 | } 27 | }) 28 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/wrap-components/online-validator-badge.js: -------------------------------------------------------------------------------- 1 | import { OAS3ComponentWrapFactory } from "../helpers" 2 | import OnlineValidatorBadge from "core/components/online-validator-badge" 3 | 4 | // OAS3 spec is now supported by the online validator. 5 | export default OAS3ComponentWrapFactory(OnlineValidatorBadge) 6 | -------------------------------------------------------------------------------- /src/core/plugins/oas3/wrap-components/openapi-version.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { OAS30ComponentWrapFactory } from "../helpers" 3 | 4 | export default OAS30ComponentWrapFactory((props) => { 5 | const { Ori } = props 6 | return 7 | }) 8 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/auth-extensions/wrap-selectors.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { Map } from "immutable" 5 | import { createOnlyOAS31SelectorWrapper } from "../fn" 6 | 7 | export const definitionsToAuthorize = createOnlyOAS31SelectorWrapper( 8 | () => (oriSelector, system) => { 9 | const definitions = system.specSelectors.securityDefinitions() 10 | let list = oriSelector() 11 | 12 | if (!definitions) return list 13 | 14 | definitions.entrySeq().forEach(([defName, definition]) => { 15 | const type = definition?.get("type") 16 | 17 | if (type === "mutualTLS") { 18 | list = list.push( 19 | new Map({ 20 | [defName]: definition, 21 | }) 22 | ) 23 | } 24 | }) 25 | 26 | return list 27 | } 28 | ) 29 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/components/_all.scss: -------------------------------------------------------------------------------- 1 | @use "./model/model"; 2 | @use "./models/models"; 3 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/components/auth/mutual-tls-auth.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const MutualTLSAuth = ({ schema, getComponent, name, authSelectors }) => { 8 | const JumpToPath = getComponent("JumpToPath", true) 9 | const path = authSelectors.selectAuthPath(name) 10 | 11 | return ( 12 |
13 |

14 | {name} (mutualTLS) 15 |

16 |

17 | Mutual TLS is required by this API/Operation. Certificates are managed 18 | via your Operating System and/or your browser. 19 |

20 |

{schema.get("description")}

21 |
22 | ) 23 | } 24 | 25 | MutualTLSAuth.propTypes = { 26 | schema: PropTypes.object.isRequired, 27 | getComponent: PropTypes.func.isRequired, 28 | name: PropTypes.string.isRequired, 29 | authSelectors: PropTypes.object.isRequired, 30 | } 31 | 32 | export default MutualTLSAuth 33 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/components/contact.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | import { sanitizeUrl } from "core/utils/url" 8 | 9 | const Contact = ({ getComponent, specSelectors }) => { 10 | const name = specSelectors.selectContactNameField() 11 | const url = specSelectors.selectContactUrl() 12 | const email = specSelectors.selectContactEmailField() 13 | 14 | const Link = getComponent("Link") 15 | 16 | return ( 17 |
18 | {url && ( 19 |
20 | 21 | {name} - Website 22 | 23 |
24 | )} 25 | {email && ( 26 | 27 | {url ? `Send email to ${name}` : `Contact ${name}`} 28 | 29 | )} 30 |
31 | ) 32 | } 33 | 34 | Contact.propTypes = { 35 | getComponent: PropTypes.func.isRequired, 36 | specSelectors: PropTypes.shape({ 37 | selectContactNameField: PropTypes.func.isRequired, 38 | selectContactUrl: PropTypes.func.isRequired, 39 | selectContactEmailField: PropTypes.func.isRequired, 40 | }).isRequired, 41 | } 42 | 43 | export default Contact 44 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/components/license.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | import { sanitizeUrl } from "core/utils/url" 8 | 9 | const License = ({ getComponent, specSelectors }) => { 10 | const name = specSelectors.selectLicenseNameField() 11 | const url = specSelectors.selectLicenseUrl() 12 | 13 | const Link = getComponent("Link") 14 | 15 | return ( 16 |
17 | {url ? ( 18 |
19 | 20 | {name} 21 | 22 |
23 | ) : ( 24 | {name} 25 | )} 26 |
27 | ) 28 | } 29 | 30 | License.propTypes = { 31 | getComponent: PropTypes.func.isRequired, 32 | specSelectors: PropTypes.shape({ 33 | selectLicenseNameField: PropTypes.func.isRequired, 34 | selectLicenseUrl: PropTypes.func.isRequired, 35 | }).isRequired, 36 | } 37 | 38 | export default License 39 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/components/model/_model.scss: -------------------------------------------------------------------------------- 1 | .model-box { 2 | // inferred names of Schema Objects 3 | & 4 | .json-schema-2020-12:not(.json-schema-2020-12--embedded) 5 | > .json-schema-2020-12-head 6 | .json-schema-2020-12__title:first-of-type { 7 | font-size: 16px; 8 | } 9 | 10 | & > .json-schema-2020-12 { 11 | margin: 0; 12 | } 13 | 14 | .json-schema-2020-12 { 15 | padding: 0; 16 | background-color: transparent; 17 | } 18 | 19 | .json-schema-2020-12-accordion, 20 | .json-schema-2020-12-expand-deep-button { 21 | background-color: transparent; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/components/models/_models.scss: -------------------------------------------------------------------------------- 1 | .models 2 | .json-schema-2020-12:not(.json-schema-2020-12--embedded) 3 | > .json-schema-2020-12-head 4 | .json-schema-2020-12__title:first-of-type { 5 | font-size: 16px; 6 | } 7 | 8 | .models .json-schema-2020-12:not(.json-schema-2020-12--embedded) { 9 | width: calc(100% - 40px); 10 | overflow-x: auto; 11 | } 12 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Description.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const Description = ({ schema, getSystem }) => { 8 | if (!schema?.description) return null 9 | 10 | const { getComponent } = getSystem() 11 | const MarkDown = getComponent("Markdown") 12 | 13 | return ( 14 |
15 |
16 | 17 |
18 |
19 | ) 20 | } 21 | 22 | Description.propTypes = { 23 | schema: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]).isRequired, 24 | getSystem: PropTypes.func.isRequired, 25 | } 26 | 27 | export default Description 28 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Discriminator/DiscriminatorMapping.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const DiscriminatorMapping = ({ discriminator }) => { 8 | const mapping = discriminator?.mapping || {} 9 | 10 | if (Object.keys(mapping).length === 0) { 11 | return null 12 | } 13 | 14 | return Object.entries(mapping).map(([key, value]) => ( 15 |
16 | 17 | {key} 18 | 19 | 20 | {value} 21 | 22 |
23 | )) 24 | } 25 | 26 | DiscriminatorMapping.propTypes = { 27 | discriminator: PropTypes.shape({ 28 | mapping: PropTypes.any, 29 | }), 30 | } 31 | 32 | export default DiscriminatorMapping 33 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/Example.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const Example = ({ schema, getSystem }) => { 8 | const { fn, getComponent } = getSystem() 9 | const { hasKeyword } = fn.jsonSchema202012.useFn() 10 | const JSONViewer = getComponent("JSONSchema202012JSONViewer") 11 | 12 | if (!hasKeyword(schema, "example")) return null 13 | 14 | return ( 15 | 20 | ) 21 | } 22 | 23 | Example.propTypes = { 24 | schema: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]).isRequired, 25 | getSystem: PropTypes.func.isRequired, 26 | } 27 | 28 | export default Example 29 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/json-schema-2020-12-extensions/components/keywords/OpenAPIExtensions.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const OpenAPIExtensions = ({ 8 | openAPISpecObj, 9 | getSystem, 10 | openAPIExtensions, 11 | }) => { 12 | const { fn } = getSystem() 13 | const { useComponent } = fn.jsonSchema202012 14 | 15 | const JSONViewer = useComponent("JSONViewer") 16 | return openAPIExtensions.map((keyword) => ( 17 | 23 | )) 24 | } 25 | 26 | OpenAPIExtensions.propTypes = { 27 | openAPISpecObj: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]) 28 | .isRequired, 29 | getSystem: PropTypes.func.isRequired, 30 | openAPIExtensions: PropTypes.arrayOf(PropTypes.string).isRequired, 31 | } 32 | 33 | export default OpenAPIExtensions 34 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/json-schema-2020-12-extensions/wrap-components/keywords/Description.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import DescriptionKeyword from "../../components/keywords/Description" 5 | import { createOnlyOAS31ComponentWrapper } from "../../../fn" 6 | 7 | const DescriptionWrapper = createOnlyOAS31ComponentWrapper(DescriptionKeyword) 8 | 9 | export default DescriptionWrapper 10 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/json-schema-2020-12-extensions/wrap-components/keywords/Examples.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import { createOnlyOAS31ComponentWrapper } from "../../../fn" 6 | 7 | const ExamplesWrapper = createOnlyOAS31ComponentWrapper( 8 | ({ schema, getSystem, originalComponent: KeywordExamples }) => { 9 | const { getComponent } = getSystem() 10 | const KeywordDiscriminator = getComponent( 11 | "JSONSchema202012KeywordDiscriminator" 12 | ) 13 | const KeywordXml = getComponent("JSONSchema202012KeywordXml") 14 | const KeywordExample = getComponent("JSONSchema202012KeywordExample") 15 | const KeywordExternalDocs = getComponent( 16 | "JSONSchema202012KeywordExternalDocs" 17 | ) 18 | 19 | return ( 20 | <> 21 | 22 | 23 | 24 | 25 | 26 | 27 | ) 28 | } 29 | ) 30 | 31 | export default ExamplesWrapper 32 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/json-schema-2020-12-extensions/wrap-components/keywords/Properties.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import PropertiesKeyword from "../../components/keywords/Properties" 5 | import { createOnlyOAS31ComponentWrapper } from "../../../fn" 6 | 7 | const PropertiesWrapper = createOnlyOAS31ComponentWrapper(PropertiesKeyword) 8 | 9 | export default PropertiesWrapper 10 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/selectors.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { createSelector } from "reselect" 5 | 6 | import { safeBuildUrl } from "core/utils/url" 7 | 8 | export const selectLicenseUrl = createSelector( 9 | [ 10 | (state, system) => system.specSelectors.url(), 11 | (state, system) => system.oas3Selectors.selectedServer(), 12 | (state, system) => system.specSelectors.selectLicenseUrlField(), 13 | (state, system) => system.specSelectors.selectLicenseIdentifierField(), 14 | ], 15 | (specUrl, selectedServer, url, identifier) => { 16 | if (url) { 17 | return safeBuildUrl(url, specUrl, { selectedServer }) 18 | } 19 | 20 | if (identifier) { 21 | return `https://spdx.org/licenses/${identifier}.html` 22 | } 23 | 24 | return undefined 25 | } 26 | ) 27 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/spec-extensions/wrap-selectors.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | import { createOnlyOAS31SelectorWrapper } from "../fn" 6 | 7 | export const isOAS3 = 8 | (oriSelector, system) => 9 | (state, ...args) => { 10 | const isOAS31 = system.specSelectors.isOAS31() 11 | return isOAS31 || oriSelector(...args) 12 | } 13 | 14 | export const selectLicenseUrl = createOnlyOAS31SelectorWrapper( 15 | () => (oriSelector, system) => { 16 | return system.oas31Selectors.selectLicenseUrl() 17 | } 18 | ) 19 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/wrap-components/auth/auth-item.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { createOnlyOAS31ComponentWrapper } from "../../fn" 7 | 8 | const AuthItem = createOnlyOAS31ComponentWrapper( 9 | ({ originalComponent: Ori, ...props }) => { 10 | const { getComponent, schema, name } = props 11 | const MutualTLSAuth = getComponent("MutualTLSAuth", true) 12 | const type = schema.get("type") 13 | 14 | if (type === "mutualTLS") { 15 | return 16 | } 17 | 18 | return 19 | } 20 | ) 21 | 22 | export default AuthItem 23 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/wrap-components/auths.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { createOnlyOAS31ComponentWrapper } from "../fn" 7 | 8 | const AuthsWrapper = createOnlyOAS31ComponentWrapper( 9 | ({ getSystem, ...props }) => { 10 | const system = getSystem() 11 | const OAS31Auths = system.getComponent("OAS31Auths", true) 12 | 13 | return 14 | } 15 | ) 16 | 17 | export default AuthsWrapper 18 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/wrap-components/contact.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { createOnlyOAS31ComponentWrapper } from "../fn" 7 | 8 | const ContactWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => { 9 | const system = getSystem() 10 | const OAS31Contact = system.getComponent("OAS31Contact", true) 11 | 12 | return 13 | }) 14 | 15 | export default ContactWrapper 16 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/wrap-components/info.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { createOnlyOAS31ComponentWrapper } from "../fn" 7 | 8 | const InfoWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => { 9 | const system = getSystem() 10 | const OAS31Info = system.getComponent("OAS31Info", true) 11 | 12 | return 13 | }) 14 | 15 | export default InfoWrapper 16 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/wrap-components/license.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | import { createOnlyOAS31ComponentWrapper } from "../fn" 7 | 8 | const LicenseWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => { 9 | const system = getSystem() 10 | const OAS31License = system.getComponent("OAS31License", true) 11 | 12 | return 13 | }) 14 | 15 | export default LicenseWrapper 16 | -------------------------------------------------------------------------------- /src/core/plugins/oas31/wrap-components/version-pragma-filter.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | 6 | const VersionPragmaFilterWrapper = (Original, system) => (props) => { 7 | const isOAS31 = system.specSelectors.isOAS31() 8 | 9 | const OAS31VersionPragmaFilter = system.getComponent( 10 | "OAS31VersionPragmaFilter" 11 | ) 12 | 13 | return 14 | } 15 | 16 | export default VersionPragmaFilterWrapper 17 | -------------------------------------------------------------------------------- /src/core/plugins/on-complete/index.js: -------------------------------------------------------------------------------- 1 | let engaged = false 2 | 3 | export default function() { 4 | 5 | return { 6 | statePlugins: { 7 | spec: { 8 | wrapActions: { 9 | updateSpec: (ori) => (...args) => { 10 | engaged = true 11 | return ori(...args) 12 | }, 13 | updateJsonSpec: (ori, system) => (...args) => { 14 | const cb = system.getConfigs().onComplete 15 | if(engaged && typeof cb === "function") { 16 | // call `onComplete` on next tick, which allows React to 17 | // reconcile the DOM before we notify the user 18 | setTimeout(cb, 0) 19 | engaged = false 20 | } 21 | 22 | return ori(...args) 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/core/plugins/request-snippets/index.js: -------------------------------------------------------------------------------- 1 | import { requestSnippetGenerator_curl_bash, requestSnippetGenerator_curl_cmd, requestSnippetGenerator_curl_powershell } from "./fn" 2 | import * as selectors from "./selectors" 3 | import RequestSnippets from "./request-snippets" 4 | 5 | export default () => { 6 | return { 7 | components: { 8 | RequestSnippets 9 | }, 10 | fn: { 11 | requestSnippetGenerator_curl_bash, 12 | requestSnippetGenerator_curl_cmd, 13 | requestSnippetGenerator_curl_powershell, 14 | }, 15 | statePlugins: { 16 | requestSnippets: { 17 | selectors 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/core/plugins/request-snippets/selectors.js: -------------------------------------------------------------------------------- 1 | import { createSelector } from "reselect" 2 | import { Map } from "immutable" 3 | 4 | const state = state => state || Map() 5 | 6 | export const getGenerators = createSelector( 7 | state, 8 | state => { 9 | const languageKeys = state 10 | .get("languages") 11 | const generators = state 12 | .get("generators", Map()) 13 | if(!languageKeys || languageKeys.isEmpty()) { 14 | return generators 15 | } 16 | return generators 17 | .filter((v, key) => languageKeys.includes(key)) 18 | } 19 | ) 20 | 21 | export const getSnippetGenerators = (state) => ({ fn }) => { 22 | const getGenFn = (key) => fn[`requestSnippetGenerator_${key}`] 23 | return getGenerators(state) 24 | .map((gen, key) => { 25 | const genFn = getGenFn(key) 26 | if(typeof genFn !== "function") { 27 | return null 28 | } 29 | 30 | return gen.set("fn", genFn) 31 | }) 32 | .filter(v => v) 33 | } 34 | 35 | export const getActiveLanguage = createSelector( 36 | state, 37 | state => state 38 | .get("activeLanguage") 39 | ) 40 | 41 | export const getDefaultExpanded = createSelector( 42 | state, 43 | state => state 44 | .get("defaultExpanded") 45 | ) 46 | -------------------------------------------------------------------------------- /src/core/plugins/safe-render/components/fallback.jsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | 4 | const Fallback = ({ name }) => ( 5 |
6 | 😱 Could not render { name === "t" ? "this component" : name }, see the console. 7 |
8 | ) 9 | Fallback.propTypes = { 10 | name: PropTypes.string.isRequired, 11 | } 12 | 13 | export default Fallback 14 | -------------------------------------------------------------------------------- /src/core/plugins/safe-render/fn.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react" 2 | 3 | export const componentDidCatch = console.error 4 | 5 | const isClassComponent = component => component.prototype && component.prototype.isReactComponent 6 | 7 | export const withErrorBoundary = (getSystem) => (WrappedComponent) => { 8 | const { getComponent, fn } = getSystem() 9 | const ErrorBoundary = getComponent("ErrorBoundary") 10 | const targetName = fn.getDisplayName(WrappedComponent) 11 | 12 | class WithErrorBoundary extends Component { 13 | render() { 14 | return ( 15 | 16 | 17 | 18 | ) 19 | } 20 | } 21 | WithErrorBoundary.displayName = `WithErrorBoundary(${targetName})` 22 | if (isClassComponent(WrappedComponent)) { 23 | /** 24 | * We need to handle case of class components defining a `mapStateToProps` public method. 25 | * Components with `mapStateToProps` public method cannot be wrapped. 26 | */ 27 | WithErrorBoundary.prototype.mapStateToProps = WrappedComponent.prototype.mapStateToProps 28 | } 29 | 30 | return WithErrorBoundary 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/core/plugins/spec/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import reducers from "./reducers" 5 | import * as actions from "./actions" 6 | import * as selectors from "./selectors" 7 | import * as wrapActions from "./wrap-actions" 8 | 9 | const SpecPlugin = () => ({ 10 | statePlugins: { 11 | spec: { 12 | wrapActions: { ...wrapActions }, 13 | reducers: { ...reducers }, 14 | actions: { ...actions }, 15 | selectors: { ...selectors }, 16 | }, 17 | }, 18 | }) 19 | 20 | export default SpecPlugin 21 | -------------------------------------------------------------------------------- /src/core/plugins/spec/wrap-actions.js: -------------------------------------------------------------------------------- 1 | import get from "lodash/get" 2 | import isPlainObject from "lodash/isPlainObject" 3 | 4 | export const updateSpec = (ori, {specActions}) => (...args) => { 5 | ori(...args) 6 | specActions.parseToJson(...args) 7 | } 8 | 9 | export const updateJsonSpec = (ori, {specActions}) => (...args) => { 10 | ori(...args) 11 | 12 | specActions.invalidateResolvedSubtreeCache() 13 | 14 | // Trigger resolution of any path-level $refs. 15 | const [json] = args 16 | const pathItems = get(json, ["paths"]) || {} 17 | const pathItemKeys = Object.keys(pathItems) 18 | 19 | pathItemKeys.forEach(k => { 20 | const val = get(pathItems, [k]) 21 | 22 | if (isPlainObject(val) && val.$ref) { 23 | specActions.requestResolvedSubtree(["paths", k]) 24 | } 25 | }) 26 | 27 | // Trigger resolution of any securitySchemes-level $refs. 28 | specActions.requestResolvedSubtree(["components", "securitySchemes"]) 29 | } 30 | 31 | // Log the request ( just for debugging, shouldn't affect prod ) 32 | export const executeRequest = (ori, { specActions }) => (req) => { 33 | specActions.logRequest(req) 34 | return ori(req) 35 | } 36 | 37 | export const validateParams = (ori, { specSelectors }) => (req) => { 38 | return ori(req, specSelectors.isOAS3()) 39 | } 40 | -------------------------------------------------------------------------------- /src/core/plugins/swagger-client/configs-wrap-actions.js: -------------------------------------------------------------------------------- 1 | export const loaded = (ori, system) => (...args) => { 2 | ori(...args) 3 | const value = system.getConfigs().withCredentials 4 | 5 | system.fn.fetch.withCredentials = value 6 | } 7 | -------------------------------------------------------------------------------- /src/core/plugins/syntax-highlighting/components/PlainTextViewer.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | import classNames from "classnames" 7 | 8 | const PlainTextViewer = ({ className = "", children }) => ( 9 |
{children}
10 | ) 11 | 12 | PlainTextViewer.propTypes = { 13 | className: PropTypes.string, 14 | children: PropTypes.string.isRequired, 15 | } 16 | 17 | export default PlainTextViewer 18 | -------------------------------------------------------------------------------- /src/core/plugins/syntax-highlighting/components/SyntaxHighlighter.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | import ReactSyntaxHighlighter from "react-syntax-highlighter/dist/esm/light" 7 | 8 | const SyntaxHighlighter = ({ 9 | language, 10 | className = "", 11 | getConfigs, 12 | syntaxHighlighting = {}, 13 | children = "", 14 | }) => { 15 | const theme = getConfigs().syntaxHighlight.theme 16 | const { styles, defaultStyle } = syntaxHighlighting 17 | const style = styles?.[theme] ?? defaultStyle 18 | 19 | return ( 20 | 25 | {children} 26 | 27 | ) 28 | } 29 | 30 | SyntaxHighlighter.propTypes = { 31 | language: PropTypes.string.isRequired, 32 | className: PropTypes.string, 33 | getConfigs: PropTypes.func.isRequired, 34 | syntaxHighlighting: PropTypes.shape({ 35 | styles: PropTypes.object, 36 | defaultStyle: PropTypes.object, 37 | }), 38 | renderPlainText: PropTypes.func, 39 | children: PropTypes.string, 40 | } 41 | 42 | export default SyntaxHighlighter 43 | -------------------------------------------------------------------------------- /src/core/plugins/syntax-highlighting/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import afterLoad from "./after-load" 5 | import { styles, defaultStyle } from "./root-injects" 6 | import SyntaxHighlighter from "./components/SyntaxHighlighter" 7 | import HighlightCode from "./components/HighlightCode" 8 | import PlainTextViewer from "./components/PlainTextViewer" 9 | import SyntaxHighlighterWrapper from "./wrap-components/SyntaxHighlighter" 10 | 11 | const SyntaxHighlightingPlugin1 = () => ({ 12 | afterLoad, 13 | rootInjects: { 14 | syntaxHighlighting: { styles, defaultStyle }, 15 | }, 16 | components: { 17 | SyntaxHighlighter, 18 | HighlightCode, 19 | PlainTextViewer, 20 | }, 21 | }) 22 | 23 | const SyntaxHighlightingPlugin2 = () => ({ 24 | wrapComponents: { 25 | SyntaxHighlighter: SyntaxHighlighterWrapper, 26 | }, 27 | }) 28 | 29 | const SyntaxHighlightingPlugin = () => [ 30 | SyntaxHighlightingPlugin1, 31 | SyntaxHighlightingPlugin2, 32 | ] 33 | 34 | export default SyntaxHighlightingPlugin 35 | -------------------------------------------------------------------------------- /src/core/plugins/syntax-highlighting/root-injects.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import agate from "react-syntax-highlighter/dist/esm/styles/hljs/agate" 5 | import arta from "react-syntax-highlighter/dist/esm/styles/hljs/arta" 6 | import monokai from "react-syntax-highlighter/dist/esm/styles/hljs/monokai" 7 | import nord from "react-syntax-highlighter/dist/esm/styles/hljs/nord" 8 | import obsidian from "react-syntax-highlighter/dist/esm/styles/hljs/obsidian" 9 | import tomorrowNight from "react-syntax-highlighter/dist/esm/styles/hljs/tomorrow-night" 10 | import idea from "react-syntax-highlighter/dist/esm/styles/hljs/idea" 11 | 12 | export const styles = { 13 | agate, 14 | arta, 15 | monokai, 16 | nord, 17 | obsidian, 18 | "tomorrow-night": tomorrowNight, 19 | idea, 20 | } 21 | 22 | export const defaultStyle = agate 23 | -------------------------------------------------------------------------------- /src/core/plugins/syntax-highlighting/wrap-components/SyntaxHighlighter.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import PropTypes from "prop-types" 6 | 7 | const SyntaxHighlighterWrapper = (Original, system) => { 8 | const SyntaxHighlighter = ({ renderPlainText, children, ...rest }) => { 9 | const canSyntaxHighlight = system.getConfigs().syntaxHighlight.activated 10 | const PlainTextViewer = system.getComponent("PlainTextViewer") 11 | 12 | if (!canSyntaxHighlight && typeof renderPlainText === "function") { 13 | return renderPlainText({ children, PlainTextViewer }) 14 | } 15 | if (!canSyntaxHighlight) { 16 | return {children} 17 | } 18 | 19 | return {children} 20 | } 21 | 22 | SyntaxHighlighter.propTypes = { 23 | ...Original.propTypes, 24 | renderPlainText: PropTypes.func, 25 | children: PropTypes.string.isRequired, 26 | } 27 | 28 | return SyntaxHighlighter 29 | } 30 | 31 | export default SyntaxHighlighterWrapper 32 | -------------------------------------------------------------------------------- /src/core/plugins/util/index.js: -------------------------------------------------------------------------------- 1 | import { shallowEqualKeys } from "core/utils" 2 | import { sanitizeUrl } from "core/utils/url" 3 | 4 | export default function() { 5 | return { 6 | fn: { 7 | shallowEqualKeys, 8 | sanitizeUrl, 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/core/plugins/versions/after-load.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import win from "core/window" 5 | 6 | const afterLoad = () => { 7 | // eslint-disable-next-line no-undef 8 | const { GIT_DIRTY, GIT_COMMIT, PACKAGE_VERSION, BUILD_TIME } = buildInfo 9 | 10 | win.versions = win.versions || {} 11 | win.versions.swaggerUI = { 12 | version: PACKAGE_VERSION, 13 | gitRevision: GIT_COMMIT, 14 | gitDirty: GIT_DIRTY, 15 | buildTimestamp: BUILD_TIME, 16 | } 17 | } 18 | 19 | export default afterLoad 20 | -------------------------------------------------------------------------------- /src/core/plugins/versions/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import afterLoad from "./after-load.js" 5 | 6 | const VersionsPlugin = () => ({ 7 | afterLoad, 8 | }) 9 | 10 | export default VersionsPlugin 11 | -------------------------------------------------------------------------------- /src/core/plugins/view-legacy/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import { getComponent } from "core/plugins/view/root-injects" 5 | import { render } from "./root-injects" 6 | 7 | const ViewLegacyPlugin = ({ React, getSystem, getStore, getComponents }) => { 8 | const rootInjects = {} 9 | const reactMajorVersion = parseInt(React?.version, 10) 10 | 11 | if (reactMajorVersion >= 16 && reactMajorVersion < 18) { 12 | rootInjects.render = render( 13 | getSystem, 14 | getStore, 15 | getComponent, 16 | getComponents 17 | ) 18 | } 19 | 20 | return { 21 | rootInjects, 22 | } 23 | } 24 | 25 | export default ViewLegacyPlugin 26 | -------------------------------------------------------------------------------- /src/core/plugins/view-legacy/root-injects.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import ReactDOM from "react-dom" 6 | 7 | export const render = 8 | (getSystem, getStore, getComponent, getComponents) => (domNode) => { 9 | const App = getComponent(getSystem, getStore, getComponents)("App", "root") 10 | 11 | ReactDOM.render(, domNode) 12 | } 13 | -------------------------------------------------------------------------------- /src/core/plugins/view/fn.js: -------------------------------------------------------------------------------- 1 | export const getDisplayName = (WrappedComponent) => WrappedComponent.displayName || WrappedComponent.name || "Component" 2 | -------------------------------------------------------------------------------- /src/core/plugins/view/index.js: -------------------------------------------------------------------------------- 1 | import { memoize } from "core/utils" 2 | 3 | import memoizeN from "core/utils/memoizeN" 4 | import { getComponent, render, withMappedContainer } from "./root-injects" 5 | import { getDisplayName } from "./fn" 6 | 7 | const memoizeForGetComponent = (fn) => { 8 | const resolver = (...args) => JSON.stringify(args) 9 | return memoize(fn, resolver) 10 | } 11 | 12 | const memoizeForWithMappedContainer = (fn) => { 13 | const resolver = (...args) => args 14 | return memoizeN(fn, resolver) 15 | } 16 | 17 | const viewPlugin = ({getComponents, getStore, getSystem}) => { 18 | // getComponent should be passed into makeMappedContainer, _already_ memoized... otherwise we have a big performance hit ( think, really big ) 19 | const memGetComponent = memoizeForGetComponent(getComponent(getSystem, getStore, getComponents)) 20 | const memMakeMappedContainer = memoizeForWithMappedContainer(withMappedContainer(getSystem, getStore, memGetComponent)) 21 | 22 | return { 23 | rootInjects: { 24 | getComponent: memGetComponent, 25 | makeMappedContainer: memMakeMappedContainer, 26 | render: render(getSystem, getStore, getComponent, getComponents), 27 | }, 28 | fn: { 29 | getDisplayName, 30 | }, 31 | } 32 | } 33 | 34 | export default viewPlugin 35 | -------------------------------------------------------------------------------- /src/core/presets/apis/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import BasePreset from "core/presets/base" 5 | import OpenAPI30Plugin from "core/plugins/oas3" 6 | import OpenAPI31Plugin from "core/plugins/oas31" 7 | import JSONSchema202012Plugin from "core/plugins/json-schema-2020-12" 8 | import JSONSchema202012SamplesPlugin from "core/plugins/json-schema-2020-12-samples" 9 | 10 | export default function PresetApis() { 11 | return [ 12 | BasePreset, 13 | OpenAPI30Plugin, 14 | JSONSchema202012Plugin, 15 | JSONSchema202012SamplesPlugin, 16 | OpenAPI31Plugin, 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/core/presets/base/plugins/form-components/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import * as LayoutUtils from "core/components/layout-utils" 5 | 6 | const FormComponentsPlugin = () => ({ 7 | components: { ...LayoutUtils }, 8 | }) 9 | 10 | export default FormComponentsPlugin 11 | -------------------------------------------------------------------------------- /src/core/utils/create-html-ready-id.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Replace invalid characters from a string to create an html-ready ID 3 | * 4 | * @param {string} id A string that may contain invalid characters for the HTML ID attribute 5 | * @param {string} [replacement=_] The string to replace invalid characters with; "_" by default 6 | * @return {string} Information about the parameter schema 7 | */ 8 | export default function createHtmlReadyId(id, replacement = "_") { 9 | return id.replace(/[^\w-]/g, replacement) 10 | } 11 | -------------------------------------------------------------------------------- /src/core/utils/jsonParse.js: -------------------------------------------------------------------------------- 1 | export function canJsonParse(str) { 2 | try { 3 | let testValueForJson = JSON.parse(str) 4 | return testValueForJson ? true : false 5 | } catch (e) { 6 | // exception: string is not valid json 7 | return null 8 | } 9 | } 10 | 11 | export function getKnownSyntaxHighlighterLanguage(val) { 12 | // to start, only check for json. can expand as needed in future 13 | const isValidJson = canJsonParse(val) 14 | return isValidJson ? "json" : null 15 | } 16 | -------------------------------------------------------------------------------- /src/core/window.js: -------------------------------------------------------------------------------- 1 | function makeWindow() { 2 | var win = { 3 | location: {}, 4 | history: {}, 5 | open: () => {}, 6 | close: () => {}, 7 | File: function() {}, 8 | FormData: function() {}, 9 | } 10 | 11 | if(typeof window === "undefined") { 12 | return win 13 | } 14 | 15 | try { 16 | win = window 17 | var props = ["File", "Blob", "FormData"] 18 | for (var prop of props) { 19 | if (prop in window) { 20 | win[prop] = window[prop] 21 | } 22 | } 23 | } catch( e ) { 24 | console.error(e) 25 | } 26 | 27 | return win 28 | } 29 | 30 | export default makeWindow() 31 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import SwaggerUI from "./core" 2 | 3 | export default SwaggerUI 4 | -------------------------------------------------------------------------------- /src/standalone/plugins/stadalone-layout/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import StandaloneLayout from "./components/StandaloneLayout" 5 | 6 | const StandaloneLayoutPlugin = () => ({ 7 | components: { 8 | StandaloneLayout, 9 | }, 10 | }) 11 | 12 | export default StandaloneLayoutPlugin 13 | -------------------------------------------------------------------------------- /src/standalone/plugins/top-bar/components/Logo.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import React from "react" 5 | import SwaggerUILogo from "../assets/logo_small.svg" 6 | 7 | const Logo = () => 8 | 9 | export default Logo 10 | -------------------------------------------------------------------------------- /src/standalone/plugins/top-bar/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import TopBar from "./components/TopBar" 5 | import Logo from "./components/Logo" 6 | 7 | const TopBarPlugin = () => ({ 8 | components: { Topbar: TopBar, Logo }, 9 | }) 10 | 11 | export default TopBarPlugin 12 | -------------------------------------------------------------------------------- /src/standalone/presets/standalone/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | import StandaloneLayoutPlugin from "standalone/plugins/stadalone-layout" 5 | import TopBarPlugin from "standalone/plugins/top-bar" 6 | import ConfigsPlugin from "core/plugins/configs" 7 | import SafeRenderPlugin from "core/plugins/safe-render" 8 | 9 | const StandalonePreset = [ 10 | TopBarPlugin, 11 | ConfigsPlugin, 12 | StandaloneLayoutPlugin, 13 | SafeRenderPlugin({ 14 | fullOverride: true, 15 | componentList: ["Topbar", "StandaloneLayout", "onlineValidatorBadge"], 16 | }), 17 | ] 18 | 19 | export default StandalonePreset 20 | -------------------------------------------------------------------------------- /src/style/_errors.scss: -------------------------------------------------------------------------------- 1 | @use "variables" as *; 2 | @use "type"; 3 | 4 | .errors-wrapper { 5 | margin: 20px; 6 | padding: 10px 20px; 7 | 8 | animation: scaleUp 0.5s; 9 | 10 | border: 2px solid $color-delete; 11 | border-radius: 4px; 12 | background: rgba($color-delete, 0.1); 13 | 14 | .error-wrapper { 15 | margin: 0 0 10px 0; 16 | } 17 | 18 | .errors { 19 | h4 { 20 | font-size: 14px; 21 | 22 | margin: 0; 23 | 24 | @include type.text_code(); 25 | } 26 | 27 | small { 28 | color: $errors-wrapper-errors-small-font-color; 29 | } 30 | 31 | .message { 32 | white-space: pre-line; 33 | 34 | &.thrown { 35 | max-width: 100%; 36 | } 37 | } 38 | 39 | .error-line { 40 | text-decoration: underline; 41 | cursor: pointer; 42 | } 43 | } 44 | 45 | hgroup { 46 | display: flex; 47 | 48 | align-items: center; 49 | 50 | h4 { 51 | font-size: 20px; 52 | 53 | margin: 0; 54 | 55 | flex: 1; 56 | @include type.text_headline(); 57 | } 58 | } 59 | } 60 | 61 | @keyframes scaleUp { 62 | 0% { 63 | transform: scale(0.8); 64 | 65 | opacity: 0; 66 | } 67 | 100% { 68 | transform: scale(1); 69 | 70 | opacity: 1; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/style/_markdown.scss: -------------------------------------------------------------------------------- 1 | @use "variables" as *; 2 | @use "type"; 3 | 4 | .markdown, 5 | .renderedMarkdown { 6 | p, 7 | pre { 8 | margin: 1em auto; 9 | 10 | word-break: break-all; /* Fallback trick */ 11 | word-break: break-word; 12 | } 13 | pre { 14 | color: black; 15 | font-weight: normal; 16 | white-space: pre-wrap; 17 | background: none; 18 | padding: 0px; 19 | } 20 | 21 | code { 22 | font-size: 14px; 23 | padding: 5px 7px; 24 | 25 | border-radius: 4px; 26 | background: rgba($info-code-background-color, 0.05); 27 | 28 | @include type.text_code($info-code-font-color); 29 | } 30 | 31 | pre > code { 32 | display: block; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/style/_servers.scss: -------------------------------------------------------------------------------- 1 | @use "variables" as *; 2 | @use "type"; 3 | 4 | .servers { 5 | > label { 6 | font-size: 12px; 7 | 8 | margin: -20px 15px 0 0; 9 | 10 | @include type.text_headline(); 11 | 12 | select { 13 | min-width: 130px; 14 | max-width: 100%; 15 | width: 100%; 16 | } 17 | } 18 | 19 | h4.message { 20 | padding-bottom: 2em; 21 | } 22 | 23 | table { 24 | tr { 25 | width: 30em; 26 | } 27 | td { 28 | display: inline-block; 29 | max-width: 15em; 30 | vertical-align: middle; 31 | padding-top: 10px; 32 | padding-bottom: 10px; 33 | 34 | &:first-of-type { 35 | padding-right: 1em; 36 | } 37 | 38 | input { 39 | width: 100%; 40 | height: 100%; 41 | } 42 | } 43 | } 44 | 45 | .computed-url { 46 | margin: 2em 0; 47 | 48 | code { 49 | display: inline-block; 50 | padding: 4px; 51 | font-size: 16px; 52 | margin: 0 1em; 53 | } 54 | } 55 | } 56 | 57 | .servers-title { 58 | font-size: 12px; 59 | font-weight: bold; 60 | } 61 | 62 | .operation-servers { 63 | h4.message { 64 | margin-bottom: 2em; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/style/_split-pane-mode.scss: -------------------------------------------------------------------------------- 1 | .Resizer.vertical.disabled { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /src/style/_type.scss: -------------------------------------------------------------------------------- 1 | @use "variables" as *; 2 | 3 | @mixin text_body($color: $text-body-default-font-color) { 4 | & { 5 | font-family: sans-serif; 6 | color: $color; 7 | } 8 | } 9 | 10 | @mixin text_code($color: $text-code-default-font-color) { 11 | font-family: monospace; 12 | font-weight: 600; 13 | 14 | color: $color; 15 | } 16 | 17 | @mixin text_headline($color: $text-headline-default-font-color) { 18 | font-family: sans-serif; 19 | 20 | color: $color; 21 | } 22 | -------------------------------------------------------------------------------- /src/style/main.scss: -------------------------------------------------------------------------------- 1 | @use "sass:meta"; 2 | @use "type"; 3 | 4 | .swagger-ui { 5 | @include type.text_body(); 6 | @include meta.load-css("~tachyons-sass/tachyons.scss"); 7 | @include meta.load-css("mixins"); 8 | @include meta.load-css("variables"); 9 | @include meta.load-css("type"); 10 | @include meta.load-css("layout"); 11 | @include meta.load-css("buttons"); 12 | @include meta.load-css("form"); 13 | @include meta.load-css("modal"); 14 | @include meta.load-css("models"); 15 | @include meta.load-css("servers"); 16 | @include meta.load-css("table"); 17 | @include meta.load-css("topbar"); 18 | @include meta.load-css("information"); 19 | @include meta.load-css("authorize"); 20 | @include meta.load-css("errors"); 21 | @include meta.load-css("split-pane-mode"); 22 | @include meta.load-css("markdown"); 23 | @include meta.load-css("../core/plugins/json-schema-2020-12/components/all"); 24 | @include meta.load-css("../core/plugins/oas31/components/all"); 25 | } 26 | -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | module.exports = { 6 | plugins: ["stylelint-prettier"], 7 | customSyntax: "postcss-scss", 8 | rules: { 9 | "prettier/prettier": [true, { requirePragma: false, insertPragma: false }], 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /swagger-ui-dist-package/.npmignore: -------------------------------------------------------------------------------- 1 | README.md 2 | deploy.sh 3 | -------------------------------------------------------------------------------- /swagger-ui-dist-package/.npmrc: -------------------------------------------------------------------------------- 1 | //registry.npmjs.org/:_authToken=${NPM_TOKEN} 2 | -------------------------------------------------------------------------------- /swagger-ui-dist-package/absolute-path.js: -------------------------------------------------------------------------------- 1 | /* 2 | * getAbsoluteFSPath 3 | * @return {string} When run in NodeJS env, returns the absolute path to the current directory 4 | * When run outside of NodeJS, will return an error message 5 | */ 6 | const getAbsoluteFSPath = function () { 7 | // detect whether we are running in a browser or nodejs 8 | if (typeof module !== "undefined" && module.exports) { 9 | return require("path").resolve(__dirname) 10 | } 11 | throw new Error('getAbsoluteFSPath can only be called within a Nodejs environment'); 12 | } 13 | 14 | module.exports = getAbsoluteFSPath 15 | -------------------------------------------------------------------------------- /swagger-ui-dist-package/deploy.sh: -------------------------------------------------------------------------------- 1 | # Deploy `swagger-ui-dist` to npm. 2 | 3 | # Parameter Expansion: http://stackoverflow.com/questions/6393551/what-is-the-meaning-of-0-in-a-bash-script 4 | cd "${0%/*}" 5 | 6 | # Get UI version 7 | UI_VERSION=$(node -p "require('../package.json').version") 8 | 9 | # Replace our version placeholder with UI's version 10 | sed -i "s|\$\$VERSION|$UI_VERSION|g" package.json 11 | 12 | # Copy UI's dist files to our directory 13 | cp ../dist/* . 14 | 15 | # Copy LICENSE & NOTICE to our directory 16 | cp ../LICENSE . 17 | cp ../NOTICE . 18 | 19 | if [ "$PUBLISH_DIST" = "true" ] || [ "$TRAVIS" = "true" ] ; then 20 | npm publish . 21 | else 22 | npm pack . 23 | fi 24 | 25 | find . -not -name .npmignore -not -name .npmrc -not -name deploy.sh -not -name index.js -not -name package.json -not -name README.md -not -name *.tgz -delete 26 | -------------------------------------------------------------------------------- /swagger-ui-dist-package/index.js: -------------------------------------------------------------------------------- 1 | try { 2 | module.exports.SwaggerUIBundle = require("./swagger-ui-bundle.js") 3 | module.exports.SwaggerUIStandalonePreset = require("./swagger-ui-standalone-preset.js") 4 | } catch(e) { 5 | // swallow the error if there's a problem loading the assets. 6 | // allows this module to support providing the assets for browserish contexts, 7 | // without exploding in a Node context. 8 | // 9 | // see https://github.com/swagger-api/swagger-ui/issues/3291#issuecomment-311195388 10 | // for more information. 11 | } 12 | 13 | // `absolutePath` and `getAbsoluteFSPath` are both here because at one point, 14 | // we documented having one and actually implemented the other. 15 | // They were both retained so we don't break anyone's code. 16 | module.exports.absolutePath = require("./absolute-path.js") 17 | module.exports.getAbsoluteFSPath = require("./absolute-path.js") 18 | -------------------------------------------------------------------------------- /swagger-ui-dist-package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "swagger-ui-dist", 3 | "version": "$$VERSION", 4 | "main": "index.js", 5 | "repository": "git@github.com:swagger-api/swagger-ui.git", 6 | "contributors": [ 7 | "(in alphabetical order)", 8 | "Anna Bodnia ", 9 | "Buu Nguyen ", 10 | "Josh Ponelat ", 11 | "Kyle Shockey ", 12 | "Robert Barnwell ", 13 | "Sahar Jafari " 14 | ], 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "@scarf/scarf": "=1.4.0" 18 | }, 19 | "devDependencies": {} 20 | } 21 | -------------------------------------------------------------------------------- /webpack/_helpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | const { gitDescribeSync } = require("git-describe") 6 | 7 | function getRepoInfo() { 8 | try { 9 | return gitDescribeSync(__dirname) 10 | } catch (e) { 11 | console.error(e) 12 | return { 13 | hash: "noGit", 14 | dirty: false, 15 | } 16 | } 17 | } 18 | 19 | function getDevtool(sourcemaps, minimize) { 20 | if (!sourcemaps) return false 21 | return minimize ? "source-map" : "cheap-module-source-map" 22 | } 23 | 24 | module.exports = { 25 | getRepoInfo, 26 | getDevtool, 27 | } 28 | -------------------------------------------------------------------------------- /webpack/core.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | const configBuilder = require("./_config-builder") 6 | 7 | const result = configBuilder( 8 | { 9 | minimize: true, 10 | mangle: true, 11 | sourcemaps: true, 12 | includeDependencies: false, 13 | }, 14 | { 15 | entry: { 16 | "swagger-ui": ["./src/index.js"], 17 | }, 18 | 19 | output: { 20 | globalObject: "this", 21 | library: { 22 | name: "SwaggerUICore", 23 | export: "default", 24 | }, 25 | }, 26 | } 27 | ) 28 | 29 | module.exports = result 30 | -------------------------------------------------------------------------------- /webpack/standalone.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @prettier 3 | */ 4 | 5 | const configBuilder = require("./_config-builder") 6 | 7 | const result = configBuilder( 8 | { 9 | minimize: true, 10 | mangle: true, 11 | sourcemaps: false, 12 | }, 13 | { 14 | entry: { 15 | "swagger-ui-standalone-preset": [ 16 | "./src/standalone/presets/standalone/index.js", 17 | ], 18 | }, 19 | 20 | output: { 21 | globalObject: "this", 22 | library: { 23 | name: "SwaggerUIStandalonePreset", 24 | export: "default", 25 | }, 26 | }, 27 | } 28 | ) 29 | 30 | module.exports = result 31 | --------------------------------------------------------------------------------