Merge commit '00703e0ed0879d5b7fe3707c3f5a883551bacfef' into releases

This commit is contained in:
RedocBot 2016-12-02 10:34:06 +00:00 committed by travis@localhost
commit 6e69bff71c
34 changed files with 94 additions and 112 deletions

View File

@ -1,3 +1,17 @@
# 1.6.0 (2016-11-30)
### Bug fixes
* Update webpack to the latest beta ([#143](https://github.com/Rebilly/ReDoc/issues/143))
* Fix read-only fields appear in request samples ([#142](https://github.com/Rebilly/ReDoc/issues/142))
* A few more minor UI improvemnts
### Features/Improvements
* Major performance optimization with new option `lazy-rendering`
To enable use `<redoc>` tag parameter: `<redoc spec-url="..." lazy-rendering></redoc>`.
In this mode ReDoc shows initial screen ASAP and then renders the rest operations asynchronously while showing progress bar on the top. Check out [the demo](//rebilly.github.io/ReDoc) for the example.
* Enable cors-proxy for demo
* README: Add button link to yeoman-generator
# 1.5.2 (2016-11-28)
### Bug fixes
* Fix crashing on array without items ([#104](https://github.com/Rebilly/ReDoc/issues/104))

View File

@ -18,19 +18,24 @@
## Features
- Extremely easy deployment
- Its free and open-source project under MIT license
- The widest OpenAPI features support (yes, it supports even discriminator)
- Neat documentation for nested objects
- The widest OpenAPI features support (yes, it supports even `discriminator`)
- Neat **interactive** documentation for nested objects
<img src="http://i.imgur.com/260gaV4.png" width="500">
- Code samples support (via vendor extension)
- Responsive three-panel design with menu/scrolling synchronization
- Integrate API introduction into side menu - ReDoc takes advantage of markdown headings from OpenAPI description field. It pulls them into side menu and also supports deep linking.
## Roadmap
- [ ] docs pre-rendering (performance and SEO)
- [ ] ability to simple customization
- [x] performance optimizations
- [ ] better navigation (menu improvements + search)
- [ ] ability to simple branding/styling
- [ ] built-in API Console
- [ ] docs pre-rendering (performance and SEO)
## Releases
We host latest and all the previous ReDoc releases on GitHub Pages-based **CDN**:
We host the latest and all the previous ReDoc releases on GitHub Pages-based **CDN**:
- particular release, e.g. `v1.2.0`: https://rebilly.github.io/ReDoc/releases/v1.2.0/redoc.min.js
- `v1.x.x` release: https://rebilly.github.io/ReDoc/releases/v1.x.x/redoc.min.js
- `latest` release: https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js **[not for production]**

View File

@ -10,7 +10,6 @@ import {
TestBed
} from '@angular/core/testing';
import { ApiInfo } from './api-info';
import { SpecManager } from '../../utils/spec-manager';
describe('Redoc components', () => {

View File

@ -1,7 +1,7 @@
'use strict';
import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
import { SpecManager, BaseComponent } from '../base';
import { OptionsService, MenuService } from '../../services/index';
import { OptionsService } from '../../services/index';
@Component({
selector: 'api-info',

View File

@ -9,7 +9,6 @@ import {
TestBed
} from '@angular/core/testing';
import { ApiLogo } from './api-logo';
import { SpecManager } from '../../utils/spec-manager';

View File

@ -20,9 +20,6 @@ describe('Redoc components', () => {
let component;
let fixture;
beforeEach(inject([TestBed], (tcb) => {
}));
beforeEach(() => {
fixture = TestBed.createComponent(TestAppComponent);
let debugEl = getChildDebugElement(fixture.debugElement, 'json-schema-lazy');

View File

@ -67,7 +67,7 @@ export class JsonSchemaLazy implements OnDestroy, AfterViewInit {
this._loadAfterSelf();
return;
}
//insertAfter($element.cloneNode(true), this.elementRef.nativeElement);
insertAfter($element.cloneNode(true), this.elementRef.nativeElement);
this.loaded = true;
} else {
cache[this.pointer] = this._loadAfterSelf();

View File

@ -8,8 +8,6 @@ import {
import { getChildDebugElement } from '../../../tests/helpers';
import { JsonSchema } from './json-schema';
import { SpecManager } from '../../utils/spec-manager';;
describe('Redoc components', () => {

View File

@ -120,7 +120,7 @@ export class JsonSchema extends BaseComponent implements OnInit {
}
}
trackByName(index: number, item: any): number {
trackByName(_: number, item: any): number {
return item.name + (item._pointer || '');
}

View File

@ -1,9 +1,5 @@
'use strict';
import { Input, HostBinding, Component, OnInit, ChangeDetectionStrategy, ElementRef, ChangeDetectorRef } from '@angular/core';
import JsonPointer from '../../utils/JsonPointer';
import { BaseComponent, SpecManager } from '../base';
import { SchemaHelper } from '../../services/schema-helper.service';
import { OptionsService, AppStateService } from '../../services/';
import { Input, HostBinding, Component, OnChanges } from '@angular/core';
@Component({
selector: 'loading-bar',
@ -32,10 +28,9 @@ import { OptionsService, AppStateService } from '../../services/';
background-color: #5f7fc3;
transition: right 0.2s linear;
}
`],
//changeDetection: ChangeDetectionStrategy.OnPush
`]
})
export class LoadingBar {
export class LoadingBar implements OnChanges {
@Input() progress:number = 0;
@HostBinding('style.display') display = 'block';

View File

@ -1,9 +1,9 @@
'use strict';
import { Input, Component, OnInit, ChangeDetectionStrategy, ElementRef, ChangeDetectorRef } from '@angular/core';
import { Input, Component, OnInit, ChangeDetectionStrategy, ElementRef } from '@angular/core';
import JsonPointer from '../../utils/JsonPointer';
import { BaseComponent, SpecManager } from '../base';
import { SchemaHelper } from '../../services/schema-helper.service';
import { OptionsService, AppStateService } from '../../services/';
import { OptionsService } from '../../services/';
@Component({
selector: 'method',
@ -20,8 +20,7 @@ export class Method extends BaseComponent implements OnInit {
method:any;
constructor(specMgr:SpecManager, private optionsService: OptionsService, private chDetector: ChangeDetectorRef,
private appState: AppStateService, private el: ElementRef) {
constructor(specMgr:SpecManager, private optionsService: OptionsService, private el: ElementRef) {
super(specMgr);
}

View File

@ -30,11 +30,7 @@ export class MethodsList extends BaseComponent implements OnInit {
});
}
trackByPointer(idx, el) {
return el.pointer;
}
trackByTagName(idx, el) {
trackByTagName(_, el) {
return el.name;
}

View File

@ -1,12 +1,10 @@
'use strict';
import { ElementRef,
ComponentRef,
ChangeDetectorRef,
Input,
Component,
OnInit,
ChangeDetectionStrategy,
HostBinding
} from '@angular/core';
@ -18,7 +16,6 @@ import * as detectScollParent from 'scrollparent';
import { SpecManager } from '../../utils/spec-manager';
import { OptionsService, Hash, AppStateService, SchemaHelper } from '../../services/index';
import { LazyTasksService } from '../../shared/components/LazyFor/lazy-for';
import { CustomErrorHandler } from '../../utils/';
@Component({
selector: 'redoc',
@ -112,16 +109,12 @@ export class Redoc extends BaseComponent implements OnInit {
this.appState.error.subscribe(_err => {
if (!_err) return;
if (this.specLoading) {
this.specLoaded = true;
this.hideLoadingAnimation();
}
this.appState.stopLoading();
if (this.loadingProgress === 100) return;
this.error = _err;
this.changeDetector.markForCheck();
setTimeout(() => {
this.changeDetector.detectChanges()
});
})
if (this.specUrl) {
this.options.specUrl = this.specUrl;

View File

@ -63,7 +63,7 @@ export class ResponsesList extends BaseComponent implements OnInit {
this.responses = responses;
}
trackByCode(idx, el) {
trackByCode(_, el) {
return el.code;
}

View File

@ -1,5 +1,5 @@
'use strict';
import { Component, ChangeDetectionStrategy, OnInit, HostListener } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
import { SpecManager, BaseComponent } from '../base';
import { ComponentParser } from '../../services/component-parser.service';

View File

@ -11,7 +11,7 @@
<label class="menu-cat-header" (click)="activateAndScroll(idx, -1)" [hidden]="cat.headless"
[ngClass]="{active: cat.active, disabled: !cat.ready }"> {{cat.name}}</label>
<ul class="menu-subitems" [@itemAnimation]="cat.active ? 'expanded' : 'collapsed'">
<ul *ngIf="cat.methods.length" class="menu-subitems" [@itemAnimation]="cat.active ? 'expanded' : 'collapsed'">
<li *ngFor="let method of cat.methods; trackBy:summary; let methIdx = index"
[ngClass]="{active: method.active, disabled: !method.ready}"
(click)="activateAndScroll(idx, methIdx)">

View File

@ -5,7 +5,7 @@ import { Component, ElementRef, ChangeDetectorRef, OnInit } from '@angular/core'
//import { global } from '@angular/core/src/facade/lang';
import { trigger, state, animate, transition, style } from '@angular/core';
import { BaseComponent, SpecManager } from '../base';
import { ScrollService, Hash, MenuService, OptionsService } from '../../services/index';
import { ScrollService, MenuService, OptionsService } from '../../services/index';
import { BrowserDomAdapter as DOM } from '../../utils/browser-adapter';
import { MenuCategory } from '../../services/schema-helper.service';
@ -41,7 +41,7 @@ export class SideMenu extends BaseComponent implements OnInit {
private firstChange = true;
constructor(specMgr:SpecManager, elementRef:ElementRef,
private scrollService:ScrollService, private menuService:MenuService, private hash:Hash,
private scrollService:ScrollService, private menuService:MenuService,
optionsService:OptionsService, private detectorRef:ChangeDetectorRef) {
super(specMgr);
this.$element = elementRef.nativeElement;

View File

@ -3,7 +3,6 @@ import './components/Redoc/redoc-initial-styles.css';
import { enableProdMode } from '@angular/core';
import { Redoc } from './components/index';
import { SpecManager } from './utils/spec-manager';
import { BrowserDomAdapter as DOM } from './utils/browser-adapter';
import { disableDebugTools } from '@angular/platform-browser';

View File

@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
import { Redoc, SecurityDefinitions, Method, REDOC_DIRECTIVES } from './components/index';
import { REDOC_COMMON_DIRECTIVES, DynamicNg2Wrapper } from './shared/components/index';
import { REDOC_PIPES, KeysPipe } from './utils/pipes';
import { REDOC_PIPES } from './utils/pipes';
import { CustomErrorHandler } from './utils/'
import { LazyTasksService } from './shared/components/LazyFor/lazy-for';

View File

@ -1,15 +1,15 @@
'use strict';
import { Injectable, NgZone } from '@angular/core';
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Injector } from '@angular/core';
@Injectable()
export class AppStateService {
samplesLanguage = new Subject<string>();
error = new BehaviorSubject<any>(null);
loading = new Subject<boolean>();
initialized = new BehaviorSubject<any>(false);
startLoading() {
this.loading.next(true);
@ -18,7 +18,4 @@ export class AppStateService {
stopLoading() {
this.loading.next(false);
}
constructor(private injector: Injector, private zone: NgZone) {
}
}

View File

@ -64,7 +64,7 @@ export class ComponentParser {
}
createComponentByHtml(htmlTag: string, injector:Injector):ComponentRef<any>| null {
let {componentType, options} = this._parseHtml(htmlTag);
let { componentType } = this._parseHtml(htmlTag);
if (!componentType) return null;
let factory = this.resolver.resolveComponentFactory(componentType);

View File

@ -29,13 +29,13 @@ export class ContentProjector {
let parentCompRef = parentView.createComponent(componentFactory, null, contextInjector, [projectedNodes]);
// using private property to get AppElement instance
let appElement = (<any>parentView)._element;
appElement.nestedViews = appElement.nestedViews || [];
let viewContainer = (<any>parentView)._element;
viewContainer.nestedViews = viewContainer.nestedViews || [];
for (let i=0; i < componentRefs.length; i++) {
let compRef = componentRefs[i];
appElement.nestedViews.push((<any>compRef.hostView).internalView);
// attach appElement to parentView change detector
(<any>compRef.hostView).internalView.addToContentChildren(appElement);
// attach view to viewContainer change detector
viewContainer.nestedViews.push((<any>compRef.hostView).internalView);
(<any>compRef.hostView).internalView.viewContainer = viewContainer;
}
return parentCompRef;
}

View File

@ -52,7 +52,7 @@ export class OptionsService {
//camelCasify
.map(k => ({
attrName: k,
name: k.replace(/-(.)/g, (m, $1) => $1.toUpperCase())
name: k.replace(/-(.)/g, (_, $1) => $1.toUpperCase())
})
)
.filter(option => OPTION_NAMES.has(option.name))

View File

@ -64,7 +64,7 @@ const injectors = {
},
discriminator: {
check: (propertySchema) => propertySchema.discriminator || propertySchema['x-extendedDiscriminator'],
inject: (injectTo, propertySchema = injectTo, pointer) => {
inject: (injectTo, propertySchema = injectTo) => {
injectTo.discriminator = propertySchema.discriminator;
injectTo['x-extendedDiscriminator'] = propertySchema['x-extendedDiscriminator'];
}
@ -182,7 +182,7 @@ const injectors = {
},
file: {
check: propertySchema => (propertySchema.type === 'file'),
inject: (injectTo, propertySchema = injectTo, propPointer, hostPointer) => {
inject: (injectTo, propertySchema = injectTo, _, hostPointer) => {
injectTo.isFile = true;
let parentPtr;
if (propertySchema.in === 'formData') {
@ -230,7 +230,7 @@ export class SchemaHelper {
schema.required.forEach(prop => requiredMap[prop] = true);
}
let props = schema.properties && Object.keys(schema.properties).map((propName, idx) => {
let props = schema.properties && Object.keys(schema.properties).map(propName => {
let propertySchema = Object.assign({}, schema.properties[propName]);
let propPointer = propertySchema._pointer ||
JsonPointer.join(pointer, ['properties', propName]);

View File

@ -20,7 +20,7 @@ interface Schema {
@Injectable()
export class SchemaNormalizer {
_dereferencer:SchemaDereferencer;
constructor(private _schema:any) {
constructor(_schema:any) {
this._dereferencer = new SchemaDereferencer(_schema, this);
}
normalize(schema, ptr, opts:any ={}) {

View File

@ -19,7 +19,7 @@ export class ScrollService {
private _cancel:any;
private _savedPosition:number;
private _stickElement: HTMLElement;
constructor(private optionsService:OptionsService) {
constructor(optionsService:OptionsService) {
this.scrollYOffset = () => optionsService.options.scrollYOffset();
this.$scrollParent = optionsService.options.$scrollParent || window;
this.scroll = new EventEmitter();

View File

@ -2,8 +2,6 @@
import {
Component,
EventEmitter,
Output,
Input,
OnInit,
ViewContainerRef,

View File

@ -6,8 +6,7 @@ import {
TemplateRef,
ChangeDetectorRef,
ViewContainerRef,
Injectable,
NgZone
Injectable
} from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@ -36,7 +35,7 @@ export class LazyTasksService {
public loadProgress = new BehaviorSubject<number>(0);
public allSync = false;
constructor(public optionsService: OptionsService, private zone: NgZone) {
constructor(public optionsService: OptionsService) {
}
get empty() {
@ -117,8 +116,8 @@ export class LazyTasksService {
@Injectable()
export class LazyTasksServiceSync extends LazyTasksService {
constructor(optionsService: OptionsService, zone: NgZone) {
super(optionsService, zone);
constructor(optionsService: OptionsService) {
super(optionsService);
this.allSync = true;
}
}
@ -132,7 +131,6 @@ export class LazyFor {
prevIdx = null;
private _viewRef;
constructor(
public _template: TemplateRef<LazyForRow>,
public cdr: ChangeDetectorRef,
@ -152,7 +150,7 @@ export class LazyFor {
if (sync) {
return Promise.resolve();
}
return new Promise<void>((resolve, reject) => {
return new Promise<void>(resolve => {
requestAnimationFrame(() => {
this.scroll.saveScroll();

View File

@ -18,12 +18,12 @@ describe('Common components', () => {
let component;
let fixture;
beforeEach(inject([TestBed], (tcb) => {
beforeEach(() => {
fixture = TestBed.createComponent(TestApp);
let debugEl = getChildDebugElementByType(fixture.debugElement, StickySidebar);
component = debugEl.injector.get(StickySidebar);
}));
});
it('should init component', () => {

View File

@ -22,14 +22,14 @@ describe('Common components', () => {
let fixture;
let hostComponent;
beforeEach(inject([TestBed], (tcb) => {
beforeEach(() => {
fixture = TestBed.createComponent(TestApp);
hostComponent = fixture.debugElement.componentInstance;
debugEl = getChildDebugElement(fixture.debugElement, 'tabs');
childDebugEls = getChildDebugElementAll(debugEl, 'tab');
component = debugEl.componentInstance;
}));
});
it('should init component', () => {
expect(component).not.toBeNull();

View File

@ -20,12 +20,12 @@ describe('Common components', () => {
let nativeElement;
let fixture;
beforeEach(inject([TestBed], (tcb) => {
beforeEach(() => {
fixture = TestBed.createComponent(TestApp);
let debugEl = getChildDebugElement(fixture.debugElement, 'zippy');
component = debugEl.componentInstance;
nativeElement = debugEl.nativeElement;
}));
});
it('should init component', () => {
expect(component).not.toBeNull();

View File

@ -19,11 +19,6 @@ const md = new Remarkable({
}
});
interface HeadersHandler {
open: Function;
close: Function;
}
@Injectable()
export class MdRenderer {
public firstLevelHeadings: string[] = [];

View File

@ -1,7 +1,7 @@
{
"name": "redoc",
"description": "Swagger-generated API Reference Documentation",
"version": "1.6.0",
"version": "1.6.1",
"repository": {
"type": "git",
"url": "git://github.com/Rebilly/ReDoc"
@ -45,13 +45,13 @@
"author": "Roman Hotsiy",
"license": "MIT",
"devDependencies": {
"@angular/common": "~2.1.2",
"@angular/compiler": "~2.1.2",
"@angular/compiler-cli": "~2.1.2",
"@angular/core": "~2.1.2",
"@angular/platform-browser": "~2.1.2",
"@angular/platform-browser-dynamic": "~2.1.2",
"@angular/platform-server": "~2.1.2",
"@angular/common": "^2.2.4",
"@angular/compiler": "^2.2.4",
"@angular/compiler-cli": "^2.2.4",
"@angular/core": "^2.2.4",
"@angular/platform-browser": "^2.2.4",
"@angular/platform-browser-dynamic": "^2.2.4",
"@angular/platform-server": "^2.2.4",
"@types/core-js": "^0.9.31",
"@types/jasmine": "^2.2.32",
"@types/requirejs": "^2.1.26",
@ -60,10 +60,10 @@
"awesome-typescript-loader": "2.2.4",
"branch-release": "^1.0.3",
"chalk": "^1.1.3",
"codelyzer": "^1.0.0-beta.3",
"codelyzer": "^2.0.0-beta.1",
"core-js": "^2.4.1",
"coveralls": "^2.11.9",
"css-loader": "^0.25.0",
"css-loader": "^0.26.0",
"deploy-to-gh-pages": "^1.1.2",
"http-server": "^0.9.0",
"istanbul-instrumenter-loader": "^0.2.0",
@ -94,7 +94,7 @@
"string-replace-webpack-plugin": "0.0.4",
"style-loader": "^0.13.1",
"ts-helpers": "^1.1.1",
"tslint": "^3.15.1",
"tslint": "^4.0.2",
"typescript": "^2.0.3",
"webpack": "^2.1.0-beta.27",
"webpack-dev-server": "^2.1.0-beta.12",
@ -113,12 +113,12 @@
"stream-http": "^2.3.1"
},
"peerDependencies": {
"@angular/common": "~2.1.2",
"@angular/compiler": "~2.1.2",
"@angular/core": "~2.1.2",
"@angular/platform-browser": "~2.1.2",
"@angular/platform-browser-dynamic": "~2.1.2",
"@angular/platform-server": "~2.1.2",
"@angular/common": "^2.2.4",
"@angular/compiler": "^2.2.4",
"@angular/core": "^2.2.4",
"@angular/platform-browser": "^2.2.4",
"@angular/platform-browser-dynamic": "^2.2.4",
"@angular/platform-server": "^2.2.4",
"core-js": "^2.4.1",
"rxjs": "5.0.0-beta.12",
"zone.js": "^0.6.25"

View File

@ -13,14 +13,12 @@
],
"no-arg": true,
"no-construct": true,
"no-duplicate-key": true,
"no-duplicate-variable": true,
"no-empty": true,
"no-eval": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-unused-variable": true,
"no-unreachable": true,
"no-use-before-declare": true,
"one-line": [true,
"check-open-brace",
@ -36,10 +34,8 @@
],
"variable-name": false,
"directive-selector-type": [true, "attribute"],
"component-selector-type": [true, "element"],
"component-selector-name": [true, "kebab-case"],
"directive-selector-name": [true, "camelCase"],
"directive-selector": [true, "attribute", "", "camelCase"],
"component-selector": [true, "element", "", "kebab-case"],
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
@ -53,6 +49,10 @@
"no-access-missing-member": true,
"invoke-injectable": true,
"no-forward-ref": true,
"no-attribute-parameter-decorator": true
"no-attribute-parameter-decorator": true,
"templates-use-public": true,
"no-access-missing-member": true,
"invoke-injectable": true,
"no-unused-css": true
}
}