From 6dcbad780cb716fe1d2a4b2ce201a757ea7f03a4 Mon Sep 17 00:00:00 2001 From: Ian Johnson Date: Mon, 8 Apr 2024 05:49:22 -0400 Subject: [PATCH] Autodoc: fix Markdown indented lists (#19577) Previously, indentation was not being handled correctly in some cases, causing examples such as `std.json.WriteStream` to be rendered with improper list nesting. Additionally, some more test cases have been added to ensure indentation (or lack of indentation) is handled correctly in some other constructs. --- lib/docs/wasm/markdown.zig | 132 ++++++++++++++++++++++++++++++ lib/docs/wasm/markdown/Parser.zig | 26 +++--- 2 files changed, 145 insertions(+), 13 deletions(-) diff --git a/lib/docs/wasm/markdown.zig b/lib/docs/wasm/markdown.zig index e0bf4bbaac..c7dfb15073 100644 --- a/lib/docs/wasm/markdown.zig +++ b/lib/docs/wasm/markdown.zig @@ -376,6 +376,106 @@ test "lists with block content" { ); } +test "indented lists" { + try testRender( + \\Test: + \\ * a1 + \\ * a2 + \\ * b1 + \\ * b2 + \\ + \\--- + \\ + \\ Test: + \\ - One + \\Two + \\ - Three + \\Four + \\ Five + \\Six + \\ + \\--- + \\ + \\None of these items are indented far enough from the previous one to + \\start a nested list: + \\ - One + \\ - Two + \\ - Three + \\ - Four + \\ - Five + \\ - Six + \\ - Seven + \\ - Eight + \\ - Nine + \\ + \\--- + \\ + \\ - One + \\ - Two + \\ - Three + \\ - Four + \\ - Five + \\ - Six + \\- Seven + \\ + , + \\

Test:

+ \\ + \\
+ \\

Test:

+ \\ + \\
+ \\

None of these items are indented far enough from the previous one to + \\start a nested list:

+ \\ + \\
+ \\ + \\ + ); +} + test "tables" { try testRender( \\| Operator | Meaning | @@ -394,6 +494,10 @@ test "tables" { \\| :--- | :----: | ----: | \\| Left | Center | Right | \\ + \\ | One | Two | + \\ | Three | Four | + \\ | Five | Six | + \\ , \\ \\ @@ -446,6 +550,20 @@ test "tables" { \\ \\ \\
Right
+ \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\ + \\
OneTwo
ThreeFour
FiveSix
\\ ); } @@ -597,6 +715,14 @@ test "code blocks" { \\ try std.testing.expect(2 + 2 == 4); \\} \\``` + \\ ``` + \\ Indentation up to the fence is removed. + \\ Like this. + \\ Doesn't need to be fully indented. + \\ ``` + \\``` + \\Overly indented closing fence is fine: + \\ ``` \\ , \\
Hello, world!
@@ -608,6 +734,12 @@ test "code blocks" {
         \\    try std.testing.expect(2 + 2 == 4);
         \\}
         \\
+ \\
Indentation up to the fence is removed.
+        \\     Like this.
+        \\Doesn't need to be fully indented.
+        \\
+ \\
Overly indented closing fence is fine:
+        \\
\\ ); } diff --git a/lib/docs/wasm/markdown/Parser.zig b/lib/docs/wasm/markdown/Parser.zig index 9b377dce34..7f463224be 100644 --- a/lib/docs/wasm/markdown/Parser.zig +++ b/lib/docs/wasm/markdown/Parser.zig @@ -152,7 +152,7 @@ const Block = struct { "" else null, - .table => if (unindented.len > 0) unindented else null, + .table => if (unindented.len > 0) line else null, .table_row => null, .heading => null, .code_block => code_block: { @@ -168,7 +168,7 @@ const Block = struct { unindented[1..] else null, - .paragraph => if (unindented.len > 0) unindented else null, + .paragraph => if (unindented.len > 0) line else null, .thematic_break => null, }; } @@ -225,7 +225,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void { p.pending_blocks.items.len > 0 and p.pending_blocks.getLast().tag == .paragraph) { - try p.addScratchStringLine(rest_line); + try p.addScratchStringLine(mem.trimLeft(u8, rest_line, " \t")); return; } @@ -271,8 +271,8 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void { // loose, since we might just be looking at a blank line after the // end of the last item in the list. The final determination will be // made when appending the next child of the list or list item. - const maybe_containing_list = if (p.pending_blocks.items.len > 0 and p.pending_blocks.getLast().tag == .list_item) - &p.pending_blocks.items[p.pending_blocks.items.len - 2] + const maybe_containing_list_index = if (p.pending_blocks.items.len > 0 and p.pending_blocks.getLast().tag == .list_item) + p.pending_blocks.items.len - 2 else null; @@ -285,8 +285,8 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void { try p.addScratchStringLine(rest_line_trimmed); } - if (maybe_containing_list) |containing_list| { - containing_list.data.list.last_line_blank = rest_line_trimmed.len == 0; + if (maybe_containing_list_index) |containing_list_index| { + p.pending_blocks.items[containing_list_index].data.list.last_line_blank = rest_line_trimmed.len == 0; } }, .inlines => try p.addScratchStringLine(rest_line_trimmed), @@ -515,7 +515,7 @@ fn startBlock(p: *Parser, line: []const u8) !?BlockStart { .data = .{ .list_item = .{ .marker = list_item.marker, .number = list_item.number, - .continuation_indent = list_item.continuation_indent, + .continuation_indent = indent + list_item.marker_len, } }, .rest = list_item.rest, }; @@ -559,7 +559,7 @@ fn startBlock(p: *Parser, line: []const u8) !?BlockStart { const ListItemStart = struct { marker: Block.Data.ListMarker, number: u30, - continuation_indent: usize, + marker_len: usize, rest: []const u8, }; @@ -568,21 +568,21 @@ fn startListItem(unindented_line: []const u8) ?ListItemStart { return .{ .marker = .@"-", .number = undefined, - .continuation_indent = 2, + .marker_len = 2, .rest = unindented_line[2..], }; } else if (mem.startsWith(u8, unindented_line, "* ")) { return .{ .marker = .@"*", .number = undefined, - .continuation_indent = 2, + .marker_len = 2, .rest = unindented_line[2..], }; } else if (mem.startsWith(u8, unindented_line, "+ ")) { return .{ .marker = .@"+", .number = undefined, - .continuation_indent = 2, + .marker_len = 2, .rest = unindented_line[2..], }; } @@ -600,7 +600,7 @@ fn startListItem(unindented_line: []const u8) ?ListItemStart { return .{ .marker = marker, .number = number, - .continuation_indent = number_end + 2, + .marker_len = number_end + 2, .rest = after_number[2..], }; }