aboutsummaryrefslogtreecommitdiffstats
path: root/parser/src/conversion/inline.rs
diff options
context:
space:
mode:
Diffstat (limited to 'parser/src/conversion/inline.rs')
-rw-r--r--parser/src/conversion/inline.rs278
1 files changed, 137 insertions, 141 deletions
diff --git a/parser/src/conversion/inline.rs b/parser/src/conversion/inline.rs
index 82a74e7..a0dcb88 100644
--- a/parser/src/conversion/inline.rs
+++ b/parser/src/conversion/inline.rs
@@ -2,159 +2,155 @@ use failure::Error;
use pest::iterators::Pair;
use document_tree::{
- HasChildren,
- elements as e,
- url::Url,
- element_categories as c,
- extra_attributes as a,
- attribute_types as at,
+ attribute_types as at, element_categories as c, elements as e, extra_attributes as a, url::Url,
+ HasChildren,
};
-use crate::{
- pest_rst::Rule,
-// pair_ext_parse::PairExt,
-};
use super::whitespace_normalize_name;
-
+use crate::pest_rst::Rule;
pub fn convert_inline(pair: Pair<Rule>) -> Result<c::TextOrInlineElement, Error> {
- Ok(match pair.as_rule() {
- Rule::str | Rule::str_nested => pair.as_str().into(),
- Rule::ws_newline => " ".to_owned().into(),
- Rule::reference => convert_reference(pair)?,
- Rule::substitution_name => convert_substitution_ref(pair)?.into(),
- Rule::emph => e::Emphasis::with_children(convert_inlines(pair)?).into(),
- Rule::strong => e::Strong::with_children(convert_inlines(pair)?).into(),
- Rule::literal => e::Literal::with_children(vec![pair.as_str().to_owned()]).into(),
- rule => unimplemented!("unknown rule {:?}", rule),
- })
+ Ok(match pair.as_rule() {
+ Rule::str | Rule::str_nested => pair.as_str().into(),
+ Rule::ws_newline => " ".to_owned().into(),
+ Rule::reference => convert_reference(pair)?,
+ Rule::substitution_name => convert_substitution_ref(pair)?.into(),
+ Rule::emph => e::Emphasis::with_children(convert_inlines(pair)?).into(),
+ Rule::strong => e::Strong::with_children(convert_inlines(pair)?).into(),
+ Rule::literal => e::Literal::with_children(vec![pair.as_str().to_owned()]).into(),
+ rule => unimplemented!("unknown rule {:?}", rule),
+ })
}
pub fn convert_inlines(pair: Pair<Rule>) -> Result<Vec<c::TextOrInlineElement>, Error> {
- pair.into_inner().map(convert_inline).collect()
+ pair.into_inner().map(convert_inline).collect()
}
fn convert_reference(pair: Pair<Rule>) -> Result<c::TextOrInlineElement, Error> {
- let name;
- let refuri;
- let refid;
- let mut refname = vec![];
- let mut children: Vec<c::TextOrInlineElement> = vec![];
- let concrete = pair.into_inner().next().unwrap();
- match concrete.as_rule() {
- Rule::reference_target => {
- let rt_inner = concrete.into_inner().next().unwrap(); // reference_target_uq or target_name_qu
- match rt_inner.as_rule() {
- Rule::reference_target_uq => {
- refid = None;
- name = Some(rt_inner.as_str().into());
- refuri = None;
- refname.push(rt_inner.as_str().into());
- children.push(rt_inner.as_str().into());
- },
- Rule::reference_target_qu => {
- let (text, reference) = {
- let mut text = None;
- let mut reference = None;
- for inner in rt_inner.clone().into_inner() {
- match inner.as_rule() {
- Rule::reference_text => text = Some(inner),
- Rule::reference_bracketed => reference = Some(inner),
- _ => unreachable!()
- }
- }
- (text, reference)
- };
- let trimmed_text = match (&text, &reference) {
- (Some(text), None) => text.as_str(),
- (_, Some(reference)) => {
- text
- .map(|text| text.as_str().trim_end_matches(|ch| " \n\r".contains(ch)))
- .filter(|text| !text.is_empty())
- .unwrap_or_else(|| reference.clone().into_inner().next().unwrap().as_str())
- }
- (None, None) => unreachable!()
- };
- refid = None;
- name = Some(trimmed_text.into());
- refuri = if let Some(reference) = reference {
- let inner = reference.into_inner().next().unwrap();
- match inner.as_rule() {
- // The URL rules in our parser accept a narrow superset of
- // valid URLs, so we need to handle false positives.
- Rule::url => if let Ok(target) = Url::parse_absolute(inner.as_str()) {
- Some(target)
- } else if inner.as_str().ends_with('_') {
- // like target_name_qu (minus the final underscore)
- let full_str = inner.as_str();
- refname.push(full_str[0..full_str.len() - 1].into());
- None
- } else {
- // like relative_reference
- Some(Url::parse_relative(inner.as_str())?)
- },
- Rule::target_name_qu => {
- refname.push(inner.as_str().into());
- None
- },
- Rule::relative_reference => {
- Some(Url::parse_relative(inner.as_str())?)
- },
- _ => unreachable!()
- }
- } else {
- refname.push(trimmed_text.into());
- None
- };
- children.push(trimmed_text.into());
- },
- _ => unreachable!()
- }
- },
- Rule::reference_explicit => unimplemented!("explicit reference"),
- Rule::reference_auto => {
- let rt_inner = concrete.into_inner().next().unwrap();
- match rt_inner.as_rule() {
- Rule::url_auto => match Url::parse_absolute(rt_inner.as_str()) {
- Ok(target) => {
- refuri = Some(target);
- name = None;
- refid = None;
- children.push(rt_inner.as_str().into());
- },
- // if our parser got a URL wrong, return it as a string
- Err(_) => return Ok(rt_inner.as_str().into())
- },
- Rule::email => {
- let mailto_url = String::from("mailto:") + rt_inner.as_str();
- match Url::parse_absolute(&mailto_url) {
- Ok(target) => {
- refuri = Some(target);
- name = None;
- refid = None;
- children.push(rt_inner.as_str().into());
- },
- // if our parser got a URL wrong, return it as a string
- Err(_) => return Ok(rt_inner.as_str().into())
- }
- },
- _ => unreachable!()
- }
- },
- _ => unreachable!(),
- };
- Ok(e::Reference::new(
- Default::default(),
- a::Reference { name, refuri, refid, refname },
- children
- ).into())
+ let name;
+ let refuri;
+ let refid;
+ let mut refname = vec![];
+ let mut children: Vec<c::TextOrInlineElement> = vec![];
+ let concrete = pair.into_inner().next().unwrap();
+ match concrete.as_rule() {
+ Rule::reference_target => {
+ let rt_inner = concrete.into_inner().next().unwrap(); // reference_target_uq or target_name_qu
+ match rt_inner.as_rule() {
+ Rule::reference_target_uq => {
+ refid = None;
+ name = Some(rt_inner.as_str().into());
+ refuri = None;
+ refname.push(rt_inner.as_str().into());
+ children.push(rt_inner.as_str().into());
+ }
+ Rule::reference_target_qu => {
+ let (text, reference) = {
+ let mut text = None;
+ let mut reference = None;
+ for inner in rt_inner.clone().into_inner() {
+ match inner.as_rule() {
+ Rule::reference_text => text = Some(inner),
+ Rule::reference_bracketed => reference = Some(inner),
+ _ => unreachable!(),
+ }
+ }
+ (text, reference)
+ };
+ let trimmed_text = match (&text, &reference) {
+ (Some(text), None) => text.as_str(),
+ (_, Some(reference)) => text
+ .map(|text| text.as_str().trim_end_matches(|ch| " \n\r".contains(ch)))
+ .filter(|text| !text.is_empty())
+ .unwrap_or_else(|| {
+ reference.clone().into_inner().next().unwrap().as_str()
+ }),
+ (None, None) => unreachable!(),
+ };
+ refid = None;
+ name = Some(trimmed_text.into());
+ refuri = if let Some(reference) = reference {
+ let inner = reference.into_inner().next().unwrap();
+ match inner.as_rule() {
+ // The URL rules in our parser accept a narrow superset of
+ // valid URLs, so we need to handle false positives.
+ Rule::url => {
+ if let Ok(target) = Url::parse_absolute(inner.as_str()) {
+ Some(target)
+ } else if inner.as_str().ends_with('_') {
+ // like target_name_qu (minus the final underscore)
+ let full_str = inner.as_str();
+ refname.push(full_str[0..full_str.len() - 1].into());
+ None
+ } else {
+ // like relative_reference
+ Some(Url::parse_relative(inner.as_str())?)
+ }
+ }
+ Rule::target_name_qu => {
+ refname.push(inner.as_str().into());
+ None
+ }
+ Rule::relative_reference => Some(Url::parse_relative(inner.as_str())?),
+ _ => unreachable!(),
+ }
+ } else {
+ refname.push(trimmed_text.into());
+ None
+ };
+ children.push(trimmed_text.into());
+ }
+ _ => unreachable!(),
+ }
+ }
+ Rule::reference_explicit => unimplemented!("explicit reference"),
+ Rule::reference_auto => {
+ let rt_inner = concrete.into_inner().next().unwrap();
+ match rt_inner.as_rule() {
+ Rule::url_auto => match Url::parse_absolute(rt_inner.as_str()) {
+ Ok(target) => {
+ refuri = Some(target);
+ name = None;
+ refid = None;
+ children.push(rt_inner.as_str().into());
+ }
+ // if our parser got a URL wrong, return it as a string
+ Err(_) => return Ok(rt_inner.as_str().into()),
+ },
+ Rule::email => {
+ let mailto_url = String::from("mailto:") + rt_inner.as_str();
+ match Url::parse_absolute(&mailto_url) {
+ Ok(target) => {
+ refuri = Some(target);
+ name = None;
+ refid = None;
+ children.push(rt_inner.as_str().into());
+ }
+ // if our parser got a URL wrong, return it as a string
+ Err(_) => return Ok(rt_inner.as_str().into()),
+ }
+ }
+ _ => unreachable!(),
+ }
+ }
+ _ => unreachable!(),
+ };
+ Ok(e::Reference::new(
+ Default::default(),
+ a::Reference {
+ name,
+ refuri,
+ refid,
+ refname,
+ },
+ children,
+ )
+ .into())
}
fn convert_substitution_ref(pair: Pair<Rule>) -> Result<e::SubstitutionReference, Error> {
- let name = whitespace_normalize_name(pair.as_str());
- Ok(a::ExtraAttributes::with_extra(
- a::SubstitutionReference {
- refname: vec![at::NameToken(name)]
- }
- ))
+ let name = whitespace_normalize_name(pair.as_str());
+ Ok(a::ExtraAttributes::with_extra(a::SubstitutionReference {
+ refname: vec![at::NameToken(name)],
+ }))
}