| ... | @@ -288,16 +288,21 @@ fn issue(html: &str, repository: &str, id: Option<u64>) -> Result<Value> { | ... | @@ -288,16 +288,21 @@ fn issue(html: &str, repository: &str, id: Option<u64>) -> Result<Value> { |
| 288 | let spans: Vec<_> = document | 288 | let spans: Vec<_> = document |
| 289 | .select(&Selector::parse("h1 > span").unwrap()) | 289 | .select(&Selector::parse("h1 > span").unwrap()) |
| 290 | .collect(); | 290 | .collect(); |
| 291 | let issue_id = spans.first().and_then(|s| { | 291 | let (issue_id, title) = if spans.len() == 2 { |
| 292 | text(*s) | 292 | (text(spans[0]).strip_prefix('#').and_then(|id| id.parse::<u64>().ok()), Some(text(spans[1]))) |
| 293 | .strip_prefix('#') | 293 | } else if spans.is_empty() && tokenless_r1616(&document) { |
| 294 | .and_then(|s| s.parse::<u64>().ok()) | 294 | let headings: Vec<_> = document.select(&Selector::parse("h1").unwrap()).collect(); |
| 295 | }); | 295 | if let [heading] = headings.as_slice() { |
| | 296 | text(*heading).strip_prefix("Issue #").and_then(|text| text.split_once(": ")) |
| | 297 | .map(|(id, title)| (id.parse::<u64>().ok(), Some(title.to_owned()))) |
| | 298 | .unwrap_or((None, None)) |
| | 299 | } else { (None, None) } |
| | 300 | } else { (None, None) }; |
| 296 | let status = document | 301 | let status = document |
| 297 | .select(&Selector::parse("select[name=status] option[selected]").unwrap()) | 302 | .select(&Selector::parse("select[name=status] option[selected]").unwrap()) |
| 298 | .next() | 303 | .next() |
| 299 | .and_then(|e| e.attr("value")); | 304 | .and_then(|e| e.attr("value")); |
| 300 | if spans.len() != 2 | 305 | if title.as_ref().is_none_or(|title| title.is_empty()) |
| 301 | || issue_id.is_none_or(|n| n == 0 || id.is_some_and(|id| n != id)) | 306 | || issue_id.is_none_or(|n| n == 0 || id.is_some_and(|id| n != id)) |
| 302 | || status.is_none() | 307 | || status.is_none() |
| 303 | { | 308 | { |
| ... | @@ -334,7 +339,7 @@ fn issue(html: &str, repository: &str, id: Option<u64>) -> Result<Value> { | ... | @@ -334,7 +339,7 @@ fn issue(html: &str, repository: &str, id: Option<u64>) -> Result<Value> { |
| 334 | .map(text) | 339 | .map(text) |
| 335 | .collect(); | 340 | .collect(); |
| 336 | Ok( | 341 | Ok( |
| 337 | json!({"repository":repository,"id":issue_id,"title":text(spans[1]),"status":status,"labels":labels,"comments":comments}), | 342 | json!({"repository":repository,"id":issue_id,"title":title.unwrap(),"status":status,"labels":labels,"comments":comments}), |
| 338 | ) | 343 | ) |
| 339 | } | 344 | } |
| 340 | fn current(app: &App, grant: &Value, credential: &str) -> Result<()> { | 345 | fn current(app: &App, grant: &Value, credential: &str) -> Result<()> { |
| ... | @@ -921,6 +926,15 @@ mod tests { | ... | @@ -921,6 +926,15 @@ mod tests { |
| 921 | assert!(issue(&page.replace("selected", ""), "owned", Some(3)).is_err()); | 926 | assert!(issue(&page.replace("selected", ""), "owned", Some(3)).is_err()); |
| 922 | } | 927 | } |
| 923 | #[test] | 928 | #[test] |
| | 929 | fn verified_r1616_issue_heading_keeps_identity_checks() { |
| | 930 | let page = "<head><meta name='astheno.shale.repo.name' content='owned'></head><body id=page-issue><h1>Issue #3: Snow &amp; ☃</h1><select name=status><option selected value=done>Done</option></select><footer class=usa-footer><div class=usa-footer__secondary-section><a href='https://astheno.software/shale/'>shale r1616-ga87d2f5.zig.0.16.0</a></div></footer></body>"; |
| | 931 | assert_eq!(issue(page, "owned", Some(3)).unwrap()["title"], "Snow & ☃"); |
| | 932 | assert!(issue(page, "other", Some(3)).is_err()); |
| | 933 | assert!(issue(page, "owned", Some(4)).is_err()); |
| | 934 | assert!(issue(&page.replace("r1616-ga87d2f5.zig.0.16.0", "r1758-new"), "owned", Some(3)).is_err()); |
| | 935 | assert!(issue(&page.replace("Issue #3", "Issue #0"), "owned", None).is_err()); |
| | 936 | } |
| | 937 | #[test] |
| 924 | fn account_identity_uses_html_text_and_rejects_login_or_changed_markup() { | 938 | fn account_identity_uses_html_text_and_rejects_login_or_changed_markup() { |
| 925 | assert_eq!( | 939 | assert_eq!( |
| 926 | username("<body id=page-user-settings><kbd>snow&amp;flake☃</kbd>").unwrap(), | 940 | username("<body id=page-user-settings><kbd>snow&amp;flake☃</kbd>").unwrap(), |