feat(elements): into_owned function

This commit is contained in:
PoiScript 2019-08-10 20:17:39 +08:00
parent 9bc260627b
commit f2d0a1dd2d
25 changed files with 475 additions and 131 deletions

View file

@ -12,6 +12,15 @@ pub struct SpecialBlock<'a> {
pub name: Cow<'a, str>,
}
impl SpecialBlock<'_> {
pub fn into_owned(self) -> SpecialBlock<'static> {
SpecialBlock {
name: self.name.into_owned().into(),
parameters: self.parameters.map(Into::into).map(Cow::Owned),
}
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
@ -19,6 +28,14 @@ pub struct QuoteBlock<'a> {
pub parameters: Option<Cow<'a, str>>,
}
impl QuoteBlock<'_> {
pub fn into_owned(self) -> QuoteBlock<'static> {
QuoteBlock {
parameters: self.parameters.map(Into::into).map(Cow::Owned),
}
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
@ -26,6 +43,14 @@ pub struct CenterBlock<'a> {
pub parameters: Option<Cow<'a, str>>,
}
impl CenterBlock<'_> {
pub fn into_owned(self) -> CenterBlock<'static> {
CenterBlock {
parameters: self.parameters.map(Into::into).map(Cow::Owned),
}
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
@ -33,6 +58,14 @@ pub struct VerseBlock<'a> {
pub parameters: Option<Cow<'a, str>>,
}
impl VerseBlock<'_> {
pub fn into_owned(self) -> VerseBlock<'static> {
VerseBlock {
parameters: self.parameters.map(Into::into).map(Cow::Owned),
}
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
@ -41,6 +74,15 @@ pub struct CommentBlock<'a> {
pub contents: Cow<'a, str>,
}
impl CommentBlock<'_> {
pub fn into_owned(self) -> CommentBlock<'static> {
CommentBlock {
data: self.data.map(Into::into).map(Cow::Owned),
contents: self.contents.into_owned().into(),
}
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
@ -49,6 +91,15 @@ pub struct ExampleBlock<'a> {
pub contents: Cow<'a, str>,
}
impl ExampleBlock<'_> {
pub fn into_owned(self) -> ExampleBlock<'static> {
ExampleBlock {
data: self.data.map(Into::into).map(Cow::Owned),
contents: self.contents.into_owned().into(),
}
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
@ -57,6 +108,15 @@ pub struct ExportBlock<'a> {
pub contents: Cow<'a, str>,
}
impl ExportBlock<'_> {
pub fn into_owned(self) -> ExportBlock<'static> {
ExportBlock {
data: self.data.into_owned().into(),
contents: self.contents.into_owned().into(),
}
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
@ -66,6 +126,16 @@ pub struct SourceBlock<'a> {
pub arguments: Cow<'a, str>,
}
impl SourceBlock<'_> {
pub fn into_owned(self) -> SourceBlock<'static> {
SourceBlock {
language: self.language.into_owned().into(),
arguments: self.arguments.into_owned().into(),
contents: self.contents.into_owned().into(),
}
}
}
pub(crate) fn parse_block_element(input: &str) -> IResult<&str, (&str, Option<&str>, &str)> {
let (input, name) = preceded(tag_no_case("#+BEGIN_"), alpha1)(input)?;
let (input, args) = line(input)?;

View file

@ -90,6 +90,33 @@ impl Clock<'_> {
}
}
pub fn into_onwed(self) -> Clock<'static> {
match self {
Clock::Closed {
start,
end,
repeater,
delay,
duration,
} => Clock::Closed {
start: start.into_owned(),
end: end.into_owned(),
repeater: repeater.map(Into::into).map(Cow::Owned),
delay: delay.map(Into::into).map(Cow::Owned),
duration: duration.into_owned().into(),
},
Clock::Running {
start,
repeater,
delay,
} => Clock::Running {
start: start.into_owned(),
repeater: repeater.map(Into::into).map(Cow::Owned),
delay: delay.map(Into::into).map(Cow::Owned),
},
}
}
/// returns `true` if the clock is running
pub fn is_running(&self) -> bool {
match self {

View file

@ -35,6 +35,12 @@ impl Cookie<'_> {
},
))
}
pub fn into_owned(self) -> Cookie<'static> {
Cookie {
value: self.value.into_owned().into(),
}
}
}
#[test]

View file

