Add Cfg option to disable DOCTYPE minification

This commit is contained in:
Wilson Lin 2021-08-10 17:45:37 +10:00
parent ca30897dae
commit 14b3999705
10 changed files with 59 additions and 12 deletions

View File

@ -15,33 +15,47 @@ struct Cli {
/// File to minify; omit for stdin.
#[structopt(parse(from_os_str))]
input: Option<std::path::PathBuf>,
/// Output destination; omit for stdout.
#[structopt(short, long, parse(from_os_str))]
output: Option<std::path::PathBuf>,
/// Minify JS in `<script>` tags that have a valid or no `type` attribute value.
#[structopt(long)]
minify_js: bool,
/// Minify CSS in `<style>` tags and `style` attributes.
#[structopt(long)]
minify_css: bool,
#[structopt(long)]
/// Do not minify DOCTYPEs. Minified DOCTYPEs may not be spec compliant.
do_not_minify_doctype: bool,
/// Ensure all unquoted attribute values in the output do not contain any characters prohibited by the WHATWG specification.
#[structopt(long)]
ensure_spec_compliant_unquoted_attribute_values: bool,
/// Do not omit closing tags when possible.
#[structopt(long)]
keep_closing_tags: bool,
/// Do not omit `<html>` and `<head>` opening tags when they don't have attributes.
#[structopt(long)]
keep_html_and_head_opening_tags: bool,
/// Keep spaces between attributes when possible to conform to HTML standards.
#[structopt(long)]
keep_spaces_between_attributes: bool,
/// Keep all comments.
#[structopt(long)]
keep_comments: bool,
/// Remove all bangs.
#[structopt(long)]
remove_bangs: bool,
/// Remove all processing_instructions.
#[structopt(long)]
remove_processing_instructions: bool,
@ -74,6 +88,7 @@ fn main() {
let out_code = minify(
&src_code,
&Cfg {
do_not_minify_doctype: args.do_not_minify_doctype,
ensure_spec_compliant_unquoted_attribute_values: args
.ensure_spec_compliant_unquoted_attribute_values,
keep_closing_tags: args.keep_closing_tags,

View File

@ -4,6 +4,7 @@ package in.wilsonl.minifyhtml;
* Class representing minification configuration.
*/
public class Configuration {
public final boolean do_not_minify_doctype;
public final boolean ensure_spec_compliant_unquoted_attribute_values;
public final boolean keep_closing_tags;
public final boolean keep_comments;
@ -15,6 +16,7 @@ public class Configuration {
public final boolean remove_processing_instructions;
public Configuration(
boolean do_not_minify_doctype,
boolean ensure_spec_compliant_unquoted_attribute_values,
boolean keep_closing_tags,
boolean keep_comments,
@ -25,6 +27,7 @@ public class Configuration {
boolean remove_bangs,
boolean remove_processing_instructions
) {
this.do_not_minify_doctype = do_not_minify_doctype;
this.ensure_spec_compliant_unquoted_attribute_values = ensure_spec_compliant_unquoted_attribute_values;
this.keep_closing_tags = keep_closing_tags;
this.keep_comments = keep_comments;
@ -40,6 +43,7 @@ public class Configuration {
* Builder to help create configuration.
*/
public static class Builder {
private boolean do_not_minify_doctype = false;
private boolean ensure_spec_compliant_unquoted_attribute_values = false;
private boolean keep_closing_tags = false;
private boolean keep_comments = false;
@ -50,6 +54,11 @@ public class Configuration {
private boolean remove_bangs = false;
private boolean remove_processing_instructions = false;
public Builder setDoNotMinifyDoctype(boolean val) {
this.do_not_minify_doctype = val;
return this;
}
public Builder setEnsureSpecCompliantUnquotedAttributeValues(boolean val) {
this.ensure_spec_compliant_unquoted_attribute_values = val;
return this;
@ -98,6 +107,7 @@ public class Configuration {
public Configuration build() {
return new Configuration(
this.do_not_minify_doctype,
this.ensure_spec_compliant_unquoted_attribute_values,
this.keep_closing_tags,
this.keep_comments,

View File

@ -6,6 +6,11 @@ use std::str::from_utf8;
fn build_cfg(env: &JNIEnv, obj: &JObject) -> Cfg {
Cfg {
do_not_minify_doctype: env
.get_field(*obj, "do_not_minify_doctype", "Z")
.unwrap()
.z()
.unwrap(),
ensure_spec_compliant_unquoted_attribute_values: env
.get_field(*obj, "ensure_spec_compliant_unquoted_attribute_values", "Z")
.unwrap()

View File

@ -71,6 +71,7 @@ napi_value node_method_create_configuration(napi_env env, napi_callback_info inf
/* It's OK if this fails. */ napi_get_value_bool(env, prop##_value, &prop); \
}
GET_CFG_PROP(do_not_minify_doctype);
GET_CFG_PROP(ensure_spec_compliant_unquoted_attribute_values);
GET_CFG_PROP(keep_closing_tags);
GET_CFG_PROP(keep_comments);
@ -82,6 +83,7 @@ napi_value node_method_create_configuration(napi_env env, napi_callback_info inf
GET_CFG_PROP(remove_processing_instructions);
Cfg const* cfg = ffi_create_cfg(
do_not_minify_doctype,
ensure_spec_compliant_unquoted_attribute_values,
keep_closing_tags,
keep_comments,

2
nodejs/index.d.ts vendored
View File

@ -8,6 +8,8 @@ export type Cfg = { __doNotUseCfgDirectly: string & { __itIsANapiExternalValue:
* @returns An opaque value that can be passed to minify functions
*/
export function createConfiguration (options: {
/** Do not minify DOCTYPEs. Minified DOCTYPEs may not be spec compliant. */
do_not_minify_doctype?: boolean,
/** Ensure all unquoted attribute values in the output do not contain any characters prohibited by the WHATWG specification. */
ensure_spec_compliant_unquoted_attribute_values?: boolean;
/** Do not omit closing tags when possible. */

View File

@ -3,6 +3,7 @@ use std::{mem, slice};
#[no_mangle]
pub extern "C" fn ffi_create_cfg(
do_not_minify_doctype: bool,
ensure_spec_compliant_unquoted_attribute_values: bool,
keep_closing_tags: bool,
keep_comments: bool,
@ -14,6 +15,7 @@ pub extern "C" fn ffi_create_cfg(
remove_processing_instructions: bool,
) -> *const Cfg {
Box::into_raw(Box::new(Cfg {
do_not_minify_doctype,
ensure_spec_compliant_unquoted_attribute_values,
keep_closing_tags,
keep_comments,

View File

@ -4,19 +4,21 @@ use pyo3::wrap_pyfunction;
use std::string::String;
#[pyfunction(
py_args="*",
ensure_spec_compliant_unquoted_attribute_values="false",
keep_closing_tags="false",
keep_comments="false",
keep_html_and_head_opening_tags="false",
keep_spaces_between_attributes="false",
minify_css="false",
minify_js="false",
remove_bangs="false",
remove_processing_instructions="false",
py_args = "*",
do_not_minify_doctype = "false",
ensure_spec_compliant_unquoted_attribute_values = "false",
keep_closing_tags = "false",
keep_comments = "false",
keep_html_and_head_opening_tags = "false",
keep_spaces_between_attributes = "false",
minify_css = "false",
minify_js = "false",
remove_bangs = "false",
remove_processing_instructions = "false",
)]
fn minify(
code: String,
do_not_minify_doctype: bool,
ensure_spec_compliant_unquoted_attribute_values: bool,
keep_closing_tags: bool,
keep_comments: bool,
@ -29,6 +31,7 @@ fn minify(
) -> PyResult<String> {
let code = code.into_bytes();
let out_code = minify_html_native(&code, &Cfg {
do_not_minify_doctype,
ensure_spec_compliant_unquoted_attribute_values,
keep_closing_tags,
keep_comments,

View File

@ -29,6 +29,7 @@ methods! {
.unwrap();
let cfg = &Cfg {
do_not_minify_doctype: get_cfg_hash_prop!(cfg_hash, "do_not_minify_doctype"),
ensure_spec_compliant_unquoted_attribute_values: get_cfg_hash_prop!(cfg_hash, "ensure_spec_compliant_unquoted_attribute_values"),
keep_closing_tags: get_cfg_hash_prop!(cfg_hash, "keep_closing_tags"),
keep_comments: get_cfg_hash_prop!(cfg_hash, "keep_comments"),

View File

@ -2,6 +2,8 @@
/// minification approach.
#[derive(Default)]
pub struct Cfg {
/// Do not minify DOCTYPEs. Minified DOCTYPEs may not be spec compliant.
pub do_not_minify_doctype: bool,
/// Ensure all unquoted attribute values in the output do not contain any characters prohibited by the [WHATWG specification](https://html.spec.whatwg.org/multipage/syntax.html#attributes-2).
pub ensure_spec_compliant_unquoted_attribute_values: bool,
/// Do not omit closing tags when possible.
@ -37,6 +39,7 @@ impl Cfg {
pub fn spec_compliant() -> Cfg {
Cfg {
do_not_minify_doctype: true,
ensure_spec_compliant_unquoted_attribute_values: true,
keep_spaces_between_attributes: true,
..Cfg::default()

View File

@ -1,7 +1,11 @@
use crate::cfg::Cfg;
pub fn minify_doctype(_cfg: &Cfg, out: &mut Vec<u8>, legacy: &[u8], ended: bool) {
out.extend_from_slice(b"<!doctypehtml");
pub fn minify_doctype(cfg: &Cfg, out: &mut Vec<u8>, legacy: &[u8], ended: bool) {
out.extend_from_slice(b"<!doctype");
if cfg.do_not_minify_doctype {
out.push(b' ');
}
out.extend_from_slice(b"html");
if !legacy.is_empty() {
out.push(b' ');
out.extend_from_slice(legacy);