7 releases
Uses new Rust 2024
| 0.3.13 | Jan 24, 2026 |
|---|---|
| 0.3.12 | Jan 22, 2026 |
| 0.3.4 | Dec 31, 2025 |
#1989 in Web programming
Used in 3 crates
(via herolib-osis)
53KB
1K
SLoC
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
Dependencies
~10–14MB
~199K SLoC