diff --git a/README.md b/README.md index 80cf0226..63ef580d 100644 --- a/README.md +++ b/README.md @@ -126,16 +126,17 @@ Redoc.init('http://petstore.swagger.io/v2/swagger.json', { ----------- ## Development #### Running local dev-server -1. Clone repository +- Clone repository `git clone https://github.com/Rebilly/ReDoc.git` -2. Go to the project folder +- Go to the project folder `cd ReDoc` -3. Install node modules and front-end dependencies +- Install dependencies +`npm install` +- *(Temporary step, will be obsolete after fixing #97)* Compile CSS +```bash +npm run build:sass ``` -npm install -npm run jspm-install -``` -4. _(optional)_ Replace `demo/swagger.json` with your own schema -5. Start the server +- _(optional)_ Replace `demo/swagger.json` with your own schema +- Start the server `npm start` -6. Open `http://localhost:9000` +- Open `http://localhost:9000` diff --git a/build/webpack.dev.js b/build/webpack.dev.js index 831fbc35..ff2ddacc 100644 --- a/build/webpack.dev.js +++ b/build/webpack.dev.js @@ -9,14 +9,10 @@ const IS_PRODUCTION = process.env.NODE_ENV === "production"; module.exports = { context: root(), devtool: 'source-map', - debug: false, resolve: { - extensions: ['', '.ts', '.js', '.json', '.css'], - root: root('lib'), - modulesDirectories: ['node_modules'], + extensions: ['.ts', '.js', '.json', '.css'], alias: { - './lib/bootstrap': root('lib/bootstrap.dev'), http: 'stream-http', https: 'stream-http' } @@ -28,7 +24,7 @@ module.exports = { node: { fs: "empty", crypto: "empty", - global: "window", + global: true, process: true, module: false, clearImmediate: false, @@ -58,29 +54,30 @@ module.exports = { }, module: { - preLoaders: [{ + exprContextCritical: false, + rules: [{ + enforce: 'pre', test: /\.js$/, loader: 'source-map-loader', exclude: [ /node_modules/ ] - }], - loaders: [{ + }, { test: /\.ts$/, loaders: [ 'awesome-typescript-loader', 'angular2-template-loader' ], exclude: [/\.(spec|e2e)\.ts$/] - },{ - test: /lib\/.*\.css$/, + }, { + test: /lib[\\\/].*\.css$/, loaders: ['raw-loader'], exclude: [/redoc-initial-styles\.css$/] - },{ + }, { test: /\.css$/, loaders: ['style', 'css?-import'], - exclude: [/lib\/(?!.*redoc-initial-styles).*\.css$/] - },{ + exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.css$/] + }, { test: /\.html$/, loader: 'raw-loader' }] @@ -96,7 +93,8 @@ module.exports = { new webpack.DefinePlugin({ 'IS_PRODUCTION': IS_PRODUCTION, - 'LIB_VERSION': VERSION + 'LIB_VERSION': VERSION, + 'AOT': IS_PRODUCTION }), new ForkCheckerPlugin() diff --git a/build/webpack.prod.js b/build/webpack.prod.js index e234dd44..ae10a82e 100644 --- a/build/webpack.prod.js +++ b/build/webpack.prod.js @@ -15,9 +15,7 @@ module.exports = { devtool: 'source-map', resolve: { - extensions: ['', '.ts', '.js', '.json', '.css'], - root: root('lib'), - modulesDirectories: ['node_modules'], + extensions: ['.ts', '.js', '.json', '.css'], alias: { http: 'stream-http', https: 'stream-http' @@ -30,7 +28,7 @@ module.exports = { node: { fs: "empty", crypto: "empty", - global: "window", + global: true, process: true, module: false, clearImmediate: false, @@ -50,14 +48,15 @@ module.exports = { }, module: { - preLoaders: [{ + exprContextCritical: false, + rules: [{ + enforce: 'pre', test: /\.js$/, loader: 'source-map-loader', exclude: [ /node_modules/ ] - }], - loaders: [{ + },{ test: /\.ts$/, loader: 'awesome-typescript-loader', exclude: /(node_modules)/ @@ -86,7 +85,8 @@ module.exports = { new webpack.BannerPlugin(BANNER), new webpack.DefinePlugin({ 'IS_PRODUCTION': true, - 'LIB_VERSION': VERSION + 'LIB_VERSION': VERSION, + 'AOT': true }) ], } diff --git a/build/webpack.test.js b/build/webpack.test.js index ba223e6e..869faf91 100644 --- a/build/webpack.test.js +++ b/build/webpack.test.js @@ -8,11 +8,8 @@ module.exports = { devtool: 'inline-source-map', resolve: { - extensions: ['', '.ts', '.js', '.json', '.css'], - root: root('lib'), - modulesDirectories: ['node_modules'], + extensions: ['.ts', '.js', '.json', '.css'], alias: { - './lib/bootstrap': root('lib/bootstrap.dev'), http: 'stream-http', https: 'stream-http' } @@ -24,7 +21,7 @@ module.exports = { node: { fs: "empty", crypto: "empty", - global: "window", + global: true, process: true, module: false, clearImmediate: false, @@ -39,74 +36,73 @@ module.exports = { }, module: { - preLoaders: [{ + exprContextCritical: false, + rules: [{ + enforce: 'pre', test: /\.js$/, loader: 'source-map-loader', exclude: [ /node_modules/ ] - }], - loaders: [ { + },{ test: /\.ts$/, loaders: [ 'awesome-typescript-loader' - ], - query: { - "sourceMap": false, - "inlineSourceMap": true, - "removeComments": true, - "module": "commonjs" - } + ] }, { test: /\.ts$/, loaders: [ 'angular2-template-loader' ], exclude: [/\.(spec|e2e)\.ts$/] - },{ - test: /lib\/.*\.css$/, + }, { + test: /lib[\\\/].*\.css$/, loaders: ['raw-loader'], exclude: [/redoc-initial-styles\.css$/] - },{ + }, { test: /\.css$/, loaders: ['style', 'css?-import'], - exclude: [/lib\/(?!.*redoc-initial-styles).*\.css$/] - },{ + exclude: [/lib[\\\/](?!.*redoc-initial-styles).*\.css$/] + }, { test: /\.html$/, loader: 'raw-loader' - }], - postLoaders: [ - + }, { /** * Instruments JS files with Istanbul for subsequent code coverage reporting. * Instrument only testing sources. * * See: https://github.com/deepsweet/istanbul-instrumenter-loader */ - { - test: /\.(js|ts)$/, loader: 'istanbul-instrumenter-loader', - include: root('lib'), - exclude: [ - /\.(e2e|spec)\.ts$/, - /node_modules/ - ] - } - - ] + enforce: 'post', + test: /\.(js|ts)$/, loader: 'istanbul-instrumenter-loader', + include: root('lib'), + exclude: [ + /\.(e2e|spec)\.ts$/, + /node_modules/ + ] + }] }, plugins: [ new webpack.DefinePlugin({ 'IS_PRODUCTION': false, - 'LIB_VERSION': VERSION + 'LIB_VERSION': VERSION, + 'AOT': 'false' }), + new webpack.LoaderOptionsPlugin({ + test: /\.ts$/, + sourceMap: false, + inlineSourceMap: true, + removeComments: true, + module: "commonjs" + }), // ignore changes during tests new webpack.WatchIgnorePlugin([ - /\/ReDoc$/i, // ignore change of ReDoc folder itself - /node_modules\/(?:[^\/]*(?:\/|$))*[^\/]*$/, - /\.tmp\/(?:[^\/]*(?:\/|$))*[^\/]*$/, - /dist\/(?:[^\/]*(?:\/|$))*[^\/]*$/, - /(?:[^\/]*(?:\/|$))*[^\/]*\.css$/ // ignore css files + /[\\\/]ReDoc$/i, // ignore change of ReDoc folder itself + /node_modules[\\\/].*$/, + /\.tmp[\\\/].*$/, + /dist[\\\/].*$/, + /(?:[^\\\/]*(?:[\\\/]|$))*[^\\\/]*\.css$/ // ignore css files ]) ], } diff --git a/lib/components/JsonSchema/json-schema.ts b/lib/components/JsonSchema/json-schema.ts index 6fa7917d..1ad68d8b 100644 --- a/lib/components/JsonSchema/json-schema.ts +++ b/lib/components/JsonSchema/json-schema.ts @@ -57,7 +57,7 @@ export class JsonSchema extends BaseComponent implements OnInit { this.descendants = this.specMgr.findDerivedDefinitions(this.normPointer); if (!this.descendants.length) return; this.hasDescendants = true; - let discriminator = this.schema.discriminator; + let discriminator = this.schema.discriminator || this.schema['x-extendedDiscriminator']; let discrProperty = this.schema._properties && this.schema._properties.filter((prop) => prop.name === discriminator)[0]; if (discrProperty && discrProperty.enum) { diff --git a/lib/components/SchemaSample/schema-sample.ts b/lib/components/SchemaSample/schema-sample.ts index 11de5307..74e77366 100644 --- a/lib/components/SchemaSample/schema-sample.ts +++ b/lib/components/SchemaSample/schema-sample.ts @@ -48,7 +48,7 @@ export class SchemaSample extends BaseComponent implements OnInit { this.componentSchema = this._normalizer.normalize(this.componentSchema, this.pointer); - let discriminator = this.componentSchema.discriminator; + let discriminator = this.componentSchema.discriminator || this.componentSchema['x-extendedDiscriminator']; if (discriminator) { let descendants = this.specMgr.findDerivedDefinitions(this.componentSchema._pointer || this.pointer); if (descendants.length) { diff --git a/lib/index.ts b/lib/index.ts index 06eeef8a..1ad46f3a 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -6,7 +6,13 @@ import { Redoc } from './components/index'; import { SpecManager } from './utils/SpecManager'; import { BrowserDomAdapter as DOM } from './utils/browser-adapter'; import { disableDebugTools } from '@angular/platform-browser'; -import { bootstrapRedoc } from './bootstrap'; + +var bootstrapRedoc; +if (AOT) { + bootstrapRedoc = require('./bootstrap').bootstrapRedoc; +} else { + bootstrapRedoc = require('./bootstrap.dev').bootstrapRedoc; +} if (IS_PRODUCTION) { disableDebugTools(); diff --git a/lib/services/schema-helper.service.ts b/lib/services/schema-helper.service.ts index 315761fd..fac99333 100644 --- a/lib/services/schema-helper.service.ts +++ b/lib/services/schema-helper.service.ts @@ -57,9 +57,10 @@ const injectors = { } }, discriminator: { - check: (propertySchema) => propertySchema.discriminator, + check: (propertySchema) => propertySchema.discriminator || propertySchema['x-extendedDiscriminator'], inject: (injectTo, propertySchema = injectTo, pointer) => { injectTo.discriminator = propertySchema.discriminator; + injectTo['x-extendedDiscriminator'] = propertySchema['x-extendedDiscriminator']; } }, simpleArray: { @@ -229,7 +230,8 @@ export class SchemaHelper { propertySchema._pointer = null; } propertySchema._required = !!requiredMap[propName]; - propertySchema.isDiscriminator = (schema.discriminator === propName); + propertySchema.isDiscriminator = (schema.discriminator === propName + || schema['x-extendedDiscriminator'] === propName); return propertySchema; }); diff --git a/lib/services/schema-normalizer.service.ts b/lib/services/schema-normalizer.service.ts index f97d6d65..300a4e27 100644 --- a/lib/services/schema-normalizer.service.ts +++ b/lib/services/schema-normalizer.service.ts @@ -118,7 +118,7 @@ class AllOfMerger { private static mergeObject(into, subSchema, allOfNumber) { if (subSchema.properties) { - if (!into.properties) into.properties = {}; + into.properties = Object.assign({}, into.properties || {}); Object.assign(into.properties, subSchema.properties); Object.keys(subSchema.properties).forEach(propName => { let prop = subSchema.properties[propName]; diff --git a/lib/utils/SpecManager.ts b/lib/utils/SpecManager.ts index 64755d6a..1c4032d5 100644 --- a/lib/utils/SpecManager.ts +++ b/lib/utils/SpecManager.ts @@ -152,19 +152,29 @@ export class SpecManager { findDerivedDefinitions(defPointer) { let definition = this.byPointer(defPointer); if (!definition) throw new Error(`Can't load schema at ${defPointer}`); - if (!definition.discriminator) return []; + if (!definition.discriminator && !definition['x-extendedDiscriminator']) return []; let globalDefs = this._schema.definitions || {}; let res = []; + let extendedDiscriminatorProp = definition['x-extendedDiscriminator']; for (let defName of Object.keys(globalDefs)) { - if (!globalDefs[defName].allOf && - !globalDefs[defName]['x-derived-from']) continue; - let subTypes = globalDefs[defName]['x-derived-from'] || - globalDefs[defName].allOf.map(subType => subType._pointer || subType.$ref); + let def = globalDefs[defName]; + if (!def.allOf && + !def['x-derived-from']) continue; + let subTypes = def['x-derived-from'] || + def.allOf.map(subType => subType._pointer || subType.$ref); let idx = subTypes.findIndex(ref => ref === defPointer); if (idx < 0) continue; - res.push({name: defName, $ref: `#/definitions/${defName}`}); + let derivedName = defName; + if (extendedDiscriminatorProp) { + let prop = def.properties && def.properties[extendedDiscriminatorProp]; + if (prop && prop.enum && prop.enum.length === 1) { + derivedName = prop.enum[0]; + } + } + + res.push({name: derivedName, $ref: `#/definitions/${defName}`}); } return res; } diff --git a/manual-types/index.d.ts b/manual-types/index.d.ts index 22733ca1..faecbd1c 100644 --- a/manual-types/index.d.ts +++ b/manual-types/index.d.ts @@ -14,6 +14,7 @@ declare module "*.css" { declare var LIB_VERSION: any; declare var IS_PRODUCTION: any; +declare var AOT: any; interface ErrorStackTraceLimit { stackTraceLimit: number; diff --git a/package.json b/package.json index 0834b2cc..6f84ef02 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,15 @@ { "name": "redoc", "description": "Swagger-generated API Reference Documentation", - "version": "1.3.2", + "version": "1.3.3", "repository": { "type": "git", "url": "git://github.com/Rebilly/ReDoc" }, + "engines": { + "node": ">=4.0.0", + "npm": ">=3.0.0" + }, "main": "dist/redoc.min.js", "scripts": { "test": "npm run lint && node ./build/run_tests.js", @@ -40,7 +44,7 @@ "author": "Roman Hotsiy", "license": "MIT", "devDependencies": { - "@angular/compiler-cli": "^0.6.0", + "@angular/compiler-cli": "^0.6.3", "@types/core-js": "^0.9.31", "@types/jasmine": "^2.2.32", "@types/requirejs": "^2.1.26", @@ -49,7 +53,7 @@ "awesome-typescript-loader": "^2.2.1", "branch-release": "^1.0.3", "chalk": "^1.1.3", - "codelyzer": "0.0.28", + "codelyzer": "^1.0.0-beta.0", "copy-webpack-plugin": "^3.0.1", "coveralls": "^2.11.9", "css-loader": "^0.24.0", @@ -80,31 +84,31 @@ "source-map-loader": "^0.1.5", "style-loader": "^0.13.1", "ts-helpers": "^1.1.1", - "tslint": "^3.15.0-dev.0", + "tslint": "^3.15.1", "tslint-stylish": "^2.1.0-beta", - "typescript": "^2.0.2", - "webpack": "^2.1.0-beta.21", - "webpack-dev-server": "^2.1.0-beta.2" + "typescript": "^2.0.3", + "webpack": "^2.1.0-beta.25", + "webpack-dev-server": "^2.1.0-beta.6" }, "dependencies": { - "@angular/common": "^2.0.0-rc.6", - "@angular/compiler": "^2.0.0-rc.6", - "@angular/core": "^2.0.0-rc.6", - "@angular/platform-browser": "^2.0.0-rc.6", - "@angular/platform-browser-dynamic": "^2.0.0-rc.6", - "@angular/platform-server": "^2.0.0-rc.6", + "@angular/common": "^2.0.1", + "@angular/compiler": "^2.0.1", + "@angular/core": "^2.0.1", + "@angular/platform-browser": "^2.0.1", + "@angular/platform-browser-dynamic": "^2.0.1", + "@angular/platform-server": "^2.0.1", "core-js": "^2.4.1", "dropkickjs": "^2.1.10", "hint.css": "^2.3.2", "json-pointer": "^0.5.0", "json-schema-ref-parser": "^3.1.2", - "openapi-sampler": "^0.3.0", + "openapi-sampler": "^0.3.1", "prismjs": "^1.5.1", "remarkable": "^1.6.2", - "rxjs": "^5.0.0-beta.11", + "rxjs": "^5.0.0-beta.12", "scrollparent": "^1.0.0", "slugify": "^1.0.2", "stream-http": "^2.3.1", - "zone.js": "^0.6.17" + "zone.js": "^0.6.25" } }