diff --git a/README.md b/README.md index 63ef580d..533d86d6 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,9 @@ For npm: ## Configuration +### Security Definition location +You can inject Security Definitions widget into any place of your specification `description`. Check out details [here](docs/security-definitions-injection.md). + ### Swagger vendor extensions ReDoc makes use of the following [vendor extensions](http://swagger.io/specification/#vendorExtensions): * [`x-logo`](docs/redoc-vendor-extensions.md#x-logo) - is used to specify API logo @@ -132,11 +135,7 @@ Redoc.init('http://petstore.swagger.io/v2/swagger.json', { `cd ReDoc` - Install dependencies `npm install` -- *(Temporary step, will be obsolete after fixing #97)* Compile CSS -```bash -npm run build:sass -``` -- _(optional)_ Replace `demo/swagger.json` with your own schema +- _(optional)_ Replace `demo/swagger.yaml` with your own schema - Start the server `npm start` - Open `http://localhost:9000` diff --git a/build/webpack.dev.js b/build/webpack.dev.js index cc6afc4a..449f6d50 100644 --- a/build/webpack.dev.js +++ b/build/webpack.dev.js @@ -1,5 +1,6 @@ const webpack = require('webpack'); const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin; +const StringReplacePlugin = require("string-replace-webpack-plugin"); const root = require('./helpers').root; const VERSION = JSON.stringify(require('../package.json').version); @@ -62,6 +63,28 @@ module.exports = { exclude: [ /node_modules/ ] + }, { + enforce: 'pre', + test: /\.ts$/, + exclude: [ + /node_modules/ + ], + loader: StringReplacePlugin.replace({ + replacements: [ + { + pattern: /styleUrls:\s*\[\s*'([\w\.\/-]*)\.css'\s*\][\s,]*$/m, + replacement: function (match, p1, offset, string) { + return `styleUrls: ['${p1}.scss'],`; + } + }, + { + pattern: /(\.\/components\/Redoc\/redoc-initial-styles\.css)/m, + replacement: function (match, p1, offset, string) { + return p1.replace('.css', '.scss'); + } + } + ] + }) }, { test: /\.ts$/, loaders: [ @@ -70,13 +93,16 @@ module.exports = { ], exclude: [/\.(spec|e2e)\.ts$/] }, { - test: /lib[\\\/].*\.css$/, - loaders: ['raw-loader'], - exclude: [/redoc-initial-styles\.css$/] + test: /lib[\\\/].*\.scss$/, + loaders: ['raw-loader', "sass"], + exclude: [/redoc-initial-styles\.scss$/] + }, { + test: /\.scss$/, + loaders: ['style', 'css?-import', "sass"], + exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.scss$/] }, { test: /\.css$/, loaders: ['style', 'css?-import'], - exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.css$/] }, { test: /\.html$/, loader: 'raw-loader' @@ -97,6 +123,8 @@ module.exports = { 'AOT': IS_PRODUCTION }), - new ForkCheckerPlugin() + new ForkCheckerPlugin(), + + new StringReplacePlugin() ], } diff --git a/build/webpack.prod.js b/build/webpack.prod.js index ffecdfe0..8fc8ef45 100644 --- a/build/webpack.prod.js +++ b/build/webpack.prod.js @@ -12,18 +12,6 @@ const BANNER = const IS_MODULE = process.env.IS_MODULE != null; -const TS_RULE = { - test: /\.ts$/, - loader: 'awesome-typescript-loader', - exclude: /(node_modules)/, -}; -// -// if (IS_MODULE) { -// TS_RULE.query = { -// noEmitHelpers: false -// } -// } - const config = { context: root(), devtool: 'source-map', @@ -70,7 +58,14 @@ const config = { exclude: [ /node_modules/ ] - }, TS_RULE, { + }, { + test: /node_modules\/.*\.ngfactory\.ts$/, + loader: 'awesome-typescript-loader' + }, { + test: /\.ts$/, + loader: 'awesome-typescript-loader', + exclude: /(node_modules)/, + }, { test: /lib[\\\/].*\.css$/, loaders: ['raw-loader'], exclude: [/redoc-initial-styles\.css$/] diff --git a/demo/swagger.yaml b/demo/swagger.yaml index 9bb9dee4..ac84c381 100644 --- a/demo/swagger.yaml +++ b/demo/swagger.yaml @@ -26,7 +26,6 @@ info: This API features Cross-Origin Resource Sharing (CORS) implemented in compliance with [W3C spec](https://www.w3.org/TR/cors/). And that allows cross-domain communication from the browser. All responses have a wildcard same-origin which makes them completely public and accessible to everyone, including any code on any site. - version: 1.0.0 title: Swagger Petstore termsOfService: 'http://swagger.io/terms/' diff --git a/docs/redoc-vendor-extensions.md b/docs/redoc-vendor-extensions.md index e12ef1e5..6cda3908 100644 --- a/docs/redoc-vendor-extensions.md +++ b/docs/redoc-vendor-extensions.md @@ -49,7 +49,7 @@ info: ### Tag Object vendor extensions Extends OpenAPI [Tag Object](http://swagger.io/specification/#tagObject) -#### x-traitTag +#### x-traitTag [DEPRECATED] | Field Name | Type | Description | | :------------- | :------: | :---------- | | x-traitTag | boolean | In Swagger two operations can have multiply tags. This property distinguish between tags that are used to group operations (default) from tags that are used to mark operation with certain trait (`true` value) | diff --git a/docs/security-definitions-injection.md b/docs/security-definitions-injection.md new file mode 100644 index 00000000..84071c07 --- /dev/null +++ b/docs/security-definitions-injection.md @@ -0,0 +1,19 @@ +# Injection security definitions + +You can inject Security Definitions widget into any place of your specification `description`: + +```markdown +... +# Authorization +Some description + + +... +``` +Inject instruction is wrapped into HTML comment so it is **visible only in ReDoc**. It won't be visible e.g. in SwaggerUI. + +# Default behavior +If injection tag is not found in the description it will be appended to the end +of description under `Authentication` header. + +If `Authentication` header is already present in the description, Security Definitions won't be inserted and rendered at all. diff --git a/lib/app.module.ts b/lib/app.module.ts new file mode 100644 index 00000000..37ee2c5a --- /dev/null +++ b/lib/app.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { RedocModule } from './redoc.module'; +import { Redoc } from './components/index'; + +@NgModule({ + imports: [ BrowserModule, RedocModule ], + bootstrap: [ Redoc ], + exports: [ Redoc ] +}) +export class AppModule { +} diff --git a/lib/bootstrap.dev.ts b/lib/bootstrap.dev.ts index f826b733..296618d7 100644 --- a/lib/bootstrap.dev.ts +++ b/lib/bootstrap.dev.ts @@ -1,6 +1,6 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { RedocModule } from './redoc.module'; +import { AppModule } from './app.module'; export function bootstrapRedoc() { - return platformBrowserDynamic().bootstrapModule(RedocModule); + return platformBrowserDynamic().bootstrapModule(AppModule); } diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index d7439b26..c55ccecb 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -1,6 +1,6 @@ import { platformBrowser } from '@angular/platform-browser'; -import { RedocModuleNgFactory } from './redoc.module.ngfactory'; +import { AppModuleNgFactory } from './app.module.ngfactory'; export function bootstrapRedoc() { - return platformBrowser().bootstrapModuleFactory(RedocModuleNgFactory); + return platformBrowser().bootstrapModuleFactory(AppModuleNgFactory); } diff --git a/lib/components/ApiInfo/api-info.html b/lib/components/ApiInfo/api-info.html index de1daf78..b8a8428c 100644 --- a/lib/components/ApiInfo/api-info.html +++ b/lib/components/ApiInfo/api-info.html @@ -17,5 +17,5 @@ {{info.license.name}}

