mirror of
				https://github.com/Redocly/redoc.git
				synced 2025-10-31 07:47:29 +03:00 
			
		
		
		
	Merge branch 'master' into releases
This commit is contained in:
		
						commit
						20915ed40f
					
				|  | @ -139,21 +139,21 @@ api-logo { | ||||||
|         color: $red; |         color: $red; | ||||||
|         border: 1px solid rgba(38,50,56,0.1); |         border: 1px solid rgba(38,50,56,0.1); | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | footer { | ||||||
|  |     text-align: right; | ||||||
|  |     padding: 10px; | ||||||
|  |     font-size: 15px; | ||||||
|  |     background-color: white; | ||||||
| 
 | 
 | ||||||
|     strong { |     strong { | ||||||
|         font-size: 18px; |         font-size: 18px; | ||||||
|         color: $headers-color; |         color: $headers-color; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     footer { |  | ||||||
|         text-align: right; |  | ||||||
|         padding: 10px; |  | ||||||
|         font-size: 15px; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| /* markdown elements */ | /* markdown elements */ | ||||||
| 
 | 
 | ||||||
| :host .redoc-markdown-block { | :host .redoc-markdown-block { | ||||||
|  |  | ||||||
|  | @ -17,6 +17,21 @@ function safeConcat(a, b) { | ||||||
|   return res.concat(b); |   return res.concat(b); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function defaults(target, src) { | ||||||
|  |   var props = Object.keys(src); | ||||||
|  | 
 | ||||||
|  |   var index = -1, | ||||||
|  |       length = props.length; | ||||||
|  | 
 | ||||||
|  |   while (++index < length) { | ||||||
|  |     var key = props[index]; | ||||||
|  |     if (target[key] === undefined) { | ||||||
|  |       target[key] = src[key]; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return target; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| function snapshot(obj) { | function snapshot(obj) { | ||||||
|   if(obj == null || typeof(obj) != 'object') { |   if(obj == null || typeof(obj) != 'object') { | ||||||
|     return obj; |     return obj; | ||||||
|  | @ -156,41 +171,57 @@ export class BaseComponent { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   joinAllOf(schema = this.componentSchema, opts) { |   joinAllOf(schema = this.componentSchema, opts) { | ||||||
|     var self = this; |  | ||||||
|     function merge(into, schemas) { |     function merge(into, schemas) { | ||||||
|       if (into.required || into.properties) { |  | ||||||
|         let errMessage = `Can\'t merge allOf: properties or required fields are specified on the same level as allOf
 |  | ||||||
|           ${into}`;
 |  | ||||||
|         throw new Error(errMessage); |  | ||||||
|       } |  | ||||||
|       into.required = []; |  | ||||||
|       into.properties = {}; |  | ||||||
|       for (let subSchema of schemas) { |       for (let subSchema of schemas) { | ||||||
|         if (opts && opts.omitParent && subSchema.discriminator) continue; |         if (opts && opts.omitParent && subSchema.discriminator) continue; | ||||||
| 
 |  | ||||||
|         // TODO: add support for merge array schemas
 |         // TODO: add support for merge array schemas
 | ||||||
|         if (typeof subSchema !== 'object' || subSchema.type !== 'object') { |         if (typeof subSchema !== 'object') { | ||||||
|           let errMessage = `Can\'t merge allOf: only subschemas with type: object can be merged
 |           let errMessage = `Items of allOf should be Object: ${typeof subSchema} found
 | ||||||
|             ${subSchema}`;
 |             ${subSchema}`;
 | ||||||
|           throw new Error(errMessage); |           throw new Error(errMessage); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         self.joinAllOf(subSchema); |         if (into.type && into.type !== subSchema.type) { | ||||||
|  |           let errMessage = `allOf merging error: schemas with different types can't be merged`; | ||||||
|  |           throw new Error(errMessage); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (into.type === 'array') { | ||||||
|  |           console.warn('allOf: subschemas with type array are not supported yet'); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // TODO: add check if can be merged correctly (no different properties with the same name)
 |         // TODO: add check if can be merged correctly (no different properties with the same name)
 | ||||||
|         if (subSchema.properties) { |         if (subSchema.type === 'object' && subSchema.properties) { | ||||||
|  |           into.properties || (into.properties = {}); | ||||||
|           Object.assign(into.properties, subSchema.properties); |           Object.assign(into.properties, subSchema.properties); | ||||||
|         } |         } | ||||||
|         if (subSchema.required) { |         if (subSchema.type === 'object' && subSchema.required) { | ||||||
|  |           into.required || (into.required = []); | ||||||
|           into.required.push(...subSchema.required); |           into.required.push(...subSchema.required); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         defaults(into, subSchema); | ||||||
|       } |       } | ||||||
|       into.type = 'object'; |  | ||||||
|       into.allOf = null; |       into.allOf = null; | ||||||
|     } |     } | ||||||
|     if (schema.allOf) { | 
 | ||||||
|       merge(schema, schema.allOf); |     function traverse(obj) { | ||||||
|  |       if (obj === null || typeof(obj) !== 'object') { | ||||||
|  |         return; | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       for(var key in obj) { | ||||||
|  |         if (obj.hasOwnProperty(key)) { | ||||||
|  |           traverse(obj[key]); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (obj.allOf) { | ||||||
|  |         merge(obj, obj.allOf); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     traverse(schema); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|  |  | ||||||
|  | @ -217,19 +217,66 @@ describe('Redoc components', () => { | ||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       describe('Incorrect or not supported allOf', () => { |       describe('AllOf with other properties on the allOf level', () => { | ||||||
|         it('should throw when properties or required is set on the same level as allOf', () => { |         let joined; | ||||||
|           component.pointer = '/definitions/BadAllOf2'; |         beforeAll(() => { | ||||||
|  |           component.pointer = '/definitions/AllOfWithOther'; | ||||||
|  |           component.ngOnInit(); | ||||||
|  |           component.dereference(); | ||||||
|  |           component.joinAllOf(); | ||||||
|  |           joined = component.componentSchema; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         it('should remove $allOf field', () => { | ||||||
|  |           expect(joined.allOf).toBeNull(); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         it('should set type object', () => { | ||||||
|  |           joined.type.should.be.equal('object'); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         it('should merge properties', () => { | ||||||
|  |           Object.keys(joined.properties).length.should.be.equal(1); | ||||||
|  |           Object.keys(joined.properties).should.be.deepEqual(['id']); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         it('should merge required', () => { | ||||||
|  |           joined.required.length.should.be.equal(1); | ||||||
|  |           joined.required.should.be.deepEqual(['id']); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         it('should preserve parent properties', () => { | ||||||
|  |           joined.description.should.be.equal('Test'); | ||||||
|  |           joined.readOnly.should.be.equal(true); | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       describe('allOf edgecases', () => { | ||||||
|  |         it('should merge properties and required when defined on allOf level', () => { | ||||||
|  |           component.pointer = '/definitions/PropertiesOnAllOfLevel'; | ||||||
|  |           component.ngOnInit(); | ||||||
|  |           component.dereference(); | ||||||
|  |           (() => component.joinAllOf()).should.not.throw(); | ||||||
|  |           let joined = component.componentSchema; | ||||||
|  |           Object.keys(joined.properties).length.should.be.equal(3); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         it('should throw when merging schemas with different types', () => { | ||||||
|  |           component.pointer = '/definitions/BadAllOf1'; | ||||||
|           component.ngOnInit(); |           component.ngOnInit(); | ||||||
|           component.dereference(); |           component.dereference(); | ||||||
|           (() => component.joinAllOf()).should.throw(); |           (() => component.joinAllOf()).should.throw(); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         it('should throw when merging non-object schemas', () => { |         it('should handle nested allOF', () => { | ||||||
|           component.pointer = '/definitions/BadAllOf1'; |           component.pointer = '/definitions/NestedAllOf'; | ||||||
|           component.ngOnInit(); |           component.ngOnInit(); | ||||||
|           component.dereference(); |           component.dereference(); | ||||||
|           (() => component.joinAllOf()).should.throw(); |           (() => component.joinAllOf()).should.not.throw(); | ||||||
|  |           let joined = component.componentSchema; | ||||||
|  |           Object.keys(joined.properties).length.should.be.equal(4); | ||||||
|  |           Object.keys(joined.properties).should.be.deepEqual(['prop1', 'prop2', 'prop3', 'prop4']); | ||||||
|  |           joined.required.should.be.deepEqual(['prop1', 'prop3']); | ||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| { | { | ||||||
|   "name": "redoc", |   "name": "redoc", | ||||||
|   "description": "Swagger-generated API Reference Documentation", |   "description": "Swagger-generated API Reference Documentation", | ||||||
|   "version": "0.7.2", |   "version": "0.7.3", | ||||||
|   "repository": { |   "repository": { | ||||||
|     "type": "git", |     "type": "git", | ||||||
|     "url": "git://github.com/Rebilly/ReDoc" |     "url": "git://github.com/Rebilly/ReDoc" | ||||||
|  |  | ||||||
|  | @ -61,6 +61,7 @@ describe('APIs.guru specs test', ()=> { | ||||||
|   delete apisGuruList['googleapis.com:mirror']; // bad urls in images
 |   delete apisGuruList['googleapis.com:mirror']; // bad urls in images
 | ||||||
|   delete apisGuruList['googleapis.com:discovery']; // non-string references
 |   delete apisGuruList['googleapis.com:discovery']; // non-string references
 | ||||||
|   delete apisGuruList['clarify.io']; // non-string references
 |   delete apisGuruList['clarify.io']; // non-string references
 | ||||||
|  |   delete apisGuruList['pushpay.com']; // https://github.com/Rebilly/ReDoc/issues/30
 | ||||||
| 
 | 
 | ||||||
|   // run quick version of e2e test on all builds except releases
 |   // run quick version of e2e test on all builds except releases
 | ||||||
|   if (process.env.TRAVIS && !process.env.TRAVIS_TAG) { |   if (process.env.TRAVIS && !process.env.TRAVIS_TAG) { | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
|   "basePath": "/v2/", |   "basePath": "/v2/", | ||||||
|   "definitions": { |   "definitions": { | ||||||
|     "Simple": { |     "Simple": { | ||||||
|  |       "description": "simple", | ||||||
|       "type": "object", |       "type": "object", | ||||||
|       "required": ["id"], |       "required": ["id"], | ||||||
|       "properties": { |       "properties": { | ||||||
|  | @ -57,6 +58,15 @@ | ||||||
|         } |         } | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|  |     "AllOfWithOther": { | ||||||
|  |       "description": "Test", | ||||||
|  |       "readOnly": true, | ||||||
|  |       "allOf": [ | ||||||
|  |         { | ||||||
|  |           "$ref": "#/definitions/Simple" | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|     "BadAllOf1": { |     "BadAllOf1": { | ||||||
|       "allOf": [ |       "allOf": [ | ||||||
|         { |         { | ||||||
|  | @ -67,8 +77,12 @@ | ||||||
|         } |         } | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "BadAllOf2": { |     "PropertiesOnAllOfLevel": { | ||||||
|       "properties": {}, |       "properties": { | ||||||
|  |         "prop": { | ||||||
|  |           "type": "string" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|       "allOf": [ |       "allOf": [ | ||||||
|         { |         { | ||||||
|           "$ref": "#/definitions/Simple" |           "$ref": "#/definitions/Simple" | ||||||
|  | @ -83,6 +97,21 @@ | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       ] |       ] | ||||||
|  |     }, | ||||||
|  |     "NestedAllOf": { | ||||||
|  |       "allOf": [ | ||||||
|  |         { | ||||||
|  |           "$ref": "#/definitions/SimpleAllOf" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           "type": "object", | ||||||
|  |           "properties": { | ||||||
|  |             "prop4": { | ||||||
|  |               "type": "string" | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   "paths": { |   "paths": { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user