mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-27 19:13:44 +03:00
Merge commit '71752aea02f8923e1e9fe7278ba7393c3ba751bf' into releases
This commit is contained in:
commit
e13c6309ce
65
CHANGELOG.md
65
CHANGELOG.md
|
@ -1,3 +1,68 @@
|
|||
<a name="1.14.0"></a>
|
||||
# [1.14.0](https://github.com/Rebilly/ReDoc/compare/v1.13.0...v1.14.0) (2017-04-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* don't show download button if initialized with an object ([476d6c4](https://github.com/Rebilly/ReDoc/commit/476d6c4))
|
||||
* endpoint link doesn't expand when click on arrow ([9248cc2](https://github.com/Rebilly/ReDoc/commit/9248cc2))
|
||||
* markdown block text color 💅 ([0f6f035](https://github.com/Rebilly/ReDoc/commit/0f6f035)), closes [#255](https://github.com/Rebilly/ReDoc/issues/255)
|
||||
* ReDoc removes path if site is using history API ([c77e1a2](https://github.com/Rebilly/ReDoc/commit/c77e1a2)), closes [#257](https://github.com/Rebilly/ReDoc/issues/257)
|
||||
* remove trailing slash from url when use `x-servers` ([2760a34](https://github.com/Rebilly/ReDoc/commit/2760a34))
|
||||
* subscription leak in side-menu ([838f233](https://github.com/Rebilly/ReDoc/commit/838f233))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add GH-like anchors to h1 and h2 headings in md ([bb3667d](https://github.com/Rebilly/ReDoc/commit/bb3667d))
|
||||
* add perfect-scrollbar for side menu ([cdeee67](https://github.com/Rebilly/ReDoc/commit/cdeee67))
|
||||
* emphasize path with primary color in servers dropdown ([388b3d4](https://github.com/Rebilly/ReDoc/commit/388b3d4))
|
||||
* new option `path-in-middle-panel` ([74a3193](https://github.com/Rebilly/ReDoc/commit/74a3193))
|
||||
* SideMenu to support items template as a parameter ([8a49fb3](https://github.com/Rebilly/ReDoc/commit/8a49fb3))
|
||||
|
||||
|
||||
<a name="1.13.0"></a>
|
||||
# 1.13.0 (2017-04-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix issue with loading https spec ([585b9cf](https://github.com/Rebilly/ReDoc/commit/585b9cf)), closes [#243](https://github.com/Rebilly/ReDoc/issues/243) (by Khoa Tran)
|
||||
* UL missing css ([303b49e](https://github.com/Rebilly/ReDoc/commit/303b49e)), closes [#248](https://github.com/Rebilly/ReDoc/issues/248)
|
||||
* don't show contact info if it is empty object ([6077cc6](https://github.com/Rebilly/ReDoc/commit/6077cc6))
|
||||
* code block formatting in markdown list ([a9cad19](https://github.com/Rebilly/ReDoc/commit/a9cad19)), closes [#242](https://github.com/Rebilly/ReDoc/issues/242)
|
||||
|
||||
### Features
|
||||
|
||||
* HTTP verbs badges in side menu ([92eec25](https://github.com/Rebilly/ReDoc/commit/92eec25)), closes [#61](https://github.com/Rebilly/ReDoc/issues/61)
|
||||
* HTTP verbs badges in search results ([61fd426](https://github.com/Rebilly/ReDoc/commit/61fd426))
|
||||
* new option [`no-auto-auth`](https://github.com/Rebilly/ReDoc#redoc-tag-attributes) to disable authentication section auto adding ([00b304a](https://github.com/Rebilly/ReDoc/commit/00b304a))
|
||||
|
||||
<a name="1.12.1"></a>
|
||||
# 1.12.1 (2017-04-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix: use replace state instead of pushState ([4f4e748](https://github.com/Rebilly/ReDoc/commit/4f4e748)), closes [#244](https://github.com/Rebilly/ReDoc/issues/244)
|
||||
|
||||
<a name="1.12.0"></a>
|
||||
# 1.12.0 (2017-04-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add safeguard for undefined ([aaac434](https://github.com/Rebilly/ReDoc/commit/aaac434)), closes [#236](https://github.com/Rebilly/ReDoc/issues/236)
|
||||
* view errors were not reported ([6aa3a7d](https://github.com/Rebilly/ReDoc/commit/6aa3a7d))
|
||||
|
||||
### Features
|
||||
|
||||
* Support x-examples vendor extension for requests (by [@brendo](https://github.com/brendo))
|
||||
|
||||
### Other
|
||||
|
||||
* Updated to Angular 4, bundle is a bit smaller now
|
||||
|
||||
<a name="1.11.0"></a>
|
||||
# 1.11.0 (2017-03-09)
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ ReDoc makes use of the following [vendor extensions](http://swagger.io/specifica
|
|||
* `expand-responses` - specify which responses to expand by default by response codes. Values should be passed as comma-separated list without spaces e.g. `expand-responses="200,201"`. Special value `"all"` expands all responses by default. Be careful: this option can slow-down documentation rendering time.
|
||||
* `required-props-first` - show required properties first ordered in the same order as in `required` array.
|
||||
* `no-auto-auth` - do not inject Authentication section automatically
|
||||
* `path-in-middle-panel` - show path link and HTTP verb in the middle panel instead of the right one
|
||||
|
||||
## Advanced usage
|
||||
Instead of adding `spec-url` attribute to the `<redoc>` element you can initialize ReDoc via globally exposed `Redoc` object:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="api-info-wrapper">
|
||||
<h1>{{info.title}} <span class="api-info-version">({{info.version}})</span></h1>
|
||||
<p>
|
||||
<p class="donwload-openapi" *ngIf="specUrl">
|
||||
Download OpenAPI (fka Swagger) specification:
|
||||
<a class="openapi-button" target="_blank" attr.href='{{specUrl}}'> Download </a>
|
||||
</p>
|
||||
|
|
|
@ -23,7 +23,7 @@ export class ApiInfo extends BaseComponent implements OnInit {
|
|||
|
||||
init() {
|
||||
this.info = this.componentSchema.info;
|
||||
this.specUrl = this.optionsService.options.specUrl;
|
||||
this.specUrl = this.specMgr.specUrl;
|
||||
if (!isNaN(parseInt(this.info.version.toString().substring(0, 1)))) {
|
||||
this.info.version = 'v' + this.info.version;
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<span><!--
|
||||
--><span class="operation-api-url-path">{{path}}</span><!--
|
||||
--></span>
|
||||
<svg class="expand-icon" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" viewBox="0 0 24 24" xml:space="preserve">
|
||||
<polygon fill="white" points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "/>
|
||||
</svg>
|
||||
</div>
|
||||
<svg class="expand-icon" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" viewBox="0 0 24 24" xml:space="preserve">
|
||||
<polygon fill="white" points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "/>
|
||||
</svg>
|
||||
<div class="servers-overlay">
|
||||
<div *ngFor="let server of servers" class="server-item">
|
||||
<div class="description" [innerHtml]="server.description | marked"></div>
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
border: 1px solid $border-color;
|
||||
background: $background-color;
|
||||
word-break: break-all;
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import { Component, ChangeDetectionStrategy, Input, OnInit, HostListener, HostBinding} from '@angular/core';
|
||||
import { BaseComponent, SpecManager } from '../base';
|
||||
import { OptionsService } from '../../services/';
|
||||
import { stripTrailingSlash } from '../../utils/';
|
||||
|
||||
export interface ServerInfo {
|
||||
description: string;
|
||||
|
@ -36,7 +37,7 @@ export class EndpointLink implements OnInit {
|
|||
if (servers) {
|
||||
this.servers = servers.map(({url, description}) => ({
|
||||
description,
|
||||
url: url.startsWith('//') ? `${this.specMgr.apiProtocol}:${url}` : url
|
||||
url: stripTrailingSlash(url.startsWith('//') ? `${this.specMgr.apiProtocol}:${url}` : url)
|
||||
}));
|
||||
} else {
|
||||
this.servers = [
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
<h2 class="operation-header sharable-header">
|
||||
<a class="share-link" href="#{{operation.anchor}}"></a>{{operation.summary}}
|
||||
</h2>
|
||||
<endpoint-link *ngIf="pathInMiddlePanel"
|
||||
[verb]="operation.verb" [path]="operation.path"> </endpoint-link>
|
||||
<div class="operation-tags" *ngIf="operation.info.tags.length">
|
||||
<a *ngFor="let tag of operation.info.tags" attr.href="#tag/{{tag}}"> {{tag}} </a>
|
||||
</div>
|
||||
|
@ -14,9 +16,9 @@
|
|||
<responses-list pointer="{{pointer}}/responses"> </responses-list>
|
||||
</div>
|
||||
<div class="operation-samples">
|
||||
<h4 class="operation-params-subheader">Definition</h4>
|
||||
|
||||
<endpoint-link [verb]="operation.verb" [path]="operation.path"> </endpoint-link>
|
||||
<endpoint-link *ngIf="!pathInMiddlePanel"
|
||||
[verb]="operation.verb" [path]="operation.path"> </endpoint-link>
|
||||
|
||||
<div>
|
||||
<request-samples [pointer]="pointer" [schemaPointer]="operation.bodyParam?._pointer">
|
||||
|
|
|
@ -57,6 +57,10 @@
|
|||
background: $samples-panel-bg-color;
|
||||
}
|
||||
|
||||
.operation-samples pre {
|
||||
color: $sample-panel-color;
|
||||
}
|
||||
|
||||
.operation-samples header,
|
||||
.operation-samples > h5 {
|
||||
color: $sample-panel-headers-color;
|
||||
|
@ -103,3 +107,28 @@
|
|||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.operation-content /deep/ endpoint-link {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.operation-endpoint[class] {
|
||||
padding: 5px 30px 5px 5px;
|
||||
border: 0;
|
||||
border-bottom: 1px solid $border-color;
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
.operation-api-url-path {
|
||||
color: $black;
|
||||
}
|
||||
|
||||
.expand-icon {
|
||||
top: 8px;
|
||||
background-color: $border-color;
|
||||
}
|
||||
|
||||
.servers-overlay {
|
||||
border: 1px solid $border-color;
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,15 @@ export class Operation extends BaseComponent implements OnInit {
|
|||
@HostBinding('attr.operation-id') operationId;
|
||||
|
||||
operation: OperationInfo;
|
||||
pathInMiddlePanel: boolean;
|
||||
|
||||
constructor(
|
||||
specMgr:SpecManager,
|
||||
private optionsService: OptionsService,
|
||||
private menu: MenuService) {
|
||||
super(specMgr);
|
||||
|
||||
this.pathInMiddlePanel = optionsService.options.pathInMiddlePanel;
|
||||
}
|
||||
|
||||
init() {
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
}
|
||||
|
||||
side-menu {
|
||||
overflow-y: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
[sticky-sidebar] {
|
||||
|
@ -264,6 +264,7 @@ footer {
|
|||
|
||||
code {
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
|
||||
&:before, &:after {
|
||||
content: none;
|
||||
|
|
|
@ -62,7 +62,7 @@ input {
|
|||
}
|
||||
|
||||
li.menu-item-depth-1 {
|
||||
color: #0033a0;
|
||||
color: $primary-color;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
-o-transition: all .15s ease-in-out;
|
||||
transition: all .15s ease-in-out;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: $side-menu-item-vpadding*2.5 $side-menu-item-hpadding;
|
||||
|
||||
&[hidden] {
|
||||
|
@ -33,11 +34,6 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
.menu-item:hover,
|
||||
.menu-item.active {
|
||||
//background: darken($side-menu-active-bg-color, 6%);
|
||||
}
|
||||
|
||||
.menu-subitems {
|
||||
margin: 0;
|
||||
font-size: 0.929em;
|
||||
|
|
|
@ -4,8 +4,14 @@
|
|||
<span class="selected-endpoint">{{activeItemCaption}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div #desktop id="resources-nav">
|
||||
<ng-template #default>
|
||||
<side-menu-items [items]="menuItems" (activate)="activateAndScroll($event)"></side-menu-items>
|
||||
</ng-template>
|
||||
|
||||
<div #desktop id="resources-nav" perfect-scrollbar>
|
||||
<ul class="menu-root">
|
||||
<side-menu-items [items]="menuItems" (activate)="activateAndScroll($event)"></side-menu-items>
|
||||
<div *ngIf="itemsTemplate; else default">
|
||||
<ng-container *ngTemplateOutlet="itemsTemplate; context: this"></ng-container>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
$mobile-menu-compact-breakpoint: 550px;
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#resources-nav {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
ul.menu-root {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@ -35,6 +39,10 @@ ul.menu-root {
|
|||
}
|
||||
|
||||
@media (max-width: $side-menu-mobile-breakpoint) {
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mobile-nav {
|
||||
display: block;
|
||||
}
|
||||
|
|
|
@ -6,12 +6,14 @@ import { Component,
|
|||
Output,
|
||||
ElementRef,
|
||||
ChangeDetectorRef,
|
||||
ViewChild,
|
||||
OnInit,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
|
||||
import { trigger, state, animate, transition, style } from '@angular/core';
|
||||
import { ScrollService, MenuService, OptionsService, MenuItem } from '../../services/';
|
||||
import { PerfectScrollbar } from '../../shared/components';
|
||||
import { BrowserDomAdapter as DOM } from '../../utils/browser-adapter';
|
||||
|
||||
const global = window;
|
||||
|
@ -50,6 +52,8 @@ export class SideMenu implements OnInit, OnDestroy {
|
|||
activeCatCaption: string;
|
||||
activeItemCaption: string;
|
||||
menuItems: Array<MenuItem>;
|
||||
@Input() itemsTemplate;
|
||||
@ViewChild(PerfectScrollbar) PS:PerfectScrollbar;
|
||||
|
||||
private options: any;
|
||||
private $element: any;
|
||||
|
@ -57,6 +61,9 @@ export class SideMenu implements OnInit, OnDestroy {
|
|||
private $resourcesNav: any;
|
||||
private $scrollParent: any;
|
||||
|
||||
private changedActiveSubscription;
|
||||
private changedSubscription;
|
||||
|
||||
constructor(
|
||||
elementRef:ElementRef,
|
||||
private scrollService:ScrollService,
|
||||
|
@ -71,8 +78,10 @@ export class SideMenu implements OnInit, OnDestroy {
|
|||
|
||||
this.options = optionsService.options;
|
||||
|
||||
this.menuService.changedActiveItem.subscribe((evt) => this.changed(evt));
|
||||
this.menuService.changed.subscribe((evt) => this.detectorRef.detectChanges());
|
||||
this.changedActiveSubscription = this.menuService.changedActiveItem.subscribe((evt) => this.changed(evt));
|
||||
this.changedSubscription = this.menuService.changed.subscribe((evt) => {
|
||||
this.update();
|
||||
});
|
||||
}
|
||||
|
||||
changed(item) {
|
||||
|
@ -89,11 +98,16 @@ export class SideMenu implements OnInit, OnDestroy {
|
|||
this.activeItemCaption = '';
|
||||
}
|
||||
|
||||
//safari doesn't update bindings if not run changeDetector manually :(
|
||||
this.detectorRef.detectChanges();
|
||||
// safari doesn't update bindings if not run changeDetector manually :(
|
||||
this.update();
|
||||
this.scrollActiveIntoView();
|
||||
}
|
||||
|
||||
update() {
|
||||
this.detectorRef.detectChanges();
|
||||
this.PS && this.PS.update();
|
||||
}
|
||||
|
||||
scrollActiveIntoView() {
|
||||
let $item = this.$element.querySelector('li.active, label.active');
|
||||
if ($item) $item.scrollIntoViewIfNeeded();
|
||||
|
@ -141,6 +155,8 @@ export class SideMenu implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
destroy() {
|
||||
this.changedActiveSubscription.unsubscribe();
|
||||
this.changedSubscription.unsubscribe();
|
||||
this.scrollService.unbind();
|
||||
this.menuService.destroy();
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import { NgModule, ErrorHandler, APP_ID } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { SpecManager } from './utils/spec-manager';
|
||||
|
||||
import { Redoc, SecurityDefinitions, Operation, REDOC_DIRECTIVES } from './components/index';
|
||||
import { REDOC_COMMON_DIRECTIVES, DynamicNg2Wrapper } from './shared/components/index';
|
||||
import { REDOC_COMMON_DIRECTIVES, DynamicNg2Wrapper, DropDown } from './shared/components/index';
|
||||
import { REDOC_PIPES } from './utils/pipes';
|
||||
import { CustomErrorHandler } from './utils/'
|
||||
import { LazyTasksService } from './shared/components/LazyFor/lazy-for';
|
||||
|
||||
import {
|
||||
OptionsService,
|
||||
Options,
|
||||
MenuService,
|
||||
ScrollService,
|
||||
Hash,
|
||||
|
@ -19,10 +22,9 @@ import {
|
|||
Marker,
|
||||
SchemaHelper,
|
||||
SearchService,
|
||||
MenuItem,
|
||||
COMPONENT_PARSER_ALLOWED } from './services/';
|
||||
|
||||
import { SpecManager } from './utils/spec-manager';
|
||||
|
||||
@NgModule({
|
||||
imports: [ CommonModule ],
|
||||
declarations: [ REDOC_DIRECTIVES, REDOC_COMMON_DIRECTIVES, REDOC_PIPES ],
|
||||
|
@ -49,6 +51,7 @@ export { Redoc, SpecManager, ScrollService,
|
|||
Hash,
|
||||
WarningsService,
|
||||
OptionsService,
|
||||
Options,
|
||||
AppStateService,
|
||||
ComponentParser,
|
||||
ContentProjector,
|
||||
|
@ -56,4 +59,5 @@ MenuService,
|
|||
SearchService,
|
||||
SchemaHelper,
|
||||
LazyTasksService,
|
||||
Marker };
|
||||
MenuItem,
|
||||
Marker, DropDown };
|
||||
|
|
|
@ -30,7 +30,7 @@ export class Hash {
|
|||
update(hash: string|null, rewriteHistory:boolean = false) {
|
||||
if (hash == undefined) return;
|
||||
if (rewriteHistory) {
|
||||
window.history.replaceState(null, '', '#' + hash);
|
||||
window.history.replaceState(null, '', window.location.href.split('#')[0] + '#' + hash);
|
||||
return;
|
||||
}
|
||||
this.noEmit = true;
|
||||
|
|
|
@ -104,7 +104,7 @@ export class MenuService {
|
|||
|
||||
// check if previous items§ can be enabled
|
||||
let prevItem = this.flatItems[idx -= 1];
|
||||
while(prevItem && (!prevItem.metadata || !prevItem.items)) {
|
||||
while(prevItem && (!prevItem.metadata || prevItem.metadata.type === 'heading' || !prevItem.items)) {
|
||||
prevItem.ready = true;
|
||||
prevItem = this.flatItems[idx -= 1];
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ export class MenuService {
|
|||
// We only need to go up the chain for operations that
|
||||
// might have multiple tags. For headers/subheaders
|
||||
// we need to siply early terminate.
|
||||
if (!currentItem.metadata) {
|
||||
if (!currentItem.metadata || currentItem.metadata.type === 'heading') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +291,10 @@ export class MenuService {
|
|||
let item = {
|
||||
name: heading.title,
|
||||
id: id,
|
||||
items: null
|
||||
items: null,
|
||||
metadata: {
|
||||
type: 'heading'
|
||||
}
|
||||
};
|
||||
item.items = this.getMarkdownSubheaders(item, heading);
|
||||
|
||||
|
@ -309,7 +312,10 @@ export class MenuService {
|
|||
let subItem = {
|
||||
name: heading.title,
|
||||
id: id,
|
||||
parent: parent
|
||||
parent: parent,
|
||||
metadata: {
|
||||
type: 'heading'
|
||||
}
|
||||
};
|
||||
res.push(subItem);
|
||||
});
|
||||
|
|
|
@ -17,7 +17,8 @@ const OPTION_NAMES = new Set([
|
|||
'lazyRendering',
|
||||
'expandResponses',
|
||||
'requiredPropsFirst',
|
||||
'noAutoAuth'
|
||||
'noAutoAuth',
|
||||
'pathInMiddlePanel',
|
||||
]);
|
||||
|
||||
export interface Options {
|
||||
|
@ -31,6 +32,7 @@ export interface Options {
|
|||
$scrollParent?: HTMLElement | Window;
|
||||
requiredPropsFirst?: boolean;
|
||||
noAutoAuth?: boolean;
|
||||
pathInMiddlePanel?: boolean;
|
||||
spec?: any;
|
||||
}
|
||||
|
||||
|
@ -98,6 +100,7 @@ export class OptionsService {
|
|||
if (isString(this._options.lazyRendering)) this._options.lazyRendering = true;
|
||||
if (isString(this._options.requiredPropsFirst)) this._options.requiredPropsFirst = true;
|
||||
if (isString(this._options.noAutoAuth)) this._options.noAutoAuth = true;
|
||||
if (isString(this._options.pathInMiddlePanel)) this._options.pathInMiddlePanel = true;
|
||||
if (isString(this._options.expandResponses)) {
|
||||
let str = this._options.expandResponses as string;
|
||||
if (str === 'all') return;
|
||||
|
|
37
lib/shared/components/PerfectScrollbar/perfect-scrollbar.ts
Normal file
37
lib/shared/components/PerfectScrollbar/perfect-scrollbar.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
'use strict';
|
||||
|
||||
import 'perfect-scrollbar/dist/css/perfect-scrollbar.css';
|
||||
|
||||
import { Directive, ElementRef, Input, OnInit, OnDestroy } from '@angular/core';
|
||||
import { BrowserDomAdapter as DOM } from '../../../utils/browser-adapter';
|
||||
|
||||
import * as PS from 'perfect-scrollbar';
|
||||
|
||||
@Directive({
|
||||
selector: '[perfect-scrollbar]'
|
||||
})
|
||||
export class PerfectScrollbar implements OnInit, OnDestroy {
|
||||
$element: any;
|
||||
subscription: any;
|
||||
|
||||
constructor(elementRef:ElementRef) {
|
||||
this.$element = elementRef.nativeElement;
|
||||
}
|
||||
|
||||
update() {
|
||||
PS.update(this.$element);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
requestAnimationFrame(() => PS.initialize(this.$element, {
|
||||
wheelSpeed: 2,
|
||||
wheelPropagation: false,
|
||||
minScrollbarLength: 20,
|
||||
suppressScrollX: true
|
||||
}));
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
PS.destroy(this.$element);
|
||||
}
|
||||
}
|
|
@ -7,10 +7,11 @@ import { CopyButton } from './CopyButton/copy-button.directive';
|
|||
import { SelectOnClick } from './SelectOnClick/select-on-click.directive';
|
||||
import { DynamicNg2Viewer, DynamicNg2Wrapper } from './DynamicNg2Viewer/dynamic-ng2-viewer.component';
|
||||
import { LazyFor, LazyTasksService, LazyTasksServiceSync } from './LazyFor/lazy-for';
|
||||
import { PerfectScrollbar } from './PerfectScrollbar/perfect-scrollbar';
|
||||
|
||||
export const REDOC_COMMON_DIRECTIVES = [
|
||||
DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper, LazyFor
|
||||
PerfectScrollbar, DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper, LazyFor
|
||||
];
|
||||
|
||||
export { DropDown, StickySidebar, Tabs, Tab, Zippy, CopyButton, SelectOnClick, DynamicNg2Viewer, DynamicNg2Wrapper, LazyFor }
|
||||
export { LazyTasksService, LazyTasksServiceSync }
|
||||
export { LazyTasksService, LazyTasksServiceSync, PerfectScrollbar }
|
||||
|
|
|
@ -20,6 +20,10 @@ export function isBlank(obj: any): boolean {
|
|||
return obj == undefined;
|
||||
}
|
||||
|
||||
export function stripTrailingSlash(path:string):string {
|
||||
return path.endsWith('/') ? path.substring(0, path.length - 1) : path;
|
||||
}
|
||||
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
export function groupBy<T>(array: T[], key:string):StringMap<T[]> {
|
||||
return array.reduce<StringMap<T[]>>(function(res, value) {
|
||||
|
@ -119,7 +123,7 @@ export function isJsonLike(contentType: string): boolean {
|
|||
return contentType.search(/json/i) !== -1;
|
||||
}
|
||||
|
||||
export function getJsonLike(object: object) {
|
||||
export function getJsonLike(object: Object) {
|
||||
const jsonLikeKeys = Object.keys(object).filter(isJsonLike);
|
||||
|
||||
if (!jsonLikeKeys.length) {
|
||||
|
|
|
@ -23,6 +23,7 @@ const md = new Remarkable({
|
|||
export interface MarkdownHeading {
|
||||
title?: string;
|
||||
id: string;
|
||||
slug?: string;
|
||||
content?: string;
|
||||
children?: StringMap<MarkdownHeading>;
|
||||
}
|
||||
|
@ -52,12 +53,14 @@ export class MdRenderer {
|
|||
}
|
||||
|
||||
saveHeading(title: string, parent:MarkdownHeading = {id:null, children: this.headings}) :MarkdownHeading {
|
||||
let id = slugify(title);
|
||||
let slug = slugify(title);
|
||||
let id = slug;
|
||||
if (parent && parent.id) id = `${parent.id}/${id}`;
|
||||
parent.children = parent.children || {};
|
||||
parent.children[id] = {
|
||||
title,
|
||||
id
|
||||
id,
|
||||
slug
|
||||
};
|
||||
return parent.children[id];
|
||||
}
|
||||
|
@ -110,12 +113,14 @@ export class MdRenderer {
|
|||
this.currentTopHeading = this.saveHeading(content);;
|
||||
let id = this.currentTopHeading.id;
|
||||
return `<h${tokens[idx].hLevel} section="section/${id}">` +
|
||||
`<a class="share-link" href="#section/${id}"></a>`;
|
||||
`<a class="share-link" href="#section/${id}"></a>` +
|
||||
`<a name="${id.toLowerCase()}"></a>`;
|
||||
} else if (tokens[idx].hLevel === 2 ) {
|
||||
let heading = this.saveHeading(content, this.currentTopHeading);
|
||||
let contentSlug = `${heading.id}`;
|
||||
return `<h${tokens[idx].hLevel} section="section/${heading.id}">` +
|
||||
`<a class="share-link" href="#section/${contentSlug}"></a>`;
|
||||
`<a class="share-link" href="#section/${contentSlug}"></a>` +
|
||||
`<a name="${heading.slug.toLowerCase()}"></a>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ export class SpecManager {
|
|||
public basePath: string;
|
||||
|
||||
public spec = new BehaviorSubject<any|null>(null);
|
||||
public _specUrl: string;
|
||||
public specUrl: string;
|
||||
private parser: any;
|
||||
private options: Options;
|
||||
|
||||
|
@ -46,7 +46,7 @@ export class SpecManager {
|
|||
this.parser.bundle(urlOrObject, {http: {withCredentials: false}})
|
||||
.then(schema => {
|
||||
if (typeof urlOrObject === 'string') {
|
||||
this._specUrl = urlOrObject;
|
||||
this.specUrl = urlOrObject;
|
||||
}
|
||||
this._schema = snapshot(schema);
|
||||
try {
|
||||
|
@ -64,7 +64,7 @@ export class SpecManager {
|
|||
|
||||
/* calculate common used values */
|
||||
init() {
|
||||
let urlParts = this._specUrl ? urlParse(urlResolve(window.location.href, this._specUrl)) : {};
|
||||
let urlParts = this.specUrl ? urlParse(urlResolve(window.location.href, this.specUrl)) : {};
|
||||
let schemes = this._schema.schemes;
|
||||
let protocol;
|
||||
if (!schemes || !schemes.length) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "redoc",
|
||||
"description": "Swagger-generated API Reference Documentation",
|
||||
"version": "1.13.0",
|
||||
"version": "1.14.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/Rebilly/ReDoc"
|
||||
|
@ -124,5 +124,7 @@
|
|||
"webpack-merge": "^4.1.0",
|
||||
"zone.js": "^0.8.5"
|
||||
},
|
||||
"dependencies": {}
|
||||
"dependencies": {
|
||||
"perfect-scrollbar": "^0.6.16"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,21 +46,21 @@ describe('Utils', () => {
|
|||
|
||||
it('should substitute api scheme when spec schemes are undefined', () => {
|
||||
specMgr._schema.schemes = undefined;
|
||||
specMgr._specUrl = 'https://petstore.swagger.io/v2';
|
||||
specMgr.specUrl = 'https://petstore.swagger.io/v2';
|
||||
specMgr.init();
|
||||
specMgr.apiUrl.should.be.equal('https://petstore.swagger.io/v2');
|
||||
});
|
||||
|
||||
it('should substitute api host when spec host is undefined', () => {
|
||||
specMgr._schema.host = undefined;
|
||||
specMgr._specUrl = 'http://petstore.swagger.io/v2';
|
||||
specMgr.specUrl = 'http://petstore.swagger.io/v2';
|
||||
specMgr.init();
|
||||
specMgr.apiUrl.should.be.equal('http://petstore.swagger.io/v2');
|
||||
});
|
||||
|
||||
it('should use empty basePath when basePath is not present', () => {
|
||||
specMgr._schema.basePath = undefined;
|
||||
specMgr._specUrl = 'https://petstore.swagger.io';
|
||||
specMgr.specUrl = 'https://petstore.swagger.io';
|
||||
specMgr.init();
|
||||
specMgr.basePath.should.be.equal('');
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
"outDir": "dist",
|
||||
"lib": [
|
||||
"DOM", "ES2016", "DOM.Iterable"
|
||||
"dom", "es2016", "dom.iterable"
|
||||
],
|
||||
"noEmitHelpers": false
|
||||
},
|
||||
|
|
|
@ -3782,6 +3782,10 @@ pend@~1.2.0:
|
|||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
|
||||
perfect-scrollbar@^0.6.16:
|
||||
version "0.6.16"
|
||||
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-0.6.16.tgz#b1d61a5245cf3962bb9a8407a3fc669d923212fc"
|
||||
|
||||
phantomjs-prebuilt@^2.1.7:
|
||||
version "2.1.14"
|
||||
resolved "https://registry.yarnpkg.com/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.14.tgz#d53d311fcfb7d1d08ddb24014558f1188c516da0"
|
||||
|
|
Loading…
Reference in New Issue
Block a user