@@ -28,7 +28,7 @@ Resolver.prototype.processAllOf = function(name, definition, resolutionTable, un
2828 location = '/definitions/' + name + '/allOf' ;
2929 this . resolveInline ( null , spec , property , resolutionTable , unresolvedRefs , location ) ;
3030 }
31- }
31+ } ;
3232
3333Resolver . prototype . resolve = function ( spec , arg1 , arg2 , arg3 ) {
3434 var root = arg1 , callback = arg2 , scope = arg3 , location , i ;
@@ -115,6 +115,7 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
115115 // if the root is same as obj[i].root we can resolve locally
116116 var all = resolutionTable ;
117117
118+ var parts ;
118119 for ( i = 0 ; i < all . length ; i ++ ) {
119120 var a = all [ i ] ;
120121 if ( root === a . root ) {
@@ -145,7 +146,7 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
145146 toResolve . push ( a ) ;
146147 }
147148 else {
148- var parts = a . key . split ( '#' ) ;
149+ parts = a . key . split ( '#' ) ;
149150 if ( parts . length === 2 ) {
150151 if ( parts [ 0 ] . indexOf ( 'http://' ) === 0 || parts [ 0 ] . indexOf ( 'https://' ) === 0 ) {
151152 a . root = parts [ 0 ] ;
@@ -175,6 +176,17 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
175176 }
176177 else {
177178 if ( a . resolveAs === 'inline' ) {
179+ if ( a . key && a . key . indexOf ( '#' ) === - 1 && a . key . charAt ( 0 ) !== '/' ) {
180+ // handle relative schema
181+ parts = a . root . split ( '/' ) ;
182+ location = '' ;
183+ for ( i = 0 ; i < parts . length - 1 ; i ++ ) {
184+ location += parts [ i ] + '/' ;
185+ }
186+ location += a . key ;
187+ a . root = location ;
188+ a . location = '' ;
189+ }
178190 toResolve . push ( a ) ;
179191 }
180192 }
@@ -208,15 +220,18 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
208220 on : {
209221 error : function ( ) {
210222 processedCalls += 1 ;
211- unresolvedRefs [ item . key ] = null ;
223+ unresolvedRefs [ item . key ] = {
224+ root : item . root ,
225+ location : item . location
226+ } ;
212227
213228 if ( processedCalls === expectedCalls ) {
214229 self . finish ( spec , _root , resolutionTable , resolvedRefs , unresolvedRefs , callback ) ;
215230 }
216231 } , // jshint ignore:line
217232 response : function ( response ) {
218233 var swagger = response . obj ;
219- self . resolveItem ( swagger , _root , resolutionTable , resolvedRefs , unresolvedRefs , item ) ;
234+ self . resolveItem ( swagger , item . root , resolutionTable , resolvedRefs , unresolvedRefs , item ) ;
220235 processedCalls += 1 ;
221236
222237 if ( processedCalls === expectedCalls ) {
@@ -242,23 +257,25 @@ Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) {
242257Resolver . prototype . resolveItem = function ( spec , root , resolutionTable , resolvedRefs , unresolvedRefs , item ) {
243258 var path = item . location ;
244259 var location = spec , parts = path . split ( '/' ) ;
245- for ( var j = 0 ; j < parts . length ; j ++ ) {
246- var segment = parts [ j ] ;
247- if ( segment . indexOf ( '~1' ) !== - 1 ) {
248- segment = parts [ j ] . replace ( / ~ 0 / g, '~' ) . replace ( / ~ 1 / g, '/' ) ;
249- if ( segment . charAt ( 0 ) !== '/' ) {
250- segment = '/' + segment ;
260+ if ( path !== '' ) {
261+ for ( var j = 0 ; j < parts . length ; j ++ ) {
262+ var segment = parts [ j ] ;
263+ if ( segment . indexOf ( '~1' ) !== - 1 ) {
264+ segment = parts [ j ] . replace ( / ~ 0 / g, '~' ) . replace ( / ~ 1 / g, '/' ) ;
265+ if ( segment . charAt ( 0 ) !== '/' ) {
266+ segment = '/' + segment ;
267+ }
268+ }
269+ if ( typeof location === 'undefined' || location === null ) {
270+ break ;
271+ }
272+ if ( segment === '' && j === ( parts . length - 1 ) && parts . length > 1 ) {
273+ location = null ;
274+ break ;
275+ }
276+ if ( segment . length > 0 ) {
277+ location = location [ segment ] ;
251278 }
252- }
253- if ( typeof location === 'undefined' || location === null ) {
254- break ;
255- }
256- if ( segment === '' && j === ( parts . length - 1 ) && parts . length > 1 ) {
257- location = null ;
258- break ;
259- }
260- if ( segment . length > 0 ) {
261- location = location [ segment ] ;
262279 }
263280 }
264281 var resolved = item . key ;
@@ -295,6 +312,9 @@ Resolver.prototype.finish = function (spec, root, resolutionTable, resolvedRefs,
295312 if ( resolvedTo ) {
296313 spec . definitions = spec . definitions || { } ;
297314 if ( item . resolveAs === 'ref' ) {
315+ for ( key in resolvedTo . obj ) {
316+ var abs = this . retainRoot ( resolvedTo . obj [ key ] , item . root ) ;
317+ }
298318 spec . definitions [ resolvedTo . name ] = resolvedTo . obj ;
299319 item . obj . $ref = '#/definitions/' + resolvedTo . name ;
300320 } else if ( item . resolveAs === 'inline' ) {
@@ -359,7 +379,9 @@ Resolver.prototype.getRefs = function(spec, obj) {
359379 obj = obj || spec ;
360380 var output = { } ;
361381 for ( var key in obj ) {
362- if ( ! obj . hasOwnProperty ( key ) ) continue ;
382+ if ( ! obj . hasOwnProperty ( key ) ) {
383+ continue ;
384+ }
363385 var item = obj [ key ] ;
364386 if ( key === '$ref' && typeof item === 'string' ) {
365387 output [ item ] = null ;
@@ -471,13 +493,48 @@ Resolver.prototype.resolveInline = function (root, spec, property, resolutionTab
471493} ;
472494
473495Resolver . prototype . resolveTo = function ( root , property , resolutionTable , location ) {
496+ var sp , i ;
474497 var ref = property . $ref ;
475- if ( ref ) {
498+ var lroot = root ;
499+ if ( typeof ref !== 'undefined' ) {
476500 if ( ref . indexOf ( '#' ) >= 0 ) {
477- location = ref . split ( '#' ) [ 1 ] ;
501+ var parts = ref . split ( '#' ) ;
502+
503+ // #/definitions/foo
504+ // foo.json#/bar
505+ if ( parts [ 0 ] && ref . indexOf ( '/' ) === 0 ) {
506+
507+ }
508+ else if ( parts [ 0 ] && ref . indexOf ( 'http' ) === 0 ) {
509+
510+ }
511+ else if ( parts [ 0 ] && parts [ 0 ] . length > 0 ) {
512+ // relative file
513+ sp = root . split ( '/' ) ;
514+ lroot = '' ;
515+ for ( i = 0 ; i < sp . length - 1 ; i ++ ) {
516+ lroot += sp [ i ] + '/' ;
517+ }
518+ lroot += parts [ 0 ] ;
519+ }
520+ else {
521+
522+ }
523+
524+ location = parts [ 1 ] ;
525+ }
526+ else {
527+ // relative file
528+ sp = root . split ( '/' ) ;
529+ lroot = '' ;
530+ for ( i = 0 ; i < sp . length - 1 ; i ++ ) {
531+ lroot += sp [ i ] + '/' ;
532+ }
533+ lroot += ref ;
534+ location = '' ;
478535 }
479536 resolutionTable . push ( {
480- obj : property , resolveAs : 'ref' , root : root , key : ref , location : location
537+ obj : property , resolveAs : 'ref' , root : lroot , key : ref , location : location
481538 } ) ;
482539 } else if ( property . type === 'array' ) {
483540 var items = property . items ;
@@ -490,10 +547,12 @@ Resolver.prototype.resolveAllOf = function(spec, obj, depth) {
490547 obj = obj || spec ;
491548 var name ;
492549 for ( var key in obj ) {
493- if ( ! obj . hasOwnProperty ( key ) ) continue ;
550+ if ( ! obj . hasOwnProperty ( key ) ) {
551+ continue ;
552+ }
494553 var item = obj [ key ] ;
495554 if ( item === null ) {
496- throw new TypeError ( " Swagger 2.0 does not support null types (" + obj + " ). See https://github.com/swagger-api/swagger-spec/issues/229." )
555+ throw new TypeError ( ' Swagger 2.0 does not support null types (' + obj + ' ). See https://github.com/swagger-api/swagger-spec/issues/229.' ) ;
497556 }
498557 if ( typeof item === 'object' ) {
499558 this . resolveAllOf ( spec , item , depth + 1 ) ;
0 commit comments