mirror of
https://github.com/Hopiu/lychee.git
synced 2026-03-16 20:50:25 +00:00
Unwrap option type
This commit is contained in:
parent
696a7cafc8
commit
1de218a78a
4 changed files with 59 additions and 78 deletions
|
|
@ -7,18 +7,10 @@ use tokio_stream::StreamExt;
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
// Collect all links from the following inputs
|
// Collect all links from the following inputs
|
||||||
let inputs = vec![
|
let inputs = vec![
|
||||||
Input {
|
Input::from_input_source(InputSource::RemoteUrl(Box::new(
|
||||||
source: InputSource::RemoteUrl(Box::new(
|
Url::parse("https://github.com/lycheeverse/lychee").unwrap(),
|
||||||
Url::parse("https://github.com/lycheeverse/lychee").unwrap(),
|
))),
|
||||||
)),
|
Input::from_input_source(InputSource::FsPath(PathBuf::from("fixtures/TEST.md"))),
|
||||||
file_type_hint: None,
|
|
||||||
excluded_paths: None,
|
|
||||||
},
|
|
||||||
Input {
|
|
||||||
source: InputSource::FsPath(PathBuf::from("fixtures/TEST.md")),
|
|
||||||
file_type_hint: None,
|
|
||||||
excluded_paths: None,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let links = Collector::default()
|
let links = Collector::default()
|
||||||
|
|
|
||||||
|
|
@ -331,15 +331,16 @@ impl LycheeOptions {
|
||||||
// accept a `Vec<Input>` in `LycheeOptions` and do the conversion there, but
|
// accept a `Vec<Input>` in `LycheeOptions` and do the conversion there, but
|
||||||
// we wouldn't get access to `glob_ignore_case`.
|
// we wouldn't get access to `glob_ignore_case`.
|
||||||
pub(crate) fn inputs(&self) -> Result<Vec<Input>> {
|
pub(crate) fn inputs(&self) -> Result<Vec<Input>> {
|
||||||
let excluded = if self.config.exclude_path.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.config.exclude_path.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
self.raw_inputs
|
self.raw_inputs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| Input::new(s, None, self.config.glob_ignore_case, excluded.clone()))
|
.map(|s| {
|
||||||
|
Input::new(
|
||||||
|
s,
|
||||||
|
None,
|
||||||
|
self.config.glob_ignore_case,
|
||||||
|
self.config.exclude_path.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<Result<_, _>>()
|
.collect::<Result<_, _>>()
|
||||||
.context("Cannot parse inputs from arguments")
|
.context("Cannot parse inputs from arguments")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,12 @@ mod tests {
|
||||||
// Treat as plaintext file (no extension)
|
// Treat as plaintext file (no extension)
|
||||||
let file_path = temp_dir.path().join("README");
|
let file_path = temp_dir.path().join("README");
|
||||||
let _file = File::create(&file_path).unwrap();
|
let _file = File::create(&file_path).unwrap();
|
||||||
let input = Input::new(&file_path.as_path().display().to_string(), None, true, None)?;
|
let input = Input::new(
|
||||||
|
&file_path.as_path().display().to_string(),
|
||||||
|
None,
|
||||||
|
true,
|
||||||
|
vec![],
|
||||||
|
)?;
|
||||||
let contents: Vec<_> = input
|
let contents: Vec<_> = input
|
||||||
.get_contents(
|
.get_contents(
|
||||||
true,
|
true,
|
||||||
|
|
@ -293,7 +298,7 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_url_without_extension_is_html() -> Result<()> {
|
async fn test_url_without_extension_is_html() -> Result<()> {
|
||||||
let input = Input::new("https://example.com/", None, true, None)?;
|
let input = Input::new("https://example.com/", None, true, vec![])?;
|
||||||
let contents: Vec<_> = input
|
let contents: Vec<_> = input
|
||||||
.get_contents(
|
.get_contents(
|
||||||
true,
|
true,
|
||||||
|
|
@ -330,33 +335,17 @@ mod tests {
|
||||||
let mock_server = mock_server!(StatusCode::OK, set_body_string(TEST_URL));
|
let mock_server = mock_server!(StatusCode::OK, set_body_string(TEST_URL));
|
||||||
|
|
||||||
let inputs = vec![
|
let inputs = vec![
|
||||||
Input {
|
Input::from_input_source(InputSource::String(TEST_STRING.to_owned())),
|
||||||
source: InputSource::String(TEST_STRING.to_owned()),
|
Input::from_input_source(InputSource::RemoteUrl(Box::new(
|
||||||
file_type_hint: None,
|
Url::parse(&mock_server.uri())
|
||||||
excluded_paths: None,
|
.map_err(|e| (mock_server.uri(), e))
|
||||||
},
|
.unwrap(),
|
||||||
Input {
|
))),
|
||||||
source: InputSource::RemoteUrl(Box::new(
|
Input::from_input_source(InputSource::FsPath(file_path)),
|
||||||
Url::parse(&mock_server.uri())
|
Input::from_input_source(InputSource::FsGlob {
|
||||||
.map_err(|e| (mock_server.uri(), e))
|
pattern: temp_dir_path.join("glob*").to_str().unwrap().to_owned(),
|
||||||
.unwrap(),
|
ignore_case: true,
|
||||||
)),
|
}),
|
||||||
file_type_hint: None,
|
|
||||||
excluded_paths: None,
|
|
||||||
},
|
|
||||||
Input {
|
|
||||||
source: InputSource::FsPath(file_path),
|
|
||||||
file_type_hint: None,
|
|
||||||
excluded_paths: None,
|
|
||||||
},
|
|
||||||
Input {
|
|
||||||
source: InputSource::FsGlob {
|
|
||||||
pattern: temp_dir_path.join("glob*").to_str().unwrap().to_owned(),
|
|
||||||
ignore_case: true,
|
|
||||||
},
|
|
||||||
file_type_hint: None,
|
|
||||||
excluded_paths: None,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let links = collect_verbatim(inputs, None, None, FileType::default_extensions())
|
let links = collect_verbatim(inputs, None, None, FileType::default_extensions())
|
||||||
|
|
@ -383,7 +372,7 @@ mod tests {
|
||||||
let input = Input {
|
let input = Input {
|
||||||
source: InputSource::String("This is [a test](https://endler.dev). This is a relative link test [Relative Link Test](relative_link)".to_string()),
|
source: InputSource::String("This is [a test](https://endler.dev). This is a relative link test [Relative Link Test](relative_link)".to_string()),
|
||||||
file_type_hint: Some(FileType::Markdown),
|
file_type_hint: Some(FileType::Markdown),
|
||||||
excluded_paths: None,
|
excluded_paths: vec![],
|
||||||
};
|
};
|
||||||
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
||||||
|
|
||||||
|
|
@ -409,7 +398,7 @@ mod tests {
|
||||||
.to_string(),
|
.to_string(),
|
||||||
),
|
),
|
||||||
file_type_hint: Some(FileType::Html),
|
file_type_hint: Some(FileType::Html),
|
||||||
excluded_paths: None,
|
excluded_paths: vec![],
|
||||||
};
|
};
|
||||||
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
||||||
|
|
||||||
|
|
@ -438,7 +427,7 @@ mod tests {
|
||||||
.to_string(),
|
.to_string(),
|
||||||
),
|
),
|
||||||
file_type_hint: Some(FileType::Html),
|
file_type_hint: Some(FileType::Html),
|
||||||
excluded_paths: None,
|
excluded_paths: vec![],
|
||||||
};
|
};
|
||||||
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
||||||
|
|
||||||
|
|
@ -464,7 +453,7 @@ mod tests {
|
||||||
.to_string(),
|
.to_string(),
|
||||||
),
|
),
|
||||||
file_type_hint: Some(FileType::Markdown),
|
file_type_hint: Some(FileType::Markdown),
|
||||||
excluded_paths: None,
|
excluded_paths: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
||||||
|
|
@ -487,7 +476,7 @@ mod tests {
|
||||||
let input = Input {
|
let input = Input {
|
||||||
source: InputSource::String(input),
|
source: InputSource::String(input),
|
||||||
file_type_hint: Some(FileType::Html),
|
file_type_hint: Some(FileType::Html),
|
||||||
excluded_paths: None,
|
excluded_paths: vec![],
|
||||||
};
|
};
|
||||||
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
||||||
|
|
||||||
|
|
@ -516,11 +505,7 @@ mod tests {
|
||||||
|
|
||||||
let server_uri = Url::parse(&mock_server.uri()).unwrap();
|
let server_uri = Url::parse(&mock_server.uri()).unwrap();
|
||||||
|
|
||||||
let input = Input {
|
let input = Input::from_input_source(InputSource::RemoteUrl(Box::new(server_uri.clone())));
|
||||||
source: InputSource::RemoteUrl(Box::new(server_uri.clone())),
|
|
||||||
file_type_hint: None,
|
|
||||||
excluded_paths: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let links = collect(vec![input], None, None).await.ok().unwrap();
|
let links = collect(vec![input], None, None).await.ok().unwrap();
|
||||||
|
|
||||||
|
|
@ -534,13 +519,10 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_email_with_query_params() {
|
async fn test_email_with_query_params() {
|
||||||
let input = Input {
|
let input = Input::from_input_source(InputSource::String(
|
||||||
source: InputSource::String(
|
"This is a mailto:user@example.com?subject=Hello link".to_string(),
|
||||||
"This is a mailto:user@example.com?subject=Hello link".to_string(),
|
));
|
||||||
),
|
|
||||||
file_type_hint: None,
|
|
||||||
excluded_paths: None,
|
|
||||||
};
|
|
||||||
let links = collect(vec![input], None, None).await.ok().unwrap();
|
let links = collect(vec![input], None, None).await.ok().unwrap();
|
||||||
|
|
||||||
let expected_links = HashSet::from_iter([mail("user@example.com")]);
|
let expected_links = HashSet::from_iter([mail("user@example.com")]);
|
||||||
|
|
@ -569,7 +551,7 @@ mod tests {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)),
|
)),
|
||||||
file_type_hint: Some(FileType::Html),
|
file_type_hint: Some(FileType::Html),
|
||||||
excluded_paths: None,
|
excluded_paths: vec![],
|
||||||
},
|
},
|
||||||
Input {
|
Input {
|
||||||
source: InputSource::RemoteUrl(Box::new(
|
source: InputSource::RemoteUrl(Box::new(
|
||||||
|
|
@ -580,7 +562,7 @@ mod tests {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)),
|
)),
|
||||||
file_type_hint: Some(FileType::Html),
|
file_type_hint: Some(FileType::Html),
|
||||||
excluded_paths: None,
|
excluded_paths: vec![],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -615,7 +597,7 @@ mod tests {
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
file_type_hint: Some(FileType::Html),
|
file_type_hint: Some(FileType::Html),
|
||||||
excluded_paths: None,
|
excluded_paths: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ pub struct Input {
|
||||||
/// Hint to indicate which extractor to use
|
/// Hint to indicate which extractor to use
|
||||||
pub file_type_hint: Option<FileType>,
|
pub file_type_hint: Option<FileType>,
|
||||||
/// Excluded paths that will be skipped when reading content
|
/// Excluded paths that will be skipped when reading content
|
||||||
pub excluded_paths: Option<Vec<PathBuf>>,
|
pub excluded_paths: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
|
|
@ -124,7 +124,7 @@ impl Input {
|
||||||
value: &str,
|
value: &str,
|
||||||
file_type_hint: Option<FileType>,
|
file_type_hint: Option<FileType>,
|
||||||
glob_ignore_case: bool,
|
glob_ignore_case: bool,
|
||||||
excluded_paths: Option<Vec<PathBuf>>,
|
excluded_paths: Vec<PathBuf>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let source = if value == STDIN {
|
let source = if value == STDIN {
|
||||||
InputSource::Stdin
|
InputSource::Stdin
|
||||||
|
|
@ -200,7 +200,16 @@ impl Input {
|
||||||
/// Returns an error if the input does not exist (i.e. invalid path)
|
/// Returns an error if the input does not exist (i.e. invalid path)
|
||||||
/// and the input cannot be parsed as a URL.
|
/// and the input cannot be parsed as a URL.
|
||||||
pub fn from_value(value: &str) -> Result<Self> {
|
pub fn from_value(value: &str) -> Result<Self> {
|
||||||
Self::new(value, None, false, None)
|
Self::new(value, None, false, vec![])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience constructor
|
||||||
|
pub fn from_input_source(source: InputSource) -> Self {
|
||||||
|
Self {
|
||||||
|
source,
|
||||||
|
file_type_hint: None,
|
||||||
|
excluded_paths: vec![],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the contents from the input
|
/// Retrieve the contents from the input
|
||||||
|
|
@ -360,10 +369,7 @@ impl Input {
|
||||||
|
|
||||||
/// Check if the given path was excluded from link checking
|
/// Check if the given path was excluded from link checking
|
||||||
fn is_excluded_path(&self, path: &PathBuf) -> bool {
|
fn is_excluded_path(&self, path: &PathBuf) -> bool {
|
||||||
let Some(excluded_paths) = &self.excluded_paths else {
|
is_excluded_path(&self.excluded_paths, path)
|
||||||
return false;
|
|
||||||
};
|
|
||||||
is_excluded_path(excluded_paths, path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the input content of a given path
|
/// Get the input content of a given path
|
||||||
|
|
@ -437,15 +443,15 @@ mod tests {
|
||||||
assert!(path.exists());
|
assert!(path.exists());
|
||||||
assert!(path.is_relative());
|
assert!(path.is_relative());
|
||||||
|
|
||||||
let input = Input::new(test_file, None, false, None);
|
let input = Input::new(test_file, None, false, vec![]);
|
||||||
assert!(input.is_ok());
|
assert!(input.is_ok());
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
input,
|
input,
|
||||||
Ok(Input {
|
Ok(Input {
|
||||||
source: InputSource::FsPath(PathBuf { .. }),
|
source: InputSource::FsPath(PathBuf { .. }),
|
||||||
file_type_hint: None,
|
file_type_hint: None,
|
||||||
excluded_paths: None,
|
excluded_paths
|
||||||
})
|
}) if excluded_paths.is_empty()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue