Skip to content

Commit 8368635

Browse files
committed
🐛 Preserve empty months (with placeholders)
1 parent 25d94ae commit 8368635

File tree

3 files changed

+126
-25
lines changed

3 files changed

+126
-25
lines changed

dco.txt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Developer Certificate of Origin
2+
Version 1.1
3+
4+
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
5+
1 Letterman Drive
6+
Suite D4700
7+
San Francisco, CA, 94129
8+
9+
Everyone is permitted to copy and distribute verbatim copies of this
10+
license document, but changing it is not allowed.
11+
12+
13+
Developer's Certificate of Origin 1.1
14+
15+
By making a contribution to this project, I certify that:
16+
17+
(a) The contribution was created in whole or in part by me and I
18+
have the right to submit it under the open source license
19+
indicated in the file; or
20+
21+
(b) The contribution is based upon previous work that, to the best
22+
of my knowledge, is covered under an appropriate open source
23+
license and I have the right under that license to submit that
24+
work with modifications, whether created in whole or in part
25+
by me, under the same open source license (unless I am
26+
permitted to submit under a different license), as indicated
27+
in the file; or
28+
29+
(c) The contribution was provided directly to me by some other
30+
person who certified (a), (b) or (c) and I have not modified
31+
it.
32+
33+
(d) I understand and agree that this project and the contribution
34+
are public and that a record of the contribution (including all
35+
personal information I submit with it, including my sign-off) is
36+
maintained indefinitely and may be redistributed consistent with
37+
this project or the open source license(s) involved.

src/domainsUpdateCalendars.ts

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,43 @@ DOMAIN_LIST: JSON payload; Array containing domain records.
1212
interface CalendarEntry {
1313
day: number;
1414
description: string;
15+
isPlaceholder?: boolean;
1516
}
1617

1718
interface CalendarMonth {
1819
monthName: string;
1920
entries: CalendarEntry[];
2021
}
2122

