The pack
englishWords
function englishWords(options: EnglishWordsOptions = {}): Pack<{ words: WordsApi }>
The english-words pack: game.words, the Common English Lexicon (69,223 words) and lists of your own, with exact,
pattern, prefix, anagram and fuzzy search. Headless; needs no world or renderer.
Helpers
ALPHABET
const ALPHABET: "abcdefghijklmnopqrstuvwxyz"
The 26 letters every word is made of, in order.
CEL_COMMIT
const CEL_COMMIT: "5836e959e56bac99547345837aacbde8f2a623b8"
The CEL commit these words come from.
CEL_COUNTS
const CEL_COUNTS: Readonly<Record<number, number>>
How many words of each length, 69223 in all.
createWordList
function createWordList(source: Iterable<string> | string, options: WordListOptions = {}): WordList
A list of your own words: an array, or text as parseWords reads it. Each entry is normalised as normaliseWord
does (so "Tyrannosaurus Rex" becomes tyrannosaurusrex) and duplicates are kept once. Throws a RangeError for an
entry that is not a word, unless options.invalid is 'skip'.
editDistance
function editDistance(a: string, b: string): number
The fewest single-letter edits that turn a into b: an insertion, a deletion, a change, or two neighbouring
letters swapped (hte → the is 1). Case and the characters normaliseWord drops are ignored. This is the
distance the fuzzy search ranks by.
englishLexicon
function englishLexicon(options: EnglishOptions = {}): WordList
The Common English Lexicon: 69,223 English words of 2 to 45 letters, chosen as common for word games, by Eric Smith
and Kenji Matsumoto (MIT licence). By default the 86 rated offensive (slurs, strong swearing, explicit terms) are
left out; rating: 'family' leaves out 147 milder ones too, and 'unfiltered' keeps all. Shared and decoded a length
at a time, the first time a length is asked for. With options, a list narrowed to min..max letters with
include added and exclude taken out.
normaliseWord
function normaliseWord(text: string): string | null
A word's letters as they are stored: lower case, a-z only. Spaces, hyphens, apostrophes and full stops are dropped
and accents taken off ("T. Rex" → trex, "café" → cafe). Null when anything else is left or nothing is.
parseWords
function parseWords(text: string): string[]
The words in text: one entry per line, or separated by commas or semicolons. Blank entries and lines starting
with # are skipped. Entries are not normalised; createWordList does that.
word
function word(text: string): Word
A word from text: word('Crane').at(2) → 'a'. Throws a RangeError for anything but letters. Not checked against any list.
Functions
wordRating
function wordRating(word: string): WordRating | null
A lexicon word's rating: 'offensive' (slurs, strong swearing, explicit terms), 'mature' (milder swearing, sex,
the body, crime), or null for every other word. Rated for the words of the Common English Lexicon; any other text is
null. Case does not matter.
Classes
Word
class Word
One word, with questions about its letters: what is at a position, how often a letter appears, whether a partly
traced word is on its way to this one, and whether its letters can make another word. Make one with word(text)
or take one from a list (pick, sample, list.word). Immutable.
readonly text: string— The word in lower case, a-z only.constructor(text: string)— NormalisestextasnormaliseWorddoes. Throws a RangeError when it holds anything but letters.get length(): number— How many letters.get first(): string— The first letter.get last(): string— The last letter.get upper(): string— The word in capitals, as most word games show it.get letters(): ReadonlyArray<string>— The letters in order, one string each.get sorted(): string— The letters in alphabetical order, as one string: two words are anagrams when these are equal.at(index: number): string— The letter atindex, counting from 0; a negative index counts back from the end (-1 is the last letter). Throws a RangeError outside the word.is(index: number, letter: string): boolean— Isletteratindex(from 0; negative from the end)? False outside the word. Case does not matter.has(letter: string): boolean— Does the word containletter?count(letter: string): number— How many timesletterappears. Throws a RangeError for anything but one letter.positions(letter: string): number[]— Every position ofletter, from 0, in order.startsWith(part: string): boolean— Does the word start withpart? A traced or typed word that is still on its way to this one does.endsWith(part: string): boolean— Does the word end withpart?includes(part: string): boolean— Doespartappear anywhere in the word?next(part: string): string | null— The letter that comes afterpartwhenpartis the start of this word, else null (also whenpartis the whole word). What a hint shows a player halfway through tracing it.matches(pattern: string): boolean— Does the word fitpattern??,.or_is any letter,[abc]any of those,[^abc]any but those.canMake(other: string | Word): boolean— Canotherbe spelt with this word's letters, each used no more often than it appears here?listencan makesilent,tinandlest, nottilt. What a letter-wheel puzzle asks of its base word.isAnagramOf(other: string | Word): boolean— Isotherthe same letters in another order? A word is not an anagram of itself.equals(other: string | Word): boolean— The same word, ignoring case and the charactersnormaliseWorddrops?toString(): string— The word, lower case.toJSON(): string— The word, lower case, so a Word goes into a save as a plain string.
WordList
class WordList
A list of words, any size, from the English lexicon (englishLexicon) or your own (createWordList). Every word
is lower case, a-z only; every lookup ignores case. Immutable: filter, with and without return new lists.
readonly name: string— A name for messages and for telling lists apart.readonly size: number— How many words.readonly lengths: ReadonlyArray<number>— The lengths that have words, shortest first.constructor(name: string, counts: ReadonlyMap<number, number>, private readonly group: (length: number) => ReadonlyArray<string>)— UsecreateWordListorenglishLexiconrather than this.countsgives each length's word count andgroup(length)that length's words, sorted, when first asked for.ofLength(length: number): ReadonlyArray<string>— Every word oflengthletters, in alphabetical order. Empty for a length the list has none of.words(): string[]— Every word, shortest first, alphabetical within a length.has(text: string): boolean— Istextin the list? Case and the charactersnormaliseWorddrops do not matter.word(text: string): Word | null—textas aWordwhen it is in the list, else null.find(query: WordQuery = {}, limit = Infinity): string[]— Every word that matches, shortest first and alphabetical within a length, at mostlimitof them.count(query: WordQuery = {}): number— How many words match.first(query: WordQuery = {}): Word | null— The first word that matches, infind's order, as aWord, or null.isPrefix(prefix: string): boolean— Does any word start withprefix(or equal it)? What a grid solver asks before it goes a letter deeper, and what a game asks of a word the player is still tracing.completions(prefix: string, limit = Infinity): string[]— Words that start withprefix, in alphabetical order (not by length), at mostlimit.anagrams(letters: string): string[]— Words made of exactlyletters, rearranged (anagrams('least')→slate,stale,steal,tales…);lettersitself is left out.near(text: string, distance = 1, limit = Infinity): string[]— The words withindistanceedits oftext(an insertion, deletion, change or swap of two neighbours each), nearest first, then shortest, then alphabetical;textitself first when it is a word. What a "did you mean" needs. Default distance 1.closest(text: string, distance = 2): string | null— The nearest word totextwithindistanceedits (default 2), or null.textitself when it is a word.pick(rng: Rng, query: WordQuery = {}): Word— One matching word, chosen byrng. Throws a RangeError when nothing matches, naming the list and the query.sample(rng: Rng, count: number, query: WordQuery = {}): Word[]— Up tocountdifferent matching words, chosen byrng, in the order drawn. Fewer only when fewer match.filter(query: WordQuery, name = \${this.name} (filtered)`): WordList` — A new list of the words that match.with(words: Iterable<string>, name = this.name): WordList— A new list withwordsadded, normalised asnormaliseWorddoes. Throws a RangeError for an entry that is not a word.without(words: Iterable<string>, name = this.name): WordList— A new list withoutwords(any case).letterFrequency(): Readonly<Record<string, number>>— How often each letter appears across the list, a to z, as fractions that add up to 1. A letter grid that wants playable letters draws by these. Worked out once, the first time it is asked for.
Types
EnglishOptions
interface EnglishOptions
What englishLexicon and the pack's options take.
min?: number— Shortest word, in letters. Default 2, the shortest in the lexicon.max?: number— Longest word, in letters. Default 45, the longest in the lexicon.include?: ReadonlyArray<string>— Words to add (a game's own slang, names it allows). Normalised asnormaliseWorddoes.exclude?: ReadonlyArray<string>— Words to leave out (any case).rating?: RatingFilter— Which rated words to keep (seewordRating):'standard'(the default) leaves out slurs, strong swearing and explicit terms;'family'leaves out milder swearing and words about sex, the body and crime as well;'unfiltered'keeps every word of the lexicon.
EnglishWordsOptions
type EnglishWordsOptions = EnglishOptions
Manifest options: the game's own word list, game.words.lexicon, is the lexicon narrowed by these.
RatingFilter
type RatingFilter = 'standard' | 'family' | 'unfiltered'
Which words a list keeps: standard drops the offensive, family the mature too, unfiltered none.
WordListOptions
interface WordListOptions
How createWordList reads its words.
name?: string— A name for messages and for telling lists apart. Default'custom'.invalid?: 'throw' | 'skip'— What to do with an entry that is not a word of the letters a-z once normalised:'throw'(the default) or'skip'.rating?: RatingFilter— Leave out rated words (seewordRating):'standard','family', or'unfiltered'(the default: your list as given).
WordQuery
interface WordQuery
What to find in a list. Every field narrows it; leave a field out to ignore it. Letters may be given in either case. Results come in length order, then alphabetical.
length?: number— Exactly this many letters.min?: number— At least this many letters.max?: number— At most this many letters.startsWith?: string— Starts with these letters.endsWith?: string— Ends with these letters.contains?: string— Has these letters together somewhere.pattern?: string— Fits this pattern, which also fixes the length:?,.or_is any letter,[abc]any of those,[^abc]any but those (c?a[^s]e).from?: string— Can be spelt from these letters, each used no more often than it appears here: a letter rack or wheel (from: 'listen').only?: string— Uses no letters but these, as often as it likes (only: 'abcde').uses?: string— Contains every one of these letters at least once.without?: string— Contains none of these letters.exclude?: Iterable<string>— Leave these words out (any case).where?: (word: string) => boolean— Any other test, given the lower-case word.
WordRating
type WordRating = 'offensive' | 'mature'
How suitable a word is for a game's audience.
WordsApi
interface WordsApi
game.words: the game's word list, lists of your own, and seeded picks from the game's random source.
readonly lexicon: WordList— The game's word list: the English lexicon within the manifest'smin..maxletters,includeadded,excludetaken out.english(options?: EnglishOptions): WordList— The English lexicon narrowed differently fromlexicon(english({ min: 3, max: 8 })). The full lexicon with no options.list(source: Iterable<string> | string, options?: WordListOptions): WordList— A list of your own, from an array or from text (one word a line, or separated by commas). SeecreateWordList.loaded(key: string, options?: WordListOptions): WordList— A list from a file the loader fetched underkey: atextitem read aslistreads text, or ajsonitem holding an array of strings. Headless, where the loader fetches nothing, the list is empty. Throws for an unknown key or a JSON value that is not an array of strings.has(text: string): boolean— Istextinlexicon? Case does not matter.word(text: string): Word—textas aWord, whether or not any list holds it. Throws a RangeError for anything but letters.find(query?: WordQuery, list?: WordList): string[]— Every word inlist(defaultlexicon) that matches, shortest first, alphabetical within a length.pick(query?: WordQuery, list?: WordList): Word— One matching word fromlist(defaultlexicon), chosen by the game's random source. Throws a RangeError when nothing matches.sample(count: number, query?: WordQuery, list?: WordList): Word[]— Up tocountdifferent matching words fromlist(defaultlexicon), chosen by the game's random source.distance(a: string, b: string): number— The fewest single-letter edits between two words; seeeditDistance.readonly rng: Rng— The random sourcepickandsampledraw from: the game's, forked as'words'.


