├── .github └── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── config.yml │ └── feature-request.md ├── .gitignore ├── .npmignore ├── .nvmrc ├── .travis.yml ├── CODEOWNERS ├── README.md ├── index.js ├── package.json ├── test └── index.js └── yarn.lock /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Bug Report" 3 | labels: ["bug"] 4 | assignees: 5 | - @RateGravity/developers 6 | --- 7 | 8 | ## Describe the issue: 9 | Provide a brief explanation of what your're seeing. You should use this as an opportunity to provide any context that is required 10 | to understand the test cases below. 11 | 12 | ## Provide failing test cases 13 | Each test case should provide the inputs being passed to parse full name, the expected outputs, the actual outputs or errors 14 | For instance: 15 | ```js 16 | const result = parseFullName('This Name Is A Tests'); 17 | // expected result.first to be 'This' 18 | // actual result.first is 'This Name' 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Feature Request" 3 | labels: ["enhancement"] 4 | assignees: 5 | - @RateGravity/developers 6 | --- 7 | 8 | ## Describe the feature: 9 | Provide a brief explanation of what the feature is that you would like to see added. 10 | 11 | ## Give examples of the feature in use. 12 | If your proposed feature was implemented how would people use it? Give an example showing how it's use unlocks some new behavior. 13 | For instance: 14 | ```js 15 | const result = parseFullName('Name with miXed CASES', 'all', 2); // pass 2 to fix case to indicate all caps 16 | console.log(result); // { first: 'NAME', last: 'CASES' ...etc. } 17 | ``` 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | .nvmrc 3 | .travis.yml 4 | yarn.lock -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | - node 5 | - lts/* 6 | branches: 7 | only: 8 | - master 9 | - "/^v\\d+\\.\\d+(\\.\\d+)?(-\\S*)?$/" 10 | deploy: 11 | provider: npm 12 | email: dev+npmci@rategravity.com 13 | skip_cleanup: true 14 | on: 15 | tags: true 16 | api_key: 17 | secure: c0gVQy52xsoNpdcBlA0UpdJZ4SrRmNxeo76BpKo6KfOGrXHh6/kqCArj8W6de2FPVEfYodzqyDCU81IgxCuIGGz5b9DrcVChYKAv1jeAKZFVYrE2ZjjBcN4L/dbdtNREovvRX9Krd03+dtqxrGx9b/WJist1NjojuKBardDZ/hZGpVkjeK4CwOtKmI63jCWwnoICcRrNxNRkpg5vdf0pShIcK0QFW+CSvjDPXgeMm6ucP5SfkUdOEQFOEuhxdlZm7C6BbfX9ddyfhCp+Q33V+aZkjYrhF5pocsSTtNfKRjCd+oLQ5mW/JKoGPS0G/UYLlKgFqIciQyA5DxmKWa5MfzsQLiWfrAJgqFKm9jz6yftMoZPxutXrTV4lAi5rcVS03JUGSHRX3P4BhNk3pc0hZxKSCxOFVZlAr1hvxtmMtUZNMF55hxput8FUbOVtiJJHGNSzDC/fY9AIIe0NvvzfayG1x1GmjLIOyt9FU3w38Wviz4K53xAVPcO8xPjedLbNOgkFt5T3JBq+mRLGcQoltcL8vGW95y1u++hOgbVU3X95NNZfDsOB9Lc4yP2LZMxzycRbZCiCoqmJk0ceCVW/7zhda5KyRpBn+9s2TvAtVgJeJFjYCLivXVD+7w79gVmyBXWLh6CKaqlcHMU61z3MOHnk59Y+3naWEBng4vYLej8= 18 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @RateGravity/core 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # parse-full-name 2 | 3 | [![Build](https://travis-ci.org/dschnelldavis/parse-full-name.svg?branch=master)](https://travis-ci.org/dschnelldavis/parse-full-name) 4 | [![Dependencies](https://david-dm.org/dschnelldavis/parse-full-name.svg)](https://david-dm.org/dschnelldavis/parse-full-name) 5 | [![Vulnerabilities](https://snyk.io/test/npm/parse-full-name/badge.svg?style=flat-square)](https://snyk.io/test/npm/parse-full-name) 6 | 7 | ## Description 8 | 9 | parseFullName() is designed to parse large batches of full names in multiple 10 | inconsistent formats, as from a database, and continue processing without error, 11 | even if given some unparsable garbage entries. 12 | 13 | parseFullName(): 14 | 15 | 1. accepts a string containing a person's full name, in any format, 16 | 2. analyzes and attempts to detect the format of that name, 17 | 3. (if possible) parses the name into its component parts, and 18 | 4. (by default) returns an object containing all individual parts of the name: 19 | - title (string): title(s) (e.g. "Ms." or "Dr.") 20 | - first (string): first name or initial 21 | - middle (string): middle name(s) or initial(s) 22 | - last (string): last name or initial 23 | - nick (string): nickname(s) 24 | - suffix (string): suffix(es) (e.g. "Jr.", "II", or "Esq.") 25 | - error (array of strings): any parsing error messages 26 | 27 | Optionally, parseFullName() can also: 28 | 29 | * return only the specified part of a name as a string (or errors as an array) 30 | * always fix or ignore the letter case of the returned parts (the default is 31 | to fix the case only when the original input is all upper or all lowercase) 32 | * stop on errors (the default is to return warning messages in the output, 33 | but never throw a JavaScript error, no matter how mangled the input) 34 | * detect more variations of name prefixes, suffixes, and titles (the default 35 | detects 29 prefixes, 19 suffixes, 16 titles, and 8 conjunctions, but it 36 | can be set to detect 97 prefixes, 23 suffixes, and 204 titles instead) 37 | 38 | If this is not what you're looking for, is overkill for your application, or 39 | is in the wrong language, check the "Credits" section at the end of this file 40 | for links to several other excellent parsers which may suit your needs better. 41 | 42 | ## Use 43 | 44 | ### Basic Use 45 | 46 | ```javascript 47 | var parseFullName = require('parse-full-name').parseFullName; 48 | 49 | name = parseFullName('Mr. David Davis'); 50 | 51 | assert.strictEqual(name.title, 'Mr.'); 52 | assert.strictEqual(name.first, 'David'); 53 | assert.strictEqual(name.last, 'Davis'); 54 | ``` 55 | 56 | ### Options 57 | 58 | parseFullName(nameToParse, partToReturn, fixCase, stopOnError, useLongLists) 59 | 60 | nameToParse (string, required): the name to be parsed 61 | 62 | partToReturn (string, optional): the name of a single part to return 63 | 64 | - 'all' (default) = return an object containing all name parts 65 | - 'title' = return only the title(s) as a string (or an empty string) 66 | - 'first' = return only the first name as a string (or an empty string) 67 | - 'middle' = return only the middle name(s) as a string (or an empty string) 68 | - 'last' = return only the last name as a string (or an empty string) 69 | - 'nick' = return only the nickname(s) as a string (or an empty string) 70 | - 'suffix' = return only the suffix(es) as a string (or an empty string) 71 | - 'error' = return only the array of parsing error messages (or an empty array) 72 | 73 | fixCase (integer, optional): fix case of output name 74 | 75 | - -1 (default) = fix case only if input name is all upper or lowercase 76 | - 0 or false = never fix the case (retain and output same case as input name) 77 | - 1 or true = always fix case of output, even if input is mixed case 78 | 79 | stopOnError (integer, optional): makes parsing errors throw JavaScript errors 80 | 81 | - 0 or false (default) = return warnings about parsing errors, but continue 82 | - 1 or true = if a parsing error is found, throw a JavaScript error 83 | 84 | useLongLists (integer, optional): use long prefix, suffix, and title lists 85 | 86 | - 0 or false (default) = use default lists (29 prefixes, 19 suffixes, 16 titles) 87 | - 1 or true = use experimental long lists (97 prefixes, 23 suffixes, 204 titles) 88 | Note: The alternate long lists are experimental and have not been tested. 89 | Be especially careful using the long prefix list, which may incorrectly 90 | detect "Ben" as a prefix, which is common in middle-eastern names, 91 | rather than as a first name, which is common in English names 92 | 93 | ### Advanced Use 94 | 95 | ```javascript 96 | var parseFullName = require('parse-full-name').parseFullName; 97 | 98 | name = parseFullName('DE LORENZO Y GUTIEREZ, Mr. JÜAN MARTINEZ (MARTIN) Jr.','all',1,0,0); 99 | 100 | assert.strictEqual(name.title, 'Mr.'); 101 | assert.strictEqual(name.first, 'Jüan'); 102 | assert.strictEqual(name.middle, 'Martinez'); 103 | assert.strictEqual(name.last, 'de Lorenzo y Gutierez'); 104 | assert.strictEqual(name.nick, 'Martin'); 105 | assert.strictEqual(name.suffix, 'Jr.'); 106 | assert.strictEqual(name.error, []); 107 | ``` 108 | 109 | ## Reporting Bugs 110 | 111 | If you find a name this function does not parse correctly, or any other bug, 112 | please report it here: https://github.com/dschnelldavis/parse-full-name/issues 113 | 114 | ## Credits and precursors 115 | 116 | Before creating this function I studied many other name-parsing functions. 117 | None quite suited my needs, but many are excellent at what they do, and 118 | this function uses ideas from several of them. 119 | 120 | My thanks to all the following developers for sharing their work. 121 | 122 | "If I have seen further, it is by standing on the shoulders of giants." 123 | — Isaac Newton 124 | 125 | Josh Fraser's PHP-Name-Parser: 126 | https://github.com/joshfraser/PHP-Name-Parser 127 | 128 | Josh Fraser's JavaScript-Name-Parser: 129 | https://github.com/joshfraser/JavaScript-Name-Parser 130 | 131 | Garve Hays' Java NameParser: 132 | https://github.com/gkhays/NameParser 133 | 134 | Jason Priem's PHP HumanNameParser: 135 | https://web.archive.org/web/20150408022642/http://jasonpriem.org/human-name-parse/ and 136 | https://github.com/jasonpriem/HumanNameParser.php 137 | 138 | Keith Beckman's PHP nameparse: 139 | http://alphahelical.com/code/misc/nameparse/ 140 | 141 | Jed Hartman's PHP normalize_name: 142 | http://www.kith.org/journals/jed/2007/02/11/3813.html and 143 | http://www.kith.org/logos/things/code/name-parser-php.html 144 | 145 | ashaffer88's JavaScript parse-name: 146 | https://github.com/weo-edu/parse-name and 147 | https://www.npmjs.com/package/parse-name 148 | 149 | Derek Gulbranson's Python nameparser: 150 | https://github.com/derek73/python-nameparser/ 151 | 152 | Discussion about how to change all upper or lowercase names to correct case: 153 | http://stackoverflow.com/questions/11529213/given-upper-case-names-transform-to-proper-case-handling-ohara-mcdonald 154 | 155 | Title lists modified from: 156 | http://www.codeproject.com/Questions/262876/Titles-or-Salutation-list 157 | 158 | Suffix lists modified from: 159 | http://en.wikipedia.org/wiki/Suffix_(name) and 160 | https://github.com/derek73/python-nameparser/blob/master/nameparser/config/suffixes.py 161 | 162 | Prefix lists modified from: 163 | http://en.wikipedia.org/wiki/List_of_family_name_affixes 164 | 165 | Conjunction list copied entirely from: 166 | https://github.com/derek73/python-nameparser/blob/master/nameparser/config/conjunctions.py 167 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | exports.parseFullName = function parseFullName( 2 | nameToParse, partToReturn, fixCase, stopOnError, useLongLists 3 | ) { 4 | "use strict"; 5 | 6 | var i, j, k, l, m, n, part, comma, titleList, suffixList, prefixList, regex, 7 | partToCheck, partFound, partsFoundCount, firstComma, remainingCommas, 8 | nameParts = [], nameCommas = [null], partsFound = [], 9 | conjunctionList = ['&','and','et','e','of','the','und','y'], 10 | parsedName = { 11 | title: '', first: '', middle: '', last: '', nick: '', suffix: '', error: [] 12 | }; 13 | 14 | // Validate inputs, or set to defaults 15 | partToReturn = partToReturn && ['title','first','middle','last','nick', 16 | 'suffix','error'].indexOf(partToReturn.toLowerCase()) > -1 ? 17 | partToReturn.toLowerCase() : 'all'; 18 | // 'all' = return object with all parts, others return single part 19 | if ( fixCase === false ) fixCase = 0; 20 | if ( fixCase === true ) fixCase = 1; 21 | fixCase = fixCase !== 'undefined' && ( fixCase === 0 || fixCase === 1 ) ? 22 | fixCase : -1; // -1 = fix case only if input is all upper or lowercase 23 | if ( stopOnError === true ) stopOnError = 1; 24 | stopOnError = stopOnError && stopOnError === 1 ? 1 : 0; 25 | // false = output warnings on parse error, but don't stop 26 | if ( useLongLists === true ) useLongLists = 1; 27 | useLongLists = useLongLists && useLongLists === 1 ? 1 : 0; // 0 = short lists 28 | 29 | // If stopOnError = 1, throw error, otherwise return error messages in array 30 | function handleError( errorMessage ) { 31 | if ( stopOnError ) { 32 | throw 'Error: ' + errorMessage; 33 | } else { 34 | parsedName.error.push('Error: ' + errorMessage); 35 | } 36 | } 37 | 38 | // If fixCase = 1, fix case of parsedName parts before returning 39 | function fixParsedNameCase ( fixedCaseName, fixCaseNow ) { 40 | var forceCaseList = ['e','y','av','af','da','dal','de','del','der','di', 41 | 'la','le','van','der','den','vel','von','II','III','IV','J.D.','LL.M.', 42 | 'M.D.','D.O.','D.C.','Ph.D.']; 43 | var forceCaseListIndex; 44 | var namePartLabels = []; 45 | var namePartWords; 46 | if (fixCaseNow) { 47 | namePartLabels = Object.keys(parsedName) 48 | .filter( function(v) { return v !== 'error'; } ); 49 | for ( i = 0, l = namePartLabels.length; i < l; i++ ) { 50 | if ( fixedCaseName[namePartLabels[i]] ) { 51 | namePartWords = ( fixedCaseName[namePartLabels[i]] + '' ).split(' '); 52 | for ( j = 0, m = namePartWords.length; j < m; j++ ) { 53 | forceCaseListIndex = forceCaseList 54 | .map( function(v) { return v.toLowerCase(); } ) 55 | .indexOf(namePartWords[j].toLowerCase()); 56 | if ( forceCaseListIndex > -1 ) { // Set case of words in forceCaseList 57 | namePartWords[j] = forceCaseList[forceCaseListIndex]; 58 | } else if ( namePartWords[j].length === 1 ) { // Uppercase initials 59 | namePartWords[j] = namePartWords[j].toUpperCase(); 60 | } else if ( 61 | namePartWords[j].length > 2 && 62 | namePartWords[j].slice(0,1) === 63 | namePartWords[j].slice(0,1).toUpperCase() && 64 | namePartWords[j].slice(1,2) === 65 | namePartWords[j].slice(1,2).toLowerCase() && 66 | namePartWords[j].slice(2) === 67 | namePartWords[j].slice(2).toUpperCase() 68 | ) { // Detect McCASE and convert to McCase 69 | namePartWords[j] = namePartWords[j].slice(0,3) + 70 | namePartWords[j].slice(3).toLowerCase(); 71 | } else if ( 72 | namePartLabels[j] === 'suffix' && 73 | namePartWords[j].slice(-1) !== '.' && 74 | !suffixList.indexOf(namePartWords[j].toLowerCase()) 75 | ) { // Convert suffix abbreviations to UPPER CASE 76 | if ( namePartWords[j] === namePartWords[j].toLowerCase() ) { 77 | namePartWords[j] = namePartWords[j].toUpperCase(); 78 | } 79 | } else { // Convert to Title Case 80 | namePartWords[j] = namePartWords[j].slice(0,1).toUpperCase() + 81 | namePartWords[j].slice(1).toLowerCase(); 82 | } 83 | } 84 | fixedCaseName[namePartLabels[i]] = namePartWords.join(' '); 85 | } 86 | } 87 | } 88 | return fixedCaseName; 89 | } 90 | 91 | // Nickname: remove and store parts with surrounding punctuation as nicknames 92 | function findNicknames(nameToParse) { 93 | const paddedName = ' ' + nameToParse + ' '; 94 | const nicknameMatches = []; 95 | 96 | // Define delimiter pairs as a direct mapping 97 | const delimiterPairs = { 98 | "'": "'", 99 | '"': '"', 100 | "“": "”", 101 | "‘": "’", 102 | "[": "]", 103 | "(": ")" 104 | }; 105 | 106 | let i = 0, currentDelimiter = null, startPos = -1, char, nextChar; 107 | 108 | for (i = 0 ; i < paddedName.length ; i++) { 109 | char = paddedName[i]; 110 | 111 | if (currentDelimiter === null) { 112 | // Not inside a delimiter - check if this is an opening delimiter 113 | if (delimiterPairs[char] && i > 0 && paddedName[i-1] === ' ') { 114 | currentDelimiter = char; 115 | startPos = i - 1; // Include the preceding space 116 | } 117 | } else { 118 | // Already inside a delimiter - check if this is the matching closing delimiter 119 | if (char === delimiterPairs[currentDelimiter]) { 120 | // Check what follows the closing delimiter 121 | if (i + 1 < paddedName.length) { 122 | nextChar = paddedName[i + 1]; 123 | 124 | if (nextChar === ' ' || (nextChar === ',' && i + 2 < paddedName.length && paddedName[i + 2] === ' ')) { 125 | // Valid nickname found 126 | const endPos = nextChar === ',' ? i + 2 : i + 1; 127 | nicknameMatches.push(paddedName.substring(startPos, endPos + 1)); 128 | } 129 | } 130 | 131 | // Reset state 132 | currentDelimiter = null; 133 | } 134 | } 135 | } 136 | 137 | return nicknameMatches; 138 | } 139 | 140 | // If no input name, or input name is not a string, abort 141 | if ( !nameToParse || typeof nameToParse !== 'string' ) { 142 | handleError('No input'); 143 | parsedName = fixParsedNameCase(parsedName, fixCase); 144 | return partToReturn === 'all' ? parsedName : parsedName[partToReturn]; 145 | } else { 146 | nameToParse = nameToParse.trim(); 147 | } 148 | 149 | // Auto-detect fixCase: fix if nameToParse is all upper or all lowercase 150 | if ( fixCase === -1 ) { 151 | fixCase = ( 152 | nameToParse === nameToParse.toUpperCase() || 153 | nameToParse === nameToParse.toLowerCase() ? 1 : 0 154 | ); 155 | } 156 | 157 | // Initilize lists of prefixs, suffixs, and titles to detect 158 | // Note: These list entries must be all lowercase 159 | if ( useLongLists ) { 160 | suffixList = ['esq','esquire','jr','jnr','sr','snr','2','ii','iii','iv', 161 | 'v','clu','chfc','cfp','md','phd','j.d.','ll.m.','m.d.','d.o.','d.c.', 162 | 'p.c.','ph.d.']; 163 | prefixList = ['a','ab','antune','ap','abu','al','alm','alt','bab','bäck', 164 | 'bar','bath','bat','beau','beck','ben','berg','bet','bin','bint','birch', 165 | 'björk','björn','bjur','da','dahl','dal','de','degli','dele','del', 166 | 'della','der','di','dos','du','e','ek','el','escob','esch','fleisch', 167 | 'fitz','fors','gott','griff','haj','haug','holm','ibn','kauf','kil', 168 | 'koop','kvarn','la','le','lind','lönn','lund','mac','mhic','mic','mir', 169 | 'na','naka','neder','nic','ni','nin','nord','norr','ny','o','ua','ui\'', 170 | 'öfver','ost','över','öz','papa','pour','quarn','skog','skoog','sten', 171 | 'stor','ström','söder','ter','ter','tre','türk','van','väst','väster', 172 | 'vest','von']; 173 | titleList = ['mr','mrs','ms','miss','dr','herr','monsieur','hr','frau', 174 | 'a v m','admiraal','admiral','air cdre','air commodore','air marshal', 175 | 'air vice marshal','alderman','alhaji','ambassador','baron','barones', 176 | 'brig','brig gen','brig general','brigadier','brigadier general', 177 | 'brother','canon','capt','captain','cardinal','cdr','chief','cik','cmdr', 178 | 'coach','col','col dr','colonel','commandant','commander','commissioner', 179 | 'commodore','comte','comtessa','congressman','conseiller','consul', 180 | 'conte','contessa','corporal','councillor','count','countess', 181 | 'crown prince','crown princess','dame','datin','dato','datuk', 182 | 'datuk seri','deacon','deaconess','dean','dhr','dipl ing','doctor', 183 | 'dott','dott sa','dr','dr ing','dra','drs','embajador','embajadora','en', 184 | 'encik','eng','eur ing','exma sra','exmo sr','f o','father', 185 | 'first lieutient','first officer','flt lieut','flying officer','fr', 186 | 'frau','fraulein','fru','gen','generaal','general','governor','graaf', 187 | 'gravin','group captain','grp capt','h e dr','h h','h m','h r h','hajah', 188 | 'haji','hajim','her highness','her majesty','herr','high chief', 189 | 'his highness','his holiness','his majesty','hon','hr','hra','ing','ir', 190 | 'jonkheer','judge','justice','khun ying','kolonel','lady','lcda','lic', 191 | 'lieut','lieut cdr','lieut col','lieut gen','lord','m','m l','m r', 192 | 'madame','mademoiselle','maj gen','major','master','mevrouw','miss', 193 | 'mlle','mme','monsieur','monsignor','mr','mrs','ms','mstr','nti','pastor', 194 | 'president','prince','princess','princesse','prinses','prof','prof dr', 195 | 'prof sir','professor','puan','puan sri','rabbi','rear admiral','rev', 196 | 'rev canon','rev dr','rev mother','reverend','rva','senator','sergeant', 197 | 'sheikh','sheikha','sig','sig na','sig ra','sir','sister','sqn ldr','sr', 198 | 'sr d','sra','srta','sultan','tan sri','tan sri dato','tengku','teuku', 199 | 'than puying','the hon dr','the hon justice','the hon miss','the hon mr', 200 | 'the hon mrs','the hon ms','the hon sir','the very rev','toh puan','tun', 201 | 'vice admiral','viscount','viscountess','wg cdr', 'ind', 'misc', 'mx']; 202 | } else { 203 | suffixList = ['esq','esquire','jr','jnr','sr','snr','2','ii','iii','iv', 204 | 'md','phd','j.d.','ll.m.','m.d.','d.o.','d.c.','p.c.','ph.d.']; 205 | prefixList = ['ab','bar','bin','da','dal','de','de la','del','della','der', 206 | 'di','du','ibn','l\'','la','le','san','st','st.','ste','ter','van', 207 | 'van de','van der','van den','vel','ver','vere','von']; 208 | titleList = ['dr','miss','mr','mrs','ms','prof','sir','frau','herr','hr', 209 | 'monsieur','captain','doctor','judge','officer','professor', 'ind', 'misc', 210 | 'mx']; 211 | } 212 | 213 | partFound = findNicknames(nameToParse); 214 | if ( partFound && partFound.length > 0 ) partsFound = partsFound.concat(partFound); 215 | partsFoundCount = partsFound.length; 216 | if ( partsFoundCount === 1 ) { 217 | parsedName.nick = partsFound[0].slice(2).slice(0,-2); 218 | if ( parsedName.nick.slice(-1) === ',' ) { 219 | parsedName.nick = parsedName.nick.slice(0,-1); 220 | } 221 | nameToParse = (' '+nameToParse+' ').replace(partsFound[0], ' ').trim(); 222 | partsFound = []; 223 | } else if ( partsFoundCount > 1 ) { 224 | handleError( partsFoundCount + ' nicknames found' ); 225 | for ( i = 0; i < partsFoundCount; i++ ) { 226 | nameToParse = ( ' ' + nameToParse + ' ' ) 227 | .replace(partsFound[i], ' ').trim(); 228 | partsFound[i] = partsFound[i].slice(2).slice(0,-2); 229 | if ( partsFound[i].slice(-1) === ',' ) { 230 | partsFound[i] = partsFound[i].slice(0,-1); 231 | } 232 | } 233 | parsedName.nick = partsFound.join(', '); 234 | partsFound = []; 235 | } 236 | if ( !nameToParse.trim().length ) { 237 | parsedName = fixParsedNameCase(parsedName, fixCase); 238 | return partToReturn === 'all' ? parsedName : parsedName[partToReturn]; 239 | } 240 | 241 | // Split remaining nameToParse into parts, remove and store preceding commas 242 | for ( i = 0, n = nameToParse.split(' '), l = n.length; i < l; i++ ) { 243 | part = n[i]; 244 | comma = null; 245 | if ( part.slice(-1) === ',' ) { 246 | comma = ','; 247 | part = part.slice(0,-1); 248 | } 249 | nameParts.push(part); 250 | nameCommas.push(comma); 251 | } 252 | 253 | // Suffix: remove and store matching parts as suffixes 254 | for ( l = nameParts.length, i = l-1; i > 0; i-- ) { 255 | partToCheck = (nameParts[i].slice(-1) === '.' ? 256 | nameParts[i].slice(0,-1).toLowerCase() : nameParts[i].toLowerCase()); 257 | if ( 258 | suffixList.indexOf(partToCheck) > -1 || 259 | suffixList.indexOf(partToCheck+'.') > -1 260 | ) { 261 | partsFound = nameParts.splice(i,1).concat(partsFound); 262 | if ( nameCommas[i] === ',' ) { // Keep comma, either before or after 263 | nameCommas.splice(i+1,1); 264 | } else { 265 | nameCommas.splice(i,1); 266 | } 267 | } 268 | } 269 | partsFoundCount = partsFound.length; 270 | if ( partsFoundCount === 1 ) { 271 | parsedName.suffix = partsFound[0]; 272 | partsFound = []; 273 | } else if ( partsFoundCount > 1 ) { 274 | handleError(partsFoundCount + ' suffixes found'); 275 | parsedName.suffix = partsFound.join(', '); 276 | partsFound = []; 277 | } 278 | if ( !nameParts.length ) { 279 | parsedName = fixParsedNameCase(parsedName, fixCase); 280 | return partToReturn === 'all' ? parsedName : parsedName[partToReturn]; 281 | } 282 | 283 | // Title: remove and store matching parts as titles 284 | for( l = nameParts.length, i = l-1; i >= 0; i--) { 285 | partToCheck = (nameParts[i].slice(-1) === '.' ? 286 | nameParts[i].slice(0,-1).toLowerCase() : nameParts[i].toLowerCase()); 287 | if ( 288 | titleList.indexOf(partToCheck) > -1 || 289 | titleList.indexOf(partToCheck+'.') > -1 290 | ) { 291 | partsFound = nameParts.splice(i,1).concat(partsFound); 292 | if ( nameCommas[i] === ',' ) { // Keep comma, either before or after 293 | nameCommas.splice(i+1,1); 294 | } else { 295 | nameCommas.splice(i,1); 296 | } 297 | } 298 | } 299 | partsFoundCount = partsFound.length; 300 | if ( partsFoundCount === 1 ) { 301 | parsedName.title = partsFound[0]; 302 | partsFound = []; 303 | } else if ( partsFoundCount > 1 ) { 304 | handleError(partsFoundCount + ' titles found'); 305 | parsedName.title = partsFound.join(', '); 306 | partsFound = []; 307 | } 308 | if ( !nameParts.length ) { 309 | parsedName = fixParsedNameCase(parsedName, fixCase); 310 | return partToReturn === 'all' ? parsedName : parsedName[partToReturn]; 311 | } 312 | 313 | // Join name prefixes to following names 314 | if ( nameParts.length > 1 ) { 315 | for ( i = nameParts.length-2; i >= 0; i-- ) { 316 | if ( prefixList.indexOf(nameParts[i].toLowerCase()) > -1 ) { 317 | nameParts[i] = nameParts[i] + ' ' + nameParts[i+1]; 318 | nameParts.splice(i+1,1); 319 | nameCommas.splice(i+1,1); 320 | } 321 | } 322 | } 323 | 324 | // Join conjunctions to surrounding names 325 | if ( nameParts.length > 2 ) { 326 | for ( i = nameParts.length-3; i >= 0; i-- ) { 327 | if ( conjunctionList.indexOf(nameParts[i+1].toLowerCase()) > -1 ) { 328 | nameParts[i] = nameParts[i] + ' ' + nameParts[i+1] + ' ' + nameParts[i+2]; 329 | nameParts.splice(i+1,2); 330 | nameCommas.splice(i+1,2); 331 | i--; 332 | } 333 | } 334 | } 335 | 336 | // Suffix: remove and store items after extra commas as suffixes 337 | nameCommas.pop(); 338 | firstComma = nameCommas.indexOf(','); 339 | remainingCommas = nameCommas.filter(function(v) { return v !== null; }).length; 340 | if ( firstComma > 1 || remainingCommas > 1 ) { 341 | for ( i = nameParts.length-1; i >= 2; i-- ) { 342 | if ( nameCommas[i] === ',' ) { 343 | partsFound = nameParts.splice(i,1).concat(partsFound); 344 | nameCommas.splice(i,1); 345 | remainingCommas--; 346 | } else { 347 | break; 348 | } 349 | } 350 | } 351 | if ( partsFound.length ) { 352 | if ( parsedName.suffix ) { 353 | partsFound = [parsedName.suffix].concat(partsFound); 354 | } 355 | parsedName.suffix = partsFound.join(', '); 356 | partsFound = []; 357 | } 358 | 359 | // Last name: remove and store last name 360 | if ( remainingCommas > 0 ) { 361 | if ( remainingCommas > 1 ) { 362 | handleError( (remainingCommas-1) + ' extra commas found' ); 363 | } 364 | // Remove and store all parts before first comma as last name 365 | if ( nameCommas.indexOf(',') ) { 366 | parsedName.last = nameParts.splice(0,nameCommas.indexOf(',')).join(' '); 367 | nameCommas.splice(0,nameCommas.indexOf(',')); 368 | } 369 | } else { 370 | // Remove and store last part as last name 371 | parsedName.last = nameParts.pop(); 372 | } 373 | if ( !nameParts.length ) { 374 | parsedName = fixParsedNameCase(parsedName, fixCase); 375 | return partToReturn === 'all' ? parsedName : parsedName[partToReturn]; 376 | } 377 | 378 | // First name: remove and store first part as first name 379 | parsedName.first = nameParts.shift(); 380 | if ( !nameParts.length ) { 381 | parsedName = fixParsedNameCase(parsedName, fixCase); 382 | return partToReturn === 'all' ? parsedName : parsedName[partToReturn]; 383 | } 384 | 385 | // Middle name: store all remaining parts as middle name 386 | if ( nameParts.length > 2 ) { 387 | handleError(nameParts.length + ' middle names'); 388 | } 389 | parsedName.middle = nameParts.join(' '); 390 | 391 | parsedName = fixParsedNameCase(parsedName, fixCase); 392 | return partToReturn === 'all' ? parsedName : parsedName[partToReturn]; 393 | }; 394 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parse-full-name", 3 | "version": "1.2.6", 4 | "description": "A function that accepts the full name of a person in any format, parses it, and returns its parts { title, first name, middle name, last name, nickname, suffix, [and any parsing errors] }.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha test/" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/RateGravity/parse-full-name" 12 | }, 13 | "keywords": [ 14 | "parse", 15 | "parser", 16 | "name", 17 | "full name", 18 | "first name", 19 | "middle name", 20 | "last name", 21 | "nickname" 22 | ], 23 | "author": "Own Up (https://www,ownup.com)", 24 | "contributors": [ 25 | "David Schnell-Davis (http://github.com/dschnelldavis)" 26 | ], 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/RateGravity/parse-full-name/issues" 30 | }, 31 | "homepage": "https://github.com/RateGravity/parse-full-name", 32 | "dependencies": {}, 33 | "devDependencies": { 34 | "mocha": "^11.1.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var parseFullName = require('../').parseFullName; 3 | var error; 4 | 5 | var verifyName = function(nameToCheck, partsToCheck) { 6 | assert.strictEqual(nameToCheck.title, partsToCheck[0]); 7 | assert.strictEqual(nameToCheck.first, partsToCheck[1]); 8 | assert.strictEqual(nameToCheck.middle, partsToCheck[2]); 9 | assert.strictEqual(nameToCheck.last, partsToCheck[3]); 10 | assert.strictEqual(nameToCheck.nick, partsToCheck[4]); 11 | assert.strictEqual(nameToCheck.suffix, partsToCheck[5]); 12 | assert.strictEqual(nameToCheck.error.length, partsToCheck[6].length); 13 | for ( var i = 1, l = partsToCheck[6].length; i < l; i++ ) { 14 | assert.strictEqual(nameToCheck.error[i], partsToCheck[6][i]); 15 | } 16 | }; 17 | 18 | 19 | 20 | describe('parse-full-name', function() { 21 | describe('parseFullName', function() { 22 | it('parses first names', function() { 23 | verifyName(parseFullName('David Davis'), 24 | ['','David','','Davis','','',[]]); 25 | verifyName(parseFullName('Davis, David'), 26 | ['','David','','Davis','','',[]]); 27 | }); 28 | it('parses last names', function() { 29 | verifyName(parseFullName('Gerald Böck'), 30 | ['','Gerald','','Böck','','',[]]); 31 | verifyName(parseFullName('Böck, Gerald'), 32 | ['','Gerald','','Böck','','',[]]); 33 | }); 34 | it('parses middle names', function() { 35 | verifyName(parseFullName('David William Davis'), 36 | ['','David','William','Davis','','',[]]); 37 | verifyName(parseFullName('Davis, David William'), 38 | ['','David','William','Davis','','',[]]); 39 | }); 40 | it('parses last names including known prefixes', function() { 41 | verifyName(parseFullName('Vincent Van Gogh'), 42 | ['','Vincent','','Van Gogh','','',[]]); 43 | verifyName(parseFullName('Van Gogh, Vincent'), 44 | ['','Vincent','','Van Gogh','','',[]]); 45 | verifyName(parseFullName('Lorenzo de Médici'), 46 | ['','Lorenzo','','de Médici','','',[]]); 47 | verifyName(parseFullName('de Médici, Lorenzo'), 48 | ['','Lorenzo','','de Médici','','',[]]); 49 | verifyName(parseFullName('Jüan de la Véña'), 50 | ['','Jüan','','de la Véña','','',[]]); 51 | verifyName(parseFullName('de la Véña, Jüan'), 52 | ['','Jüan','','de la Véña','','',[]]); 53 | }); 54 | it('parses compound last names', function() { 55 | verifyName(parseFullName('Jüan Martinez de Lorenzo y Gutierez'), 56 | ['','Jüan','Martinez','de Lorenzo y Gutierez','','',[]]); 57 | verifyName(parseFullName('de Lorenzo y Gutierez, Jüan Martinez'), 58 | ['','Jüan','Martinez','de Lorenzo y Gutierez','','',[]]); 59 | }); 60 | it('parses nicknames', function() { 61 | verifyName(parseFullName('Orenthal James "O. J." Simpson'), 62 | ['','Orenthal','James','Simpson','O. J.','',[]]); 63 | verifyName(parseFullName("Orenthal 'O. J.' James Simpson"), 64 | ['','Orenthal','James','Simpson','O. J.','',[]]); 65 | verifyName(parseFullName('(O. J.) Orenthal James Simpson'), 66 | ['','Orenthal','James','Simpson','O. J.','',[]]); 67 | verifyName(parseFullName('Simpson, Orenthal James “O. J.”'), 68 | ['','Orenthal','James','Simpson','O. J.','',[]]); 69 | verifyName(parseFullName("Simpson, Orenthal ‘O. J.’ James"), 70 | ['','Orenthal','James','Simpson','O. J.','',[]]); 71 | verifyName(parseFullName('Simpson, [O. J.] Orenthal James'), 72 | ['','Orenthal','James','Simpson','O. J.','',[]]); 73 | verifyName(parseFullName('Strippoli, Charles J (HM Home and Community Svcs LLC)'), 74 | ['','Charles','J','Strippoli','HM Home and Community Svcs LLC','',[]]); 75 | 76 | }); 77 | it('parses known suffixes', function() { 78 | verifyName(parseFullName('Sammy Davis, Jr.'), 79 | ['','Sammy','','Davis','','Jr.',[]]); 80 | verifyName(parseFullName('Davis, Sammy, Jr.'), 81 | ['','Sammy','','Davis','','Jr.',[]]); 82 | }); 83 | it('parses unknown suffixes', function() { 84 | verifyName(parseFullName('John P. Doe-Ray, Jr., CLU, CFP, LUTC'), 85 | ['','John','P.','Doe-Ray','','Jr., CLU, CFP, LUTC',[]]); 86 | verifyName(parseFullName('Doe-Ray, John P., Jr., CLU, CFP, LUTC'), 87 | ['','John','P.','Doe-Ray','','Jr., CLU, CFP, LUTC',[]]); 88 | }); 89 | it('parses titles', function() { 90 | verifyName(parseFullName('Dr. John P. Doe-Ray, Jr.'), 91 | ['Dr.','John','P.','Doe-Ray','','Jr.',[]]); 92 | verifyName(parseFullName('Dr. Doe-Ray, John P., Jr.'), 93 | ['Dr.','John','P.','Doe-Ray','','Jr.',[]]); 94 | verifyName(parseFullName('Doe-Ray, Dr. John P., Jr.'), 95 | ['Dr.','John','P.','Doe-Ray','','Jr.',[]]); 96 | }); 97 | it('parses name parts in many different orders', function() { 98 | verifyName(parseFullName( 99 | 'Mr. Jüan Martinez (Martin) de Lorenzo y Gutierez Jr.'), 100 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 101 | verifyName(parseFullName( 102 | 'de Lorenzo y Gutierez, Mr. Jüan Martinez (Martin) Jr.'), 103 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 104 | verifyName(parseFullName( 105 | 'de Lorenzo y Gutierez, Mr. Jüan (Martin) Martinez Jr.'), 106 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 107 | verifyName(parseFullName( 108 | 'Mr. de Lorenzo y Gutierez, Jüan Martinez (Martin) Jr.'), 109 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 110 | verifyName(parseFullName( 111 | 'Mr. de Lorenzo y Gutierez, Jüan (Martin) Martinez Jr.'), 112 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 113 | verifyName(parseFullName( 114 | 'Mr. de Lorenzo y Gutierez Jr., Jüan Martinez (Martin)'), 115 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 116 | verifyName(parseFullName( 117 | 'Mr. de Lorenzo y Gutierez Jr., Jüan (Martin) Martinez'), 118 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 119 | verifyName(parseFullName( 120 | 'Mr. de Lorenzo y Gutierez, Jr. Jüan Martinez (Martin)'), 121 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 122 | verifyName(parseFullName( 123 | 'Mr. de Lorenzo y Gutierez, Jr. Jüan (Martin) Martinez'), 124 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 125 | }); 126 | it('automatically fixes all upper and all lowercase names', function() { 127 | verifyName(parseFullName( 128 | 'MR. JÜAN MARTINEZ (MARTIN) DE LORENZO Y GUTIEREZ JR.'), 129 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 130 | verifyName(parseFullName( 131 | 'mr. jüan martinez (martin) de lorenzo y gutierez jr.'), 132 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 133 | }); 134 | it('manually fixes case, or not, when specified', function() { 135 | verifyName(parseFullName( 136 | 'Mr. JÜAN MARTINEZ (MARTIN) DE LORENZO Y GUTIEREZ Jr.'), 137 | ['Mr.','JÜAN','MARTINEZ','DE LORENZO Y GUTIEREZ','MARTIN','Jr.',[]]); 138 | verifyName(parseFullName( 139 | 'Mr. JÜAN MARTINEZ (MARTIN) DE LORENZO Y GUTIEREZ JR.','all',1), 140 | ['Mr.','Jüan','Martinez','de Lorenzo y Gutierez','Martin','Jr.',[]]); 141 | verifyName(parseFullName( 142 | 'mr. jüan martinez (martin) de lorenzo y gutierez jr.','all',0), 143 | ['mr.','jüan','martinez','de lorenzo y gutierez','martin','jr.',[]]); 144 | }); 145 | it('handles leading or trailing whitespace', function() { 146 | verifyName(parseFullName('Ezekiel Johnson '), 147 | ['','Ezekiel','','Johnson','','',[]]); 148 | verifyName(parseFullName(' Ezekiel Johnson'), 149 | ['','Ezekiel','','Johnson','','',[]]); 150 | }); 151 | it('returns a single part, when specified', function() { 152 | assert.strictEqual(parseFullName( 153 | 'Mr. Jüan Martinez (Martin) de Lorenzo y Gutierez Jr.', 154 | 'title'),'Mr.'); 155 | assert.strictEqual(parseFullName( 156 | 'Mr. Jüan Martinez (Martin) de Lorenzo y Gutierez Jr.', 157 | 'first'),'Jüan'); 158 | assert.strictEqual(parseFullName( 159 | 'Mr. Jüan Martinez (Martin) de Lorenzo y Gutierez Jr.', 160 | 'middle'),'Martinez'); 161 | assert.strictEqual(parseFullName( 162 | 'Mr. Jüan Martinez (Martin) de Lorenzo y Gutierez Jr.', 163 | 'last'),'de Lorenzo y Gutierez'); 164 | assert.strictEqual(parseFullName( 165 | 'Mr. Jüan Martinez (Martin) de Lorenzo y Gutierez Jr.', 166 | 'nick'),'Martin'); 167 | assert.strictEqual(parseFullName( 168 | 'Mr. Jüan Martinez (Martin) de Lorenzo y Gutierez Jr.', 169 | 'suffix'),'Jr.'); 170 | }); 171 | it('continues processing, even when fed garbage input', function() { 172 | verifyName(parseFullName('as;dfkj ;aerha;sfa ef;oia;woeig hz;sofi hz;oifj;zoseifj zs;eofij z;soeif jzs;oefi jz;osif z;osefij zs;oif jz;soefihz;sodifh z;sofu hzsieufh zlsiudfh zksefiulzseofih ;zosufh ;oseihgfz;osef h:OSfih lziusefhaowieufyg oaweifugy'), 173 | ['','as;dfkj', 174 | ';aerha;sfa ef;oia;woeig hz;sofi hz;oifj;zoseifj zs;eofij z;soeif jzs;oefi jz;osif z;osefij zs;oif jz;soefihz;sodifh z;sofu hzsieufh zlsiudfh zksefiulzseofih ;zosufh ;oseihgfz;osef h:OSfih lziusefhaowieufyg', 175 | 'oaweifugy','','',['Error: 22 middle names']]); 176 | }); 177 | it('returns warnings for null/undefined names', function() { 178 | verifyName(parseFullName(null),['','','','','','',['Error: No input']]); 179 | verifyName(parseFullName(),['','','','','','',['Error: No input']]); 180 | }); 181 | it('will throw errors, when specified', function() { 182 | assert.doesNotThrow(function(){ return parseFullName(''); }); 183 | assert.throws(function(){ return parseFullName('','all',-1,1); }); 184 | }); 185 | }); 186 | }); 187 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@isaacs/cliui@^8.0.2": 6 | version "8.0.2" 7 | resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" 8 | integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== 9 | dependencies: 10 | string-width "^5.1.2" 11 | string-width-cjs "npm:string-width@^4.2.0" 12 | strip-ansi "^7.0.1" 13 | strip-ansi-cjs "npm:strip-ansi@^6.0.1" 14 | wrap-ansi "^8.1.0" 15 | wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" 16 | 17 | "@pkgjs/parseargs@^0.11.0": 18 | version "0.11.0" 19 | resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" 20 | integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== 21 | 22 | ansi-colors@^4.1.3: 23 | version "4.1.3" 24 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" 25 | integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== 26 | 27 | ansi-regex@^5.0.1: 28 | version "5.0.1" 29 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 30 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 31 | 32 | ansi-regex@^6.0.1: 33 | version "6.1.0" 34 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" 35 | integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== 36 | 37 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 38 | version "4.3.0" 39 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 40 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 41 | dependencies: 42 | color-convert "^2.0.1" 43 | 44 | ansi-styles@^6.1.0: 45 | version "6.2.1" 46 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" 47 | integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== 48 | 49 | anymatch@~3.1.2: 50 | version "3.1.3" 51 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 52 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 53 | dependencies: 54 | normalize-path "^3.0.0" 55 | picomatch "^2.0.4" 56 | 57 | argparse@^2.0.1: 58 | version "2.0.1" 59 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 60 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 61 | 62 | balanced-match@^1.0.0: 63 | version "1.0.2" 64 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 65 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 66 | 67 | binary-extensions@^2.0.0: 68 | version "2.3.0" 69 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" 70 | integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== 71 | 72 | brace-expansion@^2.0.1: 73 | version "2.0.1" 74 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 75 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 76 | dependencies: 77 | balanced-match "^1.0.0" 78 | 79 | braces@~3.0.2: 80 | version "3.0.3" 81 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 82 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 83 | dependencies: 84 | fill-range "^7.1.1" 85 | 86 | browser-stdout@^1.3.1: 87 | version "1.3.1" 88 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 89 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 90 | 91 | camelcase@^6.0.0: 92 | version "6.3.0" 93 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 94 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 95 | 96 | chalk@^4.1.0: 97 | version "4.1.2" 98 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 99 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 100 | dependencies: 101 | ansi-styles "^4.1.0" 102 | supports-color "^7.1.0" 103 | 104 | chokidar@^3.5.3: 105 | version "3.6.0" 106 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" 107 | integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== 108 | dependencies: 109 | anymatch "~3.1.2" 110 | braces "~3.0.2" 111 | glob-parent "~5.1.2" 112 | is-binary-path "~2.1.0" 113 | is-glob "~4.0.1" 114 | normalize-path "~3.0.0" 115 | readdirp "~3.6.0" 116 | optionalDependencies: 117 | fsevents "~2.3.2" 118 | 119 | cliui@^8.0.1: 120 | version "8.0.1" 121 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" 122 | integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== 123 | dependencies: 124 | string-width "^4.2.0" 125 | strip-ansi "^6.0.1" 126 | wrap-ansi "^7.0.0" 127 | 128 | color-convert@^2.0.1: 129 | version "2.0.1" 130 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 131 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 132 | dependencies: 133 | color-name "~1.1.4" 134 | 135 | color-name@~1.1.4: 136 | version "1.1.4" 137 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 138 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 139 | 140 | cross-spawn@^7.0.0: 141 | version "7.0.6" 142 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" 143 | integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== 144 | dependencies: 145 | path-key "^3.1.0" 146 | shebang-command "^2.0.0" 147 | which "^2.0.1" 148 | 149 | debug@^4.3.5: 150 | version "4.4.0" 151 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" 152 | integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== 153 | dependencies: 154 | ms "^2.1.3" 155 | 156 | decamelize@^4.0.0: 157 | version "4.0.0" 158 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 159 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 160 | 161 | diff@^5.2.0: 162 | version "5.2.0" 163 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" 164 | integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== 165 | 166 | eastasianwidth@^0.2.0: 167 | version "0.2.0" 168 | resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" 169 | integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== 170 | 171 | emoji-regex@^8.0.0: 172 | version "8.0.0" 173 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 174 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 175 | 176 | emoji-regex@^9.2.2: 177 | version "9.2.2" 178 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" 179 | integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== 180 | 181 | escalade@^3.1.1: 182 | version "3.2.0" 183 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" 184 | integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== 185 | 186 | escape-string-regexp@^4.0.0: 187 | version "4.0.0" 188 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 189 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 190 | 191 | fill-range@^7.1.1: 192 | version "7.1.1" 193 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 194 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 195 | dependencies: 196 | to-regex-range "^5.0.1" 197 | 198 | find-up@^5.0.0: 199 | version "5.0.0" 200 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 201 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 202 | dependencies: 203 | locate-path "^6.0.0" 204 | path-exists "^4.0.0" 205 | 206 | flat@^5.0.2: 207 | version "5.0.2" 208 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 209 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 210 | 211 | foreground-child@^3.1.0: 212 | version "3.3.0" 213 | resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" 214 | integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== 215 | dependencies: 216 | cross-spawn "^7.0.0" 217 | signal-exit "^4.0.1" 218 | 219 | fsevents@~2.3.2: 220 | version "2.3.3" 221 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 222 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 223 | 224 | get-caller-file@^2.0.5: 225 | version "2.0.5" 226 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 227 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 228 | 229 | glob-parent@~5.1.2: 230 | version "5.1.2" 231 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 232 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 233 | dependencies: 234 | is-glob "^4.0.1" 235 | 236 | glob@^10.4.5: 237 | version "10.4.5" 238 | resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" 239 | integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== 240 | dependencies: 241 | foreground-child "^3.1.0" 242 | jackspeak "^3.1.2" 243 | minimatch "^9.0.4" 244 | minipass "^7.1.2" 245 | package-json-from-dist "^1.0.0" 246 | path-scurry "^1.11.1" 247 | 248 | has-flag@^4.0.0: 249 | version "4.0.0" 250 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 251 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 252 | 253 | he@^1.2.0: 254 | version "1.2.0" 255 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 256 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 257 | 258 | is-binary-path@~2.1.0: 259 | version "2.1.0" 260 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 261 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 262 | dependencies: 263 | binary-extensions "^2.0.0" 264 | 265 | is-extglob@^2.1.1: 266 | version "2.1.1" 267 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 268 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 269 | 270 | is-fullwidth-code-point@^3.0.0: 271 | version "3.0.0" 272 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 273 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 274 | 275 | is-glob@^4.0.1, is-glob@~4.0.1: 276 | version "4.0.3" 277 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 278 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 279 | dependencies: 280 | is-extglob "^2.1.1" 281 | 282 | is-number@^7.0.0: 283 | version "7.0.0" 284 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 285 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 286 | 287 | is-plain-obj@^2.1.0: 288 | version "2.1.0" 289 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 290 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 291 | 292 | is-unicode-supported@^0.1.0: 293 | version "0.1.0" 294 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 295 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 296 | 297 | isexe@^2.0.0: 298 | version "2.0.0" 299 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 300 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 301 | 302 | jackspeak@^3.1.2: 303 | version "3.4.3" 304 | resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" 305 | integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== 306 | dependencies: 307 | "@isaacs/cliui" "^8.0.2" 308 | optionalDependencies: 309 | "@pkgjs/parseargs" "^0.11.0" 310 | 311 | js-yaml@^4.1.0: 312 | version "4.1.0" 313 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 314 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 315 | dependencies: 316 | argparse "^2.0.1" 317 | 318 | locate-path@^6.0.0: 319 | version "6.0.0" 320 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 321 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 322 | dependencies: 323 | p-locate "^5.0.0" 324 | 325 | log-symbols@^4.1.0: 326 | version "4.1.0" 327 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 328 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 329 | dependencies: 330 | chalk "^4.1.0" 331 | is-unicode-supported "^0.1.0" 332 | 333 | lru-cache@^10.2.0: 334 | version "10.4.3" 335 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" 336 | integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== 337 | 338 | minimatch@^5.1.6: 339 | version "5.1.6" 340 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" 341 | integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== 342 | dependencies: 343 | brace-expansion "^2.0.1" 344 | 345 | minimatch@^9.0.4: 346 | version "9.0.5" 347 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" 348 | integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== 349 | dependencies: 350 | brace-expansion "^2.0.1" 351 | 352 | "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: 353 | version "7.1.2" 354 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" 355 | integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== 356 | 357 | mocha@^11.1.0: 358 | version "11.1.0" 359 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.1.0.tgz#20d7c6ac4d6d6bcb60a8aa47971fca74c65c3c66" 360 | integrity sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg== 361 | dependencies: 362 | ansi-colors "^4.1.3" 363 | browser-stdout "^1.3.1" 364 | chokidar "^3.5.3" 365 | debug "^4.3.5" 366 | diff "^5.2.0" 367 | escape-string-regexp "^4.0.0" 368 | find-up "^5.0.0" 369 | glob "^10.4.5" 370 | he "^1.2.0" 371 | js-yaml "^4.1.0" 372 | log-symbols "^4.1.0" 373 | minimatch "^5.1.6" 374 | ms "^2.1.3" 375 | serialize-javascript "^6.0.2" 376 | strip-json-comments "^3.1.1" 377 | supports-color "^8.1.1" 378 | workerpool "^6.5.1" 379 | yargs "^17.7.2" 380 | yargs-parser "^21.1.1" 381 | yargs-unparser "^2.0.0" 382 | 383 | ms@^2.1.3: 384 | version "2.1.3" 385 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 386 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 387 | 388 | normalize-path@^3.0.0, normalize-path@~3.0.0: 389 | version "3.0.0" 390 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 391 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 392 | 393 | p-limit@^3.0.2: 394 | version "3.1.0" 395 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 396 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 397 | dependencies: 398 | yocto-queue "^0.1.0" 399 | 400 | p-locate@^5.0.0: 401 | version "5.0.0" 402 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 403 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 404 | dependencies: 405 | p-limit "^3.0.2" 406 | 407 | package-json-from-dist@^1.0.0: 408 | version "1.0.1" 409 | resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" 410 | integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== 411 | 412 | path-exists@^4.0.0: 413 | version "4.0.0" 414 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 415 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 416 | 417 | path-key@^3.1.0: 418 | version "3.1.1" 419 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 420 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 421 | 422 | path-scurry@^1.11.1: 423 | version "1.11.1" 424 | resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" 425 | integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== 426 | dependencies: 427 | lru-cache "^10.2.0" 428 | minipass "^5.0.0 || ^6.0.2 || ^7.0.0" 429 | 430 | picomatch@^2.0.4, picomatch@^2.2.1: 431 | version "2.3.1" 432 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 433 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 434 | 435 | randombytes@^2.1.0: 436 | version "2.1.0" 437 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 438 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 439 | dependencies: 440 | safe-buffer "^5.1.0" 441 | 442 | readdirp@~3.6.0: 443 | version "3.6.0" 444 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 445 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 446 | dependencies: 447 | picomatch "^2.2.1" 448 | 449 | require-directory@^2.1.1: 450 | version "2.1.1" 451 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 452 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 453 | 454 | safe-buffer@^5.1.0: 455 | version "5.2.1" 456 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 457 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 458 | 459 | serialize-javascript@^6.0.2: 460 | version "6.0.2" 461 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" 462 | integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== 463 | dependencies: 464 | randombytes "^2.1.0" 465 | 466 | shebang-command@^2.0.0: 467 | version "2.0.0" 468 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 469 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 470 | dependencies: 471 | shebang-regex "^3.0.0" 472 | 473 | shebang-regex@^3.0.0: 474 | version "3.0.0" 475 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 476 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 477 | 478 | signal-exit@^4.0.1: 479 | version "4.1.0" 480 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" 481 | integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== 482 | 483 | "string-width-cjs@npm:string-width@^4.2.0": 484 | version "4.2.3" 485 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 486 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 487 | dependencies: 488 | emoji-regex "^8.0.0" 489 | is-fullwidth-code-point "^3.0.0" 490 | strip-ansi "^6.0.1" 491 | 492 | string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 493 | version "4.2.3" 494 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 495 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 496 | dependencies: 497 | emoji-regex "^8.0.0" 498 | is-fullwidth-code-point "^3.0.0" 499 | strip-ansi "^6.0.1" 500 | 501 | string-width@^5.0.1, string-width@^5.1.2: 502 | version "5.1.2" 503 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" 504 | integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== 505 | dependencies: 506 | eastasianwidth "^0.2.0" 507 | emoji-regex "^9.2.2" 508 | strip-ansi "^7.0.1" 509 | 510 | "strip-ansi-cjs@npm:strip-ansi@^6.0.1": 511 | version "6.0.1" 512 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 513 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 514 | dependencies: 515 | ansi-regex "^5.0.1" 516 | 517 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 518 | version "6.0.1" 519 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 520 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 521 | dependencies: 522 | ansi-regex "^5.0.1" 523 | 524 | strip-ansi@^7.0.1: 525 | version "7.1.0" 526 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" 527 | integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== 528 | dependencies: 529 | ansi-regex "^6.0.1" 530 | 531 | strip-json-comments@^3.1.1: 532 | version "3.1.1" 533 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 534 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 535 | 536 | supports-color@^7.1.0: 537 | version "7.2.0" 538 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 539 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 540 | dependencies: 541 | has-flag "^4.0.0" 542 | 543 | supports-color@^8.1.1: 544 | version "8.1.1" 545 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 546 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 547 | dependencies: 548 | has-flag "^4.0.0" 549 | 550 | to-regex-range@^5.0.1: 551 | version "5.0.1" 552 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 553 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 554 | dependencies: 555 | is-number "^7.0.0" 556 | 557 | which@^2.0.1: 558 | version "2.0.2" 559 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 560 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 561 | dependencies: 562 | isexe "^2.0.0" 563 | 564 | workerpool@^6.5.1: 565 | version "6.5.1" 566 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" 567 | integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== 568 | 569 | "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": 570 | version "7.0.0" 571 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 572 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 573 | dependencies: 574 | ansi-styles "^4.0.0" 575 | string-width "^4.1.0" 576 | strip-ansi "^6.0.0" 577 | 578 | wrap-ansi@^7.0.0: 579 | version "7.0.0" 580 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 581 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 582 | dependencies: 583 | ansi-styles "^4.0.0" 584 | string-width "^4.1.0" 585 | strip-ansi "^6.0.0" 586 | 587 | wrap-ansi@^8.1.0: 588 | version "8.1.0" 589 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" 590 | integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== 591 | dependencies: 592 | ansi-styles "^6.1.0" 593 | string-width "^5.0.1" 594 | strip-ansi "^7.0.1" 595 | 596 | y18n@^5.0.5: 597 | version "5.0.8" 598 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 599 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 600 | 601 | yargs-parser@^21.1.1: 602 | version "21.1.1" 603 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" 604 | integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 605 | 606 | yargs-unparser@^2.0.0: 607 | version "2.0.0" 608 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 609 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 610 | dependencies: 611 | camelcase "^6.0.0" 612 | decamelize "^4.0.0" 613 | flat "^5.0.2" 614 | is-plain-obj "^2.1.0" 615 | 616 | yargs@^17.7.2: 617 | version "17.7.2" 618 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" 619 | integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== 620 | dependencies: 621 | cliui "^8.0.1" 622 | escalade "^3.1.1" 623 | get-caller-file "^2.0.5" 624 | require-directory "^2.1.1" 625 | string-width "^4.2.3" 626 | y18n "^5.0.5" 627 | yargs-parser "^21.1.1" 628 | 629 | yocto-queue@^0.1.0: 630 | version "0.1.0" 631 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 632 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 633 | --------------------------------------------------------------------------------