diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Changelog and Acknowledgements
 
+## 2.1.0.1
+* Explicitly required `text` < 2.
+* Minor docs adjustments.
+
 ## 2.1.0
 * Replaced `Proxy :: Proxy info` with type applications in splices from
   `regex`/`_regex`.  This significantly shortens the splices, producing nicer
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -84,4 +84,4 @@
 PCRE2 is distributed under the [3-clause BSD](https://www.pcre.org/licence.txt) license.
 
 ## Main Author
-&copy;2020&ndash;2021 Shlomo Shuck
+&copy;2020&ndash;2022 Shlomo Shuck
diff --git a/pcre2.cabal b/pcre2.cabal
--- a/pcre2.cabal
+++ b/pcre2.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           pcre2
-version:        2.1.0
+version:        2.1.0.1
 synopsis:       Regular expressions via the PCRE2 C library (included)
 description:    Please see the README on GitHub at <https://github.com/sjshuck/hs-pcre2>
 category:       Text
@@ -147,7 +147,7 @@
     , microlens
     , mtl
     , template-haskell
-    , text
+    , text <2
   default-language: Haskell2010
 
 test-suite pcre2-test
@@ -167,7 +167,7 @@
     , mtl
     , pcre2
     , template-haskell
-    , text
+    , text <2
   default-language: Haskell2010
 
 benchmark pcre2-benchmarks
@@ -189,5 +189,5 @@
     , pcre2
     , regex-pcre-builtin
     , template-haskell
-    , text
+    , text <2
   default-language: Haskell2010
diff --git a/src/hs/Text/Regex/Pcre2.hs b/src/hs/Text/Regex/Pcre2.hs
--- a/src/hs/Text/Regex/Pcre2.hs
+++ b/src/hs/Text/Regex/Pcre2.hs
@@ -26,7 +26,7 @@
     Likewise, we do not require the user to know whether a PCRE2 option is to be
     applied at pattern compile time or match time.  Instead we fold all possible
     options into a single datatype, `Option`.  Most functions have vanilla and
-    configurable variants; the latter have \"@Opt@\" in the name and accept a
+    configurable variants; the latter have "@Opt@" in the name and accept a
     value of this type.
 
     Similar to how @head :: [a] -> a@ sacrifices totality for type simplicity,
@@ -34,15 +34,15 @@
     exceptions are typed (as `SomePcre2Exception`s); moreover, we offer Template
     Haskell facilities that can intercept some of these errors before the
     program is run.  (Failure to match is not considered a user error and is
-    represented in the types.)
+    represented by `Control.Applicative.empty`; see below.)
 
     [There's more than one way to do it](https://en.wikipedia.org/wiki/There's_more_than_one_way_to_do_it)
     with this library.  The choices between functions and traversals,
     poly-kinded `Captures` and plain lists, string literals and
     quasi-quotations, quasi-quoted expressions and quasi-quoted patterns...these
-    are left to the user.  She will observe that advanced features\' extra
+    are left to the user.  She will observe that advanced features' extra
     safety, power, and convenience entail additional language extensions,
-    cognitive overhead, and (for lenses) library dependencies, so it\'s really a
+    cognitive overhead, and (for lenses) library dependencies, so it's really a
     matter of finding the best trade-offs for her case.
 
     === __Definitions__
@@ -55,8 +55,8 @@
     [Regex]:  A function of the form @`Data.Text.Text` -> result@, where the
     argument is the subject.  It is \"compiled\" via partial application as
     discussed above.  (Lens users:  A regex has the more abstract form
-    @[Traversal\'](https://hackage.haskell.org/package/microlens/docs/Lens-Micro.html#t:Traversal-39-)
-    `Data.Text.Text` result@, but the concept is the same.)
+    @`Lens.Micro.Traversal'` `Data.Text.Text` result@, but the concept is the
+    same.)
 
     [Capture (or capture group)]:  Any substrings of the subject matched by the
     pattern, meaning the whole pattern and any parenthesized groupings.  The
@@ -80,7 +80,7 @@
 
     Each API function is designed such that, when a regex is obtained, the
     underlying C data generated from the pattern and any options is reused for
