diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md
index d0d7b49a220c7b8a1a59de7cb3c09087fa295a99..bec28a07a261bf2e90a1ec1d905a64dd298d15ef 100644
--- a/docs/usage/configuration-options.md
+++ b/docs/usage/configuration-options.md
@@ -1577,20 +1577,6 @@ Usually, each language or package manager has a specific type of "version scheme
 
 By exposing `versionScheme` to config, it allows you to override the default version scheme for a package manager if you really need. In most cases it would not be recommended, but there are some cases such as Docker or Gradle where versioning is not strictly defined and you may need to specify the versioning type per-package.
 
-For the `regex` `versionScheme`, will accept a regex string after a colon, for example:
-
-```json
-{
-  "versionScheme": "regex:^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)(?<prerelease>[^.-]+)?(-(?<compatibility>.*))?$"
-}
-```
-
-The valid capture groups for the `regex` `versionScheme` are:
-
-- `major`, `minor`, and `patch`: at least one of these must be provided. When determining whether a package has updated, these values will be compared in the standard semantic versioning fashion. If any of these fields are omitted, they will be treated as if they were `0` -- in this way, you can describe versioning schemes with up to three incrementing values.
-- `prerelease`: this value, if captured, will mark a given release as a prerelease (eg. unstable). If this value is captured and you have configured `"ignoreUnstable": true`, the given release will be skipped.
-- `compatibility`: this value defines the "build compatibility" of a given dependency. A proposed Renovate update will never change the specified compatibility value. For example, if you are pinning to `1.2.3-linux` (and `linux` is captured as the compatbility value), Renovate will not update you to `1.2.4-osx`.
-
 ## vulnerabilityAlerts
 
 Use this object to customise PRs that are raised when vulnerability alerts are detected (GitHub-only). For example, to configure custom labels and assignees:
diff --git a/lib/versioning/cargo/index.ts b/lib/versioning/cargo/index.ts
index aa21ac9c573afa3a5403197a90de4b34dac42f19..1d959ec210cdffd427cd2a4e0a3ff260388d1ec1 100644
--- a/lib/versioning/cargo/index.ts
+++ b/lib/versioning/cargo/index.ts
@@ -1,6 +1,13 @@
 import { api as npm } from '../npm';
 import { VersioningApi, NewValueConfig } from '../common';
 
