diff --git a/.gitignore b/.gitignore index 82cb0860..01e1272c 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,8 @@ lib/**/*.css # files produced by ngc lib/**/*.ngfactory.ts lib/**/*.css.shim.ts +lib/**/*.ngsummary.json +lib/**/*.shim.ngstyle.ts # other /dist diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a8e1858..8e6f9828 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.6.2 (2016-12-11) +### Bug fixes +* Use markdown in responses description ([#158](https://github.com/Rebilly/ReDoc/issues/158)) + +### Features/Improvements +* [x-displayName](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-displayname) for tags - by [@bfirsh](https://github.com/bfirsh) ([PR #152](https://github.com/Rebilly/ReDoc/pull/152)) + # 1.6.1 (2016-12-02) ### Bug fixes * Fix only the first instance of schema was rendered ([#150](https://github.com/Rebilly/ReDoc/issues/150)) diff --git a/README.md b/README.md index 90607e9c..3bf8cdad 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ ReDoc makes use of the following [vendor extensions](http://swagger.io/specifica * [`x-traitTag`](docs/redoc-vendor-extensions.md#x-traitTag) - useful for handling out common things like Pagination, Rate-Limits, etc * [`x-code-samples`](docs/redoc-vendor-extensions.md#x-code-samples) - specify operation code samples * [`x-nullable`](docs/redoc-vendor-extensions.md#nullable) - mark schema param as a nullable +* [`x-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories ### `` tag attributes * `spec-url` - relative or absolute url to your spec file; @@ -123,6 +124,7 @@ ReDoc makes use of the following [vendor extensions](http://swagger.io/specifica * `suppress-warnings` - if set, warnings are not rendered at the top of documentation (they still are logged to the console). * `lazy-rendering` - if set, enables lazy rendering mode in ReDoc. This mode is useful for APIs with big number of operations (e.g. > 50). 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. * `hide-hostname` - if set, the protocol and hostname is not shown in the method definition. +* `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. ## Advanced usage Instead of adding `spec-url` attribute to the `` element you can initialize ReDoc via globally exposed `Redoc` object: diff --git a/build/webpack.dev.js b/build/webpack.dev.js index 3d483811..e7b24293 100644 --- a/build/webpack.dev.js +++ b/build/webpack.dev.js @@ -9,7 +9,7 @@ const IS_PRODUCTION = process.env.NODE_ENV === "production"; module.exports = { devtool: '#inline-source-map', - + performance: { hints: false }, resolve: { extensions: ['.ts', '.js', '.json', '.css'], alias: { diff --git a/build/webpack.prod.js b/build/webpack.prod.js index 54ef935c..baeee310 100644 --- a/build/webpack.prod.js +++ b/build/webpack.prod.js @@ -14,6 +14,7 @@ const IS_MODULE = process.env.IS_MODULE != null; const config = { context: root(), devtool: 'source-map', + performance: { hints: false }, resolve: { extensions: ['.ts', '.js', '.json', '.css'], diff --git a/lib/components/Redoc/redoc.ts b/lib/components/Redoc/redoc.ts index 8efcd4d7..7bbefece 100644 --- a/lib/components/Redoc/redoc.ts +++ b/lib/components/Redoc/redoc.ts @@ -5,6 +5,7 @@ import { ElementRef, Input, Component, OnInit, + OnDestroy, HostBinding } from '@angular/core'; @@ -26,14 +27,16 @@ import { LazyTasksService } from '../../shared/components/LazyFor/lazy-for'; export class Redoc extends BaseComponent implements OnInit { static _preOptions: any; - private element: any; - error: any; specLoaded: boolean; options: any; loadingProgress: number; + private element: HTMLElement; + private $parent: Element; + private $refElem: Element; + @Input() specUrl: string; @HostBinding('class.loading') specLoading: boolean = false; @HostBinding('class.loading-remove') specLoadingRemove: boolean = false; @@ -53,6 +56,9 @@ export class Redoc extends BaseComponent implements OnInit { optionsMgr.options = Redoc._preOptions || {}; this.element = elementRef.nativeElement; + this.$parent = this.element.parentElement; + this.$refElem = this.element.nextElementSibling; + //parse options (top level component doesn't support inputs) optionsMgr.parseOptions( this.element ); let scrollParent = detectScollParent( this.element ); @@ -121,4 +127,9 @@ export class Redoc extends BaseComponent implements OnInit { } this.load(); } + + ngOnDestroy() { + let $clone = this.element.cloneNode(); + this.$parent.insertBefore($clone, this.$refElem); + } } diff --git a/lib/components/ResponsesList/responses-list.html b/lib/components/ResponsesList/responses-list.html index 192b80f8..8bbd42cc 100644 --- a/lib/components/ResponsesList/responses-list.html +++ b/lib/components/ResponsesList/responses-list.html @@ -1,6 +1,6 @@

