57 lines
2.1 KiB
TypeScript
57 lines
2.1 KiB
TypeScript
import { parsePublishedDocumentForCommunityRuleDisplay } from "./publishedDocumentToDisplaySections";
|
||
import { RULE_SECTION_CATEGORY } from "./ruleSectionsFromMethodSelections";
|
||
import sharedTerms from "../../messages/en/create/sharedTerms.json";
|
||
|
||
const DESCRIPTION_MAX = 140;
|
||
|
||
/** Initials for the invite email disc when the group has no photo. */
|
||
export function communityInviteInitials(name: string): string {
|
||
const words = name
|
||
.trim()
|
||
.split(/\s+/)
|
||
.filter((word) => word.length > 0);
|
||
if (words.length === 0) return "·";
|
||
if (words.length === 1) {
|
||
const word = words[0] ?? "";
|
||
return word.slice(0, 2).toUpperCase();
|
||
}
|
||
const first = words[0]?.charAt(0) ?? "";
|
||
const second = words[1]?.charAt(0) ?? "";
|
||
return `${first}${second}`.toUpperCase();
|
||
}
|
||
|
||
/** Possessive for footer copy (`Share’s` / `Members’`). */
|
||
export function communityPossessive(name: string): string {
|
||
const trimmed = name.trim();
|
||
if (trimmed.length === 0) return "this community’s";
|
||
if (/s$/i.test(trimmed)) return `${trimmed}’`;
|
||
return `${trimmed}’s`;
|
||
}
|
||
|
||
/** Community description on the invite card, cut at 140 characters. */
|
||
export function clipCommunityInviteDescription(
|
||
raw: string | null | undefined,
|
||
): string {
|
||
const trimmed = typeof raw === "string" ? raw.trim() : "";
|
||
if (trimmed.length <= DESCRIPTION_MAX) return trimmed;
|
||
return trimmed.slice(0, DESCRIPTION_MAX).trimEnd();
|
||
}
|
||
|
||
/** Tag on the invite Rule card (`3 VALUES AND 6 CARDS`). Shared terms do not count. */
|
||
export function inviteRuleCountsLabel(document: unknown): string {
|
||
const sections = parsePublishedDocumentForCommunityRuleDisplay(document);
|
||
let values = 0;
|
||
let cards = 0;
|
||
for (const section of sections) {
|
||
const n = section.entries.length;
|
||
if (section.categoryName === RULE_SECTION_CATEGORY.values) {
|
||
values += n;
|
||
} else if (section.categoryName !== sharedTerms.sectionTitle) {
|
||
cards += n;
|
||
}
|
||
}
|
||
const valuePart = values === 1 ? "1 VALUE" : `${values} VALUES`;
|
||
const cardPart = cards === 1 ? "1 CARD" : `${cards} CARDS`;
|
||
return `${valuePart} AND ${cardPart}`;
|
||
}
|