@@ -45,14 +45,25 @@ function crawl (parent, key, path, pathFromRoot, indirections, inventory, $refs,
45
45
inventory$Ref ( parent , key , path , pathFromRoot , indirections , inventory , $refs , options ) ;
46
46
}
47
47
else {
48
- var keys = Object . keys ( obj ) ;
49
-
50
- // Most people will expect references to be bundled into the the "definitions" property,
51
- // so we always crawl that property first, if it exists.
52
- var defs = keys . indexOf ( 'definitions' ) ;
53
- if ( defs > 0 ) {
54
- keys . splice ( 0 , 0 , keys . splice ( defs , 1 ) [ 0 ] ) ;
55
- }
48
+ // Crawl the object in a specific order that's optimized for bundling.
49
+ // This is important because it determines how `pathFromRoot` gets built,
50
+ // which later determines which keys get dereferenced and which ones get remapped
51
+ var keys = Object . keys ( obj )
52
+ . sort ( function ( a , b ) {
53
+ // Most people will expect references to be bundled into the the "definitions" property,
54
+ // so we always crawl that property first, if it exists.
55
+ if ( a === 'definitions' ) {
56
+ return - 1 ;
57
+ }
58
+ else if ( b === 'definitions' ) {
59
+ return 1 ;
60
+ }
61
+ else {
62
+ // Otherwise, crawl the keys based on their length.
63
+ // This produces the shortest possible bundled references
64
+ return a . length - b . length ;
65
+ }
66
+ } ) ;
56
67
57
68
keys . forEach ( function ( key ) {
58
69
var keyPath = Pointer . join ( path , key ) ;
@@ -150,26 +161,43 @@ function remap (inventory) {
150
161
// Group & sort all the $ref pointers, so they're in the order that we need to dereference/remap them
151
162
inventory . sort ( function ( a , b ) {
152
163
if ( a . file !== b . file ) {
153
- return a . file < b . file ? - 1 : + 1 ; // Group all the $refs that point to the same file
164
+ // Group all the $refs that point to the same file
165
+ return a . file < b . file ? - 1 : + 1 ;
154
166
}
155
167
else if ( a . hash !== b . hash ) {
156
- return a . hash < b . hash ? - 1 : + 1 ; // Group all the $refs that point to the same part of the file
168
+ // Group all the $refs that point to the same part of the file
169
+ return a . hash < b . hash ? - 1 : + 1 ;
157
170
}
158
171
else if ( a . circular !== b . circular ) {
159
- return a . circular ? - 1 : + 1 ; // If the $ref points to itself, then sort it higher than other $refs that point to this $ref
172
+ // If the $ref points to itself, then sort it higher than other $refs that point to this $ref
173
+ return a . circular ? - 1 : + 1 ;
160
174
}
161
175
else if ( a . extended !== b . extended ) {
162
- return a . extended ? + 1 : - 1 ; // If the $ref extends the resolved value, then sort it lower than other $refs that don't extend the value
176
+ // If the $ref extends the resolved value, then sort it lower than other $refs that don't extend the value
177
+ return a . extended ? + 1 : - 1 ;
163
178
}
164
179
else if ( a . indirections !== b . indirections ) {
165
- return a . indirections - b . indirections ; // Sort direct references higher than indirect references
180
+ // Sort direct references higher than indirect references
181
+ return a . indirections - b . indirections ;
166
182
}
167
183
else if ( a . depth !== b . depth ) {
168
- return a . depth - b . depth ; // Sort $refs by how close they are to the JSON Schema root
184
+ // Sort $refs by how close they are to the JSON Schema root
185
+ return a . depth - b . depth ;
169
186
}
170
187
else {
171
- // If all else is equal, use the $ref that's in the "definitions" property
172
- return b . pathFromRoot . lastIndexOf ( '/definitions' ) - a . pathFromRoot . lastIndexOf ( '/definitions' ) ;
188
+ // Determine how far each $ref is from the "definitions" property.
189
+ // Most people will expect references to be bundled into the the "definitions" property if possible.
190
+ var aDefinitionsIndex = a . pathFromRoot . lastIndexOf ( '/definitions' ) ;
191
+ var bDefinitionsIndex = b . pathFromRoot . lastIndexOf ( '/definitions' ) ;
192
+
193
+ if ( aDefinitionsIndex !== bDefinitionsIndex ) {
194
+ // Give higher priority to the $ref that's closer to the "definitions" property
195
+ return bDefinitionsIndex - aDefinitionsIndex ;
196
+ }
197
+ else {
198
+ // All else is equal, so use the shorter path, which will produce the shortest possible reference
199
+ return a . pathFromRoot . length - b . pathFromRoot . length ;
200
+ }
173
201
}
174
202
} ) ;
175
203
0 commit comments