feat(element): distinguish block by its name
This commit is contained in:
parent
5b9ceebea4
commit
da18d87aeb
|
@ -1,19 +1,15 @@
|
|||
use memchr::{memchr, memchr_iter};
|
||||
|
||||
use crate::elements::Element;
|
||||
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub struct Block<'a> {
|
||||
pub name: &'a str,
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub args: Option<&'a str>,
|
||||
}
|
||||
|
||||
impl Block<'_> {
|
||||
#[inline]
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, Element<'_>, &str)> {
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, Block<'_>, &str)> {
|
||||
debug_assert!(text.starts_with("#+"));
|
||||
|
||||
if text.len() <= 8 || text[2..8].to_uppercase() != "BEGIN_" {
|
||||
|
@ -36,18 +32,14 @@ impl Block<'_> {
|
|||
|
||||
for i in lines {
|
||||
if text[pos..i].trim().eq_ignore_ascii_case(&end) {
|
||||
return Some((
|
||||
&text[i + 1..],
|
||||
Element::Block(Block { name, args }),
|
||||
&text[off..pos],
|
||||
));
|
||||
return Some((&text[i + 1..], Block { name, args }, &text[off..pos]));
|
||||
}
|
||||
|
||||
pos = i + 1;
|
||||
}
|
||||
|
||||
if text[pos..].trim().eq_ignore_ascii_case(&end) {
|
||||
Some(("", Element::Block(Block { name, args }), &text[off..pos]))
|
||||
Some(("", Block { name, args }, &text[off..pos]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -60,10 +52,10 @@ fn parse() {
|
|||
Block::parse("#+BEGIN_SRC\n#+END_SRC"),
|
||||
Some((
|
||||
"",
|
||||
Element::Block(Block {
|
||||
Block {
|
||||
name: "SRC",
|
||||
args: None,
|
||||
}),
|
||||
},
|
||||
""
|
||||
))
|
||||
);
|
||||
|
@ -71,12 +63,74 @@ fn parse() {
|
|||
Block::parse("#+BEGIN_SRC javascript \nconsole.log('Hello World!');\n#+END_SRC\n"),
|
||||
Some((
|
||||
"",
|
||||
Element::Block(Block {
|
||||
Block {
|
||||
name: "SRC",
|
||||
args: Some("javascript"),
|
||||
}),
|
||||
},
|
||||
"console.log('Hello World!');\n"
|
||||
))
|
||||
);
|
||||
// TODO: more testing
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub struct SpecialBlock<'a> {
|
||||
pub parameters: Option<&'a str>,
|
||||
pub name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub struct QuoteBlock<'a> {
|
||||
pub parameters: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub struct CenterBlock<'a> {
|
||||
pub parameters: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub struct VerseBlock<'a> {
|
||||
pub parameters: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub struct CommentBlock<'a> {
|
||||
pub data: Option<&'a str>,
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub struct ExampleBlock<'a> {
|
||||
pub data: Option<&'a str>,
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub struct ExportBlock<'a> {
|
||||
pub data: &'a str,
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub struct SourceBlock<'a> {
|
||||
pub contents: &'a str,
|
||||
pub language: &'a str,
|
||||
pub arguments: &'a str,
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use memchr::{memchr, memchr2};
|
|||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub struct Cookie<'a> {
|
||||
value: &'a str,
|
||||
pub value: &'a str,
|
||||
}
|
||||
|
||||
impl Cookie<'_> {
|
||||
|
|
|
@ -23,9 +23,13 @@ mod timestamp;
|
|||
mod title;
|
||||
|
||||
pub(crate) use emphasis::parse as parse_emphasis;
|
||||
pub(crate) use block::Block;
|
||||
|
||||
pub use self::{
|
||||
block::Block,
|
||||
block::{
|
||||
CenterBlock, CommentBlock, ExampleBlock, ExportBlock, QuoteBlock, SourceBlock,
|
||||
SpecialBlock, VerseBlock,
|
||||
},
|
||||
clock::Clock,
|
||||
cookie::Cookie,
|
||||
drawer::Drawer,
|
||||
|
@ -53,7 +57,14 @@ pub use self::{
|
|||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(tag = "type", rename_all = "snake_case"))]
|
||||
pub enum Element<'a> {
|
||||
Block(Block<'a>),
|
||||
SpecialBlock(SpecialBlock<'a>),
|
||||
QuoteBlock(QuoteBlock<'a>),
|
||||
CenterBlock(CenterBlock<'a>),
|
||||
VerseBlock(VerseBlock<'a>),
|
||||
CommentBlock(CommentBlock<'a>),
|
||||
ExampleBlock(ExampleBlock<'a>),
|
||||
ExportBlock(ExportBlock<'a>),
|
||||
SourceBlock(SourceBlock<'a>),
|
||||
BabelCall(BabelCall<'a>),
|
||||
Section,
|
||||
Clock(Clock<'a>),
|
||||
|
@ -93,7 +104,10 @@ pub enum Element<'a> {
|
|||
impl Element<'_> {
|
||||
pub fn is_container(&self) -> bool {
|
||||
match self {
|
||||
Element::Block(_)
|
||||
Element::SpecialBlock(_)
|
||||
| Element::QuoteBlock(_)
|
||||
| Element::CenterBlock(_)
|
||||
| Element::VerseBlock(_)
|
||||
| Element::Bold
|
||||
| Element::Document
|
||||
| Element::DynBlock(_)
|
||||
|
@ -112,30 +126,50 @@ impl Element<'_> {
|
|||
}
|
||||
|
||||
macro_rules! impl_from {
|
||||
($ident:ident) => {
|
||||
impl<'a> From<$ident<'a>> for Element<'a> {
|
||||
fn from(ele: $ident<'a>) -> Element<'a> {
|
||||
Element::$ident(ele)
|
||||
($($ele0:ident),*; $($ele1:ident),*) => {
|
||||
$(
|
||||
impl<'a> From<$ele0<'a>> for Element<'a> {
|
||||
fn from(ele: $ele0<'a>) -> Element<'a> {
|
||||
Element::$ele0(ele)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
$(
|
||||
impl<'a> From<$ele1> for Element<'a> {
|
||||
fn from(ele: $ele1) -> Element<'a> {
|
||||
Element::$ele1(ele)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
impl_from!(Block);
|
||||
impl_from!(BabelCall);
|
||||
impl_from!(Clock);
|
||||
impl_from!(Cookie);
|
||||
impl_from!(Drawer);
|
||||
impl_from!(DynBlock);
|
||||
impl_from!(FnDef);
|
||||
impl_from!(FnRef);
|
||||
impl_from!(InlineCall);
|
||||
impl_from!(InlineSrc);
|
||||
impl_from!(Keyword);
|
||||
impl_from!(Link);
|
||||
impl_from!(ListItem);
|
||||
impl_from!(Macros);
|
||||
impl_from!(Planning);
|
||||
impl_from!(Snippet);
|
||||
impl_from!(Timestamp);
|
||||
impl_from!(Target);
|
||||
impl_from!(
|
||||
BabelCall,
|
||||
CenterBlock,
|
||||
Clock,
|
||||
CommentBlock,
|
||||
Cookie,
|
||||
Drawer,
|
||||
DynBlock,
|
||||
ExampleBlock,
|
||||
ExportBlock,
|
||||
FnDef,
|
||||
FnRef,
|
||||
InlineCall,
|
||||
InlineSrc,
|
||||
Keyword,
|
||||
Link,
|
||||
ListItem,
|
||||
Macros,
|
||||
Planning,
|
||||
QuoteBlock,
|
||||
Snippet,
|
||||
SourceBlock,
|
||||
SpecialBlock,
|
||||
Target,
|
||||
Timestamp,
|
||||
VerseBlock;
|
||||
RadioTarget,
|
||||
List
|
||||
);
|
||||
|
|
|
@ -34,7 +34,10 @@ pub trait HtmlHandler<E: From<Error>> {
|
|||
|
||||
match element {
|
||||
// container elements
|
||||
Block(_block) => write!(w, "<div>")?,
|
||||
SpecialBlock(_) => (),
|
||||
QuoteBlock(_) => write!(w, "<blockquote>")?,
|
||||
CenterBlock(_) => write!(w, "<div class=\"center\">")?,
|
||||
VerseBlock(_) => write!(w, "<p class=\"verse\">")?,
|
||||
Bold => write!(w, "<b>")?,
|
||||
Document => write!(w, "<main>")?,
|
||||
DynBlock(_dyn_block) => (),
|
||||
|
@ -53,11 +56,37 @@ pub trait HtmlHandler<E: From<Error>> {
|
|||
Strike => write!(w, "<s>")?,
|
||||
Underline => write!(w, "<u>")?,
|
||||
// non-container elements
|
||||
BabelCall(_babel_call) => (),
|
||||
InlineSrc(inline_src) => write!(w, "<code>{}</code>", Escape(inline_src.body))?,
|
||||
CommentBlock(_) => (),
|
||||
ExampleBlock(block) => {
|
||||
write!(w, "<pre class=\"example\">{}</pre>", Escape(block.contents))?
|
||||
}
|
||||
ExportBlock(block) => {
|
||||
if block.data.eq_ignore_ascii_case("HTML") {
|
||||
write!(w, "{}", block.contents)?
|
||||
}
|
||||
}
|
||||
SourceBlock(block) => {
|
||||
if block.language.is_empty() {
|
||||
write!(w, "<pre class=\"example\">{}</pre>", Escape(block.contents))?;
|
||||
} else {
|
||||
write!(
|
||||
w,
|
||||
"<div class=\"org-src-container\"><pre class=\"src src-{}\">{}</pre></div>",
|
||||
block.language,
|
||||
Escape(block.contents)
|
||||
)?;
|
||||
}
|
||||
}
|
||||
BabelCall(_) => (),
|
||||
InlineSrc(inline_src) => write!(
|
||||
w,
|
||||
"<code class=\"src src-{}\">{}</code>",
|
||||
inline_src.lang,
|
||||
Escape(inline_src.body)
|
||||
)?,
|
||||
Code { value } => write!(w, "<code>{}</code>", Escape(value))?,
|
||||
FnRef(_fn_ref) => (),
|
||||
InlineCall(_inline_call) => (),
|
||||
InlineCall(_) => (),
|
||||
Link(link) => write!(
|
||||
w,
|
||||
"<a href=\"{}\">{}</a>",
|
||||
|
@ -74,16 +103,85 @@ pub trait HtmlHandler<E: From<Error>> {
|
|||
}
|
||||
Target(_target) => (),
|
||||
Text { value } => write!(w, "{}", Escape(value))?,
|
||||
Timestamp(_timestamp) => (),
|
||||
Timestamp(timestamp) => {
|
||||
use crate::elements::{Date, Time, Timestamp::*};
|
||||
|
||||
write!(
|
||||
&mut w,
|
||||
"<span class=\"timestamp-wrapper\"><span class=\"timestamp\">"
|
||||
)?;
|
||||
|
||||
fn write_datetime<W: Write>(
|
||||
mut w: W,
|
||||
start: &str,
|
||||
date: &Date,
|
||||
time: &Option<Time>,
|
||||
end: &str,
|
||||
) -> Result<(), Error> {
|
||||
write!(w, "{}", start)?;
|
||||
write!(
|
||||
w,
|
||||
"{}-{}-{} {}",
|
||||
date.year,
|
||||
date.month,
|
||||
date.day,
|
||||
Escape(date.dayname)
|
||||
)?;
|
||||
if let Some(time) = time {
|
||||
write!(w, " {}:{}", time.hour, time.minute)?;
|
||||
}
|
||||
write!(w, "{}", end)
|
||||
}
|
||||
|
||||
match timestamp {
|
||||
Active {
|
||||
start_date,
|
||||
start_time,
|
||||
..
|
||||
} => {
|
||||
write_datetime(&mut w, "<", start_date, start_time, ">")?;
|
||||
}
|
||||
Inactive {
|
||||
start_date,
|
||||
start_time,
|
||||
..
|
||||
} => {
|
||||
write_datetime(&mut w, "[", start_date, start_time, "]")?;
|
||||
}
|
||||
ActiveRange {
|
||||
start_date,
|
||||
start_time,
|
||||
end_date,
|
||||
end_time,
|
||||
..
|
||||
} => {
|
||||
write_datetime(&mut w, "<", start_date, start_time, ">–")?;
|
||||
write_datetime(&mut w, "<", end_date, end_time, ">")?;
|
||||
}
|
||||
InactiveRange {
|
||||
start_date,
|
||||
start_time,
|
||||
end_date,
|
||||
end_time,
|
||||
..
|
||||
} => {
|
||||
write_datetime(&mut w, "[", start_date, start_time, "]–")?;
|
||||
write_datetime(&mut w, "[", end_date, end_time, "]")?;
|
||||
}
|
||||
Diary(value) => write!(&mut w, "<%%({})>", Escape(value))?,
|
||||
}
|
||||
|
||||
write!(&mut w, "</span></span>")?;
|
||||
}
|
||||
Verbatim { value } => write!(&mut w, "<code>{}</code>", Escape(value))?,
|
||||
FnDef(_fn_def) => (),
|
||||
Clock(_clock) => (),
|
||||
Comment { value } => write!(w, "<!--\n{}\n-->", Escape(value))?,
|
||||
FixedWidth { value } => write!(w, "<pre>{}</pre>", Escape(value))?,
|
||||
Comment { .. } => (),
|
||||
FixedWidth { value } => write!(w, "<pre class=\"example\">{}</pre>", Escape(value))?,
|
||||
Keyword(_keyword) => (),
|
||||
Drawer(_drawer) => (),
|
||||
Rule => write!(w, "<hr>")?,
|
||||
Cookie(_cookie) => (),
|
||||
Cookie(cookie) => write!(w, "<code>{}</code>", cookie.value)?,
|
||||
Title(title) => write!(w, "<h{}>", if title.level <= 6 { title.level } else { 6 })?,
|
||||
}
|
||||
|
||||
|
@ -94,7 +192,10 @@ pub trait HtmlHandler<E: From<Error>> {
|
|||
|
||||
match element {
|
||||
// container elements
|
||||
Block(_block) => write!(w, "</div>")?,
|
||||
SpecialBlock(_) => (),
|
||||
QuoteBlock(_) => write!(w, "</blockquote>")?,
|
||||
CenterBlock(_) => write!(w, "</div>")?,
|
||||
VerseBlock(_) => write!(w, "</p>")?,
|
||||
Bold => write!(w, "</b>")?,
|
||||
Document => write!(w, "</main>")?,
|
||||
DynBlock(_dyn_block) => (),
|
||||
|
|
|
@ -7,13 +7,10 @@ pub trait OrgHandler<E: From<Error>> {
|
|||
|
||||
match element {
|
||||
// container elements
|
||||
Block(block) => {
|
||||
write!(&mut w, "#+BEGIN_{}", block.name)?;
|
||||
if let Some(parameters) = block.args {
|
||||
write!(&mut w, " {}", parameters)?;
|
||||
}
|
||||
writeln!(&mut w)?;
|
||||
}
|
||||
SpecialBlock(block) => writeln!(w, "#+BEGIN_{}", block.name)?,
|
||||
QuoteBlock(_) => write!(w, "#+BEGIN_QUOTE")?,
|
||||
CenterBlock(_) => write!(w, "#+BEGIN_CENTER")?,
|
||||
VerseBlock(_) => write!(w, "#+BEGIN_VERSE")?,
|
||||
Bold => write!(w, "*")?,
|
||||
Document => (),
|
||||
DynBlock(dyn_block) => {
|
||||
|
@ -33,6 +30,22 @@ pub trait OrgHandler<E: From<Error>> {
|
|||
Underline => write!(w, "_")?,
|
||||
Drawer(drawer) => writeln!(w, ":{}:", drawer.name)?,
|
||||
// non-container elements
|
||||
CommentBlock(block) => {
|
||||
writeln!(w, "#+BEGIN_COMMENT\n{}\n#+END_COMMENT", block.contents)?
|
||||
}
|
||||
ExampleBlock(block) => {
|
||||
writeln!(w, "#+BEGIN_EXAMPLE\n{}\n#+END_EXAMPLE", block.contents)?
|
||||
}
|
||||
ExportBlock(block) => writeln!(
|
||||
w,
|
||||
"#+BEGIN_EXPORT {}\n{}\n#+END_EXPORT",
|
||||
block.data, block.contents
|
||||
)?,
|
||||
SourceBlock(block) => writeln!(
|
||||
w,
|
||||
"#+BEGIN_SRC {}\n{}\n#+END_SRC",
|
||||
block.language, block.contents
|
||||
)?,
|
||||
BabelCall(_babel_call) => (),
|
||||
InlineSrc(inline_src) => {
|
||||
write!(&mut w, "src_{}", inline_src.lang)?;
|
||||
|
@ -78,20 +91,23 @@ pub trait OrgHandler<E: From<Error>> {
|
|||
Timestamp(timestamp) => {
|
||||
use crate::elements::{Date, Time, Timestamp::*};
|
||||
|
||||
fn write_date<W: Write>(mut w: W, date: &Date) -> Result<(), Error> {
|
||||
fn write_datetime<W: Write>(
|
||||
mut w: W,
|
||||
start: &str,
|
||||
date: &Date,
|
||||
time: &Option<Time>,
|
||||
end: &str,
|
||||
) -> Result<(), Error> {
|
||||
write!(w, "{}", start)?;
|
||||
write!(
|
||||
w,
|
||||
"{}-{}-{} {}",
|
||||
date.year, date.month, date.day, date.dayname
|
||||
)
|
||||
}
|
||||
|
||||
fn write_time<W: Write>(mut w: W, time: &Option<Time>) -> Result<(), Error> {
|
||||
)?;
|
||||
if let Some(time) = time {
|
||||
write!(w, " {}:{}", time.hour, time.minute)
|
||||
} else {
|
||||
Ok(())
|
||||
write!(w, " {}:{}", time.hour, time.minute,)?;
|
||||
}
|
||||
write!(w, "{}", end)
|
||||
}
|
||||
|
||||
match timestamp {
|
||||
|
@ -100,20 +116,14 @@ pub trait OrgHandler<E: From<Error>> {
|
|||
start_time,
|
||||
..
|
||||
} => {
|
||||
write!(&mut w, "<")?;
|
||||
write_date(&mut w, start_date)?;
|
||||
write_time(&mut w, start_time)?;
|
||||
write!(&mut w, ">")?;
|
||||
write_datetime(&mut w, "<", start_date, start_time, ">")?;
|
||||
}
|
||||
Inactive {
|
||||
start_date,
|
||||
start_time,
|
||||
..
|
||||
} => {
|
||||
write!(&mut w, "[")?;
|
||||
write_date(&mut w, start_date)?;
|
||||
write_time(&mut w, start_time)?;
|
||||
write!(&mut w, "]")?;
|
||||
write_datetime(&mut w, "[", start_date, start_time, "]")?;
|
||||
}
|
||||
ActiveRange {
|
||||
start_date,
|
||||
|
@ -122,13 +132,8 @@ pub trait OrgHandler<E: From<Error>> {
|
|||
end_time,
|
||||
..
|
||||
} => {
|
||||
write!(&mut w, "<")?;
|
||||
write_date(&mut w, start_date)?;
|
||||
write_time(&mut w, start_time)?;
|
||||
write!(&mut w, ">--<")?;
|
||||
write_date(&mut w, end_date)?;
|
||||
write_time(&mut w, end_time)?;
|
||||
write!(&mut w, ">")?;
|
||||
write_datetime(&mut w, "<", start_date, start_time, ">--")?;
|
||||
write_datetime(&mut w, "<", end_date, end_time, ">")?;
|
||||
}
|
||||
InactiveRange {
|
||||
start_date,
|
||||
|
@ -137,13 +142,8 @@ pub trait OrgHandler<E: From<Error>> {
|
|||
end_time,
|
||||
..
|
||||
} => {
|
||||
write!(&mut w, "[")?;
|
||||
write_date(&mut w, start_date)?;
|
||||
write_time(&mut w, start_time)?;
|
||||
write!(&mut w, "]--[")?;
|
||||
write_date(&mut w, end_date)?;
|
||||
write_time(&mut w, end_time)?;
|
||||
write!(&mut w, "]")?;
|
||||
write_datetime(&mut w, "[", start_date, start_time, "]--")?;
|
||||
write_datetime(&mut w, "[", end_date, end_time, "]")?;
|
||||
}
|
||||
Diary(value) => write!(w, "<%%({})>", value)?,
|
||||
}
|
||||
|
@ -184,7 +184,10 @@ pub trait OrgHandler<E: From<Error>> {
|
|||
|
||||
match element {
|
||||
// container elements
|
||||
Block(block) => writeln!(w, "#+END_{}", block.name)?,
|
||||
SpecialBlock(block) => writeln!(w, "#+END_{}", block.name)?,
|
||||
QuoteBlock(_) => writeln!(w, "#+END_QUOTE")?,
|
||||
CenterBlock(_) => writeln!(w, "#+END_CENTER")?,
|
||||
VerseBlock(_) => writeln!(w, "#+END_VERSE")?,
|
||||
Bold => write!(w, "*")?,
|
||||
Document => (),
|
||||
DynBlock(_dyn_block) => writeln!(w, "#+END:")?,
|
||||
|
|
81
src/org.rs
81
src/org.rs
|
@ -315,12 +315,12 @@ fn parse_block<'a>(
|
|||
let mut last_end = 1; // ":"
|
||||
for i in memchr_iter(b'\n', contents.as_bytes()) {
|
||||
last_end = i + 1;
|
||||
let line = &contents[last_end..];
|
||||
if !(line == ":" || line.starts_with(": ") || line.starts_with(":\n")) {
|
||||
let tail = contents[last_end..].trim_start();
|
||||
if !(tail == ":" || tail.starts_with(": ") || tail.starts_with(":\n")) {
|
||||
let fixed_width = arena.new_node(Element::FixedWidth {
|
||||
value: &contents[0..i + 1],
|
||||
value: &contents[0..last_end],
|
||||
});
|
||||
return Some((&contents[i + 1..], fixed_width));
|
||||
return Some((&contents[last_end..], fixed_width));
|
||||
}
|
||||
}
|
||||
let fixed_width = arena.new_node(Element::FixedWidth {
|
||||
|
@ -334,12 +334,12 @@ fn parse_block<'a>(
|
|||
let mut last_end = 1; // "#"
|
||||
for i in memchr_iter(b'\n', contents.as_bytes()) {
|
||||
last_end = i + 1;
|
||||
let line = &contents[last_end..];
|
||||
let line = contents[last_end..].trim_start();
|
||||
if !(line == "#" || line.starts_with("# ") || line.starts_with("#\n")) {
|
||||
let comment = arena.new_node(Element::Comment {
|
||||
value: &contents[0..i + 1],
|
||||
value: &contents[0..last_end],
|
||||
});
|
||||
return Some((&contents[i + 1..], comment));
|
||||
return Some((&contents[last_end..], comment));
|
||||
}
|
||||
}
|
||||
let comment = arena.new_node(Element::Comment {
|
||||
|
@ -350,9 +350,70 @@ fn parse_block<'a>(
|
|||
|
||||
if tail.starts_with("#+") {
|
||||
if let Some((tail, block, content)) = Block::parse(tail) {
|
||||
let node = arena.new_node(block);
|
||||
containers.push(Container::Block { content, node });
|
||||
Some((tail, node))
|
||||
match &*block.name.to_uppercase() {
|
||||
"CENTER" => {
|
||||
let node = arena.new_node(Element::CenterBlock(CenterBlock {
|
||||
parameters: block.args,
|
||||
}));
|
||||
containers.push(Container::Block { content, node });
|
||||
Some((tail, node))
|
||||
}
|
||||
"QUOTE" => {
|
||||
let node = arena.new_node(Element::QuoteBlock(QuoteBlock {
|
||||
parameters: block.args,
|
||||
}));
|
||||
containers.push(Container::Block { content, node });
|
||||
Some((tail, node))
|
||||
}
|
||||
"COMMENT" => {
|
||||
let node = arena.new_node(Element::CommentBlock(CommentBlock {
|
||||
data: block.args,
|
||||
contents: content,
|
||||
}));
|
||||
Some((tail, node))
|
||||
}
|
||||
"EXAMPLE" => {
|
||||
let node = arena.new_node(Element::ExampleBlock(ExampleBlock {
|
||||
data: block.args,
|
||||
contents: content,
|
||||
}));
|
||||
Some((tail, node))
|
||||
}
|
||||
"EXPORT" => {
|
||||
let node = arena.new_node(Element::ExportBlock(ExportBlock {
|
||||
data: block.args.unwrap_or(""),
|
||||
contents: content,
|
||||
}));
|
||||
Some((tail, node))
|
||||
}
|
||||
"SRC" => {
|
||||
let (language, arguments) = block
|
||||
.args
|
||||
.map(|args| args.split_at(args.find(' ').unwrap_or_else(|| args.len())))
|
||||
.unwrap_or(("", ""));
|
||||
let node = arena.new_node(Element::SourceBlock(SourceBlock {
|
||||
arguments,
|
||||
language,
|
||||
contents: content,
|
||||
}));
|
||||
Some((tail, node))
|
||||
}
|
||||
"VERSE" => {
|
||||
let node = arena.new_node(Element::VerseBlock(VerseBlock {
|
||||
parameters: block.args,
|
||||
}));
|
||||
containers.push(Container::Block { content, node });
|
||||
Some((tail, node))
|
||||
}
|
||||
_ => {
|
||||
let node = arena.new_node(Element::SpecialBlock(SpecialBlock {
|
||||
parameters: block.args,
|
||||
name: block.name,
|
||||
}));
|
||||
containers.push(Container::Block { content, node });
|
||||
Some((tail, node))
|
||||
}
|
||||
}
|
||||
} else if let Some((tail, dyn_block, content)) = DynBlock::parse(tail) {
|
||||
let node = arena.new_node(dyn_block);
|
||||
containers.push(Container::Block { content, node });
|
||||
|
|
Loading…
Reference in a new issue