Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions apps/web/src/lib/smugmug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ const STOPWORDS = new Set([
"an",
]);

// Folder names are conventionally "YYYY-MM-DD-Event-Name". Strip that prefix
// before tokenizing rather than filtering every pure-digit token: an event
// name can BE a number ("The 912"), and a blanket digit filter erases it from
// the folder side too, leaving nothing to match against.
const DATE_PREFIX = /^(\d{4}-\d{2}-\d{2})[-_ ]?/;

interface FolderSummary {
urlName: string;
webUri: string;
Expand Down Expand Up @@ -77,10 +83,13 @@ export function matchEventFolder(
let bestUri: string | null = null;

for (const folder of folders) {
// Content tokens: strip pure-digit tokens (date prefix like 2026, 05, 17) from folder name
const contentTokens = tokenize(folder.urlName).filter(
(t) => !/^\d+$/.test(t)
);
// Drop the leading date prefix (e.g. "2026-04-25-") and tokenize the rest.
// Digits inside the name itself are kept — they can be the whole name.
const dateMatch = DATE_PREFIX.exec(folder.urlName);
const bareName = dateMatch
? folder.urlName.slice(dateMatch[0].length)
: folder.urlName;
const contentTokens = tokenize(bareName);
if (contentTokens.length === 0) continue;

const matchCount = eventTokens.filter((t) =>
Expand All @@ -93,8 +102,8 @@ export function matchEventFolder(
const reverse = matchCount / contentTokens.length;
const tScore = Math.max(forward, reverse);

// Parse date from UrlName prefix (e.g. "2026-04-25-blooming-cones")
const dateMatch = /^(\d{4}-\d{2}-\d{2})/.exec(folder.urlName);
// Reuse the prefix match above for date proximity; fall back to DateAdded
// for folders that don't follow the date-prefix convention.
const folderDate = dateMatch
? new Date(dateMatch[1] + "T00:00:00Z")
: new Date(folder.dateAdded);
Expand Down
92 changes: 92 additions & 0 deletions apps/web/tests/smugmug.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,98 @@ describe("matchEventFolder", () => {
const combinedLabel = matchEventFolder(combinedFolders, "Cone in 60 Seconds", combinedDate);
expect(combinedLabel).toBe(sessionA);
});

// An event name can consist entirely of a number ("The 912" — "the" is a
// stopword, leaving just "912"). The folder side used to strip every
// pure-digit token to drop the "YYYY-MM-DD-" prefix, which erased the 912
// from the folder name too, so no folder had any content token left to
// match and the photos link silently never rendered.
describe("numeric event names", () => {
const nineTwelveDate = new Date("2026-09-12T00:00:00Z");
const nineTwelveUri =
"https://rmrpca.smugmug.com/Autocross/2026/2026-09-12-The-912-Autocross";
const nineTwelveFolders = [
{
urlName: "2026-09-12-The-912-Autocross",
webUri: nineTwelveUri,
dateAdded: "2026-09-13T12:00:00Z",
},
];

it("matches an event whose only token is a number", () => {
expect(matchEventFolder(nineTwelveFolders, "The 912", nineTwelveDate)).toBe(
nineTwelveUri,
);
});

it("matches when the folder omits the leading article", () => {
expect(
matchEventFolder(
[
{
urlName: "2026-09-12-912-Autocross",
webUri: nineTwelveUri,
dateAdded: "2026-09-13T12:00:00Z",
},
],
"The 912",
nineTwelveDate,
),
).toBe(nineTwelveUri);
});

// A lone numeric token must not match anything that merely shares its date.
it("does not match a same-day folder with no shared token", () => {
expect(
matchEventFolder(
[
{
urlName: "2026-09-12-Fall-Finale",
webUri: "WRONG",
dateAdded: "2026-09-13T12:00:00Z",
},
],
"The 912",
nineTwelveDate,
),
).toBeNull();
});

// Date proximity still gates a perfect token score: 0.6 * 1.0 + 0.4 * 0
// is exactly the threshold, and the comparison is strictly greater-than.
it("does not match a same-named folder far from the event date", () => {
expect(
matchEventFolder(
[
{
urlName: "2026-07-04-The-912",
webUri: "WRONG",
dateAdded: "2026-07-05T12:00:00Z",
},
],
"The 912",
nineTwelveDate,
),
).toBeNull();
});

it("picks the date-nearest folder when several share the numeric token", () => {
expect(
matchEventFolder(
[
...nineTwelveFolders,
{
urlName: "2026-05-02-912-Tribute",
webUri: "WRONG",
dateAdded: "2026-05-03T12:00:00Z",
},
],
"The 912",
nineTwelveDate,
),
).toBe(nineTwelveUri);
});
});
});

// PR #99 review: the SMUGMUG_* env fallbacks (and the "rmrpca"/"Autocross"
Expand Down
Loading