@@ -12,13 +12,43 @@ DOMAIN_LIST: JSON payload; Array containing domain records.
1212interface CalendarEntry {
1313 day : number ;
1414 description : string ;
15+ isPlaceholder ?: boolean ;
1516}
1617
1718interface 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+
2252const 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" ) ;
0 commit comments