{"id":13447453,"url":"https://github.com/kentcdodds/match-sorter","last_synced_at":"2025-05-13T15:08:32.408Z","repository":{"id":39988409,"uuid":"66523440","full_name":"kentcdodds/match-sorter","owner":"kentcdodds","description":"Simple, expected, and deterministic best-match sorting of an array in JavaScript","archived":false,"fork":false,"pushed_at":"2025-05-02T16:17:06.000Z","size":277,"stargazers_count":3958,"open_issues_count":3,"forks_count":133,"subscribers_count":27,"default_branch":"main","last_synced_at":"2025-05-06T14:58:46.935Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://npm.im/match-sorter","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kentcdodds.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-08-25T04:04:48.000Z","updated_at":"2025-05-02T16:15:30.000Z","dependencies_parsed_at":"2022-06-26T02:25:34.043Z","dependency_job_id":"57acc39b-7d6b-499d-aa62-ef089c4e399d","html_url":"https://github.com/kentcdodds/match-sorter","commit_stats":{"total_commits":112,"total_committers":36,"mean_commits":3.111111111111111,"dds":0.8482142857142857,"last_synced_commit":"15b023cd594bd7822bf29157e1810699be604a9d"},"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kentcdodds%2Fmatch-sorter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kentcdodds%2Fmatch-sorter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kentcdodds%2Fmatch-sorter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kentcdodds%2Fmatch-sorter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kentcdodds","download_url":"https://codeload.github.com/kentcdodds/match-sorter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253176434,"owners_count":21866143,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T05:01:18.150Z","updated_at":"2025-05-13T15:08:32.357Z","avatar_url":"https://github.com/kentcdodds.png","language":"TypeScript","funding_links":[],"categories":["JavaScript","TypeScript","filter and sort arrays","others","UI Components"],"sub_categories":["Search"],"readme":"\u003cdiv align=\"center\"\u003e\n\u003ch1\u003ematch-sorter\u003c/h1\u003e\n\n\u003cp\u003eSimple, expected, and deterministic best-match sorting of an array in JavaScript\u003c/p\u003e\n\u003c/div\u003e\n\n---\n\n**[Demo](https://codesandbox.io/s/wyk856yo48)**\n\n\u003c!-- prettier-ignore-start --\u003e\n[![Build Status][build-badge]][build]\n[![Code Coverage][coverage-badge]][coverage]\n[![version][version-badge]][package]\n[![downloads][downloads-badge]][npmtrends]\n[![MIT License][license-badge]][license]\n[![All Contributors][all-contributors-badge]](#contributors-)\n[![PRs Welcome][prs-badge]][prs]\n[![Code of Conduct][coc-badge]][coc]\n[![Examples][examples-badge]][examples]\n\u003c!-- prettier-ignore-end --\u003e\n\n## The problem\n\n1.  You have a list of dozens, hundreds, or thousands of items\n2.  You want to filter and sort those items intelligently (maybe you have a\n    filter input for the user)\n3.  You want simple, expected, and deterministic sorting of the items (no fancy\n    math algorithm that fancily changes the sorting as they type)\n\n## This solution\n\nThis follows a simple and sensible (user friendly) algorithm that makes it easy\nfor you to filter and sort a list of items based on given input. Items are\nranked based on sensible criteria that result in a better user experience.\n\nTo explain the ranking system, I'll use countries as an example:\n\n1.  **CASE SENSITIVE EQUALS**: Case-sensitive equality trumps all. These will be\n    first. (ex. `France` would match `France`, but not `france`)\n2.  **EQUALS**: Case-insensitive equality (ex. `France` would match `france`)\n3.  **STARTS WITH**: If the item starts with the given value (ex. `Sou` would\n    match `South Korea` or `South Africa`)\n4.  **WORD STARTS WITH**: If the item has multiple words, then if one of those\n    words starts with the given value (ex. `Repub` would match\n    `Dominican Republic`)\n5.  **CONTAINS**: If the item contains the given value (ex. `ham` would match\n    `Bahamas`)\n6.  **ACRONYM**: If the item's acronym is the given value (ex. `us` would match\n    `United States`)\n7.  **SIMPLE MATCH**: If the item has letters in the same order as the letters\n    of the given value (ex. `iw` would match `Zimbabwe`, but not `Kuwait`\n    because it must be in the same order). Furthermore, if the item is a closer\n    match, it will rank higher (ex. `ua` matches `Uruguay` more closely than\n    `United States of America`, therefore `Uruguay` will be ordered before\n    `United States of America`)\n\nThis ranking seems to make sense in people's minds. At least it does in mine.\nFeedback welcome!\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Advanced options](#advanced-options)\n  - [keys: `[string]`](#keys-string)\n  - [threshold: `number`](#threshold-number)\n  - [keepDiacritics: `boolean`](#keepdiacritics-boolean)\n  - [baseSort: `function(itemA, itemB): -1 | 0 | 1`](#basesort-functionitema-itemb--1--0--1)\n  - [sorter: `function(rankedItems): rankedItems`](#sorter-functionrankeditems-rankeditems)\n- [Recipes](#recipes)\n  - [Match PascalCase, camelCase, snake_case, or kebab-case as words](#match-pascalcase-camelcase-snake_case-or-kebab-case-as-words)\n  - [Match many words across multiple fields (table filtering)](#match-many-words-across-multiple-fields-table-filtering)\n- [Inspiration](#inspiration)\n- [Other Solutions](#other-solutions)\n- [Issues](#issues)\n  - [🐛 Bugs](#-bugs)\n  - [💡 Feature Requests](#-feature-requests)\n- [Contributors ✨](#contributors-)\n- [LICENSE](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Installation\n\nThis module is distributed via [npm][npm] which is bundled with [node][node] and\nshould be installed as one of your project's `dependencies`:\n\n```\nnpm install match-sorter\n```\n\n## Usage\n\n```javascript\nimport {matchSorter} from 'match-sorter'\n// or const {matchSorter} = require('match-sorter')\n// or window.matchSorter.matchSorter\nconst list = ['hi', 'hey', 'hello', 'sup', 'yo']\nmatchSorter(list, 'h') // ['hello', 'hey', 'hi']\nmatchSorter(list, 'y') // ['yo', 'hey']\nmatchSorter(list, 'z') // []\n```\n\n## Advanced options\n\n### keys: `[string]`\n\n_Default: `undefined`_\n\nBy default it just uses the value itself as above. Passing an array tells\nmatch-sorter which keys to use for the ranking.\n\n```javascript\nconst objList = [\n  {name: 'Janice', color: 'Green'},\n  {name: 'Fred', color: 'Orange'},\n  {name: 'George', color: 'Blue'},\n  {name: 'Jen', color: 'Red'},\n]\nmatchSorter(objList, 'g', {keys: ['name', 'color']})\n// [{name: 'George', color: 'Blue'}, {name: 'Janice', color: 'Green'}, {name: 'Fred', color: 'Orange'}]\n\nmatchSorter(objList, 're', {keys: ['color', 'name']})\n// [{name: 'Jen', color: 'Red'}, {name: 'Janice', color: 'Green'}, {name: 'Fred', color: 'Orange'}, {name: 'George', color: 'Blue'}]\n```\n\n**Array of values**: When the specified key matches an array of values, the best\nmatch from the values of in the array is going to be used for the ranking.\n\n```javascript\nconst iceCreamYum = [\n  {favoriteIceCream: ['mint', 'chocolate']},\n  {favoriteIceCream: ['candy cane', 'brownie']},\n  {favoriteIceCream: ['birthday cake', 'rocky road', 'strawberry']},\n]\nmatchSorter(iceCreamYum, 'cc', {keys: ['favoriteIceCream']})\n// [{favoriteIceCream: ['candy cane', 'brownie']}, {favoriteIceCream: ['mint', 'chocolate']}]\n```\n\n**Nested Keys**: You can specify nested keys using dot-notation.\n\n```javascript\nconst nestedObjList = [\n  {name: {first: 'Janice'}},\n  {name: {first: 'Fred'}},\n  {name: {first: 'George'}},\n  {name: {first: 'Jen'}},\n]\nmatchSorter(nestedObjList, 'j', {keys: ['name.first']})\n// [{name: {first: 'Janice'}}, {name: {first: 'Jen'}}]\n\nconst nestedObjList = [\n  {name: [{first: 'Janice'}]},\n  {name: [{first: 'Fred'}]},\n  {name: [{first: 'George'}]},\n  {name: [{first: 'Jen'}]},\n]\nmatchSorter(nestedObjList, 'j', {keys: ['name.0.first']})\n// [{name: {first: 'Janice'}}, {name: {first: 'Jen'}}]\n\n// matchSorter(nestedObjList, 'j', {keys: ['name[0].first']}) does not work\n```\n\nThis even works with arrays of multiple nested objects: just specify the key\nusing dot-notation with the `*` wildcard instead of a numeric index.\n\n```javascript\nconst nestedObjList = [\n  {aliases: [{name: {first: 'Janice'}},{name: {first: 'Jen'}}]},\n  {aliases: [{name: {first: 'Fred'}},{name: {first: 'Frederic'}}]},\n  {aliases: [{name: {first: 'George'}},{name: {first: 'Georgie'}}]},\n]\nmatchSorter(nestedObjList, 'jen', {keys: ['aliases.*.name.first']})\n// [{aliases: [{name: {first: 'Janice'}},{name: {first: 'Jen'}}]}]\nmatchSorter(nestedObjList, 'jen', {keys: ['aliases.0.name.first']})\n// []\n```\n\n**Property Callbacks**: Alternatively, you may also pass in a callback function\nthat resolves the value of the key(s) you wish to match on. This is especially\nuseful when interfacing with libraries such as Immutable.js\n\n```javascript\nconst list = [{name: 'Janice'}, {name: 'Fred'}, {name: 'George'}, {name: 'Jen'}]\nmatchSorter(list, 'j', {keys: [item =\u003e item.name]})\n// [{name: 'Janice'}, {name: 'Jen'}]\n```\n\nFor more complex structures, expanding on the `nestedObjList` example above, you\ncan use `map`:\n\n```javascript\nconst nestedObjList = [\n  {\n    name: [\n      {first: 'Janice', last: 'Smith'},\n      {first: 'Jon', last: 'Doe'},\n    ],\n  },\n  {\n    name: [\n      {first: 'Fred', last: 'Astaire'},\n      {first: 'Jenny', last: 'Doe'},\n      {first: 'Wilma', last: 'Flintstone'},\n    ],\n  },\n]\nmatchSorter(nestedObjList, 'doe', {\n  keys: [\n    item =\u003e item.name.map(i =\u003e i.first),\n    item =\u003e item.name.map(i =\u003e i.last),\n  ],\n})\n// [name: [{ first: 'Janice', last: 'Smith' },{ first: 'Jon', last: 'Doe' }], name: [{ first: 'Fred', last: 'Astaire' },{ first: 'Jenny', last: 'Doe' },{ first: 'Wilma', last: 'Flintstone' }]]\n```\n\n**Threshold**: You may specify an individual threshold for specific keys. A key\nwill only match if it meets the specified threshold. _For more information\nregarding thresholds [see below](#threshold-number)_\n\n```javascript\nconst list = [\n  {name: 'Fred', color: 'Orange'},\n  {name: 'Jen', color: 'Red'},\n]\nmatchSorter(list, 'ed', {\n  keys: [{threshold: matchSorter.rankings.STARTS_WITH, key: 'name'}, 'color'],\n})\n//[{name: 'Jen', color: 'Red'}]\n```\n\n**Min and Max Ranking**: You may restrict specific keys to a minimum or maximum\nranking by passing in an object. A key with a minimum rank will only get\npromoted if there is at least a simple match.\n\n```javascript\nconst tea = [\n  {tea: 'Earl Grey', alias: 'A'},\n  {tea: 'Assam', alias: 'B'},\n  {tea: 'Black', alias: 'C'},\n]\nmatchSorter(tea, 'A', {\n  keys: ['tea', {maxRanking: matchSorter.rankings.STARTS_WITH, key: 'alias'}],\n})\n// without maxRanking, Earl Grey would come first because the alias \"A\" would be CASE_SENSITIVE_EQUAL\n// `tea` key comes before `alias` key, so Assam comes first even though both match as STARTS_WITH\n// [{tea: 'Assam', alias: 'B'}, {tea: 'Earl Grey', alias: 'A'},{tea: 'Black', alias: 'C'}]\n```\n\n```javascript\nconst tea = [\n  {tea: 'Milk', alias: 'moo'},\n  {tea: 'Oolong', alias: 'B'},\n  {tea: 'Green', alias: 'C'},\n]\nmatchSorter(tea, 'oo', {\n  keys: ['tea', {minRanking: matchSorter.rankings.EQUAL, key: 'alias'}],\n})\n// minRanking bumps Milk up to EQUAL from CONTAINS (alias)\n// Oolong matches as STARTS_WITH\n// Green is missing due to no match\n// [{tea: 'Milk', alias: 'moo'}, {tea: 'Oolong', alias: 'B'}]\n```\n\n### threshold: `number`\n\n_Default: `MATCHES`_\n\nThresholds can be used to specify the criteria used to rank the results.\nAvailable thresholds (from top to bottom) are:\n\n- CASE_SENSITIVE_EQUAL\n- EQUAL\n- STARTS_WITH\n- WORD_STARTS_WITH\n- CONTAINS\n- ACRONYM\n- MATCHES _(default value)_\n- NO_MATCH\n\n```javascript\nconst fruit = ['orange', 'apple', 'grape', 'banana']\nmatchSorter(fruit, 'ap', {threshold: matchSorter.rankings.NO_MATCH})\n// ['apple', 'grape', 'orange', 'banana'] (returns all items, just sorted by best match)\n\nconst things = ['google', 'airbnb', 'apple', 'apply', 'app'],\nmatchSorter(things, 'app', {threshold: matchSorter.rankings.EQUAL})\n// ['app'] (only items that are equal)\n\nconst otherThings = ['fiji apple', 'google', 'app', 'crabapple', 'apple', 'apply']\nmatchSorter(otherThings, 'app', {threshold: matchSorter.rankings.WORD_STARTS_WITH})\n// ['app', 'apple', 'apply', 'fiji apple'] (everything that matches with \"word starts with\" or better)\n```\n\n### keepDiacritics: `boolean`\n\n_Default: `false`_\n\nBy default, match-sorter will strip diacritics before doing any comparisons.\nThis is the default because it makes the most sense from a UX perspective.\n\nYou can disable this behavior by specifying `keepDiacritics: true`\n\n```javascript\nconst thingsWithDiacritics = [\n  'jalapeño',\n  'à la carte',\n  'café',\n  'papier-mâché',\n  'à la mode',\n]\nmatchSorter(thingsWithDiacritics, 'aa')\n// ['jalapeño', 'à la carte', 'à la mode', 'papier-mâché']\n\nmatchSorter(thingsWithDiacritics, 'aa', {keepDiacritics: true})\n// ['jalapeño', 'à la carte']\n\nmatchSorter(thingsWithDiacritics, 'à', {keepDiacritics: true})\n// ['à la carte', 'à la mode']\n```\n\n### baseSort: `function(itemA, itemB): -1 | 0 | 1`\n\n_Default: `(a, b) =\u003e String(a.rankedValue).localeCompare(b.rankedValue)`_\n\nBy default, match-sorter uses the `String.localeCompare` function to tie-break\nitems that have the same ranking. This results in a stable, alphabetic sort.\n\n```javascript\nconst list = ['C apple', 'B apple', 'A apple']\nmatchSorter(list, 'apple')\n// ['A apple', 'B apple', 'C apple']\n```\n\n_You can customize this behavior by specifying a custom `baseSort` function:_\n\n```javascript\nconst list = ['C apple', 'B apple', 'A apple']\n// This baseSort function will use the original index of items as the tie breaker\nmatchSorter(list, 'apple', {baseSort: (a, b) =\u003e (a.index \u003c b.index ? -1 : 1)})\n// ['C apple', 'B apple', 'A apple']\n```\n\n### sorter: `function(rankedItems): rankedItems`\n\n_Default:\n`matchedItems =\u003e matchedItems.sort((a, b) =\u003e sortRankedValues(a, b, baseSort))`_\n\nBy default, match-sorter uses an internal `sortRankedValues` function to sort\nitems after matching them.\n\n_You can customize the core sorting behavior by specifying a custom `sorter`\nfunction:_\n\nDisable sorting entirely:\n```javascript\nconst list = ['appl', 'C apple', 'B apple', 'A apple', 'app', 'applebutter']\nmatchSorter(list, 'apple', {sorter: rankedItems =\u003e rankedItems})\n// ['C apple', 'B apple', 'A apple', 'applebutter']\n```\n\nReturn the unsorted rankedItems, but in reverse order:\n```javascript\nconst list = ['appl', 'C apple', 'B apple', 'A apple', 'app', 'applebutter']\nmatchSorter(list, 'apple', {sorter: rankedItems =\u003e [...rankedItems].reverse()})\n// ['applebutter', 'A apple', 'B apple', 'C apple']\n```\n\n## Recipes\n\n### Match PascalCase, camelCase, snake_case, or kebab-case as words\n\nBy default, `match-sorter` assumes spaces to be the word separator. However, if\nyour data has a different word separator, you can use a property callback to\nreplace your separator with spaces. For example, for `snake_case`:\n\n```javascript\nconst list = [\n  {name: 'Janice_Kurtis'},\n  {name: 'Fred_Mertz'},\n  {name: 'George_Foreman'},\n  {name: 'Jen_Smith'},\n]\nmatchSorter(list, 'js', {keys: [item =\u003e item.name.replace(/_/g, ' ')]})\n// [{name: 'Jen_Smith'}, {name: 'Janice_Kurtis'}]\n```\n\n### Match many words across multiple fields (table filtering)\n\nBy default, `match-sorter` will return matches from objects where one of the\nproperties matches _the entire_ search term. For multi-column data sets it can\nbe beneficial to split words in search string and match each word separately.\nThis can be done by chaining `match-sorter` calls.\n\nThe benefit of this is that a filter string of \"two words\" will match both \"two\"\nand \"words\", but will return rows where the two words are found in _different_\ncolumns as well as when both words match in the same column. For single-column\nmatches it will also return matches out of order (column = \"wordstwo\" will match\njust as well as column=\"twowords\", the latter getting a higher score).\n\n```javascript\nfunction fuzzySearchMultipleWords(\n  rows, // array of data [{a: \"a\", b: \"b\"}, {a: \"c\", b: \"d\"}]\n  keys, // keys to search [\"a\", \"b\"]\n  filterValue: string, // potentially multi-word search string \"two words\"\n) {\n  if (!filterValue || !filterValue.length) {\n    return rows\n  }\n\n  const terms = filterValue.split(' ')\n  if (!terms) {\n    return rows\n  }\n\n  // reduceRight will mean sorting is done by score for the _first_ entered word.\n  return terms.reduceRight(\n    (results, term) =\u003e matchSorter(results, term, {keys}),\n    rows,\n  )\n}\n```\n\n[Multi-column code sandbox](https://codesandbox.io/s/match-sorter-example-forked-1ko35)\n\n## Inspiration\n\nActually, most of this code was extracted from the _very first_ library I ever\nwrote: [genie][genie]!\n\n## Other Solutions\n\nYou might try [Fuse.js](https://github.com/krisk/Fuse). It uses advanced math\nfanciness to get the closest match. Unfortunately what's \"closest\" doesn't\nalways really make sense. So I extracted this from [genie][genie].\n\n## Issues\n\n_Looking to contribute? Look for the [Good First Issue][good-first-issue]\nlabel._\n\n### 🐛 Bugs\n\nPlease file an issue for bugs, missing documentation, or unexpected behavior.\n\n[**See Bugs**][bugs]\n\n### 💡 Feature Requests\n\nPlease file an issue to suggest new features. Vote on feature requests by adding\na 👍. This helps maintainers prioritize what to work on.\n\n[**See Feature Requests**][requests]\n\n## Contributors ✨\n\nThanks goes to these people ([emoji key][emojis]):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://kentcdodds.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1500684?v=3?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eKent C. Dodds\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=kentcdodds\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=kentcdodds\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"#infra-kentcdodds\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=kentcdodds\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3Akentcdodds\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"http://conorhastings.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/8263298?v=3?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eConor Hastings\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=conorhastings\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=conorhastings\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=conorhastings\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3Aconorhastings\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/rogeliog\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/574806?v=3?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRogelio Guzman\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=rogeliog\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"http://ced.io\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1416436?v=3?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eClaudéric Demers\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=clauderic\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=clauderic\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=clauderic\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"kevindav.us\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/4150097?v=3?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eKevin Davis\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=osfan501\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=osfan501\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/nfdjps\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/19157735?v=3?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eDenver Chen\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=nfdjps\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=nfdjps\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=nfdjps\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"http://ruigrok.info\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/12719057?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eChristian Ruigrok\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/issues?q=author%3AChrisRu\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=ChrisRu\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=ChrisRu\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/hozefaj\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/2084833?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eHozefa\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/issues?q=author%3Ahozefaj\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=hozefaj\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=hozefaj\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#ideas-hozefaj\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/pushpinder107\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/9403361?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003epushpinder107\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=pushpinder107\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/tikotzky\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/200528?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMordy Tikotzky\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=tikotzky\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=tikotzky\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=tikotzky\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/sdbrannum\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/11765845?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSteven Brannum\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=sdbrannum\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=sdbrannum\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/cmeeren\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/7766733?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eChrister van der Meeren\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/issues?q=author%3Acmeeren\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"http://securitynull.net/\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/3801362?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSamuel Petrosyan\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=samyan\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/issues?q=author%3Asamyan\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://brandonkalinowski.com\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/4714862?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eBrandon Kalinowski\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/issues?q=author%3Abrandonkal\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://codefund.io\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/12481?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eEric Berry\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#fundingFinding-coderberry\" title=\"Funding Finding\"\u003e🔍\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/skube\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/146396?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSkubie Doo\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=skube\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://michaeldeboey.be\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/6643991?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMichaël De Boey\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=MichaelDeBoey\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3AMichaelDeBoey\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://tannerlinsley.com\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/5580297?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTanner Linsley\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=tannerlinsley\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=tannerlinsley\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/SweVictor\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/449347?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eVictor\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=SweVictor\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/RebeccaStevens\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/7224206?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRebecca Stevens\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/issues?q=author%3ARebeccaStevens\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=RebeccaStevens\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/marcosvega91\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/5365582?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMarco Moretti\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=marcosvega91\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://ricardobusquet.com\"\u003e\u003cimg src=\"https://avatars1.githubusercontent.com/u/7198302?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRicardo Busquet\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#ideas-rbusquet\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3Arbusquet\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=rbusquet\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/weyert\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/7049?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eWeyert de Boer\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#ideas-weyert\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/pulls?q=is%3Apr+reviewed-by%3Aweyert\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/PhilGarb\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/38015558?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePhilipp Garbowsky\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=PhilGarb\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/mart-jansink\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/4381258?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMart\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=mart-jansink\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=mart-jansink\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=mart-jansink\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/levenleven\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/6463364?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAleksey Levenstein\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=levenleven\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/diesieben07\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1915984?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTake Weiland\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=diesieben07\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/AmitAber\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/8988867?v=4?s=100\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAmit Abershitz\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/kentcdodds/match-sorter/commits?author=AmitAber\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors][all-contributors] specification.\nContributions of any kind welcome!\n\n## LICENSE\n\nMIT\n\n\u003c!-- prettier-ignore-start --\u003e\n[npm]: https://www.npmjs.com\n[node]: https://nodejs.org\n[build-badge]: https://img.shields.io/github/actions/workflow/status/kentcdodds/match-sorter/validate.yml?logo=github\u0026style=flat-square\u0026branch=main\n[build]: https://github.com/kentcdodds/match-sorter/actions?query=workflow%3Avalidate\n[coverage-badge]: https://img.shields.io/codecov/c/github/kentcdodds/match-sorter.svg?style=flat-square\n[coverage]: https://codecov.io/github/kentcdodds/match-sorter\n[version-badge]: https://img.shields.io/npm/v/match-sorter.svg?style=flat-square\n[package]: https://www.npmjs.com/package/match-sorter\n[downloads-badge]: https://img.shields.io/npm/dm/match-sorter.svg?style=flat-square\n[npmtrends]: https://www.npmtrends.com/match-sorter\n[license-badge]: https://img.shields.io/npm/l/match-sorter.svg?style=flat-square\n[license]: https://github.com/kentcdodds/match-sorter/blob/master/LICENSE\n[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\n[prs]: http://makeapullrequest.com\n[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square\n[coc]: https://github.com/kentcdodds/match-sorter/blob/master/CODE_OF_CONDUCT.md\n[examples-badge]: https://img.shields.io/badge/%F0%9F%92%A1-examples-8C8E93.svg?style=flat-square\n[examples]: https://github.com/kentcdodds/match-sorter/blob/master/other/EXAMPLES.md\n[emojis]: https://github.com/all-contributors/all-contributors#emoji-key\n[all-contributors]: https://github.com/all-contributors/all-contributors\n[all-contributors-badge]: https://img.shields.io/github/all-contributors/kentcdodds/match-sorter?color=orange\u0026style=flat-square\n[bugs]: https://github.com/kentcdodds/match-sorter/issues?utf8=%E2%9C%93\u0026q=is%3Aissue+is%3Aopen+sort%3Acreated-desc+label%3Abug\n[requests]: https://github.com/kentcdodds/match-sorter/issues?utf8=%E2%9C%93\u0026q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement\n[good-first-issue]: https://github.com/kentcdodds/match-sorter/issues?utf8=%E2%9C%93\u0026q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3Aenhancement+label%3A%22good+first+issue%22\n\n[genie]: https://github.com/kentcdodds/genie\n\u003c!-- prettier-ignore-end --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkentcdodds%2Fmatch-sorter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkentcdodds%2Fmatch-sorter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkentcdodds%2Fmatch-sorter/lists"}