-    that regex\'s lifetime.  Care should be taken that the same regex is not
+    that regex's lifetime.  Care should be taken that the same regex is not
     recreated /ex nihilo/ and discarded for each new subject:
 
     > isEmptyOrHas2Digits :: Text -> Bool
@@ -100,7 +100,7 @@
     Note: Template Haskell regexes are immune from this problem and may be
     freely inlined; see below.
 
-    Also of note is the optimization that, for each capture that\'s more than
+    Also of note is the optimization that, for each capture that's more than
     half the length of the subject, a zero-copy `Data.Text.Text` is produced in
     constant time and space.  This can yield a large performance boost in many
     cases, for example when splitting lines into key-value pairs as in
@@ -154,11 +154,6 @@
     >>> :set -XTypeApplications
     >>> handle @SomePcre2Exception (\_ -> return Nothing) $ evaluate $ broken "foo"
     Nothing
-
-    Or simply select `IO` as the `Control.Applicative.Alternative` instance:
-
-    >>> handle @SomePcre2Exception (\_ -> return "broken") $ broken "foo"
-    "broken"
     -}
 
     -- ** Basic matching functions
@@ -227,7 +222,7 @@
     --
     -- * out-of-bounds indexing of a capture group list /(runtime error)/
     --
-    -- * out-of-bounds @ix@ing of a @Traversal\'@ target
+    -- * out-of-bounds `Lens.Micro.ix`ing of a `Lens.Micro.Traversal'` target
     -- /(spurious failure to match)/
     --
     -- * case expression containing a Haskell list pattern of the wrong length
diff --git a/src/hs/Text/Regex/Pcre2/Foreign.hs b/src/hs/Text/Regex/Pcre2/Foreign.hs
--- a/src/hs/Text/Regex/Pcre2/Foreign.hs
+++ b/src/hs/Text/Regex/Pcre2/Foreign.hs
@@ -15,16 +15,16 @@
 
 -- * Types
 
--- | \"The @UCHAR@ types define unsigned code units of the appropriate widths.
--- For example, @PCRE2_UCHAR16@ is usually defined as @uint16_t@.\"
+-- | "The @UCHAR@ types define unsigned code units of the appropriate widths.
+-- For example, @PCRE2_UCHAR16@ is usually defined as @uint16_t@."
 type PCRE2_UCHAR = CUShort
 
--- | \"The @SPTR@ types are constant pointers to the equivalent @UCHAR@ types,
--- that is, they are pointers to vectors of unsigned code units.\"
+-- | "The @SPTR@ types are constant pointers to the equivalent @UCHAR@ types,
+-- that is, they are pointers to vectors of unsigned code units."
 type PCRE2_SPTR = Ptr PCRE2_UCHAR
 
--- | \"...string lengths and offsets into strings of code units...are always of
--- type @PCRE2_SIZE@...currently always defined as @size_t@.\"
+-- | "...string lengths and offsets into strings of code units...are always of
+-- type @PCRE2_SIZE@...currently always defined as @size_t@."
 type PCRE2_SIZE = CSize
 
 -- ** Opaque types
@@ -92,7 +92,7 @@
 
 foreign import capi unsafe "pcre2.h" pcre2_set_compile_extra_options
     :: Ptr Pcre2_compile_context
-    -> CUInt -- ^ See \"Extra compile options\" below for possible bit flags.
+    -> CUInt -- ^ See "Extra compile options" below for possible bit flags.
     -> IO CInt
 
 foreign import capi unsafe "pcre2.h" pcre2_set_max_pattern_length
@@ -203,7 +203,7 @@
     :: PCRE2_SPTR
     -> PCRE2_SIZE -- ^ Can be zero-terminated.  See below.
     -> CUInt
-    -- ^ See \"Main compile options\" below for possible bit flags.
+    -- ^ See "Main compile options" below for possible bit flags.
     -> Ptr CInt
     -> Ptr PCRE2_SIZE
     -> Ptr Pcre2_compile_context
@@ -475,11 +475,11 @@
 constant ''CInt "ERROR_NULL"
 -- *** UTF-16-specific errors
 --
--- | \"Missing low surrogate at end of string\"
+-- | "Missing low surrogate at end of string"
 constant ''CInt "ERROR_UTF16_ERR1"
