@@ -46,13 +46,16 @@ pub enum Generator {
4646/// yarn.lock entry.
4747/// It only shows the name of the dependency and the version.
4848#[ derive( Debug , PartialEq , Eq , Default ) ]
49+ #[ non_exhaustive]
4950pub struct Entry < ' a > {
5051 pub name : & ' a str ,
5152 pub version : & ' a str ,
5253 pub resolved : & ' a str ,
5354 pub integrity : & ' a str ,
5455 pub dependencies : Vec < ( & ' a str , & ' a str ) > ,
5556 pub optional_dependencies : Vec < ( & ' a str , & ' a str ) > ,
57+ pub peer_dependencies : Vec < ( & ' a str , & ' a str ) > ,
58+ pub peer_dependencies_meta : Vec < ( & ' a str , PeerMeta ) > ,
5659 pub descriptors : Vec < ( & ' a str , & ' a str ) > ,
5760}
5861
@@ -190,6 +193,8 @@ enum EntryItem<'a> {
190193 Resolved ( & ' a str ) ,
191194 Dependencies ( Vec < ( & ' a str , & ' a str ) > ) ,
192195 OptionalDependencies ( Vec < ( & ' a str , & ' a str ) > ) ,
196+ PeerDependencies ( Vec < ( & ' a str , & ' a str ) > ) ,
197+ PeersMeta ( Vec < ( & ' a str , PeerMeta ) > ) ,
193198 Integrity ( & ' a str ) ,
194199 Unknown ( & ' a str ) ,
195200}
@@ -220,9 +225,9 @@ fn entry_item(input: &str) -> Res<&str, EntryItem<'_>> {
220225 alt ( (
221226 entry_version,
222227 parse_dependencies,
223- parse_optional_dependencies,
224228 integrity,
225229 entry_resolved,
230+ parse_peers_meta,
226231 unknown_line,
227232 ) )
228233 . parse ( input)
@@ -243,6 +248,8 @@ fn parse_entry(input: &str) -> Res<&str, Entry<'_>> {
243248 let mut resolved = "" ;
244249 let mut dependencies = Vec :: new ( ) ;
245250 let mut optional_dependencies = Vec :: new ( ) ;
251+ let mut peer_dependencies = Vec :: new ( ) ;
252+ let mut peer_dependencies_meta = Vec :: new ( ) ;
246253 let mut integrity = "" ;
247254
248255 for ei in entry_items {
@@ -251,7 +258,9 @@ fn parse_entry(input: &str) -> Res<&str, Entry<'_>> {
251258 EntryItem :: Resolved ( r) => resolved = r,
252259 EntryItem :: Dependencies ( d) => dependencies = d,
253260 EntryItem :: OptionalDependencies ( d) => optional_dependencies = d,
261+ EntryItem :: PeerDependencies ( d) => peer_dependencies = d,
254262 EntryItem :: Integrity ( c) => integrity = c,
263+ EntryItem :: PeersMeta ( m) => peer_dependencies_meta = m,
255264 EntryItem :: Unknown ( _) => ( ) ,
256265 }
257266 }
@@ -272,6 +281,8 @@ fn parse_entry(input: &str) -> Res<&str, Entry<'_>> {
272281 integrity,
273282 dependencies,
274283 optional_dependencies,
284+ peer_dependencies,
285+ peer_dependencies_meta,
275286 descriptors,
276287 } ,
277288 ) )
@@ -283,7 +294,16 @@ fn dependency_version(input: &str) -> Res<&str, &str> {
283294}
284295
285296fn parse_dependencies ( input : & str ) -> Res < & str , EntryItem < ' _ > > {
286- let ( input, ( indent, _, _) ) = ( space1, tag ( "dependencies:" ) , line_ending) . parse ( input) ?;
297+ let ( input, ( indent, key, _) ) = (
298+ space1,
299+ alt ( (
300+ tag ( "dependencies:" ) ,
301+ tag ( "optionalDependencies:" ) ,
302+ tag ( "peerDependencies:" ) ,
303+ ) ) ,
304+ line_ending,
305+ )
306+ . parse ( input) ?;
287307
288308 let dependencies_parser = many1 ( move |i| {
289309 (
@@ -300,29 +320,79 @@ fn parse_dependencies(input: &str) -> Res<&str, EntryItem<'_>> {
300320 } ) ;
301321 context ( "dependencies" , dependencies_parser)
302322 . parse ( input)
303- . map ( |( i, res) | ( i, EntryItem :: Dependencies ( res) ) )
323+ . map ( |( i, res) | {
324+ (
325+ i,
326+ match key {
327+ "dependencies:" => EntryItem :: Dependencies ( res) ,
328+ "optionalDependencies:" => EntryItem :: OptionalDependencies ( res) ,
329+ "peerDependencies:" => EntryItem :: PeerDependencies ( res) ,
330+ _ => unreachable ! ( ) ,
331+ } ,
332+ )
333+ } )
304334}
305335
306- fn parse_optional_dependencies ( input : & str ) -> Res < & str , EntryItem < ' _ > > {
307- let ( input, ( indent, _, _) ) =
308- ( space1, tag ( "optionalDependencies:" ) , line_ending) . parse ( input) ?;
336+ #[ derive( Debug , PartialEq , Eq , Default ) ]
337+ #[ non_exhaustive]
338+ pub struct PeerMeta {
339+ pub optional : Option < bool > ,
340+ }
309341
310- let optional_dependencies_parser = many1 ( move |i| {
311- (
312- tag ( indent) , // indented as much as the parent...
313- space1, // ... plus extra indentation
314- is_not ( ": " ) , // package name
315- one_of ( ": " ) ,
316- space0,
317- dependency_version, // version
318- alt ( ( line_ending, space0) ) , // newline or space
319- )
320- . parse ( i)
321- . map ( |( i, ( _, _, p, _, _, v, _) ) | ( i, ( p. trim_matches ( '"' ) , v) ) )
322- } ) ;
323- context ( "optionalDependencies" , optional_dependencies_parser)
342+ fn parse_peers_meta ( input : & str ) -> Res < & str , EntryItem < ' _ > > {
343+ let ( input, indent_top) = space1 ( input) ?;
344+ let ( input, _) = ( tag ( "peerDependenciesMeta:" ) , line_ending) . parse ( input) ?;
345+ many1 ( |i| peers_meta_dep ( i, indent_top) )
346+ . parse ( input)
347+ . map ( |( i, pm) | ( i, EntryItem :: PeersMeta ( pm) ) )
348+ }
349+
350+ fn peers_meta_dep < ' a > ( input : & ' a str , indent_top : & ' a str ) -> Res < & ' a str , ( & ' a str , PeerMeta ) > {
351+ let ( input, indent_dep) = recognize ( ( tag ( indent_top) , space1) ) . parse ( input) ?;
352+ let ( input, dep_name) = take_until ( ":" ) ( input) ?;
353+ let ( input, _) = ( tag ( ":" ) , line_ending) . parse ( input) ?;
354+ many1 ( |i| peers_meta_dep_prop ( i, indent_dep) )
324355 . parse ( input)
325- . map ( |( i, res) | ( i, EntryItem :: OptionalDependencies ( res) ) )
356+ . and_then ( |( i, props) | {
357+ let mut meta = PeerMeta { optional : None } ;
358+ for ( prop_key, prop_val) in props {
359+ #[ allow( clippy:: single_match) ]
360+ match prop_key {
361+ "optional" => {
362+ meta. optional = Some ( match prop_val {
363+ "true" => true ,
364+ "false" => false ,
365+ _ => {
366+ return Err ( nom:: Err :: Failure ( VerboseError :: from_error_kind (
367+ "bool property not 'true' or 'false'" ,
368+ nom:: error:: ErrorKind :: Fail ,
369+ ) ) )
370+ }
371+ } )
372+ }
373+ _ => { }
374+ }
375+ }
376+ Ok ( ( i, ( dep_name, meta) ) )
377+ } )
378+ }
379+
380+ fn peers_meta_dep_prop < ' a > (
381+ input : & ' a str ,
382+ indent_dep : & ' a str ,
383+ ) -> Res < & ' a str , ( & ' a str , & ' a str ) > {
384+ let ( input, _) = recognize ( ( tag ( indent_dep) , space1) ) . parse ( input) ?;
385+ let ( input, ( prop_key, _, prop_val) ) = (
386+ take_until ( ":" ) ,
387+ tag ( ": " ) ,
388+ map ( take_till_line_end, |v| {
389+ v. strip_suffix ( "\r \n " )
390+ . or_else ( || v. strip_suffix ( "\n " ) )
391+ . unwrap ( )
392+ } ) ,
393+ )
394+ . parse ( input) ?;
395+ Ok ( ( input, ( prop_key, prop_val) ) )
326396}
327397
328398/**
@@ -626,7 +696,8 @@ cli-table3@~0.6.1:
626696 descriptors : vec ! [ ( "cli-table3" , "~0.6.1" ) ] ,
627697 dependencies : vec ! [ ( "string-width" , "^4.2.0" ) ] ,
628698 optional_dependencies : vec ! [ ( "@colors/colors" , "1.5.0" ) ] ,
629- integrity : "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ=="
699+ integrity : "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==" ,
700+ ..Default :: default ( )
630701 } ,
631702 Entry {
632703 name : "@babel/helper-validator-identifier" ,
@@ -769,6 +840,7 @@ __metadata:
769840 resolved : "@babel/plugin-transform-for-of@npm:7.16.7" ,
770841 descriptors : vec ! [ ( "@babel/plugin-transform-for-of" , "npm:^7.12.1" ) ] ,
771842 dependencies : vec ! [ ( "@babel/helper-plugin-utils" , "^7.16.7" ) ] ,
843+ peer_dependencies : vec ! [ ( "@babel/core" , "^7.0.0-0" ) ] ,
772844 integrity : "35c9264ee4bef814818123d70afe8b2f0a85753a0a9dc7b73f93a71cadc5d7de852f1a3e300a7c69a491705805704611de1e2ccceb5686f7828d6bca2e5a7306" ,
773845 ..Default :: default ( )
774846 } ,
@@ -1183,12 +1255,20 @@ __metadata:
11831255 "# ,
11841256 EntryItem :: Dependencies ( vec ! [ ( "foo" , "1.0 || 2.0" ) , ( "bar" , "0.3-alpha1" ) ] ) ,
11851257 ) ;
1258+
1259+ assert (
1260+ r#" peerDependencies:
1261+ foo: 1.0 || 2.0
1262+ "bar": "0.3-alpha1"
1263+ "# ,
1264+ EntryItem :: PeerDependencies ( vec ! [ ( "foo" , "1.0 || 2.0" ) , ( "bar" , "0.3-alpha1" ) ] ) ,
1265+ ) ;
11861266 }
11871267
11881268 #[ test]
11891269 fn parse_optional_dependencies_work ( ) {
11901270 fn assert ( input : & str , expect : EntryItem ) {
1191- let res = parse_optional_dependencies ( input) . unwrap ( ) ;
1271+ let res = parse_dependencies ( input) . unwrap ( ) ;
11921272 assert_eq ! ( res. 1 , expect) ;
11931273 }
11941274
@@ -1270,17 +1350,49 @@ __metadata:
12701350 let res = parse_str ( & content) . unwrap ( ) ;
12711351
12721352 assert_eq ! (
1273- res. entries. last( ) . unwrap( ) ,
1274- & Entry {
1275- name: "node-semver" ,
1276- version: "7.6.3" ,
1277- resolved
: "ssh://[email protected] /npm/node-semver.git#0a12d6c7debb1dc82d8645c770e77c47bac5e1ea" , 1278- integrity: "" ,
1279- dependencies: vec![ ] ,
1280- descriptors: vec![ (
1281- "node-semver" ,
1282- "ssh://[email protected] /npm/node-semver.git#semver:^7.5.0" 1283- ) ] ,
1353+ res. entries. last( ) . unwrap( ) ,
1354+ & Entry {
1355+ name: "node-semver" ,
1356+ version: "7.6.3" ,
1357+ resolved
: "ssh://[email protected] /npm/node-semver.git#0a12d6c7debb1dc82d8645c770e77c47bac5e1ea" , 1358+ integrity: "" ,
1359+ dependencies: vec![ ] ,
1360+ descriptors: vec![ (
1361+ "node-semver" ,
1362+ "ssh://[email protected] /npm/node-semver.git#semver:^7.5.0" 1363+ ) ] ,
1364+ ..Default :: default ( )
1365+ }
1366+ ) ;
1367+ }
1368+
1369+ #[ test]
1370+ fn supports_peer_dependencies ( ) {
1371+ let content = std:: fs:: read_to_string ( "tests/peer_dependencies/yarn.lock" ) . unwrap ( ) ;
1372+ let res = parse_str ( & content) . unwrap ( ) ;
1373+
1374+ assert_eq ! (
1375+ res. entries[ 4 ] ,
1376+ Entry {
1377+ name: "react-router" ,
1378+ version: "7.2.0" ,
1379+ resolved: "react-router@npm:7.2.0" ,
1380+ descriptors: vec![ ( "react-router" , "npm:^7.2.0" ) ] ,
1381+ integrity: "05c79d86639f146aafc64351bb042acd785dbb69c7874ad8e0a3f5f3e70890b1b3ee07d0e18f8cebaffd62bca47e58d0645b07d1cc428a73ba449ce378cbef01" ,
1382+ dependencies: vec![
1383+ ( "@types/cookie" , "^0.6.0" ) ,
1384+ ( "cookie" , "^1.0.1" ) ,
1385+ ( "set-cookie-parser" , "^2.6.0" ) ,
1386+ ( "turbo-stream" , "2.4.0" ) ,
1387+ ] ,
1388+ peer_dependencies: vec![
1389+ ( "react" , ">=18" ) ,
1390+ ( "react-dom" , ">=18" ) ,
1391+ ] ,
1392+ peer_dependencies_meta: vec![ ( "react-dom" , PeerMeta {
1393+ optional: Some ( true ) ,
1394+ ..Default :: default ( )
1395+ } ) ] ,
12841396 ..Default :: default ( )
12851397 }
12861398 ) ;
0 commit comments