vers 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ae79cd7ee206fc3d6a786291f57f0c3fd55c37cb0db864c2eba049cfb820542c
4
+ data.tar.gz: dc8b996bcc1aad44e585eab361dc396bcd0b5b864d9cc287553c55c036bcbe01
5
+ SHA512:
6
+ metadata.gz: 1d9c6b0983644a8f52807a6dfa6d524f447c1856273bf6e86810c4c4f52767ebdd3c26bd77bc6ebff378f5147292b49d4636e9baed0576e1a1f2851dcd32248c
7
+ data.tar.gz: 0e7b47362f4f5ce6395d1785f92dcb21b71e737287d59547c95b11d0ed1b8c5979f5c80379df4a437c875d908639f72a2ce2a89ed4f74106faab5fffa4bab80f
data/CHANGELOG.md ADDED
@@ -0,0 +1,87 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2025-01-25
11
+
12
+ ### Added
13
+ - **JSON Test Dataset** (`test-suite-data.json`) with 37 comprehensive test cases for cross-language compatibility
14
+ - **Enhanced NPM Support**: X-ranges (`1.2.x`), OR logic (`||`), wildcard support, invalid range validation
15
+ - **Maven Union Ranges**: Complex multi-range support like `"[2.0,2.3.1] , [2.4.0,2.12.2) , [2.13.0,2.15.0)"`
16
+ - **Prerelease Version Handling**: Caret and hyphen ranges with prerelease versions
17
+ - **Specification Compliance Tests**: Automated test suite validating VERS spec compliance
18
+ - **Cross-Ecosystem Compatibility Tests**: Verify equivalent ranges work across package managers
19
+ - **Bidirectional Conversion Tests**: Ensure parsing and regenerating produces equivalent results
20
+ - **Enhanced Rake Tasks**:
21
+ - `rake spec:compliance` - Run VERS specification compliance test suite
22
+ - `rake spec:test_data` - Show JSON test dataset information
23
+ - **Comprehensive Error Handling**: Invalid ranges like `"blerg"` and `"git+https://..."` raise proper errors
24
+ - **Maven Malformed Range Validation**: Detect and reject invalid bracket notation like `"(1.0.0]"`
25
+
26
+ ### Enhanced
27
+ - **NPM Parser**: Added support for empty ranges, X-ranges, OR logic, and invalid range detection
28
+ - **Maven Parser**: Fixed union range parsing with proper bracket preservation
29
+ - **Test Coverage**: Expanded from 113 to 129 tests with 725 assertions, all passing
30
+ - **Documentation**: Added package manager syntax comparison table inspired by Eve Martin-Jones and Elitsa Bankova's presentation
31
+
32
+ ## [0.1.0] - 2025-01-25
33
+
34
+ ### Added
35
+
36
+ - **Initial release** of Vers Ruby gem for parsing, comparing and sorting versions according to the VERS specification
37
+ - **Mathematical interval model** for precise version range representation
38
+ - **Universal version range parsing** with support for 6 package ecosystems:
39
+ - npm (Node.js): Caret ranges (^1.2.3), tilde ranges (~1.2.3), hyphen ranges (1.2.3 - 2.3.4)
40
+ - gem (RubyGems): Pessimistic operator (~> 1.2), standard operators (>=, <=, etc.)
41
+ - pypi (Python): Comma-separated constraints (>=1.0,<2.0), exclusions (!=1.5.0)
42
+ - maven (Java): Bracket notation ([1.0,2.0], (1.0,2.0), [1.0,2.0))
43
+ - debian: Standard comparison operators (>=1.0.0, <<2.0.0)
44
+ - rpm: Standard comparison operators (>=1.0.0, <=2.0.0)
45
+ - **VERS URI format support** - parse and generate vers URI strings (e.g., `vers:npm/>=1.2.3|<2.0.0`)
46
+ - **Bidirectional conversion** between native package manager syntax and universal vers URI format
47
+ - **Set operations** on version ranges:
48
+ - Union: combine multiple version ranges
49
+ - Intersection: find overlapping versions
50
+ - Complement: find versions NOT in a range
51
+ - Exclusion: remove specific versions from ranges
52
+ - **Semantic versioning features** inspired by the semantic gem:
53
+ - Version increment methods (`increment_major`, `increment_minor`, `increment_patch`)
54
+ - Pessimistic constraint checking (`version.satisfies?("~> 1.2")`)
55
+ - Prerelease and build metadata support
56
+ - Version comparison and normalization
57
+ - **Comprehensive error handling** with detailed parsing exceptions
58
+ - **Core classes**:
59
+ - `Vers::Version` - semantic version parsing and comparison
60
+ - `Vers::Interval` - mathematical interval representation with bounds
61
+ - `Vers::VersionRange` - collection of intervals with set operations
62
+ - `Vers::Constraint` - individual version constraints (>=, <, etc.)
63
+ - `Vers::Parser` - extensible translation layer for package manager syntaxes
64
+ - **Complete test coverage** with 113 tests and 366 assertions
65
+ - **Comprehensive RDoc documentation** for all public APIs
66
+ - **Development tooling**:
67
+ - Rake tasks for specification validation and examples
68
+ - Security policy and contributing guidelines
69
+ - GitHub Actions-ready project structure
70
+
71
+ ### Documentation
72
+
73
+ - **README.md** with comprehensive usage examples and API documentation
74
+ - **CONTRIBUTING.md** with development guidelines and project structure
75
+ - **SECURITY.md** with vulnerability reporting procedures
76
+ - **VERSION-RANGE-SPEC.rst** - official VERS specification included in repository
77
+ - **RDoc documentation** for all classes and methods
78
+
79
+ ### Dependencies
80
+
81
+ - **Ruby 3.2+** required
82
+ - **No runtime dependencies** - pure Ruby implementation
83
+ - **Minitest** for testing (development dependency only)
84
+
85
+ [Unreleased]: https://github.com/andrew/vers/compare/v1.0.0...HEAD
86
+ [1.0.0]: https://github.com/andrew/vers/compare/v0.1.0...v1.0.0
87
+ [0.1.0]: https://github.com/andrew/vers/releases/tag/v0.1.0
@@ -0,0 +1,132 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or advances of
31
+ any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official email address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ [INSERT CONTACT METHOD].
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series of
86
+ actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or permanent
93
+ ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within the
113
+ community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.1, available at
119
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120
+
121
+ Community Impact Guidelines were inspired by
122
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
+
124
+ For answers to common questions about this code of conduct, see the FAQ at
125
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126
+ [https://www.contributor-covenant.org/translations][translations].
127
+
128
+ [homepage]: https://www.contributor-covenant.org
129
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130
+ [Mozilla CoC]: https://github.com/mozilla/diversity
131
+ [FAQ]: https://www.contributor-covenant.org/faq
132
+ [translations]: https://www.contributor-covenant.org/translations
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,194 @@
1
+ # Contributing to Vers
2
+
3
+ Thank you for your interest in contributing to the Vers Ruby library! This document provides guidelines and information for contributors.
4
+
5
+ ## Code of Conduct
6
+
7
+ This project and everyone participating in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
8
+
9
+ ## How to Contribute
10
+
11
+ ### Reporting Issues
12
+
13
+ Before creating an issue, please:
14
+ 1. Search existing issues to avoid duplicates
15
+ 2. Use the latest version of the gem
16
+ 3. Provide a clear, descriptive title
17
+ 4. Include steps to reproduce the issue
18
+ 5. Share relevant code examples or error messages
19
+
20
+ ### Suggesting Enhancements
21
+
22
+ Enhancement suggestions are welcome! Please:
23
+ 1. Check if the enhancement is already requested
24
+ 2. Explain the use case and expected behavior
25
+ 3. Consider if it fits the project's scope
26
+ 4. Be willing to help implement if accepted
27
+
28
+ ### Pull Requests
29
+
30
+ 1. **Fork** the repository
31
+ 2. **Create** a feature branch (`git checkout -b my-new-feature`)
32
+ 3. **Make** your changes following our coding standards
33
+ 4. **Add** tests for your changes
34
+ 5. **Ensure** all tests pass (`rake test`)
35
+ 6. **Run** the full test suite including any compliance tests
36
+ 7. **Commit** your changes with clear, descriptive messages
37
+ 8. **Push** to your branch (`git push origin my-new-feature`)
38
+ 9. **Create** a Pull Request with a clear description
39
+
40
+ ## Development Setup
41
+
42
+ ### Prerequisites
43
+
44
+ - Ruby 3.2 or higher
45
+ - Bundler gem
46
+
47
+ ### Setup
48
+
49
+ ```bash
50
+ git clone https://github.com/andrew/vers.git
51
+ cd vers
52
+ bundle install
53
+ ```
54
+
55
+ ### Running Tests
56
+
57
+ ```bash
58
+ # Run all tests
59
+ rake test
60
+
61
+ # Run tests with coverage
62
+ bundle exec rake test
63
+
64
+ # Show all available tasks
65
+ rake -T
66
+ ```
67
+
68
+ ### Coding Standards
69
+
70
+ - Follow Ruby best practices and conventions
71
+ - Use meaningful variable and method names
72
+ - Add RDoc documentation for public methods
73
+ - Keep methods focused and concise
74
+ - Follow the existing code style
75
+ - Use `frozen_string_literal: true` at the top of all files
76
+
77
+ ### Testing Requirements
78
+
79
+ All contributions must include appropriate tests:
80
+
81
+ - **Unit tests** for new functionality
82
+ - **Integration tests** for feature interactions
83
+ - **Edge case tests** for boundary conditions
84
+ - **Error handling tests** for exception cases
85
+
86
+ ### Documentation
87
+
88
+ - Update the README.md if adding new features
89
+ - Add RDoc documentation for complex methods
90
+ - Update CHANGELOG.md following the format
91
+ - Include examples in documentation
92
+
93
+ ## Project Structure
94
+
95
+ ```
96
+ ├── lib/
97
+ │ ├── vers.rb # Main module
98
+ │ └── vers/
99
+ │ ├── version.rb # Version class with semantic versioning
100
+ │ ├── interval.rb # Mathematical interval model
101
+ │ ├── version_range.rb # Version range operations
102
+ │ ├── constraint.rb # Individual version constraints
103
+ │ └── parser.rb # Package manager syntax parsers
104
+ ├── test/ # Test files
105
+ ├── VERSION-RANGE-SPEC.rst # Official specification
106
+ └── README.md # Project documentation
107
+ ```
108
+
109
+ ## Adding New Package Manager Support
110
+
111
+ To add support for a new package manager:
112
+
113
+ 1. **Add parser methods** to `lib/vers/parser.rb`
114
+ 2. **Include examples** in documentation
115
+ 3. **Add comprehensive tests** for the new syntax
116
+ 4. **Update README** with supported syntax examples
117
+ 5. **Verify** against VERS specification compliance
118
+
119
+ ## Version Range Operations
120
+
121
+ When working with version ranges:
122
+
123
+ 1. **Use interval model** for internal representation
124
+ 2. **Test set operations** (union, intersection, complement)
125
+ 3. **Verify mathematical correctness** of operations
126
+ 4. **Handle edge cases** like empty and unbounded ranges
127
+
128
+ ## VERS Specification Compliance
129
+
130
+ This library maintains compliance with the VERS specification:
131
+
132
+ - All changes must maintain specification compliance
133
+ - New features should align with the spec
134
+ - Report spec issues upstream when discovered
135
+ - Test against official specification examples
136
+
137
+ ## Release Process
138
+
139
+ Releases are handled by maintainers:
140
+
141
+ 1. Update version in `lib/vers/version.rb`
142
+ 2. Update `CHANGELOG.md` with changes
143
+ 3. Run full test suite
144
+ 4. Create release tag
145
+ 5. Publish to RubyGems
146
+
147
+ ## Getting Help
148
+
149
+ - **Issues**: Use GitHub issues for bugs and feature requests
150
+ - **Discussions**: Use GitHub discussions for questions
151
+ - **Security**: Follow our [Security Policy](SECURITY.md)
152
+
153
+ ## Recognition
154
+
155
+ Contributors will be recognized in:
156
+ - Git commit history
157
+ - CHANGELOG.md for significant contributions
158
+ - Project documentation where appropriate
159
+
160
+ ## License
161
+
162
+ By contributing to Vers, you agree that your contributions will be licensed under the [MIT License](LICENSE).
163
+
164
+ ## Development Philosophy
165
+
166
+ ### Mathematical Accuracy
167
+
168
+ Version ranges are implemented using mathematical interval theory:
169
+ - Intervals have clear bounds and inclusivity rules
170
+ - Set operations follow mathematical principles
171
+ - Edge cases are handled consistently
172
+
173
+ ### Extensibility
174
+
175
+ The architecture supports easy extension:
176
+ - New package managers can be added via parser methods
177
+ - Version comparison logic is centralized
178
+ - Testing framework supports new syntax validation
179
+
180
+ ### Performance
181
+
182
+ Consider performance implications:
183
+ - Avoid excessive regular expression backtracking
184
+ - Cache compiled patterns where appropriate
185
+ - Test with large version lists
186
+
187
+ ### Error Handling
188
+
189
+ Provide clear, actionable error messages:
190
+ - Include context about what failed
191
+ - Suggest corrections when possible
192
+ - Use specific exception types
193
+
194
+ Thank you for contributing to make Vers better for everyone!
data/README.md ADDED
@@ -0,0 +1,257 @@
1
+ # Vers - Version Range Parser for Ruby
2
+
3
+ A Ruby library for parsing, comparing and sorting versions according to the [VERS specification](https://github.com/package-url/purl-spec/blob/main/VERSION-RANGE-SPEC.rst).
4
+
5
+ This gem provides tools for working with version ranges across different package managers, using a mathematical interval model internally and supporting the vers specification from the Package URL (PURL) project.
6
+
7
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.2-red.svg)](https://www.ruby-lang.org/)
8
+ [![Gem Version](https://badge.fury.io/rb/vers.svg)](https://rubygems.org/gems/vers)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
+
11
+ **[Available on RubyGems](https://rubygems.org/gems/vers)** | **[API Documentation](https://rdoc.info/github/andrew/vers)** | **[GitHub Repository](https://github.com/andrew/vers)**
12
+
13
+ ## Features
14
+
15
+ - **Universal version range parsing** with support for 6 package ecosystems (npm, gem, pypi, maven, debian, rpm)
16
+ - **Mathematical interval model** for precise set operations (union, intersection, complement)
17
+ - **VERS specification compliance** with full support for the Package URL version range specification
18
+ - **Native syntax support** - parse native package manager syntax (^1.2.3, ~>1.0, >=1.0,<2.0, [1.0,2.0))
19
+ - **Bidirectional conversion** between native syntax and universal vers URI format
20
+ - **Semantic versioning features** - version increment, constraint checking, prerelease handling
21
+ - **Comprehensive error handling** with detailed parsing exceptions
22
+ - **100% test coverage** with 113 tests and 366 assertions
23
+
24
+ ## Installation
25
+
26
+ Add this line to your application's Gemfile:
27
+
28
+ ```ruby
29
+ gem 'vers'
30
+ ```
31
+
32
+ And then execute:
33
+
34
+ ```bash
35
+ bundle install
36
+ ```
37
+
38
+ Or install it yourself as:
39
+
40
+ ```bash
41
+ gem install vers
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ```ruby
47
+ require 'vers'
48
+
49
+ # Parse a vers URI
50
+ range = Vers.parse("vers:npm/>=1.2.3|<2.0.0")
51
+ range.contains?("1.5.0") # => true
52
+ range.contains?("2.1.0") # => false
53
+
54
+ # Parse native package manager syntax
55
+ npm_range = Vers.parse_native("^1.2.3", "npm")
56
+ gem_range = Vers.parse_native("~> 1.0", "gem")
57
+
58
+ # Check version containment
59
+ Vers.satisfies?("1.5.0", ">=1.0.0,<2.0.0") # => true
60
+
61
+ # Compare versions
62
+ Vers.compare("1.2.3", "1.2.4") # => -1
63
+
64
+ # Version operations
65
+ version = Vers::Version.new("1.2.3")
66
+ version.increment_major # => #<Vers::Version "2.0.0">
67
+ version.satisfies?("~> 1.2") # => true
68
+ ```
69
+
70
+ ## Supported Package Managers
71
+
72
+ - **npm**: Caret ranges (^1.2.3), tilde ranges (~1.2.3), hyphen ranges (1.2.3 - 2.3.4)
73
+ - **RubyGems**: Pessimistic operator (~> 1.2), standard operators (>=, <=, etc.)
74
+ - **PyPI**: Comma-separated constraints (>=1.0,<2.0)
75
+ - **Maven**: Bracket notation ([1.0,2.0], (1.0,2.0))
76
+ - **Debian/RPM**: Standard comparison operators
77
+
78
+ ## Mathematical Model
79
+
80
+ Internally, all version ranges are represented as mathematical intervals, similar to those used in mathematics:
81
+
82
+ - `[1.0.0, 2.0.0)` represents versions from 1.0.0 (inclusive) to 2.0.0 (exclusive)
83
+ - `(1.0.0, 2.0.0]` represents versions from 1.0.0 (exclusive) to 2.0.0 (inclusive)
84
+
85
+ This allows for precise set operations like union, intersection, and complement, regardless of the original package manager syntax.
86
+
87
+ ## Usage Examples
88
+
89
+ ### Basic Version Range Parsing
90
+
91
+ ```ruby
92
+ require 'vers'
93
+
94
+ # Parse vers URI format
95
+ range = Vers.parse("vers:npm/>=1.2.3|<2.0.0")
96
+ puts range.contains?("1.5.0") # => true
97
+ puts range.contains?("2.1.0") # => false
98
+
99
+ # Parse native package manager syntax
100
+ npm_range = Vers.parse_native("^1.2.3", "npm")
101
+ gem_range = Vers.parse_native("~> 1.0", "gem")
102
+ pypi_range = Vers.parse_native(">=1.0,<2.0", "pypi")
103
+ maven_range = Vers.parse_native("[1.0,2.0)", "maven")
104
+ ```
105
+
106
+ ### Creating Version Ranges
107
+
108
+ ```ruby
109
+ # Create exact version range
110
+ exact = Vers.exact("1.2.3")
111
+ puts exact.contains?("1.2.3") # => true
112
+ puts exact.contains?("1.2.4") # => false
113
+
114
+ # Create comparison ranges
115
+ greater = Vers.greater_than("1.0.0", inclusive: true)
116
+ less = Vers.less_than("2.0.0", inclusive: false)
117
+
118
+ # Create unbounded and empty ranges
119
+ all_versions = Vers.unbounded
120
+ no_versions = Vers.empty
121
+ ```
122
+
123
+ ### Converting Between Formats
124
+
125
+ ```ruby
126
+ # Parse native syntax and convert to vers URI
127
+ npm_range = Vers.parse_native("^1.2.3", "npm")
128
+ vers_string = Vers.to_vers_string(npm_range, "npm")
129
+ puts vers_string # => "vers:npm/>=1.2.3|<2.0.0"
130
+
131
+ # Parse vers URI and use in your application
132
+ range = Vers.parse("vers:gem/~>1.0")
133
+ puts range.contains?("1.5.0") # => true
134
+ ```
135
+
136
+ ### Set Operations on Version Ranges
137
+
138
+ ```ruby
139
+ range1 = Vers.parse("vers:npm/>=1.0.0|<2.0.0")
140
+ range2 = Vers.parse("vers:npm/>=1.5.0|<3.0.0")
141
+
142
+ # Union: versions in either range
143
+ union = range1.union(range2)
144
+ puts union.contains?("0.9.0") # => false
145
+ puts union.contains?("1.2.0") # => true
146
+ puts union.contains?("2.5.0") # => true
147
+
148
+ # Intersection: versions in both ranges
149
+ intersection = range1.intersect(range2)
150
+ puts intersection.contains?("1.2.0") # => false
151
+ puts intersection.contains?("1.7.0") # => true
152
+ puts intersection.contains?("2.5.0") # => false
153
+
154
+ # Complement: versions NOT in range
155
+ complement = range1.complement
156
+ puts complement.contains?("0.5.0") # => true
157
+ puts complement.contains?("1.5.0") # => false
158
+
159
+ # Exclusions: remove specific versions
160
+ excluded = range1.exclude("1.5.0")
161
+ puts excluded.contains?("1.4.0") # => true
162
+ puts excluded.contains?("1.5.0") # => false
163
+ puts excluded.contains?("1.6.0") # => true
164
+ ```
165
+
166
+ ### Version Comparison and Manipulation
167
+
168
+ ```ruby
169
+ version = Vers::Version.new("1.2.3-alpha.1+build.123")
170
+
171
+ # Access version components
172
+ puts version.major # => 1
173
+ puts version.minor # => 2
174
+ puts version.patch # => 3
175
+ puts version.prerelease # => "alpha.1"
176
+ puts version.build # => "build.123"
177
+
178
+ # Compare versions
179
+ puts Vers.compare("1.2.3", "1.2.4") # => -1
180
+ puts Vers.compare("2.0.0", "1.9.9") # => 1
181
+ puts Vers.compare("1.0.0", "1.0.0") # => 0
182
+
183
+ # Increment versions (returns new Version objects)
184
+ puts version.increment_major # => #<Vers::Version "2.0.0">
185
+ puts version.increment_minor # => #<Vers::Version "1.3.0">
186
+ puts version.increment_patch # => #<Vers::Version "1.2.4">
187
+
188
+ # Version properties
189
+ puts version.stable? # => false (has prerelease)
190
+ puts version.prerelease? # => true
191
+ puts version.to_h # => {major: 1, minor: 2, patch: 3, ...}
192
+ ```
193
+
194
+ ### Constraint Checking
195
+
196
+ ```ruby
197
+ version = Vers::Version.new("1.2.5")
198
+
199
+ # Pessimistic constraint checking (Ruby-style)
200
+ puts version.satisfies?("~> 1.2") # => true (>= 1.2.0, < 1.3.0)
201
+ puts version.satisfies?("~> 1.2.3") # => true (>= 1.2.3, < 1.3.0)
202
+ puts version.satisfies?("~> 1.3") # => false
203
+
204
+ # General satisfaction checking
205
+ puts Vers.satisfies?("1.5.0", "vers:npm/>=1.0.0|<2.0.0") # => true
206
+ puts Vers.satisfies?("1.5.0", "^1.2.3", "npm") # => true
207
+ ```
208
+
209
+ ## Specification Compliance
210
+
211
+ This gem implements the [PURL Version Range Specification](https://github.com/package-url/purl-spec/blob/main/VERSION-RANGE-SPEC.rst), providing a universal way to express version ranges across different software packaging ecosystems.
212
+
213
+ Learn more about the motivation and design behind VERS in the [presentation from Open Source Summit NA 2025](https://www.youtube.com/watch?v=EU-TodN27rM) ([slides PDF](https://static.sched.com/hosted_files/ossna2025/74/We%20need%20a%20standard%20for%20open%20source%20package%20requirements.pdf)) by Eve Martin-Jones and Elitsa Bankova. The following table from their talk shows how different package managers express the same version constraints:
214
+
215
+ | Operator | NPM | Cargo | Carthage | RubyGems | PyPI | Maven | NuGet |
216
+ |----------|-----|-------|----------|----------|------|-------|--------|
217
+ | **behavior with no op** | 1.0.0 | ^1.0.0⁴ | illegal | 1.0.0 | illegal | *⁵ | >=1.0 |
218
+ | **= ==** | =1.0 | = | == | = | == | [1.0]⁵ | [1.0]⁸ |
219
+ | **>** | > | > | | > | > | (1.0,) | (1.0,) |
220
+ | **>=** | >= | >= | >= | >= | >= | 1.0⁵ | 1.0⁷ᵇᵃ |
221
+ | **<** | < | < | | < | < | (,1.0) | (,1.0) |
222
+ | **<=** | <= | <= | | <= | <= | (,1.0] | (,1.0] |
223
+ | **!=** | | | | != | != | | |
224
+ | **^** | ^ | ^² | | | | | |
225
+ | **~** | ~, ~>¹ | ~ | | | ~= | | |
226
+ | **~>** | ¹ | | ~> | ~> | | | |
227
+ | **wildcards** | * x X | * x X | | | * | * | |
228
+ | **OR** | \|\| | | | | | , | |
229
+ | **AND** | space | , | | ,³ | , | | |
230
+ | **RANGE** | - | | | | | [,],(,)⁶ | [,],(,) |
231
+
232
+ This complexity across ecosystems is exactly why VERS provides a universal format that works consistently across all package managers.
233
+
234
+ ## Development
235
+
236
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
237
+
238
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
239
+
240
+ ## Contributing
241
+
242
+ Bug reports and pull requests are welcome on GitHub at https://github.com/andrew/vers. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/andrew/vers/blob/main/CODE_OF_CONDUCT.md).
243
+
244
+ ## Related Projects
245
+
246
+ - [purl](https://github.com/andrew/purl) - Ruby implementation of Package URL (PURL)
247
+ - [semantic_range](https://github.com/librariesio/semantic_range) - Semantic version parsing (JavaScript style)
248
+ - [univers](https://github.com/package-url/univers) - Python implementation of version ranges
249
+ - [versatile](https://github.com/package-url/versatile) - Java implementation of version ranges
250
+
251
+ ## License
252
+
253
+ The gem is available as open source under the terms of the MIT License.
254
+
255
+ ## Code of Conduct
256
+
257
+ Everyone interacting in the Vers project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/andrew/vers/blob/main/CODE_OF_CONDUCT.md).