@ -30,6 +30,12 @@ impl Drawer<'_> {
Ok((input, (Drawer { name: name.into() }, contents)))
}
pub fn into_owned(self) -> Drawer<'static> {
Drawer {
name: self.name.into_owned().into(),
}
}
}
#[test]

View file

@ -43,6 +43,13 @@ impl DynBlock<'_> {
),
))
}
pub fn into_owned(self) -> DynBlock<'static> {
DynBlock {
block_name: self.block_name.into_owned().into(),
arguments: self.arguments.map(Into::into).map(Cow::Owned),
}
}
}
#[test]

View file

@ -35,6 +35,12 @@ impl FnDef<'_> {
),
))
}
pub fn into_owned(self) -> FnDef<'static> {
FnDef {
label: self.label.into_owned().into(),
}
}
}
#[test]

View file

@ -50,6 +50,13 @@ impl FnRef<'_> {
},
))
}
pub fn into_owned(self) -> FnRef<'static> {
FnRef {
label: self.label.into_owned().into(),
definition: self.definition.map(Into::into).map(Cow::Owned),
}
}
}
#[test]

View file

@ -49,6 +49,15 @@ impl InlineCall<'_> {
},
))
}
pub fn into_owned(self) -> InlineCall<'static> {
InlineCall {
name: self.name.into_owned().into(),
arguments: self.arguments.into_owned().into(),
inside_header: self.inside_header.map(Into::into).map(Cow::Owned),
end_header: self.end_header.map(Into::into).map(Cow::Owned),
}
}
}
#[test]

View file

@ -40,6 +40,14 @@ impl InlineSrc<'_> {
},
))
}
pub fn into_owned(self) -> InlineSrc<'static> {
InlineSrc {
lang: self.lang.into_owned().into(),
options: self.options.map(Into::into).map(Cow::Owned),
body: self.body.into_owned().into(),
}
}
}
#[test]

View file

@ -19,6 +19,16 @@ pub struct Keyword<'a> {
pub value: Cow<'a, str>,
}
impl Keyword<'_> {
pub fn into_owned(self) -> Keyword<'static> {
Keyword {
key: self.key.into_owned().into(),
optional: self.optional.map(Into::into).map(Cow::Owned),
value: self.value.into_owned().into(),
}
}
}
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
#[derive(Debug)]
@ -26,6 +36,14 @@ pub struct BabelCall<'a> {
pub value: Cow<'a, str>,
}
impl BabelCall<'_> {
pub fn into_owned(self) -> BabelCall<'static> {
BabelCall {
value: self.value.into_owned().into(),
}
}
}
pub(crate) fn parse_keyword(input: &str) -> IResult<&str, (&str, Option<&str>, &str)> {
let (input, _) = tag("#+")(input)?;
let (input, key) = take_till(|c: char| c.is_ascii_whitespace() || c == ':' || c == '[')(input)?;

View file

@ -38,6 +38,13 @@ impl Link<'_> {
},
))
}
pub fn into_owned(self) -> Link<'static> {
Link {
path: self.path.into_owned().into(),
desc: self.desc.map(Into::into).map(Cow::Owned),
}
}
}
#[test]

View file

@ -106,6 +106,12 @@ impl ListItem<'_> {
&text[off..],
)
}
pub fn into_owned(self) -> ListItem<'static> {
ListItem {
bullet: self.bullet.into_owned().into(),
}
}
}
#[inline]

View file

@ -35,6 +35,13 @@ impl Macros<'_> {
},
))
}
pub fn into_owned(self) -> Macros<'static> {
Macros {
name: self.name.into_owned().into(),
arguments: self.arguments.map(Into::into).map(Cow::Owned),
}
}
}
#[test]

View file

