#![cfg(feature = "pulldown-cmark")]
#[cfg(all(feature = "syn", feature = "thiserror"))]
use std::path::Path;
use std::sync::Arc;
#[cfg(feature = "thiserror")]
use thiserror::Error;
#[cfg(feature = "thiserror")]
use crate::DisallowUrlsWithPrefixError;
#[cfg(all(feature = "syn", feature = "thiserror"))]
use crate::FileDocsFromFileError;
use crate::{CMarkData, CMarkDataIter, FileDocs, Manifest, Package};
#[cfg(all(feature = "syn", feature = "thiserror"))]
use crate::{Config, File, FileFromPathError};
#[derive(Clone, Debug, Default, PartialEq)]
pub struct CMarkDocs<P, M> {
data: CMarkData,
package_path: P,
manifest: M,
}
#[cfg(all(feature = "syn", feature = "thiserror"))]
impl<'a> CMarkDocs<&'a Path, &'a Manifest> {
pub fn from_package_with_default_config(
package: &'a Package,
) -> Result<Self, CMarkDocsFromPackageError> {
Self::from_package_and_config(package, &Config::default())
}
pub fn from_package_and_config(
package: &'a Package,
config: &Config<'_>,
) -> Result<Self, CMarkDocsFromPackageError> {
let path = package.manifest().default_relative_target_path();
let file = Arc::new(File::from_path(path.to_path_buf(), Some(package.path()))?);
let package_path = package.path();
let manifest = package.manifest();
Ok(Self::from_file_and_config_and_package_path_and_manifest(
file,
config,
package_path,
manifest,
)?)
}
}
#[cfg(all(feature = "syn", feature = "thiserror"))]
impl<'a> CMarkDocs<(), ()> {
pub fn from_file_and_config(
file: Arc<File>,
config: &Config<'_>,
) -> Result<Self, FileDocsFromFileError> {
Self::from_file_and_config_and_package_path_and_manifest(file, config, (), ())
}
}
impl<'a, P, M> CMarkDocs<P, M> {
pub fn with_package_path(self, package_path: &'a Package) -> CMarkDocs<&'a Package, M> {
CMarkDocs {
data: self.data,
package_path,
manifest: self.manifest,
}
}
pub fn with_manifest(self, manifest: &'a Manifest) -> CMarkDocs<P, &'a Manifest> {
CMarkDocs {
data: self.data,
package_path: self.package_path,
manifest,
}
}
#[cfg(all(feature = "syn", feature = "thiserror"))]
pub fn from_file_and_config_and_package_path_and_manifest(
file: Arc<File>,
config: &Config<'_>,
package_path: P,
manifest: M,
) -> Result<Self, FileDocsFromFileError> {
let file_docs = Arc::new(FileDocs::from_file(file, config)?);
Ok(Self::from_file_docs_and_package_path_and_manifest(
file_docs,
package_path,
manifest,
))
}
pub fn from_file_docs_and_package_path_and_manifest(
file_docs: Arc<FileDocs>,
package_path: P,
manifest: M,
) -> Self {
let data = CMarkData::from_file_docs(file_docs);
Self::from_data_chunks_package_pach_and_manifest(data, package_path, manifest)
}
pub fn from_data_chunks_package_pach_and_manifest(
data: CMarkData,
package_path: P,
manifest: M,
) -> Self {
Self {
data,
package_path,
manifest,
}
}
pub fn data(&self) -> &CMarkData {
&self.data
}
pub fn package_path(&self) -> &P {
&self.package_path
}
pub fn manifest(&self) -> &M {
&self.manifest
}
pub fn iter(&self) -> CMarkDataIter<'_> {
self.data.iter()
}
fn map<F>(mut self, func: F) -> CMarkDocs<P, M>
where
F: FnOnce(CMarkData) -> CMarkData,
{
self.data = func(self.data);
self
}
#[cfg(feature = "thiserror")]
fn map_result<F, E>(mut self, func: F) -> Result<CMarkDocs<P, M>, E>
where
F: FnOnce(CMarkData) -> Result<CMarkData, E>,
{
self.data = func(self.data)?;
Ok(self)
}
pub fn concat_texts(self) -> CMarkDocs<P, M> {
self.map(|data| data.concat_texts())
}
pub fn increment_heading_levels(self) -> CMarkDocs<P, M> {
self.map(|data| data.increment_heading_levels())
}
pub fn add_title(self, text: &str) -> CMarkDocs<P, M> {
self.map(|data| data.add_title(text))
}
pub fn remove_codeblock_tag(self, tag: &str) -> CMarkDocs<P, M> {
self.map(|data| data.remove_codeblock_tag(tag))
}
pub fn remove_codeblock_tags(self, tags: &[&str]) -> CMarkDocs<P, M> {
self.map(|data| data.remove_codeblock_tags(tags))
}
pub fn remove_codeblock_rust_test_tags(self) -> CMarkDocs<P, M> {
self.map(|data| data.remove_codeblock_rust_test_tags())
}
pub fn use_default_codeblock_tag(self, tag: &str) -> CMarkDocs<P, M> {
self.map(|data| data.use_default_codeblock_tag(tag))
}
pub fn use_default_codeblock_rust_tag(self) -> CMarkDocs<P, M> {
self.map(|data| data.use_default_codeblock_rust_tag())
}
pub fn remove_hidden_rust_code(self) -> CMarkDocs<P, M> {
self.map(|data| data.remove_hidden_rust_code())
}
#[cfg(feature = "thiserror")]
pub fn disallow_absolute_docs_links(
self,
package_name: &str,
documentation_url: &str,
) -> Result<CMarkDocs<P, M>, DisallowUrlsWithPrefixError> {
self.map_result(|data| data.disallow_absolute_docs_links(package_name, documentation_url))
}
pub fn use_absolute_docs_urls(
self,
package_name: &str,
documentation_url: &str,
) -> CMarkDocs<P, M> {
self.map(|data| data.use_absolute_docs_urls(package_name, documentation_url))
}
}
impl<'a, P> CMarkDocs<P, &'a Manifest> {
pub fn add_package_title(self) -> CMarkDocs<P, &'a Manifest> {
let name = self.manifest.package.name.clone();
self.add_title(&name)
}
#[cfg(feature = "thiserror")]
pub fn disallow_absolute_package_docs_links(
self,
) -> Result<CMarkDocs<P, &'a Manifest>, DisallowAbsolutePackageDocsLinksError> {
let name = self.manifest.package.name.clone();
let documentation = self
.manifest
.package
.documentation
.clone()
.ok_or(DisallowAbsolutePackageDocsLinksError::DocsUrlNotFound)?;
Ok(self.disallow_absolute_docs_links(&name, &documentation)?)
}
#[cfg(feature = "thiserror")]
pub fn use_absolute_package_docs_urls(
self,
) -> Result<CMarkDocs<P, &'a Manifest>, UseAbsolutePackageDocsUrlsError> {
let name = self.manifest.package.name.clone();
let documentation = self
.manifest
.package
.documentation
.clone()
.ok_or(UseAbsolutePackageDocsUrlsError::DocsUrlNotFound)?;
Ok(self.use_absolute_docs_urls(&name, &documentation))
}
}
#[cfg(all(feature = "syn", feature = "thiserror"))]
#[derive(Debug, Error)]
pub enum CMarkDocsFromPackageError {
#[error(transparent)]
FileError(#[from] FileFromPathError),
#[error("Documentation parsing failed: {0}")]
ParseError(#[from] FileDocsFromFileError),
}
#[cfg(feature = "thiserror")]
#[derive(Clone, Debug, Error)]
pub enum DisallowAbsolutePackageDocsLinksError {
#[error(transparent)]
DisallowUrlsWithPrefixError(#[from] DisallowUrlsWithPrefixError),
#[error("Manifest does not contain package.documentation field")]
DocsUrlNotFound,
}
#[cfg(feature = "thiserror")]
#[derive(Clone, Copy, Debug, Error)]
pub enum UseAbsolutePackageDocsUrlsError {
#[error("Manifest does not contain package.documentation field")]
DocsUrlNotFound,
}