Fix unbalanced anchor tags

This commit is contained in:
Juno Takano 2026-01-05 00:35:38 -03:00
commit cb24837ff0
6 changed files with 88 additions and 26 deletions

View file

@ -1,6 +1,6 @@
use crate::syntax::content::parser::{
token::{Token, paragraph::Paragraph, preformat::PreFormat},
State,
token::{Token, paragraph::Paragraph, preformat::PreFormat},
};
pub mod anchor;

View file

@ -57,6 +57,7 @@ pub fn parse(
);
// Conditions in this decision tree should match the destination end
// or some intermediary state necessary to finding it
if lexeme.match_as_char('s')
&& lexeme.is_next_boundary()
&& !lexeme.match_next_as_char('|')
@ -80,7 +81,7 @@ pub fn parse(
state.context.inline = Inline::None;
return true;
} else if lexeme.match_as_char('|') && !candidate.balanced {
log!("Found a pipe, but no boundary: Destination likely follows");
log!("State: Found a pipe, but no boundary: destination follows");
candidate.balanced = true;
return true;
} else if lexeme.match_as_char('|') {
@ -96,12 +97,13 @@ pub fn parse(
tokens.push(Token::Anchor(candidate.clone()));
state.context.inline = Inline::None;
return false;
} else if lexeme.is_whitespace() {
log!("End: Whitespace");
} else if lexeme.is_next_whitespace() {
log!("End: next is whitespace");
buffer.destination.push_str(&lexeme.text());
candidate.destination = Some(buffer.destination.clone());
tokens.push(Token::Anchor(candidate.clone()));
state.context.inline = Inline::None;
return false;
return true;
// This else branch is the 'no end found yet' state and will keep
// pushing lexemes into the buffer until an end is found above
@ -137,3 +139,32 @@ pub fn parse(
state.context.inline = Inline::None;
false
}
#[cfg(test)]
mod tests {
use crate::{syntax::content::parser, types::Graph};
fn read_noconfig(input: &str) -> String {
parser::read(input, &Graph::new(None).meta.config)
}
#[test]
fn indifferent_trailing_pipe() {
assert_eq!(read_noconfig("|a|a|"), read_noconfig("a|a|"));
}
#[test]
fn indifferent_leading_pipe() {
assert_eq!(read_noconfig("|a|a|"), read_noconfig("|a|a"));
}
#[test]
fn indifferent_multiline_trailing_pipe() {
assert_eq!(read_noconfig("|a|a|\nn"), read_noconfig("a|a|\nn"));
}
#[test]
fn indifferent_multiline_leading_pipe() {
assert_eq!(read_noconfig("|a|a|\nn"), read_noconfig("|a|a\nn"));
}
}

View file

@ -2,12 +2,12 @@ use crate::{
syntax::content::{Parseable, parser::lexeme::Lexeme},
};
#[derive(Debug, Clone, Eq, PartialEq)]
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct LineBreak {}
impl Parseable for LineBreak {
fn probe(lexeme: &Lexeme) -> bool {
lexeme.text() == "\n"
lexeme.text() == "\n" && !lexeme.last()
}
fn lex(_lexeme: &Lexeme) -> LineBreak {

View file

@ -6,8 +6,8 @@ pub struct Literal {
}
impl Parseable for Literal {
fn probe(_lexeme: &Lexeme) -> bool {
true
fn probe(lexeme: &Lexeme) -> bool {
!(lexeme.last() && lexeme.is_whitespace())
}
fn lex(lexeme: &Lexeme) -> Literal {

View file

@ -9,6 +9,10 @@ impl Paragraph {
pub fn new(open: bool) -> Paragraph {
Paragraph { open: Some(open) }
}
pub fn probe_end(lexeme: &Lexeme) -> bool {
lexeme.match_as_char('\n') && lexeme.match_next_as_char('\n')
}
}
impl Parseable for Paragraph {