feat: Link::description & Link::description_raw

This commit is contained in:
PoiScript 2024-05-08 18:46:39 +08:00
parent df0d5baec9
commit f9b2d73dd4
No known key found for this signature in database
GPG key ID: 22C2B1249D99985E

View file

@ -1,7 +1,7 @@
use rowan::ast::{support, AstNode};
use super::{AffiliatedKeyword, Link, Paragraph, Token};
use crate::syntax::SyntaxKind;
use crate::{syntax::SyntaxKind, SyntaxElement};
impl Link {
/// Returns link destination
@ -35,9 +35,59 @@ impl Link {
/// assert!(!link.has_description());
/// let link = Org::parse("[[https://google.com][Google]]").first_node::<Link>().unwrap();
/// assert!(link.has_description());
/// let link = Org::parse("[[https://example.com][*abc* /abc/]]").first_node::<Link>().unwrap();
/// assert!(link.has_description());
/// ```
pub fn has_description(&self) -> bool {
support::token(self.syntax(), SyntaxKind::TEXT).is_some()
self.syntax()
.children_with_tokens()
.any(|e| e.kind() == SyntaxKind::L_BRACKET)
}
/// Returns parsed description
///
/// Returns empty iterator if this link doesn't contain description
///
/// ```rust
/// use orgize::{Org, ast::Link, SyntaxKind};
///
/// let link = Org::parse("[[https://google.com]]").first_node::<Link>().unwrap();
/// assert_eq!(link.description().count(), 0);
///
/// let link = Org::parse("[[https://google.com][Google]]").first_node::<Link>().unwrap();
/// let description = link.description().collect::<Vec<_>>();
/// assert_eq!((description[0].kind(), description[0].to_string()), (SyntaxKind::TEXT, "Google".into()));
///
/// let link = Org::parse("[[https://example.com][*abc* /abc/]]").first_node::<Link>().unwrap();
/// let description = link.description().collect::<Vec<_>>();
/// assert_eq!((description[0].kind(), description[0].to_string()), (SyntaxKind::BOLD, "*abc*".into()));
/// assert_eq!((description[2].kind(), description[2].to_string()), (SyntaxKind::ITALIC, "/abc/".into()));
/// ```
pub fn description(&self) -> impl Iterator<Item = SyntaxElement> {
self.syntax()
.children_with_tokens()
.skip_while(|e| e.kind() != SyntaxKind::L_BRACKET)
.skip(1)
.take_while(|e| e.kind() != SyntaxKind::R_BRACKET2)
}
/// Returns description raw string
///
/// Returns empty string if this link doesn't contain description
///
/// ```rust
/// use orgize::{Org, ast::Link};
///
/// let link = Org::parse("[[https://google.com]]").first_node::<Link>().unwrap();
/// assert_eq!(link.description_raw(), "");
/// let link = Org::parse("[[https://google.com][Google]]").first_node::<Link>().unwrap();
/// assert_eq!(link.description_raw(), "Google");
/// let link = Org::parse("[[https://example.com][*abc* /abc/]]").first_node::<Link>().unwrap();
/// assert_eq!(link.description_raw(), "*abc* /abc/");
/// ```
pub fn description_raw(&self) -> String {
self.description()
.fold(String::new(), |acc, e| acc + &e.to_string())
}
/// Returns `true` if link is an image link