@@ -12,7 +12,7 @@ local function find_section_at_row(row)
12
12
local node = nodes .get_at_row (row )
13
13
if not node then return nil end
14
14
15
- local current = node
15
+ local current = node --[[ @as TSNode? ]]
16
16
while current do
17
17
if current :type () == " section" then
18
18
return current
@@ -209,28 +209,42 @@ function M.get_prev_outer_heading(row)
209
209
if not util .is_markdown_file () then return nil , nil end
210
210
if not heading .is_heading (row ) then return nil , nil end
211
211
212
- local section = find_section_at_row (row )
213
- if not section then return nil , nil end
214
-
215
- local current_level = get_section_level (section )
212
+ local current_level = heading .heading_level (row )
216
213
if not current_level or current_level <= 1 then return nil , nil end
217
214
218
- -- Find parent section with level current_level - 1
219
- local parent = section :parent ()
220
- while parent do
221
- if parent :type () == " section" then
222
- local parent_level = get_section_level (parent )
223
- if parent_level == current_level - 1 then
224
- local heading_row = get_section_heading_row (parent )
225
- if heading_row then
226
- return nodes .get_at_row (heading_row ), heading_row
215
+ -- For out-of-order headings, we need to find the nearest previous heading
216
+ -- with a lower level (not necessarily direct AST parent)
217
+ local root = vim .treesitter .get_parser ():parse ()[1 ]:root ()
218
+ local target_level = current_level - 1
219
+ local best_match = nil
220
+
221
+ local function find_in_node (node )
222
+ if node :type () == " section" then
223
+ local section_level = get_section_level (node )
224
+ local section_row = get_section_heading_row (node )
225
+
226
+ if section_row and section_row < row and section_level and section_level <= target_level then
227
+ -- Update best match if this is closer or has a higher level (but still <= target_level)
228
+ if not best_match or section_row > best_match .row or
229
+ (section_row == best_match .row and section_level > best_match .level ) then
230
+ best_match = { row = section_row , level = section_level }
227
231
end
228
232
end
229
233
end
230
- parent = parent :parent ()
234
+
235
+ -- Recursively search children
236
+ for child in node :iter_children () do
237
+ find_in_node (child )
238
+ end
239
+ end
240
+
241
+ find_in_node (root )
242
+
243
+ if best_match then
244
+ return nodes .get_at_row (best_match .row ), best_match .row
231
245
end
232
246
233
247
return nil , nil
234
248
end
235
249
236
- return M
250
+ return M
0 commit comments