srctree

Ian Johnson parent 355cceeb 6dcbad78
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.

inlinesplit
lib/docs/wasm/markdown.zig added: 147, removed: 15, total 132
@@ -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
\\
,
\\<p>Test:</p>
\\<ul>
\\<li>a1</li>
\\<li>a2<ul>
\\<li>b1</li>
\\<li>b2</li>
\\</ul>
\\</li>
\\</ul>
\\<hr />
\\<p>Test:</p>
\\<ul>
\\<li>One
\\Two<ul>
\\<li>Three
\\Four
\\Five
\\Six</li>
\\</ul>
\\</li>
\\</ul>
\\<hr />
\\<p>None of these items are indented far enough from the previous one to
\\start a nested list:</p>
\\<ul>
\\<li>One</li>
\\<li>Two</li>
\\<li>Three</li>
\\<li>Four</li>
\\<li>Five</li>
\\<li>Six</li>
\\<li>Seven</li>
\\<li>Eight</li>
\\<li>Nine</li>
\\</ul>
\\<hr />
\\<ul>
\\<li>One<ul>
\\<li>Two<ul>
\\<li>Three<ul>
\\<li>Four</li>
\\</ul>
\\</li>
\\</ul>
\\</li>
\\<li>Five<ul>
\\<li>Six</li>
\\</ul>
\\</li>
\\</ul>
\\</li>
\\<li>Seven</li>
\\</ul>
\\
);
}
 
test "tables" {
try testRender(
\\| Operator | Meaning |
@@ -394,6 +494,10 @@ test "tables" {
\\| :--- | :----: | ----: |
\\| Left | Center | Right |
\\
\\ | One | Two |
\\ | Three | Four |
\\ | Five | Six |
\\
,
\\<table>
\\<tr>
@@ -446,6 +550,20 @@ test "tables" {
\\<td style="text-align: right">Right</td>
\\</tr>
\\</table>
\\<table>
\\<tr>
\\<td>One</td>
\\<td>Two</td>
\\</tr>
\\<tr>
\\<td>Three</td>
\\<td>Four</td>
\\</tr>
\\<tr>
\\<td>Five</td>
\\<td>Six</td>
\\</tr>
\\</table>
\\
);
}
@@ -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:
\\ ```
\\
,
\\<pre><code>Hello, world!
@@ -608,6 +734,12 @@ test "code blocks" {
\\ try std.testing.expect(2 + 2 == 4);
\\}
\\</code></pre>
\\<pre><code>Indentation up to the fence is removed.
\\ Like this.
\\Doesn't need to be fully indented.
\\</code></pre>
\\<pre><code>Overly indented closing fence is fine:
\\</code></pre>
\\
);
}
 
lib/docs/wasm/markdown/Parser.zig added: 147, removed: 15, total 132
@@ -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..],
};
}