Add documentation comments to Rust API

This commit is contained in:
Wilson Lin 2020-08-25 00:36:27 +10:00
parent ef44006ef6
commit 693c847563
4 changed files with 142 additions and 45 deletions

View File

@ -51,49 +51,7 @@ If the `js-esbuild` feature is not enabled, `cfg.minify_js` will have no effect.
##### Use
```rust
use minify_html::{Cfg, Error, FriendlyError, in_place, copy, with_friendly_error, truncate};
fn main() {
let mut code = b"<p> Hello, world! </p>".to_vec();
let cfg = &Cfg {
minify_js: false,
};
// Minifies a slice in-place and returns the new minified length,
// but leaves any original code after the minified code intact.
match in_place(&mut code, cfg) {
Ok(minified_len) => {}
Err(Error { error_type, position }) => {}
};
// Creates a vector copy containing only minified code
// instead of minifying in-place.
match copy(&code, cfg) {
Ok(minified) => {}
Err(Error { error_type, position }) => {}
};
// Minifies a vector in-place, and then truncates the
// vector to the new minified length.
match truncate(&mut code, cfg) {
Ok(()) => {}
Err(Error { error_type, position }) => {}
};
// Identical to `in_place` except with FriendlyError instead.
// `code_context` is a string of a visual representation of the source,
// with line numbers and position markers to aid in debugging syntax.
match with_friendly_error(&mut code, cfg) {
Ok(minified_len) => {}
Err(FriendlyError { position, message, code_context }) => {
eprintln!("Failed at character {}:", position);
eprintln!("{}", message);
eprintln!("{}", code_context);
}
};
}
```
Check out the [docs](https://docs.rs/minify-html) for API and usage examples.
</details>

View File

@ -1,3 +1,12 @@
/// Configuration settings that can be adjusted and passed to a minification function to change the
/// minification approach.
pub struct Cfg {
/// If enabled, JavaScript in `<script>` tags are minified using
/// [esbuild-rs](https://github.com/wilsonzlin/esbuild-rs). The `js-esbuild` feature must be
/// enabled; otherwise, this value has no effect.
///
/// Only `<script>` tags with a valid or no
/// [MIME type](https://mimesniff.spec.whatwg.org/#javascript-mime-type) is considered to
/// contain JavaScript, as per the specification.
pub minify_js: bool,
}

View File

@ -1,4 +1,4 @@
// Implement debug to allow .unwrap().
/// Represents the type of minification error.
#[derive(Debug, Eq, PartialEq)]
pub enum ErrorType {
ClosingTagMismatch { expected: String, got: String },
@ -8,6 +8,7 @@ pub enum ErrorType {
}
impl ErrorType {
/// Generates an English message describing the error with any additional context.
pub fn message(self) -> String {
match self {
ErrorType::ClosingTagMismatch { expected, got } => {
@ -26,12 +27,17 @@ impl ErrorType {
}
}
/// Details about a minification failure, including where it occurred and why.
#[derive(Debug)]
pub struct Error {
pub error_type: ErrorType,
pub position: usize,
}
/// User-friendly details about a minification failure, including an English message description of
/// the reason, and generated printable contextual representation of the code where the error
/// occurred.
#[derive(Debug)]
pub struct FriendlyError {
pub position: usize,
@ -64,7 +70,7 @@ pub fn debug_repr(code: &[u8], read_pos: isize, write_pos: isize) -> String {
// Include '\n'. Note that the last line might not have '\n' but that's OK for these calculations.
let len = line.len() + 1;
let line_as_string = unsafe { String::from_utf8_unchecked(line.to_vec()) };
lines.push((line_no as isize, line_as_string));
lines.push(((line_no + 1) as isize, line_as_string));
let new_pos = cur_pos + len;
// Rust does lazy allocation by default, so this is not wasteful.

View File

@ -15,6 +15,28 @@ mod spec;
mod tests;
mod unit;
/// Minifies a slice in-place and returns the new minified length.
/// Any original code after the end of the minified code is left intact.
///
/// # Arguments
///
/// * `code` - A mutable slice of bytes representing the source code to minify.
/// * `cfg` - Configuration object to adjust minification approach.
///
/// # Examples
///
/// ```
/// use minify_html::{Cfg, Error, in_place};
///
/// let mut code = b"<p> Hello, world! </p>".to_vec();
/// let cfg = &Cfg {
/// minify_js: false,
/// };
/// match in_place(&mut code, cfg) {
/// Ok(minified_len) => assert_eq!(&code, b"<p>Hello, world!d! </p>"),
/// Err(Error { error_type, position }) => {}
/// };
/// ```
pub fn in_place(code: &mut [u8], cfg: &Cfg) -> Result<usize, Error> {
let mut proc = Processor::new(code);
process_content(&mut proc, cfg, Namespace::Html, None)
@ -30,6 +52,28 @@ pub fn in_place(code: &mut [u8], cfg: &Cfg) -> Result<usize, Error> {
proc.finish()
}
/// Minifies a str in-place and returns the new minified length.
/// Any original code after the end of the minified code is left intact.
///
/// # Arguments
///
/// * `code` - A mutable str representing the source code to minify.
/// * `cfg` - Configuration object to adjust minification approach.
///
/// # Examples
///
/// ```
/// use minify_html::{Cfg, Error, in_place_str};
///
/// let mut code = "<p> Hello, world! </p>".to_string();
/// let cfg = &Cfg {
/// minify_js: false,
/// };
/// match in_place_str(&mut code, cfg) {
/// Ok(minified_len) => assert_eq!(&code, "<p>Hello, world!d! </p>"),
/// Err(Error { error_type, position }) => {}
/// };
/// ```
pub fn in_place_str<'s>(code: &'s mut str, cfg: &Cfg) -> Result<&'s str, Error> {
let bytes = unsafe { code.as_bytes_mut() };
match in_place(bytes, cfg) {
@ -38,6 +82,27 @@ pub fn in_place_str<'s>(code: &'s mut str, cfg: &Cfg) -> Result<&'s str, Error>
}
}
/// Minifies a Vec in-place, truncating it to the minified length.
///
/// # Arguments
///
/// * `code` - A slice of bytes representing the source code to minify.
/// * `cfg` - Configuration object to adjust minification approach.
///
/// # Examples
///
/// ```
/// use minify_html::{Cfg, Error, truncate};
///
/// let mut code = b"<p> Hello, world! </p>".to_vec();
/// let cfg = &Cfg {
/// minify_js: false,
/// };
/// match truncate(&mut code, cfg) {
/// Ok(()) => assert_eq!(code, b"<p>Hello, world!".to_vec()),
/// Err(Error { error_type, position }) => {}
/// };
/// ```
pub fn truncate(code: &mut Vec<u8>, cfg: &Cfg) -> Result<(), Error> {
match in_place(code, cfg) {
Ok(written_len) => {
@ -48,6 +113,31 @@ pub fn truncate(code: &mut Vec<u8>, cfg: &Cfg) -> Result<(), Error> {
}
}
/// Copies a slice into a new Vec and minifies it, returning the Vec.
/// The resulting Vec will only contain minified code.
///
/// # Arguments
///
/// * `code` - A slice of bytes representing the source code to minify.
/// * `cfg` - Configuration object to adjust minification approach.
///
/// # Examples
///
/// ```
/// use minify_html::{Cfg, Error, copy};
///
/// let mut code = b"<p> Hello, world! </p>".to_vec();
/// let cfg = &Cfg {
/// minify_js: false,
/// };
/// match copy(&code, cfg) {
/// Ok(minified) => {
/// assert_eq!(code, b"<p> Hello, world! </p>".to_vec());
/// assert_eq!(minified, b"<p>Hello, world!".to_vec());
/// }
/// Err(Error { error_type, position }) => {}
/// };
/// ```
pub fn copy(code: &[u8], cfg: &Cfg) -> Result<Vec<u8>, Error> {
let mut copy = code.to_vec();
match truncate(&mut copy, cfg) {
@ -56,6 +146,40 @@ pub fn copy(code: &[u8], cfg: &Cfg) -> Result<Vec<u8>, Error> {
}
}
/// Minifies a slice in-place and returns the new minified length.
/// Any original code after the end of the minified code is left intact.
///
/// This function is identical to `in_place` except it returns a `FriendlyError` on error instead.
///
/// `FriendlyError` has a `code_context` field, which is a string of a visual representation of the
/// source, with line numbers and position markers to aid in debugging syntax.
///
/// # Arguments
///
/// * `code` - A mutable slice of bytes representing the source code to minify.
/// * `cfg` - Configuration object to adjust minification approach.
///
/// # Examples
///
/// ```
/// use minify_html::{Cfg, FriendlyError, with_friendly_error};
///
/// let mut code = b"<p></div>".to_vec();
/// let cfg = &Cfg {
/// minify_js: false,
/// };
/// match with_friendly_error(&mut code, cfg) {
/// Ok(minified_len) => {}
/// Err(FriendlyError { position, message, code_context }) => {
/// assert_eq!(position, 3);
/// assert_eq!(message, "Unexpected closing tag.");
/// assert_eq!(code_context, concat!(
/// "1|<p></div>\n",
/// ">| R \n",
/// ));
/// }
/// };
/// ```
pub fn with_friendly_error(code: &mut [u8], cfg: &Cfg) -> Result<usize, FriendlyError> {
in_place(code, cfg).map_err(|err| FriendlyError {
position: err.position,