feat(glossy): improve pluralize
This commit is contained in:
2 files changed
+418
-12
No files matched your search
+110
-12
@@ -10,29 +10,127 @@
|
|||||||
// word: The singular word to pluralize
|
// word: The singular word to pluralize
|
||||||
// Returns: The pluralized form of the word, or none if input is none
|
// Returns: The pluralized form of the word, or none if input is none
|
||||||
#let __pluralize(word) = {
|
#let __pluralize(word) = {
|
||||||
// early exit with invalid input
|
// Early exit for invalid input
|
||||||
if word == none {
|
if word == none {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define helper functions for checking endings
|
// Helper functions for checking endings
|
||||||
let ends_with = (suffix) => lower(word).ends-with(suffix)
|
let ends_with = (suffix) => lower(word).ends-with(suffix)
|
||||||
let ends_with_any = (suffixes) => suffixes.any((suffix) => ends_with(suffix))
|
let ends_with_any = (suffixes) => suffixes.any((suffix) => ends_with(suffix))
|
||||||
|
|
||||||
// Handle special cases for "es" endings (s, x, z, sh, ch)
|
// Map of irregular plurals for common words
|
||||||
if ends_with_any(( "s", "x", "z", "sh", "ch" )) {
|
let irregulars = (
|
||||||
|
"alumna": "alumnae",
|
||||||
|
"alumnus": "alumni",
|
||||||
|
"analysis": "analyses",
|
||||||
|
"appendix": "appendices",
|
||||||
|
"basis": "bases",
|
||||||
|
"cactus": "cacti",
|
||||||
|
"child": "children",
|
||||||
|
"crisis": "crises",
|
||||||
|
"criterion": "criteria",
|
||||||
|
"datum": "data",
|
||||||
|
"foot": "feet",
|
||||||
|
"fungus": "fungi",
|
||||||
|
"goose": "geese",
|
||||||
|
"man": "men",
|
||||||
|
"medium": "media",
|
||||||
|
"mouse": "mice",
|
||||||
|
"nucleus": "nuclei",
|
||||||
|
"oasis": "oases",
|
||||||
|
"person": "people",
|
||||||
|
"phenomenon": "phenomena",
|
||||||
|
"stimulus": "stimuli",
|
||||||
|
"thesis": "theses",
|
||||||
|
"tooth": "teeth",
|
||||||
|
"woman": "women",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set of plural-only words
|
||||||
|
let plural_only = (
|
||||||
|
"advice",
|
||||||
|
"alumni",
|
||||||
|
"bison",
|
||||||
|
"children",
|
||||||
|
"criteria",
|
||||||
|
"data",
|
||||||
|
"deer",
|
||||||
|
"feet",
|
||||||
|
"fish",
|
||||||
|
"geese",
|
||||||
|
"information",
|
||||||
|
"media",
|
||||||
|
"men",
|
||||||
|
"mice",
|
||||||
|
"money",
|
||||||
|
"moose",
|
||||||
|
"octopi",
|
||||||
|
"octopodes",
|
||||||
|
"people",
|
||||||
|
"scissors",
|
||||||
|
"series",
|
||||||
|
"sheep",
|
||||||
|
"species",
|
||||||
|
"teeth",
|
||||||
|
"trousers",
|
||||||
|
"women",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Irregular suffixes
|
||||||
|
let f_to_ves = ("leaf", "loaf", "calf", "half", "wolf", "thief")
|
||||||
|
let fe_to_ves = ("wife", "knife", "life")
|
||||||
|
let o_to_os = ("photo", "piano", "halo", "radio", "video", "studio", "solo", "taco", "memo", "zero")
|
||||||
|
|
||||||
|
// Convenience
|
||||||
|
let w = lower(word)
|
||||||
|
|
||||||
|
// Check for words already plural
|
||||||
|
if plural_only.contains(w) {
|
||||||
|
return word
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for irregular singulars
|
||||||
|
if irregulars.keys().contains(w) {
|
||||||
|
return irregulars.at(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard pluralization rules
|
||||||
|
if ends_with("iz") {
|
||||||
|
word + "zes"
|
||||||
|
} else if ends_with_any(("s", "x", "z", "sh", "ch")) {
|
||||||
word + "es"
|
word + "es"
|
||||||
} else if ends_with("y") and not ends_with_any(( "a", "e", "i", "o", "u" )) {
|
} else if ends_with("y") {
|
||||||
// Convert y to ies when y follows a consonant
|
if not ends_with_any(("ay", "ey", "iy", "oy", "uy")) {
|
||||||
word.slice(0, -1) + "ies"
|
word.slice(0, -1) + "ies"
|
||||||
|
} else {
|
||||||
|
word + "s"
|
||||||
|
}
|
||||||
} else if ends_with("f") {
|
} else if ends_with("f") {
|
||||||
// Convert f to ves
|
if f_to_ves.contains(w) {
|
||||||
word.slice(0, -1) + "ves"
|
word.slice(0, -1) + "ves"
|
||||||
|
} else {
|
||||||
|
word + "s"
|
||||||
|
}
|
||||||
} else if ends_with("fe") {
|
} else if ends_with("fe") {
|
||||||
// Convert fe to ves
|
if fe_to_ves.contains(w) {
|
||||||
word.slice(0, -2) + "ves"
|
word.slice(0, -2) + "ves"
|
||||||
|
} else {
|
||||||
|
word + "s"
|
||||||
|
}
|
||||||
|
} else if ends_with("us") {
|
||||||
|
word.slice(0, -2) + "i"
|
||||||
|
} else if ends_with("is") {
|
||||||
|
word.slice(0, -2) + "es"
|
||||||
|
} else if ends_with("on") {
|
||||||
|
word + "s"
|
||||||
|
} else if ends_with("o") {
|
||||||
|
if o_to_os.contains(w) {
|
||||||
|
word + "s"
|
||||||
|
} else {
|
||||||
|
word + "es"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Default case: just add s
|
|
||||||
word + "s"
|
word + "s"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
#import "/src/utils.typ": __pluralize
|
||||||
|
|
||||||
|
#let plural_tests = (
|
||||||
|
("BUS", "BUSes"),
|
||||||
|
("Box", "Boxes"),
|
||||||
|
("Buzz", "Buzzes"),
|
||||||
|
("CHURCH", "CHURCHes"),
|
||||||
|
("Lady", "Ladies"),
|
||||||
|
("Leaf", "Leaves"),
|
||||||
|
("Loaf", "Loaves"),
|
||||||
|
("ability", "abilities"),
|
||||||
|
("account", "accounts"),
|
||||||
|
("advice", "advice"),
|
||||||
|
("age", "ages"),
|
||||||
|
("agent", "agents"),
|
||||||
|
("alumna", "alumnae"),
|
||||||
|
("alumni", "alumni"),
|
||||||
|
("alumnus", "alumni"),
|
||||||
|
("answer", "answers"),
|
||||||
|
("appendix", "appendices"),
|
||||||
|
("apple", "apples"),
|
||||||
|
("art", "arts"),
|
||||||
|
("artist", "artists"),
|
||||||
|
("attention", "attentions"),
|
||||||
|
("ax", "axes"),
|
||||||
|
("baby", "babies"),
|
||||||
|
("ball", "balls"),
|
||||||
|
("bank", "banks"),
|
||||||
|
("basis", "bases"),
|
||||||
|
("beauty", "beauties"),
|
||||||
|
("bed", "beds"),
|
||||||
|
("belief", "beliefs"),
|
||||||
|
("berry", "berries"),
|
||||||
|
("bird", "birds"),
|
||||||
|
("book", "books"),
|
||||||
|
("bottle", "bottles"),
|
||||||
|
("box", "boxes"),
|
||||||
|
("boy", "boys"),
|
||||||
|
("branch", "branches"),
|
||||||
|
("brother", "brothers"),
|
||||||
|
("brush", "brushes"),
|
||||||
|
("bus", "buses"),
|
||||||
|
("business", "businesses"),
|
||||||
|
("cactus", "cacti"),
|
||||||
|
("cake", "cakes"),
|
||||||
|
("calf", "calves"),
|
||||||
|
("car", "cars"),
|
||||||
|
("care", "cares"),
|
||||||
|
("carrot", "carrots"),
|
||||||
|
("cart", "carts"),
|
||||||
|
("cat", "cats"),
|
||||||
|
("chair", "chairs"),
|
||||||
|
("chance", "chances"),
|
||||||
|
("change", "changes"),
|
||||||
|
("chef", "chefs"),
|
||||||
|
("chief", "chiefs"),
|
||||||
|
("child", "children"),
|
||||||
|
("church", "churches"),
|
||||||
|
("city", "cities"),
|
||||||
|
("class", "classes"),
|
||||||
|
("cloud", "clouds"),
|
||||||
|
("coach", "coaches"),
|
||||||
|
("comfort", "comforts"),
|
||||||
|
("company", "companies"),
|
||||||
|
("computer", "computers"),
|
||||||
|
("confidence", "confidences"),
|
||||||
|
("cookie", "cookies"),
|
||||||
|
("corpus", "corpuses"),
|
||||||
|
("country", "countries"),
|
||||||
|
("courage", "courages"),
|
||||||
|
("cow", "cows"),
|
||||||
|
("criterion", "criteria"),
|
||||||
|
("culture", "cultures"),
|
||||||
|
("cup", "cups"),
|
||||||
|
("danger", "dangers"),
|
||||||
|
("dart", "darts"),
|
||||||
|
("day", "days"),
|
||||||
|
("deer", "deer"),
|
||||||
|
("desk", "desks"),
|
||||||
|
("development", "developments"),
|
||||||
|
("dish", "dishes"),
|
||||||
|
("dog", "dogs"),
|
||||||
|
("door", "doors"),
|
||||||
|
("dream", "dreams"),
|
||||||
|
("education", "educations"),
|
||||||
|
("egg", "eggs"),
|
||||||
|
("elephant", "elephants"),
|
||||||
|
("employee", "employees"),
|
||||||
|
("energy", "energies"),
|
||||||
|
("entertainment", "entertainments"),
|
||||||
|
("exam", "exams"),
|
||||||
|
("experience", "experiences"),
|
||||||
|
("family", "families"),
|
||||||
|
("farm", "farms"),
|
||||||
|
("father", "fathers"),
|
||||||
|
("fish", "fish"),
|
||||||
|
("floor", "floors"),
|
||||||
|
("flower", "flowers"),
|
||||||
|
("fly", "flies"),
|
||||||
|
("focus", "focuses"),
|
||||||
|
("foot", "feet"),
|
||||||
|
("fork", "forks"),
|
||||||
|
("fox", "foxes"),
|
||||||
|
("freedom", "freedoms"),
|
||||||
|
("friend", "friends"),
|
||||||
|
("future", "futures"),
|
||||||
|
("game", "games"),
|
||||||
|
("garden", "gardens"),
|
||||||
|
("gas", "gases"),
|
||||||
|
("gift", "gifts"),
|
||||||
|
("girl", "girls"),
|
||||||
|
("glass", "glasses"),
|
||||||
|
("goat", "goats"),
|
||||||
|
("goose", "geese"),
|
||||||
|
("grass", "grasses"),
|
||||||
|
("guy", "guys"),
|
||||||
|
("half", "halves"),
|
||||||
|
("hand", "hands"),
|
||||||
|
("hat", "hats"),
|
||||||
|
("head", "heads"),
|
||||||
|
("health", "healths"),
|
||||||
|
("help", "helps"),
|
||||||
|
("hero", "heroes"),
|
||||||
|
("history", "histories"),
|
||||||
|
("holiday", "holidays"),
|
||||||
|
("hope", "hopes"),
|
||||||
|
("horse", "horses"),
|
||||||
|
("house", "houses"),
|
||||||
|
("idea", "ideas"),
|
||||||
|
("image", "images"),
|
||||||
|
("information", "information"),
|
||||||
|
("interest", "interests"),
|
||||||
|
("island", "islands"),
|
||||||
|
("journey", "journeys"),
|
||||||
|
("joy", "joys"),
|
||||||
|
("justice", "justices"),
|
||||||
|
("key", "keys"),
|
||||||
|
("keyboard", "keyboards"),
|
||||||
|
("king", "kings"),
|
||||||
|
("kiss", "kisses"),
|
||||||
|
("kitchen", "kitchens"),
|
||||||
|
("knife", "knives"),
|
||||||
|
("knowledge", "knowledges"),
|
||||||
|
("lady", "ladies"),
|
||||||
|
("lamp", "lamps"),
|
||||||
|
("laptop", "laptops"),
|
||||||
|
("law", "laws"),
|
||||||
|
("leaf", "leaves"),
|
||||||
|
("learning", "learnings"),
|
||||||
|
("leg", "legs"),
|
||||||
|
("letter", "letters"),
|
||||||
|
("life", "lives"),
|
||||||
|
("light", "lights"),
|
||||||
|
("line", "lines"),
|
||||||
|
("lion", "lions"),
|
||||||
|
("loaf", "loaves"),
|
||||||
|
("love", "loves"),
|
||||||
|
("luck", "lucks"),
|
||||||
|
("man", "men"),
|
||||||
|
("map", "maps"),
|
||||||
|
("market", "markets"),
|
||||||
|
("match", "matches"),
|
||||||
|
("memory", "memories"),
|
||||||
|
("milk", "milks"),
|
||||||
|
("money", "money"),
|
||||||
|
("monitor", "monitors"),
|
||||||
|
("month", "months"),
|
||||||
|
("mosquito", "mosquitoes"),
|
||||||
|
("mother", "mothers"),
|
||||||
|
("mountain", "mountains"),
|
||||||
|
("mouse", "mice"),
|
||||||
|
("movie", "movies"),
|
||||||
|
("name", "names"),
|
||||||
|
("nation", "nations"),
|
||||||
|
("neck", "necks"),
|
||||||
|
("night", "nights"),
|
||||||
|
("nucleus", "nuclei"),
|
||||||
|
("ocean", "oceans"),
|
||||||
|
("octopi", "octopi"),
|
||||||
|
("octopodes", "octopodes"),
|
||||||
|
("octopus", "octopuses"),
|
||||||
|
("office", "offices"),
|
||||||
|
("onion", "onions"),
|
||||||
|
("opinion", "opinions"),
|
||||||
|
("orange", "oranges"),
|
||||||
|
("page", "pages"),
|
||||||
|
("park", "parks"),
|
||||||
|
("party", "parties"),
|
||||||
|
("peace", "peaces"),
|
||||||
|
("peach", "peaches"),
|
||||||
|
("pen", "pens"),
|
||||||
|
("person", "people"),
|
||||||
|
("phenomenon", "phenomena"),
|
||||||
|
("phone", "phones"),
|
||||||
|
("photo", "photos"),
|
||||||
|
("piano", "pianos"),
|
||||||
|
("picture", "pictures"),
|
||||||
|
("pig", "pigs"),
|
||||||
|
("place", "places"),
|
||||||
|
("plane", "planes"),
|
||||||
|
("plant", "plants"),
|
||||||
|
("plate", "plates"),
|
||||||
|
("play", "plays"),
|
||||||
|
("player", "players"),
|
||||||
|
("pocket", "pockets"),
|
||||||
|
("potato", "potatoes"),
|
||||||
|
("power", "powers"),
|
||||||
|
("printer", "printers"),
|
||||||
|
("problem", "problems"),
|
||||||
|
("program", "programs"),
|
||||||
|
("proof", "proofs"),
|
||||||
|
("puppy", "puppies"),
|
||||||
|
("queen", "queens"),
|
||||||
|
("quiz", "quizzes"),
|
||||||
|
("radio", "radios"),
|
||||||
|
("rain", "rains"),
|
||||||
|
("respect", "respects"),
|
||||||
|
("responsibility", "responsibilities"),
|
||||||
|
("river", "rivers"),
|
||||||
|
("road", "roads"),
|
||||||
|
("roof", "roofs"),
|
||||||
|
("room", "rooms"),
|
||||||
|
("safe", "safes"),
|
||||||
|
("school", "schools"),
|
||||||
|
("scissors", "scissors"),
|
||||||
|
("sea", "seas"),
|
||||||
|
("series", "series"),
|
||||||
|
("sheep", "sheep"),
|
||||||
|
("ship", "ships"),
|
||||||
|
("shoe", "shoes"),
|
||||||
|
("shop", "shops"),
|
||||||
|
("shore", "shores"),
|
||||||
|
("sister", "sisters"),
|
||||||
|
("sky", "skies"),
|
||||||
|
("snow", "snows"),
|
||||||
|
("solo", "solos"),
|
||||||
|
("son", "sons"),
|
||||||
|
("song", "songs"),
|
||||||
|
("sound", "sounds"),
|
||||||
|
("spoon", "spoons"),
|
||||||
|
("star", "stars"),
|
||||||
|
("station", "stations"),
|
||||||
|
("stone", "stones"),
|
||||||
|
("store", "stores"),
|
||||||
|
("story", "stories"),
|
||||||
|
("street", "streets"),
|
||||||
|
("student", "students"),
|
||||||
|
("studio", "studios"),
|
||||||
|
("success", "successes"),
|
||||||
|
("sun", "suns"),
|
||||||
|
("syllabus", "syllabuses"),
|
||||||
|
("table", "tables"),
|
||||||
|
("taco", "tacos"),
|
||||||
|
("teacher", "teachers"),
|
||||||
|
("team", "teams"),
|
||||||
|
("television", "televisions"),
|
||||||
|
("test", "tests"),
|
||||||
|
("thief", "thieves"),
|
||||||
|
("thing", "things"),
|
||||||
|
("time", "times"),
|
||||||
|
("tomato", "tomatoes"),
|
||||||
|
("tooth", "teeth"),
|
||||||
|
("town", "towns"),
|
||||||
|
("toy", "toys"),
|
||||||
|
("tree", "trees"),
|
||||||
|
("trousers", "trousers"),
|
||||||
|
("truth", "truths"),
|
||||||
|
("umbrella", "umbrellas"),
|
||||||
|
("valley", "valleys"),
|
||||||
|
("victory", "victories"),
|
||||||
|
("video", "videos"),
|
||||||
|
("village", "villages"),
|
||||||
|
("wall", "walls"),
|
||||||
|
("watch", "watches"),
|
||||||
|
("water", "waters"),
|
||||||
|
("wealth", "wealths"),
|
||||||
|
("week", "weeks"),
|
||||||
|
("wife", "wives"),
|
||||||
|
("window", "windows"),
|
||||||
|
("wisdom", "wisdoms"),
|
||||||
|
("wish", "wishes"),
|
||||||
|
("wolf", "wolves"),
|
||||||
|
("woman", "women"),
|
||||||
|
("wood", "woods"),
|
||||||
|
("word", "words"),
|
||||||
|
("work", "works"),
|
||||||
|
("year", "years"),
|
||||||
|
("zero", "zeros"),
|
||||||
|
(none, none),
|
||||||
|
)
|
||||||
|
|
||||||
|
#for (singular, expected) in plural_tests {
|
||||||
|
let result = __pluralize(singular)
|
||||||
|
if result != expected {
|
||||||
|
panic(
|
||||||
|
"Pluralization failed for: "
|
||||||
|
+ (if singular == none { "none" } else { str(singular) })
|
||||||
|
+ ". Expected: "
|
||||||
|
+ (if expected == none { "none" } else { str(expected) })
|
||||||
|
+ ", got: "
|
||||||
|
+ (if result == none { "none" } else { str(result) })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#set page(height: auto, width: auto, margin: 1em)
|
||||||
|
|
||||||
|
"Success! All pluralizations determined properly!"
|
||||||
Reference in new issue
Block a user