use super::prelude::*;
use crate::tree::{AnchorTarget, LinkLabel, LinkLocation, LinkType};
use crate::url::is_url;
pub const RULE_LINK_SINGLE: Rule = Rule {
name: "link-single",
position: LineRequirement::Any,
try_consume_fn: link,
};
pub const RULE_LINK_SINGLE_NEW_TAB: Rule = Rule {
name: "link-single-new-tab",
position: LineRequirement::Any,
try_consume_fn: link_new_tab,
};
fn link<'r, 't>(parser: &mut Parser<'r, 't>) -> ParseResult<'r, 't, Elements<'t>> {
trace!("Trying to create a single-bracket link (regular)");
assert_step(parser, Token::LeftBracket)?;
try_consume_link(parser, RULE_LINK_SINGLE, None)
}
fn link_new_tab<'r, 't>(
parser: &mut Parser<'r, 't>,
) -> ParseResult<'r, 't, Elements<'t>> {
trace!("Trying to create a single-bracket link (new tab)");
assert_step(parser, Token::LeftBracketStar)?;
try_consume_link(parser, RULE_LINK_SINGLE_NEW_TAB, Some(AnchorTarget::NewTab))
}
fn try_consume_link<'r, 't>(
parser: &mut Parser<'r, 't>,
rule: Rule,
target: Option<AnchorTarget>,
) -> ParseResult<'r, 't, Elements<'t>> {
debug!(
"Trying to create a single-bracket link (target {})",
match target {
Some(target) => target.name(),
None => "<none>",
},
);
let url = collect_text(
parser,
rule,
&[ParseCondition::current(Token::Whitespace)],
&[
ParseCondition::current(Token::RightBracket),
ParseCondition::current(Token::ParagraphBreak),
ParseCondition::current(Token::LineBreak),
],
None,
)?;
if !url_valid(url) {
return Err(parser.make_err(ParseErrorKind::InvalidUrl));
}
trace!("Retrieved URL '{url}' for link, now fetching label");
let label = collect_text(
parser,
rule,
&[ParseCondition::current(Token::RightBracket)],
&[
ParseCondition::current(Token::ParagraphBreak),
ParseCondition::current(Token::LineBreak),
],
None,
)?;
trace!("Retrieved label for link, now build element (label '{label}')");
let label = label.trim();
let element = Element::Link {
ltype: LinkType::Direct,
link: LinkLocation::Url(cow!(url)),
label: LinkLabel::Text(cow!(label)),
target,
};
ok!(element)
}
fn url_valid(url: &str) -> bool {
if url.is_empty() {
return false;
}
if url.starts_with('/') {
return true;
}
if is_url(url) {
return true;
}
false
}