span tag / url
This commit is contained in:
parent
f6fa422e6b
commit
f74ea7a138
1 changed files with 131 additions and 45 deletions
176
src/inline.rs
176
src/inline.rs
|
@ -34,12 +34,16 @@ pub enum Container {
|
||||||
DoubleQuoted,
|
DoubleQuoted,
|
||||||
// Verbatim
|
// Verbatim
|
||||||
Verbatim,
|
Verbatim,
|
||||||
|
/// Span is the format.
|
||||||
RawFormat,
|
RawFormat,
|
||||||
InlineMath,
|
InlineMath,
|
||||||
DisplayMath,
|
DisplayMath,
|
||||||
// Links
|
/// Span is the reference link tag.
|
||||||
ReferenceLink,
|
ReferenceLink,
|
||||||
|
|
||||||
|
/// Delimiter spans are the URL.
|
||||||
InlineLink,
|
InlineLink,
|
||||||
|
|
||||||
AutoLink,
|
AutoLink,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +157,7 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut span_inner = Span::empty_at(self.span.end());
|
let mut span_inner = Span::empty_at(self.span.end());
|
||||||
|
let mut span_outer = None;
|
||||||
|
|
||||||
while let Some(t) = self.eat() {
|
while let Some(t) = self.eat() {
|
||||||
if matches!(t.kind, lex::Kind::Seq(lex::Sequence::Backtick)) && t.len == opener_len
|
if matches!(t.kind, lex::Kind::Seq(lex::Sequence::Backtick)) && t.len == opener_len
|
||||||
|
@ -182,7 +187,8 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
|
||||||
kind = RawFormat;
|
kind = RawFormat;
|
||||||
self.events[opener_event].kind = EventKind::Enter(kind);
|
self.events[opener_event].kind = EventKind::Enter(kind);
|
||||||
self.events[opener_event].span = span_format;
|
self.events[opener_event].span = span_format;
|
||||||
self.span = span_format;
|
self.span = span_format.translate(1); // }
|
||||||
|
span_outer = Some(span_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -198,63 +204,66 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
|
||||||
|
|
||||||
Event {
|
Event {
|
||||||
kind: EventKind::Exit(kind),
|
kind: EventKind::Exit(kind),
|
||||||
span: self.span,
|
span: span_outer.unwrap_or(self.span),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_span(&mut self, first: &lex::Token) -> Option<Event> {
|
fn parse_span(&mut self, first: &lex::Token) -> Option<Event> {
|
||||||
if let Some(open) = match first.kind {
|
match first.kind {
|
||||||
lex::Kind::Open(Delimiter::Bracket) => Some(true),
|
lex::Kind::Open(Delimiter::Bracket) => Some(true),
|
||||||
lex::Kind::Close(Delimiter::Bracket) => Some(false),
|
lex::Kind::Close(Delimiter::Bracket) => Some(false),
|
||||||
_ => None,
|
_ => None,
|
||||||
} {
|
}
|
||||||
Some(if open {
|
.and_then(|open| {
|
||||||
|
if open {
|
||||||
self.spans.push(self.events.len());
|
self.spans.push(self.events.len());
|
||||||
// use str for now, replace if closed later
|
// use str for now, replace if closed later
|
||||||
Event {
|
Some(Event {
|
||||||
kind: EventKind::Str,
|
kind: EventKind::Str,
|
||||||
span: self.span,
|
span: self.span,
|
||||||
|
})
|
||||||
|
} else if !self.spans.is_empty() {
|
||||||
|
let mut ahead = self.lexer.inner().clone();
|
||||||
|
match ahead.next() {
|
||||||
|
Some(opener @ ('[' | '(')) => {
|
||||||
|
let (closer, kind) = match opener {
|
||||||
|
'[' => (']', ReferenceLink),
|
||||||
|
'(' => (')', InlineLink),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let mut end = false;
|
||||||
|
let len = (&mut ahead)
|
||||||
|
.take_while(|c| {
|
||||||
|
if *c == closer {
|
||||||
|
end = true;
|
||||||
|
};
|
||||||
|
!end && *c != opener
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
end.then(|| {
|
||||||
|
let span = Span::by_len(self.span.end() + 1, len);
|
||||||
|
(kind, span)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Some('{') => todo!(),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
|
.map(|(kind, span)| {
|
||||||
|
self.lexer = lex::Lexer::new(ahead);
|
||||||
|
let opener_event = self.spans.pop().unwrap();
|
||||||
|
self.events[opener_event].kind = EventKind::Enter(kind);
|
||||||
|
self.events[opener_event].span = span;
|
||||||
|
self.span = span.translate(1);
|
||||||
|
Event {
|
||||||
|
kind: EventKind::Exit(kind),
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
/*
|
None
|
||||||
let kind = if self.lexer.peek_ahead().starts_with('[') {
|
}
|
||||||
let mut chars = self.lexer.peek_ahead()["[".len()..].chars();
|
})
|
||||||
let len = chars
|
|
||||||
.clone()
|
|
||||||
.take_while(|c| !c.is_whitespace() && !matches!(c, '[' | ']'))
|
|
||||||
.count();
|
|
||||||
match chars.nth(len) {
|
|
||||||
Some(']') => EventKind::Exit(ReferenceLink),
|
|
||||||
None => {
|
|
||||||
self.atomic_state = AtomicState::ReferenceLinkTag;
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
_ => EventKind::Str,
|
|
||||||
}
|
|
||||||
} else if self.lexer.peek_ahead().starts_with('(') {
|
|
||||||
let mut chars = self.lexer.peek_ahead()["[".len()..].chars();
|
|
||||||
let len = chars
|
|
||||||
.clone()
|
|
||||||
.take_while(|c| !c.is_whitespace() && !matches!(c, '[' | ']'))
|
|
||||||
.count();
|
|
||||||
match chars.nth(len) {
|
|
||||||
Some(']') => EventKind::Exit(ReferenceLink),
|
|
||||||
None => {
|
|
||||||
self.atomic_state = AtomicState::Url { auto: false };
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
_ => EventKind::Str,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
todo!()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_typeset(&mut self, first: &lex::Token) -> Option<Event> {
|
fn parse_typeset(&mut self, first: &lex::Token) -> Option<Event> {
|
||||||
|
@ -336,6 +345,7 @@ impl<I: Iterator<Item = char> + Clone> Iterator for Parser<I> {
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while self.events.is_empty()
|
while self.events.is_empty()
|
||||||
|| !self.typesets.is_empty()
|
|| !self.typesets.is_empty()
|
||||||
|
|| !self.spans.is_empty()
|
||||||
|| self // for merge
|
|| self // for merge
|
||||||
.events
|
.events
|
||||||
.back()
|
.back()
|
||||||
|
@ -480,6 +490,82 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn raw_format() {
|
||||||
|
test_parse!(
|
||||||
|
"`raw`{=format}",
|
||||||
|
(Enter(RawFormat), "format"),
|
||||||
|
(Str, "raw"),
|
||||||
|
(Exit(RawFormat), "format"),
|
||||||
|
);
|
||||||
|
test_parse!(
|
||||||
|
"before `raw`{=format} after",
|
||||||
|
(Str, "before "),
|
||||||
|
(Enter(RawFormat), "format"),
|
||||||
|
(Str, "raw"),
|
||||||
|
(Exit(RawFormat), "format"),
|
||||||
|
(Str, " after"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn raw_attr() {
|
||||||
|
test_parse!(
|
||||||
|
"`raw`{=format #id}",
|
||||||
|
(Enter(Verbatim), "`"),
|
||||||
|
(Str, "raw"),
|
||||||
|
(Exit(Verbatim), "`"),
|
||||||
|
(Str, "{=format #id}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn span_tag() {
|
||||||
|
test_parse!(
|
||||||
|
"[text][tag]",
|
||||||
|
(Enter(ReferenceLink), "tag"),
|
||||||
|
(Str, "text"),
|
||||||
|
(Exit(ReferenceLink), "tag"),
|
||||||
|
);
|
||||||
|
test_parse!(
|
||||||
|
"before [text][tag] after",
|
||||||
|
(Str, "before "),
|
||||||
|
(Enter(ReferenceLink), "tag"),
|
||||||
|
(Str, "text"),
|
||||||
|
(Exit(ReferenceLink), "tag"),
|
||||||
|
(Str, " after"),
|
||||||
|
);
|
||||||
|
test_parse!(
|
||||||
|
"[[inner][i]][o]",
|
||||||
|
(Enter(ReferenceLink), "o"),
|
||||||
|
(Enter(ReferenceLink), "i"),
|
||||||
|
(Str, "inner"),
|
||||||
|
(Exit(ReferenceLink), "i"),
|
||||||
|
(Exit(ReferenceLink), "o"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn span_url() {
|
||||||
|
test_parse!(
|
||||||
|
"before [text](url) after",
|
||||||
|
(Str, "before "),
|
||||||
|
(Enter(InlineLink), "url"),
|
||||||
|
(Str, "text"),
|
||||||
|
(Exit(InlineLink), "url"),
|
||||||
|
(Str, " after"),
|
||||||
|
);
|
||||||
|
test_parse!(
|
||||||
|
"[outer [inner](i)](o)",
|
||||||
|
(Enter(InlineLink), "o"),
|
||||||
|
(Str, "outer "),
|
||||||
|
(Enter(InlineLink), "i"),
|
||||||
|
(Str, "inner"),
|
||||||
|
(Exit(InlineLink), "i"),
|
||||||
|
(Exit(InlineLink), "o"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn typeset_basic() {
|
fn typeset_basic() {
|
||||||
test_parse!(
|
test_parse!(
|
||||||
|
|
Loading…
Reference in a new issue