23+
function formatMonthEntries(
24+
lines: string[],
25+
monthName: string,
26+
entries: CalendarEntry[],
27+
): void {
28+
const realEntries = entries.filter((e) => !e.isPlaceholder);
29+
const hasPlaceholder = entries.some((e) => e.isPlaceholder);
30+
31+
lines.push(`## ${monthName}`);
32+
lines.push("");
33+
34+
if (realEntries.length === 0) {
35+
// Preserve placeholder for empty sections
36+
if (hasPlaceholder) {
37+
lines.push("- .");
38+
}
39+
} else {
40+
// Sort entries by day
41+
const sortedEntries = [...realEntries].sort((a, b) => a.day - b.day);
42+
43+
for (const entry of sortedEntries) {
44+
const dayStr = entry.day.toString().padStart(2, "0");
45+
lines.push(`- ${dayStr}: ${entry.description}`);
46+
}
47+
}
48+
49+
lines.push("");
50+
}
51+
2252
const MONTH_NAMES = [
2353
"January",
2454
"February",
@@ -56,6 +86,13 @@ export function parseCalendarFile(content: string): Map<string, CalendarMonth> {
5686
const day = Number.parseInt(entryMatch[1], 10);
5787
const description = entryMatch[2].trim();
5888
currentMonth.entries.push({ day, description });
89+
} else if (line.match(/^-\s+\.$/)) {
90+
// Preserve placeholder entries (- .)
91+
currentMonth.entries.push({
92+
day: 0,
93+
description: ".",
94+
isPlaceholder: true,
95+
});
5996
}
6097
}
6198
}
@@ -115,39 +152,28 @@ export function formatCalendarFile(
115152
// First output custom sections (not in MONTH_NAMES)
116153
for (const [monthName, month] of months) {
117154
if (MONTH_NAMES.includes(monthName)) continue;
118-
if (month.entries.length === 0) continue;
119-
120-
lines.push(`## ${monthName}`);
121-
lines.push("");
122155

123-
// Sort entries by day
124-
const sortedEntries = [...month.entries].sort((a, b) => a.day - b.day);
156+
const realEntries = month.entries.filter((e) => !e.isPlaceholder);
157+
const hasPlaceholder = month.entries.some((e) => e.isPlaceholder);
125158

126-
for (const entry of sortedEntries) {
127-
const dayStr = entry.day.toString().padStart(2, "0");
128-
lines.push(`- ${dayStr}: ${entry.description}`);
129-
}
159+
// Skip custom sections with no entries at all
160+
if (realEntries.length === 0 && !hasPlaceholder) continue;
130161

131-
lines.push("");
162+
formatMonthEntries(lines, monthName, month.entries);
132163
}
133164

134165
// Then output standard months in order
135166
for (const monthName of MONTH_NAMES) {
136167
const month = months.get(monthName);
137-
if (!month || month.entries.length === 0) continue;
138-
139-
lines.push(`## ${monthName}`);
140-
lines.push("");
168+
if (!month) continue;
141169

142-
// Sort entries by day
143-
const sortedEntries = [...month.entries].sort((a, b) => a.day - b.day);
170+
const realEntries = month.entries.filter((e) => !e.isPlaceholder);
171+
const hasPlaceholder = month.entries.some((e) => e.isPlaceholder);
144172

145-
for (const entry of sortedEntries) {
146-
const dayStr = entry.day.toString().padStart(2, "0");
147-
lines.push(`- ${dayStr}: ${entry.description}`);
148-
}
173+
// Skip months with no entries and no placeholder
174+
if (realEntries.length === 0 && !hasPlaceholder) continue;
149175

150-
lines.push("");
176+
formatMonthEntries(lines, monthName, month.entries);
151177
}
152178

153179
return lines.join("\n");

test/domainsUpdateCalendars.test.ts

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,19 @@ describe("parseCalendarFile", () => {
7070
const result = parseCalendarFile(content);
7171

7272
expect(result.size).toBe(2);
73-
expect(result.get("May")?.entries).toHaveLength(0); // '.' is not a valid day entry
74-
expect(result.get("June")?.entries).toHaveLength(0);
73+
// Placeholder entries are now parsed and preserved
74+
expect(result.get("May")?.entries).toHaveLength(1);
75+
expect(result.get("May")?.entries[0]).toEqual({
76+
day: 0,
77+
description: ".",
78+
isPlaceholder: true,
79+
});
80+
expect(result.get("June")?.entries).toHaveLength(1);
81+
expect(result.get("June")?.entries[0]).toEqual({
82+
day: 0,
83+
description: ".",
84+
isPlaceholder: true,
85+
});
7586
});
7687

7788
it("should handle a custom Monthly section", () => {
@@ -313,7 +324,7 @@ describe("formatCalendarFile", () => {
313324
expect(day22Index).toBeGreaterThan(day16Index);
314325
});
315326

316-
it("should skip empty months", () => {
327+
it("should skip months with no entries and no placeholder", () => {
317328
const months = new Map();
318329
months.set("January", {
319330
monthName: "January",
@@ -335,6 +346,33 @@ describe("formatCalendarFile", () => {
335346
expect(result).toContain("## March");
336347
});
337348

349+
it("should preserve placeholder entries for empty months", () => {
350+
const months = new Map();
351+
months.set("January", {
352+
monthName: "January",
353+
entries: [{ day: 24, description: "Some event" }],
354+
});
355+
months.set("February", {
356+
monthName: "February",
357+
entries: [{ day: 0, description: ".", isPlaceholder: true }],
358+
});
359+
months.set("March", {
360+
monthName: "March",
361+
entries: [{ day: 15, description: "Another event" }],
362+
});
363+
364+
const result = formatCalendarFile(months, 2027);
365+
366+
expect(result).toContain("## January");
367+
expect(result).toContain("## February");
368+
expect(result).toContain("## March");
369+
370+
// February should have the placeholder
371+
const lines = result.split("\n");
372+
const febIndex = lines.indexOf("## February");
373+
expect(lines[febIndex + 2]).toBe("- .");
374+
});
375+
338376
it("should format days with leading zeros", () => {
339377
const months = new Map();
340378
months.set("January", {

0 commit comments

Comments
 (0)