33use indexmap:: IndexMap ;
44use serde_json:: Map ;
55use serde_json:: Value ;
6- use std:: cmp:: Ordering ;
76use std:: collections:: HashSet ;
87use std:: fmt;
98use std:: fmt:: Debug ;
109use thiserror:: Error ;
1110use url:: Url ;
1211
12+ use self :: merge:: code_unit_compare;
13+ use self :: merge:: MergeDiagnostic ;
14+
1315#[ cfg( feature = "ext" ) ]
1416pub mod ext;
17+ pub mod merge;
1518pub mod specifier;
1619
1720#[ derive( Debug , Clone , PartialEq , Eq ) ]
@@ -22,6 +25,7 @@ pub enum ImportMapDiagnostic {
2225 InvalidAddress ( String , String ) ,
2326 InvalidAddressNotString ( String , String ) ,
2427 InvalidTopLevelKey ( String ) ,
28+ Merge ( Box < MergeDiagnostic > ) ,
2529}
2630
2731impl fmt:: Display for ImportMapDiagnostic {
@@ -58,6 +62,9 @@ impl fmt::Display for ImportMapDiagnostic {
5862 ImportMapDiagnostic :: InvalidTopLevelKey ( key) => {
5963 write ! ( f, "Invalid top-level key \" {}\" . Only \" imports\" and \" scopes\" can be present." , key)
6064 }
65+ ImportMapDiagnostic :: Merge ( merge) => {
66+ write ! ( f, "Due to merge: {merge}" )
67+ }
6168 }
6269 }
6370}
@@ -130,6 +137,7 @@ struct SpecifierMapValue {
130137 raw_key : Option < String > ,
131138 /// The raw value if it differs from the actual value.
132139 raw_value : Option < String > ,
140+ /// None in case of block by null entry
133141 maybe_address : Option < Url > ,
134142}
135143
@@ -199,6 +207,7 @@ type SpecifierMapInner = IndexMap<String, SpecifierMapValue>;
199207
200208#[ derive( Debug , Clone ) ]
201209pub struct SpecifierMap {
210+ #[ deprecated = "import map base_url doesn't work with merged import maps" ]
202211 base_url : Url ,
203212 inner : SpecifierMapInner ,
204213}
@@ -221,6 +230,8 @@ impl SpecifierMap {
221230 } )
222231 }
223232
233+ #[ deprecated = "specifier map base_url doesn't work with merged import maps" ]
234+ #[ allow( deprecated) ]
224235 pub fn contains ( & self , key : & str ) -> bool {
225236 if let Ok ( key) = normalize_specifier_key ( key, & self . base_url ) {
226237 self . inner . contains_key ( & key)
@@ -229,6 +240,8 @@ impl SpecifierMap {
229240 }
230241 }
231242
243+ #[ deprecated = "specifier map base_url doesn't work with merged import maps" ]
244+ #[ allow( deprecated) ]
232245 pub fn append ( & mut self , key : String , value : String ) -> Result < ( ) , String > {
233246 let start_index = self
234247 . inner
@@ -280,12 +293,9 @@ impl SpecifierMap {
280293
281294 fn sort ( & mut self ) {
282295 // Sort in longest and alphabetical order.
283- self . inner . sort_by ( |k1, _v1, k2, _v2| match k1. cmp ( k2) {
284- Ordering :: Greater => Ordering :: Less ,
285- Ordering :: Less => Ordering :: Greater ,
286- // index map guarantees that there can't be duplicate keys
287- Ordering :: Equal => unreachable ! ( ) ,
288- } ) ;
296+ self
297+ . inner
298+ . sort_by ( |k1, _v1, k2, _v2| code_unit_compare ( k1, k2) . reverse ( ) ) ;
289299 }
290300}
291301
@@ -318,11 +328,27 @@ pub struct ImportMapWithDiagnostics {
318328 pub diagnostics : Vec < ImportMapDiagnostic > ,
319329}
320330
331+ impl ImportMapWithDiagnostics {
332+ pub fn merge ( & mut self , new : ImportMapWithDiagnostics ) {
333+ let mut merge_diagnostics = vec ! [ ] ;
334+ merge:: merge ( & mut self . import_map , new. import_map , & mut merge_diagnostics) ;
335+
336+ self . diagnostics . extend (
337+ merge_diagnostics
338+ . into_iter ( )
339+ . map ( Box :: new)
340+ . map ( ImportMapDiagnostic :: Merge ) ,
341+ ) ;
342+ // Should diagnostics ignored due to merge be dropped?
343+ self . diagnostics . extend ( new. diagnostics ) ;
344+ }
345+ }
346+
321347#[ derive( Default ) ]
322348pub struct ImportMapOptions {
323349 /// `(parsed_address, key, maybe_scope) -> new_address`
324350 #[ allow( clippy:: type_complexity) ]
325- pub address_hook : Option < Box < dyn ( Fn ( & str , & str , Option < & str > ) -> String ) > > ,
351+ pub address_hook : Option < Box < dyn Fn ( & str , & str , Option < & str > ) -> String > > ,
326352 /// Whether to expand imports in the import map.
327353 ///
328354 /// This functionality can be used to modify the import map
@@ -362,6 +388,7 @@ impl ResolveOptions {
362388
363389#[ derive( Debug , Clone , serde:: Serialize ) ]
364390pub struct ImportMap {
391+ #[ deprecated = "specifier map base_url doesn't work with merged import maps" ]
365392 #[ serde( skip) ]
366393 base_url : Url ,
367394
@@ -372,15 +399,19 @@ pub struct ImportMap {
372399impl ImportMap {
373400 pub fn new ( base_url : Url ) -> Self {
374401 Self {
402+ #[ allow( deprecated) ]
375403 base_url : base_url. clone ( ) ,
376404 imports : SpecifierMap {
405+ #[ allow( deprecated) ]
377406 base_url,
378407 inner : Default :: default ( ) ,
379408 } ,
380409 scopes : Default :: default ( ) ,
381410 }
382411 }
383412
413+ #[ deprecated = "import map base_url doesn't work with merged import maps" ]
414+ #[ allow( deprecated) ]
384415 pub fn base_url ( & self ) -> & Url {
385416 & self . base_url
386417 }
@@ -507,6 +538,8 @@ impl ImportMap {
507538 } )
508539 }
509540
541+ #[ deprecated = "import map base_url doesn't work with merged import maps" ]
542+ #[ allow( deprecated) ]
510543 pub fn get_or_append_scope_mut (
511544 & mut self ,
512545 key : & str ,
@@ -539,6 +572,7 @@ impl ImportMap {
539572 Some ( key. to_string ( ) )
540573 } ,
541574 imports : SpecifierMap {
575+ #[ allow( deprecated) ]
542576 base_url,
543577 inner : Default :: default ( ) ,
544578 } ,
@@ -645,6 +679,7 @@ pub fn parse_from_json_with_options(
645679 Ok ( ImportMapWithDiagnostics {
646680 diagnostics,
647681 import_map : ImportMap {
682+ #[ allow( deprecated) ]
648683 base_url,
649684 imports,
650685 scopes,
@@ -674,6 +709,7 @@ pub fn parse_from_value_with_options(
674709 Ok ( ImportMapWithDiagnostics {
675710 diagnostics,
676711 import_map : ImportMap {
712+ #[ allow( deprecated) ]
677713 base_url,
678714 imports,
679715 scopes,
@@ -891,15 +927,12 @@ fn parse_specifier_map(
891927 }
892928
893929 // Sort in longest and alphabetical order.
894- normalized_map. sort_by ( |k1, _v1, k2, _v2| match k1. cmp ( k2) {
895- Ordering :: Greater => Ordering :: Less ,
896- Ordering :: Less => Ordering :: Greater ,
897- // JSON guarantees that there can't be duplicate keys
898- Ordering :: Equal => unreachable ! ( ) ,
899- } ) ;
930+ normalized_map
931+ . sort_by ( |k1, _v1, k2, _v2| code_unit_compare ( k1, k2) . reverse ( ) ) ;
900932
901933 SpecifierMap {
902934 inner : normalized_map,
935+ #[ allow( deprecated) ]
903936 base_url : base_url. clone ( ) ,
904937 }
905938}
@@ -948,12 +981,8 @@ fn parse_scope_map(
948981 }
949982
950983 // Sort in longest and alphabetical order.
951- normalized_map. sort_by ( |k1, _v1, k2, _v2| match k1. cmp ( k2) {
952- Ordering :: Greater => Ordering :: Less ,
953- Ordering :: Less => Ordering :: Greater ,
954- // JSON guarantees that there can't be duplicate keys
955- Ordering :: Equal => unreachable ! ( ) ,
956- } ) ;
984+ normalized_map
985+ . sort_by ( |k1, _v1, k2, _v2| code_unit_compare ( k1, k2) . reverse ( ) ) ;
957986
958987 Ok ( normalized_map)
959988}
@@ -1179,6 +1208,7 @@ mod test {
11791208 } ,
11801209 ) ;
11811210 let specifiers = SpecifierMap {
1211+ #[ allow( deprecated) ]
11821212 base_url : Url :: parse ( "file:///" ) . unwrap ( ) ,
11831213 inner : specifiers,
11841214 } ;
@@ -1198,6 +1228,7 @@ mod test {
11981228 } ,
11991229 ) ;
12001230 let specifiers = SpecifierMap {
1231+ #[ allow( deprecated) ]
12011232 base_url : Url :: parse ( "file:///" ) . unwrap ( ) ,
12021233 inner : specifiers,
12031234 } ;
@@ -1224,6 +1255,7 @@ mod test {
12241255 } ,
12251256 ) ;
12261257 let specifiers = SpecifierMap {
1258+ #[ allow( deprecated) ]
12271259 base_url : Url :: parse ( "file:///" ) . unwrap ( ) ,
12281260 inner : specifiers,
12291261 } ;
0 commit comments