RapiDoc icon indicating copy to clipboard operation
RapiDoc copied to clipboard

RapiDoc Features

Open mrin9 opened this issue 4 years ago • 5 comments

Highlighting some of RapiDoc's features as these may be helpful for making a decision if RapiDoc is the right tool

I have included links of some examples below, sources of all of them can be found at https://github.com/rapi-doc/RapiDoc/tree/master/docs/examples and the OpenAPI specs used by the examples can be found at https://github.com/rapi-doc/RapiDoc/tree/master/docs/specs

RapiDoc Features

Theming and Customization

One of the main advantage of RapiDoc is its powerful customization. RapiDoc do not put any text that indicates the documentation is rendered using RapiDoc, you can completely replace the logos with your own, colors, fonts and theme can be changed to match with your own brand. Below are some of the feature that’s usually used

  • You may change font according to your liking
  • 3 different Font Sizes and spacing available
  • Dark and Light theme - Examples of Dark and Light Theme
  • Extend Dark and Light theme with your own mix of Background, Foreground, and other colors
  • Provide your own brand color, Logo - Logo Example Checkout this Theme Playground for various changes that you may do

Three Different Presentation Styles

  • View (accordion style exploration - resembles Swagger UI but with better space management with an option of side by side Request/Response or one below the other, suited mostly for API programmers) - Example
  • Read (typical left navigation and content, easy to read, good for specs that are heavy on descriptions and illustrations, images, tables etc) - Example
  • Focused (resembles read style, but instead of continuous scroll, it focuses on a single operation at a time ) Example

Hide/Show Sections to restrict or enable functionality

  • Enable/Disable Built In console (TRY Feature)
  • Hide or Show authentication section
  • Hide or Show API server’s associated with your spec
  • Hide or show Overview sections.

2 Beautiful Schema Presentation style

  • Tree Style (Good for schemas that are heavily nested, resembles typescript style type annotations )
  • Table Style (Good for flat or schemas with less nesting ) Example where you can toggle between both the styles and find out which one suites your need

Search and Filter Functionality

  • Supports in place filtering of operations
  • You can use filtering to hide certain operations for certain users. So the same spec can be presented showing different operations to different users
  • Provides advance search functionality allows you search specific locations like in response, request body, parameters

Authentication

Built In API console

Not a premium feature, in fact we do not have any premium product.

  • You can Try out API calls from the documentation
  • You can provide multiple API servers and make calls to any of them Example
  • Generates curl syntaxes
  • Parameters/ Request body can be pre-filled with examples, they also can be cleared or filled with a single click from the UI (nice to have for specs with lots of request parameters) Example
  • Auto generates multiple combinations of Request Body examples based on the schema definition -
  • Support Binary responses such as Images and renders them in the UI - Example

Markdown

  • Supports multiple markdown flavors - Example
  • Supports Code Syntax Highlight for various languages - Java, JavaScript, C#, python, Go and many more - Example
  • Create links to various sections of the Spec or list them on the side navigation bar - Example

Supports Open Schema Composition

  • Supports ALL-OF , ANY-OF, ONE-OF combinations and renders them beautifully - Example
  • Supports refs to externalize definitions

HTML, JavaScript and CSS Injection

Sometimes markdown is not enough to achieve, what’s needed. For those situations you can inject your own functionality using JS , HTML and CSS.

It also allows you to present the same spec with different, content to different section of users You can use JS to add functionality, such as provide a button inside the document that can automatically authenticate your user HTML Injection Example

RapiDoc’s Vendor Extensions

  • Code Samples
  • OAuth - Pre filling of clientId and Secret

Microservices support

Micro-services architecture may end up generating several OpenAPI spec, each with few Operations, However for the purpose of documentation you may want to list all these Specs in a single integrated view and should appear as a single spec. Thats possible with RapiDoc. For an inspiration have a look at this example - https://www.northbricks.io/apis/ , which appears to be a single documentation but is made with multiple instance of RapiDoc , each rendering a separate OpenAPI spec. (VIew source from browser to check implementation)

Framework Agnostic

All the above listed feature is programmable, You may check our API section to see how you can use these feature programatically. This isn’t a React, Angular or Vue component, But a standard natively supported Web Component and therefore can be accessed and integrated with any framework or just using a plain javascript without any other library

Here is a RapiDoc API Playground where we use plain JavaScript to dynamically make changes to the RapiDoc

mrin9 avatar Feb 27 '21 23:02 mrin9

Hello,

What about typescript definitions?

I tried to use rapidoc in a typescript react project without success.

francipvb avatar Jan 29 '22 22:01 francipvb

@francipvb Same problem. I started working on a wrapper for use in react:

/* eslint-disable @typescript-eslint/no-explicit-any */
import React from 'react';
import 'rapidoc';

