redoc/src/standalone.tsx

101 lines
2.4 KiB
TypeScript

import * as React from 'react';
import { hydrate as hydrateComponent, render } from 'react-dom';
import { Redoc, RedocStandalone } from './components/';
import { AppStore, StoreState } from './services/AppStore';
import { debugTime, debugTimeEnd } from './utils/debug';
import { querySelector } from './utils/dom';
export { Redoc, AppStore } from '.';
export const version = __REDOC_VERSION__;
export const revision = __REDOC_REVISION__;
function attributesMap(element: Element) {
const res = {};
const elAttrs = element.attributes;
// tslint:disable-next-line
for (let i = 0; i < elAttrs.length; i++) {
const attrib = elAttrs[i];
res[attrib.name] = attrib.value;
}
return res;
}
function parseOptionsFromElement(element: Element) {
const attrMap = attributesMap(element);
const res = {};
for (const attrName in attrMap) {
const optionName = attrName.replace(/-(.)/g, (_, $1) => $1.toUpperCase());
res[optionName] = attrMap[attrName];
// TODO: normalize options
}
return res;
}
export function init(
specOrSpecUrl: string | any,
options: any = {},
element: Element | null = querySelector('redoc'),
callback?: (e?: Error) => void,
) {
if (element === null) {
throw new Error('"element" argument is not provided and <redoc> tag is not found on the page');
}
let specUrl: string | undefined;
let spec: object | undefined;
if (typeof specOrSpecUrl === 'string') {
specUrl = specOrSpecUrl;
} else if (typeof specOrSpecUrl === 'object') {
spec = specOrSpecUrl;
}
render(
React.createElement(
RedocStandalone,
{
spec,
onLoaded: callback,
specUrl,
options: { ...options, ...parseOptionsFromElement(element) },
},
['Loading...'],
),
element,
);
}
export function hydrate(
state: StoreState,
element: Element | null = querySelector('redoc'),
callback?: () => void,
) {
debugTime('Redoc create store');
const store = AppStore.fromJS(state);
debugTimeEnd('Redoc create store');
setTimeout(() => {
debugTime('Redoc hydrate');
hydrateComponent(<Redoc store={store} />, element, callback);
debugTimeEnd('Redoc hydrate');
}, 0);
}
/**
* autoinit ReDoc if <redoc> tag is found on the page with "spec-url" attr
*/
function autoInit() {
const element = querySelector('redoc');
if (!element) {
return;
}
const specUrl = element.getAttribute('spec-url');
if (specUrl) {
init(specUrl, {}, element);
}
}
autoInit();