Add support for Image targets in the intermediate step.
This commit is contained in:
parent
7c92b602bc
commit
eb18185131
22
org_test_documents/regular_link/image_links.org
Normal file
22
org_test_documents/regular_link/image_links.org
Normal file
@ -0,0 +1,22 @@
|
||||
[[file:image.svg]]
|
||||
|
||||
[[file:/image.svg]]
|
||||
|
||||
[[file:./image.svg]]
|
||||
|
||||
[[/image.svg]]
|
||||
|
||||
[[./image.svg]]
|
||||
|
||||
# Check capitalization of extension
|
||||
[[./image.SVG]]
|
||||
|
||||
# Check spaces in path
|
||||
[[./image and stuff.SVG]]
|
||||
|
||||
[[/ssh:admin@test.example:important/file.svg]]
|
||||
|
||||
[[file:/ssh:admin@test.example:important/file.svg]]
|
||||
|
||||
# Check multiple parts in the path
|
||||
[[file:/foo/bar/baz/image.svg]]
|
@ -1,3 +1,7 @@
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
|
||||
use organic::types::LinkType;
|
||||
use organic::types::StandardProperties;
|
||||
use url::Url;
|
||||
|
||||
@ -31,8 +35,11 @@ intermediate!(
|
||||
ret
|
||||
};
|
||||
let raw_link = original.get_raw_link();
|
||||
let target =
|
||||
LinkTarget::from_string(intermediate_context.clone(), raw_link.clone().into_owned())?;
|
||||
let target = LinkTarget::from_string(
|
||||
intermediate_context.clone(),
|
||||
raw_link.clone().into_owned(),
|
||||
&original.link_type,
|
||||
)?;
|
||||
Ok(IRegularLink {
|
||||
raw_link: raw_link.into_owned(),
|
||||
children,
|
||||
@ -52,13 +59,28 @@ pub(crate) enum LinkTarget {
|
||||
Target {
|
||||
target_id: String,
|
||||
},
|
||||
Image {
|
||||
src: String,
|
||||
alt: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl LinkTarget {
|
||||
pub(crate) fn from_string(
|
||||
intermediate_context: IntermediateContext<'_, '_>,
|
||||
input: String,
|
||||
link_type: &LinkType<'_>,
|
||||
) -> Result<LinkTarget, CustomError> {
|
||||
// If link type is file and the path ends in .svg then make it an image target
|
||||
if let LinkType::File = link_type
|
||||
&& input.to_ascii_lowercase().ends_with(".svg")
|
||||
{
|
||||
let src = Self::get_image_src(&input)?;
|
||||
let alt = Self::get_image_alt(&input)?;
|
||||
|
||||
return Ok(LinkTarget::Image { src, alt });
|
||||
};
|
||||
|
||||
let parsed = Url::parse(&input);
|
||||
if let Err(url::ParseError::RelativeUrlWithoutBase) = parsed {
|
||||
let target_id = {
|
||||
@ -121,12 +143,64 @@ impl LinkTarget {
|
||||
.unwrap_or_default(),
|
||||
target_id
|
||||
))),
|
||||
LinkTarget::Image { src, .. } => Ok(Some(src.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the value for the src attribute of the image.
|
||||
fn get_image_src(input: &str) -> Result<String, CustomError> {
|
||||
let input = if input.to_ascii_lowercase().starts_with("file:") {
|
||||
Cow::Borrowed(&input[5..])
|
||||
} else {
|
||||
Cow::Borrowed(input)
|
||||
};
|
||||
let path = Path::new(input.as_ref());
|
||||
|
||||
if input.to_ascii_lowercase().starts_with("/ssh:") {
|
||||
return Ok(format!("file:/{}", input));
|
||||
}
|
||||
|
||||
if path.is_absolute() {
|
||||
return Ok(format!("file://{}", input));
|
||||
}
|
||||
return Ok(input.into_owned());
|
||||
}
|
||||
|
||||
/// Get file name from the last segment of an image path.
|
||||
fn get_image_alt(input: &str) -> Result<String, CustomError> {
|
||||
let input = if input.to_ascii_lowercase().starts_with("file:") {
|
||||
Cow::Borrowed(&input[5..])
|
||||
} else {
|
||||
Cow::Borrowed(input)
|
||||
};
|
||||
let path = Path::new(input.as_ref());
|
||||
match path
|
||||
.components()
|
||||
.last()
|
||||
.ok_or("Images should have at least one component in their path.")?
|
||||
{
|
||||
std::path::Component::Prefix(_) => {
|
||||
// Prefix components only occur on windows
|
||||
panic!("Prefix components are not supporterd.")
|
||||
}
|
||||
std::path::Component::RootDir
|
||||
| std::path::Component::CurDir
|
||||
| std::path::Component::ParentDir => {
|
||||
return Err(
|
||||
"Final component of an image path should be a normal component.".into(),
|
||||
);
|
||||
}
|
||||
std::path::Component::Normal(file_name) => Ok(file_name
|
||||
.to_str()
|
||||
.ok_or("Image link was not valid utf-8.")?
|
||||
.to_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
@ -139,12 +213,78 @@ mod tests {
|
||||
let registry = Registry::new();
|
||||
let registry = Arc::new(Mutex::new(registry));
|
||||
let intermediate_context = IntermediateContext::new(registry)?;
|
||||
for inp in ["https://test.example/foo"] {
|
||||
for (inp, typ) in [(
|
||||
"https://test.example/foo",
|
||||
LinkType::Protocol(Cow::from("https")),
|
||||
)] {
|
||||
assert_eq!(
|
||||
LinkTarget::from_string(intermediate_context.clone(), inp.to_owned())?,
|
||||
LinkTarget::from_string(intermediate_context.clone(), inp.to_owned(), &typ)?,
|
||||
LinkTarget::Raw(inp.to_owned())
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn link_target_image() -> Result<(), CustomError> {
|
||||
let registry = Registry::new();
|
||||
let registry = Arc::new(Mutex::new(registry));
|
||||
let intermediate_context = IntermediateContext::new(registry)?;
|
||||
for (inp, typ, expected_src, expected_alt) in [
|
||||
("file:image.svg", LinkType::File, "image.svg", "image.svg"),
|
||||
(
|
||||
"file:/image.svg",
|
||||
LinkType::File,
|
||||
"file:///image.svg",
|
||||
"image.svg",
|
||||
),
|
||||
(
|
||||
"file:./image.svg",
|
||||
LinkType::File,
|
||||
"./image.svg",
|
||||
"image.svg",
|
||||
),
|
||||
(
|
||||
"/image.svg",
|
||||
LinkType::File,
|
||||
"file:///image.svg",
|
||||
"image.svg",
|
||||
),
|
||||
("./image.svg", LinkType::File, "./image.svg", "image.svg"),
|
||||
("./image.SVG", LinkType::File, "./image.SVG", "image.SVG"),
|
||||
(
|
||||
"./image and stuff.SVG",
|
||||
LinkType::File,
|
||||
"./image and stuff.SVG",
|
||||
"image and stuff.SVG",
|
||||
),
|
||||
(
|
||||
"/ssh:admin@test.example:important/file.svg",
|
||||
LinkType::File,
|
||||
"file://ssh:admin@test.example:important/file.svg",
|
||||
"file.svg",
|
||||
),
|
||||
(
|
||||
"file:/ssh:admin@test.example:important/file.svg",
|
||||
LinkType::File,
|
||||
"file://ssh:admin@test.example:important/file.svg",
|
||||
"file.svg",
|
||||
),
|
||||
(
|
||||
"file:/foo/bar/baz/image.svg",
|
||||
LinkType::File,
|
||||
"file:///foo/bar/baz/image.svg",
|
||||
"image.svg",
|
||||
),
|
||||
] {
|
||||
assert_eq!(
|
||||
LinkTarget::from_string(intermediate_context.clone(), inp.to_owned(), &typ)?,
|
||||
LinkTarget::Image {
|
||||
src: expected_src.to_owned(),
|
||||
alt: expected_alt.to_owned()
|
||||
}
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user