diff --git a/lib/datasource/api.ts b/lib/datasource/api.ts
index 43de52583e779fc93c838e8f39d59d0eecec527c..a5448742d0aa9fc05c1250a52cdda1e6eea0ac46 100644
--- a/lib/datasource/api.ts
+++ b/lib/datasource/api.ts
@@ -4,6 +4,7 @@ import { AwsMachineImageDataSource } from './aws-machine-image';
 import { BitBucketTagsDatasource } from './bitbucket-tags';
 import { CdnJsDatasource } from './cdnjs';
 import { ClojureDatasource } from './clojure';
+import { ConanDatasource } from './conan';
 import { CrateDatasource } from './crate';
 import { DartDatasource } from './dart';
 import * as docker from './docker';
@@ -48,6 +49,7 @@ api.set(AwsMachineImageDataSource.id, new AwsMachineImageDataSource());
 api.set('bitbucket-tags', new BitBucketTagsDatasource());
 api.set('cdnjs', new CdnJsDatasource());
 api.set('clojure', new ClojureDatasource());
+api.set(ConanDatasource.id, new ConanDatasource());
 api.set('crate', new CrateDatasource());
 api.set('dart', new DartDatasource());
 api.set('docker', docker);
diff --git a/lib/datasource/conan/__fixtures__/fake.json b/lib/datasource/conan/__fixtures__/fake.json
new file mode 100644
index 0000000000000000000000000000000000000000..be9d4f096c737dcf01ed588e01fac0d10846471f
--- /dev/null
+++ b/lib/datasource/conan/__fixtures__/fake.json
@@ -0,0 +1,3 @@
+{
+  "results" : [  ]
+}
diff --git a/lib/datasource/conan/__fixtures__/malformed.json b/lib/datasource/conan/__fixtures__/malformed.json
new file mode 100644
index 0000000000000000000000000000000000000000..5c5d2a7d8e890ab011a14f875131a676ad547abf
--- /dev/null
+++ b/lib/datasource/conan/__fixtures__/malformed.json
@@ -0,0 +1,3 @@
+{
+  "results" : [ "bad/@conan/stable", "bad/1.3", "bad/1.8.1@conan", "bad/1.9.3@_/_", "bad1.20.3@_/_" ]
+}
diff --git a/lib/datasource/conan/__fixtures__/poco.json b/lib/datasource/conan/__fixtures__/poco.json
new file mode 100644
index 0000000000000000000000000000000000000000..064057f4890f86a5dcf3fcb1ac573669f0f20fe8
--- /dev/null
+++ b/lib/datasource/conan/__fixtures__/poco.json
@@ -0,0 +1,3 @@
+{
+  "results" : [ "poco/1.10.0@_/_", "poco/1.10.1@_/_", "poco/1.8.1@_/_", "poco/1.9.3@_/_", "poco/1.9.4@_/_" ]
+}
diff --git a/lib/datasource/conan/common.ts b/lib/datasource/conan/common.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8ba8bb6061ee20692b36f228a47880a1c9199e41
--- /dev/null
+++ b/lib/datasource/conan/common.ts
@@ -0,0 +1,10 @@
+import { regEx } from '../../util/regex';
+
+export const defaultRegistryUrl = 'https://center.conan.io/';
+
+export const datasource = 'conan';
+
+export const conanDatasourceRegex = regEx(
+  /(?<name>[a-z\-_0-9]+)\/(?<version>[^@/\n]+)(?<userChannel>@\S+\/\S+)/,
+  'gim'
+);
diff --git a/lib/datasource/conan/index.spec.ts b/lib/datasource/conan/index.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e0faf02ce47d0154d754a6894b52b9a73e88c63f
--- /dev/null
+++ b/lib/datasource/conan/index.spec.ts
@@ -0,0 +1,182 @@
+import { getPkgReleases } from '..';
+import { Fixtures } from '../../../test/fixtures';
+import * as httpMock from '../../../test/http-mock';
+import * as conan from '../../versioning/conan';
+import type { GetPkgReleasesConfig } from '../types';
+import { defaultRegistryUrl } from './common';
+import { ConanDatasource } from '.';
+
+const pocoJson = Fixtures.get('poco.json');
+const malformedJson = Fixtures.get('malformed.json');
+const fakeJson = Fixtures.get('fake.json');
+const datasource = ConanDatasource.id;
+
+const config: GetPkgReleasesConfig = {
+  depName: '',
+  datasource,
+  versioning: conan.id,
+  registryUrls: [defaultRegistryUrl],
+};
+
+describe('datasource/conan/index', () => {
+  beforeEach(() => {
+    config.registryUrls = [defaultRegistryUrl];
+  });
+
+  describe('getReleases', () => {
+    it('handles bad return', async () => {
+      httpMock
+        .scope(defaultRegistryUrl)
+        .get('/v2/conans/search?q=fakepackage')
+        .reply(200, null);
+      config.depName = 'fakepackage';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'fakepackage/1.2@_/_',
+        })
+      ).toBeNull();
+    });
+
+    it('handles empty return', async () => {
+      httpMock
+        .scope(defaultRegistryUrl)
+        .get('/v2/conans/search?q=fakepackage')
+        .reply(200, {});
+      config.depName = 'fakepackage';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'fakepackage/1.2@_/_',
+        })
+      ).toBeNull();
+    });
+
+    it('handles bad registries', async () => {
+      httpMock
+        .scope('https://fake.bintray.com/')
+        .get('/v2/conans/search?q=poco')
+        .reply(404);
+      config.registryUrls = ['https://fake.bintray.com/'];
+      config.depName = 'poco';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'poco/1.2@_/_',
+        })
+      ).toBeNull();
+    });
+
+    it('handles missing packages', async () => {
+      httpMock
+        .scope(defaultRegistryUrl)
+        .get('/v2/conans/search?q=fakepackage')
+        .reply(200, fakeJson);
+      config.depName = 'fakepackage';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'fakepackage/1.2@_/_',
+        })
+      ).toBeNull();
+    });
+
+    it('processes real versioned data', async () => {
+      httpMock
+        .scope(defaultRegistryUrl)
+        .get('/v2/conans/search?q=poco')
+        .reply(200, pocoJson);
+      config.depName = 'poco';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'poco/1.2@_/_',
+        })
+      ).toEqual({
+        registryUrl: 'https://center.conan.io',
+        releases: [
+          {
+            version: '1.8.1',
+          },
+          {
+            version: '1.9.3',
+          },
+          {
+            version: '1.9.4',
+          },
+          {
+            version: '1.10.0',
+          },
+          {
+            version: '1.10.1',
+          },
+        ],
+      });
+    });
+
+    it('it handles mismatched userAndChannel versioned data', async () => {
+      httpMock
+        .scope(defaultRegistryUrl)
+        .get('/v2/conans/search?q=poco')
+        .reply(200, pocoJson);
+      config.depName = 'poco';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'poco/1.2@un/matched',
+        })
+      ).toBeNull();
+    });
+
+    it('handles malformed packages', async () => {
+      httpMock
+        .scope(defaultRegistryUrl)
+        .get('/v2/conans/search?q=bad')
+        .reply(200, malformedJson);
+      config.depName = 'bad';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'bad/1.2@_/_',
+        })
+      ).toEqual({
+        registryUrl: 'https://center.conan.io',
+        releases: [
+          {
+            version: '1.9.3',
+          },
+        ],
+      });
+    });
+
+    it('handles non 404 errors', async () => {
+      httpMock
+        .scope('https://fake.bintray.com/')
+        .get('/v2/conans/search?q=poco')
+        .replyWithError('error');
+      config.registryUrls = ['https://fake.bintray.com/'];
+      config.depName = 'poco';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'poco/1.2@_/_',
+        })
+      ).toBeNull();
+    });
+
+    it('handles missing slash on registries', async () => {
+      httpMock
+        .scope('https://fake.bintray.com/')
+        .get('/v2/conans/search?q=poco')
+        .reply(200, fakeJson);
+      config.registryUrls = ['https://fake.bintray.com'];
+      config.depName = 'poco';
+      expect(
+        await getPkgReleases({
+          ...config,
+          lookupName: 'poco/1.2@_/_',
+        })
+      ).toBeNull();
+    });
+  });
+});
diff --git a/lib/datasource/conan/index.ts b/lib/datasource/conan/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ca85f878cb12288bd6246d54d8e3c1672f316f31
--- /dev/null
+++ b/lib/datasource/conan/index.ts
@@ -0,0 +1,67 @@
+import { logger } from '../../logger';
+import { cache } from '../../util/cache/package/decorator';
+import { ensureTrailingSlash, joinUrlParts } from '../../util/url';
+import { Datasource } from '../datasource';
+import type { GetReleasesConfig, Release, ReleaseResult } from '../types';
+import { conanDatasourceRegex, datasource, defaultRegistryUrl } from './common';
+import type { ConanJSON } from './types';
+
+export class ConanDatasource extends Datasource {
+  static readonly id = datasource;
+
+  override readonly defaultRegistryUrls = [defaultRegistryUrl];
+
+  override readonly caching = true;
+
+  override readonly registryStrategy = 'merge';
+
+  constructor() {
+    super(ConanDatasource.id);
+  }
+
+  @cache({
+    namespace: `datasource-${datasource}`,
+    key: ({ registryUrl, lookupName }: GetReleasesConfig) =>
+      `${registryUrl}:${lookupName}`,
+  })
+  async getReleases({
+    registryUrl,
+    lookupName,
+  }: GetReleasesConfig): Promise<ReleaseResult | null> {
+    const depName = lookupName.split('/')[0];
+    const userAndChannel = '@' + lookupName.split('@')[1];
+
+    logger.trace({ depName, registryUrl }, 'Looking up conan api dependency');
+    if (registryUrl) {
+      const url = ensureTrailingSlash(registryUrl);
+      const lookupUrl = joinUrlParts(url, `v2/conans/search?q=${depName}`);
+
+      try {
+        const rep = await this.http.getJson<ConanJSON>(lookupUrl);
+        const versions = rep?.body;
+        if (versions) {
+          logger.trace({ lookupUrl }, 'Got conan api result');
+          const dep: ReleaseResult = { releases: [] };
+
+          for (const resultString of Object.values(versions.results || {})) {
+            const fromMatch = conanDatasourceRegex.exec(resultString);
+            if (fromMatch?.groups?.version && fromMatch?.groups?.userChannel) {
+              const version = fromMatch.groups.version;
+              if (fromMatch.groups.userChannel === userAndChannel) {
+                const result: Release = {
+                  version,
+                };
+                dep.releases.push(result);
+              }
+            }
+          }
+          return dep;
+        }
+      } catch (err) {
+        this.handleGenericErrors(err);
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/lib/datasource/conan/types.ts b/lib/datasource/conan/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b062195a3e57a5c02271195563b3900179306475
--- /dev/null
+++ b/lib/datasource/conan/types.ts
@@ -0,0 +1,3 @@
+export interface ConanJSON {
+  results?: Record<string, string>;
+}
diff --git a/lib/manager/api.ts b/lib/manager/api.ts
index 109301ab1e16b763eebd796a1c5ff396cd7a7f46..76fad55f08a9088063d4097785025a803f0900eb 100644
--- a/lib/manager/api.ts
+++ b/lib/manager/api.ts
@@ -15,6 +15,7 @@ import * as circleci from './circleci';
 import * as cloudbuild from './cloudbuild';
 import * as cocoapods from './cocoapods';
 import * as composer from './composer';
+import * as conan from './conan';
 import * as depsEdn from './deps-edn';
 import * as dockerCompose from './docker-compose';
 import * as dockerfile from './dockerfile';
@@ -86,6 +87,7 @@ api.set('circleci', circleci);
 api.set('cloudbuild', cloudbuild);
 api.set('cocoapods', cocoapods);
 api.set('composer', composer);
+api.set('conan', conan);
 api.set('deps-edn', depsEdn);
 api.set('docker-compose', dockerCompose);
 api.set('dockerfile', dockerfile);
diff --git a/lib/manager/conan/__fixtures__/conanfile.py b/lib/manager/conan/__fixtures__/conanfile.py
new file mode 100644
index 0000000000000000000000000000000000000000..b1cfdb5f902910f257f54e5c0aa4ea99a2857c00
--- /dev/null
+++ b/lib/manager/conan/__fixtures__/conanfile.py
@@ -0,0 +1,27 @@
+from conans import ConanFile
+
+class Pkg(ConanFile):
+   python_requires = "pyreq/0.1@user/channel"  # recipe to reuse code from
+   build_requires = "tool_a/0.2@user/testing", "tool_b/0.2@user/testing"
+   requires = "req_a/1.0", "req_l/2.1@otheruser/testing"
+
+   requires = [("req_b/0.1@user/testing"),
+               ("req_d/0.2@dummy/stable", "override"),
+               ("req_e/2.1@coder/beta", "private")]
+
+   requires = (("req_c/1.0@user/stable", "private"), )
+   requires = ("req_f/1.0@user/stable", ("req_h/3.0@other/beta", "override"))
+   requires = "req_g/[>1.0 <1.8]@user/stable"
+
+
+def requirements(self):
+   if self.options.myoption:
+      self.requires("req_i/1.2@drl/testing")
+   else:
+      self.requires("req_i/2.2@drl/stable")
+      self.requires("req_k/1.2@drl/testing", private=True, override=False)
+
+
+def build_requirements(self):
+   if self.settings.os == "Windows":
+      self.build_requires("tool_win/0.1@user/stable")
diff --git a/lib/manager/conan/__fixtures__/conanfile.txt b/lib/manager/conan/__fixtures__/conanfile.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e06417f57dd93bdc8a9cf5c8a9bfff220d7f85d0
--- /dev/null
+++ b/lib/manager/conan/__fixtures__/conanfile.txt
@@ -0,0 +1,30 @@
+[requires]
+poco/1.9.4
+zlib/[~1.2.3, loose=False]  
+fake/8.62.134@test/dev
+
+[build_requires]
+7zip/[>1.1 <2.1, include_prerelease=True]
+curl/[~1.2.3, loose=False, include_prerelease=True]@test/dev
+boost/[>1.1 <2.1]
+catch2/[2.8]     
+openssl/[~=3.0]@test/prod
+cmake/[>1.1 || 0.8] 
+cryptopp/[1.2.7 || >=1.2.9 <2.0.0]@test/local
+#commentedout/1.2
+# commentedout/3.4
+
+[generators]
+xcode
+cmake
+qmake
+
+[options]
+poco:shared=True
+openssl:shared=True
+
+# A comment
+
+[imports]
+bin, *.dll -> ./bin # Copies all dll files from packages bin folder to my local "bin" folder
+lib, *.dylib* -> ./bin # Copies all dylib files from packages lib folder to my local "bin" folder
\ No newline at end of file
diff --git a/lib/manager/conan/__fixtures__/conanfile2.txt b/lib/manager/conan/__fixtures__/conanfile2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b8e88c919169ab2575134c7a99f1c8756cb4a836
--- /dev/null
+++ b/lib/manager/conan/__fixtures__/conanfile2.txt
@@ -0,0 +1,10 @@
+[generators]
+xcode
+cmake
+qmake
+
+[options]
+poco:shared=True
+openssl:shared=True
+
+# A comment
diff --git a/lib/manager/conan/extract.spec.ts b/lib/manager/conan/extract.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1aad1e2ba9a39744f933ab52fa61bbfb733dc368
--- /dev/null
+++ b/lib/manager/conan/extract.spec.ts
@@ -0,0 +1,212 @@
+import { Fixtures } from '../../../test/fixtures';
+import { extractPackageFile } from '.';
+
+const conanfile1 = Fixtures.get('conanfile.txt');
+const conanfile2 = Fixtures.get('conanfile2.txt');
+const conanfile3 = Fixtures.get('conanfile.py');
+
+describe('manager/conan/extract', () => {
+  describe('extractPackageFile', () => {
+    it('returns null for empty', () => {
+      expect(extractPackageFile('nothing here')).toBeNull();
+    });
+    it('extracts multiple image lines from conanfile.txt', () => {
+      const res = extractPackageFile(conanfile1);
+      expect(res?.deps).toEqual([
+        {
+          currentValue: '1.9.4',
+          depName: 'poco',
+          depType: 'requires',
+          lookupName: 'poco/1.9.4@_/_',
+          replaceString: 'poco/1.9.4',
+        },
+        {
+          currentValue: '[~1.2.3, loose=False]',
+          depName: 'zlib',
+          depType: 'requires',
+          lookupName: 'zlib/[~1.2.3, loose=False]@_/_',
+          replaceString: 'zlib/[~1.2.3, loose=False]',
+        },
+        {
+          currentValue: '8.62.134',
+          depName: 'fake',
+          depType: 'requires',
+          lookupName: 'fake/8.62.134@test/dev',
+          replaceString: 'fake/8.62.134@test/dev',
+        },
+        {
+          currentValue: '[>1.1 <2.1, include_prerelease=True]',
+          depName: '7zip',
+          depType: 'build_requires',
+          lookupName: '7zip/[>1.1 <2.1, include_prerelease=True]@_/_',
+          replaceString: '7zip/[>1.1 <2.1, include_prerelease=True]',
+        },
+        {
+          currentValue: '[~1.2.3, loose=False, include_prerelease=True]',
+          depName: 'curl',
+          depType: 'build_requires',
+          lookupName:
+            'curl/[~1.2.3, loose=False, include_prerelease=True]@test/dev',
+          replaceString:
+            'curl/[~1.2.3, loose=False, include_prerelease=True]@test/dev',
+        },
+        {
+          currentValue: '[>1.1 <2.1]',
+          depName: 'boost',
+          depType: 'build_requires',
+          lookupName: 'boost/[>1.1 <2.1]@_/_',
+          replaceString: 'boost/[>1.1 <2.1]',
+        },
+        {
+          currentValue: '[2.8]',
+          depName: 'catch2',
+          depType: 'build_requires',
+          lookupName: 'catch2/[2.8]@_/_',
+          replaceString: 'catch2/[2.8]',
+        },
+        {
+          currentValue: '[~=3.0]',
+          depName: 'openssl',
+          depType: 'build_requires',
+          lookupName: 'openssl/[~=3.0]@test/prod',
+          replaceString: 'openssl/[~=3.0]@test/prod',
+        },
+        {
+          currentValue: '[>1.1 || 0.8]',
+          depName: 'cmake',
+          depType: 'build_requires',
+          lookupName: 'cmake/[>1.1 || 0.8]@_/_',
+          replaceString: 'cmake/[>1.1 || 0.8]',
+        },
+        {
+          currentValue: '[1.2.7 || >=1.2.9 <2.0.0]',
+          depName: 'cryptopp',
+          depType: 'build_requires',
+          lookupName: 'cryptopp/[1.2.7 || >=1.2.9 <2.0.0]@test/local',
+          replaceString: 'cryptopp/[1.2.7 || >=1.2.9 <2.0.0]@test/local',
+        },
+      ]);
+    });
+    it('extracts multiple 0 lines from conanfile.txt', () => {
+      const res = extractPackageFile(conanfile2);
+      expect(res).toBeNull();
+    });
+    it('extracts multiple image lines from conanfile.py', () => {
+      const res = extractPackageFile(conanfile3);
+      expect(res?.deps).toEqual([
+        {
+          currentValue: '0.1',
+          depName: 'pyreq',
+          depType: 'python_requires',
+          lookupName: 'pyreq/0.1@user/channel',
+          replaceString: 'pyreq/0.1@user/channel',
+        },
+        {
+          currentValue: '0.2',
+          depName: 'tool_a',
+          depType: 'build_requires',
+          lookupName: 'tool_a/0.2@user/testing',
+          replaceString: 'tool_a/0.2@user/testing',
+        },
+        {
+          currentValue: '0.2',
+          depName: 'tool_b',
+          depType: 'build_requires',
+          lookupName: 'tool_b/0.2@user/testing',
+          replaceString: 'tool_b/0.2@user/testing',
+        },
+        {
+          currentValue: '1.0',
+          depName: 'req_a',
+          depType: 'requires',
+          lookupName: 'req_a/1.0@_/_',
+          replaceString: 'req_a/1.0',
+        },
+        {
+          currentValue: '2.1',
+          depName: 'req_l',
+          depType: 'requires',
+          lookupName: 'req_l/2.1@otheruser/testing',
+          replaceString: 'req_l/2.1@otheruser/testing',
+        },
+        {
+          currentValue: '0.1',
+          depName: 'req_b',
+          depType: 'requires',
+          lookupName: 'req_b/0.1@user/testing',
+          replaceString: 'req_b/0.1@user/testing',
+        },
+        {
+          currentValue: '0.2',
+          depName: 'req_d',
+          depType: 'requires',
+          lookupName: 'req_d/0.2@dummy/stable',
+          replaceString: 'req_d/0.2@dummy/stable',
+        },
+        {
+          currentValue: '2.1',
+          depName: 'req_e',
+          depType: 'requires',
+          lookupName: 'req_e/2.1@coder/beta',
+          replaceString: 'req_e/2.1@coder/beta',
+        },
+        {
+          currentValue: '1.0',
+          depName: 'req_c',
+          depType: 'requires',
+          lookupName: 'req_c/1.0@user/stable',
+          replaceString: 'req_c/1.0@user/stable',
+        },
+        {
+          currentValue: '1.0',
+          depName: 'req_f',
+          depType: 'requires',
+          lookupName: 'req_f/1.0@user/stable',
+          replaceString: 'req_f/1.0@user/stable',
+        },
+        {
+          currentValue: '3.0',
+          depName: 'req_h',
+          depType: 'requires',
+          lookupName: 'req_h/3.0@other/beta',
+          replaceString: 'req_h/3.0@other/beta',
+        },
+        {
+          currentValue: '[>1.0 <1.8]',
+          depName: 'req_g',
+          depType: 'requires',
+          lookupName: 'req_g/[>1.0 <1.8]@user/stable',
+          replaceString: 'req_g/[>1.0 <1.8]@user/stable',
+        },
+        {
+          currentValue: '1.2',
+          depName: 'req_i',
+          depType: 'requires',
+          lookupName: 'req_i/1.2@drl/testing',
+          replaceString: 'req_i/1.2@drl/testing',
+        },
+        {
+          currentValue: '2.2',
+          depName: 'req_i',
+          depType: 'requires',
+          lookupName: 'req_i/2.2@drl/stable',
+          replaceString: 'req_i/2.2@drl/stable',
+        },
+        {
+          currentValue: '1.2',
+          depName: 'req_k',
+          depType: 'requires',
+          lookupName: 'req_k/1.2@drl/testing',
+          replaceString: 'req_k/1.2@drl/testing',
+        },
+        {
+          currentValue: '0.1',
+          depName: 'tool_win',
+          depType: 'build_requires',
+          lookupName: 'tool_win/0.1@user/stable',
+          replaceString: 'tool_win/0.1@user/stable',
+        },
+      ]);
+    });
+  });
+});
diff --git a/lib/manager/conan/extract.ts b/lib/manager/conan/extract.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f0f2eb5c1bedd9dd5dc3c42be12019090643f7cd
--- /dev/null
+++ b/lib/manager/conan/extract.ts
@@ -0,0 +1,75 @@
+import is from '@sindresorhus/is';
+import { regEx } from '../../util/regex';
+import type { PackageDependency, PackageFile } from '../types';
+
+const regex = regEx(
+  `(?<name>[-_a-z0-9]+)/(?<version>[^@\n{*"']+)(?<userChannel>@[-_a-zA-Z0-9]+/[^\n.{*"' ]+)?`
+);
+
+function setDepType(content: string, originalType: string): string {
+  let depType = originalType;
+  if (content.includes('python_requires')) {
+    depType = 'python_requires';
+  } else if (content.includes('build_require')) {
+    depType = 'build_requires';
+  } else if (content.includes('requires')) {
+    depType = 'requires';
+  }
+  return depType;
+}
+
+export function extractPackageFile(content: string): PackageFile | null {
+  // only process sections where requirements are defined
+  const sections = content.split(/def |\n\[/).filter(
+    (part) =>
+      part.includes('python_requires') || // only matches python_requires
+      part.includes('build_require') || // matches [build_requires], build_requirements(), and build_requires
+      part.includes('require') // matches [requires], requirements(), and requires
+  );
+
+  const deps: PackageDependency[] = [];
+  for (const section of sections) {
+    let depType = setDepType(section, 'requires');
+    const rawLines = section.split('\n').filter(is.nonEmptyString);
+
+    for (const rawline of rawLines) {
+      // don't process after a comment
+      const sanitizedLine = rawline.split('#')[0].split('//')[0];
+      if (sanitizedLine) {
+        depType = setDepType(sanitizedLine, depType);
+        // extract all dependencies from each line
+        const lines = sanitizedLine.split(/["'],/);
+        for (const line of lines) {
+          const matches = regex.exec(line.trim());
+          if (matches?.groups) {
+            let dep: PackageDependency = {};
+            const depName = matches.groups?.name;
+            const currentValue = matches.groups?.version.trim();
+
+            let replaceString = `${depName}/${currentValue}`;
+            // conan uses @_/_ as a placeholder for no userChannel
+            let userAndChannel = '@_/_';
+
+            if (matches.groups.userChannel) {
+              userAndChannel = matches.groups.userChannel;
+              replaceString = `${depName}/${currentValue}${userAndChannel}`;
+            }
+            const lookupName = `${depName}/${currentValue}${userAndChannel}`;
+
+            dep = {
+              ...dep,
+              depName,
+              lookupName,
+              currentValue,
+              replaceString,
+              depType,
+            };
+            deps.push(dep);
+          }
+        }
+      }
+    }
+  }
+
+  return deps.length ? { deps } : null;
+}
diff --git a/lib/manager/conan/index.ts b/lib/manager/conan/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..80d820ef1a02b87edb39885e057cf8dfdd2b672f
--- /dev/null
+++ b/lib/manager/conan/index.ts
@@ -0,0 +1,12 @@
+export { extractPackageFile } from './extract';
+import { ConanDatasource } from '../../datasource/conan';
+import * as conan from '../../versioning/conan';
+
+export const defaultConfig = {
+  fileMatch: ['(^|/)conanfile\\.(txt|py)$'],
+  datasource: ConanDatasource.id,
+  versioning: conan.id,
+  rangeStrategy: 'bump',
+};
+
+export const supportedDatasources = [ConanDatasource.id];
diff --git a/lib/manager/conan/readme.md b/lib/manager/conan/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..a2d109bffc6f69b51b8d685b7b53eeb6bd0b6bc8
--- /dev/null
+++ b/lib/manager/conan/readme.md
@@ -0,0 +1,17 @@
+Automated dependency updates for Conan
+
+Renovate can upgrade dependencies in `conanfile.txt` or `conanfile.py` files.
+
+How it works:
+
+1. Renovate searches in each repository for any `conanfile.txt` or `conanfile.py` file
+1. Renovate extracts existing dependencies from:
+   - the `[requires]` and `[build_requires]` sections in the `conanfile.txt` format
+   - the `requirements()` and `build_requirements()` functions in the `conanfile.py` format
+   - and the `python_requires`, `requires` and `build_requires` variables in the `conanfile.py` format
+1. Renovate resolves the dependency's version using the Conan v2 API
+1. If Renovate finds an update, Renovate will update `conanfile.txt` or `conanfile.py`
+
+Enabling Conan updating
+
+Renovate updates Conan packages by default.
diff --git a/lib/versioning/api.ts b/lib/versioning/api.ts
index 932441370655fa578be24e800614bff2e52dea8f..a76a544750e28a466c581fefeccc06ccffde9ed5 100644
--- a/lib/versioning/api.ts
+++ b/lib/versioning/api.ts
@@ -1,6 +1,7 @@
 import * as amazonMachineImage from './aws-machine-image';
 import * as cargo from './cargo';
 import * as composer from './composer';
+import * as conan from './conan';
 import * as docker from './docker';
 import * as git from './git';
 import * as gradle from './gradle';
@@ -30,6 +31,7 @@ export default api;
 api.set(amazonMachineImage.id, amazonMachineImage.api);
 api.set('cargo', cargo.api);
 api.set('composer', composer.api);
+api.set('conan', conan.api);
 api.set('docker', docker.api);
 api.set('git', git.api);
 api.set('gradle', gradle.api);
diff --git a/lib/versioning/conan/common.ts b/lib/versioning/conan/common.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e6009901a16133093deeae0c9b403ef41c143092
--- /dev/null
+++ b/lib/versioning/conan/common.ts
@@ -0,0 +1,108 @@
+import * as semver from 'semver';
+import { regEx } from '../../util/regex';
+
+export function makeVersion(
+  version: string,
+  options: semver.Options
+): string | boolean | null {
+  const splitVersion = version.split('.');
+  const prerelease = semver.prerelease(version, options);
+
+  if (prerelease && !options.includePrerelease) {
+    if (!Number.isNaN(parseInt(prerelease.toString()[0], 10))) {
+      const stringVersion = `${splitVersion[0]}.${splitVersion[1]}.${splitVersion[2]}`;
+      return semver.valid(stringVersion, options);
+    }
+    return false;
+  }
+
+  if (
+    options.loose &&
+    !semver.valid(version, options) &&
+    splitVersion.length !== 3
+  ) {
+    return semver.valid(semver.coerce(version, options), options);
+  }
+  return semver.valid(version, options);
+}
+
+export function cleanVersion(version: string): string {
+  if (version) {
+    return version
+      .replace(regEx(/,|\[|\]|"|include_prerelease=|loose=|True|False/g), '')
+      .trim();
+  }
+  return version;
+}
+
+export function getOptions(input: string): {
+  loose: boolean;
+  includePrerelease: boolean;
+} {
+  let includePrerelease = false;
+  let loose = true;
+  if (input) {
+    includePrerelease =
+      input.includes('include_prerelease=True') &&
+      !input.includes('include_prerelease=False');
+    loose = input.includes('loose=True') || !input.includes('loose=False');
+  }
+  return { loose, includePrerelease };
+}
+
+export function containsOperators(input: string): boolean {
+  return regEx('[<=>^~]').test(input);
+}
+
+export function matchesWithOptions(
+  version: string,
+  cleanRange: string,
+  options: semver.Options
+): boolean {
+  let cleanedVersion = version;
+  if (
+    cleanedVersion &&
+    semver.prerelease(cleanedVersion) &&
+    options.includePrerelease
+  ) {
+    const coercedVersion = semver.coerce(cleanedVersion)?.raw;
+    cleanedVersion = coercedVersion ? coercedVersion : '';
+  }
+  return semver.satisfies(cleanedVersion, cleanRange, options);
+}
+
+export function findSatisfyingVersion(
+  versions: string[],
+  range: string,
+  compareRt: number
+): string | null {
+  const options = getOptions(range);
+  let cur: any = null;
+  let curSV: any = null;
+  let index = 0;
+  let curIndex = -1;
+
+  for (const v of versions) {
+    const versionFromList = makeVersion(v, options);
+    if (typeof versionFromList === 'string') {
+      const cleanedVersion = cleanVersion(versionFromList);
+      const options = getOptions(range);
+      const cleanRange = cleanVersion(range);
+      if (matchesWithOptions(cleanedVersion, cleanRange, options)) {
+        if (
+          !cur ||
+          semver.compare(curSV, versionFromList, options) === compareRt
+        ) {
+          cur = versionFromList;
+          curIndex = index;
+          curSV = new semver.SemVer(cur, options);
+        }
+      }
+    }
+    index += 1;
+  }
+  if (curIndex >= 0) {
+    return versions[curIndex];
+  }
+  return null;
+}
diff --git a/lib/versioning/conan/index.spec.ts b/lib/versioning/conan/index.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..51926b987f4c8eb9983af2bf826b9ccc1f5ccc1e
--- /dev/null
+++ b/lib/versioning/conan/index.spec.ts
@@ -0,0 +1,907 @@
+import { api as conan } from '.';
+
+describe('versioning/conan/index', () => {
+  // isValid(version: string): boolean;
+  test.each`
+    version                                                      | result
+    ${'[1.2.3.4, loose=False]'}                                  | ${false}
+    ${'[NOT VALID, loose=False]'}                                | ${false}
+    ${'[1.2, loose=False]'}                                      | ${true}
+    ${'[1.a.2, loose=False]'}                                    | ${false}
+    ${'[Infinity.NaN.Infinity, loose=False]'}                    | ${false}
+    ${'1.2.3.4'}                                                 | ${true}
+    ${'NOT VALID'}                                               | ${false}
+    ${'1.2'}                                                     | ${true}
+    ${'1.a.2'}                                                   | ${false}
+    ${''}                                                        | ${true}
+    ${'Infinity.NaN.Infinity'}                                   | ${false}
+    ${'17.04.0'}                                                 | ${true}
+    ${'1.2.3'}                                                   | ${true}
+    ${'1.2.3-foo'}                                               | ${true}
+    ${'[>1.1 <2.0]'}                                             | ${true}
+    ${'1.2.3foo'}                                                | ${true}
+    ${'[~1.2.3]'}                                                | ${true}
+    ${'[^1.2.3]'}                                                | ${true}
+    ${'1.x'}                                                     | ${true}
+    ${'[>1.2.3]'}                                                | ${true}
+    ${'[>1.1 <2.1]'}                                             | ${true}
+    ${'[~=3.0]'}                                                 | ${true}
+    ${'[>1.1 || 0.8]'}                                           | ${true}
+    ${'[1.2.7 || >=1.2.9 <2.0.0]'}                               | ${true}
+    ${'[>1.1 <2.1, include_prerelease=True]'}                    | ${true}
+    ${'[~1.2.3, loose=False]'}                                   | ${true}
+    ${'[~1.2.3, loose=False, include_prerelease=True]'}          | ${true}
+    ${'renovatebot/renovate'}                                    | ${false}
+    ${'renovatebot/renovate#main'}                               | ${false}
+    ${'https://github.com/renovatebot/renovate.git'}             | ${false}
+    ${'[>=01.02.03]'}                                            | ${true}
+    ${'[~1.02.03beta]'}                                          | ${true}
+    ${'[">1.0.0 <1.0.2", loose=False, include_prerelease=True]'} | ${true}
+    ${'[1.0.0 - 2.0.0, loose=False]'}                            | ${true}
+    ${'[1.0.0, loose=False]'}                                    | ${true}
+    ${'[>=*, loose=False]'}                                      | ${true}
+    ${'[, loose=False]'}                                         | ${true}
+    ${'[*, loose=False]'}                                        | ${true}
+    ${'[>=1.0.0, loose=False]'}                                  | ${true}
+    ${'[>1.0.0, loose=False]'}                                   | ${true}
+    ${'[<=2.0.0, loose=False]'}                                  | ${true}
+    ${'[1, loose=False]'}                                        | ${true}
+    ${'[<=2.0.0, loose=False]'}                                  | ${true}
+    ${'[<=2.0.0, loose=False]'}                                  | ${true}
+    ${'[<2.0.0, loose=False]'}                                   | ${true}
+    ${'[<2.0.0, loose=False]'}                                   | ${true}
+    ${'[>= 1.0.0, loose=False]'}                                 | ${true}
+    ${'[>=  1.0.0, loose=False]'}                                | ${true}
+    ${'[>=   1.0.0, loose=False]'}                               | ${true}
+    ${'[> 1.0.0, loose=False]'}                                  | ${true}
+    ${'[>  1.0.0, loose=False]'}                                 | ${true}
+    ${'[<=   2.0.0, loose=False]'}                               | ${true}
+    ${'[<= 2.0.0, loose=False]'}                                 | ${true}
+    ${'[<=  2.0.0, loose=False]'}                                | ${true}
+    ${'[<    2.0.0, loose=False]'}                               | ${true}
+    ${'[<	2.0.0, loose=False]'}                                   | ${true}
+    ${'[>=0.1.97, loose=False]'}                                 | ${true}
+    ${'[>=0.1.97, loose=False]'}                                 | ${true}
+    ${'[0.1.20 || 1.2.4, loose=False]'}                          | ${true}
+    ${'[>=0.2.3 || <0.0.1, loose=False]'}                        | ${true}
+    ${'[>=0.2.3 || <0.0.1, loose=False]'}                        | ${true}
+    ${'[>=0.2.3 || <0.0.1, loose=False]'}                        | ${true}
+    ${'[||, loose=False]'}                                       | ${true}
+    ${'[2.x.x, loose=False]'}                                    | ${true}
+    ${'[1.2.x, loose=False]'}                                    | ${true}
+    ${'[1.2.x || 2.x, loose=False]'}                             | ${true}
+    ${'[1.2.x || 2.x, loose=False]'}                             | ${true}
+    ${'[x, loose=False]'}                                        | ${true}
+    ${'[2.*.*, loose=False]'}                                    | ${true}
+    ${'[1.2.*, loose=False]'}                                    | ${true}
+    ${'[1.2.* || 2.*, loose=False]'}                             | ${true}
+    ${'[*, loose=False]'}                                        | ${true}
+    ${'[2, loose=False]'}                                        | ${true}
+    ${'[2.3, loose=False]'}                                      | ${true}
+    ${'[~2.4, loose=False]'}                                     | ${true}
+    ${'[~>3.2.1, loose=False]'}                                  | ${true}
+    ${'[~1, loose=False]'}                                       | ${true}
+    ${'[~>1, loose=False]'}                                      | ${true}
+    ${'[~> 1, loose=False]'}                                     | ${true}
+    ${'[~1.0, loose=False]'}                                     | ${true}
+    ${'[~ 1.0, loose=False]'}                                    | ${true}
+    ${'[^0, loose=False]'}                                       | ${true}
+    ${'[^ 1, loose=False]'}                                      | ${true}
+    ${'[^0.1, loose=False]'}                                     | ${true}
+    ${'[^1.0, loose=False]'}                                     | ${true}
+    ${'[^1.2, loose=False]'}                                     | ${true}
+    ${'[^0.0.1, loose=False]'}                                   | ${true}
+    ${'[^0.0.1-beta, loose=False]'}                              | ${true}
+    ${'[^0.1.2, loose=False]'}                                   | ${true}
+    ${'[^1.2.3, loose=False]'}                                   | ${true}
+    ${'[^1.2.3-beta.4, loose=False]'}                            | ${true}
+    ${'[<1, loose=False]'}                                       | ${true}
+    ${'[< 1, loose=False]'}                                      | ${true}
+    ${'[>=1, loose=False]'}                                      | ${true}
+    ${'[>= 1, loose=False]'}                                     | ${true}
+    ${'[<1.2, loose=False]'}                                     | ${true}
+    ${'[< 1.2, loose=False]'}                                    | ${true}
+    ${'[1, loose=False]'}                                        | ${true}
+    ${'[>01.02.03, loose=True]'}                                 | ${true}
+    ${'[>01.02.03, loose=False]'}                                | ${false}
+    ${'[~1.2.3beta, loose=True]'}                                | ${true}
+    ${'[~1.2.3beta, loose=False]'}                               | ${false}
+    ${'[^ 1.2 ^ 1, loose=False]'}                                | ${true}
+  `('isValid("$version") === $result', ({ version, result }) => {
+    const res = conan.isValid(version);
+    expect(res).toBe(result);
+  });
+
+  // isVersion(version: string): boolean;
+  // isSingleVersion(version: string): boolean;
+  test.each`
+    version                                            | result
+    ${'1.0.7-prerelease.1'}                            | ${true}
+    ${'1.0.7-prerelease.1, include_prerelease=True'}   | ${true}
+    ${'NOT VALID, loose=False'}                        | ${false}
+    ${'NOT VALID'}                                     | ${false}
+    ${'1.a.2, loose=False'}                            | ${false}
+    ${'1.a.2'}                                         | ${true}
+    ${null}                                            | ${false}
+    ${'1.2, loose=False'}                              | ${false}
+    ${'1.2'}                                           | ${true}
+    ${'1.2.3.4, loose=False'}                          | ${false}
+    ${'1.2.3.4'}                                       | ${true}
+    ${'1.2.23.4'}                                      | ${true}
+    ${'4.1.3-pre, include_prerelease=True'}            | ${true}
+    ${'X.2, loose=False'}                              | ${false}
+    ${'X.2'}                                           | ${true}
+    ${'Infinity.NaN.Infinity, loose=False'}            | ${false}
+    ${'Infinity.NaN.Infinity'}                         | ${false}
+    ${'1.2.3'}                                         | ${true}
+    ${'"1.2.3", loose=False'}                          | ${true}
+    ${'"1.2.3", loose=False, include_prerelease=True'} | ${true}
+    ${'"1.2.3", include_prerelease=True'}              | ${true}
+    ${'1.2.3-alpha.1'}                                 | ${true}
+    ${'"1.2.3-alpha.1", include_prerelease=True'}      | ${true}
+    ${'"1.2.6-pre.1", include_prerelease=True'}        | ${true}
+    ${'"1.2.3-dev.1+abc", include_prerelease=True'}    | ${true}
+    ${'1.2.3-dev.1+abc'}                               | ${true}
+    ${'1.2.6-pre.1'}                                   | ${true}
+    ${'=1.2.3'}                                        | ${true}
+    ${'= 1.2.3'}                                       | ${true}
+    ${'1.x'}                                           | ${true}
+    ${'"1.x", loose=False'}                            | ${false}
+    ${'01.02.03'}                                      | ${true}
+    ${'1.2.3-beta.01, include_prerelease=True'}        | ${true}
+    ${'   =1.2.3'}                                     | ${true}
+    ${'1.2.3foo, include_prerelease=True'}             | ${true}
+    ${'5.0.20210712-T1759Z+b563c1478'}                 | ${true}
+    ${'0.2'}                                           | ${true}
+    ${'16.00'}                                         | ${true}
+  `('isVersion("$version") === $result', ({ version, result }) => {
+    const res = conan.isVersion(version);
+    expect(res).toBe(result);
+  });
+
+  // isCompatible(version: string, range?: string): boolean;
+  test.each`
+    range                                                                           | version              | result
+    ${'[>1.1 <2.0]'}                                                                | ${'1.2.3'}           | ${true}
+    ${'["~1.2.3", loose=False, include_prerelease=True]'}                           | ${'1.2.3-pre.1'}     | ${false}
+    ${'["1.0.0 - 2.0.0", loose=False, include_prerelease=False]'}                   | ${'1.2.3'}           | ${true}
+    ${'["^1.2.3+build", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'["^1.2.3+build", loose=False, include_prerelease=False]'}                    | ${'1.3.0'}           | ${true}
+    ${'["1.2.3-pre+asdf - 2.4.3-pre+asdf", loose=False, include_prerelease=False]'} | ${'1.2.3'}           | ${true}
+    ${'["1.2.3pre+asdf - 2.4.3-pre+asdf", loose=True, include_prerelease=False]'}   | ${'1.2.3'}           | ${true}
+    ${'["1.2.3-pre+asdf - 2.4.3pre+asdf", loose=True, include_prerelease=False]'}   | ${'1.2.3'}           | ${true}
+    ${'["1.2.3pre+asdf - 2.4.3pre+asdf", loose=True, include_prerelease=False]'}    | ${'1.2.3'}           | ${true}
+    ${'["1.2.3-pre+asdf - 2.4.3-pre+asdf", loose=False, include_prerelease=False]'} | ${'1.2.3-pre.2'}     | ${false}
+    ${'["1.2.3-pre+asdf - 2.4.3-pre+asdf", loose=False, include_prerelease=False]'} | ${'2.4.3-alpha'}     | ${false}
+    ${'["1.2.3+asdf - 2.4.3+asdf", loose=False, include_prerelease=False]'}         | ${'1.2.3'}           | ${true}
+    ${'["1.0.0", loose=False, include_prerelease=False]'}                           | ${'1.0.0'}           | ${true}
+    ${'[">=*", loose=False, include_prerelease=False]'}                             | ${'0.2.4'}           | ${true}
+    ${'["", loose=False, include_prerelease=False]'}                                | ${'1.0.0'}           | ${true}
+    ${'["*", loose=False, include_prerelease=False]'}                               | ${'1.2.3'}           | ${true}
+    ${'["*", loose=True, include_prerelease=False]'}                                | ${'v1.2.3'}          | ${true}
+    ${'[">=1.0.0", loose=False, include_prerelease=False]'}                         | ${'1.0.0'}           | ${true}
+    ${'[">=1.0.0", loose=False, include_prerelease=False]'}                         | ${'1.0.1'}           | ${true}
+    ${'[">=1.0.0", loose=False, include_prerelease=False]'}                         | ${'1.1.0'}           | ${true}
+    ${'[">1.0.0", loose=False, include_prerelease=False]'}                          | ${'1.0.1'}           | ${true}
+    ${'[">1.0.0", loose=False, include_prerelease=True]'}                           | ${'1.0.1-pre.1'}     | ${true}
+    ${'[">1.0.0", loose=False, include_prerelease=False]'}                          | ${'1.1.0'}           | ${true}
+    ${'["<=2.0.0", loose=False, include_prerelease=False]'}                         | ${'2.0.0'}           | ${true}
+    ${'["<=2.0.0", loose=False, include_prerelease=False]'}                         | ${'1.9999.9999'}     | ${true}
+    ${'["<=2.0.0", loose=False, include_prerelease=False]'}                         | ${'0.2.9'}           | ${true}
+    ${'["<2.0.0", loose=False, include_prerelease=False]'}                          | ${'1.9999.9999'}     | ${true}
+    ${'["<2.0.0", loose=False, include_prerelease=False]'}                          | ${'0.2.9'}           | ${true}
+    ${'[">= 1.0.0", loose=False, include_prerelease=False]'}                        | ${'1.0.0'}           | ${true}
+    ${'[">=  1.0.0", loose=False, include_prerelease=False]'}                       | ${'1.0.1'}           | ${true}
+    ${'[">=   1.0.0", loose=False, include_prerelease=False]'}                      | ${'1.1.0'}           | ${true}
+    ${'["> 1.0.0", loose=False, include_prerelease=False]'}                         | ${'1.0.1'}           | ${true}
+    ${'[">  1.0.0", loose=False, include_prerelease=False]'}                        | ${'1.1.0'}           | ${true}
+    ${'["<=   2.0.0", loose=False, include_prerelease=False]'}                      | ${'2.0.0'}           | ${true}
+    ${'["<= 2.0.0", loose=False, include_prerelease=False]'}                        | ${'1.9999.9999'}     | ${true}
+    ${'["<=  2.0.0", loose=False, include_prerelease=False]'}                       | ${'0.2.9'}           | ${true}
+    ${'["<    2.0.0", loose=False, include_prerelease=False]'}                      | ${'1.9999.9999'}     | ${true}
+    ${'["<\t2.0.0", loose=False, include_prerelease=False]'}                        | ${'0.2.9'}           | ${true}
+    ${'[">=0.1.97", loose=True, include_prerelease=False]'}                         | ${'v0.1.97'}         | ${true}
+    ${'[">=0.1.97", loose=False, include_prerelease=False]'}                        | ${'0.1.97'}          | ${true}
+    ${'["0.1.20 || 1.2.4", loose=False, include_prerelease=False]'}                 | ${'1.2.4'}           | ${true}
+    ${'[">=0.2.3 || <0.0.1", loose=False, include_prerelease=False]'}               | ${'0.0.0'}           | ${true}
+    ${'[">=0.2.3 || <0.0.1", loose=False, include_prerelease=False]'}               | ${'0.2.3'}           | ${true}
+    ${'[">=0.2.3 || <0.0.1", loose=False, include_prerelease=False]'}               | ${'0.2.4'}           | ${true}
+    ${'["||", loose=False, include_prerelease=False]'}                              | ${'1.3.4'}           | ${true}
+    ${'["2.x.x", loose=False, include_prerelease=False]'}                           | ${'2.1.3'}           | ${true}
+    ${'["1.2.x", loose=False, include_prerelease=False]'}                           | ${'1.2.3'}           | ${true}
+    ${'["1.2.x || 2.x", loose=False, include_prerelease=False]'}                    | ${'2.1.3'}           | ${true}
+    ${'["1.2.x || 2.x", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'["x", loose=False, include_prerelease=False]'}                               | ${'1.2.3'}           | ${true}
+    ${'["2.*.*", loose=False, include_prerelease=False]'}                           | ${'2.1.3'}           | ${true}
+    ${'["1.2.*", loose=False, include_prerelease=False]'}                           | ${'1.2.3'}           | ${true}
+    ${'["1.2.* || 2.*", loose=False, include_prerelease=False]'}                    | ${'2.1.3'}           | ${true}
+    ${'["1.2.* || 2.*", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'["*", loose=False, include_prerelease=False]'}                               | ${'1.2.3'}           | ${true}
+    ${'["2", loose=False, include_prerelease=False]'}                               | ${'2.1.2'}           | ${true}
+    ${'["2.3", loose=False, include_prerelease=False]'}                             | ${'2.3.1'}           | ${true}
+    ${'["~x", loose=False, include_prerelease=False]'}                              | ${'0.0.9'}           | ${true}
+    ${'["~2", loose=False, include_prerelease=False]'}                              | ${'2.0.9'}           | ${true}
+    ${'["~2.4", loose=False, include_prerelease=False]'}                            | ${'2.4.0'}           | ${true}
+    ${'["~2.4", loose=False, include_prerelease=False]'}                            | ${'2.4.5'}           | ${true}
+    ${'["~>3.2.1", loose=False, include_prerelease=False]'}                         | ${'3.2.2'}           | ${true}
+    ${'["~1", loose=False, include_prerelease=False]'}                              | ${'1.2.3'}           | ${true}
+    ${'["~>1", loose=False, include_prerelease=False]'}                             | ${'1.2.3'}           | ${true}
+    ${'["~> 1", loose=False, include_prerelease=False]'}                            | ${'1.2.3'}           | ${true}
+    ${'["~1.0", loose=False, include_prerelease=False]'}                            | ${'1.0.2'}           | ${true}
+    ${'["~ 1.0", loose=False, include_prerelease=False]'}                           | ${'1.0.2'}           | ${true}
+    ${'[">=1", loose=False, include_prerelease=False]'}                             | ${'1.0.0'}           | ${true}
+    ${'[">= 1", loose=False, include_prerelease=False]'}                            | ${'1.0.0'}           | ${true}
+    ${'["<1.2", loose=False, include_prerelease=False]'}                            | ${'1.1.1'}           | ${true}
+    ${'["< 1.2", loose=False, include_prerelease=False]'}                           | ${'1.1.1'}           | ${true}
+    ${'["~v0.5.4-pre", loose=False, include_prerelease=False]'}                     | ${'0.5.5'}           | ${true}
+    ${'["~v0.5.4-pre", loose=False, include_prerelease=False]'}                     | ${'0.5.4'}           | ${true}
+    ${'["=0.7.x", loose=False, include_prerelease=False]'}                          | ${'0.7.2'}           | ${true}
+    ${'["<=0.7.x", loose=False, include_prerelease=False]'}                         | ${'0.7.2'}           | ${true}
+    ${'[">=0.7.x", loose=False, include_prerelease=False]'}                         | ${'0.7.2'}           | ${true}
+    ${'["<=0.7.x", loose=False, include_prerelease=False]'}                         | ${'0.6.2'}           | ${true}
+    ${'["~1.2.1 >=1.2.3", loose=False, include_prerelease=False]'}                  | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 =1.2.3", loose=False, include_prerelease=False]'}                   | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 1.2.3", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 >=1.2.3 1.2.3", loose=False, include_prerelease=False]'}            | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 1.2.3 >=1.2.3", loose=False, include_prerelease=False]'}            | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 1.2.3", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'[">1.1.0 <2.0.0", include_prerelease=True]'}                                 | ${'1.2.3-dev.1+abc'} | ${true}
+    ${'["~ 1.0.3", loose=False, include_prerelease=False]'}                         | ${'1.0.12'}          | ${true}
+    ${'[">=1.2.1 1.2.3", loose=False, include_prerelease=False]'}                   | ${'1.2.3'}           | ${true}
+    ${'["1.2.3 >=1.2.1", loose=False, include_prerelease=False]'}                   | ${'1.2.3'}           | ${true}
+    ${'[">=1.2.3 >=1.2.1", loose=False, include_prerelease=False]'}                 | ${'1.2.3'}           | ${true}
+    ${'[">=1.2.1 >=1.2.3", loose=False, include_prerelease=False]'}                 | ${'1.2.3'}           | ${true}
+    ${'[">=1.2", loose=False, include_prerelease=False]'}                           | ${'1.2.8'}           | ${true}
+    ${'["^1.2.3", loose=False, include_prerelease=False]'}                          | ${'1.8.1'}           | ${true}
+    ${'["^0.1.2", loose=False, include_prerelease=False]'}                          | ${'0.1.2'}           | ${true}
+    ${'["^0.1", loose=False, include_prerelease=False]'}                            | ${'0.1.2'}           | ${true}
+    ${'["^0.0.1", loose=False, include_prerelease=False]'}                          | ${'0.0.1'}           | ${true}
+    ${'["^1.2", loose=False, include_prerelease=False]'}                            | ${'1.4.2'}           | ${true}
+    ${'["^1.2 ^1", loose=False, include_prerelease=False]'}                         | ${'1.4.2'}           | ${true}
+    ${'["^1.2.3-alpha", loose=False, include_prerelease=False]'}                    | ${'1.2.3-pre'}       | ${false}
+    ${'["^1.2.3-alpha", loose=False, include_prerelease=True]'}                     | ${'1.2.4-pre'}       | ${true}
+    ${'["^1.2.0-alpha", loose=False, include_prerelease=False]'}                    | ${'"1.2.0-pre'}      | ${false}
+    ${'["^0.0.1-alpha", loose=False, include_prerelease=False]'}                    | ${'0.0.1-beta'}      | ${false}
+    ${'["^0.1.1-alpha", loose=False, include_prerelease=False]'}                    | ${'"0.1.1-beta'}     | ${false}
+    ${'["^x", loose=False, include_prerelease=False]'}                              | ${'1.2.3'}           | ${true}
+    ${'["x - 1.0.0", loose=False, include_prerelease=False]'}                       | ${'0.9.7'}           | ${true}
+    ${'["x - 1.x", loose=False, include_prerelease=False]'}                         | ${'0.9.7'}           | ${true}
+    ${'["1.0.0 - x", loose=False, include_prerelease=False]'}                       | ${'1.9.7'}           | ${true}
+    ${'["1.x - x", loose=False, include_prerelease=False]'}                         | ${'1.9.7'}           | ${true}
+    ${'["<=7.x", loose=False, include_prerelease=False]'}                           | ${'7.9.9'}           | ${true}
+    ${'[>1.1.0 <2.0.0]'}                                                            | ${'1.2.3-dev.1+abc'} | ${false}
+    ${'[">1.0.0 <1.0.2", loose=False, include_prerelease=True]'}                    | ${'1.0.2-beta'}      | ${true}
+    ${'[">1.1.0 <2.0.0", include_prerelease=False]'}                                | ${'1.2.3-dev.1+abc'} | ${false}
+    ${'["1.0.0 - 2.0.0", loose=False]'}                                             | ${'2.2.3'}           | ${true}
+    ${'["1.2.3+asdf - 2.4.3+asdf", loose=False]'}                                   | ${'1.2.3-pre.2'}     | ${false}
+    ${'["1.2.3+asdf - 2.4.3+asdf", loose=False]'}                                   | ${'2.4.3-alpha'}     | ${false}
+    ${'["^1.2.3+build", loose=False]'}                                              | ${'2.0.0'}           | ${true}
+    ${'["^1.2.3+build", loose=False]'}                                              | ${'1.2.0'}           | ${false}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'1.2.3-pre'}       | ${false}
+    ${'["^1.2", loose=False]'}                                                      | ${'1.2.0-pre'}       | ${false}
+    ${'[">1.2", loose=False]'}                                                      | ${'1.3.0-beta'}      | ${false}
+    ${'["<=1.2.3", loose=False]'}                                                   | ${'1.2.3-beta'}      | ${false}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'1.2.3-beta'}      | ${false}
+    ${'["=0.7.x", loose=False]'}                                                    | ${'0.7.0-asdf'}      | ${false}
+    ${'[">=0.7.x", loose=False]'}                                                   | ${'0.7.0-asdf'}      | ${false}
+    ${'["1", loose=True]'}                                                          | ${'1.0.0beta'}       | ${false}
+    ${'["<1", loose=True]'}                                                         | ${'1.0.0beta'}       | ${false}
+    ${'["< 1", loose=True]'}                                                        | ${'1.0.0beta'}       | ${false}
+    ${'["1.0.0", loose=False]'}                                                     | ${'1.0.1'}           | ${true}
+    ${'[">=1.0.0", loose=False]'}                                                   | ${'0.0.0'}           | ${false}
+    ${'[">=1.0.0", loose=False]'}                                                   | ${'0.0.1'}           | ${false}
+    ${'[">=1.0.0", loose=False]'}                                                   | ${'0.1.0'}           | ${false}
+    ${'[">1.0.0", loose=False]'}                                                    | ${'0.0.1'}           | ${false}
+    ${'[">1.0.0", loose=False]'}                                                    | ${'0.1.0'}           | ${false}
+    ${'["<=2.0.0", loose=False]'}                                                   | ${'3.0.0'}           | ${true}
+    ${'["<=2.0.0", loose=False]'}                                                   | ${'2.9999.9999'}     | ${true}
+    ${'["<=2.0.0", loose=False]'}                                                   | ${'2.2.9'}           | ${true}
+    ${'["<2.0.0", loose=False]'}                                                    | ${'2.9999.9999'}     | ${true}
+    ${'["<2.0.0", loose=False]'}                                                    | ${'2.2.9'}           | ${true}
+    ${'[">=0.1.97", loose=True]'}                                                   | ${'v0.1.93'}         | ${false}
+    ${'[">=0.1.97", loose=False]'}                                                  | ${'0.1.93'}          | ${false}
+    ${'["0.1.20 || 1.2.4", loose=False]'}                                           | ${'1.2.3'}           | ${true}
+    ${'[">=0.2.3 || <0.0.1", loose=False]'}                                         | ${'0.0.3'}           | ${true}
+    ${'[">=0.2.3 || <0.0.1", loose=False]'}                                         | ${'0.2.2'}           | ${true}
+    ${'["2.x.x", loose=False]'}                                                     | ${'1.1.3'}           | ${false}
+    ${'["2.x.x", loose=False]'}                                                     | ${'3.1.3'}           | ${true}
+    ${'["1.2.x", loose=False]'}                                                     | ${'1.3.3'}           | ${true}
+    ${'["1.2.x || 2.x", loose=False]'}                                              | ${'3.1.3'}           | ${true}
+    ${'["1.2.x || 2.x", loose=False]'}                                              | ${'1.1.3'}           | ${false}
+    ${'["2.*.*", loose=False]'}                                                     | ${'1.1.3'}           | ${false}
+    ${'["2.*.*", loose=False]'}                                                     | ${'3.1.3'}           | ${true}
+    ${'["1.2.*", loose=False]'}                                                     | ${'1.3.3'}           | ${true}
+    ${'["1.2.* || 2.*", loose=False]'}                                              | ${'3.1.3'}           | ${true}
+    ${'["1.2.* || 2.*", loose=False]'}                                              | ${'1.1.3'}           | ${false}
+    ${'["2", loose=False]'}                                                         | ${'1.1.2'}           | ${false}
+    ${'["2.3", loose=False]'}                                                       | ${'2.4.1'}           | ${true}
+    ${'["~2.4", loose=False]'}                                                      | ${'2.5.0'}           | ${true}
+    ${'["~2.4", loose=False]'}                                                      | ${'2.3.9'}           | ${false}
+    ${'["~>3.2.1", loose=False]'}                                                   | ${'3.3.2'}           | ${true}
+    ${'["~>3.2.1", loose=False]'}                                                   | ${'3.2.0'}           | ${false}
+    ${'["~1", loose=False]'}                                                        | ${'0.2.3'}           | ${false}
+    ${'["~>1", loose=False]'}                                                       | ${'2.2.3'}           | ${true}
+    ${'["~1.0", loose=False]'}                                                      | ${'1.1.0'}           | ${true}
+    ${'["<1", loose=False]'}                                                        | ${'1.0.0'}           | ${true}
+    ${'[">=1.2", loose=False]'}                                                     | ${'1.1.1'}           | ${false}
+    ${'["1", loose=True]'}                                                          | ${'2.0.0beta'}       | ${false}
+    ${'["~v0.5.4-beta", loose=False]'}                                              | ${'0.5.4-alpha'}     | ${false}
+    ${'["=0.7.x", loose=False]'}                                                    | ${'0.8.2'}           | ${true}
+    ${'[">=0.7.x", loose=False]'}                                                   | ${'0.6.2'}           | ${false}
+    ${'["<0.7.x", loose=False]'}                                                    | ${'0.7.2'}           | ${true}
+    ${'["<1.2.3", loose=False]'}                                                    | ${'1.2.3-beta'}      | ${false}
+    ${'["=1.2.3", loose=False]'}                                                    | ${'1.2.3-beta'}      | ${false}
+    ${'[">1.2", loose=False]'}                                                      | ${'1.2.8'}           | ${false}
+    ${'["^0.0.1", loose=False]'}                                                    | ${'0.0.2'}           | ${true}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'2.0.0-alpha'}     | ${false}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'1.2.2'}           | ${false}
+    ${'["^1.2", loose=False]'}                                                      | ${'1.1.9'}           | ${false}
+    ${'["*", loose=True]'}                                                          | ${'v1.2.3-foo'}      | ${false}
+    ${'["blerg", loose=False]'}                                                     | ${'1.2.3'}           | ${true}
+    ${'["git+https: #user:password0123@github.com/foo", loose=True]'}               | ${'123.0.0'}         | ${true}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'2.0.0-pre'}       | ${false}
+    ${'[~=1.18]'}                                                                   | ${'1.20.0'}          | ${true}
+    ${'[0.2.0]'}                                                                    | ${'0.3.0'}           | ${true}
+    ${'[~8.4.0, loose=False]'}                                                      | ${'8.5.0'}           | ${true}
+    ${'[~=1.0 include_prerelease=True]'}                                            | ${'1.21.2'}          | ${true}
+    ${'1.0.7'}                                                                      | ${'1.21.2'}          | ${true}
+    ${'16.00'}                                                                      | ${'19.00'}           | ${true}
+  `(
+    'isCompatible("$version", "$range") === $result',
+    ({ version, range, result }) => {
+      const res = !!conan.isCompatible(version, range);
+      expect(res).toBe(result);
+    }
+  );
+
+  // matches(version: string, range: string | Range): string | boolean | null;
+  test.each`
+    range                                                                           | version              | result
+    ${'[>1.1 <2.0]'}                                                                | ${'1.2.3'}           | ${true}
+    ${'["~1.2.3", loose=False, include_prerelease=True]'}                           | ${'1.2.3-pre.1'}     | ${true}
+    ${'["1.0.0 - 2.0.0", loose=False, include_prerelease=False]'}                   | ${'1.2.3'}           | ${true}
+    ${'["^1.2.3+build", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'["^1.2.3+build", loose=False, include_prerelease=False]'}                    | ${'1.3.0'}           | ${true}
+    ${'["1.2.3-pre+asdf - 2.4.3-pre+asdf", loose=False, include_prerelease=False]'} | ${'1.2.3'}           | ${true}
+    ${'["1.2.3pre+asdf - 2.4.3-pre+asdf", loose=True, include_prerelease=False]'}   | ${'1.2.3'}           | ${true}
+    ${'["1.2.3-pre+asdf - 2.4.3pre+asdf", loose=True, include_prerelease=False]'}   | ${'1.2.3'}           | ${true}
+    ${'["1.2.3pre+asdf - 2.4.3pre+asdf", loose=True, include_prerelease=False]'}    | ${'1.2.3'}           | ${true}
+    ${'["1.2.3-pre+asdf - 2.4.3-pre+asdf", loose=False, include_prerelease=False]'} | ${'1.2.3-pre.2'}     | ${true}
+    ${'["1.2.3-pre+asdf - 2.4.3-pre+asdf", loose=False, include_prerelease=False]'} | ${'2.4.3-alpha'}     | ${true}
+    ${'["1.2.3+asdf - 2.4.3+asdf", loose=False, include_prerelease=False]'}         | ${'1.2.3'}           | ${true}
+    ${'["1.0.0", loose=False, include_prerelease=False]'}                           | ${'1.0.0'}           | ${true}
+    ${'[">=*", loose=False, include_prerelease=False]'}                             | ${'0.2.4'}           | ${true}
+    ${'["", loose=False, include_prerelease=False]'}                                | ${'1.0.0'}           | ${true}
+    ${'["*", loose=False, include_prerelease=False]'}                               | ${'1.2.3'}           | ${true}
+    ${'["*", loose=True, include_prerelease=False]'}                                | ${'v1.2.3'}          | ${true}
+    ${'[">=1.0.0", loose=False, include_prerelease=False]'}                         | ${'1.0.0'}           | ${true}
+    ${'[">=1.0.0", loose=False, include_prerelease=False]'}                         | ${'1.0.1'}           | ${true}
+    ${'[">=1.0.0", loose=False, include_prerelease=False]'}                         | ${'1.1.0'}           | ${true}
+    ${'[">1.0.0", loose=False, include_prerelease=False]'}                          | ${'1.0.1'}           | ${true}
+    ${'[">1.0.0", loose=False, include_prerelease=True]'}                           | ${'1.0.1-pre.1'}     | ${true}
+    ${'[">1.0.0", loose=False, include_prerelease=False]'}                          | ${'1.1.0'}           | ${true}
+    ${'["<=2.0.0", loose=False, include_prerelease=False]'}                         | ${'2.0.0'}           | ${true}
+    ${'["<=2.0.0", loose=False, include_prerelease=False]'}                         | ${'1.9999.9999'}     | ${true}
+    ${'["<=2.0.0", loose=False, include_prerelease=False]'}                         | ${'0.2.9'}           | ${true}
+    ${'["<2.0.0", loose=False, include_prerelease=False]'}                          | ${'1.9999.9999'}     | ${true}
+    ${'["<2.0.0", loose=False, include_prerelease=False]'}                          | ${'0.2.9'}           | ${true}
+    ${'[">= 1.0.0", loose=False, include_prerelease=False]'}                        | ${'1.0.0'}           | ${true}
+    ${'[">=  1.0.0", loose=False, include_prerelease=False]'}                       | ${'1.0.1'}           | ${true}
+    ${'[">=   1.0.0", loose=False, include_prerelease=False]'}                      | ${'1.1.0'}           | ${true}
+    ${'["> 1.0.0", loose=False, include_prerelease=False]'}                         | ${'1.0.1'}           | ${true}
+    ${'[">  1.0.0", loose=False, include_prerelease=False]'}                        | ${'1.1.0'}           | ${true}
+    ${'["<=   2.0.0", loose=False, include_prerelease=False]'}                      | ${'2.0.0'}           | ${true}
+    ${'["<= 2.0.0", loose=False, include_prerelease=False]'}                        | ${'1.9999.9999'}     | ${true}
+    ${'["<=  2.0.0", loose=False, include_prerelease=False]'}                       | ${'0.2.9'}           | ${true}
+    ${'["<    2.0.0", loose=False, include_prerelease=False]'}                      | ${'1.9999.9999'}     | ${true}
+    ${'["<\t2.0.0", loose=False, include_prerelease=False]'}                        | ${'0.2.9'}           | ${true}
+    ${'[">=0.1.97", loose=True, include_prerelease=False]'}                         | ${'v0.1.97'}         | ${true}
+    ${'[">=0.1.97", loose=False, include_prerelease=False]'}                        | ${'0.1.97'}          | ${true}
+    ${'["0.1.20 || 1.2.4", loose=False, include_prerelease=False]'}                 | ${'1.2.4'}           | ${true}
+    ${'[">=0.2.3 || <0.0.1", loose=False, include_prerelease=False]'}               | ${'0.0.0'}           | ${true}
+    ${'[">=0.2.3 || <0.0.1", loose=False, include_prerelease=False]'}               | ${'0.2.3'}           | ${true}
+    ${'[">=0.2.3 || <0.0.1", loose=False, include_prerelease=False]'}               | ${'0.2.4'}           | ${true}
+    ${'["||", loose=False, include_prerelease=False]'}                              | ${'1.3.4'}           | ${true}
+    ${'["2.x.x", loose=False, include_prerelease=False]'}                           | ${'2.1.3'}           | ${true}
+    ${'["1.2.x", loose=False, include_prerelease=False]'}                           | ${'1.2.3'}           | ${true}
+    ${'["1.2.x || 2.x", loose=False, include_prerelease=False]'}                    | ${'2.1.3'}           | ${true}
+    ${'["1.2.x || 2.x", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'["x", loose=False, include_prerelease=False]'}                               | ${'1.2.3'}           | ${true}
+    ${'["2.*.*", loose=False, include_prerelease=False]'}                           | ${'2.1.3'}           | ${true}
+    ${'["1.2.*", loose=False, include_prerelease=False]'}                           | ${'1.2.3'}           | ${true}
+    ${'["1.2.* || 2.*", loose=False, include_prerelease=False]'}                    | ${'2.1.3'}           | ${true}
+    ${'["1.2.* || 2.*", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'["*", loose=False, include_prerelease=False]'}                               | ${'1.2.3'}           | ${true}
+    ${'["2", loose=False, include_prerelease=False]'}                               | ${'2.1.2'}           | ${true}
+    ${'["2.3", loose=False, include_prerelease=False]'}                             | ${'2.3.1'}           | ${true}
+    ${'["~x", loose=False, include_prerelease=False]'}                              | ${'0.0.9'}           | ${true}
+    ${'["~2", loose=False, include_prerelease=False]'}                              | ${'2.0.9'}           | ${true}
+    ${'["~2.4", loose=False, include_prerelease=False]'}                            | ${'2.4.0'}           | ${true}
+    ${'["~2.4", loose=False, include_prerelease=False]'}                            | ${'2.4.5'}           | ${true}
+    ${'["~>3.2.1", loose=False, include_prerelease=False]'}                         | ${'3.2.2'}           | ${true}
+    ${'["~1", loose=False, include_prerelease=False]'}                              | ${'1.2.3'}           | ${true}
+    ${'["~>1", loose=False, include_prerelease=False]'}                             | ${'1.2.3'}           | ${true}
+    ${'["~> 1", loose=False, include_prerelease=False]'}                            | ${'1.2.3'}           | ${true}
+    ${'["~1.0", loose=False, include_prerelease=False]'}                            | ${'1.0.2'}           | ${true}
+    ${'["~ 1.0", loose=False, include_prerelease=False]'}                           | ${'1.0.2'}           | ${true}
+    ${'[">=1", loose=False, include_prerelease=False]'}                             | ${'1.0.0'}           | ${true}
+    ${'[">= 1", loose=False, include_prerelease=False]'}                            | ${'1.0.0'}           | ${true}
+    ${'["<1.2", loose=False, include_prerelease=False]'}                            | ${'1.1.1'}           | ${true}
+    ${'["< 1.2", loose=False, include_prerelease=False]'}                           | ${'1.1.1'}           | ${true}
+    ${'["~v0.5.4-pre", loose=False, include_prerelease=False]'}                     | ${'0.5.5'}           | ${true}
+    ${'["~v0.5.4-pre", loose=False, include_prerelease=False]'}                     | ${'0.5.4'}           | ${true}
+    ${'["=0.7.x", loose=False, include_prerelease=False]'}                          | ${'0.7.2'}           | ${true}
+    ${'["<=0.7.x", loose=False, include_prerelease=False]'}                         | ${'0.7.2'}           | ${true}
+    ${'[">=0.7.x", loose=False, include_prerelease=False]'}                         | ${'0.7.2'}           | ${true}
+    ${'["<=0.7.x", loose=False, include_prerelease=False]'}                         | ${'0.6.2'}           | ${true}
+    ${'["~1.2.1 >=1.2.3", loose=False, include_prerelease=False]'}                  | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 =1.2.3", loose=False, include_prerelease=False]'}                   | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 1.2.3", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 >=1.2.3 1.2.3", loose=False, include_prerelease=False]'}            | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 1.2.3 >=1.2.3", loose=False, include_prerelease=False]'}            | ${'1.2.3'}           | ${true}
+    ${'["~1.2.1 1.2.3", loose=False, include_prerelease=False]'}                    | ${'1.2.3'}           | ${true}
+    ${'[">1.1.0 <2.0.0", include_prerelease=True]'}                                 | ${'1.2.3-dev.1+abc'} | ${true}
+    ${'["~ 1.0.3", loose=False, include_prerelease=False]'}                         | ${'1.0.12'}          | ${true}
+    ${'[">=1.2.1 1.2.3", loose=False, include_prerelease=False]'}                   | ${'1.2.3'}           | ${true}
+    ${'["1.2.3 >=1.2.1", loose=False, include_prerelease=False]'}                   | ${'1.2.3'}           | ${true}
+    ${'[">=1.2.3 >=1.2.1", loose=False, include_prerelease=False]'}                 | ${'1.2.3'}           | ${true}
+    ${'[">=1.2.1 >=1.2.3", loose=False, include_prerelease=False]'}                 | ${'1.2.3'}           | ${true}
+    ${'[">=1.2", loose=False, include_prerelease=False]'}                           | ${'1.2.8'}           | ${true}
+    ${'["^1.2.3", loose=False, include_prerelease=False]'}                          | ${'1.8.1'}           | ${true}
+    ${'["^0.1.2", loose=False, include_prerelease=False]'}                          | ${'0.1.2'}           | ${true}
+    ${'["^0.1", loose=False, include_prerelease=False]'}                            | ${'0.1.2'}           | ${true}
+    ${'["^0.0.1", loose=False, include_prerelease=False]'}                          | ${'0.0.1'}           | ${true}
+    ${'["^1.2", loose=False, include_prerelease=False]'}                            | ${'1.4.2'}           | ${true}
+    ${'["^1.2 ^1", loose=False, include_prerelease=False]'}                         | ${'1.4.2'}           | ${true}
+    ${'["^1.2.3-alpha", loose=False, include_prerelease=False]'}                    | ${'1.2.3-pre'}       | ${true}
+    ${'["^1.2.3-alpha", loose=False, include_prerelease=True]'}                     | ${'1.2.4-pre'}       | ${true}
+    ${'["^1.2.0-alpha", loose=False, include_prerelease=False]'}                    | ${'"1.2.0-pre'}      | ${true}
+    ${'["^0.0.1-alpha", loose=False, include_prerelease=False]'}                    | ${'0.0.1-beta'}      | ${true}
+    ${'["^0.1.1-alpha", loose=False, include_prerelease=False]'}                    | ${'"0.1.1-beta'}     | ${true}
+    ${'["^x", loose=False, include_prerelease=False]'}                              | ${'1.2.3'}           | ${true}
+    ${'["x - 1.0.0", loose=False, include_prerelease=False]'}                       | ${'0.9.7'}           | ${true}
+    ${'["x - 1.x", loose=False, include_prerelease=False]'}                         | ${'0.9.7'}           | ${true}
+    ${'["1.0.0 - x", loose=False, include_prerelease=False]'}                       | ${'1.9.7'}           | ${true}
+    ${'["1.x - x", loose=False, include_prerelease=False]'}                         | ${'1.9.7'}           | ${true}
+    ${'["<=7.x", loose=False, include_prerelease=False]'}                           | ${'7.9.9'}           | ${true}
+    ${'[>1.1.0 <2.0.0]'}                                                            | ${'1.2.3-dev.1+abc'} | ${false}
+    ${'[">1.0.0 <1.0.2", loose=False, include_prerelease=True]'}                    | ${'1.0.2-beta'}      | ${false}
+    ${'[">1.1.0 <2.0.0", include_prerelease=False]'}                                | ${'1.2.3-dev.1+abc'} | ${false}
+    ${'["1.0.0 - 2.0.0", loose=False]'}                                             | ${'2.2.3'}           | ${false}
+    ${'["1.2.3+asdf - 2.4.3+asdf", loose=False]'}                                   | ${'1.2.3-pre.2'}     | ${false}
+    ${'["1.2.3+asdf - 2.4.3+asdf", loose=False]'}                                   | ${'2.4.3-alpha'}     | ${false}
+    ${'["^1.2.3+build", loose=False]'}                                              | ${'2.0.0'}           | ${false}
+    ${'["^1.2.3+build", loose=False]'}                                              | ${'1.2.0'}           | ${false}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'1.2.3-pre'}       | ${false}
+    ${'["^1.2", loose=False]'}                                                      | ${'1.2.0-pre'}       | ${false}
+    ${'[">1.2", loose=False]'}                                                      | ${'1.3.0-beta'}      | ${false}
+    ${'["<=1.2.3", loose=False]'}                                                   | ${'1.2.3-beta'}      | ${false}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'1.2.3-beta'}      | ${false}
+    ${'["=0.7.x", loose=False]'}                                                    | ${'0.7.0-asdf'}      | ${false}
+    ${'[">=0.7.x", loose=False]'}                                                   | ${'0.7.0-asdf'}      | ${false}
+    ${'["1", loose=True]'}                                                          | ${'1.0.0beta'}       | ${false}
+    ${'["<1", loose=True]'}                                                         | ${'1.0.0beta'}       | ${false}
+    ${'["< 1", loose=True]'}                                                        | ${'1.0.0beta'}       | ${false}
+    ${'["1.0.0", loose=False]'}                                                     | ${'1.0.1'}           | ${false}
+    ${'[">=1.0.0", loose=False]'}                                                   | ${'0.0.0'}           | ${false}
+    ${'[">=1.0.0", loose=False]'}                                                   | ${'0.0.1'}           | ${false}
+    ${'[">=1.0.0", loose=False]'}                                                   | ${'0.1.0'}           | ${false}
+    ${'[">1.0.0", loose=False]'}                                                    | ${'0.0.1'}           | ${false}
+    ${'[">1.0.0", loose=False]'}                                                    | ${'0.1.0'}           | ${false}
+    ${'["<=2.0.0", loose=False]'}                                                   | ${'3.0.0'}           | ${false}
+    ${'["<=2.0.0", loose=False]'}                                                   | ${'2.9999.9999'}     | ${false}
+    ${'["<=2.0.0", loose=False]'}                                                   | ${'2.2.9'}           | ${false}
+    ${'["<2.0.0", loose=False]'}                                                    | ${'2.9999.9999'}     | ${false}
+    ${'["<2.0.0", loose=False]'}                                                    | ${'2.2.9'}           | ${false}
+    ${'[">=0.1.97", loose=True]'}                                                   | ${'v0.1.93'}         | ${false}
+    ${'[">=0.1.97", loose=False]'}                                                  | ${'0.1.93'}          | ${false}
+    ${'["0.1.20 || 1.2.4", loose=False]'}                                           | ${'1.2.3'}           | ${false}
+    ${'[">=0.2.3 || <0.0.1", loose=False]'}                                         | ${'0.0.3'}           | ${false}
+    ${'[">=0.2.3 || <0.0.1", loose=False]'}                                         | ${'0.2.2'}           | ${false}
+    ${'["2.x.x", loose=False]'}                                                     | ${'1.1.3'}           | ${false}
+    ${'["2.x.x", loose=False]'}                                                     | ${'3.1.3'}           | ${false}
+    ${'["1.2.x", loose=False]'}                                                     | ${'1.3.3'}           | ${false}
+    ${'["1.2.x || 2.x", loose=False]'}                                              | ${'3.1.3'}           | ${false}
+    ${'["1.2.x || 2.x", loose=False]'}                                              | ${'1.1.3'}           | ${false}
+    ${'["2.*.*", loose=False]'}                                                     | ${'1.1.3'}           | ${false}
+    ${'["2.*.*", loose=False]'}                                                     | ${'3.1.3'}           | ${false}
+    ${'["1.2.*", loose=False]'}                                                     | ${'1.3.3'}           | ${false}
+    ${'["1.2.* || 2.*", loose=False]'}                                              | ${'3.1.3'}           | ${false}
+    ${'["1.2.* || 2.*", loose=False]'}                                              | ${'1.1.3'}           | ${false}
+    ${'["2", loose=False]'}                                                         | ${'1.1.2'}           | ${false}
+    ${'["2.3", loose=False]'}                                                       | ${'2.4.1'}           | ${false}
+    ${'["~2.4", loose=False]'}                                                      | ${'2.5.0'}           | ${false}
+    ${'["~2.4", loose=False]'}                                                      | ${'2.3.9'}           | ${false}
+    ${'["~>3.2.1", loose=False]'}                                                   | ${'3.3.2'}           | ${false}
+    ${'["~>3.2.1", loose=False]'}                                                   | ${'3.2.0'}           | ${false}
+    ${'["~1", loose=False]'}                                                        | ${'0.2.3'}           | ${false}
+    ${'["~>1", loose=False]'}                                                       | ${'2.2.3'}           | ${false}
+    ${'["~1.0", loose=False]'}                                                      | ${'1.1.0'}           | ${false}
+    ${'["<1", loose=False]'}                                                        | ${'1.0.0'}           | ${false}
+    ${'[">=1.2", loose=False]'}                                                     | ${'1.1.1'}           | ${false}
+    ${'["1", loose=True]'}                                                          | ${'2.0.0beta'}       | ${false}
+    ${'["~v0.5.4-beta", loose=False]'}                                              | ${'0.5.4-alpha'}     | ${false}
+    ${'["=0.7.x", loose=False]'}                                                    | ${'0.8.2'}           | ${false}
+    ${'[">=0.7.x", loose=False]'}                                                   | ${'0.6.2'}           | ${false}
+    ${'["<0.7.x", loose=False]'}                                                    | ${'0.7.2'}           | ${false}
+    ${'["<1.2.3", loose=False]'}                                                    | ${'1.2.3-beta'}      | ${false}
+    ${'["=1.2.3", loose=False]'}                                                    | ${'1.2.3-beta'}      | ${false}
+    ${'[">1.2", loose=False]'}                                                      | ${'1.2.8'}           | ${false}
+    ${'["^0.0.1", loose=False]'}                                                    | ${'0.0.2'}           | ${false}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'2.0.0-alpha'}     | ${false}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'1.2.2'}           | ${false}
+    ${'["^1.2", loose=False]'}                                                      | ${'1.1.9'}           | ${false}
+    ${'["*", loose=True]'}                                                          | ${'v1.2.3-foo'}      | ${false}
+    ${'["blerg", loose=False]'}                                                     | ${'1.2.3'}           | ${false}
+    ${'["git+https: #user:password0123@github.com/foo", loose=True]'}               | ${'123.0.0'}         | ${false}
+    ${'["^1.2.3", loose=False]'}                                                    | ${'2.0.0-pre'}       | ${false}
+    ${'[~=1.18]'}                                                                   | ${'1.20.0'}          | ${false}
+    ${'[0.2.0]'}                                                                    | ${'0.3.0'}           | ${false}
+    ${'[~8.4.0, loose=False]'}                                                      | ${'8.5.0'}           | ${false}
+    ${'[~=1.0 include_prerelease=True]'}                                            | ${'1.21.2'}          | ${false}
+    ${'1.0.7'}                                                                      | ${'1.21.2'}          | ${true}
+    ${'16.00'}                                                                      | ${'19.00'}           | ${true}
+  `(
+    'matches("$version", "$range") === $result',
+    ({ version, range, result }) => {
+      const res = !!conan.matches(version, range);
+      expect(res).toBe(result);
+    }
+  );
+
+  // isStable(version: string): boolean;
+  test.each`
+    version                                          | result
+    ${'5.0.1'}                                       | ${true}
+    ${'19.00'}                                       | ${true}
+    ${'1.0.7-prerelease.1'}                          | ${false}
+    ${'1.0.7-prerelease.1, include_prerelease=True'} | ${true}
+  `('isStable("$version") === $result', ({ version, result }) => {
+    const res = conan.isStable(version);
+    expect(res).toBe(result);
+  });
+
+  // getNewValue(newValueConfig: NewValueConfig): string;
+  test.each`
+    currentValue                                          | rangeStrategy | currentVersion                     | newVersion                         | result
+    ${'[<=1.2.3]'}                                        | ${'widen'}    | ${'1.0.0'}                         | ${'1.2.3'}                         | ${'[<=1.2.3]'}
+    ${'[<1.2.3]'}                                         | ${'widen'}    | ${'1.5.5'}                         | ${'1.5.6'}                         | ${'[<1.5.7]'}
+    ${'[>1.2.7 >3.0.0 5.0]'}                              | ${'widen'}    | ${'0.1.21'}                        | ${'0.1.24'}                        | ${'[>1.2.7 >3.0.0 5.0 || 0.1.24]'}
+    ${'[>=1.2.7 >3.0.0 >5.0]'}                            | ${'widen'}    | ${'0.1.21'}                        | ${'0.1.24'}                        | ${null}
+    ${'[>=1.2.7]'}                                        | ${'widen'}    | ${'0.1.21'}                        | ${'0.1.24'}                        | ${'[>=1.2.7 || 0.1.24]'}
+    ${'[<= 1.2.3]'}                                       | ${'widen'}    | ${'1.0.0'}                         | ${'1.2.4'}                         | ${'[<= 1.2.4]'}
+    ${'[4.5.5 - 1.2.3 - 2.0]'}                            | ${'widen'}    | ${'1.0.0'}                         | ${'1.4.8'}                         | ${'[4.5.5 - 1.2.3 - 1.4.8]'}
+    ${'1.0.0'}                                            | ${'replace'}  | ${'1.0.0'}                         | ${'1.1.0'}                         | ${'1.1.0'}
+    ${'[<1.0.0]'}                                         | ${'replace'}  | ${'1.0.0'}                         | ${'2.1.0'}                         | ${'[<3.0.0]'}
+    ${'[<1.1]'}                                           | ${'replace'}  | ${'1.0.0'}                         | ${'2.1.0'}                         | ${'[<2.2]'}
+    ${'[1.0.*]'}                                          | ${'replace'}  | ${'1.0.0'}                         | ${'1.1.0'}                         | ${'[1.1.*]'}
+    ${'[1.*]'}                                            | ${'replace'}  | ${'1.0.0'}                         | ${'2.1.0'}                         | ${'[2.*]'}
+    ${'[1.0.x]'}                                          | ${'replace'}  | ${'1.0.0'}                         | ${'1.1.0'}                         | ${'[1.1.x]'}
+    ${'[1.x]'}                                            | ${'replace'}  | ${'1.0.0'}                         | ${'2.1.0'}                         | ${'[2.x]'}
+    ${'[~0.6]'}                                           | ${'replace'}  | ${'0.6.8'}                         | ${'0.7.0'}                         | ${'[~0.7.0]'}
+    ${'[~0.6.1]'}                                         | ${'replace'}  | ${'0.7.0'}                         | ${'0.7.0-rc.2'}                    | ${'[~0.7.0-rc]'}
+    ${'[~>0.6.1]'}                                        | ${'replace'}  | ${'0.7.0'}                         | ${'0.7.0-rc.2'}                    | ${'[~> 0.7.0]'}
+    ${'[<=1.2]'}                                          | ${'replace'}  | ${'1.0.0'}                         | ${'1.2.3'}                         | ${'[<=1.2]'}
+    ${'[<=1]'}                                            | ${'replace'}  | ${'1.0.0'}                         | ${'1.2.3'}                         | ${'[<=1]'}
+    ${'[<1.6.11]'}                                        | ${'replace'}  | ${'0.6.14'}                        | ${'1.6.14'}                        | ${'[<1.6.15]'}
+    ${'[0.2.0]'}                                          | ${'replace'}  | ${'0.6.14'}                        | ${'0.3.0'}                         | ${'[0.3.0]'}
+    ${'[< 1]'}                                            | ${'replace'}  | ${'1.0.0'}                         | ${'1.0.1'}                         | ${'[< 2]'}
+    ${'[<3.6 loose=False, include_prerelease=True]'}      | ${'replace'}  | ${'0.1'}                           | ${'3.7.0'}                         | ${'[<3.8 loose=False, include_prerelease=True]'}
+    ${'[<1.8 loose=False]'}                               | ${'replace'}  | ${'0.2'}                           | ${'1.17.1'}                        | ${'[<1.18 loose=False]'}
+    ${'[=8.4.0]'}                                         | ${'replace'}  | ${'0.6.14'}                        | ${'8.5.0'}                         | ${'[=8.5.0]'}
+    ${'[>8.0.0]'}                                         | ${'replace'}  | ${'0.6.14'}                        | ${'8.5.0'}                         | ${'[>9.0.0]'}
+    ${'[>8]'}                                             | ${'replace'}  | ${'0.6.14'}                        | ${'8.5.0'}                         | ${'[>8]'}
+    ${'[> 8]'}                                            | ${'replace'}  | ${'0.6.14'}                        | ${'8.5.0'}                         | ${'[>8]'}
+    ${'5.0.1'}                                            | ${'pin'}      | ${'5.0.1'}                         | ${'5.0.7'}                         | ${'5.0.7'}
+    ${'2.1'}                                              | ${'pin'}      | ${'2.1'}                           | ${'3.1'}                           | ${'3.1'}
+    ${'0.1'}                                              | ${'pin'}      | ${'0.1'}                           | ${'2.7.1'}                         | ${'2.7.1'}
+    ${'0.2'}                                              | ${'pin'}      | ${'0.2'}                           | ${'3.6.5'}                         | ${'3.6.5'}
+    ${'1.0'}                                              | ${'pin'}      | ${'1.0'}                           | ${'1.0.0'}                         | ${'1.0.0'}
+    ${'2.1'}                                              | ${'pin'}      | ${'2.1'}                           | ${'11.0.12'}                       | ${'11.0.12'}
+    ${'0.1'}                                              | ${'pin'}      | ${'0.1'}                           | ${'3.5.0'}                         | ${'3.5.0'}
+    ${'2.1'}                                              | ${'pin'}      | ${'2.1'}                           | ${'1.19.0'}                        | ${'1.19.0'}
+    ${'1.15.0'}                                           | ${'pin'}      | ${'1.15.0'}                        | ${'1.42.0'}                        | ${'1.42.0'}
+    ${'1.0'}                                              | ${'pin'}      | ${'1.0'}                           | ${'1.10.2'}                        | ${'1.10.2'}
+    ${'0.2'}                                              | ${'pin'}      | ${'0.2'}                           | ${'1.1.9'}                         | ${'1.1.9'}
+    ${'2.2'}                                              | ${'pin'}      | ${'2.2'}                           | ${'1.21.1'}                        | ${'1.21.1'}
+    ${'1.2'}                                              | ${'pin'}      | ${'1.2'}                           | ${'1.12.20'}                       | ${'1.12.20'}
+    ${'16.00'}                                            | ${'pin'}      | ${'16.00'}                         | ${'19.00'}                         | ${'19.00'}
+    ${'2.9.2'}                                            | ${'pin'}      | ${'2.9.2'}                         | ${'2.13.7'}                        | ${'2.13.7'}
+    ${'[^0.5.12]'}                                        | ${'pin'}      | ${'0.5.12'}                        | ${'0.5.13'}                        | ${'0.5.13'}
+    ${'0.5.12'}                                           | ${'pin'}      | ${'0.5.12'}                        | ${'0.5.13'}                        | ${'0.5.13'}
+    ${'5.0.20210712-T1759Z+b563c1478'}                    | ${'pin'}      | ${'5.0.20210712-T1759Z+b563c1478'} | ${'5.0.20211022-T0612Z+743f9e41b'} | ${'5.0.20211022-T0612Z+743f9e41b'}
+    ${'[=8.4.0]'}                                         | ${'bump'}     | ${'0.6.14'}                        | ${'8.5.0'}                         | ${'[=8.5.0]'}
+    ${'[~8.4.0, loose=False]'}                            | ${'bump'}     | ${'0.6.14'}                        | ${'8.5.0'}                         | ${'[~8.5.0, loose=False]'}
+    ${'[~0.7.15, loose=False, include_prerelease=True]'}  | ${'bump'}     | ${'0.6.14'}                        | ${'0.9.7'}                         | ${'[~0.9.7, loose=False, include_prerelease=True]'}
+    ${'[~=1.0 include_prerelease=True]'}                  | ${'bump'}     | ${'0.2'}                           | ${'1.21.1'}                        | ${'[~=1.21 include_prerelease=True]'}
+    ${'[~=1.18]'}                                         | ${'bump'}     | ${'0.6.14'}                        | ${'1.20.0'}                        | ${'[~=1.20]'}
+    ${'[0.2.0]'}                                          | ${'bump'}     | ${'0.6.14'}                        | ${'0.3.0'}                         | ${'[0.3.0]'}
+    ${'[~1]'}                                             | ${'bump'}     | ${'2'}                             | ${'1.1.7'}                         | ${'[~1]'}
+    ${'[~1]'}                                             | ${'bump'}     | ${'1.0.0'}                         | ${'2.1.7'}                         | ${'[~2]'}
+    ${'[~1.0]'}                                           | ${'bump'}     | ${'1.0.0'}                         | ${'1.1.7'}                         | ${'[~1.1]'}
+    ${'[~1.0.0]'}                                         | ${'bump'}     | ${'1.0.0'}                         | ${'1.1.7'}                         | ${'[~1.1.7]'}
+    ${'[~1.0]'}                                           | ${'bump'}     | ${'1.0.0'}                         | ${'1.0.7-prerelease.1'}            | ${'[~1.0.7-prerelease.1]'}
+    ${'[~1.0.7-prerelease.1]'}                            | ${'bump'}     | ${'1.0.0'}                         | ${'1.0.7-prerelease.1'}            | ${'[~1.0.7-prerelease.1]'}
+    ${'[5]'}                                              | ${'bump'}     | ${'5.0.0'}                         | ${'6.1.7'}                         | ${'[6]'}
+    ${'[>=1.0.0]'}                                        | ${'bump'}     | ${'1.0.0'}                         | ${'1.1.0'}                         | ${'[>=1.1.0]'}
+    ${'[<1.0.0]'}                                         | ${'bump'}     | ${'1.0.0'}                         | ${'1.1.0'}                         | ${'[<1.0.0]'}
+    ${'[>1.1 <3.0, include_prerelease=True]'}             | ${'bump'}     | ${'0.6.14'}                        | ${'1.1.1l'}                        | ${'[>1.1 <3.0, include_prerelease=True]'}
+    ${'[>= 0.0.1 < 1]'}                                   | ${'bump'}     | ${'1.0.0'}                         | ${'1.0.1'}                         | ${'[>= 1.0.1 < 2]'}
+    ${'[>3.0 <3.6 loose=False, include_prerelease=True]'} | ${'bump'}     | ${'0.1'}                           | ${'3.7.0'}                         | ${'[>3.7 <3.8 loose=False, include_prerelease=True]'}
+    ${'[>1.0 <1.8 loose=False]'}                          | ${'bump'}     | ${'0.2'}                           | ${'1.17.1'}                        | ${'[>1.17 <1.18 loose=False]'}
+    ${'[>0.6.7 <1.6.11]'}                                 | ${'bump'}     | ${'0.6.14'}                        | ${'1.6.14'}                        | ${'[>1.6.14 <1.6.15]'}
+    ${'[3.17.2 || 3.15.7]'}                               | ${'bump'}     | ${'0.6.14'}                        | ${'3.21.3'}                        | ${'[3.17.2 || 3.15.7 || 3.21.3]'}
+    ${'[>3.17.2 || 3.15.7]'}                              | ${'bump'}     | ${'0.6.14'}                        | ${'3.21.3'}                        | ${'[>3.21.3 || 3.15.7]'}
+    ${'[1.69.0 || >=1.71.0 <1.76.0]'}                     | ${'bump'}     | ${'0.6.14'}                        | ${'1.76.0'}                        | ${'[1.69.0 || >=1.76.0 <1.76.1]'}
+  `(
+    'getNewValue("$currentValue", "$rangeStrategy", "$currentVersion", "$newVersion") === "$result"',
+    ({ currentValue, rangeStrategy, currentVersion, newVersion, result }) => {
+      const res = conan.getNewValue({
+        currentValue,
+        rangeStrategy,
+        currentVersion,
+        newVersion,
+      });
+      expect(res).toEqual(result);
+    }
+  );
+
+  // getSatisfyingVersion(versions: string[], range: string): string | null;
+  test.each`
+    versions                                                                                   | range                                                              | result
+    ${['1.2.4', '1.2.3', '1.2.5-beta']}                                                        | ${'["~1.2.3", loose=False, include_prerelease=True]'}              | ${'1.2.5-beta'}
+    ${['1.2.4', '1.2.3', '1.2.5-beta']}                                                        | ${'["~1.2.3", loose=False, include_prerelease=False]'}             | ${'1.2.4'}
+    ${['1.2.3', '1.2.4']}                                                                      | ${'["1.2", loose=False, include_prerelease=False]'}                | ${'1.2.4'}
+    ${['1.2.4', '1.2.3']}                                                                      | ${'["1.2", loose=False, include_prerelease=False]'}                | ${'1.2.4'}
+    ${['1.2.3', '1.2.4', '1.2.5', '1.2.6']}                                                    | ${'["~1.2.3", loose=False, include_prerelease=False]'}             | ${'1.2.6'}
+    ${['1.0.1-beta']}                                                                          | ${'["1.x", loose=False, include_prerelease=False]'}                | ${null}
+    ${['1.0.1-beta']}                                                                          | ${'["1.x", loose=False, include_prerelease=True]'}                 | ${'1.0.1-beta'}
+    ${['1.0.0-beta']}                                                                          | ${'["1.x", loose=False, include_prerelease=True]'}                 | ${'1.0.0-beta'}
+    ${['1.1.0-beta']}                                                                          | ${'["1.0.x", loose=False, include_prerelease=True]'}               | ${null}
+    ${['1.0.0-beta', '1.1.0-beta', '1.1.0']}                                                   | ${'["1.0.x", loose=False, include_prerelease=False]'}              | ${null}
+    ${['1.0.0-beta', '1.1.0-beta', '1.1.0']}                                                   | ${'["1.0.x", loose=False, include_prerelease=True]'}               | ${'1.0.0-beta'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1-beta', '1.0.2-beta']}                                     | ${'[">1.0.0 <1.0.2", loose=False, include_prerelease=False]'}      | ${null}
+    ${['1.0.0-beta', '1.0.0', '1.0.1-beta', '1.0.2-beta']}                                     | ${'[">1.0.0 <1.0.2", loose=False, include_prerelease=True]'}       | ${'1.0.1-beta'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1', '1.1.0-beta', '1.1.0']}                                 | ${'[">1.0.0 <1.1.0", loose=False, include_prerelease=False]'}      | ${'1.0.1'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1', '1.1.0-beta', '1.1.0']}                                 | ${'[">1.0.0 <1.1.0", loose=False, include_prerelease=True]'}       | ${'1.0.1'}
+    ${['1.0.0-beta', '1.1.0-beta']}                                                            | ${'[">1.0.0 <1.1.0", loose=False, include_prerelease=True]'}       | ${null}
+    ${['1.0.0-beta', '1.1.0-beta', '1.0.0']}                                                   | ${'[">=1.0.0 <=1.0.1", loose=False, include_prerelease=False]'}    | ${'1.0.0'}
+    ${['1.0.0-beta', '1.1.0-beta', '1.0.0']}                                                   | ${'[">=1.0.0 <=1.0.1", loose=False, include_prerelease=True]'}     | ${'1.0.0'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1', '1.1.0-beta']}                                          | ${'[">=1.0.0 <=1.1.0", loose=False, include_prerelease=False]'}    | ${'1.0.1'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1', '1.1.0-beta']}                                          | ${'[">=1.0.0 <=1.1.0", loose=False, include_prerelease=True]'}     | ${'1.1.0-beta'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1', '1.1.0-beta']}                                          | ${'[">=1.0.0 <1.1.0", loose=False, include_prerelease=False]'}     | ${'1.0.1'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1', '1.1.0-beta']}                                          | ${'[">=1.0.0 <1.1.0", loose=False, include_prerelease=True]'}      | ${'1.0.1'}
+    ${['1.0.0-beta', '1.1.0-beta']}                                                            | ${'[">=1.0.0 <=1.1.0", loose=False, include_prerelease=False]'}    | ${null}
+    ${['1.0.0-beta', '1.1.0-beta']}                                                            | ${'[">=1.0.0 <=1.1.0", loose=False, include_prerelease=True]'}     | ${'1.1.0-beta'}
+    ${['1.0.0-beta', '1.1.0-beta', '1.0.0']}                                                   | ${'[">=1.0.0-0 <1.0.1", loose=False, include_prerelease=True]'}    | ${'1.0.0'}
+    ${['1.0.0-beta', '1.1.0-beta', '1.1.0']}                                                   | ${'[">=1.0.0-0 <1.1.0-0", loose=False, include_prerelease=True]'}  | ${'1.0.0-beta'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1', '1.1.0-beta', '1.1.0']}                                 | ${'[">=1.0.0-0 <1.1.0-0", loose=False, include_prerelease=False]'} | ${'1.0.1'}
+    ${['1.0.0-beta', '1.0.0', '1.0.1', '1.1.0-beta', '1.1.0']}                                 | ${'[">=1.0.0-0 <1.1.0-0", loose=False, include_prerelease=True]'}  | ${'1.0.1'}
+    ${['1.0.0-beta', '1.1.0-beta']}                                                            | ${'[">=1.0.0-0 <1.1.0", loose=False, include_prerelease=True]'}    | ${'1.0.0-beta'}
+    ${['1.0.0-pre']}                                                                           | ${'[1.0.x", loose=False, include_prerelease=True]'}                | ${'1.0.0-pre'}
+    ${['1.0.0-pre']}                                                                           | ${'[">=1.0.x", loose=False, include_prerelease=True]'}             | ${'1.0.0-pre'}
+    ${['1.1.0-pre']}                                                                           | ${'[">=1.0.0 <1.1.1-z", loose=False, include_prerelease=False]'}   | ${null}
+    ${['1.2.3', '1.2.4', '1.2.5', '1.2.6', '2.0.1']}                                           | ${'["~1.2.3", loose=False]'}                                       | ${'1.2.6'}
+    ${['1.1.0', '1.2.0', '1.3.0', '2.0.0b1', '2.0.0b3', '2.0.0', '2.1.0']}                     | ${'[~2.0.0]'}                                                      | ${'2.0.0'}
+    ${['1.1.0', '1.2.0', '1.3.0', '2.0.0b1', '2.0.0b3', '2.1.0']}                              | ${'["~2.0.0", loose=False]'}                                       | ${null}
+    ${['1.1.0', '1.2.0', '1.3.0', '2.0.0b1', '2.0.0b3', '2.0.1', '2.1.0']}                     | ${'["~2.0.0", loose=False]'}                                       | ${'2.0.1'}
+    ${['1.2.3', '1.2.4', '1.2.5', '1.2.6-pre.1', '2.0.1']}                                     | ${'["~1.2.3", loose=False, include_prerelease=True]'}              | ${'1.2.6-pre.1'}
+    ${['1.2.3', '1.2.4', '1.2.5', '1.2.6-pre.1', '2.0.1']}                                     | ${'["~1.2.3", loose=False, include_prerelease=False]'}             | ${'1.2.5'}
+    ${['1.2.3', '1.2.4', '1.2.5', '1.2.6-pre.1', '2.0.1']}                                     | ${'["~1.2.3", loose=False, include_prerelease=False]'}             | ${'1.2.5'}
+    ${['1.1.1', '1.2.0-pre', '1.2.0', '1.1.1-111', '1.1.1-21']}                                | ${'[<=1.2]'}                                                       | ${'1.2.0'}
+    ${['1.1.1', '1.2.0-pre', '1.2', '1.1.1-111', '1.1.1-21']}                                  | ${'[<=1.2]'}                                                       | ${'1.2'}
+    ${['1.1.1', '1.2.0-pre', '1.2.0', '1.1.1-111', '1.1.1-21']}                                | ${'[<=1.2.0]'}                                                     | ${'1.2.0'}
+    ${['1.1.1', '1.2.0-pre', '1.2', '1.1.1-111', '1.1.1-21']}                                  | ${'[<=1.2.0]'}                                                     | ${'1.2'}
+    ${['1.1.0', '1.2.0', '1.2.1', '1.3.0', '2.0.0b1', '2.0.0b2', '2.0.0b3', '2.0.0', '2.1.0']} | ${'["~2.0.0", loose=True, include_prerelease=False]'}              | ${'2.0.0'}
+    ${['1.1.0', '1.2.0', '1.2.1', '1.3.0', '2.0.0b1', '2.0.0b2', '2.0.0b3', '2.0.0', '2.1.0']} | ${'["~2.0.0", loose=False, include_prerelease=False]'}             | ${'2.0.0'}
+    ${['1.1.0', '1.2.0', '1.2.1', '1.3.0', '2.0.0b1', '2.0.0b2', '2.0.0', '2.0.1b1', '2.1.0']} | ${'["~2.0.0", loose=True, include_prerelease=False]'}              | ${'2.0.0'}
+    ${['1.1.0', '1.2.0', '1.2.1', '1.3.0', '2.0.0b1', '2.0.0b2', '2.0.0', '2.0.1b1', '2.1.0']} | ${'["~2.0.0", loose=True, include_prerelease=True]'}               | ${'2.0.1b1'}
+  `(
+    'getSatisfyingVersion("$versions", "$range") === "$result"',
+    ({ versions, range, result }) => {
+      const res = conan.getSatisfyingVersion(versions, range);
+      expect(res).toEqual(result);
+    }
+  );
+
+  // minSatisfyingVersion(versions: string[], range: string): string | null;
+  test.each`
+    versions                                                                                   | range                                                  | result
+    ${['1.2.3', '1.2.4', '1.2.5', '1.2.6', '2.0.1']}                                           | ${'["~1.2.3", loose=False]'}                           | ${'1.2.3'}
+    ${['1.1.0', '1.2.0', '1.3.0', '2.0.0b1', '2.0.0b3', '2.0.0', '2.1.0']}                     | ${'[~2.0.0]'}                                          | ${'2.0.0'}
+    ${['1.1.0', '1.2.0', '1.3.0', '2.0.0b1', '2.0.0b3', '2.1.0']}                              | ${'["~2.0.0", loose=False]'}                           | ${null}
+    ${['1.1.0', '1.2.0', '1.3.0', '2.0.0b1', '2.0.0b3', '2.0.1', '2.1.0']}                     | ${'["~2.0.0", loose=False]'}                           | ${'2.0.1'}
+    ${['1.2.3-pre.1', '1.2.4', '1.2.5', '1.2.6-pre.1', '2.0.1']}                               | ${'["~1.2.3", loose=False, include_prerelease=True]'}  | ${'1.2.3-pre.1'}
+    ${['1.2.3-pre.1', '1.2.4', '1.2.5', '1.2.6-pre.1', '2.0.1']}                               | ${'["~1.2.3", loose=False, include_prerelease=False]'} | ${'1.2.4'}
+    ${['1.2.3', '1.2.4']}                                                                      | ${'["1.2", loose=False]'}                              | ${'1.2.3'}
+    ${['1.2.4', '1.2.3']}                                                                      | ${'["1.2", loose=False]'}                              | ${'1.2.3'}
+    ${['1.2.3', '1.2.4', '1.2.5', '1.2.6']}                                                    | ${'[~1.2.3, loose=False]'}                             | ${'1.2.3'}
+    ${['1.1.0', '1.2.0', '1.2.1', '1.3.0', '2.0.0b1', '2.0.0b2', '2.0.0b3', '2.0.0', '2.1.0']} | ${'[~2.0.0, loose=True]'}                              | ${'2.0.0'}
+  `(
+    'minSatisfyingVersion("$versions", "$range") === "$result"',
+    ({ versions, range, result }) => {
+      const res = conan.minSatisfyingVersion(versions, range);
+      expect(res).toEqual(result);
+    }
+  );
+
+  // test 4-digit
+  test.each`
+    version                | major   | minor   | patch
+    ${'4.1.3'}             | ${4}    | ${1}    | ${3}
+    ${'4.1.3+jenkins'}     | ${4}    | ${1}    | ${3}
+    ${'4.1.3-pre'}         | ${4}    | ${1}    | ${3}
+    ${'4.1.3.2'}           | ${4}    | ${1}    | ${3}
+    ${'4.1.3.2+jenkins'}   | ${4}    | ${1}    | ${3}
+    ${'4.1.3.2-pre'}       | ${4}    | ${1}    | ${3}
+    ${'4.1.3.2-pre2'}      | ${4}    | ${1}    | ${3}
+    ${'4.1.3.2-pre.2'}     | ${4}    | ${1}    | ${3}
+    ${'4.1.3.2-pre.2+xxx'} | ${4}    | ${1}    | ${3}
+    ${'4.1.33.2'}          | ${4}    | ${1}    | ${33}
+    ${'1.a.2'}             | ${null} | ${null} | ${null}
+  `(
+    'getMajor("$version") === $major getMinor("$version") === $minor getPatch("$version") === $patch',
+    ({ version, major, minor, patch }) => {
+      expect(conan.getMajor(version)).toBe(major);
+      expect(conan.getMinor(version)).toBe(minor);
+      expect(conan.getPatch(version)).toBe(patch);
+    }
+  );
+
+  // getMajor(version: string): null | number;
+  test.each`
+    version       | result
+    ${'4.1.33.2'} | ${4}
+  `('getMajor("$version") === "$result"', ({ version, result }) => {
+    const res = conan.getMajor(version);
+    expect(res).toEqual(result);
+  });
+
+  // getMinor(version: string): null | number;
+  test.each`
+    version       | result
+    ${'1.2.3'}    | ${2}
+    ${'5.2.1'}    | ${2}
+    ${'4.1.33.2'} | ${1}
+  `('getMinor("$version") === "$result"', ({ version, result }) => {
+    const res = conan.getMinor(version);
+    expect(res).toEqual(result);
+  });
+
+  // getPatch(version: string): null | number;
+  test.each`
+    version       | result
+    ${'1.2.3'}    | ${3}
+    ${'5.2.1'}    | ${1}
+    ${'4.1.33.2'} | ${33}
+  `('getPatch("$version") === "$result"', ({ version, result }) => {
+    const res = conan.getPatch(version);
+    expect(res).toEqual(result);
+  });
+
+  // equals(version: string, other: string): boolean;
+  test.each`
+    version               | other                                     | result
+    ${'1.2.3'}            | ${'1.2.3'}                                | ${true}
+    ${'2.3.1'}            | ${'1.2.3'}                                | ${false}
+    ${'1.2.3'}            | ${'v1.2.3, loose=True'}                   | ${true}
+    ${'1.2.3'}            | ${'=1.2.3, loose=True'}                   | ${true}
+    ${'1.2.3'}            | ${'v 1.2.3, loose=True'}                  | ${true}
+    ${'1.2.3'}            | ${'= 1.2.3, loose=True'}                  | ${true}
+    ${'1.2.3'}            | ${' v1.2.3, loose=True'}                  | ${true}
+    ${'1.2.3'}            | ${' =1.2.3, loose=True'}                  | ${true}
+    ${'1.2.3'}            | ${' v 1.2.3, loose=True'}                 | ${true}
+    ${'1.2.3'}            | ${' = 1.2.3, loose=True'}                 | ${true}
+    ${'1.2.3-0'}          | ${'v1.2.3-0, loose=True'}                 | ${true}
+    ${'1.2.3-0'}          | ${'=1.2.3-0, loose=True'}                 | ${true}
+    ${'1.2.3-0'}          | ${'v 1.2.3-0, loose=True'}                | ${true}
+    ${'1.2.3-0'}          | ${'= 1.2.3-0, loose=True'}                | ${true}
+    ${'1.2.3-0'}          | ${' v1.2.3-0, loose=True'}                | ${true}
+    ${'1.2.3-0'}          | ${' =1.2.3-0, loose=True'}                | ${true}
+    ${'1.2.3-0'}          | ${' v 1.2.3-0, loose=True'}               | ${true}
+    ${'1.2.3-0'}          | ${' = 1.2.3-0, loose=True'}               | ${true}
+    ${'1.2.3-1'}          | ${'v1.2.3-1, loose=True'}                 | ${true}
+    ${'1.2.3-1'}          | ${'=1.2.3-1, loose=True'}                 | ${true}
+    ${'1.2.3-1'}          | ${'v 1.2.3-1, loose=True'}                | ${true}
+    ${'1.2.3-1'}          | ${'= 1.2.3-1, loose=True'}                | ${true}
+    ${'1.2.3-1'}          | ${' v1.2.3-1, loose=True'}                | ${true}
+    ${'1.2.3-1'}          | ${' =1.2.3-1, loose=True'}                | ${true}
+    ${'1.2.3-1'}          | ${' v 1.2.3-1, loose=True'}               | ${true}
+    ${'1.2.3-1'}          | ${' = 1.2.3-1, loose=True'}               | ${true}
+    ${'1.2.3-beta'}       | ${'v1.2.3-beta, loose=True'}              | ${true}
+    ${'1.2.3-beta'}       | ${'=1.2.3-beta, loose=True'}              | ${true}
+    ${'1.2.3-beta'}       | ${'v 1.2.3-beta, loose=True'}             | ${true}
+    ${'1.2.3-beta'}       | ${'= 1.2.3-beta, loose=True'}             | ${true}
+    ${'1.2.3-beta'}       | ${' v1.2.3-beta, loose=True'}             | ${true}
+    ${'1.2.3-beta'}       | ${' =1.2.3-beta, loose=True'}             | ${true}
+    ${'1.2.3-beta'}       | ${' v 1.2.3-beta, loose=True'}            | ${true}
+    ${'1.2.3-beta'}       | ${' = 1.2.3-beta, loose=True'}            | ${true}
+    ${'1.2.3-beta+build'} | ${' = 1.2.3-beta+otherbuild, loose=True'} | ${true}
+    ${'1.2.3+build'}      | ${' = 1.2.3+otherbuild, loose=True'}      | ${true}
+    ${'1.2.3-beta+build'} | ${'1.2.3-beta+otherbuild, loose=False'}   | ${true}
+    ${'1.2.3+build'}      | ${'1.2.3+otherbuild, loose=False'}        | ${true}
+    ${'  v1.2.3+build'}   | ${'1.2.3+otherbuild, loose=False'}        | ${true}
+    ${'1.3'}              | ${'1.2'}                                  | ${false}
+  `(
+    'equals("$version", "$other) === "$result"',
+    ({ version, other, result }) => {
+      const res = conan.equals(version, other);
+      expect(res).toEqual(result);
+    }
+  );
+
+  // isGreaterThan(version: string, other: string): boolean;
+  test.each`
+    version                              | other                                 | result
+    ${'1.2.3'}                           | ${'1.2.3'}                            | ${false}
+    ${'19.00'}                           | ${'16.00'}                            | ${true}
+    ${'1.2'}                             | ${'1.0'}                              | ${true}
+    ${'2.3.1'}                           | ${'1.2.3'}                            | ${true}
+    ${'0.0.0, loose=False'}              | ${'0.0.0-foo, loose=False'}           | ${true}
+    ${'0.0.1, loose=False'}              | ${'0.0.0, loose=False'}               | ${true}
+    ${'1.0.0, loose=False'}              | ${'0.9.9, loose=False'}               | ${true}
+    ${'0.10.0, loose=False'}             | ${'0.9.0, loose=False'}               | ${true}
+    ${'0.99.0, loose=False'}             | ${'0.10.0, loose=False'}              | ${true}
+    ${'2.0.0, loose=False'}              | ${'1.2.3, loose=False'}               | ${true}
+    ${'v0.0.0'}                          | ${'0.0.0-foo'}                        | ${true}
+    ${'v0.0.1'}                          | ${'0.0.0'}                            | ${true}
+    ${'v1.0.0'}                          | ${'0.9.9'}                            | ${true}
+    ${'v0.10.0'}                         | ${'0.9.0'}                            | ${true}
+    ${'v0.99.0'}                         | ${'0.10.0'}                           | ${true}
+    ${'v2.0.0'}                          | ${'1.2.3'}                            | ${true}
+    ${'0.0.0, loose=False'}              | ${'v0.0.0-foo, loose=False'}          | ${true}
+    ${'0.0.1, loose=False'}              | ${'v0.0.0, loose=False'}              | ${true}
+    ${'1.0.0, loose=False'}              | ${'v0.9.9, loose=False'}              | ${true}
+    ${'0.10.0, loose=False'}             | ${'v0.9.0, loose=False'}              | ${true}
+    ${'0.99.0, loose=False'}             | ${'v0.10.0, loose=False'}             | ${true}
+    ${'2.0.0, loose=False'}              | ${'v1.2.3, loose=False'}              | ${true}
+    ${'1.2.3, loose=False'}              | ${'1.2.3-asdf, loose=False'}          | ${true}
+    ${'1.2.3, loose=False'}              | ${'1.2.3-4, loose=False'}             | ${true}
+    ${'1.2.3, loose=False'}              | ${'1.2.3-4-foo, loose=False'}         | ${true}
+    ${'1.2.3-5-foo, loose=False'}        | ${'1.2.3-5, loose=False'}             | ${true}
+    ${'1.2.3-5, loose=False'}            | ${'1.2.3-4, loose=False'}             | ${true}
+    ${'1.2.3-5-foo, loose=False'}        | ${'1.2.3-5-Foo, loose=False'}         | ${true}
+    ${'3.0.0, loose=False'}              | ${'2.7.2+asdf, loose=False'}          | ${true}
+    ${'1.2.3-a.10, loose=False'}         | ${'1.2.3-a.5, loose=False'}           | ${true}
+    ${'1.2.3-a.b, loose=False'}          | ${'1.2.3-a.5, loose=False'}           | ${true}
+    ${'1.2.3-a.b, loose=False'}          | ${'1.2.3-a, loose=False'}             | ${true}
+    ${'1.2.3-a.b.c.10.d.5, loose=False'} | ${'1.2.3-a.b.c.5.d.100, loose=False'} | ${true}
+    ${'1.2.3-r2, loose=False'}           | ${'1.2.3-r100, loose=False'}          | ${true}
+    ${'1.2.3-r100, loose=False'}         | ${'1.2.3-R2, loose=False'}            | ${true}
+  `(
+    'isGreaterThan("$version", "$other) === "$result"',
+    ({ version, other, result }) => {
+      const res = conan.isGreaterThan(version, other);
+      expect(res).toEqual(result);
+    }
+  );
+
+  // sortVersions(version: string, other: string): boolean;
+  test.each`
+    version    | other      | result
+    ${'1.2'}   | ${'1.3'}   | ${-1}
+    ${'1.2.3'} | ${'1.2.3'} | ${0}
+    ${'2.3.1'} | ${'1.2.3'} | ${1}
+    ${'1.2.3'} | ${'2.3.1'} | ${-1}
+  `(
+    'sortVersions("$version", "$other) === "$result"',
+    ({ version, other, result }) => {
+      const res = conan.sortVersions(version, other);
+      expect(res).toEqual(result);
+    }
+  );
+
+  // isLessThanRange(version: string, range: string): boolean;
+  test.each`
+    version    | range         | result
+    ${'1.2.3'} | ${'[>1.2.3]'} | ${true}
+    ${'2.3.1'} | ${'[>1.2.3]'} | ${false}
+    ${'1.2.3'} | ${'[>2.3.1]'} | ${true}
+  `(
+    'isLessThanRange("$version", "$range") === "$result"',
+    ({ version, range, result }) => {
+      const res = conan.isLessThanRange?.(version, range);
+      expect(res).toEqual(result);
+    }
+  );
+});
diff --git a/lib/versioning/conan/index.ts b/lib/versioning/conan/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a27ffae2c15df60a504c5925f789f119b3c5e8af
--- /dev/null
+++ b/lib/versioning/conan/index.ts
@@ -0,0 +1,215 @@
+import * as semver from 'semver';
+import { api as looseAPI } from '../loose';
+import type { NewValueConfig, VersioningApi } from '../types';
+import {
+  cleanVersion,
+  findSatisfyingVersion,
+  getOptions,
+  makeVersion,
+  matchesWithOptions,
+} from './common';
+import {
+  bumpRange,
+  getMajor,
+  getMinor,
+  getPatch,
+  replaceRange,
+  widenRange,
+} from './range';
+
+export const id = 'conan';
+export const displayName = 'conan';
+export const urls = [
+  'https://semver.org/',
+  'https://github.com/podhmo/python-node-semver',
+  'https://github.com/podhmo/python-node-semver/tree/master/examples',
+  'https://docs.conan.io/en/latest/versioning/version_ranges.html#version-ranges',
+];
+export const supportsRanges = true;
+export const supportedRangeStrategies = ['auto', 'bump', 'widen', 'replace'];
+
+const MIN = 1;
+const MAX = -1;
+
+function isVersion(input: string): boolean {
+  if (input && !input.includes('[')) {
+    const qualifiers = getOptions(input);
+    const version = cleanVersion(input);
+    if (qualifiers.loose) {
+      if (looseAPI.isVersion(version)) {
+        return true;
+      }
+    }
+    return makeVersion(version, qualifiers) !== null;
+  }
+  return false;
+}
+
+function isValid(input: string): boolean {
+  const version = cleanVersion(input);
+  const qualifiers = getOptions(input);
+  if (makeVersion(version, qualifiers)) {
+    return version !== null;
+  }
+
+  return semver.validRange(version, qualifiers) !== null;
+}
+
+function equals(version: string, other: string): boolean {
+  const cleanedVersion = cleanVersion(version);
+  const cleanOther = cleanVersion(other);
+  const options = { loose: true, includePrerelease: true };
+  const looseResult = looseAPI.equals(cleanedVersion, cleanOther);
+  try {
+    return semver.eq(cleanedVersion, cleanOther, options) || looseResult;
+  } catch {
+    return looseResult;
+  }
+}
+
+function isGreaterThan(version: string, other: string): boolean {
+  const cleanedVersion = cleanVersion(version);
+  const cleanOther = cleanVersion(other);
+  const options = { loose: true, includePrerelease: true };
+  const looseResult = looseAPI.isGreaterThan(cleanedVersion, cleanOther);
+  try {
+    return semver.gt(cleanedVersion, cleanOther, options) || looseResult;
+  } catch {
+    return looseResult;
+  }
+}
+
+function isLessThanRange(version: string, range: string): boolean {
+  const cleanedVersion = cleanVersion(version);
+  const cleanRange = cleanVersion(range);
+  const options = getOptions(range);
+  const looseResult: any = looseAPI.isLessThanRange?.(
+    cleanedVersion,
+    cleanRange
+  );
+  try {
+    return semver.ltr(cleanedVersion, cleanRange, options) || looseResult;
+  } catch {
+    return looseResult;
+  }
+}
+
+function sortVersions(version: string, other: string): number {
+  const cleanedVersion = cleanVersion(version);
+  const cleanOther = cleanVersion(other);
+  const options = { loose: true, includePrerelease: true };
+  try {
+    return semver.compare(cleanedVersion, cleanOther, options);
+  } catch {
+    return looseAPI.sortVersions(cleanedVersion, cleanOther);
+  }
+}
+
+function matches(version: string, range: string): boolean {
+  if (isVersion(version) && isVersion(range)) {
+    return true;
+  }
+  const cleanedVersion = cleanVersion(version);
+  const options = getOptions(range);
+  const cleanRange = cleanVersion(range);
+  return matchesWithOptions(cleanedVersion, cleanRange, options);
+}
+
+function isCompatible(version: string, range: string): boolean {
+  if (isVersion(version) && isVersion(range)) {
+    return true;
+  }
+  const options = getOptions(range);
+  const compatibleVersion = makeVersion(version, options);
+  if (compatibleVersion) {
+    return !isLessThanRange(version, range);
+  }
+  return false;
+}
+
+function isStable(version: string): boolean {
+  const cleanedVersion = cleanVersion(version);
+  const options = getOptions(version);
+  if (
+    !options.includePrerelease &&
+    semver.prerelease(cleanedVersion, options)
+  ) {
+    return false;
+  }
+
+  return true;
+}
+
+function minSatisfyingVersion(
+  versions: string[],
+  range: string
+): string | null {
+  return findSatisfyingVersion(versions, range, MIN);
+}
+
+function getSatisfyingVersion(
+  versions: string[],
+  range: string
+): string | null {
+  return findSatisfyingVersion(versions, range, MAX);
+}
+
+function getNewValue({
+  currentValue,
+  rangeStrategy,
+  currentVersion,
+  newVersion,
+}: NewValueConfig): string | null {
+  const cleanRange = cleanVersion(currentValue);
+  if (isVersion(currentValue) || rangeStrategy === 'pin') {
+    return newVersion;
+  }
+  const options = getOptions(currentValue);
+  let newValue: any = '';
+
+  if (rangeStrategy === 'widen') {
+    newValue = widenRange(
+      { currentValue: cleanRange, rangeStrategy, currentVersion, newVersion },
+      options
+    );
+  } else if (rangeStrategy === 'bump') {
+    newValue = bumpRange(
+      { currentValue: cleanRange, rangeStrategy, currentVersion, newVersion },
+      options
+    );
+  } else {
+    newValue = replaceRange({
+      currentValue: cleanRange,
+      rangeStrategy,
+      currentVersion,
+      newVersion,
+    });
+  }
+
+  if (newValue) {
+    return currentValue.replace(cleanRange, newValue);
+  }
+
+  return null;
+}
+
+export const api: VersioningApi = {
+  equals,
+  getMajor,
+  getMinor,
+  getNewValue,
+  getPatch,
+  isCompatible,
+  isGreaterThan,
+  isLessThanRange,
+  isSingleVersion: isVersion,
+  isStable,
+  isValid,
+  isVersion,
+  matches,
+  getSatisfyingVersion,
+  minSatisfyingVersion,
+  sortVersions,
+};
+
+export default api;
diff --git a/lib/versioning/conan/range.ts b/lib/versioning/conan/range.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6ac598a8b4cbe215c725f3c81847c82585cd822a
--- /dev/null
+++ b/lib/versioning/conan/range.ts
@@ -0,0 +1,345 @@
+import * as semver from 'semver';
+import { SemVer, parseRange } from 'semver-utils';
+import { logger } from '../../logger';
+import type { NewValueConfig } from '../types';
+import {
+  cleanVersion,
+  containsOperators,
+  getOptions,
+  makeVersion,
+  matchesWithOptions,
+} from './common';
+
+// always include prereleases
+export function getMajor(version: string): null | number {
+  const cleanedVersion = cleanVersion(version);
+  const options = getOptions(version);
+  options.includePrerelease = true;
+  const cleanerVersion = makeVersion(cleanedVersion, options);
+  if (typeof cleanerVersion === 'string') {
+    return Number(cleanerVersion.split('.')[0]);
+  }
+  return null;
+}
+
+// always include prereleases
+export function getMinor(version: string): null | number {
+  const cleanedVersion = cleanVersion(version);
+  const options = getOptions(version);
+  options.includePrerelease = true;
+  const cleanerVersion = makeVersion(cleanedVersion, options);
+  if (typeof cleanerVersion === 'string') {
+    return Number(cleanerVersion.split('.')[1]);
+  }
+  return null;
+}
+
+// always include prereleases
+export function getPatch(version: string): null | number {
+  const cleanedVersion = cleanVersion(version);
+  const options = getOptions(version);
+  options.includePrerelease = true;
+  const cleanerVersion = makeVersion(cleanedVersion, options);
+
+  if (typeof cleanerVersion === 'string') {
+    const newVersion = semver.valid(
+      semver.coerce(cleanedVersion, options),
+      options
+    );
+    return Number(newVersion?.split('.')[2]);
+  }
+  return null;
+}
+
+export function fixParsedRange(range: string): any {
+  const ordValues = [];
+
+  // don't bump or'd single version values
+  const originalSplit = range.split(' ');
+  for (let i = 0; i < originalSplit.length; i += 1) {
+    if (
+      !containsOperators(originalSplit[i]) &&
+      !originalSplit[i].includes('||')
+    ) {
+      if (i !== 0 && originalSplit[i - 1].includes('||')) {
+        ordValues.push(`|| ${originalSplit[i]}`);
+      } else if (i !== originalSplit.length && originalSplit[i + 1] === '||') {
+        ordValues.push(`${originalSplit[i]} ||`);
+      }
+    } else {
+      ordValues.push(originalSplit[i]);
+    }
+  }
+
+  const parsedRange = parseRange(range);
+  const cleanRange = range.replace(/([<=>^~])( )?/g, '');
+  const splitRange = cleanRange.split(' ');
+  const semverRange: SemVer[] = [];
+
+  for (let i = 0; i < splitRange.length; i += 1) {
+    if (!splitRange[i].includes('||')) {
+      const splitVersion = splitRange[i].split('.');
+      const major = splitVersion[0];
+      const minor = splitVersion[1];
+      const patch = splitVersion[2];
+      const operator = ordValues[i].includes('||')
+        ? '||'
+        : parsedRange[i].operator;
+      const NewSemVer: SemVer = {
+        major,
+      };
+
+      let full = `${operator || ''}${major}`;
+      if (minor) {
+        NewSemVer.minor = minor;
+        full = `${full}.${minor}`;
+        if (patch) {
+          NewSemVer.patch = patch;
+          full = `${full}.${patch}`;
+        }
+      }
+      if (operator) {
+        NewSemVer.operator = operator;
+        full = range.includes(`${operator} `)
+          ? `${operator} ${full.replace(operator, '')}`
+          : `${operator}${full.replace(operator, '')}`;
+      }
+
+      full = ordValues[i].includes('||') ? ordValues[i] : full;
+
+      NewSemVer.semver = full;
+
+      semverRange.push(NewSemVer);
+    }
+  }
+  return semverRange;
+}
+
+export function replaceRange({
+  currentValue,
+  newVersion,
+}: NewValueConfig): string {
+  const parsedRange = parseRange(currentValue);
+  const element = parsedRange[parsedRange.length - 1];
+  const toVersionMajor = getMajor(newVersion);
+  const toVersionMinor = getMinor(newVersion);
+  const toVersionPatch = getPatch(newVersion);
+  const suffix = semver.prerelease(newVersion)
+    ? '-' + String(semver.prerelease(newVersion)?.[0])
+    : '';
+
+  if (element.operator === '~>') {
+    return `~> ${toVersionMajor}.${toVersionMinor}.0`;
+  }
+  if (element.operator === '=') {
+    return `=${newVersion}`;
+  }
+  if (element.operator === '~') {
+    if (suffix.length) {
+      return `~${toVersionMajor}.${toVersionMinor}.${toVersionPatch}${suffix}`;
+    }
+    return `~${toVersionMajor}.${toVersionMinor}.0`;
+  }
+  if (element.operator === '<=') {
+    let res;
+    if (element.patch || suffix.length) {
+      res = `<=${newVersion}`;
+    } else if (element.minor) {
+      res = `<=${toVersionMajor}.${toVersionMinor}`;
+    } else {
+      res = `<=${toVersionMajor}`;
+    }
+    if (currentValue.includes('<= ')) {
+      res = res.replace('<=', '<= ');
+    }
+    return res;
+  }
+  if (element.operator === '<' && toVersionMajor) {
+    let res;
+    if (currentValue.endsWith('.0.0')) {
+      const newMajor = toVersionMajor + 1;
+      res = `<${newMajor}.0.0`;
+    } else if (element.patch) {
+      res = `<${semver.inc(newVersion, 'patch')}`;
+    } else if (element.minor && toVersionMinor) {
+      res = `<${toVersionMajor}.${toVersionMinor + 1}`;
+    } else {
+      res = `<${toVersionMajor + 1}`;
+    }
+    if (currentValue.includes('< ')) {
+      res = res.replace(/</g, '< ');
+    }
+    return res;
+  }
+  if (element.operator === '>') {
+    let res;
+    if (currentValue.endsWith('.0.0') && toVersionMajor) {
+      const newMajor = toVersionMajor + 1;
+      res = `>${newMajor}.0.0`;
+    } else if (element.patch) {
+      res = `>${toVersionMajor}.${toVersionMinor}.${toVersionPatch}`;
+    } else if (element.minor) {
+      res = `>${toVersionMajor}.${toVersionMinor}`;
+    } else {
+      res = `>${toVersionMajor}`;
+    }
+    if (currentValue.includes('> ')) {
+      res = res.replace(/</g, '> ');
+    }
+    return res;
+  }
+  if (!element.operator) {
+    if (element.minor) {
+      if (element.minor === 'x') {
+        return `${toVersionMajor}.x`;
+      }
+      if (element.minor === '*') {
+        return `${toVersionMajor}.*`;
+      }
+      if (element.patch === 'x') {
+        return `${toVersionMajor}.${toVersionMinor}.x`;
+      }
+      if (element.patch === '*') {
+        return `${toVersionMajor}.${toVersionMinor}.*`;
+      }
+      return `${newVersion}`;
+    }
+    return `${toVersionMajor}`;
+  }
+  return newVersion;
+}
+
+export function widenRange(
+  { currentValue, currentVersion, newVersion }: NewValueConfig,
+  options: semver.Options
+): string | null {
+  const parsedRange = parseRange(currentValue);
+  const element = parsedRange[parsedRange.length - 1];
+
+  if (matchesWithOptions(newVersion, currentValue, options)) {
+    return currentValue;
+  }
+  const newValue = replaceRange({
+    currentValue,
+    rangeStrategy: 'replace',
+    currentVersion,
+    newVersion,
+  });
+  if (element.operator?.startsWith('<')) {
+    const splitCurrent = currentValue.split(element.operator);
+    splitCurrent.pop();
+    return splitCurrent.join(element.operator) + newValue;
+  }
+  if (parsedRange.length > 1) {
+    const previousElement = parsedRange[parsedRange.length - 2];
+    if (previousElement.operator === '-') {
+      const splitCurrent = currentValue.split('-');
+      splitCurrent.pop();
+      return splitCurrent.join('-') + '- ' + newValue;
+    }
+    if (element.operator?.startsWith('>')) {
+      logger.warn(`Complex ranges ending in greater than are not supported`);
+      return null;
+    }
+  }
+  return `${currentValue} || ${newValue}`;
+}
+
+export function bumpRange(
+  { currentValue, currentVersion, newVersion }: NewValueConfig,
+  options: semver.Options
+): string | null {
+  if (!containsOperators(currentValue) && currentValue.includes('||')) {
+    return widenRange(
+      {
+        currentValue,
+        rangeStrategy: 'widen',
+        currentVersion,
+        newVersion,
+      },
+      options
+    );
+  }
+  const parsedRange = parseRange(currentValue);
+  const element = parsedRange[parsedRange.length - 1];
+
+  const toVersionMajor = getMajor(newVersion);
+  const toVersionMinor = getMinor(newVersion);
+  const suffix = semver.prerelease(newVersion)
+    ? '-' + String(semver.prerelease(newVersion)?.[0])
+    : '';
+
+  if (parsedRange.length === 1) {
+    if (!element.operator) {
+      return replaceRange({
+        currentValue,
+        rangeStrategy: 'replace',
+        currentVersion,
+        newVersion,
+      });
+    }
+    if (element.operator.startsWith('~')) {
+      const split = currentValue.split('.');
+      if (suffix.length) {
+        return `${element.operator}${newVersion}`;
+      }
+      if (split.length === 1) {
+        // ~4
+        return `${element.operator}${toVersionMajor}`;
+      }
+      if (split.length === 2) {
+        // ~4.1
+        return `${element.operator}${toVersionMajor}.${toVersionMinor}`;
+      }
+      return `${element.operator}${newVersion}`;
+    }
+    if (element.operator === '=') {
+      return `=${newVersion}`;
+    }
+    if (element.operator === '>=') {
+      return currentValue.includes('>= ')
+        ? `>= ${newVersion}`
+        : `>=${newVersion}`;
+    }
+    if (element.operator.startsWith('<')) {
+      return currentValue;
+    }
+  } else {
+    const newRange = fixParsedRange(currentValue);
+    const versions = newRange.map((x: any) => {
+      // don't bump or'd single version values
+      if (x.operator === '||') {
+        return x.semver;
+      }
+      if (x.operator) {
+        const bumpedSubRange = bumpRange(
+          {
+            currentValue: x.semver,
+            rangeStrategy: 'bump',
+            currentVersion,
+            newVersion,
+          },
+          options
+        );
+        if (
+          bumpedSubRange &&
+          matchesWithOptions(newVersion, bumpedSubRange, options)
+        ) {
+          return bumpedSubRange;
+        }
+      }
+
+      return replaceRange({
+        currentValue: x.semver,
+        rangeStrategy: 'replace',
+        currentVersion,
+        newVersion,
+      });
+    });
+    return versions.filter((x: any) => x !== null && x !== '').join(' ');
+  }
+  logger.debug(
+    'Unsupported range type for rangeStrategy=bump: ' + currentValue
+  );
+  return null;
+}
diff --git a/lib/versioning/conan/readme.md b/lib/versioning/conan/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..cf539a8faf580ee8360c166b61d0bb93adbd2516
--- /dev/null
+++ b/lib/versioning/conan/readme.md
@@ -0,0 +1,19 @@
+Conan versioning supports [Semantic Versioning 2.0](https://semver.org) but some packages don't follow this specification.
+
+Conan implements [python-node-semver](https://github.com/podhmo/python-node-semver).
+
+More information can be found in the [Conan docs](https://docs.conan.io/en/latest/versioning/version_ranges.html#version-ranges)
+
+| syntax                                           | description                                                                                                |
+| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
+| `5.45`                                           | Equivalent to `5.45`                                                                                       |
+| `16.00`                                          | Equivalent to `16.00`                                                                                      |
+| `2.8.3`                                          | Equivalent to `2.8.3`                                                                                      |
+| `[>1.1 <2.1]`                                    | Keep version within range                                                                                  |
+| `[2.8]`                                          | Equivalent to `=2.8`                                                                                       |
+| `[~=3.0]`                                        | Compatible, according to SemVer                                                                            |
+| `[>1.1 \|\| 0.8]`                                | Conditions can be OR'ed                                                                                    |
+| `[1.2.7 \|\| >=1.2.9 <2.0.0]`                    | This range would match the versions `1.2.7`, `1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0` |
+| `[>1.1 <2.1, include_prerelease=True]`           | Would e.g. accept `2.0.0-pre.1` as match                                                                   |
+| `[~1.2.3, loose=False]`                          | Would only accept correct Semantic Versioning strings. E.g. version `1.2.3.4` would not be accepted        |
+| `[~1.2.3, loose=False, include_prerelease=True]` | Both options can be used for the same version range                                                        |