@danielhaim/titlecaser 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ /*!
2
+ * @danielhaim/titlecaser - v1.7.2 - 2025-04-09
3
+ * https://github.com/danielhaim1/titlecaser.git
4
+ * Copyright (c) 2025 Daniel Haim, Licensed Apache-2.0
5
+ */(()=>{"use strict";var e={16:e=>{e.exports=JSON.parse('{"ranks":["Pvt.","Cpl.","Sgt.","SSgt.","GySgt.","MSgt.","1stSgt.","SgtMaj.","WO1","CW2","CW3","CW4","CW5","2ndLt.","1stLt.","Capt.","Maj.","LtCol.","Col.","BrigGen.","MajGen.","LtGen.","Gen.","Adm.","Cpt.","Cmdr.","Lt.","Ens."],"branches":["Army","Navy","Air Force","Marines","Coast Guard","Space Force","National Guard","People\'s Liberation Army","Russian Ground Forces","JASDF","ROKA"],"units":["Platoon","Company","Battalion","Regiment","Brigade","Division","Corps","Squad","Fleet","Wing","Squadron","Task Force","Eurocorps","Battlegroup","Rapid Reaction Force","Joint Expeditionary Force"],"acronyms":["DoD","NATO","EUFOR","EUTM","OSCE","UNSC","JAG","ROTC","AFB","MOS","AWOL","MRE","IED","FOB","TOC","CONUS","OCONUS","UCMJ","USMC","USAF","USN","USA","SOCOM","CENTCOM","NORAD","PACOM","JTF","RPG","SAM","ASEAN","AUKUS","QUAD","CSTO","SCO","CFSP","EEAS","EUMS","Frontex","GRU","FSB","PLAN","PLAAF"],"equipment":["Humvee","MRAP","Apache","Black Hawk","Bradley","Abrams","F-16","F-22","F-35","B-2","B-52","C-130","LCAC","MRE"],"operations":["Operation Desert Storm","Operation Enduring Freedom","Operation Iraqi Freedom","Operation Inherent Resolve"],"treaties":["Lisbon Treaty","Maastricht Treaty","Treaty of Rome","Nice Treaty","Schengen Agreement"],"regions":["South China Sea","Taiwan Strait","Korean DMZ","Kashmir","Kuril Islands","Senkaku Islands"],"alliances":["NATO","AUKUS","QUAD","ASEAN","SCO","CSTO","Five Eyes"]}')},157:e=>{e.exports=JSON.parse('{"countries":["Afghanistan","Albania","Algeria","Andorra","Angola","Antigua and Barbuda","Argentina","Armenia","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bhutan","Bolivia","Bosnia and Herzegovina","Botswana","Brazil","Brunei","Bulgaria","Burkina Faso","Burundi","Cabo Verde","Cambodia","Cameroon","Canada","Central African Republic","Chad","Chile","China","Colombia","Comoros","Congo","Costa Rica","Cote d\'Ivoire","Croatia","Cuba","Cyprus","Czech Republic","Denmark","Djibouti","Dominica","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea","Estonia","Eswatini","Ethiopia","Fiji","Finland","France","Gabon","Gambia","Georgia","Germany","Ghana","Greece","Grenada","Guatemala","Guinea","Guinea-Bissau","Guyana","Haiti","Honduras","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Israel","Italy","Jamaica","Japan","Jordan","Kazakhstan","Kenya","Kiribati","Korea","Kosovo","Kuwait","Kyrgyzstan","Laos","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands","Mauritania","Mauritius","Mexico","Micronesia","Moldova","Monaco","Mongolia","Montenegro","Morocco","Mozambique","Myanmar","Namibia","Nauru","Nepal","Netherlands","New Zealand","Nicaragua","Niger","Nigeria","North Macedonia","Norway","Oman","Pakistan","Palau","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Qatar","Romania","Russia","Rwanda","Saint Kitts and Nevis","Saint Lucia","Saint Vincent and the Grenadines","Samoa","San Marino","Sao Tome and Principe","Saudi Arabia","Senegal","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","Solomon Islands","Somalia","South Africa","South Korea","South Sudan","Spain","Sri Lanka","Sudan","Suriname","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor-Leste","Togo","Tonga","Trinidad and Tobago","Tunisia","Turkey","Turkmenistan","Tuvalu","Uganda","Ukraine","United Arab Emirates","United Kingdom","United States","Uruguay","Uzbekistan","Vanuatu","Vatican City","Venezuela","Vietnam","Yemen","Zambia","Zimbabwe"],"alpha2":["UK"],"alpha3":["USA"]}')},223:e=>{e.exports=JSON.parse('{"sports":["FIFA","UEFA","NBA","NFL","MLB","NHL","NASCAR","IOC","FIBA","ATP","WTA","PGA","LPGA","FIA","WADA","ITF","AFL","NRL","ICC","IRB","IHF","FIVB","FINA","UCI","IAAF","ISU","WSF","BWF","WBC","WBO","IBF","IBO","UEFA","CONMEBOL","CONCACAF","CAF","AFC","OFC","CPL","MLS","LaLiga","Bundesliga","Ligue1","Eredivisie","JLeague","KLeague","Ryder Cup","Davis Cup","FedCup","XGames","Olympics","Paralympics","Dakar"],"apple":["Apple","AirDrop","AirPlay","AirPods","AirTags","FinalCut","GarageBand","iBooks","iCloud","iLife","iMac","iMessage","iMovie","iPhoto","iWatch","iWork","LogicPro","macOS","ProTools","QuickTime","iPhone","iPad","iPod","iOS","macOS","tvOS","watchOS"],"corporate":["Deloitte","Devoteam","ExxonMobil","GE","Boeing","Shell","Chevron"],"tech":["Bing","Salesforce","Asus","Acer","Lenovo","Huawei","Xiaomi","Epson","Nvidia","AMD","Qualcomm","Logitech","Panasonic","Sharp","Toshiba","Philips","Fujitsu","Netgear","Lexmark","Razer","SAP","Symantec","Kaspersky","Avast","McAfee","Siemens","Canon","Nikon","Garmin","GoPro","Oculus","Zoom","Slack","Trello","WeChat","Alibaba","Tencent","Baidu","Roku","Fitbit","Dropbox","Reddit","TikTok","Slack","Trello","Uber","Zoom","Reddit","Quora","JIRA","ZoomInfo","HubSpot","Mailchimp","WeChat","Dropbox","Uber","Telegram","Discord","StackOverflow","Quora","Reddit","ZoomInfo","Airbnb","LinkedIn","Snapchat","GitHub","GitLab","Nginx","OpenSSL","Webpack","Unity3D","Figma","JIRA","Kubernetes","TensorFlow","NPM","WooCommerce","WordPress","Slack","Trello","Uber","Zoom","Reddit","Quora","WeChat","Dropbox","Telegram","Discord","StackOverflow","Airbnb","LinkedIn","Snapchat","JIRA","MobX","VMware","Google"],"business":["Visa","Mastercard","Citibank","JPMorgan","Barclay","AMEX","Citigroup","PayPal","BNP","HSBC","Santander","UBS","Allianz","Prudential","Vanguard","BlackRock","CapitalOne","TD","Robinhood","MoneyGram","SoFi","Experian","Equifax","TransUnion","MasterCard","Blockchain","Coinbase","Binance","Kraken","Ethereum","Bitcoin"],"automotive":["BMW","Ford","Mercedes","Nissan","Tesla","Toyota","Audi","Chevrolet","Chrysler","Dodge","Ferrari","Fiat","Honda","Hyundai","Infiniti","Jaguar","Jeep","Kia","Lamborghini","LandRover","Lexus","Maserati","Mazda","McLaren","Mitsubishi","Peugeot","Porsche","Renault","RollsRoyce","Saab","Subaru","Suzuki","Volkswagen","Volvo","Alfa Romeo","Bentley","Bugatti","Cadillac","Citroen","Daewoo","Daihatsu","Datsun","DeLorean","Fiat Chrysler","GMC","Holden","Hummer","Isuzu","Koenigsegg","Lancia","Lincoln","Lotus","Mahindra","Suzuki","Opel","Pagani","Perodua","Proton","Rover","Scania","Skoda","SsangYong","Tata","Vauxhall","VinFast","Yugo","Zenvo"],"media":["Disney","Netflix","YouTube","Instagram","Twitter","Facebook","Spotify","Hulu","TikTok","Snapchat","Vimeo","Twitch","Reddit","HBO","Showtime","Starz","Crunchyroll","Audible","Pixar","DreamWorks","MGM","Lionsgate","Miramax","EpicGames","Ubisoft","Blizzard","Capcom","Bethesda","Sega","Roku","Fandango","IMDb","Shazam","SoundCloud","Vevo","Vine","Zynga","Tidal","Quibi","Crave","Gaia","PlutoTV","Vudu","Kanopy","Mubi","BritBox"],"telecom":["Verizon","Sprint","Nokia","Ericsson","Vodafone","AT&T","Huawei","Xiaomi","Orange","NTT","T-Mobile","Telefonica","Airtel","Telstra","Rogers","Bell","MTN","ZTE","Qualcomm","Motorola","Telus","BT","Swisscom","SoftBank","KDDI"],"entertainment":["Disney","Netflix","YouTube","Instagram","Twitter","Facebook","Spotify","Hulu","TikTok","Snapchat","Vimeo","Twitch","Reddit","Pandora","HBO","Showtime","Starz","Paramount","Peacock","Crunchyroll","Audible","Pixar","DreamWorks","MGM","Lionsgate","Miramax","EpicGames","Ubisoft","Blizzard","Capcom","Bethesda","Sega","Roku","Fandango","IMDb","Shazam","SoundCloud","Vevo","Zynga","Tidal","Oscars"],"retail":["Amazon","eBay","IKEA","Walmart","Zara","Target","Costco","Sephora","Nordstrom","Tesco","Asda","Aldi","Lidl","Carrefour","Uniqlo","H&M","Gap","Cabela’s","BassPro","REI","Ulta","Saks","JCPenney","Belk","Argos","Safeway","Kroger","Publix","HomeDepot","Woolworths","Staples","OfficeMax","B&H","Newegg","MicroCenter","Frys","Monoprix","Waitrose","Morrisons","Ocado","Flipkart","Rakuten","Alibaba","JD","Taobao","Tmall","Guomei","Suning"],"food":["Nestle","Pepsi","Coca-Cola","PepsiCo","Starbucks","KFC","BurgerKing","PizzaHut","TacoBell","Kroger","Costco","Woolworths","Carrefour","Tesco","Aldi","Lidl","Walmart","Safeway","Publix","WholeFoods","RedBull","Monster","Nespresso","Heineken","Budweiser","Corona","Guinness","GeneralMills","Unilever","Kraft","Heinz","Danone","Campbell","Tyson","Conagra","Mondelez","Suntory","Diageo","Pernod"],"pharmaceutical":["Pfizer","Moderna","Gilead","Merck","Novartis","Sanofi","Roche","AbbVie","Amgen","Bayer","Biogen","BristolMyers","Celgene","GSK","Janssen","Lilly","Medtronic","Mylan","NovoNordisk","Regeneron","Teva","AstraZeneca","Boehringer","Daiichi","Eisai","Genentech","Grifols","Ipsen","Mundipharma","Otsuka","Purdue","Sandoz","Servier","SunPharma","Takeda","UCB","Viatris","Wockhardt","Zydus","Alkem"],"nonprofit":["NGO","NPO","NGOs","NPOs","UN","UNESCO","UNICEF","UNHCR","UNODC","UNDP","UNFPA","UNEP","UNRWA"]}')},279:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.TitleCaserUtils=void 0;var i=r(416);function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,i)}return r}function s(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){o(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function o(e,t,r){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var i=r.call(e,t||"default");if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}class n{static validateOption(e,t){if(!Array.isArray(t))throw new TypeError(`Invalid option: ${e} must be an array`);if(!t.every((e=>"string"==typeof e)))throw new TypeError(`Invalid option: ${e} must be an array of strings`)}static validateOptions(e){for(const t of Object.keys(e))if("style"!==t)if("wordReplacementsList"!==t){if(!i.titleCaseDefaultOptionsList.hasOwnProperty(t))throw new TypeError(`Invalid option: ${t}`);this.TitleCaseValidator.validateOption(t,e[t])}else{if(!Array.isArray(e.wordReplacementsList))throw new TypeError(`Invalid option: ${t} must be an array`);for(const r of e.wordReplacementsList)if("string"!=typeof r)throw new TypeError(`Invalid option: ${t} must contain only strings`)}else{if("string"!=typeof e.style)throw new TypeError(`Invalid option: ${t} must be a string`);if(!i.allowedTitleCaseStylesList.includes(e.style))throw new TypeError(`Invalid option: ${t} must be a string`)}}static getTitleCaseOptions(e={},t=[]){const r=JSON.stringify({options:e,lowercaseWords:t});if(n.titleCaseOptionsCache.has(r))return n.titleCaseOptionsCache.get(r);const a=s(s(s({},i.titleCaseDefaultOptionsList[e.style||"ap"]),e),{},{smartQuotes:!!e.hasOwnProperty("smartQuotes")&&e.smartQuotes}),o=a.articlesList.concat(t).filter(((e,t,r)=>r.indexOf(e)===t)),l=a.shortConjunctionsList.concat(t).filter(((e,t,r)=>r.indexOf(e)===t)),c=a.shortPrepositionsList.concat(t).filter(((e,t,r)=>r.indexOf(e)===t)),u=[...(a.replaceTerms||[]).map((([e,t])=>[e.toLowerCase(),t])),...i.wordReplacementsList],p={articlesList:o,shortConjunctionsList:l,shortPrepositionsList:c,neverCapitalizedList:[...a.neverCapitalizedList],replaceTerms:u,smartQuotes:a.smartQuotes};return n.titleCaseOptionsCache.set(r,p),p}static capitalizeFirstLetter(e){return e.charAt(0).toUpperCase()+e.slice(1)}static isShortConjunction(e,t){const r=[...n.getTitleCaseOptions({style:t}).shortConjunctionsList],i=e.toLowerCase();return r.includes(i)}static isArticle(e,t){return n.getTitleCaseOptions({style:t}).articlesList.includes(e.toLowerCase())}static isShortPreposition(e,t){const{shortPrepositionsList:r}=n.getTitleCaseOptions({style:t});return r.includes(e.toLowerCase())}static isNeverCapitalized(e,t){const r=`${t}_${e.toLowerCase()}`;if(n.isNeverCapitalizedCache.has(r))return n.isNeverCapitalizedCache.get(r);const{neverCapitalizedList:i}=n.getTitleCaseOptions({style:t}),a=i.includes(e.toLowerCase());return n.isNeverCapitalizedCache.set(r,a),a}static isShortWord(e,t){if("string"!=typeof e)throw new TypeError(`Invalid input: word must be a string. Received ${typeof e}.`);if(!i.allowedTitleCaseStylesList.includes(t))throw new Error(`Invalid option: style must be one of ${i.allowedTitleCaseStylesList.join(", ")}.`);return n.isShortConjunction(e,t)||n.isArticle(e,t)||n.isShortPreposition(e,t)||n.isNeverCapitalized(e,t)}static hasNumbers(e){return/\d/.test(e)}static hasUppercaseMultiple(e){let t=0;for(let r=0;r<e.length&&t<2;r++)/[A-Z]/.test(e[r])&&t++;return t>=2}static hasUppercaseIntentional(e){if(e.length<=4)return/[A-Z]/.test(e.slice(1));const t=/[A-Z]/.test(e.slice(1)),r=/[a-z]/.test(e.slice(1));return t&&r}static isEntirelyUppercase(e){return e===e.toUpperCase()&&e!==e.toLowerCase()&&e.length>1}static isRegionalAcronym(e){if("string"!=typeof e)throw new TypeError("Invalid input: word must be a string.");if(e.length<2)return!1;const t=e.toLowerCase();return i.regionalAcronymList.includes(t)}static isRegionalAcronymNoDot(e,t,r=null){if("string"!=typeof e||"string"!=typeof t)return!1;const a=e.toLowerCase().replace(/[^\w\s]/g,""),s=t.toLowerCase().replace(/[^\w\s]/g,"");return!!(r&&i.regionalAcronymList.includes(a)&&["the"].includes(r.toLowerCase()))||i.regionalAcronymList.includes(a)&&i.directFollowingIndicatorsRegionalAcronym.includes(s)}static isFinalWordRegionalAcronym(e,t,r=null){if("string"!=typeof e||"string"!=typeof t)return!1;const a=e.toLowerCase().replace(/[^\w]/g,""),s=t.toLowerCase().replace(/[^\w]/g,""),o="string"==typeof r?r.toLowerCase().replace(/[^\w]/g,""):null;return!!i.regionalAcronymList.includes(a)&&(!!i.regionalAcronymPrecedingWords.includes(s)||!("the"!==s||!o||!i.regionalAcronymPrecedingWords.includes(o)))}static normalizeRegionalAcronym(e){if("string"!=typeof e)throw new TypeError("Invalid input: word must be a string.");return e.toUpperCase()}static normalizeAcronymKey(e){return e.toLowerCase().replace(/\./g,"")}static normalizeCasingForWordByStyle(e,t){if(!e||!t||!i.titleCaseDefaultOptionsList[t])return!1;const r=e.toLowerCase(),{shortConjunctionsList:a,articlesList:s,shortPrepositionsList:o,neverCapitalizedList:n}=i.titleCaseDefaultOptionsList[t];return!![...a,...s,...o,...n].includes(r)&&e}static hasSuffix(e){return e.length>2&&e.endsWith("'s")}static hasApostrophe(e){return-1!==e.indexOf("'")}static hasHyphen(e){return-1!==e.indexOf("-")||-1!==e.indexOf("–")||-1!==e.indexOf("—")}static hasRomanNumeral(e){if("string"!=typeof e||""===e)throw new TypeError("Invalid input: word must be a non-empty string.");const t=e.includes("'")?e.split("'"):[e],r=/^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/i;return t.every((e=>r.test(e)))}static hasHyphenRomanNumeral(e){if("string"!=typeof e||""===e)throw new TypeError("Invalid input: word must be a non-empty string.");const t=e.split("-");for(let e=0;e<t.length;e++)if(!n.hasRomanNumeral(t[e]))return!1;return!0}static hasHtmlBreak(e){return"nl2br"===e}static hasUnicodeSymbols(e){return/[^\x00-\x7F\u00A0-\u00FF\u0100-\u017F\u0180-\u024F\u0250-\u02AF\u02B0-\u02FF\u0300-\u036F\u0370-\u03FF\u0400-\u04FF\u0500-\u052F\u0530-\u058F\u0590-\u05FF\u0600-\u06FF\u0700-\u074F\u0750-\u077F\u0780-\u07BF\u07C0-\u07FF\u0800-\u083F\u0840-\u085F\u0860-\u087F\u0880-\u08AF\u08B0-\u08FF\u0900-\u097F\u0980-\u09FF\u0A00-\u0A7F\u0A80-\u0AFF\u0B00-\u0B7F\u0B80-\u0BFF\u0C00-\u0C7F\u0C80-\u0CFF\u0D00-\u0D7F\u0D80-\u0DFF\u0E00-\u0E7F\u0E80-\u0EFF\u0F00-\u0FFF]/.test(e)}static hasCurrencySymbols(e){return/[^\x00-\x7F\u00A0-\u00FF\u20AC\u20A0-\u20B9\u20BD\u20A1-\u20A2\u00A3-\u00A5\u058F\u060B\u09F2-\u09F3\u0AF1\u0BF9\u0E3F\u17DB\u20A6\u20A8\u20B1\u2113\u20AA-\u20AB\u20AA\u20AC-\u20AD\u20B9]/.test(e)}static isWordAmpersand(e){return/&amp;|&/.test(e)}static startsWithSymbol(e){if("string"!=typeof e)throw new Error(`Parameter 'word' must be a string. Received '${typeof e}' instead.`);if(0===e.length)return!1;const t=e.charAt(0);return"#"===t||"@"===t||"."===t}static escapeSpecialCharacters(e){return e.replace(/[&<>"']/g,(function(e){switch(e){case"&":return"&amp;";case"<":return"&lt;";case">":return"&gt;";case'"':return"&quot;";case"'":return"&#x27;";default:return e}}))}static unescapeSpecialCharacters(e){return e.replace(/&amp;|&lt;|&gt;|&quot;|&#x27;/g,(function(e){switch(e){case"&amp;":return"&";case"&lt;":return"<";case"&gt;":return">";case"&quot;":return'"';case"&#x27;":return"'";default:return e}}))}static endsWithSymbol(e,t=[".",",",";",":","?","!"]){if("string"!=typeof e||!Array.isArray(t))throw new Error("Invalid arguments");return t.some((t=>e.endsWith(t)))||t.includes(e.slice(-2))}static isWordIgnored(e,t=i.ignoredWordList){if(!Array.isArray(t))throw new TypeError("Invalid input: ignoredWords must be an array.");if("string"!=typeof e||""===e.trim())throw new TypeError("Invalid input: word must be a non-empty string.");let r;return r=e.toLowerCase().trim(),t.includes(r)}static isWordInArray(e,t){return!!Array.isArray(t)&&t.some((t=>t.toLowerCase()===e.toLowerCase()))}static convertQuotesToCurly(e){const t={"'":["‘","’"],'"':["“","”"]};let r="";for(let i=0;i<e.length;i++){const a=e[i],s=t[a];if(s){const t=e[i-1],a=e[i+1],o=!t||" "===t||"\n"===t?s[0]:s[1];r+=o,o===s[1]&&/[.,;!?()\[\]{}:]/.test(a)&&(r+=a,i++)}else r+=a}return r}static replaceTerm(e,t){if("string"!=typeof e||""===e)throw new TypeError("Invalid input: word must be a non-empty string.");if(!t||"object"!=typeof t)throw new TypeError("Invalid input: replaceTermObj must be a non-null object.");let r;if(r=e.toLowerCase(),t.hasOwnProperty(r))return t[r];if(t.hasOwnProperty(e))return t[e];const i=e.toUpperCase();return t.hasOwnProperty(i)?t[i]:e}static isElidedWord(e){if("string"!=typeof e||""===e.trim())throw new TypeError("Invalid input: word must be a non-empty string.");const t=new Set(["o’","fo’","ne’er","e’er","’tis","’twas","’n’"]),r=e.trim().toLowerCase().replace(/'/g,"’");for(const e of t)if(r.startsWith(e))return!0;return!1}static normalizeElidedWord(e){if("string"!=typeof e||""===e.trim())throw new TypeError("Invalid input: word must be a non-empty string.");const t=new Set(["o’","fo’","ne’er","e’er","’tis","’twas","’n’"]),r=e.trim(),i=r.replace(/'/g,"’").toLowerCase();for(const e of t)if(i.startsWith(e)){const t=e.length,i=r.slice(t);return e.charAt(0).toUpperCase()+e.slice(1)+(i.length>0?i.charAt(0).toUpperCase()+i.slice(1):"")}return!1}static correctSuffix(e,t){if("string"!=typeof e||""===e)throw new TypeError("Invalid input: word must be a non-empty string.");if(!t||!Array.isArray(t)||t.some((e=>"string"!=typeof e)))throw new TypeError("Invalid input: correctTerms must be an array of strings.");if(/'s$/i.test(e)){const r=e.slice(0,-2),i=t.findIndex((e=>e.toLowerCase()===r.toLowerCase()));if(i>=0){return`${t[i]}'s`}return`${r.charAt(0).toUpperCase()+r.slice(1)}'s`}return e}static correctTerm(e,t,r=/[-']/){if("string"!=typeof e||""===e)throw new TypeError("Invalid input: word must be a non-empty string.");if(!t||!Array.isArray(t))throw new TypeError("Invalid input: correctTerms must be an array.");if(!("string"==typeof r||Array.isArray(r)||r instanceof RegExp))throw new TypeError("Invalid input: delimiters must be a string, an array of strings, or a regular expression.");"string"==typeof r?r=new RegExp(`[${r}]`):Array.isArray(r)&&(r=new RegExp(`[${r.join("")}]`));const i=e.split(r),a=i.length;for(let e=0;e<a;e++){const r=i[e].toLowerCase(),a=t.findIndex((e=>e.toLowerCase()===r));i[e]=a>=0?t[a]:i[e].charAt(0).toUpperCase()+i[e].slice(1).toLowerCase()}let s=r.source.charAt(0);return e.includes("-")?s="-":e.includes("'")&&(s="'"),i.join(s)}static correctTermHyphenated(e,t){const r=e.split("-"),a=e=>e.charAt(0).toUpperCase()+e.slice(1),s=e=>e.charAt(0)+e.slice(1).toLowerCase(),o={ap:(e,t)=>0===t?a(e):s(e),chicago:a,apa:(e,r,i)=>n.isShortWord(e,t)&&r>0&&r<i-1?e.toLowerCase():a(e),nyt:(e,t)=>0===t?a(e):s(e),wikipedia:(e,t)=>0===t?a(e):s(e)},l=o[t]||s,c=r.map(((e,t)=>{let a=e;if(/^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})'s$/i.test(e)){return a.toUpperCase().replace(/'S$/,"'s")}const s=/^(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/i;if(s.test(e))return e.toUpperCase();if(e.includes("'")){const i=e.split("'");return i.every((e=>s.test(e)))?(a=i.map((e=>e.toUpperCase())).join("'"),a):l(a,t,r.length)}const o=e.toLowerCase(),n=i.correctTitleCasingList.findIndex((e=>e.toLowerCase()===o));if(n>=0)a=i.correctTitleCasingList[n];else if(o.endsWith("'s")){const e=o.substring(0,o.length-2),t=i.correctTitleCasingList.findIndex((t=>t.toLowerCase()===e));t>=0&&(a=`${i.correctTitleCasingList[t]}'s`)}return l(a,t,r.length)}));return c.join("-")}}t.TitleCaserUtils=n,o(n,"TitleCaseValidator",void 0),o(n,"titleCaseOptionsCache",new Map),o(n,"isNeverCapitalizedCache",new Map)},321:e=>{e.exports=JSON.parse('{"advertising":["AdWords","AdSense","AdMob","DoubleClick","SpotX"],"digitalMarketing":["DSP","SSP","CTR","CPA","CPC","CPL","CPM","CRM","SEO","SEM","SMM","A/B","CTOR","KPI","SERP","FAQ","PR"],"general":["B2B","B2C","CMO","USP","PWA","SMO","T&C","TOS","PP","UI","UX","UI/UX"],"blockchain":["PoE","PoW","PoC"],"accessibility":["A11Y"]}')},388:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.TitleCaser=void 0;var i=r(416),a=r(279);t.TitleCaser=class{constructor(e={}){this.options=e,this.debug=e.debug||!1,this.wordReplacementsList=i.wordReplacementsList,this.correctPhraseCasingList=i.correctPhraseCasingList}logWarning(e){this.debug&&console.warn(`Warning: ${e}`)}toTitleCase(e){try{if(0===e.trim().length)throw new TypeError("Invalid input: input must not be empty.");if("string"!=typeof e)throw new TypeError("Invalid input: input must be a string.");if(void 0!==this.options&&"object"!=typeof this.options)throw new TypeError("Invalid options: options must be an object.");const{style:t="ap",neverCapitalize:r=[],replaceTermList:s=this.wordReplacementsList,smartQuotes:o=!1}=this.options,n=["nl2br",...r],{articlesList:l,shortConjunctionsList:c,shortPrepositionsList:u,neverCapitalizedList:p,replaceTerms:d,smartQuotes:m}=a.TitleCaserUtils.getTitleCaseOptions(this.options,i.commonShortWords,i.wordReplacementsList),g=s.map((e=>Object.keys(e)[0].toLowerCase())),C=Object.fromEntries(s.map((e=>[Object.keys(e)[0].toLowerCase(),Object.values(e)[0]])));this.logWarning(`replaceTermsArray: ${g}`),this.logWarning(`this.wordReplacementsList: ${this.wordReplacementsList}`);let h=e.trim();h=h.replace(/<\s*br\s*\/?\s*>/gi," nl2br "),h=h.replace(/ {2,}/g,(e=>e.slice(0,1)));a.TitleCaserUtils.isEntirelyUppercase(h.replace(/[^a-zA-Z]/g,""))&&(this.logWarning("Input string is entirely uppercase, normalizing to lowercase first"),h=h.toLowerCase());const y=h.split(" ");h=y.map(((e,r)=>{switch(!0){case a.TitleCaserUtils.isWordAmpersand(e):case a.TitleCaserUtils.hasHtmlBreak(e):case a.TitleCaserUtils.isWordIgnored(e,n):return e;case g.includes(e.toLowerCase()):return C[e.toLowerCase()];case a.TitleCaserUtils.isWordInArray(e,i.correctTitleCasingList):return a.TitleCaserUtils.correctTerm(e,i.correctTitleCasingList);case a.TitleCaserUtils.isElidedWord(e):return a.TitleCaserUtils.normalizeElidedWord(e);case a.TitleCaserUtils.hasHyphen(e):const s=e.replace(/[\W_]+$/,""),o=e.slice(s.length),l=s.split("-"),c=l.map((e=>{const t=e.toLowerCase();return g.includes(t)?C[t]:e})),u=!c.every(((e,t)=>e===l[t]))?c.join("-"):a.TitleCaserUtils.correctTermHyphenated(e,t);return u.endsWith(o)?u:u+o;case a.TitleCaserUtils.hasSuffix(e,t):return a.TitleCaserUtils.correctSuffix(e,i.correctTitleCasingList);case a.TitleCaserUtils.hasUppercaseIntentional(e):return e;case a.TitleCaserUtils.isShortWord(e,t)&&0!==r:if(r>0&&a.TitleCaserUtils.endsWithSymbol(y[r-1],[":","?","!","."]))return e.charAt(0).toUpperCase()+e.slice(1);return a.TitleCaserUtils.normalizeCasingForWordByStyle(e,t);case a.TitleCaserUtils.endsWithSymbol(e):this.logWarning(`Check if the word ends with a symbol: ${e}`);const p=e.split(/([.,\/#!$%\^&\*;:{}=\-_`~()?])/g);this.logWarning(`Splitting word at symbols, result: ${p}`);return p.map((e=>{if(this.logWarning(`Processing part: ${e}`),a.TitleCaserUtils.endsWithSymbol(e))return this.logWarning(`Part is a symbol: ${e}`),e;if(this.logWarning(`Part is a word: ${e}`),a.TitleCaserUtils.isWordInArray(e,i.correctTitleCasingList)){const t=a.TitleCaserUtils.correctTerm(e,i.correctTitleCasingList);return this.logWarning(`Word is in correctTitleCasingList, corrected term: ${t}`),t}if(g.includes(e)){const t=C[e];return this.logWarning(`Word is in replaceTermsArray, replacement: ${t}`),t}{const t=e.charAt(0).toUpperCase()+e.slice(1).toLowerCase();return this.logWarning(`Applying title casing to word: ${t}`),t}})).join("");case a.TitleCaserUtils.startsWithSymbol(e):return a.TitleCaserUtils.isWordInArray(e,i.correctTitleCasingList)?a.TitleCaserUtils.correctTerm(e):e;case a.TitleCaserUtils.hasRomanNumeral(e):return e.toUpperCase();case a.TitleCaserUtils.hasNumbers(e):return e;default:return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()}})).join(" "),h=h.replace(/nl2br/gi,"<br>"),o&&(h=a.TitleCaserUtils.convertQuotesToCurly(h));const f=h.split(" ");let S=f[0],w=f[1]||null;f[f.length-1];for(let e=0;e<f.length;e++){e>0&&f[e-1];let t=f[e];const r=e<f.length-1?f[e+1]:null,i=t.match(/[.,!?;:]+$/);let s="";i&&(s=i[0],t=t.replace(/[.,!?;:]+$/,"")),a.TitleCaserUtils.isRegionalAcronym(t)&&(t=a.TitleCaserUtils.normalizeRegionalAcronym(t)),a.TitleCaserUtils.isRegionalAcronymNoDot(t,r)&&(t=a.TitleCaserUtils.normalizeRegionalAcronym(t)),""!==s&&(t+=s)}h=f.join(" ");const A=h.split(" ");for(let e=1;e<A.length-1;e++){const t=A[e];A[e-1],A[e+1];t===t.toUpperCase()||a.TitleCaserUtils.hasUppercaseIntentional(t)||a.TitleCaserUtils.isWordInArray(t,i.commonShortWords)&&(A[e]=t.length<=3?t.toLowerCase():t)}h=A.join(" ");const L=h.split(" ");for(let e=0;e<L.length;e++){let t=L[e],r=L[e+1],i=L[e-1];null!==r&&a.TitleCaserUtils.isRegionalAcronymNoDot(t,r,i)&&(L[e]=t.toUpperCase())}let b=L[L.length-1],T=L[L.length-2],O=L[L.length-3];a.TitleCaserUtils.isRegionalAcronym(S)&&(console.log("firstWord is a regional acronym, proof: ",S),L[0]=S.toUpperCase()),a.TitleCaserUtils.isRegionalAcronymNoDot(S,w)&&(L[0]=S.toUpperCase()),a.TitleCaserUtils.isFinalWordRegionalAcronym(b,T,O)&&(L[L.length-1]=b.toUpperCase()),h=L.join(" ");for(const[e,t]of Object.entries(this.correctPhraseCasingList)){const r=new RegExp(e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"gi");h=h.replace(r,t)}return h}catch(e){throw new Error(e)}}setReplaceTerms(e){if(!Array.isArray(e))throw new TypeError("Invalid argument: setReplaceTerms must be an array of objects.");e.forEach((e=>{if(e&&"object"==typeof e){const[t,r]=Object.entries(e)[0],i=this.wordReplacementsList.findIndex((e=>e.hasOwnProperty(t)));-1!==i?this.wordReplacementsList[i][t]=r:this.wordReplacementsList.push({[t]:r})}else console.warn("Invalid entry in terms array:",e)})),this.options.wordReplacementsList=this.wordReplacementsList,this.logWarning(`Log the updated this.wordReplacementsList: ${this.wordReplacementsList}`)}addReplaceTerm(e,t){if("string"!=typeof e||"string"!=typeof t)throw new TypeError("Invalid argument: term and replacement must be strings.");const r=this.wordReplacementsList.findIndex((t=>Object.keys(t)[0]===e));-1!==r?this.wordReplacementsList[r][e]=t:this.wordReplacementsList.push({[e]:t}),this.options.wordReplacementsList=this.wordReplacementsList}removeReplaceTerm(e){if("string"!=typeof e)throw new TypeError("Invalid argument: term must be a string.");const t=this.wordReplacementsList.findIndex((t=>Object.keys(t)[0]===e));if(-1===t)throw new Error(`Term '${e}' not found in word replacements list.`);this.wordReplacementsList.splice(t,1),this.options.wordReplacementsList=this.wordReplacementsList,this.logWarning(`Log the updated this.wordReplacementsList: ${this.wordReplacementsList}`)}addExactPhraseReplacements(e){if(!Array.isArray(e))throw new TypeError("Invalid argument: newPhrases must be an array.");e.forEach((e=>{if("object"!=typeof e||Array.isArray(e)||1!==Object.keys(e).length){if("object"!=typeof e||Array.isArray(e))throw new TypeError("Invalid argument: Each item must be an object with a single key-value pair.");Object.entries(e).forEach((([e,t])=>{if("string"!=typeof e||"string"!=typeof t)throw new TypeError("Invalid argument: Each key-value pair must contain strings.");this.correctPhraseCasingList[e]=t}))}else{const t=Object.keys(e)[0],r=e[t];if("string"!=typeof t||"string"!=typeof r)throw new TypeError("Invalid argument: Each key-value pair must contain strings.");this.correctPhraseCasingList[t]=r}})),this.logWarning(`Log the this.correctPhraseCasingList: ${this.correctPhraseCasingList}`)}setStyle(e){if("string"!=typeof e)throw new TypeError("Invalid argument: style must be a string.");this.options.style=e}}},416:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.wordReplacementsList=t.titleCaseStylesList=t.titleCaseDefaultOptionsList=t.regionalAcronymPrecedingWords=t.regionalAcronymList=t.ignoredWordList=t.directFollowingIndicatorsRegionalAcronym=t.correctTitleCasingList=t.correctPhraseCasingList=t.commonShortWords=t.allowedTitleCaseStylesList=void 0;var i=d(r(223)),a=d(r(814)),s=d(r(661)),o=d(r(157)),n=d(r(321)),l=d(r(742)),c=d(r(501)),u=d(r(491)),p=d(r(16));function d(e){return e&&e.__esModule?e:{default:e}}const m=function(...e){const t=[];return e.forEach((e=>{Array.isArray(e)?e.forEach((e=>{Object.values(e).forEach((e=>{t.push(...e)}))})):"object"==typeof e&&Object.values(e).forEach((e=>{t.push(...e)}))})),[...new Set(t)]}(i.default,a.default,s.default,o.default,n.default,l.default,c.default,u.default,p.default),g=(t.correctTitleCasingList=m,t.commonShortWords=["the","in","to","within","towards","into","at","of","for","by","on","from","with","through","about","across","over","under","between"],t.wordReplacementsList=[{"a.k.a":"AKA"},{"a.s.a.p":"ASAP"},{"f.a.q":"FAQ"},{"f.a.q.s":"FAQs"},{FAQS:"FAQs"},{"f.y.i":"FYI"},{"d.i.y":"DIY"},{"t.b.d":"TBD"},{"back-end":"Backend"},{"front-end":"Frontend"},{"full-stack":"Fullstack"},{nodejs:"Node.js"},{nextjs:"Next.js"},{nuxtjs:"Nuxt.js"},{reactjs:"React"},{"react.js":"React"},{"cyber-security":"Cybersecurity"}],t.titleCaseStylesList=Object.freeze({AP:"ap",APA:"apa",BRITISH:"british",CHICAGO:"chicago",NYT:"nyt",WIKIPEDIA:"wikipedia"}));t.allowedTitleCaseStylesList=Object.values(g),t.titleCaseDefaultOptionsList=Object.freeze({ap:{shortConjunctionsList:["and","but","or","for","nor","yet","so"],articlesList:["a","an","the"],shortPrepositionsList:["as","at","by","in","into","of","off","on","onto","out","over","to","up","via","with","from","under","upon","among"],neverCapitalizedList:[]},apa:{shortConjunctionsList:["and","but","by","for","in","nor","of","on","or","so","to","yet"],articlesList:["a","an","the"],shortPrepositionsList:["about","above","across","after","against","along","among","around","as","at","before","behind","below","beneath","beside","between","beyond","by","despite","down","during","except","for","from","in","inside","into","like","near","of","off","on","onto","out","outside","over","past","since","through","throughout","till","to","toward","under","underneath","until","up","upon","via","with","within","without"],neverCapitalizedList:[]},british:{shortConjunctionsList:["and","but","or","for","nor","yet","so"],articlesList:["a","an","the"],shortPrepositionsList:["as","at","by","in","into","of","off","on","onto","out","over","to","up","via","with","from","under","upon"],neverCapitalizedList:[]},chicago:{shortConjunctionsList:["and","but","or","for","nor","yet","so"],articlesList:["a","an","the"],shortPrepositionsList:["as","at","by","in","into","of","off","on","onto","out","over","to","up","via","with","from","under","upon"],neverCapitalizedList:["etc."]},nyt:{shortConjunctionsList:["and","but","or","for","nor","yet","so"],articlesList:["a","an","the"],shortPrepositionsList:["as","at","by","in","into","of","off","on","onto","out","over","to","up","via","with","from","under","upon"],neverCapitalizedList:[]},wikipedia:{shortConjunctionsList:["and","as","but","for","nor","or","so","yet"],articlesList:["a","an","the"],shortPrepositionsList:["as","at","by","in","into","of","off","on","onto","out","over","to","up","via","with","from","under","upon"],neverCapitalizedList:[]}}),t.ignoredWordList=[],t.correctPhraseCasingList={"the cybersmile foundation":"The Cybersmile Foundation","co. by colgate":"CO. by Colgate","on & off":"On & Off","on and off":"On and Off"},t.regionalAcronymList=["usa","us","u.s.a","u.s.","u.s","u.s.a.","eu","e.u.","e.u","uk","u.k.","u.k"],t.regionalAcronymPrecedingWords=["the","via","among","across","beyond","outside","alongside","throughout","despite","unlike","upon"],t.directFollowingIndicatorsRegionalAcronym=["act","acts","administration","administrations","agency","agencies","agreement","agreements","airforce","airforces","aid","alliance","alliances","ambassador","ambassadors","authority","authorities","bill","bills","bloc","blocs","budget","budgets","bureau","bureaus","cabinet","cabinets","charter","charters","command","commands","commission","commissions","conference","conferences","congress","congresses","convention","conventions","council","councils","court","courts","defense","defences","defence","defenses","delegation","delegations","democracy","democracies","department","departments","development","developments","directive","directives","diplomacy","division","divisions","economy","economies","embassy","embassies","engagement","engagements","envoy","envoys","exports","federation","federations","finance","finances","forces","framework","frameworks","funding","government","governments","hearing","hearings","imports","initiative","initiatives","intel","intelligence","intervention","interventions","jurisdiction","jurisdictions","law","laws","leadership","leaders","legislation","liaison","liaisons","mandate","mandates","markets","marines","military","militaries","ministry","ministries","mission","missions","navy","navies","negotiations","office","offices","operations","oversight","parliament","parliaments","plan","plans","policies","policy","policy-makers","precedent","precedents","presence","program","programme","programmes","programs","project","projects","protocol","protocols","province","provinces","reform","reforms","regulation","regulations","regulator","regulators","relations","representation","representations","republic","republics","resolution","resolutions","ruling","rulings","sanctions","security","securities","senate","senates","service","services","state","states","statute","statutes","strategy","strategies","summit","summits","summitry","surveillance","talks","tariffs","territory","territories","trade","trades","treasury","treasuries","treaty","treaties","tribunal","tribunals","troops","union","unions","veterans","warships","zone","zones"]},491:e=>{e.exports=JSON.parse('{"timeRelated":["a.m.","p.m.","ca.","cc.","fig.","pl.","pt.","rev.","sr.","v.","vol.","et al.","pp.","p."],"academic":["adj.","adv.","cf.","cm.","co.","corp.","dept.","dist.","ed.","edn.","esp.","etc.","ex.","i.e.","e.g.","op. cit.","vs."]}')},501:e=>{e.exports=JSON.parse('{"terms":["API","APIs","ASCII","CI","CLI","DLL","DNS","EC2","FTP","HTTP","HTTPS","ICMP","IDE","IP","ISP","LPWAN","M2M","MQTT","OOP","REST","SSH","SSL","TCP","UDP","URL","WLAN","WYSIWYG","IMAP","RSS","IaaS","PaaS","SaaS","CaaS","FaaS","XaaS","RaaS","IoE","IoT","LoRa","NB-IoT","RFID","RF","RFI","RFQ","ECMAScript","IO","I/O","DevOps","SecOps","DDoS","VoIP","AI","AR","ML","VR","CI/CD","DevSecOps","UI/UX","UX/UI","UI","UX","MVC","ORM","3G","4G","5G","NumPy","VPN","PKI","WAN","NAT","GPU","SSD","HDD","RAM","Frontend","Backend","Fullstack"],"legal":["DMCA","GDPR","HIPAA","NDA","SOW","TOS"],"languages":["JavaScript","TypeScript","Java","PHP","SQL","CSS",".NET","ES5","ES6","NoSQL","DynamoDB","Terraform","CloudFormation","RDS","Python","Ruby","Go","Swift","Kotlin","Perl"],"formats":["JSON","XML","YAML","GraphQL","WebSocket","RESTful"],"secops":["RaaS","DevSecOps","SecOps","Cybersecurity","DDoS"],"technologies":["AWS","Azure","GCP","VMware","Docker","Ansible","Chef","Puppet","Git","Subversion","Jenkins","CircleCI","Hadoop","Spark","BigQuery","PowerBI","Tableau"],"os":["Android","macOS","Windows","Linux","iOS","Ubuntu","CentOS","Fedora","Debian","SUSE","HarmonyOS","FreeRTOS","BeOS","BSD","Cordova","Flutter"],"programming":["Angular","Bootstrap","CodeIgniter","jQuery","Laravel","Redux","Vue.js","VueX","SCSS","AJAX","GraphQL","HTML","HTML5","MySQL","MongoDB","PostgresQL","SQLite","ASP","ASPX","Elasticsearch","Nginx","OpenSSL","Webpack","Unity3D","Kubernetes","TensorFlow","NPM","cURL"]}')},661:e=>{e.exports=JSON.parse('{"eterms":["eBook","eBooks","eMarket","eMarketplace","eMarketplaces","eMarkets","eReader","eShop","eShops","eStore","eStores","E-commerce","E-com"]}')},742:e=>{e.exports=JSON.parse('{"miscellaneous":["w/","w/o","Open Source","Cybersecurity","Ecosystem","Biodiversity","LGBT","LGBTQ+","LGBTQIA+","2SLGBTQ+","BIPOC"]}')},814:e=>{e.exports=JSON.parse('{"commercial":["Ltd.","LLC","PLC","Co.","Inc.","St.","Ave.","Bldg.","No.","GmbH"],"titles":["CEO","CEOs","CFO","CFOs","CIO","CIOs","CMO","CMOs","COO","COOs","CPO","CPOs","CRO","CROs","CSO","CSOs","CTO","CTOs","EVP","EVPs","HR","HRs","SVP","SVPs","VP","VPs","CMTO","CDO"],"accounting":["AP","COGS","EBIT","EPS","FIFO","GAAP","LIFO","P&L","ROI","SOX","TCO","VAT","EBITDA","NPV","WACC","AR"],"finance":["CAGR","DCF","ETF","IPO","IRR","M&A","NAV","PE","PEG","PPE","ROE","S&P","TVM","VC","FOMC","FX","ETF"],"legal":["AFA","ADR","CCPA","CFAA","CISG","DMCA","EULA","GDPR","HIPAA","NDA","SOW","TOS","LLM","JD","Esq.","AG","SARL","KYC","AML","ph.d.","m.d.","d.d.s.","d.m.d.","d.o.","d.c.","d.v.m.","d.n.p.","d.p.m.","d.s.w.","d.s.n.","d.n.sc.","d.n.a.","d.n.t.","d.n.p.t.","d.n.o.","d.n.m.","d.n.e.","d.n.s.","d.n.p.s."]}')},987:(e,t,r)=>{var i=r(388);void 0===String.prototype.toTitleCase&&(String.prototype.toTitleCase=function(e){return new i.TitleCaser(e).toTitleCase(this)}),e.exports&&(e.exports={TitleCaser:i.TitleCaser}),"undefined"!=typeof window&&window.document&&(window.TitleCaser=i.TitleCaser)}},t={};var r=function r(i){var a=t[i];if(void 0!==a)return a.exports;var s=t[i]={exports:{}};return e[i](s,s.exports,r),s.exports}(987);module.exports=r})();
package/index.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ declare module '@danielhaim/titlecaser' {
2
+ export interface TitleCaserOptions {
3
+ style?: 'ap' | 'apa' | 'chicago' | 'wikipedia' | 'nyt';
4
+ smartQuotes?: boolean;
5
+ ignoreWords?: string[];
6
+ acronyms?: string[];
7
+ }
8
+
9
+ export class TitleCaser {
10
+ constructor(options?: TitleCaserOptions);
11
+ toTitleCase(text: string): string;
12
+ setReplaceTerms(terms: Array<{ [key: string]: string }>): void;
13
+ addReplaceTerm(term: string, replacement: string): void;
14
+ removeReplaceTerm(term: string): void;
15
+ addExactPhraseReplacements(phrases: Array<{ [key: string]: string }>): void;
16
+ }
17
+ }
18
+
19
+ declare global {
20
+ interface String {
21
+ toTitleCase(options?: import('@danielhaim/titlecaser').TitleCaserOptions): string;
22
+ }
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danielhaim/titlecaser",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "Converts a string to title case with multiple style options, ability to ignore certain words, and handle acronyms",
5
5
  "keywords": [
6
6
  "title case",
@@ -37,9 +37,11 @@
37
37
  "main": "./index.js",
38
38
  "files": [
39
39
  "LICENSE",
40
+ "index.d.ts",
40
41
  "README.md",
41
42
  "index.js",
42
43
  "src/",
44
+ "dist",
43
45
  "package.json"
44
46
  ],
45
47
  "scripts": {
@@ -52,27 +54,27 @@
52
54
  "tree": "tree -a -I 'node_modules|.git|.DS_Store'"
53
55
  },
54
56
  "devDependencies": {
55
- "@babel/cli": "^7.24.7",
56
- "@babel/core": "^7.24.7",
57
+ "@babel/cli": "^7.27.0",
58
+ "@babel/core": "^7.26.10",
57
59
  "@babel/plugin-proposal-class-properties": "^7.18.6",
58
60
  "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
59
- "@babel/plugin-transform-modules-commonjs": "^7.24.7",
60
- "@babel/preset-env": "^7.24.7",
61
- "@babel/runtime-corejs3": "^7.24.7",
61
+ "@babel/plugin-transform-modules-commonjs": "^7.26.3",
62
+ "@babel/preset-env": "^7.26.9",
63
+ "@babel/runtime-corejs3": "^7.27.0",
62
64
  "@jest/expect": "^29.5.0",
63
65
  "babel-jest": "^29.7.0",
64
- "babel-loader": "^9.1.2",
66
+ "babel-loader": "^10.0.0",
65
67
  "esbuild-jest": "^0.5.0",
66
68
  "exports-loader": "^5.0.0",
67
69
  "jest": "^29.7.0",
68
70
  "jest-environment-jsdom": "^29.5.0",
69
- "jest-environment-puppeteer": "^10.0.1",
70
- "jest-puppeteer": "^10.0.1",
71
- "puppeteer": "^22.11.0",
72
- "puppeteer-core": "^22.11.0",
73
- "terser-webpack-plugin": "^5.3.9",
74
- "webpack": "^5.92.0",
75
- "webpack-cli": "^5.1.4",
71
+ "jest-environment-puppeteer": "^11.0.0",
72
+ "jest-puppeteer": "^11.0.0",
73
+ "puppeteer": "^24.6.0",
74
+ "puppeteer-core": "^24.6.0",
75
+ "terser-webpack-plugin": "^5.3.14",
76
+ "webpack": "^5.99.5",
77
+ "webpack-cli": "6.0.1",
76
78
  "webpack-node-externals": "^3.0.0"
77
79
  },
78
80
  "publishConfig": {
package/src/TitleCaser.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import {
2
- commonAbbreviationList,
2
+ commonShortWords,
3
3
  correctTitleCasingList,
4
4
  correctPhraseCasingList,
5
- wordReplacementsList,
5
+ wordReplacementsList
6
6
  } from "./TitleCaserConsts.js";
7
7
 
8
8
  import { TitleCaserUtils } from "./TitleCaserUtils.js";
9
9
 
10
10
  export class TitleCaser {
11
- constructor(options = {}) {
11
+ constructor (options = {}) {
12
12
  this.options = options;
13
13
  this.debug = options.debug || false;
14
14
  this.wordReplacementsList = wordReplacementsList;
@@ -23,13 +23,13 @@ export class TitleCaser {
23
23
 
24
24
  toTitleCase(str) {
25
25
  try {
26
- // If input is empty, throw an error.
26
+ // ! If input is empty, throw an error.
27
27
  if (str.trim().length === 0) throw new TypeError("Invalid input: input must not be empty.");
28
28
 
29
- // If input is not a string, throw an error.
29
+ // ! If input is not a string, throw an error.
30
30
  if (typeof str !== "string") throw new TypeError("Invalid input: input must be a string.");
31
31
 
32
- // If options is not an object, throw an error.
32
+ // ! If options is not an object, throw an error.
33
33
  if (typeof this.options !== "undefined" && typeof this.options !== "object")
34
34
  throw new TypeError("Invalid options: options must be an object.");
35
35
 
@@ -47,8 +47,8 @@ export class TitleCaser {
47
47
  shortPrepositionsList,
48
48
  neverCapitalizedList,
49
49
  replaceTerms,
50
- smartQuotes: mergedSmartQuotes, // Rename for clarity
51
- } = TitleCaserUtils.getTitleCaseOptions(this.options, commonAbbreviationList, wordReplacementsList);
50
+ smartQuotes: mergedSmartQuotes,
51
+ } = TitleCaserUtils.getTitleCaseOptions(this.options, commonShortWords, wordReplacementsList);
52
52
 
53
53
  // Prerocess the replaceTerms array to make it easier to search for.
54
54
  const replaceTermsArray = replaceTermList.map((term) => Object.keys(term)[0].toLowerCase());
@@ -79,26 +79,37 @@ export class TitleCaser {
79
79
  // Remove extra spaces and replace <br> tags with a placeholder.
80
80
  inputString = inputString.replace(/ {2,}/g, (match) => match.slice(0, 1));
81
81
 
82
+ // Check if the entire input string is uppercase and normalize it to lowercase
83
+ // before processing if it is. This ensures consistent handling for all-caps text.
84
+ const isEntireStringUppercase = TitleCaserUtils.isEntirelyUppercase(inputString.replace(/[^a-zA-Z]/g, ''));
85
+ if (isEntireStringUppercase) {
86
+ this.logWarning("Input string is entirely uppercase, normalizing to lowercase first");
87
+ inputString = inputString.toLowerCase();
88
+ }
89
+
82
90
  // Split the string into an array of words.
83
91
  const words = inputString.split(" ");
84
92
 
85
93
  const wordsInTitleCase = words.map((word, i) => {
86
94
  switch (true) {
87
95
  case TitleCaserUtils.isWordAmpersand(word):
88
- // if the word is an ampersand, return it as is.
96
+ // ! if the word is an ampersand, return it as is.
89
97
  return word;
90
98
  case TitleCaserUtils.hasHtmlBreak(word):
91
- // If the word is a <br> tag, return it as is.
99
+ // ! If the word is a <br> tag, return it as is.
92
100
  return word;
93
101
  case TitleCaserUtils.isWordIgnored(word, ignoreList):
94
- // If the word is in the ignore list, return it as is.
102
+ // ! If the word is in the ignore list, return it as is.
95
103
  return word;
96
104
  case replaceTermsArray.includes(word.toLowerCase()):
97
- // If the word is in the replaceTerms array, return the replacement.
105
+ // ! If the word is in the replaceTerms array, return the replacement.
98
106
  return replaceTermObj[word.toLowerCase()];
99
107
  case TitleCaserUtils.isWordInArray(word, correctTitleCasingList):
100
- // If the word is in the correctTitleCasingList array, return the correct casing.
108
+ // ! If the word is in the correctTitleCasingList array, return the correct casing.
101
109
  return TitleCaserUtils.correctTerm(word, correctTitleCasingList);
110
+ case TitleCaserUtils.isElidedWord(word):
111
+ // ! If the word is an elided word, return the correct casing.
112
+ return TitleCaserUtils.normalizeElidedWord(word);
102
113
  case TitleCaserUtils.hasHyphen(word):
103
114
  // Separate the base word from any trailing punctuation
104
115
  const baseWord = word.replace(/[\W_]+$/, "");
@@ -121,19 +132,23 @@ export class TitleCaser {
121
132
  const processedWord = isReplaced ? replacedParts.join("-") : TitleCaserUtils.correctTermHyphenated(word, style);
122
133
  return processedWord.endsWith(trailingPunctuation) ? processedWord : processedWord + trailingPunctuation;
123
134
  case TitleCaserUtils.hasSuffix(word, style):
124
- // If the word has a suffix, return the correct casing.
135
+ // ! If the word has a suffix, return the correct casing.
125
136
  return TitleCaserUtils.correctSuffix(word, correctTitleCasingList);
126
137
  case TitleCaserUtils.hasUppercaseIntentional(word):
127
- // If the word has an intentional uppercase letter, return the correct casing.
138
+ // ! If the word has an intentional uppercase letter, return the correct casing.
128
139
  return word;
129
140
  case TitleCaserUtils.isShortWord(word, style) && i !== 0:
130
- // If the word is a short word, return the correct casing.
131
- return i > 0 && TitleCaserUtils.endsWithSymbol(words[i - 1], [":", "?", "!", "."])
132
- ? word.charAt(0).toUpperCase() + word.slice(1)
133
- : word.toLowerCase();
141
+ // ! If the word is a short word, return the correct casing.
142
+ const isAtEndOfSentence = i > 0 && TitleCaserUtils.endsWithSymbol(words[i - 1], [":", "?", "!", "."]);
143
+ if (isAtEndOfSentence) {
144
+ return word.charAt(0).toUpperCase() + word.slice(1);
145
+ }
146
+
147
+ const wordCasing = TitleCaserUtils.normalizeCasingForWordByStyle(word, style);
148
+ return wordCasing;
134
149
  case TitleCaserUtils.endsWithSymbol(word):
135
150
  this.logWarning(`Check if the word ends with a symbol: ${word}`);
136
- // If the word ends with a symbol, return the correct casing.
151
+ // ! If the word ends with a symbol, return the correct casing.
137
152
  const splitWord = word.split(/([.,\/#!$%\^&\*;:{}=\-_`~()?])/g);
138
153
  this.logWarning(`Splitting word at symbols, result: ${splitWord}`);
139
154
  // Process each part for correct casing
@@ -145,7 +160,7 @@ export class TitleCaser {
145
160
  return part;
146
161
  } else {
147
162
  this.logWarning(`Part is a word: ${part}`);
148
- // If it's a word, process it for correct casing
163
+ // ! If it's a word, process it for correct casing
149
164
  if (TitleCaserUtils.isWordInArray(part, correctTitleCasingList)) {
150
165
  const correctedTerm = TitleCaserUtils.correctTerm(part, correctTitleCasingList);
151
166
  this.logWarning(`Word is in correctTitleCasingList, corrected term: ${correctedTerm}`);
@@ -165,15 +180,15 @@ export class TitleCaser {
165
180
  // Join the processed words and return them.
166
181
  return processedWords.join("");
167
182
  case TitleCaserUtils.startsWithSymbol(word):
168
- // If the word starts with a symbol, return the correct casing.
183
+ // ! If the word starts with a symbol, return the correct casing.
169
184
  return !TitleCaserUtils.isWordInArray(word, correctTitleCasingList)
170
185
  ? word
171
186
  : TitleCaserUtils.correctTerm(word);
172
187
  case TitleCaserUtils.hasRomanNumeral(word):
173
- // If the word has a roman numeral, return the correct casing.
188
+ // ! If the word has a roman numeral, return the correct casing.
174
189
  return word.toUpperCase();
175
190
  case TitleCaserUtils.hasNumbers(word):
176
- // If the word has numbers, return the correct casing.
191
+ // ! If the word has numbers, return the correct casing.
177
192
  return word;
178
193
  default:
179
194
  // Default to returning the word with the correct casing.
@@ -184,14 +199,6 @@ export class TitleCaser {
184
199
  // Join the words in the array into a string.
185
200
  inputString = wordsInTitleCase.join(" ");
186
201
 
187
- for (const [phrase, replacement] of Object.entries(this.correctPhraseCasingList)) {
188
- // Create a regular expression for case-insensitive matching of the phrase
189
- const regex = new RegExp(phrase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
190
-
191
- // Replace the phrase in the input string with its corresponding replacement
192
- inputString = inputString.replace(regex, replacement);
193
- }
194
-
195
202
  // Replace the nl2br placeholder with <br> tags.
196
203
  inputString = inputString.replace(/nl2br/gi, "<br>");
197
204
 
@@ -202,6 +209,9 @@ export class TitleCaser {
202
209
  }
203
210
 
204
211
  const newWords = inputString.split(" ");
212
+ let firstWord = newWords[0];
213
+ let secondWord = newWords[1] || null;
214
+ let lastWord = newWords[newWords.length - 1];
205
215
 
206
216
  for (let i = 0; i < newWords.length; i++) {
207
217
  const prevWord = i > 0 ? newWords[i - 1] : null;
@@ -217,29 +227,86 @@ export class TitleCaser {
217
227
  currentWord = currentWord.replace(/[.,!?;:]+$/, ""); // Remove punctuation at the end
218
228
  }
219
229
 
220
- let cleanCurrentWord = currentWord.replace(/[.,!?;:]/g, "");
221
- let cleanNextWord = nextWord ? nextWord.replace(/[.,!?;:]/g, "") : nextWord;
230
+ if (TitleCaserUtils.isRegionalAcronym(currentWord)) {
231
+ currentWord = TitleCaserUtils.normalizeRegionalAcronym(currentWord);
232
+ }
222
233
 
223
- if (cleanCurrentWord === "Us") {
224
- if (TitleCaserUtils.isAcronym(currentWord, prevWord, nextWord)) {
225
- if (punctuation === "") {
226
- newWords[i] = "US";
227
- } else {
228
- newWords[i] = "US" + punctuation;
229
- }
230
- } else {
231
- if (punctuation === "") {
232
- newWords[i] = "Us";
233
- } else {
234
- newWords[i] = "Us" + punctuation;
235
- }
236
- }
234
+ if (TitleCaserUtils.isRegionalAcronymNoDot(currentWord, nextWord)) {
235
+ currentWord = TitleCaserUtils.normalizeRegionalAcronym(currentWord);
236
+ }
237
+
238
+ // if punctuation is not empty, add it to the end of the word
239
+ if (punctuation !== "") {
240
+ currentWord = currentWord + punctuation;
237
241
  }
238
242
  }
239
243
 
240
244
  inputString = newWords.join(" ");
241
245
 
246
+ const newSplit = inputString.split(" ");
247
+ for (let i = 1; i < newSplit.length - 1; i++) {
248
+ const currentWord = newSplit[i];
249
+ const prevWord = newSplit[i - 1];
250
+ const nextWord = newSplit[i + 1];
251
+
252
+ if (
253
+ currentWord === currentWord.toUpperCase() ||
254
+ TitleCaserUtils.hasUppercaseIntentional(currentWord)
255
+ ) {
256
+ continue;
257
+ }
258
+
259
+ if (TitleCaserUtils.isWordInArray(currentWord, commonShortWords)) {
260
+ newSplit[i] =
261
+ currentWord.length <= 3
262
+ ? currentWord.toLowerCase()
263
+ : currentWord;
264
+ }
265
+ }
266
+
267
+ inputString = newSplit.join(" ");
268
+
269
+ const newSplit2 = inputString.split(" ");
270
+ for (let i = 0; i < newSplit2.length; i++) {
271
+ let currentWord = newSplit2[i];
272
+ let nextWord = newSplit2[i + 1];
273
+ let prevWord = newSplit2[i - 1];
274
+ if (nextWord !== null && TitleCaserUtils.isRegionalAcronymNoDot(currentWord, nextWord, prevWord)) {
275
+ newSplit2[i] = currentWord.toUpperCase();
276
+ }
277
+ }
278
+
279
+
280
+
281
+ let finalWord = newSplit2[newSplit2.length - 1];
282
+ let wordBeforeFinal = newSplit2[newSplit2.length - 2];
283
+ let twoWordsBeforeFinal = newSplit2[newSplit2.length - 3];
284
+
285
+ if (TitleCaserUtils.isRegionalAcronym(firstWord)) {
286
+ console.log("firstWord is a regional acronym, proof: ", firstWord);
287
+ newSplit2[0] = firstWord.toUpperCase();
288
+ }
289
+
290
+ if (TitleCaserUtils.isRegionalAcronymNoDot(firstWord, secondWord)) {
291
+ newSplit2[0] = firstWord.toUpperCase();
292
+ }
293
+
294
+ if (TitleCaserUtils.isFinalWordRegionalAcronym(finalWord, wordBeforeFinal, twoWordsBeforeFinal)) {
295
+ newSplit2[newSplit2.length - 1] = finalWord.toUpperCase();
296
+ }
297
+
298
+ inputString = newSplit2.join(" ");
299
+
300
+ for (const [phrase, replacement] of Object.entries(this.correctPhraseCasingList)) {
301
+ // Create a regular expression for case-insensitive matching of the phrase
302
+ const regex = new RegExp(phrase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
303
+
304
+ // Replace the phrase in the input string with its corresponding replacement
305
+ inputString = inputString.replace(regex, replacement);
306
+ }
307
+
242
308
  return inputString;
309
+
243
310
  } catch (error) {
244
311
  throw new Error(error);
245
312
  }
@@ -249,7 +316,7 @@ export class TitleCaser {
249
316
  if (!Array.isArray(terms)) {
250
317
  throw new TypeError("Invalid argument: setReplaceTerms must be an array of objects.");
251
318
  }
252
- // Iterate over each term-replacement object in the array
319
+ // ! Iterate over each term-replacement object in the array
253
320
  terms.forEach((termObject) => {
254
321
  if (termObject && typeof termObject === "object") {
255
322
  const [term, replacement] = Object.entries(termObject)[0];
@@ -296,7 +363,7 @@ export class TitleCaser {
296
363
  // Find the index of the term in the wordReplacementsList array
297
364
  const index = this.wordReplacementsList.findIndex((obj) => Object.keys(obj)[0] === term);
298
365
 
299
- // If the term is not found in the array, throw an error
366
+ // ! If the term is not found in the array, throw an error
300
367
  if (index === -1) {
301
368
  throw new Error(`Term '${term}' not found in word replacements list.`);
302
369
  }
@@ -316,7 +383,7 @@ export class TitleCaser {
316
383
  }
317
384
 
318
385
  newPhrases.forEach((item) => {
319
- // If the item is an object with a single key-value pair
386
+ // ! If the item is an object with a single key-value pair
320
387
  if (typeof item === "object" && !Array.isArray(item) && Object.keys(item).length === 1) {
321
388
  const key = Object.keys(item)[0];
322
389
  const value = item[key];
@@ -326,7 +393,7 @@ export class TitleCaser {
326
393
  throw new TypeError("Invalid argument: Each key-value pair must contain strings.");
327
394
  }
328
395
  }
329
- // If the item is already a key-value pair
396
+ // ! If the item is already a key-value pair
330
397
  else if (typeof item === "object" && !Array.isArray(item)) {
331
398
  Object.entries(item).forEach(([key, value]) => {
332
399
  if (typeof key === "string" && typeof value === "string") {
@@ -336,7 +403,7 @@ export class TitleCaser {
336
403
  }
337
404
  });
338
405
  }
339
- // Invalid format
406
+ // ! Invalid format
340
407
  else {
341
408
  throw new TypeError("Invalid argument: Each item must be an object with a single key-value pair.");
342
409
  }