@ -24,8 +24,8 @@ mod timestamp;
mod title;
pub(crate) use self::{
block::parse_block_element, emphasis::parse_emphasis, keyword::parse_keyword, rule::parse_rule,
table::parse_table_el,
block::parse_block_element, emphasis::parse_emphasis, keyword::parse_keyword,
radio_target::parse_radio_target, rule::parse_rule, table::parse_table_el,
};
pub use self::{
@ -46,7 +46,6 @@ pub use self::{
list::{List, ListItem},
macros::Macros,
planning::Planning,
radio_target::RadioTarget,
snippet::Snippet,
table::{Table, TableRow},
target::Target,
@ -74,7 +73,7 @@ pub enum Element<'a> {
Section,
Clock(Clock<'a>),
Cookie(Cookie<'a>),
RadioTarget(RadioTarget),
RadioTarget,
Drawer(Drawer<'a>),
Document,
DynBlock(DynBlock<'a>),
@ -89,7 +88,7 @@ pub enum Element<'a> {
ListItem(ListItem<'a>),
Macros(Macros<'a>),
Snippet(Snippet<'a>),
Text { value: &'a str },
Text { value: Cow<'a, str> },
Paragraph,
Rule,
Timestamp(Timestamp<'a>),
@ -110,29 +109,76 @@ pub enum Element<'a> {
impl Element<'_> {
pub fn is_container(&self) -> bool {
use Element::*;
match self {
Element::SpecialBlock(_)
| Element::QuoteBlock(_)
| Element::CenterBlock(_)
| Element::VerseBlock(_)
| Element::Bold
| Element::Document
| Element::DynBlock(_)
| Element::Headline
| Element::Italic
| Element::List(_)
| Element::ListItem(_)
| Element::Paragraph
| Element::Section
| Element::Strike
| Element::Underline
| Element::Title(_)
| Element::Table(_)
| Element::TableRow(_)
| Element::TableCell => true,
SpecialBlock(_) | QuoteBlock(_) | CenterBlock(_) | VerseBlock(_) | Bold | Document
| DynBlock(_) | Headline | Italic | List(_) | ListItem(_) | Paragraph | Section
| Strike | Underline | Title(_) | Table(_) | TableRow(_) | TableCell => true,
_ => false,
}
}
pub fn into_owned(self) -> Element<'static> {
use Element::*;
match self {
SpecialBlock(e) => SpecialBlock(e.into_owned()),
QuoteBlock(e) => QuoteBlock(e.into_owned()),
CenterBlock(e) => CenterBlock(e.into_owned()),
VerseBlock(e) => VerseBlock(e.into_owned()),
CommentBlock(e) => CommentBlock(e.into_owned()),
ExampleBlock(e) => ExampleBlock(e.into_owned()),
ExportBlock(e) => ExportBlock(e.into_owned()),
SourceBlock(e) => SourceBlock(e.into_owned()),
BabelCall(e) => BabelCall(e.into_owned()),
Section => Section,
Clock(e) => Clock(e.into_onwed()),
Cookie(e) => Cookie(e.into_owned()),
RadioTarget => RadioTarget,
Drawer(e) => Drawer(e.into_owned()),
Document => Document,
DynBlock(e) => DynBlock(e.into_owned()),
FnDef(e) => FnDef(e.into_owned()),
FnRef(e) => FnRef(e.into_owned()),
Headline => Headline,
InlineCall(e) => InlineCall(e.into_owned()),
InlineSrc(e) => InlineSrc(e.into_owned()),
Keyword(e) => Keyword(e.into_owned()),
Link(e) => Link(e.into_owned()),
List(e) => List(e),
ListItem(e) => ListItem(e.into_owned()),
Macros(e) => Macros(e.into_owned()),
Snippet(e) => Snippet(e.into_owned()),
Text { value } => Text {
value: value.into_owned().into(),
},
Paragraph => Paragraph,
Rule => Rule,
Timestamp(e) => Timestamp(e.into_owned()),
Target(e) => Target(e.into_owned()),
Bold => Bold,
Strike => Strike,
Italic => Italic,
Underline => Underline,
Verbatim { value } => Verbatim {
value: value.into_owned().into(),
},
Code { value } => Code {
value: value.into_owned().into(),
},
Comment { value } => Comment {
value: value.into_owned().into(),
},
FixedWidth { value } => FixedWidth {
value: value.into_owned().into(),
},
Title(e) => Title(e.into_owned()),
Table(e) => Table(e.into_owned()),
TableRow(e) => TableRow(e),
TableCell => TableCell,
}
}
}
macro_rules! impl_from {
@ -181,7 +227,6 @@ impl_from!(
Table,
Title,
VerseBlock;
RadioTarget,
List,
TableRow
);

View file

@ -64,6 +64,14 @@ impl Planning<'_> {
))
}
}
pub fn into_owned(self) -> Planning<'static> {
Planning {
deadline: self.deadline.map(|x| x.into_owned()),
scheduled: self.scheduled.map(|x| x.into_owned()),
closed: self.closed.map(|x| x.into_owned()),
}
}
}
#[test]

View file

@ -5,17 +5,10 @@ use nom::{
IResult,
};
use crate::elements::Element;
// TODO: text-markup, entities, latex-fragments, subscript and superscript
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]
#[derive(Debug)]
pub struct RadioTarget;
impl RadioTarget {
#[inline]
pub(crate) fn parse(input: &str) -> IResult<&str, (Element, &str)> {
#[inline]
pub(crate) fn parse_radio_target(input: &str) -> IResult<&str, &str> {
let (input, contents) = delimited(
tag("<<<"),
verify(
@ -25,24 +18,17 @@ impl RadioTarget {
tag(">>>"),
)(input)?;
Ok((input, (Element::RadioTarget(RadioTarget), contents)))
}
Ok((input, contents))
}
#[test]
fn parse() {
assert_eq!(
RadioTarget::parse("<<<target>>>"),
Ok(("", (Element::RadioTarget(RadioTarget), "target")))
);
assert_eq!(
RadioTarget::parse("<<<tar get>>>"),
Ok(("", (Element::RadioTarget(RadioTarget), "tar get")))
);
assert!(RadioTarget::parse("<<<target >>>").is_err());
assert!(RadioTarget::parse("<<< target>>>").is_err());
assert!(RadioTarget::parse("<<<ta<get>>>").is_err());
assert!(RadioTarget::parse("<<<ta>get>>>").is_err());
assert!(RadioTarget::parse("<<<ta\nget>>>").is_err());
assert!(RadioTarget::parse("<<<target>>").is_err());
assert_eq!(parse_radio_target("<<<target>>>"), Ok(("", "target")));
assert_eq!(parse_radio_target("<<<tar get>>>"), Ok(("", "tar get")));
assert!(parse_radio_target("<<<target >>>").is_err());
assert!(parse_radio_target("<<< target>>>").is_err());
assert!(parse_radio_target("<<<ta<get>>>").is_err());
assert!(parse_radio_target("<<<ta>get>>>").is_err());
assert!(parse_radio_target("<<<ta\nget>>>").is_err());
assert!(parse_radio_target("<<<target>>").is_err());
}

View file

@ -35,6 +35,13 @@ impl Snippet<'_> {
},
))
}
pub fn into_owned(self) -> Snippet<'static> {
Snippet {
name: self.name.into_owned().into(),
value: self.value.into_owned().into(),
}
}
}
#[test]

View file

@ -18,6 +18,19 @@ pub enum Table<'a> {
TableEl { value: Cow<'a, str> },
}
impl Table<'_> {
pub fn into_owned(self) -> Table<'static> {
match self {
Table::Org { tblfm } => Table::Org {
tblfm: tblfm.map(Into::into).map(Cow::Owned),
},
Table::TableEl { value } => Table::TableEl {
value: value.into_owned().into(),
},
}
}
}
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(feature = "ser", derive(serde::Serialize))]

