documents: a picture shrinks within a narrow table cell; tree tests in their own file; test comments within ten words
CI / platforms (windows-latest) (push) Failing after 8s
CI / site (push) Successful in 22s
CI / crate (push) Failing after 11m42s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-12 05:23:55 -04:00
1 parent 4801555e0d
commit 2e196a10a7
4 files changed
+215 -206

No files matched your search

+2
View File
@@ -300,6 +300,7 @@ impl Draw<'_> {
let cell = |blocks: &[Node], column: usize, header: bool, cx: &App| {
div()
.flex_1()
.min_w_0()
.flex()
.px_3()
.py_1p5()
@@ -315,6 +316,7 @@ impl Draw<'_> {
})
.child(
div()
.max_w_full()
.flex()
.flex_col()
.gap_1()
+17 -6
View File
@@ -23,7 +23,7 @@ fn hit(page: usize) -> PageHit {
}
}
/// Three tall pages and the hits found; a press while pinning records the note asked.
/// Three tall pages and hits; a pinning press records notes.
struct Reader {
query: Entity<TextInput>,
width: f32,
@@ -60,7 +60,7 @@ fn open(cx: &mut TestAppContext) -> (Entity<Reader>, Noted, &mut VisualTestConte
open_with(400.0, None, cx)
}
/// Pages `width` points wide, with a hit on the second, current from the first frame when `current` says.
/// Pages `width` wide, a hit on page two, maybe current.
fn open_with(
width: f32,
current: Option<usize>,
@@ -86,7 +86,7 @@ fn settle(cx: &mut VisualTestContext) {
cx.run_until_parked();
}
/// A point on the pages, below the header and the find bar, at the view's middle.
/// A point on the pages, below the bars, mid-view.
fn on_pages(cx: &mut VisualTestContext) -> Point<Pixels> {
cx.update(|window, _| point(window.viewport_size().width / 2.0, px(300.0)))
}
@@ -102,7 +102,7 @@ fn wheel(down: f32, cx: &mut VisualTestContext) {
settle(cx);
}
/// Turns pinning on with the header's last button, then presses the pages at their middle; returns the note asked.
/// Turns pinning on, presses mid-page; the note asked.
fn pin(cx: &mut VisualTestContext, noted: &Noted) -> (usize, Point<f32>) {
let at = on_pages(cx);
pin_at(at, cx, noted)
@@ -143,7 +143,7 @@ fn a_note_lands_where_the_press_is_on_a_scrolled_page(cx: &mut TestAppContext) {
assert_eq!(scrolled.y, top.y + 150.0, "the press counts the scroll");
}
/// Scrolls `down`, makes the hit current, then pins a note at the same window point.
/// Scrolls `down`, makes the hit current, pins a note.
fn revealed(down: f32, cx: &mut TestAppContext) -> (usize, Point<f32>) {
let (reader, noted, cx) = open(cx);
if down > 0.0 {
@@ -201,7 +201,7 @@ fn a_hit_current_from_the_first_frame_comes_into_view(cx: &mut TestAppContext) {
assert_eq!(at_once, later);
}
/// A field outside a zen view, and how often Escape left zen.
/// A field outside zen, and the Escapes that left zen.
struct Zen {
outside: Entity<TextInput>,
on: bool,
@@ -375,6 +375,17 @@ fn a_picture_in_a_table_cell_draws(cx: &mut TestAppContext) {
assert_eq!(drawn_picture(table, 400.0, cx), size(px(200.0), px(100.0)));
}
#[gpui::test]
fn a_picture_in_a_narrow_cell_shrinks_within_it(cx: &mut TestAppContext) {
let table = "| A | B |
| - | - |
| ![shot](assets/wide%20shot.png) | b |
";
let drawn = drawn_picture(table, 160.0, cx);
assert!(drawn.width < px(80.0), "within its half: {drawn:?}");
assert_eq!(drawn.height, drawn.width / 2.0, "at its ratio");
}
#[gpui::test]
fn a_formula_that_fails_shows_why_and_its_source(cx: &mut TestAppContext) {
cx.update(Theme::init);
@@ -310,203 +310,4 @@ fn styled(inline: &mut Inline, text: &str, style: Style) {
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn blocks_nest_as_written() {
let nodes = parse(
"# Lift\n\nBlend **toward** [white](https://ely.dev).\n\n- [x] clamp\n- [ ] gamma\n\n> quoted\n\n```rust\nfn main() {}\n```\n\n---\n",
);
assert!(matches!(&nodes[0], Node::Heading(1, text) if text.text == "Lift"));
let Node::Paragraph(line) = &nodes[1] else {
panic!("a paragraph, not {:?}", nodes[1])
};
assert_eq!(line.text, "Blend toward white.");
assert_eq!(line.styles, [(6..12, Style::Strong), (13..18, Style::Link)]);
assert_eq!(line.links, [(13..18, "https://ely.dev".to_string())]);
let Node::List { start: None, items } = &nodes[2] else {
panic!("a list, not {:?}", nodes[2])
};
assert_eq!(
items.iter().map(|(task, _)| *task).collect::<Vec<_>>(),
[Some(true), Some(false)]
);
assert!(matches!(&items[0].1[0], Node::Paragraph(text) if text.text == "clamp"));
assert!(matches!(&nodes[3], Node::Quote(inner) if inner.len() == 1));
assert_eq!(
nodes[4],
Node::Code {
language: Some("rust".into()),
text: "fn main() {}".into()
}
);
assert_eq!(nodes[5], Node::Rule);
}
#[test]
fn an_image_inside_an_image_is_the_outer_one() {
// markdown-rs drops the inner image from the alt.
assert_eq!(
parse("![outer ![inner](inner.png)](outer.png)"),
[Node::Image {
alt: "outer ".into(),
url: "outer.png".into(),
link: None
}]
);
}
#[test]
fn an_image_splits_its_paragraph_and_references_resolve() {
let nodes =
parse("Before ![a][pic] after [site].\n\n[pic]: a.png\n[site]: https://ely.dev\n");
assert!(matches!(&nodes[0], Node::Paragraph(text) if text.text == "Before "));
assert_eq!(
nodes[1],
Node::Image {
alt: "a".into(),
url: "a.png".into(),
link: None
}
);
let Node::Paragraph(after) = &nodes[2] else {
panic!("a paragraph, not {:?}", nodes[2])
};
assert_eq!(after.text, " after site.");
assert_eq!(after.links, [(7..11, "https://ely.dev".to_string())]);
assert_eq!(nodes.len(), 3, "definitions draw nothing: {nodes:?}");
}
#[test]
fn a_soft_break_reads_as_a_space_and_a_hard_one_as_a_line() {
for (source, shown) in [
("one\ntwo \nthree", "one two\nthree"),
("one\r\ntwo \r\nthree", "one two\nthree"),
("one\rtwo \rthree", "one two\nthree"),
] {
let nodes = parse(source);
assert!(
matches!(&nodes[0], Node::Paragraph(text) if text.text == shown),
"{source:?} reads {nodes:?}"
);
}
}
#[test]
fn definitions_nested_in_quotes_and_lists_resolve() {
for source in [
"[site] ![pic]\n\n> [site]: https://ely.dev\n> [pic]: a.png\n",
"[site] ![pic]\n\n- [site]: https://ely.dev\n- [pic]: a.png\n",
] {
let nodes = parse(source);
let Node::Paragraph(text) = &nodes[0] else {
panic!("a paragraph, not {:?}", nodes[0])
};
assert_eq!(text.links, [(0..4, "https://ely.dev".to_string())]);
assert_eq!(
nodes[1],
Node::Image {
alt: "pic".into(),
url: "a.png".into(),
link: None
}
);
}
}
#[test]
fn an_image_inside_styles_and_links_stays_an_image() {
let nodes = parse("*a ![x](x.png) b* [![y](y.png)](https://ely.dev)");
let Node::Paragraph(before) = &nodes[0] else {
panic!("a paragraph, not {:?}", nodes[0])
};
assert_eq!(
(before.text.as_str(), &before.styles[..]),
("a ", &[(0..2, Style::Emphasis)][..])
);
assert_eq!(
nodes[1],
Node::Image {
alt: "x".into(),
url: "x.png".into(),
link: None
}
);
let Node::Paragraph(after) = &nodes[2] else {
panic!("a paragraph, not {:?}", nodes[2])
};
assert_eq!(
(after.text.as_str(), &after.styles[..]),
(" b ", &[(0..2, Style::Emphasis)][..])
);
assert_eq!(
nodes[3],
Node::Image {
alt: "y".into(),
url: "y.png".into(),
link: Some("https://ely.dev".into())
}
);
assert_eq!(nodes.len(), 4, "{nodes:?}");
}
#[test]
fn a_heading_keeps_its_images_after_it() {
let nodes = parse("# Lift ![x](x.png)");
assert!(matches!(&nodes[0], Node::Heading(1, text) if text.text == "Lift "));
assert!(matches!(&nodes[1], Node::Image { url, .. } if url == "x.png"));
}
#[test]
fn display_math_stands_alone() {
assert_eq!(parse("$$c = 1$$"), [Node::Math("c = 1".into())]);
assert_eq!(parse("$$\nc = 1\n$$"), [Node::Math("c = 1".into())]);
let Node::Paragraph(inline) = &parse("so $c$ holds")[0] else {
panic!("inline math stays in its paragraph")
};
assert_eq!(inline.styles, [(3..4, Style::Math)]);
}
#[test]
fn tables_keep_their_cells_and_alignment() {
let nodes = parse("| Name | Lift |\n|:--|--:|\n| accent | 0.5 |\n");
let Node::Table { aligns, head, rows } = &nodes[0] else {
panic!("a table, not {:?}", nodes[0])
};
assert_eq!(aligns, &[AlignKind::Left, AlignKind::Right]);
let text = |cell: &[Node]| match cell {
[Node::Paragraph(line)] => line.text.clone(),
other => panic!("one line, not {other:?}"),
};
assert_eq!(
head.iter().map(|cell| text(cell)).collect::<Vec<_>>(),
["Name", "Lift"]
);
assert_eq!(text(&rows[0][1]), "0.5");
}
#[test]
fn a_picture_in_a_cell_stays_a_picture() {
let nodes = parse("| Picture |\n| --- |\n| ![shot](assets/shot.png) |\n");
let Node::Table { rows, .. } = &nodes[0] else {
panic!("a table, not {:?}", nodes[0])
};
assert!(
matches!(&rows[0][0][..], [Node::Image { alt, url, .. }] if alt == "shot" && url == "assets/shot.png")
);
}
#[test]
fn footnotes_number_their_references_and_hold_their_body() {
let nodes = parse("Lift[^a].\n\n[^a]: Toward white.\n");
let Node::Paragraph(line) = &nodes[0] else {
panic!("a paragraph, not {:?}", nodes[0])
};
assert_eq!(line.text, "Lift[a].");
assert_eq!(line.styles, [(4..7, Style::Footnote)]);
assert!(
matches!(&nodes[1], Node::Footnote { label, body } if label == "a" && body.len() == 1)
);
}
}
mod tests;
+195
View File
@@ -0,0 +1,195 @@
use super::*;
#[test]
fn blocks_nest_as_written() {
let nodes = parse(
"# Lift\n\nBlend **toward** [white](https://ely.dev).\n\n- [x] clamp\n- [ ] gamma\n\n> quoted\n\n```rust\nfn main() {}\n```\n\n---\n",
);
assert!(matches!(&nodes[0], Node::Heading(1, text) if text.text == "Lift"));
let Node::Paragraph(line) = &nodes[1] else {
panic!("a paragraph, not {:?}", nodes[1])
};
assert_eq!(line.text, "Blend toward white.");
assert_eq!(line.styles, [(6..12, Style::Strong), (13..18, Style::Link)]);
assert_eq!(line.links, [(13..18, "https://ely.dev".to_string())]);
let Node::List { start: None, items } = &nodes[2] else {
panic!("a list, not {:?}", nodes[2])
};
assert_eq!(
items.iter().map(|(task, _)| *task).collect::<Vec<_>>(),
[Some(true), Some(false)]
);
assert!(matches!(&items[0].1[0], Node::Paragraph(text) if text.text == "clamp"));
assert!(matches!(&nodes[3], Node::Quote(inner) if inner.len() == 1));
assert_eq!(
nodes[4],
Node::Code {
language: Some("rust".into()),
text: "fn main() {}".into()
}
);
assert_eq!(nodes[5], Node::Rule);
}
#[test]
fn an_image_inside_an_image_is_the_outer_one() {
// markdown-rs drops the inner image from the alt.
assert_eq!(
parse("![outer ![inner](inner.png)](outer.png)"),
[Node::Image {
alt: "outer ".into(),
url: "outer.png".into(),
link: None
}]
);
}
#[test]
fn an_image_splits_its_paragraph_and_references_resolve() {
let nodes = parse("Before ![a][pic] after [site].\n\n[pic]: a.png\n[site]: https://ely.dev\n");
assert!(matches!(&nodes[0], Node::Paragraph(text) if text.text == "Before "));
assert_eq!(
nodes[1],
Node::Image {
alt: "a".into(),
url: "a.png".into(),
link: None
}
);
let Node::Paragraph(after) = &nodes[2] else {
panic!("a paragraph, not {:?}", nodes[2])
};
assert_eq!(after.text, " after site.");
assert_eq!(after.links, [(7..11, "https://ely.dev".to_string())]);
assert_eq!(nodes.len(), 3, "definitions draw nothing: {nodes:?}");
}
#[test]
fn a_soft_break_reads_as_a_space_and_a_hard_one_as_a_line() {
for (source, shown) in [
("one\ntwo \nthree", "one two\nthree"),
("one\r\ntwo \r\nthree", "one two\nthree"),
("one\rtwo \rthree", "one two\nthree"),
] {
let nodes = parse(source);
assert!(
matches!(&nodes[0], Node::Paragraph(text) if text.text == shown),
"{source:?} reads {nodes:?}"
);
}
}
#[test]
fn definitions_nested_in_quotes_and_lists_resolve() {
for source in [
"[site] ![pic]\n\n> [site]: https://ely.dev\n> [pic]: a.png\n",
"[site] ![pic]\n\n- [site]: https://ely.dev\n- [pic]: a.png\n",
] {
let nodes = parse(source);
let Node::Paragraph(text) = &nodes[0] else {
panic!("a paragraph, not {:?}", nodes[0])
};
assert_eq!(text.links, [(0..4, "https://ely.dev".to_string())]);
assert_eq!(
nodes[1],
Node::Image {
alt: "pic".into(),
url: "a.png".into(),
link: None
}
);
}
}
#[test]
fn an_image_inside_styles_and_links_stays_an_image() {
let nodes = parse("*a ![x](x.png) b* [![y](y.png)](https://ely.dev)");
let Node::Paragraph(before) = &nodes[0] else {
panic!("a paragraph, not {:?}", nodes[0])
};
assert_eq!(
(before.text.as_str(), &before.styles[..]),
("a ", &[(0..2, Style::Emphasis)][..])
);
assert_eq!(
nodes[1],
Node::Image {
alt: "x".into(),
url: "x.png".into(),
link: None
}
);
let Node::Paragraph(after) = &nodes[2] else {
panic!("a paragraph, not {:?}", nodes[2])
};
assert_eq!(
(after.text.as_str(), &after.styles[..]),
(" b ", &[(0..2, Style::Emphasis)][..])
);
assert_eq!(
nodes[3],
Node::Image {
alt: "y".into(),
url: "y.png".into(),
link: Some("https://ely.dev".into())
}
);
assert_eq!(nodes.len(), 4, "{nodes:?}");
}
#[test]
fn a_heading_keeps_its_images_after_it() {
let nodes = parse("# Lift ![x](x.png)");
assert!(matches!(&nodes[0], Node::Heading(1, text) if text.text == "Lift "));
assert!(matches!(&nodes[1], Node::Image { url, .. } if url == "x.png"));
}
#[test]
fn display_math_stands_alone() {
assert_eq!(parse("$$c = 1$$"), [Node::Math("c = 1".into())]);
assert_eq!(parse("$$\nc = 1\n$$"), [Node::Math("c = 1".into())]);
let Node::Paragraph(inline) = &parse("so $c$ holds")[0] else {
panic!("inline math stays in its paragraph")
};
assert_eq!(inline.styles, [(3..4, Style::Math)]);
}
#[test]
fn tables_keep_their_cells_and_alignment() {
let nodes = parse("| Name | Lift |\n|:--|--:|\n| accent | 0.5 |\n");
let Node::Table { aligns, head, rows } = &nodes[0] else {
panic!("a table, not {:?}", nodes[0])
};
assert_eq!(aligns, &[AlignKind::Left, AlignKind::Right]);
let text = |cell: &[Node]| match cell {
[Node::Paragraph(line)] => line.text.clone(),
other => panic!("one line, not {other:?}"),
};
assert_eq!(
head.iter().map(|cell| text(cell)).collect::<Vec<_>>(),
["Name", "Lift"]
);
assert_eq!(text(&rows[0][1]), "0.5");
}
#[test]
fn a_picture_in_a_cell_stays_a_picture() {
let nodes = parse("| Picture |\n| --- |\n| ![shot](assets/shot.png) |\n");
let Node::Table { rows, .. } = &nodes[0] else {
panic!("a table, not {:?}", nodes[0])
};
assert!(
matches!(&rows[0][0][..], [Node::Image { alt, url, .. }] if alt == "shot" && url == "assets/shot.png")
);
}
#[test]
fn footnotes_number_their_references_and_hold_their_body() {
let nodes = parse("Lift[^a].\n\n[^a]: Toward white.\n");
let Node::Paragraph(line) = &nodes[0] else {
panic!("a paragraph, not {:?}", nodes[0])
};
assert_eq!(line.text, "Lift[a].");
assert_eq!(line.styles, [(4..7, Style::Footnote)]);
assert!(matches!(&nodes[1], Node::Footnote { label, body } if label == "a" && body.len() == 1));
}