diff --git a/semver-range.cabal b/semver-range.cabal
--- a/semver-range.cabal
+++ b/semver-range.cabal
@@ -1,5 +1,5 @@
 name:                semver-range
-version:             0.1.0
+version:             0.1.1
 synopsis:            An implementation of semver and semantic version ranges.
 license:             MIT
 license-file:        LICENSE
diff --git a/src/Data/SemVer.hs b/src/Data/SemVer.hs
--- a/src/Data/SemVer.hs
+++ b/src/Data/SemVer.hs
@@ -64,6 +64,16 @@
 rangeReleaseTags :: SemVerRange -> [ReleaseTag]
 rangeReleaseTags = concatMap releaseTags . versionsOf
 
+-- | Get the range release tags if they're all the same; otherwise
+-- Nothing.
+sharedReleaseTags :: SemVerRange -> Maybe [ReleaseTag]
+sharedReleaseTags range = case map releaseTags $ versionsOf range of
+  [] -> Nothing -- shouldn't happen but in case
+  []:_ -> Nothing -- no release tags, so that seals it
+  tagList:otherLists
+    | all (== tagList) otherLists -> Just tagList
+    | otherwise -> Nothing
+
 -- | Satisfies any version.
 anyVersion :: SemVerRange
 anyVersion = Gt $ semver 0 0 0
@@ -92,18 +102,15 @@
 -- Note that there are special cases when there are release tags. For detauls
 -- see https://github.com/npm/node-semver#prerelease-tags.
 matches :: SemVerRange -> SemVer -> Bool
-matches range ver = case (rangeReleaseTags range, releaseTags ver) of
+matches range version = case (sharedReleaseTags range, releaseTags version) of
   -- This is the simple case, where neither the range nor the version has given
   -- any release tags. Then we can just do regular predicate calculus.
-  ([], []) -> matchesSimple range ver
-  -- If the version has release tags but the range doesn't, it's not a match.
-  ([], _) -> False
-  -- If the version has release tags but none of the comparators have the same
-  -- (major, minor, patch) tuples, it's not a match. For now, we're being even
-  -- more strict, saying that there has to be exactly one comparator as well.
-  (_, _) | tuplesOf range /= [toTuple ver] -> False
-  -- If they have the same tuples, we can compare the version tags.
-  (rTags, vTags) -> matchesTags range rTags vTags
+  (Nothing, []) -> matchesSimple range version
+  (Just rTags, vTags)
+    | rTags == vTags -> matchesSimple range version
+    | tuplesOf range /= [toTuple version] -> False
+    | otherwise -> matchesTags range rTags vTags
+  (_, _) -> False
 
 -- | Simple predicate calculus matching, doing AND and OR combination with
 -- numerical comparison.
diff --git a/src/Data/SemVer/Parser.hs b/src/Data/SemVer/Parser.hs
--- a/src/Data/SemVer/Parser.hs
+++ b/src/Data/SemVer/Parser.hs
@@ -3,7 +3,7 @@
 {-# LANGUAGE LambdaCase #-}
 module Data.SemVer.Parser (
     parseSemVer, parseSemVerRange, pSemVerRange, pSemVer,
-    fromHaskellVersion
+    fromHaskellVersion, matchText
   ) where
 
 import qualified Prelude as P
@@ -107,7 +107,7 @@
       tag = fmap pack $ many1 $ letter <|> digit <|> char '-'
   -- Versions can optionally start with the character 'v'
   optional (char 'v')
-  takeWhile isJust <$> sepBy1 bound (sstring ".") >>= \case
+  res <- takeWhile isJust <$> sepBy1 bound (sstring ".") >>= \case
     [] -> return Any
     [Just n] -> return $ One n
     [Just n, Just m] -> return $ Two n m
@@ -116,6 +116,7 @@
       tags <- tag `sepBy1` char '.'
       return $ Three n m o tags
     w -> unexpected ("Invalid version " ++ show w)
+  spaces *> return res
 
 -- | Parses a tilde range (~1.2.3).
 pTildeRange :: Parser Wildcard
@@ -143,3 +144,12 @@
   bad -> do
     let badVer = intercalate "." (map show bad)
     Left $ pack ("Not a SemVer version: " <> badVer)
+
+-- | Parses the first argument as a range and the second argument as a semver,
+-- and returns whether they match.
+matchText :: Text -> Text -> Either Text Bool
+matchText rangeTxt verTxt = case parseSemVerRange rangeTxt of
+  Left err -> Left ("Could not parse range: " <> pack (show err))
+  Right range -> case parseSemVer verTxt of
+    Left err -> Left ("Could not parse version: " <> pack (show err))
+    Right version -> Right $ matches range version
