One station reaches the log SHOUTED by QRZ, lower-cased by a hurried
operator and in whatever case an imported ADIF carried, so the same name
appears three ways across a log. Name and QTH are now title-cased word by
word; Comment and Note only get a capital first letter, because the rest
routinely holds callsigns and modes ("TNX QSO F5ABC, FT8 59") that
lower-casing would destroy.
Normalised on blur, never per keystroke — rewriting the value mid-word
fights the typist (the controlled-input trap in CLAUDE.md). Applied in
both entry layouts and in the QSO editor, since leaving the editor alone
would just reintroduce the mess on the first correction.
The Recent QSOs box only ever searches callsigns, so it upper-cases as
you type and carries an inline clear button.
29 lines
1.3 KiB
TypeScript
29 lines
1.3 KiB
TypeScript
// Capitalisation helpers for the free-text QSO fields (Name / QTH / Comment /
|
||
// Note).
|
||
//
|
||
// The same station reaches the log SHOUTED by QRZ, lower-cased by a hurried
|
||
// operator, and in whatever case the other logger stored it in an imported
|
||
// ADIF — so one callsign ends up as "JEAN", "jean" and "Jean" across a log,
|
||
// and sorting or reading a QTH column becomes a mess.
|
||
//
|
||
// Both helpers are meant to run on BLUR, never per keystroke: rewriting the
|
||
// value while the operator is still typing a word fights them mid-word (see
|
||
// the controlled-input note in CLAUDE.md).
|
||
|
||
// titleCase upper-cases the first letter of every word and lower-cases the
|
||
// rest. Separators are kept, so "SAINT-JULIEN" → "Saint-Julien" and
|
||
// "o'brien" → "O'Brien".
|
||
export function titleCase(s: string): string {
|
||
return s
|
||
.toLowerCase()
|
||
.replace(/(^|[\s\-'’/.])(\p{L})/gu, (_m, sep: string, ch: string) => sep + ch.toUpperCase());
|
||
}
|
||
|
||
// sentenceCase upper-cases the first letter and leaves everything after it as
|
||
// typed. A comment routinely carries callsigns, modes and abbreviations
|
||
// ("TNX QSO F5ABC, FT8 59") that lower-casing would quietly destroy — which is
|
||
// why this is NOT titleCase.
|
||
export function sentenceCase(s: string): string {
|
||
return s.replace(/^(\s*)(\p{L})/u, (_m, sp: string, ch: string) => sp + ch.toUpperCase());
|
||
}
|