From 0c1541c8a6c344e55c30014698f302b76c951b15 Mon Sep 17 00:00:00 2001 From: Roberto Huertas Date: Sun, 11 Jan 2026 12:37:05 +0100 Subject: [PATCH 1/5] updated thiserror --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 32a560f..ea0205e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,4 +21,4 @@ maintenance = { status = "actively-developed" } [dependencies] nom = "8.0.0" nom-language = "0.1.0" -thiserror = "2.0.11" +thiserror = "2.0.17" From 3e485bf449f9952701ba994cf1d98f558468c063 Mon Sep 17 00:00:00 2001 From: Roberto Huertas Date: Sun, 11 Jan 2026 12:37:27 +0100 Subject: [PATCH 2/5] 2024 edition --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ea0205e..cdc309e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = [ "Roberto Huertas ", "Riccardo Attilio Galli ", ] -edition = "2021" +edition = "2024" license = "MIT" repository = "https://github.com/robertohuertasm/yarn-lock-parser" readme = "README.md" From 58a25919318dec22f3149babf91777728c8d9381 Mon Sep 17 00:00:00 2001 From: Roberto Huertas Date: Sun, 11 Jan 2026 12:38:03 +0100 Subject: [PATCH 3/5] update version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index cdc309e..ce26b56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "yarn-lock-parser" description = "yarn.lock parser" -version = "0.12.0" +version = "0.13.0" authors = [ "Roberto Huertas ", "Riccardo Attilio Galli ", From ea50602c24626856c739df22fe9d3feb114458e5 Mon Sep 17 00:00:00 2001 From: Roberto Huertas Date: Sun, 11 Jan 2026 12:51:52 +0100 Subject: [PATCH 4/5] update readme --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bbaa4d4..25eb6e4 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,27 @@ # yarn-lock-parser -[![ActionsStatus](https://github.com/robertohuertasm/yarn-lock-parser/workflows/Build/badge.svg)](https://github.com/robertohuertasm/yarn-lock-parser/actions) [![Crates.io](https://img.shields.io/crates/v/yarn-lock-parser.svg)](https://crates.io/crates/yarn-lock-parser) +[![ActionsStatus](https://github.com/robertohuertasm/yarn-lock-parser/workflows/Build/badge.svg)](https://github.com/robertohuertasm/yarn-lock-parser/actions) [![Crates.io](https://img.shields.io/crates/v/yarn-lock-parser.svg)](https://crates.io/crates/yarn-lock-parser) [![Docs.rs](https://docs.rs/yarn-lock-parser/badge.svg)](https://docs.rs/yarn-lock-parser/) -Easily parse `yarn-lock` files (v1 and v2). +A fast and reliable parser for `yarn.lock` files written in Rust. Supports all yarn.lock versions (v1, v2, and later). Parse lock files into structured data for dependency analysis, validation, and programmatic access. -## Example +## Features + +- ✅ Supports all yarn.lock versions (v1, v2, and later) +- ✅ Fast and memory-efficient parsing using nom +- ✅ Comprehensive error handling with `thiserror` +- ✅ Zero-copy where possible +- ✅ Pure Rust implementation + +## Installation + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +yarn-lock-parser = "0.13" +``` + +## Quick Start ```rust use std::{error::Error, fs}; @@ -14,7 +31,9 @@ fn main() -> Result<(), Box> { let yarn_lock_text = fs::read_to_string("yarn.lock")?; let entries: Vec = parse_str(&yarn_lock_text)?; - println!("{:?}", entries); + for entry in entries { + println!("{:?}", entry); + } Ok(()) } @@ -22,18 +41,32 @@ fn main() -> Result<(), Box> { ## Documentation -Visit [https://docs.rs/yarn-lock-parser/](https://docs.rs/yarn-lock-parser/) +API documentation is available on [docs.rs](https://docs.rs/yarn-lock-parser/) + +## Development -## Build +### Requirements -You will need [cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html), the Rust package manager. +- [Rust](https://www.rust-lang.org/tools/install) (with `cargo`) + +### Build ```bash cargo build ``` -## Test +### Test ```bash cargo test ``` + +### Running Tests Verbosely + +```bash +cargo test -- --nocapture +``` + +## License + +MIT From cead8aee8458d0893c4cf439b8a6fd3063b5ecf8 Mon Sep 17 00:00:00 2001 From: Roberto Huertas Date: Sun, 11 Jan 2026 12:55:36 +0100 Subject: [PATCH 5/5] format --- src/lib.rs | 134 +++++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 66 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 22363cd..a329670 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,14 @@ use nom::{ + IResult, Parser, branch::alt, bytes::complete::{is_not, tag, take, take_till, take_until}, character::complete::{ digit1, line_ending, multispace0, not_line_ending, one_of, space0, space1, }, combinator::{cond, eof, map, map_res, opt, recognize}, - error::{context, ParseError}, - multi::{count, many0, many1, many_till, separated_list1}, + error::{ParseError, context}, + multi::{count, many_till, many0, many1, separated_list1}, sequence::{delimited, preceded, terminated}, - IResult, Parser, }; use nom_language::error::VerboseError; @@ -405,7 +405,7 @@ fn deps_meta_dep<'a>(input: &'a str, indent_top: &'a str) -> Res<&'a str, (&'a s return Err(nom::Err::Failure(VerboseError::from_error_kind( "bool property not 'true' or 'false'", nom::error::ErrorKind::Fail, - ))) + ))); } }) } @@ -970,20 +970,20 @@ __metadata: ); assert( - "\"@babel/code-frame@^7.0.0\":\n version \"7.12.13\"\n resolved \"https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658\"\n integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==\n dependencies:\n \"@babel/highlight\" \"^7.12.13\"\n\n", - Entry { - name: "@babel/code-frame", - version: "7.12.13", - resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658", - descriptors: vec![("@babel/code-frame", "^7.0.0")], - dependencies: vec![("@babel/highlight", "^7.12.13")], - integrity: "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - ..Default::default() - }, - ); + "\"@babel/code-frame@^7.0.0\":\n version \"7.12.13\"\n resolved \"https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658\"\n integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==\n dependencies:\n \"@babel/highlight\" \"^7.12.13\"\n\n", + Entry { + name: "@babel/code-frame", + version: "7.12.13", + resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658", + descriptors: vec![("@babel/code-frame", "^7.0.0")], + dependencies: vec![("@babel/highlight", "^7.12.13")], + integrity: "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + ..Default::default() + }, + ); assert( - r#""@babel/code-frame@^7.0.0": + r#""@babel/code-frame@^7.0.0": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== @@ -991,52 +991,52 @@ __metadata: "@babel/highlight" "^7.12.13" "#, - Entry { - name: "@babel/code-frame", - version: "7.12.13", - resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658", - descriptors: vec![("@babel/code-frame", "^7.0.0")], - dependencies: vec![("@babel/highlight", "^7.12.13")], - integrity: "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - ..Default::default() - }, - ); + Entry { + name: "@babel/code-frame", + version: "7.12.13", + resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658", + descriptors: vec![("@babel/code-frame", "^7.0.0")], + dependencies: vec![("@babel/highlight", "^7.12.13")], + integrity: "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + ..Default::default() + }, + ); // with final spaces assert( - r#""@babel/helper-validator-identifier@^7.12.11": + r#""@babel/helper-validator-identifier@^7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== "#, - Entry { - name: "@babel/helper-validator-identifier", - version: "7.12.11", - resolved: "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed", - descriptors: vec![("@babel/helper-validator-identifier", "^7.12.11")], - integrity: "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - ..Default::default() - }, - ); + Entry { + name: "@babel/helper-validator-identifier", + version: "7.12.11", + resolved: "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed", + descriptors: vec![("@babel/helper-validator-identifier", "^7.12.11")], + integrity: "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + ..Default::default() + }, + ); // without final spaces assert( - r#""@babel/helper-validator-identifier@^7.12.11": + r#""@babel/helper-validator-identifier@^7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== "#, - Entry { - name: "@babel/helper-validator-identifier", - version: "7.12.11", - resolved: "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed", - descriptors: vec![("@babel/helper-validator-identifier", "^7.12.11")], - integrity: "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - ..Default::default() - }, - ); + Entry { + name: "@babel/helper-validator-identifier", + version: "7.12.11", + resolved: "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed", + descriptors: vec![("@babel/helper-validator-identifier", "^7.12.11")], + integrity: "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + ..Default::default() + }, + ); } #[test] @@ -1075,7 +1075,7 @@ __metadata: // normal assert( - r#""@babel/code-frame@^7.0.0": + r#""@babel/code-frame@^7.0.0": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== @@ -1083,16 +1083,16 @@ __metadata: "@babel/highlight" "^7.12.13" "#, - Entry { - name: "@babel/code-frame", - version: "7.12.13", - resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658", - descriptors: vec![("@babel/code-frame", "^7.0.0")], - dependencies: vec![("@babel/highlight", "^7.12.13")], - integrity: "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - ..Default::default() - }, - ); + Entry { + name: "@babel/code-frame", + version: "7.12.13", + resolved: "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658", + descriptors: vec![("@babel/code-frame", "^7.0.0")], + dependencies: vec![("@babel/highlight", "^7.12.13")], + integrity: "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + ..Default::default() + }, + ); } #[test] @@ -1260,7 +1260,9 @@ __metadata: assert( r#" checksum: fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80 "#, - EntryItem::Integrity("fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80"), + EntryItem::Integrity( + "fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80", + ), ); } @@ -1441,14 +1443,14 @@ __metadata: ("set-cookie-parser", "^2.6.0"), ("turbo-stream", "2.4.0"), ], - peer_dependencies: vec![ - ("react", ">=18"), - ("react-dom", ">=18"), - ], - peer_dependencies_meta: vec![("react-dom", DepMeta { - optional: Some(true), - ..Default::default() - })], + peer_dependencies: vec![("react", ">=18"), ("react-dom", ">=18"),], + peer_dependencies_meta: vec![( + "react-dom", + DepMeta { + optional: Some(true), + ..Default::default() + } + )], ..Default::default() } );