#[test]
fn a_link_inside_a_fenced_content_section_is_not_checked() {
let dir = tempfile::tempdir().expect("tmpdir");
let input = "# Rhei: Link demo\n\n## How To Write A Task\n\n\
Example of the body we want:\n\n\
```markdown\n\
See [the design note](docs/design.md) for the rationale.\n\
```\n\n\
## Tasks\n\n\
### Task 1: Do it\n**State:** pending\n";
let rhei = parse(input).expect("parse ok");
let report = Validator::new(sample_machine()).validate_with_base(&rhei, Some(dir.path()));
assert!(!report.has_errors(), "fenced example should not be checked: {:?}", report.errors);
}
#[test]
fn a_link_inside_a_fenced_task_body_is_not_checked() {
let dir = tempfile::tempdir().expect("tmpdir");
let input = "# Rhei: Link demo\n\n## Tasks\n\n\
### Task 1: Do it\n**State:** pending\n\n\
Example:\n\n\
```markdown\n\
See [the design note](docs/design.md).\n\
```\n";
let rhei = parse(input).expect("parse ok");
let report = Validator::new(sample_machine()).validate_with_base(&rhei, Some(dir.path()));
assert!(!report.has_errors(), "fenced example should not be checked: {:?}", report.errors);
}
#[test]
fn a_broken_link_outside_a_fence_still_fails() {
let dir = tempfile::tempdir().expect("tmpdir");
let input = "# Rhei: Link demo\n\n## Overview\n\n\
```markdown\n\
See [an example](docs/example.md).\n\
```\n\n\
Really see [the spec](specs/nonexistent.md).\n\n\
## Tasks\n\n\
### Task 1: Do it\n**State:** pending\n";
let rhei = parse(input).expect("parse ok");
let report = Validator::new(sample_machine()).validate_with_base(&rhei, Some(dir.path()));
let joined = report.errors.join("\n");
assert!(joined.contains("nonexistent.md"), "prose link should fail; got:\n{joined}");
assert!(!joined.contains("docs/example.md"), "fenced link was checked; got:\n{joined}");
}
#[test]
fn an_unclosed_fence_runs_to_the_end_of_the_body() {
let dir = tempfile::tempdir().expect("tmpdir");
let input = "# Rhei: Link demo\n\n## Tasks\n\n\
### Task 1: Do it\n**State:** pending\n\n\
```markdown\n\
See [an example](docs/example.md).\n\n\
And [another](docs/other.md).\n";
let rhei = parse(input).expect("parse ok");
let report = Validator::new(sample_machine()).validate_with_base(&rhei, Some(dir.path()));
assert!(!report.has_errors(), "unclosed fence should swallow both: {:?}", report.errors);
}
#[test]
fn an_inline_code_span_hides_its_link_and_nothing_else() {
let links = extract_markdown_links("Write `[text](target.md)`, then read [it](real.md).");
assert_eq!(links, vec![("it".to_string(), "real.md".to_string())]);
}
#[test]
fn a_shorter_run_inside_a_longer_fence_does_not_close_it() {
let text = "````markdown\n```\n[a](a.md)\n```\n````\n[b](b.md)\n";
assert_eq!(extract_markdown_links(text), vec![("b".to_string(), "b.md".to_string())]);
}
#[test]
fn tilde_fences_are_code_and_do_not_close_backtick_blocks() {
let tildes = "~~~\n[a](a.md)\n~~~\n[b](b.md)\n";
assert_eq!(extract_markdown_links(tildes), vec![("b".to_string(), "b.md".to_string())]);
let mixed = "```\n[a](a.md)\n~~~\n[b](b.md)\n";
assert!(extract_markdown_links(mixed).is_empty());
}
#[test]
fn an_unclosed_backtick_run_leaves_the_line_alone() {
let links = extract_markdown_links("A ` stray tick and [a link](a.md).");
assert_eq!(links, vec![("a link".to_string(), "a.md".to_string())]);
}