interface RapiDocProps
  extends React.DetailedHTMLProps<
    React.HTMLAttributes<HTMLDivElement>,
    HTMLDivElement
  > {
  // General
  'spec-url': string;
  'update-route'?: boolean;
  'route-prefix'?: string;
  'sort-tags'?: boolean;
  'sort-endpoints-by'?: 'path' | 'method' | 'summary' | 'none';
  'heading-text'?: string;
  'goto-path'?: string;
  'fill-request-fields-with-example'?: boolean;
  'persist-auth'?: boolean;
  // UI Colors and Fonts
  theme?: 'light' | 'dark';
  'bg-color'?: string;
  'text-color'?: string;
  'header-color'?: string;
  'primary-color'?: string;
  'load-fonts'?: boolean;
  'regular-fonts'?: string;
  'mono-fonts'?: string;
  'font-size'?: 'default' | 'large' | 'largest';
  // Navigation
  'use-path-in-nav-bar'?: boolean;
  'nav-bg-color'?: string;
  'nav-text-color'?: string;
  'nav-hover-bg-color'?: string;
  'nav-hover-text-color'?: string;
  'nav-accent-color'?: string;
  'nav-item-spacing'?: 'default' | 'compact' | 'relaxed';
  // UI Layout & Placement
  layout?: 'row' | 'column';
  'render-style'?: 'read' | 'view' | 'focused';
  'on-nav-tag-click'?: 'expand-collapse' | 'show-description';
  'schema-style'?: 'tree' | 'table';
  'schema-expand-level'?: number;
  'schema-description-expanded'?: boolean;
  'schema-hide-read-only'?: 'always' | 'never' | string;
  'default-schema-tab'?: 'model' | 'example';
  'response-area-height'?: string;
  // Hide/Show Sections
  'show-info'?: boolean;
  'info-description-headings-in-navbar'?: boolean;
  'show-components'?: boolean;
  'show-header'?: boolean;
  'allow-authentication'?: boolean;
  'allow-spec-url-load'?: boolean;
  'allow-spec-file-load'?: boolean;
  'allow-spec-file-download'?: boolean;
  'allow-search'?: boolean;
  'allow-advanced-search'?: boolean;
  'allow-try'?: boolean;
  'allow-server-selection'?: boolean;
  'allow-schema-description-expand-toggle'?: boolean;
  // API Server & calls
  'server-url'?: string;
  'default-api-server'?: string;
  'api-key-name'?: string;
  'api-key-location'?: 'header' | 'query';
  'api-key-value'?: string;
  'fetch-credentials'?: 'omit' | 'same-origin' | 'include';
  // Events
  beforeRender?: (spec: any) => void;
  specLoaded?: (spec: any) => void;
  beforeTry?: (request: any) => any;
  afterTry?: (data: any) => any;
  apiServerChange?: (server: any) => any;
}

declare global {
  interface HTMLElementTagNameMap {
    'rapi-doc': HTMLDivElement;
  }
  /* eslint-disable @typescript-eslint/no-namespace */
  namespace JSX {
    interface IntrinsicElements {
      'rapi-doc': RapiDocProps;
    }
  }
}

export const RapiDocReact = React.forwardRef<HTMLDivElement, RapiDocProps>(
  (
    {
      beforeRender,
      specLoaded,
      beforeTry,
      afterTry,
      apiServerChange,
      children,
      ...props
    }: RapiDocProps,
    ref
  ) => {
    const localRef = React.useRef<HTMLDivElement>(null);

    React.useEffect(() => {
      const rapiDocRef =
        typeof ref === 'object' && ref?.current
          ? ref?.current
          : localRef.current;

      const handleBeforeRender = (spec: any) => {
        beforeRender && beforeRender(spec);
      };

      const handleSpecLoaded = (spec: any) => {
        specLoaded && specLoaded(spec);
      };

      const handleBeforeTry = (request: any) => {
        beforeTry && beforeTry(request);
      };

      const handleAfterTry = (data: any) => {
        afterTry && afterTry(data);
      };

      const handleApiServerChange = (server: any) => {
        apiServerChange && apiServerChange(server);
      };

      console.log(`rapiDocRef`, rapiDocRef);
      if (rapiDocRef) {
        beforeRender &&
          rapiDocRef.addEventListener('before-render', handleBeforeRender);
        specLoaded &&
          rapiDocRef.addEventListener('spec-loaded', handleSpecLoaded);
        beforeTry && rapiDocRef.addEventListener('before-try', handleBeforeTry);
        afterTry && rapiDocRef.addEventListener('after-try', handleAfterTry);
        apiServerChange &&
          rapiDocRef.addEventListener(
            'api-server-change',
            handleApiServerChange
          );
      }
      return () => {
        if (rapiDocRef) {
          beforeRender &&
            rapiDocRef.removeEventListener('before-render', handleBeforeRender);
          specLoaded &&
            rapiDocRef.removeEventListener('spec-loaded', handleSpecLoaded);
          beforeTry &&
            rapiDocRef.removeEventListener('before-try', handleBeforeTry);
          afterTry &&
            rapiDocRef.removeEventListener('after-try', handleAfterTry);
          apiServerChange &&
            rapiDocRef.removeEventListener(
              'api-server-change',
              handleApiServerChange
            );
        }
      };
    }, [
      ref,
      localRef,
      specLoaded,
      beforeRender,
      beforeTry,
      afterTry,
      apiServerChange,
    ]);

    return (
      <rapi-doc {...props} ref={ref || localRef}>
        {children}
      </rapi-doc>
    );
  }
);

export default RapiDocReact;

Then you can use it like:

export function Example() {
  return (
    <RapiDocReact
      specLoaded={(spec) => {
        console.log(spec);
      }}
      show-header={false}
      spec-url="https://petstore.swagger.io/v2/swagger.json"
      render-style="read"
      theme="dark"
      style={{ height: '100vh', width: '100%' }}
    />
  );
}

export default Example;

Brian-McBride avatar Feb 02 '22 14:02 Brian-McBride

how to change the markdown styles. for ex: If i need to style the table,what is the approach?

meiyananthamp avatar Mar 08 '23 08:03 meiyananthamp

@mrin9 Hi Mrinmoy, pls can you update examples for the filtering functionality, specifically to hide certain operations for specific users?

Thanks

sberwal avatar Jun 21 '23 17:06 sberwal