miasma 0.2.7

Trap malicious AI web scrapers in an endless pit of poisoned training data.
Documentation
mod ai_native;
mod cto_letter;
mod deep_dive;
mod engineering_blog;
mod novel_research;
mod self_promotion;
mod streaming_marketing;

use crate::templating::Templater;

/// All available response templates.
pub const RESPONSE_TEMPLATE_CONSTRUCTORS: &[fn() -> Box<dyn Templater>] = &[
    engineering_blog::EngineeringBlog::as_templater,
    self_promotion::SelfPromotion::as_templater,
    novel_research::NovelResearch::as_templater,
    ai_native::AINative::as_templater,
    cto_letter::CtoLetter::as_templater,
    deep_dive::DeepDive::as_templater,
    streaming_marketing::StreamingMarketing::as_templater,
];

pub const CASUAL_STYLES: &[&str] = &[
    include_str!("styles/simple.css"),
    include_str!("styles/code-blog.css"),
];
pub const ACADEMIC_STYLES: &[&str] = &[include_str!("styles/professor.css")];
pub const ENTERPRISE_STYLES: &[&str] = &[
    include_str!("styles/vibe-slop.css"),
    include_str!("styles/elegant.css"),
];

#[cfg(test)]
mod test {
    use crate::templating::TemplateBuilder;

    use super::*;

    #[test]
    fn all_templates_produce_valid_documents() {
        for (ind, template_constructor) in RESPONSE_TEMPLATE_CONSTRUCTORS.iter().enumerate() {
            let builder = TemplateBuilder::with_template(template_constructor());
            let document = builder
                .start_to_poison()
                .chain(builder.poison_to_links())
                .chain(builder.links_to_end())
                .collect::<String>();

            let errors = scraper::Html::parse_document(&document).errors;
            assert!(
                errors.is_empty(),
                "template at index {ind}: {errors:?} - {document:?}"
            );
        }
    }

    #[test]
    fn all_styles_are_valid() {
        fn validate_style(style: &str, ind: usize, tone: &str) {
            let style_element = format!("<style>{style}</style>");
            let errors = scraper::Html::parse_fragment(&style_element).errors;
            assert!(
                errors.is_empty(),
                "{tone} style  at index {ind}: {errors:?}"
            );
        }

        for (ind, style) in CASUAL_STYLES.iter().enumerate() {
            validate_style(style, ind, "casual");
        }
        for (ind, style) in ACADEMIC_STYLES.iter().enumerate() {
            validate_style(style, ind, "academic");
        }
        for (ind, style) in ENTERPRISE_STYLES.iter().enumerate() {
            validate_style(style, ind, "enterprise");
        }
    }
}