block: specify link def label in event
instead of using span
This commit is contained in:
parent
bc4dd794bc
commit
e90594f2b7
3 changed files with 56 additions and 53 deletions
84
src/block.rs
84
src/block.rs
|
@ -12,13 +12,13 @@ use Container::*;
|
||||||
use Leaf::*;
|
use Leaf::*;
|
||||||
use ListType::*;
|
use ListType::*;
|
||||||
|
|
||||||
pub type Tree = tree::Tree<Node, Atom>;
|
pub type Tree<'s> = tree::Tree<Node<'s>, Atom>;
|
||||||
pub type TreeBuilder = tree::Builder<Node, Atom>;
|
pub type TreeBuilder<'s> = tree::Builder<Node<'s>, Atom>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Node {
|
pub enum Node<'s> {
|
||||||
Container(Container),
|
Container(Container),
|
||||||
Leaf(Leaf),
|
Leaf(Leaf<'s>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -27,12 +27,12 @@ pub fn parse(src: &str) -> Tree {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
enum Block {
|
enum Block<'s> {
|
||||||
/// An atomic block, containing no children elements.
|
/// An atomic block, containing no children elements.
|
||||||
Atom(Atom),
|
Atom(Atom),
|
||||||
|
|
||||||
/// A leaf block, containing only inline elements.
|
/// A leaf block, containing only inline elements.
|
||||||
Leaf(Leaf),
|
Leaf(Leaf<'s>),
|
||||||
|
|
||||||
/// A container block, containing children blocks.
|
/// A container block, containing children blocks.
|
||||||
Container(Container),
|
Container(Container),
|
||||||
|
@ -51,7 +51,7 @@ pub enum Atom {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Leaf {
|
pub enum Leaf<'s> {
|
||||||
/// Span is empty, before first character of paragraph.
|
/// Span is empty, before first character of paragraph.
|
||||||
/// Each inline is a line.
|
/// Each inline is a line.
|
||||||
Paragraph,
|
Paragraph,
|
||||||
|
@ -72,7 +72,7 @@ pub enum Leaf {
|
||||||
|
|
||||||
/// Span is the link tag.
|
/// Span is the link tag.
|
||||||
/// Inlines are lines of the URL.
|
/// Inlines are lines of the URL.
|
||||||
LinkDefinition,
|
LinkDefinition { label: &'s str },
|
||||||
|
|
||||||
/// Span is language specifier.
|
/// Span is language specifier.
|
||||||
/// Each inline is a line.
|
/// Each inline is a line.
|
||||||
|
@ -135,7 +135,7 @@ struct OpenList {
|
||||||
/// Parser for block-level tree structure of entire document.
|
/// Parser for block-level tree structure of entire document.
|
||||||
struct TreeParser<'s> {
|
struct TreeParser<'s> {
|
||||||
src: &'s str,
|
src: &'s str,
|
||||||
tree: TreeBuilder,
|
tree: TreeBuilder<'s>,
|
||||||
|
|
||||||
/// The previous block element was a blank line.
|
/// The previous block element was a blank line.
|
||||||
prev_blankline: bool,
|
prev_blankline: bool,
|
||||||
|
@ -163,7 +163,7 @@ impl<'s> TreeParser<'s> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn parse(mut self) -> Tree {
|
pub fn parse(mut self) -> Tree<'s> {
|
||||||
let mut lines = lines(self.src).collect::<Vec<_>>();
|
let mut lines = lines(self.src).collect::<Vec<_>>();
|
||||||
let mut line_pos = 0;
|
let mut line_pos = 0;
|
||||||
while line_pos < lines.len() {
|
while line_pos < lines.len() {
|
||||||
|
@ -246,7 +246,33 @@ impl<'s> TreeParser<'s> {
|
||||||
self.prev_blankline = false;
|
self.prev_blankline = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
match kind.block(top_level) {
|
let block = match kind {
|
||||||
|
Kind::Atom(a) => Block::Atom(a),
|
||||||
|
Kind::Paragraph => Block::Leaf(Paragraph),
|
||||||
|
Kind::Heading { level } => Block::Leaf(Heading {
|
||||||
|
level: level.try_into().unwrap(),
|
||||||
|
has_section: top_level,
|
||||||
|
}),
|
||||||
|
Kind::Fenced {
|
||||||
|
kind: FenceKind::CodeBlock(..),
|
||||||
|
..
|
||||||
|
} => Block::Leaf(CodeBlock),
|
||||||
|
Kind::Fenced {
|
||||||
|
kind: FenceKind::Div,
|
||||||
|
..
|
||||||
|
} => Block::Container(Div),
|
||||||
|
Kind::Definition {
|
||||||
|
footnote: false, ..
|
||||||
|
} => Block::Leaf(LinkDefinition {
|
||||||
|
label: span.of(self.src),
|
||||||
|
}),
|
||||||
|
Kind::Definition { footnote: true, .. } => Block::Container(Footnote),
|
||||||
|
Kind::Blockquote => Block::Container(Blockquote),
|
||||||
|
Kind::ListItem { ty, .. } => Block::Container(ListItem(ty)),
|
||||||
|
Kind::Table { .. } => Block::Container(Table),
|
||||||
|
};
|
||||||
|
|
||||||
|
match block {
|
||||||
Block::Atom(a) => self.tree.atom(a, span),
|
Block::Atom(a) => self.tree.atom(a, span),
|
||||||
Block::Leaf(l) => self.parse_leaf(l, &kind, span, lines),
|
Block::Leaf(l) => self.parse_leaf(l, &kind, span, lines),
|
||||||
Block::Container(Table) => self.parse_table(lines, span),
|
Block::Container(Table) => self.parse_table(lines, span),
|
||||||
|
@ -259,7 +285,7 @@ impl<'s> TreeParser<'s> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_leaf(&mut self, leaf: Leaf, k: &Kind, span: Span, lines: &mut [Span]) {
|
fn parse_leaf(&mut self, leaf: Leaf<'s>, k: &Kind, span: Span, lines: &mut [Span]) {
|
||||||
if let Kind::Fenced { indent, .. } = k {
|
if let Kind::Fenced { indent, .. } = k {
|
||||||
for line in lines.iter_mut() {
|
for line in lines.iter_mut() {
|
||||||
let indent_line = line
|
let indent_line = line
|
||||||
|
@ -564,7 +590,7 @@ impl<'s> TreeParser<'s> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'t> tree::Element<'t, Node, Atom> {
|
impl<'t, 's> tree::Element<'t, Node<'s>, Atom> {
|
||||||
fn list_mut(&mut self) -> Option<&mut ListKind> {
|
fn list_mut(&mut self) -> Option<&mut ListKind> {
|
||||||
if let tree::Element::Container(Node::Container(Container::List(l))) = self {
|
if let tree::Element::Container(Node::Container(Container::List(l))) = self {
|
||||||
Some(l)
|
Some(l)
|
||||||
|
@ -936,35 +962,9 @@ impl Kind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(&self, top_level: bool) -> Block {
|
|
||||||
match self {
|
|
||||||
Self::Atom(a) => Block::Atom(*a),
|
|
||||||
Self::Paragraph => Block::Leaf(Paragraph),
|
|
||||||
Self::Heading { level } => Block::Leaf(Heading {
|
|
||||||
level: (*level).try_into().unwrap(),
|
|
||||||
has_section: top_level,
|
|
||||||
}),
|
|
||||||
Self::Fenced {
|
|
||||||
kind: FenceKind::CodeBlock(..),
|
|
||||||
..
|
|
||||||
} => Block::Leaf(CodeBlock),
|
|
||||||
Self::Fenced {
|
|
||||||
kind: FenceKind::Div,
|
|
||||||
..
|
|
||||||
} => Block::Container(Div),
|
|
||||||
Self::Definition {
|
|
||||||
footnote: false, ..
|
|
||||||
} => Block::Leaf(LinkDefinition),
|
|
||||||
Self::Definition { footnote: true, .. } => Block::Container(Footnote),
|
|
||||||
Self::Blockquote => Block::Container(Blockquote),
|
|
||||||
Self::ListItem { ty, .. } => Block::Container(ListItem(*ty)),
|
|
||||||
Self::Table { .. } => Block::Container(Table),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Block {
|
impl<'s> std::fmt::Display for Block<'s> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Block::Atom(a) => std::fmt::Debug::fmt(a, f),
|
Block::Atom(a) => std::fmt::Debug::fmt(a, f),
|
||||||
|
@ -1501,9 +1501,9 @@ mod test {
|
||||||
fn parse_link_definition() {
|
fn parse_link_definition() {
|
||||||
test_parse!(
|
test_parse!(
|
||||||
"[tag]: url\n",
|
"[tag]: url\n",
|
||||||
(Enter(Leaf(LinkDefinition)), "tag"),
|
(Enter(Leaf(LinkDefinition { label: "tag" })), "tag"),
|
||||||
(Inline, "url"),
|
(Inline, "url"),
|
||||||
(Exit(Leaf(LinkDefinition)), "tag"),
|
(Exit(Leaf(LinkDefinition { label: "tag" })), "tag"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
src/lib.rs
19
src/lib.rs
|
@ -555,7 +555,7 @@ pub struct Parser<'s> {
|
||||||
src: &'s str,
|
src: &'s str,
|
||||||
|
|
||||||
/// Block tree parsed at first.
|
/// Block tree parsed at first.
|
||||||
tree: block::Tree,
|
tree: block::Tree<'s>,
|
||||||
|
|
||||||
/// Contents obtained by the prepass.
|
/// Contents obtained by the prepass.
|
||||||
pre_pass: PrePass<'s>,
|
pre_pass: PrePass<'s>,
|
||||||
|
@ -598,7 +598,11 @@ struct PrePass<'s> {
|
||||||
|
|
||||||
impl<'s> PrePass<'s> {
|
impl<'s> PrePass<'s> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn new(src: &'s str, mut tree: block::Tree, inline_parser: &mut inline::Parser<'s>) -> Self {
|
fn new(
|
||||||
|
src: &'s str,
|
||||||
|
mut tree: block::Tree<'s>,
|
||||||
|
inline_parser: &mut inline::Parser<'s>,
|
||||||
|
) -> Self {
|
||||||
let mut link_definitions = Map::new();
|
let mut link_definitions = Map::new();
|
||||||
let mut headings: Vec<Heading> = Vec::new();
|
let mut headings: Vec<Heading> = Vec::new();
|
||||||
let mut used_ids: Set<&str> = Set::new();
|
let mut used_ids: Set<&str> = Set::new();
|
||||||
|
@ -606,10 +610,11 @@ impl<'s> PrePass<'s> {
|
||||||
let mut attr_prev: Option<Span> = None;
|
let mut attr_prev: Option<Span> = None;
|
||||||
while let Some(e) = tree.next() {
|
while let Some(e) = tree.next() {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
tree::EventKind::Enter(block::Node::Leaf(block::Leaf::LinkDefinition)) => {
|
tree::EventKind::Enter(block::Node::Leaf(block::Leaf::LinkDefinition {
|
||||||
|
label,
|
||||||
|
})) => {
|
||||||
// All link definition tags have to be obtained initially, as references can
|
// All link definition tags have to be obtained initially, as references can
|
||||||
// appear before the definition.
|
// appear before the definition.
|
||||||
let tag = e.span.of(src);
|
|
||||||
let attrs =
|
let attrs =
|
||||||
attr_prev.map_or_else(Attributes::new, |sp| attr::parse(sp.of(src)));
|
attr_prev.map_or_else(Attributes::new, |sp| attr::parse(sp.of(src)));
|
||||||
let url = match tree.count_children() {
|
let url = match tree.count_children() {
|
||||||
|
@ -617,7 +622,7 @@ impl<'s> PrePass<'s> {
|
||||||
1 => tree.take_inlines().next().unwrap().of(src).trim().into(),
|
1 => tree.take_inlines().next().unwrap().of(src).trim().into(),
|
||||||
_ => tree.take_inlines().map(|sp| sp.of(src).trim()).collect(),
|
_ => tree.take_inlines().map(|sp| sp.of(src).trim()).collect(),
|
||||||
};
|
};
|
||||||
link_definitions.insert(tag, (url, attrs));
|
link_definitions.insert(label, (url, attrs));
|
||||||
}
|
}
|
||||||
tree::EventKind::Enter(block::Node::Leaf(block::Leaf::Heading { .. })) => {
|
tree::EventKind::Enter(block::Node::Leaf(block::Leaf::Heading { .. })) => {
|
||||||
// All headings ids have to be obtained initially, as references can appear
|
// All headings ids have to be obtained initially, as references can appear
|
||||||
|
@ -905,8 +910,8 @@ impl<'s> Parser<'s> {
|
||||||
head: self.table_head_row,
|
head: self.table_head_row,
|
||||||
},
|
},
|
||||||
block::Leaf::Caption => Container::Caption,
|
block::Leaf::Caption => Container::Caption,
|
||||||
block::Leaf::LinkDefinition => {
|
block::Leaf::LinkDefinition { label } => {
|
||||||
Container::LinkDefinition { label: content }
|
Container::LinkDefinition { label }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub struct Event<C, A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Tree<C: 'static, A: 'static> {
|
pub struct Tree<C, A> {
|
||||||
nodes: std::rc::Rc<[InternalNode<C, A>]>,
|
nodes: std::rc::Rc<[InternalNode<C, A>]>,
|
||||||
branch: Vec<NodeIndex>,
|
branch: Vec<NodeIndex>,
|
||||||
head: Option<NodeIndex>,
|
head: Option<NodeIndex>,
|
||||||
|
@ -349,9 +349,7 @@ impl<C, A> Builder<C, A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: std::fmt::Debug + Clone + 'static, A: std::fmt::Debug + Clone + 'static> std::fmt::Debug
|
impl<C: std::fmt::Debug + Clone, A: std::fmt::Debug + Clone> std::fmt::Debug for Builder<C, A> {
|
||||||
for Builder<C, A>
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
self.clone().finish().fmt(f)
|
self.clone().finish().fmt(f)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue