UNPKG

@danielhaim/titlecaser

Version:

A powerful utility for transforming text to title case with support for multiple style guides and extensive customization options.

402 lines (375 loc) 9.93 kB
import brandList from "./data/brandList.json"; import businessFinanceLegalTerms from "./data/businessFinanceLegalTerms.json"; import eCommerceDigitalTerms from "./data/eCommerceDigitalTerms.json"; import globalGeography from "./data/globalGeography.json"; import marketingMediaTerms from "./data/marketingMediaTerms.json"; import miscSpecializedTerms from "./data/miscSpecializedTerms.json"; import techComputingConcepts from "./data/techComputingConcepts.json"; import timeAcademicTerms from "./data/timeAcademicTerms.json"; import militaryTerms from "./data/militaryTerms.json"; function mergeArrays(...arraysOrObjects) { const merged = []; arraysOrObjects.forEach((item) => { if (Array.isArray(item)) { // If the item is an array, process each object in the array item.forEach((obj) => { Object.values(obj).forEach((value) => { merged.push(...value); }); }); } else if (typeof item === "object") { // If the item is an object, directly take its values Object.values(item).forEach((value) => { merged.push(...value); }); } }); return [...new Set(merged)]; } const mergedArray = mergeArrays( brandList, businessFinanceLegalTerms, eCommerceDigitalTerms, globalGeography, marketingMediaTerms, miscSpecializedTerms, techComputingConcepts, timeAcademicTerms, militaryTerms, ); export const specialTermsList = mergedArray; export const shortWordsList = [ "the", "in", "to", "within", "towards", "into", "at", "of", "for", "by", "on", "from", "with", "through", "about", "across", "over", "under", "between" ]; export const 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" }, // { 'twitter': 'Twitter, formerly known as 𝕏' } ]; // * ! =============================================== // * ! Title Case Styles // * ! =============================================== export const TITLE_CASE_STYLES = Object.freeze({ AP: "ap", APA: "apa", BRITISH: "british", CHICAGO: "chicago", NYT: "nyt", WIKIPEDIA: "wikipedia", }); export const allowedStylesList = Object.values(TITLE_CASE_STYLES); export const styleConfigMap = Object.freeze({ ap: { caseStyle: "title", // AP: Capitalize all words 4+ letters and all verbs/adverbs shortConjunctionsList: ["and", "but", "or", "nor", "yet", "so", "for"], articlesList: ["a", "an", "the"], shortPrepositionsList: [ // Pure prepositions (2–3 letters) safe to lowercase in AP "at", // e.g., "Dinner at Eight" "by", // e.g., "Written by the Author" "for", // e.g., "A Gift for You" "in", // e.g., "Made in America" "of", // e.g., "State of Mind" "off", // e.g., "10% Off Everything" "on", // e.g., "The War on Drugs" "out", // e.g., "Out of Context" "per", // e.g., "As per Usual" "to", // e.g., "Back to the Future" "via" // e.g., "Sent via Email" ], neverCapitalizedList: [], }, apa: { caseStyle: "title", // APA: Minor words are ≤3 letters, regardless of function shortConjunctionsList: ["and", "as", "but", "for", "if", "nor", "or", "so", "yet"], articlesList: ["a", "an", "the"], shortPrepositionsList: [ // Strictly ≤3-letter prepositions per APA 7th edition "as", // Subordinating conj. but included per APA convention "at", "by", "for", "in", "of", "off", "on", "per", "to", "via" ], neverCapitalizedList: [], }, british: { caseStyle: "title", // British English typically follows Chicago or APA rules shortConjunctionsList: ["and", "but", "or", "for", "nor", "yet", "so"], articlesList: ["a", "an", "the"], shortPrepositionsList: [ // Safe lowercasing set, similar to APA "at", "by", "for", "in", "of", "off", "on", "out", "per", "to", "via" ], neverCapitalizedList: [], }, chicago: { caseStyle: "title", // Chicago: Similar to AP, but may capitalize some longer preps shortConjunctionsList: ["and", "but", "or", "for", "nor", "yet", "so"], articlesList: ["a", "an", "the"], shortPrepositionsList: [ // Filtered to exclude questionable entries like "up", "under", etc. "at", "by", "for", "in", "of", "off", "on", "out", "per", "to", "via" ], neverCapitalizedList: ["etc."], }, nyt: { caseStyle: "title", // NYT style aligns closely with Chicago/AP shortConjunctionsList: ["and", "but", "or", "nor", "yet", "so", "for"], articlesList: ["a", "an", "the"], shortPrepositionsList: [ "at", "by", "for", "in", "of", "off", "on", "out", "per", "to", "via" ], neverCapitalizedList: [], }, wikipedia: { caseStyle: "sentence", // Sentence case: first word + acronyms only, preps list for completeness shortConjunctionsList: ["and", "as", "but", "for", "nor", "or", "so", "yet"], articlesList: ["a", "an", "the"], shortPrepositionsList: [ // No impact unless sentence case logic is bypassed "at", "by", "for", "in", "of", "off", "on", "out", "per", "to", "via" ], neverCapitalizedList: [], } }); // * ! =============================================== // * ! Ignored Words // * ! =============================================== export const ignoredWordList = []; // * ! =============================================== // * ! Correct Phrase Casing // * ! =============================================== export const phraseReplacementMap = { 'the cybersmile foundation': 'The Cybersmile Foundation', 'co. by colgate': 'CO. by Colgate', "on & off": "On & Off", "on and off": "On and Off", }; // * ! =============================================== // * ! Regex Patterns // * ! =============================================== export const REGEX_PATTERNS = Object.freeze({ // Punctuation at end of word TRAILING_PUNCTUATION: /[.,!?;:]+$/, // Split word at punctuation while preserving delimiters SPLIT_AT_PUNCTUATION: /([.,\/#!$%\^&\*;:{}=\-_`~()?])/g, // Match HTML break tags HTML_BREAK: /<\s*br\s*\/?\s*>/gi, // Multiple consecutive spaces MULTIPLE_SPACES: / {2,}/g, // Regex escape special characters REGEX_ESCAPE: /[.*+?^${}()|[\]\\]/g, }); // * ! =============================================== // * ! Acronym Replacements // * ! =============================================== export const regionalAcronymList = [ "usa", "us", "u.s.a", "u.s.", "u.s", "u.s.a.", "eu", "e.u.", "e.u", "uk", "u.k.", "u.k", ]; export const regionalAcronymPrecedingWordsList = [ "the", "via", "among", "across", "beyond", "outside", "alongside", "throughout", "despite", "unlike", "upon" ]; export const regionalAcronymFollowingWordsList = [ "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" ];