herolib-web

Crates.ioherolib-web
lib.rsherolib-web
version0.3.13
created_at2025-12-31 13:56:19.038496+00
updated_at2026-01-24 05:26:32.198774+00
descriptionWeb utilities for herolib - HTML/Markdown processing and web scraping
homepage
repositoryhttps://github.com/herolib/herolib_rust
max_upload_size
id2014747
size95,283
kristof de spiegeleer (despiegk)

documentation

README

herolib-web

Fast, ergonomic web utilities for Markdown and HTML processing.

Features

  • Markdown → HTML: Convert with Bootstrap 5.3.8 styling built-in
  • HTML Utilities: Parsing, validation, minification, escaping
  • Builders: Ergonomic APIs via builder pattern for both Markdown and HTML
  • Bootstrap Integration: Automatic CSS/JS injection, removal, and updates

Installation

[dependencies]
herolib-web = { path = "packages/web", version = "0.3.3" }

Markdown: Basic Usage

use herolib_web::markdown;

// Complete HTML5 page (ready to save as .html file)
let html = markdown::markdown_to_html_page("# Hello\n\nWorld", "My Page");
std::fs::write("page.html", html)?;

// Embed in existing page
let fragment = markdown::markdown_to_html_bootstrap("# Title\nContent");
// Returns: <div class="container mt-5 mb-5">..HTML..</div>

// Extract headings & word count
let headings = markdown::extract_headings(md);
let words = markdown::count_words(md);

Markdown: Builder Pattern

use herolib_web::markdown::MarkdownBuilder;

let md = MarkdownBuilder::new()
    .heading(1, "Guide")?
    .paragraph("Intro text")
    .heading(2, "Section")?
    .list(&["Item 1", "Item 2"])
    .code_block("rust", "fn main() {}")
    .ordered_list(&["Step 1", "Step 2"])
    .blockquote("A quote")
    .link("Site", "https://example.com")
    .build();

let html = markdown::markdown_to_html(&md);

Markdown: Functions Reference

Function Returns Purpose
markdown_to_html(md) String Raw HTML conversion
markdown_to_html_page(md, title) String Standalone page (with Bootstrap)
markdown_to_html_bootstrap(md) String Container div for embedding
markdown_to_toc_bootstrap(md) String Table of contents nav
extract_headings(md) Vec<(usize, String)> (level, text) tuples
count_words(md) usize Word count
count_lines(md) usize Line count
MarkdownBuilder Builder Programmatic generation

HTML: Basic Usage

use herolib_web::html;

// XSS prevention
let safe = html::escape_html("<script>alert('xss')</script>");

// Remove HTML tags
let text = html::extract_text("<p>Keep <b>this</b></p>");

// Validate structure
html::validate_html("<div><p>OK</p></div>")?;

// Minify (remove whitespace)
let min = html::minify_html(html);

HTML: Bootstrap Management

use herolib_web::html;

// Add Bootstrap 5.3.8 (removes old versions, idempotent)
let with_bs = html::add_bootstrap(html);

// Remove all Bootstrap references
let without = html::remove_bootstrap(&with_bs);

HTML: Builder Pattern

use herolib_web::html::HtmlBuilder;

let page = HtmlBuilder::new()
    .add_tag("h1", "Title", &[])
    .add_tag("p", "Text", &[("class", "lead")])
    .add_tag("a", "Link", &[("href", "https://example.com")])
    .build();

HTML: Functions Reference

Function Purpose
escape_html(text) Encode special chars for safe HTML
unescape_html(text) Decode HTML entities
extract_text(html) Remove all tags
minify_html(html) Remove whitespace
validate_html(html) Check tag balance (returns WebResult)
add_bootstrap(html) Inject Bootstrap 5.3.8
remove_bootstrap(html) Strip Bootstrap CDN links
HtmlBuilder Build HTML programmatically

Real-World Examples

Blog Post with TOC

use herolib_web::markdown;
use std::fs;

let md = fs::read_to_string("blog.md")?;
let toc = markdown::markdown_to_toc_bootstrap(&md);
let content = markdown::markdown_to_html_page(&md, "My Blog");

// Combine in your template
let page = format!("{}\n{}", toc, content);
fs::write("blog.html", page)?;

File to HTML

use herolib_web::markdown;
use std::fs;

let content = fs::read_to_string("input.md")?;
let html = markdown::markdown_to_html_page(&content, "Title");
fs::write("output.html", html)?;

HTML Cleaning

use herolib_web::html;

let dirty = "<p>  Content  </p>";
let clean = html::minify_html(dirty);      // "<p> Content </p>"

let text = html::extract_text(clean);      // "Content"

Form Generation

use herolib_web::html::HtmlBuilder;

let form = HtmlBuilder::new()
    .add_tag("input", "", &[
        ("type", "email"),
        ("name", "email"),
        ("placeholder", "your@email.com")
    ])
    .add_tag("button", "Submit", &[("type", "submit")])
    .build();

Error Handling

All fallible operations return WebResult<T>:

match markdown::MarkdownBuilder::new().heading(7, "Bad") {
    Ok(_) => {},
    Err(e) => println!("Error: {} (levels 1-6 only)", e),
}

Error variants: HtmlParseError, MarkdownError, InvalidHtml, Utf8Error, IoError, JsonError

Bootstrap Details

  • Version: Locked to 5.3.8 via CDN
  • CSS: Added to <head> section
  • JS: Added before </body> closing tag
  • Idempotent: Safe to call add_bootstrap() multiple times
  • Smart: Auto-detects missing head/body tags

Performance

  • Regex cached via OnceLock (zero overhead)
  • Zero-copy markdown parsing (pulldown-cmark)
  • ~40% size reduction via minify_html()

Testing & Docs

./build.sh    # Build, test, lint, generate docs
./run.sh      # Run demo app
cargo test    # Tests only
cargo doc --no-deps --open  # View API docs

License

Apache-2.0

Commit count: 0

cargo fmt