--- | \"Invalid low surrogate follows high surrogate\"
+-- | "Invalid low surrogate follows high surrogate"
 constant ''CInt "ERROR_UTF16_ERR2"
--- | \"Isolated low surrogate\"
+-- | "Isolated low surrogate"
 constant ''CInt "ERROR_UTF16_ERR3"
 
 -- * DFA matching
diff --git a/src/hs/Text/Regex/Pcre2/Foreign/TH.hs b/src/hs/Text/Regex/Pcre2/Foreign/TH.hs
--- a/src/hs/Text/Regex/Pcre2/Foreign/TH.hs
+++ b/src/hs/Text/Regex/Pcre2/Foreign/TH.hs
@@ -18,7 +18,7 @@
 
 {-
     For example,
-getter "callout_block" ''CUInt "version"
+getter "callout_block" [t| CUInt |] "version"
     will produce
 foreign import capi unsafe "getters.h" pcre2_callout_block_version
     :: Ptr Pcre2_callout_block
diff --git a/src/hs/Text/Regex/Pcre2/Internal.hs b/src/hs/Text/Regex/Pcre2/Internal.hs
--- a/src/hs/Text/Regex/Pcre2/Internal.hs
+++ b/src/hs/Text/Regex/Pcre2/Internal.hs
@@ -56,7 +56,7 @@
 bitOr :: (Foldable t, Bits a) => t a -> a
 bitOr = foldl' (.|.) zeroBits
 
--- | Like `lines`, but don\'t remove any characters.
+-- | Like `lines`, but don't remove any characters.
 unchompedLines :: String -> [String]
 unchompedLines s = case break (== '\n') s of
     (line,     _ : rest) -> (line ++ "\n") : unchompedLines rest
@@ -102,7 +102,7 @@
         & Text.takeWord16 offEnd
         & Text.dropWord16 off
 
--- | Slice a 'Text', copying if it\'s less than half of the original.  Note this
+-- | Slice a 'Text', copying if it's less than half of the original.  Note this
 -- is a lazy, pure operation.
 smartSlice :: Text -> Slice -> Text
 smartSlice text slice = fromMaybe Text.empty $ maybeSmartSlice text slice
@@ -205,8 +205,8 @@
 -- the behavior of regex compilation and execution.
 --
 -- All library functions that take options have the suffix @Opt@ in their names;
--- for each of them, there\'s also a non-@Opt@ convenience function that simply
--- has the (unexported) `mempty` option.  For many uses, options won\'t be
+-- for each of them, there's also a non-@Opt@ convenience function that simply
+-- has the (unexported) `mempty` option.  For many uses, options won't be
 -- needed.
 --
 -- Some options can be enabled by special character sequences in the pattern as
@@ -236,13 +236,13 @@
     -- @(*MARK:L\\(O\\)L)@.
     | Anchored -- ^ Equivalent to beginning pattern with @^@.
     | BadEscapeIsLiteral -- ^ Do not throw an error for unrecognized or
-    -- malformed escapes.  /\"This is a dangerous option.\"/
+    -- malformed escapes.  /"This is a dangerous option."/
     | Bsr Bsr -- ^ Override what @\\R@ matches (default given by `defaultBsr`).
     | Caseless -- ^ Case-insensitive match.  Equivalent to @(?i)@.
     | DepthLimit Word32 -- ^ Override maximum depth of nested backtracking
     -- (default given by `defaultDepthLimit`).  Equivalent to
     -- @(*LIMIT_DEPTH=@/number/@)@.
-    | DollarEndOnly -- ^ Don\'t match @$@ with a newline at the end of the
+    | DollarEndOnly -- ^ Don't match @$@ with a newline at the end of the
     -- subject.
     | DotAll -- ^ A dot also matches a (single-character) newline.  Equivalent
     -- to @(?s)@.
@@ -257,7 +257,7 @@
     -- hold backtracking information (default given by `defaultHeapLimit`).
     -- Equivalent to @(*LIMIT_HEAP=@/number/@)@.
     | Literal -- ^ Treat the pattern as a literal string.
-    | MatchLimit Word32 -- ^ Override maximum value of the main matching loop\'s
+    | MatchLimit Word32 -- ^ Override maximum value of the main matching loop's
     -- internal counter (default given by `defaultMatchLimit`), as a simple CPU
     -- throttle.  Equivalent to @(*LIMIT_MATCH=@/number/@)@.
     | MatchLine -- ^ Only match complete lines.  Equivalent to bracketing the
@@ -268,10 +268,10 @@
     -- beginning and end.  Equivalent to bracketing the pattern with
     -- @\\b(?:@/pattern/@)\\b@.
     | MaxPatternLength Word64 -- ^ Default is `maxBound`.
-    | Multiline -- ^ @^@ and @$@ mean \"beginning\/end of a line\" rather than
-    -- \"beginning\/end of the subject\".  Equivalent to @(?m)@.
+    | Multiline -- ^ @^@ and @$@ mean "beginning\/end of a line" rather than
+    -- "beginning\/end of the subject".  Equivalent to @(?m)@.
     | NeverBackslashC -- ^ Do not allow the unsafe @\\C@ sequence.
-    | NeverUcp -- ^ Don\'t count Unicode characters in some character classes
+    | NeverUcp -- ^ Don't count Unicode characters in some character classes
     -- such as @\\d@.  Overrides @(*UCP)@.
     | Newline Newline -- ^ Override what a newline is (default given by
     -- `defaultNewline`).  Equivalent to @(*CRLF)@ or similar.
@@ -284,8 +284,8 @@
     -- beginning of a pattern.
     | NotBol -- ^ First character of subject is not the __b__eginning __o__f
     -- __l__ine.  Only affects @^@.
-    | NotEmpty -- ^ The 0th capture doesn\'t match if it would be empty.
-    | NotEmptyAtStart -- ^ The 0th capture doesn\'t match if it would be empty
+    | NotEmpty -- ^ The 0th capture doesn't match if it would be empty.
+    | NotEmptyAtStart -- ^ The 0th capture doesn't match if it would be empty
     -- and at the beginning of the subject.
     | NotEol -- ^ End of subject is not the __e__nd __o__f __l__ine.  Only
     -- affects @$@.
@@ -308,9 +308,9 @@
     -- replacement instead of it within the subject.  With `SubGlobal`, all
     -- results are concatenated.
     | SubUnknownUnset -- ^ /Affects `subOpt`./  References in the replacement to
-    -- non-existent captures don\'t error but are treated as unset.
+    -- non-existent captures don't error but are treated as unset.
     | SubUnsetEmpty -- ^ /Affects `subOpt`./  References in the replacement to
-    -- unset captures don\'t error but are treated as empty.
+    -- unset captures don't error but are treated as empty.
     | Ucp -- ^ Count Unicode characters in some character classes such as @\\d@.
     -- Incompatible with `NeverUcp`.
     | Ungreedy -- ^ Invert the effect of @?@.  Without it, quantifiers are
@@ -360,7 +360,7 @@
 bsrToC BsrUnicode = pcre2_BSR_UNICODE
 bsrToC BsrAnyCrlf = pcre2_BSR_ANYCRLF
 
--- | What\'s considered a newline.
+-- | What's considered a newline.
 data Newline
     = NewlineCr      -- ^ @\\r@ only
     | NewlineLf      -- ^ @\\n@ only
@@ -393,7 +393,7 @@
 -- | Input for user-defined callouts.
 data CalloutInfo
     = CalloutInfo{
-        -- | The index of which callout point we\'re on.
+        -- | The index of which callout point we're on.
         calloutIndex :: CalloutIndex,
         -- | The captures that have been set so far.
         calloutCaptures :: NonEmpty (Maybe Text),
@@ -429,8 +429,8 @@
 -- | Input for user-defined substitution callouts.
 data SubCalloutInfo
     = SubCalloutInfo{
-        -- | The 1-based index of which substitution we\'re on.  Only goes past
-        -- 1 during global substitutions.
+        -- | The 1-based index of which substitution we're on.  Only goes past 1
+        -- during global substitutions.
         subCalloutSubsCount :: Int,
         -- | The captures that have been set so far.
         subCalloutCaptures :: NonEmpty (Maybe Text),
@@ -541,7 +541,7 @@
     unary ctor f x = [ctor $ \ctx -> withForeignPtr ctx applyAndCheck] where
         applyAndCheck ctxPtr = f ctxPtr x >>= check (== 0)
 
--- | Intermediate representation of options expressing what effect they\'ll have
+-- | Intermediate representation of options expressing what effect they'll have
 -- on which stage of regex compilation\/execution.  Also provide fake @Prism'@s.
 data AppliedOption
     = CompileOption !CUInt
@@ -1040,7 +1040,7 @@
 
 -- | A function that takes a C match result and extracts captures into a
 -- container.  We need to pass this effectful callback to `_gcaptures` because
--- of the latter\'s imperative loop that reuses the same @pcre2_match_data@
+-- of the latter's imperative loop that reuses the same @pcre2_match_data@
 -- block.
 --
 -- The container type is polymorphic and in practice carries a `Traversable`
@@ -1056,7 +1056,7 @@
 --   Template Haskell-generated @ViewPatterns@.
 type FromMatch t = Ptr Pcre2_match_data -> IO (t Slice)
 
--- | Read all specifically indexed captures\' offsets from match results.
+-- | Read all specifically indexed captures' offsets from match results.
 getWhitelistedSlices :: (Traversable t) => t Int -> FromMatch t
 getWhitelistedSlices whitelist matchDataPtr = do
     ovecPtr <- pcre2_get_ovector_pointer matchDataPtr
@@ -1067,11 +1067,11 @@
         <$> peekOvec (i * 2)
         <*> peekOvec (i * 2 + 1)
 
--- | Read just the 0th capture\'s offsets from match results.
+-- | Read just the 0th capture's offsets from match results.
 get0thSlice :: FromMatch Identity
 get0thSlice = getWhitelistedSlices $ Identity 0
 
--- | Read all captures\' offsets from match results.
+-- | Read all captures' offsets from match results.
 getAllSlices :: FromMatch NonEmpty
 getAllSlices matchDataPtr = do
     count <- fromIntegral <$> pcre2_get_ovector_count matchDataPtr
@@ -1157,7 +1157,7 @@
 --
 -- Substitution works in the following way:  If a capture is set such that the
 -- new `Text` is not equal to the old one, a substitution occurs, otherwise it
--- doesn\'t.  This matters in cases where a capture encloses another
+-- doesn't.  This matters in cases where a capture encloses another
 -- capture&#x2014;notably, /all/ parenthesized captures are enclosed by the 0th.
 --
 -- >>> threeAndMiddle = _captures ". (.) ."
@@ -1166,7 +1166,7 @@
 -- >>> "A A A" & threeAndMiddle .~ "A B A" :| ["A"]
 -- "A B A"
 --
--- Changing multiple overlapping captures won\'t do what you want and is
+-- Changing multiple overlapping captures won't do what you want and is
 -- unsupported.
 --
 -- Changing an unset capture is unsupported because the PCRE2 match API does not
@@ -1175,7 +1175,7 @@
 -- `SubUnknownUnset` and `SubUnsetEmpty`.)
 --
 -- If the list becomes longer for some reason, the extra elements are ignored.
--- If it\'s shortened, the absent elements are considered to be unchanged.
+-- If it's shortened, the absent elements are considered to be unchanged.
 --
 -- It's recommended that the list be modified capture-wise, using `ix`.
 --
@@ -1198,7 +1198,7 @@
 -- | Given a pattern, produce a traversal (0 or more targets) that focuses from
 -- a subject to the non-overlapping portions of it that match.
 --
--- @_match = `_captures` patt . ix 0@
+-- Equivalent to @`_captures` patt . `ix` 0@, but more efficient.
 _match :: Text -> Traversal' Text Text
 _match = _matchOpt mempty
 
@@ -1333,7 +1333,7 @@
 defaultParensLimit :: Int
 defaultParensLimit = fromIntegral $ getConfigNumeric pcre2_CONFIG_PARENSLIMIT
 
--- | Size in bytes of PCRE2\'s built-in character processing tables.
+-- | Size in bytes of PCRE2's built-in character processing tables.
 defaultTablesLength :: Int
 defaultTablesLength = fromIntegral $ getConfigNumeric pcre2_CONFIG_TABLES_LENGTH
 
diff --git a/src/hs/Text/Regex/Pcre2/TH.hs b/src/hs/Text/Regex/Pcre2/TH.hs
--- a/src/hs/Text/Regex/Pcre2/TH.hs
+++ b/src/hs/Text/Regex/Pcre2/TH.hs
@@ -46,18 +46,18 @@
 -- explicitly in a type signature is not supported&#x2014;the definition of
 -- `CapturesInfo` is not part of the public API and may change without warning.
 --
--- After obtaining `Captures` it\'s recommended to immediately consume them and
+-- After obtaining `Captures` it's recommended to immediately consume them and
 -- transform them into application-level data, to avoid leaking the types.
 newtype Captures (info :: CapturesInfo) = Captures (NonEmpty Text)
     deriving (Show {- ^ @since 2.0.4 -})
 
--- | The kind of `Captures`\'s @info@.  The first number is the total number of
+-- | The kind of `Captures`'s @info@.  The first number is the total number of
 -- parenthesized captures, and the list is a lookup table from capture names to
 -- numbers.
 type CapturesInfo = (Nat, [(Symbol, Nat)])
 
 -- | Look up the number of a capture at compile time, either by number or by
--- name.  Throw a helpful 'TypeError' if the index doesn\'t exist.
+-- name.  Throw a helpful 'TypeError' if the index doesn't exist.
 type family CaptNum (i :: k) (info :: CapturesInfo) :: Nat where
     CaptNum (num :: Nat) '(hi, _) = If (num `CmpNat` hi == 'GT)
         -- then
@@ -79,7 +79,7 @@
 -- The ugly type signature may be interpreted like this:  /Given some capture/
 -- /group index @i@ and some @info@ about a regex, ensure that index exists and/
 -- /is resolved to the number @num@ at compile time.  Then, at runtime, get a/
--- /capture group from a list of captures./
+-- /capture group (numbered @num@) from a list of (at least @num@) captures./
 --
 -- In practice the variable @i@ is specified by type application and the other
 -- variables are inferred.
@@ -98,7 +98,7 @@
 _capture = _Captures . singular (ix $ fromInteger $ natVal @num Proxy) where
     _Captures f (Captures cs) = Captures <$> f cs
 
--- | Unexported, top-level `IORef` that\'s created upon the first runtime
+-- | Unexported, top-level `IORef` that's created upon the first runtime
 -- evaluation of a Template Haskell `Matcher`.
 globalMatcherCache :: IORef (Map Text Matcher)
 globalMatcherCache = unsafePerformIO $ newIORef Map.empty
@@ -114,8 +114,7 @@
             let matcher = pureUserMatcher mempty patt
             in (Map.insert patt matcher cache, matcher)
 
--- | From options and pattern, determine parenthesized captures\' names in
--- order.
+-- | From options and pattern, determine parenthesized captures' names in order.
 predictCaptureNames :: Option -> Text -> IO [Maybe Text]
 predictCaptureNames option patt = do
     code <- evalStateT
@@ -124,7 +123,7 @@
 
     withForeignPtr code getCaptureNames
 
--- | Get parenthesized captures\' names in order.
+-- | Get parenthesized captures' names in order.
 getCaptureNames :: Ptr Pcre2_code -> IO [Maybe Text]
 getCaptureNames codePtr = do
     nameCount <- getCodeInfo @CUInt codePtr pcre2_INFO_NAMECOUNT
@@ -281,7 +280,8 @@
 
     quoteDec = const $ fail "regex: cannot produce declarations"}
 
--- | An optical variant of `regex`.  Can only be used as an expression.
+-- | An optical variant of `regex`\/a type-annotated variant of `_captures`. Can
+-- only be used as an expression.
 --
 -- @
 -- _regex :: String -> `Traversal'` Text (`Captures` info)
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -255,7 +255,7 @@
 broken :: (Alternative f) => Text -> f Text
 broken = match "*"
 
--- | @microlens@ doesn\'t have this yet as of 01/18/2022
+-- | @microlens@ doesn't have this yet as of 03/09/2022
 _Show :: (Read a, Show a) => Traversal' String a
 _Show f s = case reads s of
     [(x, "")] -> show <$> f x
