Recognize multi-line unattached attributes #108
Conversation
bef8cc7 to
499e59c
Compare
test rendering of attributes that span multiple lines and are not attached to any element Assisted-by: Claude:glm-5.1 Signed-off-by: Chen Linxuan <me@black-desk.cn>
When an attribute block spans multiple lines (e.g. `{ .a\n }`), the
block parser only checked the first line with attr::valid() and
classified it as a paragraph since the attribute was incomplete on that
line alone. Add a post-check in parse_block() that re-examines
multi-line paragraphs starting with `{` to see if the combined text
forms a valid attribute block.
Assisted-by: Claude:glm-5.1
Signed-off-by: Chen Linxuan <me@black-desk.cn>
499e59c to
4fa293b
Compare
When a paragraph starts with an incomplete attribute (e.g. `{#id
.class` without closing `}`), detect whether subsequent lines complete
it. If the completed attribute is followed by more content, split the
block: emit the attribute event first, then let the caller parse the
remaining lines as a separate paragraph block.
This resolves the multi-line block attributes test case from hellux#53.
Assisted-by: Claude Code:glm-5.1
Signed-off-by: Chen Linxuan <me@black-desk.cn>
4fa293b to
09658a0
Compare
hellux
left a comment
There was a problem hiding this comment.
There is a fuzzer that can be used to detect some bugs, it can be run with make afl. It can take a while to find some rare things so the CI step sometimes misses things because it only runs for one minute.
However, running it locally I found some errors after a few minutes, there seems to be an issue with multi-line attrs before a header, e.g:
# header 1
- list
{.attrs
}
# header 2yields
<section id="header-1">
<h1>header 1</h1>
<ul>
<li>
list
</li>
</section> <!-- this should be swapped -->
</ul> <!-- with this -->
<section id="header-2">
<h1>header 2</h1> <!-- missing class="attrs" -->
</section>The open_sections part does some manipulation of the events that may not interact with the multi-line attributes correctly.
| "{ .a }\n", // | ||
| ), | ||
| (Attributes(attrs![(AttributeKind::Class, "a")]), "{ .a }\n"), | ||
| ); |
There was a problem hiding this comment.
This case is covered in attr_block_dangling above.
| A paragraph | ||
| . | ||
| <p id="id" class="class" style="color:red">A paragraph</p> | ||
| ``` |
There was a problem hiding this comment.
This test already exists in the the djot_attributes.test file (test_html_ut symlinks it from reference implementation) so no need to add it here.
| " }\n", // | ||
| ), | ||
| (Attributes(attrs![(AttributeKind::Class, "a")]), "{ .a\n }"), | ||
| ); |
There was a problem hiding this comment.
May also try attributes in nested quotes:
> {#id .class
> style="color:red"}
This seems to crash now because we get the > as part of the attributes:
panicked at src/lib.rs:2646:30:
should be valid: 12
| ), | ||
| (Str("A paragraph".into()), "A paragraph"), | ||
| (End(Paragraph), ""), | ||
| ); |
There was a problem hiding this comment.
This should also work with nested blocks:
> {#id .class
> style="color:red"}
> A paragraph
but also crashes atm.
| " }\n", // | ||
| ), | ||
| (Attributes(attrs![(AttributeKind::Class, "a")]), "{ .a\n }"), | ||
| ); |
There was a problem hiding this comment.
May also try non-indented continuation. As per the syntax reference:
Block attributes have the same syntax as inline attributes, but if they don’t fit on one line, subsequent lines must be indented.
So
{.a
}
should be parsed as attributes, while
{.a
}
should not. Right now they seem to parsed as attributes with or without indentation.
| ), | ||
| (Str("A paragraph".into()), "A paragraph"), | ||
| (End(Paragraph), ""), | ||
| ); |
There was a problem hiding this comment.
Should also not allow non indented continuation, i.e.
{#id .class
style="color:red"}
A paragraph
should not be parsed as attributes.
No description provided.