//! `cargo xtask site [--out DIR] [--app DIR]`: the project's web site for //! GitHub Pages (https://fabianhassler.github.io/rustfig/): a landing page, //! the manual (`docs/manual/*.md`) as HTML pages, the screenshot, a //! sitemap, and with `--app` the web app built by `cargo xtask web` under //! `app/`. Static HTML and CSS only (no scripts besides the app itself), so //! search engines read every page. The output is deterministic. use pulldown_cmark::{html, CowStr, Event, Options, Parser, Tag}; use std::fmt::Write as _; use std::path::{Path, PathBuf}; /// Where the site is served. pub const BASE: &str = "https://fabianhassler.github.io/rustfig/"; const REPO: &str = "https://github.com/FabianHassler/rustfig"; /// One manual page: file stem, title (its `# ` heading) and HTML body. pub struct Page { pub stem: String, pub title: String, pub description: String, pub body: String, } /// Escapes text for HTML. fn esc(s: &str) -> String { s.replace('&', "&") .replace('<', "<") .replace('>', ">") .replace('"', """) } /// The manual's per-system blocks (`` … ``, /// which the program shows only on that system) as labelled boxes. fn os_blocks(md: &str) -> String { let mut out = String::with_capacity(md.len()); let mut open = false; for line in md.lines() { let t = line.trim(); if let Some(rest) = t.strip_prefix("")) { if open { out.push_str("\n\n\n"); open = false; } let systems: Vec<&str> = rest .split_whitespace() .filter(|s| *s != "end") .map(|s| match s { "mac" => "macOS", "windows" => "Windows", "linux" => "Linux", other => other, }) .collect(); if !systems.is_empty() { let _ = write!( out, "
On {}
\n\n", systems.join(" and ") ); open = true; } continue; } out.push_str(line); out.push('\n'); } if open { out.push_str("\n