View file

@ -33,6 +33,12 @@ impl Target<'_> {
},
))
}
pub fn into_owned(self) -> Target<'static> {
Target {
target: self.target.into_owned().into(),
}
}
}
#[test]

View file

@ -30,47 +30,17 @@ pub struct Datetime<'a> {
pub minute: Option<u8>,
}
fn parse_time(input: &str) -> IResult<&str, (u8, u8)> {
let (input, hour) = map_res(take_while_m_n(1, 2, |c: char| c.is_ascii_digit()), |num| {
u8::from_str_radix(num, 10)
})(input)?;
let (input, _) = tag(":")(input)?;
let (input, minute) = map_res(take(2usize), |num| u8::from_str_radix(num, 10))(input)?;
Ok((input, (hour, minute)))
}
fn parse_datetime(input: &str) -> IResult<&str, Datetime<'_>> {
let parse_u8 = |num| u8::from_str_radix(num, 10);
let (input, year) = map_res(take(4usize), |num| u16::from_str_radix(num, 10))(input)?;
let (input, _) = tag("-")(input)?;
let (input, month) = map_res(take(2usize), parse_u8)(input)?;
let (input, _) = tag("-")(input)?;
let (input, day) = map_res(take(2usize), parse_u8)(input)?;
let (input, _) = space1(input)?;
let (input, dayname) = take_while(|c: char| {
!c.is_ascii_whitespace()
&& !c.is_ascii_digit()
&& c != '+'
&& c != '-'
&& c != ']'
&& c != '>'
})(input)?;
let (input, (hour, minute)) = map(opt(preceded(space1, parse_time)), |time| {
(time.map(|t| t.0), time.map(|t| t.1))
})(input)?;
Ok((
input,
impl Datetime<'_> {
pub fn into_owned(self) -> Datetime<'static> {
Datetime {
year,
month,
day,
dayname: dayname.into(),
hour,
minute,
},
))
year: self.year,
month: self.month,
day: self.day,
dayname: self.dayname.into_owned().into(),
hour: self.hour,
minute: self.minute,
}
}
}
#[cfg(feature = "chrono")]
@ -281,6 +251,97 @@ impl Timestamp<'_> {
},
))
}
pub fn into_owned(self) -> Timestamp<'static> {
match self {
Timestamp::Active {
start,
repeater,
delay,
} => Timestamp::Active {
start: start.into_owned(),
repeater: repeater.map(Into::into).map(Cow::Owned),
delay: delay.map(Into::into).map(Cow::Owned),
},
Timestamp::Inactive {
start,
repeater,
delay,
} => Timestamp::Inactive {
start: start.into_owned(),
repeater: repeater.map(Into::into).map(Cow::Owned),
delay: delay.map(Into::into).map(Cow::Owned),
},
Timestamp::ActiveRange {
start,
end,
repeater,
delay,
} => Timestamp::ActiveRange {
start: start.into_owned(),
end: end.into_owned(),
repeater: repeater.map(Into::into).map(Cow::Owned),
delay: delay.map(Into::into).map(Cow::Owned),
},
Timestamp::InactiveRange {
start,
end,
repeater,
delay,
} => Timestamp::InactiveRange {
start: start.into_owned(),
end: end.into_owned(),
repeater: repeater.map(Into::into).map(Cow::Owned),
delay: delay.map(Into::into).map(Cow::Owned),
},
Timestamp::Diary { value } => Timestamp::Diary {
value: value.into_owned().into(),
},
}
}
}
fn parse_time(input: &str) -> IResult<&str, (u8, u8)> {
let (input, hour) = map_res(take_while_m_n(1, 2, |c: char| c.is_ascii_digit()), |num| {
u8::from_str_radix(num, 10)
})(input)?;
let (input, _) = tag(":")(input)?;
let (input, minute) = map_res(take(2usize), |num| u8::from_str_radix(num, 10))(input)?;
Ok((input, (hour, minute)))
}
fn parse_datetime(input: &str) -> IResult<&str, Datetime<'_>> {
let parse_u8 = |num| u8::from_str_radix(num, 10);
let (input, year) = map_res(take(4usize), |num| u16::from_str_radix(num, 10))(input)?;
let (input, _) = tag("-")(input)?;
let (input, month) = map_res(take(2usize), parse_u8)(input)?;
let (input, _) = tag("-")(input)?;
let (input, day) = map_res(take(2usize), parse_u8)(input)?;
let (input, _) = space1(input)?;
let (input, dayname) = take_while(|c: char| {
!c.is_ascii_whitespace()
&& !c.is_ascii_digit()
&& c != '+'
&& c != '-'
&& c != ']'
&& c != '>'
})(input)?;
let (input, (hour, minute)) = map(opt(preceded(space1, parse_time)), |time| {
(time.map(|t| t.0), time.map(|t| t.1))
})(input)?;
Ok((
input,
Datetime {
year,
month,
day,
dayname: dayname.into(),
hour,
minute,
},
))
}
// TODO

View file

@ -71,6 +71,26 @@ impl Title<'_> {
),
))
}
pub fn into_owned(self) -> Title<'static> {
Title {
level: self.level,
priority: self.priority,
tags: self
.tags
.into_iter()
.map(|s| s.into_owned().into())
.collect(),
keyword: self.keyword.map(Into::into).map(Cow::Owned),
raw: self.raw.into_owned().into(),
planning: self.planning.map(|p| Box::new(p.into_owned())),
properties: self
.properties
.into_iter()
.map(|(k, v)| (k.into_owned().into(), v.into_owned().into()))
.collect(),
}
}
}
fn parse_headline<'a>(

View file

@ -101,7 +101,7 @@ pub trait HtmlHandler<E: From<Error>> {
Escape(link.desc.as_ref().unwrap_or(&link.path)),
)?,
Macros(_macros) => (),
RadioTarget(_radio_target) => (),
RadioTarget => (),
Snippet(snippet) => {
if snippet.name.eq_ignore_ascii_case("HTML") {
write!(w, "{}", snippet.value)?;

View file

@ -81,7 +81,7 @@ pub trait OrgHandler<E: From<Error>> {
write!(&mut w, "]")?;
}
Macros(_macros) => (),
RadioTarget(_radio_target) => (),
RadioTarget => (),
Snippet(snippet) => write!(w, "@@{}:{}@@", snippet.name, snippet.value)?,
Target(_target) => (),
Text { value } => write!(w, "{}", value)?,

View file

@ -5,7 +5,7 @@ use crate::config::ParseConfig;
use crate::elements::Element;
use crate::export::*;
use crate::node::HeadlineNode;
use crate::parsers::*;
use crate::parsers::{parse_container, Container};
pub struct Org<'a> {
pub(crate) arena: Arena<Element<'a>>,
@ -27,31 +27,7 @@ impl Org<'_> {
let mut arena = Arena::new();
let node = arena.new_node(Element::Document);
let containers = &mut vec![Container::Document { content, node }];
while let Some(container) = containers.pop() {
match container {
Container::Document { content, node } => {
parse_section_and_headlines(&mut arena, content, node, containers);
}
Container::Headline { content, node } => {
parse_headline_content(&mut arena, content, node, containers, config);
}
Container::Block { content, node } => {
parse_blocks(&mut arena, content, node, containers);
}
Container::Inline { content, node } => {
parse_inlines(&mut arena, content, node, containers);
}
Container::List {
content,
node,
indent,
} => {
parse_list_items(&mut arena, content, indent, node, containers);
}
}
}
parse_container(&mut arena, Container::Document { content, node }, config);
Org { arena, root: node }
}

View file

@ -1,6 +1,7 @@
// parser related functions
use std::borrow::Cow;
use std::marker::PhantomData;
use indextree::{Arena, NodeId};
use jetscii::bytes;
@ -80,6 +81,38 @@ pub enum Container<'a> {
},
}
pub fn parse_container<'a, T: ElementArena<'a>>(
arena: &mut T,
container: Container<'a>,
config: &ParseConfig,
) {
let containers = &mut vec![container];
while let Some(container) = containers.pop() {
match container {
Container::Document { content, node } => {
parse_section_and_headlines(arena, content, node, containers);
}
Container::Headline { content, node } => {
parse_headline_content(arena, content, node, containers, config);
}
Container::Block { content, node } => {
parse_blocks(arena, content, node, containers);
}
Container::Inline { content, node } => {
parse_inlines(arena, content, node, containers);
}
Container::List {
content,
node,
indent,
} => {
parse_list_items(arena, content, indent, node, containers);
}
}
}
}
pub fn parse_headline_content<'a, T: ElementArena<'a>>(
arena: &mut T,
content: &'a str,
@ -397,7 +430,12 @@ pub fn parse_inlines<'a, T: ElementArena<'a>>(
macro_rules! insert_text {
($value:expr) => {
arena.insert_before_last_child(Element::Text { value: $value }, parent);
arena.insert_before_last_child(
Element::Text {
value: $value.into(),
},
parent,
);
pos = 0;
};
}
@ -449,7 +487,7 @@ pub fn parse_inlines<'a, T: ElementArena<'a>>(
}
if !text.is_empty() {
arena.push_element(Element::Text { value: text }, parent);
arena.push_element(Element::Text { value: text.into() }, parent);
}
}
@ -478,8 +516,8 @@ pub fn parse_inline<'a, T: ElementArena<'a>>(
}
}
b'<' => {
if let Ok((tail, (radio, _content))) = RadioTarget::parse(contents) {
arena.push_element(radio, parent);
if let Ok((tail, _content)) = parse_radio_target(contents) {
arena.push_element(Element::RadioTarget, parent);
return Some(tail);
} else if let Ok((tail, target)) = Target::parse(contents) {
arena.push_element(target, parent);
@ -717,7 +755,7 @@ pub fn take_one_word(input: &str) -> IResult<&str, &str> {
}
#[test]
fn test_skip_empty_lines() {
pub fn test_skip_empty_lines() {
assert_eq!(skip_empty_lines("foo"), "foo");
assert_eq!(skip_empty_lines(" foo"), " foo");
assert_eq!(skip_empty_lines(" \nfoo\n"), "foo\n");