Responses

- +
Headers @@ -20,6 +20,6 @@
Response Schema
- + diff --git a/lib/components/ResponsesList/responses-list.ts b/lib/components/ResponsesList/responses-list.ts index 08b8b303..f7744041 100644 --- a/lib/components/ResponsesList/responses-list.ts +++ b/lib/components/ResponsesList/responses-list.ts @@ -49,6 +49,13 @@ export class ResponsesList extends BaseComponent implements OnInit { resp.empty = !resp.schema; resp.code = respCode; resp.type = statusCodeType(resp.code); + + if (this.options.expandResponses) { + if (this.options.expandResponses === 'all' || this.options.expandResponses.has(respCode.toString())) { + resp.expanded = true; + } + } + if (resp.headers && !(resp.headers instanceof Array)) { resp.headers = Object.keys(resp.headers).map((k) => { let respInfo = resp.headers[k]; diff --git a/lib/components/SideMenu/side-menu.ts b/lib/components/SideMenu/side-menu.ts index 7a46dcf9..3a6bc0fc 100644 --- a/lib/components/SideMenu/side-menu.ts +++ b/lib/components/SideMenu/side-menu.ts @@ -1,6 +1,6 @@ 'use strict'; -import { Component, ElementRef, ChangeDetectorRef, OnInit } from '@angular/core'; +import { Component, ElementRef, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core'; //import { global } from '@angular/core/src/facade/lang'; import { trigger, state, animate, transition, style } from '@angular/core'; @@ -21,13 +21,14 @@ const global = window; style({ height: '0px' })), state('expanded', style({ height: '*' })), - transition('collapsed <=> expanded', [ - animate('200ms ease') - ]) + // https://github.com/Rebilly/ReDoc/issues/162 + // transition('collapsed <=> expanded', [ + // animate('200ms ease') + // ]) ]) ], }) -export class SideMenu extends BaseComponent implements OnInit { +export class SideMenu extends BaseComponent implements OnInit, OnDestroy { activeCatCaption: string; activeItemCaption: string; categories: Array; @@ -122,6 +123,11 @@ export class SideMenu extends BaseComponent implements OnInit { destroy() { this.scrollService.unbind(); + this.menuService.destroy(); + } + + ngOnDestroy() { + this.destroy(); } ngOnInit() { diff --git a/lib/index.ts b/lib/index.ts index bb2fdc3a..163de55a 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -33,7 +33,6 @@ export function init(specUrl:string, options:any = {}) { moduleRef = appRef; console.log('ReDoc initialized!'); }).catch(err => { - //Redoc.displayError(err); throw err; }); }; diff --git a/lib/redoc.module.ts b/lib/redoc.module.ts index a8224fb3..b13b2dc3 100644 --- a/lib/redoc.module.ts +++ b/lib/redoc.module.ts @@ -1,4 +1,4 @@ -import { NgModule, ErrorHandler } from '@angular/core'; +import { NgModule, ErrorHandler, APP_ID } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Redoc, SecurityDefinitions, Method, REDOC_DIRECTIVES } from './components/index'; @@ -35,6 +35,7 @@ import { SpecManager } from './utils/spec-manager'; ComponentParser, ContentProjector, LazyTasksService, + { provide: APP_ID, useValue: 'redoc' }, { provide: ErrorHandler, useClass: CustomErrorHandler }, { provide: COMPONENT_PARSER_ALLOWED, useValue: { 'security-definitions': SecurityDefinitions} } ], diff --git a/lib/services/menu.service.ts b/lib/services/menu.service.ts index d470facb..f76b85fd 100644 --- a/lib/services/menu.service.ts +++ b/lib/services/menu.service.ts @@ -1,5 +1,6 @@ 'use strict'; import { Injectable, EventEmitter } from '@angular/core'; +import { Subscription } from 'rxjs/Subscription'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { ScrollService, INVIEW_POSITION } from './scroll.service'; import { Hash } from './hash.service'; @@ -16,6 +17,7 @@ const CHANGE = { @Injectable() export class MenuService { + changed: EventEmitter = new EventEmitter(); ready: BehaviorSubject = new BehaviorSubject(false); categories: Array; @@ -23,6 +25,8 @@ export class MenuService { activeCatIdx: number = 0; activeMethodIdx: number = -1; + private _hashSubscription: Subscription; + constructor( private hash:Hash, private tasks: LazyTasksService, @@ -39,7 +43,7 @@ export class MenuService { //this.changeActive(CHANGE.INITIAL); - this.hash.value.subscribe((hash) => { + this._hashSubscription = this.hash.value.subscribe((hash) => { if (hash == undefined) return; this.setActiveByHash(hash); if (!this.tasks.empty) { @@ -228,4 +232,8 @@ export class MenuService { } this.activate(catIdx, methodIdx); } + + destroy() { + this._hashSubscription.unsubscribe(); + } } diff --git a/lib/services/options.service.spec.ts b/lib/services/options.service.spec.ts index c02af6cd..1b887f92 100644 --- a/lib/services/options.service.spec.ts +++ b/lib/services/options.service.spec.ts @@ -14,7 +14,8 @@ describe('Options Service', () => { } afterEach(() => { - document.body.removeChild(tmpDiv); + if (tmpDiv) document.body.removeChild(tmpDiv); + tmpDiv = false; }); beforeEach(() => { @@ -47,4 +48,18 @@ describe('Options Service', () => { optionsService.parseOptions(elem); optionsService.options.scrollYOffset().should.be.equal(123); }); + + it('should convert expandResponses options to Set', () => { + optionsService.options = { expandResponses: '200,300' }; + optionsService._normalizeOptions(); + optionsService.options.expandResponses.should.be.instanceof(Set); + Array.from(optionsService.options.expandResponses.values()).should.deepEqual(['200', '300']); + }); + + it('should preserve special value "all" as string', () => { + optionsService.options = { expandResponses: 'all' }; + optionsService._normalizeOptions(); + optionsService.options.expandResponses.should.be.of.type('string'); + optionsService.options.expandResponses.should.be.equal('all'); + }); }); diff --git a/lib/services/options.service.ts b/lib/services/options.service.ts index e8e41663..4da11b42 100644 --- a/lib/services/options.service.ts +++ b/lib/services/options.service.ts @@ -14,7 +14,8 @@ const OPTION_NAMES = new Set([ 'specUrl', 'suppressWarnings', 'hideHostname', - 'lazyRendering' + 'lazyRendering', + 'expandResponses' ]); interface Options { @@ -24,6 +25,7 @@ interface Options { suppressWarnings?: boolean; hideHostname?: boolean; lazyRendering?: boolean; + expandResponses?: Set | 'all'; $scrollParent?: HTMLElement | Window; } @@ -36,7 +38,7 @@ export class OptionsService { this._normalizeOptions(); } - get options():Options { + get options(): Options { return this._options; } @@ -89,5 +91,10 @@ export class OptionsService { if (isString(this._options.suppressWarnings)) this._options.suppressWarnings = true; if (isString(this._options.hideHostname)) this._options.hideHostname = true; if (isString(this._options.lazyRendering)) this._options.lazyRendering = true; + if (isString(this._options.expandResponses)) { + let str = this._options.expandResponses as string; + if (str === 'all') return; + this._options.expandResponses = new Set(str.split(',')); + } } } diff --git a/lib/shared/components/Zippy/zippy.html b/lib/shared/components/Zippy/zippy.html index 5ba42121..f6c92aec 100644 --- a/lib/shared/components/Zippy/zippy.html +++ b/lib/shared/components/Zippy/zippy.html @@ -5,7 +5,7 @@ - {{title}} +
diff --git a/lib/shared/components/Zippy/zippy.scss b/lib/shared/components/Zippy/zippy.scss index a72b7ef9..bed7cb7a 100644 --- a/lib/shared/components/Zippy/zippy.scss +++ b/lib/shared/components/Zippy/zippy.scss @@ -45,11 +45,15 @@ $zippy-redirect-bg-color: rgba($zippy-redirect-color, .08); color: $zippy-info-color; background-color: $zippy-info-bg-color; } + + /deep/ p { + font-weight: normal; + } } .zippy-indicator svg { height: 1.2em; - vertical-align: middle; + vertical-align: top; transition: all 0.3s ease; transform: rotateZ(-180deg); } @@ -81,6 +85,8 @@ span.zippy-indicator { font-size: 1.2em; text-align: center; display: inline-block; + float: left; + margin-right: 5px; } .zippy-content { diff --git a/package.json b/package.json index 4f5aca28..bbab5615 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "redoc", "description": "Swagger-generated API Reference Documentation", - "version": "1.6.2", + "version": "1.6.3", "repository": { "type": "git", "url": "git://github.com/Rebilly/ReDoc" @@ -45,22 +45,22 @@ "author": "Roman Hotsiy", "license": "MIT", "devDependencies": { - "@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", + "@angular/common": "^2.3.1", + "@angular/compiler": "^2.3.1", + "@angular/compiler-cli": "^2.3.1", + "@angular/core": "^2.3.1", + "@angular/platform-browser": "^2.3.1", + "@angular/platform-browser-dynamic": "^2.3.1", + "@angular/platform-server": "^2.3.1", "@types/core-js": "^0.9.31", "@types/jasmine": "^2.2.32", "@types/requirejs": "^2.1.26", "@types/should": "^8.1.28", "angular2-template-loader": "^0.6.0", - "awesome-typescript-loader": "2.2.4", + "awesome-typescript-loader": "^2.2.4", "branch-release": "^1.0.3", "chalk": "^1.1.3", - "codelyzer": "^2.0.0-beta.1", + "codelyzer": "^2.0.0-beta.3", "core-js": "^2.4.1", "coveralls": "^2.11.9", "css-loader": "^0.26.0", @@ -85,7 +85,7 @@ "phantomjs-prebuilt": "^2.1.7", "protractor": "^4.0.10", "raw-loader": "^0.5.1", - "rxjs": "5.0.0-beta.12", + "rxjs": "^5.0.0-rc.4", "sass-loader": "^4.0.2", "shelljs": "^0.7.0", "should": "^11.1.0", @@ -95,10 +95,10 @@ "style-loader": "^0.13.1", "ts-helpers": "^1.1.1", "tslint": "^4.0.2", - "typescript": "^2.0.3", - "webpack": "^2.1.0-beta.27", + "typescript": "2.0.9", + "webpack": "^2.1.0-beta.28", "webpack-dev-server": "^2.1.0-beta.12", - "zone.js": "^0.6.25" + "zone.js": "^0.7.2" }, "dependencies": { "dropkickjs": "^2.1.10", @@ -113,14 +113,14 @@ "stream-http": "^2.3.1" }, "peerDependencies": { - "@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", + "@angular/common": "^2.3.1", + "@angular/compiler": "^2.3.1", + "@angular/core": "^2.3.1", + "@angular/platform-browser": "^2.3.1", + "@angular/platform-browser-dynamic": "^2.3.1", + "@angular/platform-server": "^2.3.1", "core-js": "^2.4.1", - "rxjs": "5.0.0-beta.12", - "zone.js": "^0.6.25" + "rxjs": "5.0.0-rc.4", + "zone.js": "^0.7.2" } }