@@ -168,14 +168,54 @@ func Merge(fsys fs.FS) (*md.Document, error) {
168
168
addLines (b , delta )
169
169
}
170
170
}
171
- doc .Blocks = append (doc .Blocks , fd .Blocks ... )
171
+ // Append non-empty blocks to the result document.
172
+ for _ , b := range fd .Blocks {
173
+ if _ , ok := b .(* md.Empty ); ! ok {
174
+ doc .Blocks = append (doc .Blocks , b )
175
+ }
176
+ }
172
177
// TODO(jba): merge links
173
178
// TODO(jba): add headings for package sections under "Minor changes to the library".
174
179
}
175
- // TODO(jba): remove headings with empty contents
180
+ // Remove headings with empty contents.
181
+ doc .Blocks = removeEmptySections (doc .Blocks )
176
182
return doc , nil
177
183
}
178
184
185
+ // removeEmptySections removes headings with no content. A heading has no content
186
+ // if there are no blocks between it and the next heading at the same level, or the
187
+ // end of the document.
188
+ func removeEmptySections (bs []md.Block ) []md.Block {
189
+ res := bs [:0 ]
190
+ delta := 0 // number of lines by which to adjust positions
191
+
192
+ // Remove preceding headings at same or higher level; they are empty.
193
+ rem := func (level int ) {
194
+ for len (res ) > 0 {
195
+ last := res [len (res )- 1 ]
196
+ if lh , ok := last .(* md.Heading ); ok && lh .Level >= level {
197
+ res = res [:len (res )- 1 ]
198
+ // Adjust subsequent block positions by the size of this block
199
+ // plus 1 for the blank line between headings.
200
+ delta += lh .EndLine - lh .StartLine + 2
201
+ } else {
202
+ break
203
+ }
204
+ }
205
+ }
206
+
207
+ for _ , b := range bs {
208
+ if h , ok := b .(* md.Heading ); ok {
209
+ rem (h .Level )
210
+ }
211
+ addLines (b , - delta )
212
+ res = append (res , b )
213
+ }
214
+ // Remove empty headings at the end of the document.
215
+ rem (1 )
216
+ return res
217
+ }
218
+
179
219
func sortedMarkdownFilenames (fsys fs.FS ) ([]string , error ) {
180
220
var filenames []string
181
221
err := fs .WalkDir (fsys , "." , func (path string , d fs.DirEntry , err error ) error {
@@ -203,6 +243,8 @@ func lastBlock(doc *md.Document) md.Block {
203
243
return doc .Blocks [len (doc .Blocks )- 1 ]
204
244
}
205
245
246
+ // addLines adds n lines to the position of b.
247
+ // n can be negative.
206
248
func addLines (b md.Block , n int ) {
207
249
pos := position (b )
208
250
pos .StartLine += n
@@ -248,3 +290,14 @@ func parseFile(fsys fs.FS, path string) (*md.Document, error) {
248
290
doc := NewParser ().Parse (in )
249
291
return doc , nil
250
292
}
293
+
294
+ // headingIndex returns the index in bs of the first heading at the given level,
295
+ // or len(bs) if there isn't one.
296
+ func headingIndex (bs []md.Block , level int ) int {
297
+ for i , b := range bs {
298
+ if h , ok := b .(* md.Heading ); ok && h .Level == level {
299
+ return i
300
+ }
301
+ }
302
+ return len (bs )
303
+ }
0 commit comments