Merge commit '942cd5dc53534c6ff952872ace41ce632888a4f4' into releases

This commit is contained in:
RedocBot 2017-02-22 16:02:31 +00:00 committed by travis@localhost
commit d97374d3c4
20 changed files with 443 additions and 287 deletions

View File

@ -1,3 +1,16 @@
# 1.8.0 (2017-02-03)
### Features/Improvements
* In-page search :tada: []#51](https://github.com/Rebilly/ReDoc/issues/51)
* Render externalDocs [#103](https://github.com/Rebilly/ReDoc/issues/103)
* Undeprecate x-traitTag
### Bug fixes
* Tags with x-traitTag: true are now greyed out in ReDoc output bug [#194](https://github.com/Rebilly/ReDoc/issues/194)
* CSS: request body model-tree wrapping problem [#185](https://github.com/Rebilly/ReDoc/issues/185)
* Strange request to `example.com` causing CSP error [#178](https://github.com/Rebilly/ReDoc/issues/178)
* Fix latest empty menu-items not getting active [#194](https://github.com/Rebilly/ReDoc/issues/194)
* Fixed crash when level-2 heading goes before level-1 in description [#179](https://github.com/Rebilly/ReDoc/issues/179) (by [@jsmartfo](https://github.com/jsmartfo))
# 1.7.0 (2017-01-06)
### Features/Improvements
* Add support for grouping items in menu via [`x-tagGroups`](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-taggroups)

View File

@ -31,8 +31,8 @@
- Multiple ReDoc instances on single page ([example](demo/examples/multiple-apis/index.html))
## Roadmap
- [x] performance optimizations
- [ ] better navigation (menu improvements + search)
- [x] ~~performance optimizations~~
- [x] ~~better navigation (menu improvements + search)~~
- [ ] ability to simple branding/styling
- [ ] built-in API Console
- [ ] docs pre-rendering (performance and SEO)
@ -43,6 +43,14 @@ We host the latest and all the previous ReDoc releases on GitHub Pages-based **C
- `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 this file is updated with each release of ReDoc and may introduce breaking changes. **Not recommended to use in production.** Use particular release or `v1.x.x`.
## Some Real-life usages
- [Rebilly](https://rebilly.github.io/RebillyAPI)
- [Docker Engine](https://docs.docker.com/engine/api/v1.25/)
- [Zuora](https://www.zuora.com/developer/api-reference/)
- [Shopify Draft Orders](https://help.shopify.com/api/draft-orders)
- [Discourse](https://docs.discourse.org)
- [APIs.guru](https://apis.guru/api-doc/)
## Deployment
### TL;DR

View File

@ -87,7 +87,11 @@ module.exports = function (options) {
},
{
test: /\.scss$/,
loaders: ['style-loader', 'css-loader?-import', "sass-loader"],
use: [
'style-loader',
'css-loader?-import',
'sass-loader'
],
exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.scss$/]
},
{

View File

@ -68,7 +68,7 @@
</td>
<td class="param-info">
<div>
<span class="param-type {{prop.type}}" [ngClass]="{'with-hint': prop._displayTypeHint, 'tuple': prop._isTuple}"
<span class="param-type {{prop.type}}" [ngClass]="{'with-hint': prop._displayTypeHint, 'tuple': prop._isTuple, 'array': prop._isArray}"
title="{{prop._displayTypeHint}}"> {{prop._displayType}} {{prop._displayFormat}}
<span class="param-range" *ngIf="prop._range"> {{prop._range}} </span>
</span>

View File

@ -93,6 +93,7 @@ zippy {
.param.complex > .param-name svg {
height: 1.2em;
width: 1.2em;
vertical-align: middle;
transition: all 0.3s ease;
}

View File

@ -6,7 +6,7 @@ import { Input, HostBinding, Component, OnChanges } from '@angular/core';
template: `
<span [style.width]='progress + "%"'> </span>
`,
styleUrls: ['loading-bar.scss']
styleUrls: ['loading-bar.css']
})
export class LoadingBar implements OnChanges {
@Input() progress:number = 0;

View File

@ -1,6 +1,6 @@
<header *ngIf="data.responses.length"> Response samples </header>
<tabs *ngIf="data.responses.length">
<tab *ngFor="let response of data.responses" tabTitle="{{response.code}} {{response.description}}"
<tab *ngFor="let response of data.responses" [tabTitle]="response.code + ' ' + response.description | marked"
[tabStatus]="response.type">
<schema-sample [pointer]="response.pointer"></schema-sample>
</tab>

View File

@ -51,8 +51,6 @@ export class SideMenu extends BaseComponent implements OnInit, OnDestroy {
private $resourcesNav: any;
private $scrollParent: any;
private firstChange = true;
constructor(specMgr:SpecManager, elementRef:ElementRef,
private scrollService:ScrollService, private menuService:MenuService,
optionsService:OptionsService, private detectorRef:ChangeDetectorRef, private marker:Marker) {
@ -84,15 +82,12 @@ export class SideMenu extends BaseComponent implements OnInit, OnDestroy {
//safari doesn't update bindings if not run changeDetector manually :(
this.detectorRef.detectChanges();
if (this.firstChange) {
this.scrollActiveIntoView();
this.firstChange = false;
}
}
scrollActiveIntoView() {
let $item = this.$element.querySelector('li.active, label.active');
if ($item) $item.scrollIntoView();
if ($item) $item.scrollIntoViewIfNeeded();
}
activateAndScroll(item) {

View File

@ -28,3 +28,35 @@ if (!IS_PRODUCTION) {
Error.stackTraceLimit = Infinity;
require('zone.js/dist/long-stack-trace-zone');
}
interface Element {
scrollIntoViewIfNeeded(centerIfNeeded?: boolean): void;
};
if (!(<any>Element).prototype.scrollIntoViewIfNeeded) {
(<any>Element).prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) {
centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded;
var parent = this.parentNode,
parentComputedStyle = window.getComputedStyle(parent, null),
parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
overTop = this.offsetTop - parent.offsetTop < parent.scrollTop,
overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight),
overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft,
overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth),
alignWithTop = overTop && !overBottom;
if ((overTop || overBottom) && centerIfNeeded) {
parent.scrollTop = this.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + this.clientHeight / 2;
}
if ((overLeft || overRight) && centerIfNeeded) {
parent.scrollLeft = this.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + this.clientWidth / 2;
}
if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
this.scrollIntoView(alignWithTop);
}
};
}

View File

@ -17,4 +17,19 @@ describe('Spec Helper', () => {
(<jasmine.Spy>console.warn).and.callThrough();
});
});
describe('preprocessProperties', () => {
it('should not throw when type array and items are not defined', () => {
let schema = {
type: 'object',
properties: {
prop1: {
type: 'array'
}
}
};
(() => SchemaHelper.preprocessProperties(schema, '#/', {})).should.not.throw();
});
});
});

View File

@ -5,7 +5,7 @@ import { WarningsService } from './warnings.service';
import * as slugify from 'slugify';
interface PropertyPreprocessOptions {
childFor: string;
childFor?: string;
skipReadOnly?: boolean;
discriminator?: string;
}
@ -54,6 +54,7 @@ const injectors = {
return propertySchema.type === 'array' && !Array.isArray(propertySchema.items);
},
inject: (injectTo, propertySchema = injectTo, propPointer) => {
if (!propertySchema.items) propertySchema.items = {};
if (!(SchemaHelper.detectType(propertySchema.items) === 'object')) {
injectTo._isArray = true;
injectTo._pointer = propertySchema.items._pointer
@ -63,6 +64,7 @@ const injectors = {
} else {
injectors.object.inject(injectTo, propertySchema.items);
}
if (!injectTo.description) injectTo.description = propertySchema.items.description;
injectTo._widgetType = 'array';
}
},
@ -207,7 +209,11 @@ export class SchemaHelper {
static preprocessProperties(schema:any, pointer:string, opts: PropertyPreprocessOptions) {
let requiredMap = {};
if (schema.required) {
if (Array.isArray(schema.required)) {
schema.required.forEach(prop => requiredMap[prop] = true);
} else {
WarningsService.warn(`required must be an array: "${typeof schema.required}" found at ${pointer}`);
}
}
let props = schema.properties && Object.keys(schema.properties).map(propName => {

View File

@ -1,5 +1,5 @@
<ul>
<li *ngFor="let tab of tabs" [ngClass]="{active: tab.active}" (click)="selectTab(tab)"
class="tab-{{tab.tabStatus}}">{{tab.tabTitle}}</li>
class="tab-{{tab.tabStatus}}" [innerHTML]="tab.tabTitle"></li>
</ul>
<ng-content></ng-content>

View File

@ -16,6 +16,10 @@ li {
cursor: pointer;
}
li /deep/ .redoc-markdown-block p {
display: inline;
}
.tab-success, .tab-error, .tab-redirect, .tab-info {
&:before {
content: "";

View File

@ -53,6 +53,7 @@ $zippy-redirect-bg-color: rgba($zippy-redirect-color, .08);
.zippy-indicator svg {
height: 1.2em;
width: 1.2em;
vertical-align: top;
transition: all 0.3s ease;
transform: rotateZ(-180deg);

View File

@ -8,6 +8,7 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { MdRenderer } from './md-renderer';
import { SwaggerOperation, SwaggerParameter } from './swagger-typings';
import { snapshot } from './helpers';
function getDiscriminator(obj) {
return obj.discriminator || obj['x-extendedDiscriminator'];
@ -37,7 +38,7 @@ export class SpecManager {
if (typeof urlOrObject === 'string') {
this._url = urlOrObject;
}
this._schema = schema;
this._schema = snapshot(schema);
try {
this.init();
resolve(this._schema);
@ -67,7 +68,7 @@ export class SpecManager {
}
let host = this._schema.host || urlParts.host;
this.basePath = this._schema.basePath || '/';
this.basePath = this._schema.basePath || '';
this.apiUrl = protocol + '://' + host + this.basePath;
if (this.apiUrl.endsWith('/')) {
this.apiUrl = this.apiUrl.substr(0, this.apiUrl.length - 1);

View File

@ -1,7 +1,7 @@
{
"name": "redoc",
"description": "Swagger-generated API Reference Documentation",
"version": "1.8.0",
"version": "1.8.1",
"repository": {
"type": "git",
"url": "git://github.com/Rebilly/ReDoc"
@ -47,32 +47,37 @@
"author": "Roman Hotsiy",
"license": "MIT",
"devDependencies": {
"@angular/common": "^2.4.5",
"@angular/compiler": "^2.4.5",
"@angular/compiler-cli": "^2.4.5",
"@angular/core": "^2.4.5",
"@angular/platform-browser": "^2.4.5",
"@angular/platform-browser-dynamic": "^2.4.5",
"@angular/platform-server": "^2.4.5",
"@angular/common": "^2.4.8",
"@angular/compiler": "^2.4.8",
"@angular/compiler-cli": "^2.4.8",
"@angular/core": "^2.4.8",
"@angular/platform-browser": "^2.4.8",
"@angular/platform-browser-dynamic": "^2.4.8",
"@angular/platform-server": "^2.4.8",
"@types/core-js": "^0.9.31",
"@types/jasmine": "^2.2.32",
"@types/jasmine": "^2.5.43",
"@types/requirejs": "^2.1.26",
"@types/should": "^8.1.28",
"@types/swagger-schema-official": "^2.0.0",
"angular2-template-loader": "^0.6.0",
"awesome-typescript-loader": "~3.0.0-beta.17",
"@types/webpack": "^2.2.6",
"angular2-template-loader": "^0.6.2",
"awesome-typescript-loader": "^3.0.6",
"branch-release": "^1.0.3",
"chalk": "^1.1.3",
"codelyzer": "^2.0.0-beta.4",
"codelyzer": "^2.0.1",
"core-js": "^2.4.1",
"coveralls": "^2.11.9",
"coveralls": "^2.11.16",
"css-loader": "^0.26.0",
"deploy-to-gh-pages": "^1.1.2",
"dropkickjs": "^2.1.10",
"hint.css": "^2.3.2",
"http-server": "^0.9.0",
"istanbul-instrumenter-loader": "^1.2.0",
"istanbul-instrumenter-loader": "^2.0.0",
"jasmine-core": "^2.4.1",
"jasmine-spec-reporter": "^3.1.0",
"karma": "^1.4.1",
"json-pointer": "^0.6.0",
"json-schema-ref-parser": "^3.1.2",
"karma": "^1.5.0",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.1",
"karma-coveralls": "^1.1.2",
@ -85,51 +90,35 @@
"karma-sinon": "^1.0.4",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.1",
"lunr": "^1.0.0",
"mark.js": "github:julmot/mark.js",
"ngc-webpack": "^1.2.0",
"node-sass": "^4.5.0",
"openapi-sampler": "^0.4.0",
"phantomjs-prebuilt": "^2.1.7",
"protractor": "^5.1.0",
"prismjs": "^1.5.1",
"protractor": "^5.1.1",
"raw-loader": "^0.5.1",
"rimraf": "^2.5.4",
"rxjs": "^5.1.0",
"sass-loader": "^4.1.1",
"remarkable": "^1.6.2",
"rimraf": "^2.6.0",
"rxjs": "^5.2.0",
"sass-loader": "^6.0.2",
"scrollparent": "^1.0.0",
"shelljs": "^0.7.0",
"should": "^11.1.0",
"sinon": "^1.17.2",
"slugify": "^1.0.2",
"source-map-loader": "^0.1.5",
"stream-http": "^2.6.1",
"string-replace-webpack-plugin": "0.0.5",
"style-loader": "^0.13.1",
"ts-helpers": "^1.1.1",
"tslint": "^4.3.1",
"typescript": "^2.1.5",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.2.0-rc.0",
"webpack-merge": "^2.6.1",
"zone.js": "^0.7.2"
"webpack-dev-server": "^2.4.1",
"webpack-merge": "^3.0.0",
"zone.js": "^0.7.7"
},
"dependencies": {
"dropkickjs": "^2.1.10",
"hint.css": "^2.3.2",
"json-pointer": "^0.6.0",
"json-schema-ref-parser": "^3.1.2",
"lunr": "^0.7.2",
"mark.js": "github:julmot/mark.js",
"openapi-sampler": "^0.3.3",
"prismjs": "^1.5.1",
"remarkable": "^1.6.2",
"scrollparent": "^1.0.0",
"slugify": "^1.0.2",
"stream-http": "^2.6.1"
},
"peerDependencies": {
"@angular/common": "^2.4.5",
"@angular/compiler": "^2.4.5",
"@angular/core": "^2.4.5",
"@angular/platform-browser": "^2.4.5",
"@angular/platform-browser-dynamic": "^2.4.5",
"@angular/platform-server": "^2.4.5",
"core-js": "^2.4.1",
"rxjs": "^5.0.1",
"zone.js": "^0.7.2"
}
"dependencies": {}
}

View File

@ -63,6 +63,13 @@ describe('Utils', () => {
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._url = 'https://petstore.swagger.io';
specMgr.init();
specMgr.basePath.should.be.equal('');
});
describe('byPointer method', () => {
it('should return correct schema part', ()=> {
let part = specMgr.byPointer('/tags/0');

View File

@ -11,6 +11,7 @@
"noEmitHelpers": true,
"strictNullChecks": false,
"baseUrl": "./src",
"typeRoots": [ "./node_modules/@types" ],
"paths": {
},
"lib": [
@ -18,7 +19,7 @@
"dom"
],
"types": [
"node"
"webpack"
]
},
"exclude": [

519
yarn.lock

File diff suppressed because it is too large Load Diff