-

+ diff --git a/lib/components/ApiInfo/api-info.spec.ts b/lib/components/ApiInfo/api-info.spec.ts index 7f5bf1c8..4d0e6612 100644 --- a/lib/components/ApiInfo/api-info.spec.ts +++ b/lib/components/ApiInfo/api-info.spec.ts @@ -11,7 +11,7 @@ import { } from '@angular/core/testing'; import { ApiInfo } from './api-info'; -import { SpecManager } from '../../utils/SpecManager'; +import { SpecManager } from '../../utils/spec-manager'; describe('Redoc components', () => { describe('ApiInfo Component', () => { diff --git a/lib/components/ApiInfo/api-info.ts b/lib/components/ApiInfo/api-info.ts index 9847210a..946b6ff2 100644 --- a/lib/components/ApiInfo/api-info.ts +++ b/lib/components/ApiInfo/api-info.ts @@ -12,7 +12,7 @@ import { OptionsService, MenuService } from '../../services/index'; export class ApiInfo extends BaseComponent implements OnInit { info: any = {}; specUrl: String; - constructor(specMgr:SpecManager, private optionsService:OptionsService, private menuServ: MenuService) { + constructor(specMgr: SpecManager, private optionsService: OptionsService) { super(specMgr); } diff --git a/lib/components/ApiLogo/api-logo.spec.ts b/lib/components/ApiLogo/api-logo.spec.ts index e4ba00c0..5ef98c1f 100644 --- a/lib/components/ApiLogo/api-logo.spec.ts +++ b/lib/components/ApiLogo/api-logo.spec.ts @@ -10,7 +10,7 @@ import { } from '@angular/core/testing'; import { ApiLogo } from './api-logo'; -import { SpecManager } from '../../utils/SpecManager'; +import { SpecManager } from '../../utils/spec-manager'; describe('Redoc components', () => { diff --git a/lib/components/JsonSchema/json-schema-lazy.ts b/lib/components/JsonSchema/json-schema-lazy.ts index 80dc3f63..4cfe9143 100644 --- a/lib/components/JsonSchema/json-schema-lazy.ts +++ b/lib/components/JsonSchema/json-schema-lazy.ts @@ -5,7 +5,7 @@ import { Component, ElementRef, ViewContainerRef, OnDestroy, Input, import { JsonSchema } from './json-schema'; import { OptionsService } from '../../services/options.service'; -import { SpecManager } from '../../utils/SpecManager'; +import { SpecManager } from '../../utils/spec-manager'; var cache = {}; @@ -38,7 +38,7 @@ export class JsonSchemaLazy implements OnDestroy, AfterViewInit { var componentFactory = this.resolver.resolveComponentFactory(JsonSchema); let contextInjector = this.location.parentInjector; let compRef = this.location.createComponent(componentFactory, null, contextInjector, null); - this.initComponent(compRef.instance); + this.projectComponentInputs(compRef.instance); this._renderer.setElementAttribute(compRef.location.nativeElement, 'class', this.location.element.nativeElement.className); compRef.changeDetectorRef.detectChanges(); this.loaded = true; @@ -58,24 +58,22 @@ export class JsonSchemaLazy implements OnDestroy, AfterViewInit { this.pointer = this.normalizePointer(); if (cache[this.pointer]) { let compRef = cache[this.pointer]; - setTimeout( ()=> { - let $element = compRef.location.nativeElement; + let $element = compRef.location.nativeElement; - // skip caching view with descendant schemas - // as it needs attached controller - if (!this.disableLazy && (compRef.instance.hasDescendants || compRef.instance._hasSubSchemas)) { - this._loadAfterSelf(); - return; - } - insertAfter($element.cloneNode(true), this.elementRef.nativeElement); - this.loaded = true; - }); + // skip caching view with descendant schemas + // as it needs attached controller + if (!this.disableLazy && (compRef.instance.hasDescendants || compRef.instance._hasSubSchemas)) { + this._loadAfterSelf(); + return; + } + insertAfter($element.cloneNode(true), this.elementRef.nativeElement); + this.loaded = true; } else { cache[this.pointer] = this._loadAfterSelf(); } } - initComponent(instance:JsonSchema) { + projectComponentInputs(instance:JsonSchema) { Object.assign(instance, this); } diff --git a/lib/components/JsonSchema/json-schema.spec.ts b/lib/components/JsonSchema/json-schema.spec.ts index d2c8f697..53b77cad 100644 --- a/lib/components/JsonSchema/json-schema.spec.ts +++ b/lib/components/JsonSchema/json-schema.spec.ts @@ -10,7 +10,7 @@ import { getChildDebugElement } from '../../../tests/helpers'; import { JsonSchema } from './json-schema'; -import { SpecManager } from '../../utils/SpecManager';; +import { SpecManager } from '../../utils/spec-manager';; describe('Redoc components', () => { beforeEach(() => { diff --git a/lib/components/Method/method.spec.ts b/lib/components/Method/method.spec.ts index c5e80d15..c35508a0 100644 --- a/lib/components/Method/method.spec.ts +++ b/lib/components/Method/method.spec.ts @@ -10,7 +10,7 @@ import { import { getChildDebugElement } from '../../../tests/helpers'; import { Method } from './method'; -import { SpecManager } from '../../utils/SpecManager';; +import { SpecManager } from '../../utils/spec-manager';; describe('Redoc components', () => { beforeEach(() => { diff --git a/lib/components/MethodsList/methods-list.spec.ts b/lib/components/MethodsList/methods-list.spec.ts index e552d2d2..ca59e157 100644 --- a/lib/components/MethodsList/methods-list.spec.ts +++ b/lib/components/MethodsList/methods-list.spec.ts @@ -11,7 +11,7 @@ import { getChildDebugElement } from '../../../tests/helpers'; import { MethodsList } from './methods-list'; -import { SpecManager } from '../../utils/SpecManager'; +import { SpecManager } from '../../utils/spec-manager'; describe('Redoc components', () => { beforeEach(() => { diff --git a/lib/components/Redoc/redoc-initial-styles.scss b/lib/components/Redoc/redoc-initial-styles.scss index 1a1b441b..abb29d88 100644 --- a/lib/components/Redoc/redoc-initial-styles.scss +++ b/lib/components/Redoc/redoc-initial-styles.scss @@ -4,12 +4,15 @@ redoc.loading { position: relative; display: block; - min-height:350px; + min-height: 350px; } @keyframes rotate { - 0% {transform: rotate(0deg)} - 100% {transform: rotate(360deg)} + 0% { + transform: rotate(0deg); } + 100% { + transform: rotate(360deg); + } } redoc.loading:before { @@ -33,7 +36,7 @@ redoc.loading:before { } redoc.loading:after { - z-index: 10000; + z-index: 10000; background-image: url('data:image/svg+xml;utf8,'); animation: 2s rotate linear infinite; width: 50px; @@ -51,20 +54,3 @@ redoc.loading:after { redoc.loading-remove:before, redoc.loading-remove:after { opacity: 0; } - -.redoc-error { - padding: 20px; - text-align: center; - color: #cc0000; - - > h2 { - color: #cc0000; - font-size: 40px; - } -} - -.redoc-error-details { - max-width: 750px; - margin: 0 auto; - font-size: 18px; -} diff --git a/lib/components/Redoc/redoc.html b/lib/components/Redoc/redoc.html index 8df000b0..8b4476ad 100644 --- a/lib/components/Redoc/redoc.html +++ b/lib/components/Redoc/redoc.html @@ -1,4 +1,8 @@ -
+
+

Oops... ReDoc failed to render this spec

+
{{error.message}}
+
+