pub struct StaticSiteGenerator { /* private fields */ }ssg only.Expand description
Writes rendered pages and assets into an output directory.
§Examples
use molt::prelude::*;
use molt::{Document, ssg::StaticSiteGenerator};
let site = StaticSiteGenerator::new("dist");
site.clean(true)?;
site.generate(&Document::new(Some("pt-BR")), "index.html", &RenderOptions::pretty())?;Implementations§
Source§impl StaticSiteGenerator
impl StaticSiteGenerator
Sourcepub fn new(output_directory: impl Into<PathBuf>) -> Self
pub fn new(output_directory: impl Into<PathBuf>) -> Self
Creates a generator writing into output_directory.
Sourcepub fn output_directory(&self) -> &Path
pub fn output_directory(&self) -> &Path
The directory pages are written into.
Sourcepub fn generate(
&self,
document: &Document,
path: &str,
options: &RenderOptions,
) -> Result<(), SsgError>
pub fn generate( &self, document: &Document, path: &str, options: &RenderOptions, ) -> Result<(), SsgError>
Renders a document to path, relative to the output directory.
The page is written with Document::render_to, section by section, into a
temporary file that is then renamed. The bytes match Document::render_with.
§Errors
Returns an error if the path escapes the output directory, or if the write fails.
Sourcepub fn generate_multiple(
&self,
documents: &[(Document, String)],
options: &RenderOptions,
) -> Result<(), SsgError>
pub fn generate_multiple( &self, documents: &[(Document, String)], options: &RenderOptions, ) -> Result<(), SsgError>
Renders several documents.
With the parallel feature the pages are rendered concurrently — sound because the
node tree is Send + Sync.
Every failure is reported, not just the first: a bulk build that names one of twelve broken pages is worse than useless.
§Errors
Returns an error naming every page that failed.
Sourcepub fn generate_page(
&self,
page: &Node,
path: &str,
options: &RenderOptions,
doctype: bool,
) -> Result<(), SsgError>
pub fn generate_page( &self, page: &Node, path: &str, options: &RenderOptions, doctype: bool, ) -> Result<(), SsgError>
Renders a bare node to path, optionally prefixed by the doctype.
§Errors
Returns an error if the path is unsafe or the write fails.
Sourcepub fn copy_asset(
&self,
from: impl AsRef<Path>,
to: &str,
) -> Result<(), SsgError>
pub fn copy_asset( &self, from: impl AsRef<Path>, to: &str, ) -> Result<(), SsgError>
Copies a file into the output directory, replacing any existing destination.
§Errors
Returns an error if the destination is unsafe or the copy fails.
Sourcepub fn copy_dir(
&self,
from: impl AsRef<Path>,
to: &str,
) -> Result<usize, SsgError>
pub fn copy_dir( &self, from: impl AsRef<Path>, to: &str, ) -> Result<usize, SsgError>
Copies a directory tree into the output directory, replacing files that already exist.
to names the destination directory under the output directory; "" or "." copies
into the output directory itself. Returns how many files were copied. Every file goes
through copy_asset, so each copy is atomic.
Symbolic links in from are not followed: a link to a file or a directory is
skipped, because what it points at may lie outside the tree you meant to publish. The
output directory is skipped too if it sits inside from, so copying . cannot copy
the site into itself. Use copy_dir_where to leave out names
such as .DS_Store.
§Errors
Returns an error if from cannot be read, if to is unsafe (see
copy_asset), if a name under from is not valid UTF-8, or if a
copy fails.
§Examples
use molt::ssg::StaticSiteGenerator;
let base = std::env::temp_dir().join(format!("molt-copy-dir-{}", std::process::id()));
std::fs::create_dir_all(base.join("static/img"))?;
std::fs::write(base.join("static/app.css"), "a{}")?;
std::fs::write(base.join("static/img/logo.svg"), "<svg/>")?;
let site = StaticSiteGenerator::new(base.join("dist"));
assert_eq!(site.copy_dir(base.join("static"), "assets")?, 2);
assert!(base.join("dist/assets/img/logo.svg").is_file());Sourcepub fn copy_dir_where(
&self,
from: impl AsRef<Path>,
to: &str,
keep: impl Fn(&OsStr) -> bool,
) -> Result<usize, SsgError>
pub fn copy_dir_where( &self, from: impl AsRef<Path>, to: &str, keep: impl Fn(&OsStr) -> bool, ) -> Result<usize, SsgError>
As copy_dir, copying only the entries keep accepts.
keep sees each file or directory name (not the path). A directory it rejects is
skipped with everything under it.
§Errors
The same as copy_dir.
§Examples
use molt::ssg::StaticSiteGenerator;
let base = std::env::temp_dir().join(format!("molt-copy-where-{}", std::process::id()));
std::fs::create_dir_all(base.join("static"))?;
std::fs::write(base.join("static/app.css"), "a{}")?;
std::fs::write(base.join("static/.DS_Store"), "junk")?;
let site = StaticSiteGenerator::new(base.join("dist"));
let copied = site.copy_dir_where(base.join("static"), "", |name| name != ".DS_Store")?;
assert_eq!(copied, 1);
assert!(!base.join("dist/.DS_Store").exists());Sourcepub fn copy_asset_hashed(
&self,
from: impl AsRef<Path>,
dir: &str,
) -> Result<String, SsgError>
pub fn copy_asset_hashed( &self, from: impl AsRef<Path>, dir: &str, ) -> Result<String, SsgError>
Copies a file into dir under a name that holds a hash of its content, and returns the
URL to use for it.
site.css copied to "css" becomes css/site.<hash>.css and the result is
"/css/site.<hash>.css", ready for stylesheet or
script_src. The same bytes always give the same name and
different bytes a different one, so a cache can keep the file for a year
(Cache-Control: public, max-age=31536000, immutable) and a new build still reaches
every visitor. dir of "" or "." is the output directory itself. The copy is atomic,
like copy_asset, and writes the bytes that were hashed, so a file
that changes mid-build cannot get the wrong name.
The hash is 64-bit FNV-1a, written out in full as 16 hex digits. It names content for a
cache and is not a security measure: it is trivially forged. For a hash a browser
checks, see Element::csp_hash.
§What it does not do
It renames one file and rewrites nothing. A module that imports another by relative
path (import './motion.js') keeps asking for the old name, and so does a url(...) in
a stylesheet. Either concatenate those scripts into one file before copying it, or copy
the files they refer to first and write their returned URLs into the file you then copy.
An earlier version of the file stays in the directory until clean.
The file name should be URL-safe, because it is returned as it is.
§Errors
Returns an error if from cannot be read, its name is not valid UTF-8, or dir is
unsafe (see copy_asset).
§Examples
use molt::prelude::*;
use molt::ssg::StaticSiteGenerator;
let base = std::env::temp_dir().join(format!("molt-hashed-{}", std::process::id()));
std::fs::create_dir_all(&base)?;
std::fs::write(base.join("site.css"), "body{color:red}")?;
let site = StaticSiteGenerator::new(base.join("dist"));
let url = site.copy_asset_hashed(base.join("site.css"), "css")?;
assert_eq!(url, "/css/site.c0e0533c847ec633.css");
assert_eq!(
stylesheet(&url).render(),
r#"<link href="/css/site.c0e0533c847ec633.css" rel="stylesheet">"#
);
assert!(base.join("dist/css/site.c0e0533c847ec633.css").is_file());Sourcepub fn clean(&self, create_directory: bool) -> Result<(), SsgError>
pub fn clean(&self, create_directory: bool) -> Result<(), SsgError>
Removes the output directory, optionally recreating it empty.
Only a directory Molt can show is its own is emptied: one that does not exist, is
empty, or holds the OUTPUT_MARKER file that writing a page or an asset leaves
there. A relative path such as "dist" is resolved against the current directory of
the process, so the same code run from another project would otherwise empty that
project’s dist.
§Errors
Returns an error if the output directory is unsafe to delete — empty, a filesystem
root, a top-level directory, the home directory, the working directory or one of its
ancestors, or containing a .. component, because removing it recursively would delete
whatever it points at. It also refuses a symbolic link, and a directory that has
contents but no OUTPUT_MARKER; for one made before the marker existed, remove it by
hand once or create the file.
§Examples
use molt::ssg::StaticSiteGenerator;
let base = std::env::temp_dir().join(format!("molt-clean-{}", std::process::id()));
let site = StaticSiteGenerator::new(base.join("dist"));
site.write_file("<p>old</p>", "old.html")?; // leaves the marker behind
site.clean(true)?;
assert!(!base.join("dist/old.html").exists());
// A directory the generator did not make is left alone.
std::fs::write(base.join("dist/keep.txt"), "mine")?;
std::fs::remove_file(base.join("dist").join(molt::ssg::OUTPUT_MARKER))?;
assert!(site.clean(true).is_err());
assert!(base.join("dist/keep.txt").exists());Sourcepub fn write_file(&self, content: &str, path: &str) -> Result<(), SsgError>
pub fn write_file(&self, content: &str, path: &str) -> Result<(), SsgError>
Writes UTF-8 content to path, creating parent directories.
The write is atomic: content goes to a temporary file in the same directory and is then renamed, so a reader never sees a half-written page.
§Errors
Returns an error if the path escapes the output directory or the write fails.
Trait Implementations§
Source§impl Clone for StaticSiteGenerator
impl Clone for StaticSiteGenerator
Auto Trait Implementations§
impl Freeze for StaticSiteGenerator
impl RefUnwindSafe for StaticSiteGenerator
impl Send for StaticSiteGenerator
impl Sync for StaticSiteGenerator
impl Unpin for StaticSiteGenerator
impl UnsafeUnpin for StaticSiteGenerator
impl UnwindSafe for StaticSiteGenerator
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more