+export const displayName = 'Cargo';
+export const urls = [
+  'https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html',
+];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 const isVersion = (input: string): string | boolean => npm.isVersion(input);
 
 function convertToCaret(item: string): string {
diff --git a/lib/versioning/cargo/readme.md b/lib/versioning/cargo/readme.md
index cadd50a919f7b48d2ea09b3a5265274f4fe70d24..37ce59d515b1a5a7845c81964f572206d1e90e80 100644
--- a/lib/versioning/cargo/readme.md
+++ b/lib/versioning/cargo/readme.md
@@ -1,31 +1,11 @@
-# Cargo versioning
-
-## Documentation and URLs
-
-https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
-
-## What type of versioning is used?
-
-Cargo uses [Semantic Versioning 2.0](https://semver.org).
-
-## Are ranges supported? How?
+Cargo versioning uses [Semantic Versioning 2.0](https://semver.org).
 
 Cargo supports ranges in a similar manner to npm, but not identical. The important differences are:
 
-##### Use of commas
+**Use of commas**
 
 Multiple version requirements can also be separated with a comma, e.g. `>= 1.2, < 1.5`. We interpret this to mean AND.
 
-##### No exact versions unless using equals =
+**No exact versions unless using equals =**
 
 In Cargo, `1.2.3` doesn't mean "exactly 1.2.3", it actually means `>=1.2.3 <2.0.0`. So this is like the equivalent of `^1.2.3` in npm.
-
-## Range Strategy support
-
-Cargo versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Add cargo2npm and npm2cargo functions to leverage existing npm semver logic
-- [x] Exact version support
-- [x] Range support
diff --git a/lib/versioning/composer/index.ts b/lib/versioning/composer/index.ts
index d1f7b686d3301e466902402b5de8c025bcc6b741..065007b3ac47a257b882eacdea71769bb7f971cc 100644
--- a/lib/versioning/composer/index.ts
+++ b/lib/versioning/composer/index.ts
@@ -3,6 +3,16 @@ import { logger } from '../../logger';
 import { api as npm } from '../npm';
 import { VersioningApi, NewValueConfig } from '../common';
 
+export const displayName = 'Composer';
+export const urls = [
+  'https://getcomposer.org/doc/articles/versions.md',
+  'https://packagist.org/packages/composer/semver',
+  'https://madewithlove.be/tilde-and-caret-constraints/',
+  'https://semver.mwl.be',
+];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 function padZeroes(input: string): string {
   const sections = input.split('.');
   while (sections.length < 3) {
diff --git a/lib/versioning/composer/readme.md b/lib/versioning/composer/readme.md
index f545f56c70773ae6948c16e3329c3f103af9e542..f47e656cba379469de19c838fbf249aa5e412430 100644
--- a/lib/versioning/composer/readme.md
+++ b/lib/versioning/composer/readme.md
@@ -1,18 +1,5 @@
-# Composer versioning
-
-## Documentation and URLs
-
-https://getcomposer.org/doc/articles/versions.md
-https://packagist.org/packages/composer/semver
-https://madewithlove.be/tilde-and-caret-constraints/
-https://semver.mwl.be
-
-## What type of versioning is used?
-
 Composer uses Semver-like versioning, however some package authors may use versions that are not completely valid, e.g. `1.2` instead of `1.2.0`.
 
-## Are ranges supported? How?
-
 Composer supports ranges in a similar manner to npm, but not identical. The main difference is with tilde ranges.
 
 Tilde ranges with "short" versions are different to npm. e.g.
@@ -20,13 +7,3 @@ Tilde ranges with "short" versions are different to npm. e.g.
 `~4` is equivalent to `^4` in npm
 `~4.1` is equivalent to `^4.1` in npm
 `~0.4` is equivalent to `>=0.4 <1` in npm
-
-## Range Strategy support
-
-Composer versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Add composer2npm and npm2composer functions to leverage existing npm semver logic
-- [x] Exact version support
-- [x] Range support
diff --git a/lib/versioning/docker/index.ts b/lib/versioning/docker/index.ts
index 62a6536f550705bcacb800c33118adf737cb6165..fd7ba544f220f84f5d19d9c2a19fef36ed0aef6f 100644
--- a/lib/versioning/docker/index.ts
+++ b/lib/versioning/docker/index.ts
@@ -1,6 +1,12 @@
 import * as generic from '../loose/generic';
 import { VersioningApi } from '../common';
 
+export const displayName = 'Docker';
+export const urls = [
+  'https://docs.docker.com/engine/reference/commandline/tag/',
+];
+export const supportsRanges = false;
+
 function parse(version: string): any {
   const versionPieces = version.replace(/^v/, '').split('-');
   const prefix = versionPieces.shift();
diff --git a/lib/versioning/docker/readme.md b/lib/versioning/docker/readme.md
index 21c5db074798e68812c861ec343039cc86e67402..35eb8194bfee1a653eb22b0f58c309fb91bb1eec 100644
--- a/lib/versioning/docker/readme.md
+++ b/lib/versioning/docker/readme.md
@@ -1,35 +1,15 @@
-# Docker versioning
+Docker doesn't really have _versioning_, instead it supports "tags" and these are usually used by Docker image authors as a form of versioning.
 
-## Documentation and URLs
+This Docker versioning implementation in Renovate is designed to handle the most common _conventions_ used in tagging images. In particular, it treats the text after the first hyphen as a type of platform/compatibility indicator.
 
-Docker doesn't really use _versioning_, but it supports "tags" and these are usually used by Docker image authors as a form of versioning.
+For example, many images include images with the "-alpine" suffix, e.g. the official `node` Docker image includes tags like `12.15.0-alpine` which is _not_ compatible with `12.15.0` or `12.15.0-stretch`. This means users only want/expect upgrades to `12.16.0-alpine` and not `12.16.0` or `12.16.0-stretch`.
 
-This "versioning" implementation is essentially a creation of Renovate to handle the default _conventions_ used in tagging most images. In particular, it treats the text after the first hyphen as a type of platform/compatibility indicator.
+Similarly, a user with `12.14` expects to be upgraded to `12.15` and not `12.15.0`.
 
-For example, many images include images with the "-alpine" suffix, e.g. the offical `node` Docker image includes tags like `8.14.0-alpine` which is _not_ compatible with `8.14.0` or `8.14.0-stretch`. This means users only want/expect upgrades to `8.15.0-alpine` and not `8.15.0` or `8.15.0-stretch`.
-
-Similarly, a user with `8.14` expects to be upgraded to `8.15` and not `8.15.0`.
-
-## What type of versioning is used?
+**What type of versioning is used?**
 
 It's pretty "wild west" for tagging and not always compliant with semver. Docker versioning in Renovate should do a best effort to accept and sort semver-like versions.
 
-## Are ranges supported? How?
-
-Yes and no. In theory, a tag of `8.15` should be like `>=8.15.0 <8.16.0`. In practice, there is nothing that enforces that the latest `8.15` code matches exactly with the latest `8.15.x` tag. e.g. `8.15` may not be the same as `8.15.0`, but it usually should be. Also, `8.15` is technically a version and not a range.
-
-## Range Strategy support
-
-We may be able to "pin" from range-like tags like `8.15` to semver-like tags like `8.15.0` but we should probably work out a way to compare the sha256 hashes before pinning.
-
-Otherwise, we can support "replace" strategy.
-
-"Bump" strategy and "extend" strategies are not applicable.
-
-## Implementation plan/status
+**Are ranges supported?**
 
-- [x] Compatibility check between tag suffixes
-- [x] Upgrade semver tags (e.g. `8.14.0` to `8.15.0`)
-- [x] Upgrade range-like tags (e.g. `8.14` to `8.15`)
-- [x] Allow non-semver-compatible leading zeroes, e.g. `16.04.0` to `16.04.1`
-- [x] Support getDigest for pinning and updating tag digests
+No. Although a tag like `12.15` might seem like it means `12.15.x`, it is a tag of its own and may or may not point to an of the available `12.15.x` tags, including `12.15.0`.
diff --git a/lib/versioning/git/index.ts b/lib/versioning/git/index.ts
index b545fc8a4427c02f7602f2bd2d94caa9e9fff939..acef8725a41e87048b13db2a8d65592674d9726f 100644
--- a/lib/versioning/git/index.ts
+++ b/lib/versioning/git/index.ts
@@ -1,6 +1,10 @@
 import * as generic from '../loose/generic';
 import { VersioningApi } from '../common';
 
+export const displayName = 'git';
+export const urls = ['https://git-scm.com/'];
+export const supportsRanges = false;
+
 const parse = (version: string): any => ({ release: [parseInt(version, 10)] });
 
 const isCompatible = (version: string, range: string): boolean => true;
diff --git a/lib/versioning/git/readme.md b/lib/versioning/git/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..4687ea83c9fc2ca2361fd19f68818f525bdd72f5
--- /dev/null
+++ b/lib/versioning/git/readme.md
@@ -0,0 +1 @@
+Renovate's git versioning is a kind of hack to support git submodule updating.
diff --git a/lib/versioning/hashicorp/index.ts b/lib/versioning/hashicorp/index.ts
index b60f42d8cc702c7c2f7218435ac67432c24904fb..31f28d683f29d9e32b4226973b875b63de0f6e61 100644
--- a/lib/versioning/hashicorp/index.ts
+++ b/lib/versioning/hashicorp/index.ts
@@ -1,6 +1,13 @@
 import { api as npm } from '../npm';
 import { VersioningApi, NewValueConfig } from '../common';
 
+export const displayName = 'Hashicorp';
+export const urls = [
+  'https://www.terraform.io/docs/configuration/terraform.html#specifying-a-required-terraform-version',
+];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 function hashicorp2npm(input: string): string {
   // The only case incompatible with semver is a "short" ~>, e.g. ~> 1.2
   return input.replace(/~>(\s*\d+\.\d+$)/, '^$1').replace(',', '');
diff --git a/lib/versioning/hashicorp/readme.md b/lib/versioning/hashicorp/readme.md
index cb1f1e560346108f86799b906ac469605508996a..238c5626b911a0de56c00f7f9cfa4122164c502b 100644
--- a/lib/versioning/hashicorp/readme.md
+++ b/lib/versioning/hashicorp/readme.md
@@ -1,25 +1,3 @@
-# Hashicorp versioning
+Hashicorp versioning syntax is used for Terraform.
 
-## Documentation and URLs
-
-https://www.terraform.io/docs/configuration/terraform.html#specifying-a-required-terraform-version
-
-This versioning syntax is used for Terraform only currently.
-
-## What type of versioning is used?
-
-Hashicorp uses [Semantic Versioning 2.0](https://semver.org).
-
-## Are ranges supported? How?
-
-Hashicorp supports a subset of npm's range syntax.
-
-## Range Strategy support
-
-Hashicorp versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Add hashicorp2npm functions to leverage existing npm semver logic
-- [x] Exact version support
-- [x] Range support
+It is based off [Semantic Versioning 2.0](https://semver.org) but with a subset of npm's range syntax.
diff --git a/lib/versioning/hex/index.ts b/lib/versioning/hex/index.ts
index b7a7894ee9a978cbdc7dad02671c25bc10185a39..a20d3c80cc2d3888a4a3ccf40106537c9fc27977 100644
--- a/lib/versioning/hex/index.ts
+++ b/lib/versioning/hex/index.ts
@@ -1,6 +1,11 @@
 import { api as npm } from '../npm';
 import { VersioningApi, NewValueConfig } from '../common';
 
+export const displayName = 'Hex';
+export const urls = ['https://hexdocs.pm/elixir/Version.html'];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 function hex2npm(input: string): string {
   return input
     .replace(/~>\s*(\d+\.\d+)$/, '^$1')
diff --git a/lib/versioning/hex/readme.md b/lib/versioning/hex/readme.md
index 23ee8f6ebae53d74261afbb284da0afb24ec8a15..154efd1f375b5b48b6c5aefcb044968ec884216b 100644
--- a/lib/versioning/hex/readme.md
+++ b/lib/versioning/hex/readme.md
@@ -1,25 +1 @@
-# Hex versioning
-
-## Documentation and URLs
-
-https://hexdocs.pm/elixir/Version.html#module-requirements
-
-This versioning syntax is used for Elixir and Erlang hex dependencies
-
-## What type of versioning is used?
-
-Hex versions are based on [Semantic Versioning 2.0](https://semver.org)
-
-## Are ranges supported? How?
-
-Hex supports a [subset of npm range syntax](https://hexdocs.pm/elixir/Version.html).
-
-## Range Strategy support
-
-Hex versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Add hex2npm functions to leverage existing npm semver logic
-- [x] Exact version support
-- [x] Range support
+Hex versioning syntax is used for Elixir and Erlang hex dependencies. It is based on [Semantic Versioning 2.0](https://semver.org) and supports a subset of npm's range syntax.
diff --git a/lib/versioning/ivy/index.ts b/lib/versioning/ivy/index.ts
index 7f273001e697c5073c3fc1cc8aa0744572e426c8..73efe931d36b795ccb703cde29fcce4edbd74068 100644
--- a/lib/versioning/ivy/index.ts
+++ b/lib/versioning/ivy/index.ts
@@ -7,6 +7,11 @@ import {
 } from './parse';
 import { VersioningApi } from '../common';
 
+export const displayName = 'Ivy';
+export const urls = ['https://ant.apache.org/ivy/'];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 const {
   equals,
   getMajor,
diff --git a/lib/versioning/loose/index.ts b/lib/versioning/loose/index.ts
index 2f2cf8b0c9103f7e2f38c39669f550eb16718156..8304481a5541c2393290f7b3b5d0185bfcd4d3b7 100644
--- a/lib/versioning/loose/index.ts
+++ b/lib/versioning/loose/index.ts
@@ -1,6 +1,10 @@
 import * as generic from './generic';
 import { VersioningApi } from '../common';
 
+export const displayName = 'Loose';
+export const urls = [];
+export const supportsRanges = false;
+
 const pattern = /^v?(\d+(?:\.\d+)*)(.*)$/;
 
 function parse(version: string): any {
diff --git a/lib/versioning/loose/readme.md b/lib/versioning/loose/readme.md
index 571a8c4fa7106156ac12054ef9de39e23b51bfef..c8620b9a9063291f2193c6ffad7c832d9e5abe7c 100644
--- a/lib/versioning/loose/readme.md
+++ b/lib/versioning/loose/readme.md
@@ -1,23 +1 @@
-# loose versioning
-
-This "loose" is specific for Renovate and created for instances where no strict versioning is in place. It works like semver if semver-compliant versions are suppolied, but otherwise is "best effort".
-
-## Documentation and URLs
-
-None
-
-## What type of versioning is used?
-
-None, but it's semver-like.
-
-## Are ranges supported? How?
-
-No
-
-## Range Strategy support
-
-No
-
-## Implementation plan/status
-
-- [x] Best effort parsing and sorting
+Renovate's "loose" versioning was created for cases where no strict versioning is in place. It works like semver if semver-compliant versions are supplied, but otherwise is "best effort". Essentially it just does its best to sort versions.
diff --git a/lib/versioning/maven/index.ts b/lib/versioning/maven/index.ts
index c1636d7f7600d6a11d9c162ed677dcbca9b4b313..8ea8d8148d7855a43ea46f091ee250866151f283 100644
--- a/lib/versioning/maven/index.ts
+++ b/lib/versioning/maven/index.ts
@@ -14,6 +14,15 @@ import {
 } from './compare';
 import { NewValueConfig, VersioningApi } from '../common';
 
+export const displayName = 'Maven';
+export const urls = [
+  'https://maven.apache.org/pom.html#Dependency_Version_Requirement_Specification',
+  'https://octopus.com/blog/maven-versioning-explained',
+  'https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html',
+];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 const equals = (a: string, b: string): boolean => compare(a, b) === 0;
 
 function matches(a: string, b: string): boolean {
diff --git a/lib/versioning/maven/readme.md b/lib/versioning/maven/readme.md
index 0ffb3427f40fb59035472c93cb130c0b40fd433b..a6d1c33d467881a5b5407ee21fd42c362dc03664 100644
--- a/lib/versioning/maven/readme.md
+++ b/lib/versioning/maven/readme.md
@@ -1,24 +1,3 @@
-# Maven versioning
+Maven versioning is similar to semver but also very different in places. It's specified by Maven itself.
 
-## Documentation and URLs
-
-https://maven.apache.org/pom.html#Dependency_Version_Requirement_Specification
-https://octopus.com/blog/maven-versioning-explained
-https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html
-
-## What type of versioning is used?
-
-Maven's versioning is similar to semver but also very different in places. It's specified by Maven itself.
-
-## Are ranges supported? How?
-
-Yes, Maven uses its own special syntax for ranges.
-
-## Range Strategy support
-
-npm versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Exact version support
-- [ ] Range support (#2986)
+Ranges are supported using Maven's special syntax.
diff --git a/lib/versioning/node/index.ts b/lib/versioning/node/index.ts
index c7ac9e9a5212c46367202f19ea3a43b39cd75cd3..028427786a1567e35970e6cf98d4270340c597c7 100644
--- a/lib/versioning/node/index.ts
+++ b/lib/versioning/node/index.ts
@@ -1,6 +1,10 @@
 import npm, { isVersion, isValid } from '../npm';
 import { NewValueConfig, VersioningApi } from '../common';
 
+export const displayName = 'Node.js';
+export const urls = [];
+export const supportsRanges = false;
+
 function getNewValue({
   currentValue,
   rangeStrategy,
diff --git a/lib/versioning/node/readme.md b/lib/versioning/node/readme.md
index 03a68d8f03815cfc6e79e47dde1993559deb4b1d..b53137c719d9951dae140f11b878a51a53204169 100644
--- a/lib/versioning/node/readme.md
+++ b/lib/versioning/node/readme.md
@@ -1,24 +1,3 @@
-# node versioning
+Renovate's Node.js versioning is a wrapper around npm's versioning, except that it makes sure to strip "v" prefixes from exact versions when replacing.
 
-This "node" versioning is nearly identical to npm's semver except that it makes sure to strip "v" prefixes from exact versions when replacing.
-
-## Documentation and URLs
-
-https://semver.org/
-
-## What type of versioning is used?
-
-Node.JS's versioning complies with [Semantic Versioning 2.0](https://semver.org).
-
-## Are ranges supported? How?
-
-Same as npm.
-
-## Range Strategy support
-
-Same as npm
-
-## Implementation plan/status
-
-- [x] Strip v prefix
-- [ ] Support Node.js-specific "stable" awareness
+It is planned to extend it one day to support "stability" awareness, because Node.js's version stability does not follow the SemVer approach.
diff --git a/lib/versioning/npm/index.ts b/lib/versioning/npm/index.ts
index f78579d9f1657ec1c1835fb2c54798ec82a298f8..06a52c3061107124da1dab97adb2dbcb8dd70a8b 100644
--- a/lib/versioning/npm/index.ts
+++ b/lib/versioning/npm/index.ts
@@ -3,6 +3,16 @@ import { is as isStable } from 'semver-stable';
 import { getNewValue } from './range';
 import { VersioningApi } from '../common';
 
+export const displayName = 'npm';
+export const urls = [
+  'https://semver.org/',
+  'https://www.npmjs.com/package/semver',
+  'https://docs.npmjs.com/about-semantic-versioning',
+  'https://semver.npmjs.com/',
+];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 const {
   compare: sortVersions,
   maxSatisfying: maxSatisfyingVersion,
diff --git a/lib/versioning/npm/readme.md b/lib/versioning/npm/readme.md
index 29abebfc71459dce19e782fba2d55f91f703a30b..2a65882fedd87530e4eb37270032271d50f78e68 100644
--- a/lib/versioning/npm/readme.md
+++ b/lib/versioning/npm/readme.md
@@ -1,25 +1,3 @@
-# npm versioning
+npm versioning is the most well known/widely-used implementation of [Semantic Versioning 2.0](https://semver.org).
 
-## Documentation and URLs
-
-https://semver.org/
-https://www.npmjs.com/package/semver
-https://docs.npmjs.com/about-semantic-versioning
-https://semver.npmjs.com/
-
-## What type of versioning is used?
-
-npm has the most well known/widely used implementation of [Semantic Versioning 2.0](https://semver.org).
-
-## Are ranges supported? How?
-
-npm's semver implementation supports a large number of range operators.
-
-## Range Strategy support
-
-npm versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Exact version support
-- [x] Range support
+It's important to understand that "npm" versioning scheme is not the same as "semver" versioning. SemVer's spec does not define ranges at all - so all range/constraint syntax in npm is npm-specific and not part of the spec.
diff --git a/lib/versioning/nuget/index.ts b/lib/versioning/nuget/index.ts
index 66a420fdd3afccd398342bac885b8da63a8bf80b..4769592cdb8f87dc3d5623a612acb048f068138e 100644
--- a/lib/versioning/nuget/index.ts
+++ b/lib/versioning/nuget/index.ts
@@ -1,6 +1,12 @@
 import * as generic from '../loose/generic';
 import { VersioningApi } from '../common';
 
+export const displayName = 'NuGet';
+export const urls = [
+  'https://docs.microsoft.com/en-us/nuget/concepts/package-versioning',
+];
+export const supportsRanges = false;
+
 const pattern = /^(\d+(?:\.\d+)*)(-[^+]+)?(\+.*)?$/;
 
 function parse(version: string): any {
diff --git a/lib/versioning/nuget/readme.md b/lib/versioning/nuget/readme.md
index 7ac1594e8187c8c0e2101e0f193cb90dc00dde7a..4e680039cccdae0f203d4afb600524e616dbe193 100644
--- a/lib/versioning/nuget/readme.md
+++ b/lib/versioning/nuget/readme.md
@@ -1,24 +1,5 @@
-# NuGet versioning
-
-## Documentation and URLs
-
-https://docs.microsoft.com/en-us/nuget/concepts/package-versioning
-
-The intention of this version scheme is to match as closely as possible the version comparison that NuGet itself uses.
-
-## What type of versioning is used?
+NuGet versioning matches as closely as possible to the version comparison that NuGet itself uses.
 
 NuGet supports SemVer 2.0.0, but permits versions with differing numbers of version parts.
 
-## Are ranges supported? How?
-
 Ranges are not yet supported by this version scheme, but they are defined in NuGet and could be supported in the future.
-
-## Range Strategy support
-
-Not yet implemented.
-
-## Implementation plan/status
-
-- [x] Best effort parsing and sorting
-- [ ] Range support
diff --git a/lib/versioning/pep440/index.ts b/lib/versioning/pep440/index.ts
index f0bf0b09f13affdf0595dfcc1466f71d61887caa..e7b700663ff889594d53dabf6281f5187d44afc4 100644
--- a/lib/versioning/pep440/index.ts
+++ b/lib/versioning/pep440/index.ts
@@ -3,6 +3,11 @@ import { filter } from '@renovate/pep440/lib/specifier';
 import { getNewValue } from './range';
 import { VersioningApi } from '../common';
 
+export const displayName = 'PEP440';
+export const urls = ['https://www.python.org/dev/peps/pep-0440/'];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 const {
   compare: sortVersions,
   satisfies: matches,
diff --git a/lib/versioning/pep440/readme.md b/lib/versioning/pep440/readme.md
index 04e96b5af184737bab36b5b1f9dd3ab7cdc08059..faf4822d0176a9bd248ea0cdd791b1105e0f34c9 100644
--- a/lib/versioning/pep440/readme.md
+++ b/lib/versioning/pep440/readme.md
@@ -1,22 +1,3 @@
-# PEP 440 versioning
+PEP 440 is defined as part of the Python project, and its versioning is independent of others such as SemVer.
 
-## Documentation and URLs
-
-https://www.python.org/dev/peps/pep-0440/
-
-## What type of versioning is used?
-
-PEP 440 is part of the Python project, and its versioning is independent of others such as semver.
-
-## Are ranges supported? How?
-
-Ranges are supported, with a proprietary syntax.
-
-## Range Strategy support
-
-PEP 440 versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Exact version support
-- [x] Range support
+Ranges are supported using the syntax defined as part of the PEP440 spec.
diff --git a/lib/versioning/poetry/index.ts b/lib/versioning/poetry/index.ts
index e6b77e9cddf17a3a5a2647c7f41355cc451f6c5f..3c976a54fb1cee37dba368462ce1827d7b03a928 100644
--- a/lib/versioning/poetry/index.ts
+++ b/lib/versioning/poetry/index.ts
@@ -3,6 +3,11 @@ import { major, minor } from 'semver';
 import { api as npm } from '../npm';
 import { NewValueConfig, VersioningApi } from '../common';
 
+export const displayName = 'Poetry';
+export const urls = ['https://python-poetry.org/docs/versions/'];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 function notEmpty(s: string): boolean {
   return s !== '';
 }
diff --git a/lib/versioning/poetry/readme.md b/lib/versioning/poetry/readme.md
index b51b84e3d44ae596cc5ee3feea4149c5523a77ae..efbeccdcbf3b3c910d6740d2ac53454ab70ec61f 100644
--- a/lib/versioning/poetry/readme.md
+++ b/lib/versioning/poetry/readme.md
@@ -1,27 +1,3 @@
-# Poetry versioning
+Poetry versioning is a little like a mix of PEP440 and SemVer.
 
-## Documentation and URLs
-
-https://poetry.eustace.io/docs/versions/
-
-## What type of versioning is used?
-
-Poetry uses [Semantic Versioning 2.0](https://semver.org).
-
-## Are ranges supported? How?
-
-Poetry supports ranges in a similar manner to npm, but not identical. The important differences are:
-
-##### Use of commas
-
-Multiple version requirements can be separated with a comma, e.g. `>= 1.2, < 1.5`. We interpret this to mean AND.
-
-## Range Strategy support
-
-Poetry versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Add poetry2npm and npm2poetry functions to leverage existing npm semver logic
-- [x] Exact version support
-- [x] Range support
+Currently Renovate's implementation is based off npm versioning, but it is being migrated to be based off PEP440 to be more compatible with Poetry's behaviour.
diff --git a/lib/versioning/regex/index.ts b/lib/versioning/regex/index.ts
index 78c69579b6b7e435de8b978e051b7fd6f4667466..1c937e9edb5d5f07b71dab82339666cae278fc96 100644
--- a/lib/versioning/regex/index.ts
+++ b/lib/versioning/regex/index.ts
@@ -4,6 +4,10 @@ import { GenericVersion, GenericVersioningApi } from '../loose/generic';
 import { regEx } from '../../util/regex';
 import { CONFIG_VALIDATION } from '../../constants/error-messages';
 
+export const displayName = 'Regular Expression';
+export const urls = [];
+export const supportsRanges = false;
+
 export interface RegExpVersion extends GenericVersion {
   /** prereleases are treated in the standard semver manner, if present */
   prerelease: string;
diff --git a/lib/versioning/regex/readme.md b/lib/versioning/regex/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..6b44b52b3527c7a7868ac079a76d05a81d205071
--- /dev/null
+++ b/lib/versioning/regex/readme.md
@@ -0,0 +1,36 @@
+Regular Expression Versioning is designed to be like a flexible fallback versioning approach is Renovate's other versioning schemes don't do the job.
+
+The `regex` scheme makes use of Regular Express capture groups. The valid capture groups for `regex` versioning are:
+
+- `major`, `minor`, and `patch`: at least one of these must be provided. When determining whether a package has updated, these values will be compared in the standard semantic versioning fashion. If any of these fields are omitted, they will be treated as if they were `0` -- in this way, you can describe versioning schemes with up to three incrementing values.
+- `prerelease`: this value, if captured, will mark a given release as a prerelease (eg. unstable). If this value is captured and you have configured `"ignoreUnstable": true`, the given release will be skipped.
+- `compatibility`: this value defines the "build compatibility" of a given dependency. A proposed Renovate update will never change the specified compatibility value. For example, if you are pinning to `1.2.3-linux` (and `linux` is captured as the compatbility value), Renovate will not update you to `1.2.4-osx`.
+
+The compatibility concept was originally introduced for Docker versioning but sometimes package authors may use/misuse suffixes to mean compatibility in other versioning schemes.
+
+Here is an example of using `regex` versioning to correct behavior of the `guava` Maven package, which misuses suffixes as compatibility indicators:
+
+```json
+{
+  "packageRules": [
+    {
+      "packageNames": ["com.google.guava:guava"],
+      "versionScheme": "regex:^(?<major>\\d+)(\\.(?<minor>\\d+))?(\\.(?<patch>\\d+))?(-(?<compatibility>.*))?$"
+    }
+  ]
+}
+```
+
+Here is another example, this time for handling `python` Docker images, which use both pre-release indicators as well as version suffixes for compatibility:
+
+```json
+{
+  "packageRules": [
+    {
+      "datasources": ["docker"],
+      "packageNames": ["python"],
+      "versionScheme": "regex:^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)(?<prerelease>[^.-]+)?(-(?<compatibility>.*))?$"
+    }
+  ]
+}
+```
diff --git a/lib/versioning/ruby/index.ts b/lib/versioning/ruby/index.ts
index 0d4b4b3f89fdc0a7f63df6dade7bc107b6fc5922..cb549aaca95183cc939dcb67eb118bf43728f743 100644
--- a/lib/versioning/ruby/index.ts
+++ b/lib/versioning/ruby/index.ts
@@ -13,6 +13,15 @@ import { parse as parseRange, ltr } from './range';
 import { isSingleOperator, isValidOperator } from './operator';
 import { pin, bump, replace } from './strategies';
 
+export const displayName = 'Ruby';
+export const urls = [
+  'https://guides.rubygems.org/patterns/',
+  'https://bundler.io/v1.5/gemfile.html',
+  'https://www.devalot.com/articles/2012/04/gem-versions.html',
+];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 function vtrim<T = unknown>(version: T): string | T {
   if (typeof version === 'string') return version.replace(/^v/, '');
   return version;
diff --git a/lib/versioning/ruby/readme.md b/lib/versioning/ruby/readme.md
index 3a33a0cb683e53392df985ae95ca27bc5e390721..eca194c56569efd16d1cfe7e5bb80e5a00162bad 100644
--- a/lib/versioning/ruby/readme.md
+++ b/lib/versioning/ruby/readme.md
@@ -1,24 +1,3 @@
-# Ruby versioning
-
-## Documentation and URLs
-
-https://guides.rubygems.org/patterns/
-https://bundler.io/v1.5/gemfile.html
-https://www.devalot.com/articles/2012/04/gem-versions.html
-
-## What type of versioning is used?
-
-> The RubyGems team urges gem developers to follow the Semantic Versioning standard for their gem’s versions.
-
-## Are ranges supported? How?
+The RubyGems team urges gem developers to follow the Semantic Versioning standard for their gem’s versions, but it is not enforced.
 
 Range syntax is similar to npm's but not identical. The main difference is the use of "pessimistic" greater than or equals: `~>`
-
-## Range Strategy support
-
-Ruby versioning should support all range strategies - pin, replace, bump, extend.
-
-## Implementation plan/status
-
-- [x] Exact version support
-- [x] Range support
diff --git a/lib/versioning/semver/index.ts b/lib/versioning/semver/index.ts
index 389d81b4e556ed5aaadb276e2933bdb735f08fc2..c93d263dac6fd588d6ceff2d32d636ec4002ef4e 100644
--- a/lib/versioning/semver/index.ts
+++ b/lib/versioning/semver/index.ts
@@ -2,6 +2,10 @@ import semver from 'semver';
 import stable from 'semver-stable';
 import { NewValueConfig, VersioningApi } from '../common';
 
+export const displayName = 'Semantic';
+export const urls = ['https://semver.org/'];
+export const supportsRanges = false;
+
 const { is: isStable } = stable;
 
 const {
diff --git a/lib/versioning/semver/readme.md b/lib/versioning/semver/readme.md
index bd3388edc530fda0da331732343277f0978f0cc9..7b79556644138bb4d3e4c0da7f15aca85b8332eb 100644
--- a/lib/versioning/semver/readme.md
+++ b/lib/versioning/semver/readme.md
@@ -1,21 +1,3 @@
-# Semver versioning
+Renovate's Semantic Versioning is a strict/independent implementation of [Semantic Versioning 2.0](https://semver.org). It has been developed to be used in situations where exact-only semver support is needed and not npm's extended semver implementation including ranges.
 
-## Documentation and URLs
-
-https://semver.org/
-
-## What type of versioning is used?
-
-This is a strict/independent implementation of [Semantic Versioning 2.0](https://semver.org). It has been developed to be used in situations where exact-only semver support is needed and not npm's extended semver implementation including ranges.
-
-## Are ranges supported? How?
-
-Semver deliberately doesn't support any ranges, as per the spec
-
-## Range Strategy support
-
-Not applicable
-
-## Implementation plan/status
-
-- [x] Exact version support
+Ranges are not supported, as per the specification.
diff --git a/lib/versioning/swift/index.ts b/lib/versioning/swift/index.ts
index 61b583bb71209c3e669ee8d48d20e4f0c8174205..e7e06022151fb5c9a6d36af970a5e483bbedb79c 100644
--- a/lib/versioning/swift/index.ts
+++ b/lib/versioning/swift/index.ts
@@ -3,6 +3,11 @@ import stable from 'semver-stable';
 import { toSemverRange, getNewValue } from './range';
 import { VersioningApi } from '../common';
 
+export const displayName = 'Swift';
+export const urls = ['https://swift.org/package-manager/'];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];
+
 const { is: isStable } = stable;
 
 const {
diff --git a/lib/versioning/swift/readme.md b/lib/versioning/swift/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..9da29917c6c6bf82cf10d6000de3dc6401459e87
--- /dev/null
+++ b/lib/versioning/swift/readme.md
@@ -0,0 +1 @@
+Swift versioning was developed to support the Swift Package Manager. It's based on Semantic versioning but includes its own concept of ranges.
diff --git a/test/versioning/versioning-readmes.spec.ts b/test/versioning/versioning-readmes.spec.ts
index 4d7afafe337f1e6233562d7326f8377af8a9d5f2..35b0d717f90f3df08c26296e334732df7652c150 100644
--- a/test/versioning/versioning-readmes.spec.ts
+++ b/test/versioning/versioning-readmes.spec.ts
@@ -1,11 +1,10 @@
 import { readdir, readFile } from 'fs-extra';
 
-describe('versioning readmes', () => {
-  it('has same questions for all version schemes', async () => {
+describe('versioning metadata', () => {
+  it('readme no markdown headers', async () => {
     const managers = (await readdir('lib/versioning')).filter(
       item => !item.includes('.')
     );
-    let expectedHeaders: string[];
     for (const manager of managers) {
       let readme: string;
       try {
@@ -17,11 +16,21 @@ describe('versioning readmes', () => {
         // ignore missing file
       }
       if (readme) {
-        const headers = readme
-          .match(/\n## (.*?)\n/g)
-          .map(match => match.substring(4, match.length - 1));
-        expectedHeaders = expectedHeaders || headers;
-        expect(headers).toEqual(expectedHeaders);
+        expect(RegExp(/(^|\n)#+ /).exec(readme)).toBe(null);
+      }
+    }
+  });
+  it('mandatory fields', async () => {
+    const managers = (await readdir('lib/versioning')).filter(
+      item => !item.includes('.')
+    );
+    for (const manager of managers) {
+      const managerObj = require(`../../lib/versioning/${manager}`);
+      expect(managerObj.displayName).toBeDefined();
+      expect(managerObj.urls).toBeDefined();
+      expect(managerObj.supportsRanges).toBeDefined();
+      if (managerObj.supportsRanges === true) {
+        expect(managerObj.supportedRangeStrategies).toBeDefined();
       }
     }
   });