Versions
A valid version is a version core with optional pre-release and build labels.
<valid semver> ::= <version core>
| <version core> "-" <pre-release>
| <version core> "+" <build>
| <version core> "-" <pre-release> "+" <build>
<version core> ::= <major> "." <minor> "." <patch>
<major> ::= <numeric identifier>
<minor> ::= <numeric identifier>
<patch> ::= <numeric identifier>
<pre-release> ::= <dot-separated pre-release identifiers>
<dot-separated pre-release identifiers> ::= <pre-release identifier>
| <pre-release identifier> "." <dot-separated pre-release identifiers>
<build> ::= <dot-separated build identifiers>
<dot-separated build identifiers> ::= <build identifier>
| <build identifier> "." <dot-separated build identifiers>
<pre-release identifier> ::= <alphanumeric identifier>
| <numeric identifier>
<build identifier> ::= <alphanumeric identifier>
| <digits>
<numeric identifier> ::= "0"
| <positive digit>
| <positive digit> <digits>
<positive digit> ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
The full leaf definitions (identifier characters, letters, digits) are in the downloadable file.
References & context
A version rarely travels alone. A reference pairs a version (or a range)
with the context it belongs to: the identity of a package,
module, image, crate or service. The context is optional and, when present, is separated
from the version by @. An ecosystem qualifies a context with a
source (source:name), so the same grammar names artifacts
anywhere: npm:react@18.2.0, pypi:flask@3.0.0,
gem:rails@7.1.3, golang:golang.org/x/text@0.14.0. A context
never contains whitespace and a
version never contains @, so the split is unambiguous.
<reference> ::= <valid semver>
| <context> "@" <valid semver>
<range reference> ::= <range set>
| <context> "@" <range set>
<context> ::= <name>
| <source> ":" <name>
<source> ::= <lowercase letter> ( <lowercase letter> | <digit> | "-" ) *
<name> ::= <name path>
| "@" <name path> ; scoped, e.g. @scope/pkg
<name path> ::= <name segment> ( "/" <name segment> ) *
<name segment> ::= <name character> +
<name character> ::= <letter> | <digit> | "-" | "." | "_"
Context is identity, not precedence: it never changes how versions order. It scopes a range to a Contextual Set, so npm:react@^1.2.3 admits only versions of npm:react.
Ranges
A range-set is one or more comparator sets joined by ||. Hyphen, x-range, tilde, caret and approximate forms desugar to primitive comparators.
<range set> ::= <range> ( <logical or> <range> ) *
<logical or> ::= ( " " ) * "||" ( " " ) *
<range> ::= <hyphen>
| <simple> ( " " <simple> ) *
| ""
<hyphen> ::= <partial> " - " <partial>
<simple> ::= <primitive>
| <partial>
| <tilde>
| <caret>
<primitive> ::= <operator> <partial>
<operator> ::= "<" | ">" | ">=" | "<=" | "="
<tilde> ::= "~" [ ">" ] <partial>
<caret> ::= "^" <partial>
<partial> ::= <xr> [ "." <xr> [ "." <xr> <qualifier> ? ] ]
<xr> ::= "x" | "X" | "*" | <numeric identifier>
<qualifier> ::= ( "-" <pre-release> ) ? ( "+" <build> ) ?
Comparators
A comparator is an operator and a version; a comparator set is the intersection of whitespace-joined comparators.
<comparator set> ::= <comparator> ( <whitespace> <comparator> ) *
<comparator> ::= <operator> <partial>
| <partial>
<operator> ::= "<" | ">" | ">=" | "<=" | "="
<whitespace> ::= ( " " ) +
<partial> ::= <xr> [ "." <xr> [ "." <xr> <qualifier> ? ] ]
<xr> ::= "x" | "X" | "*" | <numeric identifier>
<qualifier> ::= ( "-" <pre-release> ) ? ( "+" <build> ) ?
Reference parser
The semantic-versions package implements this grammar. It exposes
Version, Range, satisfies, compare,
valid, validRange and the usual comparison helpers, and is the
engine behind the range selector.
import { Range, satisfies, validRange } from "semantic-versions"
validRange("~>1.2") // ">=1.2.0 <1.3.0-0"
satisfies("1.4.0", "^1.2.3") // true
new Range("1.2.7 || >=1.2.9 <2.0.0").test("1.4.6") // true