Add support for target links.
This commit is contained in:
		
							parent
							
								
									d2ea6b6a0f
								
							
						
					
					
						commit
						59a91331cc
					
				| @ -14,9 +14,17 @@ pub(crate) struct RenderTarget { | ||||
|     post_blank: organic::types::PostBlank, | ||||
| } | ||||
| 
 | ||||
| render!(RenderTarget, ITarget, original, _render_context, { | ||||
| render!(RenderTarget, ITarget, original, render_context, { | ||||
|     let id = format!( | ||||
|         "{}{}", | ||||
|         render_context | ||||
|             .id_addition | ||||
|             .map(|id_addition| format!("sec{}.", id_addition)) | ||||
|             .unwrap_or_default(), | ||||
|         original.id | ||||
|     ); | ||||
|     Ok(RenderTarget { | ||||
|         id: original.id.clone(), | ||||
|         id, | ||||
|         post_blank: original.post_blank, | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -14,7 +14,7 @@ type IdCounter = u16; | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct Registry<'orig, 'parse> { | ||||
|     id_counter: IdCounter, | ||||
|     targets: HashMap<&'parse str, String>, | ||||
|     targets: HashMap<String, String>, | ||||
|     footnote_ids: Vec<(Option<&'parse str>, Vec<IAstNode>)>, | ||||
|     footnote_reference_counts: HashMap<&'parse str, usize>, | ||||
|     on_deck_footnote_ids: HashMap<&'parse str, &'orig Vec<Element<'parse>>>, | ||||
| @ -31,8 +31,8 @@ impl<'orig, 'parse> Registry<'orig, 'parse> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) fn get_target<'reg>(&'reg mut self, body: &'parse str) -> &'reg String { | ||||
|         self.targets.entry(body).or_insert_with(|| { | ||||
|     pub(crate) fn get_target<S: Into<String>>(&mut self, body: S) -> &String { | ||||
|         self.targets.entry(body.into()).or_insert_with(|| { | ||||
|             self.id_counter += 1; | ||||
|             format!("target_{}", self.id_counter) | ||||
|         }) | ||||
|  | ||||
| @ -3,6 +3,7 @@ use url::Url; | ||||
| 
 | ||||
| use super::get_web_path; | ||||
| use super::macros::intermediate; | ||||
| use super::IntermediateContext; | ||||
| 
 | ||||
| use super::IObject; | ||||
| use crate::context::RenderContext; | ||||
| @ -30,7 +31,8 @@ intermediate!( | ||||
|             ret | ||||
|         }; | ||||
|         let raw_link = original.get_raw_link(); | ||||
|         let target = LinkTarget::from_string(&raw_link)?; | ||||
|         let target = | ||||
|             LinkTarget::from_string(intermediate_context.clone(), raw_link.clone().into_owned())?; | ||||
|         Ok(IRegularLink { | ||||
|             raw_link: raw_link.into_owned(), | ||||
|             children, | ||||
| @ -47,38 +49,44 @@ pub(crate) enum LinkTarget { | ||||
|         post_id: Option<String>, | ||||
|         subpath: String, | ||||
|     }, | ||||
|     Target { | ||||
|         target_id: String, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| impl LinkTarget { | ||||
|     pub(crate) fn from_string<S: AsRef<str>>(input: S) -> Result<LinkTarget, CustomError> { | ||||
|         fn impl_from_string(input: &str) -> Result<LinkTarget, CustomError> { | ||||
|             let parsed = Url::parse(input); | ||||
|             if let Err(url::ParseError::RelativeUrlWithoutBase) = parsed { | ||||
|                 // For URLs to targets.
 | ||||
|                 // TODO: This shouldn't be raw but instead a variant for targets.
 | ||||
|                 return Ok(LinkTarget::Raw(input.to_owned())); | ||||
|             } | ||||
|             let parsed = parsed?; | ||||
|             match parsed.scheme() { | ||||
|                 "post" => { | ||||
|                     let post_id = parsed.host_str().map(str::to_owned); | ||||
|                     let subpath = { | ||||
|                         let subpath = parsed.path(); | ||||
|                         if let Some(subpath) = subpath.strip_prefix('/') { | ||||
|                             subpath | ||||
|                         } else { | ||||
|                             subpath | ||||
|                         } | ||||
|                     }; | ||||
|                     Ok(LinkTarget::Post { | ||||
|                         post_id, | ||||
|                         subpath: subpath.to_owned(), | ||||
|                     }) | ||||
|                 } | ||||
|                 _ => Ok(LinkTarget::Raw(input.to_owned())), | ||||
|             } | ||||
|     pub(crate) fn from_string( | ||||
|         intermediate_context: IntermediateContext<'_, '_>, | ||||
|         input: String, | ||||
|     ) -> Result<LinkTarget, CustomError> { | ||||
|         let parsed = Url::parse(&input); | ||||
|         if let Err(url::ParseError::RelativeUrlWithoutBase) = parsed { | ||||
|             let target_id = { | ||||
|                 let mut registry = intermediate_context.registry.lock().unwrap(); | ||||
|                 let target_id = registry.get_target(input).to_owned(); | ||||
|                 target_id | ||||
|             }; | ||||
|             return Ok(LinkTarget::Target { target_id }); | ||||
|         } | ||||
|         let parsed = parsed?; | ||||
|         match parsed.scheme() { | ||||
|             "post" => { | ||||
|                 let post_id = parsed.host_str().map(str::to_owned); | ||||
|                 let subpath = { | ||||
|                     let subpath = parsed.path(); | ||||
|                     if let Some(subpath) = subpath.strip_prefix('/') { | ||||
|                         subpath | ||||
|                     } else { | ||||
|                         subpath | ||||
|                     } | ||||
|                 }; | ||||
|                 Ok(LinkTarget::Post { | ||||
|                     post_id, | ||||
|                     subpath: subpath.to_owned(), | ||||
|                 }) | ||||
|             } | ||||
|             _ => Ok(LinkTarget::Raw(input.to_owned())), | ||||
|         } | ||||
|         impl_from_string(input.as_ref()) | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) fn generate_final_target( | ||||
| @ -105,6 +113,14 @@ impl LinkTarget { | ||||
|                     .map_or(Ok(None), |r| r.map(Some))?; | ||||
|                 Ok(path) | ||||
|             } | ||||
|             LinkTarget::Target { target_id } => Ok(Some(format!( | ||||
|                 "#{}{}", | ||||
|                 render_context | ||||
|                     .id_addition | ||||
|                     .map(|id_addition| format!("sec{}.", id_addition)) | ||||
|                     .unwrap_or_default(), | ||||
|                 target_id | ||||
|             ))), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander