@@ -45,15 +45,33 @@ 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 ) ;
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
+ } ) ;
49
67
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
68
var defs = keys . indexOf ( 'definitions' ) ;
53
69
if ( defs > 0 ) {
54
70
keys . splice ( 0 , 0 , keys . splice ( defs , 1 ) [ 0 ] ) ;
55
71
}
56
72
73
+ keys . sort ( ( a , b ) => a . length - b . length ) ;
74
+
57
75
keys . forEach ( function ( key ) {
58
76
var keyPath = Pointer . join ( path , key ) ;
59
77
var keyPathFromRoot = Pointer . join ( pathFromRoot , key ) ;
@@ -150,29 +168,43 @@ function remap (inventory) {
150
168
// Group & sort all the $ref pointers, so they're in the order that we need to dereference/remap them
151
169
inventory . sort ( function ( a , b ) {
152
170
if ( a . file !== b . file ) {
153
- return a . file < b . file ? - 1 : + 1 ; // Group all the $refs that point to the same file
171
+ // Group all the $refs that point to the same file
172
+ return a . file < b . file ? - 1 : + 1 ;
154
173
}
155
174
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
175
+ // Group all the $refs that point to the same part of the file
176
+ return a . hash < b . hash ? - 1 : + 1 ;
157
177
}
158
178
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
179
+ // If the $ref points to itself, then sort it higher than other $refs that point to this $ref
180
+ return a . circular ? - 1 : + 1 ;
160
181
}
161
182
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
183
+ // If the $ref extends the resolved value, then sort it lower than other $refs that don't extend the value
184
+ return a . extended ? + 1 : - 1 ;
163
185
}
164
186
else if ( a . indirections !== b . indirections ) {
165
- return a . indirections - b . indirections ; // Sort direct references higher than indirect references
187
+ // Sort direct references higher than indirect references
188
+ return a . indirections - b . indirections ;
166
189
}
167
190
else if ( a . depth !== b . depth ) {
168
- return a . depth - b . depth ; // Sort $refs by how close they are to the JSON Schema root
169
- }
170
- else if ( a . pathFromRoot . lastIndexOf ( '/definitions' ) === - 1 && b . pathFromRoot . lastIndexOf ( '/definitions' ) === - 1 ) {
171
- return a . pathFromRoot . localeCompare ( b . pathFromRoot ) ;
191
+ // Sort $refs by how close they are to the JSON Schema root
192
+ return a . depth - b . depth ;
172
193
}
173
194
else {
174
- // If all else is equal, use the $ref that's in the "definitions" property
175
- return b . pathFromRoot . lastIndexOf ( '/definitions' ) - a . pathFromRoot . lastIndexOf ( '/definitions' ) ;
195
+ // Determine how far each $ref is from the "definitions" property.
196
+ // Most people will expect references to be bundled into the the "definitions" property if possible.
197
+ var aDefinitionsIndex = a . pathFromRoot . lastIndexOf ( '/definitions' ) ;
198
+ var bDefinitionsIndex = b . pathFromRoot . lastIndexOf ( '/definitions' ) ;
199
+
200
+ if ( aDefinitionsIndex !== bDefinitionsIndex ) {
201
+ // Give higher priority to the $ref that's closer to the "definitions" property
202
+ return bDefinitionsIndex - aDefinitionsIndex ;
203
+ }
204
+ else {
205
+ // All else is equal, so use the shorter path, which will produce the shortest possible reference
206
+ return a . pathFromRoot . length - b . pathFromRoot . length ;
207
+ }
176
208
}
177
209
} ) ;
178
210
0 commit comments