render_readme 0.11.0

Render Markdown or reStructuredText with syntax highlighting and image filtering similar to GitHub's
Documentation
//! Render Markdown or reStructuredText with syntax highlighting and image filtering similar to GitHub's
//!
//! ```rust
//! use render_readme::*;
//! let deadline = std::time::Instant::now() + std::time::Duration::from_secs(3);
//! let r = Renderer::new(Some(Highlighter::new()));
//! let _ = r.markdown_str("# Hello", false, None, deadline);
//! let _ = r.page(&Markup::Markdown("# Hello".to_string()), &LinksContext {
//!     base_url: None,
//!     nofollow: None,
//!     own_crate_name: None,
//!     link_own_crate_to_crates_io: true,
//!     link_fixer: None,
//! }, deadline);
//! ```
//!
//! Markdown is implemented natively in Rust. RST rendering requires `rst2html` installed.
//!
#![allow(clippy::needless_raw_string_hashes)]

#[macro_use] extern crate html5ever;

mod filter;
mod highlight;
mod markup;
mod parser;

pub use crate::filter::*;
pub use crate::markup::*;
use std::path::Path;

pub use crate::highlight::Highlighter;
use serde::{Deserialize, Serialize};

/// Describe format/syntax used in the string
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum Markup {
    Markdown(String),
    Rst(String),
    AsciiDoc(String),
    Html(String),
}

/// Readme page from a repository
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Readme {
    pub markup: Markup,
    pub base_url: Option<String>,
    pub base_image_url: Option<String>,
}

impl Readme {
    #[must_use] pub fn new(markup: Markup, base_url: Option<String>, base_image_url: Option<String>) -> Self {
        Self { markup, base_url, base_image_url }
    }

    #[must_use]
    pub fn base_urls(&self) -> Option<(&str, &str)> {
        match (self.base_url.as_deref(), self.base_image_url.as_deref()) {
            (Some(l), Some(i)) => Some((l, i)),
            (Some(l), None) | (None, Some(l)) => Some((l, l)),
            _ => None,
        }
    }

    #[must_use]
    pub fn raw_text(&self) -> &str {
        match &self.markup {
            Markup::Markdown(t) | Markup::Rst(t) | Markup::AsciiDoc(t) | Markup::Html(t) => t,
        }
    }
}

#[must_use]
pub fn is_readme_filename(path: &Path) -> bool {
    path.to_str().is_some_and(|s| {
        // that's not great; there are readme-windows, readme.ja.md and more
        let readme_filenames = &[
            "readme_en.md", "readme.en.md", // i18n attempt
            "readme.md", "readme.markdown", "readme.mdown", "readme", "readme.rst", "readme.adoc", "readme.asciidoc", "readme.txt", "readme.rest"];
        readme_filenames.iter().any(|f| f.eq_ignore_ascii_case(s.as_ref()))
    })
}