mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-13 04:16:34 +03:00
do not crashe when used in node (isomorphic)
This commit is contained in:
parent
50e2a5868d
commit
d67852f9c4
|
@ -50,7 +50,6 @@
|
||||||
"enzyme": "^3.1.1",
|
"enzyme": "^3.1.1",
|
||||||
"enzyme-adapter-react-16": "^1.0.4",
|
"enzyme-adapter-react-16": "^1.0.4",
|
||||||
"enzyme-to-json": "^3.2.2",
|
"enzyme-to-json": "^3.2.2",
|
||||||
"extract-text-webpack-plugin": "^3.0.0",
|
|
||||||
"html-webpack-plugin": "^2.30.1",
|
"html-webpack-plugin": "^2.30.1",
|
||||||
"http-server": "^0.10.0",
|
"http-server": "^0.10.0",
|
||||||
"jest": "^21.1.0",
|
"jest": "^21.1.0",
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import styled from '../styled-components';
|
import styled, { injectGlobal } from '../styled-components';
|
||||||
import 'perfect-scrollbar/dist/css/perfect-scrollbar.css';
|
import psStyles from 'perfect-scrollbar/dist/css/perfect-scrollbar.css';
|
||||||
|
|
||||||
import PerfectScrollbarOriginal from 'react-perfect-scrollbar';
|
import PerfectScrollbarOriginal from 'react-perfect-scrollbar';
|
||||||
|
|
||||||
|
injectGlobal`${psStyles}`;
|
||||||
|
|
||||||
export const PerfectScrollbar = styled(PerfectScrollbarOriginal)`
|
export const PerfectScrollbar = styled(PerfectScrollbarOriginal)`
|
||||||
position: relative;
|
position: relative;
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -72,7 +72,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -114,6 +114,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -176,7 +177,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -218,6 +219,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -263,7 +265,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -305,6 +307,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -404,7 +407,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -446,6 +449,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -508,7 +512,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -550,6 +554,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -595,7 +600,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -637,6 +642,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -706,7 +712,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -748,6 +754,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -843,7 +850,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -885,6 +892,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -947,7 +955,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -989,6 +997,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -1034,7 +1043,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -1076,6 +1085,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -1173,7 +1183,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -1215,6 +1225,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
@ -1284,7 +1295,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
"weight": "300",
|
"weight": "300",
|
||||||
},
|
},
|
||||||
"code": Object {
|
"code": Object {
|
||||||
"fontFamily": "\\"Lucida Console\\", Monaco, monospace",
|
"fontFamily": "Courirer, monospace",
|
||||||
"fontSize": "13px",
|
"fontSize": "13px",
|
||||||
},
|
},
|
||||||
"colors": Object {
|
"colors": Object {
|
||||||
|
@ -1326,6 +1337,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
|
||||||
"width": 40,
|
"width": 40,
|
||||||
},
|
},
|
||||||
"schemaView": Object {
|
"schemaView": Object {
|
||||||
|
"defaultDetailsWidth": "75%",
|
||||||
"linesColor": "#7f99cf",
|
"linesColor": "#7f99cf",
|
||||||
},
|
},
|
||||||
"spacingUnit": 20,
|
"spacingUnit": 20,
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Stickyfill from 'stickyfill';
|
|
||||||
|
|
||||||
import { ComponentWithOptions } from '../OptionsProvider';
|
import { ComponentWithOptions } from '../OptionsProvider';
|
||||||
import { RedocNormalizedOptions, RedocRawOptions } from '../../services/RedocNormalizedOptions';
|
import { RedocNormalizedOptions, RedocRawOptions } from '../../services/RedocNormalizedOptions';
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
|
|
||||||
|
let Stickyfill;
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
Stickyfill = require('stickyfill').default;
|
||||||
|
}
|
||||||
|
|
||||||
export interface StickySidebarProps {
|
export interface StickySidebarProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
scrollYOffset?: RedocRawOptions['scrollYOffset']; // passed directly or via context
|
scrollYOffset?: RedocRawOptions['scrollYOffset']; // passed directly or via context
|
||||||
}
|
}
|
||||||
|
|
||||||
const stickyfill = Stickyfill();
|
const stickyfill = Stickyfill && Stickyfill();
|
||||||
|
|
||||||
const StyledStickySidebar = styled.div`
|
const StyledStickySidebar = styled.div`
|
||||||
width: ${props => props.theme.menu.width};
|
width: ${props => props.theme.menu.width};
|
||||||
|
@ -31,11 +34,11 @@ export class StickySidebar extends ComponentWithOptions<StickySidebarProps> {
|
||||||
stickyElement: Element;
|
stickyElement: Element;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
stickyfill.add(this.stickyElement);
|
stickyfill && stickyfill.add(this.stickyElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
stickyfill.remove(this.stickyElement);
|
stickyfill && stickyfill.remove(this.stickyElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
get scrollYOffset() {
|
get scrollYOffset() {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
const isSupported = document.queryCommandSupported && document.queryCommandSupported('copy');
|
const isSupported =
|
||||||
|
typeof document !== 'undefined' &&
|
||||||
|
document.queryCommandSupported &&
|
||||||
|
document.queryCommandSupported('copy');
|
||||||
|
|
||||||
export class ClipboardService {
|
export class ClipboardService {
|
||||||
static isSupported(): boolean {
|
static isSupported(): boolean {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { bind, debounce } from 'decko';
|
import { bind, debounce } from 'decko';
|
||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
import { isBrowser } from '../utils/';
|
||||||
|
|
||||||
const EVENT = 'hashchange';
|
const EVENT = 'hashchange';
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ class _HistoryService {
|
||||||
}
|
}
|
||||||
|
|
||||||
get hash(): string {
|
get hash(): string {
|
||||||
return window.location.hash;
|
return isBrowser ? window.location.hash : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(cb): () => void {
|
subscribe(cb): () => void {
|
||||||
|
@ -34,11 +35,15 @@ class _HistoryService {
|
||||||
};
|
};
|
||||||
|
|
||||||
bind() {
|
bind() {
|
||||||
window.addEventListener('hashchange', this.emit, false);
|
if (isBrowser) {
|
||||||
|
window.addEventListener('hashchange', this.emit, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
window.removeEventListener('hashchange', this.emit);
|
if (isBrowser) {
|
||||||
|
window.removeEventListener('hashchange', this.emit);
|
||||||
|
}
|
||||||
this.causedHashChange = false;
|
this.causedHashChange = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +52,15 @@ class _HistoryService {
|
||||||
update(hash: string | null, rewriteHistory: boolean = false) {
|
update(hash: string | null, rewriteHistory: boolean = false) {
|
||||||
if (hash == null || isSameHash(hash, this.hash)) return;
|
if (hash == null || isSameHash(hash, this.hash)) return;
|
||||||
if (rewriteHistory) {
|
if (rewriteHistory) {
|
||||||
window.history.replaceState(null, '', window.location.href.split('#')[0] + '#' + hash);
|
if (isBrowser) {
|
||||||
|
window.history.replaceState(null, '', window.location.href.split('#')[0] + '#' + hash);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.causedHashChange = true;
|
this.causedHashChange = true;
|
||||||
window.location.hash = hash;
|
if (isBrowser) {
|
||||||
|
window.location.hash = hash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as Remarkable from 'remarkable';
|
||||||
import { MDComponent } from '../components/Markdown/Markdown';
|
import { MDComponent } from '../components/Markdown/Markdown';
|
||||||
import { IMenuItem, SECTION_ATTR } from './MenuStore';
|
import { IMenuItem, SECTION_ATTR } from './MenuStore';
|
||||||
import { GroupModel } from './models';
|
import { GroupModel } from './models';
|
||||||
import { highlight } from '../utils';
|
import { highlight, html2Str } from '../utils';
|
||||||
|
|
||||||
const md = new Remarkable('default', {
|
const md = new Remarkable('default', {
|
||||||
html: true,
|
html: true,
|
||||||
|
@ -64,13 +64,6 @@ export class MarkdownRenderer {
|
||||||
attachHeadingsContent(rawText: string) {
|
attachHeadingsContent(rawText: string) {
|
||||||
const buildRegexp = heading => new RegExp(`<h\\d ${SECTION_ATTR}="section/${heading.id}">`);
|
const buildRegexp = heading => new RegExp(`<h\\d ${SECTION_ATTR}="section/${heading.id}">`);
|
||||||
|
|
||||||
const tmpEl = document.createElement('DIV');
|
|
||||||
|
|
||||||
const html2Str = html => {
|
|
||||||
tmpEl.innerHTML = html;
|
|
||||||
return tmpEl.innerText;
|
|
||||||
};
|
|
||||||
|
|
||||||
let flatHeadings = this.flattenHeadings(this.headings);
|
let flatHeadings = this.flattenHeadings(this.headings);
|
||||||
if (flatHeadings.length < 1) return;
|
if (flatHeadings.length < 1) return;
|
||||||
let prevHeading = flatHeadings[0];
|
let prevHeading = flatHeadings[0];
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { OperationModel, SpecStore } from './models';
|
import { querySelector } from '../utils/dom';
|
||||||
|
import { OperationModel, GroupModel, SpecStore } from './models';
|
||||||
import { computed, action } from 'mobx';
|
import { computed, action } from 'mobx';
|
||||||
|
|
||||||
import { ScrollService } from './ScrollService';
|
import { ScrollService } from './ScrollService';
|
||||||
|
@ -36,9 +37,9 @@ export class MenuStore {
|
||||||
/**
|
/**
|
||||||
* cached flattened menu items to support absolute indexing
|
* cached flattened menu items to support absolute indexing
|
||||||
*/
|
*/
|
||||||
private _flatItems: IMenuItem[];
|
|
||||||
private _unsubscribe: Function;
|
private _unsubscribe: Function;
|
||||||
private _hashUnsubscribe: Function;
|
private _hashUnsubscribe: Function;
|
||||||
|
private _items?: (GroupModel | OperationModel)[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* active item absolute index (when flattened). -1 means nothing is selected
|
* active item absolute index (when flattened). -1 means nothing is selected
|
||||||
|
@ -60,7 +61,10 @@ export class MenuStore {
|
||||||
*/
|
*/
|
||||||
@computed
|
@computed
|
||||||
get items(): IMenuItem[] {
|
get items(): IMenuItem[] {
|
||||||
return this.spec.operationGroups;
|
if (!this._items) {
|
||||||
|
this._items = this.spec.operationGroups;
|
||||||
|
}
|
||||||
|
return this._items;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,7 +143,7 @@ export class MenuStore {
|
||||||
*/
|
*/
|
||||||
getElementAt(idx: number): Element | null {
|
getElementAt(idx: number): Element | null {
|
||||||
const item = this.flatItems[idx];
|
const item = this.flatItems[idx];
|
||||||
return (item && document.querySelector(`[${SECTION_ATTR}="${item.id}"]`)) || null;
|
return (item && querySelector(`[${SECTION_ATTR}="${item.id}"]`)) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -152,13 +156,11 @@ export class MenuStore {
|
||||||
/**
|
/**
|
||||||
* flattened items as they appear in the tree depth-first (top to bottom in the view)
|
* flattened items as they appear in the tree depth-first (top to bottom in the view)
|
||||||
*/
|
*/
|
||||||
|
@computed
|
||||||
get flatItems(): IMenuItem[] {
|
get flatItems(): IMenuItem[] {
|
||||||
if (!this._flatItems) {
|
const flatItems = flattenByProp(this._items || [], 'items');
|
||||||
this._flatItems = flattenByProp(this.items, 'items');
|
flatItems.forEach((item, idx) => (item.absoluteIdx = idx));
|
||||||
this._flatItems.forEach((item, idx) => (item.absoluteIdx = idx));
|
return flatItems;
|
||||||
}
|
|
||||||
|
|
||||||
return this._flatItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,7 +190,7 @@ export class MenuStore {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.activeItemIdx = item.absoluteIdx!;
|
this.activeItemIdx = item.absoluteIdx || -1;
|
||||||
if (updateHash) {
|
if (updateHash) {
|
||||||
HistoryService.update(item.getHash(), rewriteHistory);
|
HistoryService.update(item.getHash(), rewriteHistory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { JsonPointer } from '../utils/JsonPointer';
|
||||||
import { isNamedDefinition } from '../utils/openapi';
|
import { isNamedDefinition } from '../utils/openapi';
|
||||||
import { COMPONENT_REGEXP, buildComponentComment } from './MarkdownRenderer';
|
import { COMPONENT_REGEXP, buildComponentComment } from './MarkdownRenderer';
|
||||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||||
import { appendToMdHeading } from '../utils/';
|
import { appendToMdHeading, isBrowser } from '../utils/';
|
||||||
|
|
||||||
export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
||||||
|
|
||||||
|
@ -52,10 +52,11 @@ export class OpenAPIParser {
|
||||||
|
|
||||||
this.spec = spec;
|
this.spec = spec;
|
||||||
|
|
||||||
|
const href = isBrowser ? window.location.href : '';
|
||||||
if (typeof specUrl === 'string') {
|
if (typeof specUrl === 'string') {
|
||||||
this.specUrl = urlResolve(window.location.href, specUrl);
|
this.specUrl = urlResolve(href, specUrl);
|
||||||
} else {
|
} else {
|
||||||
this.specUrl = window.location.href;
|
this.specUrl = href;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { ThemeInterface } from '../theme';
|
import { ThemeInterface } from '../theme';
|
||||||
import { isNumeric, mergeObjects } from '../utils/helpers';
|
import { isNumeric, mergeObjects } from '../utils/helpers';
|
||||||
|
import { querySelector } from '../utils/dom';
|
||||||
import defaultTheme from '../theme';
|
import defaultTheme from '../theme';
|
||||||
|
|
||||||
export interface RedocRawOptions {
|
export interface RedocRawOptions {
|
||||||
|
@ -69,7 +70,7 @@ export class RedocNormalizedOptions {
|
||||||
static normalizeScrollYOffset(value: RedocRawOptions['scrollYOffset']): () => number {
|
static normalizeScrollYOffset(value: RedocRawOptions['scrollYOffset']): () => number {
|
||||||
// just number is not valid selector and leads to crash so checking if isNumeric here
|
// just number is not valid selector and leads to crash so checking if isNumeric here
|
||||||
if (typeof value === 'string' && !isNumeric(value)) {
|
if (typeof value === 'string' && !isNumeric(value)) {
|
||||||
const el = document.querySelector(value);
|
const el = querySelector(value);
|
||||||
if (!el) {
|
if (!el) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'scrollYOffset value is a selector to non-existing element. Using offset 0 by default',
|
'scrollYOffset value is a selector to non-existing element. Using offset 0 by default',
|
||||||
|
|
|
@ -1,33 +1,35 @@
|
||||||
import { debounce, bind } from 'decko';
|
import { debounce, bind } from 'decko';
|
||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
|
||||||
|
import { querySelector, isBrowser } from '../utils';
|
||||||
|
|
||||||
const EVENT = 'scroll';
|
const EVENT = 'scroll';
|
||||||
|
|
||||||
export class ScrollService {
|
export class ScrollService {
|
||||||
private _scrollParent: Window | HTMLElement;
|
private _scrollParent: Window | HTMLElement | undefined;
|
||||||
private _emiter: EventEmitter;
|
private _emiter: EventEmitter;
|
||||||
private _prevOffsetY: number = 0;
|
private _prevOffsetY: number = 0;
|
||||||
constructor() {
|
constructor() {
|
||||||
this._scrollParent = window;
|
this._scrollParent = isBrowser ? window : undefined;
|
||||||
this._emiter = new EventEmitter();
|
this._emiter = new EventEmitter();
|
||||||
this.bind();
|
this.bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
bind() {
|
bind() {
|
||||||
this._prevOffsetY = this.scrollY();
|
this._prevOffsetY = this.scrollY();
|
||||||
this._scrollParent.addEventListener('scroll', this.handleScroll);
|
this._scrollParent && this._scrollParent.addEventListener('scroll', this.handleScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this._scrollParent.removeEventListener('scroll', this.handleScroll);
|
this._scrollParent && this._scrollParent.removeEventListener('scroll', this.handleScroll);
|
||||||
this._emiter.removeAllListeners(EVENT);
|
this._emiter.removeAllListeners(EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollY(): number {
|
scrollY(): number {
|
||||||
if (this._scrollParent === window) {
|
if (typeof HTMLElement !== 'undefined' && this._scrollParent instanceof HTMLElement) {
|
||||||
return window.pageYOffset;
|
|
||||||
} else if (this._scrollParent instanceof HTMLElement) {
|
|
||||||
return this._scrollParent.scrollTop;
|
return this._scrollParent.scrollTop;
|
||||||
|
} else if (this._scrollParent !== undefined) {
|
||||||
|
return (this._scrollParent as Window).pageYOffset;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +58,7 @@ export class ScrollService {
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollIntoViewBySelector(selector: string) {
|
scrollIntoViewBySelector(selector: string) {
|
||||||
const element = document.querySelector(selector);
|
const element = querySelector(selector);
|
||||||
this.scrollIntoView(element);
|
this.scrollIntoView(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { OpenAPIContact, OpenAPIInfo, OpenAPILicense } from '../../types';
|
import { OpenAPIContact, OpenAPIInfo, OpenAPILicense } from '../../types';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
import { isBrowser } from '../../utils/';
|
||||||
|
|
||||||
export class ApiInfoModel implements OpenAPIInfo {
|
export class ApiInfoModel implements OpenAPIInfo {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -15,7 +16,7 @@ export class ApiInfoModel implements OpenAPIInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
get downloadLink() {
|
get downloadLink() {
|
||||||
if (!this.parser.specUrl && window.Blob && window.URL) {
|
if (!this.parser.specUrl && isBrowser && window.Blob && window.URL) {
|
||||||
const blob = new Blob([JSON.stringify(this.parser.spec, null, 2)], {
|
const blob = new Blob([JSON.stringify(this.parser.spec, null, 2)], {
|
||||||
type: 'application/json',
|
type: 'application/json',
|
||||||
});
|
});
|
||||||
|
@ -25,7 +26,7 @@ export class ApiInfoModel implements OpenAPIInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
get downloadFileName(): string | undefined {
|
get downloadFileName(): string | undefined {
|
||||||
if (!this.parser.specUrl && window.Blob && window.URL) {
|
if (!this.parser.specUrl && isBrowser && window.Blob && window.URL) {
|
||||||
return 'swagger.json';
|
return 'swagger.json';
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { querySelector } from './utils/dom';
|
||||||
import { RedocStandalone } from './components/RedocStandalone';
|
import { RedocStandalone } from './components/RedocStandalone';
|
||||||
|
|
||||||
export const version = __REDOC_VERSION__;
|
export const version = __REDOC_VERSION__;
|
||||||
|
@ -30,7 +31,7 @@ function parseOptionsFromElement(element: Element) {
|
||||||
export function init(
|
export function init(
|
||||||
specOrSpecUrl: string | any,
|
specOrSpecUrl: string | any,
|
||||||
options: any = {},
|
options: any = {},
|
||||||
element: Element | null = document.querySelector('redoc'),
|
element: Element | null = querySelector('redoc'),
|
||||||
) {
|
) {
|
||||||
if (element === null) {
|
if (element === null) {
|
||||||
throw new Error('"element" argument is not provided and <redoc> tag is not found on the page');
|
throw new Error('"element" argument is not provided and <redoc> tag is not found on the page');
|
||||||
|
@ -63,7 +64,7 @@ export function init(
|
||||||
* autoinit ReDoc if <redoc> tag is found on the page with "spec-url" attr
|
* autoinit ReDoc if <redoc> tag is found on the page with "spec-url" attr
|
||||||
*/
|
*/
|
||||||
function autoInit() {
|
function autoInit() {
|
||||||
const element = document.querySelector('redoc');
|
const element = querySelector('redoc');
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
25
src/utils/dom.ts
Normal file
25
src/utils/dom.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
export const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
||||||
|
|
||||||
|
export function querySelector(selector: string): Element | null {
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
return document.querySelector(selector);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop everything inside <...> (i.e., tags/elements), and keep the text.
|
||||||
|
* Unlike browser innerText, this removes newlines; it also doesn't handle
|
||||||
|
* un-encoded `<` or `>` characters very well, so don't feed it malformed HTML
|
||||||
|
*/
|
||||||
|
export function html2Str(html: string): string {
|
||||||
|
return html
|
||||||
|
.split(/<[^>]+>/)
|
||||||
|
.map(function(chunk) {
|
||||||
|
return chunk.trim();
|
||||||
|
})
|
||||||
|
.filter(function(trimmedChunk) {
|
||||||
|
return trimmedChunk.length > 0;
|
||||||
|
})
|
||||||
|
.join(' ');
|
||||||
|
}
|
|
@ -20,7 +20,10 @@ import 'prismjs/components/prism-objectivec.js';
|
||||||
import 'prismjs/components/prism-scala.js';
|
import 'prismjs/components/prism-scala.js';
|
||||||
import 'prismjs/components/prism-markup.js'; // xml
|
import 'prismjs/components/prism-markup.js'; // xml
|
||||||
|
|
||||||
import 'prismjs/themes/prism-dark.css'; // dark theme
|
import { injectGlobal } from '../styled-components';
|
||||||
|
|
||||||
|
import prismStyles from 'prismjs/themes/prism-dark.css'; // dark theme
|
||||||
|
injectGlobal`${prismStyles}`;
|
||||||
|
|
||||||
const DEFAULT_LANG = 'clike';
|
const DEFAULT_LANG = 'clike';
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,4 @@ export * from './openapi';
|
||||||
export * from './helpers';
|
export * from './helpers';
|
||||||
export * from './highlight';
|
export * from './highlight';
|
||||||
export * from './loadAndBundleSpec';
|
export * from './loadAndBundleSpec';
|
||||||
|
export * from './dom';
|
||||||
|
|
|
@ -92,16 +92,13 @@ export default env => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
use: [
|
use: {
|
||||||
'style-loader',
|
loader: 'css-loader',
|
||||||
{
|
options: {
|
||||||
loader: 'css-loader',
|
sourceMap: true,
|
||||||
options: {
|
minimize: true,
|
||||||
sourceMap: true,
|
|
||||||
minimize: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
},
|
},
|
||||||
{ enforce: 'pre', test: /\.js$/, loader: 'source-map-loader' },
|
{ enforce: 'pre', test: /\.js$/, loader: 'source-map-loader' },
|
||||||
],
|
],
|
||||||
|
@ -128,7 +125,7 @@ export default env => {
|
||||||
if (!env.standalone) {
|
if (!env.standalone) {
|
||||||
config.externals = (context, request, callback) => {
|
config.externals = (context, request, callback) => {
|
||||||
// ignore node-fetch dep of swagger2openapi as it is not used
|
// ignore node-fetch dep of swagger2openapi as it is not used
|
||||||
if (/node-fetch$/i.test(request)) return callback(null, 'var fetch');
|
if (/node-fetch$/i.test(request)) return callback(null, 'var undefined');
|
||||||
return nodeExternals(context, request, callback);
|
return nodeExternals(context, request, callback);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
11
yarn.lock
11
yarn.lock
|
@ -424,7 +424,7 @@ async@^1.4.0, async@^1.5.2:
|
||||||
version "1.5.2"
|
version "1.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
||||||
|
|
||||||
async@^2.1.2, async@^2.1.4, async@^2.4.1, async@^2.5.0:
|
async@^2.1.2, async@^2.1.4, async@^2.5.0:
|
||||||
version "2.6.0"
|
version "2.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
|
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -2505,15 +2505,6 @@ extglob@^2.0.2:
|
||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
extract-text-webpack-plugin@^3.0.0:
|
|
||||||
version "3.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz#5f043eaa02f9750a9258b78c0a6e0dc1408fb2f7"
|
|
||||||
dependencies:
|
|
||||||
async "^2.4.1"
|
|
||||||
loader-utils "^1.1.0"
|
|
||||||
schema-utils "^0.3.0"
|
|
||||||
webpack-sources "^1.0.1"
|
|
||||||
|
|
||||||
extract-zip@1.6.5:
|
extract-zip@1.6.5:
|
||||||
version "1.6.5"
|
version "1.6.5"
|
||||||
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.5.tgz#99a06735b6ea20ea9b705d779acffcc87cff0440"
|
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.5.tgz#99a06735b6ea20ea9b705d779acffcc87cff0440"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user